Files
ccdi/ruoyi-ui/src/views/ccdiProject/detail.vue

573 lines
14 KiB
Vue
Raw Normal View History

2026-03-02 19:18:45 +08:00
<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">
<el-menu
:default-active="activeTab"
mode="horizontal"
@select="handleMenuSelect"
class="nav-menu"
>
<el-menu-item index="upload">上传数据</el-menu-item>
<el-menu-item index="config">参数配置</el-menu-item>
<el-menu-item index="overview">结果总览</el-menu-item>
<el-menu-item index="special">专项排查</el-menu-item>
<el-menu-item index="detail">流水明细查询</el-menu-item>
</el-menu>
2026-03-02 19:18:45 +08:00
</div>
</div>
<!-- 动态组件渲染区域 -->
<component
:is="currentComponent"
2026-03-02 19:18:45 +08:00
: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 ParamConfig from "./components/detail/ParamConfig";
import PreliminaryCheck from "./components/detail/PreliminaryCheck";
import SpecialCheck from "./components/detail/SpecialCheck";
import DetailQuery from "./components/detail/DetailQuery";
2026-03-05 15:53:56 +08:00
import {getProject} from "@/api/ccdiProject";
2026-03-02 19:18:45 +08:00
export default {
name: "ProjectDetail",
components: {
UploadData,
ParamConfig,
PreliminaryCheck,
SpecialCheck,
DetailQuery,
2026-03-02 19:18:45 +08:00
},
data() {
return {
// 当前激活的菜单项索引
activeTab: "upload",
// 当前显示的组件名称
currentComponent: "UploadData",
2026-03-02 19:18:45 +08:00
// 项目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.initActiveTabFromRoute();
2026-03-02 19:18:45 +08:00
this.initPageData();
}
},
"$route.query.tab"() {
this.initActiveTabFromRoute();
},
2026-03-02 19:18:45 +08:00
},
created() {
// 初始化页面数据
this.initActiveTabFromRoute();
2026-03-02 19:18:45 +08:00
this.initPageData();
},
methods: {
initActiveTabFromRoute() {
const tab = (this.$route.query && this.$route.query.tab) || "";
const validTabs = ["upload", "config", "overview", "special", "detail"];
const targetTab = validTabs.includes(tab) ? tab : "upload";
this.setActiveTab(targetTab);
},
setActiveTab(index) {
this.activeTab = index;
const componentMap = {
upload: "UploadData",
config: "ParamConfig",
overview: "PreliminaryCheck",
special: "SpecialCheck",
detail: "DetailQuery",
};
this.currentComponent = componentMap[index] || "UploadData";
},
2026-03-02 19:18:45 +08:00
/** 初始化页面数据 */
initPageData() {
// 这里应该从API获取项目详细信息
2026-03-05 15:53:56 +08:00
if (!this.projectId) {
return;
}
this.projectInfo.projectName = "";
this.updatePageTitle();
getProject(this.projectId)
.then((res) => {
const data = res.data || {};
this.projectInfo = {
...this.projectInfo,
...data,
projectId: data.projectId || this.projectId,
projectName: data.projectName || "",
projectDesc: data.projectDesc || data.description || "",
projectStatus: String(
data.projectStatus !== undefined && data.projectStatus !== null
? data.projectStatus
: data.status !== undefined && data.status !== null
? data.status
: this.projectInfo.projectStatus
),
};
this.updatePageTitle();
})
.catch(() => {
this.$message.error("Failed to load project details");
this.updatePageTitle();
});
},
updatePageTitle() {
const title = this.projectInfo.projectName || `ProjectDetail-${this.projectId}`;
this.$route.meta.title = title;
this.$store.dispatch("settings/setTitle", title);
this.$store.dispatch("tagsView/updateVisitedView", {
path: this.$route.path,
title,
});
2026-03-02 19:18:45 +08:00
},
/** 格式化更新时间 */
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");
},
/** 菜单选择事件 */
handleMenuSelect(index) {
console.log("菜单选择:", index);
this.setActiveTab(index);
},
2026-03-02 19:18:45 +08:00
/** UploadData 组件:菜单切换 */
handleMenuChange({ key, route }) {
console.log("切换到菜单:", key, route);
// 直接触发菜单选择
this.handleMenuSelect(route);
2026-03-02 19:18:45 +08:00
},
/** 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("拉取本行信息功能开发中");
},
/** 数据上传完成 */
handleDataUploaded() {
console.log("数据上传完成");
this.$message.success("数据上传成功");
},
/** 刷新页面 */
handleRefresh() {
2026-03-05 15:53:56 +08:00
this.initPageData();
2026-03-02 19:18:45 +08:00
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 {
display: flex;
align-items: center;
.nav-menu {
// 移除默认背景色和边框
background-color: transparent;
border-bottom: none;
// 菜单项基础样式
.el-menu-item,
.el-submenu__title {
2026-03-02 19:18:45 +08:00
font-size: 14px;
color: #606266;
padding: 0 16px;
height: 40px;
line-height: 40px;
border-bottom: 2px solid transparent;
&:hover {
background-color: #f5f7fa;
color: #303133;
2026-03-02 19:18:45 +08:00
}
}
// 子菜单容器高度统一
.el-submenu {
height: 40px;
line-height: 40px;
}
// 激活状态:底部下划线 + 蓝色文字
.el-menu-item.is-active {
color: #1890ff;
border-bottom: 2px solid #1890ff;
background-color: transparent;
}
// 下拉菜单激活状态
.el-submenu.is-active > .el-submenu__title {
color: #1890ff;
border-bottom: 2px solid #1890ff;
}
// 下拉菜单图标
.el-submenu__icon-arrow {
2026-03-02 19:18:45 +08:00
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;
.header-right {
width: 100%;
margin-top: 12px;
.nav-menu {
width: 100%;
display: flex;
justify-content: flex-start;
.el-menu-item,
.el-submenu {
flex: 1;
text-align: center;
padding: 0 8px;
font-size: 13px;
}
}
}
2026-03-02 19:18:45 +08:00
}
.info-content {
.info-row {
flex-direction: column;
gap: 8px;
.info-item {
.label {
min-width: auto;
}
}
}
}
.action-bar {
flex-wrap: wrap;
.el-button {
width: 100%;
}
}
}
// 下拉菜单弹窗样式
::v-deep .el-menu--popup {
min-width: 140px;
.el-menu-item {
font-size: 14px;
&:hover {
background-color: #f5f7fa;
}
&.is-active {
color: #1890ff;
background-color: #e6f7ff;
}
}
}
2026-03-02 19:18:45 +08:00
</style>