小程序一些功能更新

This commit is contained in:
李琦
2026-09-29 10:57:01 +08:00
parent 0cb70a7618
commit 3bb7fa8db3
96 changed files with 13890 additions and 213 deletions

View File

@@ -0,0 +1,21 @@
package entity
import "github.com/gogf/gf/v2/os/gtime"
// AnnualEvents 年会活动(一场年会 = 一个活动,隶属某企业)。
//
// Status 采用字符串(draft/published/ended),与 PRD-02 §6.2 字面一致;
// HallLayout 为画布/背景/舞台 JSON;LayoutVersion 为并发编辑 CAS 版本号。
type AnnualEvents struct {
Id int64 `json:"id"`
EnterpriseId int64 `json:"enterprise_id"`
Title string `json:"title"`
Venue string `json:"venue"`
EventTime *gtime.Time `json:"event_time"`
Status string `json:"status"` // draft / published / ended
HallLayout string `json:"hall_layout"`
CodeUrl string `json:"code_url"`
LayoutVersion int `json:"layout_version"`
CreatedAt *gtime.Time `json:"created_at"`
UpdatedAt *gtime.Time `json:"updated_at"`
}

View File

@@ -0,0 +1,29 @@
package entity
import "github.com/gogf/gf/v2/os/gtime"
// Coupons 优惠券模板。
//
// 券型(CouponType):1 免单券(走支付)/ 2 展示券(仅展示,**新建默认**)。
// 面额语义(Kind):1 满减 / 2 免单;Value 为面额(分,仅展示用途)。
// 适用范围(Scope):0 全部 / 1 指定会员套餐 / 2 指定次数包,ScopeKeys 为 JSON 数组。
// TotalLimit 总发行上限(0=不限),PerUserLimit 单人限领。
type Coupons struct {
Id int64 `json:"id"`
Title string `json:"title"`
SubTitle string `json:"sub_title"`
CouponType int `json:"coupon_type"`
Kind int `json:"kind"`
Value int `json:"value"`
ThresholdCents int `json:"threshold_cents"`
Scope int `json:"scope"`
ScopeKeys string `json:"scope_keys"`
TotalLimit int `json:"total_limit"`
PerUserLimit int `json:"per_user_limit"`
ValidFrom *gtime.Time `json:"valid_from"`
ValidTo *gtime.Time `json:"valid_to"`
Status int `json:"status"`
Remark string `json:"remark"`
CreatedAt *gtime.Time `json:"created_at"`
UpdatedAt *gtime.Time `json:"updated_at"`
}

View File

@@ -0,0 +1,22 @@
package entity
import "github.com/gogf/gf/v2/os/gtime"
// Employees 企业员工库(跨活动复用)。
//
// 去重键为 (EnterpriseId, Phone)(见 migrate 的 UNIQUE uk_ent_phone);
// Name 参与导入时的「同名不同号」冲突检测。
type Employees struct {
Id int64 `json:"id"`
EnterpriseId int64 `json:"enterprise_id"`
Name string `json:"name"`
Phone string `json:"phone"` // 手机号(入库前去空格)
Dept string `json:"dept"`
Remark string `json:"remark"`
Status int `json:"status"` // 1 正常 / 0 停用
CreatedAt *gtime.Time `json:"created_at"`
UpdatedAt *gtime.Time `json:"updated_at"`
// DeletedAt 软删除时间,NULL=未删除;DeletedFrom 保存墓碑化前的 phone 原值(JSON),便于恢复。
DeletedAt *gtime.Time `json:"deleted_at"`
DeletedFrom *string `json:"deleted_from"`
}

View File

@@ -0,0 +1,14 @@
package entity
import "github.com/gogf/gf/v2/os/gtime"
// Enterprises 企业(年会座次的顶层归属,一个企业可办多场年会)
type Enterprises struct {
Id int64 `json:"id"`
Name string `json:"name"` // 企业名称
Contact string `json:"contact"`
Remark string `json:"remark"`
Status int `json:"status"` // 1 正常 / 0 停用
CreatedAt *gtime.Time `json:"created_at"`
UpdatedAt *gtime.Time `json:"updated_at"`
}

View File

@@ -0,0 +1,27 @@
package entity
import "github.com/gogf/gf/v2/os/gtime"
// EventImportLogs 员工导入记录/审计(两段式:预览草稿 → 确认入库)。
//
// 快照防篡改方案:**DB 快照 by id**(不用 HMAC)。
// 预览时把「原始行 + 逐行分类判定」序列化为 Snapshot 落库(status=draft);
// 确认时凭 Id 从库读回快照,只接受快照内的行 —— 无需密钥、无硬编码密钥隐患。
type EventImportLogs struct {
Id int64 `json:"id"`
EnterpriseId int64 `json:"enterprise_id"`
EventId int64 `json:"event_id"` // 0=仅入企业库,不纳入某活动
FileName string `json:"file_name"`
Status string `json:"status"` // draft 预览中 / committed 已入库 / cancelled 已取消
Token string `json:"token"` // 预览快照令牌(保留字段;确认以 Id 为准)
Snapshot string `json:"snapshot"` // 解析后完整行 + 分类判定 JSON
Total int `json:"total"`
Inserted int `json:"inserted"`
Updated int `json:"updated"`
Skipped int `json:"skipped"`
Conflict int `json:"conflict"`
Conflicts string `json:"conflicts"` // 人工裁决结果 JSON
Operator string `json:"operator"`
CreatedAt *gtime.Time `json:"created_at"`
UpdatedAt *gtime.Time `json:"updated_at"`
}

