cyy 7 miesięcy temu
rodzic
commit
04308acecd

+ 6 - 4
public/config.js

@@ -1,8 +1,8 @@
 (function (global) {
-     // 是否启用动态API,启用后,将根据访问IP的origin获取API地址
-    const ENABLE_DYNAMIC_API = true
-    const HOST_URL = `${location.origin}${location.pathname}`
-    const BASE_URL = ENABLE_DYNAMIC_API ? HOST_URL : 'http://192.168.2.209/'
+    // 是否启用动态API,启用后,将根据访问IP的origin获取API地址
+    const ENABLE_DYNAMIC_API = true;
+    const HOST_URL = `${location.origin}${location.pathname}`;
+    const BASE_URL = ENABLE_DYNAMIC_API ? HOST_URL : "http://192.168.2.209/";
     //const BASE_URL = "http://192.168.2.209/";
     global.__IBPS_CONFIG__ = {
         // 是否启用配置
@@ -97,5 +97,7 @@
         SYSTEM_NAME: "金通检测/校准实验室质量管理系统(LQMS-基础版)",
         // 润乾报表根目录
         REPORT_PATH: "17025实验室质量管理系统",
+        // 是否加密 GET 请求参数
+        ENCRYPT_GET_PARAMS: false,
     };
 })(window);

+ 307 - 291
src/api/oauth2/oauth2.js

@@ -1,4 +1,3 @@
-
 /**
  * OAUTH2 授权
  *   登录,用户授权
@@ -9,35 +8,33 @@
  * 版权:广州流辰信息技术有限公司
  * </pre>
  */
-import { OAUTH2_URL } from '@/api/baseUrl'
-import request from '@/utils/request'
-import requestState from '@/constants/state'
-import {
-  Message
-} from 'element-ui'
+import { OAUTH2_URL } from "@/api/baseUrl";
+import request from "@/utils/request";
+import requestState from "@/constants/state";
+import { Message } from "element-ui";
 
-import qs from 'qs'
+import qs from "qs";
 
-var AccessToken = function(data) {
-  if (!(this instanceof AccessToken)) {
-    return new AccessToken(data)
-  }
-  this.data = data
-}
+var AccessToken = function (data) {
+    if (!(this instanceof AccessToken)) {
+        return new AccessToken(data);
+    }
+    this.data = data;
+};
 /**
  * 对返回结果的一层封装,如果遇见IBPS平台返回的错误,将返回一个错误
  * 参见:IBPS返回码说明
  */
-var wrapper = function(callback) {
-  return function(err, data, res) {
-    callback = callback || function() {}
-    if (err) {
-      err.name = 'IBPSAPI' + err.name
-      return callback(err, data, res)
-    }
-    callback(null, data, res)
-  }
-}
+var wrapper = function (callback) {
+    return function (err, data, res) {
+        callback = callback || function () {};
+        if (err) {
+            err.name = "IBPSAPI" + err.name;
+            return callback(err, data, res);
+        }
+        callback(null, data, res);
+    };
+};
 
 /*!
  * 检查AccessToken是否有效,检查规则为当前时间和过期时间进行对比
@@ -47,30 +44,33 @@ var wrapper = function(callback) {
  * token.isValid();
  * ```
  */
-AccessToken.prototype.isValid = function() {
-  return !!this.data.access_token && (new Date().getTime()) < (this.data.create_at + this.data.expires_in * 1000)
-}
+AccessToken.prototype.isValid = function () {
+    return (
+        !!this.data.access_token &&
+        new Date().getTime() < this.data.create_at + this.data.expires_in * 1000
+    );
+};
 
 /*!
  * 处理token,更新过期时间
  */
-var processToken = function(that, callback) {
-  var createAt = new Date().getTime()
+var processToken = function (that, callback) {
+    var createAt = new Date().getTime();
 
-  return function(err, data, res) {
-    if (err) {
-      return callback(err, data, res)
-    }
-    data.create_at = createAt
-    if (res.variables && res.variables.licJson) {
-      data.licJson = JSON.parse(res.variables.licJson)
-  }
-    // 存储token
-    that.saveToken(data.uid, data, function(err) {
-      callback(err, new AccessToken(data))
-    })
-  }
-}
+    return function (err, data, res) {
+        if (err) {
+            return callback(err, data, res);
+        }
+        data.create_at = createAt;
+        if (res.variables && res.variables.licJson) {
+            data.licJson = JSON.parse(res.variables.licJson);
+        }
+        // 存储token
+        that.saveToken(data.uid, data, function (err) {
+            callback(err, new AccessToken(data));
+        });
+    };
+};
 
 /**
  * 根据clientId和clientSecret创建OAuth接口的构造函数
@@ -90,25 +90,31 @@ var processToken = function(that, callback) {
  * @param {Function} getToken 用于获取token的方法
  * @param {Function} saveToken 用于保存token的方法
  */
-var OAuth = function(clientId, clientSecret, getToken, saveToken) {
-  this.clientId = clientId
-  this.clientSecret = clientSecret
-  this.statistic =''
-  this.username = ''
-  // token的获取和存储
-  this.store = {}
-  this.getToken = getToken || function(uid, callback) {
-    callback(null, this.store[uid])
-  }
-  if (!saveToken && process.env.NODE_ENV === 'production') {
-    console.warn('Please dont save oauth token into memory under production')
-  }
-  this.saveToken = saveToken || function(uid, token, callback) {
-    this.store[uid] = token
-    callback(null)
-  }
-  this.defaults = {}
-}
+var OAuth = function (clientId, clientSecret, getToken, saveToken) {
+    this.clientId = clientId;
+    this.clientSecret = clientSecret;
+    this.statistic = "";
+    this.username = "";
+    // token的获取和存储
+    this.store = {};
+    this.getToken =
+        getToken ||
+        function (uid, callback) {
+            callback(null, this.store[uid]);
+        };
+    if (!saveToken && process.env.NODE_ENV === "production") {
+        console.warn(
+            "Please dont save oauth token into memory under production"
+        );
+    }
+    this.saveToken =
+        saveToken ||
+        function (uid, token, callback) {
+            this.store[uid] = token;
+            callback(null);
+        };
+    this.defaults = {};
+};
 
 /*!
  * request的封装
@@ -117,39 +123,43 @@ var OAuth = function(clientId, clientSecret, getToken, saveToken) {
  * @param {Object} opts urllib选项
  * @param {Function} callback 回调函数
  */
