瀏覽代碼

初步完成登录页

shaogen1995 4 年之前
父節點
當前提交
04bf4e10da

+ 72 - 4
houtai/package-lock.json

@@ -2280,6 +2280,14 @@
       "integrity": "sha1-3TeelPDbgxCwgpH51kwyCXZmF/0=",
       "integrity": "sha1-3TeelPDbgxCwgpH51kwyCXZmF/0=",
       "dev": true
       "dev": true
     },
     },
+    "async-validator": {
+      "version": "1.8.5",
+      "resolved": "https://registry.npmjs.org/async-validator/-/async-validator-1.8.5.tgz",
+      "integrity": "sha512-tXBM+1m056MAX0E8TL2iCjg8WvSyXu0Zc8LNtYqrVeyoL3+esHRZ4SieE9fKQyyU09uONjnMEjrNBMqT0mbvmA==",
+      "requires": {
+        "babel-runtime": "6.x"
+      }
+    },
     "asynckit": {
     "asynckit": {
       "version": "0.4.0",
       "version": "0.4.0",
       "resolved": "https://registry.npm.taobao.org/asynckit/download/asynckit-0.4.0.tgz",
       "resolved": "https://registry.npm.taobao.org/asynckit/download/asynckit-0.4.0.tgz",
@@ -2327,6 +2335,19 @@
       "integrity": "sha1-1h9G2DslGSUOJ4Ta9bCUeai0HFk=",
       "integrity": "sha1-1h9G2DslGSUOJ4Ta9bCUeai0HFk=",
       "dev": true
       "dev": true
     },
     },
+    "axios": {
+      "version": "0.24.0",
+      "resolved": "https://registry.npmjs.org/axios/-/axios-0.24.0.tgz",
+      "integrity": "sha512-Q6cWsys88HoPgAaFAVUb0WpPk0O8iTeisR9IMqy9G8AbO4NlpVknrnQS03zzF9PGAWgO3cgletO3VjV/P7VztA==",
+      "requires": {
+        "follow-redirects": "^1.14.4"
+      }
+    },
+    "babel-helper-vue-jsx-merge-props": {
+      "version": "2.0.3",
+      "resolved": "https://registry.npmjs.org/babel-helper-vue-jsx-merge-props/-/babel-helper-vue-jsx-merge-props-2.0.3.tgz",
+      "integrity": "sha512-gsLiKK7Qrb7zYJNgiXKpXblxbV5ffSwR0f5whkPAaBAR4fhi6bwRZxX9wBlIc5M/v8CCkXUbXZL4N/nSE97cqg=="
+    },
     "babel-loader": {
     "babel-loader": {
       "version": "8.2.3",
       "version": "8.2.3",
       "resolved": "https://registry.npmmirror.com/babel-loader/download/babel-loader-8.2.3.tgz",
       "resolved": "https://registry.npmmirror.com/babel-loader/download/babel-loader-8.2.3.tgz",
@@ -2378,6 +2399,27 @@
         "@babel/helper-define-polyfill-provider": "^0.3.0"
         "@babel/helper-define-polyfill-provider": "^0.3.0"
       }
       }
     },
     },
