liuyanpeng 8 місяців тому
коміт
230022c452

+ 10 - 0
.babelrc

@@ -0,0 +1,10 @@
+{
+  "presets": [
+    "@babel/env",
+    "@vue/babel-preset-jsx"
+    // ["env", { "modules": false }],
+    // "stage-3", 
+    // "es2015"
+  ],
+  "plugins": ["@vue/babel-plugin-jsx"]
+}

+ 4 - 0
.eslintignore

@@ -0,0 +1,4 @@
+/Dictionary/*
+/node_modules/*
+/client-base-v5/.eslintrc.js
+/client-base-v5/.eslintignore

+ 98 - 0
.eslintrc.js

@@ -0,0 +1,98 @@
+module.exports = {
+  // 如果想要在不同的目录中使用不同的 .eslintrc, 就需要在该目录中添加如下的配置项:
+  // 告诉eslint找.eslintrc配置文件不能往父级查找
+  // root: true,
+  // 此项是用来提供插件的,插件名称省略了eslint-plugin-,下面这个配置是用来规范vue的
+  // plugins: ['vue'],
+  extends: [
+    // add more generic rulesets here, such as:
+    'eslint:recommended', // eslint推荐规则预设
+    'plugin:vue/vue3-recommended', // eslint-plugin-vue推荐的适用于vue3的规则预设
+  ],
+  parser: 'vue-eslint-parser',
+  // 自定义 parser
+  parserOptions: {
+    parser: '@babel/eslint-parser',
+    sourceType: 'module',
+  },
+  env: {
+    browser: true,
+    node: true,
+    es6: true,
+    jquery: true,
+  },
+  rules: {
+    // override/add rules settings here, such as:
+    'vue/no-unused-vars': 'error',
+    // 此规则禁用不必要的分号。
+    'no-extra-semi': 'off',
+    // 该规则强制使用一致的分号
+    semi: ['error', 'always'],
+    // 该规则强制使用一致的反勾号、双引号或单引号。
+    quotes: ['error', 'single'],
+    // 该规则旨在强制使用一致的缩进风格。默认是 4个空格。
+    indent: ['error', 2],
+    // 该规则旨在通过限制代码行的长度来提高代码的可读性和可维护性。
+    // 一行的长度为行中的 Unicode 字符的数量。
+    'max-len': ['error', { code: 185 }],
+    // 这个规则强制在对象和数组字面量中使用一致的拖尾逗号。
+    // "always-multiline" 当最后一个元素或属性与闭括号 ] 或 } 在 不同的行时,要求使用拖尾逗号;当在 同一行时,禁止使用拖尾逗号。
+    'comma-dangle': ['error', 'always-multiline'],
+    // 该规则强制箭头函数单个参数是否要使用圆括号括起来
+    // "as-needed":在可以省略括号的地方强制不使用括号
+    'arrow-parens': ['error', 'as-needed'],
+    // 此规则在单行元素的内容之前和之后强制换行。
+    'vue/singleline-html-element-content-newline': 'off',
+    // 限制每行最多能写多少个属性
+    'vue/max-attributes-per-line': 'off',
+
+    'vue/multi-word-component-names': 'off',
+    // 标签自闭合相关设置
+    'vue/html-self-closing': [
+      'warn',
+      {
+        html: {
+          void: 'always',
+          normal: 'always',
+          component: 'always',
+        },
+      },
+    ],
+
+    'no-unused-vars': [0, {
+      // function 参数未使用不检查
+      'args': 'none',
+    }],
+
+    'vue/v-on-event-hyphenation': ['warn', 'always', {
+      'autofix': true,
+      'ignore': [],
+    }],
+
+    'vue/no-unused-components': 'off',
+    'no-unused-vars': 'off',
+
+    'vue/no-parsing-error': [
+      2, 
+      { 
+        'x-invalid-end-tag': false, 
+      },
+    ],
+
+    'camelcase': [0,{
+      'properties': 'always',
+    }],
+
+  },
+  'globals': {
+    'document': true,
+    'localStorage': true,
+    'window': true,
+    'BootstrapDialog': true,
+    'gantt': true,
+    '__webpack_public_path__': true,
+    'Notify': true,
+    'Vue': true,
+    'Handsontable': true,
+  },
+};

+ 3 - 0
.gitignore

@@ -0,0 +1,3 @@
+/node_modules
+/dist
+/package-lock.json

+ 0 - 0
.gitmodules


+ 11 - 0
PcClient.code-workspace

@@ -0,0 +1,11 @@
+{
+	"folders": [
+		{
+			"path": "."
+		},
+		{
+			"path": "../Plugins"
+		}
+	],
+	"settings": {}
+}

+ 46 - 0
README.md

@@ -0,0 +1,46 @@
+# PcClient 
+
+## 项目安装
+```
+npm install
+```
+
+### 项目启动
+```
+npm run serve
+```
+
+### 项目打包
+```
+npm run build
+```
+
+### 项目发布
+```
+npm publish
+```
+
+#### 项目自身更新后的部署流程
+* 1、进入 package.json 文件中将项目版本 "version" 提升;
+* 2、进入 bat 目录,在其目录下打开 cmd;
+* 3、首先在 cmd 内执行 build.bat 命令进行打包,即 npm run build;
+* 4、其次在 cmd 内执行 publish.bat 命令进行发布,即 npm publish;
+* 5、最后在 cmd 内执行 debug.bat 命令进行测试(是否成功),即 npm run dev;
+
+#### 项目子组件库更新后的部署流程
+* 1、进入 package.json 文件中将其子组件库的项目版本提升;
+* 2、进入 bat 目录,在其目录下打开 cmd;
+* 3、首先在 cmd 内执行 install.bat 命令进行安装,即 npm install;
+* 4、其次在 cmd 内执行 debug.bat 命令进行测试(是否报错),即 npm run dev;
+* 5、再次进入 package.json 文件中将其自身版本提升;
+* 6、然后在 cmd 内执行 build.bat 命令进行打包,即 npm run build;
+* 7、接着在 cmd 内执行 publish.bat 命令进行发布,即 npm publish;
+* 8、最后再次在 cmd 内执行 debug.bat 命令进行测试(是否成功),即 npm run dev;
+
+#### 注意事项
+* 1、一定要确保子组件库部署成功后再部署其自身;
+* 2、一定要在 bat 目录下执行安装、打包、发布命令;
+* 3、一定不要忘记在项目部署时更改 package.json 里的版本(两次);
+
+### 项目版本详情
+见 [Configuration Reference](http://wuzhixin.vip:4873).

+ 6 - 0
bat/build.bat

@@ -0,0 +1,6 @@
+set current_path="%~dp0"
+cd %current_path%
+cd ..
+rmdir /s/q dist
+npm run build
+pause

+ 5 - 0
bat/debug.bat

@@ -0,0 +1,5 @@
+set current_path="%~dp0"
+cd %current_path%
+cd ..
+npm run dev
+pause

+ 5 - 0
bat/install.bat

@@ -0,0 +1,5 @@
+set current_path="%~dp0"
+cd %current_path%
+cd ..
+npm install -registry=http://wuzhixin.vip:4873 --force
+pause

+ 5 - 0
bat/publish.bat

@@ -0,0 +1,5 @@
+set current_path="%~dp0"
+cd %current_path%
+cd ..
+npm publish --registry http://wuzhixin.vip:4873/
+pause

+ 63 - 0
bug-fixed/node_modules/@ant-design/icons-vue/es/insert-css.js

@@ -0,0 +1,63 @@
+// https://github.com/substack/insert-css
+var containers = []; // will store container HTMLElement references
+
+var styleElements = []; // will store {prepend: HTMLElement, append: HTMLElement}
+
+var usage = 'insert-css: You need to provide a CSS string. Usage: insertCss(cssString[, options]).';
+
+function createStyleElement() {
+  var styleElement = document.createElement('style');
+  styleElement.setAttribute('type', 'text/css');
+  return styleElement;
+} // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
+
+
+function insertCss(css, options) {
+  options = options || {};
+
+  if (css === undefined) {
+    throw new Error(usage);
+  }
+
+  var position = options.prepend === true ? 'prepend' : 'append';
+  var container = options.container !== undefined ? options.container : document.querySelector('head');
+  var containerId = containers.indexOf(container); // first time we see this container, create the necessary entries
+
+  if (containerId === -1) {
+    containerId = containers.push(container) - 1;
+    styleElements[containerId] = {};
+  } // try to get the correponding container + position styleElement, create it otherwise
+
+
+  var styleElement;
+
+  if (styleElements[containerId] !== undefined && styleElements[containerId][position] !== undefined) {
+    styleElement = styleElements[containerId][position];
+  } else {
+    styleElement = styleElements[containerId][position] = createStyleElement();
+
+    if (position === 'prepend') {
+      // toggled by jack, violate csp
+      //container.insertBefore(styleElement, container.childNodes[0]);
+    } else {
+      container.appendChild(styleElement);
+    }
+  } // strip potential UTF-8 BOM if css was read from a file
+
+
+  if (css.charCodeAt(0) === 0xfeff) {
+    css = css.substr(1, css.length);
+  } // actually add the stylesheet
+
+
+  if (styleElement.styleSheet) {
+    // toggled by jack, violate csp
+    //styleElement.styleSheet.cssText += css;
+  } else {
+    styleElement.textContent += css;
+  }
+
+  return styleElement;
+}
+
+export default insertCss;

+ 70 - 0
bug-fixed/node_modules/@ant-design/icons-vue/lib/insert-css.js

@@ -0,0 +1,70 @@
+"use strict";
+
+Object.defineProperty(exports, "__esModule", {
+  value: true
+});
+exports["default"] = void 0;
+// https://github.com/substack/insert-css
+var containers = []; // will store container HTMLElement references
+
+var styleElements = []; // will store {prepend: HTMLElement, append: HTMLElement}
+
+var usage = 'insert-css: You need to provide a CSS string. Usage: insertCss(cssString[, options]).';
+
+function createStyleElement() {
+  var styleElement = document.createElement('style');
+  styleElement.setAttribute('type', 'text/css');
+  return styleElement;
+} // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
+
+
+function insertCss(css, options) {
+  options = options || {};
+
+  if (css === undefined) {
+    throw new Error(usage);
+  }
+
+  var position = options.prepend === true ? 'prepend' : 'append';
+  var container = options.container !== undefined ? options.container : document.querySelector('head');
+  var containerId = containers.indexOf(container); // first time we see this container, create the necessary entries
+
+  if (containerId === -1) {
+    containerId = containers.push(container) - 1;
+    styleElements[containerId] = {};
+  } // try to get the correponding container + position styleElement, create it otherwise
+
+
+  var styleElement;
+
+  if (styleElements[containerId] !== undefined && styleElements[containerId][position] !== undefined) {
+    styleElement = styleElements[containerId][position];
+  } else {
+    styleElement = styleElements[containerId][position] = createStyleElement();
+
+    if (position === 'prepend') {
+      // toggled by jack, violate csp
+      //container.insertBefore(styleElement, container.childNodes[0]);
+    } else {
+      container.appendChild(styleElement);
+    }
+  } // strip potential UTF-8 BOM if css was read from a file
+
+
+  if (css.charCodeAt(0) === 0xfeff) {
+    css = css.substr(1, css.length);
+  } // actually add the stylesheet
+
+
+  if (styleElement.styleSheet) {
+    // toggled by jack, violate csp
+    //styleElement.styleSheet.cssText += css;
+  } else {
+    styleElement.textContent += css;
+  }
+
+  return styleElement;
+}
+
+var _default = insertCss;
+exports["default"] = _default;

+ 74 - 0
package.json

@@ -0,0 +1,74 @@
+{
+  "name": "pc-client-cf",
+  "description": "Leanwo Prodog Client",
+  "version": "1.0.6-1",
+  "author": "yangzhijie1488 <yangzhijie1488@163.com>",
+  "scripts": {
+    "ins": "npm install --registry=http://wuzhixin.vip:4873 -force",
+    "dev": "cross-env webpack serve --config ./webpack.dev.js",
+    "build": "cross-env NODE_ENV=production webpack --mode=production --config ./webpack.prod.js --progress",
+    "pub": "npm publish --registry http://wuzhixin.vip:4873/"
+  },
+  "files": [
+    "package.json",
+    "dist"
+  ],
+  "dependencies": {
+    "ant-design-vue": "^4.2.1",
+    "axios": "^0.19.2",
+    "click-outside-vue3": "^4.0.1",
+    "client-base-v5": "1.0.5",
+    "client-dic-v3": "^3.0.52",
+    "client-eam-v5": "1.0.2",
+    "client-role-v3": "^3.0.26",
+    "client-sensor-v3": "^1.0.4",
+    "client-wms-v5": "1.0.0",
+    "client-finance-v3": "^0.0.4",
+    "dayjs": "^1.11.6",
+    "dingtalk-jsapi": "^2.8.33",
+    "js-cookie": "^2.2.1",
+    "lodash": "^4.17.21",
+    "pc-component-v3": "2.0.3",
+    "qrcode": "^1.5.3",
+    "select2": "^4.0.13",
+    "select2-bootstrap-theme": "^0.1.0-beta.10",
+    "uuid": "^8.3.2",
+    "v-tooltip": "^4.0.0-beta.17",
+    "vue-request": "^1.2.4",
+    "vue-select": "^4.0.0-beta.3",
+    "vuedraggable": "^4.1.0",
+    "xlsx": "^0.18.5"
+  },
+  "devDependencies": {
+    "@babel/core": "^7.17.5",
+    "@babel/eslint-parser": "^7.17.0",
+    "@babel/preset-env": "^7.16.11",
+    "@intlify/vue-i18n-loader": "^4.2.0",
+    "@vue/babel-helper-vue-jsx-merge-props": "^1.4.0",
+    "@vue/babel-plugin-jsx": "^1.1.1",
+    "@vue/babel-preset-jsx": "^1.4.0",
+    "babel-loader": "^8.2.3",
+    "clean-webpack-plugin": "^4.0.0",
+    "copy-webpack-plugin": "^11.0.0",
+    "cross-env": "^7.0.3",
+    "css-loader": "^6.7.0",
+    "eslint": "^8.10.0",
+    "eslint-plugin-vue": "^8.5.0",
+    "eslint-webpack-plugin": "^3.1.1",
+    "file-loader": "^6.2.0",
+    "html-webpack-plugin": "^5.5.0",
+    "mini-css-extract-plugin": "^2.6.0",
+    "style-loader": "^3.3.1",
+    "terser-webpack-plugin": "^5.3.6",
+    "vue-loader": "^17.0.0",
+    "webpack": "^5.70.0",
+    "webpack-cli": "^4.9.2",
+    "webpack-dev-server": "^4.7.4",
+    "webpack-merge": "^5.8.0",
+    "is-what": "^3.14.1"
+  },
+  "publishConfig": {
+    "access": "public",
+    "registry": "http://wuzhixin.vip:4873/"
+  }
+}

+ 232 - 0
public/casLogin.html

@@ -0,0 +1,232 @@
+<!DOCTYPE html>
+<html lang="en">
+  <head>
+    <meta charset="utf-8" />
+    <meta
+      name="viewport"
+      content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no"
+    />
+    <script
+      type="text/javascript"
+      src="/static/jquery/dist/jquery.min.js"
+    ></script>
+    <script
+      type="text/javascript"
+      src="/static/vue/dist/vue.global.prod.js"
+    ></script>
+    <style scoped>
+      .jumbotron {
+        margin-top: 30px;
+      }
+    </style>
+  </head>
+
+  <body>
+    <div id="app1" class="container">
+      <div class="jumbotron">
+        <h1>登录中</h1>
+        <p>{{message}}</p>
+        <p>
+          <button @click="logout()">注销</button>
+        </p>
+      </div>
+    </div>
+    <script>
+      Vue.createApp({
+        data: function () {
+          return {
+            urlRoot: "",
+            ticket: undefined,
+            message: "正在检查您的权限,请稍等...",
+            casUrl: undefined, // cas验证url
+            authSettingNo: undefined, // 标识
+            serviceUrl: undefined, // 传入后台验证地址
+            casLogoutUrl: undefined, // cas退出登录url
+            casTicketUrl: undefined, // cas Ticket检验Url
+            redirectUrl: undefined, // 登录成功后自动跳转的地址
+          };
+        },
+        mounted: function () {
+          this.urlRoot = this.getRootPath() + "/";
+          this.authSettingNo = this.getQueryString("authSettingNo");
+          this.existsCAS();
+        },
+        methods: {
+          getQueryString: function (name) {
+            const url = window.location.href;
+            const params = new URLSearchParams(url.split("?")[1]);
+            return params.get(name);
+          },
+
+          // 根据认证跳转系统对应页面
+          getTicket: function () {
+            const _self = this;
+            // 如果是从和系统不同的域名跳转进入系统,系统以prevUrl当作标识播放消息推送声音
+            let prevUrl = localStorage.getItem("#prevUrl");
+            if (!prevUrl) {
+              if (document.referrer) {
+                prevUrl = new URL(document.referrer).hostname;
+                localStorage.setItem("#prevUrl", prevUrl);
+              }
+            }
+            const redirect_uri = window.location.href;
+            _self.ticket = _self.getQueryString("ticket");
+            if (_self.ticket) {
+              // 1.判断是否包含重定向地址
+              // 2.判断后台验证登录是否成功
+              const newUrl = localStorage.getItem("#redirect_uri");
+              if (newUrl.indexOf("redirectUrl") != -1) {
+                // 存在redirectUrl地址,调用登录接口,跳转redirectUrl地址
+                _self.azureCasLogin(newUrl);
+              } else {
+                // 没有redirectUrl地址,跳转到x端(PC、Propass、App)选择界面,调用登录,authSettingNo、ticket、newUrl必须传递过去
+                const loginUrl = `${_self.urlRoot}#/casLogin?authSettingNo=${_self.authSettingNo}&ticket=${_self.ticket}&serviceUrl=${newUrl}`;
+                window.location.href = loginUrl;
+              }
+            } else {
+              localStorage.setItem("#redirect_uri", redirect_uri);
+              const casBoard = `${_self.casUrl}?service=${redirect_uri}`;
+              window.location.href = casBoard;
+            }
+          },
+
+          // 注销
+          logout: function () {
+            let _self = this;
+
+            window.location.href = _self.urlRoot;
+          },
+
+          // 单点登录
+          azureCasLogin: function (newUrl) {
+            let _self = this;
+            const params = {
+              ticket: _self.ticket,
+              redirect_uri: newUrl,
+              authSettingNo: _self.authSettingNo,
+              languageId: "zh-CN",
+            };
+            $.ajax({
+              url: _self.urlRoot + "api/CasLogin/login",
+              type: "post",
+              async: true,
+              data: params,
+              success: function (loginInfoData) {
+                if (loginInfoData.errorCode == 0) {
+                  _self.setLoginInfo(loginInfoData.data, newUrl);
+                } else {
+                  _self.message =
+                    "不好意思你的账号不在系统中,请点击【注销】按钮,登录其他账号";
+                  console.error(loginInfoData.errorMessage);
+                }
+              },
+              error: function (XMLHttpRequest, textStatus, errorThrown) {
+                console.log("服务器出错啦。");
+              },
+            });
+          },
+
+          //   获取cas参数值
+          existsCAS: function () {
+            const _self = this;
+            $.ajax({
+              url:
+                _self.urlRoot +
+                "api/CasLogin/casServiceProviderCheck?authSettingNo=" +
+                _self.authSettingNo,
+              type: "get",
+              contentType: "application/json",
+              dataType: "json",
+              success: function (response) {
+                if (response.errorCode === 0) {
+                  _self.casUrl = response.data.casUrl;
+                  _self.authSettingNo = response.data.no;
+                  _self.casLogoutUrl = response.data.casLogoutUrl;
+                  _self.getTicket();
+                } else {
+                  _self.message = response.errorMessage;
+                  console.log("错误", response.errorMessage);
+                }
+              },
+              error: function (XMLHttpRequest, textStatus, errorThrown) {
+                _self.message = "服务器出错啦。";
+                console.log(XMLHttpRequest, textStatus, errorThrown);
+              },
+            });
+          },
+          /**
+           * 获取主机地址
+           */
+          getRootPath: function () {
+            var protocol = window.location.protocol;
+            var host = window.location.host;
+            var localhostPath = protocol + "//" + host;
+            return localhostPath;
+          },
+
+          setLoginInfo: function (loginInfo, newUrl) {
+            const _self = this;
+            const prevUrl = localStorage.getItem("#prevUrl");
+            _self.clearLocalStorage();
+
+            _self.setLocalStorage(loginInfo,prevUrl);
+
+            const str = "redirectUrl=";
+            const endStart = newUrl.indexOf("redirectUrl");
+            const startIndex = endStart + str.length;
+            const endIndex = newUrl.length - 1;
+            const redirectUrl = newUrl.substring(startIndex, endIndex);
+
+            window.location.href = redirectUrl;
+          },
+
+          //  设置localStorage
+          setLocalStorage: function (loginInfo,prevUrl) {
+            localStorage.setItem("allowSound", false);
+            localStorage.setItem("#prevUrl", prevUrl);
+            localStorage.setItem("#LoginInfo", JSON.stringify(loginInfo));
+            localStorage.setItem("#token", loginInfo.token);
+            localStorage.setItem("#accountId", loginInfo.accountId);
+          },
+
+          clearLocalStorage: function () {
+            // 清理localStorage时需要保留的参数列表
+            var reserveParams = [
+              "hostPageBaseURL",
+              "workShopId",
+              "resourceInstanceId",
+              "resourceInstanceName",
+              "apsBaseUrl",
+              "cameraBaseURL",
+              "#rememberPassword",
+              "#userName",
+              "#password",
+              "#languageSelected",
+            ];
+            //存放的信息
+            var reserveParamValues = [];
+
+            //获取参数信息
+            var len = reserveParams.length;
+            for (let i = 0; i < len; i++) {
+              var reserveParam = reserveParams[i];
+              var reserveParamValue = "";
+              if (localStorage.getItem(reserveParam) != undefined) {
+                reserveParamValue = localStorage.getItem(reserveParam);
+              }
+              reserveParamValues.push(reserveParamValue);
+            }
+
+            //清理localStorage
+            window.localStorage.clear();
+
+            //还原参数信息
+            for (let i = 0; i < len; i++) {
+              localStorage.setItem(reserveParams[i], reserveParamValues[i]);
+            }
+          },
+        },
+      }).mount("#app1");
+    </script>
+  </body>
+</html>

