Compare commits

...

19 Commits

Author SHA1 Message Date
b74bc2d1e7 feat:项目管理-取证单-优化取证单导出word功能 2026-02-04 17:12:16 +08:00
a0a833c534 feat:项目管理-取证单-优化取证单生成、取证单项目名称 2026-02-04 15:03:43 +08:00
8cf26ca53a 修改工作底稿可以直接预览 2026-02-02 16:02:21 +08:00
4ed51bb06a 修改工作底稿索引字段 2026-02-02 15:38:28 +08:00
f2c726c5c6 feat:项目管理-取证单-附件优化 2026-02-02 11:08:18 +08:00
79db6cbcc9 feat:项目管理-项目详情-添加字段案引号 2026-02-02 10:21:34 +08:00
859a396fab 修改工作底稿索引字段 2026-01-30 19:53:09 +08:00
fb71c9e54e 1、调整取证单审计人员数据来源
2、调整工作底稿索引格式
2026-01-30 19:50:23 +08:00
3abf43e054 调整取证单样式 2026-01-30 19:04:01 +08:00
3cf727430a 调整取证单样式 2026-01-30 18:05:19 +08:00
43a8e6e599 feat:项目管理-审计内容7-工作底稿索引优化 2026-01-27 18:03:37 +08:00
b742b80abe feat:项目管理-审计内容-取证单生成 2026-01-16 17:42:52 +08:00
29f6579c8c feat:项目管理-审计内容9-福利费超范围支出明细清单 2026-01-14 18:28:53 +08:00
c3c3a8c3d1 修复编辑、删除无法操作的问题 2026-01-14 09:56:19 +08:00
1adf7de021 修复编辑、删除无法操作的问题 2026-01-14 09:10:29 +08:00
d8b4cba12d 1、审计内容里的操作功能优化
2、审计内容9增加一个表的内容生成
3、添加取证单弹窗
2026-01-13 12:23:55 +08:00
d574975c97 feat:项目管理-审计内容-优化工作底稿索引 2026-01-09 14:50:56 +08:00
f751d5eda4 feat:项目管理-审计内容-优化表格内容编辑、保存、删除功能 2026-01-08 11:20:37 +08:00
20675364e5 feat:项目管理-审计内容-优化表格内容编辑、保存、删除功能 2026-01-08 11:20:25 +08:00
22 changed files with 3510 additions and 1031 deletions

View File

@@ -2,7 +2,8 @@ VITE_APP_NAME=后台管理系统
VITE_SOCKET_URL=wss://server.websoft.top
VITE_SERVER_URL=https://server.websoft.top/api
#VITE_API_URL=https://cms-api.websoft.top/api
VITE_API_URL=https://jfsj.wsdns.cn/api
#VITE_API_URL=https://jfsj.wsdns.cn/api
VITE_API_URL=http://1.14.159.185:9200/api
#VITE_SOCKET_URL=ws://127.0.0.1:9191
#VITE_SERVER_URL=http://127.0.0.1:8000/api

View File

@@ -742,3 +742,76 @@ export async function exportDefault1Table(data: {
}
return Promise.reject(new Error('导出失败'));
}
/**
* 生成取证单
*/
export async function generateAuditEvidence(data: {
// 基础信息
caseIndex?: string; // 案引号
projectName?: string; // 项目名称
auditedTarget?: string; // 被审计单位或个人
auditMatter?: string; // 审计事项
summaryTitle?: string; // 标题
auditRecord?: string; // 审计记录
auditFinding?: string; // 审计发现
evidenceBasis?: string; // 定性依据
handling?: string; // 处理
suggestion?: string; // 建议
attachment?: string; // 附件
auditors?: string; // 审计人员
compileDate?: string; // 编制日期
providerOpinion?: string; // 证据提供单位意见
providerDate?: string; // 证据提供日期
attachmentPages?: string; // 附件页数
feedbackDeadline?: string; // 反馈期限
history?: string; // 历史内容(用于工作流生成)
}) {
const res = await request.post<ApiResult<any>>(
MODULES_API_URL + '/ai/auditEvidence/generate',
data
);
if (res.data.code === 0) {
return res.data;
}
return Promise.reject(new Error(res.data.message));
}
/**
* 下载审计取证单Word文档
*/
export async function downloadAuditEvidence(data: {
caseIndex?: string;
pageIndex?: string;
pageTotal?: string;
projectName?: string;
auditedTarget?: string;
auditMatter?: string;
summaryTitle?: string;
auditRecord?: string;
auditFinding?: string;
evidenceBasis?: string;
handling?: string;
attachment?: string;
auditors?: string;
compileDate?: string;
providerOpinion?: string;
providerDate?: string;
attachmentPages?: string;
feedbackDeadline?: string;
}) {
const res = await request.post(
MODULES_API_URL + '/ai/auditEvidence/download',
data,
{
responseType: 'blob' // 处理二进制流响应
}
);
if (res.status === 200) {
return res.data;
}
return Promise.reject(new Error('文件下载失败'));
}

View File

