Merge branch 'main' of https://git.jsspisoft.com/ry-das
This commit is contained in:
commit
26699c4910
@ -4,9 +4,6 @@ ENV = 'development'
|
||||
# base路径
|
||||
VITE_BASE_PATH = './'
|
||||
|
||||
# 网站是否不需要权限认证: NoAuth Auth
|
||||
VITE_APP_NO_AUTH='NoAuth'
|
||||
|
||||
# 代理配置(开发使用),必须在一行中
|
||||
VITE_APP_PROXY=[["/api","https://usp2.jsspisoft.com/api"]]
|
||||
|
||||
|
@ -42,6 +42,7 @@
|
||||
"@typescript-eslint/parser": "7.12.0",
|
||||
"@vitejs/plugin-vue": "5.0.5",
|
||||
"async-validator": "4.2.5",
|
||||
"crypto-js": "^4.2.0",
|
||||
"eslint": "8.56.0",
|
||||
"eslint-config-prettier": "9.1.0",
|
||||
"eslint-plugin-vue": "9.26.0",
|
||||
|
@ -24,12 +24,9 @@ export function login(method: 'get' | 'post', params: object = {}) {
|
||||
}
|
||||
|
||||
export function logout() {
|
||||
const adminInfo = useAdminInfo()
|
||||
// const adminInfo = useAdminInfo()
|
||||
return createAxios({
|
||||
url: '/api/auth/token/revoke',
|
||||
method: 'POST',
|
||||
data: {
|
||||
refreshToken: adminInfo.getToken('refresh'),
|
||||
},
|
||||
})
|
||||
}
|
||||
|
@ -1,12 +0,0 @@
|
||||
/**
|
||||
* frontend common language package
|
||||
*/
|
||||
export default {
|
||||
Integral: 'Integral',
|
||||
Balance: 'Balance',
|
||||
Language: 'Language',
|
||||
Copyright: 'Copyright',
|
||||
'Member Center': 'Member Center',
|
||||
'Logout login': 'Logout',
|
||||
'Member center disabled': 'The member center has been disabled. Please contact the webmaster to turn it on.',
|
||||
}
|
@ -1,3 +0,0 @@
|
||||
export default {
|
||||
'Steve Jobs': "Great art don't have to follow the trend, it alone can lead.-- Steve Jobs",
|
||||
}
|
@ -1,6 +0,0 @@
|
||||
export default {
|
||||
'Change time': 'Change time',
|
||||
'Current balance': 'Current balance',
|
||||
'Balance after change': 'Balance after change',
|
||||
'Balance change record': 'Balance change record',
|
||||
}
|
@ -1,8 +0,0 @@
|
||||
export default {
|
||||
'Change Password': 'Change Password',
|
||||
'Old password': 'Old password',
|
||||
'New password': 'New password',
|
||||
'Confirm new password': 'Confirm new password',
|
||||
'Please enter your current password': 'Please enter your current password',
|
||||
'The duplicate password does not match the new password': 'The duplicate password does not match the new password',
|
||||
}
|
@ -1,6 +0,0 @@
|
||||
export default {
|
||||
'Change time': 'Change time',
|
||||
'Current points': 'Current points',
|
||||
'Points after change': 'Points after change',
|
||||
'Score change record': 'Score change record',
|
||||
}
|
@ -1,11 +0,0 @@
|
||||
export default {
|
||||
'Account information': 'Account information',
|
||||
'personal data': 'personal data',
|
||||
'Filled in': 'Filled in',
|
||||
'Not filled in': 'Not filled in',
|
||||
mobile: 'mobile',
|
||||
email: 'email',
|
||||
'Last login IP': 'Last login IP',
|
||||
'Last login': 'Last login',
|
||||
'Growth statistics': 'Growth statistics',
|
||||
}
|
@ -1,32 +0,0 @@
|
||||
export default {
|
||||
'personal data': 'personal data',
|
||||
'Change Password': 'Change Password',
|
||||
'head portrait': 'head portrait',
|
||||
'User name': 'User name',
|
||||
'User nickname': 'User nickname',
|
||||
mail: 'mail',
|
||||
email: 'email',
|
||||
'Operation via right button': 'Operation via right button',
|
||||
'Click Modify': 'Click Modify',
|
||||
bind: 'bind',
|
||||
mobile: 'mobile',
|
||||
Gender: 'Gender',
|
||||
secrecy: 'secrecy',
|
||||
male: 'male',
|
||||
female: 'female',
|
||||
birthday: 'birthday',
|
||||
'Personal signature': 'Personal signature',
|
||||
'Account verification': 'Account verification',
|
||||
'Account password verification': 'Account password verification',
|
||||
'Mail verification': 'Mail verification',
|
||||
'SMS verification': 'SMS verification',
|
||||
password: 'password',
|
||||
accept: 'accept',
|
||||
'next step': 'next step',
|
||||
'New email': 'New email',
|
||||
'New mobile': 'New mobile',
|
||||
'Verification Code': 'Captcha',
|
||||
send: 'send',
|
||||
seconds: 'seconds',
|
||||
nickname: 'nickname',
|
||||
}
|
@ -1,24 +0,0 @@
|
||||
export default {
|
||||
reach: ' Reach ',
|
||||
login: 'Login',
|
||||
register: 'Register',
|
||||
'Via email': 'By email',
|
||||
'Via mobile number': 'By mobile number',
|
||||
'User name': 'User name',
|
||||
account: 'Username/Email/Mobile',
|
||||
password: 'Password',
|
||||
'Verification Code': 'Captcha',
|
||||
mobile: 'mobile',
|
||||
email: 'email',
|
||||
send: 'send',
|
||||
seconds: 'seconds',
|
||||
'Remember me': 'Remember me',
|
||||
'Forgot your password?': 'Forgot your password?',
|
||||
'Back to login': 'Back to login',
|
||||
'No account yet? Click Register': 'No account yet? Click Register',
|
||||
'Retrieve password': 'Retrieve password',
|
||||
'Retrieval method': 'Retrieval method',
|
||||
'New password': 'New password',
|
||||
second: 'second',
|
||||
'Account name': 'Account name',
|
||||
}
|
@ -1,13 +0,0 @@
|
||||
/**
|
||||
* 前台公共语言包
|
||||
* 覆盖风险:请避免使用页面语言包的目录名、文件名作为翻译 key
|
||||
*/
|
||||
export default {
|
||||
Integral: '积分',
|
||||
Balance: '余额',
|
||||
Language: '语言',
|
||||
Copyright: '版权所有',
|
||||
'Member Center': '会员中心',
|
||||
'Logout login': '注销登录',
|
||||
'Member center disabled': '会员中心已禁用,请联系网站管理员开启。',
|
||||
}
|
@ -1,3 +0,0 @@
|
||||
export default {
|
||||
'Steve Jobs': '伟大的艺术品不必追随潮流,他本身就能引领潮流。 -- 乔布斯',
|
||||
}
|
@ -1,6 +0,0 @@
|
||||
export default {
|
||||
'Change time': '变更时间',
|
||||
'Current balance': '当前余额',
|
||||
'Balance after change': '变更后余额',
|
||||
'Balance change record': '余额变更记录',
|
||||
}
|
@ -1,8 +0,0 @@
|
||||
export default {
|
||||
'Change Password': '修改密码',
|
||||
'Old password': '旧密码',
|
||||
'New password': '新密码',
|
||||
'Confirm new password': '确认新密码',
|
||||
'Please enter your current password': '请输入现在的密码',
|
||||
'The duplicate password does not match the new password': '重复密码与新密码不相符',
|
||||
}
|
@ -1,6 +0,0 @@
|
||||
export default {
|
||||
'Change time': '变更时间',
|
||||
'Current points': '当前积分',
|
||||
'Points after change': '变更后积分',
|
||||
'Score change record': '积分变更记录',
|
||||
}
|
@ -1,11 +0,0 @@
|
||||
export default {
|
||||
'Account information': '账户信息',
|
||||
'personal data': '个人资料',
|
||||
'Filled in': '已填写',
|
||||
'Not filled in': '未填写',
|
||||
mobile: '手机号',
|
||||
email: '电子邮箱',
|
||||
'Last login IP': '最后登录IP',
|
||||
'Last login': '最后登录',
|
||||
'Growth statistics': '增长统计',
|
||||
}
|
@ -1,32 +0,0 @@
|
||||
export default {
|
||||
'personal data': '个人资料',
|
||||
'Change Password': '修改密码',
|
||||
'head portrait': '头像',
|
||||
'User name': '用户名',
|
||||
'User nickname': '用户昵称',
|
||||
mail: '邮箱',
|
||||
email: '电子邮箱',
|
||||
'Operation via right button': '通过右侧按钮操作',
|
||||
'Click Modify': '点击修改',
|
||||
bind: '绑定',
|
||||
mobile: '手机号',
|
||||
Gender: '性别',
|
||||
secrecy: '保密',
|
||||
male: '男',
|
||||
female: '女',
|
||||
birthday: '生日',
|
||||
'Personal signature': '个性签名',
|
||||
'Account verification': '账户验证',
|
||||
'Account password verification': '账户密码验证',
|
||||
'Mail verification': '邮件验证',
|
||||
'SMS verification': '短信验证',
|
||||
password: '密码',
|
||||
accept: '接受',
|
||||
'next step': '下一步',
|
||||
'New email': '新邮箱',
|
||||
'New mobile': '新手机号',
|
||||
'Verification Code': '验证码',
|
||||
send: '发送',
|
||||
seconds: '秒',
|
||||
nickname: '昵称',
|
||||
}
|
@ -1,24 +0,0 @@
|
||||
export default {
|
||||
reach: '到',
|
||||
login: '登录',
|
||||
register: '注册',
|
||||
'Via email': '通过邮箱',
|
||||
'Via mobile number': '通过手机号',
|
||||
'User name': '用户名',
|
||||
account: '用户名/邮箱/手机号',
|
||||
password: '密码',
|
||||
'Verification Code': '验证码',
|
||||
mobile: '手机号',
|
||||
email: '电子邮箱',
|
||||
send: '发送',
|
||||
seconds: '秒',
|
||||
'Remember me': '记住我',
|
||||
'Forgot your password?': '忘记密码?',
|
||||
'Back to login': '回到登录',
|
||||
'No account yet? Click Register': '还没有账户?点击注册',
|
||||
'Retrieve password': '找回密码',
|
||||
'Retrieval method': '找回方式',
|
||||
'New password': '新密码',
|
||||
second: '确定',
|
||||
'Account name': '账户',
|
||||
}
|
@ -160,6 +160,7 @@ const onAdminInfo = () => {
|
||||
|
||||
const onLogout = () => {
|
||||
logout().then(() => {
|
||||
debugger
|
||||
Local.remove(ADMIN_INFO)
|
||||
router.go(0)
|
||||
})
|
||||
|
@ -18,7 +18,7 @@ export const useSiteConfig = defineStore('siteConfig', {
|
||||
},
|
||||
headNav: [],
|
||||
initialize: false,
|
||||
userInitialize: false,
|
||||
userInitialize: true,
|
||||
}
|
||||
},
|
||||
actions: {
|
||||
|
@ -8,7 +8,7 @@ import adminBaseRoute from '/@/router/static/adminBase'
|
||||
import { useAdminInfo } from '/@/stores/adminInfo'
|
||||
import { useConfig } from '/@/stores/config'
|
||||
import { useUserInfo } from '/@/stores/userInfo'
|
||||
import { isAdminApp } from '/@/utils/common'
|
||||
import { encrypt_aes, decrypt_aes, generateRandomNumber } from './crypto'
|
||||
|
||||
window.requests = []
|
||||
window.tokenRefreshing = false
|
||||
@ -50,7 +50,6 @@ function createAxios<Data = any, T = ApiPromise<Data>>(axiosConfig: AxiosRequest
|
||||
headers: {
|
||||
'think-lang': config.lang.defaultLang,
|
||||
server: true,
|
||||
'Content-Type': 'application/x-www-form-urlencoded;charset=UTF-8',
|
||||
},
|
||||
responseType: 'json',
|
||||
})
|
||||
@ -59,6 +58,7 @@ function createAxios<Data = any, T = ApiPromise<Data>>(axiosConfig: AxiosRequest
|
||||
// if (adminBaseRoute.path != '/admin' && isAdminApp() && /^\/admin\//.test(axiosConfig.url!)) {
|
||||
// axiosConfig.url = axiosConfig.url!.replace(/^\/admin\//, adminBaseRoute.path + '.php/')
|
||||
// }
|
||||
alert(axiosConfig.data)
|
||||
|
||||
// 合并默认请求选项
|
||||
options = Object.assign(
|
||||
@ -89,8 +89,11 @@ function createAxios<Data = any, T = ApiPromise<Data>>(axiosConfig: AxiosRequest
|
||||
|
||||
// 自动携带token
|
||||
if (config.headers) {
|
||||
const v = generateRandomNumber(16)
|
||||
config.headers.v = v
|
||||
const token = adminInfo.getToken()
|
||||
if (token) (config.headers as anyObj).token = token
|
||||
if (token) (config.headers as anyObj).token = encrypt_aes(token, v)
|
||||
|
||||
// const userToken = options.anotherToken || userInfo.getToken()
|
||||
// if (userToken) (config.headers as anyObj)['token'] = userToken
|
||||
}
|
||||
@ -105,76 +108,54 @@ function createAxios<Data = any, T = ApiPromise<Data>>(axiosConfig: AxiosRequest
|
||||
// 响应拦截
|
||||
Axios.interceptors.response.use(
|
||||
(response) => {
|
||||
debugger
|
||||
removePending(response.config)
|
||||
options.loading && closeLoading(options) // 关闭loading
|
||||
|
||||
if (response.config.responseType == 'json') {
|
||||
if (response.data && response.data.code !== 200) {
|
||||
if (response.data.code == 409) {
|
||||
if (!window.tokenRefreshing) {
|
||||
window.tokenRefreshing = true
|
||||
return refreshToken()
|
||||
.then((res) => {
|
||||
if (res.data.type == 'admin-refresh') {
|
||||
adminInfo.setToken(res.data.token, 'auth')
|
||||
response.headers.batoken = `${res.data.token}`
|
||||
window.requests.forEach((cb) => cb(res.data.token, 'admin-refresh'))
|
||||
} else if (res.data.type == 'user-refresh') {
|
||||
userInfo.setToken(res.data.token, 'auth')
|
||||
response.headers['ba-user-token'] = `${res.data.token}`
|
||||
window.requests.forEach((cb) => cb(res.data.token, 'user-refresh'))
|
||||
}
|
||||
window.requests = []
|
||||
return Axios(response.config)
|
||||
})
|
||||
.catch((err) => {
|
||||
adminInfo.removeToken()
|
||||
if (router.currentRoute.value.name != 'adminLogin') {
|
||||
router.push({ name: 'adminLogin' })
|
||||
return Promise.reject(err)
|
||||
} else {
|
||||
response.headers.batoken = ''
|
||||
window.requests.forEach((cb) => cb('', 'admin-refresh'))
|
||||
window.requests = []
|
||||
return Axios(response.config)
|
||||
}
|
||||
})
|
||||
.finally(() => {
|
||||
window.tokenRefreshing = false
|
||||
})
|
||||
} else {
|
||||
return new Promise((resolve) => {
|
||||
// 用函数形式将 resolve 存入,等待刷新后再执行
|
||||
window.requests.push((token: string, type: string) => {
|
||||
if (type == 'admin-refresh') {
|
||||
response.headers.batoken = `${token}`
|
||||
} else {
|
||||
response.headers['ba-user-token'] = `${token}`
|
||||
}
|
||||
resolve(Axios(response.config))
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
||||
if (options.showCodeMessage) {
|
||||
ElNotification({
|
||||
type: 'error',
|
||||
message: response.data.msg,
|
||||
})
|
||||
}
|
||||
// 自动跳转到路由name或path
|
||||
if (response.data.code == 302) {
|
||||
router.push({ path: response.data.data.routePath ?? '', name: response.data.data.routeName ?? '' })
|
||||
}
|
||||
if (response.data.code == 303) {
|
||||
// if (response.data.code == 409) {
|
||||
// if (!window.tokenRefreshing) {
|
||||
// window.tokenRefreshing = true
|
||||
// return refreshToken()
|
||||
// .then((res) => {
|
||||
// adminInfo.setToken(res.data.token, 'auth')
|
||||
// response.headers.token = `${res.data.token}`
|
||||
// window.requests.forEach((cb) => cb(res.data.token, 'admin-refresh'))
|
||||
// window.requests = []
|
||||
// return Axios(response.config)
|
||||
// })
|
||||
// .catch((err) => {
|
||||
// adminInfo.removeToken()
|
||||
// router.push({ name: 'adminLogin' })
|
||||
// return Promise.reject(err)
|
||||
// })
|
||||
// .finally(() => {
|
||||
// window.tokenRefreshing = false
|
||||
// })
|
||||
// } else {
|
||||
// return new Promise((resolve) => {
|
||||
// // 用函数形式将 resolve 存入,等待刷新后再执行
|
||||
// window.requests.push((token: string, type: string) => {
|
||||
// response.headers.token = `${token}`
|
||||
// resolve(Axios(response.config))
|
||||
// })
|
||||
// })
|
||||
// }
|
||||
// }
|
||||
// if (options.showCodeMessage) {
|
||||
// ElNotification({
|
||||
// type: 'error',
|
||||
// message: response.data.msg,
|
||||
// })
|
||||
// }
|
||||
// // 自动跳转到路由name或path
|
||||
// if (response.data.code == 302) {
|
||||
// router.push({ path: response.data.data.routePath ?? '', name: response.data.data.routeName ?? '' })
|
||||
// }
|
||||
if (response.data.code == 401) {
|
||||
let routerPath = adminBaseRoute.path
|
||||
|
||||
// 需要登录,清理 token,转到登录页
|
||||
if (response.data.data.type == 'need login') {
|
||||
userInfo.removeToken()
|
||||
routerPath += '/login'
|
||||
}
|
||||
router.push({ path: routerPath })
|
||||
}
|
||||
// code不等于1, 页面then内的具体逻辑就不执行了
|
||||
|
44
ui/dasadmin/src/utils/crypto.ts
Normal file
44
ui/dasadmin/src/utils/crypto.ts
Normal file
@ -0,0 +1,44 @@
|
||||
import CryptoJS from 'crypto-js'
|
||||
|
||||
const key = ''
|
||||
|
||||
export function encrypt_aes(plaintText: string, iv: string) {
|
||||
const encryptedData = CryptoJS.AES.encrypt(plaintText, key, {
|
||||
iv,
|
||||
|
||||
mode: CryptoJS.mode.CBC,
|
||||
|
||||
padding: CryptoJS.pad.Pkcs7,
|
||||
})
|
||||
|
||||
const encryptedBase64Str = encryptedData.toString()
|
||||
|
||||
// 需要读取encryptedData上的ciphertext.toString()才能拿到跟Java一样的密文
|
||||
|
||||
const encryptedStr = encryptedData.ciphertext.toString()
|
||||
|
||||
return encryptedData.toString(CryptoJS.format.Base64)
|
||||
}
|
||||
|
||||
export function decrypt_aes(word: string, iv: string) {
|
||||
var decrypt = CryptoJS.AES.decrypt(word, key, {
|
||||
iv,
|
||||
mode: CryptoJS.mode.CBC,
|
||||
padding: CryptoJS.pad.Pkcs7,
|
||||
})
|
||||
//解密后,需要按照Utf8的方式将明文转位字符串
|
||||
var decryptedStr = decrypt.toString(CryptoJS.enc.Utf8)
|
||||
|
||||
return decryptedStr
|
||||
}
|
||||
|
||||
export function generateRandomNumber(length: number) {
|
||||
// 生成一个指定长度的随机数字字符串
|
||||
let result = ''
|
||||
const characters = '0123456789'
|
||||
const charactersLength = characters.length
|
||||
for (let i = 0; i < length; i++) {
|
||||
result += characters.charAt(Math.floor(Math.random() * charactersLength))
|
||||
}
|
||||
return result
|
||||
}
|
Loading…
Reference in New Issue
Block a user