|
|
|
@ -9,7 +9,44 @@ |
|
|
|
修改时间: |
|
|
|
--> |
|
|
|
<template> |
|
|
|
<div class="bg-[#fff] p-5"> |
|
|
|
<div class="bg-[#fff] p-5 relative"> |
|
|
|
<!-- 查询条件卡片 --> |
|
|
|
<a-card v-if="hasQueryParams" class="query-params-card mb-4" :bordered="false"> |
|
|
|
<template #title> |
|
|
|
<div class="query-title"> |
|
|
|
<SearchOutlined class="title-icon" /> |
|
|
|
<span>查询条件</span> |
|
|
|
</div> |
|
|
|
</template> |
|
|
|
<div class="query-tags"> |
|
|
|
<a-tag v-if="queryParams.title" color="blue" class="query-tag"> |
|
|
|
<span class="tag-label">标题:</span> |
|
|
|
<span class="tag-value">{{ queryParams.title }}</span> |
|
|
|
</a-tag> |
|
|
|
<a-tag v-if="queryParams.description" color="cyan" class="query-tag"> |
|
|
|
<span class="tag-label">描述:</span> |
|
|
|
<span class="tag-value">{{ queryParams.description }}</span> |
|
|
|
</a-tag> |
|
|
|
<a-tag v-if="queryParams.createTime" color="orange" class="query-tag"> |
|
|
|
<span class="tag-label">创建时间:</span> |
|
|
|
<span class="tag-value">{{ formatDateRange(queryParams.createTime) }}</span> |
|
|
|
</a-tag> |
|
|
|
</div> |
|
|
|
</a-card> |
|
|
|
<div class="flex justify-between items-center"> |
|
|
|
<!-- 上一页按钮 --> |
|
|
|
<a-button |
|
|
|
type="primary" |
|
|
|
shape="circle" |
|
|
|
size="large" |
|
|
|
class="nav-button prev-button" |
|
|
|
:disabled="!prevId" |
|
|
|
@click="handlePrev" |
|
|
|
> |
|
|
|
<template #icon> |
|
|
|
<LeftOutlined /> |
|
|
|
</template> |
|
|
|
</a-button> |
|
|
|
<a-spin :spinning="loading"> |
|
|
|
<a-tabs default-active-key="1"> |
|
|
|
<a-tab-pane key="1" tab="基础信息"> |
|
|
|
@ -29,6 +66,19 @@ |
|
|
|
</a-tab-pane> |
|
|
|
</a-tabs> |
|
|
|
</a-spin> |
|
|
|
<a-button |
|
|
|
type="primary" |
|
|
|
shape="circle" |
|
|
|
size="large" |
|
|
|
class="nav-button next-button" |
|
|
|
:disabled="!nextId" |
|
|
|
@click="handleNext" |
|
|
|
> |
|
|
|
<template #icon> |
|
|
|
<RightOutlined /> |
|
|
|
</template> |
|
|
|
</a-button> |
|
|
|
</div> |
|
|
|
</div> |
|
|
|
</template> |
|
|
|
|
|
|
|
@ -38,10 +88,11 @@ |
|
|
|
import { useForm } from '@/components/core/schema-form'; |
|
|
|
import { getEditFormSchema } from './formSchemas'; |
|
|
|
import { useRoute } from 'vue-router'; |
|
|
|
import { onMounted, ref } from 'vue'; |
|
|
|
import { findOneById } from '@/api/knowledgeBase'; |
|
|
|
import { onMounted, ref, computed, watch } from 'vue'; |
|
|
|
import { findOneById, fetchKnowledgeBasePageList } from '@/api/knowledgeBase'; |
|
|
|
import { SvgIcon } from '@/components/basic/svg-icon'; |
|
|
|
import { stateTypeList } from './data'; |
|
|
|
import { LeftOutlined, RightOutlined, SearchOutlined } from '@ant-design/icons-vue'; |
|
|
|
const route = useRoute(); |
|
|
|
const editorOptions = ref({ |
|
|
|
theme: 'snow', |
|
|
|
@ -66,7 +117,47 @@ |
|
|
|
|
|
|
|
const current = ref(0); |
|
|
|
|
|
|
|
const { id } = route.query; |
|
|
|
// 当前 id(用于 watch) |
|
|
|
const currentId = ref<string | undefined>(route.query.id as string | undefined); |
|
|
|
|
|
|
|
// 上一页和下一页的 id |
|
|
|
const prevId = ref<string | null>(null); |
|
|
|
const nextId = ref<string | null>(null); |
|
|
|
|
|
|
|
// 查询参数(排除id)- 直接从 route.query 获取,确保响应式更新 |
|
|
|
const queryParams = computed(() => { |
|
|
|
const params: Record<string, string> = {}; |
|
|
|
Object.keys(route.query).forEach((key) => { |
|
|
|
// 排除 id 参数 |
|
|
|
if ( |
|
|
|
key !== 'id' && |
|
|
|
route.query[key] !== undefined && |
|
|
|
route.query[key] !== null && |
|
|
|
route.query[key] !== '' |
|
|
|
) { |
|
|
|
params[key] = String(route.query[key]); |
|
|
|
} |
|
|
|
}); |
|
|
|
return params; |
|
|
|
}); |
|
|
|
|
|
|
|
// 是否有查询参数 |
|
|
|
const hasQueryParams = computed(() => { |
|
|
|
return Object.keys(queryParams.value).length > 0; |
|
|
|
}); |
|
|
|
|
|
|
|
// 格式化日期范围显示 |
|
|
|
const formatDateRange = (dateStr: string) => { |
|
|
|
if (!dateStr) return ''; |
|
|
|
// 如果是逗号分隔的日期范围 |
|
|
|
if (dateStr.includes(',')) { |
|
|
|
const dates = dateStr.split(','); |
|
|
|
if (dates.length === 2) { |
|
|
|
return `${dates[0]} 至 ${dates[1]}`; |
|
|
|
} |
|
|
|
} |
|
|
|
return dateStr; |
|
|
|
}; |
|
|
|
|
|
|
|
const [SchemaForm, formRef] = useForm({ |
|
|
|
labelWidth: 150, |
|
|
|
@ -81,10 +172,83 @@ |
|
|
|
disabled: true, |
|
|
|
}); |
|
|
|
|
|
|
|
onMounted(async () => { |
|
|
|
// 获取列表数据,找到当前记录的位置 |
|
|
|
const loadListData = async () => { |
|
|
|
try { |
|
|
|
// 构建查询参数 |
|
|
|
const searchParams: any = { |
|
|
|
current: 1, |
|
|
|
size: 1000, // 获取足够多的数据以便查找 |
|
|
|
}; |
|
|
|
|
|
|
|
// 处理查询参数 - 从 route.query 直接获取,确保获取到最新的查询参数 |
|
|
|
const currentQuery = route.query; |
|
|
|
if (currentQuery.title) { |
|
|
|
searchParams.title = String(currentQuery.title); |
|
|
|
} |
|
|
|
if (currentQuery.description) { |
|
|
|
searchParams.description = String(currentQuery.description); |
|
|
|
} |
|
|
|
if (currentQuery.createTime) { |
|
|
|
const dateStr = String(currentQuery.createTime); |
|
|
|
if (dateStr.includes(',')) { |
|
|
|
const dates = dateStr.split(','); |
|
|
|
if (dates.length === 2) { |
|
|
|
searchParams.startDate = dates[0]; |
|
|
|
searchParams.endDate = dates[1]; |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
// 添加其他可能的查询参数 |
|
|
|
Object.keys(currentQuery).forEach((key) => { |
|
|
|
if (key !== 'id' && key !== 'title' && key !== 'description' && key !== 'createTime') { |
|
|
|
const value = currentQuery[key]; |
|
|
|
if (value !== undefined && value !== null && value !== '') { |
|
|
|
searchParams[key] = String(value); |
|
|
|
} |
|
|
|
} |
|
|
|
}); |
|
|
|
|
|
|
|
console.log('加载列表数据,查询参数:', searchParams); |
|
|
|
const res = await fetchKnowledgeBasePageList(searchParams); |
|
|
|
const list = res.data?.records || []; |
|
|
|
console.log('获取到的列表数据,总数:', list.length); |
|
|
|
|
|
|
|
// 找到当前记录在列表中的位置 |
|
|
|
const currentIdValue = currentId.value || (route.query.id as string); |
|
|
|
const currentIndex = list.findIndex((item: any) => item.id == currentIdValue); |
|
|
|
console.log('当前记录索引:', currentIndex, '当前ID:', currentIdValue); |
|
|
|
|
|
|
|
if (currentIndex !== -1) { |
|
|
|
// 设置上一页和下一页的 id |
|
|
|
prevId.value = currentIndex > 0 ? list[currentIndex - 1].id : null; |
|
|
|
nextId.value = currentIndex < list.length - 1 ? list[currentIndex + 1].id : null; |
|
|
|
console.log('上一页ID:', prevId.value, '下一页ID:', nextId.value); |
|
|
|
} else { |
|
|
|
// 如果找不到当前记录,清空上一页和下一页 |
|
|
|
prevId.value = null; |
|
|
|
nextId.value = null; |
|
|
|
console.warn('未找到当前记录在列表中'); |
|
|
|
} |
|
|
|
} catch (error) { |
|
|
|
console.error('获取列表数据失败:', error); |
|
|
|
prevId.value = null; |
|
|
|
nextId.value = null; |
|
|
|
} |
|
|
|
}; |
|
|
|
|
|
|
|
// 加载详情数据 |
|
|
|
const loadDetailData = async (targetId: string) => { |
|
|
|
if (!targetId) { |
|
|
|
return; |
|
|
|
} |
|
|
|
|
|
|
|
currentId.value = targetId; |
|
|
|
loading.value = true; |
|
|
|
const res = await findOneById({ id: id as string }); |
|
|
|
loading.value = false; |
|
|
|
|
|
|
|
try { |
|
|
|
const res = await findOneById({ id: targetId }); |
|
|
|
|
|
|
|
if (res?.files && Array.isArray(res.files) && res.files.length) { |
|
|
|
res.files = res.files.map((e) => { |
|
|
|
@ -104,12 +268,136 @@ |
|
|
|
title: stateTypeList.find((item) => item.value === e.state)?.label, |
|
|
|
}; |
|
|
|
}); |
|
|
|
} else { |
|
|
|
historyList.value = []; |
|
|
|
} |
|
|
|
|
|
|
|
current.value = res?.state; |
|
|
|
|
|
|
|
formRef?.setFieldsValue(res); |
|
|
|
formRef?.clearValidate(); |
|
|
|
|
|
|
|
// 重新加载列表数据以更新上一页和下一页 |
|
|
|
await loadListData(); |
|
|
|
} catch (error) { |
|
|
|
console.error('加载详情数据失败:', error); |
|
|
|
} finally { |
|
|
|
loading.value = false; |
|
|
|
} |
|
|
|
}; |
|
|
|
|
|
|
|
// 跳转到上一页 |
|
|
|
const handlePrev = () => { |
|
|
|
if (prevId.value) { |
|
|
|
loadDetailData(prevId.value); |
|
|
|
} |
|
|
|
}; |
|
|
|
|
|
|
|
// 跳转到下一页 |
|
|
|
const handleNext = () => { |
|
|
|
if (nextId.value) { |
|
|
|
loadDetailData(nextId.value); |
|
|
|
} |
|
|
|
}; |
|
|
|
|
|
|
|
onMounted(async () => { |
|
|
|
const currentIdValue = route.query.id as string; |
|
|
|
if (!currentIdValue) { |
|
|
|
console.warn('未找到 id 参数'); |
|
|
|
return; |
|
|
|
} |
|
|
|
await loadDetailData(currentIdValue); |
|
|
|
}); |
|
|
|
|
|
|
|
// 监听路由变化,重新加载数据(用于从外部路由跳转过来的情况) |
|
|
|
watch( |
|
|
|
() => route.query.id, |
|
|
|
async (newId) => { |
|
|
|
if (newId && newId !== currentId.value) { |
|
|
|
await loadDetailData(newId as string); |
|
|
|
} |
|
|
|
}, |
|
|
|
); |
|
|
|
</script> |
|
|
|
<style lang="less" scoped></style> |
|
|
|
<style lang="less" scoped> |
|
|
|
.query-params-card { |
|
|
|
background: linear-gradient(135deg, #f8fafc 0%, #ffffff 100%); |
|
|
|
border-radius: 8px; |
|
|
|
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08); |
|
|
|
border: 1px solid #e2e8f0; |
|
|
|
transition: all 0.3s ease; |
|
|
|
|
|
|
|
&:hover { |
|
|
|
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.12); |
|
|
|
} |
|
|
|
|
|
|
|
.query-title { |
|
|
|
display: flex; |
|
|
|
align-items: center; |
|
|
|
gap: 8px; |
|
|
|
font-size: 15px; |
|
|
|
font-weight: 600; |
|
|
|
color: #1e293b; |
|
|
|
|
|
|
|
.title-icon { |
|
|
|
color: #3b82f6; |
|
|
|
font-size: 16px; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
.query-tags { |
|
|
|
display: flex; |
|
|
|
flex-wrap: wrap; |
|
|
|
gap: 12px; |
|
|
|
margin-top: 8px; |
|
|
|
|
|
|
|
.query-tag { |
|
|
|
padding: 6px 16px; |
|
|
|
border-radius: 6px; |
|
|
|
font-size: 14px; |
|
|
|
border: none; |
|
|
|
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1); |
|
|
|
transition: all 0.3s ease; |
|
|
|
|
|
|
|
&:hover { |
|
|
|
transform: translateY(-2px); |
|
|
|
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.15); |
|
|
|
} |
|
|
|
|
|
|
|
.tag-label { |
|
|
|
font-weight: 500; |
|
|
|
margin-right: 4px; |
|
|
|
opacity: 0.8; |
|
|
|
} |
|
|
|
|
|
|
|
.tag-value { |
|
|
|
font-weight: 600; |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
:deep(.ant-card-head) { |
|
|
|
border-bottom: 1px solid #e2e8f0; |
|
|
|
padding: 12px 16px; |
|
|
|
min-height: auto; |
|
|
|
} |
|
|
|
|
|
|
|
:deep(.ant-card-body) { |
|
|
|
padding: 16px; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
.nav-button { |
|
|
|
z-index: 1000; |
|
|
|
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15); |
|
|
|
transition: all 0.3s; |
|
|
|
|
|
|
|
&:hover { |
|
|
|
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.25); |
|
|
|
} |
|
|
|
|
|
|
|
&.next-button { |
|
|
|
left: 10px; |
|
|
|
} |
|
|
|
} |
|
|
|
</style> |
|
|
|
|