Просмотр исходного кода

feat:增加宇信首页,按菜单权限配置

liujt 3 месяцев назад
Родитель
Сommit
1339e1d11d

+ 57 - 1
src/api/main/index.js

@@ -15,5 +15,61 @@ export default {
       return res.data.data;
     }
     return Promise.reject(new Error(res.data.message));
-  }
+  },
+  // 宇信首页统计
+  coalStatistics: async function () {
+    const res = await request.get('/wms/index/coalStatistics');
+    if (res.data.code == 0) {
+      return res.data.data;
+    }
+    return Promise.reject(new Error(res.data.message));
+  },
+  // 宇信煤的月
+  monthCoalStatistics: async function () {
+    const res = await request.get('/wms/index/monthCoalStatistics');
+    if (res.data.code == 0) {
+      return res.data.data;
+    }
+    return Promise.reject(new Error(res.data.message));
+  },
+  // 宇信煤的日
+  dayCoalStatistics: async function () {
+    const res = await request.get('/wms/index/dayCoalStatistics');
+    if (res.data.code == 0) {
+      return res.data.data;
+    }
+    return Promise.reject(new Error(res.data.message));
+  },
+  // 宇信灰的月
+  greyMonthStatistics: async function () {
+    const res = await request.get('/wms/index/greyMonthStatistics');
+    if (res.data.code == 0) {
+      return res.data.data;
+    }
+    return Promise.reject(new Error(res.data.message));
+  },
+  // 宇信灰的日
+  greyDayStatistics: async function () {
+    const res = await request.get('/wms/index/greyDayStatistics');
+    if (res.data.code == 0) {
+      return res.data.data;
+    }
+    return Promise.reject(new Error(res.data.message));
+  },
+  // 宇信渣的月
+  slagMonthStatistics: async function () {
+    const res = await request.get('/wms/index/slagMonthStatistics');
+    if (res.data.code == 0) {
+      return res.data.data;
+    }
+    return Promise.reject(new Error(res.data.message));
+  },
+  // 宇信渣的日
+  slagDayStatistics: async function () {
+    const res = await request.get('/wms/index/slagDayStatistics');
+    if (res.data.code == 0) {
+      return res.data.data;
+    }
+    return Promise.reject(new Error(res.data.message));
+  },
 };

+ 160 - 0
src/components/ChartBarLine/index.vue

@@ -0,0 +1,160 @@
+<template>
+  <div class="chart-bar-line" ref="chartWrap" :style="{ height: height }">
+    <v-chart
+      ref="chartRef"
+      :option="chartOption"
+      :autoresize="true"
+      style="width: 100%; height: 100%;"
+    />
+  </div>
+</template>
+
+<script>
+  import { use } from 'echarts/core';
+  import { CanvasRenderer } from 'echarts/renderers';
+  import { BarChart, LineChart } from 'echarts/charts';
+  import {
+    GridComponent,
+    TooltipComponent,
+    LegendComponent,
+    TitleComponent
+  } from 'echarts/components';
+  import VChart from 'vue-echarts';
+
+  use([
+    CanvasRenderer,
+    BarChart,
+    LineChart,
+    GridComponent,
+    TooltipComponent,
+    LegendComponent,
+    TitleComponent
+  ]);
+
+  export default {
+    name: 'ChartBarLine',
+    components: { VChart },
+    props: {
+      // 图表标题
+      title: { type: String, default: '' },
+      // X 轴数据
+      xAxisData: { type: Array, default: () => [] },
+      // 柱状图系列 [{ name, data, color, unit }]
+      barSeries: { type: Array, default: () => [] },
+      // 折线图系列 [{ name, data, color, unit }]
+      lineSeries: { type: Array, default: () => [] },
+      // 左侧 Y 轴名称(柱状图)
+      barYAxisName: { type: String, default: '' },
+      // 右侧 Y 轴名称(折线图)
+      lineYAxisName: { type: String, default: '' },
+      // 图表高度
+      height: { type: String, default: '360px' },
+      // Legend 位置
+      legendTop: { type: [Number, String], default: 0 }
+    },
+    data() {
+      return {
+        chartInstance: null
+      };
+    },
+    computed: {
+      chartOption() {
+        const allLegends = [
+          ...this.barSeries.map((s) => s.name),
+          ...this.lineSeries.map((s) => s.name)
+        ];
+        return {
+          title: {
+            text: this.title,
+            left: 'center',
+            top: 0,
+            textStyle: { fontSize: 14, fontWeight: 'bold' }
+          },
+          tooltip: {
+            trigger: 'axis',
+            axisPointer: { type: 'cross' }
+          },
+          legend: {
+            data: allLegends,
+            top: this.legendTop || (this.title ? 30 : 0),
+            left: 'center'
+          },
+          grid: {
+            left: '3%',
+            right: '4%',
+            bottom: '10%',
+            top: (this.legendTop || (this.title ? 30 : 0)) + 30,
+            containLabel: true
+          },
+          xAxis: {
+            type: 'category',
+            data: this.xAxisData,
+            axisLabel: { interval: 0 }
+          },
+          yAxis: [
+            {
+              type: 'value',
+              name: this.barYAxisName,
+              axisLabel: { formatter: '{value}' }
+            },
+            {
+              type: 'value',
+              name: this.lineYAxisName,
+              axisLabel: { formatter: '{value} %' }
+            }
+          ],
+          series: [
+            ...this.barSeries.map((s) => ({
+              name: s.name,
+              type: 'bar',
+              data: s.data,
+              barMaxWidth: 20,
+              itemStyle: {
+                color: s.color,
+                barBorderRadius: [2, 2, 0, 0]
+              },
+              yAxisIndex: 0
+            })),
+            ...this.lineSeries.map((s) => ({
+              name: s.name,
+              type: 'line',
+              data: s.data,
+              itemStyle: { color: s.color },
+              lineStyle: { color: s.color, width: 2 },
+              yAxisIndex: 1
+            }))
+          ]
+        };
+      }
+    },
+    mounted() {
+      window.addEventListener('resize', this._resize);
+    },
+    beforeDestroy() {
+      window.removeEventListener('resize', this._resize);
+      if (this.$refs.chartRef) {
+        const instance = this.$refs.chartRef.chart;
+        if (instance && !instance.isDisposed()) {
+          instance.dispose();
+        }
+      }
+    },
+    methods: {
+      _resize() {
+        const chart = this.$refs.chartRef;
+        if (chart) {
+          chart.resize();
+        }
+      }
+    }
+  };
+</script>
+
+<style lang="scss" scoped>
+  .chart-bar-line {
+    width: 100%;
+    border-radius: 4px;
+    background: #fff;
+    box-sizing: border-box;
+  }
+</style>

