统计报表页面完成
This commit is contained in:
@@ -122,3 +122,12 @@ export function factoryStatisticsApi(params: {from: string | null, to: string |
|
||||
params
|
||||
});
|
||||
}
|
||||
|
||||
// 统计报表
|
||||
export function reportStatisticsApi(params: {from: string | null, to: string | null}) {
|
||||
return request({
|
||||
url: `/api/reports/admin-center`,
|
||||
method: 'get',
|
||||
params
|
||||
});
|
||||
}
|
||||
|
||||
+201
-190
@@ -1,99 +1,77 @@
|
||||
<script setup lang="ts">
|
||||
import { ref, computed } from 'vue';
|
||||
import { useAppStore } from '@/store/modules/app';
|
||||
import { ref, computed, onMounted } from 'vue';
|
||||
import { Icon } from '@iconify/vue'
|
||||
import { useThemeStore } from '@/store/modules/theme';
|
||||
import { getColorWithOpacity } from '@/utils/common';
|
||||
import { useRouterPush } from '@/hooks/common/router';
|
||||
import { getColorWithOpacity, formatTimestamp, getTimeRangeStamp } from '@/utils/common';
|
||||
import RingChart from './modules/ringChart.vue';
|
||||
import ColumnChart from './modules/columnChart.vue';
|
||||
import { reportStatisticsApi } from '@/service/api/statistics';
|
||||
|
||||
const appStore = useAppStore();
|
||||
const themeStore = useThemeStore();
|
||||
const gap = computed(() => (appStore.isMobile ? 0 : 16));
|
||||
const { routerPushByKey } = useRouterPush();
|
||||
|
||||
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 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 RANGE_OPTIONS = [
|
||||
{ label: "近一个月", value: "month" },
|
||||
{ label: "近三个月", value: "quarter" },
|
||||
{ label: "近半年", value: "half_year" },
|
||||
{ label: "近一年", value: "year" },
|
||||
];
|
||||
|
||||
const loading = ref<boolean>(false);
|
||||
const range = ref<string>("year");
|
||||
const from = ref<number | null>(getTimeRangeStamp(range.value)?.from || null);
|
||||
const to = ref<number | null>(getTimeRangeStamp(range.value)?.to || null);
|
||||
const homeData = ref<any>(null);
|
||||
|
||||
// 匹配日期范围
|
||||
const dateLabel = computed(() => {
|
||||
return RANGE_OPTIONS.find(item => item.value === range.value)?.label || '';
|
||||
})
|
||||
|
||||
// 小时转换天
|
||||
const hourToDay = (hour: number) => {
|
||||
return Math.trunc((hour / 24) * 100) / 100;
|
||||
}
|
||||
|
||||
// 时间范围切换
|
||||
const rangeChange = (val: string) => {
|
||||
range.value = val;
|
||||
from.value = getTimeRangeStamp(val)?.from || null;
|
||||
to.value = getTimeRangeStamp(val)?.to || null;
|
||||
getData();
|
||||
}
|
||||
|
||||
// 跳转详情页
|
||||
const jumpTo = (key: string, qid: number = 0) => {
|
||||
if(key==='details_index' && qid){
|
||||
routerPushByKey(key,{ query: { id: qid.toString(),key:'report' } });
|
||||
}else{
|
||||
routerPushByKey(key as any);
|
||||
}
|
||||
}
|
||||
|
||||
// 获取数据
|
||||
const getData = async () => {
|
||||
loading.value = true;
|
||||
const {data,error} = await reportStatisticsApi({
|
||||
from: formatTimestamp(from.value, "yyyy-MM-dd"),
|
||||
to: formatTimestamp(to.value, "yyyy-MM-dd")
|
||||
});
|
||||
if(!error){
|
||||
homeData.value = data;
|
||||
console.log(data)
|
||||
}
|
||||
loading.value = false;
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
getData();
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<NSpin :show="loading" size="small">
|
||||
<NSpace vertical :size="16">
|
||||
<!-- 统计报表 -->
|
||||
<NCard :bordered="false" size="small" :style="{borderRadius: themeStore.themeRadius + 'px'}">
|
||||
@@ -103,10 +81,10 @@ const ADM_ARCHIVE_TAGS = [
|
||||
<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="tiny" round v-for="p in RANGE_OPTIONS" :key="p.value" @click="rangeChange(p.value)"
|
||||
:ghost="range === p.value ? false : true"
|
||||
:type="range === p.value ? 'primary' : 'default'"
|
||||
>{{ p.label }}</NButton>
|
||||
<NButton size="small" class="text-xs ml-1">
|
||||
<Icon icon="material-symbols:download" class="size-14px mr-1" />导出
|
||||
</NButton>
|
||||
@@ -114,7 +92,7 @@ const ADM_ARCHIVE_TAGS = [
|
||||
</div>
|
||||
</NCard>
|
||||
<!-- 卡片数据 -->
|
||||
<NGrid cols="s:1 m:4 l:4" responsive="screen" :x-gap="gap" :y-gap="16" :style="{'--theme-color': themeStore.themeColor}">
|
||||
<NGrid cols="s:1 m:4 l:4" responsive="screen" :x-gap="16" :y-gap="16" :style="{'--theme-color': themeStore.themeColor}">
|
||||
<NGi>
|
||||
<div
|
||||
class="flex-1 bg-white px-16px py-12px text-[#94a3b8]"
|
||||
@@ -124,11 +102,11 @@ const ADM_ARCHIVE_TAGS = [
|
||||
<div class="flex items-center">
|
||||
<CountTo
|
||||
:start-value="0"
|
||||
:end-value="126"
|
||||
:end-value="homeData?.summary?.total || 0"
|
||||
class="text-24px font-600 text-[var(--theme-color)]"
|
||||
/>
|
||||
</div>
|
||||
<p class="text-12px">{{period}} · 全厂</p>
|
||||
<p class="text-12px">{{dateLabel}} · 全厂</p>
|
||||
</div>
|
||||
</NGi>
|
||||
<NGi>
|
||||
@@ -140,11 +118,11 @@ const ADM_ARCHIVE_TAGS = [
|
||||
<div class="flex items-center">
|
||||
<CountTo
|
||||
:start-value="0"
|
||||
:end-value="18"
|
||||
:end-value="homeData?.summary?.important_total || 0"
|
||||
class="text-26px font-600 text-[var(--theme-color)]"
|
||||
/>
|
||||
</div>
|
||||
<p class="text-12px">占比 14%</p>
|
||||
<p class="text-12px">占比 {{homeData?.summary?.important_pct || 0}}%</p>
|
||||
</div>
|
||||
</NGi>
|
||||
<NGi>
|
||||
@@ -156,7 +134,7 @@ const ADM_ARCHIVE_TAGS = [
|
||||
<div class="flex items-center">
|
||||
<CountTo
|
||||
:start-value="0"
|
||||
:end-value="86.4"
|
||||
:end-value="homeData?.invest_card?.total_fee || 0"
|
||||
:decimals="1"
|
||||
class="text-26px font-600 text-[var(--theme-color)]"
|
||||
/><p class="text-26px font-600 text-[var(--theme-color)]">万</p>
|
||||
@@ -169,11 +147,11 @@ 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"
|
||||
:end-value="homeData?.invest_card?.full_rate || 0"
|
||||
class="text-26px font-600 text-[var(--theme-color)]"
|
||||
/><p class="text-26px font-600 text-[var(--theme-color)]">%</p>
|
||||
</div>
|
||||
@@ -182,26 +160,29 @@ const ADM_ARCHIVE_TAGS = [
|
||||
</NGi>
|
||||
</NGrid>
|
||||
|
||||
<NGrid :x-gap="gap" :y-gap="16" responsive="screen" item-responsive>
|
||||
<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>
|
||||
<p class=" text-base font-semibold border-b border-slate-100 p-3">各车间变更数量({{dateLabel}})</p>
|
||||
<div class="py-3 px-4">
|
||||
<ColumnChart :data="changeData" style="height: 220px" />
|
||||
<ColumnChart v-if="homeData" :data="homeData?.workshop_counts?.items || []" />
|
||||
</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>
|
||||
<p class=" text-base font-semibold border-b border-slate-100 p-3">变更类型分布({{dateLabel}})</p>
|
||||
<div class="py-3 px-4">
|
||||
<RingChart :data="DEPT_ACCEPT" :colors="ACCEPT_COLORS" />
|
||||
<RingChart v-if="homeData" :data="homeData?.type_dist?.items || []" />
|
||||
</div>
|
||||
</NCard>
|
||||
</NGi>
|
||||
</NGrid>
|
||||
|
||||
<NGrid :x-gap="gap" :y-gap="16" responsive="screen" item-responsive>
|
||||
<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="{
|
||||
@@ -216,7 +197,7 @@ const ADM_ARCHIVE_TAGS = [
|
||||
'--theme-bg': getColorWithOpacity(themeStore.themeColor,0.1),
|
||||
}"
|
||||
>
|
||||
<p class=" text-base font-semibold border-b border-slate-100 p-3">各审批人审批时长(天 · {{period}} · 系统自动采集)</p>
|
||||
<p class=" text-base font-semibold border-b border-slate-100 p-3">各审批人审批时长(天 · {{dateLabel}} · 系统自动采集)</p>
|
||||
<div class="py-3 px-4">
|
||||
<table class="w-full text-xs">
|
||||
<thead>
|
||||
@@ -224,23 +205,26 @@ const ADM_ARCHIVE_TAGS = [
|
||||
<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>
|
||||
<th class="w-[130px] py-2 font-semibold">及时率(≤{{hourToDay(homeData?.approver_eff?.sign_timely_hours || 0)}}天)</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr v-for="r in ADM_PERSON_EFF" :key="r.p" class="border-b last:border-0">
|
||||
<tr v-if="homeData?.approver_eff?.rows?.length===0">
|
||||
<td colspan="4" class="text-center text-xs text-slate-400 py-3">暂无数据</td>
|
||||
</tr>
|
||||
<tr v-for="r in homeData?.approver_eff?.rows || []" :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>
|
||||
<p class="text-xs font-medium text-slate-800">{{ r.user_name }}</p>
|
||||
<p class="text-[11px] text-slate-400">{{ r.step_name }}</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 text-right text-xs font-bold text-slate-800">{{ r.avg_days }}</td>
|
||||
<td class="py-2 text-right text-xs text-slate-500">{{ r.max_days }}</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 class="h-full rounded-full" :class="r.avg_days <= hourToDay(homeData?.approver_eff?.sign_timely_hours || 0) ? 'bg-[var(--success-color)]' : 'bg-[var(--warning-color)]'" :style="{ width: `${r.timely_rate}%` }" />
|
||||
</div>
|
||||
<span class="text-[11px] text-slate-500">{{ r.onTime }}%</span>
|
||||
<span class="text-[11px] text-slate-500">{{ r.timely_rate }}%</span>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
@@ -248,8 +232,8 @@ const ADM_ARCHIVE_TAGS = [
|
||||
</table>
|
||||
</div>
|
||||
</NCard>
|
||||
|
||||
</NGi>
|
||||
<!-- 变更是否达到预期效果及费用 -->
|
||||
<NGi span="24 s:24 m:24 l:16">
|
||||
<NCard
|
||||
:bordered="true"
|
||||
@@ -266,23 +250,17 @@ const ADM_ARCHIVE_TAGS = [
|
||||
'--warning-bg': getColorWithOpacity(themeStore.otherColor.warning,0.1),
|
||||
}"
|
||||
>
|
||||
<p class=" text-base font-semibold border-b border-slate-100 p-3">变更是否达到预期效果及费用({{period}})</p>
|
||||
<p class=" text-base font-semibold border-b border-slate-100 p-3">变更是否达到预期效果及费用({{dateLabel}})</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
|
||||
<div v-for="item in homeData?.invest_card?.items || []" :key="item.key" class="flex items-center gap-1 text-[11px] text-slate-500">
|
||||
<span v-if="item.key==='3'" class="h-2 w-2 rounded-full bg-[var(--theme-color)]"></span>
|
||||
<span v-if="item.key==='2'" class="h-2 w-2 rounded-full bg-[var(--success-color)]"></span>
|
||||
<span v-if="item.key==='1'" class="h-2 w-2 rounded-full bg-[var(--error-color)]"></span>
|
||||
{{item.label}} {{item.count}}
|
||||
</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>
|
||||
<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>
|
||||
<span class="ml-auto text-[11px] text-slate-500">费用合计 <b class="text-[var(--theme-color)]">86.4 万元</b></span>
|
||||
<span class="ml-auto text-[11px] text-slate-500">费用合计 <b class="text-[var(--theme-color)]">{{homeData?.invest_card?.total_fee}} 万元</b></span>
|
||||
</div>
|
||||
<div class="overflow-x-auto rounded-lg border">
|
||||
<div class="min-w-[680px]">
|
||||
@@ -296,35 +274,36 @@ const ADM_ARCHIVE_TAGS = [
|
||||
<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">
|
||||
<div v-for="r in homeData?.accept_detail || []" :key="r.change_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 class="block font-mono text-[11px] text-slate-400">{{ r.change_no }} · {{ r.org_name }}</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-[84px] shrink-0 text-xs text-slate-600">{{ r?.apply_time?.slice(0,10) }}</span>
|
||||
<span class="w-[84px] shrink-0 text-xs text-slate-600">{{ r?.use_time?.slice(0,10) }}</span>
|
||||
<span class="w-[84px] shrink-0 text-xs text-slate-600">{{ r?.accept_time?.slice(0,10) }}</span>
|
||||
<span class="w-[68px] shrink-0 text-right text-xs font-bold text-slate-800">{{ r.cost }}</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>
|
||||
<NTag v-if="r.result_label==='完全达到'" size="small" type="success">{{ r.result_label }}</NTag>
|
||||
<NTag v-if="r.result_label==='基本达到'" size="small" type="warning">{{ r.result_label }}</NTag>
|
||||
<NTag v-if="r.result_label==='未达到'" size="small" type="error">{{ r.result_label }}</NTag>
|
||||
</span>
|
||||
<span class="w-[52px] shrink-0 text-right">
|
||||
<NButton size="small" class="text-[11px]" @click="message.info(`演示:打开 ${r.id} 验收详情(含费用明细与运行数据)`)">查看</NButton>
|
||||
<NButton size="small" class="text-[11px]" @click="jumpTo('details_index',r.change_id)">查看</NButton>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="text-[11px] text-slate-400">明细为部分演示数据 · 全量见变更台账筛选「已关闭」</div>
|
||||
<div class="text-[11px] text-slate-400">当前明细为部分数据 · 全量见变更台账筛选「已关闭」</div>
|
||||
</div>
|
||||
</div>
|
||||
</NCard>
|
||||
</NGi>
|
||||
</NGrid>
|
||||
|
||||
<NGrid :x-gap="gap" :y-gap="16" responsive="screen" item-responsive>
|
||||
<NGrid :x-gap="16" :y-gap="16" responsive="screen" item-responsive>
|
||||
<!-- 变更带来的风险增量及管控 -->
|
||||
<NGi span="24 s:24 m:24 l:8">
|
||||
<NCard
|
||||
:bordered="true"
|
||||
@@ -340,25 +319,25 @@ const ADM_ARCHIVE_TAGS = [
|
||||
'--warning-bg': getColorWithOpacity(themeStore.otherColor.warning,0.1),
|
||||
}"
|
||||
>
|
||||
<p class=" text-base font-semibold border-b border-slate-100 p-3">变更带来的风险增量及管控({{period}})</p>
|
||||
<p class=" text-base font-semibold border-b border-slate-100 p-3">变更带来的风险增量及管控({{dateLabel}})</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 class="mt-1 text-sm font-bold text-slate-800">高 <b class="text-[var(--error-color)]">{{homeData?.risk?.inherent_high || 0}}</b> · 中 <b class="text-[var(--warning-color)]">{{homeData?.risk?.inherent_mid || 0}}</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="mt-1 text-sm font-bold text-slate-800">高 <b class="text-[var(--error-color)]">{{homeData?.risk?.residual_high || 0}}</b> · 中 <b class="text-[var(--warning-color)]">{{homeData?.risk?.residual_mid || 0}}</b></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>
|
||||
<span>管控措施落实率</span><b class="text-[var(--success-color)]">{{homeData?.risk?.pssr_rate || 0}}%</b>
|
||||
</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>
|
||||
<div class="h-full rounded-full bg-[var(--success-color)]" :style="{ width: `${homeData?.risk?.pssr_rate || 0}%` }"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="text-[11px] text-slate-400">口径:风险分析记录表识别的新增固有高/中风险项,与验收时剩余风险项对比;剩余高风险项均挂接管控措施并跟踪落实</div>
|
||||
@@ -366,6 +345,7 @@ const ADM_ARCHIVE_TAGS = [
|
||||
</div>
|
||||
</NCard>
|
||||
</NGi>
|
||||
<!-- 当前未关闭变更 -->
|
||||
<NGi span="24 s:24 m:24 l:8">
|
||||
<NCard :bordered="true" size="small" :content-style="{padding: 0}"
|
||||
:style="{
|
||||
@@ -380,26 +360,29 @@ const ADM_ARCHIVE_TAGS = [
|
||||
'--theme-bg': getColorWithOpacity(themeStore.themeColor,0.1),
|
||||
}"
|
||||
>
|
||||
<p class=" text-base font-semibold border-b border-slate-100 p-3">当前未关闭变更({{period}})</p>
|
||||
<p class=" text-base font-semibold border-b border-slate-100 p-3">当前未关闭变更({{dateLabel}})</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="text-3xl font-extrabold leading-none text-[var(--theme-color)]">{{homeData?.open_changes?.total || 0}}</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>
|
||||
<NTag v-for="item in homeData?.open_changes?.items || []" :key="item.status" size="small" type="primary">
|
||||
{{item.label}}{{item.count}}
|
||||
</NTag>
|
||||
</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> 起(临期提醒天数可在通知设置调整)
|
||||
临时变更临期 <b>{{homeData?.open_changes?.temp_near || 0}}</b> 起 · 已到期未处置 <b class="text-[var(--error-color)]">{{homeData?.open_changes?.temp_over || 0}}</b> 起(临期提醒天数可在通知设置调整)
|
||||
</div>
|
||||
<NButton size="small" ghost type="primary" block class="text-xs" @click="emit('go', 'ledger')">
|
||||
<NButton size="small" ghost type="primary" block class="text-xs" @click="jumpTo('changeledger')">
|
||||
进入变更台账<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="{
|
||||
@@ -414,18 +397,18 @@ const ADM_ARCHIVE_TAGS = [
|
||||
'--theme-bg': getColorWithOpacity(themeStore.themeColor,0.1),
|
||||
}"
|
||||
>
|
||||
<p class=" text-base font-semibold border-b border-slate-100 p-3">驳回的变更申请({{period}})</p>
|
||||
<p class=" text-base font-semibold border-b border-slate-100 p-3">驳回的变更申请({{dateLabel}})</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>
|
||||
<span class="text-3xl font-extrabold leading-none text-[var(--error-color)]">{{homeData?.reject?.total || 0}}</span>
|
||||
<span class="pb-0.5 text-[11px] text-slate-400">起 · 驳回率 {{homeData?.reject?.rate || 0}}%</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>
|
||||
驳回后修改重报通过率 <b class="text-[var(--success-color)]">{{homeData?.reject?.repass_rate || 0}}%</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')">
|
||||
<NButton size="small" ghost type="primary" block class="text-xs" @click="jumpTo('changeledger')">
|
||||
查看驳回单<Icon icon="formkit:right" class="size-12px" />
|
||||
</NButton>
|
||||
</div>
|
||||
@@ -434,14 +417,15 @@ const ADM_ARCHIVE_TAGS = [
|
||||
</NGi>
|
||||
</NGrid>
|
||||
|
||||
<NGrid :x-gap="gap" :y-gap="16" responsive="screen" item-responsive>
|
||||
<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>
|
||||
<p class=" text-base font-semibold border-b border-slate-100 p-3">各部门审批时长(天 · {{dateLabel}})</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>
|
||||
<div v-for="e in homeData?.dept_approval_days || []" :key="e.org_id" class="flex items-center gap-3">
|
||||
<span class="w-14 shrink-0 text-xs text-slate-600">{{ e.org_name }}</span>
|
||||
<NProgress
|
||||
type="line"
|
||||
:percentage="(e.days / 10) * 100"
|
||||
@@ -456,6 +440,7 @@ const ADM_ARCHIVE_TAGS = [
|
||||
</div>
|
||||
</NCard>
|
||||
</NGi>
|
||||
<!-- 临时变更后续处置方式 -->
|
||||
<NGi span="24 s:24 m:24 l:8">
|
||||
<NCard :bordered="true" size="small" :content-style="{padding: 0}"
|
||||
:style="{
|
||||
@@ -470,23 +455,47 @@ const ADM_ARCHIVE_TAGS = [
|
||||
'--theme-bg': getColorWithOpacity(themeStore.themeColor,0.1),
|
||||
}"
|
||||
>
|
||||
<p class=" text-base font-semibold border-b border-slate-100 p-3">临时变更后续处置方式({{period}})</p>
|
||||
<p class=" text-base font-semibold border-b border-slate-100 p-3">临时变更后续处置方式({{dateLabel}})</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="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>
|
||||
<span class="h-2.5 w-2.5 rounded-sm bg-[var(--theme-color)]"></span>
|
||||
<span class="text-xs font-medium text-slate-800">到期恢复</span>
|
||||
<p class="mt-[1px] pl-1 text-[11px] text-slate-400">恢复原状并验收关闭</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>
|
||||
<span class="ml-auto text-sm font-extrabold text-[var(--theme-color)]">{{ homeData?.temp_disposal?.restore || 0 }}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="rounded-lg border px-3 py-2.5">
|
||||
<div class="flex items-center gap-1">
|
||||
<div class="flex items-center gap-1">
|
||||
<span class="h-2.5 w-2.5 rounded-sm bg-[var(--warning-color)]"></span>
|
||||
<span class="text-xs font-medium text-slate-800">办理延期</span>
|
||||
<p class="mt-[1px] pl-1 text-[11px] text-slate-400">均符合「至多延期 1 次」</p>
|
||||
</div>
|
||||
<span class="ml-auto text-sm font-extrabold text-[var(--warning-color)]">{{ homeData?.temp_disposal?.extend || 0 }}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="rounded-lg border px-3 py-2.5">
|
||||
<div class="flex items-center gap-1">
|
||||
<div class="flex items-center gap-1">
|
||||
<span class="h-2.5 w-2.5 rounded-sm bg-[var(--success-color)]"></span>
|
||||
<span class="text-xs font-medium text-slate-800">转为永久</span>
|
||||
<p class="mt-[1px] pl-1 text-[11px] text-slate-400">补办永久变更审批</p>
|
||||
</div>
|
||||
<span class="ml-auto text-sm font-extrabold text-[var(--success-color)]">{{ homeData?.temp_disposal?.permanent || 0 }}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="rounded-lg border px-3 py-2.5">
|
||||
<div class="flex items-center gap-1">
|
||||
<div class="flex items-center gap-1">
|
||||
<span class="h-2.5 w-2.5 rounded-sm bg-[var(--error-color)]"></span>
|
||||
<span class="text-xs font-medium text-slate-800">超期未处理</span>
|
||||
<p class="mt-[1px] pl-1 text-[11px] text-slate-400">系统已推送超期提醒至申请人</p>
|
||||
</div>
|
||||
<span class="ml-auto text-sm font-extrabold text-[var(--error-color)]">{{ homeData?.temp_disposal?.overdue_untreated || 0 }}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="text-[11px] text-slate-400">处置子单(延期 / 转永久 / 恢复)均走简化审批并留痕,与本统计同源</div>
|
||||
@@ -494,6 +503,7 @@ const ADM_ARCHIVE_TAGS = [
|
||||
</div>
|
||||
</NCard>
|
||||
</NGi>
|
||||
<!-- 主要驳回理由汇总 -->
|
||||
<NGi span="24 s:24 m:24 l:8">
|
||||
<NCard :bordered="true" size="small" :content-style="{padding: 0}"
|
||||
:style="{
|
||||
@@ -508,18 +518,18 @@ const ADM_ARCHIVE_TAGS = [
|
||||
'--theme-bg': getColorWithOpacity(themeStore.themeColor,0.1),
|
||||
}"
|
||||
>
|
||||
<p class=" text-base font-semibold border-b border-slate-100 p-3">主要驳回理由汇总({{period}} · 按驳回单数)</p>
|
||||
<p class=" text-base font-semibold border-b border-slate-100 p-3">主要驳回理由汇总({{dateLabel}} · 按驳回单数)</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 v-for="r in homeData?.reject?.reasons || []" :key="r">
|
||||
<div class="flex items-center justify-between text-xs">
|
||||
<span class="text-slate-600">{{ r.reason }}</span>
|
||||
<span class="text-slate-600">{{ r.remark }}</span>
|
||||
</div>
|
||||
<NProgress
|
||||
type="line"
|
||||
:percentage="(r.n / 10) * 100"
|
||||
:percentage="(r.count / 10) * 100"
|
||||
>
|
||||
<span class="w-12 shrink-0 text-right text-xs font-bold text-slate-800">{{ r.n }} 起</span>
|
||||
<span class="w-12 shrink-0 text-right text-xs font-bold text-slate-800">{{ r.count }} 起</span>
|
||||
</NProgress>
|
||||
</div>
|
||||
<div class="text-[11px] text-slate-400">可用于申请端填报质量改进:TOP2 理由已纳入 AI 预识别检查项</div>
|
||||
@@ -528,8 +538,8 @@ const ADM_ARCHIVE_TAGS = [
|
||||
</NCard>
|
||||
</NGi>
|
||||
</NGrid>
|
||||
|
||||
<NGrid :x-gap="gap" :y-gap="16" responsive="screen" item-responsive>
|
||||
<!-- 变更归档资料情况 -->
|
||||
<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}"
|
||||
:style="{
|
||||
@@ -539,51 +549,51 @@ const ADM_ARCHIVE_TAGS = [
|
||||
'--success-color': themeStore.otherColor.success,
|
||||
}"
|
||||
>
|
||||
<p class=" text-base font-semibold border-b border-slate-100 p-3">变更归档资料情况({{period}})</p>
|
||||
<p class=" text-base font-semibold border-b border-slate-100 p-3">变更归档资料情况({{dateLabel}})</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">
|
||||
<NProgress type="circle" :percentage="homeData?.archive?.rate || 0" :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>
|
||||
{{homeData?.archive?.rate || 0}}<span class="text-sm font-semibold">%</span>
|
||||
</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>应归档 <b class="text-slate-800">{{homeData?.archive?.should_total || 0}}</b> 起 · 已归档 <b class="text-[var(--success-color)]">{{homeData?.archive?.archived_total || 0}}</b> 起</div>
|
||||
<div>待补齐资料 <b class="text-[var(--error-color)]">{{homeData?.archive?.pending_total || 0}}</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 v-for="g in homeData?.archive?.gaps || []" :key="g.key" class="flex items-center gap-2 text-xs">
|
||||
<span class="min-w-0 flex-1 text-slate-600">{{ g.label }}</span>
|
||||
<div class="w-44">
|
||||
<NProgress
|
||||
type="line"
|
||||
status="warning"
|
||||
:percentage="(g.n / 5) * 100"
|
||||
:percentage="(g.count / 10) * 100"
|
||||
>
|
||||
<span class="w-12 shrink-0 text-right text-xs font-bold text-slate-800">{{ g.n }}</span>
|
||||
<span class="w-12 shrink-0 text-right text-xs font-bold text-slate-800">{{ g.count }}</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>
|
||||
<p class="text-[11px] font-bold uppercase tracking-[0.14em] text-slate-400">归档构成(已关闭 {{homeData?.archive?.should_total || 0}} 起)</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>
|
||||
<NTag size="small" type="success">资料齐全 {{ homeData?.archive?.archived_total || 0 }}</NTag>
|
||||
<template v-for="x in homeData?.archive?.gaps || []" :key="x.key">
|
||||
<NTag v-if="x.key==='3'" size="small" type="warning">缺培训签到 {{ x.count }}</NTag>
|
||||
<NTag v-if="x.key==='4'" size="small" type="warning">缺PSSR表 {{ x.count }}</NTag>
|
||||
<NTag v-if="x.key==='5'" size="small" type="error">缺验收单 {{ x.count }}</NTag>
|
||||
</template>
|
||||
</div>
|
||||
<NButton size="small" type="primary" ghost block class="mt-3 text-xs" @click="emit('go', 'knowledge')">
|
||||
<NButton size="small" type="primary" ghost block class="mt-3 text-xs" @click="jumpTo('docs_archives')">
|
||||
进入资料库 / 归档<Icon icon="formkit:right" class="size-12px" />
|
||||
</NButton>
|
||||
</div>
|
||||
@@ -594,6 +604,7 @@ const ADM_ARCHIVE_TAGS = [
|
||||
</NGrid>
|
||||
|
||||
</NSpace>
|
||||
</NSpin>
|
||||
</template>
|
||||
|
||||
<style scoped></style>
|
||||
|
||||
@@ -6,7 +6,7 @@ defineOptions({
|
||||
name: 'RingChart'
|
||||
});
|
||||
|
||||
const props = defineProps<{ data: { name: string; value: number; }[]; }>();
|
||||
const props = defineProps<{ data: { org_name: string; count: number; }[]; }>();
|
||||
|
||||
const { domRef, updateOptions } = useEcharts(() => ({
|
||||
tooltip: {
|
||||
@@ -30,9 +30,9 @@ const { domRef, updateOptions } = useEcharts(() => ({
|
||||
},
|
||||
},
|
||||
grid: {
|
||||
top: "5%",
|
||||
left: "5%",
|
||||
right: "5%",
|
||||
top: "10%",
|
||||
left: 0,
|
||||
right: 0,
|
||||
bottom: "11%",
|
||||
},
|
||||
calculable: true,
|
||||
@@ -44,7 +44,8 @@ const { domRef, updateOptions } = useEcharts(() => ({
|
||||
show: false,
|
||||
},
|
||||
axisLabel: {
|
||||
interval: 0,
|
||||
interval: 'auto',
|
||||
hideOverlap: true
|
||||
},
|
||||
splitLine: { show: false },
|
||||
axisTick: { show: false },
|
||||
@@ -72,8 +73,8 @@ const { domRef, updateOptions } = useEcharts(() => ({
|
||||
|
||||
function init() {
|
||||
updateOptions(opts => {
|
||||
let allMonth = props.data.map((item:any) => item.name);
|
||||
let values = props.data.map((item:any) => item.value);
|
||||
let allMonth = props.data.map((item:any) => item.org_name);
|
||||
let values = props.data.map((item:any) => item.count);
|
||||
opts.xAxis[0].data = allMonth;
|
||||
opts.series[0].data = values;
|
||||
return opts;
|
||||
|
||||
@@ -6,7 +6,8 @@ defineOptions({
|
||||
name: 'RingChart'
|
||||
});
|
||||
|
||||
const props = defineProps<{ data?: { name: string; value: number }[]; colors?: string[] }>();
|
||||
const props = defineProps<{ data?: { name: string; value: number }[]; }>();
|
||||
const chartData = ref<{ name: string; value: number; }[]>([]);
|
||||
|
||||
const { domRef, updateOptions } = useEcharts(() => ({
|
||||
tooltip: {
|
||||
@@ -22,6 +23,25 @@ const { domRef, updateOptions } = useEcharts(() => ({
|
||||
itemStyle: {
|
||||
borderWidth: 0
|
||||
},
|
||||
textStyle: {
|
||||
rich: {
|
||||
name: {
|
||||
padding: [0, 0, 0, 0],
|
||||
},
|
||||
count: {
|
||||
padding: [0, 0, 0, 5],
|
||||
fontWeight: 600,
|
||||
},
|
||||
}
|
||||
},
|
||||
formatter: function (name: string) {
|
||||
var info = chartData.value?.find((item: { name: string }) => item.name === name);
|
||||
if(info){
|
||||
return '{name|'+name+'} {count|'+(info.value)+'}';
|
||||
}else{
|
||||
return name;
|
||||
}
|
||||
}
|
||||
},
|
||||
title: {
|
||||
text: `{a|126}\n{b|总数}`,
|
||||
@@ -50,7 +70,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,
|
||||
@@ -72,8 +92,14 @@ const { domRef, updateOptions } = useEcharts(() => ({
|
||||
|
||||
function init() {
|
||||
updateOptions(opts => {
|
||||
opts.series[0].data = props.data || [];
|
||||
opts.series[0].color = props.colors || [];
|
||||
const total = props.data?.reduce((sum:number, item:any) => sum + item.count, 0);
|
||||
const result:any = props.data?.map((item:any) => ({
|
||||
name: item.label,
|
||||
value: item.count,
|
||||
}));
|
||||
chartData.value = result || [];
|
||||
opts.title.text = `{a|${total}}\n{b|总数}`;
|
||||
opts.series[0].data = result || [];
|
||||
return opts;
|
||||
});
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user