loulijun2021
2023-12-07 0477ff4020f8953a2db3022726db70e34aa84c14
pages/znfx/scfx.vue
@@ -1,8 +1,478 @@
<template>
   <view>
      <page-nav title="生产分析"></page-nav>
      <view :style="{height:'1400rpx',overflow: 'scroll',background:'#0659FF'}">
         <view class="body">
            <view class="body_head">
               <view class="body_head_title">生产看板</view>
               <view>
                  <u-button type="" icon='calendar' iconColor="#0659FF" size="mini" @click="calendarShowTrue"
                     :text="calendarRange">
                  </u-button>
               </view>
            </view>
            <view class="body_content" style="height: 330rpx;">
               <view class="body_content_title">
                  <view>生产总览</view>
                  <uni-tooltip content="一段时间内的生产数据" style='margin-left: 10rpx;'>
                     <u-icon name="question-circle"></u-icon>
                  </uni-tooltip>
               </view>
               <view class="flex_between">
                  <view class="cont_item">
                     <view class="cont_item_title">计划数量</view>
                     <view class="cont_item_content">{{topData.plan_qty?topData.plan_qty:'0'}}</view>
                  </view>
                  <u-line direction="col" color="#ccc" style='margin-top: 35rpx;' length='60rpx'></u-line>
                  <view class="cont_item">
                     <view class="cont_item_title">完工数量</view>
                     <!-- <view class="cont_item_content">{{topData.end_qty?topData.end_qty:'0'}}</view> -->
                     <view class="cont_item_content">
                        {{topData.good_qty+topData.ng_qty+topData.laborbad_qty+topData.materielbad_qty ?topData.good_qty+topData.ng_qty+topData.laborbad_qty+topData.materielbad_qty:'0'}}
                     </view>
                  </view>
                  <u-line direction="col" color="#ccc" style='margin-top: 35rpx;' length='60rpx'></u-line>
                  <view class="cont_item">
                     <view class="cont_item_title">合格产出</view>
                     <view class="cont_item_content">{{topData.good_qty?topData.good_qty:'0'}}</view>
                  </view>
               </view>
               <view class="flex_between">
                  <view class="cont_item">
                     <view class="cont_item_title">缺陷产出</view>
                     <view class="cont_item_content">{{topData.ng_qty?topData.ng_qty:'0'}}</view>
                  </view>
                  <u-line direction="col" color="#ccc" style='margin-top: 35rpx;' length='60rpx'></u-line>
                  <view class="cont_item">
                     <view class="cont_item_title">工废产出</view>
                     <view class="cont_item_content">
                        {{topData.good_qty? topData.good_qty  :'0'}}
                     </view>
                  </view>
                  <u-line direction="col" color="#ccc" style='margin-top: 35rpx;' length='60rpx'></u-line>
                  <view class="cont_item">
                     <view class="cont_item_title">料废产出</view>
                     <view class="cont_item_content">
                        {{topData.materielbad_qty ? topData.materielbad_qty :'0'}}
                     </view>
                  </view>
               </view>
            </view>
            <view class="body_content">
               <view class="body_content_title" style="margin-bottom: 0;">生产工单</view>
               <view style="display: flex;justify-content: center;align-items: center;">
                  <!-- <view v-if="centerData.length===0" style="color: #c5c5c5;margin:120rpx auto;">暂无数据</view> -->
                  <echarts ref="pieEcharts" :option="pieOption" canvasId="pieEcharts"
                     style='width: 100%;height:360rpx;' />
               </view>
            </view>
            <view class="body_content" style="height: 440rpx;">
               <view class="body_content_title"
                  style="margin-bottom: 0;display: flex;justify-content: space-between;">
                  <view>不良统计Top5</view>
                  <view
                     style="background-color: #c5c5c5;padding: 5rpx;font-size: 12px;display: flex;border-radius: 6rpx;"
                     @click="operSheetShow=true">{{seleteValue}}
                     <u-icon :name="!operSheetShow?'arrow-down-fill':'arrow-up-fill'"></u-icon>
                  </view>
               </view>
               <view style="display: flex;justify-content: center;align-items: center;">
                  <!-- <view v-if="footerData.length===0" style="color: #c5c5c5;margin:120rpx auto;">暂无数据</view> -->
                  <echarts ref="barEcharts" :option="barOption" canvasId="barEcharts"
                     style='width: 100%;height:360rpx;' />
               </view>
            </view>
         </view>
      </view>
      <uni-calendar ref="calendar" :range='true' :insert="false" @confirm="calendarConfirm" />
      <u-picker :show="operSheetShow" :columns="columns" :itemHeight='55' :closeOnClickOverlay='true'
         @close='operSheetShow=false' @confirm='operSheetShowConfirm' @cancel='operSheetShow=false'></u-picker>
   </view>
