Sfoglia il codice sorgente

全局通用下载功能

sunlupeng 1 anno fa
parent
commit
de4524097b

+ 2 - 2
.env.dev

@@ -6,11 +6,11 @@ VUE_APP_TITLE = 爱思系统
 
 # 爱思系统/开发环境
 # 赵培清
-# VUE_APP_BASE_API = 'http://192.168.100.213:48080'
+VUE_APP_BASE_API = 'http://192.168.100.213:48080'
 # 王东坡
 # VUE_APP_BASE_API = 'http://192.168.100.64:48081'
 # 测试
-VUE_APP_BASE_API = 'http://47.103.79.143:48081'
+# VUE_APP_BASE_API = 'http://47.103.79.143:48081'
 
 # 路由懒加载
 VUE_CLI_BABEL_TRANSPILE_MODULES = true

+ 2 - 0
src/main.js

@@ -10,6 +10,7 @@ import store from './store'
 import router from './router'
 import directive from './directive' // directive
 import plugins from './plugins' // plugins
+import { download } from '@/utils/request'
 
 import './assets/icons' // icon
 import './permission' // permission control
@@ -37,6 +38,7 @@ Vue.prototype.DICT_TYPE = DICT_TYPE
 Vue.prototype.handleTree = handleTree
 Vue.prototype.addBeginAndEndTime = addBeginAndEndTime
 Vue.prototype.divide = divide
+Vue.prototype.download = download
 
 // 全局组件挂载
 Vue.component('DictTag', DictTag)

+ 31 - 1
src/utils/request.js

@@ -1,10 +1,13 @@
 import axios from 'axios'
-import {Message, MessageBox, Notification} from 'element-ui'
+import {Message, MessageBox, Notification, Loading} from 'element-ui'
 import store from '@/store'
 import {getAccessToken, getRefreshToken, getTenantId, setToken} from '@/utils/auth'
 import errorCode from '@/utils/errorCode'
 import {getPath, getTenantEnable} from "@/utils/ruoyi";
 import {refreshToken} from "@/api/login";
+import { tansParams, blobValidate } from "@/utils/ruoyi";
+import { saveAs } from 'file-saver'
+let downloadLoadingInstance;
 
 // 需要忽略的提示。忽略后,自动 Promise.reject('error')
 const ignoreMsgs = [
@@ -208,5 +211,32 @@ function handleAuthorized() {
   }
   return Promise.reject('无效的会话,或者会话已过期,请重新登录。')
 }
+// 通用下载方法
+export function download(url, params, filename, config) {
+  downloadLoadingInstance = Loading.service({ text: "正在下载数据,请稍候", spinner: "el-icon-loading", background: "rgba(0, 0, 0, 0.7)", })
+  return service.post(url, params, {
+    transformRequest: [(params) => { return tansParams(params) }],
+    headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
+    responseType: 'blob',
+    ...config
+  }).then(async (data) => {
+    const isBlob = blobValidate(data);
+    if (isBlob) {
+      const blob = new Blob([data])
+      saveAs(blob, filename)
+    } else {
+      const resText = await data.text();
+      const rspObj = JSON.parse(resText);
+      const errMsg = errorCode[rspObj.code] || rspObj.msg || errorCode['default']
+      Message.error(errMsg);
+    }
+    downloadLoadingInstance.close();
+  }).catch((r) => {
+    console.error(r)
+    Message.error('下载文件出现错误,请联系管理员!')
+    downloadLoadingInstance.close();
+  })
+}
+
 
 export default service

+ 32 - 0
src/utils/ruoyi.js

@@ -251,3 +251,35 @@ export function getPath(path) {
   }
   return Math.floor(divisor/dividend*100)/100;
 }
+
+
+/**
+* 参数处理
+* @param {*} params  参数
+*/
+export function tansParams(params) {
+  let result = ''
+  for (const propName of Object.keys(params)) {
+    const value = params[propName];
+    var part = encodeURIComponent(propName) + "=";
+    if (value !== null && value !== "" && typeof (value) !== "undefined") {
+      if (typeof value === 'object') {
+        for (const key of Object.keys(value)) {
+          if (value[key] !== null && value[key] !== "" && typeof (value[key]) !== 'undefined') {
+            let params = propName + '[' + key + ']';
+            var subPart = encodeURIComponent(params) + "=";
+            result += subPart + encodeURIComponent(value[key]) + "&";
+          }
+        }
+      } else {
+        result += part + encodeURIComponent(value) + "&";
+      }
+    }
+  }
+  return result
+}
+
+// 验证是否为blob格式
+export function blobValidate(data) {
+  return data.type !== 'application/json'
+}

