Files
jzsj-vue/src/views/pwl/pwlProject/index.vue

736 lines
19 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<a-page-header :title="getPageTitle()" @back="() => $router.go(-1)">
<template #subTitle>
<div style="width: 300px;margin-left: 100px">
<a-steps :current="1" size="small">
<a-step title="单位信息" status="wait" />
<a-step title="项目管理" />
</a-steps>
</div>
</template>
<template #extra>
<Extra />
</template>
<a-card :bordered="false" :body-style="{ padding: '16px' }">
<ele-pro-table
ref="tableRef"
row-key="id"
:columns="columns"
:datasource="datasource"
:customRow="customRow"
:scroll="{ x: 4000 }"
tool-class="ele-toolbar-form"
class="sys-org-table"
bordered
>
<template #toolbar>
<search
@search="reload"
:selection="selection"
@add="openEdit"
@remove="removeBatch"
@batchMove="openMove"
/>
</template>
<template #bodyCell="{ column, record }">
<template v-if="column.key === 'image'">
<a-image v-if="record.image" :src="record.image" :width="50" />
</template>
<template v-if="column.key === 'status'">
<a-tag v-if="record.status === 0" color="green">已完成</a-tag>
<a-tag v-if="record.status === 1" color="red">未完成</a-tag>
</template>
<template v-if="column.key === 'draftUser'">
<a-space direction="vertical" v-if="record.draftUser">
<a-tag
v-for="(item, index) in JSON.parse(record.draftUser)"
:key="index"
>{{ item }}</a-tag
>
</a-space>
</template>
<template v-if="column.key === 'users'">
<a-space direction="vertical" v-if="record.users">
<a-tag
v-for="(item, index) in JSON.parse(record.users)"
:key="index"
>{{ item }}</a-tag
>
</a-space>
</template>
<template v-if="column.key === 'signUser'">
<a-space direction="vertical" v-if="record.signUser">
<a-tag
v-for="(item, index) in JSON.parse(record.signUser)"
:key="index"
>{{ item }}</a-tag
>
</a-space>
</template>
<template v-if="column.key === 'saleUser'">
<a-space direction="vertical" v-if="record.saleUser">
<a-tag
v-for="(item, index) in JSON.parse(record.saleUser)"
:key="index"
>{{ item }}</a-tag
>
</a-space>
</template>
<template v-if="column.key === 'electron'">
<span>电子</span>
<a-tag v-if="record.electron === 0" color="green">已完成</a-tag>
<a-tag v-else color="red">未完成</a-tag>
<span>纸质</span>
<a-tag v-if="record.paper === 0" color="green">已完成</a-tag>
<a-tag v-else color="red">未完成</a-tag>
</template>
<template v-if="column.key === 'createTime'">
<a-tooltip
:title="`创建于:${record.createTime}`"
class="flex flex-col"
>
<a-space>
<span>{{ toDateString(record.createTime, 'YYYY-MM-dd') }}</span>
<a-avatar :src="record.avatar" size="small" />
</a-space>
</a-tooltip>
</template>
<template v-if="column.key === 'action'">
<div>
<a-space>
<a class="action-btn bg-blue-500" @click="openReport(record)"
>1 生成审计方案</a
>
<a class="action-btn bg-green-600" @click="openReportContent(record)">2 审计内容</a>
<a class="action-btn bg-red-600" @click="openReportView(record)"
>3 审计报告</a
>
</a-space>
</div>
<div class="mt-2">
<a-space>
<a class="edit-btn" @click="openEdit(record)">修改</a>
<a-popconfirm
title="确定要删除此记录吗?"
@confirm="remove(record)"
>
<a class="remove-btn">删除</a>
</a-popconfirm>
</a-space>
</div>
</template>
</template>
</ele-pro-table>
</a-card>
<!-- 编辑弹窗 -->
<Edit v-model:visible="showEdit" :data="current" @done="reload" />
<!-- 生成报告 -->
<Report v-model:visible="showReport" :data="current" @done="reload" />
<ReportContent v-model:visible="showReportContent" :data="current" @done="reload" />
<!-- 审计报告查看 -->
<ReportView v-model:visible="showReportView" :data="current" @done="reload" />
<!-- 审计核查弹窗 -->
<AuditCheck
v-model:visible="showAuditCheck"
:data="current"
@done="reload"
/>
<!-- 添加文档管理弹窗 -->
<a-modal
v-model:visible="showDocManage"
:title="`文档管理 - ${currentDocType} - ${current?.name || ''}`"
width="800px"
:footer="null"
>
<div style="margin-bottom: 16px">
<a-button type="primary" @click="openImport">新增文档</a-button>
</div>
<a-table
:dataSource="docList"
:columns="docColumns"
:loading="docLoading"
rowKey="id"
:pagination="{
current: currentPage,
pageSize: 10,
total: total,
showSizeChanger: false,
showTotal: (total) => `共 ${total} 条`
}"
@change="
(pag) => {
currentPage = pag.current;
loadDocuments();
}
"
>
<template #bodyCell="{ column, record }">
<template v-if="column.key === 'action'">
<a-space>
<a-popconfirm
title="确定要删除此文档吗?"
@confirm="deleteDoc(record)"
>
<a class="ele-text-danger">删除</a>
</a-popconfirm>
</a-space>
</template>
</template>
</a-table>
</a-modal>
<!-- 导入弹窗 -->
<Import
v-model:visible="showImport"
@done="loadDocuments"
:kbId="currentKbId"
/>
</a-page-header>
</template>
<script lang="ts" setup>
import { createVNode, ref } from 'vue';
import { message, Modal } from 'ant-design-vue';
import { ExclamationCircleOutlined } from '@ant-design/icons-vue';
import type { EleProTable } from 'ele-admin-pro';
import { toDateString } from 'ele-admin-pro';
import type {
DatasourceFunction,
ColumnItem
} from 'ele-admin-pro/es/ele-pro-table/types';
import Search from './components/search.vue';
import Edit from './components/pwlProjectEdit.vue';
import Report from './components/report.vue';
import ReportContent from './components/reportContent.vue';
import ReportView from './components/reportView.vue';
import AuditCheck from './components/auditCheck.vue';
import {
pagePwlProject,
removePwlProject,
removeBatchPwlProject
} from '@/api/pwl/pwlProject';
import type { PwlProject, PwlProjectParam } from '@/api/pwl/pwlProject/model';
import { getPageTitle } from '@/utils/common';
import Extra from './components/extra.vue';
import Import from '@/views/oa/oaCompany/components/Import.vue';
import {
getKnowledgeBaseDocuments,
deleteKnowledgeBaseDocument
} from '@/api/ai/knowledgeBase';
// 表格实例
const tableRef = ref<InstanceType<typeof EleProTable> | null>(null);
// 表格选中数据
const selection = ref<PwlProject[]>([]);
// 当前编辑数据
const current = ref<PwlProject | null>(null);
// 是否显示编辑弹窗
const showEdit = ref(false);
// 是否显示报告弹窗
const showReport = ref(false);
// 是否显示审计内容弹窗
const showReportContent = ref(false);
// 是否显示审计报告查看弹窗
const showReportView = ref(false);
// 是否显示审计核查弹窗
const showAuditCheck = ref(false);
// 是否显示批量移动弹窗
const showMove = ref(false);
// const draftUser = ref<string[]>([]);
// const users = ref<string[]>([]);
// const signUser = ref<string[]>([]);
// const saleUser = ref<string[]>([]);
// 加载状态
const loading = ref(true);
// 文档管理相关响应式变量
const showDocManage = ref(false); // 是否显示文档管理弹窗
const showImport = ref(false); // 是否显示导入弹窗
const currentKbId = ref(''); // 当前知识库ID
const currentDocType = ref(''); // 当前文档类型(材料分析/项目文档)
const docList = ref<any[]>([]); // 文档列表数据
const docLoading = ref(false); // 文档加载状态
const currentPage = ref(1);
const total = ref(0);
// 文档表格列配置
const docColumns = ref([
{
title: '文件名',
dataIndex: 'name',
key: 'fileName'
},
{
title: '文件大小',
dataIndex: 'size',
key: 'fileSize'
},
{
title: '上传时间',
dataIndex: 'gmtModified',
key: 'createTime',
customRender: ({ text }) => toDateString(text)
},
{
title: '操作',
key: 'action',
width: 100
}
]);
// 打开审计报告查看弹窗
const openReportView = (record: PwlProject) => {
current.value = record;
showReportView.value = true;
};
// 打开审计核查弹窗
const openAuditCheck = (record: PwlProject) => {
current.value = record;
showAuditCheck.value = true;
};
// 打开材料分析
const openCaseManagement = (record: PwlProject) => {
if (!record.analysisLibrary) {
message.warning('当前记录没有关联材料分析知识库');
return;
}
currentKbId.value = record.analysisLibrary;
currentDocType.value = '材料分析';
currentPage.value = 1;
showDocManage.value = true;
loadDocuments();
};
// 打开项目文档
const openDocumentManagement = (record: PwlProject) => {
if (!record.projectLibrary) {
message.warning('当前记录没有关联项目文档知识库');
return;
}
currentKbId.value = record.projectLibrary;
currentDocType.value = '项目文档';
currentPage.value = 1;
showDocManage.value = true;
loadDocuments();
};
// 加载文档列表
const loadDocuments = async () => {
docLoading.value = true;
try {
const response = await getKnowledgeBaseDocuments(
currentKbId.value,
10,
currentPage.value
);
docList.value = Array.isArray(response?.list) ? response.list : [];
total.value = response?.count || 0;
} catch (error) {
message.error('加载文档列表失败');
console.error('加载文档错误:', error);
} finally {
docLoading.value = false;
}
};
// 删除文档
const deleteDoc = async (record: any) => {
try {
await deleteKnowledgeBaseDocument(currentKbId.value, record.id);
// 立即本地删除
const index = docList.value.findIndex((item) => item.id === record.id);
if (index > -1) {
docList.value.splice(index, 1);
total.value -= 1;
}
message.success('删除成功');
} catch (error) {
message.error('删除失败');
console.error(error);
}
};
// 打开导入弹窗
const openImport = () => {
showImport.value = true;
};
// 表格数据源
const datasource: DatasourceFunction = ({ page, limit, where, orders }) => {
return pagePwlProject({
...where,
...orders,
page,
limit
});
};
// 表格列配置
const columns = ref<ColumnItem[]>([
{
title: '序号',
key: 'index',
width: 48,
fixed: 'left',
align: 'center',
customRender: ({ index }) => index + (tableRef.value?.tableIndex ?? 0)
},
{
title: '被审计单位',
dataIndex: 'name',
key: 'name',
width: 240,
fixed: 'left',
align: 'center'
},
{
title: '项目名称',
dataIndex: 'code',
key: 'code',
width: 240,
sorter: true,
align: 'center'
},
{
title: '案引号',
dataIndex: 'caseIndex',
key: 'caseIndex',
width: 240,
sorter: true,
align: 'center'
},
{
title: '项目完成进度',
dataIndex: 'status',
key: 'status',
width: 120,
align: 'center'
},
{
title: '报告时间',
dataIndex: 'expirationTime',
key: 'expirationTime',
align: 'center',
width: 120
},
// {
// title: '类型',
// dataIndex: 'type',
// key: 'type',
// align: 'center',
// customRender: ({text}) => ['审字', '专审', '验证', '咨询'][text]
// },
{
title: '项目信息',
dataIndex: 'itemName',
key: 'itemName',
align: 'center',
children: [
{
title: '开票单位/汇款人',
dataIndex: 'itemName',
key: 'itemName',
align: 'center',
width: 180
},
{
title: '所属年度',
dataIndex: 'itemYear',
key: 'itemYear',
align: 'center'
},
{
title: '类型',
dataIndex: 'itemType',
key: 'itemType',
align: 'center'
},
{
title: '审计意见',
dataIndex: 'itemOpinion',
key: 'itemOpinion',
align: 'center'
}
]
},
{
title: '年末资产总额(万元)',
dataIndex: 'totalAssets',
key: 'totalAssets',
align: 'center',
width: 170
},
{
title: '合同金额',
dataIndex: 'contractPrice',
key: 'contractPrice',
align: 'center'
},
{
title: '实收金额',
dataIndex: 'payPrice',
key: 'payPrice',
align: 'center',
width: 120
},
{
title: '到账信息',
dataIndex: 'itemName',
key: 'itemName',
align: 'center',
children: [
{
title: '银行',
dataIndex: 'bankName',
key: 'bankName',
align: 'center',
width: 120
},
{
title: '日期',
dataIndex: 'bankPayTime',
key: 'bankPayTime',
align: 'center',
width: 120
},
{
title: '金额',
dataIndex: 'bankPrice',
key: 'bankPrice',
align: 'center',
width: 120
}
]
},
{
title: '开票信息',
dataIndex: 'invoice',
key: 'invoice',
align: 'center',
children: [
{
title: '日期',
dataIndex: 'invoiceTime',
key: 'invoiceTime',
align: 'center',
width: 120
},
{
title: '金额',
dataIndex: 'invoicePrice',
key: 'invoicePrice',
align: 'center',
width: 120
},
{
title: '发票类型',
dataIndex: 'invoiceType',
key: 'invoiceType',
align: 'center',
width: 120
}
]
},
{
title: '报告份数',
dataIndex: 'reportNum',
key: 'reportNum',
align: 'center',
width: 90
},
{
title: '底稿人员',
dataIndex: 'draftUser',
key: 'draftUser',
align: 'center',
width: 90
},
{
title: '参与成员',
dataIndex: 'users',
key: 'users',
align: 'center',
width: 180
},
{
title: '签字注会',
dataIndex: 'signUser',
key: 'signUser',
align: 'center',
width: 90
},
{
title: '展业人员',
dataIndex: 'saleUser',
key: 'saleUser',
align: 'center',
width: 90
},
{
title: '底稿完成情况',
dataIndex: 'electron',
key: 'electron',
align: 'center',
width: 120
},
{
title: '备注',
dataIndex: 'comments',
key: 'comments',
align: 'center',
width: 180
},
{
title: '创建时间',
dataIndex: 'createTime',
key: 'createTime',
align: 'center',
sorter: true,
width: 180,
ellipsis: true,
customRender: ({ text }) => toDateString(text, 'yyyy-MM-dd HH:mm')
},
{
title: '操作',
key: 'action',
width: 260,
fixed: 'right',
align: 'center',
hideInSetting: true
}
]);
/* 搜索 */
const reload = (where?: PwlProjectParam) => {
selection.value = [];
tableRef?.value?.reload({ where: where });
};
/* 打开编辑弹窗 */
const openEdit = (row?: PwlProject) => {
current.value = row ?? null;
showEdit.value = true;
};
const openReport = (row?: PwlProject) => {
current.value = row ?? null;
showReport.value = true;
};
const openReportContent = (row?: PwlProject) => {
current.value = row ?? null;
showReportContent.value = true;
};
/* 打开批量移动弹窗 */
const openMove = () => {
showMove.value = true;
};
/* 删除单个 */
const remove = (row: PwlProject) => {
const hide = message.loading('请求中..', 0);
removePwlProject(row.id)
.then((msg) => {
hide();
message.success(msg);
reload();
})
.catch((e) => {
hide();
message.error(e.message);
});
};
/* 批量删除 */
const removeBatch = () => {
if (!selection.value.length) {
message.error('请至少选择一条数据');
return;
}
Modal.confirm({
title: '提示',
content: '确定要删除选中的记录吗?',
icon: createVNode(ExclamationCircleOutlined),
maskClosable: true,
onOk: () => {
const hide = message.loading('请求中..', 0);
removeBatchPwlProject(selection.value.map((d) => d.id))
.then((msg) => {
hide();
message.success(msg);
reload();
})
.catch((e) => {
hide();
message.error(e.message);
});
}
});
};
/* 查询 */
const query = () => {
loading.value = true;
};
/* 自定义行属性 */
const customRow = (record: PwlProject) => {
return {
// 行点击事件
onClick: () => {
// console.log(record);
},
// 行双击事件
onDblclick: () => {
openEdit(record);
}
};
};
query();
</script>
<script lang="ts">
export default {
name: 'PwlProject'
};
</script>
<style lang="less" scoped>
.action-btn {
border-radius: 3px;
padding: 3px;
color: white;
font-size: 12px;
}
.edit-btn {
border-radius: 3px;
padding: 3px 10px;
color: #3B82F6;
border: 1px solid #3B82F6;
font-size: 12px;
}
.remove-btn {
border-radius: 3px;
padding: 3px 10px;
color: red;
border: 1px solid red;
font-size: 12px;
}
</style>
<style scoped>
/* 修改已完成步骤的连接线颜色 */
.ant-steps-item-wait > .ant-steps-item-container > .ant-steps-item-tail::after {
background-color: red !important;
}
</style>