+    "babel-runtime": {
+      "version": "6.26.0",
+      "resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz",
+      "integrity": "sha1-llxwWGaOgrVde/4E/yM3vItWR/4=",
+      "requires": {
+        "core-js": "^2.4.0",
+        "regenerator-runtime": "^0.11.0"
+      },
+      "dependencies": {
+        "core-js": {
+          "version": "2.6.12",
+          "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.12.tgz",
+          "integrity": "sha512-Kb2wC0fvsWfQrgk8HU5lW6U/Lcs8+9aaYcy4ZFc6DDlo4nZ7n70dEgE5rtR0oG6ufKDUnrwfWL1mXR5ljDatrQ=="
+        },
+        "regenerator-runtime": {
+          "version": "0.11.1",
+          "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz",
+          "integrity": "sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg=="
+        }
+      }
+    },
     "balanced-match": {
     "balanced-match": {
       "version": "1.0.2",
       "version": "1.0.2",
       "resolved": "https://registry.npm.taobao.org/balanced-match/download/balanced-match-1.0.2.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fbalanced-match%2Fdownload%2Fbalanced-match-1.0.2.tgz",
       "resolved": "https://registry.npm.taobao.org/balanced-match/download/balanced-match-1.0.2.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fbalanced-match%2Fdownload%2Fbalanced-match-1.0.2.tgz",
@@ -3980,8 +4022,7 @@
     "deepmerge": {
     "deepmerge": {
       "version": "1.5.2",
       "version": "1.5.2",
       "resolved": "https://registry.npm.taobao.org/deepmerge/download/deepmerge-1.5.2.tgz",
       "resolved": "https://registry.npm.taobao.org/deepmerge/download/deepmerge-1.5.2.tgz",
-      "integrity": "sha1-EEmdhohEza1P7ghC34x/bwyVp1M=",
-      "dev": true
+      "integrity": "sha1-EEmdhohEza1P7ghC34x/bwyVp1M="
     },
     },
     "default-gateway": {
     "default-gateway": {
       "version": "5.0.5",
       "version": "5.0.5",
@@ -4421,6 +4462,19 @@
       "integrity": "sha512-9ldvb6QMHiDpUNF1iSwBTiTT0qXEN+xIO5WlCJrC5gt0z74ofOiqR698vaJqYWnri0XZiF0YmnrFmGq/EmpGAA==",
       "integrity": "sha512-9ldvb6QMHiDpUNF1iSwBTiTT0qXEN+xIO5WlCJrC5gt0z74ofOiqR698vaJqYWnri0XZiF0YmnrFmGq/EmpGAA==",
       "dev": true
       "dev": true
     },
     },
+    "element-ui": {
+      "version": "2.15.6",
+      "resolved": "https://registry.npmjs.org/element-ui/-/element-ui-2.15.6.tgz",
+      "integrity": "sha512-rcYXEKd/j2G0AgficAOk1Zd1AsnHRkhmrK4yLHmNOiimU2JfsywgfKUjMoFuT6pQx0luhovj8lFjpE4Fnt58Iw==",
+      "requires": {
+        "async-validator": "~1.8.1",
+        "babel-helper-vue-jsx-merge-props": "^2.0.0",
+        "deepmerge": "^1.2.0",
+        "normalize-wheel": "^1.0.1",
+        "resize-observer-polyfill": "^1.5.0",
+        "throttle-debounce": "^1.0.1"
+      }
+    },
     "elliptic": {
     "elliptic": {
       "version": "6.5.4",
       "version": "6.5.4",
       "resolved": "https://registry.npm.taobao.org/elliptic/download/elliptic-6.5.4.tgz",
       "resolved": "https://registry.npm.taobao.org/elliptic/download/elliptic-6.5.4.tgz",
@@ -5065,8 +5119,7 @@
     "follow-redirects": {
     "follow-redirects": {
       "version": "1.14.5",
       "version": "1.14.5",
       "resolved": "https://registry.npmmirror.com/follow-redirects/download/follow-redirects-1.14.5.tgz",
       "resolved": "https://registry.npmmirror.com/follow-redirects/download/follow-redirects-1.14.5.tgz",
-      "integrity": "sha1-8JpYSJgdPHcrU5Iwl3hSP42Fw4E=",
-      "dev": true
+      "integrity": "sha1-8JpYSJgdPHcrU5Iwl3hSP42Fw4E="
     },
     },
     "for-in": {
     "for-in": {
       "version": "1.0.2",
       "version": "1.0.2",
@@ -7180,6 +7233,11 @@
       "integrity": "sha1-suHE3E98bVd0PfczpPWXjRhlBVk=",
       "integrity": "sha1-suHE3E98bVd0PfczpPWXjRhlBVk=",
       "dev": true
       "dev": true
     },
     },
+    "normalize-wheel": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/normalize-wheel/-/normalize-wheel-1.0.1.tgz",
+      "integrity": "sha1-rsiGr/2wRQcNhWRH32Ls+GFG7EU="
+    },
     "npm-run-path": {
     "npm-run-path": {
       "version": "2.0.2",
       "version": "2.0.2",
       "resolved": "https://registry.npmmirror.com/npm-run-path/download/npm-run-path-2.0.2.tgz?cache=0&sync_timestamp=1633420549182&other_urls=https%3A%2F%2Fregistry.npmmirror.com%2Fnpm-run-path%2Fdownload%2Fnpm-run-path-2.0.2.tgz",
       "resolved": "https://registry.npmmirror.com/npm-run-path/download/npm-run-path-2.0.2.tgz?cache=0&sync_timestamp=1633420549182&other_urls=https%3A%2F%2Fregistry.npmmirror.com%2Fnpm-run-path%2Fdownload%2Fnpm-run-path-2.0.2.tgz",
@@ -8783,6 +8841,11 @@
       "integrity": "sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8=",
       "integrity": "sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8=",
       "dev": true
       "dev": true
     },
     },
+    "resize-observer-polyfill": {
+      "version": "1.5.1",
+      "resolved": "https://registry.npmjs.org/resize-observer-polyfill/-/resize-observer-polyfill-1.5.1.tgz",
+      "integrity": "sha512-LwZrotdHOo12nQuZlHEmtuXdqGoOD0OhaxopaNFxWzInpEgaLWoVuAMbTzixuosCx2nEG58ngzW3vxdWoxIgdg=="
+    },
     "resolve": {
     "resolve": {
       "version": "1.20.0",
       "version": "1.20.0",
       "resolved": "https://registry.npm.taobao.org/resolve/download/resolve-1.20.0.tgz?cache=0&sync_timestamp=1613054822645&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fresolve%2Fdownload%2Fresolve-1.20.0.tgz",
       "resolved": "https://registry.npm.taobao.org/resolve/download/resolve-1.20.0.tgz?cache=0&sync_timestamp=1613054822645&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fresolve%2Fdownload%2Fresolve-1.20.0.tgz",
@@ -9886,6 +9949,11 @@
         "neo-async": "^2.6.0"
         "neo-async": "^2.6.0"
       }
       }
     },
     },
+    "throttle-debounce": {
+      "version": "1.1.0",
+      "resolved": "https://registry.npmjs.org/throttle-debounce/-/throttle-debounce-1.1.0.tgz",
+      "integrity": "sha512-XH8UiPCQcWNuk2LYePibW/4qL97+ZQ1AN3FNXwZRBNPPowo/NRU5fAlDCSNBJIYCKbioZfuYtMhG4quqoJhVzg=="
+    },
     "through2": {
     "through2": {
       "version": "2.0.5",
       "version": "2.0.5",
       "resolved": "https://registry.npm.taobao.org/through2/download/through2-2.0.5.tgz",
       "resolved": "https://registry.npm.taobao.org/through2/download/through2-2.0.5.tgz",

+ 2 - 0
houtai/package.json

@@ -7,7 +7,9 @@
     "build": "vue-cli-service build"
     "build": "vue-cli-service build"
   },
   },
   "dependencies": {
   "dependencies": {
+    "axios": "^0.24.0",
     "core-js": "^3.6.5",
     "core-js": "^3.6.5",
+    "element-ui": "^2.15.6",
     "vue": "^2.6.11",
     "vue": "^2.6.11",
     "vue-router": "^3.2.0"
     "vue-router": "^3.2.0"
   },
   },

+ 1 - 1
houtai/public/index.html

@@ -5,7 +5,7 @@
     <meta http-equiv="X-UA-Compatible" content="IE=edge">
     <meta http-equiv="X-UA-Compatible" content="IE=edge">
     <meta name="viewport" content="width=device-width,initial-scale=1.0">
     <meta name="viewport" content="width=device-width,initial-scale=1.0">
     <link rel="icon" href="<%= BASE_URL %>favicon.ico">
     <link rel="icon" href="<%= BASE_URL %>favicon.ico">
-    <title><%= htmlWebpackPlugin.options.title %></title>
+    <title>珠海高新区中共党史学习教育园地线上展厅</title>
   </head>
   </head>
   <body>
   <body>
     <noscript>
     <noscript>

+ 0 - 23
houtai/src/App.vue

@@ -1,32 +1,9 @@
 <template>
 <template>
   <div id="app">
   <div id="app">
-    <div id="nav">
-      <router-link to="/">Home</router-link> |
-      <router-link to="/about">About</router-link>
-    </div>
     <router-view/>
     <router-view/>
   </div>
   </div>
 </template>
 </template>
 
 
 <style lang="less">
 <style lang="less">
-#app {
-  font-family: Avenir, Helvetica, Arial, sans-serif;
-  -webkit-font-smoothing: antialiased;
-  -moz-osx-font-smoothing: grayscale;
-  text-align: center;
-  color: #2c3e50;
-}
 
 
-#nav {
-  padding: 30px;
-
-  a {
-    font-weight: bold;
-    color: #2c3e50;
-
-    &.router-link-exact-active {
-      color: #42b983;
-    }
-  }
-}
 </style>
 </style>

