本专业变更统计-数据统计字段修改

This commit is contained in:
2026-09-30 13:32:00 +08:00
parent 253df87b31
commit 8206121d46
5 changed files with 369 additions and 722 deletions
-1
View File
@@ -53,7 +53,6 @@ const getData = async () => {
loading.value = true;
const {data,error} = await homeNonApproverApi();
if(!error){
console.log(data)
homeData.value = data;
}
loading.value = false;
+31 -22
View File
@@ -10,12 +10,6 @@ import { specialtyStatisticsApi } from '@/service/api/statistics';
const themeStore = useThemeStore();
const { routerPushByKey } = useRouterPush();
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 供应商)' },
];
const loading = ref<boolean>(false);
const homeData = ref<any>(null);
@@ -23,6 +17,10 @@ const homeData = ref<any>(null);
const jumpTo = (key: string) => {
routerPushByKey(key as any);
}
// 小时转换天
const hourToDay = (hour: number) => {
return Math.trunc((hour / 24) * 100) / 100;
}
// 获取数据
const getData = async () => {
@@ -33,7 +31,6 @@ const getData = async () => {
});
if(!error){
homeData.value = data;
console.log(data);
}
loading.value = false;
}
@@ -44,7 +41,8 @@ onMounted(() => {
</script>
<template>
<NSpace vertical :size="16">
<NSpin :show="loading" size="small">
<NSpace vertical :size="16">
<!-- 卡片数据 -->
<NGrid cols="s:1 m:5 l:5" responsive="screen" :x-gap="16" :y-gap="16"
:style="{
@@ -62,7 +60,7 @@ onMounted(() => {
<div class="flex items-center">
<CountTo
:start-value="0"
:end-value="6"
:end-value="homeData?.my_stats?.month_signed || 0"
class="text-24px font-600 text-[#333]"
/>
</div>
@@ -78,12 +76,12 @@ onMounted(() => {
<div class="flex items-center">
<CountTo
:start-value="0"
:end-value="1.8"
:end-value="homeData?.my_stats?.avg_audit_days || 0"
: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>
<p class="text-12px">口径:签收→签出时长 · 目标 ≤{{hourToDay(homeData?.my_stats?.sign_timely_hours || 0)}} 天</p>
</div>
</NGi>
<NGi>
@@ -95,7 +93,7 @@ onMounted(() => {
<div class="flex items-center">
<CountTo
:start-value="0"
:end-value="95"
:end-value="homeData?.my_stats?.timely_rate || 0"
class="text-26px font-600 text-[var(--success-color)]"
/><p class="text-26px font-600 text-[var(--success-color)]">%</p>
</div>
@@ -111,7 +109,7 @@ onMounted(() => {
<div class="flex items-center">
<CountTo
:start-value="0"
:end-value="2"
:end-value="homeData?.my_stats?.risk_analysis_count || 0"
class="text-26px font-600 text-[var(--theme-color)]"
/><p class="text-26px font-600 text-[var(--theme-color)]">次</p>
</div>
@@ -127,7 +125,7 @@ onMounted(() => {
<div class="flex items-center">
<CountTo
:start-value="0"
:end-value="1"
:end-value="homeData?.my_stats?.todo_total || 0"
class="text-26px font-600 text-[var(--warning-color)]"
/>
</div>
@@ -160,17 +158,17 @@ onMounted(() => {
<span :class="e.avg_days > 2.5 ? 'font-medium text-[var(--error-color)]' : 'text-slate-500'">{{ e.avg_days }} 天</span>
</div>
<div class="h-2 overflow-hidden rounded-full bg-slate-100">
<div class="h-full rounded-full" :class="e.avg_days > 2.5 ? 'bg-[var(--error-color)]' : 'bg-[var(--theme-color)]'" :style="{ width: `${Math.min(100, (e.avg_days / e.total) * 100)}%` }"></div>
<div class="h-full rounded-full" :class="e.avg_days > hourToDay(homeData?.my_stats?.sign_timely_hours || 0) ? 'bg-[var(--error-color)]' : 'bg-[var(--theme-color)]'" :style="{ width: `${Math.min(100, (e.avg_days / e.total) * 100)}%` }"></div>
</div>
</div>
<p v-if="homeData?.approver_time?.length===0" class="text-xs text-slate-400 text-center py-3">暂无数据</p>
<div>
<div class="mb-1 flex items-center justify-between text-xs">
<span class="text-slate-600">考核目标</span>
<span class="text-slate-500">2.5 天(标线)</span>
<span class="text-slate-500">{{hourToDay(homeData?.my_stats?.sign_timely_hours || 0)}} 天(标线)</span>
</div>
<div class="h-2 overflow-hidden rounded-full bg-slate-100">
<div class="h-full rounded-full bg-slate-300" :style="{ width: `${Math.min(100, (2.5 / 2.5) * 100)}%` }"></div>
<div class="h-full rounded-full bg-slate-300" :style="{ width: `${Math.min(100, (hourToDay(homeData?.my_stats?.sign_timely_hours || 0) / hourToDay(homeData?.my_stats?.sign_timely_hours || 0)) * 100)}%` }"></div>
</div>
</div>
<p class="text-[11px] text-slate-400">考核数据来源:节点签收 → 签出时长自动统计;连续两月超标将纳入绩效面谈</p>
@@ -190,11 +188,21 @@ onMounted(() => {
<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 v-if="profHighRisk.length" class="space-y-2 pt-1">
<div v-for="c in profHighRisk" :key="c.id" @click="jumpTo('my_highrisk')" 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">
<div v-if="homeData?.high_risk?.total > 0" class="space-y-2 pt-1">
<div v-for="c in homeData?.high_risk?.items || []" :key="c.id" @click="jumpTo('my_highrisk')" 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 class="block truncate text-sm font-medium text-slate-800">{{ c.change_title }}</span>
<div class="flex items-center gap-2 text-[11px] text-slate-400 mt-1">
<span>{{ c.change_no }}</span>
<!-- 状态标签 -->
<span v-if="c.change_status==='APPROVING'">审批中</span>
<span v-if="c.change_status==='APPROVED'">已通过</span>
<span v-if="c.change_status==='IMPLEMENTED'">待验收</span>
<span v-if="c.change_status==='ACCEPTED'">待关闭</span>
<span v-if="c.change_status==='CLOSED'">已关闭</span>
<span v-if="c.change_status==='WITHDRAWN'">已撤回</span>
<span v-if="c.change_status==='REJECTED'">已驳回</span>
</div>
</span>
<Icon icon="formkit:right" class="size-14px text-slate-300" />
</div>
@@ -205,7 +213,8 @@ onMounted(() => {
</NCard>
</NGi>
</NGrid>
</NSpace>
</NSpace>
</NSpin>
</template>
<style scoped></style>
+202 -472
View File
@@ -1,132 +1,77 @@
<script setup lang="ts">
import { ref, computed } from 'vue';
import { Icon } from '@iconify/vue'
import { ref, onMounted } from 'vue';
import { useThemeStore } from '@/store/modules/theme';
import { getColorWithOpacity } from '@/utils/common';
import RingChart from './modules/ringChart.vue';
import ColumnChart from './modules/columnChart.vue';
import { systemConfigApi } from "@/service/api/system";
import { deptStatisticsApi } from '@/service/api/statistics';
const themeStore = useThemeStore();
const P_PERIODS = ["近一个月", "近三个月", "近半年", "近一年"];
const period = ref<(typeof P_PERIODS)[number]>("近一年");
const DEPT_ACCEPT = [
{ name: "工艺", value: 52 },
{ name: "设备", value: 49 },
{ name: "管理", value: 25 },
];
const ACCEPT_COLORS = ["#2080f0", "#7CC242", "#F5A623"];
const changeData = ref([
{
name: '一车间',
value: 42,
},
{
name: '二车间',
value: 35,
},
{
name: '三车间',
value: 28,
},
{
name: '供应部',
value: 12,
},
{
name: '质量部',
value: 9,
},
]);
const ADM_ACCEPT_DETAIL = [
{ id: "MOC-2026-R01-0028", title: "成品包装规格调整", dept: "一车间", applyDate: "2026-02-20", useTime: "2026-03-15", acceptDate: "2026-04-10", cost: 3.2, result: "完全达到" },
{ id: "MOC-2026-R01-0019", title: "R-201 搅拌密封改造", dept: "一车间", applyDate: "2026-03-18", useTime: "2026-04-12", acceptDate: "2026-05-20", cost: 6.8, result: "完全达到" },
{ id: "MOC-2026-R01-0022", title: "循环水加药泵冲程临时调整", dept: "一车间", applyDate: "2026-04-25", useTime: "2026-05-18", acceptDate: "2026-06-30", cost: 1.5, result: "基本达到" },
{ id: "MOC-2026-R02-0031", title: "冷冻盐水泵 P-103 叶轮材质变更", dept: "二车间", applyDate: "2026-06-30", useTime: "2026-07-24", acceptDate: "2026-08-02", cost: 4.6, result: "基本达到" },
{ id: "MOC-2026-R03-0040", title: "原料环己烷供应商变更", dept: "供应部", applyDate: "2026-07-10", useTime: "2026-08-01", acceptDate: "2026-08-04", cost: 2.1, result: "完全达到" },
];
const admOpenStages = ref<{ name: string, n: number }[]>([
{ name: "审批中(含会签)", n: 5 },
{ name: "已批准待投用", n: 2 },
{ name: "待验收", n: 0 },
{ name: "待关闭", n: 1 },
]);
const loading = ref<boolean>(false);
// 变更临期天数
const remindDays = ref<number>(0);
const homeData = ref<any>(null);
const EFFICIENCY_DATA = [
{ d: "一车间", days: 6.2 }, { d: "二车间", days: 7.8 }, { d: "三车间", days: 9.4 }, { d: "供应部", days: 5.1 },
];
const ADM_PERSON_EFF = [
{ p: "李主任", node: "部门审核", avg: 1.2, max: 2.5, onTime: 96 },
{ p: "王仪表", node: "专业会签(仪表)", avg: 1.8, max: 3.0, onTime: 92 },
{ p: "周设备", node: "专业会签(设备)", avg: 2.6, max: 4.1, onTime: 85 },
{ p: "陈质量", node: "质量会签", avg: 1.6, max: 2.4, onTime: 95 },
{ p: "王海燕", node: "安全审查", avg: 2.1, max: 3.5, onTime: 90 },
{ p: "刘副总", node: "最终批准", avg: 1.5, max: 2.8, onTime: 94 },
];
const ADM_TEMP_DISP = [
{ name: "到期恢复", value: 8, c: "#1D4E9C", note: "恢复原状并验收关闭" },
{ name: "办理延期", value: 5, c: "#F5A623", note: "均符合「至多延期 1 次」" },
{ name: "转为永久", value: 2, c: "#7CC242", note: "补办永久变更审批" },
{ name: "超期未处理", value: 3, c: "#E15555", note: "系统已推送超期提醒至申请人" },
];
const ADM_REJECT_REASONS = [
{ reason: "变更前后对比描述不完整 / 缺少核算数据", n: 4 },
{ reason: "风险分析覆盖不足(情景缺失)", n: 3 },
{ reason: "连带变更识别遗漏", n: 3 },
{ reason: "所需材料不齐全", n: 2 },
{ reason: "变更等级判定偏低", n: 2 },
];
const ADM_ARCHIVE_GAP = [
{ item: "培训签到表", n: 3 }, { item: "PSSR 确认表", n: 2 }, { item: "变更验收单", n: 1 },
];
const ADM_ARCHIVE_TAGS = [
{ k: "资料齐全", n: 76, c: "border-emerald-200 bg-emerald-50 text-emerald-700" },
{ k: "缺培训签到", n: 3, c: "border-amber-200 bg-amber-50 text-amber-700" },
{ k: "缺PSSR表", n: 2, c: "border-amber-200 bg-amber-50 text-amber-700" },
{ k: "缺验收单", n: 1, c: "border-red-200 bg-red-50 text-red-700" },
];
// 获取数据
const getData = async () => {
loading.value = true;
const {data,error} = await deptStatisticsApi({
from: null,
to: null,
});
if(!error){
homeData.value = data;
console.log(data);
}
loading.value = false;
}
// 获取系统配置
const getConfig = async () => {
const {data,error} = await systemConfigApi();
if(!error){
// 解析 临时变更临期提醒
const remindDaysGroup = data.find((group:{group_key:string}) => group.group_key === 'change_remind');
if (remindDaysGroup) {
remindDaysGroup?.items.forEach((item:any) => {
if(item.item_key === 'temp_due_remind_days'){
remindDays.value = Number(item.value);
}
})
}
}
}
onMounted(() => {
getConfig();
getData();
});
</script>
<template>
<NSpace vertical :size="16">
<!-- 统计报表 -->
<NCard :bordered="false" size="small" :style="{borderRadius: themeStore.themeRadius + 'px'}">
<div class="flex flex-wrap items-center justify-between">
<div class="flex items-center gap-1.5 text-sm font-semibold text-slate-700">
<span>统计中心</span>
<span class="text-xs font-normal text-slate-400">变更归口管理视角 · 全厂口径</span>
</div>
<div class="flex flex-wrap items-center gap-1.5 min-h-28px">
<NButton size="tiny" round v-for="p in P_PERIODS" :key="p" @click="period = p"
:ghost="period === p ? false : true"
:type="period === p ? 'primary' : 'default'"
>{{ p }}</NButton>
<NButton size="small" class="text-xs ml-1">
<Icon icon="material-symbols:download" class="size-14px mr-1" />导出
</NButton>
</div>
</div>
</NCard>
<!-- 卡片数据 -->
<NGrid cols="s:1 m:4 l:4" responsive="screen" :x-gap="16" :y-gap="16" :style="{'--theme-color': themeStore.themeColor}">
<NGrid cols="s:1 m:4 l:4" responsive="screen" :x-gap="16" :y-gap="16">
<NGi>
<div
class="flex-1 bg-white px-16px py-12px text-[#94a3b8]"
:style="{ borderRadius: themeStore.themeRadius + 'px' }"
>
<p class="text-12px font-600">变更总数</p>
<p class="text-12px font-600">本车间变更总数</p>
<div class="flex items-center">
<CountTo
:start-value="0"
:end-value="126"
class="text-24px font-600 text-[var(--theme-color)]"
class="text-24px font-600 text-slate-800"
/>
</div>
<p class="text-12px">{{period}} · 全厂</p>
<p class="text-12px">近一年 · 汇报口径</p>
</div>
</NGi>
<NGi>
@@ -134,15 +79,16 @@ const ADM_ARCHIVE_TAGS = [
class="flex-1 bg-white px-16px py-12px text-[#94a3b8]"
:style="{ borderRadius: themeStore.themeRadius + 'px' }"
>
<p class="text-12px font-600">重要变更</p>
<p class="text-12px font-600">在办变更</p>
<div class="flex items-center">
<CountTo
:start-value="0"
:end-value="18"
class="text-26px font-600 text-[var(--theme-color)]"
class="text-26px font-600"
:style="{color:themeStore.themeColor}"
/>
</div>
<p class="text-12px">占比 14%</p>
<p class="text-12px">实时 · 三大阶段分布见下</p>
</div>
</NGi>
<NGi>
@@ -150,16 +96,16 @@ const ADM_ARCHIVE_TAGS = [
class="flex-1 bg-white px-16px py-12px text-[#94a3b8]"
:style="{ borderRadius: themeStore.themeRadius + 'px' }"
>
<p class="text-12px font-600">变更费用合计</p>
<p class="text-12px font-600">超期未关闭</p>
<div class="flex items-center">
<CountTo
:start-value="0"
:end-value="86.4"
:decimals="1"
class="text-26px font-600 text-[var(--theme-color)]"
/><p class="text-26px font-600 text-[var(--theme-color)]">万</p>
:end-value="86"
class="text-26px font-600"
:style="{color:themeStore.otherColor.error}"
/>
</div>
<p class="text-12px">验收填报口径</p>
<p class="text-12px">管理考核一票指标</p>
</div>
</NGi>
<NGi>
@@ -167,88 +113,120 @@ const ADM_ARCHIVE_TAGS = [
class="flex-1 bg-white px-16px py-12px text-[#94a3b8]"
:style="{ borderRadius: themeStore.themeRadius + 'px' }"
>
<p class="text-12px font-600">平均审批通过时长</p>
<p class="text-12px font-600">我的审批按时率</p>
<div class="flex items-center">
<CountTo
:start-value="0"
:end-value="58"
class="text-26px font-600 text-[var(--theme-color)]"
/><p class="text-26px font-600 text-[var(--theme-color)]">%</p>
class="text-26px font-600"
:style="{color:themeStore.otherColor.success}"
/><p class="text-26px font-600" :style="{color:themeStore.otherColor.success}">%</p>
</div>
<p class="text-12px">验收结论口径</p>
<p class="text-12px">考核:目标 ≥90% · 达标</p>
</div>
</NGi>
</NGrid>
<NGrid :x-gap="16" :y-gap="16" responsive="screen" item-responsive>
<NGi span="24 s:24 m:24 l:14">
<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">各车间变更数量({{period}})</p>
<div class="py-3 px-4">
<ColumnChart :data="changeData" style="height: 220px" />
</div>
</NCard>
</NGi>
<NGi span="24 s:24 m:24 l:10">
<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">变更类型分布({{period}})</p>
<div class="py-3 px-4">
<RingChart :data="DEPT_ACCEPT" :colors="ACCEPT_COLORS" />
</div>
</NCard>
</NGi>
</NGrid>
<NGrid :x-gap="16" :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%' }">
<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 class="flex items-center gap-2 rounded-lg bg-slate-50 px-3 py-2.5">
<span class="min-w-0 flex-1 text-sm text-slate-700">平均审批时长</span>
<span class="text-base font-bold" :style="{color:themeStore.themeColor}">1.6 天</span>
<span class="text-[11px]" :style="{color:themeStore.otherColor.success}">目标 ≤2 天</span>
</div>
<div class="flex items-center gap-2 rounded-lg bg-slate-50 px-3 py-2.5">
<span class="min-w-0 flex-1 text-sm text-slate-700">按时审批率</span>
<span class="text-base font-bold" :style="{color:themeStore.themeColor}">92%</span>
<span class="text-[11px]" :style="{color:themeStore.otherColor.success}">目标 ≥90%</span>
</div>
<div class="flex items-center gap-2 rounded-lg bg-slate-50 px-3 py-2.5">
<span class="min-w-0 flex-1 text-sm text-slate-700">驳回补充说明率</span>
<span class="text-base font-bold" :style="{color:themeStore.themeColor}">100%</span>
<span class="text-[11px]" :style="{color:themeStore.otherColor.success}">驳回必附整改指引</span>
</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">
<div class="space-y-2.5">
<div v-for="item in homeData?.open_status_counts" :key="item.status" class="flex items-center gap-2">
<!-- 审批中 -->
<span v-if="item.status==='APPROVING'" class="h-2.5 w-2.5 shrink-0 rounded-sm" :style="{background:themeStore.otherColor.warning}"></span>
<!-- 已批准待投用 -->
<span v-if="item.status==='APPROVED'" class="h-2.5 w-2.5 shrink-0 rounded-sm" :style="{background:themeStore.themeColor}"></span>
<!-- 待验收 -->
<span v-if="item.status==='IMPLEMENTED'" class="h-2.5 w-2.5 shrink-0 rounded-sm" :style="{background:themeStore.otherColor.success}"></span>
<!-- 待关闭 -->
<span v-if="item.status==='ACCEPTED'" class="h-2.5 w-2.5 shrink-0 rounded-sm" :style="{background:themeStore.otherColor.error}"></span>
<!-- 已驳回 -->
<span v-if="item.status==='REJECTED'" class="h-2.5 w-2.5 shrink-0 rounded-sm" :style="{background:themeStore.otherColor.error}"></span>
<span class="min-w-0 flex-1 text-sm text-slate-600">{{item.label}}</span>
<span class="text-sm font-bold text-slate-800">{{item.count}}</span>
</div>
<p class="pt-1 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">
<div class="space-y-3">
<div class="rounded-lg border px-3 py-2">
<div class="flex items-center gap-2 text-xs">
<span class="h-2 w-2 rounded-full" :style="{ background: themeStore.otherColor.success }"></span>
<span class="font-medium text-slate-700">正常(到期 > {{remindDays}} 天)</span>
<span class="ml-auto font-semibold text-slate-600">{{homeData?.kpis?.unclosed_total || 0}}</span>
</div>
</div>
<div class="rounded-lg border px-3 py-2">
<div class="flex items-center gap-2 text-xs">
<span class="h-2 w-2 rounded-full" :style="{ background: themeStore.otherColor.warning }"></span>
<span class="font-medium text-slate-700">临期(到期 ≤ {{remindDays}} 天)</span>
<span class="ml-auto font-semibold text-slate-600">{{homeData?.kpis?.near_overdue_total || 0}}</span>
</div>
</div>
<div class="rounded-lg border px-3 py-2">
<div class="flex items-center gap-2 text-xs">
<span class="h-2 w-2 rounded-full" :style="{ background: themeStore.otherColor.error }"></span>
<span class="font-medium text-slate-700">已超期</span>
<span class="ml-auto font-semibold text-slate-600">{{homeData?.kpis?.overdue_total || 0}}</span>
</div>
</div>
<NButton size="small" ghost dashed block class="text-xs text-slate-400">前往变更台账查看处置 →</NButton>
</div>
</div>
</NCard>
</NGi>
</NGrid>
<NGrid :x-gap="16" :y-gap="16" responsive="screen" item-responsive>
<!-- 变更类型分布 -->
<NGi span="24 s:24 m:24 l:10">
<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">各审批人审批时长(天 · {{period}} · 系统自动采集)</p>
<div class="py-3 px-4">
<table class="w-full text-xs">
<thead>
<tr class="border-b text-left text-slate-500">
<th class="py-2 font-semibold">审批人 / 节点</th>
<th class="w-[50px] py-2 text-right font-semibold">平均时长</th>
<th class="w-[60px] py-2 text-right font-semibold">最长时长</th>
<th class="w-[130px] py-2 font-semibold">及时率(≤2天)</th>
</tr>
</thead>
<tbody>
<tr v-for="r in ADM_PERSON_EFF" :key="r.p" class="border-b last:border-0">
<td class="py-2">
<p class="text-xs font-medium text-slate-800">{{ r.p }}</p>
<p class="text-[11px] text-slate-400">{{ r.node }}</p>
</td>
<td class="py-2 text-right text-xs font-bold text-slate-800">{{ r.avg.toFixed(1) }}</td>
<td class="py-2 text-right text-xs text-slate-500">{{ r.max.toFixed(1) }}</td>
<td class="py-2">
<div class="flex items-center gap-2">
<div class="h-1.5 flex-1 overflow-hidden rounded-full bg-slate-100">
<div class="h-full rounded-full" :class="r.onTime >= 90 ? 'bg-[var(--success-color)]' : 'bg-[var(--warning-color)]'" :style="{ width: `${r.onTime}%` }" />
</div>
<span class="text-[11px] text-slate-500">{{ r.onTime }}%</span>
</div>
</td>
</tr>
</tbody>
</table>
</div>
<p class=" text-base font-semibold border-b border-slate-100 p-3">变更类型分布(近一年)</p>
<RingChart :data="DEPT_ACCEPT" />
</NCard>
</NGi>
<NGi span="24 s:24 m:24 l:16">
<!-- 风险增量与管控 -->
<NGi span="24 s:24 m:24 l:14">
<NCard
:bordered="true"
size="small"
@@ -256,277 +234,43 @@ const ADM_ARCHIVE_TAGS = [
: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),
}"
>
<p class=" text-base font-semibold border-b border-slate-100 p-3">变更是否达到预期效果及费用({{period}})</p>
<div class="py-3 px-4">
<div class="space-y-2.5">
<div class="flex flex-wrap items-center gap-x-4 gap-y-1">
<div class="flex items-center gap-1 text-[11px] text-slate-500">
<span class="h-2 w-2 rounded-full bg-[var(--theme-color)]"></span>
完全达到 73
<p class=" text-base font-semibold border-b border-slate-100 p-3">风险增量与管控(近一年 · 本车间变更新增风险与管控落实)</p>
<div class="py-3 px-4 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-slate-500">新增固有高风险项</div>
<div class="text-xl font-bold" :style="{color:themeStore.otherColor.error}">{{homeData?.risk?.inherent_high || 0}}</div>
</div>
<div class="flex items-center gap-1 text-[11px] text-slate-500">
<span class="h-2 w-2 rounded-full bg-[var(--success-color)]"></span>
基本达到 44
<div class="rounded-lg bg-amber-50 px-3 py-2">
<div class="text-[11px] text-slate-500">新增中风险项</div>
<div class="text-xl font-bold" :style="{color:themeStore.otherColor.warning}">{{homeData?.risk?.inherent_mid || 0}}</div>
</div>
<div class="flex items-center gap-1 text-[11px] text-slate-500">
<span class="h-2 w-2 rounded-full bg-[var(--error-color)]"></span>
未达到 9
<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" :style="{color:themeStore.otherColor.error}">{{homeData?.risk?.residual_high || 0}}</div>
</div>
<span class="ml-auto text-[11px] text-slate-500">费用合计 <b class="text-[var(--theme-color)]">86.4 万元</b></span>
</div>
<div class="overflow-x-auto rounded-lg border">
<div class="min-w-[680px]">
<div class="flex items-center gap-3 border-b bg-slate-50 px-3 py-1.5 text-[11px] font-semibold text-slate-500">
<span class="min-w-0 flex-1">验收明细 · 变更名称 / 编号 / 部门</span>
<span class="w-[84px] shrink-0">申请日期</span>
<span class="w-[84px] shrink-0">投用日期</span>
<span class="w-[84px] shrink-0">验收日期</span>
<span class="w-[68px] shrink-0 text-right">费用(万元)</span>
<span class="w-[76px] shrink-0 text-center">验收结论</span>
<span class="w-[52px] shrink-0 text-right">操作</span>
</div>
<div class="divide-y">
<div v-for="r in ADM_ACCEPT_DETAIL" :key="r.id" class="flex items-center gap-3 px-3 py-2 transition hover:bg-[#EAF0F9]/40">
<span class="min-w-0 flex-1">
<span class="block truncate text-xs font-medium text-slate-800">{{ r.title }}</span>
<span class="block font-mono text-[11px] text-slate-400">{{ r.id }} · {{ r.dept }}</span>
</span>
<span class="w-[84px] shrink-0 text-xs text-slate-600">{{ r.applyDate }}</span>
<span class="w-[84px] shrink-0 text-xs text-slate-600">{{ r.useTime }}</span>
<span class="w-[84px] shrink-0 text-xs text-slate-600">{{ r.acceptDate }}</span>
<span class="w-[68px] shrink-0 text-right text-xs font-bold text-slate-800">{{ r.cost.toFixed(1) }}</span>
<span class="w-[76px] shrink-0 text-center">
<NTag v-if="r.result==='完全达到'" size="small" type="success">{{ r.result }}</NTag>
<NTag v-if="r.result==='基本达到'" size="small" type="info">{{ r.result }}</NTag>
<NTag v-if="r.result==='未达到'" size="small" type="error">{{ r.result }}</NTag>
</span>
<span class="w-[52px] shrink-0 text-right">
<NButton size="small" class="text-[11px]" @click="message.info(`演示:打开 ${r.id} 验收详情(含费用明细与运行数据)`)">查看</NButton>
</span>
</div>
</div>
</div>
</div>
<div class="text-[11px] text-slate-400">明细为部分演示数据 · 全量见变更台账筛选「已关闭」</div>
</div>
</div>
</NCard>
</NGi>
</NGrid>
<NGrid :x-gap="16" :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%',
'--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),
}"
>
<p class=" text-base font-semibold border-b border-slate-100 p-3">变更带来的风险增量及管控({{period}})</p>
<div class="py-3 px-4">
<div class="space-y-3">
<div class="grid grid-cols-2 gap-3">
<div class="rounded-lg border border-[var(--error-color)] bg-[var(--error-bg)] px-3 py-2.5">
<div class="text-[11px] text-slate-500">新增固有风险项</div>
<div class="mt-1 text-sm font-bold text-slate-800">高 <b class="text-[var(--error-color)]">7</b> · 中 <b class="text-[var(--warning-color)]">21</b></div>
</div>
<div class="rounded-lg border border-[var(--warning-color)] bg-[var(--warning-bg)] px-3 py-2.5">
<div class="text-[11px] text-slate-500">剩余风险项(管控中)</div>
<div class="mt-1 text-sm font-bold text-slate-800">高 <b class="text-[var(--error-color)]">2</b> · 中 <b class="text-[var(--warning-color)]">9</b></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" :style="{color:themeStore.otherColor.warning}">{{homeData?.risk?.residual_mid || 0}}</div>
</div>
</div>
<div>
<div class="flex items-center justify-between text-xs text-slate-500">
<span>管控措施落实率</span><b class="text-[var(--success-color)]">92%</b>
<div class="flex items-center gap-2 text-slate-500">
<span class="text-xs">管控措施落实率</span>
<div class="h-2 flex-1 rounded-full bg-slate-100">
<div class="h-2 rounded-full" :style="{ background: themeStore.otherColor.success }" style="width: 96%"></div>
</div>
<div class="mt-1.5 h-1.5 w-full overflow-hidden rounded-full bg-slate-100">
<div class="h-full rounded-full bg-[var(--success-color)]" :style="{ width: `92%` }"></div>
<span class="font-semibold" :style="{color:themeStore.otherColor.success}">96%</span>
</div>
</div>
<div class="text-[11px] text-slate-400">口径:风险分析记录表识别的新增固有高/中风险项,与验收时剩余风险项对比;剩余高风险项均挂接管控措施并跟踪落实</div>
</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%',
'--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">当前未关闭变更({{period}})</p>
<div class="py-3 px-4">
<div class="space-y-3">
<div class="flex items-end gap-2">
<span class="text-3xl font-extrabold leading-none text-[var(--theme-color)]">8</span>
<span class="pb-0.5 text-[11px] text-slate-400">起 · 实时台账口径</span>
</div>
<div class="flex flex-wrap gap-1.5">
<span v-for="s in admOpenStages" :key="s.name" class="rounded-md border border-[var(--theme-color)] bg-[var(--theme-bg)] px-2 py-0.5 text-[11px] text-[var(--theme-color)]">{{ s.name }} <b>{{ s.n }}</b></span>
</div>
<div class="rounded-lg border border-[var(--warning-color)] bg-[var(--warning-bg)] px-3 py-2 text-[11px] text-[var(--warning-color)]">
临时变更临期 <b>1</b> 起 · 已到期未处置 <b class="text-[var(--error-color)]">1</b> 起(临期提醒天数可在通知设置调整)
</div>
<NButton size="small" ghost type="primary" block class="text-xs" @click="emit('go', 'ledger')">
进入变更台账<Icon icon="formkit:right" class="size-12px" />
</NButton>
</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%',
'--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">驳回的变更申请({{period}})</p>
<div class="py-3 px-4">
<div class="space-y-3">
<div class="flex items-end gap-2">
<span class="text-3xl font-extrabold leading-none text-[var(--error-color)]">14</span>
<span class="pb-0.5 text-[11px] text-slate-400">起 · 驳回率 11.1%</span>
</div>
<div class="rounded-lg border px-3 py-2.5 text-[11px] text-slate-500">
驳回后修改重报通过率 <b class="text-[var(--success-color)]">78.6%</b>
<div class="mt-0.5 text-slate-400">驳回均留痕并附带理由,申请人可「修改重报」</div>
</div>
<NButton size="small" ghost type="primary" block class="text-xs" @click="emit('go', 'ledger')">
查看驳回单<Icon icon="formkit:right" class="size-12px" />
</NButton>
</div>
<p class="mt-1.5 text-[11px] text-slate-400">高风险场景明细见「高风险」页(按部门筛选一车间)</p>
</div>
</NCard>
</NGi>
</NGrid>
<NGrid :x-gap="16" :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%' }">
<p class=" text-base font-semibold border-b border-slate-100 p-3">各部门审批时长(天 · {{period}})</p>
<div class="py-3 px-4">
<div class="space-y-3">
<div v-for="e in EFFICIENCY_DATA" :key="e.d" class="flex items-center gap-3">
<span class="w-14 shrink-0 text-xs text-slate-600">{{ e.d }}</span>
<NProgress
type="line"
:percentage="(e.days / 10) * 100"
:height="15"
:border-radius="4"
:fill-border-radius="4"
>
<span class="w-12 shrink-0 text-right text-xs font-bold text-slate-800">{{ e.days }} 天</span>
</NProgress>
</div>
</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%',
'--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">临时变更后续处置方式({{period}})</p>
<div class="py-3 px-4">
<div class="space-y-2.5">
<div v-for="t in ADM_TEMP_DISP" :key="t.name" class="rounded-lg border px-3 py-2.5">
<div class="flex items-center gap-1">
<div class="flex items-center gap-1">
<span v-if="t.name==='到期恢复'" class="h-2.5 w-2.5 rounded-sm bg-[var(--theme-color)]"></span>
<span v-if="t.name==='办理延期'" class="h-2.5 w-2.5 rounded-sm bg-[var(--warning-color)]"></span>
<span v-if="t.name==='转为永久'" class="h-2.5 w-2.5 rounded-sm bg-[var(--success-color)]"></span>
<span v-if="t.name==='超期未处理'" class="h-2.5 w-2.5 rounded-sm bg-[var(--error-color)]"></span>
<span class="text-xs font-medium text-slate-800">{{ t.name }}</span>
<p class="mt-[1px] pl-1 text-[11px] text-slate-400">{{ t.note }}</p>
</div>
<span v-if="t.name==='到期恢复'" class="ml-auto text-sm font-extrabold text-[var(--theme-color)]">{{ t.value }}</span>
<span v-if="t.name==='办理延期'" class="ml-auto text-sm font-extrabold text-[var(--warning-color)]">{{ t.value }}</span>
<span v-if="t.name==='转为永久'" class="ml-auto text-sm font-extrabold text-[var(--success-color)]">{{ t.value }}</span>
<span v-if="t.name==='超期未处理'" class="ml-auto text-sm font-extrabold text-[var(--error-color)]">{{ t.value }}</span>
</div>
</div>
<div class="text-[11px] text-slate-400">处置子单(延期 / 转永久 / 恢复)均走简化审批并留痕,与本统计同源</div>
</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%',
'--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">主要驳回理由汇总({{period}} · 按驳回单数)</p>
<div class="py-3 px-4">
<div class="space-y-2.5">
<div v-for="r in ADM_REJECT_REASONS" :key="r.reason">
<div class="flex items-center justify-between text-xs">
<span class="text-slate-600">{{ r.reason }}</span>
</div>
<NProgress
type="line"
:percentage="(r.n / 10) * 100"
>
<span class="w-12 shrink-0 text-right text-xs font-bold text-slate-800">{{ r.n }} 起</span>
</NProgress>
</div>
<div class="text-[11px] text-slate-400">可用于申请端填报质量改进:TOP2 理由已纳入 AI 预识别检查项</div>
</div>
</div>
</NCard>
</NGi>
</NGrid>
<!-- 变更投入和效果 -->
<NGrid :x-gap="16" :y-gap="16" responsive="screen" item-responsive>
<NGi span="24 s:24 m:24 l:24">
<NCard :bordered="true" size="small" :content-style="{padding: 0}"
@@ -537,55 +281,41 @@ const ADM_ARCHIVE_TAGS = [
'--success-color': themeStore.otherColor.success,
}"
>
<p class=" text-base font-semibold border-b border-slate-100 p-3">变更归档资料情况({{period}})</p>
<div class="py-3 px-4">
<div class="grid gap-4 grid-cols-12">
<div class="flex items-center gap-4 col-span-4">
<NProgress type="circle" :percentage="93.8" :offset-degree="180">
<div class="flex flex-col items-center mt-2">
<p class="flex text-xl font-bold leading-none text-[#1D2129]">
93.8<span class="text-sm font-semibold">%</span>
<div class="flex items-center justify-between p-3">
<p class=" text-base font-semibold border-b border-slate-100">变更投入和效果(近一年 · 已验收变更)</p>
<p class="text-[11px] text-slate-400">
已验收 <b class="text-slate-700">3</b> 起 ·
投入合计 <b :style="{color:themeStore.themeColor}">11.5</b> 万元 ·
完全达到率 <b :style="{color:themeStore.otherColor.success}">67%</b>
</p>
<p class="mt-1 text-[11px] text-slate-400">Good</p>
</div>
</NProgress>
<div class="space-y-1 text-xs text-slate-500">
<div>应归档 <b class="text-slate-800">81</b> 起 · 已归档 <b class="text-[var(--success-color)]">76</b> 起</div>
<div>待补齐资料 <b class="text-[var(--error-color)]">5</b> 起(已推送申请人补齐提醒)</div>
<div class="text-[11px] text-slate-400">归档包确认关闭后只读锁定,不可修改删除</div>
</div>
</div>
<div class="col-span-4">
<p class="text-[11px] font-bold uppercase tracking-[0.14em] text-slate-400">资料缺项 TOP</p>
<div class="mt-2 space-y-2">
<div v-for="g in ADM_ARCHIVE_GAP" :key="g.item" class="flex items-center gap-2 text-xs">
<span class="min-w-0 flex-1 text-slate-600">{{ g.item }}缺失</span>
<div class="w-44">
<NProgress
type="line"
status="warning"
:percentage="(g.n / 5) * 100"
>
<span class="w-12 shrink-0 text-right text-xs font-bold text-slate-800">{{ g.n }}</span>
</NProgress>
</div>
</div>
</div>
</div>
<div class="col-span-4">
<p class="text-[11px] font-bold uppercase tracking-[0.14em] text-slate-400">归档构成(已关闭 81 起)</p>
<div class="mt-2 flex flex-wrap gap-1.5">
<template v-for="x in ADM_ARCHIVE_TAGS" :key="x.k">
<NTag v-if="x.k==='资料齐全'" size="small" type="success">{{ x.k }} {{ x.n }}</NTag>
<NTag v-if="x.k==='缺培训签到' || x.k==='缺PSSR表'" size="small" type="warning">{{ x.k }} {{ x.n }}</NTag>
<NTag v-if="x.k==='缺验收单'" size="small" type="error">{{ x.k }} {{ x.n }}</NTag>
</template>
</div>
<NButton size="small" type="primary" ghost block class="mt-3 text-xs" @click="emit('go', 'knowledge')">
进入资料库 / 归档<Icon icon="formkit:right" class="size-12px" />
</NButton>
</div>
</div>
<div class="py-3 px-4">
<NTable size="small">
<thead>
<tr>
<td>变更名称 / 编号</td>
<td>申请日期</td>
<td>投用日期</td>
<td>验收日期</td>
<td>费用(万元)</td>
<td>验收结论</td>
</tr>
</thead>
<tbody>
<tr>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
<td>
<!-- <NTag v-if="r.result_status===3" size="small" type="success">{{r.result_label}}</NTag>
<NTag v-if="r.result_status===2" size="small" type="warning">{{r.result_label}}</NTag>
<NTag v-if="r.result_status===1" size="small" type="error">{{r.result_label}}</NTag> -->
</td>
</tr>
</tbody>
</NTable>
</div>
</NCard>
</NGi>
@@ -1,90 +0,0 @@
<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; }[]; }>();
const { domRef, updateOptions } = useEcharts(() => ({
tooltip: {
trigger: "axis",
axisPointer: {
type: "shadow",
textStyle: {
color: "#fff",
},
},
},
legend: {
show:false,
bottom: '20%',
left: 'center',
icon: 'circle',
itemWidth: 10,
itemHeight: 10,
itemStyle: {
borderWidth: 0
},
},
grid: {
top: "5%",
left: "5%",
right: "5%",
bottom: "11%",
},
calculable: true,
xAxis: [
{
type: "category",
boundaryGap: true, // 新增,固定柱子位置
axisLine: {
show: false,
},
axisLabel: {
interval: 0,
},
splitLine: { show: false },
axisTick: { show: false },
splitArea: { show: false },
data: [] as string[],
},
],
yAxis: [
{
type: "value",
show: false,
},
],
series: [
{
type: "bar",
barWidth: 45,
barGap: "10%",
color: "#2080f0",
label: { show: true, position: 'top',color: '#333',fontWeight: 'bold' },
data: [] as number[],
},
]
}));
function init() {
updateOptions(opts => {
let allMonth = props.data.map((item:any) => item.name);
let values = props.data.map((item:any) => item.value);
opts.xAxis[0].data = allMonth;
opts.series[0].data = values;
return opts;
});
}
init();
</script>
<template>
<div ref="domRef" class="w-full h-220px overflow-hidden"></div>
</template>
<style scoped></style>
@@ -6,7 +6,7 @@ defineOptions({
name: 'RingChart'
});
const props = defineProps<{ data?: { name: string; value: number }[]; colors?: string[] }>();
const props = defineProps<{ data?: { name: string; value: number }[]; }>();
const { domRef, updateOptions } = useEcharts(() => ({
tooltip: {
@@ -24,7 +24,7 @@ const { domRef, updateOptions } = useEcharts(() => ({
},
},
title: {
text: `{a|126}\n{b|总数}`,
text: `{a|126}\n{b|近一年}`,
textStyle: {
rich: {
a: {
@@ -50,7 +50,7 @@ const { domRef, updateOptions } = useEcharts(() => ({
series: [
{
type: 'pie',
color: ['#5da8ff', '#8e9dff', '#fedc69', '#26deca'],
color: ["#2080f0", "#7CC242", "#F5A623"],
radius: ['45%', '65%'],
center: ['50%', '45%'],
avoidLabelOverlap: false,
@@ -73,7 +73,6 @@ const { domRef, updateOptions } = useEcharts(() => ({
function init() {
updateOptions(opts => {
opts.series[0].data = props.data || [];
opts.series[0].color = props.colors || [];
return opts;
});
}