风险预分析和风险检查表插件完成

This commit is contained in:
2026-09-10 13:18:19 +08:00
parent a5cca53127
commit bb41d5a849
9 changed files with 643 additions and 162 deletions
@@ -3,6 +3,7 @@
import { computed, onMounted, ref } from 'vue';
import { Icon } from '@iconify/vue'
import { useThemeStore } from '@/store/modules/theme';
import RiskPre from "./riskPre.vue";
import Hazop from "./hazop.vue";
import Jsa from "./jsa.vue";
import Scl from "./scl.vue";
@@ -24,16 +25,16 @@ const pluginDone = computed(() =>
return acc;
}, {} as Record<string, number>)
);
const tools = ref<string[]>(["HAZOP","JSA", "SCL", "RISK_CHECK"]);
const tools = ref<string[]>(["RISK","HAZOP","JSA", "RISK_CHECK"]);
const riskRecords = ref<any>([]);
const pluginDrawer = ref<boolean>(false);
const currentPlugin = ref<string>('');
// 风险识别分析记录表
const TOOL_CARDS = [
{ key: "RISK", name: "风险预分析" },
{ key: "HAZOP", name: "HAZOP 分析" },
{ key: "JSA", name: "JSA 分析" },
{ key: "SCL", name: "设备 SCL" },
{ key: "RISK_CHECK", name: "风险检查表" },
];
@@ -160,12 +161,14 @@ const exportAll = (type: string, items: any[]) => {
// 使用插件弹框
const usePlugin = (key: string) => {
console.log(riskRecords.value)
currentPlugin.value = key;
pluginDrawer.value = true;
}
// 关闭插件弹框
const closePlugin = () => {
const closePlugin = (type: string = "", count: any = undefined) => {
if(type){
pluginDone.value[type] = count;
}
pluginDrawer.value = false;
}
@@ -218,7 +221,7 @@ onMounted(() => {
{{ formInfo?.change_level === 2 ? '重要变更' : '一般变更' }}
</NTag>
<span class="text-xs text-slate-400">
{{ formInfo?.change_level === 2 ? '规则:HAZOP 必做,同时开展 JSA 与检查表法(SCL' : '规则:JSA + 检查表法(SCL,涉及工艺安全边界的应升级 HAZOP' }}
{{ formInfo?.change_level === 2 ? '规则:HAZOP 必做,同时开展 JSA' : '规则:JSA,涉及工艺安全边界的应升级 HAZOP' }}
</span>
</div>
<div class="grid gap-2 grid-cols-4 mt-3">
@@ -268,7 +271,7 @@ onMounted(() => {
尚无风险记录调用上方插件完成分析后逐条入表或点击AI 自动整理形成记录表
</div>
<div v-else class="overflow-x-auto p-3">
<table class="w-full min-w-[960px] border-collapse text-xs">
<table class="w-full border-collapse text-xs">
<thead>
<tr>
<th class="w-40 border bg-slate-50 px-2 py-1.5 text-[11px] font-medium text-slate-500">风险项</th>
@@ -283,13 +286,39 @@ onMounted(() => {
</thead>
<tbody>
<tr v-for="(rec, i) in riskRecords" :key="i">
<td class="border px-1.5 py-1 align-top font-medium text-slate-700">
<td class="border px-1.5 py-1 font-medium text-slate-700">
<NInput type="textarea" size="small" v-model:value="rec.risk_item" :autosize="{minRows:1}" class="text-xs" />
</td>
<td class="border px-1.5 py-1 align-top">
<td class="border px-1.5 py-1">
<NInput type="textarea" size="small" v-model:value="rec.scene" :autosize="{minRows:1}" class="text-xs" />
</td>
<td class="border px-1.5 py-1 text-center align-top">
<div v-if="rec.source==='RISK'">
<NTag
v-if="rec.risk_value && rec.risk_value === '低'"
class="text-[11px]"
size="small"
type="success"
>
{{rec.risk_value}}
</NTag>
<NTag
v-if="rec.risk_value && rec.risk_value === '中'"
class="text-[11px]"
size="small"
type="warning"
>
{{rec.risk_value}}
</NTag>
<NTag
v-if="rec.risk_value && rec.risk_value === '高'"
class="text-[11px]"
size="small"
type="error"
>
{{rec.risk_value}}
</NTag>
</div>
<div v-if="rec.source==='HAZOP'">
<NTag
v-if="rec.l_value>0 && rec.s_value>0"
@@ -319,13 +348,39 @@ onMounted(() => {
</NTag>
</div>
</td>
<td class="border px-1.5 py-1 align-top">
<td class="border px-1.5 py-1">
<NInput type="textarea" size="small" v-model:value="rec.safe" :autosize="{minRows:1}" class="text-xs" />
</td>
<td class="border px-1.5 py-1 align-top">
<NInput type="textarea" size="small" v-model:value="rec.suggestion" :autosize="{minRows:1}" class="text-xs" />
<td class="border px-1.5 py-1">
<NInput type="textarea" size="small" v-model:value="rec.suggestion" :autosize="{minRows:1}" class="text-xs" />
</td>
<td class="border px-1.5 py-1 text-center align-top">
<div v-if="rec.source==='RISK'">
<NTag
v-if="rec.residual_risk_value && rec.residual_risk_value === '低'"
class="text-[11px]"
size="small"
type="success"
>
{{rec.residual_risk_value}}
</NTag>
<NTag
v-if="rec.residual_risk_value && rec.residual_risk_value === '中'"
class="text-[11px]"
size="small"
type="warning"
>
{{rec.residual_risk_value}}
</NTag>
<NTag
v-if="rec.residual_risk_value && rec.residual_risk_value === '高'"
class="text-[11px]"
size="small"
type="error"
>
{{rec.residual_risk_value}}
</NTag>
</div>
<div v-if="rec.source==='HAZOP'">
<NTag
v-if="rec.l_value>0 && rec.s_value>0"
@@ -360,7 +415,7 @@ onMounted(() => {
</div>
</td>
<td class="border px-1.5 py-1 text-center align-top">
<NTag size="small" type="info" class="text-11px">{{ rec.source }}</NTag>
<NTag size="small" type="info" class="text-11px">{{ rec.source==='RISK'?'风险预分析':rec.source }}</NTag>
</td>
<td class="border px-1.5 py-1 text-center align-top">
<NTag v-if="rec.to_pssr" size="small" :color="{ color: '#f5f3ff', textColor: '#7c3aed', borderColor: '#f5f3ff' }">已转 PSSR</NTag>
@@ -400,17 +455,20 @@ onMounted(() => {
<!-- 插件抽屉 -->
<NDrawer v-model:show="pluginDrawer" width="85%" placement="right">
<NDrawerContent>
<template v-if="currentPlugin === 'RISK'">
<RiskPre :isAiOpen="props.isAiOpen" :currentId="props.currentId" :jsaRiskMatrixConfig="jsaRiskMatrixConfig" @close="closePlugin" @toTable="exportAll" />
</template>
<template v-if="currentPlugin === 'HAZOP'">
<Hazop :isAiOpen="props.isAiOpen" :currentId="props.currentId" :hazopRiskMatrixConfig="hazopRiskMatrixConfig" @close="closePlugin" @toTable="exportAll" />
</template>
<template v-else-if="currentPlugin === 'JSA'">
<template v-if="currentPlugin === 'JSA'">
<Jsa :isAiOpen="props.isAiOpen" :currentId="props.currentId" :jsaRiskMatrixConfig="jsaRiskMatrixConfig" @close="closePlugin" @toTable="exportAll" />
</template>
<template v-else-if="currentPlugin === 'SCL'">
<template v-if="currentPlugin === 'SCL'">
<Scl @close="closePlugin" @toTable="exportAll" />
</template>
<template v-else-if="currentPlugin === 'RISK_CHECK'">
<RiskCheck @close="closePlugin" />
<template v-if="currentPlugin === 'RISK_CHECK'">
<RiskCheck :isAiOpen="props.isAiOpen" :currentId="props.currentId" @close="closePlugin" />
</template>
</NDrawerContent>
</NDrawer>