+ 616 - 0
src/views/warehouseManagement/index/common.vue

@@ -0,0 +1,616 @@
+<template>
+  <div id="my_index">
+    <div class="viewBar">
+      <div v-for="item in list">
+        <div class="item">
+          <div class="title"
+            >{{ item.title }}<span>{{ item.unit }}</span></div
+          >
+          <div class="count">{{ item.count }}</div>
+        </div>
+        <div class="icon">
+          <img :src="item.icon" />
+        </div>
+      </div>
+    </div>
+    <div class="echart_box">
+      <div class="left">
+        <div>
+          <div class="title_box">库总量同比及趋势分析</div>
+          <div class="erchats1"></div>
+        </div>
+        <div>
+          <div class="title_box">物料库存周转趋势分析</div>
+          <div class="erchats2"></div>
+        </div>
+      </div>
+      <div class="right">
+        <div>
+          <div class="title_box">在库总量分析</div>
+          <div class="erchats3"></div>
+        </div>
+        <div>
+          <div class="title_box">呆滞品总量分析</div>
+          <div class="erchats4"></div>
+        </div>
+        <!-- <div>
+          <div class="title_box">在库总量分析</div>
+          <div class="erchats5"></div>
+        </div> -->
+      </div>
+    </div>
+  </div>
+</template>
+
+<script>
+  import * as echarts from 'echarts';
+  import indexApi from '@/api/main/index.js';
+  import { dateReg } from 'ele-admin/lib/utils/validate';
+  import { factorial } from 'mathjs';
+
+  export default {
+    data() {
+      return {
+        timeR:null,
+        list: [
+          {
+            title: '库存总量',
+            key: 'totalInventory',
+            count: '',
+            icon: require('../../../assets/index/Vector@2x.png')
+          },
+          {
+            title: '库存周转天数',
+            unit: '(本月)',
+            key: 'materialTurnoverDays',
+            count: '',
+            icon: require('../../../assets/index/Vector@2x.png')
+          },
+          // {
+          //   title: '物料库存周转率',
+          //   unit: '(本月)',
+          //   count: '',
+          //   key: 'materialTurnoverRate',
+          //   icon: require('../../../assets/index/Vector@2x.png')
+          // },
+          {
+            title: '呆滞品总量',
+            // unit: '(单位)',
+            count: '',
+            key: 'totalSlowMovingItems',
+            icon: require('../../../assets/index/Vector@2x.png')
+          },
+          {
+            title: '产成品总量',
+            // unit: '(单位)',
+            count: '',
+            key: 'totalFinishedProducts',
+            icon: require('../../../assets/index/Vector@2x.png')
+          },
+          {
+            title: '原材料总量',
+            // unit: '(单位)',
+            count: '',
+            key: 'totalRawMaterials',
+            icon: require('../../../assets/index/Vector@2x.png')
+          }
+        ]
+      };
+    },
+    mounted() {
+      // this.initCharts1();
+      // this.initCharts2();
+
+      this.init();
+      this.timeR = setInterval(() => {
+        this.init();
+      },86400000);
+    },
+    beforeDestroy(){
+      clearInterval(this.timeR)
+    },
+    methods: {
+      async init() {
+        let data = await indexApi.indexQuery();
+        let barData = await indexApi.queryList();
+
+        this.list.forEach((item) => {
+          item.count = data[item.key];
+        });
+
+        this.initCharts3(data.slowMovingItemsAnalysis);
+        this.initCircle1(data);
+        this.initCharts1(barData);
+        this.initCharts2(barData);
+      },
+
+      initCharts3(data) {
+        var myChart = echarts.init(document.querySelector('.erchats4'));
+        let x = data.map((item) => item.name);
+        let y = data.map((item) => item.num);
+        let option = {
+          tooltip: {
+            trigger: 'axis',
+            axisPointer: {
+              type: 'shadow'
+            }
+          },
+          grid: {
+            top: '10%',
+            left: '3%',
+            right: '4%',
+            bottom: '3%',
+            containLabel: true
+          },
+          xAxis: [
+            {
+              type: 'category',
+              data: x,
+              axisTick: {
+                alignWithLabel: true
+              }
+            }
+          ],
+          yAxis: [
+            {
+              type: 'value'
+            }
+          ],
+          series: [
+            {
+              name: '个',
+              type: 'bar',
+              barWidth: '30%',
+              itemStyle: {
+                color: '#20BE4B'
+              },
+              data: y
+            }
+          ]
+        };
+        myChart.setOption(option);
+      },
+      initCircle1(data) {
+        var myChart = echarts.init(document.querySelector('.erchats3'));
+        let arr = [
+          {
+            value: data.inspectedQuantity,
+            name: '已质检',
+            rate: data.inspectedPercentage
+          },
+          {
+            value: data.pendingInspectionQuantity,
+            name: '未质检',
+            rate: data.pendingInspectionPercentage
+          },
+          {
+            value: data.noInspectionRequiredQuantity,
+            name: '无需质检',
+            rate: data.noInspectionRequiredPercentage
+          }
+        ];
+        let option = {
+          tooltip: {
+            trigger: 'item'
+          },
+          graphic: {
+            //图形中间图片
+            elements: [
+              {
+                type: 'text', //通过不同top值可以设置上下显示
+                left: '25%',
+                top: '44%',
+                style: {
+                  text: '在库总量(台)',
+                  fill: '#000', //文字的颜色
+                  width: 30,
+                  height: 30,
+                  fontSize: 12,
+                  color: '#000',
+                  fontFamily: 'Microsoft YaHei'
+                }
+              },
+              {
+                type: 'text', //通过不同top值可以设置上下显示
+                left: '25%',
+                top: '53%',
+                style: {
+                  text: data.totalInventory,
+                  fill: '#000', //文字的颜色
+                  width: 30,
+                  height: 30,
+                  fontSize: 18,
+                  color: '#000',
+                  fontFamily: 'Microsoft YaHei'
+                }
+              }
+            ]
+          },
+          legend: {
+            top: 'center',
+            right: '6%',
+            // left:'right',
+            type: 'scroll',
+            orient: 'vertical',
+            itemGap: 15,
+            textStyle: {
+              rich: {
+                // 通过富文本rich给每个项设置样式,下面的oneone、twotwo、threethree可以理解为"每一列"的样式
+                oneone: {
+                  // 设置文字、数学、英语这一列的样式
+                  width: 80,
+                  color: '#000',
+                  fontSize: 12,
+                  fontWeight: 'bolder'
+                },
+                twotwo: {
+                  // 设置10分、20分、30分这一列的样式
+                  width: 35,
+                  color: '#000',
+                  fontSize: 12
+                },
+                threethree: {
+                  // 设置百分比这一列的样式
+                  width: 20,
+                  color: '#000',
+                  fontSize: 12
+                }
+              }
+            },
+            formatter: (name) => {
+              let data = arr.find((item) => item.name == name);
+              return `{oneone|${name}}{twotwo|${data?.value}}           {threethree|(${data?.rate}%)}`;
+            }
+          },
+          series: [
+            {
+              type: 'pie',
+              radius: ['60%', '75%'],
+              center: ['30%', '50%'], //图的位置,距离左跟上的位置
+              avoidLabelOverlap: false,
+              padAngle: 5,
+              label: {
+                show: false,
+                position: 'center'
+              },
+              emphasis: {
+                label: {
+                  show: false,
+                  fontSize: 40,
+                  fontWeight: 'bold'
+                }
+              },
+              labelLine: {
+                show: false
+              },
+              data: arr
+            }
+          ]
+        };
+        myChart.setOption(option);
+      },
+
+      initCharts1(barData) {
+        const colors = ['#5470C6', '#91CC75', '#EE6666'];
+        console.log(barData, 'barData');
+        var myChart = echarts.init(document.querySelector('.erchats1'));
+        myChart.setOption({
+          color: colors,
+          tooltip: {
+            trigger: 'axis',
+            axisPointer: {
+              type: 'cross'
+            }
+          },
+          grid: {
+            left: '5%',
+            right: '5%',
+            bottom: '8%'
+          },
+          legend: {},
+          xAxis: [
+            {
+              type: 'category',
+              axisTick: {
+                alignWithLabel: true
+              },
+              data: barData.map((item) => item.month)
+            }
+          ],
+          yAxis: [
+            {
+              type: 'value',
+              name: '',
+              position: 'right',
+              alignTicks: true,
+              axisLine: {
+                show: false
+              },
+              axisLabel: {
+                formatter: '{value}%'
+              }
+            },
+            // {
+            //   type: 'value',
+            //   name: '2024',
+            //   show: false,
+            //   position: 'right',
+            //   alignTicks: true,
+            //   offset: 80,
+            //   axisLine: {
+            //     show: false
+            //   },
+            //   axisLabel: {
+            //     formatter: '{value} ml'
+            //   }
+            // },
+            {
+              type: 'value',
+              name: '(单位:pcs)',
+              position: 'left',
+              alignTicks: true,
+              axisLine: {
+                show: false
+              },
+              axisLabel: {
+                formatter: '{value}'
+              }
+            }
+          ],
+          series: [
+            {
+              name: '去年同期库存总量',
+              type: 'bar',
+              barWidth: '20%',
+              itemStyle: {
+                color: '#3976F1'
+              },
+              yAxisIndex: 1,
+              data: barData.map((item) => item.lastYearTotalInventory)
+            },
+            {
+              name: '本年库存总量',
+              type: 'bar',
+              yAxisIndex: 1,
+              barWidth: '20%',
+              itemStyle: {
+                color: '#5DD07C'
+              },
+              data: barData.map((item) => item.totalInventory)
+            },
+            {
+              name: '趋势',
+              type: 'line',
+              itemStyle: {
+                color: '#FF9669'
+              },
+              data: barData.map((item) => item.inventoryTrendRate)
+            }
+          ]
+        });
+      },
+      initCharts2(barData) {
+        var myChart = echarts.init(document.querySelector('.erchats2'));
+        myChart.setOption({
+          tooltip: {
+            trigger: 'axis',
+            axisPointer: {
+              type: 'cross'
+            }
+          },
+          grid: {
+            left: '5%',
+            right: '5%',
+            bottom: '8%'
+          },
+          legend: {
+            // data: ['当年存货周转率', '去年存货周转率', '当年趋势']
+          },
+          xAxis: [
+            {
+              type: 'category',
+              axisTick: {
+                alignWithLabel: true
+              },
+              data: barData.map((item) => item.month)
+            }
+          ],
+          yAxis: [
+            {
+              type: 'value',
+              name: '',
+              position: 'right',
+              alignTicks: true,
+              axisLine: {
+                show: false
+              },
+              axisLabel: {
+                formatter: '{value}%'
+              }
+            },
+            // {
+            //   type: 'value',
+            //   name: '2024',
+            //   show: false,
+            //   position: 'right',
+            //   alignTicks: true,
+            //   offset: 80,
+            //   axisLine: {
+            //     show: false
+            //   },
+            //   axisLabel: {
+            //     formatter: '{value} ml'
+            //   }
+            // },
+            {
+              type: 'value',
+              name: '(单位:pcs)',
+              position: 'left',
+              alignTicks: true,
+              axisLine: {
+                show: false
+              },
+              axisLabel: {
+                formatter: '{value}'
+              }
+            }
+          ],
+          series: [
+            {
+              name: '本年存货周转率',
+              type: 'bar',
+              barWidth: '20%',
+              itemStyle: {
+                color: '#FF9669'
+              },
+              yAxisIndex: 1,
+              data: barData.map((item) => item.materialTurnoverRate)
+            },
+            {
+              name: '去年存货周转率',
+              type: 'bar',
+              yAxisIndex: 1,
+              barWidth: '20%',
+              yAxisIndex: 1,
+              itemStyle: {
+                color: '#26ADAD'
+              },
+              data: barData.map((item) => item.lastYearMaterialTurnoverRate)
+            },
+            {
+              name: '趋势',
+              type: 'line',
+              itemStyle: {
+                color: '#095BFF'
+              },
+              data: barData.map((item) => item.materialTurnoverTrend)
+            }
+          ]
+        });
+      }
+    }
+  };
+</script>
+
+<style lang="scss" scoped>
+  #my_index {
+    height: calc(100vh - 96px);
+    display: flex;
+    width: 100%;
+    padding: 10px;
+    flex-direction: column;
+    box-sizing: border-box;
+    background-color: #dbdbdb;
+    .viewBar {
+      height: 93px;
+      width: 100%;
+      display: flex;
+      margin-bottom: 10px;
+      > div {
+        flex: 1;
+        margin-left: 10px;
+        background: linear-gradient(to right, #2d80ee 100%, #e9f2ff 50%);
+        border-radius: 8px;
+        display: flex;
+        padding: 0 20px;
+        box-sizing: border-box;
+        .item {
+          flex: 1;
+          display: flex;
+          flex-direction: column;
+          .title {
+            flex: 1;
+            display: flex;
+            align-items: center;
+            font-size: 16px;
+            color: rgba(255, 255, 255, 1);
+            > span {
+              font-size: 12px;
+            }
+          }
+          .count {
+            flex: 1;
+            display: flex;
+            align-items: center;
+            font-size: 28px;
+            color: rgba(255, 255, 255, 1);
+          }
+        }
+        .icon {
+          width: 50px;
+          height: 100%;
+          display: flex;
+          align-items: center;
+          justify-content: center;
+          > img {
+            height: 50px;
+            width: 50px;
+          }
+        }
+      }
+      > div:first-child {
+        margin-left: 0;
+      }
+    }
+    .echart_box {
+      display: flex;
+      flex: 1;
+      .left {
+        flex: 5;
+        display: flex;
+        flex-direction: column;
+        margin-right: 10px;
+        height: 100%;
+        > div:first-child {
+          margin-bottom: 10px;
+        }
+        > div {
+          flex: 1;
+          background-color: #fff;
+          padding: 10px;
+          box-sizing: border-box;
+          border-radius: 6px;
+          display: flex;
+          flex-direction: column;
+          .title_box {
+            font-size: 14px;
+            padding-bottom: 10px;
+            box-sizing: border-box;
+            border-bottom: 1px solid #e6e8e8;
+          }
+          > div:last-child {
+            flex: 1;
+          }
+        }
+      }
+      .right {
+        flex: 3;
+        display: flex;
+        flex-direction: column;
+        height: 100%;
+        > div {
+          flex: 1;
+          padding: 10px;
+          box-sizing: border-box;
+          background-color: #fff;
+          margin-bottom: 10px;
+          border-radius: 6px;
+          display: flex;
+          flex-direction: column;
+          .title_box {
+            font-size: 14px;
+            padding-bottom: 10px;
+            box-sizing: border-box;
+            border-bottom: 1px solid #e6e8e8;
+          }
+          > div:last-child {
+            flex: 1;
+          }
+        }
+        > div:last-child {
+          margin-bottom: 0;
+        }
+      }
+    }
+  }
+</style>

