Browse Source

Merge branch 'master' of http://39.106.8.246:3003/BDTP/adm-frontend

qule 3 years ago
parent
commit
e793d6cb11

+ 3 - 2
package.json

@@ -15,11 +15,12 @@
     "@saga-web/graph": "^2.1.139",
     "font-awesome": "^4.7.0",
     "handsontable-pro": "^3.0.0",
+    "jquery": "^3.3.1",
     "meri-design": "^1.5.515",
     "moment": "^2.29.1",
+    "spark-md5": "^3.0.2",
     "vue-router": "^3.5.3",
-    "vuex": "^3.6.2",
-    "jquery": "^3.3.1"
+    "vuex": "^3.6.2"
   },
   "devDependencies": {
     "@vue/cli-plugin-babel": "~4.5.0",

+ 2 - 2
public/systemConf.js

@@ -6,9 +6,9 @@ var __systemConf = {
   //系统图服务域名
   sysGraphServiceUrl: 'http://develop.ysbdtp.com/adm-diagram',
   //登录服务域名
-  loginServiceUrl: '/loginRequest',
+  loginServiceUrl: 'http://develop.ysbdtp.com/adm-server',
   //文件服务域名
-  fileServiceUrl: 'http://develop.ysbdtp.com/adm-server',
+  fileServiceUrl: 'http://develop.ysbdtp.com/dmp-file',
   // 地图key
   mapKey: 'd42beb96e0e4fb0d49482975abeae1b7',
   //登录相关配置

+ 0 - 1
src/components/systemGraph/index.vue

@@ -60,7 +60,6 @@
 </template>
 <script>
 import { mapState } from "vuex";
-import { logicConfig } from "@/logicConfig";
 import { sysGraphController } from "@/controller/systemGraph/sysGraphController";
 
 export default {

+ 158 - 10
src/utils/http/basic/axiosUtils.ts

@@ -6,6 +6,8 @@
 import axios from "axios";
 import vueStore from "@/store";
 import { logicConfig } from "@/logicConfig";
+import { toolUtils } from "@/utils/toolUtils";
+import SparkMD5 from 'spark-md5';
 
 var CancelToken = axios.CancelToken;
 var cancel;
@@ -35,7 +37,7 @@ axiosservice.interceptors.response.use(
     return res;
   },
   function (err) {
-    console.log("axios interceptors err = ", err);
+    console.error("axios interceptors err = ", err);
     return Promise.reject(err);
   }
 );
@@ -53,12 +55,9 @@ export class axiosUtils {
       var urlPrefix = urlArr[0];
       var urlParamStr = urlArr[1] || "";
 
-      var paramKeyArr = Object.keys(data || {});
-      paramKeyArr.forEach(_key => { 
-        urlParamStr = _key + '=' + data[_key] + '&' + urlParamStr;
-      });
+      var _newParamStr = toolUtils.objectKeyToUrlParam(data);
 
-      var newUrl = urlPrefix + '?' + urlParamStr;
+      var newUrl = urlPrefix + '?' + _newParamStr + '&' + urlParamStr;
 
       let response = await this.customRequest(newUrl, {}, {}, "get");
       return response;
@@ -131,10 +130,159 @@ export class axiosUtils {
     } catch (err) {
       // throw err;
       console.error(err);
-      return {
-        result: logicConfig.resultObj.failure,
-        message: '请求异常'
-      };
+      return toolUtils.resultConstructor(logicConfig.resultObj.failure, null, '请求异常,' + err.message);
     }
   }
+
+
+  /**
+   * 上传文件
+   * @param _paramobj 格式如下:
+   * {
+   *    fileServiceUrl 文件服务地址
+   *    uploadProgressCall 上传进度回调函数,函数参数为object,格式如下:{fileName:'文件名称',uploadedTotal:1},uploadedTotal某个文件总共上传的字节数
+   *    oneUploadedCall 每上传完一个后的回调函数,函数参数为object,格式如下:{fileName:'文件名称',fileId:'文件ID'}
+   *    userId:'不传时,默认会取vuex中user.id',
+   *    files 数组或者object,示例
+   *    { 
+   *      groupCode:'不传时,默认会取vuex中selectProject.groupCode',
+   *      projectId:'不传时,默认会取vuex中selectProject.id',
+   *      fileName:'文件名称',
+   *      fileBucket:'存储空间名称,可以不传',
+   *      file:文件信息,假设有一个input type为file id为txtFile的标签,那么file为document.getElementById('txtFile').files[0]
+   *    }
+   * }
+   * @returns 
+   */
+  protected async uploadFiles(_paramobj: any) {
+    //注意,这里的this 指向的是实例化的子类
+    var _this = this;
+    let userId = _paramobj.userId || vueStore.state.user.id;
+    let fileServiceUrl = _paramobj.fileServiceUrl;
+    let files = _paramobj.files;
+    try {
+      let waitFiles = files instanceof Array == true ? files : [files];
+      //上传成功的文件数量
+      let uploadedCount = 0;
+
+      for (let i = 0; i < waitFiles.length; i++) {
+        let _currFileObj = waitFiles[i];
+
+        //获取文件md5
+        let fileContentMd5 = await getFileContentMd5(_currFileObj);
+        //获取文件上传地址
+        let getUploadResult = await getUploadUrl(fileContentMd5 as string, _currFileObj);
+        switch (getUploadResult.result) {
+          case logicConfig.resultObj.success:
+            let getUploadData = getUploadResult.data || {};
+            //uploadCode 200 代表已经上传过了;    201  代表需上传
+            switch (getUploadData.uploadCode) { 
+              case 201:
+                //获取文件地址上传成功时进行上传
+                let uploadUrl = ((getUploadData.content || [])[0] || {}).uploadUrl;
+                if (!uploadUrl)
+                  return toolUtils.resultConstructor(logicConfig.resultObj.failure, null, '未获取到文件' + _currFileObj.fileName + '的上传地址');
+                //开始上传
+                await upload(uploadUrl, _currFileObj.file, function (progressObj) {
+                  if (typeof _paramobj.uploadProgressCall == 'function') {
+                    let uploadedFileSize = progressObj.loaded / progressObj.total * _currFileObj.file.size;
+                    _paramobj.uploadProgressCall({ uploadedTotal: uploadedFileSize, fileName: _currFileObj.fileName });
+                  }
+                });
+              case 200:
+                ++uploadedCount;
+                if (typeof _paramobj.oneUploadedCall == 'function') {
+                  _paramobj.oneUploadedCall({ fileName: _currFileObj.fileName, fileId: getUploadData.id });
+                }
+                break;
+            }
+            break;
+          default:
+            return toolUtils.resultConstructor(logicConfig.resultObj.failure, null, '获取文件' + _currFileObj.fileName + '的上传地址时出错:' + getUploadResult.message);
+        }
+        if (uploadedCount == waitFiles.length)
+          return toolUtils.resultConstructor(logicConfig.resultObj.success, null, null);
+      }
+    } catch (error) {
+      console.error(error);
+      return toolUtils.resultConstructor(logicConfig.resultObj.failure, null, error.message);
+    }
+
+    //获取文件内容的md5值
+    function getFileContentMd5(_fileObj) {
+      return new Promise((resolve, reject) => {
+        let file = _fileObj.file;
+        let blobSlice = File.prototype.slice;
+        let chunkSize = 2097152;
+        let chunks = Math.ceil(file.size / chunkSize);
+        let currentChunk = 0;
+        let spark = new SparkMD5.ArrayBuffer();
+        let fileReader = new FileReader();
+        fileReader.onload = function (e) {
+          spark.append(e.target.result);                   // Append array buffer
+          currentChunk++;
+          if (currentChunk < chunks) {
+            loadNext();
+          } else {
+            let fileContentMd5 = spark.end();
+            console.info('computed hash', fileContentMd5);  // Compute hash
+            //文件md5获取完成后,调用后台接口获取上传地址
+            // let getUploadResult = await getUploadUrl(fileContentMd5, _fileObj.fileName, file.size);
+            resolve(fileContentMd5);
+          }
+        };
+
+        fileReader.onerror = function (e) {
+          let errStr = '文件:' + _fileObj.fileName + '读取错误:';
+          console.error(e);
+          reject(errStr);
+        };
+
+        function loadNext() {
+          var start = currentChunk * chunkSize,
+            end = ((start + chunkSize) >= file.size) ? file.size : start + chunkSize;
+
+          fileReader.readAsArrayBuffer(blobSlice.call(file, start, end));
+        }
+
+        loadNext();
+      });
+    };
+
+    //获取文件上传地址
+    async function getUploadUrl(fileContentMd5: string, _fileObj: any) {
+      let fileName = _fileObj.fileName;
+      let fileSize = _fileObj.file.size;
+      let projectId = _fileObj.projectId || vueStore.state.selectProject.id;
+      let groupCode = _fileObj.groupCode || vueStore.state.selectProject.groupCode;
+      //应用ID暂时用不上
+      let appId = '';
+
+      let getUploadUrl = toolUtils.getBaseHttpUrl(fileServiceUrl, 'file/initSingleUpload') +
+        '?userId=' + userId + '&projectId=' + projectId + '&groupCode=' + groupCode + '&appId=';
+
+      let paramObj = {
+        fileMd5: fileContentMd5,
+        fileName: fileName,
+        fileBucket: (window as any).__systemConf.baseRouteUrl,
+        fileSize: fileSize
+      };
+      return await _this.customRequest(getUploadUrl, null, paramObj, 'post');
+    };
+
+    //上传
+    async function upload(uploadUrl, file, uploadProgressCall) {
+      return new Promise((resolve, reject) => {
+        var formData = new FormData();
+        formData.append('file', file);
+        axios.put(uploadUrl, formData, {
+          onUploadProgress: uploadProgressCall
+        }).then(function (res) {
+          resolve(res);
+        }).catch(function (error) {
+          reject(error);
+        });
+      });
+    }
+  };
 }

+ 22 - 0
src/utils/http/basic/httpUtils.ts

@@ -62,4 +62,26 @@ export class httpUtils extends axiosUtils {
   ) {
     return await super.customRequest(url, headers, data, method);
   }
+
+  /**
+   * 上传文件
+   * @param _paramobj 格式如下:
+   * {
+   *    uploadProgressCall 上传进度回调函数,函数参数为object,格式如下:{uploadedTotal:1},uploadedTotal总共上传了多少字节,是所有文件上传的字节数总和
+   *    oneUploadedCall 每上传完一个后的回调函数,函数参数为object,格式如下:{fileName:'文件名称'}
+   *    userId:'不传时,默认会取vuex中user.id',
+   *    files 数组或者object,示例
+   *    { 
+   *      groupCode:'不传时,默认会取vuex中selectProject.groupCode',
+   *      projectId:'不传时,默认会取vuex中selectProject.id',
+   *      fileName:'文件名称',
+   *      fileBucket:'存储空间名称,可以不传',
+   *      file:文件信息,假设有一个input type为file id为txtFile的标签,那么file为document.getElementById('txtFile').files[0]
+   *    }
+   * }
+   */
+  public async uploadFiles(_paramobj: any) {
+    _paramobj.fileServiceUrl = this.baseUrl;
+    return await super.uploadFiles(_paramobj);
+  }
 }

