Commit c5d4c613 authored by youjie's avatar youjie

账号中心

parent 15d9ad15
...@@ -144,9 +144,6 @@ body { ...@@ -144,9 +144,6 @@ body {
.customColor-text-7{color: var(--customColor-text-7);} .customColor-text-7{color: var(--customColor-text-7);}
.customColor-text-6{color: var(--customColor-text-6);} .customColor-text-6{color: var(--customColor-text-6);}
.customColor-text-5{color: var(--customColor-text-5);} .customColor-text-5{color: var(--customColor-text-5);}
*{
color: var(--customColor-text-10);
}
@font-face{ @font-face{
font-family:'Source Han Sans CN ExtraLight'; font-family:'Source Han Sans CN ExtraLight';
......
...@@ -13,6 +13,8 @@ ...@@ -13,6 +13,8 @@
"coupon": "优惠券", "coupon": "优惠券",
"accountCenter": "账户中心", "accountCenter": "账户中心",
"commonPassengerInfo": "常用旅客信息", "commonPassengerInfo": "常用旅客信息",
"distributionCenter": "分销中心" "distributionCenter": "分销中心",
"resetPassword": "重置密码",
"editEmail": "绑定/修改邮箱"
} }
} }
\ No newline at end of file
...@@ -178,14 +178,18 @@ export default { ...@@ -178,14 +178,18 @@ export default {
medium: '中', medium: '中',
high: '高', high: '高',
passwordSecurityTip: ' 安全性高的密码可以使账号更安全。建议您定期更换密码,且设置一个包含数字和字母,并且长度超过8位以上的密码。', passwordSecurityTip: ' 安全性高的密码可以使账号更安全。建议您定期更换密码,且设置一个包含数字和字母,并且长度超过8位以上的密码。',
bindPhoneTip: '绑定手机后,您即可享受手机号登录、动态码登录、找回密码等。为了帐号安全建议您在更换手机号后第一时间更换绑定手机。 ', bindPhoneTip: '绑定手机。 ',
changeBindData: '更换', changeBindData: '更换',
bindEmailTip: '邮箱用于验证码接收,账户登录。', bindEmailTip: '邮箱用于验证码接收,账户登录。',
bindWechatTip: '通过微信账户快速登录,无需输入密码。', bindWechatTip: '通过微信账户快速登录,无需输入密码。',
bindGoogleTip: '通过谷歌账户快速登录,无需输入密码。', bindGoogleTip: '通过谷歌账户快速登录,无需输入密码。',
bindLineTip: '绑定手机后,您即可享受手机号登录、动态码登录、找回密码等。为了帐号安全建议您在更换手机号后第一时间更换绑定手机。', bindLineTip: '通过Line账户快速登录,无需输入密码。',
notYetBin: '暂未绑定', notYetBin: '暂未绑定',
goBind: '去绑定', goBind: '去绑定',
confirmChange: '确认修改',
return: '返回',
oldPassword: '旧密码',
placeholderNewPassword: '请输入新密码',
}, },
// HTTP 错误状态码 // HTTP 错误状态码
httpError: { httpError: {
......
...@@ -21,7 +21,7 @@ import Headers from './components/Headers.vue' ...@@ -21,7 +21,7 @@ import Headers from './components/Headers.vue'
const { t } = useI18n() const { t } = useI18n()
const route = useRoute() const route = useRoute()
const collapsed = ref(false) const loading = ref(true)
// 当前激活的菜单 // 当前激活的菜单
...@@ -70,13 +70,10 @@ const menuList = ref([ ...@@ -70,13 +70,10 @@ const menuList = ref([
} }
]) ])
// 菜单点击
const handleMenuClick = (key: string) => {
}
onMounted(() => { onMounted(() => {
setTimeout(()=>{
loading.value = false
},500)
}) })
</script> </script>
......
...@@ -54,7 +54,17 @@ const router = createRouter({ ...@@ -54,7 +54,17 @@ const router = createRouter({
component: () => import ('../views/personalCenter/distributionCenter.vue') component: () => import ('../views/personalCenter/distributionCenter.vue')
}, },
] ]
} },
{
path: '/resetPassword',
meta: { title: "page.resetPassword" },
component: () => import ('../views/personalCenter/resetPassword.vue')
},
{
path: '/editEmail',
meta: { title: "page.editEmail" },
component: () => import ('../views/personalCenter/editEmail.vue')
},
] ]
}, },
{ {
...@@ -70,7 +80,7 @@ const router = createRouter({ ...@@ -70,7 +80,7 @@ const router = createRouter({
meta: { title: "page.register" }, meta: { title: "page.register" },
}, },
{ {
path: "/forgePassword", path: "/forgePassword/:email?",
name: "forgePassword", name: "forgePassword",
component: () => import("../views/auth/forgePassword.vue"), component: () => import("../views/auth/forgePassword.vue"),
meta: { title: "page.forgotPassword" }, meta: { title: "page.forgotPassword" },
......
...@@ -242,6 +242,20 @@ export interface ResetPasswordDto { ...@@ -242,6 +242,20 @@ export interface ResetPasswordDto {
newPassword: string newPassword: string
} }
/**
* 更新密码请求参数
*/
export interface NewPasswordResponseDto {
/** 租户ID */
tenantId: string
/** 旧密码 */
oldPassword: string
/** 新密码 */
newPassword: string
}
/** /**
* 重置密码响应 * 重置密码响应
*/ */
...@@ -571,6 +585,32 @@ class UserService { ...@@ -571,6 +585,32 @@ class UserService {
return response as unknown as ResetPasswordResponseDto return response as unknown as ResetPasswordResponseDto
} }
/**
* 更新密码
* @param email 邮箱地址
* @param code 验证码
* @param newPassword 新密码
* @param confirmPassword 确认密码
* @param tenantId 租户ID(可选)
* @returns 重置结果
*/
static async setNewPasswordAsync(
tenantId: string,
oldPassword: string,
newPassword: string,
): Promise<HttpResponse> {
const data: NewPasswordResponseDto = {
tenantId,
oldPassword,
newPassword,
}
const response = await OtaRequest.post(
'/account/password',
data
)
return response as unknown as HttpResponse
}
/** /**
* 获取个人中心信息 * 获取个人中心信息
* @param tenantId 租户ID(可选) * @param tenantId 租户ID(可选)
......
<template> <template>
<a-spin :loading="loading" class="login h-screen overflow-hidden"> <div class="login h-screen overflow-hidden">
<a-spin :loading="loading" style="height: 100%;width: 100%;">
<div ref="loginPage" <div ref="loginPage"
class="light-login-bg pl-[85px] pr-[98px] pt-[33px] h-full !overflow-y-auto light-login-bg"> class="light-login-bg pl-[85px] pr-[98px] pt-[33px] h-full !overflow-y-auto light-login-bg">
<loginHeader /> <loginHeader />
...@@ -124,6 +125,7 @@ ...@@ -124,6 +125,7 @@
</div> </div>
</div> </div>
</a-spin> </a-spin>
</div>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { ref, reactive, computed, onMounted } from "vue"; import { ref, reactive, computed, onMounted } from "vue";
...@@ -391,6 +393,9 @@ const init = async () => { ...@@ -391,6 +393,9 @@ const init = async () => {
init() init()
onMounted(async () => { onMounted(async () => {
setTimeout(()=>{
loading.value = false
})
const queryParams = query() const queryParams = query()
const code = queryParams.code const code = queryParams.code
if (code) { if (code) {
...@@ -404,9 +409,7 @@ onMounted(async () => { ...@@ -404,9 +409,7 @@ onMounted(async () => {
await new Promise(resolve => setTimeout(resolve)); await new Promise(resolve => setTimeout(resolve));
renderGoogleButton() renderGoogleButton()
setTimeout(()=>{
loading.value = false
},500)
} catch (error) { } catch (error) {
console.error('SDK 初始化失败:', error); console.error('SDK 初始化失败:', error);
} }
......
<template> <template>
<a-spin :loading="loading" class="h-screen overflow-hidden"> <div class="h-screen overflow-hidden">
<a-spin :loading="loading" style="height: 100%;width: 100%;">
<div ref="loginPage" <div ref="loginPage"
class="light-login-bg pl-[85px] pr-[98px] pt-[33px] h-full !overflow-y-auto light-login-bgActive"> class="light-login-bg pl-[85px] pr-[98px] pt-[33px] h-full !overflow-y-auto light-login-bgActive">
<loginHeader /> <loginHeader />
...@@ -51,7 +52,7 @@ ...@@ -51,7 +52,7 @@
</a-form-item> </a-form-item>
</div> </div>
<div v-show="currentStep==2"> <div v-show="currentStep==2">
<a-form-item field="" :label="t('login.newPassword')"> <a-form-item field="password" :label="t('login.newPassword')">
<a-input-password class="formData-input" <a-input-password class="formData-input"
v-model="formData.password" v-model="formData.password"
:placeholder="t('login.passwordRequiredReset')" :placeholder="t('login.passwordRequiredReset')"
...@@ -61,7 +62,7 @@ ...@@ -61,7 +62,7 @@
size="large"> size="large">
</a-input-password> </a-input-password>
</a-form-item> </a-form-item>
<a-form-item field="" :label="t('login.confirmPassword')" class=""> <a-form-item field="newPassword" :label="t('login.confirmPassword')" class="">
<a-input-password class="formData-input" <a-input-password class="formData-input"
v-model="formData.newPassword" v-model="formData.newPassword"
size="large" size="large"
...@@ -93,7 +94,7 @@ ...@@ -93,7 +94,7 @@
<div class="mt-[62px] flex justify-center items-center"> <div class="mt-[62px] flex justify-center items-center">
<div class="w-[42px] h-[42px] rounded-full bg-[#FFFFFF] flex items-center justify-center <div class="w-[42px] h-[42px] rounded-full bg-[#FFFFFF] flex items-center justify-center
shadow-[0_0_10px_rgba(0,0,0,0.1)] cursor-pointer" shadow-[0_0_10px_rgba(0,0,0,0.1)] cursor-pointer"
@click="currentStep==1?goLogin('/login'):handlePrevious()"> @click="currentStep==1?goPage('/login'):handlePrevious()">
<icon-left size="24" strokeLinejoin="miter" /> <icon-left size="24" strokeLinejoin="miter" />
</div> </div>
</div> </div>
...@@ -110,6 +111,7 @@ ...@@ -110,6 +111,7 @@
</div> --> </div> -->
</div> </div>
</a-spin> </a-spin>
</div>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { reactive, ref, watch, computed, onMounted } from "vue"; import { reactive, ref, watch, computed, onMounted } from "vue";
...@@ -125,12 +127,13 @@ import UserService from '@/services/UserService' ...@@ -125,12 +127,13 @@ import UserService from '@/services/UserService'
const { t } = useI18n(); const { t } = useI18n();
const router = useRouter() const router = useRouter()
const { params } = router.currentRoute.value
const userStore = useUserStore() const userStore = useUserStore()
const systemConfigStore = useSystemConfigStore() const systemConfigStore = useSystemConfigStore()
const formData = reactive({ const formData = reactive({
tenantId: systemConfigStore.tenantId || null, tenantId: systemConfigStore.tenantId || null,
email: '2310721242@qq.com', email: '',
code: '', code: '',
password: '', password: '',
newPassword: '', newPassword: '',
...@@ -154,7 +157,7 @@ const rules = computed(() => ({ ...@@ -154,7 +157,7 @@ const rules = computed(() => ({
}, },
{ {
validator: (value: any, cb: any) => { validator: (value: any, cb: any) => {
if (!/^(?=.*[A-Za-z])(?=.*\d).{8,}$/.test(value)) { if (!/^(?=.*[A-Za-z])(?=.*\d)[A-Za-z\d\S]{8,}$/.test(value)) {
cb(t('login.passwordFormat')) cb(t('login.passwordFormat'))
}else { }else {
cb() cb()
...@@ -166,7 +169,7 @@ const rules = computed(() => ({ ...@@ -166,7 +169,7 @@ const rules = computed(() => ({
{ required: true, message: t('login.confirmPasswordRequired') }, { required: true, message: t('login.confirmPasswordRequired') },
{ {
validator: (value: any, cb: any) => { validator: (value: any, cb: any) => {
if (!/^(?=.*[A-Za-z])(?=.*\d).{8,}$/.test(value)) { if (!/^(?=.*[A-Za-z])(?=.*\d)[A-Za-z\d\S]{8,}$/.test(value)) {
cb(t('login.passwordFormat')) cb(t('login.passwordFormat'))
}else { }else {
cb() cb()
...@@ -227,8 +230,12 @@ const handleEmailBlur = async () => { ...@@ -227,8 +230,12 @@ const handleEmailBlur = async () => {
}else emailValidateStatus.value = 'success' }else emailValidateStatus.value = 'success'
} }
const goLogin = (path:string) => { const goPage = (path:string) => {
if(!params||!params.email){
router.push(path) router.push(path)
return
}
router.push('/accountCenter')
} }
// 验证邮箱是否可用 // 验证邮箱是否可用
...@@ -424,7 +431,11 @@ const handleSubmit = async () => { ...@@ -424,7 +431,11 @@ const handleSubmit = async () => {
Message.success(t('login.resetSuccess')) Message.success(t('login.resetSuccess'))
// 延迟跳转到登录页 // 延迟跳转到登录页
setTimeout(() => { setTimeout(() => {
if(params&&params.email){
router.push('/accountCenter')
}else{
router.push('/login') router.push('/login')
}
}, 2000) }, 2000)
} catch (error: any) { } catch (error: any) {
Message.error(error.message || t('login.resetFailed')) Message.error(error.message || t('login.resetFailed'))
...@@ -446,13 +457,16 @@ const init = async () => { ...@@ -446,13 +457,16 @@ const init = async () => {
router.replace('/') router.replace('/')
} }
} }
console.log('params',router.currentRoute.value.params.email)
init() if(!params||!params.email){
init()
}else{
formData.email = params.email
}
onMounted(() => { onMounted(() => {
setTimeout(()=>{ setTimeout(()=>{
loading.value = false loading.value = false
},500) })
}) })
</script> </script>
<style scoped lang="scss"> <style scoped lang="scss">
......
<template> <template>
<a-spin :loading="loading" class="h-screen overflow-hidden"> <div class="h-screen overflow-hidden">
<a-spin :loading="loading" style="height: 100%;width: 100%;">
<div ref="loginPage" <div ref="loginPage"
class="light-login-bg pl-[85px] pr-[98px] pt-[33px] h-full !overflow-y-auto" class="light-login-bg pl-[85px] pr-[98px] pt-[33px] h-full !overflow-y-auto"
:class="[currentStep<3?'light-login-bg':'light-login-bgActive']"> :class="[currentStep<3?'light-login-bg':'light-login-bgActive']">
...@@ -222,6 +223,7 @@ ...@@ -222,6 +223,7 @@
<registerSuccess v-if="currentStep==3" /> <registerSuccess v-if="currentStep==3" />
</div> </div>
</a-spin> </a-spin>
</div>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { reactive, ref, watch, computed, provide, onMounted } from "vue"; import { reactive, ref, watch, computed, provide, onMounted } from "vue";
...@@ -302,7 +304,7 @@ const rules = computed(() => ({ ...@@ -302,7 +304,7 @@ const rules = computed(() => ({
}, },
{ {
validator: (value: any, cb: any) => { validator: (value: any, cb: any) => {
if (!/^(?=.*[A-Za-z])(?=.*\d).{8,}$/.test(value)) { if (!/^(?=.*[A-Za-z])(?=.*\d)[A-Za-z\d\S]{8,}$/.test(value)) {
cb(t('login.passwordFormat')) cb(t('login.passwordFormat'))
}else if (value !== formData.confirmPassword) { }else if (value !== formData.confirmPassword) {
cb(t('login.passwordMismatch')) cb(t('login.passwordMismatch'))
...@@ -316,7 +318,7 @@ const rules = computed(() => ({ ...@@ -316,7 +318,7 @@ const rules = computed(() => ({
{ required: true, message: t('login.confirmPasswordRequired') }, { required: true, message: t('login.confirmPasswordRequired') },
{ {
validator: (value: any, cb: any) => { validator: (value: any, cb: any) => {
if (!/^(?=.*[A-Za-z])(?=.*\d).{8,}$/.test(value)) { if (!/^(?=.*[A-Za-z])(?=.*\d)[A-Za-z\d\S]{8,}$/.test(value)) {
cb(t('login.passwordFormat')) cb(t('login.passwordFormat'))
}else if (value !== formData.password) { }else if (value !== formData.password) {
cb(t('login.passwordMismatch')) cb(t('login.passwordMismatch'))
...@@ -676,7 +678,7 @@ getSimples() ...@@ -676,7 +678,7 @@ getSimples()
onMounted(() => { onMounted(() => {
setTimeout(()=>{ setTimeout(()=>{
loading.value = false loading.value = false
},500) })
}) })
</script> </script>
<style> <style>
......
This diff is collapsed.
...@@ -59,7 +59,9 @@ ...@@ -59,7 +59,9 @@
</span> </span>
<a-badge class="ml-[8px]" v-if="item.count" <a-badge class="ml-[8px]" v-if="item.count"
:count="item.count" :count="item.count"
:dotStyle="{ background: '#FF9707', minWidth: '16px', width: '16px', minHeight: '16px', height: '16px',fontSize:'12px',borderRadius:'16px',lineHeight:'15px' }" :dotStyle="{ background: '#FF9707', minWidth: '16px', width: '16px',
minHeight: '16px', height: '16px',fontSize:'12px',borderRadius:'16px',
lineHeight:'15px', color:'#fff' }"
/> />
</div> </div>
</div> </div>
......
...@@ -153,7 +153,7 @@ const rules = computed(() => ({ ...@@ -153,7 +153,7 @@ const rules = computed(() => ({
}, },
{ {
validator: (value: any, cb: any) => { validator: (value: any, cb: any) => {
if (!/^(?=.*[A-Za-z])(?=.*\d).{8,}$/.test(value)) { if (!/^(?=.*[A-Za-z])(?=.*\d)[A-Za-z\d\S]{8,}$/.test(value)) {
cb(t('login.passwordFormat')) cb(t('login.passwordFormat'))
}else { }else {
cb() cb()
...@@ -165,7 +165,7 @@ const rules = computed(() => ({ ...@@ -165,7 +165,7 @@ const rules = computed(() => ({
{ required: true, message: t('login.newPasswordRequired') }, { required: true, message: t('login.newPasswordRequired') },
{ {
validator: (value: any, cb: any) => { validator: (value: any, cb: any) => {
if (!/^(?=.*[A-Za-z])(?=.*\d).{8,}$/.test(value)) { if (!/^(?=.*[A-Za-z])(?=.*\d)[A-Za-z\d\S]{8,}$/.test(value)) {
cb(t('login.passwordFormat')) cb(t('login.passwordFormat'))
}else { }else {
cb() cb()
......
This diff is collapsed.
<template> <template>
<a-spin :loading="loading" class="w-[977px] h-full flex flex-col flex-shrink-0"> <div class="w-[977px] h-full flex flex-col flex-shrink-0">
<a-spin :loading="loading">
<div class="myOrderData rounded-[14px] flex justify-between pt-[22px] pb-[19px] pl-[16px] relative"> <div class="myOrderData rounded-[14px] flex justify-between pt-[22px] pb-[19px] pl-[16px] relative">
<div class="flex items-center p-[20px]"> <div class="flex items-center p-[20px]">
<div class="bg-[#F3F3F2] rounded-full w-[52px] h-[52px] flex justify-center items-center mr-[16px]"> <div class="bg-[#F3F3F2] rounded-full w-[52px] h-[52px] flex justify-center items-center mr-[16px]">
...@@ -134,6 +135,7 @@ ...@@ -134,6 +135,7 @@
</a-scrollbar> </a-scrollbar>
</div> </div>
</a-spin> </a-spin>
</div>
<Modal class="ModalRef" <Modal class="ModalRef"
ref="ModalRef" ref="ModalRef"
:modal-config="modalConfig" :modal-config="modalConfig"
......
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment