项管首页
This commit is contained in:
@@ -30,7 +30,12 @@
|
|||||||
"Skill(superpowers:using-superpowers)",
|
"Skill(superpowers:using-superpowers)",
|
||||||
"Bash(tree:*)",
|
"Bash(tree:*)",
|
||||||
"Skill(docx)",
|
"Skill(docx)",
|
||||||
"Bash(bash:*)"
|
"Bash(bash:*)",
|
||||||
|
"mcp__zai-mcp-server__analyze_image",
|
||||||
|
"Skill(frontend-design:frontend-design)",
|
||||||
|
"mcp__web-reader__webReader",
|
||||||
|
"mcp__fetch__imageFetch",
|
||||||
|
"Skill(frontend-design)"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"enabledMcpjsonServers": [
|
"enabledMcpjsonServers": [
|
||||||
|
|||||||
Binary file not shown.
|
Before Width: | Height: | Size: 50 KiB |
BIN
doc/other/ScreenShot_2026-01-30_091448_399.png
Normal file
BIN
doc/other/ScreenShot_2026-01-30_091448_399.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 161 KiB |
157
ruoyi-ui/src/api/dpcProject.js
Normal file
157
ruoyi-ui/src/api/dpcProject.js
Normal file
@@ -0,0 +1,157 @@
|
|||||||
|
import request from '@/utils/request'
|
||||||
|
|
||||||
|
// 查询初核项目列表
|
||||||
|
export function listProject(query) {
|
||||||
|
return request({
|
||||||
|
url: '/dpc/project/list',
|
||||||
|
method: 'get',
|
||||||
|
params: query
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 查询初核项目详细
|
||||||
|
export function getProject(projectId) {
|
||||||
|
return request({
|
||||||
|
url: '/dpc/project/' + projectId,
|
||||||
|
method: 'get'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 新增初核项目
|
||||||
|
export function addProject(data) {
|
||||||
|
return request({
|
||||||
|
url: '/dpc/project',
|
||||||
|
method: 'post',
|
||||||
|
data: data
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 修改初核项目
|
||||||
|
export function updateProject(data) {
|
||||||
|
return request({
|
||||||
|
url: '/dpc/project',
|
||||||
|
method: 'put',
|
||||||
|
data: data
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 删除初核项目
|
||||||
|
export function delProject(projectIds) {
|
||||||
|
return request({
|
||||||
|
url: '/dpc/project/' + projectIds,
|
||||||
|
method: 'delete'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 导出初核项目
|
||||||
|
export function exportProject(query) {
|
||||||
|
return request({
|
||||||
|
url: '/dpc/project/export',
|
||||||
|
method: 'get',
|
||||||
|
params: query
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 刷新项目预警人数
|
||||||
|
export function refreshWarningCount(projectId) {
|
||||||
|
return request({
|
||||||
|
url: '/dpc/project/' + projectId + '/warning',
|
||||||
|
method: 'post'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 归档项目
|
||||||
|
export function archiveProject(projectId) {
|
||||||
|
return request({
|
||||||
|
url: '/dpc/project/' + projectId + '/archive',
|
||||||
|
method: 'post'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取历史项目列表(用于导入)
|
||||||
|
export function listHistoryProjects(query) {
|
||||||
|
return request({
|
||||||
|
url: '/dpc/project/history',
|
||||||
|
method: 'get',
|
||||||
|
params: query
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 从历史项目导入
|
||||||
|
export function importFromHistory(data) {
|
||||||
|
return request({
|
||||||
|
url: '/dpc/project/import',
|
||||||
|
method: 'post',
|
||||||
|
data: data
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// Mock数据:获取项目列表
|
||||||
|
export function getMockProjectList() {
|
||||||
|
return Promise.resolve({
|
||||||
|
code: 200,
|
||||||
|
total: 3,
|
||||||
|
rows: [
|
||||||
|
{
|
||||||
|
projectId: 1,
|
||||||
|
projectName: '2024年Q1初核',
|
||||||
|
projectDesc: '2024年第一季度纪检初核排查工作',
|
||||||
|
createTime: '2024-01-01',
|
||||||
|
projectStatus: '0',
|
||||||
|
targetCount: 500,
|
||||||
|
warningCount: 15,
|
||||||
|
startDate: '2024-01-01',
|
||||||
|
endDate: '2024-03-31'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
projectId: 2,
|
||||||
|
projectName: '2023年Q4初核',
|
||||||
|
projectDesc: '2023年第四季度纪检初核排查工作',
|
||||||
|
createTime: '2023-10-01',
|
||||||
|
projectStatus: '1',
|
||||||
|
targetCount: 480,
|
||||||
|
warningCount: 23,
|
||||||
|
startDate: '2023-10-01',
|
||||||
|
endDate: '2023-12-31'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
projectId: 3,
|
||||||
|
projectName: '2023年Q3初核',
|
||||||
|
projectDesc: '2023年第三季度纪检初核排查工作',
|
||||||
|
createTime: '2023-07-01',
|
||||||
|
projectStatus: '2',
|
||||||
|
targetCount: 450,
|
||||||
|
warningCount: 18,
|
||||||
|
startDate: '2023-07-01',
|
||||||
|
endDate: '2023-09-30'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// Mock数据:获取历史项目列表
|
||||||
|
export function getMockHistoryProjects() {
|
||||||
|
return Promise.resolve({
|
||||||
|
code: 200,
|
||||||
|
data: [
|
||||||
|
{
|
||||||
|
projectId: 3,
|
||||||
|
projectName: '2023年Q3初核',
|
||||||
|
projectDesc: '2023年第三季度纪检初核排查工作',
|
||||||
|
createTime: '2023-07-01',
|
||||||
|
projectStatus: '2',
|
||||||
|
targetCount: 450,
|
||||||
|
warningCount: 18
|
||||||
|
},
|
||||||
|
{
|
||||||
|
projectId: 4,
|
||||||
|
projectName: '2023年Q2初核',
|
||||||
|
projectDesc: '2023年第二季度纪检初核排查工作',
|
||||||
|
createTime: '2023-04-01',
|
||||||
|
projectStatus: '2',
|
||||||
|
targetCount: 420,
|
||||||
|
warningCount: 12
|
||||||
|
}
|
||||||
|
]
|
||||||
|
})
|
||||||
|
}
|
||||||
@@ -45,10 +45,6 @@ export default {
|
|||||||
} else {
|
} else {
|
||||||
matched = router.matched.filter(item => item.meta && item.meta.title)
|
matched = router.matched.filter(item => item.meta && item.meta.title)
|
||||||
}
|
}
|
||||||
// 判断是否为首页
|
|
||||||
if (!this.isDashboard(matched[0])) {
|
|
||||||
matched = [{ path: "/index", meta: { title: "首页" } }].concat(matched)
|
|
||||||
}
|
|
||||||
this.levelList = matched.filter(item => item.meta && item.meta.title && item.meta.breadcrumb !== false)
|
this.levelList = matched.filter(item => item.meta && item.meta.title && item.meta.breadcrumb !== false)
|
||||||
},
|
},
|
||||||
findPathNum(str, char = "/") {
|
findPathNum(str, char = "/") {
|
||||||
|
|||||||
@@ -161,6 +161,10 @@ export default {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
closeSelectedTag(view) {
|
closeSelectedTag(view) {
|
||||||
|
// 如果只有一个标签且该标签不是固定标签,则不允许关闭
|
||||||
|
if (this.visitedViews.length === 1 && !this.isAffix(view)) {
|
||||||
|
return
|
||||||
|
}
|
||||||
this.$tab.closePage(view).then(({ visitedViews }) => {
|
this.$tab.closePage(view).then(({ visitedViews }) => {
|
||||||
if (this.isActive(view)) {
|
if (this.isActive(view)) {
|
||||||
this.toLastView(visitedViews, view)
|
this.toLastView(visitedViews, view)
|
||||||
|
|||||||
@@ -1,11 +1,10 @@
|
|||||||
import Vue from 'vue'
|
import Vue from 'vue'
|
||||||
import Router from 'vue-router'
|
import Router from 'vue-router'
|
||||||
|
|
||||||
Vue.use(Router)
|
|
||||||
|
|
||||||
/* Layout */
|
/* Layout */
|
||||||
import Layout from '@/layout'
|
import Layout from '@/layout'
|
||||||
|
|
||||||
|
Vue.use(Router)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Note: 路由配置项
|
* Note: 路由配置项
|
||||||
*
|
*
|
||||||
@@ -64,13 +63,13 @@ export const constantRoutes = [
|
|||||||
{
|
{
|
||||||
path: '',
|
path: '',
|
||||||
component: Layout,
|
component: Layout,
|
||||||
redirect: 'index',
|
redirect: 'dpcProject',
|
||||||
children: [
|
children: [
|
||||||
{
|
{
|
||||||
path: 'index',
|
path: 'dpcProject',
|
||||||
component: () => import('@/views/index'),
|
component: () => import('@/views/dpcProject/index'),
|
||||||
name: 'Index',
|
name: 'DpcProject',
|
||||||
meta: { title: '首页', icon: 'dashboard', affix: true }
|
meta: { title: '初核项目管理', icon: 'dashboard', affix: true }
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -1,205 +0,0 @@
|
|||||||
<!DOCTYPE html>
|
|
||||||
<html lang="zh-CN">
|
|
||||||
<head>
|
|
||||||
<meta charset="UTF-8">
|
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
||||||
<title>中介黑名单编辑对话框修复测试</title>
|
|
||||||
<style>
|
|
||||||
body {
|
|
||||||
font-family: Arial, sans-serif;
|
|
||||||
padding: 20px;
|
|
||||||
background-color: #f5f5f5;
|
|
||||||
}
|
|
||||||
.test-container {
|
|
||||||
max-width: 800px;
|
|
||||||
margin: 0 auto;
|
|
||||||
background: white;
|
|
||||||
padding: 30px;
|
|
||||||
border-radius: 8px;
|
|
||||||
box-shadow: 0 2px 12px rgba(0, 0, 0, 0.1);
|
|
||||||
}
|
|
||||||
h1 {
|
|
||||||
color: #303133;
|
|
||||||
border-bottom: 2px solid #409eff;
|
|
||||||
padding-bottom: 10px;
|
|
||||||
}
|
|
||||||
h2 {
|
|
||||||
color: #606266;
|
|
||||||
margin-top: 30px;
|
|
||||||
}
|
|
||||||
.test-case {
|
|
||||||
background: #f9f9f9;
|
|
||||||
padding: 15px;
|
|
||||||
margin: 15px 0;
|
|
||||||
border-left: 4px solid #409eff;
|
|
||||||
border-radius: 4px;
|
|
||||||
}
|
|
||||||
.test-case.success {
|
|
||||||
border-left-color: #67c23a;
|
|
||||||
}
|
|
||||||
.test-case.error {
|
|
||||||
border-left-color: #f56c6c;
|
|
||||||
}
|
|
||||||
.code {
|
|
||||||
background: #282c34;
|
|
||||||
color: #abb2bf;
|
|
||||||
padding: 15px;
|
|
||||||
border-radius: 4px;
|
|
||||||
overflow-x: auto;
|
|
||||||
font-family: 'Courier New', monospace;
|
|
||||||
font-size: 14px;
|
|
||||||
line-height: 1.5;
|
|
||||||
}
|
|
||||||
.fix-description {
|
|
||||||
background: #ecf5ff;
|
|
||||||
padding: 20px;
|
|
||||||
border-left: 4px solid #409eff;
|
|
||||||
border-radius: 4px;
|
|
||||||
margin: 20px 0;
|
|
||||||
}
|
|
||||||
.fix-description h3 {
|
|
||||||
color: #409eff;
|
|
||||||
margin-top: 0;
|
|
||||||
}
|
|
||||||
ul {
|
|
||||||
line-height: 1.8;
|
|
||||||
}
|
|
||||||
.status-badge {
|
|
||||||
display: inline-block;
|
|
||||||
padding: 4px 12px;
|
|
||||||
border-radius: 12px;
|
|
||||||
font-size: 12px;
|
|
||||||
font-weight: bold;
|
|
||||||
margin-left: 10px;
|
|
||||||
}
|
|
||||||
.status-badge.fixed {
|
|
||||||
background: #67c23a;
|
|
||||||
color: white;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<div class="test-container">
|
|
||||||
<h1>中介黑名单编辑对话框修复测试报告 <span class="status-badge fixed">已修复</span></h1>
|
|
||||||
|
|
||||||
<div class="fix-description">
|
|
||||||
<h3>问题描述</h3>
|
|
||||||
<p>在中介黑名单列表中点击修改按钮时,该行的信息没有正确反显到输入框内。</p>
|
|
||||||
|
|
||||||
<h3>根本原因</h3>
|
|
||||||
<ul>
|
|
||||||
<li><strong>时序问题</strong>:当 <code>visible</code> 从 false 变为 true 时,触发 <code>initDialogState()</code>,但此时 <code>form</code> 数据可能还没有完全传递到子组件</li>
|
|
||||||
<li><strong>缺少监听</strong>:没有监听 <code>form.intermediaryType</code> 的变化,导致数据加载后无法更新 <code>selectedType</code></li>
|
|
||||||
<li><strong>判断不完整</strong>:在 <code>initDialogState()</code> 中直接使用 <code>this.form.intermediaryType</code> 而没有检查是否存在</li>
|
|
||||||
</ul>
|
|
||||||
|
|
||||||
<h3>修复方案</h3>
|
|
||||||
<ul>
|
|
||||||
<li>添加对 <code>form.intermediaryType</code> 的 watch 监听</li>
|
|
||||||
<li>在 <code>initDialogState()</code> 中添加存在性检查</li>
|
|
||||||
<li>确保修改模式下正确设置 <code>selectedType</code></li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<h2>修复内容</h2>
|
|
||||||
|
|
||||||
<div class="test-case success">
|
|
||||||
<h3>1. 添加 form.intermediaryType 监听器</h3>
|
|
||||||
<p><strong>文件:</strong> ruoyi-ui/src/views/dpcIntermediary/components/EditDialog.vue</p>
|
|
||||||
<div class="code">
|
|
||||||
watch: {
|
|
||||||
// 原有的 visible 和 form.intermediaryId 监听...
|
|
||||||
|
|
||||||
// 新增:监听 form.intermediaryType 变化
|
|
||||||
'form.intermediaryType': {
|
|
||||||
handler(newVal) {
|
|
||||||
if (!this.isAddMode && newVal) {
|
|
||||||
// 修改模式下,类型加载后设置 selectedType
|
|
||||||
this.selectedType = newVal;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
immediate: true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="test-case success">
|
|
||||||
<h3>2. 改进 initDialogState 方法</h3>
|
|
||||||
<p><strong>文件:</strong> ruoyi-ui/src/views/dpcIntermediary/components/EditDialog.vue</p>
|
|
||||||
<div class="code">
|
|
||||||
initDialogState() {
|
|
||||||
if (this.isAddMode) {
|
|
||||||
// 新增模式:重置选择状态
|
|
||||||
this.selectedType = null;
|
|
||||||
this.tempSelectedType = null;
|
|
||||||
this.shouldAnimate = false;
|
|
||||||
this.form.intermediaryType = '1';
|
|
||||||
} else {
|
|
||||||
// 修改模式:设置已选择的类型(添加存在性检查)
|
|
||||||
if (this.form.intermediaryType) {
|
|
||||||
this.selectedType = this.form.intermediaryType;
|
|
||||||
}
|
|
||||||
this.shouldAnimate = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<h2>测试场景</h2>
|
|
||||||
|
|
||||||
<div class="test-case">
|
|
||||||
<h3>场景 1:修改个人中介信息</h3>
|
|
||||||
<p><strong>步骤:</strong></p>
|
|
||||||
<ol>
|
|
||||||
<li>打开中介黑名单列表页面</li>
|
|
||||||
<li>找到一条个人类型的记录(intermediaryType = '1')</li>
|
|
||||||
<li>点击"修改"按钮</li>
|
|
||||||
<li>验证:对话框应直接显示个人信息表单</li>
|
|
||||||
<li>验证:姓名、证件号等字段应正确反显</li>
|
|
||||||
</ol>
|
|
||||||
<p><strong>预期结果:</strong> ✅ 个人信息表单正确显示,所有字段数据正确反显</p>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="test-case">
|
|
||||||
<h3>场景 2:修改机构中介信息</h3>
|
|
||||||
<p><strong>步骤:</strong></p>
|
|
||||||
<ol>
|
|
||||||
<li>打开中介黑名单列表页面</li>
|
|
||||||
<li>找到一条机构类型的记录(intermediaryType = '2')</li>
|
|
||||||
<li>点击"修改"按钮</li>
|
|
||||||
<li>验证:对话框应直接显示机构信息表单</li>
|
|
||||||
<li>验证:机构名称、统一社会信用代码等字段应正确反显</li>
|
|
||||||
</ol>
|
|
||||||
<p><strong>预期结果:</strong> ✅ 机构信息表单正确显示,所有字段数据正确反显</p>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="test-case">
|
|
||||||
<h3>场景 3:新增中介信息</h3>
|
|
||||||
<p><strong>步骤:</strong></p>
|
|
||||||
<ol>
|
|
||||||
<li>打开中介黑名单列表页面</li>
|
|
||||||
<li>点击"新增"按钮</li>
|
|
||||||
<li>验证:对话框应显示类型选择卡片(个人/机构)</li>
|
|
||||||
<li>选择类型后,显示对应表单</li>
|
|
||||||
</ol>
|
|
||||||
<p><strong>预期结果:</strong> ✅ 类型选择卡片正确显示,选择后表单正常显示</p>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<h2>验证要点</h2>
|
|
||||||
<ul>
|
|
||||||
<li>✅ 修改模式下,不需要选择类型,直接显示对应表单</li>
|
|
||||||
<li>✅ 表单字段数据正确反显</li>
|
|
||||||
<li>✅ 新增模式下,类型选择卡片正常显示</li>
|
|
||||||
<li>✅ 新增和修改模式切换正常</li>
|
|
||||||
<li>✅ 枚举字段(下拉框)正确显示选中值</li>
|
|
||||||
</ul>
|
|
||||||
|
|
||||||
<h2>相关文件</h2>
|
|
||||||
<ul>
|
|
||||||
<li><strong>修改文件:</strong> ruoyi-ui/src/views/dpcIntermediary/components/EditDialog.vue</li>
|
|
||||||
<li><strong>关联文件:</strong> ruoyi-ui/src/views/dpcIntermediary/index.vue</li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
333
ruoyi-ui/src/views/dpcProject/components/AddProjectDialog.vue
Normal file
333
ruoyi-ui/src/views/dpcProject/components/AddProjectDialog.vue
Normal file
@@ -0,0 +1,333 @@
|
|||||||
|
<template>
|
||||||
|
<el-dialog
|
||||||
|
:visible.sync="dialogVisible"
|
||||||
|
:title="title"
|
||||||
|
width="600px"
|
||||||
|
:close-on-click-modal="false"
|
||||||
|
:close-on-press-escape="false"
|
||||||
|
@close="handleClose"
|
||||||
|
>
|
||||||
|
<el-form
|
||||||
|
ref="projectForm"
|
||||||
|
:model="formData"
|
||||||
|
:rules="rules"
|
||||||
|
label-width="100px"
|
||||||
|
label-position="right"
|
||||||
|
>
|
||||||
|
<!-- 项目名称 -->
|
||||||
|
<el-form-item label="项目名称" prop="projectName">
|
||||||
|
<el-input
|
||||||
|
v-model="formData.projectName"
|
||||||
|
placeholder="请输入项目名称"
|
||||||
|
maxlength="50"
|
||||||
|
show-word-limit
|
||||||
|
/>
|
||||||
|
</el-form-item>
|
||||||
|
|
||||||
|
<!-- 项目描述 -->
|
||||||
|
<el-form-item label="项目描述" prop="projectDesc">
|
||||||
|
<el-input
|
||||||
|
v-model="formData.projectDesc"
|
||||||
|
type="textarea"
|
||||||
|
:rows="3"
|
||||||
|
placeholder="请输入项目描述"
|
||||||
|
maxlength="200"
|
||||||
|
show-word-limit
|
||||||
|
/>
|
||||||
|
</el-form-item>
|
||||||
|
|
||||||
|
<!-- 目标人员 -->
|
||||||
|
<el-form-item label="目标人员">
|
||||||
|
<div class="target-persons-wrapper">
|
||||||
|
<el-button
|
||||||
|
icon="el-icon-plus"
|
||||||
|
size="small"
|
||||||
|
@click="handleAddPerson"
|
||||||
|
>添加人员</el-button>
|
||||||
|
<div v-if="formData.targetPersons && formData.targetPersons.length > 0" class="persons-list">
|
||||||
|
<el-tag
|
||||||
|
v-for="(person, index) in formData.targetPersons"
|
||||||
|
:key="index"
|
||||||
|
closable
|
||||||
|
@close="handleRemovePerson(index)"
|
||||||
|
type="info"
|
||||||
|
>
|
||||||
|
{{ person.name }} ({{ person.certNo }})
|
||||||
|
</el-tag>
|
||||||
|
</div>
|
||||||
|
<div v-else class="empty-hint">
|
||||||
|
<i class="el-icon-info"></i>
|
||||||
|
<span>暂未添加目标人员,可后续添加</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</el-form-item>
|
||||||
|
|
||||||
|
<!-- 时间范围 -->
|
||||||
|
<el-form-item label="开始日期" prop="startDate">
|
||||||
|
<el-date-picker
|
||||||
|
v-model="formData.startDate"
|
||||||
|
type="date"
|
||||||
|
placeholder="选择开始日期"
|
||||||
|
value-format="yyyy-MM-dd"
|
||||||
|
style="width: 100%"
|
||||||
|
/>
|
||||||
|
</el-form-item>
|
||||||
|
|
||||||
|
<el-form-item label="结束日期" prop="endDate">
|
||||||
|
<el-date-picker
|
||||||
|
v-model="formData.endDate"
|
||||||
|
type="date"
|
||||||
|
placeholder="选择结束日期"
|
||||||
|
value-format="yyyy-MM-dd"
|
||||||
|
:picker-options="endDatePickerOptions"
|
||||||
|
style="width: 100%"
|
||||||
|
/>
|
||||||
|
</el-form-item>
|
||||||
|
|
||||||
|
<!-- 目标人数 -->
|
||||||
|
<el-form-item label="目标人数" prop="targetCount">
|
||||||
|
<el-input-number
|
||||||
|
v-model="formData.targetCount"
|
||||||
|
:min="0"
|
||||||
|
:max="10000"
|
||||||
|
:step="10"
|
||||||
|
controls-position="right"
|
||||||
|
style="width: 100%"
|
||||||
|
/>
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
|
|
||||||
|
<!-- 高级设置(可选扩展) -->
|
||||||
|
<el-collapse class="advanced-settings" v-model="activeCollapse">
|
||||||
|
<el-collapse-item title="高级设置" name="advanced">
|
||||||
|
<el-form label-width="100px" label-position="right">
|
||||||
|
<el-form-item label="自动预警">
|
||||||
|
<el-switch v-model="formData.autoWarning" />
|
||||||
|
<span class="form-item-hint">开启后将自动计算预警人员</span>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="预警阈值">
|
||||||
|
<el-input-number
|
||||||
|
v-model="formData.warningThreshold"
|
||||||
|
:min="1"
|
||||||
|
:max="100"
|
||||||
|
controls-position="right"
|
||||||
|
/>
|
||||||
|
<span class="form-item-hint">匹配度低于此值时触发预警</span>
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
|
</el-collapse-item>
|
||||||
|
</el-collapse>
|
||||||
|
|
||||||
|
<div slot="footer" class="dialog-footer">
|
||||||
|
<el-button @click="handleClose">取 消</el-button>
|
||||||
|
<el-button type="primary" :loading="submitting" @click="handleSubmit">
|
||||||
|
<i v-if="!submitting" class="el-icon-check"></i>
|
||||||
|
确 定
|
||||||
|
</el-button>
|
||||||
|
</div>
|
||||||
|
</el-dialog>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
name: 'AddProjectDialog',
|
||||||
|
props: {
|
||||||
|
visible: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false
|
||||||
|
},
|
||||||
|
title: {
|
||||||
|
type: String,
|
||||||
|
default: '新建项目'
|
||||||
|
},
|
||||||
|
form: {
|
||||||
|
type: Object,
|
||||||
|
default: () => ({})
|
||||||
|
}
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
// 结束日期验证规则
|
||||||
|
const validateEndDate = (rule, value, callback) => {
|
||||||
|
if (value && this.formData.startDate && value < this.formData.startDate) {
|
||||||
|
callback(new Error('结束日期不能早于开始日期'))
|
||||||
|
} else {
|
||||||
|
callback()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
submitting: false,
|
||||||
|
activeCollapse: [],
|
||||||
|
formData: {
|
||||||
|
projectId: null,
|
||||||
|
projectName: '',
|
||||||
|
projectDesc: '',
|
||||||
|
startDate: '',
|
||||||
|
endDate: '',
|
||||||
|
targetCount: 0,
|
||||||
|
targetPersons: [],
|
||||||
|
autoWarning: true,
|
||||||
|
warningThreshold: 60
|
||||||
|
},
|
||||||
|
rules: {
|
||||||
|
projectName: [
|
||||||
|
{ required: true, message: '请输入项目名称', trigger: 'blur' },
|
||||||
|
{ min: 2, max: 50, message: '长度在 2 到 50 个字符', trigger: 'blur' }
|
||||||
|
],
|
||||||
|
startDate: [
|
||||||
|
{ required: true, message: '请选择开始日期', trigger: 'change' }
|
||||||
|
],
|
||||||
|
endDate: [
|
||||||
|
{ required: true, message: '请选择结束日期', trigger: 'change' },
|
||||||
|
{ validator: validateEndDate, trigger: 'change' }
|
||||||
|
],
|
||||||
|
targetCount: [
|
||||||
|
{ required: true, message: '请输入目标人数', trigger: 'blur' }
|
||||||
|
]
|
||||||
|
},
|
||||||
|
endDatePickerOptions: {
|
||||||
|
disabledDate: (time) => {
|
||||||
|
if (this.formData.startDate) {
|
||||||
|
return time.getTime() < new Date(this.formData.startDate).getTime()
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
dialogVisible: {
|
||||||
|
get() {
|
||||||
|
return this.visible
|
||||||
|
},
|
||||||
|
set(val) {
|
||||||
|
if (!val) {
|
||||||
|
this.handleClose()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
watch: {
|
||||||
|
form: {
|
||||||
|
handler(newVal) {
|
||||||
|
if (newVal && Object.keys(newVal).length > 0) {
|
||||||
|
this.formData = { ...this.formData, ...newVal }
|
||||||
|
}
|
||||||
|
},
|
||||||
|
immediate: true,
|
||||||
|
deep: true
|
||||||
|
},
|
||||||
|
visible(val) {
|
||||||
|
if (val) {
|
||||||
|
// 对话框打开时重置表单验证状态
|
||||||
|
this.$nextTick(() => {
|
||||||
|
if (this.$refs.projectForm) {
|
||||||
|
this.$refs.projectForm.clearValidate()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
/** 添加人员 */
|
||||||
|
handleAddPerson() {
|
||||||
|
// 这里可以打开一个选择人员的对话框
|
||||||
|
this.$message.info('人员选择功能待实现')
|
||||||
|
// 模拟添加人员
|
||||||
|
if (!this.formData.targetPersons) {
|
||||||
|
this.formData.targetPersons = []
|
||||||
|
}
|
||||||
|
this.formData.targetPersons.push({
|
||||||
|
name: '张三',
|
||||||
|
certNo: '3301**********202101'
|
||||||
|
})
|
||||||
|
},
|
||||||
|
/** 移除人员 */
|
||||||
|
handleRemovePerson(index) {
|
||||||
|
this.formData.targetPersons.splice(index, 1)
|
||||||
|
},
|
||||||
|
/** 提交表单 */
|
||||||
|
handleSubmit() {
|
||||||
|
this.$refs.projectForm.validate(valid => {
|
||||||
|
if (valid) {
|
||||||
|
this.submitting = true
|
||||||
|
// 模拟提交
|
||||||
|
setTimeout(() => {
|
||||||
|
this.submitting = false
|
||||||
|
this.$emit('submit', { ...this.formData })
|
||||||
|
}, 500)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
},
|
||||||
|
/** 关闭对话框 */
|
||||||
|
handleClose() {
|
||||||
|
this.$emit('close')
|
||||||
|
this.$refs.projectForm.resetFields()
|
||||||
|
this.formData = {
|
||||||
|
projectId: null,
|
||||||
|
projectName: '',
|
||||||
|
projectDesc: '',
|
||||||
|
startDate: '',
|
||||||
|
endDate: '',
|
||||||
|
targetCount: 0,
|
||||||
|
targetPersons: [],
|
||||||
|
autoWarning: true,
|
||||||
|
warningThreshold: 60
|
||||||
|
}
|
||||||
|
this.activeCollapse = []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.target-persons-wrapper {
|
||||||
|
width: 100%;
|
||||||
|
|
||||||
|
.persons-list {
|
||||||
|
margin-top: 12px;
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
gap: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.empty-hint {
|
||||||
|
margin-top: 12px;
|
||||||
|
padding: 12px;
|
||||||
|
background-color: #f5f7fa;
|
||||||
|
border-radius: 4px;
|
||||||
|
color: #909399;
|
||||||
|
font-size: 13px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 6px;
|
||||||
|
|
||||||
|
i {
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.advanced-settings {
|
||||||
|
margin: 20px 0;
|
||||||
|
|
||||||
|
:deep(.el-collapse-item__header) {
|
||||||
|
font-size: 14px;
|
||||||
|
color: #606266;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-item-hint {
|
||||||
|
margin-left: 12px;
|
||||||
|
font-size: 12px;
|
||||||
|
color: #909399;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dialog-footer {
|
||||||
|
text-align: right;
|
||||||
|
|
||||||
|
.el-button + .el-button {
|
||||||
|
margin-left: 8px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -0,0 +1,247 @@
|
|||||||
|
<template>
|
||||||
|
<el-dialog
|
||||||
|
:visible.sync="dialogVisible"
|
||||||
|
title="归档确认"
|
||||||
|
width="500px"
|
||||||
|
:close-on-click-modal="false"
|
||||||
|
@close="handleClose"
|
||||||
|
>
|
||||||
|
<div class="archive-confirm-content">
|
||||||
|
<!-- 警告图标 -->
|
||||||
|
<div class="warning-icon">
|
||||||
|
<i class="el-icon-warning"></i>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 确认文字 -->
|
||||||
|
<div class="confirm-text">
|
||||||
|
确定要归档项目"<span class="project-name-highlight">{{ projectData && projectData.projectName }}</span>"吗?
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 归档说明 -->
|
||||||
|
<div class="archive-info">
|
||||||
|
<div class="info-title">归档后将:</div>
|
||||||
|
<ul class="info-list">
|
||||||
|
<li>
|
||||||
|
<i class="el-icon-check"></i>
|
||||||
|
<span>项目状态变为"已归档"</span>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<i class="el-icon-check"></i>
|
||||||
|
<span>自动生成项目报告PDF</span>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<i class="el-icon-check"></i>
|
||||||
|
<span>移入归档库,可随时查看</span>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 删除选项 -->
|
||||||
|
<div class="delete-option">
|
||||||
|
<el-checkbox v-model="deleteData">同时删除项目相关数据(不可恢复)</el-checkbox>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 提示信息 -->
|
||||||
|
<div class="archive-hint">
|
||||||
|
<i class="el-icon-info"></i>
|
||||||
|
<span>归档后可从"归档库"中查看和恢复</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div slot="footer" class="dialog-footer">
|
||||||
|
<el-button @click="handleClose">取 消</el-button>
|
||||||
|
<el-button
|
||||||
|
type="primary"
|
||||||
|
:loading="submitting"
|
||||||
|
@click="handleConfirm"
|
||||||
|
>
|
||||||
|
<i v-if="!submitting" class="el-icon-folder-checked"></i>
|
||||||
|
确认归档
|
||||||
|
</el-button>
|
||||||
|
</div>
|
||||||
|
</el-dialog>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
name: 'ArchiveConfirmDialog',
|
||||||
|
props: {
|
||||||
|
visible: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false
|
||||||
|
},
|
||||||
|
projectData: {
|
||||||
|
type: Object,
|
||||||
|
default: null
|
||||||
|
}
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
submitting: false,
|
||||||
|
deleteData: false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
dialogVisible: {
|
||||||
|
get() {
|
||||||
|
return this.visible
|
||||||
|
},
|
||||||
|
set(val) {
|
||||||
|
if (!val) {
|
||||||
|
this.handleClose()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
watch: {
|
||||||
|
visible(val) {
|
||||||
|
if (!val) {
|
||||||
|
this.deleteData = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
handleConfirm() {
|
||||||
|
if (this.deleteData) {
|
||||||
|
this.$confirm('删除后数据将无法恢复,是否确认删除?', '警告', {
|
||||||
|
confirmButtonText: '确认删除',
|
||||||
|
cancelButtonText: '取消',
|
||||||
|
type: 'warning'
|
||||||
|
}).then(() => {
|
||||||
|
this.doArchive()
|
||||||
|
}).catch(() => {
|
||||||
|
// 取消删除,但仍归档
|
||||||
|
this.deleteData = false
|
||||||
|
this.doArchive()
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
this.doArchive()
|
||||||
|
}
|
||||||
|
},
|
||||||
|
doArchive() {
|
||||||
|
this.submitting = true
|
||||||
|
setTimeout(() => {
|
||||||
|
this.submitting = false
|
||||||
|
this.$emit('confirm', {
|
||||||
|
projectId: this.projectData.projectId,
|
||||||
|
deleteData: this.deleteData
|
||||||
|
})
|
||||||
|
}, 500)
|
||||||
|
},
|
||||||
|
handleClose() {
|
||||||
|
this.$emit('close')
|
||||||
|
this.deleteData = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.archive-confirm-content {
|
||||||
|
padding: 20px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.warning-icon {
|
||||||
|
text-align: center;
|
||||||
|
margin-bottom: 20px;
|
||||||
|
|
||||||
|
i {
|
||||||
|
font-size: 64px;
|
||||||
|
color: #E6A23C;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.confirm-text {
|
||||||
|
text-align: center;
|
||||||
|
font-size: 16px;
|
||||||
|
color: #303133;
|
||||||
|
line-height: 1.6;
|
||||||
|
margin-bottom: 24px;
|
||||||
|
|
||||||
|
.project-name-highlight {
|
||||||
|
color: #409EFF;
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.archive-info {
|
||||||
|
background-color: #f5f7fa;
|
||||||
|
border-radius: 8px;
|
||||||
|
padding: 16px 20px;
|
||||||
|
margin-bottom: 16px;
|
||||||
|
|
||||||
|
.info-title {
|
||||||
|
font-size: 14px;
|
||||||
|
font-weight: 600;
|
||||||
|
color: #606266;
|
||||||
|
margin-bottom: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.info-list {
|
||||||
|
margin: 0;
|
||||||
|
padding-left: 0;
|
||||||
|
list-style: none;
|
||||||
|
|
||||||
|
li {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
font-size: 14px;
|
||||||
|
color: #606266;
|
||||||
|
margin-bottom: 8px;
|
||||||
|
|
||||||
|
&:last-child {
|
||||||
|
margin-bottom: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
i {
|
||||||
|
color: #67C23A;
|
||||||
|
margin-right: 8px;
|
||||||
|
font-size: 16px;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.delete-option {
|
||||||
|
margin-bottom: 16px;
|
||||||
|
padding: 12px;
|
||||||
|
background-color: #fef0f0;
|
||||||
|
border-radius: 6px;
|
||||||
|
border: 1px solid #fde2e2;
|
||||||
|
|
||||||
|
:deep(.el-checkbox__label) {
|
||||||
|
color: #F56C6C;
|
||||||
|
}
|
||||||
|
|
||||||
|
:deep(.el-checkbox__input.is-checked + .el-checkbox__label) {
|
||||||
|
color: #F56C6C;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.archive-hint {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
font-size: 13px;
|
||||||
|
color: #909399;
|
||||||
|
padding: 12px;
|
||||||
|
background-color: #ecf5ff;
|
||||||
|
border-radius: 6px;
|
||||||
|
border: 1px solid #d9ecff;
|
||||||
|
|
||||||
|
i {
|
||||||
|
margin-right: 6px;
|
||||||
|
font-size: 14px;
|
||||||
|
color: #409EFF;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.dialog-footer {
|
||||||
|
text-align: right;
|
||||||
|
|
||||||
|
.el-button + .el-button {
|
||||||
|
margin-left: 8px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
428
ruoyi-ui/src/views/dpcProject/components/ImportHistoryDialog.vue
Normal file
428
ruoyi-ui/src/views/dpcProject/components/ImportHistoryDialog.vue
Normal file
@@ -0,0 +1,428 @@
|
|||||||
|
<template>
|
||||||
|
<el-dialog
|
||||||
|
:visible.sync="dialogVisible"
|
||||||
|
title="导入历史项目"
|
||||||
|
width="700px"
|
||||||
|
:close-on-click-modal="false"
|
||||||
|
@close="handleClose"
|
||||||
|
>
|
||||||
|
<!-- 搜索区 -->
|
||||||
|
<div class="search-section">
|
||||||
|
<el-input
|
||||||
|
v-model="searchKeyword"
|
||||||
|
placeholder="搜索历史项目名称"
|
||||||
|
prefix-icon="el-icon-search"
|
||||||
|
clearable
|
||||||
|
size="small"
|
||||||
|
style="width: 300px"
|
||||||
|
>
|
||||||
|
<el-button slot="append" icon="el-icon-search" @click="handleSearch" />
|
||||||
|
</el-input>
|
||||||
|
<el-date-picker
|
||||||
|
v-model="dateRange"
|
||||||
|
type="daterange"
|
||||||
|
range-separator="至"
|
||||||
|
start-placeholder="开始日期"
|
||||||
|
end-placeholder="结束日期"
|
||||||
|
size="small"
|
||||||
|
style="width: 240px; margin-left: 12px"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 历史项目列表 -->
|
||||||
|
<div class="project-list-section">
|
||||||
|
<div class="section-title">历史项目列表</div>
|
||||||
|
<el-radio-group v-model="selectedProjectId" class="project-radio-group">
|
||||||
|
<div
|
||||||
|
v-for="item in filteredProjects"
|
||||||
|
:key="item.projectId"
|
||||||
|
class="project-item-wrapper"
|
||||||
|
>
|
||||||
|
<el-radio :label="item.projectId" class="project-radio">
|
||||||
|
<div class="project-item">
|
||||||
|
<div class="project-header">
|
||||||
|
<span class="name">{{ item.projectName }}</span>
|
||||||
|
<el-tag
|
||||||
|
:type="getStatusType(item.projectStatus)"
|
||||||
|
size="mini"
|
||||||
|
>{{ getStatusLabel(item.projectStatus) }}</el-tag>
|
||||||
|
</div>
|
||||||
|
<div class="project-info">
|
||||||
|
<span class="info-item">
|
||||||
|
<i class="el-icon-time"></i>
|
||||||
|
创建时间: {{ item.createTime }}
|
||||||
|
</span>
|
||||||
|
<span class="info-item">
|
||||||
|
<i class="el-icon-user"></i>
|
||||||
|
目标人数: {{ item.targetCount }}
|
||||||
|
</span>
|
||||||
|
<span class="info-item warning">
|
||||||
|
<i class="el-icon-warning"></i>
|
||||||
|
预警人数: {{ item.warningCount }}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</el-radio>
|
||||||
|
</div>
|
||||||
|
</el-radio-group>
|
||||||
|
|
||||||
|
<el-empty
|
||||||
|
v-if="filteredProjects.length === 0"
|
||||||
|
description="暂无历史项目"
|
||||||
|
:image-size="100"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 新项目配置 -->
|
||||||
|
<div class="new-project-config">
|
||||||
|
<el-divider />
|
||||||
|
<el-form
|
||||||
|
ref="configForm"
|
||||||
|
:model="configForm"
|
||||||
|
:rules="configRules"
|
||||||
|
label-width="100px"
|
||||||
|
label-position="right"
|
||||||
|
>
|
||||||
|
<el-form-item label="新项目名称" prop="newProjectName">
|
||||||
|
<el-input
|
||||||
|
v-model="configForm.newProjectName"
|
||||||
|
placeholder="新项目名称(可自动生成)"
|
||||||
|
maxlength="50"
|
||||||
|
/>
|
||||||
|
</el-form-item>
|
||||||
|
|
||||||
|
<el-row :gutter="16">
|
||||||
|
<el-col :span="12">
|
||||||
|
<el-form-item label="开始日期" prop="startDate">
|
||||||
|
<el-date-picker
|
||||||
|
v-model="configForm.startDate"
|
||||||
|
type="date"
|
||||||
|
placeholder="选择开始日期"
|
||||||
|
value-format="yyyy-MM-dd"
|
||||||
|
style="width: 100%"
|
||||||
|
/>
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="12">
|
||||||
|
<el-form-item label="结束日期" prop="endDate">
|
||||||
|
<el-date-picker
|
||||||
|
v-model="configForm.endDate"
|
||||||
|
type="date"
|
||||||
|
placeholder="选择结束日期"
|
||||||
|
value-format="yyyy-MM-dd"
|
||||||
|
:picker-options="endDatePickerOptions"
|
||||||
|
style="width: 100%"
|
||||||
|
/>
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
</el-row>
|
||||||
|
</el-form>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div slot="footer" class="dialog-footer">
|
||||||
|
<el-button @click="handleClose">取 消</el-button>
|
||||||
|
<el-button
|
||||||
|
type="primary"
|
||||||
|
:loading="submitting"
|
||||||
|
:disabled="!selectedProjectId"
|
||||||
|
@click="handleSubmit"
|
||||||
|
>
|
||||||
|
<i v-if="!submitting" class="el-icon-download"></i>
|
||||||
|
导 入
|
||||||
|
</el-button>
|
||||||
|
</div>
|
||||||
|
</el-dialog>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import {getMockHistoryProjects} from '@/api/dpcProject'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: 'ImportHistoryDialog',
|
||||||
|
props: {
|
||||||
|
visible: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
// 结束日期验证规则
|
||||||
|
const validateEndDate = (rule, value, callback) => {
|
||||||
|
if (value && this.configForm.startDate && value < this.configForm.startDate) {
|
||||||
|
callback(new Error('结束日期不能早于开始日期'))
|
||||||
|
} else {
|
||||||
|
callback()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
submitting: false,
|
||||||
|
searchKeyword: '',
|
||||||
|
dateRange: null,
|
||||||
|
selectedProjectId: null,
|
||||||
|
historyProjects: [],
|
||||||
|
configForm: {
|
||||||
|
newProjectName: '',
|
||||||
|
startDate: '',
|
||||||
|
endDate: ''
|
||||||
|
},
|
||||||
|
configRules: {
|
||||||
|
newProjectName: [
|
||||||
|
{ required: true, message: '请输入新项目名称', trigger: 'blur' }
|
||||||
|
],
|
||||||
|
startDate: [
|
||||||
|
{ required: true, message: '请选择开始日期', trigger: 'change' }
|
||||||
|
],
|
||||||
|
endDate: [
|
||||||
|
{ required: true, message: '请选择结束日期', trigger: 'change' },
|
||||||
|
{ validator: validateEndDate, trigger: 'change' }
|
||||||
|
]
|
||||||
|
},
|
||||||
|
endDatePickerOptions: {
|
||||||
|
disabledDate: (time) => {
|
||||||
|
if (this.configForm.startDate) {
|
||||||
|
return time.getTime() < new Date(this.configForm.startDate).getTime()
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
dialogVisible: {
|
||||||
|
get() {
|
||||||
|
return this.visible
|
||||||
|
},
|
||||||
|
set(val) {
|
||||||
|
if (!val) {
|
||||||
|
this.handleClose()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
filteredProjects() {
|
||||||
|
let result = [...this.historyProjects]
|
||||||
|
if (this.searchKeyword) {
|
||||||
|
result = result.filter(item =>
|
||||||
|
item.projectName.toLowerCase().includes(this.searchKeyword.toLowerCase())
|
||||||
|
)
|
||||||
|
}
|
||||||
|
if (this.dateRange && this.dateRange.length === 2) {
|
||||||
|
const [start, end] = this.dateRange
|
||||||
|
result = result.filter(item => {
|
||||||
|
const createTime = new Date(item.createTime)
|
||||||
|
return createTime >= new Date(start) && createTime <= new Date(end)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
},
|
||||||
|
watch: {
|
||||||
|
visible(val) {
|
||||||
|
if (val) {
|
||||||
|
this.loadHistoryProjects()
|
||||||
|
}
|
||||||
|
},
|
||||||
|
selectedProjectId(val) {
|
||||||
|
if (val) {
|
||||||
|
const project = this.historyProjects.find(p => p.projectId === val)
|
||||||
|
if (project) {
|
||||||
|
// 自动生成新项目名称
|
||||||
|
const now = new Date()
|
||||||
|
const year = now.getFullYear()
|
||||||
|
const month = String(now.getMonth() + 1).padStart(2, '0')
|
||||||
|
const day = String(now.getDate()).padStart(2, '0')
|
||||||
|
this.configForm.newProjectName = `${project.projectName}(${year}-${month}-${day}复制)`
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
/** 加载历史项目 */
|
||||||
|
loadHistoryProjects() {
|
||||||
|
getMockHistoryProjects().then(response => {
|
||||||
|
this.historyProjects = response.data
|
||||||
|
})
|
||||||
|
},
|
||||||
|
/** 获取状态类型 */
|
||||||
|
getStatusType(status) {
|
||||||
|
const statusMap = {
|
||||||
|
'0': 'primary',
|
||||||
|
'1': 'success',
|
||||||
|
'2': 'info'
|
||||||
|
}
|
||||||
|
return statusMap[status] || 'info'
|
||||||
|
},
|
||||||
|
/** 获取状态标签 */
|
||||||
|
getStatusLabel(status) {
|
||||||
|
const statusMap = {
|
||||||
|
'0': '进行中',
|
||||||
|
'1': '已完成',
|
||||||
|
'2': '已归档'
|
||||||
|
}
|
||||||
|
return statusMap[status] || '未知'
|
||||||
|
},
|
||||||
|
/** 搜索 */
|
||||||
|
handleSearch() {
|
||||||
|
// 搜索逻辑在 computed 中处理
|
||||||
|
},
|
||||||
|
/** 提交导入 */
|
||||||
|
handleSubmit() {
|
||||||
|
if (!this.selectedProjectId) {
|
||||||
|
this.$message.warning('请选择要导入的历史项目')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
this.$refs.configForm.validate(valid => {
|
||||||
|
if (valid) {
|
||||||
|
this.submitting = true
|
||||||
|
const selectedProject = this.historyProjects.find(p => p.projectId === this.selectedProjectId)
|
||||||
|
setTimeout(() => {
|
||||||
|
this.submitting = false
|
||||||
|
this.$emit('submit', {
|
||||||
|
sourceProjectId: this.selectedProjectId,
|
||||||
|
sourceProject: selectedProject,
|
||||||
|
...this.configForm
|
||||||
|
})
|
||||||
|
}, 500)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
},
|
||||||
|
/** 关闭对话框 */
|
||||||
|
handleClose() {
|
||||||
|
this.$emit('close')
|
||||||
|
this.selectedProjectId = null
|
||||||
|
this.searchKeyword = ''
|
||||||
|
this.dateRange = null
|
||||||
|
this.configForm = {
|
||||||
|
newProjectName: '',
|
||||||
|
startDate: '',
|
||||||
|
endDate: ''
|
||||||
|
}
|
||||||
|
this.$refs.configForm?.resetFields()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.search-section {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
margin-bottom: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.project-list-section {
|
||||||
|
margin-bottom: 16px;
|
||||||
|
|
||||||
|
.section-title {
|
||||||
|
font-size: 14px;
|
||||||
|
font-weight: 600;
|
||||||
|
color: #303133;
|
||||||
|
margin-bottom: 12px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.project-radio-group {
|
||||||
|
width: 100%;
|
||||||
|
max-height: 300px;
|
||||||
|
overflow-y: auto;
|
||||||
|
|
||||||
|
&::-webkit-scrollbar {
|
||||||
|
width: 6px;
|
||||||
|
}
|
||||||
|
|
||||||
|
&::-webkit-scrollbar-thumb {
|
||||||
|
background-color: #dcdfe6;
|
||||||
|
border-radius: 3px;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background-color: #c0c4cc;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.project-item-wrapper {
|
||||||
|
margin-bottom: 12px;
|
||||||
|
|
||||||
|
&:last-child {
|
||||||
|
margin-bottom: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.project-radio {
|
||||||
|
display: block;
|
||||||
|
width: 100%;
|
||||||
|
|
||||||
|
:deep(.el-radio__label) {
|
||||||
|
width: calc(100% - 24px);
|
||||||
|
padding-left: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
:deep(.el-radio__input) {
|
||||||
|
margin-top: 20px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.project-item {
|
||||||
|
padding: 12px;
|
||||||
|
background-color: #f5f7fa;
|
||||||
|
border-radius: 8px;
|
||||||
|
transition: all 0.3s;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background-color: #ecf5ff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.project-header {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
margin-bottom: 8px;
|
||||||
|
|
||||||
|
.name {
|
||||||
|
font-size: 15px;
|
||||||
|
font-weight: 500;
|
||||||
|
color: #303133;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.project-info {
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
gap: 16px;
|
||||||
|
|
||||||
|
.info-item {
|
||||||
|
font-size: 13px;
|
||||||
|
color: #909399;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 4px;
|
||||||
|
|
||||||
|
i {
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.warning {
|
||||||
|
color: #E6A23C;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.new-project-config {
|
||||||
|
:deep(.el-divider) {
|
||||||
|
margin: 16px 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.dialog-footer {
|
||||||
|
text-align: right;
|
||||||
|
|
||||||
|
.el-button + .el-button {
|
||||||
|
margin-left: 8px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
:deep(.el-empty) {
|
||||||
|
padding: 20px 0;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
347
ruoyi-ui/src/views/dpcProject/components/ProjectTable.vue
Normal file
347
ruoyi-ui/src/views/dpcProject/components/ProjectTable.vue
Normal file
@@ -0,0 +1,347 @@
|
|||||||
|
<template>
|
||||||
|
<div class="project-table-container">
|
||||||
|
<el-card class="table-card" shadow="hover">
|
||||||
|
<el-table
|
||||||
|
v-loading="loading"
|
||||||
|
:data="dataList"
|
||||||
|
style="width: 100%"
|
||||||
|
:header-cell-style="{ background: '#f5f7fa', color: '#606266', fontWeight: '600' }"
|
||||||
|
>
|
||||||
|
<!-- 序号 -->
|
||||||
|
<el-table-column
|
||||||
|
type="index"
|
||||||
|
label="序号"
|
||||||
|
width="60"
|
||||||
|
align="center"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<!-- 项目名称 -->
|
||||||
|
<el-table-column
|
||||||
|
label="项目名称"
|
||||||
|
min-width="160"
|
||||||
|
show-overflow-tooltip
|
||||||
|
>
|
||||||
|
<template slot-scope="scope">
|
||||||
|
<div class="project-name-cell">
|
||||||
|
<div class="name">{{ scope.row.projectName }}</div>
|
||||||
|
<div class="desc">{{ scope.row.projectDesc }}</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
|
||||||
|
<!-- 创建时间 -->
|
||||||
|
<el-table-column
|
||||||
|
label="创建时间"
|
||||||
|
prop="createTime"
|
||||||
|
width="110"
|
||||||
|
align="center"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<!-- 状态 -->
|
||||||
|
<el-table-column
|
||||||
|
label="状态"
|
||||||
|
prop="projectStatus"
|
||||||
|
width="90"
|
||||||
|
align="center"
|
||||||
|
>
|
||||||
|
<template slot-scope="scope">
|
||||||
|
<el-tag
|
||||||
|
:type="getStatusType(scope.row.projectStatus)"
|
||||||
|
size="medium"
|
||||||
|
effect="plain"
|
||||||
|
>
|
||||||
|
{{ getStatusLabel(scope.row.projectStatus) }}
|
||||||
|
</el-tag>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
|
||||||
|
<!-- 目标人数 -->
|
||||||
|
<el-table-column
|
||||||
|
label="目标人数"
|
||||||
|
prop="targetCount"
|
||||||
|
width="80"
|
||||||
|
align="center"
|
||||||
|
>
|
||||||
|
<template slot-scope="scope">
|
||||||
|
<span class="count-number">{{ scope.row.targetCount }}</span>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
|
||||||
|
<!-- 预警人数 -->
|
||||||
|
<el-table-column
|
||||||
|
label="预警人数"
|
||||||
|
width="90"
|
||||||
|
align="center"
|
||||||
|
>
|
||||||
|
<template slot-scope="scope">
|
||||||
|
<span :class="getWarningClass(scope.row)">{{ scope.row.warningCount }}</span>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
|
||||||
|
<!-- 操作 -->
|
||||||
|
<el-table-column
|
||||||
|
label="操作"
|
||||||
|
width="200"
|
||||||
|
align="center"
|
||||||
|
fixed="right"
|
||||||
|
class-name="operation-column"
|
||||||
|
>
|
||||||
|
<template slot-scope="scope">
|
||||||
|
<div class="operation-buttons">
|
||||||
|
<!-- 进行中项目 -->
|
||||||
|
<template v-if="scope.row.projectStatus === '0'">
|
||||||
|
<el-button
|
||||||
|
size="mini"
|
||||||
|
type="text"
|
||||||
|
icon="el-icon-s-data"
|
||||||
|
@click="handleEnter(scope.row)"
|
||||||
|
>进入项目</el-button>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<!-- 已完成项目 -->
|
||||||
|
<template v-else-if="scope.row.projectStatus === '1'">
|
||||||
|
<el-button
|
||||||
|
size="mini"
|
||||||
|
type="text"
|
||||||
|
icon="el-icon-view"
|
||||||
|
@click="handleViewResult(scope.row)"
|
||||||
|
>查看结果</el-button>
|
||||||
|
<el-button
|
||||||
|
size="mini"
|
||||||
|
type="text"
|
||||||
|
icon="el-icon-refresh"
|
||||||
|
@click="handleReAnalyze(scope.row)"
|
||||||
|
>重新分析</el-button>
|
||||||
|
<el-button
|
||||||
|
size="mini"
|
||||||
|
type="text"
|
||||||
|
icon="el-icon-folder"
|
||||||
|
@click="handleArchive(scope.row)"
|
||||||
|
>归档</el-button>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<!-- 已归档项目 -->
|
||||||
|
<template v-else>
|
||||||
|
<el-button
|
||||||
|
size="mini"
|
||||||
|
type="text"
|
||||||
|
icon="el-icon-document"
|
||||||
|
@click="handleDetail(scope.row)"
|
||||||
|
>查看详情</el-button>
|
||||||
|
</template>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
</el-table>
|
||||||
|
|
||||||
|
<!-- 分页 -->
|
||||||
|
<div class="pagination-container">
|
||||||
|
<el-pagination
|
||||||
|
:current-page="pageParams.pageNum"
|
||||||
|
:page-sizes="[10, 20, 30, 50]"
|
||||||
|
:page-size="pageParams.pageSize"
|
||||||
|
:total="total"
|
||||||
|
layout="total, sizes, prev, pager, next, jumper"
|
||||||
|
@size-change="handleSizeChange"
|
||||||
|
@current-change="handleCurrentChange"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</el-card>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
name: 'ProjectTable',
|
||||||
|
props: {
|
||||||
|
loading: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false
|
||||||
|
},
|
||||||
|
dataList: {
|
||||||
|
type: Array,
|
||||||
|
default: () => []
|
||||||
|
},
|
||||||
|
total: {
|
||||||
|
type: Number,
|
||||||
|
default: 0
|
||||||
|
},
|
||||||
|
pageParams: {
|
||||||
|
type: Object,
|
||||||
|
default: () => ({
|
||||||
|
pageNum: 1,
|
||||||
|
pageSize: 10
|
||||||
|
})
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
/** 获取状态类型 */
|
||||||
|
getStatusType(status) {
|
||||||
|
const statusMap = {
|
||||||
|
'0': 'primary', // 进行中
|
||||||
|
'1': 'success', // 已完成
|
||||||
|
'2': 'info' // 已归档
|
||||||
|
}
|
||||||
|
return statusMap[status] || 'info'
|
||||||
|
},
|
||||||
|
/** 获取状态标签 */
|
||||||
|
getStatusLabel(status) {
|
||||||
|
const statusMap = {
|
||||||
|
'0': '进行中',
|
||||||
|
'1': '已完成',
|
||||||
|
'2': '已归档'
|
||||||
|
}
|
||||||
|
return statusMap[status] || '未知'
|
||||||
|
},
|
||||||
|
/** 获取预警数量样式类名 */
|
||||||
|
getWarningClass(row) {
|
||||||
|
if (row.warningCount > 20) return 'warning-high'
|
||||||
|
if (row.warningCount > 10) return 'warning-medium'
|
||||||
|
return 'warning-normal'
|
||||||
|
},
|
||||||
|
/** 进入项目 */
|
||||||
|
handleEnter(row) {
|
||||||
|
this.$emit('enter', row)
|
||||||
|
},
|
||||||
|
/** 查看详情 */
|
||||||
|
handleDetail(row) {
|
||||||
|
this.$emit('detail', row)
|
||||||
|
},
|
||||||
|
/** 查看结果 */
|
||||||
|
handleViewResult(row) {
|
||||||
|
this.$emit('view-result', row)
|
||||||
|
},
|
||||||
|
/** 重新分析 */
|
||||||
|
handleReAnalyze(row) {
|
||||||
|
this.$emit('re-analyze', row)
|
||||||
|
},
|
||||||
|
/** 归档 */
|
||||||
|
handleArchive(row) {
|
||||||
|
this.$emit('archive', row)
|
||||||
|
},
|
||||||
|
/** 分页大小变化 */
|
||||||
|
handleSizeChange(val) {
|
||||||
|
this.$emit('pagination', { pageSize: val, pageNum: 1 })
|
||||||
|
},
|
||||||
|
/** 当前页变化 */
|
||||||
|
handleCurrentChange(val) {
|
||||||
|
this.$emit('pagination', { pageNum: val })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.project-table-container {
|
||||||
|
margin-bottom: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.table-card {
|
||||||
|
border-radius: 4px;
|
||||||
|
border: 1px solid #EBEEF5;
|
||||||
|
box-shadow: 0 1px 4px rgba(0, 0, 0, 0.08);
|
||||||
|
|
||||||
|
:deep(.el-card__body) {
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.project-name-cell {
|
||||||
|
.name {
|
||||||
|
font-weight: 500;
|
||||||
|
color: #303133;
|
||||||
|
margin-bottom: 2px;
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.desc {
|
||||||
|
font-size: 12px;
|
||||||
|
color: #909399;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.count-number {
|
||||||
|
font-weight: 500;
|
||||||
|
color: #606266;
|
||||||
|
}
|
||||||
|
|
||||||
|
.warning-count-cell {
|
||||||
|
.warning-high {
|
||||||
|
color: #F56C6C;
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
|
|
||||||
|
.warning-medium {
|
||||||
|
color: #E6A23C;
|
||||||
|
font-weight: 500;
|
||||||
|
}
|
||||||
|
|
||||||
|
.warning-normal {
|
||||||
|
color: #67C23A;
|
||||||
|
font-weight: 400;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.pagination-container {
|
||||||
|
padding: 12px 16px;
|
||||||
|
display: flex;
|
||||||
|
justify-content: flex-end;
|
||||||
|
border-top: 1px solid #EBEEF5;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 表格行样式优化
|
||||||
|
:deep(.el-table) {
|
||||||
|
.el-table__row {
|
||||||
|
transition: background-color 0.3s;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background-color: #f5f7fa;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.el-table__body-wrapper {
|
||||||
|
&::-webkit-scrollbar {
|
||||||
|
width: 6px;
|
||||||
|
height: 6px;
|
||||||
|
}
|
||||||
|
|
||||||
|
&::-webkit-scrollbar-thumb {
|
||||||
|
background-color: #dcdfe6;
|
||||||
|
border-radius: 3px;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background-color: #c0c4cc;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 操作列样式
|
||||||
|
.operation-column {
|
||||||
|
.cell {
|
||||||
|
padding: 0 8px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.operation-buttons {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
gap: 2px;
|
||||||
|
flex-wrap: nowrap;
|
||||||
|
white-space: nowrap;
|
||||||
|
|
||||||
|
:deep(.el-button--mini) {
|
||||||
|
padding: 4px 6px;
|
||||||
|
font-size: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
:deep(.el-button--mini .el-icon--left) {
|
||||||
|
margin-right: 2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
:deep(.el-button + .el-button) {
|
||||||
|
margin-left: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
169
ruoyi-ui/src/views/dpcProject/components/QuickEntry.vue
Normal file
169
ruoyi-ui/src/views/dpcProject/components/QuickEntry.vue
Normal file
@@ -0,0 +1,169 @@
|
|||||||
|
<template>
|
||||||
|
<div class="quick-entry-container">
|
||||||
|
<div class="section-title">
|
||||||
|
<i class="el-icon-s-grid title-icon"></i>
|
||||||
|
<span>快捷入口</span>
|
||||||
|
</div>
|
||||||
|
<el-row :gutter="12">
|
||||||
|
<el-col :span="6">
|
||||||
|
<div class="entry-card" @click="handleImportHistory">
|
||||||
|
<div class="card-icon import-icon">
|
||||||
|
<i class="el-icon-folder-opened"></i>
|
||||||
|
</div>
|
||||||
|
<div class="card-content">
|
||||||
|
<div class="card-title">导入历史项目</div>
|
||||||
|
<div class="card-desc">从历史项目中快速创建新项目</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="6">
|
||||||
|
<div class="entry-card" @click="handleCreateQuarterly">
|
||||||
|
<div class="card-icon quarterly-icon">
|
||||||
|
<i class="el-icon-date"></i>
|
||||||
|
</div>
|
||||||
|
<div class="card-content">
|
||||||
|
<div class="card-title">创建季度初核</div>
|
||||||
|
<div class="card-desc">按季度创建初核排查项目</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="6">
|
||||||
|
<div class="entry-card" @click="handleCreateEmployee">
|
||||||
|
<div class="card-icon employee-icon">
|
||||||
|
<i class="el-icon-user"></i>
|
||||||
|
</div>
|
||||||
|
<div class="card-content">
|
||||||
|
<div class="card-title">创建新员工排查</div>
|
||||||
|
<div class="card-desc">针对新入职员工的初核排查</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="6">
|
||||||
|
<div class="entry-card" @click="handleCreateHighRisk">
|
||||||
|
<div class="card-icon highrisk-icon">
|
||||||
|
<i class="el-icon-warning"></i>
|
||||||
|
</div>
|
||||||
|
<div class="card-content">
|
||||||
|
<div class="card-title">创建高风险专项</div>
|
||||||
|
<div class="card-desc">针对高风险人员的专项排查</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</el-col>
|
||||||
|
</el-row>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
name: 'QuickEntry',
|
||||||
|
methods: {
|
||||||
|
handleImportHistory() {
|
||||||
|
this.$emit('import-history')
|
||||||
|
},
|
||||||
|
handleCreateQuarterly() {
|
||||||
|
this.$emit('create-quarterly')
|
||||||
|
},
|
||||||
|
handleCreateEmployee() {
|
||||||
|
this.$emit('create-employee')
|
||||||
|
},
|
||||||
|
handleCreateHighRisk() {
|
||||||
|
this.$emit('create-highrisk')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.quick-entry-container {
|
||||||
|
margin-top: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.section-title {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
margin-bottom: 12px;
|
||||||
|
font-size: 14px;
|
||||||
|
font-weight: 500;
|
||||||
|
color: #606266;
|
||||||
|
|
||||||
|
.title-icon {
|
||||||
|
margin-right: 6px;
|
||||||
|
color: #909399;
|
||||||
|
font-size: 16px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.entry-card {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
padding: 16px;
|
||||||
|
background: white;
|
||||||
|
border-radius: 4px;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: all 0.2s ease;
|
||||||
|
box-shadow: 0 1px 4px rgba(0, 0, 0, 0.08);
|
||||||
|
border: 1px solid #EBEEF5;
|
||||||
|
height: 100%;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
transform: translateY(-2px);
|
||||||
|
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.12);
|
||||||
|
border-color: #409EFF;
|
||||||
|
|
||||||
|
.card-icon {
|
||||||
|
transform: scale(1.05);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&:active {
|
||||||
|
transform: translateY(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.card-icon {
|
||||||
|
width: 48px;
|
||||||
|
height: 48px;
|
||||||
|
border-radius: 4px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
margin-right: 12px;
|
||||||
|
flex-shrink: 0;
|
||||||
|
transition: all 0.2s ease;
|
||||||
|
font-size: 20px;
|
||||||
|
color: white;
|
||||||
|
|
||||||
|
&.import-icon {
|
||||||
|
background-color: #667eea;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.quarterly-icon {
|
||||||
|
background-color: #f5576c;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.employee-icon {
|
||||||
|
background-color: #4facfe;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.highrisk-icon {
|
||||||
|
background-color: #F56C6C;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.card-content {
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.card-title {
|
||||||
|
font-size: 14px;
|
||||||
|
font-weight: 500;
|
||||||
|
color: #303133;
|
||||||
|
margin-bottom: 2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.card-desc {
|
||||||
|
font-size: 12px;
|
||||||
|
color: #909399;
|
||||||
|
line-height: 1.4;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
140
ruoyi-ui/src/views/dpcProject/components/SearchBar.vue
Normal file
140
ruoyi-ui/src/views/dpcProject/components/SearchBar.vue
Normal file
@@ -0,0 +1,140 @@
|
|||||||
|
<template>
|
||||||
|
<div class="search-bar-container">
|
||||||
|
<el-card class="search-card" shadow="hover">
|
||||||
|
<el-row :gutter="12" align="middle">
|
||||||
|
<el-col :span="8">
|
||||||
|
<el-input
|
||||||
|
v-model="searchKeyword"
|
||||||
|
placeholder="请输入项目名称"
|
||||||
|
prefix-icon="el-icon-search"
|
||||||
|
clearable
|
||||||
|
size="medium"
|
||||||
|
@keyup.enter.native="handleSearch"
|
||||||
|
>
|
||||||
|
<el-button
|
||||||
|
slot="append"
|
||||||
|
icon="el-icon-search"
|
||||||
|
@click="handleSearch"
|
||||||
|
>搜索</el-button>
|
||||||
|
</el-input>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="5">
|
||||||
|
<el-select
|
||||||
|
v-model="selectedStatus"
|
||||||
|
placeholder="项目状态"
|
||||||
|
clearable
|
||||||
|
size="medium"
|
||||||
|
style="width: 100%"
|
||||||
|
@change="handleStatusChange"
|
||||||
|
>
|
||||||
|
<el-option
|
||||||
|
v-for="item in statusOptions"
|
||||||
|
:key="item.value"
|
||||||
|
:label="item.label"
|
||||||
|
:value="item.value"
|
||||||
|
/>
|
||||||
|
</el-select>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="11" style="text-align: right">
|
||||||
|
<el-button
|
||||||
|
type="primary"
|
||||||
|
icon="el-icon-plus"
|
||||||
|
size="medium"
|
||||||
|
@click="handleAdd"
|
||||||
|
>新建项目</el-button>
|
||||||
|
<el-button
|
||||||
|
icon="el-icon-folder-opened"
|
||||||
|
size="medium"
|
||||||
|
@click="handleImport"
|
||||||
|
>导入历史项目</el-button>
|
||||||
|
</el-col>
|
||||||
|
</el-row>
|
||||||
|
</el-card>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
name: 'SearchBar',
|
||||||
|
props: {
|
||||||
|
showSearch: {
|
||||||
|
type: Boolean,
|
||||||
|
default: true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
searchKeyword: '',
|
||||||
|
selectedStatus: '',
|
||||||
|
statusOptions: [
|
||||||
|
{ label: '进行中', value: '0' },
|
||||||
|
{ label: '已完成', value: '1' },
|
||||||
|
{ label: '已归档', value: '2' }
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
/** 搜索 */
|
||||||
|
handleSearch() {
|
||||||
|
this.emitQuery()
|
||||||
|
},
|
||||||
|
/** 状态变化 */
|
||||||
|
handleStatusChange() {
|
||||||
|
this.emitQuery()
|
||||||
|
},
|
||||||
|
/** 发送查询 */
|
||||||
|
emitQuery() {
|
||||||
|
this.$emit('query', {
|
||||||
|
projectName: this.searchKeyword || null,
|
||||||
|
projectStatus: this.selectedStatus || null
|
||||||
|
})
|
||||||
|
},
|
||||||
|
/** 新增 */
|
||||||
|
handleAdd() {
|
||||||
|
this.$emit('add')
|
||||||
|
},
|
||||||
|
/** 导入 */
|
||||||
|
handleImport() {
|
||||||
|
this.$emit('import')
|
||||||
|
}
|
||||||
|
},
|
||||||
|
watch: {
|
||||||
|
searchKeyword(newVal) {
|
||||||
|
if (newVal === '') {
|
||||||
|
this.emitQuery()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.search-bar-container {
|
||||||
|
margin-bottom: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.search-card {
|
||||||
|
border-radius: 4px;
|
||||||
|
border: 1px solid #EBEEF5;
|
||||||
|
box-shadow: 0 1px 4px rgba(0, 0, 0, 0.08);
|
||||||
|
|
||||||
|
:deep(.el-card__body) {
|
||||||
|
padding: 12px 16px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
:deep(.el-input-group__append) {
|
||||||
|
background-color: #409EFF;
|
||||||
|
color: white;
|
||||||
|
border-color: #409EFF;
|
||||||
|
cursor: pointer;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background-color: #66b1ff;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
:deep(.el-button--medium) {
|
||||||
|
padding: 10px 16px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
264
ruoyi-ui/src/views/dpcProject/index.vue
Normal file
264
ruoyi-ui/src/views/dpcProject/index.vue
Normal file
@@ -0,0 +1,264 @@
|
|||||||
|
<template>
|
||||||
|
<div class="app-container dpc-project-container">
|
||||||
|
<!-- 页面标题 -->
|
||||||
|
<div class="page-header">
|
||||||
|
<h2 class="page-title">初核项目管理</h2>
|
||||||
|
<p class="page-subtitle">管理纪检初核排查项目,跟踪预警信息</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 搜索和操作区 -->
|
||||||
|
<search-bar
|
||||||
|
:show-search="showSearch"
|
||||||
|
@query="handleQuery"
|
||||||
|
@add="handleAdd"
|
||||||
|
@import="handleImport"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<!-- 项目列表表格 -->
|
||||||
|
<project-table
|
||||||
|
:loading="loading"
|
||||||
|
:data-list="projectList"
|
||||||
|
:total="total"
|
||||||
|
:page-params="queryParams"
|
||||||
|
@pagination="getList"
|
||||||
|
@detail="handleDetail"
|
||||||
|
@enter="handleEnter"
|
||||||
|
@view-result="handleViewResult"
|
||||||
|
@re-analyze="handleReAnalyze"
|
||||||
|
@archive="handleArchive"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<!-- 快捷入口区 -->
|
||||||
|
<quick-entry
|
||||||
|
@import-history="handleImport"
|
||||||
|
@create-quarterly="handleCreateQuarterly"
|
||||||
|
@create-employee="handleCreateEmployee"
|
||||||
|
@create-highrisk="handleCreateHighRisk"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<!-- 新建项目弹窗 -->
|
||||||
|
<add-project-dialog
|
||||||
|
:visible.sync="addDialogVisible"
|
||||||
|
:title="addDialogTitle"
|
||||||
|
:form="projectForm"
|
||||||
|
@submit="handleSubmitProject"
|
||||||
|
@close="handleCloseAddDialog"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<!-- 导入历史项目弹窗 -->
|
||||||
|
<import-history-dialog
|
||||||
|
:visible.sync="importDialogVisible"
|
||||||
|
@submit="handleSubmitImport"
|
||||||
|
@close="handleCloseImportDialog"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<!-- 项目归档确认弹窗 -->
|
||||||
|
<archive-confirm-dialog
|
||||||
|
:visible.sync="archiveDialogVisible"
|
||||||
|
:project-data="currentArchiveProject"
|
||||||
|
@confirm="handleConfirmArchive"
|
||||||
|
@close="archiveDialogVisible = false"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import {getMockProjectList} from '@/api/dpcProject'
|
||||||
|
import SearchBar from './components/SearchBar'
|
||||||
|
import ProjectTable from './components/ProjectTable'
|
||||||
|
import QuickEntry from './components/QuickEntry'
|
||||||
|
import AddProjectDialog from './components/AddProjectDialog'
|
||||||
|
import ImportHistoryDialog from './components/ImportHistoryDialog'
|
||||||
|
import ArchiveConfirmDialog from './components/ArchiveConfirmDialog'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: 'DpcProject',
|
||||||
|
components: {
|
||||||
|
SearchBar,
|
||||||
|
ProjectTable,
|
||||||
|
QuickEntry,
|
||||||
|
AddProjectDialog,
|
||||||
|
ImportHistoryDialog,
|
||||||
|
ArchiveConfirmDialog
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
// 加载状态
|
||||||
|
loading: true,
|
||||||
|
// 显示搜索栏
|
||||||
|
showSearch: true,
|
||||||
|
// 总条数
|
||||||
|
total: 0,
|
||||||
|
// 项目列表
|
||||||
|
projectList: [],
|
||||||
|
// 查询参数
|
||||||
|
queryParams: {
|
||||||
|
pageNum: 1,
|
||||||
|
pageSize: 10,
|
||||||
|
projectName: null,
|
||||||
|
projectStatus: null
|
||||||
|
},
|
||||||
|
// 新增/编辑弹窗
|
||||||
|
addDialogVisible: false,
|
||||||
|
addDialogTitle: '新建项目',
|
||||||
|
projectForm: {},
|
||||||
|
// 导入历史项目弹窗
|
||||||
|
importDialogVisible: false,
|
||||||
|
// 归档确认弹窗
|
||||||
|
archiveDialogVisible: false,
|
||||||
|
currentArchiveProject: null
|
||||||
|
}
|
||||||
|
},
|
||||||
|
created() {
|
||||||
|
this.getList()
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
/** 查询项目列表 */
|
||||||
|
getList() {
|
||||||
|
this.loading = true
|
||||||
|
// 使用Mock数据
|
||||||
|
getMockProjectList().then(response => {
|
||||||
|
this.projectList = response.rows
|
||||||
|
this.total = response.total
|
||||||
|
this.loading = false
|
||||||
|
}).catch(() => {
|
||||||
|
this.loading = false
|
||||||
|
})
|
||||||
|
},
|
||||||
|
/** 搜索按钮操作 */
|
||||||
|
handleQuery(queryParams) {
|
||||||
|
if (queryParams) {
|
||||||
|
this.queryParams = { ...this.queryParams, ...queryParams }
|
||||||
|
}
|
||||||
|
this.queryParams.pageNum = 1
|
||||||
|
this.getList()
|
||||||
|
},
|
||||||
|
/** 新增按钮操作 */
|
||||||
|
handleAdd() {
|
||||||
|
this.projectForm = this.getEmptyForm()
|
||||||
|
this.addDialogTitle = '新建项目'
|
||||||
|
this.addDialogVisible = true
|
||||||
|
},
|
||||||
|
/** 获取空表单 */
|
||||||
|
getEmptyForm() {
|
||||||
|
return {
|
||||||
|
projectId: null,
|
||||||
|
projectName: '',
|
||||||
|
projectDesc: '',
|
||||||
|
startDate: '',
|
||||||
|
endDate: '',
|
||||||
|
targetCount: 0,
|
||||||
|
targetPersons: []
|
||||||
|
}
|
||||||
|
},
|
||||||
|
/** 关闭新增弹窗 */
|
||||||
|
handleCloseAddDialog() {
|
||||||
|
this.addDialogVisible = false
|
||||||
|
this.projectForm = {}
|
||||||
|
},
|
||||||
|
/** 提交项目表单 */
|
||||||
|
handleSubmitProject(data) {
|
||||||
|
// 这里应该调用实际的API
|
||||||
|
console.log('提交项目数据:', data)
|
||||||
|
this.$modal.msgSuccess('项目创建成功')
|
||||||
|
this.addDialogVisible = false
|
||||||
|
this.getList()
|
||||||
|
},
|
||||||
|
/** 导入历史项目 */
|
||||||
|
handleImport() {
|
||||||
|
this.importDialogVisible = true
|
||||||
|
},
|
||||||
|
/** 关闭导入弹窗 */
|
||||||
|
handleCloseImportDialog() {
|
||||||
|
this.importDialogVisible = false
|
||||||
|
},
|
||||||
|
/** 提交导入 */
|
||||||
|
handleSubmitImport(data) {
|
||||||
|
console.log('导入历史项目:', data)
|
||||||
|
this.$modal.msgSuccess('项目导入成功')
|
||||||
|
this.importDialogVisible = false
|
||||||
|
this.getList()
|
||||||
|
},
|
||||||
|
/** 创建季度初核 */
|
||||||
|
handleCreateQuarterly() {
|
||||||
|
this.projectForm = this.getEmptyForm()
|
||||||
|
this.addDialogTitle = '创建季度初核项目'
|
||||||
|
this.addDialogVisible = true
|
||||||
|
},
|
||||||
|
/** 创建新员工排查 */
|
||||||
|
handleCreateEmployee() {
|
||||||
|
this.projectForm = this.getEmptyForm()
|
||||||
|
this.addDialogTitle = '创建新员工排查项目'
|
||||||
|
this.addDialogVisible = true
|
||||||
|
},
|
||||||
|
/** 创建高风险专项 */
|
||||||
|
handleCreateHighRisk() {
|
||||||
|
this.projectForm = this.getEmptyForm()
|
||||||
|
this.addDialogTitle = '创建高风险专项项目'
|
||||||
|
this.addDialogVisible = true
|
||||||
|
},
|
||||||
|
/** 查看详情 */
|
||||||
|
handleDetail(row) {
|
||||||
|
console.log('查看详情:', row)
|
||||||
|
this.$modal.msgInfo('查看项目详情: ' + row.projectName)
|
||||||
|
},
|
||||||
|
/** 进入项目 */
|
||||||
|
handleEnter(row) {
|
||||||
|
console.log('进入项目:', row)
|
||||||
|
this.$modal.msgSuccess('进入项目: ' + row.projectName)
|
||||||
|
},
|
||||||
|
/** 查看结果 */
|
||||||
|
handleViewResult(row) {
|
||||||
|
console.log('查看结果:', row)
|
||||||
|
this.$modal.msgInfo('查看项目结果: ' + row.projectName)
|
||||||
|
},
|
||||||
|
/** 重新分析 */
|
||||||
|
handleReAnalyze(row) {
|
||||||
|
console.log('重新分析:', row)
|
||||||
|
this.$modal.msgSuccess('正在重新分析项目: ' + row.projectName)
|
||||||
|
},
|
||||||
|
/** 归档项目 */
|
||||||
|
handleArchive(row) {
|
||||||
|
this.currentArchiveProject = row
|
||||||
|
this.archiveDialogVisible = true
|
||||||
|
},
|
||||||
|
/** 确认归档 */
|
||||||
|
handleConfirmArchive(data) {
|
||||||
|
console.log('确认归档:', data)
|
||||||
|
this.$modal.msgSuccess('项目已归档')
|
||||||
|
this.archiveDialogVisible = false
|
||||||
|
this.getList()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.dpc-project-container {
|
||||||
|
padding: 16px;
|
||||||
|
background: #f0f2f5;
|
||||||
|
min-height: calc(100vh - 140px);
|
||||||
|
}
|
||||||
|
|
||||||
|
.page-header {
|
||||||
|
margin-bottom: 12px;
|
||||||
|
padding: 16px 20px;
|
||||||
|
background: #ffffff;
|
||||||
|
border-radius: 4px;
|
||||||
|
box-shadow: 0 1px 4px rgba(0, 0, 0, 0.08);
|
||||||
|
|
||||||
|
.page-title {
|
||||||
|
margin: 0;
|
||||||
|
font-size: 18px;
|
||||||
|
font-weight: 500;
|
||||||
|
color: #303133;
|
||||||
|
}
|
||||||
|
|
||||||
|
.page-subtitle {
|
||||||
|
margin: 4px 0 0 0;
|
||||||
|
font-size: 13px;
|
||||||
|
color: #909399;
|
||||||
|
font-weight: 400;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -1,98 +0,0 @@
|
|||||||
<template>
|
|
||||||
<div class="dashboard-editor-container">
|
|
||||||
|
|
||||||
<panel-group @handleSetLineChartData="handleSetLineChartData" />
|
|
||||||
|
|
||||||
<el-row style="background:#fff;padding:16px 16px 0;margin-bottom:32px;">
|
|
||||||
<line-chart :chart-data="lineChartData" />
|
|
||||||
</el-row>
|
|
||||||
|
|
||||||
<el-row :gutter="32">
|
|
||||||
<el-col :xs="24" :sm="24" :lg="8">
|
|
||||||
<div class="chart-wrapper">
|
|
||||||
<raddar-chart />
|
|
||||||
</div>
|
|
||||||
</el-col>
|
|
||||||
<el-col :xs="24" :sm="24" :lg="8">
|
|
||||||
<div class="chart-wrapper">
|
|
||||||
<pie-chart />
|
|
||||||
</div>
|
|
||||||
</el-col>
|
|
||||||
<el-col :xs="24" :sm="24" :lg="8">
|
|
||||||
<div class="chart-wrapper">
|
|
||||||
<bar-chart />
|
|
||||||
</div>
|
|
||||||
</el-col>
|
|
||||||
</el-row>
|
|
||||||
|
|
||||||
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
import PanelGroup from './dashboard/PanelGroup'
|
|
||||||
import LineChart from './dashboard/LineChart'
|
|
||||||
import RaddarChart from './dashboard/RaddarChart'
|
|
||||||
import PieChart from './dashboard/PieChart'
|
|
||||||
import BarChart from './dashboard/BarChart'
|
|
||||||
|
|
||||||
const lineChartData = {
|
|
||||||
newVisitis: {
|
|
||||||
expectedData: [100, 120, 161, 134, 105, 160, 165],
|
|
||||||
actualData: [120, 82, 91, 154, 162, 140, 145]
|
|
||||||
},
|
|
||||||
messages: {
|
|
||||||
expectedData: [200, 192, 120, 144, 160, 130, 140],
|
|
||||||
actualData: [180, 160, 151, 106, 145, 150, 130]
|
|
||||||
},
|
|
||||||
purchases: {
|
|
||||||
expectedData: [80, 100, 121, 104, 105, 90, 100],
|
|
||||||
actualData: [120, 90, 100, 138, 142, 130, 130]
|
|
||||||
},
|
|
||||||
shoppings: {
|
|
||||||
expectedData: [130, 140, 141, 142, 145, 150, 160],
|
|
||||||
actualData: [120, 82, 91, 154, 162, 140, 130]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export default {
|
|
||||||
name: 'Index',
|
|
||||||
components: {
|
|
||||||
PanelGroup,
|
|
||||||
LineChart,
|
|
||||||
RaddarChart,
|
|
||||||
PieChart,
|
|
||||||
BarChart
|
|
||||||
},
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
lineChartData: lineChartData.newVisitis
|
|
||||||
}
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
handleSetLineChartData(type) {
|
|
||||||
this.lineChartData = lineChartData[type]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
|
||||||
.dashboard-editor-container {
|
|
||||||
padding: 32px;
|
|
||||||
background-color: rgb(240, 242, 245);
|
|
||||||
position: relative;
|
|
||||||
|
|
||||||
.chart-wrapper {
|
|
||||||
background: #fff;
|
|
||||||
padding: 16px 16px 0;
|
|
||||||
margin-bottom: 32px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@media (max-width:1024px) {
|
|
||||||
.chart-wrapper {
|
|
||||||
padding: 8px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
@@ -62,9 +62,9 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { getCodeImg } from "@/api/login"
|
import {getCodeImg} from "@/api/login"
|
||||||
import Cookies from "js-cookie"
|
import Cookies from "js-cookie"
|
||||||
import { encrypt, decrypt } from '@/utils/jsencrypt'
|
import {decrypt, encrypt} from '@/utils/jsencrypt'
|
||||||
import defaultSettings from '@/settings'
|
import defaultSettings from '@/settings'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
@@ -94,16 +94,7 @@ export default {
|
|||||||
// 验证码开关
|
// 验证码开关
|
||||||
captchaEnabled: true,
|
captchaEnabled: true,
|
||||||
// 注册开关
|
// 注册开关
|
||||||
register: false,
|
register: false
|
||||||
redirect: undefined
|
|
||||||
}
|
|
||||||
},
|
|
||||||
watch: {
|
|
||||||
$route: {
|
|
||||||
handler: function(route) {
|
|
||||||
this.redirect = route.query && route.query.redirect
|
|
||||||
},
|
|
||||||
immediate: true
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
created() {
|
created() {
|
||||||
@@ -144,7 +135,7 @@ export default {
|
|||||||
Cookies.remove('rememberMe')
|
Cookies.remove('rememberMe')
|
||||||
}
|
}
|
||||||
this.$store.dispatch("Login", this.loginForm).then(() => {
|
this.$store.dispatch("Login", this.loginForm).then(() => {
|
||||||
this.$router.push({ path: this.redirect || "/" }).catch(()=>{})
|
this.$router.push({ path: "/" }).catch(()=>{})
|
||||||
}).catch(() => {
|
}).catch(() => {
|
||||||
this.loading = false
|
this.loading = false
|
||||||
if (this.captchaEnabled) {
|
if (this.captchaEnabled) {
|
||||||
|
|||||||
Reference in New Issue
Block a user