ソースを参照

feat(search): 将列表查询条件从单选改为多选支持

- 检查任务、检查标准页面的设备类型改为树形多选(multiple)
- 任务状态、工单类别、部门等下拉框添加 mode="multiple" 属性
- 查询参数字段由单数改为复数形式(如 status → statusList、level → levelList)
- 设备信息页的等级、自定义类型、所属车间、设备状态、主子设备均支持多选
- 备件信息、备件库存、快速出库等页面同步改为多选查询
- 维修工单页新增「我的工单」不默认按部门筛选的逻辑调整
- 新增批量下载保养记录PDF弹窗组件,支持按时间范围和部门筛选
dazhaxie 3 週間 前
親
コミット
b03cb10b26

+ 3 - 3
src/views/check/checkjob/CheckJob.vue

@@ -26,8 +26,8 @@
             <a-col :md="6" :sm="24">
               <a-form-item label="设备类型">
                 <a-tree-select style="width: 100%" :dropdownStyle="{ maxHeight: '400px', overflow: 'auto' }"
-                  :treeData="treeData" :treeNodeFilterProp="'title'" :showSearch="true" v-model="queryParam.typeId"
-                  placeholder="请选择">
+                  :treeData="treeData" :treeNodeFilterProp="'title'" :showSearch="true" v-model="queryParam.typeIdList"
+                  multiple allowClear placeholder="请选择">
                 </a-tree-select>
               </a-form-item>
             </a-col>
@@ -56,7 +56,7 @@
             </a-col>
             <a-col :md="6" :sm="24">
               <a-form-item label="任务状态">
-                <a-select v-model="queryParam.status" placeholder="请选择">
+                <a-select v-model="queryParam.statusList" mode="multiple" placeholder="请选择">
                   <a-select-option v-for="(label, value) in statusMap" :key="value" :label="label"
                     :value="parseInt(value)">{{ label }}
                   </a-select-option>

+ 242 - 0
src/views/check/checkjob/modules/BatchDownloadModal.vue

