zhaowei
2024-07-31 e5498c84797de1a07bbd0a8584dc4d14cabcc693
1、新增统计分析和报警分析页面
2、调整用户管理页面字段
已添加5个文件
已修改2个文件
2945 ■■■■ 文件已修改
src/views/mdc/base/StatisticsChart.vue 45 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/mdc/base/alarmAnalysis.vue 139 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/mdc/base/modules/StatisticsChart/StatisticsLegend.vue 866 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/mdc/base/modules/alarmAnalysis/alarmAnalysisMain.vue 543 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/system/UserList.vue 239 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/system/modules/SelectDeviceModal.vue 231 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/system/modules/UserModal.vue 882 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/mdc/base/StatisticsChart.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,45 @@
<template>
  <a-card :bordered="false">
      <div style="width: 100%; height: 100%;overflow: hidden">
        <a-row type="flex" :gutter="16">
          <a-col :md="5" :sm="24">
            <base-tree @getCurrSelected="changeSelectionNode"></base-tree>
          </a-col>
          <a-col :md="24-5" :sm="24">
              <statistics-legend  :equip="selectEquementnode"></statistics-legend>
          </a-col>
        </a-row>
      </div>
  </a-card>
</template>
<script>
  import BaseTree from '../common/BaseTree'
  import StatisticsLegend from './modules/StatisticsChart/StatisticsLegend'
  export default {
    name: 'StatisticsChart',
    components:{
      BaseTree,
      StatisticsLegend
    },
    data() {
      return {
        description: '设备信息',
        selectEquementnode:{},
        equipmentStatisticsInfo:{},
        url:{
          equipmentStatistics:"/mdc/equipment/equipmentStatistics"
        }
      }
    },
    methods: {
      changeSelectionNode(val){
        this.selectEquementnode = val
      }
    }
  }
</script>
<style scoped>
</style>
src/views/mdc/base/alarmAnalysis.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,139 @@
<template>
  <div style="width: 100%; height: 100%;">
    <a-card :bordered="false">
      <a-row type="flex" :gutter="16">
        <a-col :md="5">
          <a-tabs :activeKey="activeKey"  @change="tabChange">
            <a-tab-pane key="1" tab="车间层级" force-render>
              <base-tree @getCurrSelected="changeSelectionNode"></base-tree>
            </a-tab-pane>
            <a-tab-pane v-if="isDepartType == 0" key="2" tab="部门层级">,
              <depart-tree  @getCurrSelectedDD="changeSelectionNodedd"></depart-tree>
            </a-tab-pane>
          </a-tabs>
        </a-col>
        <a-col :md="19">
          <alarm-analysis-main  ref="alarmAnalysisMain" :nodePeople='selectPeople' :nodeTree = 'selectEquement' :Type="slectTypeTree"></alarm-analysis-main>
        </a-col>
      </a-row>
    </a-card>
  </div>
</template>
<script>
  import { putAction, getAction } from '@/api/manage'
  import { frozenBatch } from '@/api/api'
  import { JeecgListMixin } from '@/mixins/JeecgListMixin'
  import JInput from '@/components/jeecg/JInput'
  import BaseTree from '../common/BaseTree'
  import alarmAnalysisMain from './modules/alarmAnalysis/alarmAnalysisMain'
  import JSuperQuery from '@/components/jeecg/JSuperQuery'
  import JThirdAppButton from '@/components/jeecgbiz/thirdApp/JThirdAppButton'
  import DepartTree from './modules/DepartList/DepartListTree/DepartTree'
  import {mapActions} from 'vuex'
  export default {
    name: 'alarmAnalysis',
    components: {
      JThirdAppButton,
      JInput,
      BaseTree,
      JSuperQuery,
      DepartTree,
      alarmAnalysisMain
    },
    data() {
      return {
        activeKey: '1',
        description: '设备信息',
        selectEquementId: '',
        selectEquement: {},
        selectPeople:{},
        slectTypeTree:"",
        url: {
          equipmentStatistics: '/mdc/equipment/equipmentStatistics'
        },
        isDepartType:'',
      }
    },
    created() {
      this.queryTreeData()
    },
    methods: {
      ...mapActions(['QueryDepartTree']),
      queryTreeData() {
        this.QueryDepartTree().then(res => {
          if (res.success) {
            this.isDepartType = res.result[0].value
          } else {
            // this.$message.warn(res.message)
            this.$notification.warning({
              message:'消息',
              description:res.message
            });
          }
        }).finally(() =>{
        })
      },
      tabChange(val) {
        // console.log(val);
        this.activeKey = val
        this.slectTypeTree = val
      },
      // changeSelection(val) {
      //   this.selectEquementId = val
      //   this.$refs.efficiencyList.pQuery(val)
      //   this.$refs.efficiencyList.searchQuery()
      // },
      changeSelectionNode(val) {
        this.selectEquement = val
        this.slectTypeTree = "1"
      },
      changeSelectionNodedd(val) {
        this.selectPeople = val
        this.slectTypeTree = "2"
      }
    }
  }
</script>
<style scoped>
  @import '~@assets/less/common.less';
  .equipMessage {
    width: 100%;
    height: 10%;
  }
  .equipMessage table {
    width: 60%;
    height: 100%;
    line-height: 50%;
  }
  .equipMessage table td {
    text-align: center;
  }
  .equipMessage table td span {
    display: inline-block;
    width: 15px;
    height: 15px;
  }
  .equipMessage table td .equipShutdown {
    background-color: #808080;
  }
  .equipMessage table td .equipStandby {
    background-color: #ffbf37;
  }
  .equipMessage table td .equipRun {
    background-color: #19FE01;
  }
  .equipMessage table td .equipAlarm {
    background-color: #FD0008;
  }
</style>
src/views/mdc/base/modules/StatisticsChart/StatisticsLegend.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,866 @@
<template>
  <div id="StatisticsLegend"
       style="width: 100%; height: 100%; overflow: hidden;display: flex;flex-direction: column;background-color: #f5f4f4">
    <!-- æŸ¥è¯¢åŒºåŸŸ -->
    <div style="width: 100%; height: 44px; background-color: #fff" class="table-page-search-wrapper">
      <a-form layout="inline" @keyup.enter.native="searchQuery">
        <a-row :gutter="24">
          <a-col :md="5" :sm="5" :xs="5">
            <a-form-item label="名称">
              <a-input placeholder="输入设备名称查询" :readOnly="readOnly" v-model="queryParam.tierName"></a-input>
            </a-form-item>
          </a-col>
          <a-col :md="4" :sm="4" :xs="4">
            <a-form-item label="日期">
              <a-date-picker v-model="queryParams.collectTime" :disabledDate="disabledDate" format='YYYY-MM-DD'
                             @change="dataChange" :allowClear="false"/>
            </a-form-item>
          </a-col>
          <a-col :md="2" :sm="2" :xs="2">
            <a-space>
              <a-button type="primary" @click="searchQuery" icon="search">查询</a-button>
              <a-button type="primary" @click="searchReset" icon="reload">重置</a-button>
            </a-space>
          </a-col>
        </a-row>
      </a-form>
    </div>
    <!--开机率-->
    <div class="PowerOnRate  Line-box">
      <div class="title">
        <div class="circle"></div>
        <div class="text">利用率</div>
      </div>
      <div class="PowerOnRate-box box-bottom">
        <div class="PowerOnRate-left" ref="PowerOnRatePie" id="PowerOnRatePie"></div>
        <div class="PowerOnRate-right" ref="PowerOnRateLine" id="PowerOnRateLine"></div>
      </div>
    </div>
    <!--利用率和开动率-->
    <div class="UtilizationStartup">
      <div class="Utilization Line-box">
        <div class="title">
          <div class="circle"></div>
          <div class="text">开机率</div>
        </div>
        <div class="Utilization-box box-bottom">
          <div class="Utilization-left left">
            <div class="left-box">
              <div class="left-box-con">
                <div class="Rate-box-kong" :style="{height:100-UtilizationHeight+'%'}"></div>
                <div class="Rate-box" :style="{height:UtilizationHeight+'%'}">
                  <p class="Rate-box-text">
                    <span ref="UtilizationRate">{{UtilizationHeight}}%</span>
                    <br>
                    å¼€æœºçއ
                  </p>
                </div>
              </div>
            </div>
          </div>
          <div class="Utilization-right" ref="UtilizationLine" id="UtilizationLine"></div>
        </div>
      </div>
      <div class="Startup Line-box">
        <div class="title">
          <div class="circle"></div>
          <div class="text">开动率</div>
        </div>
        <div class="Startup-box box-bottom">
          <div class="Startup-left left" ref="StartupRate">
            <div class="left-box">
              <div class="left-box-con">
                <div class="Rate-box-kong" :style="{height:100-StartupHeight+'%'}"></div>
                <div class="Rate-box" :style="{height:StartupHeight+'%'}">
                  <p class="Rate-box-text">
                    <span>{{StatCharUsedopeningRate}}%</span>
                    <br>
                    å¼€åŠ¨çŽ‡
                  </p>
                </div>
              </div>
            </div>
          </div>
          <div class="Startup-right" ref="StartupLine" id="StartupLine"></div>
        </div>
      </div>
    </div>
  </div>
