diff --git a/src/api/risk-workorder.ts b/src/api/risk-workorder.ts index 1e95490..e010a2c 100644 --- a/src/api/risk-workorder.ts +++ b/src/api/risk-workorder.ts @@ -111,9 +111,9 @@ export type RiskStatisticsVO = { highCount: number; mediumCount: number; lowCount: number; - categoryStats: Record; - levelStats: Record; - trendData: Record; + categoryStats: Record; + levelStats: Record; + trendData: Record | null; averageRiskScore: number; unresolvedHighCount: number; }; diff --git a/src/views/project/detail.vue b/src/views/project/detail.vue index 7031329..1cbc82d 100644 --- a/src/views/project/detail.vue +++ b/src/views/project/detail.vue @@ -59,6 +59,10 @@ const marginStyle = computed(() => ({ // 项目详情数据 const projectDetail = ref(null); +// 成员详情模态框 +const memberDetailModal = ref(false); +const selectedMember = ref(null); + // 项目基本信息(计算属性) const projectInfo = computed(() => { const data = projectDetail.value; @@ -144,6 +148,12 @@ function goBack() { router.push("/project"); } +// 打开成员详情模态框 +function openMemberDetail(member: ProjectMember) { + selectedMember.value = member; + memberDetailModal.value = true; +} + // 获取甘特图数据(现在使用项目详情中的任务数据) async function fetchGanttData() { // 任务数据已从项目详情API获取,无需单独请求 @@ -555,11 +565,13 @@ onMounted(() => { `https://api.dicebear.com/7.x/avataaars/svg?seed=${member.id}` " :title="getRoleText(member.roleCode)" + class="cursor-pointer" + @click="openMemberDetail(member)" /> +{{ memberList.length - 4 }} @@ -817,6 +829,84 @@ onMounted(() => { + + + +
+
+ +
+

{{ selectedMember.realName }}

+

{{ selectedMember.userName }}

+ + {{ getRoleText(selectedMember.roleCode) }} + +
+
+ + + +
+
+ 所属部门 + {{ + selectedMember.department || "未设置" + }} +
+
+ 职责 + {{ + selectedMember.responsibility || "未设置" + }} +
+
+ 每周工时 + {{ selectedMember.weeklyHours }} 小时 +
+
+ 加入日期 + {{ + selectedMember.joinDate || "未设置" + }} +
+
+ 状态 + + + {{ selectedMember.status === 1 ? "活跃" : "非活跃" }} + + +
+
+
+
+ +
+
diff --git a/src/views/risk-assessment/index.vue b/src/views/risk-assessment/index.vue index e4edabc..99375ca 100644 --- a/src/views/risk-assessment/index.vue +++ b/src/views/risk-assessment/index.vue @@ -332,31 +332,43 @@ function initPieChart() { updatePieChart(); } -// 更新饼图 +// 更新饼图 - 使用 categoryStats 分类统计数据 function updatePieChart() { if (!pieChart) return; - const data = [ - { - value: statistics.value.criticalCount || 0, - name: "严重", - itemStyle: { color: "#f56c6c" } - }, - { - value: statistics.value.highCount || 0, - name: "高", - itemStyle: { color: "#e6a23c" } - }, - { - value: statistics.value.mediumCount || 0, - name: "中", - itemStyle: { color: "#409eff" } - }, - { - value: statistics.value.lowCount || 0, - name: "低", - itemStyle: { color: "#67c23a" } - } - ].filter(item => item.value > 0); + + // 从 categoryStats 获取分类统计数据 + const categoryStats = statistics.value.categoryStats || {}; + const categoryColors: Record = { + schedule: "#409eff", // 进度 - 蓝色 + external: "#e6a23c", // 外部 - 橙色 + technical: "#67c23a", // 技术 - 绿色 + resource: "#909399", // 资源 - 灰色 + personnel: "#f56c6c", // 人员 - 红色 + quality: "#9c27b0", // 质量 - 紫色 + cost: "#ff9800", // 成本 - 深橙 + other: "#795548" // 其他 - 棕色 + }; + const categoryNames: Record = { + schedule: "进度风险", + external: "外部风险", + technical: "技术风险", + resource: "资源风险", + personnel: "人员风险", + quality: "质量风险", + cost: "成本风险", + other: "其他风险" + }; + + // 构建饼图数据 + const data = Object.entries(categoryStats) + .map(([key, value]) => ({ + value: parseInt(String(value)) || 0, + name: categoryNames[key] || key, + itemStyle: { color: categoryColors[key] || "#909399" } + })) + .filter(item => item.value > 0) + .sort((a, b) => b.value - a.value); + const option = { tooltip: { trigger: "item", @@ -371,7 +383,7 @@ function updatePieChart() { }, series: [ { - name: "风险分布", + name: "风险分类分布", type: "pie", radius: ["50%", "70%"], center: ["50%", "45%"], @@ -394,7 +406,10 @@ function updatePieChart() { labelLine: { show: false }, - data + data: + data.length > 0 + ? data + : [{ value: 1, name: "暂无数据", itemStyle: { color: "#e0e0e0" } }] } ] }; @@ -408,34 +423,61 @@ function initTrendChart() { updateTrendChart(); } -// 更新趋势图 +// 更新趋势图 - 使用风险状态分布数据 function updateTrendChart() { if (!trendChart) return; - const months = ["1月", "2月", "3月", "4月", "5月", "6月"]; + + // 使用状态统计数据展示风险状态分布 + const statusData = [ + { + name: "已识别", + value: statistics.value.identifiedCount || 0, + color: "#909399" + }, + { + name: "已分派", + value: statistics.value.assignedCount || 0, + color: "#409eff" + }, + { + name: "缓解中", + value: statistics.value.mitigatingCount || 0, + color: "#e6a23c" + }, + { + name: "已解决", + value: statistics.value.resolvedCount || 0, + color: "#67c23a" + }, + { + name: "已关闭", + value: statistics.value.closedCount || 0, + color: "#13c2c2" + } + ]; + const option = { tooltip: { trigger: "axis", - axisPointer: { type: "shadow" } - }, - legend: { - data: ["高风险", "中风险", "低风险"], - right: 10, - top: 10, - itemWidth: 12, - itemHeight: 12 + axisPointer: { type: "shadow" }, + formatter: (params: any) => { + const data = params[0]; + return `${data.name}: ${data.value} 个`; + } }, grid: { left: "3%", right: "4%", bottom: "3%", - top: "15%", + top: "10%", containLabel: true }, xAxis: { type: "category", - data: months, + data: statusData.map(item => item.name), axisLine: { lineStyle: { color: "#dcdfe6" } }, - axisLabel: { color: "#606266" } + axisLabel: { color: "#606266", fontSize: 12 }, + axisTick: { show: false } }, yAxis: { type: "value", @@ -445,25 +487,23 @@ function updateTrendChart() { }, series: [ { - name: "高风险", + name: "风险数量", type: "bar", - stack: "total", - data: [5, 8, 6, 10, 12, 8], - itemStyle: { color: "#f56c6c", borderRadius: [0, 0, 4, 4] } - }, - { - name: "中风险", - type: "bar", - stack: "total", - data: [8, 12, 10, 15, 18, 16], - itemStyle: { color: "#e6a23c" } - }, - { - name: "低风险", - type: "bar", - stack: "total", - data: [10, 15, 12, 18, 20, 22], - itemStyle: { color: "#67c23a", borderRadius: [4, 4, 0, 0] } + data: statusData.map((item, index) => ({ + value: item.value, + itemStyle: { + color: item.color, + borderRadius: [4, 4, 0, 0] + } + })), + barWidth: "50%", + label: { + show: true, + position: "top", + color: "#606266", + fontSize: 12, + formatter: "{c}" + } } ] }; @@ -708,7 +748,7 @@ onUnmounted(() => {