Pārlūkot izejas kodu

第一次提交

yf_yx 3 gadi atpakaļ
vecāks
revīzija
f120863dfa

+ 3 - 0
test/.browserslistrc

@@ -0,0 +1,3 @@
+> 1%
+last 2 versions
+not dead

+ 5 - 0
test/.editorconfig

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

+ 17 - 0
test/.eslintrc.js

@@ -0,0 +1,17 @@
+module.exports = {
+  root: true,
+  env: {
+    node: true
+  },
+  extends: [
+    'plugin:vue/essential',
+    '@vue/standard'
+  ],
+  parserOptions: {
+    parser: '@babel/eslint-parser'
+  },
+  rules: {
+    'no-console': process.env.NODE_ENV === 'production' ? 'warn' : 'off',
+    'no-debugger': process.env.NODE_ENV === 'production' ? 'warn' : 'off'
+  }
+}

+ 23 - 0
test/.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
test/README.md

@@ -0,0 +1,24 @@
+# test
+
+## 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
test/babel.config.js

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

+ 19 - 0
test/jsconfig.json

@@ -0,0 +1,19 @@
+{
+  "compilerOptions": {
+    "target": "es5",
+    "module": "esnext",
+    "baseUrl": "./",
+    "moduleResolution": "node",
+    "paths": {
+      "@/*": [
+        "src/*"
+      ]
+    },
+    "lib": [
+      "esnext",
+      "dom",
+      "dom.iterable",
+      "scripthost"
+    ]
+  }
+}

Failā izmaiņas netiks attēlotas, jo tās ir par lielu
+ 21647 - 0
test/package-lock.json


+ 38 - 0
test/package.json

@@ -0,0 +1,38 @@
+{
+  "name": "test",
+  "version": "0.1.0",
+  "private": true,
+  "scripts": {
+    "serve": "vue-cli-service serve",
+    "build": "vue-cli-service build",
+    "lint": "vue-cli-service lint"
+  },
+  "dependencies": {
+    "axios": "^0.26.1",
+    "core-js": "^3.8.3",
+    "echarts": "^5.3.1",
+    "element-ui": "^2.15.6",
+    "js-cookie": "^3.0.1",
+    "normalize.css": "^8.0.1",
+    "qs": "^6.10.3",
+    "vue": "^2.6.14",
+    "vue-router": "^3.5.1"
+  },
+  "devDependencies": {
+    "@babel/core": "^7.12.16",
+    "@babel/eslint-parser": "^7.12.16",
+    "@vue/cli-plugin-babel": "~5.0.0",
+    "@vue/cli-plugin-eslint": "~5.0.0",
+    "@vue/cli-plugin-router": "~5.0.0",
+    "@vue/cli-service": "~5.0.0",
+    "@vue/eslint-config-standard": "^6.1.0",
+    "eslint": "^7.32.0",
+    "eslint-plugin-import": "^2.25.3",
+    "eslint-plugin-node": "^11.1.0",
+    "eslint-plugin-promise": "^5.1.0",
+    "eslint-plugin-vue": "^8.0.3",
+    "less": "^4.0.0",
+    "less-loader": "^8.0.0",
+    "vue-template-compiler": "^2.6.14"
+  }
+}

BIN
test/public/favicon.ico


+ 17 - 0
test/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><%= htmlWebpackPlugin.options.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>

+ 24 - 0
test/src/App.vue

@@ -0,0 +1,24 @@
+<template>
+    <div id="app">
+        <!-- 路由的出口 -->
+
+        <router-view></router-view>
+    </div>
+</template>
+
+<script>
+// import LayOut from './views/layout/LayOut.vue'
+export default {
+
+  // components:{
+  //     LayOut
+  // }
+}
+</script>
+
+<style scoped>
+    body,html {
+        margin: 0;
+        padding: 0;
+    }
+</style>

BIN
test/src/assets/OIP-C.jpg


BIN
test/src/assets/ban-Selected.png


BIN
test/src/assets/ban.png


BIN
test/src/assets/headPortrait.png


BIN
test/src/assets/home.png


BIN
test/src/assets/logo.png


BIN
test/src/assets/system-Selected.png


BIN
test/src/assets/system.png


+ 47 - 0
test/src/main.js