+ 8 - 0
houtai/src/assets/chushi.css

@@ -0,0 +1,8 @@
+*{
+  margin: 0;
+  padding: 0;
+  box-sizing: border-box;
+}
+ul li {
+  list-style: none;
+}

二進制
houtai/src/assets/left.jpg


二進制
houtai/src/assets/loBac.jpg


二進制
houtai/src/assets/logo.png


二進制
houtai/src/assets/user.jpg


+ 0 - 58
houtai/src/components/HelloWorld.vue

@@ -1,58 +0,0 @@
-<template>
-  <div class="hello">
-    <h1>{{ msg }}</h1>
-    <p>
-      For a guide and recipes on how to configure / customize this project,<br>
-      check out the
-      <a href="https://cli.vuejs.org" target="_blank" rel="noopener">vue-cli documentation</a>.
-    </p>
-    <h3>Installed CLI Plugins</h3>
-    <ul>
-      <li><a href="https://github.com/vuejs/vue-cli/tree/dev/packages/%40vue/cli-plugin-babel" target="_blank" rel="noopener">babel</a></li>
-      <li><a href="https://github.com/vuejs/vue-cli/tree/dev/packages/%40vue/cli-plugin-router" target="_blank" rel="noopener">router</a></li>
-    </ul>
-    <h3>Essential Links</h3>
-    <ul>
-      <li><a href="https://vuejs.org" target="_blank" rel="noopener">Core Docs</a></li>
-      <li><a href="https://forum.vuejs.org" target="_blank" rel="noopener">Forum</a></li>
-      <li><a href="https://chat.vuejs.org" target="_blank" rel="noopener">Community Chat</a></li>
-      <li><a href="https://twitter.com/vuejs" target="_blank" rel="noopener">Twitter</a></li>
-      <li><a href="https://news.vuejs.org" target="_blank" rel="noopener">News</a></li>
-    </ul>
-    <h3>Ecosystem</h3>
-    <ul>
-      <li><a href="https://router.vuejs.org" target="_blank" rel="noopener">vue-router</a></li>
-      <li><a href="https://vuex.vuejs.org" target="_blank" rel="noopener">vuex</a></li>
-      <li><a href="https://github.com/vuejs/vue-devtools#vue-devtools" target="_blank" rel="noopener">vue-devtools</a></li>
-      <li><a href="https://vue-loader.vuejs.org" target="_blank" rel="noopener">vue-loader</a></li>
-      <li><a href="https://github.com/vuejs/awesome-vue" target="_blank" rel="noopener">awesome-vue</a></li>
-    </ul>
-  </div>
-</template>
-
-<script>
-export default {
-  name: 'HelloWorld',
-  props: {
-    msg: String
-  }
-}
-</script>
-
-<!-- Add "scoped" attribute to limit CSS to this component only -->
-<style scoped lang="less">
-h3 {
-  margin: 40px 0 0;
-}
-ul {
-  list-style-type: none;
-  padding: 0;
-}
-li {
-  display: inline-block;
-  margin: 0 10px;
-}
-a {
-  color: #42b983;
-}
-</style>

