From 6f41d613bae44c4a61185dfbeb86e2b3cd2ef578 Mon Sep 17 00:00:00 2001 From: bestlee Date: Tue, 8 Sep 2026 10:25:17 +0800 Subject: [PATCH] =?UTF-8?q?hazop=E6=8F=92=E4=BB=B6=E6=8F=90=E4=BA=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/service/api/plugin.ts | 25 +++ src/views/my/initiateChange/modules/hazop.vue | 165 ++++++++++++------ 2 files changed, 140 insertions(+), 50 deletions(-) diff --git a/src/service/api/plugin.ts b/src/service/api/plugin.ts index 57d6eb1..69a775c 100644 --- a/src/service/api/plugin.ts +++ b/src/service/api/plugin.ts @@ -96,3 +96,28 @@ export function hazopRowAddApi(dev_id: number, data: { data, }); } + +// 编辑偏离分析行 +export function hazopRowEditApi(row_id: number, data: { + cause: string, + consequence: string, + l_value: number, + s_value: number, + risk_value:string, + safeguards:string, + suggestions:string +}) { + return request({ + url: `/api/hazop/rows/${row_id}`, + method: 'put', + data, + }); +} + +// 删除偏离分析行 +export function hazopRowDelApi(row_id: number) { + return request({ + url: `/api/hazop/rows/${row_id}`, + method: 'delete', + }); +} diff --git a/src/views/my/initiateChange/modules/hazop.vue b/src/views/my/initiateChange/modules/hazop.vue index b92b62d..7686569 100644 --- a/src/views/my/initiateChange/modules/hazop.vue +++ b/src/views/my/initiateChange/modules/hazop.vue @@ -4,7 +4,6 @@ import { useMessage } from "naive-ui"; import { Icon } from '@iconify/vue' import { useThemeStore } from '@/store/modules/theme'; import { AiError, aiHazopDeviation } from '@/service/api/ai'; -import Ed from "./Ed.vue"; import { matrixConfigApi } from "@/service/api/system"; import { hazopNodesApi, @@ -17,7 +16,9 @@ import { hazopNodeDelApi, hazopObjDelApi, hazopDevDelApi, - hazopRowAddApi + hazopRowAddApi, + hazopRowEditApi, + hazopRowDelApi, } from "@/service/api/plugin"; const themeStore = useThemeStore(); @@ -99,6 +100,38 @@ const nodes = ref([]); // 表格样式 const TH = "border bg-slate-100 px-2 py-1.5 text-[11px] font-medium text-slate-500"; const TD = "border px-1.5 py-1 align-top"; +// 偏离总数 +const devTotal = computed(() => { + let total = 0; + nodes.value.forEach((node:any) => { + node.objects.forEach((obj:any) => { + total += obj.deviations.length; + }); + }); + return total; +}); +// 已分析偏离数 +const devDone = computed(() => { + let nonEmptyCount = 0; + nodes.value.forEach((node:any) => { + node.objects.forEach((obj:any) => { + obj.deviations.forEach((dev:any) => { + if (dev.rows && dev.rows.length > 0) { + nonEmptyCount++; + } + }); + }); + }); + return nonEmptyCount; +}); +// 已完成记录总数 +const recTotal = computed(() => { + const totalRows = nodes.value.flatMap((node:any) => node.objects) + .flatMap((obj:any) => obj.deviations) + .filter((d:any) => d.rows && d.rows.length > 0) + .reduce((sum:number, d:any) => sum + d.rows.length, 0); + return totalRows; +}); const HAZOP_AI:any = { @@ -124,9 +157,6 @@ const lowerOf = (lv: "高" | "中" | "低"): "高" | "中" | "低" => { const sel = ref({ n: 0, d: 0 }); const analyzing = ref(false); -const devTotal = computed(() => 0); -const devDone = computed(() => 0); -const recTotal = computed(() => 0); const toRec = (obj: string, dev: string, row: any): any => ({ item: `${dev}(${obj})`, @@ -138,12 +168,6 @@ const toRec = (obj: string, dev: string, row: any): any => ({ source: "HAZOP", }); -const updRow = (ri: number, patch: Partial) => { - const row = currentDev.value.rows[ri]; - if (row) Object.assign(row, patch); -}; -const clampLS = (v: string) => Math.max(1, Math.min(5, +v || 1)); - const runAi = async () => { if (currentDev.value.rows.length) return message.info("当前偏离已有分析记录,可手动新增行补充"); analyzing.value = true; @@ -202,6 +226,21 @@ const selectWorker = (n: string) => { sels.value = sels.value.includes(n) ? sels.value.filter((x) => x !== n) : [...sels.value, n]; }; +// 保存 +const save = () => { + window.$message?.success("已手动保存,分析记录数已同步至工具卡片(内容修改实时自动保存,退出不丢失)"); +}; + +// AI整理如表 +const exportAll = () => { + emit("export", nodes.value.flatMap((n) => n.devs.flatMap((d) => d.rows.map((row) => toRec(n.obj, d.name, row)))), "ai"); +} + +// 导出 Word +const exportWord = () => { + window.$message?.success('HAZOP 分析报告已导出(Word)') +} + // 根据l和s获取风险等级 const riskLevel = (l: number, s: number) => { const num = l * s; @@ -216,8 +255,9 @@ const riskLevel = (l: number, s: number) => { // 新增行 const addRow = async () => { - console.log(l_options.value) - console.log(s_options.value) + if(!currentDev.value){ + return window.$message?.warning("请先在左侧选择偏离") + } loading.value = true; const {data,error} = await hazopRowAddApi(currentDev.value?.id,{ cause: "", @@ -229,35 +269,39 @@ const addRow = async () => { suggestions: "", }) if(!error){ - console.log(data) - // getHazopNodes(); + currentDev.value.rows.push(data); window.$message?.success("新增行成功") } loading.value = false; }; +// 编辑行 +const editRow = async (row: any) => { + const {error} = await hazopRowEditApi(row.id,{ + cause: row.cause, + consequence: row.consequence, + l_value: row.l_value, + s_value: row.s_value, + risk_value: riskLevel(row.l_value, row.s_value)?.name || '', + safeguards: row.safeguards, + suggestions: row.suggestions, + }) +} // 删除行 -const delRow = (index: number) => currentDev.value.rows.splice(index, 1); +const delRow = async (index: number, row_id: number) => { + loading.value = true; + const {error} = await hazopRowDelApi(row_id); + if(!error){ + currentDev.value.rows.splice(index, 1); + window.$message?.success("删除成功") + } + loading.value = false; +} // 展开收起 const leftToggle = (id: string) => { collapsed.value = { ...collapsed.value, [id]: !collapsed.value[id] } } -// 保存 -const save = () => { - window.$message?.success("已手动保存,分析记录数已同步至工具卡片(内容修改实时自动保存,退出不丢失)"); -}; - -// AI整理如表 -const exportAll = () => { - emit("export", nodes.value.flatMap((n) => n.devs.flatMap((d) => d.rows.map((row) => toRec(n.obj, d.name, row)))), "ai"); -} - -// 导出 Word -const exportWord = () => { - window.$message?.success('HAZOP 分析报告已导出(Word)') -} - // 打开弹窗 const openModal = (type: string,obj: string, title: string,editName: string = '') => { if(type==='add'){ @@ -511,6 +555,7 @@ const getHazopNodes = async () => { treeLoading.value = true; const {data,error} = await hazopNodesApi(props.currentId); if(!error){ + console.log(data) nodes.value = data; } treeLoading.value = false; @@ -660,17 +705,17 @@ onMounted(() => { 操作 - 原因 - 后果 - L - S + 原因 + 后果 + L + S RR - 安全措施 - 建议措施 + 安全措施 + 建议措施 - + 当前偏离暂无分析记录,点击右上角「AI 分析当前偏离」自动生成,或「新增行」手动填写 @@ -681,33 +726,53 @@ onMounted(() => { 入表 - - - + + + + 确定删除吗? + - + - + - + - + - - {{ row.risk_value }} - + + {{riskLevel(row.l_value, row.s_value)?.name}}({{row.l_value * row.s_value}}) + - + - +