init
commit
4e333fbe16
@ -0,0 +1,30 @@
|
||||
.DS_Store
|
||||
.history
|
||||
node_modules/
|
||||
dist/
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
**/*.log
|
||||
|
||||
tests/**/coverage/
|
||||
tests/e2e/reports
|
||||
selenium-debug.log
|
||||
|
||||
# Editor directories and files
|
||||
.idea
|
||||
.vscode
|
||||
.hbuilderx
|
||||
*.suo
|
||||
*.ntvs*
|
||||
*.njsproj
|
||||
*.sln
|
||||
*.local
|
||||
|
||||
package-lock.json
|
||||
yarn.lock
|
||||
pnpm-lock.yaml
|
||||
|
||||
# 编译生成的文件
|
||||
auto-imports.d.ts
|
||||
components.d.ts
|
||||
@ -0,0 +1,17 @@
|
||||
<script>
|
||||
export default {
|
||||
onLaunch: function() {
|
||||
console.log('App Launch')
|
||||
},
|
||||
onShow: function() {
|
||||
console.log('App Show')
|
||||
},
|
||||
onHide: function() {
|
||||
console.log('App Hide')
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
/*每个页面公共css */
|
||||
</style>
|
||||
@ -0,0 +1,28 @@
|
||||
import {
|
||||
request
|
||||
} from '@/utils/request'
|
||||
import {
|
||||
getGlobalData
|
||||
} from '@/store/index.js'
|
||||
|
||||
|
||||
const clientId = getGlobalData('clientId')
|
||||
export function loginApi(params) {
|
||||
return request({
|
||||
url: '/auth/login',
|
||||
method: 'POST',
|
||||
headers: {
|
||||
isToken: false,
|
||||
isEncrypt: true,
|
||||
repeatSubmit: false
|
||||
},
|
||||
method: 'post',
|
||||
data: {
|
||||
...params,
|
||||
clientId,
|
||||
grantType: params.grantType || 'password',
|
||||
rememberMe: false,
|
||||
tenantId: "000000",
|
||||
}
|
||||
})
|
||||
}
|
||||
@ -0,0 +1,20 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="zh-CN">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<script>
|
||||
var coverSupport = 'CSS' in window && typeof CSS.supports === 'function' && (CSS.supports('top: env(a)') ||
|
||||
CSS.supports('top: constant(a)'))
|
||||
document.write(
|
||||
'<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0' +
|
||||
(coverSupport ? ', viewport-fit=cover' : '') + '" />')
|
||||
</script>
|
||||
<title></title>
|
||||
<!--preload-links-->
|
||||
<!--app-context-->
|
||||
</head>
|
||||
<body>
|
||||
<div id="app"><!--app-html--></div>
|
||||
<script type="module" src="/main.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
@ -0,0 +1,24 @@
|
||||
import App from './App'
|
||||
|
||||
// #ifndef VUE3
|
||||
import Vue from 'vue'
|
||||
import './uni.promisify.adaptor'
|
||||
Vue.config.productionTip = false
|
||||
App.mpType = 'app'
|
||||
const app = new Vue({
|
||||
...App
|
||||
})
|
||||
app.$mount()
|
||||
// #endif
|
||||
|
||||
// #ifdef VUE3
|
||||
import {
|
||||
createSSRApp
|
||||
} from 'vue'
|
||||
export function createApp() {
|
||||
const app = createSSRApp(App)
|
||||
return {
|
||||
app
|
||||
}
|
||||
}
|
||||
// #endif
|
||||
@ -0,0 +1,73 @@
|
||||
{
|
||||
"name" : "highwayiot-business-management-platform",
|
||||
"appid" : "__UNI__5F0F000",
|
||||
"description" : "",
|
||||
"versionName" : "1.0.0",
|
||||
"versionCode" : "100",
|
||||
"transformPx" : false,
|
||||
/* 5+App特有相关 */
|
||||
"app-plus" : {
|
||||
"usingComponents" : true,
|
||||
"nvueStyleCompiler" : "uni-app",
|
||||
"compilerVersion" : 3,
|
||||
"splashscreen" : {
|
||||
"alwaysShowBeforeRender" : true,
|
||||
"waiting" : true,
|
||||
"autoclose" : true,
|
||||
"delay" : 0
|
||||
},
|
||||
/* 模块配置 */
|
||||
"modules" : {},
|
||||
/* 应用发布信息 */
|
||||
"distribute" : {
|
||||
/* android打包配置 */
|
||||
"android" : {
|
||||
"permissions" : [
|
||||
"<uses-permission android:name=\"android.permission.CHANGE_NETWORK_STATE\"/>",
|
||||
"<uses-permission android:name=\"android.permission.MOUNT_UNMOUNT_FILESYSTEMS\"/>",
|
||||
"<uses-permission android:name=\"android.permission.VIBRATE\"/>",
|
||||
"<uses-permission android:name=\"android.permission.READ_LOGS\"/>",
|
||||
"<uses-permission android:name=\"android.permission.ACCESS_WIFI_STATE\"/>",
|
||||
"<uses-feature android:name=\"android.hardware.camera.autofocus\"/>",
|
||||
"<uses-permission android:name=\"android.permission.ACCESS_NETWORK_STATE\"/>",
|
||||
"<uses-permission android:name=\"android.permission.CAMERA\"/>",
|
||||
"<uses-permission android:name=\"android.permission.GET_ACCOUNTS\"/>",
|
||||
"<uses-permission android:name=\"android.permission.READ_PHONE_STATE\"/>",
|
||||
"<uses-permission android:name=\"android.permission.CHANGE_WIFI_STATE\"/>",
|
||||
"<uses-permission android:name=\"android.permission.WAKE_LOCK\"/>",
|
||||
"<uses-permission android:name=\"android.permission.FLASHLIGHT\"/>",
|
||||
"<uses-feature android:name=\"android.hardware.camera\"/>",
|
||||
"<uses-permission android:name=\"android.permission.WRITE_SETTINGS\"/>"
|
||||
]
|
||||
},
|
||||
/* ios打包配置 */
|
||||
"ios" : {},
|
||||
/* SDK配置 */
|
||||
"sdkConfigs" : {}
|
||||
}
|
||||
},
|
||||
/* 快应用特有相关 */
|
||||
"quickapp" : {},
|
||||
/* 小程序特有相关 */
|
||||
"mp-weixin" : {
|
||||
"appid" : "",
|
||||
"setting" : {
|
||||
"urlCheck" : false,
|
||||
"es6" : true
|
||||
},
|
||||
"usingComponents" : true
|
||||
},
|
||||
"mp-alipay" : {
|
||||
"usingComponents" : true
|
||||
},
|
||||
"mp-baidu" : {
|
||||
"usingComponents" : true
|
||||
},
|
||||
"mp-toutiao" : {
|
||||
"usingComponents" : true
|
||||
},
|
||||
"uniStatistics" : {
|
||||
"enable" : false
|
||||
},
|
||||
"vueVersion" : "3"
|
||||
}
|
||||
@ -0,0 +1,6 @@
|
||||
{
|
||||
"dependencies": {
|
||||
"crypto-js": "^4.2.0",
|
||||
"jsencrypt": "^3.5.4"
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,40 @@
|
||||
<template>
|
||||
<view class="content">
|
||||
<image class="logo" src="/static/logo.png"></image>
|
||||
<view class="text-area">
|
||||
<text class="title">{{title}}</text>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
const title = 'hello'
|
||||
</script>
|
||||
|
||||
<style>
|
||||
.content {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.logo {
|
||||
height: 200rpx;
|
||||
width: 200rpx;
|
||||
margin-top: 200rpx;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
margin-bottom: 50rpx;
|
||||
}
|
||||
|
||||
.text-area {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.title {
|
||||
font-size: 36rpx;
|
||||
color: #8f8f94;
|
||||
}
|
||||
</style>
|
||||
@ -0,0 +1,21 @@
|
||||
const globaldata = {
|
||||
token: '',
|
||||
encryptHeader: 'encrypt-key',
|
||||
clientId: '428a8310cd442757ae699df5d894f051',
|
||||
RSA_PUBLIC_KEY: 'MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAKoR8mX0rGKLqzcWmOzbfj64K8ZIgOdHnzkXSOVOZbFu/TJhZ7rFAN+eaGkl3C4buccQd/EjEsj9ir7ijT7h96MCAwEAAQ==',
|
||||
RSA_PRIVATE_KEY: 'MIIBVAIBADANBgkqhkiG9w0BAQEFAASCAT4wggE6AgEAAkEAmc3CuPiGL/LcIIm7zryCEIbl1SPzBkr75E2VMtxegyZ1lYRD+7TZGAPkvIsBcaMs6Nsy0L78n2qh+lIZMpLH8wIDAQABAkEAk82Mhz0tlv6IVCyIcw/s3f0E+WLmtPFyR9/WtV3Y5aaejUkU60JpX4m5xNR2VaqOLTZAYjW8Wy0aXr3zYIhhQQIhAMfqR9oFdYw1J9SsNc+CrhugAvKTi0+BF6VoL6psWhvbAiEAxPPNTmrkmrXwdm/pQQu3UOQmc2vCZ5tiKpW10CgJi8kCIFGkL6utxw93Ncj4exE/gPLvKcT+1Emnoox+O9kRXss5AiAMtYLJDaLEzPrAWcZeeSgSIzbL+ecokmFKSDDcRske6QIgSMkHedwND1olF8vlKsJUGK3BcdtM8w4Xq7BpSBwsloE='
|
||||
}
|
||||
export const getGlobalData = (key) => {
|
||||
if (Array.isArray(key)) {
|
||||
let res = {}
|
||||
key.forEach(e => {
|
||||
res[e] = globaldata[e] || ''
|
||||
})
|
||||
return res
|
||||
} else {
|
||||
return globaldata[key] || ''
|
||||
}
|
||||
}
|
||||
export const setGlobalData = (key, value) => {
|
||||
globaldata[key] = value
|
||||
}
|
||||
@ -0,0 +1,13 @@
|
||||
uni.addInterceptor({
|
||||
returnValue (res) {
|
||||
if (!(!!res && (typeof res === "object" || typeof res === "function") && typeof res.then === "function")) {
|
||||
return res;
|
||||
}
|
||||
return new Promise((resolve, reject) => {
|
||||
res.then((res) => {
|
||||
if (!res) return resolve(res)
|
||||
return res[0] ? reject(res[0]) : resolve(res[1])
|
||||
});
|
||||
});
|
||||
},
|
||||
});
|
||||
@ -0,0 +1,66 @@
|
||||
import CryptoJS from 'crypto-js'
|
||||
|
||||
/**
|
||||
* 随机生成32位的字符串
|
||||
* @returns {string}
|
||||
*/
|
||||
const generateRandomString = () => {
|
||||
const characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
|
||||
let result = '';
|
||||
const charactersLength = characters.length;
|
||||
for (let i = 0; i < 32; i++) {
|
||||
result += characters.charAt(Math.floor(Math.random() * charactersLength));
|
||||
}
|
||||
return result;
|
||||
};
|
||||
|
||||
/**
|
||||
* 随机生成aes 密钥
|
||||
* @returns {string}
|
||||
*/
|
||||
export const generateAesKey = () => {
|
||||
return CryptoJS.enc.Utf8.parse(generateRandomString());
|
||||
};
|
||||
|
||||
/**
|
||||
* 加密base64
|
||||
* @returns {string}
|
||||
*/
|
||||
export const encryptBase64 = (str) => {
|
||||
return CryptoJS.enc.Base64.stringify(str);
|
||||
};
|
||||
|
||||
/**
|
||||
* 解密base64
|
||||
*/
|
||||
export const decryptBase64 = (str) => {
|
||||
return CryptoJS.enc.Base64.parse(str);
|
||||
};
|
||||
|
||||
/**
|
||||
* 使用密钥对数据进行加密
|
||||
* @param message
|
||||
* @param aesKey
|
||||
* @returns {string}
|
||||
*/
|
||||
export const encryptWithAes = (message, aesKey) => {
|
||||
const encrypted = CryptoJS.AES.encrypt(message, aesKey, {
|
||||
mode: CryptoJS.mode.ECB,
|
||||
padding: CryptoJS.pad.Pkcs7
|
||||
});
|
||||
return encrypted.toString();
|
||||
};
|
||||
|
||||
/**
|
||||
* 使用密钥对数据进行解密
|
||||
* @param message
|
||||
* @param aesKey
|
||||
* @returns {string}
|
||||
*/
|
||||
export const decryptWithAes = (message, aesKey) => {
|
||||
const decrypted = CryptoJS.AES.decrypt(message, aesKey, {
|
||||
mode: CryptoJS.mode.ECB,
|
||||
padding: CryptoJS.pad.Pkcs7
|
||||
});
|
||||
return decrypted.toString(CryptoJS.enc.Utf8);
|
||||
};
|
||||
@ -0,0 +1,25 @@
|
||||
import JSEncrypt from 'jsencrypt';
|
||||
import {
|
||||
getGlobalData
|
||||
} from '@/store/index.js'
|
||||
|
||||
|
||||
const {
|
||||
RSA_PUBLIC_KEY: publicKey,
|
||||
RSA_PRIVATE_KEY: privateKey
|
||||
} = getGlobalData(['RSA_PUBLIC_KEY', 'RSA_PRIVATE_KEY'])
|
||||
|
||||
|
||||
// 加密
|
||||
export const encrypt = (txt) => {
|
||||
const encryptor = new JSEncrypt();
|
||||
encryptor.setPublicKey(publicKey); // 设置公钥
|
||||
return encryptor.encrypt(txt); // 对数据进行加密
|
||||
};
|
||||
|
||||
// 解密
|
||||
export const decrypt = (txt) => {
|
||||
const encryptor = new JSEncrypt();
|
||||
encryptor.setPrivateKey(privateKey); // 设置私钥
|
||||
return encryptor.decrypt(txt); // 对数据进行解密
|
||||
};
|
||||
File diff suppressed because one or more lines are too long
@ -0,0 +1,88 @@
|
||||
import {
|
||||
encryptBase64,
|
||||
encryptWithAes,
|
||||
generateAesKey,
|
||||
decryptWithAes,
|
||||
decryptBase64
|
||||
} from '@/utils/crypto';
|
||||
import {
|
||||
encrypt,
|
||||
decrypt
|
||||
} from '@/utils/jsencrypt';
|
||||
|
||||
import {
|
||||
getGlobalData
|
||||
} from '@/store/index.js'
|
||||
|
||||
const encryptHeader = getGlobalData('encryptHeader');
|
||||
|
||||
const baseURL = 'https://frp-off.com:47543'
|
||||
|
||||
const getToken = () => {
|
||||
return getGlobalData('token')
|
||||
}
|
||||
|
||||
export function request(options) {
|
||||
// 加密
|
||||
const isEncrypt = options.headers && (options.headers.isEncrypt === 'true' || options.headers.isEncrypt === true);
|
||||
|
||||
if (isEncrypt && (options.method === 'post' || options.method === 'put')) {
|
||||
const aesKey = generateAesKey();
|
||||
options.headers[encryptHeader] = encrypt(encryptBase64(aesKey));
|
||||
options.data = typeof options.data === 'object' ? encryptWithAes(JSON.stringify(options.data), aesKey) :
|
||||
encryptWithAes(options.data, aesKey);
|
||||
}
|
||||
// token
|
||||
let isToken = (options.headers || {}).isToken === false
|
||||
if (getToken() && !isToken) {
|
||||
options.headers['Authorization'] = 'Bearer ' + getToken();
|
||||
}
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
uni.request({
|
||||
url: baseURL + options.url,
|
||||
method: options.method || 'GET',
|
||||
data: options.data || {},
|
||||
header: options.headers || {},
|
||||
success: res => {
|
||||
if (res.statusCode === 200) {
|
||||
let code = res.data.code
|
||||
let msg = res.data.msg
|
||||
if (code === 200) {
|
||||
uni.showToast({
|
||||
title: msg.length < 10 ? msg : '成功',
|
||||
icon: 'success',
|
||||
duration: 2000
|
||||
})
|
||||
resolve(res.data)
|
||||
} else {
|
||||
if (code === 401) {
|
||||
uni.showToast({
|
||||
title: '请重新登录',
|
||||
icon: 'error',
|
||||
duration: 2000
|
||||
})
|
||||
} else {
|
||||
uni.showToast({
|
||||
title: msg.length < 10 ? msg : '网络错误请重试',
|
||||
icon: 'error',
|
||||
duration: 2000
|
||||
})
|
||||
}
|
||||
reject(false)
|
||||
}
|
||||
} else {
|
||||
reject(false)
|
||||
}
|
||||
},
|
||||
fail: err => {
|
||||
uni.showToast({
|
||||
title: '网络错误请重试',
|
||||
icon: 'error',
|
||||
duration: 2000
|
||||
})
|
||||
reject(false)
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
Loading…
Reference in New Issue