@@ -0,0 +1,47 @@
+// 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'
+
+// Vue.use(ElementUI);
+
+// Vue.config.productionTip = false
+
+// new Vue({
+//   router,
+//   render: h => h(App)
+// }).$mount('#app')
+import Vue from 'vue'
+import App from './App.vue'
+import router from './router'
+import ElementUI, { MessageBox, Message } from 'element-ui'
+import 'element-ui/lib/theme-chalk/index.css'
+
+import 'normalize.css/normalize.css'
+
+import http from './utils/axiosQuest'
+
+// 按需引入echarts
+import * as echarts from 'echarts/core'
+import { TooltipComponent } from 'echarts/components'
+import { GaugeChart } from 'echarts/charts'
+import { CanvasRenderer } from 'echarts/renderers'
+// import 'default-passive-events';//谷歌流畅运行
+
+Vue.use(ElementUI)
+
+echarts.use([TooltipComponent, GaugeChart, CanvasRenderer])
+Vue.prototype.$echarts = echarts
+Vue.prototype.$confirm = MessageBox.confirm
+Vue.prototype.$message = Message
+Vue.prototype.$axios = http
+
+Vue.config.productionTip = false
+
+new Vue({
+  router,
+  render: h => h(App)
+}).$mount('#app')

+ 84 - 0
test/src/router/index.js

@@ -0,0 +1,84 @@
+// import Vue from 'vue'
+// import VueRouter from 'vue-router'
+
+// Vue.use(VueRouter)
+
+// const routes = [
+
+// ]
+
+// const router = new VueRouter({
+//   routes
+// })
+
+// export default router
+
+import Vue from 'vue'
+import VueRouter from 'vue-router'
+// import islogin from "../utils/islogin"
+import LayOut from '../views/layout/LayOut.vue'
+import home from '../views/home/index.vue'
+import BanMange from '../views/banMange/index.vue'
+Vue.use(VueRouter)
+
+const routes = [
+  { path: '/', name: 'login', component: () => import('../views/login/index.vue') },
+  { path: '/login', name: 'Login', component: () => import('../views/login/index.vue') },
+  {
+    path: '/LayOut',
+    component: LayOut,
+    // redirect:'/home',
+    children: [
+      {
+        path: '/',
+        component: home
+      },
+      {
+        path: 'home',
+        component: home
+      },
+      {
+        path: 'banmange',
+        component: BanMange
+      }
+    ]
+  }
+]
+
+const router = new VueRouter({
+  routes
+})
+// router.beforeEach((to, from, next) => {
+//   // if (to.path === '/pagelogin') return next();
+//   // //获取token
+//   // const tokenStr = window.sessionStorage.getItem('token')
+//   // if (!tokenStr) return next('/pagelogin')
+//   // next()
+//   islogin(to.path, next);
+// })
+
+// 解决vue-router重复点击报错  push方法
+const originalPush = VueRouter.prototype.push
+VueRouter.prototype.push = function push (location) {
+  return originalPush.call(this, location).catch(err => err)
+}
+
+// replace方法
+const originalrePlace = VueRouter.prototype.replace
+VueRouter.prototype.replace = function replace (location) {
+  return originalrePlace.call(this, location).catch(err => err)
+}
+
+// 全局路由守卫
+router.beforeEach((to, form, next) => {
+  if (to.path === '/login') {
+    return next()
+  }
+  const token = window.sessionStorage.getItem('token') // 获取token
+  if (!token) {
+    return next('/login') // 在原地不动
+  }
+  next() // 继续走
+})
+
+export default router

+ 42 - 0
test/src/utils/axiosQuest.js

@@ -0,0 +1,42 @@
+import axios from 'axios'
+import qs from 'qs'
+
+function axiosRQ (url, method, data) {
+  return new Promise((resolve, reject) => {
+    if (method === 'GET') { // 这边GET是大写 传的时候要大写
+      axios.get(url, data).then((response) => {
+        // response 该参数返回的是一个相应对象
+        resolve(response.data)
+      }).catch((error) => {
+        reject(`${url} GET 请求失败:${error.response.data}`)
+      })
+    } else if (method === 'POST') { // 这边GET是大写 传的时候要大写
+      axios.post(url, qs.stringify(data)).then((response) => {
+        // response 该参数返回的是一个相应对象
+        resolve(response.data)
+      }).catch((error) => {
+        // reject(`${url} POST 请求失败:${error.response.data}`)
+        this.$message.error({
+          message: error.response.data.msg
+        })
+        // console.log(error.response);
+      })
+    } else {
+      // 如果是PUT请求或者DELETE请求,使用axios()通用请求 通用请求 自己写一般用这个
+      axios({
+        url,
+        method,
+        // 要么用data要么用params 不可能两个都写上 因为这个项目用get 上面有了 不会走到这一步
+        data: data// 如果是PUT或者POST,携带参数使用data这个属性;
+        // params: data,//如果是GET或DELETE,携带参数使用params这个属性;params参数会被放在URL后面用?拼接
+      }).then((response) => {
+        resolve(response.data)
+      }).catch((error) => {
+        reject(error.response.data)
+      })
+    }
+  })
+}
+
+// 将请求方法暴露出去,其他文件只需要import from 这个js文件,就可以得到这个请求函数
+export default axiosRQ

