Переглянути джерело

feat(sparetype): 新增备件类型导入功能并优化设备信息管理

- 在备件类型页面添加导入按钮和导入模板下载功能
- 创建ImportFormAdd组件实现备件类型Excel文件上传导入
- 集成importSpareType和downloadSpareTypeImportTemplate API接口
- 更新BaseForm中saveUser字段验证规则为非必填
- 在设备信息页面添加初始化打点功能按钮和模态框
- 实现initPoints API接口用于设备位置均匀分布打点
- 添加矩形区域坐标输入和设备位置选择功能
- 集成地图名称查询和显示状态选择功能
dazhaxie 3 днів тому
батько
коміт
1d10c79fbd

+ 17 - 0
src/api/sb/position.js

@@ -156,3 +156,20 @@ export function getSbPositionSbTree (parameter) {
     }
   })
 }
+
+/**
+ * 初始化打点:将指定位置下的设备均匀分布在矩形区域内
+ * @param parameter { points: [{longitude, latitude}...], positionIds: [...] }
+ * @returns {*}
+ */
+export function initPoints (parameter) {
+  return axios({
+    url: '/sb/positions/initPoints',
+    method: 'POST',
+    headers: {
+      'Accept': 'application/json',
+      'Content-Type': 'application/json;charset=UTF-8'
+    },
+    data: parameter
+  })
+}

+ 29 - 0
src/api/sqarepartmanage/sparetype.js

@@ -155,4 +155,33 @@ export function fetchSpareTypeAndSbModelTree (parameter) {
       'Content-Type': 'application/json;charset=UTF-8'
     }
   })
+}
+
+/**
+ * 导入备件类型
+ * @param parameter FormData
+ * @returns {*}
+ */
+export function importSpareType (parameter) {
+  return axios({
+    url: '/sqarepartmanage/spare-type/import',
+    method: 'POST',
+    headers: {
+      'Accept': 'application/json',
+      'Content-Type': 'application/json;charset=UTF-8'
+    },
+    data: parameter
+  })
+}
+
+/**
+ * 下载备件类型导入模板
+ * @returns {*}
+ */
+export function downloadSpareTypeImportTemplate () {
+  return axios({
+    url: '/sqarepartmanage/spare-type/import/template',
+    method: 'get',
+    responseType: 'blob'
+  })
 }

+ 163 - 1
src/views/sb/info/SbInfo.vue

@@ -144,6 +144,7 @@
             <a-button style="margin-left:8px;" type="primary" icon="download" @click="doDownloadImportTemplate">导入模板下载</a-button>
             <a-button style="margin-left: 8px" type="primary" icon="printer" @click="handlePrintBatch()">批量打印</a-button>
             <a-button style="margin-left: 8px" v-if="$auth('sb-infos-generate-code-all')" :loading="confirmLoading" type="primary" @click="batchGenerate()">重新生成二维码</a-button>
+            <a-button style="margin-left: 8px" type="primary" icon="environment" @click="handleInitPoints">初始化打点</a-button>
             <a-dropdown v-action:edit v-if="selectedRowKeys.length > 0 && $auth('sb-infos-del')">
               <a-menu slot="overlay">
                 <a-popconfirm title="是否要删除所选数据?" @confirm="batchDelete()">
@@ -225,6 +226,107 @@
     <import-form-update ref="importModalUpdate" @ok="handleOk"/>
     <print-sb-code ref="printSbCode"/>
     <print-in-sb-info-batch ref="printInSbInfoBatch" @ok="handleOk"/>