+ 4 - 2
houtai/src/main.js

@@ -1,9 +1,11 @@
 import Vue from 'vue'
 import Vue from 'vue'
+import ElementUI from 'element-ui';
+import 'element-ui/lib/theme-chalk/index.css';
 import App from './App.vue'
 import App from './App.vue'
 import router from './router'
 import router from './router'
-
+Vue.use(ElementUI);
 Vue.config.productionTip = false
 Vue.config.productionTip = false
-
+import './assets/chushi.css'
 new Vue({
 new Vue({
   router,
   router,
   render: h => h(App)
   render: h => h(App)

+ 25 - 13
houtai/src/router/index.js

@@ -1,29 +1,41 @@
 import Vue from 'vue'
 import Vue from 'vue'
 import VueRouter from 'vue-router'
 import VueRouter from 'vue-router'
-import Home from '../views/Home.vue'
-
+import login from '../views/login.vue'
+import home from '../views/home.vue'
+import { Message } from 'element-ui'
 Vue.use(VueRouter)
 Vue.use(VueRouter)
 
 
 const routes = [
 const routes = [
   {
   {
     path: '/',
     path: '/',
-    name: 'Home',
-    component: Home
+    name: 'login',
+    component: login
+  }, 
+   {
+    path: '/home',
+    name: 'home',
+    component: home
   },
   },
-  {
-    path: '/about',
-    name: 'About',
-    // route level code-splitting
-    // this generates a separate chunk (about.[hash].js) for this route
-    // which is lazy-loaded when the route is visited.
-    component: () => import(/* webpackChunkName: "about" */ '../views/About.vue')
-  }
+
 ]
 ]
 
 
 const router = new VueRouter({
 const router = new VueRouter({
-  mode: 'history',
+  // mode: 'history',
   base: process.env.BASE_URL,
   base: process.env.BASE_URL,
   routes
   routes
 })
 })
 
 
+router.beforeEach((to, from, next) => {
+  // 如果是去登录页,不需要验证,直接下一步
+  if (to.name === 'login') next()
+  // 否则要有token值才能下一步,不然就返回登录页
+  else {
+    const token = localStorage.getItem('DSJY_token')
+    if (token) next()
+    else {
+      Message.warning('登录失效,请重新登录')
+      next({ name: 'login' })
+    }
+  }
+})
 export default router
 export default router

+ 17 - 0
houtai/src/utils/api.js

@@ -0,0 +1,17 @@
+import axios from './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
+  })
+}

+ 37 - 0
houtai/src/utils/request.js

@@ -0,0 +1,37 @@
+import axios from 'axios'
+const service = axios.create({
+  baseURL: 'http://192.168.0.135:8011/', // 本地调试
+  // baseURL: '', // build
+  timeout: 5000
+})
+// 请求拦截器
+service.interceptors.request.use(function (config) {
+  // console.log('触发拦截器')
+  // 在发送请求之前做些什么:看看有没有token,如果有通过请求头的方式传递token
+  const token = localStorage.getItem('DSJY_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('DSJY_token')
+  }
+  return response.data
+}, function (error) {
+  // 对响应错误做点什么
+  return Promise.reject(error)
+})
+
+export default service

+ 0 - 5
houtai/src/views/About.vue

@@ -1,5 +0,0 @@
-<template>
-  <div class="about">
-    <h1>This is an about page</h1>
-  </div>
-</template>

+ 207 - 9
houtai/src/views/Home.vue

@@ -1,18 +1,216 @@
 <template>
 <template>
   <div class="home">
   <div class="home">
-    <img alt="Vue logo" src="../assets/logo.png">
-    <HelloWorld msg="Welcome to Your Vue.js App"/>
+    <div class="top">
+      <div class="left">珠海高新区中共党史学习教育园地线上展厅</div>
+      <div class="right" @click="cut = !cut">
+        <img src="../assets/user.jpg" alt="" />
+        <p>{{ userName }}</p>
+        <!-- 下箭头 -->
+        <div class="pull_down" v-if="cut"></div>
+        <div class="pull_up" v-else></div>
+        <!-- 点击箭头出来的ul -->
+        <ul class="user_handle" v-show="cut">
+          <li @click="isShow = true">修改密码</li>
+          <li @click="outLogin">退出登录</li>
+        </ul>
+      </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>
   </div>
 </template>
 </template>
 
 
 <script>
 <script>
-// @ is an alias to /src
-import HelloWorld from '@/components/HelloWorld.vue'
-
+//这里可以导入其他文件(比如:组件,工具js,第三方插件js,json文件,图片文件等等)
+//例如:import 《组件名称》 from '《组件路径》';
+import { updatePwd } from "../utils/api";
 export default {
 export default {
-  name: 'Home',
-  components: {
-    HelloWorld
+  //import引入的组件需要注入到对象中才能使用
+  components: {},
+  data() {
+    //这里存放数据
+        const validatePass2 = (rule, value, callback) => {
+      if (value !== this.form.newPassword) {
+        callback(new Error('两次输入密码不一致!'))
+      } else {
+        callback()
+      }
+    }
+    return {
+      userName: "",
+      cut: false,
+      isShow: false,
+      // 修改密码
+      form: {
+        oldPassword: "",
+        newPassword: "",
+        checkPass: "",
+      },
+      rules: {
+        checkPass: [{ validator: validatePass2, trigger: "blur" }],
+        oldPassword: [{ required: true, message: "不能为空", trigger: "blur" }],
+        newPassword: [{ required: true, message: "不能为空", trigger: "blur" }],
+      },
+    };
+  },
+  //监听属性 类似于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 {
+        await updatePwd(this.form);
+        this.$message.success("修改成功");
+        localStorage.clear("DSJY_token");
+        localStorage.clear("DSJY_Name");
+        this.$router.push("/");
+      } catch (error) {
+        this.$message.error("旧密码错误");
+      }
+    },
+    outLogin() {
+      this.cut = false;
+      this.$confirm("确定退出吗?", "提示", {
+        confirmButtonText: "确定",
+        cancelButtonText: "取消",
+        type: "warning",
+      })
+        .then(() => {
+          localStorage.clear("DSJY_token");
+          localStorage.clear("DSJY_Name");
+          this.$router.push("/");
+          this.$message.success("退出成功!");
+        })
+        .catch(() => {
+          this.$message.info("已取消");
+        });
+    },
+  },
+  //生命周期 - 创建完成(可以访问当前this实例)
+  created() {
+    // 获取用户信息
+    this.userName = localStorage.getItem("DSJY_Name");
+  },
+  //生命周期 - 挂载完成(可以访问DOM元素)
+  mounted() {},
+  beforeCreate() {}, //生命周期 - 创建之前
+  beforeMount() {}, //生命周期 - 挂载之前
+  beforeUpdate() {}, //生命周期 - 更新之前
+  updated() {}, //生命周期 - 更新之后
+  beforeDestroy() {}, //生命周期 - 销毁之前
+  destroyed() {}, //生命周期 - 销毁完成
+  activated() {}, //如果页面有keep-alive缓存功能,这个函数会触发
+};
+</script>
+<style lang='less' scoped>
+.home {
+  .top {
+    padding: 0 30px;
+    display: flex;
+    align-items: center;
+    justify-content: space-between;
+    height: 100px;
+    background-color: #ac3334;
+    color: #fff;
+    .left {
+      font-weight: 700;
+      font-size: 34px;
+    }
+    .right {
+      position: relative;
+      display: flex;
+      align-items: center;
+      img {
+        margin-right: 10px;
+        width: 40px;
+        height: 40px;
+        border-radius: 50%;
+      }
+      .pull_down {
+        position: absolute;
+        right: -20px;
+        bottom: 13px;
+        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: -20px;
+        bottom: 13px;
+        display: inline-block;
+        width: 0;
+        height: 0;
+        border-left: 8px solid transparent;
+        border-right: 8px solid transparent;
+        border-top: 8px solid #fff;
+      }
+      .user_handle {
+        width: 200px;
+        z-index: 999;
+        padding: 10px 0;
+        position: absolute;
+        right: -30px;
+        bottom: -110px;
+        background-color: #ac3334;
+        li {
+          display: flex;
+          justify-content: center;
+          cursor: pointer;
+          margin: 10px 0;
+        }
+        li:hover {
+          color: #dc3545;
+        }
+      }
+    }
   }
   }
 }
 }
