| | |
| | | |
| | | <!-- 顶部标题栏 --> |
| | | <div class="dashboard-header"> |
| | | <div class="factory-name">{{ userStore.currentFactoryName }}</div> |
| | | </div> |
| | | |
| | | <!-- 主要内容区域 --> |
| | |
| | | |
| | | <!-- 质量统计 --> |
| | | <div class="panel-header"> |
| | | <span class="panel-title">质量统计</span> |
| | | <span class="panel-title">近4个月质量统计</span> |
| | | </div> |
| | | <div class="main-panel"> |
| | | <div class="panel-item-customers"> |
| | |
| | | </div> |
| | | <div class="equipment-items"> |
| | | <div class="equipment-item"> |
| | | <span class="equipment-value">{{equipmentNum}}</span> |
| | | <span class="equipment-value">21</span> |
| | | <span class="equipment-label">设备总数</span> |
| | | </div> |
| | | <div class="equipment-item"> |
| | | <span class="equipment-value">{{equipmentRepair}}</span> |
| | | <span class="equipment-value">3</span> |
| | | <span class="equipment-label">待维修设备</span> |
| | | </div> |
| | | <div class="equipment-item"> |
| | | <span class="equipment-value">{{equipmentMaintain}}</span> |
| | | <span class="equipment-value">4</span> |
| | | <span class="equipment-label">待保养设备</span> |
| | | </div> |
| | | <div class="equipment-item"> |
| | | <!-- <div class="equipment-item"> |
| | | <span class="equipment-value">{{totalMeasuring}}</span> |
| | | <span class="equipment-label">计量器具总数</span> |
| | | </div> --> |
| | | </div> |
| | | </div> |
| | | <!-- 合格率 --> |
| | | <div class="equipment-stats"> |
| | | <div class="equipment-header"> |
| | | <img src="@/assets/BI/shujutongjiicon@2x.png" alt="图标" class="equipment-icon" /> |
| | | <span class="equipment-title">质检统计</span> |
| | | </div> |
| | | <div class="equipment-items"> |
| | | <div class="equipment-item"> |
| | | <span class="equipment-value">{{rawMaterialQualifiedRate}}%</span> |
| | | <span class="equipment-label">原材料合格率</span> |
| | | </div> |
| | | <div class="equipment-item"> |
| | | <span class="equipment-value">{{processQualifiedRate}}%</span> |
| | | <span class="equipment-label">过程合格率</span> |
| | | </div> |
| | | <div class="equipment-item"> |
| | | <span class="equipment-value">{{factoryQualifiedRate}}%</span> |
| | | <span class="equipment-label">出厂合格率</span> |
| | | </div> |
| | | <div class="equipment-item"> |
| | | <span class="equipment-value">{{inventoryTurnoverRate}}%</span> |
| | | <span class="equipment-label">库存周转率</span> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | |
| | | <!-- 事件名称 --> |
| | | <div class="event-info"> |
| | | <div class="event-header"> |
| | | <img src="@/assets/BI/shijianmingxiicon@2x.png" alt="图标" class="event-icon" /> |
| | | <span class="event-title">事件名称</span> |
| | | </div> |
| | | <div class="event-content"> |
| | | <ul class="todo-list" v-if="todoList.length > 0" ref="refTodoList"> |
| | | <li v-for="item in todoList" :key="item.id"> |
| | | <div style="display: flex;flex-direction: column;justify-content: space-between;width: 100%;gap: 20px"> |
| | | <div style="display: flex;justify-content: space-between;align-items: center;"> |
| | | <div class="todo-title">待办编号:{{item.approveId}}</div> |
| | | <div class="todo-division">部门:{{item.approveDeptName}}</div> |
| | | <div class="todo-time">{{item.approveTime}}</div> |
| | | </div> |
| | | <div class="todo-division">待办事由:{{item.approveReason}}</div> |
| | | </div> |
| | | </li> |
| | | </ul> |
| | | <div v-else style="text-align: center"> |
| | | 暂无数据 |
| | | </div> |
| | | </div> |
| | | </div> |
| | | <!-- <div class="event-info">--> |
| | | <!-- <div class="event-header">--> |
| | | <!-- <img src="@/assets/BI/shijianmingxiicon@2x.png" alt="图标" class="event-icon" />--> |
| | | <!-- <span class="event-title">事件名称</span>--> |
| | | <!-- </div>--> |
| | | <!-- <div class="event-content">--> |
| | | <!-- <ul class="todo-list" v-if="todoList.length > 0" ref="refTodoList"> --> |
| | | <!-- <li v-for="item in todoList" :key="item.id"> --> |
| | | <!-- <div style="display: flex;flex-direction: column;justify-content: space-between;width: 100%;gap: 20px"> --> |
| | | <!-- <div style="display: flex;justify-content: space-between;align-items: center;"> --> |
| | | <!-- <div class="todo-title">待办编号:{{item.approveId}}</div> --> |
| | | <!-- <div class="todo-division">部门:{{item.approveDeptName}}</div> --> |
| | | <!-- <div class="todo-time">{{item.approveTime}}</div> --> |
| | | <!-- </div> --> |
| | | <!-- <div class="todo-division">待办事由:{{item.approveReason}}</div> --> |
| | | <!-- </div> --> |
| | | <!-- </li> --> |
| | | <!-- </ul>--> |
| | | <!-- <div v-else style="text-align: center">--> |
| | | <!-- 暂无数据--> |
| | | <!-- </div>--> |
| | | <!-- </div>--> |
| | | <!-- </div>--> |
| | | |
| | | <div class="financial-header"> |
| | | <span class="financial-title">财务分析</span> |
| | |
| | | :xAxis="xAxis3" |
| | | :yAxis="yAxis3" |
| | | :options="{backgroundColor: 'transparent', textStyle: {color: '#B8C8E0'}}" |
| | | style="height: 300px"></Echarts> |
| | | style="height: 280px"></Echarts> |
| | | </div> |
| | | </div> |
| | | </div> |
| | |
| | | <div class="panel-item-customers"> |
| | | <div style="display: flex;justify-content: space-between;margin-bottom: 20px;"> |
| | | <div class="section-title">应收应付统计</div> |
| | | <el-radio-group v-model="radio1" size="large" @change="statisticsReceivable" class="custom-radio-group"> |
| | | <el-radio-button label="按周" :value="1" /> |
| | | <el-radio-button label="按月" :value="2" /> |
| | | <el-radio-button label="按季度" :value="3" /> |
| | | </el-radio-group> |
| | | <!-- <el-radio-group v-model="radio1" size="large" @change="statisticsReceivable" class="custom-radio-group">--> |
| | | <!-- <el-radio-button label="按周" :value="1" />--> |
| | | <!-- <el-radio-button label="按月" :value="2" />--> |
| | | <!-- <el-radio-button label="按季度" :value="3" />--> |
| | | <!-- </el-radio-group>--> |
| | | </div> |
| | | <Echarts ref="chart" |
| | | :color="barColors2" |
| | |
| | | import { ref, onMounted, onBeforeUnmount, nextTick } from 'vue' |
| | | import autofit from 'autofit.js' |
| | | import Echarts from "@/components/Echarts/echarts.vue"; |
| | | import useUserStore from '@/store/modules/user' |
| | | import { |
| | | analysisCustomerContractAmounts, getAmountHalfYear, |
| | | homeTodos, |
| | | homeTodos, qualityProductQualifiedRate, |
| | | qualityStatistics, |
| | | statisticsReceivablePayable |
| | | } from "@/api/viewIndex.js"; |
| | |
| | | |
| | | // 全屏相关状态 |
| | | const isFullscreen = ref(false); |
| | | |
| | | // 用户store |
| | | const userStore = useUserStore() |
| | | |
| | | // 响应式数据 |
| | | const currentTime = ref('') |
| | |
| | | const equipmentRepair = ref(0) |
| | | const equipmentMaintain = ref(0) |
| | | const totalMeasuring = ref(0) |
| | | const rawMaterialQualifiedRate = ref(0) |
| | | const processQualifiedRate = ref(0) |
| | | const factoryQualifiedRate = ref(0) |
| | | const inventoryTurnoverRate = ref(0) |
| | | const pieTooltip = reactive({ |
| | | trigger: 'item', |
| | | formatter: function (params) { |
| | |
| | | const barLegend = { |
| | | show: true, |
| | | textStyle: { color: '#B8C8E0' }, |
| | | data: ['原材料不合格数', '过程不合格数', '出厂不合格数'] |
| | | data: ['原材料合格数', '过程合格数', '出厂合格数'] |
| | | } |
| | | const barLegend1 = { |
| | | show: true, |
| | |
| | | ]) |
| | | const barSeries1 = ref([ |
| | | { |
| | | name: '原材料不合格数', |
| | | name: '原材料合格数', |
| | | type: 'bar', |
| | | barGap: 0, |
| | | emphasis: { |
| | |
| | | data: [] |
| | | }, |
| | | { |
| | | name: '过程不合格数', |
| | | name: '过程合格数', |
| | | type: 'bar', |
| | | emphasis: { |
| | | focus: 'series' |
| | |
| | | data: [] |
| | | }, |
| | | { |
| | | name: '出厂不合格数', |
| | | name: '出厂合格数', |
| | | type: 'bar', |
| | | emphasis: { |
| | | focus: 'series' |
| | |
| | | qualityStatisticsObject.value.supplierNum = res.data.supplierNum |
| | | qualityStatisticsObject.value.processNum = res.data.processNum |
| | | qualityStatisticsObject.value.factoryNum = res.data.factoryNum |
| | | }) |
| | | } |
| | | // 产品合格率 |
| | | const qualityProductQualifiedRateInfo = () => { |
| | | qualityProductQualifiedRate().then((res) => { |
| | | rawMaterialQualifiedRate.value = res.data.rawMaterialQualifiedRate |
| | | processQualifiedRate.value = res.data.processQualifiedRate |
| | | factoryQualifiedRate.value = res.data.factoryQualifiedRate |
| | | inventoryTurnoverRate.value = res.data.inventoryTurnoverRate |
| | | }) |
| | | } |
| | | // 财务统计 |
| | |
| | | updateTime() |
| | | timer.value = setInterval(updateTime, 1000) |
| | | } |
| | | |
| | | // 客户饼图 |
| | | const initCustomerPieChart = () => { |
| | | if (!customerPieChartRef.value) return |
| | | const chart = echarts.init(customerPieChartRef.value) |
| | | const option = { |
| | | tooltip: { |
| | | trigger: 'item', |
| | | formatter: '{a} <br/>{b}: {c} ({d}%)' |
| | | }, |
| | | series: [{ |
| | | name: '客户分布', |
| | | type: 'pie', |
| | | radius: ['40%', '70%'], |
| | | center: ['50%', '50%'], |
| | | data: [ |
| | | { value: 25, name: '潜在客户', itemStyle: { color: '#00d4ff' } }, |
| | | { value: 25, name: '意向客户', itemStyle: { color: '#0099ff' } }, |
| | | { value: 25, name: '签约客户', itemStyle: { color: '#6666ff' } }, |
| | | { value: 25, name: '流失客户', itemStyle: { color: '#ffcc00' } } |
| | | ], |
| | | label: { |
| | | show: false |
| | | } |
| | | }] |
| | | } |
| | | chart.setOption(option) |
| | | charts.value.push(chart) |
| | | } |
| | | |
| | | // 销售柱状图 |
| | | const initSalesBarChart = () => { |
| | | if (!salesBarChartRef.value) return |
| | | const chart = echarts.init(salesBarChartRef.value) |
| | | const option = { |
| | | tooltip: { |
| | | trigger: 'axis' |
| | | }, |
| | | xAxis: { |
| | | type: 'category', |
| | | data: ['6/9', '6/10', '6/11', '6/12', '6/13'], |
| | | axisLine: { lineStyle: { color: '#333' } }, |
| | | axisLabel: { color: '#B8C8E0' }, |
| | | }, |
| | | yAxis: { |
| | | type: 'value', |
| | | axisLine: { show: false }, |
| | | axisTick: { show: false }, |
| | | axisLabel: { color: '#B8C8E0' }, |
| | | splitLine: { lineStyle: { color: '#333' } } |
| | | }, |
| | | series: [{ |
| | | data: [150, 200, 180, 220, 190], |
| | | type: 'bar', |
| | | itemStyle: { |
| | | color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [ |
| | | { offset: 0, color: 'rgba(0,164,237,0)' }, |
| | | { offset: 1, color: '#4EE4FF' } |
| | | ]) |
| | | } |
| | | }] |
| | | } |
| | | chart.setOption(option) |
| | | charts.value.push(chart) |
| | | } |
| | | |
| | | // 数据统计横向柱状图 |
| | | const initDataBarChart = () => { |
| | | if (!dataBarChartRef.value) return |
| | | const chart = echarts.init(dataBarChartRef.value) |
| | | const option = { |
| | | tooltip: { |
| | | trigger: 'axis' |
| | | }, |
| | | grid: { |
| | | left: '10%', |
| | | right: '10%', |
| | | top: '10%', |
| | | bottom: '10%' |
| | | }, |
| | | xAxis: { |
| | | type: 'value', |
| | | axisLine: { show: false }, |
| | | axisTick: { show: false }, |
| | | axisLabel: { color: '#B8C8E0' }, |
| | | splitLine: { lineStyle: { color: '#333' } } |
| | | }, |
| | | yAxis: { |
| | | type: 'category', |
| | | data: ['设计数据', '财务数据', '生产数据', '合同数据'], |
| | | axisLine: { lineStyle: { color: '#333' } }, |
| | | axisLabel: { color: '#B8C8E0' } |
| | | }, |
| | | series: [{ |
| | | data: [80, 100, 120, 90], |
| | | type: 'bar', |
| | | itemStyle: { |
| | | color: new echarts.graphic.LinearGradient(0, 0, 1, 0, [ |
| | | { offset: 0, color: 'rgba(0,164,237,0)' }, |
| | | { offset: 1, color: '#4EE4FF' } |
| | | ]) |
| | | } |
| | | }] |
| | | } |
| | | chart.setOption(option) |
| | | charts.value.push(chart) |
| | | } |
| | | |
| | | // 财务分析面积图 |
| | | const initFinancialAreaChart = () => { |
| | | if (!financialAreaChartRef.value) return |
| | | const chart = echarts.init(financialAreaChartRef.value) |
| | | const option = { |
| | | tooltip: { |
| | | trigger: 'axis' |
| | | }, |
| | | grid: { |
| | | left: '10%', |
| | | right: '10%', |
| | | top: '10%', |
| | | bottom: '20%' |
| | | }, |
| | | xAxis: { |
| | | type: 'category', |
| | | data: ['6/9', '6/10', '6/11', '6/12', '6/13'], |
| | | axisLine: { lineStyle: { color: '#333' } }, |
| | | axisLabel: { color: '#B8C8E0' } |
| | | }, |
| | | yAxis: { |
| | | type: 'value', |
| | | axisLine: { show: false }, |
| | | axisTick: { show: false }, |
| | | axisLabel: { color: '#B8C8E0' }, |
| | | splitLine: { lineStyle: { color: '#333' } } |
| | | }, |
| | | series: [{ |
| | | data: [150, 180, 200, 170, 190], |
| | | type: 'line', |
| | | areaStyle: { |
| | | color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [ |
| | | { offset: 0, color: 'rgba(0, 212, 255, 0.3)' }, |
| | | { offset: 1, color: 'rgba(0, 212, 255, 0.1)' } |
| | | ]) |
| | | }, |
| | | lineStyle: { color: '#00d4ff' }, |
| | | itemStyle: { color: '#00d4ff' } |
| | | }] |
| | | } |
| | | chart.setOption(option) |
| | | charts.value.push(chart) |
| | | } |
| | | |
| | | // 实时数据折线图 |
| | | const initRealtimeLineChart = () => { |
| | | if (!realtimeLineChartRef.value) return |
| | | const chart = echarts.init(realtimeLineChartRef.value) |
| | | const option = { |
| | | tooltip: { |
| | | trigger: 'axis' |
| | | }, |
| | | grid: { |
| | | left: '10%', |
| | | right: '10%', |
| | | top: '10%', |
| | | bottom: '20%' |
| | | }, |
| | | xAxis: { |
| | | type: 'category', |
| | | data: ['6/9', '6/10', '6/11', '6/12', '6/13'], |
| | | axisLine: { lineStyle: { color: '#333' } }, |
| | | axisLabel: { color: '#B8C8E0' } |
| | | }, |
| | | yAxis: { |
| | | type: 'value', |
| | | axisLine: { show: false }, |
| | | axisTick: { show: false }, |
| | | axisLabel: { color: '#B8C8E0' }, |
| | | splitLine: { lineStyle: { color: '#333' } } |
| | | }, |
| | | series: [ |
| | | { |
| | | name: '数据1', |
| | | data: [120, 140, 160, 130, 150], |
| | | type: 'line', |
| | | lineStyle: { color: '#00d4ff' }, |
| | | itemStyle: { color: '#00d4ff' } |
| | | }, |
| | | { |
| | | name: '数据2', |
| | | data: [100, 120, 140, 110, 130], |
| | | type: 'line', |
| | | lineStyle: { color: '#0099ff' }, |
| | | itemStyle: { color: '#0099ff' } |
| | | } |
| | | ] |
| | | } |
| | | chart.setOption(option) |
| | | charts.value.push(chart) |
| | | } |
| | | |
| | | // 全屏功能实现 - 针对data-dashboard元素 |
| | | const toggleFullscreen = () => { |
| | | const element = document.querySelector('.data-dashboard') |
| | | |
| | | 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('.data-dashboard') |
| | | |
| | | 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() |
| | | } |
| | | } |
| | | } |
| | | |
| | | // 监听全屏变化事件 |
| | |
| | | // 使用nextTick确保DOM完全渲染后再初始化图表 |
| | | nextTick(() => { |
| | | // 初始化autofit自适应 |
| | | autofit.init({ dh: 1440, dw: 2560, el: '.data-dashboard', resize: true }, false) |
| | | autofit.init({ dh: 1080, dw: 1920, el: '.data-dashboard', resize: true }, false) |
| | | |
| | | // 添加自动滚动动画效果 - 客户信息列表 |
| | | const contractList = refContractList.value |
| | |
| | | window.addEventListener('resize', handleResize) |
| | | analysisCustomer() |
| | | qualityStatisticsInfo() |
| | | qualityProductQualifiedRateInfo() |
| | | accountStatisticsInfo() |
| | | getNum() |
| | | getLedgerNum() |
| | |
| | | <style scoped> |
| | | .data-dashboard { |
| | | position: relative; |
| | | width: 100vw; |
| | | overflow: hidden; |
| | | width: 100%; |
| | | height: 100%; |
| | | background-image: url("@/assets/BI/backImage@2x.png"); |
| | | background-size: cover; |
| | | background-position: center; |
| | |
| | | z-index: 9999; |
| | | } |
| | | |
| | | /* 全屏状态下的内容区域适配 */ |
| | | .data-dashboard:fullscreen .dashboard-content { |
| | | height: calc(100vh - 120px); |
| | | } |
| | | |
| | | .data-dashboard:-webkit-full-screen .dashboard-content { |
| | | height: calc(100vh - 120px); |
| | | } |
| | | |
| | | .data-dashboard:-ms-fullscreen .dashboard-content { |
| | | height: calc(100vh - 120px); |
| | | } |
| | | |
| | | .dashboard-header { |
| | | position: relative; |
| | |
| | | background-size: cover; |
| | | background-position: center; |
| | | background-repeat: no-repeat; |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: center; |
| | | } |
| | | |
| | | .factory-name { |
| | | font-weight: 600; |
| | | font-size: 52px; |
| | | color: #FFFFFF; |
| | | top: 32px; |
| | | position: absolute; |
| | | } |
| | | |
| | | .fullscreen-btn { |
| | |
| | | display: flex; |
| | | gap: 30px; |
| | | padding: 0 30px; |
| | | height: calc(100vh - 120px); |
| | | height: calc(100% - 120px); |
| | | overflow: hidden; |
| | | } |
| | | |
| | |
| | | border: 1px solid #1A58B0; |
| | | padding: 18px; |
| | | width: 100%; |
| | | height: 540px; |
| | | height: 520px; |
| | | } |
| | | .panel-title-second { |
| | | height: 60px; |
| | |
| | | background-position: center; |
| | | background-repeat: no-repeat; |
| | | } |
| | | .panel-item { |
| | | background: rgba(0, 20, 60, 0.8); |
| | | border: 1px solid rgba(0, 212, 255, 0.3); |
| | | border-radius: 12px; |
| | | padding: 30px; |
| | | backdrop-filter: blur(10px); |
| | | min-height: 200px; |
| | | } |
| | | |
| | | .panel-header { |
| | | background-image: url("@/assets/BI/kehuhetongback@2x.png"); |
| | | background-size: 100% 100%; |
| | | background-position: center; |
| | | background-repeat: no-repeat; |
| | | height: 36px; |
| | | } |
| | | |
| | | .panel-title { |
| | |
| | | font-size: 20px; |
| | | color: #FFFFFE; |
| | | } |
| | | .data-statistics { |
| | | flex: 1; |
| | | } |
| | | .financial-header { |
| | | background-image: url("@/assets/BI/caiwufenxiback@2x.png"); |
| | | background-size: 100% 100%; |
| | |
| | | color: #D9ECFF; |
| | | padding-left: 46px; |
| | | line-height: 36px; |
| | | } |
| | | .data-legend { |
| | | display: flex; |
| | | flex-wrap: wrap; |
| | | gap: 20px; |
| | | margin-bottom: 20px; |
| | | } |
| | | |
| | | .legend-item { |
| | | display: flex; |
| | | align-items: center; |
| | | gap: 12px; |
| | | } |
| | | |
| | | .legend-color { |
| | | width: 12px; |
| | | height: 12px; |
| | | border-radius: 4px; |
| | | } |
| | | |
| | | .legend-text { |
| | | font-size: 12px; |
| | | color: #999; |
| | | } |
| | | |
| | | .horizontal-bar-chart { |
| | | height: 150px; |
| | | } |
| | | |
| | | .financial-analysis, |
| | | .realtime-analysis { |
| | | flex: 1; |
| | | } |
| | | |
| | | .financial-tabs, |
| | | .realtime-tabs { |
| | | display: flex; |
| | | gap: 16px; |
| | | margin-bottom: 20px; |
| | | } |
| | | |
| | | .tab { |
| | | padding: 12px 24px; |
| | | background: rgba(0, 0, 0, 0.3); |
| | | border: 1px solid rgba(0, 212, 255, 0.3); |
| | | border-radius: 6px; |
| | | color: #999; |
| | | cursor: pointer; |
| | | transition: all 0.3s; |
| | | } |
| | | |
| | | .tab.active { |
| | | background: rgba(0, 212, 255, 0.2); |
| | | color: #00d4ff; |
| | | border-color: #00d4ff; |
| | | } |
| | | |
| | | .area-chart, |
| | | .line-chart { |
| | | height: 150px; |
| | | } |
| | | |
| | | /* 自定义单选按钮组样式 */ |