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

281 lines
13 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, computed } from 'vue';
import { useAppStore } from '@/store/modules/app';
import { Icon } from '@iconify/vue'
import { useThemeStore } from '@/store/modules/theme';
import { getColorWithOpacity } from "@/utils/common";
import ColumnChart from './modules/columnChart.vue';
import RingChart from "./modules/ringChart.vue";
import RingChart2 from "./modules/ringChart2.vue";
const appStore = useAppStore();
const themeStore = useThemeStore();
const gap = computed(() => (appStore.isMobile ? 0 : 16));
const emit = defineEmits<{ go: [v: string, preset?: string]; openChange: [c: any] }>();
const range = ref("近一年");
const rangeOptions = [
{label: "近一年", value: "近一年"},
{label: "近半年", value: "近半年"},
{label: "近三个月", value: "近三个月"},
{label: "近一个月", value: "近一个月"},
];
const changeData = ref([
{
name: '一车间',
value: 42,
},
{
name: '二车间',
value: 35,
},
{
name: '三车间',
value: 28,
},
{
name: '供应部',
value: 12,
},
{
name: '质量部',
value: 9,
},
]);
const DEPT_ACCEPT = [
{ name: "工艺", value: 58 },
{ name: "设备", value: 41 },
{ name: "管理", value: 27 },
];
const ACCEPT_COLORS = ["#2080f0", "#faad14", "#52c41a"];
const DEPT_ACCEPT2 = [
{ name: "完全达到", value: 13, money: 61.2, rate: 68 },
{ name: "基本达到", value: 4, money: 19.8, rate: 21 },
{ name: "未达到", value: 2, money: 5.4, rate: 11 },
];
const ACCEPT_COLORS2 = ["#52c41a", "#faad14", "#ff4d4f"];
const residualHigh = ref<{id: string, title: string}>({id:'MOC-2026-R01-0035',title:'R-201 反应釜搅拌器电机更换(55kW→75kW 防爆电机)'});
</script>
<template>
<NSpace vertical :size="16">
<!-- 我的工作台 -->
<NCard :bordered="false" size="small" :style="{ borderRadius: themeStore.themeRadius + 'px' }">
<div class="flex flex-wrap items-center gap-2">
<p class="text-sm font-bold text-slate-800">全厂变更数据中心</p>
<p class="text-[11px] text-slate-400 mt-[1px]">时间相关数据统一在此查询 · 统计时段</p>
<NSelect v-model:value="range" :options="rangeOptions" size="tiny" class="w-28" />
<NButton ghost size="small" class="ml-auto text-xs">导出</NButton>
</div>
</NCard>
<!-- 卡片数据 -->
<NGrid cols="s:1 m:2 l:4" responsive="screen" :x-gap="gap" :y-gap="16"
:style="{
'--theme-color': themeStore.themeColor,
'--theme-bg': getColorWithOpacity(themeStore.themeColor, 0.2),
'--warning-bg': getColorWithOpacity(themeStore.otherColor.warning, 0.2),
'--warning-color': themeStore.otherColor.warning,
'--success-color': themeStore.otherColor.success,
'--success-bg': getColorWithOpacity(themeStore.otherColor.success, 0.2),
'--error-color': themeStore.otherColor.error,
'--error-bg': getColorWithOpacity(themeStore.otherColor.error, 0.2),
}"
>
<NGi>
<div
class="h-100% flex-1 flex items-center gap-3 bg-white px-16px py-12px cursor-pointer transition hover:-translate-y-1"
:style="{ borderRadius: themeStore.themeRadius + 'px' }"
@click="emit('go', 'tasks')"
>
<span class="shrink-0 rounded-lg p-2.5 bg-[var(--theme-bg)]">
<Icon icon="akar-icons:file" class="size-24px text-[--theme-color]" />
</span>
<div class="flex flex-col">
<CountTo
:start-value="0"
:end-value="126"
class="text-26px font-600"
/>
<p class="text-[11px] font-semibold text-slate-400">变更总数 · {{ range }}</p>
</div>
</div>
</NGi>
<NGi>
<div
class="h-100% flex-1 flex items-center gap-3 bg-white px-16px py-12px cursor-pointer transition hover:-translate-y-1"
:style="{ borderRadius: themeStore.themeRadius + 'px' }"
@click="emit('go', 'tasks')"
>
<span class="shrink-0 rounded-lg p-2.5 bg-[var(--warning-bg)]">
<Icon icon="lucide:shield-check" class="size-24px text-[--warning-color]" />
</span>
<div class="flex flex-col">
<CountTo
:start-value="0"
:end-value="18"
class="text-26px font-600"
/>
<p class="text-[11px] font-semibold text-slate-400">重要变更数量 · {{ range }} · 占比 14%</p>
</div>
</div>
</NGi>
<NGi>
<div
class="h-100% flex-1 flex items-center gap-3 bg-white px-16px py-12px cursor-pointer transition hover:-translate-y-1"
:style="{ borderRadius: themeStore.themeRadius + 'px' }"
@click="emit('go', 'tasks')"
>
<span class="shrink-0 rounded-lg p-2.5 bg-[var(--warning-bg)]">
<Icon icon="lucide:shield-check" class="size-24px text-[--warning-color]" />
</span>
<div class="flex flex-col">
<div class="flex items-center">
<CountTo
:start-value="0"
:end-value="4"
class="text-26px font-600 text-[var(--error-color)]"
/>
<p class="text-26px font-600 text-[var(--error-color)]"> 高 /</p>
<CountTo
:start-value="0"
:end-value="11"
class="text-26px font-600 text-[var(--error-color)]"
/><p class="text-26px font-600 text-[var(--error-color)]"> 中</p>
</div>
<p class="text-[11px] font-semibold text-slate-400">变更新增风险 · 剩余高风险 1 · 剩余中风险 6</p>
</div>
</div>
</NGi>
<NGi>
<div
class="h-100% flex-1 flex items-center gap-3 bg-white px-16px py-12px cursor-pointer transition hover:-translate-y-1"
:style="{ borderRadius: themeStore.themeRadius + 'px' }"
@click="emit('go', 'tasks')"
>
<span class="shrink-0 rounded-lg p-2.5 bg-[var(--success-bg)]">
<Icon icon="material-symbols:check-circle-outline" class="size-24px text-[--success-color]" />
</span>
<div class="flex flex-col">
<CountTo
:start-value="0"
:end-value="86.4"
class="text-26px font-600"
/>
<p class="text-[11px] font-semibold text-slate-400">验收投入合计 · 已验收 19 起 · 完全达标率 68%</p>
</div>
</div>
</NGi>
</NGrid>
<NGrid
:x-gap="gap" :y-gap="16" responsive="screen" item-responsive
:style="{
'--theme-color':themeStore.themeColor
}"
>
<NGi span="24 s:24 m:24 l:14">
<NCard :bordered="false" size="small" :style="{ borderRadius: themeStore.themeRadius + 'px', height: '100%' }">
<div class="flex items-center mb-3 gap-2">
<Icon icon="akar-icons:file" class="size-16px text-[--theme-color]" />
<p class="text-13px font-700 text-#64749a">各车间变更数量</p>
<p class="text-11px text-#94a3b8 mt-2px">{{range}} · 按申请部门</p>
</div>
<ColumnChart :data="changeData" style="height: 100%;" />
</NCard>
</NGi>
<NGi span="24 s:24 m:24 l:10">
<NCard :bordered="false" size="small" :style="{ borderRadius: themeStore.themeRadius + 'px', height: '100%' }">
<div class="flex items-center mb-3 gap-2">
<Icon icon="akar-icons:file" class="size-16px text-[--theme-color]" />
<p class="text-13px font-700 text-#64749a">变更类型分布</p>
<p class="text-11px text-#94a3b8 mt-2px">{{range}} · 工艺 / 设备 / 管理</p>
</div>
<RingChart :data="DEPT_ACCEPT" :colors="ACCEPT_COLORS" :range="range" />
</NCard>
</NGi>
</NGrid>
<NGrid
:x-gap="gap" :y-gap="16" responsive="screen" item-responsive
:style="{
'--error-color':themeStore.otherColor.error,
'--warning-color':themeStore.otherColor.warning,
'--success-color':themeStore.otherColor.success,
'--theme-color':themeStore.themeColor
}"
>
<NGi span="24 s:24 m:24 l:10">
<NCard :bordered="false" size="small" :style="{ borderRadius: themeStore.themeRadius + 'px', height: '100%' }">
<div class="flex items-center mb-3 gap-2">
<Icon icon="lucide:shield-alert" class="size-16px text-[--theme-color]" />
<p class="text-13px font-700 text-#64749a">风险增量与管控</p>
<p class="text-11px text-#94a3b8 mt-2px">{{range}} · 变更新增风险与管控落实</p>
</div>
<div class="space-y-2.5">
<div class="grid grid-cols-2 gap-2">
<div class="rounded-lg bg-red-50 px-3 py-2">
<div class="text-[11px] text-[var(--error-color)]">新增固有高风险项</div>
<div class="text-xl font-bold text-[var(--error-color)]">4</div>
</div>
<div class="rounded-lg bg-amber-50 px-3 py-2">
<div class="text-[11px] text-[var(--warning-color)]">新增中风险项</div>
<div class="text-xl font-bold text-[var(--warning-color)]">11</div>
</div>
<div class="rounded-lg bg-slate-50 px-3 py-2">
<div class="text-[11px] text-slate-500">剩余高风险项</div>
<div class="text-xl font-bold text-slate-800">1</div>
</div>
<div class="rounded-lg bg-slate-50 px-3 py-2">
<div class="text-[11px] text-slate-500">剩余中风险项</div>
<div class="text-xl font-bold text-slate-800">6</div>
</div>
</div>
<div>
<div class="flex justify-between text-[11px] text-slate-500">
<span>管控措施落实率</span>
<span class="font-semibold text-[var(--success-color)]">96%</span>
</div>
<div class="mt-1 h-2 w-full rounded-full bg-slate-100">
<div class="h-2 rounded-full bg-[var(--success-color)]" style="width: 96%" />
</div>
</div>
<div v-if="residualHigh.id" @click="emit('openChange', residualHigh)"
class="cursor-pointer w-full rounded-lg border border-red-100 bg-[#FFF2F0] px-3 py-2 text-left transition hover:border-red-300">
<span class="block text-[11px] font-medium text-[var(--error-color)]">剩余高风险 · 措施落实中</span>
<span class="mt-0.5 block truncate text-xs font-medium text-slate-800">{{ residualHigh.title }}</span>
<span class="mt-0.5 block text-[11px] text-slate-400">{{ residualHigh.id }} · 电机吊装作业管控措施执行跟踪</span>
</div>
</div>
</NCard>
</NGi>
<NGi span="24 s:24 m:24 l:14">
<NCard :bordered="false" size="small" :style="{ borderRadius: themeStore.themeRadius + 'px', height: '100%' }">
<div class="flex items-center mb-3 gap-2">
<Icon icon="material-symbols:check-circle-outline" class="size-16px text-[--theme-color]" />
<p class="text-13px font-700 text-#64749a">变更投入和效果</p>
<p class="text-11px text-#94a3b8 mt-2px">{{range}} · 支持查询验收明细</p>
</div>
<RingChart2 :data="DEPT_ACCEPT2" :colors="ACCEPT_COLORS2" style="height: 210px;" />
<div class="flex items-center justify-between border-slate-200 pt-1.5">
<span class="text-[11px] text-slate-400">投入合计(变更材料和实施费) · 完全达到率 68%</span>
<span class="text-xs font-bold text-[var(--theme-color)]">86.4 万元</span>
</div>
<div @click="emit('go', 'invest')"
class="cursor-pointer mt-3 flex w-full items-center justify-center gap-1 rounded-lg border border-dashed py-2 text-[11px] text-slate-400 transition hover:border-[#6E93C6] hover:text-[#1D4E9C]">
验收明细(名称 / 日期链 / 费用 / 结论)见左边栏「变更效果跟踪」<ChevronRight class="h-3 w-3" />
</div>
</NCard>
</NGi>
</NGrid>
</NSpace>
</template>
<style scoped></style>