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/index.vue | 458 ++++++++++++++++++++++++++++++++-------------------------
1 files changed, 258 insertions(+), 200 deletions(-)
diff --git a/src/views/reportAnalysis/PSIDataAnalysis/index.vue b/src/views/reportAnalysis/PSIDataAnalysis/index.vue
index f81e482..ab6840c 100644
--- a/src/views/reportAnalysis/PSIDataAnalysis/index.vue
+++ b/src/views/reportAnalysis/PSIDataAnalysis/index.vue
@@ -1,50 +1,66 @@
<template>
- <div class="scale-container">
- <div class="data-dashboard" :style="{ transform: `scale(${scaleRatio})` }">
- <!-- 鍏ㄥ睆鎸夐挳 - 绉诲姩鍒板乏涓婅 -->
- <button class="fullscreen-btn" @click="toggleFullscreen" :title="isFullscreen ? '閫�鍑哄叏灞�' : '鍏ㄥ睆鏄剧ず'">
- <svg v-if="!isFullscreen" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
- <path d="M8 3v3a2 2 0 0 1-2 2H3m18 0h-3a2 2 0 0 1-2-2V3m0 18v-3a2 2 0 0 1 2-2h3M3 16h3a2 2 0 0 1 2 2v3"/>
- </svg>
- <svg v-else width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
- <path d="M8 3H5a2 2 0 0 0-2 2v3m18 0V5a2 2 0 0 0-2-2h-3m0 18h3a2 2 0 0 0 2-2v-3M3 16v3a2 2 0 0 0 2 2h3"/>
- </svg>
- </button>
-
- <!-- 椤堕儴鏍囬鏍� -->
- <div class="dashboard-header">
- <div class="factory-name">PSI 鏁版嵁鍒嗘瀽</div>
- </div>
-
- <!-- 涓昏鍐呭鍖哄煙 -->
- <div class="dashboard-content">
- <!-- 宸︿晶鍖哄煙 -->
- <div class="left-panel">
- <LeftTop />
-
- <LeftBottom />
- </div>
-
- <!-- 涓棿鍖哄煙 -->
- <div class="center-panel">
- <CenterTop />
- <CenterCenter/>
- <CenterBottom />
- </div>
-
- <!-- 鍙充晶鍖哄煙 -->
- <div class="right-panel">
- <RightBottom />
- <RightTop />
- </div>
- </div>
- </div>
- </div>
+ <div class="scale-container">
+ <div class="data-dashboard" :style="{ transform: `scale(${scaleRatio})` }">
+ <!-- 鍏ㄥ睆鎸夐挳 - 绉诲姩鍒板乏涓婅 -->
+ <button class="fullscreen-btn" @click="toggleFullscreen" :title="isFullscreen ? '閫�鍑哄叏灞�' : '鍏ㄥ睆鏄剧ず'">
+ <svg v-if="!isFullscreen" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
+ <path d="M8 3v3a2 2 0 0 1-2 2H3m18 0h-3a2 2 0 0 1-2-2V3m0 18v-3a2 2 0 0 1 2-2h3M3 16h3a2 2 0 0 1 2 2v3"/>
+ </svg>
+ <svg v-else width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
+ <path d="M8 3H5a2 2 0 0 0-2 2v3m18 0V5a2 2 0 0 0-2-2h-3m0 18h3a2 2 0 0 0 2-2v-3M3 16v3a2 2 0 0 0 2 2h3"/>
+ </svg>
+ </button>
+
+ <!-- 椤堕儴鏍囬鏍� -->
+ <div class="dashboard-header">
+ <div class="header-left"></div>
+ <div class="factory-name">PSI 鏁版嵁鍒嗘瀽</div>
+ <div class="header-right">
+ <div class="date-picker-wrapper">
+ <el-date-picker
+ v-model="psiDateRange"
+ type="daterange"
+ range-separator="鑷�"
+ start-placeholder="寮�濮嬫棩鏈�"
+ end-placeholder="缁撴潫鏃ユ湡"
+ value-format="YYYY-MM-DD"
+ :shortcuts="dateShortcuts"
+ @change="onDateRangeChange"
+ />
+ </div>
+ </div>
+ </div>
+
+ <!-- 涓昏鍐呭鍖哄煙 -->
+ <div class="dashboard-content">
+ <!-- 宸︿晶鍖哄煙 -->
+ <div class="left-panel">
+ <LeftTop />
+
+ <LeftBottom />
+ </div>
+
+ <!-- 涓棿鍖哄煙 -->
+ <div class="center-panel">
+ <CenterTop />
+ <CenterCenter/>
+ <CenterBottom />
+ </div>
+
+ <!-- 鍙充晶鍖哄煙 -->
+ <div class="right-panel">
+ <RightBottom />
+ <RightTop />
+ </div>
+ </div>
+ </div>
+ </div>
</template>
<script setup>
-import { ref, onMounted, onBeforeUnmount, nextTick, provide } from 'vue'
+import { ref, onMounted, onBeforeUnmount, nextTick, provide, reactive } from 'vue'
import autofit from 'autofit.js'
+import dayjs from 'dayjs'
import LeftBottom from './components/left-bottom.vue'
import CenterCenter from './components/center-center.vue'
import RightTop from '../dataDashboard/components/basic/right-top.vue'
@@ -66,6 +82,27 @@
// 鐢ㄦ埛store
const userStore = useUserStore()
+// 鏃ユ湡鑼冨洿绛涢��
+const psiDateRange = ref([])
+const psiDateRangeParams = ref({})
+const dateShortcuts = [
+ { text: '鏈湀', value: () => { const start = dayjs().startOf('month').format('YYYY-MM-DD'); const end = dayjs().format('YYYY-MM-DD'); return [start, end] } },
+ { text: '杩�7澶�', value: () => { const start = dayjs().subtract(6, 'day').format('YYYY-MM-DD'); const end = dayjs().format('YYYY-MM-DD'); return [start, end] } },
+ { text: '杩�30澶�', value: () => { const start = dayjs().subtract(29, 'day').format('YYYY-MM-DD'); const end = dayjs().format('YYYY-MM-DD'); return [start, end] } },
+ { text: '杩�90澶�', value: () => { const start = dayjs().subtract(89, 'day').format('YYYY-MM-DD'); const end = dayjs().format('YYYY-MM-DD'); return [start, end] } },
+]
+
+const onDateRangeChange = (val) => {
+ if (val && val.length === 2) {
+ psiDateRangeParams.value = { startDate: val[0], endDate: val[1] }
+ } else {
+ psiDateRangeParams.value = {}
+ }
+ dataDashboardRefreshTick.value++
+}
+
+provide('psiDateRange', psiDateRangeParams)
+
/** 涓� dataDashboard 鍏辩敤娉ㄥ叆鍚嶏紝瀛愮粍浠讹紙鍚鐢ㄧ殑 right-top/right-bottom锛夋瘡鍒嗛挓鍒锋柊 */
const DASHBOARD_REFRESH_MS = 60 * 1000
const dataDashboardRefreshTick = ref(0)
@@ -74,232 +111,253 @@
// 璁$畻缂╂斁姣斾緥
const calculateScale = () => {
- const container = document.querySelector('.scale-container')
- if (!container) return
-
- // 鑾峰彇瀹瑰櫒鐨勫疄闄呭昂瀵�
- const rect = container.getBoundingClientRect?.()
- const containerWidth = container.clientWidth || rect?.width || window.innerWidth
- const containerHeight = container.clientHeight || rect?.height || window.innerHeight
-
- // 璁$畻瀹介珮缂╂斁姣斾緥锛屽彇杈冨皬鍊间互淇濊瘉鍐呭瀹屾暣鏄剧ず锛堢瓑姣旂缉鏀撅級
- const scaleX = containerWidth / designWidth
- const scaleY = containerHeight / designHeight
- scaleRatio.value = Math.min(scaleX, scaleY)
+ const container = document.querySelector('.scale-container')
+ if (!container) return
+
+ // 鑾峰彇瀹瑰櫒鐨勫疄闄呭昂瀵�
+ const rect = container.getBoundingClientRect?.()
+ const containerWidth = container.clientWidth || rect?.width || window.innerWidth
+ const containerHeight = container.clientHeight || rect?.height || window.innerHeight
+
+ // 璁$畻瀹介珮缂╂斁姣斾緥锛屽彇杈冨皬鍊间互淇濊瘉鍐呭瀹屾暣鏄剧ず锛堢瓑姣旂缉鏀撅級
+ const scaleX = containerWidth / designWidth
+ const scaleY = containerHeight / designHeight
+ scaleRatio.value = Math.min(scaleX, scaleY)
}
// 绐楀彛澶у皬鍙樺寲澶勭悊
const handleResize = () => {
- // 寤惰繜鎵ц锛岀‘淇滵OM鏇存柊瀹屾垚
- setTimeout(() => {
- calculateScale()
- }, 100)
+ // 寤惰繜鎵ц锛岀‘淇滵OM鏇存柊瀹屾垚
+ setTimeout(() => {
+ calculateScale()
+ }, 100)
}
// 鍏ㄥ睆鍔熻兘瀹炵幇 - 閽堝scale-container鍏冪礌
const toggleFullscreen = () => {
- const element = document.querySelector('.scale-container')
-
- if (!element) return
-
- if (!isFullscreen.value) {
- if (element.requestFullscreen) {
- element.requestFullscreen()
- } else if (element.webkitRequestFullscreen) {
- element.webkitRequestFullscreen()
- } else if (element.msRequestFullscreen) {
- element.msRequestFullscreen()
- }
- } else {
- if (document.exitFullscreen) {
- document.exitFullscreen()
- } else if (document.webkitExitFullscreen) {
- document.webkitExitFullscreen()
- } else if (document.msExitFullscreen) {
- document.msExitFullscreen()
- }
- }
+ const element = document.querySelector('.scale-container')
+
+ if (!element) return
+
+ if (!isFullscreen.value) {
+ if (element.requestFullscreen) {
+ element.requestFullscreen()
+ } else if (element.webkitRequestFullscreen) {
+ element.webkitRequestFullscreen()
+ } else if (element.msRequestFullscreen) {
+ element.msRequestFullscreen()
+ }
+ } else {
+ if (document.exitFullscreen) {
+ document.exitFullscreen()
+ } else if (document.webkitExitFullscreen) {
+ document.webkitExitFullscreen()
+ } else if (document.msExitFullscreen) {
+ document.msExitFullscreen()
+ }
+ }
}
// 鐩戝惉鍏ㄥ睆鍙樺寲浜嬩欢
const handleFullscreenChange = () => {
- const fullscreenElement = document.fullscreenElement ||
- document.webkitFullscreenElement ||
- document.msFullscreenElement
- isFullscreen.value = fullscreenElement && fullscreenElement.classList.contains('scale-container')
-
- // 鍏ㄥ睆鐘舵�佸彉鍖栨椂锛屽欢杩熼噸鏂拌绠楃缉鏀炬瘮渚嬶紙纭繚DOM鏇存柊瀹屾垚锛�
- setTimeout(() => {
- calculateScale()
- }, 200)
+ const fullscreenElement = document.fullscreenElement ||
+ document.webkitFullscreenElement ||
+ document.msFullscreenElement
+ isFullscreen.value = fullscreenElement && fullscreenElement.classList.contains('scale-container')
+
+ // 鍏ㄥ睆鐘舵�佸彉鍖栨椂锛屽欢杩熼噸鏂拌绠楃缉鏀炬瘮渚嬶紙纭繚DOM鏇存柊瀹屾垚锛�
+ setTimeout(() => {
+ calculateScale()
+ }, 200)
}
// 鐢熷懡鍛ㄦ湡閽╁瓙
onMounted(() => {
- // 浣跨敤nextTick纭繚DOM瀹屽叏娓叉煋鍚庡啀鍒濆鍖�
- nextTick(() => {
- // 璁$畻鍒濆缂╂斁姣斾緥
- calculateScale()
- })
-
- window.addEventListener('resize', handleResize)
- window.addEventListener('fullscreenchange', handleFullscreenChange)
- window.addEventListener('webkitfullscreenchange', handleFullscreenChange)
- window.addEventListener('MSFullscreenChange', handleFullscreenChange)
-
- dashboardPollTimer = setInterval(() => {
- dataDashboardRefreshTick.value++
- }, DASHBOARD_REFRESH_MS)
+ // 浣跨敤nextTick纭繚DOM瀹屽叏娓叉煋鍚庡啀鍒濆鍖�
+ nextTick(() => {
+ // 璁$畻鍒濆缂╂斁姣斾緥
+ calculateScale()
+ })
+
+ window.addEventListener('resize', handleResize)
+ window.addEventListener('fullscreenchange', handleFullscreenChange)
+ window.addEventListener('webkitfullscreenchange', handleFullscreenChange)
+ window.addEventListener('MSFullscreenChange', handleFullscreenChange)
+
+ dashboardPollTimer = setInterval(() => {
+ dataDashboardRefreshTick.value++
+ }, DASHBOARD_REFRESH_MS)
})
onBeforeUnmount(() => {
- if (dashboardPollTimer) {
- clearInterval(dashboardPollTimer)
- dashboardPollTimer = null
- }
- window.removeEventListener('resize', handleResize)
- window.removeEventListener('fullscreenchange', handleFullscreenChange)
- window.removeEventListener('webkitfullscreenchange', handleFullscreenChange)
- window.removeEventListener('MSFullscreenChange', handleFullscreenChange)
- // 绉婚櫎鎴戜滑娣诲姞鐨刟utofit鍔ㄦ�佽皟鏁寸洃鍚櫒
- if (window._autofitUpdateHandler) {
- window.removeEventListener('resize', window._autofitUpdateHandler)
- delete window._autofitUpdateHandler
- }
- // 鍏抽棴autofit
- autofit.off()
+ if (dashboardPollTimer) {
+ clearInterval(dashboardPollTimer)
+ dashboardPollTimer = null
+ }
+ window.removeEventListener('resize', handleResize)
+ window.removeEventListener('fullscreenchange', handleFullscreenChange)
+ window.removeEventListener('webkitfullscreenchange', handleFullscreenChange)
+ window.removeEventListener('MSFullscreenChange', handleFullscreenChange)
+ // 绉婚櫎鎴戜滑娣诲姞鐨刟utofit鍔ㄦ�佽皟鏁寸洃鍚櫒
+ if (window._autofitUpdateHandler) {
+ window.removeEventListener('resize', window._autofitUpdateHandler)
+ delete window._autofitUpdateHandler
+ }
+ // 鍏抽棴autofit
+ autofit.off()
})
</script>
<style scoped>
/* 澶栭儴缂╂斁瀹瑰櫒 - 鍗犳嵁鏁翠釜瑙嗗彛 */
.scale-container {
-position: relative;
-width: 100%;
-/* 椤甸潰鍦ㄥ父瑙勫竷灞�涓嬶紙鏈夐《鏍忥級榛樿鍑忓幓 84px锛岄伩鍏嶅唴瀹硅瑁佸垏 */
-height: calc(100vh - 84px);
-display: flex;
-align-items: center;
-justify-content: center;
-background-color: #000;
-overflow: hidden;
+ position: relative;
+ width: 100%;
+ /* 椤甸潰鍦ㄥ父瑙勫竷灞�涓嬶紙鏈夐《鏍忥級榛樿鍑忓幓 84px锛岄伩鍏嶅唴瀹硅瑁佸垏 */
+ height: calc(100vh - 84px);
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ background-color: #000;
+ overflow: hidden;
}
/* 鍐呴儴鍐呭鍖哄煙 - 鍥哄畾璁捐灏哄 */
.data-dashboard {
-position: relative;
-width: 1920px;
-height: 1080px;
-background-image: url("@/assets/BI/backImage@2x.png");
-background-size: cover;
-background-position: center;
-background-repeat: no-repeat;
-transform-origin: center center;
+ position: relative;
+ width: 1920px;
+ height: 1080px;
+ background-image: url("@/assets/BI/backImage@2x.png");
+ background-size: cover;
+ background-position: center;
+ background-repeat: no-repeat;
+ transform-origin: center center;
}
/* 鍏ㄥ睆鐘舵�佺殑鏍峰紡 - 浣滅敤浜巗cale-container */
.scale-container:fullscreen {
-width: 100vw;
-height: 100vh;
-margin: 0;
-padding: 0;
-background-color: #000;
-z-index: 9999;
+ width: 100vw;
+ height: 100vh;
+ margin: 0;
+ padding: 0;
+ background-color: #000;
+ z-index: 9999;
}
/* Webkit娴忚鍣ㄥ墠缂� */
.scale-container:-webkit-full-screen {
-width: 100vw;
-height: 100vh;
-margin: 0;
-padding: 0;
-background-color: #000;
-z-index: 9999;
+ width: 100vw;
+ height: 100vh;
+ margin: 0;
+ padding: 0;
+ background-color: #000;
+ z-index: 9999;
}
/* MS娴忚鍣ㄥ墠缂� */
.scale-container:-ms-fullscreen {
-width: 100vw;
-height: 100vh;
-margin: 0;
-padding: 0;
-background-color: #000;
-z-index: 9999;
+ width: 100vw;
+ height: 100vh;
+ margin: 0;
+ padding: 0;
+ background-color: #000;
+ z-index: 9999;
}
.dashboard-header {
-position: relative;
-z-index: 1;
-height: 86px;
-background-image: url("@/assets/BI/biaoti.png");
-background-size: cover;
-background-repeat: no-repeat;
-display: flex;
-align-items: center;
-justify-content: center;
+ position: relative;
+ z-index: 1;
+ height: 86px;
+ background-image: url("@/assets/BI/biaoti.png");
+ background-size: cover;
+ background-repeat: no-repeat;
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+}
+
+.header-left {
+ width: 300px;
+ padding-left: 20px;
+ display: flex;
+ align-items: center;
+}
+
+.header-right {
+ width: 300px;
+ display: flex;
+ align-items: center;
+ justify-content: flex-end;
+ padding-right: 20px;
+}
+
+.date-picker-wrapper {
+ /* 鏃ユ湡閫夋嫨鍣ㄥ湪澶у睆涓婄殑鏍峰紡 */
+ --el-fill-color-blank: rgba(0, 20, 60, 0.8);
+ --el-border-color: rgba(0, 212, 255, 0.3);
+ --el-text-color-regular: #00d4ff;
+ --el-color-primary: #00d4ff;
}
.factory-name {
-font-weight: 600;
-font-size: 52px;
-color: #FFFFFF;
-top: 16px;
-position: absolute;
+ font-weight: 600;
+ font-size: 52px;
+ color: #FFFFFF;
}
.fullscreen-btn {
-position: absolute;
-top: 10px;
-left: 20px;
-width: 40px;
-height: 40px;
-background: rgba(0, 20, 60, 0.8);
-border: 1px solid rgba(0, 212, 255, 0.3);
-border-radius: 6px;
-color: #00d4ff;
-cursor: pointer;
-display: flex;
-align-items: center;
-justify-content: center;
-transition: all 0.3s;
-z-index: 10000;
+ position: absolute;
+ top: 10px;
+ left: 20px;
+ width: 40px;
+ height: 40px;
+ background: rgba(0, 20, 60, 0.8);
+ border: 1px solid rgba(0, 212, 255, 0.3);
+ border-radius: 6px;
+ color: #00d4ff;
+ cursor: pointer;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ transition: all 0.3s;
+ z-index: 10000;
}
.fullscreen-btn:hover {
-background: rgba(0, 30, 90, 0.9);
-border-color: rgba(0, 212, 255, 0.5);
+ background: rgba(0, 30, 90, 0.9);
+ border-color: rgba(0, 212, 255, 0.5);
}
.dashboard-content {
-position: relative;
-z-index: 1;
-display: flex;
-gap: 30px;
-padding: 0 30px;
-height: calc(100% - 86px);
-overflow: hidden;
+ position: relative;
+ z-index: 1;
+ display: flex;
+ gap: 30px;
+ padding: 0 30px;
+ height: calc(100% - 86px);
+ overflow: hidden;
}
/* 纭繚鍚勯潰鏉胯兘澶熸纭樉绀� */
.left-panel, .center-panel, .right-panel {
-overflow: hidden;
+ overflow: hidden;
}
.left-panel,
.right-panel {
-flex: 1;
-display: flex;
-flex-direction: column;
-gap: 24px;
-width: 520px;
+ flex: 1;
+ display: flex;
+ flex-direction: column;
+ gap: 24px;
+ width: 520px;
}
.center-panel {
-flex: 1.5;
-display: flex;
-flex-direction: column;
-gap: 20px;
+ flex: 1.5;
+ display: flex;
+ flex-direction: column;
+ gap: 20px;
}
</style>
\ No newline at end of file
--
Gitblit v1.9.3