-OAuth.prototype.request = function(opts, callback) {
-  const options = {}
-  Object.assign(options, this.defaults)
-  if (typeof opts === 'function') {
-    callback = opts
-    opts = {}
-  }
-  for (const key in opts) {
-    if (key !== 'headers') {
-      options[key] = opts[key]
-    } else {
-      if (opts.headers) {
-        options.headers = options.headers || {}
-        Object.assign(options.headers, opts.headers)
-      }
+OAuth.prototype.request = function (opts, callback) {
+    const options = {};
+    Object.assign(options, this.defaults);
+    if (typeof opts === "function") {
+        callback = opts;
+        opts = {};
     }
-  }
-
-  request(options).then(response => {
-    const { state } = response
-    if (state === requestState.UNSUPORT ||
-      state === requestState.WARNING) {
-      const err = new Error(response.message)
-      err.state = state
-      err.cause = response.cause
-      callback(err)
-    } else {
-      callback(null, response.data, response)
+    for (const key in opts) {
+        if (key !== "headers") {
+            options[key] = opts[key];
+        } else {
+            if (opts.headers) {
+                options.headers = options.headers || {};
+                Object.assign(options.headers, opts.headers);
+            }
+        }
     }
-  }).catch(error => {
-    callback(error)
-  })
-}
+
+    request(options)
+        .then((response) => {
+            const { state } = response;
+            if (
+                state === requestState.UNSUPORT ||
+                state === requestState.WARNING
+            ) {
+                const err = new Error(response.message);
+                err.state = state;
+                err.cause = response.cause;
+                callback(err);
+            } else {
+                callback(null, response.data, response);
+            }
+        })
+        .catch((error) => {
+            callback(error);
+        });
+};
 
 /**
  * 获取授权页面的URL地址
@@ -157,18 +167,18 @@ OAuth.prototype.request = function(opts, callback) {
  * @param {String} state 开发者可提供的数据
  * @param {String} scope 作用范围,值为snsapi_userinfo和snsapi_base,前者用于弹出,后者用于跳转
  */
-OAuth.prototype.getAuthorizeURL = function(redirect, state, scope) {
-  const url = OAUTH2_URL() + ''
-  const info = {
-    clientId: this.clientId,
-    redirect_uri: redirect,
-    response_type: 'code',
-    scope: scope || 'snsapi_base',
-    state: state || ''
-  }
+OAuth.prototype.getAuthorizeURL = function (redirect, state, scope) {
+    const url = OAUTH2_URL() + "";
+    const info = {
+        clientId: this.clientId,
+        redirect_uri: redirect,
+        response_type: "code",
+        scope: scope || "snsapi_base",
+        state: state || "",
+    };
 
-  return url + '?' + qs.stringify(info) + '#ibps_redirect'
-}
+    return url + "?" + qs.stringify(info) + "#ibps_redirect";
+};
 
 /**
  * 获取授权页面的URL地址
@@ -176,18 +186,18 @@ OAuth.prototype.getAuthorizeURL = function(redirect, state, scope) {
  * @param {String} state 开发者可提供的数据
  * @param {String} scope 作用范围,值为snsapi_login,前者用于弹出,后者用于跳转
  */
-OAuth.prototype.getAuthorizeURLForWebsite = function(redirect, state, scope) {
-  const url = OAUTH2_URL() + '/qrconnect'
-  const info = {
-    clientId: this.clientId,
-    redirect_uri: redirect,
-    response_type: 'code',
-    scope: scope || 'snsapi_login',
-    state: state || ''
-  }
+OAuth.prototype.getAuthorizeURLForWebsite = function (redirect, state, scope) {
+    const url = OAUTH2_URL() + "/qrconnect";
+    const info = {
+        clientId: this.clientId,
+        redirect_uri: redirect,
+        response_type: "code",
+        scope: scope || "snsapi_login",
+        state: state || "",
+    };
 
-  return url + '?' + qs.stringify(info) + '#ibps_redirect'
-}
+    return url + "?" + qs.stringify(info) + "#ibps_redirect";
+};
 
 /**
  * 根据授权获取到的code,换取access_token和uid
@@ -216,21 +226,21 @@ OAuth.prototype.getAuthorizeURLForWebsite = function(redirect, state, scope) {
  * @param {String} code 授权获取到的code
  * @param {Function} callback 回调函数
  */
-OAuth.prototype.getAccessTokenByCode = function(code, callback) {
-  localStorage.setItem('username', this.username)
-  const args = {
-    url: OAUTH2_URL() + '/authentication/apply',
-    data: {
-      client_id: this.clientId,
-      client_secret: this.clientSecret,
-      authorize_code: code,
-      username: this.username,
-      grant_type: 'authorization_code'
-    },
-    method: 'post'
-  }
-  this.request(args, wrapper(processToken(this, callback)))
-}
+OAuth.prototype.getAccessTokenByCode = function (code, callback) {
+    localStorage.setItem("username", this.username);
+    const args = {
+        url: OAUTH2_URL() + "/authentication/apply",
+        data: {
+            client_id: this.clientId,
+            client_secret: this.clientSecret,
+            authorize_code: code,
+            username: this.username,
+            grant_type: "authorization_code",
+        },
+        method: "post",
+    };
+    this.request(args, wrapper(processToken(this, callback)));
+};
 /**
  * 密码授权模式
  * 根据用户名和密码,换取access token和uid
@@ -261,20 +271,23 @@ OAuth.prototype.getAccessTokenByCode = function(code, callback) {
  * @param {String} password  密码
  * @param {Function} callback 回调函数
  */
-OAuth.prototype.getAccessTokenByPassword = function({ username, password }, callback) {
-  const args = {
-    url: OAUTH2_URL() + '/authentication/apply',
-    data: {
-      client_id: this.clientId,
-      client_secret: this.clientSecret,
-      username: username,
-      password: password,
-      grant_type: 'password_credentials'
-    },
-    method: 'post'
-  }
-  this.request(args, wrapper(processToken(this, callback)))
-}
+OAuth.prototype.getAccessTokenByPassword = function (
+    { username, password },
+    callback
+) {
+    const args = {
+        url: OAUTH2_URL() + "/authentication/apply",
+        data: {
+            client_id: this.clientId,
+            client_secret: this.clientSecret,
+            username: username,
+            password: password,
+            grant_type: "password_credentials",
+        },
+        method: "post",
+    };
+    this.request(args, wrapper(processToken(this, callback)));
+};
 
 /**
  * 根据refresh token,刷新access token,调用getAccessTokenByCode后才有效
@@ -302,39 +315,38 @@ OAuth.prototype.getAccessTokenByPassword = function({ username, password }, call
  * @param {String} refreshToken 刷新tonken
  * @param {Function} callback 回调函数
  */
-OAuth.prototype.refreshAccessToken = function(refreshToken, callback) {
-  const username = localStorage.getItem('username')
-  const args = {
-    url: OAUTH2_URL() + '/authentication/apply',
-    data: {
-      client_id: this.clientId,
-      client_secret: this.clientSecret,
-      grant_type: 'refresh_token',
-      username,
-      refresh_token: refreshToken
-    },
-    method: 'post'
-
-  }
-  this.request(args, wrapper(processToken(this, callback)))
-}
+OAuth.prototype.refreshAccessToken = function (refreshToken, callback) {
+    const username = localStorage.getItem("username");
+    const args = {
+        url: OAUTH2_URL() + "/authentication/apply",
+        data: {
+            client_id: this.clientId,
+            client_secret: this.clientSecret,
+            grant_type: "refresh_token",
+            username,
+            refresh_token: refreshToken,
+        },
+        method: "post",
+    };
+    this.request(args, wrapper(processToken(this, callback)));
+};
 /**
  * 获取用户信息 【私有方法】
  * @param {*} options
  * @param {*} accessToken
  * @param {*} callback
  */
-OAuth.prototype._getUser = function(options, accessToken, callback) {
-  const args = {
-    url: OAUTH2_URL() + '/user/context',
-    data: {
-      access_token: accessToken,
-      uid: options.uid,
-      lang: options.lang || 'zh_CN'
-    }
-  }
-  this.request(args, wrapper(callback))
-}
+OAuth.prototype._getUser = function (options, accessToken, callback) {
+    const args = {
+        url: OAUTH2_URL() + "/user/context",
+        data: {
+            access_token: accessToken,
+            uid: options.uid,
+            lang: options.lang || "zh_CN",
+        },
+    };
+    this.request(args, wrapper(callback));
+};
 
 /**
  * 根据uid,获取用户信息。
@@ -377,44 +389,48 @@ OAuth.prototype._getUser = function(options, accessToken, callback) {
  * @param {Object|String} options 传入uid或者参见Options
  * @param {Function} callback 回调函数
  */
-OAuth.prototype.getUser = function(options, callback) {
-  if (typeof options !== 'object') {
-    options = {
-      uid: options
+OAuth.prototype.getUser = function (options, callback) {
+    if (typeof options !== "object") {
+        options = {
+            uid: options,
+        };
     }
-  }
-  const that = this
-  this.getToken(options.uid, function(err, data) {
-    if (err) {
-      return callback(err)
-    }
-    // 没有token数据
-    if (!data) {
-      const message = 'No token for ' + options.uid + ', please authorize first.'
-      Message({
-        message: `${message}`,
-        type: 'error',
-        showClose: true,
-        dangerouslyUseHTMLString: true,
-        duration: 5 * 1000
-      })
-      const error = new Error(message)
-      err.state = 'NoOAuthTokenError'
-      return callback(error)
-    }
-    const token = new AccessToken(data)
-    if (token.isValid()) {
-      that._getUser(options, token.data.access_token, callback)
-    } else {
-      that.refreshAccessToken(token.data.refresh_token, function(err, token) {
+    const that = this;
+    this.getToken(options.uid, function (err, data) {
         if (err) {
-          return callback(err)
+            return callback(err);
         }
-        that._getUser(options, token.data.access_token, callback)
-      })
-    }
-  })
-}
+        // 没有token数据
+        if (!data) {
+            const message =
+                "No token for " + options.uid + ", please authorize first.";
+            Message({
+                message: `${message}`,
+                type: "error",
+                showClose: true,
+                dangerouslyUseHTMLString: true,
+                duration: 5 * 1000,
+            });
+            const error = new Error(message);
+            err.state = "NoOAuthTokenError";
+            return callback(error);
+        }
+        const token = new AccessToken(data);
+        if (token.isValid()) {
+            that._getUser(options, token.data.access_token, callback);
+        } else {
+            that.refreshAccessToken(
+                token.data.refresh_token,
+                function (err, token) {
+                    if (err) {
+                        return callback(err);
+                    }
+                    that._getUser(options, token.data.access_token, callback);
+                }
+            );
+        }
+    });
+};
 
 /**
  * 检验授权凭证(access_token)是否有效。
@@ -426,17 +442,17 @@ OAuth.prototype.getUser = function(options, callback) {
  * @param {String} accessToken 待校验的access token
  * @param {Function} callback 回调函数
  */
-OAuth.prototype.verifyToken = function(uid, accessToken, callback) {
-  const args = {
-    url: OAUTH2_URL() + '/authentication/verify',
-    params: {
-      access_token: accessToken,
-      uid: uid
-    },
-    method: 'post'
-  }
-  this.request(args, wrapper(callback))
-}
+OAuth.prototype.verifyToken = function (uid, accessToken, callback) {
+    const args = {
+        url: OAUTH2_URL() + "/authentication/verify",
+        params: {
+            access_token: accessToken,
+            uid: uid,
+        },
+        method: "post",
+    };
+    this.request(args, wrapper(callback));
+};
 
 /**
  * 用户名、密码方式登录。
@@ -449,14 +465,14 @@ OAuth.prototype.verifyToken = function(uid, accessToken, callback) {
  *     password : 密码
  * @param {Function} callback 回调函数
  */
-OAuth.prototype.userLogin = function(data, callback) {
-  const args = {
-    url: OAUTH2_URL() + '/user/login/apply',
-    data: data,
-    method: 'post'
-  }
-  this.request(args, wrapper(callback))
-}
+OAuth.prototype.userLogin = function (data, callback) {
+    const args = {
+        url: OAUTH2_URL() + "/user/login/apply",
+        data: data,
+        method: "post",
+    };
+    this.request(args, wrapper(callback));
+};
 
 /**
  *
@@ -468,22 +484,22 @@ OAuth.prototype.userLogin = function(data, callback) {
  * @param {Objcct} options
  * @param {Function} callback 回调函数
  */
-OAuth.prototype.authorize = function(data, callback) {
-  const url = OAUTH2_URL() + '/authorize/apply'
-  if (typeof data !== 'object') {
-    data = {
-      login_state: data
+OAuth.prototype.authorize = function (data, callback) {
+    const url = OAUTH2_URL() + "/authorize/apply";
+    if (typeof data !== "object") {
+        data = {
+            login_state: data,
+        };
     }
-  }
-  data.client_id = this.clientId
+    data.client_id = this.clientId;
 
-  const args = {
-    url,
-    data: data,
-    method: 'post'
-  }
-  this.request(args, wrapper(callback))
-}
+    const args = {
+        url,
+        data: data,
+        method: "post",
+    };
+    this.request(args, wrapper(callback));
+};
 
 /**
  * 根据code,获取用户信息。
@@ -515,65 +531,65 @@ OAuth.prototype.authorize = function(data, callback) {
  * @param {Object|String} options 授权获取到的code
  * @param {Function} callback 回调函数
  */
-OAuth.prototype.getUserByCode = function(options, callback) {
-  const that = this
+OAuth.prototype.getUserByCode = function (options, callback) {
+    const that = this;
 
-  let lang
-  let code
-  if (typeof options === 'string') {
-    code = options
-  } else {
-    lang = options.lang
-    code = options.code
-  }
-
-  this.getAccessTokenByCode(code, function(err, result) {
-    if (err) {
-      return callback(err)
+    let lang;
+    let code;
+    if (typeof options === "string") {
+        code = options;
+    } else {
+        lang = options.lang;
+        code = options.code;
     }
-    const uid = result.data.uid
-    that.getUser({ uid: uid, lang: lang }, callback)
-  })
-}
+
+    this.getAccessTokenByCode(code, function (err, result) {
+        if (err) {
+            return callback(err);
+        }
+        const uid = result.data.uid;
+        that.getUser({ uid: uid, lang: lang }, callback);
+    });
+};
 
 /**
  * 通过登录获取access_token
  * @param {*} options
  * @param {*} callback
  */
-OAuth.prototype.getLoginCode = function(options, callback) {
-  this.username = options.username
-  const that = this
-  /**
-   * 用户登录
-   */
-  this.userLogin(options, function(err, data,res) {
-    if (err) {
-      return callback(err)
-    }
-    that.statistic = res.variables.statistic //判斷是否有统计权限
-    // 没有token数据
-    if (!data) {
-      const message = '没有传回用户信息'
-      Message({
-        message: `${message}`,
-        type: 'error',
-        showClose: true,
-        dangerouslyUseHTMLString: true,
-        duration: 5 * 1000
-      })
-      const error = new Error(message)
-      err.state = 'NoOAuthTokenError'
-      return callback(error)
-    }
+OAuth.prototype.getLoginCode = function (options, callback) {
+    this.username = options.username;
+    const that = this;
+    /**
+     * 用户登录
+     */
+    this.userLogin(options, function (err, data, res) {
+        if (err) {
+            return callback(err);
+        }
+        that.statistic = res.variables.statistic; //判斷是否有统计权限
+        // 没有token数据
+        if (!data) {
+            const message = "没有传回用户信息";
+            Message({
+                message: `${message}`,
+                type: "error",
+                showClose: true,
+                dangerouslyUseHTMLString: true,
+                duration: 5 * 1000,
+            });
+            const error = new Error(message);
+            err.state = "NoOAuthTokenError";
+            return callback(error);
+        }
 
-    that.authorize(data, function(err1, data1) {
-      if (err1) {
-        return callback(err1)
-      }
-      that.getAccessTokenByCode(data1, callback)
-    })
-  })
-}
+        that.authorize(data, function (err1, data1) {
+            if (err1) {
+                return callback(err1);
+            }
+            that.getAccessTokenByCode(data1, callback);
+        });
+    });
+};
 
-export default OAuth
+export default OAuth;

+ 88 - 63
src/business/platform/form/utils/custom/joinCURD.js

@@ -1,83 +1,108 @@
-import request from '@/utils/request'
-import md5 from 'js-md5'
-import { requestType, requestPath } from './requestType'
-import { mapValues } from 'lodash'
-import { encryptByAes } from '@/utils/encrypt'
-import { SHOW_PLAINTEXT } from '@/constant'
+import request from "@/utils/request";
+import md5 from "js-md5";
+import { requestType, requestPath, normal } from "./requestType";
+import { mapValues } from "lodash";
+import { encryptByAes } from "@/utils/encrypt";
+import { SHOW_PLAINTEXT } from "@/constant";
+import { getToken } from "@/utils/auth";
 
-// 请求方式默认POST
-const post = (method, data, type = 'post', loading = false) => {
-    const path = requestType[method]
-    let requestData = ''
-    let requestParams = null
-    // 部分接口保留参数,用于后续接口传参
-    const retainData = null
+const BASE_URL = "business/v3/sys/universal/";
+const DEFAULT_METHOD = "post";
+const DEFAULT_LOADING = false;
 
-    if (type === 'get') {
-        requestParams = data
-    } else { // 对象转字符串
-        requestData = dealData(method, data)
-    }
+const post = (
+    type,
+    data,
+    method = DEFAULT_METHOD,
+    loading = DEFAULT_LOADING
+) => {
+    const requestUrl = `${BASE_URL}${normal[type]}`;
+    const isQueryType = type === "query";
+
+    // 查询类型默认无 loading 动画,非查询类型要关闭 loading 动画需传参 loading:true
+    const isLoading = ["sql", "query"].includes(type) ? loading : !loading;
 
-    const isSpecial = Object.keys(requestPath).includes(method)
-    const requestUrl = isSpecial ? requestPath[method] : `business/v3/sys/universal/${path}`
     return request({
         url: requestUrl,
-        method: type,
-        data: requestData,
-        params: requestParams,
-        // 开启表单提交加载,查询接口除外(sql,select)
-        isLoading: ['sql', 'select'].includes(method) ? loading : true,
-        retainData
-    })
-}
+        method,
+        isLoading,
+        data: dealData(data, type),
+        // ...(isQueryType ? { data: JSON } : { data: dealData(data, type) })
+    });
+};
+
+// 请求方式默认POST
+// const post = (method, data, type = "post", loading = false) => {
+//     const path = normal[method];
+//     let requestData = "";
+//     let requestParams = null;
+//     // 部分接口保留参数,用于后续接口传参
+//     const retainData = null;
+
+//     if (type === "get") {
+//         requestParams = data;
+//     } else {
+//         // 对象转字符串
+//         requestData = dealData(method, data);
+//     }
+
+//     const isSpecial = Object.keys(requestPath).includes(method);
+//     const requestUrl = isSpecial
+//         ? requestPath[method]
+//         : `business/v3/sys/universal/${path}`;
+//     return request({
+//         url: requestUrl,
+//         method: type,
+//         data: dealData(data, type),
+//         params: requestParams,
+//         // 开启表单提交加载,查询接口除外(sql,select)
+//         isLoading: ["sql", "select"].includes(method) ? loading : true,
+//         retainData,
+//     });
+// };
 
 /* 直接传入sql的签名算法   MD5加密*/
-const sig = sql => {
-    const rul = (sql.length + 9) * 12 * 3 + 168
-    const salt = 'JinYuanXinTong'
-    return md5(rul + '' + salt)
-}
+const sig = (sql) => {
+    const rul = (sql.length + 9) * 12 * 3 + 168;
+    const salt = "JinYuanXinTong";
+    return md5(rul + "" + salt);
+};
 
 // 替换对象中的空数据
-const replaceNullWithEmpty = obj => {
-    function replaceValue (value) {
+const replaceNullWithEmpty = (obj) => {
+    function replaceValue(value) {
         if (value === null) {
-            return ''
-        } else if (typeof value === 'object') {
+            return "";
+        } else if (typeof value === "object") {
             if (Array.isArray(value)) {
-                return value.map(item => replaceValue(item))
+                return value.map((item) => replaceValue(item));
             } else {
-                return mapValues(value, v => replaceValue(v))
+                return mapValues(value, (v) => replaceValue(v));
             }
         } else {
-            return value
+            return value;
         }
     }
-    return replaceValue(obj)
-}
+    return replaceValue(obj);
+};
 
-const dealData = (method, data) => {
-    const strType = ['sql']
-    // 查询方法直接拼接字符串
-    if (strType.includes(method)) {
-        data = {
-            sql: data.replace(/\n/g, ' ')
-        }
-    } else {
-        // 其余方法先处理数据
-        if (typeof data === 'object') {
-            data = replaceNullWithEmpty(data)
-        } else {
-            data = replaceNullWithEmpty(JSON.parse(data))
-        }
+const dealData = (args, type) => {
+    if (type === "query") {
+        return JSON.stringify(args);
     }
-    const plaintext = SHOW_PLAINTEXT ? { plaintext: data } : {}
-    const res = {
-        ciphertext: encryptByAes(data),
-        ...plaintext
+    // sql方法特殊处理
+    if (type === "sql") {
+        args = {
+            sql: args.replace(/\n/g, " "),
+        };
     }
-    return JSON.stringify(res)
-}
+    const data = typeof args === "object" ? replaceNullWithEmpty(args) : args;
+    const plaintext = SHOW_PLAINTEXT ? { plaintext: data } : {};
+    const res = {
+        ciphertext: encryptByAes(data, "dynamic", getToken()),
+        ...plaintext,
+    };
+    return JSON.stringify(res);
+};
 
-export default post
+export default post;

+ 33 - 22
src/business/platform/form/utils/custom/requestType.js

@@ -1,40 +1,51 @@
 export const requestType = {
     // 直接传入sql
-    sql: 'inputSqlSelectData',
-    select: 'selectDataContextTable',
-    selects: 'selectDatasContextTable',
-    delete: 'deleteDataContextTable',
-    add: 'addDataContextTable',
+    sql: "inputSqlSelectData",
+    select: "selectDataContextTable",
+    selects: "selectDatasContextTable",
+    delete: "deleteDataContextTable",
+    add: "addDataContextTable",
     // update: 'updateDataContextTable',
-    update: 'updatesBatchContextTable',
+    update: "updatesBatchContextTable",
     // 批量修改
-    updates: 'updateDatasContextTable',
+    updates: "updateDatasContextTable",
     // 批量修改 修改多条数据各自对应的值
-    updatesByWhere: 'updatesBatchContextTable',
-    batchDelete: 'batchDelete',
+    updatesByWhere: "updatesBatchContextTable",
+    batchDelete: "batchDelete",
     // 主管提醒(第一滴血)
-    str: 'crudZhuGuan',
+    str: "crudZhuGuan",
     // 主管提醒(二连击破)
-    send: 'sendmessage',
+    send: "sendmessage",
     // 主管提醒(三联决胜)
-    sendCms: 'sendCms',
+    sendCms: "sendCms",
     // 主管提醒(四连超凡 😥)
-    sendmessages: 'sendmessages'
-}
+    sendmessages: "sendmessages",
+};
+export const normal = {
+    // sql: 'encipher',
+    sql: "general",
+    delete: "batchDelete",
+    add: "addDataContextTable",
+    // 批量更新:不同结果
+    update: "updatesBatchContextTable",
+    // 批量更新:统一结果
+    updates: "updateDatasContextTable",
+    query: "queryData",
+};
 
 export const requestPath = {
     // 公告短信
-    notice: 'business/v3/hwsys/universal/sendNoticeMsg',
+    notice: "business/v3/hwsys/universal/sendNoticeMsg",
     // 财务短信
-    financial: 'business/v3/hwsys/universal/sendFinancialMsg',
+    financial: "business/v3/hwsys/universal/sendFinancialMsg",
     // 创建流程
-    createProcess: 'business/v3/bpm/modeler/save',
+    createProcess: "business/v3/bpm/modeler/save",
     // 设置流程
-    setProcess: 'business/v3/bpm/definition/saveSetting/vo',
+    setProcess: "business/v3/bpm/definition/saveSetting/vo",
     // 获取流水号
-    getId: 'platform/v3/identity/getNextIdByAlias',
+    getId: "platform/v3/identity/getNextIdByAlias",
     // 发送内部消息
-    sendNotice: 'platform/v3/msg/innerMessage/save',
+    sendNotice: "platform/v3/msg/innerMessage/save",
     // 保存表单数据
-    saveFormData: 'business/v3/bpm/task/save/task'
-}
+    saveFormData: "business/v3/bpm/task/save/task",
+};

+ 40 - 37
src/constant.js

@@ -2,16 +2,16 @@
  * 常量配置
  *
  */
-import env from '@/env'
+import env from "@/env";
 /**
  * 读取静态配置
  * @private
  */
-const __IBPS_CONFIG__ = window.__IBPS_CONFIG__ || {}
+const __IBPS_CONFIG__ = window.__IBPS_CONFIG__ || {};
 
-export default __IBPS_CONFIG__
+export default __IBPS_CONFIG__;
 
-const enableConfig = __IBPS_CONFIG__.ENABLE_CONFIG || false
+const enableConfig = __IBPS_CONFIG__.ENABLE_CONFIG || false;
 
 /**
  * 接口服务器
@@ -19,68 +19,71 @@ const enableConfig = __IBPS_CONFIG__.ENABLE_CONFIG || false
  */
 export const BASE_URL = enableConfig
     ? __IBPS_CONFIG__.BASE_URL || env.VUE_APP_BASE_URL
-    : env.VUE_APP_BASE_URL
+    : env.VUE_APP_BASE_URL;
 export const PUBLIC_URL = enableConfig
     ? __IBPS_CONFIG__.PUBLIC_URL || env.VUE_APP_BASE_URL
-    : env.VUE_APP_BASE_URL
+    : env.VUE_APP_BASE_URL;
 export const INTRANET_URL = enableConfig
     ? __IBPS_CONFIG__.INTRANET_URL || env.VUE_APP_BASE_URL
-    : env.VUE_APP_BASE_URL
+    : env.VUE_APP_BASE_URL;
 export const BASE_API = enableConfig
     ? __IBPS_CONFIG__.BASE_API || env.VUE_APP_BASE_API
-    : env.VUE_APP_BASE_API
+    : env.VUE_APP_BASE_API;
 export const BASE_GATEWAY_API = enableConfig
     ? __IBPS_CONFIG__.BASE_GATEWAY_API || env.VUE_APP_BASE_GATEWAY_API
-    : env.VUE_APP_BASE_GATEWAY_API
+    : env.VUE_APP_BASE_GATEWAY_API;
 export const BASE_WEBSOCKET = enableConfig
     ? __IBPS_CONFIG__.BASE_WEBSOCKET || env.VUE_APP_BASE_WEBSOCKET
-    : env.VUE_APP_BASE_WEBSOCKET
+    : env.VUE_APP_BASE_WEBSOCKET;
 export const BASE_REPORT_API = enableConfig
     ? __IBPS_CONFIG__.BASE_REPORT_API || env.VUE_APP_BASE_REPORT_API
-    : env.VUE_APP_BASE_REPORT_API
-export const BASE_SEAL_API = __IBPS_CONFIG__.BASE_SEAL_API || ''
+    : env.VUE_APP_BASE_REPORT_API;
+export const BASE_SEAL_API = __IBPS_CONFIG__.BASE_SEAL_API || "";
 
-export const SINGLE = __IBPS_CONFIG__.SINGLE || false
-export const API_DOMAIN_NAMES = __IBPS_CONFIG__.API_DOMAIN_NAMES || []
-export const MULTIPLE_DOMAIN = __IBPS_CONFIG__.MULTIPLE_DOMAIN || false
+export const SINGLE = __IBPS_CONFIG__.SINGLE || false;
+export const API_DOMAIN_NAMES = __IBPS_CONFIG__.API_DOMAIN_NAMES || [];
+export const MULTIPLE_DOMAIN = __IBPS_CONFIG__.MULTIPLE_DOMAIN || false;
 
 // ================认证中心=====================
 
-export const GRANT_TYPE = __IBPS_CONFIG__.GRANT_TYPE || ''
-export const CLIENT_ID = __IBPS_CONFIG__.CLIENT_ID || ''
-export const CLIENT_SECRET = __IBPS_CONFIG__.CLIENT_SECRET || ''
+export const GRANT_TYPE = __IBPS_CONFIG__.GRANT_TYPE || "";
+export const CLIENT_ID = __IBPS_CONFIG__.CLIENT_ID || "";
+export const CLIENT_SECRET = __IBPS_CONFIG__.CLIENT_SECRET || "";
 
 // ================请求头=====================
 export const HEADER_TOKEN_KEY =
-    __IBPS_CONFIG__.HEADER_TOKEN_KEY || 'X-Authorization-access_token'
-export const FORM_TOKEN_KEY = __IBPS_CONFIG__.TOKEN_KEY || 'access_token'
+    __IBPS_CONFIG__.HEADER_TOKEN_KEY || "X-Authorization-access_token";
+export const FORM_TOKEN_KEY = __IBPS_CONFIG__.TOKEN_KEY || "access_token";
 export const HEADER_SYSTEM_ID =
-    __IBPS_CONFIG__.HEADER_SYSTEM_ID || 'X-Authorization-systemid'
+    __IBPS_CONFIG__.HEADER_SYSTEM_ID || "X-Authorization-systemid";
 export const HEADER_TENANT_ID =
-    __IBPS_CONFIG__.HEADER_TENANT_ID || 'X-Authorization-tenantid'
-export const TENANT_ID = __IBPS_CONFIG__.TENANT_ID || 'tenant_id'
+    __IBPS_CONFIG__.HEADER_TENANT_ID || "X-Authorization-tenantid";
+export const TENANT_ID = __IBPS_CONFIG__.TENANT_ID || "tenant_id";
 
 // ================Cookies 存储=====================
-export const UUID_KEY = __IBPS_CONFIG__.UUID_KEY || 'uuid'
-export const LANG_KEY = __IBPS_CONFIG__.LANG_KEY || 'lang'
+export const UUID_KEY = __IBPS_CONFIG__.UUID_KEY || "uuid";
+export const LANG_KEY = __IBPS_CONFIG__.LANG_KEY || "lang";
 
-export const TOKEN_STORE = __IBPS_CONFIG__.TOKEN_STORE || 'default'
-export const TOKEN_DOMAIN = __IBPS_CONFIG__.TOKEN_DOMAIN || 'bpmhome.cn'
+export const TOKEN_STORE = __IBPS_CONFIG__.TOKEN_STORE || "default";
+export const TOKEN_DOMAIN = __IBPS_CONFIG__.TOKEN_DOMAIN || "bpmhome.cn";
 export const TOKEN_STORE_PREFIX =
-    __IBPS_CONFIG__.TOKEN_STORE_PREFIX || 'default'
-export const TOKEN_STORE_KEY = __IBPS_CONFIG__.TOKEN_STORE_KEY || 'token'
+    __IBPS_CONFIG__.TOKEN_STORE_PREFIX || "default";
+export const TOKEN_STORE_KEY = __IBPS_CONFIG__.TOKEN_STORE_KEY || "token";
 export const REFRESH_TOKEN_STORE_KEY =
-    __IBPS_CONFIG__.REFRESH_TOKEN_STORE_KEY || 'refresh_token'
+    __IBPS_CONFIG__.REFRESH_TOKEN_STORE_KEY || "refresh_token";
 
-export const TRANSFER_DATA = __IBPS_CONFIG__.TRANSFER_DATA || 'transfer'
+export const TRANSFER_DATA = __IBPS_CONFIG__.TRANSFER_DATA || "transfer";
 
-export const I18N_LOCALE = __IBPS_CONFIG__.I18N_LOCALE || 'zh-CN'
+export const I18N_LOCALE = __IBPS_CONFIG__.I18N_LOCALE || "zh-CN";
 export const I18N_FALLBACK_LOCALE =
-    __IBPS_CONFIG__.I18N_FALLBACK_LOCALE || 'zh-CN'
+    __IBPS_CONFIG__.I18N_FALLBACK_LOCALE || "zh-CN";
 
-export const ELEMENT_COLOR = __IBPS_CONFIG__.ELEMENT_COLOR || '#409EFF'
+export const ELEMENT_COLOR = __IBPS_CONFIG__.ELEMENT_COLOR || "#409EFF";
 export const SYSTEM_NAME =
-    __IBPS_CONFIG__.SYSTEM_NAME || '金通检测/校准实验室质量管理系统(LQMS)'
-export const REPORT_PATH = __IBPS_CONFIG__.REPORT_PATH || ''
+    __IBPS_CONFIG__.SYSTEM_NAME || "金通检测/校准实验室质量管理系统(LQMS)";
+export const REPORT_PATH = __IBPS_CONFIG__.REPORT_PATH || "";
+// 是否加密 GET 请求参数
+export const ENCRYPT_GET_PARAMS = __IBPS_CONFIG__.ENCRYPT_GET_PARAMS || false;
 // 是否显示明文SQL,开发环境默认显示
-export const SHOW_PLAINTEXT = __IBPS_CONFIG__.SHOW_PLAINTEXT || env.NODE_ENV === 'development'
+export const SHOW_PLAINTEXT =
+    __IBPS_CONFIG__.SHOW_PLAINTEXT || env.NODE_ENV === "development";

+ 190 - 133
src/router/index.js

@@ -1,162 +1,219 @@
-import Vue from 'vue'
-import VueRouter from 'vue-router'
+import Vue from "vue";
+import VueRouter from "vue-router";
 
 // 进度条
-import NProgress from 'nprogress'
-import 'nprogress/nprogress.css'
+import NProgress from "nprogress";
+import "nprogress/nprogress.css";
 
-import store from '@/store/index.js'
-import util from '@/utils/util.js'
-import setting from '@/setting.js'
-import i18n from '@/utils/i18n.js'
+import store from "@/store/index.js";
+import util from "@/utils/util.js";
+import setting from "@/setting.js";
+import i18n from "@/utils/i18n.js";
 
 // 验权
-import { getToken, getRefreshToken } from '@/utils/auth'
+import { getToken, getRefreshToken } from "@/utils/auth";
 
 // 路由数据
-import routes from './routes'
+import routes from "./routes";
 
 // fix vue-router NavigationDuplicated
-const VueRouterPush = VueRouter.prototype.push
+const VueRouterPush = VueRouter.prototype.push;
 VueRouter.prototype.push = function push(location) {
-  return VueRouterPush.call(this, location).catch(err => err)
-}
-const VueRouterReplace = VueRouter.prototype.replace
+    return VueRouterPush.call(this, location).catch((err) => err);
+};
+const VueRouterReplace = VueRouter.prototype.replace;
 VueRouter.prototype.replace = function replace(location) {
-  return VueRouterReplace.call(this, location).catch(err => err)
-}
+    return VueRouterReplace.call(this, location).catch((err) => err);
+};
 
-Vue.use(VueRouter)
+Vue.use(VueRouter);
 
 // 导出路由 在 main.js 里使用
 const router = new VueRouter({
-  routes
-})
+    routes,
+});
 
 /**
  * 路由拦截
  * 权限验证
  */
