Files
moc/src/views/home/pssr/index.vue
T

266 lines
14 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, onMounted } from 'vue';
import { Icon } from '@iconify/vue'
import { useThemeStore } from '@/store/modules/theme';
import { useRouterPush } from '@/hooks/common/router';
const themeStore = useThemeStore();
const { routerPushByKey } = useRouterPush();
const loading = ref<boolean>(false);
const keyword = ref<string>("");
const openCount = ref<number>(4);
const closedCount = ref<number>(2);
const currentTab = ref<string>("open");
const range = ref<string>("全部时间");
const list = ref<any[]>([]);
const openList = [
{
id: "MOC-2026-R02-0038",statusDetail: "培训 / PSSR 资料已传 · 待确认投用",
dept: "一车间", planUse: "2026-07-31", applicant: "吴强",
title: 'DCS 罐区液位报警值 LIA-301 调整', status: '待PSSR',
pssr: "PSSR 检查确认表-签字版.pdf",hasChange: true,
},
{
id: "MOC-2026-R01-0039",statusDetail: "待关闭确认(资料更新核查中)",
dept: "一车间", planUse: "2026-07-16(已投用)", applicant: "张工艺",
title: 'V-102 安全阀起跳压力临时调整(紧急补办)', status: '待关闭',
pssr: "",hasChange: true,
},
{
id: "MOC-2026-R03-0040",statusDetail: "实施准备中 · 培训 / PSSR 资料待上传",
dept: "供应部", planUse: "2026-08-01", applicant: "刘芳",
title: '原料环己烷供应商变更(新增 B 供应商)', status: '实施中',
pssr: "",hasChange: true,
},
{
id: "MOC-2026-R02-0031",statusDetail: "变更验收(72h 运行验证)",
dept: "二车间", planUse: "2026-07-15", applicant: "周涛",
title: '冷冻盐水泵 P-103 叶轮材质变更', status: '待验收',
pssr: "PSSR 检查确认表-签字版.pdf",hasChange: false,
},
{
id: "MOC-2026-R02-0038",statusDetail: "培训 / PSSR 资料已传 · 待确认投用",
dept: "一车间", planUse: "2026-07-31", applicant: "吴强",
title: 'DCS 罐区液位报警值 LIA-301 调整', status: '待PSSR',
pssr: "PSSR 检查确认表-签字版.pdf",hasChange: true,
},
{
id: "MOC-2026-R01-0039",statusDetail: "待关闭确认(资料更新核查中)",
dept: "一车间", planUse: "2026-07-16(已投用)", applicant: "张工艺",
title: 'V-102 安全阀起跳压力临时调整(紧急补办)', status: '待关闭',
pssr: "",hasChange: true,
},
{
id: "MOC-2026-R03-0040",statusDetail: "实施准备中 · 培训 / PSSR 资料待上传",
dept: "供应部", planUse: "2026-08-01", applicant: "刘芳",
title: '原料环己烷供应商变更(新增 B 供应商)', status: '实施中',
pssr: "",hasChange: true,
},
{
id: "MOC-2026-R02-0031",statusDetail: "变更验收(72h 运行验证)",
dept: "二车间", planUse: "2026-07-15", applicant: "周涛",
title: '冷冻盐水泵 P-103 叶轮材质变更', status: '待验收',
pssr: "PSSR 检查确认表-签字版.pdf",hasChange: false,
},
{
id: "MOC-2026-R02-0038",statusDetail: "培训 / PSSR 资料已传 · 待确认投用",
dept: "一车间", planUse: "2026-07-31", applicant: "吴强",
title: 'DCS 罐区液位报警值 LIA-301 调整', status: '待PSSR',
pssr: "PSSR 检查确认表-签字版.pdf",hasChange: true,
},
{
id: "MOC-2026-R01-0039",statusDetail: "待关闭确认(资料更新核查中)",
dept: "一车间", planUse: "2026-07-16(已投用)", applicant: "张工艺",
title: 'V-102 安全阀起跳压力临时调整(紧急补办)', status: '待关闭',
pssr: "",hasChange: true,
},
{
id: "MOC-2026-R03-0040",statusDetail: "实施准备中 · 培训 / PSSR 资料待上传",
dept: "供应部", planUse: "2026-08-01", applicant: "刘芳",
title: '原料环己烷供应商变更(新增 B 供应商)', status: '实施中',
pssr: "",hasChange: true,
},
{
id: "MOC-2026-R02-0031",statusDetail: "变更验收(72h 运行验证)",
dept: "二车间", planUse: "2026-07-15", applicant: "周涛",
title: '冷冻盐水泵 P-103 叶轮材质变更', status: '待验收',
pssr: "PSSR 检查确认表-签字版.pdf",hasChange: false,
},
];
const closedList = [
{
id: "MOC-2026-R03-0027",statusDetail: "关闭确认完成,已归档",
dept: "质量部", planUse: "2026-06-25", applicant: "陈静",
title: '化验室通风橱整体更换', status: '已关闭',
pssr: "PSSR 检查确认表-归档版.pdf"
},
{
id: "MOC-2026-R01-0024",statusDetail: "关闭确认完成,已归档",
dept: "一车间", planUse: "2026-06-20", applicant: "孙丽",
title: '氮气管网压力分级调整', status: '已关闭',
pssr: "PSSR 检查确认表-归档版.pdf"
},
];
// 切换tab
const tabChange = (k: string) => {
list.value = []
currentTab.value = k;
loading.value = true;
if(k === 'open'){
setTimeout(() => {
list.value = openList;
loading.value = false;
}, 1000);
}
if(k === 'closed'){
setTimeout(() => {
list.value = closedList;
loading.value = false;
}, 1000);
}
}
// 查看
const viewFile = (record: any) => {
window.$message?.info(`预览「${record.pssr}」(上传件不做内容识别,原件已随单归档)`)
};
// 下载
const downloadFile = (record: any) => {
window.$message?.success(`下载「${record.pssr}」`)
};
// 下载模板
const downloadTemplate = (record: any) => {
window.$message?.success(`下载 PSSR 确认表空白模板(打印后线下签署)`)
};
// 打开变更单
const openChange = (record: any) => {
routerPushByKey('home_highriskdetail', { query: { params: JSON.stringify(record) } })
};
onMounted(() => {
tabChange('open');
})
</script>
<template>
<NSpace vertical :size="16">
<!-- PSSR监督 -->
<NSpin :show="loading" size="small">
<NCard :bordered="false" size="small" :style="{ borderRadius: themeStore.themeRadius + 'px' }">
<div
class="flex flex-wrap items-center gap-2 mb-3"
:style="{ '--theme-color': themeStore.themeColor}"
>
<div class="flex overflow-hidden rounded-full border">
<div @click="tabChange('open')" class="px-3.5 py-1.5 text-xs cursor-pointer select-none"
:class="currentTab === 'open' ? 'bg-[var(--theme-color)] font-medium text-white' : 'bg-white text-slate-600 hover:bg-slate-50'">
未关闭的变更 <b>{{ openCount }}</b>
</div>
<div @click="tabChange('closed')" class="border-l px-3.5 py-1.5 text-xs cursor-pointer select-none"
:class="currentTab === 'closed' ? 'bg-[var(--theme-color)] font-medium text-white' : 'bg-white text-slate-600 hover:bg-slate-50'">
已关闭的变更 <b>{{ closedCount }}</b>
</div>
</div>
<NInput v-model:value="keyword" size="small" class="text-xs !w-160px" placeholder="搜索变更名称 / 编号">
<template #suffix>
<Icon icon="akar-icons:search" class="size-14px text-slate-400 cursor-pointer" />
</template>
</NInput>
<div class="flex items-center gap-1.5">
<NButton
size="tiny"
round
v-for="t in ['全部时间', '近 7 天', '近 30 天', '近 90 天']"
:key="t"
class="text-[11px]"
:type="range === t ? 'primary' : 'default'"
@click="range = t"
>
{{ t }}
</NButton>
</div>
<span class="ml-auto text-[11px] text-slate-400">培训 / PSSR 为线下确认 + 资料上传制 · PSSR 检查表同行查看 / 下载</span>
</div>
<div class="text-[11px] leading-4 text-slate-400 pb-2">
培训 / PSSR 为线下组织并签字拍照或扫描上传即视为完成确认并随单归档系统不做内容识别本页为 PSSR 检查表的查看 / 下载入口
</div>
<!-- 未关闭的变更 -->
<div v-if="currentTab === 'open'" class="scroll">
<div
class="space-y-3 h-100%"
:style="{
'--theme-color': themeStore.themeColor,
'--warning-color': themeStore.otherColor.warning,
}"
>
<div v-for="(s, i) in list" :key="`${s.id ?? 'x'}-${i}`" class="flex flex-wrap items-center gap-x-3 gap-y-2 border p-4" :style="{ borderRadius: themeStore.themeRadius + 'px' }">
<NTag v-if="s.status==='待PSSR'" type="warning" size="small">{{ s.status }}</NTag>
<NTag v-if="s.status==='待关闭'" type="error" size="small">{{ s.status }}</NTag>
<NTag v-if="s.status==='实施中'" type="primary" size="small">{{ s.status }}</NTag>
<NTag v-if="s.status==='待验收'" type="success" size="small">{{ s.status }}</NTag>
<div class="min-w-0 flex-1">
<p class="block truncate text-sm font-medium text-slate-800">{{ s.title }}</p>
<span class="mt-0.5 block text-[11px] text-slate-400">{{ s.id }} · {{ s.dept }} · {{ s.applicant }} · {{ s.statusDetail }} · 计划投用 {{ s.planUse }}</span>
</div>
<div class="flex items-center gap-1.5 rounded-md border bg-slate-50/60 px-2 py-1">
<Icon icon="akar-icons:file" class="size-14px text-[var(--theme-color)]" />
<span class="text-[11px] font-medium text-slate-600">PSSR 检查确认表</span>
<template v-if="s.pssr">
<span class="max-w-[150px] truncate text-[11px] text-slate-400">{{ s.pssr }}</span>
<NButton ghost size="tiny" class="text-11px" @click="viewFile(s)">查看</NButton>
<NButton ghost size="tiny" class="text-11px" @click="downloadFile(s)">下载</NButton>
</template>
<template v-else>
<span class="text-[11px] text-[var(--warning-color)]">待传</span>
<NButton ghost size="tiny" class="text-11px" @click="downloadTemplate(s)">下载模板</NButton>
</template>
</div>
<NButton v-if="s.hasChange" size="small" type="primary" class="text-xs" @click="openChange(s)">打开变更单</NButton>
</div>
<div v-if="list.length === 0" class="h-100% flex items-center justify-center">
<NEmpty description="暂无数据"></NEmpty>
</div>
</div>
</div>
<!-- 已关闭的变更 -->
<div v-if="currentTab === 'closed'" class="scroll">
<div
class="space-y-3 h-100%"
:style="{
'--theme-color': themeStore.themeColor,
'--warning-color': themeStore.otherColor.warning,
}"
>
<div v-for="(s, i) in list" :key="`${s.id ?? 'x'}-${i}`" class="flex flex-wrap items-center gap-x-3 gap-y-2 border p-4" :style="{ borderRadius: themeStore.themeRadius + 'px' }">
<NTag v-if="s.status==='已关闭'" type="success" size="small">{{ s.status }}</NTag>
<div class="min-w-0 flex-1">
<p class="block truncate text-sm font-medium text-slate-800">{{ s.title }}</p>
<span class="mt-0.5 block text-[11px] text-slate-400">{{ s.id }} · {{ s.dept }} · {{ s.applicant }} · {{ s.statusDetail }} · 计划投用 {{ s.planUse }}</span>
</div>
<div class="flex items-center gap-1.5 rounded-md border bg-slate-50/60 px-2 py-1">
<Icon icon="akar-icons:file" class="size-14px text-[var(--theme-color)]" />
<span class="text-[11px] font-medium text-slate-600">PSSR 检查确认表</span>
<span class="max-w-[150px] truncate text-[11px] text-slate-400">{{ s.pssr }}</span>
<NButton ghost size="tiny" class="text-11px" @click="viewFile(s)">查看</NButton>
<NButton ghost size="tiny" class="text-11px" @click="downloadFile(s)">下载</NButton>
</div>
</div>
<div v-if="list.length === 0" class="h-100% flex items-center justify-center">
<NEmpty description="暂无数据"></NEmpty>
</div>
</div>
</div>
</NCard>
</NSpin>
</NSpace>
</template>
<style scoped lang="scss">
.scroll {
height: calc(100vh - 212px);
overflow-y: auto;
}
</style>