gaosp
2024-01-05 ea911d3b42cac8948eb6f1285c7ad46706707643
zancun
已修改17个文件
已添加33个文件
已删除2个文件
1578 ■■■■■ 文件已修改
.postcssrc.js 13 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
LICENSE 21 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
README.md 8 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
build/webpack.base.conf.js 3 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
build/webpack.dev.conf.js 17 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
build/webpack.prod.conf.js 23 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
config/dev.env.js 8 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
config/index.js 16 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
favicon.ico 补丁 | 查看 | 原始文档 | blame | 历史
index.html 10 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
package-lock.json 29 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
package.json 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/Test.vue 291 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/MdcApi.js 10 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/img/login/bg.png 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/img/login/btn_bg.png 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/img/login/footer.png 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/img/login/ico.png 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/img/login/ico副本.png 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/img/login/logo.png 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/img/login/logo_bg.png 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/img/login/top.png 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/rem.js 30 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/Maps/index.vue 257 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/home/index.vue 89 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/container/Map/img/1.png 补丁 | 查看 | 原始文档 | blame | 历史
src/container/Map/img/2.png 补丁 | 查看 | 原始文档 | blame | 历史
src/container/Map/img/3.png 补丁 | 查看 | 原始文档 | blame | 历史
src/container/Map/img/4.png 补丁 | 查看 | 原始文档 | blame | 历史
src/container/Map/img/5.png 补丁 | 查看 | 原始文档 | blame | 历史
src/container/Map/img/left_1.png 补丁 | 查看 | 原始文档 | blame | 历史
src/container/Map/img/left_2.png 补丁 | 查看 | 原始文档 | blame | 历史
src/container/Map/img/left_3.png 补丁 | 查看 | 原始文档 | blame | 历史
src/container/Map/img/left_4.png 补丁 | 查看 | 原始文档 | blame | 历史
src/container/Map/img/left_5.png 补丁 | 查看 | 原始文档 | blame | 历史
src/container/Map/index.vue 21 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main.js 12 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/permission.js 89 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/router/index.js 19 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/store/modules/user.js 51 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/test.js 21 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/utils/ajax.js 14 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/home/Welcome.vue 28 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/home/earth.png 补丁 | 查看 | 原始文档 | blame | 历史
src/views/home/index.vue 111 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/home/logout.png 补丁 | 查看 | 原始文档 | blame | 历史
src/views/home/map.vue 9 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/home/welcome.png 补丁 | 查看 | 原始文档 | blame | 历史
src/views/login/index.vue 180 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/login/index1.vue 195 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
static/ico.png 补丁 | 查看 | 原始文档 | blame | 历史
static/table-merge-utils.min.js 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
.postcssrc.js
@@ -1,3 +1,9 @@
/*
 * @Date: 2019-11-21 14:21:14
 * @LastEditors: Sneed
 * @LastEditTime: 2024-01-04 21:19:30
 * @FilePath: /belleson-frontend/Users/mache/Library/Containers/com.tencent.xinWeChat/Data/Library/Application Support/com.tencent.xinWeChat/2.0b4.0.9/650b28d71b3acf9feb5c2af6da2686eb/Message/MessageTemp/650b28d71b3acf9feb5c2af6da2686eb/File/mdc-portal/.postcssrc.js
 */
// https://github.com/michael-ciniawsky/postcss-load-config
module.exports = {
@@ -5,6 +11,11 @@
    "postcss-import": {},
    "postcss-url": {},
    // to edit target browsers: use "browserslist" field in package.json
    "autoprefixer": {}
    "autoprefixer": {},
    'postcss-pxtorem': {
        rootValue: 19, // è¡¨ç¤ºæ ¹å…ƒç´ å­—体大小或根据input参数返回根元素字体大小
        propList: ['*'], // å¯ä»¥ä»Žpx更改为rem的属性, é€šé…ç¬¦*表示启用所有属性
        selectorBlackList: ['.norem'] // è¿‡æ»¤æŽ‰.norem开头的class,不进行rem转换
    }
  }
}
LICENSE
ÎļþÒÑɾ³ý
README.md
@@ -0,0 +1,8 @@
<!--
 * @Date: 2024-01-05 21:15:51
 * @LastEditors: Sneed
 * @LastEditTime: 2024-01-05 21:49:28
 * @FilePath: /belleson-frontend/Users/mache/Documents/demo/mdc/README.md
-->
#Administrator
#Kknd_1234
build/webpack.base.conf.js
@@ -22,7 +22,8 @@
module.exports = {
  context: path.resolve(__dirname, '../'),
  entry: {
    app: ['babel-polyfill','./src/main.js']
    app: ['babel-polyfill','./src/main.js'],
    test: ['babel-polyfill','./src/test.js'],
  },
  output: {
    path: config.build.assetsRoot,
build/webpack.dev.conf.js
@@ -1,3 +1,9 @@
/*
 * @Date: 2019-12-13 16:30:56
 * @LastEditors: Sneed
 * @LastEditTime: 2024-01-03 21:54:18
 * @FilePath: /belleson-frontend/Users/mache/Library/Containers/com.tencent.xinWeChat/Data/Library/Application Support/com.tencent.xinWeChat/2.0b4.0.9/650b28d71b3acf9feb5c2af6da2686eb/Message/MessageTemp/650b28d71b3acf9feb5c2af6da2686eb/File/mdc-portal/build/webpack.dev.conf.js
 */
'use strict'
const path = require('path')
const utils = require('./utils')
@@ -54,7 +60,16 @@
      filename: 'index.html',
      template: 'index.html',
      inject: true,
      favicon: resolve('favicon.ico'),
      chunks: ['manifest', 'vendor', 'app'],
      // favicon: resolve('favicon.ico'),
      title: 'mdc-portal'
    }),
    new HtmlWebpackPlugin({
      filename: 'test.html',
      template: 'index.html',
      inject: true,
      chunks: ['manifest', 'vendor', 'test'],
      // favicon: resolve('favicon.ico'),
      title: 'mdc-portal'
    }),
  ]
