From 73d112ddc9bdfeb7eaaf3b7308cfb4dbeb470c89 Mon Sep 17 00:00:00 2001
From: gaoluyang <2820782392@qq.com>
Date: 星期五, 07 八月 2026 17:28:10 +0800
Subject: [PATCH] 天津_意博凯信 1.备件管理-新增独立备件出库功能入口,支持直接完成备件领用出库操作。 2.设备保养-支持按日期分组折叠展示,分组条目可展开查看明细;单条明细行末尾增加【保养完成】操作按钮,可单独办结单条保养任务;折叠汇总状态下,新增【一键保养完成】批量操作按钮,快速办结当前分组全部保养项。 3.设备巡检-按日期分组折叠展示,分组支持展开查看明细;每条巡检明细后增设【巡检完成】按钮,支持单独办结单条巡检记录;分组折叠未展开状态下,提供【一键巡检完成】批量操作,统一办结该分组下所有巡检任务。 4.增值税对比-优化数据展示逻辑,列表展示各订单增值税明细;页面右侧新增柱状可视化图表,直观对比进销项增值税数据。 5.管理驾驶舱-指标修改:将顶部「销售产品数」调整为「销售订单数」;时间筛选:页面左上角新增日期范围下拉筛选控件,所有统计指标标注当前筛选时段;

---
 src/views/reportAnalysis/PSIDataAnalysis/components/left-bottom.vue |  356 +++++++++++++++++++++++++++++-----------------------------
 1 files changed, 179 insertions(+), 177 deletions(-)

diff --git a/src/views/reportAnalysis/PSIDataAnalysis/components/left-bottom.vue b/src/views/reportAnalysis/PSIDataAnalysis/components/left-bottom.vue
index 65a72fe..6a4ffa6 100644
--- a/src/views/reportAnalysis/PSIDataAnalysis/components/left-bottom.vue
+++ b/src/views/reportAnalysis/PSIDataAnalysis/components/left-bottom.vue
@@ -1,24 +1,24 @@
 <template>
-  <div>
-    <PanelHeader title="閲囪喘鍝佸垎甯�" />
-    <div class="main-panel panel-item-customers">
-      <CarouselCards :items="cardItems" :visible-count="3" />
-      <div class="pie-chart-wrapper" ref="pieWrapperRef">
-        <div class="pie-background" ref="pieBackgroundRef"></div>
-        <Echarts
-          ref="chart"
-          :chartStyle="chartStyle"
-          :legend="landLegend"
-          :series="landSeries"
-          :tooltip="landTooltip"
-          :color="landColors"
-          :options="pieOptions"
-          style="height: 320px"
-          class="land-chart"
-        />
-      </div>
-    </div>
-  </div>
+	<div>
+		<PanelHeader title="閲囪喘鍝佸垎甯�" />
+		<div class="main-panel panel-item-customers">
+			<CarouselCards :items="cardItems" :visible-count="3" />
+			<div class="pie-chart-wrapper" ref="pieWrapperRef">
+				<div class="pie-background" ref="pieBackgroundRef"></div>
+				<Echarts
+					ref="chart"
+					:chartStyle="chartStyle"
+					:legend="landLegend"
+					:series="landSeries"
+					:tooltip="landTooltip"
+					:color="landColors"
+					:options="pieOptions"
+					style="height: 320px"
+					class="land-chart"
+				/>
+			</div>
+		</div>
+	</div>
 </template>
 
 <script setup>
@@ -28,6 +28,8 @@
 import CarouselCards from './CarouselCards.vue'
 import { rawMaterialPurchaseAmountRatio } from '@/api/viewIndex.js'
 import { useChartBackground } from '@/hooks/useChartBackground.js'
+
+const dateRange = inject('psiDateRange', null)
 
 const pieWrapperRef = ref(null)
 const pieBackgroundRef = ref(null)
@@ -39,11 +41,11 @@
  * @return {杩斿洖绫诲瀷璇存槑}
  */
 function array2obj(array, key) {
-  const resObj = {}
-  for (let i = 0; i < array.length; i++) {
-    resObj[array[i][key]] = array[i]
-  }
-  return resObj
+	const resObj = {}
+	for (let i = 0; i < array.length; i++) {
+		resObj[array[i][key]] = array[i]
+	}
+	return resObj
 }
 
 // 鏁版嵁鍒楄〃锛堟潵鑷帴鍙o級
