1.修复谷歌验证报错
2.修复商城配置为小数点后3位
This commit is contained in:
@@ -53,13 +53,13 @@ class AdminTotp
|
|||||||
return self::tfa()->getQRCodeImageAsDataUri($label, $secret);
|
return self::tfa()->getQRCodeImageAsDataUri($label, $secret);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function verifyCode(string $plainSecret, string $code): bool
|
public static function verifyCode(string $plainSecret, string $code, int $discrepancy = 2): bool
|
||||||
{
|
{
|
||||||
$code = trim($code);
|
$code = trim($code);
|
||||||
if (!preg_match('/^\d{6}$/', $code)) {
|
if (!preg_match('/^\d{6}$/', $code)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return self::tfa()->verifyCode($plainSecret, $code);
|
return self::tfa()->verifyCode($plainSecret, $code, $discrepancy);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function encryptSecret(string $plainSecret): string
|
public static function encryptSecret(string $plainSecret): string
|
||||||
|
|||||||
@@ -27,19 +27,29 @@ export function login(method: 'get' | 'post', params: object = {}, axiosConfig:
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function totpVerify(params: object = {}) {
|
export function totpVerify(params: object = {}) {
|
||||||
return createAxios({
|
return createAxios(
|
||||||
|
{
|
||||||
url: url + 'totpVerify',
|
url: url + 'totpVerify',
|
||||||
data: params,
|
data: params,
|
||||||
method: 'post',
|
method: 'post',
|
||||||
})
|
},
|
||||||
|
{
|
||||||
|
cancelDuplicateRequest: false,
|
||||||
|
}
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
export function totpBindInit(params: object = {}) {
|
export function totpBindInit(params: object = {}) {
|
||||||
return createAxios({
|
return createAxios(
|
||||||
|
{
|
||||||
url: url + 'totpBindInit',
|
url: url + 'totpBindInit',
|
||||||
data: params,
|
data: params,
|
||||||
method: 'post',
|
method: 'post',
|
||||||
})
|
},
|
||||||
|
{
|
||||||
|
cancelDuplicateRequest: false,
|
||||||
|
}
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
export function totpBindConfirm(params: object = {}) {
|
export function totpBindConfirm(params: object = {}) {
|
||||||
@@ -50,6 +60,7 @@ export function totpBindConfirm(params: object = {}) {
|
|||||||
method: 'post',
|
method: 'post',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
cancelDuplicateRequest: false,
|
||||||
showSuccessMessage: true,
|
showSuccessMessage: true,
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -13,4 +13,5 @@ export default {
|
|||||||
'Back to login': 'Back to login',
|
'Back to login': 'Back to login',
|
||||||
'Binding...': 'Binding...',
|
'Binding...': 'Binding...',
|
||||||
'Verifying...': 'Verifying...',
|
'Verifying...': 'Verifying...',
|
||||||
|
'Login failed, please try again': 'Sign-in could not be completed. Please try again or contact support.',
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,4 +13,5 @@ export default {
|
|||||||
'Back to login': '返回登录',
|
'Back to login': '返回登录',
|
||||||
'Binding...': '绑定中...',
|
'Binding...': '绑定中...',
|
||||||
'Verifying...': '验证中...',
|
'Verifying...': '验证中...',
|
||||||
|
'Login failed, please try again': '登录未完成,请重试或联系管理员',
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -91,6 +91,8 @@ router.afterEach(() => {
|
|||||||
ensureStandardHashUrl()
|
ensureStandardHashUrl()
|
||||||
if (window.existLoading) {
|
if (window.existLoading) {
|
||||||
loading.hide()
|
loading.hide()
|
||||||
|
} else {
|
||||||
|
window.existLoading = false
|
||||||
}
|
}
|
||||||
NProgress.done()
|
NProgress.done()
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -26,9 +26,11 @@ export const loading = {
|
|||||||
hide: () => {
|
hide: () => {
|
||||||
nextTick(() => {
|
nextTick(() => {
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
const el = document.querySelector('.block-loading')
|
document.querySelectorAll('.block-loading').forEach((el) => {
|
||||||
el && el.parentNode?.removeChild(el)
|
el.parentNode?.removeChild(el)
|
||||||
}, 1000)
|
})
|
||||||
|
window.existLoading = false
|
||||||
|
}, 100)
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -194,6 +194,28 @@ const unwrapLoginApiData = (res: anyObj | undefined): anyObj => {
|
|||||||
return res as anyObj
|
return res as anyObj
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** 从 login / totpVerify / totpBindConfirm 响应中解析 userInfo */
|
||||||
|
const extractLoginUserInfo = (res: anyObj | undefined): anyObj | undefined => {
|
||||||
|
const data = unwrapLoginApiData(res)
|
||||||
|
if (data.userInfo && typeof data.userInfo === 'object' && data.userInfo.token) {
|
||||||
|
return data.userInfo as anyObj
|
||||||
|
}
|
||||||
|
if (data.token) {
|
||||||
|
return data as anyObj
|
||||||
|
}
|
||||||
|
return undefined
|
||||||
|
}
|
||||||
|
|
||||||
|
const finishLoginWithApiResponse = (res: anyObj | undefined) => {
|
||||||
|
const userInfo = extractLoginUserInfo(res)
|
||||||
|
if (userInfo) {
|
||||||
|
navigateAfterLogin(userInfo)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
handleLoginApiResult(res)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
const handleLoginApiResult = (res: anyObj | undefined) => {
|
const handleLoginApiResult = (res: anyObj | undefined) => {
|
||||||
if (!res || typeof res !== 'object') {
|
if (!res || typeof res !== 'object') {
|
||||||
return
|
return
|
||||||
@@ -211,7 +233,6 @@ const handleLoginApiResult = (res: anyObj | undefined) => {
|
|||||||
navigateAfterLogin(data.userInfo)
|
navigateAfterLogin(data.userInfo)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
const tempToken = data.tempToken || data.temp_token
|
const tempToken = data.tempToken || data.temp_token
|
||||||
if (data.type === 'need_totp' && tempToken) {
|
if (data.type === 'need_totp' && tempToken) {
|
||||||
state.step = 'totp'
|
state.step = 'totp'
|
||||||
@@ -311,13 +332,16 @@ const resetToLogin = () => {
|
|||||||
|
|
||||||
const navigateAfterLogin = (userInfo: anyObj) => {
|
const navigateAfterLogin = (userInfo: anyObj) => {
|
||||||
if (!userInfo?.token) {
|
if (!userInfo?.token) {
|
||||||
|
ElMessage.error(t('login.Login failed, please try again'))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
abortLoginPrefetch()
|
abortLoginPrefetch()
|
||||||
adminInfo.dataFill(userInfo, false)
|
adminInfo.setToken(userInfo.token, 'auth')
|
||||||
nextTick(() => {
|
if (userInfo.refresh_token) {
|
||||||
|
adminInfo.setToken(userInfo.refresh_token, 'refresh')
|
||||||
|
}
|
||||||
|
adminInfo.dataFill(userInfo, ['token', 'refresh_token'])
|
||||||
router.replace({ path: adminBaseRoutePath })
|
router.replace({ path: adminBaseRoutePath })
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
@@ -365,13 +389,17 @@ const onSubmit = (captchaInfo = '') => {
|
|||||||
form.captchaInfo = captchaInfo
|
form.captchaInfo = captchaInfo
|
||||||
login('post', form)
|
login('post', form)
|
||||||
.then((res) => {
|
.then((res) => {
|
||||||
handleLoginApiResult(res)
|
finishLoginWithApiResponse(res)
|
||||||
})
|
})
|
||||||
.catch((err) => {
|
.catch((err) => {
|
||||||
if (err?.code === 'ERR_CANCELED' || err?.message === 'canceled') {
|
if (err?.code === 'ERR_CANCELED' || err?.message === 'canceled') {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
if (err && typeof err === 'object' && 'code' in err) {
|
||||||
handleLoginApiResult(err as anyObj)
|
handleLoginApiResult(err as anyObj)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
console.log(err)
|
||||||
})
|
})
|
||||||
.finally(() => {
|
.finally(() => {
|
||||||
state.submitLoading = false
|
state.submitLoading = false
|
||||||
@@ -400,7 +428,17 @@ const onTotpVerify = () => {
|
|||||||
keep: form.keep,
|
keep: form.keep,
|
||||||
})
|
})
|
||||||
.then((res) => {
|
.then((res) => {
|
||||||
navigateAfterLogin(res?.data?.userInfo)
|
if (!finishLoginWithApiResponse(res)) {
|
||||||
|
const code = res?.code
|
||||||
|
if (code === 1) {
|
||||||
|
ElMessage.error(t('login.Login failed, please try again'))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch((err) => {
|
||||||
|
if (err && typeof err === 'object' && 'msg' in err && err.msg) {
|
||||||
|
ElMessage.error(String(err.msg))
|
||||||
|
}
|
||||||
})
|
})
|
||||||
.finally(() => {
|
.finally(() => {
|
||||||
state.submitLoading = false
|
state.submitLoading = false
|
||||||
@@ -419,7 +457,17 @@ const onBindConfirm = () => {
|
|||||||
keep: form.keep,
|
keep: form.keep,
|
||||||
})
|
})
|
||||||
.then((res) => {
|
.then((res) => {
|
||||||
navigateAfterLogin(res?.data?.userInfo)
|
if (!finishLoginWithApiResponse(res)) {
|
||||||
|
const code = res?.code
|
||||||
|
if (code === 1) {
|
||||||
|
ElMessage.error(t('login.Login failed, please try again'))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch((err) => {
|
||||||
|
if (err && typeof err === 'object' && 'msg' in err && err.msg) {
|
||||||
|
ElMessage.error(String(err.msg))
|
||||||
|
}
|
||||||
})
|
})
|
||||||
.finally(() => {
|
.finally(() => {
|
||||||
state.submitLoading = false
|
state.submitLoading = false
|
||||||
|
|||||||
@@ -21,8 +21,8 @@
|
|||||||
v-model="form.unlock_ratio"
|
v-model="form.unlock_ratio"
|
||||||
:min="0"
|
:min="0"
|
||||||
:max="100"
|
:max="100"
|
||||||
:step="0.01"
|
:step="0.001"
|
||||||
:precision="2"
|
:precision="3"
|
||||||
controls-position="right"
|
controls-position="right"
|
||||||
class="w100"
|
class="w100"
|
||||||
/>
|
/>
|
||||||
@@ -82,8 +82,8 @@
|
|||||||
v-model="form.return_ratio"
|
v-model="form.return_ratio"
|
||||||
:min="0"
|
:min="0"
|
||||||
:max="100"
|
:max="100"
|
||||||
:step="0.01"
|
:step="0.001"
|
||||||
:precision="2"
|
:precision="3"
|
||||||
controls-position="right"
|
controls-position="right"
|
||||||
class="w100"
|
class="w100"
|
||||||
:disabled="!form.daily_points_enabled"
|
:disabled="!form.daily_points_enabled"
|
||||||
@@ -101,8 +101,8 @@
|
|||||||
v-model="form.lifetime_points_ratio"
|
v-model="form.lifetime_points_ratio"
|
||||||
:min="0"
|
:min="0"
|
||||||
:max="100"
|
:max="100"
|
||||||
:step="0.01"
|
:step="0.001"
|
||||||
:precision="2"
|
:precision="3"
|
||||||
controls-position="right"
|
controls-position="right"
|
||||||
class="w100"
|
class="w100"
|
||||||
:disabled="!form.lifetime_points_enabled"
|
:disabled="!form.lifetime_points_enabled"
|
||||||
|
|||||||
Reference in New Issue
Block a user