| @@ -0,0 +1,3 @@ | |||||
| > 1% | |||||
| last 2 versions | |||||
| not ie <= 8 | |||||
| @@ -0,0 +1,14 @@ | |||||
| module.exports = { | |||||
| root: true, | |||||
| env: { | |||||
| node: true | |||||
| }, | |||||
| extends: ["plugin:vue/essential"], | |||||
| rules: { | |||||
| "no-console": process.env.NODE_ENV === "production" ? "error" : "off", | |||||
| "no-debugger": process.env.NODE_ENV === "production" ? "error" : "off" | |||||
| }, | |||||
| parserOptions: { | |||||
| parser: "babel-eslint" | |||||
| } | |||||
| }; | |||||
| @@ -0,0 +1,21 @@ | |||||
| .DS_Store | |||||
| node_modules | |||||
| /dist | |||||
| # local env files | |||||
| .env.local | |||||
| .env.*.local | |||||
| # Log files | |||||
| npm-debug.log* | |||||
| yarn-debug.log* | |||||
| yarn-error.log* | |||||
| # Editor directories and files | |||||
| .idea | |||||
| .vscode | |||||
| *.suo | |||||
| *.ntvs* | |||||
| *.njsproj | |||||
| *.sln | |||||
| *.sw* | |||||
| @@ -0,0 +1,27 @@ | |||||
| # mobile-admin | |||||
| ## Project setup | |||||
| ``` | |||||
| npm install | |||||
| ``` | |||||
| ### Compiles and hot-reloads for development | |||||
| ``` | |||||
| npm run serve | |||||
| ``` | |||||
| ### Compiles and minifies for production | |||||
| ``` | |||||
| npm run build | |||||
| ``` | |||||
| ### Run your tests | |||||
| ``` | |||||
| npm run test | |||||
| ``` | |||||
| ### Lints and fixes files | |||||
| ``` | |||||
| npm run lint | |||||
| ``` | |||||
| @@ -0,0 +1 @@ | |||||
| <!DOCTYPE html><html lang=en><head><meta charset=utf-8><meta http-equiv=X-UA-Compatible content="IE=edge"><meta name=viewport content="maximum-scale=1,minimum-scale=1,user-scalable=1,width=device-width,initial-scale=1"><link rel=icon href=/favicon.ico><title>mobile-admin</title><link href=/static/css/chunk-4ca71562.c4fd982f.css rel=prefetch><link href=/static/js/chunk-2d0df214.55b65f36.js rel=prefetch><link href=/static/js/chunk-4ca71562.02fcf80f.js rel=prefetch><link href=/static/css/app.640e1136.css rel=preload as=style><link href=/static/css/chunk-vendors.3bd1146c.css rel=preload as=style><link href=/static/js/app.58b1b7dc.js rel=preload as=script><link href=/static/js/chunk-vendors.6e82d040.js rel=preload as=script><link href=/static/css/chunk-vendors.3bd1146c.css rel=stylesheet><link href=/static/css/app.640e1136.css rel=stylesheet></head><body style="background-color: #f7f8fa;"><noscript><strong>We're sorry but mobile-admin doesn't work properly without JavaScript enabled. Please enable it to continue.</strong></noscript><div id=app></div><script src=/static/js/chunk-vendors.6e82d040.js></script><script src=/static/js/app.58b1b7dc.js></script></body></html> | |||||
| @@ -0,0 +1 @@ | |||||
| #app{font-family:Avenir,Helvetica,Arial,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;color:#2c3e50;overflow:hidden}a:-webkit-any-link{text-decoration:none}input:-webkit-autofill{-webkit-box-shadow:0 0 0 26.66667rem #fff inset}input{-webkit-filter:none!important;filter:none!important}.panel-container{margin-bottom:.13333rem}.panel-container .panel-content{padding:.26667rem .4rem}.van-hairline--top-bottom:after{border:none!important}.van-cell{padding-bottom:0!important}.van-cell .van-cell__title{-webkit-box-flex:3;-ms-flex:3;flex:3}@font-face{font-family:iconfont;src:url(//at.alicdn.com/t/font_927880_2ihl8qth6yg.eot);src:url(//at.alicdn.com/t/font_927880_2ihl8qth6yg.eot#iefix) format("embedded-opentype"),url(//at.alicdn.com/t/font_927880_2ihl8qth6yg.woff) format("woff"),url(//at.alicdn.com/t/font_927880_2ihl8qth6yg.ttf) format("truetype"),url(//at.alicdn.com/t/font_927880_2ihl8qth6yg.svg#iconfont) format("svg")}@font-face{font-family:iconfont;src:url(//at.alicdn.com/t/font_2723835_y1jsf7gbkz.woff2?t=1628136189738) format("woff2"),url(//at.alicdn.com/t/font_2723835_y1jsf7gbkz.woff?t=1628136189738) format("woff"),url(//at.alicdn.com/t/font_2723835_y1jsf7gbkz.ttf?t=1628136189738) format("truetype")}.iconfont{font-family:iconfont!important;font-size:.74667rem;font-style:normal;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.icon-home:before{content:"\E620"}.icon-shu:before{content:"\E634"}.icon-ziyuan:before{content:"\E621"}.icon-username:before{content:"\EAC3";position:absolute;left:-.13333rem;bottom:.05333rem;font-size:.58667rem}.icon-password:before{content:"\EAC2";position:absolute;left:-.13333rem;bottom:.02667rem;font-size:.64rem}.icon-yanzhengma:before{content:"\E63F";position:absolute;left:-.05333rem;bottom:.08rem;font-size:.48rem;font-weight:700} | |||||
| @@ -0,0 +1 @@ | |||||
| .login-container[data-v-3d4a5790]{height:100vh;background:#fff!important;text-align:center}.login-container .input-box[data-v-3d4a5790]{display:inline-block;position:relative}.login-container .input-box input[data-v-3d4a5790]{outline:none;border-bottom:.02667rem solid #c8b185;border-left-width:0;border-top-width:0;border-right-width:0;text-align:left;padding:0 .8rem;width:6.66667rem;-webkit-box-sizing:border-box;box-sizing:border-box;font-size:.42667rem;border-radius:0}.login-container .van-button[data-v-3d4a5790]{margin-top:1.33333rem;width:6.66667rem} | |||||
| @@ -0,0 +1 @@ | |||||
| (window["webpackJsonp"]=window["webpackJsonp"]||[]).push([["chunk-2d0df214"],{8930:function(t,e,n){"use strict";n.r(e);var s=function(){var t=this,e=t.$createElement,n=t._self._c||e;return n("div",{staticStyle:{height:"calc(100vh - 2.5rem)",overflow:"auto","margin-top":"1.3rem"}},[t.sysConfig?n("van-cell",{attrs:{center:"",title:"报警提醒"}},[[n("van-switch",{attrs:{value:t.checked,size:"24"},on:{input:t.onInput}})]],2):n("div",{staticClass:"van-list__finished-text"},[t._v("服务器异常,请稍后重试~~")]),n("van-row",{attrs:{type:"flex",justify:"space-around"}},[n("van-col",[n("van-button",{attrs:{type:"info",size:"small"},on:{click:t.handleLogout}},[t._v("退出登录")])],1)],1)],1)},i=[],o=n("b970"),a=n("2f62"),c={data(){return{checked:!0}},computed:{...Object(a["c"])(["sysConfig"])},mounted(){this.getSysConfig("limit=10&page=1&sidx=&order=asc&key=IS_NOTIFY_SERVICE").then(t=>{0===t.code&&(this.checked="1"===this.sysConfig["value"])})},methods:{...Object(a["b"])({getSysConfig:"setting/fetchSysConfig",handleSysConfigs:"setting/handleSysConfigs"}),onInput(t){let e=t?"开启":"关闭";o["a"].confirm({title:"提醒",message:`是否${e}报警通知?`}).then(()=>{this.sysConfig["value"]=t?"1":"0",this.handleSysConfigs(this.sysConfig).then(e=>{0===e.code?this.checked=t:o["b"].error("设置失败,请稍后重试~~")})}).catch(()=>{})},handleLogout(){o["a"].confirm({title:"退出登录",message:"是否立即退出登录?"}).then(()=>{this.$store.dispatch("LogOut",(new Date).getTime()).then(t=>{window.location.href="/login"})}).catch(()=>{})}}},l=c,h=n("2877"),r=Object(h["a"])(l,s,i,!1,null,null,null);r.options.__file="index.vue";e["default"]=r.exports}}]); | |||||
| @@ -0,0 +1 @@ | |||||
| (window["webpackJsonp"]=window["webpackJsonp"]||[]).push([["chunk-4ca71562"],{d9c9:function(t,i,e){"use strict";e.r(i);var n=function(){var t=this,i=t.$createElement,e=t._self._c||i;return e("div",{staticClass:"login-container"},[e("header",{staticStyle:{"padding-top":"50px","font-size":"0.7rem"}},[t._v("综合管理平台")]),e("div",[e("div",{staticClass:"input-box",staticStyle:{"margin-top":"100px"}},[e("i",{staticClass:"iconfont icon-username"}),e("input",{directives:[{name:"model",rawName:"v-model",value:t.loginInfo.username,expression:"loginInfo.username"}],attrs:{type:"text"},domProps:{value:t.loginInfo.username},on:{input:function(i){i.target.composing||t.$set(t.loginInfo,"username",i.target.value)}}})]),e("div",{staticClass:"input-box",staticStyle:{"margin-top":"10px"}},[e("i",{staticClass:"iconfont icon-password"}),e("input",{directives:[{name:"model",rawName:"v-model",value:t.loginInfo.password,expression:"loginInfo.password"}],attrs:{type:"password"},domProps:{value:t.loginInfo.password},on:{input:function(i){i.target.composing||t.$set(t.loginInfo,"password",i.target.value)}}})]),e("div",{staticClass:"input-box",staticStyle:{"margin-top":"10px"}},[e("i",{staticClass:"iconfont icon-yanzhengma"}),e("input",{directives:[{name:"model",rawName:"v-model",value:t.loginInfo.captcha,expression:"loginInfo.captcha"}],domProps:{value:t.loginInfo.captcha},on:{input:function(i){i.target.composing||t.$set(t.loginInfo,"captcha",i.target.value)}}}),e("div",{staticStyle:{color:"darkgray",position:"absolute",right:"-2px",bottom:"1px"}},[e("img",{staticStyle:{width:"3.3rem","vertical-align":"middle","line-height":"16px","font-size":"11px","border-radius":"4px 4px 0 0"},attrs:{src:"/platform-framework/captcha.jpg?t="+t.loginInfo.time,alt:"验证码获取失败~~"},on:{click:t.handleClickFreshCaptcha}})])])]),e("van-button",{attrs:{loading:t.isLogin,type:"info"},nativeOn:{click:function(i){return t.login(i)}}},[t._v("登录")])],1)},o=[],a=e("b970"),s=e("ed08"),r={data(){return{loginInfo:{username:"",password:"",captcha:"",time:""},isLogin:!1,redirect:void 0}},created(){this.loginInfo.username=this.$route.query.username||"",this.loginInfo.password=this.$route.query.password||""},mounted(){},watch:{$route:{handler:function(t){this.redirect=t.query&&t.query.redirect},immediate:!0}},methods:{async login(){if(Object(s["a"])(this.loginInfo.username)&&""!==this.loginInfo.password){const{username:i,password:e,captcha:n}=this.loginInfo;if(i&&e&&n){this.isLogin=!0;try{const o=await this.$store.dispatch("Login",`username=${i.trim()}&password=${e}&captcha=${n}`);if(this.isLogin=!1,this.handleClickFreshCaptcha(),0!==o.code)return Object(a["b"])(o.msg);this.$router.push({path:this.redirect||"/"})}catch(t){this.isLogin=!1,Object(a["b"])(t.toString())}}else Object(a["b"])("请检查账号、密码以及验证码是否填写完毕 ~~")}},handleClickFreshCaptcha(){this.loginInfo.time=(new Date).getTime()}}},c=r,l=(e("fc32"),e("2877")),p=Object(l["a"])(c,n,o,!1,null,"3d4a5790",null);p.options.__file="index.vue";i["default"]=p.exports},f565:function(t,i,e){},fc32:function(t,i,e){"use strict";var n=e("f565"),o=e.n(n);o.a}}]); | |||||
| @@ -0,0 +1,48 @@ | |||||
| { | |||||
| "name": "mobile-admin", | |||||
| "version": "0.1.0", | |||||
| "private": true, | |||||
| "scripts": { | |||||
| "dev": "vue-cli-service serve", | |||||
| "build": "vue-cli-service build", | |||||
| "lint": "vue-cli-service lint", | |||||
| "start": "concurrently -k \"npm run server\" \"npm run dev\"" | |||||
| }, | |||||
| "dependencies": { | |||||
| "amfe-flexible": "^2.2.1", | |||||
| "axios": "^0.18.0", | |||||
| "bcryptjs": "^2.4.3", | |||||
| "clipboard": "^2.0.4", | |||||
| "js-cookie": "^2.2.0", | |||||
| "koa": "^2.6.2", | |||||
| "koa-bodyparser": "^4.2.1", | |||||
| "koa-jwt": "^3.5.1", | |||||
| "koa-router": "^7.4.0", | |||||
| "mysql2": "^1.6.4", | |||||
| "vant": "^1.6.28", | |||||
| "vue": "^2.5.17", | |||||
| "vue-router": "^3.0.1", | |||||
| "vuex": "^3.0.1", | |||||
| "weixin-js-sdk": "^1.4.0-test" | |||||
| }, | |||||
| "devDependencies": { | |||||
| "@vue/cli-plugin-eslint": "^3.0.5", | |||||
| "@vue/cli-service": "^3.0.5", | |||||
| "@vue/eslint-config-prettier": "^4.0.0", | |||||
| "babel-core": "^6.26.3", | |||||
| "babel-eslint": "^10.0.1", | |||||
| "babel-preset-env": "^1.7.0", | |||||
| "concurrently": "^4.1.0", | |||||
| "eslint": "^5.8.0", | |||||
| "eslint-plugin-vue": "^5.0.0-0", | |||||
| "ioredis": "^4.2.0", | |||||
| "less": "^3.0.4", | |||||
| "less-loader": "^4.1.0", | |||||
| "node-uuid": "^1.4.8", | |||||
| "nodemon": "^1.18.7", | |||||
| "postcss-pxtorem": "^4.0.1", | |||||
| "request-promise": "^4.2.2", | |||||
| "sha1": "^1.1.1", | |||||
| "vue-template-compiler": "^2.5.17" | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,5 @@ | |||||
| module.exports = { | |||||
| plugins: { | |||||
| autoprefixer: {} | |||||
| } | |||||
| }; | |||||
| @@ -0,0 +1,17 @@ | |||||
| <!DOCTYPE html> | |||||
| <html lang="en"> | |||||
| <head> | |||||
| <meta charset="utf-8"> | |||||
| <meta http-equiv="X-UA-Compatible" content="IE=edge"> | |||||
| <meta name="viewport" content="maximum-scale=1.0,minimum-scale=1.0,user-scalable=1,width=device-width,initial-scale=1.0"/> | |||||
| <link rel="icon" href="<%= BASE_URL %>favicon.ico"> | |||||
| <title>mobile-admin</title> | |||||
| </head> | |||||
| <body style=" background-color: #f7f8fa;"> | |||||
| <noscript> | |||||
| <strong>We're sorry but mobile-admin 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> | |||||
| @@ -0,0 +1,65 @@ | |||||
| <template> | |||||
| <div id="app"> | |||||
| <van-nav-bar v-if="path !== '/login'" :title="navTitle" fixed /> | |||||
| <router-view /> | |||||
| <van-tabbar v-model="active" v-if="path !== '/login'" @change="handleChangeTabbar"> | |||||
| <van-tabbar-item icon="wap-home" :to="{ path: '/' }">首页</van-tabbar-item> | |||||
| <van-tabbar-item icon="setting" :to="{ path: '/setting' }">设置</van-tabbar-item> | |||||
| </van-tabbar> | |||||
| </div> | |||||
| </template> | |||||
| <script> | |||||
| export default { | |||||
| data() { | |||||
| return { | |||||
| navTitle: '警报列表' | |||||
| } | |||||
| }, | |||||
| computed: { | |||||
| path() { | |||||
| return this.$route.path | |||||
| }, | |||||
| active: { | |||||
| get: function() { | |||||
| return this.$route.path === '/' ? 0 : 1 | |||||
| }, | |||||
| set: function() {} | |||||
| } | |||||
| }, | |||||
| mounted() { | |||||
| const navTitle = localStorage.getItem('navTitle') | |||||
| if (navTitle) { | |||||
| this.navTitle = navTitle | |||||
| } else { | |||||
| localStorage.setItem('navTitle', this.navTitle) | |||||
| } | |||||
| }, | |||||
| methods: { | |||||
| handleChangeTabbar(active) { | |||||
| this.navTitle = active === 0 ? '警报列表': '设置中心' | |||||
| localStorage.setItem('navTitle', this.navTitle) | |||||
| } | |||||
| } | |||||
| } | |||||
| </script> | |||||
| <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; | |||||
| overflow: hidden; | |||||
| } | |||||
| a:-webkit-any-link { | |||||
| text-decoration: none; | |||||
| } | |||||
| input:-webkit-autofill { | |||||
| -webkit-box-shadow: 0 0 0px 1000px white inset; | |||||
| } | |||||
| input { | |||||
| filter: none !important; | |||||
| } | |||||
| </style> | |||||
| @@ -0,0 +1,18 @@ | |||||
| import request from '@/utils/request' | |||||
| /* 获取紧急报警列表 */ | |||||
| export function getAlarmList(data) { | |||||
| return request({ | |||||
| url: `/alarm/list?${data}`, | |||||
| method: 'get' | |||||
| }) | |||||
| } | |||||
| /* 处理紧急报警 */ | |||||
| export function handleAlarm(data) { | |||||
| return request({ | |||||
| url: '/alarm/handle', | |||||
| method: 'post', | |||||
| data | |||||
| }) | |||||
| } | |||||
| @@ -0,0 +1,65 @@ | |||||
| import request from '@/utils/request'; | |||||
| // export function login(data) { | |||||
| // return request({ | |||||
| // url: '/user/login', | |||||
| // method: 'post', | |||||
| // data | |||||
| // }) | |||||
| // } | |||||
| // export function getUserInfo(id) { | |||||
| // return request({ | |||||
| // url: '/user/getUserInfo', | |||||
| // method: 'get', | |||||
| // params: { id } | |||||
| // }) | |||||
| // } | |||||
| export function getWxUserInfo(data) { | |||||
| return request({ | |||||
| url: '/user/getWxUserInfo', | |||||
| method: 'post', | |||||
| data | |||||
| }) | |||||
| } | |||||
| export function registerUser(data) { | |||||
| return request({ | |||||
| url: '/user/register', | |||||
| method: 'post', | |||||
| data | |||||
| }) | |||||
| } | |||||
| export function getJsapiSignature(url) { | |||||
| return request({ | |||||
| url: '/user/getJsapiSignature', | |||||
| method: 'get', | |||||
| params: { url } | |||||
| }) | |||||
| } | |||||
| export function checkAuthorizeCode(data) { | |||||
| return request({ | |||||
| url: '/user/checkAuthorizeCode', | |||||
| method: 'post', | |||||
| data | |||||
| }) | |||||
| } | |||||
| export function saveUrlToken(data) { | |||||
| return request({ | |||||
| url: '/user/saveUrlToken', | |||||
| method: 'post', | |||||
| data | |||||
| }) | |||||
| } | |||||
| export function getProxyList(data) { | |||||
| return request({ | |||||
| url: '/user/getProxyList', | |||||
| method: 'post', | |||||
| data | |||||
| }) | |||||
| } | |||||
| @@ -0,0 +1,18 @@ | |||||
| import request from '@/utils/request' | |||||
| /* 获取系统参数配置 */ | |||||
| export function getSysConfig(data) { | |||||
| return request({ | |||||
| url: `/sys/config/list?${data}`, | |||||
| method: 'get' | |||||
| }) | |||||
| } | |||||
| /* 修改系统参数配置 */ | |||||
| export function handleSysConfig(data) { | |||||
| return request({ | |||||
| url: `/sys/config/update`, | |||||
| method: 'post', | |||||
| data | |||||
| }) | |||||
| } | |||||
| @@ -0,0 +1,26 @@ | |||||
| import request from '@/utils/request' | |||||
| /* 登录 */ | |||||
| export function login(data) { | |||||
| return request({ | |||||
| url: '/sys/login', | |||||
| method: 'post', | |||||
| data | |||||
| }) | |||||
| } | |||||
| /* 获取用户信息 */ | |||||
| export function getInfo(time) { | |||||
| return request({ | |||||
| url: `/sys/user/info?${time}`, | |||||
| method: 'get' | |||||
| }) | |||||
| } | |||||
| /* 退出登录 */ | |||||
| export function logout(time) { | |||||
| return request({ | |||||
| url: `/logout?${time}`, | |||||
| method: 'get' | |||||
| }) | |||||
| } | |||||
| @@ -0,0 +1,18 @@ | |||||
| import Vue from "vue" | |||||
| import App from "./App.vue" | |||||
| import router from "@/router" | |||||
| import store from "@/store" | |||||
| import '@/styles/index.less' // global css | |||||
| import '@/permission' // permission control | |||||
| import Vant from 'vant' | |||||
| import 'vant/lib/index.css' | |||||
| import 'amfe-flexible' | |||||
| Vue.use(Vant) | |||||
| Vue.config.productionTip = false | |||||
| new Vue({ | |||||
| router, | |||||
| store, | |||||
| render: h => h(App) | |||||
| }).$mount("#app") | |||||
| @@ -0,0 +1,38 @@ | |||||
| import router from '@/router'; | |||||
| import store from '@/store'; | |||||
| import { getToken } from '@/utils/auth'; // 验权 | |||||
| const whiteList = ['/login']; // 不重定向白名单 | |||||
| router.beforeEach(async (to, from, next) => { | |||||
| if (getToken()) { | |||||
| if (to.path === '/login') { | |||||
| next({ path: '/' }) | |||||
| } else { | |||||
| if (!store.getters.userInfo.userId) { | |||||
| // store.dispatch('GetUserInfo').then(res => { | |||||
| // // 如果拉取用户信息成功则跳转页面,否则重新登录 | |||||
| // if (res) next() | |||||
| // else store.dispatch('FedLogOut').then(() => { next({ path: '/' }) }) | |||||
| // }).catch(err => { | |||||
| // store.dispatch('FedLogOut').then(() => { | |||||
| // next({ path: '/' }) | |||||
| // }); | |||||
| // }) | |||||
| const res = await store.dispatch('GetUserInfo') | |||||
| if (res === 0) next() | |||||
| else store.dispatch('FedLogOut').then(() => { | |||||
| //next({ path: '/' }) | |||||
| next(`/login?redirect=${to.path}`) | |||||
| }) | |||||
| } else { | |||||
| next() | |||||
| } | |||||
| } | |||||
| } else { | |||||
| if (whiteList.indexOf(to.path) !== -1 || whiteList.indexOf(to.path.split('to/')[0] + 'to') !== -1) { | |||||
| next() | |||||
| } else { | |||||
| next(`/login?redirect=${to.path}`) | |||||
| } | |||||
| } | |||||
| }) | |||||
| @@ -0,0 +1,76 @@ | |||||
| import Vue from 'vue'; | |||||
| import Router from 'vue-router'; | |||||
| import Home from '@/views/Home.vue'; | |||||
| Vue.use(Router); | |||||
| export default new Router({ | |||||
| mode: 'history', | |||||
| // base: process.env.BASE_URL, | |||||
| routes: [ | |||||
| { | |||||
| path: '/login', | |||||
| component: () => import('@/views/Login/index'), | |||||
| hidden: true | |||||
| }, | |||||
| { | |||||
| path: '/', | |||||
| name: 'home', | |||||
| component: Home, | |||||
| meta: { | |||||
| // 页面标题title | |||||
| title: '警报列表' | |||||
| } | |||||
| }, | |||||
| { | |||||
| path: '/setting', | |||||
| name: 'setting', | |||||
| component: () => import('@/views/Setting/index'), | |||||
| meta: { | |||||
| // 页面标题title | |||||
| title: '设置中心' | |||||
| } | |||||
| } | |||||
| // { | |||||
| // path: '/answer', | |||||
| // name: 'answer', | |||||
| // // 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/Answer') | |||||
| // }, | |||||
| // { | |||||
| // path: '/personal', | |||||
| // name: 'personal', | |||||
| // component: () => import('@/views/Personal') | |||||
| // }, | |||||
| // { | |||||
| // path: '/personal/order', | |||||
| // component: () => import('@/views/Personal/Order') | |||||
| // }, | |||||
| // { | |||||
| // path: '/personal/address', | |||||
| // component: () => import('@/views/Personal/Address') | |||||
| // }, | |||||
| // { | |||||
| // path: '/personal/develop', | |||||
| // component: () => import('@/views/Personal/Develop') | |||||
| // }, | |||||
| // { | |||||
| // path: '/personal/develop/share', | |||||
| // component: () => import('@/views/Personal/Develop/Share') | |||||
| // }, | |||||
| // { | |||||
| // path: '/personal/develop/to/:state', | |||||
| // component: () => import('@/views/Personal/Develop/To') | |||||
| // }, | |||||
| // { | |||||
| // path: '/login', | |||||
| // component: () => import('@/views/Login') | |||||
| // }, | |||||
| // { | |||||
| // path: '/product/list', | |||||
| // component: () => import('@/views/Product') | |||||
| // } | |||||
| ] | |||||
| }); | |||||
| @@ -0,0 +1,8 @@ | |||||
| const getters = { | |||||
| token: state => state.user.token, | |||||
| userInfo: state => state.user.userInfo, | |||||
| alarmList: state => state.alarm.alarmList, | |||||
| alarmMsg: state => state.alarm.alarmMsg, | |||||
| sysConfig: state => state.setting.sysConfig, | |||||
| } | |||||
| export default getters | |||||
| @@ -0,0 +1,19 @@ | |||||
| import Vue from 'vue'; | |||||
| import Vuex from 'vuex'; | |||||
| import user from './modules/user'; | |||||
| import alarm from './modules/alarm'; | |||||
| import setting from './modules/setting'; | |||||
| import getters from './getters'; | |||||
| Vue.use(Vuex) | |||||
| const store = new Vuex.Store({ | |||||
| modules: { | |||||
| user, | |||||
| alarm, | |||||
| setting | |||||
| }, | |||||
| getters | |||||
| }) | |||||
| export default store | |||||
| @@ -0,0 +1,63 @@ | |||||
| import { getAlarmList, handleAlarm } from '@/api/alarm' | |||||
| const state = { | |||||
| alarmList: '', | |||||
| alarmMsg: '' | |||||
| } | |||||
| const mutations = { | |||||
| SET_ALARM_LIST: (state, payload) => { | |||||
| state.alarmList = payload | |||||
| }, | |||||
| SET_ALARM_MSG: (state, payload) => { | |||||
| state.alarmMsg = payload | |||||
| } | |||||
| } | |||||
| const actions = { | |||||
| fetchAlarmList({ commit }, option) { | |||||
| return new Promise((resolve, reject) => { | |||||
| getAlarmList(option).then((res) => { | |||||
| if (res.code === 0) { | |||||
| const { page } = res | |||||
| commit('SET_ALARM_LIST', page.list) | |||||
| } | |||||
| if (res.msg == '没有权限,请联系管理员授权') { | |||||
| commit('SET_ALARM_LIST', []) | |||||
| } | |||||
| resolve(res) | |||||
| }).catch((err) => { | |||||
| reject(err) | |||||
| }) | |||||
| }) | |||||
| }, | |||||
| handleAlarms({ commit }, ids) { | |||||
| return new Promise((resolve, reject) => { | |||||
| handleAlarm(ids).then(res => { | |||||
| resolve(res) | |||||
| }).catch(err => { | |||||
| reject(err) | |||||
| }) | |||||
| }) | |||||
| } | |||||
| // fetchVideoMsg({ commit }, videoId) { | |||||
| // return new Promise((resolve, reject) => { | |||||
| // getVideoMsg(videoId).then((res) => { | |||||
| // const { video } = res | |||||
| // video['label'] = video['label'] ? video['label'].split(',') : [] | |||||
| // commit('SET_VIDEO_MSG', video) | |||||
| // resolve() | |||||
| // }).catch((err) => { | |||||
| // reject(err) | |||||
| // }) | |||||
| // }) | |||||
| // }, | |||||
| } | |||||
| export default { | |||||
| namespaced: true, | |||||
| state, | |||||
| mutations, | |||||
| actions | |||||
| } | |||||
| @@ -0,0 +1,47 @@ | |||||
| import { getSysConfig, handleSysConfig } from '@/api/setting' | |||||
| const state = { | |||||
| sysConfig: '' | |||||
| } | |||||
| const mutations = { | |||||
| SET_SYS_CONFIG: (state, payload) => { | |||||
| state.sysConfig = payload | |||||
| } | |||||
| } | |||||
| const actions = { | |||||
| fetchSysConfig({ commit }, option) { | |||||
| return new Promise((resolve, reject) => { | |||||
| getSysConfig(option).then((res) => { | |||||
| if (res.code === 0) { | |||||
| const { page } = res | |||||
| commit('SET_SYS_CONFIG', ...page.list) | |||||
| } | |||||
| if (res.msg == '没有权限,请联系管理员授权') { | |||||
| commit('SET_SYS_CONFIG', '') | |||||
| } | |||||
| resolve(res) | |||||
| }).catch((err) => { | |||||
| reject(err) | |||||
| }) | |||||
| }) | |||||
| }, | |||||
| handleSysConfigs({ commit }, option) { | |||||
| return new Promise((resolve, reject) => { | |||||
| handleSysConfig(option).then(res => { | |||||
| resolve(res) | |||||
| }).catch(err => { | |||||
| reject(err) | |||||
| }) | |||||
| }) | |||||
| } | |||||
| } | |||||
| export default { | |||||
| namespaced: true, | |||||
| state, | |||||
| mutations, | |||||
| actions | |||||
| } | |||||
| @@ -0,0 +1,82 @@ | |||||
| import { login, getInfo, logout } from '@/api/user' | |||||
| import { getToken, setToken, removeToken } from '@/utils/auth' | |||||
| import { uuid } from '@/utils' | |||||
| const user = { | |||||
| state: { | |||||
| token: getToken(), | |||||
| userInfo: {} | |||||
| }, | |||||
| mutations: { | |||||
| SET_TOKEN: (state, token) => { | |||||
| state.token = token | |||||
| }, | |||||
| SET_USERINFO: (state, userInfo) => { | |||||
| state.userInfo = userInfo | |||||
| } | |||||
| }, | |||||
| actions: { | |||||
| // 登录 | |||||
| Login({ commit }, loginInfo) { | |||||
| return new Promise((resolve, reject) => { | |||||
| login(loginInfo).then(data => { | |||||
| // const { success, msg, authData } = data | |||||
| //console.log(data, 'login success') | |||||
| // resolve({ success, msg }) | |||||
| const { code } = data | |||||
| resolve(data) | |||||
| if (code !== 0) return | |||||
| const token = uuid() | |||||
| setToken(token) | |||||
| commit('SET_TOKEN', token) | |||||
| //setToken(authData.token) | |||||
| //commit('SET_TOKEN', authData.token) | |||||
| }).catch(error => { | |||||
| reject(error) | |||||
| }) | |||||
| }) | |||||
| }, | |||||
| // 获取用户信息 | |||||
| GetUserInfo({ commit, state }) { | |||||
| return new Promise((resolve, reject) => { | |||||
| getInfo(new Date().getTime()).then(data => { | |||||
| const { code, user } = data | |||||
| if (code === 0) commit('SET_USERINFO', user) | |||||
| resolve(code) | |||||
| }).catch(error => { | |||||
| reject(error) | |||||
| }) | |||||
| }) | |||||
| }, | |||||
| // 登出 | |||||
| LogOut({ commit, time }) { | |||||
| return new Promise((resolve, reject) => { | |||||
| logout(time) | |||||
| .then(() => { | |||||
| commit('SET_TOKEN', '') | |||||
| //commit('SET_ROLES', []) | |||||
| removeToken() | |||||
| resolve() | |||||
| }) | |||||
| .catch(error => { | |||||
| reject(error) | |||||
| }) | |||||
| }) | |||||
| }, | |||||
| // 前端 登出 | |||||
| FedLogOut({ commit }) { | |||||
| return new Promise(resolve => { | |||||
| commit('SET_TOKEN', '') | |||||
| removeToken() | |||||
| resolve() | |||||
| }) | |||||
| } | |||||
| } | |||||
| } | |||||
| export default user | |||||
| @@ -0,0 +1,35 @@ | |||||
| @font-face { | |||||
| font-family: 'iconfont'; /* project id 927880 */ | |||||
| src: url('//at.alicdn.com/t/font_927880_2ihl8qth6yg.eot'); | |||||
| src: url('//at.alicdn.com/t/font_927880_2ihl8qth6yg.eot?#iefix') format('embedded-opentype'), | |||||
| url('//at.alicdn.com/t/font_927880_2ihl8qth6yg.woff') format('woff'), | |||||
| url('//at.alicdn.com/t/font_927880_2ihl8qth6yg.ttf') format('truetype'), | |||||
| url('//at.alicdn.com/t/font_927880_2ihl8qth6yg.svg#iconfont') format('svg'); | |||||
| } | |||||
| @font-face { | |||||
| font-family: 'iconfont'; /* Project id 2723835 */ | |||||
| src: url('//at.alicdn.com/t/font_2723835_y1jsf7gbkz.woff2?t=1628136189738') format('woff2'), | |||||
| url('//at.alicdn.com/t/font_2723835_y1jsf7gbkz.woff?t=1628136189738') format('woff'), | |||||
| url('//at.alicdn.com/t/font_2723835_y1jsf7gbkz.ttf?t=1628136189738') format('truetype'); | |||||
| } | |||||
| .iconfont { | |||||
| font-family:"iconfont" !important; | |||||
| font-size: 28px; | |||||
| font-style:normal; | |||||
| -webkit-font-smoothing: antialiased; | |||||
| -moz-osx-font-smoothing: grayscale; | |||||
| } | |||||
| .icon-home:before { content: "\e620"; } | |||||
| .icon-shu:before { content: "\e634"; } | |||||
| .icon-ziyuan:before { content: "\e621"; } | |||||
| .icon-username:before { content: "\eac3"; position: absolute; left: -5px; bottom: 2px; font-size: 22px;} | |||||
| .icon-password:before { content: "\eac2"; position: absolute; left: -5px; bottom: 1px; font-size: 24px;} | |||||
| .icon-yanzhengma:before { content: "\e63f"; position: absolute; left: -2px; bottom: 3px; font-size: 18px; font-weight: bold;} | |||||
| @@ -0,0 +1,14 @@ | |||||
| @import './icon.less'; | |||||
| // .van-tabs__nav--card { | |||||
| // border: 1px solid #c8b185 !important; | |||||
| // .van-tab { | |||||
| // color: #c8b185 !important; | |||||
| // border-right: 1px solid #c8b185 !important; | |||||
| // } | |||||
| // .van-tab--active { | |||||
| // color: #fff!important; | |||||
| // background-color: #c8b185 !important; | |||||
| // } | |||||
| // } | |||||
| @@ -0,0 +1,15 @@ | |||||
| import Cookies from 'js-cookie'; | |||||
| const TokenKey = 'User-Token'; | |||||
| export function getToken() { | |||||
| return Cookies.get(TokenKey) | |||||
| } | |||||
| export function setToken(token) { | |||||
| return Cookies.set(TokenKey, token) | |||||
| } | |||||
| export function removeToken() { | |||||
| return Cookies.remove(TokenKey) | |||||
| } | |||||
| @@ -0,0 +1,74 @@ | |||||
| /* 合法手机号*/ | |||||
| export function checkPhone(value) { | |||||
| const reg = /^1[34578]\d{9}$/; | |||||
| return reg.test(value) | |||||
| } | |||||
| export function param2Obj(url) { | |||||
| const search = url.split('?')[1] | |||||
| if (!search) { | |||||
| return {} | |||||
| } | |||||
| return JSON.parse( | |||||
| '{"' + | |||||
| decodeURIComponent(search) | |||||
| .replace(/"/g, '\\"') | |||||
| .replace(/&/g, '","') | |||||
| .replace(/=/g, '":"') + | |||||
| '"}' | |||||
| ) | |||||
| } | |||||
| export function trim(str) { | |||||
| return str.replace(/(^\s*)|(\s*$)/g, "") | |||||
| } | |||||
| export function check_user_name(str) { | |||||
| var str2 = "该用户名合法"; | |||||
| if ("" == str) { | |||||
| str2 = "用户名为空"; | |||||
| return str2; | |||||
| } else if ((str.length < 5) || (str.length > 20)) { | |||||
| str2 = "用户名必须为5 ~ 20位"; | |||||
| return str2; | |||||
| } else if (check_other_char(str)) { | |||||
| str2 = "不能含有特殊字符"; | |||||
| return str2; | |||||
| } | |||||
| return str2; | |||||
| } | |||||
| // 验证用户名是否含有特殊字符 | |||||
| function check_other_char(str) { | |||||
| var arr = ["&", "\\", "/", "*", ">", "<", "@", "!"]; | |||||
| for (var i = 0; i < arr.length; i++) { | |||||
| for (var j = 0; j < str.length; j++) { | |||||
| if (arr[i] == str.charAt(j)) { | |||||
| return true; | |||||
| } | |||||
| } | |||||
| } | |||||
| return false; | |||||
| } | |||||
| export function getUrlToken() { | |||||
| let urlToken = '' | |||||
| for (let i = 0; i < 6; i++) { | |||||
| urlToken += Math.floor(Math.random() * 10) | |||||
| } | |||||
| const date = new Date() | |||||
| return urlToken = date.getFullYear() + '' + (date.getMonth() + 1) + '' + date.getDate() + '' + urlToken | |||||
| } | |||||
| export function uuid() { | |||||
| const s = [] | |||||
| const hexDigits = '0123456789abcdef' | |||||
| for (let i = 0; i < 36; i++) { | |||||
| s[i] = hexDigits.substr(Math.floor(Math.random() * 0x10), 1) | |||||
| } | |||||
| s[14] = '4' // bits 12-15 of the time_hi_and_version field to 0010 | |||||
| s[19] = hexDigits.substr((s[19] & 0x3) | 0x8, 1) // bits 6-7 of the clock_seq_hi_and_reserved to 01 | |||||
| s[8] = s[13] = s[18] = s[23] = '-' | |||||
| const uuid = s.join('') | |||||
| return uuid | |||||
| }; | |||||
| @@ -0,0 +1,98 @@ | |||||
| import axios from 'axios'; | |||||
| import store from '@/store'; | |||||
| import { getToken } from '@/utils/auth'; | |||||
| // 创建axios实例 | |||||
| const service = axios.create({ | |||||
| baseURL: '/platform-framework', // api 的 base_url | |||||
| timeout: 5000 // 请求超时时间 | |||||
| }) | |||||
| // request拦截器 | |||||
| service.interceptors.request.use( | |||||
| config => { | |||||
| // if (store.getters.token) { | |||||
| // config.headers.authorization = getToken() // jwt token | |||||
| // } | |||||
| return config | |||||
| }, | |||||
| error => { | |||||
| // Do something with request error | |||||
| // console.log(error) // for debug | |||||
| Promise.reject(error) | |||||
| } | |||||
| ) | |||||
| // response 拦截器 | |||||
| service.interceptors.response.use( | |||||
| // response => response, | |||||
| /** | |||||
| * 下面的注释为通过在response里,自定义code来标示请求状态 | |||||
| * 当code返回如下情况则说明权限有问题,登出并返回到登录页 | |||||
| * 如想通过 xmlhttprequest 来状态码标识 逻辑可写在下面error中 | |||||
| * 以下代码均为样例,请结合自生需求加以修改,若不需要,则可删除 | |||||
| */ | |||||
| res => { | |||||
| // const res = response.data | |||||
| // if (res.code !== 20000 && res.code !== 0) { | |||||
| // Message({ | |||||
| // message: res.message, | |||||
| // type: 'error', | |||||
| // duration: 5 * 1000 | |||||
| // }) | |||||
| // // 50008:非法的token; 50012:其他客户端登录了; 50014:Token 过期了; | |||||
| // if (res.code === 50008 || res.code === 50012 || res.code === 50014) { | |||||
| // // 请自行在引入 MessageBox | |||||
| // // import { Message, MessageBox } from 'element-ui' | |||||
| // MessageBox.confirm('你已被登出,可以取消继续留在该页面,或者重新登录', '确定登出', { | |||||
| // confirmButtonText: '重新登录', | |||||
| // cancelButtonText: '取消', | |||||
| // type: 'warning' | |||||
| // }).then(() => { | |||||
| // store.dispatch('FedLogOut').then(() => { | |||||
| // location.reload() // 为了重新实例化vue-router对象 避免bug | |||||
| // }) | |||||
| // }) | |||||
| // } | |||||
| // return Promise.reject('error') | |||||
| // } else { | |||||
| // return response.data | |||||
| // } | |||||
| if (res.code && res.code !== 0) { | |||||
| Message({ | |||||
| message: res.msg || 'Error', | |||||
| type: 'error', | |||||
| duration: 5 * 1000 | |||||
| }) | |||||
| // 50008: Illegal token; 50012: Other clients logged in; 50014: Token expired; | |||||
| if (res.code && res.code === 401 || res.msg == "没有权限,请联系管理员授权") { | |||||
| // to re-login | |||||
| MessageBox.confirm('您已经退出登录,请重新重新登录', '退出登录', { | |||||
| confirmButtonText: '重新登录', | |||||
| // cancelButtonText: '返回', | |||||
| showCancelButton: false, | |||||
| type: 'warning' | |||||
| }).then(() => { | |||||
| store.dispatch('FedLogOut').then(() => { | |||||
| location.reload() | |||||
| }) | |||||
| }) | |||||
| } | |||||
| return Promise.reject(new Error(res.msg || 'Error')) | |||||
| } else { | |||||
| return res.data || res | |||||
| } | |||||
| }, | |||||
| error => { | |||||
| console.log('err' + error) // for debug | |||||
| // Message({ | |||||
| // message: error.message, | |||||
| // type: 'error', | |||||
| // duration: 5 * 1000 | |||||
| // }) | |||||
| return Promise.reject(error) | |||||
| } | |||||
| ) | |||||
| export default service | |||||
| @@ -0,0 +1,122 @@ | |||||
| <template> | |||||
| <div style="height: calc(100vh - 2.5rem); overflow: auto; margin-top: 1.3rem;"> | |||||
| <van-pull-refresh v-model="refreshing" @refresh="onRefresh"> | |||||
| <van-list | |||||
| v-model="loading" | |||||
| :finished="finished" | |||||
| :finished-text="finishedText" | |||||
| @load="onLoad" | |||||
| > | |||||
| <van-cell v-for="item in list" :key="item.id" class="panel-container"> | |||||
| <van-panel :title="`${item.userName ? item.userName : ''} ${item.userMobile ? item.userMobile : ''}`" :desc="`${item.createTime}`" status="紧急报警"> | |||||
| <div class="panel-content"> | |||||
| <div style="font-size: 0.27rem;" v-if="item.address && item.longitude !== 0 && item.latitude !== 0">设备{{item.imei}},在{{item.address}}附近发起紧急报警。</div> | |||||
| <div style="font-size: 0.27rem;" v-else>设备{{item.imei}}, {{item.address}}</div> | |||||
| <div style="text-align: right"> | |||||
| <van-button size="small" type="primary" @click.native="handleDetailAlarm(item)">处理</van-button> | |||||
| </div> | |||||
| </div> | |||||
| </van-panel> | |||||
| </van-cell> | |||||
| </van-list> | |||||
| </van-pull-refresh> | |||||
| </div> | |||||
| </template> | |||||
| <script> | |||||
| import { Toast, Dialog } from "vant"; | |||||
| import { mapGetters, mapActions } from "vuex"; | |||||
| export default { | |||||
| data() { | |||||
| return { | |||||
| list: [], | |||||
| dialogLoading: false, | |||||
| loading: false, | |||||
| finished: false, | |||||
| refreshing: false, | |||||
| page: 1, | |||||
| finishedText: '已经到底啦~~' | |||||
| }; | |||||
| }, | |||||
| computed: { | |||||
| ...mapGetters(["alarmList"]), | |||||
| }, | |||||
| methods: { | |||||
| ...mapActions({ | |||||
| getAlarmList: "alarm/fetchAlarmList", | |||||
| handleAlarms: "alarm/handleAlarms" | |||||
| }), | |||||
| onLoad() { | |||||
| setTimeout(() => { | |||||
| if (this.refreshing) { | |||||
| this.list = []; | |||||
| this.refreshing = false; | |||||
| } | |||||
| this.getAlarmList(`startTime=&endTime=&state=0&limit=10&page=${this.page}&type=0&sidx=&order=asc&serviceTime=1`).then((res) => { | |||||
| this.loading = false; | |||||
| if (res.code === 0) { | |||||
| this.list.push(...this.alarmList); | |||||
| if (this.page == res.totalPage) { | |||||
| this.finishedText = '已经到底啦~~' | |||||
| this.finished = true; | |||||
| } | |||||
| this.page++; | |||||
| } else { | |||||
| this.finished = true; | |||||
| this.finishedText = '服务器异常,请稍后重试~~' | |||||
| } | |||||
| }); | |||||
| }, 500); | |||||
| }, | |||||
| onRefresh() { | |||||
| // 清空列表数据 | |||||
| this.finished = false; | |||||
| // 重新加载数据 | |||||
| // 将 loading 设置为 true,表示处于加载状态 | |||||
| this.loading = true; | |||||
| this.page = 1; | |||||
| this.onLoad(); | |||||
| }, | |||||
| handleDetailAlarm(alarm) { | |||||
| Dialog.confirm({ | |||||
| title: '报警处理', | |||||
| message: '是否处理该紧急报警?', | |||||
| beforeClose: (action, done) => { | |||||
| if (action === 'confirm') { | |||||
| this.handleAlarms([alarm.id]).then(res => { | |||||
| if (res.code === 0) { | |||||
| Toast.success('处理成功!'); | |||||
| this.list = [] | |||||
| this.onRefresh() | |||||
| } | |||||
| done() | |||||
| }) | |||||
| } else done() | |||||
| } | |||||
| }).catch(() => { | |||||
| console.log('返回') | |||||
| }) | |||||
| } | |||||
| }, | |||||
| }; | |||||
| </script> | |||||
| <style lang="less"> | |||||
| .panel-container { | |||||
| margin-bottom: 5px; | |||||
| .panel-content { | |||||
| padding: 0.26667rem 0.4rem; | |||||
| } | |||||
| } | |||||
| .van-hairline--top-bottom::after { | |||||
| border: none !important; | |||||
| } | |||||
| .van-cell { | |||||
| padding-bottom: 0 !important; | |||||
| .van-cell__title { | |||||
| flex: 3; | |||||
| } | |||||
| } | |||||
| </style> | |||||
| @@ -0,0 +1,127 @@ | |||||
| <template> | |||||
| <div class="login-container"> | |||||
| <header style="padding-top: 50px;font-size: 0.7rem;">综合管理平台</header> | |||||
| <div> | |||||
| <div class="input-box" style="margin-top: 100px;"> | |||||
| <i class="iconfont icon-username" /> | |||||
| <input v-model="loginInfo.username" type="text"> | |||||
| </div> | |||||
| <div class="input-box" style="margin-top: 10px;"> | |||||
| <i class="iconfont icon-password" /> | |||||
| <input v-model="loginInfo.password" type="password"> | |||||
| </div> | |||||
| <div class="input-box" style="margin-top: 10px;"> | |||||
| <i class="iconfont icon-yanzhengma" /> | |||||
| <input v-model="loginInfo.captcha"> | |||||
| <div style="color: darkgray;position: absolute;right: -2px; bottom: 1px;"> | |||||
| <img | |||||
| :src="`/platform-framework/captcha.jpg?t=${loginInfo.time}`" | |||||
| alt="验证码获取失败~~" | |||||
| style="width: 3.3rem;vertical-align: middle;line-height: 16px; font-size: 11px;border-radius: 4px 4px 0 0;" | |||||
| @click="handleClickFreshCaptcha" | |||||
| > | |||||
| </div> | |||||
| </div> | |||||
| </div> | |||||
| <van-button :loading="isLogin" type="info" @click.native="login">登录</van-button> | |||||
| </div> | |||||
| </template> | |||||
| <script> | |||||
| import { Toast } from "vant"; | |||||
| import { check_user_name } from "@/utils"; | |||||
| export default { | |||||
| data() { | |||||
| return { | |||||
| loginInfo: { | |||||
| username: "", | |||||
| password: "", | |||||
| captcha: "", | |||||
| time: "", | |||||
| }, | |||||
| isLogin: false, | |||||
| redirect: undefined, | |||||
| }; | |||||
| }, | |||||
| created() { | |||||
| this.loginInfo.username = this.$route.query.username || ""; | |||||
| this.loginInfo.password = this.$route.query.password || ""; | |||||
| }, | |||||
| mounted() { | |||||
| }, | |||||
| watch: { | |||||
| $route: { | |||||
| handler: function(route) { | |||||
| this.redirect = route.query && route.query.redirect; | |||||
| }, | |||||
| immediate: true, | |||||
| }, | |||||
| }, | |||||
| methods: { | |||||
| async login() { | |||||
| if ( | |||||
| check_user_name(this.loginInfo.username) && | |||||
| this.loginInfo.password !== "" | |||||
| ) { | |||||
| // 调用登录接口 | |||||
| // 登录成功后继续跳转到被拦截的页面 this.$router.push({ path: this.redirect }) | |||||
| const { username, password, captcha } = this.loginInfo | |||||
| if (username && password && captcha) { | |||||
| this.isLogin = true; | |||||
| try { | |||||
| const res = await this.$store.dispatch("Login", `username=${username.trim()}&password=${password}&captcha=${captcha}`); | |||||
| this.isLogin = false; | |||||
| this.handleClickFreshCaptcha(); | |||||
| if (res.code !== 0) return Toast(res.msg); | |||||
| this.$router.push({ path: this.redirect || "/" }); | |||||
| } catch (e) { | |||||
| this.isLogin = false; | |||||
| Toast(e.toString()); | |||||
| } | |||||
| } else { | |||||
| Toast('请检查账号、密码以及验证码是否填写完毕 ~~'); | |||||
| } | |||||
| } | |||||
| }, | |||||
| handleClickFreshCaptcha() { | |||||
| this.loginInfo.time = new Date().getTime() | |||||
| } | |||||
| }, | |||||
| }; | |||||
| </script> | |||||
| <style lang="less" scoped> | |||||
| .login-container { | |||||
| height: 100vh; | |||||
| // display: flex; | |||||
| // align-items: center; | |||||
| // flex-direction: column; | |||||
| // justify-content: center; | |||||
| // padding: 0 10px; | |||||
| background: #fff !important; | |||||
| text-align: center; | |||||
| .input-box { | |||||
| display: inline-block; | |||||
| position: relative; | |||||
| input { | |||||
| outline: none; | |||||
| border-bottom: 1px solid #c8b185; | |||||
| border-left-width: 0px; | |||||
| border-top-width: 0px; | |||||
| border-right-width: 0px; | |||||
| text-align: left; | |||||
| padding: 0 30px; | |||||
| width: 250px; | |||||
| box-sizing: border-box; | |||||
| font-size: 16px; | |||||
| border-radius: 0; | |||||
| } | |||||
| } | |||||
| .van-button { | |||||
| margin-top: 50px; | |||||
| width: 250px; | |||||
| // background: #c8b185; | |||||
| // color: #fff; | |||||
| } | |||||
| } | |||||
| </style> | |||||
| @@ -0,0 +1,71 @@ | |||||
| <template> | |||||
| <div style="height: calc(100vh - 2.5rem); overflow: auto; margin-top: 1.3rem;"> | |||||
| <van-cell center title="报警提醒" v-if="sysConfig"> | |||||
| <template #right-icon> | |||||
| <van-switch :value="checked" @input="onInput" size="24" /> | |||||
| </template> | |||||
| </van-cell> | |||||
| <div class="van-list__finished-text" v-else>服务器异常,请稍后重试~~</div> | |||||
| <van-row type="flex" justify="space-around"> | |||||
| <van-col> | |||||
| <van-button type="info" size="small" @click="handleLogout">退出登录</van-button> | |||||
| </van-col> | |||||
| </van-row> | |||||
| </div> | |||||
| </template> | |||||
| <script> | |||||
| import { Toast, Dialog } from "vant"; | |||||
| import { mapGetters, mapActions } from "vuex"; | |||||
| export default { | |||||
| data() { | |||||
| return { | |||||
| checked: true | |||||
| }; | |||||
| }, | |||||
| computed: { | |||||
| ...mapGetters(["sysConfig"]), | |||||
| }, | |||||
| mounted() { | |||||
| this.getSysConfig('limit=10&page=1&sidx=&order=asc&key=IS_NOTIFY_SERVICE').then(res => { | |||||
| if (res.code === 0) { | |||||
| this.checked = this.sysConfig['value'] === '1' ? true : false | |||||
| } | |||||
| }) | |||||
| }, | |||||
| methods: { | |||||
| ...mapActions({ | |||||
| getSysConfig: "setting/fetchSysConfig", | |||||
| handleSysConfigs: "setting/handleSysConfigs", | |||||
| }), | |||||
| onInput(checked) { | |||||
| let msg = checked ? '开启' : '关闭' | |||||
| Dialog.confirm({ | |||||
| title: '提醒', | |||||
| message: `是否${msg}报警通知?`, | |||||
| }).then(() => { | |||||
| this.sysConfig['value'] = checked ? '1' : '0' | |||||
| this.handleSysConfigs(this.sysConfig).then(res => { | |||||
| if (res.code === 0) { | |||||
| this.checked = checked; | |||||
| } else { | |||||
| Toast.error('设置失败,请稍后重试~~'); | |||||
| } | |||||
| }) | |||||
| }).catch(() => {}) | |||||
| }, | |||||
| handleLogout() { | |||||
| Dialog.confirm({ | |||||
| title: '退出登录', | |||||
| message: `是否立即退出登录?`, | |||||
| }).then(() => { | |||||
| this.$store.dispatch('LogOut', new Date().getTime()).then(res => { | |||||
| //this.$router.push(`/login?redirect=${this.$route.fullPath}`) | |||||
| window.location.href = '/login' | |||||
| }) | |||||
| }).catch(() => {}) | |||||
| } | |||||
| }, | |||||
| } | |||||
| </script> | |||||
| @@ -0,0 +1,40 @@ | |||||
| const autoprefixer = require('autoprefixer') | |||||
| const pxtorem = require('postcss-pxtorem') | |||||
| module.exports = { | |||||
| outputDir: 'docs', | |||||
| baseUrl: '/', | |||||
| assetsDir: 'static', | |||||
| productionSourceMap: false, | |||||
| css: { | |||||
| loaderOptions: { | |||||
| postcss: { | |||||
| plugins: [ | |||||
| autoprefixer(), | |||||
| pxtorem({ | |||||
| rootValue: 37.5, | |||||
| propList: ['*'] | |||||
| }) | |||||
| ] | |||||
| } | |||||
| } | |||||
| }, | |||||
| devServer: { | |||||
| port: 9090, // 端口号 | |||||
| https: false, // https:{type:Boolean} | |||||
| open: true, //配置自动启动浏览器 | |||||
| disableHostCheck: true, | |||||
| proxy: { | |||||
| // '/api': { | |||||
| // target: 'http://localhost:8889', | |||||
| // changeOrigin: true | |||||
| // }, | |||||
| '/platform-framework': { | |||||
| // target: `http://127.0.0.1:${port}/mock`, | |||||
| target: `http://192.168.1.83:8080`, | |||||
| // target: 'http://192.168.1.169:8086/', | |||||
| changeOrigin: true | |||||
| } | |||||
| } | |||||
| } | |||||
| } | |||||