View File

@@ -0,0 +1,16 @@
package entity
import "github.com/gogf/gf/v2/os/gtime"
// EventParticipants 活动候场名单(活动 × 员工,多对多;支持跨活动复用)。
//
// 「未分配」= 在候场名单中、但未绑定任何 event_seats.employee_id 的成员。
//
// T04 新增:ExcludeAssign 是否不参与自动排座(1=不参与,永不被自动分配,一直留在员工池)。
type EventParticipants struct {
Id int64 `json:"id"`
EventId int64 `json:"event_id"`
EmployeeId int64 `json:"employee_id"`
ExcludeAssign int `json:"exclude_assign"` // 1=不参与排座
CreatedAt *gtime.Time `json:"created_at"`
}

View File

@@ -0,0 +1,17 @@
package entity
import "github.com/gogf/gf/v2/os/gtime"
// EventSeatQueries 查座审计 + 限流依据(无 Redis 时的权威统计源,架构 §8.6.2)。
//
// 每次「通过限流闸门」的查询都会落一行(成功/失败都写);限流窗口判定与连续失败冷却
// 都基于本表的时间窗 COUNT 与最近若干条 result 计算。
type EventSeatQueries struct {
Id int64 `json:"id"`
EventId int64 `json:"event_id"`
Openid string `json:"openid"` // 有登录态时记录,否则空
Ip string `json:"ip"` // 客户端 IP
PhoneMasked string `json:"phone_masked"` // 脱敏手机号(138****0000)
Result int `json:"result"` // 0 失败 / 1 成功
CreatedAt *gtime.Time `json:"created_at"`
}

View File

@@ -0,0 +1,18 @@
package entity
import "github.com/gogf/gf/v2/os/gtime"
// EventSeats 座位(默认编号 1..capacity,顺时针自桌正上方(12 点)起)。
//
// IsManual 标记该座位号是否被人工改过(决定「自动排座」fill 是否保留);
// EmployeeId 为 NULL 表示空位。去重键 (EventId, TableId, SeatNo)。
type EventSeats struct {
Id int64 `json:"id"`
EventId int64 `json:"event_id"` // 冗余,便于按活动查座
TableId int64 `json:"table_id"`
SeatNo int `json:"seat_no"`
IsManual int `json:"is_manual"` // 1 已手工指定编号 / 0 默认
EmployeeId *int64 `json:"employee_id"` // NULL=空位
CreatedAt *gtime.Time `json:"created_at"`
UpdatedAt *gtime.Time `json:"updated_at"`
}

View File

@@ -0,0 +1,23 @@
package entity
import "github.com/gogf/gf/v2/os/gtime"
// EventTables 圆桌(画布上一个可拖拽的圆桌)。
//
// T04 新增:TableType 桌型(0 普通 / 1 主桌 / 2 签到台 / 3 媒体席 / 4 备用桌 / 9 其他)、
// Remark 桌备注、ExcludeAuto 是否不参与自动排序(1=不参与)。老数据回退默认值(S14)。
type EventTables struct {
Id int64 `json:"id"`
EventId int64 `json:"event_id"`
TableNo string `json:"table_no"`
Name string `json:"name"`
X int `json:"x"`
Y int `json:"y"`
Capacity int `json:"capacity"` // 每桌人数,同步生成 1..Capacity 个座位;特殊桌可为 0
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=不参与自动排序
CreatedAt *gtime.Time `json:"created_at"`
UpdatedAt *gtime.Time `json:"updated_at"`
}

View File

@@ -0,0 +1,31 @@
package entity
import "github.com/gogf/gf/v2/os/gtime"
// Notes 笔记主体(含定时提醒与订阅授权计数)。
//
// 额度语义(见 PRD-02 §4.1.1):
// - 免费用户活跃笔记数(DeletedAt IS NULL)上限 50,会员不限量;
// - 新建计入、编辑不计入、删除(软删除)立即释放额度;
// - 会员判定走 logic.EffectiveLevelKey,会员过期即回落免费额度。
//
// 提醒语义(见 PRD-02 §4.1.2、架构 §4.2):
// - RemindStatus 取值见 consts(0 未设置 / 1 待提醒 / 2 已提醒 / 3 发送失败 / 4 已过期);
// - SubscribeCount 记录「已获授权的可发送次数」,前端 requestSubscribeMessage 成功后累加,
// 发送前条件扣减,不足即降级为站内提醒。
type Notes struct {
Id int64 `json:"id"`
UserId int64 `json:"user_id"` // 归属用户
Title string `json:"title"` // 标题
Content string `json:"content"` // 正文(长文本,可为空)
Tags string `json:"tags"` // 标签,逗号分隔(便于 LIKE/FIND_IN_SET 筛选)
IsPinned int `json:"is_pinned"` // 置顶:1 是 / 0 否
RemindAt *gtime.Time `json:"remind_at"` // 提醒时间,NULL=未设置
RemindStatus int `json:"remind_status"` // 0 未设置 / 1 待提醒 / 2 已提醒 / 3 发送失败 / 4 已过期
RemindSentAt *gtime.Time `json:"remind_sent_at"` // 实际发送时间
RemindAttempts int `json:"remind_attempts"` // 发送尝试次数(失败重试上限用)
SubscribeCount int `json:"subscribe_count"` // 已获授权的可发送次数
DeletedAt *gtime.Time `json:"deleted_at"` // 软删除时间,NULL=未删除(不占额度)
CreatedAt *gtime.Time `json:"created_at"`
UpdatedAt *gtime.Time `json:"updated_at"`
}