BIN
public/favicon.ico


+ 105 - 0
public/index-debug.html

@@ -0,0 +1,105 @@
+<!DOCTYPE html>
+<html lang="en">
+
+<head>
+	<meta charset="utf-8">
+	<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" />
+	
+    <!-- hard fixed by jack 20200613 -->
+	<!-- 在部署 http 网站的时候,要把下面的一行配置注释掉 -->
+	
+	<!-- 加这个的原因是 asset.html 要访问 websocket,其中 websocket 是本地的ws不是wss,如果网页是通过https访问的,那么也要求websocket是 ws的 -->
+	<!-- 把http请求转化为https请求。这样就不会再出现Mixed Content的错误了。 
+	<meta http-equiv="Content-Security-Policy" content="upgrade-insecure-requests">-->
+	<title>prodog</title>
+
+	<link nonce="*NONCE_TOKEN_CSS*" rel="stylesheet" type="text/css" href="/static/font-awesome/css/font-awesome.min.css">
+	<!-- <link nonce="*NONCE_TOKEN_CSS*" rel="stylesheet" type="text/css" href="/static/bootstrap/dist/css/bootstrap.css">
+	<link nonce="*NONCE_TOKEN_CSS*" rel="stylesheet" type="text/css" href="/static/bootstrap/dist/css//bootstrap-theme.min.css">
+	<link nonce="*NONCE_TOKEN_CSS*" rel="stylesheet" type="text/css" href="/static/bootstrap3-dialog/dist/css/bootstrap-dialog.css"> -->
+	
+	<!-- <link rel="stylesheet" type="text/css" href="/static/dhtmlxgantt/dhtmlxgantt.css"> -->
+	<!-- <link rel="stylesheet" type="text/css" href="/static/bootstrap-treeview/bootstrap-treeview.css"> -->
+	<link nonce="*NONCE_TOKEN_CSS*" rel="stylesheet" type="text/css" href="/static/trumbowyg/css/trumbowyg.min.css">
+
+
+
+	<link nonce="*NONCE_TOKEN_CSS*" rel="stylesheet" type="text/css" href="/static/cropper/dist/cropper.css">
+	<link nonce="*NONCE_TOKEN_CSS*" rel="stylesheet" type="text/css" href="/static/colResizable/colResizable-1.6.css">
+
+	<link nonce="*NONCE_TOKEN_CSS*" rel="stylesheet" type="text/css" href="/static/jQuery-ResizableColumns/jQuery.resizableColumns.css">
+	<link nonce="*NONCE_TOKEN_CSS*" rel="stylesheet" type="text/css" href="./api/file/getThemeCss">
+
+
+
+	<script nonce="*NONCE_TOKEN*" type="text/javascript" src="/static/jquery/dist/jquery.js"></script>
+
+	<script nonce="*NONCE_TOKEN*" type="text/javascript" src="/static/jquery.cookie/jquery.cookie.js"></script>
+	<script nonce="*NONCE_TOKEN*" type="text/javascript" src="/static/table-fixer.jquery/table-fixer.jquery.js"></script>
+
+	
+	<script nonce="*NONCE_TOKEN*" type="text/javascript" src="/static/cropper/dist/cropper.js"></script>
+	<!-- <script nonce="*NONCE_TOKEN*" type="text/javascript" src="/static/bootstrap/dist/js/bootstrap.js"></script>
+	<script nonce="*NONCE_TOKEN*" type="text/javascript" src="/static/bootstrap3-dialog/dist/js/bootstrap-dialog.js"></script> -->
+	<script nonce="*NONCE_TOKEN*" type="text/javascript" src="/static/colResizable/colResizable-1.6.js"></script>
+
+	<script nonce="*NONCE_TOKEN*" defer="defer" src="/static/bootstrap-treeview/bootstrap-treeview.js"></script>
+
+	<script nonce="*NONCE_TOKEN*" type="text/javascript" src="/static/jQuery-ResizableColumns/jQuery.resizableColumns.js"></script>
+	<!-- <script src="../static/js/api.js"></script> -->
+
+
+	<script nonce="*NONCE_TOKEN*" type="text/javascript" src="/static/reconnecting-websocket/reconnecting-websocket.js"></script>
+	
+	<!-- <script nonce="*NONCE_TOKEN*" type="text/javascript" src="../static/plugin/dingtalk-jsapi/2.10.3/dingtalk.open.js"></script> -->
+
+	<!-- 富文本编辑器 -->
+	<script nonce="*NONCE_TOKEN*" type="text/javascript" src="/static/trumbowyg/js/trumbowyg.min.js"></script> 
+	<script nonce="*NONCE_TOKEN*" type="text/javascript" src="/static/trumbowyg/js/trumbowyg.upload.min.js"></script>
+	<script nonce="*NONCE_TOKEN*" type="text/javascript" src="/static/trumbowyg/js/trumbowyg.zh_cn.min.js"></script>
+
+	<!--VueJS has 2 different versions: the full version and the runtime version. 'unsafe-eval' is only needed for the full version of VueJS; the runtime version doesn't need it. 
+	The runtime-only build is fully CSP-compliant. When using the runtime-only build with Webpack + vue-loader or Browserify + vueify, your templates will be precompiled into render functions which work perfectly in CSP environments. -->
+	<script nonce="*NONCE_TOKEN*" type="text/javascript" src="/static/vue/dist/vue.global.js"></script>
+	<script nonce="*NONCE_TOKEN*" type="text/javascript" src="/static/vue-i18n/dist/vue-i18n.global.js"></script>
+	<script nonce="*NONCE_TOKEN*" type="text/javascript" src="/static/vuex/dist/vuex.global.js"></script>
+	<script nonce="*NONCE_TOKEN*" type="text/javascript" src="/static/vue-router/dist/vue-router.global.js"></script>
+	<script nonce="*NONCE_TOKEN*" type="text/javascript" src="/static/dayjs/dayjs.min.js"></script>
+	<script nonce="*NONCE_TOKEN*" type="text/javascript" src="/static/axios/dist/axios.js"></script>
+	<script nonce="*NONCE_TOKEN*" type="text/javascript" src="/static/sortablejs/Sortable.js"></script>
+	
+	<!-- <link rel="stylesheet" type="text/css" href="/static/summernote/dist/summernote.min.css"> -->
+	<link nonce="*NONCE_TOKEN_CSS*" rel="stylesheet" type="text/css" href="https://unpkg.com/@wangeditor/editor@latest/dist/css/style.css">
+
+	
+
+	
+	<script nonce="*NONCE_TOKEN*"  type="text/javascript">
+		
+		var nonce_token = "*NONCE_TOKEN*";
+	</script>
+</head>
+
+<body>
+	<div id="app">
+	</div>
+	<div id="refreshCount"></div>
+	<script defer="defer" src="/static/echarts/dist/echarts.min.js"></script>
+	
+
+	<!-- <script defer="defer" type="text/javascript" src="/static/summernote/dist/summernote.min.js"></script>
+	<script defer="defer" type="text/javascript" src="/static/summernote/dist/lang/summernote-zh-CN.min.js"></script> -->
+
+	<!-- <script defer="defer" type="text/javascript" src="/static/dhtmlxgantt/dhtmlxgantt.js"></script>
+	<script defer="defer" type="text/javascript" src="/static/dhtmlxgantt/locale/locale_cn.js"></script>
+	<script defer="defer" type="text/javascript" src="/static/dhtmlxgantt/ext/dhtmlxgantt_auto_scheduling.js"></script>
+	<script defer="defer" type="text/javascript" src="/static/dhtmlxgantt/ext/dhtmlxgantt_smart_rendering.js"></script>
+	<script defer="defer" type="text/javascript" src="/static/dhtmlxgantt/ext/dhtmlxgantt_undo.js"></script>
+	<script defer="defer" type="text/javascript" src="/static/dhtmlxgantt/ext/dhtmlxgantt_fullscreen.js"></script>
+	<script defer="defer" type="text/javascript" src="/static/dhtmlxgantt/ext/api.js"></script> -->
+	<!-- <script src="../static/js/fullscreen-api.js"></script> -->
+	<!-- <script src="../static/js/problem-feedback-api.js"></script> -->
+
+</body>
+
+</html>

+ 99 - 0
public/index-release.html

@@ -0,0 +1,99 @@
+<!DOCTYPE html>
+<html lang="en">
+
+<head>
+	<meta charset="utf-8">
+	<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" />
+	
+    <!-- hard fixed by jack 20200613 -->
+	<!-- 在部署 http 网站的时候,要把下面的一行配置注释掉 -->
+	
+	<!-- 加这个的原因是 asset.html 要访问 websocket,其中 websocket 是本地的ws不是wss,如果网页是通过https访问的,那么也要求websocket是 ws的 -->
+	<!-- 把http请求转化为https请求。这样就不会再出现Mixed Content的错误了。 
+	<meta http-equiv="Content-Security-Policy" content="upgrade-insecure-requests">-->
+	<title>prodog</title>
+
+	<link nonce="*NONCE_TOKEN_CSS*" rel="stylesheet" type="text/css" href="/static/font-awesome/css/font-awesome.min.css">
+	<!-- <link nonce="*NONCE_TOKEN_CSS*" rel="stylesheet" type="text/css" href="/static/bootstrap/dist/css/bootstrap.min.css">
+	<link nonce="*NONCE_TOKEN_CSS*" rel="stylesheet" type="text/css" href="/static/bootstrap/dist/css//bootstrap-theme.min.css">
+	<link nonce="*NONCE_TOKEN_CSS*" rel="stylesheet" type="text/css" href="/static/bootstrap3-dialog/dist/css/bootstrap-dialog.min.css"> -->
+	
+	<!-- <link rel="stylesheet" type="text/css" href="/static/dhtmlxgantt/dhtmlxgantt.css"> -->
+	<!-- <link rel="stylesheet" type="text/css" href="/static/bootstrap-treeview/bootstrap-treeview.css"> -->
+
+	<link nonce="*NONCE_TOKEN_CSS*" rel="stylesheet" type="text/css" href="/static/trumbowyg/css/trumbowyg.min.css">
+
+	<link nonce="*NONCE_TOKEN_CSS*" rel="stylesheet" type="text/css" href="/static/cropper/dist/cropper.css">
+	<link nonce="*NONCE_TOKEN_CSS*" rel="stylesheet" type="text/css" href="/static/colResizable/colResizable-1.6.css">
+
+	<link nonce="*NONCE_TOKEN_CSS*" rel="stylesheet" type="text/css" href="/static/jQuery-ResizableColumns/jQuery.resizableColumns.css">
+	<link nonce="*NONCE_TOKEN_CSS*" rel="stylesheet" type="text/css" href="./api/file/getThemeCss">
+
+
+
+	<script nonce="*NONCE_TOKEN*" type="text/javascript" src="/static/jquery/dist/jquery.min.js"></script>
+
+	<script nonce="*NONCE_TOKEN*" type="text/javascript" src="/static/table-fixer.jquery/table-fixer.jquery.js"></script>
+
+	
+	<script nonce="*NONCE_TOKEN*" type="text/javascript" src="/static/cropper/dist/cropper.min.js"></script>
+	<!-- <script nonce="*NONCE_TOKEN*" type="text/javascript" src="/static/bootstrap/dist/js/bootstrap.min.js"></script>
+	<script nonce="*NONCE_TOKEN*" type="text/javascript" src="/static/bootstrap3-dialog/dist/js/bootstrap-dialog.min.js"></script> -->
+	<script nonce="*NONCE_TOKEN*" type="text/javascript" src="/static/colResizable/colResizable-1.6.js"></script>
+
+	<script defer="defer" src="/static/bootstrap-treeview/bootstrap-treeview.js"></script>
+
+	<script nonce="*NONCE_TOKEN*" type="text/javascript" src="/static/jQuery-ResizableColumns/jQuery.resizableColumns.js"></script>
+	<!-- <script src="../static/js/api.js"></script> -->
+
+
+	<script nonce="*NONCE_TOKEN*" type="text/javascript" src="/static/reconnecting-websocket/reconnecting-websocket.js"></script>
+	
+	<!-- <script nonce="*NONCE_TOKEN*" type="text/javascript" src="../static/plugin/dingtalk-jsapi/2.10.3/dingtalk.open.js"></script> -->
+
+	<!-- 富文本编辑器 -->
+	<script nonce="*NONCE_TOKEN*" type="text/javascript" src="/static/trumbowyg/js/trumbowyg.min.js"></script> 
+	<script nonce="*NONCE_TOKEN*" type="text/javascript" src="/static/trumbowyg/js/trumbowyg.upload.min.js"></script>
+	<script nonce="*NONCE_TOKEN*" type="text/javascript" src="/static/trumbowyg/js/trumbowyg.zh_cn.min.js"></script>
+
+
+	<!--VueJS has 2 different versions: the full version and the runtime version. 'unsafe-eval' is only needed for the full version of VueJS; the runtime version doesn't need it. 
+	The runtime-only build is fully CSP-compliant. When using the runtime-only build with Webpack + vue-loader or Browserify + vueify, your templates will be precompiled into render functions which work perfectly in CSP environments. -->
+	<script nonce="*NONCE_TOKEN*" type="text/javascript" src="/static/vue/dist/vue.global.prod.js"></script>
+	<script nonce="*NONCE_TOKEN*" type="text/javascript" src="/static/vue-i18n/dist/vue-i18n.global.prod.js"></script>
+	<script nonce="*NONCE_TOKEN*" type="text/javascript" src="/static/vuex/dist/vuex.global.prod.js"></script>
+	<script nonce="*NONCE_TOKEN*" type="text/javascript" src="/static/vue-router/dist/vue-router.global.prod.js"></script>
+	<script nonce="*NONCE_TOKEN*" type="text/javascript" src="/static/dayjs/dayjs.min.js"></script>
+	<script nonce="*NONCE_TOKEN*" type="text/javascript" src="/static/axios/dist/axios.min.js"></script>
+	<script nonce="*NONCE_TOKEN*" type="text/javascript" src="/static/sortablejs/Sortable.min.js"></script>
+	
+	<!-- <link rel="stylesheet" type="text/css" href="/static/summernote/dist/summernote.min.css"> -->
+	
+	<script nonce="*NONCE_TOKEN*"  type="text/javascript">
+		var nonce_token = "*NONCE_TOKEN*";
+	</script>
+</head>
+
+<body>
+	<div id="app">
+	</div>
+	<div id="refreshCount"></div>
+	<script defer="defer" nonce="*NONCE_TOKEN*"  src="/static/echarts/dist/echarts.min.js"></script>
+
+	<!-- <script src="../static/js/fullscreen-api.js"></script> -->
+	<!-- <script src="../static/js/problem-feedback-api.js"></script> -->
+	
+	<!-- <script defer="defer" nonce="*NONCE_TOKEN*" type="text/javascript" src="/static/summernote/dist/summernote.min.js"></script>
+	<script defer="defer" nonce="*NONCE_TOKEN*" type="text/javascript" src="/static/summernote/dist/lang/summernote-zh-CN.min.js"></script> -->
+
+	<!-- <script defer="defer" nonce="*NONCE_TOKEN*" type="text/javascript" src="/static/dhtmlxgantt/dhtmlxgantt.js"></script>
+	<script defer="defer" nonce="*NONCE_TOKEN*" type="text/javascript" src="/static/dhtmlxgantt/locale/locale_cn.js"></script>
+	<script defer="defer" nonce="*NONCE_TOKEN*" type="text/javascript" src="/static/dhtmlxgantt/ext/dhtmlxgantt_auto_scheduling.js"></script>
+	<script defer="defer" nonce="*NONCE_TOKEN*" type="text/javascript" src="/static/dhtmlxgantt/ext/dhtmlxgantt_smart_rendering.js"></script>
+	<script defer="defer" nonce="*NONCE_TOKEN*" type="text/javascript" src="/static/dhtmlxgantt/ext/dhtmlxgantt_undo.js"></script>
+	<script defer="defer" nonce="*NONCE_TOKEN*" type="text/javascript" src="/static/dhtmlxgantt/ext/dhtmlxgantt_fullscreen.js"></script>
+	<script defer="defer" nonce="*NONCE_TOKEN*" type="text/javascript" src="/static/dhtmlxgantt/ext/api.js"></script> -->
+
+</body>
+
+</html>

+ 162 - 0
public/oalogin.html

