882 lines
20 KiB
Markdown
882 lines
20 KiB
Markdown
|
|
# 创建项目功能 - 前端实施计划
|
|||
|
|
|
|||
|
|
> **For Claude:** REQUIRED SUB-SKILL: Use superpowers:executing-plans to implement this plan task-by-task.
|
|||
|
|
|
|||
|
|
**目标:** 实现创建项目功能的前端界面,包括弹窗表单、项目列表展示、API调用
|
|||
|
|
|
|||
|
|
**架构:** 基于 Vue 2.6.12 + Element UI 2.15.14,采用组件化开发
|
|||
|
|
|
|||
|
|
**技术栈:** Vue.js 2.6.12, Element UI 2.15.14, Axios 0.28.1
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 前置条件
|
|||
|
|
|
|||
|
|
- 后端接口已部署并测试通过
|
|||
|
|
- 前端项目依赖已安装
|
|||
|
|
- 已有测试账号(admin/admin123)
|
|||
|
|
- 后端服务运行在 http://localhost:8080
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## Task 1: 更新 API 接口文件
|
|||
|
|
|
|||
|
|
**文件:**
|
|||
|
|
- Modify: `ruoyi-ui/src/api/ccdiProject.js`
|
|||
|
|
|
|||
|
|
**Step 1: 备份原文件**
|
|||
|
|
|
|||
|
|
```bash
|
|||
|
|
cp ruoyi-ui/src/api/ccdiProject.js ruoyi-ui/src/api/ccdiProject.js.bak
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**Step 2: 修改 API 文件**
|
|||
|
|
|
|||
|
|
将 `ruoyi-ui/src/api/ccdiProject.js` 修改为以下内容:
|
|||
|
|
|
|||
|
|
```javascript
|
|||
|
|
import request from '@/utils/request'
|
|||
|
|
|
|||
|
|
// 创建初核项目
|
|||
|
|
export function createProject(data) {
|
|||
|
|
return request({
|
|||
|
|
url: '/ccdi/project',
|
|||
|
|
method: 'post',
|
|||
|
|
data: data
|
|||
|
|
})
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 查询初核项目列表(分页)
|
|||
|
|
export function listProject(query) {
|
|||
|
|
return request({
|
|||
|
|
url: '/ccdi/project/list',
|
|||
|
|
method: 'get',
|
|||
|
|
params: query
|
|||
|
|
})
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 查询初核项目详细
|
|||
|
|
export function getProject(projectId) {
|
|||
|
|
return request({
|
|||
|
|
url: '/ccdi/project/' + projectId,
|
|||
|
|
method: 'get'
|
|||
|
|
})
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 修改初核项目
|
|||
|
|
export function updateProject(data) {
|
|||
|
|
return request({
|
|||
|
|
url: '/ccdi/project',
|
|||
|
|
method: 'put',
|
|||
|
|
data: data
|
|||
|
|
})
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 删除初核项目
|
|||
|
|
export function delProject(projectId) {
|
|||
|
|
return request({
|
|||
|
|
url: '/ccdi/project/' + projectId,
|
|||
|
|
method: 'delete'
|
|||
|
|
})
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 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',
|
|||
|
|
configType: 'default',
|
|||
|
|
targetCount: 500,
|
|||
|
|
highRiskCount: 5,
|
|||
|
|
mediumRiskCount: 10,
|
|||
|
|
lowRiskCount: 0
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
projectId: 2,
|
|||
|
|
projectName: '2023年Q4初核',
|
|||
|
|
projectDesc: '2023年第四季度纪检初核排查工作',
|
|||
|
|
createTime: '2023-10-01',
|
|||
|
|
projectStatus: '1',
|
|||
|
|
configType: 'custom',
|
|||
|
|
targetCount: 480,
|
|||
|
|
highRiskCount: 8,
|
|||
|
|
mediumRiskCount: 15,
|
|||
|
|
lowRiskCount: 0
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
projectId: 3,
|
|||
|
|
projectName: '2023年Q3初核',
|
|||
|
|
projectDesc: '2023年第三季度纪检初核排查工作',
|
|||
|
|
createTime: '2023-07-01',
|
|||
|
|
projectStatus: '2',
|
|||
|
|
configType: 'default',
|
|||
|
|
targetCount: 450,
|
|||
|
|
highRiskCount: 0,
|
|||
|
|
mediumRiskCount: 18,
|
|||
|
|
lowRiskCount: 5
|
|||
|
|
}
|
|||
|
|
]
|
|||
|
|
})
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**Step 3: 验证语法**
|
|||
|
|
|
|||
|
|
```bash
|
|||
|
|
cd ruoyi-ui && npm run lint -- --fix src/api/ccdiProject.js
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
预期输出:无 ESLint 错误
|
|||
|
|
|
|||
|
|
**Step 4: 提交代码**
|
|||
|
|
|
|||
|
|
```bash
|
|||
|
|
git add ruoyi-ui/src/api/ccdiProject.js
|
|||
|
|
git commit -m "feat: 更新项目API接口,添加创建项目接口"
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## Task 2: 修改 AddProjectDialog 组件
|
|||
|
|
|
|||
|
|
**文件:**
|
|||
|
|
- Modify: `ruoyi-ui/src/views/ccdiProject/components/AddProjectDialog.vue`
|
|||
|
|
|
|||
|
|
**Step 1: 备份原文件**
|
|||
|
|
|
|||
|
|
```bash
|
|||
|
|
cp ruoyi-ui/src/views/ccdiProject/components/AddProjectDialog.vue ruoyi-ui/src/views/ccdiProject/components/AddProjectDialog.vue.bak
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**Step 2: 重写组件**
|
|||
|
|
|
|||
|
|
将 `ruoyi-ui/src/views/ccdiProject/components/AddProjectDialog.vue` 重写为以下内容:
|
|||
|
|
|
|||
|
|
```vue
|
|||
|
|
<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="100"
|
|||
|
|
show-word-limit
|
|||
|
|
/>
|
|||
|
|
</el-form-item>
|
|||
|
|
|
|||
|
|
<!-- 项目描述 -->
|
|||
|
|
<el-form-item label="项目描述" prop="projectDesc">
|
|||
|
|
<el-input
|
|||
|
|
v-model="formData.projectDesc"
|
|||
|
|
type="textarea"
|
|||
|
|
:rows="4"
|
|||
|
|
placeholder="请输入项目描述"
|
|||
|
|
maxlength="500"
|
|||
|
|
show-word-limit
|
|||
|
|
/>
|
|||
|
|
</el-form-item>
|
|||
|
|
|
|||
|
|
<!-- 配置方式 -->
|
|||
|
|
<el-form-item label="配置方式" prop="configType">
|
|||
|
|
<el-radio-group v-model="formData.configType">
|
|||
|
|
<el-radio label="default">全局默认模型参数配置</el-radio>
|
|||
|
|
<el-radio label="custom">自定义项目规则参数配置</el-radio>
|
|||
|
|
</el-radio-group>
|
|||
|
|
</el-form-item>
|
|||
|
|
</el-form>
|
|||
|
|
|
|||
|
|
<div slot="footer" class="dialog-footer">
|
|||
|
|
<el-button @click="handleClose">取 消</el-button>
|
|||
|
|
<el-button type="primary" :loading="submitting" @click="handleSubmit">
|
|||
|
|
创建项目
|
|||
|
|
</el-button>
|
|||
|
|
</div>
|
|||
|
|
</el-dialog>
|
|||
|
|
</template>
|
|||
|
|
|
|||
|
|
<script>
|
|||
|
|
import { createProject } from '@/api/ccdiProject'
|
|||
|
|
|
|||
|
|
export default {
|
|||
|
|
name: 'AddProjectDialog',
|
|||
|
|
props: {
|
|||
|
|
visible: {
|
|||
|
|
type: Boolean,
|
|||
|
|
default: false
|
|||
|
|
},
|
|||
|
|
title: {
|
|||
|
|
type: String,
|
|||
|
|
default: '新建项目'
|
|||
|
|
},
|
|||
|
|
form: {
|
|||
|
|
type: Object,
|
|||
|
|
default: () => ({})
|
|||
|
|
}
|
|||
|
|
},
|
|||
|
|
data() {
|
|||
|
|
return {
|
|||
|
|
submitting: false,
|
|||
|
|
formData: {
|
|||
|
|
projectName: '',
|
|||
|
|
projectDesc: '',
|
|||
|
|
configType: 'default'
|
|||
|
|
},
|
|||
|
|
rules: {
|
|||
|
|
projectName: [
|
|||
|
|
{ required: true, message: '请输入项目名称', trigger: 'blur' },
|
|||
|
|
{ min: 2, max: 100, message: '长度在 2 到 100 个字符', trigger: 'blur' }
|
|||
|
|
],
|
|||
|
|
configType: [
|
|||
|
|
{ required: true, message: '请选择配置方式', trigger: 'change' }
|
|||
|
|
]
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
},
|
|||
|
|
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: {
|
|||
|
|
/** 提交表单 */
|
|||
|
|
handleSubmit() {
|
|||
|
|
this.$refs.projectForm.validate(valid => {
|
|||
|
|
if (valid) {
|
|||
|
|
this.submitting = true
|
|||
|
|
createProject(this.formData).then(response => {
|
|||
|
|
this.$message.success('项目创建成功')
|
|||
|
|
this.submitting = false
|
|||
|
|
this.$emit('submit', response.data)
|
|||
|
|
this.handleClose()
|
|||
|
|
}).catch(() => {
|
|||
|
|
this.submitting = false
|
|||
|
|
})
|
|||
|
|
}
|
|||
|
|
})
|
|||
|
|
},
|
|||
|
|
|
|||
|
|
/** 关闭对话框 */
|
|||
|
|
handleClose() {
|
|||
|
|
this.$emit('close')
|
|||
|
|
this.$refs.projectForm.resetFields()
|
|||
|
|
this.formData = {
|
|||
|
|
projectName: '',
|
|||
|
|
projectDesc: '',
|
|||
|
|
configType: 'default'
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
</script>
|
|||
|
|
|
|||
|
|
<style lang="scss" scoped>
|
|||
|
|
.dialog-footer {
|
|||
|
|
text-align: right;
|
|||
|
|
|
|||
|
|
.el-button + .el-button {
|
|||
|
|
margin-left: 8px;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
:deep(.el-radio-group) {
|
|||
|
|
display: flex;
|
|||
|
|
flex-direction: column;
|
|||
|
|
gap: 12px;
|
|||
|
|
|
|||
|
|
.el-radio {
|
|||
|
|
line-height: 32px;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
</style>
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**Step 3: 验证语法**
|
|||
|
|
|
|||
|
|
```bash
|
|||
|
|
cd ruoyi-ui && npm run lint -- --fix src/views/ccdiProject/components/AddProjectDialog.vue
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
预期输出:无 ESLint 错误
|
|||
|
|
|
|||
|
|
**Step 4: 提交代码**
|
|||
|
|
|
|||
|
|
```bash
|
|||
|
|
git add ruoyi-ui/src/views/ccdiProject/components/AddProjectDialog.vue
|
|||
|
|
git commit -m "feat: 简化项目创建弹窗,只保留3个核心字段"
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## Task 3: 修改 ProjectTable 组件
|
|||
|
|
|
|||
|
|
**文件:**
|
|||
|
|
- Modify: `ruoyi-ui/src/views/ccdiProject/components/ProjectTable.vue`
|
|||
|
|
|
|||
|
|
**Step 1: 备份原文件**
|
|||
|
|
|
|||
|
|
```bash
|
|||
|
|
cp ruoyi-ui/src/views/ccdiProject/components/ProjectTable.vue ruoyi-ui/src/views/ccdiProject/components/ProjectTable.vue.bak
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**Step 2: 重写组件**
|
|||
|
|
|
|||
|
|
将 `ruoyi-ui/src/views/ccdiProject/components/ProjectTable.vue` 重写为以下内容:
|
|||
|
|
|
|||
|
|
```vue
|
|||
|
|
<template>
|
|||
|
|
<div class="project-table-container">
|
|||
|
|
<el-table
|
|||
|
|
:data="dataList"
|
|||
|
|
:loading="loading"
|
|||
|
|
border
|
|||
|
|
style="width: 100%"
|
|||
|
|
>
|
|||
|
|
<!-- 项目名称(含描述) -->
|
|||
|
|
<el-table-column
|
|||
|
|
label="项目名称"
|
|||
|
|
min-width="300"
|
|||
|
|
align="left"
|
|||
|
|
>
|
|||
|
|
<template slot-scope="scope">
|
|||
|
|
<div class="project-info-cell">
|
|||
|
|
<div class="project-name">{{ scope.row.projectName }}</div>
|
|||
|
|
<div class="project-desc">{{ scope.row.projectDesc || '暂无描述' }}</div>
|
|||
|
|
</div>
|
|||
|
|
</template>
|
|||
|
|
</el-table-column>
|
|||
|
|
|
|||
|
|
<!-- 项目状态 -->
|
|||
|
|
<el-table-column
|
|||
|
|
prop="projectStatus"
|
|||
|
|
label="项目状态"
|
|||
|
|
width="100"
|
|||
|
|
align="center"
|
|||
|
|
>
|
|||
|
|
<template slot-scope="scope">
|
|||
|
|
<el-tag :type="getStatusType(scope.row.projectStatus)">
|
|||
|
|
<dict-tag :options="dict.type.ccdi_project_status" :value="scope.row.projectStatus"/>
|
|||
|
|
</el-tag>
|
|||
|
|
</template>
|
|||
|
|
</el-table-column>
|
|||
|
|
|
|||
|
|
<!-- 目标人数 -->
|
|||
|
|
<el-table-column
|
|||
|
|
prop="targetCount"
|
|||
|
|
label="目标人数"
|
|||
|
|
width="100"
|
|||
|
|
align="center"
|
|||
|
|
/>
|
|||
|
|
|
|||
|
|
<!-- 预警人数(带悬停详情) -->
|
|||
|
|
<el-table-column
|
|||
|
|
label="预警人数"
|
|||
|
|
width="120"
|
|||
|
|
align="center"
|
|||
|
|
>
|
|||
|
|
<template slot-scope="scope">
|
|||
|
|
<el-tooltip placement="top" effect="light">
|
|||
|
|
<div slot="content">
|
|||
|
|
<div style="padding: 8px;">
|
|||
|
|
<div style="margin-bottom: 8px; font-weight: bold; color: #303133;">
|
|||
|
|
风险人数统计
|
|||
|
|
</div>
|
|||
|
|
<div style="margin-bottom: 6px;">
|
|||
|
|
<span style="color: #f56c6c;">● 高风险:</span>
|
|||
|
|
<span style="font-weight: bold;">{{ scope.row.highRiskCount }} 人</span>
|
|||
|
|
</div>
|
|||
|
|
<div style="margin-bottom: 6px;">
|
|||
|
|
<span style="color: #e6a23c;">● 中风险:</span>
|
|||
|
|
<span style="font-weight: bold;">{{ scope.row.mediumRiskCount }} 人</span>
|
|||
|
|
</div>
|
|||
|
|
<div>
|
|||
|
|
<span style="color: #909399;">● 低风险:</span>
|
|||
|
|
<span style="font-weight: bold;">{{ scope.row.lowRiskCount }} 人</span>
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
<div class="warning-count-wrapper">
|
|||
|
|
<span :class="getWarningClass(scope.row)" style="cursor: pointer;">
|
|||
|
|
{{ scope.row.highRiskCount + scope.row.mediumRiskCount + scope.row.lowRiskCount }}
|
|||
|
|
</span>
|
|||
|
|
</div>
|
|||
|
|
</el-tooltip>
|
|||
|
|
</template>
|
|||
|
|
</el-table-column>
|
|||
|
|
|
|||
|
|
<!-- 创建人 -->
|
|||
|
|
<el-table-column
|
|||
|
|
prop="createBy"
|
|||
|
|
label="创建人"
|
|||
|
|
width="120"
|
|||
|
|
align="center"
|
|||
|
|
/>
|
|||
|
|
|
|||
|
|
<!-- 创建时间 -->
|
|||
|
|
<el-table-column
|
|||
|
|
prop="createTime"
|
|||
|
|
label="创建时间"
|
|||
|
|
width="160"
|
|||
|
|
align="center"
|
|||
|
|
>
|
|||
|
|
<template slot-scope="scope">
|
|||
|
|
<span>{{ parseTime(scope.row.createTime) }}</span>
|
|||
|
|
</template>
|
|||
|
|
</el-table-column>
|
|||
|
|
|
|||
|
|
<!-- 操作列 -->
|
|||
|
|
<el-table-column
|
|||
|
|
label="操作"
|
|||
|
|
width="200"
|
|||
|
|
align="center"
|
|||
|
|
fixed="right"
|
|||
|
|
>
|
|||
|
|
<template slot-scope="scope">
|
|||
|
|
<el-button
|
|||
|
|
size="mini"
|
|||
|
|
type="text"
|
|||
|
|
icon="el-icon-view"
|
|||
|
|
@click="handleDetail(scope.row)"
|
|||
|
|
>详情</el-button>
|
|||
|
|
<el-button
|
|||
|
|
size="mini"
|
|||
|
|
type="text"
|
|||
|
|
icon="el-icon-edit"
|
|||
|
|
@click="handleEdit(scope.row)"
|
|||
|
|
>编辑</el-button>
|
|||
|
|
<el-button
|
|||
|
|
size="mini"
|
|||
|
|
type="text"
|
|||
|
|
icon="el-icon-delete"
|
|||
|
|
@click="handleDelete(scope.row)"
|
|||
|
|
>删除</el-button>
|
|||
|
|
</template>
|
|||
|
|
</el-table-column>
|
|||
|
|
</el-table>
|
|||
|
|
|
|||
|
|
<!-- 分页 -->
|
|||
|
|
<el-pagination
|
|||
|
|
v-show="total > 0"
|
|||
|
|
:current-page="pageParams.pageNum"
|
|||
|
|
:page-size="pageParams.pageSize"
|
|||
|
|
:page-sizes="[10, 20, 30, 50]"
|
|||
|
|
:total="total"
|
|||
|
|
layout="total, sizes, prev, pager, next, jumper"
|
|||
|
|
@size-change="handleSizeChange"
|
|||
|
|
@current-change="handleCurrentChange"
|
|||
|
|
style="margin-top: 16px; text-align: right;"
|
|||
|
|
/>
|
|||
|
|
</div>
|
|||
|
|
</template>
|
|||
|
|
|
|||
|
|
<script>
|
|||
|
|
export default {
|
|||
|
|
name: 'ProjectTable',
|
|||
|
|
dicts: ['ccdi_project_status', 'ccdi_config_type'],
|
|||
|
|
props: {
|
|||
|
|
dataList: {
|
|||
|
|
type: Array,
|
|||
|
|
default: () => []
|
|||
|
|
},
|
|||
|
|
loading: {
|
|||
|
|
type: Boolean,
|
|||
|
|
default: false
|
|||
|
|
},
|
|||
|
|
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'
|
|||
|
|
},
|
|||
|
|
|
|||
|
|
getWarningClass(row) {
|
|||
|
|
const total = row.highRiskCount + row.mediumRiskCount + row.lowRiskCount
|
|||
|
|
if (row.highRiskCount > 0) {
|
|||
|
|
return 'text-danger text-bold'
|
|||
|
|
} else if (row.mediumRiskCount > 0) {
|
|||
|
|
return 'text-warning text-bold'
|
|||
|
|
} else if (total > 0) {
|
|||
|
|
return 'text-info'
|
|||
|
|
}
|
|||
|
|
return ''
|
|||
|
|
},
|
|||
|
|
|
|||
|
|
handleDetail(row) {
|
|||
|
|
this.$emit('detail', row)
|
|||
|
|
},
|
|||
|
|
|
|||
|
|
handleEdit(row) {
|
|||
|
|
this.$emit('edit', row)
|
|||
|
|
},
|
|||
|
|
|
|||
|
|
handleDelete(row) {
|
|||
|
|
this.$emit('delete', row)
|
|||
|
|
},
|
|||
|
|
|
|||
|
|
handleSizeChange(val) {
|
|||
|
|
this.$emit('pagination', { pageNum: this.pageParams.pageNum, pageSize: val })
|
|||
|
|
},
|
|||
|
|
|
|||
|
|
handleCurrentChange(val) {
|
|||
|
|
this.$emit('pagination', { pageNum: val, pageSize: this.pageParams.pageSize })
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
</script>
|
|||
|
|
|
|||
|
|
<style lang="scss" scoped>
|
|||
|
|
.project-table-container {
|
|||
|
|
margin-top: 16px;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.project-info-cell {
|
|||
|
|
padding: 8px 0;
|
|||
|
|
line-height: 1.5;
|
|||
|
|
|
|||
|
|
.project-name {
|
|||
|
|
font-size: 14px;
|
|||
|
|
font-weight: 600;
|
|||
|
|
color: #303133;
|
|||
|
|
margin-bottom: 4px;
|
|||
|
|
overflow: hidden;
|
|||
|
|
text-overflow: ellipsis;
|
|||
|
|
white-space: nowrap;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.project-desc {
|
|||
|
|
font-size: 12px;
|
|||
|
|
color: #909399;
|
|||
|
|
overflow: hidden;
|
|||
|
|
text-overflow: ellipsis;
|
|||
|
|
white-space: nowrap;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.warning-count-wrapper {
|
|||
|
|
display: inline-block;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.text-danger {
|
|||
|
|
color: #f56c6c;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.text-warning {
|
|||
|
|
color: #e6a23c;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.text-info {
|
|||
|
|
color: #909399;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.text-bold {
|
|||
|
|
font-weight: bold;
|
|||
|
|
}
|
|||
|
|
</style>
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**Step 3: 验证语法**
|
|||
|
|
|
|||
|
|
```bash
|
|||
|
|
cd ruoyi-ui && npm run lint -- --fix src/views/ccdiProject/components/ProjectTable.vue
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
预期输出:无 ESLint 错误
|
|||
|
|
|
|||
|
|
**Step 4: 提交代码**
|
|||
|
|
|
|||
|
|
```bash
|
|||
|
|
git add ruoyi-ui/src/views/ccdiProject/components/ProjectTable.vue
|
|||
|
|
git commit -m "feat: 优化项目列表表格,添加预警人数悬停提示"
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## Task 4: 修改父组件 index.vue
|
|||
|
|
|
|||
|
|
**文件:**
|
|||
|
|
- Modify: `ruoyi-ui/src/views/ccdiProject/index.vue`
|
|||
|
|
|
|||
|
|
**Step 1: 备份原文件**
|
|||
|
|
|
|||
|
|
```bash
|
|||
|
|
cp ruoyi-ui/src/views/ccdiProject/index.vue ruoyi-ui/src/views/ccdiProject/index.vue.bak
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**Step 2: 修改父组件**
|
|||
|
|
|
|||
|
|
将 `ruoyi-ui/src/views/ccdiProject/index.vue` 的 `getList` 和 `handleSubmitProject` 方法修改为:
|
|||
|
|
|
|||
|
|
```javascript
|
|||
|
|
/** 查询项目列表 */
|
|||
|
|
getList() {
|
|||
|
|
this.loading = true
|
|||
|
|
// 使用真实API
|
|||
|
|
listProject(this.queryParams).then(response => {
|
|||
|
|
this.projectList = response.rows
|
|||
|
|
this.total = response.total
|
|||
|
|
this.loading = false
|
|||
|
|
}).catch(() => {
|
|||
|
|
this.loading = false
|
|||
|
|
})
|
|||
|
|
},
|
|||
|
|
|
|||
|
|
/** 提交项目表单 */
|
|||
|
|
handleSubmitProject(data) {
|
|||
|
|
// 不需要再次调用API,因为AddProjectDialog已经处理了
|
|||
|
|
this.addDialogVisible = false
|
|||
|
|
this.getList() // 刷新列表
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**Step 3: 验证语法**
|
|||
|
|
|
|||
|
|
```bash
|
|||
|
|
cd ruoyi-ui && npm run lint -- --fix src/views/ccdiProject/index.vue
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
预期输出:无 ESLint 错误
|
|||
|
|
|
|||
|
|
**Step 4: 提交代码**
|
|||
|
|
|
|||
|
|
```bash
|
|||
|
|
git add ruoyi-ui/src/views/ccdiProject/index.vue
|
|||
|
|
git commit -m "feat: 修改父组件,切换为真实API调用"
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## Task 5: 启动前端并测试
|
|||
|
|
|
|||
|
|
**Step 1: 启动前端开发服务器**
|
|||
|
|
|
|||
|
|
```bash
|
|||
|
|
cd ruoyi-ui && npm run dev
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
预期输出:前端服务启动成功,访问地址 http://localhost:80
|
|||
|
|
|
|||
|
|
**Step 2: 测试登录**
|
|||
|
|
|
|||
|
|
浏览器访问 http://localhost:80,使用测试账号登录:
|
|||
|
|
- 用户名:admin
|
|||
|
|
- 密码:admin123
|
|||
|
|
|
|||
|
|
预期结果:登录成功,进入首页
|
|||
|
|
|
|||
|
|
**Step 3: 测试项目列表**
|
|||
|
|
|
|||
|
|
导航到"纪检初核管理 > 项目管理"菜单:
|
|||
|
|
|
|||
|
|
预期结果:
|
|||
|
|
- 项目列表正常显示
|
|||
|
|
- 项目名称和描述上下排列
|
|||
|
|
- 项目状态标签显示正确
|
|||
|
|
- 预警人数悬停提示显示风险详情
|
|||
|
|
|
|||
|
|
**Step 4: 测试创建项目**
|
|||
|
|
|
|||
|
|
点击"新建项目"按钮:
|
|||
|
|
|
|||
|
|
预期结果:
|
|||
|
|
- 弹窗正常打开
|
|||
|
|
- 显示3个字段(项目名称、项目描述、配置方式)
|
|||
|
|
- 配置方式默认选中"全局默认模型参数配置"
|
|||
|
|
|
|||
|
|
填写表单:
|
|||
|
|
- 项目名称:测试项目001
|
|||
|
|
- 项目描述:这是测试项目的描述
|
|||
|
|
- 配置方式:选择"自定义项目规则参数配置"
|
|||
|
|
|
|||
|
|
点击"创建项目"按钮:
|
|||
|
|
|
|||
|
|
预期结果:
|
|||
|
|
- 按钮显示 loading 状态
|
|||
|
|
- 创建成功,提示"项目创建成功"
|
|||
|
|
- 弹窗关闭
|
|||
|
|
- 项目列表自动刷新,显示新创建的项目
|
|||
|
|
|
|||
|
|
**Step 5: 测试预警人数悬停**
|
|||
|
|
|
|||
|
|
在项目列表中,将鼠标悬停在预警人数上:
|
|||
|
|
|
|||
|
|
预期结果:
|
|||
|
|
- 显示风险人数统计提示框
|
|||
|
|
- 显示高风险、中风险、低风险人数
|
|||
|
|
- 预警人数颜色根据风险级别变化
|
|||
|
|
|
|||
|
|
**Step 6: 测试表单验证**
|
|||
|
|
|
|||
|
|
不填写项目名称,直接点击"创建项目":
|
|||
|
|
|
|||
|
|
预期结果:
|
|||
|
|
- 提示"请输入项目名称"
|
|||
|
|
- 表单不提交
|
|||
|
|
|
|||
|
|
**Step 7: 测试取消按钮**
|
|||
|
|
|
|||
|
|
点击"新建项目",然后点击"取消":
|
|||
|
|
|
|||
|
|
预期结果:
|
|||
|
|
- 弹窗关闭
|
|||
|
|
- 表单数据清空
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## Task 6: 跨浏览器测试
|
|||
|
|
|
|||
|
|
**Step 1: Chrome 测试**
|
|||
|
|
|
|||
|
|
在 Chrome 浏览器中重复 Task 5 的所有测试:
|
|||
|
|
|
|||
|
|
预期结果:所有功能正常
|
|||
|
|
|
|||
|
|
**Step 2: Edge 测试**
|
|||
|
|
|
|||
|
|
在 Edge 浏览器中重复 Task 5 的所有测试:
|
|||
|
|
|
|||
|
|
预期结果:所有功能正常
|
|||
|
|
|
|||
|
|
**Step 3: Firefox 测试(可选)**
|
|||
|
|
|
|||
|
|
在 Firefox 浏览器中重复 Task 5 的所有测试:
|
|||
|
|
|
|||
|
|
预期结果:所有功能正常
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## Task 7: 响应式测试
|
|||
|
|
|
|||
|
|
**Step 1: 测试不同分辨率**
|
|||
|
|
|
|||
|
|
调整浏览器窗口大小,测试以下分辨率:
|
|||
|
|
|
|||
|
|
- 1920x1080(桌面)
|
|||
|
|
- 1366x768(笔记本)
|
|||
|
|
- 768x1024(平板)
|
|||
|
|
|
|||
|
|
预期结果:
|
|||
|
|
- 表格自适应宽度
|
|||
|
|
- 弹窗居中显示
|
|||
|
|
- 所有功能正常使用
|
|||
|
|
|
|||
|
|
**Step 2: 测试表格横向滚动**
|
|||
|
|
|
|||
|
|
缩小浏览器窗口,使表格宽度小于内容宽度:
|
|||
|
|
|
|||
|
|
预期结果:
|
|||
|
|
- 表格出现横向滚动条
|
|||
|
|
- 操作列固定在右侧
|
|||
|
|
- 可以横向滚动查看所有列
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## Task 8: 提交最终代码
|
|||
|
|
|
|||
|
|
**Step 1: 检查所有文件**
|
|||
|
|
|
|||
|
|
```bash
|
|||
|
|
git status
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
预期输出:所有前端文件已提交
|
|||
|
|
|
|||
|
|
**Step 2: 推送到远程仓库**
|
|||
|
|
|
|||
|
|
```bash
|
|||
|
|
git push origin dev
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
预期输出:推送成功
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 完成检查清单
|
|||
|
|
|
|||
|
|
- [ ] API 接口文件更新完成
|
|||
|
|
- [ ] AddProjectDialog 组件简化完成(3个字段)
|
|||
|
|
- [ ] ProjectTable 组件优化完成(上下排列、预警悬停)
|
|||
|
|
- [ ] 父组件切换为真实API
|
|||
|
|
- [ ] 前端服务启动成功
|
|||
|
|
- [ ] 登录功能正常
|
|||
|
|
- [ ] 项目列表显示正常
|
|||
|
|
- [ ] 项目名称和描述上下排列正确
|
|||
|
|
- [ ] 项目状态标签显示正确
|
|||
|
|
- [ ] 预警人数悬停提示显示正常
|
|||
|
|
- [ ] 预警人数颜色根据风险级别变化
|
|||
|
|
- [ ] 创建项目弹窗打开正常
|
|||
|
|
- [ ] 配置方式默认值正确
|
|||
|
|
- [ ] 创建项目功能正常
|
|||
|
|
- [ ] 创建成功后列表刷新
|
|||
|
|
- [ ] 表单验证正常
|
|||
|
|
- [ ] 取消按钮功能正常
|
|||
|
|
- [ ] 跨浏览器测试通过
|
|||
|
|
- [ ] 响应式测试通过
|
|||
|
|
- [ ] 所有代码已提交到 git
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
**前端实施计划完成!**
|