+ 29 - 0
test/src/utils/islogin.js

@@ -0,0 +1,29 @@
+// 验证函数 判断有没有登录
+
+export default function islogin (to, next, target) {
+  // const token = localStorage.getItem("token");
+  // if (token) {
+  //     //已登录
+  //     next();
+  // } else {
+  //     //未登录
+  //     next({
+  //         path: "/pagelogin",
+  //         query: { redirect_url: target },
+  //     })
+  // }
+
+  if (to === '/login') return next()
+  // 获取token
+  const tokenStr = window.sessionStorage.getItem('token')
+  if (!tokenStr) {
+    return next({
+      path: '/login',
+      query: { redirect_url: to }
+    })
+  }
+  // if(!tokenStr) {
+  //     return next('/login')
+  // }
+  next()
+}

+ 289 - 0
test/src/views/banMange/index.vue

@@ -0,0 +1,289 @@
+<template>
+  <div>
+    <div class="right-top">
+      <img src="../../assets/home.png" alt="" />
+      <span>解封/</span>
+      <span class="info">解封</span>
+    </div>
+
+    <el-card>
+      <div class="right-bottom-inp">
+
+        <div class="inp">
+          <label for="inp2" style="background-color: #dcdfe6">编号</label>
+          <el-input
+            size="mini"
+            suffix-icon="el-icon-search"
+            type="text"
+            id="inp2"
+            placeholder="请输入设备编号"
+            v-model="inp2"
+            autocomplete="off"
+          >
+          </el-input>
+        </div>
+
+        <div class="btn">
+          <el-button size="mini" @click="handleReset">重置</el-button>
+          <el-button size="mini" type="primary"  @click="handleSearchs">查询</el-button>
+        </div>
+
+      </div>
+
+      <!-- 表格部分 -->
+      <!-- 内容区域 -->
+      <div class="table-container">
+        <el-table ref="multipleTable" :data="list" style="width: 100%">
+          <el-table-column label="序号" width="100" align="center">
+            <template slot-scope="scope">
+              {{ scope.$index + 1 + (page - 1) * page_size }}
+            </template>
+          </el-table-column>
+
+          <el-table-column label="设备名称" width="100" align="center">
+            <template slot-scope="scope">{{ scope.row.device_name }}</template>
+          </el-table-column>
+
+          <el-table-column label="设备编号" width="200" align="center">
+            <template slot-scope="scope">{{ scope.row.device_id }}</template>
+          </el-table-column>
+
+          <el-table-column label="拍照数量" width="100" align="center">
+            <template slot-scope="scope">{{ scope.row.photo_num }}</template>
+          </el-table-column>
+
+          <el-table-column label="描述信息" width="800" align="center">
+            <template slot-scope="scope">{{ scope.row.msg_info }}</template>
+          </el-table-column>
+
+          <el-table-column label="封禁时间" width="200" align="center">
+            <template slot-scope="scope">{{ scope.row.create_time }}</template>
+          </el-table-column>
+
+          <el-table-column label="操作" width="150" align="center">
+            <template slot-scope="scope">
+              <el-button
+                size="mini"
+                type="success"
+                @click="handleBan(scope.$index, scope.row)"
+                >解封</el-button
+              >
+            </template>
+          </el-table-column>
+        </el-table>
+      </div>
+
+      <!-- 分页区域 -->
+      <div class="pagination-container">
+        <el-pagination
+          background
+          @current-change="handleCurrentChange"
+          :page-size="page_size"
+          :current-page="page"
+          layout="prev, pager, next,jumper"
+          :total="total"
+        >
+        </el-pagination>
+      </div>
+    </el-card>
+  </div>
+</template>
+
+<script>
+
+export default {
+  name: 'BanManage',
+  data () {
+    return {
+      // listQuery: Object.assign({}, defaultListQuery),
+      inp1: '',
+      inp2: '',
+      list: [], // 表格的数据源
+      page: 1, // 当前是第几页
+      page_size: 10, // 每页显示多少条数据
+      total: null, // 数据总条数,
+      device_name: '', // 设备名称
+      device_id: '', // 设备id
+      photo_num: '', // 拍照数量
+      msg_info: '', // 描述信息
+      create_time: ''// 封禁时间
+    }
+  },
+  created () {},
+  mounted () {
+    this.getList()
+  },
+  methods: {
+    async getList () {
+      const response = await this.$axios(`/api/photo/?page=${this.page}&size=10`, 'GET')
+      // console.log(response);
+      if (response.code === 0) {
+        this.page_size = 10
+        this.list = response.result.data
+        this.total = response.result.paging.total
+      }
+    },
+    // 解封操作
+    handleBan (index, row) {
+      this.$confirm(`确定解封 ${row.device_id} 吗?`, '提示', {
+        confirmButtonText: '确定',
+        cancelButtonText: '取消',
+        type: 'error'
+      })
+        .then(() => {
+          // 点击确定的操作(调用接口)
+          this.$axios('/api/photo/', 'POST', {
+            device_id: row.device_id
+          }).then((data) => {
+            // console.log(data);
+            this.$message({
+              type: 'success',
+              message: '已解封'
+            })
+            // 解封之后在刷新页面
+            this.getList()
+          })
+        })
+        .catch(() => {
+          // 点取消的提示
+          this.$message({
+            type: 'success',
+            message: '已取消解封'
+          })
+        })
+    },
+    handleSearchs () {
+      this.page = 1
+      this.handleSearch()
+    },
+    // 查询
+    handleSearch () {
+      // this.page = 1
+
+      this.$axios(`/api/photo/?device_id=${this.inp2}&page=${this.page}&size=10`, 'GET').then((res) => {
+        console.log(res)
+        this.list = []
+        this.list = res.result.data
+        this.total = res.result.paging.total
+        console.log(this.inp2)
+        this.device_id = this.inp2
+        this.inp2 = this.device_id
+        console.log(this.device_id)
+      }).catch((err) => {
+        console.log(err)
+      })
+    },
+    // 重置
+    handleReset () {
+      this.inp2 = ''
+      this.getList()
+    },
+
+    handleCurrentChange (val) {
+    // 当前页改变的时候触发
+      console.log(this.inp2)
+
+      this.inp2 = this.inp2.trim()
+      if (this.inp2 === '') {
+        this.page = val
+        console.log('getlist')
+        this.getList()
+      } else {
+        console.log('search')
+        console.log(this.device_id)
+        this.inp2 = this.device_id
+        this.page = val
+        this.handleSearch()
+      }
+    }
+
+  }
+
+}
+</script>
+
+<style scoped lang="less">
+.right-top {
+  // width: 100%;
+  // width: calc(100vw - 146px);
+  background-color: rgb(240, 242, 245);
+
+  min-width: 1185px;
+  height: 50px;
+  display: flex;
+  align-items: center;
+  font-size: 16px;
+  color: #1a2a35;
+  > img {
+    margin-left: 12px;
+    margin-right: 12px;
+  }
+  .info {
+    color: #3eb984;
+  }
+}
+
+.right-bottom-inp {
+  display: flex;
+
+  .inp:nth-child(2) {
+    margin-left: 6px;
+  }
+  .inp {
+    width: 260px;
+    height: 28px;
+    font-size: 13px;
+    border-radius: 3px;
+    font-weight: 500;
+    color: #909399;
+    display: flex;
+    align-items: center;
+    margin-left: 22px;
+    label {
+      display: inline-block;
+      box-sizing: border-box;
+      width: 88px;
+      height: 28px;
+      line-height: 28px;
+      text-align: center;
+      border: 1px solid #dcdfe6;
+      border-radius: 3px 0px 0px 3px;
+      border-right: none;
+    }
+
+  }
+}
+
+.el-pagination {
+  text-align: center;
+  margin-top: 20px;
+}
+::v-deep {
+  .el-pagination.is-background .el-pager li:not(.disabled).active {
+    background-color: green;
+    color: #fff;
+  }
+  .el-input__inner {
+    border-radius: 0px !important;
+  }
+}
+
+.el-card {
+  // border: 1px solid red;
+  // height: 800px;
+  width: 93vw;
+  margin: 0 auto;
+
+}
+
+.table-container {
+  // border: 1px solid red;
+  height:680px;
+}
+
+.btn {
+  // border: 1px solid red;
+  margin-left: 10px;
+}
+
+</style>