@@ -0,0 +1,162 @@
+<!DOCTYPE html>
+<html lang="en">
+  <head>
+    <meta charset="utf-8" />
+    <meta
+      name="viewport"
+      content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no"
+    />
+  </head>
+
+  <body>
+    <div id="app1" class="container">
+      <div style="margin-top: 30px">
+        <h1>登录中</h1>
+        <p>{{ message }}</p>
+      </div>
+    </div>
+    <script
+      type="text/javascript"
+      src="/static/jquery/dist/jquery.min.js"
+    ></script>
+    <script
+      type="text/javascript"
+      src="/static/vue/dist/vue.global.prod.js"
+    ></script>
+    <script>
+      Vue.createApp({
+        data: function () {
+          return {
+            userId: undefined, //用户ID
+            clientId: undefined, //公司ID
+            userName: undefined, //用户姓名
+            checkCode: undefined, // 校验码
+            loginDateMs: undefined, //当前登录时间
+            message: "正在检查您的权限,请稍等...",
+            urlRoot: "",
+          };
+        },
+        mounted: function () {
+          this.urlRoot = this.getRootPath() + "/";
+          this.getParams();
+        },
+        methods: {
+          // 获取参数后登录
+          getParams: function () {
+            var _self = this;
+            const url = window.location.href
+            const params = _self.getQueryString(url)
+            _self.userId = params.userId;
+            _self.userName = params.userName;
+            _self.clientId = params.clientId;
+            _self.checkCode = params.checkCode;
+            _self.loginDateMs = params.loginDateMs;
+            this.azureSamlLogin();
+          },
+
+          // 单点登录
+          azureSamlLogin: function () {
+            let _self = this;
+            var loginData = {
+              userId: _self.userId,
+              userName: _self.userName,
+              clientId: _self.clientId,
+              checkCode: _self.checkCode,
+              loginDateMs: _self.loginDateMs,
+            };
+            $.ajax({
+              url: "authApi/LoginResource/loginPoint",
+              type: "post",
+              data: loginData,
+              success: function (loginInfo) {
+                if (loginInfo.errorCode == 0) {
+                  _self.setTokenClient();
+                  _self.setLoginInfo(loginInfo.data);
+                } else {
+                  _self.message = loginInfo.errorMessage;
+                }
+              },
+              error: function (XMLHttpRequest, textStatus, errorThrown) {},
+            });
+          },
+          // 设置LoginInfo
+          setLoginInfo: function (loginInfo) {
+            var _self = this;
+            _self.clearLocalStorage();
+            localStorage.setItem("#token", loginInfo.token);
+            localStorage.setItem("#accountId", loginInfo.accountId);
+            localStorage.setItem("#LoginInfo", JSON.stringify(loginInfo));
+            window.location.href = _self.urlRoot + "#/desktop/dashboard";
+          },
+
+          // 获取参数函数
+          getQueryString: function (url) {
+            let urlStr = url.split("?")[1];
+            const urlSearchParams = new URLSearchParams(urlStr);
+            const result = Object.fromEntries(urlSearchParams.entries());
+            return result;
+          },
+
+          // 获取主机地址
+          getRootPath: function () {
+            var protocol = window.location.protocol;
+            var host = window.location.host;
+            var localhostPath = protocol + "//" + host;
+            return localhostPath;
+          },
+
+          // 设置TokenClient
+          setTokenClient: function () {
+            var _self = this;
+            $.ajax({
+              url: "TokenClientResource/saveTokenClient",
+              type: "post",
+              contentType: "application/json",
+              beforeSend: function (request) {
+                var token = localStorage.getItem("#token");
+                var account = localStorage.getItem("#accountId");
+                request.setRequestHeader("account", account);
+                request.setRequestHeader("token", token);
+              },
+              success: function (data) {},
+              error: function (XMLHttpRequest, textStatus, errorThrown) {},
+            });
+          },
+          // 清理localStorage
+          clearLocalStorage: function () {
+            // 需要保留的参数列表
+            var reserveParams = [
+              "hostPageBaseURL",
+              "workShopId",
+              "resourceInstanceId",
+              "resourceInstanceName",
+              "apsBaseUrl",
+              "cameraBaseURL",
+            ];
+            //存放的信息
+            var reserveParamValues = [];
+
+            //获取参数信息
+            var len = reserveParams.length;
+            for (let i = 0; i < len; i++) {
+              var reserveParam = reserveParams[i];
+              var reserveParamValue = "";
+              if (localStorage.getItem(reserveParam) != undefined) {
+                reserveParamValue = localStorage.getItem(reserveParam);
+              }
+              reserveParamValues.push(reserveParamValue);
+            }
+
+            //清理localStorage
+            window.localStorage.clear();
+
+            //还原参数信息
+            for (let i = 0; i < len; i++) {
+              localStorage.setItem(reserveParams[i], reserveParamValues[i]);
+            }
+          },
+        },
+      }).mount("#app1");
+    </script>
+  </body>
+</html>

+ 153 - 0
public/ssoLogin.html

@@ -0,0 +1,153 @@
+<!DOCTYPE html>
+<html lang="en">
+  <head>
+    <meta charset="utf-8" />
+    <meta
+      name="viewport"
+      content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no"
+    />
+  </head>
+
+  <body>
+    <div id="app1" class="container">
+      <div style="margin-top: 30px">
+        <h1>登录中</h1>
+        <p>{{ message }}</p>
+      </div>
+    </div>
+    <script
+      type="text/javascript"
+      src="/static/jquery/dist/jquery.min.js"
+    ></script>
+    <script
+      type="text/javascript"
+      src="/static/vue/dist/vue.global.prod.js"
+    ></script>
+    <script>
+      Vue.createApp({
+        data: function () {
+          return {
+            token: "",
+            urlRoot: "",
+            languageId: "zh-CN",
+            message: "正在检查您的权限,请稍等...",
+          };
+        },
+        mounted: function () {
+          this.urlRoot = this.getRootPath() + "/";
+          this.getParams();
+        },
+        methods: {
+          // 获取参数后登录
+          getParams: function () {
+            var _self = this;
+            const url = window.location.href;
+            const params = _self.getQueryString();
+            _self.token = params.token;
+            this.azureSamlLogin();
+          },
+
+          // 单点登录
+          azureSamlLogin: function () {
+            const _self = this;
+            const params = {
+              token:_self.token,
+              languageId:_self.languageId,
+            }
+            $.ajax({
+              url: _self.urlRoot + `api/SsoResource/login`,
+              type: "post",
+              data:params,
+              success: function (loginInfo) {
+                if (loginInfo.errorCode == 0) {
+                  _self.setLoginInfo(loginInfo.data);
+                } else {
+                  _self.message = loginInfo.errorMessage;
+                }
+              },
+              error: function (XMLHttpRequest, textStatus, errorThrown) {},
+            });
+          },
+          // 设置LoginInfo
+          setLoginInfo: function (loginInfo) {
+            var _self = this;
+            _self.clearLocalStorage();
+            localStorage.setItem("#token", loginInfo.token);
+            localStorage.setItem("#accountId", loginInfo.accountId);
+            localStorage.setItem("#languageSelected", _self.languageId);
+            localStorage.setItem("#LoginInfo", JSON.stringify(loginInfo));
+			if (_self.isMobile() === false) {
+              localStorage.setItem('allowSound', false);
+              window.location.href = _self.urlRoot + "#/desktop/dashboard";
+            } else  {
+              window.location.href = _self.urlRoot + "app.html#/desktop/appMenu";
+            }
+            //window.location.href = _self.urlRoot + "#/desktop/dashboard";
+          },
+		  
+		   /**
+			* 判断当前的环境是手机端还是电脑端
+			*/
+		isMobile: function () {
+			if (window.navigator.userAgent.match(/(phone|pad|pod|iPhone|iPod|ios|iPad|Android|Mobile|BlackBerry|IEMobile|MQQBrowser|JUC|Fennec|wOSBrowser|BrowserNG|WebOS|Symbian|Windows Phone)/i)) {
+				return true; // 移动端
+			} else {
+				return false; // PC端
+			}
+		},
+
+          // 获取参数函数
+          getQueryString: function () {
+            const url = window.location.href;
+            const urlStr = url.split("?")[1];
+            const urlSearchParams = new URLSearchParams(urlStr);
+            const result = Object.fromEntries(urlSearchParams.entries());
+            return result;
+          },
+
+          // 获取主机地址
+          getRootPath: function () {
+            var protocol = window.location.protocol;
+            var host = window.location.host;
+            var localhostPath = protocol + "//" + host;
+            return localhostPath;
+          },
+
+          // 清理localStorage
+          clearLocalStorage: function () {
+            // 需要保留的参数列表
+            var reserveParams = [
+              "hostPageBaseURL",
+              "workShopId",
+              "resourceInstanceId",
+              "resourceInstanceName",
+              "apsBaseUrl",
+              "cameraBaseURL",
+            ];
+            //存放的信息
+            var reserveParamValues = [];
+
+            //获取参数信息
+            var len = reserveParams.length;
+            for (let i = 0; i < len; i++) {
+              var reserveParam = reserveParams[i];
+              var reserveParamValue = "";
+              if (localStorage.getItem(reserveParam) != undefined) {
+                reserveParamValue = localStorage.getItem(reserveParam);
+              }
+              reserveParamValues.push(reserveParamValue);
+            }
+
+            //清理localStorage
+            window.localStorage.clear();
+
+            //还原参数信息
+            for (let i = 0; i < len; i++) {
+              localStorage.setItem(reserveParams[i], reserveParamValues[i]);
+            }
+          },
+        },
+      }).mount("#app1");
+    </script>
+  </body>
+</html>

+ 369 - 0
src/custom/common/Common.js

@@ -0,0 +1,369 @@
+import { DownloadService } from 'pc-component-v3';
+
+
+export default {
+  pageSize: 20,
+
+
+  // 异常处理
+  processException: function (XMLHttpRequest, textStatus, errorThrown) {
+    var _self = this;
+    console.log(XMLHttpRequest);
+    if (XMLHttpRequest.status == 400) {
+      // 400 Bad Request
+      Notify.error('400', XMLHttpRequest.responseText, true);
+    } else if (XMLHttpRequest.status == 401) {
+      var currentUrl = window.location;
+      var href = window.location.href;
+      // 当前未处于登陆的界面
+      // 系统未登录
+      if (href.indexOf('login') < 0 && href.indexOf('redirectUrl=') < 0) {
+        // 处理钉钉免登陆
+        const clientId = this.getRouteParam('clientId');
+        const appName = this.getRouteParam('appName');
+        const corpId = this.getRouteParam('corpId');
+
+        let newUrl;
+        if (clientId != null && clientId.length > 0 && appName != null && appName.length > 0 && corpId != null && corpId.length > 0) {
+          newUrl = _self.getRedirectUrl('#/login?clientId=' + clientId + '&appName=' + appName + '&corpId=' + corpId + '&redirectUrl=' + encodeURIComponent(currentUrl));
+        } else {
+          newUrl = _self.getRedirectUrl('#/login?redirectUrl=' + encodeURIComponent(currentUrl));
+        }
+        window.location = newUrl;
+      }
+    } else if (XMLHttpRequest.status == 500) {
+      // 500 Internal Server Error
+      Notify.error('500', XMLHttpRequest.responseText, true);
+      if (XMLHttpRequest.responseText.indexOf('登录超时') > 0) {
+        // 如果异常信息包含“登录超时”,则2秒后跳转到登录页面
+        setTimeout(function () {
+          window.location = _self.getRedirectUrl('#/login');
+        }, 2 * 1000);
+      }
+    } else {
+      Notify.error('服务器异常', XMLHttpRequest.responseText, true);
+    }
+  },
+
+
+  /**
+   * 获取主机地址
+   */
+  getRootPath: function () {
+    var protocol = window.location.protocol;
+    // console.log('protocol:' + protocol);
+    var host = window.location.host;
+    // console.log('host:' + host);
+    var localhostPaht = protocol + '//' + host;
+    // console.log('localhostPaht:' + localhostPaht);
+    return localhostPaht;
+  },
+
+  getHostPageBaseURL: function () {
+    if (typeof REMOTE_DEV_PORT !== 'undefined' && REMOTE_DEV_PORT != null) {
+      return this.getRootPath() + '/proxy/' + REMOTE_DEV_PORT;
+    } else {
+      return this.getRootPath();
+    }
+  },
+
+
+  // 获取API的地址
+  getApiURL: function (apiName) {
+    if (apiName.startsWith('/')) {
+      return this.getHostPageBaseURL() + '/api' + apiName;
+    } else {
+      return this.getHostPageBaseURL() + '/api/' + apiName;
+    }
+  },
+
+  /**
+   * 获取API的地址 直接拼接
+   * @param {*} apiName 
+   * @returns 
+   */
+  getApiUrl2: function (apiName) {
+    if (apiName.startsWith('/')) {
+      return this.getHostPageBaseURL() + apiName;
+    } else {
+      return this.getHostPageBaseURL() + '/' + apiName;
+    }
+  },
+
+
+  // 获取图片路径
+  getImageUrl: function (imageName) {
+    if (imageName == null || imageName == '') {
+      return this.getHostPageBaseURL() + 'notFound.png';
+    } else {
+      return this.getHostPageBaseURL() + imageName;
+    }
+  },
+
+  // 获取图片路径
+  getImageSrc: function (className, imageName) {
+    if (imageName == null) {
+      return null;
+    }
+    return this.getHostPageBaseURL() + '/api/file/imageDownload?className=' + className + '&fileName=' + imageName;
+  },
+
+
+  // 获取略缩图图片路径
+  getThumbnailImageSrc: function (className, imageName) {
+    if (imageName == null) {
+      return null;
+    }
+    return this.getHostPageBaseURL() + '/api/file/thumbnailImageDownload?className=' + className + '&fileName=' + imageName;
+  },
+
+
+  /**
+   * 获取附件的路径
+   * @param  {[type]} className [description]
+   * @param  {[type]} imageName [description]
+   * @return {[type]}           [description]
+   */
+  getAttachmentsSrc: function (className, imageName) {
+    var accountId = localStorage.getItem('#accountId');
+    return this.getHostPageBaseURL() + 'Files/' + accountId + '/Attachments/' + className + '/' + imageName;
+  },
+
+  // 获取图片路径
+  getVideoSrc: function (className, imageName) {
+    var accountId = localStorage.getItem('#accountId');
+    if (imageName == undefined || imageName == '') {
+      return this.getHostPageBaseURL() + 'static/image/noImage.jpg';
+    }
+
+    return this.getHostPageBaseURL() + 'Files/' + accountId + '/Video/' + className + '/' + imageName;
+  },
+
+
+  //获取资源路径   type: 图片image,视频video,文件file,
+  getResourceUrl: function (type, className, resourceName) {
+    var accountId = localStorage.getItem('#accountId');
+    if (resourceName == undefined || className == undefined || type == undefined || resourceName == '' || className == '' || type == '') {
+      return;
+    }
+    if (type == 'image') {
+      return this.getHostPageBaseURL() + '/Files/' + accountId + '/Images/' + className + '/' + resourceName;
+    }
+    if (type == 'video') {
+      return this.getHostPageBaseURL() + '/Files/' + accountId + '/Video/' + className + '/' + resourceName;
+    }
+    if (type == 'file') {
+      return this.getHostPageBaseURL() + '/Files/' + accountId + '/Files/' + className + '/' + resourceName;
+    }
+
+  },
+  // 后台接口返回的数据带className使用
+  getResourceUrl1: function (type, resourceName) {
+    var accountId = localStorage.getItem('#accountId');
+    if (resourceName == undefined || type == undefined || resourceName == '' || type == '') {
+      return;
+    }
+    if (type == 'image') {
+      return this.getHostPageBaseURL() + '/Files/' + accountId + '/Images/' + resourceName;
+    }
+    if (type == 'video') {
+      return this.getHostPageBaseURL() + '/Files/' + accountId + '/Video/' + resourceName;
+    }
+    if (type == 'file') {
+      return this.getHostPageBaseURL() + '/Files/' + accountId + '/Files/' + resourceName;
+    }
+
+  },
+
+
+
+  //设置路径到localStorage
+  setHref: function () {
+    var href = window.location.href;
+    if (href.indexOf('http') == 0) {
+      href = href.substring(0, href.indexOf('#') + 2);
+      localStorage.setItem('href', href);
+    } else {
+      var hostPageBaseURL = localStorage.getItem('hostPageBaseURL');
+      if (hostPageBaseURL == undefined) {
+        href = href.substring(0, href.indexOf('#') + 2);
+        localStorage.setItem('href', href);
+      }
+    }
+  },
+
+  //加载系统参数到localStorage
+  loadSystemParam: function (systemParamName, success) {
+    var that = this;
+    $.ajax({
+      url: that.getApiURL('SystemParamResource/loadSystemParam'),
+      type: 'GET',
+      dataType: 'text',
+      data: {
+        'systemParamName': systemParamName,
+      },
+      beforeSend: function (request) {
+        that.addTokenToRequest(request);
+      },
+      success: function (data) {
+        localStorage.setItem(systemParamName, data);
+        success();
+      },
+      error: function (XMLHttpRequest, textStatus, errorThrown) {
+        that.processException(XMLHttpRequest, textStatus, errorThrown);
+      },
+    });
+  },
+
+  // 给请求头中加上account和token信息
+  addTokenToRequest: function (request) {
+    // request.setRequestHeader('#accountId', localStorage.getItem('#accountId'));
+    request.setRequestHeader('token', localStorage.getItem('#token'));
+  },
+
+  /**
+   * 获取Token
+   */
+  getToken: function () {
+    return localStorage.getItem('#token');
+  },
+
+  // 获取新建对象的Id
+  getNewRecordId: function () {
+    window.CRUDId++;
+    return window.CRUDId;
+  },
+
+  // 清空 Cookie
+  clearCookie: function () {
+    // eslint-disable-next-line
+    var keys = document.cookie.match('/[^ =;]+(?=\=)/g');
+    if (keys) {
+      for (var i = keys.length; i--;) {
+        // 清除当前域名路径的有限日期
+        document.cookie = keys[i] + '=0;path=/;expires=' + new Date(0).toUTCString();
+        // Domain Name域名 清除当前域名的
+        document.cookie = keys[i] + '=0;path=/;domain=' + document.domain + ';expires=' + new Date(0).toUTCString();
+        // 清除一级域名下的或指定的
+        document.cookie = keys[i] + '=0;path=/;domain=baidu.com;expires=' + new Date(0).toUTCString();
+      }
+    }
+  },
+  // 清空 Cookie
+  clearAppCookie: function (loginInfo) {
+    document.cookie.split(';').forEach(function (c) {
+      document.cookie = c.replace(/^ +/, '').replace(/=.*/, '=;expires=' + new Date().toUTCString() + ';path=/');
+    });
+    // $.removeCookie('token', { path: '/' });
+    // $.removeCookie('token', { path: '/app' });
+    // $.cookie('token', loginInfo.token, {
+    //   expires: 7,
+    //   path: '/',
+    //   secure: true,
+    //   sameSite: 'Strict',
+    // });
+  },
+  clearLocalStorage: function (isClearWorkTabs) {
+    // 清理localStorage时需要保留的参数列表
+    var reserveParams = ['hostPageBaseURL', 'workShopId', 'resourceInstanceId',
+      'resourceInstanceName', 'apsBaseUrl', 'cameraBaseURL', '#rememberPassword', '#userName', '#password', '#languageSelected'];
+    if (!isClearWorkTabs) reserveParams.push('workTabs');
+    //存放的信息
+    var reserveParamValues = [];
+
+    //获取参数信息 
+    var len = reserveParams.length;
+    for (let i = 0; i < len; i++) {
+      var reserveParam = reserveParams[i];
+      var reserveParamValue = '';
+      if (localStorage.getItem(reserveParam) != undefined) {
+        reserveParamValue = localStorage.getItem(reserveParam);
+      }
+      reserveParamValues.push(reserveParamValue);
+    }
+
+    //清理localStorage
+    window.localStorage.clear();
+
+    //还原参数信息
+    for (let i = 0; i < len; i++) {
+      localStorage.setItem(reserveParams[i], reserveParamValues[i]);
+    }
+
+  },
+
+  showDialog: function (title, content, type) {
+    if (type == 'success') {
+      Notify.success(title, content, 4000);
+    }
+    else if (type == 'error') {
+      Notify.error(title, content, -1);
+    }
+    else if (type == 'info') {
+      Notify.info(title, content, 2000);
+    }
+    else if (type == 'notice') {
+      Notify.notice(title, content, 2000);
+    }
+  },
+
+
+  // 获取路由中的参数
+  getRouteParam: function (name) {
+    var reg = new RegExp('(^|\\?|&)' + name + '=([^&]*)(\\s|&|$)', 'i');
+    if (reg.test(location.href)) return unescape(RegExp.$2.replace(/\+/g, ' '));
+    return '';
+  },
+
+  /**
+   * 获取跳转的路径
+   * @param {*} url 
+   */
+  getRedirectUrl: function (url) {
+    var href = window.location.href;
+    if (href.indexOf('pcapp') >= 0) {
+      return this.getHostPageBaseURL() + '/pcapp/' + url;
+    } else {
+      return this.getHostPageBaseURL() + '/' + url;
+    }
+  },
+
+  /**
+   * 函数防抖
+   * 在事件被触发n秒后再执行回调,如果在这n秒内又被触发,则重新计时。
+   * @param {*} fn 
+   * @param {*} delay 
+   * @returns 
+   */
+  debounce: function (fn, delay) {
+    var timer; // 维护一个 timer
+    return function () {
+      var _this = this; // 取debounce执行作用域的this
+      var args = arguments;
+      if (timer) {
+        clearTimeout(timer);
+      }
+      timer = setTimeout(function () {
+        fn.apply(_this, args); // 用apply指向调用debounce的对象,相当于_this.fn(args);
+      }, delay);
+    };
+  },
+
+  // trumbowyg 查看内容时通过对应的a标签进行附件下载
+  downloadByA: function (element) {
+    const contents = document.querySelectorAll(element);
+    if (!contents.length) return;
+    contents.forEach(content => {
+      content.addEventListener('click', function (e) {
+        const target = e.target;
+        if (target && target.classList && target.classList.contains('trumbowyg-attachment-link')) {
+          e.preventDefault();
+          const fileName = target.getAttribute('file-name');
+          const className = target.getAttribute('class-name');
+          DownloadService.fileDownload(className, fileName);
+        }
+      });
+    });
+  },
+};
+