+ 12 - 0
src/utils/http/fileHttpUtils.ts

@@ -0,0 +1,12 @@
+/**
+ * 文件访问的http辅助类,供业务调用
+ * nh 2022.01.18
+ */
+
+import { httpUtils } from "./basic/httpUtils";
+
+export class fileHttpUtils extends httpUtils {
+    constructor() {
+        super((window as any).__systemConf.fileServiceUrl);
+    };
+}

+ 26 - 0
src/utils/toolUtils.ts

@@ -74,4 +74,30 @@ export class toolUtils {
     }
     return newData;
   };
+
+  /**
+   * 把object对象中的属性转为url中的参数字符串。比如:{a:1,b:2}转为a=1&b=2
+   */
+  static objectKeyToUrlParam(_obj: any) {
+    var paramStr = '';
+    var keyArr = Object.keys(_obj || {});
+    keyArr.forEach((_key, _index) => {
+      paramStr = paramStr + _key + '=' + _obj[_key] + (_index == keyArr.length - 1 ? '' : '&');
+    });
+    return paramStr;
+  };
+
+  /**
+   * 拼装返回给页面的接口调用结果
+   * resultStr 结果字符串,成功时为success,否则为失败码
+   * data 数据
+   * reason 失败时的原因
+   */
+  static resultConstructor(resultStr, data, reason) {
+    return {
+      result: resultStr,
+      data: data,
+      message: reason
+    };
+  };
 }