yangxiao 3 年之前
父節點
當前提交
b800caf933

+ 4 - 0
package.json

@@ -9,12 +9,16 @@
     "lint": "vue-cli-service lint"
   },
   "dependencies": {
+    "axios": "^0.21.1",
     "core-js": "^3.6.5",
     "echarts": "^5.1.1",
     "echarts-gl": "^2.0.4",
+    "element-plus": "^1.0.2-beta.46",
     "font-awesome": "^4.7.0",
+    "stompjs": "^2.3.3",
     "vivus": "^0.4.6",
     "vue": "^3.0.0",
+    "vue-axios": "^3.2.4",
     "vue-router": "^4.0.0-0",
     "vuex": "^4.0.0-0"
   },

+ 22 - 0
public/static/config/modeConfig.js

@@ -0,0 +1,22 @@
+
+// 本地联调开关
+const localTest = 0;
+
+// 服务器地址
+let baseURL = null;
+
+// websocket 服务器地址
+let websocketUrl = null;
+
+if (localTest) {
+  baseURL = "http://192.168.10.23:8082/" // 联机调试 - 石林
+  websocketUrl = (baseURL.replace(/http:\/\//g, "")) + "gyee-websocket";
+} else {
+  baseURL = "http://10.155.32.4:8082/" // 正式环境
+  websocketUrl = (baseURL.replace(/http:\/\//g, "")) + "gyee-websocket";
+}
+
+window.__MODE__ = {
+  baseURL,
+  websocketUrl
+};

File diff suppressed because it is too large
+ 82 - 106
src/App.vue


+ 32 - 0
src/api/AES.js

@@ -0,0 +1,32 @@
+import CryptoJS from 'crypto-js';
+/**
+ * CryptoJS加密
+ */
+export function localEncrypt(word, keyStr) {
+  keyStr = keyStr ? keyStr : "BTRH201911PERMIS";
+  let key = CryptoJS.enc.Utf8.parse(keyStr);
+  let srcs = CryptoJS.enc.Utf8.parse(word);
+  let encrypted = CryptoJS.AES.encrypt(srcs, key, {
+    mode: CryptoJS.mode.ECB,
+    padding: CryptoJS.pad.Pkcs7
+  });
+  return encrypted.toString();
+}
+
+/**
+ * CryptoJS解密
+ */
+export function localDecrypt(word, keyStr) {
+  keyStr = keyStr ? keyStr : "BTRH201911PERMIS";
+  var key = CryptoJS.enc.Utf8.parse(keyStr);
+  var decrypt = CryptoJS.AES.decrypt(word, key, {
+    mode: CryptoJS.mode.ECB,
+    padding: CryptoJS.pad.Pkcs7
+  });
+  return CryptoJS.enc.Utf8.stringify(decrypt).toString();
+}
+
+export default {
+  localEncrypt,
+  localDecrypt
+}

+ 116 - 0
src/api/axios.js

@@ -0,0 +1,116 @@
+// 引入axios
+import axios from 'axios';
+import BASE from '@tools/basicTool.js';
+
+axios.defaults.withCredentials = true;
+
+/**
+ * 通用请求函数
+ * @param {Object} options 详细配置项,使用方法与所有配置项说明如下:
+
+  this.API.requestData({
+    isMust: true, // 请求是否携带 token ,默认为 true ,可缺省
+    showLoading: false, // 请求是否显示加载中遮罩层,默认 false ,可缺省
+    method: "GET", // 请求方式,默认为 GET ,可缺省
+    baseURL: "http://192.168.10.23:8082/", // 请求服务器地址 + 端口,可缺省
+    subUrl: "api/repassword", // 请求接口地址,必传项
+    timeout: 3000, // 请求超时时间,默认 3s ,可缺省
+    data: { name: "admin", pasword: "123456" }, // 请求所携带参数,默认为空,可缺省
+    success (res) {
+      // 请求成功的回调
+    },
+    fail (error) {
+      // 请求失败的回调
+    }
+  });
+
+ */
+export function requestData (options) {
+  return new Promise((resolve, reject) => {
+
+    if (options.showLoading) {
+      BASE.showLoading();
+    }
+
+    // 包装请求头
+    let headers = options.headers || {
+      'Content-Type': 'application/x-www-form-urlencoded',
+      'Access-Control-Allow-Origin': '*',
+      'Access-Control-Allow-Credentials': 'true'
+    };
+
+    // 请求是否携带 token
+    const isMust = (options.isMust == true || options.isMust == false) ? options.isMust : true;
+    if (isMust) headers.authToken = localStorage.getItem('authToken');
+
+    // 创建请求实例
+    const XHRReq = axios.create({
+      headers,
+      withCredentials: true,
+      crossDomain: true,
+      baseURL: window.__MODE__.baseURL || '/api/',
+      timeout: options.timeout || 3000, // 请求超时时间 - 3s
+    });
+
+    // 请求拦截器
+    XHRReq.interceptors.request.use((config) => {
+      return config;
+    }, (err) => {
+      return Promise.reject(err);
+    });
+
+    // 统一格式包装请求参数
+    let params = new URLSearchParams();
+    for (let key in (options.data || {})) {
+      params.append(key, options.data[key]);
+    }
+
+    // 发起请求
+    XHRReq({
+      url: options.subUrl,
+      method: options.method || 'GET',
+      params,
+    }).then(response => {
+      if (options.showLoading) {
+        BASE.closeLoading();
+      }
+      if (response.code === 501) { // 用户类请求错误code (账号密码错误、用户锁定、token过期等)
+
+        localStorage.removeItem('authToken');
+        BASE.showMsg({
+          msg: (response.data && response.data.msg) || ("请求出错[" + response.data.code + "]")
+        });
+
+        setTimeout(() => {
+          // window.location.reload();
+          // window.__STATICVUE__.$router.replace('/login');
+        }, 1000);
+
+      } else if (response.data.code === 200) { // 请求成功 code
+
+        options.success && options.success(response.data);
+        resolve(response);
+
+      } else { // 其他code
+
+        BASE.showMsg({
+          msg: (response.data && response.data.msg) || ("请求出错[" + response.data.code + "]")
+        });
+
+      }
+    }).catch(error => {
+
+      if (options.showLoading) {
+        BASE.closeLoading();
+      }
+
+      options.fail && options.fail(error);
+      reject(error);
+
+    });
+  });
+}
+
+export default {
+  requestData
+}

+ 13 - 0
src/api/config.js

@@ -0,0 +1,13 @@
+/**
+ * 国电电力宁夏新能源集中监控系统
+ * */
+
+//测试 - 国电
+export default {
+  webSoketUrl: 'ws://10.155.32.4:8082/gyee-websocket', // webSoket
+}
+
+//生产 - 国电
+// export default {
+//   webSoketUrl: '192.168.4.203:9008', // webSoket
+// }

+ 27 - 9
src/main.js

@@ -1,12 +1,30 @@
-import { createApp } from 'vue'
-import App from './App.vue'
-import router from './router'
-import store from './store'
-import 'font-awesome/css/font-awesome.min.css'
+import { createApp } from 'vue';
+import App from './App.vue';
+import router from './router';
+import store from './store';
+import 'font-awesome/css/font-awesome.min.css';
+
+// 引入 element-ui
+import ElementPlus from 'element-plus';
+import 'element-plus/lib/theme-chalk/index.css';
+
+// 引入环境配置
+import "@modeConfig/modeConfig.js";
 
 import "@/lib/global-import.js";
 
-createApp(App)
-    .use(store)
-    .use(router)
-    .mount('#app')
+// 引入请求工具
+import axios from "@api/axios";
+
+// 引入基础工具
+import basicTool from "@tools/basicTool";
+
+window.__STATICVUE__ = createApp(App);
+window.__STATICVUE__.use(ElementPlus);
+window.__STATICVUE__.use(store);
+window.__STATICVUE__.use(router);
+
+window.__STATICVUE__.config.globalProperties.API = axios; //全局注册
+window.__STATICVUE__.config.globalProperties.BASE = basicTool; //全局注册
+
+window.__STATICVUE__.mount('#app');

+ 16 - 15
src/router/index.js

@@ -27,20 +27,20 @@ const routes = [
     name: 'WindSite',
     component: () => import(/* webpackChunkName: "windsite" */ '../views/WindSite/WindSite.vue'),
     children: [{
-        path: 'home',
-        component: () => import(/* webpackChunkName: "windsitehome" */ '../views/WindSite/pages/Home/Home.vue')
-    },{
-        path: 'draughtfanlist',
-        component: () => import(/* webpackChunkName: "windsitedraughtfanlist" */ '../views/WindSite/pages/DraughtFanList.vue')
-    },{
-        path: 'matrix',
-        component: () => import(/* webpackChunkName: "windsitematrix" */ '../views/WindSite/pages/Matrix.vue')
-    },{
-        path: 'lightmatrix',
-        component: () => import(/* webpackChunkName: "windsitelightmatrix" */ '../views/WindSite/pages/LightMatrix.vue')
-    },{
-        path: 'box',
-        component: () => import(/* webpackChunkName: "windsitebox" */ '../views/WindSite/pages/Box.vue')
+      path: 'home',
+      component: () => import(/* webpackChunkName: "windsitehome" */ '../views/WindSite/pages/Home/Home.vue')
+    }, {
+      path: 'draughtfanlist',
+      component: () => import(/* webpackChunkName: "windsitedraughtfanlist" */ '../views/WindSite/pages/DraughtFanList.vue')
+    }, {
+      path: 'matrix',
+      component: () => import(/* webpackChunkName: "windsitematrix" */ '../views/WindSite/pages/Matrix.vue')
+    }, {
+      path: 'lightmatrix',
+      component: () => import(/* webpackChunkName: "windsitelightmatrix" */ '../views/WindSite/pages/LightMatrix.vue')
+    }, {
+      path: 'box',
+      component: () => import(/* webpackChunkName: "windsitebox" */ '../views/WindSite/pages/Box.vue')
     }]
   },
   {
@@ -57,7 +57,7 @@ const routes = [
     path: '/lightmatrix2',
     name: 'LightMatrix2',
     component: () => import(/* webpackChunkName: "lightmatrix2" */ '../views/LightMatrix2/LightMatrix2.vue')
-  },{
+  }, {
     path: '/lightmatrix3',
     name: 'LightMatrix3',
     component: () => import(/* webpackChunkName: "lightmatrix3" */ '../views/LightMatrix3/LightMatrix3.vue')
@@ -66,6 +66,7 @@ const routes = [
 
 const router = createRouter({
   history: createWebHashHistory(),
+  base: '/zhfx/',
   routes
 })
 

+ 48 - 5
src/store/index.js

@@ -1,12 +1,55 @@
-import { createStore, createLogger } from 'vuex'
-import weather from './modules/weather'
+import { createStore, createLogger } from 'vuex';
+import weather from './modules/weather';
+import user from './modules/user';
 
-const debug = process.env.NODE_ENV !== 'production'
+const debug = process.env.NODE_ENV !== 'production';
+
+// 默认状态
+const state = {
+  loading: false, //全局 - 加载中....
+  themeName: "light", // 主题
+  windturbineMap: {},
+};
+
+//改变状态的方法
+const mutations = {
+  loadingStore (state, tag) {
+    state.loading = tag;
+  },
+  changeTheme (state, tag) {
+    state.themeName = tag;
+  },
+  update (state, newData) {
+    state.windturbineMap = newData
+  }
+};
+
+const actions = {
+  getupdate (context, newData) {
+    context.commit("update", newData);
+  },
+};
+
+const getters = {
+  authToken: state => state.user.authToken,  //建立token的快捷访问   user 是因为index.js中导入的时候名称定义为user
+  submitDDTag: state => state.submitDDTag,
+  loading: state => state.loading,
+  username: state => state.user.username,
+  themeName: state => state.themeName,
+  asidez: state => state.z,
+  mainy: state => state.y,
+  login: state => state.login,
+}
 
 export default createStore({
   modules: {
-    weather
+    weather,
+    user
   },
+  state,
+  mutations,
+  actions,
+  getters,
   strict: debug,
   plugins: debug ? [createLogger()] : []
-})
+});

+ 46 - 0
src/store/modules/user.js

@@ -0,0 +1,46 @@
+// import {getToken,setToken,removeToken} from '@/utils/auth'
+// import { Message } from 'element-plus';
+const state = {
+  authToken: '', //
+  username: '',
+}
+const mutations = {
+  REMOVE_TOKEN (state) {
+    localStorage.removeItem('authToken');
+    localStorage.removeItem('username');
+    state.authToken = "";
+    state.username = "";
+    Message({
+      message: '退出成功',
+      type: 'success'
+    });
+    setTimeout(() => {
+      window.location.reload();
+    }, 1000);
+
+  },
+  SET_TOKEN: (state, token_name) => {
+    state.authToken = token_name.token;
+    state.username = token_name.username;
+    localStorage.setItem('authToken', token_name.token);
+    localStorage.setItem('username', token_name.username);
+  },
+  SET_NAME: (state, name) => {
+    state.username = name;
+  },
+}
+const actions = {
+  async login (context, data) {
+    const result = await login(data)
+    if (result.data.sucess) {
+      //调用vuex中setToken方法
+      context.commit('setToken', result.data.data)
+    }
+  }
+}
+export default {
+  namespaced: true,
+  state,
+  mutations,
+  actions,
+}

+ 264 - 0
src/tools/basicTool.js

@@ -0,0 +1,264 @@
+
+let loadingStatus = null;
+
+import { ElMessage } from 'element-plus';
+import { ElLoading } from 'element-plus';
+
+export default {
+  /**
+   * 页面顶部出现消息提示
+   * @param {Object} options 传入一个对象为配置项,其中:
+   * @param {Boolean} showClose 是否显示可手动关闭的 x 于提示框右侧,默认 false
+   * @param {Boolean} center 消息提示内容是否居中,默认 true
+   * @param {String} msg 消息提示的内容
+   * @param {String} type 消息提示的类型,可选值为 ['success(成功)','warning(警告)','error(错误)',或者直接传入空字符串],默认 error
+   */
+  showMsg (options) {
+    ElMessage({
+      showClose: (options.showClose == true || options.showClose == false) ? options.showClose : false,
+      center: (options.center == true || options.center == false) ? options.center : true,
+      message: options.msg,
+      type: (options.type || options.type === '') ? options.type : 'error'
+    });
+  },
+
+  /**
+   * 显示防穿透点击 loading 蒙版
+   * @param {Objectr} opt 传入一个对象为配置项,其中:
+   * @param {String} target 此蒙版需要绑定的 DOM 标签 ID 或者 CLASS 或者 TAGNAME,默认绑在 body 上
+   * @param {Boolean} body 是否插入蒙版至 boyd 上,默认 true
+   * @param {Boolean} fullscreen 蒙版是否全屏蒙住整个 html 页面,默认 true
+   * @param {Boolean} lock 蒙版出现时,是否锁定屏幕滚动,默认 false
+   * @param {String} text 蒙版上显示的提示文本
+   * @param {String} background 蒙版的背景颜色,写死 50% 透明度的纯黑色
+   */
+  showLoading (opt) {
+    let options = opt || {};
+    loadingStatus = ElLoading.service({
+      target: options.target || 'body',
+      body: (options.body == true || options.body == false) ? options.body : false,
+      fullscreen: (options.fullscreen == true || options.fullscreen == false) ? options.fullscreen : true,
+      lock: (options.lock == true || options.lock == false) ? options.lock : false,
+      text: options.text || '请稍等...',
+      background: 'rgba(0,0,0,.5)',
+    });
+  },
+
+  /**
+   * 获取标签上的自定义属性
+   * @param {any} node 传入 字符串 或 标准DOM对象 或 jQuery DOM对象 ,函数自动判断传入的类型并返回其 dataset 属性。
+   */
+  getCurrentData (node) {
+    // 如果传入的是 jQuery 对象
+    if (window.jQuery && node instanceof jQuery) {
+      return node[0].dataset;
+    } else {
+      // 判断传入的是否是标准 DOM 对象
+      let isDom = (typeof node === 'object') ?
+        function (obj) {
+          return obj instanceof HTMLElement;
+        } :
+        function (obj) {
+          return obj && typeof obj === 'object' && obj.nodeType === 1 && typeof obj.nodeName === 'string';
+        };
+
+      // 如果是标准 DOM 对象,输出 dataset
+      if (isDom(node)) {
+        return node.dataset;
+      } else {
+        // 如果是不是,则表示传入的是字符串,根据字符串取 DOM 后输出 dataset
+        let dom = document.querySelector(node);
+        return dom.dataset;
+      }
+    }
+  },
+
+  /**
+   * 关闭loading
+   */
+  closeLoading () {
+    loadingStatus.close();
+  },
+
+  /**
+   * 深拷贝 json 数组
+   * @param {Array} jsonArray 传入 Json 数组,返回一个指向新指针拷贝份数据
+   */
+  deepCopy (jsonArray) {
+    return JSON.parse(JSON.stringify(jsonArray));
+  },
+
+  /**
+   * 根据后端返回的 ID 遍历树形结构包装组件编辑用数据函数
+   * @param {String} key 需要找到的 ID
+   * @param {Array} treeData 树形 Array
+   */
+  getTreeDeepArr (key, treeData) {
+
+    let arr = []; // 在递归时操作的数组
+    let returnArr = []; // 存放结果的数组
+    let depth = 0; // 定义全局层级
+
+    // 定义递归函数
+    function childrenEach (childrenData, depthN) {
+
+      for (var j = 0; j < childrenData.length; j++) {
+
+        depth = depthN; // 将执行的层级赋值 到 全局层级
+        arr[depthN] = (childrenData[j].id);
+
+        if (childrenData[j].id == key) {
+
+          // returnArr = arr; // 原写法不行, 因 此赋值存在指针关系
+          returnArr = arr.slice(0, depthN + 1); //将目前匹配的数组,截断并保存到结果数组
+          break;
+
+        } else {
+
+          if (childrenData[j].children) {
+
+            depth++;
+            childrenEach(childrenData[j].children, depth);
+
+          }
+
+        }
+
+      }
+
+      return returnArr;
+
+    }
+
+    return childrenEach(treeData, depth);
+
+  },
+
+  /**
+   * 获取数据的类型
+   * @param {any} options 传入一个数据,返回其类型 (object, array, string, number等)
+   */
+  getType (options) {
+    return Object.prototype.toString.call(options).slice(8, Object.prototype.toString.call(options).length - 1).toLowerCase();
+  },
+
+  /**
+   * 控制页面滚动到指定位置
+   * @param {Object} options 传入一个配置项,其中:
+   * @param {String} el 需要滚动的 DOM 元素选择器,可以为 CLASS 或 ID
+   * @param {Number} scrollTop 需要滚动到顶部的位置,数值越低滚动的越靠近顶部,默认 0
+   * @param {Number} scrollLeft 需要滚动到顶部的位置,数值越低滚动的越靠近顶部,默认 0
+   * @param {Number} speed 滚动到指定位置需要的时间 (动画时间),默认 200
+   * @param {Function} success 滚动执行完毕后的回调函数
+   */
+  scrollTo (options) {
+    if (!options || !options.el) {
+      this.showMsg({
+        msg: 'scrollTo() 方法需要传入 el 属性'
+      });
+      return;
+    }
+    if ($(options.el)[0] && ($(options.el)[0].scrollHeight > (window.innerHeight || document.documentElement.clientHeight))) {
+      $(options.el).animate({
+        scrollTop: options.scrollTop || 0,
+        scrollLeft: options.scrollLeft || 0,
+      }, options.speed || 200, () => {
+        options.success && options.success();
+      });
+    } else {
+      options.success && options.success();
+    }
+  },
+
+  /**
+   * 导出 Json 为 excel 表格
+   * @param {Object} options 传入一个配置项,根据传入的配置项导出对应的 excel 表格,其中:
+   * @param {Array} tTitle 表格的标题,置空则为默认以日期为标题的表格
+   * @param {Array} tHeader 表格的表头,必传
+   * @param {Array} tBody 表格需要展示的字段名,必传
+   * @param {Array} tMerges 表格标题需要合并的单元格,置空则为默认 A1 格为表格标题显示区域
+   * @param {Array} tData 表格渲染所用的数据源,必传
+   * @param {Boolean} autoWidth 表是否根据表格内容自动撑开列宽,置空则为默认 true 
+   * @param {String} exportName 所导出的表格文件名,置空则以时间戳为文件名称进行导出
+   */
+  exportExcelForJson (options) {
+    const {
+      export_json_to_excel
+    } = __getExport2Excel();
+
+    let title = options.tTitle;
+
+    if (!title || !title.length) {
+      title = []
+      options.tBody.forEach((ele, index) => {
+        if (!index) {
+          title.push(new Date().formatDate("yyyy-MM-dd") + '导出的表格');
+        } else {
+          title.push("");
+        }
+      });
+    }
+
+    let header = options.tHeader;
+    let data = options.tData.map(data => options.tBody.map(key => data[key]));
+    let merges = options.tMerges || [];
+    let filename = options.exportName || new Date().getTime();
+    let bookType = "xlsx";
+    let autoWidth = (options.autoWidth == true || options.autoWidth == false) ? options.autoWidth : true;
+
+    data.map(item => {
+      item.map((i, index) => {
+        if (!i) item[index] = "";
+      });
+    });
+
+    export_json_to_excel({
+      title,
+      header,
+      data,
+      merges,
+      filename,
+      bookType,
+      autoWidth
+    });
+  },
+
+  /**
+   * 颜色进制转换  16 <--> 10 互转
+   * @param {String} colorStr 传入一个颜色字符串, 16进制 或者 10进制 ,返回转换后的结果,例:传入 #1890ff ,返回 rgb(24, 144, 255),反之亦然
+   */
+  replaceColor (colorStr) {
+    if (!colorStr) return '';
+
+    let colorString = colorStr.replace(/#|rgb|\(|\)|\|;|\s+/g, "");
+
+    if (colorString.indexOf(",") === -1) {
+      let color10 = [];
+      for (let i = 0; i < colorString.length; i++) {
+        if (!((i + 1) % 2)) {
+          color10.push(parseInt((colorString[i - 1] + colorString[i]), 16));
+        }
+      }
+      return "rgb(" + color10.toString() + ")";
+    } else {
+      let colorArray = colorString.split(',');
+      let color16 = '';
+      colorArray.forEach(ele => {
+        color16 += (parseInt(ele).toString(16));
+      });
+      return "#" + color16;
+    }
+  },
+
+  // 正则表达式
+  regs: {
+    // 是否为手机号
+    isPhone: /^1(3|4|5|6|7|8|9)\d{9}$/,
+    // 是否为合法 15 或 18 位身份证号
+    isIdentityCard: /^[1-9]\d{7}((0\d)|(1[0-2]))(([0|1|2]\d)|3[0-1])\d{3}$|^[1-9]\d{5}[1-9]\d{3}((0\d)|(1[0-2]))(([0|1|2]\d)|3[0-1])\d{3}([0-9]|X)$/,
+    // 是否是邮箱
+    isMail: /^[a-zA-Z0-9_.-]+@[a-zA-Z0-9-]+(\.[a-zA-Z0-9-]+)*\.[a-zA-Z0-9]{2,6}$/,
+    // 是否是数字
+    isNumber: /^(-?\d+)(\.\d+)?$/
+  }
+};

+ 56 - 0
src/tools/websocket.js

@@ -0,0 +1,56 @@
+import Stomp from "stompjs";
+import store from '@store/index';
+var projectconfig = `ws://${window.__MODE__.websocketUrl}`;
+// ============================一般使用的变量============================
+let number = 0;
+export const datainit = initialize;
+export const webtest = test;
+
+// ============================  大函数体   ============================
+function initialize (topic, adpClient) {
+
+  if (adpClient != null) {
+    adpClient.disconnect();
+  }
+
+  var url = projectconfig;
+  // let socket = new SockJS(url);  // 这个地址要找你们后端
+  // adpClient = Stomp.over(socket);
+  adpClient = Stomp.client(url);
+  adpClient.debug = null;
+
+  adpClient.connect({ topic: topic, authToken: localStorage.getItem('authToken') }, adpClient2 => connectCallBackSubscribe(adpClient, topic), error => reconnect(error, adpClient, topic));
+
+  return adpClient;
+}
+// 断线重连
+function reconnect (error, adpClient, topic) {
+  //连接失败时再次调用函数
+  number++;
+  adpClient.connected = false;
+  clearTimeout(setTimeout(initialize(topic), 1000 * 60 * 5));
+  debugX("DataAdapter reconnect:" + number + " 次");
+  return;
+}
+// ============================  订阅函数体  ============================
+function connectCallBackSubscribe (adpClient, topic) {
+  number = 0;
+  adpClient.connected = true;
+  adpClient.subscribe(topic, stompMessage => reflexWindturbineBasicInformation(stompMessage));
+}
+// ============================  解析函数体  ============================
+function reflexWindturbineBasicInformation (stompMessage) {
+  var newdata = JSON.parse(stompMessage.body);
+  store.dispatch('getupdate', newdata);
+  // console.log("newdata", newdata)
+
+}
+// ============================  其他  ============================
+function debugX (text) {
+  console.log("text", text);
+}
+
+function test () {
+  clearTimeout(setTimeout(initialize('/topic/detial/param_MG01_02'), 1000 * 60 * 2));
+}
+

+ 46 - 43
src/views/LightMatrix/LightMatrix.vue

@@ -7,45 +7,45 @@
       <div class="dot right bottom"></div>
       <Row>
         <Col :span="3">
-          <div class="panel-item-gf">
-            <div class="panel-item-gf-left">
-              <span class="svg-icon svg-icon-write svg-icon-md">
-                <SvgIcon :svgid="panelData.first.icon"></SvgIcon>
+        <div class="panel-item-gf">
+          <div class="panel-item-gf-left">
+            <span class="svg-icon svg-icon-write svg-icon-md">
+              <SvgIcon :svgid="panelData.first.icon"></SvgIcon>
+            </span>
+          </div>
+          <div class="panel-item-gf-right">
+            <div class="panel-item-gf-up">{{ panelData.first.text }}</div>
+            <div class="panel-item-gf-down">{{ panelData.first.num }}</div>
+          </div>
+        </div>
+        </Col>
+        <Col :span="3" v-for="(data, index) of panelData.datas" :key="index">
+        <div class="panel-item" :class="data.color">
+          <div class="panel-item-left">
+            <div class="panel-item-li">
+              <span>{{ data.name }}</span>
+              <span class="svg-icon svg-icon-sm" :class="'svg-icon-' + data.color">
+                <SvgIcon :svgid="data.nameIcon"></SvgIcon>
               </span>
             </div>
-            <div class="panel-item-gf-right">
-              <div class="panel-item-gf-up">{{ panelData.first.text }}</div>
-              <div class="panel-item-gf-down">{{ panelData.first.num }}</div>
+            <div class="panel-item-li">
+              <span>{{ data.num }}</span>
+              <span class="svg-icon svg-icon-sm" :class="'svg-icon-' + data.color">
+                <SvgIcon :svgid="data.numIcon"></SvgIcon>
+              </span>
             </div>
           </div>
-        </Col>
-        <Col :span="3" v-for="(data, index) of panelData.datas" :key="index">
-          <div class="panel-item" :class="data.color">
-            <div class="panel-item-left">
-              <div class="panel-item-li">
-                <span>{{ data.name }}</span>
-                <span class="svg-icon svg-icon-sm" :class="'svg-icon-' + data.color">
-                  <SvgIcon :svgid="data.nameIcon"></SvgIcon>
-                </span>
-              </div>
-              <div class="panel-item-li">
-                <span>{{ data.num }}</span>
-                <span class="svg-icon svg-icon-sm" :class="'svg-icon-' + data.color">
-                  <SvgIcon :svgid="data.numIcon"></SvgIcon>
-                </span>
-              </div>
+          <div class="panel-item-right">
+            <div class="panel-item-ri">
+              <span>{{ data.text1 }}</span>
+              <span>{{ data.num1 }}</span>
             </div>
-            <div class="panel-item-right">
-              <div class="panel-item-ri">
-                <span>{{ data.text1 }}</span>
-                <span>{{ data.num1 }}</span>
-              </div>
-              <div class="panel-item-ri">
-                <span>{{ data.text2 }}</span>
-                <span>{{ data.num2 }}</span>
-              </div>
+            <div class="panel-item-ri">
+              <span>{{ data.text2 }}</span>
+              <span>{{ data.num2 }}</span>
             </div>
           </div>
+        </div>
         </Col>
       </Row>
     </div>
@@ -107,6 +107,7 @@ import Row from "@com/coms/grid/row.vue";
 import Col from "@com/coms/grid/col.vue";
 import SvgIcon from "@com/coms/icon/svg-icon.vue";
 import util from "@/helper/util.js";
+
 export default {
   // 名称
   name: "LightMatrix",
@@ -117,7 +118,7 @@ export default {
     SvgIcon,
   },
   // 数据
-  data() {
+  data () {
     return {
       panelData: {
         first: {
@@ -300,9 +301,10 @@ export default {
       ],
     };
   },
+
   // 函数
   methods: {
-    createGroupDatas: function(table) {
+    createGroupDatas: function (table) {
       table.groupDatas = [];
       let tempDatas = [];
       table.datas.forEach((data, index) => {
@@ -321,10 +323,10 @@ export default {
     },
   },
   // 生命周期钩子
-  beforeCreate() {
+  beforeCreate () {
     // 创建前
   },
-  created() {
+  created () {
     // 创建后
     let tempData = [];
     for (let i = 0; i < 45; i++) {
@@ -354,18 +356,19 @@ export default {
       this.tables.push(util.copy(this.tables[0]));
     }
   },
-  beforeMount() {
+  beforeMount () {
     // 渲染前
   },
-  mounted() {
-    // 渲染后
+  mounted () {
+    let that = this;
+    that.$nextTick(() => { });
   },
-  beforeUpdate() {
+  beforeUpdate () {
     // 数据更新前
   },
-  updated() {
+  updated () {
     // 数据更新后
-  },
+  }
 };
 </script>
 
@@ -654,7 +657,7 @@ export default {
 
           .sub-count {
             font-size: @fontsize;
-            font-family: "Bicubik";
+            font-family: 'Bicubik';
             font-weight: 500;
 
             &.write {

File diff suppressed because it is too large
+ 585 - 561
src/views/LightMatrix1/LightMatrix1.vue


+ 155 - 123
vue.config.js

@@ -2,134 +2,166 @@ const path = require("path");
 const resolve = (dir) => path.join(__dirname, dir);
 // const SVGSpriteLoaderPlugin = require("svg-sprite-loader/plugin");
 
-function extendDefaultPlugins(arr) {
-    let plug = [
-        'removeDoctype',
-        'removeXMLProcInst',
-        'removeComments',
-        'removeMetadata',
-        'removeEditorsNSData',
-        'cleanupAttrs',
-        'mergeStyles',
-        'inlineStyles',
-        'minifyStyles',
-        'cleanupIDs',
-        'removeUselessDefs',
-        'cleanupNumericValues',
-        'convertColors',
-        'removeUnknownsAndDefaults',
-        'removeNonInheritableGroupAttrs',
-        'removeUselessStrokeAndFill',
-        'removeViewBox',
-        'cleanupEnableBackground',
-        'removeHiddenElems',
-        'removeEmptyText',
-        'convertShapeToPath',
-        'convertEllipseToCircle',
-        'moveElemsAttrsToGroup',
-        'moveGroupAttrsToElems',
-        'collapseGroups',
-        'convertPathData',
-        'convertTransform',
-        'removeEmptyAttrs',
-        'removeEmptyContainers',
-        'mergePaths',
-        'removeUnusedNS',
-        'sortDefsChildren',
-        'removeTitle',
-        'removeDesc'
-    ];
-    return plug.concat(arr);
+function extendDefaultPlugins (arr) {
+  let plug = [
+    'removeDoctype',
+    'removeXMLProcInst',
+    'removeComments',
+    'removeMetadata',
+    'removeEditorsNSData',
+    'cleanupAttrs',
+    'mergeStyles',
+    'inlineStyles',
+    'minifyStyles',
+    'cleanupIDs',
+    'removeUselessDefs',
+    'cleanupNumericValues',
+    'convertColors',
+    'removeUnknownsAndDefaults',
+    'removeNonInheritableGroupAttrs',
+    'removeUselessStrokeAndFill',
+    'removeViewBox',
+    'cleanupEnableBackground',
+    'removeHiddenElems',
+    'removeEmptyText',
+    'convertShapeToPath',
+    'convertEllipseToCircle',
+    'moveElemsAttrsToGroup',
+    'moveGroupAttrsToElems',
+    'collapseGroups',
+    'convertPathData',
+    'convertTransform',
+    'removeEmptyAttrs',
+    'removeEmptyContainers',
+    'mergePaths',
+    'removeUnusedNS',
+    'sortDefsChildren',
+    'removeTitle',
+    'removeDesc'
+  ];
+  return plug.concat(arr);
 }
 
 // 添加less继承
-function addStyleResource(rule) {
-    rule.use('style-resource')
-        .loader('style-resources-loader')
-        .options({
-            patterns: [
-                resolve('src/assets/styles/common/common.less')
-            ]
-        })
+function addStyleResource (rule) {
+  rule.use('style-resource')
+    .loader('style-resources-loader')
+    .options({
+      patterns: [
+        resolve('src/assets/styles/common/common.less')
+      ]
+    })
 }
 
 
 module.exports = {
-    chainWebpack: (config) => {
-
-        // 路径别名
-        config.resolve.alias
-            .set("@", resolve("src"))
-            .set("@node", resolve("node_modules"))
-            .set("@com", resolve("src/components"))
-            .set("@assets", resolve("src/assets"));
-
-        // less 继承
-        const types = ['vue-modules', 'vue', 'normal-modules', 'normal'];
-        types.forEach(type => addStyleResource(config.module.rule('less').oneOf(type)));
-
-        // svg 雪碧图
-        config.module // 排除其他svg-loader
-            .rule('svg')
-            .exclude.add(resolve('src/assets/icon/svg'))
-            .end()
-            .exclude.add(resolve('src/assets/icon/svg_fill'))
-            .end();
-
-        // svg雪碧图
-        const svgRule = config.module.rule('icons');
-        svgRule.test(/\.svg$/)
-            .include.add(resolve('src/assets/icon/svg'))
-            .end()
-            .use('svg-sprite-loader')
-            .loader('svg-sprite-loader')
-            .options({
-                symbolId: 'svg-[name]',
-                // extract: true,
-                // publicPath: "img/",
-                // spriteFilename: "svg-sprite-[hash:8].svg",
-            });
-
-        // config
-        //     .plugin("svgsprite")
-        //     .use(SVGSpriteLoaderPlugin, [{ 
-        //       plainSprite: true
-        //     }]);
-
-        // svgo 去除svg中无用元素
-        svgRule.use('svgo-loader').loader('svgo-loader').options({
-            plugins: extendDefaultPlugins([{
-                name: "removeAttrs",
-                params: {
-                    attrs: 'fill',
-                }
-            }])
-        });
-
-        // svg雪碧图 不去除fill属性
-        // const svgRuleFill = config.module.rule('icons_fill');
-        // svgRuleFill.test(/\.svg$/)
-        //     .include.add(resolve('src/assets/icon/svg_fill'))
-        //     .end()
-        //     .use('svg-sprite-loader')
-        //     .loader('svg-sprite-loader')
-        //     .options({
-        //         symbolId: 'fill-[name]',
-        //         // extract: true,
-        //         // publicPath: "img/",
-        //         // spriteFilename: "svg-sprite-[hash:8].svg",
-        //     });
-
-        // // config
-        // //     .plugin("svgsprite")
-        // //     .use(SVGSpriteLoaderPlugin, [{ 
-        // //       plainSprite: true
-        // //     }]);
-
-        // // svgo 去除svg中无用元素
-        // svgRuleFill.use('svgo-loader').loader('svgo-loader').options({
-        //     plugins: extendDefaultPlugins([])
-        // });
-
-    },
+
+  publicPath: "./", // 默认'/',部署应用包时的基本 URL
+  indexPath: 'index.html', // 相对于打包路径index.html的路径
+  outputDir: 'dist', // 'dist', 生产环境构建文件的目录
+  assetsDir: 'static', // 相对于outputDir的静态资源(js、css、img、fonts)目录
+  lintOnSave: false, // 是否在开发环境下通过 eslint-loader 在每次保存时 lint 代码
+  runtimeCompiler: true, // 是否使用包含运行时编译器的 Vue 构建版本
+
+  chainWebpack: (config) => {
+
+    config.resolve.symlinks(true); // 修复热更新失效
+
+    // 路径别名
+    config.resolve.alias
+      .set("@", resolve("src"))
+      .set("@node", resolve("node_modules"))
+      .set("@com", resolve("src/components"))
+      .set("@assets", resolve("src/assets"))
+      .set("@api", resolve("src/api"))
+      .set("@store", resolve("src/store"))
+      .set("@modeConfig", resolve("public/static/config"))
+      .set("@tools", resolve("src/tools"));
+
+    // less 继承
+    const types = ['vue-modules', 'vue', 'normal-modules', 'normal'];
+    types.forEach(type => addStyleResource(config.module.rule('less').oneOf(type)));
+
+    // svg 雪碧图
+    config.module // 排除其他svg-loader
+      .rule('svg')
+      .exclude.add(resolve('src/assets/icon/svg'))
+      .end()
+      .exclude.add(resolve('src/assets/icon/svg_fill'))
+      .end();
+
+    // svg雪碧图
+    const svgRule = config.module.rule('icons');
+    svgRule.test(/\.svg$/)
+      .include.add(resolve('src/assets/icon/svg'))
+      .end()
+      .use('svg-sprite-loader')
+      .loader('svg-sprite-loader')
+      .options({
+        symbolId: 'svg-[name]',
+        // extract: true,
+        // publicPath: "img/",
+        // spriteFilename: "svg-sprite-[hash:8].svg",
+      });
+
+    // config
+    //     .plugin("svgsprite")
+    //     .use(SVGSpriteLoaderPlugin, [{ 
+    //       plainSprite: true
+    //     }]);
+
+    // svgo 去除svg中无用元素
+    svgRule.use('svgo-loader').loader('svgo-loader').options({
+      plugins: extendDefaultPlugins([{
+        name: "removeAttrs",
+        params: {
+          attrs: 'fill',
+        }
+      }])
+    });
+
+    // svg雪碧图 不去除fill属性
+    // const svgRuleFill = config.module.rule('icons_fill');
+    // svgRuleFill.test(/\.svg$/)
+    //     .include.add(resolve('src/assets/icon/svg_fill'))
+    //     .end()
+    //     .use('svg-sprite-loader')
+    //     .loader('svg-sprite-loader')
+    //     .options({
+    //         symbolId: 'fill-[name]',
+    //         // extract: true,
+    //         // publicPath: "img/",
+    //         // spriteFilename: "svg-sprite-[hash:8].svg",
+    //     });
+
+    // // config
+    // //     .plugin("svgsprite")
+    // //     .use(SVGSpriteLoaderPlugin, [{ 
+    // //       plainSprite: true
+    // //     }]);
+
+    // // svgo 去除svg中无用元素
+    // svgRuleFill.use('svgo-loader').loader('svgo-loader').options({
+    //     plugins: extendDefaultPlugins([])
+    // });
+
+  },
+
+  // devServer: {
+  //   //代理配置
+  //   proxy: {
+  //     '/lightmatrix': {
+  //       target: 'https://h5.caibeike.com.cn/', // 请求地址
+
+  //       changeOrigin: true, // 在vue-cli3中,默认changeOrigin的值是true,意味着服务器host设置成target,这与vue-cli2不一致,vue-cli2这个默认值是false
+  //       // changeOrigin的值是true,target是host, request URL是http://baidu.com
+  //       // 如果设置changeOrigin: false,host就是浏览器发送过来的host,也就是localhost:8082。
+
+  //       pathRewrite: {  // 路径重写,eg:把api接口替换为''
+  //         '^/h5.caibeike.com.cn/': 'localhost:8888/'
+  //       }
+  //     }
+  //   },
+  //   open: false, // 是否打开浏览器
+  // }
 }