feat: 完成上传数据页面
This commit is contained in:
@@ -108,10 +108,10 @@
|
|||||||
"Skill(mcp-mysql-correct-db)",
|
"Skill(mcp-mysql-correct-db)",
|
||||||
"Bash(git diff:*)",
|
"Bash(git diff:*)",
|
||||||
"Bash(git pull:*)",
|
"Bash(git pull:*)",
|
||||||
"Bash(git merge:*)"
|
"Bash(git merge:*)",
|
||||||
|
"WebFetch(domain:raw.githubusercontent.com)",
|
||||||
|
"WebSearch"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"enabledMcpjsonServers": [
|
"enabledMcpjsonServers": ["mysql"]
|
||||||
"mysql"
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
|
|||||||
81
ruoyi-ui/src/api/ccdiProjectUpload.js
Normal file
81
ruoyi-ui/src/api/ccdiProjectUpload.js
Normal file
@@ -0,0 +1,81 @@
|
|||||||
|
import request from '@/utils/request'
|
||||||
|
|
||||||
|
// 获取项目上传数据状态
|
||||||
|
export function getUploadStatus(projectId) {
|
||||||
|
return request({
|
||||||
|
url: '/ccdi/project/' + projectId + '/upload-status',
|
||||||
|
method: 'get'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 上传文件
|
||||||
|
export function uploadFile(projectId, uploadType, file) {
|
||||||
|
const formData = new FormData()
|
||||||
|
formData.append('file', file)
|
||||||
|
formData.append('uploadType', uploadType)
|
||||||
|
return request({
|
||||||
|
url: '/ccdi/project/' + projectId + '/upload',
|
||||||
|
method: 'post',
|
||||||
|
data: formData,
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'multipart/form-data'
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 删除文件
|
||||||
|
export function deleteFile(projectId, uploadType) {
|
||||||
|
return request({
|
||||||
|
url: '/ccdi/project/' + projectId + '/file/' + uploadType,
|
||||||
|
method: 'delete'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取名单库选项
|
||||||
|
export function getNameListOptions() {
|
||||||
|
return request({
|
||||||
|
url: '/ccdi/project/name-list/options',
|
||||||
|
method: 'get'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 更新名单库选择
|
||||||
|
export function updateNameListSelection(projectId, data) {
|
||||||
|
return request({
|
||||||
|
url: '/ccdi/project/' + projectId + '/name-lists',
|
||||||
|
method: 'put',
|
||||||
|
data: data
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 执行数据质量检查
|
||||||
|
export function executeQualityCheck(projectId) {
|
||||||
|
return request({
|
||||||
|
url: '/ccdi/project/' + projectId + '/quality-check',
|
||||||
|
method: 'post'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 拉取本行信息
|
||||||
|
export function pullBankInfo(projectId) {
|
||||||
|
return request({
|
||||||
|
url: '/ccdi/project/' + projectId + '/pull-bank-info',
|
||||||
|
method: 'post'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 生成报告
|
||||||
|
export function generateReport(projectId) {
|
||||||
|
return request({
|
||||||
|
url: '/ccdi/project/' + projectId + '/generate-report',
|
||||||
|
method: 'post'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 查询导入状态
|
||||||
|
export function getImportStatus(taskId) {
|
||||||
|
return request({
|
||||||
|
url: '/ccdi/project/upload-status/' + taskId,
|
||||||
|
method: 'get'
|
||||||
|
})
|
||||||
|
}
|
||||||
@@ -70,6 +70,13 @@ export const constantRoutes = [
|
|||||||
component: () => import('@/views/ccdiProject/index'),
|
component: () => import('@/views/ccdiProject/index'),
|
||||||
name: 'CcdiProject',
|
name: 'CcdiProject',
|
||||||
meta: { title: '初核项目管理', icon: 'dashboard', affix: true }
|
meta: { title: '初核项目管理', icon: 'dashboard', affix: true }
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: 'ccdiProject/detail/:projectId',
|
||||||
|
component: () => import('@/views/ccdiProject/detail'),
|
||||||
|
name: 'ProjectDetail',
|
||||||
|
hidden: true,
|
||||||
|
meta: { title: '项目详情', noCache: true }
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
|||||||
947
ruoyi-ui/src/views/ccdiProject/components/detail/UploadData.vue
Normal file
947
ruoyi-ui/src/views/ccdiProject/components/detail/UploadData.vue
Normal file
@@ -0,0 +1,947 @@
|
|||||||
|
<template>
|
||||||
|
<div class="upload-data-container">
|
||||||
|
<!-- 主内容区 -->
|
||||||
|
<div class="main-content">
|
||||||
|
<!-- 页面头部 -->
|
||||||
|
<div class="content-header">
|
||||||
|
<h2 class="content-title">{{ currentMenuTitle }}</h2>
|
||||||
|
<div class="header-actions">
|
||||||
|
<el-button
|
||||||
|
size="small"
|
||||||
|
type="primary"
|
||||||
|
icon="el-icon-document"
|
||||||
|
@click="handleGenerateReport"
|
||||||
|
>
|
||||||
|
生成报告
|
||||||
|
</el-button>
|
||||||
|
<el-button
|
||||||
|
size="small"
|
||||||
|
icon="el-icon-download"
|
||||||
|
@click="handleFetchBankInfo"
|
||||||
|
>
|
||||||
|
拉取本行信息
|
||||||
|
</el-button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 上传模块 -->
|
||||||
|
<div class="upload-section">
|
||||||
|
<div class="upload-cards">
|
||||||
|
<div v-for="card in uploadCards" :key="card.key" class="upload-card">
|
||||||
|
<div class="card-icon">
|
||||||
|
<i :class="card.icon"></i>
|
||||||
|
</div>
|
||||||
|
<div class="card-title">{{ card.title }}</div>
|
||||||
|
<div class="card-desc">{{ card.desc }}</div>
|
||||||
|
<el-button
|
||||||
|
size="small"
|
||||||
|
:type="card.uploaded ? 'primary' : ''"
|
||||||
|
:icon="card.uploaded ? 'el-icon-view' : 'el-icon-upload2'"
|
||||||
|
:plain="!card.uploaded"
|
||||||
|
@click="handleUploadClick(card.key)"
|
||||||
|
>
|
||||||
|
{{ card.btnText }}
|
||||||
|
</el-button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 数据质量检查
|
||||||
|
<div class="quality-check-section">
|
||||||
|
<div class="section-header">
|
||||||
|
<i class="el-icon-warning-outline warning-icon"></i>
|
||||||
|
<span>检查结果</span>
|
||||||
|
</div>
|
||||||
|
<div class="metrics">
|
||||||
|
<div v-for="metric in metrics" :key="metric.key" class="metric-card">
|
||||||
|
<div class="metric-title">{{ metric.title }}</div>
|
||||||
|
<div class="metric-value" :class="`value-${metric.level}`">
|
||||||
|
{{ metric.value }}
|
||||||
|
</div>
|
||||||
|
<div class="progress-ring-container">
|
||||||
|
<svg class="progress-ring" viewBox="0 0 32 32">
|
||||||
|
<circle
|
||||||
|
class="progress-ring-bg"
|
||||||
|
cx="16"
|
||||||
|
cy="16"
|
||||||
|
r="14"
|
||||||
|
fill="none"
|
||||||
|
stroke="#f0f0f0"
|
||||||
|
stroke-width="4"
|
||||||
|
/>
|
||||||
|
<circle
|
||||||
|
class="progress-ring-progress"
|
||||||
|
:stroke="getProgressColor(metric.level)"
|
||||||
|
cx="16"
|
||||||
|
cy="16"
|
||||||
|
r="14"
|
||||||
|
fill="none"
|
||||||
|
stroke-width="4"
|
||||||
|
:stroke-dasharray="circumference"
|
||||||
|
:stroke-dashoffset="getProgressOffset(metric.value)"
|
||||||
|
stroke-linecap="round"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div> -->
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 上传弹窗 -->
|
||||||
|
<el-dialog
|
||||||
|
v-if="showUploadDialog"
|
||||||
|
:title="uploadDialogTitle"
|
||||||
|
:visible.sync="showUploadDialog"
|
||||||
|
:close-on-click-modal="false"
|
||||||
|
width="500px"
|
||||||
|
>
|
||||||
|
<el-upload
|
||||||
|
class="upload-area"
|
||||||
|
drag
|
||||||
|
action="#"
|
||||||
|
:auto-upload="false"
|
||||||
|
:on-change="handleFileChange"
|
||||||
|
:file-list="fileList"
|
||||||
|
>
|
||||||
|
<i class="el-icon-upload"></i>
|
||||||
|
<div class="el-upload__text">将文件拖到此处,或<em>点击上传</em></div>
|
||||||
|
<div class="el-upload__tip" slot="tip">
|
||||||
|
支持 {{ uploadFileTypes }} 格式文件
|
||||||
|
</div>
|
||||||
|
</el-upload>
|
||||||
|
<span slot="footer">
|
||||||
|
<el-button @click="showUploadDialog = false">取消</el-button>
|
||||||
|
<el-button
|
||||||
|
type="primary"
|
||||||
|
@click="handleConfirmUpload"
|
||||||
|
:loading="uploading"
|
||||||
|
>确定</el-button
|
||||||
|
>
|
||||||
|
</span>
|
||||||
|
</el-dialog>
|
||||||
|
|
||||||
|
<!-- 名单选择弹窗 -->
|
||||||
|
<el-dialog
|
||||||
|
:title="'名单库选择'"
|
||||||
|
:visible.sync="showNameListDialog"
|
||||||
|
width="600px"
|
||||||
|
>
|
||||||
|
<el-form :model="nameListForm" label-width="100px">
|
||||||
|
<el-form-item label="名单类型">
|
||||||
|
<el-select v-model="nameListForm.type" placeholder="请选择名单类型">
|
||||||
|
<el-option label="黑名单" value="blacklist"></el-option>
|
||||||
|
<el-option label="灰名单" value="graylist"></el-option>
|
||||||
|
<el-option label="白名单" value="whitelist"></el-option>
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="名单来源">
|
||||||
|
<el-select v-model="nameListForm.source" placeholder="请选择名单来源">
|
||||||
|
<el-option label="中台管理系统" value="platform"></el-option>
|
||||||
|
<el-option label="本地上传" value="local"></el-option>
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
|
<span slot="footer">
|
||||||
|
<el-button @click="showNameListDialog = false">取消</el-button>
|
||||||
|
<el-button type="primary" @click="handleConfirmNameList"
|
||||||
|
>确定</el-button
|
||||||
|
>
|
||||||
|
</span>
|
||||||
|
</el-dialog>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import {
|
||||||
|
getUploadStatus,
|
||||||
|
uploadFile,
|
||||||
|
deleteFile,
|
||||||
|
getNameListOptions,
|
||||||
|
updateNameListSelection,
|
||||||
|
executeQualityCheck,
|
||||||
|
pullBankInfo,
|
||||||
|
generateReport,
|
||||||
|
getImportStatus,
|
||||||
|
} from "@/api/ccdiProjectUpload";
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: "UploadData",
|
||||||
|
props: {
|
||||||
|
projectId: {
|
||||||
|
type: [String, Number],
|
||||||
|
default: null,
|
||||||
|
},
|
||||||
|
projectInfo: {
|
||||||
|
type: Object,
|
||||||
|
default: () => ({
|
||||||
|
projectName: "",
|
||||||
|
updateTime: "",
|
||||||
|
projectStatus: "0",
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
// 加载状态
|
||||||
|
loading: false,
|
||||||
|
// 当前选中的菜单
|
||||||
|
activeMenu: "upload",
|
||||||
|
// 当前菜单标题
|
||||||
|
currentMenuTitle: "上传数据",
|
||||||
|
// 圆环周长
|
||||||
|
circumference: 2 * Math.PI * 14,
|
||||||
|
// 上传弹窗
|
||||||
|
showUploadDialog: false,
|
||||||
|
uploadDialogTitle: "",
|
||||||
|
uploadFileType: "",
|
||||||
|
uploadFileTypes: "",
|
||||||
|
fileList: [],
|
||||||
|
uploading: false,
|
||||||
|
// 名单选择弹窗
|
||||||
|
showNameListDialog: false,
|
||||||
|
nameListForm: {
|
||||||
|
type: "",
|
||||||
|
source: "platform",
|
||||||
|
},
|
||||||
|
// 上传状态列表
|
||||||
|
uploadStatusList: [],
|
||||||
|
// 名单库选项列表
|
||||||
|
nameListOptions: [],
|
||||||
|
// 侧边栏菜单项
|
||||||
|
menuItems: [
|
||||||
|
{ key: "upload", label: "上传数据", route: "upload" },
|
||||||
|
{ key: "config", label: "参数配置", route: "config" },
|
||||||
|
{ key: "overview", label: "结果总览", route: "overview" },
|
||||||
|
{ key: "special", label: "专项排查", route: "special" },
|
||||||
|
{ key: "detail", label: "流水明细查询", route: "detail" },
|
||||||
|
],
|
||||||
|
// 上传卡片
|
||||||
|
uploadCards: [
|
||||||
|
{
|
||||||
|
key: "transaction",
|
||||||
|
title: "流水导入",
|
||||||
|
desc: "支持 Excel、PDF 格式文件上传",
|
||||||
|
icon: "el-icon-document",
|
||||||
|
btnText: "上传流水",
|
||||||
|
uploaded: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: "credit",
|
||||||
|
title: "征信导入",
|
||||||
|
desc: "支持 HTML 格式征信数据解析",
|
||||||
|
icon: "el-icon-s-data",
|
||||||
|
btnText: "上传征信",
|
||||||
|
uploaded: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: "employee",
|
||||||
|
title: "员工关系导入",
|
||||||
|
desc: "Excel 表格上传员工家庭关系信息",
|
||||||
|
icon: "el-icon-user",
|
||||||
|
btnText: "上传员工关系",
|
||||||
|
uploaded: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: "namelist",
|
||||||
|
title: "名单库选择",
|
||||||
|
desc: "选择中台管理系统的名单",
|
||||||
|
icon: "el-icon-s-order",
|
||||||
|
btnText: "选择名单",
|
||||||
|
uploaded: false,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
// 质量指标
|
||||||
|
metrics: [
|
||||||
|
{
|
||||||
|
key: "completeness",
|
||||||
|
title: "数据完整性",
|
||||||
|
value: "98.5%",
|
||||||
|
level: "success",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: "consistency",
|
||||||
|
title: "格式一致性",
|
||||||
|
value: "95.2%",
|
||||||
|
level: "info",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: "continuity",
|
||||||
|
title: "余额连续性",
|
||||||
|
value: "92.8%",
|
||||||
|
level: "info",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
||||||
|
},
|
||||||
|
created() {
|
||||||
|
// 加载初始数据
|
||||||
|
// this.loadInitialData();
|
||||||
|
// 监听路由变化更新选中菜单
|
||||||
|
this.updateActiveMenu();
|
||||||
|
},
|
||||||
|
mounted() {
|
||||||
|
// 组件挂载后监听项目ID变化
|
||||||
|
this.$watch("projectId", this.loadInitialData);
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
/** 加载初始数据 */
|
||||||
|
async loadInitialData() {
|
||||||
|
if (!this.projectId) return;
|
||||||
|
|
||||||
|
try {
|
||||||
|
this.loading = true;
|
||||||
|
|
||||||
|
// 并行加载上传状态和名单库选项
|
||||||
|
const [uploadStatusRes, nameListRes] = await Promise.all([
|
||||||
|
getUploadStatus(this.projectId),
|
||||||
|
getNameListOptions(),
|
||||||
|
]);
|
||||||
|
|
||||||
|
this.uploadStatusList = uploadStatusRes.data || [];
|
||||||
|
this.nameListOptions = nameListRes.data || [];
|
||||||
|
|
||||||
|
// 更新上传卡片状态
|
||||||
|
this.updateUploadCards();
|
||||||
|
|
||||||
|
// 模拟更新质量指标(实际应从API获取)
|
||||||
|
this.updateQualityMetrics();
|
||||||
|
} catch (error) {
|
||||||
|
console.error("加载初始数据失败:", error);
|
||||||
|
this.$message.error("加载数据失败");
|
||||||
|
} finally {
|
||||||
|
this.loading = false;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
/** 更新上传卡片状态 */
|
||||||
|
updateUploadCards() {
|
||||||
|
const statusMap = {};
|
||||||
|
this.uploadStatusList.forEach((item) => {
|
||||||
|
statusMap[item.uploadType] = item;
|
||||||
|
});
|
||||||
|
|
||||||
|
this.uploadCards.forEach((card) => {
|
||||||
|
const status = statusMap[card.key.toUpperCase()];
|
||||||
|
if (status) {
|
||||||
|
card.uploaded = status.uploaded;
|
||||||
|
card.btnText = status.uploaded
|
||||||
|
? "已上传" + card.title.replace("导入", "").replace("上传", "")
|
||||||
|
: card.btnText;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
/** 更新质量指标 */
|
||||||
|
updateQualityMetrics() {
|
||||||
|
// 模拟更新质量指标
|
||||||
|
this.metrics.forEach((metric) => {
|
||||||
|
if (metric.key === "completeness") {
|
||||||
|
metric.value = "98.5%";
|
||||||
|
metric.level = "success";
|
||||||
|
} else if (metric.key === "consistency") {
|
||||||
|
metric.value = "95.2%";
|
||||||
|
metric.level = "info";
|
||||||
|
} else if (metric.key === "continuity") {
|
||||||
|
metric.value = "92.8%";
|
||||||
|
metric.level = "info";
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
/** 菜单点击 */
|
||||||
|
handleMenuClick(key, route) {
|
||||||
|
const menuItem = this.menuItems.find((m) => m.key === key);
|
||||||
|
if (menuItem) {
|
||||||
|
this.currentMenuTitle = menuItem.label;
|
||||||
|
}
|
||||||
|
if (key === "upload") {
|
||||||
|
this.activeMenu = key;
|
||||||
|
} else {
|
||||||
|
// 其他菜单项通知父组件跳转
|
||||||
|
this.$emit("menu-change", { key, route });
|
||||||
|
}
|
||||||
|
},
|
||||||
|
/** 更新当前选中菜单 */
|
||||||
|
updateActiveMenu() {
|
||||||
|
this.activeMenu = "upload";
|
||||||
|
this.currentMenuTitle = "上传数据";
|
||||||
|
},
|
||||||
|
/** 上传卡片点击 */
|
||||||
|
handleUploadClick(key) {
|
||||||
|
const card = this.uploadCards.find((c) => c.key === key);
|
||||||
|
if (!card) return;
|
||||||
|
|
||||||
|
if (key === "namelist") {
|
||||||
|
this.showNameListDialog = true;
|
||||||
|
} else {
|
||||||
|
this.uploadFileType = key;
|
||||||
|
this.uploadDialogTitle = `上传${card.title}`;
|
||||||
|
this.uploadFileTypes = card.desc.replace(/.*支持|上传/g, "").trim();
|
||||||
|
this.showUploadDialog = true;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
/** 文件选择变化 */
|
||||||
|
handleFileChange(file, fileList) {
|
||||||
|
this.fileList = fileList.slice(-1); // 只保留最后一个文件
|
||||||
|
},
|
||||||
|
/** 确认上传 */
|
||||||
|
async handleConfirmUpload() {
|
||||||
|
if (this.fileList.length === 0) {
|
||||||
|
this.$message.warning("请选择要上传的文件");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.uploading = true;
|
||||||
|
try {
|
||||||
|
// 调用上传API
|
||||||
|
const res = await uploadFile(
|
||||||
|
this.projectId,
|
||||||
|
this.uploadFileType.toUpperCase(),
|
||||||
|
this.fileList[0].raw
|
||||||
|
);
|
||||||
|
|
||||||
|
this.uploading = false;
|
||||||
|
this.showUploadDialog = false;
|
||||||
|
|
||||||
|
this.$message.success("文件上传成功,正在处理中...");
|
||||||
|
this.$emit("data-uploaded", { type: this.uploadFileType });
|
||||||
|
|
||||||
|
// 刷新上传状态
|
||||||
|
await this.loadUploadStatus();
|
||||||
|
|
||||||
|
// 开始轮询任务状态
|
||||||
|
this.startPolling(res.data);
|
||||||
|
} catch (error) {
|
||||||
|
this.uploading = false;
|
||||||
|
this.$message.error("上传失败:" + (error.msg || "未知错误"));
|
||||||
|
} finally {
|
||||||
|
this.fileList = [];
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
/** 轮询任务状态 */
|
||||||
|
startPolling(taskId) {
|
||||||
|
const maxAttempts = 20; // 最多轮询20次(约10分钟)
|
||||||
|
let attempts = 0;
|
||||||
|
|
||||||
|
const poll = async () => {
|
||||||
|
if (attempts >= maxAttempts) {
|
||||||
|
this.$message.warning("文件处理超时,请稍后查看");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
const res = await getImportStatus(taskId);
|
||||||
|
const status = res.data;
|
||||||
|
|
||||||
|
if (!status) {
|
||||||
|
attempts++;
|
||||||
|
setTimeout(poll, 30000); // 30秒后再次查询
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (status.uploadStatus === "SUCCESS") {
|
||||||
|
// 处理完成,刷新状态
|
||||||
|
await this.loadUploadStatus();
|
||||||
|
this.$message.success("文件处理完成");
|
||||||
|
return;
|
||||||
|
} else if (status.uploadStatus === "FAILED") {
|
||||||
|
// 处理失败
|
||||||
|
await this.loadUploadStatus();
|
||||||
|
this.$message.error(
|
||||||
|
"文件处理失败:" + (status.errorMessage || "未知错误")
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 继续处理中
|
||||||
|
attempts++;
|
||||||
|
setTimeout(poll, 30000);
|
||||||
|
} catch (error) {
|
||||||
|
console.error("轮询任务状态失败:", error);
|
||||||
|
attempts++;
|
||||||
|
setTimeout(poll, 30000);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
poll();
|
||||||
|
},
|
||||||
|
|
||||||
|
/** 加载上传状态 */
|
||||||
|
async loadUploadStatus() {
|
||||||
|
try {
|
||||||
|
const res = await getUploadStatus(this.projectId);
|
||||||
|
this.uploadStatusList = res.data || [];
|
||||||
|
this.updateUploadCards();
|
||||||
|
} catch (error) {
|
||||||
|
console.error("加载上传状态失败:", error);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
/** 确认选择名单 */
|
||||||
|
async handleConfirmNameList() {
|
||||||
|
if (!this.nameListForm.type || !this.nameListForm.source) {
|
||||||
|
this.$message.warning("请完善名单选择信息");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
// 调用更新名单API
|
||||||
|
await updateNameListSelection(this.projectId, {
|
||||||
|
nameLists: [
|
||||||
|
{
|
||||||
|
type: this.nameListForm.type,
|
||||||
|
source: this.nameListForm.source,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
});
|
||||||
|
|
||||||
|
const card = this.uploadCards.find((c) => c.key === "namelist");
|
||||||
|
if (card) {
|
||||||
|
card.uploaded = true;
|
||||||
|
card.btnText = "已选择名单";
|
||||||
|
}
|
||||||
|
|
||||||
|
this.showNameListDialog = false;
|
||||||
|
this.$message.success("名单选择成功");
|
||||||
|
this.$emit("name-selected", this.nameListForm);
|
||||||
|
} catch (error) {
|
||||||
|
this.$message.error("名单选择失败:" + (error.msg || "未知错误"));
|
||||||
|
}
|
||||||
|
},
|
||||||
|
/** 生成报告 */
|
||||||
|
async handleGenerateReport() {
|
||||||
|
this.$confirm("确认生成报告吗?", "提示", {
|
||||||
|
confirmButtonText: "确定",
|
||||||
|
cancelButtonText: "取消",
|
||||||
|
type: "warning",
|
||||||
|
})
|
||||||
|
.then(async () => {
|
||||||
|
try {
|
||||||
|
const loading = this.$loading({
|
||||||
|
lock: true,
|
||||||
|
text: "正在生成报告...",
|
||||||
|
spinner: "el-icon-loading",
|
||||||
|
background: "rgba(0, 0, 0, 0.7)",
|
||||||
|
});
|
||||||
|
|
||||||
|
// await generateReport(this.projectId);
|
||||||
|
|
||||||
|
loading.close();
|
||||||
|
this.$message.success("报告生成成功");
|
||||||
|
this.$emit("generate-report");
|
||||||
|
} catch (error) {
|
||||||
|
this.$message.error("生成报告失败:" + (error.msg || "未知错误"));
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch(() => {});
|
||||||
|
},
|
||||||
|
/** 拉取本行信息 */
|
||||||
|
async handleFetchBankInfo() {
|
||||||
|
this.$confirm("确认拉取本行信息吗?", "提示", {
|
||||||
|
confirmButtonText: "确定",
|
||||||
|
cancelButtonText: "取消",
|
||||||
|
type: "warning",
|
||||||
|
})
|
||||||
|
.then(async () => {
|
||||||
|
try {
|
||||||
|
const loading = this.$loading({
|
||||||
|
lock: true,
|
||||||
|
text: "正在拉取本行信息...",
|
||||||
|
spinner: "el-icon-loading",
|
||||||
|
background: "rgba(0, 0, 0, 0.7)",
|
||||||
|
});
|
||||||
|
|
||||||
|
await pullBankInfo(this.projectId);
|
||||||
|
|
||||||
|
loading.close();
|
||||||
|
this.$message.success("本行信息拉取成功");
|
||||||
|
this.$emit("fetch-bank-info");
|
||||||
|
|
||||||
|
// 刷新质量指标
|
||||||
|
this.updateQualityMetrics();
|
||||||
|
} catch (error) {
|
||||||
|
this.$message.error(
|
||||||
|
"拉取本行信息失败:" + (error.msg || "未知错误")
|
||||||
|
);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch(() => {});
|
||||||
|
},
|
||||||
|
/** 获取进度条偏移 */
|
||||||
|
getProgressOffset(value) {
|
||||||
|
const percentage = parseFloat(value);
|
||||||
|
return this.circumference * (1 - percentage / 100);
|
||||||
|
},
|
||||||
|
/** 获取进度条颜色 */
|
||||||
|
getProgressColor(level) {
|
||||||
|
const colorMap = {
|
||||||
|
success: "#52c41a",
|
||||||
|
info: "#1890ff",
|
||||||
|
warning: "#fa8c16",
|
||||||
|
danger: "#f5222d",
|
||||||
|
};
|
||||||
|
return colorMap[level] || "#1890ff";
|
||||||
|
},
|
||||||
|
/** 格式化更新时间 */
|
||||||
|
formatUpdateTime(time) {
|
||||||
|
if (!time) return "-";
|
||||||
|
const date = new Date(time);
|
||||||
|
const year = date.getFullYear();
|
||||||
|
const month = String(date.getMonth() + 1).padStart(2, "0");
|
||||||
|
const day = String(date.getDate()).padStart(2, "0");
|
||||||
|
const hours = String(date.getHours()).padStart(2, "0");
|
||||||
|
const minutes = String(date.getMinutes()).padStart(2, "0");
|
||||||
|
return `${year}-${month}-${day} ${hours}:${minutes}`;
|
||||||
|
},
|
||||||
|
/** 获取状态样式类 */
|
||||||
|
getStatusClass() {
|
||||||
|
const status = String(this.projectInfo.projectStatus);
|
||||||
|
const statusMap = {
|
||||||
|
0: "processing",
|
||||||
|
1: "success",
|
||||||
|
2: "archived",
|
||||||
|
};
|
||||||
|
return statusMap[status] || "processing";
|
||||||
|
},
|
||||||
|
/** 获取状态标签 */
|
||||||
|
getStatusLabel() {
|
||||||
|
const status = String(this.projectInfo.projectStatus);
|
||||||
|
const statusMap = {
|
||||||
|
0: "进行中",
|
||||||
|
1: "已完成",
|
||||||
|
2: "已归档",
|
||||||
|
};
|
||||||
|
return statusMap[status] || "未知";
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.upload-data-container {
|
||||||
|
padding: 16px;
|
||||||
|
background: #fff;
|
||||||
|
min-height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 侧边栏
|
||||||
|
.sidebar {
|
||||||
|
background: #ffffff;
|
||||||
|
border-radius: 4px;
|
||||||
|
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.05);
|
||||||
|
padding: 16px;
|
||||||
|
height: 100%;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
|
||||||
|
.sidebar-header {
|
||||||
|
font-size: 16px;
|
||||||
|
font-weight: 600;
|
||||||
|
color: #303133;
|
||||||
|
margin-bottom: 20px;
|
||||||
|
padding-bottom: 12px;
|
||||||
|
border-bottom: 1px solid #ebeef5;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sidebar-menu {
|
||||||
|
list-style: none;
|
||||||
|
padding: 0;
|
||||||
|
margin: 0 0 auto 0;
|
||||||
|
flex: 1;
|
||||||
|
|
||||||
|
.menu-item {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
padding: 10px 12px;
|
||||||
|
margin-bottom: 4px;
|
||||||
|
cursor: pointer;
|
||||||
|
border-radius: 4px;
|
||||||
|
font-size: 14px;
|
||||||
|
color: #606266;
|
||||||
|
transition: all 0.3s;
|
||||||
|
position: relative;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background: #f5f7fa;
|
||||||
|
color: #303133;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.active {
|
||||||
|
background: #1890ff;
|
||||||
|
color: #ffffff;
|
||||||
|
|
||||||
|
.menu-dot {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.menu-dot {
|
||||||
|
display: none;
|
||||||
|
width: 4px;
|
||||||
|
height: 4px;
|
||||||
|
background: #ffffff;
|
||||||
|
border-radius: 50%;
|
||||||
|
margin-right: 8px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.sidebar-footer {
|
||||||
|
border-top: 1px solid #ebeef5;
|
||||||
|
padding-top: 16px;
|
||||||
|
margin-top: 16px;
|
||||||
|
|
||||||
|
.status {
|
||||||
|
font-size: 13px;
|
||||||
|
color: #606266;
|
||||||
|
margin-bottom: 8px;
|
||||||
|
|
||||||
|
.status-processing {
|
||||||
|
color: #1890ff;
|
||||||
|
font-weight: 500;
|
||||||
|
}
|
||||||
|
|
||||||
|
.status-success {
|
||||||
|
color: #52c41a;
|
||||||
|
font-weight: 500;
|
||||||
|
}
|
||||||
|
|
||||||
|
.status-archived {
|
||||||
|
color: #909399;
|
||||||
|
font-weight: 500;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.update-time {
|
||||||
|
font-size: 12px;
|
||||||
|
color: #909399;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 主内容区
|
||||||
|
.main-content {
|
||||||
|
.content-header {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
margin-bottom: 20px;
|
||||||
|
|
||||||
|
.content-title {
|
||||||
|
margin: 0;
|
||||||
|
font-size: 18px;
|
||||||
|
font-weight: 600;
|
||||||
|
color: #303133;
|
||||||
|
}
|
||||||
|
|
||||||
|
.header-actions {
|
||||||
|
display: flex;
|
||||||
|
gap: 12px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 上传模块
|
||||||
|
.upload-section {
|
||||||
|
background: #ffffff;
|
||||||
|
border-radius: 4px;
|
||||||
|
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.05);
|
||||||
|
padding: 20px;
|
||||||
|
margin-bottom: 16px;
|
||||||
|
|
||||||
|
.upload-cards {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: repeat(4, 1fr);
|
||||||
|
gap: 16px;
|
||||||
|
|
||||||
|
.upload-card {
|
||||||
|
border: 1px solid #ebeef5;
|
||||||
|
border-radius: 4px;
|
||||||
|
padding: 20px 16px;
|
||||||
|
text-align: center;
|
||||||
|
transition: all 0.3s;
|
||||||
|
background-color: #fff;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
border-color: #1890ff;
|
||||||
|
box-shadow: 0 4px 12px rgba(24, 144, 255, 0.15);
|
||||||
|
}
|
||||||
|
|
||||||
|
.card-icon {
|
||||||
|
font-size: 32px;
|
||||||
|
color: #1890ff;
|
||||||
|
margin-bottom: 12px;
|
||||||
|
|
||||||
|
i {
|
||||||
|
font-size: 32px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.card-title {
|
||||||
|
font-size: 16px;
|
||||||
|
font-weight: 500;
|
||||||
|
color: #303133;
|
||||||
|
margin-bottom: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.card-desc {
|
||||||
|
font-size: 13px;
|
||||||
|
color: #909399;
|
||||||
|
margin-bottom: 16px;
|
||||||
|
min-height: 36px;
|
||||||
|
line-height: 1.4;
|
||||||
|
}
|
||||||
|
|
||||||
|
.el-upload {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 数据质量检查
|
||||||
|
.quality-check-section {
|
||||||
|
background: #ffffff;
|
||||||
|
border-radius: 4px;
|
||||||
|
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.05);
|
||||||
|
padding: 20px;
|
||||||
|
|
||||||
|
.section-header {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
margin-bottom: 20px;
|
||||||
|
|
||||||
|
.warning-icon {
|
||||||
|
font-size: 18px;
|
||||||
|
color: #fa8c16;
|
||||||
|
margin-right: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
span {
|
||||||
|
font-size: 15px;
|
||||||
|
font-weight: 500;
|
||||||
|
color: #303133;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.metrics {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: repeat(3, 1fr);
|
||||||
|
gap: 32px;
|
||||||
|
|
||||||
|
.metric-card {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
padding: 16px;
|
||||||
|
border: 1px solid #ebeef5;
|
||||||
|
border-radius: 4px;
|
||||||
|
background: #fafafa;
|
||||||
|
|
||||||
|
.metric-title {
|
||||||
|
font-size: 14px;
|
||||||
|
color: #606266;
|
||||||
|
margin-bottom: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.metric-value {
|
||||||
|
font-size: 24px;
|
||||||
|
font-weight: 600;
|
||||||
|
margin-bottom: 12px;
|
||||||
|
|
||||||
|
&.value-success {
|
||||||
|
color: #52c41a;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.value-info {
|
||||||
|
color: #1890ff;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.value-warning {
|
||||||
|
color: #fa8c16;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.value-danger {
|
||||||
|
color: #f5222d;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.progress-ring-container {
|
||||||
|
width: 48px;
|
||||||
|
height: 48px;
|
||||||
|
|
||||||
|
.progress-ring {
|
||||||
|
width: 48px;
|
||||||
|
height: 48px;
|
||||||
|
transform: rotate(-90deg);
|
||||||
|
|
||||||
|
.progress-ring-bg {
|
||||||
|
stroke: #ebeef5;
|
||||||
|
}
|
||||||
|
|
||||||
|
.progress-ring-progress {
|
||||||
|
transition: stroke-dashoffset 0.5s ease;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 上传弹窗样式
|
||||||
|
::v-deep .el-dialog__wrapper {
|
||||||
|
.upload-area {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.el-upload {
|
||||||
|
width: 100%;
|
||||||
|
|
||||||
|
.el-upload-dragger {
|
||||||
|
width: 100%;
|
||||||
|
height: 200px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.el-upload__tip {
|
||||||
|
margin-top: 8px;
|
||||||
|
color: #909399;
|
||||||
|
font-size: 12px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 响应式
|
||||||
|
@media (max-width: 1200px) {
|
||||||
|
.upload-section .upload-cards {
|
||||||
|
grid-template-columns: repeat(2, 1fr);
|
||||||
|
}
|
||||||
|
|
||||||
|
.quality-check-section .metrics {
|
||||||
|
grid-template-columns: repeat(3, 1fr);
|
||||||
|
gap: 16px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 768px) {
|
||||||
|
.upload-data-container {
|
||||||
|
padding: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sidebar {
|
||||||
|
margin-bottom: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.content-header {
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: flex-start;
|
||||||
|
gap: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.upload-section .upload-cards {
|
||||||
|
grid-template-columns: 1fr;
|
||||||
|
}
|
||||||
|
|
||||||
|
.quality-check-section .metrics {
|
||||||
|
grid-template-columns: 1fr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
497
ruoyi-ui/src/views/ccdiProject/detail.vue
Normal file
497
ruoyi-ui/src/views/ccdiProject/detail.vue
Normal file
@@ -0,0 +1,497 @@
|
|||||||
|
<template>
|
||||||
|
<div class="app-container dpc-detail-container">
|
||||||
|
<!-- 原页面头部 (已隐藏,使用UploadData组件的头部) -->
|
||||||
|
<div class="detail-header">
|
||||||
|
<div class="header-left">
|
||||||
|
<el-button size="small" icon="el-icon-back" @click="handleBack"
|
||||||
|
>返回</el-button
|
||||||
|
>
|
||||||
|
<div class="title-section">
|
||||||
|
<div class="page-title">
|
||||||
|
<h2>
|
||||||
|
{{ projectInfo.projectName }}
|
||||||
|
</h2>
|
||||||
|
<el-tag
|
||||||
|
:type="getStatusType(projectInfo.projectStatus)"
|
||||||
|
size="small"
|
||||||
|
>
|
||||||
|
{{ getStatusLabel(projectInfo.projectStatus) }}
|
||||||
|
</el-tag>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<p class="update-time">
|
||||||
|
最后更新时间:{{ formatUpdateTime(projectInfo.updateTime) }}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="header-right">
|
||||||
|
<div class="action-buttons">
|
||||||
|
<el-button
|
||||||
|
size="small"
|
||||||
|
type="primary"
|
||||||
|
icon="el-icon-upload2"
|
||||||
|
@click="handleUploadData"
|
||||||
|
>
|
||||||
|
上传数据
|
||||||
|
</el-button>
|
||||||
|
<el-button
|
||||||
|
size="small"
|
||||||
|
icon="el-icon-setting"
|
||||||
|
@click="handleParamConfig"
|
||||||
|
>
|
||||||
|
参数配置
|
||||||
|
</el-button>
|
||||||
|
<el-dropdown @command="handleCheckResultCommand" trigger="click">
|
||||||
|
<el-button size="small" icon="el-icon-document">
|
||||||
|
初核结果<i class="el-icon-arrow-down el-icon--right"></i>
|
||||||
|
</el-button>
|
||||||
|
<el-dropdown-menu slot="dropdown">
|
||||||
|
<el-dropdown-item command="overview">结果总览</el-dropdown-item>
|
||||||
|
<el-dropdown-item command="special">专项排查</el-dropdown-item>
|
||||||
|
<el-dropdown-item command="detail">流水明细查询</el-dropdown-item>
|
||||||
|
</el-dropdown-menu>
|
||||||
|
</el-dropdown>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 数据上传页面 -->
|
||||||
|
<UploadData
|
||||||
|
:project-id="projectId"
|
||||||
|
:project-info="projectInfo"
|
||||||
|
@menu-change="handleMenuChange"
|
||||||
|
@data-uploaded="handleDataUploaded"
|
||||||
|
@name-selected="handleNameSelected"
|
||||||
|
@generate-report="handleGenerateReport"
|
||||||
|
@fetch-bank-info="handleFetchBankInfo"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import UploadData from "./components/detail/UploadData";
|
||||||
|
// import UploadParams from "./components/detail/UploadParams";
|
||||||
|
// import ParamConfig from "./components/detail/ParamConfig";
|
||||||
|
// import PreliminaryCheck from "./components/detail/PreliminaryCheck";
|
||||||
|
// import SpecialCheck from "./components/detail/SpecialCheck";
|
||||||
|
// import DetailQuery from './components/detail/DetailQuery'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: "ProjectDetail",
|
||||||
|
components: {
|
||||||
|
UploadData,
|
||||||
|
// UploadParams,
|
||||||
|
// ParamConfig,
|
||||||
|
// PreliminaryCheck,
|
||||||
|
// SpecialCheck,
|
||||||
|
// DetailQuery,
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
// 当前标签页
|
||||||
|
activeTab: "data",
|
||||||
|
// 项目ID
|
||||||
|
projectId: this.$route.params.projectId,
|
||||||
|
// 项目信息
|
||||||
|
projectInfo: {
|
||||||
|
projectId: this.$route.params.projectId,
|
||||||
|
projectName: "",
|
||||||
|
projectDesc: "",
|
||||||
|
createTime: "",
|
||||||
|
updateTime: "",
|
||||||
|
startDate: "",
|
||||||
|
endDate: "",
|
||||||
|
targetCount: 0,
|
||||||
|
warningCount: 0,
|
||||||
|
warningThreshold: 60,
|
||||||
|
projectStatus: "0",
|
||||||
|
},
|
||||||
|
};
|
||||||
|
},
|
||||||
|
watch: {
|
||||||
|
"$route.params.projectId"(newId) {
|
||||||
|
if (newId) {
|
||||||
|
this.projectId = newId;
|
||||||
|
this.projectInfo.projectId = newId;
|
||||||
|
this.initPageData();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
created() {
|
||||||
|
// 初始化页面数据
|
||||||
|
this.initPageData();
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
/** 初始化页面数据 */
|
||||||
|
initPageData() {
|
||||||
|
// 这里应该从API获取项目详细信息
|
||||||
|
this.mockProjectInfo();
|
||||||
|
},
|
||||||
|
/** 格式化更新时间 */
|
||||||
|
formatUpdateTime(time) {
|
||||||
|
if (!time) return "-";
|
||||||
|
const date = new Date(time);
|
||||||
|
const year = date.getFullYear();
|
||||||
|
const month = String(date.getMonth() + 1).padStart(2, "0");
|
||||||
|
const day = String(date.getDate()).padStart(2, "0");
|
||||||
|
const hours = String(date.getHours()).padStart(2, "0");
|
||||||
|
const minutes = String(date.getMinutes()).padStart(2, "0");
|
||||||
|
const seconds = String(date.getSeconds()).padStart(2, "0");
|
||||||
|
return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`;
|
||||||
|
},
|
||||||
|
/** 模拟项目信息 */
|
||||||
|
mockProjectInfo() {
|
||||||
|
// 模拟数据,实际应该调用API
|
||||||
|
this.projectInfo = {
|
||||||
|
projectId: this.projectId,
|
||||||
|
projectName: "2024年Q1初核项目",
|
||||||
|
projectDesc: "第一季度员工异常行为排查",
|
||||||
|
createTime: "2024-01-01 10:00:00",
|
||||||
|
updateTime: new Date().toISOString(),
|
||||||
|
startDate: "2024-01-01",
|
||||||
|
endDate: "2024-03-31",
|
||||||
|
targetCount: 500,
|
||||||
|
warningCount: 15,
|
||||||
|
warningThreshold: 60,
|
||||||
|
projectStatus: "0",
|
||||||
|
};
|
||||||
|
},
|
||||||
|
/** 获取状态类型 */
|
||||||
|
getStatusType(status) {
|
||||||
|
const statusMap = {
|
||||||
|
0: "primary", // 进行中
|
||||||
|
1: "success", // 已完成
|
||||||
|
2: "info", // 已归档
|
||||||
|
};
|
||||||
|
return statusMap[status] || "info";
|
||||||
|
},
|
||||||
|
/** 获取状态标签 */
|
||||||
|
getStatusLabel(status) {
|
||||||
|
const statusMap = {
|
||||||
|
0: "进行中",
|
||||||
|
1: "已完成",
|
||||||
|
2: "已归档",
|
||||||
|
};
|
||||||
|
return statusMap[status] || "未知";
|
||||||
|
},
|
||||||
|
/** 标签页切换 */
|
||||||
|
handleTabChange(tab) {
|
||||||
|
console.log("切换到标签页:", tab.name);
|
||||||
|
},
|
||||||
|
/** 返回列表页 */
|
||||||
|
handleBack() {
|
||||||
|
this.$router.push("/ccdiProject");
|
||||||
|
},
|
||||||
|
/** UploadData 组件:菜单切换 */
|
||||||
|
handleMenuChange({ key, route }) {
|
||||||
|
console.log("切换到菜单:", key, route);
|
||||||
|
// 根据不同的菜单项跳转到不同的组件或页面
|
||||||
|
switch (route) {
|
||||||
|
case "config":
|
||||||
|
this.$message.info("参数配置功能开发中");
|
||||||
|
break;
|
||||||
|
case "overview":
|
||||||
|
this.$message.info("结果总览功能开发中");
|
||||||
|
break;
|
||||||
|
case "special":
|
||||||
|
this.$message.info("专项排查功能开发中");
|
||||||
|
break;
|
||||||
|
case "detail":
|
||||||
|
this.$message.info("流水明细查询功能开发中");
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
/** UploadData 组件:数据上传完成 */
|
||||||
|
handleDataUploaded({ type }) {
|
||||||
|
console.log("数据上传完成:", type);
|
||||||
|
this.$message.success(`${type} 数据上传成功`);
|
||||||
|
},
|
||||||
|
/** UploadData 组件:名单选择完成 */
|
||||||
|
handleNameSelected(nameList) {
|
||||||
|
console.log("名单选择完成:", nameList);
|
||||||
|
this.$message.success("名单选择成功");
|
||||||
|
},
|
||||||
|
/** UploadData 组件:生成报告 */
|
||||||
|
handleGenerateReport() {
|
||||||
|
console.log("生成报告");
|
||||||
|
// this.$message.info("生成报告功能开发中");
|
||||||
|
},
|
||||||
|
/** UploadData 组件:拉取本行信息 */
|
||||||
|
handleFetchBankInfo() {
|
||||||
|
console.log("拉取本行信息");
|
||||||
|
this.$message.info("拉取本行信息功能开发中");
|
||||||
|
},
|
||||||
|
/** 上传数据 (原方法,已由UploadData组件处理) */
|
||||||
|
handleUploadData() {
|
||||||
|
console.log("上传数据");
|
||||||
|
this.$message.info("上传数据功能已迁移至上传页面");
|
||||||
|
},
|
||||||
|
/** 参数配置 (原方法) */
|
||||||
|
handleParamConfig() {
|
||||||
|
console.log("参数配置");
|
||||||
|
this.$message.info("参数配置功能开发中");
|
||||||
|
},
|
||||||
|
/** 初核结果下拉菜单命令 */
|
||||||
|
handleCheckResultCommand(command) {
|
||||||
|
console.log("初核结果命令:", command);
|
||||||
|
switch (command) {
|
||||||
|
case "overview":
|
||||||
|
this.$message.info("结果总览功能开发中");
|
||||||
|
break;
|
||||||
|
case "special":
|
||||||
|
this.$message.info("专项排查功能开发中");
|
||||||
|
break;
|
||||||
|
case "detail":
|
||||||
|
this.$message.info("流水明细查询功能开发中");
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
/** 数据上传完成 */
|
||||||
|
handleDataUploaded() {
|
||||||
|
console.log("数据上传完成");
|
||||||
|
this.$message.success("数据上传成功");
|
||||||
|
},
|
||||||
|
/** 刷新页面 */
|
||||||
|
handleRefresh() {
|
||||||
|
this.mockProjectInfo();
|
||||||
|
this.$message.success("刷新成功");
|
||||||
|
},
|
||||||
|
/** 导出报告 */
|
||||||
|
handleExport() {
|
||||||
|
console.log("导出报告");
|
||||||
|
this.$message.info("报告导出功能开发中");
|
||||||
|
},
|
||||||
|
/** 完成项目 */
|
||||||
|
handleComplete() {
|
||||||
|
this.$confirm("确定要完成当前项目吗?", "提示", {
|
||||||
|
confirmButtonText: "确定",
|
||||||
|
cancelButtonText: "取消",
|
||||||
|
type: "warning",
|
||||||
|
})
|
||||||
|
.then(() => {
|
||||||
|
this.$message.success("项目已完成");
|
||||||
|
this.projectInfo.projectStatus = "1";
|
||||||
|
})
|
||||||
|
.catch(() => {
|
||||||
|
this.$message.info("已取消");
|
||||||
|
});
|
||||||
|
},
|
||||||
|
/** 归档项目 */
|
||||||
|
handleArchive() {
|
||||||
|
this.$confirm(
|
||||||
|
"确定要归档当前项目吗?归档后将不能进行修改操作。",
|
||||||
|
"警告",
|
||||||
|
{
|
||||||
|
confirmButtonText: "确定",
|
||||||
|
cancelButtonText: "取消",
|
||||||
|
type: "warning",
|
||||||
|
}
|
||||||
|
)
|
||||||
|
.then(() => {
|
||||||
|
this.$message.success("项目已归档");
|
||||||
|
this.projectInfo.projectStatus = "2";
|
||||||
|
})
|
||||||
|
.catch(() => {
|
||||||
|
this.$message.info("已取消");
|
||||||
|
});
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.dpc-detail-container {
|
||||||
|
padding: 16px;
|
||||||
|
background: #f0f2f5;
|
||||||
|
min-height: calc(100vh - 84px);
|
||||||
|
}
|
||||||
|
|
||||||
|
.detail-header {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
margin-bottom: 16px;
|
||||||
|
padding: 16px 20px;
|
||||||
|
background: #ffffff;
|
||||||
|
border-radius: 4px;
|
||||||
|
box-shadow: 0 1px 4px rgba(0, 0, 0, 0.08);
|
||||||
|
|
||||||
|
.header-left {
|
||||||
|
display: flex;
|
||||||
|
align-items: flex-start;
|
||||||
|
gap: 12px;
|
||||||
|
|
||||||
|
.el-button {
|
||||||
|
padding: 8px 12px;
|
||||||
|
font-size: 13px;
|
||||||
|
margin-top: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.title-section {
|
||||||
|
.page-title {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
h2 {
|
||||||
|
margin: 0 0 4px 0;
|
||||||
|
font-size: 20px;
|
||||||
|
font-weight: 500;
|
||||||
|
color: #303133;
|
||||||
|
margin-right: 5px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.update-time {
|
||||||
|
margin: 0;
|
||||||
|
font-size: 13px;
|
||||||
|
color: #909399;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.header-right {
|
||||||
|
.action-buttons {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 12px;
|
||||||
|
|
||||||
|
.el-button {
|
||||||
|
padding: 8px 16px;
|
||||||
|
font-size: 14px;
|
||||||
|
|
||||||
|
.el-icon--right {
|
||||||
|
margin-left: 4px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.el-tag {
|
||||||
|
margin-left: 4px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.info-card {
|
||||||
|
margin-bottom: 16px;
|
||||||
|
|
||||||
|
:deep(.el-card__body) {
|
||||||
|
padding: 20px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.info-header {
|
||||||
|
margin-bottom: 16px;
|
||||||
|
|
||||||
|
h3 {
|
||||||
|
margin: 0;
|
||||||
|
font-size: 16px;
|
||||||
|
font-weight: 500;
|
||||||
|
color: #303133;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.info-content {
|
||||||
|
.info-row {
|
||||||
|
display: flex;
|
||||||
|
gap: 32px;
|
||||||
|
margin-bottom: 12px;
|
||||||
|
|
||||||
|
&:last-child {
|
||||||
|
margin-bottom: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.info-item {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
font-size: 14px;
|
||||||
|
|
||||||
|
.label {
|
||||||
|
color: #606266;
|
||||||
|
min-width: 100px;
|
||||||
|
font-weight: 500;
|
||||||
|
}
|
||||||
|
|
||||||
|
.value {
|
||||||
|
color: #303133;
|
||||||
|
font-weight: 400;
|
||||||
|
|
||||||
|
&.warning-count {
|
||||||
|
color: #e6a23c;
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.content-card {
|
||||||
|
margin-bottom: 16px;
|
||||||
|
|
||||||
|
:deep(.el-card__body) {
|
||||||
|
padding: 0;
|
||||||
|
|
||||||
|
.el-tabs {
|
||||||
|
height: 100%;
|
||||||
|
|
||||||
|
.el-tabs__content {
|
||||||
|
padding: 20px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.action-bar {
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
gap: 12px;
|
||||||
|
padding: 16px;
|
||||||
|
background: #ffffff;
|
||||||
|
border-radius: 4px;
|
||||||
|
box-shadow: 0 1px 4px rgba(0, 0, 0, 0.08);
|
||||||
|
|
||||||
|
.el-button {
|
||||||
|
padding: 10px 20px;
|
||||||
|
|
||||||
|
i {
|
||||||
|
margin-right: 4px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 响应式设计
|
||||||
|
@media (max-width: 768px) {
|
||||||
|
.dpc-detail-container {
|
||||||
|
padding: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.detail-header {
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: flex-start;
|
||||||
|
gap: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.info-content {
|
||||||
|
.info-row {
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 8px;
|
||||||
|
|
||||||
|
.info-item {
|
||||||
|
.label {
|
||||||
|
min-width: auto;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.action-bar {
|
||||||
|
flex-wrap: wrap;
|
||||||
|
|
||||||
|
.el-button {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -63,23 +63,23 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import {getMockProjectList} from '@/api/ccdiProject'
|
import { getMockProjectList } from "@/api/ccdiProject";
|
||||||
import SearchBar from './components/SearchBar'
|
import SearchBar from "./components/SearchBar";
|
||||||
import ProjectTable from './components/ProjectTable'
|
import ProjectTable from "./components/ProjectTable";
|
||||||
import QuickEntry from './components/QuickEntry'
|
import QuickEntry from "./components/QuickEntry";
|
||||||
import AddProjectDialog from './components/AddProjectDialog'
|
import AddProjectDialog from "./components/AddProjectDialog";
|
||||||
import ImportHistoryDialog from './components/ImportHistoryDialog'
|
import ImportHistoryDialog from "./components/ImportHistoryDialog";
|
||||||
import ArchiveConfirmDialog from './components/ArchiveConfirmDialog'
|
import ArchiveConfirmDialog from "./components/ArchiveConfirmDialog";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'DpcProject',
|
name: "DpcProject",
|
||||||
components: {
|
components: {
|
||||||
SearchBar,
|
SearchBar,
|
||||||
ProjectTable,
|
ProjectTable,
|
||||||
QuickEntry,
|
QuickEntry,
|
||||||
AddProjectDialog,
|
AddProjectDialog,
|
||||||
ImportHistoryDialog,
|
ImportHistoryDialog,
|
||||||
ArchiveConfirmDialog
|
ArchiveConfirmDialog,
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
@@ -96,141 +96,145 @@ export default {
|
|||||||
pageNum: 1,
|
pageNum: 1,
|
||||||
pageSize: 10,
|
pageSize: 10,
|
||||||
projectName: null,
|
projectName: null,
|
||||||
projectStatus: null
|
projectStatus: null,
|
||||||
},
|
},
|
||||||
// 新增/编辑弹窗
|
// 新增/编辑弹窗
|
||||||
addDialogVisible: false,
|
addDialogVisible: false,
|
||||||
addDialogTitle: '新建项目',
|
addDialogTitle: "新建项目",
|
||||||
projectForm: {},
|
projectForm: {},
|
||||||
// 导入历史项目弹窗
|
// 导入历史项目弹窗
|
||||||
importDialogVisible: false,
|
importDialogVisible: false,
|
||||||
// 归档确认弹窗
|
// 归档确认弹窗
|
||||||
archiveDialogVisible: false,
|
archiveDialogVisible: false,
|
||||||
currentArchiveProject: null
|
currentArchiveProject: null,
|
||||||
}
|
};
|
||||||
},
|
},
|
||||||
created() {
|
created() {
|
||||||
this.getList()
|
this.getList();
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
/** 查询项目列表 */
|
/** 查询项目列表 */
|
||||||
getList() {
|
getList() {
|
||||||
this.loading = true
|
this.loading = true;
|
||||||
// 使用Mock数据
|
// 使用Mock数据
|
||||||
getMockProjectList().then(response => {
|
getMockProjectList()
|
||||||
this.projectList = response.rows
|
.then((response) => {
|
||||||
this.total = response.total
|
this.projectList = response.rows;
|
||||||
this.loading = false
|
this.total = response.total;
|
||||||
}).catch(() => {
|
this.loading = false;
|
||||||
this.loading = false
|
|
||||||
})
|
})
|
||||||
|
.catch(() => {
|
||||||
|
this.loading = false;
|
||||||
|
});
|
||||||
},
|
},
|
||||||
/** 搜索按钮操作 */
|
/** 搜索按钮操作 */
|
||||||
handleQuery(queryParams) {
|
handleQuery(queryParams) {
|
||||||
if (queryParams) {
|
if (queryParams) {
|
||||||
this.queryParams = { ...this.queryParams, ...queryParams }
|
this.queryParams = { ...this.queryParams, ...queryParams };
|
||||||
}
|
}
|
||||||
this.queryParams.pageNum = 1
|
this.queryParams.pageNum = 1;
|
||||||
this.getList()
|
this.getList();
|
||||||
},
|
},
|
||||||
/** 新增按钮操作 */
|
/** 新增按钮操作 */
|
||||||
handleAdd() {
|
handleAdd() {
|
||||||
this.projectForm = this.getEmptyForm()
|
this.projectForm = this.getEmptyForm();
|
||||||
this.addDialogTitle = '新建项目'
|
this.addDialogTitle = "新建项目";
|
||||||
this.addDialogVisible = true
|
this.addDialogVisible = true;
|
||||||
},
|
},
|
||||||
/** 获取空表单 */
|
/** 获取空表单 */
|
||||||
getEmptyForm() {
|
getEmptyForm() {
|
||||||
return {
|
return {
|
||||||
projectId: null,
|
projectId: null,
|
||||||
projectName: '',
|
projectName: "",
|
||||||
projectDesc: '',
|
projectDesc: "",
|
||||||
startDate: '',
|
startDate: "",
|
||||||
endDate: '',
|
endDate: "",
|
||||||
targetCount: 0,
|
targetCount: 0,
|
||||||
targetPersons: []
|
targetPersons: [],
|
||||||
}
|
};
|
||||||
},
|
},
|
||||||
/** 关闭新增弹窗 */
|
/** 关闭新增弹窗 */
|
||||||
handleCloseAddDialog() {
|
handleCloseAddDialog() {
|
||||||
this.addDialogVisible = false
|
this.addDialogVisible = false;
|
||||||
this.projectForm = {}
|
this.projectForm = {};
|
||||||
},
|
},
|
||||||
/** 提交项目表单 */
|
/** 提交项目表单 */
|
||||||
handleSubmitProject(data) {
|
handleSubmitProject(data) {
|
||||||
// 这里应该调用实际的API
|
// 这里应该调用实际的API
|
||||||
console.log('提交项目数据:', data)
|
console.log("提交项目数据:", data);
|
||||||
this.$modal.msgSuccess('项目创建成功')
|
this.$modal.msgSuccess("项目创建成功");
|
||||||
this.addDialogVisible = false
|
this.addDialogVisible = false;
|
||||||
this.getList()
|
this.getList();
|
||||||
},
|
},
|
||||||
/** 导入历史项目 */
|
/** 导入历史项目 */
|
||||||
handleImport() {
|
handleImport() {
|
||||||
this.importDialogVisible = true
|
this.importDialogVisible = true;
|
||||||
},
|
},
|
||||||
/** 关闭导入弹窗 */
|
/** 关闭导入弹窗 */
|
||||||
handleCloseImportDialog() {
|
handleCloseImportDialog() {
|
||||||
this.importDialogVisible = false
|
this.importDialogVisible = false;
|
||||||
},
|
},
|
||||||
/** 提交导入 */
|
/** 提交导入 */
|
||||||
handleSubmitImport(data) {
|
handleSubmitImport(data) {
|
||||||
console.log('导入历史项目:', data)
|
console.log("导入历史项目:", data);
|
||||||
this.$modal.msgSuccess('项目导入成功')
|
this.$modal.msgSuccess("项目导入成功");
|
||||||
this.importDialogVisible = false
|
this.importDialogVisible = false;
|
||||||
this.getList()
|
this.getList();
|
||||||
},
|
},
|
||||||
/** 创建季度初核 */
|
/** 创建季度初核 */
|
||||||
handleCreateQuarterly() {
|
handleCreateQuarterly() {
|
||||||
this.projectForm = this.getEmptyForm()
|
this.projectForm = this.getEmptyForm();
|
||||||
this.addDialogTitle = '创建季度初核项目'
|
this.addDialogTitle = "创建季度初核项目";
|
||||||
this.addDialogVisible = true
|
this.addDialogVisible = true;
|
||||||
},
|
},
|
||||||
/** 创建新员工排查 */
|
/** 创建新员工排查 */
|
||||||
handleCreateEmployee() {
|
handleCreateEmployee() {
|
||||||
this.projectForm = this.getEmptyForm()
|
this.projectForm = this.getEmptyForm();
|
||||||
this.addDialogTitle = '创建新员工排查项目'
|
this.addDialogTitle = "创建新员工排查项目";
|
||||||
this.addDialogVisible = true
|
this.addDialogVisible = true;
|
||||||
},
|
},
|
||||||
/** 创建高风险专项 */
|
/** 创建高风险专项 */
|
||||||
handleCreateHighRisk() {
|
handleCreateHighRisk() {
|
||||||
this.projectForm = this.getEmptyForm()
|
this.projectForm = this.getEmptyForm();
|
||||||
this.addDialogTitle = '创建高风险专项项目'
|
this.addDialogTitle = "创建高风险专项项目";
|
||||||
this.addDialogVisible = true
|
this.addDialogVisible = true;
|
||||||
},
|
},
|
||||||
/** 查看详情 */
|
/** 查看详情 */
|
||||||
handleDetail(row) {
|
handleDetail(row) {
|
||||||
console.log('查看详情:', row)
|
console.log("查看详情:", row);
|
||||||
this.$modal.msgInfo('查看项目详情: ' + row.projectName)
|
this.$modal.msgInfo("查看项目详情: " + row.projectName);
|
||||||
},
|
},
|
||||||
/** 进入项目 */
|
/** 进入项目 */
|
||||||
handleEnter(row) {
|
handleEnter(row) {
|
||||||
console.log('进入项目:', row)
|
this.$router.push({
|
||||||
this.$modal.msgSuccess('进入项目: ' + row.projectName)
|
path: `ccdiProject/detail/${row.projectId}`,
|
||||||
|
});
|
||||||
|
// this.$modal.msgSuccess("进入项目: " + row.projectName);
|
||||||
},
|
},
|
||||||
/** 查看结果 */
|
/** 查看结果 */
|
||||||
handleViewResult(row) {
|
handleViewResult(row) {
|
||||||
console.log('查看结果:', row)
|
console.log("查看结果:", row);
|
||||||
this.$modal.msgInfo('查看项目结果: ' + row.projectName)
|
this.$modal.msgInfo("查看项目结果: " + row.projectName);
|
||||||
},
|
},
|
||||||
/** 重新分析 */
|
/** 重新分析 */
|
||||||
handleReAnalyze(row) {
|
handleReAnalyze(row) {
|
||||||
console.log('重新分析:', row)
|
console.log("重新分析:", row);
|
||||||
this.$modal.msgSuccess('正在重新分析项目: ' + row.projectName)
|
this.$modal.msgSuccess("正在重新分析项目: " + row.projectName);
|
||||||
},
|
},
|
||||||
/** 归档项目 */
|
/** 归档项目 */
|
||||||
handleArchive(row) {
|
handleArchive(row) {
|
||||||
this.currentArchiveProject = row
|
this.currentArchiveProject = row;
|
||||||
this.archiveDialogVisible = true
|
this.archiveDialogVisible = true;
|
||||||
},
|
},
|
||||||
/** 确认归档 */
|
/** 确认归档 */
|
||||||
handleConfirmArchive(data) {
|
handleConfirmArchive(data) {
|
||||||
console.log('确认归档:', data)
|
console.log("确认归档:", data);
|
||||||
this.$modal.msgSuccess('项目已归档')
|
this.$modal.msgSuccess("项目已归档");
|
||||||
this.archiveDialogVisible = false
|
this.archiveDialogVisible = false;
|
||||||
this.getList()
|
this.getList();
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
}
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
|
|||||||
Reference in New Issue
Block a user