+ 91 - 28
src/views/personnel/attendance/info/index.vue

@@ -35,6 +35,10 @@
         <el-button type="primary" plain icon="el-icon-plus" size="mini" @click="handleAdd"
           v-hasPermi="['attendance:info:create']">新增</el-button>
       </el-col>
+      <el-col :span="1.5">
+        <el-button type="info" plain icon="el-icon-upload2" size="mini" @click="handleImport"
+          v-hasPermi="['attendance:info:import']">导入</el-button>
+      </el-col>
       <el-col :span="1.5">
         <el-button type="warning" icon="el-icon-download" size="mini" @click="handleExport" :loading="exportLoading"
           v-hasPermi="['attendance:info:export']">导出</el-button>
@@ -103,29 +107,17 @@
           </el-col>
           <el-col :span="24">
             <el-form-item label="上班打卡" prop="workStartTime">
-              <el-time-picker
-                v-model="form.workStartTime"
-                value-format="HH:mm"
-                format="HH:mm"
-                :picker-options="{
-                  selectableRange: '00:00:00 - 23:59:59'
-                }"
-                style="width: 100%;"
-                placeholder="上班时间">
+              <el-time-picker v-model="form.workStartTime" value-format="HH:mm" format="HH:mm" :picker-options="{
+                selectableRange: '00:00:00 - 23:59:59'
+              }" style="width: 100%;" placeholder="上班时间">
               </el-time-picker>
             </el-form-item>
           </el-col>
           <el-col :span="24">
             <el-form-item label="下班打卡" prop="workEndTime">
-              <el-time-picker
-                v-model="form.workEndTime"
-                value-format="HH:mm"
-                format="HH:mm"
-                :picker-options="{
-                  selectableRange: '00:00:00 - 23:59:59'
-                }"
-                style="width: 100%;"
-                placeholder="下班时间">
+              <el-time-picker v-model="form.workEndTime" value-format="HH:mm" format="HH:mm" :picker-options="{
+                selectableRange: '00:00:00 - 23:59:59'
+              }" style="width: 100%;" placeholder="下班时间">
               </el-time-picker>
             </el-form-item>
           </el-col>
@@ -197,6 +189,35 @@
           </div>
         </div>
       </div>
+    </el-dialog>
+     <!-- 导入对话框 -->
+     <el-dialog :title="upload.title" :visible.sync="upload.open" width="400px" append-to-body>
+      <el-upload
+        ref="upload"
+        :limit="1"
+        accept=".xlsx, .xls"
+        :headers="upload.headers"
+        :action="upload.url + '?updateSupport=' + upload.updateSupport"
+        :disabled="upload.isUploading"
+        :on-progress="handleFileUploadProgress"
+        :on-success="handleFileSuccess"
+        :auto-upload="false"
+        drag
+      >
+        <i class="el-icon-upload"></i>
+        <div class="el-upload__text">将文件拖到此处,或<em>点击上传</em></div>
+        <div class="el-upload__tip text-center" slot="tip">
+          <div class="el-upload__tip" slot="tip">
+            <el-checkbox v-model="upload.updateSupport" /> 是否更新已经存在的数据
+          </div>
+          <span>仅允许导入xls、xlsx格式文件。</span>
+          <el-link type="primary" :underline="false" style="font-size:12px;vertical-align: baseline;" @click="importTemplate">下载模板</el-link>
+        </div>
+      </el-upload>
+      <div slot="footer" class="dialog-footer">
+        <el-button type="primary" @click="submitFileForm">确 定</el-button>
+        <el-button @click="upload.open = false">取 消</el-button>
+      </div>
     </el-dialog>
     <PeopleSelect ref="peopleSelect" type="single" :isCheck="true" :open="singlePeopleOpen"
       @cancel="singlePeopleOpen = false" @submit="submitSingle"></PeopleSelect>
