质量会签统计静态页面完成
This commit is contained in:
@@ -251,7 +251,8 @@ const local: App.I18n.Schema = {
|
|||||||
home_effect: '变更投入和效果',
|
home_effect: '变更投入和效果',
|
||||||
home_datachangecenter: '变更数据中心',
|
home_datachangecenter: '变更数据中心',
|
||||||
home_closeconfirm: '关闭确认',
|
home_closeconfirm: '关闭确认',
|
||||||
report: '统计报表'
|
report: '统计报表',
|
||||||
|
signstatistics: '质量会签统计'
|
||||||
},
|
},
|
||||||
form: {
|
form: {
|
||||||
required: '不能为空',
|
required: '不能为空',
|
||||||
|
|||||||
@@ -40,6 +40,7 @@ export const views: Record<LastLevelRouteKey, RouteComponent | (() => Promise<Ro
|
|||||||
login: () => import("@/views/login/index.vue"),
|
login: () => import("@/views/login/index.vue"),
|
||||||
report: () => import("@/views/report/index.vue"),
|
report: () => import("@/views/report/index.vue"),
|
||||||
riskstatistics: () => import("@/views/riskStatistics/index.vue"),
|
riskstatistics: () => import("@/views/riskStatistics/index.vue"),
|
||||||
|
signstatistics: () => import("@/views/signStatistics/index.vue"),
|
||||||
systemmanage_role: () => import("@/views/systemManage/role/index.vue"),
|
systemmanage_role: () => import("@/views/systemManage/role/index.vue"),
|
||||||
systemmanage_template: () => import("@/views/systemManage/template/index.vue"),
|
systemmanage_template: () => import("@/views/systemManage/template/index.vue"),
|
||||||
systemmanage_user: () => import("@/views/systemManage/user/index.vue"),
|
systemmanage_user: () => import("@/views/systemManage/user/index.vue"),
|
||||||
|
|||||||
@@ -319,6 +319,17 @@ export const generatedRoutes: GeneratedRoute[] = [
|
|||||||
order: 3
|
order: 3
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: 'signstatistics',
|
||||||
|
path: '/signstatistics',
|
||||||
|
component: 'layout.base$view.signstatistics',
|
||||||
|
meta: {
|
||||||
|
title: 'signstatistics',
|
||||||
|
i18nKey: 'route.signstatistics',
|
||||||
|
icon: 'ix:barchart',
|
||||||
|
order: 3
|
||||||
|
}
|
||||||
|
},
|
||||||
{
|
{
|
||||||
name: 'systemmanage',
|
name: 'systemmanage',
|
||||||
path: '/systemmanage',
|
path: '/systemmanage',
|
||||||
|
|||||||
@@ -191,6 +191,7 @@ const routeMap: RouteMap = {
|
|||||||
"login": "/login/:module(pwd-login)?",
|
"login": "/login/:module(pwd-login)?",
|
||||||
"report": "/report",
|
"report": "/report",
|
||||||
"riskstatistics": "/riskstatistics",
|
"riskstatistics": "/riskstatistics",
|
||||||
|
"signstatistics": "/signstatistics",
|
||||||
"systemmanage": "/systemmanage",
|
"systemmanage": "/systemmanage",
|
||||||
"systemmanage_role": "/systemmanage/role",
|
"systemmanage_role": "/systemmanage/role",
|
||||||
"systemmanage_template": "/systemmanage/template",
|
"systemmanage_template": "/systemmanage/template",
|
||||||
|
|||||||
Vendored
+3
@@ -45,6 +45,7 @@ declare module "@elegant-router/types" {
|
|||||||
"login": "/login/:module(pwd-login)?";
|
"login": "/login/:module(pwd-login)?";
|
||||||
"report": "/report";
|
"report": "/report";
|
||||||
"riskstatistics": "/riskstatistics";
|
"riskstatistics": "/riskstatistics";
|
||||||
|
"signstatistics": "/signstatistics";
|
||||||
"systemmanage": "/systemmanage";
|
"systemmanage": "/systemmanage";
|
||||||
"systemmanage_role": "/systemmanage/role";
|
"systemmanage_role": "/systemmanage/role";
|
||||||
"systemmanage_template": "/systemmanage/template";
|
"systemmanage_template": "/systemmanage/template";
|
||||||
@@ -90,6 +91,7 @@ declare module "@elegant-router/types" {
|
|||||||
| "login"
|
| "login"
|
||||||
| "report"
|
| "report"
|
||||||
| "riskstatistics"
|
| "riskstatistics"
|
||||||
|
| "signstatistics"
|
||||||
| "systemmanage"
|
| "systemmanage"
|
||||||
>;
|
>;
|
||||||
|
|
||||||
@@ -132,6 +134,7 @@ declare module "@elegant-router/types" {
|
|||||||
| "login"
|
| "login"
|
||||||
| "report"
|
| "report"
|
||||||
| "riskstatistics"
|
| "riskstatistics"
|
||||||
|
| "signstatistics"
|
||||||
| "systemmanage_role"
|
| "systemmanage_role"
|
||||||
| "systemmanage_template"
|
| "systemmanage_template"
|
||||||
| "systemmanage_user"
|
| "systemmanage_user"
|
||||||
|
|||||||
@@ -0,0 +1,189 @@
|
|||||||
|
<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 RingChart from './modules/ringChart.vue';
|
||||||
|
|
||||||
|
const appStore = useAppStore();
|
||||||
|
const themeStore = useThemeStore();
|
||||||
|
const gap = computed(() => (appStore.isMobile ? 0 : 16));
|
||||||
|
|
||||||
|
const profEff = ref<{d: string, days: number, me?: boolean, target?: boolean}[]>([
|
||||||
|
{ d: `陈质量(本人)`, days: 1.8, me: true },
|
||||||
|
{ d: "仪表专业均值", days: 2.1, me: false },
|
||||||
|
{ d: "设备专业均值", days: 2.2, me: false },
|
||||||
|
{ d: "工艺专业均值", days: 2.6, me: false },
|
||||||
|
{ d: "考核目标", days: 2.5, me: false, target: true },
|
||||||
|
]);
|
||||||
|
const DEPT_ACCEPT = [
|
||||||
|
{ name: "工艺", value: 52 },
|
||||||
|
{ name: "设备", value: 49 },
|
||||||
|
{ name: "管理", value: 25 },
|
||||||
|
];
|
||||||
|
const ACCEPT_COLORS = ["#2080f0", "#7CC242", "#F5A623"];
|
||||||
|
|
||||||
|
const profHighRisk = [
|
||||||
|
{ id: "MOC-2026-R01-0035", status: '审批中', title: 'R-201 反应釜搅拌器电机更换(55kW→75kW 防爆电机)' },
|
||||||
|
{ id: "MOC-2026-R01-0036", status: '审批中', title: '聚合反应温度控制上限调整(78℃→82℃)' },
|
||||||
|
{ id: "MOC-2026-R01-0037", status: '实施中', title: '原料环己烷供应商变更(新增 B 供应商)' },
|
||||||
|
];
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<NSpace vertical :size="16">
|
||||||
|
<!-- 卡片数据 -->
|
||||||
|
<NGrid cols="s:1 m:5 l:5" responsive="screen" :x-gap="gap" :y-gap="16"
|
||||||
|
:style="{
|
||||||
|
'--theme-color': themeStore.themeColor,
|
||||||
|
'--success-color': themeStore.otherColor.success,
|
||||||
|
'--warning-color': themeStore.otherColor.warning,
|
||||||
|
}"
|
||||||
|
>
|
||||||
|
<NGi>
|
||||||
|
<div
|
||||||
|
class="flex-1 bg-white px-16px py-12px text-[#94a3b8]"
|
||||||
|
:style="{ borderRadius: themeStore.themeRadius + 'px', height: '100%' }"
|
||||||
|
>
|
||||||
|
<p class="text-12px font-600">本月会签 / 审批</p>
|
||||||
|
<div class="flex items-center">
|
||||||
|
<CountTo
|
||||||
|
:start-value="0"
|
||||||
|
:end-value="6"
|
||||||
|
class="text-24px font-600 text-[#333]"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<p class="text-12px">口径:节点签出记录</p>
|
||||||
|
</div>
|
||||||
|
</NGi>
|
||||||
|
<NGi>
|
||||||
|
<div
|
||||||
|
class="flex-1 bg-white px-16px py-12px text-[#94a3b8]"
|
||||||
|
:style="{ borderRadius: themeStore.themeRadius + 'px', height: '100%' }"
|
||||||
|
>
|
||||||
|
<p class="text-12px font-600">我的会签平均耗时</p>
|
||||||
|
<div class="flex items-center">
|
||||||
|
<CountTo
|
||||||
|
:start-value="0"
|
||||||
|
:end-value="1.8"
|
||||||
|
:decimals="1"
|
||||||
|
class="text-26px font-600 text-[var(--success-color)]"
|
||||||
|
/><p class="text-26px font-600 text-[var(--success-color)]">天</p>
|
||||||
|
</div>
|
||||||
|
<p class="text-12px">口径:签收→签出时长 · 目标 ≤2.5 天</p>
|
||||||
|
</div>
|
||||||
|
</NGi>
|
||||||
|
<NGi>
|
||||||
|
<div
|
||||||
|
class="flex-1 bg-white px-16px py-12px text-[#94a3b8]"
|
||||||
|
:style="{ borderRadius: themeStore.themeRadius + 'px', height: '100%' }"
|
||||||
|
>
|
||||||
|
<p class="text-12px font-600">按时完成率</p>
|
||||||
|
<div class="flex items-center">
|
||||||
|
<CountTo
|
||||||
|
:start-value="0"
|
||||||
|
:end-value="95"
|
||||||
|
class="text-26px font-600 text-[var(--success-color)]"
|
||||||
|
/><p class="text-26px font-600 text-[var(--success-color)]">%</p>
|
||||||
|
</div>
|
||||||
|
<p class="text-12px">考核:目标 ≥90%</p>
|
||||||
|
</div>
|
||||||
|
</NGi>
|
||||||
|
<NGi>
|
||||||
|
<div
|
||||||
|
class="flex-1 bg-white px-16px py-12px text-[#94a3b8]"
|
||||||
|
:style="{ borderRadius: themeStore.themeRadius + 'px', height: '100%' }"
|
||||||
|
>
|
||||||
|
<p class="text-12px font-600">参与风险分析</p>
|
||||||
|
<div class="flex items-center">
|
||||||
|
<CountTo
|
||||||
|
:start-value="0"
|
||||||
|
:end-value="2"
|
||||||
|
class="text-26px font-600 text-[var(--theme-color)]"
|
||||||
|
/><p class="text-26px font-600 text-[var(--theme-color)]">次</p>
|
||||||
|
</div>
|
||||||
|
<p class="text-12px">口径:HAZOP / JSA 分析组成员(选择式)记录</p>
|
||||||
|
</div>
|
||||||
|
</NGi>
|
||||||
|
<NGi>
|
||||||
|
<div
|
||||||
|
class="flex-1 bg-white px-16px py-12px text-[#94a3b8]"
|
||||||
|
:style="{ borderRadius: themeStore.themeRadius + 'px', height: '100%' }"
|
||||||
|
>
|
||||||
|
<p class="text-12px font-600">当前待我审批</p>
|
||||||
|
<div class="flex items-center">
|
||||||
|
<CountTo
|
||||||
|
:start-value="0"
|
||||||
|
:end-value="1"
|
||||||
|
class="text-26px font-600 text-[var(--warning-color)]"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<p class="text-12px">实时 · 与工作台同源</p>
|
||||||
|
</div>
|
||||||
|
</NGi>
|
||||||
|
</NGrid>
|
||||||
|
|
||||||
|
<NGrid :x-gap="gap" :y-gap="16" responsive="screen" item-responsive>
|
||||||
|
<NGi span="24 s:24 m:24 l:8">
|
||||||
|
<NCard :bordered="true" size="small" :content-style="{padding: 0}"
|
||||||
|
:style="{
|
||||||
|
borderRadius: themeStore.themeRadius + 'px',
|
||||||
|
height: '100%',
|
||||||
|
'--theme-color': themeStore.themeColor,
|
||||||
|
'--error-color': themeStore.otherColor.error,
|
||||||
|
'--warning-color': themeStore.otherColor.warning,
|
||||||
|
'--success-color': themeStore.otherColor.success,
|
||||||
|
'--error-bg': getColorWithOpacity(themeStore.otherColor.error,0.1),
|
||||||
|
'--warning-bg': getColorWithOpacity(themeStore.otherColor.warning,0.1),
|
||||||
|
'--theme-bg': getColorWithOpacity(themeStore.themeColor,0.1),
|
||||||
|
}"
|
||||||
|
>
|
||||||
|
<p class=" text-base font-semibold border-b border-slate-100 p-3">会签效率对比(考核 · 汇报)</p>
|
||||||
|
<div class="py-3 px-4">
|
||||||
|
<div class="space-y-3">
|
||||||
|
<div v-for="e in profEff" :key="e.d">
|
||||||
|
<div class="mb-1 flex items-center justify-between text-xs">
|
||||||
|
<span :class="e.me ? 'font-semibold text-[var(--theme-color)]' : 'text-slate-600'">{{ e.d }}</span>
|
||||||
|
<span :class="e.target ? 'text-slate-400' : e.days > 2.5 ? 'font-medium text-[var(--error-color)]' : 'text-slate-500'">{{ e.days }} 天{{ e.target ? "(标线)" : "" }}</span>
|
||||||
|
</div>
|
||||||
|
<div class="h-2 overflow-hidden rounded-full bg-slate-100">
|
||||||
|
<div class="h-full rounded-full" :class="e.target ? 'bg-slate-300' : e.me ? 'bg-[var(--theme-color)]' : e.days > 2.5 ? 'bg-[var(--error-color)]' : 'bg-[#6E93C6]'" :style="{ width: `${Math.min(100, (e.days / 4) * 100)}%` }" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<p class="text-[11px] text-slate-400">考核数据来源:节点签收 → 签出时长自动统计;连续两月超标将纳入绩效面谈</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</NCard>
|
||||||
|
</NGi>
|
||||||
|
<NGi span="24 s:24 m:24 l:8">
|
||||||
|
<NCard :bordered="true" size="small" :content-style="{padding: 0}" :style="{ borderRadius: themeStore.themeRadius + 'px', height: '100%' }">
|
||||||
|
<p class=" text-base font-semibold border-b border-slate-100 p-3">本专业变更类型分布(近一年)</p>
|
||||||
|
<div class="py-3 px-4">
|
||||||
|
<RingChart :data="DEPT_ACCEPT" :colors="ACCEPT_COLORS" />
|
||||||
|
</div>
|
||||||
|
</NCard>
|
||||||
|
</NGi>
|
||||||
|
<NGi span="24 s:24 m:24 l:8">
|
||||||
|
<NCard :bordered="true" size="small" :content-style="{padding: 0}" :style="{ borderRadius: themeStore.themeRadius + 'px', height: '100%' }">
|
||||||
|
<p class=" text-base font-semibold border-b border-slate-100 p-3">本专业高风险在办(直达风险分析)</p>
|
||||||
|
<div class="py-3 px-4">
|
||||||
|
<div class="space-y-2 pt-1">
|
||||||
|
<div v-for="c in profHighRisk" :key="c.id" @click="emit('go', 'risk')" class="cursor-pointer flex w-full items-center gap-2 rounded-lg border px-3 py-2 text-left hover:border-red-300 hover:bg-red-50/30">
|
||||||
|
<span class="min-w-0 flex-1">
|
||||||
|
<span class="block truncate text-sm font-medium text-slate-800">{{ c.title }}</span>
|
||||||
|
<span class="text-[11px] text-slate-400">{{ c.id }} · {{ c.status }}</span>
|
||||||
|
</span>
|
||||||
|
<ChevronRight class="h-3.5 w-3.5 shrink-0 text-slate-300" />
|
||||||
|
</div>
|
||||||
|
<p class="text-[11px] text-slate-400">更多高风险场景与分析记录见「本专业高风险」页</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</NCard>
|
||||||
|
</NGi>
|
||||||
|
</NGrid>
|
||||||
|
</NSpace>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style scoped></style>
|
||||||
@@ -0,0 +1,88 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
import { ref } from 'vue';
|
||||||
|
import { useEcharts } from '@/hooks/common/echarts';
|
||||||
|
|
||||||
|
defineOptions({
|
||||||
|
name: 'RingChart'
|
||||||
|
});
|
||||||
|
|
||||||
|
const props = defineProps<{ data?: { name: string; value: number }[]; colors?: string[] }>();
|
||||||
|
|
||||||
|
const { domRef, updateOptions } = useEcharts(() => ({
|
||||||
|
tooltip: {
|
||||||
|
trigger: 'item',
|
||||||
|
formatter: '{b}: {c} ({d}%)'
|
||||||
|
},
|
||||||
|
legend: {
|
||||||
|
bottom: 0,
|
||||||
|
left: 'center',
|
||||||
|
icon: 'circle',
|
||||||
|
itemWidth: 10,
|
||||||
|
itemHeight: 10,
|
||||||
|
itemStyle: {
|
||||||
|
borderWidth: 0
|
||||||
|
},
|
||||||
|
},
|
||||||
|
title: {
|
||||||
|
text: `{a|39}\n{b|本专业变更}`,
|
||||||
|
textStyle: {
|
||||||
|
rich: {
|
||||||
|
a: {
|
||||||
|
fontSize: 24,
|
||||||
|
color: '#333',
|
||||||
|
fontWeight: 800,
|
||||||
|
align: 'center',
|
||||||
|
verticalAlign: 'middle',
|
||||||
|
},
|
||||||
|
b: {
|
||||||
|
fontSize: 12,
|
||||||
|
color: '#999',
|
||||||
|
align: 'center',
|
||||||
|
verticalAlign: 'middle',
|
||||||
|
fontWeight: 500,
|
||||||
|
padding: [5, 0, 0, 0]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
left: 'center',
|
||||||
|
top: '35%',
|
||||||
|
},
|
||||||
|
series: [
|
||||||
|
{
|
||||||
|
type: 'pie',
|
||||||
|
color: ['#5da8ff', '#8e9dff', '#fedc69', '#26deca'],
|
||||||
|
radius: ['45%', '65%'],
|
||||||
|
center: ['50%', '45%'],
|
||||||
|
avoidLabelOverlap: false,
|
||||||
|
label: {
|
||||||
|
show: false,
|
||||||
|
position: 'outside',
|
||||||
|
formatter: '{b}\n{c} ({d}%)',
|
||||||
|
fontSize: 12,
|
||||||
|
},
|
||||||
|
labelLine: {
|
||||||
|
show: true,
|
||||||
|
length: 10,
|
||||||
|
length2: 10
|
||||||
|
},
|
||||||
|
data: [] as { name: string; value: number }[]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}));
|
||||||
|
|
||||||
|
function init() {
|
||||||
|
updateOptions(opts => {
|
||||||
|
opts.series[0].data = props.data || [];
|
||||||
|
opts.series[0].color = props.colors || [];
|
||||||
|
return opts;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
init();
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div ref="domRef" class="w-full h-220px overflow-hidden"></div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style scoped></style>
|
||||||
Reference in New Issue
Block a user