+ 273 - 0
src/custom/common/CommonTable.vue

@@ -0,0 +1,273 @@
+<template>
+  <div class="tablePaganations">
+    <!-- <a-config-provider :locale="locale"> -->
+    <a-table
+      id="commonTable"
+      class="ant-table-striped"
+      bordered
+      size="small"
+      height="1000px"
+      :loading="isLoading"
+      :data-source="dataSource"
+      :columns="columns"
+      :row-key="(record) => record.id"
+      :scroll="{ y: yScroll }"
+      :pagination="havePage ? pagination : false"
+      :row-class-name="
+        (_record, index) => (index % 2 === 1 ? 'table-striped' : null)
+      "
+      :row-selection="
+        isSelect
+          ? {
+            selectedRowKeys: state.selectedRowKeys,
+            onSelect: selectEvent,
+            onSelectAll: selectAllEvent,
+          }
+          : null
+      "
+      @change="tableChange"
+      @resize-column="handleResizeColumn"
+    >
+      <template
+        v-for="(item, index) in renderArr"
+        #[item]="scope"
+        :key="index"
+      >
+        <slot :name="item" :scope="scope" v-bind="scope || {}" />
+      </template>
+    </a-table>
+    <!-- </a-config-provider> -->
+  </div>
+</template>
+  
+<script setup>
+import {
+  useSlots,
+  ref,
+  reactive,
+  defineProps,
+  defineEmits,
+  defineExpose,
+  watch,
+  onMounted,
+} from 'vue';
+import { getTableScroll } from './tableScroll.js';
+// import zhCN from 'ant-design-vue/lib/locale-provider/zh_CN';
+// const locale = ref(zhCN);
+
+const props = defineProps({
+  // 表格数据
+  dataSource: {
+    type: Object,
+    required: true,
+  },
+  // 表头数据
+  columns: {
+    type: Object,
+    required: true,
+  },
+  // 是否可选择
+  isSelect: {
+    type: Boolean,
+  },
+  // 表格loading
+  isLoading: {
+    type: Boolean,
+  },
+  // 数据总数
+  total: {
+    type: Number,
+    default: 0,
+  },
+  // 是否分页
+  havePage: {
+    type: Boolean,
+    default: true,
+  },
+  // 分页在右上角
+  topRight: {
+    type: Boolean,
+    default: false,
+  },
+  // 表格距底部高度
+  extraHeight: {
+    type: Number,
+    default: undefined,
+  },
+  // 选择的key值
+  selectedKeys: {
+    type: Array,
+    default: () => [],
+  },
+});
+
+const emit = defineEmits(['getPager', 'getSorter', 'getSelected']);
+
+// 分页配置
+const pagination = reactive({
+  showQuickJumper: true,
+  current: 1,
+  pageSize: 20, // 默认每页显示数量
+  showSizeChanger: true, // 显示可改变每页数量
+  pageSizeOptions: ['10', '20', '50', '100', '200', '500'], // 每页数量选项值
+  showTotal: (total, range) =>
+    range[0] + '-' + range[1] + '条' + ' 共' + total + '条', // 显示总数
+  onShowSizeChange: (current, pageSize) => showSizeChange(current, pageSize),
+  onChange: (current, pageSize) => changePage(current, pageSize), //点击页码事件
+  total: props.total,
+  position:props.topRight ? ['topRight'] : ['bottomRight'],
+});
+
+const yScroll = ref(400); //默认滚动高度
+const extraHeight = ref(undefined); //表格距离底部值
+
+// 最后一次排序信息
+const lastSorter = reactive({ field: '', order: '' });
+
+//  选择的数据
+const state = reactive({
+  selectedRows: [],
+  selectedRowKeys: [],
+});
+
+onMounted(() => {
+  if (!props.havePage) {
+    extraHeight.value = 30;
+  } else {
+    extraHeight.value = props.extraHeight;
+  }
+  if(props.extraHeight){
+    extraHeight.value = props.extraHeight;
+  }
+  onResizeTable();
+  window.onresize = () => {
+    onResizeTable();
+  };
+});
+
+// 表格位置
+const onResizeTable = () => {
+  yScroll.value = getTableScroll({
+    extraHeight: extraHeight.value,
+    id: 'commonTable',
+  });
+};
+
+//点击页码事件
+const changePage = (current, size) => {
+  pagination.current = current;
+  emit('getPager', pagination.current, size);
+};
+
+// 改变每页数量时更新显示
+const showSizeChange = (current, pageSize) => {
+  setTimeout(() => {
+    pagination.current = 1;
+    emit('getPager', pagination.current, pageSize);
+  });
+  pagination.pageSize = pageSize;
+};
+
+// 回到第一页
+const backFirstPage = () => {
+  pagination.current = 1;
+  emit('getPager', pagination.current, pagination.pageSize);
+};
+
+// 伸缩列
+const handleResizeColumn = (w, col) => {
+  col.width = w;
+};
+
+// 选择每一项操作
+const selectEvent = (record, selected) => {
+  if (selected) {
+    state.selectedRows.push(record);
+    state.selectedRowKeys.push(record.id);
+  } else {
+    let index = state.selectedRowKeys.indexOf(record.id);
+    if (index >= 0) {
+      state.selectedRows.splice(index, 1);
+      state.selectedRowKeys.splice(index, 1);
+    }
+  }
+  emit('getSelected', state);
+};
+
+// 点击以后全选当前分页数据
+const selectAllEvent = (selected, selectedRows, changeRows) => {
+  if (selected) {
+    changeRows.forEach(item => {
+      state.selectedRows.push(item);
+      state.selectedRowKeys.push(item.id);
+    });
+  } else {
+    changeRows.forEach(item => {
+      let index = state.selectedRowKeys.indexOf(item.id);
+      if (index >= 0) {
+        state.selectedRows.splice(index, 1);
+        state.selectedRowKeys.splice(index, 1);
+      }
+    });
+  }
+  emit('getSelected', state);
+};
+
+// 清空选择
+const clear = (isClear = true) => {
+  state.selectedRowKeys = [];
+  state.selectedRows = [];
+  if (isClear) {
+    emit('getSelected', state);
+  }
+};
+
+// 获取排序信息
+const tableChange = (pagination, filters, sorter) => {
+  // pagination, filters 变化时也会触发所以对sorter进行判断限制执行
+  if (Object.keys(sorter).length > 0) {
+    if (sorter.field != lastSorter.field && sorter.order != lastSorter.order) {
+      lastSorter.field = sorter.field;
+      lastSorter.order = sorter.order;
+      emit('getSorter', sorter);
+    }
+    if (sorter.field != lastSorter.field && sorter.order == lastSorter.order) {
+      lastSorter.field = sorter.field;
+      lastSorter.order = sorter.order;
+      emit('getSorter', sorter);
+    }
+    if (sorter.field == lastSorter.field && sorter.order != lastSorter.order) {
+      lastSorter.field = sorter.field;
+      lastSorter.order = sorter.order;
+      emit('getSorter', sorter);
+    }
+  }
+};
+
+// 暴露出方法
+defineExpose({ backFirstPage, clear });
+
+// 监听total变化
+watch(
+  props,
+  newData => {
+    pagination.total = newData.total;
+    extraHeight.value = newData.extraHeight;
+  },
+  { immediate: true, deep: true },
+);
+// 插槽的实例
+const slots = useSlots();
+const renderArr = Object.keys(slots);
+</script>
+<style scoped>
+.tablePaganations {
+  width: 100%;
+  margin-top: 8px;
+}
+.ant-table-striped :deep(.table-striped) td {
+  background-color: #fafafa;
+}
+</style>
+  
+  

+ 26 - 0
src/custom/common/tableScroll.js

@@ -0,0 +1,26 @@
+/**
+* 获取表格的可视化高度
+* @param {*} extraHeight 额外的高度(表格底部的内容高度) 
+* @param {*} id 当前页面中有多个table时需要制定table的id
+*/
+export const getTableScroll = ({ extraHeight, id }) => {
+  if (typeof extraHeight == 'undefined') {
+    //  默认底部分页高度
+    extraHeight = 60;
+  }
+  let tHeader = null;
+  if (id) {
+    tHeader = document.getElementById(id) ?
+      document.getElementById(id).getElementsByClassName('ant-table-thead')[0] : null;
+  } else {
+    tHeader = document.getElementsByClassName('ant-table-thead')[0];
+  }
+  //表格内容距离顶部的距离
+  let tHeaderBottom = 0;
+  if (tHeader) {
+    tHeaderBottom = tHeader.getBoundingClientRect().bottom;
+  }
+  //窗体高度-表格内容顶部的高度-表格内容底部的高度
+  let height = `calc(100vh - ${tHeaderBottom + extraHeight}px)`;
+  return height;
+};

+ 820 - 0
src/custom/printer/AssetLabelPrinting.vue