</template>
<script>
   import echarts from '../../components/echarts-uniapp/echarts-uniapp.vue'
   import {
      ProductionKanban
   } from '../../config/api.js';
   export default {
      components: {
         echarts
      },
      onLoad(option) {},
      onPullDownRefresh() {
         setTimeout(() => {
            this.init(() => {
               uni.stopPullDownRefresh();
            })
         }, 1000);
      },
      data() {
         return {
            topRightMessageCount: '',
            calendarRange: new Date().getFullYear() + '-' + (new Date().getMonth() + 1).toString().padStart(
               2, '0') + '-01' + '~' + new Date().toISOString().slice(0, 10),
            operSheetShow: false, //切换不良统计Top5 底部滑出组件是否显示
            columns: [ //按产品统计:prt   按工序统计:stp
               ['按产品统计', '按工序统计']
            ],
            seleteValue: '按产品统计',
            topData: {},
            centerData: [],
            footerData: [],
            pieOption: {},
            barOption: {},
         }
      },
      created() {
      },
      mounted() {
         this.init()
         this.topRightMessageCount = uni.getStorageSync('topRightMessageCount')
         this.getData()
      },
      methods: {
         init() {
            uni.stopPullDownRefresh()
         },
         // 获取安灯消息列表长度
         getTopRightMessageCountIsChange(val) {
            this.topRightMessageCount = val
         },
         async getData() {
            const data = {
               Ratetime: this.calendarRange,
               defecttype: this.seleteValue === '按产品统计' ? 'prt' : 'stp',
            }
            const res = await ProductionKanban(data)
            if (res.code === '200') {
               this.topData = res.data.dt0[0]
               this.centerData = res.data.dt1.map(({
                  wo_coum,
                  wo_status
               }) => ({
                  name: wo_status + ' ' + wo_coum,
                  value: wo_coum
               }))
               this.footerData = res.data.dt2
               this.getPieEcharts()
               this.getTop5Echarts()
            }
         },
         // 绘制生产工单图
         getPieEcharts() {
            let sum = 0
            this.centerData.forEach(i => {
               sum += i.value
            })
            this.pieOption = {
               title: [{
                  text: '工单数',
                  subtext: sum + '个',
                  // textStyle: {
                  //    fontSize: 20,
                  //    color: "black"
                  // },
                  // subtextStyle: {
                  //    fontSize: 20,
                  //    color: 'black'
                  // },
                  textAlign: "center",
                  x: '33.5%',
                  y: '40%',
               }],
               legend: {
                  type: "scroll",
                  orient: 'vertical',
                  left: '70%',
                  align: 'left',
                  top: 'middle',
                  textStyle: {
                     color: '#8C8C8C'
                  },
                  height: 250
               },
               series: [{
                  name: '无数据',
                  type: 'pie',
                  center: ['35%', '50%'],
                  radius: ['40%', '65%'],
                  clockwise: false, //饼图的扇区是否是顺时针排布
                  avoidLabelOverlap: false,
                  label: {
                     normal: {
                        show: true,
                        position: 'outter',
                        formatter: function(parms) {
                           return parms.data.legendname
                        }
                     }
                  },
                  labelLine: {
                     normal: {
                        length: 5,
                        length2: 3,
                        smooth: true,
                     }
                  },
                  data: this.centerData
               }]
            };
         },
         //绘制不良统计Top5
         getTop5Echarts() {
            console.log(this.footerData);
            const barData = this.footerData.map(i => i.defect_qty) //柱状图数据
            const lineData = this.footerData.map(i => parseFloat((i.defect_qty * 100 / i.plan_qty).toFixed(
               2))) //折线图图数据
            const xData = this.seleteValue === '按产品统计' ? this.footerData.map(i => i.partname) : this.footerData.map(
               i => i.stepname) //x轴数据
            this.barOption = {
               grid: {
                  left: '5%',
                  right: '5%',
                  bottom: '10%',
                  top: '12%',
                  containLabel: true
               },
               xAxis: [{
                  type: 'category',
                  data: xData,
                  axisPointer: {
                     type: 'shadow'
                  },
                  axisLabel: {
                     interval: 0,
                     // rotate: 40,
                     formatter: function(value) {
                        if (value.length > 4) {
                           return `${value.slice(0, 4)}...`;
                        }
                        return value;
                     },
                  }
               }],
               yAxis: [{
                     type: 'value',
                     // name: 'Precipitation',
                     min: 0,
                     max: Math.floor((Math.max(...barData) * 1.2)),
                     // interval: 4,
                     splitNumber: 4,
                     axisLabel: {
                        formatter: '{value}'
                     }
                  },
                  {
                     show: false,
                     type: 'value',
                     // name: 'Temperature',
                     min: 0,
                     max: Math.floor((Math.max(...lineData) * 1.2)),
                     // interval: 4,
                     splitNumber: 4,
                     axisLabel: {
                        formatter: '{value} %'
                     }
                  }
               ],
               series: [{
                     name: 'Precipitation',
                     type: 'bar',
                     label: {
                        show: true
                     },
                     barWidth: 20,
                     itemStyle: {
                        color: '#356bff'
                     },
                     data: barData
                  },
                  {
                     name: 'Temperature',
                     type: 'line',
                     yAxisIndex: 1,
                     label: {
                        show: true,
                     },
                     itemStyle: {
                        color: '#0000ff',
                        "normal": {
                           "barBorderRadius": 0,
                           "label": {
                              "show": true,
                              "position": "top",
                              formatter: function(p) {
                                 return p.value + '%';
                              }
                           }
                        }
                     },
                     data: lineData
                  }
               ]
            };
         },
         operSheetShowConfirm(val) {
            this.seleteValue = val.value[0]
            this.operSheetShow = false
            this.getData()
         },
         calendarConfirm(val) {
            // this.calendarRange = val.range.before + '~' + val.range.after
            if (val.range.before < val.range.after) {
               this.calendarRange = val.range.before + '~' + val.range.after
            } else {
               this.calendarRange = val.range.after + '~' + val.range.before
            }
            if (val.range.before === '') {
               this.calendarRange = new Date().toISOString().slice(0, 10) + '~' + val.range.after
            }
            if (val.range.after === '') {
               this.calendarRange = val.range.before + '~' + new Date().toISOString().slice(0, 10)
            }
            if (val.range.before === '' && val.range.after === '') {
               this.calendarRange = new Date().toISOString().slice(0, 10) + '~' + new Date().toISOString()
                  .slice(0,
                     10)
            }
            this.getData()
         },
         calendarShowTrue() {
            this.$refs.calendar.open();
         }
      }
   }
