Commit 2e541790 authored by youjie's avatar youjie

绑定邮箱

parent 6332dc3f
......@@ -66,6 +66,7 @@ onMounted(async () => {
</template>
<style lang="scss">
@import './assets/styles.css';
body {
--arcoblue-10: 245, 246, 240;//#F5F6F0
--arcoblue-9: 255, 151, 7;//#FF9707
......
<template>
<a-modal v-model:visible="modalVisible"
v-bind="modalConfig"
@ok="handleOk"
@cancel="handleCancel" draggable
:mask="modalMask">
<slot
name="modal"
:visible="modalVisible"
:data="modalrData"
:close="handleCancel">
</slot>
</a-modal>
</template>
<script setup lang="ts">
import { ref } from 'vue';
const props = defineProps({
modalMask: {
type: Boolean,
default: false,
},
modalConfig: {
type: Object,
default: null,
},
});
const emit = defineEmits<{
(e: 'modal-cancel'): void
(e: 'modal-ok', key: string): void
}>()
const modalrData = ref(null);
const modalVisible = ref(false);// 弹窗是否显示
const handleOk = () => {
modalrData.value = null;
modalVisible.value = false;
emit('modal-ok', 'key');
};
const handleCancel = () => {
modalrData.value = null;
modalVisible.value = false;
emit('modal-cancel');
};
const openModal = (data: null | any) => {
modalrData.value = data;
modalVisible.value = true;
}
defineExpose({
openModal,
handleCancel,
})
</script>
\ No newline at end of file
......@@ -161,6 +161,10 @@ export default {
systemMessage: '系统消息',
orderType: '所有类型',
management: '管理',
editEmail: '编辑邮箱',
binEmail: '绑定邮箱',
bindEmailFailed: '绑定邮箱失败',
save: '保存',
},
// HTTP 错误状态码
httpError: {
......
......@@ -92,6 +92,20 @@ export interface DistributorSelfRegisterDto {
wechatId?: null | string;
}
/**
* 修改邮箱请求参数
*/
export interface setRegisterDto {
/*** 电子邮箱(需要判断唯一,作为登录账号)*/
email: string;
/*** 确认密码*/
newPassword: string;
/*** 临时令牌token*/
temporaryToken?: null | string;
/*** 租户ID(手动传入,用于多租户隔离)*/
tenantId: string;
}
// ==================== 响应 DTO ====================
/**
......@@ -357,7 +371,7 @@ class UserService {
providerType
}
// OtaRequest 的响应拦截器会返回 response.data
const response = await OtaRequest.post(
const response = await OtaRequest.get(
'/member-auth/third-config',
data,
{
......@@ -523,6 +537,24 @@ class UserService {
)
return response as unknown as HttpResponse
}
/**
* 设置邮箱
* @param tenantId 租户ID(可选)
* @param email 邮箱地址
* @returns 验证结果
*/
static async resetEmail(tenantId: string,data: setRegisterDto,): Promise<HttpResponse> {
const response = await OtaRequest.post(
'/member-auth/reset-email',
data,
{
headers: tenantId ? {
'__tenant': tenantId
} : {}
}
)
return response as unknown as HttpResponse
}
}
export default UserService
......@@ -4,10 +4,11 @@ import SecureLS from 'secure-ls'
import UserService, {
type DistributorSelfRegisterDto,
ApplicationStatus,
type setRegisterDto,
} from '@/services/UserService'
import { ResultMessage } from '@/utils/message'
import i18n from '@/i18n'
import { string } from 'three/tsl'
const ls = new SecureLS({
isCompression: false,
encryptionSecret: '38c31684-d00d-30dc-82e0-fad9eec46d1d',
......@@ -40,8 +41,9 @@ export interface RegisterResult {
export const useUserStore = defineStore('user', {
state: () => ({
token: '' as string,
userInfo: {} as any,
memberData: {} as any,
userInfo: {} as any,// 登录用户信息
memberData: {} as any,// 登录会员数据
personalInfo: {} as any,// 个人信息
}),
getters: {
getUserToken: (state) => {
......@@ -53,6 +55,13 @@ export const useUserStore = defineStore('user', {
},
actions: {
/**
* 设置email
* @param email email
*/
setEmail(email: string){
this.personalInfo.email = email
},
/**
* 设置用户头像
* @param photo 头像URL
......@@ -60,6 +69,9 @@ export const useUserStore = defineStore('user', {
setPhoto(photo: string){
this.memberData.photo = photo
},
setPersonalInfo(personalInfo: any){
this.personalInfo = personalInfo
},
/**
* 账号密码登录 - 使用新的 UserService
* @param email 账号(邮箱)
......@@ -227,6 +239,35 @@ export const useUserStore = defineStore('user', {
}
}
},
/**
* 设置邮箱
* @param data 邮箱信息
*/
async setEmailAsync(data: setRegisterDto): Promise<UserLoginResult> {
try {
const response = await UserService.resetEmail(data.tenantId,data)
this.userInfo.email = data.email
return {
status: 'SUCCESS',
data: [response]
}
} catch (error: any) {
console.error('Bind email error:', error)
// 处理 ABP 错误响应
if (error.error) {
const errorInfo = error.error
const errorMessage = errorInfo.message || i18n.global.t('login.bindEmailFailed')
ResultMessage.Error(errorMessage)
} else {
ResultMessage.Error(error.message || i18n.global.t('httpError.networkError'))
}
return {
status: 'ERROR',
}
}
},
},
persist: {
storage: st,
......
......@@ -222,11 +222,11 @@ const getAppIdRedirectUri = async () => {
try {
// 获取微信登录AppID 域名
const response = await userStore.getUserWechatAppIdAsync(loginMsg.tenantId?.toString() || '',loginMsg.reType || 2)
console.log('微信appid-----', response)
if (response.status == 'SUCCESS') {
openInfo.value = response.data[0]
const { appId, redirectUri } = openInfo.value;
const url = `https://open.weixin.qq.com/connect/qrconnect?appid=${appId}&redirect_uri=${encodeURIComponent('https://www.oytour.com/#/login')}&response_type=code&scope=snsapi_login&wechat_redirect=${redirectUri}`;
const redirect_url = redirectUri?redirectUri:'https://www.oytour.com/#/login'
const url = `https://open.weixin.qq.com/connect/qrconnect?appid=${appId}&redirect_uri=${encodeURIComponent(redirect_url)}&response_type=code&scope=snsapi_login&state=${1}&wechat_redirect=${redirect_url}`;
window.location.href = url;
}
}catch (error: any) {
......
......@@ -289,18 +289,6 @@ const rules = computed(() => ({
{ required: true, message: t('login.emailRequired') },
{ type: 'email', message: t('login.emailInvalid') }
],
emailNum: [
{
required: true,
message: t('login.emailFormat'),
},
],
emailSuffix: [
{
required: true,
message: t('login.emailFormat'),
},
],
verificationCode: [
{
required: true,
......
......@@ -135,6 +135,7 @@ const goPage = (path:string) => {
const getPersonalInfor = async () => {
const response = await UserService.memberCenterAsync(tenantId.value)
userData.value.userInfo = response
userStore.setPersonalInfo(response)
}
getPersonalInfor()
</script>
......
This diff is collapsed.
<template>
<div class="w-[977px] h-full flex flex-col flex-shrink-0 overflow-hidden">
<div 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="flex items-center p-[20px]">
<div class="bg-[#F3F3F2] rounded-full w-[52px] h-[52px] flex justify-center items-center mr-[16px]">
......@@ -11,7 +11,9 @@
</div>
<div class="mt-[10px] flex items-center">
<span class="text-base font-normal">{{ userInfo?.email || t('personal.unbound') }}</span>
<img class="w-[15px] h-[15px] ml-[10px] cursor-pointer" src="../../assets/images/personal/pen.png" alt="" />
<img class="w-[15px] h-[15px] ml-[10px] cursor-pointer"
src="../../assets/images/personal/pen.png"
alt="" @click="editEmailClick"/>
</div>
</div>
</div>
......@@ -97,7 +99,7 @@
<span class="myOrder-number">1128143664585527</span>
<span class="ml-[45px] SourceHanSansCN">{{ t('personal.reserveDate') }}:2025-11-10</span>
</div>
<img class="w-[14px] h-[16px]" src="../../assets/images/personal/right_n.png" alt="" />
<icon-delete size="16" class="customPrimary-5 cursor-pointer"/>
</div>
<div class="pl-[25px] pr-[24px] pt-[13px] pb-[19px]">
<div class="flex justify-between">
......@@ -106,7 +108,7 @@
</div>
<div class="flex justify-between items-center mt-[0px]">
<div class="flex-1 flex-shrink-0 flex items-center">
<img class="w-[12px] h-[14px] mr-[6px]" src="../../assets/images/personal/right_n.png" alt="" />
<icon-location size="14" class="customPrimary-5 mr-[6px]"/>
<span class="text-sm SourceHanSansCN">红宝石路188号B幢</span>
</div>
<span class="text-lg font-medium flex-shrink-0">¥1756.28</span>
......@@ -132,6 +134,16 @@
</a-scrollbar>
</div>
</div>
<Modal class="ModalRef"
ref="ModalRef"
:modal-config="modalConfig"
:modal-mask="true">
<template #modal="{ visible }">
<editEmail v-if="visible&&showType==1" :data="userInfo"
@save-success="handleSaveSuccess"
/>
</template>
</Modal>
</template>
<script setup lang="ts">
import { ref, inject, computed, watch } from 'vue'
......@@ -141,7 +153,8 @@ import { useSystemConfigStore } from '@/stores/index'
// 引入订单状态枚举
import OrderStatusEnum from '@/utils/orderStautsEnum'
import ListProductTypeEnum from '@/utils/listProductType'
import Modal from '@/components/common/modal.vue'
import editEmail from './components/myOrder/editEmail.vue'
const { t } = useI18n()
const userStore = useUserStore()
......@@ -149,7 +162,26 @@ const systemConfigStore = useSystemConfigStore()
const userData = ref({} as any)
userData.value = inject('userData')
const userInfo = ref({} as any)
const userInfo = ref(userStore.personalInfo)
const showType = ref(null as number | null)
const modalConfig = ref({
title: t('personal.editEmail'),
width: '500px',
maskClosable: false,
footer: false,
modalStyle:{
borderRadius: '8px',
},
// okButtonProps:{
// size:'large',
// },
// okText: t('personal.save'),
// cancelButtonProps:{
// size:'large',
// },
})
const ModalRef = ref<any>(null)
const orderList = ref<any>([])
const currentStatus = ref(0)
......@@ -197,12 +229,24 @@ const noMoreData = ref(false)
const scrollContainer = ref<any>(null)
const scrollThreshold = 0 // 阈值,距离底部多少距离时触发加载
watch(() => userData.value.userInfo, (newVal, oldVal) => {
watch(() => userStore.personalInfo, (newVal, oldVal) => {
if(newVal!=oldVal){
userInfo.value = userData.value.userInfo
userInfo.value = newVal
}
})
const handleSaveSuccess = (email: string) => {
ModalRef.value.handleCancel()
userStore.setEmail(email)
}
// 编辑邮箱 绑定邮箱
const editEmailClick = async () => {
showType.value = 1
modalConfig.value.title = userInfo.value.email?t('personal.editEmail'):t('personal.binEmail')
if(ModalRef.value) await ModalRef.value.openModal(userInfo.value)
}
const changeStatus = (key: number) => {
currentStatus.value = key
}
......
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