fix #91 otp ui

This commit is contained in:
jxxghp
2024-03-28 19:04:15 +08:00
parent 984d502259
commit d244363321
3 changed files with 81 additions and 64 deletions
+1 -1
View File
@@ -428,7 +428,7 @@ watch(() => props.plugin?.has_update, (newHasUpdate, oldHasUpdate) => {
</div> </div>
<span v-if="props.count" class="absolute bottom-1 right-2 flex items-center"> <span v-if="props.count" class="absolute bottom-1 right-2 flex items-center">
<VIcon icon="mdi-fire" /> <VIcon icon="mdi-fire" />
<span class="text-sm ms-1">{{ props.count }}</span> <span class="text-sm ms-1">{{ props.count?.toLocaleString() }}</span>
</span> </span>
<VCardItem class="py-2"> <VCardItem class="py-2">
<VCardTitle class="flex items-center flex-row"> <VCardTitle class="flex items-center flex-row">
+1 -1
View File
@@ -179,8 +179,8 @@ onMounted(() => {
</VCol> </VCol>
<VCol cols="12"> <VCol cols="12">
<VTextField <VTextField
hint="非必传,如开启二次验证需填写"
v-model="form.otp_password" v-model="form.otp_password"
hint="非必须,如开启二次验证需填写"
label="二次验证" label="二次验证"
type="input" type="input"
/> />
+79 -62
View File
@@ -1,10 +1,11 @@
<script lang="ts" setup> <script lang="ts" setup>
import { useToast } from 'vue-toast-notification' import { useToast } from 'vue-toast-notification'
import QrcodeVue from 'qrcode.vue'
import { VForm } from 'vuetify/lib/components/index.mjs'
import { requiredValidator } from '@/@validators' import { requiredValidator } from '@/@validators'
import api from '@/api' import api from '@/api'
import type { User } from '@/api/types' import type { User } from '@/api/types'
import avatar1 from '@images/avatars/avatar-1.png' import avatar1 from '@images/avatars/avatar-1.png'
import QrcodeVue from 'qrcode.vue'
const isNewPasswordVisible = ref(false) const isNewPasswordVisible = ref(false)
const isConfirmPasswordVisible = ref(false) const isConfirmPasswordVisible = ref(false)
@@ -48,7 +49,7 @@ const accountInfo = ref<User>({
is_active: false, is_active: false,
is_superuser: false, is_superuser: false,
avatar: '', avatar: '',
is_otp: false is_otp: false,
}) })
// 所有用户信息 // 所有用户信息
@@ -193,10 +194,12 @@ async function getOtpUri() {
secret.value = result.data.secret secret.value = result.data.secret
qrCode.value = result.data.uri qrCode.value = result.data.uri
otpDialog.value = true otpDialog.value = true
} else { }
else {
$toast.error(`获取otp uri失败:${result.message}`) $toast.error(`获取otp uri失败:${result.message}`)
} }
} catch (error) { }
catch (error) {
console.log(error) console.log(error)
} }
} }
@@ -206,28 +209,29 @@ async function disableOtp() {
try { try {
const result: { [key: string]: any } = await api.post('user/otp/disable') const result: { [key: string]: any } = await api.post('user/otp/disable')
if (result.success) { if (result.success) {
accountInfo.value.is_otp = false; accountInfo.value.is_otp = false
$toast.success('关闭二次验证成功!') $toast.success('关闭登录二次验证成功!')
} }
else { else {
$toast.error(`关闭otp失败:${result.message}`) $toast.error(`关闭otp失败:${result.message}`)
} }
} catch (error) { }
catch (error) {
console.log(error) console.log(error)
} }
} }
// 启用Otp // 启用Otp
async function judgeOtpPassword() { async function judgeOtpPassword() {
if (!otpPassword) { if (!otpPassword.value) {
$toast.error('请填写6位验证码') $toast.error('请填写6位验证码')
return return
} }
try { try {
const result: { [key: string]: any } = await api.post('user/otp/judge', {'uri': otpUri.value, 'otpPassword': otpPassword.value}) const result: { [key: string]: any } = await api.post('user/otp/judge', { uri: otpUri.value, otpPassword: otpPassword.value })
if (result.success) { if (result.success) {
$toast.success('开启二次验证成功!') $toast.success('开启登录二次验证成功!')
otpDialog.value = false otpDialog.value = false
accountInfo.value.is_otp = true accountInfo.value.is_otp = true
} }
@@ -267,10 +271,11 @@ onMounted(() => {
color="primary" color="primary"
@click="refInputEl?.click()" @click="refInputEl?.click()"
> >
<VIcon <template #prepend>
icon="mdi-cloud-upload-outline" <VIcon
class="d-sm-none" icon="mdi-cloud-upload-outline"
/> />
</template>
<span class="d-none d-sm-block">上传头像</span> <span class="d-none d-sm-block">上传头像</span>
</VBtn> </VBtn>
@@ -289,21 +294,25 @@ onMounted(() => {
variant="tonal" variant="tonal"
@click="resetAvatar" @click="resetAvatar"
> >
<template #prepend>
<VIcon
icon="mdi-refresh"
/>
</template>
<span class="d-none d-sm-block">重置</span> <span class="d-none d-sm-block">重置</span>
<VIcon
icon="mdi-refresh"
class="d-sm-none"
/>
</VBtn> </VBtn>
<VBtn <VBtn
:color="accountInfo.is_otp? 'error': 'info'" :color="accountInfo.is_otp ? 'error' : 'info'"
@click.stop="accountInfo.is_otp? disableOtp(): getOtpUri()" variant="tonal"
@click.stop="accountInfo.is_otp ? disableOtp() : getOtpUri()"
> >
<VIcon <template #prepend>
icon="mdi-account-key" <VIcon
/> icon="mdi-account-key"
<span class="d-none d-sm-block">{{accountInfo.is_otp? "关闭验证": "二次验证"}}</span> />
</template>
<span class="d-none d-sm-block">{{ accountInfo.is_otp ? "关闭验证" : "二次验证" }}</span>
</VBtn> </VBtn>
</div> </div>
@@ -351,11 +360,9 @@ onMounted(() => {
<VTextField <VTextField
v-model="newPassword" v-model="newPassword"
:type="isNewPasswordVisible ? 'text' : 'password'" :type="isNewPasswordVisible ? 'text' : 'password'"
:append-inner-icon=" :append-inner-icon="isNewPasswordVisible ? 'mdi-eye-off-outline' : 'mdi-eye-outline'"
isNewPasswordVisible ? 'mdi-eye-off-outline' : 'mdi-eye-outline'
"
label="新密码" label="新密码"
autocomplete="new-password" autocomplete=""
@click:append-inner="isNewPasswordVisible = !isNewPasswordVisible" @click:append-inner="isNewPasswordVisible = !isNewPasswordVisible"
/> />
</VCol> </VCol>
@@ -557,46 +564,56 @@ onMounted(() => {
<!-- 二次验证弹窗 --> <!-- 二次验证弹窗 -->
<VDialog <VDialog
v-model="otpDialog" v-model="otpDialog"
max-width="40rem" max-width="45rem"
persistent persistent
z-index="1010" z-index="1010"
> >
<!-- 开启二次验证弹窗内容 --> <!-- 开启二次验证弹窗内容 -->
<VCard title="二次验证"> <VCard>
<DialogCloseBtn @click="otpDialog = false" />
<VCardText> <VCardText>
<VRow> <h4 class="text-h4 text-center mb-6 mt-5">
<VCol> 登录二次验证
<QrcodeVue :value="qrCode" :size="200" max-width="25rem"/> </h4><h5 class="text-h5 font-weight-medium mb-2">
</VCol> 身份验证器
<VCol> </h5>
<VRow> <p class="mb-6">
1你可以使用 Microsoft Authenticator (谷歌或其他支持软件如Keeper等) 软件扫描左侧二维码 使用像Google AuthenticatorMicrosoft AuthenticatorAuthy或1Password这样的身份验证器应用程序扫描二维码它将为您生成一个6位数的代码供您在下方输入
或者在 APP 中手动输入以下 Key </p>
<h1>{{secret}}</h1> <div class="my-6">
</VRow> <QrcodeVue class="mx-auto" :value="qrCode" :size="200" max-width="25rem" />
<VRow> </div>
2 APP 中获取6位验证码并输入 <VAlert
</VRow> :title="secret"
<VRow> variant="tonal"
<VTextField type="warning"
v-model="otpPassword" class="my-4"
type="text" text="如果您在使用二维码时遇到困难,请在您的应用程序中选择手动输入以上代码。"
label="输入验证码以确认开启双重验证" >
autocomplete="otpPassword" <template #prepend />
/> </VAlert>
</VRow> <VForm>
</VCol> <VTextField
</VRow> v-model="otpPassword"
type="text"
label="输入验证码以确认开启双重验证"
autocomplete=""
class="mb-8"
variant="outlined"
/>
<div class="d-flex justify-end flex-wrap gap-4">
<VBtn variant="outlined" color="secondary" @click="otpDialog = false">
取消
</VBtn>
<VBtn @click="judgeOtpPassword">
确定
<template #append>
<VIcon icon="mdi-check" />
</template>
</VBtn>
</div>
</VForm>
</VCardText> </VCardText>
<VCardActions>
<VBtn @click="otpDialog = false">
取消
</VBtn>
<VSpacer />
<VBtn @click="judgeOtpPassword">
确定
</VBtn>
</VCardActions>
</VCard> </VCard>
</VDialog> </VDialog>
</template> </template>