Files
moc/src/views/my/initiateChange/modules/evaluation.vue
T

207 lines
12 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!-- 验收评价 -->
<script setup lang="ts">
import { ref } from 'vue';
import { Icon } from '@iconify/vue'
import { useThemeStore } from '@/store/modules/theme';
import { getColorWithOpacity } from "@/utils/common";
import Footer from './footer.vue';
const themeStore = useThemeStore();
const props = defineProps(['type','isAiOpen','title','currentId','formInfo'])
const emit = defineEmits(['save','submit','confirmTab']);
const form = ref<{ content: string }>({
content: ''
});
const editing = ref<any>(null);
const acceptRows = ref([
{ id: 1, item: "反应转化率", basis: "转化率不低于 98%", standard: "转化率 ≥ 98%(连续 3 批化验合格)", method: "化验室逐批取样分析,出具检验报告", owner: "车间 · 张工艺", result: "待验收" },
{ id: 2, item: "单批反应时间 / 产能", basis: "反应时间缩短 50%、产能提升一倍", standard: "保温时间 4h±0.5h,产能提升 ≥ 80%", method: "DCS 批次记录统计,对比变更前 30 天均值", owner: "车间 · 李主任", result: "待验收" },
{ id: 3, item: "未知杂质含量", basis: "杂质水平受控、产品质量合格", standard: "杂质 ≤ 0.15%,产品质量指标全部合格", method: "每批化验跟踪,连续 5 批数据趋势评估", owner: "质量 · 王海燕", result: "待验收" },
{ id: 4, item: "温控与联锁有效性", basis: "温度窗口上调后保护层有效", standard: "温度波动 ≤ ±2℃,高报/联锁动作正确率 100%", method: "DCS 趋势核查 + 联锁测试记录复核", owner: "仪表 · 王仪表", result: "待验收" },
{ id: 5, item: "设备运行状态", basis: "负荷变化后设备长周期稳定", standard: "搅拌电流、釜壁温度无异常趋势,无泄漏", method: "设备巡检 + 振动/温度记录评估", owner: "设备 · 周设备", result: "待验收" },
]);
const acceptNote = ref("");
// 保存草稿
const saveDraft = () => {
emit('save');
}
// 提交
const submitConfirm = () => {
emit('submit', props.type);
}
// // 确认标签内容
const confirmTab = (tab:string, val:boolean) => {
emit('confirmTab', tab, val);
}
defineExpose({form})
</script>
<template>
<div class="p-4">
<div class="space-y-4 scroll">
<div class="flex flex-wrap items-center gap-3">
<span class="flex items-center gap-1.5 text-sm font-semibold text-slate-700">
<Icon icon="ix:success" class="size-18px text-emerald-500" />
验收评价依据预期效果设定可量化验收标准
</span>
<span class="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>
<span class="ml-auto text-xs text-slate-400">申请阶段由 AI 依据预期效果生成量化标准与验收方式可手动修改投用运行后由车间和各专业按标准验收并给出评估结论</span>
</div>
<div
class="space-y-1.5 rounded-lg border border-[var(--border-color)] bg-[var(--bg-color)] px-4 py-3 text-xs leading-6 text-slate-700"
:style="{
'--bg-color': getColorWithOpacity(themeStore.themeColor, 0.1),
'--border-color': getColorWithOpacity(themeStore.themeColor, 0.2)
}"
>
<div><b :style="{color: themeStore.themeColor}">变更目的</b>{{ formInfo?.purposes?.join('、') || '' }}</div>
<div><b :style="{color: themeStore.themeColor}">预期效果</b>{{ formInfo?.effect || '' }}</div>
<div
class="border-t border-[var(--border-color)] pt-1.5 text-slate-500"
:style="{'--border-color': getColorWithOpacity(themeStore.themeColor, 0.2)}"
>
<b :style="{color: themeStore.themeColor}">对应说明</b>验收项目由预期效果逐条拆解设定各项目对应的预期效果来源见表格验收项目列下方灰色小字点击可修改);验收时须逐项对照预期效果判定达成程度
</div>
</div>
<div class="overflow-x-auto border" :style="{ borderRadius: themeStore.themeRadius + 'px' }">
<table class="w-full min-w-[900px] border-collapse text-sm">
<thead>
<tr class="bg-slate-100 text-left text-slate-600">
<th class="w-8 px-3 py-2 font-medium">#</th>
<th class="w-56 px-3 py-2 font-medium">验收项目含对应预期效果</th>
<th class="px-3 py-2 font-medium">量化验收标准</th>
<th class="px-3 py-2 font-medium">验收方式可执行</th>
<th class="w-32 px-3 py-2 font-medium">责任单位/</th>
<th class="px-3 py-2 font-medium">评估结论</th>
<th class="w-12 px-2 py-2 font-medium text-center">操作</th>
</tr>
</thead>
<tbody>
<tr v-for="(row, i) in acceptRows" :key="row.id" class="align-top">
<td class="border-t px-3 py-2.5 text-slate-400">{{ i + 1 }}</td>
<td class="border-t px-3 py-2.5">
<NInput
v-if="editing === `acc-${row.id}-item`"
class="text-xs"
v-model:value="row.item"
type="textarea"
autofocus
rows="2"
@blur="editing = null"
/>
<button v-else @click="editing = `acc-${row.id}-item`" title="点击修改"
class="bg-transparent block w-full rounded-md px-2 py-1 text-left text-xs font-medium leading-relaxed text-slate-700 transition hover:bg-[#EAF0F9]"
>
{{ row.item }}
</button>
<NInput
v-if="editing === `acc-${row.id}-basis`"
class="text-[11px]"
size="small"
v-model:value="row.basis"
autofocus
@blur="editing = null"
/>
<button v-else @click="editing = `acc-${row.id}-basis`" title="本项目对应的预期效果来源,点击修改"
class="bg-transparent mt-0.5 block w-full rounded px-2 text-left text-[11px] text-slate-400 transition hover:bg-[#EAF0F9] hover:text-slate-500"
>
对应预期{{ row.basis || '(点击填写对应预期效果)' }}
</button>
</td>
<td v-for="field in (['standard', 'method', 'owner'])" :key="field" class="border-t px-3 py-2.5">
<NInput
v-if="editing === `acc-${row.id}-${field}`"
class="text-xs"
v-model:value="row[field]"
type="textarea"
autofocus
rows="2"
@blur="editing = null"
/>
<button v-else @click="editing = `acc-${row.id}-${field}`" title="点击修改"
class="bg-transparent block w-full rounded-md px-2 py-1 text-left text-xs leading-relaxed text-slate-700 transition hover:bg-[#EAF0F9]"
>
{{ row[field] }}
</button>
</td>
<td class="border-t px-3 py-2.5">
<div class="flex flex-nowrap items-center gap-1">
<NButton v-for="v in (['完全达到', '基本达到', '未达成'])" :key="v"
size="small"
round
@click="acceptRows = acceptRows.map((x) => (x.id === row.id ? { ...x, result: x.result === v ? '待验收' : v } : x))"
class="text-[11px]"
:type="row.result === v
? v === '未达成' ? 'error' : v === '基本达到' ? 'warning' : 'success'
: 'default'">
{{ v }}
</NButton>
</div>
</td>
<td class="border-t px-2 py-2.5 text-center">
<NPopconfirm
positive-text="确定"
:positiveButtonProps="{ size: 'tiny' }"
:negativeButtonProps="{ size: 'tiny' }"
@positive-click="acceptRows = acceptRows.filter((x) => x.id !== row.id)"
>
<template #trigger>
<NButton text type="error" title="删除本验收项">
<Icon icon="iconamoon:trash" class="size-16px" />
</NButton>
</template>
确定删除吗?
</NPopconfirm>
</td>
</tr>
</tbody>
</table>
</div>
<div class="flex items-center gap-3">
<NButton ghost class="text-xs"
@click="acceptRows = [...acceptRows, { id: Date.now(), item: '新验收项目', basis: '', standard: '', method: '', owner: '', result: '待验收' }]">
<Icon icon="ic:round-plus" class="size-16px" />添加验收项
</NButton>
<span class="text-xs text-slate-400">评估结论在验收阶段由责任单位填写:点击选择「完全达到 / 基本达到 / 未达成」,再次点击取消;行尾可删除验收项</span>
</div>
<div class="rounded-lg border">
<div class="border-b bg-slate-100 px-3 py-2 text-sm font-medium text-slate-700">综合验收结论(验收阶段由车间会同各专业评估填写)</div>
<div class="space-y-3 p-3">
<div class="flex flex-wrap items-center gap-2">
<span v-for="v in (['完全达到', '基本达到', '未达成'])" :key="v">
<NRadio :checked="acceptNote !== '' && acceptNote.startsWith(v)" :value="'v'" :label="v" @change="acceptNote = v + ''"></NRadio>
</span>
<span class="text-xs text-slate-400">「基本达到 / 未达成」须说明偏差原因与处置措施,并纳入变更关闭审核</span>
</div>
<NInput v-model:value="acceptNote" type="textarea" rows="2" placeholder="验收意见总体评价偏差说明后续跟踪措施…(验收阶段填写" />
</div>
</div>
<div class="rounded-lg bg-emerald-50/80 px-4 py-2.5 text-xs leading-5 text-emerald-700">
流程说明:投用运行满验收周期后,系统向车间(属地)与涉及专业推送验收任务;各责任单位按上表逐项给出评估结论并上传佐证(数据报表 / 化验报告 / 现场照片),全部完成后汇总至综合验收结论,结论与佐证资料一并纳入变更关闭校验,验收不通过时退回整改或评估恢复原状。
</div>
</div>
</div>
<Footer
ref="footerRef"
:type="props.type"
:currentId="props.currentId"
:title="props.title"
:isAiOpen="props.isAiOpen"
@save="saveDraft"
@submit="submitConfirm"
@confirmTab="confirmTab"
/>
</template>
<style scoped lang="scss">
.scroll {
height: calc(100vh - 393px);
overflow-y: auto;
}
</style>