重组前端功能目录并统一代码规范工具链 (#10)
Reviewed-on: #10
This commit was merged in pull request #10.
This commit is contained in:
@@ -0,0 +1,217 @@
|
||||
<script setup lang="ts">
|
||||
import { onMounted, ref } from 'vue'
|
||||
import { RouterLink } from 'vue-router'
|
||||
import { NAlert, NButton, NCard, NForm, NInput, useMessage } from 'naive-ui'
|
||||
import { useAuthStore } from '@/features/auth/stores/auth'
|
||||
|
||||
const authStore = useAuthStore()
|
||||
const message = useMessage()
|
||||
|
||||
const usernameDraft = ref('')
|
||||
const currentPassword = ref('')
|
||||
const newPassword = ref('')
|
||||
const confirmNewPassword = ref('')
|
||||
const error = ref('')
|
||||
const success = ref('')
|
||||
const usernameSaving = ref(false)
|
||||
const passwordSaving = ref(false)
|
||||
|
||||
onMounted(() => {
|
||||
usernameDraft.value = authStore.profile?.username || ''
|
||||
})
|
||||
|
||||
async function saveUsername() {
|
||||
const nextUsername = usernameDraft.value.trim()
|
||||
|
||||
error.value = ''
|
||||
success.value = ''
|
||||
|
||||
if (!nextUsername) {
|
||||
error.value = '昵称不能为空。'
|
||||
return
|
||||
}
|
||||
if (nextUsername.length > 16) {
|
||||
error.value = '昵称不能超过 16 个字符。'
|
||||
return
|
||||
}
|
||||
if (nextUsername === authStore.profile?.username) {
|
||||
success.value = '昵称没有变化。'
|
||||
return
|
||||
}
|
||||
|
||||
usernameSaving.value = true
|
||||
try {
|
||||
await authStore.updateUsername(nextUsername)
|
||||
success.value = '昵称已更新。'
|
||||
message.success('昵称已更新')
|
||||
} catch (e) {
|
||||
error.value = e instanceof Error ? e.message : '昵称更新失败'
|
||||
} finally {
|
||||
usernameSaving.value = false
|
||||
}
|
||||
}
|
||||
|
||||
async function savePassword() {
|
||||
error.value = ''
|
||||
success.value = ''
|
||||
|
||||
if (newPassword.value.length < 8) {
|
||||
error.value = '新密码至少需要 8 位。'
|
||||
return
|
||||
}
|
||||
if (newPassword.value !== confirmNewPassword.value) {
|
||||
error.value = '两次输入的新密码不一致。'
|
||||
return
|
||||
}
|
||||
if (!currentPassword.value) {
|
||||
error.value = '请输入当前密码。'
|
||||
return
|
||||
}
|
||||
|
||||
passwordSaving.value = true
|
||||
try {
|
||||
await authStore.updatePassword(currentPassword.value, newPassword.value)
|
||||
currentPassword.value = ''
|
||||
newPassword.value = ''
|
||||
confirmNewPassword.value = ''
|
||||
success.value = '密码已更新。其他设备上的会话已退出。'
|
||||
message.success('密码已更新')
|
||||
} catch (e) {
|
||||
error.value = e instanceof Error ? e.message : '密码更新失败'
|
||||
} finally {
|
||||
passwordSaving.value = false
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div
|
||||
class="min-h-[calc(100vh-4rem)] bg-[linear-gradient(180deg,#e0f2fe_0%,#f8fafc_100%)] py-10"
|
||||
>
|
||||
<div class="oc-container oc-container--content">
|
||||
<RouterLink to="/profile">
|
||||
<NButton
|
||||
type="default"
|
||||
secondary
|
||||
strong
|
||||
class="oc-panel-button oc-panel-button--neutral"
|
||||
>← 返回个人主页</NButton
|
||||
>
|
||||
</RouterLink>
|
||||
|
||||
<div class="mt-6">
|
||||
<p class="oc-page-eyebrow">Account Settings</p>
|
||||
<h1 class="oc-page-title">个人资料设置</h1>
|
||||
<p class="oc-page-description">
|
||||
修改公开昵称和登录密码。昵称会显示在画廊、百科和地图中,且不能与其他用户重复。
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="mt-8 grid gap-6">
|
||||
<NAlert v-if="error" type="error" :show-icon="false" :bordered="false">
|
||||
{{ error }}
|
||||
</NAlert>
|
||||
<NAlert v-if="success" type="success" :show-icon="false" :bordered="false">
|
||||
{{ success }}
|
||||
</NAlert>
|
||||
|
||||
<NCard class="oc-panel-card border border-slate-200 bg-white" :bordered="false">
|
||||
<div class="grid gap-5 lg:grid-cols-[0.8fr_1.2fr] lg:items-start">
|
||||
<div>
|
||||
<h2 class="text-2xl font-bold text-slate-900">公开昵称</h2>
|
||||
<p class="mt-2 text-sm leading-6 text-slate-500">
|
||||
用于公开展示你的上传记录。保存前会检查是否与其他用户重复。
|
||||
</p>
|
||||
</div>
|
||||
<div class="grid gap-3 sm:grid-cols-[minmax(0,1fr)_auto]">
|
||||
<NInput
|
||||
v-model:value="usernameDraft"
|
||||
placeholder="输入新的昵称"
|
||||
maxlength="16"
|
||||
show-count
|
||||
/>
|
||||
<NButton
|
||||
secondary
|
||||
strong
|
||||
type="default"
|
||||
class="oc-panel-button oc-panel-button--teal"
|
||||
:loading="usernameSaving"
|
||||
@click="saveUsername"
|
||||
>
|
||||
保存昵称
|
||||
</NButton>
|
||||
</div>
|
||||
</div>
|
||||
</NCard>
|
||||
|
||||
<NCard class="oc-panel-card border border-slate-200 bg-white" :bordered="false">
|
||||
<div class="grid gap-5 lg:grid-cols-[0.8fr_1.2fr] lg:items-start">
|
||||
<div>
|
||||
<h2 class="text-2xl font-bold text-slate-900">登录密码</h2>
|
||||
<p class="mt-2 text-sm leading-6 text-slate-500">
|
||||
修改后下次登录需要使用新密码。建议使用至少 8 位且不易猜测的密码。
|
||||
</p>
|
||||
</div>
|
||||
<NForm class="grid gap-3" @submit.prevent="savePassword">
|
||||
<input
|
||||
:value="authStore.user?.email || ''"
|
||||
type="text"
|
||||
name="username"
|
||||
autocomplete="username"
|
||||
class="sr-only"
|
||||
tabindex="-1"
|
||||
aria-label="账户邮箱"
|
||||
readonly
|
||||
/>
|
||||
<NInput
|
||||
v-model:value="currentPassword"
|
||||
type="password"
|
||||
show-password-on="click"
|
||||
:input-props="{
|
||||
autocomplete: 'current-password',
|
||||
name: 'current-password',
|
||||
required: true,
|
||||
}"
|
||||
placeholder="当前密码"
|
||||
/>
|
||||
<NInput
|
||||
v-model:value="newPassword"
|
||||
type="password"
|
||||
show-password-on="click"
|
||||
:input-props="{
|
||||
autocomplete: 'new-password',
|
||||
name: 'new-password',
|
||||
required: true,
|
||||
}"
|
||||
placeholder="新密码"
|
||||
/>
|
||||
<NInput
|
||||
v-model:value="confirmNewPassword"
|
||||
type="password"
|
||||
show-password-on="click"
|
||||
:input-props="{
|
||||
autocomplete: 'new-password',
|
||||
name: 'confirm-new-password',
|
||||
required: true,
|
||||
}"
|
||||
placeholder="确认新密码"
|
||||
/>
|
||||
<div class="flex justify-end">
|
||||
<NButton
|
||||
secondary
|
||||
strong
|
||||
type="default"
|
||||
attr-type="submit"
|
||||
class="oc-panel-button oc-panel-button--teal"
|
||||
:loading="passwordSaving"
|
||||
>
|
||||
保存密码
|
||||
</NButton>
|
||||
</div>
|
||||
</NForm>
|
||||
</div>
|
||||
</NCard>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
Reference in New Issue
Block a user