@@ -59,204 +61,204 @@
 
 // 鍥句緥閰嶇疆锛堝彸渚х珫鎺掞級
 const landLegend = computed(() => {
-  const data = dataList.value.map((d, idx) => ({
-    name: d.name,
-    icon: 'circle',
-    textStyle: {
-      fontSize: 18,
-      color: landColors[idx % landColors.length],
-    },
-  }))
-
-  return {
-    orient: 'vertical',
-    top: 'center',
-    left: '52%',
-    itemGap: 30,
-    data: data,
-    formatter: function (name) {
-      const item = landObjData.value[name]
-      if (!item) return name
-      return `{title|${name}}{value|${item.value}}{unit|鍏儅{percent|${item.rate}}{unit|%}`
-    },
-    textStyle: {
-      rich: {
-        value: {
-          color: '#43e8fc',
-          fontSize: 14,
-          fontWeight: 600,
-          padding: [0, 0, 0, 10],
-        },
-        unit: {
-          color: '#82baff',
-          fontSize: 12,
-          fontWeight: 600,
-          padding: [0, 10, 0, 0],
-        },
-        percent: {
-          color: '#43e8fc',
-          fontSize: 14,
-          fontWeight: 600,
-          padding: [0, 0, 0, 0],
-        },
-        title: {
-          fontSize: 12,
-          padding: [0, 0, 0, 0],
-        },
-      },
-    },
-  }
+	const data = dataList.value.map((d, idx) => ({
+		name: d.name,
+		icon: 'circle',
+		textStyle: {
+			fontSize: 18,
+			color: landColors[idx % landColors.length],
+		},
+	}))
+	
+	return {
+		orient: 'vertical',
+		top: 'center',
+		left: '52%',
+		itemGap: 30,
+		data: data,
+		formatter: function (name) {
+			const item = landObjData.value[name]
+			if (!item) return name
+			return `{title|${name}}{value|${item.value}}{unit|鍏儅{percent|${item.rate}}{unit|%}`
+		},
+		textStyle: {
+			rich: {
+				value: {
+					color: '#43e8fc',
+					fontSize: 14,
+					fontWeight: 600,
+					padding: [0, 0, 0, 10],
+				},
+				unit: {
+					color: '#82baff',
+					fontSize: 12,
+					fontWeight: 600,
+					padding: [0, 10, 0, 0],
+				},
+				percent: {
+					color: '#43e8fc',
+					fontSize: 14,
+					fontWeight: 600,
+					padding: [0, 0, 0, 0],
+				},
+				title: {
+					fontSize: 12,
+					padding: [0, 0, 0, 0],
+				},
+			},
+		},
+	}
 })
 
 // 鎻愮ず妗�
 const landTooltip = {
-  trigger: 'item',
-  formatter: '{a} <br/>{b} : {c}鍏� ({d}%)',
+	trigger: 'item',
+	formatter: '{a} <br/>{b} : {c}鍏� ({d}%)',
 }
 
 // 鍙屽眰鐜舰楗煎浘
 const landSeries = ref([
-  {
-    name: '浜у搧閲囪喘閲戦鍒嗘瀽',
-    type: 'pie',
-    radius: ['40%', '60%'],
-    center: ['25%', '50%'],
-    itemStyle: {
-      borderColor: '#0a1c3a',
-      borderWidth: 2,
-      color: function (params) {
-        return landColors[params.dataIndex % landColors.length]
-      },
-    },
-    label: {
-      show: false
-    },
-    minAngle: 15,
-    data: dataList.value,
-    animationType: 'scale',
-    animationEasing: 'elasticOut',
-    animationDelay: function () {
-      return Math.random() * 200
-    },
-  },
-  {
-    // 鍐呭湀
-    type: 'pie',
-    radius: ['40%', '45%'],
-    center: ['25%', '50%'],
-    silent: true,
-    label: {
-      show: false,
-    },
-    labelLine: {
-      show: false,
-    },
-    itemStyle: {
-      color: 'rgba(0, 127, 255, 0.25)',
-    },
-    data: [1],
-  },
+	{
+		name: '浜у搧閲囪喘閲戦鍒嗘瀽',
+		type: 'pie',
+		radius: ['40%', '60%'],
+		center: ['25%', '50%'],
+		itemStyle: {
+			borderColor: '#0a1c3a',
+			borderWidth: 2,
+			color: function (params) {
+				return landColors[params.dataIndex % landColors.length]
+			},
+		},
+		label: {
+			show: false
+		},
+		minAngle: 15,
+		data: dataList.value,
+		animationType: 'scale',
+		animationEasing: 'elasticOut',
+		animationDelay: function () {
+			return Math.random() * 200
+		},
+	},
+	{
+		// 鍐呭湀
+		type: 'pie',
+		radius: ['40%', '45%'],
+		center: ['25%', '50%'],
+		silent: true,
+		label: {
+			show: false,
+		},
+		labelLine: {
+			show: false,
+		},
+		itemStyle: {
+			color: 'rgba(0, 127, 255, 0.25)',
+		},
+		data: [1],
+	},
 ])
 
 const chartStyle = {
-  width: '100%',
-  height: '100%',
+	width: '100%',
+	height: '100%',
 }
 
 const pieOptions = {
-  backgroundColor: 'transparent',
-  textStyle: { color: '#B8C8E0' },
+	backgroundColor: 'transparent',
+	textStyle: { color: '#B8C8E0' },
 }
 
 // 浣跨敤灏佽鐨勮儗鏅綅缃皟鏁存柟娉�
 // 鍥捐〃涓績鏄� ['25%', '50%']锛岃儗鏅渶瑕佸榻愬埌杩欎釜浣嶇疆
 const { init: initBackground, cleanup: cleanupBackground } = useChartBackground({
-  wrapperRef: pieWrapperRef,
-  backgroundRef: pieBackgroundRef,
-  left: '25%',       // 鍥捐〃涓績 X 鏄� 25%
-  top: '50%',        // 鍥捐〃涓績 Y 鏄� 50%
-  offsetX: '-51.5%', // X 杞村亸绉�
-  offsetY: '-50%',   // Y 杞村亸绉�
-  watchData: dataList // 鐩戝惉鏁版嵁鍙樺寲锛岃嚜鍔ㄨ皟鏁翠綅缃�
+	wrapperRef: pieWrapperRef,
+	backgroundRef: pieBackgroundRef,
+	left: '25%',       // 鍥捐〃涓績 X 鏄� 25%
+	top: '50%',        // 鍥捐〃涓績 Y 鏄� 50%
+	offsetX: '-51.5%', // X 杞村亸绉�
+	offsetY: '-50%',   // Y 杞村亸绉�
+	watchData: dataList // 鐩戝惉鏁版嵁鍙樺寲锛岃嚜鍔ㄨ皟鏁翠綅缃�
 })
 
 const fetchData = () => {
-  rawMaterialPurchaseAmountRatio()
-    .then((res) => {
-      if (res.code === 200 && Array.isArray(res.data)) {
-        const items = res.data
-        cardItems.value = items.map((item) => ({
-          label: item.name,
-          value: item.value,
-          unit: '鍏�',
-          rate: item.rate,
-        }))
-        dataList.value = items.map((it) => ({
-          name: it.name,
-          value: parseFloat(it.value) || 0,
-          rate: it.rate,
-          children: [],
-        }))
-        landSeries.value[0].data = dataList.value
-      }
-    })
-    .catch((err) => {
-      console.error('鑾峰彇鍘熸潗鏂欓噰璐噾棰濆崰姣斿け璐�:', err)
-    })
+	rawMaterialPurchaseAmountRatio(dateRange?.value || undefined)
+		.then((res) => {
+			if (res.code === 200 && Array.isArray(res.data)) {
+				const items = res.data
+				cardItems.value = items.map((item) => ({
+					label: item.name,
+					value: item.value,
+					unit: '鍏�',
+					rate: item.rate,
+				}))
+				dataList.value = items.map((it) => ({
+					name: it.name,
+					value: parseFloat(it.value) || 0,
+					rate: it.rate,
+					children: [],
+				}))
+				landSeries.value[0].data = dataList.value
+			}
+		})
+		.catch((err) => {
+			console.error('鑾峰彇鍘熸潗鏂欓噰璐噾棰濆崰姣斿け璐�:', err)
+		})
 }
 
 const dataDashboardRefreshTick = inject('dataDashboardRefreshTick', null)
 if (dataDashboardRefreshTick) {
-  watch(dataDashboardRefreshTick, () => {
-    fetchData()
-  })
+	watch(dataDashboardRefreshTick, () => {
+		fetchData()
+	})
 }
 
 onMounted(() => {
-  fetchData()
-  initBackground()
+	fetchData()
+	initBackground()
 })
 
 onBeforeUnmount(() => {
-  cleanupBackground()
+	cleanupBackground()
 })
 </script>
 
 <style scoped>
 .main-panel {
-  display: flex;
-  flex-direction: column;
-  gap: 20px;
+	display: flex;
+	flex-direction: column;
+	gap: 20px;
 }
 
 .panel-item-customers {
-  border: 1px solid #1a58b0;
-  padding: 18px;
-  width: 100%;
-  height: 449px;
+	border: 1px solid #1a58b0;
+	padding: 18px;
+	width: 100%;
+	height: 449px;
 }
 
 .pie-chart-wrapper {
-  position: relative;
-  width: 100%;
-  height: 320px;
-  background: transparent;
+	position: relative;
+	width: 100%;
+	height: 320px;
+	background: transparent;
 }
 
 
 .pie-background {
-  position: absolute;
-  width: 310px;
-  height: 310px;
-  background-image: url('@/assets/BI/鐜懓鍥捐竟妗�.png');
-  background-size: contain;
-  background-position: center;
-  background-repeat: no-repeat;
-  z-index: 1;
-  pointer-events: none;
-  /* 浣嶇疆鐢� JS 鍔ㄦ�佽缃紝榛樿灞呬腑 */
-  left: 25%;
-  top: 50%;
-  transform: translate(-51.5%, -50%);
+	position: absolute;
+	width: 310px;
+	height: 310px;
+	background-image: url('@/assets/BI/鐜懓鍥捐竟妗�.png');
+	background-size: contain;
+	background-position: center;
+	background-repeat: no-repeat;
+	z-index: 1;
+	pointer-events: none;
+	/* 浣嶇疆鐢� JS 鍔ㄦ�佽缃紝榛樿灞呬腑 */
+	left: 25%;
+	top: 50%;
+	transform: translate(-51.5%, -50%);
 }
 </style>

--
Gitblit v1.9.3