+ 11 - 603
src/views/warehouseManagement/index/index.vue

@@ -1,616 +1,24 @@
 <template>
-  <div id="my_index">
-    <div class="viewBar">
-      <div v-for="item in list">
-        <div class="item">
-          <div class="title"
-            >{{ item.title }}<span>{{ item.unit }}</span></div
-          >
-          <div class="count">{{ item.count }}</div>
-        </div>
-        <div class="icon">
-          <img :src="item.icon" />
-        </div>
-      </div>
-    </div>
-    <div class="echart_box">
-      <div class="left">
-        <div>
-          <div class="title_box">库总量同比及趋势分析</div>
-          <div class="erchats1"></div>
-        </div>
-        <div>
-          <div class="title_box">物料库存周转趋势分析</div>
-          <div class="erchats2"></div>
-        </div>
-      </div>
-      <div class="right">
-        <div>
-          <div class="title_box">在库总量分析</div>
-          <div class="erchats3"></div>
-        </div>
-        <div>
-          <div class="title_box">呆滞品总量分析</div>
-          <div class="erchats4"></div>
-        </div>
-        <!-- <div>
-          <div class="title_box">在库总量分析</div>
-          <div class="erchats5"></div>
-        </div> -->
-      </div>
-    </div>
+  <div>
+    <yuxin v-if="$hasPermission('wms:home:yuxin')"></yuxin>
+     
+    <common v-else></common>
   </div>
 </template>
 
 <script>
