Browse Source

登录功能开发

master
yxq 5 months ago
parent
commit
018f22697d
13 changed files with 221 additions and 94 deletions
  1. +10
    -1
      monitorMobile/api/user.js
  2. +3
    -10
      monitorMobile/common/mixins.vue
  3. +2
    -12
      monitorMobile/common/setting.js
  4. +29
    -20
      monitorMobile/http/api.js
  5. +15
    -0
      monitorMobile/manifest.json
  6. +14
    -0
      monitorMobile/package-lock.json
  7. +1
    -0
      monitorMobile/package.json
  8. +32
    -28
      monitorMobile/pages.json
  9. +24
    -0
      monitorMobile/pages/blankPage.vue
  10. +22
    -11
      monitorMobile/pages/login.vue
  11. +4
    -1
      monitorMobile/pages/my/index.vue
  12. +35
    -11
      monitorMobile/store/index.js
  13. +30
    -0
      monitorMobile/utils/smCrypto.js

+ 10
- 1
monitorMobile/api/user.js View File

@@ -1,9 +1,18 @@
import http from '@/http/api.js'
let url = '/api/sys/auth/b'
// 登录
export const login = (data) => {
return http.request({
url: '/api/sys/auth/b/login',
url: url + '/login',
method: 'POST',
data
})
}
// 获取登录用户信息
export const getLoginUser = (params) => {
return http.request({
url: url + '/getLoginUser',
method: 'GET',
params
})
}

+ 3
- 10
monitorMobile/common/mixins.vue View File