Failā izmaiņas netiks attēlotas, jo tās ir par lielu
+ 1002 - 0
test/src/views/home/index.vue


+ 48 - 0
test/src/views/layout/LayOut.vue

@@ -0,0 +1,48 @@
+<template>
+  <!-- 整个页面的布局结构 -->
+
+<div>
+    <!-- 头部区域 -->
+    <NavBar></NavBar>
+
+    <!-- 主体部分 -->
+    <el-container>
+      <!-- 左侧内容 -->
+      <LeftAside></LeftAside>
+      <!-- 右侧 -->
+      <AppMain></AppMain>
+    </el-container>
+</div>
+</template>
+
+<script>
+import NavBar from '../layout/components/NavBar.vue'
+import LeftAside from '../layout/components/LeftAside.vue'
+import AppMain from '../layout/components/AppMain.vue'
+export default {
+  name: 'LayOut',
+  // 需要渲染的组件
+  components: {
+    NavBar,
+    LeftAside,
+    AppMain
+  },
+  data () {
+    return {}
+  },
+  methods: {}
+}
+</script>
+<style >
+
+/* .el-aside {
+  background-color: #d3dce6;
+  color: #333;
+  text-align: center;
+  line-height: 200px;
+} */
+
+  body > .el-container {
+    margin-bottom: 40px;
+  }
+</style>

