/** * 服务预约(U51 服务预约 / U52 我的预约) * * 归属与契约边界(Phase 19): * - 用户端只能读写本人预约:详情/列表/取消全部由服务端按登录主体过滤, * 越权访问一律返回空或 404,前端不得以任何参数指定他人 userId。 * - 提交预约**只传服务内容**。来源(source)由服务端强制为 user_self, * 前端禁止传 requestSource / createdByOperatorId / userId(伪造运营代登记身份)。 * - 运营代登记走独立端点(后端 /service-appointments/operator/register),前端不在本层暴露。 */ const api = require('../utils/api'); /** * 读取当前服务站点(U51 预约上下文) * * 服务站页(U50)跳转时会带 `?serviceLocationId=xxx`,本方法用于把该 ID 还原成 * 可展示的站点名。仅**展示用途**:真正的归属由服务端按登录主体校验, * 展示失败(无站点 / 接口异常)不影响提交,返回 null。 * @returns {Promise<{id: string, name: string} | null>} */ async function getCurrentServiceLocation() { try { const home = await api.get('/home'); const location = home && home.serviceLocation; if (!location || !location.id) { return null; } return { id: location.id, name: location.name || '已选服务站点' }; } catch (err) { return null; } } /** * 我的预约列表 * @returns {Promise>} */ function getMyAppointments() { return api.get('/service-appointments'); } /** * 预约详情(越权由服务端返回 404) * @param {string} id */ function getAppointmentDetail(id) { return api.get(`/service-appointments/${id}`); } /** * 提交预约 * @param {{ serviceLocationId?: string, serviceType: string, preferredDate: string, * preferredTimeSlot?: string, userNote?: string }} payload */ function createAppointment(payload) { return api.post('/service-appointments', { serviceLocationId: payload.serviceLocationId, serviceType: payload.serviceType, preferredDate: payload.preferredDate, preferredTimeSlot: payload.preferredTimeSlot, userNote: payload.userNote, }); } /** * 取消我的预约 * @param {string} id * @param {string} [reason] */ function cancelAppointment(id, reason) { return api.post(`/service-appointments/${id}/cancel`, { reason: reason || '' }); } module.exports = { getCurrentServiceLocation, getMyAppointments, getAppointmentDetail, createAppointment, cancelAppointment, };