mirror of
https://github.com/continew-org/continew-admin-ui.git
synced 2025-09-09 18:59:26 +08:00
feat: 新增修改手机号、修改邮箱、修改密码、修改基本信息
This commit is contained in:
@@ -7,6 +7,7 @@ export interface UserInfo {
|
|||||||
email: string
|
email: string
|
||||||
phone: string
|
phone: string
|
||||||
avatar: string
|
avatar: string
|
||||||
|
pwdResetTime: string
|
||||||
registrationDate: string
|
registrationDate: string
|
||||||
deptName: string
|
deptName: string
|
||||||
roles: string[]
|
roles: string[]
|
||||||
|
@@ -2,9 +2,9 @@ export * from './user'
|
|||||||
export * from './role'
|
export * from './role'
|
||||||
export * from './menu'
|
export * from './menu'
|
||||||
export * from './dept'
|
export * from './dept'
|
||||||
export * from '../monitor/log'
|
export * from './announcement'
|
||||||
export * from './dict'
|
export * from './dict'
|
||||||
export * from './file'
|
export * from './file'
|
||||||
export * from './storage'
|
export * from './storage'
|
||||||
export * from './option'
|
export * from './option'
|
||||||
export * from './announcement'
|
export * from './user-center'
|
||||||
|
39
src/apis/system/user-center.ts
Normal file
39
src/apis/system/user-center.ts
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
import http from '@/utils/http'
|
||||||
|
import type * as System from '@/apis/system/type'
|
||||||
|
|
||||||
|
const BASE_URL = '/system/user'
|
||||||
|
|
||||||
|
/** @desc 修改用户基本信息 */
|
||||||
|
export function updateUserBaseInfo(data: { nickname: string; gender: number }) {
|
||||||
|
return http.patch(`${BASE_URL}/basic/info`, data)
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @desc 修改密码 */
|
||||||
|
export function updateUserPassword(data: { oldPassword: string; newPassword: string }) {
|
||||||
|
return http.patch(`${BASE_URL}/password`, data)
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @desc 修改手机号 */
|
||||||
|
export function updateUserPhone(data: { newPhone: string; captcha: string; currentPassword: string }) {
|
||||||
|
return http.patch(`${BASE_URL}/phone`, data)
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @desc 修改邮箱 */
|
||||||
|
export function updateUserEmail(data: { newEmail: string; captcha: string; currentPassword: string }) {
|
||||||
|
return http.patch(`${BASE_URL}/email`, data)
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @desc 获取绑定的三方账号 */
|
||||||
|
export function listUserSocial() {
|
||||||
|
return http.get<System.BindSocialAccountRes[]>(`${BASE_URL}/social`)
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @desc 绑定三方账号 */
|
||||||
|
export function bindSocialAccount(source: string, data: any) {
|
||||||
|
return http.post(`${BASE_URL}/social/${source}`, data)
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @desc 解绑三方账号 */
|
||||||
|
export function unbindSocialAccount(source: string) {
|
||||||
|
return http.del(`${BASE_URL}/social/${source}`)
|
||||||
|
}
|
@@ -37,25 +37,3 @@ export function exportUser(query: System.UserQuery) {
|
|||||||
export function resetUserPwd(data: any, id: string) {
|
export function resetUserPwd(data: any, id: string) {
|
||||||
return http.patch(`${BASE_URL}/${id}/password`, data)
|
return http.patch(`${BASE_URL}/${id}/password`, data)
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @desc 修改用户基础信息 */
|
|
||||||
export function updateUserBaseInfo(data: { nickname?: string; gender?: number }) {
|
|
||||||
return http.patch(`${BASE_URL}/basic/info`, data)
|
|
||||||
}
|
|
||||||
|
|
||||||
/** @desc 修改邮箱 */
|
|
||||||
export function updateUserEmail(data: { newEmail: string; captcha: string; currentPassword: string }) {
|
|
||||||
return http.patch(`${BASE_URL}/email`, data)
|
|
||||||
}
|
|
||||||
/**@desc 绑定三方账号 */
|
|
||||||
export function bindSocialAccount(source: string, data: any) {
|
|
||||||
return http.post(`${BASE_URL}/social/${source}`, data)
|
|
||||||
}
|
|
||||||
/**@desc 获取绑定的三方账号 */
|
|
||||||
export function getSocialAccount() {
|
|
||||||
return http.get<System.BindSocialAccountRes[]>(`${BASE_URL}/social`)
|
|
||||||
}
|
|
||||||
/**@desc 解绑三方账号 */
|
|
||||||
export function unbindSocialAccount(source: string) {
|
|
||||||
return http.del(`${BASE_URL}/social/${source}`)
|
|
||||||
}
|
|
||||||
|
@@ -26,6 +26,7 @@ const storeSetup = () => {
|
|||||||
email: '',
|
email: '',
|
||||||
phone: '',
|
phone: '',
|
||||||
avatar: '',
|
avatar: '',
|
||||||
|
pwdResetTime: '',
|
||||||
registrationDate: '',
|
registrationDate: '',
|
||||||
deptName: '',
|
deptName: '',
|
||||||
roles: [],
|
roles: [],
|
||||||
|
@@ -313,6 +313,12 @@
|
|||||||
.btn {
|
.btn {
|
||||||
height: 28px;
|
height: 28px;
|
||||||
width: 56px;
|
width: 56px;
|
||||||
|
&:hover {
|
||||||
|
-webkit-box-shadow: 0 2px 3px rgba(0, 0, 0, .15);
|
||||||
|
box-shadow: 0 2px 3px rgba(0, 0, 0, .15);
|
||||||
|
border-color: rgb(var(--primary-5));
|
||||||
|
color: var(--color-text-2);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -74,8 +74,10 @@ const handleLogin = async () => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const captchaTime = ref(60)
|
|
||||||
const captchaTimer = ref()
|
const captchaTimer = ref()
|
||||||
|
const captchaTime = ref(60)
|
||||||
|
const captchaBtnName = ref('获取验证码')
|
||||||
|
const captchaDisable = ref(false)
|
||||||
// 重置验证码
|
// 重置验证码
|
||||||
const resetCaptcha = () => {
|
const resetCaptcha = () => {
|
||||||
window.clearInterval(captchaTimer.value)
|
window.clearInterval(captchaTimer.value)
|
||||||
@@ -84,15 +86,13 @@ const resetCaptcha = () => {
|
|||||||
captchaDisable.value = false
|
captchaDisable.value = false
|
||||||
}
|
}
|
||||||
|
|
||||||
const captchaBtnName = ref('获取验证码')
|
|
||||||
const captchaLoading = ref(false)
|
const captchaLoading = ref(false)
|
||||||
const captchaDisable = ref(false)
|
|
||||||
// 获取验证码
|
// 获取验证码
|
||||||
const onCaptcha = async () => {
|
const onCaptcha = async () => {
|
||||||
|
if (captchaLoading.value) return
|
||||||
|
const isInvalid = await formRef.value?.validateField('email')
|
||||||
|
if (isInvalid) return
|
||||||
try {
|
try {
|
||||||
if (captchaLoading.value) return
|
|
||||||
const isInvalid = await formRef.value?.validateField('email')
|
|
||||||
if (isInvalid) return
|
|
||||||
captchaLoading.value = true
|
captchaLoading.value = true
|
||||||
captchaBtnName.value = '发送中...'
|
captchaBtnName.value = '发送中...'
|
||||||
// await getEmailCaptcha({
|
// await getEmailCaptcha({
|
||||||
|
@@ -77,8 +77,10 @@ const handleLogin = async () => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const captchaTime = ref(60)
|
|
||||||
const captchaTimer = ref()
|
const captchaTimer = ref()
|
||||||
|
const captchaTime = ref(60)
|
||||||
|
const captchaBtnName = ref('获取验证码')
|
||||||
|
const captchaDisable = ref(false)
|
||||||
// 重置验证码
|
// 重置验证码
|
||||||
const resetCaptcha = () => {
|
const resetCaptcha = () => {
|
||||||
window.clearInterval(captchaTimer.value)
|
window.clearInterval(captchaTimer.value)
|
||||||
@@ -87,15 +89,13 @@ const resetCaptcha = () => {
|
|||||||
captchaDisable.value = false
|
captchaDisable.value = false
|
||||||
}
|
}
|
||||||
|
|
||||||
const captchaBtnName = ref('获取验证码')
|
|
||||||
const captchaLoading = ref(false)
|
const captchaLoading = ref(false)
|
||||||
const captchaDisable = ref(false)
|
|
||||||
// 获取验证码
|
// 获取验证码
|
||||||
const onCaptcha = async () => {
|
const onCaptcha = async () => {
|
||||||
|
if (captchaLoading.value) return
|
||||||
|
const isInvalid = await formRef.value?.validateField('phone')
|
||||||
|
if (isInvalid) return
|
||||||
try {
|
try {
|
||||||
if (captchaLoading.value) return
|
|
||||||
const isInvalid = await formRef.value?.validateField('phone')
|
|
||||||
if (isInvalid) return
|
|
||||||
captchaLoading.value = true
|
captchaLoading.value = true
|
||||||
captchaBtnName.value = '发送中...'
|
captchaBtnName.value = '发送中...'
|
||||||
// await getSmsCaptcha({
|
// await getSmsCaptcha({
|
||||||
|
@@ -1,43 +0,0 @@
|
|||||||
<template>
|
|
||||||
<div class="card">
|
|
||||||
<div class="card_header">
|
|
||||||
<slot name="header"></slot>
|
|
||||||
</div>
|
|
||||||
<div class="card_body">
|
|
||||||
<slot name="body"> </slot>
|
|
||||||
</div>
|
|
||||||
<slot name="footer"></slot>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
<style scoped lang="scss">
|
|
||||||
.card {
|
|
||||||
width: 100%;
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
border-radius: 8px;
|
|
||||||
background: var(--color-bg-1);
|
|
||||||
border: 1px solid var(--color-neutral-2);
|
|
||||||
.card_header {
|
|
||||||
padding: 18px 20px;
|
|
||||||
background: -webkit-gradient(
|
|
||||||
linear,
|
|
||||||
left top,
|
|
||||||
left bottom,
|
|
||||||
from(rgba(232, 244, 255, 0.5)),
|
|
||||||
to(hsla(0, 0%, 100%, 0))
|
|
||||||
);
|
|
||||||
font-size: 16px;
|
|
||||||
font-weight: 500;
|
|
||||||
line-height: 24px;
|
|
||||||
background: linear-gradient(180deg, rgba(232, 244, 255, 0.5), hsla(0, 0%, 100%, 0));
|
|
||||||
}
|
|
||||||
.card_body {
|
|
||||||
flex: 1;
|
|
||||||
padding: 15px 28px;
|
|
||||||
}
|
|
||||||
.card_footer {
|
|
||||||
padding: 15px 28px;
|
|
||||||
border-top: 1px solid var(--color-neutral-2);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</style>
|
|
@@ -1,107 +1,184 @@
|
|||||||
<template>
|
<template>
|
||||||
<a-modal v-model:visible="visible" :title="title" @before-ok="save" @cancel="handleCancel">
|
<a-modal v-model:visible="visible" :title="title" @before-ok="save" @close="reset">
|
||||||
<a-form :model="form" ref="formRef">
|
<GiForm ref="formRef" v-model="form" :options="options" :columns="columns">
|
||||||
<a-form-item
|
<template #captcha>
|
||||||
field="newPhone"
|
<a-input v-model="form.captcha" placeholder="请输入验证码" :max-length="4" allow-clear style="flex: 1 1" />
|
||||||
label="新手机号"
|
<a-button
|
||||||
:rules="[{ required: true, match: Regexp.Phone, message: '请输入正确的手机号' }]"
|
class="captcha-btn"
|
||||||
v-if="verifyType === 'phone'"
|
:loading="captchaLoading"
|
||||||
>
|
:disabled="captchaDisable"
|
||||||
<a-input v-model="form.newPhone" />
|
size="large"
|
||||||
</a-form-item>
|
@click="onCaptcha"
|
||||||
<a-form-item
|
>
|
||||||
field="email"
|
{{ captchaBtnName }}
|
||||||
label="邮箱"
|
</a-button>
|
||||||
v-if="verifyType === 'email'"
|
</template>
|
||||||
:rules="[{ required: true, match: Regexp.Email, message: '请输入正确的邮箱' }]"
|
</GiForm>
|
||||||
>
|
|
||||||
<a-input v-model="form.email" />
|
|
||||||
</a-form-item>
|
|
||||||
<a-form-item field="verifyCode" label="验证码" :rules="[{ required: true, message: '请输入正确的验证码' }]">
|
|
||||||
<a-input v-model="form.captcha" />
|
|
||||||
<a-button type="outline" @click="onSendCaptcha">发送验证码</a-button>
|
|
||||||
</a-form-item>
|
|
||||||
<a-form-item
|
|
||||||
field="currentPassword"
|
|
||||||
label="当前密码"
|
|
||||||
:rules="[
|
|
||||||
{ required: true, message: '请输入当前密码' },
|
|
||||||
{ match: Regexp.Password, message: '请输入格式的密码' }
|
|
||||||
]"
|
|
||||||
>
|
|
||||||
<a-input v-model="form.currentPassword" />
|
|
||||||
</a-form-item>
|
|
||||||
</a-form>
|
|
||||||
</a-modal>
|
</a-modal>
|
||||||
</template>
|
</template>
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { computed, ref } from 'vue'
|
// import { getSmsCaptcha, getEmailCaptcha, updateUserEmail, updateUserPhone } from '@/apis'
|
||||||
import { getSmsCaptcha, getEmailCaptcha, updateUserEmail } from '@/apis'
|
import { Message } from '@arco-design/web-vue'
|
||||||
import { encryptByRsa } from '@/utils/encrypt'
|
// import { encryptByRsa } from '@/utils/encrypt'
|
||||||
import * as Regexp from '@/utils/regexp'
|
import * as Regexp from '@/utils/regexp'
|
||||||
import { Message, type Modal } from '@arco-design/web-vue'
|
|
||||||
import { useUserStore } from '@/stores'
|
import { useUserStore } from '@/stores'
|
||||||
const userStore = useUserStore()
|
import { type Columns, GiForm } from '@/components/GiForm'
|
||||||
const visible = ref<boolean>(false)
|
import { useForm } from '@/hooks'
|
||||||
const form = reactive({
|
|
||||||
|
const verifyType = ref()
|
||||||
|
const title = computed(() => (verifyType.value === 'phone' ? '修改手机号' : '修改邮箱'))
|
||||||
|
const formRef = ref<InstanceType<typeof GiForm>>()
|
||||||
|
|
||||||
|
const options: Options = {
|
||||||
|
form: {},
|
||||||
|
col: { xs: 24, sm: 24, md: 24, lg: 24, xl: 24, xxl: 24 },
|
||||||
|
btns: { hide: true }
|
||||||
|
}
|
||||||
|
|
||||||
|
const columns: Columns = [
|
||||||
|
{
|
||||||
|
label: '手机号',
|
||||||
|
field: 'newPhone',
|
||||||
|
type: 'input',
|
||||||
|
rules: [
|
||||||
|
{ required: true, message: '请输入手机号' },
|
||||||
|
{ match: Regexp.Phone, message: '请输入正确的手机号' }
|
||||||
|
],
|
||||||
|
hide: () => {
|
||||||
|
return verifyType.value !== 'phone'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '邮箱',
|
||||||
|
field: 'email',
|
||||||
|
type: 'input',
|
||||||
|
rules: [
|
||||||
|
{ required: true, message: '请输入邮箱' },
|
||||||
|
{ match: Regexp.Email, message: '请输入正确的邮箱' }
|
||||||
|
],
|
||||||
|
hide: () => {
|
||||||
|
return verifyType.value !== 'email'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '验证码',
|
||||||
|
field: 'captcha',
|
||||||
|
type: 'input',
|
||||||
|
rules: [{ required: true, message: '请输入验证码' }]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '当前密码',
|
||||||
|
field: 'currentPassword',
|
||||||
|
type: 'input',
|
||||||
|
rules: [{ required: true, message: '请输入当前密码' }]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
|
const { form, resetForm } = useForm({
|
||||||
newPhone: '',
|
newPhone: '',
|
||||||
captcha: '',
|
captcha: '',
|
||||||
currentPassword: '',
|
currentPassword: '',
|
||||||
email: ''
|
email: ''
|
||||||
})
|
})
|
||||||
const formRef = ref()
|
|
||||||
const verifyType = ref()
|
// 重置
|
||||||
const title = computed(() => {
|
const reset = () => {
|
||||||
return verifyType.value === 'phone' ? '修改手机号' : '修改邮箱'
|
formRef.value?.formRef?.resetFields()
|
||||||
})
|
resetForm()
|
||||||
const onSendCaptcha = () => {
|
resetCaptcha()
|
||||||
formRef.value.validateField(verifyType.value === 'phone' ? 'newPhone' : 'email', (validate) => {
|
|
||||||
if (!validate) {
|
|
||||||
// 发送验证码
|
|
||||||
if (verifyType.value === 'phone') {
|
|
||||||
//手机号
|
|
||||||
getSmsCaptcha({ phone: form.newPhone }).then((res) => {
|
|
||||||
console.log(res)
|
|
||||||
})
|
|
||||||
} else if (verifyType.value === 'email') {
|
|
||||||
//邮箱
|
|
||||||
getEmailCaptcha({ email: form.email }).then((res) => {
|
|
||||||
console.log(res)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
const save: InstanceType<typeof Modal>['onBeforeOk'] = async () => {
|
|
||||||
const flag = await formRef.value?.validate()
|
const captchaTimer = ref()
|
||||||
if (flag) return false
|
const captchaTime = ref(60)
|
||||||
|
const captchaBtnName = ref('获取验证码')
|
||||||
|
const captchaDisable = ref(false)
|
||||||
|
// 重置验证码
|
||||||
|
const resetCaptcha = () => {
|
||||||
|
window.clearInterval(captchaTimer.value)
|
||||||
|
captchaTime.value = 60
|
||||||
|
captchaBtnName.value = '获取验证码'
|
||||||
|
captchaDisable.value = false
|
||||||
|
}
|
||||||
|
|
||||||
|
const captchaLoading = ref(false)
|
||||||
|
// 获取验证码
|
||||||
|
const onCaptcha = async () => {
|
||||||
|
const isInvalid = await formRef.value?.formRef?.validateField(verifyType.value === 'phone' ? 'newPhone' : 'email')
|
||||||
|
if (isInvalid) return false
|
||||||
|
// 发送验证码
|
||||||
try {
|
try {
|
||||||
const res = await updateUserEmail({
|
captchaLoading.value = true
|
||||||
newEmail: form.email,
|
captchaBtnName.value = '发送中...'
|
||||||
captcha: form.captcha,
|
if (verifyType.value === 'phone') {
|
||||||
currentPassword: encryptByRsa(form.currentPassword) as string
|
// await getSmsCaptcha({
|
||||||
})
|
// phone: form.newPhone
|
||||||
if (res.code === 200) {
|
// })
|
||||||
Message.success('修改成功')
|
} else if (verifyType.value === 'email') {
|
||||||
visible.value = false
|
// await getEmailCaptcha({
|
||||||
// 修改成功后,重新获取用户信息
|
// email: form.email
|
||||||
userStore.getInfo()
|
// })
|
||||||
return true
|
|
||||||
}
|
}
|
||||||
|
captchaLoading.value = false
|
||||||
|
captchaDisable.value = true
|
||||||
|
captchaBtnName.value = `获取验证码(${(captchaTime.value -= 1)}s)`
|
||||||
|
// Message.success('发送成功')
|
||||||
|
Message.success('仅提供效果演示,实际使用请查看代码取消相关注释')
|
||||||
|
captchaTimer.value = window.setInterval(() => {
|
||||||
|
captchaTime.value -= 1
|
||||||
|
captchaBtnName.value = `获取验证码(${captchaTime.value}s)`
|
||||||
|
if (captchaTime.value <= 0) {
|
||||||
|
resetCaptcha()
|
||||||
|
}
|
||||||
|
}, 1000)
|
||||||
|
} catch (error) {
|
||||||
|
resetCaptcha()
|
||||||
|
} finally {
|
||||||
|
captchaLoading.value = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const userStore = useUserStore()
|
||||||
|
// 保存
|
||||||
|
const save = async () => {
|
||||||
|
const isInvalid = await formRef.value?.formRef?.validate()
|
||||||
|
if (isInvalid) return false
|
||||||
|
try {
|
||||||
|
if (verifyType.value === 'phone') {
|
||||||
|
// await updateUserEmail({
|
||||||
|
// newEmail: form.email,
|
||||||
|
// captcha: form.captcha,
|
||||||
|
// currentPassword: encryptByRsa(form.currentPassword) as string
|
||||||
|
// })
|
||||||
|
} else if (verifyType.value === 'email') {
|
||||||
|
// await updateUserPhone({
|
||||||
|
// newPhone: form.email,
|
||||||
|
// captcha: form.captcha,
|
||||||
|
// currentPassword: encryptByRsa(form.currentPassword) as string
|
||||||
|
// })
|
||||||
|
}
|
||||||
|
Message.success('修改成功')
|
||||||
|
// 修改成功后,重新获取用户信息
|
||||||
|
await userStore.getInfo()
|
||||||
|
return true
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
// return await saveApi()
|
|
||||||
}
|
|
||||||
const handleCancel = () => {
|
|
||||||
formRef.value?.resetFields()
|
|
||||||
visible.value = false
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const visible = ref(false)
|
||||||
|
// 打开弹框
|
||||||
const open = (type: string) => {
|
const open = (type: string) => {
|
||||||
verifyType.value = type
|
verifyType.value = type
|
||||||
visible.value = true
|
visible.value = true
|
||||||
}
|
}
|
||||||
defineExpose({
|
|
||||||
open
|
defineExpose({ open })
|
||||||
})
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.captcha-btn {
|
||||||
|
margin-left: 12px;
|
||||||
|
min-width: 98px;
|
||||||
|
border-radius: 4px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
@@ -7,7 +7,7 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="name">
|
<div class="name">
|
||||||
<span style="margin-right: 10px">{{ userInfo.nickname }}</span>
|
<span style="margin-right: 10px">{{ userInfo.nickname }}</span>
|
||||||
<icon-edit :size="16" class="btn" @click="onEditNickName" />
|
<icon-edit :size="16" class="btn" @click="onUpdate" />
|
||||||
</div>
|
</div>
|
||||||
<div class="id">
|
<div class="id">
|
||||||
<GiSvgIcon name="id" :size="16" />
|
<GiSvgIcon name="id" :size="16" />
|
||||||
@@ -43,22 +43,81 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="footer">注册于 {{ userInfo.registrationDate }}</div>
|
<div class="footer">注册于 {{ userInfo.registrationDate }}</div>
|
||||||
</a-card>
|
</a-card>
|
||||||
<VerifyModel ref="verifyModelRef" />
|
|
||||||
|
<a-modal v-model:visible="visible" title="修改基本信息" @before-ok="save" @close="reset">
|
||||||
|
<GiForm ref="formRef" v-model="form" :options="options" :columns="columns" />
|
||||||
|
</a-modal>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { updateUserBaseInfo } from '@/apis'
|
import { updateUserBaseInfo, updateUserPassword } from '@/apis'
|
||||||
import VerifyModel from '../components/VerifyModel.vue'
|
import { Message } from '@arco-design/web-vue'
|
||||||
|
import { type Columns, GiForm } from '@/components/GiForm'
|
||||||
|
import { useForm } from '@/hooks'
|
||||||
import { useUserStore } from '@/stores'
|
import { useUserStore } from '@/stores'
|
||||||
|
import { encryptByRsa } from '@/utils/encrypt'
|
||||||
|
|
||||||
const userStore = useUserStore()
|
const userStore = useUserStore()
|
||||||
const userInfo = computed(() => userStore.userInfo)
|
const userInfo = computed(() => userStore.userInfo)
|
||||||
const verifyModelRef = ref<InstanceType<typeof VerifyModel>>()
|
const formRef = ref<InstanceType<typeof GiForm>>()
|
||||||
const onEditNickName = () => {
|
|
||||||
userStore.editNickNameVisible = true
|
const options: Options = {
|
||||||
|
form: {},
|
||||||
|
col: { xs: 24, sm: 24, md: 24, lg: 24, xl: 24, xxl: 24 },
|
||||||
|
btns: { hide: true }
|
||||||
}
|
}
|
||||||
const openVerifyModel = (type: 'phone' | 'email') => {
|
|
||||||
verifyModelRef.value?.open(type)
|
const columns: Columns = [
|
||||||
|
{
|
||||||
|
label: '昵称',
|
||||||
|
field: 'nickname',
|
||||||
|
type: 'input',
|
||||||
|
rules: [{ required: true, message: '请输入昵称' }]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '性别',
|
||||||
|
field: 'gender',
|
||||||
|
type: 'radio-group',
|
||||||
|
options: [
|
||||||
|
{ label: '男', value: 1 },
|
||||||
|
{ label: '女', value: 2 },
|
||||||
|
{ label: '未知', value: 0, disabled: true }
|
||||||
|
],
|
||||||
|
rules: [{ required: true, message: '请选择性别' }]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
|
const { form, resetForm } = useForm({
|
||||||
|
nickname: userInfo.value.nickname,
|
||||||
|
gender: userInfo.value.gender
|
||||||
|
})
|
||||||
|
|
||||||
|
// 重置
|
||||||
|
const reset = () => {
|
||||||
|
formRef.value?.formRef?.resetFields()
|
||||||
|
resetForm()
|
||||||
|
}
|
||||||
|
|
||||||
|
const visible = ref(false)
|
||||||
|
// 修改
|
||||||
|
const onUpdate = async () => {
|
||||||
|
reset()
|
||||||
|
visible.value = true
|
||||||
|
}
|
||||||
|
|
||||||
|
// 保存
|
||||||
|
const save = async () => {
|
||||||
|
const isInvalid = await formRef.value?.formRef?.validate()
|
||||||
|
if (isInvalid) return false
|
||||||
|
try {
|
||||||
|
await updateUserBaseInfo(form)
|
||||||
|
Message.success('修改成功')
|
||||||
|
// 修改成功后,重新获取用户信息
|
||||||
|
await userStore.getInfo()
|
||||||
|
return true
|
||||||
|
} catch (error) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
@@ -24,7 +24,7 @@
|
|||||||
v-if="item.jumpMode == 'modal'"
|
v-if="item.jumpMode == 'modal'"
|
||||||
class="btn"
|
class="btn"
|
||||||
:type="item.status ? 'secondary' : 'primary'"
|
:type="item.status ? 'secondary' : 'primary'"
|
||||||
@click="openVerifyModel(item.type, item.status)"
|
@click="onUpdate(item.type, item.status)"
|
||||||
>
|
>
|
||||||
{{ item.status ? '修改' : '绑定' }}
|
{{ item.status ? '修改' : '绑定' }}
|
||||||
</a-button>
|
</a-button>
|
||||||
@@ -44,19 +44,15 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { socialAuth, getSocialAccount, unbindSocialAccount } from '@/apis'
|
import { socialAuth, listUserSocial, unbindSocialAccount } from '@/apis'
|
||||||
import type { ModeItem } from '../type'
|
import type { ModeItem } from '../type'
|
||||||
import { useUserStore } from '@/stores'
|
|
||||||
import VerifyModel from '../components/VerifyModel.vue'
|
import VerifyModel from '../components/VerifyModel.vue'
|
||||||
|
import { useUserStore } from '@/stores'
|
||||||
|
|
||||||
const userStore = useUserStore()
|
const userStore = useUserStore()
|
||||||
const userInfo = computed(() => userStore.userInfo)
|
const userInfo = computed(() => userStore.userInfo)
|
||||||
const verifyModelRef = ref<InstanceType<typeof VerifyModel>>()
|
|
||||||
const openVerifyModel = (type: 'phone' | 'email') => {
|
|
||||||
verifyModelRef.value?.open(type)
|
|
||||||
}
|
|
||||||
const socialList = ref<any>([])
|
|
||||||
|
|
||||||
|
const socialList = ref<any>([])
|
||||||
const modeList = ref<ModeItem[]>([])
|
const modeList = ref<ModeItem[]>([])
|
||||||
modeList.value = [
|
modeList.value = [
|
||||||
{
|
{
|
||||||
@@ -94,12 +90,8 @@ modeList.value = [
|
|||||||
status: socialList.value.some((el) => el == 'github')
|
status: socialList.value.some((el) => el == 'github')
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
const initData = () => {
|
|
||||||
getSocialAccount().then((res) => {
|
|
||||||
socialList.value = res.data.map((el) => el.source)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
|
// 绑定
|
||||||
const onBinding = (type: string, status: boolean) => {
|
const onBinding = (type: string, status: boolean) => {
|
||||||
if (!status) {
|
if (!status) {
|
||||||
socialAuth(type).then((res) => {
|
socialAuth(type).then((res) => {
|
||||||
@@ -114,6 +106,19 @@ const onBinding = (type: string, status: boolean) => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const verifyModelRef = ref<InstanceType<typeof VerifyModel>>()
|
||||||
|
// 修改
|
||||||
|
const onUpdate = (type: string) => {
|
||||||
|
verifyModelRef.value?.open(type)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 初始化数据
|
||||||
|
const initData = () => {
|
||||||
|
listUserSocial().then((res) => {
|
||||||
|
socialList.value = res.data.map((el) => el.source)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
initData()
|
initData()
|
||||||
})
|
})
|
||||||
|
@@ -19,7 +19,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="btn-wrapper">
|
<div class="btn-wrapper">
|
||||||
<a-switch disabled />
|
<a-switch disabled title="未开放" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@@ -9,7 +9,7 @@
|
|||||||
<div class="info-desc">为了您的账号安全,建议定期修改密码</div>
|
<div class="info-desc">为了您的账号安全,建议定期修改密码</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="btn-wrapper">
|
<div class="btn-wrapper">
|
||||||
<a-button class="btn">修改</a-button>
|
<a-button class="btn" @click="onUpdate">修改</a-button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="detail">
|
<div class="detail">
|
||||||
@@ -31,8 +31,91 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</a-card>
|
</a-card>
|
||||||
|
|
||||||
|
<a-modal v-model:visible="visible" title="修改密码" @before-ok="save" @close="reset">
|
||||||
|
<GiForm ref="formRef" v-model="form" :options="options" :columns="columns" />
|
||||||
|
</a-modal>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts" setup></script>
|
<script lang="ts" setup>
|
||||||
|
import { updateUserPassword } from '@/apis'
|
||||||
|
import { Message } from '@arco-design/web-vue'
|
||||||
|
import { encryptByRsa } from '@/utils/encrypt'
|
||||||
|
import { type Columns, GiForm } from '@/components/GiForm'
|
||||||
|
import { useForm } from '@/hooks'
|
||||||
|
import { useUserStore } from '@/stores'
|
||||||
|
|
||||||
|
const userStore = useUserStore()
|
||||||
|
const userInfo = computed(() => userStore.userInfo)
|
||||||
|
const formRef = ref<InstanceType<typeof GiForm>>()
|
||||||
|
|
||||||
|
const options: Options = {
|
||||||
|
form: {},
|
||||||
|
col: { xs: 24, sm: 24, md: 24, lg: 24, xl: 24, xxl: 24 },
|
||||||
|
btns: { hide: true }
|
||||||
|
}
|
||||||
|
|
||||||
|
const columns: Columns = [
|
||||||
|
{
|
||||||
|
label: '当前密码',
|
||||||
|
field: 'oldPassword',
|
||||||
|
type: 'input-password',
|
||||||
|
rules: [{ required: true, message: '请输入当前密码' }],
|
||||||
|
hide: () => {
|
||||||
|
return userInfo.pwdResetTime
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '新密码',
|
||||||
|
field: 'newPassword',
|
||||||
|
type: 'input-password',
|
||||||
|
rules: [{ required: true, message: '请输入新密码' }]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '确认新密码',
|
||||||
|
field: 'rePassword',
|
||||||
|
type: 'input-password',
|
||||||
|
rules: [{ required: true, message: '请再次输入新密码' }],
|
||||||
|
props: {
|
||||||
|
placeholder: '请再次输入新密码'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
|
const { form, resetForm } = useForm({
|
||||||
|
oldPassword: '',
|
||||||
|
newPassword: '',
|
||||||
|
rePassword: ''
|
||||||
|
})
|
||||||
|
|
||||||
|
// 重置
|
||||||
|
const reset = () => {
|
||||||
|
formRef.value?.formRef?.resetFields()
|
||||||
|
resetForm()
|
||||||
|
}
|
||||||
|
|
||||||
|
const visible = ref(false)
|
||||||
|
// 修改
|
||||||
|
const onUpdate = async () => {
|
||||||
|
reset()
|
||||||
|
visible.value = true
|
||||||
|
}
|
||||||
|
|
||||||
|
// 保存
|
||||||
|
const save = async () => {
|
||||||
|
const isInvalid = await formRef.value?.formRef?.validate()
|
||||||
|
if (isInvalid) return false
|
||||||
|
try {
|
||||||
|
await updateUserPassword({
|
||||||
|
oldPassword: encryptByRsa(form.oldPassword) || '',
|
||||||
|
newPassword: encryptByRsa(form.newPassword) || ''
|
||||||
|
})
|
||||||
|
Message.success('修改成功')
|
||||||
|
return true
|
||||||
|
} catch (error) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
<style lang="scss" scoped></style>
|
<style lang="scss" scoped></style>
|
||||||
|
Reference in New Issue
Block a user