Commit 15d9ad15 authored by youjie's avatar youjie

账户中心

parent 2e541790
...@@ -13,16 +13,6 @@ const { t, locale } = useI18n() ...@@ -13,16 +13,6 @@ const { t, locale } = useI18n()
const useUser = useUserStore() const useUser = useUserStore()
const systemConfigStore = useSystemConfigStore() const systemConfigStore = useSystemConfigStore()
// 判断是否显示语言切换器
const showLanguageSwitcher = computed(() => {
// 在Layout页面中不显示APP.vue的语言切换器,因为Layout组件有自己的语言切换器
// const layoutRoutes = ['dashboard', 'products', 'orders', 'billing', 'account']
// const currentRouteName = route.name as string
// 如果当前路由使用Layout组件,则不显示APP.vue的语言切换器
return useUser.userInfo == null
})
// 监听语言变化,更新 Arco Design 国际化 // 监听语言变化,更新 Arco Design 国际化
watch(locale, async (newLocale) => { watch(locale, async (newLocale) => {
try { try {
...@@ -154,7 +144,9 @@ body { ...@@ -154,7 +144,9 @@ 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';
......
...@@ -165,6 +165,27 @@ export default { ...@@ -165,6 +165,27 @@ export default {
binEmail: '绑定邮箱', binEmail: '绑定邮箱',
bindEmailFailed: '绑定邮箱失败', bindEmailFailed: '绑定邮箱失败',
save: '保存', save: '保存',
bindGoogleAccount: '绑定google',
bindWechatAccount: '绑定微信',
bindLineAccount: '绑定Lnline',
bindGoogleFailed: '绑定google失败',
bindWechatSuccess: '绑定微信成功',
bindGoogleSuccess: '绑定google成功',
changeBind: '换绑',
unBind: '解绑',
securityLevel: '安全等级',
low: '低',
medium: '中',
high: '高',
passwordSecurityTip: ' 安全性高的密码可以使账号更安全。建议您定期更换密码,且设置一个包含数字和字母,并且长度超过8位以上的密码。',
bindPhoneTip: '绑定手机后,您即可享受手机号登录、动态码登录、找回密码等。为了帐号安全建议您在更换手机号后第一时间更换绑定手机。 ',
changeBindData: '更换',
bindEmailTip: '邮箱用于验证码接收,账户登录。',
bindWechatTip: '通过微信账户快速登录,无需输入密码。',
bindGoogleTip: '通过谷歌账户快速登录,无需输入密码。',
bindLineTip: '绑定手机后,您即可享受手机号登录、动态码登录、找回密码等。为了帐号安全建议您在更换手机号后第一时间更换绑定手机。',
notYetBin: '暂未绑定',
goBind: '去绑定',
}, },
// HTTP 错误状态码 // HTTP 错误状态码
httpError: { httpError: {
......
...@@ -336,6 +336,32 @@ class UserService { ...@@ -336,6 +336,32 @@ class UserService {
return response as unknown as HttpResponse return response as unknown as HttpResponse
} }
/**
* 谷歌绑定
* @param credential 谷歌token
* @returns
*/
static async GoogleBindAsync(tenantId: string,code: string,distributorId: number,parentId?: any,redirectUri?: string): Promise<HttpResponse> {
const data = {
tenantId,
code,
distributorId,
parentId,
redirectUri,
}
// OtaRequest 的响应拦截器会返回 response.data
const response = await OtaRequest.post(
'/member-auth/google-bind-by-code',
data,
{
headers: {
}
}
)
return response as unknown as HttpResponse
}
/** /**
* 微信登录 * 微信登录
* @param tenantId 租户ID * @param tenantId 租户ID
...@@ -361,6 +387,31 @@ class UserService { ...@@ -361,6 +387,31 @@ class UserService {
) )
return response as unknown as HttpResponse return response as unknown as HttpResponse
} }
/**
* 微信绑定
* @param tenantId 租户ID
* @returns
*/
static async wechatBindAsync(tenantId: string,code: string,distributorId: number,parentId?: any,redirectUri?: string): Promise<HttpResponse> {
const data = {
tenantId,
code,
distributorId,
parentId,
redirectUri,
}
// OtaRequest 的响应拦截器会返回 response.data
const response = await OtaRequest.post(
'/member-auth/we-chat-bind-by-code',
data,
{
headers: {
'__tenant': tenantId
}
}
)
return response as unknown as HttpResponse
}
/** /**
* 获取微信AppID * 获取微信AppID
* @param tenantId 租户ID * @param tenantId 租户ID
...@@ -555,6 +606,27 @@ class UserService { ...@@ -555,6 +606,27 @@ class UserService {
) )
return response as unknown as HttpResponse return response as unknown as HttpResponse
} }
/**
* 解绑外部登录账号
* @param tenantId 租户ID(可选)
* @param ProviderType 外部id
*/
static async externalunbindBind(tenantId: string,ProviderType:string): Promise<HttpResponse> {
const data = {
ProviderType
}
const response = await OtaRequest.get(
'/member-auth/member-center',
data,
{
headers: tenantId ? {
'__tenant': tenantId
} : {}
}
)
return response as unknown as HttpResponse
}
} }
export default UserService export default UserService
...@@ -42,8 +42,9 @@ export const useUserStore = defineStore('user', { ...@@ -42,8 +42,9 @@ export const useUserStore = defineStore('user', {
state: () => ({ state: () => ({
token: '' as string, token: '' as string,
userInfo: {} as any,// 登录用户信息 userInfo: {} as any,// 登录用户信息
loginType: 0 as number,// 0: 账号密码登录, 2: 微信登录, 3: Line登录, 1: Google登录 7: Facebook登录
memberData: {} as any,// 登录会员数据 memberData: {} as any,// 登录会员数据
personalInfo: {} as any,// 个人信息 personalInfor: {} as any,// 个人信息
}), }),
getters: { getters: {
getUserToken: (state) => { getUserToken: (state) => {
...@@ -60,7 +61,7 @@ export const useUserStore = defineStore('user', { ...@@ -60,7 +61,7 @@ export const useUserStore = defineStore('user', {
* @param email email * @param email email
*/ */
setEmail(email: string){ setEmail(email: string){
this.personalInfo.email = email this.personalInfor.email = email
}, },
/** /**
* 设置用户头像 * 设置用户头像
...@@ -69,8 +70,14 @@ export const useUserStore = defineStore('user', { ...@@ -69,8 +70,14 @@ export const useUserStore = defineStore('user', {
setPhoto(photo: string){ setPhoto(photo: string){
this.memberData.photo = photo this.memberData.photo = photo
}, },
setPersonalInfo(personalInfo: any){ setPersonalInfor(personalInfor: any){
this.personalInfo = personalInfo this.personalInfor = {
...this.personalInfor,
...personalInfor,
}
},
setLoginType(loginType: number){
this.loginType = loginType
}, },
/** /**
* 账号密码登录 - 使用新的 UserService * 账号密码登录 - 使用新的 UserService
...@@ -143,6 +150,29 @@ export const useUserStore = defineStore('user', { ...@@ -143,6 +150,29 @@ export const useUserStore = defineStore('user', {
} }
}, },
/**
* 谷歌绑定
* @param credential 谷歌凭证
*/
async setUserGoogleBindAsync(tenantId: string, code: string,distributorId: number,parentId?: any,redirectUri?: string): Promise<UserLoginResult> {
try {
const response = await UserService.GoogleBindAsync(tenantId, code,distributorId,parentId,redirectUri)
console.log('Google login response:', response)
return {
status: 'SUCCESS',
verify: false,
data: [response]
}
} catch (error: any) {
console.error('Google login error:', error)
ResultMessage.Error(error.message || i18n.global.t('login.googleLoginFailed'))
return {
status: 'ERROR',
verify: false
}
}
},
/** /**
* 微信登录 * 微信登录
* @param tenantId 租户ID * @param tenantId 租户ID
...@@ -169,6 +199,28 @@ export const useUserStore = defineStore('user', { ...@@ -169,6 +199,28 @@ export const useUserStore = defineStore('user', {
} }
}, },
/**
* 微信绑定
* @param tenantId 租户ID
*/
async setUserWechatBindAsync(tenantId: string, code: string,distributorId: number,parentId?: any,redirectUri?: string): Promise<UserLoginResult> {
try {
const response = await UserService.wechatBindAsync(tenantId, code,distributorId,parentId,redirectUri)
return {
status: 'SUCCESS',
verify: false,
data: [response]
}
} catch (error: any) {
console.error('Google login error:', error)
ResultMessage.Error(error.message|| i18n.global.t('login.wechatLoginFailed'))
return {
status: 'ERROR',
verify: false
}
}
},
/** /**
* 获取微信appid * 获取微信appid
* @param tenantId 租户ID * @param tenantId 租户ID
...@@ -247,7 +299,7 @@ export const useUserStore = defineStore('user', { ...@@ -247,7 +299,7 @@ export const useUserStore = defineStore('user', {
async setEmailAsync(data: setRegisterDto): Promise<UserLoginResult> { async setEmailAsync(data: setRegisterDto): Promise<UserLoginResult> {
try { try {
const response = await UserService.resetEmail(data.tenantId,data) const response = await UserService.resetEmail(data.tenantId,data)
this.userInfo.email = data.email this.personalInfor.email = data.email
return { return {
status: 'SUCCESS', status: 'SUCCESS',
data: [response] data: [response]
......
<template> <template>
<div class="login h-screen overflow-hidden"> <a-spin :loading="loading" class="login h-screen overflow-hidden">
<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 />
...@@ -123,7 +123,7 @@ ...@@ -123,7 +123,7 @@
</div> </div>
</div> </div>
</div> </div>
</div> </a-spin>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { ref, reactive, computed, onMounted } from "vue"; import { ref, reactive, computed, onMounted } from "vue";
...@@ -147,7 +147,7 @@ const { t } = useI18n(); ...@@ -147,7 +147,7 @@ const { t } = useI18n();
const userStore = useUserStore() const userStore = useUserStore()
const systemConfigStore = useSystemConfigStore() const systemConfigStore = useSystemConfigStore()
const loading = ref(false) const loading = ref(true)
const router = useRouter() const router = useRouter()
const googleButtonContainer = ref(null); const googleButtonContainer = ref(null);
...@@ -156,8 +156,8 @@ const loginMsg = reactive({ ...@@ -156,8 +156,8 @@ const loginMsg = reactive({
tenantId: systemConfigStore.tenantId || null, tenantId: systemConfigStore.tenantId || null,
reType: 0,//登录方式 0账号密码 1谷歌授权 3LINE授权 7FaceBook授权 reType: 0,//登录方式 0账号密码 1谷歌授权 3LINE授权 7FaceBook授权
openId: "", openId: "",
email: "2310721242@qq.com",// email: "",//2310721242@qq.com
password: 'yj123456',//123456 password: '',//yj123456
distributorId: systemConfigStore.distributorId as any, distributorId: systemConfigStore.distributorId as any,
parentId: null, parentId: null,
redirectUri: '', redirectUri: '',
...@@ -242,6 +242,7 @@ const useWechatLogin = async(code:string) => { ...@@ -242,6 +242,7 @@ const useWechatLogin = async(code:string) => {
try { try {
const response = await userStore.setUserWechatLoginAsync(loginMsg.tenantId?.toString() || '', code, loginMsg.distributorId,loginMsg.parentId,loginMsg.redirectUri) const response = await userStore.setUserWechatLoginAsync(loginMsg.tenantId?.toString() || '', code, loginMsg.distributorId,loginMsg.parentId,loginMsg.redirectUri)
if (response.status == 'SUCCESS') { if (response.status == 'SUCCESS') {
userStore.setLoginType(loginMsg.reType || 0)
Message.success(t('login.loginSuccess')) Message.success(t('login.loginSuccess'))
const forward = localStorage.getItem('forward') const forward = localStorage.getItem('forward')
localStorage.removeItem('forward') localStorage.removeItem('forward')
...@@ -317,6 +318,7 @@ const handleSignInSuccess = async (googleUser:any) => { ...@@ -317,6 +318,7 @@ const handleSignInSuccess = async (googleUser:any) => {
// 获取授权码 // 获取授权码
const response = await userStore.setUserGoogleLoginAsync(loginMsg.tenantId?.toString() || '', googleUser.credential, loginMsg.distributorId,loginMsg.parentId,loginMsg.redirectUri) const response = await userStore.setUserGoogleLoginAsync(loginMsg.tenantId?.toString() || '', googleUser.credential, loginMsg.distributorId,loginMsg.parentId,loginMsg.redirectUri)
if (response.status == 'SUCCESS') { if (response.status == 'SUCCESS') {
userStore.setLoginType(loginMsg.reType || 0)
Message.success(t('login.loginSuccess')) Message.success(t('login.loginSuccess'))
const forward = localStorage.getItem('forward') const forward = localStorage.getItem('forward')
localStorage.removeItem('forward') localStorage.removeItem('forward')
...@@ -363,6 +365,7 @@ const handleLogin = async () => { ...@@ -363,6 +365,7 @@ const handleLogin = async () => {
) )
loading.value = false loading.value = false
if (result.status == 'SUCCESS') { if (result.status == 'SUCCESS') {
userStore.setLoginType(loginMsg.reType || 0)
Message.success(t('login.loginSuccess')) Message.success(t('login.loginSuccess'))
const forward = localStorage.getItem('forward') const forward = localStorage.getItem('forward')
localStorage.removeItem('forward') localStorage.removeItem('forward')
...@@ -391,6 +394,7 @@ onMounted(async () => { ...@@ -391,6 +394,7 @@ onMounted(async () => {
const queryParams = query() const queryParams = query()
const code = queryParams.code const code = queryParams.code
if (code) { if (code) {
loginMsg.reType = 2
useWechatLogin(code) useWechatLogin(code)
} }
try { try {
...@@ -400,7 +404,9 @@ onMounted(async () => { ...@@ -400,7 +404,9 @@ 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>
<div class="h-screen overflow-hidden"> <a-spin :loading="loading" class="h-screen overflow-hidden">
<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 />
...@@ -55,7 +55,7 @@ ...@@ -55,7 +55,7 @@
<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')"
:maxLength="8" :maxLength="100"
:defaultVisibility="true" :defaultVisibility="true"
:invisible-button="false" :invisible-button="false"
size="large"> size="large">
...@@ -66,7 +66,7 @@ ...@@ -66,7 +66,7 @@
v-model="formData.newPassword" v-model="formData.newPassword"
size="large" size="large"
:placeholder="t('login.confirmPasswordRequired')" :placeholder="t('login.confirmPasswordRequired')"
:maxLength="8" :maxLength="100"
:defaultVisibility="true" :defaultVisibility="true"
:invisible-button="false" :invisible-button="false"
> >
...@@ -109,10 +109,10 @@ ...@@ -109,10 +109,10 @@
</div> </div>
</div> --> </div> -->
</div> </div>
</div> </a-spin>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { reactive, ref, watch, computed } from "vue"; import { reactive, ref, watch, computed, onMounted } from "vue";
import { useI18n } from "vue-i18n"; import { useI18n } from "vue-i18n";
import { useSystemConfigStore } from '@/stores/index' import { useSystemConfigStore } from '@/stores/index'
import loginHeader from "./components/header.vue"; import loginHeader from "./components/header.vue";
...@@ -177,7 +177,7 @@ const rules = computed(() => ({ ...@@ -177,7 +177,7 @@ const rules = computed(() => ({
})) }))
const loginPage = ref(null as unknown as HTMLElement) const loginPage = ref(null as unknown as HTMLElement)
const loading = ref(false) const loading = ref(true)
const currentStep = ref(1) const currentStep = ref(1)
// 判断用户是否已登录 // 判断用户是否已登录
...@@ -449,6 +449,11 @@ const init = async () => { ...@@ -449,6 +449,11 @@ const init = async () => {
init() init()
onMounted(() => {
setTimeout(()=>{
loading.value = false
},500)
})
</script> </script>
<style scoped lang="scss"> <style scoped lang="scss">
.light-login-bg { .light-login-bg {
......
<template> <template>
<div class="h-screen overflow-hidden"> <a-spin :loading="loading" class="h-screen overflow-hidden">
<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']">
...@@ -63,7 +63,7 @@ ...@@ -63,7 +63,7 @@
v-model="formData.password" v-model="formData.password"
size="large" size="large"
:placeholder="t('login.setPasswordRequired')" :placeholder="t('login.setPasswordRequired')"
:maxLength="8" :maxLength="100"
:defaultVisibility="true" :defaultVisibility="true"
:invisible-button="false" :invisible-button="false"
> >
...@@ -77,7 +77,7 @@ ...@@ -77,7 +77,7 @@
v-model="formData.confirmPassword" v-model="formData.confirmPassword"
size="large" size="large"
:placeholder="t('login.confirmPasswordRequired')" :placeholder="t('login.confirmPasswordRequired')"
:maxLength="8" :maxLength="100"
:defaultVisibility="true" :defaultVisibility="true"
:invisible-button="false" :invisible-button="false"
> >
...@@ -221,10 +221,10 @@ ...@@ -221,10 +221,10 @@
</div> </div>
<registerSuccess v-if="currentStep==3" /> <registerSuccess v-if="currentStep==3" />
</div> </div>
</div> </a-spin>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { reactive, ref, watch, computed, provide } from "vue"; import { reactive, ref, watch, computed, provide, onMounted } from "vue";
import { useI18n } from "vue-i18n"; import { useI18n } from "vue-i18n";
import { useRouter } from 'vue-router' import { useRouter } from 'vue-router'
import { Message } from '@arco-design/web-vue' import { Message } from '@arco-design/web-vue'
...@@ -331,7 +331,7 @@ const rules = computed(() => ({ ...@@ -331,7 +331,7 @@ const rules = computed(() => ({
const loginPage = ref(null) const loginPage = ref(null)
const currentStep = ref(1) const currentStep = ref(1)
const loading = ref(false) const loading = ref(true)
const isFromOta = ref(false) // 是否从 OTA 授权进入 const isFromOta = ref(false) // 是否从 OTA 授权进入
provide('currentStep', currentStep.value) provide('currentStep', currentStep.value)
...@@ -673,6 +673,11 @@ init() ...@@ -673,6 +673,11 @@ init()
getSimples() getSimples()
onMounted(() => {
setTimeout(()=>{
loading.value = false
},500)
})
</script> </script>
<style> <style>
.light-login-bg { .light-login-bg {
......
This diff is collapsed.
<template> <template>
<div class="flex flex flex-col w-[198px]"> <div class="flex flex flex-col w-[198px]">
<div class="h-full bg-[#F9F9F7] rounded-[14px]"> <div class="h-full bg-[#F9F9F7] rounded-[14px]">
<template v-if="userInfo">
<div class="mt-[37px] flex justify-center items-center"> <div class="mt-[37px] flex justify-center items-center">
<a-avatar class="LeftViewImg cursor-pointer flex-shrink-0 !w-[80px] !h-[80px]"> <a-avatar class="LeftViewImg cursor-pointer flex-shrink-0 !w-[80px] !h-[80px]">
<img class="w-full h-full cursor-pointer" <img class="w-full h-full cursor-pointer"
...@@ -37,6 +38,7 @@ ...@@ -37,6 +38,7 @@
</span> </span>
</div> </div>
</div> </div>
</template>
<a-divider class="border-[#ECECE7]"/> <a-divider class="border-[#ECECE7]"/>
<div class="flex items-center cursor-pointer py-[7px] rounded-[8px] pl-[27px] mb-[5px]"> <div class="flex items-center cursor-pointer py-[7px] rounded-[8px] pl-[27px] mb-[5px]">
...@@ -118,24 +120,24 @@ const userStore = useUserStore() ...@@ -118,24 +120,24 @@ const userStore = useUserStore()
const systemConfigStore = useSystemConfigStore() const systemConfigStore = useSystemConfigStore()
const tenantId = computed(() => systemConfigStore.tenantId) const tenantId = computed(() => systemConfigStore.tenantId)
const userData = ref({} as any) const userInfo = ref(null as any)
userData.value = inject('userData')
const userInfo = computed(() => userData.value.userInfo)
const activeMenu = ref(props.activeMenu) const activeMenu = ref(props.activeMenu)
watch(() => props.activeMenu, (newVal, oldVal) => { watch(() => props.activeMenu, (newVal, oldVal) => {
activeMenu.value = newVal activeMenu.value = newVal
}) })
watch(() => userStore.personalInfor, (newVal, oldVal) => {
userInfo.value = newVal
})
const goPage = (path:string) => { const goPage = (path:string) => {
router.push(path) router.push(path)
} }
const getPersonalInfor = async () => { const getPersonalInfor = async () => {
const response = await UserService.memberCenterAsync(tenantId.value) const response = await UserService.memberCenterAsync(tenantId.value)
userData.value.userInfo = response userStore.setPersonalInfor(response)
userStore.setPersonalInfo(response)
} }
getPersonalInfor() getPersonalInfor()
</script> </script>
......
...@@ -40,7 +40,7 @@ ...@@ -40,7 +40,7 @@
v-model="formData.password" v-model="formData.password"
size="large" size="large"
:placeholder="t('login.setPasswordRequired')" :placeholder="t('login.setPasswordRequired')"
:maxLength="8" :maxLength="100"
:defaultVisibility="true" :defaultVisibility="true"
:invisible-button="false" :invisible-button="false"
> >
...@@ -54,7 +54,7 @@ ...@@ -54,7 +54,7 @@
v-model="formData.newPassword" v-model="formData.newPassword"
size="large" size="large"
:placeholder="t('login.confirmPasswordRequired')" :placeholder="t('login.confirmPasswordRequired')"
:maxLength="8" :maxLength="100"
:defaultVisibility="true" :defaultVisibility="true"
:invisible-button="false" :invisible-button="false"
> >
...@@ -64,7 +64,7 @@ ...@@ -64,7 +64,7 @@
<div class="mt-[27px] w-full flex flex-col items-center items-center-button mb-[20px]"> <div class="mt-[27px] w-full flex flex-col items-center items-center-button mb-[20px]">
<div class="w-full " <div class="w-full "
:class="[(formData.email&&formData.verificationCode&&formData.verificationCode.length==6) :class="[(formData.email&&formData.verificationCode&&formData.verificationCode.length==6)
||(data.email&&formData.password&&formData.password.length==8 ||(data.email&&formData.password&&formData.password.length>=8
&&formData.password==formData.newPassword)?'isClick':'']"> &&formData.password==formData.newPassword)?'isClick':'']">
<a-button <a-button
type="primary" type="primary"
...@@ -103,7 +103,7 @@ const props = defineProps({ ...@@ -103,7 +103,7 @@ const props = defineProps({
}) })
const emit = defineEmits<{ const emit = defineEmits<{
(e: 'save-success', email: string): void (e: 'save-success'): void
}>() }>()
const { t } = useI18n(); const { t } = useI18n();
...@@ -410,7 +410,7 @@ const handleSubmit = async () => { ...@@ -410,7 +410,7 @@ const handleSubmit = async () => {
const response = await userStore.setEmailAsync(registerData) const response = await userStore.setEmailAsync(registerData)
if (response.status== 'SUCCESS') { if (response.status== 'SUCCESS') {
emit('save-success',formData.email) emit('save-success')
} }
} catch (error: any) { } catch (error: any) {
console.error('提交失败:', error) console.error('提交失败:', error)
......
...@@ -13,7 +13,7 @@ ...@@ -13,7 +13,7 @@
</div> </div>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { ref, computed,reactive, provide } from 'vue' import { ref, computed,reactive } from 'vue'
import { useRoute } from 'vue-router' import { useRoute } from 'vue-router'
import { useI18n } from 'vue-i18n' import { useI18n } from 'vue-i18n'
import LeftView from './components/LeftView.vue' import LeftView from './components/LeftView.vue'
...@@ -69,10 +69,6 @@ const menuList = ref([ ...@@ -69,10 +69,6 @@ const menuList = ref([
key: 'distributionCenter', key: 'distributionCenter',
}, },
]) ])
const userData = reactive({
userInfo: {},
})
provide('userData', userData)
</script> </script>
<style scoped> <style scoped>
......
<template> <template>
<div class="w-[977px] h-full flex flex-col flex-shrink-0"> <a-spin :loading="loading" class="w-[977px] h-full flex flex-col flex-shrink-0">
<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]">
...@@ -10,7 +10,7 @@ ...@@ -10,7 +10,7 @@
{{t('personal.bindingEmail')}} {{t('personal.bindingEmail')}}
</div> </div>
<div class="mt-[10px] flex items-center"> <div class="mt-[10px] flex items-center">
<span class="text-base font-normal">{{ userInfo?.email || t('personal.unbound') }}</span> <span class="text-base font-normal">{{ userInfor?.email || t('personal.unbound') }}</span>
<img class="w-[15px] h-[15px] ml-[10px] cursor-pointer" <img class="w-[15px] h-[15px] ml-[10px] cursor-pointer"
src="../../assets/images/personal/pen.png" src="../../assets/images/personal/pen.png"
alt="" @click="editEmailClick"/> alt="" @click="editEmailClick"/>
...@@ -50,7 +50,7 @@ ...@@ -50,7 +50,7 @@
</div> </div>
<div class="flex justify-between items-center text-base relative"> <div class="flex justify-between items-center text-base relative">
<div class="flex"> <div class="flex">
<div v-for="(item,index) in orderList" <div v-for="(item,index) in orderTypes"
class="myOrder-status px-[13px] py-[22px] cursor-pointer relative" class="myOrder-status px-[13px] py-[22px] cursor-pointer relative"
:class="[currentStatus==item.value?'active font-medium':'font-light']" :class="[currentStatus==item.value?'active font-medium':'font-light']"
@click="changeStatus(item.value)">{{ item.label }} @click="changeStatus(item.value)">{{ item.label }}
...@@ -87,7 +87,7 @@ ...@@ -87,7 +87,7 @@
</div> </div>
<a-divider class="!m-[0]"/> <a-divider class="!m-[0]"/>
<div class="flex-1 flex flex-col flex-shrink-0" <div class="flex-1 flex flex-col flex-shrink-0"
:class="[!(dataList.length==0&&!loding)?'items-center justify-center':'']"> :class="[!(dataList.length==0&&!loading)?'items-center justify-center':'']">
<a-scrollbar class="max-h-[615px] overflow-auto" <a-scrollbar class="max-h-[615px] overflow-auto"
@scroll="handleDivScroll" @scroll="handleDivScroll"
ref="scrollContainer"> ref="scrollContainer">
...@@ -127,26 +127,26 @@ ...@@ -127,26 +127,26 @@
</div> </div>
</div> </div>
</div> </div>
<div v-else-if="dataList.length==0&&!loding" class="flex flex-col items-center justify-center"> <div v-else-if="dataList.length==0&&!loading" class="flex flex-col items-center justify-center">
<img class="w-[250px] h-[213px]" src="../../assets/images/personal/wsj.png" alt="" /> <img class="w-[250px] h-[213px]" src="../../assets/images/personal/wsj.png" alt="" />
<span class="text-base SourceHanSansCN mt-[15px]">{{ t('personal.noOrder') }}</span> <span class="text-base SourceHanSansCN mt-[15px]">{{ t('personal.noOrder') }}</span>
</div> </div>
</a-scrollbar> </a-scrollbar>
</div> </div>
</div> </a-spin>
<Modal class="ModalRef" <Modal class="ModalRef"
ref="ModalRef" ref="ModalRef"
:modal-config="modalConfig" :modal-config="modalConfig"
:modal-mask="true"> :modal-mask="true">
<template #modal="{ visible }"> <template #modal="{ visible }">
<editEmail v-if="visible&&showType==1" :data="userInfo" <editEmail v-if="visible&&showType==1" :data="userInfor"
@save-success="handleSaveSuccess" @save-success="handleSaveSuccess"
/> />
</template> </template>
</Modal> </Modal>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { ref, inject, computed, watch } from 'vue' import { ref, inject, computed, watch, onMounted } from 'vue'
import { useI18n } from 'vue-i18n' import { useI18n } from 'vue-i18n'
import { useUserStore } from '@/stores/user' import { useUserStore } from '@/stores/user'
import { useSystemConfigStore } from '@/stores/index' import { useSystemConfigStore } from '@/stores/index'
...@@ -162,7 +162,7 @@ const systemConfigStore = useSystemConfigStore() ...@@ -162,7 +162,7 @@ const systemConfigStore = useSystemConfigStore()
const userData = ref({} as any) const userData = ref({} as any)
userData.value = inject('userData') userData.value = inject('userData')
const userInfo = ref(userStore.personalInfo) const userInfor = ref(null as any)
const showType = ref(null as number | null) const showType = ref(null as number | null)
const modalConfig = ref({ const modalConfig = ref({
...@@ -183,6 +183,7 @@ const modalConfig = ref({ ...@@ -183,6 +183,7 @@ const modalConfig = ref({
}) })
const ModalRef = ref<any>(null) const ModalRef = ref<any>(null)
const orderTypes = ref<any>([])
const orderList = ref<any>([]) const orderList = ref<any>([])
const currentStatus = ref(0) const currentStatus = ref(0)
const productTypeList = ref<any>([]) const productTypeList = ref<any>([])
...@@ -197,23 +198,23 @@ productTypeList.value.push({ ...@@ -197,23 +198,23 @@ productTypeList.value.push({
}) })
// console.log(productTypeList.value,'--------') // console.log(productTypeList.value,'--------')
orderList.value.push({ orderTypes.value.push({
value: 0, value: 0,
label: t('personal.orderStatus.ALL'), label: t('personal.orderStatus.ALL'),
}) })
orderList.value.push({ orderTypes.value.push({
value: OrderStatusEnum.UN_PAY.value, value: OrderStatusEnum.UN_PAY.value,
label: OrderStatusEnum.UN_PAY.desc, label: OrderStatusEnum.UN_PAY.desc,
}) })
orderList.value.push({ orderTypes.value.push({
value: OrderStatusEnum.PAYED.value, value: OrderStatusEnum.PAYED.value,
label: OrderStatusEnum.PAYED.desc, label: OrderStatusEnum.PAYED.desc,
}) })
orderList.value.push({ orderTypes.value.push({
value: OrderStatusEnum.FINISH.value, value: OrderStatusEnum.FINISH.value,
label: OrderStatusEnum.FINISH.desc, label: OrderStatusEnum.FINISH.desc,
}) })
orderList.value.push({ orderTypes.value.push({
value: OrderStatusEnum.CANCEL.value, value: OrderStatusEnum.CANCEL.value,
label: OrderStatusEnum.CANCEL.desc, label: OrderStatusEnum.CANCEL.desc,
}) })
...@@ -224,27 +225,26 @@ const queryParams = ref<any>({ ...@@ -224,27 +225,26 @@ const queryParams = ref<any>({
orderStatus: currentStatus.value, orderStatus: currentStatus.value,
}) })
const dataList = ref<any>([]) const dataList = ref<any>([])
const loding = ref(false) const loading = ref(true)
const noMoreData = ref(false) const noMoreData = ref(true)
const scrollContainer = ref<any>(null) const scrollContainer = ref<any>(null)
const scrollThreshold = 0 // 阈值,距离底部多少距离时触发加载 const scrollThreshold = 0 // 阈值,距离底部多少距离时触发加载
watch(() => userStore.personalInfo, (newVal, oldVal) => { watch(() => userStore.personalInfor, (newVal, oldVal) => {
if(newVal!=oldVal){ if(newVal!=oldVal){
userInfo.value = newVal userInfor.value = newVal
} }
}) })
const handleSaveSuccess = (email: string) => { const handleSaveSuccess = () => {
ModalRef.value.handleCancel() ModalRef.value.handleCancel()
userStore.setEmail(email)
} }
// 编辑邮箱 绑定邮箱 // 编辑邮箱 绑定邮箱
const editEmailClick = async () => { const editEmailClick = async () => {
showType.value = 1 showType.value = 1
modalConfig.value.title = userInfo.value.email?t('personal.editEmail'):t('personal.binEmail') modalConfig.value.title = userInfor.value.email?t('personal.editEmail'):t('personal.binEmail')
if(ModalRef.value) await ModalRef.value.openModal(userInfo.value) if(ModalRef.value) await ModalRef.value.openModal(userInfor.value)
} }
const changeStatus = (key: number) => { const changeStatus = (key: number) => {
...@@ -256,7 +256,7 @@ const loadData = async () => { ...@@ -256,7 +256,7 @@ const loadData = async () => {
// 处理 div 滚动事件(核心修改) // 处理 div 滚动事件(核心修改)
const handleDivScroll = (e: any) => { const handleDivScroll = (e: any) => {
if (loding.value || noMoreData.value) return; if (loading.value || noMoreData.value) return;
const container = e.target; const container = e.target;
if (!container) return; if (!container) return;
// 计算滚动位置(兼容不同浏览器) // 计算滚动位置(兼容不同浏览器)
...@@ -271,6 +271,11 @@ const handleDivScroll = (e: any) => { ...@@ -271,6 +271,11 @@ const handleDivScroll = (e: any) => {
} }
} }
onMounted(() => {
setTimeout(()=>{
loading.value = false
})
})
</script> </script>
<style scoped lang="scss"> <style scoped lang="scss">
.myOrderData{ .myOrderData{
......
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