</script>
<style>
<style lang="scss" scoped>
   @import url('@/style/global.css');
   ::v-deep .uicon-arrow-left>span {
      display: block;
   }
   .body {
      // min-height: 1382rpx;
      background-color: #0659FF !important;
      display: flex;
      flex-direction: column;
      padding: 20rpx 36rpx;
   }
   .body_head {
      display: flex;
      justify-content: space-between;
      align-items: center;
      line-height: 40rpx;
      height: 40rpx;
   }
   .body_head_title {
      font-size: 36rpx;
      // font-weight: 490;
      color: #fff;
   }
   ::v-deep .uni-select__input-placeholder {
      color: #ccc;
   }
   ::v-deep .uni-select__input-text {
      color: #fff;
   }
   ::v-deep .uniui-bottom {
      color: #fff !important;
   }
   ::v-deep .uniui-top {
      color: #fff !important;
   }
   .body_content {
      background-color: #fff;
      // max-height: 390rpx;
      margin: 12rpx 0;
      border-radius: 10rpx;
      display: flex;
      flex-direction: column;
   }
   .body_content_title {
      margin: 20rpx 30rpx 0;
      font-size: 32rpx;
      display: flex;
      align-items: center;
      font-weight: bolder;
   }
   ::v-deep .uni-tooltip-popup {
      width: 260rpx;
   }
   .cont_item {
      width: 33%;
      display: flex;
      justify-content: center;
      align-items: center;
      height: 120rpx;
      flex-direction: column;
      line-height: 50rpx;
      .cont_item_title {
         color: #ccc;
         font-size: 28rpx
      }
      .cont_item_content {
         font-weight: bolder;
      }
   }
   ::v-deep .uicon-calendar {
      font-size: 32rpx !important;
   }
</style>