shaogen1995 3 năm trước cách đây
commit
4a2cfd6710

+ 5 - 0
.editorconfig

@@ -0,0 +1,5 @@
+[*.{js,jsx,ts,tsx,vue}]
+indent_style = space
+indent_size = 2
+trim_trailing_whitespace = true
+insert_final_newline = true

+ 23 - 0
.gitignore

@@ -0,0 +1,23 @@
+.DS_Store
+node_modules
+/dist
+
+
+# local env files
+.env.local
+.env.*.local
+
+# Log files
+npm-debug.log*
+yarn-debug.log*
+yarn-error.log*
+pnpm-debug.log*
+
+# Editor directories and files
+.idea
+.vscode
+*.suo
+*.ntvs*
+*.njsproj
+*.sln
+*.sw?

+ 24 - 0
README.md

@@ -0,0 +1,24 @@
+# houtai
+
+## Project setup
+```
+npm install
+```
+
+### Compiles and hot-reloads for development
+```
+npm run serve
+```
+
+### Compiles and minifies for production
+```
+npm run build
+```
+
+### Lints and fixes files
+```
+npm run lint
+```
+
+### Customize configuration
+See [Configuration Reference](https://cli.vuejs.org/config/).

+ 5 - 0
babel.config.js

@@ -0,0 +1,5 @@
+module.exports = {
+  presets: [
+    '@vue/cli-plugin-babel/preset'
+  ]
+}

Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 13390 - 0
package-lock.json


+ 66 - 0
package.json

@@ -0,0 +1,66 @@
+{
+  "name": "houtai",
+  "version": "0.1.0",
+  "private": true,
+  "scripts": {
+    "serve": "vue-cli-service serve",
+    "build": "vue-cli-service build",
+    "lint": "vue-cli-service lint"
+  },
+  "dependencies": {
+    "Base64": "^1.1.0",
+    "axios": "^0.24.0",
+    "core-js": "^3.6.5",
+    "element-ui": "^2.15.6",
+    "js-base64": "^3.7.2",
+    "moment": "^2.29.1",
+    "vue": "^2.6.11",
+    "vue-router": "^3.2.0"
+  },
+  "devDependencies": {
+    "@vue/cli-plugin-babel": "~4.5.0",
+    "@vue/cli-plugin-eslint": "~4.5.0",
+    "@vue/cli-plugin-router": "~4.5.0",
+    "@vue/cli-service": "~4.5.0",
+    "@vue/eslint-config-standard": "^5.1.2",
+    "babel-eslint": "^10.1.0",
+    "eslint": "^6.7.2",
+    "eslint-plugin-import": "^2.20.2",
+    "eslint-plugin-node": "^11.1.0",
+    "eslint-plugin-promise": "^4.2.1",
+    "eslint-plugin-standard": "^4.0.0",
+    "eslint-plugin-vue": "^6.2.2",
+    "less": "^3.0.4",
+    "less-loader": "^5.0.0",
+    "lint-staged": "^9.5.0",
+    "vue-template-compiler": "^2.6.11"
+  },
+  "eslintConfig": {
+    "root": true,
+    "env": {
+      "node": true
+    },
+    "extends": [
+      "plugin:vue/essential",
+      "@vue/standard"
+    ],
+    "parserOptions": {
+      "parser": "babel-eslint"
+    },
+    "rules": {}
+  },
+  "browserslist": [
+    "> 1%",
+    "last 2 versions",
+    "not dead"
+  ],
+  "gitHooks": {
+    "pre-commit": "lint-staged"
+  },
+  "lint-staged": {
+    "*.{js,jsx,vue}": [
+      "vue-cli-service lint",
+      "git add"
+    ]
+  }
+}

BIN
public/favicon.ico


+ 17 - 0
public/index.html

@@ -0,0 +1,17 @@
+<!DOCTYPE html>
+<html lang="">
+  <head>
+    <meta charset="utf-8">
+    <meta http-equiv="X-UA-Compatible" content="IE=edge">
+    <meta name="viewport" content="width=device-width,initial-scale=1.0">
+    <link rel="icon" href="<%= BASE_URL %>favicon.ico">
+    <title>石壁龙智慧园区-管理后台</title>
+  </head>
+  <body>
+    <noscript>
+      <strong>We're sorry but <%= htmlWebpackPlugin.options.title %> doesn't work properly without JavaScript enabled. Please enable it to continue.</strong>
+    </noscript>
+    <div id="app"></div>
+    <!-- built files will be auto injected -->
+  </body>
+</html>

+ 9 - 0
src/App.vue

@@ -0,0 +1,9 @@
+<template>
+  <div id="app">
+    <Router-view/>
+  </div>
+</template>
+
+<style lang="less">
+
+</style>

+ 17 - 0
src/apis/login.js

@@ -0,0 +1,17 @@
+import axios from '../utils/request'
+// 用户登录接口
+export const userLogin = (data) => {
+  return axios({
+    method: 'post',
+    url: '/admin/login',
+    data
+  })
+}
+// 修改密码
+export const updatePwd = (data) => {
+  return axios({
+    method: 'post',
+    url: '/sys/user/updatePwd',
+    data
+  })
+}

+ 24 - 0
src/apis/tab1.js

@@ -0,0 +1,24 @@
+import axios from '../utils/request'
+// 获取整体概况
+export const parkList = (data) => {
+  return axios({
+    method: 'post',
+    url: '/cms/park/list',
+    data
+  })
+}
+// // 获取整体概况
+// export const getDetailById = (id) => {
+//   return axios({
+//     method: 'post',
+//     url: `/cms/park/detail/${id}`
+//   })
+// }
+// 点击修改
+export const parkSave = (data) => {
+  return axios({
+    method: 'post',
+    url: '/cms/park/save',
+    data
+  })
+}

+ 35 - 0
src/assets/css/base.css

@@ -0,0 +1,35 @@
+* {
+  margin: 0;
+  padding: 0;
+  box-sizing: border-box;
+}
+body {
+  background-color: #f2f2f2;
+}
+ul li {
+  list-style: none;
+}
+.el-button--primary{
+  background-color: #1482b4;
+  border-color: #1482b4;
+}
+.el-button--primary:focus, .el-button--primary:hover {
+  background: #186f97;
+  border-color: #186f97;
+}
+.el-input.is-active .el-input__inner, .el-input__inner:focus {
+  border-color: #1482b4;
+}
+.cell{
+  text-align: center !important;
+}
+.el-input__inner{
+  line-height: normal;
+}
+input::-webkit-outer-spin-button,
+input::-webkit-inner-spin-button {
+-webkit-appearance: none;
+}
+input[type="number"] {
+-moz-appearance: textfield;
+}

BIN
src/assets/img/logo.png


BIN
src/assets/img/user.jpg


+ 14 - 0
src/main.js

@@ -0,0 +1,14 @@
+import Vue from 'vue'
+import ElementUI from 'element-ui'
+import 'element-ui/lib/theme-chalk/index.css'
+import App from './App.vue'
+import router from './router'
+import './assets/css/base.css'
+import Moment from 'moment'
+Vue.prototype.moment = Moment
+Vue.config.productionTip = false
+Vue.use(ElementUI)
+new Vue({
+  router,
+  render: h => h(App)
+}).$mount('#app')

+ 59 - 0
src/router/index.js

@@ -0,0 +1,59 @@
+import Vue from 'vue'
+import VueRouter from 'vue-router'
+import { Message } from 'element-ui'
+Vue.use(VueRouter)
+
+const routes = [
+  {
+    path: '/',
+    name: 'login',
+    component: () => import('../views/login.vue')
+  },
+  {
+    path: '/layout',
+    name: 'layout',
+    component: () => import('../views/layout/index.vue'),
+    children: [
+      {
+        path: 'tab1',
+        name: 'tab1',
+        meta: { myInd: 1 },
+        component: () => import('../views/tab1/index.vue')
+      },
+      {
+        path: 'tab1Edit',
+        name: 'tab1Edit',
+        meta: { myInd: 1 },
+        component: () => import('../views/tab1/edit.vue')
+      },
+      {
+        path: 'tab2',
+        name: 'tab2',
+        meta: { myInd: 2 },
+        component: () => import('../views/tab2/index.vue')
+      }
+    ]
+  }
+]
+
+const router = new VueRouter({
+  // mode: 'history',
+  base: process.env.BASE_URL,
+  routes
+})
+
+router.beforeEach((to, from, next) => {
+  // 如果是去登录页,不需要验证,直接下一步
+  if (to.name === 'login') next()
+  // 否则要有token值才能下一步,不然就返回登录页
+  else {
+    const token = localStorage.getItem('SZSBL_token')
+    if (token) next()
+    else {
+      Message.warning('登录失效,请重新登录')
+      next({ name: 'login' })
+    }
+  }
+})
+
+export default router

+ 106 - 0
src/utils/pass.js

@@ -0,0 +1,106 @@
+/* eslint-disable */
+function NoToChinese (num) {
+  num = String(num)
+  var chnNumChar = ['零', '一', '二', '三', '四', '五', '六', '七', '八', '九', '十']
+  if (num == 0) {
+    return chnNumChar[0]
+  }
+  let tmp = ''
+  for (let i = 0; i < num.length; i++) {
+    const ele = num.charAt(i)
+    tmp += chnNumChar[ele]
+  }
+
+  return tmp
+}
+
+function randomWord (randomFlag, min, max) {
+  let str = ''
+  let range = min
+  const arr = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z']
+  // 随机产生
+  if (randomFlag) {
+    range = Math.round(Math.random() * (max - min)) + min
+  }
+  for (var i = 0; i < range; i++) {
+    const pos = Math.round(Math.random() * (arr.length - 1))
+    str += arr[pos]
+  }
+  return str
+}
+
+module.exports = {
+  formatDate: function (time) {
+    var weekArr = ['日', '一', '二', '三', '四', '五', '六']
+    var date = new Date(time)
+    var year = date.getFullYear()
+    var month = date.getMonth() + 1
+    var day = date.getDate()
+    var week = '星期' + weekArr[date.getDay()]
+    if (window.innerWidth < 1700) {
+      return (
+        year +
+        '年' +
+        (String(month).length > 1 ? month : '0' + month) +
+        '月' +
+        (String(day).length > 1 ? day : '0' + day) +
+        '日' +
+        '<br/>' +
+        week
+      )
+    }
+    return (
+      year +
+      '年' +
+      (String(month).length > 1 ? month : '0' + month) +
+      '月' +
+      (String(day).length > 1 ? day : '0' + day) +
+      '日' +
+      ' ' +
+      week
+    )
+  },
+  smoothscrollpos: function (domName) {
+    if (domName == '/') {
+      return window.scrollTo(0, 0)
+    }
+    const smoothscroll = () => {
+      const dom = document.getElementById(domName)
+      // window.scrollTo({
+      //   top:dom.offsetTop - 100,
+      //   left:0,
+      //   behavior: "smooth"
+      // })
+      dom && window.scrollTo(0, dom.offsetTop - 120)
+    }
+    smoothscroll()
+  },
+
+  formatTime: function (time, fan = false) {
+    let t1 = time.split(' ')[0].split('-')
+    if (fan) {
+      t1 = t1.map((item) => {
+        const t = NoToChinese(item)
+        return t
+      })
+    }
+    return t1
+  },
+  encodeStr: function (str, strv = '') {
+    const NUM = 2
+    const front = randomWord(false, 8)
+    const middle = randomWord(false, 8)
+    const end = randomWord(false, 8)
+
+    const str1 = str.substring(0, NUM)
+    const str2 = str.substring(NUM)
+
+    if (strv) {
+      const strv1 = strv.substring(0, NUM)
+      const strv2 = strv.substring(NUM)
+      return [front + str2 + middle + str1 + end, front + strv2 + middle + strv1 + end]
+    }
+
+    return front + str2 + middle + str1 + end
+  }
+}

+ 38 - 0
src/utils/request.js

@@ -0,0 +1,38 @@
+import axios from 'axios'
+const service = axios.create({
+  baseURL: 'http://192.168.0.135:8011/', // 本地调试
+  // baseURL: '', // 线上调试
+  // baseURL: '', // build
+  timeout: 5000
+})
+// 请求拦截器
+service.interceptors.request.use(function (config) {
+  // console.log('触发拦截器')
+  // 在发送请求之前做些什么:看看有没有token,如果有通过请求头的方式传递token
+  const token = localStorage.getItem('SZSBL_token')
+  if (token) { // 判断是否有token,有,则
+    // config.headers['Authorization'] = token
+    config.headers.token = token
+  }
+
+  return config
+}, function (error) {
+  // 对请求错误做些什么
+  return Promise.reject(error)
+})
+
+// 添加响应拦截器
+service.interceptors.response.use(function (response) {
+  // console.log('触发相应拦截器', response)
+  // 对响应数据做点什么--response就是发送每个请求的返回值
+  if (response.data.code === 5001 || response.data.code === 5002) {
+    // Toast.fail('未登录,请先登录')
+    localStorage.removeItem('SZSBL_token')
+  }
+  return response.data
+}, function (error) {
+  // 对响应错误做点什么
+  return Promise.reject(error)
+})
+
+export default service

+ 340 - 0
src/views/layout/index.vue

@@ -0,0 +1,340 @@
+<template>
+  <div class="layout">
+    <div class="top">
+      <img src="@/assets/img/logo.png" alt="" />
+      <p>石壁龙智慧园区</p>
+      <div class="top_right">
+        <div class="user" @click="cut = !cut">
+          <img src="@/assets/img/user.jpg" alt="" />
+          <span>{{userName}}</span>
+          <!-- 下箭头 -->
+          <div class="pull_down" v-if="cut"></div>
+          <div class="pull_up" v-else></div>
+        </div>
+        <!-- 点击箭头出来的ul -->
+        <ul class="user_handle" v-show="cut">
+          <li @click="isShow = true">修改密码</li>
+          <li @click="outLogin">退出登录</li>
+        </ul>
+      </div>
+    </div>
+    <div class="con">
+      <div class="left">
+        <div class="biaoji">数据管理</div>
+        <ul>
+          <li
+            v-for="item in tab1"
+            :key="item.id"
+            :class="{ active: $route.meta.myInd === item.id }"
+            @click="push(item.url)"
+          >
+            {{ item.name }}
+          </li>
+        </ul>
+        <div class="biaoji">系统管理</div>
+        <ul>
+          <li
+            v-for="item in tab2"
+            :key="item.id"
+            :class="{ active: $route.meta.myInd === item.id }"
+            @click="push(item.url)"
+          >
+            {{ item.name }}
+          </li>
+        </ul>
+      </div>
+      <!-- 右侧内容 -->
+      <div class="right">
+        <Router-view />
+      </div>
+    </div>
+    <!-- 点击修改密码出现弹窗 -->
+    <el-dialog title="修改密码" :visible.sync="isShow"  @close="btnX()">
+      <el-form :model="form" label-width="100px" :rules="rules" ref="ruleForm">
+        <el-form-item label="旧密码:" prop="oldPassword">
+          <el-input
+            v-model="form.oldPassword"
+            placeholder="请输入"
+            show-password
+          ></el-input>
+        </el-form-item>
+        <el-form-item label="新密码:" prop="newPassword">
+          <el-input
+            v-model="form.newPassword"
+            placeholder="请输入"
+            show-password
+          ></el-input>
+        </el-form-item>
+        <el-form-item label="确定新密码:" prop="checkPass">
+          <el-input
+            v-model="form.checkPass"
+            placeholder="请输入"
+            show-password
+          ></el-input>
+        </el-form-item>
+      </el-form>
+      <div slot="footer" class="dialog-footer">
+        <el-button @click="btnX">取 消</el-button>
+        <el-button type="primary" @click="btnOk">确 定</el-button>
+      </div>
+    </el-dialog>  </div>
+</template>
+
+<script>
+import { encodeStr } from '../../utils/pass'
+import { Base64 } from 'js-base64'
+import { updatePwd } from '@/apis/login'
+export default {
+  name: 'layout',
+  components: {},
+  data () {
+    // 这里存放数据
+    const validatePass2 = (rule, value, callback) => {
+      if (value !== this.form.newPassword) {
+        callback(new Error('两次输入密码不一致!'))
+      } else {
+        callback()
+      }
+    }
+    return {
+      // 修改密码
+      form: {
+        oldPassword: '',
+        newPassword: '',
+        checkPass: ''
+      },
+      rules: {
+        checkPass: [
+          { validator: validatePass2, trigger: 'blur' }
+        ],
+        oldPassword: [
+          { required: true, message: '不能为空', trigger: 'blur' }
+        ],
+        newPassword: [
+          { required: true, message: '不能为空', trigger: 'blur' }
+        ]
+      },
+      userName: '',
+      cut: false,
+      isShow: false,
+      tab1: [
+        { name: '整体概况', id: 1, url: '/layout/tab1' },
+        { name: '鹏城云脑-能耗管理', id: 2, url: '/layout/tab2' },
+        { name: '鹏城云脑-安防管理', id: 3, url: '/layout/tab3' },
+        { name: '鹏城云脑-物联网设备', id: 4, url: '/layout/tab4' },
+        { name: '工地监控', id: 5, url: '/layout/tab5' },
+        { name: '无人机巡检', id: 6, url: '/layout/tab6' }
+      ],
+      tab2: [
+        { name: '用户管理', id: 7, url: '/layout/tab7' },
+        { name: '操作日志', id: 8, url: '/layout/tab8' }
+      ]
+    }
+  },
+  // 监听属性 类似于data概念
+  computed: {},
+  // 监控data中的数据变化
+  watch: {},
+  // 方法集合
+  methods: {
+  // 修改密码点击取消
+    btnX () {
+      this.$refs.ruleForm.resetFields()
+      this.cut = false
+      this.isShow = false
+      this.form = {
+        oldPassword: '',
+        newPassword: '',
+        checkPass: ''
+      }
+    },
+    // 修改密码点击确定
+    async btnOk () {
+      await this.$refs.ruleForm.validate()
+      try {
+        const data = {
+          oldPassword: encodeStr(Base64.encode(this.form.oldPassword)),
+          newPassword: encodeStr(Base64.encode(this.form.newPassword))
+        }
+        await updatePwd(data)
+        this.$message.success('修改成功')
+        localStorage.clear('SWKK_token')
+        localStorage.clear('SWKK_userInfo')
+        this.$router.push('/')
+      } catch (error) {
+        this.$message.error('旧密码错误')
+      }
+    },
+    push (url) {
+      this.$router.push(url).catch(() => {})
+    },
+    // 点击退出登录
+    outLogin () {
+      this.cut = false
+      this.$confirm('确定退出吗?', '提示', {
+        confirmButtonText: '确定',
+        cancelButtonText: '取消',
+        type: 'warning'
+      })
+        .then(() => {
+          localStorage.clear('SZSBL_token')
+          localStorage.clear('SZSBL_userName')
+          this.$router.push('/')
+          this.$message.success('退出成功!')
+        })
+        .catch(() => {
+          this.$message.info('已取消')
+        })
+    }
+  },
+  // 生命周期 - 创建完成(可以访问当前this实例)
+  created () {
+    // 获取用户名
+    const res = localStorage.getItem('SZSBL_userName')
+    this.userName = res
+  },
+  // 生命周期 - 挂载完成(可以访问DOM元素)
+  mounted () {},
+  beforeCreate () {}, // 生命周期 - 创建之前
+  beforeMount () {}, // 生命周期 - 挂载之前
+  beforeUpdate () {}, // 生命周期 - 更新之前
+  updated () {}, // 生命周期 - 更新之后
+  beforeDestroy () {}, // 生命周期 - 销毁之前
+  destroyed () {}, // 生命周期 - 销毁完成
+  activated () {} // 如果页面有keep-alive缓存功能,这个函数会触发
+}
+</script>
+<style lang='less' scoped>
+.layout {
+  .top {
+    position: relative;
+    width: 100%;
+    min-width: 1800px;
+    box-shadow: 1px 3px 3px 3px rgb(196, 177, 177);
+    height: 70px;
+    background-color: #1482b4;
+    display: flex;
+    align-items: center;
+    & > img {
+      width: 35px;
+      height: 35px;
+      border-radius: 50%;
+      overflow: hidden;
+      margin: 0 30px;
+    }
+    & > P {
+      color: #fff;
+      font-size: 24px;
+      font-weight: 700;
+    }
+    .top_right {
+      width: 150px;
+      position: absolute;
+      right: 30px;
+      top: 0;
+      height: 100%;
+      display: flex;
+      align-items: center;
+      justify-content: space-between;
+      .user {
+        color: #fff;
+        cursor: pointer;
+        position: relative;
+        display: flex;
+        align-items: center;
+        img {
+          margin-right: 15px;
+          width: 34px;
+          height: 34px;
+          border-radius: 50%;
+          overflow: hidden;
+        }
+        .pull_down {
+          position: absolute;
+          right: -25px;
+          bottom: 10px;
+          display: inline-block;
+          width: 0;
+          height: 0;
+          border-left: 8px solid transparent;
+          border-right: 8px solid transparent;
+          border-bottom: 8px solid #fff;
+        }
+        .pull_up {
+          cursor: pointer;
+          position: absolute;
+          right: -25px;
+          bottom: 10px;
+          display: inline-block;
+          width: 0;
+          height: 0;
+          border-left: 8px solid transparent;
+          border-right: 8px solid transparent;
+          border-top: 8px solid #fff;
+        }
+      }
+      .user_handle {
+        z-index: 999;
+        padding: 10px 40px;
+        position: absolute;
+        right: 0;
+        bottom: -90px;
+        background-color: #1482b4;
+        li {
+          color: #fff;
+          cursor: pointer;
+          margin: 10px 0;
+        }
+        li:hover {
+          color: #dc3545;
+        }
+      }
+    }
+  }
+  .con {
+    display: flex;
+    width: 100%;
+    padding: 30px 30px 0;
+    height: calc(100vh - 100px);
+  }
+  .left {
+    min-width: 220px;
+    width: 220px;
+    height: 100%;
+    background-color: #fff;
+    padding-top: 15px;
+    .biaoji {
+      height: 40px;
+      background-color: #1482b4;
+      width: 90%;
+      border-radius: 0 40px 40px 0;
+      color: #fff;
+      font-weight: 700;
+      font-size: 20px;
+      line-height: 40px;
+      padding-left: 50px;
+    }
+    ul {
+      li {
+        cursor: pointer;
+        padding-left: 50px;
+        margin: 40px 0;
+        &:hover {
+          color: #1482b4;
+        }
+      }
+      .active {
+        color: #1482b4;
+      }
+    }
+  }
+  .right {
+    padding: 20px;
+    min-width: 1500px;
+    flex: 1;
+    margin-left: 30px;
+    background-color: #fff;
+    height: 100%;
+  }
+}
+</style>

+ 145 - 0
src/views/login.vue

@@ -0,0 +1,145 @@
+<!--  -->
+<template>
+<div class='login'>
+  <div class="top">
+    <img src="../assets/img/logo.png" alt="">
+    <p>石壁龙智慧园区</p>
+  </div>
+  <div class="con">
+    <div class="left">
+      <p>石壁龙智慧园区</p>
+      <p>管理后台</p>
+    </div>
+    <div class="right">
+      <p>欢迎登录</p>
+      <div class="row">
+        <el-input v-model="from.userName" placeholder="账号"></el-input>
+      </div>
+      <div class="row">
+        <el-input v-model="from.passWord" placeholder="密码" show-password></el-input>
+      </div>
+      <div class="btn" @click="login">登 陆</div>
+    </div>
+  </div>
+</div>
+</template>
+
+<script>
+import { userLogin } from '@/apis/login'
+export default {
+  name: 'login',
+  components: {},
+  data () {
+    // 这里存放数据
+    return {
+      from: {
+        userName: '',
+        passWord: ''
+      }
+    }
+  },
+  // 监听属性 类似于data概念
+  computed: {},
+  // 监控data中的数据变化
+  watch: {},
+  // 方法集合
+  methods: {
+    async login () {
+      if (this.from.userName.trim() === '') return this.$message.warning('账号不能为空!')
+      if (this.from.passWord.trim() === '') return this.$message.warning('密码不能为空!')
+      const res = await userLogin(this.from)
+      if (res.code === 0) {
+        localStorage.setItem('SZSBL_token', res.data.token)
+        localStorage.setItem('SZSBL_userName', res.data.user.userName)
+        this.$router.push('/layout/tab1')
+        this.$message.success('登录成功')
+      } else this.$message.warning(res.msg)
+    }
+  },
+  // 生命周期 - 创建完成(可以访问当前this实例)
+  created () {
+
+  },
+  // 生命周期 - 挂载完成(可以访问DOM元素)
+  mounted () {
+
+  },
+  beforeCreate () {}, // 生命周期 - 创建之前
+  beforeMount () {}, // 生命周期 - 挂载之前
+  beforeUpdate () {}, // 生命周期 - 更新之前
+  updated () {}, // 生命周期 - 更新之后
+  beforeDestroy () {}, // 生命周期 - 销毁之前
+  destroyed () {}, // 生命周期 - 销毁完成
+  activated () {} // 如果页面有keep-alive缓存功能,这个函数会触发
+}
+</script>
+<style lang='less' scoped>
+.login{
+  .top{
+    box-shadow: 1px 3px 3px 3px rgb(196, 177, 177);
+    height: 70px;
+    background-color: #1482b4;
+    display: flex;
+    align-items: center;
+    &>img {
+      width: 35px;
+      height: 35px;
+      border-radius: 50%;
+      overflow: hidden;
+      margin: 0 30px;
+    }
+    &>P {
+      color: #fff;
+      font-size: 24px;
+      font-weight: 700;
+    }
+  }
+  .con{
+    display: flex;
+    margin: 180px auto 0;
+    width: 700px;
+    height: 500px;
+    border: 1px solid #ccc;
+    .left{
+      display: flex;
+      flex-direction: column;
+      justify-content: center;
+      width: 350px;
+      height: 100%;
+      background-color: #1482b4;
+      &>p{
+        margin-bottom: 30px;
+        color: #fff;
+        font-weight: 700;
+        text-align: center;
+        font-size: 30px;
+      }
+    }
+    .right{
+      width: 350px;
+      &>p {
+        font-size: 24px;
+        text-align: center;
+        margin-top: 100px;
+      }
+      .row{
+        width: 90%;
+        margin: 50px auto;
+      }
+      .btn {
+        cursor: pointer;
+        width: 90%;
+        height: 40px;
+        line-height: 40px;
+        text-align: center;
+        margin: 50px auto 0;
+        background-color: #1482b4;
+        border-radius: 8px;
+        color: #fff;
+
+      }
+    }
+  }
+}
+
+</style>

+ 256 - 0
src/views/tab1/edit.vue

@@ -0,0 +1,256 @@
+<!--  -->
+<template>
+  <div class="tab1Edit">
+    <div class="top">
+      {{ ruleForm.id === "1" ? "园区概况" : "各楼宇人数统计" }}
+    </div>
+    <div class="from">
+      <el-form
+        :model="ruleForm"
+        :rules="rules"
+        ref="ruleForm"
+        label-width="130px"
+        class="demo-ruleForm"
+      >
+        <el-form-item label="综合大楼:" prop="complexBuilding">
+          <el-input
+            v-model.number="ruleForm.complexBuilding"
+            type="number"
+          ></el-input>
+          <span class="unit" v-if="ruleForm.id === '1'">m<sup>2</sup></span>
+          <span class="unit2" v-else>人</span>
+        </el-form-item>
+        <el-form-item label="学术交流中心:" prop="exchangeCentre">
+          <el-input
+            v-model.number="ruleForm.exchangeCentre"
+            type="number"
+          ></el-input>
+          <span class="unit" v-if="ruleForm.id === '1'">m<sup>2</sup></span>
+          <span class="unit2" v-else>人</span>
+        </el-form-item>
+        <el-form-item label="公寓楼:" prop="apartment">
+          <el-input
+            v-model.number="ruleForm.apartment"
+            type="number"
+          ></el-input>
+          <span class="unit" v-if="ruleForm.id === '1'">m<sup>2</sup></span>
+          <span class="unit2" v-else>人</span>
+        </el-form-item>
+        <el-form-item label="综合服务中心:" prop="serviceCentre">
+          <el-input
+            v-model.number="ruleForm.serviceCentre"
+            type="number"
+          ></el-input>
+          <span class="unit" v-if="ruleForm.id === '1'">m<sup>2</sup></span>
+          <span class="unit2" v-else>人</span>
+        </el-form-item>
+        <el-form-item label="科研楼:" prop="scientificBuilding">
+          <el-input
+            v-model.number="ruleForm.scientificBuilding"
+            type="number"
+          ></el-input>
+          <span class="unit" v-if="ruleForm.id === '1'">m<sup>2</sup></span>
+          <span class="unit2" v-else>人</span>
+        </el-form-item>
+        <el-form-item label="更新时间:">
+          <el-date-picker
+            v-model="time"
+            type="datetime"
+            placeholder="选择日期时间"
+            align="right"
+            :picker-options="pickerOptions"
+          >
+          </el-date-picker>
+        </el-form-item>
+      </el-form>
+    </div>
+    <!-- 下面的按钮 -->
+    <div class="btn">
+      <el-button @click="$router.push('/layout/tab1')">返 回</el-button>
+      <el-button type="primary" @click="btnOk">提 交</el-button>
+    </div>
+  </div>
+</template>
+
+<script>
+import { parkSave } from '@/apis/tab1'
+export default {
+  name: 'tab1Edit',
+  components: {},
+  data () {
+    // 这里存放数据
+    const validatePass = (rule, value, callback) => {
+      if (value > 99999999.99) {
+        callback(new Error('不能超过99999999.99'))
+      } else {
+        callback()
+      }
+    }
+    return {
+      pickerOptions: {
+        shortcuts: [
+          {
+            text: '今天',
+            onClick (picker) {
+              picker.$emit('pick', new Date())
+            }
+          },
+          {
+            text: '昨天',
+            onClick (picker) {
+              const date = new Date()
+              date.setTime(date.getTime() - 3600 * 1000 * 24)
+              picker.$emit('pick', date)
+            }
+          },
+          {
+            text: '一周前',
+            onClick (picker) {
+              const date = new Date()
+              date.setTime(date.getTime() - 3600 * 1000 * 24 * 7)
+              picker.$emit('pick', date)
+            }
+          }
+        ]
+      },
+      disTime: '',
+      time: '',
+      ruleForm: {
+        complexBuilding: '', // 综合大楼
+        exchangeCentre: '', // 学术交流中心
+        apartment: '', // 公寓楼
+        serviceCentre: '', // 综合服务中心
+        scientificBuilding: '' // 科研楼
+      },
+      rules: {
+        complexBuilding: [
+          { required: true, message: '不能为空', trigger: 'blur' },
+          { validator: validatePass, trigger: 'blur' }
+        ],
+        exchangeCentre: [
+          { required: true, message: '不能为空', trigger: 'blur' },
+          { validator: validatePass, trigger: 'blur' }
+        ],
+        apartment: [
+          { required: true, message: '不能为空', trigger: 'blur' },
+          { validator: validatePass, trigger: 'blur' }
+        ],
+        serviceCentre: [
+          { required: true, message: '不能为空', trigger: 'blur' },
+          { validator: validatePass, trigger: 'blur' }
+        ],
+        scientificBuilding: [
+          { required: true, message: '不能为空', trigger: 'blur' },
+          { validator: validatePass, trigger: 'blur' }
+        ]
+      }
+    }
+  },
+  // 监听属性 类似于data概念
+  computed: {},
+  // 监控data中的数据变化
+  watch: {
+    time (val) {
+      const temp = this.moment(val).format('YYYY-MM-DD HH:mm:ss')
+      this.disTime = temp
+    }
+  },
+  // 方法集合
+  methods: {
+    // 点击提交
+    async btnOk () {
+      if (this.time === null) return this.$message.warning('时间不能为空!')
+      try {
+        await this.$refs.ruleForm.validate()
+        const obj = {}
+        if (this.ruleForm.id === '1') {
+          obj.type = 'park'
+        } else if (this.ruleForm.id === '2') {
+          obj.type = 'building'
+        }
+        obj.id = Number(this.ruleForm.id)
+        obj.data = JSON.stringify(this.ruleForm)
+        obj.userUpdateTime = this.disTime
+        const res = await parkSave(obj)
+        if (res.code === 0) {
+          this.$message.success('修改成功')
+          this.$router.push('/layout/tab1')
+        }
+        // console.log(999, res)
+        // console.log(777777777777, obj)
+      } catch (error) {
+        console.log(error)
+      }
+    },
+    getCurrentTime () {
+      // 获取当前时间并打印
+      var _this = this
+      const yy = new Date().getFullYear()
+      const mm = new Date().getMonth() + 1
+      const dd = new Date().getDate()
+      const hh = new Date().getHours()
+      const mf =
+        new Date().getMinutes() < 10
+          ? '0' + new Date().getMinutes()
+          : new Date().getMinutes()
+      const ss =
+        new Date().getSeconds() < 10
+          ? '0' + new Date().getSeconds()
+          : new Date().getSeconds()
+      _this.gettime = yy + '/' + mm + '/' + dd + ' ' + hh + ':' + mf + ':' + ss
+      this.time = _this.gettime
+      // console.log(_this.gettime)
+    }
+  },
+  // 生命周期 - 创建完成(可以访问当前this实例)
+  async created () {
+    this.ruleForm = this.$route.query
+    this.getCurrentTime()
+    // console.log(999, this.$route.query)
+  },
+  // 生命周期 - 挂载完成(可以访问DOM元素)
+  mounted () {},
+  beforeCreate () {}, // 生命周期 - 创建之前
+  beforeMount () {}, // 生命周期 - 挂载之前
+  beforeUpdate () {}, // 生命周期 - 更新之前
+  updated () {}, // 生命周期 - 更新之后
+  beforeDestroy () {}, // 生命周期 - 销毁之前
+  destroyed () {}, // 生命周期 - 销毁完成
+  activated () {} // 如果页面有keep-alive缓存功能,这个函数会触发
+}
+</script>
+<style lang='less' scoped>
+.tab1Edit {
+  height: 100%;
+  position: relative;
+  .top {
+    height: 40px;
+    line-height: 40px;
+    background-color: #fbfbfb;
+    padding-left: 20px;
+  }
+  .from {
+    margin-top: 30px;
+    width: 50%;
+    .unit {
+      position: absolute;
+      right: -40px;
+      top: -5px;
+    }
+    .unit2 {
+      position: absolute;
+      right: -40px;
+      top: 0;
+    }
+  }
+  .btn {
+    display: flex;
+    justify-content: space-between;
+    width: 200px;
+    position: absolute;
+    left: 50%;
+    bottom: 30px;
+    transform: translateX(-50%);
+  }
+}
+</style>

+ 100 - 0
src/views/tab1/index.vue

@@ -0,0 +1,100 @@
+<template>
+  <div class="tab1">
+    <!-- <div class="search">
+      <span>栏目类型:</span>
+      <el-input
+        v-model="from.searchKey"
+        placeholder="请输入"
+        style="width: 300px"
+      ></el-input>
+      <el-button type="primary" style="margin-left: 40px">搜 索</el-button>
+    </div> -->
+    <!-- 表格 -->
+    <div class="table">
+      <el-table :data="tableData" border style="width: 100%">
+        <el-table-column prop="id" label="序列" width="80"></el-table-column>
+        <el-table-column prop="type" label="栏目类型" width="240"></el-table-column>
+        <el-table-column prop="const" label="数据字段"></el-table-column>
+        <el-table-column prop="time" label="更新时间" width="200"> </el-table-column>
+        <el-table-column  label="操作" width="120">
+          <template #default='{row}'>
+              <el-button type="text" @click="edit(row.data,row.id)">修 改</el-button>
+          </template>
+        </el-table-column>
+      </el-table>
+    </div>
+  </div>
+</template>
+
+<script>
+import { parkList } from '@/apis/tab1'
+export default {
+  name: 'tab1',
+  components: {},
+  data () {
+    // 这里存放数据
+    return {
+      from: {
+        pageNum: 1,
+        pageSize: 9999,
+        searchKey: '',
+        type: ''
+      },
+      tableData: []
+    }
+  },
+  // 监听属性 类似于data概念
+  computed: {},
+  // 监控data中的数据变化
+  watch: {},
+  // 方法集合
+  methods: {
+    // 点击修改
+    edit (val, id) {
+      // console.log(999, id)
+      this.$router.push({
+        path: '/layout/tab1Edit',
+        query: { ...val, id }
+      })
+    },
+    // 封装获取列表方法
+    async parkList (data) {
+      const res = await parkList(data)
+      const temp1 = JSON.parse(res.data[0].data)
+      const temp2 = JSON.parse(res.data[1].data)
+      // console.log(999, temp1)
+      this.tableData.push({
+        id: 1, type: '园区概况', const: `综合大楼:${temp1.complexBuilding};学术交流中心:${temp1.exchangeCentre};公寓楼:${temp1.apartment};综合服务中心:${temp1.serviceCentre};科研楼:${temp1.scientificBuilding}`, time: res.data[0].userUpdateTime, data: temp1
+      })
+      this.tableData.push({
+        id: 2, type: '各楼宇人数统计', const: `综合大楼:${temp2.complexBuilding};学术交流中心:${temp2.exchangeCentre};公寓楼:${temp2.apartment};综合服务中心:${temp2.serviceCentre};科研楼:${temp2.scientificBuilding}`, time: res.data[1].userUpdateTime, data: temp2
+      })
+      // console.log(999, JSON.parse(res.data[0].data))
+    }
+  },
+  // 生命周期 - 创建完成(可以访问当前this实例)
+  created () {
+    this.parkList(this.from)
+  },
+  // 生命周期 - 挂载完成(可以访问DOM元素)
+  mounted () {},
+  beforeCreate () {}, // 生命周期 - 创建之前
+  beforeMount () {}, // 生命周期 - 挂载之前
+  beforeUpdate () {}, // 生命周期 - 更新之前
+  updated () {}, // 生命周期 - 更新之后
+  beforeDestroy () {}, // 生命周期 - 销毁之前
+  destroyed () {}, // 生命周期 - 销毁完成
+  activated () {} // 如果页面有keep-alive缓存功能,这个函数会触发
+}
+</script>
+<style lang='less' scoped>
+.tab1 {
+  .search {
+    height: 40px;
+    align-items: center;
+    display: flex;
+  }
+  .table{
+  }
+}
+</style>

+ 46 - 0
src/views/tab2/index.vue

@@ -0,0 +1,46 @@
+<template>
+<div class='tab2'>tab2</div>
+</template>
+
+<script>
+// 这里可以导入其他文件(比如:组件,工具js,第三方插件js,json文件,图片文件等等)
+// 例如:import 《组件名称》 from '《组件路径》';
+
+export default {
+  name: 'tab2',
+  components: {},
+  data () {
+    // 这里存放数据
+    return {
+
+    }
+  },
+  // 监听属性 类似于data概念
+  computed: {},
+  // 监控data中的数据变化
+  watch: {},
+  // 方法集合
+  methods: {
+
+  },
+  // 生命周期 - 创建完成(可以访问当前this实例)
+  created () {
+
+  },
+  // 生命周期 - 挂载完成(可以访问DOM元素)
+  mounted () {
+
+  },
+  beforeCreate () {}, // 生命周期 - 创建之前
+  beforeMount () {}, // 生命周期 - 挂载之前
+  beforeUpdate () {}, // 生命周期 - 更新之前
+  updated () {}, // 生命周期 - 更新之后
+  beforeDestroy () {}, // 生命周期 - 销毁之前
+  destroyed () {}, // 生命周期 - 销毁完成
+  activated () {} // 如果页面有keep-alive缓存功能,这个函数会触发
+}
+</script>
+<style lang='less' scoped>
+//@import url(); 引入公共css类
+
+</style>

+ 3 - 0
vue.config.js

@@ -0,0 +1,3 @@
+module.exports = {
+  publicPath: './'
+}