调整项目列表入口和操作按钮
This commit is contained in:
@@ -0,0 +1,31 @@
|
|||||||
|
# 项目列表整行进入与操作按钮收敛实施记录
|
||||||
|
|
||||||
|
## 修改时间
|
||||||
|
|
||||||
|
2026-07-01 15:52:04
|
||||||
|
|
||||||
|
## 需求背景
|
||||||
|
|
||||||
|
项目管理列表中“进入项目 / 查看结果 / 重新分析”操作含义接近,用户希望点击项目行任意位置即可进入项目详情;列表页只保留真正的操作按钮,项目结果、分析、明细统一进入详情页后查看。
|
||||||
|
|
||||||
|
## 修改内容
|
||||||
|
|
||||||
|
- 调整项目列表交互:项目表格整行点击进入项目详情。
|
||||||
|
- 行点击进入项目详情时明确默认页签:
|
||||||
|
- 进行中、打标中、打标失败项目进入“上传数据”。
|
||||||
|
- 已完成、已归档或当前用户不可操作的项目进入“结果总览”。
|
||||||
|
- 移除列表操作列中的“进入项目”“查看结果”“重新分析”按钮。
|
||||||
|
- 操作列保留“归档”“删除”:
|
||||||
|
- 已完成项目显示“归档”。
|
||||||
|
- 删除按钮调用既有删除接口。
|
||||||
|
- 不调整后端权限、删除字段和查询逻辑。
|
||||||
|
- 删除、归档按钮点击时阻止行点击,避免误进入项目详情。
|
||||||
|
|
||||||
|
## 影响范围
|
||||||
|
|
||||||
|
- 项目管理列表页。
|
||||||
|
- 不涉及后端接口、权限、数据库字段和查询逻辑。
|
||||||
|
|
||||||
|
## 验证情况
|
||||||
|
|
||||||
|
- 前端已通过 `nvm use 14.21.3` 切换 Node 版本,并执行生产构建,构建通过;仅存在既有资源体积 warning。
|
||||||
@@ -4,6 +4,8 @@
|
|||||||
v-loading="loading"
|
v-loading="loading"
|
||||||
:data="dataList"
|
:data="dataList"
|
||||||
style="width: 100%"
|
style="width: 100%"
|
||||||
|
class="project-entry-table"
|
||||||
|
@row-click="handleOpen"
|
||||||
>
|
>
|
||||||
<el-table-column
|
<el-table-column
|
||||||
label="项目名称"
|
label="项目名称"
|
||||||
@@ -92,7 +94,7 @@
|
|||||||
|
|
||||||
<el-table-column
|
<el-table-column
|
||||||
label="操作"
|
label="操作"
|
||||||
width="390"
|
width="180"
|
||||||
align="left"
|
align="left"
|
||||||
fixed="right"
|
fixed="right"
|
||||||
>
|
>
|
||||||
@@ -102,74 +104,34 @@
|
|||||||
size="mini"
|
size="mini"
|
||||||
type="text"
|
type="text"
|
||||||
icon="el-icon-refresh-left"
|
icon="el-icon-refresh-left"
|
||||||
@click="handleRestore(scope.row)"
|
@click.stop="handleRestore(scope.row)"
|
||||||
>
|
>
|
||||||
恢复
|
恢复
|
||||||
</el-button>
|
</el-button>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<template v-else>
|
<template v-else>
|
||||||
|
<div class="row-actions">
|
||||||
<el-button
|
<el-button
|
||||||
v-if="['0', '3', '4'].includes(scope.row.status)"
|
v-if="scope.row.status === '1' && canOperate(scope.row)"
|
||||||
size="mini"
|
|
||||||
type="text"
|
|
||||||
:icon="canOperate(scope.row) ? 'el-icon-right' : 'el-icon-view'"
|
|
||||||
@click="handleEnter(scope.row)"
|
|
||||||
>
|
|
||||||
{{ canOperate(scope.row) ? "进入项目" : "查看项目" }}
|
|
||||||
</el-button>
|
|
||||||
|
|
||||||
<template v-if="scope.row.status === '1'">
|
|
||||||
<el-button
|
|
||||||
size="mini"
|
|
||||||
type="text"
|
|
||||||
icon="el-icon-view"
|
|
||||||
@click="handleViewResult(scope.row)"
|
|
||||||
>
|
|
||||||
查看结果
|
|
||||||
</el-button>
|
|
||||||
<el-button
|
|
||||||
v-if="canOperate(scope.row)"
|
|
||||||
size="mini"
|
|
||||||
type="text"
|
|
||||||
icon="el-icon-refresh"
|
|
||||||
:loading="reAnalyzeLoadingMap[String(scope.row.projectId)]"
|
|
||||||
:disabled="reAnalyzeLoadingMap[String(scope.row.projectId)]"
|
|
||||||
@click="handleReAnalyze(scope.row)"
|
|
||||||
>
|
|
||||||
重新分析
|
|
||||||
</el-button>
|
|
||||||
<el-button
|
|
||||||
v-if="canOperate(scope.row)"
|
|
||||||
size="mini"
|
size="mini"
|
||||||
type="text"
|
type="text"
|
||||||
icon="el-icon-folder"
|
icon="el-icon-folder"
|
||||||
@click="handleArchive(scope.row)"
|
@click.stop="handleArchive(scope.row)"
|
||||||
>
|
>
|
||||||
归档
|
归档
|
||||||
</el-button>
|
</el-button>
|
||||||
</template>
|
|
||||||
|
|
||||||
<el-button
|
|
||||||
v-if="scope.row.status === '2'"
|
|
||||||
size="mini"
|
|
||||||
type="text"
|
|
||||||
icon="el-icon-view"
|
|
||||||
@click="handleViewResult(scope.row)"
|
|
||||||
>
|
|
||||||
查看结果
|
|
||||||
</el-button>
|
|
||||||
|
|
||||||
<el-button
|
<el-button
|
||||||
v-if="canDelete(scope.row) && scope.row.status !== '5'"
|
v-if="canDelete(scope.row) && scope.row.status !== '5'"
|
||||||
size="mini"
|
size="mini"
|
||||||
type="text"
|
type="text"
|
||||||
class="delete-button"
|
class="delete-button"
|
||||||
icon="el-icon-delete"
|
icon="el-icon-delete"
|
||||||
@click="handleDelete(scope.row)"
|
@click.stop="handleDelete(scope.row)"
|
||||||
>
|
>
|
||||||
删除
|
删除
|
||||||
</el-button>
|
</el-button>
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
@@ -213,10 +175,6 @@ export default {
|
|||||||
pageSize: 10,
|
pageSize: 10,
|
||||||
}),
|
}),
|
||||||
},
|
},
|
||||||
reAnalyzeLoadingMap: {
|
|
||||||
type: Object,
|
|
||||||
default: () => ({}),
|
|
||||||
},
|
|
||||||
deletedList: {
|
deletedList: {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
default: false,
|
default: false,
|
||||||
@@ -247,14 +205,8 @@ export default {
|
|||||||
}
|
}
|
||||||
return "";
|
return "";
|
||||||
},
|
},
|
||||||
handleEnter(row) {
|
handleOpen(row) {
|
||||||
this.$emit("enter", row);
|
this.$emit("open", row);
|
||||||
},
|
|
||||||
handleViewResult(row) {
|
|
||||||
this.$emit("view-result", row);
|
|
||||||
},
|
|
||||||
handleReAnalyze(row) {
|
|
||||||
this.$emit("re-analyze", row);
|
|
||||||
},
|
},
|
||||||
handleArchive(row) {
|
handleArchive(row) {
|
||||||
this.$emit("archive", row);
|
this.$emit("archive", row);
|
||||||
@@ -296,6 +248,14 @@ export default {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
::v-deep .project-entry-table .el-table__body tr {
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
::v-deep .project-entry-table .el-table__body tr:hover > td {
|
||||||
|
background-color: #f5f9ff;
|
||||||
|
}
|
||||||
|
|
||||||
.status-tag {
|
.status-tag {
|
||||||
display: inline-flex;
|
display: inline-flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
|||||||
@@ -20,12 +20,9 @@
|
|||||||
:data-list="projectList"
|
:data-list="projectList"
|
||||||
:total="total"
|
:total="total"
|
||||||
:page-params="queryParams"
|
:page-params="queryParams"
|
||||||
:re-analyze-loading-map="reAnalyzeLoadingMap"
|
|
||||||
:deleted-list="queryParams.includeDeleted === true"
|
:deleted-list="queryParams.includeDeleted === true"
|
||||||
@pagination="handlePagination"
|
@pagination="handlePagination"
|
||||||
@enter="handleEnter"
|
@open="handleOpenProject"
|
||||||
@view-result="handleViewResult"
|
|
||||||
@re-analyze="handleReAnalyze"
|
|
||||||
@archive="handleArchive"
|
@archive="handleArchive"
|
||||||
@delete="handleDelete"
|
@delete="handleDelete"
|
||||||
@restore="handleRestore"
|
@restore="handleRestore"
|
||||||
@@ -67,7 +64,8 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import {archiveProject, delProject, getStatusCounts, listProject, rebuildProjectTags, restoreProject} from '@/api/ccdiProject'
|
import {archiveProject, delProject, getStatusCounts, listProject} from '@/api/ccdiProject'
|
||||||
|
import { restoreProject } from '@/api/ccdiProject'
|
||||||
import SearchBar from './components/SearchBar'
|
import SearchBar from './components/SearchBar'
|
||||||
import ProjectTable from './components/ProjectTable'
|
import ProjectTable from './components/ProjectTable'
|
||||||
import QuickEntry from './components/QuickEntry'
|
import QuickEntry from './components/QuickEntry'
|
||||||
@@ -122,8 +120,6 @@ export default {
|
|||||||
// 归档确认弹窗
|
// 归档确认弹窗
|
||||||
archiveDialogVisible: false,
|
archiveDialogVisible: false,
|
||||||
currentArchiveProject: null,
|
currentArchiveProject: null,
|
||||||
// 重新分析按钮提交态
|
|
||||||
reAnalyzeLoadingMap: {},
|
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
created() {
|
created() {
|
||||||
@@ -267,52 +263,22 @@ export default {
|
|||||||
this.addDialogTitle = "创建高风险专项项目";
|
this.addDialogTitle = "创建高风险专项项目";
|
||||||
this.addDialogVisible = true;
|
this.addDialogVisible = true;
|
||||||
},
|
},
|
||||||
/** 进入项目 */
|
/** 打开项目 */
|
||||||
handleEnter(row) {
|
handleOpenProject(row) {
|
||||||
|
if (this.queryParams.includeDeleted) {
|
||||||
|
return
|
||||||
|
}
|
||||||
this.$router.push({
|
this.$router.push({
|
||||||
path: `/ccdiProject/detail/${row.projectId}`,
|
path: `/ccdiProject/detail/${row.projectId}`,
|
||||||
query: { tab: this.canOperate(row) ? "upload" : "overview" },
|
query: { tab: this.resolveProjectEntryTab(row) },
|
||||||
});
|
|
||||||
// this.$modal.msgSuccess("进入项目: " + row.projectName);
|
|
||||||
},
|
|
||||||
/** 查看结果 */
|
|
||||||
handleViewResult(row) {
|
|
||||||
this.$router.push({
|
|
||||||
path: `/ccdiProject/detail/${row.projectId}`,
|
|
||||||
query: { tab: "overview" },
|
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
/** 重新分析 */
|
resolveProjectEntryTab(row) {
|
||||||
async handleReAnalyze(row) {
|
const status = row && row.status !== undefined ? String(row.status) : ""
|
||||||
if (!this.canOperate(row)) {
|
if (row && row.canOperate === false) {
|
||||||
this.$modal.msgWarning("当前项目仅可查看,不能重新分析")
|
return "overview"
|
||||||
return
|
|
||||||
}
|
|
||||||
const projectKey = String(row.projectId)
|
|
||||||
if (this.reAnalyzeLoadingMap[projectKey]) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
await this.$modal.confirm(
|
|
||||||
`确认对项目“${row.projectName}”重新分析吗?重新分析将重新计算项目标签。`
|
|
||||||
)
|
|
||||||
} catch (confirmError) {
|
|
||||||
if (confirmError === "cancel" || confirmError === "close") {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
throw confirmError
|
|
||||||
}
|
|
||||||
this.$set(this.reAnalyzeLoadingMap, projectKey, true)
|
|
||||||
try {
|
|
||||||
await rebuildProjectTags({ projectId: row.projectId })
|
|
||||||
this.$modal.msgSuccess("已开始重新分析")
|
|
||||||
this.getList()
|
|
||||||
} catch (error) {
|
|
||||||
const message = error && error.message ? error.message : "重新分析失败,请稍后重试"
|
|
||||||
this.$modal.msgError(message)
|
|
||||||
} finally {
|
|
||||||
this.$set(this.reAnalyzeLoadingMap, projectKey, false)
|
|
||||||
}
|
}
|
||||||
|
return ["1", "2"].includes(status) ? "overview" : "upload"
|
||||||
},
|
},
|
||||||
/** 归档项目 */
|
/** 归档项目 */
|
||||||
handleArchive(row) {
|
handleArchive(row) {
|
||||||
|
|||||||
Reference in New Issue
Block a user