@@ -0,0 +1,242 @@
+<template>
+  <a-modal
+    title="批量下载保养记录PDF"
+    :width="580"
+    :visible="visible"
+    :maskClosable="false"
+    @cancel="handleCancel"
+  >
+    <a-form layout="vertical">
+      <a-form-item label="时间范围">
+        <a-radio-group v-model="rangeMode" button-style="solid" @change="onPresetChange">
+          <a-radio-button value="year">今年</a-radio-button>
+          <a-radio-button value="quarter">本季度</a-radio-button>
+          <a-radio-button value="lastQuarter">上季度</a-radio-button>
+          <a-radio-button value="month">本月</a-radio-button>
+          <a-radio-button value="custom">自定义</a-radio-button>
+        </a-radio-group>
+      </a-form-item>
+      <a-form-item label="起止日期">
+        <a-range-picker
+          v-model="dateRange"
+          style="width: 100%"
+          format="YYYY-MM-DD"
+          :allowClear="false"
+          @change="onDateChange"
+        />
+      </a-form-item>
+      <a-form-item label="部门/班组">
+        <a-tree-select
+          v-model="deptId"
+          style="width: 100%"
+          :dropdownStyle="{ maxHeight: '400px', overflow: 'auto' }"
+          :treeData="deptTree"
+          treeNodeFilterProp="title"
+          :showSearch="true"
+          allowClear
+          placeholder="不选则下载全部部门"
+          @change="loadCount"
+        />
+        <div class="batch-download-tip">
+          按部门筛选时,会同时包含该部门(含所有下级)的班组任务,以及执行人属于该部门范围的非班组任务;不选部门则为全部。
+        </div>
+      </a-form-item>
+    </a-form>
+
+    <a-alert :type="countType" show-icon>
+      <template slot="message">
+        <span v-if="countLoading">正在统计可下载数量...</span>
+        <span v-else-if="count > 0">
+          将下载约 <b>{{ count }}</b> 条已完成保养记录({{ rangeText }})
+        </span>
+        <span v-else>当前条件下没有可下载的已完成保养记录({{ rangeText }})</span>
+      </template>
+    </a-alert>
+
+    <template slot="footer">
+      <a-button @click="handleCancel">取消</a-button>
+      <a-button
+        type="primary"
+        icon="download"
+        :loading="downloading"
+        :disabled="count === 0 || countLoading"
+        @click="doDownload"
+      >下载PDF压缩包</a-button>
+    </template>
+  </a-modal>
+</template>
+
+<script>
+import { getDeptTree } from '@/api/upms/dept'
+import { batchDownloadCheckJobPdf, countCheckJobDownloadPdf } from '@/api/check/checkjob'
+
+export default {
+  name: 'BatchDownloadModal',
+  props: {
+    // 检查类型:1-点检 2-保养,与列表页保持一致
+    checkType: {
+      type: Number,
+      default: null
+    },
+    // 数据权限过滤标识,透传给后端保证与列表可见范围一致
+    filter: {
+      type: Number,
+      default: null
+    },
+    // 任务状态,保养记录页固定为 3(已完成)
+    status: {
+      type: Number,
+      default: 3
+    }
+  },
+  data () {
+    return {
+      visible: false,
+      downloading: false,
+      countLoading: false,
+      count: 0,
+      rangeMode: 'year',
+      dateRange: [],
+      deptId: undefined,
+      deptTree: []
+    }
+  },
+  computed: {
+    countType () {
+      if (this.countLoading) {
+        return 'info'
+      }
+      return this.count > 0 ? 'success' : 'warning'
+    },
+    rangeText () {
+      if (!this.dateRange || this.dateRange.length !== 2) {
+        return '未选择时间'
+      }
+      const start = this.dateRange[0].format('YYYY-MM-DD')
+      const end = this.dateRange[1].format('YYYY-MM-DD')
+      return start + ' ~ ' + end
+    }
+  },
+  methods: {
+    base () {
+      this.visible = true
+      this.downloading = false
+      this.count = 0
+      this.deptId = undefined
+      this.rangeMode = 'year'
+      this.applyPreset('year')
+      this.loadDeptTree()
+      this.loadCount()
+    },
+    loadDeptTree () {
+      if (this.deptTree && this.deptTree.length > 0) {
+        return
+      }
+      getDeptTree({}).then((res) => {
+        this.deptTree = res.data || []
+      })
+    },
+    onPresetChange (e) {
+      const mode = e.target.value
+      if (mode === 'custom') {
+        // 自定义模式保留当前日期,由用户手动选择
+        this.loadCount()
+        return
+      }
+      this.applyPreset(mode)
+      this.loadCount()
+    },
+    onDateChange (dates) {
+      this.dateRange = dates || []
+      this.rangeMode = 'custom'
+      this.loadCount()
+    },
+    applyPreset (mode) {
+      const m = this.BaseTool.Moment
+      const today = m()
+      let start
+      let end
+      if (mode === 'year') {
+        start = m(today).startOf('year')
+        end = m(today).endOf('year')
+      } else if (mode === 'quarter') {
+        start = m(today).startOf('quarter')
+        end = m(today).endOf('quarter')
+      } else if (mode === 'lastQuarter') {
+        start = m(today).subtract(1, 'quarters').startOf('quarter')
+        end = m(today).subtract(1, 'quarters').endOf('quarter')
+      } else if (mode === 'month') {
+        start = m(today).startOf('month')
+        end = m(today).endOf('month')
+      } else {
+        return
+      }
+      this.dateRange = [start, end]
+    },
+    buildParams () {
+      const params = {
+        status: this.status
+      }
+      if (this.checkType !== null && this.checkType !== undefined) {
+        params.type = this.checkType
+      }
+      if (this.filter !== null && this.filter !== undefined) {
+        params.filter = this.filter
+      }
+      if (this.dateRange && this.dateRange.length === 2) {
+        params.searchStartTime = this.dateRange[0].format('YYYY-MM-DD') + ' 00:00:00'
+        params.searchEndTime = this.dateRange[1].format('YYYY-MM-DD') + ' 23:59:59'
+      }
+      if (this.deptId) {
+        params.batchDeptId = this.deptId
+      }
+      return params
+    },
+    loadCount () {
+      if (!this.dateRange || this.dateRange.length !== 2) {
+        this.count = 0
+        return
+      }
+      this.countLoading = true
+      countCheckJobDownloadPdf(this.buildParams())
+        .then((res) => {
+          this.count = (res && res.data) || 0
+        })
+        .catch(() => {
+          this.count = 0
+        })
+        .finally(() => {
+          this.countLoading = false
+        })
+    },
+    doDownload () {
+      this.downloading = true
+      this.$message.loading({ content: '正在打包保养记录PDF,请稍候...', key: 'batchPdf', duration: 0 })
+      batchDownloadCheckJobPdf(this.buildParams())
+        .then((file) => {
+          this.BaseTool.UPLOAD.downLoadExportExcel(file)
+          this.$message.success({ content: '打包下载成功', key: 'batchPdf', duration: 2 })
+          this.visible = false
+        })
+        .catch(() => {
+          this.$message.error({ content: '没有可下载的保养记录PDF或下载失败', key: 'batchPdf', duration: 3 })
+        })
+        .finally(() => {
+          this.downloading = false
+        })
+    },
+    handleCancel () {
+      this.visible = false
+    }
+  }
+}
+</script>
+
+<style scoped>
+.batch-download-tip {
+  color: #888;
+  font-size: 12px;
+  line-height: 1.5;
+  margin-top: 4px;
+}
+</style>