</template>
<script>
  import moment from 'moment'
  import { putAction, getAction } from '@/api/manage'
  import $ from 'jquery'
  import * as echarts from 'echarts'
  export default {
    name: 'StatisticsLegend',
    props: { equip: {} },
    data() {
      return {
        readOnly: true,
        showday: true,
        StatCharOpeningRate: 0,
        StatCharUsedRate: 0,
        StatCharUsedopeningRate: 0,
        openingLong: 0,
        waitingLong: 0,
        processLong: 0,
        closedLong: 0,
        totalLong: 0,
        UtilizationHeight: 0,
        StartupHeight: 0,
        quip: {},
        dates: [],
        queryParam: {},
        queryParams: {
          collectTime: undefined
        },
        shiftSubList: [],
        shiftList: [],
        url: {
          getEquipmentByPid: '/mdc/mdcequipment/getEquipmentByPid',
          dayStatisticalRate: '/mdc/efficiencyReport/dayStatisticalRate',
          getBaseTree: '/mdc/mdcEquipment/queryTreeListByProduction'
        }
      }
    },
    created() {
      let collectTime = moment(moment().add(-1, 'd'), 'YYYY-MM-DD')
      this.queryParams.collectTime = moment().add(-1, 'd').format('YYYY-MM-DD')
      this.queryParams.dateTime = moment().add(-1, 'd').format('YYYYMMDD')
      this.initEquipmentNode()
    },
    methods: {
      disabledDate(current) {
        //Can not slect days before today and today
        return current && current > moment().subtract('days', 1)
      },
      //把秒计算成对应的时分秒的函数
      getTime(time) {
        //转换为时分秒
        let h = Math.round(time / 60 / 60)
        h = h < 10 ? '0' + h : h
        //作为返回值返回
        // console.log(h);
        return h
      },
      moment,
      draw() {
        //利用率
        //饼图
        let PowerOnRatePie = this.$echarts.init(document.getElementById('PowerOnRatePie'), 'macarons')
        let PowerOnRatePie_option = {
          // color: ["#3859fa", '#ccc'],
          title: {
            text: this.StatCharUsedRate + '%',
            subtext: '利用率',
            textStyle: {
              color: '#268e80',
              fontSize: 18
            },
            subtextStyle: {
              color: '#292929'
            },
            x: 'center',
            y: 'center'
          },
          series: [{
            name: '',
            type: 'pie',
            radius: ['55%', '70%'],
            itemStyle: {
              normal: {
                borderWidth: 4,//扇区间加间隔
                borderColor: '#fff'//间隔为白色
              }
            },
            label: {
              normal: {
                show: false
              }
            },
            data: [{
              value: 100,
              itemStyle: {
                color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [{
                  offset: 0,
                  color: '#88a8fd'
                },
                  {
                    offset: 1,
                    color: '#544cee'
                  }], false)
              }
            },
              {
                value: 100 - this.StatCharUsedRate,
                itemStyle: {
                  color: '#f0f3f5'
                }
              }
            ]
          }
          ]
        }
        PowerOnRatePie.setOption(PowerOnRatePie_option)
        let PowerOnRateLine = this.$echarts.init(document.getElementById('PowerOnRateLine'), 'macarons')
        let PowerOnRateLine_option = {
          tooltip: {
            trigger: 'axis'
          },
          grid: {
            left: '3%',
            right: '4%',
            bottom: '3%',
            top: 60,
            containLabel: true
          },
          legend: {
            // selected:{
            //     "曲线":false,
            // },
            top: '0',
            right: '10',
            //设置单选多选模式
            // selectedMode:'single',
            icon: 'pin',
            data: [
              // {
              //   name:'曲线',
              //   textStyle:{
              //     padding:4,
              //     color:'#e957ff',
              //     // borderWidth:1,
              //     fontSize:16,
              //     // borderColor:'#50E6D7'
              //   }
              // },
              {
                name: '柱状图',
                textStyle: {
                  padding: 4,
                  fontSize: 16,
                  color: '#9996f8'
                  // borderWidth:1,
                  // borderColor:'#50E6D7'
                }
              }
            ]
          },
          xAxis: {
            type: 'category',
            data: ['开机时长', '关机时长', '运行时长', '待机时长'],
            axisLabel: {          //坐标轴字体颜色
              textStyle: {
                color: '#000'
              }
            },
            axisLine: {
              lineStyle: {
                color: '#e5e5e5'
              }
            },
            axisTick: {       //y轴刻度线
              show: false
            },
            splitLine: {    //网格
              show: false
            },
            boundaryGap: true
          },
          yAxis: {
            name: '时间/小时',
            type: 'value',
            axisLabel: {        //坐标轴字体颜色
              textStyle: {
                color: '#000'
              }
            },
            axisLine: {
              show: false
            },
            axisTick: {       //y轴刻度线
              show: false
            },
            splitLine: {    //网格
              show: true,
              lineStyle: {
                color: '#dadde4',
                type: 'dashed'
              }
            }
          },
          series: [
            //   {
            //   name:'曲线',
            //   type: 'line',
            //   smooth:true,
            //   symbol: 'circle',
            //   symbolSize: 8,
            //   label:{
            //     show:true,
            //     position:"top",
            //     textStyle:{
            //       color:'#000',
            //     },
            //     formatter:"时长:{c}H"
            //   },
            //   itemStyle: {
            //     color: "rgb(87, 120, 225)",
            //     borderColor: "#fff",
            //     borderWidth: 2,
            //     shadowColor: 'rgba(0, 0, 0, .3)',
            //   },
            //   lineStyle: {
            //     normal: {
            //       color:"rgb(87, 120, 225)",
            //       shadowColor: 'rgba(87, 120, 225, .4)',
            //       shadowBlur: 8,
            //       shadowOffsetY: 10,
            //       shadowOffsetX: 0,
            //     },
            //   },
            //   areaStyle: {
            //     normal: {
            //       color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [{
            //         offset: 0,
            //         color: 'rgba(87, 120, 225, .6)'
            //       }, {
            //         offset: 1,
            //         color: 'rgba(87, 120, 225, .3)'
            //       }]),
            //     }
            //   },
            //   data: [this.openingLong, this.closedLong, this.processLong,this.waitingLong],
            // },
            {
              name: '柱状图',
              type: 'bar',
              data: [this.openingLong, this.closedLong, this.processLong, this.waitingLong],
              // data:[22,3,5,6],
              barWidth: 25,
              label: {
                show: true,
                position: 'top',
                textStyle: {
                  color: '#000'
                },
                // formatter:"时长:{c}H",
                formatter: params => {
                  const value = String(params.value)
                  return value.length == 2 && value[0] === '0' ? `时长:${value.slice(1)}H` : `时长:${value}H`
                }
              },
              itemStyle: {
                normal: {
                  color: function(params) {
                    let colorList = [
                      ['#6496e9', '#6bded3'],
                      ['#849db8', '#b4b8cc'],
                      ['#4fe1c5', '#4ecee1'],
                      // ["#9978fa","#88a1fa"],
                      ['#ffbb65', '#fdc68b']
                    ]
                    // return colorList[params.dataIndex];
                    let colorItem = colorList[params.dataIndex]
                    return new echarts.graphic.LinearGradient(0, 0, 0, 1, [{
                      offset: 0,
                      color: colorItem[0]
                    },
                      {
                        offset: 1,
                        color: colorItem[1]
                      }], false)
                  },
                  barBorderRadius: [5, 5, 0, 0]
                }
              }
            }]
        }
        PowerOnRateLine.setOption(PowerOnRateLine_option)
        //开机率
        let UtilizationLine = this.$echarts.init(document.getElementById('UtilizationLine'), 'macarons')
        let UtilizationLine_option = {
          tooltip: {
            trigger: 'axis',
            axisPointer: {
              type: 'shadow'
            }
          },
          grid: {
            top: '15%',
            right: '3%',
            left: '10%',
            bottom: '12%'
          },
          xAxis: [{
            type: 'category',
            data: ['开机时长', '总时长'],
            axisLine: {
              lineStyle: {
                // color: 'rgba(70, 196, 255, .8)'
              }
            },
            axisTick: {
              show: false
            },
            axisLabel: {
              // color: 'rgba(111, 132, 189, 1)',
              textStyle: {
                fontSize: 14
              }
            }
          }],
          yAxis: [{
            type: 'value',
            name: '时间/小时',
            nameTextStyle: {
              // color: 'rgba(111, 132, 189, 1)'
            },
            axisLabel: {
              formatter: '{value}'
              // color: 'rgba(111, 132, 189, 1)',
            },
            axisTick: {
              show: false
            },
            axisLine: {
              show: false
            },
            splitLine: {
              lineStyle: {
                // color: 'rgba(70, 196, 255, .3)'
              }
            }
          }],
          series: [
            {
              type: 'bar',
              data: [this.openingLong, this.totalLong],
              // data:[22,22],
              barWidth: 25,
              label: {
                show: true,
                position: 'top',
                textStyle: {
                  color: '#000'
                },
                // formatter:"时长:{c}H",
                formatter: params => {
                  const value = String(params.value)
                  return value.length == 2 && value[0] === '0' ? `时长:${value.slice(1)}H` : `时长:${value}H`
                }
              },
              itemStyle: {
                normal: {
                  color: function(params) {
                    let colorList = [
                      ['#6496e9', '#6bded3'],
                      ['#9978fa', '#88a1fa']
                    ]
                    // return colorList[params.dataIndex];
                    let colorItem = colorList[params.dataIndex]
                    return new echarts.graphic.LinearGradient(0, 0, 0, 1, [{
                      offset: 0,
                      color: colorItem[0]
                    },
                      {
                        offset: 1,
                        color: colorItem[1]
                      }], false)
                  },
                  barBorderRadius: [5, 5, 0, 0]
                }
              }
            }]
        }
        UtilizationLine.setOption(UtilizationLine_option)
        //开动率
        let StartupLine = this.$echarts.init(document.getElementById('StartupLine'), 'macarons')
        let StartupLine_option = {
          tooltip: {
            trigger: 'axis',
            axisPointer: {
              type: 'shadow'
            }
          },
          grid: {
            top: '15%',
            right: '3%',
            left: '10%',
            bottom: '12%'
          },
          xAxis: [{
            type: 'category',
            data: ['运行时长', '开机时长'],
            axisLine: {
              lineStyle: {
                // color: 'rgba(70, 196, 255, .8)'
              }
            },
            axisTick: {
              show: false
            },
            axisLabel: {
              // color: 'rgba(111, 132, 189, 1)',
              textStyle: {
                fontSize: 14
              }
            }
          }],
          yAxis: [{
            type: 'value',
            name: '时间/小时',
            nameTextStyle: {
              // color: 'rgba(111, 132, 189, 1)'
            },
            axisLabel: {
              formatter: '{value}'
              // color: 'rgba(111, 132, 189, 1)',
            },
            axisTick: {
              show: false
            },
            axisLine: {
              show: false
            },
            splitLine: {
              lineStyle: {
                // color: 'rgba(70, 196, 255, .3)'
              }
            }
          }],
          series: [{
            type: 'bar',
            data: [this.processLong, this.openingLong],
            // data:[22,22],
            barWidth: 25,
            label: {
              show: true,
              position: 'top',
              textStyle: {
                color: '#000'
              },
              // formatter:"时长:{c}H",
              formatter: params => {
                const value = String(params.value)
                return value.length == 2 && value[0] === '0' ? `时长:${value.slice(1)}H` : `时长:${value}H`
              }
            },
            itemStyle: {
              normal: {
                color: function(params) {
                  let colorList = [
                    ['#4fe1c5', '#4ecee1'],
                    ['#6496e9', '#6bded3']
                  ]
                  // return colorList[params.dataIndex];
                  let colorItem = colorList[params.dataIndex]
                  return new echarts.graphic.LinearGradient(0, 0, 0, 1, [{
                    offset: 0,
                    color: colorItem[0]
                  },
                    {
                      offset: 1,
                      color: colorItem[1]
                    }], false)
                },
                barBorderRadius: [5, 5, 0, 0]
              }
            }
          }]
        }
        StartupLine.setOption(StartupLine_option)
      },
      queryStatistical() {
        getAction(this.url.dayStatisticalRate, this.queryParams).then(res => {
          if (res.success) {
            this.StatCharOpeningRate = res.result.openRate
            this.StatCharUsedRate = res.result.utilizationRate
            this.UtilizationHeight = res.result.openRate
            this.StatCharUsedopeningRate = res.result.usedOpenRate
            this.StartupHeight = res.result.usedOpenRate
            this.openingLong = this.getTime(res.result.openLong)
            this.waitingLong = this.getTime(res.result.waitLong)
            this.processLong = this.getTime(res.result.processLong)
            this.closedLong = this.getTime(res.result.closeLong)
            this.totalLong = parseInt(this.openingLong) + parseInt(this.closedLong)
            this.draw()
          }
        })
      },
      dataChange(val) {
        if (val) {
          this.queryParams.dateTime = val.format('YYYYMMDD')
          this.queryParams.collectTime = val.format('YYYY-MM-DD')
        }
      },
      initEquipmentNode() {
        let _this = this
        getAction(this.url.getBaseTree).then((res) => {
          if (res.success) {
            const { isEquipment, productionId, tierName } = this.$route.params
            // åˆ¤æ–­æ˜¯å¦æ˜¯ä»Žçœ‹æ¿è·³è½¬è¿‡æ¥ï¼ŒproductionId å­˜åœ¨åˆ™ä¸ºä»Žçœ‹æ¿è·³è½¬
            if (productionId) {
              // åˆ¤æ–­æ˜¯å¦ç‚¹å‡»çš„æ˜¯è®¾å¤‡å±‚级
              if (!isEquipment) {
                _this.$set(this.queryParams, 'parentId', productionId)
                _this.$set(this.queryParam, 'tierName', tierName)
              } else {
                _this.$set(this.queryParams, 'equipmentId', productionId)
                _this.$set(this.queryParam, 'tierName', productionId + '/' + tierName)
              }
            } else {
              if (res.result[0]) {
                _this.$set(this.queryParam, 'tierName', res.result[0].title)
                _this.$set(this.queryParams, 'parentId', res.result[0].key)
              }
            }
            this.queryStatistical()
          } else {
            this.$notification.warning({
              message: '消息',
              description: res.message
            })
          }
        }).finally(() => {
          this.loading = false
          this.cardLoading = false
        })
      },
      searchReset() {
        this.queryParam = {}
        this.queryParams = {
          collectTime: moment().add(-1, 'd').format('YYYY-MM-DD'),
          dateTime: moment().add(-1, 'd').format('YYYYMMDD')
        }
        this.initEquipmentNode()
      },
      searchQuery() {
        this.queryStatistical()
      }
    },
    watch: {
      equip(val) {
        // console.log(val);
        if (val && val.equipmentId) {
          this.$set(this.queryParam, 'tierName', val.title)
          this.$set(this.queryParam, 'equipmentId', val.equipmentId)
          this.queryParams.parentId = ''
          this.queryParams.equipmentId = val.equipmentId
        } else {
          this.queryParams.parentId = val.key
          this.queryParams.equipmentId = ''
          this.$set(this.queryParam, 'tierName', val.title)
        }
        this.searchQuery()
      }
      // this.searchQuery();
    }
  }