+ 23 - 0
test/src/views/layout/components/AppMain.vue

@@ -0,0 +1,23 @@
+<template>
+  <!-- 右侧内容 -->
+  <el-main>
+    <!-- 路由的出口 -->
+    <router-view></router-view>
+  </el-main>
+</template>
+
+<script>
+export default {
+  name: 'AppMain',
+  methods: {}
+}
+</script>
+
+<style scoped>
+.el-main {
+  /* border: 1px solid red; */
+  width: calc(100vw - 106px);
+  height: calc(100vh - 60px);
+  padding: 0;
+}
+</style>

+ 93 - 0
test/src/views/layout/components/LeftAside.vue

@@ -0,0 +1,93 @@
+<template>
+  <el-aside class="page-home-content">
+    <div class="left">
+
+      <router-link   to="/LayOut" active-class="change" exact>
+          <div class="system-info">
+            <!-- <img src="../../../assets/system-Selected.png" alt="" /> -->
+            <img :src="aside[0].path === $route.path ? aside[0].selected : aside[0].normal" alt="" />
+
+            <span >系统信息</span>
+          </div>
+      </router-link>
+
+      <router-link style="margin-top:35px"   to="/LayOut/banmange"  active-class="change" exact>
+        <div class="system-info"  >
+          <!-- <img src="../../../assets/ban-Selected.png" alt="" /> -->
+            <img :src="aside[1].path === $route.path ? aside[1].selected : aside[1].normal" alt="" />
+          <span >四情封禁</span>
+        </div>
+      </router-link>
+    </div>
+  </el-aside>
+</template>
+
+<script>
+export default {
+  name: 'LeftAside',
+  data () {
+    return {
+      aside: [
+        { path: '/LayOut', normal: require('../../../assets/system.png'), selected: require('../../../assets/system-Selected.png') },
+        { path: '/LayOut/banmange', normal: require('../../../assets/ban.png'), selected: require('../../../assets/ban-Selected.png') }
+      ]
+
+    }
+  }
+
+}
+</script>
+
+<style scoped lang="less">
+
+a{
+  text-decoration: none;
+  color: #6A7A88 ;
+}
+
+.change {
+  color: white;
+}
+
+.el-aside {
+  // border: 1px solid red;
+  width: 106px !important ;
+}
+
+.page-home-content {
+    background-color: rgb(240, 242, 245);
+    box-sizing: border-box;
+    // height: 875px;
+    height: calc(98vh - 60px);
+    width: 100vw;
+    display: flex;
+    justify-content: space-between;
+    .left {
+      // height: calc(1080px - 203px);
+      // height: calc(1080px - 61px);
+      // height: calc(100vh - 61px);
+      height: 100%;
+      width: 106px;
+      min-height: 640px;
+      background-color: #040e1b;
+      border-top: 1px solid #ecf0f8;
+      padding-top: 25px;
+      box-sizing: border-box;
+      display: flex;
+      align-items: center;
+      flex-direction: column;
+
+    }
+
+    .system-info {
+      display: flex;
+      flex-direction: column;
+    }
+
+    img {
+      width: 60px;
+      height: 60px;
+    }
+
+}
+</style>

