| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614 |
- const fs = require('fs');
- const path = 'D:\\new_project\\plus-ui\\src\\views\\health\\pharmacy\\index.vue';
- const content = `<template>
- <div class="analysis-page">
- <div class="page-header">
- <div>
- <h2>全市药房药物分析</h2>
- <p class="subtitle">通过门诊发药、住院发药、药房进销存、药库进销存监控药房药库的情况</p>
- </div>
- </div>
- <!-- 一、门诊发药模块 -->
- <div class="section-title">一、门诊发药</div>
- <!-- 发药工作量维度 -->
- <div class="sub-title">1. 发药工作量维度</div>
- <div class="metrics-grid-4">
- <div class="metric-card">
- <div class="metric-icon" style="background:linear-gradient(135deg,#667eea,#764ba2)">
- <el-icon :size="24"><Document /></el-icon>
- </div>
- <div class="metric-content">
- <div class="metric-value">{{ stats.outpatientPrescriptionCount ?? '---' }}</div>
- <div class="metric-label">处方总数</div>
- </div>
- </div>
- <div class="metric-card">
- <div class="metric-icon" style="background:linear-gradient(135deg,#43e97b,#38f9d7)">
- <el-icon :size="24"><CircleCheck /></el-icon>
- </div>
- <div class="metric-content">
- <div class="metric-value">{{ stats.validPrescriptionCount ?? '---' }}</div>
- <div class="metric-label">有效发药处方数</div>
- </div>
- </div>
- <div class="metric-card">
- <div class="metric-icon" style="background:linear-gradient(135deg,#f5576c,#f093fb)">
- <el-icon :size="24"><CircleClose /></el-icon>
- </div>
- <div class="metric-content">
- <div class="metric-value">{{ stats.returnPrescriptionCount ?? '---' }}</div>
- <div class="metric-label">退方处方数</div>
- </div>
- </div>
- <div class="metric-card">
- <div class="metric-icon" style="background:linear-gradient(135deg,#4facfe,#00f2fe)">
- <el-icon :size="24"><User /></el-icon>
- </div>
- <div class="metric-content">
- <div class="metric-value">{{ stats.avgPrescriptionPerWindow ?? '---' }}</div>
- <div class="metric-label">窗口人均调配处方量</div>
- </div>
- </div>
- </div>
- <!-- 时效服务维度 -->
- <div class="sub-title">2. 时效服务维度</div>
- <div class="metrics-grid-2">
- <div class="metric-card">
- <div class="metric-icon" style="background:linear-gradient(135deg,#fa709a,#fee140)">
- <el-icon :size="24"><Clock /></el-icon>
- </div>
- <div class="metric-content">
- <div class="metric-value">{{ stats.avgWaitTime ?? '---' }}<span class="unit">分钟</span></div>
- <div class="metric-label">平均候药时长</div>
- </div>
- </div>
- <div class="metric-card">
- <div class="metric-icon" style="background:linear-gradient(135deg,#a18cd1,#fbc2eb)">
- <el-icon :size="24"><Warning /></el-icon>
- </div>
- <div class="metric-content">
- <div class="metric-value">{{ stats.overtimeWaitCount ?? '---' }}</div>
- <div class="metric-label">超时候药处方数量</div>
- </div>
- </div>
- </div>
- <!-- 药品消耗维度 + 处方异常维度 -->
- <div class="charts-row">
- <div class="chart-card">
- <div class="chart-header"><h3>3. 药品消耗维度 - 西药/中成药/中药饮片调配金额占比</h3></div>
- <div ref="outpatientDrugTypeChartRef" class="chart-container"></div>
- </div>
- <div class="chart-card">
- <div class="chart-header"><h3>4. 处方异常维度 - 退方原因统计占比</h3></div>
- <div ref="returnReasonChartRef" class="chart-container"></div>
- </div>
- </div>
- <!-- 二、住院发药模块 -->
- <div class="section-title">二、住院发药</div>
- <!-- 药品消耗维度 -->
- <div class="sub-title">1. 药品消耗维度</div>
- <div class="metrics-grid-2">
- <div class="metric-card">
- <div class="metric-icon" style="background:linear-gradient(135deg,#f093fb,#f5576c)">
- <el-icon :size="24"><Money /></el-icon>
- </div>
- <div class="metric-content">
- <div class="metric-value">{{ stats.inpatientDrugAmount ?? '---' }}<span class="unit">万元</span></div>
- <div class="metric-label">住院发药总金额</div>
- </div>
- </div>
- <div class="metric-card">
- <div class="metric-icon" style="background:linear-gradient(135deg,#667eea,#764ba2)">
- <el-icon :size="24"><Box /></el-icon>
- </div>
- <div class="metric-content">
- <div class="metric-value">{{ stats.inpatientDrugCount ?? '---' }}</div>
- <div class="metric-label">住院发药数量</div>
- </div>
- </div>
- </div>
- <!-- 摆药/发药工作量维度 + 退药管控维度 -->
- <div class="charts-row">
- <div class="chart-card">
- <div class="chart-header"><h3>2. 摆药/发药工作量维度</h3></div>
- <div class="inline-metrics">
- <div class="inline-metric">
- <div class="inline-value">{{ stats.avgDailyBatch ?? '---' }}</div>
- <div class="inline-label">日均摆药批次</div>
- </div>
- <div class="inline-metric">
- <div class="inline-value">{{ stats.avgDailyBag ?? '---' }}</div>
- <div class="inline-label">日均摆药袋数</div>
- </div>
- <div class="inline-metric">
- <div class="inline-value">{{ stats.ivMixBagCount ?? '---' }}</div>
- <div class="inline-label">静配输液调配袋数</div>
- </div>
- </div>
- </div>
- <div class="chart-card">
- <div class="chart-header"><h3>3. 退药管控维度</h3></div>
- <div class="inline-metrics">
- <div class="inline-metric">
- <div class="inline-value">{{ stats.inpatientReturnCount ?? '---' }}</div>
- <div class="inline-label">住院退药次数</div>
- </div>
- <div class="inline-metric">
- <div class="inline-value">{{ stats.inpatientReturnAmount ?? '---' }}<span class="unit">万元</span></div>
- <div class="inline-label">住院退药金额</div>
- </div>
- <div class="inline-metric">
- <div class="inline-value">{{ stats.inpatientReturnRate ?? '---' }}<span class="unit">%</span></div>
- <div class="inline-label">住院退药率</div>
- </div>
- </div>
- </div>
- </div>
- <!-- 三、药房进销存模块 -->
- <div class="section-title">三、药房进销存</div>
- <!-- 入库维度 -->
- <div class="sub-title">1. 入库维度</div>
- <div class="metrics-grid-5">
- <div class="metric-card">
- <div class="metric-icon" style="background:linear-gradient(135deg,#4facfe,#00f2fe)">
- <el-icon :size="24"><Money /></el-icon>
- </div>
- <div class="metric-content">
- <div class="metric-value">{{ stats.pharmacyInAmount ?? '---' }}<span class="unit">万元</span></div>
- <div class="metric-label">药房申领入库金额</div>
- </div>
- </div>
- <div class="metric-card">
- <div class="metric-icon" style="background:linear-gradient(135deg,#43e97b,#38f9d7)">
- <el-icon :size="24"><Box /></el-icon>
- </div>
- <div class="metric-content">
- <div class="metric-value">{{ stats.pharmacyInCount ?? '---' }}</div>
- <div class="metric-label">入库数量</div>
- </div>
- </div>
- <div class="metric-card">
- <div class="metric-icon" style="background:linear-gradient(135deg,#667eea,#764ba2)">
- <el-icon :size="24"><PieChart /></el-icon>
- </div>
- <div class="metric-content">
- <div class="metric-value">{{ stats.pharmacyWesternInRate ?? '---' }}<span class="unit">%</span></div>
- <div class="metric-label">西药入库占比</div>
- </div>
- </div>
- <div class="metric-card">
- <div class="metric-icon" style="background:linear-gradient(135deg,#f093fb,#f5576c)">
- <el-icon :size="24"><PieChart /></el-icon>
- </div>
- <div class="metric-content">
- <div class="metric-value">{{ stats.pharmacyChinesePatentInRate ?? '---' }}<span class="unit">%</span></div>
- <div class="metric-label">中成药入库占比</div>
- </div>
- </div>
- <div class="metric-card">
- <div class="metric-icon" style="background:linear-gradient(135deg,#fa709a,#fee140)">
- <el-icon :size="24"><PieChart /></el-icon>
- </div>
- <div class="metric-content">
- <div class="metric-value">{{ stats.pharmacyHerbalInRate ?? '---' }}<span class="unit">%</span></div>
- <div class="metric-label">中药饮片入库占比</div>
- </div>
- </div>
- </div>
- <!-- 出库消耗维度 -->
- <div class="sub-title">2. 出库消耗维度</div>
- <div class="metrics-grid-3">
- <div class="metric-card">
- <div class="metric-icon" style="background:linear-gradient(135deg,#667eea,#764ba2)">
- <el-icon :size="24"><FirstAidKit /></el-icon>
- </div>
- <div class="metric-content">
- <div class="metric-value">{{ stats.outpatientConsumeCount ?? '---' }}</div>
- <div class="metric-label">门诊发药消耗量</div>
- </div>
- </div>
- <div class="metric-card">
- <div class="metric-icon" style="background:linear-gradient(135deg,#4facfe,#00f2fe)">
- <el-icon :size="24"><Box /></el-icon>
- </div>
- <div class="metric-content">
- <div class="metric-value">{{ stats.inpatientConsumeCount ?? '---' }}</div>
- <div class="metric-label">住院摆药消耗量</div>
- </div>
- </div>
- <div class="metric-card">
- <div class="metric-icon" style="background:linear-gradient(135deg,#43e97b,#38f9d7)">
- <el-icon :size="24"><Switch /></el-icon>
- </div>
- <div class="metric-content">
- <div class="metric-value">{{ stats.internalTransferCount ?? '---' }}</div>
- <div class="metric-label">药房内部调拨数量</div>
- </div>
- </div>
- </div>
- <!-- 库存现状维度 -->
- <div class="sub-title">3. 库存现状维度</div>
- <div class="metrics-grid-4">
- <div class="metric-card">
- <div class="metric-icon" style="background:linear-gradient(135deg,#f5576c,#f093fb)">
- <el-icon :size="24"><Money /></el-icon>
- </div>
- <div class="metric-content">
- <div class="metric-value">{{ stats.currentStockAmount ?? '---' }}<span class="unit">万元</span></div>
- <div class="metric-label">当前库存总金额</div>
- </div>
- </div>
- <div class="metric-card">
- <div class="metric-icon" style="background:linear-gradient(135deg,#667eea,#764ba2)">
- <el-icon :size="24"><Coin /></el-icon>
- </div>
- <div class="metric-content">
- <div class="metric-value">{{ stats.westernStockAmount ?? '---' }}<span class="unit">万元</span></div>
- <div class="metric-label">西药库存金额</div>
- </div>
- </div>
- <div class="metric-card">
- <div class="metric-icon" style="background:linear-gradient(135deg,#4facfe,#00f2fe)">
- <el-icon :size="24"><Coin /></el-icon>
- </div>
- <div class="metric-content">
- <div class="metric-value">{{ stats.chinesePatentStockAmount ?? '---' }}<span class="unit">万元</span></div>
- <div class="metric-label">中成药库存金额</div>
- </div>
- </div>
- <div class="metric-card">
- <div class="metric-icon" style="background:linear-gradient(135deg,#43e97b,#38f9d7)">
- <el-icon :size="24"><Coin /></el-icon>
- </div>
- <div class="metric-content">
- <div class="metric-value">{{ stats.herbalStockAmount ?? '---' }}<span class="unit">万元</span></div>
- <div class="metric-label">中药饮片库存金额</div>
- </div>
- </div>
- </div>
- <div class="charts-row">
- <div class="chart-card" style="max-width:50%">
- <div class="chart-header"><h3>药房库存类型占比</h3></div>
- <div ref="stockTypeChartRef" class="chart-container"></div>
- </div>
- </div>
- <!-- 四、药库进销存模块 -->
- <div class="section-title">四、药库进销存</div>
- <!-- 采购入库维度 -->
- <div class="sub-title">1. 采购入库维度</div>
- <div class="metrics-grid-2">
- <div class="metric-card">
- <div class="metric-icon" style="background:linear-gradient(135deg,#667eea,#764ba2)">
- <el-icon :size="24"><Money /></el-icon>
- </div>
- <div class="metric-content">
- <div class="metric-value">{{ stats.purchaseAmount ?? '---' }}<span class="unit">万元</span></div>
- <div class="metric-label">药品采购入库金额</div>
- </div>
- </div>
- <div class="metric-card">
- <div class="metric-icon" style="background:linear-gradient(135deg,#43e97b,#38f9d7)">
- <el-icon :size="24"><List /></el-icon>
- </div>
- <div class="metric-content">
- <div class="metric-value">{{ stats.purchaseBatchCount ?? '---' }}</div>
- <div class="metric-label">入库批次</div>
- </div>
- </div>
- </div>
- <!-- 供应商占比 + 调拨出库 -->
- <div class="charts-row">
- <div class="chart-card">
- <div class="chart-header"><h3>各供应商采购金额占比</h3></div>
- <div ref="supplierChartRef" class="chart-container"></div>
- </div>
- <div class="chart-card">
- <div class="chart-header"><h3>2. 调拨出库维度 - 向各药房调拨金额</h3></div>
- <div ref="transferChartRef" class="chart-container"></div>
- </div>
- </div>
- <!-- 药库库存现状维度 -->
- <div class="sub-title">3. 库存现状维度</div>
- <div class="metrics-grid-4">
- <div class="metric-card">
- <div class="metric-icon" style="background:linear-gradient(135deg,#f5576c,#f093fb)">
- <el-icon :size="24"><Money /></el-icon>
- </div>
- <div class="metric-content">
- <div class="metric-value">{{ stats.drugStoreStockAmount ?? '---' }}<span class="unit">万元</span></div>
- <div class="metric-label">药库当前库存总金额</div>
- </div>
- </div>
- <div class="metric-card">
- <div class="metric-icon" style="background:linear-gradient(135deg,#667eea,#764ba2)">
- <el-icon :size="24"><Coin /></el-icon>
- </div>
- <div class="metric-content">
- <div class="metric-value">{{ stats.drugStoreWesternAmount ?? '---' }}<span class="unit">万元</span></div>
- <div class="metric-label">西药库存金额</div>
- </div>
- </div>
- <div class="metric-card">
- <div class="metric-icon" style="background:linear-gradient(135deg,#4facfe,#00f2fe)">
- <el-icon :size="24"><Coin /></el-icon>
- </div>
- <div class="metric-content">
- <div class="metric-value">{{ stats.drugStoreChinesePatentAmount ?? '---' }}<span class="unit">万元</span></div>
- <div class="metric-label">中成药库存金额</div>
- </div>
- </div>
- <div class="metric-card">
- <div class="metric-icon" style="background:linear-gradient(135deg,#43e97b,#38f9d7)">
- <el-icon :size="24"><Coin /></el-icon>
- </div>
- <div class="metric-content">
- <div class="metric-value">{{ stats.drugStoreHerbalAmount ?? '---' }}<span class="unit">万元</span></div>
- <div class="metric-label">中药饮片库存金额</div>
- </div>
- </div>
- </div>
- <div class="charts-row">
- <div class="chart-card" style="max-width:50%">
- <div class="chart-header"><h3>药库库存类型占比</h3></div>
- <div ref="drugStoreStockChartRef" class="chart-container"></div>
- </div>
- </div>
- <!-- 效期与损耗维度 -->
- <div class="sub-title">4. 效期与损耗维度</div>
- <div class="metrics-grid-2">
- <div class="metric-card">
- <div class="metric-icon" style="background:linear-gradient(135deg,#fa709a,#fee140)">
- <el-icon :size="24"><Warning /></el-icon>
- </div>
- <div class="metric-content">
- <div class="metric-value">{{ stats.expiredBatchCount ?? '---' }}</div>
- <div class="metric-label">过期药品批次数</div>
- </div>
- </div>
- <div class="metric-card">
- <div class="metric-icon" style="background:linear-gradient(135deg,#f5576c,#f093fb)">
- <el-icon :size="24"><Money /></el-icon>
- </div>
- <div class="metric-content">
- <div class="metric-value">{{ stats.expiredLossAmount ?? '---' }}<span class="unit">万元</span></div>
- <div class="metric-label">过期药品报损金额</div>
- </div>
- </div>
- </div>
- </div>
- </template>
- <script setup name="Pharmacy" lang="ts">
- import { ref, onMounted, onBeforeUnmount, nextTick } from 'vue';
- import * as echarts from 'echarts';
- import { Document, CircleCheck, CircleClose, User, Clock, Warning, Money, Box, PieChart, Switch, Coin, List, FirstAidKit } from '@element-plus/icons-vue';
- import { getPharmacyStats } from '@/api/health/pharmacy';
- import type { PharmacyStatsVO } from '@/api/health/pharmacy/types';
- const stats = ref<PharmacyStatsVO>({} as PharmacyStatsVO);
- const outpatientDrugTypeChartRef = ref<HTMLElement>();
- const returnReasonChartRef = ref<HTMLElement>();
- const stockTypeChartRef = ref<HTMLElement>();
- const supplierChartRef = ref<HTMLElement>();
- const transferChartRef = ref<HTMLElement>();
- const drugStoreStockChartRef = ref<HTMLElement>();
- let outpatientDrugTypeChart: echarts.ECharts | null = null;
- let returnReasonChart: echarts.ECharts | null = null;
- let stockTypeChart: echarts.ECharts | null = null;
- let supplierChart: echarts.ECharts | null = null;
- let transferChart: echarts.ECharts | null = null;
- let drugStoreStockChart: echarts.ECharts | null = null;
- function loadStats() {
- getPharmacyStats().then((response: any) => {
- stats.value = response.data || {};
- nextTick(() => {
- renderOutpatientDrugTypeChart();
- renderReturnReasonChart();
- renderStockTypeChart();
- renderSupplierChart();
- renderTransferChart();
- renderDrugStoreStockChart();
- });
- });
- }
- function renderOutpatientDrugTypeChart() {
- if (!outpatientDrugTypeChartRef.value) return;
- if (outpatientDrugTypeChart) outpatientDrugTypeChart.dispose();
- outpatientDrugTypeChart = echarts.init(outpatientDrugTypeChartRef.value);
- const list = stats.value.outpatientDrugTypeList || [];
- const data = list.map((item: any) => ({ name: item.name, value: Number(item.value) }));
- outpatientDrugTypeChart.setOption({
- tooltip: { trigger: 'item', formatter: '{b}: {c}万元 ({d}%)' },
- legend: { orient: 'vertical', left: 10, top: 'middle' },
- series: [{
- name: '药品消耗占比', type: 'pie', radius: ['40%', '70%'], center: ['60%', '50%'],
- data: data, itemStyle: { borderRadius: 4, borderColor: '#fff', borderWidth: 2 },
- label: { formatter: '{b}: {d}%' },
- emphasis: { itemStyle: { shadowBlur: 10, shadowOffsetX: 0, shadowColor: 'rgba(0,0,0,0.5)' } }
- }]
- });
- }
- function renderReturnReasonChart() {
- if (!returnReasonChartRef.value) return;
- if (returnReasonChart) returnReasonChart.dispose();
- returnReasonChart = echarts.init(returnReasonChartRef.value);
- const list = stats.value.returnReasonList || [];
- const data = list.map((item: any) => ({ name: item.name, value: Number(item.value) }));
- returnReasonChart.setOption({
- tooltip: { trigger: 'item', formatter: '{b}: {c}例 ({d}%)' },
- legend: { orient: 'vertical', left: 10, top: 'middle' },
- color: ['#f5576c', '#fa709a', '#a18cd1', '#667eea', '#4facfe'],
- series: [{
- name: '退方原因', type: 'pie', radius: ['40%', '70%'], center: ['60%', '50%'],
- data: data, itemStyle: { borderRadius: 4, borderColor: '#fff', borderWidth: 2 },
- label: { formatter: '{b}: {d}%' },
- emphasis: { itemStyle: { shadowBlur: 10, shadowOffsetX: 0, shadowColor: 'rgba(0,0,0,0.5)' } }
- }]
- });
- }
- function renderStockTypeChart() {
- if (!stockTypeChartRef.value) return;
- if (stockTypeChart) stockTypeChart.dispose();
- stockTypeChart = echarts.init(stockTypeChartRef.value);
- const list = stats.value.stockTypeList || [];
- const data = list.map((item: any) => ({ name: item.name, value: Number(item.value) }));
- stockTypeChart.setOption({
- tooltip: { trigger: 'item', formatter: '{b}: {c}万元 ({d}%)' },
- legend: { orient: 'vertical', left: 10, top: 'middle' },
- series: [{
- name: '药房库存占比', type: 'pie', radius: ['40%', '70%'], center: ['60%', '50%'],
- data: data, itemStyle: { borderRadius: 4, borderColor: '#fff', borderWidth: 2 },
- label: { formatter: '{b}: {d}%' },
- emphasis: { itemStyle: { shadowBlur: 10, shadowOffsetX: 0, shadowColor: 'rgba(0,0,0,0.5)' } }
- }]
- });
- }
- function renderSupplierChart() {
- if (!supplierChartRef.value) return;
- if (supplierChart) supplierChart.dispose();
- supplierChart = echarts.init(supplierChartRef.value);
- const list = stats.value.supplierList || [];
- const data = list.map((item: any) => ({ name: item.name, value: Number(item.value) }));
- supplierChart.setOption({
- tooltip: { trigger: 'item', formatter: '{b}: {c}万元 ({d}%)' },
- legend: { orient: 'vertical', left: 10, top: 'middle' },
- color: ['#667eea', '#4facfe', '#43e97b', '#fa709a', '#f5576c'],
- series: [{
- name: '供应商采购占比', type: 'pie', radius: ['40%', '70%'], center: ['60%', '50%'],
- data: data, itemStyle: { borderRadius: 4, borderColor: '#fff', borderWidth: 2 },
- label: { formatter: '{b}: {d}%' },
- emphasis: { itemStyle: { shadowBlur: 10, shadowOffsetX: 0, shadowColor: 'rgba(0,0,0,0.5)' } }
- }]
- });
- }
- function renderTransferChart() {
- if (!transferChartRef.value) return;
- if (transferChart) transferChart.dispose();
- transferChart = echarts.init(transferChartRef.value);
- const list = stats.value.transferList || [];
- const names = list.map((item: any) => item.name);
- const values = list.map((item: any) => Number(item.value));
- transferChart.setOption({
- tooltip: { trigger: 'axis', axisPointer: { type: 'shadow' } },
- grid: { top: 30, left: 100, right: 30, bottom: 30 },
- xAxis: { type: 'value', name: '万元' },
- yAxis: { type: 'category', data: names },
- series: [{
- name: '调拨金额', type: 'bar', data: values,
- itemStyle: {
- borderRadius: [0, 4, 4, 0],
- color: new echarts.graphic.LinearGradient(0, 0, 1, 0, [
- { offset: 0, color: '#4facfe' }, { offset: 1, color: '#00f2fe' }
- ])
- },
- barWidth: 24,
- label: { show: true, position: 'right', formatter: '{c}万元' }
- }]
- });
- }
- function renderDrugStoreStockChart() {
- if (!drugStoreStockChartRef.value) return;
- if (drugStoreStockChart) drugStoreStockChart.dispose();
- drugStoreStockChart = echarts.init(drugStoreStockChartRef.value);
- const list = stats.value.drugStoreStockTypeList || [];
- const data = list.map((item: any) => ({ name: item.name, value: Number(item.value) }));
- drugStoreStockChart.setOption({
- tooltip: { trigger: 'item', formatter: '{b}: {c}万元 ({d}%)' },
- legend: { orient: 'vertical', left: 10, top: 'middle' },
- series: [{
- name: '药库库存占比', type: 'pie', radius: ['40%', '70%'], center: ['60%', '50%'],
- data: data, itemStyle: { borderRadius: 4, borderColor: '#fff', borderWidth: 2 },
- label: { formatter: '{b}: {d}%' },
- emphasis: { itemStyle: { shadowBlur: 10, shadowOffsetX: 0, shadowColor: 'rgba(0,0,0,0.5)' } }
- }]
- });
- }
- function handleResize() {
- outpatientDrugTypeChart?.resize();
- returnReasonChart?.resize();
- stockTypeChart?.resize();
- supplierChart?.resize();
- transferChart?.resize();
- drugStoreStockChart?.resize();
- }
- onMounted(() => {
- loadStats();
- window.addEventListener('resize', handleResize);
- });
- onBeforeUnmount(() => {
- window.removeEventListener('resize', handleResize);
- outpatientDrugTypeChart?.dispose();
- returnReasonChart?.dispose();
- stockTypeChart?.dispose();
- supplierChart?.dispose();
- transferChart?.dispose();
- drugStoreStockChart?.dispose();
- });
- </script>
- <style scoped lang="scss">
- .analysis-page { padding: 20px; background: #f5f7fa; min-height: 100vh; }
- .page-header { background: white; padding: 20px 24px; border-radius: 8px; margin-bottom: 16px;
- h2 { margin: 0 0 4px; font-size: 22px; color: #2c3e50; }
- .subtitle { margin: 0; font-size: 13px; color: #909399; }
- }
- .section-title { font-size: 18px; font-weight: 700; color: #2c3e50; margin: 24px 0 12px; padding-left: 12px; border-left: 4px solid #667eea; }
- .sub-title { font-size: 15px; font-weight: 600; color: #606266; margin: 16px 0 10px; }
- .metrics-grid-2 { display: grid; grid-template-columns: repeat(2, 1fr); gap: 16px; margin-bottom: 16px; }
- .metrics-grid-3 { display: grid; grid-template-columns: repeat(3, 1fr); gap: 16px; margin-bottom: 16px; }
- .metrics-grid-4 { display: grid; grid-template-columns: repeat(4, 1fr); gap: 16px; margin-bottom: 16px; }
- .metrics-grid-5 { display: grid; grid-template-columns: repeat(5, 1fr); gap: 16px; margin-bottom: 16px; }
- .metric-card { background: white; padding: 20px; border-radius: 8px; display: flex; gap: 16px; align-items: center;
- .metric-icon { width: 56px; height: 56px; border-radius: 12px; display: flex; align-items: center; justify-content: center; color: white; flex-shrink: 0; }
- .metric-content { flex: 1; }
- .metric-value { font-size: 22px; font-weight: 700; color: #2c3e50;
- .unit { font-size: 13px; font-weight: 400; color: #909399; margin-left: 2px; }
- }
- .metric-label { font-size: 13px; color: #909399; margin-top: 4px; }
- }
- .charts-row { display: grid; grid-template-columns: 1fr 1fr; gap: 16px; margin-bottom: 16px; }
- .chart-card { background: white; border-radius: 8px; padding: 20px;
- .chart-header { margin-bottom: 12px; h3 { margin: 0; font-size: 15px; color: #2c3e50; } }
- .chart-container { height: 320px; }
- }
- .inline-metrics { display: flex; gap: 24px; padding: 20px 0; justify-content: space-around; }
- .inline-metric { text-align: center;
- .inline-value { font-size: 28px; font-weight: 700; color: #2c3e50;
- .unit { font-size: 13px; font-weight: 400; color: #909399; margin-left: 2px; }
- }
- .inline-label { font-size: 13px; color: #909399; margin-top: 8px; }
- }
- </style>
- `;
- fs.writeFileSync(path, content, 'utf8');
- console.log('File written successfully, size:', fs.statSync(path).size);
|