-  import * as echarts from 'echarts';
-  import indexApi from '@/api/main/index.js';
-  import { dateReg } from 'ele-admin/lib/utils/validate';
-  import { factorial } from 'mathjs';
+  import common from './common.vue';
+  import yuxin from './yuxin.vue';
 
   export default {
+    components: { common, yuxin },
     data() {
-      return {
-        timeR:null,
-        list: [
-          {
-            title: '库存总量',
-            key: 'totalInventory',
-            count: '',
-            icon: require('../../../assets/index/Vector@2x.png')
-          },
-          {
-            title: '库存周转天数',
-            unit: '(本月)',
-            key: 'materialTurnoverDays',
-            count: '',
-            icon: require('../../../assets/index/Vector@2x.png')
-          },
-          // {
-          //   title: '物料库存周转率',
-          //   unit: '(本月)',
-          //   count: '',
-          //   key: 'materialTurnoverRate',
-          //   icon: require('../../../assets/index/Vector@2x.png')
-          // },
-          {
-            title: '呆滞品总量',
-            // unit: '(单位)',
-            count: '',
-            key: 'totalSlowMovingItems',
-            icon: require('../../../assets/index/Vector@2x.png')
-          },
-          {
-            title: '产成品总量',
-            // unit: '(单位)',
-            count: '',
-            key: 'totalFinishedProducts',
-            icon: require('../../../assets/index/Vector@2x.png')
-          },
-          {
-            title: '原材料总量',
-            // unit: '(单位)',
-            count: '',
-            key: 'totalRawMaterials',
-            icon: require('../../../assets/index/Vector@2x.png')
-          }
-        ]
-      };
+      return {};
     },
-    mounted() {
-      // this.initCharts1();
-      // this.initCharts2();
+    computed: {},
 
-      this.init();
-      this.timeR = setInterval(() => {
-        this.init();
-      },86400000);
-    },
-    beforeDestroy(){
-      clearInterval(this.timeR)
-    },
-    methods: {
-      async init() {
-        let data = await indexApi.indexQuery();
-        let barData = await indexApi.queryList();
-
-        this.list.forEach((item) => {
-          item.count = data[item.key];
-        });
-
-        this.initCharts3(data.slowMovingItemsAnalysis);
-        this.initCircle1(data);
-        this.initCharts1(barData);
-        this.initCharts2(barData);
-      },
-
-      initCharts3(data) {
-        var myChart = echarts.init(document.querySelector('.erchats4'));
-        let x = data.map((item) => item.name);
-        let y = data.map((item) => item.num);
-        let option = {
-          tooltip: {
-            trigger: 'axis',
-            axisPointer: {
-              type: 'shadow'
-            }
-          },
-          grid: {
-            top: '10%',
-            left: '3%',
-            right: '4%',
-            bottom: '3%',
-            containLabel: true
-          },
-          xAxis: [
-            {
-              type: 'category',
-              data: x,
-              axisTick: {
-                alignWithLabel: true
-              }
-            }
-          ],
-          yAxis: [
-            {
-              type: 'value'
-            }
-          ],
-          series: [
-            {
-              name: '个',
-              type: 'bar',
-              barWidth: '30%',
-              itemStyle: {
-                color: '#20BE4B'
-              },
-              data: y
-            }
-          ]
-        };
-        myChart.setOption(option);
-      },
-      initCircle1(data) {
-        var myChart = echarts.init(document.querySelector('.erchats3'));
-        let arr = [
-          {
-            value: data.inspectedQuantity,
-            name: '已质检',
-            rate: data.inspectedPercentage
-          },
-          {
-            value: data.pendingInspectionQuantity,
-            name: '未质检',
-            rate: data.pendingInspectionPercentage
-          },
-          {
-            value: data.noInspectionRequiredQuantity,
-            name: '无需质检',
-            rate: data.noInspectionRequiredPercentage
-          }
-        ];
-        let option = {
-          tooltip: {
-            trigger: 'item'
-          },
-          graphic: {
-            //图形中间图片
-            elements: [
-              {
-                type: 'text', //通过不同top值可以设置上下显示
-                left: '25%',
-                top: '44%',
-                style: {
-                  text: '在库总量(台)',
-                  fill: '#000', //文字的颜色
-                  width: 30,
-                  height: 30,
-                  fontSize: 12,
-                  color: '#000',
-                  fontFamily: 'Microsoft YaHei'
-                }
-              },
-              {
-                type: 'text', //通过不同top值可以设置上下显示
-                left: '25%',
-                top: '53%',
-                style: {
-                  text: data.totalInventory,
-                  fill: '#000', //文字的颜色
-                  width: 30,
-                  height: 30,
-                  fontSize: 18,
-                  color: '#000',
-                  fontFamily: 'Microsoft YaHei'
-                }
-              }
-            ]
-          },
-          legend: {
-            top: 'center',
-            right: '6%',
-            // left:'right',
-            type: 'scroll',
-            orient: 'vertical',
-            itemGap: 15,
-            textStyle: {
-              rich: {
-                // 通过富文本rich给每个项设置样式,下面的oneone、twotwo、threethree可以理解为"每一列"的样式
-                oneone: {
-                  // 设置文字、数学、英语这一列的样式
-                  width: 80,
-                  color: '#000',
-                  fontSize: 12,
-                  fontWeight: 'bolder'
-                },
-                twotwo: {
-                  // 设置10分、20分、30分这一列的样式
-                  width: 35,
-                  color: '#000',
-                  fontSize: 12
-                },
-                threethree: {
-                  // 设置百分比这一列的样式
-                  width: 20,
-                  color: '#000',
-                  fontSize: 12
-                }
-              }
-            },
-            formatter: (name) => {
-              let data = arr.find((item) => item.name == name);
-              return `{oneone|${name}}{twotwo|${data?.value}}           {threethree|(${data?.rate}%)}`;
-            }
-          },
-          series: [
-            {
-              type: 'pie',
-              radius: ['60%', '75%'],
-              center: ['30%', '50%'], //图的位置,距离左跟上的位置
-              avoidLabelOverlap: false,
-              padAngle: 5,
-              label: {
-                show: false,
-                position: 'center'
-              },
-              emphasis: {
-                label: {
-                  show: false,
-                  fontSize: 40,
-                  fontWeight: 'bold'
-                }
-              },
-              labelLine: {
-                show: false
-              },
-              data: arr
-            }
-          ]
-        };
-        myChart.setOption(option);
-      },
-
-      initCharts1(barData) {
-        const colors = ['#5470C6', '#91CC75', '#EE6666'];
-        console.log(barData, 'barData');
-        var myChart = echarts.init(document.querySelector('.erchats1'));
-        myChart.setOption({
-          color: colors,
-          tooltip: {
-            trigger: 'axis',
-            axisPointer: {
-              type: 'cross'
-            }
-          },
-          grid: {
-            left: '5%',
-            right: '5%',
-            bottom: '8%'
-          },
-          legend: {},
-          xAxis: [
-            {
-              type: 'category',
-              axisTick: {
-                alignWithLabel: true
-              },
-              data: barData.map((item) => item.month)
-            }
-          ],
-          yAxis: [
-            {
-              type: 'value',
-              name: '',
-              position: 'right',
-              alignTicks: true,
-              axisLine: {
-                show: false
-              },
-              axisLabel: {
-                formatter: '{value}%'
-              }
-            },
-            // {
-            //   type: 'value',
-            //   name: '2024',
-            //   show: false,
-            //   position: 'right',
-            //   alignTicks: true,
-            //   offset: 80,
-            //   axisLine: {
-            //     show: false
-            //   },
-            //   axisLabel: {
-            //     formatter: '{value} ml'
-            //   }
-            // },
-            {
-              type: 'value',
-              name: '(单位:pcs)',
-              position: 'left',
-              alignTicks: true,
-              axisLine: {
-                show: false
-              },
-              axisLabel: {
-                formatter: '{value}'
-              }
-            }
-          ],
-          series: [
-            {
-              name: '去年同期库存总量',
-              type: 'bar',
-              barWidth: '20%',
-              itemStyle: {
-                color: '#3976F1'
-              },
-              yAxisIndex: 1,
-              data: barData.map((item) => item.lastYearTotalInventory)
-            },
-            {
-              name: '本年库存总量',
-              type: 'bar',
-              yAxisIndex: 1,
-              barWidth: '20%',
-              itemStyle: {
-                color: '#5DD07C'
-              },
-              data: barData.map((item) => item.totalInventory)
-            },
-            {
-              name: '趋势',
-              type: 'line',
-              itemStyle: {
-                color: '#FF9669'
-              },
-              data: barData.map((item) => item.inventoryTrendRate)
-            }
-          ]
-        });
-      },
-      initCharts2(barData) {
-        var myChart = echarts.init(document.querySelector('.erchats2'));
-        myChart.setOption({
-          tooltip: {
-            trigger: 'axis',
-            axisPointer: {
-              type: 'cross'
-            }
-          },
-          grid: {
-            left: '5%',
-            right: '5%',
-            bottom: '8%'
-          },
-          legend: {
-            // data: ['当年存货周转率', '去年存货周转率', '当年趋势']
-          },
-          xAxis: [
-            {
-              type: 'category',
-              axisTick: {
-                alignWithLabel: true
-              },
-              data: barData.map((item) => item.month)
-            }
-          ],
-          yAxis: [
-            {
-              type: 'value',
-              name: '',
-              position: 'right',
-              alignTicks: true,
-              axisLine: {
-                show: false
-              },
-              axisLabel: {
-                formatter: '{value}%'
-              }
-            },
-            // {
-            //   type: 'value',
-            //   name: '2024',
-            //   show: false,
-            //   position: 'right',
-            //   alignTicks: true,
-            //   offset: 80,
-            //   axisLine: {
-            //     show: false
-            //   },
-            //   axisLabel: {
-            //     formatter: '{value} ml'
-            //   }
-            // },
-            {
-              type: 'value',
-              name: '(单位:pcs)',
-              position: 'left',
-              alignTicks: true,
-              axisLine: {
-                show: false
-              },
-              axisLabel: {
-                formatter: '{value}'
-              }
-            }
-          ],
-          series: [
-            {
-              name: '本年存货周转率',
-              type: 'bar',
-              barWidth: '20%',
-              itemStyle: {
-                color: '#FF9669'
-              },
-              yAxisIndex: 1,
-              data: barData.map((item) => item.materialTurnoverRate)
-            },
-            {
-              name: '去年存货周转率',
-              type: 'bar',
-              yAxisIndex: 1,
-              barWidth: '20%',
-              yAxisIndex: 1,
-              itemStyle: {
-                color: '#26ADAD'
-              },
-              data: barData.map((item) => item.lastYearMaterialTurnoverRate)
-            },
-            {
-              name: '趋势',
-              type: 'line',
-              itemStyle: {
-                color: '#095BFF'
-              },
-              data: barData.map((item) => item.materialTurnoverTrend)
-            }
-          ]
-        });
-      }
-    }
+    mounted() {}
   };
 </script>
 