+ 164 - 0
test/src/views/layout/components/NavBar.vue

@@ -0,0 +1,164 @@
+<template>
+  <!-- 头部信息的组件 -->
+  <el-header class="el-header">
+    <header class="page-home-header">
+      <div class="page-home-left">
+        <span class="name">欢迎你,&ensp;{{ nameLeft }}</span>
+        <span>{{ week }}</span
+        >&ensp;<span>{{ data_show }}</span>
+      </div>
+      <div class="page-home-right">
+        <div class="head-portrait">
+          <img src="../../../assets/OIP-C.jpg" alt="头像" />
+        </div>
+        <span class="admin">{{ nameRight }}</span>
+        <span class="line"></span>
+        <i class="el-icon-switch-button out" @click="output"></i>
+      </div>
+    </header>
+  </el-header>
+</template>
+<script>
+export default {
+  name: 'NavBar',
+  data () {
+    return {
+      nameLeft: '管理员', // 左边名字
+      nameRight: '管理员', // 右边名字
+      // headPortrait:"../../assets/OIP-C.jpg",//用户图片
+      week: '', // 左边周
+      data_show: '' // 左边时间
+    }
+  },
+  mounted () {
+    this.getDataTime()
+  },
+  methods: {
+    // 获取当前时间
+    getDataTime () {
+      const wk = new Date().getDay()
+      const yy = new Date().getFullYear()
+      const mm = new Date().getMonth() + 1
+      const dd = new Date().getDate()
+      const weeks = [
+        '星期日',
+        '星期一',
+        '星期二',
+        '星期三',
+        '星期四',
+        '星期五',
+        '星期六'
+      ]
+      this.week = weeks[wk]
+      this.data_show = yy + '年' + mm + '月' + dd + '日'
+    },
+
+    // 用户退出
+    output () {
+      this.$confirm('确定要退出系统吗?', '提示', {
+        confirmButtonText: '确定',
+        cancelButtonText: '取消',
+        type: 'error'
+      })
+        .then(() => {
+          // 点击确定的操作(调用接口)
+          // this.jiashuzu.splice(index, 1);
+          sessionStorage.removeItem('token')
+          this.$axios('/api/user/logout/', 'GET').then((data) => {
+            if (data) {
+              this.$message({
+                type: 'success',
+                message: '已成功退出'
+              })
+              this.$router.go(0)
+              window.sessionStorage.clear()
+            } else {
+              this.$message({
+                type: 'error',
+                message: '请稍后再试或者直接关闭浏览器'
+              })
+            }
+          })
+        })
+        .catch(() => {
+          // 点取消的提示
+          this.$message({
+            type: 'success',
+            message: '已取消退出'
+          })
+        })
+    }
+  }
+}
+</script>
+
+<style scoped lang="less">
+.el-header {
+  width: 100%;
+  // border: 1px solid red;
+  background-color: #040e1b;
+
+  // color: #333;
+  text-align: center;
+  line-height: 60px;
+}
+
+  .page-home-header {
+    width: 100%;
+    // min-width: 1400px;
+    min-width: 1291px;
+    height: 60px;
+    box-sizing: border-box;
+    display: flex;
+    justify-content: space-between;
+    align-items: center;
+    // border-bottom: 1px solid #ecf0f8;
+    font-size: 16px;
+    font-family: Microsoft YaHei;
+    font-weight: bold;
+    color: #ffffff;
+    background: #040e1b;
+    // box-shadow: 0px 1px 50px 0px rgba(210, 214, 223, 0.7);
+
+    .name {
+      margin-right: 25px;
+    }
+    .admin {
+      cursor: pointer;
+    }
+    .page-home-right {
+      display: flex;
+      // width: 149px;
+      align-items: center;
+      .head-portrait {
+        width: 38px;
+        height: 38px;
+        box-sizing: border-box;
+        img {
+          width: 100%;
+          height: 100%;
+          object-fit: cover;
+          border-radius: 50%;
+        }
+      }
+      .admin {
+        margin: 0 20px;
+      }
+      .line {
+        width: 1px;
+        height: 36px;
+        background-color: #ccc;
+        margin-right: 15px;
+      }
+      .out {
+        width: 40px;
+        height: 40px;
+        font-size: 35px;
+        text-align: center;
+        line-height: 40px;
+        cursor: pointer;
+      }
+    }
+  }
+
+</style>

