csi-financial-front/src/views/pages/index/common/index.vue

794 lines
25 KiB
Vue
Raw Normal View History

2026-03-23 15:21:53 +08:00
<template>
<div class="container">
<div class="w1400">
<div class="mt20">
<el-breadcrumb separator="/" class="font16">
<el-breadcrumb-item :to="{ path: '/home' }">首页</el-breadcrumb-item>
<el-breadcrumb-item>智能检校</el-breadcrumb-item>
</el-breadcrumb>
</div>
2026-03-23 15:21:53 +08:00
<!-- 时间滑动 start -->
<Slide v-if="historyData.length > 0" :data="historyData" @doDetail="goDetail" />
<!-- 时间滑动 end -->
<div class="main">
<el-form class="el_form" style="width: 100%; display: flex; justify-content: space-between" @submit.native.prevent>
<div style="display: flex">
<el-form-item label="" class="el_form_item" style="width: 224px">
<el-input v-model="queryFrom.title" placeholder="请输入标题" @change="handleChangeFilter">
<template #suffix>
<img :src="iconSearch" class="input_icon" @click="handleChangeFilter" />
</template>
</el-input>
</el-form-item>
<el-form-item label="" class="el_form_item" style="margin-left: 10px; width: 91px" v-if="userType !== 2">
<ZButton btn-width="100%" @btnClick="restFrom(true)" btnType="rest" :btnDisabled="!queryFrom.title && !queryFrom.status">
<div class="btn_content">
<text style="color: #19213d">重置条件</text>
</div>
</ZButton>
</el-form-item>
</div>
<ZButton btn-width="111px" @btnClick="showUploadDialog" v-if="userType != 2">
<div class="btn_content">
<img :src="iconFile" />
<text>公告上传</text>
</div>
</ZButton>
</el-form>
<el-tabs v-model="fileType" class="demo-tabs" @tab-click="handleTabClick">
<el-tab-pane label="单文件检校" :name="0"></el-tab-pane>
<el-tab-pane label="跨文件检校(公测)" :name="1" v-if="Session.get('userData')?.kuaSwitch == 1"></el-tab-pane>
</el-tabs>
<!-- 单文件检校 start -->
<div v-if="fileType == 0">
<table-components
:tableLoading="tableLoading"
:tableData="tableData"
:defaultCurrentPage="defaultCurrentPage"
@currentChange="currentChange"
@sizeChange="sizeChange"
size="mini"
>
<el-table-column prop="fileName" label="标题" align="left" />
<el-table-column prop="year" label="年份" align="left" />
<el-table-column label="类型" align="left">
<template v-slot="scope">
<div>
{{ reportType[scope.row.reportType] }}
</div>
</template>
</el-table-column>
<el-table-column prop="createTime" label="上传时间" align="left" sortable />
<el-table-column prop="status" label="" align="left" width="380">
<template #header>
<el-dropdown trigger="click" @command="handleCommand">
<div class="el-dropdown-link">
<span>校验状态</span>
<el-icon class="el-icon--right">
<Filter />
</el-icon>
</div>
<template #dropdown>
<el-dropdown-menu>
<el-dropdown-item :command="null">全部</el-dropdown-item>
<el-dropdown-item :command="0">分析中</el-dropdown-item>
<!-- <el-dropdown-item :command="1">未检校</el-dropdown-item> -->
<!-- <el-dropdown-item :command="2">校验异常</el-dropdown-item> -->
<el-dropdown-item :command="3">校验通过</el-dropdown-item>
<el-dropdown-item :command="4">分析失败</el-dropdown-item>
<el-dropdown-item :command="-9">待确认</el-dropdown-item>
</el-dropdown-menu>
</template>
</el-dropdown>
</template>
<template v-slot="scope">
<div v-if="scope.row.reportType == 5">
<ListStatus :item="scope.row"></ListStatus>
</div>
<div v-else>
<!-- -1-排队中0-分析中1-检校异常2-校验中3-已通过4-分析失败5-财保文件解析中6-数据指标抽取中 -->
<div
class="r_point"
v-if="
(scope.row.status == 0 ||
scope.row.status == 1 ||
scope.row.status == 5 ||
scope.row.status == 6 ||
scope.row.modelCheckTextStatus == 0 ||
scope.row.modelCheckTextStatus == -1) &&
scope.row.status != -1 &&
scope.row.status != -3
"
>
<div class="point" style="background-color: #ffb100"></div>
<text style="color: #ffb100; white-space: nowrap">分析中</text>
<text style="color: #b0b3be; margin-left: 5px; white-space: nowrap">{{ scope.row.process }}</text>
<text style="color: #b0b3be; margin-left: 5px" v-if="scope.row.process && scope.row.process.length > 0">...</text>
</div>
<div class="r_point" v-if="scope.row.status == -1 || scope.row.status == -3">
<div class="point" style="background-color: #ffaa48"></div>
<text style="color: #ffaa48">等待中</text>
</div>
<!-- <div class="r_point" v-if="scope.row.status == 1">
<div class="point" style="background-color: #ffb100"></div>
<text style="color: #ffb100">分析中</text>
</div> -->
<!-- <div class="r_point" v-if="scope.row.status == 2 && scope.row.modelCheckTextStatus != -1 && scope.row.modelCheckTextStatus != 0">
<div class="point" style="background-color: #f64558"></div>
<text style="color: #f64558">校验异常</text>
</div> -->
<div class="r_point" v-if="scope.row.status == 3 && scope.row.modelCheckTextStatus != -1 && scope.row.modelCheckTextStatus != 0">
<div class="point" style="background-color: #34a353"></div>
<text style="color: #34a353">校验通过</text>
</div>
<div
class="r_point"
v-if="
(scope.row.status == 4 || scope.row.status == 7 || scope.row.status == 8) &&
scope.row.modelCheckTextStatus != -1 &&
scope.row.modelCheckTextStatus != 0
"
>
<div class="point" style="background-color: #ccc"></div>
<text style="color: #ccc">分析失败</text>
</div>
<text v-if="scope.row.status == 7" style="font-size: 10px; color: #ff3b3b">文件格式不规范建议将此PDF另存为新PDF文件后重试</text>
<text v-if="scope.row.status == 8" style="font-size: 10px; color: #ff3b3b">暂不支持纯图片PDF</text>
<!-- <div class="r_point" v-if="scope.row.status == 21 && scope.row.modelCheckTextStatus != -1 && scope.row.modelCheckTextStatus != 0">
<div class="point" style="background-color: rgb(249, 170, 50)"></div>
<text style="color: rgb(249, 170, 50)">疑似异常</text>
</div> -->
<div
class="r_point"
v-if="
(scope.row.status == 2 || scope.row.status == 21) && scope.row.modelCheckTextStatus != -1 && scope.row.modelCheckTextStatus != 0
"
>
<div class="point" style="background-color: rgb(249, 170, 50)"></div>
<text style="color: rgb(249, 170, 50)">待确认</text>
</div>
</div>
</template>
</el-table-column>
<el-table-column label="操作" align="left" fixed="right" width="150">
<template v-slot="scope">
<!-- <el-button type="text" v-if="scope.row.status == 2 || scope.row.status == 3"
@click="openReSendFile(scope.row)">重新分析</el-button> -->
<!-- <el-button type="text" @click="doReportCheckFn(scope.row)" :disabled="scope.row.status == 0"
v-if="scope.row.status == 1">开始检校</el-button> -->
<div style="display: flex; flex-wrap: nowrap">
<el-button
type="text"
@click="doReportCheckFn(scope.row)"
v-if="scope.row.status != -1 && scope.row.status != -3 && scope.row.status != 4"
>查看详情</el-button
>
<el-button
type="text"
@click="doReportCheckFn(scope.row)"
v-if="
scope.row.status == 4 &&
(scope.row.modelCheckTextStatus == 0 || scope.row.modelCheckTextStatus == 3 || scope.row.modelCheckTextStatus == 4)
"
>查看详情</el-button
>
<el-button
type="text"
@click="doDel(scope.row)"
:disabled="
scope.row.status == 0 ||
scope.row.status == -1 ||
scope.row.status == -3 ||
scope.row.status == 5 ||
scope.row.status == 6 ||
scope.row.modelCheckTextStatus == 0 ||
scope.row.modelCheckTextStatus == 3 ||
scope.row.modelCheckTextStatus == 4
"
>删除</el-button
>
</div>
</template>
</el-table-column>
</table-components>
</div>
<!-- 单文件检校 end -->
<!-- 跨文件检校 start -->
<div v-if="fileType == 1">
<table-components
:tableLoading="tableLoading"
:tableData="tableData"
:defaultCurrentPage="defaultCurrentPage"
@currentChange="currentChange"
@sizeChange="sizeChange"
size="mini"
>
<el-table-column prop="title1" label="年报" align="left" />
<el-table-column prop="title2" label="审计报告" align="left" />
<el-table-column prop="companyName" label="企业简称" align="left" />
<el-table-column prop="year" label="年份" align="left" />
<el-table-column label="类型" align="left" min-width="120">
<template v-slot="scope">
<div>年报&审计报告</div>
</template>
</el-table-column>
<el-table-column prop="createTime" label="上传时间" align="left" sortable />
<el-table-column prop="status" label="" align="left" width="380">
<template #header>
<el-dropdown trigger="click" @command="handleCommand">
<div class="el-dropdown-link">
<span>校验状态</span>
<el-icon class="el-icon--right">
<Filter />
</el-icon>
</div>
<template #dropdown>
<el-dropdown-menu>
<el-dropdown-item :command="null">全部</el-dropdown-item>
<el-dropdown-item :command="0">分析中</el-dropdown-item>
<!-- <el-dropdown-item :command="1">未检校</el-dropdown-item> -->
<!-- <el-dropdown-item :command="2">校验异常</el-dropdown-item> -->
<el-dropdown-item :command="3">校验通过</el-dropdown-item>
<el-dropdown-item :command="4">分析失败</el-dropdown-item>
<el-dropdown-item :command="-9">待确认</el-dropdown-item>
</el-dropdown-menu>
</template>
</el-dropdown>
</template>
<template v-slot="scope">
<div v-if="scope.row.reportType == 5">
<ListStatus :item="scope.row"></ListStatus>
</div>
<div v-else>
<!-- -1-排队中0-分析中1-检校异常2-校验中3-已通过4-分析失败5-财保文件解析中6-数据指标抽取中 -->
<div
class="r_point"
v-if="
(scope.row.status == 0 ||
scope.row.status == 1 ||
scope.row.status == 5 ||
scope.row.status == 6 ||
scope.row.modelCheckTextStatus == 0 ||
scope.row.modelCheckTextStatus == -1) &&
scope.row.status != -1 &&
scope.row.status != -3
"
>
<div class="point" style="background-color: #ffb100"></div>
<text style="color: #ffb100; white-space: nowrap">分析中</text>
<text style="color: #b0b3be; margin-left: 5px; white-space: nowrap">{{ scope.row.process }}</text>
<text style="color: #b0b3be; margin-left: 5px" v-if="scope.row.process && scope.row.process.length > 0">...</text>
</div>
<div class="r_point" v-if="scope.row.status == -1 || scope.row.status == -3">
<div class="point" style="background-color: #ffaa48"></div>
<text style="color: #ffaa48">等待中</text>
</div>
<!-- <div class="r_point" v-if="scope.row.status == 1">
<div class="point" style="background-color: #ffb100"></div>
<text style="color: #ffb100">分析中</text>
</div> -->
<!-- <div class="r_point" v-if="scope.row.status == 2 && scope.row.modelCheckTextStatus != -1 && scope.row.modelCheckTextStatus != 0">
<div class="point" style="background-color: #f64558"></div>
<text style="color: #f64558">校验异常</text>
</div> -->
<div class="r_point" v-if="scope.row.status == 3 && scope.row.modelCheckTextStatus != -1 && scope.row.modelCheckTextStatus != 0">
<div class="point" style="background-color: #34a353"></div>
<text style="color: #34a353">校验通过</text>
</div>
<div
class="r_point"
v-if="
(scope.row.status == 4 || scope.row.status == 7 || scope.row.status == 8) &&
scope.row.modelCheckTextStatus != -1 &&
scope.row.modelCheckTextStatus != 0
"
>
<div class="point" style="background-color: #ccc"></div>
<text style="color: #ccc">分析失败</text>
</div>
<text v-if="scope.row.status == 7" style="font-size: 10px; color: #ff3b3b">文件格式不规范建议将此PDF另存为新PDF文件后重试</text>
<text v-if="scope.row.status == 8" style="font-size: 10px; color: #ff3b3b">暂不支持纯图片PDF</text>
<!-- <div class="r_point" v-if="scope.row.status == 21 && scope.row.modelCheckTextStatus != -1 && scope.row.modelCheckTextStatus != 0">
<div class="point" style="background-color: rgb(249, 170, 50)"></div>
<text style="color: rgb(249, 170, 50)">疑似异常</text>
</div> -->
<div
class="r_point"
v-if="
(scope.row.status == 2 || scope.row.status == 21) && scope.row.modelCheckTextStatus != -1 && scope.row.modelCheckTextStatus != 0
"
>
<div class="point" style="background-color: rgb(249, 170, 50)"></div>
<text style="color: rgb(249, 170, 50)">待确认</text>
</div>
</div>
</template>
</el-table-column>
<el-table-column label="操作" align="left" fixed="right" width="150">
<template v-slot="scope">
<!-- <el-button type="text" v-if="scope.row.status == 2 || scope.row.status == 3"
@click="openReSendFile(scope.row)">重新分析</el-button> -->
<!-- <el-button type="text" @click="doReportCheckFn(scope.row)" :disabled="scope.row.status == 0"
v-if="scope.row.status == 1">开始检校</el-button> -->
<div style="display: flex; flex-wrap: nowrap">
<el-button
type="text"
@click="doReportCheckFn(scope.row)"
v-if="scope.row.status != -1 && scope.row.status != -3 && scope.row.status != 4"
>查看详情</el-button
>
<el-button
type="text"
@click="doReportCheckFn(scope.row)"
v-if="
scope.row.status == 4 &&
(scope.row.modelCheckTextStatus == 0 || scope.row.modelCheckTextStatus == 3 || scope.row.modelCheckTextStatus == 4)
"
>查看详情</el-button
>
<el-button
type="text"
@click="doDel(scope.row)"
:disabled="
scope.row.status == 0 ||
scope.row.status == -1 ||
scope.row.status == -3 ||
scope.row.status == 5 ||
scope.row.status == 6 ||
scope.row.modelCheckTextStatus == 0 ||
scope.row.modelCheckTextStatus == 3 ||
scope.row.modelCheckTextStatus == 4
"
>删除</el-button
>
</div>
</template>
</el-table-column>
</table-components>
</div>
<!-- 跨文件检校 end -->
</div>
<UploadDialog ref="uploadDialog" @handleClose="handleClose"></UploadDialog>
<UploadDialogKua ref="uploadDialogKua" @handleClose="handleClose"></UploadDialogKua>
<ZNotification :show="messageShow" :data="dialogData" @handleClose="messageShow = false"></ZNotification>
</div>
</div>
</template>
<script setup lang="ts" name="loginIndex">
import { onMounted, reactive, ref, onBeforeUnmount, onUnmounted } from 'vue';
import { getReportList, startCheck, doReportDelete, doReportAgain, getReportHistory, getKuaFileList } from '/@/api/api';
import { NextLoading } from '/@/utils/loading';
import TableComponents from '/@/components/tableComponents/index.vue';
import UploadDialog from '/@/components/Upload/UploadDialog.vue';
import UploadDialogKua from '/@/components/Upload/UploadDialogKua.vue';
import { useRouter, useRoute } from 'vue-router';
import ZButton from '/@/components/ZButton/index.vue';
import { ElMessageBox } from 'element-plus';
import iconFile from '/@/assets/images/icon_file.png';
import iconSearch from '/@/assets/images/icon_search.png';
import { Session } from '/@/utils/storage';
import ZNotification from '/@/components/ZNotification/index.vue';
import Slide from '/@/components/swipe/IndexSlide.vue';
import ListStatus from '/@/components/TypoDetection/ListStatus.vue';
// fileType 0单文件检校 1跨文件检校
const fileType = ref(0);
const route = useRoute();
const router = useRouter();
const userType = ref(Session.get('userData').userType);
const reportType: string[] = ['年报', '半年报', '一季报', '三季报', '', '日常公告'];
const uploadDialog = ref(null);
const uploadDialogKua = ref(null);
const queryFrom = ref({});
const tableLoading = ref(false);
const tableData = reactive({
data: [],
total: 0,
page: 1,
size: 10,
});
// 默认页码
const defaultCurrentPage = ref(1);
// 历史数据
const historyData = ref([]);
function handleClose() {
getData(null);
}
function showUploadDialog() {
console.log('🚀 ~ showUploadDialog ~ fileType.value:', fileType.value);
if (fileType.value == 0) {
if (uploadDialog.value) {
uploadDialog.value.showModal();
}
} else {
if (uploadDialogKua.value) {
uploadDialogKua.value.showModal();
}
}
}
function goDetail(item) {
if (fileType.value == 0) {
router.push({
path: '/detail',
query: {
id: item.id,
fromPath: route.path,
type: 1, // type 0看板进入 1检校进入
reportType: item.reportType,
fileName: item.fileName,
},
});
} else {
router.push({
path: '/detailKua',
query: {
id: item.id,
fromPath: route.path,
type: 1, // type 0看板进入 1检校进入
reportType: item.reportType,
fileName: item.fileName,
batchNo: item.batchNo,
},
});
}
}
// 检校
async function doReportCheckFn(item) {
tableLoading.value = true;
let { code } = await startCheck({
id: item.id,
}).catch((e) => {
tableLoading.value = false;
});
tableLoading.value = false;
if (code == 200) {
Session.set('detail_name', item.title);
goDetail(item);
getData(null);
}
}
// 页码数量改变
function sizeChange(size) {
tableData.size = size;
getData(null);
}
// 翻页
function currentChange(page) {
tableData.page = page;
defaultCurrentPage.value = page;
getData(null);
}
// 列表某一项删除
async function doDel(item) {
let res = await ElMessageBox.confirm('删除操作将不可恢复,是否确定?', '提示', {
confirmButtonText: '删除',
cancelButtonText: '取消',
type: 'warning',
});
if (res == 'confirm') {
tableLoading.value = true;
let { code } = await doReportDelete({
id: item.id,
}).catch((e) => {
tableLoading.value = false;
});
tableLoading.value = false;
if (code == 200) {
getData(null);
}
}
}
async function getData(hideLoading: Boolean) {
saveForm();
if (!hideLoading) tableLoading.value = true;
if (fileType.value == 0) {
if (userType.value == 0 || userType.value == 1) {
let { code, data } = await getReportList({
...queryFrom.value,
page: tableData.page,
size: tableData.size,
});
tableLoading.value = false;
if (code == 200) {
tableData.data = data.list;
tableData.total = data.total;
tableLoading.value = false;
}
}
} else {
let { code, data } = await getKuaFileList({
...queryFrom.value,
page: tableData.page,
size: tableData.size,
});
if (code == 200) {
tableData.data = data.list;
console.log('🚀 ~ getData ~ tableData.data:', tableData.data);
tableData.total = data.total;
tableLoading.value = false;
}
}
}
async function getHistory() {
let { code, data } = await getReportHistory({});
if (code == 200) {
historyData.value = data;
}
}
function openReSendFile(row) {
ElMessageBox.confirm('确认是否进行重新分析?', '提示', {
confirmButtonText: '重新分析',
cancelButtonText: '取消',
type: 'warning',
})
.then(() => {
reSendFile(row);
})
.catch(() => {});
}
async function reSendFile(row) {
tableLoading.value = true;
let { code } = await doReportAgain({
id: row.id,
}).catch((e) => {
tableLoading.value = false;
});
if (code == 200) {
getData(null);
} else {
tableLoading.value = false;
}
}
// 记录下所有查询条件,返回时使用
function saveForm() {
Session.set('indexPage', tableData.page);
Session.set('indexFilter', queryFrom.value);
}
// 重置
function restFrom(reload = false) {
for (let obj in queryFrom.value) {
queryFrom.value[obj] = null;
}
if (reload) {
getData(false);
}
}
// 检验状态筛选
function handleCommand(d) {
queryFrom.value.status = d;
handleChangeFilter();
}
// 筛选
function handleChangeFilter() {
getData(false);
}
// 轮询
const autoRef = setInterval(
() => {
getData(true);
},
1000 * 60,
0
);
const beforeunloadHandler = (e) => {};
const unloadHandler = (e) => {
Session.remove('indexPage');
Session.remove('indexFilter');
};
async function getKuaFileListFn() {
let { code, data } = await getKuaFileList({
...queryFrom.value,
page: tableData.page,
size: tableData.size,
pageType: 0,
});
if (code == 200) {
tableData.data = data.list;
tableData.total = data.total;
tableLoading.value = false;
}
}
function handleTabClick(value) {
// 0单文件检校 1跨文件检校
fileType.value = value.props.name;
getData(null);
}
// 页面加载时
onMounted(() => {
NextLoading.done();
if (Session.get('indexPage')) {
tableData.page = Session.get('indexPage');
defaultCurrentPage.value = Session.get('indexPage');
}
if (Session.get('indexFilter')) {
queryFrom.value = Session.get('indexFilter');
}
getData(null);
getHistory();
window.addEventListener('beforeunload', (e) => beforeunloadHandler(e));
window.addEventListener('unload', (e) => unloadHandler(e));
});
onBeforeUnmount(() => {
// console.log('🚀 ~ onBeforeUnmount ~ onBeforeUnmount:');
clearInterval(autoRef);
window.removeEventListener('beforeunload', (e) => beforeunloadHandler(e));
window.removeEventListener('unload', (e) => unloadHandler(e));
});
/******* scoket start *************/
// 初始化消息数组
const ws = new WebSocket(import.meta.env.VITE_API_WS + '/' + Session.get('userData')?.phone);
const messageShow = ref(false);
// 监听WebSocket打开事件
ws.addEventListener('open', () => {
console.log('WebSocket已连接');
});
const dialogData = ref();
// 监听接收到消息的事件
ws.addEventListener('message', (event) => {
console.log('🚀 ~ ws.addEventListener ~ event:', event.data);
dialogData.value = JSON.parse(event.data);
// ElNotification({
// title: 'Title',
// message: h('i', { style: 'color: teal' }, event.data),
// position: 'bottom-right'
// })
messageShow.value = true;
getData(false);
// setTimeout(() => {
// messageShow.value = false
// }, 5000);
// const data = JSON.parse(event.data);
// messages1.value.push(data.message);
});
// 发送消息至服务器的方法
function sendMessage() {
const message = 'Hello, Server!';
ws.send(JSON.stringify({ message }));
}
// 监听WebSocket关闭事件
ws.addEventListener('close', () => {
console.log('WebSocket连接已关闭');
});
// 监听错误事件
ws.addEventListener('error', (error) => {
console.error('WebSocket发生错误:', error);
});
onUnmounted(() => {
ws.close();
});
/******* scoket start *************/
</script>
<style scoped lang="scss">
@import url('/@/theme/page/page.scss');
.container {
width: 100%;
min-width: 1400px;
min-height: calc(100vh - 56px);
margin: 0 auto;
background: url('/@/assets/images/bk_charts1.png') #f5f7fd no-repeat center 0;
background-size: 100% auto;
2026-03-23 15:21:53 +08:00
}
:deep(.el-form-item--large .el-form-item__label) {
font-weight: 400;
}
.main {
background: #ffffff;
border: 2px solid #ffffff;
box-shadow: 0 12px 32px -2px rgba(206, 208, 211, 0.8);
border-radius: 0 4px 4px 4px;
padding: 0 24px 24px;
margin: 24px 0;
}
.btn_content {
display: flex;
align-items: center;
img {
width: 11px;
height: 14px;
margin-right: 5px;
}
text {
color: #ffffff;
text-align: center;
font-size: 14px;
font-style: normal;
font-weight: 500;
line-height: 18.2px;
}
}
.input_icon {
width: 12px;
height: 12px;
cursor: pointer;
}
.r_point {
display: flex;
align-items: center;
gap: 3px;
}
.point {
width: 8px;
height: 8px;
border-radius: 100px;
// color: #ffaa48;
}
// 监管账号图表样式
.el-dropdown {
vertical-align: middle;
cursor: pointer;
.el-dropdown-link {
display: flex;
color: rgb(136, 151, 174);
font-family: Alip-Regular;
font-weight: 400;
font-size: 15px;
align-items: center;
}
}
.el-option-label-div {
max-width: 250px;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.w1400 {
max-width: 1400px;
margin: 0 auto;
}
</style>