-router.beforeEach(async(to, from, next) => {
-  // 确认已经加载多标签页数据
-  await store.dispatch('ibps/page/isLoaded')
-  // 确认已经加载组件尺寸设置
-  await store.dispatch('ibps/size/isLoaded')
-  // 关闭搜索面板
-  store.commit('ibps/search/set', false)
-  // 进度条
-  NProgress.start()
+router.beforeEach(async (to, from, next) => {
+    // 确认已经加载多标签页数据
+    await store.dispatch("ibps/page/isLoaded");
+    // 确认已经加载组件尺寸设置
+    await store.dispatch("ibps/size/isLoaded");
+    // 关闭搜索面板
+    store.commit("ibps/search/set", false);
+    // 进度条
+    NProgress.start();
 
-  const locking = util.cookies.get('locking')
-  if (locking === 'locked' && to.name !== 'locking') { // 判断当前是否是锁定状态
-    next({
-      replace: true,
-      name: 'locking'
-    })
-  } else if (locking === 'unlock' && to.name === 'locking') {
-    next(false)
-  } else {
-    // 这里将cookie里是否存有token作为验证是否登录的条件
-    const hasToken = getToken()
-    if (hasToken && hasToken !== 'undefined') { // 从cookie 获取用户token
-      // 登录 锁定 401没权限  403禁止访问
-      if (to.name === 'locking' || to.name === 'login' || to.name === 'error401' || to.name === 'error403' || to.name === 'nomenu') {
-        next()
-      } else {
-        // 判断是否有子系统和是否有菜单
-        if (util.isEmpty(store.getters.system) || util.isEmpty(store.getters.menus)) {
-          store.dispatch('ibps/user/load').then(res => { // 拉取用户信息,避免刷新用户丢失
-            const system = store.getters.system
-            if ((util.isEmpty(system) || util.isEmpty(system.id))) {
-              if (util.isEmpty(store.getters.tenants)) {
-                if (to.name === 'systemSelect') return next()
-                return next({ path: '/systemSelect', replace: true })
-              }
-              // 租户模式下跳转
-              if (util.isNotEmpty(store.getters.tenants)) {
-                if (to.name === 'tenantSelect') return next()
-                if (to.name === 'systemSelect') return next()
-                return next({ path: '/tenantSelect', replace: true })
-              }
-            }
-            store.dispatch('ibps/menu/init', { systemId: system.id }).then(() => { // 根据用户菜单权限生成可访问的路由表
-              if (util.isEmpty(store.getters.menus)) {
-                next()
-              } else {
-                const addRouters = store.getters.routers
-                
-                if (addRouters && addRouters.length > 0) {
-                  // 动态添加可访问路由表
-                  router.addRoutes(addRouters)
-                  // 初始化加载或用户刷新页面后从数据库加载一系列的设置
-                  store.dispatch('ibps/account/loadInfo', {
-                    addRouters,
-                    menus: store.getters.menus
-                  })
-                  next({ ...to, replace: true }) // hack方法 确保addRoutes已完成
+    const locking = util.cookies.get("locking");
+    if (locking === "locked" && to.name !== "locking") {
+        // 判断当前是否是锁定状态
+        next({
+            replace: true,
+            name: "locking",
+        });
+    } else if (locking === "unlock" && to.name === "locking") {
+        next(false);
+    } else {
+        // 这里将cookie里是否存有token作为验证是否登录的条件
+        const hasToken = getToken();
+        if (hasToken && hasToken !== "undefined") {
+            // 从cookie 获取用户token
+            // 登录 锁定 401没权限  403禁止访问
+            if (
+                to.name === "locking" ||
+                to.name === "login" ||
+                to.name === "error401" ||
+                to.name === "error403" ||
+                to.name === "nomenu"
+            ) {
+                next();
+            } else {
+                // 判断是否有子系统和是否有菜单
+                if (
+                    util.isEmpty(store.getters.system) ||
+                    util.isEmpty(store.getters.menus)
+                ) {
+                    store
+                        .dispatch("ibps/user/load")
+                        .then((res) => {
+                            // 拉取用户信息,避免刷新用户丢失
+                            const system = store.getters.system;
+                            if (
+                                util.isEmpty(system) ||
+                                util.isEmpty(system.id)
+                            ) {
+                                if (util.isEmpty(store.getters.tenants)) {
+                                    if (to.name === "systemSelect")
+                                        return next();
+                                    return next({
+                                        path: "/systemSelect",
+                                        replace: true,
+                                    });
+                                }
+                                // 租户模式下跳转
+                                if (util.isNotEmpty(store.getters.tenants)) {
+                                    if (to.name === "tenantSelect")
+                                        return next();
+                                    if (to.name === "systemSelect")
+                                        return next();
+                                    return next({
+                                        path: "/tenantSelect",
+                                        replace: true,
+                                    });
+                                }
+                            }
+                            store
+                                .dispatch("ibps/menu/init", {
+                                    systemId: system.id,
+                                })
+                                .then(() => {
+                                    // 根据用户菜单权限生成可访问的路由表
+                                    if (util.isEmpty(store.getters.menus)) {
+                                        next();
+                                    } else {
+                                        const addRouters =
+                                            store.getters.routers;
+
+                                        if (
+                                            addRouters &&
+                                            addRouters.length > 0
+                                        ) {
+                                            // 动态添加可访问路由表
+                                            router.addRoutes(addRouters);
+                                            // 初始化加载或用户刷新页面后从数据库加载一系列的设置
+                                            store.dispatch(
+                                                "ibps/account/loadInfo",
+                                                {
+                                                    addRouters,
+                                                    menus: store.getters.menus,
+                                                }
+                                            );
+                                            next({ ...to, replace: true }); // hack方法 确保addRoutes已完成
+                                        } else {
+                                            next({
+                                                path: "/403",
+                                                replace: true,
+                                                query: { noGoBack: true },
+                                            });
+                                        }
+                                    }
+                                })
+                                .catch((e) => {
+                                    console.error(e);
+                                    NProgress.done(); // 结束Progress
+                                });
+                        })
+                        .catch((e) => {
+                            NProgress.done(); // 结束Progress
+                            // 前台登出
+                            store
+                                .dispatch("ibps/account/fedLogout")
+                                .then(() => {
+                                    next({ name: "login" });
+                                })
+                                .catch((err) => {
+                                    console.error(err);
+                                });
+                        });
                 } else {
-                  next({ path: '/403', replace: true, query: { noGoBack: true }})
+                    // 动态改变权限,判断是否有菜单权限,或者刷新页面
+                    if (to.matched.length === 0) {
+                        // 不能匹配的路由
+                        return next({
+                            path: "401",
+                            replace: true,
+                            query: { noGoBack: true },
+                        });
+                    } else {
+                        next();
+                    }
                 }
-              }
-            }).catch((e) => {
-              console.error(e)
-              NProgress.done() // 结束Progress
-            })
-          }).catch((e) => {
-            NProgress.done() // 结束Progress
-            // 前台登出
-            store.dispatch('ibps/account/fedLogout').then(() => {
-              next({ name: 'login' })
-            }).catch((err) => {
-              console.error(err)
-            })
-          })
-        } else { // 动态改变权限,判断是否有菜单权限,或者刷新页面
-          if (to.matched.length === 0) { // 不能匹配的路由
-            return next({ path: '401', replace: true, query: { noGoBack: true }})
-          } else {
-            next()
-          }
-        }
-      // end
-      }
-    } else { /* has no token */
-      // 判断refresh tonken是否过期
-      const refreshToken = getRefreshToken()
-      if (util.isNotEmpty(refreshToken)) {
-        // 刷新tonken
-        await store.dispatch('ibps/account/refreshToken').then(() => {
-          next()
-        }).catch((err) => {
-          console.error(err)
-        })
-      } else {
-        // 在免登录白名单,直接进入
-        if (setting.whiteRouterList.indexOf(to.path) !== -1) {
-          next()
+                // end
+            }
         } else {
-          // 没有登录的时候跳转到登录界面
-          // 携带上登陆成功之后需要跳转的页面完整路径
-          next({
-            name: 'login',
-            query: {
-              redirect: to.fullPath
+            /* has no token */
+            // 判断refresh tonken是否过期
+            const refreshToken = getRefreshToken();
+            if (util.isNotEmpty(refreshToken)) {
+                // 刷新tonken
+                await store
+                    .dispatch("ibps/account/refreshToken")
+                    .then(() => {
+                        next();
+                    })
+                    .catch((err) => {
+                        console.error(err);
+                    });
+            } else {
+                // 在免登录白名单,直接进入
+                if (setting.whiteRouterList.indexOf(to.path) !== -1) {
+                    next();
+                } else {
+                    // 没有登录的时候跳转到登录界面
+                    // 携带上登陆成功之后需要跳转的页面完整路径
+                    next({
+                        name: "login",
+                        query: {
+                            redirect: to.fullPath,
+                        },
+                    });
+                    NProgress.done();
+                }
             }
-          })
-          NProgress.done()
         }
-      }
     }
-  }
-})
+});
 
-router.afterEach(to => {
-  // 进度条
-  NProgress.done()
-  // 多页控制 打开新的页面
- /* store.dispatch('ibps/page/open', to) */
-  // 更改标题
-  i18n.setTitle(to.meta.name || to.name, to.meta.title)
-})
+router.afterEach((to) => {
+    // 进度条
+    NProgress.done();
+    // 多页控制 打开新的页面
+    /* store.dispatch('ibps/page/open', to) */
+    // 更改标题
+    i18n.setTitle(to.meta.name || to.name, to.meta.title);
+});
 
-export default router
+export default router;

+ 341 - 308
src/store/modules/ibps/modules/account.js

@@ -1,314 +1,347 @@
-import { login, logout, getValidCode, refreshAccessToken, resetPasswd, resetTenantPasswd, register, getRegisterOpen } from '@/api/oauth2/user'
-import { MessageBox } from 'element-ui'
+import {
+    login,
+    logout,
+    getValidCode,
+    refreshAccessToken,
+    resetPasswd,
+    resetTenantPasswd,
+    register,
+    getRegisterOpen,
+} from "@/api/oauth2/user";
+import { MessageBox } from "element-ui";
 // 框架内部路由
-import { frameInRoutes } from '@/router/routes'
+import { frameInRoutes } from "@/router/routes";
 // 验权
-import { getToken, updateToken, removeToken, removeRefreshToken, setUuid, removeUuid, removeTenantId } from '@/utils/auth'
+import {
+    getToken,
+    updateToken,
+    removeToken,
+    removeRefreshToken,
+    setUuid,
+    removeUuid,
+    removeTenantId,
+} from "@/utils/auth";
 
 export default {
-  namespaced: true,
-  actions: {
-    /**
-     * @description 获取验证码
-     * @param {*} payload
-     * @param {*} payload
-     */
-    getCaptcha({ dispatch }, { params } = {}) {
-      return new Promise((resolve, reject) => {
-        getValidCode(params).then(response => {
-          resolve(response)
-        }).catch(error => {
-          reject(error)
-        })
-      })
-    },
-    /**
-     *  @description 是否开启注册
-     *
-     */
-    getRegisterOpen() {
-      return new Promise((resolve, reject) => {
-        getRegisterOpen().then(response => {
-          resolve(response)
-        }).catch(error => {
-          reject(error)
-        })
-      })
-    },
-    /**
-     * @description 登录
-     * @param {Object} context
-     * @param {Object} payload username {String} 用户账号
-     * @param {Object} payload password {String} 密码
-     * @param {Object} payload route {Object} 登录成功后定向的路由对象 任何 vue-router 支持的格式
-     */
-    login({ dispatch }, {
-      form
-    } = {}) {
-      return new Promise(async(resolve, reject) => {
-        // 开始请求登录接口
-        login(form).then(async response => {
-          const data = response.data
-          const tokenInfo = JSON.parse(JSON.stringify(data))
-          tokenInfo.licJson = undefined
-          const licenceData = data.licJson || { isTrialVersion: false }
-          const { isTrialVersion, notAfter, reminderDays, notBefore } = licenceData
-          const now = Date.now()
-          // 判定是否超时
-          licenceData.overtime = isTrialVersion && (notBefore > now || notAfter < now)
-          // 判定是否提醒
-          licenceData.needRemind = isTrialVersion && notBefore < now && notAfter > now && now + reminderDays * 86400000 > notAfter
-           // 更新token
-           dispatch('updataTokenInfo', data)
-          // 设置 vuex 用户信息
-           dispatch('ibps/user/setAccount', form.username, { root: true })
-          // 设置认证信息
-          dispatch('ibps/licence/setLicence', licenceData, { root: true })
-          localStorage.setItem('licence', JSON.stringify(licenceData))
-          // 结束
-          resolve(data)
-        }).catch(err => {
-          console.error('err: ', err)
-          reject(err)
-        })
-      })
-    },
-    /**
-     * 更新token 用户信息
-     * @param {*} param0
-     * @param {*} data
-     */
-    updataTokenInfo({
-      commit,
-      dispatch
-    }, data) {
-      // 设置 cookie 一定要存 uuid 和 token 两个 cookie
-      // 整个系统依赖这两个数据进行校验和存储
-      // uuid 是用户身份唯一标识 用户注册的时候确定 并且不可改变 不可重复
-      // token 代表用户当前登录状态 建议在网络请求中携带 token
-      // 如有必要 token 需要定时更新,默认保存一天
-      updateToken(data)
-      setUuid(data.uid)
-    },
-    /**
-     * 忘记密码
-     * @param {*} param context 上下文
-     * @param {*} form 表单
-     */
-    resetPasswd({
-      commit,
-      dispatch
-    }, form) {
-      return new Promise(async(resolve, reject) => {
-        // 开始请求重置密码接口
-        resetPasswd(form).then(response => {
-          resolve()
-        }).catch(err => {
-          console.error('err: ', err)
-          reject(err)
-        })
-      })
-    },
-    /**
-     * 企业租户用户忘记密码
-     * @param {*} param context 上下文
-     * @param {*} form 表单
-     */
-    resetTenantPasswd({
-      commit,
-      dispatch
-    }, form) {
-      return new Promise(async(resolve, reject) => {
-        // 开始请求重置密码接口
-        resetTenantPasswd(form).then(response => {
-          resolve()
-        }).catch(err => {
-          console.error('err: ', err)
-          reject(err)
-        })
-      })
-    },
-    /**
-     * 注册帐号
-     * @param {*} param context 上下文
-     * @param {*} form 表单
-     */
-    register({
-      commit,
-      dispatch
-    }, form) {
-      return new Promise(async(resolve, reject) => {
-        // 开始请求注册接口
-        register(form).then(response => {
-          resolve()
-        }).catch(err => {
-          console.error('err: ', err)
-          reject(err)
-        })
-      })
-    },
-    /**
-     * @description 注销用户并返回登录页面
-     * @param {Object} param context 上下文
-     * @param {Object} param vm {Object} vue 实例
-     * @param {Object} param confirm {Boolean} 是否需要确认
-     */
-    logout({
-      commit,
-      dispatch
-    }, {
-      vm,
-      confirm = false
-    }) {
-      // 判断是否需要确认
-      if (confirm) {
-        commit('ibps/gray/set', true, {
-          root: true
-        })
-        MessageBox.confirm(vm.$t('logout.message'), vm.$t('logout.title'), {
-          confirmButtonText: vm.$t('logout.confirmButtonText'),
-          cancelButtonText: vm.$t('logout.cancelButtonText'),
-          type: 'warning'
-        }).then(() => {
-          commit('ibps/gray/set', false, {
-            root: true
-          })
-          dispatch('logoff', { vm })
-        })
-          .catch(() => {
-            commit('ibps/gray/set', false, {
-              root: true
-            })
-          })
-      } else {
-        dispatch('logoff', { vm })
-      }
-    },
-    /**
-     * 注销,包含后台登出和前台清除token
-     */
-    logoff({ dispatch }, { vm }) {
-      const token = getToken()
-      // 如果token过期直接登出
-      if (token === null || token === '') {
-        dispatch('fedLogout').then(() => {
-          vm.$router.push({
-            name: 'login'
-          })
-        }).catch(() => {})
-        return
-      }
-      // 后台登出
-      logout(token).then(() => {
-        dispatch('fedLogout').then(() => {
-          vm.$router.push({
-            name: 'login'
-          })
-        }).catch(() => {})
-      }).catch(() => {
-        dispatch('fedLogout').then(() => {
-          vm.$router.push({
-            name: 'login'
-          })
-        }).catch(() => {})
-      })
-    },
-    /**
-     * 前台登出
-     */
-   fedLogout({
-      commit,
-      dispatch
-    }, vm) {
-      return new Promise(async(resolve, reject) => {
-        // 重置路由
-        // resetRouter()
-        // 删除一系列cookie
-        removeToken()
-        removeUuid()
-        removeRefreshToken()
-        removeTenantId()
-        // 删除用户信息
-        dispatch('ibps/user/setAccount', null, { root: true })
-        dispatch('ibps/user/set', null, { root: true })
-        // 删除菜单
-        dispatch('ibps/menu/menusSet', null, { root: true })
-        resolve(vm)
-      })
-    },
-    /**
-     * 刷新token
-     * @param {*} param0
-     * @param {*} token
-     */
-    refreshToken({
-      commit,
-      dispatch
-    }) {
-      return new Promise(async(resolve, reject) => {
-        await refreshAccessToken().then(response => {
-          const data = response.data
-          // 更新token信息
-          updateToken(data)
-          resolve(data)
-        }).catch(err => {
-          console.error('refreshAccessToken-err: ', err)
-          removeRefreshToken()
-          reject(err)
-        })
-      })
-    },
-    /**
-     * 加载登录后的信息
-     * @param {*} param0
-     * @param {*} param1
-     */
-    loadInfo({
-      commit,
-      dispatch
-    }, {
-      addRouters = [],
-      menus
-    }) {
-      return new Promise(async resolve => {
-        const routes = [...frameInRoutes, ...addRouters]
-        // 处理路由 得到每一级的路由设置
-        await commit('ibps/page/init', routes, {
-          root: true
-        })
-        // 初始化菜单搜索功能
-        await commit('ibps/search/init', menus, {
-          root: true
-        })
+    namespaced: true,
+    actions: {
+        /**
+         * @description 获取验证码
+         * @param {*} payload
+         * @param {*} payload
+         */
+        getCaptcha({ dispatch }, { params } = {}) {
+            return new Promise((resolve, reject) => {
+                getValidCode(params)
+                    .then((response) => {
+                        resolve(response);
+                    })
+                    .catch((error) => {
+                        reject(error);
+                    });
+            });
+        },
+        /**
+         *  @description 是否开启注册
+         *
+         */
+        getRegisterOpen() {
+            return new Promise((resolve, reject) => {
+                getRegisterOpen()
+                    .then((response) => {
+                        resolve(response);
+                    })
+                    .catch((error) => {
+                        reject(error);
+                    });
+            });
+        },
+        /**
+         * @description 登录
+         * @param {Object} context
+         * @param {Object} payload username {String} 用户账号
+         * @param {Object} payload password {String} 密码
+         * @param {Object} payload route {Object} 登录成功后定向的路由对象 任何 vue-router 支持的格式
+         */
+        login({ dispatch }, { form } = {}) {
+            return new Promise(async (resolve, reject) => {
+                // 开始请求登录接口
+                login(form)
+                    .then(async (response) => {
+                        const { data = {} } = response;
+                        const tokenInfo = JSON.parse(JSON.stringify(data));
+                        tokenInfo.licJson = undefined;
+                        const licenceData = data.licJson || {
+                            isTrialVersion: false,
+                        };
+                        const {
+                            isTrialVersion,
+                            notAfter,
+                            reminderDays,
+                            notBefore,
+                        } = licenceData;
+                        const now = Date.now();
+                        // 判定是否超时
+                        licenceData.overtime =
+                            isTrialVersion &&
+                            (notBefore > now || notAfter < now);
+                        // 判定是否提醒
+                        licenceData.needRemind =
+                            isTrialVersion &&
+                            notBefore < now &&
+                            notAfter > now &&
+                            now + reminderDays * 86400000 > notAfter;
+
+                        // 更新token
+                        dispatch("updataTokenInfo", tokenInfo);
+                        // 设置 vuex 用户信息
+                        dispatch("ibps/user/setAccount", form.username, {
+                            root: true,
+                        });
+                        // 设置认证信息
+                        dispatch("ibps/licence/setLicence", licenceData, {
+                            root: true,
+                        });
+                        localStorage.setItem(
+                            "licence",
+                            JSON.stringify(licenceData)
+                        );
+                        // 结束
+                        resolve({ ...tokenInfo, licenceData });
+                    })
+                    .catch((err) => {
+                        console.error("err: ", err);
+                        reject(err);
+                    });
+            });
+        },
+        /**
+         * 更新token 用户信息
+         * @param {*} param0
+         * @param {*} data
+         */
+        updataTokenInfo({ commit, dispatch }, data) {
+            // 设置 cookie 一定要存 uuid 和 token 两个 cookie
+            // 整个系统依赖这两个数据进行校验和存储
+            // uuid 是用户身份唯一标识 用户注册的时候确定 并且不可改变 不可重复
+            // token 代表用户当前登录状态 建议在网络请求中携带 token
+            // 如有必要 token 需要定时更新,默认保存一天
+            updateToken(data);
+            setUuid(data.uid);
+        },
+        /**
+         * 忘记密码
+         * @param {*} param context 上下文
+         * @param {*} form 表单
+         */
+        resetPasswd({ commit, dispatch }, form) {
+            return new Promise(async (resolve, reject) => {
+                // 开始请求重置密码接口
+                resetPasswd(form)
+                    .then((response) => {
+                        resolve();
+                    })
+                    .catch((err) => {
+                        console.error("err: ", err);
+                        reject(err);
+                    });
+            });
+        },
+        /**
+         * 企业租户用户忘记密码
+         * @param {*} param context 上下文
+         * @param {*} form 表单
+         */
+        resetTenantPasswd({ commit, dispatch }, form) {
+            return new Promise(async (resolve, reject) => {
+                // 开始请求重置密码接口
+                resetTenantPasswd(form)
+                    .then((response) => {
+                        resolve();
+                    })
+                    .catch((err) => {
+                        console.error("err: ", err);
+                        reject(err);
+                    });
+            });
+        },
+        /**
+         * 注册帐号
+         * @param {*} param context 上下文
+         * @param {*} form 表单
+         */
+        register({ commit, dispatch }, form) {
+            return new Promise(async (resolve, reject) => {
+                // 开始请求注册接口
+                register(form)
+                    .then((response) => {
+                        resolve();
+                    })
+                    .catch((err) => {
+                        console.error("err: ", err);
+                        reject(err);
+                    });
+            });
+        },
+        /**
+         * @description 注销用户并返回登录页面
+         * @param {Object} param context 上下文
+         * @param {Object} param vm {Object} vue 实例
+         * @param {Object} param confirm {Boolean} 是否需要确认
+         */
+        logout({ commit, dispatch }, { vm, confirm = false }) {
+            // 判断是否需要确认
+            if (confirm) {
+                commit("ibps/gray/set", true, {
+                    root: true,
+                });
+                MessageBox.confirm(
+                    vm.$t("logout.message"),
+                    vm.$t("logout.title"),
+                    {
+                        confirmButtonText: vm.$t("logout.confirmButtonText"),
+                        cancelButtonText: vm.$t("logout.cancelButtonText"),
+                        type: "warning",
+                    }
+                )
+                    .then(() => {
+                        commit("ibps/gray/set", false, {
+                            root: true,
+                        });
+                        dispatch("logoff", { vm });
+                    })
+                    .catch(() => {
+                        commit("ibps/gray/set", false, {
+                            root: true,
+                        });
+                    });
+            } else {
+                dispatch("logoff", { vm });
+            }
+        },
+        /**
+         * 注销,包含后台登出和前台清除token
+         */
+        logoff({ dispatch }, { vm }) {
+            const token = getToken();
+            // 如果token过期直接登出
+            if (token === null || token === "") {
+                dispatch("fedLogout")
+                    .then(() => {
+                        vm.$router.push({
+                            name: "login",
+                        });
+                    })
+                    .catch(() => {});
+                return;
+            }
+            // 后台登出
+            logout(token)
+                .then(() => {
+                    dispatch("fedLogout")
+                        .then(() => {
+                            vm.$router.push({
+                                name: "login",
+                            });
+                        })
+                        .catch(() => {});
+                })
+                .catch(() => {
+                    dispatch("fedLogout")
+                        .then(() => {
+                            vm.$router.push({
+                                name: "login",
+                            });
+                        })
+                        .catch(() => {});
+                });
+        },
+        /**
+         * 前台登出
+         */
+        fedLogout({ commit, dispatch }, vm) {
+            return new Promise(async (resolve, reject) => {
+                // 重置路由
+                // resetRouter()
+                // 删除一系列cookie
+                removeToken();
+                removeUuid();
+                removeRefreshToken();
+                removeTenantId();
+                // 删除用户信息
+                dispatch("ibps/user/setAccount", null, { root: true });
+                dispatch("ibps/user/set", null, { root: true });
+                // 删除菜单
+                dispatch("ibps/menu/menusSet", null, { root: true });
+                resolve(vm);
+            });
+        },
+        /**
+         * 刷新token
+         * @param {*} param0
+         * @param {*} token
+         */
+        refreshToken({ commit, dispatch }) {
+            return new Promise(async (resolve, reject) => {
+                await refreshAccessToken()
+                    .then((response) => {
+                        const data = response.data;
+                        // 更新token信息
+                        updateToken(data);
+                        resolve(data);
+                    })
+                    .catch((err) => {
+                        console.error("refreshAccessToken-err: ", err);
+                        removeRefreshToken();
+                        reject(err);
+                    });
+            });
+        },
+        /**
+         * 加载登录后的信息
+         * @param {*} param0
+         * @param {*} param1
+         */
+        loadInfo({ commit, dispatch }, { addRouters = [], menus }) {
+            return new Promise(async (resolve) => {
+                const routes = [...frameInRoutes, ...addRouters];
+                // 处理路由 得到每一级的路由设置
+                await commit("ibps/page/init", routes, {
+                    root: true,
+                });
+                // 初始化菜单搜索功能
+                await commit("ibps/search/init", menus, {
+                    root: true,
+                });
 
-        await dispatch('load')
-      })
+                await dispatch("load");
+            });
+        },
+        /**
+         * @description 用户登录后从持久化数据加载一系列的设置
+         * @param {Object} context
+         */
+        load({ dispatch }) {
+            return new Promise(async (resolve) => {
+                // DB -> store 加载用户名
+                await dispatch("ibps/user/get", null, { root: true });
+                // DB -> store 加载主题
+                await dispatch("ibps/theme/load", null, { root: true });
+                // DB -> store 加载页面过渡效果设置
+                await dispatch("ibps/transition/load", null, { root: true });
+                // DB -> store 持久化数据加载上次退出时的多页列表
+                await dispatch("ibps/page/openedLoad", null, { root: true });
+                // DB -> store  持久化数据加载侧边栏配置
+                await dispatch("ibps/menu/asideLoad", null, { root: true });
+                // DB -> store 持久化数据加载全局尺寸
+                await dispatch("ibps/size/load", null, { root: true });
+                // DB -> store 持久化数据加载全局国际化
+                await dispatch("ibps/language/load", null, { root: true });
+                // DB -> store 持久化数据加载颜色设置
+                await dispatch("ibps/color/load", null, { root: true });
+                // end
+                resolve();
+            });
+        },
     },
-    /**
-     * @description 用户登录后从持久化数据加载一系列的设置
-     * @param {Object} context
-     */
-    load({ dispatch }) {
-      return new Promise(async resolve => {
-        // DB -> store 加载用户名
-        await dispatch('ibps/user/get', null, { root: true })
-        // DB -> store 加载主题
-        await dispatch('ibps/theme/load', null, { root: true })
-        // DB -> store 加载页面过渡效果设置
-        await dispatch('ibps/transition/load', null, { root: true })
-        // DB -> store 持久化数据加载上次退出时的多页列表
-        await dispatch('ibps/page/openedLoad', null, { root: true })
-        // DB -> store  持久化数据加载侧边栏配置
-        await dispatch('ibps/menu/asideLoad', null, { root: true })
-        // DB -> store 持久化数据加载全局尺寸
-        await dispatch('ibps/size/load', null, { root: true })
-        // DB -> store 持久化数据加载全局国际化
-        await dispatch('ibps/language/load', null, { root: true })
-        // DB -> store 持久化数据加载颜色设置
-        await dispatch('ibps/color/load', null, { root: true })
-        // end
-        resolve()
-      })
-    }
-  }
-}
+};

+ 159 - 39
src/utils/encrypt.js

@@ -1,44 +1,164 @@
-import CryptoJS from 'crypto-js'
-const key1 = CryptoJS.enc.Utf8.parse('dmngJmmO+9GMw+tu')
-const iv1 = CryptoJS.enc.Utf8.parse('sanXyqhk8+U7LPP4')
-const key2 = CryptoJS.enc.Utf8.parse('49PBou+TREIOzSHj')
-const iv2 = CryptoJS.enc.Utf8.parse('5lDsNRe&UduJ97uS')
+import CryptoJS from "crypto-js";
+const key = "49PBou+TREIOzSHj";
+const key1 = CryptoJS.enc.Utf8.parse("dmngJmmO+9GMw+tu");
+const iv1 = CryptoJS.enc.Utf8.parse("sanXyqhk8+U7LPP4");
+const key2 = CryptoJS.enc.Utf8.parse(key);
+const iv2 = CryptoJS.enc.Utf8.parse("5lDsNRe&UduJ97uS");
+// 固定IV 用于密码、get请求参数加密
+const defaultIv = CryptoJS.enc.Utf8.parse("5lDsNRe&UduJ97uS");
+// 密钥派生参数配置
+const PBKDF2_CONFIG = {
+    // 盐值长度(bits)
+    saltSize: 128,
+    // 迭代次数
+    iterations: 10000,
+    // 密钥长度(256bit)
+    keySize: 128 / 32,
+    hashAlgorithm: CryptoJS.algo.SHA256,
+};
+const deriveDynamicKey = (token, salt) => {
+    if (!token || typeof token !== "string") {
+        throw new Error("Invalid user token");
+    }
+
+    return CryptoJS.PBKDF2(token, salt, {
+        keySize: PBKDF2_CONFIG.keySize,
+        iterations: PBKDF2_CONFIG.iterations,
+        hasher: PBKDF2_CONFIG.hashAlgorithm,
+    });
+};
+export const generateDynamicIV = () => {
+    // 1. 获取当前时间戳(8字节,64位)
+    const timestamp = Date.now();
+    // 将时间戳转换为8字节的WordArray(大端序)
+    const timestampBytes = CryptoJS.enc.Hex.parse(
+        timestamp.toString(16).padStart(16, "0")
+    );
+
+    // 2. 生成8字节随机数
+    const randomBytes = CryptoJS.lib.WordArray.random(8);
+
+    // 3. 构造IV(16字节)y
+    const ivWords = [
+        // 前4字节:随机数的高4字节
+        randomBytes.words[0],
+        // 接下来4字节:时间戳的高4字节
+        timestampBytes.words[0],
+        // 接下来4字节:随机数的低4字节
+        randomBytes.words[1],
+        // 最后4字节:时间戳的低4字节
+        timestampBytes.words[1],
+    ];
+
+    return CryptoJS.lib.WordArray.create(ivWords, 16);
+};
+const xorEncrypt = (text) => {
+    let encrypted = "";
+    for (let i = 0; i < text.length; i++) {
+        const charCode = text.charCodeAt(i) ^ key.charCodeAt(i % key.length);
+        encrypted += String.fromCharCode(charCode);
+    }
+
+    return btoa(encrypted);
+};
+const xorDecrypt = (encryptedBase64) => {
+    // 从Base64解码
+    const decodedStr = atob(encryptedBase64);
+    let decrypted = "";
+
+    // 异或解密
+    for (let i = 0; i < decodedStr.length; i++) {
+        const charCode =
+            decodedStr.charCodeAt(i) ^ key.charCodeAt(i % key.length);
+        decrypted += String.fromCharCode(charCode);
+    }
+
+    return decrypted;
+};
 // AES加密
-export const encryptByAes = (pwd, type = 'normal') => {
-    let encrypted = ''
-    const key = type === 'normal' ? key1 : key2
-    const iv = type === 'normal' ? iv1 : iv2
-    if (typeof pwd === 'string') {
-        const srcs = CryptoJS.enc.Utf8.parse(pwd)
-        const options = {
-            iv: iv,
-            mode: CryptoJS.mode.CBC, // 使用CBC模式
-            padding: CryptoJS.pad.Pkcs7 // 使用PKCS7填充
-        }
-        encrypted = CryptoJS.AES.encrypt(srcs, key, options)
-    } else if (typeof pwd === 'object') {
-        const data = JSON.stringify(pwd)
-        const srcs = CryptoJS.enc.Utf8.parse(data)
-        const options = {
+export const encryptByAes = (params, type = "dynamic", token) => {
+    try {
+        const isDynamic = type === "dynamic";
+        // 生成随机盐值
+        const salt = CryptoJS.lib.WordArray.random(PBKDF2_CONFIG.saltSize);
+        // 动态派生密钥
+        const derivedKey = isDynamic ? deriveDynamicKey(token, salt) : key2;
+        // 生成动态iv
+        const iv = isDynamic ? generateDynamicIV() : defaultIv;
+        const data =
+            typeof params === "string" ? params : JSON.stringify(params);
+        const srcs = CryptoJS.enc.Utf8.parse(data);
+
+        const encrypted = CryptoJS.AES.encrypt(srcs, derivedKey, {
             iv: iv,
-            mode: CryptoJS.mode.CBC, // 使用CBC模式
-            padding: CryptoJS.pad.Pkcs7 // 使用PKCS7填充
+            mode: CryptoJS.mode.CBC,
+            padding: CryptoJS.pad.Pkcs7,
+        });
+
+        if (isDynamic) {
+            const str =
+                encrypted.ciphertext.toString(CryptoJS.enc.Base64) +
+                "|" +
+                iv.toString(CryptoJS.enc.Base64) +
+                "|" +
+                salt.toString(CryptoJS.enc.Base64) +
+                "|" +
+                token;
+            return xorEncrypt(str);
         }
-        encrypted = CryptoJS.AES.encrypt(srcs, key, options)
+        return encrypted.ciphertext.toString(CryptoJS.enc.Base64);
+    } catch (error) {
+        console.error("Encryption error:", error);
+        throw new Error("Encryption failed");
     }
-    return encrypted.ciphertext.toString(CryptoJS.enc.Base64)
-}
-
-export const decryptByAes = (encryptedText, type = 'normal') => {
-    const key = type === 'normal' ? key1 : key2
-    const iv = type === 'normal' ? iv1 : iv2
-    const options = {
-        iv: iv,
-        mode: CryptoJS.mode.CBC, // 使用CBC模式
-        padding: CryptoJS.pad.Pkcs7 // 使用PKCS7填充
+};
+
+const isValidBase64 = (str) => {
+    try {
+        return btoa(atob(str)) === str;
+    } catch (e) {
+        return false;
+    }
+};
+
+export const decryptByAes = (ciphertext) => {
+    try {
+        // 初始化解密参数
+        let cipherToDecrypt = ciphertext;
+        let iv = defaultIv;
+        let key = key2;
+
+        // 尝试XOR解密并解析参数
+        const decryptedStr = xorDecrypt(ciphertext);
+        const parts = decryptedStr.split("|");
+        if (parts.length === 4) {
+            const [ciphertextBase64, ivBase64, saltBase64, token] = parts;
+
+            if (
+                token &&
+                !(isValidBase64(ivBase64) && isValidBase64(saltBase64))
+            ) {
+                console.error("解密失败: 无效的IV参数或salt参数!");
+                return "";
+            }
+            // 转换编码
+            iv = CryptoJS.enc.Base64.parse(ivBase64);
+            const salt = CryptoJS.enc.Base64.parse(saltBase64);
+            // 动态派生密钥
+            key = deriveDynamicKey(token, salt);
+            cipherToDecrypt = ciphertextBase64;
+        }
+
+        // 解密
+        const decrypted = CryptoJS.AES.decrypt(
+            { ciphertext: CryptoJS.enc.Base64.parse(cipherToDecrypt) },
+            key,
+            { iv, mode: CryptoJS.mode.CBC, padding: CryptoJS.pad.Pkcs7 }
+        );
+
+        return decrypted.toString(CryptoJS.enc.Utf8).trim();
+    } catch (error) {
+        console.error("AES解密失败:", error);
+        return "";
     }
-    const encryptedData = CryptoJS.enc.Base64.parse(encryptedText)
-    const decryptedData = CryptoJS.AES.decrypt({ ciphertext: encryptedData }, key, options)
-    const decryptedText = decryptedData.toString(CryptoJS.enc.Utf8)
-    return decryptedText.trim()
-}
+};

+ 263 - 207
src/utils/request.js

@@ -8,28 +8,35 @@
  * 版权:广州流辰信息技术有限公司
  * </pre>
  */
-import axios from 'axios'
-import { Message, MessageBox } from 'element-ui'
-import store from '@/store'
-import router from '@/router'
+import axios from "axios";
+import { Message, MessageBox } from "element-ui";
+import store from "@/store";
+import router from "@/router";
 // Internationalization 国际化
-import I18n from '@/utils/i18n'
-import Utils from '@/utils/util'
-import Ids from 'ids'
-import setting from '@/setting.js'
-
+import I18n from "@/utils/i18n";
+import Utils from "@/utils/util";
+import Ids from "ids";
+import setting from "@/setting.js";
+import { encryptByAes } from "@/utils/encrypt";
 // 验权
-import { getToken, updateToken, removeRefreshToken } from '@/utils/auth'
-import { refreshAccessToken } from '@/api/oauth2/user'
+import { getToken, updateToken, removeRefreshToken } from "@/utils/auth";
+import { refreshAccessToken } from "@/api/oauth2/user";
 
-import { showFullScreenLoading, tryHideFullScreenLoading } from './loading'
+import { showFullScreenLoading, tryHideFullScreenLoading } from "./loading";
 
-import requestState from '@/constants/state'
-import { BASE_API, BASE_GATEWAY_API } from '@/api/baseUrl'
-import { HEADER_TOKEN_KEY, HEADER_SYSTEM_ID, HEADER_TENANT_ID, MULTIPLE_DOMAIN, API_DOMAIN_NAMES } from '@/constant'
+import requestState from "@/constants/state";
+import { BASE_API, BASE_GATEWAY_API } from "@/api/baseUrl";
+import {
+    HEADER_TOKEN_KEY,
+    HEADER_SYSTEM_ID,
+    HEADER_TENANT_ID,
+    MULTIPLE_DOMAIN,
+    API_DOMAIN_NAMES,
+    ENCRYPT_GET_PARAMS,
+} from "@/constant";
 
 // 请求超时(timeout)时间
-const TIMEOUT = setting.requestTimeout
+const TIMEOUT = setting.requestTimeout;
 
 /**
  * 创建axios实例
@@ -40,26 +47,26 @@ const service = axios.create({
     // 跨域安全策略
     withCredentials: true,
     headers: {
-        'Cache-Control': 'no-cache',
-        'Content-Type': 'application/json;charset=utf-8'
-    }
-})
+        "Cache-Control": "no-cache",
+        "Content-Type": "application/json;charset=utf-8",
+    },
+});
 
 // 是否正在刷新的标记
-let isRefreshing = false
+let isRefreshing = false;
 // 重试队列,每一项将是一个待执行的函数形式
-let requests = []
+let requests = [];
 // 取消请求
-let cancelRequest = false
+let cancelRequest = false;
 
-let requestCount = 0
+let requestCount = 0;
 
 /**
  * 请求(request)拦截器
  *
  * get请求,统一参数放在params里面,后台对应只有@RequestParam
  * `params`是即将与请求一起发送的 URL 参数,必须是一个无格式对象(plain object)或 URLSearchParams 对象
- * 
+ *
  * post请求,统一参数放在data里面——json格式,后台对应@RequestBody ,其他 后台对应@RequestParam
  * `data` 是作为请求主体被发送的数据
  * 只适用于这些请求方法 'PUT', 'POST', 和 'PATCH'
@@ -69,209 +76,258 @@ let requestCount = 0
  * - Node 专属: Stream
  * post 请求 `params` 这个同get 但要注意 后台对应@RequestParam 请求的`Content-Type`是 application/x-www-form-urlencoded 用 qs.stringify 去构造数据
  */
-service.interceptors.request.use(async config => {
-    if (!config.baseURL) {
-        config.baseURL = BASE_API(parseInt(requestCount / 5, 10))
-        if (MULTIPLE_DOMAIN) {
-            requestCount >= ((API_DOMAIN_NAMES.length - 1) * 5) ? requestCount = 0 : requestCount++
+service.interceptors.request.use(
+    async (config) => {
+        if (!config.baseURL) {
+            config.baseURL = BASE_API(parseInt(requestCount / 5, 10));
+            if (MULTIPLE_DOMAIN) {
+                requestCount >= (API_DOMAIN_NAMES.length - 1) * 5
+                    ? (requestCount = 0)
+                    : requestCount++;
+            }
+        }
+        if (config.gateway) {
+            config.baseURL = BASE_GATEWAY_API();
         }
-    }
-    if (config.gateway) {
-        config.baseURL = BASE_GATEWAY_API()
-    }
 
-    config.isLoading = config.isLoading !== undefined && config.isLoading !== null ? config.isLoading : false
-    if (config.isLoading) {
-        showFullScreenLoading(config.loading)
-    }
-    // 如果超时不对还原默认超时时间
-    if (config.timeout !== TIMEOUT) {
-        config.timeout = TIMEOUT
-    }
-    // 只设置当前的时间设置以设置为准
-    if (Utils.isNotEmpty(config.overtime)) {
-        config.timeout = config.overtime
-    }
-    // 防止缓存
-    if (config.method.toUpperCase() === 'GET') {
-        config.params = {
-            ...config.params,
-            _t: new Ids([32, 36, 1]).next()
+        config.isLoading =
+            config.isLoading !== undefined && config.isLoading !== null
+                ? config.isLoading
+                : false;
+        if (config.isLoading) {
+            showFullScreenLoading(config.loading);
+        }
+        // 如果超时不对还原默认超时时间
+        if (config.timeout !== TIMEOUT) {
+            config.timeout = TIMEOUT;
+        }
+        // 只设置当前的时间设置以设置为准
+        if (Utils.isNotEmpty(config.overtime)) {
+            config.timeout = config.overtime;
+        }
+        // 防止缓存
+        if (config.method.toUpperCase() === "GET") {
+            if (ENCRYPT_GET_PARAMS) {
+                config.params = {
+                    _p: Utils.isNotEmpty(config.params)
+                        ? encryptByAes(JSON.stringify(config.params), "get")
+                        : undefined,
+                    _t: new Ids([32, 36, 1]).next(),
+                };
+            } else {
+                config.params = {
+                    ...config.params,
+                    _t: new Ids([32, 36, 1]).next(),
+                };
+            }
         }
-    }
 
-    // 判断是否需要token
-    if (setting.whiteRequestList.indexOf(config.url) !== -1) {
-        return config
-    }
-    config.headers[HEADER_TOKEN_KEY] = getToken()
-    // 系统ID
-    if (store && store.getters.systemid) {
-        config.headers[HEADER_SYSTEM_ID] = store.getters.systemid
-    }
-    // 租户ID
-    if (store && store.getters.tenantid) {
-        config.headers[HEADER_TENANT_ID] = store.getters.designTenantid ? store.getters.designTenantid : store.getters.tenantid
-    }
-    // 租户模式
-    if (store && store.getters.isTenantOpen) {
-        config.headers[HEADER_TENANT_ID] = store.getters.designTenantid ? store.getters.designTenantid : store.getters.tenantid
+        // 判断是否需要token
+        if (setting.whiteRequestList.indexOf(config.url) !== -1) {
+            return config;
+        }
+        config.headers[HEADER_TOKEN_KEY] = getToken();
+        // 系统ID
+        if (store && store.getters.systemid) {
+            config.headers[HEADER_SYSTEM_ID] = store.getters.systemid;
+        }
+        // 租户ID
+        if (store && store.getters.tenantid) {
+            config.headers[HEADER_TENANT_ID] = store.getters.designTenantid
+                ? store.getters.designTenantid
+                : store.getters.tenantid;
+        }
+        // 租户模式
+        if (store && store.getters.isTenantOpen) {
+            config.headers[HEADER_TENANT_ID] = store.getters.designTenantid
+                ? store.getters.designTenantid
+                : store.getters.tenantid;
+        }
+        return config;
+    },
+    (error) => {
+        tryHideFullScreenLoading();
+        // Do something with request error
+        // for debug
+        Utils.log.error("request" + error);
+        Promise.reject(error);
     }
-    return config
-}, error => {
-    tryHideFullScreenLoading()
-    // Do something with request error
-    // for debug
-    Utils.log.error('request' + error)
-    Promise.reject(error)
-})
+);
 
 /**
  * 响应(respone)拦截器
  */
-service.interceptors.response.use(response => {
-    //临时关闭了保存等待的取消功能
-    tryHideFullScreenLoading()
+service.interceptors.response.use(
+    (response) => {
+        //临时关闭了保存等待的取消功能
+        tryHideFullScreenLoading();
 
-    const dataAxios = response.data
-    const { state, message, cause } = dataAxios
-    // 获取接口保留参数,用于部分接口的后续请求
-    const { retainData } = response.config
-    if (response.config.responseType === 'arraybuffer') {
-        // 刷新tonken
-        return response
-    }
-    // 如果没有 state 代表这不是项目后端开发的接口 比如可能是请求最新版本,或者是请求的数据,或者是
-    if (state === undefined) {
-        const msg = '接口异常,没有返回[state]参数</br>' + response.config.url
-        Message.closeAll()
-        Message({
-            message: `${msg}`,
-            type: 'error',
-            showClose: true,
-            dangerouslyUseHTMLString: true,
-            duration: 10000
-        })
-        return
-    }
-    // state为200是正确的请求 或者 验证码问题,或者警告类型的错误 自行处理
-    if (state === requestState.SUCCESS || state === requestState.UNSUPORT || state === requestState.WARNING || state === requestState.WARN) {
-        return { ...dataAxios, retainData }
-    }
-    // 处理刷新tonken问题,说明token过期了,刷新token
-    if (state === requestState.TOKEN_EXPIRED) {
-        const config = response.config
-        if (!isRefreshing) {
-            isRefreshing = true
-            return refreshAccessToken().then(res => {
-                const data = res.data
-                updateToken(data)
-                const token = getToken()
-                config.headers[HEADER_TOKEN_KEY] = token
-                // 已经刷新了token,将所有队列中的请求进行重试
-                requests.forEach(cb => cb(token))
-                requests = []
-                return service(config)
-            }).catch(res => {
-                console.error('refreshtoken error =>', res)
-                removeRefreshToken()
-                window.location.href = this.$baseUrl
-            }).finally(() => {
-                isRefreshing = false
-            })
-        } else {
-            // 正在刷新token,将返回一个未执行resolve的promise
-            return new Promise((resolve) => {
-                // 将resolve放进队列,用一个函数形式来保存,等token刷新后直接执行
-                requests.push((token) => {
-                    config.headers[HEADER_TOKEN_KEY] = token
-                    resolve(service(config))
-                })
-            })
+        const dataAxios = response.data;
+        const { state, message, cause } = dataAxios;
+        // 获取接口保留参数,用于部分接口的后续请求
+        const { retainData } = response.config;
+        if (response.config.responseType === "arraybuffer") {
+            // 刷新tonken
+            return response;
         }
-        // 6020201:非法的token;6020202:其他客户端登录了;6020301:Token 过期了;
-    } else if (state === requestState.ILLEGAL_TOKEN ||
-        state === requestState.OTHER_CLIENTS) {
-        // if (!cancelRequest) {
-            cancelRequest = false
-            MessageBox.confirm(
-                I18n.t('error.logout.message'),
-                I18n.t('error.logout.title'), {
-                confirmButtonText: I18n.t('error.logout.confirmButtonText'),
-                cancelButtonText: I18n.t('error.logout.cancelButtonText'),
-                type: 'warning'
-            }).then(() => {
-                store.dispatch('ibps/account/fedLogout').then(() => {
-                    // 终止所有请求
-                    cancelRequest = true
-                    router.push({
-                        name: 'login'
+        // 如果没有 state 代表这不是项目后端开发的接口 比如可能是请求最新版本,或者是请求的数据,或者是
+        if (state === undefined) {
+            const msg =
+                "接口异常,没有返回[state]参数</br>" + response.config.url;
+            Message.closeAll();
+            Message({
+                message: `${msg}`,
+                type: "error",
+                showClose: true,
+                dangerouslyUseHTMLString: true,
+                duration: 10000,
+            });
+            return;
+        }
+        // state为200是正确的请求 或者 验证码问题,或者警告类型的错误 自行处理
+        if (
+            state === requestState.SUCCESS ||
+            state === requestState.UNSUPORT ||
+            state === requestState.WARNING ||
+            state === requestState.WARN
+        ) {
+            return { ...dataAxios, retainData };
+        }
+        // 处理刷新tonken问题,说明token过期了,刷新token
+        if (state === requestState.TOKEN_EXPIRED) {
+            const config = response.config;
+            if (!isRefreshing) {
+                isRefreshing = true;
+                return refreshAccessToken()
+                    .then((res) => {
+                        const data = res.data;
+                        updateToken(data);
+                        const token = getToken();
+                        config.headers[HEADER_TOKEN_KEY] = token;
+                        // 已经刷新了token,将所有队列中的请求进行重试
+                        requests.forEach((cb) => cb(token));
+                        requests = [];
+                        return service(config);
                     })
-                }).catch(() => {
-                    cancelRequest = false
+                    .catch((res) => {
+                        console.error("refreshtoken error =>", res);
+                        removeRefreshToken();
+                        window.location.href = this.$baseUrl;
+                    })
+                    .finally(() => {
+                        isRefreshing = false;
+                    });
+            } else {
+                // 正在刷新token,将返回一个未执行resolve的promise
+                return new Promise((resolve) => {
+                    // 将resolve放进队列,用一个函数形式来保存,等token刷新后直接执行
+                    requests.push((token) => {
+                        config.headers[HEADER_TOKEN_KEY] = token;
+                        resolve(service(config));
+                    });
+                });
+            }
+            // 6020201:非法的token;6020202:其他客户端登录了;6020301:Token 过期了;
+        } else if (
+            state === requestState.ILLEGAL_TOKEN ||
+            state === requestState.OTHER_CLIENTS
+        ) {
+            // if (!cancelRequest) {
+            cancelRequest = false;
+            MessageBox.confirm(
+                I18n.t("error.logout.message"),
+                I18n.t("error.logout.title"),
+                {
+                    confirmButtonText: I18n.t("error.logout.confirmButtonText"),
+                    cancelButtonText: I18n.t("error.logout.cancelButtonText"),
+                    type: "warning",
+                }
+            )
+                .then(() => {
+                    store
+                        .dispatch("ibps/account/fedLogout")
+                        .then(() => {
+                            // 终止所有请求
+                            cancelRequest = true;
+                            router.push({
+                                name: "login",
+                            });
+                        })
+                        .catch(() => {
+                            cancelRequest = false;
+                        });
                 })
-            }).finally(() => {
-                cancelRequest = false
-            })
-        // }
-        return Promise.reject(new Error(message))
-    } else { // 错误处理
-        let errorMsg = ''
-        if (Utils.isNotEmpty(message)) { // 有错误消息
-            errorMsg = Utils.isNotEmpty(dataAxios.cause) ? I18n.t('error.messageCause', {
-                message,
-                cause: dataAxios.cause
-            }) : I18n.t('error.message', {
-                message
-            })
-        } else if (Utils.isNotEmpty(cause)) { // 只有错误原因
-            errorMsg = I18n.t('error.cause', {
-                cause
-            })
-        } else if (I18n.te('error.status.' + state)) { // 有错误编码
-            errorMsg = I18n.t('error.status.' + state)
-        } else { // 未知
-            errorMsg = message || I18n.t('error.unknown', {
-                state
-            })
+                .finally(() => {
+                    cancelRequest = false;
+                });
+            // }
+            return Promise.reject(new Error(message));
+        } else {
+            // 错误处理
+            let errorMsg = "";
+            if (Utils.isNotEmpty(message)) {
+                // 有错误消息
+                errorMsg = Utils.isNotEmpty(dataAxios.cause)
+                    ? I18n.t("error.messageCause", {
+                          message,
+                          cause: dataAxios.cause,
+                      })
+                    : I18n.t("error.message", {
+                          message,
+                      });
+            } else if (Utils.isNotEmpty(cause)) {
+                // 只有错误原因
+                errorMsg = I18n.t("error.cause", {
+                    cause,
+                });
+            } else if (I18n.te("error.status." + state)) {
+                // 有错误编码
+                errorMsg = I18n.t("error.status." + state);
+            } else {
+                // 未知
+                errorMsg =
+                    message ||
+                    I18n.t("error.unknown", {
+                        state,
+                    });
+            }
+            Message.closeAll();
+            Message({
+                message: `${errorMsg}`,
+                type: "error",
+                showClose: true,
+                dangerouslyUseHTMLString: true,
+                duration: 5 * 1000,
+            });
+            const err = new Error(errorMsg);
+            err.state = state;
+            err.cause = cause;
+            return Promise.reject(err);
         }
-        Message.closeAll()
-        Message({
-            message: `${errorMsg}`,
-            type: 'error',
-            showClose: true,
-            dangerouslyUseHTMLString: true,
-            duration: 5 * 1000
-        })
-        const err = new Error(errorMsg)
-        err.state = state
-        err.cause = cause
-        return Promise.reject(err)
-    }
-},
+    },
     // 异常处理
-    error => {
-        tryHideFullScreenLoading()
+    (error) => {
+        tryHideFullScreenLoading();
         // for debug
-        console.error('request-error', error)
+        console.error("request-error", error);
         if (error && error.response) {
-            error.message = I18n.t('error.status.' + error.response.status, {
-                url: error.response.config.url
-            })
+            error.message = I18n.t("error.status." + error.response.status, {
+                url: error.response.config.url,
+            });
         } else {
-            error.state = 500
+            error.state = 500;
             // '服务器君开小差了,请稍后再试'
-            error.message = I18n.t('error.network')
+            error.message = I18n.t("error.network");
         }
-        Message.closeAll()
+        Message.closeAll();
         Message({
-            message: error.message || I18n.t('error.network'),
-            type: 'error',
+            message: error.message || I18n.t("error.network"),
+            type: "error",
             showClose: true,
-            duration: 5 * 1000
-        })
-        return Promise.reject(error)
+            duration: 5 * 1000,
+        });
+        return Promise.reject(error);
     }
-)
+);
 
-export default service
+export default service;

+ 38 - 21
src/views/platform/org/employee/change-password.vue

@@ -44,6 +44,7 @@
 import { changePassword, registerChangePassword } from '@/api/platform/org/user'
 import { mapActions } from 'vuex'
 import ActionUtils from '@/utils/action'
+import { encryptByAes } from '@/utils/encrypt'
 
 export default {
   props: {
@@ -178,31 +179,47 @@ export default {
     // 提交保存数据
     saveData() {
       this.password.userIds = this.ids
+      const { primitivePassword, repeatPassword, newPassword, userIds } =
+        this.password
+      const params = {
+        userIds: userIds.split(','),
+        primitivePassword: primitivePassword
+          ? encryptByAes(primitivePassword, 'pwd')
+          : '',
+        repeatPassword: encryptByAes(repeatPassword, 'pwd'),
+        newPassword: encryptByAes(newPassword, 'pwd')
+      }
       if (this.$store.getters.regOpen) {
-        this.password.reset = 0 // 0-非重置、1-重置
-        this.password.userIds = this.password.userIds.split(',')
-        registerChangePassword(this.password).then(response => {
-          ActionUtils.saveSuccessMessage(response.message, (rtn) => {
-            this.logOff()
-            if (rtn) {
-              this.closeDialog()
-            }
+        params.reset = 0 // 0-非重置、1-重置
+        registerChangePassword(params)
+          .then((response) => {
+            ActionUtils.saveSuccessMessage(response.message, (rtn) => {
+              this.logOff()
+              if (rtn) {
+                this.closeDialog()
+              }
+            })
+          })
+          .catch((err) => {
+            console.error(err)
           })
-        }).catch((err) => {
-          console.error(err)
-        })
       } else {
-        this.restoreDefaultPassW === 'restoreDefault' ? this.password.reset = 2 : !this.isReset ? this.password.reset = 0 : this.password.reset = 1
-        this.password.userIds = this.password.userIds.split(',')
-        changePassword(this.password).then(response => {
-          ActionUtils.saveSuccessMessage(response.message, (rtn) => {
-            if (rtn) {
-              this.closeDialog()
-            }
+        this.restoreDefaultPassW === 'restoreDefault'
+          ? (params.reset = 2)
+          : !this.isReset
+            ? (params.reset = 0)
+            : (params.reset = 1)
+        changePassword(params)
+          .then((response) => {
+            ActionUtils.saveSuccessMessage(response.message, (rtn) => {
+              if (rtn) {
+                this.closeDialog()
+              }
+            })
+          })
+          .catch((err) => {
+            console.error(err)
           })
-        }).catch((err) => {
-          console.error(err)
-        })
       }
     },
     /**

+ 358 - 303
src/views/platform/org/employee/edit/index.vue

@@ -23,7 +23,7 @@
                     :readonly="readonly"
                     :data="employee"
                     :formType="formType"
-                    @input="data => employee = data"
+                    @input="(data) => (employee = data)"
                 />
             </el-tab-pane>
             <el-tab-pane label="扩展属性" name="ext-attr">
@@ -31,7 +31,7 @@
                     ref="attrInfo"
                     :readonly="readonly"
                     :data="employee.attrItemList"
-                    @input="data => employee.attrItemList = data"
+                    @input="(data) => (employee.attrItemList = data)"
                 />
             </el-tab-pane>
             <el-tab-pane
@@ -45,7 +45,7 @@
                     :readonly="readonly"
                     :data="employee.orgItem"
                     :groupID="employee.groupID"
-                    @input="data => employee.orgItem = data"
+                    @input="(data) => (employee.orgItem = data)"
                 />
             </el-tab-pane>
 
@@ -56,10 +56,14 @@
                     :readonly="readonly"
                     :org-id="orgId"
                     :data="employee.posItemList"
-                    @input="data => employee.posItemList = data"
+                    @input="(data) => (employee.posItemList = data)"
                 />
             </el-tab-pane>
-            <el-tab-pane v-if="!infoIncludes('role-info')"  label="角色信息" name="role-info">
+            <el-tab-pane
+                v-if="!infoIncludes('role-info')"
+                label="角色信息"
+                name="role-info"
+            >
                 <!-- <span slot="label">角色信息
                     <el-tooltip
                         v-if="!readonly"
@@ -76,7 +80,7 @@
                     :span="span"
                     :readonly="readonly"
                     :data="employee.roleItemList"
-                    @input="data => employee.roleItemList = data"
+                    @input="(data) => (employee.roleItemList = data)"
                 />
             </el-tab-pane>
             <!-- <el-tab-pane label="用户组信息" name="group-info">
@@ -94,155 +98,159 @@
                 @action-event="handleActionEvent"
             />
         </div>
-         <personal-code
+        <personal-code
             v-if="qrcodeVisible"
             :visible.sync="qrcodeVisible"
             :content="personalInfo"
             :photo="employee.photo"
-            @close="visible => (qrcodeVisible = visible)"
+            @close="(visible) => (qrcodeVisible = visible)"
         />
     </el-dialog>
 </template>
 
 <script>
-    import { create, update, load,upEmployee } from '@/api/platform/org/employee'
-    import ActionUtils from '@/utils/action'
-    import BasicInfo from './basic-info'
-    import ExtAttr from './ext-attr'
-    import OrgInfo from './org-info'
-    import PositionInfo from './position-info'
-    import RoleInfo from './role-info'
-    import GroupInfo from './group-info'
-    import PersonalCode from './personal-qrcode'
+import { create, update, load, upEmployee } from "@/api/platform/org/employee";
+import ActionUtils from "@/utils/action";
+import BasicInfo from "./basic-info";
+import ExtAttr from "./ext-attr";
+import OrgInfo from "./org-info";
+import PositionInfo from "./position-info";
+import RoleInfo from "./role-info";
+import GroupInfo from "./group-info";
+import PersonalCode from "./personal-qrcode";
+import { encryptByAes } from "@/utils/encrypt";
 
-    export default {
-        components: {
-            BasicInfo,
-            ExtAttr,
-            OrgInfo,
-            PositionInfo,
-            RoleInfo,
-            GroupInfo,
-            PersonalCode
+export default {
+    components: {
+        BasicInfo,
+        ExtAttr,
+        OrgInfo,
+        PositionInfo,
+        RoleInfo,
+        GroupInfo,
+        PersonalCode,
+    },
+    props: {
+        visible: Boolean,
+        id: String,
+        title: String,
+        readonly: {
+            type: Boolean,
+            default: false,
         },
-        props: {
-            visible: Boolean,
-            id: String,
-            title: String,
-            readonly: {
-                type: Boolean,
-                default: false
-            },
-            formType: {
-                type: String,
-                default: 'add'
-            },
-            ceroParams: {
-                type: Object,
-                default: () => {}
-            },
-            span: [Number, String]
+        formType: {
+            type: String,
+            default: "add",
         },
-        data() {
-            return {
-                info: [],
-                orgId: '',
-                dialogLoading: false,
-                dialogVisible: false,
-                activeName: 'basic-info',
-                defaultEmployee: {
-                    id: '',
-                    account: '',
-                    password: '',
-                    isSuper: 'N',
-                    name: '',
-                    status: 'actived',
-                    gender: 'male',
-                    email: '',
-                    photo: '',
-                    mobile: '',
-                    createTime: '',
-                    attrItemList: [], // 扩展属性
-                    groupID: '', // 组织ID
-                    posItemList: [],
-                    roleItemList: [],
-                    userGroupItemList: [],
-                    orgItem: {} // 组织全部信息
-                },
-                employee: {},
-                qrcodeVisible: false,
-                toolbars: [
-                    {
-                        key: 'save',
-                        hidden: () => { return this.readonly && this.formType == 'detail' }
-                    },
-                    {
-                    key: 'qrcode',
-                    icon: 'ibps-icon-qrcode',
-                    label: '个人二维码',
-                    type: 'success'
-                    },
-                    { key: 'cancel' }
-                ]
-            }
-        },
-        computed: {
-            formId() {
-                return this.id
-            }
+        ceroParams: {
+            type: Object,
+            default: () => {},
         },
-        watch: {
-            visible: {
-                handler (val, oldVal) {
-                    this.dialogVisible = this.visible
-                },
-                immediate: true
+        span: [Number, String],
+    },
+    data() {
+        return {
+            info: [],
+            orgId: "",
+            dialogLoading: false,
+            dialogVisible: false,
+            activeName: "basic-info",
+            defaultEmployee: {
+                id: "",
+                account: "",
+                password: "",
+                isSuper: "N",
+                name: "",
+                status: "actived",
+                gender: "male",
+                email: "",
+                photo: "",
+                mobile: "",
+                createTime: "",
+                attrItemList: [], // 扩展属性
+                groupID: "", // 组织ID
+                posItemList: [],
+                roleItemList: [],
+                userGroupItemList: [],
+                orgItem: {}, // 组织全部信息
             },
-            ceroParams: {
-                handler (val, oldVal) {
-                    if (val && val !== {}) {
-                        this.orgId = val.groundId
-                    }
+            employee: {},
+            qrcodeVisible: false,
+            toolbars: [
+                {
+                    key: "save",
+                    hidden: () => {
+                        return this.readonly && this.formType == "detail";
+                    },
                 },
-                deep: true
-            }
+                {
+                    key: "qrcode",
+                    icon: "ibps-icon-qrcode",
+                    label: "个人二维码",
+                    type: "success",
+                },
+                { key: "cancel" },
+            ],
+        };
+    },
+    computed: {
+        formId() {
+            return this.id;
         },
-        methods: {
-            infoIncludes(params) {
-                const arr = this.ceroParams !== undefined ? this.ceroParams.unshow : []
-                return arr.includes(params)
+    },
+    watch: {
+        visible: {
+            handler(val, oldVal) {
+                this.dialogVisible = this.visible;
             },
-            handleActionEvent({ key }) {
-                switch (key) {
-                    case 'save':
-                        this.handleSave()
-                        break
-                    case 'qrcode':
-                    this.handleQRCode()
-                    break
-                    case 'cancel':
-                        this.closeDialog()
-                        break
-                    default:
-                        break
+            immediate: true,
+        },
+        ceroParams: {
+            handler(val, oldVal) {
+                if (val && val !== {}) {
+                    this.orgId = val.groundId;
                 }
             },
-            handleSave() {
-                // 验证表单是否填写
-                this.$refs.basicInfo.validate((valid) => {
-                    if (valid) {
-                        if(this.formId){
-                            this.getUpEmployee()
-                        }else{
-                            this.saveData()
-                        }
+            deep: true,
+        },
+    },
+    methods: {
+        infoIncludes(params) {
+            const arr =
+                this.ceroParams !== undefined ? this.ceroParams.unshow : [];
+            return arr.includes(params);
+        },
+        handleActionEvent({ key }) {
+            switch (key) {
+                case "save":
+                    this.handleSave();
+                    break;
+                case "qrcode":
+                    this.handleQRCode();
+                    break;
+                case "cancel":
+                    this.closeDialog();
+                    break;
+                default:
+                    break;
+            }
+        },
+        handleSave() {
+            // 验证表单是否填写
+            this.$refs.basicInfo.validate((valid) => {
+                if (valid) {
+                    if (this.formId) {
+                        this.getUpEmployee();
                     } else {
-                        this.activeName = 'basic-info'
-                        ActionUtils.saveErrorMessage()
+                        this.saveData();
                     }
-                })
-            },
-             handleQRCode () {
+                } else {
+                    this.activeName = "basic-info";
+                    ActionUtils.saveErrorMessage();
+                }
+            });
+        },
+        handleQRCode() {
             this.personalInfo = JSON.stringify({
                 id: this.employee.id,
                 account: this.employee.account,
@@ -250,195 +258,242 @@
                 mobile: this.employee.mobile,
                 email: this.employee.email,
                 gender: this.employee.gender,
-                dept: this.employee.posItemList.map(i => i.name).join(','),
-                role: this.employee.roleItemList.map(i => i.name).join(',')
-            })
-            this.qrcodeVisible = true
-            },
-            checkPhone(value) {
-                const reg = /^((13[0-9])|(14[5,7])|(15[0-3,5-9])|(17[0,3,5-8])|(18[0-9])|166|198|199|(147))\d{8}$/
-                if (!reg.test(value)) {
-                    return false
-                }
-                return true
-            },
-            getUpEmployee(){
-                let params = {
-                    id: this.employee.id,
-                    account: this.employee.account
-                }
-                upEmployee(params).then(res => {
-                    if(res.state == 200){
-                        const data = res.variables.data
-                        if(data == "Y"){
-                            this.saveData()
-                        }else{
-                            ActionUtils.warning(res.message)
-                        }
+                dept: this.employee.posItemList.map((i) => i.name).join(","),
+                role: this.employee.roleItemList.map((i) => i.name).join(","),
+            });
+            this.qrcodeVisible = true;
+        },
+        checkPhone(value) {
+            const reg =
+                /^((13[0-9])|(14[5,7])|(15[0-3,5-9])|(17[0,3,5-8])|(18[0-9])|166|198|199|(147))\d{8}$/;
+            if (!reg.test(value)) {
+                return false;
+            }
+            return true;
+        },
+        getUpEmployee() {
+            let params = {
+                id: this.employee.id,
+                account: this.employee.account,
+            };
+            upEmployee(params).then((res) => {
+                if (res.state == 200) {
+                    const data = res.variables.data;
+                    if (data == "Y") {
+                        this.saveData();
+                    } else {
+                        ActionUtils.warning(res.message);
                     }
-                })
-            },
-            saveData() {
-                const attrValidator = this.$refs['attrInfo'] ? this.$refs['attrInfo'].callback() : null
-                const vo = this.formatSubmitData()
-                if (!this.$utils.isEmpty(this.formId) && !this.ceroParams) {
-                    delete vo.partyEmployeePo.password
-                }
-                this.dialogLoading = true
-                if (!attrValidator) {
-                    ActionUtils.warning('请检查扩展属性是否填写正确')
-                    this.dialogLoading = false
-                    return
                 }
-                const { mobile = '' } = vo.user || {}
-                if (mobile && !this.checkPhone(mobile)) {
-                    ActionUtils.warning('请输入正确的手机号')
-                    this.dialogLoading = false
-                    return
-                }
-                if (this.formId) {
-                    update(vo).then(response => {
-                        this.dialogLoading = false
-                        this.$emit('dialog-callback', this)
-                        ActionUtils.saveSuccessMessage(response.message, r => {
+            });
+        },
+        saveData() {
+            const attrValidator = this.$refs["attrInfo"]
+                ? this.$refs["attrInfo"].callback()
+                : null;
+            const vo = this.formatSubmitData();
+            if (!this.$utils.isEmpty(this.formId) && !this.ceroParams) {
+                delete vo.partyEmployeePo.password;
+            } else {
+                // 创建用户时密码加密处理
+                vo.partyEmployeePo.password = encryptByAes(
+                    vo.partyEmployeePo.password,
+                    "pwd"
+                );
+            }
+            this.dialogLoading = true;
+            if (!attrValidator) {
+                ActionUtils.warning("请检查扩展属性是否填写正确");
+                this.dialogLoading = false;
+                return;
+            }
+            const { mobile = "" } = vo.user || {};
+            if (mobile && !this.checkPhone(mobile)) {
+                ActionUtils.warning("请输入正确的手机号");
+                this.dialogLoading = false;
+                return;
+            }
+
+            const { email = "" } = vo.user || {};
+            if (email && !this.checkEmail(email)) {
+                ActionUtils.warning("请输入正确的邮箱");
+                this.dialogLoading = false;
+                return;
+            }
+
+            if (this.formId) {
+                update(vo)
+                    .then((response) => {
+                        this.dialogLoading = false;
+
+                        this.$emit("dialog-callback", this);
+                        // if (this.formType === "part") {
+                        //     this.closeDialog();
+                        //     return this.$router.currentRoute.path ===
+                        //         "/dashboard"
+                        //         ? location.reload()
+                        //         : this.$router.push("/");
+                        // }
+                        ActionUtils.saveSuccessMessage(
+                            response.message,
+                            (r) => {
                                 // if (this.$utils.isEmpty(this.formId)) {
                                 //     this.$refs[this.formName].resetFields()
                                 // }
                                 if (r) {
-                                    this.closeDialog()
+                                    this.closeDialog();
                                 }
                             }
-                        )
-                    }).catch(() => {
-                        this.dialogLoading = false
+                        );
                     })
-                } else {
-                    create(vo).then(response => {
-                        this.dialogLoading = false
-                        this.$emit('dialog-callback', this)
-                        ActionUtils.saveSuccessMessage(response.message, r => {
+                    .catch(() => {
+                        this.dialogLoading = false;
+                    });
+            } else {
+                create(vo)
+                    .then((response) => {
+                        this.dialogLoading = false;
+                        this.$emit("dialog-callback", this);
+                        ActionUtils.saveSuccessMessage(
+                            response.message,
+                            (r) => {
                                 if (r) {
-                                    this.closeDialog()
+                                    this.closeDialog();
                                 } else {
-                                    this.init()
-                                    this.$refs.attrInfo.clearData()
+                                    this.init();
+                                    if (this.isSuper) {
+                                        this.$refs.attrInfo.clearData();
+                                    }
                                 }
                             }
-                        )
-                    }).catch(() => {
-                        this.dialogLoading = false
+                        );
                     })
+                    .catch(() => {
+                        this.dialogLoading = false;
+                    });
+            }
+        },
+        // 关闭当前窗口
+        closeDialog() {
+            this.$emit("close", false);
+        },
+        // 初始化页面,出现之前的数据
+        init() {
+            this.activeName = "basic-info";
+            this.employee = this.$utils.newData(this.defaultEmployee);
+            this.$nextTick(() => {
+                if (this.$refs.orgInfo) {
+                    this.$refs.orgInfo.init();
                 }
-            },
-            // 关闭当前窗口
-            closeDialog() {
-                this.$emit('close', false)
-            },
-            // 初始化页面,出现之前的数据
-            init() {
-                this.activeName = 'basic-info'
-                this.employee = this.$utils.newData(this.defaultEmployee)
-                this.$nextTick(() => {
-                    if (this.$refs.orgInfo) {
-                        this.$refs.orgInfo.init()
-                    }
-                    // this.$refs.positionInfo.init()
-                    if (this.$refs.roleInfo) {
-                        this.$refs.roleInfo.init()
-                    }
-                })
-            },
-            getFormData() {
-                this.init()
-                this.$nextTick(() => {
-                    this.$refs['basicInfo'].handleGetDefaultUserSecurity()
-                })
-                if (this.$utils.isEmpty(this.formId)) {
-                    // 清空拓展属性数据
-                    this.$nextTick(() => {
-                        this.$refs.attrInfo.clearData()
-                    })
-                    return
+                // this.$refs.positionInfo.init()
+                if (this.$refs.roleInfo) {
+                    this.$refs.roleInfo.init();
                 }
-                this.dialogLoading = true
-                // 用户基本信息
-                load({ employeeId: this.formId }).then((response) => {
-                    this.dialogLoading = false
-                    this.employee = response.data
-                    this.employee.orgItem = response.variables.partyOrg || {}
-                    this.employee.attrItemList = response.variables.partyAttrs || []
-                    this.employee.posItemList = response.variables.partyPositions || []
-                    this.employee.roleItemList = response.variables.partyRoles || []
-                    this.employee.userGroupItemList = response.variables.partyGroups || []
+            });
+        },
+        getFormData() {
+            this.init();
+            this.$nextTick(() => {
+                this.$refs["basicInfo"].handleGetDefaultUserSecurity();
+            });
+            if (this.$utils.isEmpty(this.formId)) {
+                // 清空拓展属性数据
+                this.$nextTick(() => {
+                    this.$refs.attrInfo.clearData();
+                });
+                return;
+            }
+            this.dialogLoading = true;
+            // 用户基本信息
+            load({ employeeId: this.formId })
+                .then((response) => {
+                    this.dialogLoading = false;
+                    this.employee = response.data;
+                    this.employee.orgItem = response.variables.partyOrg || {};
+                    this.employee.attrItemList =
+                        response.variables.partyAttrs || [];
+                    this.employee.posItemList =
+                        response.variables.partyPositions || [];
+                    this.employee.roleItemList =
+                        response.variables.partyRoles || [];
+                    this.employee.userGroupItemList =
+                        response.variables.partyGroups || [];
                     this.$nextTick(() => {
-                        this.$refs.attrInfo.loadAttrData()
-                    })
-                }).catch(() => {
-                    this.dialogLoading = false
+                        this.$refs.attrInfo.loadAttrData();
+                    });
                 })
-            },
-            formatSubmitData() {
-                const vo = {}
-                vo.partyEmployeePo = this.employee
-                vo.user = this.employee
-                vo.user.password = this.formId === '' || this.ceroParams ? this.employee.password : this.defaultEmployee.password
-                vo.partyEmployeePo.groupID = this.ceroParams !== {} && this.ceroParams ? this.ceroParams.groundId : this.formatOrgData()
-                vo.positionVoList = this.formatPositionData()
-                vo.roleVoList = this.formatRoleData()
-                vo.attrValueVoList = this.employee.attrItemList
-                vo.userGroupPoList = this.formatUserGroupData()
-                if (this.ceroParams !== {} && this.ceroParams) {
-                    vo.partyEmployeePo.prem = this.ceroParams.prem
-                }
-                return vo
-            },
-            formatOrgData() {
-                return this.employee.orgItem.id || ''
-            },
-            formatPositionData() {
-                const result = []
-                const list = this.employee.posItemList
-                if (this.$utils.isEmpty(list)) return result
-                for (const variable of list) {
-                    const tmp = { id: variable.id, name: variable.name }
-                    tmp['isMainPost'] = variable.isMainPost === 'Y'
-                    tmp['isPrincipal'] = variable.isPrincipal === 'Y'
-                    result.push(tmp)
-                }
-                return result
-            },
-            formatRoleData() {
-                const result = []
-                const list = this.employee.roleItemList
-                if (this.$utils.isEmpty(list)) return result
-                for (const variable of list) {
-                    const tmp = { id: variable.id, name: variable.name }
-                    tmp['subSystemName'] = variable.subSystemName
-                    tmp['source'] = this.employee.id ? variable.source : '自有'
-                    tmp['canDelete'] = variable.source === '自有'
-                    result.push(tmp)
-                }
-                return result
-            },
-            formatUserGroupData() {
-                const result = []
-                const list = this.employee.userGroupItemList
-                if (this.$utils.isEmpty(list)) return result
-                for (const variable of list) {
-                    result.push({
-                        groupId: variable.id,
-                        groupName: variable.name
-                    })
-                }
-                return result
+                .catch(() => {
+                    this.dialogLoading = false;
+                });
+        },
+        formatSubmitData() {
+            const vo = {};
+            vo.partyEmployeePo = this.employee;
+            vo.user = this.employee;
+            vo.user.password =
+                this.formId === "" || this.ceroParams
+                    ? this.employee.password
+                    : this.defaultEmployee.password;
+            vo.partyEmployeePo.groupID =
+                this.ceroParams !== {} && this.ceroParams
+                    ? this.ceroParams.groundId
+                    : this.formatOrgData();
+            vo.positionVoList = this.formatPositionData();
+            vo.roleVoList = this.formatRoleData();
+            vo.attrValueVoList = this.employee.attrItemList;
+            vo.userGroupPoList = this.formatUserGroupData();
+            if (this.ceroParams !== {} && this.ceroParams) {
+                vo.partyEmployeePo.prem = this.ceroParams.prem;
             }
-        }
-    }
+            return vo;
+        },
+        formatOrgData() {
+            return this.employee.orgItem.id || "";
+        },
+        formatPositionData() {
+            const result = [];
+            const list = this.employee.posItemList;
+            if (this.$utils.isEmpty(list)) return result;
+            for (const variable of list) {
+                const tmp = { id: variable.id, name: variable.name };
+                tmp["isMainPost"] = variable.isMainPost === "Y";
+                tmp["isPrincipal"] = variable.isPrincipal === "Y";
+                result.push(tmp);
+            }
+            return result;
+        },
+        formatRoleData() {
+            const result = [];
+            const list = this.employee.roleItemList;
+            if (this.$utils.isEmpty(list)) return result;
+            for (const variable of list) {
+                const tmp = { id: variable.id, name: variable.name };
+                tmp["subSystemName"] = variable.subSystemName;
+                tmp["source"] = this.employee.id ? variable.source : "自有";
+                tmp["canDelete"] = variable.source === "自有";
+                result.push(tmp);
+            }
+            return result;
+        },
+        formatUserGroupData() {
+            const result = [];
+            const list = this.employee.userGroupItemList;
+            if (this.$utils.isEmpty(list)) return result;
+            for (const variable of list) {
+                result.push({
+                    groupId: variable.id,
+                    groupName: variable.name,
+                });
+            }
+            return result;
+        },
+    },
+};
 </script>
 <style lang="scss">
-    .employee-dialog {
-        .el-dialog__body {
-            height: calc(100% - 110px) !important;
-        }
+.employee-dialog {
+    .el-dialog__body {
+        height: calc(100% - 110px) !important;
     }
+}
 </style>