build/webpack.prod.conf.js
@@ -29,7 +29,8 @@
  output: {
    path: config.build.assetsRoot,
    filename: utils.assetsPath('js/[name].[chunkhash].js'),
    chunkFilename: utils.assetsPath('js/[id].[chunkhash].js')
    chunkFilename: utils.assetsPath('js/[id].[chunkhash].js'),
    publicPath: './'
  },
  plugins: [
    // http://vuejs.github.io/vue-loader/en/workflow/production.html
@@ -67,8 +68,26 @@
      filename: config.build.index,
      template: 'index.html',
      inject: true,
      favicon: resolve('favicon.ico'),
      // favicon: resolve('favicon.ico'),
      title: 'mdc-portal',
      chunks: ['manifest', 'vendor', 'app'],
      minify: {
        removeComments: true,
        collapseWhitespace: true,
        removeAttributeQuotes: true
        // more options:
        // https://github.com/kangax/html-minifier#options-quick-reference
      },
      // necessary to consistently work with multiple chunks via CommonsChunkPlugin
      chunksSortMode: 'dependency'
    }),
    new HtmlWebpackPlugin({
      filename: config.build.test,
      template: 'index.html',
      inject: true,
      // favicon: resolve('favicon.ico'),
      title: 'mdc-portal',
      chunks: ['manifest', 'vendor', 'test'],
      minify: {
        removeComments: true,
        collapseWhitespace: true,
config/dev.env.js
@@ -1,8 +1,14 @@
/*
 * @Date: 2022-11-09 12:37:25
 * @LastEditors: Sneed
 * @LastEditTime: 2024-01-05 23:08:13
 * @FilePath: /belleson-frontend/Users/mache/Documents/demo/mdc/config/dev.env.js
 */
'use strict'
const merge = require('webpack-merge')
const prodEnv = require('./prod.env')
module.exports = merge(prodEnv, {
  NODE_ENV: '"development"',
  BASE_API: '"/api/mdc"'
  BASE_API: '"/mdc"'
})
config/index.js
@@ -1,3 +1,9 @@
/*
 * @Date: 2023-12-20 20:21:29
 * @LastEditors: Sneed
 * @LastEditTime: 2024-01-04 22:19:02
 * @FilePath: /belleson-frontend/Users/mache/Library/Containers/com.tencent.xinWeChat/Data/Library/Application Support/com.tencent.xinWeChat/2.0b4.0.9/650b28d71b3acf9feb5c2af6da2686eb/Message/MessageTemp/650b28d71b3acf9feb5c2af6da2686eb/File/mdc-portal/config/index.js
 */
'use strict'
// Template version: 1.2.6
// see http://vuejs-templates.github.io/webpack for documentation.
@@ -11,14 +17,14 @@
    assetsSubDirectory: 'static',
    assetsPublicPath: '/',
    proxyTable: {
      '/api': {
      '/mdc': {
    //  target: 'http://172.20.10.8:8087/',
      //  target: 'http://192.168.230.143:8087/',
      target: 'http://localhost:8087/',
      target: 'http://116.63.148.72:8088/',
      // target: 'http://111.230.17.122:8087/',
        changeOrigin: true,
        pathRewrite: {
          '^/api': '/'
          '^/mdc': '/mdc'
        }
      }
    },
@@ -34,7 +40,7 @@
    // Use Eslint Loader?
    // If true, your code will be linted during bundling and
    // linting errors and warnings will be shown in the console.
    useEslint: true,
    useEslint: false,
    // If true, eslint errors and warnings will also be shown in the error overlay
    // in the browser.
    showEslintErrorsInOverlay: false,
@@ -62,7 +68,7 @@
  build: {
    // Template for index.html
    index: path.resolve(__dirname, '../dist/index.html'),
    test: path.resolve(__dirname, '../dist/test.html'),
    // Paths
    assetsRoot: path.resolve(__dirname, '../dist'),
    assetsSubDirectory: 'static',
favicon.ico
Binary files differ
index.html
@@ -1,9 +1,16 @@
<!--
 * @Date: 2022-11-09 12:37:25
 * @LastEditors: Sneed
 * @LastEditTime: 2024-01-03 21:49:35
 * @FilePath: /belleson-frontend/Users/mache/Library/Containers/com.tencent.xinWeChat/Data/Library/Application Support/com.tencent.xinWeChat/2.0b4.0.9/650b28d71b3acf9feb5c2af6da2686eb/Message/MessageTemp/650b28d71b3acf9feb5c2af6da2686eb/File/mdc-portal/index.html
-->
<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width,height=device-height,initial-scale=1.0">
    <title>MDC展示平台</title>
    <title>千文科技</title>
    <link rel="icon" href="/static/ico.png" />
      <script src="/static/plugins/echarts-3.8.5/echarts.common.min.js"></script>
      <script src="/static/plugins/highcharts/highcharts.js"></script>
      <script src="/static/plugins/highcharts/highcharts-more.js"></script>
@@ -13,6 +20,7 @@
      <script src="/static/plugins/highcharts/bullet.js"></script>
<!--      <script src="https://img.hcharts.cn/highcharts/modules/xrange.js"></script>-->
      <script src="/static/plugins/highcharts/xrange.js"></script>
      <script src="./static/table-merge-utils.min.js"></script>
  </head>
  <body>
    <div id="app"></div>
package-lock.json
@@ -5,6 +5,7 @@
  "requires": true,
  "packages": {
    "": {
      "name": "mdc-portal",
      "version": "0.0.1",
      "license": "MIT",
      "dependencies": {
@@ -19,7 +20,9 @@
        "normalize.css": "7.0.0",
        "nprogress": "0.2.0",
        "postcss": "^7.0.27",
        "postcss-pxtorem": "^5.1.1",
        "qs": "^6.9.1",
        "table-merge-utils": "^1.0.3",
        "vue": "2.5.10",
        "vue-echarts": "^3.0.7",
        "vue-router": "3.0.1",
@@ -11464,6 +11467,14 @@
        "postcss": ">4 <9"
      }
    },
    "node_modules/postcss-pxtorem": {
      "version": "5.1.1",
      "resolved": "https://registry.npmmirror.com/postcss-pxtorem/-/postcss-pxtorem-5.1.1.tgz",
      "integrity": "sha512-uvgIujL/pn0GbZ+rczESD2orHsbXrrCqi+q9wJO8PCk3ZGCoVVtu5hZTbtk+tbZHZP5UkTfCvqOrTZs9Ncqfsg==",
      "dependencies": {
        "postcss": "^7.0.27"
      }
    },
    "node_modules/postcss-reduce-idents": {
      "version": "2.4.0",
      "resolved": "https://registry.npmjs.org/postcss-reduce-idents/-/postcss-reduce-idents-2.4.0.tgz",
@@ -14458,6 +14469,11 @@
      "engines": {
        "node": ">=4.0.0"
      }
    },
    "node_modules/table-merge-utils": {
      "version": "1.0.3",
      "resolved": "https://registry.npmmirror.com/table-merge-utils/-/table-merge-utils-1.0.3.tgz",
      "integrity": "sha512-brrIbMkq6yVKN2tUSYiDdqkvaVCWPYq1+5+EHALS9BlG4s2UPcovfU6cNoZKlHsDEPSLGEsZsWQEZhVtyhpb+A=="
    },
    "node_modules/table/node_modules/ajv": {
      "version": "6.12.6",
@@ -26360,6 +26376,14 @@
      "dev": true,
      "requires": {}
    },
    "postcss-pxtorem": {
      "version": "5.1.1",
      "resolved": "https://registry.npmmirror.com/postcss-pxtorem/-/postcss-pxtorem-5.1.1.tgz",
      "integrity": "sha512-uvgIujL/pn0GbZ+rczESD2orHsbXrrCqi+q9wJO8PCk3ZGCoVVtu5hZTbtk+tbZHZP5UkTfCvqOrTZs9Ncqfsg==",
      "requires": {
        "postcss": "^7.0.27"
      }
    },
    "postcss-reduce-idents": {
      "version": "2.4.0",
      "resolved": "https://registry.npmjs.org/postcss-reduce-idents/-/postcss-reduce-idents-2.4.0.tgz",
@@ -28835,6 +28859,11 @@
        }
      }
    },
    "table-merge-utils": {
      "version": "1.0.3",
      "resolved": "https://registry.npmmirror.com/table-merge-utils/-/table-merge-utils-1.0.3.tgz",
      "integrity": "sha512-brrIbMkq6yVKN2tUSYiDdqkvaVCWPYq1+5+EHALS9BlG4s2UPcovfU6cNoZKlHsDEPSLGEsZsWQEZhVtyhpb+A=="
    },
    "tapable": {
      "version": "0.2.9",
      "resolved": "https://registry.npmjs.org/tapable/-/tapable-0.2.9.tgz",
package.json
@@ -24,7 +24,9 @@
    "normalize.css": "7.0.0",
    "nprogress": "0.2.0",
    "postcss": "^7.0.27",
    "postcss-pxtorem": "^5.1.1",
    "qs": "^6.9.1",
    "table-merge-utils": "^1.0.3",
    "vue": "2.5.10",
    "vue-echarts": "^3.0.7",
    "vue-router": "3.0.1",
src/Test.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,291 @@
<!--
 * @Date: 2023-12-20 20:24:53
 * @LastEditors: Sneed
 * @LastEditTime: 2024-01-02 20:35:01
 * @FilePath: /belleson-frontend/Users/mache/Library/Containers/com.tencent.xinWeChat/Data/Library/Application Support/com.tencent.xinWeChat/2.0b4.0.9/650b28d71b3acf9feb5c2af6da2686eb/Message/MessageTemp/650b28d71b3acf9feb5c2af6da2686eb/File/mdc-portal/src/Test.vue
-->
<template>
  <div id="app" class="wrap" @mouseup="mouseup">
    <el-row>
      <el-col :xs="24" :sm="2" :md="2" :lg="2" :xl="2">
              <el-input v-model.number="rows" placeholder="行数"></el-input>
      </el-col>
      <el-col style="margin-left: 14px;" :xs="24" :sm="2" :md="2" :lg="2" :xl="2">
            <el-input v-model.number="cols" placeholder="列数"></el-input>
      </el-col>
      <el-col style="margin-left: 14px;" :xs="24" :sm="2" :md="2" :lg="2" :xl="2">
        <el-button @click="createMap">生成厂房地图</el-button>
      </el-col>
    </el-row>
    <div>
      <!-- <el-input v-model.number="rows"></el-input> -->
      <!-- <el-input v-model.number="cols"></el-input> -->
      <!-- <input type="text" v-model="rows"> -->
      <!-- <input type="text" v-model="cols"> -->
      <!-- <button @click="createMap">生成厂房地图</button> -->
    </div>
    <div class="btns">
      <div v-for="btn in btns" :key="btn.handle" :class="{
        btn,
        sign: ['markdevice','markroad','markcancel'].includes(btn.disHandle),
        disable:['markdevice','markroad','markcancel'].includes(btn.disHandle) ? hasSignBtn !==  btn.disHandle: (hasSignBtn || disabledHandles && disabledHandles.includes(btn.disHandle)),
      }" @click="handleFn(btn)">
        {{ btn.name }}
      </div>
    </div>
    <div class="table-wrap">
      <table class="table">
        <tr v-for="(row, rowIndex) in tableRows" :key="rowIndex">
          <td v-for="(td, colIndex) in row" :key="colIndex" :style="getCellStyle(td)"
            :class="getCellClass(rowIndex, colIndex)" @mousedown="mousedown" @mousemove="mousemove(rowIndex, colIndex)" @mouseup="mouseup" @click="handleSelectCell(rowIndex, colIndex)" :rowspan="td.rowspan"
            :colspan="td.colspan"></td>
        </tr>
      </table>
    </div>
  </div>
</template>
<script>
// import TableMergeUtils from "table-merge-utils";
export default {
  name: 'App',
  data() {
    return {
      rows: 10,
      cols: 10,
      btns: [
        { name: "向上添加行", handle: "addTopRow", disHandle: "insertRow" },
        { name: "向下添加行", handle: "addBottomRow", disHandle: "insertRow" },
        { name: "向左添加列", handle: "addLeftCol", disHandle: "insertCol" },
        { name: "向右添加列", handle: "addRightCol", disHandle: "insertCol" },
        { name: "删除行", handle: "delRow", disHandle: "delRow" },
        { name: "删除列", handle: "delCol", disHandle: "delCol" },
        { name: "水平拆分", handle: "splitH", disHandle: "splitH" },
        { name: "垂直拆分", handle: "splitV", disHandle: "splitV" },
        { name: "向左合并", handle: "leftMerge", disHandle: "leftMerge" },
        { name: "向右合并", handle: "rightMerge", disHandle: "rightMerge" },
        { name: "向上合并", handle: "topMerge", disHandle: "topMerge" },
        { name: "向下合并", handle: "bottomMerge", disHandle: "bottomMerge" },
        // { name: "标记设备", handle: "markdevice", disHandle: "markdevice" },
        { name: "标记过道", handle: "markroad", disHandle: "markroad" },
        { name: "取消标记", handle: "markcancel", disHandle: "markcancel" }
      ],
      tableRows: [],
      table: null,
      selectCell: {
        row: -1,
        col: -1
      },
      disabledHandles: null,
      hasSignBtn: '',
      mousedownStatus: false
    }
  },
  mounted () {
    document.querySelector('body').addEventListener('mouseup', () => {
      if (this.hasSignBtn) {
        this.mousedownStatus = false
      }
    })
  },
  methods: {
    createMap() {
      this.tableRows = TableMergeUtils.init({ rows: this.rows - 0, cols: this.cols -0,width: 50,height: 50 })
      this.table = new TableMergeUtils(this.tableRows, { minRetainRow: 1, minSplitHcolspan: 1, minSplitVrowspan: 1, fixRowType: 2 })
      console.log(this.table)
      this.disabledHandles = this.table.getDisabledHandles()
      console.log(this.disabledHandles)
    },
    getCellClass(row, col) {
      if (row === this.selectCell.row && col === this.selectCell.col) {
        return "cell active";
      }
      return "cell";
    },
    getCellStyle(cell) {
      console.log(cell,'>>>>>>>')
      return {
        width: cell.type === 0 ? `24px` : cell.type === 1 ? `${50}px` : `${50}px`,
        height: cell.type === 0 ? `24px` : cell.type === 1 ? `${50}px` : `${50}px`,
        lineHieght: `${cell.height}px`,
        border: cell.type === 0 ? '' : "1px solid rgba(9,54,89,1)",
        background: cell.type === 1 ?  '#060c14' : cell.type === 0 ? '#112c5a' : ''
      }
    },
    mousedown () {
      if (this.hasSignBtn) {
        this.mousedownStatus = true
      }
    },
    mousemove (row,col) {
      if (!this.mousedownStatus) return
      if (['markroad','markdevice'].includes(this.hasSignBtn)) {
        this.sign({row,col},this.hasSignBtn === 'markroad' ? 0 : 1)
        return
      } else if (this.hasSignBtn === 'markcancel') {
        return this.sign({row,col},'')
      }
    },
    mouseup () {
      if (this.hasSignBtn) {
        this.mousedownStatus = false
      }
    },
    handleSelectCell(row, col) {
      if (['markroad','markdevice'].includes(this.hasSignBtn)) {
        this.sign({row,col},this.hasSignBtn === 'markroad' ? 0 : 1)
        return
      } else if (this.hasSignBtn === 'markcancel') {
        return this.sign({row,col},'')
      }
      this.selectCell = Object.assign(this.selectCell, { row, col })
      this.disabledHandles = this.table.getDisabledHandles(
        this.selectCell.row,
        this.selectCell.col
      );
    },
    sign ({row,col},type) {
      this.tableRows[row][col].type  = type
      this.table = new TableMergeUtils(this.tableRows, { minRetainRow: 1, minSplitHcolspan: 1, minSplitVrowspan: 1, fixRowType: 2 })
      this.disabledHandles = this.table.getDisabledHandles()
      this.selectCell ={
          row: -1,
          col: -1
        }
    },
    handleFn(btn) {
      console.log('-----',btn)
      if (this.selectCell.row > -1 && this.selectCell.col > -1 && !['markdevice','markroad', 'markcancel'].includes(btn.handle)) {
        switch (btn.handle) {
          case "addTopRow": {
            let res = this.table.insertRow(this.selectCell.row, this.selectCell.col, 0);
            this.handleSelectCell(res.row, res.col);
            this.hasSignBtn = ''
            break;
          }
          case "addBottomRow": {
            let res = this.table.insertRow(this.selectCell.row, this.selectCell.col, 1);
            this.handleSelectCell(res.row, res.col);
            this.hasSignBtn = ''
            break;
          }
          case "addLeftCol": {
            let res = this.table.insertCol(this.selectCell.row, this.selectCell.col, 0);
            this.handleSelectCell(res.row, res.col);
            this.hasSignBtn = ''
            break;
          }
          case "addRightCol": {
            let res = this.table.insertCol(this.selectCell.row, this.selectCell.col, 1);
            this.handleSelectCell(res.row, res.col);
            this.hasSignBtn = ''
            break;
          }
          // case 'markdevice':
          //   if (this.hasSignBtn === 'markdevice') {
          //     this.hasSignBtn = ''
          //   } else {
          //     this.hasSignBtn = 'markdevice'
          //   }
          //   break
          // case 'markroad':
          //   if (this.hasSignBtn === 'markroad') {
          //     this.hasSignBtn = ''
          //   } else {
          //     this.hasSignBtn = 'markroad'
          //   }
          //   break;
          // case 'markcancel':
          //   if (this.hasSignBtn === 'markcancel') {
          //     this.hasSignBtn = ''
          //   } else {
          //     this.hasSignBtn = 'markcancel'
          //   }
          //   break;
          default: {
            let handle = btn.handle;
            let fn = (this.table[handle]).bind(this.table);
            if (fn) {
              let res = fn(this.selectCell.row, this.selectCell.col);
              if (res) {
                this.handleSelectCell(res.row, res.col);
              }
            }
          }
        }
      } else if(['markdevice','markroad', 'markcancel'].includes(btn.handle)){
        if (this.hasSignBtn === btn.handle) {
          this.hasSignBtn = ''
        } else {
          this.hasSignBtn = btn.handle
        }
        this.selectCell ={
          row: -1,
          col: -1
        }
      }
    }
  }
}
</script>
<style>
.wrap {
  width: 100%;
  height: 100%;;
  background: #000005;
}
.btns {
  display: flex;
  margin-top: 20px;
}
.btn {
  margin-left: 10px;
  width: 100px;
  line-height: 40px;
  border-radius: 10px;
  text-align: center;
  color: #fff;
  background: #6363f5;
  cursor: pointer;
  color: #fff;
  &.disable {
    background: #9696ab;
    cursor: not-allowed;
  }
  &.disable.sign {
    cursor: pointer;
  }
}
.btn:hover {
  color: #000;
}
.btn:focus {
  color: inherit;
  background: inherit;
  border-color: inherit;
}
.table-wrap {
  display: flex;
  justify-content: center;
}
.table {
  margin-top: 20px;
  border-collapse: collapse;
  background: rgba(1,6,17,1);
  border-radius: 20px;
  overflow: hidden;
}
.cell {
  margin: 0;
  padding: 0;
}
.cell.active {
  background: #6363f5!important;
}
</style>
src/api/MdcApi.js
@@ -16,7 +16,9 @@
  // ç™»å½•接口
  LOGIN: '/user/login',
  // èŽ·å–ç”¨æˆ·ä¿¡æ¯
  GET_USERINFO: '/user/currentUser',
  GET_WORKSHOP_INFO: '/workshop/list',
  // èŽ·å–æŒ‡å®šè½¦é—´ä¸‹æ‰€æœ‰æœºåºŠçš„çŠ¶æ€
  GET_MACHINE_STATUS_BY_WORKSHOP_ID: '/workshop/machine/status',
  // èŽ·å–ç‰¹å®šæœºåºŠçš„æ•°æ®
@@ -349,7 +351,7 @@
 * @return {*}
 */
export function login(username, password) {
  return sendRequest(HttpConstants.LOGIN, { userName: username, password: password })
  return sendRequest(HttpConstants.LOGIN, { username: username, password: password })
}
/**
@@ -419,7 +421,9 @@
export function getWorkShopInfo() {
  return sendRequest(HttpConstants.GET_WORKSHOP_INFO)
}
export function getUserInfo() {
  return getData(HttpConstants.GET_USERINFO)
}
/**
 *
 * @param method
@@ -438,7 +442,7 @@
 * @return {*}
 */
export function getData(method, params) {
  return ajax.get(method, params)
  return ajax.get(URL_CFG.BASE_URL + method, params)
}
/**
src/assets/img/login/bg.png
src/assets/img/login/btn_bg.png
src/assets/img/login/footer.png
src/assets/img/login/ico.png
src/assets/img/login/ico¸±±¾.png
src/assets/img/login/logo.png
src/assets/img/login/logo_bg.png
src/assets/img/login/top.png
src/assets/rem.js
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,30 @@
/*
 * @Date: 2024-01-04 21:16:19
 * @LastEditors: Sneed
 * @LastEditTime: 2024-01-04 21:16:35
 * @FilePath: /belleson-frontend/Users/mache/Library/Containers/com.tencent.xinWeChat/Data/Library/Application Support/com.tencent.xinWeChat/2.0b4.0.9/650b28d71b3acf9feb5c2af6da2686eb/Message/MessageTemp/650b28d71b3acf9feb5c2af6da2686eb/File/mdc-portal/src/assets/rem.js
 */
// é…ç½®åŸºæœ¬å¤§å°
let baseSize = 19;
// è®¾ç½® rem å‡½æ•°
function setRem () {
    //当前页面宽度相对于1920px屏幕宽的缩放比例,可根据自己需要修改。
    let scale = document.documentElement.clientWidth / 1920;
    //设置页面根节点字体大小(“Math.min(scale, 2)” æŒ‡æœ€é«˜æ”¾å¤§æ¯”例为2,可根据实际业务需求调整)
    document.documentElement.style.fontSize = baseSize * Math.min(scale, 2) + 'px'
}
setRem(); //初始化
// é€‚配 - é‡ç½®å‡½æ•°
function resetRem (num) {
    if(num) baseSize = Number(num);
    setRem();
}
window.resetRem = resetRem; // å…¨å±€å¯è°ƒç”¨(其他方式也可)
// æ”¹å˜çª—口大小时重置 rem
window.onresize = function () {
    setRem()
}
src/components/Maps/index.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,257 @@
<!--
 * @Date: 2023-12-20 20:24:53
 * @LastEditors: Sneed
 * @LastEditTime: 2023-12-28 21:06:35
 * @FilePath: /belleson-frontend/Users/mache/Library/Containers/com.tencent.xinWeChat/Data/Library/Application Support/com.tencent.xinWeChat/2.0b4.0.9/650b28d71b3acf9feb5c2af6da2686eb/Message/MessageTemp/650b28d71b3acf9feb5c2af6da2686eb/File/mdc-portal/src/Test.vue
-->
<template>
    <div id="app" @mouseup="mouseup">
      <div>
        <input type="text" v-model="rows">
        <input type="text" v-model="cols">
        <button @click="createMap">生成厂房地图</button>
      </div>
      <div class="btns">
        <div v-for="btn in btns" :key="btn.handle" :class="{
          btn,
          sign: ['markdevice','markroad','markcancel'].includes(btn.disHandle),
          disable:['markdevice','markroad','markcancel'].includes(btn.disHandle) ? hasSignBtn !==  btn.disHandle: (hasSignBtn || disabledHandles && disabledHandles.includes(btn.disHandle)),
        }" @click="handleFn(btn)">
          {{ btn.name }}
        </div>
      </div>
      <table class="table">
        <tr v-for="(row, rowIndex) in tableRows" :key="rowIndex">
          <td v-for="(td, colIndex) in row" :key="colIndex" :style="getCellStyle(td)"
            :class="getCellClass(rowIndex, colIndex)" @mousedown="mousedown" @mousemove="mousemove(rowIndex, colIndex)" @mouseup="mouseup" @click="handleSelectCell(rowIndex, colIndex)" :rowspan="td.rowspan"
            :colspan="td.colspan"></td>
        </tr>
      </table>
    </div>
  </template>
  <script>
  // import TableMergeUtils from "table-merge-utils";
  export default {
    name: 'App',
    data() {
      return {
        rows: 10,
        cols: 10,
        btns: [
          { name: "向上添加行", handle: "addTopRow", disHandle: "insertRow" },
          { name: "向下添加行", handle: "addBottomRow", disHandle: "insertRow" },
          { name: "向左添加列", handle: "addLeftCol", disHandle: "insertCol" },
          { name: "向右添加列", handle: "addRightCol", disHandle: "insertCol" },
          { name: "删除行", handle: "delRow", disHandle: "delRow" },
          { name: "删除列", handle: "delCol", disHandle: "delCol" },
          { name: "水平拆分", handle: "splitH", disHandle: "splitH" },
          { name: "垂直拆分", handle: "splitV", disHandle: "splitV" },
          { name: "向左合并", handle: "leftMerge", disHandle: "leftMerge" },
          { name: "向右合并", handle: "rightMerge", disHandle: "rightMerge" },
          { name: "向上合并", handle: "topMerge", disHandle: "topMerge" },
          { name: "向下合并", handle: "bottomMerge", disHandle: "bottomMerge" },
          { name: "标记设备", handle: "markdevice", disHandle: "markdevice" },
          { name: "标记过道", handle: "markroad", disHandle: "markroad" },
          { name: "取消标记", handle: "markcancel", disHandle: "markcancel" }
        ],
        tableRows: [],
        table: null,
        selectCell: {
          row: -1,
          col: -1
        },
        disabledHandles: null,
        hasSignBtn: '',
        mousedownStatus: false
      }
    },
    methods: {
      createMap() {
        this.tableRows = TableMergeUtils.init({ rows: this.rows - 0, cols: this.cols -0,width: 50,height: 50 })
        this.table = new TableMergeUtils(this.tableRows, { minRetainRow: 1, minSplitHcolspan: 1, minSplitVrowspan: 1, fixRowType: 2 })
        console.log(this.table)
        this.disabledHandles = this.table.getDisabledHandles()
        console.log(this.disabledHandles)
      },
      getCellClass(row, col) {
        if (row === this.selectCell.row && col === this.selectCell.col) {
          return "cell active";
        }
        return "cell";
      },
      getCellStyle(cell) {
        console.log(cell,'>>>>>>>')
        return {
          width: cell.type === 0 ? `5px` : cell.type === 1 ? `${cell.width*4}px` : `${cell.width}px`,
          height: cell.type === 0 ? `5px` : cell.type === 1 ? `${cell.height*4}px` : `${cell.height}px`,
          lineHieght: `${cell.height}px`,
          border: cell.type === 0 ? '' : "1px solid rgba(9,54,89,1)",
          background: cell.type === 1 ?  '#060c14' : cell.type === 0 ? '#112c5a' : ''
        }
      },
      mousedown () {
        if (this.hasSignBtn) {
          this.mousedownStatus = true
        }
      },
      mousemove (row,col) {
        if (!this.mousedownStatus) return
        if (['markroad','markdevice'].includes(this.hasSignBtn)) {
          this.sign({row,col},this.hasSignBtn === 'markroad' ? 0 : 1)
          return
        } else if (this.hasSignBtn === 'markcancel') {
          return this.sign({row,col},'')
        }
      },
      mouseup () {
        if (this.hasSignBtn) {
          this.mousedownStatus = false
        }
      },
      handleSelectCell(row, col) {
        if (['markroad','markdevice'].includes(this.hasSignBtn)) {
          this.sign({row,col},this.hasSignBtn === 'markroad' ? 0 : 1)
          return
        } else if (this.hasSignBtn === 'markcancel') {
          return this.sign({row,col},'')
        }
        this.selectCell = Object.assign(this.selectCell, { row, col })
        this.disabledHandles = this.table.getDisabledHandles(
          this.selectCell.row,
          this.selectCell.col
        );
      },
      sign ({row,col},type) {
        this.tableRows[row][col].type  = type
        this.table = new TableMergeUtils(this.tableRows, { minRetainRow: 1, minSplitHcolspan: 1, minSplitVrowspan: 1, fixRowType: 2 })
        this.disabledHandles = this.table.getDisabledHandles()
        this.selectCell ={
            row: -1,
            col: -1
          }
      },
      handleFn(btn) {
        console.log('-----',btn)
        if (this.selectCell.row > -1 && this.selectCell.col > -1 && !['markdevice','markroad', 'markcancel'].includes(btn.handle)) {
          switch (btn.handle) {
            case "addTopRow": {
              let res = this.table.insertRow(this.selectCell.row, this.selectCell.col, 0);
              this.handleSelectCell(res.row, res.col);
              this.hasSignBtn = ''
              break;
            }
            case "addBottomRow": {
              let res = this.table.insertRow(this.selectCell.row, this.selectCell.col, 1);
              this.handleSelectCell(res.row, res.col);
              this.hasSignBtn = ''
              break;
            }
            case "addLeftCol": {
              let res = this.table.insertCol(this.selectCell.row, this.selectCell.col, 0);
              this.handleSelectCell(res.row, res.col);
              this.hasSignBtn = ''
              break;
            }
            case "addRightCol": {
              let res = this.table.insertCol(this.selectCell.row, this.selectCell.col, 1);
              this.handleSelectCell(res.row, res.col);
              this.hasSignBtn = ''
              break;
            }
            // case 'markdevice':
            //   if (this.hasSignBtn === 'markdevice') {
            //     this.hasSignBtn = ''
            //   } else {
            //     this.hasSignBtn = 'markdevice'
            //   }
            //   break
            // case 'markroad':
            //   if (this.hasSignBtn === 'markroad') {
            //     this.hasSignBtn = ''
            //   } else {
            //     this.hasSignBtn = 'markroad'
            //   }
            //   break;
            // case 'markcancel':
            //   if (this.hasSignBtn === 'markcancel') {
            //     this.hasSignBtn = ''
            //   } else {
            //     this.hasSignBtn = 'markcancel'
            //   }
            //   break;
            default: {
              let handle = btn.handle;
              let fn = (this.table[handle]).bind(this.table);
              if (fn) {
                let res = fn(this.selectCell.row, this.selectCell.col);
                if (res) {
                  this.handleSelectCell(res.row, res.col);
                }
              }
            }
          }
        } else if(['markdevice','markroad', 'markcancel'].includes(btn.handle)){
          if (this.hasSignBtn === btn.handle) {
            this.hasSignBtn = ''
          } else {
            this.hasSignBtn = btn.handle
          }
          this.selectCell ={
            row: -1,
            col: -1
          }
        }
      }
    }
  }
  </script>
  <style>
  .wrap {
    display: flex;
    align-items: start;
    width: 1200px;
  }
  .btns {
    position: absolute;
    margin-right: 20px;
  }
  .btn {
    margin-bottom: 10px;
    width: 100px;
    height: 30px;
    line-height: 30px;
    text-align: center;
    color: #fff;
    background: #6363f5;
    cursor: pointer;
    &.disable {
      background: #9696ab;
      cursor: not-allowed;
    }
    &.disable.sign {
      cursor: pointer;
    }
  }
  .table {
    border-collapse: collapse;
    margin-left: 120px;
    background: rgba(1,6,17,1);
  }
  .cell {
    margin: 0;
    padding: 0;
  }
  .cell.active {
    background: #6363f5!important;
  }
  </style>
src/components/home/index.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,89 @@
<!--
 * @Date: 2024-01-04 19:40:32
 * @LastEditors: Sneed
 * @LastEditTime: 2024-01-04 20:45:45
 * @FilePath: /belleson-frontend/Users/mache/Library/Containers/com.tencent.xinWeChat/Data/Library/Application Support/com.tencent.xinWeChat/2.0b4.0.9/650b28d71b3acf9feb5c2af6da2686eb/Message/MessageTemp/650b28d71b3acf9feb5c2af6da2686eb/File/mdc-portal/src/components/home/index.vue
-->
<template>
    <div class="home">
        <div class="header">
            <img src="~@/assets/img/login/logo.png" alt="">
            <div class="menu">
              <slot name="menu"></slot>
            </div>
        </div>
        <div class="content">
            <slot name="content"></slot>
        </div>
        <div class="footer">
        </div>
    </div>
</template>
<script>
export default {
    mounted () {
        console.log(this, '------')
    }
}
</script>
<style lang="scss" scoped>
$bg:#2d3a4b;
$dark_gray:#889aa4;
$light_gray:#eee;
.home {
  /*position: relative;*/
  height: 100%;
  width: 100%;
  background-color: $bg;
  overflow: auto;
  display: flex;
  flex-direction: column;
  .header {
    padding-left: 24px;
    padding-right: 24px;
    height: 94px;
    flex: 0 0 auto;
    background-image: url('~@/assets/img/login/top.png');
    background-size: contain;
    display: flex;
    align-items: center;
    // justify-content: space-between;
    & > img {
      flex: 0 0 auto;
      width: 500px;
      max-height: 91px;
      align-self: flex-start;
    }
    .menu {
      height: 50px;
      margin-left: auto;
    }
  }
  .content {
    flex: 1 1 auto;
    background-image: url('~@/assets/img/login/bg.png');
    background-size: cover;
    background-repeat: no-repeat;
    position: relative;
    overflow: hidden;
    .compName {
      font-size: 23px;
      color: #FFFFFF;
      line-height: 33px;
      position: absolute;
      left: 0;
      right: 0;
      text-align: center;
      bottom: 30px;
    }
  }
  .footer {
    height: 46px;
    background-image: url('~@/assets/img/login/footer.png');
    background-size: cover;
    background-repeat: no-repeat;
    flex: 0 0 auto;
  }
}
</style>
src/container/Map/img/1.png
src/container/Map/img/2.png
src/container/Map/img/3.png
src/container/Map/img/4.png
src/container/Map/img/5.png
src/container/Map/img/left_1.png
src/container/Map/img/left_2.png
src/container/Map/img/left_3.png
src/container/Map/img/left_4.png
src/container/Map/img/left_5.png
src/container/Map/index.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,21 @@
<!--
 * @Date: 2024-01-05 22:26:22
 * @LastEditors: Sneed
 * @LastEditTime: 2024-01-05 23:12:49
 * @FilePath: /belleson-frontend/Users/mache/Documents/demo/mdc/src/container/Map/index.vue
-->
<template>
    <div style="color: red">车间地图</div>
</template>
<script>
    export default {
        methods: {
            getMapList() {
                this.$post('')
            }
        },
        mounted () {
            this.getMapList()
        }
    }
</script>
src/main.js
@@ -1,3 +1,9 @@
/*
 * @Date: 2024-01-05 21:45:19
 * @LastEditors: Sneed
 * @LastEditTime: 2024-01-05 23:12:32
 * @FilePath: /belleson-frontend/Users/mache/Documents/demo/mdc/src/main.js
 */
import Vue from 'vue'
import 'normalize.css/normalize.css'// A modern alternative to CSS resets
@@ -7,16 +13,18 @@
import locale from 'element-ui/lib/locale/lang/zh-CN' // lang i18n
import '@/styles/index.scss' // global css
import '@/assets/rem.js'
import App from './App'
import router from './router'
import store from './store'
import {post,get} from '@/utils/ajax'
import '@/icons' // icon
import '@/permission' // permission control
Vue.use(ElementUI, { locale })
Vue.config.productionTip = false
Vue.$prototype.$post = post
Vue.$prototype.$get = get
new Vue({
  el: '#app',
  router,
src/permission.js
@@ -1,3 +1,9 @@
/*
 * @Date: 2022-11-09 12:37:25
 * @LastEditors: Sneed
 * @LastEditTime: 2024-01-05 22:50:54
 * @FilePath: /belleson-frontend/Users/mache/Documents/demo/mdc/src/permission.js
 */
import router from './router'
import store from './store'
import NProgress from 'nprogress' // Progress è¿›åº¦æ¡
@@ -16,49 +22,50 @@
router.beforeEach((to, from, next) => {
  NProgress.start()
  initApplicationCfg().then(res => {
    // console.log(to.path)
    console.log(to.path)
    if (getToken().value) {
      if (store.getters.workshopList.length === 0) {
        store.dispatch('GetInfo').then(res => { // æ‹‰å–用户信息
          if (to.path === '/') {
            next('/dashboard/index')
          }
          // if (to.path !== '/' && res.code === 0) {
          if (res.code === 0) {
            Message({
              message: res.msg,
              type: 'error',
              duration: 3 * 1000
            })
          }
          // if (to.path === '/' && store.getters.workshopList.length > 0) {
          //   next({ path: `/workshop/${store.getters.workshopList[0].workshopId}` })
          // } else
          if (to.path.indexOf('workshop') > -1) {
            // è½¦é—´
            const workshopIds = store.getters.workshopList.map((item) => item.status.id)
            if (to.params.pid === 'undefined') {
              next('/')
            } else if (workshopIds.indexOf(to.params.pid) > -1) {
              next({ path: `/workshop/${to.params.pid}` })
            } else {
              next({ path: `/workshop/${workshopIds[0]}` })
            }
          } else if (to.path.indexOf('device') > -1) {
            // è®¾å¤‡
            const cateIds = store.getters.deviceCategories.map((item) => item.type)
            // console.log(to.params.did)
            if (to.params.did === 'undefined') {
              next('/')
            } else if (cateIds.indexOf(to.params.did) > -1) {
              next({ path: `/device/${to.params.did}` })
            } else {
              next({ path: `/device/${cateIds[0]}` })
            }
          } else {
            next()
          }
        })
        // store.dispatch('GetInfo').then(res => { // æ‹‰å–用户信息
        //   if (to.path === '/') {
        //     next('/home')
        //   }
        //   // if (to.path !== '/' && res.code === 0) {
        //   if (res.code === 0) {
        //     Message({
        //       message: res.msg,
        //       type: 'error',
        //       duration: 3 * 1000
        //     })
        //   }
        //   // if (to.path === '/' && store.getters.workshopList.length > 0) {
        //   //   next({ path: `/workshop/${store.getters.workshopList[0].workshopId}` })
        //   // } else
        //   if (to.path.indexOf('workshop') > -1) {
        //     // è½¦é—´
        //     const workshopIds = store.getters.workshopList.map((item) => item.status.id)
        //     if (to.params.pid === 'undefined') {
        //       next('/')
        //     } else if (workshopIds.indexOf(to.params.pid) > -1) {
        //       next({ path: `/workshop/${to.params.pid}` })
        //     } else {
        //       next({ path: `/workshop/${workshopIds[0]}` })
        //     }
        //   } else if (to.path.indexOf('device') > -1) {
        //     // è®¾å¤‡
        //     const cateIds = store.getters.deviceCategories.map((item) => item.type)
        //     // console.log(to.params.did)
        //     if (to.params.did === 'undefined') {
        //       next('/')
        //     } else if (cateIds.indexOf(to.params.did) > -1) {
        //       next({ path: `/device/${to.params.did}` })
        //     } else {
        //       next({ path: `/device/${cateIds[0]}` })
        //     }
        //   } else {
        //     next()
        //   }
        // })
        next()
      } else {
        next()
      }
src/router/index.js
@@ -26,6 +26,21 @@
  { path: '/', component: () => import('@/views/login/index'), hidden: true },
  // { path: '/login', component: () => import('@/views/login/index'), hidden: true },
  // é¦–页
  { path: '/home',
    component: () => import('@/views/home/index'),
    children: [
      {
        path: 'index',
        name: 'index',
        component: () => import('@/views/home/Welcome')
      },
      {
        path: 'map',
        name: 'map',
        component: () => import('@/container/Map/index')
      }
    ]
  },
  {
    path: '/dashboard',
    component: Layout,
@@ -380,8 +395,8 @@
]
export default new Router({
  mode: 'history',
  base: '/mdc/',
  mode: 'hash',
  base: '/',
  scrollBehavior: () => ({ y: 0 }),
  routes: constantRouterMap
})
src/store/modules/user.js
@@ -1,4 +1,4 @@
import { login, getWorkShopInfo, URL_CFG } from '@/api/MdcApi'
import { login, getUserInfo, URL_CFG } from '@/api/MdcApi'
import { getToken, setToken, removeToken } from '@/utils/auth'
import Vue from 'vue'
const user = {
@@ -62,13 +62,22 @@
          // {"result":"SUCCESS","token":"43a187c9b3f1f6cd6c8342c15f91a52a"}
          response = response || {}
          if (response.result === 'SUCCESS') {
            setToken(response.token)
            commit('SET_TOKEN', response.token)
            debugger
            setToken(response.data)
            commit('SET_TOKEN', response.data)
            resolve(response)
            this.dispatch('GetInfo').then(res => resolve(res))
          } else {
            resolve({ code: 0, msg: '用户名或密码错误!' })
          }
        }).catch(error => {
          // TODO: del
          // let response = {"result":"SUCCESS","data":"43a187c9b3f1f6cd6c8342c15f91a52a"}
          // setToken(response.data)
          // commit('SET_TOKEN', response.data)
          // resolve(response)
          reject(error)
          // console.log(error)
        })
@@ -77,26 +86,26 @@
    // èŽ·å–ç”¨æˆ·ä¿¡æ¯
    GetInfo({ commit, state }) {
      return new Promise((resolve, reject) => {
        getWorkShopInfo().then(data => {
        getUserInfo().then(data => {
          if (data.result === 'SUCCESS') {
            if (data.workshopList && data.workshopList.length > 0) {
              commit('SET_WORKSHOP_LIST', data.workshopList)
              // console.log(data)
              commit('SET_DEVICE_CATEGORY_LIST', data.workshopList)
              commit('SET_USER_INFO', data)
              resolve({ code: 1, data: data })
            } else {
              commit('SET_WORKSHOP_LIST', [])
              commit('SET_DEVICE_CATEGORY_LIST', [])
              commit('SET_TOKEN', '')
              commit('SET_USER_INFO', {})
              removeToken()
              resolve({ code: 0, msg: '您没有权限访问,请联系管理员进行授权!' })
            }
            // if (data.workshopList && data.workshopList.length > 0) {
            //   commit('SET_WORKSHOP_LIST', data.workshopList)
            //   // console.log(data)
            //   commit('SET_DEVICE_CATEGORY_LIST', data.workshopList)
            //   commit('SET_USER_INFO', data)
            //   resolve({ code: 1, data: data })
            // } else {
            //   commit('SET_WORKSHOP_LIST', [])
            //   commit('SET_DEVICE_CATEGORY_LIST', [])
            //   commit('SET_TOKEN', '')
            //   commit('SET_USER_INFO', {})
            //   removeToken()
            //   resolve({ code: 0, msg: '您没有权限访问,请联系管理员进行授权!' })
            // }
          }else {
            removeToken()
            resolve({ code: 0, msg: '由于您长时间没有操作,请重新登录!' })
          }
          // else {
          //   resolve({ code: 0, msg: '由于您长时间没有操作,请重新登录!' })
          // }
        }).catch(() => {
          resolve({ code: -1, msg: '网络异常,稍后重试!' })
        })
src/test.js
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,21 @@
/*
 * @Date: 2023-12-20 20:24:18
 * @LastEditors: Sneed
 * @LastEditTime: 2024-01-02 20:09:15
 * @FilePath: /belleson-frontend/Users/mache/Library/Containers/com.tencent.xinWeChat/Data/Library/Application Support/com.tencent.xinWeChat/2.0b4.0.9/650b28d71b3acf9feb5c2af6da2686eb/Message/MessageTemp/650b28d71b3acf9feb5c2af6da2686eb/File/mdc-portal/src/test.js
 */
import Vue from 'vue'
import ElementUI from 'element-ui'
import 'element-ui/lib/theme-chalk/index.css'
import locale from 'element-ui/lib/locale/lang/zh-CN' // lang i18n
import '@/styles/index.scss' // global css
import App from './Test.vue'
Vue.use(ElementUI, { locale })
Vue.config.productionTip = false
new Vue({
  el: '#app',
  template: '<App/>',
  components: { App }
})
src/utils/ajax.js
@@ -1,17 +1,28 @@
/*
 * @Date: 2022-11-09 12:37:25
 * @LastEditors: Sneed
 * @LastEditTime: 2024-01-05 23:08:20
 * @FilePath: /belleson-frontend/Users/mache/Documents/demo/mdc/src/utils/ajax.js
 */
import axios from 'axios'
import { Message } from 'element-ui'
import store from '../store'
import { getToken, setToken } from '@/utils/auth'
import qs from 'qs'
const URL_CFG = {
  BASE_URL: '',
  WEB_SOCKET_URL: ''
}
// åˆ›å»ºaxios实例
const service = axios.create({
  // baseURL: process.env.BASE_API, // api的base_url
  timeout: 300000 // è¯·æ±‚è¶…æ—¶æ—¶é—´
  timeout: 3000 // è¯·æ±‚è¶…æ—¶æ—¶é—´
})
// request拦截器
service.interceptors.request.use(config => {
  config.url = `${URL_CFG.BASE_URL}${config.url}`
  if (store.getters.token) {
    config.headers['mdc-token'] = getToken().value // è®©æ¯ä¸ªè¯·æ±‚携带自定义token è¯·æ ¹æ®å®žé™…情况自行修改
  }
@@ -70,6 +81,7 @@
  }
)
export default {
  URL_CFG,
  // post请求
  post: function(url, params) {
    return service({
src/views/home/Welcome.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,28 @@
<!--
 * @Date: 2024-01-04 23:08:48
 * @LastEditors: Sneed
 * @LastEditTime: 2024-01-05 22:24:02
 * @FilePath: /belleson-frontend/Users/mache/Documents/demo/mdc/src/views/home/Welcome.vue
-->
<template>
    <div>
        <div class="welcome">
            admin您好,欢迎使用千文科技MDC展示系统
        </div>
    </div>
</template>
<style lang="scss" scoped>
    .welcome {
        width: 100%;
        height: 102px;
        position: absolute;
        top: 30%;
        font-size: 40px;
        color: #68D9FF;
        line-height: 102px;
        background: url('./welcome.png') 0 0 no-repeat;
        background-size: contain;
        text-align: center;
        user-select:none;
    }
</style>
src/views/home/earth.png
src/views/home/index.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,111 @@
<template>
    <Home>
        <template slot="menu">
            <div class="menu-container">
                <ul class="" @click="navigateTo('map')">
                    <li class="active">状态监控</li>
                    <li @click="navigateTo('map')">大屏展示</li>
                    <li>车间地图</li>
                    <li>车间列表</li>
                    <li>设备保养</li>
                    <li>报表生成</li>
                    <li>班次设置</li>
                    <li>工件信息</li>
                    <li>更多菜单</li>
                </ul>
                <div class="user">
                    <span>Admin</span>
                    <img @click="logout" src="./logout.png" alt="">
                </div>
            </div>
        </template>
        <template slot="content">
            <div class="container">
                <!-- <div class="welcome">
                    admin您好,欢迎使用千文科技MDC展示系统
                </div> -->
                <router-view></router-view>
            </div>
        </template>
    </Home>
</template>
<script>
import { mapGetters } from 'vuex'
import Home from '@/components/home/index'
export default {
    components: {
        Home
    },
    methods: {
        logout() {
            this.$store.dispatch('LogOut').then(() => {
                // location.reload() // ä¸ºäº†é‡æ–°å®žä¾‹åŒ–vue-router对象 é¿å…bug
                this.$router.push('/')
            })
        },
        navigateTo (name) {
            console.log(name)
            this.$router.push('/home/map')
        }
    },
}
</script>
<style lang="scss" scoped>
.container {
    position: absolute;
    top: 0;
    left: 50%;
    width: 60%;
    transform: translateX(-50%);
    height: 100%;
    background-image: url('./earth.png');
    background-repeat: no-repeat;
    background-size: contain;
}
.menu-container {
    margin-left: auto;
    display: flex;
    line-height: 37px;
    ul {
        flex: 0 1 auto;
        color: #AEAFAF;
        font-size: 18px;
        list-style: none;
        display: flex;
        li {
            cursor: pointer;
            background: #27394E;
            padding: 0 12px;
            white-space: nowrap;
            text-overflow: ellipsis;
            // user-select:none;
        }
        li~li {
            margin-left: 10px;
        }
        li.active {
            color: #68D9FF;
        }
    }
    .user {
        margin-left: 30px;
        width: 114px;
        height: 37px;
        background: rgba(38, 36, 36, 0.58);
        border-radius: 19px;
        display: flex;
        align-items: center;
        cursor: pointer;
        span {
            padding: 0 13px;
            color: #FFFFFF;
            font-size: 16px;
        }
        img {
            width: 20px;
            height: 20px;
        }
    }
}
</style>
src/views/home/logout.png
src/views/home/map.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,9 @@
<!--
 * @Date: 2024-01-05 22:26:22
 * @LastEditors: Sneed
 * @LastEditTime: 2024-01-05 22:26:30
 * @FilePath: /belleson-frontend/Users/mache/Documents/demo/mdc/src/container/Map/index.vue
-->
<template>
    <div>车间地图</div>
</template>
src/views/home/welcome.png
src/views/login/index.vue
@@ -1,37 +1,94 @@
<template>
  <div class="login-container">
    <el-form class="login-form" autoComplete="on" :model="loginForm" :rules="loginRules" ref="loginForm" label-position="left">
      <h3 class="title">航星MDC展示系统</h3>
      <el-form-item prop="username">
  <Home>
    <template slot="test"><span style="color: red">123</span></template>
    <template slot="content">
      <el-form  class="login-form" autoComplete="on" :model="loginForm" :rules="loginRules" ref="loginForm" label-position="left">
      <el-form-item prop="username" class="username">
        <span class="svg-container svg-container_login">
          <svg-icon icon-class="user" />
        </span>
        <el-input name="username" type="text" v-model="loginForm.username" autoComplete="on" placeholder="用户名" />
        <el-input  name="username" type="text" v-model="loginForm.username" autoComplete="on" placeholder="请输入用户名" />
      </el-form-item>
      <el-form-item prop="password">
      <el-form-item prop="password" class="username">
        <span class="svg-container">
          <svg-icon icon-class="password"></svg-icon>
        </span>
        <el-input name="password" :type="pwdType" @keyup.enter.native="handleLogin" v-model="loginForm.password" autoComplete="off"
          placeholder="密码"></el-input>
          placeholder="请输入密码"></el-input>
          <span class="show-pwd" @click="showPwd"><svg-icon icon-class="eye" v-show="pwdType==='password'"/><svg-icon icon-class="eyeopen" v-show="pwdType!=='password'"/></span>
      </el-form-item>
      <el-form-item>
        <el-button type="primary" style="width:100%;" :loading="loading" @click.native.prevent="handleLogin">
      <el-form-item style="text-align: center;margin-top: 30px">
        <div class="btn" :loading="loading" @click="handleLogin">
          ç™»å½•
        </el-button>
        </div>
      </el-form-item>
    </el-form>
    <p class="copy-right"><span>航星国际自动控制工程有限公司</span></p>
  </div>
    <p class="compName">千文科技</p><el-form class="login-form" autoComplete="on" :model="loginForm" :rules="loginRules" ref="loginForm" label-position="left">
      <el-form-item prop="username" class="username">
        <span class="svg-container svg-container_login">
          <svg-icon icon-class="user" />
        </span>
        <el-input  name="username" type="text" v-model="loginForm.username" autoComplete="on" placeholder="请输入用户名" />
      </el-form-item>
      <el-form-item prop="password" class="username">
        <span class="svg-container">
          <svg-icon icon-class="password"></svg-icon>
        </span>
        <el-input name="password" :type="pwdType" @keyup.enter.native="handleLogin" v-model="loginForm.password" autoComplete="off"
          placeholder="请输入密码"></el-input>
          <span class="show-pwd" @click="showPwd"><svg-icon icon-class="eye" v-show="pwdType==='password'"/><svg-icon icon-class="eyeopen" v-show="pwdType!=='password'"/></span>
      </el-form-item>
      <el-form-item style="text-align: center;margin-top: 30px">
        <div class="btn" :loading="loading" @click="handleLogin">
          ç™»å½•
        </div>
      </el-form-item>
    </el-form>
    <p class="compName">千文科技</p>
    </template>
  </Home>
  <!-- <div class="login-container">
    <div class="header">
      <img src="~@/assets/img/login/logo.png" alt="">
    </div>
    <div class="content">
      <el-form class="login-form" autoComplete="on" :model="loginForm" :rules="loginRules" ref="loginForm" label-position="left">
      <el-form-item prop="username" class="username">
        <span class="svg-container svg-container_login">
          <svg-icon icon-class="user" />
        </span>
        <el-input  name="username" type="text" v-model="loginForm.username" autoComplete="on" placeholder="请输入用户名" />
      </el-form-item>
      <el-form-item prop="password" class="username">
        <span class="svg-container">
          <svg-icon icon-class="password"></svg-icon>
        </span>
        <el-input name="password" :type="pwdType" @keyup.enter.native="handleLogin" v-model="loginForm.password" autoComplete="off"
          placeholder="请输入密码"></el-input>
          <span class="show-pwd" @click="showPwd"><svg-icon icon-class="eye" v-show="pwdType==='password'"/><svg-icon icon-class="eyeopen" v-show="pwdType!=='password'"/></span>
      </el-form-item>
      <el-form-item style="text-align: center;margin-top: 30px">
        <div class="btn" :loading="loading" @click="handleLogin">
          ç™»å½•
        </div>
      </el-form-item>
    </el-form>
    <p class="compName">千文科技</p>
    </div>
    <div class="footer">
    </div>
  </div> -->
</template>
<script>
import { isvalidUsername } from '@/utils/validate'
import { Message } from 'element-ui'
import Home from '@/components/home/index'
export default {
  name: 'login',
  components: {
    Home
  },
  data() {
    const validateUsername = (rule, value, callback) => {
      if (!isvalidUsername(value)) {
@@ -51,8 +108,8 @@
    }
    return {
      loginForm: {
        username: '',
        password: ''
        username: 'admin',
        password: 'password'
      },
      loginRules: {
        username: [
@@ -82,9 +139,10 @@
          this.loading = true
          this.$store.dispatch('Login', this.loginForm).then((ret) => {
            this.loading = false
            if (ret.code === 1) {
            console.log('------')
            if (ret.result === 'SUCCESS') {
              // this.$router.push({ path: `/room/${this.$store.getters.workshopList[0].roomId}` })
              this.$router.push({ path: `/dashboard` })
              this.$router.push({ path: `/home/index` })
            } else {
              Message({
                message: ret.msg,
@@ -110,8 +168,7 @@
$light_gray:#eee;
/* reset element-ui css */
.login-container {
  .el-input {
.el-input {
    display: inline-block;
    height: 47px;
    width: calc(100% - 40px);
@@ -129,13 +186,6 @@
      }
    }
  }
  .el-form-item {
    border: 1px solid rgba(255, 255, 255, 0.1);
    background: rgba(0, 0, 0, 0.1);
    border-radius: 5px;
    color: #454545;
  }
}
</style>
@@ -149,10 +199,79 @@
  width: 100%;
  background-color: $bg;
  overflow: auto;
  .login-form {
    max-width: 520px;
    padding: 35px 35px 15px 35px;
    margin: 120px auto 0;
  display: flex;
  flex-direction: column;
  .header {
    padding-left: 30px;
    height: 94px;
    flex: 0 0 auto;
    background-image: url('~@/assets/img/login/top.png');
    background-size: contain;
    img {
      display: inline-block;
      width: 500px;
      max-height: 91px;
    }
  }
  .content {
    flex: 1 1 auto;
    background-image: url('~@/assets/img/login/bg.png');
    background-size: cover;
    background-repeat: no-repeat;
    position: relative;
    .compName {
      font-size: 23px;
      color: #FFFFFF;
      line-height: 33px;
      position: absolute;
      left: 0;
      right: 0;
      text-align: center;
      bottom: 30px;
    }
  }
  .footer {
    height: 46px;
    background-image: url('~@/assets/img/login/footer.png');
    background-size: cover;
    background-repeat: no-repeat;
    flex: 0 0 auto;
  }
}
.login-form {
    position: absolute;
    left: 50%;
    top: 20%;
    transform: translate(-50%,0);
    width: 668px;
    height: 340px;
    background-image: url('~@/assets/img/login/logo_bg.png');
    background-size: contain;
    background-repeat: no-repeat;
    padding: 60px 26px;
    // margin: 120px auto 0;
    // background: #161A19;
    .username {
      background: linear-gradient(90deg, rgba(83,198,255,0) 0%, rgba(83,198,255,0.23) 26%, rgba(83,198,255,0) 100%);
border: 1px solid;
border-image: linear-gradient(90deg, rgba(83, 198, 255, 0), rgba(83, 198, 255, 1), rgba(83, 198, 255, 0)) 1 1;
    }
    .username ~ .username {
      margin-top: 30px;
    }
  }
  .btn {
    display: inline-block;
    width: 293px;
    height: 57px;
    text-align: center;
    line-height: 57px;
    background-image: url('~@/assets/img/login/btn_bg.png');
    background-size: contain;
    background-repeat: no-repeat;
    font-size: 19px;
    color: #379BC7;
    cursor: pointer;
  }
  .svg-container {
    padding: 6px 5px 6px 15px;
@@ -191,5 +310,4 @@
    text-align: center;
    font-size: 70%;
  }
}
</style>
src/views/login/index1.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,195 @@
<template>
  <div class="login-container">
    <el-form class="login-form" autoComplete="on" :model="loginForm" :rules="loginRules" ref="loginForm" label-position="left">
      <h3 class="title">航星MDC展示系统</h3>
      <el-form-item prop="username">
        <span class="svg-container svg-container_login">
          <svg-icon icon-class="user" />
        </span>
        <el-input name="username" type="text" v-model="loginForm.username" autoComplete="on" placeholder="用户名" />
      </el-form-item>
      <el-form-item prop="password">
        <span class="svg-container">
          <svg-icon icon-class="password"></svg-icon>
        </span>
        <el-input name="password" :type="pwdType" @keyup.enter.native="handleLogin" v-model="loginForm.password" autoComplete="off"
          placeholder="密码"></el-input>
          <span class="show-pwd" @click="showPwd"><svg-icon icon-class="eye" v-show="pwdType==='password'"/><svg-icon icon-class="eyeopen" v-show="pwdType!=='password'"/></span>
      </el-form-item>
      <el-form-item>
        <el-button type="primary" style="width:100%;" :loading="loading" @click.native.prevent="handleLogin">
          ç™»å½•
        </el-button>
      </el-form-item>
    </el-form>
    <p class="copy-right"><span>航星国际自动控制工程有限公司</span></p>
  </div>
</template>
<script>
import { isvalidUsername } from '@/utils/validate'
import { Message } from 'element-ui'
export default {
  name: 'login',
  data() {
    const validateUsername = (rule, value, callback) => {
      if (!isvalidUsername(value)) {
        callback(new Error('请输入正确的用户名'))
      } else {
        callback()
      }
    }
    const validatePass = (rule, value, callback) => {
      if (value.length === 0) {
        callback(new Error('密码不能为空'))
      } else if (value.length < 5) {
        callback(new Error('密码不能小于6位'))
      } else {
        callback()
      }
    }
    return {
      loginForm: {
        username: '',
        password: ''
      },
      loginRules: {
        username: [
          { required: true, message: '用户名不能为空', trigger: ['blur', 'change'] },
          { trigger: ['blur', 'change'], validator: validateUsername }
        ],
        password: [
          { required: true, message: '密码不能为空', trigger: ['blur', 'change'] },
          { trigger: ['blur', 'change'], validator: validatePass }
        ]
      },
      loading: false,
      pwdType: 'password'
    }
  },
  methods: {
    showPwd() {
      if (this.pwdType === 'password') {
        this.pwdType = ''
      } else {
        this.pwdType = 'password'
      }
    },
    handleLogin() {
      this.$refs.loginForm.validate(valid => {
        if (valid) {
          this.loading = true
          this.$store.dispatch('Login', this.loginForm).then((ret) => {
            this.loading = false
            if (ret.code === 1) {
              // this.$router.push({ path: `/room/${this.$store.getters.workshopList[0].roomId}` })
              this.$router.push({ path: `/dashboard` })
            } else {
              Message({
                message: ret.msg,
                type: 'error',
                duration: 3 * 1000
              })
            }
          }).catch(() => {
            this.loading = false
          })
        } else {
          // console.log('error submit!!')
          return false
        }
      })
    }
  }
}
</script>
<style rel="stylesheet/scss" lang="scss">
$bg:#2d3a4b;
$light_gray:#eee;
/* reset element-ui css */
.login-container {
  .el-input {
    display: inline-block;
    height: 47px;
    width: calc(100% - 40px);
    input {
      background: transparent;
      border: 0px;
      -webkit-appearance: none;
      border-radius: 0px;
      padding: 12px 5px 12px 15px;
      color: $light_gray;
      height: 47px;
      &:-webkit-autofill {
        -webkit-box-shadow: 0 0 0px 1000px $bg inset !important;
        -webkit-text-fill-color: #fff !important;
      }
    }
  }
  .el-form-item {
    border: 1px solid rgba(255, 255, 255, 0.1);
    background: rgba(0, 0, 0, 0.1);
    border-radius: 5px;
    color: #454545;
  }
}
</style>
<style rel="stylesheet/scss" lang="scss" scoped>
$bg:#2d3a4b;
$dark_gray:#889aa4;
$light_gray:#eee;
.login-container {
  /*position: relative;*/
  height: 100%;
  width: 100%;
  background-color: $bg;
  overflow: auto;
  .login-form {
    max-width: 520px;
    padding: 35px 35px 15px 35px;
    margin: 120px auto 0;
  }
  .svg-container {
    padding: 6px 5px 6px 15px;
    color: $dark_gray;
    vertical-align: middle;
    width: 30px;
    display: inline-block;
    &_login {
      font-size: 20px;
    }
  }
  .title {
    font-size: 26px;
    font-weight: 400;
    color: $light_gray;
    margin: 0px auto 40px auto;
    text-align: center;
    font-weight: bold;
  }
  .show-pwd {
    position: absolute;
    right: 10px;
    top: 7px;
    font-size: 16px;
    color: $dark_gray;
    /*cursor: pointer;*/
    user-select: none;
  }
  .copy-right{
    width: 100%;
    margin-top: 40px;
    display: flex;
    justify-content: center;
    align-items: center;
    color: #eee;
    text-align: center;
    font-size: 70%;
  }
}
</style>
static/ico.png
static/table-merge-utils.min.js
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1 @@
var TableMergeUtils=function(){"use strict";function r(r,t){var o=Object.keys(r);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(r);t&&(n=n.filter((function(t){return Object.getOwnPropertyDescriptor(r,t).enumerable}))),o.push.apply(o,n)}return o}function t(t){for(var o=1;o<arguments.length;o++){var e=null!=arguments[o]?arguments[o]:{};o%2?r(Object(e),!0).forEach((function(r){n(t,r,e[r])})):Object.getOwnPropertyDescriptors?Object.defineProperties(t,Object.getOwnPropertyDescriptors(e)):r(Object(e)).forEach((function(r){Object.defineProperty(t,r,Object.getOwnPropertyDescriptor(e,r))}))}return t}function o(r,t){for(var o=0;o<t.length;o++){var n=t[o];n.enumerable=n.enumerable||!1,n.configurable=!0,"value"in n&&(n.writable=!0),Object.defineProperty(r,a(n.key),n)}}function n(r,t,o){return(t=a(t))in r?Object.defineProperty(r,t,{value:o,enumerable:!0,configurable:!0,writable:!0}):r[t]=o,r}function e(r,t){if(null==r)return{};var o,n,e=function(r,t){if(null==r)return{};var o,n,e={},s=Object.keys(r);for(n=0;n<s.length;n++)o=s[n],t.indexOf(o)>=0||(e[o]=r[o]);return e}(r,t);if(Object.getOwnPropertySymbols){var s=Object.getOwnPropertySymbols(r);for(n=0;n<s.length;n++)o=s[n],t.indexOf(o)>=0||Object.prototype.propertyIsEnumerable.call(r,o)&&(e[o]=r[o])}return e}function s(r){return function(r){if(Array.isArray(r))return i(r)}(r)||function(r){if("undefined"!=typeof Symbol&&null!=r[Symbol.iterator]||null!=r["@@iterator"])return Array.from(r)}(r)||function(r,t){if(!r)return;if("string"==typeof r)return i(r,t);var o=Object.prototype.toString.call(r).slice(8,-1);"Object"===o&&r.constructor&&(o=r.constructor.name);if("Map"===o||"Set"===o)return Array.from(r);if("Arguments"===o||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(o))return i(r,t)}(r)||function(){throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}()}function i(r,t){(null==t||t>r.length)&&(t=r.length);for(var o=0,n=new Array(t);o<t;o++)n[o]=r[o];return n}function a(r){var t=function(r,t){if("object"!=typeof r||null===r)return r;var o=r[Symbol.toPrimitive];if(void 0!==o){var n=o.call(r,t||"default");if("object"!=typeof n)return n;throw new TypeError("@@toPrimitive must return a primitive value.")}return("string"===t?String:Number)(r)}(r,"string");return"symbol"==typeof t?t:String(t)}function l(r){var o=JSON.parse(JSON.stringify(r)),n=o[0].reduce((function(r,t){return r+t.colspan}),0),e=Array.from({length:n},(function(){return 0})),s=Array.from({length:n},(function(){return[]}));return o.forEach((function(r,o){r.forEach((function(r,i){r._row=o,r._col=i,r._startRow=o,r._endRow=o+r.rowspan-1;for(var a=e.reduce((function(r,t,o){return t<r.height?{index:o,height:t}:r}),{index:0,height:e[0]}).index,l=r.colspan;l>0;){var w=a+l-1;w<n&&(s[w].push(t({},r)),e[w]+=r.rowspan),l--}r._startCol=a,r._endCol=r._startCol+r.colspan-1}))})),{_rows:o,_cols:s}}function w(r,t,o,n){return!(t<o||r>n)&&{start:r===o,end:t===n,pass:r>=o&&t<=n,common:Math.min(t,n)-Math.max(r,o)+1,comCol:[Math.max(r,o),Math.min(t,n)]}}function c(r,t,o,n){var e=l(r)._rows,s=e[t][o],i=e[t][o+n],a=i&&i.rowspan===s.rowspan&&-1===n&&i._endCol+1===s._startCol,w=i&&i.rowspan===s.rowspan&&1===n&&i._startCol-1===s._endCol;return a||w?r[t][o+n]:null}function h(r,t,o,n){var e=l(r)._rows,s=e[t][o],i=null,a=null,c=null;return e.forEach((function(t,o){t.forEach((function(t,e){var l=w(t._startCol,t._endCol,s._startCol,s._endCol);l.start&&l.end&&(-1===n&&t._endRow+1===s._startRow||1===n&&t._startRow-1===s._endRow)&&(i=r[o][e],a=o,c=e)}))})),{targetCell:i,row:a,col:c}}var u=["rows","cols"],f={rowspan:1,colspan:1,width:100,height:40},p=function(){function r(o){var e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{};!function(r,t){if(!(r instanceof t))throw new TypeError("Cannot call a class as a function")}(this,r),n(this,"rows",[]),n(this,"options",{minRetainRow:0,minRetainCol:0,minSplitHcolspan:2,minSplitVrowspan:2,fixRowType:1}),this.rows=o,this.options=t(t({},this.options),e)}var i,a,p;return i=r,a=[{key:"getDisabledHandles",value:function(){var r=arguments.length>0&&void 0!==arguments[0]?arguments[0]:-1,t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:-1,o=[],n=this.rows[r]&&this.rows[r][t];return n?(this.rows.reduce((function(r,t){return r+Math.min.apply(Math,s(t.map((function(r){return r.rowspan}))))}),0)-n.rowspan<this.options.minRetainRow&&o.push("delRow"),this.rows[0].reduce((function(r,t){return r+t.colspan}),0)-n.colspan<this.options.minRetainCol&&o.push("delCol"),n.colspan<this.options.minSplitHcolspan&&o.push("splitH"),n.rowspan<this.options.minSplitVrowspan&&o.push("splitV"),c(this.rows,r,t,-1)||o.push("leftMerge"),c(this.rows,r,t,1)||o.push("rightMerge"),h(this.rows,r,t,-1).targetCell||o.push("topMerge"),h(this.rows,r,t,1).targetCell||o.push("bottomMerge")):o=["insertRow","insertCol","delRow","delCol","splitH","splitV","leftMerge","rightMerge","topMerge","bottomMerge"],o}},{key:"handFixRow",value:function(){1===this.options.fixRowType?this.rows.forEach((function(r){if(r.length>1){var t=r.reduce((function(r,t){return Math.min(r,t.rowspan)}),r[0].rowspan)-1;t>0&&r.forEach((function(r){return r.rowspan-=t}))}})):2===this.options.fixRowType&&function(r){var t=0;r.forEach((function(o,n){var e=o.length&&o.every((function(r){return r.rowspan>1}));e&&(r.splice(n+t+1,0,[]),t++)}))}(this.rows)}},{key:"insertRow",value:function(r,o,n){var e=this;if(!this.getDisabledHandles(r,o).includes("insertRow")){var s=l(this.rows)._rows,i=this.rows[r][o],a=n?r+i.rowspan:r;if(a<s.length){s.forEach((function(r,t){t<a&&r.forEach((function(r){w(r._startRow,r._endRow,a,a)&&(e.rows[r._row][r._col].rowspan++,e.rows[r._row][r._col].height+=f.height)}))}));var c=this.rows[a].map((function(r){return t(t({},f),{},{width:r.width,colspan:r.colspan})}));this.rows.splice(a,0,c)}else{var h=this.rows[this.rows.length-1].map((function(r){return t(t({},f),{},{width:r.width,colspan:r.colspan})}));this.rows.splice(a,0,h)}var u=n?r:r+1;return{rows:this.rows,row:u,col:o,disabledHandles:this.getDisabledHandles(u,o)}}}},{key:"insertCol",value:function(r,o,n){var e=this;if(!this.getDisabledHandles(r,o).includes("insertCol")){var s=l(this.rows)._rows,i=s[r][o];s.forEach((function(s,a){if(r===a)e.rows[a].splice(o+n,0,t(t({},f),{},{rowspan:i.rowspan}));else if(n){var l=-1;if(s.forEach((function(r,t){w(r._startCol,r._endCol,i._startCol,i._endCol)&&(l=t)})),l>-1){var c=s[l];w(c._startCol,c._endCol,i._startCol,i._endCol).end?e.rows[a].splice(l+n,0,t(t({},f),{},{rowspan:c.rowspan,colspan:1})):(e.rows[c._row][c._col].colspan++,e.rows[c._row][c._col].width+=f.width)}}else{var h=s.findIndex((function(r){return w(r._startCol,r._endCol,i._startCol,i._endCol)}));if(h>-1){var u=s[h];w(u._startCol,u._endCol,i._startCol,i._endCol).start?e.rows[a].splice(h+n,0,t(t({},f),{},{rowspan:u.rowspan,colspan:1})):(e.rows[u._row][u._col].colspan++,e.rows[u._row][u._col].width+=f.width)}}}));var a=n?o:o+1;return{rows:this.rows,row:r,col:a,disabledHandles:this.getDisabledHandles(r,a)}}}},{key:"delRow",value:function(r,o){var n,e=this;if(!this.getDisabledHandles(r,o).includes("delRow")){var i=l(this.rows)._rows,a=i[r][o];i.forEach((function(n,s){if(s<r)n.forEach((function(r){var t=w(r._startRow,r._endRow,a._startRow,a._endRow);t&&(e.rows[r._row][r._col].rowspan-=t.common,e.rows[r._row][r._col].height-=a.height)}));else if(s>r){var l=[];n.forEach((function(n,s){var c=w(n._startRow,n._endRow,a._startRow,a._endRow);if(c&&(l.push(s),!c.pass)){var u=t(t({},e.rows[n._row][n._col]),{},{rowspan:n.rowspan-c.common}),f=h(i,r,o,1),p=f.row,d=f.col;e.rows[p].splice(d+1,0,u)}}));var c=e.rows[s].filter((function(r,t){return!l.includes(t)}));e.rows.splice(s,1,c)}}));var c=r+a.rowspan;i[r].forEach((function(r){var o=l(e.rows)._rows;if(r.rowspan>a.rowspan){var n=o[c].findIndex((function(t){return t._startCol>r._endCol}));-1===n&&o[c].forEach((function(t,o){t._endCol<r._startCol&&(n=o+1)})),e.rows[c].splice(n,0,t(t({},r),{},{rowspan:r.rowspan-a.rowspan,height:r.height-a.height}))}})),this.rows.splice(r,1);var u=this.rows.filter((function(r){return 0!==r.length}));return(n=this.rows).splice.apply(n,[0,this.rows.length].concat(s(u))),{rows:this.rows,row:-1,col:-1,disabledHandles:this.getDisabledHandles(-1,-1)}}}},{key:"delCol",value:function(r,t){var o,n=this;if(!this.getDisabledHandles(r,t).includes("delCol")){var e=l(this.rows)._rows,i=e[r][t];e.forEach((function(r,t){var o=[];r.forEach((function(r,t){var e=w(r._startCol,r._endCol,i._startCol,i._endCol);e&&(e.pass?o.push(t):(n.rows[r._row][r._col].colspan-=e.common,n.rows[r._row][r._col].width-=i.width))}));var e=n.rows[t].filter((function(r,t){return!o.includes(t)}));t<n.rows.length?n.rows.splice(t,1,e):n.rows.splice(t-n.rows.length,1,e)})),this.rows.every((function(r){return 1===r.length}))&&this.rows.forEach((function(r){return r.forEach((function(r){return r.rowspan=1}))}));var a=this.rows.filter((function(r){return 0!==r.length}));return(o=this.rows).splice.apply(o,[0,this.rows.length].concat(s(a))),this.handFixRow(),{rows:this.rows,row:-1,col:-1,disabledHandles:this.getDisabledHandles(-1,-1)}}}},{key:"splitH",value:function(r,o){var n=this;if(!this.getDisabledHandles(r,o).includes("splitH")){var e=l(this.rows),s=e._rows,i=e._cols,a=this.rows[r][o],c=s[r][o];if(a.colspan>1){var h=c.colspan;a.colspan-=Math.floor(h/2);for(var u=c._startCol,p=c._startCol+a.colspan-1,d=0;u<=p;)d+=i[u].find((function(r){return 1===r.colspan})).width,u++;a.width=d;for(var g=h-a.colspan,v=p+1,_=v+g-1,b=0;v<=_;)b+=i[v].find((function(r){return 1===r.colspan})).width,v++;this.rows[r].splice(o+1,0,t(t({},f),{},{width:b,height:a.height,colspan:g,rowspan:a.rowspan}))}else s.forEach((function(e,s){if(s===r)a.width/=2,n.rows[r].splice(o+1,0,t(t({},f),{},{width:a.width,height:a.height,rowspan:a.rowspan}));else{var i=e.findIndex((function(r){return w(r._startCol,r._endCol,c._startCol,c._endCol)}));i>-1&&(n.rows[s][i].colspan+=1)}}));return{rows:this.rows,row:r,col:o,disabledHandles:this.getDisabledHandles(r,o)}}}},{key:"splitV",value:function(r,o){var n=this;if(!this.getDisabledHandles(r,o).includes("splitV")){var e=l(this.rows)._rows,s=e[r][o],i=this.rows[r][o];if(i.rowspan>1){var a=s.rowspan;i.rowspan-=Math.floor(a/2);for(var c=s._startRow,h=s._startRow+i.rowspan-1,u=0;c<=h;)u+=e[c].find((function(r){return 1===r.rowspan})).height,c++;i.height=u;for(var p=a-i.rowspan,d=h+1,g=d+p-1,v=0;d<=g;)v+=e[d].find((function(r){return 1===r.rowspan})).height,d++;var _=r+i.rowspan,b=e[_].findIndex((function(r){return r._startCol>s._endCol}));-1===b?(e[_].forEach((function(r,t){r._endCol<s._startCol&&(b=t)})),this.rows[_].splice(b+1,0,t(t({},f),{},{rowspan:p,colspan:i.colspan,width:i.width,height:v}))):this.rows[_].splice(b,0,t(t({},f),{},{rowspan:p,colspan:i.colspan,width:i.width,height:v}))}else i.height/=2,this.rows.splice(r+1,0,Array.from({length:1},(function(){return t(t({},f),{},{colspan:i.colspan,width:i.width,height:i.height})}))),e.forEach((function(t,e){t.forEach((function(t,i){e===r&&i===o||w(t._startRow,t._endRow,s._startRow,s._endRow)&&n.rows[t._row][t._col].rowspan++}))}));return{rows:this.rows,row:r,col:o,disabledHandles:this.getDisabledHandles(r,o)}}}},{key:"leftMerge",value:function(r,t){if(!this.getDisabledHandles(r,t).includes("leftMerge")){var o=c(this.rows,r,t,-1);if(o){var n=this.rows[r][t];return o.colspan+=n.colspan,o.width+=n.width,this.rows[r].splice(t,1),{rows:this.rows,row:r,col:t-1,disabledHandles:this.getDisabledHandles(r,t-1)}}}}},{key:"rightMerge",value:function(r,t){if(!this.getDisabledHandles(r,t).includes("rightMerge")){var o=c(this.rows,r,t,1);if(o){var n=this.rows[r][t];return n.colspan+=o.colspan,n.width+=o.width,this.rows[r].splice(t+1,1),{rows:this.rows,row:r,col:t,disabledHandles:this.getDisabledHandles(r,t)}}}}},{key:"topMerge",value:function(r,t){if(!this.getDisabledHandles(r,t).includes("topMerge")){var o=h(this.rows,r,t,-1),n=o.targetCell,e=o.row,s=o.col;if(n){if(1===this.rows[r].length)this.delRow(this.rows,r,t);else{var i=this.rows[r][t];n.rowspan+=i.rowspan,n.height+=i.height,this.rows[r].splice(t,1)}return{rows:this.rows,row:e,col:s,disabledHandles:this.getDisabledHandles(e,s)}}}}},{key:"bottomMerge",value:function(r,t){if(!this.getDisabledHandles(r,t).includes("bottomMerge")){var o=h(this.rows,r,t,1),n=o.targetCell,e=o.row,s=o.col;if(n){if(1===this.rows[e].length)this.delRow(e,s);else{var i=this.rows[r][t];i.rowspan+=n.rowspan,i.height+=n.height,this.rows[e].splice(s,1)}return{rows:this.rows,row:r,col:t,disabledHandles:this.getDisabledHandles(r,t)}}}}}],p=[{key:"init",value:function(r){var o=r.rows,n=r.cols,s=e(r,u);return Array.from({length:o},(function(){return Array.from({length:n},(function(){return t(t({},f),s)}))}))}}],a&&o(i.prototype,a),p&&o(i,p),Object.defineProperty(i,"prototype",{writable:!1}),r}();return p}();