|
|
@ -1,49 +1,227 @@ |
|
|
|
<template> |
|
|
|
<!-- 添加 col-span-2 和高度样式 --> |
|
|
|
<div class="tabs-container"> |
|
|
|
<Tabs v-model:activeKey="activeKey" type="card"> |
|
|
|
<TabPane key="1" tab="审查结果"> |
|
|
|
<div class="action-buttons"> |
|
|
|
<Button type="primary" class="action-button add-button" @click="handleAdd"> |
|
|
|
<template #icon><PlusOutlined /></template> |
|
|
|
新增审查点 |
|
|
|
</Button> |
|
|
|
</div> |
|
|
|
<div class="scroll-container"> |
|
|
|
<div class="card-container"> |
|
|
|
<div class="card-container"> |
|
|
|
<!-- 编辑卡片 --> |
|
|
|
<Card v-if="isAdding" class="custom-card edit-card"> |
|
|
|
<template #title> |
|
|
|
<div class="input-group"> |
|
|
|
<div class="input-label">标题:</div> |
|
|
|
<Input v-model:value="newCard.title" placeholder="请输入标题" /> |
|
|
|
</div> |
|
|
|
</template> |
|
|
|
<div class="input-group"> |
|
|
|
<div class="input-label">属性:</div> |
|
|
|
<Input v-model:value="newCard.text" placeholder="请输入属性" style="margin-bottom: 8px;" /> |
|
|
|
</div> |
|
|
|
<div class="input-group"> |
|
|
|
<div class="input-label">问题内容:</div> |
|
|
|
<Input.TextArea v-model:value="newCard.content" placeholder="请输入问题内容" style="margin-bottom: 8px;" /> |
|
|
|
</div> |
|
|
|
<div class="card-actions"> |
|
|
|
<Button type="primary" size="small" class="action-button save-button" @click="handleSave"> |
|
|
|
<template #icon><SaveOutlined /></template> |
|
|
|
保存 |
|
|
|
</Button> |
|
|
|
<Button size="small" class="action-button cancel-button" @click="handleCancel"> |
|
|
|
<template #icon><CloseOutlined /></template> |
|
|
|
取消 |
|
|
|
</Button> |
|
|
|
</div> |
|
|
|
</Card> |
|
|
|
|
|
|
|
<!-- 展示卡片列表 --> |
|
|
|
<Card |
|
|
|
v-for="(item, index) in props.cardList" |
|
|
|
:key="index" |
|
|
|
:class="['custom-card', { 'card-selected': selectedCard === item.title }]" |
|
|
|
@click="handleCardClick(item.title)" |
|
|
|
:class="['custom-card', { 'card-selected': selectedIndex === index }]" |
|
|
|
@click="handleCardClick(index)" |
|
|
|
> |
|
|
|
<template #title>{{ item.title }}</template> |
|
|
|
{{ item.text }} |
|
|
|
{{ item.content }} |
|
|
|
<template #title> |
|
|
|
<template v-if="editingIndex === index"> |
|
|
|
<div class="input-group"> |
|
|
|
<div class="input-label">标题:</div> |
|
|
|
<Input v-model:value="item.title" @click.stop /> |
|
|
|
</div> |
|
|
|
</template> |
|
|
|
<template v-else> |
|
|
|
<div class="card-header"> |
|
|
|
<span class="card-title">{{ item.title }}</span> |
|
|
|
<div class="card-header-actions"> |
|
|
|
<Button type="primary" size="small" class="action-button edit-button" @click.stop="startEdit(index)"> |
|
|
|
<template #icon><EditOutlined /></template> |
|
|
|
编辑 |
|
|
|
</Button> |
|
|
|
<Button type="primary" danger size="small" class="action-button delete-button" @click.stop="handleDelete(index)"> |
|
|
|
<template #icon><DeleteOutlined /></template> |
|
|
|
删除 |
|
|
|
</Button> |
|
|
|
</div> |
|
|
|
</div> |
|
|
|
</template> |
|
|
|
</template> |
|
|
|
<template v-if="editingIndex === index"> |
|
|
|
<div class="input-group"> |
|
|
|
<div class="input-label">属性:</div> |
|
|
|
<Input v-model:value="item.text" style="margin-bottom: 8px;" @click.stop /> |
|
|
|
</div> |
|
|
|
<div class="input-group"> |
|
|
|
<div class="input-label">问题内容:</div> |
|
|
|
<Input.TextArea v-model:value="item.content" style="margin-bottom: 8px;" @click.stop /> |
|
|
|
</div> |
|
|
|
<div class="card-actions"> |
|
|
|
<Button type="primary" size="small" class="action-button save-button" @click.stop="handleEditSave(index)"> |
|
|
|
<template #icon><SaveOutlined /></template> |
|
|
|
保存 |
|
|
|
</Button> |
|
|
|
<Button size="small" class="action-button cancel-button" @click.stop="cancelEdit"> |
|
|
|
<template #icon><CloseOutlined /></template> |
|
|
|
取消 |
|
|
|
</Button> |
|
|
|
</div> |
|
|
|
</template> |
|
|
|
<template v-else> |
|
|
|
<div class="content-group"> |
|
|
|
<div class="content-label">属性:</div> |
|
|
|
<div>{{ item.text }}</div> |
|
|
|
</div> |
|
|
|
<div class="content-group"> |
|
|
|
<div class="content-label">问题内容:</div> |
|
|
|
<div>{{ item.content }}</div> |
|
|
|
</div> |
|
|
|
</template> |
|
|
|
</Card> |
|
|
|
</div> |
|
|
|
</div> |
|
|
|
</TabPane> |
|
|
|
<!-- <TabPane key="2" tab="Tab 2">Content of Tab Pane 2</TabPane> |
|
|
|
<TabPane key="3" tab="Tab 3">Content of Tab Pane 3</TabPane> --> |
|
|
|
</Tabs> |
|
|
|
</div> |
|
|
|
</template> |
|
|
|
|
|
|
|
<script lang="ts" setup> |
|
|
|
import { ref, onMounted, reactive } from 'vue'; |
|
|
|
|
|
|
|
import { Tabs, TabPane, Card } from 'ant-design-vue'; |
|
|
|
// Props 定义 |
|
|
|
interface Props { |
|
|
|
cardList:any[]; |
|
|
|
} |
|
|
|
const props = defineProps<Props>(); |
|
|
|
const activeKey = ref('1'); |
|
|
|
// 卡片数据 |
|
|
|
const selectedCard = ref(''); // 用于存储当前选中的卡片标题 |
|
|
|
const handleCardClick = (title) => { |
|
|
|
selectedCard.value = title; |
|
|
|
console.log('点击的卡片标题:', title); |
|
|
|
}; |
|
|
|
|
|
|
|
// 初始化数据 |
|
|
|
onMounted(() => { |
|
|
|
|
|
|
|
import { ref, reactive } from 'vue'; |
|
|
|
import { Tabs, TabPane, Card, Input, Button, Modal } from 'ant-design-vue'; |
|
|
|
import { ExclamationCircleOutlined, SaveOutlined, EditOutlined, DeleteOutlined, CloseOutlined, PlusOutlined } from '@ant-design/icons-vue'; |
|
|
|
import { createVNode } from 'vue'; |
|
|
|
|
|
|
|
// Props 定义 |
|
|
|
interface Props { |
|
|
|
cardList: any[]; |
|
|
|
} |
|
|
|
const props = defineProps<Props>(); |
|
|
|
const emit = defineEmits(['update:cardList']); |
|
|
|
|
|
|
|
const activeKey = ref('1'); |
|
|
|
const selectedIndex = ref(-1); // 使用-1表示未选中状态 |
|
|
|
const editingIndex = ref(-1); // 使用-1表示未编辑状态 |
|
|
|
const isAdding = ref(false); |
|
|
|
|
|
|
|
// 新卡片数据 |
|
|
|
const newCard = reactive({ |
|
|
|
title: '', |
|
|
|
text: '', |
|
|
|
content: '' |
|
|
|
}); |
|
|
|
|
|
|
|
// 点击卡片 |
|
|
|
const handleCardClick = (index: number) => { |
|
|
|
selectedIndex.value = index; |
|
|
|
}; |
|
|
|
|
|
|
|
// 开始编辑 |
|
|
|
const startEdit = (index: number) => { |
|
|
|
editingIndex.value = index; |
|
|
|
}; |
|
|
|
|
|
|
|
// 取消编辑 |
|
|
|
const cancelEdit = () => { |
|
|
|
editingIndex.value = -1; |
|
|
|
}; |
|
|
|
|
|
|
|
// 保存编辑 |
|
|
|
const handleEditSave = (index: number) => { |
|
|
|
// 直接使用索引更新数组 |
|
|
|
const newList = [...props.cardList]; |
|
|
|
// 不需要创建新对象,因为已经直接修改了原对象 |
|
|
|
emit('update:cardList', newList); |
|
|
|
editingIndex.value = -1; |
|
|
|
}; |
|
|
|
|
|
|
|
// 新增卡片 |
|
|
|
const handleAdd = () => { |
|
|
|
isAdding.value = true; |
|
|
|
newCard.title = ''; |
|
|
|
newCard.text = ''; |
|
|
|
newCard.content = ''; |
|
|
|
}; |
|
|
|
|
|
|
|
// 保存新卡片 |
|
|
|
const handleSave = () => { |
|
|
|
if (!newCard.title.trim()) { |
|
|
|
Modal.warning({ |
|
|
|
title: '提示', |
|
|
|
content: '标题不能为空!' |
|
|
|
}); |
|
|
|
return; |
|
|
|
} |
|
|
|
|
|
|
|
// 检查标题是否重复 |
|
|
|
const isDuplicate = props.cardList.some(card => card.title === newCard.title); |
|
|
|
if (isDuplicate) { |
|
|
|
Modal.warning({ |
|
|
|
title: '提示', |
|
|
|
content: '标题已存在,请修改!' |
|
|
|
}); |
|
|
|
return; |
|
|
|
} |
|
|
|
|
|
|
|
// 创建新的数组并添加新卡片 |
|
|
|
const newList = [...props.cardList, { |
|
|
|
title: newCard.title, |
|
|
|
text: newCard.text, |
|
|
|
content: newCard.content |
|
|
|
}]; |
|
|
|
|
|
|
|
// 触发更新事件 |
|
|
|
emit('update:cardList', newList); |
|
|
|
|
|
|
|
// 清空表单并关闭新增界面 |
|
|
|
newCard.title = ''; |
|
|
|
newCard.text = ''; |
|
|
|
newCard.content = ''; |
|
|
|
isAdding.value = false; |
|
|
|
}; |
|
|
|
|
|
|
|
// 取消新增 |
|
|
|
const handleCancel = () => { |
|
|
|
isAdding.value = false; |
|
|
|
}; |
|
|
|
|
|
|
|
// 删除卡片 |
|
|
|
const handleDelete = (index: number) => { |
|
|
|
const title = props.cardList[index].title; |
|
|
|
Modal.confirm({ |
|
|
|
title: '确认删除', |
|
|
|
icon: createVNode(ExclamationCircleOutlined), |
|
|
|
content: `确定要删除"${title}"吗?`, |
|
|
|
okText: '确认', |
|
|
|
cancelText: '取消', |
|
|
|
onOk() { |
|
|
|
const newList = props.cardList.filter((_, i) => i !== index); |
|
|
|
emit('update:cardList', newList); |
|
|
|
selectedIndex.value = -1; // 重置选中状态 |
|
|
|
editingIndex.value = -1; |
|
|
|
} |
|
|
|
}); |
|
|
|
}; |
|
|
|
</script> |
|
|
|
<style scoped> |
|
|
|
/* Tabs 相关样式 */ |
|
|
@ -121,29 +299,177 @@ |
|
|
|
|
|
|
|
/* 滚动容器样式 */ |
|
|
|
.scroll-container { |
|
|
|
height: calc(100vh - 25vh); /* 可以根据实际需要调整高度 */ |
|
|
|
overflow-y: auto; /* 添加垂直滚动条 */ |
|
|
|
flex: 1; |
|
|
|
overflow-y: auto; |
|
|
|
padding: 16px; |
|
|
|
} |
|
|
|
|
|
|
|
/* 美化滚动条样式(可选) */ |
|
|
|
.scroll-container::-webkit-scrollbar { |
|
|
|
width: 6px; /* 滚动条宽度 */ |
|
|
|
/* 确保整个容器可以正确伸展 */ |
|
|
|
.tabs-container { |
|
|
|
height: 100%; |
|
|
|
display: flex; |
|
|
|
flex-direction: column; |
|
|
|
} |
|
|
|
|
|
|
|
:deep(.ant-tabs) { |
|
|
|
height: 100%; |
|
|
|
display: flex; |
|
|
|
flex-direction: column; |
|
|
|
} |
|
|
|
|
|
|
|
.scroll-container::-webkit-scrollbar-thumb { |
|
|
|
background-color: #ccc; /* 滚动条颜色 */ |
|
|
|
border-radius: 3px; /* 滚动条圆角 */ |
|
|
|
:deep(.ant-tabs-content) { |
|
|
|
flex: 1; |
|
|
|
overflow: hidden; |
|
|
|
} |
|
|
|
|
|
|
|
.scroll-container::-webkit-scrollbar-track { |
|
|
|
background-color: #f1f1f1; /* 滚动条轨道颜色 */ |
|
|
|
:deep(.ant-tabs-tabpane) { |
|
|
|
height: 100%; |
|
|
|
display: flex; |
|
|
|
flex-direction: column; |
|
|
|
} |
|
|
|
|
|
|
|
/* 保持原有的卡片容器样式 */ |
|
|
|
.card-container { |
|
|
|
/* 编辑卡片样式 */ |
|
|
|
.edit-card { |
|
|
|
border: 1px dashed #1890ff; |
|
|
|
} |
|
|
|
|
|
|
|
/* 按钮组样式优化 */ |
|
|
|
.card-actions { |
|
|
|
margin-top: 16px; |
|
|
|
display: flex; |
|
|
|
gap: 16px; |
|
|
|
flex-wrap: wrap; |
|
|
|
gap: 8px; |
|
|
|
justify-content: flex-end; |
|
|
|
} |
|
|
|
|
|
|
|
/* 通用按钮样式 */ |
|
|
|
.action-button { |
|
|
|
display: flex; |
|
|
|
align-items: center; |
|
|
|
gap: 4px; |
|
|
|
padding: 4px 12px; |
|
|
|
border-radius: 4px; |
|
|
|
transition: all 0.3s; |
|
|
|
} |
|
|
|
|
|
|
|
/* 保存按钮样式 */ |
|
|
|
.save-button { |
|
|
|
background-color: #1890ff; |
|
|
|
border-color: #1890ff; |
|
|
|
} |
|
|
|
|
|
|
|
.save-button:hover { |
|
|
|
background-color: #40a9ff; |
|
|
|
border-color: #40a9ff; |
|
|
|
} |
|
|
|
|
|
|
|
/* 编辑按钮样式 */ |
|
|
|
.edit-button { |
|
|
|
background-color: #1890ff; |
|
|
|
border-color: #1890ff; |
|
|
|
} |
|
|
|
|
|
|
|
.edit-button:hover { |
|
|
|
background-color: #40a9ff; |
|
|
|
border-color: #40a9ff; |
|
|
|
} |
|
|
|
|
|
|
|
/* 取消按钮样式 */ |
|
|
|
.cancel-button { |
|
|
|
color: #666; |
|
|
|
background-color: #f4f4f4; |
|
|
|
border-color: #d9d9d9; |
|
|
|
} |
|
|
|
|
|
|
|
.cancel-button:hover { |
|
|
|
color: #40a9ff; |
|
|
|
border-color: #40a9ff; |
|
|
|
background-color: #fff; |
|
|
|
} |
|
|
|
|
|
|
|
/* 删除按钮样式 */ |
|
|
|
.delete-button { |
|
|
|
background-color: #ff4d4f; |
|
|
|
border-color: #ff4d4f; |
|
|
|
} |
|
|
|
|
|
|
|
.delete-button:hover { |
|
|
|
background-color: #ff7875; |
|
|
|
border-color: #ff7875; |
|
|
|
} |
|
|
|
|
|
|
|
/* 按钮图标样式 */ |
|
|
|
:deep(.anticon) { |
|
|
|
font-size: 14px; |
|
|
|
} |
|
|
|
|
|
|
|
/* 输入框样式调整 */ |
|
|
|
:deep(.ant-input) { |
|
|
|
margin-bottom: 8px; |
|
|
|
} |
|
|
|
|
|
|
|
.input-group { |
|
|
|
margin-bottom: 12px; |
|
|
|
} |
|
|
|
|
|
|
|
.input-label { |
|
|
|
font-weight: bold; |
|
|
|
margin-bottom: 4px; |
|
|
|
color: #333; |
|
|
|
} |
|
|
|
|
|
|
|
.content-group { |
|
|
|
margin-bottom: 12px; |
|
|
|
} |
|
|
|
|
|
|
|
.content-label { |
|
|
|
font-weight: bold; |
|
|
|
margin-bottom: 4px; |
|
|
|
color: #666; |
|
|
|
} |
|
|
|
|
|
|
|
/* 新增按钮样式 */ |
|
|
|
.action-buttons { |
|
|
|
padding: 8px 16px; |
|
|
|
} |
|
|
|
|
|
|
|
.add-button { |
|
|
|
background-color: #1890ff; |
|
|
|
border-color: #1890ff; |
|
|
|
} |
|
|
|
|
|
|
|
.add-button:hover { |
|
|
|
background-color: #40a9ff; |
|
|
|
border-color: #40a9ff; |
|
|
|
} |
|
|
|
|
|
|
|
/* 添加卡片标题区域样式 */ |
|
|
|
.card-header { |
|
|
|
display: flex; |
|
|
|
justify-content: space-between; |
|
|
|
align-items: center; |
|
|
|
width: 100%; |
|
|
|
} |
|
|
|
|
|
|
|
.card-title { |
|
|
|
font-weight: bold; |
|
|
|
font-size: 16px; |
|
|
|
color: #333; |
|
|
|
flex: 1; |
|
|
|
} |
|
|
|
|
|
|
|
.card-header-actions { |
|
|
|
display: flex; |
|
|
|
gap: 8px; |
|
|
|
margin-left: 16px; |
|
|
|
} |
|
|
|
|
|
|
|
/* 调整卡片标题区域的按钮大小 */ |
|
|
|
.card-header-actions .action-button { |
|
|
|
padding: 2px 8px; |
|
|
|
font-size: 12px; |
|
|
|
} |
|
|
|
|
|
|
|
.card-header-actions :deep(.anticon) { |
|
|
|
font-size: 12px; |
|
|
|
} |
|
|
|
</style> |
|
|
|