-<style lang="scss" scoped>
-  #my_index {
-    height: calc(100vh - 96px);
-    display: flex;
-    width: 100%;
-    padding: 10px;
-    flex-direction: column;
-    box-sizing: border-box;
-    background-color: #dbdbdb;
-    .viewBar {
-      height: 93px;
-      width: 100%;
-      display: flex;
-      margin-bottom: 10px;
-      > div {
-        flex: 1;
-        margin-left: 10px;
-        background: linear-gradient(to right, #2d80ee 100%, #e9f2ff 50%);
-        border-radius: 8px;
-        display: flex;
-        padding: 0 20px;
-        box-sizing: border-box;
-        .item {
-          flex: 1;
-          display: flex;
-          flex-direction: column;
-          .title {
-            flex: 1;
-            display: flex;
-            align-items: center;
-            font-size: 16px;
-            color: rgba(255, 255, 255, 1);
-            > span {
-              font-size: 12px;
-            }
-          }
-          .count {
-            flex: 1;
-            display: flex;
-            align-items: center;
-            font-size: 28px;
-            color: rgba(255, 255, 255, 1);
-          }
-        }
-        .icon {
-          width: 50px;
-          height: 100%;
-          display: flex;
-          align-items: center;
-          justify-content: center;
-          > img {
-            height: 50px;
-            width: 50px;
-          }
-        }
-      }
-      > div:first-child {
-        margin-left: 0;
-      }
-    }
-    .echart_box {
-      display: flex;
-      flex: 1;
-      .left {
-        flex: 5;
-        display: flex;
-        flex-direction: column;
-        margin-right: 10px;
-        height: 100%;
-        > div:first-child {
-          margin-bottom: 10px;
-        }
-        > div {
-          flex: 1;
-          background-color: #fff;
-          padding: 10px;
-          box-sizing: border-box;
-          border-radius: 6px;
-          display: flex;
-          flex-direction: column;
-          .title_box {
-            font-size: 14px;
-            padding-bottom: 10px;
-            box-sizing: border-box;
-            border-bottom: 1px solid #e6e8e8;
-          }
-          > div:last-child {
-            flex: 1;
-          }
-        }
-      }
-      .right {
-        flex: 3;
-        display: flex;
-        flex-direction: column;
-        height: 100%;
-        > div {
-          flex: 1;
-          padding: 10px;
-          box-sizing: border-box;
-          background-color: #fff;
-          margin-bottom: 10px;
-          border-radius: 6px;
-          display: flex;
-          flex-direction: column;
-          .title_box {
-            font-size: 14px;
-            padding-bottom: 10px;
-            box-sizing: border-box;
-            border-bottom: 1px solid #e6e8e8;
-          }
-          > div:last-child {
-            flex: 1;
-          }
-        }
-        > div:last-child {
-          margin-bottom: 0;
-        }
-      }
-    }
-  }
-</style>
+<style lang="scss" scoped></style>

