风险检查表分析工具完成

This commit is contained in:
2026-08-26 16:34:10 +08:00
parent b51de262b3
commit 26192167f3
5 changed files with 119 additions and 6 deletions
+7 -3
View File
@@ -11,6 +11,7 @@ import Ed from "./modules/Ed.vue";
import Hazop from "./modules/hazop.vue"; import Hazop from "./modules/hazop.vue";
import Jsa from "./modules/jsa.vue"; import Jsa from "./modules/jsa.vue";
import Scl from "./modules/scl.vue"; import Scl from "./modules/scl.vue";
import RiskCheck from "./modules/riskCheck.vue";
const themeStore = useThemeStore(); const themeStore = useThemeStore();
@@ -109,7 +110,7 @@ const formGen = ref<string>("idle");
const materialsText = ref(""); const materialsText = ref("");
const updateDocs = ref<string[]>([]); const updateDocs = ref<string[]>([]);
const disciplines = ref<string[]>([]); const disciplines = ref<string[]>([]);
const tools = ref<string[]>(["HAZOP","JSA", "SCL", "通用检查表"]); const tools = ref<string[]>(["HAZOP","JSA", "SCL", "RISK_CHECK"]);
const genForm = () => { const genForm = () => {
if (formGen.value === "generating") return; if (formGen.value === "generating") return;
formGen.value = "generating"; formGen.value = "generating";
@@ -294,7 +295,7 @@ const RISK_TOOLS_FORM = [
{ key: "HAZOP", label: "HAZOP" }, { key: "HAZOP", label: "HAZOP" },
{ key: "JSA", label: "JSA" }, { key: "JSA", label: "JSA" },
{ key: "SCL", label: "设备SCL" }, { key: "SCL", label: "设备SCL" },
{ key: "通用检查表", label: "风险检查表" }, { key: "RISK_CHECK", label: "风险检查表" },
]; ];
const recommendTools = () => { const recommendTools = () => {
const lv = form.value?.level === "重要" ? "重要" : "一般"; const lv = form.value?.level === "重要" ? "重要" : "一般";
@@ -394,7 +395,7 @@ const TOOL_CARDS = [
{ key: "HAZOP" as const, name: "HAZOP 分析", desc: "节点-偏离结构化分析:原因 / 后果 / LS 风险矩阵 / 安全措施" }, { key: "HAZOP" as const, name: "HAZOP 分析", desc: "节点-偏离结构化分析:原因 / 后果 / LS 风险矩阵 / 安全措施" },
{ key: "JSA" as const, name: "JSA 分析", desc: "作业步骤分解:危害因素识别与 LS 风险分级管控" }, { key: "JSA" as const, name: "JSA 分析", desc: "作业步骤分解:危害因素识别与 LS 风险分级管控" },
{ key: "SCL" as const, name: "设备 SCL", desc: "设备 / 管理检查项目对照标准逐项核查" }, { key: "SCL" as const, name: "设备 SCL", desc: "设备 / 管理检查项目对照标准逐项核查" },
{ key: "通用检查表" as const, name: "风险检查表", desc: "变更通用检查项:是 / 否 / 不涉及逐项判定,输出风险描述与管控措施" }, { key: "RISK_CHECK" as const, name: "风险检查表", desc: "变更通用检查项:是 / 否 / 不涉及逐项判定,输出风险描述与管控措施" },
]; ];
const pluginDone = ref<Record<string, number>>({}); const pluginDone = ref<Record<string, number>>({});
const riskRecords = ref<any>([]); const riskRecords = ref<any>([]);
@@ -1656,6 +1657,9 @@ const onBack = () => {
<template v-else-if="currentPlugin === 'SCL'"> <template v-else-if="currentPlugin === 'SCL'">
<Scl @back="onBack" @export="exportAll" /> <Scl @back="onBack" @export="exportAll" />
</template> </template>
<template v-else-if="currentPlugin === 'RISK_CHECK'">
<RiskCheck @back="onBack" />
</template>
</NDrawerContent> </NDrawerContent>
</NDrawer> </NDrawer>
</NCard> </NCard>
@@ -141,7 +141,7 @@ const rrOf = (l: number, s: number) => {
</NButton> </NButton>
<NButton size="small" ghost type="primary" class="text-xs" @click="save">保存</NButton> <NButton size="small" ghost type="primary" class="text-xs" @click="save">保存</NButton>
<span class="text-sm font-bold text-[var(--theme-color)]">HAZOP 分析插件</span> <span class="text-sm font-bold text-[var(--theme-color)]">HAZOP 分析插件</span>
<NTag size="small" type="primary">插件</NTag> <NTag size="small" type="info">插件</NTag>
<NTag size="small">MOC 变更缩合反应温度及时间优化演示</NTag> <NTag size="small">MOC 变更缩合反应温度及时间优化演示</NTag>
<span class="text-[11px] text-slate-500">{{ `分析进度 ${devDone}/${devTotal} 个偏离 · ${recTotal} 条记录` }}</span> <span class="text-[11px] text-slate-500">{{ `分析进度 ${devDone}/${devTotal} 个偏离 · ${recTotal} 条记录` }}</span>
<div class="relative"> <div class="relative">
+1 -1
View File
@@ -154,7 +154,7 @@ const toRec = (step: string, row: any): any => ({
</NButton> </NButton>
<NButton size="small" ghost type="primary" class="text-xs" @click="save">保存</NButton> <NButton size="small" ghost type="primary" class="text-xs" @click="save">保存</NButton>
<span class="text-sm font-bold text-[var(--theme-color)]">JSA 分析插件</span> <span class="text-sm font-bold text-[var(--theme-color)]">JSA 分析插件</span>
<NTag size="small" type="primary">插件</NTag> <NTag size="small" type="info">插件</NTag>
<NTag size="small">MOC 变更缩合反应温度及时间优化演示</NTag> <NTag size="small">MOC 变更缩合反应温度及时间优化演示</NTag>
<span class="text-[11px] text-slate-500">{{`LS 矩阵 · ${steps.length} 个作业步骤 · ${recTotal} 条危害因素记录`}}</span> <span class="text-[11px] text-slate-500">{{`LS 矩阵 · ${steps.length} 个作业步骤 · ${recTotal} 条危害因素记录`}}</span>
<div class="relative"> <div class="relative">
@@ -0,0 +1,109 @@
<script setup lang="ts">
import { computed, ref } from "vue";
import { useMessage } from "naive-ui";
import { Icon } from '@iconify/vue'
const message = useMessage();
const emit = defineEmits<{
back: [];
}>();
const RISK_CHECKS_INIT = [
{
id: 1, group: "安全健康", ans: "是",
q: "是否存在任何可能导致安全问题的化学反应?检查化学反应禁忌表。",
risk: "反应温度从80℃升至90℃,反应速率加快,放热更集中,可能引发反应失控或副反应,导致超温超压。",
measure: "1. 进行反应量热试验或查阅反应热数据,确认90℃下的放热速率和绝热温升;2. 评估现有冷却系统能力是否满足最大放热需求;3. 更新化学反应风险评估报告;4. 验证反应釜搅拌、冷却系统完好。",
},
{ id: 2, group: "安全健康", ans: "否", q: "是否存在任何易燃易爆化学物质或粉尘?" },
{
id: 3, group: "安全健康", ans: "是",
q: "是否存在任何有危险的原材料流速、成分或温度条件变更?",
risk: "反应温度条件从80±2℃变更至90±2℃,接近设备设计温度上限100℃,可能造成副反应增加或杂质生成。",
measure: "1. 通过小试实验验证90℃下的副反应种类及含量,确保产品杂质合格;2. 确认原料A和B在此温度下的稳定性;3. 将温度控制精度要求写入操作参数表。",
},
{
id: 4, group: "安全健康", ans: "是",
q: "是否会因加热、冷却或精确的温度控制失控而导致安全问题?",
risk: "温度控制失效(如加热阀门卡死、冷却中断)可能使实际温度超过100℃,导致设备超温、压力升高或反应失控。",
measure: "1. 调试并确认DCS温度高报警(95℃)和高高报警联锁(100℃)功能正常;2. 执行联锁回路功能测试(温度变送器、DCS卡件、电磁阀、切断阀);3. 确认加热介质切断阀为故障安全型。",
},
{
id: 5, group: "安全健康", ans: "是",
q: "是否具有为安全操作所必需的仪表、控制、紧急制动、开关或报警?",
risk: "变更后温度报警值上调,现有温度仪表量程可能不足或精度不够,影响安全操作。",
measure: "1. 检查温度变送器量程是否覆盖0~100℃,精度是否优于0.5级;2. 确认DCS报警值设定正确且已组态;3. 在DCS画面中明显标注新报警值。",
},
{
id: 6, group: "工艺与操作", ans: "是",
q: "变更后是否需要对操作人员进行专门培训?",
risk: "新工况(90℃ / 4小时)与原操作习惯差异较大,误操作可能引发超温或产品质量波动。",
measure: "1. 修订操作规程并组织专项培训考核;2. 投用首周实行双人复核操作;3. 关键参数调整权限上收至班长。",
},
{ id: 7, group: "工艺与操作", ans: "否", q: "是否涉及应急预案或消防设施的调整?" },
];
const pluginDone = ref<Record<string, number>>({});
const riskChecks = ref<any[]>(RISK_CHECKS_INIT.map((x) => ({ ...x })));
const riskGroups = computed(() => [...new Set(riskChecks.value.map((x) => x.group))]);
const riskFilter = ref<string>("全部");
const onBack = () => {
pluginDone.value = { ...pluginDone.value, RISK_CHECK: riskChecks.value.filter((x) => x.ans === '是').length };
emit("back");
}
const save = () => {
pluginDone.value = { ...pluginDone.value, RISK_CHECK: riskChecks.value.filter((x) => x.ans === '是').length };
message.success("已手动保存,分析记录数已同步至工具卡片(内容修改实时自动保存,退出不丢失)");
};
</script>
<template>
<div class="space-y-4">
<div class="flex flex-wrap items-center gap-3">
<NButton size="small" ghost type="primary" class="text-xs" @click="onBack">
<Icon icon="basil:arrow-left-outline" class="size-18px" /> 返回工具列表
</NButton>
<NButton size="small" ghost type="primary" class="text-xs" @click="save">保存</NButton>
<span class="flex items-center gap-1.5 text-sm font-semibold text-slate-700">变更风险检查表通用</span>
<NTag size="small" type="info">插件</NTag>
<div class="flex items-center gap-3">
<NRadioGroup v-model:value="riskFilter" name="radiogroup">
<NRadio v-for="song in [{label:'全部',value:'全部'},{label:'仅看「是」',value:'是'}]" :key="song.value" :value="song.value">
{{ song.label }}
</NRadio>
</NRadioGroup>
</div>
<span class="ml-auto inline-flex items-center gap-1 rounded-full border border-violet-200 bg-violet-100 px-2 py-0.5 text-xs font-medium text-violet-700">
AI 生成 · 需人工确认
</span>
</div>
<p class="text-[11px] text-slate-400">逐项判定 / / 不涉及判定为的检查项输出风险描述与管控措施完成后点返回工具列表回显完成项数</p>
<div v-for="g in riskGroups" :key="g" class="overflow-hidden rounded-lg border">
<div class="bg-slate-100 px-3 py-2 text-sm font-medium text-slate-700">{{ g }}</div>
<div v-for="item in riskChecks.filter((x) => x.group === g && (riskFilter === '全部' || x.ans === '是'))" :key="item.id"
class="grid gap-3 border-t px-3 py-3 grid-cols-[1.1fr_1fr_1fr]">
<div>
<div class="text-sm text-slate-700">{{ item.q }}</div>
<div class="mt-2 flex items-center gap-4">
<span v-for="a in ['是', '否', 'NA']" :key="a">
<NRadio
:checked="item.ans === a"
@change="riskChecks = riskChecks.map((x) => (x.id === item.id ? { ...x, ans: a } : x))"
>
{{ a }}
</NRadio>
</span>
</div>
</div>
<template v-if="item.ans === '是'">
<div class="rounded-lg bg-slate-50 p-2.5 text-xs leading-relaxed text-slate-600">
<span class="font-medium text-slate-500">风险描述</span>{{ item.risk }}
</div>
<div class="rounded-lg bg-slate-50 p-2.5 text-xs leading-relaxed text-slate-600">
<span class="font-medium text-slate-500">管控措施</span>{{ item.measure }}
</div>
</template>
<div v-else class="text-xs text-slate-300 self-center col-span-2">回答为{{ item.ans }}无风险描述</div>
</div>
</div>
</div>
</template>
+1 -1
View File
@@ -113,7 +113,7 @@ const groups = ref([
</NButton> </NButton>
<NButton size="small" ghost type="primary" class="text-xs" @click="save">保存</NButton> <NButton size="small" ghost type="primary" class="text-xs" @click="save">保存</NButton>
<span class="text-sm font-bold text-[var(--theme-color)]">SCL 安全检查表插件</span> <span class="text-sm font-bold text-[var(--theme-color)]">SCL 安全检查表插件</span>
<NTag size="small" type="primary">插件</NTag> <NTag size="small" type="info">插件</NTag>
<NTag size="small">MOC 变更缩合反应温度及时间优化演示</NTag> <NTag size="small">MOC 变更缩合反应温度及时间优化演示</NTag>
<span class="text-[11px] text-slate-500">{{ `${groups.length} 个检查分类 · ${recTotal} 项检查记录` }}</span> <span class="text-[11px] text-slate-500">{{ `${groups.length} 个检查分类 · ${recTotal} 项检查记录` }}</span>
<div class="relative"> <div class="relative">