657 lines
28 KiB
Markdown
657 lines
28 KiB
Markdown
# Actions(动作)
|
||
|
||
> 读写实体的命令/用例。每个动作标注入口(controller/service 方法)、输入输出实体、适用规则。
|
||
|
||
## Store 相关
|
||
|
||
### action:register_boss
|
||
|
||
老板入驻:创建 `Store` + `boss` `User`,签发 `session_token`。
|
||
|
||
- **入口**:`POST /api/user/register-boss` → `UserService#registerBoss`(公开,在 AuthInterceptor allowlist)
|
||
- **输入**:`storeName`、`bossName`、`phone`、`password`
|
||
- **输出**:`entity:store`、`entity:user`、`session_token`
|
||
- **适用规则**:`rule:BR-AUTH-001`(session token 签发)
|
||
- **代码**:`backend/src/main/java/com/petstore/service/UserService.java#registerBoss`
|
||
- **证据**:`anchored`
|
||
|
||
### action:update_store
|
||
|
||
更新店铺信息:仅 boss 且只能改自己所属门店。
|
||
|
||
- **入口**:`PUT /api/store/update` → `StoreController#update` → `StoreService#update`
|
||
- **输入**:`entity:store`(id 必须等于 `current.storeId`)
|
||
- **输出**:`entity:store`
|
||
- **适用规则**:`rule:BR-STORE-001`(仅 boss + 同店)
|
||
- **代码**:`backend/src/main/java/com/petstore/controller/StoreController.java#update`
|
||
- **测试**:`StoreControllerTest`
|
||
- **证据**:`anchored`
|
||
|
||
### action:delete_store
|
||
|
||
删除店铺:仅 boss 且只能删自己所属门店(软删)。
|
||
|
||
- **入口**:`DELETE /api/store/delete` → `StoreController#delete`
|
||
- **适用规则**:`rule:BR-STORE-001`
|
||
- **代码**:`backend/src/main/java/com/petstore/controller/StoreController.java#delete`
|
||
- **测试**:`StoreControllerTest`
|
||
- **证据**:`anchored`
|
||
|
||
### action:get_store_by_invite_code
|
||
|
||
按邀请码查门店:仅 boss/staff 且邀请码对应门店必须为当前用户所属门店。
|
||
|
||
- **入口**:`GET /api/store/invite-code` → `StoreController#getByInviteCode`
|
||
- **适用规则**:`rule:BR-STORE-002`(邀请码同店校验)
|
||
- **代码**:`backend/src/main/java/com/petstore/controller/StoreController.java#getByInviteCode`
|
||
- **测试**:`StoreControllerTest`
|
||
- **证据**:`anchored`
|
||
|
||
## User / 鉴权相关
|
||
|
||
### action:login
|
||
|
||
手机号 + 短信验证码登录。**生产禁用**,仅 dev 模式(万能验证码 123456)可用。
|
||
|
||
- **入口**:`POST /api/user/login` → `UserService#login`(公开)
|
||
- **输入**:`phone`、`code`
|
||
- **输出**:`entity:user`、`entity:store`、`session_token`
|
||
- **适用规则**:`rule:BR-AUTH-001`、`rule:BR-AUTH-002`(生产 SMS 禁用)
|
||
- **代码**:`backend/src/main/java/com/petstore/service/UserService.java#login`
|
||
- **测试**:`UserServiceLoginStrategyTest`
|
||
- **证据**:`anchored`
|
||
|
||
### action:wx_phone_login
|
||
|
||
微信小程序手机号授权登录:`getPhoneNumber` 的 phoneCode + `uni.login` 的 loginCode 换手机号并沉淀 openid。
|
||
|
||
- **入口**:`POST /api/user/wx-phone-login` → `UserController#wxPhoneLogin` → `UserService#loginByVerifiedPhone`(公开)
|
||
- **输出**:`entity:user`、`entity:store`、`session_token`、可能绑定 `wechat_openid`/`wechat_unionid`
|
||
- **适用规则**:`rule:BR-AUTH-001`
|
||
- **代码**:`backend/src/main/java/com/petstore/controller/UserController.java#wxPhoneLogin`
|
||
- **证据**:`anchored`(生产登录主路径)
|
||
|
||
### action:bind_wechat
|
||
|
||
绑定小程序 openid/unionid;若标识曾绑定其他账号则先解绑。
|
||
|
||
- **入口**:`UserController#wxPhoneLogin` 内调用 `UserService#bindWechatMiniIdentity`
|
||
- **适用规则**:—
|
||
- **代码**:`backend/src/main/java/com/petstore/service/UserService.java#bindWechatMiniIdentity`
|
||
- **证据**:`anchored`
|
||
|
||
## Appointment 相关
|
||
|
||
### action:create_appointment
|
||
|
||
创建预约:半小时占号,取消不占号;客户与创建人分开记录。
|
||
|
||
- **入口**:`POST /api/appointment/create` → `AppointmentController#create` → `AppointmentService#createBooking`
|
||
- **输入**:`petName`、`petType`、`serviceType`、`appointmentTime`、`storeId`、`remark?`、`petId?`;门店代客预约另需 `customerUserId` 或 `customerPhone`
|
||
- **输出**:`entity:appointment`
|
||
- **身份口径**:customer 自约时客户=创建人=current.userId;boss/staff 代约时创建人=current.userId,客户按请求解析,legacy userId 镜像客户
|
||
- **适用规则**:`rule:BR-APPT-001`(状态机)、`rule:BR-APPT-003`(客户归属)、`rule:BR-APPT-004`(半小时档 + 营业时间 + 占用校验)
|
||
- **代码**:`backend/src/main/java/com/petstore/controller/AppointmentController.java#create`
|
||
- **证据**:`anchored`
|
||
|
||
### action:start_service
|
||
|
||
开始服务:仅 `new → doing`,指定技师(谁点谁服务);仅 boss/staff 且同店。
|
||
|
||
- **入口**:`POST /api/appointment/start` → `AppointmentController#start` → `AppointmentService#startService`
|
||
- **适用规则**:`rule:BR-APPT-001`、`rule:BR-APPT-002`(仅 boss/staff + 同店)
|
||
- **代码**:`backend/src/main/java/com/petstore/controller/AppointmentController.java#start`
|
||
- **测试**:`AppointmentServiceTest`
|
||
- **证据**:`anchored`
|
||
|
||
### action:transition_appointment_status
|
||
|
||
更新预约状态:合法迁移见 `AppointmentService#transitionStatus`;customer 仅可取消自己的。
|
||
|
||
- **入口**:`PUT /api/appointment/status` → `AppointmentController#updateStatus`
|
||
- **适用规则**:`rule:BR-APPT-001`、`rule:BR-APPT-003`(customer 仅取消自己的)
|
||
- **代码**:`backend/src/main/java/com/petstore/controller/AppointmentController.java#updateStatus`
|
||
- **测试**:`AppointmentServiceTest`
|
||
- **证据**:`anchored`
|
||
|
||
### action:get_appointment_detail
|
||
|
||
预约详情:customer 仅本人,boss/staff 仅同店。
|
||
|
||
- **入口**:`GET /api/appointment/detail` → `AppointmentController#detail`
|
||
- **适用规则**:`rule:BR-APPT-002`、`rule:BR-APPT-003`
|
||
- **代码**:`backend/src/main/java/com/petstore/controller/AppointmentController.java#detail`
|
||
- **测试**:`AppointmentControllerDetailTest`
|
||
- **证据**:`anchored`
|
||
|
||
### action:list_appointments
|
||
|
||
预约列表:身份从上下文派生,customer 看自己,boss/staff 看本店。
|
||
|
||
- **入口**:`GET /api/appointment/list` → `AppointmentController#list`
|
||
- **适用规则**:`rule:BR-APPT-002`、`rule:BR-APPT-003`
|
||
- **代码**:`backend/src/main/java/com/petstore/controller/AppointmentController.java#list`
|
||
- **证据**:`anchored`
|
||
|
||
## Report 相关
|
||
|
||
### action:submit_report
|
||
|
||
提交报告:仅 boss/staff;`authorStaffId` 从上下文派生,`customerUserId` 从预约派生;报告所属门店必须等于当前用户门店。
|
||
|
||
- **入口**:`POST /api/report/create` → `ReportController#create` → `ReportService#create`
|
||
- **输入**:`appointmentId`、`remark?`、`images`;身份字段不从请求体采信
|
||
- **输出**:`reportToken`、`reportId`
|
||
- **适用规则**:`rule:BR-RPT-001`(必须绑定预约)、`rule:BR-RPT-002`(一约一份)、`rule:BR-RPT-003`(前后照片必填)、`rule:BR-RPT-004`(仅 doing 预约)、`rule:BR-RPT-005`(跨店 403)
|
||
- **代码**:`backend/src/main/java/com/petstore/controller/ReportController.java#create`
|
||
- **测试**:`ReportControllerTest`、`ReportServiceTest`
|
||
- **证据**:`anchored`
|
||
|
||
### action:get_report_by_token
|
||
|
||
公开报告查询:凭 token 匿名访问,字段裁剪不返回 top-level `userId/storeId/reportToken`。
|
||
|
||
- **入口**:`GET /api/report/get?token=` → `ReportController#getByAppointmentId`(公开)
|
||
- **适用规则**:`rule:BR-RPT-006`(公开字段裁剪)
|
||
- **代码**:`backend/src/main/java/com/petstore/controller/ReportController.java#getByAppointmentId`
|
||
- **测试**:`ReportControllerTest#publicTokenQueryHidesInternalFields`
|
||
- **证据**:`anchored`
|
||
|
||
### action:track_report_open
|
||
|
||
报告打开埋点:日志只记 token SHA-256 前 8 位 hash。
|
||
|
||
- **入口**:`POST /api/report/open-track` → `ReportController#trackReportOpen`(公开)
|
||
- **适用规则**:`rule:BR-RPT-007`(token hash 日志)
|
||
- **代码**:`backend/src/main/java/com/petstore/controller/ReportController.java#trackReportOpen`
|
||
- **证据**:`anchored`
|
||
|
||
### action:delete_report
|
||
|
||
删除报告:仅 boss/staff 且同店。
|
||
|
||
- **入口**:`DELETE /api/report/delete` → `ReportController#delete`
|
||
- **适用规则**:`rule:BR-RPT-005`
|
||
- **代码**:`backend/src/main/java/com/petstore/controller/ReportController.java#delete`
|
||
- **证据**:`anchored`(同店校验用 `reportService.list(storeId,null)` 遍历,性能非最优,列为已知 gap)
|
||
|
||
## ReportLead 相关
|
||
|
||
### action:submit_lead
|
||
|
||
宠主留资:凭 `reportToken` 匿名提交手机号,同报告同手机号去重。
|
||
|
||
- **入口**:`POST /api/report/{token}/reminder` → `ReportLeadController#submitReminder` → `ReportLeadService#submit`(公开)
|
||
- **输入**:`phone`、`consent`、`loginCode?`
|
||
- **输出**:`leadId`、`remindDate`、`unsubscribeToken`、`wechatBound`
|
||
- **适用规则**:`rule:BR-LEAD-001`(去重)
|
||
- **代码**:`backend/src/main/java/com/petstore/controller/ReportLeadController.java#submitReminder`
|
||
- **证据**:`documented`(去重逻辑未补测试用例)
|
||
|
||
### action:unsubscribe
|
||
|
||
一键退订:凭 `unsubscribeToken`。
|
||
|
||
- **入口**:`POST /api/report/unsubscribe` → `ReportLeadController#unsubscribe`(公开)
|
||
- **适用规则**:`rule:BR-UNSUB-001`
|
||
- **代码**:`backend/src/main/java/com/petstore/controller/ReportLeadController.java#unsubscribe`
|
||
- **测试**:`ReportLeadControllerTest`
|
||
- **证据**:`anchored`
|
||
|
||
### action:list_leads
|
||
|
||
回访池列表:仅 boss/staff,`storeId` 从上下文派生;返回脱敏 openid/unionid。
|
||
|
||
- **入口**:`GET /api/report/leads` → `ReportLeadController#leads`
|
||
- **适用规则**:`rule:BR-LEAD-002`(标识脱敏)、`rule:BR-LEAD-003`(跨店 403)
|
||
- **代码**:`backend/src/main/java/com/petstore/controller/ReportLeadController.java#leads`
|
||
- **证据**:`anchored`
|
||
|
||
---
|
||
|
||
## Batch 2 录入动作
|
||
|
||
## Pet 相关
|
||
|
||
### action:list_pets
|
||
|
||
宠物列表:customer 查自己宠物(`ownerUserId=current.userId`);boss/staff 查本店服务过的宠物(`storeId=current.storeId`)。
|
||
|
||
- **入口**:`GET /api/pet/list` → `PetController#list`
|
||
- **适用规则**:`rule:BR-PET-001`(跨用户/跨店)
|
||
- **代码**:`backend/src/main/java/com/petstore/controller/PetController.java#list`
|
||
- **证据**:`anchored`
|
||
|
||
### action:create_pet
|
||
|
||
创建宠物档案:customer 强制 `ownerUserId=current.userId`;boss/staff 用 body.ownerUserId(代客建档)。
|
||
|
||
- **入口**:`POST /api/pet/create` → `PetController#create` → `PetService#create`
|
||
- **适用规则**:`rule:BR-PET-001`
|
||
- **代码**:`backend/src/main/java/com/petstore/controller/PetController.java#create`
|
||
- **证据**:`anchored`
|
||
|
||
### action:update_pet
|
||
|
||
更新宠物:`operatorUserId`/`role` 从上下文派生。
|
||
|
||
- **入口**:`PUT /api/pet/update` → `PetController#update` → `PetService#update`
|
||
- **适用规则**:`rule:BR-PET-001`
|
||
- **代码**:`backend/src/main/java/com/petstore/controller/PetController.java#update`
|
||
- **证据**:`anchored`
|
||
|
||
### action:delete_pet
|
||
|
||
删除宠物:`operatorUserId`/`role` 从上下文派生。
|
||
|
||
- **入口**:`DELETE /api/pet/delete` → `PetController#delete` → `PetService#delete`
|
||
- **适用规则**:`rule:BR-PET-001`
|
||
- **代码**:`backend/src/main/java/com/petstore/controller/PetController.java#delete`
|
||
- **证据**:`anchored`
|
||
|
||
### action:get_pet_history
|
||
|
||
宠物服务时间线:宠主本人或本店员工/老板可查。
|
||
|
||
- **入口**:`GET /api/pet/history` → `PetController#history` → `PetService#getServiceHistory`
|
||
- **适用规则**:`rule:BR-PET-001`
|
||
- **代码**:`backend/src/main/java/com/petstore/controller/PetController.java#history`
|
||
- **证据**:`anchored`
|
||
|
||
## ServiceType 相关
|
||
|
||
### action:list_service_types
|
||
|
||
服务类型列表:公开接口,不传 storeId 返回系统默认;传 storeId 返回系统默认 + 该店自定义。
|
||
|
||
- **入口**:`GET /api/service-type/list` → `ServiceTypeController#list`(公开,在 AuthInterceptor allowlist)
|
||
- **代码**:`backend/src/main/java/com/petstore/controller/ServiceTypeController.java#list`
|
||
- **证据**:`anchored`
|
||
|
||
### action:create_service_type
|
||
|
||
新增服务类型:仅 boss;`storeId=current.storeId`。
|
||
|
||
- **入口**:`POST /api/service-type/create` → `ServiceTypeController#create` → `ServiceTypeService#create`
|
||
- **适用规则**:`rule:BR-ST-001`(仅 boss + 同店)
|
||
- **代码**:`backend/src/main/java/com/petstore/controller/ServiceTypeController.java#create`
|
||
- **测试**:`ServiceTypeControllerTest`
|
||
- **证据**:`anchored`
|
||
|
||
### action:update_service_type
|
||
|
||
编辑服务类型:仅 boss;必须为本店自定义(系统默认 `storeId` 为空不可改、他店不可改)。
|
||
|
||
- **入口**:`PUT /api/service-type/update` → `ServiceTypeController#update`
|
||
- **适用规则**:`rule:BR-ST-001`
|
||
- **代码**:`backend/src/main/java/com/petstore/controller/ServiceTypeController.java#update`
|
||
- **测试**:`ServiceTypeControllerTest`
|
||
- **证据**:`anchored`
|
||
|
||
### action:delete_service_type
|
||
|
||
删除服务类型:仅 boss;必须为本店自定义(系统默认不可删、他店不可删)。
|
||
|
||
- **入口**:`DELETE /api/service-type/delete` → `ServiceTypeController#delete`
|
||
- **适用规则**:`rule:BR-ST-001`
|
||
- **代码**:`backend/src/main/java/com/petstore/controller/ServiceTypeController.java#delete`
|
||
- **测试**:`ServiceTypeControllerTest`
|
||
- **证据**:`anchored`
|
||
|
||
### action:init_service_types
|
||
|
||
初始化系统默认服务类型:仅 boss/staff(启动期已自动初始化)。
|
||
|
||
- **入口**:`POST /api/service-type/init` → `ServiceTypeController#init`
|
||
- **代码**:`backend/src/main/java/com/petstore/controller/ServiceTypeController.java#init`
|
||
- **测试**:`ServiceTypeControllerTest`
|
||
- **证据**:`anchored`
|
||
|
||
## Schedule 相关
|
||
|
||
### action:day_agenda
|
||
|
||
门店某日日程:仅 boss/staff;`storeId=current.storeId`。
|
||
|
||
- **入口**:`GET /api/schedule/day` → `ScheduleController#day` → `ScheduleService#dayAgenda`
|
||
- **适用规则**:`rule:BR-SCH-001`(仅 boss/staff + 跨店 403)
|
||
- **代码**:`backend/src/main/java/com/petstore/controller/ScheduleController.java#day`
|
||
- **测试**:`ScheduleControllerTest`
|
||
- **证据**:`anchored`
|
||
|
||
### action:create_schedule_block
|
||
|
||
手动占用半小时档:仅 boss/staff;`storeId=current.storeId`、`createdByUserId=current.userId`。
|
||
|
||
- **入口**:`POST /api/schedule/block` → `ScheduleController#createBlock` → `ScheduleService#createBlock`
|
||
- **适用规则**:`rule:BR-SCH-001`
|
||
- **代码**:`backend/src/main/java/com/petstore/controller/ScheduleController.java#createBlock`
|
||
- **测试**:`ScheduleControllerTest`
|
||
- **证据**:`anchored`
|
||
|
||
### action:delete_schedule_block
|
||
|
||
取消手动占用:仅 boss/staff;service 层做同店校验(`operatorStoreId`)。
|
||
|
||
- **入口**:`DELETE /api/schedule/block` → `ScheduleController#deleteBlock` → `ScheduleService#deleteBlock`
|
||
- **适用规则**:`rule:BR-SCH-001`
|
||
- **代码**:`backend/src/main/java/com/petstore/controller/ScheduleController.java#deleteBlock`、`service/ScheduleService.java#deleteBlock`
|
||
- **测试**:`ScheduleControllerTest`
|
||
- **证据**:`anchored`
|
||
|
||
## Upload / Highlight 相关
|
||
|
||
### action:upload_image
|
||
|
||
上传图片/视频:扩展名/MIME 校验 + 路径归一化防逃逸;需登录。
|
||
|
||
- **入口**:`POST /api/upload/image` → `FileController#uploadImage`
|
||
- **适用规则**:`rule:BR-UPLOAD-001`(路径归一化)、`rule:BR-UPLOAD-002`(扩展名/MIME 校验)
|
||
- **代码**:`backend/src/main/java/com/petstore/controller/FileController.java#uploadImage`
|
||
- **证据**:`anchored`
|
||
|
||
### action:get_upload_image
|
||
|
||
读取上传资源:公开(在 AuthInterceptor allowlist `GET /api/upload/image/**`);路径归一化防逃逸。
|
||
|
||
- **入口**:`GET /api/upload/image/**` → `FileController#getImage`
|
||
- **适用规则**:`rule:BR-UPLOAD-001`
|
||
- **代码**:`backend/src/main/java/com/petstore/controller/FileController.java#getImage`
|
||
- **证据**:`anchored`
|
||
|
||
### action:generate_highlight
|
||
|
||
触发服务回顾短片生成:仅 boss/staff;`operatorUserId`/`role` 从上下文派生;异步 FFmpeg 拼接。
|
||
|
||
- **入口**:`POST /api/report/highlight/start` → `ReportController#startHighlight` → `ReportHighlightVideoService#requestGenerate`
|
||
- **适用规则**:`rule:BR-HL-001`(仅 boss/staff)、`rule:BR-HL-002`(三态 + composeMode)
|
||
- **代码**:`backend/src/main/java/com/petstore/controller/ReportController.java#startHighlight`、`service/ReportHighlightVideoService.java#requestGenerate`
|
||
- **文档**:`docs/洗美报告短视频成片方案.md`
|
||
- **证据**:`anchored`(接口与上下文派生已实现;FFmpeg 集成测试 `gap`)
|
||
|
||
## User 管理相关
|
||
|
||
### action:create_staff
|
||
|
||
老板创建员工:仅 boss;`storeId=current.storeId`。
|
||
|
||
- **入口**:`POST /api/user/create-staff` → `UserController#createStaff` → `UserService#createStaff`
|
||
- **适用规则**:`rule:BR-USER-001`(仅 boss)
|
||
- **代码**:`backend/src/main/java/com/petstore/controller/UserController.java#createStaff`
|
||
- **证据**:`anchored`
|
||
|
||
### action:list_staff
|
||
|
||
员工列表:仅 boss/staff;`storeId=current.storeId`。
|
||
|
||
- **入口**:`GET /api/user/staff-list` → `UserController#staffList`
|
||
- **适用规则**:`rule:BR-USER-001`
|
||
- **代码**:`backend/src/main/java/com/petstore/controller/UserController.java#staffList`
|
||
- **证据**:`anchored`
|
||
|
||
### action:delete_staff
|
||
|
||
删除员工:仅 boss;目标员工必须属于本店。
|
||
|
||
- **入口**:`DELETE /api/user/staff` → `UserController#deleteStaff`
|
||
- **适用规则**:`rule:BR-USER-001`
|
||
- **代码**:`backend/src/main/java/com/petstore/controller/UserController.java#deleteStaff`
|
||
- **证据**:`anchored`
|
||
|
||
### action:update_user
|
||
|
||
更新当前登录用户信息(头像/姓名/手机号):`id=current.userId`(覆盖请求体);手机号变更需 SMS 验证码(生产禁用)。
|
||
|
||
- **入口**:`PUT /api/user/update` → `UserController#updateUser` → `UserService#updateUser`
|
||
- **适用规则**:`rule:BR-USER-002`(仅本人)、`rule:BR-AUTH-002`(生产手机号变更禁用)
|
||
- **代码**:`backend/src/main/java/com/petstore/controller/UserController.java#updateUser`
|
||
- **证据**:`anchored`
|
||
|
||
---
|
||
|
||
## Batch 2.1 补录动作(audit_drift 发现的遗漏)
|
||
|
||
## 公开查询类(在 AuthInterceptor allowlist)
|
||
|
||
### action:list_stores
|
||
|
||
门店列表:公开接口,经 `toPublicStoreView` 裁剪(不含 ownerId/inviteCode)。
|
||
|
||
- **入口**:`GET /api/store/list` → `StoreController#list`(公开)
|
||
- **适用规则**:`rule:BR-STORE-003`
|
||
- **代码**:`backend/src/main/java/com/petstore/controller/StoreController.java#list`
|
||
- **测试**:`StoreControllerTest#publicListHidesOwnerIdAndInviteCode`
|
||
- **证据**:`anchored`
|
||
|
||
### action:get_store
|
||
|
||
门店详情:公开接口,经 `toPublicStoreView` 裁剪(含 intro/营业时段,不含 ownerId/inviteCode/deleted)。
|
||
|
||
- **入口**:`GET /api/store/get` → `StoreController#get`(公开)
|
||
- **适用规则**:`rule:BR-STORE-003`
|
||
- **代码**:`backend/src/main/java/com/petstore/controller/StoreController.java#get`
|
||
- **测试**:`StoreControllerTest#publicGetHidesOwnerIdAndInviteCode`
|
||
- **证据**:`anchored`
|
||
|
||
### action:get_available_slots
|
||
|
||
门店某日可预约时段:公开接口,半小时档,含已占用/已过/可约。
|
||
|
||
- **入口**:`GET /api/appointment/available-slots` → `AppointmentController#availableSlots`(公开)
|
||
- **适用规则**:`rule:BR-APPT-004`(时段校验)
|
||
- **代码**:`backend/src/main/java/com/petstore/controller/AppointmentController.java#availableSlots`
|
||
- **证据**:`anchored`
|
||
|
||
### action:get_report_suggestion
|
||
|
||
报告下次建议日期:公开接口,凭 token 查询(读取 `entity:service_interval` 推算)。
|
||
|
||
- **入口**:`GET /api/report/{token}/suggestion` → `ReportLeadController#suggestion`(公开)
|
||
- **适用规则**:`rule:BR-INT-001`
|
||
- **代码**:`backend/src/main/java/com/petstore/controller/ReportLeadController.java#suggestion`
|
||
- **证据**:`anchored`
|
||
|
||
### action:submit_testimonial
|
||
|
||
宠主寄语提交:公开接口,凭 token 提交;同一报告保留一条,重复提交更新。
|
||
|
||
- **入口**:`POST /api/report/{token}/testimonial` → `ReportController#submitTestimonial`(公开)
|
||
- **输出**:`entity:report_testimonial`
|
||
- **适用规则**:`rule:BR-TST-001`
|
||
- **触发事件**:`event:testimonial_saved`
|
||
- **代码**:`backend/src/main/java/com/petstore/controller/ReportController.java#submitTestimonial`
|
||
- **证据**:`anchored`
|
||
|
||
### action:get_legacy_upload
|
||
|
||
兼容旧路径读取上传资源:公开接口,路径归一化防逃逸。
|
||
|
||
- **入口**:`GET /api/upload/legacy/**` → `FileController#getLegacyImage`(公开)
|
||
- **适用规则**:`rule:BR-UPLOAD-001`
|
||
- **代码**:`backend/src/main/java/com/petstore/controller/FileController.java#getLegacyImage`
|
||
- **证据**:`anchored`
|
||
|
||
## 注册/短信类(公开)
|
||
|
||
### action:register_staff
|
||
|
||
员工注册(邀请码方式):公开接口,凭邀请码加入对应门店。
|
||
|
||
- **入口**:`POST /api/user/register-staff` → `UserController#registerStaff` → `UserService#registerStaff`(公开)
|
||
- **输出**:`entity:user`(staff)、`entity:store`、`session_token`
|
||
- **适用规则**:`rule:BR-AUTH-001`
|
||
- **代码**:`backend/src/main/java/com/petstore/controller/UserController.java#registerStaff`
|
||
- **证据**:`anchored`
|
||
|
||
### action:send_sms
|
||
|
||
发送短信验证码:公开接口;**生产禁用**(`universalSmsCode` 为空时返回 403 `SMS_LOGIN_DISABLED`)。
|
||
|
||
- **入口**:`POST /api/sms/send` → `SmsController#send`(公开)
|
||
- **适用规则**:`rule:BR-AUTH-002`
|
||
- **代码**:`backend/src/main/java/com/petstore/controller/SmsController.java#send`
|
||
- **证据**:`anchored`
|
||
|
||
### action:register_store
|
||
|
||
店铺注册(旧入口):公开接口,创建 Store。**deprecated**:与 `action:register_boss` 重复,勿作为新集成入口。
|
||
|
||
- **入口**:`POST /api/store/register` → `StoreController#register` → `StoreService#create`
|
||
- **输出**:`entity:store`
|
||
- **状态**:`deprecated`
|
||
- **代码**:`backend/src/main/java/com/petstore/controller/StoreController.java#register`
|
||
- **证据**:`gap`(与 `register_boss` 重复,建议废弃或合并)
|
||
|
||
## 删除/列表类(protected)
|
||
|
||
### action:delete_appointment
|
||
|
||
删除预约:仅 boss/staff 且同店。
|
||
|
||
- **入口**:`DELETE /api/appointment/delete` → `AppointmentController#delete`
|
||
- **适用规则**:`rule:BR-APPT-002`
|
||
- **代码**:`backend/src/main/java/com/petstore/controller/AppointmentController.java#delete`
|
||
- **证据**:`anchored`
|
||
|
||
### action:list_reports
|
||
|
||
报告列表:boss/staff 查本店,customer 查自己相关报告;身份从上下文派生。
|
||
|
||
- **入口**:`GET /api/report/list` → `ReportController#list`
|
||
- **适用规则**:`rule:BR-RPT-005`(跨店 403)
|
||
- **代码**:`backend/src/main/java/com/petstore/controller/ReportController.java#list`
|
||
- **证据**:`anchored`
|
||
|
||
## 微信 OAuth(TODO demo,deprecated)
|
||
|
||
### action:wechat_authorize
|
||
|
||
获取微信授权跳转 URL:公开接口(TODO demo,真实微信登录走 `action:wx_phone_login`)。**deprecated**。
|
||
|
||
- **入口**:`GET /api/wechat/authorize` → `WechatController#getAuthorizeUrl`(公开)
|
||
- **状态**:`deprecated`
|
||
- **代码**:`backend/src/main/java/com/petstore/controller/WechatController.java#getAuthorizeUrl`
|
||
- **证据**:`gap`(TODO demo,未真实实现)
|
||
|
||
### action:wechat_callback
|
||
|
||
微信授权回调:公开接口(TODO demo,返回 `demo_openid_` + code,未真实换取 access_token)。**deprecated**。
|
||
|
||
- **入口**:`GET /api/wechat/callback` → `WechatController#callback`(公开)
|
||
- **状态**:`deprecated`
|
||
- **代码**:`backend/src/main/java/com/petstore/controller/WechatController.java#callback`
|
||
- **证据**:`gap`(TODO demo,未真实实现;真实微信登录走 `action:wx_phone_login`)
|
||
|
||
## 客户端埋点 / 会话生命周期
|
||
|
||
### action:track_video_play
|
||
|
||
成片点击播放埋点(前端客户端事件)。
|
||
|
||
- **入口**:frontend `reportView` / `videoPlayer`(client-emitted)
|
||
- **触发事件**:`event:video_play`
|
||
- **证据**:`documented`(schema 已冻结;上报与统计落地 `gap`)
|
||
|
||
### action:track_video_save
|
||
|
||
成片保存到相册埋点(前端客户端事件)。
|
||
|
||
- **入口**:frontend `reportView` / `videoPlayer`(client-emitted)
|
||
- **触发事件**:`event:video_save`
|
||
- **证据**:`documented`(schema 已冻结;上报与统计落地 `gap`)
|
||
|
||
### action:logout
|
||
|
||
退出登录 / 吊销会话:当前仅前端清本地 token,**无服务端吊销**。
|
||
|
||
- **入口**:—(未实现)
|
||
- **触发事件**:`event:session_revoked`
|
||
- **适用规则**:`rule:BR-AUTH-001`
|
||
- **证据**:`gap`
|
||
|
||
### action:get_user_info
|
||
|
||
获取当前登录用户信息:`userId=current.userId`。
|
||
|
||
- **入口**:`GET /api/user/info` → `UserController#info`
|
||
- **适用规则**:`rule:BR-USER-002`、`rule:BR-USER-003`
|
||
- **代码**:`backend/src/main/java/com/petstore/controller/UserController.java#info`
|
||
- **证据**:`anchored`
|
||
|
||
---
|
||
|
||
## 门店 Web 后台(Phase A · documented)
|
||
|
||
> 产品:`docs/门店管理后台升级方案-对标宠老板.md`。优先复用现有 `/api/**`,不另造状态机。
|
||
|
||
### action:view_workbench
|
||
|
||
查看今日工作台(登录落点;可弹今日待办)。
|
||
|
||
- **入口**:Admin UI `/workbench`(planned)
|
||
- **输出**:`entity:workbench`、`entity:workbench_todo_item`
|
||
- **适用规则**:`rule:BR-ADMIN-001`、`rule:BR-ADMIN-002`、`rule:BR-ADMIN-004`
|
||
- **触发事件**:`event:workbench_viewed`(可选,gap)
|
||
- **证据**:`documented`
|
||
|
||
### action:drilldown_workbench_todo
|
||
|
||
工作台待办卡片下钻到对应列表并带筛选。
|
||
|
||
- **入口**:Admin UI workbench todo click(planned)
|
||
- **适用规则**:`rule:BR-ADMIN-001`、`rule:BR-ADMIN-002`
|
||
- **证据**:`documented`
|
||
|
||
### action:admin_list_appointments
|
||
|
||
后台预约列表(增强筛选;规则复用 Appointment*)。
|
||
|
||
- **入口**:Admin UI `/appointments`(planned);数据复用 `GET /api/appointment/list`
|
||
- **适用规则**:`rule:BR-ADMIN-001`、`rule:BR-ADMIN-002`、`rule:BR-APPT-001`、`rule:BR-APPT-002`
|
||
- **证据**:`documented`
|
||
|
||
### action:admin_list_reports
|
||
|
||
后台报告列表(成片三态、复制公开链接、触发重生成)。
|
||
|
||
- **入口**:Admin UI `/reports`(planned);复用 `GET /api/report/list` + `action:generate_highlight`
|
||
- **适用规则**:`rule:BR-ADMIN-001`、`rule:BR-ADMIN-002`、`rule:BR-ADMIN-003`、`rule:BR-RPT-005`
|
||
- **证据**:`documented`
|
||
|
||
### action:admin_list_leads
|
||
|
||
后台回访线索列表。
|
||
|
||
- **入口**:Admin UI `/leads`(planned);复用 `GET /api/report/leads`
|
||
- **适用规则**:`rule:BR-ADMIN-001`、`rule:BR-ADMIN-002`、`rule:BR-LEAD-002`、`rule:BR-LEAD-003`
|
||
- **证据**:`documented`
|
||
|
||
### action:admin_list_service_customers
|
||
|
||
后台服务客户列表(瘦身主档;姓名/手机/宠物名搜索)。
|
||
|
||
- **入口**:`GET /api/admin/service-customers` → `AdminServiceCustomerController#listServiceCustomers` → Admin UI `/customers`
|
||
- **输出**:`entity:service_customer`
|
||
- **适用规则**:`rule:BR-ADMIN-001` … `BR-ADMIN-004`
|
||
- **证据**:`anchored`
|
||
- **代码**:`backend/src/main/java/com/petstore/controller/AdminServiceCustomerController.java`、`AdminServiceCustomerService`
|
||
- **产品决策**:新建聚合 API,不以前端拼装为正式方案;不做余额/次卡列、持卡会员导入
|
||
- **文档**:`docs/门店管理后台-PhaseA-页面清单PRD.md §7.6`
|
||
|
||
### action:admin_update_settings
|
||
|
||
后台门店设置(资料、营业时段、服务类型瘦身表单、员工)。
|
||
|
||
- **入口**:`GET /api/admin/store` → `AdminStoreController#currentStore`;Admin UI `/settings`;写资料 `PUT /api/store/update`
|
||
- **适用规则**:`rule:BR-ADMIN-001`、`rule:BR-ADMIN-002`、`rule:BR-ADMIN-003`、`rule:BR-STORE-001`、`rule:BR-ST-001`、`rule:BR-USER-001`
|
||
- **证据**:`anchored`
|
||
- **代码**:`AdminStoreController`、`StoreController#update`;服务类型/员工复用既有 API
|
||
|
||
### action:admin_manage_schedule
|
||
|
||
后台排班与手动占用(日视图)。
|
||
|
||
- **入口**:Admin UI `/schedule`;`GET /api/schedule/day`;`POST/DELETE /api/schedule/block`
|
||
- **适用规则**:`rule:BR-ADMIN-001`、`rule:BR-ADMIN-002`、`rule:BR-SCH-001`
|
||
- **证据**:`anchored`
|