+
+    <!-- 初始化打点弹窗 -->
+    <a-modal
+      title="初始化打点"
+      :visible="initPointsVisible"
+      :confirmLoading="initPointsLoading"
+      @ok="doInitPoints"
+      @cancel="initPointsVisible = false"
+      width="600px"
+    >
+      <a-form :form="initPointsForm" :label-col="{ span: 8 }" :wrapper-col="{ span: 14 }">
+        <a-divider orientation="left">矩形角点坐标</a-divider>
+        <a-row :gutter="16">
+          <a-col :span="12">
+            <a-form-item label="角点1 经度">
+              <a-input-number v-model="initPointsData.points[0].longitude" :step="0.000001" style="width: 100%" placeholder="经度"/>
+            </a-form-item>
+          </a-col>
+          <a-col :span="12">
+            <a-form-item label="角点1 纬度">
+              <a-input-number v-model="initPointsData.points[0].latitude" :step="0.000001" style="width: 100%" placeholder="纬度"/>
+            </a-form-item>
+          </a-col>
+        </a-row>
+        <a-row :gutter="16">
+          <a-col :span="12">
+            <a-form-item label="角点2 经度">
+              <a-input-number v-model="initPointsData.points[1].longitude" :step="0.000001" style="width: 100%" placeholder="经度"/>
+            </a-form-item>
+          </a-col>
+          <a-col :span="12">
+            <a-form-item label="角点2 纬度">
+              <a-input-number v-model="initPointsData.points[1].latitude" :step="0.000001" style="width: 100%" placeholder="纬度"/>
+            </a-form-item>
+          </a-col>
+        </a-row>
+        <a-row :gutter="16">
+          <a-col :span="12">
+            <a-form-item label="角点3 经度">
+              <a-input-number v-model="initPointsData.points[2].longitude" :step="0.000001" style="width: 100%" placeholder="经度"/>
+            </a-form-item>
+          </a-col>
+          <a-col :span="12">
+            <a-form-item label="角点3 纬度">
+              <a-input-number v-model="initPointsData.points[2].latitude" :step="0.000001" style="width: 100%" placeholder="纬度"/>
+            </a-form-item>
+          </a-col>
+        </a-row>
+        <a-row :gutter="16">
+          <a-col :span="12">
+            <a-form-item label="角点4 经度">
+              <a-input-number v-model="initPointsData.points[3].longitude" :step="0.000001" style="width: 100%" placeholder="经度"/>
+            </a-form-item>
+          </a-col>
+          <a-col :span="12">
+            <a-form-item label="角点4 纬度">
+              <a-input-number v-model="initPointsData.points[3].latitude" :step="0.000001" style="width: 100%" placeholder="纬度"/>
+            </a-form-item>
+          </a-col>
+        </a-row>
+        <a-divider orientation="left">选择设备位置</a-divider>
+        <a-form-item label="设备位置" :label-col="{ span: 4 }" :wrapper-col="{ span: 18 }">
+          <a-select
+            v-model="initPointsData.positionIds"
+            mode="multiple"
+            placeholder="请选择设备位置"
+            style="width: 100%"
+          >
+            <a-select-option
+              v-for="item in sbPositionData"
+              :key="item.id"
+              :value="item.id"
+            >{{ item.name }}</a-select-option>
+          </a-select>
+        </a-form-item>
+        <a-divider orientation="left">底图与显示</a-divider>
+        <a-form-item label="选择底图" :label-col="{ span: 4 }" :wrapper-col="{ span: 18 }">
+          <a-select
+            v-model="initPointsData.mapName"
+            placeholder="请选择底图"
+            style="width: 100%"
+          >
+            <a-select-option
+              v-for="item in mapNameList"
+              :key="item.targetId"
+              :value="item.targetId"
+            >{{ item.targetId }}</a-select-option>
+          </a-select>
+        </a-form-item>
+        <a-form-item label="是否显示" :label-col="{ span: 4 }" :wrapper-col="{ span: 18 }">
+          <a-select v-model="initPointsData.isShow" placeholder="请选择">
+            <a-select-option
+              v-for="(label, value) in isShowMap"
+              :key="value"
+              :label="label"
+              :value="parseInt(value)"
+            >{{ label }}</a-select-option>
+          </a-select>
+        </a-form-item>
+      </a-form>
+    </a-modal>
   </a-card>
 
 </template>
@@ -244,7 +346,8 @@ import ImportFormAdd from './modules/ImportFormAdd'
 import ImportFormUpdate from './modules/ImportFormUpdate'
 import PrintSbCode from '@/views/sb/info/modules/PrintSbCode'
 import PrintInSbInfoBatch from '@/views/sb/info/modules/PrintInSbInfoBatch'