+ 2 - 2
src/views/check/checkstandard/CheckStandard.vue

@@ -22,8 +22,8 @@
             <a-col :md="6" :sm="24">
               <a-form-item label="设备类型">
                 <a-tree-select style="width: 100%" :dropdownStyle="{ maxHeight: '400px', overflow: 'auto' }"
-                  :treeData="treeData" :treeNodeFilterProp="'title'" :showSearch="true" v-model="queryParam.typeId"
-                  placeholder="请选择">
+                  :treeData="treeData" :treeNodeFilterProp="'title'" :showSearch="true" v-model="queryParam.typeIdList"
+                  multiple allowClear placeholder="请选择">
                 </a-tree-select>
               </a-form-item>
             </a-col>

+ 2 - 2
src/views/repair/application-form/RepairApplicationForm.vue

@@ -31,7 +31,7 @@
             </a-col>
             <a-col :md="6" :sm="24">
               <a-form-item label="工单类别">
-                <a-select v-model="queryParam.category" placeholder="请选择">
+                <a-select v-model="queryParam.categoryList" mode="multiple" placeholder="请选择">
                   <a-select-option v-for="(label, value) in categoryMap" :key="value" :label="label"
                     :value="parseInt(value)">{{ label }}
                   </a-select-option>
@@ -40,7 +40,7 @@
             </a-col>
             <a-col :md="6" :sm="24">
               <a-form-item label="状态">
-                <a-select v-model="queryParam.status" placeholder="请选择">
+                <a-select v-model="queryParam.statusList" mode="multiple" placeholder="请选择">
                   <a-select-option v-for="(label, value) in statusMap" :key="value" :label="label"
                     :value="parseInt(value)">{{ label }}
                   </a-select-option>

+ 9 - 18
src/views/repair/application-form/RepairForm.vue

@@ -26,7 +26,7 @@
             </a-col>
             <a-col :md="6" :sm="24">
               <a-form-item label="部门">
-                <a-select v-model="queryParam.deptId" placeholder="请选择部门" allowClear showSearch
+                <a-select v-model="queryParam.deptIdList" mode="multiple" placeholder="请选择部门" allowClear showSearch
                   optionFilterProp="label">
                   <a-select-option v-for="item in deptList" :key="item.deptId" :label="item.name"
                     :value="item.deptId">{{ item.name }}
@@ -41,7 +41,7 @@
             </a-col>
             <a-col :md="6" :sm="24">
               <a-form-item label="状态">
