@@ -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 >