428 lines
16 KiB
Go
428 lines
16 KiB
Go
package v1
|
||
|
||
import "github.com/gogf/gf/v2/frame/g"
|
||
|
||
// ============================================================================
|
||
// 管理端「年会座次」域(企业 / 员工 / 活动 / 桌 / 座)
|
||
// 依据:架构-2026-09-18 §5.2 A1–A17、§5.3 骨架。
|
||
// 导入两段式(A6–A8)与小程序码(A18)、查座审计(A19)由 T09/T10 实现。
|
||
// ============================================================================
|
||
|
||
// ===== 企业 =====
|
||
|
||
type EnterpriseItem struct {
|
||
Id int64 `json:"id"`
|
||
Name string `json:"name"`
|
||
Contact string `json:"contact"`
|
||
Remark string `json:"remark"`
|
||
Status int `json:"status"`
|
||
EmpCount int64 `json:"emp_count"` // 员工数
|
||
}
|
||
|
||
type EnterpriseListReq struct {
|
||
g.Meta `path:"/event/enterprise/list" method:"get" tags:"event" summary:"企业列表"`
|
||
Keyword string `json:"keyword"`
|
||
Page int `json:"page"`
|
||
PageSize int `json:"pageSize"`
|
||
}
|
||
type EnterpriseListRes struct {
|
||
List []EnterpriseItem `json:"list"`
|
||
Total int `json:"total"`
|
||
}
|
||
|
||
type EnterpriseSaveReq struct {
|
||
g.Meta `path:"/event/enterprise/save" method:"post" tags:"event" summary:"保存企业"`
|
||
Id int64 `json:"id"`
|
||
Name string `v:"required|length:1,128#企业名称不能为空" json:"name"`
|
||
Contact string `json:"contact"`
|
||
Remark string `json:"remark"`
|
||
Status int `json:"status"`
|
||
}
|
||
type EnterpriseSaveRes struct {
|
||
Id int64 `json:"id"`
|
||
}
|
||
|
||
// ===== 员工 =====
|
||
|
||
type EmployeeItem struct {
|
||
Id int64 `json:"id"`
|
||
Name string `json:"name"`
|
||
Phone string `json:"phone"`
|
||
Dept string `json:"dept"`
|
||
Remark string `json:"remark"`
|
||
Status int `json:"status"`
|
||
InEvent bool `json:"in_event"` // 是否已在当前活动候场名单
|
||
ExcludeAssign int `json:"exclude_assign"` // 1=不参与排座(仅 in_event 时有意义)
|
||
}
|
||
|
||
type EmployeeListReq struct {
|
||
g.Meta `path:"/event/employee/list" method:"get" tags:"event" summary:"员工库列表"`
|
||
EnterpriseId int64 `json:"enterprise_id"`
|
||
EventId int64 `json:"event_id"`
|
||
Keyword string `json:"keyword"`
|
||
Page int `json:"page"`
|
||
PageSize int `json:"pageSize"`
|
||
}
|
||
type EmployeeListRes struct {
|
||
List []EmployeeItem `json:"list"`
|
||
Total int `json:"total"`
|
||
}
|
||
|
||
// EmployeeSaveReq 手工加人(临时人员)。EventId > 0 时同时纳入该活动候场名单。
|
||
type EmployeeSaveReq struct {
|
||
g.Meta `path:"/event/employee/save" method:"post" tags:"event" summary:"新增/修改员工"`
|
||
Id int64 `json:"id"`
|
||
EnterpriseId int64 `v:"required#请选择企业" json:"enterprise_id"`
|
||
EventId int64 `json:"event_id"`
|
||
Name string `v:"required|length:1,64#姓名不能为空" json:"name"`
|
||
Phone string `v:"required|length:6,20#手机号格式不正确" json:"phone"`
|
||
Dept string `json:"dept"`
|
||
Remark string `json:"remark"`
|
||
}
|
||
type EmployeeSaveRes struct {
|
||
Id int64 `json:"id"`
|
||
}
|
||
|
||
type EmployeeStatusReq struct {
|
||
g.Meta `path:"/event/employee/status" method:"post" tags:"event" summary:"员工启停"`
|
||
Id int64 `v:"required" json:"id"`
|
||
Status int `v:"in:0,1#状态取值非法" json:"status"`
|
||
}
|
||
type EmployeeStatusRes struct{}
|
||
|
||
// EmployeeBatchReq 批量操作员工(T15):action=status(启停)/ delete(软删除,可恢复)。
|
||
// 部分成功语义见 BatchFailure。
|
||
type EmployeeBatchReq struct {
|
||
g.Meta `path:"/event/employee/batch" method:"post" tags:"event" summary:"批量操作员工"`
|
||
Ids []int64 `v:"required|min-length:1#请选择要操作的员工" json:"ids"`
|
||
Action string `v:"required|in:status,delete#动作非法" json:"action"`
|
||
Status int `v:"in:0,1#状态取值非法" json:"status"`
|
||
}
|
||
type EmployeeBatchRes struct {
|
||
Success int `json:"success"`
|
||
Failed int `json:"failed"`
|
||
Failures []BatchFailure `json:"failures"`
|
||
}
|
||
|
||
// ParticipantExcludeReq 批量设置「不参与排座」(N4)。仅对已在候场名单(in_event)的员工生效。
|
||
type ParticipantExcludeReq struct {
|
||
g.Meta `path:"/event/participant/exclude" method:"post" tags:"event" summary:"批量设置员工不参与排座"`
|
||
EventId int64 `v:"required" json:"event_id"`
|
||
EmployeeIds []int64 `v:"required|min-length:1#请选择员工" json:"employee_ids"`
|
||
ExcludeAssign int `v:"in:0,1#取值非法" json:"exclude_assign"`
|
||
}
|
||
type ParticipantExcludeRes struct {
|
||
Success int `json:"success"` // 实际更新的候场记录数
|
||
}
|
||
|
||
// ===== 活动 =====
|
||
|
||
type EventItem struct {
|
||
Id int64 `json:"id"`
|
||
EnterpriseId int64 `json:"enterprise_id"`
|
||
EnterpriseName string `json:"enterprise_name"`
|
||
Title string `json:"title"`
|
||
Venue string `json:"venue"`
|
||
EventTime string `json:"event_time"`
|
||
Status string `json:"status"`
|
||
LayoutVersion int `json:"layout_version"`
|
||
CodeUrl string `json:"code_url"`
|
||
TableCount int64 `json:"table_count"`
|
||
}
|
||
|
||
type EventListReq struct {
|
||
g.Meta `path:"/event/admin/list" method:"get" tags:"event" summary:"活动列表"`
|
||
EnterpriseId int64 `json:"enterprise_id"`
|
||
Page int `json:"page"`
|
||
PageSize int `json:"pageSize"`
|
||
}
|
||
type EventListRes struct {
|
||
List []EventItem `json:"list"`
|
||
Total int `json:"total"`
|
||
}
|
||
|
||
type EventSaveReq struct {
|
||
g.Meta `path:"/event/admin/save" method:"post" tags:"event" summary:"保存活动"`
|
||
Id int64 `json:"id"`
|
||
EnterpriseId int64 `v:"required#请选择企业" json:"enterprise_id"`
|
||
Title string `v:"required|length:1,128#活动主题不能为空" json:"title"`
|
||
Venue string `json:"venue"`
|
||
EventTime string `json:"event_time"`
|
||
}
|
||
type EventSaveRes struct {
|
||
Id int64 `json:"id"`
|
||
}
|
||
|
||
type EventStatusReq struct {
|
||
g.Meta `path:"/event/admin/status" method:"post" tags:"event" summary:"发布/结束活动"`
|
||
EventId int64 `v:"required" json:"event_id"`
|
||
Status string `v:"required|in:draft,published,ended#状态取值非法" json:"status"`
|
||
}
|
||
type EventStatusRes struct{}
|
||
|
||
// ===== 设计器全量(活动详情)=====
|
||
|
||
type SeatOut struct {
|
||
Id int64 `json:"id"`
|
||
SeatNo int `json:"seat_no"`
|
||
IsManual bool `json:"is_manual"`
|
||
EmployeeId int64 `json:"employee_id"`
|
||
EmployeeName string `json:"employee_name"`
|
||
}
|
||
|
||
type TableOut struct {
|
||
Id int64 `json:"id"`
|
||
TableNo string `json:"table_no"`
|
||
Name string `json:"name"`
|
||
X int `json:"x"`
|
||
Y int `json:"y"`
|
||
Capacity int `json:"capacity"`
|
||
Rotation int `json:"rotation"`
|
||
TableType int `json:"table_type"` // 桌型:0普通 1主桌 2签到台 3媒体席 4备用桌 9其他
|
||
Remark string `json:"remark"` // 桌备注
|
||
ExcludeAuto int `json:"exclude_auto"` // 1=不参与自动排序
|
||
Seats []SeatOut `json:"seats"`
|
||
}
|
||
|
||
// UnassignedItem 未分配池成员(在候场名单但未绑定座位)
|
||
type UnassignedItem struct {
|
||
EmployeeId int64 `json:"employee_id"`
|
||
Name string `json:"name"`
|
||
Phone string `json:"phone"`
|
||
Dept string `json:"dept"`
|
||
}
|
||
|
||
type EventDetailReq struct {
|
||
g.Meta `path:"/event/admin/detail" method:"get" tags:"event" summary:"活动设计器全量"`
|
||
EventId int64 `v:"required" json:"event_id"`
|
||
}
|
||
type EventDetailRes struct {
|
||
Id int64 `json:"id"`
|
||
EnterpriseId int64 `json:"enterprise_id"`
|
||
Title string `json:"title"`
|
||
Venue string `json:"venue"`
|
||
EventTime string `json:"event_time"`
|
||
Status string `json:"status"`
|
||
LayoutVersion int `json:"layout_version"`
|
||
HallLayout string `json:"hall_layout"`
|
||
Tables []TableOut `json:"tables"`
|
||
ParticipantCount int `json:"participant_count"`
|
||
SeatCount int `json:"seat_count"`
|
||
Unassigned []UnassignedItem `json:"unassigned"`
|
||
}
|
||
|
||
// ===== 布局保存(CAS)=====
|
||
|
||
// TableIn 布局内的一张桌(capacity 变更会联动座位)
|
||
type TableIn struct {
|
||
Id int64 `json:"id"`
|
||
TableNo string `json:"table_no"`
|
||
Name string `json:"name"`
|
||
X int `json:"x"`
|
||
Y int `json:"y"`
|
||
Capacity int `json:"capacity"`
|
||
Rotation int `json:"rotation"`
|
||
TableType int `json:"table_type"`
|
||
Remark string `json:"remark"`
|
||
ExcludeAuto int `json:"exclude_auto"`
|
||
}
|
||
|
||
// EventLayoutSaveReq 带 layout_version 提交 → 服务端 CAS 更新,冲突返回 4009。
|
||
// 说明:LayoutVersion 允许为 0(首次保存版本即 0),故不用 required 校验,逻辑内校验 < 0。
|
||
type EventLayoutSaveReq struct {
|
||
g.Meta `path:"/event/admin/layout/save" method:"post" tags:"event" summary:"保存大厅布局"`
|
||
EventId int64 `v:"required" json:"event_id"`
|
||
LayoutVersion int `v:"min:0#缺少布局版本号" json:"layout_version"`
|
||
HallLayout string `json:"hall_layout"`
|
||
Tables []TableIn `json:"tables"`
|
||
}
|
||
type EventLayoutSaveRes struct {
|
||
LayoutVersion int `json:"layout_version"`
|
||
}
|
||
|
||
// ===== 桌 =====
|
||
|
||
// TableSaveReq 建/改桌(改人数联动补/删座)。
|
||
// 特殊桌(签到台/媒体席/备用桌)允许 0 座,故 capacity 下限为 0。
|
||
type TableSaveReq struct {
|
||
g.Meta `path:"/event/admin/table/save" method:"post" tags:"event" summary:"保存桌(含人数联动座位)"`
|
||
EventId int64 `v:"required" json:"event_id"`
|
||
Id int64 `json:"id"`
|
||
TableNo string `json:"table_no"`
|
||
Name string `json:"name"`
|
||
X int `json:"x"`
|
||
Y int `json:"y"`
|
||
Capacity int `v:"min:0|max:50#每桌人数需在 0~50 之间" json:"capacity"` // 特殊桌允许 0 座
|
||
Rotation int `json:"rotation"`
|
||
TableType int `v:"min:0|max:9#桌型取值非法" json:"table_type"`
|
||
Remark string `v:"length:0,50#备注最多 50 字" json:"remark"`
|
||
ExcludeAuto int `v:"in:0,1#取值非法" json:"exclude_auto"`
|
||
}
|
||
type TableSaveRes struct {
|
||
TableId int64 `json:"table_id"`
|
||
AddedSeats int `json:"added_seats"` // 补出的座位数
|
||
RemovedSeats int `json:"removed_seats"` // 移除的座位数
|
||
MovedToUnassigned int `json:"moved_to_unassigned"` // 因减座而移入未分配池的人数
|
||
}
|
||
|
||
type TableDeleteReq struct {
|
||
g.Meta `path:"/event/admin/table/delete" method:"post" tags:"event" summary:"删除桌"`
|
||
EventId int64 `v:"required" json:"event_id"`
|
||
TableId int64 `v:"required" json:"table_id"`
|
||
}
|
||
type TableDeleteRes struct {
|
||
MovedToUnassigned int `json:"moved_to_unassigned"` // 该桌原有员工数(删桌后全部进入未分配池)
|
||
}
|
||
|
||
// ===== 座位 =====
|
||
|
||
// SeatSaveReq 改号 / 绑定 / 解绑。
|
||
//
|
||
// SeatNo > 0 时改号(置 is_manual=1);
|
||
// EmployeeId 非 nil 时改绑定:指向 0 表示解绑,>0 表示绑定该员工。
|
||
type SeatSaveReq struct {
|
||
g.Meta `path:"/event/admin/seat/save" method:"post" tags:"event" summary:"改座位号/绑定/解绑"`
|
||
EventId int64 `v:"required" json:"event_id"`
|
||
SeatId int64 `v:"required" json:"seat_id"`
|
||
SeatNo int `json:"seat_no"`
|
||
EmployeeId *int64 `json:"employee_id"`
|
||
}
|
||
type SeatSaveRes struct{}
|
||
|
||
// SeatAutoReq mode: fill=增量补位(保留手工);reorder=全部重排(覆盖手工,需二次确认)
|
||
type SeatAutoReq struct {
|
||
g.Meta `path:"/event/admin/seat/auto" method:"post" tags:"event" summary:"自动排座"`
|
||
EventId int64 `v:"required" json:"event_id"`
|
||
Mode string `v:"required|in:fill,reorder#模式取值非法" json:"mode"`
|
||
}
|
||
type SeatAutoRes struct {
|
||
Assigned int `json:"assigned"` // 本次新分配人数
|
||
Unassigned int `json:"unassigned"` // 仍未分配人数
|
||
ManualOverridden int `json:"manual_overridden"` // 被覆盖/清空的手工座位数(reorder 才有意义)
|
||
Excluded int `json:"excluded"` // 本次「不参与排座」的员工人数
|
||
}
|
||
|
||
// ===== 员工导入(两段式:预览不落库 → 冲突裁决 → 确认入库)=====
|
||
|
||
// ImportRow 一行解析后的员工数据(由管理端 SheetJS 解析后提交;后端不解析文件)
|
||
type ImportRow struct {
|
||
Name string `json:"name"`
|
||
Phone string `json:"phone"`
|
||
Dept string `json:"dept"`
|
||
Remark string `json:"remark"`
|
||
}
|
||
|
||
type ImportPreviewRowOut struct {
|
||
Idx int `json:"idx"`
|
||
Type string `json:"type"` // new / update / conflict / error
|
||
Name string `json:"name"`
|
||
Phone string `json:"phone"` // 原样回显,前端展示可自行脱敏
|
||
Dept string `json:"dept"`
|
||
Message string `json:"message"` // 分类原因(如"手机号缺失""同名不同号")
|
||
}
|
||
|
||
// ImportPreviewReq 预览入参:已解析好的结构化行数组(非 multipart 文件)
|
||
type ImportPreviewReq struct {
|
||
g.Meta `path:"/event/employee/import-preview" method:"post" tags:"event" summary:"导入预览(不落库)"`
|
||
EnterpriseId int64 `v:"required#请选择企业" json:"enterprise_id"`
|
||
EventId int64 `json:"event_id"`
|
||
FileName string `json:"file_name"`
|
||
Rows []ImportRow `v:"required|min-length:1#文件没有有效数据" json:"rows"`
|
||
}
|
||
|
||
type ImportPreviewRes struct {
|
||
ImportLogId int64 `json:"import_log_id"` // 确认时回传;服务端据此从库读回快照
|
||
Total int `json:"total"`
|
||
Inserted int `json:"inserted"`
|
||
Updated int `json:"updated"`
|
||
Skipped int `json:"skipped"`
|
||
Conflict int `json:"conflict"`
|
||
Rows []ImportPreviewRowOut `json:"rows"`
|
||
}
|
||
|
||
// ImportDecision action: merge(视为同一人·更新手机号) / create(视为另一个人新增) / ignore
|
||
type ImportDecision struct {
|
||
Idx int `json:"idx"`
|
||
Action string `v:"required|in:merge,create,ignore#裁决动作非法" json:"action"`
|
||
}
|
||
|
||
type ImportConfirmReq struct {
|
||
g.Meta `path:"/event/employee/import-confirm" method:"post" tags:"event" summary:"确认导入"`
|
||
ImportLogId int64 `v:"required#导入标识缺失" json:"import_log_id"`
|
||
Decisions []ImportDecision `json:"decisions"`
|
||
}
|
||
type ImportConfirmRes struct {
|
||
Inserted int `json:"inserted"`
|
||
Updated int `json:"updated"`
|
||
Skipped int `json:"skipped"`
|
||
}
|
||
|
||
type ImportLogItem struct {
|
||
Id int64 `json:"id"`
|
||
EnterpriseId int64 `json:"enterprise_id"`
|
||
EventId int64 `json:"event_id"`
|
||
FileName string `json:"file_name"`
|
||
Status string `json:"status"`
|
||
Total int `json:"total"`
|
||
Inserted int `json:"inserted"`
|
||
Updated int `json:"updated"`
|
||
Skipped int `json:"skipped"`
|
||
Conflict int `json:"conflict"`
|
||
Operator string `json:"operator"`
|
||
CreatedAt string `json:"created_at"`
|
||
}
|
||
|
||
type ImportLogListReq struct {
|
||
g.Meta `path:"/event/import/log/list" method:"get" tags:"event" summary:"导入历史"`
|
||
EnterpriseId int64 `json:"enterprise_id"`
|
||
EventId int64 `json:"event_id"`
|
||
Page int `json:"page"`
|
||
PageSize int `json:"pageSize"`
|
||
}
|
||
type ImportLogListRes struct {
|
||
List []ImportLogItem `json:"list"`
|
||
Total int `json:"total"`
|
||
}
|
||
|
||
// ===== 活动小程序码(A18)=====
|
||
|
||
// EventQrcodeReq 生成活动小程序码(scene 只承载 event_id)
|
||
type EventQrcodeReq struct {
|
||
g.Meta `path:"/event/admin/qrcode" method:"post" tags:"event" summary:"生成活动小程序码"`
|
||
EventId int64 `v:"required" json:"event_id"`
|
||
}
|
||
type EventQrcodeRes struct {
|
||
CodeUrl string `json:"code_url"`
|
||
}
|
||
|
||
// ===== 查座审计(A19,架构 §5.2 遗漏项补录)=====
|
||
|
||
// QueryLogItem 查座审计列表项。
|
||
//
|
||
// PhoneMasked 落库时已脱敏(138****0000),原样返回,不再二次脱敏;
|
||
// OpenidMasked 由服务端输出时脱敏(前 6 位 + ***),openid 为空时为空串;
|
||
// Result 0 失败 / 1 成功。
|
||
type QueryLogItem struct {
|
||
Id int64 `json:"id"`
|
||
EventId int64 `json:"event_id"`
|
||
EventTitle string `json:"event_title"`
|
||
Ip string `json:"ip"`
|
||
PhoneMasked string `json:"phone_masked"`
|
||
OpenidMasked string `json:"openid_masked"`
|
||
Result int `json:"result"`
|
||
CreatedAt string `json:"created_at"`
|
||
}
|
||
|
||
// EventQueryLogReq 查座审计查询条件:EventId=0 表示全部活动;Result=-1 表示全部结果。
|
||
type EventQueryLogReq struct {
|
||
g.Meta `path:"/event/query/log/list" method:"get" tags:"event" summary:"查座审计列表"`
|
||
EventId int64 `json:"event_id"` // 0 = 全部
|
||
Result int `json:"result"` // -1 全部 / 0 失败 / 1 成功
|
||
Page int `json:"page"`
|
||
PageSize int `json:"pageSize"`
|
||
}
|
||
type EventQueryLogRes struct {
|
||
List []QueryLogItem `json:"list"`
|
||
Total int `json:"total"`
|
||
}
|