-                <a-select v-model="queryParam.status" placeholder="请选择">
+                <a-select v-model="queryParam.statusList" mode="multiple" placeholder="请选择">
                   <a-select-option v-for="(label, value) in statusMap" :key="value" :label="label"
                     :value="parseInt(value)">{{ label }}
                   </a-select-option>
@@ -162,12 +162,13 @@ export default {
     }
   },
   data() {
-    // 从通知链接跳转时(带no参数),不默认按本部门筛选,避免跨部门工单看不到
+    // 从通知链接跳转时(带no参数)或「我的工单」页面,不默认按本部门筛选,显示全部工单
     const hasNoParam = this.$route.query.no != null
+    const skipDeptDefault = hasNoParam || this.searchType === 2
     return {
       // 查询参数
       queryParam: {
-        deptId: hasNoParam ? null : this.$store.getters.userInfo.deptId,
+        deptIdList: skipDeptDefault ? [] : [this.$store.getters.userInfo.deptId],
         searchStartTime: null,
         searchEndTime: null
       },
@@ -336,23 +337,12 @@ export default {
     if (no != null) {
       this.queryParam.no = no
       // 从通知跳转过来时,清除部门筛选,确保能看到该工单
-      this.queryParam.deptId = null
+      this.queryParam.deptIdList = []
     }
     // 部门下拉数据
     queryDept({}).then(res => {
       this.deptList = res.data || []
     })
-    // 我的工单:默认查询当前登录人部门的所有相关工单
-    // if (this.searchType === 2) {
-    // selectUserDept().then(res => {
-    //   if (res.data && res.data.deptId) {
-    //     this.queryParam.deptId = res.data.deptId
-    //     if (this.$refs.table) {
-    //       this.$refs.table.refresh()
-    //     }
-    //   }
-    // })
-    // }
     this.tableOption()
   },
   methods: {
@@ -435,10 +425,11 @@ export default {
       this.selectedRows = selectedRows
     },
     resetSearchForm() {
-      // 重置时:如果是从通知跳转(带no参数),则不恢复部门筛选
+      // 重置时:通知跳转(带no参数)或「我的工单」页面不恢复部门筛选
       const no = this.$route.query.no
+      const skipDeptDefault = no != null || this.searchType === 2
       this.queryParam = {
-        deptId: no != null ? null : this.$store.getters.userInfo.deptId,
+        deptId: skipDeptDefault ? null : this.$store.getters.userInfo.deptId,
         searchStartTime: null,
         searchEndTime: null
       }

+ 1 - 1
src/views/repair/application-form/RepairOut.vue

@@ -11,7 +11,7 @@
             </a-col>
             <a-col :md="8" :sm="24">
               <a-form-item label="状态">
-                <a-select v-model="queryParam.status" placeholder="全部" allowClear>
+                <a-select v-model="queryParam.statusList" mode="multiple" placeholder="全部" allowClear>
                   <a-select-option :value="1">委外维修中</a-select-option>
                   <a-select-option :value="2">已完成</a-select-option>
                 </a-select>

+ 7 - 7
src/views/sb/info/SbInfo.vue

@@ -40,7 +40,7 @@
                 </a-col>
                 <a-col :md="6" :sm="24">
                   <a-form-item label="设备等级">
-                    <a-select v-model="queryParam.level" placeholder="请选择">
+                    <a-select v-model="queryParam.levelList" mode="multiple" placeholder="请选择">
                       <a-select-option v-for="(label, value) in levelMap" :key="value" :label="label"
                         :value="parseInt(value)">{{ label }}
                       </a-select-option>
@@ -49,7 +49,7 @@
                 </a-col>
                 <a-col :md="6" :sm="24">
                   <a-form-item label="自定义类型">
-                    <a-select v-model="queryParam.useType" placeholder="请选择">
+                    <a-select v-model="queryParam.useTypeList" mode="multiple" placeholder="请选择">
                       <a-select-option v-for="(label, value) in useTypeMap" :key="value" :label="label"
                         :value="parseInt(value)">{{ label }}
                       </a-select-option>
@@ -63,7 +63,7 @@
                 </a-col>
                 <a-col :md="6" :sm="24">
                   <a-form-item label="所属车间">
-                    <a-select v-model="queryParam.positionId" placeholder="请选择">
+                    <a-select v-model="queryParam.positionIdList" mode="multiple" placeholder="请选择">
                       <a-select-option v-for="({ id, name }) in sbPositionData" :key="id" :label="name" :value="id">{{
                         name
                         }}
@@ -79,14 +79,14 @@
                 <a-col :md="6" :sm="24">
                   <a-form-item label="设备类型">
                     <a-tree-select style="width: 100%" :dropdownStyle="{ maxHeight: '400px', overflow: 'auto' }"
-                      :treeData="treeData" :treeNodeFilterProp="'title'" :showSearch="true" v-model="queryParam.typeId"
-                      placeholder="请选择">
+                      :treeData="treeData" :treeNodeFilterProp="'title'" :showSearch="true" v-model="queryParam.typeIdList"
+                      multiple allowClear placeholder="请选择">
                     </a-tree-select>
                   </a-form-item>
                 </a-col>
                 <a-col :md="6" :sm="24">
                   <a-form-item label="设备状态">
-                    <a-select v-model="queryParam.status" placeholder="请选择">
+                    <a-select v-model="queryParam.statusList" mode="multiple" placeholder="请选择">
                       <a-select-option v-for="(label, value) in statusMap" :key="value"
                         :defaultValue="DictCache.VALUE.SB_INFO_STATUS.IN_USE" :label="label" :value="parseInt(value)">{{
                           label }}
@@ -96,7 +96,7 @@
                 </a-col>
                 <a-col :md="6" :sm="24">
                   <a-form-item label="主子设备">
-                    <a-select v-model="queryParam.isChild" placeholder="请选择">
+                    <a-select v-model="queryParam.isChildList" mode="multiple" placeholder="请选择">
                       <a-select-option value="1">子设备</a-select-option>
                       <a-select-option value="2">父设备</a-select-option>
                       <a-select-option value="3">普通设备</a-select-option>

+ 4 - 4
src/views/sqarepartmanage/sparepartinfo/SparePartInfo.vue

@@ -29,7 +29,7 @@
                 <a-form-item label="类型">
                   <a-tree-select style="width: 100%" :dropdownStyle="{ maxHeight: '400px', overflow: 'auto' }"
                     :treeData="spareTypeTreeData" :treeNodeFilterProp="'title'" :showSearch="true"
-                    v-model="queryParam.typeId" placeholder="请选择">
+                    v-model="queryParam.typeIdList" multiple allowClear placeholder="请选择">
                   </a-tree-select>
                 </a-form-item>
               </a-col>
@@ -55,7 +55,7 @@
               </a-col>
               <a-col :md="8" :sm="24">
                 <a-form-item label="等级">
-                  <a-select v-model="queryParam.level" placeholder="请选择">
+                  <a-select v-model="queryParam.levelList" mode="multiple" placeholder="请选择">
                     <a-select-option v-for="(label, value) in levelMap" :key="value" :label="label"
                       :value="parseInt(value)">{{ label }}
                     </a-select-option>
@@ -64,7 +64,7 @@
               </a-col>
               <a-col :md="6" :sm="24">
                 <a-form-item label="用途">
-                  <a-select v-model="queryParam.yt" placeholder="请选择">
+                  <a-select v-model="queryParam.ytList" mode="multiple" placeholder="请选择">
                     <a-select-option v-for="(label, value) in ytMap" :key="value" :label="label"
                       :value="parseInt(value)">{{ label }}
                     </a-select-option>
@@ -73,7 +73,7 @@
               </a-col>
               <a-col :md="6" :sm="24">
                 <a-form-item label="是否专用">
-                  <a-select v-model="queryParam.isSpecial" placeholder="请选择">
+                  <a-select v-model="queryParam.isSpecialList" mode="multiple" placeholder="请选择">
                     <a-select-option v-for="(label, value) in specialMap" :key="value" :label="label"
                       :value="parseInt(value)">{{ label }}
                     </a-select-option>

+ 2 - 2
src/views/sqarepartmanage/sparepartinfo/SpareStoreTotal.vue

@@ -43,7 +43,7 @@
           </a-col>
           <a-col :md="8" :sm="24">
             <a-form-item label="等级">
-              <a-select v-model="queryParam.level" placeholder="请选择">
+              <a-select v-model="queryParam.levelList" mode="multiple" placeholder="请选择">
                 <a-select-option v-for="(label, value) in levelMap" :key="value" :label="label"
                   :value="parseInt(value)">{{ label }}
                 </a-select-option>
@@ -52,7 +52,7 @@
           </a-col>
           <a-col :md="6" :sm="24">
             <a-form-item label="用途">
-              <a-select v-model="queryParam.yt" placeholder="请选择">
+              <a-select v-model="queryParam.ytList" mode="multiple" placeholder="请选择">
                 <a-select-option v-for="(label, value) in ytMap" :key="value" :label="label" :value="parseInt(value)">{{
                   label }}
                 </a-select-option>

+ 1 - 1
src/views/store/fastoutstore/FastOutStore.vue

@@ -51,7 +51,7 @@
               </a-col>-->
               <a-col :md="8" :sm="24">
                 <a-form-item label="等级">
-                  <a-select v-model="queryParam.level" placeholder="请选择">
+                  <a-select v-model="queryParam.levelList" mode="multiple" placeholder="请选择">
                     <a-select-option
                       v-for="(label,value) in levelMap"
                       :key="value"

+ 3 - 3
src/views/store/sparestore/SpareStore.vue

@@ -45,7 +45,7 @@
               </a-col>
               <a-col :md="8" :sm="24">
                 <a-form-item label="等级">
-                  <a-select v-model="queryParam.level" placeholder="请选择">
+                  <a-select v-model="queryParam.levelList" mode="multiple" placeholder="请选择">
                     <a-select-option v-for="(label,value) in levelMap" :key="value" :label="label" :value="parseInt(value)">{{ label }}
                     </a-select-option>
                   </a-select>
@@ -53,7 +53,7 @@
               </a-col>
               <a-col :md="8" :sm="24">
                 <a-form-item label="用途">
-                  <a-select v-model="queryParam.yt" placeholder="请选择">
+                  <a-select v-model="queryParam.ytList" mode="multiple" placeholder="请选择">
                     <a-select-option v-for="(label,value) in ytMap" :key="value" :label="label" :value="parseInt(value)">{{ label }}
                     </a-select-option>
                   </a-select>
@@ -61,7 +61,7 @@
               </a-col>
               <a-col :md="8" :sm="24">
                 <a-form-item label="是否专用">
-                  <a-select v-model="queryParam.isSpecial" placeholder="请选择">
+                  <a-select v-model="queryParam.isSpecialList" mode="multiple" placeholder="请选择">
                     <a-select-option v-for="(label,value) in specialMap" :key="value" :label="label" :value="parseInt(value)">{{ label }}
                     </a-select-option>
                   </a-select>

+ 1 - 1
src/views/store/store/Store.vue

@@ -22,7 +22,7 @@
           </a-col>
           <a-col :md="6" :sm="24">
             <a-form-item label="选择等级">
-              <a-select v-model="queryParam.level" placeholder="请选择">
+              <a-select v-model="queryParam.levelList" mode="multiple" placeholder="请选择">
                 <a-select-option
                   v-for="(label,value) in levelMap"
                   :key="value"

+ 1 - 1
src/views/store/storesparebom/SpareStoreBom.vue

@@ -28,7 +28,7 @@
               </a-col>
               <a-col :md="8" :sm="24">
                 <a-form-item label="等级">
-                  <a-select v-model="queryParam.level" placeholder="请选择">
+                  <a-select v-model="queryParam.levelList" mode="multiple" placeholder="请选择">
                     <a-select-option v-for="(label,value) in levelMap" :key="value" :label="label" :value="parseInt(value)">{{ label }}
                     </a-select-option>
                   </a-select>