1、审计内容里的操作功能优化
2、审计内容9增加一个表的内容生成 3、添加取证单弹窗
This commit is contained in:
543
src/views/pwl/pwlProject/components/components/EvidenceModal.vue
Normal file
543
src/views/pwl/pwlProject/components/components/EvidenceModal.vue
Normal file
@@ -0,0 +1,543 @@
|
||||
<template>
|
||||
<a-modal
|
||||
:visible="visible"
|
||||
title="审计取证单预览"
|
||||
:width="1100"
|
||||
:footer="null"
|
||||
@cancel="handleCancel"
|
||||
destroy-on-close
|
||||
>
|
||||
<div class="evidence-actions">
|
||||
<a-space>
|
||||
<a-button @click="resetFields">重置内容</a-button>
|
||||
<a-button type="primary" @click="printEvidence">打印/导出</a-button>
|
||||
</a-space>
|
||||
<div class="action-tip">可直接在表格中编辑,打印即可生成与效果图一致的取证单</div>
|
||||
</div>
|
||||
|
||||
<div class="evidence-container">
|
||||
<div class="evidence-sheet" ref="printArea">
|
||||
<div class="sheet-title">审计取证单</div>
|
||||
<div class="sheet-meta">
|
||||
<div class="meta-left">
|
||||
<span>案引号:</span>
|
||||
<input
|
||||
v-model="form.caseIndex"
|
||||
class="inline-input long"
|
||||
placeholder="填写案件编号"
|
||||
/>
|
||||
</div>
|
||||
<div class="meta-right">
|
||||
<span>第</span>
|
||||
<input v-model="form.pageIndex" class="inline-input small" />
|
||||
<span>页(共</span>
|
||||
<input v-model="form.pageTotal" class="inline-input small" />
|
||||
<span>页)</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<table class="sheet-table">
|
||||
<colgroup>
|
||||
<col style="width: 18%" />
|
||||
<col style="width: 32%" />
|
||||
<col style="width: 18%" />
|
||||
<col style="width: 32%" />
|
||||
</colgroup>
|
||||
<tbody>
|
||||
<tr>
|
||||
<th>项目名称</th>
|
||||
<td colspan="3">
|
||||
<textarea
|
||||
v-model="form.projectName"
|
||||
class="cell-input single"
|
||||
placeholder="填写项目名称"
|
||||
></textarea>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>被审计(调查)单位或个人</th>
|
||||
<td colspan="3">
|
||||
<textarea
|
||||
v-model="form.auditedTarget"
|
||||
class="cell-input single"
|
||||
placeholder="填写被审计(调查)单位或个人"
|
||||
></textarea>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>审计(调查)事项</th>
|
||||
<td colspan="3">
|
||||
<textarea
|
||||
v-model="form.auditMatter"
|
||||
class="cell-input single"
|
||||
placeholder="填写审计(调查)事项"
|
||||
></textarea>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<th>摘要提示</th>
|
||||
<td colspan="3" class="summary-cell">
|
||||
<div class="summary-title">
|
||||
审计(调查)事项摘要包括:标题、审计记录、审计发现、定性依据。
|
||||
</div>
|
||||
<div class="summary-hint">
|
||||
1. 标题:突出核心问题,采用观点性语句,可作为审计内容、审计目标的结论性描述。
|
||||
</div>
|
||||
<div class="summary-hint">
|
||||
2. 审计记录:客观记录审计核查的具体事实(时间、地点、主体、行为、数据等),避免主观评价。
|
||||
</div>
|
||||
<div class="summary-hint">
|
||||
3. 审计发现:基于审计记录提出具体问题性质,先事实后定性,避免夸大。
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<th>标题</th>
|
||||
<td colspan="3">
|
||||
<textarea
|
||||
v-model="form.summaryTitle"
|
||||
class="cell-input"
|
||||
placeholder="填写核心标题或要点"
|
||||
></textarea>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<th>审计记录</th>
|
||||
<td colspan="3">
|
||||
<textarea
|
||||
v-model="form.auditRecord"
|
||||
class="cell-input tall"
|
||||
placeholder="客观记录审计核查的过程与事实"
|
||||
></textarea>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<th>审计发现</th>
|
||||
<td colspan="3">
|
||||
<textarea
|
||||
v-model="form.auditFinding"
|
||||
class="cell-input tall"
|
||||
placeholder="写明审计发现的事实、性质及影响"
|
||||
></textarea>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<th>定性依据</th>
|
||||
<td colspan="3">
|
||||
<textarea
|
||||
v-model="form.evidenceBasis"
|
||||
class="cell-input"
|
||||
placeholder="引用法规、制度或合同条款作为依据"
|
||||
></textarea>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<th>处理</th>
|
||||
<td colspan="3">
|
||||
<textarea
|
||||
v-model="form.handling"
|
||||
class="cell-input"
|
||||
placeholder="拟采取的处理措施"
|
||||
></textarea>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<th>建议</th>
|
||||
<td colspan="3">
|
||||
<textarea
|
||||
v-model="form.suggestion"
|
||||
class="cell-input"
|
||||
placeholder="提出改进或整改建议"
|
||||
></textarea>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<th>附件</th>
|
||||
<td colspan="3">
|
||||
<textarea
|
||||
v-model="form.attachment"
|
||||
class="cell-input"
|
||||
placeholder="列示随附的证明材料"
|
||||
></textarea>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<th>审计人员</th>
|
||||
<td colspan="2">
|
||||
<input
|
||||
v-model="form.auditors"
|
||||
class="cell-input input-line"
|
||||
placeholder="填写审计人员"
|
||||
/>
|
||||
</td>
|
||||
<th>编制日期</th>
|
||||
<td>
|
||||
<input
|
||||
v-model="form.compileDate"
|
||||
class="cell-input input-line"
|
||||
placeholder="YYYY-MM-DD"
|
||||
/>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<th>证据提供单位或个人意见</th>
|
||||
<td colspan="2">
|
||||
<textarea
|
||||
v-model="form.providerOpinion"
|
||||
class="cell-input tall"
|
||||
placeholder="盖章并填写确认意见"
|
||||
></textarea>
|
||||
</td>
|
||||
<td class="date-cell">
|
||||
<div class="date-label">日期</div>
|
||||
<input
|
||||
v-model="form.providerDate"
|
||||
class="cell-input input-line"
|
||||
placeholder="YYYY-MM-DD"
|
||||
/>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<div class="footer-note">
|
||||
<div class="note-row">
|
||||
附件:
|
||||
<input
|
||||
v-model="form.attachmentPages"
|
||||
class="inline-input small"
|
||||
placeholder="页数"
|
||||
/>
|
||||
页
|
||||
</div>
|
||||
<div class="note">
|
||||
说明:1. 请你单位在
|
||||
<input
|
||||
v-model="form.feedbackDeadline"
|
||||
class="inline-input long"
|
||||
placeholder="填写反馈期限"
|
||||
/>
|
||||
前反馈意见,逾期未反馈视为无异议;
|
||||
</div>
|
||||
<div class="note">
|
||||
2. 证据提供单位意见栏如填写不下,可另附说明。
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</a-modal>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { PropType, reactive, ref, watch } from 'vue';
|
||||
import { message } from 'ant-design-vue';
|
||||
|
||||
type BaseInfo = {
|
||||
caseIndex?: string;
|
||||
projectName?: string;
|
||||
auditedTarget?: string;
|
||||
auditMatter?: string;
|
||||
};
|
||||
|
||||
const props = defineProps({
|
||||
visible: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
baseInfo: {
|
||||
type: Object as PropType<BaseInfo>,
|
||||
default: () => ({})
|
||||
},
|
||||
selectedRows: {
|
||||
type: Array as PropType<any[]>,
|
||||
default: () => []
|
||||
}
|
||||
});
|
||||
|
||||
const emit = defineEmits<{
|
||||
(e: 'update:visible', value: boolean): void;
|
||||
}>();
|
||||
|
||||
const printArea = ref<HTMLElement | null>(null);
|
||||
|
||||
const defaultForm = () => ({
|
||||
caseIndex: '',
|
||||
pageIndex: '1',
|
||||
pageTotal: '1',
|
||||
projectName: '',
|
||||
auditedTarget: '',
|
||||
auditMatter: '',
|
||||
summaryTitle: '',
|
||||
auditRecord: '',
|
||||
auditFinding: '',
|
||||
evidenceBasis: '',
|
||||
handling: '',
|
||||
suggestion: '',
|
||||
attachment: '',
|
||||
auditors: '',
|
||||
compileDate: '',
|
||||
providerOpinion: '',
|
||||
providerDate: '',
|
||||
attachmentPages: '',
|
||||
feedbackDeadline: ''
|
||||
});
|
||||
|
||||
const form = reactive(defaultForm());
|
||||
|
||||
const applyBaseInfo = () => {
|
||||
Object.assign(form, defaultForm(), props.baseInfo || {});
|
||||
|
||||
if (props.selectedRows && props.selectedRows.length > 0) {
|
||||
const firstRow: any = props.selectedRows[0] || {};
|
||||
form.summaryTitle =
|
||||
firstRow.title || firstRow.name || form.summaryTitle || '';
|
||||
form.auditRecord =
|
||||
firstRow.auditRecord ||
|
||||
firstRow.auditContent ||
|
||||
firstRow.content ||
|
||||
form.auditRecord ||
|
||||
'';
|
||||
form.auditFinding =
|
||||
firstRow.auditFinding || firstRow.testResult || form.auditFinding || '';
|
||||
}
|
||||
|
||||
if (!form.compileDate) {
|
||||
const now = new Date();
|
||||
form.compileDate = `${now.getFullYear()}-${String(
|
||||
now.getMonth() + 1
|
||||
).padStart(2, '0')}-${String(now.getDate()).padStart(2, '0')}`;
|
||||
}
|
||||
};
|
||||
|
||||
watch(
|
||||
() => props.visible,
|
||||
(visible) => {
|
||||
if (visible) {
|
||||
applyBaseInfo();
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
watch(
|
||||
() => props.baseInfo,
|
||||
() => {
|
||||
if (props.visible) {
|
||||
applyBaseInfo();
|
||||
}
|
||||
},
|
||||
{ deep: true }
|
||||
);
|
||||
|
||||
const handleCancel = () => {
|
||||
emit('update:visible', false);
|
||||
};
|
||||
|
||||
const resetFields = () => {
|
||||
applyBaseInfo();
|
||||
message.success('内容已重置');
|
||||
};
|
||||
|
||||
const printEvidence = () => {
|
||||
const area = printArea.value;
|
||||
if (!area) {
|
||||
message.warning('暂无可导出的内容');
|
||||
return;
|
||||
}
|
||||
|
||||
const newWindow = window.open('', '_blank');
|
||||
if (!newWindow) {
|
||||
message.error('浏览器阻止了弹窗,请允许弹窗后重试');
|
||||
return;
|
||||
}
|
||||
|
||||
const style = `
|
||||
* { box-sizing: border-box; }
|
||||
body { margin: 0; padding: 24px; font-family: 'Songti SC', 'SimSun', serif; }
|
||||
.sheet-title { text-align: center; font-size: 28px; letter-spacing: 4px; margin-bottom: 12px; }
|
||||
.sheet-meta { display: flex; justify-content: space-between; font-size: 14px; margin-bottom: 8px; }
|
||||
.inline-input { border: none; border-bottom: 1px solid #000; min-width: 60px; padding: 2px 4px; font-size: 14px; }
|
||||
.inline-input.small { width: 48px; text-align: center; }
|
||||
.inline-input.long { min-width: 180px; }
|
||||
.sheet-table { width: 100%; border-collapse: collapse; table-layout: fixed; }
|
||||
.sheet-table th, .sheet-table td { border: 1px solid #000; padding: 8px 10px; vertical-align: top; font-size: 14px; }
|
||||
.sheet-table th { background: #fafafa; font-weight: 600; text-align: center; }
|
||||
.cell-input { width: 100%; border: none; resize: vertical; min-height: 34px; font-size: 14px; line-height: 1.5; font-family: inherit; }
|
||||
.cell-input:focus { outline: none; }
|
||||
.cell-input.single { min-height: 32px; }
|
||||
.cell-input.tall { min-height: 120px; }
|
||||
.input-line { height: 32px; }
|
||||
.summary-title { font-weight: 700; margin-bottom: 4px; }
|
||||
.summary-hint { color: #555; line-height: 1.5; margin-bottom: 2px; }
|
||||
.summary-cell { background: #fcfcfc; }
|
||||
.date-cell { display: flex; flex-direction: column; gap: 6px; }
|
||||
.date-label { font-weight: 600; }
|
||||
.footer-note { margin-top: 12px; font-size: 14px; line-height: 1.6; }
|
||||
.note-row { margin-bottom: 4px; }
|
||||
.note input { vertical-align: middle; }
|
||||
`;
|
||||
|
||||
newWindow.document.write(`
|
||||
<html>
|
||||
<head>
|
||||
<title>审计取证单</title>
|
||||
<style>${style}</style>
|
||||
</head>
|
||||
<body>${area.innerHTML}</body>
|
||||
</html>
|
||||
`);
|
||||
newWindow.document.close();
|
||||
newWindow.focus();
|
||||
newWindow.print();
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.evidence-actions {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
|
||||
.action-tip {
|
||||
color: #666;
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
.evidence-container {
|
||||
max-height: 70vh;
|
||||
overflow: auto;
|
||||
background: #f5f5f5;
|
||||
padding: 12px;
|
||||
}
|
||||
|
||||
.evidence-sheet {
|
||||
background: #fff;
|
||||
padding: 16px 20px;
|
||||
border: 1px solid #e5e5e5;
|
||||
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.08);
|
||||
}
|
||||
|
||||
.sheet-title {
|
||||
text-align: center;
|
||||
font-size: 28px;
|
||||
letter-spacing: 4px;
|
||||
margin-bottom: 12px;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.sheet-meta {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
font-size: 14px;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.inline-input {
|
||||
border: none;
|
||||
border-bottom: 1px solid #000;
|
||||
min-width: 60px;
|
||||
padding: 2px 4px;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.inline-input.small {
|
||||
width: 48px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.inline-input.long {
|
||||
min-width: 180px;
|
||||
}
|
||||
|
||||
.sheet-table {
|
||||
width: 100%;
|
||||
border-collapse: collapse;
|
||||
table-layout: fixed;
|
||||
}
|
||||
|
||||
.sheet-table th,
|
||||
.sheet-table td {
|
||||
border: 1px solid #000;
|
||||
padding: 8px 10px;
|
||||
vertical-align: top;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.sheet-table th {
|
||||
background: #fafafa;
|
||||
font-weight: 600;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.cell-input {
|
||||
width: 100%;
|
||||
border: none;
|
||||
resize: vertical;
|
||||
min-height: 34px;
|
||||
font-size: 14px;
|
||||
line-height: 1.5;
|
||||
font-family: inherit;
|
||||
}
|
||||
|
||||
.cell-input:focus {
|
||||
outline: none;
|
||||
}
|
||||
|
||||
.cell-input.single {
|
||||
min-height: 32px;
|
||||
}
|
||||
|
||||
.cell-input.tall {
|
||||
min-height: 120px;
|
||||
}
|
||||
|
||||
.input-line {
|
||||
height: 32px;
|
||||
}
|
||||
|
||||
.summary-cell {
|
||||
background: #fcfcfc;
|
||||
}
|
||||
|
||||
.summary-title {
|
||||
font-weight: 700;
|
||||
margin-bottom: 4px;
|
||||
}
|
||||
|
||||
.summary-hint {
|
||||
color: #555;
|
||||
line-height: 1.5;
|
||||
margin-bottom: 2px;
|
||||
}
|
||||
|
||||
.date-cell {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 6px;
|
||||
}
|
||||
|
||||
.date-label {
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.footer-note {
|
||||
margin-top: 12px;
|
||||
font-size: 14px;
|
||||
line-height: 1.6;
|
||||
}
|
||||
|
||||
.note-row {
|
||||
margin-bottom: 4px;
|
||||
}
|
||||
</style>
|
||||
@@ -17,8 +17,11 @@ export function initNavigationItems() {
|
||||
mode: 'table',
|
||||
showFileSelect: true, // 所有项都显示文件选择
|
||||
data: [],
|
||||
extraData: [],
|
||||
currentTableIndex: 0, // 当前选中的表格索引
|
||||
columns: null,
|
||||
extraTableTitle: config?.extraTableTitle || null,
|
||||
extraColumns: config?.extraColumns || [],
|
||||
tableOptions: config?.options || [],
|
||||
count: index + 1,
|
||||
tableType: config?.type || `auditContent${index + 1}`,
|
||||
|
||||
@@ -68,12 +68,12 @@ export const partyConductColumns = [
|
||||
width: 200,
|
||||
// ellipsis: true
|
||||
},
|
||||
{
|
||||
title: '操作',
|
||||
key: 'action',
|
||||
align: 'center',
|
||||
width: 100
|
||||
}
|
||||
// {
|
||||
// title: '操作',
|
||||
// key: 'action',
|
||||
// align: 'center',
|
||||
// width: 100
|
||||
// }
|
||||
];
|
||||
|
||||
export default {
|
||||
|
||||
@@ -81,12 +81,12 @@ export const auditHistoryColumns = [
|
||||
width: 200,
|
||||
// ellipsis: true
|
||||
},
|
||||
{
|
||||
title: '操作',
|
||||
key: 'action',
|
||||
align: 'center',
|
||||
width: 100
|
||||
}
|
||||
// {
|
||||
// title: '操作',
|
||||
// key: 'action',
|
||||
// align: 'center',
|
||||
// width: 100
|
||||
// }
|
||||
];
|
||||
|
||||
export default {
|
||||
|
||||
@@ -429,12 +429,12 @@ export const eightRegColumns = [
|
||||
width: 200,
|
||||
ellipsis: true
|
||||
},
|
||||
{
|
||||
title: '操作',
|
||||
key: 'action',
|
||||
align: 'center',
|
||||
width: 140
|
||||
}
|
||||
// {
|
||||
// title: '操作',
|
||||
// key: 'action',
|
||||
// align: 'center',
|
||||
// width: 140
|
||||
// }
|
||||
];
|
||||
|
||||
export default {
|
||||
|
||||
@@ -48,12 +48,12 @@ export const strategyAuditColumns = [
|
||||
align: 'center',
|
||||
// ellipsis: true
|
||||
},
|
||||
{
|
||||
title: '操作',
|
||||
key: 'action',
|
||||
width: 100,
|
||||
align: 'center'
|
||||
}
|
||||
// {
|
||||
// title: '操作',
|
||||
// key: 'action',
|
||||
// width: 100,
|
||||
// align: 'center'
|
||||
// }
|
||||
];
|
||||
|
||||
export default {
|
||||
|
||||
@@ -126,12 +126,12 @@ export const decisionTableColumns = [
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
title: '操作',
|
||||
key: 'action',
|
||||
align: 'center',
|
||||
width: 140
|
||||
}
|
||||
// {
|
||||
// title: '操作',
|
||||
// key: 'action',
|
||||
// align: 'center',
|
||||
// width: 140
|
||||
// }
|
||||
];
|
||||
|
||||
export default {
|
||||
|
||||
@@ -164,12 +164,12 @@ export const budgetExecutionColumns = [
|
||||
width: 200,
|
||||
ellipsis: true
|
||||
},
|
||||
{
|
||||
title: '操作',
|
||||
key: 'action',
|
||||
align: 'center',
|
||||
width: 100
|
||||
}
|
||||
// {
|
||||
// title: '操作',
|
||||
// key: 'action',
|
||||
// align: 'center',
|
||||
// width: 100
|
||||
// }
|
||||
];
|
||||
|
||||
export default {
|
||||
|
||||
@@ -105,12 +105,12 @@ export const stateAssetsManageColumns = [
|
||||
width: 200,
|
||||
ellipsis: true
|
||||
},
|
||||
{
|
||||
title: '操作',
|
||||
key: 'action',
|
||||
align: 'center',
|
||||
width: 100
|
||||
}
|
||||
// {
|
||||
// title: '操作',
|
||||
// key: 'action',
|
||||
// align: 'center',
|
||||
// width: 100
|
||||
// }
|
||||
];
|
||||
|
||||
export default {
|
||||
|
||||
@@ -41,12 +41,12 @@ export const investmentSituationColumns = [
|
||||
width: 200,
|
||||
// ellipsis: true
|
||||
},
|
||||
{
|
||||
title: '操作',
|
||||
key: 'action',
|
||||
align: 'center',
|
||||
width: 100
|
||||
}
|
||||
// {
|
||||
// title: '操作',
|
||||
// key: 'action',
|
||||
// align: 'center',
|
||||
// width: 100
|
||||
// }
|
||||
];
|
||||
|
||||
// 删除不再需要的单独列配置
|
||||
|
||||
@@ -70,12 +70,12 @@ export const internalControlTestColumns = [
|
||||
width: 200,
|
||||
// ellipsis: true
|
||||
},
|
||||
{
|
||||
title: '操作',
|
||||
key: 'action',
|
||||
align: 'center',
|
||||
width: 100
|
||||
}
|
||||
// {
|
||||
// title: '操作',
|
||||
// key: 'action',
|
||||
// align: 'center',
|
||||
// width: 100
|
||||
// }
|
||||
];
|
||||
|
||||
export default {
|
||||
|
||||
@@ -42,12 +42,12 @@ export const personnelEstablishmentColumns = [
|
||||
align: 'center',
|
||||
width: 200,
|
||||
},
|
||||
{
|
||||
title: '操作',
|
||||
key: 'action',
|
||||
align: 'center',
|
||||
width: 100
|
||||
}
|
||||
// {
|
||||
// title: '操作',
|
||||
// key: 'action',
|
||||
// align: 'center',
|
||||
// width: 100
|
||||
// }
|
||||
];
|
||||
|
||||
export default {
|
||||
|
||||
@@ -0,0 +1,60 @@
|
||||
|
||||
export const benefitEstablishmentColumns = [
|
||||
{
|
||||
title: '序号',
|
||||
dataIndex: 'index',
|
||||
key: 'index',
|
||||
width: 80,
|
||||
align: 'center'
|
||||
},
|
||||
{
|
||||
title: '凭证号',
|
||||
dataIndex: 'voucher',
|
||||
key: 'voucher',
|
||||
align: 'center'
|
||||
},
|
||||
{
|
||||
title: '支出日期',
|
||||
dataIndex: 'expenditureDate',
|
||||
key: 'expenditureDate',
|
||||
align: 'center'
|
||||
},
|
||||
{
|
||||
title: '用途',
|
||||
dataIndex: 'usage',
|
||||
key: 'usage',
|
||||
align: 'center'
|
||||
},
|
||||
{
|
||||
title: '收款方',
|
||||
dataIndex: 'payee',
|
||||
key: 'payee',
|
||||
align: 'center'
|
||||
},
|
||||
{
|
||||
title: '金额(元)',
|
||||
dataIndex: 'amount',
|
||||
key: 'amount',
|
||||
align: 'center'
|
||||
},
|
||||
{
|
||||
title: '归属部门/人员',
|
||||
dataIndex: 'belongTo',
|
||||
key: 'belongTo',
|
||||
align: 'center'
|
||||
},
|
||||
{
|
||||
title: '款项性质说明',
|
||||
dataIndex: 'natureDesc',
|
||||
key: 'natureDesc',
|
||||
align: 'center'
|
||||
},
|
||||
{
|
||||
title: '违规说明',
|
||||
dataIndex: 'violationDesc',
|
||||
key: 'violationDesc',
|
||||
align: 'center'
|
||||
}
|
||||
];
|
||||
|
||||
export default benefitEstablishmentColumns;
|
||||
@@ -1,3 +1,5 @@
|
||||
import table9ExtraColumns from './table9ExtraColumns';
|
||||
|
||||
export const tableConfigs = {
|
||||
// 审计内容1表格配置
|
||||
auditContent1: {
|
||||
@@ -5,9 +7,22 @@ export const tableConfigs = {
|
||||
title: '贯彻决策部署情况',
|
||||
options: [
|
||||
// { title: '贯彻决策部署', value: 'default1', columns: () => import('./table1Columns').then(m => m.default1Columns) },
|
||||
{ title: '领导班子名单', value: 'leaderList', columns: () => import('./table1Columns').then(m => m.leaderListColumns) },
|
||||
{ title: '决策支出表', value: 'expense', columns: () => import('./table1Columns').then(m => m.expenseColumns) },
|
||||
{ title: '八项规定', value: 'eightReg', columns: () => import('./table1Columns').then(m => m.eightRegColumns) }
|
||||
{
|
||||
title: '领导班子名单',
|
||||
value: 'leaderList',
|
||||
columns: () =>
|
||||
import('./table1Columns').then((m) => m.leaderListColumns)
|
||||
},
|
||||
{
|
||||
title: '决策支出表',
|
||||
value: 'expense',
|
||||
columns: () => import('./table1Columns').then((m) => m.expenseColumns)
|
||||
},
|
||||
{
|
||||
title: '八项规定',
|
||||
value: 'eightReg',
|
||||
columns: () => import('./table1Columns').then((m) => m.eightRegColumns)
|
||||
}
|
||||
],
|
||||
// 接口映射
|
||||
interfaceMap: {
|
||||
@@ -22,7 +37,12 @@ export const tableConfigs = {
|
||||
type: 'auditContent2',
|
||||
title: '单位发展战略执行',
|
||||
options: [
|
||||
{ title: '单位发展战略执行', value: 'strategyAudit', columns: () => import('./table2Columns').then(m => m.strategyAuditColumns) }
|
||||
{
|
||||
title: '单位发展战略执行',
|
||||
value: 'strategyAudit',
|
||||
columns: () =>
|
||||
import('./table2Columns').then((m) => m.strategyAuditColumns)
|
||||
}
|
||||
],
|
||||
interfaceMap: {
|
||||
strategyAudit: '/api/ai/auditContent2/generateStrategyAuditTable'
|
||||
@@ -33,8 +53,17 @@ export const tableConfigs = {
|
||||
type: 'auditContent3',
|
||||
title: '重大经济决策调查',
|
||||
options: [
|
||||
{ title: '重大经济决策调查表', value: 'decisionTable', columns: () => import('./table3Columns').then(m => m.decisionTableColumns) },
|
||||
{ title: '三重一大', value: 'tripleOne', columns: () => import('./table3Columns').then(m => m.tripleOneColumns) }
|
||||
{
|
||||
title: '重大经济决策调查表',
|
||||
value: 'decisionTable',
|
||||
columns: () =>
|
||||
import('./table3Columns').then((m) => m.decisionTableColumns)
|
||||
},
|
||||
{
|
||||
title: '三重一大',
|
||||
value: 'tripleOne',
|
||||
columns: () => import('./table3Columns').then((m) => m.tripleOneColumns)
|
||||
}
|
||||
],
|
||||
interfaceMap: {
|
||||
tripleOne: '/api/ai/auditContent3/generateTripleOneTable',
|
||||
@@ -46,7 +75,11 @@ export const tableConfigs = {
|
||||
type: 'auditContent4',
|
||||
title: '目标完成情况',
|
||||
options: [
|
||||
{ title: '目标责任完成情况表', value: 'target', columns: () => import('./table4Columns').then(m => m.columns0) }
|
||||
{
|
||||
title: '目标责任完成情况表',
|
||||
value: 'target',
|
||||
columns: () => import('./table4Columns').then((m) => m.columns0)
|
||||
}
|
||||
],
|
||||
interfaceMap: {
|
||||
target: '/api/ai/auditContent4/generateTargetTable'
|
||||
@@ -57,8 +90,18 @@ export const tableConfigs = {
|
||||
type: 'auditContent5',
|
||||
title: '财务管理情况',
|
||||
options: [
|
||||
{ title: '预算管理审计', value: 'budgetManage', columns: () => import('./table5Columns').then(m => m.budgetManageColumns) },
|
||||
{ title: '预算执行情况审计', value: 'budgetExecution', columns: () => import('./table5Columns').then(m => m.budgetExecutionColumns) }
|
||||
{
|
||||
title: '预算管理审计',
|
||||
value: 'budgetManage',
|
||||
columns: () =>
|
||||
import('./table5Columns').then((m) => m.budgetManageColumns)
|
||||
},
|
||||
{
|
||||
title: '预算执行情况审计',
|
||||
value: 'budgetExecution',
|
||||
columns: () =>
|
||||
import('./table5Columns').then((m) => m.budgetExecutionColumns)
|
||||
}
|
||||
],
|
||||
interfaceMap: {
|
||||
budgetManage: '/api/ai/auditContent5/generateBudgetManageTable',
|
||||
@@ -70,7 +113,12 @@ export const tableConfigs = {
|
||||
type: 'auditContent6',
|
||||
title: '国资管理情况',
|
||||
options: [
|
||||
{ title: '国有资产管理审计', value: 'assets', columns: () => import('./table6Columns').then(m => m.stateAssetsManageColumns) }
|
||||
{
|
||||
title: '国有资产管理审计',
|
||||
value: 'assets',
|
||||
columns: () =>
|
||||
import('./table6Columns').then((m) => m.stateAssetsManageColumns)
|
||||
}
|
||||
],
|
||||
interfaceMap: {
|
||||
assets: '/api/ai/auditContent6/generateAssetsTable'
|
||||
@@ -80,17 +128,28 @@ export const tableConfigs = {
|
||||
type: 'auditContent7',
|
||||
title: '重大投资情况',
|
||||
options: [
|
||||
{ title: '重大投资情况审计', value: 'investmentSituation', columns: () => import('./table7Columns').then(m => m.investmentSituationColumns) },
|
||||
{
|
||||
title: '重大投资情况审计',
|
||||
value: 'investmentSituation',
|
||||
columns: () =>
|
||||
import('./table7Columns').then((m) => m.investmentSituationColumns)
|
||||
}
|
||||
],
|
||||
interfaceMap: {
|
||||
investmentSituation: '/api/ai/auditContent7/generateInvestmentSituationTable'
|
||||
investmentSituation:
|
||||
'/api/ai/auditContent7/generateInvestmentSituationTable'
|
||||
}
|
||||
},
|
||||
auditContent8: {
|
||||
type: 'auditContent8',
|
||||
title: '治理结构与内部控制',
|
||||
options: [
|
||||
{ title: '内部控制测试', value: 'internalControl', columns: () => import('./table8Columns').then(m => m.internalControlTestColumns) }
|
||||
{
|
||||
title: '内部控制测试',
|
||||
value: 'internalControl',
|
||||
columns: () =>
|
||||
import('./table8Columns').then((m) => m.internalControlTestColumns)
|
||||
}
|
||||
],
|
||||
interfaceMap: {
|
||||
internalControl: '/api/ai/auditContent8/generateInternalControlTable'
|
||||
@@ -100,8 +159,15 @@ export const tableConfigs = {
|
||||
type: 'auditContent9',
|
||||
title: '人员编制管理',
|
||||
options: [
|
||||
{ title: '人员编制管理审计', value: 'personnel', columns: () => import('./table9Columns').then(m => m.personnelEstablishmentColumns) }
|
||||
{
|
||||
title: '人员编制管理审计',
|
||||
value: 'personnel',
|
||||
columns: () =>
|
||||
import('./table9Columns').then((m) => m.personnelEstablishmentColumns)
|
||||
}
|
||||
],
|
||||
extraTableTitle: '福利费超范围支出明细清单',
|
||||
extraColumns: table9ExtraColumns,
|
||||
interfaceMap: {
|
||||
personnel: '/api/ai/auditContent9/generatePersonnelTable'
|
||||
}
|
||||
@@ -110,7 +176,12 @@ export const tableConfigs = {
|
||||
type: 'auditContent10',
|
||||
title: '廉政情况',
|
||||
options: [
|
||||
{ title: '党风廉政建设责任制审计', value: 'partyConduct', columns: () => import('./table10Columns').then(m => m.partyConductColumns) }
|
||||
{
|
||||
title: '党风廉政建设责任制审计',
|
||||
value: 'partyConduct',
|
||||
columns: () =>
|
||||
import('./table10Columns').then((m) => m.partyConductColumns)
|
||||
}
|
||||
],
|
||||
interfaceMap: {
|
||||
partyConduct: '/api/ai/auditContent10/generatePartyConductTable'
|
||||
@@ -120,7 +191,12 @@ export const tableConfigs = {
|
||||
type: 'auditContent11',
|
||||
title: '历史审计问题整改',
|
||||
options: [
|
||||
{ title: '历史审计问题整改', value: 'history', columns: () => import('./table11Columns').then(m => m.auditHistoryColumns) }
|
||||
{
|
||||
title: '历史审计问题整改',
|
||||
value: 'history',
|
||||
columns: () =>
|
||||
import('./table11Columns').then((m) => m.auditHistoryColumns)
|
||||
}
|
||||
],
|
||||
interfaceMap: {
|
||||
history: '/api/ai/auditContent11/generateHistoryTable'
|
||||
@@ -145,7 +221,9 @@ export function getAllTableConfigs() {
|
||||
// 通过接口名称查找表格配置
|
||||
export function findTableConfigByInterface(interfaceName: string) {
|
||||
for (const [key, config] of Object.entries(tableConfigs)) {
|
||||
for (const [tableValue, tableInterface] of Object.entries(config.interfaceMap || {})) {
|
||||
for (const [tableValue, tableInterface] of Object.entries(
|
||||
config.interfaceMap || {}
|
||||
)) {
|
||||
if (tableInterface === interfaceName) {
|
||||
return {
|
||||
sectionType: key,
|
||||
@@ -162,7 +240,7 @@ export function findTableConfigByInterface(interfaceName: string) {
|
||||
function parseWorkPaperIndex(workPaperIndex) {
|
||||
if (!workPaperIndex || !Array.isArray(workPaperIndex)) return [];
|
||||
|
||||
return workPaperIndex.map(item => {
|
||||
return workPaperIndex.map((item) => {
|
||||
if (item && typeof item === 'object') {
|
||||
return {
|
||||
fileId: item.fileId || item.file_id || '',
|
||||
@@ -192,41 +270,48 @@ function parseWorkPaperIndex(workPaperIndex) {
|
||||
// 通用数据映射函数
|
||||
export function createDataMapper(type: string) {
|
||||
const mappers = {
|
||||
default1: (data) => data.map((item, index) => ({
|
||||
default1: (data) =>
|
||||
data.map((item, index) => ({
|
||||
key: index,
|
||||
index: index + 1,
|
||||
...item,
|
||||
workPaperIndex: parseWorkPaperIndex(item.workPaperIndex)
|
||||
})),
|
||||
leaderList: (data) => data.map((item, index) => ({
|
||||
leaderList: (data) =>
|
||||
data.map((item, index) => ({
|
||||
key: index,
|
||||
...item,
|
||||
workPaperIndex: parseWorkPaperIndex(item.workPaperIndex)
|
||||
})),
|
||||
expense: (data) => data.map((item, index) => ({
|
||||
expense: (data) =>
|
||||
data.map((item, index) => ({
|
||||
key: index,
|
||||
...item,
|
||||
finalStatementAmount: formatAmount(item.finalStatementAmount),
|
||||
initialBudgetAmount: formatAmount(item.initialBudgetAmount),
|
||||
workPaperIndex: parseWorkPaperIndex(item.workPaperIndex)
|
||||
})),
|
||||
eightReg: (data) => data.map((item, index) => ({
|
||||
eightReg: (data) =>
|
||||
data.map((item, index) => ({
|
||||
key: index,
|
||||
...item,
|
||||
workPaperIndex: parseWorkPaperIndex(item.workPaperIndex)
|
||||
})),
|
||||
strategyAudit: (data) => data.map((item, index) => ({
|
||||
strategyAudit: (data) =>
|
||||
data.map((item, index) => ({
|
||||
key: index,
|
||||
index: index + 1,
|
||||
...item,
|
||||
workPaperIndex: parseWorkPaperIndex(item.workPaperIndex)
|
||||
})),
|
||||
tripleOne: (data) => data.map((item, index) => ({
|
||||
tripleOne: (data) =>
|
||||
data.map((item, index) => ({
|
||||
key: index,
|
||||
...item,
|
||||
workPaperIndex: parseWorkPaperIndex(item.workPaperIndex)
|
||||
})),
|
||||
decisionTable: (data) => data.map((item, index) => ({
|
||||
decisionTable: (data) =>
|
||||
data.map((item, index) => ({
|
||||
key: index,
|
||||
index: index + 1,
|
||||
goods: item.executionEffect?.good || item.goods || '否',
|
||||
@@ -235,7 +320,8 @@ export function createDataMapper(type: string) {
|
||||
...item,
|
||||
workPaperIndex: parseWorkPaperIndex(item.workPaperIndex)
|
||||
})),
|
||||
budgetManage: (data) => data.map((item, index) => ({
|
||||
budgetManage: (data) =>
|
||||
data.map((item, index) => ({
|
||||
key: index,
|
||||
index: index + 1,
|
||||
...item,
|
||||
@@ -246,14 +332,17 @@ export function createDataMapper(type: string) {
|
||||
initialBudget: formatAmount(item.indicatorSourceInitialBudget),
|
||||
additionalBudget: formatAmount(item.indicatorSourceAdditionalBudget),
|
||||
indicatorUseTotal: formatAmount(item.indicatorUseTotal),
|
||||
appropriationSubtotal: formatAmount(item.indicatorUseAppropriationSubtotal),
|
||||
appropriationSubtotal: formatAmount(
|
||||
item.indicatorUseAppropriationSubtotal
|
||||
),
|
||||
appropriation: formatAmount(item.indicatorUseAppropriation),
|
||||
salaryPayment: formatAmount(item.indicatorUseSalaryPayment),
|
||||
govProcurement: formatAmount(item.indicatorUseGovProcurement),
|
||||
indicatorBalance: formatAmount(item.indicatorBalance),
|
||||
workPaperIndex: parseWorkPaperIndex(item.workPaperIndex),
|
||||
workPaperIndex: parseWorkPaperIndex(item.workPaperIndex)
|
||||
})),
|
||||
investmentSituation: (data) => data.map((item, index) => ({
|
||||
investmentSituation: (data) =>
|
||||
data.map((item, index) => ({
|
||||
key: index,
|
||||
index: index + 1,
|
||||
category: item.category || '未分类',
|
||||
@@ -264,7 +353,8 @@ export function createDataMapper(type: string) {
|
||||
...item
|
||||
})),
|
||||
// 其他类型的映射...
|
||||
default: (data) => data.map((item, index) => ({
|
||||
default: (data) =>
|
||||
data.map((item, index) => ({
|
||||
key: index,
|
||||
index: index + 1,
|
||||
...item,
|
||||
@@ -280,7 +370,9 @@ function formatAmount(amount) {
|
||||
if (!amount) return '0.00';
|
||||
if (typeof amount === 'string' && amount.includes(',')) return amount;
|
||||
const num = parseFloat(amount);
|
||||
return isNaN(num) ? '0.00' : num.toLocaleString('zh-CN', {
|
||||
return isNaN(num)
|
||||
? '0.00'
|
||||
: num.toLocaleString('zh-CN', {
|
||||
minimumFractionDigits: 2,
|
||||
maximumFractionDigits: 2
|
||||
});
|
||||
@@ -289,30 +381,66 @@ function formatAmount(amount) {
|
||||
// 生成接口映射
|
||||
export const apiMethodMap = {
|
||||
// 审计内容1
|
||||
default1: { generate: 'generateDefault1Table', export: 'exportDefault1Table' },
|
||||
leaderList: { generate: 'generateLeaderListTable', export: 'exportLeaderListTable' },
|
||||
default1: {
|
||||
generate: 'generateDefault1Table',
|
||||
export: 'exportDefault1Table'
|
||||
},
|
||||
leaderList: {
|
||||
generate: 'generateLeaderListTable',
|
||||
export: 'exportLeaderListTable'
|
||||
},
|
||||
expense: { generate: 'generateExpenseTable', export: 'exportExpenseTable' },
|
||||
eightReg: { generate: 'generateEightRegTable', export: 'exportEightRegTable' },
|
||||
eightReg: {
|
||||
generate: 'generateEightRegTable',
|
||||
export: 'exportEightRegTable'
|
||||
},
|
||||
// 审计内容2
|
||||
strategyAudit: { generate: 'generateStrategyAuditTable', export: 'exportStrategyAuditTable' },
|
||||
strategyAudit: {
|
||||
generate: 'generateStrategyAuditTable',
|
||||
export: 'exportStrategyAuditTable'
|
||||
},
|
||||
// 审计内容3
|
||||
tripleOne: { generate: 'generateTripleOneTable', export: 'exportTripleOneTable' },
|
||||
decisionTable: { generate: 'generateDecisionTable', export: 'exportDecisionTable' },
|
||||
tripleOne: {
|
||||
generate: 'generateTripleOneTable',
|
||||
export: 'exportTripleOneTable'
|
||||
},
|
||||
decisionTable: {
|
||||
generate: 'generateDecisionTable',
|
||||
export: 'exportDecisionTable'
|
||||
},
|
||||
// 审计内容4
|
||||
target: { generate: 'generateTargetTable', export: 'exportTargetTable' },
|
||||
// 审计内容5
|
||||
budgetManage: { generate: 'generateBudgetManageTable', export: 'exportBudgetManageTable' },
|
||||
budgetExecution: { generate: 'generateBudgetExecutionTable', export: 'exportBudgetExecutionTable' },
|
||||
budgetManage: {
|
||||
generate: 'generateBudgetManageTable',
|
||||
export: 'exportBudgetManageTable'
|
||||
},
|
||||
budgetExecution: {
|
||||
generate: 'generateBudgetExecutionTable',
|
||||
export: 'exportBudgetExecutionTable'
|
||||
},
|
||||
// 审计内容6
|
||||
assets: { generate: 'generateAssetsTable', export: 'exportAssetsTable' },
|
||||
// 审计内容7
|
||||
investmentSituation: { generate: 'generateInvestmentSituationTable', export: 'exportInvestmentSituationTable' },
|
||||
investmentSituation: {
|
||||
generate: 'generateInvestmentSituationTable',
|
||||
export: 'exportInvestmentSituationTable'
|
||||
},
|
||||
// 审计内容8
|
||||
internalControl: { generate: 'generateInternalControlTable', export: 'exportInternalControlTable' },
|
||||
internalControl: {
|
||||
generate: 'generateInternalControlTable',
|
||||
export: 'exportInternalControlTable'
|
||||
},
|
||||
// 审计内容9
|
||||
personnel: { generate: 'generatePersonnelTable', export: 'exportPersonnelTable' },
|
||||
personnel: {
|
||||
generate: 'generatePersonnelTable',
|
||||
export: 'exportPersonnelTable'
|
||||
},
|
||||
// 审计内容10
|
||||
partyConduct: { generate: 'generatePartyConductTable', export: 'exportPartyConductTable' },
|
||||
partyConduct: {
|
||||
generate: 'generatePartyConductTable',
|
||||
export: 'exportPartyConductTable'
|
||||
},
|
||||
// 审计内容11
|
||||
history: { generate: 'generateHistoryTable', export: 'exportHistoryTable' },
|
||||
// 默认
|
||||
|
||||
@@ -13,13 +13,22 @@
|
||||
<!-- 基本信息卡片 -->
|
||||
<a-card title="基本信息" style="margin-bottom: 20px" :bordered="false">
|
||||
<a-descriptions>
|
||||
<a-descriptions-item label="公司名称" :labelStyle="{ width: '90px', color: '#808080' }">
|
||||
<a-descriptions-item
|
||||
label="公司名称"
|
||||
:labelStyle="{ width: '90px', color: '#808080' }"
|
||||
>
|
||||
<span @click="copyText(form.name)">{{ form.name }}</span>
|
||||
</a-descriptions-item>
|
||||
<a-descriptions-item label="被审计人" :labelStyle="{ width: '90px', color: '#808080' }">
|
||||
<a-descriptions-item
|
||||
label="被审计人"
|
||||
:labelStyle="{ width: '90px', color: '#808080' }"
|
||||
>
|
||||
<span>{{ form.nickname || '暂无' }}</span>
|
||||
</a-descriptions-item>
|
||||
<a-descriptions-item label="审计时间" :labelStyle="{ width: '90px', color: '#808080' }">
|
||||
<a-descriptions-item
|
||||
label="审计时间"
|
||||
:labelStyle="{ width: '90px', color: '#808080' }"
|
||||
>
|
||||
<span>{{ form.expirationTime }}</span>
|
||||
</a-descriptions-item>
|
||||
</a-descriptions>
|
||||
@@ -115,7 +124,9 @@
|
||||
<div
|
||||
class="progress-fill"
|
||||
:style="{
|
||||
width: `${((currentSection + 1) / navigationItems.length) * 100}%`
|
||||
width: `${
|
||||
((currentSection + 1) / navigationItems.length) * 100
|
||||
}%`
|
||||
}"
|
||||
></div>
|
||||
</div>
|
||||
@@ -155,11 +166,10 @@
|
||||
<template #extra>
|
||||
<a-space>
|
||||
<!-- 所有表格都显示导出按钮 -->
|
||||
<template v-if="item.mode === 'table' && item.tableOptions.length > 0">
|
||||
<a-button
|
||||
danger
|
||||
@click="clearCurrentTable(index)"
|
||||
<template
|
||||
v-if="item.mode === 'table' && item.tableOptions.length > 0"
|
||||
>
|
||||
<a-button danger @click="clearCurrentTable(index)">
|
||||
清空表格
|
||||
</a-button>
|
||||
<a-button
|
||||
@@ -196,8 +206,16 @@
|
||||
</template>
|
||||
|
||||
<!-- 通用表格切换器 - 所有表格都显示 -->
|
||||
<div class="flex justify-between items-center mb-4" v-if="item.mode === 'table'">
|
||||
<div
|
||||
class="flex justify-between items-center mb-4"
|
||||
v-if="item.mode === 'table'"
|
||||
>
|
||||
<div class="flex justify-start items-center">
|
||||
<a-space>
|
||||
<a-button type="primary">编辑</a-button>
|
||||
<a-button type="primary" danger>删除</a-button>
|
||||
<a-button>导出</a-button>
|
||||
<a-button @click="openEvidenceModal(index)">导出取证单</a-button>
|
||||
<template v-if="item.tableOptions.length > 0">
|
||||
<div class="flex items-center">
|
||||
<span class="mr-2">切换表格:</span>
|
||||
@@ -223,14 +241,16 @@
|
||||
条数据
|
||||
</span>
|
||||
</template>
|
||||
</a-space>
|
||||
</div>
|
||||
<!-- 所有表格都显示历史记录 -->
|
||||
<a @click="openHistory(index)" class="cursor-pointer">历史记录</a>
|
||||
</div>
|
||||
|
||||
<!-- 表格内容 -->
|
||||
<template v-if="item.mode === 'table' && item.columns">
|
||||
<a-table
|
||||
v-if="item.mode === 'table' && item.columns"
|
||||
:row-selection="getRowSelection(index)"
|
||||
:columns="item.columns"
|
||||
:scroll="{ y: 500, x: 1000 }"
|
||||
:pagination="false"
|
||||
@@ -239,19 +259,38 @@
|
||||
>
|
||||
<template #bodyCell="{ column, record }">
|
||||
<!-- 操作列 -->
|
||||
<template v-if="column.key === 'action'">
|
||||
<a-space>
|
||||
<a-button type="link" size="small" @click="editRow(record, index)">编辑</a-button>
|
||||
<a-button type="link" size="small" danger @click="deleteRow(record, index)">删除</a-button>
|
||||
</a-space>
|
||||
</template>
|
||||
<!-- <template v-if="column.key === 'action'">-->
|
||||
<!-- <a-space>-->
|
||||
<!-- <a-button-->
|
||||
<!-- type="link"-->
|
||||
<!-- size="small"-->
|
||||
<!-- @click="editRow(record, index)"-->
|
||||
<!-- >编辑</a-button-->
|
||||
<!-- >-->
|
||||
<!-- <a-button-->
|
||||
<!-- type="link"-->
|
||||
<!-- size="small"-->
|
||||
<!-- danger-->
|
||||
<!-- @click="deleteRow(record, index)"-->
|
||||
<!-- >删除</a-button-->
|
||||
<!-- >-->
|
||||
<!-- </a-space>-->
|
||||
<!-- </template>-->
|
||||
|
||||
<!-- 测试结果列 -->
|
||||
<template v-if="column.key === 'testResult' || column.key === 'result'">
|
||||
<span class="text-green-400" v-if="record[column.key] === '通过'">
|
||||
<template
|
||||
v-if="column.key === 'testResult' || column.key === 'result'"
|
||||
>
|
||||
<span
|
||||
class="text-green-400"
|
||||
v-if="record[column.key] === '通过'"
|
||||
>
|
||||
通过
|
||||
</span>
|
||||
<span class="text-red-400" v-else-if="record[column.key] === '不通过'">
|
||||
<span
|
||||
class="text-red-400"
|
||||
v-else-if="record[column.key] === '不通过'"
|
||||
>
|
||||
不通过
|
||||
</span>
|
||||
<span class="text-gray-400" v-else>
|
||||
@@ -261,14 +300,24 @@
|
||||
|
||||
<!-- 工作底稿索引列 -->
|
||||
<template v-if="column.key === 'workPaperIndex'">
|
||||
<div v-if="record.workPaperIndex && record.workPaperIndex.length > 0">
|
||||
<div
|
||||
v-if="
|
||||
record.workPaperIndex && record.workPaperIndex.length > 0
|
||||
"
|
||||
>
|
||||
<div
|
||||
@click="openDoc(fileItem)"
|
||||
v-for="(fileItem, fileIndex) in record.workPaperIndex"
|
||||
:key="fileIndex"
|
||||
>
|
||||
<img
|
||||
src="@/assets/word.png"
|
||||
style="width: 20px; height: 20px; vertical-align: middle; margin-right: 4px;"
|
||||
style="
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
vertical-align: middle;
|
||||
margin-right: 4px;
|
||||
"
|
||||
alt=""
|
||||
/>
|
||||
|
||||
@@ -279,7 +328,7 @@
|
||||
target="_blank"
|
||||
@click.stop="handleFileDownload(fileItem, $event)"
|
||||
class="file-link cursor-pointer text-wrap"
|
||||
style="color: #1890ff; text-decoration: none;"
|
||||
style="color: #1890ff; text-decoration: none"
|
||||
>
|
||||
{{ fileItem.fileName || '未命名文件' }}
|
||||
</a>
|
||||
@@ -304,13 +353,21 @@
|
||||
style="width: 20px; height: 20px"
|
||||
alt=""
|
||||
/>
|
||||
<span class="cursor-pointer text-wrap">{{ fileItem }}</span>
|
||||
<span class="cursor-pointer text-wrap">{{
|
||||
fileItem
|
||||
}}</span>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<!-- 执行效果相关列 -->
|
||||
<template v-if="column.key === 'goods' || column.key === 'normal' || column.key === 'bad'">
|
||||
<template
|
||||
v-if="
|
||||
column.key === 'goods' ||
|
||||
column.key === 'normal' ||
|
||||
column.key === 'bad'
|
||||
"
|
||||
>
|
||||
<span v-if="record[column.key] === '是'">✅</span>
|
||||
<span v-else>❌</span>
|
||||
</template>
|
||||
@@ -330,7 +387,16 @@
|
||||
</template>
|
||||
</template>
|
||||
</a-table>
|
||||
|
||||
<p v-if="item.extraTableTitle" class="font-bold my-2">{{ item.extraTableTitle }}</p>
|
||||
<a-table
|
||||
v-if="item.extraColumns && item.extraColumns.length"
|
||||
:columns="item.extraColumns"
|
||||
:scroll="{ y: 500, x: 1000 }"
|
||||
:pagination="false"
|
||||
bordered
|
||||
:data-source="item.extraData"
|
||||
></a-table>
|
||||
</template>
|
||||
<!-- 单选模式 -->
|
||||
<template v-else-if="item.mode === 'radio'">
|
||||
<div
|
||||
@@ -423,35 +489,42 @@
|
||||
:fields="editingFields"
|
||||
@save="saveEdit"
|
||||
/>
|
||||
<EvidenceModal
|
||||
v-model:visible="evidenceModalVisible"
|
||||
:base-info="evidenceBaseInfo"
|
||||
:selected-rows="evidenceSelectedRows"
|
||||
/>
|
||||
</a-drawer>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
import { ref, reactive, watch, onMounted, onUnmounted, computed } from 'vue';
|
||||
import { Form, message, Modal } from 'ant-design-vue';
|
||||
import { Form, message, Modal, TableProps } from 'ant-design-vue';
|
||||
import { assignObject } from 'ele-admin-pro';
|
||||
import { copyText } from '@/utils/common';
|
||||
import type { PwlProject } from '@/api/pwl/pwlProject/model';
|
||||
import {
|
||||
RedoOutlined,
|
||||
RobotOutlined,
|
||||
UngroupOutlined,
|
||||
QuestionCircleOutlined,
|
||||
DownloadOutlined,
|
||||
UploadOutlined,
|
||||
FolderOpenOutlined,
|
||||
SaveOutlined
|
||||
} from '@ant-design/icons-vue';
|
||||
import { generateAuditReport, downloadAuditReport } from '@/api/ai/auditReport';
|
||||
import { generateAuditReport } from '@/api/ai/auditReport';
|
||||
import { getPwlProjectLibraryByIds } from '@/api/pwl/pwlProjectLibrary';
|
||||
import { addAiHistory } from '@/api/ai/aiHistory';
|
||||
import * as auditContentApi from '@/api/ai/auditContent';
|
||||
|
||||
import FileModal from '@/views/pwl/pwlProject/components/components/FileModal.vue';
|
||||
import HistoryModal from '@/views/pwl/pwlProject/components/components/HistoryModal.vue';
|
||||
import EvidenceModal from '@/views/pwl/pwlProject/components/components/EvidenceModal.vue';
|
||||
import EditModal from './EditModal.vue';
|
||||
|
||||
import useNavigationItems from './data/navigationItems';
|
||||
import { tableConfigs, getTableConfig, createDataMapper, apiMethodMap, findTableConfigByInterface } from './data/tableCommon';
|
||||
import {
|
||||
tableConfigs,
|
||||
getTableConfig,
|
||||
createDataMapper,
|
||||
apiMethodMap,
|
||||
findTableConfigByInterface
|
||||
} from './data/tableCommon';
|
||||
|
||||
// 工具函数
|
||||
import {
|
||||
@@ -509,25 +582,56 @@ const checkedDirKeys = ref<(string | number)[]>([]);
|
||||
const lastSelectedDirKeys = ref<(string | number)[]>([]);
|
||||
const lastSelectedFileKeys = ref<(string | number)[]>([]);
|
||||
|
||||
// ========== 取证单相关 ==========
|
||||
const evidenceModalVisible = ref(false);
|
||||
const evidenceBaseInfo = reactive({
|
||||
caseIndex: '',
|
||||
projectName: '',
|
||||
auditedTarget: '',
|
||||
auditMatter: ''
|
||||
});
|
||||
const evidenceSelectedRows = ref<any[]>([]);
|
||||
|
||||
// ========== 表格选择 ==========
|
||||
const selectedRowsMap = reactive<Record<number, any[]>>({});
|
||||
const rowSelections = reactive<Record<number, TableProps['rowSelection']>>(
|
||||
{}
|
||||
);
|
||||
|
||||
const getRowSelection = (sectionIndex: number): TableProps['rowSelection'] => {
|
||||
if (!rowSelections[sectionIndex]) {
|
||||
rowSelections[sectionIndex] = {
|
||||
onChange: (selectedRowKeys: string[], selectedRows: any[]) => {
|
||||
selectedRowsMap[sectionIndex] = selectedRows;
|
||||
}
|
||||
};
|
||||
}
|
||||
return rowSelections[sectionIndex];
|
||||
};
|
||||
// ========== 历史记录相关 ==========
|
||||
const showHistory = ref(false);
|
||||
const currentInterfaceName = ref('');
|
||||
|
||||
// ========== 三重一大数据 ==========
|
||||
const tripleOneData = ref(null);
|
||||
const tripleOneData = ref<any>(null);
|
||||
// ========== 国资管理数据 ==========
|
||||
const stateAssetsData = ref(null);
|
||||
const stateAssetsData = ref<any>(null);
|
||||
|
||||
// ========== 表格数据存储 ==========
|
||||
const tableData = reactive({});
|
||||
|
||||
// ========== 统一的表格生成数据存储 ==========
|
||||
const tableGenerationData = reactive<Record<string, {
|
||||
const tableGenerationData = reactive<
|
||||
Record<
|
||||
string,
|
||||
{
|
||||
requestData?: any;
|
||||
responseData?: any;
|
||||
interfaceName?: string;
|
||||
timestamp?: number;
|
||||
}>>({});
|
||||
}
|
||||
>
|
||||
>({});
|
||||
|
||||
// ========== 表单数据 ==========
|
||||
const form = reactive<PwlProject>({
|
||||
@@ -538,22 +642,24 @@ const { resetFields } = useForm(form);
|
||||
|
||||
// ========== 计算属性 ==========
|
||||
const hasTripleOneData = computed(() => {
|
||||
const section = navigationItems.value[2];
|
||||
const section: any = navigationItems.value[2];
|
||||
return section.data && section.data.length > 0;
|
||||
});
|
||||
|
||||
// ========== 工具函数 ==========
|
||||
const getTableKey = (sectionIndex: number) => {
|
||||
const section = navigationItems.value[sectionIndex];
|
||||
if (!section || !section.tableOptions || section.tableOptions.length === 0) return '';
|
||||
const section: any = navigationItems.value[sectionIndex];
|
||||
if (!section || !section.tableOptions || section.tableOptions.length === 0)
|
||||
return '';
|
||||
const currentTable = section.tableOptions[section.currentTableIndex];
|
||||
if (!currentTable) return '';
|
||||
return `${section.tableType}_${currentTable.value}`;
|
||||
};
|
||||
|
||||
const getTableInfo = (sectionIndex: number) => {
|
||||
const section = navigationItems.value[sectionIndex];
|
||||
if (!section || !section.tableOptions || section.tableOptions.length === 0) return null;
|
||||
const section: any = navigationItems.value[sectionIndex];
|
||||
if (!section || !section.tableOptions || section.tableOptions.length === 0)
|
||||
return null;
|
||||
const currentTable = section.tableOptions[section.currentTableIndex];
|
||||
if (!currentTable) return null;
|
||||
|
||||
@@ -573,8 +679,11 @@ const updateVisible = (value: boolean) => {
|
||||
};
|
||||
|
||||
/* 表格切换处理 */
|
||||
const handleTableChange = async (sectionIndex: number, tableIndex: number) => {
|
||||
const section = navigationItems.value[sectionIndex];
|
||||
const handleTableChange = async (
|
||||
sectionIndex: number,
|
||||
tableIndex: number
|
||||
) => {
|
||||
const section: any = navigationItems.value[sectionIndex];
|
||||
if (!section || !section.tableOptions[tableIndex]) return;
|
||||
|
||||
section.currentTableIndex = tableIndex;
|
||||
@@ -609,14 +718,43 @@ const openDocSelect = (sectionIndex: number) => {
|
||||
|
||||
checkedDirKeys.value = [...lastSelectedDirKeys.value];
|
||||
selectedFileKeys.value = [...lastSelectedFileKeys.value];
|
||||
selectedDocList.value = lastSelectedDirKeys.value.map(key => key.toString());
|
||||
selectedFileList.value = lastSelectedFileKeys.value.map(key => key.toString());
|
||||
selectedDocList.value = lastSelectedDirKeys.value.map((key) =>
|
||||
key.toString()
|
||||
);
|
||||
selectedFileList.value = lastSelectedFileKeys.value.map((key) =>
|
||||
key.toString()
|
||||
);
|
||||
|
||||
fileModal.value.open(tableInfo.tableKey);
|
||||
};
|
||||
|
||||
/* 打开取证单预览弹窗 */
|
||||
const openEvidenceModal = (sectionIndex: number) => {
|
||||
const section: any = navigationItems.value[sectionIndex];
|
||||
const tableInfo = getTableInfo(sectionIndex);
|
||||
|
||||
evidenceBaseInfo.caseIndex = (form as any).code || props.data?.code || '';
|
||||
evidenceBaseInfo.projectName = form.name || props.data?.name || '';
|
||||
evidenceBaseInfo.auditedTarget =
|
||||
(form as any).nickname || (props.data as any)?.nickname || '';
|
||||
|
||||
const baseMatter = section?.title || section?.name || '';
|
||||
const tableTitle = tableInfo?.currentTable?.title || '';
|
||||
evidenceBaseInfo.auditMatter = tableTitle
|
||||
? `${baseMatter ? `${baseMatter} - ` : ''}${tableTitle}`
|
||||
: baseMatter;
|
||||
|
||||
evidenceSelectedRows.value = selectedRowsMap[sectionIndex] || [];
|
||||
evidenceModalVisible.value = true;
|
||||
};
|
||||
|
||||
/* 保存表格生成数据 */
|
||||
const saveTableGenerationData = (tableKey: string, requestData: any, responseData: any, tableValue?: string) => {
|
||||
const saveTableGenerationData = (
|
||||
tableKey: string,
|
||||
requestData: any,
|
||||
responseData: any,
|
||||
tableValue?: string
|
||||
) => {
|
||||
// 根据tableKey找到对应的表格配置,获取正确的接口名称
|
||||
let correctInterfaceName = tableKey;
|
||||
|
||||
@@ -625,11 +763,15 @@ const saveTableGenerationData = (tableKey: string, requestData: any, responseDat
|
||||
|
||||
// 查找对应的表格配置
|
||||
const sectionKeys = Object.keys(tableConfigs);
|
||||
const sectionIndex = sectionKeys.findIndex(key => key === sectionType);
|
||||
const sectionIndex = sectionKeys.findIndex((key) => key === sectionType);
|
||||
|
||||
if (sectionIndex !== -1) {
|
||||
const tableConfig = getTableConfig(sectionIndex);
|
||||
if (tableConfig && tableConfig.interfaceMap && tableConfig.interfaceMap[value || tableValue]) {
|
||||
if (
|
||||
tableConfig &&
|
||||
tableConfig.interfaceMap &&
|
||||
tableConfig.interfaceMap[value || tableValue]
|
||||
) {
|
||||
correctInterfaceName = tableConfig.interfaceMap[value || tableValue];
|
||||
}
|
||||
}
|
||||
@@ -666,20 +808,28 @@ const generateTableContent = async (sectionIndex: number) => {
|
||||
kbIds: props.data?.kbId || '',
|
||||
libraryIds: props.data?.libraryIds || '',
|
||||
projectLibrary: props.data?.projectLibrary || '',
|
||||
history: section.data?.length > 0 ? JSON.stringify(section.data, null, 2) : '',
|
||||
history:
|
||||
section.data?.length > 0 ? JSON.stringify(section.data, null, 2) : '',
|
||||
suggestion: section.suggestion || '',
|
||||
docList: checkedDirKeys.value,
|
||||
fileList: selectedFileKeys.value,
|
||||
// 重大经济决策调查表需要三重一大数据
|
||||
...(currentTable.value === 'decisionTable' ? { data: tripleOneData.value } : {}),
|
||||
...(currentTable.value === 'decisionTable'
|
||||
? { data: tripleOneData.value }
|
||||
: {}),
|
||||
// 预算管理审计表需要国资管理数据
|
||||
...(currentTable.value === 'budgetManage' ? { data: stateAssetsData.value } : {}),
|
||||
...(currentTable.value === 'budgetManage'
|
||||
? { data: stateAssetsData.value }
|
||||
: {}),
|
||||
// 预算执行情况审计表需要预算管理审计的数据
|
||||
...(currentTable.value === 'budgetExecution' ? { data: tableData['auditContent5_budgetManage'] } : {}),
|
||||
...(currentTable.value === 'budgetExecution'
|
||||
? { data: tableData['auditContent5_budgetManage'] }
|
||||
: {})
|
||||
};
|
||||
|
||||
// 获取对应的生成方法
|
||||
const apiMethod = apiMethodMap[currentTable.value] || apiMethodMap.default;
|
||||
const apiMethod =
|
||||
apiMethodMap[currentTable.value] || apiMethodMap.default;
|
||||
const generateMethod = auditContentApi[apiMethod.generate];
|
||||
|
||||
if (!generateMethod) {
|
||||
@@ -690,7 +840,12 @@ const generateTableContent = async (sectionIndex: number) => {
|
||||
|
||||
if (result.code === 0 && result.data?.success) {
|
||||
// 保存表格生成数据
|
||||
saveTableGenerationData(tableKey, requestData, result.data, currentTable.value);
|
||||
saveTableGenerationData(
|
||||
tableKey,
|
||||
requestData,
|
||||
result.data,
|
||||
currentTable.value
|
||||
);
|
||||
|
||||
// 使用对应的数据映射函数
|
||||
const dataMapper = createDataMapper(currentTable.value);
|
||||
@@ -709,7 +864,9 @@ const generateTableContent = async (sectionIndex: number) => {
|
||||
|
||||
section.data = mappedData;
|
||||
section.suggestion = '';
|
||||
message.success(`成功生成 ${mappedData.length} 条${currentTable.title}记录`);
|
||||
message.success(
|
||||
`成功生成 ${mappedData.length} 条${currentTable.title}记录`
|
||||
);
|
||||
} else {
|
||||
throw new Error(result.data?.error || result.message || '生成失败');
|
||||
}
|
||||
@@ -735,7 +892,8 @@ const handleExportTable = async (sectionIndex: number) => {
|
||||
|
||||
// 使用正确的公司名称和审计时间
|
||||
const companyName = form.name || props.data?.name || '未知公司';
|
||||
const auditTime = form.expirationTime || props.data?.expirationTime || '未知时间';
|
||||
const auditTime =
|
||||
form.expirationTime || props.data?.expirationTime || '未知时间';
|
||||
|
||||
// 设置导出状态
|
||||
exportStates[tableKey] = true;
|
||||
@@ -748,7 +906,8 @@ const handleExportTable = async (sectionIndex: number) => {
|
||||
};
|
||||
|
||||
// 获取对应的导出方法
|
||||
const apiMethod = apiMethodMap[currentTable.value] || apiMethodMap.default;
|
||||
const apiMethod =
|
||||
apiMethodMap[currentTable.value] || apiMethodMap.default;
|
||||
const exportMethod = auditContentApi[apiMethod.export];
|
||||
|
||||
if (!exportMethod) {
|
||||
@@ -760,7 +919,10 @@ const handleExportTable = async (sectionIndex: number) => {
|
||||
const url = window.URL.createObjectURL(new Blob([blob]));
|
||||
const link = document.createElement('a');
|
||||
link.href = url;
|
||||
link.setAttribute('download', `${currentTable.title}_${companyName}.xlsx`);
|
||||
link.setAttribute(
|
||||
'download',
|
||||
`${currentTable.title}_${companyName}.xlsx`
|
||||
);
|
||||
document.body.appendChild(link);
|
||||
link.click();
|
||||
document.body.removeChild(link);
|
||||
@@ -803,7 +965,7 @@ const handleGenerateAll = async () => {
|
||||
|
||||
/* AI生成内容 */
|
||||
const generateContent = async (sectionIndex: number, childIndex?: number) => {
|
||||
const section = navigationItems.value[sectionIndex];
|
||||
const section: any = navigationItems.value[sectionIndex];
|
||||
|
||||
if (section.mode === 'table') {
|
||||
await generateTableContent(sectionIndex);
|
||||
@@ -813,8 +975,11 @@ const generateContent = async (sectionIndex: number, childIndex?: number) => {
|
||||
};
|
||||
|
||||
/* 默认内容生成方法 */
|
||||
const generateDefaultContent = async (sectionIndex: number, childIndex?: number) => {
|
||||
const section = navigationItems.value[sectionIndex];
|
||||
const generateDefaultContent = async (
|
||||
sectionIndex: number,
|
||||
childIndex?: number
|
||||
) => {
|
||||
const section: any = navigationItems.value[sectionIndex];
|
||||
const contextData = await buildExportData();
|
||||
|
||||
section.generating = true;
|
||||
@@ -843,7 +1008,8 @@ const openHistory = (sectionIndex: number) => {
|
||||
// 通过表格配置获取接口名称
|
||||
const tableConfig = getTableConfig(sectionIndex);
|
||||
if (tableConfig && tableConfig.interfaceMap) {
|
||||
currentInterfaceName.value = tableConfig.interfaceMap[currentTable.value] || '';
|
||||
currentInterfaceName.value =
|
||||
tableConfig.interfaceMap[currentTable.value] || '';
|
||||
}
|
||||
}
|
||||
|
||||
@@ -868,14 +1034,22 @@ const handleHistorySelect = (record: any) => {
|
||||
}
|
||||
|
||||
// 找到对应的章节索引
|
||||
const sectionIndex = Object.keys(tableConfigs).findIndex(key => key === tableConfig.sectionType);
|
||||
const sectionIndex = Object.keys(tableConfigs).findIndex(
|
||||
(key) => key === tableConfig.sectionType
|
||||
);
|
||||
if (sectionIndex === -1) {
|
||||
message.warning('未找到对应的章节');
|
||||
return;
|
||||
}
|
||||
|
||||
// 应用历史数据
|
||||
applyHistoryData(sectionIndex, responseData.data, tableConfig.tableValue, record.requestData, record.interfaceName);
|
||||
applyHistoryData(
|
||||
sectionIndex,
|
||||
responseData.data,
|
||||
tableConfig.tableValue,
|
||||
record.requestData,
|
||||
record.interfaceName
|
||||
);
|
||||
message.success('已应用选择的历史记录');
|
||||
} catch (error: any) {
|
||||
console.error('解析历史记录数据失败:', error);
|
||||
@@ -884,15 +1058,23 @@ const handleHistorySelect = (record: any) => {
|
||||
};
|
||||
|
||||
/* 应用历史数据 */
|
||||
const applyHistoryData = async (sectionIndex: number, data: any[], tableValue: string, requestDataStr?: string, interfaceName?: string) => {
|
||||
const section = navigationItems.value[sectionIndex];
|
||||
const applyHistoryData = async (
|
||||
sectionIndex: number,
|
||||
data: any[],
|
||||
tableValue: string,
|
||||
requestDataStr?: string,
|
||||
interfaceName?: string
|
||||
) => {
|
||||
const section: any = navigationItems.value[sectionIndex];
|
||||
if (!section) return;
|
||||
|
||||
const tableConfig = getTableConfig(sectionIndex);
|
||||
if (!tableConfig) return;
|
||||
|
||||
// 找到对应的表格选项索引
|
||||
const tableOptionIndex = section.tableOptions.findIndex(option => option.value === tableValue);
|
||||
const tableOptionIndex = section.tableOptions.findIndex(
|
||||
(option) => option.value === tableValue
|
||||
);
|
||||
if (tableOptionIndex === -1) return;
|
||||
|
||||
// 解析请求数据
|
||||
@@ -940,11 +1122,12 @@ const applyHistoryData = async (sectionIndex: number, data: any[], tableValue: s
|
||||
|
||||
/* 编辑行 */
|
||||
const editRow = (record: any, sectionIndex: number) => {
|
||||
const section = navigationItems.value[sectionIndex];
|
||||
const section: any = navigationItems.value[sectionIndex];
|
||||
if (!section || !section.columns) return;
|
||||
|
||||
// 获取可编辑的字段(排除操作列)
|
||||
editingFields.value = section.columns.filter(col =>
|
||||
editingFields.value = section.columns.filter(
|
||||
(col) =>
|
||||
col.key !== 'action' &&
|
||||
col.dataIndex !== 'key' &&
|
||||
col.dataIndex !== 'index' &&
|
||||
@@ -966,10 +1149,12 @@ const editRow = (record: any, sectionIndex: number) => {
|
||||
|
||||
/* 保存编辑 */
|
||||
const saveEdit = (updatedRecord: any) => {
|
||||
const section = navigationItems.value[editingSectionIndex.value];
|
||||
const section: any = navigationItems.value[editingSectionIndex.value];
|
||||
if (!section || !section.data) return;
|
||||
|
||||
const index = section.data.findIndex((item: any) => item.key === updatedRecord.key);
|
||||
const index = section.data.findIndex(
|
||||
(item: any) => item.key === updatedRecord.key
|
||||
);
|
||||
if (index !== -1) {
|
||||
// 保留原有数据的其他字段
|
||||
const originalRecord = section.data[index];
|
||||
@@ -978,10 +1163,15 @@ const saveEdit = (updatedRecord: any) => {
|
||||
// 更新对应的响应数据
|
||||
if (editingTableKey.value && tableGenerationData[editingTableKey.value]) {
|
||||
// 获取当前的响应数据
|
||||
const responseData = tableGenerationData[editingTableKey.value].responseData;
|
||||
const responseData =
|
||||
tableGenerationData[editingTableKey.value].responseData;
|
||||
|
||||
// 如果响应数据存在且包含data数组
|
||||
if (responseData && responseData.data && Array.isArray(responseData.data)) {
|
||||
if (
|
||||
responseData &&
|
||||
responseData.data &&
|
||||
Array.isArray(responseData.data)
|
||||
) {
|
||||
// 找到对应的原始数据索引
|
||||
const dataIndex = (() => {
|
||||
const hasValidId =
|
||||
@@ -990,7 +1180,9 @@ const saveEdit = (updatedRecord: any) => {
|
||||
updatedRecord.id !== '';
|
||||
|
||||
if (hasValidId) {
|
||||
const byId = responseData.data.findIndex((item: any) => item.id === updatedRecord.id);
|
||||
const byId = responseData.data.findIndex(
|
||||
(item: any) => item.id === updatedRecord.id
|
||||
);
|
||||
if (byId !== -1) return byId;
|
||||
}
|
||||
|
||||
@@ -1003,10 +1195,12 @@ const saveEdit = (updatedRecord: any) => {
|
||||
return updatedRecord.key;
|
||||
}
|
||||
|
||||
const hasKey = updatedRecord.key !== undefined && updatedRecord.key !== null;
|
||||
const hasKey =
|
||||
updatedRecord.key !== undefined && updatedRecord.key !== null;
|
||||
if (hasKey) {
|
||||
const byKey = responseData.data.findIndex(
|
||||
(item: any) => item.key !== undefined && item.key === updatedRecord.key
|
||||
(item: any) =>
|
||||
item.key !== undefined && item.key === updatedRecord.key
|
||||
);
|
||||
if (byKey !== -1) return byKey;
|
||||
}
|
||||
@@ -1025,15 +1219,19 @@ const saveEdit = (updatedRecord: any) => {
|
||||
};
|
||||
|
||||
// 更新tableGenerationData中的响应数据
|
||||
tableGenerationData[editingTableKey.value].responseData = responseData;
|
||||
tableGenerationData[editingTableKey.value].responseData =
|
||||
responseData;
|
||||
} else {
|
||||
// 如果没找到对应的原始数据,直接将编辑后的数据添加到响应数据中
|
||||
// 这可能发生在手动添加行的情况下
|
||||
responseData.data.push((() => {
|
||||
responseData.data.push(
|
||||
(() => {
|
||||
const { workPaperIndex, key, index, ...rest } = updatedRecord;
|
||||
return rest;
|
||||
})());
|
||||
tableGenerationData[editingTableKey.value].responseData = responseData;
|
||||
})()
|
||||
);
|
||||
tableGenerationData[editingTableKey.value].responseData =
|
||||
responseData;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1047,21 +1245,36 @@ const saveEdit = (updatedRecord: any) => {
|
||||
|
||||
/* 删除行 */
|
||||
const deleteRow = (record: any, sectionIndex: number) => {
|
||||
const section = navigationItems.value[sectionIndex];
|
||||
const section: any = navigationItems.value[sectionIndex];
|
||||
if (!section || !section.data) return;
|
||||
|
||||
const uiIndex = section.data.findIndex((item: any) => item.key === record.key);
|
||||
const uiIndex = section.data.findIndex(
|
||||
(item: any) => item.key === record.key
|
||||
);
|
||||
if (uiIndex === -1) return;
|
||||
|
||||
// 同步删除原始 responseData(删除前就计算 rawIndex,避免 key 重排导致错位)
|
||||
const tableInfo = getTableInfo(sectionIndex);
|
||||
if (tableInfo && tableInfo.tableKey && tableGenerationData[tableInfo.tableKey]) {
|
||||
if (
|
||||
tableInfo &&
|
||||
tableInfo.tableKey &&
|
||||
tableGenerationData[tableInfo.tableKey]
|
||||
) {
|
||||
const responseData = tableGenerationData[tableInfo.tableKey].responseData;
|
||||
if (responseData && responseData.data && Array.isArray(responseData.data)) {
|
||||
if (
|
||||
responseData &&
|
||||
responseData.data &&
|
||||
Array.isArray(responseData.data)
|
||||
) {
|
||||
const rawIndex = (() => {
|
||||
const hasValidId = record?.id !== undefined && record?.id !== null && record?.id !== '';
|
||||
const hasValidId =
|
||||
record?.id !== undefined &&
|
||||
record?.id !== null &&
|
||||
record?.id !== '';
|
||||
if (hasValidId) {
|
||||
const byId = responseData.data.findIndex((item: any) => item.id === record.id);
|
||||
const byId = responseData.data.findIndex(
|
||||
(item: any) => item.id === record.id
|
||||
);
|
||||
if (byId !== -1) return byId;
|
||||
}
|
||||
|
||||
@@ -1076,12 +1289,15 @@ const deleteRow = (record: any, sectionIndex: number) => {
|
||||
|
||||
const hasKey = record?.key !== undefined && record?.key !== null;
|
||||
if (hasKey) {
|
||||
const byKey = responseData.data.findIndex((item: any) => item.key !== undefined && item.key === record.key);
|
||||
const byKey = responseData.data.findIndex(
|
||||
(item: any) => item.key !== undefined && item.key === record.key
|
||||
);
|
||||
if (byKey !== -1) return byKey;
|
||||
}
|
||||
|
||||
// 最后兜底:使用 UI 索引
|
||||
if (uiIndex >= 0 && uiIndex < responseData.data.length) return uiIndex;
|
||||
if (uiIndex >= 0 && uiIndex < responseData.data.length)
|
||||
return uiIndex;
|
||||
return -1;
|
||||
})();
|
||||
|
||||
@@ -1139,7 +1355,11 @@ const saveCurrentTable = async (sectionIndex: number) => {
|
||||
const tableConfig = getTableConfig(sectionIndex);
|
||||
let correctInterfaceName = generationData.interfaceName; // 默认为当前值
|
||||
|
||||
if (tableConfig && tableConfig.interfaceMap && tableConfig.interfaceMap[currentTable.value]) {
|
||||
if (
|
||||
tableConfig &&
|
||||
tableConfig.interfaceMap &&
|
||||
tableConfig.interfaceMap[currentTable.value]
|
||||
) {
|
||||
correctInterfaceName = tableConfig.interfaceMap[currentTable.value];
|
||||
}
|
||||
|
||||
@@ -1152,7 +1372,8 @@ const saveCurrentTable = async (sectionIndex: number) => {
|
||||
const workPaperIndex = row?.workPaperIndex;
|
||||
if (!Array.isArray(workPaperIndex)) return row;
|
||||
|
||||
const normalized = workPaperIndex.map((item: any) => {
|
||||
const normalized = workPaperIndex
|
||||
.map((item: any) => {
|
||||
if (typeof item === 'string') return item;
|
||||
if (item && typeof item === 'object') {
|
||||
const fileId = item.fileId || item.file_id || '';
|
||||
@@ -1161,7 +1382,8 @@ const saveCurrentTable = async (sectionIndex: number) => {
|
||||
return `${fileId}||${fileName}||${fileUrl}`;
|
||||
}
|
||||
return '';
|
||||
}).filter((s: string) => s && s.trim() !== '');
|
||||
})
|
||||
.filter((s: string) => s && s.trim() !== '');
|
||||
|
||||
return {
|
||||
...row,
|
||||
@@ -1175,8 +1397,10 @@ const saveCurrentTable = async (sectionIndex: number) => {
|
||||
const aiHistory = {
|
||||
projectId: props.data?.id,
|
||||
interfaceName: correctInterfaceName, // 使用正确的接口名称
|
||||
requestData: generationData.requestData ? JSON.stringify(generationData.requestData) : '',
|
||||
responseData: JSON.stringify(normalizedResponseData),
|
||||
requestData: generationData.requestData
|
||||
? JSON.stringify(generationData.requestData)
|
||||
: '',
|
||||
responseData: JSON.stringify(normalizedResponseData)
|
||||
// 其他字段后端会自动设置
|
||||
};
|
||||
|
||||
@@ -1192,8 +1416,14 @@ const saveCurrentTable = async (sectionIndex: number) => {
|
||||
};
|
||||
|
||||
const clearCurrentTable = (sectionIndex: number) => {
|
||||
const section = navigationItems.value[sectionIndex];
|
||||
if (!section || section.mode !== 'table' || !section.tableOptions || section.tableOptions.length === 0) return;
|
||||
const section: any = navigationItems.value[sectionIndex];
|
||||
if (
|
||||
!section ||
|
||||
section.mode !== 'table' ||
|
||||
!section.tableOptions ||
|
||||
section.tableOptions.length === 0
|
||||
)
|
||||
return;
|
||||
|
||||
Modal.confirm({
|
||||
title: '确认清空表格?',
|
||||
@@ -1213,8 +1443,10 @@ const clearCurrentTable = (sectionIndex: number) => {
|
||||
tableGenerationData[tableKey].responseData = next;
|
||||
}
|
||||
|
||||
if (exportStates[tableKey] !== undefined) delete exportStates[tableKey];
|
||||
if (savingStates[tableKey] !== undefined) delete savingStates[tableKey];
|
||||
if (exportStates[tableKey] !== undefined)
|
||||
delete exportStates[tableKey];
|
||||
if (savingStates[tableKey] !== undefined)
|
||||
delete savingStates[tableKey];
|
||||
|
||||
if (option.value === 'tripleOne') {
|
||||
tripleOneData.value = null;
|
||||
@@ -1230,12 +1462,24 @@ const clearCurrentTable = (sectionIndex: number) => {
|
||||
});
|
||||
};
|
||||
|
||||
const openDoc = (fileItem) => {
|
||||
console.log(fileItem);
|
||||
// window.open(
|
||||
// `http://view.officeapps.live.com/op/view.aspx?src=文件地址`,
|
||||
// '_blank'
|
||||
// );
|
||||
};
|
||||
|
||||
/* 键盘快捷键处理 */
|
||||
const handleKeydown = (event: KeyboardEvent) => {
|
||||
if (!props.visible) return;
|
||||
|
||||
// Ctrl/Cmd + 数字键 1-9 快速跳转
|
||||
if ((event.ctrlKey || event.metaKey) && event.key >= '1' && event.key <= '9') {
|
||||
if (
|
||||
(event.ctrlKey || event.metaKey) &&
|
||||
event.key >= '1' &&
|
||||
event.key <= '9'
|
||||
) {
|
||||
event.preventDefault();
|
||||
const index = parseInt(event.key) - 1;
|
||||
if (index < navigationItems.value.length) {
|
||||
@@ -1290,10 +1534,14 @@ watch(
|
||||
assignObject(form, props.data);
|
||||
|
||||
// 获取知识库并拼接 kbIds
|
||||
if (props.data.libraryIds?.length > 0) {
|
||||
if (props.data.libraryIds && props.data.libraryIds?.length > 0) {
|
||||
try {
|
||||
const result = await getPwlProjectLibraryByIds(props.data.libraryIds);
|
||||
const kbIds = result.map((lib) => lib.kbId).filter((kbId) => kbId);
|
||||
const result = await getPwlProjectLibraryByIds(
|
||||
props.data.libraryIds
|
||||
);
|
||||
const kbIds = result
|
||||
.map((lib) => lib.kbId)
|
||||
.filter((kbId) => kbId);
|
||||
if (form.kbId) {
|
||||
kbIds.unshift(form.kbId);
|
||||
}
|
||||
@@ -1311,9 +1559,10 @@ watch(
|
||||
|
||||
// 初始化所有表格的列配置
|
||||
for (let i = 0; i < navigationItems.value.length; i++) {
|
||||
const section = navigationItems.value[i];
|
||||
const section: any = navigationItems.value[i];
|
||||
if (section.tableOptions.length > 0) {
|
||||
const tableOption = section.tableOptions[section.currentTableIndex];
|
||||
const tableOption =
|
||||
section.tableOptions[section.currentTableIndex];
|
||||
if (typeof tableOption.columns === 'function') {
|
||||
try {
|
||||
const module = await tableOption.columns();
|
||||
@@ -1335,12 +1584,13 @@ watch(
|
||||
} else {
|
||||
resetFields();
|
||||
combinedKbIds.value = '';
|
||||
evidenceModalVisible.value = false;
|
||||
// 清空表格数据
|
||||
Object.keys(tableData).forEach(key => {
|
||||
Object.keys(tableData).forEach((key) => {
|
||||
delete tableData[key];
|
||||
});
|
||||
// 清空表格生成数据
|
||||
Object.keys(tableGenerationData).forEach(key => {
|
||||
Object.keys(tableGenerationData).forEach((key) => {
|
||||
delete tableGenerationData[key];
|
||||
});
|
||||
// 清空特殊数据
|
||||
|
||||
Reference in New Issue
Block a user