@@ -211,6 +232,7 @@ import PeopleSelect from "@/components/PeopleSelect/index.vue";
 import Treeselect from "@riophae/vue-treeselect";
 import "@riophae/vue-treeselect/dist/vue-treeselect.css";
 import { listDept } from "@/api/system/dept";
+import { getBaseHeader } from "@/utils/request";
 export default {
   name: "SystemDictType",
   components: {
@@ -238,6 +260,21 @@ export default {
       singlePeopleOpen: false,
       open: false,
       openDetail: false,
+      // 导入参数
+      upload: {
+        // 是否显示弹出层(导入)
+        open: false,
+        // 弹出层标题(导入)
+        title: "",
+        // 是否禁用上传
+        isUploading: false,
+        // 是否更新已经存在的数据
+        updateSupport: 0,
+        // 设置上传的请求头部
+        headers: getBaseHeader(),
+        // 上传的地址
+        url: process.env.VUE_APP_BASE_API + '/admin-api/personnel/attendance/info/import-excel'
+      },
       // 查询参数
       queryParams: {
         pageNo: 1,
@@ -333,17 +370,17 @@ export default {
     // 表单重置
     reset() {
       this.files = [],
-      this.form = {
-        employeeName: undefined,
-        employeeId: undefined,
-        deptName: undefined,
-        position: undefined,
-        employeeMobile: undefined,
-        attendanceDate: undefined,
+        this.form = {
+          employeeName: undefined,
+          employeeId: undefined,
+          deptName: undefined,
+          position: undefined,
+          employeeMobile: undefined,
+          attendanceDate: undefined,
 
-        workStartTime: undefined,
-        workEndTime: undefined,
-      };
+          workStartTime: undefined,
+          workEndTime: undefined,
+        };
       this.resetForm("form");
     },
     /** 搜索按钮操作 */
@@ -427,6 +464,32 @@ export default {
         this.$download.excel(response, '员工考勤信息.xls');
         this.exportLoading = false;
       }).catch(() => { });
+    },
+     /** 导入按钮操作 */
+     handleImport() {
+      this.upload.title = "导入";
+      this.upload.open = true;
+    },
+    /** 下载模板操作 */
+    importTemplate() {
+      this.download('personnel/attendance/info/get-import-template', {
+      }, `template_${new Date().getTime()}.xlsx`)
+    },
+    // 文件上传中处理
+    handleFileUploadProgress(event, file, fileList) {
+      this.upload.isUploading = true;
+    },
+    // 文件上传成功处理
+    handleFileSuccess(response, file, fileList) {
+      this.upload.open = false;
+      this.upload.isUploading = false;
+      this.$refs.upload.clearFiles();
+      this.$alert("<div style='overflow: auto;overflow-x: hidden;max-height: 70vh;padding: 10px 20px 0;'>" + response.msg + "</div>", "导入结果", { dangerouslyUseHTMLString: true });
+      this.getList();
+    },
+    // 提交上传文件
+    submitFileForm() {
+      this.$refs.upload.submit();
     }
   }
 };

+ 1 - 1
src/views/personnel/attendance/leave/index.vue

@@ -109,7 +109,7 @@
         <el-row>
           <el-col :span="24">
             <el-form-item label="请假人" prop="employeeName">
-              <el-input v-model="form.employeeName" placeholder='点击选择' readonly @click.native="openSingle"></el-input>
+              <el-input v-model="form.employeeName" placeholder='点击选择' :disabled="title=='修改'?true:false" readonly @click.native="openSingle"></el-input>
             </el-form-item>
           </el-col>
           <el-col :span="24" style="display: none;">

+ 1 - 1
src/views/personnel/employee/index.vue

@@ -178,7 +178,7 @@
           </el-col>
           <el-col :span="12">
             <el-form-item label="剩余年假" prop="remainingAnnualLeave">
-              <el-input v-model="form.remainingAnnualLeave" placeholder="剩余年假天数" />
+              <el-input v-model="form.remainingAnnualLeave" disabled placeholder="剩余年假天数" />
             </el-form-item>
           </el-col>
           <el-col :span="12">