+ 88 - 0
test/src/views/login/index.vue

@@ -0,0 +1,88 @@
+<template>
+  <div>
+    <div class="login">
+      <h1>欢迎来到后台管理系统</h1>
+      <div class="inp">
+        <form action="">
+          用户名: <input type="text" placeholder="请输入账号" v-model="id" />
+          <br /><br />
+          密&nbsp;&nbsp;码:
+          <input
+            type="password"
+            placeholder="请输入密码"
+            autocomplete="off"
+            v-model="password"
+          />
+          <br /><br />
+          <el-button type="primary" @click="submit">登录</el-button>
+        </form>
+      </div>
+    </div>
+  </div>
+</template>
+<script>
+export default {
+  name: 'Login',
+  data () {
+    return {
+      id: '',
+      password: ''
+    }
+  },
+
+  methods: {
+    async submit () {
+      const params = {
+        username: this.id,
+        password: this.password
+      }
+
+      const data = await this.$axios('/api/user/login/', 'POST', params)
+      console.log(data)
+
+      if (data.code === 0) {
+        this.$message.success('登录成功')
+        window.sessionStorage.setItem('token', 123)
+        this.$router.push('/LayOut')
+      } else {
+        this.$message.error('登录失败')
+      }
+    }
+  }
+}
+</script>
+<style lang="less" scoped>
+.login {
+  text-align: center;
+
+  .inp {
+    margin-top: 200px;
+    border: 1px solid #66afe9;
+    padding: 40px 10px 10px;
+    width: 300px;
+
+    margin: 200px auto 0;
+    input {
+      border: 1px solid #ccc;
+      padding: 7px 0px;
+      border-radius: 3px;
+      padding-left: 5px;
+      -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
+      box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
+      -webkit-transition: border-color ease-in-out 0.15s,
+        -webkit-box-shadow ease-in-out 0.15s;
+      -o-transition: border-color ease-in-out 0.15s,
+        box-shadow ease-in-out 0.15s;
+      transition: border-color ease-in-out 0.15s, box-shadow ease-in-out 0.15s;
+    }
+    input:focus {
+      border-color: #66afe9;
+      outline: 0;
+      -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075),
+        0 0 8px rgba(102, 175, 233, 0.6);
+      box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075),
+        0 0 8px rgba(102, 175, 233, 0.6);
+    }
+  }
+}
+</style>

+ 33 - 0
test/vue.config.js

@@ -0,0 +1,33 @@
+
+module.exports = {
+  // devServe vue脚手架内置的开发服务器配置项
+  lintOnSave: false,
+  devServer: {
+    // host: "192.168.1.63",
+    // port: "8080",
+    // proxy:配置代理服务器,类似于Node.js中的http-proxy-middleware
+    proxy: {
+      '/api': { // 有api就转发
+        target: 'http://192.168.1.17:56789', // 转发到这个地址s
+        // target: 'http://192.168.1.109:56789', // 转发到这个地址s
+
+
+        changeOrigin: true, // 跨域
+        pathRewrite: {
+          '^/api': '/api'
+        }// 路径重写 因为真实路径没有edianyun 所以要把这替换为空 转为真实服务器
+
+      }
+    }
+  },
+
+  // 配置静态资源路径publicPath,默认打包时的路径为"/"  process node提供的全局的
+  // process.env.NODE_ENV:node环境下的全局变量
+  // NODE_ENV:他有两个值,如果当时运行的是npm run serve,他的值就是devepolment;如果运行的是npm run build,他的值就是production(生产环境,项目上线时使用生产环境)
+  // publicPath: process.env.NODE_ENV == "production" ? "./" : "./",//判断是不是生产环境
+
+  // 关闭打包文件使用hash值命名,默认是true 就是文件后面的一堆字符
+  filenameHashing: false
+}
+
+// 当前文件修改之后,重启服务,否则新配置无法合并到服务器中