@@ -6,10 +6,6 @@
import {
Base64
} from '@/utils/base64.js';
import {
clientId,
clientSecret
} from '@/common/setting'
export default{
methods:{
// 暂存一个跨页面变量 (与 this.GET_PARAM 成对使用)
@@ -158,13 +154,10 @@
let that = this
// 假设有token值需要在头部需要携带
let header = {}
let accessToken = uni.getStorageSync('accessToken');
if (accessToken) {
header['Blade-Auth'] = 'bearer ' + accessToken;
let token = uni.getStorageSync('token');
if (token) {
config.header['Authorization'] = 'Bearer ' + token;
}
// 客户端认证参数
header['Authorization'] = 'Basic ' + Base64.encode(clientId + ':' + clientSecret);
console.log(filePath)
return new Promise(resovle=>{
uni.uploadFile({
url:options.baseURL + '/api/blade-resource/oss/endpoint/put-uplaod-file?bucketName=',


+ 2
- 12
monitorMobile/common/setting.js View File

@@ -24,16 +24,11 @@ module.exports = {
// 小程序接口Url
// #ifndef H5
// devUrl: 'http://192.168.10.46',
devUrl: '',//开发环境接口Url
prodUrl: ``,//线上环境接口Url
// prodUrl: 'http://192.168.100.236:1888',
// prodUrl: 'http://114.255.136.189:1888',
devUrl: `${origin}/`,//开发环境接口Url
prodUrl: `${origin}/`,//线上环境接口Url
// #endif
// 后端数据的接收方式application/json;charset=UTF-8或者application/x-www-form-urlencoded;charset=UTF-8
contentType: 'application/json;charset=UTF-8',
// 后端返回状态码
@@ -42,13 +37,8 @@ module.exports = {
successCode: 200,
// 登录失效code
invalidCode: 401,
// 客户端ID
clientId: 'rider',
// 客户端密钥
clientSecret: 'rider_secret',
// token过期时间
tokenTime: 3000,
switchMode: true, // 是否开启部门切换模式
//文件预览地址
previewUrl: '',
}

+ 29
- 20
monitorMobile/http/api.js View File

@@ -1,32 +1,22 @@
import {
devUrl,
clientId,
clientSecret
} from '@/common/setting'
import {
options
} from '@/http/config.js';
import {
Base64
} from '@/utils/base64.js';
import Request from '@/utils/luch-request/index.js';
const http = new Request(options);
http.interceptors.request.use((config) => { // 可使用async await 做异步操作
// 假设有token值需要在头部需要携带
let accessToken = uni.getStorageSync('accessToken');
if (accessToken) {
config.header['Blade-Auth'] = 'bearer ' + accessToken;
let token = uni.getStorageSync('token');
if (token) {
config.header['Authorization'] = 'Bearer ' + token;
}
// 客户端认证参数
config.header['Authorization'] = 'Basic ' + Base64.encode(clientId + ':' + clientSecret);

// #ifndef H5
let url = config.url
if (process.env.NODE_ENV == 'development' && !url.startsWith("http")) {
config.url = url
}
// #endif
return config
}, config => { // 可使用async await 做异步操作
return Promise.reject(config)
@@ -38,7 +28,7 @@ http.interceptors.response.use((response) => {
}
// 服务端返回的状态码不等于200,则reject()
if (response.data.code && response.data.code !== 200) {
setTimeout(()=>{
setTimeout(() => {
uni.showToast({
title: response.data.msg,
icon: 'none'
@@ -49,20 +39,39 @@ http.interceptors.response.use((response) => {
return response.data;
}, (response) => {
/* 对响应错误做点什么 (statusCode !== 200)*/
setTimeout(()=>{
setTimeout(() => {
uni.showToast({
title: response.data.msg || response.data.error_description || '网络错误',
icon: 'none'
});
})
if (response.statusCode == 401) {
const pages = getCurrentPages()
const currentPage = pages[pages.length - 1]
uni.redirectTo({
url: `pages/login?redirect=/${currentPage.route}`
url: `/pages/login?redirect=/${currentPage.route}`
})
}
return Promise.reject(response)
})
export default http;
/**
* @description 解密 JWT token 的信息
* @param token jwt token 字符串
* @returns <any>object
*/
function decryptJWT(token) {
token = token.replace(/_/g, "/").replace(/-/g, "+");
const json = decodeURIComponent(escape(window.atob(token.split(".")[1])));
return JSON.parse(json);
}

/**
* @description 将 JWT 时间戳转换成 Date,主要针对 `exp`,`iat`,`nbf`
* @param timestamp 时间戳
* @returns Date 对象
*/
function getJWTDate(timestamp) {
return new Date(timestamp * 1000);
}
export default http;

+ 15
- 0
monitorMobile/manifest.json View File

@@ -65,6 +65,21 @@
"mp-toutiao" : {
"usingComponents" : true
},
"h5" : {
"devServer" : {
"port" : 1888,
"proxy" : {
"/api" : {
"target" : "http://192.168.10.186:8003",
"changeOrigin" : true,
"pathRewrite" : {
"^/api" : ""
}
}
},
"https" : false
}
},
"uniStatistics" : {
"enable" : false
},


+ 14
- 0
monitorMobile/package-lock.json View File

@@ -5,6 +5,7 @@
"packages": {
"": {
"dependencies": {
"sm-crypto": "^0.3.13",
"uview-ui": "^2.0.36",
"vuex": "^3.6.2"
},
@@ -801,6 +802,11 @@
"node": ">= 10.13.0"
}
},
"node_modules/jsbn": {
"version": "1.1.0",
"resolved": "https://registry.npmmirror.com/jsbn/-/jsbn-1.1.0.tgz",
"integrity": "sha512-4bYVV3aAMtDTTu4+xsDYa6sy9GyJ69/amsu9sYF2zqjiEoZA5xJi3BrfX3uY+/IekIu7MwdObdbDWpoZdBv3/A=="
},
"node_modules/json-parse-even-better-errors": {
"version": "2.3.1",
"resolved": "https://registry.npmmirror.com/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz",
@@ -1137,6 +1143,14 @@
"randombytes": "^2.1.0"
}
},
"node_modules/sm-crypto": {
"version": "0.3.13",
"resolved": "https://registry.npmmirror.com/sm-crypto/-/sm-crypto-0.3.13.tgz",
"integrity": "sha512-ztNF+pZq6viCPMA1A6KKu3bgpkmYti5avykRHbcFIdSipFdkVmfUw2CnpM2kBJyppIalqvczLNM3wR8OQ0pT5w==",
"dependencies": {
"jsbn": "^1.1.0"
}
},
"node_modules/source-map": {
"version": "0.6.1",
"resolved": "https://registry.npmmirror.com/source-map/-/source-map-0.6.1.tgz",


+ 1
- 0
monitorMobile/package.json View File

@@ -1,5 +1,6 @@
{
"dependencies": {
"sm-crypto": "^0.3.13",
"uview-ui": "^2.0.36",
"vuex": "^3.6.2"
},


+ 32
- 28
monitorMobile/pages.json View File

@@ -2,14 +2,13 @@
"easycom": {
"^u-(.*)": "uview-ui/components/u-$1/u-$1.vue"
},
"tabBar":{
"color":"#777777",
"selectedColor":"#2388FF",
"backgroundColor":"#FFFFFF",
"borderStyle":"white",
"fontSize":"18rpx",
"list": [
{
"tabBar": {
"color": "#777777",
"selectedColor": "#2388FF",
"backgroundColor": "#FFFFFF",
"borderStyle": "white",
"fontSize": "18rpx",
"list": [{
"pagePath": "pages/earlyWarning/index",
"iconPath": "/static/image/tabbar/earlyWarning.png",
"selectedIconPath": "/static/image/tabbar/earlyWarning_active.png",
@@ -30,6 +29,14 @@
]
},
"pages": [ //pages数组中第一项表示应用启动页,参考:https://uniapp.dcloud.io/collocation/pages
{
"path": "pages/blankPage",
"style": {
"navigationBarTitleText": "",
"enablePullDownRefresh": false,
"navigationStyle": "custom"
}
},
// 预警
{
"path": "pages/earlyWarning/index",
@@ -54,12 +61,11 @@
}
},
{
"path" : "pages/work/returnBed/detail",
"style" :
{
"navigationBarTitleText": "归寝",
"enablePullDownRefresh": false
}
"path": "pages/work/returnBed/detail",
"style": {
"navigationBarTitleText": "归寝",
"enablePullDownRefresh": false
}
},
// 客流
{
@@ -69,12 +75,11 @@
}
},
{
"path" : "pages/work/passengerFlow/detail",
"style" :
{
"navigationBarTitleText": "分片详情",
"enablePullDownRefresh": false
}
"path": "pages/work/passengerFlow/detail",
"style": {
"navigationBarTitleText": "分片详情",
"enablePullDownRefresh": false
}
},
// 点名
{
@@ -84,12 +89,11 @@
}
},
{
"path" : "pages/work/rollCall/detail",
"style" :
{
"navigationBarTitleText": "查看",
"enablePullDownRefresh": false
}
"path": "pages/work/rollCall/detail",
"style": {
"navigationBarTitleText": "查看",
"enablePullDownRefresh": false
}
},
// 巡警
{
@@ -132,7 +136,7 @@
"navigationStyle": "custom"
}
}
],
],
"globalStyle": {
"navigationBarTextStyle": "black",
"navigationBarTitleText": "校园监控预警平台",
@@ -140,4 +144,4 @@
"backgroundColor": "#F8F8F8"
},
"uniIdRouter": {}
}
}

+ 24
- 0
monitorMobile/pages/blankPage.vue View File

@@ -0,0 +1,24 @@
<template>
<view></view>
</template>

<script>
export default {
created() {
// token标志来判断
let token = uni.getStorageSync('token');
if (!token) {
uni.reLaunch({
url: '/pages/login'
})
} else {
uni.switchTab({
url: '/pages/earlyWarning/index'
})
}
}
}
</script>

<style>
</style>

+ 22
- 11
monitorMobile/pages/login.vue View File

@@ -38,8 +38,9 @@

<script>
import {
login
login,
} from '@/api/user.js'
import smCrypto from '@/utils/smCrypto'
export default {
data() {
return {
@@ -49,7 +50,7 @@
},
passType: 'password',
isLoading: false,
redirect:'',
redirect: '',
rules: {
account: [{
required: true,
@@ -74,21 +75,31 @@
},
onLoad(e) {
if (e.redirect) this.redirect = redirect
// this.username = ''
// this.password = ''
this.form.account = 'superAdmin'
this.form.password = '123456'
},
methods: {
login() {
async login() {
this.$refs.uForm.validate().then(() => {
this.isLoading = true
login(this.form).then(res => {
this.isLoading = false
console.log(res)
}).catch(()=>{
login({
...this.form,
password: smCrypto.doSm2Encrypt(this.form.password)
}).then(res => {
if (res.code != 200) return
let data = res.data
this.$store.dispatch('setToken',{token:data.token})
this.$store.dispatch('getUserInfo')
this.NAV_TO('/')
}).finally(() => {
this.isLoading = false
})
})
},
getLoginUser(){
return getLoginUser().then(res=>{
if (res.code != 200) return
this.$u.vuex('userInfo', res.data)
})
}
},
onReady() {


+ 4
- 1
monitorMobile/pages/my/index.vue View File

@@ -124,7 +124,10 @@
this.date = e.detail.value
},
loginOut() {
this.CONFIRM('您是否确认退出登录?')
this.CONFIRM('您是否确认退出登录?').then(()=>{
this.$store.dispatch('clearToken')
this.JUMP_TO('/pages/login')
})
}
}
}


+ 35
- 11
monitorMobile/store/index.js View File

@@ -1,6 +1,9 @@
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
import {
getLoginUser
} from '@/api/user.js'

let lifeData = {};

@@ -12,7 +15,7 @@ try {
}

// 需要永久存储,且下次APP启动需要取出的,在state中的变量名
let saveStateKeys = [];
let saveStateKeys = ['token', 'userInfo'];

// 保存变量到本地存储中
const saveLifeData = function(key, value) {
@@ -27,7 +30,7 @@ const saveLifeData = function(key, value) {
uni.setStorageSync(key, value);
uni.setStorageSync('lifeData', tmp);
}
if(key == 'refreshToken') {
if (key == 'refreshToken') {
uni.setStorageSync('token', {
content: value,
datetime: new Date().getTime()
@@ -35,16 +38,37 @@ const saveLifeData = function(key, value) {
}
}
const store = new Vuex.Store({
// 下面这些值仅为示例,使用过程中请删除
state: {
// 如果上面从本地获取的lifeData对象下有对应的属性,就赋值给state中对应的变量
// userInfo: lifeData.userInfo ? lifeData.userInfo : {
// avatar: '',
// nick_name: '游客',
// tenant_id: '暂无'
// },
// accessToken: lifeData.accessToken ? lifeData.accessToken : '',
// isLogin: lifeData.isLogin ? lifeData.isLogin : false,
userInfo: lifeData.userInfo || null,
token: lifeData.accessToken || '',
refreshToken: '',
},
actions: {
async getUserInfo(context) {
const {
data
} = await getLoginUser();
if(data){
context.commit('$uStore', {
name: 'userInfo',
value: data
})
}
return data;
},
setToken(context,payload){
context.commit('$uStore', {
name: 'token',
value: payload.token
})
},
clearToken(context){
context.commit('$uStore', {
name: 'token',
value: ''
})
}
},
mutations: {
$uStore(state, payload) {
@@ -70,4 +94,4 @@ const store = new Vuex.Store({
}
})
Vue.prototype.$store = store
export default store
export default store

+ 30
- 0
monitorMobile/utils/smCrypto.js View File

@@ -0,0 +1,30 @@
/**
* @description smCrypto 加密解密工具
* @license Apache License Version 2.0
* @Copyright (c) 2022-Now 少林寺驻北固山办事处大神父王喇嘛
* @remarks
* SimpleAdmin 基于 Apache License Version 2.0 协议发布,可用于商业项目,但必须遵守以下补充条款:
* 1.请不要删除和修改根目录下的LICENSE文件。
* 2.请不要删除和修改SimpleAdmin源码头部的版权声明。
* 3.分发源码时候,请注明软件出处 https://gitee.com/dotnetmoyu/SimpleAdmin
* 4.基于本软件的作品,只能使用 SimpleAdmin 作为后台服务,除外情况不可商用且不允许二次分发或开源。
* 5.请不得将本软件应用于危害国家安全、荣誉和利益的行为,不能以任何形式用于非法为目的的行为不要删除和修改作者声明。
* 6.任何基于本软件而产生的一切法律纠纷和责任,均于我司无关
* @see https://gitee.com/dotnetmoyu/SimpleAdmin
*/

import smCrypto from "sm-crypto";
const { sm2 } = smCrypto;
const cipherMode = 0; // 1 - C1C3C2,0 - C1C2C3,默认为1
const publicKey =
"04BD62406DF6789B1FBE8C457AECAE6D7C806CDB39316F190519905C24DF395E8952C47798D76ADECF8CA28C935702AFCDD9B17DE77121FA6448F0EDEFBD8365D6";

/**
* 国密加解密工具类
*/
export default {
// SM2加密
doSm2Encrypt(msgString) {
return sm2.doEncrypt(msgString, publicKey, cipherMode);
}
};

Loading…
Cancel
Save