1、mdc模块实现各利用率图表页面功能并与后端进行联调
2、删除用户修改密码时的输入校验
3、删除用户管理冗余查询字段
4、调整DNC模块获取权限配置功能时调用的获取所有用户列表接口(原先接口有分页参数导致获取不完整)
已修改12个文件
2607 ■■■■■ 文件已修改
src/api/dnc.js 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/mdc.js 17 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/dnc/base/modules/DeviceStructure/Permission/AssignPermissionModal.vue 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/dnc/base/modules/ProductStructure/Permission/AssignPermissionModal.vue 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/mdc/base/DeliveryGroupUtilizationRateChart.vue 363 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/mdc/base/GroupEquipmentUtilizationRateChart.vue 327 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/mdc/base/GroupUtilizationRateChart.vue 330 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/mdc/base/GroupUtilizationRateCompareChart.vue 234 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/mdc/base/modules/DeliveryGroupUtilizationRateChart/ChartComponent.vue 6 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/system/UserList.vue 37 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/system/modules/PasswordModal.vue 211 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/system/modules/UserModal.vue 1076 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/dnc.js
@@ -54,7 +54,7 @@
  // 权限配置弹窗中获取所有车间列表
  getAllDepartmentsListApi: () => getAction('/mdc/mdcProduction/queryTreeListByConfig'),
  // 权限配置弹窗中获取所有用户列表
  getAllUsersListApi: () => getAction('/sys/user/list'),
  getAllUsersListApi: () => getAction('/sys/user/listAll'),
  // 权限配置弹窗中获取有权限的部门列表
  getHasPermissionDepartApi: ({ type, id }) => getAction(`/nc/product/get/perm/depart/${type}/${id}`),
  // 权限配置弹窗中获取有权限的用户列表
src/api/mdc.js
@@ -30,4 +30,21 @@
  // -------------------------------------OEE页面--------------------------------------------
  // 计算OEE
  computeOeeApi: params => postAction('/mdc/mdcOeeInfo/computeOee', params),
  // -------------------------------------各利用率图表页面--------------------------------------------
  // 获取中心或中心对应班组列表
  getCenterOrGroupListApi: productionId => getAction('/mdc/mdcProduction/loadProductionOptions', { productionId }),
  // 获取设备综合利用率图表数据
  getGroupEquipmentChartDataApi: params => getAction('/mdc/efficiencyReport/equipmentEfficiencyAnalyze', params),
  // 获取班组对应配送小组列表
  getDeliveryGroupListApi: productionId => getAction('/mdc/mdcProduction/loadTeamOptions', { productionId }),
  // 获取月配送小组综合利用率图表数据
  getDeliveryGroupChartDataApi: params => getAction('/mdc/efficiencyReport/teamEquipmentEfficiencyAnalyze', params),
  // 获取班组设备利用率对比图表数据
  getGroupRateCompareChartDataApi: productionId => getAction('/mdc/efficiencyReport/teamEfficiencyAnalyzeByMonth', { productionId }),
  // 获取设备类型列表
  getEquipmentTypeListApi: () => getAction('/mdc/mdcEquipmentType/queryEquipmentType'),
  // 获取班制列表
  getShiftListApi: () => getAction('/mdc/mdcMdcShift/initShiftList'),
  // 获取班组设备利用率图表数据
  getGroupChartDataApi: params => getAction('/mdc/efficiencyReport/comprehensiveRateAnalyze', params)
}
src/views/dnc/base/modules/DeviceStructure/Permission/AssignPermissionModal.vue
@@ -69,7 +69,7 @@
        dncApi.getAllUsersListApi()
          .then(res => {
            if (res.success) {
              this.allUsersList = res.result.records
              this.allUsersList = res.result
              this.$nextTick(() => this.$refs.userPermissionTransferRef.getHasPermissionUserByApi())
            }
          })
src/views/dnc/base/modules/ProductStructure/Permission/AssignPermissionModal.vue
@@ -116,7 +116,7 @@
      dncApi.getAllUsersListApi()
        .then(res => {
          if (res.success) {
            this.allUsersList = res.result.records
            this.allUsersList = res.result
            this.$nextTick(() => this.$refs.userPermissionTransferRef.getHasPermissionUserByApi())
          }
        })
src/views/mdc/base/DeliveryGroupUtilizationRateChart.vue
@@ -1,82 +1,327 @@
<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">
          <ChartComponent :nodePeople='selectPeople' :nodeTree='selectEquipment' :Type="selectTypeTree"/>
        </a-col>
      </a-row>
    </a-card>
  </div>
  <a-card>
    <div class="table-page-search-wrapper">
      <a-form layout="inline" @keyup.enter.native="searchQuery">
        <a-row :gutter="24">
          <a-col :md="3" :sm="3">
            <a-form-item label="中心">
              <a-select v-model="queryParam.productionId" placeholder="请选择中心" @change="handleCenterSelectChange">
                <a-select-option v-for="item in centerList" :key="item.key">
                  {{ item.title }}
                </a-select-option>
              </a-select>
            </a-form-item>
          </a-col>
          <a-col :md="8" :sm="8">
            <a-form-item label="班组">
              <a-select :value="productionIds" placeholder="请选择班组" mode="multiple" :maxTagCount="3"
                        @change="handleGroupSelectChange" allowClear>
                <a-select-option v-for="item in groupList" :key="item.key">
                  {{ item.title }}
                </a-select-option>
              </a-select>
            </a-form-item>
          </a-col>
          <a-col :md="8" :sm="8">
            <a-form-item label="配送小组">
              <a-select v-model="teamCodes" placeholder="请选择配送小组" mode="multiple" :maxTagCount="3"
                        @change="handleDeliverGroupSelectChange" allowClear>
                <a-select-option v-for="item in deliveryGroupList" :key="item.key">{{ item.title }}</a-select-option>
              </a-select>
            </a-form-item>
          </a-col>
          <a-col :md="3" :sm="3">
            <a-form-item label="月份">
              <a-month-picker v-model="queryParam.month" style="width: 100%" value-format="YYYYMM" :allowClear="false"
                              placeholder="请选择月份"/>
            </a-form-item>
          </a-col>
          <a-col :md="2" :sm="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 id="chart-container" style="height: 700px"></div>
  </a-card>