@@ -0,0 +1,820 @@
+<template>
+  <div style="width: 98% !important">
+    <Navbar title="标签打印" :is-go-back="false" />
+    <div class="all">
+      <div class="globalMain">
+        <ul class="siteList">
+          <li class="last">
+            <div class="site">
+              <label class="labelStyle">所属部门</label>
+              <div class="form-inline-div">
+                <SearchWidget style="width: 200px" :info-window-no="organizationWindowNo" :field="organizationField"
+                  :field-value="organizationFieldValue" :display-name="organizationField.listDisplayFieldName"
+                  :where-clause-source="organizationWCS" @value-changed="organizationValueChanged" />
+              </div>
+            </div>
+          </li>
+          <li class="site">
+            <label class="labelStyle">名称</label>
+            <div class="form-inline-div">
+              <a-input v-model:value="searchParams.name" class="form-input" @keyup.enter="reQuery" />
+            </div>
+          </li>
+          <li class="site">
+            <label class="labelStyle">编号</label>
+            <div class="form-inline-div">
+              <a-input v-model:value="searchParams.no" class="form-input" @keyup.enter="reQuery" />
+            </div>
+          </li>
+          <li class="site">
+            <label class="labelStyle">规格型号</label>
+            <div class="form-inline-div">
+              <a-input v-model:value="searchParams.type" class="form-input" @keyup.enter="reQuery" />
+            </div>
+          </li>
+          <li class="site">
+            <label class="labelStyle">{{ $t("lang.AssetLabelPrint.printStatus") }}</label>
+            <div class="form-inline-div">
+              <a-select v-model:value="searchParams.printStatus" class="form-input">
+                <a-select-option :value="null">{{ $t("lang.AssetLabelPrint.all") }}</a-select-option>
+                <a-select-option :value="false">
+                  {{ $t("lang.AssetLabelPrint.notPrint") }}
+                </a-select-option>
+                <a-select-option :value="true">
+                  {{ $t("lang.AssetLabelPrint.havePrint") }}
+                </a-select-option>
+              </a-select>
+            </div>
+          </li>
+        </ul>
+      </div>
+      <ul class="siteList">
+        <li class="site">
+          <label class="labelStyle">{{ $t("lang.AssetLabelPrint.selectPrintTemplate") }}</label>
+          <div class="form-inline-div">
+            <a-select v-model:value="templateId" class="form-input">
+              <a-select-option value="" />
+              <a-select-option v-for="item in templates" :key="'templates' + item.name" :value="item.id">
+                {{ item.name }}
+              </a-select-option>
+            </a-select>
+          </div>
+        </li>
+        <li class="site">
+          <label for="selectPrinter" class="labelStyle">{{ $t("lang.AssetLabelPrint.selectPrinter") }}</label>
+          <div class="form-inline-div">
+            <a-select v-model:value="selectedPrinter" class="form-input">
+              <a-select-option value="" />
+              <a-select-option v-for="printer in printers" :key="printer" :value="printer">
+                {{ printer }}
+              </a-select-option>
+            </a-select>
+          </div>
+        </li>
+        <li style=" margin-left: 36px; display: flex; justify-content: space-between; ">
+          <a-button type="primary" style="width: 80px" @click="print()">
+            {{ $t("lang.AssetLabelPrint.print") }}
+          </a-button>
+          <PrintEpc ref="printEpc" v-model:visible="printEpcVisible" :printer-name="selectedPrinterCard"
+            @ok="closePrintEpc" />
+          <a-button type="primary" style="width: 80px;margin-left: 12px" @click="reQuery()">
+            {{ $t("lang.AssetLabelPrint.query") }}
+          </a-button>
+          <a-button style="width: 80px; margin-left: 12px" type="dashed" @click="clearFilter()">
+            {{ $t("lang.AssetLabelPrint.clear") }}
+          </a-button>
+        </li>
+      </ul>
+    </div>
+
+    <CommonTable ref="commonTableRef" :extra-height="70" :columns="labelPrintColumns"
+      :data-source="assetInstanceDtoList" :total="pagination.total" :is-select="true" @get-pager="getPageParams"
+      @get-selected="getSelectParams">
+      <template #bodyCell="{ column, record }">
+        <div v-if="column.dataIndex === 'printStatus'">
+          {{ record.printStatus ? '已打印' : '未打印' }}
+        </div>
+      </template>
+    </CommonTable>
+
+    <Loading v-if="loading" />
+  </div>
+</template>
+
+<script>
+import Printer from './printer.js';
+import { message } from 'ant-design-vue';
+import CommonTable from '../common/CommonTable.vue';
+import { assetLabelPrintColumns } from './columns.js';
+import { Common, Notify, PrintEpc } from 'pc-component-v3';
+
+export default {
+  components: { PrintEpc, CommonTable },
+  data: function () {
+    return {
+      assetInstanceDtoList: [],
+      checked: false, //全选,
+      labelPrintColumns: assetLabelPrintColumns,
+      pagination: {
+        total: 0, //总页数
+        per_page: 20, // 每页大小
+        current_page: 1, // 当前页数
+        last_page: 0, // 最后一页编号
+      },
+      rangeDate: [],
+      // 请求查询参数
+      searchParams: {
+        no: null, // 资产编号
+        name: null, // 资产名称
+        type: null,
+        printStatus: null, // 打印状态
+        organizationId: null, // 部门id
+      },
+      userWindowNo: '050408',
+      organizationWindowNo: '20220420_233656',
+      organizationField: {
+        name: '',
+        listDisplayFieldName: 'name',
+      },
+      organizationFieldValue: {
+        id: null,
+        displayValue: [''],
+        fieldType: 'Key',
+      },
+      custodianNameField: {
+        name: '',
+        listDisplayFieldName: 'name',
+      },
+      custodianNameFieldValue: {
+        id: null,
+        displayValue: [''],
+        fieldType: 'Key',
+      },
+      userField: {
+        name: '',
+        listDisplayFieldName: 'name',
+      },
+      userFieldValue: {
+        id: null,
+        displayValue: [''],
+        fieldType: 'Key',
+      },
+      applyPurchaseUserField: {
+        name: '',
+        listDisplayFieldName: 'name',
+      },
+      applyPurchaseUserFieldValue: {
+        id: null,
+        displayValue: [''],
+        fieldType: 'Key',
+      },
+      organizationWCS: {
+        customerDataDimensions: [
+          {
+            fieldName: 'client.id',
+            dataDimensionTypeNo: '202201191757',
+            defaultDataDimensionTypeValueNo: '4',
+          },
+        ],
+      },
+      custodianIdWhereClauseSource: {
+        customerDataDimensions: [
+          {
+            fieldName: 'client.id',
+            dataDimensionTypeNo: '202201191757',
+            defaultDataDimensionTypeValueNo: '4',
+          },
+        ],
+      },
+      templates: [], //打印模板
+      printers: [], //打印机
+      selectedPrinter: '', // 选择的打印机
+      templateId: '',
+      printPages: [],
+      printPreviews: [],
+      loading: false,
+      modal: false,
+      selectedPrinterCard: '发卡机',
+      printEpcVisible: false,
+      isCardEpc: false,
+      selectedIds: [],
+    };
+  },
+  computed: {},
+
+  watch: {},
+  mounted: function () {
+    const _self = this;
+
+    _self.pagination.current_page = 1;
+    _self.getAssetInstancePrint();
+    _self.loadTemplateData();
+
+    Printer.getPrinters().then(
+      success => {
+        if (success.errorCode === 0) {
+          if (success.data && success.data.length > 0) {
+            success.data.forEach(item => {
+              _self.printers.push(item);
+            });
+          }
+        } else {
+          message.warning(success.errorMessage);
+        }
+      },
+      error => {
+        console.log(error);
+      },
+    );
+  },
+
+  beforeUnmount: function () { },
+
+  methods: {
+    // 所属部门搜索框条件改变
+    organizationValueChanged: function (newFieldValue) {
+      this.organizationFieldValue = newFieldValue;
+      this.searchParams.organizationId = newFieldValue.id;
+    },
+    // 责任人
+    custodianNameValueChanged: function (newFieldValue) {
+      this.custodianNameFieldValue = newFieldValue;
+      this.searchParams.custodianId = newFieldValue.id;
+    },
+    // 保管人
+    userValueChanged: function (newFieldValue) {
+      this.userFieldValue = newFieldValue;
+      this.searchParams.depositoryUserId = newFieldValue.id;
+    },
+    // 申购人
+    applyPurchaseUserValueChanged: function (newFieldValue) {
+      this.applyPurchaseUserFieldValue = newFieldValue;
+      this.searchParams.applyPurchaseUserId = newFieldValue.id;
+    },
+    /**
+     * 获取选择数据的id集合
+     */
+    getSelectedRecordIds: function () {
+      const _self = this;
+      // let recordIds = [];
+
+      // for (let i = 0; i < _self.assetInstanceDtoList.length; i++) {
+      //   if (_self.assetInstanceDtoList[i].checked == true) {
+      //     recordIds.push(_self.assetInstanceDtoList[i].assetInstanceId);
+      //   }
+      // }
+
+      return _self.selectedIds;
+    },
+
+    onRangeChange(_, str) {
+      this.searchParams.startDate = str[0] === '' ? null : str[0];
+      this.searchParams.endDate = str[1] === '' ? null : str[1];
+    },
+
+    getPageParams(page, pageSize) {
+      this.pagination.current_page = page;
+      this.pagination.per_page = pageSize;
+      this.getAssetInstancePrint();
+    },
+    getSelectParams(selected) {
+      const _self = this;
+      if (_self.isCardEpc) {
+        return;
+      }
+      let templateId = _self.templateId;
+      if (templateId == '' || templateId == null) {
+        _self.templateId = '';
+        _self.$refs.commonTableRef.clear(false);
+        Notify.error('错误', '请先选择打印模板', false);
+        return;
+      }
+
+      _self.selectedIds = selected.selectedRowKeys;
+    },
+
+    getPrintData: function (recordIds) {
+      const _self = this;
+      let contents = [];
+
+      $.ajax({
+        url: Common.getApiURL(
+          'AssetInstanceResource/print?printPreview=' +
+          false +
+          '&templateId=' +
+          _self.templateId,
+        ),
+        dataType: 'json',
+        type: 'post',
+        contentType: 'application/json',
+        data: JSON.stringify(recordIds),
+        beforeSend: function (request) {
+          Common.addTokenToRequest(request);
+          _self.loading = true;
+        },
+        success: function (datas) {
+          datas.forEach(function (item) {
+            var printItem = {
+              id: null,
+              name: null,
+              content: item,
+            };
+            if (
+              printItem.content == null ||
+              printItem.content.printItems == null ||
+              printItem.content.printItems.length == 0
+            ) {
+              Notify.error('错误', '打印模板无数据,不能打印。');
+              return;
+            }
+            var content = JSON.stringify(printItem.content);
+            if (content == null || content == '' || content == '{}') {
+              Notify.error('错误', '请先选择模板,再点击下载。');
+              return;
+            }
+            contents.push(printItem.content);
+          });
+          _self.loading = false;
+        },
+        error: function (XMLHttpRequest, textStatus, errorThrown) {
+          _self.loading = false;
+          Common.processException(XMLHttpRequest, textStatus, errorThrown);
+        },
+      });
+    },
+
+    /**
+     * 打印文件
+     */
+    print: function () {
+      const _self = this;
+      let templateId = _self.templateId;
+      if (templateId == null || templateId.length == 0) {
+        Notify.error('提示', '请先选择打印模板。', false);
+        return;
+      }
+
+      let selectedPrinter = _self.selectedPrinter;
+      if (selectedPrinter == null || selectedPrinter.length == 0) {
+        Notify.error('提示', '请先选择打印机。', false);
+        return;
+      }
+
+      let recordIds = _self.getSelectedRecordIds();
+      if (recordIds == null || recordIds.length == 0) {
+        Notify.error('提示', '请先选择打印数据。', false);
+        return;
+      }
+      console.log(templateId, recordIds, selectedPrinter, '打印数据');
+      const cardIds = recordIds.join();
+      const url = `/barcode.html#/chartPrint?templateId=${templateId}&printName=${selectedPrinter}&cardIds=${cardIds}`;
+      window.open(url);
+    },
+
+    cardEpc: function () {
+      const _self = this;
+      _self.isCardEpc = true;
+      let recordIds = _self.getSelectedRecordIds();
+      if (recordIds == null || recordIds.length == 0) {
+        Notify.error('提示', '请先选择发卡数据。', false);
+        return;
+      }
+
+      if (recordIds.length > 1) {
+        Notify.error('提示', '至多选择一条发卡数据。', false);
+        return;
+      }
+
+      let contents = [];
+      let contentCards = [];
+
+      $.ajax({
+        url: Common.getApiURL(
+          'AssetInstanceResource/print?printPreview=' +
+          false +
+          '&templateId=' +
+          _self.templateId,
+        ),
+        dataType: 'json',
+        type: 'post',
+        contentType: 'application/json',
+        data: JSON.stringify(recordIds),
+        beforeSend: function (request) {
+          Common.addTokenToRequest(request);
+          _self.loading = true;
+        },
+        success: function (datas) {
+          datas.forEach(function (item) {
+            var printItem = {
+              id: null,
+              name: null,
+              content: item,
+            };
+            if (
+              printItem.content == null ||
+              printItem.content.printItems == null ||
+              printItem.content.printItems.length == 0
+            ) {
+              Notify.error('错误', '打印模板无数据,不能打印。');
+              return;
+            }
+            var content = JSON.stringify(printItem.content);
+            if (content == null || content == '' || content == '{}') {
+              Notify.error('错误', '请先选择模板,再点击下载。');
+              return;
+            }
+            contents.push(printItem.content);
+          });
+          _self.printEpcVisible = true;
+          _self.$refs.printEpc.printPrintPages(contents);
+          _self.loading = false;
+          _self.isCardEpc = false;
+        },
+        error: function (XMLHttpRequest, textStatus, errorThrown) {
+          _self.loading = false;
+          _self.isCardEpc = false;
+          Common.processException(XMLHttpRequest, textStatus, errorThrown);
+        },
+      });
+    },
+
+    closePrintEpc: function () {
+      const _self = this;
+      _self.printEpcVisible = false;
+    },
+
+    /**
+     * 打印模板change
+     */
+    templateChange: function (assetInstance) {
+      const _self = this;
+      if (_self.isCardEpc) {
+        return;
+      }
+      let templateId = _self.templateId;
+      if (templateId == '' || templateId == null) {
+        _self.templateId = '';
+        assetInstance.checked = false;
+        Notify.error('错误', '未请先选择打印模板', false);
+        return;
+      }
+    },
+
+    /**
+     * 设置模板
+     */
+    setTemplate: function (assetInstanceId, templateId) {
+      var _self = this;
+      _self.loading = true;
+      $.ajax({
+        url: Common.getApiURL('AssetInstanceResource/setPrintTemplate'),
+        type: 'get',
+        beforeSend: function (request) {
+          Common.addTokenToRequest(request);
+        },
+        data: {
+          assetInstanceId: assetInstanceId,
+          templateId: templateId,
+        },
+        success: function (data) {
+          _self.loading = false;
+        },
+        error: function (XMLHttpRequest, textStatus, errorThrown) {
+          _self.loading = false;
+          Common.processException(XMLHttpRequest, textStatus, errorThrown);
+        },
+      });
+    },
+
+    /**
+     * 加载打印模板数据
+     */
+    loadTemplateData: function () {
+      var _self = this;
+
+      Printer.queryTemplates().then(
+        success => {
+          if (success.errorCode === 0) {
+            if (success.datas && success.datas.length > 0) {
+              _self.templates = success.datas;
+            }
+          } else {
+            message.warning(success.errorMessage);
+          }
+        },
+        error => {
+          Common.processException(error);
+        },
+      );
+    },
+
+    /**
+     * 20200615
+     * 点击全选
+     */
+    selectAll: function () {
+      var _self = this;
+      for (var i = 0; i < _self.assetInstanceDtoList.length; i++) {
+        _self.assetInstanceDtoList[i].checked = _self.checked;
+      }
+    },
+
+    /**
+     * 重新查询
+     */
+    reQuery: function () {
+      let _self = this;
+      _self.$refs.commonTableRef.backFirstPage();
+    },
+
+    /**
+     * 查询资产卡片打印的数据
+     */
+    getAssetInstancePrint: function () {
+      var _self = this;
+      _self.loading = true;
+
+      _self.checked = false;
+      const range = {
+        start: (_self.pagination.current_page - 1) * _self.pagination.per_page,
+        length: _self.pagination.per_page,
+      };
+      const searchParams = _self.searchParams;
+      const params = { ...searchParams, ...{ range } };
+      $.ajax({
+        url: Common.getApiURL('InventoryResource/queryInventoryPrint'),
+        type: 'post',
+        contentType: 'application/json',
+
+        dataType: 'json',
+        data: JSON.stringify(params),
+        beforeSend: function (request) {
+          Common.addTokenToRequest(request);
+        },
+        success: function (successData) {
+
+          if (successData.errorCode == 0) {
+            if (successData.datas && successData.datas.length > 0) {
+              _self.assetInstanceDtoList = successData.datas;
+              _self.assetInstanceDtoList.forEach(function (item) {
+                item.id = item.inventoryId;
+                item.checked = false;
+              });
+
+            } else {
+              _self.assetInstanceDtoList = [];
+            }
+            _self.pagination.total = successData.total;
+          }
+          _self.loading = false;
+        },
+        error: function (XMLHttpRequest, textStatus, errorThrown) {
+          Common.processException(XMLHttpRequest, textStatus, errorThrown);
+          _self.loading = false;
+        },
+      });
+    },
+
+    /**
+     * 清空条件
+     */
+    clearFilter: function () {
+      const _self = this;
+      (_self.searchParams = {
+        epc: null,
+        assetNo: null,
+        assetInstanceName: null,
+        printStatus: null,
+        type: null,
+        organizationId: null,
+        custodianId: null,
+        depositoryUserId: null,
+        applyPurchaseUserId: null,
+        locationName: null,
+        startDate: null,
+        endDate: null,
+      }),
+        _self.rangeDate = [];
+      (_self.organizationFieldValue = {});
+      _self.custodianNameFieldValue = {};
+      _self.userFieldValue = {};
+      _self.applyPurchaseUserFieldValue = {};
+      _self.reQuery();
+    },
+
+    /**
+     * 修改页Size
+     */
+    gridSizeSelect: function (newPageSize) {
+      this.pagination.per_page = newPageSize;
+      this.pagination.current_page = 1;
+      this.getAssetInstancePrint();
+    },
+  },
+};
+</script>
+
+
+
+<style scoped>
+.grid-container {
+  display: grid;
+  grid-template-columns: 100%;
+  /*将视图分为四个模块,每个模块的高度*/
+  grid-template-rows: 53px min-content auto 40px;
+  /*视口被均分为 100 单位的 vh 占据整个窗口,扣掉顶部 topNav 的距离后,计算得到 responseOrgnizationSelect 的高度*/
+  height: calc(100vh - 90px);
+  width: 100%;
+  overflow: hidden;
+}
+
+.grid-item-1 {
+  grid-column: 1 / 2;
+  grid-row: 1 / 2;
+}
+
+.grid-item-2 {
+  grid-column: 1 / 2;
+  grid-row: 2 / 3;
+}
+
+.grid-item-3 {
+  padding-top: 0px;
+  padding-right: 10px;
+  overflow: hidden;
+  grid-column: 1 / 2;
+  grid-row: 3/4;
+  height: 100%;
+}
+
+.grid-item-4 {
+  padding-top: 10px;
+  grid-column: 1 / 2;
+  grid-row: 4/5;
+}
+</style>
+
+<style scoped>
+.m-form-group {
+  margin-left: 5px !important;
+  margin-right: 5px !important;
+  margin-bottom: 5px !important;
+}
+
+@media (max-width: 768px) {
+  .m-form-group-label {
+    text-align: left;
+    padding-right: 10px;
+  }
+}
+
+@media (min-width: 768px) {
+  .m-form-group-label {
+    width: 100px;
+    text-align: center;
+    padding-right: 10px;
+  }
+
+  .input-switches {
+    width: 100%;
+  }
+}
+
+.form-control-complex {
+  width: 200px !important;
+}
+
+.form-input {
+  border-radius: 4px !important;
+}
+
+.m-form-input {
+  border-radius: 4px !important;
+  width: 200px !important;
+}
+
+.form-inline-div {
+  display: inline-block;
+  height: 34px;
+}
+
+.m-btn {
+  margin-left: 5px !important;
+  margin-right: 5px !important;
+  margin-bottom: 5px !important;
+}
+
+.table-header-left {
+  float: left;
+  /* margin: 20px 0; */
+}
+
+.table-header-right {
+  margin-top: -2px;
+  float: right;
+}
+</style>
+
+<style scoped>
+.room_img {
+  width: 150px;
+  height: 100px;
+  float: left;
+  margin-right: 10px;
+}
+
+.room_img img {
+  width: 100%;
+  height: 100%;
+}
+
+.room_img span {
+  position: relative;
+  right: -130px;
+  top: -100px;
+  font-size: 20px;
+  color: red;
+}
+
+.modal-img-box {
+  width: 100%;
+  height: 400px;
+  text-align: center;
+  overflow: auto;
+}
+
+.m-small-img {
+  cursor: pointer;
+}
+
+.m-img {
+  width: 100%;
+}
+
+.labelStyle {
+  width: 120px;
+  text-align: right;
+  padding: 8px;
+}
+
+.grid-item-row2-column2 {
+  grid-row-start: 2;
+  grid-row-end: 3;
+  grid-column-start: 2;
+  grid-column-end: 3;
+  overflow: auto;
+  margin-top: 0px;
+}
+
+.globalMain {
+  max-width: 100%;
+  margin-left: auto;
+  margin-right: auto;
+}
+
+.siteList {
+  display: flex;
+  flex-wrap: wrap;
+  justify-content: space-between;
+}
+
+@media (min-width: 500px) {
+  .siteList {
+    margin-left: 0;
+    margin-right: -25px;
+    justify-content: flex-start;
+  }
+}
+
+.siteList>li {
+  margin-bottom: 10px;
+}
+
+@media (min-width: 500px) {
+  .siteList>li {
+    margin-right: 8px;
+  }
+}
+
+.siteList .site {
+  width: 300px;
+  display: flex;
+  justify-content: center;
+  align-items: center;
+  /* flex-direction: column; */
+  position: relative;
+}
+
+* {
+  margin: 0;
+  padding: 0;
+  list-style: none;
+  box-sizing: border-box;
+}
+
+.form-input {
+  width: 200px !important;
+  height: 30px !important;
+  padding-left: 6px !important;
+}
+</style>

+ 39 - 0
src/custom/printer/columns.js

@@ -0,0 +1,39 @@
+export const assetLabelPrintColumns = [
+  {
+    title: '序号',
+    dataIndex: 'index',
+    key: 'index',
+    width: 75,
+    customRender: ({ text, record, index }) => `${index + 1}`,
+  },
+  {
+    title: '部门',
+    key: 'organizationName',
+    dataIndex: 'organizationName',
+  },
+  {
+    title: '名称',
+    key: 'inventoryName',
+    dataIndex: 'inventoryName',
+  },
+  {
+    title: '编号',
+    key: 'inventoryNo',
+    dataIndex: 'inventoryNo',
+  },
+  {
+    title: '规格型号',
+    key: 'type',
+    dataIndex: 'type',
+  },
+  {
+    title: 'epc',
+    key: 'epc',
+    dataIndex: 'epc',
+  },
+  {
+    title: '打印状态',
+    key: 'printStatus',
+    dataIndex: 'printStatus',
+  },
+].map(item => ({ ...item, align: 'center', resizable: true, maxWidth: 300, minWidth: 75 }));

+ 139 - 0
src/custom/printer/printer.js

@@ -0,0 +1,139 @@
+import { Uuid } from 'pc-component-v3';
+import Common from '../common/Common.js';
+
+export default {
+
+  webSocket: null,
+
+  // 获取mac地址
+  getMacAddress: function () {
+    const _self = this;
+    const command = {
+      id: Uuid.createUUID(),
+      command: 'getMacAddress',
+    };
+    const commandStr = JSON.stringify(command);
+    return new Promise((resolve, reject) => {
+      _self.connectNodeRed(resolve, reject, commandStr);
+    });
+  },
+
+  // 获取打印机
+  getPrinters: function () {
+    const _self = this;
+    const command = {
+      id: Uuid.createUUID(),
+      command: 'getPrinters',
+    };
+    const commandStr = JSON.stringify(command);
+    return new Promise((resolve, reject) => {
+      _self.connectNodeRed(resolve, reject, commandStr);
+    });
+  },
+
+  // 执行打印
+  print: function (prnData) {
+    const _self = this;
+    const command = {
+      id: Uuid.createUUID(),
+      command: 'print',
+      data: prnData,
+    };
+    const commandStr = JSON.stringify(command);
+    return new Promise((resolve, reject) => {
+      _self.connectNodeRed(resolve, reject, commandStr);
+    });
+  },
+
+  // 取消打印
+  cancelAllTask: function (prnData) {
+    const _self = this;
+    const command = {
+      id: Uuid.createUUID(),
+      command: 'cancelAllTask',
+      data: prnData,
+    };
+    const commandStr = JSON.stringify(command);
+    return new Promise((resolve, reject) => {
+      _self.connectNodeRed(resolve, reject, commandStr);
+    });
+  },
+
+  // 连接node red的websocket
+  connectNodeRed: function (resolve, reject, commandStr) {
+    const _self = this;
+    let printers = null;
+    let socketUrl = 'ws://127.0.0.1:10092';
+
+    _self.webSocket = new WebSocket(socketUrl);
+    _self.webSocket.onopen = function (event) {
+      console.log('打印 Websocket 连接成功。');
+      if (commandStr != null && commandStr.length > 0) {
+        _self.sendCommand(commandStr);
+      } else {
+        _self.close();
+      }
+    };
+    _self.webSocket.onclose = function (event) {
+      console.log('打印 Websocket 断开连接。');
+      resolve(printers);
+    };
+    _self.webSocket.onerror = function (event) {
+      console.log('打印 Websocket 出错。');
+      _self.close();
+      reject();
+    };
+    _self.webSocket.onmessage = function (event) {
+      const data = JSON.parse(event.data);
+      printers = data;
+      _self.close();
+    };
+  },
+
+  // WebSocket 发送指令
+  sendCommand: function (command) {
+    if (this.webSocket) {
+      this.webSocket.send(command);
+    }
+  },
+
+  // 关闭Websocket
+  close: function () {
+    if (this.webSocket) {
+      this.webSocket.close();
+      this.webSocket = null;
+    };
+  },
+  getRootPath: function () {
+    var protocol = window.location.protocol;
+    var host = window.location.hostname;
+    var path = protocol + host;
+    return path;
+  },
+  // 查询所有模板信息
+  queryTemplates: function () {
+
+    var requestUrl = 'CustomerCloudPrintTemplateResource/querySimpleAllTemplate';
+
+
+    return new Promise((resolve, reject) => {
+      $.ajax({
+        url: Common.getApiURL(requestUrl),
+        type: 'get',
+        contentType: 'application/json',
+
+        beforeSend: function (request) {
+          Common.addTokenToRequest(request);
+        },
+        success: function (data) {
+          resolve(data);
+        },
+        error: function (XMLHttpRequest, textStatus, errorThrown) {
+          reject(XMLHttpRequest);
+        },
+
+      });
+    });
+  },
+};
+

+ 38 - 0
src/lang.js

@@ -0,0 +1,38 @@
+
+import { createI18n } from 'vue-i18n';
+import merge from './merge.js';
+
+import {
+    langZhCn as langZhCn0,
+    langEnUs as langEnUs0,
+} from 'client-base-v5/dist/client-base-v5.js';
+
+console.log(langZhCn0);
+
+import {
+    langZhCn as langZhCn1,
+    langEnUs as langEnUs1
+} from 'client-eam-v5/dist/client-eam-v5.js';
+
+console.log(langZhCn1);
+
+import {
+    langZhCn as langZhCn2,
+    langEnUs as langEnUs2
+} from 'client-role-v3';
+
+
+let langZhCn = merge.deepAssign(langZhCn0, langZhCn1, langZhCn2);
+let langEnUs = merge.deepAssign(langEnUs0, langEnUs1, langEnUs2);
+
+console.log(langZhCn);
+
+const i18n = createI18n({
+  locale: 'zh-CN',
+  messages: {
+    'zh-CN': langZhCn,
+    'en-US': langEnUs,
+  },
+});
+
+export { i18n };

+ 173 - 0
src/main.js

