From ec4015aabad9fafd64ad1af81f9ef3ff487015fb Mon Sep 17 00:00:00 2001 From: malei <> Date: Sat, 1 Aug 2026 20:31:53 +0800 Subject: [PATCH] feat: collect customer identity for assisted bookings --- README.md | 4 +++ src/api/index.js | 2 +- src/pages/appointment/AppointmentDetail.vue | 4 +-- .../appointment/CustAppointmentCreate.vue | 2 +- src/pages/home/Home.vue | 33 +++++++++++++++++-- src/pages/report/Report.vue | 1 - 6 files changed, 38 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index f051ff3..0161e32 100644 --- a/README.md +++ b/README.md @@ -135,6 +135,10 @@ npm run dev:h5 当前实现:**提交时登录 + guest 草稿恢复**。未登录用户可填写预约表单,提交时跳转登录页(带 `redirect` 回预约页并保留 `storeId`),登录成功后回到预约页并恢复 guest 草稿(草稿 key 不依赖 `userInfo.id`,避免 `userId: undefined`)。登录态用户继续按 `userId` 维度保存草稿。草稿有效期 7 天。 +### 门店代客预约身份 + +老板/员工在首页新建预约时必须填写宠主手机号,可选填宠主称呼。后端按手机号关联或创建 customer,并分别记录 `customerUserId` 与 `createdByUserId`;前端不得再把当前员工 `userId` 当作宠主提交。预约详情优先读取 `assignedStaffId`,兼容旧字段 `assignedUserId`。 + ## 前端 RC 发布门禁 发布前必须依次执行并全部通过: diff --git a/src/api/index.js b/src/api/index.js index afebc9a..7abe2c9 100644 --- a/src/api/index.js +++ b/src/api/index.js @@ -83,7 +83,7 @@ export const getAppointmentList = (/* userId, storeId, */ options = {}) => // 预约详情 export const getAppointmentDetail = (id) => get('/appointment/detail', { id }) -// 创建预约(userId/storeId 由后端从上下文派生;前端仍传 storeId 供 customer 选店场景,后端会按 role 决定是否采纳) +// 创建预约:登录人身份始终由后端派生;customer 传选中门店,门店代客预约传 customerUserId 或 customerPhone export const createAppointment = (data) => post('/appointment/create', data) /** 门店某日可预约半小时档(可约 / 已满 / 已过);公开接口 */ diff --git a/src/pages/appointment/AppointmentDetail.vue b/src/pages/appointment/AppointmentDetail.vue index 8343438..df5916f 100644 --- a/src/pages/appointment/AppointmentDetail.vue +++ b/src/pages/appointment/AppointmentDetail.vue @@ -42,9 +42,9 @@ 备注 {{ detail.remark }} - + 服务技师 - #{{ detail.assignedUserId }} + #{{ detail.assignedStaffId || detail.assignedUserId }} 预约编号 {{ detail.id }} diff --git a/src/pages/appointment/CustAppointmentCreate.vue b/src/pages/appointment/CustAppointmentCreate.vue index 26ed0af..8dd9cb8 100644 --- a/src/pages/appointment/CustAppointmentCreate.vue +++ b/src/pages/appointment/CustAppointmentCreate.vue @@ -593,7 +593,7 @@ const confirmNewAppt = async () => { uni.showToast({ title: '宠物档案保存失败,请重试', icon: 'none' }) return } - const payload = { ...a, storeId, userId: userInfo.id } + const payload = { ...a, storeId } payload.petId = ensuredPet.id const res = await createAppointment(payload) creatingAppt.value = false diff --git a/src/pages/home/Home.vue b/src/pages/home/Home.vue index 6c596cf..72043fb 100644 --- a/src/pages/home/Home.vue +++ b/src/pages/home/Home.vue @@ -199,6 +199,20 @@ + + 宠主手机号 + + + + 宠主称呼(可选) + + 宠物名字 @@ -387,7 +401,16 @@ const petTypes = [ { label: '其他', value: '其他' } ] -const newAppt = ref({ petName: '', petType: '', serviceType: '', appointmentTime: '', remark: '' }) +const emptyStaffAppointment = () => ({ + customerPhone: '', + customerName: '', + petName: '', + petType: '', + serviceType: '', + appointmentTime: '', + remark: '' +}) +const newAppt = ref(emptyStaffAppointment()) const appointmentTime = computed(() => { const raw = newAppt.value.appointmentTime || '' if (!raw.includes('T')) return '' @@ -671,6 +694,10 @@ const goReport = (item) => { const confirmNewAppt = async () => { const a = newAppt.value + if (!/^1[3-9]\d{9}$/.test(a.customerPhone || '')) { + uni.showToast({ title: '请输入正确的宠主手机号', icon: 'none' }) + return + } if (!a.petName) { uni.showToast({ title: '请输入宠物名字', icon: 'none' }); return } if (!a.petType) { uni.showToast({ title: '请选择宠物类型', icon: 'none' }); return } if (!a.serviceType) { uni.showToast({ title: '请选择服务类型', icon: 'none' }); return } @@ -681,11 +708,11 @@ const confirmNewAppt = async () => { return } creatingAppt.value = true - const res = await createAppointment({ ...a, storeId: storeInfo.id, userId: userInfo.id }) + const res = await createAppointment({ ...a, storeId: storeInfo.id }) creatingAppt.value = false if (res.code === 200) { uni.showToast({ title: '预约成功', icon: 'success' }) - newAppt.value = { petName: '', petType: '', serviceType: '', appointmentTime: '', remark: '' } + newAppt.value = emptyStaffAppointment() showNewAppt.value = false fetchAppointments() } else { diff --git a/src/pages/report/Report.vue b/src/pages/report/Report.vue index 59b6a4c..da2449a 100644 --- a/src/pages/report/Report.vue +++ b/src/pages/report/Report.vue @@ -700,7 +700,6 @@ const submitReport = async () => { const payload = { appointmentId: currentAppointmentId.value || null, - userId: userInfo.id, petName: report.value.petName, serviceType: report.value.serviceType, appointmentTime: report.value.appointmentTime || null,