-import { querySbPosition } from '@/api/sb/position'
+import { querySbPosition, initPoints } from '@/api/sb/position'
+import { queryFile } from '@/api/upms/file'
 
 export default {
   name: 'SbInfoList',
@@ -281,6 +384,20 @@ export default {
       depreciationTypeMap: {},
       visible: true,
       sbPositionData: [],
+      initPointsVisible: false,
+      initPointsLoading: false,
+      initPointsData: {
+        points: [
+          { longitude: undefined, latitude: undefined },
+          { longitude: undefined, latitude: undefined },
+          { longitude: undefined, latitude: undefined },
+          { longitude: undefined, latitude: undefined }
+        ],
+        positionIds: [],
+        mapName: undefined,
+        isShow: 1
+      },
+      mapNameList: [],
       levelMap: {},
       unitMap: {},
       areaList: {},
@@ -546,6 +663,9 @@ export default {
     querySbPosition().then(res => {
       this.sbPositionData = res.data
     })
+    queryFile({ type: 56 }).then(res => {
+      this.mapNameList = res.data
+    })
   },
   methods: {
     tableOption () {
@@ -763,6 +883,48 @@ export default {
       downloadSbInfoImportTemplate().then(file => {
         this.BaseTool.UPLOAD.downLoadExportExcel(file)
       })
+    },
+    handleInitPoints () {
+      this.initPointsData = {
+        points: [
+          { longitude: undefined, latitude: undefined },
+          { longitude: undefined, latitude: undefined },
+          { longitude: undefined, latitude: undefined },
+          { longitude: undefined, latitude: undefined }
+        ],
+        positionIds: [],
+        mapName: undefined,
+        isShow: 1
+      }
+      this.initPointsVisible = true
+    },
+    doInitPoints () {
+      // 校验坐标是否填写完整
+      const validPoints = this.initPointsData.points.every(
+        p => p.longitude !== undefined && p.longitude !== null && p.latitude !== undefined && p.latitude !== null
+      )
+      if (!validPoints) {
+        this.$message.warning('请填写完整的矩形四角点坐标')
+        return
+      }
+      if (!this.initPointsData.positionIds || this.initPointsData.positionIds.length === 0) {
+        this.$message.warning('请选择至少一个设备位置')
+        return
+      }
+      if (!this.initPointsData.mapName) {
+        this.$message.warning('请选择底图')
+        return
+      }
+      this.initPointsLoading = true
+      initPoints(this.initPointsData).then(res => {
+        this.$message.success('初始化打点成功')
+        this.initPointsVisible = false
+        this.$refs.table.refresh()
+      }).catch(() => {
+        this.$message.error('初始化打点失败')
+      }).finally(() => {
+        this.initPointsLoading = false
+      })
     }
   }
 }

+ 1 - 1
src/views/sb/info/modules/BaseForm.vue

@@ -365,7 +365,7 @@
             :labelCol="BaseTool.Constant.labelCol"
             :wrapperCol="BaseTool.Constant.wrapperCol"
           >
-            <a-select v-decorator="['saveUser', {rules: [{required: true, message: '项目部不能为空'}]}]" placeholder="请选择">
+            <a-select v-decorator="['saveUser', {rules: [{required: false, message: '项目部不能为空'}]}]" placeholder="请选择">
               <a-select-option
                 v-for="({userId, realName}) in userList"
                 :key="userId"

+ 15 - 2
src/views/sqarepartmanage/sparetype/SpareType.vue

@@ -34,6 +34,8 @@
         <div class="table-operator">
           <a-button v-if="$auth('sqarepartmanage-spare-type-add')" type="primary" icon="plus" @click="$refs.baseModal.base()">新增</a-button>
           <a-button style="margin-left: 8px" v-if="$auth('sqarepartmanage-spare-type-export')" type="primary" icon="download" @click="doExport">导出</a-button>
+          <a-button style="margin-left: 8px" type="primary" icon="upload" @click="doImport">导入</a-button>
+          <a-button style="margin-left: 8px" type="primary" icon="download" @click="doDownloadImportTemplate">导入模板下载</a-button>
           <a-dropdown v-action:edit v-if="selectedRowKeys.length > 0 && $auth('sqarepartmanage-spare-type-del')">
             <a-menu slot="overlay">
               <a-popconfirm title="是否要删除所选数据?" @confirm="batchDelete()">
@@ -79,6 +81,7 @@
     </a-row>
     <base-form ref="baseModal" @ok="handleOk"/>
     <detail ref="detailModal"/>
+    <import-form-add ref="importModal" @ok="handleOk"/>
   </a-card>
 </template>
 
@@ -86,7 +89,8 @@
 import { STable, Ellipsis } from '@/components'
 import BaseForm from './modules/BaseForm'
 import Detail from './modules/Detail'
-import { getSpareTypePage, deleteSpareTypes, fetchSpareType, exportSpareType, fetchSpareTypeTree } from '@/api/sqarepartmanage/sparetype'
+import ImportFormAdd from './modules/ImportFormAdd'
+import { getSpareTypePage, deleteSpareTypes, fetchSpareType, exportSpareType, fetchSpareTypeTree, downloadSpareTypeImportTemplate } from '@/api/sqarepartmanage/sparetype'
 
 export default {
   name: 'SpareTypeList',
@@ -94,7 +98,8 @@ export default {
     STable,
     Ellipsis,
     BaseForm,
-    Detail
+    Detail,
+    ImportFormAdd
   },
   data () {
     return {
@@ -303,6 +308,14 @@ export default {
     onExpand (expandedKeys) {
       this.expandedKeys = expandedKeys
       this.autoExpandParent = false
+    },
+    doImport () {
+      this.$refs.importModal.base()
+    },
+    doDownloadImportTemplate () {
+      downloadSpareTypeImportTemplate().then(file => {
+        this.BaseTool.UPLOAD.downLoadExportExcel(file)
+      })
     }
   }
 }

+ 108 - 0
src/views/sqarepartmanage/sparetype/modules/ImportFormAdd.vue

@@ -0,0 +1,108 @@
+<template>
+  <a-modal
+    :title="modalTitle"
+    :width="640"
+    :visible="visible"
+    :confirmLoading="confirmLoading"
+    @cancel="handleCancel"
+  >
+    <a-form :form="form">
+      <a-form-item
+        label="上传文件"
+        :labelCol="BaseTool.Constant.labelCol"
+        :wrapperCol="BaseTool.Constant.wrapperCol"
+      >
+        <a-upload :fileList="fileList" @change="handleChange" :remove="handleRemove" :beforeUpload="beforeUpload">
+          <a-button> <a-icon type="upload" />选择上传文件</a-button>
+        </a-upload>
+      </a-form-item>
+    </a-form>
+    <p style="color: red">注意事项:<br/>
+      1:编码为必填项,且不可与已有记录重复<br/>
+      2:位置类型填"大类"或"1"代表大类,填"子类"或"2"代表子类<br/>
+      3:子类的父类别编码必须填写,且该编码在系统中已存在<br/>
+      4:排序非必填,不填默认为1
+    </p>
+    <template slot="footer">
+      <a-button :loading="confirmLoading" type="primary" @click="save()">确定</a-button>
+    </template>
+  </a-modal>
+</template>
+
+<script>
+import { importSpareType } from '@/api/sqarepartmanage/sparetype'
+
+export default {
+  name: 'SpareTypeImportForm',
+  data () {
+    return {
+      confirmLoading: false,
+      modalTitle: null,
+      form: this.$form.createForm(this),
+      visible: false,
+      fileList: []
+    }
+  },
+  methods: {
+    base () {
+      this.visible = true
+      this.modalTitle = '备件类型导入'
+    },
+    handleRemove (file) {
+      const index = this.fileList.indexOf(file)
+      const newFileList = this.fileList.slice()
+      newFileList.splice(index, 1)
+      this.fileList = newFileList
+    },
+    beforeUpload (file) {
+      const reg = /\.(xls|xlsx)(\?.*)?$/
+      return new Promise((resolve, reject) => {
+        if (reg.test(file.name)) {
+          this.fileList = [file]
+          return false
+        } else {
+          this.$message.error('请上传正确的excel文件')
+          reject(new Error('请上传正确的excel文件'))
+          return false
+        }
+      })
+    },
+    handleChange (info) {
+      if (info.file.status !== 'uploading') {
+        console.log(info.file, info.fileList)
+      }
+      if (info.file.status === 'done') {
+        this.$message.success(`${info.file.name} file uploaded successfully`)
+      } else if (info.file.status === 'error') {
+        this.$message.error(`${info.file.name} file upload failed.`)
+      }
+    },
+    save () {
+      const { form: { validateFieldsAndScroll } } = this
+      this.confirmLoading = true
+      validateFieldsAndScroll((errors, values) => {
+        if (errors) {
+          this.confirmLoading = false
+          return
+        }
+        const formData = new FormData()
+        formData.append('file', this.fileList[0])
+        importSpareType(formData)
+          .then((res) => {
+            this.$message.success(res.data)
+            this.handleCancel(values)
+          }).catch(() => {
+            this.confirmLoading = false
+          })
+      })
+    },
+    handleCancel (values) {
+      this.visible = false
+      this.confirmLoading = false
+      this.fileList = []
+      this.form.resetFields()
+      this.$emit('ok', values)
+    }
+  }
+}
+</script>