</template>
<script>
import BaseTree from '../common/BaseTree'
import DepartTree from './modules/DepartList/DepartListTree/DepartTree'
import { mapActions } from 'vuex'
import ChartComponent from '@views/mdc/base/modules/DeliveryGroupUtilizationRateChart/ChartComponent.vue'
import { JeecgListMixin } from '@/mixins/JeecgListMixin'
import moment from 'moment/moment'
import mdcApi from '@api/mdc'
export default {
  name: 'DeliveryGroupUtilizationRateChart',
  components: {
    ChartComponent,
    BaseTree,
    DepartTree,
  },
  components: {},
  mixins: [JeecgListMixin],
  data() {
    return {
      activeKey: '1',
      selectEquipment: {},
      selectPeople: {},
      selectTypeTree: '',
      isDepartType: ''
      disableMixinCreated: true,
      queryParam: {
        month: moment().subtract('1', 'month').format('YYYYMM')
      },
      productionIds: [],//班组
      teamCodes: [],//配送小组
      centerList: [],
      groupList: [],
      deliveryGroupList: []
    }
  },
  created() {
    this.queryTreeData()
  mounted() {
    window.addEventListener('resize', this.handleWindowResize)
    this.getCenterListByApi()
    this.handleWindowResize()
  },
  methods: {
    ...mapActions(['QueryDepartTree']),
    queryTreeData() {
      this.QueryDepartTree().then(res => {
        if (res.success) {
          this.isDepartType = res.result[0].value
        } else {
          this.$notification.warning({
            message: '消息',
            description: res.message
          })
        }
      }).finally(() => {
    loadData() {
      this.chartContainer = this.$echarts.init(document.getElementById('chart-container'))
      this.initChart({})
      this.chartContainer.showLoading({
        text: '数据加载中 ...',
        color: '#0696e1', // 加载动画颜色
        textColor: '#0696e1'
      })
      const that = this
      mdcApi.getDeliveryGroupChartDataApi(this.queryParam)
        .then(res => {
          if (res.success) {
            if (Object.keys(res.result).length === 0 || res.result.teamCodeList.length === 0) {
              that.$notification.warning({
                message: '消息',
                description: '暂无数据'
              })
              // 此处未return是为保证图表数据能被清除并展示空图表
            }
            that.initChart(res.result)
          } else {
            that.$notification.warning({
              message: '消息',
              description: res.message
            })
          }
        })
        .catch(err => {
          that.$notification.error({
            message: '消息',
            description: err.message
          })
        })
    },
    tabChange(val) {
      this.activeKey = val
      this.selectTypeTree = val
    /**
     * 初始化图表
     * @param chartDataObj 数据对象 Object
     */
    initChart(chartDataObj) {
      const option = {
        title: {
          text: (this.queryParam.month.slice(-2) >= 10 ? this.queryParam.month.slice(-2) : this.queryParam.month.slice(-1)) + '月配送小组综合利用率',
          left: 'center',
          top: 0,
          textStyle: {
            fontSize: 22
          }
        },
        grid: {
          top: '12%',
          left: '1%',
          right: '1%',
          bottom: '8%',
          containLabel: true
        },
        legend: {
          top: '6%',
          right: 'center',
          itemGap: 20,
          data: ['24h综合利用率', '去除故障设备时间24h综合利用率', '班次利用率']
        },
        tooltip: {
          show: true,
          trigger: 'axis'
        },
        xAxis: {
          type: 'category',
          data: chartDataObj.teamCodeList ? chartDataObj.teamCodeList : []
          // data: ['李有为组', '丁红燕组', '唐东组', '朱小磊组', '张奇组', '宋宇坤组', '罗军组', '张双进组', '常振勇组', '葛应龙组', '赵广涛组', '于华亭组', '陈峻组', '王继峰组', '王晓明组', '陈林组', '吴吉平组']
        },
        yAxis: [
          {
            type: 'value',
            name: '利用率(%)',
            axisLine: {
              show: true
            },
            axisLabel: {
              formatter: '{value}%'
            }
          }
        ],
        series: [
          {
            type: 'bar',
            name: '24h综合利用率',
            // barWidth: '40%',
            // data: [85, 32, 23, 56, 24, 64, 34, 85, 32, 23, 56, 24, 85, 63, 74, 11, 58]
            data: chartDataObj.dataList ? chartDataObj.dataList.map(item => item.utilizationRate) : []
          },
          {
            type: 'bar',
            name: '去除故障设备时间24h综合利用率',
            // barWidth: '40%',
            // data: [24, 64, 34, 85, 32, 23, 56, 24, 85, 32, 23, 56, 24, 64, 34, 85, 54],
            data: chartDataObj.dataList ? chartDataObj.dataList.map(item => item.amendUtilizationRate) : []
          },
          {
            type: 'bar',
            name: '班次利用率',
            // barWidth: '40%',
            // data: [24, 64, 34, 85, 32, 23, 56, 24, 85, 32, 23, 56, 24, 64, 34, 85, 54],
            data: chartDataObj.dataList ? chartDataObj.dataList.map(item => item.shiftUtilizationRate) : []
          }
        ],
        dataZoom: [
          {
            type: 'slider',
            show: true,
            xAxisIndex: 0,
            startValue: 0,
            endValue: 19,
            // 是否显示detail,即拖拽时候显示详细数值信息
            showDetail: false,
            // empty:当前数据窗口外的数据,被设置为空。
            // 即不会影响其他轴的数据范围
            filterMode: 'empty',
            // 控制手柄的尺寸
            // handleSize: 0,
            // 是否锁定选择区域(或叫做数据窗口)的大小
            zoomLock: true,
            brushSelect: false
          },
          {
            // 没有下面这块的话,只能拖动滚动条,
            // 鼠标滚轮在区域内不能控制外部滚动条
            type: 'inside',
            show: true,
            // 控制哪个轴,如果是number表示控制一个轴,
            xAxisIndex: 0,
            // 滚轮是否触发缩放
            zoomOnMouseWheel: false,
            // 鼠标移动能否触发平移
            moveOnMouseMove: true,
            // 鼠标滚轮能否触发平移
            moveOnMouseWheel: true
          }
        ]
      }
      this.chartContainer.setOption(option, true)
      this.chartContainer.hideLoading()
    },
    changeSelectionNode(val) {
      this.selectEquipment = val
      this.selectTypeTree = '1'
    // 获取中心列表
    getCenterListByApi() {
      const that = this
      mdcApi.getCenterOrGroupListApi()
        .then(res => {
          if (res.success) {
            that.centerList = res.result
            that.queryParam.productionId = res.result[0].value
            that.getGroupListByApi(res.result[0].value, true)
          }
        })
    },
    changeSelectionNodedd(val) {
      this.selectPeople = val
      this.selectTypeTree = '2'
    /**
     * 获取班组列表
     * @param productionId 中心Id
     * @param isInitLoad 是否为初始化加载
     */
    getGroupListByApi(productionId, isInitLoad = false) {
      const that = this
      mdcApi.getCenterOrGroupListApi(productionId)
        .then(res => {
          if (res.success) {
            that.groupList = res.result
            if (!isInitLoad) return
            that.handleGroupSelectChange([res.result[0].value])
            that.loadData()
          }
        })
    },
    /**
     * 获取配送小组列表
     * @param productionId 班组Id
     * @param isReduceSelectOption 是否减少班组选中项
     */
    getDeliveryGroupListByApi(productionId, isReduceSelectOption = false) {
      const that = this
      mdcApi.getDeliveryGroupListApi(productionId)
        .then(res => {
          if (res.success) {
            that.deliveryGroupList = res.result
            if (!isReduceSelectOption) return
            that.teamCodes.forEach((key, keyIndex, self) => {
              // 如果将唯一一组包含选中配送小组项的班组取消勾选后应将已勾选的配送小组一并取消勾选
              if (that.deliveryGroupList.findIndex(item => item.key === key) === -1) self.splice(keyIndex, 1)
            })
          }
        })
    },
    /**
     * 中心改变时触发
     * @param value 改变后的中心Id
     */
    handleCenterSelectChange(value) {
      if (this.productionIds.length > 0) {
        this.groupList = []
        this.productionIds = []
        delete this.queryParam.productionIds
      }
      if (this.teamCodes.length > 0) {
        this.deliveryGroupList = []
        this.teamCodes = []
        delete this.queryParam.teamCodes
      }
      this.getGroupListByApi(value)
    },
    /**
     * 班组改变时触发
     * @param value 改变后的班组Id
     */
    handleGroupSelectChange(value) {
      let isReduceSelectOption
      if (value.length > this.productionIds.length) isReduceSelectOption = false //增加勾选项
      else isReduceSelectOption = true // 减少勾选项
      this.productionIds = value
      this.queryParam.productionIds = value.join(',')
      this.getDeliveryGroupListByApi(value.join(','), isReduceSelectOption)
    },
    /**
     * 配送小组发生改变时触发
     * @param value 改变后的配送小组Id
     */
    handleDeliverGroupSelectChange(value) {
      this.queryParam.teamCodes = value.join(',')
    },
    handleWindowResize() {
      if (this.chartContainer) this.chartContainer.resize()
    }
  }
}
</script>
</script>
src/views/mdc/base/GroupEquipmentUtilizationRateChart.vue
@@ -1,82 +1,291 @@
<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">
          <ChartComponent :nodePeople='selectPeople' :nodeTree='selectEquipment' :Type="selectTypeTree"/>
        </a-col>
      </a-row>
    </a-card>
  </div>
  <a-card>
    <div class="table-page-search-wrapper">
      <a-form layout="inline" @keyup.enter.native="searchQuery">
        <a-row :gutter="24">
          <a-col :md="3" :sm="3">
            <a-form-item label="中心">
              <a-select v-model="queryParam.productionId" placeholder="请选择中心" @change="handleCenterSelectChange">
                <a-select-option v-for="item in centerList" :key="item.key">
                  {{ item.title }}
                </a-select-option>
              </a-select>
            </a-form-item>
          </a-col>
          <a-col :md="10" :sm="10">
            <a-form-item label="班组">
              <a-select :value="productionIds" placeholder="请选择班组" mode="multiple" :maxTagCount="5"
                        @change="handleGroupSelectChange" allowClear>
                <a-select-option v-for="item in groupList" :key="item.key">
                  {{ item.title }}
                </a-select-option>
              </a-select>
            </a-form-item>
          </a-col>
          <a-col :md="3" :sm="3">
            <a-form-item label="月份">
              <a-month-picker v-model="queryParam.month" style="width: 100%" value-format="YYYYMM" :allowClear="false"
                              placeholder="请选择月份"/>
            </a-form-item>
          </a-col>
          <a-col :md="5" :sm="5">
            <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 id="chart-container" style="height: 700px"></div>
  </a-card>
</template>
<script>
import BaseTree from '../common/BaseTree'
import DepartTree from './modules/DepartList/DepartListTree/DepartTree'
import { mapActions } from 'vuex'
import ChartComponent from '@views/mdc/base/modules/GroupEquipmentUtilizationRateChart/ChartComponent.vue'
import mdcApi from '@api/mdc'
import moment from 'moment'
import { JeecgListMixin } from '@/mixins/JeecgListMixin'
export default {
  name: 'GroupEquipmentUtilizationRateChart',
  components: {
    ChartComponent,
    BaseTree,
    DepartTree,
  },
  components: {},
  mixins: [JeecgListMixin],
  data() {
    return {
      activeKey: '1',
      selectEquipment: {},
      selectPeople: {},
      selectTypeTree: '',
      isDepartType: ''
      disableMixinCreated: true,
      productionIds: [],//班组
      centerList: [],
      groupList: [],
      queryParam: {
        month: moment().subtract('1', 'month').format('YYYYMM')
      }
    }
  },
  created() {
    this.queryTreeData()
  mounted() {
    window.addEventListener('resize', this.handleWindowResize)
    this.handleWindowResize()
    this.getCenterListByApi()
  },
  methods: {
    ...mapActions(['QueryDepartTree']),
    queryTreeData() {
      this.QueryDepartTree().then(res => {
        if (res.success) {
          this.isDepartType = res.result[0].value
        } else {
          this.$notification.warning({
            message: '消息',
            description: res.message
          })
        }
      }).finally(() => {
    loadData() {
      this.chartContainer = this.$echarts.init(document.getElementById('chart-container'))
      this.initChart({})
      this.chartContainer.showLoading({
        text: '数据加载中 ...',
        color: '#0696e1', // 加载动画颜色
        textColor: '#0696e1'
      })
      const that = this
      mdcApi.getGroupEquipmentChartDataApi(this.queryParam)
        .then(res => {
          if (res.success) {
            if (Object.keys(res.result).length === 0 || res.result.equipmentNameList.length === 0) {
              that.$notification.warning({
                message: '消息',
                description: '暂无数据'
              })
              // 此处未return是为保证图表数据能被清除并展示空图表
            }
            that.initChart(res.result)
          } else {
            that.$notification.warning({
              message: '消息',
              description: res.message
            })
          }
        })
        .catch(err => {
          that.$notification.error({
            message: '消息',
            description: err.message
          })
        })
    },
    tabChange(val) {
      this.activeKey = val
      this.selectTypeTree = val
    /**
     * 初始化图表
     * @param chartDataObj 数据对象 Object
     */
    initChart(chartDataObj) {
      const option = {
        title: {
          text: '设备综合利用率(' + (this.queryParam.month.slice(-2) >= 10 ? this.queryParam.month.slice(-2) : this.queryParam.month.slice(-1)) + '月)',
          left: 'center',
          top: 0,
          textStyle: {
            fontSize: 22
          }
        },
        grid: {
          top: '12%',
          left: '1%',
          right: '1%',
          bottom: '8%',
          containLabel: true
        },
        legend: {
          top: '6%',
          right: 'center',
          itemGap: 20,
          data: ['24h综合利用率', '24h去除故障', '计划工作时间综合利用率']
        },
        tooltip: {
          show: true,
          trigger: 'axis'
        },
        xAxis: {
          type: 'category',
          // data: ['立加u1000-3', '五轴125P', '五坐标加工中心GS1000', 'A轴1000PLUS', '梧州80P_2', '雕刻机800TE', '四坐标立加104V', '立加u1000-4', '立加GX710_1', '三坐标立加1350', '卧加H5000-1', '立加u1000-2', '立加1000HS_1', '立加1160_1', '立加GX710_2', '立加u1000-3', '五轴125P', '五坐标加工中心GS1000', 'A轴1000PLUS', '梧州80P_2', '雕刻机800TE', '四坐标立加104V', '立加u1000-4', '立加GX710_1', '三坐标立加1350', '卧加H5000-1', '立加u1000-2', '立加1000HS_1', '立加1160_1', '立加GX710_2', '立加u1000-3', '五轴125P', '五坐标加工中心GS1000', 'A轴1000PLUS', '梧州80P_2', '雕刻机800TE', '四坐标立加104V'],
          data: chartDataObj.equipmentNameList ? chartDataObj.equipmentNameList : [],
          axisLabel: {
            interval: 0, // 坐标轴刻度标签的显示间隔,在类目轴中有效;默认会采用标签不重叠的策略间隔显示标签;可以设置成0强制显示所有标签;如果设置为1,表示『隔一个标签显示一个标签』,如果值为2,表示隔两个标签显示一个标签,以此类推。
            rotate: 45, // 刻度标签旋转的角度,在类目轴的类目标签显示不下的时候可以通过旋转防止标签之间重叠;旋转的角度从-90度到90度
            inside: false, // 刻度标签是否朝内,默认朝外
            margin: 15, // 刻度标签与轴线之间的距离
            fontSize: 14,
            color: '#000'
          }
        },
        yAxis: [
          {
            type: 'value',
            name: '利用率(%)',
            axisLine: {
              show: true
            },
            axisLabel: {
              formatter: '{value}%'
            }
          }
        ],
        series: [
          {
            type: 'bar',
            name: '24h综合利用率',
            // data: [53.28, 32.22, 23, 56, 24, 64, 34, 85, 32, 23, 56, 24, 85, 32, 23, 56, 24, 64, 34, 85, 32, 23, 56, 24, 23, 56, 24, 85, 32, 23, 56, 24, 85, 32, 85, 32, 23, 56, 24, 85, 32]
            data: chartDataObj.dataList ? chartDataObj.dataList.map(item => item.utilizationRate) : []
            // label: {
            //   show: true,
            //   position: 'top',
            //   formatter: '{c}%',
            //   avoidLabelOverlap: true
            // }
          },
          {
            type: 'bar',
            name: '24h去除故障',
            data: chartDataObj.dataList ? chartDataObj.dataList.map(item => item.amendUtilizationRate) : []
            // data: [53.28, 32.22, 23, 56, 24, 64, 34, 85, 32, 23, 56, 24, 85, 32, 23, 56, 24, 64, 34, 85, 32, 23, 56, 24, 23, 56, 24, 85, 32, 23, 56, 24, 85, 32, 85, 32, 23, 56, 24, 85, 32]
          },
          {
            type: 'bar',
            name: '计划工作时间综合利用率',
            data: chartDataObj.dataList ? chartDataObj.dataList.map(item => item.shiftUtilizationRate) : []
            // data: [63.25, 32.22, 23, 56, 24, 64, 34, 85, 32, 23, 56, 24, 85, 32, 23, 56, 24, 64, 34, 85, 32, 23, 56, 24, 85, 32, 23, 56, 24, 85, 32, 85, 32, 23, 56, 24, 85, 32]
          }
        ],
        dataZoom: [
          {
            type: 'slider',
            show: true,
            xAxisIndex: 0,
            startValue: 0,
            endValue: 19,
            // 是否显示detail,即拖拽时候显示详细数值信息
            showDetail: false,
            // empty:当前数据窗口外的数据,被设置为空。
            // 即不会影响其他轴的数据范围
            filterMode: 'empty',
            // 控制手柄的尺寸
            // handleSize: 0,
            // 是否锁定选择区域(或叫做数据窗口)的大小
            zoomLock: true,
            brushSelect: false
          },
          {
            // 没有下面这块的话,只能拖动滚动条,
            // 鼠标滚轮在区域内不能控制外部滚动条
            type: 'inside',
            show: true,
            // 控制哪个轴,如果是number表示控制一个轴,
            xAxisIndex: 0,
            // 滚轮是否触发缩放
            zoomOnMouseWheel: false,
            // 鼠标移动能否触发平移
            moveOnMouseMove: true,
            // 鼠标滚轮能否触发平移
            moveOnMouseWheel: true
          }
        ]
      }
      this.chartContainer.setOption(option, true)
      this.chartContainer.hideLoading()
    },
    changeSelectionNode(val) {
      this.selectEquipment = val
      this.selectTypeTree = '1'
    // 获取中心列表
    getCenterListByApi() {
      const that = this
      mdcApi.getCenterOrGroupListApi()
        .then(res => {
          if (res.success) {
            that.centerList = res.result
            that.queryParam.productionId = res.result[0].value
            that.getGroupListByApi(res.result[0].value, true)
          }
        })
    },
    changeSelectionNodedd(val) {
      this.selectPeople = val
      this.selectTypeTree = '2'
    /**
     * 获取班组列表
     * @param productionId 中心Id
     * @param isInitLoad 是否为初始化加载
     */
    getGroupListByApi(productionId, isInitLoad = false) {
      const that = this
      mdcApi.getCenterOrGroupListApi(productionId)
        .then(res => {
          if (res.success) {
            that.groupList = res.result
            if (!isInitLoad) return
            that.handleGroupSelectChange([res.result[0].value])
            that.loadData()
          }
        })
    },
    /**
     * 中心改变时触发
     * @param value 改变后的中心Id
     */
    handleCenterSelectChange(value) {
      if (this.productionIds.length > 0) {
        this.groupList = []
        this.productionIds = []
        delete this.queryParam.productionIds
      }
      this.getGroupListByApi(value)
    },
    /**
     * 班组发生改变时触发
     * @param value 改变后的班组Id
     */
    handleGroupSelectChange(value) {
      this.productionIds = value
      if (value.length === 0) {
        delete this.queryParam.productionIds
        return
      }
      this.queryParam.productionIds = value.join(',')
    },
    handleWindowResize() {
      if (this.chartContainer) this.chartContainer.resize()
    }
  }
}
</script>
</script>
src/views/mdc/base/GroupUtilizationRateChart.vue
@@ -1,82 +1,294 @@
<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">
          <ChartComponent :nodePeople='selectPeople' :nodeTree='selectEquipment' :Type="selectTypeTree"/>
        </a-col>
      </a-row>
    </a-card>
  </div>
  <a-card>
    <div class="table-page-search-wrapper">
      <a-form layout="inline" @keyup.enter.native="searchQuery">
        <a-row :gutter="24">
          <a-col :md="3" :sm="3">
            <a-form-item label="中心">
              <a-select v-model="queryParam.productionId" placeholder="请选择中心">
                <a-select-option v-for="item in centerList" :key="item.key">
                  {{ item.title }}
                </a-select-option>
              </a-select>
            </a-form-item>
          </a-col>
          <a-col :md="10" :sm="10">
            <a-form-item label="班组">
              <a-select :value="productionIds" placeholder="请选择班组" mode="multiple" :maxTagCount="5"
                        @change="handleGroupSelectChange($event,'productionIds')" allowClear>
                <a-select-option v-for="item in groupList" :key="item.key">
                  {{ item.title }}
                </a-select-option>
              </a-select>
            </a-form-item>
          </a-col>
          <a-col :md="4" :sm="4">
            <a-form-item label="设备类型">
              <a-select v-model="queryParam.equipmentType" placeholder="请选择设备类型" allowClear>
                <a-select-option v-for="item in equipmentTypeList" :key="item.id">
                  {{ item.equipmentTypeName }}
                </a-select-option>
              </a-select>
            </a-form-item>
          </a-col>
          <a-col :md="4" :sm="4">
            <a-form-item label="班制">
              <a-select v-model="queryParam.shiftId" placeholder="请选择班制" allowClear>
                <a-select-option v-for="item in shiftList" :key="item.value">{{ item.label }}</a-select-option>
              </a-select>
            </a-form-item>
          </a-col>
          <!--          <a-col :md="5" :sm="5">-->
          <!--            <a-form-item label="班次">-->
          <!--              <a-select v-model="queryParam.workTime" placeholder="请选择班次" mode="multiple" :maxTagCount="2">-->
          <!--                <a-select-option key="123">一班</a-select-option>-->
          <!--                <a-select-option key="234">二班</a-select-option>-->
          <!--                <a-select-option key="345">三班</a-select-option>-->
          <!--              </a-select>-->
          <!--            </a-form-item>-->
          <!--          </a-col>-->
          <a-col :md="2" :sm="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 id="chart-container" style="height: 700px"></div>
  </a-card>
</template>
<script>
import BaseTree from '../common/BaseTree'
import DepartTree from './modules/DepartList/DepartListTree/DepartTree'
import { mapActions } from 'vuex'
import ChartComponent from '@views/mdc/base/modules/GroupUtilizationRateChart/ChartComponent.vue'
import mdcApi from '@api/mdc'
import { JeecgListMixin } from '@/mixins/JeecgListMixin'
export default {
  name: 'GroupUtilizationRateChart',
  components: {
    ChartComponent,
    BaseTree,
    DepartTree,
  },
  components: {},
  mixins: [JeecgListMixin],
  data() {
    return {
      activeKey: '1',
      selectEquipment: {},
      selectPeople: {},
      selectTypeTree: '',
      isDepartType: ''
      disableMixinCreated: true,
      queryParam: {},
      productionIds: [],//班组
      centerList: [],
      groupList: [],
      equipmentTypeList: [],
      shiftList: []
    }
  },
  created() {
    this.queryTreeData()
  mounted() {
    window.addEventListener('resize', this.handleWindowResize)
    this.handleWindowResize()
    this.getCenterListByApi()
    this.getEquipmentTypeListApi()
    this.getShiftListByApi()
  },
  methods: {
    ...mapActions(['QueryDepartTree']),
    queryTreeData() {
      this.QueryDepartTree().then(res => {
        if (res.success) {
          this.isDepartType = res.result[0].value
        } else {
          this.$notification.warning({
            message: '消息',
            description: res.message
          })
        }
      }).finally(() => {
    // 获取数据
    loadData() {
      this.chartContainer = this.$echarts.init(document.getElementById('chart-container'))
      this.initChart({})
      this.chartContainer.showLoading({
        text: '数据加载中 ...',
        color: '#0696e1', // 加载动画颜色
        textColor: '#0696e1'
      })
      const that = this
      mdcApi.getGroupChartDataApi(this.queryParam)
        .then(res => {
          if (res.success) {
            if (!res.result.dataList || (res.result.dataList && res.result.dataList.length === 0)) {
              that.$notification.warning({
                message: '消息',
                description: '暂无数据'
              })
            }
            that.initChart(res.result)
          }
        })
    },
    tabChange(val) {
      this.activeKey = val
      this.selectTypeTree = val
    /**
     * 初始化图表
     * @param dataList 图表数据源
     * @param dateList 日期列表
     * @param shiftSubList 班次标题列表
     * @param shiftDataList 班次数据列表
     */
    initChart({ dataList, dateList, shiftSubList, shiftDataList }) {
      const defaultLegendData = ['24小时', '24小时(去除故障设备)', '班次', '累计运行时间(h)']
      const defaultSeries = [
        {
          type: 'line',
          name: '24小时',
          yAxisIndex: 0,
          data: dataList ? dataList.map(item => item.utilizationRate) : []
        },
        {
          type: 'line',
          name: '24小时(去除故障设备)',
          yAxisIndex: 0,
          data: dataList ? dataList.map(item => item.amendUtilizationRate) : []
        },
        {
          type: 'line',
          name: '班次',
          yAxisIndex: 0,
          data: dataList ? dataList.map(item => item.shiftUtilizationRate) : []
        },
        {
          type: 'bar',
          name: '累计运行时间(h)',
          yAxisIndex: 1,
          barWidth: '30%',
          data: dataList ? dataList.map(item => item.processLong) : []
        }
      ]
      const option = {
        title: {
          text: '设备综合利用率',
          left: 'center',
          top: 0,
          textStyle: {
            fontSize: 22
          }
        },
        grid: {
          top: '12%',
          left: '1%',
          right: '1%',
          bottom: '1%',
          containLabel: true
        },
        legend: {
          top: '6%',
          right: 'center',
          itemGap: 20,
          data: defaultLegendData
        },
        tooltip: {
          show: true,
          trigger: 'axis'
        },
        xAxis: {
          type: 'category',
          data: dateList ? dateList : []
        },
        yAxis: [
          {
            type: 'value',
            name: '利用率(%)',
            axisLine: {
              show: true
            },
            axisLabel: {
              formatter: '{value}%'
            }
          },
          {
            type: 'value',
            name: '运行时间(h)',
            axisLine: {
              show: true
            }
          }
        ],
        series: defaultSeries
      }
      if (shiftSubList) {
        option.legend.data = defaultLegendData.concat(shiftSubList)
        const newSeriesData = shiftDataList.map(item => {
          return {
            type: 'line',
            name: item.shiftSubName,
            yAxisIndex: 0,
            data: item.dataList ? item.dataList.map(item => item.utilizationRate) : []
          }
        })
        option.series = defaultSeries.concat(newSeriesData)
      }
      this.chartContainer.setOption(option, true)
      this.chartContainer.hideLoading()
    },
    changeSelectionNode(val) {
      this.selectEquipment = val
      this.selectTypeTree = '1'
    // 获取中心列表
    getCenterListByApi() {
      const that = this
      mdcApi.getCenterOrGroupListApi()
        .then(res => {
          if (res.success) {
            that.centerList = res.result
            that.queryParam.productionId = res.result[0].value
            that.getGroupListByApi(res.result[0].value)
          }
        })
    },
    changeSelectionNodedd(val) {
      this.selectPeople = val
      this.selectTypeTree = '2'
    /**
     * 获取班组列表
     * @param productionId 中心Id
     */
    getGroupListByApi(productionId) {
      const that = this
      mdcApi.getCenterOrGroupListApi(productionId)
        .then(res => {
          if (res.success) {
            that.groupList = res.result
            that.handleGroupSelectChange([res.result[0].value])
            that.loadData()
          }
        })
    },
    /**
     * 班组发生改变时触发
     * @param value 改变后的值
     */
    handleGroupSelectChange(value) {
      this.productionIds = value
      this.queryParam.productionIds = value.join(',')
    },
    // 获取设备类型列表
    getEquipmentTypeListApi() {
      const that = this
      mdcApi.getEquipmentTypeListApi()
        .then(res => {
          if (res.success) {
            that.equipmentTypeList = res.result
          }
        })
    },
    // 获取班制列表
    getShiftListByApi() {
      const that = this
      mdcApi.getShiftListApi()
        .then(res => {
          if (res.success) {
            that.shiftList = res.result
          }
        })
    },
    handleWindowResize() {
      if (this.chartContainer) this.chartContainer.resize()
    }
  }
}
</script>
</script>
src/views/mdc/base/GroupUtilizationRateCompareChart.vue
@@ -1,14 +1,38 @@
<template>
  <a-card>
    <div class="table-page-search-wrapper">
      <a-form layout="inline" @keyup.enter.native="searchQuery">
        <a-row :gutter="24">
          <a-col :md="3" :sm="3">
            <a-form-item label="中心">
              <a-select v-model="queryParam.productionId" placeholder="请选择中心">
                <a-select-option v-for="item in centerList" :key="item.key">
                  {{ item.title }}
                </a-select-option>
              </a-select>
            </a-form-item>
          </a-col>
          <a-col :md="5" :sm="5">
            <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 style="display: flex;justify-content: space-between">
      <div id="chart-container-left" style="height: 700px;width: 48%"></div>
      <div id="chart-container-right" style="height: 700px;width: 48%"></div>
      <div id="chart-container-left" style="height: 700px;width: 30%"></div>
      <div id="chart-container-middle" style="height: 700px;width: 30%"></div>
      <div id="chart-container-right" style="height: 700px;width: 30%"></div>
    </div>
  </a-card>
</template>
<script>
import api from '@api/mdc'
import mdcApi from '@api/mdc'
import { JeecgListMixin } from '@/mixins/JeecgListMixin'
export default {
@@ -18,64 +42,87 @@
  data() {
    return {
      disableMixinCreated: true,
      typeTree: '',
      queryParam: {},
      driveTypeList: [],
      centerList: [],
      chartsOptionList: [
        {
          position: 'left',
          title: '班组设备综合利用率(24h)',
          property: 'utilizationRateList'
        },
        {
          position: 'middle',
          title: '班组设备综合利用率(24h去除故障时间)',
          property: 'amendUtilizationRateList'
        },
        {
          position: 'right',
          title: '班组设备综合利用率(计划工作时间)',
          property: 'shiftUtilizationRateList'
        }
      ],
      leftChartContainer: null,
      rightChartContainer: null,
      url: {}
      middleChartContainer: null,
      rightChartContainer: null
    }
  },
  props: { nodeTree: '', Type: '', nodePeople: '' },
  created() {
  },
  mounted() {
    window.addEventListener('resize', this.handleWindowResize)
    this.getDriveTypeByApi()
    this.loadData()
    this.getCenterListByApi()
    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()
      }
    }
  },
  methods: {
    // 获取图表数据
    loadData() {
      this.initChart('left')
      this.initChart('right')
      const that = this
      this.chartsOptionList.forEach(item => {
        that.initChart(item.position)
        that.chartSetOption(item.position, item.title, [], [], false)
      })
      mdcApi.getGroupRateCompareChartDataApi(this.queryParam.productionId)
        .then(res => {
          if (res.success) {
            that.chartsOptionList.forEach(item => this.chartSetOption(item.position, item.title, res.result[item.property], res.result.dateList))
          } else {
            that.$notification.warning({
              message: '消息',
              description: res.message
            })
          }
        })
        .catch(err => {
          that.$notification.error({
            message: '消息',
            description: err.message
          })
        })
    },
    /**
     * 初始化图表
     * @param position 图表位置 String
     */
    initChart(position) {
      this[position + 'ChartContainer'] = this.$echarts.init(document.getElementById(`chart-container-${position}`))
      this[position + 'ChartContainer'].showLoading({
        text: '数据加载中 ...',
        color: '#0696e1', // 加载动画颜色
        textColor: '#0696e1'
      })
    },
    /**
     * 设置图标选项
     * @param position 图表位置 String
     * @param title 图表标题 String
     * @param dataList 图表数据源 Array
     * @param dateList 图表横坐标月份 Array
     * @param isHideLoading 是否关闭加载图标 Boolean
     */
    chartSetOption(position, title, dataList, dateList, isHideLoading = true) {
      const option = {
        title: {
          text: position === 'left' ? '各班组24小时综合效率对比' : '各班组24小时综合效率对比(去除故障设备时间)',
          text: title,
          left: 'center',
          top: 0,
          textStyle: {
@@ -86,14 +133,13 @@
          top: '10%',
          left: '1%',
          right: '1%',
          bottom: '5%',
          bottom: '12%',
          containLabel: true
        },
        legend: {
          bottom: 0,
          bottom: '3%',
          right: 'center',
          itemGap: 20,
          data: ['数铣一班', '数铣二班', '数铣三班', '数车班']
          data: dataList.map(item => item.productionName)
        },
        tooltip: {
          show: true,
@@ -101,7 +147,7 @@
        },
        xAxis: {
          type: 'category',
          data: ['1月', '2月', '3月', '4月', '5月', '6月', '7月', '8月', '9月', '10月', '11月', '12月']
          data: dateList
        },
        yAxis: [
          {
@@ -115,63 +161,57 @@
            }
          }
        ],
        series: [
          {
        series: dataList.map(item => {
          return {
            type: 'line',
            name: '数铣一班',
            yAxisIndex: 0,
            data: [85, 32, 23, 56, 24, 64, 34, 85, 32, 23, 56, 24]
          },
          {
            type: 'line',
            name: '数铣二班',
            yAxisIndex: 0,
            data: [23, 42, 76, 54, 87, 34, 53, 76, 54, 87, 34, 53]
          },
          {
            type: 'line',
            name: '数铣三班',
            yAxisIndex: 0,
            data: [10, 84, 21, 42, 53, 57, 32, 21, 42, 53, 57, 32]
          },
          {
            type: 'line',
            name: '数车班',
            yAxisIndex: 0,
            data: [23, 32, 42, 35, 64, 53, 16, 42, 35, 64, 53, 16]
            name: item.productionName,
            data: item.dataList.map(item => item.utilizationRate)
          }
        ]
        })
        // series: [
        //   {
        //     type: 'line',
        //     name: '数铣一班',
        //     data: [85, 32, 23, 56, 24, 64]
        //   },
        //   {
        //     type: 'line',
        //     name: '数铣二班',
        //     data: [23, 42, 76, 54, 87, 34]
        //   },
        //   {
        //     type: 'line',
        //     name: '数铣三班',
        //     data: [10, 84, 21, 42, 53, 57]
        //   },
        //   {
        //     type: 'line',
        //     name: '数车班',
        //     data: [23, 32, 42, 35, 64, 53]
        //   }
        // ]
      }
      this[position + 'ChartContainer'].setOption(option, true)
      if (isHideLoading) this[position + 'ChartContainer'].hideLoading()
    },
    // 调用接口获取控制系统类型
    getDriveTypeByApi() {
      api.getDriveTypeApi().then((res) => {
        this.driveTypeList = res.result.map(item => item.value)
      })
    },
    /**
     * 联想输入框筛选功能
     * @param input 输入的内容
     * @param option 配置
     * @returns {boolean} 判断是否筛选
     */
    filterOption(input, option) {
      return (
        option.componentOptions.children[0].text.toUpperCase().indexOf(input.toUpperCase()) >= 0
      )
    // 获取中心列表
    getCenterListByApi() {
      mdcApi.getCenterOrGroupListApi()
        .then(res => {
          if (res.success) {
            this.centerList = res.result
            this.queryParam.productionId = res.result[0].value
            this.loadData()
          }
        })
    },
    handleWindowResize() {
      if (this.leftChartContainer) this.leftChartContainer.resize()
      if (this.middleChartContainer) this.middleChartContainer.resize()
      if (this.rightChartContainer) this.rightChartContainer.resize()
    }
  }
}
</script>
<style scoped lang="less">
</style>
</script>
src/views/mdc/base/modules/DeliveryGroupUtilizationRateChart/ChartComponent.vue
@@ -106,15 +106,15 @@
          }
        },
        grid: {
          top: '10%',
          top: '12%',
          left: '1%',
          right: '1%',
          bottom: '1%',
          containLabel: true
        },
        legend: {
          top: 0,
          right: 0,
          top: '6%',
          right: 'center',
          itemGap: 20,
          data: ['综合效率(全部设备时间)', '综合效率(去除故障设备时间)']
        },
src/views/system/UserList.vue
@@ -14,48 +14,19 @@
          </a-col>
          <a-col :md="6" :sm="8">
            <a-form-item label="性别">
              <a-select v-model="queryParam.sex" placeholder="请选择性别">
            <a-form-item label="用户状态">
              <a-select v-model="queryParam.status" placeholder="请选择">
                <a-select-option value="">请选择</a-select-option>
                <a-select-option value="1">男</a-select-option>
                <a-select-option value="2">女</a-select-option>
                <a-select-option value="1">正常</a-select-option>
                <a-select-option value="2">冻结</a-select-option>
              </a-select>
            </a-form-item>
          </a-col>
          <template v-if="toggleSearchStatus">
            <a-col :md="6" :sm="8">
              <a-form-item label="真实名字">
                <a-input placeholder="请输入真实名字" v-model="queryParam.realname"></a-input>
              </a-form-item>
            </a-col>
            <a-col :md="6" :sm="8">
              <a-form-item label="手机号码">
                <a-input placeholder="请输入手机号码查询" v-model="queryParam.phone"></a-input>
              </a-form-item>
            </a-col>
            <a-col :md="6" :sm="8">
              <a-form-item label="用户状态">
                <a-select v-model="queryParam.status" placeholder="请选择">
                  <a-select-option value="">请选择</a-select-option>
                  <a-select-option value="1">正常</a-select-option>
                  <a-select-option value="2">冻结</a-select-option>
                </a-select>
              </a-form-item>
            </a-col>
          </template>
          <a-col :md="6" :sm="8">
            <span style="float: left;overflow: hidden;" class="table-page-search-submitButtons">
              <a-button type="primary" @click="searchQuery" icon="search">查询</a-button>
              <a-button type="primary" @click="searchReset" icon="reload" style="margin-left: 8px">重置</a-button>
              <a @click="handleToggleSearch" style="margin-left: 8px">
                {{ toggleSearchStatus ? '收起' : '展开' }}
                <a-icon :type="toggleSearchStatus ? 'up' : 'down'"/>
              </a>
            </span>
          </a-col>
src/views/system/modules/PasswordModal.vue
@@ -16,12 +16,13 @@
          <a-input placeholder="请输入用户账号" v-decorator="[ 'username', {}]" :readOnly="true"/>
        </a-form-item>
        <a-form-item label="登录密码" :labelCol="labelCol" :wrapperCol="wrapperCol" hasFeedback >
          <a-input type="password" placeholder="请输入登录密码" v-decorator="[ 'password', validatorRules.password]" />
        <a-form-item label="登录密码" :labelCol="labelCol" :wrapperCol="wrapperCol" hasFeedback>
          <a-input type="password" placeholder="请输入登录密码" v-decorator="[ 'password', validatorRules.password]"/>
        </a-form-item>
        <a-form-item label="确认密码" :labelCol="labelCol" :wrapperCol="wrapperCol" hasFeedback >
          <a-input type="password" @blur="handleConfirmBlur" placeholder="请重新输入登录密码" v-decorator="[ 'confirmpassword', validatorRules.confirmpassword]"/>
        <a-form-item label="确认密码" :labelCol="labelCol" :wrapperCol="wrapperCol" hasFeedback>
          <a-input type="password" @blur="handleConfirmBlur" placeholder="请重新输入登录密码"
                   v-decorator="[ 'confirmpassword', validatorRules.confirmpassword]"/>
        </a-form-item>
      </a-form>
@@ -30,113 +31,115 @@
</template>
<script>
  import {changePassword} from '@/api/api'
import { changePassword } from '@/api/api'
  export default {
    name: "PasswordModal",
    data () {
      return {
        visible: false,
        confirmLoading: false,
        confirmDirty: false,
        validatorRules:{
          password:{
            rules: [{
export default {
  name: 'PasswordModal',
  data() {
    return {
      visible: false,
      confirmLoading: false,
      confirmDirty: false,
      validatorRules: {
        password: {
          rules: [
            {
              required: true,
              pattern:/^(?=.*[a-zA-Z])(?=.*\d)(?=.*[~!@#$%^&*()_+`\-={}:";'<>?,./]).{8,}$/,
              message: '密码由8位数字、大小写字母和特殊符号组成!'
            }, {
              validator: this.validateToNextPassword,
            }],
          },
          confirmpassword:{
            rules: [{
              required: true, message: '请重新输入登录密码!',
            }, {
              validator: this.compareToFirstPassword,
            }],
          },
              // pattern:/^(?=.*[a-zA-Z])(?=.*\d)(?=.*[~!@#$%^&*()_+`\-={}:";'<>?,./]).{8,}$/,
              message: '请输入登录密码!'
            },
            {
              validator: this.validateToNextPassword
            }]
        },
        confirmpassword: {
          rules: [{
            required: true, message: '请重新输入登录密码!'
          }, {
            validator: this.compareToFirstPassword
          }]
        }
      },
        model: {},
      model: {},
        labelCol: {
          xs: { span: 24 },
          sm: { span: 5 },
        },
        wrapperCol: {
          xs: { span: 24 },
          sm: { span: 16 },
        },
        form:this.$form.createForm(this)
      labelCol: {
        xs: { span: 24 },
        sm: { span: 5 }
      },
      wrapperCol: {
        xs: { span: 24 },
        sm: { span: 16 }
      },
      form: this.$form.createForm(this)
    }
  },
  created() {
    console.log('created')
  },
  methods: {
    show(username) {
      this.form.resetFields()
      this.visible = true
      this.model.username = username
      this.$nextTick(() => {
        this.form.setFieldsValue({ username: username })
      })
    },
    close() {
      this.$emit('close')
      this.visible = false
      this.disableSubmit = false
      this.selectedRole = []
    },
    handleSubmit() {
      // 触发表单验证
      this.form.validateFields((err, values) => {
        if (!err) {
          this.confirmLoading = true
          let formData = Object.assign(this.model, values)
          changePassword(formData).then((res) => {
            if (res.success) {
              this.$message.success(res.message)
              this.$emit('ok')
            } else {
              this.$message.warning(res.message)
            }
          }).finally(() => {
            this.confirmLoading = false
            this.close()
          })
        }
      })
    },
    handleCancel() {
      this.close()
    },
    validateToNextPassword(rule, value, callback) {
      const form = this.form
      const confirmpassword = form.getFieldValue('confirmpassword')
      console.log('confirmpassword==>', confirmpassword)
      if (value && confirmpassword && value !== confirmpassword) {
        callback('两次输入的密码不一样!')
      }
      if (value && this.confirmDirty) {
        form.validateFields(['confirm'], { force: true })
      }
      callback()
    },
    compareToFirstPassword(rule, value, callback) {
      const form = this.form
      if (value && value !== form.getFieldValue('password')) {
        callback('两次输入的密码不一样!')
      } else {
        callback()
      }
    },
    created () {
      console.log("created");
    },
    methods: {
      show (username) {
        this.form.resetFields();
        this.visible = true;
        this.model.username = username;
        this.$nextTick(() => {
          this.form.setFieldsValue({username:username});
        });
      },
      close () {
        this.$emit('close');
        this.visible = false;
        this.disableSubmit = false;
        this.selectedRole = [];
      },
      handleSubmit () {
        // 触发表单验证
        this.form.validateFields((err, values) => {
          if (!err) {
            this.confirmLoading = true;
            let formData = Object.assign(this.model, values);
            changePassword(formData).then((res)=>{
              if(res.success){
                this.$message.success(res.message);
                this.$emit('ok');
              }else{
                this.$message.warning(res.message);
              }
            }).finally(() => {
              this.confirmLoading = false;
              this.close();
            });
          }
        })
      },
      handleCancel () {
        this.close()
      },
      validateToNextPassword  (rule, value, callback) {
        const form = this.form;
        const confirmpassword=form.getFieldValue('confirmpassword');
        console.log("confirmpassword==>",confirmpassword);
        if (value && confirmpassword && value !== confirmpassword) {
          callback('两次输入的密码不一样!');
        }
        if (value && this.confirmDirty) {
          form.validateFields(['confirm'], { force: true })
        }
        callback();
      },
      compareToFirstPassword  (rule, value, callback) {
        const form = this.form;
        if (value && value !== form.getFieldValue('password')) {
          callback('两次输入的密码不一样!');
        } else {
          callback()
        }
      },
      handleConfirmBlur  (e) {
        const value = e.target.value
        this.confirmDirty = this.confirmDirty || !!value
      }
    handleConfirmBlur(e) {
      const value = e.target.value
      this.confirmDirty = this.confirmDirty || !!value
    }
  }
}
</script>
src/views/system/modules/UserModal.vue
@@ -157,7 +157,8 @@
          :wrapperCol="wrapperCol"
          v-show="!productionDisabled"
        >
          <a-tooltip title="选择设备后,用户就只有这些设备的权限!不选择设备,则会根据车间分配控制设备的权限!" placement="topRight">
          <a-tooltip title="选择设备后,用户就只有这些设备的权限!不选择设备,则会根据车间分配控制设备的权限!"
                     placement="topRight">
            <a-input-search
              :readOnly="true"
              v-model="model.equipmentIds"
@@ -170,70 +171,69 @@
        </a-form-model-item>
        <!--<a-form-model-item-->
          <!--label="首页权限"-->
          <!--:labelCol="labelCol"-->
          <!--:wrapperCol="wrapperCol"-->
        <!--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-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"-->
          <!--prop="teamId"-->
        <!--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>-->
        <!--<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"-->
        <!--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>-->
        <!--&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"-->
        <!--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>-->
        <!--<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-->
@@ -348,504 +348,504 @@
</template>
<script>
  import moment from 'moment'
  import Vue from 'vue'
  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 { duplicateCheck } from '@/api/api'
  import JSelectProduction from '../../../components/jeecgbiz/JSelectProduction'
  import { mapActions } from 'vuex'
  import { ajaxGetDictItems, getDictItemsFromCache } from '@/api/api'
  import SelectDeviceModal from './SelectDeviceModal'
import moment from 'moment'
import Vue from 'vue'
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 { 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',
    components: {
      SelectDeviceModal,
      JSelectProduction
    },
    data() {
      return {
        departDisabled: false, //是否是我的部门调用该页面
        productionDisabled: false, //是否是我的车间调用该页面
        roleDisabled: false, //是否是角色维护调用该页面
        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: 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: '请输入正确的座机号码' }],
          teamId: [{ required: false, message: '请维护班组' }]
        },
        departIdShow: false,
        title: '操作',
        visible: false,
        model: {},
        labelCol: {
          xs: { span: 24 },
          sm: { span: 5 }
        },
        wrapperCol: {
          xs: { span: 24 },
          sm: { span: 16 }
        },
        uploadLoading: false,
        confirmLoading: false,
        headers: {},
        url: {
          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: [],
        nextProductionOptions: [],
        isDepartType: '',
        model: {
          selectedProduction: ''
        }
      }
    },
    watch: {
      visible: {
        handler(value) {
          if (value) this.initDictData('password_length')
        }
export default {
  name: 'UserModal',
  components: {
    SelectDeviceModal,
    JSelectProduction
  },
  data() {
    return {
      departDisabled: false, //是否是我的部门调用该页面
      productionDisabled: false, //是否是我的车间调用该页面
      roleDisabled: false, //是否是角色维护调用该页面
      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: '请输入登录密码!'
          },
          { 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: '请输入正确的座机号码' }],
        teamId: [{ required: false, message: '请维护班组' }]
      },
      '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
      }
    },
    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(() => {
        })
      departIdShow: false,
      title: '操作',
      visible: false,
      model: {},
      labelCol: {
        xs: { span: 24 },
        sm: { span: 5 }
      },
      add() {
        this.refresh()
        this.edit({
          activitiSync: '1',
          userType: 0,
          userIdentity: 1,
          selectedroles: '',
          selecteddeparts: '',
          selectedProduction: ''
        })
      wrapperCol: {
        xs: { span: 24 },
        sm: { span: 16 }
      },
      edit(record) {
        let that = this
        that.visible = true
        //根据屏幕宽度自适应抽屉宽度
        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 (record.hasOwnProperty('id')) {
          that.getUserRoles(record.id)
          that.getUserDeparts(record.id)
        }
      uploadLoading: false,
      confirmLoading: false,
      headers: {},
      url: {
        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'
      },
      isDisabledAuth(code) {
        return disabledAuthFilter(code)
      },
      //窗口最大化切换
      toggleScreen() {
        if (this.modaltoggleFlag) {
          this.modalWidth = window.innerWidth
        } else {
          this.modalWidth = 800
        }
        this.modaltoggleFlag = !this.modaltoggleFlag
      },
      // 根据屏幕变化,设置抽屉尺寸
      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
            })
          }
        })
      },
      //初始化角色字典
      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
            })
          }
        })
      },
      getUserRoles(userid) {
        queryUserRole({ userid: userid }).then((res) => {
          if (res.success) {
            this.$set(this.model, 'selectedroles', res.result.join(','))
          }
        })
      },
      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)
              //新增负责部门选择下拉框
              departOptions.push({
                value: res.result[i].key,
                label: res.result[i].title
              })
            }
            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
        })
      },
      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
        })
      },
      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
        // 触发表单验证
        this.$refs.form.validate(valid => {
          if (valid) {
            that.confirmLoading = true
            //如果是上级择传入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)
            }
            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()
            })
          } else {
            return false
          }
        })
      },
      handleCancel() {
        this.close()
      },
      validateToNextPassword(rule, value, callback) {
        const confirmpassword = this.model.confirmpassword
        if (value && confirmpassword && value !== confirmpassword) {
          callback('两次输入的密码不一样!')
        }
        if (value && this.confirmDirty) {
          this.$refs.form.validateField(['confirmpassword'])
        }
        callback()
      },
      compareToFirstPassword(rule, value, callback) {
        if (value && value !== this.model.password) {
          callback('两次输入的密码不一样!')
        } else {
          callback()
        }
      },
      validatePhone(rule, value, callback) {
        if (!value) {
          callback()
        } 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('手机号已存在!')
              }
            })
          } else {
            callback('请输入正确格式的手机号码!')
          }
        }
      },
      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)) {
            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('邮箱已存在!')
              }
            })
          } else {
            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('用户名已存在!')
          }
        })
      },
      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('工号已存在!')
          }
        })
      },
      handleConfirmBlur(e) {
        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
        }
        //TODO 验证文件大小
      },
      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(','))
      tenantsOptions: [],
      rolesOptions: [],
      nextDepartOptions: [],
      nextProductionOptions: [],
      isDepartType: '',
      model: {
        selectedProduction: ''
      }
    }
  },
  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
    }
  },
  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(() => {
      })
    },
    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
      console.log('record', record)
      that.model = Object.assign({}, record)
      //身份为上级显示负责部门,否则不显示
      if (this.model.userIdentity == 2) {
        this.departIdShow = true
      } else {
        this.departIdShow = false
      }
      if (record.hasOwnProperty('id')) {
        that.getUserRoles(record.id)
        that.getUserDeparts(record.id)
      }
    },
    isDisabledAuth(code) {
      return disabledAuthFilter(code)
    },
    //窗口最大化切换
    toggleScreen() {
      if (this.modaltoggleFlag) {
        this.modalWidth = window.innerWidth
      } else {
        this.modalWidth = 800
      }
      this.modaltoggleFlag = !this.modaltoggleFlag
    },
    // 根据屏幕变化,设置抽屉尺寸
    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
          })
        }
      })
    },
    //初始化角色字典
    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
          })
        }
      })
    },
    getUserRoles(userid) {
      queryUserRole({ userid: userid }).then((res) => {
        if (res.success) {
          this.$set(this.model, 'selectedroles', res.result.join(','))
        }
      })
    },
    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)
            //新增负责部门选择下拉框
            departOptions.push({
              value: res.result[i].key,
              label: res.result[i].title
            })
          }
          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
      })
    },
    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
      })
    },
    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
      // 触发表单验证
      this.$refs.form.validate(valid => {
        if (valid) {
          that.confirmLoading = true
          //如果是上级择传入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)
          }
          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()
          })
        } else {
          return false
        }
      })
    },
    handleCancel() {
      this.close()
    },
    validateToNextPassword(rule, value, callback) {
      const confirmpassword = this.model.confirmpassword
      if (value && confirmpassword && value !== confirmpassword) {
        callback('两次输入的密码不一样!')
      }
      if (value && this.confirmDirty) {
        this.$refs.form.validateField(['confirmpassword'])
      }
      callback()
    },
    compareToFirstPassword(rule, value, callback) {
      if (value && value !== this.model.password) {
        callback('两次输入的密码不一样!')
      } else {
        callback()
      }
    },
    validatePhone(rule, value, callback) {
      if (!value) {
        callback()
      } 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('手机号已存在!')
            }
          })
        } else {
          callback('请输入正确格式的手机号码!')
        }
      }
    },
    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)) {
          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('邮箱已存在!')
            }
          })
        } else {
          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('用户名已存在!')
        }
      })
    },
    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('工号已存在!')
        }
      })
    },
    handleConfirmBlur(e) {
      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
      }
      //TODO 验证文件大小
    },
    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(','))
    }
  }
}
</script>
<style scoped>
  .avatar-uploader > .ant-upload {
    width: 104px;
    height: 104px;
  }
.avatar-uploader > .ant-upload {
  width: 104px;
  height: 104px;
}
  .ant-upload-select-picture-card i {
    font-size: 49px;
    color: #999;
  }
.ant-upload-select-picture-card i {
  font-size: 49px;
  color: #999;
}
  .ant-upload-select-picture-card .ant-upload-text {
    margin-top: 8px;
    color: #666;
  }
.ant-upload-select-picture-card .ant-upload-text {
  margin-top: 8px;
  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-bottom-button {
    position: absolute;
    bottom: -8px;
    width: 100%;
    border-top: 1px solid #e8e8e8;
    padding: 10px 16px;
    text-align: right;
    left: 0;
    background: #fff;
    border-radius: 0 0 2px 2px;
  }
.drawer-bottom-button {
  position: absolute;
  bottom: -8px;
  width: 100%;
  border-top: 1px solid #e8e8e8;
  padding: 10px 16px;
  text-align: right;
  left: 0;
  background: #fff;
  border-radius: 0 0 2px 2px;
}
</style>