feat(user): add username modification function.

This commit is contained in:
Aqr-K
2024-10-17 18:56:44 +08:00
parent 2df4dc0535
commit 1c83752f56
5 changed files with 200 additions and 75 deletions

View File

@@ -59,7 +59,7 @@ onActivated(() => {
<LoadingBanner v-if="!isRefreshed" class="mt-12" />
<div v-if="allUsers.length > 0" class="grid gap-3 grid-user-card items-start">
<UserCard v-for="user in allUsers" :user="user" @remove="loadAllUsers" @save="loadAllUsers" />
<UserCard v-for="user in allUsers" :user="user" :users="allUsers" @remove="loadAllUsers" @save="loadAllUsers" />
</div>
<NoDataFound

View File

@@ -1,12 +1,12 @@
<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 { VForm } from 'vuetify/lib/components/index.mjs'
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 {useDisplay} from 'vuetify'
import store from "@/store";
import { useDisplay } from 'vuetify'
import store from '@/store'
// 显示器宽度
const display = useDisplay()
@@ -34,7 +34,10 @@ const secret = ref('')
const otpPassword = ref('')
// 当前头像缓存
const nowAvatar = ref(avatar1)
const currentAvatar = ref(avatar1)
// 当前用户名
const currentUserName = ref('')
// 当前用户信息
const accountInfo = ref<User>({
@@ -71,7 +74,7 @@ function changeAvatar(file: Event) {
fileReader.readAsDataURL(files[0])
fileReader.onload = () => {
if (typeof fileReader.result === 'string') {
nowAvatar.value = fileReader.result
currentAvatar.value = fileReader.result
$toast.success('新头像上传成功,待保存后生效!')
}
}
@@ -80,13 +83,13 @@ function changeAvatar(file: Event) {
// 重置默认头像
function resetDefaultAvatar() {
nowAvatar.value = avatar1
currentAvatar.value = avatar1
$toast.success('已重置为默认头像,待保存后生效!')
}
// 还原当前头像
function restoreNowAvatar() {
nowAvatar.value = accountInfo.value.avatar
function restoreCurrentAvatar() {
currentAvatar.value = accountInfo.value.avatar
$toast.success('已还原当前使用头像!')
}
@@ -99,7 +102,8 @@ async function loadAccountInfo() {
if (!accountInfo.value.avatar) {
accountInfo.value.avatar = avatar1
}
nowAvatar.value = accountInfo.value.avatar
currentAvatar.value = accountInfo.value.avatar
currentUserName.value = accountInfo.value.name
} catch (error) {
console.log(error)
}
@@ -107,26 +111,47 @@ async function loadAccountInfo() {
// 保存用户信息
async function saveAccountInfo() {
if (!currentUserName.value) {
$toast.error('用户名不能为空')
return
}
if (newPassword.value || confirmPassword.value) {
if (newPassword.value !== confirmPassword.value) {
$toast.error('两次输入的密码不一致')
return
}
accountInfo.value.password = newPassword.value
}
const oldUserName = accountInfo.value.name
const oldAvatar = accountInfo.value.avatar
accountInfo.value.avatar = nowAvatar.value
accountInfo.value.avatar = currentAvatar.value
accountInfo.value.name = currentUserName.value
try {
const result: { [key: string]: any } = await api.put('user/', accountInfo.value)
if (result.success) {
$toast.success('用户信息保存成功!')
if (oldAvatar !== nowAvatar.value) {
// 通知 localStorage 中的用户头像发生变化
store.commit('auth/setAvatar', nowAvatar.value)
if (oldUserName !== currentUserName.value) {
$toast.success(`${oldUserName}】更名【${currentUserName.value}】,用户信息保存成功!`)
// 更新本地用户名显示
store.commit('auth/setUserName', currentUserName.value)
} else {
$toast.success('用户信息保存成功!')
}
// 更新本地头像显示
if (oldAvatar !== currentAvatar.value) {
store.commit('auth/setAvatar', currentAvatar.value)
}
} else {
if (oldAvatar !== currentAvatar.value) {
$toast.error(`${oldUserName}】更名【${currentUserName.value}】,信息保存失败:${result.message}`)
} else {
$toast.error(`用户信息保存失败:${result.message}`)
}
// 失败缓存值还原
currentUserName.value = accountInfo.value.name
accountInfo.value.name = oldUserName
currentAvatar.value = accountInfo.value.avatar
accountInfo.value.avatar = oldAvatar
}
else $toast.error(`用户信息保存失败:${result.message}`)
} catch (error) {
console.log(error)
}
@@ -205,7 +230,7 @@ onMounted(() => {
// 监听 localStorage 中的用户头像变化
watch(() => store.state.auth.avatar, () => {
nowAvatar.value = store.state.auth.avatar
currentAvatar.value = store.state.auth.avatar
})
</script>
@@ -216,7 +241,7 @@ watch(() => store.state.auth.avatar, () => {
<VCard title="个人信息">
<VCardText class="d-flex">
<!-- 👉 Avatar -->
<VAvatar rounded="lg" size="100" class="me-6" :image="nowAvatar" />
<VAvatar rounded="lg" size="100" class="me-6" :image="currentAvatar" />
<!-- 👉 Upload Photo -->
<form class="d-flex flex-column justify-center gap-5">
@@ -235,14 +260,14 @@ watch(() => store.state.auth.avatar, () => {
@input="changeAvatar"
/>
<VBtn type="reset" color="error" variant="tonal" @click="restoreNowAvatar">
<VBtn type="reset" color="info" variant="tonal" @click="restoreCurrentAvatar">
<VIcon icon="mdi-refresh" />
<span v-if="display.mdAndUp.value" class="ms-2">还原当前头像</span>
<span v-if="display.mdAndUp.value" class="ms-2">重置</span>
</VBtn>
<VBtn type="reset" color="error" variant="tonal" @click="resetDefaultAvatar">
<VIcon icon="mdi-refresh" />
<span v-if="display.mdAndUp.value" class="ms-2">重置默认头像</span>
<VIcon icon="mdi-image-sync-outline" />
<span v-if="display.mdAndUp.value" class="ms-2">默认</span>
</VBtn>
<VBtn
@@ -266,10 +291,21 @@ watch(() => store.state.auth.avatar, () => {
<VForm class="mt-6">
<VRow>
<VCol md="6" cols="12">
<VTextField v-model="accountInfo.name" density="comfortable" readonly label="用户名" />
<VTextField
v-model="currentUserName"
density="comfortable"
clearable
label="用户名"
/>
</VCol>
<VCol cols="12" md="6">
<VTextField v-model="accountInfo.email" density="comfortable" label="邮箱" type="email" />
<VTextField
v-model="accountInfo.email"
density="comfortable"
clearable
label="邮箱"
type="email"
/>
</VCol>
<VCol cols="12" md="6">
<VTextField
@@ -277,6 +313,7 @@ watch(() => store.state.auth.avatar, () => {
density="comfortable"
:type="isNewPasswordVisible ? 'text' : 'password'"
:append-inner-icon="isNewPasswordVisible ? 'mdi-eye-off-outline' : 'mdi-eye-outline'"
clearable
label="新密码"
autocomplete=""
@click:append-inner="isNewPasswordVisible = !isNewPasswordVisible"
@@ -289,6 +326,7 @@ watch(() => store.state.auth.avatar, () => {
density="comfortable"
:type="isConfirmPasswordVisible ? 'text' : 'password'"
:append-inner-icon="isConfirmPasswordVisible ? 'mdi-eye-off-outline' : 'mdi-eye-outline'"
clearable
label="确认新密码"
@click:append-inner="isConfirmPasswordVisible = !isConfirmPasswordVisible"
/>
@@ -301,22 +339,34 @@ watch(() => store.state.auth.avatar, () => {
<VRow>
<VCol cols="12" md="6">
<VTextField v-model="accountInfo.settings.wechat_userid" density="comfortable" label="微信用户" />
<VTextField
v-model="accountInfo.settings.wechat_userid"
density="comfortable"
clearable
label="微信用户"
/>
</VCol>
<VCol cols="12" md="6">
<VTextField
v-model="accountInfo.settings.telegram_userid"
density="comfortable"
clearable
label="Telegram用户"
/>
</VCol>
<VCol cols="12" md="6">
<VTextField v-model="accountInfo.settings.slack_userid" density="comfortable" label="Slack用户" />
<VTextField
v-model="accountInfo.settings.slack_userid"
density="comfortable"
clearable
label="Slack用户"
/>
</VCol>
<VCol cols="12" md="6">
<VTextField
v-model="accountInfo.settings.vocechat_userid"
density="comfortable"
clearable
label="VoceChat用户"
/>
</VCol>
@@ -324,6 +374,7 @@ watch(() => store.state.auth.avatar, () => {
<VTextField
v-model="accountInfo.settings.synologychat_userid"
density="comfortable"
clearable
label="SynologyChat用户"
/>
</VCol>