View File

@@ -0,0 +1,30 @@
package entity
import "github.com/gogf/gf/v2/os/gtime"
// PromoCodes 优惠码(免单/固定价档位,独立于优惠券)。
//
// 语义:
// - Code 唯一(大写字母+数字,排除易混字符),下单时由用户输入;
// - ProductId / PriceCents 决定「用码后」实际走支付的道具与价格(单位:分);
// - Scope 0 全部 / 1 指定会员套餐 / 2 指定次数包,ScopeKeys 为 JSON 数组;
// - MaxUses 0=不限;PerUserLimit 单人限用次数;
// - UsedCount 在「下单事务内」自增(并发安全依赖行锁)。
type PromoCodes struct {
Id int64 `json:"id"`
Code string `json:"code"`
ProductId string `json:"product_id"`
PriceCents int64 `json:"price_cents"`
Scope int `json:"scope"`
ScopeKeys string `json:"scope_keys"`
MaxUses int `json:"max_uses"`
UsedCount int `json:"used_count"`
PerUserLimit int `json:"per_user_limit"`
ValidFrom *gtime.Time `json:"valid_from"`
ValidTo *gtime.Time `json:"valid_to"`
Status int `json:"status"`
Remark string `json:"remark"`
CreatedBy string `json:"created_by"`
CreatedAt *gtime.Time `json:"created_at"`
UpdatedAt *gtime.Time `json:"updated_at"`
}

View File

@@ -24,4 +24,6 @@ type Tools struct {
UsageCount int64 `json:"usage_count"`
CreatedAt *gtime.Time `json:"created_at"`
UpdatedAt *gtime.Time `json:"updated_at"`
// DeletedAt 软删除时间,NULL=未删除。工具不墓碑化 tool_key(跨仓契约 + 种子幂等,见 softdelete.go)。
DeletedAt *gtime.Time `json:"deleted_at"`
}

View File

@@ -0,0 +1,36 @@
package entity
import "github.com/gogf/gf/v2/os/gtime"
// UserCoupons 用户持有的优惠券(含券面快照 + 占用/核销记录)。
//
// 快照:CouponTitle / CouponType / Kind / Value / ThresholdCents 在发放时从模板复制,
// 之后模板改名/改型/改面额**不影响已发券**(约定 S8)。
//
// 状态(Status):0 未使用 / 1 已使用(占用或核销)/ 2 已过期 / 3 已作废。
// 来源(Source):1 后台发放 / 2 活动领取 / 3 系统赠送。
//
// 占用语义(免单券):下单时在同一事务内把 Status 置 1、写 UsedOrderNo / UsedBy='system' /
// LockAt;订单取消/超时由 gcron 释放(清 UsedOrderNo、Status 回 0)。
type UserCoupons struct {
Id int64 `json:"id"`
CouponId int64 `json:"coupon_id"`
UserId int64 `json:"user_id"`
CouponTitle string `json:"coupon_title"`
CouponType int `json:"coupon_type"`
Kind int `json:"kind"`
Value int `json:"value"`
ThresholdCents int `json:"threshold_cents"`
Status int `json:"status"`
Source int `json:"source"`
GrantedBy string `json:"granted_by"`
GrantedAt *gtime.Time `json:"granted_at"`
UsedAt *gtime.Time `json:"used_at"`
ExpireAt *gtime.Time `json:"expire_at"`
UsedOrderNo string `json:"used_order_no"`
UsedBy string `json:"used_by"`
LockAt *gtime.Time `json:"lock_at"`
Remark string `json:"remark"`
CreatedAt *gtime.Time `json:"created_at"`
UpdatedAt *gtime.Time `json:"updated_at"`
}

View File

@@ -25,4 +25,7 @@ type Users struct {
CreatedAt *gtime.Time `json:"created_at"`
LastLoginAt *gtime.Time `json:"last_login_at"`
UpdatedAt *gtime.Time `json:"updated_at"`
// DeletedAt 软删除时间,NULL=未删除;DeletedFrom 保存墓碑化前的唯一键原值(JSON),便于恢复。
DeletedAt *gtime.Time `json:"deleted_at"`
DeletedFrom *string `json:"deleted_from"`
}