feat: refactor layouts and login components

This commit is contained in:
skytek_xinliang
2026-03-30 15:04:27 +08:00
parent f7413111c0
commit 79b20ded3b
21 changed files with 159 additions and 210 deletions
+118
View File
@@ -0,0 +1,118 @@
<template>
<v-sheet v-bind="$attrs" class="verify-container mb-6 mb-md-4" color="transparent">
<div v-if="loading && !captchaImage" class="d-flex justify-center align-center py-4">
<v-progress-circular color="primary" indeterminate></v-progress-circular>
</div>
<div v-else class="d-flex align-center gap-2">
<!-- Captcha Image and Refresh -->
<div
class="captcha-wrapper d-flex align-center cursor-pointer me-1 me-md-2"
:title="props.refreshTitle"
@click="handleRefresh"
>
<img v-if="captchaImage" alt="Captcha" class="captcha-img" :src="captchaImage" />
<v-icon class="ms-2" color="grey" :icon="mdiRefresh"></v-icon>
</div>
<!-- Input and Verify -->
<v-text-field
v-model="inputCode"
:append-inner-icon="props.verified ? mdiCheckCircle : undefined"
bg-color="surface"
class="flex-grow-1"
color="primary"
density="compact"
:disabled="props.verified"
:error="!!errorMsg"
hide-details
:placeholder="props.captchaPlaceholder"
variant="outlined"
>
<template v-if="props.verified" #append-inner>
<v-icon color="success" :icon="mdiCheckCircle" />
</template>
</v-text-field>
</div>
<div v-if="errorMsg" class="text-caption text-error mt-1">
{{ errorMsg }}
</div>
</v-sheet>
</template>
<script setup lang="ts">
import { mdiCheckCircle, mdiRefresh } from '@mdi/js'
import { computed } from 'vue'
interface CaptchaPayload {
imgUrl?: string
id?: string
tokenValue?: string
}
interface Props {
captcha?: CaptchaPayload
modelValue?: string
loading?: boolean
errorMessage?: string
verified?: boolean
verifyText?: string
captchaPlaceholder?: string
refreshTitle?: string
}
const props = withDefaults(defineProps<Props>(), {
captcha: undefined,
modelValue: '',
loading: false,
errorMessage: '',
verified: false,
verifyText: '驗證',
captchaPlaceholder: '驗證碼',
refreshTitle: '點擊刷新驗證碼',
})
const emit = defineEmits<{
(event: 'update:modelValue', value: string): void
(event: 'refresh'): void
}>()
const captchaImage = computed(() => props.captcha?.imgUrl ?? '')
const inputCode = computed({
get: () => props.modelValue,
set: (val: string) => emit('update:modelValue', val),
})
const errorMsg = computed(() => props.errorMessage)
const loading = computed(() => props.loading)
function handleRefresh() {
if (props.verified) return
emit('refresh')
}
</script>
<style scoped>
.verify-container {
width: 100%;
}
.captcha-wrapper {
border: 1px solid rgba(var(--v-theme-on-surface), 0.12);
border-radius: 4px;
padding: 0 8px;
height: 40px;
background: rgb(var(--v-theme-surface));
display: flex;
align-items: center;
}
.captcha-img {
height: 100%;
width: auto;
display: block;
}
</style>