-</script>
+</style>

+ 161 - 0
houtai/src/views/login.vue

@@ -0,0 +1,161 @@
+<template>
+  <div class="login">
+    <div class="box">
+      <div class="left"></div>
+      <div class="right">
+        <div class="tit">
+          <h3>用户登录</h3>
+        </div>
+        <div class="inputE">
+          <el-form
+            :model="ruleForm"
+            :rules="rules"
+            ref="ruleForm"
+            class="demo-ruleForm"
+          >
+            <el-form-item  prop="userName">
+              <el-input v-model="ruleForm.userName" placeholder="请输入账号" prefix-icon="el-icon-user"></el-input>
+            </el-form-item>
+            <el-form-item  prop="password">
+              <el-input  v-model="ruleForm.password" placeholder="请输入密码" prefix-icon="el-icon-lock" show-password></el-input>
+            </el-form-item>
+          </el-form>
+          <!-- 登录按钮 -->
+          <div class="btnOk" @click="login">登 录</div>
+        </div>
+      </div>
+    </div>
+  </div>
+</template>
+
+<script>
+import {userLogin} from '../utils/api'
+export default {
+  //import引入的组件需要注入到对象中才能使用
+  components: {},
+  data() {
+    //这里存放数据
+    return {
+      ruleForm:{
+        userName:'',
+        password:''
+      },
+      rules: {
+        userName:{ required: true, message: '不能为空', trigger: 'blur' },
+        password:{ required: true, message: '不能为空', trigger: 'blur' },
+      }
+    };
+  },
+  //监听属性 类似于data概念
+  computed: {},
+  //监控data中的数据变化
+  watch: {},
+  //方法集合
+  methods: {
+   async login(){
+     if(this.ruleForm.userName.trim()==='') return this.$message.warning('账号不能为空')
+     if(this.ruleForm.password.trim()==='') return this.$message.warning('密码不能为空')
+    let res = await userLogin(this.ruleForm)
+    if(res.code===0) {
+          localStorage.setItem('DSJY_token', res.data.token)
+          localStorage.setItem('DSJY_Name', res.data.user.nickName)
+          this.$router.push('/home')
+          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 {
+/deep/.el-form-item__content{
+  height: 80px;
+  margin: 20px 0;
+}
+/deep/.el-input {
+  height: 80px;
+}
+/deep/.el-input__inner{
+  padding-left: 50px !important;
+  height: 80px;
+  border:none;
+  border-bottom: 1px solid #DCDFE6;
+  font-size: 20px;
+}
+/deep/.el-input__icon{
+  font-size: 24px;
+  color: #AC3334;
+}
+  position: relative;
+  width: 100vw;
+  height: 100vh;
+  background: url("../assets/loBac.jpg");
+  background-size: 100% 100%;
+  .box {
+    display: flex;
+    position: absolute;
+    left: 50%;
+    top: 52%;
+    transform: translate(-50%, -50%);
+    width: 1100px;
+    height: 700px;
+    .left {
+      width: 500px;
+      height: 100%;
+      background: url("../assets/left.jpg");
+      background-size: 100% 100%;
+    }
+    .right {
+      position: relative;
+      color: #ac3334;
+      padding: 0 20px;
+      flex: 1;
+      background-color: #fff;
+      .tit {
+        display: flex;
+        align-items: center;
+        height: 100px;
+        border-bottom: 1px solid #ccc;
+      }
+      h3 {
+        margin-left: 30px;
+        font-size: 30px;
+        border-left: 5px solid #ac3334;
+        padding-left: 50px;
+      }
+      .btnOk{
+        cursor: pointer;
+        position: absolute;
+        bottom: 120px;
+        left: 50%;
+        transform: translateX(-50%);
+        width: 350px;
+        height: 60px;
+        line-height: 60px;
+        border-radius: 10px;
+        background-color: #ac3334;
+        font-size: 24px;
+        color: #fff;
+        text-align: center;
+
+      }
+    }
+    .inputE{
+      width: 70%;
+      margin: 80px auto 0;
+    }
+  }
+}
+//@import url(); 引入公共css类
+</style>

二進制
web/src/assets/tabMo/moTabBac5.png


二進制
web/src/assets/tabMo/tab3dw.png


+ 190 - 2
web/src/views/gui/menu.vue

@@ -430,6 +430,7 @@
         </ul>
         </ul>
         <!-- --------------留言板输入----------------------- -->
         <!-- --------------留言板输入----------------------- -->
         <div class="MoTab3LiuInp" v-else>
         <div class="MoTab3LiuInp" v-else>
+          <span>{{ textarea.length }} / 100</span>
           <el-input
           <el-input
             resize="none"
             resize="none"
             type="textarea"
             type="textarea"
@@ -451,7 +452,78 @@
         </div>
         </div>
       </div>
       </div>
     </div>
     </div>
+    <!-- 移动端-----打卡-------------------------------------------------->
+    <div class="MoTab4 MoTab" v-if="rightTab2[3].isShow">
+      <div class="conten" ref="pcTab4">
+        <!-- 人物背景底纹 -->
+        <div class="MoRWbac">
+          <img
+            src="@/assets/tabMo/tab3dw.png"
+            alt=""
+            v-show="tab3DataInd === 0"
+          />
+          <img
+            src="@/assets/tabMo/moTab1Map.png"
+            alt=""
+            v-show="tab3DataInd === 1"
+          />
+        </div>
+        <!-- 关闭按钮 -->
+        <div class="btnX" @click="rightTab2[3].isShow = false">
+          <img src="@/assets/tab/×.png" alt="" />
+        </div>
+        <!-- 标题 -->
+        <div class="Motitle">珠海高新区中共党史学习教育园地</div>
+        <!-- 文字内容 -->
+        <p class="tab4Name">
+          {{ tab4Name }}
+        </p>
+        <!-- 弹窗输入姓名 -->
+        <div class="MoinpName" v-if="tab4NameShow">
+          <div class="shuru">
+            <!-- 下拉框 -->
+            <el-select v-model="tab3DataInd" placeholder="请选择主题">
+              <el-option label="解放万山群岛战役" :value="0"></el-option>
+              <el-option label="6666666666" :value="1"></el-option>
+            </el-select>
+            <el-input
+              v-model="tab4Name"
+              placeholder="请输入您的名字"
+            ></el-input>
+            <p>选择主题,填写姓名后,即可打卡</p>
+          </div>
+          <div class="MoinpBtnOk" @touchstart="tab4NameBtnOk">确 定</div>
+        </div>
+         <!-- 生成的二维码 -->
+        <div class="MoqrCode" v-if="qrCodeUrl">
+          <img :src="qrCodeUrl" alt="" />
+        </div>
+          <a class="MoDownload" :href="base64SUrlTab4" download v-if="qrCodeUrl"
+            >点击保存打卡主题</a>
+      </div>
+    </div>
+    <!-- 移动端-----分享-------------------------------------------------->
+    <div class="MoTab5 MoTab" v-if="rightTab2[4].isShow">
+      <div class="conten">
+        <!-- 关闭按钮 -->
+        <div class="btnX" @click="rightTab2[4].isShow = false">
+          <img src="@/assets/tab/×.png" alt="" />
+        </div>
+        <!-- 标题 -->
+        <div class="Motitle">分 享</div>
+        <p class="biaoti">珠海高新区中共党史教育学习园地</p>
+        <p class="biaoti">虚拟展厅</p>
+        <div class="Motab5ER">
+            <img src="@/assets/tab/tab5Ma.png" alt="" />
+            <p>请使用手机扫描二维码</p>
+          <a href="../../assets/tab/tab5Ma.png" download class="tab5Box"
+            >下 载 二 维 码</a
+          >
+        </div>
+      </div>
+    </div>
 
 
+<!-- PC------------------------------------------------------------------------- -->
     <!-- pc --路线 ----------------------->
     <!-- pc --路线 ----------------------->
     <div class="pcTab1 myTab" v-if="rightTab[0].isShow">
     <div class="pcTab1 myTab" v-if="rightTab[0].isShow">
       <div class="conten">
       <div class="conten">
@@ -599,6 +671,7 @@
         </div>
         </div>
         <!-- 文本域 -->
         <!-- 文本域 -->
         <div class="texe">
         <div class="texe">
+          <span>{{ textarea.length }} / 100</span>
           <el-input
           <el-input
             resize="none"
             resize="none"
             type="textarea"
             type="textarea"
@@ -639,7 +712,6 @@
             alt=""
             alt=""
             v-show="tab3DataInd === 1"
             v-show="tab3DataInd === 1"
           />
           />
-          <!-- <img src="@/assets/tab/tab1dw.png" alt=""> -->
         </div>
         </div>
         <!-- 关闭按钮 -->
         <!-- 关闭按钮 -->
         <div class="btnX" @click="rightTab[3].isShow = false" v-if="topicXShow">
         <div class="btnX" @click="rightTab[3].isShow = false" v-if="topicXShow">
@@ -861,7 +933,7 @@ export default {
     liuyanBtn() {
     liuyanBtn() {
       if (this.textarea.length > 100)
       if (this.textarea.length > 100)
         return this.$message.warning("留言内容不能超过100个字");
         return this.$message.warning("留言内容不能超过100个字");
-      if (this.textarea.trim() === '')
+      if (this.textarea.trim() === "")
         return this.$message.warning("留言内容不能为空");
         return this.$message.warning("留言内容不能为空");
       let data = {};
       let data = {};
       data.content = this.textarea;
       data.content = this.textarea;
@@ -2167,6 +2239,122 @@ export default {
       }
       }
     }
     }
   }
   }
+  .MoTab4{
+    .MoRWbac{
+      position: absolute;
+      left: 0;
+      top: 0;
+      width: 100%;
+      height: 100%;
+      &>img{
+        width: 100%;
+        height: 100%;
+      }
+    }
+    .Motitle{
+      font-size: 16px;
+    }
+    .conten{
+      .MoinpName{
+        z-index: 999;
+        position: absolute;
+        background-color: rgba(0, 0, 0, 0.5);
+        left: 0;
+        bottom:0;
+        width: 100%;
+        height: 84%;
+        .shuru{
+          width: 220px;
+          margin: 50px auto 0;
+          /deep/.el-input{
+            width: 220px;
+            margin: 20px 0;
+          }
+
+        }
+        .MoinpBtnOk{
+        color: #b24340;
+        border-radius: 8px;
+        display: flex;
+        justify-content: center;
+        align-items: center;
+        width: 131px;
+        height: 34px;
+        background-color: rgba(237, 211, 176, 1);
+        position: absolute;
+        bottom: 20px;
+        left: 50%;
+        transform: translateX(-50%);
+        }
+      }
+        .tab4Name{
+          margin-top: -10px;
+          text-align: center;
+          font-size: 20px;
+        }
+        .MoqrCode{
+          position: absolute;
+          left: 5px;
+          top: 85px;
+          width: 100px;
+          height: 100px;
+          &>img {
+            width: 100%;
+            height: 100%;
+          }
+        }
+              .MoDownload{
+          border-radius: 8px;
+          display: flex;
+          justify-content: center;
+          align-items: center;
+          width: 182px;
+          height: 34px;
+          background-color: rgba(237, 211, 176, 0.4);
+          position: absolute;
+          bottom: 15px;
+          left: 50%;
+          transform: translateX(-50%;);
+      }
+    }
+  }
+  .MoTab5{
+    .conten{
+      background: url('../../assets/tabMo/moTabBac5.png');
+      background-size: 100% 100%;
+      .biaoti{
+        font-size: 16px;
+        width: 80%;
+        margin: 0 auto 0;
+        text-align: center;
+        margin-bottom: 8px;
+      }
+      .Motab5ER{
+        margin: 20px auto 0;
+        width: 180px;
+        height: 300px;
+        &>img {
+          width: 180px;
+          height: 180px;
+        }
+        &>p {
+          text-align: center;
+          margin: 10px 0;
+        }
+        .tab5Box{
+          color: #EDD3B0;
+          margin: 0 auto;
+          border-radius: 8px;
+          display: flex;
+          justify-content: center;
+          align-items: center;
+          width: 180px;
+          height: 34px;
+          background-color: rgba(237, 211, 176, 0.4);
+        }
+      }
+    }
+  }
 }
 }
 @media only screen and (max-width: 487px) {
 @media only screen and (max-width: 487px) {
   #myMoMu {
   #myMoMu {