@@ -10,6 +10,8 @@ export interface PwlProject {
name?: string;
// 项目标识
code?: string;
// 案引号
caseIndex?: string;
// 上级id, 0是顶级
parentId?: number;
// 项目类型

View File

@@ -0,0 +1,296 @@
<template>
<a-modal
:visible="visible"
title="编辑行数据"
@ok="handleOk"
@cancel="handleCancel"
:confirm-loading="loading"
width="600px"
>
<template #title>
<div class="modal-title">
<span>编辑行数据</span>
<a-tag v-if="displayRecords.length > 1" color="blue" class="ml-2">
同步编辑 {{ displayRecords.length }}
</a-tag>
</div>
</template>
<a-alert
v-if="displayRecords.length > 1"
type="info"
show-icon
style="margin-bottom: 12px"
:message="`已选择 ${displayRecords.length} 条记录,将把当前修改同步到这些记录`"
/>
<a-list
v-if="displayRecords.length > 1"
size="small"
bordered
:data-source="displayRecords"
style="margin-bottom: 12px; max-height: 160px; overflow-y: auto"
>
<template #renderItem="{ item, index }">
<a-list-item
:class="['record-item', { active: index === selectedRecordIndex }]"
@click="selectRecord(index)"
>
<span class="record-label">#{{ index + 1 }}</span>
</a-list-item>
</template>
</a-list>
<a-form layout="vertical">
<template v-for="field in processedFields" :key="field.key">
<a-form-item :label="field.title" v-if="!field.children">
<template v-if="field.type === 'textarea'">
<a-textarea
v-model:value="activeFormData[field.dataIndex]"
:rows="4"
:placeholder="`请输入${field.title}`"
/>
</template>
<template v-else-if="field.dataIndex === 'workPaperIndex'">
<a-textarea
v-model:value="activeFormData[field.dataIndex]"
:rows="4"
:placeholder="'每行一个文件格式为file_id||文件名||url'"
/>
</template>
<template v-else>
<a-input
v-model:value="activeFormData[field.dataIndex]"
:placeholder="`请输入${field.title}`"
/>
</template>
</a-form-item>
<!-- 处理嵌套字段如职务下的党内行政 -->
<template v-else-if="field.children">
<div class="nested-fields">
<div class="field-group-title">{{ field.title }}</div>
<div class="field-group-content">
<a-form-item
v-for="childField in field.children"
:key="childField.key"
:label="childField.title"
class="nested-field-item"
>
<a-input
v-model:value="activeFormData[childField.dataIndex]"
:placeholder="`请输入${childField.title}`"
/>
</a-form-item>
</div>
</div>
</template>
</template>
</a-form>
</a-modal>
</template>
<script lang="ts" setup>
import { ref, watch, computed } from 'vue';
import { message } from 'ant-design-vue';
const props = defineProps<{
visible: boolean;
record: any;
fields: any[];
records?: any[];
}>();
const emit = defineEmits(['update:visible', 'save']);
const loading = ref(false);
const formDataList = ref<any[]>([]);
const selectedRecordIndex = ref(0);
const displayRecords = computed(() => {
if (props.records && Array.isArray(props.records) && props.records.length) {
return props.records;
}
if (props.record) return [props.record];
return [];
});
const transformRecordToFormData = (record: any) => {
if (!record) return {};
const recordCopy = JSON.parse(JSON.stringify(record));
if (
hasWorkPaperIndexField.value &&
recordCopy.workPaperIndex &&
Array.isArray(recordCopy.workPaperIndex)
) {
recordCopy.workPaperIndex = recordCopy.workPaperIndex
.map((item: any) => {
if (typeof item === 'object') {
return `${item.fileId || ''}||${item.fileName || ''}||${item.fileUrl || ''}`;
}
return item;
})
.join('\n');
}
return recordCopy;
};
const hasWorkPaperIndexField = computed(() => {
return (props.fields || []).some((field) => {
return field?.dataIndex === 'workPaperIndex' || field?.key === 'workPaperIndex';
});
});
// 处理字段,将嵌套结构展平
const processedFields = computed(() => {
const processed: any[] = [];
(props.fields || []).forEach(field => {
if (field.children && Array.isArray(field.children)) {
// 处理有子字段的情况(如职务)
processed.push({
...field,
children: field.children.flatMap(child =>
child.children && Array.isArray(child.children)
? child.children // 如果是多层嵌套,直接取孙子字段
: child // 否则就是子字段
)
});
} else {
processed.push(field);
}
});
return processed;
});
watch(
() => props.visible,
(visible) => {
if (visible) {
selectedRecordIndex.value = 0;
formDataList.value = displayRecords.value.map((rec) =>
transformRecordToFormData(rec)
);
}
},
{ immediate: true }
);
const handleOk = () => {
if (!formDataList.value || formDataList.value.length === 0) {
message.warning('没有数据可保存');
return;
}
// 处理workPaperIndex将字符串转换回对象数组
const dataToSave = formDataList.value.map((item) => {
const cloned = JSON.parse(JSON.stringify(item || {}));
if (hasWorkPaperIndexField.value && cloned.workPaperIndex && typeof cloned.workPaperIndex === 'string') {
const lines = cloned.workPaperIndex.split('\n').filter((line: string) => line.trim() !== '');
cloned.workPaperIndex = lines.map((line: string) => {
const parts = line.split('||');
if (parts.length >= 3) {
return {
fileId: parts[0] || '',
fileName: parts[1] || '',
fileUrl: parts[2] || ''
};
}
return line;
});
}
return cloned;
});
loading.value = true;
emit('save', dataToSave);
loading.value = false;
emit('update:visible', false);
};
const handleCancel = () => {
emit('update:visible', false);
};
const selectRecord = (index: number) => {
if (index < 0 || index >= displayRecords.value.length) return;
selectedRecordIndex.value = index;
if (!formDataList.value[index]) {
formDataList.value[index] = transformRecordToFormData(
displayRecords.value[index]
);
}
};
const activeFormData = computed({
get() {
if (!displayRecords.value.length) return {};
if (!formDataList.value[selectedRecordIndex.value]) {
formDataList.value[selectedRecordIndex.value] = transformRecordToFormData(
displayRecords.value[selectedRecordIndex.value]
);
}
return formDataList.value[selectedRecordIndex.value] || {};
},
set(val) {
if (!displayRecords.value.length) return;
formDataList.value[selectedRecordIndex.value] = val || {};
}
});
</script>
<style scoped>
.nested-fields {
margin-bottom: 16px;
border: 1px solid #f0f0f0;
border-radius: 4px;
padding: 12px;
background-color: #fafafa;
}
.field-group-title {
font-weight: 600;
margin-bottom: 8px;
color: #1890ff;
}
.field-group-content {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
gap: 12px;
}
.nested-field-item {
margin-bottom: 0;
}
.modal-title {
display: flex;
align-items: center;
}
.record-label {
display: inline-block;
width: 36px;
color: #888;
}
.record-text {
color: #333;
}
.record-item {
cursor: pointer;
transition: background-color 0.2s;
}
.record-item:hover {
background-color: #f5f5f5;
}
.record-item.active {
background-color: #e6f7ff;
}
</style>

View File

@@ -0,0 +1,847 @@
<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="handleExport" :loading="exporting">
导出Word文档
</a-button>
<a-button v-if="false" @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: 16%" />
<col style="width: 84%" />
</colgroup>
<tbody>
<tr>
<th>项目名称</th>
<td>
<textarea
v-model="form.projectName"
class="cell-input single"
placeholder="填写项目名称"
></textarea>
</td>
</tr>
<tr>
<th>被审计调查单位或个人</th>
<td>
<textarea
v-model="form.auditedTarget"
class="cell-input single"
placeholder="填写被审计(调查)单位或个人"
></textarea>
</td>
</tr>
<tr>
<th>审计调查事项</th>
<td>
<textarea
v-model="form.auditMatter"
class="cell-input single"
placeholder="填写审计(调查)事项"
></textarea>
</td>
</tr>
<tr>
<th class="vertical-header">
<div class="vertical-text">
<span>审计</span>
<span>调查</span>
<span>事项</span>
<span>摘要</span>
</div>
</th>
<td class="summary-cell">
<div class="summary-title">
审计调查事项摘要包括标题审计记录审计发现定性依据
</div>
<!-- <div class="summary-content">-->
<!-- <div class="summary-item">-->
<!-- <strong>1.标题</strong-->
<!-- >突出核心问题采用观点性语句一般为审计内容审计目标的结论性描述例如-->
<!-- </div>-->
<!-- <div class="summary-example">-->
<!-- 在审计期间XX单位存在"服务费,其流通"行为-->
<!-- </div>-->
<!-- <div class="summary-item">-->
<!-- <strong>2.审计记录</strong-->
<!-- >仅客观记录审计核查的具体事实时间地点主体行为数据等不使用主观评价性语言"违规""不合理"或问题定性引证合同条款凭证等等原始凭证形式"经核查[凭证描述]……"例如-->
<!-- </div>-->
<!-- <div class="summary-example">-->
<!-- -->
<!-- 经查2019年1月1日签订的XX服务合同编号XYZ-2019-001第3条约定"乙方(服务商)员工薪酬中甲方考勤费,甲方有权对乙方员工薪酬进行审核并支付"-->
<!-- </div>-->
<!-- <div class="summary-example">-->
<!-- -->
<!-- 调取2019年6月外包人员考勤表显示实际出勤人数为8人缺勤2人由甲方部门主管确认缺勤2人由甲方资源部核实无-->
<!-- </div>-->
<!-- <div class="summary-example">-->
<!-- -->
<!-- 查证2020年3月服务费结算凭证凭证号FV20200315所附明细清单显示人员名单为8人且月计薪资×工资标准结算费用-->
<!-- </div>-->
<!-- </div>-->
<div class="summary-editor">
<div class="summary-field">
<div class="summary-field-label">标题</div>
<textarea
v-model="form.summaryTitle"
class="cell-input summary-textarea medium"
placeholder="填写核心标题或要点"
></textarea>
</div>
<div class="summary-field">
<div class="summary-field-label">审计记录</div>
<textarea
v-model="form.auditRecord"
class="cell-input summary-textarea tall"
placeholder="客观记录审计核查的过程与事实"
></textarea>
</div>
<div class="summary-field">
<div class="summary-field-label">审计发现</div>
<textarea
v-model="form.auditFinding"
class="cell-input summary-textarea tall"
placeholder="写明审计发现的事实、性质及影响"
></textarea>
</div>
<div class="summary-field">
<div class="summary-field-label">定性依据</div>
<textarea
v-model="form.evidenceBasis"
class="cell-input summary-textarea medium"
placeholder="引用法规、制度或合同条款作为依据"
></textarea>
</div>
</div>
</td>
</tr>
<tr>
<th>处理建议</th>
<td>
<textarea
v-model="form.handling"
class="cell-input medium"
placeholder="拟采取的处理措施"
></textarea>
</td>
</tr>
<tr>
<th>附件</th>
<td>
<textarea
v-model="form.attachment"
class="cell-input single"
placeholder="列示随附的证明材料"
></textarea>
</td>
</tr>
<tr>
<th>审计人员</th>
<td>
<div class="split-row">
<div class="split-left">
<input
v-model="form.auditors"
class="cell-input input-line"
placeholder="填写审计人员"
/>
</div>
<div class="split-right">
<span class="label">编制日期</span>
<input
v-model="form.compileDate"
class="cell-input input-line"
placeholder="YYYY-MM-DD"
/>
</div>
</div>
</td>
</tr>
<tr>
<th>证据提供单位或个人意见</th>
<td>
<div class="provider-row">
<div class="provider-opinion">
<textarea
v-model="form.providerOpinion"
class="cell-input tall"
placeholder="证据提供单位盖章,负责人或其他定的人员签名"
></textarea>
</div>
<div class="provider-date">
<div class="date-label">日期</div>
<input
v-model="form.providerDate"
class="cell-input input-line"
placeholder="YYYY-MM-DD"
/>
</div>
</div>
</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="填写反馈期限"
/>
前反馈意见以生成的编制日期为基础往后推10天填充日期
</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';
import { PwlProject } from '@/api/pwl/pwlProject/model';
import { downloadAuditEvidence } from '@/api/ai/auditContent';
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: () => ({})
},
project: {
type: Object as PropType<PwlProject>,
default: () => ({})
},
selectedRows: {
type: Array as PropType<any[]>,
default: () => []
}
});
const emit = defineEmits<{
(e: 'update:visible', value: boolean): void;
}>();
const printArea = ref<HTMLElement | null>(null);
const exporting = ref(false);
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 formatAttachmentText = (caseIndex: string, raw: string) => {
const safeCaseIndex = (caseIndex || '').trim();
const items = (raw || '')
.split(/[\n\r,,、;\s]+/)
.map((s) => s.trim())
.filter(Boolean);
if (!safeCaseIndex || items.length === 0) return raw || '';
const escaped = safeCaseIndex.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
const prefixRe = new RegExp(`^${escaped}-\\d{3}-`);
return items
.map((name, idx) => {
const no = String(idx + 1).padStart(3, '0');
const baseName = name.replace(prefixRe, '');
return `${safeCaseIndex}-${no}-${baseName}`;
})
.join('\n');
};
const applyBaseInfo = () => {
console.log('applyBaseInfo called, selectedRows:', props.selectedRows);
console.log('baseInfo:', props.baseInfo);
// 重置表单为默认值
Object.assign(form, defaultForm(), props.baseInfo || {});
// 如果有传入的selectedRows直接使用第一个对象的数据生成取证单时通常只有一个
if (props.selectedRows && props.selectedRows.length > 0) {
const evidenceData = props.selectedRows[0] || {};
console.log('Evidence data from selectedRows:', evidenceData);
// 直接将后端返回的数据映射到表单字段
form.caseIndex =
props.baseInfo?.caseIndex || props.project?.caseIndex || form.caseIndex || '';
form.projectName = props.project?.code || evidenceData.projectName || form.projectName || '';
form.auditedTarget =
evidenceData.auditedTarget || form.auditedTarget || '';
form.auditMatter = evidenceData.auditMatter || form.auditMatter || '';
form.summaryTitle = evidenceData.summaryTitle || form.summaryTitle || '';
form.auditRecord = evidenceData.auditRecord || form.auditRecord || '';
form.auditFinding = evidenceData.auditFinding || form.auditFinding || '';
form.evidenceBasis =
evidenceData.evidenceBasis || form.evidenceBasis || '';
form.handling = evidenceData.handling || form.handling || '';
form.suggestion = evidenceData.suggestion || form.suggestion || '';
// form.auditors = evidenceData.auditors || form.auditors || '';
form.auditors = '';
if (props.project && props.project.saleUser) {
const saleUser = JSON.parse(props.project.saleUser);
form.auditors = saleUser.join();
}
form.compileDate = evidenceData.compileDate || form.compileDate || '';
// form.providerOpinion =
// evidenceData.providerOpinion || form.providerOpinion || '';
// form.providerDate = evidenceData.providerDate || form.providerDate || '';
form.providerOpinion = '';
form.providerDate = '';
form.attachmentPages =
evidenceData.attachmentPages || form.attachmentPages || '';
// form.feedbackDeadline =
// evidenceData.feedbackDeadline || form.feedbackDeadline || '';
form.feedbackDeadline = 'XX年XX月XX日';
// 处理attachment字段数组转字符串
if (evidenceData.attachment) {
const rawAttachment = Array.isArray(evidenceData.attachment)
? evidenceData.attachment.join('\n')
: evidenceData.attachment;
form.attachment = formatAttachmentText(form.caseIndex, rawAttachment);
}
// 特殊处理如果evidenceData中有title字段也填充到summaryTitle
if (evidenceData.title && !form.summaryTitle) {
form.summaryTitle = evidenceData.title;
}
}
// 设置默认编制日期(如果没有的话)
if (!form.compileDate) {
const now = new Date();
form.compileDate = `${now.getFullYear()}-${String(
now.getMonth() + 1
).padStart(2, '0')}-${String(now.getDate()).padStart(2, '0')}`;
}
// 确保页码字段有值
if (!form.pageIndex) form.pageIndex = '1';
if (!form.pageTotal) form.pageTotal = '1';
console.log(
'Form data after applyBaseInfo:',
JSON.stringify(form, null, 2)
);
};
watch(
() => props.visible,
(visible) => {
if (visible) {
applyBaseInfo();
}
}
);
watch(
() => props.baseInfo,
() => {
if (props.visible) {
applyBaseInfo();
}
},
{ deep: true }
);
watch(
() => props.project,
() => {
if (props.visible) {
applyBaseInfo();
}
},
{ deep: true }
);
watch(
() => props.selectedRows,
() => {
if (props.visible) {
applyBaseInfo();
}
},
{ deep: true }
);
const handleCancel = () => {
emit('update:visible', false);
};
const resetFields = () => {
applyBaseInfo();
message.success('内容已重置');
};
/**
* 导出Word文档
*/
const handleExport = async () => {
try {
exporting.value = true;
// 准备导出数据
const exportData = {
caseIndex: form.caseIndex,
pageIndex: form.pageIndex,
pageTotal: form.pageTotal,
projectName: form.projectName,
auditedTarget: form.auditedTarget,
auditMatter: form.auditMatter,
summaryTitle: form.summaryTitle,
auditRecord: form.auditRecord,
auditFinding: form.auditFinding,
evidenceBasis: form.evidenceBasis,
handling: form.handling,
attachment: form.attachment,
auditors: form.auditors,
compileDate: form.compileDate,
providerOpinion: form.providerOpinion,
providerDate: form.providerDate,
attachmentPages: form.attachmentPages,
feedbackDeadline: form.feedbackDeadline
};
// 调用后端下载接口
const blob = await downloadAuditEvidence(exportData);
// 创建下载链接
const url = window.URL.createObjectURL(new Blob([blob]));
const link = document.createElement('a');
link.href = url;
// 设置文件名
const fileName = `审计取证单_${form.projectName || '取证单'}_${form.caseIndex || ''}.docx`;
link.setAttribute('download', fileName);
// 触发下载
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
// 释放URL对象
window.URL.revokeObjectURL(url);
message.success('取证单导出成功');
} catch (error) {
console.error('导出失败:', error);
message.error('取证单导出失败');
} finally {
exporting.value = false;
}
};
/**
* 打印预览
*/
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: 12px; font-family: 'SimSun', 'Songti SC', serif; color: #000; }
.evidence-sheet { padding: 14px 16px; border: 1px solid #000; }
.sheet-title { text-align: center; font-size: 24px; letter-spacing: 8px; margin-bottom: 6px; font-weight: 700; }
.sheet-meta { display: flex; justify-content: space-between; align-items: flex-end; font-size: 14px; margin-bottom: 8px; }
.meta-left, .meta-right { display: flex; align-items: flex-end; gap: 4px; }
.inline-input { border: none; border-bottom: 1px solid #000; min-width: 70px; padding: 2px 4px; font-size: 14px; background: transparent; outline: none; height: 20px; line-height: 20px; }
.inline-input.small { width: 44px; 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: 6px 8px; vertical-align: top; font-size: 14px; line-height: 1.6; }
.sheet-table th { background: #fff; font-weight: 600; text-align: center; vertical-align: middle; }
.vertical-header { padding: 4px 2px; font-weight: 600; }
.vertical-text { display: flex; flex-direction: column; align-items: center; gap: 2px; }
.vertical-text span { display: block; line-height: 1.1; }
.cell-input { width: 100%; border: none; resize: none; min-height: 32px; font-size: 14px; line-height: 1.6; font-family: inherit; background: transparent; overflow: hidden; field-sizing: content; }
.cell-input:focus { outline: none; }
.cell-input.single { min-height: 30px; }
.cell-input.medium { min-height: 90px; }
.cell-input.tall { min-height: 170px; }
.input-line { height: 30px; }
.summary-cell { padding: 8px 12px; }
.summary-title { font-weight: 600; margin-bottom: 6px; text-align: left; }
.summary-content { text-align: left; line-height: 1.7; font-size: 12px; }
.summary-item { margin-bottom: 6px; }
.summary-example { margin-left: 16px; margin-bottom: 6px; color: #000; }
.summary-editor { margin-top: 8px; }
.summary-field { margin-bottom: 6px; }
.summary-field-label { font-weight: 600; margin-bottom: 4px; }
.summary-textarea { margin: 0; padding: 0; }
.split-row { display: flex; align-items: stretch; gap: 0; min-height: 36px; }
.split-left { flex: 1; padding-right: 8px; }
.split-right { display: flex; align-items: center; gap: 4px; white-space: nowrap; border-left: 1px solid #000; padding-left: 8px; }
.provider-row { display: flex; gap: 0; min-height: 140px; align-items: stretch; }
.provider-opinion { flex: 1; padding-right: 8px; }
.provider-date { width: 110px; display: flex; flex-direction: column; gap: 8px; justify-content: center; align-items: center; border-left: 1px solid #000; padding-left: 6px; }
.date-label { font-weight: 600; }
.footer-note { margin-top: 10px; font-size: 12px; line-height: 1.6; }
.note-row { margin-bottom: 6px; text-align: right; }
.note { 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: #f2f2f2;
padding: 16px;
}
.evidence-sheet {
background: #fff;
padding: 14px 16px;
border: 1px solid #000;
box-shadow: none;
width: 794px;
max-width: 100%;
min-height: 1123px;
margin: 0 auto;
font-family: 'SimSun', 'Songti SC', serif;
color: #000;
}
.sheet-title {
text-align: center;
font-size: 24px;
letter-spacing: 8px;
margin-bottom: 6px;
font-weight: 700;
}
.sheet-meta {
display: flex;
justify-content: space-between;
align-items: flex-end;
font-size: 14px;
margin-bottom: 8px;
}
.meta-left,
.meta-right {
display: flex;
align-items: flex-end;
gap: 4px;
}
.inline-input {
border: none;
border-bottom: 1px solid #000;
min-width: 70px;
padding: 2px 4px;
font-size: 14px;
background: transparent;
outline: none;
height: 20px;
line-height: 20px;
}
.inline-input.small {
width: 44px;
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: 6px 8px;
vertical-align: top;
font-size: 14px;
line-height: 1.6;
}
.sheet-table th {
background: #fff;
font-weight: 600;
text-align: center;
vertical-align: middle;
}
.vertical-header {
padding: 4px 2px;
font-weight: 600;
}
.vertical-text {
display: flex;
flex-direction: column;
align-items: center;
gap: 2px;
}
.vertical-text span {
display: block;
line-height: 1.1;
}
.cell-input {
width: 100%;
border: none;
resize: none;
min-height: 32px;
font-size: 14px;
line-height: 1.6;
font-family: inherit;
background: transparent;
overflow: hidden;
field-sizing: content;
}
.cell-input:focus {
outline: none;
}
.cell-input.single {
min-height: 30px;
}
.cell-input.medium {
min-height: 90px;
}
.cell-input.tall {
min-height: 170px;
}
.input-line {
height: 30px;
}
.summary-cell {
padding: 8px 12px;
}
.summary-title {
font-weight: 600;
margin-bottom: 6px;
text-align: left;
}
.summary-content {
text-align: left;
line-height: 1.7;
font-size: 12px;
}
.summary-item {
margin-bottom: 6px;
}
.summary-example {
margin-left: 16px;
margin-bottom: 6px;
color: #000;
}
.summary-editor {
margin-top: 8px;
}
.summary-field {
margin-bottom: 6px;
}
.summary-field-label {
font-weight: 600;
margin-bottom: 4px;
}
.summary-textarea {
margin: 0;
padding: 0;
}
.split-row {
display: flex;
align-items: stretch;
gap: 0;
min-height: 36px;
}
.split-left {
flex: 1;
padding-right: 8px;
}
.split-right {
display: flex;
align-items: center;
gap: 4px;
white-space: nowrap;
border-left: 1px solid #000;
padding-left: 8px;
}
.provider-row {
display: flex;
gap: 0;
min-height: 140px;
align-items: stretch;
}
.provider-opinion {
flex: 1;
padding-right: 8px;
}
.provider-date {
width: 110px;
display: flex;
flex-direction: column;
gap: 8px;
justify-content: center;
align-items: center;
border-left: 1px solid #000;
padding-left: 6px;
}
.date-label {
font-weight: 600;
}
.footer-note {
margin-top: 10px;
font-size: 12px;
line-height: 1.6;
}
.note-row {
margin-bottom: 6px;
text-align: right;
}
.note {
margin-bottom: 4px;
}
</style>

View File

@@ -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}`,

View File

@@ -65,15 +65,15 @@ export const partyConductColumns = [
dataIndex: 'workPaperIndex',
key: 'workPaperIndex',
align: 'center',
width: 180,
width: 200,
// ellipsis: true
},
{
title: '操作',
key: 'action',
align: 'center',
width: 100
}
// {
// title: '操作',
// key: 'action',
// align: 'center',
// width: 100
// }
];
export default {

View File

@@ -78,15 +78,15 @@ export const auditHistoryColumns = [
dataIndex: 'workPaperIndex',
key: 'workPaperIndex',
align: 'center',
width: 140,
width: 200,
// ellipsis: true
},
{
title: '操作',
key: 'action',
align: 'center',
width: 100
}
// {
// title: '操作',
// key: 'action',
// align: 'center',
// width: 100
// }
];
export default {

View File

@@ -225,7 +225,7 @@ export const default1Columns = [
dataIndex: 'workPaperIndex',
key: 'workPaperIndex',
align: 'center',
width: 140,
width: 200,
ellipsis: true
},
{
@@ -305,7 +305,7 @@ export const leaderListColumns = [
dataIndex: 'workPaperIndex',
key: 'workPaperIndex',
align: 'center',
width: 180,
width: 200,
ellipsis: true
},
{
@@ -426,15 +426,15 @@ export const eightRegColumns = [
dataIndex: 'workPaperIndex',
key: 'workPaperIndex',
align: 'center',
width: 140,
width: 200,
ellipsis: true
},
{
title: '操作',
key: 'action',
align: 'center',
width: 140
}
// {
// title: '操作',
// key: 'action',
// align: 'center',
// width: 140
// }
];
export default {

View File

@@ -44,16 +44,16 @@ export const strategyAuditColumns = [
title: '工作底稿索引',
dataIndex: 'workPaperIndex',
key: 'workPaperIndex',
width: 120,
width: 200,
align: 'center',
// ellipsis: true
},
{
title: '操作',
key: 'action',
width: 100,
align: 'center'
}
// {
// title: '操作',
// key: 'action',
// width: 100,
// align: 'center'
// }
];
export default {

View File

@@ -38,6 +38,7 @@ export const tripleOneColumns = [
dataIndex: 'testResult',
key: 'testResult',
align: 'center',
width: 80,
customRender: createTestResultRender()
},
{
@@ -45,7 +46,7 @@ export const tripleOneColumns = [
dataIndex: 'workPaperIndex',
key: 'workPaperIndex',
align: 'center',
width: 140,
width: 200,
ellipsis: true
},
{
@@ -125,12 +126,12 @@ export const decisionTableColumns = [
}
]
},
{
title: '操作',
key: 'action',
align: 'center',
width: 140
}
// {
// title: '操作',
// key: 'action',
// align: 'center',
// width: 140
// }
];
export default {

View File

@@ -79,7 +79,7 @@ export const columns0 = [
dataIndex: 'workPaperIndex',
key: 'workPaperIndex',
align: 'center',
width: 180,
width: 200,
ellipsis: true
}
];

View File

@@ -94,7 +94,7 @@ export const budgetManageColumns = [
dataIndex: 'workPaperIndex',
key: 'workPaperIndex',
align: 'center',
width: 140,
width: 200,
ellipsis: true
},
{
@@ -161,15 +161,15 @@ export const budgetExecutionColumns = [
dataIndex: 'workPaperIndex',
key: 'workPaperIndex',
align: 'center',
width: 140,
width: 200,
ellipsis: true
},
{
title: '操作',
key: 'action',
align: 'center',
width: 100
}
// {
// title: '操作',
// key: 'action',
// align: 'center',
// width: 100
// }
];
export default {

View File

@@ -102,15 +102,15 @@ export const stateAssetsManageColumns = [
dataIndex: 'workPaperIndex',
key: 'workPaperIndex',
align: 'center',
width: 140,
width: 200,
ellipsis: true
},
{
title: '操作',
key: 'action',
align: 'center',
width: 100
}
// {
// title: '操作',
// key: 'action',
// align: 'center',
// width: 100
// }
];
export default {

View File

@@ -8,15 +8,6 @@ export const investmentSituationColumns = [
key: 'category',
width: 150,
align: 'center',
// filters: [
// { text: '重大对外投资审计', value: '重大对外投资审计' },
// { text: '重大工程建设审计', value: '重大工程建设审计' },
// { text: '重大资本运作审计', value: '重大资本运作审计' },
// { text: '重大资产处置审计', value: '重大资产处置审计' },
// { text: '重大物资(服务)采购审计', value: '重大物资(服务)采购审计' },
// { text: '重大担保借款审计', value: '重大担保借款审计' },
// ],
// onFilter: (value, record) => record.category === value,
},
{
title: '审计内容',
@@ -47,15 +38,15 @@ export const investmentSituationColumns = [
dataIndex: 'workPaperIndex',
key: 'workPaperIndex',
align: 'center',
width: 140,
width: 200,
// ellipsis: true
},
{
title: '操作',
key: 'action',
align: 'center',
width: 100
}
// {
// title: '操作',
// key: 'action',
// align: 'center',
// width: 100
// }
];
// 删除不再需要的单独列配置

View File

@@ -67,15 +67,15 @@ export const internalControlTestColumns = [
dataIndex: 'workPaperIndex',
key: 'workPaperIndex',
align: 'center',
width: 140,
width: 200,
// ellipsis: true
},
{
title: '操作',
key: 'action',
align: 'center',
width: 100
}
// {
// title: '操作',
// key: 'action',
// align: 'center',
// width: 100
// }
];
export default {

View File

@@ -40,14 +40,14 @@ export const personnelEstablishmentColumns = [
dataIndex: 'workPaperIndex',
key: 'workPaperIndex',
align: 'center',
width: 140,
width: 200,
},
{
title: '操作',
key: 'action',
align: 'center',
width: 100
}
// {
// title: '操作',
// key: 'action',
// align: 'center',
// width: 100
// }
];
export default {

View File

@@ -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;

View File

@@ -1,324 +1,482 @@
import table9ExtraColumns from './table9ExtraColumns';
export const tableConfigs = {
// 审计内容1表格配置
auditContent1: {
type: 'auditContent1',
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) }
],
// 接口映射
interfaceMap: {
default1: '/api/ai/auditContent1/generateDefault1Table',
leaderList: '/api/ai/auditContent1/generateLeaderListTable',
expense: '/api/ai/auditContent1/generateExpenseTable',
eightReg: '/api/ai/auditContent1/generateEightRegTable'
}
},
// 审计内容2表格配置
auditContent2: {
type: 'auditContent2',
title: '单位发展战略执行',
options: [
{ title: '单位发展战略执行', value: 'strategyAudit', columns: () => import('./table2Columns').then(m => m.strategyAuditColumns) }
],
interfaceMap: {
strategyAudit: '/api/ai/auditContent2/generateStrategyAuditTable'
}
},
// 审计内容3表格配置
auditContent3: {
type: 'auditContent3',
title: '重大经济决策调查',
options: [
{ 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',
decisionTable: '/api/ai/auditContent3/generateDecisionTable'
}
},
// 审计内容4表格配置
auditContent4: {
type: 'auditContent4',
title: '目标完成情况',
options: [
{ title: '目标责任完成情况表', value: 'target', columns: () => import('./table4Columns').then(m => m.columns0) }
],
interfaceMap: {
target: '/api/ai/auditContent4/generateTargetTable'
}
},
// 审计内容5表格配置
auditContent5: {
type: 'auditContent5',
title: '财务管理情况',
options: [
{ 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',
budgetExecution: '/api/ai/auditContent5/generateBudgetExecutionTable'
}
},
// 审计内容6表格配置
auditContent6: {
type: 'auditContent6',
title: '国资管理情况',
options: [
{ title: '国有资产管理审计', value: 'assets', columns: () => import('./table6Columns').then(m => m.stateAssetsManageColumns) }
],
interfaceMap: {
assets: '/api/ai/auditContent6/generateAssetsTable'
}
},
auditContent7: {
type: 'auditContent7',
title: '重大投资情况',
options: [
{ title: '重大投资情况审计', value: 'investmentSituation', columns: () => import('./table7Columns').then(m => m.investmentSituationColumns) },
],
interfaceMap: {
investmentSituation: '/api/ai/auditContent7/generateInvestmentSituationTable'
}
},
auditContent8: {
type: 'auditContent8',
title: '治理结构与内部控制',
options: [
{ title: '内部控制测试', value: 'internalControl', columns: () => import('./table8Columns').then(m => m.internalControlTestColumns) }
],
interfaceMap: {
internalControl: '/api/ai/auditContent8/generateInternalControlTable'
}
},
auditContent9: {
type: 'auditContent9',
title: '人员编制管理',
options: [
{ title: '人员编制管理审计', value: 'personnel', columns: () => import('./table9Columns').then(m => m.personnelEstablishmentColumns) }
],
interfaceMap: {
personnel: '/api/ai/auditContent9/generatePersonnelTable'
}
},
auditContent10: {
type: 'auditContent10',
title: '廉政情况',
options: [
{ title: '党风廉政建设责任制审计', value: 'partyConduct', columns: () => import('./table10Columns').then(m => m.partyConductColumns) }
],
interfaceMap: {
partyConduct: '/api/ai/auditContent10/generatePartyConductTable'
}
},
auditContent11: {
type: 'auditContent11',
title: '历史审计问题整改',
options: [
{ title: '历史审计问题整改', value: 'history', columns: () => import('./table11Columns').then(m => m.auditHistoryColumns) }
],
interfaceMap: {
history: '/api/ai/auditContent11/generateHistoryTable'
}
// 审计内容1表格配置
auditContent1: {
type: 'auditContent1',
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)
}
],
// 接口映射
interfaceMap: {
default1: '/api/ai/auditContent1/generateDefault1Table',
leaderList: '/api/ai/auditContent1/generateLeaderListTable',
expense: '/api/ai/auditContent1/generateExpenseTable',
eightReg: '/api/ai/auditContent1/generateEightRegTable'
}
},
// 审计内容2表格配置
auditContent2: {
type: 'auditContent2',
title: '单位发展战略执行',
options: [
{
title: '单位发展战略执行',
value: 'strategyAudit',
columns: () =>
import('./table2Columns').then((m) => m.strategyAuditColumns)
}
],
interfaceMap: {
strategyAudit: '/api/ai/auditContent2/generateStrategyAuditTable'
}
},
// 审计内容3表格配置
auditContent3: {
type: 'auditContent3',
title: '重大经济决策调查',
options: [
{
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',
decisionTable: '/api/ai/auditContent3/generateDecisionTable'
}
},
// 审计内容4表格配置
auditContent4: {
type: 'auditContent4',
title: '目标完成情况',
options: [
{
title: '目标责任完成情况表',
value: 'target',
columns: () => import('./table4Columns').then((m) => m.columns0)
}
],
interfaceMap: {
target: '/api/ai/auditContent4/generateTargetTable'
}
},
// 审计内容5表格配置
auditContent5: {
type: 'auditContent5',
title: '财务管理情况',
options: [
{
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',
budgetExecution: '/api/ai/auditContent5/generateBudgetExecutionTable'
}
},
// 审计内容6表格配置
auditContent6: {
type: 'auditContent6',
title: '国资管理情况',
options: [
{
title: '国有资产管理审计',
value: 'assets',
columns: () =>
import('./table6Columns').then((m) => m.stateAssetsManageColumns)
}
],
interfaceMap: {
assets: '/api/ai/auditContent6/generateAssetsTable'
}
},
auditContent7: {
type: 'auditContent7',
title: '重大投资情况',
options: [
{
title: '重大投资情况审计',
value: 'investmentSituation',
columns: () =>
import('./table7Columns').then((m) => m.investmentSituationColumns)
}
],
interfaceMap: {
investmentSituation:
'/api/ai/auditContent7/generateInvestmentSituationTable'
}
},
auditContent8: {
type: 'auditContent8',
title: '治理结构与内部控制',
options: [
{
title: '内部控制测试',
value: 'internalControl',
columns: () =>
import('./table8Columns').then((m) => m.internalControlTestColumns)
}
],
interfaceMap: {
internalControl: '/api/ai/auditContent8/generateInternalControlTable'
}
},
auditContent9: {
type: 'auditContent9',
title: '人员编制管理',
options: [
{
title: '人员编制管理审计',
value: 'personnel',
columns: () =>
import('./table9Columns').then((m) => m.personnelEstablishmentColumns)
}
],
extraTableTitle: '福利费超范围支出明细清单',
extraColumns: table9ExtraColumns,
interfaceMap: {
personnel: '/api/ai/auditContent9/generatePersonnelTable'
}
},
auditContent10: {
type: 'auditContent10',
title: '廉政情况',
options: [
{
title: '党风廉政建设责任制审计',
value: 'partyConduct',
columns: () =>
import('./table10Columns').then((m) => m.partyConductColumns)
}
],
interfaceMap: {
partyConduct: '/api/ai/auditContent10/generatePartyConductTable'
}
},
auditContent11: {
type: 'auditContent11',
title: '历史审计问题整改',
options: [
{
title: '历史审计问题整改',
value: 'history',
columns: () =>
import('./table11Columns').then((m) => m.auditHistoryColumns)
}
],
interfaceMap: {
history: '/api/ai/auditContent11/generateHistoryTable'
}
}
};
// 获取表格配置
export function getTableConfig(sectionIndex: number) {
const configKeys = Object.keys(tableConfigs);
if (sectionIndex >= 0 && sectionIndex < configKeys.length) {
return tableConfigs[configKeys[sectionIndex]];
}
return null;
const configKeys = Object.keys(tableConfigs);
if (sectionIndex >= 0 && sectionIndex < configKeys.length) {
return tableConfigs[configKeys[sectionIndex]];
}
return null;
}
// 获取所有表格配置
export function getAllTableConfigs() {
return tableConfigs;
return tableConfigs;
}
// 通过接口名称查找表格配置
export function findTableConfigByInterface(interfaceName: string) {
for (const [key, config] of Object.entries(tableConfigs)) {
for (const [tableValue, tableInterface] of Object.entries(config.interfaceMap || {})) {
if (tableInterface === interfaceName) {
return {
sectionType: key,
tableValue,
config
};
}
}
for (const [key, config] of Object.entries(tableConfigs)) {
for (const [tableValue, tableInterface] of Object.entries(
config.interfaceMap || {}
)) {
if (tableInterface === interfaceName) {
return {
sectionType: key,
tableValue,
config
};
}
}
return null;
}
return null;
}
// 解析workPaperIndex字符串为对象数组
function parseWorkPaperIndex(workPaperIndex) {
if (!workPaperIndex || !Array.isArray(workPaperIndex)) return [];
if (!workPaperIndex || !Array.isArray(workPaperIndex)) return [];
return workPaperIndex.map(item => {
if (typeof item === 'string') {
const parts = item.split('||');
if (parts.length >= 3) {
return {
fileId: parts[0] || '',
fileName: parts[1] || '',
fileUrl: parts[2] || ''
};
}
}
// 兼容旧格式
return workPaperIndex.map((item) => {
if (item && typeof item === 'object') {
return {
fileId: item.fileId || item.file_id || '',
fileName: item.fileName || item.file_name || '',
fileUrl: item.fileUrl || item.url || ''
};
}
if (typeof item === 'string') {
const parts = item.split('||');
if (parts.length >= 3) {
return {
fileId: '',
fileName: typeof item === 'string' ? item : '',
fileUrl: ''
fileId: parts[0] || '',
fileName: parts[1] || '',
fileUrl: parts[2] || ''
};
});
}
}
// 兼容旧格式
return {
fileId: '',
fileName: typeof item === 'string' ? item : '',
fileUrl: ''
};
});
}
// 通用数据映射函数
export function createDataMapper(type: string) {
const mappers = {
default1: (data) => data.map((item, index) => ({
key: index,
index: index + 1,
...item,
workPaperIndex: parseWorkPaperIndex(item.workPaperIndex)
})),
leaderList: (data) => data.map((item, index) => ({
key: index,
...item,
workPaperIndex: parseWorkPaperIndex(item.workPaperIndex)
})),
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) => ({
key: index,
...item,
workPaperIndex: parseWorkPaperIndex(item.workPaperIndex)
})),
strategyAudit: (data) => data.map((item, index) => ({
key: index,
index: index + 1,
...item,
workPaperIndex: parseWorkPaperIndex(item.workPaperIndex)
})),
tripleOne: (data) => data.map((item, index) => ({
key: index,
...item,
workPaperIndex: parseWorkPaperIndex(item.workPaperIndex)
})),
decisionTable: (data) => data.map((item, index) => ({
key: index,
index: index + 1,
goods: item.executionEffect?.good || item.goods || '否',
normal: item.executionEffect?.normal || item.normal || '否',
bad: item.executionEffect?.bad || item.bad || '否',
...item,
workPaperIndex: parseWorkPaperIndex(item.workPaperIndex)
})),
budgetManage: (data) => data.map((item, index) => ({
key: index,
index: index + 1,
budgetSubject: item.budgetSubject || '-',
// 指标来源部分字段映射
indicatorSource: item.indicatorSource, // 指标来源
total: formatAmount(item.indicatorSourceTotal), // 指标来源-合计
lastYearBalance: formatAmount(item.indicatorSourceLastYearBalance), // 指标来源-上年结余
initialBudget: formatAmount(item.indicatorSourceInitialBudget), // 指标来源-年初部门预算
additionalBudget: formatAmount(item.indicatorSourceAdditionalBudget), // 指标来源-追加(减)预算
// 指标运用部分字段映射
indicatorUseTotal: formatAmount(item.indicatorUseTotal), // 指标运用-合计
appropriationSubtotal: formatAmount(item.indicatorUseAppropriationSubtotal), // 指标运用-拨款小计
appropriation: formatAmount(item.indicatorUseAppropriation), // 指标运用-拨款
salaryPayment: formatAmount(item.indicatorUseSalaryPayment), // 指标运用-工资统发
govProcurement: formatAmount(item.indicatorUseGovProcurement), // 指标运用-政府采购
// 其他字段
indicatorBalance: formatAmount(item.indicatorBalance), // 指标结余
workPaperIndex: parseWorkPaperIndex(item.workPaperIndex), // 工作底稿索引
})),
investmentSituation: (data) => data.map((item, index) => ({
key: index,
index: index + 1,
category: item.category || '未分类',
auditContent: item.auditContent || item.content || '',
checkEvidence: item.checkEvidence || item.evidence || '',
testResult: item.testResult || '待检查',
workPaperIndex: parseWorkPaperIndex(item.workPaperIndex),
...item
})),
// 其他类型的映射...
default: (data) => data.map((item, index) => ({
key: index,
index: index + 1,
...item,
workPaperIndex: parseWorkPaperIndex(item.workPaperIndex)
const mappers = {
default1: (data) =>
data.map((item, index) => ({
key: index,
index: index + 1,
...item,
workPaperIndex: parseWorkPaperIndex(item.workPaperIndex)
})),
leaderList: (data) =>
data.map((item, index) => ({
key: index,
...item,
workPaperIndex: parseWorkPaperIndex(item.workPaperIndex)
})),
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) => ({
key: index,
...item,
workPaperIndex: parseWorkPaperIndex(item.workPaperIndex)
})),
strategyAudit: (data) =>
data.map((item, index) => ({
key: index,
index: index + 1,
...item,
workPaperIndex: parseWorkPaperIndex(item.workPaperIndex)
})),
tripleOne: (data) =>
data.map((item, index) => ({
key: index,
...item,
workPaperIndex: parseWorkPaperIndex(item.workPaperIndex)
})),
decisionTable: (data) =>
data.map((item, index) => ({
key: index,
index: index + 1,
goods: item.executionEffect?.good || item.goods || '否',
normal: item.executionEffect?.normal || item.normal || '否',
bad: item.executionEffect?.bad || item.bad || '',
...item,
workPaperIndex: parseWorkPaperIndex(item.workPaperIndex)
})),
budgetManage: (data) =>
data.map((item, index) => ({
key: index,
index: index + 1,
...item,
budgetSubject: item.budgetSubject || '-',
indicatorSource: item.indicatorSource,
total: formatAmount(item.indicatorSourceTotal),
lastYearBalance: formatAmount(item.indicatorSourceLastYearBalance),
initialBudget: formatAmount(item.indicatorSourceInitialBudget),
additionalBudget: formatAmount(item.indicatorSourceAdditionalBudget),
indicatorUseTotal: formatAmount(item.indicatorUseTotal),
appropriationSubtotal: formatAmount(
item.indicatorUseAppropriationSubtotal
),
appropriation: formatAmount(item.indicatorUseAppropriation),
salaryPayment: formatAmount(item.indicatorUseSalaryPayment),
govProcurement: formatAmount(item.indicatorUseGovProcurement),
indicatorBalance: formatAmount(item.indicatorBalance),
workPaperIndex: parseWorkPaperIndex(item.workPaperIndex)
})),
investmentSituation: (data) =>
data.map((item, index) => ({
key: index,
index: index + 1,
category: item.category || '未分类',
auditContent: item.auditContent || item.content || '',
checkEvidence: item.checkEvidence || item.evidence || '',
testResult: item.testResult || '待检查',
...item,
workPaperIndex: parseWorkPaperIndex(item.workPaperIndex)
})),
personnel: (data) => {
const mainData = data.map((item, index) => {
const { ext, ...rest } = item;
return {
key: index,
index: item.index || index + 1,
...rest,
workPaperIndex: parseWorkPaperIndex(item.workPaperIndex)
};
});
const extraData = data.reduce((acc, item) => {
if (item.ext && Array.isArray(item.ext)) {
return [...acc, ...item.ext];
}
return acc;
}, []);
return {
mainData: mainData,
extraData: extraData.map((item, idx) => ({
key: idx,
...item,
index: item.index || idx + 1
}))
};
};
},
// 其他类型的映射...
default: (data) =>
data.map((item, index) => ({
key: index,
index: index + 1,
...item,
workPaperIndex: parseWorkPaperIndex(item.workPaperIndex)
}))
};
return mappers[type] || mappers.default;
return mappers[type] || mappers.default;
}
// 格式化金额
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', {
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', {
minimumFractionDigits: 2,
maximumFractionDigits: 2
});
});
}
// 生成接口映射
export const apiMethodMap = {
// 审计内容1
default1: { generate: 'generateDefault1Table', export: 'exportDefault1Table' },
leaderList: { generate: 'generateLeaderListTable', export: 'exportLeaderListTable' },
expense: { generate: 'generateExpenseTable', export: 'exportExpenseTable' },
eightReg: { generate: 'generateEightRegTable', export: 'exportEightRegTable' },
// 审计内容2
strategyAudit: { generate: 'generateStrategyAuditTable', export: 'exportStrategyAuditTable' },
// 审计内容3
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' },
// 审计内容6
assets: { generate: 'generateAssetsTable', export: 'exportAssetsTable' },
// 审计内容7
investmentSituation: { generate: 'generateInvestmentSituationTable', export: 'exportInvestmentSituationTable' },
// 审计内容8
internalControl: { generate: 'generateInternalControlTable', export: 'exportInternalControlTable' },
// 审计内容9
personnel: { generate: 'generatePersonnelTable', export: 'exportPersonnelTable' },
// 审计内容10
partyConduct: { generate: 'generatePartyConductTable', export: 'exportPartyConductTable' },
// 审计内容11
history: { generate: 'generateHistoryTable', export: 'exportHistoryTable' },
// 默认
default: { generate: 'generateDefaultTable', export: 'exportDefaultTable' }
// 审计内容1
default1: {
generate: 'generateDefault1Table',
export: 'exportDefault1Table'
},
leaderList: {
generate: 'generateLeaderListTable',
export: 'exportLeaderListTable'
},
expense: { generate: 'generateExpenseTable', export: 'exportExpenseTable' },
eightReg: {
generate: 'generateEightRegTable',
export: 'exportEightRegTable'
},
// 审计内容2
strategyAudit: {
generate: 'generateStrategyAuditTable',
export: 'exportStrategyAuditTable'
},
// 审计内容3
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'
},
// 审计内容6
assets: { generate: 'generateAssetsTable', export: 'exportAssetsTable' },
// 审计内容7
investmentSituation: {
generate: 'generateInvestmentSituationTable',
export: 'exportInvestmentSituationTable'
},
// 审计内容8
internalControl: {
generate: 'generateInternalControlTable',
export: 'exportInternalControlTable'
},
// 审计内容9
personnel: {
generate: 'generatePersonnelTable',
export: 'exportPersonnelTable'
},
// 审计内容10
partyConduct: {
generate: 'generatePartyConductTable',
export: 'exportPartyConductTable'
},
// 审计内容11
history: { generate: 'generateHistoryTable', export: 'exportHistoryTable' },
// 默认
default: { generate: 'generateDefaultTable', export: 'exportDefaultTable' }
};
export default {
tableConfigs,
getTableConfig,
getAllTableConfigs,
findTableConfigByInterface,
createDataMapper,
apiMethodMap
tableConfigs,
getTableConfig,
getAllTableConfigs,
findTableConfigByInterface,
createDataMapper,
apiMethodMap
};

View File

@@ -49,6 +49,14 @@
v-model:value="form.code"
/>
</a-form-item>
<a-form-item label="案引号" name="caseIndex">
<a-input
allow-clear
style="width: 400px"
placeholder="请输入项目名称"
v-model:value="form.caseIndex"
/>
</a-form-item>
<!-- 行业库 -->
<a-form-item label="行业库" name="bizLibIds">
@@ -355,6 +363,7 @@ const form = reactive<PwlProject>({
id: undefined,
name: undefined,
code: undefined,
caseIndex: undefined,
parentId: undefined,
type: undefined,
image: undefined,

File diff suppressed because it is too large Load Diff

View File

@@ -383,6 +383,14 @@
sorter: true,
align: 'center'
},
{
title: '案引号',
dataIndex: 'caseIndex',
key: 'caseIndex',
width: 240,
sorter: true,
align: 'center'
},
{
title: '项目完成进度',
dataIndex: 'status',