Files
ccdi/ruoyi-ui/src/views/ccdiProject/components/ProjectTable.vue

388 lines
8.5 KiB
Vue
Raw Normal View History

2026-01-30 11:01:13 +08:00
<template>
<div class="project-table-container">
<el-table
v-loading="loading"
:data="dataList"
style="width: 100%"
>
<el-table-column
label="项目名称"
min-width="180"
align="left"
2026-01-30 11:01:13 +08:00
>
<template slot-scope="scope">
<div class="project-info-cell">
<div class="project-name">{{ scope.row.projectName }}</div>
<div class="project-desc">{{ scope.row.description || "暂无描述" }}</div>
</div>
</template>
</el-table-column>
2026-01-30 11:01:13 +08:00
<el-table-column
prop="updateTime"
label="更新/创建时间"
width="180"
align="center"
>
<template slot-scope="scope">
<span>{{ parseTime(scope.row.updateTime || scope.row.createTime) }}</span>
</template>
</el-table-column>
<el-table-column
prop="createByName"
label="创建人"
width="120"
align="center"
/>
<el-table-column
prop="status"
label="状态"
width="120"
align="center"
>
<template slot-scope="scope">
<div class="status-tag">
<span class="status-dot" :style="{ color: getStatusColor(scope.row.status) }"></span>
<dict-tag :options="dict.type.ccdi_project_status" :value="scope.row.status" />
</div>
</template>
</el-table-column>
2026-01-30 11:01:13 +08:00
<el-table-column
prop="targetCount"
label="目标人数"
width="100"
align="center"
/>
2026-01-30 11:01:13 +08:00
<el-table-column
label="预警人数"
width="120"
align="center"
>
<template slot-scope="scope">
<el-tooltip placement="top" effect="light">
<div slot="content">
<div class="risk-tooltip">
<div class="risk-tooltip-title">风险人数统计</div>
<div class="risk-tooltip-item risk-tooltip-item--high">
<span> 高风险</span>
<span class="risk-tooltip-count">{{ scope.row.highRiskCount }} </span>
</div>
<div class="risk-tooltip-item risk-tooltip-item--medium">
<span> 中风险</span>
<span class="risk-tooltip-count">{{ scope.row.mediumRiskCount }} </span>
</div>
<div class="risk-tooltip-item risk-tooltip-item--low">
<span> 低风险</span>
<span class="risk-tooltip-count">{{ scope.row.lowRiskCount }} </span>
</div>
</div>
</div>
<div class="warning-count-wrapper">
<span :class="getWarningClass(scope.row)" class="warning-count">
{{ scope.row.highRiskCount + scope.row.mediumRiskCount + scope.row.lowRiskCount }}
</span>
</div>
</el-tooltip>
</template>
</el-table-column>
2026-01-30 11:01:13 +08:00
<el-table-column
label="操作"
width="350"
align="left"
fixed="right"
>
<template slot-scope="scope">
<el-button
v-if="scope.row.status === '0' || scope.row.status === '3'"
size="mini"
type="text"
icon="el-icon-right"
@click="handleEnter(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
size="mini"
type="text"
icon="el-icon-refresh"
2026-03-24 12:44:17 +08:00
:loading="reAnalyzeLoadingMap[String(scope.row.projectId)]"
:disabled="reAnalyzeLoadingMap[String(scope.row.projectId)]"
@click="handleReAnalyze(scope.row)"
>
重新分析
</el-button>
<el-button
size="mini"
type="text"
icon="el-icon-folder"
@click="handleArchive(scope.row)"
>
归档
</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>
</template>
</el-table-column>
</el-table>
2026-01-30 11:01:13 +08:00
<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"
/>
2026-01-30 11:01:13 +08:00
</div>
</template>
<script>
export default {
name: "ProjectTable",
dicts: ["ccdi_project_status", "ccdi_config_type"],
2026-01-30 11:01:13 +08:00
props: {
dataList: {
type: Array,
default: () => [],
2026-01-30 11:01:13 +08:00
},
loading: {
type: Boolean,
default: false,
},
2026-01-30 11:01:13 +08:00
total: {
type: Number,
default: 0,
2026-01-30 11:01:13 +08:00
},
pageParams: {
type: Object,
default: () => ({
pageNum: 1,
pageSize: 10,
}),
},
2026-03-24 12:44:17 +08:00
reAnalyzeLoadingMap: {
type: Object,
default: () => ({}),
},
2026-01-30 11:01:13 +08:00
},
methods: {
getStatusColor(status) {
const colorMap = {
0: "#1890ff",
1: "#52c41a",
2: "#8c8c8c",
3: "#fa8c16",
};
return colorMap[status] || "#8c8c8c";
},
2026-01-30 11:01:13 +08:00
getWarningClass(row) {
const total = row.highRiskCount + row.mediumRiskCount + row.lowRiskCount;
if (row.highRiskCount > 0) {
return "text-danger text-bold";
}
if (row.mediumRiskCount > 0) {
return "text-warning text-bold";
}
if (total > 0) {
return "text-info";
}
return "";
2026-01-30 11:01:13 +08:00
},
handleEnter(row) {
this.$emit("enter", row);
},
handleViewResult(row) {
this.$emit("view-result", row);
2026-01-30 11:01:13 +08:00
},
handleReAnalyze(row) {
this.$emit("re-analyze", row);
2026-01-30 11:01:13 +08:00
},
handleArchive(row) {
this.$emit("archive", row);
2026-01-30 11:01:13 +08:00
},
handleSizeChange(val) {
this.$emit("pagination", {
pageNum: this.pageParams.pageNum,
pageSize: val,
});
2026-01-30 11:01:13 +08:00
},
handleCurrentChange(val) {
this.$emit("pagination", {
pageNum: val,
pageSize: this.pageParams.pageSize,
});
},
},
};
2026-01-30 11:01:13 +08:00
</script>
<style lang="scss" scoped>
.project-table-container {
margin-top: 16px;
2026-01-30 11:01:13 +08:00
}
.status-tag {
display: inline-flex;
align-items: center;
gap: 6px;
.status-dot {
font-size: 10px;
line-height: 1;
}
}
.project-info-cell {
2026-02-28 13:36:22 +08:00
padding: 4px 0;
line-height: 1.4;
2026-01-30 11:01:13 +08:00
.project-name {
2026-01-30 11:01:13 +08:00
font-size: 14px;
font-weight: 600;
color: #303133;
2026-02-28 13:36:22 +08:00
margin-bottom: 2px;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
2026-01-30 11:01:13 +08:00
}
.project-desc {
2026-01-30 11:01:13 +08:00
font-size: 12px;
color: #909399;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
2026-01-30 11:01:13 +08:00
}
}
.risk-tooltip {
padding: 8px;
}
.risk-tooltip-title {
margin-bottom: 8px;
font-weight: 600;
color: #303133;
}
.risk-tooltip-item {
margin-bottom: 6px;
}
.risk-tooltip-item--high {
color: #f56c6c;
}
.risk-tooltip-item--medium {
color: #e6a23c;
}
.risk-tooltip-item--low {
color: #909399;
}
.risk-tooltip-count {
font-weight: 600;
}
.warning-count-wrapper {
display: inline-block;
2026-01-30 11:01:13 +08:00
}
.warning-count {
cursor: pointer;
}
.text-danger {
color: #f56c6c;
2026-01-30 11:01:13 +08:00
}
.text-warning {
color: #e6a23c;
2026-01-30 11:01:13 +08:00
}
.text-info {
color: #909399;
2026-01-30 11:01:13 +08:00
}
.text-bold {
font-weight: 700;
2026-01-30 11:01:13 +08:00
}
::v-deep .el-button--text {
color: #1890ff;
padding: 8px 12px;
border-radius: 4px;
transition: all 0.2s ease;
&:hover {
color: #096dd9;
background-color: rgba(24, 144, 255, 0.08);
text-decoration: none;
}
&:first-child {
padding-left: 0;
}
& + .el-button--text {
margin-left: 4px;
}
}
::v-deep .el-pagination {
margin-top: 24px;
text-align: right;
.btn-prev,
.btn-next,
.el-pager li {
border: none;
background-color: transparent;
&:hover {
background-color: #f5f5f5;
}
}
.el-pager li.active {
background-color: #1890ff;
color: #fff;
border-radius: 4px;
}
.el-pagination__total,
.el-pagination__sizes,
.el-pagination__jump {
color: #666;
}
}
2026-01-30 11:01:13 +08:00
</style>