@@ -0,0 +1,173 @@
+
+// eslint-disable-next-line no-undef
+//__webpack_nonce__ = '*NONCE_TOKEN*';
+// eslint-disable-next-line no-undef
+__webpack_nonce__ = window.nonce_token;
+
+import { createApp, defineAsyncComponent } from 'vue';
+//import { createApp, defineAsyncComponent } from 'vue/dist/vue.runtime.esm-browser.prod.js';
+
+
+
+
+// 修复异步组件中AntV控件不能打开的BUG。
+// import Antd from 'ant-design-vue';
+import * as Antd from 'ant-design-vue';
+import 'ant-design-vue/dist/reset.css';
+window.Antd = Antd;
+//console.log(Antd);
+
+// 修复异步组件中AntV控件不能打开的BUG。
+import * as AntdComponents from 'ant-design-vue';
+window.Antd = AntdComponents;
+
+
+
+
+import { createRouter, createWebHashHistory } from 'vue-router';
+import { createStore } from 'vuex';
+
+import * as PcComponentV3 from 'pc-component-v3';
+import 'pc-component-v3/dist/pc-component-v3.css';
+window.PcComponentV3 = PcComponentV3;
+
+import VTooltip from 'v-tooltip';
+import 'v-tooltip/dist/v-tooltip.css';
+
+import * as dd from 'dingtalk-jsapi';
+window.dd = dd;
+
+import 'jquery';
+
+
+import 'client-base-v5/dist/client-base-v5.css';
+
+
+import 'client-role-v3/dist/client-role-v3.css';
+// import 'client-dictionary-v3/dist/client-dictionary-v3.css';
+import 'client-dic-v3/dist/client-dic-v3.css';
+
+import 'client-eam-v5/dist/client-eam-v5.css';
+import 'client-wms-v5/dist/client-wms-v5.css';
+import 'client-sensor-v3/dist/client-sensor-v3.css';
+import 'client-finance-v3/dist/client-finance-v3.css';
+
+import { store } from './store.js';
+import { i18n } from './lang.js';
+import { router } from './routes/index.js';
+
+import { App, Common, PushMessage, CurdWindowModal, AuthImage, WorkflowUserDefine, ApproveComment, HistoryApproveComment } from 'client-base-v5/dist/client-base-v5.js';
+import { Notify, Uuid } from 'pc-component-v3/dist/pc-component-v3.js';
+window.Common = Common;
+window.Notify = Notify;
+window.Uuid = Uuid;
+
+
+import * as AntDesignIconsVue from '@ant-design/icons-vue';
+window.AntDesignIconsVue = AntDesignIconsVue;
+
+
+
+const app = createApp(App);
+app.use(Antd);
+app.use(i18n);
+app.use(router);
+app.use(VTooltip);
+app.use(store);
+app.use(PcComponentV3);
+app.use(router);
+app.mount('#app');
+
+// 全局注册组件, CURD窗口模态框编辑器
+app.component('CurdWindowModal', CurdWindowModal);
+// 图片显示
+app.component('AuthImage', AuthImage);
+// 发起审批
+app.component('WorkflowUserDefine', WorkflowUserDefine);
+// 审批状态
+app.component('ApproveComment', ApproveComment);
+// 历史审批记录
+app.component('HistoryApproveComment', HistoryApproveComment);
+
+
+window.app = app;
+
+
+// 当页面刷新后重新打开声音提示
+if (window.performance.navigation.type == 1) {
+  localStorage.setItem('allowSound', false);
+}
+
+
+/**
+ * 路由钩子
+ * @param  {[type]} (to, from,         next [description]
+ * @return {[type]}      [description]
+ */
+router.beforeEach((to, from, next) => {
+  let allowSound = localStorage.getItem('allowSound');
+  // 不是登录页才进行消息推送
+  if (to.fullPath !== '/login' && !to.path.includes('login') && !to.path.includes('Login')) {
+    PushMessage.openWebSocket();
+    if (allowSound && allowSound == 'false') {
+      PushMessage.messageModal();
+    }
+  } else {
+    PushMessage.closeWebsocket();
+  }
+
+  let funtionAccessDtos = [];
+  if (to.matched.some(function (item) {
+
+    // 判断是否需要登录才可以访问
+    if (item.meta.loginRequired) {
+      if (item.meta.functionAccessArray != undefined || item.meta.functionAccessArray != null) {
+        funtionAccessDtos = item.meta.functionAccessArray;
+      }
+      if (funtionAccessDtos != null) {
+        funtionAccessDtos.forEach(funtionAccessDto => {
+          if (typeof (funtionAccessDto.itemNo) === 'string') {
+            funtionAccessDto.itemNo = [funtionAccessDto.itemNo];
+          }
+        });
+      }
+    }
+    return item.meta.loginRequired;
+  })) {
+    // 判断是否已登录		
+    var token = localStorage.getItem('#token');
+    if (token == undefined || token.length == 0) {
+      // 如果没有登录则直接返回
+      next('/login');
+    } else {
+      // 判断该路由需要具备”xxx”功能-“x1”功能项,”xxx”功能-“x2“功能项,”yyy”功能-“y1”功能项访问权限的用户才可以访问
+      $.ajax({
+        url: Common.getApiURL(
+          'RoleResourceV3/canVisitFunctionAccess',
+        ),
+        type: 'post',
+        dataType: 'json',
+        contentType: 'application/json',
+        data: JSON.stringify(funtionAccessDtos),
+        beforeSend: function (request) {
+          Common.addTokenToRequest(request);
+        },
+        success: function (data) {
+          if (data.errorCode === 0 && data.data === true) {
+            next();
+            return;
+          } else {
+            next('/desktop/no-role');
+            return;
+          }
+        },
+        error: function (XMLHttpRequest, textStatus, errorThrown) {
+          Common.processException(XMLHttpRequest, textStatus, errorThrown);
+        },
+      });
+    }
+  } else {
+    next();
+    return;
+  }
+});

+ 65 - 0
src/merge.js

@@ -0,0 +1,65 @@
+/**
+ * 深度合并对象
+ * @param  {...any} param 
+ * @returns 
+ */
+function deepAssign(...param) {
+  let result = Object.assign({}, ...param);
+  for (let item of param) {
+    for (let [idx, val] of Object.entries(item)) {
+      if (typeof val === 'object') {
+        result[idx] = deepAssign(result[idx], val);
+      }
+    }
+  }
+  return result;
+}
+
+
+/**
+ * 合并数组
+ * @param {*} arr1 数组1 
+ * @param {*} arr2 数组2
+ * @returns 
+ */
+function mergeArray(arr1, arr2) {
+  var arr = [];
+  for (var k = 0, len = arr1.length; k < len; k++) {
+    arr.push(arr1[k]);
+  }
+  for (var i = 0, len2 = arr2.length; i < len2; i++) {
+    //是否添加该元素
+    var flag = true;
+    for (var j = 0, len1 = arr.length; j < len1; j++) {
+      //如果path相同,则合并children;如果children不存在,则不合并;
+      if (arr[j].path == arr2[i].path) {
+        flag = false;
+        if (arr[j].children instanceof Array && arr2[i].children instanceof Array) {
+          arr[j].children = this.mergeArray(arr[j].children, arr2[i].children);
+        }
+      }
+    }
+    if (flag) {
+      arr.push(arr2[i]);
+    }
+  }
+  //将path为"*"的项移到最后
+  var temp;
+  var index;
+  for (var n = 0, len3 = arr.length; n < len3; n++) {
+    if (arr[n].path == '*' || arr[n].path == '/*') {
+      index = n;
+    }
+  }
+  if (index != undefined) {
+    temp = arr[index];
+    arr[index] = arr[len3 - 1];
+    arr[len3 - 1] = temp;
+  }
+  return arr;
+}
+
+export default {
+  deepAssign,
+  mergeArray,
+};

+ 8 - 0
src/routes/custom.js

@@ -0,0 +1,8 @@
+import AssetLabelPrinting from '../custom/printer/AssetLabelPrinting.vue'
+
+
+const router = [
+    { path: '/wms/inventory-label-printing', component: AssetLabelPrinting },
+];
+
+export default router;

+ 33 - 0
src/routes/index.js

@@ -0,0 +1,33 @@
+import { createRouter, createWebHashHistory } from 'vue-router';
+
+import routes0 from './route-base-v5.js';
+import routes1 from './route-role-v3.js';
+// import routes2 from './route-dictionary-v3.js';
+import routes3 from './route-dic-v3.js';
+import routes5 from './route-eam-v5.js';
+import routes6 from './route-wms-v5.js';
+// import routes7 from './route-trace-v3.js';
+import routes8 from './route-sensor-v3.js';
+import routes9 from './route-finance-v3.js';
+import routes10 from './custom.js';
+
+import merge from '../merge.js';
+
+let routes = merge.mergeArray(routes0, routes1);
+// routes = merge.mergeArray(routes, routes2);
+routes = merge.mergeArray(routes, routes3);
+routes = merge.mergeArray(routes, routes5);
+routes = merge.mergeArray(routes, routes6);
+// routes = merge.mergeArray(routes, routes7);
+routes = merge.mergeArray(routes, routes8);
+routes = merge.mergeArray(routes, routes9);
+routes = merge.mergeArray(routes, routes10);
+
+const router = createRouter({
+  history: createWebHashHistory(),
+  base: '/',
+  mode: 'hash',
+  routes: routes,
+});
+
+export { router };

+ 374 - 0
src/routes/route-base-v5.js

@@ -0,0 +1,374 @@
+
+import { ProcessReport } from 'pc-component-v3';
+
+import {
+    Login,
+    Desktop,
+    Dashboard,
+    SheetWindow,
+    TabFormEdit1,
+    TabFormView1,
+    AttributeEditPanel,
+    TabAudit,
+    Approve,
+    RoleCurdField,
+    RoleCurdFieldTab,
+    TabDataSort,
+    WorkflowEdit,
+    DataImportPanel,
+    Notification,
+    SingleNotification,
+    GenerateDocumentTool,
+    UserParameters,
+    OrganizationEditPanel,
+    BarCodeEdit,
+    Archive,
+    UserSearch,
+    Monitor,
+    BatchUpdateField,
+    ActivitiAdmin,
+    DocManagement,
+    PrintPage,
+    NotFound,
+    Camera,
+    Cropper,
+    WebSocketCapture,
+    WebRtcCapture,
+    InfoWindowPage,
+    TaskProcessManagement,
+    ExecutionList,
+    NoRole,
+    PrivacyStatement,
+    StudyVideo,
+    ResetPassword,
+    PdfPrint,
+    RetrievePassword,
+    KnowledgeTrain1,
+    KnowledgeTrainAnswer,
+    ReportApprove,
+    ExcelReport,
+    DateExcelReport,
+    DelegationReport,
+    DataArchive,
+    ArchivalRecord,
+    ExcelImport,
+    IdentityManager,
+    CreateIdentity,
+    SamlLogin,
+    CasLogin,
+    PrinterConfiguration,
+    CurdWindow1,
+    ShortcutMenu,
+    FlowChart,
+    DeviceManagement,
+    DeviceTimingSwitcher,
+    OperationLog,
+    ViewEdit,
+    LoginGraphic,
+    LoginNode,
+} from 'client-base-v5/dist/client-base-v5.js';
+
+
+const router = [
+    { path: '/', redirect: '/login' },
+    {
+        path: '/login',
+        component: Login,
+        meta: {
+            loginRequired: false,
+        },
+    },
+    {
+        path: '/samlLogin',
+        component: SamlLogin,
+        meta: {
+            loginRequired: false,
+        },
+    },
+    {
+        path: '/casLogin',
+        component: CasLogin,
+        meta: {
+            loginRequired: false,
+        },
+    },
+    {
+        path: '/desktop', component: Desktop,
+        children: [
+            //仪表盘
+            {
+                path: 'dashboard',
+                component: Dashboard,
+                meta: {
+                    loginRequired: false,
+                    functionAccessArray: [
+                        {
+                            functionNo: '资产仪表盘',
+                            itemNo: ['公司资产统计', '部门资产统计'],
+                        },
+                        {
+                            functionNo: '仓库仪表盘',
+                            itemNo: '出入库统计',
+                        },
+                    ],
+                },
+            },
+            // Web电子表格 窗口
+            { path: 'sheetWindow/:windowNo', component: SheetWindow },
+
+            // 快捷菜单
+            { path: 'shortcutMenu',name:'ShortcutMenu', component: ShortcutMenu },
+
+
+            { path: 'window1/:windowNo', component: CurdWindow1 },
+
+            // eslint-disable-next-line
+            { path: 'window1/window-edit/:type/:uuid', component: TabFormEdit1 },
+            // eslint-disable-next-line
+            { path: 'window1/window-edit/:type/:windowNo/:tabIndex', component: TabFormEdit1 },
+            // eslint-disable-next-line
+            { path: 'window1/window-edit/:type/:windowNo/:tabIndex/:recordId', component: TabFormEdit1 },
+
+            // CRUD不可编辑窗口
+            // eslint-disable-next-line
+            { path: 'window1/window-read/:type/:uuid', component: TabFormView1 },
+            // eslint-disable-next-line
+            { path: 'window1/window-read/:type/:windowNo/:tabIndex/:recordId', component: TabFormView1 },
+
+            // 属性编辑窗口
+            {
+                path: 'attribute-edit/:uuid', component: AttributeEditPanel,
+                'meta': {
+                    'loginRequired': true,
+                    'functionAccessArray': [
+                        {
+                            'functionNo': '20220321_212846',
+                            'itemNo': '1',
+                        },
+                    ],
+                },
+            },
+            // 审计数据窗口
+            { path: 'window/window-audit/:uuid', component: TabAudit },
+            // 查询窗口
+            { path: 'info/:infoWindowNo', component: InfoWindowPage },
+
+            // 流程和报口
+            { path: 'process-report/:no', component: ProcessReport },
+            // 审批
+            { path: 'approve', component: Approve },
+            // 无权限访问界面
+            { path: 'no-role', component: NoRole },
+            //角色CURD访问权限(父页签)
+            {
+                path: 'roleCurdField',
+                component: RoleCurdField,
+                meta: {
+                    loginRequired: true,
+                    functionAccessArray: [
+                        {
+                            functionNo: 'xxx',
+                            itemNo: ['x1', 'x2'],
+                        },
+                        {
+                            functionNo: 'yyy',
+                            itemNo: 'y1',
+                        },
+                    ],
+                },
+            },
+
+            //角色CURD访问权限(子页签)
+            {
+                path: 'roleCurdFieldTab', component: RoleCurdFieldTab,
+                'meta': {
+                    'loginRequired': true,
+                    'functionAccessArray': [
+                        {
+                            'functionNo': '20220321_212846',
+                            'itemNo': '1',
+                        },
+                    ],
+                },
+            },
+
+            // 页签字段排序
+            { path: 'tab-data-sort/:uuid', component: TabDataSort },
+            // 工作流编辑
+            {
+                path: 'workflow-edit', component: WorkflowEdit,
+                meta: {
+                    'loginRequired': true,
+                    'functionAccessArray': [
+                        {
+                            'functionNo': '20220424_144806',
+                            'itemNo': '1',
+                        },
+                    ],
+                },
+            },
+            // 数据导入
+            {
+                path: 'data-import-panel', component: DataImportPanel,
+                meta: {
+                    'loginRequired': true,
+                    'functionAccessArray': [
+                        {
+                            'functionNo': '20220328_093317',
+                            'itemNo': '2',
+                        },
+                        {
+                            'functionNo': '20220712_133418',
+                            'itemNo': '1',
+                        },
+                    ],
+                },
+
+            },
+            // 数据导入
+            { path: 'data-import-panel/:uuid', component: DataImportPanel },
+            // 通知
+            { path: 'notification', component: Notification },
+            // 单条通知
+            // eslint-disable-next-line
+            { path: 'single-notification/:messageId', component: SingleNotification },
+            // 生单
+            // eslint-disable-next-line
+            { path: 'generate-document/:type/:infoWindowNo/:uuid', component: GenerateDocumentTool },
+            // 用户参数
+            { path: 'userParameters', component: UserParameters },
+            // 部门编辑
+            {
+                path: 'OrganizationEditPanel', component: OrganizationEditPanel,
+                meta: {
+                    'loginRequired': true,
+                    'functionAccessArray': [
+                        {
+                            'functionNo': '20220314_103037',
+                            'itemNo': '2',
+                        },
+                    ],
+                },
+            },
+            // 条码编辑(老编辑器)
+            {
+                path: 'barCode-edit-o', component: BarCodeEdit,
+                meta: {
+                    'loginRequired': true,
+                    'functionAccessArray': [
+                        {
+                            'functionNo': '20220328_092713',
+                            'itemNo': '3',
+                        },
+                    ],
+                },
+            },
+            // 归档
+            { path: 'archive', component: Archive },
+            // 归档
+            { path: '/desktop/dataArchive', component: DataArchive },
+            // 归档记录
+            { path: '/desktop/ArchivalRecord', component: ArchivalRecord },
+            //用户搜索
+            { path: 'userSearch', component: UserSearch },
+            //抓拍
+            { path: 'monitor', component: Monitor },
+            //批量修改字段
+            {
+                path: 'batchUpdateField/:uuid', component: BatchUpdateField,
+                'meta': {
+                    'loginRequired': true,
+                    'functionAccessArray': [
+                        {
+                            'functionNo': '20220322_095822',
+                            'itemNo': '1',
+                        },
+                    ],
+                },
+            },
+            // 工作流管理员2019
+            { path: 'activitiAdmin', component: ActivitiAdmin },
+            // 工作流管理员2019
+            {
+                path: 'DocManagement', component: DocManagement,
+                'meta': {
+                    'loginRequired': true,
+                    'functionAccessArray': [
+                        {
+                            'functionNo': '20220424_144806',
+                            'itemNo': '1',
+                        },
+                    ],
+                },
+            },
+
+
+
+
+            // 任务流程管理
+            {
+                path: 'taskProcessManagement', component: TaskProcessManagement,
+                meta: {
+                    'loginRequired': true,
+                    'functionAccessArray': [
+                        {
+                            'functionNo': '20220424_144806',
+                            'itemNo': '1',
+                        },
+                    ],
+                },
+            },
+
+            // 执行列表
+            {
+                path: 'executionList', component: ExecutionList,
+                meta: {
+                    'loginRequired': true,
+                    'functionAccessArray': [
+                        {
+                            'functionNo': '20220424_144806',
+                            'itemNo': '1',
+                        },
+                    ],
+                },
+            },
+
+            { path: 'pdf-print', component: PdfPrint },
+
+            { path: 'report-approve', component: ReportApprove },
+        ],
+    },
+
+    // 打印页面
+    { path: '/single/PrintPage', component: PrintPage },
+
+    { path: '/webrt', component: WebRtcCapture },
+    { path: '/WebSocketCapture', component: WebSocketCapture },
+    { path: '/cropper', component: Cropper },
+    { path: '/camera', component: Camera },
+
+    { path: '/notFound', component: NotFound },
+    { path: '/privacy-statement', component: PrivacyStatement },
+    { path: '/studyVideo', component: StudyVideo },
+    { path: '/resetPassword', component: ResetPassword },
+
+    { path: '/retrievePassword', component: RetrievePassword },
+    { path: '/knowledgeTrain', component: KnowledgeTrain1 },
+    { path: '/knowledgeTrainAnswer', component: KnowledgeTrainAnswer },
+    { path: '/excelReport/:processReportNo', component: ExcelReport },
+    { path: '/dateExcelReport/:processReportNo', component: DateExcelReport },
+    { path: '/desktop/delegationReport', component: DelegationReport },
+    { path: '/desktop/excelImport', component: ExcelImport },
+    { path: '/desktop/identityManager', component: IdentityManager },
+    { path: '/desktop/CreateIdentity', component: CreateIdentity },
+    { path: '/desktop/printerConfiguration', component: PrinterConfiguration },
+    { path: '/desktop/flowChart', component: FlowChart },
+    { path: '/desktop/deviceManagement', component: DeviceManagement },
+    { path: '/desktop/deviceTimingSwitcher', component: DeviceTimingSwitcher },
+    { path: '/desktop/operationLog', component: OperationLog },
+    { path: '/desktop/viewEdit', component: ViewEdit },
+    { path: '/loginGraphic', component: LoginGraphic },
+    { path: '/loginNode', component: LoginNode },
+];
+
+export default router;

+ 52 - 0
src/routes/route-dic-v3.js

