331 lines
12 KiB
Go
331 lines
12 KiB
Go
package consts
|
||
|
||
// JWT audience
|
||
const (
|
||
AudUser = "user"
|
||
AudAdmin = "admin"
|
||
)
|
||
|
||
// 请求上下文变量(中间件 SetCtxVar)
|
||
const (
|
||
CtxUserId = "userId"
|
||
CtxLevelKey = "levelKey"
|
||
CtxAdminId = "adminId"
|
||
|
||
// 管理员审计上下文(AdminPerm 中间件写入,WriteAudit 读取)
|
||
CtxAdminRole = "adminRole"
|
||
CtxAdminAccount = "adminAccount"
|
||
CtxAdminName = "adminName"
|
||
)
|
||
|
||
// 管理员角色(admin_users.role_value)
|
||
const (
|
||
AdminRoleSuper = "super" // 超管:全部权限
|
||
AdminRoleOperator = "operator" // 运营:内容读写,不含管理员管理与审计
|
||
AdminRoleReadonly = "readonly" // 只读:仅可查看
|
||
)
|
||
|
||
// 管理员状态(admin_users.status)
|
||
const (
|
||
AdminStatusDisabled = 0
|
||
AdminStatusEnabled = 1
|
||
)
|
||
|
||
// 审计结果(admin_audit_logs.result)
|
||
const (
|
||
AuditResultFail = 0 // 失败
|
||
AuditResultSuccess = 1 // 成功
|
||
)
|
||
|
||
// 业务错误码(响应 code 字段)
|
||
const (
|
||
CodeLocked = 4001 // 模块未授权(等级锁定)
|
||
CodeQuotaExhausted = 4002 // 额度用尽(免费/会员/付费额度都已耗尽)
|
||
CodeNoteLimit = 4003 // 笔记数量超上限(免费版最多 50 条)
|
||
CodeNoteNotFound = 4004 // 笔记不存在/无权
|
||
CodeEventUnavailable = 4005 // 活动不存在或未发布
|
||
CodeSeatRateLimited = 4006 // 查座频率超限
|
||
CodeSeatCooling = 4007 // 查座连续失败冷却中
|
||
CodeImportConflict = 4008 // 导入存在未处理冲突
|
||
CodeLayoutConflict = 4009 // 布局版本冲突(CAS 失败)
|
||
CodePayFail = 4101 // 下单/支付参数异常
|
||
)
|
||
|
||
// 默认等级:会员到期后回落的目标等级
|
||
const DefaultLevelKey = "v1"
|
||
|
||
// 表名
|
||
const (
|
||
TableUsers = "users"
|
||
TableModules = "modules"
|
||
TableLevels = "levels"
|
||
TableTools = "tools"
|
||
TableUsageLogs = "tool_usage_logs"
|
||
TableWorkbench = "user_workbench"
|
||
TableAdminUsers = "admin_users"
|
||
TableAdminAuditLog = "admin_audit_logs"
|
||
TableFeedbacks = "feedbacks"
|
||
TableMemberPlans = "member_plans"
|
||
TableMemberOrders = "member_orders"
|
||
TableQuotaPacks = "quota_packs"
|
||
TableUserToolQuota = "user_tool_quota"
|
||
TableQuotaUsage = "user_quota_usage"
|
||
TableSettings = "settings"
|
||
TableNotes = "notes"
|
||
|
||
// 年会域(T08 建前 6 张;T09/T10 分别追加 event_import_logs / event_seat_queries)
|
||
TableEnterprises = "enterprises"
|
||
TableEmployees = "employees"
|
||
TableAnnualEvents = "annual_events"
|
||
TableEventParticipants = "event_participants"
|
||
TableEventTables = "event_tables"
|
||
TableEventSeats = "event_seats"
|
||
TableEventImportLogs = "event_import_logs"
|
||
TableEventSeatQueries = "event_seat_queries"
|
||
)
|
||
|
||
// 年会活动状态(annual_events.status,字符串枚举;仅 published 可查座)
|
||
const (
|
||
EventStatusDraft = "draft"
|
||
EventStatusPublished = "published"
|
||
EventStatusEnded = "ended"
|
||
)
|
||
|
||
// 自动排座模式(/event/admin/seat/auto 的 mode)
|
||
const (
|
||
SeatModeFill = "fill" // 增量补位:保留手工号,只填未分配员工到空位
|
||
SeatModeReorder = "reorder" // 全部重排:覆盖含手工号在内的编号并清空 is_manual
|
||
)
|
||
|
||
// 桌型(event_tables.table_type,N4)
|
||
//
|
||
// 0 普通桌 / 1 主桌 / 2 签到台 / 3 媒体席 / 4 备用桌 / 9 其他。
|
||
// 类型默认联动(前端 N4-10,后端中立存储;老数据缺列回退 0):
|
||
//
|
||
// 签到台/媒体席/备用桌 → capacity=0 + exclude_auto=1
|
||
// 普通桌 → capacity=10 + exclude_auto=0
|
||
// 主桌 → capacity=10 + exclude_auto=1
|
||
const (
|
||
TableTypeNormal = 0 // 普通桌
|
||
TableTypeMain = 1 // 主桌
|
||
TableTypeCheckin = 2 // 签到台
|
||
TableTypeMedia = 3 // 媒体席
|
||
TableTypeSpare = 4 // 备用桌
|
||
TableTypeOther = 9 // 其他
|
||
)
|
||
|
||
// 员工导入:行分类(预览 type,见 §8.4)
|
||
const (
|
||
ImportTypeNew = "new" // 新号码 → 新增
|
||
ImportTypeUpdate = "update" // 同手机号 → 视为同一人,更新
|
||
ImportTypeConflict = "conflict" // 同名不同号 → 需人工裁决
|
||
ImportTypeError = "error" // 缺手机号/格式非法 → 跳过(计入 skipped)
|
||
)
|
||
|
||
// 员工导入:冲突裁决动作(decisions.action,见 §8.4)
|
||
const (
|
||
ImportActionMerge = "merge" // 视为同一人·更新手机号
|
||
ImportActionCreate = "create" // 视为另一个人新增
|
||
ImportActionIgnore = "ignore" // 忽略
|
||
)
|
||
|
||
// 导入记录状态(event_import_logs.status,见 §8.4)
|
||
const (
|
||
ImportStatusDraft = "draft" // 预览中
|
||
ImportStatusCommitted = "committed" // 已入库
|
||
ImportStatusCancelled = "cancelled" // 已取消
|
||
)
|
||
|
||
// 导入行数上限(超出给明确提示;可用 settings 覆盖)
|
||
const (
|
||
SettingImportRowLimit = "event_import_row_limit" // settings 键
|
||
// DefaultImportRowLimit 单次导入行数上限兜底值
|
||
DefaultImportRowLimit = 2000
|
||
)
|
||
|
||
// 查座限流/冷却阈值(settings 键 + 缺省值;无 Redis,以 event_seat_queries 时间窗为准)
|
||
const (
|
||
SettingSeatRateLimitPerMin = "event.seat.rateLimitPerMin" // ≥N 次/分钟 → 4006
|
||
SettingSeatRateLimitPerHour = "event.seat.rateLimitPerHour" // ≥N 次/小时 → 4006
|
||
SettingSeatFailCooldownMinutes = "event.seat.failCooldownMinutes" // 冷却时长(分钟)
|
||
SettingSeatFailThreshold = "event.seat.failThreshold" // 连续失败达到该值触发冷却
|
||
|
||
DefaultSeatRateLimitPerMin = 5 // PRD-02 §4.2.3 建议值
|
||
DefaultSeatRateLimitPerHour = 20 // 建议值
|
||
DefaultSeatFailCooldownMinutes = 10 // 建议值
|
||
DefaultSeatFailThreshold = 5 // 建议值
|
||
)
|
||
|
||
// 查座审计结果枚举(event_seat_queries.result,架构 §3.2.9)
|
||
const (
|
||
SeatResultFail = 0 // 失败(未命中/未分配)
|
||
SeatResultSuccess = 1 // 成功(命中并返回本人桌座)
|
||
SeatResultAll = -1 // 审计列表筛选用:全部结果(仅用于入参,不落库)
|
||
)
|
||
|
||
// 笔记额度与提醒状态
|
||
const (
|
||
// NoteFreeLimit 免费用户活跃笔记数上限(总量上限,非每月重置)
|
||
NoteFreeLimit = 50
|
||
|
||
// notes.remind_status 状态枚举
|
||
NoteRemindNone = 0 // 未设置
|
||
NoteRemindPending = 1 // 待提醒
|
||
NoteRemindSent = 2 // 已提醒
|
||
NoteRemindFailed = 3 // 发送失败(含未发送·授权不足 / 模板未配置)
|
||
NoteRemindExpired = 4 // 已过期
|
||
)
|
||
|
||
// 笔记提醒过期设置(settings 表)
|
||
const (
|
||
SettingNoteRemindExpireHours = "note_remind_expire_hours" // 待提醒超过该小时数仍未发送则置「已过期」
|
||
)
|
||
|
||
// DefaultNoteRemindExpireHours 提醒过期兜底值:settings 未配置时使用。
|
||
const DefaultNoteRemindExpireHours = 24
|
||
|
||
// 订单类型:同一个下单/发货链路承载「会员」与「次数包」两种商品
|
||
const (
|
||
OrderTypeMember = 1 // 会员套餐(延长等级有效期)
|
||
OrderTypeQuota = 2 // 次数包(增加某工具的付费额度余额)
|
||
)
|
||
|
||
// ============================================================================
|
||
// 商业化域:优惠码 / 优惠券(迭代-2026-09-20)
|
||
// ============================================================================
|
||
|
||
// 表名(优惠码 / 券模板 / 用户持有券)
|
||
const (
|
||
TablePromoCodes = "promo_codes"
|
||
TableCoupons = "coupons"
|
||
TableUserCoupons = "user_coupons"
|
||
)
|
||
|
||
// 业务错误码:优惠凭证域
|
||
//
|
||
// 编号接续 4001–4009 / 4010–4014 段(架构 §4.5 统一裁定,解决两份 PRD 的冲突)。
|
||
const (
|
||
CodePromoInvalid = 4010 // 优惠码无效/过期/达上限/超单人限用/不适用;或同时传 promo_code 与 user_coupon_id
|
||
CodeCouponUnavailable = 4011 // 券不可用/已用/过期/作废;免单券并发占用失败
|
||
CodeLevelInvalid = 4012 // 等级不存在或已停用
|
||
CodePromoRateLimited = 4013 // 同一用户 1 分钟内优惠码错误次数超限
|
||
CodeProductPriceMismatch = 4014 // 服务端自检:settings 道具价格与 goodsPrice 预期不一致
|
||
)
|
||
|
||
// 业务错误码(续 4015–4018 段)
|
||
//
|
||
// 4015 属 T01(订单两步式):订单不存在 / 不属于当前用户 / 状态不允许该操作。
|
||
// 4016/4017(T02 头像上传)见紧随其后的独立区块;4018 属 T04(座次自动排座前置条件)。
|
||
const (
|
||
CodeOrderInvalid = 4015 // 订单不存在 / 不属于当前用户 / 状态不允许该操作(已支付、已关闭)
|
||
CodeSeatAutoInvalid = 4018 // 自动排座前置条件不满足(无可参与排座的桌)——fail-closed,message 列出被排除的桌
|
||
)
|
||
|
||
// 头像上传错误码(T02 / N3)
|
||
//
|
||
// 4017 上传失败**必须给可读中文提示**(如「头像上传失败,请重试」)且**原头像不变、不静默失败**(U1)。
|
||
const (
|
||
CodeUploadInvalid = 4016 // 上传校验失败:体积超限(>5MB)/ 格式不支持 —— 前端不发起上传
|
||
CodeUploadFailed = 4017 // 上传存储失败(服务端写盘 / 目录异常)—— 可读中文提示,原头像不变
|
||
)
|
||
|
||
// 券型(coupons.coupon_type / user_coupons.coupon_type)
|
||
//
|
||
// 1 免单券(走支付)/ 2 展示券(仅展示)。**新建默认 2**(fail-closed)。
|
||
const (
|
||
CouponTypeFreebie = 1
|
||
CouponTypeDisplay = 2
|
||
)
|
||
|
||
// 券面语义 kind(coupons.kind / user_coupons.kind):1 满减 / 2 免单
|
||
const (
|
||
CouponKindCut = 1
|
||
CouponKindFreebie = 2
|
||
)
|
||
|
||
// 用户券状态(user_coupons.status)
|
||
const (
|
||
UserCouponStatusUnused = 0 // 未使用
|
||
UserCouponStatusUsed = 1 // 已使用(占用或核销)
|
||
UserCouponStatusExpired = 2 // 已过期
|
||
UserCouponStatusVoid = 3 // 已作废
|
||
)
|
||
|
||
// 用户券来源(user_coupons.source)
|
||
const (
|
||
UserCouponSourceAdmin = 1 // 后台发放
|
||
UserCouponSourceClaim = 2 // 活动领取
|
||
UserCouponSourceSystem = 3 // 系统赠送
|
||
)
|
||
|
||
// 用户券占用/核销人(user_coupons.used_by)
|
||
const (
|
||
UserCouponUsedBySystem = "system" // 订单占用
|
||
UserCouponUsedByAdmin = "admin" // 人工核销
|
||
)
|
||
|
||
// 订单使用凭证类型(member_orders.promo_kind)
|
||
const (
|
||
PromoKindNone = 0 // 未使用凭证
|
||
PromoKindCode = 1 // 优惠码
|
||
PromoKindCoupon = 2 // 免单券
|
||
)
|
||
|
||
// 适用范围(promo_codes.scope / coupons.scope):0 全部 / 1 指定会员套餐 / 2 指定次数包
|
||
const (
|
||
PromoScopeAll = 0
|
||
PromoScopePlan = 1
|
||
PromoScopePack = 2
|
||
)
|
||
|
||
// 优惠凭证域 settings 键(后台可配,不硬编码进 config.yaml)
|
||
const (
|
||
SettingFreebieProductId = "pay.freebie.product_id" // 免单道具 ID
|
||
SettingFreebiePriceCents = "pay.freebie.price_cents" // 免单道具价格(分)
|
||
SettingPromoFailLimitPerMin = "promo.fail.limitPerMin" // 同一用户 1 分钟错误上限
|
||
SettingCouponLockTtlSeconds = "coupon.lock.ttlSeconds" // 免单券占用自动释放时长(秒)
|
||
)
|
||
|
||
// 优惠凭证域 settings 兜底值(settings 未配置时使用)
|
||
const (
|
||
DefaultFreebieProductId = "admin_1"
|
||
DefaultFreebiePriceCents = 1
|
||
DefaultPromoFailLimitPerMin = 6
|
||
DefaultCouponLockTtlSeconds = 900
|
||
)
|
||
|
||
// 额度来源(扣减时实际命中的池)
|
||
const (
|
||
QuotaSourceFree = "free" // 免费额度
|
||
QuotaSourceMember = "member" // 会员额度
|
||
QuotaSourcePaid = "paid" // 付费额度(次数包)
|
||
QuotaSourceNone = "none" // 已耗尽
|
||
)
|
||
|
||
// 额度设置键(settings 表)
|
||
const (
|
||
SettingQuotaPeriodDays = "quota_period_days" // 全局默认额度重置周期(天)
|
||
)
|
||
|
||
// DefaultQuotaPeriodDays 额度周期兜底值:settings 与 config 都未配置时使用。
|
||
// 后台「额度设置」可改,用户维度与会员套餐维度可各自覆盖。
|
||
const DefaultQuotaPeriodDays = 7
|
||
|
||
// 会员订单状态
|
||
const (
|
||
OrderStatusPending = 0 // 待支付
|
||
OrderStatusDelivered = 1 // 已支付并发货(会员权益已生效)
|
||
OrderStatusRefunded = 2 // 已退款
|
||
OrderStatusClosed = 3 // 已关闭(超时未支付)
|
||
)
|
||
|
||
// 虚拟支付环境与支付渠道
|
||
const (
|
||
XPayEnvProd = 0 // env 固定填 0(现网)
|
||
XPayCurrency = "CNY" // 币种固定 CNY
|
||
XPayMode = "short_series_goods" // 道具直购
|
||
PayChannelWx = "wxpay" // 微信虚拟支付(Android 等)
|
||
PayChannelIOS = "apple" // Apple IAP
|
||
XPayNotifyEvent = "xpay_goods_deliver_notify" // 发货推送事件名
|
||
)
|