Files
qitongxue-api/api/user/v1/event.go
2026-10-09 16:49:36 +08:00

107 lines
4.9 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package v1
import "github.com/gogf/gf/v2/frame/g"
// ============================================================================
// 小程序端「年会」公开接口(免登录:/event/info、/event/seat/query)
// 依据:架构 §5.1 E1/E2、§5.3 骨架、§4.4 图④;PRD-02 §4.2.3 隐私边界。
//
// 结果最小化红线:返回体**只含本人**的桌号/桌名/座位号,以及「本人所在桌」的示意
// (各座位是否有人,但**不含任何他人姓名/手机号/全厅名单/统计**)。SeatCell 刻意只有
// seat_no / is_self / filled 三个字段。
// ============================================================================
// SeatCell 仅用于「本人所在桌」示意 —— 只含座位号与是否本人,不含任何他人信息
type SeatCell struct {
SeatNo int `json:"seat_no"`
IsSelf bool `json:"is_self"`
Filled bool `json:"filled"` // 是否有人(不返回是谁)
}
type StageOut struct {
X int `json:"x"`
Y int `json:"y"`
W int `json:"w"`
H int `json:"h"`
Shape string `json:"shape"`
Rotation int `json:"rotation"`
Color string `json:"color"`
}
type EventInfoReq struct {
g.Meta `path:"/event/info" method:"get" tags:"event" summary:"活动公开信息(查座页顶部)"`
EventId int64 `v:"required#活动不存在" json:"event_id"`
}
type EventInfoRes struct {
Title string `json:"title"`
Venue string `json:"venue"`
EventTime string `json:"event_time"`
Status string `json:"status"`
CanQuery bool `json:"can_query"` // status==published
Stage *StageOut `json:"stage"` // 用于定位,不含个人信息
}
// EventSeatQueryReq 查座入参:**姓名 / 手机号二选一即可发起查询**(C 端体验)。
//
// 匹配策略(后端 event_query.go 权威实现):
// - 只给 name → 按姓名匹配。若命中多张票(重名)→ 返回 4010 ambiguous,**不返回任何座位信息**,
// 前端引导用户补手机号做二次查询;
// - 只给 phone → 手机号在本企业内唯一,直接精确匹配;
// - 两个都给 → 双因子精确匹配(最安全)。
//
// 🔴 无论哪种组合,**重名时一律不返回座位信息**(4010),避免「输个名字就看到别人的桌号」。
type EventSeatQueryReq struct {
g.Meta `path:"/event/seat/query" method:"post" tags:"event" summary:"扫码查座(免登录)"`
EventId int64 `v:"required#活动不存在" json:"event_id"`
Name string `json:"name"`
Phone string `json:"phone"`
}
// EventSeatQueryRes 结果最小化:只有本人桌座 + 本人所在桌示意。
//
// Found=false 表示未查询到(不匹配/未录入/未分配座位),message 为统一模糊文案,
// 前端据 Found 判定;找不到时所有桌座字段为空,不透出任何他人信息。
type EventSeatQueryRes struct {
Found bool `json:"found"`
// 🔴 true = 命中重名,需补手机号二次确认。此时 Found=false 且所有座位字段为空(后端不下发)。
Ambiguous bool `json:"ambiguous"`
Message string `json:"message"`
TableNo string `json:"table_no"`
TableName string `json:"table_name"`
SeatNo int `json:"seat_no"`
Capacity int `json:"capacity"`
Seats []SeatCell `json:"seats"` // 本人所在桌,按座位号;Filled 不含身份
Stage *StageOut `json:"stage"`
// 本人桌圆心 x(大厅逻辑坐标系)。**仅 Found=true 时有意义,未命中为 0**。
TableX int `json:"table_x"`
// 本人桌圆心 y(大厅逻辑坐标系)。**仅 Found=true 时有意义,未命中为 0**。
TableY int `json:"table_y"`
// 大厅逻辑宽(取自 hall_layout.canvas.w,缺省 1600)。**仅 Found=true 时有意义,未命中为 0**。
HallW int `json:"hall_w"`
// 大厅逻辑高(取自 hall_layout.canvas.h,缺省 1200)。**仅 Found=true 时有意义,未命中为 0**。
HallH int `json:"hall_h"`
}
// ============================================================================
// 公开「可查询活动列表」(N4-A / E-list,免登录)
//
// 只返回已发布(can_query=true)的活动,仅暴露最小字段(event_id / title / venue / event_time);
// 无已发布活动 → {list:[]}(**非报错**,前端据此渲染空态);草稿 / 已结束**不出现**。
// ============================================================================
// EventPublicItem 公开活动条目(最小字段,不含任何组织/名单信息)
type EventPublicItem struct {
EventId int64 `json:"event_id"`
Title string `json:"title"`
Venue string `json:"venue"`
EventTime string `json:"event_time"`
}
// EventPublicListReq 公开可查询活动列表
type EventPublicListReq struct {
g.Meta `path:"/event/list" method:"get" tags:"event" summary:"公开可查询活动列表"`
}
type EventPublicListRes struct {
List []EventPublicItem `json:"list"`
}