@@ -0,0 +1,52 @@
+
+import {
+    InfoWindow,
+    DicMenu,
+    DataDimensionType,
+    CurdWindow,
+    SqlApi,
+    HtmlWindow,
+    CustomerWindow,
+    DashboardWindow,
+    DataTemplate,
+    ProcessReportWindow,
+    MenuWindow,
+    AppMenuWindow,
+    FunctionEdit,
+    RoleTemplate,
+    InfoWindowDrawer,
+    CurdFilterComponent,
+    LowcodeWindow,
+    DeployVueFile,
+    PostTypeEdit,
+    TaskTemplateEdit,
+    ProcessEdit,
+} from 'client-dic-v3';
+
+
+const routes = [
+    { path: '/', redirect: '/dic-management' },
+    { path: '/dic-management/', component: DicMenu },
+    { path: '/dic-management/info-window', component: InfoWindow },
+    { path: '/dic-management/data-dimension-type', component: DataDimensionType },
+    { path: '/dic-management/curd-window', component: CurdWindow },
+    { path: '/dic-management/sql-api', component: SqlApi },
+    { path: '/dic-management/html-window', component: HtmlWindow },
+    { path: '/dic-management/customer-window', component: CustomerWindow },
+    { path: '/dic-management/dashboard-window', component: DashboardWindow },
+    { path: '/dic-management/data-template', component: DataTemplate },
+    { path: '/dic-management/process-report-window', component: ProcessReportWindow },
+    { path: '/dic-management/menu-window', component: MenuWindow },
+    { path: '/dic-management/app-menu-window', component: AppMenuWindow },
+    { path: '/dic-management/function-edit', component: FunctionEdit },
+    { path: '/dic-management/post-type-edit', component: PostTypeEdit },
+    { path: '/dic-management/task-template-edit', component: TaskTemplateEdit },
+    { path: '/dic-management/process-edit', component: ProcessEdit },
+    { path: '/dic-management/role-template', component: RoleTemplate },
+    { path: '/dic-management/info-window-drawer', component: InfoWindowDrawer },
+    { path: '/dic-management/curd-filter-component', component: CurdFilterComponent },
+    { path: '/dic-management/lowcode-window', component: LowcodeWindow },
+    { path: '/dic-management/deploy-vue-file', component: DeployVueFile },
+];
+
+export default routes;

+ 291 - 0
src/routes/route-eam-v5.js

@@ -0,0 +1,291 @@
+import {
+    HelloWorld,
+    AssetBasicSet,
+    DepreciationDetailList,
+    DepreciationDistribution,
+    AssetWorkLoadInput,
+    SettleAccountAtTheEndOfMonth,
+    InventoryCheckLoss,
+    ConsolidatedAssetInventory,
+    AutoGenerateAsset,
+    AssetCheck,
+    CustomPrintAssetInstance,
+    CopyProperty,
+    DataSync,
+    DataSyncEdit,
+    AssetDetailList,
+    AssetByRfid,
+    AssetInventorySearch,
+    AssetInventoryLostConfirm,
+    PrintAsset,
+    AssetBatchOperationQuery,
+    AssetBatchOperationOrganization,
+    AssetBatchOperationScrap,
+    AssetInstancePrint,
+    AssetInstanceSearchDetail,
+    GenerateDocumentTool,
+    ExportPictureLibrary,
+    AssetBatchOperationModifyUseStatus,
+    AssetBatchOperationModifyContact,
+    PrintPreview,
+    AssetInventory,
+    AssetInventoryStep1,
+    ManuallyConfirmCountingData,
+    PerformInventoryTasks,
+    InventoryDataProcessing,
+    AssetLabelPrint,
+    AssetLabelPrinting,
+    InventoryAssetInstanceSearch,
+    RunDataArchive,
+    AssetRfidRecord,
+    BatchUploadImages,
+    AssetInstanceFullCalendar,
+    InventoryGlobalView,
+    AssetsDisposal,
+    ExecuteAssetDisposal,
+    DepreciationIndex,
+    AssetManagerDepreciation,
+    AccountingSubject
+} from 'client-eam-v5/dist/client-eam-v5.js';
+
+
+
+const routes = [
+    { path: '/eam/hello-world', component: HelloWorld },
+    {
+        path: '/eam/assetBasicSet', component: AssetBasicSet,
+        meta: {
+            'loginRequired': true,
+            'functionAccessArray': [
+                {
+                    'functionNo': '20220322_095049',
+                    'itemNo': '1',
+                },
+            ],
+        },
+    },
+    {
+        path: '/eam/depreciationDetailList', component: DepreciationDetailList,
+        meta: {
+            'loginRequired': true,
+            'functionAccessArray': [
+                {
+                    'functionNo': '20220322_095822',
+                    'itemNo': '1',
+                },
+            ],
+        },
+    },
+    {
+        path: '/eam/depreciationDistribution', component: DepreciationDistribution,
+        meta: {
+            'loginRequired': true,
+            'functionAccessArray': [
+                {
+                    'functionNo': '20220322_095822',
+                    'itemNo': '1',
+                },
+            ],
+        },
+    },
+    {
+        path: '/eam/assetWorkLoadInput', component: AssetWorkLoadInput,
+        meta: {
+            'loginRequired': true,
+            'functionAccessArray': [
+                {
+                    'functionNo': '20220322_095822',
+                    'itemNo': '1',
+                },
+            ],
+        },
+    },
+    {
+        path: '/eam/settleAccountAtTheEndOfMonth', component: SettleAccountAtTheEndOfMonth,
+        meta: {
+            'loginRequired': true,
+            'functionAccessArray': [
+                {
+                    'functionNo': '20220322_095822',
+                    'itemNo': '1',
+                },
+            ],
+        },
+    },
+    {
+        path: '/eam/asset-inventory-check-lose/:uuid', component: InventoryCheckLoss,
+
+    },
+    {
+        path: '/eam/consolidated-AssetInventory/:uuid', component: ConsolidatedAssetInventory,
+
+    },
+    // // 自动生成资产
+    {
+        path: '/eam/auto-generate-asset', component: AutoGenerateAsset,
+
+    },
+    {
+        path: '/eam/auto-assetCheck-asset', component: AssetCheck,
+    },
+    {
+        path: '/eam/custom-print-assetInstance', component: CustomPrintAssetInstance,
+
+    },
+    // //复制资产
+    {
+        path: '/eam/copy-property/:uuid', component: CopyProperty,
+    },
+    {
+        path: '/eam/data-sync', component: DataSync,
+    },
+    {
+        path: '/eam/data-sync-edit', component: DataSyncEdit,
+    },
+    {
+        path: '/eam/assetDetailList', component: AssetDetailList,
+        meta: {
+            'loginRequired': true,
+            'functionAccessArray': [
+                {
+                    'functionNo': '20220412_094415',
+                    'itemNo': [
+                        '1',
+                        '2',
+                    ],
+                },
+            ],
+        },
+    },
+    //资产进出记录
+    {
+        path: '/eam/AssetByRfid', component: AssetByRfid,
+        meta: {
+            'loginRequired': true,
+            'functionAccessArray': [
+                {
+                    'functionNo': '20220322_095845',
+                    'itemNo': '1',
+                },
+            ],
+        },
+    },
+    // 资产卡片查询生成盘点单详情
+    {
+        path: '/eam/assetInventorySearch/:uuid', component: AssetInventorySearch,
+    },
+    // 人工确认盘亏数据
+    {
+        path: '/eam/AssetInventoryLostConfirm/:uuid', component: AssetInventoryLostConfirm,
+    },
+    //资产打印
+    { path: '/eam/printAsset/:uuid', component: PrintAsset },
+    //批量转移
+    { path: '/eam/assetBatchOperationQuery/:changeType', component: AssetBatchOperationQuery },
+    //批量待转移
+    {
+        path: '/eam/assetBatchOperation/organizationChange', component: AssetBatchOperationOrganization,
+        meta: {
+            'loginRequired': true,
+            'functionAccessArray': [
+                {
+                    'functionNo': '20220412_105926',
+                    'itemNo': '1',
+                },
+            ],
+        },
+    },
+    //批量待报废
+    {
+        path: '/eam/assetBatchOperation/assetInstanceScrap', component: AssetBatchOperationScrap,
+        meta: {
+            'loginRequired': true,
+            'functionAccessArray': [
+                {
+                    'functionNo': '20220412_105926',
+                    'itemNo': '2',
+                },
+            ],
+        },
+    },
+    //打开资产卡片打印队列
+    {
+        path: '/eam/assetInstancePrint', component: AssetInstancePrint,
+    },
+    {
+        path: '/eam/assetInstanceSearchDetail', component: AssetInstanceSearchDetail,
+    },
+    // 生单组件
+    {
+        path: '/eam/generate-document/:type/:infoWindowNo/:uuid', component: GenerateDocumentTool,
+    },
+    //导出图片库
+    {
+        path: '/eam/exportPictureLibrary', component: ExportPictureLibrary,
+    },
+    //批量待修改使用状态
+    {
+        path: '/eam/assetBatchOperation/assetInstanceModifyUseStatus', component: AssetBatchOperationModifyUseStatus,
+        meta: {
+            'loginRequired': true,
+            'functionAccessArray': [
+                {
+                    'functionNo': '20220412_105926',
+                    'itemNo': '3',
+                },
+            ],
+        },
+    },
+    //批量待修改联系人
+    {
+        path: '/eam/assetBatchOperation/assetInstanceModifyContact', component: AssetBatchOperationModifyContact,
+        meta: {
+            'loginRequired': true,
+            'functionAccessArray': [
+                {
+                    'functionNo': '20220412_105926',
+                    'itemNo': '4',
+                },
+            ],
+        },
+    },
+    {
+        path: '/eam/printPreview', component: PrintPreview,
+    },
+    {
+        path: '/eam/assetInventory', component: AssetInventory,
+    },
+    {
+        path: '/eam/assetInventoryStep1', component: AssetInventoryStep1,
+    },
+    // 人工确认盘亏数据
+    {
+        path: '/eam/manuallyConfirmCountingData', component: ManuallyConfirmCountingData,
+    },
+    {
+        path: '/eam/performInventoryTasks/:id', component: PerformInventoryTasks,
+    },
+    {
+        path: '/eam/inventoryDataProcessing', component: InventoryDataProcessing,
+    },
+    {
+        path: '/eam/assetLabelPrint', component: AssetLabelPrint,
+    },
+    {
+        path: '/eam/assetLabelPrinting', component: AssetLabelPrinting,
+    },
+    { path: '/eam/inventoryAssetInstanceSearch', component: InventoryAssetInstanceSearch },
+    { path: '/eam/runDataArchive', component: RunDataArchive },
+    { path: '/eam/assetRfidRecord', component: AssetRfidRecord },
+    { path: '/eam/batchUploadImages', component: BatchUploadImages },
+    { path: '/eam/assetInstanceFullCalendar', component: AssetInstanceFullCalendar },
+    { path: '/eam/inventoryGlobalView', component: InventoryGlobalView, },
+    { path: '/eam/disposalApplication', component: AssetsDisposal }, // 处置申请单
+    { path: '/eam/executeAssetDisposal', component: ExecuteAssetDisposal }, // 执行处置
+    { path: '/eam/assetPeriodDepreciate', component: DepreciationIndex }, // 资产折旧
+    { path: '/eam/assetManagerDepreciation', component: AssetManagerDepreciation }, // 资产折旧-单位资产管理员
+    { path: '/eam/accountingSubject', component: AccountingSubject }, // 会计科目
+];
+
+
+export default routes;

+ 35 - 0
src/routes/route-finance-v3.js

@@ -0,0 +1,35 @@
+import {
+  AccountVoucher,
+  AutoGenerateAccountVoucher,
+  InsertAccountVoucher,
+  UpdateAccountVoucher,
+  AccountSubject,
+  FinanceBasicSetting,
+  Period,
+  SettleAccountAtTheEndOfMonth,
+} from 'client-finance-v3/dist/client-finance-v3.js';
+
+
+
+const routes = [
+
+  { path: '/desktop/AccountVoucher', component: AccountVoucher },
+
+  { path: '/desktop/AutoGenerateAccountVoucher', component: AutoGenerateAccountVoucher },
+
+  { path: '/desktop/InsertAccountVoucher', component: InsertAccountVoucher },
+
+  { path: '/desktop/UpdateAccountVoucher', component: UpdateAccountVoucher },
+
+  { path: '/desktop/AccountSubject', component: AccountSubject },
+
+  { path: '/desktop/FinanceBasicSetting', component: FinanceBasicSetting },
+
+  { path: '/desktop/Period', component: Period },
+
+  { path: '/desktop/SettleAccountAtTheEndOfMonth', component: SettleAccountAtTheEndOfMonth },
+
+];
+
+
+export default routes;

+ 11 - 0
src/routes/route-role-v3.js

@@ -0,0 +1,11 @@
+
+import {
+    RoleWindow,
+} from 'client-role-v3';
+
+/** 角色窗口 */
+const routes = [
+    { path: '/role-managment/role-window', component: RoleWindow },
+];
+
+export default routes;

+ 19 - 0
src/routes/route-sensor-v3.js

@@ -0,0 +1,19 @@
+import{
+    HumitureChart,
+    HumitureWarningChart,
+    MasterControlRoom
+} from 'client-sensor-v3/dist/client-sensor-v3.js'
+
+const routes = [
+
+    //项目管理员列表
+    { path: '/sensor/HumitureChart', component: HumitureChart},
+    // 已完成项目追踪
+    { path: '/sensor/HumitureWarningChart', component: HumitureWarningChart},
+
+    // 已完成项目追踪
+    { path: '/sensor/masterControlRoom', component: MasterControlRoom},
+      
+  ];
+
+export default routes;

+ 74 - 0
src/routes/route-trace-v3.js

@@ -0,0 +1,74 @@
+// import{
+//     HelloWorld,
+//     TraceList,
+//     TraceDynamic,
+//     ProjectUserList,
+//     ProjectList,
+//     TraceCreate,
+//     TraceUpdate,
+//     Trace,
+//     TraceCommentCreate,
+//     TraceCommentEdit,
+//     TraceTimeLineCreate,
+//     TraceTimeLineEdit,
+//     UserNotFinishedTrace,
+//     UseFinishedTrace,
+//     NotFinishedProjectTraces,
+//     FinishedProjectTraces,
+//     TeamList,
+//     TraceConfig,
+//     ProjectArchive,
+//     ProjectManagement,
+//     ProjectAdminUserList,
+//     CompleteProjectList,
+// } from 'client-trace-v3/dist/client-trace-v3.js'
+
+
+// const routes = [
+
+//     { path: '/trace/hello-world', component: HelloWorld},
+  
+//     // 追踪单主界面
+//     // { path: '/trace/traceMenu/:uuid', component: TraceMenu},
+//     { path: '/trace/traceList/:traceState', component: TraceList},
+//     { path: '/trace/traceDynamic', component: TraceDynamic},
+//     //项目人员列表
+//     { path: '/trace/projectUserList/:projectId', component: ProjectUserList},
+//     // 项目追踪
+//     { path: '/trace/projectList', component: ProjectList},
+//     // 追踪单主界面-新建追踪单
+//     { path: '/trace/traceCreate/:projectId', component: TraceCreate},
+//     { path: '/trace/traceUpdate/:traceId', component: TraceUpdate},
+//     // 追踪单主界面(追踪列表)-追踪单		
+//     { path: '/trace/trace/:traceId', component: Trace},
+//     // 创建追踪单评论信息
+//     { path: '/trace/traceCommentCreate/:traceId', component: TraceCommentCreate},
+//     // 创建追踪单评论信息
+//     { path: '/trace/traceCommentEdit/:traceCommentId', component: TraceCommentEdit},
+//     // 创建追踪单时间节点
+//     { path: '/trace/traceTimeLineCreate/:traceId', component: TraceTimeLineCreate},
+//     // 创建追踪单时间节点
+//     { path: '/trace/traceTimeLineEdit/:traceTimeLineId', component: TraceTimeLineEdit},
+//     // 个人未完成的任务
+//     { path: '/trace/userNotFinishedTrace/:userId', component: UserNotFinishedTrace},
+//     // 个人已完成的任务
+//     { path: '/trace/useFinishedTrace/:userId', component: UseFinishedTrace},
+//     // 未完成的项目任务
+//     { path: '/trace/notFinishedProjectTraces/:projectId', component: NotFinishedProjectTraces},
+//     // 已完成的项目任务
+//     { path: '/trace/finishedProjectTraces/:projectId', component: FinishedProjectTraces },
+//     { path: '/trace/teamList', component: TeamList},
+//     //任务配置
+//     { path: '/trace/traceConfig', component: TraceConfig },
+//     // 项目归档界面
+//     { path: '/trace/projectArchive/:projectId', component: ProjectArchive},
+//     // 项目管理图
+//     { path: '/trace/projectManagement/:projectId', component: ProjectManagement},
+//     //项目管理员列表
+//     { path: '/trace/projectAdminUserList/:projectId', component: ProjectAdminUserList},
+//     // 已完成项目追踪
+//     { path: '/trace/completeProjectList', component: CompleteProjectList},
+      
+//   ];
+
+// export default routes;

+ 466 - 0
src/routes/route-wms-v5.js