+ 350 - 0
src/views/warehouseManagement/index/yuxin.vue

@@ -0,0 +1,350 @@
+<template>
+  <div id="my_index">
+    <div class="viewBar">
+      <div v-for="item in list">
+        <div class="item">
+          <div class="title"
+            >{{ item.title }}<span>{{ item.unit }}</span></div
+          >
+          <div class="count">{{ item.count }}</div>
+        </div>
+        <div class="icon">
+          <img :src="item.icon" />
+        </div>
+      </div>
+    </div>
+    <div>
+        <el-row :gutter="16" class="mb-10">
+            <el-col :span="12">
+                <el-card shadow="always" class="box-card">
+                    <div slot="header" class="clearfix">
+                        <span>场站月用煤量对比</span>
+                    </div>
+                    <div class="grid-content">
+                        <chart-bar-line
+                            :xAxisData="monthCoalData.xAxisData"
+                            :barSeries="monthCoalData.barSeries"
+                            :lineSeries="monthCoalData.lineSeries"
+                            barYAxisName="吨"
+                            height="280px"
+                        />
+                    </div>
+                </el-card>
+            </el-col>
+            <el-col :span="12">
+                <el-card shadow="always" class="box-card">
+                    <div slot="header" class="clearfix">
+                        <span>场站日用煤量对比</span>
+                    </div>
+                    <div class="grid-content">
+                        <chart-bar-line
+                            :xAxisData="dayCoalData.xAxisData"
+                            :barSeries="dayCoalData.barSeries"
+                            :lineSeries="dayCoalData.lineSeries"
+                            barYAxisName="吨"
+                            height="280px"
+                        />
+                    </div>
+                </el-card>
+            </el-col>
+        </el-row>
+        <el-row :gutter="16" class="mb-10">
+            <el-col :span="12">
+                <el-card shadow="always" class="box-card">
+                    <div slot="header" class="clearfix">
+                        <span>场站月拉灰量对比</span>
+                    </div>
+                    <div class="grid-content">
+                        <chart-bar-line
+                            :xAxisData="monthGreyData.xAxisData"
+                            :barSeries="monthGreyData.barSeries"
+                            :lineSeries="monthGreyData.lineSeries"
+                            barYAxisName="吨"
+                            height="280px"
+                        />
+                    </div>
+                </el-card>
+            </el-col>
+            <el-col :span="12">
+                <el-card shadow="always" class="box-card">
+                    <div slot="header" class="clearfix">
+                        <span>场站日拉灰量对比</span>
+                    </div>
+                    <div class="grid-content">
+                        <chart-bar-line
+                            :xAxisData="dayGreyData.xAxisData"
+                            :barSeries="dayGreyData.barSeries"
+                            :lineSeries="dayGreyData.lineSeries"
+                            barYAxisName="吨"
+                            height="280px"
+                        />
+                    </div>
+                </el-card>
+            </el-col>
+        </el-row>
+        <el-row :gutter="16" class="mb-10">
+            <el-col :span="12">
+                <el-card shadow="always" class="box-card">
+                    <div slot="header" class="clearfix">
+                        <span>场站月拉渣量对比</span>
+                    </div>
+                    <div class="grid-content">
+                        <chart-bar-line
+                            :xAxisData="monthSlagData.xAxisData"
+                            :barSeries="monthSlagData.barSeries"
+                            :lineSeries="monthSlagData.lineSeries"
+                            barYAxisName="吨"
+                            height="280px"
+                        />
+                    </div>
+                </el-card>
+            </el-col>
+            <el-col :span="12">
+                <el-card shadow="always" class="box-card">
+                    <div slot="header" class="clearfix">
+                        <span>场站日拉渣量对比</span>
+                    </div>
+                    <div class="grid-content">
+                        <chart-bar-line
+                            :xAxisData="daySlagData.xAxisData"
+                            :barSeries="daySlagData.barSeries"
+                            :lineSeries="daySlagData.lineSeries"
+                            barYAxisName="吨"
+                            height="280px"
+                        />
+                    </div>
+                </el-card>
+            </el-col>
+        </el-row>
+    </div>
+  </div>
+</template>
+
+<script>
+import indexApi from '@/api/main/index.js';
+import chartBarLine from '@/components/ChartBarLine/index.vue';
+
+  const  COAL_WAREHOUSE_MAP = {
+    '2008474572461486082': '5#场站',
+    '2064887500559134721': '6#场站',
+    '2064887643979165697': '7#场站'
+  };
+
+  const GREY_WAREHOUSE_MAP = {
+    '2008475053149696001': '5#场站',
+    '2008475191167463426': '6#场站',
+    '2008475309006434305': '7#场站'
+  };
+
+  const COAL_STATION_KEYS = ['2008474572461486082', '2064887500559134721', '2064887643979165697'];
+
+  const GREY_STATION_KEYS = ['2008475053149696001', '2008475191167463426', '2008475309006434305'];
+
+  // 各图表颜色配置
+  const CHART_COLORS = {
+    monthCoal:  ['#3876f1', '#f8cd5d', '#5cd07b'],
+    dayCoal:    ['#5e5e5e', '#f7cd5c', '#00a1f1'],
+    monthGrey:  ['#979797', '#5df9f5', '#5cd07b'],
+    dayGrey:    ['#98aa00', '#5df9f5', '#5cd07b'],
+    monthSlag:  ['#7ca7ff', '#fef538', '#b6b6b6'],
+    daySlag:    ['#39496b', '#ff7b00', '#b6b6b6']
+  };
+
+  export default {
+    components: { chartBarLine },
+    data() {
+      return {
+        list: [
+          {
+            title: '来煤累计数',
+            key: 'coalInbound',
+            count: '',
+            icon: require('../../../assets/index/Vector@2x.png')
+          },
+          {
+            title: '用煤累计数',
+            unit: '',
+            key: 'coalConsumption',
+            count: '',
+            icon: require('../../../assets/index/Vector@2x.png')
+          },
+          {
+            title: '煤库存数',
+            count: '',
+            key: 'coalInventory',
+            icon: require('../../../assets/index/Vector@2x.png')
+          },
+        ],
+        // 图表数据
+        monthCoalData: { xAxisData: [], barSeries: [], lineSeries: [] },
+        dayCoalData:   { xAxisData: [], barSeries: [], lineSeries: [] },
+        monthGreyData: { xAxisData: [], barSeries: [], lineSeries: [] },
+        dayGreyData:   { xAxisData: [], barSeries: [], lineSeries: [] },
+        monthSlagData: { xAxisData: [], barSeries: [], lineSeries: [] },
+        daySlagData:   { xAxisData: [], barSeries: [], lineSeries: [] }
+      };
+    },
+    computed: {},
+
+    mounted() {
+        this.init();
+        this.monthCoalStatistics();
+        this.dayCoalStatistics();
+        this.monthGreyStatistics();
+        this.dayGreyStatistics();
+        this.monthSlagStatistics();
+        this.daySlagStatistics();
+    },
+    methods: {
+        async init() {
+        let data = await indexApi.coalStatistics();
+        this.list.forEach((item) => {
+          item.count = data[item.key];
+        });
+      },
+      /* 将接口数据转为图表格式
+       * records: API 返回的数组
+       * timeKey: 时间字段 'month' | 'dayTime'
+       * colors: 颜色数组 [5#, 6#, 7#]
+       * stationKeys: 场站 ID 顺序数组
+       * warehouseMap: warehouseId → 场站名称映射
+       */
+      _formatChartData(records, timeKey, colors, stationKeys, warehouseMap) {
+        // 生成完整的时间轴(key 用于数据匹配,label 用于显示)
+        const now = new Date();
+        const slots = timeKey === 'month'
+          ? Array.from({ length: 12 }, (_, i) => {
+              const m = String(i + 1).padStart(2, '0');
+              return { key: `${now.getFullYear()}-${m}`, label: `${i + 1}月` };
+            })
+          : (() => {
+              const y = now.getFullYear();
+              const m = String(now.getMonth() + 1).padStart(2, '0');
+              const lastDay = new Date(y, +m, 0).getDate();
+              return Array.from({ length: lastDay }, (_, i) => {
+                const d = String(i + 1).padStart(2, '0');
+                return { key: `${y}-${m}-${d}`, label: `${i + 1}` };
+              });
+            })();
+        const timeKeys = slots.map((s) => s.key);
+        const xAxisData = slots.map((s) => s.label);
+        // 按时间分组汇总
+        const byTime = {};
+        records.forEach((r) => {
+          const t = r[timeKey];
+          if (!t) return;
+          if (!byTime[t]) byTime[t] = {};
+          byTime[t][r.warehouseId] = (byTime[t][r.warehouseId] || 0) + parseFloat(r.totalQuantity || 0);
+        });
+        const barSeries = [];
+        const lineSeries = [];
+        stationKeys.forEach((wid, idx) => {
+          const name = warehouseMap[wid];
+          const data = timeKeys.map((t) => +(byTime[t]?.[wid] || 0).toFixed(2));
+          const color = colors[idx];
+          barSeries.push({ name, data, color });
+          lineSeries.push({ name: name + '趋势', data, color });
+        });
+        return { xAxisData, barSeries, lineSeries };
+      },
+      // 宇信煤的月度统计
+      async monthCoalStatistics() {
+        const data = await indexApi.monthCoalStatistics();
+        this.monthCoalData = this._formatChartData(data, 'month', CHART_COLORS.monthCoal, COAL_STATION_KEYS, COAL_WAREHOUSE_MAP);
+      },
+      // 宇信煤的日统计
+      async dayCoalStatistics() {
+        const data = await indexApi.dayCoalStatistics();
+        this.dayCoalData = this._formatChartData(data, 'dayTime', CHART_COLORS.dayCoal, COAL_STATION_KEYS, COAL_WAREHOUSE_MAP);
+      },
+      // 宇信灰的月度统计
+      async monthGreyStatistics() {
+        const data = await indexApi.greyMonthStatistics();
+        this.monthGreyData = this._formatChartData(data, 'month', CHART_COLORS.monthGrey, GREY_STATION_KEYS, GREY_WAREHOUSE_MAP);
+      },
+      // 宇信灰的日统计
+      async dayGreyStatistics() {
+        const data = await indexApi.greyDayStatistics();
+        this.dayGreyData = this._formatChartData(data, 'dayTime', CHART_COLORS.dayGrey, GREY_STATION_KEYS, GREY_WAREHOUSE_MAP);
+      },
+      // 宇信渣的月度统计
+      async monthSlagStatistics() {
+        const data = await indexApi.slagMonthStatistics();
+        this.monthSlagData = this._formatChartData(data, 'month', CHART_COLORS.monthSlag, GREY_STATION_KEYS, GREY_WAREHOUSE_MAP);
+      },
+      // 宇信渣的日统计
+      async daySlagStatistics() {
+        const data = await indexApi.slagDayStatistics();
+        this.daySlagData = this._formatChartData(data, 'dayTime', CHART_COLORS.daySlag, GREY_STATION_KEYS, GREY_WAREHOUSE_MAP);
+      },
+    }
+  };
+</script>
+
+<style lang="scss" scoped>
+#my_index {
+    // height: calc(100vh - 96px);
+    display: flex;
+    width: 100%;
+    padding: 10px;
+    flex-direction: column;
+    box-sizing: border-box;
+    // background-color: #dbdbdb;
+    .viewBar {
+      height: 90px;
+      width: 100%;
+      display: flex;
+      margin-bottom: 10px;
+      justify-content: space-around;
+      > div {
+        // flex: 1;
+        width: 25%;
+        margin-left: 10px;
+        background: linear-gradient(to right, #2d80ee 100%, #e9f2ff 50%);
+        border-radius: 8px;
+        display: flex;
+        padding: 0 20px;
+        box-sizing: border-box;
+        .item {
+          flex: 1;
+          display: flex;
+          flex-direction: column;
+          .title {
+            flex: 1;
+            display: flex;
+            align-items: center;
+            font-size: 16px;
+            color: rgba(255, 255, 255, 1);
+            > span {
+              font-size: 12px;
+            }
+          }
+          .count {
+            flex: 1;
+            display: flex;
+            align-items: center;
+            font-size: 28px;
+            color: rgba(255, 255, 255, 1);
+          }
+        }
+        .icon {
+          width: 50px;
+          height: 100%;
+          display: flex;
+          align-items: center;
+          justify-content: center;
+          > img {
+            height: 50px;
+            width: 50px;
+          }
+        }
+      }
+      > div:first-child {
+        margin-left: 0;
+      }
+    }
+    .mb-10 {
+        margin-bottom: 10px;
+    }
+  }
+</style>