</script>
<style scoped>
  .charContent {
    display: flex;
  }
  @media screen and (min-width: 1920px) {
    #StatisticsLegend {
      height: 748px !important;
      overflow: scroll;
    }
  }
  @media screen and (min-width: 1680px) and (max-width: 1920px) {
    #StatisticsLegend {
      height: 748px !important;
      overflow: scroll;
    }
  }
  @media screen and (min-width: 1400px) and (max-width: 1680px) {
    #StatisticsLegend {
      height: 600px !important;
      overflow: scroll;
    }
  }
  @media screen and (min-width: 1280px) and (max-width: 1400px) {
    #StatisticsLegend {
      height: 501px !important;
      overflow: scroll;
    }
  }
  @media screen and (max-width: 1280px) {
    #StatisticsLegend {
      height: 501px !important;
      overflow: scroll;
    }
  }
  #StatisticsLegend .PowerOnRate {
    flex: 1;
    margin-bottom: 15px;
    background-color: #fff;
  }
  #StatisticsLegend .UtilizationStartup {
    flex: 1;
    display: flex;
  }
  #StatisticsLegend .UtilizationStartup > div {
    flex: 1;
    background-color: #fff;
  }
  #StatisticsLegend .UtilizationStartup .Utilization {
    margin-right: 15px;
  }
  .title {
    display: flex;
    align-items: center;
    padding-left: 15px;
    padding-top: 5px;
  }
  .title .circle {
    width: 15px;
    height: 15px;
    background-color: #7282ec;
    border-radius: 100%;
    margin-right: 10px;
  }
  .title .text {
    font-size: 2vh;
  }
  .Line-box {
    display: flex;
    flex-direction: column;
  }
  .Line-box .box-bottom {
    flex: 1;
  }
  .PowerOnRate-box {
    display: flex;
  }
  .PowerOnRate-box .PowerOnRate-left {
    width: 25%;
  }
  .PowerOnRate-box .PowerOnRate-right {
    flex: 1;
  }
  .Utilization-box {
    display: flex;
  }
  .Utilization-box .Utilization-left {
    width: 25%;
  }
  .Utilization-box .Utilization-right {
    flex: 1;
  }
  .Startup-box {
    display: flex;
  }
  .Startup-box .Startup-left {
    width: 25%;
  }
  .Startup-box .Startup-right {
    flex: 1;
  }
  .left {
    display: flex;
    align-items: center;
  }
  .left .left-box {
    width: 65%;
    height: 60%;
    margin: 0 auto;
    overflow: hidden;
    border-radius: 8px;
    /*border: 6px solid red;*/
    /*!*background-color: yellow;*!*/
    /*border-image: linear-gradient(to top, #2bf3c7, #06a8f8) 1;*/
  }
  .left-box-con {
    width: 100%;
    height: 100%;
    position: relative;
    text-align: center;
    border: 6px solid red;
    /*background-color: yellow;*/
    border-image: linear-gradient(to top, #2bf3c7, #06a8f8) 1;
  }
  .left .left-box .Rate-box-kong {
    width: 100%;
    background: -moz-linear-gradient(bottom, #b5dec2 0%, #f4f5ba 100%);
    background: -webkit-gradient(linear, bottom bottom, top top, color-stop(0%, #b5dec2), color-stop(100%, #f4f5ba));
    background: -webkit-linear-gradient(bottom, #b5dec2 0%, #f4f5ba 100%);
    background: -o-linear-gradient(bottom, #b5dec2 0%, #f4f5ba 100%);
    background: -ms-linear-gradient(bottom, #b5dec2 0%, #f4f5ba 100%);
    background: linear-gradient(to top, #b5dec2 0%, #f4f5ba 100%);
  }
  .left .left-box .Rate-box {
    position: absolute;
    text-align: center;
    bottom: 0;
    width: 100%;
    height: 89%;
    /*background-color: green;*/
    background: -moz-linear-gradient(bottom, #06a8f8 0%, #2bf3c7 100%);
    background: -webkit-gradient(linear, bottom bottom, top top, color-stop(0%, #06a8f8), color-stop(100%, #2bf3c7));
    background: -webkit-linear-gradient(bottom, #06a8f8 0%, #2bf3c7 100%);
    background: -o-linear-gradient(bottom, #06a8f8 0%, #2bf3c7 100%);
    background: -ms-linear-gradient(bottom, #06a8f8 0%, #2bf3c7 100%);
    background: linear-gradient(to top, #06a8f8 0%, #2bf3c7 100%);
  }
  .left .left-box .Rate-box p {
    position: absolute;
    bottom: 0;
    color: #fff;
    width: 100%;
    text-align: center;
  }
  .con-left {
    display: flex;
    flex-direction: column;
    flex-wrap: wrap;
    justify-content: space-around;
    align-items: center;
  }
  .con-left > span {
    flex: 1;
  }
</style>
src/views/mdc/base/modules/alarmAnalysis/alarmAnalysisMain.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,543 @@
<template>
  <div class="efficiency_list" style="width: 100%;height: 100%;">
    <div :bordered="false" style="height: 100%">
      <!-- æŸ¥è¯¢åŒºåŸŸ -->
      <div class="table-page-search-wrapper">
        <a-form layout="inline" @keyup.enter.native="searchQuery">
          <a-row :gutter="24">
            <a-col :md="7" :sm="7">
              <a-form-item label="时间">
                <a-range-picker @change="dateParamChange" :disabledDate="disabledDate" format="YYYYMMDD"
                                v-model="dates" :allowClear="false"/>
              </a-form-item>
            </a-col>
            <a-col :lg="2" :md="2" :sm="2" :xs="2">
              <a-button type="primary" @click="searchQuery" icon="search">查询</a-button>
            </a-col>
          </a-row>
        </a-form>
      </div>
      <div id="DeviceList">
        <div class="openRateTrendDg">
          <a-table :columns="columns" :data-source="dataList" bordered :pagination="false" :scroll="{y:210}"
                   :customRow="customRow"
                   rowKey="alarmCode" @expand="handleExpandChange" :loading="outerDataLoading"
          >
            <span slot="timeCount" slot-scope="text">{{text | getFormattedTime}}</span>
            <a-table
              slot="expandedRowRender"
              slot-scope="row"
              :columns="innerColumns"
              :data-source="row.innerDataList"
              :pagination="false"
              rowKey="rowIndex"
              :loading="innerDataLoading"
            >
              <span slot="duration" slot-scope="text">{{text | getFormattedTime}}</span>
            </a-table>
          </a-table>
        </div>
        <a-spin :spinning="echartLoading">
          <div style="width: 100%;height: 100%;display: flex;">
            <div id="MdcEquipmentWarningPie" style="height: 100%;width: 35%;"></div>
            <div id="MdcEquipmentWarningLine" style="height: 100%;width: 65%;"></div>
          </div>
        </a-spin>
      </div>
    </div>
  </div>
</template>
<script>
  import moment from 'moment'
  import { putAction, getAction } from '@/api/manage'
  import $ from 'jquery'
  import '@/components/table2excel/table2excel'
  import { ajaxGetDictItems, getDictItemsFromCache, duplicateCheck } from '@/api/api'
  import {
    JeecgListMixin
  } from '@/mixins/JeecgListMixin'
  const columns = [
    { title: '报警号', dataIndex: 'alarmCode', key: 'alarmCode', align: 'center' },
    { title: '出现次数', dataIndex: 'count', key: 'count', align: 'center', sorter: (a, b) => b.count - a.count },
    {
      title: '合计持续时间',
      dataIndex: 'timeCount',
      key: 'timeCount',
      scopedSlots: { customRender: 'timeCount' },
      align: 'center',
      sorter: (a, b) => b.timeCount - a.timeCount
    },
    { title: '报警信息', dataIndex: 'alarmContent', key: 'alarmContent', align: 'center', ellipsis: true }
  ]
  const innerColumns = [
    {
      title: '',
      dataIndex: 'rowIndex',
      key: 'rowIndex',
      width: 60,
      align: 'center',
      customRender: function(t, r, index) {
        return parseInt(index) + 1
      }
    },
    { title: '设备编号', dataIndex: 'equipmentId', key: 'equipmentId', align: 'center' },
    { title: '设备名称', dataIndex: 'equipmentName', key: 'equipmentName', align: 'center' },
    { title: '报警时间', dataIndex: 'startTime', key: 'startTime', align: 'center' },
    { title: '结束时间', dataIndex: 'endTime', key: 'endTime', align: 'center' },
    {
      title: '持续时间',
      dataIndex: 'duration',
      key: 'duration',
      scopedSlots: { customRender: 'duration' },
      align: 'center'
    }
  ]
  export default {
    // mixins: [JeecgListMixin],
    name: 'alarmAnalysisMain',
    components: {},
    data() {
      return {
        dataSource: [],
        /* table加载状态 */
        outerDataLoading: false,
        innerDataLoading: false,
        echartLoading: false,
        typeTree: '',
        typeParent: 1,
        typeEquipment: 1,
        TreeIDOne: 1,
        TreeIDTwo: 2,
        deviceTypeDict: '',
        dates: [],
        identifying: [],
        queryParam: {},
        queryParams: {},
        queryParamEquip: {},
        queryParamPeople: {},
        efficiencyOptions: [
          { label: '利用率', value: 'lyl' },
          { label: '开机率', value: 'kjl' },
          { label: '开机时间', value: 'kjsj' },
          { label: '加工时间', value: 'jgsj' },
          { label: '待机时间', value: 'djsj' },
          { label: '关机时间', value: 'gjsj' }
        ],
        checkedList: ['lyl'],
        dataList: [],
        url: {
          efficiencyList: '/mdc/alarmAnalyze/alarmList',
          listByType: '/mdc/MdcUtilizationRate/getByType',
          alarmTrend: '/mdc/alarmAnalyze/alarmTrend',
          equipmentAlarmList: '/mdc/alarmAnalyze/equipmentAlarmList'
        },
        tableHeads: [],
        pieDate: [0],
        XData: [0],
        YData: [0],
        columns,
        innerColumns,
        hasRequsetAlarmCodeList: []
      }
    },
    props: { nodeTree: '', Type: '', nodePeople: '' },
    /**
     * ç”Ÿå‘½å‘¨æœŸ æŒ‚载前
     * */
    created() {
      this.dates = [moment().subtract('days', 8), moment().subtract('days', 1)]
      this.queryParam.startDate = moment(this.dates[0]).format('YYYYMMDD')
      this.queryParam.endDate = moment(this.dates[1]).format('YYYYMMDD')
      this.queryParam.typeTree = '1'
      this.loadData1()
    },
    mounted() {
      this.drawWrin()
      window.addEventListener('resize', this.handleWindowResize)
    },
    beforeDestroy() {
      window.removeEventListener('resize', this.handleWindowResize)
    },
    watch: {
      Type(valmath) {
        this.dataList = []
        this.queryParam.typeTree = valmath
      },
      nodeTree(val) { //监听currSelected å˜åŒ–,将变化后的数值传递给 getCurrSelected äº‹ä»¶
        if (JSON.stringify(val) != '{}') {
          if (val.equipmentId != null) {
            this.queryParamEquip.parentId = ''
            this.queryParamEquip.equipmentId = val.equipmentId
          } else {
            this.queryParamEquip.parentId = val.key
            this.queryParamEquip.equipmentId = ''
          }
          /*这里你是监听到树得变化 æ˜¯ä¸æ˜¯è¯·æ±‚一次*/
          this.searchQuery()
        }
      },
      nodePeople(val) {
        if (JSON.stringify(val) != '{}') {
          if (val.equipmentId != null) {
            this.queryParamPeople.parentId = val.equipmentId
            this.queryParamPeople.equipmentId = ''
          } else {
            this.queryParamPeople.parentId = val.key
            this.queryParamPeople.equipmentId = ''
          }
          this.searchQuery()
        }
      }
    },
    filters: {
      numFilter(value) {
        if (value) {
          return parseFloat((value * 100).toFixed(2))
        } else {
          return '0'
        }
      },
      /**
       * æ ¼å¼åŒ–æ—¶é—´
       * @param seconds ç§’æ•°
       * @returns '' æ ¼å¼åŒ–后时间字符串
       */
      getFormattedTime(seconds) {
        var hours = Math.floor(seconds / 3600)
        var minutes = Math.floor((seconds % 3600) / 60)
        var secs = seconds % 60
        if (hours === 0) {
          if (minutes === 0) {
            return secs === 0 ? 0 : `${secs}秒`
          } else {
            if (secs === 0) {
              return `${minutes}分`
            }
            return `${minutes}分 ${secs}秒`
          }
        } else {
          if (minutes === 0 && secs === 0) {
            return `${hours}小时`
          } else if (minutes !== 0 && secs === 0) {
            return `${hours}小时 ${minutes}分`
          }
        }
        return `${hours}小时 ${minutes}分 ${secs}秒`
      }
    },
    methods: {
      numBerTwo(value) {
        if (value) {
          return parseFloat((value * 100).toFixed(2))
        } else {
          return '0'
        }
      },
      TableDraw(key, val) {
        let that = this
        that.echartLoading = true
        that.queryParam.alarmCode = val.alarmCode
        console.log(this.queryParam)
        getAction(that.url.alarmTrend, that.queryParam)
          .then(res => {
            if (res.success) {
              that.pieDate = res.result.equipmentCountList.map(item => {
                return {
                  name: item.key,
                  value: item.count
                }
              })
              that.XData = res.result.dateCountList.map(item => item.key)
              that.YData = res.result.dateCountList.map(item => item.count)
              // this.tableHeads = res.result.dates
              // this.dataList = res.result
              // this.draw()
              // this.checkSameData(this.dataList)
              // this.checkSameData1(this.dataList)
              // this.checkSameData2(this.dataList)
              // this.combineCell();
              // this.initDeviceType(this.dataList)
              that.drawWrin()
            }
          })
          .finally(() => {
            that.echartLoading = false
          })
        console.log(this.YData)
      },
      disabledDate(current) {
        //Can not slect days before today and today
        return current && current > moment().subtract('days', 1)
      },
      initDeviceType(deviceList) {
        let dictCode = 'mdc_equipmentType'
        let items = []
        items = getDictItemsFromCache(dictCode)
        if (deviceList && items.length > 0) {
          for (let a = 0; a < deviceList.length; a++) {
            if (items && items.length > 0) {
              for (let i = 0; i < items.length; i++) {
                if (deviceList[a].equipmentType == items[i].value) {
                  deviceList[a].equipmentType = items[i].title
                }
              }
            } else {
              ajaxGetDictItems(dictCode, null).then((res) => {
                if (res.success) {
                  let items = res.result
                  for (let i = 0; i < items.length; i++) {
                    if (deviceList[a].equipmentType == items[i].value) {
                      deviceList[a].equipmentType = items[i].title
                    }
                  }
                }
              })
            }
          }
        }
      },
      dateParamChange(v1, v2) {
        this.queryParam.startDate = v2[0]
        this.queryParam.endDate = v2[1]
      },
      searchQuery() {
        if (this.queryParam.typeTree == '1') {
          this.queryParam.parentId = this.queryParamEquip.parentId
          this.queryParam.equipmentId = this.queryParamEquip.equipmentId
        } else {
          this.queryParam.parentId = this.queryParamPeople.parentId
          this.queryParam.equipmentId = ''
        }
        this.loadData1()
      },
      loadData1() {
        this.outerDataLoading = true
        this.tableHeads = []
        this.dataList = []
        getAction(this.url.efficiencyList, this.queryParam).then(res => {
          if (res.success) {
            // this.tableHeads = res.result.dates
            this.dataList = res.result
            this.hasRequsetAlarmCodeList = []
            // this.draw()
            // this.checkSameData(this.dataList)
            // this.checkSameData1(this.dataList)
            // this.checkSameData2(this.dataList)
            // this.combineCell();
            // this.initDeviceType(this.dataList)
          }
        }).finally(() => {
          this.outerDataLoading = false
        })
      },
      drawWrin() {
        this.equipmentWarningPie = this.$echarts.init(document.getElementById('MdcEquipmentWarningPie'), 'macarons')
        let equipmentWarningPieOption = {
          title: {
            text: '各设备出现此报警的比例',
            x: 'center',
            y: 'bottom',
            textStyle: {
              color: '#4FAEDC'
            }
          },
          tooltip: {
            trigger: 'item',
            formatter: '<br/>{b} : {c} ({d}%)'
          },
          calculable: true,
          series: [{
            type: 'pie',
            radius: '60%',
            itemStyle: {
              normal: {
                color: function(params) {
                  var colorList = ['#5AB1EF', '#2EC7C9', '#B6A2DE', '#FFB980', '#D87A80', '#8D98B3']
                  return colorList[params.dataIndex]
                },
                label: {
                  show: true,
                  // position: 'top',
                  formatter: '{b}\n{c}',
                  color: function(params) {
                    var colorList = ['#5AB1EF', '#2EC7C9', '#B6A2DE', '#FFB980', '#D87A80', '#8D98B3']
                    return colorList[params.dataIndex]
                  }
                }
              }
            },
            data: this.pieDate
            // data:[{name:'jjjjjjj',value:'2'}]
          }]
        }
        this.equipmentWarningPie.setOption(equipmentWarningPieOption, true)
        this.equipmentWarningLine = this.$echarts.init(document.getElementById('MdcEquipmentWarningLine'), 'macarons')
        let equipmentWarningLineOption = {
          title: {
            text: '每天出现此报警的数量走势',
            x: 'center',
            y: 'bottom',
            textStyle: {
              color: '#4FAEDC'
            }
          },
          tooltip: {
            trigger: 'axis'
          },
          calculable: true,
          xAxis: [
            {
              type: 'category',
              show: true,
              data: this.XData
              /*axisLabel :{
                  interval:0
              }*/,
              axisLine: {
                //x轴线的颜色以及宽度
                show: true,
                lineStyle: {
                  width: 2,
                  color: '#4FAEDC'
                }
              }
            }
          ],
          yAxis: [
            {
              type: 'value',
              name: '次数',
              axisLine: {
                //x轴线的颜色以及宽度
                show: true,
                lineStyle: {
                  width: 2,
                  color: '#4FAEDC'
                }
              }
            }
          ],
          series: [
            {
              name: '报警数量',
              type: 'line',
              data: this.YData,
              markPoint: {
                data: [
                  { type: 'max', name: '最大值' },
                  { type: 'min', name: '最小值' }
                ],
                label: {
                  color: '#fff'
                }
              },
              itemStyle: {
                normal: {
                  color: '#2EC7C9'
                }
              }
            }
          ]
        }
        this.equipmentWarningLine.setOption(equipmentWarningLineOption, true)
      },
      /**
       * è‡ªå®šä¹‰è¡¨æ ¼è¡Œè§¦å‘
       * @param record å½“前行信息
       * @param index å½“前行下标
       * @returns {{on: {click: on.click}}} è¿”回对象
       */
      customRow(record, index) {
        return {
          on: {
            click: (event) => {
              // å¦‚果点击的不是展开图标区域则渲染图表,相反则相当于点击展开图标
              if (event.target.className !== 'ant-table-row-expand-icon-cell') {
                this.TableDraw(index, record)
              } else {
                if (event.target.children && event.target.children.length > 0) event.target.children[0].click()
              }
            }
          }
        }
      },
      /**
       * è‡ªå®šä¹‰è¡¨æ ¼è¡Œè§¦å‘
       * @param expanded å½“前行是否为展开状态
       * @param record å½“前行信息
       */
      handleExpandChange(expanded, record) {
        let _this = this
        // å½“展开时若该行未被展开过才会请求后台数据,展开过的数据会被缓存无需重复请求
        this.queryParam.alarmCode = record.alarmCode
        if (expanded && !this.hasRequsetAlarmCodeList.includes(record.alarmCode)) {
          this.innerDataLoading = true
          getAction(this.url.equipmentAlarmList, this.queryParam).then(res => {
            if (res.success) {
              _this.dataList.forEach(item => {
                if (item.alarmCode === record.alarmCode) {
                  item.innerDataList = res.result
                }
              })
              _this.hasRequsetAlarmCodeList.push(record.alarmCode)
            }
          })
            .finally(() => {
              _this.innerDataLoading = false
            })
        }
      },
      /**
       * å½“浏览器可视窗口尺寸发生改变时触发
       */
      handleWindowResize() {
        if (this.equipmentWarningPie) this.equipmentWarningPie.resize()
        if (this.equipmentWarningLine) this.equipmentWarningLine.resize()
      }
    }
  }
</script>
<style scoped>
  .efficiency_list #DeviceList {
    height: 90% !important;
  }
  /deep/ .ant-table-body .ant-table-row td {
    padding-top: 10px;
    padding-bottom: 10px;
  }
  /deep/ .ant-table-scroll > .ant-table-body > table > .ant-table-tbody > .ant-table-row td {
    cursor: pointer;
  }
  /deep/ .ant-spin-nested-loading {
    height: 55%;
  }
  /deep/ .ant-spin-container {
    height: 100%;
  }
  /deep/ .ant-table.ant-table-bordered {
    height: 265px;
  }
  /deep/ .ant-table-scroll > .ant-table-placeholder {
    height: 210px;
  }
</style>
src/views/system/UserList.vue
@@ -114,7 +114,7 @@
        :rowSelection="{selectedRowKeys: selectedRowKeys, onChange: onSelectChange}"
        @change="handleTableChange">
        <template slot="avatarslot" slot-scope="text, record, index">
        <template slot="avatarslot" slot-scope="text, record">
          <div class="anty-img-wrap">
            <a-avatar shape="square" :src="getAvatarView(record.avatar)" icon="user"/>
          </div>
@@ -178,6 +178,7 @@
</template>
<script>
  import UserModal from './modules/UserModal'
  import PasswordModal from './modules/PasswordModal'
  import {putAction,getFileAccessHttpUrl} from '@/api/manage';
@@ -188,6 +189,7 @@
  import UserRecycleBinModal from './modules/UserRecycleBinModal'
  import JSuperQuery from '@/components/jeecg/JSuperQuery'
  import JThirdAppButton from '@/components/jeecgbiz/thirdApp/JThirdAppButton'
  import {mapActions} from 'vuex'
  export default {
    name: "UserList",
@@ -233,41 +235,42 @@
          {
            title: '头像',
            align: "center",
            width: 120,
            width: 80,
            dataIndex: 'avatar',
            scopedSlots: {customRender: "avatarslot"}
          },
          {
            title: '性别',
            align: "center",
            width: 80,
            dataIndex: 'sex_dictText',
            sorter: true
          },
          {
            title: '生日',
            align: "center",
            width: 100,
            dataIndex: 'birthday'
          },
          {
            title: '手机号码',
            align: "center",
            width: 100,
            dataIndex: 'phone'
          },
          // {
          //   title: '性别',
          //   align: "center",
          //   width: 80,
          //   dataIndex: 'sex_dictText',
          //   sorter: true
          // },
          // {
          //   title: '生日',
          //   align: "center",
          //   width: 100,
          //   dataIndex: 'birthday'
          // },
          // {
          //   title: '手机号码',
          //   align: "center",
          //   width: 100,
          //   dataIndex: 'phone'
          // },
          {
            title: '部门',
            align: "center",
            width: 180,
            width: 240,
            dataIndex: 'orgCodeTxt'
          },
          {
            title: '负责部门',
            title: '车间',
            align: "center",
            width: 180,
            dataIndex: 'departIds_dictText'
            width: 240,
            dataIndex: 'productionName',
            ellipsis: true,
          },
          {
            title: '状态',
@@ -278,12 +281,14 @@
          {
            title: '操作',
            dataIndex: 'action',
            scopedSlots: {customRender: 'action'},
            scopedSlots: { customRender: 'action' },
            align: "center",
            width: 170
          }
            width: 80
          },
        ],
        isDepartType:'',
        superQueryFieldList: [
          { type: 'input', value: 'username', text: '用户账号', },
          { type: 'input', value: 'realname', text: '用户姓名', },
@@ -304,14 +309,180 @@
        return `${window._CONFIG['domianURL']}/${this.url.importExcelUrl}`;
      }
    },
    created() {
      this.queryTreeData()
    },
    methods: {
      ...mapActions(['QueryDepartTree']),
      queryTreeData() {
        this.QueryDepartTree().then(res => {
          if (res.success) {
            this.isDepartType = res.result[0].value
            if(this.isDepartType == -1){
              this.columns=[
                {
                  title: '用户账号',
                  align: "center",
                  dataIndex: 'username',
                  width: 120,
                  sorter: true
                },
                {
                  title: '用户姓名',
                  align: "center",
                  width: 100,
                  dataIndex: 'realname',
                },
                {
                  title: '头像',
                  align: "center",
                  width: 80,
                  dataIndex: 'avatar',
                  scopedSlots: {customRender: "avatarslot"}
                },
                // {
                //   title: '性别',
                //   align: "center",
                //   width: 80,
                //   dataIndex: 'sex_dictText',
                //   sorter: true
                // },
                // {
                //   title: '生日',
                //   align: "center",
                //   width: 100,
                //   dataIndex: 'birthday'
                // },
                // {
                //   title: '手机号码',
                //   align: "center",
                //   width: 100,
                //   dataIndex: 'phone'
                // },
                {
                  title: '车间',
                  align: "center",
                  width: 240,
                  dataIndex: 'productionName',
                  ellipsis: true,
                },
                {
                  title: '状态',
                  align: "center",
                  width: 80,
                  dataIndex: 'status_dictText'
                },
                {
                  title: '操作',
                  dataIndex: 'action',
                  scopedSlots: { customRender: 'action' },
                  align: "center",
                  width: 80
                },
              ]
            }else{
              this.columns= [
                {
                  title: '用户账号',
                  align: "center",
                  dataIndex: 'username',
                  width: 120,
                  sorter: true
                },
                {
                  title: '用户姓名',
                  align: "center",
                  width: 100,
                  dataIndex: 'realname',
                },
                {
                  title: '头像',
                  align: "center",
                  width: 80,
                  dataIndex: 'avatar',
                  scopedSlots: {customRender: "avatarslot"}
                },
                // {
                //   title: '性别',
                //   align: "center",
                //   width: 80,
                //   dataIndex: 'sex_dictText',
                //   sorter: true
                // },
                // {
                //   title: '生日',
                //   align: "center",
                //   width: 100,
                //   dataIndex: 'birthday'
                // },
                // {
                //   title: '手机号码',
                //   align: "center",
                //   width: 100,
                //   dataIndex: 'phone'
                // },
                {
                  title: '部门',
                  align: "center",
                  width: 240,
                  dataIndex: 'orgCodeTxt'
                },
                {
                  title: '车间',
                  align: "center",
                  width: 240,
                  dataIndex: 'productionName',
                  ellipsis: true,
                },
                {
                  title: '班组',
                  align: "center",
                  width: 240,
                  dataIndex: 'teamId_dictText'
                },
                {
                  title: '状态',
                  align: "center",
                  width: 80,
                  dataIndex: 'status_dictText'
                },
                {
                  title: '操作',
                  dataIndex: 'action',
                  scopedSlots: { customRender: 'action' },
                  align: "center",
                  width: 80
                }
              ]
            }
          } else {
            // this.$message.warn(res.message)
            this.$notification.warning({
              message:'消息',
              description:res.message
            });
          }
        }).finally(() =>{
        })
      },
      getAvatarView: function (avatar) {
        return getFileAccessHttpUrl(avatar)
      },
      batchFrozen: function (status) {
        if (this.selectedRowKeys.length <= 0) {
          this.$message.warning('请选择一条记录!');
          // this.$message.warning('请选择一条记录!');
          this.$notification.warning({
            message:'消息',
            description:"请选择一条记录"
          });
          return false;
        } else {
          let ids = "";
@@ -364,10 +535,16 @@
        }
        frozenBatch({ids: id, status: status}).then((res) => {
          if (res.success) {
            that.$message.success(res.message);
            that.$notification.success({
              message:'消息',
              description:res.message
            });
            that.loadData();
          } else {
            that.$message.warning(res.message);
            that.$notification.warning({
              message:'消息',
              description:res.message
            });
          }
        });
      },
src/views/system/modules/SelectDeviceModal.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,231 @@
<template>
  <a-modal
    :title="title"
    :visible="visible"
    @ok="handleOk"
    @cancel="handleCancel"
  >
    <a-spin :spinning="loading">
      <!-- showLine -->
      <a-form>
        <a-form-item label="车间层级:">
          <a-tree showLine ref="tree" :expandedKeys.sync="expandedKeys"
                  :treeData="treeDataSource" checkable @check="onCheck" v-model="checkedKeys"
                  @expand="onExpand">
          </a-tree>
        </a-form-item>
      </a-form>
    </a-spin>
    <template slot="footer">
      <div>
        <a-dropdown
          style="float: left"
          :trigger="['click']"
          placement="topCenter"
        >
          <a-menu slot="overlay">
            <a-menu-item key="1" @click="expandAll">展开所有</a-menu-item>
            <a-menu-item key="2" @click="closeAll">合并所有</a-menu-item>
            <a-menu-item key="3" @click="refreshTree">刷新</a-menu-item>
          </a-menu>
          <a-button>
            æ ‘操作
            <a-icon type="up"/>
          </a-button>
        </a-dropdown>
        <a-popconfirm title="确定放弃编辑?" @confirm="handleCancel" okText="确定" cancelText="取消">
          <a-button style="margin-right: .8rem">关闭</a-button>
        </a-popconfirm>
        <a-button
          @click="handleOk"
          type="primary"
        >确定
        </a-button>
      </div>
    </template>
  </a-modal>
</template>
<script>
  import {
    getAction,
    postAction,
    deleteAction
  } from '@/api/manage'
  import BaseTree from '@/views/mdc/common/BaseTree'
  import DepartTree from '@/views/mdc/base/modules/DepartList/DepartListTree/DepartTree'
  export default {
    name: 'SelectDeviceModal',
    components: {
      BaseTree, DepartTree
    },
    props: {
      editDisable: {
        type: Boolean,
        default() {
          return true
        }
      },
      title: {
        type: String
      },
      selectedProduction: {
        type: String
      }
    },
    data() {
      return {
        loading: false,
        treeDataSource: [],
        expandedKeys: [],
        checkedKeys: [],
        url: {
          getDeviceTree: '/mdc/mdcEquipment/loadTreeListByProductionIds'
        },
        selectedWorkshopIds: '',
        dataList: [],
        allTreeKeys: [],
        visible: false,
        dataSource: []
      }
    },
    created() {
      this.closeAll()
    },
    methods: {
      onExpand(expandedKeys) {
        this.expandedKeys = expandedKeys
        this.autoExpandParent = false
      },
      queryTreeData(value) {
        this.loading = true
        this.selectedWorkshopIds = value
        getAction(this.url.getDeviceTree, { ids: value })
          .then(res => {
            if (res.success) {
              this.dataList = []
              this.allTreeKeys = []
              this.getTreeDataSouce(res.result)
              this.treeDataSource = res.result
              this.generateList(this.treeDataSource)
              this.expandedKeys = this.allTreeKeys
            } else {
              this.$notification.warning({
                message: '消息',
                description: res.message
              })
            }
          })
          .catch(err => {
            this.$notification.error({
              message: '消息',
              description: err.message
            })
          })
          .finally(() => {
            this.loading = false
          })
      },
      generateList(data) {
        for (let i = 0; i < data.length; i++) {
          const node = data[i]
          const key = node.key
          const title = node.title
          this.dataList.push({
            key,
            title: title
          })
          this.allTreeKeys.push(key)
          if (node.children) {
            this.generateList(node.children)
          }
        }
      },
      getTreeDataSouce(data) {
        data.forEach(item => {
          if (item.children && item.children.length > 0) {
            this.getTreeDataSouce(item.children)
          }
          item.key = item.equipmentId ? item.equipmentId : item.key
          item.value = item.equipmentId ? item.equipmentId : item.value
        })
      },
      expandAll() {
        this.expandedKeys = this.allTreeKeys
      },
      closeAll() {
        this.expandedKeys = ['-1']
      },
      refreshTree() {
        this.queryTreeData(this.selectedWorkshopIds)
      },
      onCheck(value, obj) {
        this.checkedKeys = value
        this.deviceNodes = obj.checkedNodes.filter(item => item.data.props.equipmentId).map(item => item.data.props.equipmentId)
      },
      handleCancel() {
        this.visible = false
      },
      handleOk() {
        this.$emit('selectFinished', this.deviceNodes)
        this.visible = false
      }
    }
  }
</script>
<style lang="less" scoped>
  /deep/ .ant-modal {
    /*transform-origin: 337px 50px;*/
  }
  .ant-card-body .table-operator {
    margin-bottom: 18px;
  }
  .ant-table-tbody .ant-table-row td {
    padding-top: 15px;
    padding-bottom: 15px;
  }
  .anty-row-operator button {
    margin: 0 5px
  }
  .ant-btn-danger {
    background-color: #ffffff
  }
  .ant-modal-cust-warp {
    height: 100%
  }
  .ant-modal-cust-warp .ant-modal-body {
    height: calc(100% - 110px) !important;
    overflow-y: auto
  }
  .ant-modal-cust-warp .ant-modal-content {
    height: 90% !important;
    overflow-y: hidden
  }
  .drawer-bottom-button {
    position: absolute;
    bottom: 0;
    width: 100%;
    border-top: 1px solid #e8e8e8;
    padding: 10px 16px;
    text-align: right;
    left: 0;
    background: #fff;
    border-radius: 0 0 2px 2px;
  }
</style>
src/views/system/modules/UserModal.vue
@@ -1,485 +1,810 @@
<template>
  <a-drawer
          :title="title"
          :maskClosable="true"
          :width="drawerWidth"
          placement="right"
          :closable="true"
          @close="handleCancel"
          :visible="visible"
          style="height: 100%;">
    :title="title"
    :maskClosable="true"
    :width="drawerWidth"
    placement="right"
    :closable="true"
    @close="handleCancel"
    :visible="visible"
    style="height: 100%;overflow: auto;padding-bottom: 53px;"
  >
    <template slot="title">
      <div style="width: 100%;">
        <span>{{ title }}</span>
        <span style="display:inline-block;width:calc(100% - 51px);padding-right:10px;text-align: right">
          <a-button @click="toggleScreen" icon="appstore" style="height:20px;width:20px;border:0px"></a-button>
          <a-button
            @click="toggleScreen"
            icon="appstore"
            style="height:20px;width:20px;border:0px"
          ></a-button>
        </span>
      </div>
    </template>
    <a-spin :spinning="confirmLoading">
      <a-form-model ref="form" :model="model" :rules="validatorRules">
      <a-form-model
        ref="form"
        :model="model"
        :rules="validatorRules"
      >
        <a-form-model-item label="用户账号" :labelCol="labelCol" :wrapperCol="wrapperCol" prop="username">
          <a-input placeholder="请输入用户账号" v-model="model.username" :readOnly="!!model.id"/>
        <a-form-model-item
          label="用户账号"
          :labelCol="labelCol"
          :wrapperCol="wrapperCol"
          prop="username"
        >
          <a-input
            placeholder="请输入用户账号"
            v-model="model.username"
            :readOnly="!!model.id"
          />
        </a-form-model-item>
        <template v-if="!model.id">
          <a-form-model-item label="登录密码" :labelCol="labelCol" :wrapperCol="wrapperCol" prop="password" >
            <a-input type="password" placeholder="请输入登录密码" v-model="model.password" />
          <a-form-model-item
            label="登录密码"
            :labelCol="labelCol"
            :wrapperCol="wrapperCol"
            prop="password"
          >
            <a-input
              type="password"
              placeholder="请输入登录密码"
              v-model="model.password"
            />
          </a-form-model-item>
          <a-form-model-item label="确认密码" :labelCol="labelCol" :wrapperCol="wrapperCol" prop="confirmpassword" >
            <a-input type="password" @blur="handleConfirmBlur" placeholder="请重新输入登录密码" v-model="model.confirmpassword"/>
          <a-form-model-item
            label="确认密码"
            :labelCol="labelCol"
            :wrapperCol="wrapperCol"
            prop="confirmpassword"
          >
            <a-input
              type="password"
              @blur="handleConfirmBlur"
              placeholder="请重新输入登录密码"
              v-model="model.confirmpassword"
            />
          </a-form-model-item>
        </template>
        <a-form-model-item label="用户姓名" :labelCol="labelCol" :wrapperCol="wrapperCol" prop="realname">
          <a-input placeholder="请输入用户姓名" v-model="model.realname" />
        <a-form-model-item
          label="用户姓名"
          :labelCol="labelCol"
          :wrapperCol="wrapperCol"
          prop="realname"
        >
          <a-input
            placeholder="请输入用户姓名"
            v-model="model.realname"
          />
        </a-form-model-item>
        <a-form-model-item label="工号" :labelCol="labelCol" :wrapperCol="wrapperCol" prop="workNo">
          <a-input placeholder="请输入工号" v-model="model.workNo" />
        <a-form-model-item
          label="工号"
          :labelCol="labelCol"
          :wrapperCol="wrapperCol"
          prop="workNo"
        >
          <a-input
            placeholder="请输入工号"
            v-model="model.workNo"
          />
        </a-form-model-item>
        <a-form-model-item label="手机号码" :labelCol="labelCol" :wrapperCol="wrapperCol" prop="phone">
          <a-input placeholder="请输入手机号码" v-model="model.phone" />
        </a-form-model-item>
        <!--<a-form-model-item label="职务" :labelCol="labelCol" :wrapperCol="wrapperCol">-->
        <!--<j-select-position placeholder="请选择职务" :multiple="false" v-model="model.post"/>-->
        <!--</a-form-model-item>-->
        <a-form-model-item label="职务" :labelCol="labelCol" :wrapperCol="wrapperCol">
          <j-select-position placeholder="请选择职务" :multiple="false" v-model="model.post"/>
        </a-form-model-item>
        <a-form-model-item label="角色分配" :labelCol="labelCol" :wrapperCol="wrapperCol" v-show="!roleDisabled" >
        <a-form-model-item
          label="角色分配"
          :labelCol="labelCol"
          :wrapperCol="wrapperCol"
          v-show="!roleDisabled"
        >
          <j-multi-select-tag
                  :disabled="disableSubmit"
                  v-model="model.selectedroles"
                  :options="rolesOptions"
                  placeholder="请选择角色">
            :disabled="disableSubmit"
            v-model="model.selectedroles"
            :options="rolesOptions"
            placeholder="请选择角色"
          >
          </j-multi-select-tag>
        </a-form-model-item>
        <!--部门分配-->
        <a-form-model-item label="部门分配" :labelCol="labelCol" :wrapperCol="wrapperCol" v-show="!departDisabled">
          <j-select-depart v-model="model.selecteddeparts" :multi="true" @back="backDepartInfo" :backDepart="true" :treeOpera="true">></j-select-depart>
        <a-form-model-item
          v-if="isDepartType== 0"
          label="部门分配"
          :labelCol="labelCol"
          :wrapperCol="wrapperCol"
          v-show="!departDisabled"
        >
          <j-select-depart
            v-model="model.selecteddeparts"
            :multi="true"
            @back="backDepartInfo"
            :backDepart="true"
            :treeOpera="true"
          >>
          </j-select-depart>
        </a-form-model-item>
        <!--租户分配-->
        <a-form-model-item label="租户分配" :labelCol="labelCol" :wrapperCol="wrapperCol" v-show="!departDisabled">
          <j-multi-select-tag
                  :disabled="disableSubmit"
                  v-model="model.relTenantIds"
                  :options="tenantsOptions"
                  placeholder="请选择租户">
          </j-multi-select-tag>
        <!--车间分配-->
        <a-form-model-item
          label="车间分配"
          :labelCol="labelCol"
          :wrapperCol="wrapperCol"
          v-show="!productionDisabled"
        >
          <j-select-production
            v-model="model.selectedProduction"
            :multi="true"
            @back="backProductionInfo"
            :backProduction="true"
            :treeProductOpera="true"
          ></j-select-production>
        </a-form-model-item>
        <a-form-model-item label="身份" :labelCol="labelCol" :wrapperCol="wrapperCol">
          <a-radio-group  v-model="model.userIdentity"  @change="identityChange">
            <a-radio :value="1">普通用户</a-radio>
            <a-radio :value="2">上级</a-radio>
          </a-radio-group>
        </a-form-model-item>
        <a-form-model-item label="负责部门" :labelCol="labelCol" :wrapperCol="wrapperCol"  v-show="departIdShow==true">
          <j-multi-select-tag
                  :disabled="disableSubmit"
                  v-model="model.departIds"
                  :options="nextDepartOptions"
                  placeholder="请选择负责部门">
          </j-multi-select-tag>
        </a-form-model-item>
        <!--<a-form-model-item-->
          <!--label="选择设备"-->
          <!--:labelCol="labelCol"-->
          <!--:wrapperCol="wrapperCol"-->
          <!--v-show="!productionDisabled"-->
        <!--&gt;-->
          <!--<a-input-search-->
            <!--:readOnly="true"-->
            <!--v-model="model.equipmentIds"-->
            <!--@search="deviceSearch"-->
            <!--enter-button-->
            <!--placeholder="请选择设备"-->
            <!--:disabled="!model.selectedProduction"-->
          <!--/>-->
        <!--</a-form-model-item>-->
        <a-form-model-item label="头像" :labelCol="labelCol" :wrapperCol="wrapperCol">
          <j-image-upload class="avatar-uploader" text="上传" v-model="model.avatar" ></j-image-upload>
        </a-form-model-item>
        <!--<a-form-model-item-->
          <!--label="首页权限"-->
          <!--:labelCol="labelCol"-->
          <!--:wrapperCol="wrapperCol"-->
        <!--&gt;-->
          <!--<a-radio-group-->
            <!--v-model="model.userType"-->
            <!--:defaultValue="0"-->
          <!--&gt;-->
            <!--<a-radio :value="4">公司级</a-radio>-->
            <!--<a-radio :value="3">车间级</a-radio>-->
            <!--<a-radio :value="2">工段级</a-radio>-->
            <!--<a-radio :value="1">操作工</a-radio>-->
            <!--<a-radio :value="0">无</a-radio>-->
          <!--</a-radio-group>-->
        <!--</a-form-model-item>-->
        <a-form-model-item label="生日" :labelCol="labelCol" :wrapperCol="wrapperCol">
          <a-date-picker
                  style="width: 100%"
                  placeholder="请选择生日"
                  v-model="model.birthday"
                  :format="dateFormat"
                  :getCalendarContainer="node => node.parentNode"/>
        </a-form-model-item>
        <!--<a-form-model-item-->
          <!--label="班组分配"-->
          <!--:labelCol="labelCol"-->
          <!--:wrapperCol="wrapperCol"-->
          <!--prop="teamId"-->
        <!--&gt;-->
          <!--<j-dict-select-tag-->
            <!--v-model="model.teamId"-->
            <!--:triggerChange="true"-->
            <!--dictCode="mom_base_team,name,id,del_flag = 0"-->
            <!--placeholder="请维护班组"-->
          <!--&gt;</j-dict-select-tag>-->
        <!--</a-form-model-item>-->
        <!--<a-form-model-item-->
          <!--label="中心分配"-->
          <!--:labelCol="labelCol"-->
          <!--:wrapperCol="wrapperCol"-->
          <!--prop="areaId"-->
        <!--&gt;-->
          <!--&lt;!&ndash; <j-dict-select-tag-->
            <!--v-model="model.areaId"-->
            <!--:triggerChange="true"-->
            <!--dictCode="mom_base_area,name,id,del_flag = 0"-->
            <!--placeholder="请维护中心"-->
          <!--&gt;</j-dict-select-tag> &ndash;&gt;-->
          <!--<j-multi-select-tag-->
            <!--:triggerChange="true"-->
            <!--v-model="model.areaId"-->
            <!--dictCode="mom_base_area,name,id,del_flag = 0 and type = 1"-->
            <!--placeholder="请维护中心"-->
          <!--&gt;-->
          <!--</j-multi-select-tag>-->
        <!--</a-form-model-item>-->
        <!--<a-form-model-item-->
          <!--label="负责部门"-->
          <!--:labelCol="labelCol"-->
          <!--:wrapperCol="wrapperCol"-->
          <!--v-if="departIdShow==true"-->
        <!--&gt;-->
          <!--<j-multi-select-tag-->
            <!--:disabled="disableSubmit"-->
            <!--v-model="model.departIds"-->
            <!--:options="nextDepartOptions"-->
            <!--placeholder="请选择负责部门"-->
          <!--&gt;-->
          <!--</j-multi-select-tag>-->
        <!--</a-form-model-item>-->
        <a-form-model-item label="性别" :labelCol="labelCol" :wrapperCol="wrapperCol">
          <a-select  v-model="model.sex"  placeholder="请选择性别" :getPopupContainer= "(target) => target.parentNode">
            <a-select-option :value="1">男</a-select-option>
            <a-select-option :value="2">女</a-select-option>
          </a-select>
        </a-form-model-item>
        <!--<a-form-model-item-->
        <!--label="头像"-->
        <!--:labelCol="labelCol"-->
        <!--:wrapperCol="wrapperCol"-->
        <!--&gt;-->
        <!--<j-image-upload-->
        <!--class="avatar-uploader"-->
        <!--text="上传"-->
        <!--v-model="model.avatar"-->
        <!--&gt;</j-image-upload>-->
        <!--</a-form-model-item>-->
        <a-form-model-item label="邮箱" :labelCol="labelCol" :wrapperCol="wrapperCol" prop="email">
          <a-input placeholder="请输入邮箱" v-model="model.email" />
        </a-form-model-item>
        <!--<a-form-model-item-->
        <!--label="生日"-->
        <!--:labelCol="labelCol"-->
        <!--:wrapperCol="wrapperCol"-->
        <!--&gt;-->
        <!--<a-date-picker-->
        <!--style="width: 100%"-->
        <!--placeholder="请选择生日"-->
        <!--v-model="model.birthday"-->
        <!--:format="dateFormat"-->
        <!--:getCalendarContainer="node => node.parentNode"-->
        <!--/>-->
        <!--</a-form-model-item>-->
        <a-form-model-item label="座机" :labelCol="labelCol" :wrapperCol="wrapperCol" prop="telephone">
          <a-input placeholder="请输入座机" v-model="model.telephone" />
        </a-form-model-item>
        <!--<a-form-model-item-->
        <!--label="性别"-->
        <!--:labelCol="labelCol"-->
        <!--:wrapperCol="wrapperCol"-->
        <!--&gt;-->
        <!--<a-select-->
        <!--v-model="model.sex"-->
        <!--placeholder="请选择性别"-->
        <!--:getPopupContainer="(target) => target.parentNode"-->
        <!--&gt;-->
        <!--<a-select-option :value="1">男</a-select-option>-->
        <!--<a-select-option :value="2">女</a-select-option>-->
        <!--</a-select>-->
        <!--</a-form-model-item>-->
        <a-form-model-item label="工作流引擎" :labelCol="labelCol" :wrapperCol="wrapperCol">
          <j-dict-select-tag  v-model="model.activitiSync"  placeholder="请选择是否同步工作流引擎" :type="'radio'" dictCode="activiti_sync"/>
        </a-form-model-item>
        <!--<a-form-model-item-->
        <!--label="邮箱"-->
        <!--:labelCol="labelCol"-->
        <!--:wrapperCol="wrapperCol"-->
        <!--prop="email"-->
        <!--&gt;-->
        <!--<a-input-->
        <!--placeholder="请输入邮箱"-->
        <!--v-model="model.email"-->
        <!--/>-->
        <!--</a-form-model-item>-->
        <!--<a-form-model-item-->
        <!--label="手机号码"-->
        <!--:labelCol="labelCol"-->
        <!--:wrapperCol="wrapperCol"-->
        <!--prop="phone"-->
        <!--&gt;-->
        <!--<a-input-->
        <!--placeholder="请输入手机号码"-->
        <!--v-model="model.phone"-->
        <!--/>-->
        <!--</a-form-model-item>-->
        <!--<a-form-model-item-->
        <!--label="座机"-->
        <!--:labelCol="labelCol"-->
        <!--:wrapperCol="wrapperCol"-->
        <!--prop="telephone"-->
        <!--&gt;-->
        <!--<a-input-->
        <!--placeholder="请输入座机"-->
        <!--v-model="model.telephone"-->
        <!--/>-->
        <!--</a-form-model-item>-->
        <!--<a-form-model-item label="工作流引擎" :labelCol="labelCol" :wrapperCol="wrapperCol">-->
        <!--<j-dict-select-tag  v-model="model.activitiSync"  placeholder="请选择是否同步工作流引擎" :type="'radio'" dictCode="activiti_sync"/>-->
        <!--</a-form-model-item>-->
      </a-form-model>
    </a-spin>
    <div class="drawer-bootom-button" v-show="!disableSubmit">
      <a-popconfirm title="确定放弃编辑?" @confirm="handleCancel" okText="确定" cancelText="取消">
    <div
      class="drawer-bottom-button"
      v-show="!disableSubmit"
    >
      <a-popconfirm
        title="确定放弃编辑?"
        @confirm="handleCancel"
        okText="确定"
        cancelText="取消"
      >
        <a-button style="margin-right: .8rem">取消</a-button>
      </a-popconfirm>
      <a-button @click="handleSubmit" type="primary" :loading="confirmLoading">提交</a-button>
      <a-button
        @click="handleSubmit"
        type="primary"
        :loading="confirmLoading"
      >提交
      </a-button>
    </div>
    <select-device-modal
      ref="selectDeviceModal"
      @selectFinished="selectOK"
      :title="'选择设备'"
    />
  </a-drawer>
</template>
<script>
  import moment from 'moment'
  import Vue from 'vue'
  import { ACCESS_TOKEN } from "@/store/mutation-types"
  import { ACCESS_TOKEN } from '@/store/mutation-types'
  import { getAction } from '@/api/manage'
  import { addUser,editUser,queryUserRole,queryall } from '@/api/api'
  import { disabledAuthFilter } from "@/utils/authFilter"
  import { addUser, editUser, queryUserRole, queryall } from '@/api/api'
  import { disabledAuthFilter } from '@/utils/authFilter'
  import { duplicateCheck } from '@/api/api'
  import JSelectProduction from '../../../components/jeecgbiz/JSelectProduction'
  import { mapActions } from 'vuex'
  import { ajaxGetDictItems, getDictItemsFromCache } from '@/api/api'
  import SelectDeviceModal from './SelectDeviceModal'
  export default {
    name: "UserModal",
    name: 'UserModal',
    components: {
      SelectDeviceModal,
      JSelectProduction
    },
    data () {
    data() {
      return {
        departDisabled: false, //是否是我的部门调用该页面
        productionDisabled: false, //是否是我的车间调用该页面
        roleDisabled: false, //是否是角色维护调用该页面
        modalWidth:800,
        drawerWidth:700,
        modaltoggleFlag:true,
        modalWidth: 800,
        drawerWidth: 700,
        modaltoggleFlag: true,
        confirmDirty: false,
        userId:"", //保存用户id
        disableSubmit:false,
        dateFormat:"YYYY-MM-DD",
        validatorRules:{
          username:[{required: true, message: '请输入用户账号!'},
            {validator: this.validateUsername,}],
          password: [{required: true,pattern:/^(?=.*[a-zA-Z])(?=.*\d)(?=.*[~!@#$%^&*()_+`\-={}:";'<>?,./]).{8,}$/,message: '密码由8位数字、大小写字母和特殊符号组成!'},
            {validator: this.validateToNextPassword,trigger: 'change'}],
          confirmpassword: [{required: true, message: '请重新输入登录密码!',},
            { validator: this.compareToFirstPassword,}],
          realname:[{ required: true, message: '请输入用户名称!' }],
          phone: [{required: true, message: '请输入手机号!'}, {validator: this.validatePhone}],
          email: [{validator: this.validateEmail}],
          roles:{},
          workNo:[ { required: true, message: '请输入工号' },
        userId: '', //保存用户id
        disableSubmit: false,
        dateFormat: 'YYYY-MM-DD',
        validatorRules: {
          username: [{ required: true, message: '请输入用户账号!' },
            { validator: this.validateUsername }],
          password: [{
            required: true,
            pattern: /^(?=.*[a-zA-Z])(?=.*\d)(?=.*[~!@#$%^&*()_+`\-={}:";'<>?,./]).{8,}$/,
            message: '密码由8位数字、大小写字母和特殊符号组成!'
          },
            { validator: this.validateToNextPassword, trigger: 'change' }],
          confirmpassword: [{ required: true, message: '请重新输入登录密码!' },
            { validator: this.compareToFirstPassword }],
          realname: [{ required: true, message: '请输入用户名称!' }],
          phone: [{ required: false, message: '请输入手机号!' }, { validator: this.validatePhone }],
          email: [{ validator: this.validateEmail }],
          roles: {},
          workNo: [{ required: true, message: '请输入工号' },
            { validator: this.validateWorkNo }],
          telephone: [{ pattern: /^0\d{2,3}-[1-9]\d{6,7}$/, message: '请输入正确的座机号码' },]
          telephone: [{ pattern: /^0\d{2,3}-[1-9]\d{6,7}$/, message: '请输入正确的座机号码' }],
          teamId: [{ required: false, message: '请维护班组' }]
        },
        departIdShow:false,
        title:"操作",
        departIdShow: false,
        title: '操作',
        visible: false,
        model: {},
        labelCol: {
          xs: { span: 24 },
          sm: { span: 5 },
          sm: { span: 5 }
        },
        wrapperCol: {
          xs: { span: 24 },
          sm: { span: 16 },
          sm: { span: 16 }
        },
        uploadLoading:false,
        uploadLoading: false,
        confirmLoading: false,
        headers:{},
        headers: {},
        url: {
          fileUpload: window._CONFIG['domianURL']+"/sys/common/upload",
          userWithDepart: "/sys/user/userDepartList", // å¼•入为指定用户查看部门信息需要的url
          userId:"/sys/user/generateUserId", // å¼•入生成添加用户情况下的url
          syncUserByUserName:"/act/process/extActProcess/doSyncUserByUserName",//同步用户到工作流
          fileUpload: window._CONFIG['domianURL'] + 'sys/common/upload',
          userWithDepart: '/sys/user/userDepartList', // å¼•入为指定用户查看部门信息需要的url
          //引入为指定用户查看车间信息需要的url
          userProductionList: '/sys/user/userProductionList',
          userId: '/sys/user/generateUserId', // å¼•入生成添加用户情况下的url
          syncUserByUserName: '/act/process/extActProcess/doSyncUserByUserName',//同步用户到工作流
          queryTenantList: '/sys/tenant/queryList'
        },
        tenantsOptions: [],
        rolesOptions:[],
        nextDepartOptions:[],
        rolesOptions: [],
        nextDepartOptions: [],
        nextProductionOptions: [],
        isDepartType: '',
        model: {
          selectedProduction: ''
        }
      }
    },
    created () {
      const token = Vue.ls.get(ACCESS_TOKEN);
      this.headers = {"X-Access-Token":token}
    watch: {
      visible: {
        handler(value) {
          if (value) this.initDictData('password_length')
        }
      },
      'model.selectedProduction': {
        handler(newVal, oldVal) {
          if (newVal && this.$refs.selectDeviceModal) {
            // å¦‚果车间选择前后不一致则重置选择设备
            if ((oldVal && newVal !== oldVal)) this.model.equipmentIds = ''
            this.$refs.selectDeviceModal.queryTreeData(newVal)
          }
          // å¦‚果清空车间值则重置选择设备
          if (newVal === '') this.model.equipmentIds = ''
        }
      }
    },
    created() {
      const token = Vue.ls.get(ACCESS_TOKEN)
      this.headers = { 'X-Access-Token': token }
      this.initRoleList()
      this.initTenantList()
      this.queryTreeData()
    },
    computed:{
      uploadAction:function () {
        return this.url.fileUpload;
    computed: {
      uploadAction: function () {
        return this.url.fileUpload
      }
    },
    methods: {
      add () {
        this.refresh();
        this.edit({activitiSync:'1',userIdentity:1});
      ...mapActions(['QueryDepartTree']),
      queryTreeData() {
        this.QueryDepartTree().then(res => {
          if (res.success) {
            this.isDepartType = res.result[0].value
          } else {
            // this.$message.warn(res.message)
            this.$notification.warning({
              message: '消息',
              description: res.message
            })
          }
        }).finally(() => {
        })
      },
      edit (record) {
        let that = this;
        that.visible = true;
      add() {
        this.refresh()
        this.edit({
          activitiSync: '1',
          userType: 0,
          userIdentity: 1,
          selectedroles: '',
          selecteddeparts: '',
          selectedProduction: ''
        })
      },
      edit(record) {
        let that = this
        that.visible = true
        //根据屏幕宽度自适应抽屉宽度
        this.resetScreenSize();
        that.userId = record.id;
        that.model = Object.assign({},{selectedroles:'',selecteddeparts:''}, record);
        this.resetScreenSize()
        that.userId = record.id
        console.log('record', record)
        that.model = Object.assign({}, record)
        //身份为上级显示负责部门,否则不显示
        if(this.model.userIdentity==2){
          this.departIdShow=true;
        }else{
          this.departIdShow=false;
        if (this.model.userIdentity == 2) {
          this.departIdShow = true
        } else {
          this.departIdShow = false
        }
        if(record.hasOwnProperty("id")){
          that.getUserRoles(record.id);
          that.getUserDeparts(record.id);
        if (record.hasOwnProperty('id')) {
          that.getUserRoles(record.id)
          that.getUserDeparts(record.id)
        }
        console.log('that.model=',that.model)
      },
      isDisabledAuth(code){
        return disabledAuthFilter(code);
      isDisabledAuth(code) {
        return disabledAuthFilter(code)
      },
      //窗口最大化切换
      toggleScreen(){
        if(this.modaltoggleFlag){
          this.modalWidth = window.innerWidth;
        }else{
          this.modalWidth = 800;
      toggleScreen() {
        if (this.modaltoggleFlag) {
          this.modalWidth = window.innerWidth
        } else {
          this.modalWidth = 800
        }
        this.modaltoggleFlag = !this.modaltoggleFlag;
        this.modaltoggleFlag = !this.modaltoggleFlag
      },
      // æ ¹æ®å±å¹•变化,设置抽屉尺寸
      resetScreenSize(){
        let screenWidth = document.body.clientWidth;
        if(screenWidth < 500){
          this.drawerWidth = screenWidth;
        }else{
          this.drawerWidth = 700;
      resetScreenSize() {
        let screenWidth = document.body.clientWidth
        if (screenWidth < 500) {
          this.drawerWidth = screenWidth
        } else {
          this.drawerWidth = 700
        }
      },
      //初始化租户字典
      initTenantList(){
        getAction(this.url.queryTenantList).then(res=>{
          if(res.success){
            this.tenantsOptions = res.result.map((item,index,arr)=>{
              let c = {label:item.name, value: item.id+""}
              return c;
      initTenantList() {
        getAction(this.url.queryTenantList).then(res => {
          if (res.success) {
            this.tenantsOptions = res.result.map((item, index, arr) => {
              let c = { label: item.name, value: item.id + '' }
              return c
            })
            console.log('this.tenantsOptions: ',this.tenantsOptions)
          }
        })
      },
      //初始化角色字典
      initRoleList(){
        queryall().then((res)=>{
          if(res.success){
            this.rolesOptions = res.result.map((item,index,arr)=>{
              let c = {label:item.roleName, value:item.id}
              return c;
      initRoleList() {
        queryall().then((res) => {
          if (res.success) {
            this.rolesOptions = res.result.map((item, index, arr) => {
              let c = { label: item.roleName, value: item.id }
              return c
            })
            console.log('this.rolesOptions: ',this.rolesOptions)
          }
        });
        })
      },
      getUserRoles(userid){
        queryUserRole({userid:userid}).then((res)=>{
          if(res.success){
            this.model.selectedroles = res.result.join(",");
            console.log('that.model.selectedroles=',this.model.selectedroles)
      getUserRoles(userid) {
        queryUserRole({ userid: userid }).then((res) => {
          if (res.success) {
            this.$set(this.model, 'selectedroles', res.result.join(','))
          }
        });
        })
      },
      getUserDeparts(userid){
        let that = this;
        getAction(that.url.userWithDepart,{userId:userid}).then((res)=>{
          if(res.success){
            let departOptions=[];
            let selectDepartKeys=[]
      getUserDeparts(userid) {
        let that = this
        //部门的url èŽ·å–éƒ¨é—¨åˆ†é…
        getAction(that.url.userWithDepart, { userId: userid }).then((res) => {
          if (res.success) {
            let departOptions = []
            let selectDepartKeys = []
            for (let i = 0; i < res.result.length; i++) {
              selectDepartKeys.push(res.result[i].key);
              selectDepartKeys.push(res.result[i].key)
              //新增负责部门选择下拉框
              departOptions.push({
                value: res.result[i].key,
                label: res.result[i].title
              })
            }
            that.model.selecteddeparts = selectDepartKeys.join(",")
            that.nextDepartOptions=departOptions;
            console.log('that.nextDepartOptions=',that.nextDepartOptions)
            this.$set(this.model, 'selecteddeparts', selectDepartKeys.join(','))
            that.nextDepartOptions = departOptions
          }
        })
        // èŽ·å–è½¦é—´åˆ†é…
        getAction(that.url.userProductionList, { userId: userid }).then((res) => {
          if (res.success) {
            let ProductionOptions = []
            let selectProductKeys = []
            for (let i = 0; i < res.result.length; i++) {
              selectProductKeys.push(res.result[i].key)
              //新增负责部门选择下拉框
              ProductionOptions.push({
                value: res.result[i].key,
                label: res.result[i].title
              })
            }
            this.$set(this.model, 'selectedProduction', selectProductKeys.join(','))
            that.nextProductionOptions = ProductionOptions
          }
        })
        //车间的url
      },
      backDepartInfo(info) {
        this.model.departIds = this.model.selecteddeparts;
        this.nextDepartOptions = info.map((item,index,arr)=>{
          let c = {label:item.text, value: item.value+""}
          return c;
        this.model.departIds = this.model.selecteddeparts
        this.nextDepartOptions = info.map((item, index, arr) => {
          let c = { label: item.text, value: item.value + '' }
          return c
        })
      },
      refresh () {
        this.userId=""
        this.nextDepartOptions=[];
        this.departIdShow=false;
      backProductionInfo(info) {
        this.model.productionIds = this.model.selectedProduction
        this.nextProductionOptions = info.map((item, index, arr) => {
          let c = { label: item.text, value: item.value + '' }
          return c
        })
      },
      close () {
        this.$emit('close');
        this.visible = false;
        this.disableSubmit = false;
        this.nextDepartOptions=[];
        this.departIdShow=false;
        this.$refs.form.resetFields();
      refresh() {
        this.userId = ''
        this.nextDepartOptions = []
        this.nextProductionOptions = []
        this.departIdShow = false
      },
      close() {
        this.$emit('close')
        this.visible = false
        this.disableSubmit = false
        this.nextDepartOptions = []
        this.nextProductionOptions = []
        this.departIdShow = false
        this.$refs.form.resetFields()
      },
      moment,
      handleSubmit () {
        const that = this;
      handleSubmit() {
        const that = this
        // è§¦å‘表单验证
        this.$refs.form.validate(valid => {
          if (valid) {
            that.confirmLoading = true;
            that.confirmLoading = true
            //如果是上级择传入departIds,否则为空
            if(this.model.userIdentity!==2){
              this.model.departIds="";
            if (this.model.userIdentity !== 2) {
              this.model.departIds = ''
            }
            let obj;
            if(!this.model.id){
              this.model.id = this.userId;
              obj=addUser(this.model);
            }else{
              obj=editUser(this.model);
            let obj
            if (!this.model.id) {
              this.model.id = this.userId
              obj = addUser(this.model)
            } else {
              obj = editUser(this.model)
            }
            obj.then((res)=>{
              if(res.success){
                that.$message.success(res.message);
                that.$emit('ok');
              }else{
                that.$message.warning(res.message);
            obj.then((res) => {
              if (res.success) {
                that.$message.success(res.message)
                that.$emit('ok')
              } else {
                that.$message.warning(res.message)
              }
            }).finally(() => {
              that.confirmLoading = false;
              that.close();
              that.confirmLoading = false
              that.close()
            })
          }else{
            return false;
          } else {
            return false
          }
        })
      },
      handleCancel () {
      handleCancel() {
        this.close()
      },
      validateToNextPassword (rule, value, callback) {
        const confirmpassword=this.model.confirmpassword;
      validateToNextPassword(rule, value, callback) {
        const confirmpassword = this.model.confirmpassword
        if (value && confirmpassword && value !== confirmpassword) {
          callback('两次输入的密码不一样!');
          callback('两次输入的密码不一样!')
        }
        if (value && this.confirmDirty) {
          this.$refs.form.validateField(['confirmpassword']);
          this.$refs.form.validateField(['confirmpassword'])
        }
        callback();
        callback()
      },
      compareToFirstPassword (rule, value, callback) {
      compareToFirstPassword(rule, value, callback) {
        if (value && value !== this.model.password) {
          callback('两次输入的密码不一样!');
          callback('两次输入的密码不一样!')
        } else {
          callback()
        }
      },
      validatePhone(rule, value, callback){
        if(!value){
      validatePhone(rule, value, callback) {
        if (!value) {
          callback()
        }else{
          if(new RegExp(/^1[3|4|5|6|7|8|9][0-9]\d{8}$/).test(value)){
        } else {
          if (new RegExp(/^1[3|4|5|7|8|9][0-9]\d{8}$/).test(value)) {
            var params = {
              tableName: 'sys_user',
              fieldName: 'phone',
              fieldVal: value,
              dataId: this.userId
            };
            }
            duplicateCheck(params).then((res) => {
              if (res.success) {
                callback()
              } else {
                callback("手机号已存在!")
                callback('手机号已存在!')
              }
            })
          }else{
            callback("请输入正确格式的手机号码!");
          } else {
            callback('请输入正确格式的手机号码!')
          }
        }
      },
      validateEmail(rule, value, callback){
        if(!value){
      validateEmail(rule, value, callback) {
        if (!value) {
          callback()
        }else{
          if(new RegExp(/^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/).test(value)){
        } else {
          if (new RegExp(/^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/).test(value)) {
            var params = {
              tableName: 'sys_user',
              fieldName: 'email',
              fieldVal: value,
              dataId: this.userId
            };
            }
            duplicateCheck(params).then((res) => {
              console.log(res)
              if (res.success) {
                callback()
              } else {
                callback("邮箱已存在!")
                callback('邮箱已存在!')
              }
            })
          }else{
            callback("请输入正确格式的邮箱!")
          } else {
            callback('请输入正确格式的邮箱!')
          }
        }
      },
      validateUsername(rule, value, callback){
      validateUsername(rule, value, callback) {
        var params = {
          tableName: 'sys_user',
          fieldName: 'username',
          fieldVal: value,
          dataId: this.userId
        };
        }
        duplicateCheck(params).then((res) => {
          if (res.success) {
            callback()
          } else {
            callback("用户名已存在!")
            callback('用户名已存在!')
          }
        })
      },
      validateWorkNo(rule, value, callback){
      validateWorkNo(rule, value, callback) {
        var params = {
          tableName: 'sys_user',
          fieldName: 'work_no',
          fieldVal: value,
          dataId: this.userId
        };
        }
        duplicateCheck(params).then((res) => {
          if (res.success) {
            callback()
          } else {
            callback("工号已存在!")
            callback('工号已存在!')
          }
        })
      },
      handleConfirmBlur(e) {
        const value = e.target.value;
        const value = e.target.value
        this.confirmDirty = this.confirmDirty || !!value
      },
      beforeUpload: function(file){
        var fileType = file.type;
        if(fileType.indexOf('image')<0){
          this.$message.warning('请上传图片');
          return false;
      beforeUpload: function (file) {
        var fileType = file.type
        if (fileType.indexOf('image') < 0) {
          this.$message.warning('请上传图片')
          return false
        }
        //TODO éªŒè¯æ–‡ä»¶å¤§å°
      },
      identityChange(e){
        if(e.target.value===1){
          this.departIdShow=false;
        }else{
          this.departIdShow=true;
      identityChange(e) {
        if (e.target.value === 1) {
          this.departIdShow = false
        } else {
          this.departIdShow = true
        }
      },
      initDictData(dictCode) {
        //根据字典Code, åˆå§‹åŒ–字典数组
        ajaxGetDictItems(dictCode, null).then((res) => {
          if (res.success) {
            const regExp = new RegExp('^(?=.*[a-zA-Z])(?=.*\\\d)(?=.*[~!@#$%^&*()_+`\\-={}:";\'<>?,./]).{' + Number(res.result[0].value) + ',}$')
            this.validatorRules.password[0] = {
              required: true,
              pattern: regExp,
              message: `密码由${res.result[0].value}位数字、大小写字母和特殊符号组成!`
            }
          }
        })
      },
      deviceSearch() {
        this.$refs.selectDeviceModal.visible = true
        this.$refs.selectDeviceModal.selectedRowKeys = []
        this.$refs.selectDeviceModal.selectedRows = []
        this.$refs.selectDeviceModal.checkedKeys = this.model.equipmentIds ? this.model.equipmentIds.split(',') : []
      },
      /**
       * é€‰æ‹©å·²æœ‰è®¾å¤‡åŽç‚¹å‡»ç¡®å®šæ—¶è§¦å‘
       * @param data å·²é€‰æ‹©çš„设备数组
       */
      selectOK(data) {
        console.log('data=', data)
        this.$set(this.model, 'equipmentIds', data.join(','))
      }
    }
  }
@@ -487,9 +812,10 @@
<style scoped>
  .avatar-uploader > .ant-upload {
    width:104px;
    height:104px;
    width: 104px;
    height: 104px;
  }
  .ant-upload-select-picture-card i {
    font-size: 49px;
    color: #999;
@@ -500,14 +826,14 @@
    color: #666;
  }
  .ant-table-tbody .ant-table-row td{
    padding-top:10px;
    padding-bottom:10px;
  .ant-table-tbody .ant-table-row td {
    padding-top: 10px;
    padding-bottom: 10px;
  }
  .drawer-bootom-button {
  .drawer-bottom-button {
    position: absolute;
    bottom: 0;
    bottom: -8px;
    width: 100%;
    border-top: 1px solid #e8e8e8;
    padding: 10px 16px;
@@ -516,10 +842,4 @@
    background: #fff;
    border-radius: 0 0 2px 2px;
  }
  /*【JTC-502】 æ·»åŠ ç”¨æˆ·ä¸¤ä¸ªæ»šåŠ¨æ¡*/
  /deep/ .ant-drawer-body {
    padding-bottom: 53px;
  }
</style>
</style>