@@ -0,0 +1,466 @@
+import {
+  HelloWorld,
+  WmsSetting,
+  GradeDefinition,
+  GeneratePosition,
+  InventoryPrint,
+  InventoryPrintScan,
+  StockOutPrepareLine,
+  PickingCar,
+  StockOutPrepareApproved,
+  StockOutPrepateTemplate,
+  StockOutPrepateTemplateRecording,
+  StockOutPrepareTemplateApproved,
+  StockOutPrepareLineAddProject,
+  StockOutPrepareLineProjectReceivingAddress,
+  StockOutPrepareLineProjectShippingAddress,
+  PurchaseOrderLinePrint,
+  PositionPrint,
+  PurchaseOrderPrint,
+  QueryPurchaseOrderLine,
+  PackInventoryInstance,
+  NeedPrint,
+  Printed,
+  PrintInventoryInstance,
+  CheckProfit,
+  CheckLoss,
+  StockInLineInstance,
+  StockOutLineInstance,
+  PurchaseOrderLineTraceEdit,
+  CurrentStock,
+  StockLedger,
+  GenerateToolRequest,
+  AutoGenerateInventorySafeStock,
+  AutoGenerateInventoryClassSafeStock,
+  ProjectItemAdjust,
+  InvoiceGenerate,
+  BalanceInventory,
+  VouchCheck,
+  ExpressInquiry,
+  RepertoryCheck,
+  InventorySearchDetail,
+  GenerateDocumentTool,
+  InventoryCheckLoss,
+  AdjustPositions,
+  CurrentStockProjectItemManger,
+  UploadTrainingVideo,
+  SynchronousMaintenanceForm,
+  QueryMaintenancePlan,
+  LightSetting,
+  LightStockInOrOut,
+  ShelfBoard,
+} from 'client-wms-v5/dist/client-wms-v5.js';
+
+
+
+const routes = [
+
+  { path: '/wms/hello-world', component: HelloWorld },
+
+  // 仓库设置
+  {
+    path: '/wms/wmsSetting', component: WmsSetting,
+    meta: {
+      'loginRequired': true,
+      'functionAccessArray': [
+        {
+          'functionNo': '20220328_095118',
+          'itemNo': '1',
+        },
+      ],
+    },
+  },
+
+  // 编码定义
+  {
+    path: '/wms/gradeDefinition', component: GradeDefinition,
+    meta: {
+      'loginRequired': true,
+      'functionAccessArray': [
+        {
+          'functionNo': '20220328_095118',
+          'itemNo': '1',
+        },
+      ],
+    },
+  },
+
+  // 生成货位
+  { path: '/wms/generatePosition/:uuid', component: GeneratePosition },
+
+  // 采购入库打印
+  {
+    path: '/wms/inventoryPrint', component: InventoryPrint,
+    meta: {
+      'loginRequired': true,
+      'functionAccessArray': [
+        {
+          'functionNo': '20220328_095118',
+          'itemNo': '1',
+        },
+      ],
+    },
+  },
+
+  // 扫描入库打印
+  {
+    path: '/wms/inventoryPrintScan', component: InventoryPrintScan,
+    meta: {
+      'loginRequired': true,
+      'functionAccessArray': [
+        {
+          'functionNo': '20220328_095118',
+          'itemNo': '1',
+        },
+      ],
+    },
+  },
+
+  // 领用界面
+  {
+    path: '/wms/stockOutPrepareLine', component: StockOutPrepareLine,
+    meta: {
+      'loginRequired': true,
+      'functionAccessArray': [
+        {
+          'functionNo': '20220328_095537',
+          'itemNo': '5',
+        },
+      ],
+    },
+  },
+
+  // 领料车界面
+  {
+    path: '/wms/pickingCar', component: PickingCar,
+    meta: {
+      'loginRequired': true,
+      'functionAccessArray': [
+        {
+          'functionNo': '20220328_095537',
+          'itemNo': '5',
+        },
+      ],
+    },
+  },
+
+  // 领用记录,审批意见完成
+  {
+    path: '/wms/stockOutPrepareApproved', component: StockOutPrepareApproved,
+    meta: {
+      'loginRequired': true,
+      'functionAccessArray': [
+        {
+          'functionNo': '20220328_095537',
+          'itemNo': '5',
+        },
+      ],
+    },
+  },
+
+  // 需求模板领料
+  {
+    path: '/wms/stockOutPrepateTemplate', component: StockOutPrepateTemplate,
+    meta: {
+      'loginRequired': true,
+      'functionAccessArray': [
+        {
+          'functionNo': '20220328_095537',
+          'itemNo': '5',
+        },
+      ],
+    },
+  },
+
+  // 需求模板领料待提交记录
+  {
+    path: '/wms/stockOutPrepateTemplateRecording', component: StockOutPrepateTemplateRecording,
+    meta: {
+      'loginRequired': true,
+      'functionAccessArray': [
+        {
+          'functionNo': '20220328_095537',
+          'itemNo': '5',
+        },
+      ],
+    },
+  },
+
+  // 需求模板领料已提交记录
+  {
+    path: '/wms/stockOutPrepareTemplateApproved', component: StockOutPrepareTemplateApproved,
+    meta: {
+      'loginRequired': true,
+      'functionAccessArray': [
+        {
+          'functionNo': '20220328_095537',
+          'itemNo': '5',
+        },
+      ],
+    },
+  },
+
+  // 领料跳转添加项目
+  {
+    path: '/wms/stockOutPrepareLineAddProject', component: StockOutPrepareLineAddProject,
+    meta: {
+      'loginRequired': true,
+      'functionAccessArray': [
+        {
+          'functionNo': '20220328_095537',
+          'itemNo': '5',
+        },
+      ],
+    },
+  },
+
+  // 项目事件收货信息
+  // eslint-disable-next-line
+    {
+    path: '/wms/stockOutPrepareLineProjectReceivingAddress', component: StockOutPrepareLineProjectReceivingAddress,
+    meta: {
+      'loginRequired': true,
+      'functionAccessArray': [
+        {
+          'functionNo': '20220328_095537',
+          'itemNo': '5',
+        },
+      ],
+    },
+  },
+
+  // 项目事件发货信息
+  // eslint-disable-next-line
+    {
+    path: '/wms/stockOutPrepareLineProjectShippingAddress', component: StockOutPrepareLineProjectShippingAddress,
+    meta: {
+      'loginRequired': true,
+      'functionAccessArray': [
+        {
+          'functionNo': '20220328_095537',
+          'itemNo': '5',
+        },
+      ],
+    },
+  },
+
+  // 采购订单明细打印
+  { path: '/wms/purchaseOrderLinePrint', component: PurchaseOrderLinePrint },
+
+  // 货位打印
+  { path: '/wms/positionPrint/:uuid', component: PositionPrint },
+
+  // 采购订单打印改
+  { path: '/wms/purchaseOrderPrint', component: PurchaseOrderPrint },
+
+  //采购订单打印
+  { path: '/wms/queryPurchaseOrderLine', component: QueryPurchaseOrderLine },
+
+  { path: '/wms/packInventoryInstance', component: PackInventoryInstance },
+
+  { path: '/wms/needPrint', component: NeedPrint },
+
+  { path: '/wms/printed', component: Printed },
+  {
+    path: '/wms/printInventoryInstance', component: PrintInventoryInstance,
+    children: [
+      {
+        path: '/',
+        redirect: 'needPrint',
+      },
+      {
+        path: 'needPrint',
+        component: NeedPrint,
+      },
+      {
+        path: 'printed',
+        component: Printed,
+      }],
+  },
+
+  // 盘点单盘盈数据处理
+  {
+    path: '/wms/checkProfit/:uuid', component: CheckProfit,
+    meta: {
+      'loginRequired': true,
+      'functionAccessArray': [
+        {
+          'functionNo': '20220328_095537',
+          'itemNo': '4',
+        },
+      ],
+    },
+  },
+
+  // 盘点单盘亏数据处理
+  {
+    path: '/wms/checkLoss/:uuid', component: CheckLoss,
+    meta: {
+      'loginRequired': true,
+      'functionAccessArray': [
+        {
+          'functionNo': '20220328_095537',
+          'itemNo': '4',
+        },
+      ],
+    },
+  },
+
+  // 入库单指定存货实例
+  { path: '/wms/stockInLineInstance/:uuid', component: StockInLineInstance },
+
+  // 出库单指定存货实例
+  { path: '/wms/stockOutLineInstance/:uuid', component: StockOutLineInstance },
+
+  { path: '/wms/purchaseOrderLine-trace-edit', component: PurchaseOrderLineTraceEdit },
+
+  // 西门字库存查询
+  {
+    path: '/wms/currentStock', component: CurrentStock,
+    meta: {
+      'loginRequired': true,
+      'functionAccessArray': [
+        {
+          'functionNo': '20220328_095537',
+          'itemNo': '7',
+        },
+      ],
+    },
+  },
+
+  // 仓库库存台账
+  {
+    path: '/wms/stockLedger', component: StockLedger,
+    meta: {
+      'loginRequired': true,
+      'functionAccessArray': [
+        {
+          'functionNo': '20220328_095537',
+          'itemNo': '7',
+        },
+      ],
+    },
+  },
+
+  // 根据工具安全库存生成通用工具月度需求
+  // eslint-disable-next-line
+    { path: '/wms/generateToolRequest/:uuid', component: GenerateToolRequest },
+
+  // 自动生成存货安全库存
+  // eslint-disable-next-line
+    { path: '/wms/autoGenerateInventorySafeStock/:uuid', component: AutoGenerateInventorySafeStock },
+
+  // 自动生成存货分类安全库存
+  // eslint-disable-next-line
+    { path: '/wms/autoGenerateInventoryClassSafeStock/:uuid', component: AutoGenerateInventoryClassSafeStock },
+
+  // 调拨单
+  { path: '/wms/projectItemAdjust', component: ProjectItemAdjust },
+
+  // 发货单
+  {
+    path: '/wms/invoiceGenerate', component: InvoiceGenerate,
+    meta: {
+      'loginRequired': true,
+      'functionAccessArray': [
+        {
+          'functionNo': '20220328_095537',
+          'itemNo': '6',
+        },
+      ],
+    },
+  },
+
+  // 结存
+  {
+    path: '/wms/balanceInventory', component: BalanceInventory,
+    meta: {
+      'loginRequired': true,
+      'functionAccessArray': [
+        {
+          'functionNo': '20220328_095537',
+          'itemNo': '7',
+        },
+      ],
+    },
+  },
+
+  // 生成明细
+  {
+    path: '/wms/vouchCheck/:uuid', component: VouchCheck,
+    meta: {
+      'loginRequired': true,
+      'functionAccessArray': [
+        {
+          'functionNo': '20220328_095537',
+          'itemNo': '4',
+        },
+      ],
+    },
+  },
+
+  // 快递物流信息查询
+  { path: '/wms/expressInquiry/:uuid', component: ExpressInquiry },
+
+  // 生成明细
+  {
+    path: '/wms/repertoryCheck/:uuid', component: RepertoryCheck,
+    meta: {
+      'loginRequired': true,
+      'functionAccessArray': [
+        {
+          'functionNo': '20220328_095537',
+          'itemNo': '4',
+        },
+      ],
+    },
+  },
+
+  // 物料查询存货详情
+  // eslint-disable-next-line
+    { path: '/wms/inventorySearchDetail', component: InventorySearchDetail },
+
+  // 生单组件
+  // eslint-disable-next-line
+    { path: '/wms/generate-document/:type/:infoWindowNo/:uuid', component: GenerateDocumentTool },
+
+  { path: '/wms/asset-inventory-check-lose/:uuid', component: InventoryCheckLoss },
+
+  {
+    path: '/wms/adjustPositions', component: AdjustPositions,
+    meta: {
+      'loginRequired': true,
+      'functionAccessArray': [
+        {
+          'functionNo': '20220328_095537',
+          'itemNo': '7',
+        },
+      ],
+    },
+  },
+
+
+  // 我管理项目的库存查询
+  {
+    path: '/wms/currentStockProjectItemManger', component: CurrentStockProjectItemManger,
+    meta: {
+      'loginRequired': true,
+      'functionAccessArray': [
+        {
+          'functionNo': '20220518_142645',
+          'itemNo': '3',
+        },
+      ],
+    },
+  },
+
+  { path: '/wms/uploadTrainingVideo', component: UploadTrainingVideo },
+  { path: '/wms/synchronousMaintenanceForm', component: SynchronousMaintenanceForm },
+  { path: '/wms/queryMaintenancePlan', component: QueryMaintenancePlan },
+  { path: '/wms/lightSetting', component: LightSetting },
+  { path: '/wms/lightStockInOrOut', component: LightStockInOrOut },
+  { path: '/wms/shelfBoard', component: ShelfBoard },
+];
+
+
+export default routes;

+ 12 - 0
src/store.js

@@ -0,0 +1,12 @@
+
+import { createStore } from 'vuex';
+import { downloadStore } from 'client-base-v5/dist/client-base-v5.js';
+
+const store = createStore({
+    modules: {
+        downloadStore,
+    },
+});
+
+
+export { store };

+ 106 - 0
webpack.base.js

@@ -0,0 +1,106 @@
+var path = require('path');
+const { VueLoaderPlugin } = require('vue-loader');
+const ESLintPlugin = require('eslint-webpack-plugin');
+const MiniCssExtractPlugin = require('mini-css-extract-plugin');
+
+module.exports = {
+  module: {
+    rules: [
+      {
+        test: /\.vue$/,
+        loader: 'vue-loader',
+      },
+      {
+        test: /\.js$/,
+        loader: 'babel-loader',
+        // include: [        
+        //   path.resolve(__dirname, './node_modules/pc-component-v3/dist/pc-component-v3.js'),      
+        // ],
+        exclude: /node_modules/,
+        // exclude: file => (
+        //   /node_modules/.test(file) &&
+        //   !/\.vue\.js/.test(file)
+        // ),
+      },
+      {
+        test: /\.css$/,
+        use: (process.env.NODE_ENV === 'production') ? [
+          {
+            loader: MiniCssExtractPlugin.loader,
+            options: {
+              publicPath: '../',
+            },
+          },
+          'css-loader'] : ['style-loader', 'css-loader'],
+      },
+      {
+        test: /\.(json5?|ya?ml)$/, // target json, json5, yaml and yml files
+        type: 'javascript/auto',
+        loader: '@intlify/vue-i18n-loader',
+        include: [ // Use `Rule.include` to specify the files of locale messages to be pre-compiled
+          //path.resolve(__dirname, 'src/locales'),
+          path.resolve(__dirname, 'client-base-v5/src/locales'),
+          path.resolve(__dirname, 'client-eam-v5/src/locales'),
+          path.resolve(__dirname, 'client-role-v3/src/locales'),
+        ],
+      },
+      {
+        // webpack5 通过资源模块来处理图片
+        test: /\.(png|jpg|gif|svg)$/,
+        type: 'asset/resource',
+        parser: {
+          dataUrlCondition: {
+            maxSize: 10240,
+          },
+        },
+        generator: {
+          filename: './client-v5-image/[name][ext][query]',
+        },
+      },
+      {
+        test: /\.(eot|woff|woff2|ttf)$/,
+        type: 'asset/resource',
+        generator: {
+          filename: './client-v5-font/[name].[ext]?[hash]',
+        },
+      },
+    ],
+  },
+  resolve: {
+
+    alias: {
+      //   'vue$': 'vue/dist/vue.esm.js',
+      '@static': path.resolve('static'),
+    },
+    extensions: ['*', '.js', '.vue', '.json'],
+  },
+  performance: {
+    hints: false,
+  },
+  
+  externals: {
+    jquery: 'window.jquery',
+    bootstrap: 'bootstrap',
+    BootstrapDialog: 'BootstrapDialog',
+    d3: 'd3',
+    echarts: 'echarts',
+    dayjs: 'dayjs',
+    'vue': 'Vue',
+    'vue-i18n': 'VueI18n',
+    'vue-router': 'VueRouter',
+    'vuex': 'Vuex',
+    'Vuex': 'Vuex',
+    'axios': 'axios',
+    'sortablejs': 'Sortable'
+  },
+  
+  plugins: [
+    new VueLoaderPlugin(),
+    // new ESLintPlugin({
+    //   extensions: ['js', 'vue'],
+    //   // 自动修复。
+    //   // 自从eslint推出--fix命令后,如果觉得eslint格式化规则已经够用的话,其实也可以不用prettier了。
+    //   fix: true,
+    // }),
+  ],
+};

+ 146 - 0
webpack.dev.js

@@ -0,0 +1,146 @@
+const path = require('path');
+const HtmlWebpackPlugin = require('html-webpack-plugin');
+const WebpackMerge = require('webpack-merge');
+const baseConfig = require('./webpack.base.js');
+
+module.exports = WebpackMerge.merge(baseConfig, {
+  mode: 'development',
+  //开发环境下默认启用cache,在内存中对已经构建的部分进行缓存
+  //避免其他模块修改,但是该模块未修改时候,重新构建,能够更快的进行增量构建
+  //属于空间换时间的做法
+  cache: true,
+  
+  // 代码入口
+  entry: {
+    // 注册界面
+    main: './src/main.js',
+  },
+
+  output: {
+    path: path.resolve(__dirname, '../dist'),
+    publicPath: '/',
+    filename: 'app-client-[name].js',
+    chunkFilename: 'app-client-chunk-[name].js',
+  },
+
+  watchOptions: {
+    ignored: ['**/node_modules', '/bat/', '/dist/', '/public/', '/static/', '/test/'],
+    poll: 2000,
+  },
+
+  devServer: {
+
+    port: 8080,
+    compress: false,
+
+
+    static: [
+      {
+        directory: path.join(__dirname, 'client-base-v5/static'),
+        publicPath: '/static',
+      },
+      {
+        directory: path.join(__dirname, 'client-base-v5/public'),
+        publicPath: '/',
+      },
+    ],
+
+    // historyApiFallback: true,
+    // historyApiFallback: {
+    //   rewrites: [
+    //     { from: /.*/, to: path.posix.join('/', 'index.html') },
+    //   ],
+    // },
+
+    headers: {
+      'Access-Control-Allow-Origin': '*',
+      // eslint-disable-next-line max-len
+      //'Content-Security-Policy': 'upgrade-insecure-requests; default-src \'none\'; base-uri \'self\'; frame-ancestors \'none\'; script-src \'self\' \'nonce-11111\'; connect-src \'self\'; form-action \'self\'; frame-src \'self\'; img-src \'self\'; font-src \'self\'; style-src \'self\' \'nonce-11111\'; manifest-src \'none\'; worker-src \'self\'; media-src \'self\'; object-src \'self\';',
+    },
+    
+    proxy: {
+      '/api': {
+        target: 'http://192.168.1.113:10026/',
+        ws: false,
+        changeOrigin: true,
+        secure:true,
+      },
+      '/static': {
+        target: 'http://192.168.1.113:10026/',
+        ws: false,
+        changeOrigin: true,
+        secure:true,
+      },
+      '/content': {
+        target: 'http://192.168.1.113:10026/',
+        ws: false,
+        changeOrigin: true,
+        secure:true,
+      },
+      '/dashboard': {
+        target: 'http://192.168.1.113:10026/',
+        ws: false,
+        changeOrigin: true,
+        secure:true,
+      },
+      '/assets': {
+        target: 'http://192.168.1.113:10026/',
+        ws: false,
+        changeOrigin: true,
+        secure:true,
+      },
+      '/mock': {
+        target: 'http://192.168.1.113:10026/',
+        ws: false,
+        changeOrigin: true,
+        secure:true,
+      },
+      '/authApi': {
+        target: 'http://192.168.1.113:10026/',
+        ws: false,
+        changeOrigin: true,
+        secure:true,
+      },
+      '/Dictionary': {
+        target: 'http://192.168.1.113:10026/',
+        ws: false,
+        changeOrigin: true,
+        secure:true,
+      },
+      '/Files': {
+        target: 'http://192.168.1.113:10026/',
+        ws: false,
+        changeOrigin: true,
+        secure:true,
+      },
+      '/WebSocket': {
+        target: 'http://192.168.1.113:10026/',
+        ws: true,
+        changeOrigin: true,
+      },
+      '/TrainVideo': {
+        target: 'http://192.168.1.113:10026/',
+        ws: true,
+        changeOrigin: true,
+      },
+      '/gateway-api': {
+        target: 'http://192.168.1.113:10026/',
+        ws: true,
+        changeOrigin: true,
+        secure:true,
+      },
+    },
+  },
+
+  devtool: 'source-map',
+
+
+  plugins: (module.exports.plugins || []).concat([
+    new HtmlWebpackPlugin({
+      title: 'Prodog',
+      template: './public/index-debug.html',   // 源模板文件
+      filename: './index.html',                   // 输出文件【注意:这里的根路径是module.exports.output.path】
+      chunks: ['main'],
+    }),
+  ]),
+});

+ 85 - 0
webpack.prod.js

@@ -0,0 +1,85 @@
+const path = require('path');
+const webpack = require('webpack');
+const MiniCssExtractPlugin = require('mini-css-extract-plugin');
+const HtmlWebpackPlugin = require('html-webpack-plugin');
+const WebpackMerge = require('webpack-merge');
+const baseConfig = require('./webpack.base.js');
+const TerserPlugin = require('terser-webpack-plugin');
+const { CleanWebpackPlugin } = require('clean-webpack-plugin');
+const CopyPlugin = require('copy-webpack-plugin');
+module.exports =  WebpackMerge.merge(baseConfig, {
+  mode: 'production',
+  //开发环境下默认启用cache,在内存中对已经构建的部分进行缓存
+  //避免其他模块修改,但是该模块未修改时候,重新构建,能够更快的进行增量构建
+  //属于空间换时间的做法
+  cache: true,
+  // 代码入口
+  entry: {
+    // 注册界面
+    main: './src/main.js',
+  },
+
+  output: {
+    path: path.resolve(__dirname, './dist'),
+    publicPath: './',
+    filename: './client-v5-js-bundle/[name].[contenthash:8].js',
+    chunkFilename: './client-v5-js-chunk/[name].[contenthash:8].js',
+  },
+
+  optimization: {
+    minimize: true,    // 压缩 bundle
+    minimizer: [new TerserPlugin({
+      parallel: true, //使用多进程并发运行以提高构建速度 Boolean|Number 默认值: true  
+      terserOptions: {
+        format: {
+          comments: false,//删除注释
+        },
+      },
+      extractComments: false, //不将注释提取到单独的文件中
+    })],
+    splitChunks: {
+      // include all types of chunks
+      chunks: 'all',
+      name: false,
+      minSize: 30000,
+      maxSize: 500000,
+      cacheGroups: {
+        common: {
+          test: /[\\/]node_modules[\\/]/,
+          name: 'common',
+          chunks: 'initial',
+          priority: 2,
+          minChunks: 2,
+        },
+      },
+    },
+  },
+
+  
+  //devtool: 'source-map',  // 打包不需要 source-map,注释掉本行,打包的时候,不生成 source-map
+
+  plugins: (module.exports.plugins || []).concat([
+    // 清除dist文件夹
+    new CleanWebpackPlugin(),
+    
+    new HtmlWebpackPlugin({
+      title: 'Prodog',
+      template: './public/index-release.html',  // 源模板文件
+      filename: './index.html', // 输出文件【注意:这里的根路径是module.exports.output.path】
+      chunks: ['main'],
+    }),
+
+    // CSS 提取
+    new MiniCssExtractPlugin({
+      filename: './client-v5-style/[name].[contenthash:8].css',
+    }),
+    new CopyPlugin({
+      patterns: [
+        { from: './public/oalogin.html', to: '' },
+        { from: './public/casLogin.html', to: '' },
+        { from: './public/ssoLogin.html', to: '' },
+        { from: './public/favicon.ico', to: '' },
+      ],
+    }),
+  ]),
+});