diff --git a/.DS_Store b/.DS_Store index 5444b36..aac48b0 100644 Binary files a/.DS_Store and b/.DS_Store differ diff --git a/.trae/rules/project_rules.md b/.trae/rules/project_rules.md new file mode 100644 index 0000000..3742dba --- /dev/null +++ b/.trae/rules/project_rules.md @@ -0,0 +1,228 @@ + + +# 身份定义 + +你是一位资深的软件架构师和工程师,具备丰富的项目经验和系统思维能力。你的核心优势在于: +- 上下文工程专家:构建完整的任务上下文,而非简单的提示响应 +- 规范驱动思维:将模糊需求转化为精确、可执行的规范 +- 质量优先理念:每个阶段都确保高质量输出。 +- 项目对齐能力:深度理解现有项目架构和约束 + + +# 6A工作流执行规则 + +## 阶段1: Align (对齐阶段) + +### 目标: 模糊需求 → 精确规范 + +### 执行步骤 + +1. **项目上下文分析** + - 分析现有项目结构、技术栈、架构模式、依赖关系 + - 分析现有代码模式、现有文档和约定 + - 理解业务域和数据模型 +2. **需求理解确认** + - 创建 `docs/任务名/ALIGNMENT_[任务名].md` + - 包含项目和任务特性规范 + - 包含原始需求、边界确认(明确任务范围)、需求理解(对现有项目的理解)、疑问澄清(存在歧义的地方) +3. **智能决策策略** + - 自动识别歧义和不确定性 + - 生成结构化问题清单(按优先级排序) + - 优先基于现有项目内容和查找类似工程和行业知识进行决策和在文档中回答 + - 有人员倾向或不确定的问题主动中断并询问关键决策点 + - 基于回答更新理解和规范 +4. **中断并询问关键决策点** + - 主动中断询问,迭代执行智能决策策略 +5. **最终共识** + - 生成 `docs/任务名/CONSENSUS_[任务名].md` 包含: + - 明确的需求描述和验收标准 + - 技术实现方案和技术约束和集成方案 + - 任务边界限制和验收标准 + - 确认所有不确定性已解决 + +### 质量门控 + +- 需求边界清晰无歧义 +- 技术方案与现有架构对齐 +- 验收标准具体可测试 +- 所有关键假设已确认 +- 项目特性规范已对齐 + + + + +## 阶段2: Architect (架构阶段) + +### 目标: 共识文档 → 系统架构 → 模块设计 → 接口规范 + +### 执行步骤 + +1. **系统分层设计** + - 基于CONSENSUS、ALIGNMENT文档设计架构 + - 生成 `docs/任务名/DESIGN_[任务名].md` 包含: + - 整体架构图(mermaid绘制) + - 分层设计和核心组件 + - 模块依赖关系图 + - 接口契约定义 + - 数据流向图 + - 异常处理策略 +2. **设计原则** + - 严格按照任务范围,避免过度设计 + - 确保与现有系统架构一致 + - 复用现有组件和模式 + +### 质量门控 + +- 架构图清晰准确 +- 接口定义完整 +- 与现有系统无冲突 +- 设计可行性验证 + +## 阶段3: Atomize (原子化阶段) + +### 目标: 架构设计 → 拆分任务 → 明确接口 → 依赖关系 + +### 执行步骤 + +1. **子任务拆分** + - 基于DESIGN文档生成 `docs/任务名/TASK_[任务名].md` + - 每个原子任务包含: + - 输入契约(前置依赖、输入数据、环境依赖) + - 输出契约(输出数据、交付物、验收标准) + - 实现约束(技术栈、接口规范、质量要求) + - 依赖关系(后置任务、并行任务) +2. **拆分原则** + - 复杂度可控,便于AI高成功率交付 + - 按功能模块分解,确保任务原子性和独立性 + - 有明确的验收标准,尽量可以独立编译和测试 + - 依赖关系清晰 +3. **生成任务依赖图**(使用mermaid) + +### 质量门控 + +- 任务覆盖完整需求 +- 依赖关系无循环 +- 每个任务都可独立验证 +- 复杂度评估合理 + + + + +## 阶段4: Approve (审批阶段) + +### 目标: 原子任务 → 人工审查 → 迭代修改 → 按文档执行 + +### 执行步骤 + +1. **执行检查清单** + - 完整性:任务计划覆盖所有需求 + - 一致性:与前期文档保持一致 + - 可行性:技术方案确实可行 + - 可控性:风险在可接受范围,复杂度是否可控 + - 可测性:验收标准明确可执行 +2. **最终确认清单** + - 明确的实现需求(无歧义) + - 明确的子任务定义 + - 明确的边界和限制 + - 明确的验收标准 + - 代码、测试、文档质量标准 + + + + +## 阶段5: Automate (自动化执行) + +### 目标: 按节点执行 → 编写测试 → 实现代码 → 文档同步 + +### 执行步骤 + +1. **逐步实施子任务** + - 创建 `docs/任务名/ACCEPTANCE_[任务名].md` 记录完成情况 +2. **代码质量要求** + - 严格遵循项目现有代码规范 + - 保持与现有代码风格一致 + - 使用项目现有的工具和库 + - 复用项目现有组件 + - 代码尽量精简易读 + - API KEY放到.env文件中并且不要提交git +3. **异常处理** + - 遇到不确定问题立刻中断执行 + - 在TASK文档中记录问题详细信息和位置 + - 寻求人工澄清后继续 +4. **逐步实施流程** 按任务依赖顺序执行,对每个子任务执行: + - 执行前检查(验证输入契约、环境准备、依赖满足) + - 实现核心逻辑(按设计文档编写代码) + - 编写单元测试(边界条件、异常情况) + - 运行验证测试 + - 更新相关文档 + - 每完成一个任务立即验证 + + + + +## 阶段6: Assess (评估阶段) + +### 目标: 执行结果 → 质量评估 → 文档更新 → 交付确认 + +### 执行步骤 + +1. **验证执行结果** + - 更新 `docs/任务名/ACCEPTANCE_[任务名].md` + - 整体验收检查: + - 所有需求已实现 + - 验收标准全部满足 + - 项目编译通过 + - 所有测试通过 + - 功能完整性验证 + - 实现与设计文档一致 +2. **质量评估指标** + - 代码质量(规范、可读性、复杂度) + - 测试质量(覆盖率、用例有效性) + - 文档质量(完整性、准确性、一致性) + - 现有系统集成良好 + - 未引入技术债务 +3. **最终交付物** + - 生成 `docs/任务名/FINAL_[任务名].md`(项目总结报告) + - 生成 `docs/任务名/TODO_[任务名].md`(精简明确哪些待办的事宜和哪些缺少的配置等,我方便直接寻找支持) +4. **TODO询问** 询问用户TODO的解决方式,精简明确哪些待办的事宜和哪些缺少的配置等,同时提供有用的操作指引 + +# 技术执行规范 + +## 安全规范 + +- API密钥等敏感信息使用.env文件管理 + +## 文档同步 + +- 代码变更同时更新相关文档 + +## 测试策略 + +- 测试优先:先写测试,后写实现 +- 边界覆盖:覆盖正常流程、边界条件、异常情况 + +## 交互体验优化 + +### 进度反馈 + +- 显示当前执行阶段 +- 提供详细的执行步骤 +- 标示完成情况 +- 突出需要关注的问题 + +### 异常处理机制 + +#### 中断条件 + +- 遇到无法自主决策的问题 +- 觉得需要询问用户的问题 +- 技术实现出现阻塞 +- 文档不一致需要确认修正 + +#### 恢复策略 + +- 保存当前执行状态 +- 记录问题详细信息 +- 询问并等待人工干预 +- 从中断点任务继续执行 + diff --git a/.vercel/project.json b/.vercel/project.json new file mode 100644 index 0000000..f696239 --- /dev/null +++ b/.vercel/project.json @@ -0,0 +1 @@ +{"projectName":"trae_bindbox_game_p1uh"} \ No newline at end of file diff --git a/.vercelignore b/.vercelignore new file mode 100644 index 0000000..a48e5d3 --- /dev/null +++ b/.vercelignore @@ -0,0 +1,7 @@ +node_modules +build +dist +.git +.trae +.log +.figma \ No newline at end of file diff --git a/Makefile b/Makefile index f09e1b0..89ce180 100644 --- a/Makefile +++ b/Makefile @@ -1,14 +1,14 @@ # Custom configuration | 独立配置 # Service name | 项目名称 -SERVICE=minichat +SERVICE=bindboxgame # Service name in specific style | 项目经过style格式化的名称 -SERVICE_STYLE=minichat +SERVICE_STYLE=bindboxgame # Service name in lowercase | 项目名称全小写格式 -SERVICE_LOWER=minichat +SERVICE_LOWER=bindboxgame # Service name in snake format | 项目名称下划线格式 -SERVICE_SNAKE=minichat +SERVICE_SNAKE=bindbox # Service name in snake format | 项目名称短杠格式 -SERVICE_DASH=minichat +SERVICE_DASH=bindboxgame # The project version, if you don't use git, you should set it manually | 项目版本,如果不使用git请手动设置 VERSION=$(shell git describe --tags --always) diff --git a/bin/server b/bin/server new file mode 100755 index 0000000..93762fa Binary files /dev/null and b/bin/server differ diff --git a/MINI b/bindbox-game similarity index 66% rename from MINI rename to bindbox-game index 9fd674b..0120e07 100755 Binary files a/MINI and b/bindbox-game differ diff --git a/cmd/gormgen/README.md b/cmd/gormgen/README.md index 11276d7..a2fd36f 100644 --- a/cmd/gormgen/README.md +++ b/cmd/gormgen/README.md @@ -34,6 +34,8 @@ eg : ```shell # 根目录下执行 -go run cmd/gormgen/main.go -dsn "root:api2api..@tcp(sh-cynosdbmysql-grp-88th45wy.sql.tencentcdb.com:28555)/mini_chat?charset=utf8mb4&parseTime=True&loc=Local" -tables "log_operation,log_request,admin,app_keyword,app_keyword_reply,app_user,app_message_log,mini_program,mini_program_access_token" +go run cmd/gormgen/main.go -dsn "root:api2api..@tcp(sh-cynosdbmysql-grp-88th45wy.sql.tencentcdb.com:28555)/bindbox_game?charset=utf8mb4&parseTime=True&loc=Local" -tables "admin,log_operation,log_request,activities,activity_categories,activity_draw_logs,activity_issues,activity_reward_settings,guild,guild_boxes,guild_contribute_logs,guild_members,system_coupons,user_coupons,user_inventory,user_inventory_transfers,user_points,user_points_ledger" -``` +go run cmd/gormgen/main.go -dsn "root:api2api..@tcp(sh-cynosdbmysql-grp-88th45wy.sql.tencentcdb.com:28555)/bindbox_game?charset=utf8mb4&parseTime=True&loc=Local" -tables "admin,log_operation,log_request,activities,activity_categories,activity_draw_logs,activity_issues,activity_reward_settings,guild,guild_boxes,guild_contribute_logs,guild_members,system_coupons,user_coupons,user_inventory,user_inventory_transfers,user_points,user_points_ledger,users,user_addresses,menu_actions,menus,role_actions,role_menus,role_users,roles,order_items,orders,products,shipping_records,product_categories,user_invites,system_item_cards,user_item_cards,activity_draw_effects,banner" + +``` \ No newline at end of file diff --git a/cmd/handlergen/handler_template.go.tpl b/cmd/handlergen/handler_template.go.tpl index 47ece10..9fa5d4a 100644 --- a/cmd/handlergen/handler_template.go.tpl +++ b/cmd/handlergen/handler_template.go.tpl @@ -4,12 +4,12 @@ import ( "net/http" "strconv" - "mini-chat/internal/code" - "mini-chat/internal/pkg/core" + "bindbox-game/internal/code" + "bindbox-game/internal/pkg/core" "WeChatService/internal/pkg/logger" - "mini-chat/internal/repository/mysql" - "mini-chat/internal/repository/mysql/dao" - "mini-chat/internal/repository/mysql/model" + "bindbox-game/internal/repository/mysql" + "bindbox-game/internal/repository/mysql/dao" + "bindbox-game/internal/repository/mysql/model" "go.uber.org/zap" "gorm.io/gorm" diff --git a/cmd/mfmt/main.go b/cmd/mfmt/main.go index bb4eb1a..92b0ad7 100644 --- a/cmd/mfmt/main.go +++ b/cmd/mfmt/main.go @@ -15,7 +15,7 @@ import ( "path/filepath" "strings" - "mini-chat/internal/pkg/errors" + "bindbox-game/internal/pkg/errors" "go.uber.org/zap" "golang.org/x/tools/go/packages" diff --git a/configs/configs.go b/configs/configs.go index 76c915e..21a9e4c 100644 --- a/configs/configs.go +++ b/configs/configs.go @@ -5,7 +5,7 @@ import ( _ "embed" "io" - "mini-chat/internal/pkg/env" + "bindbox-game/internal/pkg/env" "github.com/spf13/viper" ) @@ -15,28 +15,41 @@ var config = new(Config) type Config struct { MySQL struct { Read struct { - Addr string `toml:"addr"` - User string `toml:"user"` - Pass string `toml:"pass"` - Name string `toml:"name"` - } `toml:"read"` + Addr string `mapstructure:"addr" toml:"addr"` + User string `mapstructure:"user" toml:"user"` + Pass string `mapstructure:"pass" toml:"pass"` + Name string `mapstructure:"name" toml:"name"` + } `mapstructure:"read" toml:"read"` Write struct { - Addr string `toml:"addr"` - User string `toml:"user"` - Pass string `toml:"pass"` - Name string `toml:"name"` - } `toml:"write"` - } `toml:"mysql"` + Addr string `mapstructure:"addr" toml:"addr"` + User string `mapstructure:"user" toml:"user"` + Pass string `mapstructure:"pass" toml:"pass"` + Name string `mapstructure:"name" toml:"name"` + } `mapstructure:"write" toml:"write"` + } `mapstructure:"mysql" toml:"mysql"` JWT struct { - AdminSecret string `toml:"admin_secret"` - PatientSecret string `toml:"patient_secret"` - DoctorSecret string `toml:"doctor_secret"` - } `toml:"jwt"` + AdminSecret string `mapstructure:"admin_secret" toml:"admin_secret"` + PatientSecret string `mapstructure:"patient_secret" toml:"patient_secret"` + DoctorSecret string `mapstructure:"doctor_secret" toml:"doctor_secret"` + } `mapstructure:"jwt" toml:"jwt"` Language struct { - Local string `toml:"local"` - } `toml:"language"` + Local string `mapstructure:"local" toml:"local"` + } `mapstructure:"language" toml:"language"` + + Wechat struct { + AppID string `mapstructure:"app_id" toml:"app_id"` + AppSecret string `mapstructure:"app_secret" toml:"app_secret"` + } `mapstructure:"wechat" toml:"wechat"` + + COS struct { + Bucket string `mapstructure:"bucket" toml:"bucket"` + Region string `mapstructure:"region" toml:"region"` + SecretID string `mapstructure:"secret_id" toml:"secret_id"` + SecretKey string `mapstructure:"secret_key" toml:"secret_key"` + BaseURL string `mapstructure:"base_url" toml:"base_url"` + } `mapstructure:"cos" toml:"cos"` } var ( diff --git a/configs/constants.go b/configs/constants.go index ad7b71a..e72d358 100644 --- a/configs/constants.go +++ b/configs/constants.go @@ -24,13 +24,13 @@ const ( EnUS = "en-us" // CustomerProjectNameZh 客户项目中文名称 - CustomerProjectNameZh = "微聊" + CustomerProjectNameZh = "盲盒游戏" // CustomerProjectNameEn 客户项目英文名称 - CustomerProjectNameEn = "Mini Chat" + CustomerProjectNameEn = "Bindbox Game" // CustomerProjectVersion 客户项目版本 - CustomerProjectVersion = "Release-2025101601" + CustomerProjectVersion = "Release-2025111111" ) // GetResourcesFilePath 获取资源文件路径 diff --git a/configs/fat_configs.toml b/configs/fat_configs.toml index a05363f..3ccc1fb 100644 --- a/configs/fat_configs.toml +++ b/configs/fat_configs.toml @@ -3,15 +3,27 @@ local = 'zh-cn' [mysql.read] addr = 'sh-cynosdbmysql-grp-88th45wy.sql.tencentcdb.com:28555' -name = 'mini_chat' +name = 'bindbox_game' pass = 'api2api..' user = 'root' [mysql.write] addr = 'sh-cynosdbmysql-grp-88th45wy.sql.tencentcdb.com:28555' -name = 'mini_chat' +name = 'bindbox_game' pass = 'api2api..' user = 'root' [jwt] -admin_secret = "m9ycX9RTPyuYTWw9FrCc" \ No newline at end of file +admin_secret = "m9ycX9RTPyuYTWw9FrCc" + +[wechat] +app_id = "wx26ad074017e1e63f" +app_secret = "026c19ce4f3bb090c56573024c59a8be" + +[cos] +bucket = "keaiya-1259195914" +region = "ap-shanghai" +secret_id = "AKIDtjPtAFPNDuR1UnxvoUCoRAnJgw164Zv6" +secret_key = "B0vvjMoMsKcipnJlLnFyWt6A2JRSJ0Wr" +# 可选:如有 CDN/自定义域名则填写,否则留空 +base_url = "" diff --git a/data.db b/data.db new file mode 100644 index 0000000..e69de29 diff --git a/development_standards.md b/development_standards.md new file mode 100644 index 0000000..d44b9f7 --- /dev/null +++ b/development_standards.md @@ -0,0 +1,209 @@ +# 开发规范与问题记录 + +## 项目概述 +本项目基于 Vue 3 + TypeScript + Element Plus + Vite 技术栈开发的管理系统。 + +## 已发现的问题与解决方案 + +### 1. 时间字段处理错误 +**问题描述**: +创建道具卡时出现数据库错误:`Error 1292 (22007): Incorrect date value: '0000-00-00' for column 'valid_start' at row 1` + +**问题原因**: +- 当用户没有选择有效期时,代码仍然尝试提交时间字段 +- 时间数据格式不正确或包含无效值 +- 后端数据库不接受'0000-00-00'这样的无效日期 + +**解决方案**: +```typescript +// 处理有效期 - 只有当时间范围有效时才添加时间字段 +if (validTimeRange.value && validTimeRange.value.length === 2 && + validTimeRange.value[0] && validTimeRange.value[1]) { + try { + const startTime = new Date(validTimeRange.value[0]).getTime() + const endTime = new Date(validTimeRange.value[1]).getTime() + + // 验证时间是否有效 + if (!isNaN(startTime) && !isNaN(endTime) && startTime > 0 && endTime > 0) { + submitData.valid_start_unix = Math.floor(startTime / 1000) + submitData.valid_end_unix = Math.floor(endTime / 1000) + } + } catch (error) { + console.error('时间处理错误:', error) + } +} +``` + +**开发规范**: +1. **时间字段处理**: + - 必须验证时间数据的有效性 + - 使用`isNaN()`检查时间戳是否为有效数字 + - 确保时间值大于0 + - 添加try-catch处理可能的异常 + +2. **数据提交原则**: + - 只提交有效和必要的数据字段 + - 避免提交null、undefined或无效的时间数据 + - 对可选字段进行严格的有效性检查 + +### 2. 价格字段数据类型错误 +**问题描述**: +创建道具卡时出现错误:`json: cannot unmarshal null into Go struct field createItemCardRequest.price of type int64` + +**解决方案**: +```typescript +// 确保价格字段存在且为数字类型 +if (submitData.price === undefined || submitData.price === null) { + submitData.price = 0 +} else { + submitData.price = Number(submitData.price) +} +``` + +### 3. 组件结构错误 +**问题描述**: +道具卡管理页面按钮不显示,原因是错误的组件插槽使用 + +**解决方案**: +使用独立的按钮区域布局,避免错误的插槽使用: +```vue + + + + +
+
+ + 新增道具卡 + +
+
+ + + +``` + +### 4. 数据枚举显示问题 +**问题描述**: +状态、类型、范围、效果等字段显示为数字而不是对应的文本标签 + +**解决方案**: +1. 增强枚举映射函数的空值处理 +2. 完善状态字段的多状态判断 +3. 添加数据类型检查 + +```typescript +// 增强的枚举映射函数 +const getCardTypeLabel = (type: number) => cardTypeMap[type as keyof typeof cardTypeMap] || '未知' + +// 完善的状态显示 +{{ row.status === 1 ? '启用' : row.status === 2 ? '禁用' : '未知' }} + +// 空值处理 +{{ getCardTypeLabel(row.card_type || 0) }} +``` + +### 5. API路径404错误 +**问题描述**: +优惠券API请求返回404错误:`admin/system_coupons` 路径不存在 + +**问题原因**: +后端API路径可能不存在或需要调整 + +**解决方案**: +1. 检查实际的API路径配置 +2. 对比道具卡API路径确认一致性 +3. 添加详细的请求调试信息 +4. 检查代理配置是否正确 + +### 6. 数据枚举和操作按钮显示问题 +**问题描述**: +道具卡管理页面中: +- 状态、类型、范围、效果等字段显示为数字而不是对应的文本标签 +- 操作栏(编辑、删除按钮)不显示 + +**问题原因**: +1. 枚举映射函数没有正确处理空值 +2. 使用了错误的按钮组件(原生的`el-button`而不是项目封装的`ArtButtonTable`) +3. 插槽模板语法正确但组件渲染有问题 + +**解决方案**: +1. **枚举显示修复**: +```vue + + + +``` + +2. **操作按钮修复**: +```vue + +``` + +3. **组件导入**: +```typescript +import ArtButtonTable from '@/components/core/forms/art-button-table/index.vue' +``` + +**开发规范**: +1. **组件使用规范**: + - 优先使用项目封装的组件(如`ArtButtonTable`)而不是原生Element Plus组件 + - 保持与其他页面一致的UI风格和交互体验 + - 使用项目统一的图标和样式系统 + +2. **枚举显示规范**: + - 所有状态字段必须提供完整的枚举映射 + - 处理空值和异常值情况,提供默认值 + - 使用统一的标签样式和颜色规范 + +3. **调试和日志**: + - 添加详细的数据结构检查日志 + - 验证枚举映射函数的正确性 + - 检查组件渲染和插槽绑定的正确性 + +## 前端开发规范 + +### 1. 表单数据处理 +- 提交前必须清理数据,移除undefined和null值 +- 对数字类型字段进行类型转换和验证 +- 时间字段必须验证有效性 +- 可选字段需要条件判断 + +### 2. 错误处理 +- 所有API调用必须添加try-catch异常处理 +- 用户友好的错误提示信息 +- 控制台记录详细错误信息便于调试 + +### 3. 代码结构 +- 保持组件单一职责原则 +- 复杂的表单处理逻辑抽取为独立函数 +- 添加必要的注释说明业务逻辑 + +### 4. 数据验证 +- 前端表单必须进行完整的验证 +- 后端返回的错误需要友好处理 +- 特殊字段(如时间、价格)需要额外验证 + +## 后端接口规范 +- 明确字段类型要求(如int64) +- 提供清晰的错误信息和错误码 +- 对无效数据给出具体的错误描述 + +## 数据库规范 +- 不允许插入'0000-00-00'等无效日期 +- 时间字段必须有默认值或允许为null +- 数字类型字段不能接收字符串类型 + +--- + +**最后更新**:2025年11月14日 +**文档维护**:开发团队 \ No newline at end of file diff --git a/docs/docs.go b/docs/docs.go index 0369f58..ed7eb82 100644 --- a/docs/docs.go +++ b/docs/docs.go @@ -15,14 +15,59 @@ const docTemplate = `{ "host": "{{.Host}}", "basePath": "{{.BasePath}}", "paths": { - "/api/admin/app/check_status": { + "/api/admin/activities": { + "post": { + "security": [ + { + "LoginVerifyToken": [] + } + ], + "description": "创建活动,配置基本信息与分类、Boss标签", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "管理端.活动" + ], + "summary": "创建活动", + "parameters": [ + { + "description": "请求参数", + "name": "RequestBody", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/admin.createActivityRequest" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/admin.simpleMessageResponse" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/code.Failure" + } + } + } + } + }, + "/api/admin/activities/{activity_id}": { "get": { "security": [ { "LoginVerifyToken": [] } ], - "description": "管理端根据 app_id 调用外部验证服务获取状态(正常/封禁/未知)", + "description": "查看指定活动的详细信息", "consumes": [ "application/json" ], @@ -30,210 +75,23 @@ const docTemplate = `{ "application/json" ], "tags": [ - "管理端.小程序" + "管理端.活动" ], - "summary": "检查小程序状态", + "summary": "查看活动详情", "parameters": [ { - "type": "string", - "description": "小程序ID", - "name": "app_id", - "in": "query", - "required": true - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/app.checkAppStatusResponse" - } - }, - "400": { - "description": "Bad Request", - "schema": { - "$ref": "#/definitions/code.Failure" - } - } - } - } - }, - "/api/admin/app/create": { - "post": { - "security": [ - { - "LoginVerifyToken": [] - } - ], - "description": "新增小程序", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "管理端.小程序" - ], - "summary": "新增小程序", - "parameters": [ - { - "description": "请求参数", - "name": "RequestBody", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/app.createAppRequest" - } - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/app.createAppResponse" - } - }, - "400": { - "description": "Bad Request", - "schema": { - "$ref": "#/definitions/code.Failure" - } - } - } - } - }, - "/api/admin/app/delete": { - "post": { - "security": [ - { - "LoginVerifyToken": [] - } - ], - "description": "删除小程序", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "管理端.小程序" - ], - "summary": "删除小程序", - "parameters": [ - { - "description": "请求参数", - "name": "RequestBody", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/app.deleteAppRequest" - } - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/app.deleteAppResponse" - } - }, - "400": { - "description": "Bad Request", - "schema": { - "$ref": "#/definitions/code.Failure" - } - } - } - } - }, - "/api/admin/app/keyword": { - "post": { - "security": [ - { - "LoginVerifyToken": [] - } - ], - "description": "添加意图关键字", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "管理端.意图关键字" - ], - "summary": "添加意图关键字", - "parameters": [ - { - "description": "请求参数", - "name": "RequestBody", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/keyword.createKeywordRequest" - } - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/keyword.createKeywordResponse" - } - }, - "400": { - "description": "Bad Request", - "schema": { - "$ref": "#/definitions/code.Failure" - } - } - } - } - }, - "/api/admin/app/keyword/material/{id}": { - "put": { - "security": [ - { - "LoginVerifyToken": [] - } - ], - "description": "修改意图关键字素材", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "管理端.意图关键字" - ], - "summary": "修改意图关键字素材", - "parameters": [ - { - "type": "string", - "description": "素材编号ID", - "name": "id", + "type": "integer", + "description": "活动ID", + "name": "activity_id", "in": "path", "required": true - }, - { - "description": "请求参数", - "name": "RequestBody", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/keyword.modifyKeywordMaterialRequest" - } } ], "responses": { "200": { "description": "OK", "schema": { - "$ref": "#/definitions/keyword.modifyKeywordMaterialResponse" + "$ref": "#/definitions/model.Activities" } }, "400": { @@ -244,124 +102,13 @@ const docTemplate = `{ } } }, - "post": { - "security": [ - { - "LoginVerifyToken": [] - } - ], - "description": "配置意图关键字素材", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "管理端.意图关键字" - ], - "summary": "配置意图关键字素材", - "parameters": [ - { - "type": "string", - "description": "编号ID", - "name": "id", - "in": "path", - "required": true - }, - { - "description": "请求参数", - "name": "RequestBody", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/keyword.createKeywordMaterialRequest" - } - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/keyword.createKeywordMaterialResponse" - } - }, - "400": { - "description": "Bad Request", - "schema": { - "$ref": "#/definitions/code.Failure" - } - } - } - } - }, - "/api/admin/app/keyword/materials": { - "get": { - "security": [ - { - "LoginVerifyToken": [] - } - ], - "description": "获取意图关键字素材列表", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "管理端.意图关键字" - ], - "summary": "获取意图关键字素材列表", - "parameters": [ - { - "type": "integer", - "description": "意图关键字ID", - "name": "keyword_id", - "in": "query", - "required": true - }, - { - "type": "integer", - "default": 1, - "description": "当前页码", - "name": "page", - "in": "query", - "required": true - }, - { - "type": "integer", - "default": 20, - "description": "每页返回的数据量,最多 100 条", - "name": "page_size", - "in": "query", - "required": true - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/keyword.keywordMaterialPageListResponse" - } - }, - "400": { - "description": "Bad Request", - "schema": { - "$ref": "#/definitions/code.Failure" - } - } - } - } - }, - "/api/admin/app/keyword/{id}": { "put": { "security": [ { "LoginVerifyToken": [] } ], - "description": "修改意图关键字", + "description": "修改活动基本信息、分类、Boss标签等", "consumes": [ "application/json" ], @@ -369,14 +116,14 @@ const docTemplate = `{ "application/json" ], "tags": [ - "管理端.意图关键字" + "管理端.活动" ], - "summary": "修改意图关键字", + "summary": "修改活动", "parameters": [ { - "type": "string", - "description": "编号ID", - "name": "id", + "type": "integer", + "description": "活动ID", + "name": "activity_id", "in": "path", "required": true }, @@ -386,7 +133,7 @@ const docTemplate = `{ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/keyword.modifyKeywordRequest" + "$ref": "#/definitions/admin.modifyActivityRequest" } } ], @@ -394,7 +141,7 @@ const docTemplate = `{ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/keyword.modifyKeywordResponse" + "$ref": "#/definitions/admin.simpleMessageResponse" } }, "400": { @@ -411,7 +158,7 @@ const docTemplate = `{ "LoginVerifyToken": [] } ], - "description": "删除意图关键字", + "description": "删除指定活动", "consumes": [ "application/json" ], @@ -419,14 +166,14 @@ const docTemplate = `{ "application/json" ], "tags": [ - "管理端.意图关键字" + "管理端.活动" ], - "summary": "删除意图关键字", + "summary": "删除活动", "parameters": [ { - "type": "string", - "description": "编号ID", - "name": "id", + "type": "integer", + "description": "活动ID", + "name": "activity_id", "in": "path", "required": true } @@ -435,7 +182,7 @@ const docTemplate = `{ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/keyword.deleteKeywordResponse" + "$ref": "#/definitions/admin.simpleMessageResponse" } }, "400": { @@ -447,14 +194,14 @@ const docTemplate = `{ } } }, - "/api/admin/app/keywords": { + "/api/admin/activities/{activity_id}/issues": { "get": { "security": [ { "LoginVerifyToken": [] } ], - "description": "获取意图关键字列表", + "description": "获取指定活动的期数列表,支持分页", "consumes": [ "application/json" ], @@ -462,27 +209,21 @@ const docTemplate = `{ "application/json" ], "tags": [ - "管理端.意图关键字" + "管理端.活动" ], - "summary": "获取意图关键字列表", + "summary": "查看活动期数", "parameters": [ { "type": "integer", - "description": "小程序ID", - "name": "app_id", - "in": "query", + "description": "活动ID", + "name": "activity_id", + "in": "path", "required": true }, - { - "type": "string", - "description": "意图关键字", - "name": "keyword", - "in": "query" - }, { "type": "integer", "default": 1, - "description": "当前页码", + "description": "页码", "name": "page", "in": "query", "required": true @@ -490,7 +231,7 @@ const docTemplate = `{ { "type": "integer", "default": 20, - "description": "每页返回的数据量,最多 100 条", + "description": "每页数量,最多100", "name": "page_size", "in": "query", "required": true @@ -500,7 +241,7 @@ const docTemplate = `{ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/keyword.keywordPageListResponse" + "$ref": "#/definitions/admin.listIssuesResponse" } }, "400": { @@ -510,16 +251,14 @@ const docTemplate = `{ } } } - } - }, - "/api/admin/app/users": { - "get": { + }, + "post": { "security": [ { "LoginVerifyToken": [] } ], - "description": "小程序用户列表", + "description": "为指定活动创建一个新的期数", "consumes": [ "application/json" ], @@ -527,85 +266,14 @@ const docTemplate = `{ "application/json" ], "tags": [ - "管理端.小程序" + "管理端.活动" ], - "summary": "小程序用户列表", + "summary": "创建活动期数", "parameters": [ - { - "type": "string", - "description": "小程序ID", - "name": "app_id", - "in": "query", - "required": true - }, - { - "type": "string", - "description": "用户昵称", - "name": "user_name", - "in": "query" - }, - { - "type": "string", - "description": "用户ID", - "name": "user_id", - "in": "query" - }, { "type": "integer", - "default": 1, - "description": "当前页码", - "name": "page", - "in": "query", - "required": true - }, - { - "type": "integer", - "default": 20, - "description": "每页返回的数据量,最多 100 条", - "name": "page_size", - "in": "query", - "required": true - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/app.userListResponse" - } - }, - "400": { - "description": "Bad Request", - "schema": { - "$ref": "#/definitions/code.Failure" - } - } - } - } - }, - "/api/admin/app/{id}": { - "put": { - "security": [ - { - "LoginVerifyToken": [] - } - ], - "description": "编辑小程序", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "管理端.小程序" - ], - "summary": "编辑小程序", - "parameters": [ - { - "type": "string", - "description": "编号ID", - "name": "id", + "description": "活动ID", + "name": "activity_id", "in": "path", "required": true }, @@ -615,7 +283,7 @@ const docTemplate = `{ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/app.modifyAppRequest" + "$ref": "#/definitions/admin.createIssueRequest" } } ], @@ -623,7 +291,7 @@ const docTemplate = `{ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/app.modifyAppResponse" + "$ref": "#/definitions/admin.simpleMessage" } }, "400": { @@ -635,14 +303,14 @@ const docTemplate = `{ } } }, - "/api/admin/apps": { - "get": { + "/api/admin/activities/{activity_id}/issues/{issue_id}": { + "put": { "security": [ { "LoginVerifyToken": [] } ], - "description": "小程序列表", + "description": "修改指定期数的信息", "consumes": [ "application/json" ], @@ -650,32 +318,386 @@ const docTemplate = `{ "application/json" ], "tags": [ - "管理端.小程序" + "管理端.活动" ], - "summary": "小程序列表", + "summary": "修改活动期数", "parameters": [ { - "type": "string", - "description": "小程序名称", - "name": "name", - "in": "query" - }, - { - "type": "string", - "description": "小程序ID", - "name": "app_id", - "in": "query" + "type": "integer", + "description": "活动ID", + "name": "activity_id", + "in": "path", + "required": true }, { "type": "integer", - "description": "客服编号", - "name": "admin_id", + "description": "期ID", + "name": "issue_id", + "in": "path", + "required": true + }, + { + "description": "请求参数", + "name": "RequestBody", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/admin.modifyIssueRequest" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/admin.simpleMessage" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/code.Failure" + } + } + } + }, + "delete": { + "security": [ + { + "LoginVerifyToken": [] + } + ], + "description": "删除指定期数", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "管理端.活动" + ], + "summary": "删除活动期数", + "parameters": [ + { + "type": "integer", + "description": "活动ID", + "name": "activity_id", + "in": "path", + "required": true + }, + { + "type": "integer", + "description": "期ID", + "name": "issue_id", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/admin.simpleMessage" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/code.Failure" + } + } + } + } + }, + "/api/admin/activities/{activity_id}/issues/{issue_id}/rewards": { + "get": { + "security": [ + { + "LoginVerifyToken": [] + } + ], + "description": "查看指定期数的奖励配置列表", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "管理端.活动" + ], + "summary": "查看期数奖品", + "parameters": [ + { + "type": "integer", + "description": "活动ID", + "name": "activity_id", + "in": "path", + "required": true + }, + { + "type": "integer", + "description": "期ID", + "name": "issue_id", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/admin.listRewardsResponse" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/code.Failure" + } + } + } + }, + "post": { + "security": [ + { + "LoginVerifyToken": [] + } + ], + "description": "为指定期数批量创建奖励配置", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "管理端.活动" + ], + "summary": "创建期数奖品", + "parameters": [ + { + "type": "integer", + "description": "活动ID", + "name": "activity_id", + "in": "path", + "required": true + }, + { + "type": "integer", + "description": "期ID", + "name": "issue_id", + "in": "path", + "required": true + }, + { + "description": "请求参数", + "name": "RequestBody", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/admin.createRewardsRequest" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/admin.simpleMessageResponse" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/code.Failure" + } + } + } + } + }, + "/api/admin/activities/{activity_id}/issues/{issue_id}/rewards/{reward_id}": { + "put": { + "security": [ + { + "LoginVerifyToken": [] + } + ], + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "管理端.活动" + ], + "summary": "更新期数奖励", + "parameters": [ + { + "type": "integer", + "description": "活动ID", + "name": "activity_id", + "in": "path", + "required": true + }, + { + "type": "integer", + "description": "期ID", + "name": "issue_id", + "in": "path", + "required": true + }, + { + "type": "integer", + "description": "奖励ID", + "name": "reward_id", + "in": "path", + "required": true + }, + { + "description": "请求参数", + "name": "RequestBody", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/admin.modifyRewardRequest" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/admin.simpleMessageResponse" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/code.Failure" + } + } + } + }, + "delete": { + "security": [ + { + "LoginVerifyToken": [] + } + ], + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "管理端.活动" + ], + "summary": "删除期数奖励", + "parameters": [ + { + "type": "integer", + "description": "活动ID", + "name": "activity_id", + "in": "path", + "required": true + }, + { + "type": "integer", + "description": "期ID", + "name": "issue_id", + "in": "path", + "required": true + }, + { + "type": "integer", + "description": "奖励ID", + "name": "reward_id", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/admin.simpleMessageResponse" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/code.Failure" + } + } + } + } + }, + "/api/admin/activity_categories": { + "get": { + "security": [ + { + "LoginVerifyToken": [] + } + ], + "description": "获取启用状态的活动分类列表", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "管理端.活动" + ], + "summary": "活动分类列表", + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/admin.listCategoriesResponse" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/code.Failure" + } + } + } + } + }, + "/api/admin/banners": { + "get": { + "security": [ + { + "LoginVerifyToken": [] + } + ], + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "管理端.运营" + ], + "summary": "查看轮播图列表", + "parameters": [ + { + "type": "integer", + "description": "状态", + "name": "status", "in": "query" }, { "type": "integer", "default": 1, - "description": "当前页码", + "description": "页码", "name": "page", "in": "query", "required": true @@ -683,7 +705,7 @@ const docTemplate = `{ { "type": "integer", "default": 20, - "description": "每页返回的数据量,最多 100 条", + "description": "每页数量", "name": "page_size", "in": "query", "required": true @@ -693,7 +715,140 @@ const docTemplate = `{ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/app.listResponse" + "$ref": "#/definitions/admin.listBannersResponse" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/code.Failure" + } + } + } + }, + "post": { + "security": [ + { + "LoginVerifyToken": [] + } + ], + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "管理端.运营" + ], + "summary": "创建轮播图", + "parameters": [ + { + "description": "请求参数", + "name": "RequestBody", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/admin.createBannerRequest" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/admin.createBannerResponse" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/code.Failure" + } + } + } + } + }, + "/api/admin/banners/{banner_id}": { + "put": { + "security": [ + { + "LoginVerifyToken": [] + } + ], + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "管理端.运营" + ], + "summary": "修改轮播图", + "parameters": [ + { + "type": "string", + "description": "轮播图ID", + "name": "banner_id", + "in": "path", + "required": true + }, + { + "description": "请求参数", + "name": "RequestBody", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/admin.modifyBannerRequest" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/admin.pcSimpleMessage" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/code.Failure" + } + } + } + }, + "delete": { + "security": [ + { + "LoginVerifyToken": [] + } + ], + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "管理端.运营" + ], + "summary": "删除轮播图", + "parameters": [ + { + "type": "string", + "description": "轮播图ID", + "name": "banner_id", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/admin.pcSimpleMessage" } }, "400": { @@ -795,6 +950,244 @@ const docTemplate = `{ } } }, + "/api/admin/guilds": { + "post": { + "security": [ + { + "LoginVerifyToken": [] + } + ], + "description": "创建工会并将首位成员设为会长", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "管理端.工会" + ], + "summary": "创建工会", + "parameters": [ + { + "description": "请求参数", + "name": "RequestBody", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/admin.createGuildRequest" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/admin.createGuildResponse" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/code.Failure" + } + } + } + } + }, + "/api/admin/guilds/{guild_id}": { + "get": { + "security": [ + { + "LoginVerifyToken": [] + } + ], + "description": "查看指定工会详情", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "管理端.工会" + ], + "summary": "查看工会详情", + "parameters": [ + { + "type": "integer", + "description": "工会ID", + "name": "guild_id", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/model.Guild" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/code.Failure" + } + } + } + }, + "put": { + "security": [ + { + "LoginVerifyToken": [] + } + ], + "description": "修改指定工会信息", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "管理端.工会" + ], + "summary": "修改工会", + "parameters": [ + { + "type": "integer", + "description": "工会ID", + "name": "guild_id", + "in": "path", + "required": true + }, + { + "description": "请求参数", + "name": "RequestBody", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/admin.modifyGuildRequest" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/admin.modifyGuildResponse" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/code.Failure" + } + } + } + }, + "delete": { + "security": [ + { + "LoginVerifyToken": [] + } + ], + "description": "删除指定工会", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "管理端.工会" + ], + "summary": "删除工会", + "parameters": [ + { + "type": "integer", + "description": "工会ID", + "name": "guild_id", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/admin.deleteGuildResponse" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/code.Failure" + } + } + } + } + }, + "/api/admin/guilds/{guild_id}/members": { + "get": { + "security": [ + { + "LoginVerifyToken": [] + } + ], + "description": "查看指定工会的成员列表", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "管理端.工会" + ], + "summary": "查看工会成员", + "parameters": [ + { + "type": "integer", + "description": "工会ID", + "name": "guild_id", + "in": "path", + "required": true + }, + { + "type": "integer", + "default": 1, + "description": "页码", + "name": "page", + "in": "query", + "required": true + }, + { + "type": "integer", + "default": 20, + "description": "每页数量,最多100", + "name": "page_size", + "in": "query", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/admin.listGuildMembersResponse" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/code.Failure" + } + } + } + } + }, "/api/admin/list": { "get": { "security": [ @@ -899,14 +1292,13 @@ const docTemplate = `{ } } }, - "/api/admin/messages": { + "/api/admin/product_categories": { "get": { "security": [ { "LoginVerifyToken": [] } ], - "description": "获取消息日志", "consumes": [ "application/json" ], @@ -914,28 +1306,26 @@ const docTemplate = `{ "application/json" ], "tags": [ - "管理端.小程序" + "管理端.商品" ], - "summary": "获取消息日志", + "summary": "查看商品分类列表", "parameters": [ { "type": "string", - "description": "小程序ID", - "name": "app_id", - "in": "query", - "required": true + "description": "名称", + "name": "name", + "in": "query" }, { - "type": "string", - "description": "用户ID", - "name": "user_id", - "in": "query", - "required": true + "type": "integer", + "description": "状态", + "name": "status", + "in": "query" }, { "type": "integer", "default": 1, - "description": "当前页码", + "description": "页码", "name": "page", "in": "query", "required": true @@ -943,7 +1333,7 @@ const docTemplate = `{ { "type": "integer", "default": 20, - "description": "每页返回的数据量,最多 100 条", + "description": "每页数量", "name": "page_size", "in": "query", "required": true @@ -953,7 +1343,49 @@ const docTemplate = `{ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/app.appMessagePageListResponse" + "$ref": "#/definitions/admin.listProductCategoriesResponse" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/code.Failure" + } + } + } + }, + "post": { + "security": [ + { + "LoginVerifyToken": [] + } + ], + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "管理端.商品" + ], + "summary": "创建商品分类", + "parameters": [ + { + "description": "请求参数", + "name": "RequestBody", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/admin.createProductCategoryRequest" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/admin.createProductCategoryResponse" } }, "400": { @@ -965,73 +1397,13 @@ const docTemplate = `{ } } }, - "/api/admin/messages/latest": { - "get": { - "security": [ - { - "LoginVerifyToken": [] - } - ], - "description": "管理端根据appid获取最新消息记录,包含已读未读状态,访问时自动标记为已读", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "管理端.小程序" - ], - "summary": "根据appid获取最新消息记录", - "parameters": [ - { - "type": "string", - "description": "小程序ID", - "name": "app_id", - "in": "query", - "required": true - }, - { - "type": "integer", - "default": 1, - "description": "当前页码", - "name": "page", - "in": "query", - "required": true - }, - { - "type": "integer", - "default": 20, - "description": "每页返回的数据量,最多 100 条", - "name": "page_size", - "in": "query", - "required": true - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/app.latestMessageByAppIdResponse" - } - }, - "400": { - "description": "Bad Request", - "schema": { - "$ref": "#/definitions/code.Failure" - } - } - } - } - }, - "/api/admin/rel_app/{id}": { + "/api/admin/product_categories/{category_id}": { "put": { "security": [ { "LoginVerifyToken": [] } ], - "description": "客服关联小程序", "consumes": [ "application/json" ], @@ -1039,14 +1411,14 @@ const docTemplate = `{ "application/json" ], "tags": [ - "管理端.客服管理" + "管理端.商品" ], - "summary": "客服关联小程序", + "summary": "修改商品分类", "parameters": [ { "type": "string", - "description": "客服编号ID", - "name": "id", + "description": "分类ID", + "name": "category_id", "in": "path", "required": true }, @@ -1056,7 +1428,7 @@ const docTemplate = `{ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/admin.relAppRequest" + "$ref": "#/definitions/admin.modifyProductCategoryRequest" } } ], @@ -1064,7 +1436,7 @@ const docTemplate = `{ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/admin.relAppResponse" + "$ref": "#/definitions/admin.pcSimpleMessage" } }, "400": { @@ -1074,16 +1446,13 @@ const docTemplate = `{ } } } - } - }, - "/api/admin/send_message": { - "post": { + }, + "delete": { "security": [ { "LoginVerifyToken": [] } ], - "description": "管理员发送消息", "consumes": [ "application/json" ], @@ -1091,55 +1460,15 @@ const docTemplate = `{ "application/json" ], "tags": [ - "管理端.小程序" + "管理端.商品" ], - "summary": "管理员发送消息", + "summary": "删除商品分类", "parameters": [ { - "description": "请求参数", - "name": "RequestBody", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/app.adminSendMessageRequest" - } - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/app.adminSendMessageResponse" - } - }, - "400": { - "description": "Bad Request", - "schema": { - "$ref": "#/definitions/code.Failure" - } - } - } - } - }, - "/api/admin/upload/image": { - "post": { - "description": "上传图片", - "consumes": [ - "multipart/form-data" - ], - "produces": [ - "application/json" - ], - "tags": [ - "通用" - ], - "summary": "上传图片", - "parameters": [ - { - "type": "file", - "description": "选择文件", - "name": "file", - "in": "formData", + "type": "string", + "description": "分类ID", + "name": "category_id", + "in": "path", "required": true } ], @@ -1147,7 +1476,7 @@ const docTemplate = `{ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/upload.uploadImageResponse" + "$ref": "#/definitions/admin.pcSimpleMessage" } }, "400": { @@ -1159,6 +1488,1086 @@ const docTemplate = `{ } } }, + "/api/admin/products": { + "get": { + "security": [ + { + "LoginVerifyToken": [] + } + ], + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "管理端.商品" + ], + "summary": "查看商品列表", + "parameters": [ + { + "type": "string", + "description": "名称", + "name": "name", + "in": "query" + }, + { + "type": "integer", + "description": "分类ID", + "name": "category_id", + "in": "query" + }, + { + "type": "integer", + "description": "状态", + "name": "status", + "in": "query" + }, + { + "type": "integer", + "default": 1, + "description": "页码", + "name": "page", + "in": "query", + "required": true + }, + { + "type": "integer", + "default": 20, + "description": "每页数量", + "name": "page_size", + "in": "query", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/admin.listProductsResponse" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/code.Failure" + } + } + } + }, + "post": { + "security": [ + { + "LoginVerifyToken": [] + } + ], + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "管理端.商品" + ], + "summary": "创建商品", + "parameters": [ + { + "description": "请求参数", + "name": "RequestBody", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/admin.createProductRequest" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/admin.createProductResponse" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/code.Failure" + } + } + } + } + }, + "/api/admin/products/{product_id}": { + "put": { + "security": [ + { + "LoginVerifyToken": [] + } + ], + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "管理端.商品" + ], + "summary": "修改商品", + "parameters": [ + { + "type": "string", + "description": "商品ID", + "name": "product_id", + "in": "path", + "required": true + }, + { + "description": "请求参数", + "name": "RequestBody", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/admin.modifyProductRequest" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/admin.pcSimpleMessage" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/code.Failure" + } + } + } + }, + "delete": { + "security": [ + { + "LoginVerifyToken": [] + } + ], + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "管理端.商品" + ], + "summary": "删除商品", + "parameters": [ + { + "type": "string", + "description": "商品ID", + "name": "product_id", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/admin.pcSimpleMessage" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/code.Failure" + } + } + } + } + }, + "/api/admin/system_item_cards": { + "get": { + "description": "管理员获取道具卡列表,支持按名称、状态、类型等条件筛选", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "管理端.运营管理" + ], + "summary": "获取道具卡列表", + "parameters": [ + { + "type": "string", + "description": "道具卡名称", + "name": "name", + "in": "query" + }, + { + "type": "integer", + "description": "状态:1启用 2禁用", + "name": "status", + "in": "query" + }, + { + "type": "integer", + "description": "道具卡类型:1抽奖卡 2加成卡 3保底卡", + "name": "card_type", + "in": "query" + }, + { + "type": "integer", + "description": "适用范围:1全局 2活动分类 3活动 4期次", + "name": "scope_type", + "in": "query" + }, + { + "type": "integer", + "description": "页码,默认1", + "name": "page", + "in": "query" + }, + { + "type": "integer", + "description": "每页条数,默认10", + "name": "page_size", + "in": "query" + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/admin.listItemCardsResponse" + } + }, + "400": { + "description": "参数错误", + "schema": { + "$ref": "#/definitions/code.Failure" + } + }, + "401": { + "description": "未授权", + "schema": { + "$ref": "#/definitions/code.Failure" + } + }, + "500": { + "description": "服务器内部错误", + "schema": { + "$ref": "#/definitions/code.Failure" + } + } + } + }, + "post": { + "description": "管理员创建新的道具卡,支持设置类型、效果、有效期等属性", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "管理端.运营管理" + ], + "summary": "创建道具卡", + "parameters": [ + { + "description": "创建道具卡请求参数", + "name": "RequestBody", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/admin.createItemCardRequest" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/admin.createItemCardResponse" + } + }, + "400": { + "description": "参数错误", + "schema": { + "$ref": "#/definitions/code.Failure" + } + }, + "401": { + "description": "未授权", + "schema": { + "$ref": "#/definitions/code.Failure" + } + }, + "403": { + "description": "无权限,仅超管可操作", + "schema": { + "$ref": "#/definitions/code.Failure" + } + }, + "500": { + "description": "服务器内部错误", + "schema": { + "$ref": "#/definitions/code.Failure" + } + } + } + } + }, + "/api/admin/system_item_cards/{item_card_id}": { + "put": { + "description": "管理员修改道具卡信息,支持修改名称、价格、有效期等属性", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "管理端.运营管理" + ], + "summary": "修改道具卡", + "parameters": [ + { + "type": "integer", + "description": "道具卡ID", + "name": "item_card_id", + "in": "path", + "required": true + }, + { + "description": "修改道具卡请求参数", + "name": "RequestBody", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/admin.modifyItemCardRequest" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/admin.simpleMessageResponse" + } + }, + "400": { + "description": "参数错误", + "schema": { + "$ref": "#/definitions/code.Failure" + } + }, + "401": { + "description": "未授权", + "schema": { + "$ref": "#/definitions/code.Failure" + } + }, + "403": { + "description": "无权限,仅超管可操作", + "schema": { + "$ref": "#/definitions/code.Failure" + } + }, + "500": { + "description": "服务器内部错误", + "schema": { + "$ref": "#/definitions/code.Failure" + } + } + } + }, + "delete": { + "description": "管理员删除指定的道具卡", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "管理端.运营管理" + ], + "summary": "删除道具卡", + "parameters": [ + { + "type": "integer", + "description": "道具卡ID", + "name": "item_card_id", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/admin.simpleMessageResponse" + } + }, + "400": { + "description": "参数错误", + "schema": { + "$ref": "#/definitions/code.Failure" + } + }, + "401": { + "description": "未授权", + "schema": { + "$ref": "#/definitions/code.Failure" + } + }, + "403": { + "description": "无权限,仅超管可操作", + "schema": { + "$ref": "#/definitions/code.Failure" + } + }, + "500": { + "description": "服务器内部错误", + "schema": { + "$ref": "#/definitions/code.Failure" + } + } + } + } + }, + "/api/admin/users": { + "get": { + "security": [ + { + "LoginVerifyToken": [] + } + ], + "description": "查看APP端用户分页列表", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "管理端.用户" + ], + "summary": "管理端用户列表", + "parameters": [ + { + "type": "integer", + "default": 1, + "description": "页码", + "name": "page", + "in": "query", + "required": true + }, + { + "type": "integer", + "default": 20, + "description": "每页数量,最多100", + "name": "page_size", + "in": "query", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/admin.listUsersResponse" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/code.Failure" + } + } + } + } + }, + "/api/admin/users/{user_id}/coupons": { + "get": { + "security": [ + { + "LoginVerifyToken": [] + } + ], + "description": "查看指定用户持有的优惠券列表", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "管理端.用户" + ], + "summary": "查看用户优惠券列表", + "parameters": [ + { + "type": "integer", + "description": "用户ID", + "name": "user_id", + "in": "path", + "required": true + }, + { + "type": "integer", + "default": 1, + "description": "页码", + "name": "page", + "in": "query", + "required": true + }, + { + "type": "integer", + "default": 20, + "description": "每页数量,最多100", + "name": "page_size", + "in": "query", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/admin.listCouponsResponse" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/code.Failure" + } + } + } + } + }, + "/api/admin/users/{user_id}/coupons/add": { + "post": { + "security": [ + { + "LoginVerifyToken": [] + } + ], + "description": "管理端为指定用户发放优惠券", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "管理端.用户" + ], + "summary": "给用户添加优惠券", + "parameters": [ + { + "type": "integer", + "description": "用户ID", + "name": "user_id", + "in": "path", + "required": true + }, + { + "description": "请求参数", + "name": "RequestBody", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/admin.addCouponRequest" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/admin.addCouponResponse" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/code.Failure" + } + } + } + } + }, + "/api/admin/users/{user_id}/inventory": { + "get": { + "security": [ + { + "LoginVerifyToken": [] + } + ], + "description": "查看指定用户的资产记录", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "管理端.用户" + ], + "summary": "查看用户资产列表", + "parameters": [ + { + "type": "integer", + "description": "用户ID", + "name": "user_id", + "in": "path", + "required": true + }, + { + "type": "integer", + "default": 1, + "description": "页码", + "name": "page", + "in": "query", + "required": true + }, + { + "type": "integer", + "default": 20, + "description": "每页数量,最多100", + "name": "page_size", + "in": "query", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/admin.listInventoryResponse" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/code.Failure" + } + } + } + } + }, + "/api/admin/users/{user_id}/invites": { + "get": { + "security": [ + { + "LoginVerifyToken": [] + } + ], + "description": "查看指定用户邀请的用户列表", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "管理端.用户" + ], + "summary": "查看用户邀请列表", + "parameters": [ + { + "type": "integer", + "description": "用户ID", + "name": "user_id", + "in": "path", + "required": true + }, + { + "type": "integer", + "default": 1, + "description": "页码", + "name": "page", + "in": "query", + "required": true + }, + { + "type": "integer", + "default": 20, + "description": "每页数量,最多100", + "name": "page_size", + "in": "query", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/admin.listInvitesResponse" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/code.Failure" + } + } + } + } + }, + "/api/admin/users/{user_id}/item_cards": { + "post": { + "description": "管理员给指定用户分配道具卡,可指定数量", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "管理端.运营管理" + ], + "summary": "给用户分配道具卡", + "parameters": [ + { + "type": "integer", + "description": "用户ID", + "name": "user_id", + "in": "path", + "required": true + }, + { + "description": "分配道具卡请求参数", + "name": "RequestBody", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/admin.assignItemCardRequest" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/admin.simpleMessageResponse" + } + }, + "400": { + "description": "参数错误", + "schema": { + "$ref": "#/definitions/code.Failure" + } + }, + "401": { + "description": "未授权", + "schema": { + "$ref": "#/definitions/code.Failure" + } + }, + "403": { + "description": "无权限,仅超管可操作", + "schema": { + "$ref": "#/definitions/code.Failure" + } + }, + "500": { + "description": "服务器内部错误", + "schema": { + "$ref": "#/definitions/code.Failure" + } + } + } + } + }, + "/api/admin/users/{user_id}/orders": { + "get": { + "security": [ + { + "LoginVerifyToken": [] + } + ], + "description": "查看指定用户的订单记录", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "管理端.用户" + ], + "summary": "查看用户订单列表", + "parameters": [ + { + "type": "integer", + "description": "用户ID", + "name": "user_id", + "in": "path", + "required": true + }, + { + "type": "integer", + "default": 1, + "description": "页码", + "name": "page", + "in": "query", + "required": true + }, + { + "type": "integer", + "default": 20, + "description": "每页数量,最多100", + "name": "page_size", + "in": "query", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/admin.listOrdersResponse" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/code.Failure" + } + } + } + } + }, + "/api/admin/users/{user_id}/points": { + "get": { + "security": [ + { + "LoginVerifyToken": [] + } + ], + "description": "查看指定用户的积分流水记录", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "管理端.用户" + ], + "summary": "查看用户积分记录", + "parameters": [ + { + "type": "integer", + "description": "用户ID", + "name": "user_id", + "in": "path", + "required": true + }, + { + "type": "integer", + "default": 1, + "description": "页码", + "name": "page", + "in": "query", + "required": true + }, + { + "type": "integer", + "default": 20, + "description": "每页数量,最多100", + "name": "page_size", + "in": "query", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/admin.listPointsResponse" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/code.Failure" + } + } + } + } + }, + "/api/admin/users/{user_id}/points/add": { + "post": { + "security": [ + { + "LoginVerifyToken": [] + } + ], + "description": "管理端为指定用户发放积分,支持设置有效期", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "管理端.用户" + ], + "summary": "给用户添加积分", + "parameters": [ + { + "type": "integer", + "description": "用户ID", + "name": "user_id", + "in": "path", + "required": true + }, + { + "description": "请求参数", + "name": "RequestBody", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/admin.addPointsRequest" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/admin.addPointsResponse" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/code.Failure" + } + } + } + } + }, + "/api/admin/users/{user_id}/points/balance": { + "get": { + "security": [ + { + "LoginVerifyToken": [] + } + ], + "description": "查看指定用户当前积分余额(过滤过期)", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "管理端.用户" + ], + "summary": "查看用户积分余额", + "parameters": [ + { + "type": "integer", + "description": "用户ID", + "name": "user_id", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/admin.pointsBalanceResponse" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/code.Failure" + } + } + } + } + }, + "/api/admin/users/{user_id}/rewards/grant": { + "post": { + "description": "管理员给用户发放奖励,支持实物和虚拟奖品,可选择关联活动和奖励配置", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "管理端.用户" + ], + "summary": "给用户发放奖励", + "parameters": [ + { + "type": "integer", + "description": "用户ID", + "name": "user_id", + "in": "path", + "required": true + }, + { + "description": "请求参数", + "name": "RequestBody", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/admin.GrantRewardRequest" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/admin.GrantRewardResponse" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/code.Failure" + } + }, + "401": { + "description": "Unauthorized", + "schema": { + "$ref": "#/definitions/code.Failure" + } + }, + "403": { + "description": "Forbidden", + "schema": { + "$ref": "#/definitions/code.Failure" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/code.Failure" + } + } + } + } + }, "/api/admin/{id}": { "put": { "security": [ @@ -1211,9 +2620,9 @@ const docTemplate = `{ } } }, - "/api/app/messages": { + "/api/app/activities": { "get": { - "description": "获取消息日志", + "description": "获取活动列表,支持分类、Boss、状态过滤与分页", "consumes": [ "application/json" ], @@ -1221,28 +2630,38 @@ const docTemplate = `{ "application/json" ], "tags": [ - "用户端" + "APP端.活动" ], - "summary": "获取消息日志", + "summary": "活动列表", "parameters": [ { "type": "string", - "description": "小程序ID", - "name": "app_id", - "in": "query", - "required": true + "description": "活动名称(模糊)", + "name": "name", + "in": "query" }, { - "type": "string", - "description": "用户ID", - "name": "user_id", - "in": "query", - "required": true + "type": "integer", + "description": "活动分类ID", + "name": "category_id", + "in": "query" + }, + { + "type": "integer", + "description": "是否Boss(0/1)", + "name": "is_boss", + "in": "query" + }, + { + "type": "integer", + "description": "状态(1进行中 2下线)", + "name": "status", + "in": "query" }, { "type": "integer", "default": 1, - "description": "当前页码", + "description": "页码", "name": "page", "in": "query", "required": true @@ -1250,7 +2669,7 @@ const docTemplate = `{ { "type": "integer", "default": 20, - "description": "每页返回的数据量,最多 100 条", + "description": "每页数量,最多100", "name": "page_size", "in": "query", "required": true @@ -1260,7 +2679,7 @@ const docTemplate = `{ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/message.appMessagePageListResponse" + "$ref": "#/definitions/app.listActivitiesResponse" } }, "400": { @@ -1272,9 +2691,9 @@ const docTemplate = `{ } } }, - "/api/app/send_message": { - "post": { - "description": "用户发送消息", + "/api/app/activities/{activity_id}": { + "get": { + "description": "获取指定活动的详细信息", "consumes": [ "application/json" ], @@ -1282,9 +2701,488 @@ const docTemplate = `{ "application/json" ], "tags": [ - "用户端" + "APP端.活动" ], - "summary": "用户发送消息", + "summary": "活动详情", + "parameters": [ + { + "type": "integer", + "description": "活动ID", + "name": "activity_id", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/model.Activities" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/code.Failure" + } + } + } + } + }, + "/api/app/activities/{activity_id}/issues": { + "get": { + "description": "获取指定活动的期列表,支持分页", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "APP端.活动" + ], + "summary": "活动期列表", + "parameters": [ + { + "type": "integer", + "description": "活动ID", + "name": "activity_id", + "in": "path", + "required": true + }, + { + "type": "integer", + "default": 1, + "description": "页码", + "name": "page", + "in": "query", + "required": true + }, + { + "type": "integer", + "default": 20, + "description": "每页数量,最多100", + "name": "page_size", + "in": "query", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/app.listIssuesResponse" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/code.Failure" + } + } + } + } + }, + "/api/app/activities/{activity_id}/issues/{issue_id}/draw_logs": { + "get": { + "description": "查看指定活动期数的抽奖记录,支持分页", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "APP端.活动" + ], + "summary": "抽奖记录列表", + "parameters": [ + { + "type": "integer", + "description": "活动ID", + "name": "activity_id", + "in": "path", + "required": true + }, + { + "type": "integer", + "description": "期ID", + "name": "issue_id", + "in": "path", + "required": true + }, + { + "type": "integer", + "default": 1, + "description": "页码", + "name": "page", + "in": "query", + "required": true + }, + { + "type": "integer", + "default": 20, + "description": "每页数量,最多100", + "name": "page_size", + "in": "query", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/app.listDrawLogsResponse" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/code.Failure" + } + } + } + } + }, + "/api/app/activities/{activity_id}/issues/{issue_id}/rewards": { + "get": { + "description": "获取指定期的奖励配置列表", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "APP端.活动" + ], + "summary": "奖励配置列表", + "parameters": [ + { + "type": "integer", + "description": "活动ID", + "name": "activity_id", + "in": "path", + "required": true + }, + { + "type": "integer", + "description": "期ID", + "name": "issue_id", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/app.listRewardsResponse" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/code.Failure" + } + } + } + } + }, + "/api/app/banners": { + "get": { + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "APP端.运营" + ], + "summary": "APP端轮播图列表", + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/app.listAppBannersResponse" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/code.Failure" + } + } + } + } + }, + "/api/app/guilds": { + "get": { + "description": "获取工会列表,支持公开与状态过滤以及分页", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "APP端.工会" + ], + "summary": "浏览工会列表", + "parameters": [ + { + "type": "string", + "description": "工会名称(模糊)", + "name": "name", + "in": "query" + }, + { + "type": "integer", + "description": "是否公开(1公开 2私有)", + "name": "is_open", + "in": "query" + }, + { + "type": "integer", + "description": "状态(1正常 2解散)", + "name": "status", + "in": "query" + }, + { + "type": "integer", + "description": "加入方式(1审核 2自动 3消费流水)", + "name": "join_mode", + "in": "query" + }, + { + "type": "integer", + "default": 1, + "description": "页码", + "name": "page", + "in": "query", + "required": true + }, + { + "type": "integer", + "default": 20, + "description": "每页数量,最多100", + "name": "page_size", + "in": "query", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/app.listGuildsResponse" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/code.Failure" + } + } + } + } + }, + "/api/app/guilds/{guild_id}": { + "get": { + "description": "查看指定工会详情", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "APP端.工会" + ], + "summary": "查看工会详情", + "parameters": [ + { + "type": "integer", + "description": "工会ID", + "name": "guild_id", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/model.Guild" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/code.Failure" + } + } + } + } + }, + "/api/app/guilds/{guild_id}/members": { + "get": { + "description": "查看指定工会的成员列表", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "APP端.工会" + ], + "summary": "查看工会成员", + "parameters": [ + { + "type": "integer", + "description": "工会ID", + "name": "guild_id", + "in": "path", + "required": true + }, + { + "type": "integer", + "default": 1, + "description": "页码", + "name": "page", + "in": "query", + "required": true + }, + { + "type": "integer", + "default": 20, + "description": "每页数量,最多100", + "name": "page_size", + "in": "query", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/app.listMembersResponse" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/code.Failure" + } + } + } + }, + "post": { + "description": "用户加入指定工会", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "APP端.工会" + ], + "summary": "加入工会", + "parameters": [ + { + "type": "integer", + "description": "工会ID", + "name": "guild_id", + "in": "path", + "required": true + }, + { + "description": "请求参数", + "name": "RequestBody", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/app.joinGuildRequest" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/app.simpleMessageResponse" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/code.Failure" + } + } + } + } + }, + "/api/app/guilds/{guild_id}/members/{user_id}": { + "delete": { + "description": "用户离开指定工会", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "APP端.工会" + ], + "summary": "离开工会", + "parameters": [ + { + "type": "integer", + "description": "工会ID", + "name": "guild_id", + "in": "path", + "required": true + }, + { + "type": "integer", + "description": "用户ID", + "name": "user_id", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/app.simpleMessageResponse" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/code.Failure" + } + } + } + } + }, + "/api/app/users/phone/login": { + "post": { + "description": "使用手机号登录,沿用 code 字段承载手机号或手机号授权码", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "APP端.用户" + ], + "summary": "手机号登录", "parameters": [ { "description": "请求参数", @@ -1292,7 +3190,7 @@ const docTemplate = `{ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/message.userSendMessageRequest" + "$ref": "#/definitions/app.phoneLoginRequest" } } ], @@ -1300,7 +3198,7 @@ const docTemplate = `{ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/message.userSendMessageResponse" + "$ref": "#/definitions/app.phoneLoginResponse" } }, "400": { @@ -1312,9 +3210,9 @@ const docTemplate = `{ } } }, - "/api/app/user/create": { + "/api/app/users/weixin/login": { "post": { - "description": "新增小程序用户", + "description": "微信静默登录(需传递 code;可选 invite_code)", "consumes": [ "application/json" ], @@ -1322,9 +3220,9 @@ const docTemplate = `{ "application/json" ], "tags": [ - "用户端" + "APP端.用户" ], - "summary": "新增小程序用户", + "summary": "微信登录", "parameters": [ { "description": "请求参数", @@ -1332,7 +3230,7 @@ const docTemplate = `{ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/app.createAppUserRequest" + "$ref": "#/definitions/app.weixinLoginRequest" } } ], @@ -1340,7 +3238,7 @@ const docTemplate = `{ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/app.createAppUserResponse" + "$ref": "#/definitions/app.weixinLoginResponse" } }, "400": { @@ -1352,9 +3250,9 @@ const docTemplate = `{ } } }, - "/api/wechat/miniprogram/login": { - "post": { - "description": "通过AppID和code获取用户的openid,系统自动生成用户名和头像", + "/api/app/users/{user_id}": { + "put": { + "description": "修改用户昵称与头像", "consumes": [ "application/json" ], @@ -1362,17 +3260,24 @@ const docTemplate = `{ "application/json" ], "tags": [ - "微信" + "APP端.用户" ], - "summary": "小程序登录", + "summary": "修改用户信息", "parameters": [ + { + "type": "integer", + "description": "用户ID", + "name": "user_id", + "in": "path", + "required": true + }, { "description": "请求参数", - "name": "request", + "name": "RequestBody", "in": "body", "required": true, "schema": { - "$ref": "#/definitions/wechat.miniprogramLoginRequest" + "$ref": "#/definitions/app.modifyUserRequest" } } ], @@ -1380,7 +3285,7 @@ const docTemplate = `{ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/wechat.miniprogramLoginResponse" + "$ref": "#/definitions/app.modifyUserResponse" } }, "400": { @@ -1388,19 +3293,13 @@ const docTemplate = `{ "schema": { "$ref": "#/definitions/code.Failure" } - }, - "500": { - "description": "Internal Server Error", - "schema": { - "$ref": "#/definitions/code.Failure" - } } } } }, - "/api/wechat/qrcode": { - "post": { - "description": "根据 AppID、AppSecret 和页面路径生成微信小程序二维码", + "/api/app/users/{user_id}/coupons": { + "get": { + "description": "查看用户持有的优惠券列表", "consumes": [ "application/json" ], @@ -1408,25 +3307,39 @@ const docTemplate = `{ "application/json" ], "tags": [ - "微信" + "APP端.用户" ], - "summary": "生成微信小程序二维码", + "summary": "查看用户优惠券", "parameters": [ { - "description": "请求参数", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/wechat.generateQRCodeRequest" - } + "type": "integer", + "description": "用户ID", + "name": "user_id", + "in": "path", + "required": true + }, + { + "type": "integer", + "default": 1, + "description": "页码", + "name": "page", + "in": "query", + "required": true + }, + { + "type": "integer", + "default": 20, + "description": "每页数量,最多100", + "name": "page_size", + "in": "query", + "required": true } ], "responses": { "200": { "description": "OK", "schema": { - "$ref": "#/definitions/wechat.generateQRCodeResponse" + "$ref": "#/definitions/app.listCouponsResponse" } }, "400": { @@ -1434,19 +3347,13 @@ const docTemplate = `{ "schema": { "$ref": "#/definitions/code.Failure" } - }, - "500": { - "description": "Internal Server Error", - "schema": { - "$ref": "#/definitions/code.Failure" - } } } } }, - "/api/wechat/subscribe": { - "post": { - "description": "根据模板ID发送订阅消息", + "/api/app/users/{user_id}/invites": { + "get": { + "description": "查看被该用户邀请的用户列表", "consumes": [ "application/json" ], @@ -1454,25 +3361,39 @@ const docTemplate = `{ "application/json" ], "tags": [ - "微信" + "APP端.用户" ], - "summary": "发送订阅消息", + "summary": "查看用户邀请记录", "parameters": [ { - "description": "请求参数", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/wechat.sendSubscribeMessageRequest" - } + "type": "integer", + "description": "用户ID", + "name": "user_id", + "in": "path", + "required": true + }, + { + "type": "integer", + "default": 1, + "description": "页码", + "name": "page", + "in": "query", + "required": true + }, + { + "type": "integer", + "default": 20, + "description": "每页数量,最多100", + "name": "page_size", + "in": "query", + "required": true } ], "responses": { "200": { "description": "OK", "schema": { - "$ref": "#/definitions/wechat.sendSubscribeMessageResponse" + "$ref": "#/definitions/app.listInvitesResponse" } }, "400": { @@ -1480,25 +3401,13 @@ const docTemplate = `{ "schema": { "$ref": "#/definitions/code.Failure" } - }, - "404": { - "description": "Not Found", - "schema": { - "$ref": "#/definitions/code.Failure" - } - }, - "500": { - "description": "Internal Server Error", - "schema": { - "$ref": "#/definitions/code.Failure" - } } } } }, - "/api/wechat/template": { - "post": { - "description": "根据 AppID 获取微信小程序的模板ID", + "/api/app/users/{user_id}/item_cards": { + "get": { + "description": "获取指定用户的道具卡列表,支持分页", "consumes": [ "application/json" ], @@ -1506,25 +3415,163 @@ const docTemplate = `{ "application/json" ], "tags": [ - "微信" + "APP端.用户" ], - "summary": "获取微信小程序模板ID", + "summary": "获取用户道具卡列表", "parameters": [ { - "description": "请求参数", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/wechat.templateRequest" - } + "type": "integer", + "description": "用户ID", + "name": "user_id", + "in": "path", + "required": true + }, + { + "type": "integer", + "description": "页码,默认1", + "name": "page", + "in": "query" + }, + { + "type": "integer", + "description": "每页条数,默认10", + "name": "page_size", + "in": "query" } ], "responses": { "200": { "description": "OK", "schema": { - "$ref": "#/definitions/wechat.templateResponse" + "$ref": "#/definitions/app.listUserItemCardsResponse" + } + }, + "400": { + "description": "参数错误", + "schema": { + "$ref": "#/definitions/code.Failure" + } + }, + "401": { + "description": "未授权", + "schema": { + "$ref": "#/definitions/code.Failure" + } + }, + "500": { + "description": "服务器内部错误", + "schema": { + "$ref": "#/definitions/code.Failure" + } + } + } + } + }, + "/api/app/users/{user_id}/item_cards/uses": { + "get": { + "description": "获取指定用户的道具卡使用记录,支持分页", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "APP端.用户" + ], + "summary": "获取用户道具卡使用记录", + "parameters": [ + { + "type": "integer", + "description": "用户ID", + "name": "user_id", + "in": "path", + "required": true + }, + { + "type": "integer", + "description": "页码,默认1", + "name": "page", + "in": "query" + }, + { + "type": "integer", + "description": "每页条数,默认10", + "name": "page_size", + "in": "query" + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/app.listUserItemCardUsesResponse" + } + }, + "400": { + "description": "参数错误", + "schema": { + "$ref": "#/definitions/code.Failure" + } + }, + "401": { + "description": "未授权", + "schema": { + "$ref": "#/definitions/code.Failure" + } + }, + "500": { + "description": "服务器内部错误", + "schema": { + "$ref": "#/definitions/code.Failure" + } + } + } + } + }, + "/api/app/users/{user_id}/orders": { + "get": { + "description": "查看用户抽奖来源订单记录", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "APP端.用户" + ], + "summary": "查看用户订单记录", + "parameters": [ + { + "type": "integer", + "description": "用户ID", + "name": "user_id", + "in": "path", + "required": true + }, + { + "type": "integer", + "default": 1, + "description": "页码", + "name": "page", + "in": "query", + "required": true + }, + { + "type": "integer", + "default": 20, + "description": "每页数量,最多100", + "name": "page_size", + "in": "query", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/app.listOrdersResponse" } }, "400": { @@ -1532,24 +3579,551 @@ const docTemplate = `{ "schema": { "$ref": "#/definitions/code.Failure" } + } + } + } + }, + "/api/app/users/{user_id}/phone/bind": { + "post": { + "description": "使用微信手机号 code 换取手机号并绑定到指定用户", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "APP端.用户" + ], + "summary": "绑定手机号", + "parameters": [ + { + "type": "integer", + "description": "用户ID", + "name": "user_id", + "in": "path", + "required": true }, - "404": { - "description": "Not Found", + { + "description": "请求参数", + "name": "RequestBody", + "in": "body", + "required": true, "schema": { - "$ref": "#/definitions/code.Failure" + "$ref": "#/definitions/app.bindPhoneRequest" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/app.bindPhoneResponse" } }, - "500": { - "description": "Internal Server Error", + "400": { + "description": "Bad Request", "schema": { "$ref": "#/definitions/code.Failure" } } } } + }, + "/api/app/users/{user_id}/points": { + "get": { + "description": "查看用户积分流水记录", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "APP端.用户" + ], + "summary": "查看用户积分记录", + "parameters": [ + { + "type": "integer", + "description": "用户ID", + "name": "user_id", + "in": "path", + "required": true + }, + { + "type": "integer", + "default": 1, + "description": "页码", + "name": "page", + "in": "query", + "required": true + }, + { + "type": "integer", + "default": 20, + "description": "每页数量,最多100", + "name": "page_size", + "in": "query", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/app.listPointsResponse" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/code.Failure" + } + } + } + } + }, + "/api/app/users/{user_id}/points/balance": { + "get": { + "description": "查看用户积分余额(过滤过期积分)", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "APP端.用户" + ], + "summary": "查看用户积分余额", + "parameters": [ + { + "type": "integer", + "description": "用户ID", + "name": "user_id", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/app.pointsBalanceResponse" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/code.Failure" + } + } + } + } + }, + "/api/role/list": { + "get": { + "security": [ + { + "LoginVerifyToken": [] + } + ], + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "管理端.系统" + ], + "summary": "角色列表", + "parameters": [ + { + "type": "integer", + "default": 1, + "description": "页码", + "name": "current", + "in": "query", + "required": true + }, + { + "type": "integer", + "default": 20, + "description": "每页数量", + "name": "size", + "in": "query", + "required": true + }, + { + "type": "string", + "description": "角色名称", + "name": "roleName", + "in": "query" + }, + { + "type": "string", + "description": "角色编码", + "name": "roleCode", + "in": "query" + }, + { + "type": "boolean", + "description": "是否启用", + "name": "enabled", + "in": "query" + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/admin.roleListResponse" + } + } + } + } + }, + "/api/user/list": { + "get": { + "security": [ + { + "LoginVerifyToken": [] + } + ], + "description": "返回系统用户分页数据", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "管理端.系统" + ], + "summary": "系统用户列表", + "parameters": [ + { + "type": "integer", + "default": 1, + "description": "页码", + "name": "current", + "in": "query", + "required": true + }, + { + "type": "integer", + "default": 20, + "description": "每页数量", + "name": "size", + "in": "query", + "required": true + }, + { + "type": "string", + "description": "用户名", + "name": "userName", + "in": "query" + }, + { + "type": "string", + "description": "邮箱", + "name": "userEmail", + "in": "query" + }, + { + "type": "string", + "description": "手机号", + "name": "userPhone", + "in": "query" + }, + { + "type": "string", + "description": "状态", + "name": "status", + "in": "query" + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/admin.userListResponse" + } + } + } + } + }, + "/api/v3/system/menus/simple": { + "get": { + "responses": {} + } } }, "definitions": { + "admin.GrantRewardRequest": { + "type": "object", + "required": [ + "product_id" + ], + "properties": { + "activity_id": { + "description": "活动ID(可选)", + "type": "integer" + }, + "address_id": { + "description": "收货地址ID(可选,实物商品需要)", + "type": "integer" + }, + "product_id": { + "description": "商品ID", + "type": "integer" + }, + "quantity": { + "description": "发放数量", + "type": "integer", + "minimum": 1 + }, + "remark": { + "description": "备注", + "type": "string" + }, + "reward_id": { + "description": "奖励配置ID(可选)", + "type": "integer" + } + } + }, + "admin.GrantRewardResponse": { + "type": "object", + "properties": { + "inventory_ids": { + "type": "array", + "items": { + "type": "integer" + } + }, + "message": { + "type": "string" + }, + "order_id": { + "type": "integer" + }, + "success": { + "type": "boolean" + } + } + }, + "admin.activitysvcIssueData": { + "type": "object", + "properties": { + "id": { + "type": "integer" + }, + "issue_number": { + "type": "string" + }, + "sort": { + "type": "integer" + }, + "status": { + "type": "integer" + } + } + }, + "admin.addCouponRequest": { + "type": "object", + "required": [ + "coupon_id" + ], + "properties": { + "coupon_id": { + "type": "integer" + } + } + }, + "admin.addCouponResponse": { + "type": "object", + "properties": { + "success": { + "type": "boolean" + } + } + }, + "admin.addPointsRequest": { + "type": "object", + "required": [ + "points" + ], + "properties": { + "kind": { + "type": "string" + }, + "points": { + "type": "integer" + }, + "remark": { + "type": "string" + }, + "valid_days": { + "type": "integer" + } + } + }, + "admin.addPointsResponse": { + "type": "object", + "properties": { + "success": { + "type": "boolean" + } + } + }, + "admin.adminUserCouponItem": { + "type": "object", + "properties": { + "coupon_id": { + "type": "integer" + }, + "discount_type": { + "type": "integer" + }, + "discount_value": { + "type": "integer" + }, + "id": { + "type": "integer" + }, + "min_spend": { + "type": "integer" + }, + "name": { + "type": "string" + }, + "scope_type": { + "type": "integer" + }, + "status": { + "type": "integer" + }, + "used_at": { + "type": "string" + }, + "used_order_id": { + "type": "integer" + }, + "valid_end": { + "type": "string" + }, + "valid_start": { + "type": "string" + } + } + }, + "admin.adminUserItem": { + "type": "object", + "properties": { + "avatar": { + "type": "string" + }, + "created_at": { + "type": "string" + }, + "id": { + "type": "integer" + }, + "invite_code": { + "type": "string" + }, + "inviter_id": { + "type": "integer" + }, + "nickname": { + "type": "string" + } + } + }, + "admin.assignItemCardRequest": { + "type": "object", + "required": [ + "card_id" + ], + "properties": { + "card_id": { + "type": "integer" + }, + "quantity": { + "type": "integer" + } + } + }, + "admin.bannerItem": { + "type": "object", + "properties": { + "id": { + "type": "integer" + }, + "image_url": { + "type": "string" + }, + "link_url": { + "type": "string" + }, + "sort": { + "type": "integer" + }, + "status": { + "type": "integer" + }, + "title": { + "type": "string" + } + } + }, + "admin.categoryItem": { + "type": "object", + "properties": { + "id": { + "type": "integer" + }, + "name": { + "type": "string" + } + } + }, + "admin.createActivityRequest": { + "type": "object", + "required": [ + "activity_category_id", + "name" + ], + "properties": { + "activity_category_id": { + "type": "integer" + }, + "banner": { + "type": "string" + }, + "end_time": { + "type": "string" + }, + "is_boss": { + "type": "integer" + }, + "name": { + "type": "string" + }, + "price_draw": { + "type": "integer" + }, + "start_time": { + "type": "string" + }, + "status": { + "type": "integer" + } + } + }, "admin.createAdminRequest": { "type": "object", "required": [ @@ -1589,6 +4163,249 @@ const docTemplate = `{ } } }, + "admin.createBannerRequest": { + "type": "object", + "required": [ + "image_url", + "title" + ], + "properties": { + "image_url": { + "type": "string" + }, + "link_url": { + "type": "string" + }, + "sort": { + "type": "integer" + }, + "status": { + "type": "integer" + }, + "title": { + "type": "string" + } + } + }, + "admin.createBannerResponse": { + "type": "object", + "properties": { + "id": { + "type": "integer" + }, + "message": { + "type": "string" + } + } + }, + "admin.createGuildRequest": { + "type": "object", + "required": [ + "name", + "owner_id" + ], + "properties": { + "avatar_url": { + "type": "string" + }, + "consume_limit": { + "type": "integer" + }, + "description": { + "type": "string" + }, + "is_open": { + "type": "integer" + }, + "join_mode": { + "type": "integer" + }, + "name": { + "type": "string" + }, + "owner_id": { + "type": "integer" + } + } + }, + "admin.createGuildResponse": { + "type": "object", + "properties": { + "message": { + "type": "string" + } + } + }, + "admin.createIssueRequest": { + "type": "object", + "required": [ + "issue_number" + ], + "properties": { + "issue_number": { + "type": "string" + }, + "sort": { + "type": "integer" + }, + "status": { + "type": "integer" + } + } + }, + "admin.createItemCardRequest": { + "type": "object", + "required": [ + "card_type", + "effect_type", + "name", + "price", + "scope_type" + ], + "properties": { + "activity_category_id": { + "type": "integer" + }, + "activity_id": { + "type": "integer" + }, + "boost_rate_x1000": { + "type": "integer" + }, + "card_type": { + "type": "integer" + }, + "effect_type": { + "type": "integer" + }, + "issue_id": { + "type": "integer" + }, + "max_effect_value_x1000": { + "type": "integer" + }, + "name": { + "type": "string" + }, + "price": { + "type": "integer" + }, + "remark": { + "type": "string" + }, + "reward_multiplier_x1000": { + "type": "integer" + }, + "scope_type": { + "type": "integer" + }, + "stacking_strategy": { + "type": "integer" + }, + "status": { + "type": "integer" + }, + "valid_end_unix": { + "type": "integer" + }, + "valid_start_unix": { + "type": "integer" + } + } + }, + "admin.createItemCardResponse": { + "type": "object", + "properties": { + "id": { + "type": "integer" + }, + "message": { + "type": "string" + } + } + }, + "admin.createProductCategoryRequest": { + "type": "object", + "required": [ + "name" + ], + "properties": { + "name": { + "type": "string" + }, + "parent_id": { + "type": "integer" + }, + "status": { + "type": "integer" + } + } + }, + "admin.createProductCategoryResponse": { + "type": "object", + "properties": { + "id": { + "type": "integer" + }, + "message": { + "type": "string" + } + } + }, + "admin.createProductRequest": { + "type": "object", + "required": [ + "category_id", + "name", + "price", + "stock" + ], + "properties": { + "category_id": { + "type": "integer" + }, + "images_json": { + "type": "string" + }, + "name": { + "type": "string" + }, + "price": { + "type": "integer" + }, + "status": { + "type": "integer" + }, + "stock": { + "type": "integer" + } + } + }, + "admin.createProductResponse": { + "type": "object", + "properties": { + "id": { + "type": "integer" + }, + "message": { + "type": "string" + } + } + }, + "admin.createRewardsRequest": { + "type": "object", + "required": [ + "rewards" + ], + "properties": { + "rewards": { + "type": "array", + "items": { + "$ref": "#/definitions/admin.rewardItem" + } + } + } + }, "admin.deleteAdminRequest": { "type": "object", "required": [ @@ -1610,6 +4427,146 @@ const docTemplate = `{ } } }, + "admin.deleteGuildResponse": { + "type": "object", + "properties": { + "message": { + "type": "string" + } + } + }, + "admin.itemCardListItem": { + "type": "object", + "properties": { + "activity_category_id": { + "description": "指定活动分类ID(可空)", + "type": "integer" + }, + "activity_id": { + "description": "指定活动ID(可空)", + "type": "integer" + }, + "boost_rate_x1000": { + "description": "概率提升(千分比,+20%=200)", + "type": "integer" + }, + "card_type": { + "description": "卡类型:1双倍奖励 2概率提升 等", + "type": "integer" + }, + "created_at": { + "description": "创建时间", + "type": "string" + }, + "effect_type": { + "description": "效果类型:1奖励倍数 2概率提升 等", + "type": "integer" + }, + "id": { + "description": "主键ID", + "type": "integer" + }, + "issue_id": { + "description": "指定期ID(可空)", + "type": "integer" + }, + "max_effect_value_x1000": { + "description": "效果上限(千分比)", + "type": "integer" + }, + "name": { + "description": "卡名称", + "type": "string" + }, + "price": { + "description": "售卖价格(分)", + "type": "integer" + }, + "remark": { + "description": "备注", + "type": "string" + }, + "reward_multiplier_x1000": { + "description": "奖励倍数(千分比,×2=2000)", + "type": "integer" + }, + "scope_type": { + "description": "适用范围:1全局 2活动分类 3活动 4期", + "type": "integer" + }, + "stacking_strategy": { + "description": "叠加策略:1禁止 2同类叠加-上限 3取最大值 4乘法叠加", + "type": "integer" + }, + "status": { + "description": "状态:1启用 2停用", + "type": "integer" + }, + "updated_at": { + "description": "更新时间", + "type": "string" + }, + "valid_end": { + "description": "有效期结束", + "type": "string" + }, + "valid_start": { + "description": "有效期开始", + "type": "string" + } + } + }, + "admin.listBannersResponse": { + "type": "object", + "properties": { + "list": { + "type": "array", + "items": { + "$ref": "#/definitions/admin.bannerItem" + } + }, + "page": { + "type": "integer" + }, + "page_size": { + "type": "integer" + }, + "total": { + "type": "integer" + } + } + }, + "admin.listCategoriesResponse": { + "type": "object", + "properties": { + "list": { + "type": "array", + "items": { + "$ref": "#/definitions/admin.categoryItem" + } + } + } + }, + "admin.listCouponsResponse": { + "type": "object", + "properties": { + "list": { + "type": "array", + "items": { + "$ref": "#/definitions/admin.adminUserCouponItem" + } + }, + "page": { + "type": "integer" + }, + "page_size": { + "type": "integer" + }, + "total": { + "type": "integer" + } + } + }, "admin.listData": { "type": "object", "properties": { @@ -1643,6 +4600,186 @@ const docTemplate = `{ } } }, + "admin.listGuildMembersResponse": { + "type": "object", + "properties": { + "list": { + "type": "array", + "items": { + "$ref": "#/definitions/admin.memberItem" + } + }, + "page": { + "type": "integer" + }, + "page_size": { + "type": "integer" + }, + "total": { + "type": "integer" + } + } + }, + "admin.listInventoryResponse": { + "type": "object", + "properties": { + "list": { + "type": "array", + "items": { + "$ref": "#/definitions/user.InventoryWithProduct" + } + }, + "page": { + "type": "integer" + }, + "page_size": { + "type": "integer" + }, + "total": { + "type": "integer" + } + } + }, + "admin.listInvitesResponse": { + "type": "object", + "properties": { + "list": { + "type": "array", + "items": { + "$ref": "#/definitions/admin.adminUserItem" + } + }, + "page": { + "type": "integer" + }, + "page_size": { + "type": "integer" + }, + "total": { + "type": "integer" + } + } + }, + "admin.listIssuesResponse": { + "type": "object", + "properties": { + "list": { + "type": "array", + "items": { + "$ref": "#/definitions/admin.activitysvcIssueData" + } + }, + "page": { + "type": "integer" + }, + "page_size": { + "type": "integer" + }, + "total": { + "type": "integer" + } + } + }, + "admin.listItemCardsResponse": { + "type": "object", + "properties": { + "list": { + "type": "array", + "items": { + "$ref": "#/definitions/admin.itemCardListItem" + } + }, + "page": { + "type": "integer" + }, + "page_size": { + "type": "integer" + }, + "total": { + "type": "integer" + } + } + }, + "admin.listOrdersResponse": { + "type": "object", + "properties": { + "list": { + "type": "array", + "items": { + "$ref": "#/definitions/user.OrderWithItems" + } + }, + "page": { + "type": "integer" + }, + "page_size": { + "type": "integer" + }, + "total": { + "type": "integer" + } + } + }, + "admin.listPointsResponse": { + "type": "object", + "properties": { + "list": { + "type": "array", + "items": { + "$ref": "#/definitions/model.UserPointsLedger" + } + }, + "page": { + "type": "integer" + }, + "page_size": { + "type": "integer" + }, + "total": { + "type": "integer" + } + } + }, + "admin.listProductCategoriesResponse": { + "type": "object", + "properties": { + "list": { + "type": "array", + "items": { + "$ref": "#/definitions/admin.productCategoryListItem" + } + }, + "page": { + "type": "integer" + }, + "page_size": { + "type": "integer" + }, + "total": { + "type": "integer" + } + } + }, + "admin.listProductsResponse": { + "type": "object", + "properties": { + "list": { + "type": "array", + "items": { + "$ref": "#/definitions/admin.productItem" + } + }, + "page": { + "type": "integer" + }, + "page_size": { + "type": "integer" + }, + "total": { + "type": "integer" + } + } + }, "admin.listResponse": { "type": "object", "properties": { @@ -1666,6 +4803,37 @@ const docTemplate = `{ } } }, + "admin.listRewardsResponse": { + "type": "object", + "properties": { + "list": { + "type": "array", + "items": { + "$ref": "#/definitions/admin.rewardItem" + } + } + } + }, + "admin.listUsersResponse": { + "type": "object", + "properties": { + "list": { + "type": "array", + "items": { + "$ref": "#/definitions/admin.adminUserItem" + } + }, + "page": { + "type": "integer" + }, + "page_size": { + "type": "integer" + }, + "total": { + "type": "integer" + } + } + }, "admin.loginRequest": { "type": "object", "required": [ @@ -1696,6 +4864,52 @@ const docTemplate = `{ } } }, + "admin.memberItem": { + "type": "object", + "properties": { + "id": { + "type": "integer" + }, + "role": { + "type": "string" + }, + "start_time": { + "type": "string" + }, + "user_id": { + "type": "integer" + } + } + }, + "admin.modifyActivityRequest": { + "type": "object", + "properties": { + "activity_category_id": { + "type": "integer" + }, + "banner": { + "type": "string" + }, + "end_time": { + "type": "string" + }, + "is_boss": { + "type": "integer" + }, + "name": { + "type": "string" + }, + "price_draw": { + "type": "integer" + }, + "start_time": { + "type": "string" + }, + "status": { + "type": "integer" + } + } + }, "admin.modifyAdminRequest": { "type": "object", "required": [ @@ -1734,458 +4948,990 @@ const docTemplate = `{ } } }, - "admin.relAppRequest": { - "type": "object", - "required": [ - "ids" - ], - "properties": { - "ids": { - "description": "小程序编号(多个用,分割)", - "type": "string" - } - } - }, - "admin.relAppResponse": { + "admin.modifyBannerRequest": { "type": "object", "properties": { - "message": { - "description": "提示信息", - "type": "string" - } - } - }, - "app.adminSendMessageRequest": { - "type": "object", - "required": [ - "app_id", - "content", - "msg_type", - "to_user_id" - ], - "properties": { - "app_id": { - "description": "小程序ID", + "image_url": { "type": "string" }, - "content": { - "description": "内容", + "link_url": { "type": "string" }, - "msg_type": { - "description": "消息类型(1:文本 2:图片)", - "type": "integer" - }, - "to_user_id": { - "description": "接收用户ID", - "type": "string" - } - } - }, - "app.adminSendMessageResponse": { - "type": "object", - "properties": { - "message": { - "description": "提示信息", - "type": "string" - } - } - }, - "app.appMessagePageListResponse": { - "type": "object", - "properties": { - "list": { - "type": "array", - "items": { - "$ref": "#/definitions/app.listMessageData" - } - }, - "page": { - "description": "当前页码", - "type": "integer" - }, - "page_size": { - "description": "每页返回的数据量", - "type": "integer" - }, - "total": { - "description": "符合查询条件的总记录数", - "type": "integer" - } - } - }, - "app.checkAppStatusResponse": { - "type": "object", - "properties": { - "app_id": { - "description": "小程序ID", - "type": "string" - }, - "check_status_text": { - "description": "状态文字描述", - "type": "string" - }, - "code": { - "description": "外部接口返回的状态码", + "sort": { "type": "integer" }, "status": { - "description": "外部接口返回的状态", + "type": "integer" + }, + "title": { "type": "string" } } }, - "app.createAppRequest": { + "admin.modifyGuildRequest": { "type": "object", - "required": [ - "app_id", - "app_secret", - "name" - ], "properties": { - "app_id": { - "description": "小程序ID", + "avatar_url": { "type": "string" }, - "app_secret": { - "description": "小程序密钥", - "type": "string" - }, - "avatar": { - "description": "头像", - "type": "string" + "consume_limit": { + "type": "integer" }, "description": { - "description": "描述", + "type": "string" + }, + "is_open": { + "type": "integer" + }, + "join_mode": { + "type": "integer" + }, + "name": { + "type": "string" + }, + "status": { + "type": "integer" + } + } + }, + "admin.modifyGuildResponse": { + "type": "object", + "properties": { + "message": { + "type": "string" + } + } + }, + "admin.modifyIssueRequest": { + "type": "object", + "properties": { + "issue_number": { + "type": "string" + }, + "sort": { + "type": "integer" + }, + "status": { + "type": "integer" + } + } + }, + "admin.modifyItemCardRequest": { + "type": "object", + "properties": { + "activity_category_id": { + "type": "integer" + }, + "activity_id": { + "type": "integer" + }, + "boost_rate_x1000": { + "type": "integer" + }, + "card_type": { + "type": "integer" + }, + "effect_type": { + "type": "integer" + }, + "issue_id": { + "type": "integer" + }, + "max_effect_value_x1000": { + "type": "integer" + }, + "name": { + "type": "string" + }, + "price": { + "type": "integer" + }, + "remark": { + "type": "string" + }, + "reward_multiplier_x1000": { + "type": "integer" + }, + "scope_type": { + "type": "integer" + }, + "stacking_strategy": { + "type": "integer" + }, + "status": { + "type": "integer" + }, + "valid_end_unix": { + "type": "integer" + }, + "valid_start_unix": { + "type": "integer" + } + } + }, + "admin.modifyProductCategoryRequest": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "parent_id": { + "type": "integer" + }, + "status": { + "type": "integer" + } + } + }, + "admin.modifyProductRequest": { + "type": "object", + "properties": { + "category_id": { + "type": "integer" + }, + "images_json": { "type": "string" }, "name": { - "description": "名称", "type": "string" }, - "template_id": { - "description": "模版ID", - "type": "string" + "price": { + "type": "integer" + }, + "status": { + "type": "integer" + }, + "stock": { + "type": "integer" } } }, - "app.createAppResponse": { + "admin.modifyRewardRequest": { + "type": "object", + "properties": { + "is_boss": { + "type": "integer" + }, + "level": { + "type": "integer" + }, + "name": { + "type": "string" + }, + "original_qty": { + "type": "integer" + }, + "product_id": { + "type": "integer" + }, + "quantity": { + "type": "integer" + }, + "sort": { + "type": "integer" + }, + "weight": { + "type": "integer" + } + } + }, + "admin.pcSimpleMessage": { "type": "object", "properties": { "message": { - "description": "提示信息", "type": "string" } } }, - "app.createAppUserRequest": { + "admin.pointsBalanceResponse": { + "type": "object", + "properties": { + "balance": { + "type": "integer" + } + } + }, + "admin.productCategoryListItem": { + "type": "object", + "properties": { + "id": { + "type": "integer" + }, + "name": { + "type": "string" + }, + "parent_id": { + "type": "integer" + }, + "status": { + "type": "integer" + } + } + }, + "admin.productItem": { + "type": "object", + "properties": { + "category_id": { + "type": "integer" + }, + "id": { + "type": "integer" + }, + "images_json": { + "type": "string" + }, + "name": { + "type": "string" + }, + "price": { + "type": "integer" + }, + "sales": { + "type": "integer" + }, + "status": { + "type": "integer" + }, + "stock": { + "type": "integer" + } + } + }, + "admin.rewardItem": { "type": "object", "required": [ - "app_id", - "user_id", - "user_name" + "level", + "name", + "original_qty", + "quantity", + "weight" ], "properties": { - "app_id": { - "description": "小程序ID", - "type": "string" - }, - "user_avatar": { - "description": "用户头像", - "type": "string" - }, - "user_id": { - "description": "用户ID", - "type": "string" - }, - "user_mobile": { - "description": "用户手机号", - "type": "string" - }, - "user_name": { - "description": "用户昵称", - "type": "string" - } - } - }, - "app.createAppUserResponse": { - "type": "object", - "properties": { - "message": { - "description": "提示信息", - "type": "string" - } - } - }, - "app.deleteAppRequest": { - "type": "object", - "required": [ - "ids" - ], - "properties": { - "ids": { - "description": "小程序编号(多个用,分割)", - "type": "string" - } - } - }, - "app.deleteAppResponse": { - "type": "object", - "properties": { - "message": { - "description": "提示信息", - "type": "string" - } - } - }, - "app.latestMessageByAppIdResponse": { - "type": "object", - "properties": { - "list": { - "type": "array", - "items": { - "$ref": "#/definitions/app.latestMessageData" - } - }, - "page": { - "description": "当前页码", + "id": { "type": "integer" }, - "page_size": { - "description": "每页返回的数据量", + "is_boss": { "type": "integer" }, - "total": { - "description": "符合查询条件的总记录数", + "level": { + "type": "integer" + }, + "name": { + "type": "string" + }, + "original_qty": { + "type": "integer" + }, + "product_id": { + "type": "integer" + }, + "quantity": { + "type": "integer" + }, + "sort": { + "type": "integer" + }, + "weight": { "type": "integer" } } }, - "app.latestMessageData": { + "admin.roleItem": { "type": "object", "properties": { - "content": { - "description": "消息内容", - "type": "string" - }, - "msg_type": { - "description": "消息类型(1:文本 2:图片)", - "type": "integer" - }, - "send_time": { - "description": "发送时间", - "type": "string" - }, - "sender_avatar": { - "description": "发送人头像", - "type": "string" - }, - "sender_id": { - "description": "发送人ID", - "type": "string" - }, - "sender_name": { - "description": "发送人昵称", - "type": "string" - }, - "unread_count": { - "description": "未读消息数量", - "type": "integer" - } - } - }, - "app.listData": { - "type": "object", - "properties": { - "app_id": { - "description": "小程序ID", - "type": "string" - }, - "app_secret": { - "description": "小程序密钥", - "type": "string" - }, - "avatar": { - "description": "小程序头像", - "type": "string" - }, - "check_status_text": { - "description": "状态文字描述", - "type": "string" - }, - "created_at": { - "description": "创建时间", + "createTime": { "type": "string" }, "description": { - "description": "小程序描述", + "type": "string" + }, + "enabled": { + "type": "boolean" + }, + "roleCode": { + "type": "string" + }, + "roleId": { + "type": "integer" + }, + "roleName": { + "type": "string" + } + } + }, + "admin.roleListResponse": { + "type": "object", + "properties": { + "current": { + "type": "integer" + }, + "records": { + "type": "array", + "items": { + "$ref": "#/definitions/admin.roleItem" + } + }, + "size": { + "type": "integer" + }, + "total": { + "type": "integer" + } + } + }, + "admin.simpleMessage": { + "type": "object", + "properties": { + "message": { + "type": "string" + } + } + }, + "admin.simpleMessageResponse": { + "type": "object", + "properties": { + "message": { + "type": "string" + } + } + }, + "admin.userListItem": { + "type": "object", + "properties": { + "avatar": { + "type": "string" + }, + "createBy": { + "type": "string" + }, + "createTime": { "type": "string" }, "id": { - "description": "小程序编号", "type": "integer" }, - "message_total": { - "description": "消息总数", - "type": "integer" - }, - "name": { - "description": "小程序名称", + "nickName": { "type": "string" }, - "template_id": { - "description": "模版ID", + "status": { "type": "string" }, - "updated_at": { - "description": "更新时间", + "updateBy": { "type": "string" + }, + "updateTime": { + "type": "string" + }, + "userEmail": { + "type": "string" + }, + "userGender": { + "type": "string" + }, + "userName": { + "type": "string" + }, + "userPhone": { + "type": "string" + }, + "userRoles": { + "type": "array", + "items": { + "type": "string" + } } } }, - "app.listMessageData": { + "admin.userListResponse": { "type": "object", "properties": { - "content": { - "description": "消息内容", + "current": { + "type": "integer" + }, + "records": { + "type": "array", + "items": { + "$ref": "#/definitions/admin.userListItem" + } + }, + "size": { + "type": "integer" + }, + "total": { + "type": "integer" + } + } + }, + "app.activityItem": { + "type": "object", + "properties": { + "activity_category_id": { + "type": "integer" + }, + "banner": { + "type": "string" + }, + "category_name": { "type": "string" }, "id": { - "description": "消息ID", - "type": "string" - }, - "msg_type": { - "description": "消息类型(1:文本 2:图片)", "type": "integer" }, - "receiver_id": { - "description": "接收人ID", + "is_boss": { + "type": "integer" + }, + "name": { "type": "string" }, - "send_time": { - "description": "发送时间", + "price_draw": { + "type": "integer" + }, + "status": { + "type": "integer" + } + } + }, + "app.appBannerItem": { + "type": "object", + "properties": { + "id": { + "type": "integer" + }, + "image_url": { "type": "string" }, - "sender_id": { - "description": "发送人ID", + "link_url": { "type": "string" }, - "sender_name": { - "description": "发送人昵称", + "sort": { + "type": "integer" + }, + "title": { "type": "string" } } }, - "app.listResponse": { + "app.bindPhoneRequest": { + "type": "object", + "properties": { + "code": { + "type": "string" + } + } + }, + "app.bindPhoneResponse": { + "type": "object", + "properties": { + "mobile": { + "type": "string" + }, + "success": { + "type": "boolean" + } + } + }, + "app.drawLogItem": { + "type": "object", + "properties": { + "current_level": { + "type": "integer" + }, + "id": { + "type": "integer" + }, + "is_winner": { + "type": "integer" + }, + "issue_id": { + "type": "integer" + }, + "level": { + "type": "integer" + }, + "order_id": { + "type": "integer" + }, + "reward_id": { + "type": "integer" + }, + "user_id": { + "type": "integer" + } + } + }, + "app.guildItem": { + "type": "object", + "properties": { + "avatar_url": { + "type": "string" + }, + "consume_limit": { + "type": "integer" + }, + "description": { + "type": "string" + }, + "id": { + "type": "integer" + }, + "is_open": { + "type": "integer" + }, + "join_mode": { + "type": "integer" + }, + "name": { + "type": "string" + }, + "owner_id": { + "type": "integer" + }, + "status": { + "type": "integer" + } + } + }, + "app.inviteUserItem": { + "type": "object", + "properties": { + "avatar": { + "type": "string" + }, + "id": { + "type": "integer" + }, + "invite_code": { + "type": "string" + }, + "nickname": { + "type": "string" + } + } + }, + "app.issueItem": { + "type": "object", + "properties": { + "id": { + "type": "integer" + }, + "issue_number": { + "type": "string" + }, + "sort": { + "type": "integer" + }, + "status": { + "type": "integer" + } + } + }, + "app.joinGuildRequest": { + "type": "object", + "required": [ + "user_id" + ], + "properties": { + "user_id": { + "type": "integer" + } + } + }, + "app.listActivitiesResponse": { "type": "object", "properties": { "list": { "type": "array", "items": { - "$ref": "#/definitions/app.listData" + "$ref": "#/definitions/app.activityItem" } }, "page": { - "description": "当前页码", "type": "integer" }, "page_size": { - "description": "每页返回的数据量", "type": "integer" }, "total": { - "description": "符合查询条件的总记录数", "type": "integer" } } }, - "app.modifyAppRequest": { + "app.listAppBannersResponse": { "type": "object", - "required": [ - "app_id", - "app_secret", - "name" - ], "properties": { - "app_id": { - "description": "小程序ID", - "type": "string" - }, - "app_secret": { - "description": "小程序密钥", - "type": "string" - }, - "avatar": { - "description": "头像", - "type": "string" - }, - "description": { - "description": "描述", - "type": "string" - }, - "name": { - "description": "名称", - "type": "string" - }, - "template_id": { - "description": "模版ID", - "type": "string" + "list": { + "type": "array", + "items": { + "$ref": "#/definitions/app.appBannerItem" + } } } }, - "app.modifyAppResponse": { + "app.listCouponsResponse": { "type": "object", "properties": { - "message": { - "description": "提示信息", - "type": "string" + "list": { + "type": "array", + "items": { + "$ref": "#/definitions/model.UserCoupons" + } + }, + "page": { + "type": "integer" + }, + "page_size": { + "type": "integer" + }, + "total": { + "type": "integer" } } }, - "app.userListData": { + "app.listDrawLogsResponse": { "type": "object", "properties": { - "created_at": { - "description": "创建时间", + "list": { + "type": "array", + "items": { + "$ref": "#/definitions/app.drawLogItem" + } + }, + "page": { + "type": "integer" + }, + "page_size": { + "type": "integer" + }, + "total": { + "type": "integer" + } + } + }, + "app.listGuildsResponse": { + "type": "object", + "properties": { + "list": { + "type": "array", + "items": { + "$ref": "#/definitions/app.guildItem" + } + }, + "page": { + "type": "integer" + }, + "page_size": { + "type": "integer" + }, + "total": { + "type": "integer" + } + } + }, + "app.listInvitesResponse": { + "type": "object", + "properties": { + "list": { + "type": "array", + "items": { + "$ref": "#/definitions/app.inviteUserItem" + } + }, + "page": { + "type": "integer" + }, + "page_size": { + "type": "integer" + }, + "total": { + "type": "integer" + } + } + }, + "app.listIssuesResponse": { + "type": "object", + "properties": { + "list": { + "type": "array", + "items": { + "$ref": "#/definitions/app.issueItem" + } + }, + "page": { + "type": "integer" + }, + "page_size": { + "type": "integer" + }, + "total": { + "type": "integer" + } + } + }, + "app.listMembersResponse": { + "type": "object", + "properties": { + "list": { + "type": "array", + "items": { + "$ref": "#/definitions/app.memberItem" + } + }, + "page": { + "type": "integer" + }, + "page_size": { + "type": "integer" + }, + "total": { + "type": "integer" + } + } + }, + "app.listOrdersResponse": { + "type": "object", + "properties": { + "list": { + "type": "array", + "items": { + "$ref": "#/definitions/model.Orders" + } + }, + "page": { + "type": "integer" + }, + "page_size": { + "type": "integer" + }, + "total": { + "type": "integer" + } + } + }, + "app.listPointsResponse": { + "type": "object", + "properties": { + "list": { + "type": "array", + "items": { + "$ref": "#/definitions/model.UserPointsLedger" + } + }, + "page": { + "type": "integer" + }, + "page_size": { + "type": "integer" + }, + "total": { + "type": "integer" + } + } + }, + "app.listRewardsResponse": { + "type": "object", + "properties": { + "list": { + "type": "array", + "items": { + "$ref": "#/definitions/app.rewardItem" + } + } + } + }, + "app.listUserItemCardUsesResponse": { + "type": "object", + "properties": { + "list": { + "type": "array", + "items": { + "$ref": "#/definitions/model.ActivityDrawEffects" + } + }, + "page": { + "type": "integer" + }, + "page_size": { + "type": "integer" + }, + "total": { + "type": "integer" + } + } + }, + "app.listUserItemCardsResponse": { + "type": "object", + "properties": { + "list": { + "type": "array", + "items": { + "$ref": "#/definitions/model.UserItemCards" + } + }, + "page": { + "type": "integer" + }, + "page_size": { + "type": "integer" + }, + "total": { + "type": "integer" + } + } + }, + "app.memberItem": { + "type": "object", + "properties": { + "id": { + "type": "integer" + }, + "role": { "type": "string" }, - "user_avatar": { - "description": "用户头像", + "start_time": { "type": "string" }, "user_id": { - "description": "用户ID", + "type": "integer" + } + } + }, + "app.modifyUserRequest": { + "type": "object", + "properties": { + "avatar": { "type": "string" }, - "user_mobile": { - "description": "用户手机号", - "type": "string" - }, - "user_name": { - "description": "用户昵称", + "nickname": { "type": "string" } } }, - "app.userListResponse": { + "app.modifyUserResponse": { "type": "object", "properties": { - "list": { - "type": "array", - "items": { - "$ref": "#/definitions/app.userListData" - } + "user": { + "$ref": "#/definitions/app.userItem" + } + } + }, + "app.phoneLoginRequest": { + "type": "object", + "properties": { + "code": { + "description": "兼容参数名:这里作为手机号或第三方手机号code", + "type": "string" }, - "page": { - "description": "当前页码", + "invite_code": { + "type": "string" + } + } + }, + "app.phoneLoginResponse": { + "type": "object", + "properties": { + "avatar": { + "type": "string" + }, + "invite_code": { + "type": "string" + }, + "nickname": { + "type": "string" + }, + "user_id": { + "type": "integer" + } + } + }, + "app.pointsBalanceResponse": { + "type": "object", + "properties": { + "balance": { + "type": "integer" + } + } + }, + "app.rewardItem": { + "type": "object", + "properties": { + "is_boss": { "type": "integer" }, - "page_size": { - "description": "每页返回的数据量", + "level": { "type": "integer" }, - "total": { - "description": "符合查询条件的总记录数", + "name": { + "type": "string" + }, + "original_qty": { + "type": "integer" + }, + "product_id": { + "type": "integer" + }, + "quantity": { + "type": "integer" + }, + "sort": { + "type": "integer" + }, + "weight": { + "type": "integer" + } + } + }, + "app.simpleMessageResponse": { + "type": "object", + "properties": { + "message": { + "type": "string" + } + } + }, + "app.userItem": { + "type": "object", + "properties": { + "avatar": { + "type": "string" + }, + "id": { + "type": "integer" + }, + "invite_code": { + "type": "string" + }, + "inviter_id": { + "type": "integer" + }, + "nickname": { + "type": "string" + } + } + }, + "app.weixinLoginRequest": { + "type": "object", + "properties": { + "code": { + "type": "string" + }, + "invite_code": { + "type": "string" + } + } + }, + "app.weixinLoginResponse": { + "type": "object", + "properties": { + "avatar": { + "type": "string" + }, + "invite_code": { + "type": "string" + }, + "nickname": { + "type": "string" + }, + "user_id": { "type": "integer" } } @@ -2203,524 +5949,561 @@ const docTemplate = `{ } } }, - "keyword.createKeywordMaterialRequest": { - "type": "object", - "required": [ - "material_list" - ], - "properties": { - "material_list": { - "description": "素材列表", - "type": "array", - "items": { - "$ref": "#/definitions/keyword.keywordMaterial" - } - } - } - }, - "keyword.createKeywordMaterialResponse": { + "model.Activities": { "type": "object", "properties": { - "message": { - "description": "提示信息", - "type": "string" - } - } - }, - "keyword.createKeywordRequest": { - "type": "object", - "required": [ - "app_id", - "keyword" - ], - "properties": { - "app_id": { - "description": "小程序ID", - "type": "string" - }, - "keyword": { - "description": "关键字", - "type": "string" - } - } - }, - "keyword.createKeywordResponse": { - "type": "object", - "properties": { - "id": { - "description": "关键字ID", + "activity_category_id": { + "description": "活动所属分类ID(activity_categories.id,可空)", "type": "integer" }, - "message": { - "description": "提示信息", - "type": "string" - } - } - }, - "keyword.deleteKeywordResponse": { - "type": "object", - "properties": { - "message": { - "description": "提示信息", - "type": "string" - } - } - }, - "keyword.keywordListData": { - "type": "object", - "properties": { - "app_id": { - "description": "小程序ID", + "banner": { + "description": "活动横幅/海报URL", "type": "string" }, "created_at": { "description": "创建时间", "type": "string" }, - "created_user": { - "description": "创建人", - "type": "string" - }, - "id": { - "description": "关键字编号", - "type": "integer" - }, - "keyword": { - "description": "意图关键字", - "type": "string" - }, - "material_type_count": { - "description": "素材类型数量", - "type": "string" - }, - "updated_at": { - "description": "更新时间", - "type": "string" - }, - "updated_user": { - "description": "更新人", - "type": "string" - } - } - }, - "keyword.keywordMaterial": { - "type": "object", - "required": [ - "content", - "interval_seconds", - "type" - ], - "properties": { - "content": { - "description": "素材内容", - "type": "string" - }, - "interval_seconds": { - "description": "发送间隔时间(单位:秒)", - "type": "integer" - }, - "type": { - "description": "素材类型(1:文本 2:图片)", - "type": "integer" - } - } - }, - "keyword.keywordMaterialListData": { - "type": "object", - "properties": { - "content": { - "description": "素材内容", - "type": "string" - }, - "created_at": { - "description": "创建时间", - "type": "string" - }, - "created_user": { - "description": "创建人", + "end_time": { + "description": "结束时间", "type": "string" }, "id": { "description": "主键ID", "type": "integer" }, - "interval_seconds": { - "description": "素材发送间隔时间(单位:秒)", + "is_boss": { + "description": "Boss: 1 是 0 不是", "type": "integer" }, - "keyword_id": { - "description": "意图关键字ID", - "type": "integer" - }, - "type": { - "description": "素材类型(1:文本 2:图片)", - "type": "integer" - } - } - }, - "keyword.keywordMaterialPageListResponse": { - "type": "object", - "properties": { - "list": { - "type": "array", - "items": { - "$ref": "#/definitions/keyword.keywordMaterialListData" - } - }, - "page": { - "description": "当前页码", - "type": "integer" - }, - "page_size": { - "description": "每页返回的数据量", - "type": "integer" - }, - "total": { - "description": "符合查询条件的总记录数", - "type": "integer" - } - } - }, - "keyword.keywordPageListResponse": { - "type": "object", - "properties": { - "list": { - "type": "array", - "items": { - "$ref": "#/definitions/keyword.keywordListData" - } - }, - "page": { - "description": "当前页码", - "type": "integer" - }, - "page_size": { - "description": "每页返回的数据量", - "type": "integer" - }, - "total": { - "description": "符合查询条件的总记录数", - "type": "integer" - } - } - }, - "keyword.modifyKeywordMaterialRequest": { - "type": "object", - "required": [ - "content", - "interval_seconds", - "type" - ], - "properties": { - "content": { - "description": "素材内容", + "name": { + "description": "活动名称", "type": "string" }, - "interval_seconds": { - "description": "发送间隔时间(单位:秒)", + "price_draw": { + "description": "活动门票价格", "type": "integer" }, - "type": { - "description": "素材类型(1:文本 2:图片)", + "start_time": { + "description": "开始时间", + "type": "string" + }, + "status": { + "description": "状态:1进行中 2下线", "type": "integer" - } - } - }, - "keyword.modifyKeywordMaterialResponse": { - "type": "object", - "properties": { - "message": { - "description": "提示信息", + }, + "updated_at": { + "description": "更新时间", "type": "string" } } }, - "keyword.modifyKeywordRequest": { + "model.ActivityDrawEffects": { "type": "object", - "required": [ - "keyword" - ], "properties": { - "keyword": { - "description": "意图关键字", + "activity_category_id": { + "description": "范围快照-活动分类ID", + "type": "integer" + }, + "activity_id": { + "description": "范围快照-活动ID", + "type": "integer" + }, + "applied": { + "description": "是否生效:0否 1是", + "type": "integer" + }, + "card_type": { + "description": "卡类型快照", + "type": "integer" + }, + "created_at": { + "description": "创建时间", "type": "string" - } - } - }, - "keyword.modifyKeywordResponse": { - "type": "object", - "properties": { - "message": { - "description": "提示信息", + }, + "draw_log_id": { + "description": "抽奖日志ID(activity_draw_logs.id)", + "type": "integer" + }, + "effect_type": { + "description": "效果类型快照", + "type": "integer" + }, + "id": { + "description": "主键ID", + "type": "integer" + }, + "issue_id": { + "description": "范围快照-期ID", + "type": "integer" + }, + "probability_delta_x1000": { + "description": "概率相对增益(千分比)", + "type": "integer" + }, + "remark": { + "description": "备注", "type": "string" - } - } - }, - "message.appMessagePageListResponse": { - "type": "object", - "properties": { - "list": { - "type": "array", - "items": { - "$ref": "#/definitions/message.listMessageData" - } }, - "page": { - "description": "当前页码", + "reward_multiplier_x1000": { + "description": "奖励倍数(千分比)", "type": "integer" }, - "page_size": { - "description": "每页返回的数据量", + "scope_type": { + "description": "适用范围快照", "type": "integer" }, - "total": { - "description": "符合查询条件的总记录数", + "system_item_card_id": { + "description": "卡模板ID(system_item_cards.id)", + "type": "integer" + }, + "user_id": { + "description": "用户ID(users.id)", + "type": "integer" + }, + "user_item_card_id": { + "description": "用户卡实例ID(user_item_cards.id)", "type": "integer" } } }, - "message.listMessageData": { + "model.Guild": { "type": "object", "properties": { - "content": { - "description": "消息内容", + "avatar_url": { + "description": "工会头像", + "type": "string" + }, + "consume_limit": { + "description": "加入工会消费流水最低限额(分)", + "type": "integer" + }, + "created_at": { + "description": "创建时间", + "type": "string" + }, + "description": { + "description": "工会描述", "type": "string" }, "id": { - "description": "消息ID", + "description": "主键ID", "type": "integer" }, - "msg_type": { - "description": "消息类型(1:文本 2:图片)", + "is_open": { + "description": "1 公开 2 私有", "type": "integer" }, - "receiver_id": { - "description": "接收人ID", + "join_mode": { + "description": "加入方式 1: 审核通过 2: 自动通过 3. 消费流水", + "type": "integer" + }, + "name": { + "description": "公会名称", "type": "string" }, - "send_time": { - "description": "发送时间", - "type": "string" + "owner_id": { + "description": "会长用户ID", + "type": "integer" }, - "sender_id": { - "description": "发送人ID", - "type": "string" - }, - "sender_name": { - "description": "发送人昵称", - "type": "string" - } - } - }, - "message.userSendMessageRequest": { - "type": "object", - "required": [ - "app_id", - "content", - "from_user_id", - "from_user_name", - "msg_type" - ], - "properties": { - "app_id": { - "description": "小程序ID", - "type": "string" - }, - "content": { - "description": "内容", - "type": "string" - }, - "from_user_id": { - "description": "发送用户的ID", - "type": "string" - }, - "from_user_name": { - "description": "发送用户的昵称", - "type": "string" - }, - "msg_type": { - "description": "消息类型(1:文本 2:图片)", + "status": { + "description": "状态:1正常 2解散", "type": "integer" } } }, - "message.userSendMessageResponse": { + "model.OrderItems": { "type": "object", "properties": { - "message": { - "description": "提示信息", + "created_at": { + "description": "创建时间", + "type": "string" + }, + "id": { + "description": "主键ID", + "type": "integer" + }, + "order_id": { + "description": "订单ID(orders.id)", + "type": "integer" + }, + "price": { + "description": "成交单价(分)", + "type": "integer" + }, + "product_id": { + "description": "商品ID(products.id)", + "type": "integer" + }, + "product_images": { + "description": "商品图片快照(JSON)", + "type": "string" + }, + "quantity": { + "description": "购买数量", + "type": "integer" + }, + "status": { + "description": "行状态:1正常 2取消", + "type": "integer" + }, + "title": { + "description": "商品标题快照", + "type": "string" + }, + "total_amount": { + "description": "行应付总额(分)", + "type": "integer" + } + } + }, + "model.Orders": { + "type": "object", + "properties": { + "actual_amount": { + "description": "实际支付金额(分)", + "type": "integer" + }, + "cancelled_at": { + "description": "取消时间", + "type": "string" + }, + "created_at": { + "description": "创建时间", + "type": "string" + }, + "discount_amount": { + "description": "优惠券抵扣金额(分)", + "type": "integer" + }, + "id": { + "description": "主键ID", + "type": "integer" + }, + "is_consumed": { + "description": "是否已履约/消耗(对虚拟资产)", + "type": "integer" + }, + "order_no": { + "description": "业务订单号(唯一)", + "type": "string" + }, + "paid_at": { + "description": "支付完成时间", + "type": "string" + }, + "pay_preorder_id": { + "description": "关联预支付单ID(payment_preorder.id)", + "type": "integer" + }, + "points_amount": { + "description": "积分抵扣金额(分)", + "type": "integer" + }, + "points_ledger_id": { + "description": "积分扣减流水ID(user_points_ledger.id)", + "type": "integer" + }, + "remark": { + "description": "备注", + "type": "string" + }, + "source_type": { + "description": "来源:1商城直购 2抽奖票据 3其他", + "type": "integer" + }, + "status": { + "description": "订单状态:1待支付 2已支付 3已取消 4已退款", + "type": "integer" + }, + "total_amount": { + "description": "订单总金额(分)", + "type": "integer" + }, + "updated_at": { + "description": "更新时间", + "type": "string" + }, + "user_address_id": { + "description": "收货地址ID(user_addresses.id)", + "type": "integer" + }, + "user_id": { + "description": "下单用户ID(user_members.id)", + "type": "integer" + } + } + }, + "model.UserCoupons": { + "type": "object", + "properties": { + "coupon_id": { + "description": "券模板ID(system_coupons.id)", + "type": "integer" + }, + "created_at": { + "description": "创建时间", + "type": "string" + }, + "id": { + "description": "主键ID", + "type": "integer" + }, + "status": { + "description": "状态:1未使用 2已使用 3已过期", + "type": "integer" + }, + "updated_at": { + "description": "更新时间", + "type": "string" + }, + "used_at": { + "description": "核销时间", + "type": "string" + }, + "used_order_id": { + "description": "核销的订单ID(orders.id)", + "type": "integer" + }, + "user_id": { + "description": "用户ID(user_members.id)", + "type": "integer" + }, + "valid_end": { + "description": "有效期结束", + "type": "string" + }, + "valid_start": { + "description": "有效期开始", "type": "string" } } }, - "upload.uploadImageResponse": { + "model.UserItemCards": { "type": "object", "properties": { - "preview_image_url": { - "description": "可预览图片地址", + "card_id": { + "description": "卡模板ID(system_item_cards.id)", + "type": "integer" + }, + "created_at": { + "description": "创建时间", "type": "string" }, - "real_image_url": { - "description": "真实图片地址", + "id": { + "description": "主键ID", + "type": "integer" + }, + "remark": { + "description": "备注", + "type": "string" + }, + "status": { + "description": "状态:1未使用 2已使用 3已过期", + "type": "integer" + }, + "updated_at": { + "description": "更新时间", + "type": "string" + }, + "used_activity_id": { + "description": "使用时活动ID", + "type": "integer" + }, + "used_at": { + "description": "使用时间", + "type": "string" + }, + "used_draw_log_id": { + "description": "使用关联抽奖日志ID(activity_draw_logs.id)", + "type": "integer" + }, + "used_issue_id": { + "description": "使用时期ID", + "type": "integer" + }, + "user_id": { + "description": "用户ID(users.id)", + "type": "integer" + }, + "valid_end": { + "description": "有效期结束", + "type": "string" + }, + "valid_start": { + "description": "有效期开始", "type": "string" } } }, - "wechat.generateQRCodeRequest": { - "type": "object", - "required": [ - "app_id", - "app_secret", - "path" - ], - "properties": { - "app_id": { - "description": "微信小程序 AppID", - "type": "string" - }, - "app_secret": { - "description": "微信小程序 AppSecret", - "type": "string" - }, - "path": { - "description": "小程序页面路径", - "type": "string" - } - } - }, - "wechat.generateQRCodeResponse": { + "model.UserPointsLedger": { "type": "object", "properties": { - "data": { - "description": "Base64 编码的图片数据", + "action": { + "description": "变更动作:signin/order_deduct/refund_restore/manual", "type": "string" }, - "message": { + "created_at": { + "description": "创建时间", "type": "string" }, - "success": { - "type": "boolean" - } - } - }, - "wechat.miniprogramLoginRequest": { - "type": "object", - "required": [ - "app_id", - "js_code" - ], - "properties": { - "app_id": { - "description": "小程序AppID", + "id": { + "description": "主键ID", + "type": "integer" + }, + "points": { + "description": "积分变动值(正增负减)", + "type": "integer" + }, + "ref_id": { + "description": "关联ID(如订单号/记录ID)", "type": "string" }, - "js_code": { - "description": "登录时获取的code", - "type": "string" - } - } - }, - "wechat.miniprogramLoginResponse": { - "type": "object", - "properties": { - "message": { + "ref_table": { + "description": "关联表名(如orders/payment_refund)", "type": "string" }, - "openid": { - "description": "用户唯一标识", - "type": "string" - }, - "success": { - "type": "boolean" - }, - "token": { - "description": "登录token", - "type": "string" - }, - "unionid": { - "description": "用户在开放平台的唯一标识符", - "type": "string" - }, - "user_avatar": { - "description": "用户头像", + "remark": { + "description": "备注", "type": "string" }, "user_id": { - "description": "用户ID", - "type": "string" - }, - "user_name": { - "description": "用户昵称", - "type": "string" + "description": "用户ID(user_members.id)", + "type": "integer" } } }, - "wechat.sendSubscribeMessageRequest": { + "user.InventoryWithProduct": { "type": "object", - "required": [ - "app_id", - "app_secret", - "template_id", - "touser" - ], "properties": { - "app_id": { - "description": "微信小程序 AppID", + "activity_id": { + "description": "来源活动ID", + "type": "integer" + }, + "created_at": { + "description": "创建时间", "type": "string" }, - "app_secret": { - "description": "小程序 AppSecret", + "id": { + "description": "主键ID", + "type": "integer" + }, + "order_id": { + "description": "来源订单ID", + "type": "integer" + }, + "product_id": { + "description": "资产对应商品ID(实物奖/商品)", + "type": "integer" + }, + "product_images": { "type": "string" }, - "template_id": { - "description": "模板 ID", + "product_name": { "type": "string" }, - "touser": { - "description": "接收者(用户)的 openid", + "remark": { + "description": "备注", "type": "string" + }, + "reward_id": { + "description": "来源奖励ID(activity_reward_settings.id)", + "type": "integer" + }, + "status": { + "description": "状态:1持有 2作废 3已使用/发货", + "type": "integer" + }, + "updated_at": { + "description": "更新时间", + "type": "string" + }, + "user_id": { + "description": "资产归属用户ID", + "type": "integer" } } }, - "wechat.sendSubscribeMessageResponse": { + "user.OrderWithItems": { "type": "object", "properties": { - "message": { + "actual_amount": { + "description": "实际支付金额(分)", + "type": "integer" + }, + "cancelled_at": { + "description": "取消时间", "type": "string" }, - "success": { - "type": "boolean" - } - } - }, - "wechat.templateRequest": { - "type": "object", - "required": [ - "app_id" - ], - "properties": { - "app_id": { - "description": "微信小程序 AppID", - "type": "string" - } - } - }, - "wechat.templateResponse": { - "type": "object", - "properties": { - "app_id": { - "description": "小程序 AppID", + "created_at": { + "description": "创建时间", "type": "string" }, - "message": { + "discount_amount": { + "description": "优惠券抵扣金额(分)", + "type": "integer" + }, + "id": { + "description": "主键ID", + "type": "integer" + }, + "is_consumed": { + "description": "是否已履约/消耗(对虚拟资产)", + "type": "integer" + }, + "items": { + "type": "array", + "items": { + "$ref": "#/definitions/model.OrderItems" + } + }, + "order_no": { + "description": "业务订单号(唯一)", "type": "string" }, - "success": { - "type": "boolean" - }, - "template_id": { - "description": "模板 ID", + "paid_at": { + "description": "支付完成时间", "type": "string" + }, + "pay_preorder_id": { + "description": "关联预支付单ID(payment_preorder.id)", + "type": "integer" + }, + "points_amount": { + "description": "积分抵扣金额(分)", + "type": "integer" + }, + "points_ledger_id": { + "description": "积分扣减流水ID(user_points_ledger.id)", + "type": "integer" + }, + "remark": { + "description": "备注", + "type": "string" + }, + "source_type": { + "description": "来源:1商城直购 2抽奖票据 3其他", + "type": "integer" + }, + "status": { + "description": "订单状态:1待支付 2已支付 3已取消 4已退款", + "type": "integer" + }, + "total_amount": { + "description": "订单总金额(分)", + "type": "integer" + }, + "updated_at": { + "description": "更新时间", + "type": "string" + }, + "user_address_id": { + "description": "收货地址ID(user_addresses.id)", + "type": "integer" + }, + "user_id": { + "description": "下单用户ID(user_members.id)", + "type": "integer" } } } diff --git a/docs/swagger.json b/docs/swagger.json index f98e159..b5ad90a 100644 --- a/docs/swagger.json +++ b/docs/swagger.json @@ -7,14 +7,59 @@ }, "basePath": "/", "paths": { - "/api/admin/app/check_status": { + "/api/admin/activities": { + "post": { + "security": [ + { + "LoginVerifyToken": [] + } + ], + "description": "创建活动,配置基本信息与分类、Boss标签", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "管理端.活动" + ], + "summary": "创建活动", + "parameters": [ + { + "description": "请求参数", + "name": "RequestBody", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/admin.createActivityRequest" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/admin.simpleMessageResponse" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/code.Failure" + } + } + } + } + }, + "/api/admin/activities/{activity_id}": { "get": { "security": [ { "LoginVerifyToken": [] } ], - "description": "管理端根据 app_id 调用外部验证服务获取状态(正常/封禁/未知)", + "description": "查看指定活动的详细信息", "consumes": [ "application/json" ], @@ -22,210 +67,23 @@ "application/json" ], "tags": [ - "管理端.小程序" + "管理端.活动" ], - "summary": "检查小程序状态", + "summary": "查看活动详情", "parameters": [ { - "type": "string", - "description": "小程序ID", - "name": "app_id", - "in": "query", - "required": true - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/app.checkAppStatusResponse" - } - }, - "400": { - "description": "Bad Request", - "schema": { - "$ref": "#/definitions/code.Failure" - } - } - } - } - }, - "/api/admin/app/create": { - "post": { - "security": [ - { - "LoginVerifyToken": [] - } - ], - "description": "新增小程序", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "管理端.小程序" - ], - "summary": "新增小程序", - "parameters": [ - { - "description": "请求参数", - "name": "RequestBody", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/app.createAppRequest" - } - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/app.createAppResponse" - } - }, - "400": { - "description": "Bad Request", - "schema": { - "$ref": "#/definitions/code.Failure" - } - } - } - } - }, - "/api/admin/app/delete": { - "post": { - "security": [ - { - "LoginVerifyToken": [] - } - ], - "description": "删除小程序", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "管理端.小程序" - ], - "summary": "删除小程序", - "parameters": [ - { - "description": "请求参数", - "name": "RequestBody", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/app.deleteAppRequest" - } - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/app.deleteAppResponse" - } - }, - "400": { - "description": "Bad Request", - "schema": { - "$ref": "#/definitions/code.Failure" - } - } - } - } - }, - "/api/admin/app/keyword": { - "post": { - "security": [ - { - "LoginVerifyToken": [] - } - ], - "description": "添加意图关键字", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "管理端.意图关键字" - ], - "summary": "添加意图关键字", - "parameters": [ - { - "description": "请求参数", - "name": "RequestBody", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/keyword.createKeywordRequest" - } - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/keyword.createKeywordResponse" - } - }, - "400": { - "description": "Bad Request", - "schema": { - "$ref": "#/definitions/code.Failure" - } - } - } - } - }, - "/api/admin/app/keyword/material/{id}": { - "put": { - "security": [ - { - "LoginVerifyToken": [] - } - ], - "description": "修改意图关键字素材", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "管理端.意图关键字" - ], - "summary": "修改意图关键字素材", - "parameters": [ - { - "type": "string", - "description": "素材编号ID", - "name": "id", + "type": "integer", + "description": "活动ID", + "name": "activity_id", "in": "path", "required": true - }, - { - "description": "请求参数", - "name": "RequestBody", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/keyword.modifyKeywordMaterialRequest" - } } ], "responses": { "200": { "description": "OK", "schema": { - "$ref": "#/definitions/keyword.modifyKeywordMaterialResponse" + "$ref": "#/definitions/model.Activities" } }, "400": { @@ -236,124 +94,13 @@ } } }, - "post": { - "security": [ - { - "LoginVerifyToken": [] - } - ], - "description": "配置意图关键字素材", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "管理端.意图关键字" - ], - "summary": "配置意图关键字素材", - "parameters": [ - { - "type": "string", - "description": "编号ID", - "name": "id", - "in": "path", - "required": true - }, - { - "description": "请求参数", - "name": "RequestBody", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/keyword.createKeywordMaterialRequest" - } - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/keyword.createKeywordMaterialResponse" - } - }, - "400": { - "description": "Bad Request", - "schema": { - "$ref": "#/definitions/code.Failure" - } - } - } - } - }, - "/api/admin/app/keyword/materials": { - "get": { - "security": [ - { - "LoginVerifyToken": [] - } - ], - "description": "获取意图关键字素材列表", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "管理端.意图关键字" - ], - "summary": "获取意图关键字素材列表", - "parameters": [ - { - "type": "integer", - "description": "意图关键字ID", - "name": "keyword_id", - "in": "query", - "required": true - }, - { - "type": "integer", - "default": 1, - "description": "当前页码", - "name": "page", - "in": "query", - "required": true - }, - { - "type": "integer", - "default": 20, - "description": "每页返回的数据量,最多 100 条", - "name": "page_size", - "in": "query", - "required": true - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/keyword.keywordMaterialPageListResponse" - } - }, - "400": { - "description": "Bad Request", - "schema": { - "$ref": "#/definitions/code.Failure" - } - } - } - } - }, - "/api/admin/app/keyword/{id}": { "put": { "security": [ { "LoginVerifyToken": [] } ], - "description": "修改意图关键字", + "description": "修改活动基本信息、分类、Boss标签等", "consumes": [ "application/json" ], @@ -361,14 +108,14 @@ "application/json" ], "tags": [ - "管理端.意图关键字" + "管理端.活动" ], - "summary": "修改意图关键字", + "summary": "修改活动", "parameters": [ { - "type": "string", - "description": "编号ID", - "name": "id", + "type": "integer", + "description": "活动ID", + "name": "activity_id", "in": "path", "required": true }, @@ -378,7 +125,7 @@ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/keyword.modifyKeywordRequest" + "$ref": "#/definitions/admin.modifyActivityRequest" } } ], @@ -386,7 +133,7 @@ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/keyword.modifyKeywordResponse" + "$ref": "#/definitions/admin.simpleMessageResponse" } }, "400": { @@ -403,7 +150,7 @@ "LoginVerifyToken": [] } ], - "description": "删除意图关键字", + "description": "删除指定活动", "consumes": [ "application/json" ], @@ -411,14 +158,14 @@ "application/json" ], "tags": [ - "管理端.意图关键字" + "管理端.活动" ], - "summary": "删除意图关键字", + "summary": "删除活动", "parameters": [ { - "type": "string", - "description": "编号ID", - "name": "id", + "type": "integer", + "description": "活动ID", + "name": "activity_id", "in": "path", "required": true } @@ -427,7 +174,7 @@ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/keyword.deleteKeywordResponse" + "$ref": "#/definitions/admin.simpleMessageResponse" } }, "400": { @@ -439,14 +186,14 @@ } } }, - "/api/admin/app/keywords": { + "/api/admin/activities/{activity_id}/issues": { "get": { "security": [ { "LoginVerifyToken": [] } ], - "description": "获取意图关键字列表", + "description": "获取指定活动的期数列表,支持分页", "consumes": [ "application/json" ], @@ -454,27 +201,21 @@ "application/json" ], "tags": [ - "管理端.意图关键字" + "管理端.活动" ], - "summary": "获取意图关键字列表", + "summary": "查看活动期数", "parameters": [ { "type": "integer", - "description": "小程序ID", - "name": "app_id", - "in": "query", + "description": "活动ID", + "name": "activity_id", + "in": "path", "required": true }, - { - "type": "string", - "description": "意图关键字", - "name": "keyword", - "in": "query" - }, { "type": "integer", "default": 1, - "description": "当前页码", + "description": "页码", "name": "page", "in": "query", "required": true @@ -482,7 +223,7 @@ { "type": "integer", "default": 20, - "description": "每页返回的数据量,最多 100 条", + "description": "每页数量,最多100", "name": "page_size", "in": "query", "required": true @@ -492,7 +233,7 @@ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/keyword.keywordPageListResponse" + "$ref": "#/definitions/admin.listIssuesResponse" } }, "400": { @@ -502,16 +243,14 @@ } } } - } - }, - "/api/admin/app/users": { - "get": { + }, + "post": { "security": [ { "LoginVerifyToken": [] } ], - "description": "小程序用户列表", + "description": "为指定活动创建一个新的期数", "consumes": [ "application/json" ], @@ -519,85 +258,14 @@ "application/json" ], "tags": [ - "管理端.小程序" + "管理端.活动" ], - "summary": "小程序用户列表", + "summary": "创建活动期数", "parameters": [ - { - "type": "string", - "description": "小程序ID", - "name": "app_id", - "in": "query", - "required": true - }, - { - "type": "string", - "description": "用户昵称", - "name": "user_name", - "in": "query" - }, - { - "type": "string", - "description": "用户ID", - "name": "user_id", - "in": "query" - }, { "type": "integer", - "default": 1, - "description": "当前页码", - "name": "page", - "in": "query", - "required": true - }, - { - "type": "integer", - "default": 20, - "description": "每页返回的数据量,最多 100 条", - "name": "page_size", - "in": "query", - "required": true - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/app.userListResponse" - } - }, - "400": { - "description": "Bad Request", - "schema": { - "$ref": "#/definitions/code.Failure" - } - } - } - } - }, - "/api/admin/app/{id}": { - "put": { - "security": [ - { - "LoginVerifyToken": [] - } - ], - "description": "编辑小程序", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "管理端.小程序" - ], - "summary": "编辑小程序", - "parameters": [ - { - "type": "string", - "description": "编号ID", - "name": "id", + "description": "活动ID", + "name": "activity_id", "in": "path", "required": true }, @@ -607,7 +275,7 @@ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/app.modifyAppRequest" + "$ref": "#/definitions/admin.createIssueRequest" } } ], @@ -615,7 +283,7 @@ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/app.modifyAppResponse" + "$ref": "#/definitions/admin.simpleMessage" } }, "400": { @@ -627,14 +295,14 @@ } } }, - "/api/admin/apps": { - "get": { + "/api/admin/activities/{activity_id}/issues/{issue_id}": { + "put": { "security": [ { "LoginVerifyToken": [] } ], - "description": "小程序列表", + "description": "修改指定期数的信息", "consumes": [ "application/json" ], @@ -642,32 +310,386 @@ "application/json" ], "tags": [ - "管理端.小程序" + "管理端.活动" ], - "summary": "小程序列表", + "summary": "修改活动期数", "parameters": [ { - "type": "string", - "description": "小程序名称", - "name": "name", - "in": "query" - }, - { - "type": "string", - "description": "小程序ID", - "name": "app_id", - "in": "query" + "type": "integer", + "description": "活动ID", + "name": "activity_id", + "in": "path", + "required": true }, { "type": "integer", - "description": "客服编号", - "name": "admin_id", + "description": "期ID", + "name": "issue_id", + "in": "path", + "required": true + }, + { + "description": "请求参数", + "name": "RequestBody", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/admin.modifyIssueRequest" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/admin.simpleMessage" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/code.Failure" + } + } + } + }, + "delete": { + "security": [ + { + "LoginVerifyToken": [] + } + ], + "description": "删除指定期数", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "管理端.活动" + ], + "summary": "删除活动期数", + "parameters": [ + { + "type": "integer", + "description": "活动ID", + "name": "activity_id", + "in": "path", + "required": true + }, + { + "type": "integer", + "description": "期ID", + "name": "issue_id", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/admin.simpleMessage" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/code.Failure" + } + } + } + } + }, + "/api/admin/activities/{activity_id}/issues/{issue_id}/rewards": { + "get": { + "security": [ + { + "LoginVerifyToken": [] + } + ], + "description": "查看指定期数的奖励配置列表", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "管理端.活动" + ], + "summary": "查看期数奖品", + "parameters": [ + { + "type": "integer", + "description": "活动ID", + "name": "activity_id", + "in": "path", + "required": true + }, + { + "type": "integer", + "description": "期ID", + "name": "issue_id", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/admin.listRewardsResponse" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/code.Failure" + } + } + } + }, + "post": { + "security": [ + { + "LoginVerifyToken": [] + } + ], + "description": "为指定期数批量创建奖励配置", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "管理端.活动" + ], + "summary": "创建期数奖品", + "parameters": [ + { + "type": "integer", + "description": "活动ID", + "name": "activity_id", + "in": "path", + "required": true + }, + { + "type": "integer", + "description": "期ID", + "name": "issue_id", + "in": "path", + "required": true + }, + { + "description": "请求参数", + "name": "RequestBody", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/admin.createRewardsRequest" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/admin.simpleMessageResponse" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/code.Failure" + } + } + } + } + }, + "/api/admin/activities/{activity_id}/issues/{issue_id}/rewards/{reward_id}": { + "put": { + "security": [ + { + "LoginVerifyToken": [] + } + ], + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "管理端.活动" + ], + "summary": "更新期数奖励", + "parameters": [ + { + "type": "integer", + "description": "活动ID", + "name": "activity_id", + "in": "path", + "required": true + }, + { + "type": "integer", + "description": "期ID", + "name": "issue_id", + "in": "path", + "required": true + }, + { + "type": "integer", + "description": "奖励ID", + "name": "reward_id", + "in": "path", + "required": true + }, + { + "description": "请求参数", + "name": "RequestBody", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/admin.modifyRewardRequest" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/admin.simpleMessageResponse" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/code.Failure" + } + } + } + }, + "delete": { + "security": [ + { + "LoginVerifyToken": [] + } + ], + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "管理端.活动" + ], + "summary": "删除期数奖励", + "parameters": [ + { + "type": "integer", + "description": "活动ID", + "name": "activity_id", + "in": "path", + "required": true + }, + { + "type": "integer", + "description": "期ID", + "name": "issue_id", + "in": "path", + "required": true + }, + { + "type": "integer", + "description": "奖励ID", + "name": "reward_id", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/admin.simpleMessageResponse" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/code.Failure" + } + } + } + } + }, + "/api/admin/activity_categories": { + "get": { + "security": [ + { + "LoginVerifyToken": [] + } + ], + "description": "获取启用状态的活动分类列表", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "管理端.活动" + ], + "summary": "活动分类列表", + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/admin.listCategoriesResponse" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/code.Failure" + } + } + } + } + }, + "/api/admin/banners": { + "get": { + "security": [ + { + "LoginVerifyToken": [] + } + ], + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "管理端.运营" + ], + "summary": "查看轮播图列表", + "parameters": [ + { + "type": "integer", + "description": "状态", + "name": "status", "in": "query" }, { "type": "integer", "default": 1, - "description": "当前页码", + "description": "页码", "name": "page", "in": "query", "required": true @@ -675,7 +697,7 @@ { "type": "integer", "default": 20, - "description": "每页返回的数据量,最多 100 条", + "description": "每页数量", "name": "page_size", "in": "query", "required": true @@ -685,7 +707,140 @@ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/app.listResponse" + "$ref": "#/definitions/admin.listBannersResponse" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/code.Failure" + } + } + } + }, + "post": { + "security": [ + { + "LoginVerifyToken": [] + } + ], + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "管理端.运营" + ], + "summary": "创建轮播图", + "parameters": [ + { + "description": "请求参数", + "name": "RequestBody", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/admin.createBannerRequest" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/admin.createBannerResponse" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/code.Failure" + } + } + } + } + }, + "/api/admin/banners/{banner_id}": { + "put": { + "security": [ + { + "LoginVerifyToken": [] + } + ], + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "管理端.运营" + ], + "summary": "修改轮播图", + "parameters": [ + { + "type": "string", + "description": "轮播图ID", + "name": "banner_id", + "in": "path", + "required": true + }, + { + "description": "请求参数", + "name": "RequestBody", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/admin.modifyBannerRequest" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/admin.pcSimpleMessage" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/code.Failure" + } + } + } + }, + "delete": { + "security": [ + { + "LoginVerifyToken": [] + } + ], + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "管理端.运营" + ], + "summary": "删除轮播图", + "parameters": [ + { + "type": "string", + "description": "轮播图ID", + "name": "banner_id", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/admin.pcSimpleMessage" } }, "400": { @@ -787,6 +942,244 @@ } } }, + "/api/admin/guilds": { + "post": { + "security": [ + { + "LoginVerifyToken": [] + } + ], + "description": "创建工会并将首位成员设为会长", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "管理端.工会" + ], + "summary": "创建工会", + "parameters": [ + { + "description": "请求参数", + "name": "RequestBody", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/admin.createGuildRequest" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/admin.createGuildResponse" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/code.Failure" + } + } + } + } + }, + "/api/admin/guilds/{guild_id}": { + "get": { + "security": [ + { + "LoginVerifyToken": [] + } + ], + "description": "查看指定工会详情", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "管理端.工会" + ], + "summary": "查看工会详情", + "parameters": [ + { + "type": "integer", + "description": "工会ID", + "name": "guild_id", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/model.Guild" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/code.Failure" + } + } + } + }, + "put": { + "security": [ + { + "LoginVerifyToken": [] + } + ], + "description": "修改指定工会信息", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "管理端.工会" + ], + "summary": "修改工会", + "parameters": [ + { + "type": "integer", + "description": "工会ID", + "name": "guild_id", + "in": "path", + "required": true + }, + { + "description": "请求参数", + "name": "RequestBody", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/admin.modifyGuildRequest" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/admin.modifyGuildResponse" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/code.Failure" + } + } + } + }, + "delete": { + "security": [ + { + "LoginVerifyToken": [] + } + ], + "description": "删除指定工会", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "管理端.工会" + ], + "summary": "删除工会", + "parameters": [ + { + "type": "integer", + "description": "工会ID", + "name": "guild_id", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/admin.deleteGuildResponse" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/code.Failure" + } + } + } + } + }, + "/api/admin/guilds/{guild_id}/members": { + "get": { + "security": [ + { + "LoginVerifyToken": [] + } + ], + "description": "查看指定工会的成员列表", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "管理端.工会" + ], + "summary": "查看工会成员", + "parameters": [ + { + "type": "integer", + "description": "工会ID", + "name": "guild_id", + "in": "path", + "required": true + }, + { + "type": "integer", + "default": 1, + "description": "页码", + "name": "page", + "in": "query", + "required": true + }, + { + "type": "integer", + "default": 20, + "description": "每页数量,最多100", + "name": "page_size", + "in": "query", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/admin.listGuildMembersResponse" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/code.Failure" + } + } + } + } + }, "/api/admin/list": { "get": { "security": [ @@ -891,14 +1284,13 @@ } } }, - "/api/admin/messages": { + "/api/admin/product_categories": { "get": { "security": [ { "LoginVerifyToken": [] } ], - "description": "获取消息日志", "consumes": [ "application/json" ], @@ -906,28 +1298,26 @@ "application/json" ], "tags": [ - "管理端.小程序" + "管理端.商品" ], - "summary": "获取消息日志", + "summary": "查看商品分类列表", "parameters": [ { "type": "string", - "description": "小程序ID", - "name": "app_id", - "in": "query", - "required": true + "description": "名称", + "name": "name", + "in": "query" }, { - "type": "string", - "description": "用户ID", - "name": "user_id", - "in": "query", - "required": true + "type": "integer", + "description": "状态", + "name": "status", + "in": "query" }, { "type": "integer", "default": 1, - "description": "当前页码", + "description": "页码", "name": "page", "in": "query", "required": true @@ -935,7 +1325,7 @@ { "type": "integer", "default": 20, - "description": "每页返回的数据量,最多 100 条", + "description": "每页数量", "name": "page_size", "in": "query", "required": true @@ -945,7 +1335,49 @@ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/app.appMessagePageListResponse" + "$ref": "#/definitions/admin.listProductCategoriesResponse" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/code.Failure" + } + } + } + }, + "post": { + "security": [ + { + "LoginVerifyToken": [] + } + ], + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "管理端.商品" + ], + "summary": "创建商品分类", + "parameters": [ + { + "description": "请求参数", + "name": "RequestBody", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/admin.createProductCategoryRequest" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/admin.createProductCategoryResponse" } }, "400": { @@ -957,73 +1389,13 @@ } } }, - "/api/admin/messages/latest": { - "get": { - "security": [ - { - "LoginVerifyToken": [] - } - ], - "description": "管理端根据appid获取最新消息记录,包含已读未读状态,访问时自动标记为已读", - "consumes": [ - "application/json" - ], - "produces": [ - "application/json" - ], - "tags": [ - "管理端.小程序" - ], - "summary": "根据appid获取最新消息记录", - "parameters": [ - { - "type": "string", - "description": "小程序ID", - "name": "app_id", - "in": "query", - "required": true - }, - { - "type": "integer", - "default": 1, - "description": "当前页码", - "name": "page", - "in": "query", - "required": true - }, - { - "type": "integer", - "default": 20, - "description": "每页返回的数据量,最多 100 条", - "name": "page_size", - "in": "query", - "required": true - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/app.latestMessageByAppIdResponse" - } - }, - "400": { - "description": "Bad Request", - "schema": { - "$ref": "#/definitions/code.Failure" - } - } - } - } - }, - "/api/admin/rel_app/{id}": { + "/api/admin/product_categories/{category_id}": { "put": { "security": [ { "LoginVerifyToken": [] } ], - "description": "客服关联小程序", "consumes": [ "application/json" ], @@ -1031,14 +1403,14 @@ "application/json" ], "tags": [ - "管理端.客服管理" + "管理端.商品" ], - "summary": "客服关联小程序", + "summary": "修改商品分类", "parameters": [ { "type": "string", - "description": "客服编号ID", - "name": "id", + "description": "分类ID", + "name": "category_id", "in": "path", "required": true }, @@ -1048,7 +1420,7 @@ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/admin.relAppRequest" + "$ref": "#/definitions/admin.modifyProductCategoryRequest" } } ], @@ -1056,7 +1428,7 @@ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/admin.relAppResponse" + "$ref": "#/definitions/admin.pcSimpleMessage" } }, "400": { @@ -1066,16 +1438,13 @@ } } } - } - }, - "/api/admin/send_message": { - "post": { + }, + "delete": { "security": [ { "LoginVerifyToken": [] } ], - "description": "管理员发送消息", "consumes": [ "application/json" ], @@ -1083,55 +1452,15 @@ "application/json" ], "tags": [ - "管理端.小程序" + "管理端.商品" ], - "summary": "管理员发送消息", + "summary": "删除商品分类", "parameters": [ { - "description": "请求参数", - "name": "RequestBody", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/app.adminSendMessageRequest" - } - } - ], - "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/app.adminSendMessageResponse" - } - }, - "400": { - "description": "Bad Request", - "schema": { - "$ref": "#/definitions/code.Failure" - } - } - } - } - }, - "/api/admin/upload/image": { - "post": { - "description": "上传图片", - "consumes": [ - "multipart/form-data" - ], - "produces": [ - "application/json" - ], - "tags": [ - "通用" - ], - "summary": "上传图片", - "parameters": [ - { - "type": "file", - "description": "选择文件", - "name": "file", - "in": "formData", + "type": "string", + "description": "分类ID", + "name": "category_id", + "in": "path", "required": true } ], @@ -1139,7 +1468,7 @@ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/upload.uploadImageResponse" + "$ref": "#/definitions/admin.pcSimpleMessage" } }, "400": { @@ -1151,6 +1480,1086 @@ } } }, + "/api/admin/products": { + "get": { + "security": [ + { + "LoginVerifyToken": [] + } + ], + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "管理端.商品" + ], + "summary": "查看商品列表", + "parameters": [ + { + "type": "string", + "description": "名称", + "name": "name", + "in": "query" + }, + { + "type": "integer", + "description": "分类ID", + "name": "category_id", + "in": "query" + }, + { + "type": "integer", + "description": "状态", + "name": "status", + "in": "query" + }, + { + "type": "integer", + "default": 1, + "description": "页码", + "name": "page", + "in": "query", + "required": true + }, + { + "type": "integer", + "default": 20, + "description": "每页数量", + "name": "page_size", + "in": "query", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/admin.listProductsResponse" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/code.Failure" + } + } + } + }, + "post": { + "security": [ + { + "LoginVerifyToken": [] + } + ], + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "管理端.商品" + ], + "summary": "创建商品", + "parameters": [ + { + "description": "请求参数", + "name": "RequestBody", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/admin.createProductRequest" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/admin.createProductResponse" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/code.Failure" + } + } + } + } + }, + "/api/admin/products/{product_id}": { + "put": { + "security": [ + { + "LoginVerifyToken": [] + } + ], + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "管理端.商品" + ], + "summary": "修改商品", + "parameters": [ + { + "type": "string", + "description": "商品ID", + "name": "product_id", + "in": "path", + "required": true + }, + { + "description": "请求参数", + "name": "RequestBody", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/admin.modifyProductRequest" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/admin.pcSimpleMessage" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/code.Failure" + } + } + } + }, + "delete": { + "security": [ + { + "LoginVerifyToken": [] + } + ], + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "管理端.商品" + ], + "summary": "删除商品", + "parameters": [ + { + "type": "string", + "description": "商品ID", + "name": "product_id", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/admin.pcSimpleMessage" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/code.Failure" + } + } + } + } + }, + "/api/admin/system_item_cards": { + "get": { + "description": "管理员获取道具卡列表,支持按名称、状态、类型等条件筛选", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "管理端.运营管理" + ], + "summary": "获取道具卡列表", + "parameters": [ + { + "type": "string", + "description": "道具卡名称", + "name": "name", + "in": "query" + }, + { + "type": "integer", + "description": "状态:1启用 2禁用", + "name": "status", + "in": "query" + }, + { + "type": "integer", + "description": "道具卡类型:1抽奖卡 2加成卡 3保底卡", + "name": "card_type", + "in": "query" + }, + { + "type": "integer", + "description": "适用范围:1全局 2活动分类 3活动 4期次", + "name": "scope_type", + "in": "query" + }, + { + "type": "integer", + "description": "页码,默认1", + "name": "page", + "in": "query" + }, + { + "type": "integer", + "description": "每页条数,默认10", + "name": "page_size", + "in": "query" + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/admin.listItemCardsResponse" + } + }, + "400": { + "description": "参数错误", + "schema": { + "$ref": "#/definitions/code.Failure" + } + }, + "401": { + "description": "未授权", + "schema": { + "$ref": "#/definitions/code.Failure" + } + }, + "500": { + "description": "服务器内部错误", + "schema": { + "$ref": "#/definitions/code.Failure" + } + } + } + }, + "post": { + "description": "管理员创建新的道具卡,支持设置类型、效果、有效期等属性", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "管理端.运营管理" + ], + "summary": "创建道具卡", + "parameters": [ + { + "description": "创建道具卡请求参数", + "name": "RequestBody", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/admin.createItemCardRequest" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/admin.createItemCardResponse" + } + }, + "400": { + "description": "参数错误", + "schema": { + "$ref": "#/definitions/code.Failure" + } + }, + "401": { + "description": "未授权", + "schema": { + "$ref": "#/definitions/code.Failure" + } + }, + "403": { + "description": "无权限,仅超管可操作", + "schema": { + "$ref": "#/definitions/code.Failure" + } + }, + "500": { + "description": "服务器内部错误", + "schema": { + "$ref": "#/definitions/code.Failure" + } + } + } + } + }, + "/api/admin/system_item_cards/{item_card_id}": { + "put": { + "description": "管理员修改道具卡信息,支持修改名称、价格、有效期等属性", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "管理端.运营管理" + ], + "summary": "修改道具卡", + "parameters": [ + { + "type": "integer", + "description": "道具卡ID", + "name": "item_card_id", + "in": "path", + "required": true + }, + { + "description": "修改道具卡请求参数", + "name": "RequestBody", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/admin.modifyItemCardRequest" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/admin.simpleMessageResponse" + } + }, + "400": { + "description": "参数错误", + "schema": { + "$ref": "#/definitions/code.Failure" + } + }, + "401": { + "description": "未授权", + "schema": { + "$ref": "#/definitions/code.Failure" + } + }, + "403": { + "description": "无权限,仅超管可操作", + "schema": { + "$ref": "#/definitions/code.Failure" + } + }, + "500": { + "description": "服务器内部错误", + "schema": { + "$ref": "#/definitions/code.Failure" + } + } + } + }, + "delete": { + "description": "管理员删除指定的道具卡", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "管理端.运营管理" + ], + "summary": "删除道具卡", + "parameters": [ + { + "type": "integer", + "description": "道具卡ID", + "name": "item_card_id", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/admin.simpleMessageResponse" + } + }, + "400": { + "description": "参数错误", + "schema": { + "$ref": "#/definitions/code.Failure" + } + }, + "401": { + "description": "未授权", + "schema": { + "$ref": "#/definitions/code.Failure" + } + }, + "403": { + "description": "无权限,仅超管可操作", + "schema": { + "$ref": "#/definitions/code.Failure" + } + }, + "500": { + "description": "服务器内部错误", + "schema": { + "$ref": "#/definitions/code.Failure" + } + } + } + } + }, + "/api/admin/users": { + "get": { + "security": [ + { + "LoginVerifyToken": [] + } + ], + "description": "查看APP端用户分页列表", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "管理端.用户" + ], + "summary": "管理端用户列表", + "parameters": [ + { + "type": "integer", + "default": 1, + "description": "页码", + "name": "page", + "in": "query", + "required": true + }, + { + "type": "integer", + "default": 20, + "description": "每页数量,最多100", + "name": "page_size", + "in": "query", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/admin.listUsersResponse" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/code.Failure" + } + } + } + } + }, + "/api/admin/users/{user_id}/coupons": { + "get": { + "security": [ + { + "LoginVerifyToken": [] + } + ], + "description": "查看指定用户持有的优惠券列表", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "管理端.用户" + ], + "summary": "查看用户优惠券列表", + "parameters": [ + { + "type": "integer", + "description": "用户ID", + "name": "user_id", + "in": "path", + "required": true + }, + { + "type": "integer", + "default": 1, + "description": "页码", + "name": "page", + "in": "query", + "required": true + }, + { + "type": "integer", + "default": 20, + "description": "每页数量,最多100", + "name": "page_size", + "in": "query", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/admin.listCouponsResponse" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/code.Failure" + } + } + } + } + }, + "/api/admin/users/{user_id}/coupons/add": { + "post": { + "security": [ + { + "LoginVerifyToken": [] + } + ], + "description": "管理端为指定用户发放优惠券", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "管理端.用户" + ], + "summary": "给用户添加优惠券", + "parameters": [ + { + "type": "integer", + "description": "用户ID", + "name": "user_id", + "in": "path", + "required": true + }, + { + "description": "请求参数", + "name": "RequestBody", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/admin.addCouponRequest" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/admin.addCouponResponse" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/code.Failure" + } + } + } + } + }, + "/api/admin/users/{user_id}/inventory": { + "get": { + "security": [ + { + "LoginVerifyToken": [] + } + ], + "description": "查看指定用户的资产记录", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "管理端.用户" + ], + "summary": "查看用户资产列表", + "parameters": [ + { + "type": "integer", + "description": "用户ID", + "name": "user_id", + "in": "path", + "required": true + }, + { + "type": "integer", + "default": 1, + "description": "页码", + "name": "page", + "in": "query", + "required": true + }, + { + "type": "integer", + "default": 20, + "description": "每页数量,最多100", + "name": "page_size", + "in": "query", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/admin.listInventoryResponse" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/code.Failure" + } + } + } + } + }, + "/api/admin/users/{user_id}/invites": { + "get": { + "security": [ + { + "LoginVerifyToken": [] + } + ], + "description": "查看指定用户邀请的用户列表", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "管理端.用户" + ], + "summary": "查看用户邀请列表", + "parameters": [ + { + "type": "integer", + "description": "用户ID", + "name": "user_id", + "in": "path", + "required": true + }, + { + "type": "integer", + "default": 1, + "description": "页码", + "name": "page", + "in": "query", + "required": true + }, + { + "type": "integer", + "default": 20, + "description": "每页数量,最多100", + "name": "page_size", + "in": "query", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/admin.listInvitesResponse" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/code.Failure" + } + } + } + } + }, + "/api/admin/users/{user_id}/item_cards": { + "post": { + "description": "管理员给指定用户分配道具卡,可指定数量", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "管理端.运营管理" + ], + "summary": "给用户分配道具卡", + "parameters": [ + { + "type": "integer", + "description": "用户ID", + "name": "user_id", + "in": "path", + "required": true + }, + { + "description": "分配道具卡请求参数", + "name": "RequestBody", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/admin.assignItemCardRequest" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/admin.simpleMessageResponse" + } + }, + "400": { + "description": "参数错误", + "schema": { + "$ref": "#/definitions/code.Failure" + } + }, + "401": { + "description": "未授权", + "schema": { + "$ref": "#/definitions/code.Failure" + } + }, + "403": { + "description": "无权限,仅超管可操作", + "schema": { + "$ref": "#/definitions/code.Failure" + } + }, + "500": { + "description": "服务器内部错误", + "schema": { + "$ref": "#/definitions/code.Failure" + } + } + } + } + }, + "/api/admin/users/{user_id}/orders": { + "get": { + "security": [ + { + "LoginVerifyToken": [] + } + ], + "description": "查看指定用户的订单记录", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "管理端.用户" + ], + "summary": "查看用户订单列表", + "parameters": [ + { + "type": "integer", + "description": "用户ID", + "name": "user_id", + "in": "path", + "required": true + }, + { + "type": "integer", + "default": 1, + "description": "页码", + "name": "page", + "in": "query", + "required": true + }, + { + "type": "integer", + "default": 20, + "description": "每页数量,最多100", + "name": "page_size", + "in": "query", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/admin.listOrdersResponse" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/code.Failure" + } + } + } + } + }, + "/api/admin/users/{user_id}/points": { + "get": { + "security": [ + { + "LoginVerifyToken": [] + } + ], + "description": "查看指定用户的积分流水记录", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "管理端.用户" + ], + "summary": "查看用户积分记录", + "parameters": [ + { + "type": "integer", + "description": "用户ID", + "name": "user_id", + "in": "path", + "required": true + }, + { + "type": "integer", + "default": 1, + "description": "页码", + "name": "page", + "in": "query", + "required": true + }, + { + "type": "integer", + "default": 20, + "description": "每页数量,最多100", + "name": "page_size", + "in": "query", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/admin.listPointsResponse" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/code.Failure" + } + } + } + } + }, + "/api/admin/users/{user_id}/points/add": { + "post": { + "security": [ + { + "LoginVerifyToken": [] + } + ], + "description": "管理端为指定用户发放积分,支持设置有效期", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "管理端.用户" + ], + "summary": "给用户添加积分", + "parameters": [ + { + "type": "integer", + "description": "用户ID", + "name": "user_id", + "in": "path", + "required": true + }, + { + "description": "请求参数", + "name": "RequestBody", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/admin.addPointsRequest" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/admin.addPointsResponse" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/code.Failure" + } + } + } + } + }, + "/api/admin/users/{user_id}/points/balance": { + "get": { + "security": [ + { + "LoginVerifyToken": [] + } + ], + "description": "查看指定用户当前积分余额(过滤过期)", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "管理端.用户" + ], + "summary": "查看用户积分余额", + "parameters": [ + { + "type": "integer", + "description": "用户ID", + "name": "user_id", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/admin.pointsBalanceResponse" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/code.Failure" + } + } + } + } + }, + "/api/admin/users/{user_id}/rewards/grant": { + "post": { + "description": "管理员给用户发放奖励,支持实物和虚拟奖品,可选择关联活动和奖励配置", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "管理端.用户" + ], + "summary": "给用户发放奖励", + "parameters": [ + { + "type": "integer", + "description": "用户ID", + "name": "user_id", + "in": "path", + "required": true + }, + { + "description": "请求参数", + "name": "RequestBody", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/admin.GrantRewardRequest" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/admin.GrantRewardResponse" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/code.Failure" + } + }, + "401": { + "description": "Unauthorized", + "schema": { + "$ref": "#/definitions/code.Failure" + } + }, + "403": { + "description": "Forbidden", + "schema": { + "$ref": "#/definitions/code.Failure" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/code.Failure" + } + } + } + } + }, "/api/admin/{id}": { "put": { "security": [ @@ -1203,9 +2612,9 @@ } } }, - "/api/app/messages": { + "/api/app/activities": { "get": { - "description": "获取消息日志", + "description": "获取活动列表,支持分类、Boss、状态过滤与分页", "consumes": [ "application/json" ], @@ -1213,28 +2622,38 @@ "application/json" ], "tags": [ - "用户端" + "APP端.活动" ], - "summary": "获取消息日志", + "summary": "活动列表", "parameters": [ { "type": "string", - "description": "小程序ID", - "name": "app_id", - "in": "query", - "required": true + "description": "活动名称(模糊)", + "name": "name", + "in": "query" }, { - "type": "string", - "description": "用户ID", - "name": "user_id", - "in": "query", - "required": true + "type": "integer", + "description": "活动分类ID", + "name": "category_id", + "in": "query" + }, + { + "type": "integer", + "description": "是否Boss(0/1)", + "name": "is_boss", + "in": "query" + }, + { + "type": "integer", + "description": "状态(1进行中 2下线)", + "name": "status", + "in": "query" }, { "type": "integer", "default": 1, - "description": "当前页码", + "description": "页码", "name": "page", "in": "query", "required": true @@ -1242,7 +2661,7 @@ { "type": "integer", "default": 20, - "description": "每页返回的数据量,最多 100 条", + "description": "每页数量,最多100", "name": "page_size", "in": "query", "required": true @@ -1252,7 +2671,7 @@ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/message.appMessagePageListResponse" + "$ref": "#/definitions/app.listActivitiesResponse" } }, "400": { @@ -1264,9 +2683,9 @@ } } }, - "/api/app/send_message": { - "post": { - "description": "用户发送消息", + "/api/app/activities/{activity_id}": { + "get": { + "description": "获取指定活动的详细信息", "consumes": [ "application/json" ], @@ -1274,9 +2693,488 @@ "application/json" ], "tags": [ - "用户端" + "APP端.活动" ], - "summary": "用户发送消息", + "summary": "活动详情", + "parameters": [ + { + "type": "integer", + "description": "活动ID", + "name": "activity_id", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/model.Activities" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/code.Failure" + } + } + } + } + }, + "/api/app/activities/{activity_id}/issues": { + "get": { + "description": "获取指定活动的期列表,支持分页", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "APP端.活动" + ], + "summary": "活动期列表", + "parameters": [ + { + "type": "integer", + "description": "活动ID", + "name": "activity_id", + "in": "path", + "required": true + }, + { + "type": "integer", + "default": 1, + "description": "页码", + "name": "page", + "in": "query", + "required": true + }, + { + "type": "integer", + "default": 20, + "description": "每页数量,最多100", + "name": "page_size", + "in": "query", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/app.listIssuesResponse" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/code.Failure" + } + } + } + } + }, + "/api/app/activities/{activity_id}/issues/{issue_id}/draw_logs": { + "get": { + "description": "查看指定活动期数的抽奖记录,支持分页", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "APP端.活动" + ], + "summary": "抽奖记录列表", + "parameters": [ + { + "type": "integer", + "description": "活动ID", + "name": "activity_id", + "in": "path", + "required": true + }, + { + "type": "integer", + "description": "期ID", + "name": "issue_id", + "in": "path", + "required": true + }, + { + "type": "integer", + "default": 1, + "description": "页码", + "name": "page", + "in": "query", + "required": true + }, + { + "type": "integer", + "default": 20, + "description": "每页数量,最多100", + "name": "page_size", + "in": "query", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/app.listDrawLogsResponse" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/code.Failure" + } + } + } + } + }, + "/api/app/activities/{activity_id}/issues/{issue_id}/rewards": { + "get": { + "description": "获取指定期的奖励配置列表", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "APP端.活动" + ], + "summary": "奖励配置列表", + "parameters": [ + { + "type": "integer", + "description": "活动ID", + "name": "activity_id", + "in": "path", + "required": true + }, + { + "type": "integer", + "description": "期ID", + "name": "issue_id", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/app.listRewardsResponse" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/code.Failure" + } + } + } + } + }, + "/api/app/banners": { + "get": { + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "APP端.运营" + ], + "summary": "APP端轮播图列表", + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/app.listAppBannersResponse" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/code.Failure" + } + } + } + } + }, + "/api/app/guilds": { + "get": { + "description": "获取工会列表,支持公开与状态过滤以及分页", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "APP端.工会" + ], + "summary": "浏览工会列表", + "parameters": [ + { + "type": "string", + "description": "工会名称(模糊)", + "name": "name", + "in": "query" + }, + { + "type": "integer", + "description": "是否公开(1公开 2私有)", + "name": "is_open", + "in": "query" + }, + { + "type": "integer", + "description": "状态(1正常 2解散)", + "name": "status", + "in": "query" + }, + { + "type": "integer", + "description": "加入方式(1审核 2自动 3消费流水)", + "name": "join_mode", + "in": "query" + }, + { + "type": "integer", + "default": 1, + "description": "页码", + "name": "page", + "in": "query", + "required": true + }, + { + "type": "integer", + "default": 20, + "description": "每页数量,最多100", + "name": "page_size", + "in": "query", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/app.listGuildsResponse" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/code.Failure" + } + } + } + } + }, + "/api/app/guilds/{guild_id}": { + "get": { + "description": "查看指定工会详情", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "APP端.工会" + ], + "summary": "查看工会详情", + "parameters": [ + { + "type": "integer", + "description": "工会ID", + "name": "guild_id", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/model.Guild" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/code.Failure" + } + } + } + } + }, + "/api/app/guilds/{guild_id}/members": { + "get": { + "description": "查看指定工会的成员列表", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "APP端.工会" + ], + "summary": "查看工会成员", + "parameters": [ + { + "type": "integer", + "description": "工会ID", + "name": "guild_id", + "in": "path", + "required": true + }, + { + "type": "integer", + "default": 1, + "description": "页码", + "name": "page", + "in": "query", + "required": true + }, + { + "type": "integer", + "default": 20, + "description": "每页数量,最多100", + "name": "page_size", + "in": "query", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/app.listMembersResponse" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/code.Failure" + } + } + } + }, + "post": { + "description": "用户加入指定工会", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "APP端.工会" + ], + "summary": "加入工会", + "parameters": [ + { + "type": "integer", + "description": "工会ID", + "name": "guild_id", + "in": "path", + "required": true + }, + { + "description": "请求参数", + "name": "RequestBody", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/app.joinGuildRequest" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/app.simpleMessageResponse" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/code.Failure" + } + } + } + } + }, + "/api/app/guilds/{guild_id}/members/{user_id}": { + "delete": { + "description": "用户离开指定工会", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "APP端.工会" + ], + "summary": "离开工会", + "parameters": [ + { + "type": "integer", + "description": "工会ID", + "name": "guild_id", + "in": "path", + "required": true + }, + { + "type": "integer", + "description": "用户ID", + "name": "user_id", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/app.simpleMessageResponse" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/code.Failure" + } + } + } + } + }, + "/api/app/users/phone/login": { + "post": { + "description": "使用手机号登录,沿用 code 字段承载手机号或手机号授权码", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "APP端.用户" + ], + "summary": "手机号登录", "parameters": [ { "description": "请求参数", @@ -1284,7 +3182,7 @@ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/message.userSendMessageRequest" + "$ref": "#/definitions/app.phoneLoginRequest" } } ], @@ -1292,7 +3190,7 @@ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/message.userSendMessageResponse" + "$ref": "#/definitions/app.phoneLoginResponse" } }, "400": { @@ -1304,9 +3202,9 @@ } } }, - "/api/app/user/create": { + "/api/app/users/weixin/login": { "post": { - "description": "新增小程序用户", + "description": "微信静默登录(需传递 code;可选 invite_code)", "consumes": [ "application/json" ], @@ -1314,9 +3212,9 @@ "application/json" ], "tags": [ - "用户端" + "APP端.用户" ], - "summary": "新增小程序用户", + "summary": "微信登录", "parameters": [ { "description": "请求参数", @@ -1324,7 +3222,7 @@ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/app.createAppUserRequest" + "$ref": "#/definitions/app.weixinLoginRequest" } } ], @@ -1332,7 +3230,7 @@ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/app.createAppUserResponse" + "$ref": "#/definitions/app.weixinLoginResponse" } }, "400": { @@ -1344,9 +3242,9 @@ } } }, - "/api/wechat/miniprogram/login": { - "post": { - "description": "通过AppID和code获取用户的openid,系统自动生成用户名和头像", + "/api/app/users/{user_id}": { + "put": { + "description": "修改用户昵称与头像", "consumes": [ "application/json" ], @@ -1354,17 +3252,24 @@ "application/json" ], "tags": [ - "微信" + "APP端.用户" ], - "summary": "小程序登录", + "summary": "修改用户信息", "parameters": [ + { + "type": "integer", + "description": "用户ID", + "name": "user_id", + "in": "path", + "required": true + }, { "description": "请求参数", - "name": "request", + "name": "RequestBody", "in": "body", "required": true, "schema": { - "$ref": "#/definitions/wechat.miniprogramLoginRequest" + "$ref": "#/definitions/app.modifyUserRequest" } } ], @@ -1372,7 +3277,7 @@ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/wechat.miniprogramLoginResponse" + "$ref": "#/definitions/app.modifyUserResponse" } }, "400": { @@ -1380,19 +3285,13 @@ "schema": { "$ref": "#/definitions/code.Failure" } - }, - "500": { - "description": "Internal Server Error", - "schema": { - "$ref": "#/definitions/code.Failure" - } } } } }, - "/api/wechat/qrcode": { - "post": { - "description": "根据 AppID、AppSecret 和页面路径生成微信小程序二维码", + "/api/app/users/{user_id}/coupons": { + "get": { + "description": "查看用户持有的优惠券列表", "consumes": [ "application/json" ], @@ -1400,25 +3299,39 @@ "application/json" ], "tags": [ - "微信" + "APP端.用户" ], - "summary": "生成微信小程序二维码", + "summary": "查看用户优惠券", "parameters": [ { - "description": "请求参数", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/wechat.generateQRCodeRequest" - } + "type": "integer", + "description": "用户ID", + "name": "user_id", + "in": "path", + "required": true + }, + { + "type": "integer", + "default": 1, + "description": "页码", + "name": "page", + "in": "query", + "required": true + }, + { + "type": "integer", + "default": 20, + "description": "每页数量,最多100", + "name": "page_size", + "in": "query", + "required": true } ], "responses": { "200": { "description": "OK", "schema": { - "$ref": "#/definitions/wechat.generateQRCodeResponse" + "$ref": "#/definitions/app.listCouponsResponse" } }, "400": { @@ -1426,19 +3339,13 @@ "schema": { "$ref": "#/definitions/code.Failure" } - }, - "500": { - "description": "Internal Server Error", - "schema": { - "$ref": "#/definitions/code.Failure" - } } } } }, - "/api/wechat/subscribe": { - "post": { - "description": "根据模板ID发送订阅消息", + "/api/app/users/{user_id}/invites": { + "get": { + "description": "查看被该用户邀请的用户列表", "consumes": [ "application/json" ], @@ -1446,25 +3353,39 @@ "application/json" ], "tags": [ - "微信" + "APP端.用户" ], - "summary": "发送订阅消息", + "summary": "查看用户邀请记录", "parameters": [ { - "description": "请求参数", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/wechat.sendSubscribeMessageRequest" - } + "type": "integer", + "description": "用户ID", + "name": "user_id", + "in": "path", + "required": true + }, + { + "type": "integer", + "default": 1, + "description": "页码", + "name": "page", + "in": "query", + "required": true + }, + { + "type": "integer", + "default": 20, + "description": "每页数量,最多100", + "name": "page_size", + "in": "query", + "required": true } ], "responses": { "200": { "description": "OK", "schema": { - "$ref": "#/definitions/wechat.sendSubscribeMessageResponse" + "$ref": "#/definitions/app.listInvitesResponse" } }, "400": { @@ -1472,25 +3393,13 @@ "schema": { "$ref": "#/definitions/code.Failure" } - }, - "404": { - "description": "Not Found", - "schema": { - "$ref": "#/definitions/code.Failure" - } - }, - "500": { - "description": "Internal Server Error", - "schema": { - "$ref": "#/definitions/code.Failure" - } } } } }, - "/api/wechat/template": { - "post": { - "description": "根据 AppID 获取微信小程序的模板ID", + "/api/app/users/{user_id}/item_cards": { + "get": { + "description": "获取指定用户的道具卡列表,支持分页", "consumes": [ "application/json" ], @@ -1498,25 +3407,163 @@ "application/json" ], "tags": [ - "微信" + "APP端.用户" ], - "summary": "获取微信小程序模板ID", + "summary": "获取用户道具卡列表", "parameters": [ { - "description": "请求参数", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/wechat.templateRequest" - } + "type": "integer", + "description": "用户ID", + "name": "user_id", + "in": "path", + "required": true + }, + { + "type": "integer", + "description": "页码,默认1", + "name": "page", + "in": "query" + }, + { + "type": "integer", + "description": "每页条数,默认10", + "name": "page_size", + "in": "query" } ], "responses": { "200": { "description": "OK", "schema": { - "$ref": "#/definitions/wechat.templateResponse" + "$ref": "#/definitions/app.listUserItemCardsResponse" + } + }, + "400": { + "description": "参数错误", + "schema": { + "$ref": "#/definitions/code.Failure" + } + }, + "401": { + "description": "未授权", + "schema": { + "$ref": "#/definitions/code.Failure" + } + }, + "500": { + "description": "服务器内部错误", + "schema": { + "$ref": "#/definitions/code.Failure" + } + } + } + } + }, + "/api/app/users/{user_id}/item_cards/uses": { + "get": { + "description": "获取指定用户的道具卡使用记录,支持分页", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "APP端.用户" + ], + "summary": "获取用户道具卡使用记录", + "parameters": [ + { + "type": "integer", + "description": "用户ID", + "name": "user_id", + "in": "path", + "required": true + }, + { + "type": "integer", + "description": "页码,默认1", + "name": "page", + "in": "query" + }, + { + "type": "integer", + "description": "每页条数,默认10", + "name": "page_size", + "in": "query" + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/app.listUserItemCardUsesResponse" + } + }, + "400": { + "description": "参数错误", + "schema": { + "$ref": "#/definitions/code.Failure" + } + }, + "401": { + "description": "未授权", + "schema": { + "$ref": "#/definitions/code.Failure" + } + }, + "500": { + "description": "服务器内部错误", + "schema": { + "$ref": "#/definitions/code.Failure" + } + } + } + } + }, + "/api/app/users/{user_id}/orders": { + "get": { + "description": "查看用户抽奖来源订单记录", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "APP端.用户" + ], + "summary": "查看用户订单记录", + "parameters": [ + { + "type": "integer", + "description": "用户ID", + "name": "user_id", + "in": "path", + "required": true + }, + { + "type": "integer", + "default": 1, + "description": "页码", + "name": "page", + "in": "query", + "required": true + }, + { + "type": "integer", + "default": 20, + "description": "每页数量,最多100", + "name": "page_size", + "in": "query", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/app.listOrdersResponse" } }, "400": { @@ -1524,24 +3571,551 @@ "schema": { "$ref": "#/definitions/code.Failure" } + } + } + } + }, + "/api/app/users/{user_id}/phone/bind": { + "post": { + "description": "使用微信手机号 code 换取手机号并绑定到指定用户", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "APP端.用户" + ], + "summary": "绑定手机号", + "parameters": [ + { + "type": "integer", + "description": "用户ID", + "name": "user_id", + "in": "path", + "required": true }, - "404": { - "description": "Not Found", + { + "description": "请求参数", + "name": "RequestBody", + "in": "body", + "required": true, "schema": { - "$ref": "#/definitions/code.Failure" + "$ref": "#/definitions/app.bindPhoneRequest" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/app.bindPhoneResponse" } }, - "500": { - "description": "Internal Server Error", + "400": { + "description": "Bad Request", "schema": { "$ref": "#/definitions/code.Failure" } } } } + }, + "/api/app/users/{user_id}/points": { + "get": { + "description": "查看用户积分流水记录", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "APP端.用户" + ], + "summary": "查看用户积分记录", + "parameters": [ + { + "type": "integer", + "description": "用户ID", + "name": "user_id", + "in": "path", + "required": true + }, + { + "type": "integer", + "default": 1, + "description": "页码", + "name": "page", + "in": "query", + "required": true + }, + { + "type": "integer", + "default": 20, + "description": "每页数量,最多100", + "name": "page_size", + "in": "query", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/app.listPointsResponse" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/code.Failure" + } + } + } + } + }, + "/api/app/users/{user_id}/points/balance": { + "get": { + "description": "查看用户积分余额(过滤过期积分)", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "APP端.用户" + ], + "summary": "查看用户积分余额", + "parameters": [ + { + "type": "integer", + "description": "用户ID", + "name": "user_id", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/app.pointsBalanceResponse" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/code.Failure" + } + } + } + } + }, + "/api/role/list": { + "get": { + "security": [ + { + "LoginVerifyToken": [] + } + ], + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "管理端.系统" + ], + "summary": "角色列表", + "parameters": [ + { + "type": "integer", + "default": 1, + "description": "页码", + "name": "current", + "in": "query", + "required": true + }, + { + "type": "integer", + "default": 20, + "description": "每页数量", + "name": "size", + "in": "query", + "required": true + }, + { + "type": "string", + "description": "角色名称", + "name": "roleName", + "in": "query" + }, + { + "type": "string", + "description": "角色编码", + "name": "roleCode", + "in": "query" + }, + { + "type": "boolean", + "description": "是否启用", + "name": "enabled", + "in": "query" + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/admin.roleListResponse" + } + } + } + } + }, + "/api/user/list": { + "get": { + "security": [ + { + "LoginVerifyToken": [] + } + ], + "description": "返回系统用户分页数据", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "管理端.系统" + ], + "summary": "系统用户列表", + "parameters": [ + { + "type": "integer", + "default": 1, + "description": "页码", + "name": "current", + "in": "query", + "required": true + }, + { + "type": "integer", + "default": 20, + "description": "每页数量", + "name": "size", + "in": "query", + "required": true + }, + { + "type": "string", + "description": "用户名", + "name": "userName", + "in": "query" + }, + { + "type": "string", + "description": "邮箱", + "name": "userEmail", + "in": "query" + }, + { + "type": "string", + "description": "手机号", + "name": "userPhone", + "in": "query" + }, + { + "type": "string", + "description": "状态", + "name": "status", + "in": "query" + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/admin.userListResponse" + } + } + } + } + }, + "/api/v3/system/menus/simple": { + "get": { + "responses": {} + } } }, "definitions": { + "admin.GrantRewardRequest": { + "type": "object", + "required": [ + "product_id" + ], + "properties": { + "activity_id": { + "description": "活动ID(可选)", + "type": "integer" + }, + "address_id": { + "description": "收货地址ID(可选,实物商品需要)", + "type": "integer" + }, + "product_id": { + "description": "商品ID", + "type": "integer" + }, + "quantity": { + "description": "发放数量", + "type": "integer", + "minimum": 1 + }, + "remark": { + "description": "备注", + "type": "string" + }, + "reward_id": { + "description": "奖励配置ID(可选)", + "type": "integer" + } + } + }, + "admin.GrantRewardResponse": { + "type": "object", + "properties": { + "inventory_ids": { + "type": "array", + "items": { + "type": "integer" + } + }, + "message": { + "type": "string" + }, + "order_id": { + "type": "integer" + }, + "success": { + "type": "boolean" + } + } + }, + "admin.activitysvcIssueData": { + "type": "object", + "properties": { + "id": { + "type": "integer" + }, + "issue_number": { + "type": "string" + }, + "sort": { + "type": "integer" + }, + "status": { + "type": "integer" + } + } + }, + "admin.addCouponRequest": { + "type": "object", + "required": [ + "coupon_id" + ], + "properties": { + "coupon_id": { + "type": "integer" + } + } + }, + "admin.addCouponResponse": { + "type": "object", + "properties": { + "success": { + "type": "boolean" + } + } + }, + "admin.addPointsRequest": { + "type": "object", + "required": [ + "points" + ], + "properties": { + "kind": { + "type": "string" + }, + "points": { + "type": "integer" + }, + "remark": { + "type": "string" + }, + "valid_days": { + "type": "integer" + } + } + }, + "admin.addPointsResponse": { + "type": "object", + "properties": { + "success": { + "type": "boolean" + } + } + }, + "admin.adminUserCouponItem": { + "type": "object", + "properties": { + "coupon_id": { + "type": "integer" + }, + "discount_type": { + "type": "integer" + }, + "discount_value": { + "type": "integer" + }, + "id": { + "type": "integer" + }, + "min_spend": { + "type": "integer" + }, + "name": { + "type": "string" + }, + "scope_type": { + "type": "integer" + }, + "status": { + "type": "integer" + }, + "used_at": { + "type": "string" + }, + "used_order_id": { + "type": "integer" + }, + "valid_end": { + "type": "string" + }, + "valid_start": { + "type": "string" + } + } + }, + "admin.adminUserItem": { + "type": "object", + "properties": { + "avatar": { + "type": "string" + }, + "created_at": { + "type": "string" + }, + "id": { + "type": "integer" + }, + "invite_code": { + "type": "string" + }, + "inviter_id": { + "type": "integer" + }, + "nickname": { + "type": "string" + } + } + }, + "admin.assignItemCardRequest": { + "type": "object", + "required": [ + "card_id" + ], + "properties": { + "card_id": { + "type": "integer" + }, + "quantity": { + "type": "integer" + } + } + }, + "admin.bannerItem": { + "type": "object", + "properties": { + "id": { + "type": "integer" + }, + "image_url": { + "type": "string" + }, + "link_url": { + "type": "string" + }, + "sort": { + "type": "integer" + }, + "status": { + "type": "integer" + }, + "title": { + "type": "string" + } + } + }, + "admin.categoryItem": { + "type": "object", + "properties": { + "id": { + "type": "integer" + }, + "name": { + "type": "string" + } + } + }, + "admin.createActivityRequest": { + "type": "object", + "required": [ + "activity_category_id", + "name" + ], + "properties": { + "activity_category_id": { + "type": "integer" + }, + "banner": { + "type": "string" + }, + "end_time": { + "type": "string" + }, + "is_boss": { + "type": "integer" + }, + "name": { + "type": "string" + }, + "price_draw": { + "type": "integer" + }, + "start_time": { + "type": "string" + }, + "status": { + "type": "integer" + } + } + }, "admin.createAdminRequest": { "type": "object", "required": [ @@ -1581,6 +4155,249 @@ } } }, + "admin.createBannerRequest": { + "type": "object", + "required": [ + "image_url", + "title" + ], + "properties": { + "image_url": { + "type": "string" + }, + "link_url": { + "type": "string" + }, + "sort": { + "type": "integer" + }, + "status": { + "type": "integer" + }, + "title": { + "type": "string" + } + } + }, + "admin.createBannerResponse": { + "type": "object", + "properties": { + "id": { + "type": "integer" + }, + "message": { + "type": "string" + } + } + }, + "admin.createGuildRequest": { + "type": "object", + "required": [ + "name", + "owner_id" + ], + "properties": { + "avatar_url": { + "type": "string" + }, + "consume_limit": { + "type": "integer" + }, + "description": { + "type": "string" + }, + "is_open": { + "type": "integer" + }, + "join_mode": { + "type": "integer" + }, + "name": { + "type": "string" + }, + "owner_id": { + "type": "integer" + } + } + }, + "admin.createGuildResponse": { + "type": "object", + "properties": { + "message": { + "type": "string" + } + } + }, + "admin.createIssueRequest": { + "type": "object", + "required": [ + "issue_number" + ], + "properties": { + "issue_number": { + "type": "string" + }, + "sort": { + "type": "integer" + }, + "status": { + "type": "integer" + } + } + }, + "admin.createItemCardRequest": { + "type": "object", + "required": [ + "card_type", + "effect_type", + "name", + "price", + "scope_type" + ], + "properties": { + "activity_category_id": { + "type": "integer" + }, + "activity_id": { + "type": "integer" + }, + "boost_rate_x1000": { + "type": "integer" + }, + "card_type": { + "type": "integer" + }, + "effect_type": { + "type": "integer" + }, + "issue_id": { + "type": "integer" + }, + "max_effect_value_x1000": { + "type": "integer" + }, + "name": { + "type": "string" + }, + "price": { + "type": "integer" + }, + "remark": { + "type": "string" + }, + "reward_multiplier_x1000": { + "type": "integer" + }, + "scope_type": { + "type": "integer" + }, + "stacking_strategy": { + "type": "integer" + }, + "status": { + "type": "integer" + }, + "valid_end_unix": { + "type": "integer" + }, + "valid_start_unix": { + "type": "integer" + } + } + }, + "admin.createItemCardResponse": { + "type": "object", + "properties": { + "id": { + "type": "integer" + }, + "message": { + "type": "string" + } + } + }, + "admin.createProductCategoryRequest": { + "type": "object", + "required": [ + "name" + ], + "properties": { + "name": { + "type": "string" + }, + "parent_id": { + "type": "integer" + }, + "status": { + "type": "integer" + } + } + }, + "admin.createProductCategoryResponse": { + "type": "object", + "properties": { + "id": { + "type": "integer" + }, + "message": { + "type": "string" + } + } + }, + "admin.createProductRequest": { + "type": "object", + "required": [ + "category_id", + "name", + "price", + "stock" + ], + "properties": { + "category_id": { + "type": "integer" + }, + "images_json": { + "type": "string" + }, + "name": { + "type": "string" + }, + "price": { + "type": "integer" + }, + "status": { + "type": "integer" + }, + "stock": { + "type": "integer" + } + } + }, + "admin.createProductResponse": { + "type": "object", + "properties": { + "id": { + "type": "integer" + }, + "message": { + "type": "string" + } + } + }, + "admin.createRewardsRequest": { + "type": "object", + "required": [ + "rewards" + ], + "properties": { + "rewards": { + "type": "array", + "items": { + "$ref": "#/definitions/admin.rewardItem" + } + } + } + }, "admin.deleteAdminRequest": { "type": "object", "required": [ @@ -1602,6 +4419,146 @@ } } }, + "admin.deleteGuildResponse": { + "type": "object", + "properties": { + "message": { + "type": "string" + } + } + }, + "admin.itemCardListItem": { + "type": "object", + "properties": { + "activity_category_id": { + "description": "指定活动分类ID(可空)", + "type": "integer" + }, + "activity_id": { + "description": "指定活动ID(可空)", + "type": "integer" + }, + "boost_rate_x1000": { + "description": "概率提升(千分比,+20%=200)", + "type": "integer" + }, + "card_type": { + "description": "卡类型:1双倍奖励 2概率提升 等", + "type": "integer" + }, + "created_at": { + "description": "创建时间", + "type": "string" + }, + "effect_type": { + "description": "效果类型:1奖励倍数 2概率提升 等", + "type": "integer" + }, + "id": { + "description": "主键ID", + "type": "integer" + }, + "issue_id": { + "description": "指定期ID(可空)", + "type": "integer" + }, + "max_effect_value_x1000": { + "description": "效果上限(千分比)", + "type": "integer" + }, + "name": { + "description": "卡名称", + "type": "string" + }, + "price": { + "description": "售卖价格(分)", + "type": "integer" + }, + "remark": { + "description": "备注", + "type": "string" + }, + "reward_multiplier_x1000": { + "description": "奖励倍数(千分比,×2=2000)", + "type": "integer" + }, + "scope_type": { + "description": "适用范围:1全局 2活动分类 3活动 4期", + "type": "integer" + }, + "stacking_strategy": { + "description": "叠加策略:1禁止 2同类叠加-上限 3取最大值 4乘法叠加", + "type": "integer" + }, + "status": { + "description": "状态:1启用 2停用", + "type": "integer" + }, + "updated_at": { + "description": "更新时间", + "type": "string" + }, + "valid_end": { + "description": "有效期结束", + "type": "string" + }, + "valid_start": { + "description": "有效期开始", + "type": "string" + } + } + }, + "admin.listBannersResponse": { + "type": "object", + "properties": { + "list": { + "type": "array", + "items": { + "$ref": "#/definitions/admin.bannerItem" + } + }, + "page": { + "type": "integer" + }, + "page_size": { + "type": "integer" + }, + "total": { + "type": "integer" + } + } + }, + "admin.listCategoriesResponse": { + "type": "object", + "properties": { + "list": { + "type": "array", + "items": { + "$ref": "#/definitions/admin.categoryItem" + } + } + } + }, + "admin.listCouponsResponse": { + "type": "object", + "properties": { + "list": { + "type": "array", + "items": { + "$ref": "#/definitions/admin.adminUserCouponItem" + } + }, + "page": { + "type": "integer" + }, + "page_size": { + "type": "integer" + }, + "total": { + "type": "integer" + } + } + }, "admin.listData": { "type": "object", "properties": { @@ -1635,6 +4592,186 @@ } } }, + "admin.listGuildMembersResponse": { + "type": "object", + "properties": { + "list": { + "type": "array", + "items": { + "$ref": "#/definitions/admin.memberItem" + } + }, + "page": { + "type": "integer" + }, + "page_size": { + "type": "integer" + }, + "total": { + "type": "integer" + } + } + }, + "admin.listInventoryResponse": { + "type": "object", + "properties": { + "list": { + "type": "array", + "items": { + "$ref": "#/definitions/user.InventoryWithProduct" + } + }, + "page": { + "type": "integer" + }, + "page_size": { + "type": "integer" + }, + "total": { + "type": "integer" + } + } + }, + "admin.listInvitesResponse": { + "type": "object", + "properties": { + "list": { + "type": "array", + "items": { + "$ref": "#/definitions/admin.adminUserItem" + } + }, + "page": { + "type": "integer" + }, + "page_size": { + "type": "integer" + }, + "total": { + "type": "integer" + } + } + }, + "admin.listIssuesResponse": { + "type": "object", + "properties": { + "list": { + "type": "array", + "items": { + "$ref": "#/definitions/admin.activitysvcIssueData" + } + }, + "page": { + "type": "integer" + }, + "page_size": { + "type": "integer" + }, + "total": { + "type": "integer" + } + } + }, + "admin.listItemCardsResponse": { + "type": "object", + "properties": { + "list": { + "type": "array", + "items": { + "$ref": "#/definitions/admin.itemCardListItem" + } + }, + "page": { + "type": "integer" + }, + "page_size": { + "type": "integer" + }, + "total": { + "type": "integer" + } + } + }, + "admin.listOrdersResponse": { + "type": "object", + "properties": { + "list": { + "type": "array", + "items": { + "$ref": "#/definitions/user.OrderWithItems" + } + }, + "page": { + "type": "integer" + }, + "page_size": { + "type": "integer" + }, + "total": { + "type": "integer" + } + } + }, + "admin.listPointsResponse": { + "type": "object", + "properties": { + "list": { + "type": "array", + "items": { + "$ref": "#/definitions/model.UserPointsLedger" + } + }, + "page": { + "type": "integer" + }, + "page_size": { + "type": "integer" + }, + "total": { + "type": "integer" + } + } + }, + "admin.listProductCategoriesResponse": { + "type": "object", + "properties": { + "list": { + "type": "array", + "items": { + "$ref": "#/definitions/admin.productCategoryListItem" + } + }, + "page": { + "type": "integer" + }, + "page_size": { + "type": "integer" + }, + "total": { + "type": "integer" + } + } + }, + "admin.listProductsResponse": { + "type": "object", + "properties": { + "list": { + "type": "array", + "items": { + "$ref": "#/definitions/admin.productItem" + } + }, + "page": { + "type": "integer" + }, + "page_size": { + "type": "integer" + }, + "total": { + "type": "integer" + } + } + }, "admin.listResponse": { "type": "object", "properties": { @@ -1658,6 +4795,37 @@ } } }, + "admin.listRewardsResponse": { + "type": "object", + "properties": { + "list": { + "type": "array", + "items": { + "$ref": "#/definitions/admin.rewardItem" + } + } + } + }, + "admin.listUsersResponse": { + "type": "object", + "properties": { + "list": { + "type": "array", + "items": { + "$ref": "#/definitions/admin.adminUserItem" + } + }, + "page": { + "type": "integer" + }, + "page_size": { + "type": "integer" + }, + "total": { + "type": "integer" + } + } + }, "admin.loginRequest": { "type": "object", "required": [ @@ -1688,6 +4856,52 @@ } } }, + "admin.memberItem": { + "type": "object", + "properties": { + "id": { + "type": "integer" + }, + "role": { + "type": "string" + }, + "start_time": { + "type": "string" + }, + "user_id": { + "type": "integer" + } + } + }, + "admin.modifyActivityRequest": { + "type": "object", + "properties": { + "activity_category_id": { + "type": "integer" + }, + "banner": { + "type": "string" + }, + "end_time": { + "type": "string" + }, + "is_boss": { + "type": "integer" + }, + "name": { + "type": "string" + }, + "price_draw": { + "type": "integer" + }, + "start_time": { + "type": "string" + }, + "status": { + "type": "integer" + } + } + }, "admin.modifyAdminRequest": { "type": "object", "required": [ @@ -1726,458 +4940,990 @@ } } }, - "admin.relAppRequest": { - "type": "object", - "required": [ - "ids" - ], - "properties": { - "ids": { - "description": "小程序编号(多个用,分割)", - "type": "string" - } - } - }, - "admin.relAppResponse": { + "admin.modifyBannerRequest": { "type": "object", "properties": { - "message": { - "description": "提示信息", - "type": "string" - } - } - }, - "app.adminSendMessageRequest": { - "type": "object", - "required": [ - "app_id", - "content", - "msg_type", - "to_user_id" - ], - "properties": { - "app_id": { - "description": "小程序ID", + "image_url": { "type": "string" }, - "content": { - "description": "内容", + "link_url": { "type": "string" }, - "msg_type": { - "description": "消息类型(1:文本 2:图片)", - "type": "integer" - }, - "to_user_id": { - "description": "接收用户ID", - "type": "string" - } - } - }, - "app.adminSendMessageResponse": { - "type": "object", - "properties": { - "message": { - "description": "提示信息", - "type": "string" - } - } - }, - "app.appMessagePageListResponse": { - "type": "object", - "properties": { - "list": { - "type": "array", - "items": { - "$ref": "#/definitions/app.listMessageData" - } - }, - "page": { - "description": "当前页码", - "type": "integer" - }, - "page_size": { - "description": "每页返回的数据量", - "type": "integer" - }, - "total": { - "description": "符合查询条件的总记录数", - "type": "integer" - } - } - }, - "app.checkAppStatusResponse": { - "type": "object", - "properties": { - "app_id": { - "description": "小程序ID", - "type": "string" - }, - "check_status_text": { - "description": "状态文字描述", - "type": "string" - }, - "code": { - "description": "外部接口返回的状态码", + "sort": { "type": "integer" }, "status": { - "description": "外部接口返回的状态", + "type": "integer" + }, + "title": { "type": "string" } } }, - "app.createAppRequest": { + "admin.modifyGuildRequest": { "type": "object", - "required": [ - "app_id", - "app_secret", - "name" - ], "properties": { - "app_id": { - "description": "小程序ID", + "avatar_url": { "type": "string" }, - "app_secret": { - "description": "小程序密钥", - "type": "string" - }, - "avatar": { - "description": "头像", - "type": "string" + "consume_limit": { + "type": "integer" }, "description": { - "description": "描述", + "type": "string" + }, + "is_open": { + "type": "integer" + }, + "join_mode": { + "type": "integer" + }, + "name": { + "type": "string" + }, + "status": { + "type": "integer" + } + } + }, + "admin.modifyGuildResponse": { + "type": "object", + "properties": { + "message": { + "type": "string" + } + } + }, + "admin.modifyIssueRequest": { + "type": "object", + "properties": { + "issue_number": { + "type": "string" + }, + "sort": { + "type": "integer" + }, + "status": { + "type": "integer" + } + } + }, + "admin.modifyItemCardRequest": { + "type": "object", + "properties": { + "activity_category_id": { + "type": "integer" + }, + "activity_id": { + "type": "integer" + }, + "boost_rate_x1000": { + "type": "integer" + }, + "card_type": { + "type": "integer" + }, + "effect_type": { + "type": "integer" + }, + "issue_id": { + "type": "integer" + }, + "max_effect_value_x1000": { + "type": "integer" + }, + "name": { + "type": "string" + }, + "price": { + "type": "integer" + }, + "remark": { + "type": "string" + }, + "reward_multiplier_x1000": { + "type": "integer" + }, + "scope_type": { + "type": "integer" + }, + "stacking_strategy": { + "type": "integer" + }, + "status": { + "type": "integer" + }, + "valid_end_unix": { + "type": "integer" + }, + "valid_start_unix": { + "type": "integer" + } + } + }, + "admin.modifyProductCategoryRequest": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "parent_id": { + "type": "integer" + }, + "status": { + "type": "integer" + } + } + }, + "admin.modifyProductRequest": { + "type": "object", + "properties": { + "category_id": { + "type": "integer" + }, + "images_json": { "type": "string" }, "name": { - "description": "名称", "type": "string" }, - "template_id": { - "description": "模版ID", - "type": "string" + "price": { + "type": "integer" + }, + "status": { + "type": "integer" + }, + "stock": { + "type": "integer" } } }, - "app.createAppResponse": { + "admin.modifyRewardRequest": { + "type": "object", + "properties": { + "is_boss": { + "type": "integer" + }, + "level": { + "type": "integer" + }, + "name": { + "type": "string" + }, + "original_qty": { + "type": "integer" + }, + "product_id": { + "type": "integer" + }, + "quantity": { + "type": "integer" + }, + "sort": { + "type": "integer" + }, + "weight": { + "type": "integer" + } + } + }, + "admin.pcSimpleMessage": { "type": "object", "properties": { "message": { - "description": "提示信息", "type": "string" } } }, - "app.createAppUserRequest": { + "admin.pointsBalanceResponse": { + "type": "object", + "properties": { + "balance": { + "type": "integer" + } + } + }, + "admin.productCategoryListItem": { + "type": "object", + "properties": { + "id": { + "type": "integer" + }, + "name": { + "type": "string" + }, + "parent_id": { + "type": "integer" + }, + "status": { + "type": "integer" + } + } + }, + "admin.productItem": { + "type": "object", + "properties": { + "category_id": { + "type": "integer" + }, + "id": { + "type": "integer" + }, + "images_json": { + "type": "string" + }, + "name": { + "type": "string" + }, + "price": { + "type": "integer" + }, + "sales": { + "type": "integer" + }, + "status": { + "type": "integer" + }, + "stock": { + "type": "integer" + } + } + }, + "admin.rewardItem": { "type": "object", "required": [ - "app_id", - "user_id", - "user_name" + "level", + "name", + "original_qty", + "quantity", + "weight" ], "properties": { - "app_id": { - "description": "小程序ID", - "type": "string" - }, - "user_avatar": { - "description": "用户头像", - "type": "string" - }, - "user_id": { - "description": "用户ID", - "type": "string" - }, - "user_mobile": { - "description": "用户手机号", - "type": "string" - }, - "user_name": { - "description": "用户昵称", - "type": "string" - } - } - }, - "app.createAppUserResponse": { - "type": "object", - "properties": { - "message": { - "description": "提示信息", - "type": "string" - } - } - }, - "app.deleteAppRequest": { - "type": "object", - "required": [ - "ids" - ], - "properties": { - "ids": { - "description": "小程序编号(多个用,分割)", - "type": "string" - } - } - }, - "app.deleteAppResponse": { - "type": "object", - "properties": { - "message": { - "description": "提示信息", - "type": "string" - } - } - }, - "app.latestMessageByAppIdResponse": { - "type": "object", - "properties": { - "list": { - "type": "array", - "items": { - "$ref": "#/definitions/app.latestMessageData" - } - }, - "page": { - "description": "当前页码", + "id": { "type": "integer" }, - "page_size": { - "description": "每页返回的数据量", + "is_boss": { "type": "integer" }, - "total": { - "description": "符合查询条件的总记录数", + "level": { + "type": "integer" + }, + "name": { + "type": "string" + }, + "original_qty": { + "type": "integer" + }, + "product_id": { + "type": "integer" + }, + "quantity": { + "type": "integer" + }, + "sort": { + "type": "integer" + }, + "weight": { "type": "integer" } } }, - "app.latestMessageData": { + "admin.roleItem": { "type": "object", "properties": { - "content": { - "description": "消息内容", - "type": "string" - }, - "msg_type": { - "description": "消息类型(1:文本 2:图片)", - "type": "integer" - }, - "send_time": { - "description": "发送时间", - "type": "string" - }, - "sender_avatar": { - "description": "发送人头像", - "type": "string" - }, - "sender_id": { - "description": "发送人ID", - "type": "string" - }, - "sender_name": { - "description": "发送人昵称", - "type": "string" - }, - "unread_count": { - "description": "未读消息数量", - "type": "integer" - } - } - }, - "app.listData": { - "type": "object", - "properties": { - "app_id": { - "description": "小程序ID", - "type": "string" - }, - "app_secret": { - "description": "小程序密钥", - "type": "string" - }, - "avatar": { - "description": "小程序头像", - "type": "string" - }, - "check_status_text": { - "description": "状态文字描述", - "type": "string" - }, - "created_at": { - "description": "创建时间", + "createTime": { "type": "string" }, "description": { - "description": "小程序描述", + "type": "string" + }, + "enabled": { + "type": "boolean" + }, + "roleCode": { + "type": "string" + }, + "roleId": { + "type": "integer" + }, + "roleName": { + "type": "string" + } + } + }, + "admin.roleListResponse": { + "type": "object", + "properties": { + "current": { + "type": "integer" + }, + "records": { + "type": "array", + "items": { + "$ref": "#/definitions/admin.roleItem" + } + }, + "size": { + "type": "integer" + }, + "total": { + "type": "integer" + } + } + }, + "admin.simpleMessage": { + "type": "object", + "properties": { + "message": { + "type": "string" + } + } + }, + "admin.simpleMessageResponse": { + "type": "object", + "properties": { + "message": { + "type": "string" + } + } + }, + "admin.userListItem": { + "type": "object", + "properties": { + "avatar": { + "type": "string" + }, + "createBy": { + "type": "string" + }, + "createTime": { "type": "string" }, "id": { - "description": "小程序编号", "type": "integer" }, - "message_total": { - "description": "消息总数", - "type": "integer" - }, - "name": { - "description": "小程序名称", + "nickName": { "type": "string" }, - "template_id": { - "description": "模版ID", + "status": { "type": "string" }, - "updated_at": { - "description": "更新时间", + "updateBy": { "type": "string" + }, + "updateTime": { + "type": "string" + }, + "userEmail": { + "type": "string" + }, + "userGender": { + "type": "string" + }, + "userName": { + "type": "string" + }, + "userPhone": { + "type": "string" + }, + "userRoles": { + "type": "array", + "items": { + "type": "string" + } } } }, - "app.listMessageData": { + "admin.userListResponse": { "type": "object", "properties": { - "content": { - "description": "消息内容", + "current": { + "type": "integer" + }, + "records": { + "type": "array", + "items": { + "$ref": "#/definitions/admin.userListItem" + } + }, + "size": { + "type": "integer" + }, + "total": { + "type": "integer" + } + } + }, + "app.activityItem": { + "type": "object", + "properties": { + "activity_category_id": { + "type": "integer" + }, + "banner": { + "type": "string" + }, + "category_name": { "type": "string" }, "id": { - "description": "消息ID", - "type": "string" - }, - "msg_type": { - "description": "消息类型(1:文本 2:图片)", "type": "integer" }, - "receiver_id": { - "description": "接收人ID", + "is_boss": { + "type": "integer" + }, + "name": { "type": "string" }, - "send_time": { - "description": "发送时间", + "price_draw": { + "type": "integer" + }, + "status": { + "type": "integer" + } + } + }, + "app.appBannerItem": { + "type": "object", + "properties": { + "id": { + "type": "integer" + }, + "image_url": { "type": "string" }, - "sender_id": { - "description": "发送人ID", + "link_url": { "type": "string" }, - "sender_name": { - "description": "发送人昵称", + "sort": { + "type": "integer" + }, + "title": { "type": "string" } } }, - "app.listResponse": { + "app.bindPhoneRequest": { + "type": "object", + "properties": { + "code": { + "type": "string" + } + } + }, + "app.bindPhoneResponse": { + "type": "object", + "properties": { + "mobile": { + "type": "string" + }, + "success": { + "type": "boolean" + } + } + }, + "app.drawLogItem": { + "type": "object", + "properties": { + "current_level": { + "type": "integer" + }, + "id": { + "type": "integer" + }, + "is_winner": { + "type": "integer" + }, + "issue_id": { + "type": "integer" + }, + "level": { + "type": "integer" + }, + "order_id": { + "type": "integer" + }, + "reward_id": { + "type": "integer" + }, + "user_id": { + "type": "integer" + } + } + }, + "app.guildItem": { + "type": "object", + "properties": { + "avatar_url": { + "type": "string" + }, + "consume_limit": { + "type": "integer" + }, + "description": { + "type": "string" + }, + "id": { + "type": "integer" + }, + "is_open": { + "type": "integer" + }, + "join_mode": { + "type": "integer" + }, + "name": { + "type": "string" + }, + "owner_id": { + "type": "integer" + }, + "status": { + "type": "integer" + } + } + }, + "app.inviteUserItem": { + "type": "object", + "properties": { + "avatar": { + "type": "string" + }, + "id": { + "type": "integer" + }, + "invite_code": { + "type": "string" + }, + "nickname": { + "type": "string" + } + } + }, + "app.issueItem": { + "type": "object", + "properties": { + "id": { + "type": "integer" + }, + "issue_number": { + "type": "string" + }, + "sort": { + "type": "integer" + }, + "status": { + "type": "integer" + } + } + }, + "app.joinGuildRequest": { + "type": "object", + "required": [ + "user_id" + ], + "properties": { + "user_id": { + "type": "integer" + } + } + }, + "app.listActivitiesResponse": { "type": "object", "properties": { "list": { "type": "array", "items": { - "$ref": "#/definitions/app.listData" + "$ref": "#/definitions/app.activityItem" } }, "page": { - "description": "当前页码", "type": "integer" }, "page_size": { - "description": "每页返回的数据量", "type": "integer" }, "total": { - "description": "符合查询条件的总记录数", "type": "integer" } } }, - "app.modifyAppRequest": { + "app.listAppBannersResponse": { "type": "object", - "required": [ - "app_id", - "app_secret", - "name" - ], "properties": { - "app_id": { - "description": "小程序ID", - "type": "string" - }, - "app_secret": { - "description": "小程序密钥", - "type": "string" - }, - "avatar": { - "description": "头像", - "type": "string" - }, - "description": { - "description": "描述", - "type": "string" - }, - "name": { - "description": "名称", - "type": "string" - }, - "template_id": { - "description": "模版ID", - "type": "string" + "list": { + "type": "array", + "items": { + "$ref": "#/definitions/app.appBannerItem" + } } } }, - "app.modifyAppResponse": { + "app.listCouponsResponse": { "type": "object", "properties": { - "message": { - "description": "提示信息", - "type": "string" + "list": { + "type": "array", + "items": { + "$ref": "#/definitions/model.UserCoupons" + } + }, + "page": { + "type": "integer" + }, + "page_size": { + "type": "integer" + }, + "total": { + "type": "integer" } } }, - "app.userListData": { + "app.listDrawLogsResponse": { "type": "object", "properties": { - "created_at": { - "description": "创建时间", + "list": { + "type": "array", + "items": { + "$ref": "#/definitions/app.drawLogItem" + } + }, + "page": { + "type": "integer" + }, + "page_size": { + "type": "integer" + }, + "total": { + "type": "integer" + } + } + }, + "app.listGuildsResponse": { + "type": "object", + "properties": { + "list": { + "type": "array", + "items": { + "$ref": "#/definitions/app.guildItem" + } + }, + "page": { + "type": "integer" + }, + "page_size": { + "type": "integer" + }, + "total": { + "type": "integer" + } + } + }, + "app.listInvitesResponse": { + "type": "object", + "properties": { + "list": { + "type": "array", + "items": { + "$ref": "#/definitions/app.inviteUserItem" + } + }, + "page": { + "type": "integer" + }, + "page_size": { + "type": "integer" + }, + "total": { + "type": "integer" + } + } + }, + "app.listIssuesResponse": { + "type": "object", + "properties": { + "list": { + "type": "array", + "items": { + "$ref": "#/definitions/app.issueItem" + } + }, + "page": { + "type": "integer" + }, + "page_size": { + "type": "integer" + }, + "total": { + "type": "integer" + } + } + }, + "app.listMembersResponse": { + "type": "object", + "properties": { + "list": { + "type": "array", + "items": { + "$ref": "#/definitions/app.memberItem" + } + }, + "page": { + "type": "integer" + }, + "page_size": { + "type": "integer" + }, + "total": { + "type": "integer" + } + } + }, + "app.listOrdersResponse": { + "type": "object", + "properties": { + "list": { + "type": "array", + "items": { + "$ref": "#/definitions/model.Orders" + } + }, + "page": { + "type": "integer" + }, + "page_size": { + "type": "integer" + }, + "total": { + "type": "integer" + } + } + }, + "app.listPointsResponse": { + "type": "object", + "properties": { + "list": { + "type": "array", + "items": { + "$ref": "#/definitions/model.UserPointsLedger" + } + }, + "page": { + "type": "integer" + }, + "page_size": { + "type": "integer" + }, + "total": { + "type": "integer" + } + } + }, + "app.listRewardsResponse": { + "type": "object", + "properties": { + "list": { + "type": "array", + "items": { + "$ref": "#/definitions/app.rewardItem" + } + } + } + }, + "app.listUserItemCardUsesResponse": { + "type": "object", + "properties": { + "list": { + "type": "array", + "items": { + "$ref": "#/definitions/model.ActivityDrawEffects" + } + }, + "page": { + "type": "integer" + }, + "page_size": { + "type": "integer" + }, + "total": { + "type": "integer" + } + } + }, + "app.listUserItemCardsResponse": { + "type": "object", + "properties": { + "list": { + "type": "array", + "items": { + "$ref": "#/definitions/model.UserItemCards" + } + }, + "page": { + "type": "integer" + }, + "page_size": { + "type": "integer" + }, + "total": { + "type": "integer" + } + } + }, + "app.memberItem": { + "type": "object", + "properties": { + "id": { + "type": "integer" + }, + "role": { "type": "string" }, - "user_avatar": { - "description": "用户头像", + "start_time": { "type": "string" }, "user_id": { - "description": "用户ID", + "type": "integer" + } + } + }, + "app.modifyUserRequest": { + "type": "object", + "properties": { + "avatar": { "type": "string" }, - "user_mobile": { - "description": "用户手机号", - "type": "string" - }, - "user_name": { - "description": "用户昵称", + "nickname": { "type": "string" } } }, - "app.userListResponse": { + "app.modifyUserResponse": { "type": "object", "properties": { - "list": { - "type": "array", - "items": { - "$ref": "#/definitions/app.userListData" - } + "user": { + "$ref": "#/definitions/app.userItem" + } + } + }, + "app.phoneLoginRequest": { + "type": "object", + "properties": { + "code": { + "description": "兼容参数名:这里作为手机号或第三方手机号code", + "type": "string" }, - "page": { - "description": "当前页码", + "invite_code": { + "type": "string" + } + } + }, + "app.phoneLoginResponse": { + "type": "object", + "properties": { + "avatar": { + "type": "string" + }, + "invite_code": { + "type": "string" + }, + "nickname": { + "type": "string" + }, + "user_id": { + "type": "integer" + } + } + }, + "app.pointsBalanceResponse": { + "type": "object", + "properties": { + "balance": { + "type": "integer" + } + } + }, + "app.rewardItem": { + "type": "object", + "properties": { + "is_boss": { "type": "integer" }, - "page_size": { - "description": "每页返回的数据量", + "level": { "type": "integer" }, - "total": { - "description": "符合查询条件的总记录数", + "name": { + "type": "string" + }, + "original_qty": { + "type": "integer" + }, + "product_id": { + "type": "integer" + }, + "quantity": { + "type": "integer" + }, + "sort": { + "type": "integer" + }, + "weight": { + "type": "integer" + } + } + }, + "app.simpleMessageResponse": { + "type": "object", + "properties": { + "message": { + "type": "string" + } + } + }, + "app.userItem": { + "type": "object", + "properties": { + "avatar": { + "type": "string" + }, + "id": { + "type": "integer" + }, + "invite_code": { + "type": "string" + }, + "inviter_id": { + "type": "integer" + }, + "nickname": { + "type": "string" + } + } + }, + "app.weixinLoginRequest": { + "type": "object", + "properties": { + "code": { + "type": "string" + }, + "invite_code": { + "type": "string" + } + } + }, + "app.weixinLoginResponse": { + "type": "object", + "properties": { + "avatar": { + "type": "string" + }, + "invite_code": { + "type": "string" + }, + "nickname": { + "type": "string" + }, + "user_id": { "type": "integer" } } @@ -2195,524 +5941,561 @@ } } }, - "keyword.createKeywordMaterialRequest": { - "type": "object", - "required": [ - "material_list" - ], - "properties": { - "material_list": { - "description": "素材列表", - "type": "array", - "items": { - "$ref": "#/definitions/keyword.keywordMaterial" - } - } - } - }, - "keyword.createKeywordMaterialResponse": { + "model.Activities": { "type": "object", "properties": { - "message": { - "description": "提示信息", - "type": "string" - } - } - }, - "keyword.createKeywordRequest": { - "type": "object", - "required": [ - "app_id", - "keyword" - ], - "properties": { - "app_id": { - "description": "小程序ID", - "type": "string" - }, - "keyword": { - "description": "关键字", - "type": "string" - } - } - }, - "keyword.createKeywordResponse": { - "type": "object", - "properties": { - "id": { - "description": "关键字ID", + "activity_category_id": { + "description": "活动所属分类ID(activity_categories.id,可空)", "type": "integer" }, - "message": { - "description": "提示信息", - "type": "string" - } - } - }, - "keyword.deleteKeywordResponse": { - "type": "object", - "properties": { - "message": { - "description": "提示信息", - "type": "string" - } - } - }, - "keyword.keywordListData": { - "type": "object", - "properties": { - "app_id": { - "description": "小程序ID", + "banner": { + "description": "活动横幅/海报URL", "type": "string" }, "created_at": { "description": "创建时间", "type": "string" }, - "created_user": { - "description": "创建人", - "type": "string" - }, - "id": { - "description": "关键字编号", - "type": "integer" - }, - "keyword": { - "description": "意图关键字", - "type": "string" - }, - "material_type_count": { - "description": "素材类型数量", - "type": "string" - }, - "updated_at": { - "description": "更新时间", - "type": "string" - }, - "updated_user": { - "description": "更新人", - "type": "string" - } - } - }, - "keyword.keywordMaterial": { - "type": "object", - "required": [ - "content", - "interval_seconds", - "type" - ], - "properties": { - "content": { - "description": "素材内容", - "type": "string" - }, - "interval_seconds": { - "description": "发送间隔时间(单位:秒)", - "type": "integer" - }, - "type": { - "description": "素材类型(1:文本 2:图片)", - "type": "integer" - } - } - }, - "keyword.keywordMaterialListData": { - "type": "object", - "properties": { - "content": { - "description": "素材内容", - "type": "string" - }, - "created_at": { - "description": "创建时间", - "type": "string" - }, - "created_user": { - "description": "创建人", + "end_time": { + "description": "结束时间", "type": "string" }, "id": { "description": "主键ID", "type": "integer" }, - "interval_seconds": { - "description": "素材发送间隔时间(单位:秒)", + "is_boss": { + "description": "Boss: 1 是 0 不是", "type": "integer" }, - "keyword_id": { - "description": "意图关键字ID", - "type": "integer" - }, - "type": { - "description": "素材类型(1:文本 2:图片)", - "type": "integer" - } - } - }, - "keyword.keywordMaterialPageListResponse": { - "type": "object", - "properties": { - "list": { - "type": "array", - "items": { - "$ref": "#/definitions/keyword.keywordMaterialListData" - } - }, - "page": { - "description": "当前页码", - "type": "integer" - }, - "page_size": { - "description": "每页返回的数据量", - "type": "integer" - }, - "total": { - "description": "符合查询条件的总记录数", - "type": "integer" - } - } - }, - "keyword.keywordPageListResponse": { - "type": "object", - "properties": { - "list": { - "type": "array", - "items": { - "$ref": "#/definitions/keyword.keywordListData" - } - }, - "page": { - "description": "当前页码", - "type": "integer" - }, - "page_size": { - "description": "每页返回的数据量", - "type": "integer" - }, - "total": { - "description": "符合查询条件的总记录数", - "type": "integer" - } - } - }, - "keyword.modifyKeywordMaterialRequest": { - "type": "object", - "required": [ - "content", - "interval_seconds", - "type" - ], - "properties": { - "content": { - "description": "素材内容", + "name": { + "description": "活动名称", "type": "string" }, - "interval_seconds": { - "description": "发送间隔时间(单位:秒)", + "price_draw": { + "description": "活动门票价格", "type": "integer" }, - "type": { - "description": "素材类型(1:文本 2:图片)", + "start_time": { + "description": "开始时间", + "type": "string" + }, + "status": { + "description": "状态:1进行中 2下线", "type": "integer" - } - } - }, - "keyword.modifyKeywordMaterialResponse": { - "type": "object", - "properties": { - "message": { - "description": "提示信息", + }, + "updated_at": { + "description": "更新时间", "type": "string" } } }, - "keyword.modifyKeywordRequest": { + "model.ActivityDrawEffects": { "type": "object", - "required": [ - "keyword" - ], "properties": { - "keyword": { - "description": "意图关键字", + "activity_category_id": { + "description": "范围快照-活动分类ID", + "type": "integer" + }, + "activity_id": { + "description": "范围快照-活动ID", + "type": "integer" + }, + "applied": { + "description": "是否生效:0否 1是", + "type": "integer" + }, + "card_type": { + "description": "卡类型快照", + "type": "integer" + }, + "created_at": { + "description": "创建时间", "type": "string" - } - } - }, - "keyword.modifyKeywordResponse": { - "type": "object", - "properties": { - "message": { - "description": "提示信息", + }, + "draw_log_id": { + "description": "抽奖日志ID(activity_draw_logs.id)", + "type": "integer" + }, + "effect_type": { + "description": "效果类型快照", + "type": "integer" + }, + "id": { + "description": "主键ID", + "type": "integer" + }, + "issue_id": { + "description": "范围快照-期ID", + "type": "integer" + }, + "probability_delta_x1000": { + "description": "概率相对增益(千分比)", + "type": "integer" + }, + "remark": { + "description": "备注", "type": "string" - } - } - }, - "message.appMessagePageListResponse": { - "type": "object", - "properties": { - "list": { - "type": "array", - "items": { - "$ref": "#/definitions/message.listMessageData" - } }, - "page": { - "description": "当前页码", + "reward_multiplier_x1000": { + "description": "奖励倍数(千分比)", "type": "integer" }, - "page_size": { - "description": "每页返回的数据量", + "scope_type": { + "description": "适用范围快照", "type": "integer" }, - "total": { - "description": "符合查询条件的总记录数", + "system_item_card_id": { + "description": "卡模板ID(system_item_cards.id)", + "type": "integer" + }, + "user_id": { + "description": "用户ID(users.id)", + "type": "integer" + }, + "user_item_card_id": { + "description": "用户卡实例ID(user_item_cards.id)", "type": "integer" } } }, - "message.listMessageData": { + "model.Guild": { "type": "object", "properties": { - "content": { - "description": "消息内容", + "avatar_url": { + "description": "工会头像", + "type": "string" + }, + "consume_limit": { + "description": "加入工会消费流水最低限额(分)", + "type": "integer" + }, + "created_at": { + "description": "创建时间", + "type": "string" + }, + "description": { + "description": "工会描述", "type": "string" }, "id": { - "description": "消息ID", + "description": "主键ID", "type": "integer" }, - "msg_type": { - "description": "消息类型(1:文本 2:图片)", + "is_open": { + "description": "1 公开 2 私有", "type": "integer" }, - "receiver_id": { - "description": "接收人ID", + "join_mode": { + "description": "加入方式 1: 审核通过 2: 自动通过 3. 消费流水", + "type": "integer" + }, + "name": { + "description": "公会名称", "type": "string" }, - "send_time": { - "description": "发送时间", - "type": "string" + "owner_id": { + "description": "会长用户ID", + "type": "integer" }, - "sender_id": { - "description": "发送人ID", - "type": "string" - }, - "sender_name": { - "description": "发送人昵称", - "type": "string" - } - } - }, - "message.userSendMessageRequest": { - "type": "object", - "required": [ - "app_id", - "content", - "from_user_id", - "from_user_name", - "msg_type" - ], - "properties": { - "app_id": { - "description": "小程序ID", - "type": "string" - }, - "content": { - "description": "内容", - "type": "string" - }, - "from_user_id": { - "description": "发送用户的ID", - "type": "string" - }, - "from_user_name": { - "description": "发送用户的昵称", - "type": "string" - }, - "msg_type": { - "description": "消息类型(1:文本 2:图片)", + "status": { + "description": "状态:1正常 2解散", "type": "integer" } } }, - "message.userSendMessageResponse": { + "model.OrderItems": { "type": "object", "properties": { - "message": { - "description": "提示信息", + "created_at": { + "description": "创建时间", + "type": "string" + }, + "id": { + "description": "主键ID", + "type": "integer" + }, + "order_id": { + "description": "订单ID(orders.id)", + "type": "integer" + }, + "price": { + "description": "成交单价(分)", + "type": "integer" + }, + "product_id": { + "description": "商品ID(products.id)", + "type": "integer" + }, + "product_images": { + "description": "商品图片快照(JSON)", + "type": "string" + }, + "quantity": { + "description": "购买数量", + "type": "integer" + }, + "status": { + "description": "行状态:1正常 2取消", + "type": "integer" + }, + "title": { + "description": "商品标题快照", + "type": "string" + }, + "total_amount": { + "description": "行应付总额(分)", + "type": "integer" + } + } + }, + "model.Orders": { + "type": "object", + "properties": { + "actual_amount": { + "description": "实际支付金额(分)", + "type": "integer" + }, + "cancelled_at": { + "description": "取消时间", + "type": "string" + }, + "created_at": { + "description": "创建时间", + "type": "string" + }, + "discount_amount": { + "description": "优惠券抵扣金额(分)", + "type": "integer" + }, + "id": { + "description": "主键ID", + "type": "integer" + }, + "is_consumed": { + "description": "是否已履约/消耗(对虚拟资产)", + "type": "integer" + }, + "order_no": { + "description": "业务订单号(唯一)", + "type": "string" + }, + "paid_at": { + "description": "支付完成时间", + "type": "string" + }, + "pay_preorder_id": { + "description": "关联预支付单ID(payment_preorder.id)", + "type": "integer" + }, + "points_amount": { + "description": "积分抵扣金额(分)", + "type": "integer" + }, + "points_ledger_id": { + "description": "积分扣减流水ID(user_points_ledger.id)", + "type": "integer" + }, + "remark": { + "description": "备注", + "type": "string" + }, + "source_type": { + "description": "来源:1商城直购 2抽奖票据 3其他", + "type": "integer" + }, + "status": { + "description": "订单状态:1待支付 2已支付 3已取消 4已退款", + "type": "integer" + }, + "total_amount": { + "description": "订单总金额(分)", + "type": "integer" + }, + "updated_at": { + "description": "更新时间", + "type": "string" + }, + "user_address_id": { + "description": "收货地址ID(user_addresses.id)", + "type": "integer" + }, + "user_id": { + "description": "下单用户ID(user_members.id)", + "type": "integer" + } + } + }, + "model.UserCoupons": { + "type": "object", + "properties": { + "coupon_id": { + "description": "券模板ID(system_coupons.id)", + "type": "integer" + }, + "created_at": { + "description": "创建时间", + "type": "string" + }, + "id": { + "description": "主键ID", + "type": "integer" + }, + "status": { + "description": "状态:1未使用 2已使用 3已过期", + "type": "integer" + }, + "updated_at": { + "description": "更新时间", + "type": "string" + }, + "used_at": { + "description": "核销时间", + "type": "string" + }, + "used_order_id": { + "description": "核销的订单ID(orders.id)", + "type": "integer" + }, + "user_id": { + "description": "用户ID(user_members.id)", + "type": "integer" + }, + "valid_end": { + "description": "有效期结束", + "type": "string" + }, + "valid_start": { + "description": "有效期开始", "type": "string" } } }, - "upload.uploadImageResponse": { + "model.UserItemCards": { "type": "object", "properties": { - "preview_image_url": { - "description": "可预览图片地址", + "card_id": { + "description": "卡模板ID(system_item_cards.id)", + "type": "integer" + }, + "created_at": { + "description": "创建时间", "type": "string" }, - "real_image_url": { - "description": "真实图片地址", + "id": { + "description": "主键ID", + "type": "integer" + }, + "remark": { + "description": "备注", + "type": "string" + }, + "status": { + "description": "状态:1未使用 2已使用 3已过期", + "type": "integer" + }, + "updated_at": { + "description": "更新时间", + "type": "string" + }, + "used_activity_id": { + "description": "使用时活动ID", + "type": "integer" + }, + "used_at": { + "description": "使用时间", + "type": "string" + }, + "used_draw_log_id": { + "description": "使用关联抽奖日志ID(activity_draw_logs.id)", + "type": "integer" + }, + "used_issue_id": { + "description": "使用时期ID", + "type": "integer" + }, + "user_id": { + "description": "用户ID(users.id)", + "type": "integer" + }, + "valid_end": { + "description": "有效期结束", + "type": "string" + }, + "valid_start": { + "description": "有效期开始", "type": "string" } } }, - "wechat.generateQRCodeRequest": { - "type": "object", - "required": [ - "app_id", - "app_secret", - "path" - ], - "properties": { - "app_id": { - "description": "微信小程序 AppID", - "type": "string" - }, - "app_secret": { - "description": "微信小程序 AppSecret", - "type": "string" - }, - "path": { - "description": "小程序页面路径", - "type": "string" - } - } - }, - "wechat.generateQRCodeResponse": { + "model.UserPointsLedger": { "type": "object", "properties": { - "data": { - "description": "Base64 编码的图片数据", + "action": { + "description": "变更动作:signin/order_deduct/refund_restore/manual", "type": "string" }, - "message": { + "created_at": { + "description": "创建时间", "type": "string" }, - "success": { - "type": "boolean" - } - } - }, - "wechat.miniprogramLoginRequest": { - "type": "object", - "required": [ - "app_id", - "js_code" - ], - "properties": { - "app_id": { - "description": "小程序AppID", + "id": { + "description": "主键ID", + "type": "integer" + }, + "points": { + "description": "积分变动值(正增负减)", + "type": "integer" + }, + "ref_id": { + "description": "关联ID(如订单号/记录ID)", "type": "string" }, - "js_code": { - "description": "登录时获取的code", - "type": "string" - } - } - }, - "wechat.miniprogramLoginResponse": { - "type": "object", - "properties": { - "message": { + "ref_table": { + "description": "关联表名(如orders/payment_refund)", "type": "string" }, - "openid": { - "description": "用户唯一标识", - "type": "string" - }, - "success": { - "type": "boolean" - }, - "token": { - "description": "登录token", - "type": "string" - }, - "unionid": { - "description": "用户在开放平台的唯一标识符", - "type": "string" - }, - "user_avatar": { - "description": "用户头像", + "remark": { + "description": "备注", "type": "string" }, "user_id": { - "description": "用户ID", - "type": "string" - }, - "user_name": { - "description": "用户昵称", - "type": "string" + "description": "用户ID(user_members.id)", + "type": "integer" } } }, - "wechat.sendSubscribeMessageRequest": { + "user.InventoryWithProduct": { "type": "object", - "required": [ - "app_id", - "app_secret", - "template_id", - "touser" - ], "properties": { - "app_id": { - "description": "微信小程序 AppID", + "activity_id": { + "description": "来源活动ID", + "type": "integer" + }, + "created_at": { + "description": "创建时间", "type": "string" }, - "app_secret": { - "description": "小程序 AppSecret", + "id": { + "description": "主键ID", + "type": "integer" + }, + "order_id": { + "description": "来源订单ID", + "type": "integer" + }, + "product_id": { + "description": "资产对应商品ID(实物奖/商品)", + "type": "integer" + }, + "product_images": { "type": "string" }, - "template_id": { - "description": "模板 ID", + "product_name": { "type": "string" }, - "touser": { - "description": "接收者(用户)的 openid", + "remark": { + "description": "备注", "type": "string" + }, + "reward_id": { + "description": "来源奖励ID(activity_reward_settings.id)", + "type": "integer" + }, + "status": { + "description": "状态:1持有 2作废 3已使用/发货", + "type": "integer" + }, + "updated_at": { + "description": "更新时间", + "type": "string" + }, + "user_id": { + "description": "资产归属用户ID", + "type": "integer" } } }, - "wechat.sendSubscribeMessageResponse": { + "user.OrderWithItems": { "type": "object", "properties": { - "message": { + "actual_amount": { + "description": "实际支付金额(分)", + "type": "integer" + }, + "cancelled_at": { + "description": "取消时间", "type": "string" }, - "success": { - "type": "boolean" - } - } - }, - "wechat.templateRequest": { - "type": "object", - "required": [ - "app_id" - ], - "properties": { - "app_id": { - "description": "微信小程序 AppID", - "type": "string" - } - } - }, - "wechat.templateResponse": { - "type": "object", - "properties": { - "app_id": { - "description": "小程序 AppID", + "created_at": { + "description": "创建时间", "type": "string" }, - "message": { + "discount_amount": { + "description": "优惠券抵扣金额(分)", + "type": "integer" + }, + "id": { + "description": "主键ID", + "type": "integer" + }, + "is_consumed": { + "description": "是否已履约/消耗(对虚拟资产)", + "type": "integer" + }, + "items": { + "type": "array", + "items": { + "$ref": "#/definitions/model.OrderItems" + } + }, + "order_no": { + "description": "业务订单号(唯一)", "type": "string" }, - "success": { - "type": "boolean" - }, - "template_id": { - "description": "模板 ID", + "paid_at": { + "description": "支付完成时间", "type": "string" + }, + "pay_preorder_id": { + "description": "关联预支付单ID(payment_preorder.id)", + "type": "integer" + }, + "points_amount": { + "description": "积分抵扣金额(分)", + "type": "integer" + }, + "points_ledger_id": { + "description": "积分扣减流水ID(user_points_ledger.id)", + "type": "integer" + }, + "remark": { + "description": "备注", + "type": "string" + }, + "source_type": { + "description": "来源:1商城直购 2抽奖票据 3其他", + "type": "integer" + }, + "status": { + "description": "订单状态:1待支付 2已支付 3已取消 4已退款", + "type": "integer" + }, + "total_amount": { + "description": "订单总金额(分)", + "type": "integer" + }, + "updated_at": { + "description": "更新时间", + "type": "string" + }, + "user_address_id": { + "description": "收货地址ID(user_addresses.id)", + "type": "integer" + }, + "user_id": { + "description": "下单用户ID(user_members.id)", + "type": "integer" } } } diff --git a/docs/swagger.yaml b/docs/swagger.yaml index 98dc158..69fc36d 100644 --- a/docs/swagger.yaml +++ b/docs/swagger.yaml @@ -1,5 +1,178 @@ basePath: / definitions: + admin.GrantRewardRequest: + properties: + activity_id: + description: 活动ID(可选) + type: integer + address_id: + description: 收货地址ID(可选,实物商品需要) + type: integer + product_id: + description: 商品ID + type: integer + quantity: + description: 发放数量 + minimum: 1 + type: integer + remark: + description: 备注 + type: string + reward_id: + description: 奖励配置ID(可选) + type: integer + required: + - product_id + type: object + admin.GrantRewardResponse: + properties: + inventory_ids: + items: + type: integer + type: array + message: + type: string + order_id: + type: integer + success: + type: boolean + type: object + admin.activitysvcIssueData: + properties: + id: + type: integer + issue_number: + type: string + sort: + type: integer + status: + type: integer + type: object + admin.addCouponRequest: + properties: + coupon_id: + type: integer + required: + - coupon_id + type: object + admin.addCouponResponse: + properties: + success: + type: boolean + type: object + admin.addPointsRequest: + properties: + kind: + type: string + points: + type: integer + remark: + type: string + valid_days: + type: integer + required: + - points + type: object + admin.addPointsResponse: + properties: + success: + type: boolean + type: object + admin.adminUserCouponItem: + properties: + coupon_id: + type: integer + discount_type: + type: integer + discount_value: + type: integer + id: + type: integer + min_spend: + type: integer + name: + type: string + scope_type: + type: integer + status: + type: integer + used_at: + type: string + used_order_id: + type: integer + valid_end: + type: string + valid_start: + type: string + type: object + admin.adminUserItem: + properties: + avatar: + type: string + created_at: + type: string + id: + type: integer + invite_code: + type: string + inviter_id: + type: integer + nickname: + type: string + type: object + admin.assignItemCardRequest: + properties: + card_id: + type: integer + quantity: + type: integer + required: + - card_id + type: object + admin.bannerItem: + properties: + id: + type: integer + image_url: + type: string + link_url: + type: string + sort: + type: integer + status: + type: integer + title: + type: string + type: object + admin.categoryItem: + properties: + id: + type: integer + name: + type: string + type: object + admin.createActivityRequest: + properties: + activity_category_id: + type: integer + banner: + type: string + end_time: + type: string + is_boss: + type: integer + name: + type: string + price_draw: + type: integer + start_time: + type: string + status: + type: integer + required: + - activity_category_id + - name + type: object admin.createAdminRequest: properties: avatar: @@ -28,6 +201,167 @@ definitions: description: 提示信息 type: string type: object + admin.createBannerRequest: + properties: + image_url: + type: string + link_url: + type: string + sort: + type: integer + status: + type: integer + title: + type: string + required: + - image_url + - title + type: object + admin.createBannerResponse: + properties: + id: + type: integer + message: + type: string + type: object + admin.createGuildRequest: + properties: + avatar_url: + type: string + consume_limit: + type: integer + description: + type: string + is_open: + type: integer + join_mode: + type: integer + name: + type: string + owner_id: + type: integer + required: + - name + - owner_id + type: object + admin.createGuildResponse: + properties: + message: + type: string + type: object + admin.createIssueRequest: + properties: + issue_number: + type: string + sort: + type: integer + status: + type: integer + required: + - issue_number + type: object + admin.createItemCardRequest: + properties: + activity_category_id: + type: integer + activity_id: + type: integer + boost_rate_x1000: + type: integer + card_type: + type: integer + effect_type: + type: integer + issue_id: + type: integer + max_effect_value_x1000: + type: integer + name: + type: string + price: + type: integer + remark: + type: string + reward_multiplier_x1000: + type: integer + scope_type: + type: integer + stacking_strategy: + type: integer + status: + type: integer + valid_end_unix: + type: integer + valid_start_unix: + type: integer + required: + - card_type + - effect_type + - name + - price + - scope_type + type: object + admin.createItemCardResponse: + properties: + id: + type: integer + message: + type: string + type: object + admin.createProductCategoryRequest: + properties: + name: + type: string + parent_id: + type: integer + status: + type: integer + required: + - name + type: object + admin.createProductCategoryResponse: + properties: + id: + type: integer + message: + type: string + type: object + admin.createProductRequest: + properties: + category_id: + type: integer + images_json: + type: string + name: + type: string + price: + type: integer + status: + type: integer + stock: + type: integer + required: + - category_id + - name + - price + - stock + type: object + admin.createProductResponse: + properties: + id: + type: integer + message: + type: string + type: object + admin.createRewardsRequest: + properties: + rewards: + items: + $ref: '#/definitions/admin.rewardItem' + type: array + required: + - rewards + type: object admin.deleteAdminRequest: properties: ids: @@ -42,6 +376,104 @@ definitions: description: 提示信息 type: string type: object + admin.deleteGuildResponse: + properties: + message: + type: string + type: object + admin.itemCardListItem: + properties: + activity_category_id: + description: 指定活动分类ID(可空) + type: integer + activity_id: + description: 指定活动ID(可空) + type: integer + boost_rate_x1000: + description: 概率提升(千分比,+20%=200) + type: integer + card_type: + description: 卡类型:1双倍奖励 2概率提升 等 + type: integer + created_at: + description: 创建时间 + type: string + effect_type: + description: 效果类型:1奖励倍数 2概率提升 等 + type: integer + id: + description: 主键ID + type: integer + issue_id: + description: 指定期ID(可空) + type: integer + max_effect_value_x1000: + description: 效果上限(千分比) + type: integer + name: + description: 卡名称 + type: string + price: + description: 售卖价格(分) + type: integer + remark: + description: 备注 + type: string + reward_multiplier_x1000: + description: 奖励倍数(千分比,×2=2000) + type: integer + scope_type: + description: 适用范围:1全局 2活动分类 3活动 4期 + type: integer + stacking_strategy: + description: 叠加策略:1禁止 2同类叠加-上限 3取最大值 4乘法叠加 + type: integer + status: + description: 状态:1启用 2停用 + type: integer + updated_at: + description: 更新时间 + type: string + valid_end: + description: 有效期结束 + type: string + valid_start: + description: 有效期开始 + type: string + type: object + admin.listBannersResponse: + properties: + list: + items: + $ref: '#/definitions/admin.bannerItem' + type: array + page: + type: integer + page_size: + type: integer + total: + type: integer + type: object + admin.listCategoriesResponse: + properties: + list: + items: + $ref: '#/definitions/admin.categoryItem' + type: array + type: object + admin.listCouponsResponse: + properties: + list: + items: + $ref: '#/definitions/admin.adminUserCouponItem' + type: array + page: + type: integer + page_size: + type: integer + total: + type: integer + type: object admin.listData: properties: avatar: @@ -66,6 +498,123 @@ definitions: description: 用户名 type: string type: object + admin.listGuildMembersResponse: + properties: + list: + items: + $ref: '#/definitions/admin.memberItem' + type: array + page: + type: integer + page_size: + type: integer + total: + type: integer + type: object + admin.listInventoryResponse: + properties: + list: + items: + $ref: '#/definitions/user.InventoryWithProduct' + type: array + page: + type: integer + page_size: + type: integer + total: + type: integer + type: object + admin.listInvitesResponse: + properties: + list: + items: + $ref: '#/definitions/admin.adminUserItem' + type: array + page: + type: integer + page_size: + type: integer + total: + type: integer + type: object + admin.listIssuesResponse: + properties: + list: + items: + $ref: '#/definitions/admin.activitysvcIssueData' + type: array + page: + type: integer + page_size: + type: integer + total: + type: integer + type: object + admin.listItemCardsResponse: + properties: + list: + items: + $ref: '#/definitions/admin.itemCardListItem' + type: array + page: + type: integer + page_size: + type: integer + total: + type: integer + type: object + admin.listOrdersResponse: + properties: + list: + items: + $ref: '#/definitions/user.OrderWithItems' + type: array + page: + type: integer + page_size: + type: integer + total: + type: integer + type: object + admin.listPointsResponse: + properties: + list: + items: + $ref: '#/definitions/model.UserPointsLedger' + type: array + page: + type: integer + page_size: + type: integer + total: + type: integer + type: object + admin.listProductCategoriesResponse: + properties: + list: + items: + $ref: '#/definitions/admin.productCategoryListItem' + type: array + page: + type: integer + page_size: + type: integer + total: + type: integer + type: object + admin.listProductsResponse: + properties: + list: + items: + $ref: '#/definitions/admin.productItem' + type: array + page: + type: integer + page_size: + type: integer + total: + type: integer + type: object admin.listResponse: properties: list: @@ -82,6 +631,26 @@ definitions: description: 符合查询条件的总记录数 type: integer type: object + admin.listRewardsResponse: + properties: + list: + items: + $ref: '#/definitions/admin.rewardItem' + type: array + type: object + admin.listUsersResponse: + properties: + list: + items: + $ref: '#/definitions/admin.adminUserItem' + type: array + page: + type: integer + page_size: + type: integer + total: + type: integer + type: object admin.loginRequest: properties: password: @@ -103,6 +672,36 @@ definitions: description: 登录成功后颁发的 Token type: string type: object + admin.memberItem: + properties: + id: + type: integer + role: + type: string + start_time: + type: string + user_id: + type: integer + type: object + admin.modifyActivityRequest: + properties: + activity_category_id: + type: integer + banner: + type: string + end_time: + type: string + is_boss: + type: integer + name: + type: string + price_draw: + type: integer + start_time: + type: string + status: + type: integer + type: object admin.modifyAdminRequest: properties: avatar: @@ -130,329 +729,647 @@ definitions: description: 提示信息 type: string type: object - admin.relAppRequest: + admin.modifyBannerRequest: properties: - ids: - description: 小程序编号(多个用,分割) + image_url: type: string - required: - - ids - type: object - admin.relAppResponse: - properties: - message: - description: 提示信息 + link_url: type: string - type: object - app.adminSendMessageRequest: - properties: - app_id: - description: 小程序ID - type: string - content: - description: 内容 - type: string - msg_type: - description: 消息类型(1:文本 2:图片) - type: integer - to_user_id: - description: 接收用户ID - type: string - required: - - app_id - - content - - msg_type - - to_user_id - type: object - app.adminSendMessageResponse: - properties: - message: - description: 提示信息 - type: string - type: object - app.appMessagePageListResponse: - properties: - list: - items: - $ref: '#/definitions/app.listMessageData' - type: array - page: - description: 当前页码 - type: integer - page_size: - description: 每页返回的数据量 - type: integer - total: - description: 符合查询条件的总记录数 - type: integer - type: object - app.checkAppStatusResponse: - properties: - app_id: - description: 小程序ID - type: string - check_status_text: - description: 状态文字描述 - type: string - code: - description: 外部接口返回的状态码 + sort: type: integer status: - description: 外部接口返回的状态 + type: integer + title: type: string type: object - app.createAppRequest: + admin.modifyGuildRequest: properties: - app_id: - description: 小程序ID - type: string - app_secret: - description: 小程序密钥 - type: string - avatar: - description: 头像 + avatar_url: type: string + consume_limit: + type: integer description: - description: 描述 type: string + is_open: + type: integer + join_mode: + type: integer name: - description: 名称 type: string - template_id: - description: 模版ID - type: string - required: - - app_id - - app_secret - - name + status: + type: integer type: object - app.createAppResponse: + admin.modifyGuildResponse: properties: message: - description: 提示信息 type: string type: object - app.createAppUserRequest: + admin.modifyIssueRequest: properties: - app_id: - description: 小程序ID + issue_number: type: string - user_avatar: - description: 用户头像 + sort: + type: integer + status: + type: integer + type: object + admin.modifyItemCardRequest: + properties: + activity_category_id: + type: integer + activity_id: + type: integer + boost_rate_x1000: + type: integer + card_type: + type: integer + effect_type: + type: integer + issue_id: + type: integer + max_effect_value_x1000: + type: integer + name: type: string - user_id: - description: 用户ID + price: + type: integer + remark: type: string - user_mobile: - description: 用户手机号 + reward_multiplier_x1000: + type: integer + scope_type: + type: integer + stacking_strategy: + type: integer + status: + type: integer + valid_end_unix: + type: integer + valid_start_unix: + type: integer + type: object + admin.modifyProductCategoryRequest: + properties: + name: type: string - user_name: - description: 用户昵称 + parent_id: + type: integer + status: + type: integer + type: object + admin.modifyProductRequest: + properties: + category_id: + type: integer + images_json: type: string + name: + type: string + price: + type: integer + status: + type: integer + stock: + type: integer + type: object + admin.modifyRewardRequest: + properties: + is_boss: + type: integer + level: + type: integer + name: + type: string + original_qty: + type: integer + product_id: + type: integer + quantity: + type: integer + sort: + type: integer + weight: + type: integer + type: object + admin.pcSimpleMessage: + properties: + message: + type: string + type: object + admin.pointsBalanceResponse: + properties: + balance: + type: integer + type: object + admin.productCategoryListItem: + properties: + id: + type: integer + name: + type: string + parent_id: + type: integer + status: + type: integer + type: object + admin.productItem: + properties: + category_id: + type: integer + id: + type: integer + images_json: + type: string + name: + type: string + price: + type: integer + sales: + type: integer + status: + type: integer + stock: + type: integer + type: object + admin.rewardItem: + properties: + id: + type: integer + is_boss: + type: integer + level: + type: integer + name: + type: string + original_qty: + type: integer + product_id: + type: integer + quantity: + type: integer + sort: + type: integer + weight: + type: integer + required: + - level + - name + - original_qty + - quantity + - weight + type: object + admin.roleItem: + properties: + createTime: + type: string + description: + type: string + enabled: + type: boolean + roleCode: + type: string + roleId: + type: integer + roleName: + type: string + type: object + admin.roleListResponse: + properties: + current: + type: integer + records: + items: + $ref: '#/definitions/admin.roleItem' + type: array + size: + type: integer + total: + type: integer + type: object + admin.simpleMessage: + properties: + message: + type: string + type: object + admin.simpleMessageResponse: + properties: + message: + type: string + type: object + admin.userListItem: + properties: + avatar: + type: string + createBy: + type: string + createTime: + type: string + id: + type: integer + nickName: + type: string + status: + type: string + updateBy: + type: string + updateTime: + type: string + userEmail: + type: string + userGender: + type: string + userName: + type: string + userPhone: + type: string + userRoles: + items: + type: string + type: array + type: object + admin.userListResponse: + properties: + current: + type: integer + records: + items: + $ref: '#/definitions/admin.userListItem' + type: array + size: + type: integer + total: + type: integer + type: object + app.activityItem: + properties: + activity_category_id: + type: integer + banner: + type: string + category_name: + type: string + id: + type: integer + is_boss: + type: integer + name: + type: string + price_draw: + type: integer + status: + type: integer + type: object + app.appBannerItem: + properties: + id: + type: integer + image_url: + type: string + link_url: + type: string + sort: + type: integer + title: + type: string + type: object + app.bindPhoneRequest: + properties: + code: + type: string + type: object + app.bindPhoneResponse: + properties: + mobile: + type: string + success: + type: boolean + type: object + app.drawLogItem: + properties: + current_level: + type: integer + id: + type: integer + is_winner: + type: integer + issue_id: + type: integer + level: + type: integer + order_id: + type: integer + reward_id: + type: integer + user_id: + type: integer + type: object + app.guildItem: + properties: + avatar_url: + type: string + consume_limit: + type: integer + description: + type: string + id: + type: integer + is_open: + type: integer + join_mode: + type: integer + name: + type: string + owner_id: + type: integer + status: + type: integer + type: object + app.inviteUserItem: + properties: + avatar: + type: string + id: + type: integer + invite_code: + type: string + nickname: + type: string + type: object + app.issueItem: + properties: + id: + type: integer + issue_number: + type: string + sort: + type: integer + status: + type: integer + type: object + app.joinGuildRequest: + properties: + user_id: + type: integer required: - - app_id - user_id - - user_name type: object - app.createAppUserResponse: - properties: - message: - description: 提示信息 - type: string - type: object - app.deleteAppRequest: - properties: - ids: - description: 小程序编号(多个用,分割) - type: string - required: - - ids - type: object - app.deleteAppResponse: - properties: - message: - description: 提示信息 - type: string - type: object - app.latestMessageByAppIdResponse: + app.listActivitiesResponse: properties: list: items: - $ref: '#/definitions/app.latestMessageData' + $ref: '#/definitions/app.activityItem' type: array page: - description: 当前页码 type: integer page_size: - description: 每页返回的数据量 type: integer total: - description: 符合查询条件的总记录数 type: integer type: object - app.latestMessageData: - properties: - content: - description: 消息内容 - type: string - msg_type: - description: 消息类型(1:文本 2:图片) - type: integer - send_time: - description: 发送时间 - type: string - sender_avatar: - description: 发送人头像 - type: string - sender_id: - description: 发送人ID - type: string - sender_name: - description: 发送人昵称 - type: string - unread_count: - description: 未读消息数量 - type: integer - type: object - app.listData: - properties: - app_id: - description: 小程序ID - type: string - app_secret: - description: 小程序密钥 - type: string - avatar: - description: 小程序头像 - type: string - check_status_text: - description: 状态文字描述 - type: string - created_at: - description: 创建时间 - type: string - description: - description: 小程序描述 - type: string - id: - description: 小程序编号 - type: integer - message_total: - description: 消息总数 - type: integer - name: - description: 小程序名称 - type: string - template_id: - description: 模版ID - type: string - updated_at: - description: 更新时间 - type: string - type: object - app.listMessageData: - properties: - content: - description: 消息内容 - type: string - id: - description: 消息ID - type: string - msg_type: - description: 消息类型(1:文本 2:图片) - type: integer - receiver_id: - description: 接收人ID - type: string - send_time: - description: 发送时间 - type: string - sender_id: - description: 发送人ID - type: string - sender_name: - description: 发送人昵称 - type: string - type: object - app.listResponse: + app.listAppBannersResponse: properties: list: items: - $ref: '#/definitions/app.listData' + $ref: '#/definitions/app.appBannerItem' + type: array + type: object + app.listCouponsResponse: + properties: + list: + items: + $ref: '#/definitions/model.UserCoupons' type: array page: - description: 当前页码 type: integer page_size: - description: 每页返回的数据量 type: integer total: - description: 符合查询条件的总记录数 type: integer type: object - app.modifyAppRequest: + app.listDrawLogsResponse: properties: - app_id: - description: 小程序ID - type: string - app_secret: - description: 小程序密钥 - type: string - avatar: - description: 头像 - type: string - description: - description: 描述 - type: string - name: - description: 名称 - type: string - template_id: - description: 模版ID - type: string - required: - - app_id - - app_secret - - name + list: + items: + $ref: '#/definitions/app.drawLogItem' + type: array + page: + type: integer + page_size: + type: integer + total: + type: integer type: object - app.modifyAppResponse: + app.listGuildsResponse: properties: - message: - description: 提示信息 - type: string + list: + items: + $ref: '#/definitions/app.guildItem' + type: array + page: + type: integer + page_size: + type: integer + total: + type: integer type: object - app.userListData: + app.listInvitesResponse: properties: - created_at: - description: 创建时间 + list: + items: + $ref: '#/definitions/app.inviteUserItem' + type: array + page: + type: integer + page_size: + type: integer + total: + type: integer + type: object + app.listIssuesResponse: + properties: + list: + items: + $ref: '#/definitions/app.issueItem' + type: array + page: + type: integer + page_size: + type: integer + total: + type: integer + type: object + app.listMembersResponse: + properties: + list: + items: + $ref: '#/definitions/app.memberItem' + type: array + page: + type: integer + page_size: + type: integer + total: + type: integer + type: object + app.listOrdersResponse: + properties: + list: + items: + $ref: '#/definitions/model.Orders' + type: array + page: + type: integer + page_size: + type: integer + total: + type: integer + type: object + app.listPointsResponse: + properties: + list: + items: + $ref: '#/definitions/model.UserPointsLedger' + type: array + page: + type: integer + page_size: + type: integer + total: + type: integer + type: object + app.listRewardsResponse: + properties: + list: + items: + $ref: '#/definitions/app.rewardItem' + type: array + type: object + app.listUserItemCardUsesResponse: + properties: + list: + items: + $ref: '#/definitions/model.ActivityDrawEffects' + type: array + page: + type: integer + page_size: + type: integer + total: + type: integer + type: object + app.listUserItemCardsResponse: + properties: + list: + items: + $ref: '#/definitions/model.UserItemCards' + type: array + page: + type: integer + page_size: + type: integer + total: + type: integer + type: object + app.memberItem: + properties: + id: + type: integer + role: type: string - user_avatar: - description: 用户头像 + start_time: type: string user_id: - description: 用户ID + type: integer + type: object + app.modifyUserRequest: + properties: + avatar: type: string - user_mobile: - description: 用户手机号 - type: string - user_name: - description: 用户昵称 + nickname: type: string type: object - app.userListResponse: + app.modifyUserResponse: properties: - list: - items: - $ref: '#/definitions/app.userListData' - type: array - page: - description: 当前页码 + user: + $ref: '#/definitions/app.userItem' + type: object + app.phoneLoginRequest: + properties: + code: + description: 兼容参数名:这里作为手机号或第三方手机号code + type: string + invite_code: + type: string + type: object + app.phoneLoginResponse: + properties: + avatar: + type: string + invite_code: + type: string + nickname: + type: string + user_id: type: integer - page_size: - description: 每页返回的数据量 + type: object + app.pointsBalanceResponse: + properties: + balance: type: integer - total: - description: 符合查询条件的总记录数 + type: object + app.rewardItem: + properties: + is_boss: + type: integer + level: + type: integer + name: + type: string + original_qty: + type: integer + product_id: + type: integer + quantity: + type: integer + sort: + type: integer + weight: + type: integer + type: object + app.simpleMessageResponse: + properties: + message: + type: string + type: object + app.userItem: + properties: + avatar: + type: string + id: + type: integer + invite_code: + type: string + inviter_id: + type: integer + nickname: + type: string + type: object + app.weixinLoginRequest: + properties: + code: + type: string + invite_code: + type: string + type: object + app.weixinLoginResponse: + properties: + avatar: + type: string + invite_code: + type: string + nickname: + type: string + user_id: type: integer type: object code.Failure: @@ -464,373 +1381,415 @@ definitions: description: 描述信息 type: string type: object - keyword.createKeywordMaterialRequest: + model.Activities: properties: - material_list: - description: 素材列表 - items: - $ref: '#/definitions/keyword.keywordMaterial' - type: array - required: - - material_list - type: object - keyword.createKeywordMaterialResponse: - properties: - message: - description: 提示信息 - type: string - type: object - keyword.createKeywordRequest: - properties: - app_id: - description: 小程序ID - type: string - keyword: - description: 关键字 - type: string - required: - - app_id - - keyword - type: object - keyword.createKeywordResponse: - properties: - id: - description: 关键字ID + activity_category_id: + description: 活动所属分类ID(activity_categories.id,可空) type: integer - message: - description: 提示信息 - type: string - type: object - keyword.deleteKeywordResponse: - properties: - message: - description: 提示信息 - type: string - type: object - keyword.keywordListData: - properties: - app_id: - description: 小程序ID + banner: + description: 活动横幅/海报URL type: string created_at: description: 创建时间 type: string - created_user: - description: 创建人 - type: string - id: - description: 关键字编号 - type: integer - keyword: - description: 意图关键字 - type: string - material_type_count: - description: 素材类型数量 - type: string - updated_at: - description: 更新时间 - type: string - updated_user: - description: 更新人 - type: string - type: object - keyword.keywordMaterial: - properties: - content: - description: 素材内容 - type: string - interval_seconds: - description: 发送间隔时间(单位:秒) - type: integer - type: - description: 素材类型(1:文本 2:图片) - type: integer - required: - - content - - interval_seconds - - type - type: object - keyword.keywordMaterialListData: - properties: - content: - description: 素材内容 - type: string - created_at: - description: 创建时间 - type: string - created_user: - description: 创建人 + end_time: + description: 结束时间 type: string id: description: 主键ID type: integer - interval_seconds: - description: 素材发送间隔时间(单位:秒) + is_boss: + description: 'Boss: 1 是 0 不是' type: integer - keyword_id: - description: 意图关键字ID - type: integer - type: - description: 素材类型(1:文本 2:图片) - type: integer - type: object - keyword.keywordMaterialPageListResponse: - properties: - list: - items: - $ref: '#/definitions/keyword.keywordMaterialListData' - type: array - page: - description: 当前页码 - type: integer - page_size: - description: 每页返回的数据量 - type: integer - total: - description: 符合查询条件的总记录数 - type: integer - type: object - keyword.keywordPageListResponse: - properties: - list: - items: - $ref: '#/definitions/keyword.keywordListData' - type: array - page: - description: 当前页码 - type: integer - page_size: - description: 每页返回的数据量 - type: integer - total: - description: 符合查询条件的总记录数 - type: integer - type: object - keyword.modifyKeywordMaterialRequest: - properties: - content: - description: 素材内容 + name: + description: 活动名称 type: string - interval_seconds: - description: 发送间隔时间(单位:秒) + price_draw: + description: 活动门票价格 type: integer - type: - description: 素材类型(1:文本 2:图片) + start_time: + description: 开始时间 + type: string + status: + description: 状态:1进行中 2下线 type: integer - required: - - content - - interval_seconds - - type - type: object - keyword.modifyKeywordMaterialResponse: - properties: - message: - description: 提示信息 + updated_at: + description: 更新时间 type: string type: object - keyword.modifyKeywordRequest: + model.ActivityDrawEffects: properties: - keyword: - description: 意图关键字 + activity_category_id: + description: 范围快照-活动分类ID + type: integer + activity_id: + description: 范围快照-活动ID + type: integer + applied: + description: 是否生效:0否 1是 + type: integer + card_type: + description: 卡类型快照 + type: integer + created_at: + description: 创建时间 type: string - required: - - keyword - type: object - keyword.modifyKeywordResponse: - properties: - message: - description: 提示信息 + draw_log_id: + description: 抽奖日志ID(activity_draw_logs.id) + type: integer + effect_type: + description: 效果类型快照 + type: integer + id: + description: 主键ID + type: integer + issue_id: + description: 范围快照-期ID + type: integer + probability_delta_x1000: + description: 概率相对增益(千分比) + type: integer + remark: + description: 备注 type: string - type: object - message.appMessagePageListResponse: - properties: - list: - items: - $ref: '#/definitions/message.listMessageData' - type: array - page: - description: 当前页码 + reward_multiplier_x1000: + description: 奖励倍数(千分比) type: integer - page_size: - description: 每页返回的数据量 + scope_type: + description: 适用范围快照 type: integer - total: - description: 符合查询条件的总记录数 + system_item_card_id: + description: 卡模板ID(system_item_cards.id) + type: integer + user_id: + description: 用户ID(users.id) + type: integer + user_item_card_id: + description: 用户卡实例ID(user_item_cards.id) type: integer type: object - message.listMessageData: + model.Guild: properties: - content: - description: 消息内容 + avatar_url: + description: 工会头像 + type: string + consume_limit: + description: 加入工会消费流水最低限额(分) + type: integer + created_at: + description: 创建时间 + type: string + description: + description: 工会描述 type: string id: - description: 消息ID + description: 主键ID type: integer - msg_type: - description: 消息类型(1:文本 2:图片) + is_open: + description: 1 公开 2 私有 type: integer - receiver_id: - description: 接收人ID - type: string - send_time: - description: 发送时间 - type: string - sender_id: - description: 发送人ID - type: string - sender_name: - description: 发送人昵称 - type: string - type: object - message.userSendMessageRequest: - properties: - app_id: - description: 小程序ID - type: string - content: - description: 内容 - type: string - from_user_id: - description: 发送用户的ID - type: string - from_user_name: - description: 发送用户的昵称 - type: string - msg_type: - description: 消息类型(1:文本 2:图片) + join_mode: + description: '加入方式 1: 审核通过 2: 自动通过 3. 消费流水' + type: integer + name: + description: 公会名称 + type: string + owner_id: + description: 会长用户ID + type: integer + status: + description: 状态:1正常 2解散 type: integer - required: - - app_id - - content - - from_user_id - - from_user_name - - msg_type type: object - message.userSendMessageResponse: + model.OrderItems: properties: - message: - description: 提示信息 + created_at: + description: 创建时间 + type: string + id: + description: 主键ID + type: integer + order_id: + description: 订单ID(orders.id) + type: integer + price: + description: 成交单价(分) + type: integer + product_id: + description: 商品ID(products.id) + type: integer + product_images: + description: 商品图片快照(JSON) + type: string + quantity: + description: 购买数量 + type: integer + status: + description: 行状态:1正常 2取消 + type: integer + title: + description: 商品标题快照 + type: string + total_amount: + description: 行应付总额(分) + type: integer + type: object + model.Orders: + properties: + actual_amount: + description: 实际支付金额(分) + type: integer + cancelled_at: + description: 取消时间 + type: string + created_at: + description: 创建时间 + type: string + discount_amount: + description: 优惠券抵扣金额(分) + type: integer + id: + description: 主键ID + type: integer + is_consumed: + description: 是否已履约/消耗(对虚拟资产) + type: integer + order_no: + description: 业务订单号(唯一) + type: string + paid_at: + description: 支付完成时间 + type: string + pay_preorder_id: + description: 关联预支付单ID(payment_preorder.id) + type: integer + points_amount: + description: 积分抵扣金额(分) + type: integer + points_ledger_id: + description: 积分扣减流水ID(user_points_ledger.id) + type: integer + remark: + description: 备注 + type: string + source_type: + description: 来源:1商城直购 2抽奖票据 3其他 + type: integer + status: + description: 订单状态:1待支付 2已支付 3已取消 4已退款 + type: integer + total_amount: + description: 订单总金额(分) + type: integer + updated_at: + description: 更新时间 + type: string + user_address_id: + description: 收货地址ID(user_addresses.id) + type: integer + user_id: + description: 下单用户ID(user_members.id) + type: integer + type: object + model.UserCoupons: + properties: + coupon_id: + description: 券模板ID(system_coupons.id) + type: integer + created_at: + description: 创建时间 + type: string + id: + description: 主键ID + type: integer + status: + description: 状态:1未使用 2已使用 3已过期 + type: integer + updated_at: + description: 更新时间 + type: string + used_at: + description: 核销时间 + type: string + used_order_id: + description: 核销的订单ID(orders.id) + type: integer + user_id: + description: 用户ID(user_members.id) + type: integer + valid_end: + description: 有效期结束 + type: string + valid_start: + description: 有效期开始 type: string type: object - upload.uploadImageResponse: + model.UserItemCards: properties: - preview_image_url: - description: 可预览图片地址 + card_id: + description: 卡模板ID(system_item_cards.id) + type: integer + created_at: + description: 创建时间 type: string - real_image_url: - description: 真实图片地址 + id: + description: 主键ID + type: integer + remark: + description: 备注 + type: string + status: + description: 状态:1未使用 2已使用 3已过期 + type: integer + updated_at: + description: 更新时间 + type: string + used_activity_id: + description: 使用时活动ID + type: integer + used_at: + description: 使用时间 + type: string + used_draw_log_id: + description: 使用关联抽奖日志ID(activity_draw_logs.id) + type: integer + used_issue_id: + description: 使用时期ID + type: integer + user_id: + description: 用户ID(users.id) + type: integer + valid_end: + description: 有效期结束 + type: string + valid_start: + description: 有效期开始 type: string type: object - wechat.generateQRCodeRequest: + model.UserPointsLedger: properties: - app_id: - description: 微信小程序 AppID + action: + description: 变更动作:signin/order_deduct/refund_restore/manual type: string - app_secret: - description: 微信小程序 AppSecret + created_at: + description: 创建时间 type: string - path: - description: 小程序页面路径 + id: + description: 主键ID + type: integer + points: + description: 积分变动值(正增负减) + type: integer + ref_id: + description: 关联ID(如订单号/记录ID) type: string - required: - - app_id - - app_secret - - path - type: object - wechat.generateQRCodeResponse: - properties: - data: - description: Base64 编码的图片数据 + ref_table: + description: 关联表名(如orders/payment_refund) type: string - message: - type: string - success: - type: boolean - type: object - wechat.miniprogramLoginRequest: - properties: - app_id: - description: 小程序AppID - type: string - js_code: - description: 登录时获取的code - type: string - required: - - app_id - - js_code - type: object - wechat.miniprogramLoginResponse: - properties: - message: - type: string - openid: - description: 用户唯一标识 - type: string - success: - type: boolean - token: - description: 登录token - type: string - unionid: - description: 用户在开放平台的唯一标识符 - type: string - user_avatar: - description: 用户头像 + remark: + description: 备注 type: string user_id: - description: 用户ID - type: string - user_name: - description: 用户昵称 - type: string + description: 用户ID(user_members.id) + type: integer type: object - wechat.sendSubscribeMessageRequest: + user.InventoryWithProduct: properties: - app_id: - description: 微信小程序 AppID + activity_id: + description: 来源活动ID + type: integer + created_at: + description: 创建时间 type: string - app_secret: - description: 小程序 AppSecret + id: + description: 主键ID + type: integer + order_id: + description: 来源订单ID + type: integer + product_id: + description: 资产对应商品ID(实物奖/商品) + type: integer + product_images: type: string - template_id: - description: 模板 ID + product_name: type: string - touser: - description: 接收者(用户)的 openid + remark: + description: 备注 type: string - required: - - app_id - - app_secret - - template_id - - touser + reward_id: + description: 来源奖励ID(activity_reward_settings.id) + type: integer + status: + description: 状态:1持有 2作废 3已使用/发货 + type: integer + updated_at: + description: 更新时间 + type: string + user_id: + description: 资产归属用户ID + type: integer type: object - wechat.sendSubscribeMessageResponse: + user.OrderWithItems: properties: - message: + actual_amount: + description: 实际支付金额(分) + type: integer + cancelled_at: + description: 取消时间 type: string - success: - type: boolean - type: object - wechat.templateRequest: - properties: - app_id: - description: 微信小程序 AppID + created_at: + description: 创建时间 type: string - required: - - app_id - type: object - wechat.templateResponse: - properties: - app_id: - description: 小程序 AppID + discount_amount: + description: 优惠券抵扣金额(分) + type: integer + id: + description: 主键ID + type: integer + is_consumed: + description: 是否已履约/消耗(对虚拟资产) + type: integer + items: + items: + $ref: '#/definitions/model.OrderItems' + type: array + order_no: + description: 业务订单号(唯一) type: string - message: + paid_at: + description: 支付完成时间 type: string - success: - type: boolean - template_id: - description: 模板 ID + pay_preorder_id: + description: 关联预支付单ID(payment_preorder.id) + type: integer + points_amount: + description: 积分抵扣金额(分) + type: integer + points_ledger_id: + description: 积分扣减流水ID(user_points_ledger.id) + type: integer + remark: + description: 备注 type: string + source_type: + description: 来源:1商城直购 2抽奖票据 3其他 + type: integer + status: + description: 订单状态:1待支付 2已支付 3已取消 4已退款 + type: integer + total_amount: + description: 订单总金额(分) + type: integer + updated_at: + description: 更新时间 + type: string + user_address_id: + description: 收货地址ID(user_addresses.id) + type: integer + user_id: + description: 下单用户ID(user_members.id) + type: integer type: object info: contact: {} @@ -870,250 +1829,522 @@ paths: summary: 编辑客服 tags: - 管理端.客服管理 - /api/admin/app/{id}: - put: - consumes: - - application/json - description: 编辑小程序 - parameters: - - description: 编号ID - in: path - name: id - required: true - type: string - - description: 请求参数 - in: body - name: RequestBody - required: true - schema: - $ref: '#/definitions/app.modifyAppRequest' - produces: - - application/json - responses: - "200": - description: OK - schema: - $ref: '#/definitions/app.modifyAppResponse' - "400": - description: Bad Request - schema: - $ref: '#/definitions/code.Failure' - security: - - LoginVerifyToken: [] - summary: 编辑小程序 - tags: - - 管理端.小程序 - /api/admin/app/check_status: - get: - consumes: - - application/json - description: 管理端根据 app_id 调用外部验证服务获取状态(正常/封禁/未知) - parameters: - - description: 小程序ID - in: query - name: app_id - required: true - type: string - produces: - - application/json - responses: - "200": - description: OK - schema: - $ref: '#/definitions/app.checkAppStatusResponse' - "400": - description: Bad Request - schema: - $ref: '#/definitions/code.Failure' - security: - - LoginVerifyToken: [] - summary: 检查小程序状态 - tags: - - 管理端.小程序 - /api/admin/app/create: + /api/admin/activities: post: consumes: - application/json - description: 新增小程序 + description: 创建活动,配置基本信息与分类、Boss标签 parameters: - description: 请求参数 in: body name: RequestBody required: true schema: - $ref: '#/definitions/app.createAppRequest' + $ref: '#/definitions/admin.createActivityRequest' produces: - application/json responses: "200": description: OK schema: - $ref: '#/definitions/app.createAppResponse' + $ref: '#/definitions/admin.simpleMessageResponse' "400": description: Bad Request schema: $ref: '#/definitions/code.Failure' security: - LoginVerifyToken: [] - summary: 新增小程序 + summary: 创建活动 tags: - - 管理端.小程序 - /api/admin/app/delete: - post: - consumes: - - application/json - description: 删除小程序 - parameters: - - description: 请求参数 - in: body - name: RequestBody - required: true - schema: - $ref: '#/definitions/app.deleteAppRequest' - produces: - - application/json - responses: - "200": - description: OK - schema: - $ref: '#/definitions/app.deleteAppResponse' - "400": - description: Bad Request - schema: - $ref: '#/definitions/code.Failure' - security: - - LoginVerifyToken: [] - summary: 删除小程序 - tags: - - 管理端.小程序 - /api/admin/app/keyword: - post: - consumes: - - application/json - description: 添加意图关键字 - parameters: - - description: 请求参数 - in: body - name: RequestBody - required: true - schema: - $ref: '#/definitions/keyword.createKeywordRequest' - produces: - - application/json - responses: - "200": - description: OK - schema: - $ref: '#/definitions/keyword.createKeywordResponse' - "400": - description: Bad Request - schema: - $ref: '#/definitions/code.Failure' - security: - - LoginVerifyToken: [] - summary: 添加意图关键字 - tags: - - 管理端.意图关键字 - /api/admin/app/keyword/{id}: + - 管理端.活动 + /api/admin/activities/{activity_id}: delete: consumes: - application/json - description: 删除意图关键字 + description: 删除指定活动 parameters: - - description: 编号ID + - description: 活动ID in: path - name: id + name: activity_id required: true - type: string + type: integer produces: - application/json responses: "200": description: OK schema: - $ref: '#/definitions/keyword.deleteKeywordResponse' + $ref: '#/definitions/admin.simpleMessageResponse' "400": description: Bad Request schema: $ref: '#/definitions/code.Failure' security: - LoginVerifyToken: [] - summary: 删除意图关键字 + summary: 删除活动 tags: - - 管理端.意图关键字 + - 管理端.活动 + get: + consumes: + - application/json + description: 查看指定活动的详细信息 + parameters: + - description: 活动ID + in: path + name: activity_id + required: true + type: integer + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/model.Activities' + "400": + description: Bad Request + schema: + $ref: '#/definitions/code.Failure' + security: + - LoginVerifyToken: [] + summary: 查看活动详情 + tags: + - 管理端.活动 put: consumes: - application/json - description: 修改意图关键字 + description: 修改活动基本信息、分类、Boss标签等 parameters: - - description: 编号ID + - description: 活动ID in: path - name: id + name: activity_id required: true - type: string + type: integer - description: 请求参数 in: body name: RequestBody required: true schema: - $ref: '#/definitions/keyword.modifyKeywordRequest' + $ref: '#/definitions/admin.modifyActivityRequest' produces: - application/json responses: "200": description: OK schema: - $ref: '#/definitions/keyword.modifyKeywordResponse' + $ref: '#/definitions/admin.simpleMessageResponse' "400": description: Bad Request schema: $ref: '#/definitions/code.Failure' security: - LoginVerifyToken: [] - summary: 修改意图关键字 + summary: 修改活动 tags: - - 管理端.意图关键字 - /api/admin/app/keyword/material/{id}: + - 管理端.活动 + /api/admin/activities/{activity_id}/issues: + get: + consumes: + - application/json + description: 获取指定活动的期数列表,支持分页 + parameters: + - description: 活动ID + in: path + name: activity_id + required: true + type: integer + - default: 1 + description: 页码 + in: query + name: page + required: true + type: integer + - default: 20 + description: 每页数量,最多100 + in: query + name: page_size + required: true + type: integer + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/admin.listIssuesResponse' + "400": + description: Bad Request + schema: + $ref: '#/definitions/code.Failure' + security: + - LoginVerifyToken: [] + summary: 查看活动期数 + tags: + - 管理端.活动 post: consumes: - application/json - description: 配置意图关键字素材 + description: 为指定活动创建一个新的期数 parameters: - - description: 编号ID + - description: 活动ID in: path - name: id + name: activity_id required: true - type: string + type: integer - description: 请求参数 in: body name: RequestBody required: true schema: - $ref: '#/definitions/keyword.createKeywordMaterialRequest' + $ref: '#/definitions/admin.createIssueRequest' produces: - application/json responses: "200": description: OK schema: - $ref: '#/definitions/keyword.createKeywordMaterialResponse' + $ref: '#/definitions/admin.simpleMessage' "400": description: Bad Request schema: $ref: '#/definitions/code.Failure' security: - LoginVerifyToken: [] - summary: 配置意图关键字素材 + summary: 创建活动期数 tags: - - 管理端.意图关键字 + - 管理端.活动 + /api/admin/activities/{activity_id}/issues/{issue_id}: + delete: + consumes: + - application/json + description: 删除指定期数 + parameters: + - description: 活动ID + in: path + name: activity_id + required: true + type: integer + - description: 期ID + in: path + name: issue_id + required: true + type: integer + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/admin.simpleMessage' + "400": + description: Bad Request + schema: + $ref: '#/definitions/code.Failure' + security: + - LoginVerifyToken: [] + summary: 删除活动期数 + tags: + - 管理端.活动 put: consumes: - application/json - description: 修改意图关键字素材 + description: 修改指定期数的信息 parameters: - - description: 素材编号ID + - description: 活动ID in: path - name: id + name: activity_id + required: true + type: integer + - description: 期ID + in: path + name: issue_id + required: true + type: integer + - description: 请求参数 + in: body + name: RequestBody + required: true + schema: + $ref: '#/definitions/admin.modifyIssueRequest' + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/admin.simpleMessage' + "400": + description: Bad Request + schema: + $ref: '#/definitions/code.Failure' + security: + - LoginVerifyToken: [] + summary: 修改活动期数 + tags: + - 管理端.活动 + /api/admin/activities/{activity_id}/issues/{issue_id}/rewards: + get: + consumes: + - application/json + description: 查看指定期数的奖励配置列表 + parameters: + - description: 活动ID + in: path + name: activity_id + required: true + type: integer + - description: 期ID + in: path + name: issue_id + required: true + type: integer + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/admin.listRewardsResponse' + "400": + description: Bad Request + schema: + $ref: '#/definitions/code.Failure' + security: + - LoginVerifyToken: [] + summary: 查看期数奖品 + tags: + - 管理端.活动 + post: + consumes: + - application/json + description: 为指定期数批量创建奖励配置 + parameters: + - description: 活动ID + in: path + name: activity_id + required: true + type: integer + - description: 期ID + in: path + name: issue_id + required: true + type: integer + - description: 请求参数 + in: body + name: RequestBody + required: true + schema: + $ref: '#/definitions/admin.createRewardsRequest' + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/admin.simpleMessageResponse' + "400": + description: Bad Request + schema: + $ref: '#/definitions/code.Failure' + security: + - LoginVerifyToken: [] + summary: 创建期数奖品 + tags: + - 管理端.活动 + /api/admin/activities/{activity_id}/issues/{issue_id}/rewards/{reward_id}: + delete: + consumes: + - application/json + parameters: + - description: 活动ID + in: path + name: activity_id + required: true + type: integer + - description: 期ID + in: path + name: issue_id + required: true + type: integer + - description: 奖励ID + in: path + name: reward_id + required: true + type: integer + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/admin.simpleMessageResponse' + "400": + description: Bad Request + schema: + $ref: '#/definitions/code.Failure' + security: + - LoginVerifyToken: [] + summary: 删除期数奖励 + tags: + - 管理端.活动 + put: + consumes: + - application/json + parameters: + - description: 活动ID + in: path + name: activity_id + required: true + type: integer + - description: 期ID + in: path + name: issue_id + required: true + type: integer + - description: 奖励ID + in: path + name: reward_id + required: true + type: integer + - description: 请求参数 + in: body + name: RequestBody + required: true + schema: + $ref: '#/definitions/admin.modifyRewardRequest' + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/admin.simpleMessageResponse' + "400": + description: Bad Request + schema: + $ref: '#/definitions/code.Failure' + security: + - LoginVerifyToken: [] + summary: 更新期数奖励 + tags: + - 管理端.活动 + /api/admin/activity_categories: + get: + consumes: + - application/json + description: 获取启用状态的活动分类列表 + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/admin.listCategoriesResponse' + "400": + description: Bad Request + schema: + $ref: '#/definitions/code.Failure' + security: + - LoginVerifyToken: [] + summary: 活动分类列表 + tags: + - 管理端.活动 + /api/admin/banners: + get: + consumes: + - application/json + parameters: + - description: 状态 + in: query + name: status + type: integer + - default: 1 + description: 页码 + in: query + name: page + required: true + type: integer + - default: 20 + description: 每页数量 + in: query + name: page_size + required: true + type: integer + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/admin.listBannersResponse' + "400": + description: Bad Request + schema: + $ref: '#/definitions/code.Failure' + security: + - LoginVerifyToken: [] + summary: 查看轮播图列表 + tags: + - 管理端.运营 + post: + consumes: + - application/json + parameters: + - description: 请求参数 + in: body + name: RequestBody + required: true + schema: + $ref: '#/definitions/admin.createBannerRequest' + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/admin.createBannerResponse' + "400": + description: Bad Request + schema: + $ref: '#/definitions/code.Failure' + security: + - LoginVerifyToken: [] + summary: 创建轮播图 + tags: + - 管理端.运营 + /api/admin/banners/{banner_id}: + delete: + consumes: + - application/json + parameters: + - description: 轮播图ID + in: path + name: banner_id + required: true + type: string + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/admin.pcSimpleMessage' + "400": + description: Bad Request + schema: + $ref: '#/definitions/code.Failure' + security: + - LoginVerifyToken: [] + summary: 删除轮播图 + tags: + - 管理端.运营 + put: + consumes: + - application/json + parameters: + - description: 轮播图ID + in: path + name: banner_id required: true type: string - description: 请求参数 @@ -1121,198 +2352,23 @@ paths: name: RequestBody required: true schema: - $ref: '#/definitions/keyword.modifyKeywordMaterialRequest' + $ref: '#/definitions/admin.modifyBannerRequest' produces: - application/json responses: "200": description: OK schema: - $ref: '#/definitions/keyword.modifyKeywordMaterialResponse' + $ref: '#/definitions/admin.pcSimpleMessage' "400": description: Bad Request schema: $ref: '#/definitions/code.Failure' security: - LoginVerifyToken: [] - summary: 修改意图关键字素材 + summary: 修改轮播图 tags: - - 管理端.意图关键字 - /api/admin/app/keyword/materials: - get: - consumes: - - application/json - description: 获取意图关键字素材列表 - parameters: - - description: 意图关键字ID - in: query - name: keyword_id - required: true - type: integer - - default: 1 - description: 当前页码 - in: query - name: page - required: true - type: integer - - default: 20 - description: 每页返回的数据量,最多 100 条 - in: query - name: page_size - required: true - type: integer - produces: - - application/json - responses: - "200": - description: OK - schema: - $ref: '#/definitions/keyword.keywordMaterialPageListResponse' - "400": - description: Bad Request - schema: - $ref: '#/definitions/code.Failure' - security: - - LoginVerifyToken: [] - summary: 获取意图关键字素材列表 - tags: - - 管理端.意图关键字 - /api/admin/app/keywords: - get: - consumes: - - application/json - description: 获取意图关键字列表 - parameters: - - description: 小程序ID - in: query - name: app_id - required: true - type: integer - - description: 意图关键字 - in: query - name: keyword - type: string - - default: 1 - description: 当前页码 - in: query - name: page - required: true - type: integer - - default: 20 - description: 每页返回的数据量,最多 100 条 - in: query - name: page_size - required: true - type: integer - produces: - - application/json - responses: - "200": - description: OK - schema: - $ref: '#/definitions/keyword.keywordPageListResponse' - "400": - description: Bad Request - schema: - $ref: '#/definitions/code.Failure' - security: - - LoginVerifyToken: [] - summary: 获取意图关键字列表 - tags: - - 管理端.意图关键字 - /api/admin/app/users: - get: - consumes: - - application/json - description: 小程序用户列表 - parameters: - - description: 小程序ID - in: query - name: app_id - required: true - type: string - - description: 用户昵称 - in: query - name: user_name - type: string - - description: 用户ID - in: query - name: user_id - type: string - - default: 1 - description: 当前页码 - in: query - name: page - required: true - type: integer - - default: 20 - description: 每页返回的数据量,最多 100 条 - in: query - name: page_size - required: true - type: integer - produces: - - application/json - responses: - "200": - description: OK - schema: - $ref: '#/definitions/app.userListResponse' - "400": - description: Bad Request - schema: - $ref: '#/definitions/code.Failure' - security: - - LoginVerifyToken: [] - summary: 小程序用户列表 - tags: - - 管理端.小程序 - /api/admin/apps: - get: - consumes: - - application/json - description: 小程序列表 - parameters: - - description: 小程序名称 - in: query - name: name - type: string - - description: 小程序ID - in: query - name: app_id - type: string - - description: 客服编号 - in: query - name: admin_id - type: integer - - default: 1 - description: 当前页码 - in: query - name: page - required: true - type: integer - - default: 20 - description: 每页返回的数据量,最多 100 条 - in: query - name: page_size - required: true - type: integer - produces: - - application/json - responses: - "200": - description: OK - schema: - $ref: '#/definitions/app.listResponse' - "400": - description: Bad Request - schema: - $ref: '#/definitions/code.Failure' - security: - - LoginVerifyToken: [] - summary: 小程序列表 - tags: - - 管理端.小程序 + - 管理端.运营 /api/admin/create: post: consumes: @@ -1369,6 +2425,158 @@ paths: summary: 删除客服 tags: - 管理端.客服管理 + /api/admin/guilds: + post: + consumes: + - application/json + description: 创建工会并将首位成员设为会长 + parameters: + - description: 请求参数 + in: body + name: RequestBody + required: true + schema: + $ref: '#/definitions/admin.createGuildRequest' + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/admin.createGuildResponse' + "400": + description: Bad Request + schema: + $ref: '#/definitions/code.Failure' + security: + - LoginVerifyToken: [] + summary: 创建工会 + tags: + - 管理端.工会 + /api/admin/guilds/{guild_id}: + delete: + consumes: + - application/json + description: 删除指定工会 + parameters: + - description: 工会ID + in: path + name: guild_id + required: true + type: integer + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/admin.deleteGuildResponse' + "400": + description: Bad Request + schema: + $ref: '#/definitions/code.Failure' + security: + - LoginVerifyToken: [] + summary: 删除工会 + tags: + - 管理端.工会 + get: + consumes: + - application/json + description: 查看指定工会详情 + parameters: + - description: 工会ID + in: path + name: guild_id + required: true + type: integer + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/model.Guild' + "400": + description: Bad Request + schema: + $ref: '#/definitions/code.Failure' + security: + - LoginVerifyToken: [] + summary: 查看工会详情 + tags: + - 管理端.工会 + put: + consumes: + - application/json + description: 修改指定工会信息 + parameters: + - description: 工会ID + in: path + name: guild_id + required: true + type: integer + - description: 请求参数 + in: body + name: RequestBody + required: true + schema: + $ref: '#/definitions/admin.modifyGuildRequest' + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/admin.modifyGuildResponse' + "400": + description: Bad Request + schema: + $ref: '#/definitions/code.Failure' + security: + - LoginVerifyToken: [] + summary: 修改工会 + tags: + - 管理端.工会 + /api/admin/guilds/{guild_id}/members: + get: + consumes: + - application/json + description: 查看指定工会的成员列表 + parameters: + - description: 工会ID + in: path + name: guild_id + required: true + type: integer + - default: 1 + description: 页码 + in: query + name: page + required: true + type: integer + - default: 20 + description: 每页数量,最多100 + in: query + name: page_size + required: true + type: integer + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/admin.listGuildMembersResponse' + "400": + description: Bad Request + schema: + $ref: '#/definitions/code.Failure' + security: + - LoginVerifyToken: [] + summary: 查看工会成员 + tags: + - 管理端.工会 /api/admin/list: get: consumes: @@ -1437,30 +2645,27 @@ paths: summary: 管理员登录 tags: - 管理端.登录 - /api/admin/messages: + /api/admin/product_categories: get: consumes: - application/json - description: 获取消息日志 parameters: - - description: 小程序ID + - description: 名称 in: query - name: app_id - required: true + name: name type: string - - description: 用户ID + - description: 状态 in: query - name: user_id - required: true - type: string + name: status + type: integer - default: 1 - description: 当前页码 + description: 页码 in: query name: page required: true type: integer - default: 20 - description: 每页返回的数据量,最多 100 条 + description: 每页数量 in: query name: page_size required: true @@ -1471,64 +2676,75 @@ paths: "200": description: OK schema: - $ref: '#/definitions/app.appMessagePageListResponse' + $ref: '#/definitions/admin.listProductCategoriesResponse' "400": description: Bad Request schema: $ref: '#/definitions/code.Failure' security: - LoginVerifyToken: [] - summary: 获取消息日志 + summary: 查看商品分类列表 tags: - - 管理端.小程序 - /api/admin/messages/latest: - get: + - 管理端.商品 + post: consumes: - application/json - description: 管理端根据appid获取最新消息记录,包含已读未读状态,访问时自动标记为已读 parameters: - - description: 小程序ID - in: query - name: app_id + - description: 请求参数 + in: body + name: RequestBody required: true - type: string - - default: 1 - description: 当前页码 - in: query - name: page - required: true - type: integer - - default: 20 - description: 每页返回的数据量,最多 100 条 - in: query - name: page_size - required: true - type: integer + schema: + $ref: '#/definitions/admin.createProductCategoryRequest' produces: - application/json responses: "200": description: OK schema: - $ref: '#/definitions/app.latestMessageByAppIdResponse' + $ref: '#/definitions/admin.createProductCategoryResponse' "400": description: Bad Request schema: $ref: '#/definitions/code.Failure' security: - LoginVerifyToken: [] - summary: 根据appid获取最新消息记录 + summary: 创建商品分类 tags: - - 管理端.小程序 - /api/admin/rel_app/{id}: + - 管理端.商品 + /api/admin/product_categories/{category_id}: + delete: + consumes: + - application/json + parameters: + - description: 分类ID + in: path + name: category_id + required: true + type: string + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/admin.pcSimpleMessage' + "400": + description: Bad Request + schema: + $ref: '#/definitions/code.Failure' + security: + - LoginVerifyToken: [] + summary: 删除商品分类 + tags: + - 管理端.商品 put: consumes: - application/json - description: 客服关联小程序 parameters: - - description: 客服编号ID + - description: 分类ID in: path - name: id + name: category_id required: true type: string - description: 请求参数 @@ -1536,100 +2752,48 @@ paths: name: RequestBody required: true schema: - $ref: '#/definitions/admin.relAppRequest' + $ref: '#/definitions/admin.modifyProductCategoryRequest' produces: - application/json responses: "200": description: OK schema: - $ref: '#/definitions/admin.relAppResponse' + $ref: '#/definitions/admin.pcSimpleMessage' "400": description: Bad Request schema: $ref: '#/definitions/code.Failure' security: - LoginVerifyToken: [] - summary: 客服关联小程序 + summary: 修改商品分类 tags: - - 管理端.客服管理 - /api/admin/send_message: - post: - consumes: - - application/json - description: 管理员发送消息 - parameters: - - description: 请求参数 - in: body - name: RequestBody - required: true - schema: - $ref: '#/definitions/app.adminSendMessageRequest' - produces: - - application/json - responses: - "200": - description: OK - schema: - $ref: '#/definitions/app.adminSendMessageResponse' - "400": - description: Bad Request - schema: - $ref: '#/definitions/code.Failure' - security: - - LoginVerifyToken: [] - summary: 管理员发送消息 - tags: - - 管理端.小程序 - /api/admin/upload/image: - post: - consumes: - - multipart/form-data - description: 上传图片 - parameters: - - description: 选择文件 - in: formData - name: file - required: true - type: file - produces: - - application/json - responses: - "200": - description: OK - schema: - $ref: '#/definitions/upload.uploadImageResponse' - "400": - description: Bad Request - schema: - $ref: '#/definitions/code.Failure' - summary: 上传图片 - tags: - - 通用 - /api/app/messages: + - 管理端.商品 + /api/admin/products: get: consumes: - application/json - description: 获取消息日志 parameters: - - description: 小程序ID + - description: 名称 in: query - name: app_id - required: true + name: name type: string - - description: 用户ID + - description: 分类ID in: query - name: user_id - required: true - type: string + name: category_id + type: integer + - description: 状态 + in: query + name: status + type: integer - default: 1 - description: 当前页码 + description: 页码 in: query name: page required: true type: integer - default: 20 - description: 每页返回的数据量,最多 100 条 + description: 每页数量 in: query name: page_size required: true @@ -1640,194 +2804,1504 @@ paths: "200": description: OK schema: - $ref: '#/definitions/message.appMessagePageListResponse' + $ref: '#/definitions/admin.listProductsResponse' "400": description: Bad Request schema: $ref: '#/definitions/code.Failure' - summary: 获取消息日志 + security: + - LoginVerifyToken: [] + summary: 查看商品列表 tags: - - 用户端 - /api/app/send_message: + - 管理端.商品 post: consumes: - application/json - description: 用户发送消息 parameters: - description: 请求参数 in: body name: RequestBody required: true schema: - $ref: '#/definitions/message.userSendMessageRequest' + $ref: '#/definitions/admin.createProductRequest' produces: - application/json responses: "200": description: OK schema: - $ref: '#/definitions/message.userSendMessageResponse' + $ref: '#/definitions/admin.createProductResponse' "400": description: Bad Request schema: $ref: '#/definitions/code.Failure' - summary: 用户发送消息 + security: + - LoginVerifyToken: [] + summary: 创建商品 tags: - - 用户端 - /api/app/user/create: + - 管理端.商品 + /api/admin/products/{product_id}: + delete: + consumes: + - application/json + parameters: + - description: 商品ID + in: path + name: product_id + required: true + type: string + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/admin.pcSimpleMessage' + "400": + description: Bad Request + schema: + $ref: '#/definitions/code.Failure' + security: + - LoginVerifyToken: [] + summary: 删除商品 + tags: + - 管理端.商品 + put: + consumes: + - application/json + parameters: + - description: 商品ID + in: path + name: product_id + required: true + type: string + - description: 请求参数 + in: body + name: RequestBody + required: true + schema: + $ref: '#/definitions/admin.modifyProductRequest' + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/admin.pcSimpleMessage' + "400": + description: Bad Request + schema: + $ref: '#/definitions/code.Failure' + security: + - LoginVerifyToken: [] + summary: 修改商品 + tags: + - 管理端.商品 + /api/admin/system_item_cards: + get: + consumes: + - application/json + description: 管理员获取道具卡列表,支持按名称、状态、类型等条件筛选 + parameters: + - description: 道具卡名称 + in: query + name: name + type: string + - description: 状态:1启用 2禁用 + in: query + name: status + type: integer + - description: 道具卡类型:1抽奖卡 2加成卡 3保底卡 + in: query + name: card_type + type: integer + - description: 适用范围:1全局 2活动分类 3活动 4期次 + in: query + name: scope_type + type: integer + - description: 页码,默认1 + in: query + name: page + type: integer + - description: 每页条数,默认10 + in: query + name: page_size + type: integer + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/admin.listItemCardsResponse' + "400": + description: 参数错误 + schema: + $ref: '#/definitions/code.Failure' + "401": + description: 未授权 + schema: + $ref: '#/definitions/code.Failure' + "500": + description: 服务器内部错误 + schema: + $ref: '#/definitions/code.Failure' + summary: 获取道具卡列表 + tags: + - 管理端.运营管理 post: consumes: - application/json - description: 新增小程序用户 + description: 管理员创建新的道具卡,支持设置类型、效果、有效期等属性 + parameters: + - description: 创建道具卡请求参数 + in: body + name: RequestBody + required: true + schema: + $ref: '#/definitions/admin.createItemCardRequest' + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/admin.createItemCardResponse' + "400": + description: 参数错误 + schema: + $ref: '#/definitions/code.Failure' + "401": + description: 未授权 + schema: + $ref: '#/definitions/code.Failure' + "403": + description: 无权限,仅超管可操作 + schema: + $ref: '#/definitions/code.Failure' + "500": + description: 服务器内部错误 + schema: + $ref: '#/definitions/code.Failure' + summary: 创建道具卡 + tags: + - 管理端.运营管理 + /api/admin/system_item_cards/{item_card_id}: + delete: + consumes: + - application/json + description: 管理员删除指定的道具卡 + parameters: + - description: 道具卡ID + in: path + name: item_card_id + required: true + type: integer + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/admin.simpleMessageResponse' + "400": + description: 参数错误 + schema: + $ref: '#/definitions/code.Failure' + "401": + description: 未授权 + schema: + $ref: '#/definitions/code.Failure' + "403": + description: 无权限,仅超管可操作 + schema: + $ref: '#/definitions/code.Failure' + "500": + description: 服务器内部错误 + schema: + $ref: '#/definitions/code.Failure' + summary: 删除道具卡 + tags: + - 管理端.运营管理 + put: + consumes: + - application/json + description: 管理员修改道具卡信息,支持修改名称、价格、有效期等属性 + parameters: + - description: 道具卡ID + in: path + name: item_card_id + required: true + type: integer + - description: 修改道具卡请求参数 + in: body + name: RequestBody + required: true + schema: + $ref: '#/definitions/admin.modifyItemCardRequest' + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/admin.simpleMessageResponse' + "400": + description: 参数错误 + schema: + $ref: '#/definitions/code.Failure' + "401": + description: 未授权 + schema: + $ref: '#/definitions/code.Failure' + "403": + description: 无权限,仅超管可操作 + schema: + $ref: '#/definitions/code.Failure' + "500": + description: 服务器内部错误 + schema: + $ref: '#/definitions/code.Failure' + summary: 修改道具卡 + tags: + - 管理端.运营管理 + /api/admin/users: + get: + consumes: + - application/json + description: 查看APP端用户分页列表 + parameters: + - default: 1 + description: 页码 + in: query + name: page + required: true + type: integer + - default: 20 + description: 每页数量,最多100 + in: query + name: page_size + required: true + type: integer + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/admin.listUsersResponse' + "400": + description: Bad Request + schema: + $ref: '#/definitions/code.Failure' + security: + - LoginVerifyToken: [] + summary: 管理端用户列表 + tags: + - 管理端.用户 + /api/admin/users/{user_id}/coupons: + get: + consumes: + - application/json + description: 查看指定用户持有的优惠券列表 + parameters: + - description: 用户ID + in: path + name: user_id + required: true + type: integer + - default: 1 + description: 页码 + in: query + name: page + required: true + type: integer + - default: 20 + description: 每页数量,最多100 + in: query + name: page_size + required: true + type: integer + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/admin.listCouponsResponse' + "400": + description: Bad Request + schema: + $ref: '#/definitions/code.Failure' + security: + - LoginVerifyToken: [] + summary: 查看用户优惠券列表 + tags: + - 管理端.用户 + /api/admin/users/{user_id}/coupons/add: + post: + consumes: + - application/json + description: 管理端为指定用户发放优惠券 + parameters: + - description: 用户ID + in: path + name: user_id + required: true + type: integer + - description: 请求参数 + in: body + name: RequestBody + required: true + schema: + $ref: '#/definitions/admin.addCouponRequest' + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/admin.addCouponResponse' + "400": + description: Bad Request + schema: + $ref: '#/definitions/code.Failure' + security: + - LoginVerifyToken: [] + summary: 给用户添加优惠券 + tags: + - 管理端.用户 + /api/admin/users/{user_id}/inventory: + get: + consumes: + - application/json + description: 查看指定用户的资产记录 + parameters: + - description: 用户ID + in: path + name: user_id + required: true + type: integer + - default: 1 + description: 页码 + in: query + name: page + required: true + type: integer + - default: 20 + description: 每页数量,最多100 + in: query + name: page_size + required: true + type: integer + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/admin.listInventoryResponse' + "400": + description: Bad Request + schema: + $ref: '#/definitions/code.Failure' + security: + - LoginVerifyToken: [] + summary: 查看用户资产列表 + tags: + - 管理端.用户 + /api/admin/users/{user_id}/invites: + get: + consumes: + - application/json + description: 查看指定用户邀请的用户列表 + parameters: + - description: 用户ID + in: path + name: user_id + required: true + type: integer + - default: 1 + description: 页码 + in: query + name: page + required: true + type: integer + - default: 20 + description: 每页数量,最多100 + in: query + name: page_size + required: true + type: integer + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/admin.listInvitesResponse' + "400": + description: Bad Request + schema: + $ref: '#/definitions/code.Failure' + security: + - LoginVerifyToken: [] + summary: 查看用户邀请列表 + tags: + - 管理端.用户 + /api/admin/users/{user_id}/item_cards: + post: + consumes: + - application/json + description: 管理员给指定用户分配道具卡,可指定数量 + parameters: + - description: 用户ID + in: path + name: user_id + required: true + type: integer + - description: 分配道具卡请求参数 + in: body + name: RequestBody + required: true + schema: + $ref: '#/definitions/admin.assignItemCardRequest' + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/admin.simpleMessageResponse' + "400": + description: 参数错误 + schema: + $ref: '#/definitions/code.Failure' + "401": + description: 未授权 + schema: + $ref: '#/definitions/code.Failure' + "403": + description: 无权限,仅超管可操作 + schema: + $ref: '#/definitions/code.Failure' + "500": + description: 服务器内部错误 + schema: + $ref: '#/definitions/code.Failure' + summary: 给用户分配道具卡 + tags: + - 管理端.运营管理 + /api/admin/users/{user_id}/orders: + get: + consumes: + - application/json + description: 查看指定用户的订单记录 + parameters: + - description: 用户ID + in: path + name: user_id + required: true + type: integer + - default: 1 + description: 页码 + in: query + name: page + required: true + type: integer + - default: 20 + description: 每页数量,最多100 + in: query + name: page_size + required: true + type: integer + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/admin.listOrdersResponse' + "400": + description: Bad Request + schema: + $ref: '#/definitions/code.Failure' + security: + - LoginVerifyToken: [] + summary: 查看用户订单列表 + tags: + - 管理端.用户 + /api/admin/users/{user_id}/points: + get: + consumes: + - application/json + description: 查看指定用户的积分流水记录 + parameters: + - description: 用户ID + in: path + name: user_id + required: true + type: integer + - default: 1 + description: 页码 + in: query + name: page + required: true + type: integer + - default: 20 + description: 每页数量,最多100 + in: query + name: page_size + required: true + type: integer + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/admin.listPointsResponse' + "400": + description: Bad Request + schema: + $ref: '#/definitions/code.Failure' + security: + - LoginVerifyToken: [] + summary: 查看用户积分记录 + tags: + - 管理端.用户 + /api/admin/users/{user_id}/points/add: + post: + consumes: + - application/json + description: 管理端为指定用户发放积分,支持设置有效期 + parameters: + - description: 用户ID + in: path + name: user_id + required: true + type: integer + - description: 请求参数 + in: body + name: RequestBody + required: true + schema: + $ref: '#/definitions/admin.addPointsRequest' + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/admin.addPointsResponse' + "400": + description: Bad Request + schema: + $ref: '#/definitions/code.Failure' + security: + - LoginVerifyToken: [] + summary: 给用户添加积分 + tags: + - 管理端.用户 + /api/admin/users/{user_id}/points/balance: + get: + consumes: + - application/json + description: 查看指定用户当前积分余额(过滤过期) + parameters: + - description: 用户ID + in: path + name: user_id + required: true + type: integer + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/admin.pointsBalanceResponse' + "400": + description: Bad Request + schema: + $ref: '#/definitions/code.Failure' + security: + - LoginVerifyToken: [] + summary: 查看用户积分余额 + tags: + - 管理端.用户 + /api/admin/users/{user_id}/rewards/grant: + post: + consumes: + - application/json + description: 管理员给用户发放奖励,支持实物和虚拟奖品,可选择关联活动和奖励配置 + parameters: + - description: 用户ID + in: path + name: user_id + required: true + type: integer + - description: 请求参数 + in: body + name: RequestBody + required: true + schema: + $ref: '#/definitions/admin.GrantRewardRequest' + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/admin.GrantRewardResponse' + "400": + description: Bad Request + schema: + $ref: '#/definitions/code.Failure' + "401": + description: Unauthorized + schema: + $ref: '#/definitions/code.Failure' + "403": + description: Forbidden + schema: + $ref: '#/definitions/code.Failure' + "500": + description: Internal Server Error + schema: + $ref: '#/definitions/code.Failure' + summary: 给用户发放奖励 + tags: + - 管理端.用户 + /api/app/activities: + get: + consumes: + - application/json + description: 获取活动列表,支持分类、Boss、状态过滤与分页 + parameters: + - description: 活动名称(模糊) + in: query + name: name + type: string + - description: 活动分类ID + in: query + name: category_id + type: integer + - description: 是否Boss(0/1) + in: query + name: is_boss + type: integer + - description: 状态(1进行中 2下线) + in: query + name: status + type: integer + - default: 1 + description: 页码 + in: query + name: page + required: true + type: integer + - default: 20 + description: 每页数量,最多100 + in: query + name: page_size + required: true + type: integer + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/app.listActivitiesResponse' + "400": + description: Bad Request + schema: + $ref: '#/definitions/code.Failure' + summary: 活动列表 + tags: + - APP端.活动 + /api/app/activities/{activity_id}: + get: + consumes: + - application/json + description: 获取指定活动的详细信息 + parameters: + - description: 活动ID + in: path + name: activity_id + required: true + type: integer + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/model.Activities' + "400": + description: Bad Request + schema: + $ref: '#/definitions/code.Failure' + summary: 活动详情 + tags: + - APP端.活动 + /api/app/activities/{activity_id}/issues: + get: + consumes: + - application/json + description: 获取指定活动的期列表,支持分页 + parameters: + - description: 活动ID + in: path + name: activity_id + required: true + type: integer + - default: 1 + description: 页码 + in: query + name: page + required: true + type: integer + - default: 20 + description: 每页数量,最多100 + in: query + name: page_size + required: true + type: integer + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/app.listIssuesResponse' + "400": + description: Bad Request + schema: + $ref: '#/definitions/code.Failure' + summary: 活动期列表 + tags: + - APP端.活动 + /api/app/activities/{activity_id}/issues/{issue_id}/draw_logs: + get: + consumes: + - application/json + description: 查看指定活动期数的抽奖记录,支持分页 + parameters: + - description: 活动ID + in: path + name: activity_id + required: true + type: integer + - description: 期ID + in: path + name: issue_id + required: true + type: integer + - default: 1 + description: 页码 + in: query + name: page + required: true + type: integer + - default: 20 + description: 每页数量,最多100 + in: query + name: page_size + required: true + type: integer + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/app.listDrawLogsResponse' + "400": + description: Bad Request + schema: + $ref: '#/definitions/code.Failure' + summary: 抽奖记录列表 + tags: + - APP端.活动 + /api/app/activities/{activity_id}/issues/{issue_id}/rewards: + get: + consumes: + - application/json + description: 获取指定期的奖励配置列表 + parameters: + - description: 活动ID + in: path + name: activity_id + required: true + type: integer + - description: 期ID + in: path + name: issue_id + required: true + type: integer + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/app.listRewardsResponse' + "400": + description: Bad Request + schema: + $ref: '#/definitions/code.Failure' + summary: 奖励配置列表 + tags: + - APP端.活动 + /api/app/banners: + get: + consumes: + - application/json + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/app.listAppBannersResponse' + "400": + description: Bad Request + schema: + $ref: '#/definitions/code.Failure' + summary: APP端轮播图列表 + tags: + - APP端.运营 + /api/app/guilds: + get: + consumes: + - application/json + description: 获取工会列表,支持公开与状态过滤以及分页 + parameters: + - description: 工会名称(模糊) + in: query + name: name + type: string + - description: 是否公开(1公开 2私有) + in: query + name: is_open + type: integer + - description: 状态(1正常 2解散) + in: query + name: status + type: integer + - description: 加入方式(1审核 2自动 3消费流水) + in: query + name: join_mode + type: integer + - default: 1 + description: 页码 + in: query + name: page + required: true + type: integer + - default: 20 + description: 每页数量,最多100 + in: query + name: page_size + required: true + type: integer + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/app.listGuildsResponse' + "400": + description: Bad Request + schema: + $ref: '#/definitions/code.Failure' + summary: 浏览工会列表 + tags: + - APP端.工会 + /api/app/guilds/{guild_id}: + get: + consumes: + - application/json + description: 查看指定工会详情 + parameters: + - description: 工会ID + in: path + name: guild_id + required: true + type: integer + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/model.Guild' + "400": + description: Bad Request + schema: + $ref: '#/definitions/code.Failure' + summary: 查看工会详情 + tags: + - APP端.工会 + /api/app/guilds/{guild_id}/members: + get: + consumes: + - application/json + description: 查看指定工会的成员列表 + parameters: + - description: 工会ID + in: path + name: guild_id + required: true + type: integer + - default: 1 + description: 页码 + in: query + name: page + required: true + type: integer + - default: 20 + description: 每页数量,最多100 + in: query + name: page_size + required: true + type: integer + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/app.listMembersResponse' + "400": + description: Bad Request + schema: + $ref: '#/definitions/code.Failure' + summary: 查看工会成员 + tags: + - APP端.工会 + post: + consumes: + - application/json + description: 用户加入指定工会 + parameters: + - description: 工会ID + in: path + name: guild_id + required: true + type: integer + - description: 请求参数 + in: body + name: RequestBody + required: true + schema: + $ref: '#/definitions/app.joinGuildRequest' + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/app.simpleMessageResponse' + "400": + description: Bad Request + schema: + $ref: '#/definitions/code.Failure' + summary: 加入工会 + tags: + - APP端.工会 + /api/app/guilds/{guild_id}/members/{user_id}: + delete: + consumes: + - application/json + description: 用户离开指定工会 + parameters: + - description: 工会ID + in: path + name: guild_id + required: true + type: integer + - description: 用户ID + in: path + name: user_id + required: true + type: integer + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/app.simpleMessageResponse' + "400": + description: Bad Request + schema: + $ref: '#/definitions/code.Failure' + summary: 离开工会 + tags: + - APP端.工会 + /api/app/users/{user_id}: + put: + consumes: + - application/json + description: 修改用户昵称与头像 + parameters: + - description: 用户ID + in: path + name: user_id + required: true + type: integer + - description: 请求参数 + in: body + name: RequestBody + required: true + schema: + $ref: '#/definitions/app.modifyUserRequest' + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/app.modifyUserResponse' + "400": + description: Bad Request + schema: + $ref: '#/definitions/code.Failure' + summary: 修改用户信息 + tags: + - APP端.用户 + /api/app/users/{user_id}/coupons: + get: + consumes: + - application/json + description: 查看用户持有的优惠券列表 + parameters: + - description: 用户ID + in: path + name: user_id + required: true + type: integer + - default: 1 + description: 页码 + in: query + name: page + required: true + type: integer + - default: 20 + description: 每页数量,最多100 + in: query + name: page_size + required: true + type: integer + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/app.listCouponsResponse' + "400": + description: Bad Request + schema: + $ref: '#/definitions/code.Failure' + summary: 查看用户优惠券 + tags: + - APP端.用户 + /api/app/users/{user_id}/invites: + get: + consumes: + - application/json + description: 查看被该用户邀请的用户列表 + parameters: + - description: 用户ID + in: path + name: user_id + required: true + type: integer + - default: 1 + description: 页码 + in: query + name: page + required: true + type: integer + - default: 20 + description: 每页数量,最多100 + in: query + name: page_size + required: true + type: integer + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/app.listInvitesResponse' + "400": + description: Bad Request + schema: + $ref: '#/definitions/code.Failure' + summary: 查看用户邀请记录 + tags: + - APP端.用户 + /api/app/users/{user_id}/item_cards: + get: + consumes: + - application/json + description: 获取指定用户的道具卡列表,支持分页 + parameters: + - description: 用户ID + in: path + name: user_id + required: true + type: integer + - description: 页码,默认1 + in: query + name: page + type: integer + - description: 每页条数,默认10 + in: query + name: page_size + type: integer + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/app.listUserItemCardsResponse' + "400": + description: 参数错误 + schema: + $ref: '#/definitions/code.Failure' + "401": + description: 未授权 + schema: + $ref: '#/definitions/code.Failure' + "500": + description: 服务器内部错误 + schema: + $ref: '#/definitions/code.Failure' + summary: 获取用户道具卡列表 + tags: + - APP端.用户 + /api/app/users/{user_id}/item_cards/uses: + get: + consumes: + - application/json + description: 获取指定用户的道具卡使用记录,支持分页 + parameters: + - description: 用户ID + in: path + name: user_id + required: true + type: integer + - description: 页码,默认1 + in: query + name: page + type: integer + - description: 每页条数,默认10 + in: query + name: page_size + type: integer + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/app.listUserItemCardUsesResponse' + "400": + description: 参数错误 + schema: + $ref: '#/definitions/code.Failure' + "401": + description: 未授权 + schema: + $ref: '#/definitions/code.Failure' + "500": + description: 服务器内部错误 + schema: + $ref: '#/definitions/code.Failure' + summary: 获取用户道具卡使用记录 + tags: + - APP端.用户 + /api/app/users/{user_id}/orders: + get: + consumes: + - application/json + description: 查看用户抽奖来源订单记录 + parameters: + - description: 用户ID + in: path + name: user_id + required: true + type: integer + - default: 1 + description: 页码 + in: query + name: page + required: true + type: integer + - default: 20 + description: 每页数量,最多100 + in: query + name: page_size + required: true + type: integer + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/app.listOrdersResponse' + "400": + description: Bad Request + schema: + $ref: '#/definitions/code.Failure' + summary: 查看用户订单记录 + tags: + - APP端.用户 + /api/app/users/{user_id}/phone/bind: + post: + consumes: + - application/json + description: 使用微信手机号 code 换取手机号并绑定到指定用户 + parameters: + - description: 用户ID + in: path + name: user_id + required: true + type: integer + - description: 请求参数 + in: body + name: RequestBody + required: true + schema: + $ref: '#/definitions/app.bindPhoneRequest' + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/app.bindPhoneResponse' + "400": + description: Bad Request + schema: + $ref: '#/definitions/code.Failure' + summary: 绑定手机号 + tags: + - APP端.用户 + /api/app/users/{user_id}/points: + get: + consumes: + - application/json + description: 查看用户积分流水记录 + parameters: + - description: 用户ID + in: path + name: user_id + required: true + type: integer + - default: 1 + description: 页码 + in: query + name: page + required: true + type: integer + - default: 20 + description: 每页数量,最多100 + in: query + name: page_size + required: true + type: integer + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/app.listPointsResponse' + "400": + description: Bad Request + schema: + $ref: '#/definitions/code.Failure' + summary: 查看用户积分记录 + tags: + - APP端.用户 + /api/app/users/{user_id}/points/balance: + get: + consumes: + - application/json + description: 查看用户积分余额(过滤过期积分) + parameters: + - description: 用户ID + in: path + name: user_id + required: true + type: integer + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/app.pointsBalanceResponse' + "400": + description: Bad Request + schema: + $ref: '#/definitions/code.Failure' + summary: 查看用户积分余额 + tags: + - APP端.用户 + /api/app/users/phone/login: + post: + consumes: + - application/json + description: 使用手机号登录,沿用 code 字段承载手机号或手机号授权码 parameters: - description: 请求参数 in: body name: RequestBody required: true schema: - $ref: '#/definitions/app.createAppUserRequest' + $ref: '#/definitions/app.phoneLoginRequest' produces: - application/json responses: "200": description: OK schema: - $ref: '#/definitions/app.createAppUserResponse' + $ref: '#/definitions/app.phoneLoginResponse' "400": description: Bad Request schema: $ref: '#/definitions/code.Failure' - summary: 新增小程序用户 + summary: 手机号登录 tags: - - 用户端 - /api/wechat/miniprogram/login: + - APP端.用户 + /api/app/users/weixin/login: post: consumes: - application/json - description: 通过AppID和code获取用户的openid,系统自动生成用户名和头像 + description: 微信静默登录(需传递 code;可选 invite_code) parameters: - description: 请求参数 in: body - name: request + name: RequestBody required: true schema: - $ref: '#/definitions/wechat.miniprogramLoginRequest' + $ref: '#/definitions/app.weixinLoginRequest' produces: - application/json responses: "200": description: OK schema: - $ref: '#/definitions/wechat.miniprogramLoginResponse' + $ref: '#/definitions/app.weixinLoginResponse' "400": description: Bad Request schema: $ref: '#/definitions/code.Failure' - "500": - description: Internal Server Error - schema: - $ref: '#/definitions/code.Failure' - summary: 小程序登录 + summary: 微信登录 tags: - - 微信 - /api/wechat/qrcode: - post: + - APP端.用户 + /api/role/list: + get: consumes: - application/json - description: 根据 AppID、AppSecret 和页面路径生成微信小程序二维码 parameters: - - description: 请求参数 - in: body - name: request + - default: 1 + description: 页码 + in: query + name: current required: true - schema: - $ref: '#/definitions/wechat.generateQRCodeRequest' + type: integer + - default: 20 + description: 每页数量 + in: query + name: size + required: true + type: integer + - description: 角色名称 + in: query + name: roleName + type: string + - description: 角色编码 + in: query + name: roleCode + type: string + - description: 是否启用 + in: query + name: enabled + type: boolean produces: - application/json responses: "200": description: OK schema: - $ref: '#/definitions/wechat.generateQRCodeResponse' - "400": - description: Bad Request - schema: - $ref: '#/definitions/code.Failure' - "500": - description: Internal Server Error - schema: - $ref: '#/definitions/code.Failure' - summary: 生成微信小程序二维码 + $ref: '#/definitions/admin.roleListResponse' + security: + - LoginVerifyToken: [] + summary: 角色列表 tags: - - 微信 - /api/wechat/subscribe: - post: + - 管理端.系统 + /api/user/list: + get: consumes: - application/json - description: 根据模板ID发送订阅消息 + description: 返回系统用户分页数据 parameters: - - description: 请求参数 - in: body - name: request + - default: 1 + description: 页码 + in: query + name: current required: true - schema: - $ref: '#/definitions/wechat.sendSubscribeMessageRequest' + type: integer + - default: 20 + description: 每页数量 + in: query + name: size + required: true + type: integer + - description: 用户名 + in: query + name: userName + type: string + - description: 邮箱 + in: query + name: userEmail + type: string + - description: 手机号 + in: query + name: userPhone + type: string + - description: 状态 + in: query + name: status + type: string produces: - application/json responses: "200": description: OK schema: - $ref: '#/definitions/wechat.sendSubscribeMessageResponse' - "400": - description: Bad Request - schema: - $ref: '#/definitions/code.Failure' - "404": - description: Not Found - schema: - $ref: '#/definitions/code.Failure' - "500": - description: Internal Server Error - schema: - $ref: '#/definitions/code.Failure' - summary: 发送订阅消息 + $ref: '#/definitions/admin.userListResponse' + security: + - LoginVerifyToken: [] + summary: 系统用户列表 tags: - - 微信 - /api/wechat/template: - post: - consumes: - - application/json - description: 根据 AppID 获取微信小程序的模板ID - parameters: - - description: 请求参数 - in: body - name: request - required: true - schema: - $ref: '#/definitions/wechat.templateRequest' - produces: - - application/json - responses: - "200": - description: OK - schema: - $ref: '#/definitions/wechat.templateResponse' - "400": - description: Bad Request - schema: - $ref: '#/definitions/code.Failure' - "404": - description: Not Found - schema: - $ref: '#/definitions/code.Failure' - "500": - description: Internal Server Error - schema: - $ref: '#/definitions/code.Failure' - summary: 获取微信小程序模板ID - tags: - - 微信 + - 管理端.系统 + /api/v3/system/menus/simple: + get: + responses: {} securityDefinitions: LoginVerifyToken: in: header diff --git a/docs/开发规范.md b/docs/开发规范.md new file mode 100644 index 0000000..438e482 --- /dev/null +++ b/docs/开发规范.md @@ -0,0 +1,539 @@ +# Go API 开发规范 + +## 1. 概述 + +### 1.1 目的 +本文档旨在为 `bindbox-game` 项目制定一套统一、清晰的 Go API 开发规范。通过标准化代码结构、命名约定、错误处理和文档注释,我们致力于提高代码的可读性、可维护性和团队协作效率,并从根本上避免之前开发中遇到的问题(如包导入不一致、特殊字符使用不当等)。 + +### 1.2 适用范围 +本规范主要适用于项目 `internal/api/` 目录下的所有 API 层的开发工作。所有新的 API 模块以及对现有模块的修改,都必须严格遵守本规范。 + +### 1.3 核心原则 +* **一致性**:所有代码都应遵循相同的模式和风格。 +* **清晰性**:代码应易于阅读和理解,避免复杂的或晦涩的实现。 +* **可维护性**:代码结构应清晰,便于未来扩展和重构。 +* **api/service**:代码结构应清晰,api 和 service 应该保持一致的命名规范。必须: 一个 api 对应一个 service。一个函数功能对应一个 service 方法。单独一个文件 +* **接口文档注释**:所有 API 端点都必须包含详细的 Swagger 注释,描述请求参数、响应体、可能的错误码等。 +* **测试功能**:所有 API 端点都必须包含详细的测试用例,确保功能的正确性和稳定性。(cmd/testchain/ 中写) + +--- + +## 2. 目录与文件结构 + +规范的目录结构是项目可维护性的基础。 + +* **模块化目录**:每一个独立的业务功能模块都应在 `internal/api/` 下创建一个专属目录。 + ``` + internal/api/ + ├── admin/ + ├── activity/ + └── ... (其他模块) + ``` + +* **Handler 结构体定义**:在每个模块目录下,应有一个与模块同名的 `go` 文件(如 `admin.go`),用于定义该模块的 `handler` 结构体和 `New` 初始化函数(注:Handler 不直接进行数据库读写)。 + ```go + // internal/api/admin/admin.go + package admin + + type handler struct { + logger logger.CustomLogger + writeDB *dao.Query // 仅用于注入(避免在 Handler 直接使用) + readDB *dao.Query // 仅用于注入(避免在 Handler 直接使用) + svc adminsvc.Service + } + + func New(logger logger.CustomLogger, db mysql.Repo) *handler { + return &handler{ + logger: logger, + writeDB: dao.Use(db.GetDbW()), + readDB: dao.Use(db.GetDbR()), + svc: adminsvc.New(logger, db), + } + } + ``` + +* **端点文件分离**:每个 API 端点(Endpoint)的实现应放在一个独立的 `go` 文件中,文件名应清晰描述其功能,示例对齐当前 `admin` 模块: + ``` + internal/api/admin/ + ├── admin.go // Handler 定义 + ├── login.go // 管理员登录 + ├── admin_create.go // 新增客服 + ├── admin_modify.go // 编辑客服(含路径参数) + ├── admin_delete.go // 删除客服(批量) + └── admin_list.go // 客服列表(分页查询) + ``` + +--- + +## 3. 命名规范 + +统一的命名规范能极大提升代码的可读性。 + +* **Go 文件**:使用小写蛇形命名法 (`snake_case`),如 `admin_create.go`。 +* **Handler 函数**:使用大驼峰命名法 (`PascalCase`),且函数名应清晰表达其动作,如 `CreateAdmin()`。 +* **请求/响应结构体**:使用小驼峰命名法 (`camelCase`),并以 `Request`/`Response` 作为后缀,如 `createAdminRequest`, `createAdminResponse`。 + +--- + +## 4. API Handler 规范 + +API Handler 是业务逻辑的入口,其规范性至关重要。 + +### 4.1 函数签名 +所有 API Handler 函数都必须返回 `core.HandlerFunc` 类型。这是框架的核心设计,用于统一处理请求上下文。 + +```go +// CreateAdmin 新增客服 +func (h *handler) CreateAdmin() core.HandlerFunc { + return func(ctx core.Context) { + // ... 实现 + } +} +``` + +### 4.2 参数绑定与校验 +* **绑定(JSON)**:POST/PUT 等带请求体的接口使用 `ctx.ShouldBindJSON(req)` 绑定到预定义的 `Request` 结构体。 +* **绑定(Query)**:GET 查询接口使用 `ctx.ShouldBindForm(req)` 绑定到预定义的 `Request` 结构体(字段使用 `form:"..."` tag)。 +* **路径参数**:通过 `ctx.Param("id")` 等读取路径参数并进行类型转换与校验。 +* **校验**:绑定方法会自动执行 `binding` tag 定义的校验规则。如果校验失败,必须立即中断请求并返回错误。 + +```go +req := new(createAdminRequest) +res := new(createAdminResponse) +if err := ctx.ShouldBindJSON(req); err != nil { + ctx.AbortWithError(core.Error( + http.StatusBadRequest, + code.ParamBindError, + validation.Error(err)), + ) + return +} +``` + +```go +// GET 查询绑定示例(与 admin_list 对齐) +req := new(listRequest) +res := new(listResponse) +if err := ctx.ShouldBindForm(req); err != nil { + ctx.AbortWithError(core.Error( + http.StatusBadRequest, + code.ParamBindError, + validation.Error(err)), + ) + return +} +``` + +```go +// 路径参数读取示例(与 admin_modify 对齐) +id, err := strconv.Atoi(ctx.Param("id")) +if err != nil { + ctx.AbortWithError(core.Error( + http.StatusBadRequest, + code.ParamBindError, + "未传递编号ID"), + ) + return +} +``` + +### 4.3 响应处理 +* **成功响应**:当业务逻辑成功执行后,必须使用 `ctx.Payload(res)` 方法来返回标准的成功响应。`res` 是预定义的 `Response` 结构体实例。 + ```go + res.Message = "操作成功" + ctx.Payload(res) + ``` +* **错误响应**:见第 6 章“错误处理规范”。 + +--- + +## 5. 数据传输对象 (DTO) 规范 + +DTO (Data Transfer Object) 是 API 契约的直接体现。 + +* **结构体定义**:每个 API 都应定义清晰的 `Request` 和 `Response` 结构体。 +* **字段注释**:所有结构体字段都必须有清晰的中文注释,解释其含义和用途。 +* **JSON Tag**:所有字段都必须包含 `json:"..."` tag,以确保与前端交互的 JSON 字段名一致。 +* **Validation Tag**:对于 `Request` 结构体中需要校验的字段,必须添加 `binding:"..."` tag 来定义校验规则(如 `required`)。 + +```go +// internal/api/admin/admin_create.go + +type createAdminRequest struct { + UserName string `json:"username" binding:"required"` // 用户名 + NickName string `json:"nickname" binding:"required"` // 昵称 + Password string `json:"password" binding:"required"` // 密码 + Mobile string `json:"mobile"` // 手机号 (非必填) +} + +type createAdminResponse struct { + Message string `json:"message"` // 提示信息 +} +``` + +```go +// internal/api/admin/admin_list.go +// GET 查询示例(字段使用 form 标签) +type listRequest struct { + Username string `form:"username"` // 用户名 + Nickname string `form:"nickname"` // 昵称 + Page int `form:"page"` // 当前页码,默认 1 + PageSize int `form:"page_size"` // 每页返回的数据量,最多 100 条 +} + +type listData struct { + ID int32 `json:"id"` + UserName string `json:"username"` + NickName string `json:"nickname"` + Mobile string `json:"mobile"` + Avatar string `json:"avatar"` + CreatedAt string `json:"created_at"` + UpdatedAt string `json:"updated_at"` +} + +type listResponse struct { + Page int `json:"page"` + PageSize int `json:"page_size"` + Total int64 `json:"total"` + List []listData `json:"list"` +} +``` + +--- + +## 6. 错误处理规范 + +统一的错误处理是保证 API 健壮性和可预测性的关键。 + +* **统一入口**:所有在 Handler 中捕获的错误(参数校验失败、数据库操作失败、权限不足等)都必须通过 `ctx.AbortWithError()` 函数来处理。 +* **`core.Error` 结构**:`ctx.AbortWithError` 接收一个 `core.Error` 对象,该对象封装了错误的三个核心要素: + 1. **HTTP 状态码**:如 `http.StatusBadRequest`。 + 2. **业务错误码**:在 `internal/code/` 中预定义的 `code.Code`,如 `code.CreateAdminError`。 + 3. **详细错误信息**:一个描述错误具体原因的字符串。 + +* **未找到记录**:当数据库查询返回 `gorm.ErrRecordNotFound` 时,需要按具体业务错误码返回明确的提示信息(如“账号不存在”)。 +* **权限校验失败**:当 `ctx.SessionUserInfo().IsSuper != 1` 时,禁止操作,返回对应业务错误码和提示“禁止操作”。 + +```go +// 示例:用户已存在 +if info != nil { + ctx.AbortWithError(core.Error( + http.StatusBadRequest, + code.CreateAdminError, + fmt.Sprintf("%s: %s", code.Text(code.CreateAdminError), "该账号已存在")), + ) + return +} +``` + +```go +// 示例:未找到记录(与 admin_modify/login 对齐) +if err == gorm.ErrRecordNotFound { + ctx.AbortWithError(core.Error( + http.StatusBadRequest, + code.AdminLoginError, + fmt.Sprintf("%s: %s", code.Text(code.AdminLoginError), "账号不存在,请联系管理员。")), + ) + return +} +``` + +```go +// 示例:权限校验失败(与 create/modify/delete/list 对齐) +if ctx.SessionUserInfo().IsSuper != 1 { + ctx.AbortWithError(core.Error( + http.StatusBadRequest, + code.CreateAdminError, + fmt.Sprintf("%s: %s", code.Text(code.CreateAdminError), "禁止操作")), + ) + return +} +``` + +--- + +### 6.1 数据库上下文与读写分离(Service 层) +* **上下文传递**:所有数据库操作必须调用 `WithContext(ctx)`(Service 层接收 `context.Context`)。 +* **读写分离**:读取使用 `s.readDB`,写入使用 `s.writeDB`。 +* **分页查询会话**:分页列表与计数需要分别创建独立会话,避免互相影响。 + +```go +query := s.readDB.Admin.WithContext(ctx) +listQueryDB := query.Session(&gorm.Session{}) +countQueryDB := query.Session(&gorm.Session{}) + +resultData, err := listQueryDB.Order(s.readDB.Admin.ID.Desc()).Limit(in.PageSize).Offset((in.Page-1)*in.PageSize).Find() +if err != nil { /* 错误处理 */ } + +count, err := countQueryDB.Count() +if err != nil { /* 错误处理 */ } +``` + +--- + +## 7. 日志记录规范 + +虽然在 `admin` 模块的示例中未显式大量使用,但规范的日志记录对于问题排查至关重要。 + +* **使用注入的 Logger**:应通过 `handler` 结构体中注入的 `h.logger` 实例来记录日志。 +* **记录关键信息**:在关键业务节点或错误发生时,记录必要的上下文信息,如请求参数、用户 ID 等。 + +```go +// 推荐实践 (示例) +h.logger.Error("创建管理员失败", zap.Error(err), zap.String("username", req.UserName)) +``` + +--- + +## 8. 注释与文档 (Swagger) + +API 的可发现性和易用性依赖于完善的文档。 + +* **强制 Swagger 注解**:每个 API Handler 函数上方都必须添加完整的 Swagger 注解块。 +* **注解内容**:必须包含以下核心注解: + * `@Summary`:一句话功能简介。 + * `@Description`:更详细的功能描述。 + * `@Tags`:API 分组标签,便于在 Swagger UI 中分类。 + * `@Accept` / `@Produce`:通常为 `json`。 + * `@Param`:描述请求参数,包括参数位置(`body`)、类型、是否必需和说明。 + * `@Success`:描述成功响应的结构。 + * `@Failure`:描述可能发生的错误响应。 + * `@Router`:API 的路由路径和 HTTP 方法。 + * `@Security`:如果接口需要认证,需添加此注解。 + +```go +// internal/api/admin/admin_create.go + +// CreateAdmin 新增客服 +// @Summary 新增客服 +// @Description 新增客服 +// @Tags 管理端.客服管理 +// @Accept json +// @Produce json +// @Param RequestBody body createAdminRequest true "请求参数" +// @Success 200 {object} createAdminResponse +// @Failure 400 {object} code.Failure +// @Router /api/admin/create [post] +// @Security LoginVerifyToken +func (h *handler) CreateAdmin() core.HandlerFunc { /* ... */ } + +// internal/api/admin/admin_list.go(GET 查询示例) +// @Param username query string false "用户名" +// @Param nickname query string false "昵称" +// @Param page query int true "当前页码" default(1) +// @Param page_size query int true "每页返回的数据量,最多 100 条" default(20) +// @Router /api/admin/list [get] +// @Security LoginVerifyToken + +// internal/api/admin/admin_modify.go(路径参数示例) +// @Param id path string true "编号ID" +// @Router /api/admin/{id} [put] +// @Security LoginVerifyToken + +// internal/api/admin/login.go(登录接口不加 Security) +// @Router /api/admin/login [post] +``` + +--- + +## 9. 路由与中间件规范 + +路由是 API 对外的入口,必须与模块职责、认证策略保持一致,并在 `internal/router/router.go` 统一注册。 + +### 9.1 分组与路径前缀 +- **管理端**:统一前缀 `"/api/admin"` + - 非认证组:用于登录、系统状态等不需要鉴权的接口。 + - 认证组:使用鉴权中间件保护,适用于敏感操作(新增、编辑、删除、列表)。 +- **用户端(APP)**:统一前缀 `"/api/app"`,用于对外业务接口(如活动相关)。 + +### 9.2 鉴权中间件 +- **封装方式**:通过 `core.WrapAuthHandler(interceptor.AdminTokenAuthVerify)` 将会话信息写入上下文,认证失败统一返回业务错误。 +- **接口签名**:`internal/router/interceptor/interceptor.go:12-18` 定义了鉴权接口: + `AdminTokenAuthVerify(ctx core.Context) (sessionUserInfo proposal.SessionUserInfo, err core.BusinessError)`。 +- **实现参考**:管理端鉴权实现见 `internal/router/interceptor/admin_auth.go:1-80`。 + +### 9.3 路由注册示例(与当前 admin 模块对齐) +```go +// internal/router/router.go + +// 管理端非认证接口路由组(登录) +adminNonAuthApiRouter := mux.Group("/api/admin") +{ + adminNonAuthApiRouter.GET("/license/status", func(ctx core.Context) { /* ... */ }) + adminNonAuthApiRouter.POST("/login", adminHandler.Login()) +} + +// 管理端认证接口路由组(需要 Authorization) +adminAuthApiRouter := mux.Group("/api/admin", core.WrapAuthHandler(intc.AdminTokenAuthVerify)) +{ + adminAuthApiRouter.POST("/create", adminHandler.CreateAdmin()) + adminAuthApiRouter.PUT("/:id", adminHandler.ModifyAdmin()) + adminAuthApiRouter.POST("/delete", adminHandler.DeleteAdmin()) + adminAuthApiRouter.GET("/list", adminHandler.PageList()) +} + +// APP 端接口路由组 +appApiRouter := mux.Group("/api/app") +{ + appHandler := app.New(logger, db) + appApiRouter.GET("/activities", appHandler.ListActivities()) + // ... 其他 APP 端接口 +} +``` + +### 9.4 Swagger 安全定义与使用 +- **安全定义位置**:`main.go:23-26` 定义认证方案 `LoginVerifyToken`,从请求头读取 `Authorization`。 +- **注解使用规范**: + - 管理端认证组接口均需添加 `@Security LoginVerifyToken`。 + - 登录接口不需要添加 `@Security` 注解。 + +### 9.5 路径命名与语义 +- **资源语义**: + - `POST /api/admin/create`:创建资源(支持复杂校验与默认值设置)。 + - `PUT /api/admin/:id`:更新单个资源,路径参数 `id` 必须有效。 + - `POST /api/admin/delete`:批量删除,参数 `ids` 以逗号分隔。 + - `GET /api/admin/list`:分页检索,`page`/`page_size` 合理限制(最大 100)。 +- **用户端**:保持 RESTful 风格,如 `GET /api/app/activities`、`GET /api/app/activities/:activity_id`。 + +### 9.6 指标与别名(可选) +- 为避免路径参数导致指标维度爆炸,可在 Handler 前添加别名记录指标: +```go +// 例如:为 /api/app/activities/:activity_id 设置指标记录别名 +appApiRouter.GET("/activities/:activity_id", + core.AliasForRecordMetrics("/api/app/activities/:activity_id"), + appHandler.GetActivityDetail(), +) +``` + +--- + +## 10. 服务层分离规范 + +为避免 Handler 同时承担传输与业务职责,必须在 `internal/service/{module}` 引入服务层,统一承载业务规则、数据协作与事务处理。 + +### 10.1 目录与命名 +- 目录:`internal/service/admin`、`internal/service/activity` 等按模块划分。 +- 包名:与模块名一致,Handler 导入时使用别名避免冲突(如 `svc "bindbox-game/internal/service/admin"`)。 + +### 10.1.1 文件拆分(与 API 端点保持一致) +- 每个端点在服务层对应一个实现文件,避免所有方法堆叠在单文件: + ``` + internal/service/admin/ + ├── service.go // 接口、构造 + ├── login.go // 登录 + ├── create.go // 新增客服 + ├── modify.go // 编辑客服 + ├── delete.go // 删除客服 + └── list.go // 客服列表 + ``` + - 规则:每个端点的输入/输出类型在对应文件中定义(例如 `LoginInput`/`LoginResult` 在 `login.go`)。 + +--- + +## 11. 流程规范(Router → API → Service) + +### 11.1 职责边界 +- Router:负责分组、认证拦截与端点注册;不承载业务逻辑。 + - 管理端非认证路由:`internal/router/router.go:44-51` + - 管理端认证路由(鉴权中间件):`internal/router/router.go:53-60` + - 用户端 APP 路由:`internal/router/router.go:62-72` +- API(Handler):负责参数绑定、权限校验、错误码映射与响应输出;不直接操作数据库。 + - 绑定参数并校验:如登录 `internal/api/admin/login.go:35-45`、列表 `internal/api/admin/admin_list.go:57-64` + - 权限校验:如列表 `internal/api/admin/admin_list.go:83-90`、创建 `internal/api/admin/admin_create.go:49-56` + - 错误码映射与响应:如登录 `internal/api/admin/login.go:53-59,61-64` +- Service:承载领域逻辑、数据访问与事务;输入/输出类型在对应端点文件中定义。 + - 登录实现:`internal/service/admin/login.go:16-52` + - 创建实现:`internal/service/admin/admin_create.go:14-42` + - 编辑实现:`internal/service/admin/admin_modify.go:13-50` + - 删除实现:`internal/service/admin/admin_delete.go:9-15` + - 列表实现:`internal/service/admin/admin_list.go:12-38` + +### 11.2 端到端流程(以管理端为例) +- Router 接收请求并路由到对应分组:非认证或认证(携带 `Authorization`)。 +- 若为认证接口,鉴权中间件注入会话信息:`internal/router/interceptor/admin_auth.go:1-80`。 +- Handler: + - `ShouldBindJSON` 或 `ShouldBindForm` 解析请求(含路径参数 `ctx.Param`)。 + - 权限检查(如 `ctx.SessionUserInfo().IsSuper`)。 + - 将 DTO 转换为 Service 输入,调用 `svc.*(ctx.RequestContext(), input)`。 + - 根据 Service 返回的错误映射业务错误码,或输出成功响应 `ctx.Payload(res)`。 +- Service: + - 使用 `dao.Query.WithContext` 与读写分离实现查询或写入。 + - 必要场景内使用事务保障原子性(参考 `dao.gen.go` 的 `Query.Transaction`)。 + +### 11.3 错误处理策略 +- Service 返回语义化错误信息(`error`);不直接决定 HTTP 或业务码。 +- Handler 统一映射到 `core.Error(httpCode, code.* , message)` 并 `AbortWithError`。 + - 登录错误映射:`internal/api/admin/login.go:53-59` + - 创建错误映射:`internal/api/admin/admin_create.go:66-71` + - 编辑错误映射:`internal/api/admin/admin_modify.go:87-93` + - 删除错误映射:`internal/api/admin/admin_delete.go:95-102` + - 列表错误映射:`internal/api/admin/admin_list.go:98-105` + +### 11.4 数据绑定与类型转换 +- 登录:`loginRequest` → `LoginInput` 映射:`internal/api/admin/login.go:47-51` +- 创建:`createAdminRequest` → `CreateInput` 映射:`internal/api/admin/admin_create.go:58-65` +- 编辑:`modifyAdminRequest` → `ModifyInput` 映射:`internal/api/admin/admin_modify.go:79-86` +- 列表:`listRequest(form)` → `ListInput` 映射:`internal/api/admin/admin_list.go:92-97` +- 删除:解析 `ids` 列表后直接传入 `svc.Delete`:`internal/api/admin/admin_delete.go:95` + +### 11.5 事务与读写分离 +- 读操作统一使用 `readDB`,写操作统一使用 `writeDB`。 +- 所有 DAO 调用必须附带上下文:`WithContext(ctx)`。 +- 多步骤写操作建议在 Service 层使用事务(`Query.Transaction`):`internal/repository/mysql/dao/gen.go:211-213`。 + +### 11.6 鉴权与会话 +- 路由层通过 `core.WrapAuthHandler(intc.AdminTokenAuthVerify)` 进行会话注入:`internal/router/router.go:53-60`。 +- 鉴权逻辑参考:`internal/router/interceptor/admin_auth.go:1-80`。 +- Handler 使用 `ctx.SessionUserInfo()` 获取操作者信息(如 `CreatedBy`、`UpdatedBy`)。 + +### 11.7 命名与拆分 +- API 与 Service 均按端点拆分文件,命名对齐,便于定位与维护。 +- Service 的输入/输出类型在对应端点文件定义(如 `login.go` 定义 `LoginInput/LoginResult`)。 + +--- + +## 12. Repository 规范 + +### 12.1 层职责 +- 负责数据访问(CRUD、分页、事务),不包含业务规则与 HTTP 细节。 +- 仅依赖底层 DAO/Model,向 Service 层提供稳定的数据操作能力。 + +### 12.2 目录与组件 +- 目录:`internal/repository/mysql` + - `dao/`:由 `gorm/gen` 生成的查询对象与读写分离封装,参考: + - 读写分离方法:`internal/repository/mysql/dao/gen.go:135-143` + - 事务封装:`internal/repository/mysql/dao/gen.go:211-213` + - 上下文绑定:`internal/repository/mysql/dao/gen.go:188-209` + - `model/`:数据库对应的实体结构体(字段、标签)。 + +### 12.3 使用规范(在 Service 层) +- 初始化查询对象: + - 读库:`readDB := dao.Use(db.GetDbR())` + - 写库:`writeDB := dao.Use(db.GetDbW())` +- 所有操作必须绑定上下文:`WithContext(ctx)`,示例(查询管理员): +```go +info, err := s.readDB.Admin.WithContext(ctx). + Where(s.readDB.Admin.Username.Eq(in.Username)). + First() +``` +- 分页与计数使用独立会话,避免互相影响: +```go +listQueryDB := query.Session(&gorm.Session{}) +countQueryDB := query.Session(&gorm.Session{}) +items, _ := listQueryDB.Order(...).Limit(...).Offset(...).Find() +total, _ := countQueryDB.Count() +``` +- 多步骤写操作建议在事务中完成: +```go +_ = s.writeDB.Transaction(func(tx *dao.Query) error { + // 在 tx 上执行写操作 + return nil +}) +``` + +### 12.4 分层建议 +- 如需进一步解耦 DAO,可在 `internal/repository/{module}` 定义模块级仓库接口(如 `adminrepo`),内部封装 DAO 细节;Service 只依赖仓库接口,便于单元测试与替换数据源。 +- 目前项目直接在 Service 层使用 DAO,符合轻量项目场景;当跨表协作复杂时可引入仓库接口以降低耦合。 + + + diff --git a/docs/开发规范/ALIGNMENT_开发规范.md b/docs/开发规范/ALIGNMENT_开发规范.md new file mode 100644 index 0000000..995d3f4 --- /dev/null +++ b/docs/开发规范/ALIGNMENT_开发规范.md @@ -0,0 +1,40 @@ +# ALIGNMENT: 开发规范 + +## 1. 原始需求 + +根据用户指令,需要完成以下任务: +1. **学习现有代码**:参考 `/internal/api/admin` 目录下的代码实现。 +2. **制定开发规范**:总结并编写一份项目开发规范文档。 +3. **核心要求**: + * 新代码必须导入对应的包。 + * 遵循项目已有的代码风格和结构。 + * 所有的注释都必须是中文。 + +## 2. 边界确认 + +* **输入**: + * 项目源码,特别是 `/internal/api/admin` 目录。 + * 用户的口头指令和规范要求。 +* **输出**: + * 一份名为 `docs/开发规范.md` 的 Markdown 文档。 + * 文档内容需清晰、准确,能作为后续开发的指导。 +* **范围**: + * 本次任务的核心是**学习和文档化**,不涉及新的功能开发或代码修改。 + * 规范内容应主要涵盖 API 层(Handler)的编写风格,包括但不限于: + * 目录结构和文件命名。 + * 请求/响应数据结构(DTO)定义。 + * Swagger 注解的使用。 + * `core.HandlerFunc` 的实现模式。 + * 参数绑定和校验。 + * 错误处理机制。 + * 日志记录。 + +## 3. 需求理解 + +用户希望通过分析现有成熟的代码(`/internal/api/admin`),提炼出一套适用于本项目所有模块开发的统一规范。这套规范旨在解决之前开发过程中遇到的问题(如包导入不全、特殊字符使用不当),并确保未来代码的一致性、可读性和可维护性。 + +这本质上是一个**逆向工程和标准化**的过程:从已有实现中总结出最佳实践,并将其固化为团队必须遵守的规则。 + +## 4. 疑问澄清 + +目前没有需要立即澄清的疑问。我将首先分析代码,然后根据分析结果来组织规范文档的结构和内容。如果在此过程中发现任何歧义或需要决策的地方,我会再提出。 diff --git a/docs/开发规范/APP端开发统一规范.md b/docs/开发规范/APP端开发统一规范.md new file mode 100644 index 0000000..dd7ca23 --- /dev/null +++ b/docs/开发规范/APP端开发统一规范.md @@ -0,0 +1,146 @@ +# APP 端开发统一规范 + +## 1. 目标 +统一 APP 端接口的目录结构、编码范式、错误处理与文档注释,确保与管理端(admin 模块)保持一致的风格与契约。 + +## 2. 目录结构 +- 模块放置:`internal/api/activity/` +- 每个端点单文件: + - `activity_create.go` + - `activity_issue_add.go` + - `activity_list.go` + - `activity_detail.go` + - `activity_issues_list.go` + - `issue_rewards_list.go` + +## 3. Handler 初始化 +- 在模块根定义 `handler` 与 `New(logger, db)`,注入 `writeDB`/`readDB` +- 路由绑定示例:`appHandler := app.New(logger, db)`,方法统一返回 `core.HandlerFunc` + +## 4. 请求/响应范式 +- 所有接口必须定义 `Request` 与 `Response` 结构体 +- 成功统一:`ctx.Payload(res)`,`res.Message` 使用统一文案 `操作成功` + +## 5. 参数绑定与校验 +- JSON:`ctx.ShouldBindJSON(req)` +- 表单/查询:`ctx.ShouldBindForm(req)` +- 绑定错误:`ctx.AbortWithError(core.Error(http.StatusBadRequest, code.ParamBindError, validation.Error(err)))` + +## 6. 业务错误处理 +- 统一:`ctx.AbortWithError(core.Error(http.StatusBadRequest, code.ServerError, err.Error()))` +- 业务码:在 `internal/code/` 中约定并使用具体业务码 + +## 7. 分页与过滤规范 +- 分页:`page` 默认 1、`page_size` 默认 20、最大 100,超过返回参数错误 +- 过滤:字符串使用 `Like("%xxx%")`,数值/枚举使用 `Eq(...)`,`is_boss` 仅允许 `0/1` + +## 8. 路径参数规范 +- 使用 `strconv.Atoi` 并校验 `> 0`,非法返回 `ParamBindError` + +## 9. 时间规范 +- 入参解析:`timeutil.ParseCSTInLocation` +- 响应时间:`FriendlyTime` 或固定格式化 `2006-01-02 15:04` + +## 10. Swagger 注释规范 +- 标签:APP 端统一使用 `@Tags APP端.活动`(或模块名) +- 必填注释:`@Summary/@Description/@Accept/@Produce/@Param/@Success/@Failure/@Router` + +## 11. 统一 Handler 模板(示例) +以下示例来自 `internal/api/activity/activity_issues_list.go:46-127`,作为 APP 端列表接口标准参考: + +```go +// ListActivityIssues 活动期列表 +// @Summary 活动期列表 +// @Description 获取指定活动的期列表,支持分页 +// @Tags APP端.活动 +// @Accept json +// @Produce json +// @Param activity_id path int true "活动ID" +// @Param page query int true "页码" default(1) +// @Param page_size query int true "每页数量,最多100" default(20) +// @Success 200 {object} listIssuesResponse +// @Failure 400 {object} code.Failure +// @Router /api/app/activities/{activity_id}/issues [get] +func (h *handler) ListActivityIssues() core.HandlerFunc { + return func(ctx core.Context) { + idStr := ctx.Param("activity_id") + id, err := strconv.Atoi(idStr) + if err != nil || id <= 0 { + ctx.AbortWithError(core.Error( + http.StatusBadRequest, + code.ParamBindError, + "活动ID无效"), + ) + return + } + + req := new(listIssuesRequest) + res := new(listIssuesResponse) + if err := ctx.ShouldBindForm(req); err != nil { + ctx.AbortWithError(core.Error( + http.StatusBadRequest, + code.ParamBindError, + validation.Error(err)), + ) + return + } + if req.Page == 0 { req.Page = 1 } + if req.PageSize == 0 { req.PageSize = 20 } + if req.PageSize > 100 { + ctx.AbortWithError(core.Error( + http.StatusBadRequest, + code.ParamBindError, + "每页最多100条"), + ) + return + } + + query := h.readDB.ActivityIssues.WithContext(ctx.RequestContext()). + Where(h.readDB.ActivityIssues.ActivityID.Eq(int64(id))) + listQuery := query + countQuery := query + + issues, err := listQuery.Order(h.readDB.ActivityIssues.ID.Desc()). + Limit(req.PageSize).Offset((req.Page-1)*req.PageSize).Find() + if err != nil { + ctx.AbortWithError(core.Error( + http.StatusBadRequest, + code.ServerError, + err.Error()), + ) + return + } + + total, err := countQuery.Count() + if err != nil { + ctx.AbortWithError(core.Error( + http.StatusBadRequest, + code.ServerError, + err.Error()), + ) + return + } + + res.Page = req.Page + res.PageSize = req.PageSize + res.Total = total + res.List = make([]issueListItem, len(issues)) + for i, v := range issues { + res.List[i] = issueListItem{ + ID: v.ID, + IssueNumber: v.IssueNumber, + Status: v.Status, + Sort: v.Sort, + CreatedAt: timeutil.FriendlyTime(v.CreatedAt), + UpdatedAt: timeutil.FriendlyTime(v.UpdatedAt), + } + } + ctx.Payload(res) + } +} +``` + +## 12. 文档生成与预览 +- 生成:`make gen-swagger` +- 预览:`make serve-swagger`(默认端口 `36666`,访问 `http://localhost:36666/docs`) + diff --git a/docs/开发规范/CONSENSUS_开发规范.md b/docs/开发规范/CONSENSUS_开发规范.md new file mode 100644 index 0000000..f93625f --- /dev/null +++ b/docs/开发规范/CONSENSUS_开发规范.md @@ -0,0 +1,38 @@ +# CONSENSUS: 开发规范 + +## 1. 需求描述和验收标准 + +**需求描述**: +基于对 `/internal/api/admin` 模块代码的分析,制定一套清晰、统一的 Go API 开发规范。该规范将作为项目后续所有 API 开发的强制标准,以确保代码质量、一致性和可维护性。 + +**验收标准**: +1. 生成一份完整的 `docs/开发规范.md` 文档。 +2. 文档内容必须准确反映从 `admin` 模块总结出的最佳实践。 +3. 规范应覆盖从 API 定义、实现到错误处理的全过程。 +4. 规范应明确代码风格、目录结构、命名约定等关键要素。 +5. 所有示例代码必须符合规范本身,并能作为开发者参考的模板。 + +## 2. 技术实现方案 + +将遵循以下步骤来产出最终的规范文档: + +1. **结构设计**:将规范文档分为不同章节,如“目录结构”、“命名规范”、“API Handler 规范”、“数据传输对象 (DTO)”、“错误处理”等。 +2. **内容撰写**:在每个章节中,详细描述具体的规则,并提供从 `admin` 模块中提取的**正例代码**作为示范。 +3. **规则提炼**:将观察到的模式提炼为必须遵守的规则,例如: + * 每个 API Handler 必须返回 `core.HandlerFunc`。 + * 使用 `ctx.ShouldBindJSON()` 进行参数绑定和基础校验。 + * 通过 `ctx.AbortWithError()` 统一处理错误。 + * 使用 `ctx.Payload()` 返回成功响应。 + * 请求和响应结构体必须包含 `json` tag,并提供清晰的字段注释。 + * 必须为每个 API 编写完整的 Swagger 注解。 +4. **文档生成**:将所有内容整合到 `docs/开发规范.md` 文件中。 + +## 3. 任务边界限制 + +* **仅限于文档**:此任务不涉及任何代码的创建、修改或删除。 +* **聚焦于 API 层**:规范主要针对 `internal/api` 层的开发,对于 `service` 层和 `repository` 层的规范,虽然可以借鉴其思想,但不是本次任务的重点。 +* **基于现有实践**:所有规范都必须源于对现有 `admin` 代码的分析,不允许凭空创造规则。 + +## 4. 确认所有不确定性已解决 + +通过 `ALIGNMENT` 阶段的分析,所有关于任务目标、范围和方法的不确定性均已解决。现在可以进入 `Architect`(架构)阶段,设计最终规范文档的详细结构。 diff --git a/docs/开发规范/DESIGN_开发规范.md b/docs/开发规范/DESIGN_开发规范.md new file mode 100644 index 0000000..0ea90a5 --- /dev/null +++ b/docs/开发规范/DESIGN_开发规范.md @@ -0,0 +1,81 @@ +# DESIGN: 开发规范文档设计 + +本文档定义了最终 `docs/开发规范.md` 的结构和核心内容,旨在为后续的文档撰写提供清晰的蓝图。 + +## 1. 整体结构 + +最终的开发规范文档将分为以下几个核心章节,每个章节都将包含详细的规则描述和代码示例。 + +```mermaid +graph TD + A[开发规范] --\u003e B[1. 概述]; + A --\u003e C[2. 目录与文件结构]; + A --\u003e D[3. 命名规范]; + A --\u003e E[4. API Handler 规范]; + A --\u003e F[5. 数据传输对象 (DTO) 规范]; + A --\u003e G[6. 错误处理规范]; + A --\u003e H[7. 日志记录规范]; + A --\u003e I[8. 注释与文档(Swagger)]; + + subgraph E [4. API Handler 规范] + E1[4.1 Handler 定义] + E2[4.2 路由与函数签名] + E3[4.3 参数绑定与校验] + E4[4.4 业务逻辑调用] + E5[4.5 响应处理] + end + + subgraph F [5. 数据传输对象 (DTO) 规范] + F1[5.1 Request/Response 结构体] + F2[5.2 JSON Tags] + F3[5.3 Validation Tags] + end +``` + +## 2. 核心章节设计 + +### 2.1 概述 +* **目的**:阐明制定此规范的背景和目标。 +* **范围**:明确规范的适用范围(API 层)。 +* **原则**:强调代码清晰、一致、可维护的核心原则。 + +### 2.2 目录与文件结构 +* **规则**: + * API 功能模块应在 `internal/api/{模块名}` 下创建独立目录。 + * 每个目录包含 `*.go` 文件,每个文件实现一个独立的 API 端点。 + * `{模块名}.go` 文件用于定义 `handler` 结构体和 `New` 初始化函数。 +* **示例**:以 `admin` 模块为例,展示其目录结构。 + +### 2.3 命名规范 +* **规则**: + * Handler 文件名:使用小写蛇形命名法,如 `login.go`, `admin_create.go`。 + * 请求/响应结构体:使用驼峰式命名,并以 `Request`/`Response` 结尾,如 `loginRequest`, `loginResponse`。 + * Handler 函数:使用驼峰式命名,如 `Login()`, `CreateAdmin()`。 + +### 2.4 API Handler 规范 +* **Handler 定义**:`handler` 结构体应包含 `logger` 和数据库连接(`readDB`, `writeDB`)。 +* **路由与函数签名**:Handler 函数必须返回 `core.HandlerFunc` 类型。 +* **参数绑定与校验**:必须使用 `ctx.ShouldBindJSON()` 进行参数绑定,并结合 `validation` 包进行错误信息格式化。 +* **业务逻辑调用**:通过 `h.readDB` 或 `h.writeDB` 与数据库交互,或调用 `service` 层方法。 +* **响应处理**:成功时使用 `ctx.Payload(res)` 返回数据。 + +### 2.5 数据传输对象 (DTO) 规范 +* **Request/Response 结构体**:每个 API 都应定义独立的请求和响应结构体。 +* **JSON Tags**:所有结构体字段必须包含 `json:"..."` tag。 +* **Validation Tags**:对需要校验的请求字段,必须添加 `binding:"..."` tag。 + +### 2.6 错误处理规范 +* **规则**:必须使用 `ctx.AbortWithError(core.Error(...))` 来中断请求并返回标准格式的错误。 +* **`core.Error` 参数**:需提供 HTTP 状态码、业务错误码 (`code.Code`) 和详细错误信息。 + +### 2.7 日志记录规范 +* **规则**:通过注入的 `h.logger` 实例进行日志记录(虽然在 `admin` 示例中不明显,但这是标准实践)。 + +### 2.8 注释与文档 (Swagger) +* **规则**: + * 每个 Handler 函数上方必须有完整的 Swagger 注解,包括 `@Summary`, `@Description`, `@Tags`, `@Param`, `@Success`, `@Failure`, `@Router` 等。 + * 所有 DTO 字段和函数都应有清晰的中文注释。 + +## 3. 数据流与接口契约 + +本文档本身不定义新的数据流或接口,而是规范如何定义它们。其核心思想是:**通过严格的结构体和规范化的错误处理,确保所有 API 的接口契约都是明确和一致的。** diff --git a/docs/开发规范/TASK_开发规范.md b/docs/开发规范/TASK_开发规范.md new file mode 100644 index 0000000..785bfc7 --- /dev/null +++ b/docs/开发规范/TASK_开发规范.md @@ -0,0 +1,67 @@ +# TASK: 开发规范文档撰写任务拆解 + +基于 `DESIGN_开发规范.md`,现将最终文档的撰写工作拆解为以下原子任务。这些任务将按顺序执行,以确保最终交付物的完整性和准确性。 + +## 任务依赖图 + +```mermaid +graph TD + subgraph 撰写最终文档 + T1[任务1: 撰写概述章节] --\u003e T2 + T2[任务2: 撰写目录与文件结构章节] --\u003e T3 + T3[任务3: 撰写命名规范章节] --\u003e T4 + T4[任务4: 撰写 API Handler 规范章节] --\u003e T5 + T5[任务5: 撰写 DTO 规范章节] --\u003e T6 + T6[任务6: 撰写错误处理规范章节] --\u003e T7 + T7[任务7: 撰写日志记录规范章节] --\u003e T8 + T8[任务8: 撰写注释与文档(Swagger)章节] --\u003e T9 + T9[任务9: 整合所有章节并最终审查] + end +``` + +## 原子任务清单 + +### 任务 1: 撰写“概述”章节 +* **输入契约**: `DESIGN_开发规范.md` 中关于“概述”的描述。 +* **输出契约**: 完成 `docs/开发规范.md` 中“概述”章节的文本内容。 +* **实现约束**: 语言简洁,清晰传达规范的目的和原则。 + +### 任务 2: 撰写“目录与文件结构”章节 +* **输入契约**: `DESIGN_开发规范.md` 中关于目录结构的规则,以及对 `internal/api/admin` 目录的分析结果。 +* **输出契约**: 完成 `docs/开发规范.md` 中“目录与文件结构”章节的文本和示例代码。 +* **实现约束**: 必须提供清晰的目录树示例。 + +### 任务 3: 撰写“命名规范”章节 +* **输入契约**: `DESIGN_开发规范.md` 中关于命名规范的规则。 +* **输出契约**: 完成 `docs/开发规范.md` 中“命名规范”章节的文本内容。 +* **实现约束**: 规则需明确,覆盖文件、结构体、函数等不同场景。 + +### 任务 4: 撰写“API Handler 规范”章节 +* **输入契约**: `DESIGN_开发规范.md` 中关于 Handler 的详细设计,以及 `admin` 模块的源码作为示例。 +* **输出契约**: 完成 `docs/开发规范.md` 中“API Handler 规范”章节的文本和代码示例。 +* **实现约束**: 代码示例需完整展示 Handler 的标准写法。 + +### 任务 5: 撰写“数据传输对象 (DTO) 规范”章节 +* **输入契约**: `DESIGN_开发规范.md` 中关于 DTO 的设计,以及 `admin` 模块的源码作为示例。 +* **输出契约**: 完成 `docs/开发规范.md` 中“DTO 规范”章节的文本和代码示例。 +* **实现约束**: 需重点说明 `json` 和 `binding` tag 的用法。 + +### 任务 6: 撰写“错误处理规范”章节 +* **输入契约**: `DESIGN_开发规范.md` 中关于错误处理的设计,以及 `admin` 模块的源码作为示例。 +* **输出契约**: 完成 `docs/开发规范.md` 中“错误处理规范”章节的文本和代码示例。 +* **实现约束**: 需清晰解释 `ctx.AbortWithError` 和 `core.Error` 的使用方法。 + +### 任务 7: 撰写“日志记录规范”章节 +* **输入契约**: `DESIGN_开发规范.md` 中关于日志记录的设计。 +* **输出契约**: 完成 `docs/开发规范.md` 中“日志记录规范”章节的文本内容。 +* **实现约束**: 虽然示例不明显,但需根据项目架构(`handler` 中注入了 `logger`)推荐标准实践。 + +### 任务 8: 撰写“注释与文档(Swagger)”章节 +* **输入契约**: `DESIGN_开发规范.md` 中关于 Swagger 的设计,以及 `admin` 模块的源码作为示例。 +* **输出契约**: 完成 `docs/开发规范.md` 中“注释与文档(Swagger)”章节的文本和代码示例。 +* **实现约束**: 需提供一个完整的 Swagger 注解块作为模板。 + +### 任务 9: 整合所有章节并最终审查 +* **输入契约**: 已完成的所有章节内容。 +* **输出契约**: 一份格式统一、内容完整、无错误的 `docs/开发规范.md` 文档。 +* **实现约束**: 检查文档的流畅性、一致性和准确性。 diff --git a/docs/需求文档.md b/docs/需求文档.md new file mode 100644 index 0000000..7f8278f --- /dev/null +++ b/docs/需求文档.md @@ -0,0 +1,150 @@ +一、业务一句话概述 +你构建的是一个以“活动期”为载体的盲盒抽奖与商品售卖平台,支持用户参与抽奖、生成订单并支付,中奖/购买后产生成交与持仓记录,可进行转赠、发货,平台提供优惠券与积分体系以促进转化,同时具备邀请裂变、公会协作与玩法扩展(如 Boss 排行),形成完整的增长-交易-履约闭环。 + +二、用户视角的核心流程 +1. 账号与身份 + - 用户注册/登录(微信为主),维护用户基本资料与收货地址(user_members / user_addresses)。 +2. 活动参与 + - 浏览活动及分类(activity / activity_categories),在具体期(activity_issues)参与抽奖或直接购买。 + - 抽奖行为与结果记录(draw_logs),中奖奖品与参与信息可追溯。 +3. 交易与支付 + - 下单(order_headers + order_items),支持积分、优惠券抵扣(user_points / user_coupons / coupons)。 + - 支付流程(payment_preorders / payment_refunds),异常场景可退款。 +4. 资产与履约 + - 奖品持有(user_inventory)与转赠(inventory_transfers),不引入复杂状态机,使用流水记录事实与最终归属。 + - 发货(shipping_sheets,对应发货单),后续可扩展发货明细(shipping_items)。 +5. 社交与增长 + - 邀请裂变(user_invites),通过用户唯一邀请码(user_members.invite_code)建立 inviter-invitee 关系,奖励以积分或优惠券落地。 + - 公会互动(guild_main / guild_members / guild_boxes / guild_contribute_logs),支持公会玩法与贡献日志。 +6. 玩法扩展 + - Boss 排行(leaderboard_boss_players)等玩法可在活动域或独立域扩展。 +7. 平台通知 + - 系统公告(system_notices)与系统配置(system_configs),支持运营触达与配置管理。 + +三、运营视角的能力闭环 +1. 增长与激励 + - 邀请裂变:唯一邀请码与邀请关系,奖励结算可选积分或优惠券。 + - 积分体系:支持签到等行为积分,具备“每日一次”约束的唯一索引设计,利于并发安全。 + - 优惠券体系:券模板(coupons)支持适用范围(全局/活动/商品),用户持券与使用记录(user_coupons)清晰。 +2. 商品与内容运营 + - 商品与分类(product_main / product_categories / product_category_map),活动期配置(activity_issues / activity_reward_settings)。 + - 公告与配置(system_notices / system_configs)用于活动宣导与功能开关。 +3. 履约与服务 + - 发货单(shipping_sheets),配合订单与地址进行物流履约。 + - 转赠流水(inventory_transfers)增强用户间互动与资产流通。 + + + + + + + +我现在要做一个盲盒系统小程序,数据库我已经设计好了,现在我和你说业务需求 +活动(盲盒抽奖): + 1. 有活动列表: + 1.1 用户可以自己点击对应的活动 + 1.2 每个活动都有标签: 对应的活动类型 / 活动是否 Boss挑战 标签 + 1.3 创建活动是: activities 创建一个记录; 然后对应的 activity_issues 创建一个记录, 记录活动的期数;这样的目的是 一个活动可以有多个期数 + 1.3.1 例如 对对碰 一个活动 一个期数 + 1.3.2 例如 一番赏 一个活动 多个期数 + 1.4 创建好活动的时候可以根据活动分类来设置类型 + 1.5 每个活动也可以配置奖品 + 1.6 活动也可以设置是否为 boss 活动 + + 2. 活动接口: + 后台接口: + 1. 创建活动: /api/admin/activities + 2. 修改活动: /api/admin/activities/:activity_id + 3. 删除活动: /api/admin/activities/:activity_id + 4. 查看活动详情: /api/admin/activities/:activity_id + 5. 查看活动期数: /api/admin/activities/:activity_id/issues + 6. 创建期数奖品: /api/admin/activities/:activity_id/issues/:issue_id/rewards + 7. 查看期数奖品: /api/admin/activities/:activity_id/issues/:issue_id/rewards + 8. 创建活动期数: /api/admin/activities/:activity_id/issues + 9. 修改活动期数: /api/admin/activities/:activity_id/issues/:issue_id + 10. 删除活动期数: /api/admin/activities/:activity_id/issues/:issue_id + + app用户接口: + 1. 浏览活动列表: /api/app/activities + 2. 查看活动详情: /api/app/activities/:activity_id + 3. 查看活动期数: /api/app/activities/:activity_id/issues + 4. 查看期数奖品: /api/app/activities/:activity_id/issues/:issue_id/rewards + 5. 查看活动抽奖记录: /api/app/activities/:activity_id/issues/:issue_id/draw_logs + +工会(公会): + 1. 需求: + 1.1 用户可以自己点击对应的工会 + 1.2 每个工会都有标签: 对应的工会类型 / 工会是否公开 标签 + 1.3 创建工会是: guild 创建一个记录; 然后对应的 guild_members 创建一个记录, 记录工会的成员;这样的目的是 一个工会可以有多个成员 + 1.3.1 例如 一对情侣 一个工会 两个成员 + 1.3.2 例如 一个团队 一个工会 多个成员 + 1.3.3 创建公会的时候 默认 第一个人是会长 + 1.3.4 其他成员加入工会的时候, 会创建一个 guild_members 记录, 记录成员的加入时间 + 1.4 创建好工会的时候可以根据工会分类来设置类型 + 1.5 工会也可以设置是否为公开工会 + 1.6 用户离开公会后 24 小时不允许加入公会 + + 2. 工会接口: + 后台接口: + 1. 创建工会: /api/admin/guilds + 2. 修改工会: /api/admin/guilds/:guild_id + 3. 删除工会: /api/admin/guilds/:guild_id + 4. 查看工会详情: /api/admin/guilds/:guild_id + 5. 查看工会成员: /api/admin/guilds/:guild_id/members + 3. app用户接口: + 1. 浏览工会列表: /api/app/guilds + 2. 查看工会详情: /api/app/guilds/:guild_id + 3. 加入工会: /api/app/guilds/:guild_id/members + 4. 离开公会: /api/app/guilds/:guild_id/members/:user_id + 5. 查看工会成员: /api/app/guilds/:guild_id/members + + +用户(用户): + 1. 需求: + 1.1 用户可以注册登录: weixin 登录 + 1.2 用户可以查看自己的个人信息 + 1.3 用户可以修改自己的个人信息 + 1.4 用户可以查看自己邀请记录 + 1.5 可以看到自己的订单记录 + 1.6 用户可以看到自己的优惠券 + 1.7 用户可以查看自己的积分记录 和 积分余额 + + + 用户在登录的时候: 判断如果 链接里面有 code=这个参数; 那么代表是被邀请用户; 需要登录的时候携带这个参数; 后台会判断这个参数(是否可以根据这个参数找到邀请人), 然后在 邀请表中写入一个记录, 如果已经邀请了则不下发积分奖励; 如果没有邀请过, 则下发积分奖励 + 用户可以编辑修改自己的用户信息: 昵称 + 头像 + 当用户加入工会后是可以看到自己的工会成员的 + 用户可以在订单中 找到自己的订单记录(来源是 活动抽奖得到的) + 现在帮我完成这个需求; 一定需要记住: 这个是app端的接口; api 和 service 需要 遵守拆分规则 , 然后需要协商接口文档; 同时注意 req / res 这个需要在自己的代码中定义好; + 接口: + 1. 修改用户信息: /api/app/users/:user_id + 2. 查看用户订单记录: /api/app/users/:user_id/orders + 3. 查看用户优惠券: /api/app/users/:user_id/coupons + 4. 查看用户积分记录: /api/app/users/:user_id/points + 5. 查看用户积分余额: /api/app/users/:user_id/points/balance + 6. 微信登录: /api/app/users/weixin/login + 7. 查看用户邀请记录: /api/app/users/:user_id/invites + +用户(admin管理端) + 1. 查看所有用户列表: /api/admin/users + 2. 可以查看到用户邀请列表: /api/admin/users/:user_id/invites + 3. 可以查看到用户订单列表: /api/admin/users/:user_id/orders + 4. 可以查看到用户优惠券列表: /api/admin/users/:user_id/coupons + 5. 可以查看到用户积分记录列表: /api/admin/users/:user_id/points + 6. 可以查看到用户积分余额: /api/admin/users/:user_id/points/balance + 7. 可以给用户添加积分: /api/admin/users/:user_id/points/add + 8. 可以给用户添加优惠券: /api/admin/users/:user_id/coupons/add + + + +商品管理:(product_categories / products) + 1. 后台管理: + 1.1 创建商品分类: /api/admin/product_categories + 1.2 修改商品分类: /api/admin/product_categories/:category_id + 1.3 删除商品分类: /api/admin/product_categories/:category_id + 1.4 查看商品分类列表: /api/admin/product_categories + 1.5 创建商品: /api/admin/products + 1.6 修改商品: /api/admin/products/:product_id + 1.7 删除商品: /api/admin/products/:product_id + 1.8 查看商品列表: /api/admin/products + + diff --git a/docs/项目框架/ALIGNMENT_项目框架.md b/docs/项目框架/ALIGNMENT_项目框架.md new file mode 100644 index 0000000..2a70032 --- /dev/null +++ b/docs/项目框架/ALIGNMENT_项目框架.md @@ -0,0 +1,47 @@ + +# 项目和任务特性规范 + +## 原始需求 +梳理项目框架,为后续开发做准备。 + +## 边界确认 +- **目标**: 分析现有项目结构、技术栈、架构模式、依赖关系,并输出分析报告。 +- **范围**: 仅分析现有代码库,不涉及运行时环境或外部系统。 + +## 需求理解 +该项目是一个Go语言编写的后端服务,命名为 `bindbox_game`,可能是一个“盲盒游戏”相关的应用。 + +从目录结构来看,项目遵循了一定的分层架构或整洁架构思想,主要模块包括: +- `cmd/`: 存放可执行命令,如代码生成器 (`gormgen`, `handlergen`)。 +- `configs/`: 配置文件,区分不同环境 (`dev`, `fat`, `pro`, `uat`)。 +- `deploy/`: 部署相关文件,如 `docker-compose.yaml`。 +- `docs/`: 项目文档,包括 `swagger` 定义和一些说明文档。 +- `internal/`: 项目核心业务逻辑,这是分析的重点。 +- `scripts/`: 辅助脚本。 +- `static/`: 静态资源。 + +`internal/` 目录下的结构进一步体现了分层设计: +- `api/`: API接口定义,按模块划分(如 `admin`)。 +- `repository/`: 数据仓库层,负责与数据库交互,使用了 `gorm`(从 `gormgen` 推断)和 `mysql`。 +- `service/` 和 `services/`: 服务层,处理核心业务逻辑。 +- `router/`: 路由定义和中间件。 +- `pkg/`: 可重用的公共库或工具类,如日志、错误处理、加解密等。 +- `code/`: 业务状态码定义。 +- `metrics/`: 监控指标。 +- `alert/`: 告警。 + +技术栈和依赖推断: +- **语言**: Go +- **Web框架**: 可能是 `Gin` 或类似框架(需要查看 `go.mod` 确认)。 +- **ORM**: `GORM`(从 `gormgen` 和 `internal/repository/mysql` 目录推断)。 +- **数据库**: `MySQL`。 +- **文档**: `Swagger`。 +- **部署**: `Docker`。 + +## 疑问澄清 +- Web框架具体是哪个? **Gin** +- 项目依赖了哪些主要的第三方库? **GORM, Viper, Zap, Gin** +- `service` 和 `services` 两个目录的区别是什么? `service` 目录为空,`services` 目录用于存放按功能模块组织的业务逻辑,但目前未被积极使用。 +- `proposal` 目录的作用是什么? 定义了用于告警、日志等目的的数据结构和处理器。 + +接下来,我将通过分析 `go.mod` 文件来解答这些疑问。 diff --git a/docs/项目框架/CONSENSUS_项目框架.md b/docs/项目框架/CONSENSUS_项目框架.md new file mode 100644 index 0000000..cb53927 --- /dev/null +++ b/docs/项目框架/CONSENSUS_项目框架.md @@ -0,0 +1,29 @@ + +# 最终共识 + +## 需求描述和验收标准 +- **需求**: 梳理并理解现有项目框架,为后续开发提供清晰的上下文。 +- **验收标准**: 输出一份关于项目架构、技术栈和关键模块的分析报告。 + +## 技术实现方案和技术约束和集成方案 +- **项目名称**: `bindbox_game` +- **语言**: Go +- **Web框架**: Gin +- **ORM**: GORM +- **数据库**: MySQL +- **配置管理**: Viper +- **日志**: Zap +- **API文档**: Swagger +- **部署**: Docker + +## 任务边界限制和验收标准 +- **架构模式**: 项目采用分层架构,但业务逻辑目前主要集中在 `internal/api` 层,`internal/services` 层尚未被充分利用。 +- **代码生成**: 项目使用 `gormgen` 和 `handlergen` 等工具生成部分代码。 +- **公共库**: `internal/pkg` 目录提供了丰富的可重用组件。 +- **中间件**: 在 `internal/router` 中定义,用于处理认证、日志等。 + +## 确认所有不确定性已解决 +- `service` vs `services`: `service` 目录为空,`services` 用于模块化业务逻辑,但目前未被积极使用。 +- `proposal` 目录: 定义了用于告警、日志等目的的数据结构和处理器。 + +**结论**: 项目框架清晰,技术选型主流。后续开发应遵循现有架构模式,并考虑将业务逻辑更清晰地分离到 `service` 层,以提高可维护性。 diff --git a/go.mod b/go.mod index aaf38a1..4f31238 100644 --- a/go.mod +++ b/go.mod @@ -1,4 +1,4 @@ -module mini-chat +module bindbox-game go 1.19 @@ -15,7 +15,7 @@ require ( github.com/go-playground/validator/v10 v10.15.0 github.com/go-resty/resty/v2 v2.10.0 github.com/golang-jwt/jwt/v5 v5.2.0 - github.com/jakecoffman/cron v0.0.0-20190106200828-7e2009c226a5 + github.com/issue9/identicon/v2 v2.1.2 github.com/pkg/errors v0.9.1 github.com/prometheus/client_golang v1.17.0 github.com/rs/cors/wrapper/gin v0.0.0-20231013084403-73f81b45a644 @@ -25,6 +25,7 @@ require ( github.com/swaggo/gin-swagger v1.6.0 github.com/swaggo/swag v1.16.2 github.com/tealeg/xlsx v1.0.5 + github.com/tencentyun/cos-go-sdk-v5 v0.7.37 go.uber.org/multierr v1.10.0 go.uber.org/zap v1.26.0 golang.org/x/crypto v0.27.0 @@ -44,6 +45,7 @@ require ( github.com/beorn7/perks v1.0.1 // indirect github.com/bytedance/sonic/loader v0.2.4 // indirect github.com/cespare/xxhash/v2 v2.2.0 // indirect + github.com/clbanning/mxj v1.8.4 // indirect github.com/cloudwego/base64x v0.1.5 // indirect github.com/fsnotify/fsnotify v1.7.0 // indirect github.com/gabriel-vasile/mimetype v1.4.2 // indirect @@ -55,6 +57,7 @@ require ( github.com/go-sql-driver/mysql v1.7.0 // indirect github.com/goccy/go-json v0.10.2 // indirect github.com/golang/protobuf v1.5.3 // indirect + github.com/google/go-querystring v1.0.0 // indirect github.com/hashicorp/hcl v1.0.0 // indirect github.com/jinzhu/inflection v1.0.0 // indirect github.com/jinzhu/now v1.1.5 // indirect @@ -71,6 +74,7 @@ require ( github.com/mitchellh/mapstructure v1.5.0 // indirect github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect github.com/modern-go/reflect2 v1.0.2 // indirect + github.com/mozillazg/go-httpheader v0.2.1 // indirect github.com/pelletier/go-toml/v2 v2.1.0 // indirect github.com/prometheus/client_model v0.4.1-0.20230718164431-9a2bf3000d16 // indirect github.com/prometheus/common v0.44.0 // indirect diff --git a/go.sum b/go.sum index 6a38264..7c870e4 100644 --- a/go.sum +++ b/go.sum @@ -46,6 +46,7 @@ github.com/PuerkitoBio/purell v1.1.1 h1:WEQqlqaGbrPkxLJWfBwQmfEAE1Z7ONdDLqrN38tN github.com/PuerkitoBio/purell v1.1.1/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0= github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578 h1:d+Bc7a5rLufV/sSk/8dngufqelfh6jnri85riMAaF/M= github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE= +github.com/QcloudApi/qcloud_sign_golang v0.0.0-20141224014652-e4130a326409/go.mod h1:1pk82RBxDY/JZnPQrtqHlUFfCctgdorsd9M06fMynOM= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= github.com/bwmarrin/snowflake v0.3.0 h1:xm67bEhkKh6ij1790JB83OujPR5CzNe8QuQqAgISZN0= @@ -61,6 +62,8 @@ github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XL github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= +github.com/clbanning/mxj v1.8.4 h1:HuhwZtbyvyOw+3Z1AowPkU87JkJUSv751ELWaiTpj8I= +github.com/clbanning/mxj v1.8.4/go.mod h1:BVjHeAH+rl9rs6f+QIpeRl0tfu10SXn1pUSa5PVGJng= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/cloudwego/base64x v0.1.5 h1:XPciSp1xaq2VCSt6lF0phncD4koWyULpl5bUxbfCyP4= github.com/cloudwego/base64x v0.1.5/go.mod h1:0zlkT4Wn5C6NdauXdJRhSKRlJvmclQ1hhJgA0rcu/8w= @@ -172,6 +175,8 @@ github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= +github.com/google/go-querystring v1.0.0 h1:Xkwi/a1rcvNg1PPYe5vI8GbeBY/jrVuDX5ASuANWTrk= +github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= @@ -187,6 +192,8 @@ github.com/google/pprof v0.0.0-20201023163331-3e6fc7fc9c4c/go.mod h1:kpwsk12EmLe github.com/google/pprof v0.0.0-20201203190320-1bf35d6f28c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20201218002935-b9804c9f04c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= +github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.1.2 h1:EVhdT+1Kseyi1/pUmXKaFxYsDNy9RQYkMWRH68J/W7Y= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= @@ -197,6 +204,9 @@ github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4= github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= +github.com/issue9/assert/v4 v4.1.1 h1:OhPE8SB8n/qZCNGLQa+6MQtr/B3oON0JAVj68k8jJlc= +github.com/issue9/identicon/v2 v2.1.2 h1:tu+4vveoiJNXfmWYvl1pDcZSAHCG37+lsoEc2UfCzkI= +github.com/issue9/identicon/v2 v2.1.2/go.mod h1:h5JXMtcgkqxltElhpF7PPicNyvFDWzi8VCSHdNjG7KY= github.com/jackc/chunkreader/v2 v2.0.1 h1:i+RDz65UE+mmpjTfyz0MoVTnzeYxroil2G82ki7MGG8= github.com/jackc/pgconn v1.13.0 h1:3L1XMNV2Zvca/8BYhzcRFS70Lr0WlDg16Di6SFGAbys= github.com/jackc/pgio v1.0.0 h1:g12B9UwVnzGhueNavwioyEEpAmqMe1E/BN9ES+8ovkE= @@ -205,8 +215,6 @@ github.com/jackc/pgproto3/v2 v2.3.1 h1:nwj7qwf0S+Q7ISFfBndqeLwSwxs+4DPsbRFjECT1Y github.com/jackc/pgservicefile v0.0.0-20200714003250-2b9c44734f2b h1:C8S2+VttkHFdOOCXJe+YGfa4vHYwlt4Zx+IVXQ97jYg= github.com/jackc/pgtype v1.12.0 h1:Dlq8Qvcch7kiehm8wPGIW0W3KsCCHJnRacKW0UM8n5w= github.com/jackc/pgx/v4 v4.17.2 h1:0Ut0rpeKwvIVbMQ1KbMBU4h6wxehBI535LK6Flheh8E= -github.com/jakecoffman/cron v0.0.0-20190106200828-7e2009c226a5 h1:kCvm3G3u+eTRbjfLPyfsfznJtraYEfZer/UvQ6CaQhI= -github.com/jakecoffman/cron v0.0.0-20190106200828-7e2009c226a5/go.mod h1:6DM2KNNK69jRu0lAHmYK9LYxmqpNjYHOaNp/ZxttD4U= github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E= github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc= github.com/jinzhu/now v1.1.2/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8= @@ -254,6 +262,7 @@ github.com/mattn/go-sqlite3 v1.14.15/go.mod h1:2eHXhiwb8IkHr+BDWZGa96P6+rkvnG63S github.com/matttproud/golang_protobuf_extensions v1.0.4 h1:mmDVorXM7PCGKw94cs5zkfA9PSy5pEvNWRP0ET0TIVo= github.com/matttproud/golang_protobuf_extensions v1.0.4/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4= github.com/microsoft/go-mssqldb v0.17.0 h1:Fto83dMZPnYv1Zwx5vHHxpNraeEaUlQ/hhHLgZiaenE= +github.com/mitchellh/mapstructure v1.4.3/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= @@ -261,6 +270,8 @@ github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= +github.com/mozillazg/go-httpheader v0.2.1 h1:geV7TrjbL8KXSyvghnFm+NyTux/hxwueTSrwhe88TQQ= +github.com/mozillazg/go-httpheader v0.2.1/go.mod h1:jJ8xECTlalr6ValeXYdOF8fFUISeBAdw6E61aqQma60= github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= github.com/pelletier/go-toml/v2 v2.0.1/go.mod h1:r9LEWfGN8R5k0VXJ+0BkIe7MYkRdwZOjgMj2KwnJFUo= github.com/pelletier/go-toml/v2 v2.1.0 h1:FnwAJ4oYMvbT/34k9zzHuZNrhlz48GB3/s6at6/MHO4= @@ -326,6 +337,10 @@ github.com/swaggo/swag v1.16.2 h1:28Pp+8DkQoV+HLzLx8RGJZXNGKbFqnuvSbAAtoxiY04= github.com/swaggo/swag v1.16.2/go.mod h1:6YzXnDcpr0767iOejs318CwYkCQqyGer6BizOg03f+E= github.com/tealeg/xlsx v1.0.5 h1:+f8oFmvY8Gw1iUXzPk+kz+4GpbDZPK1FhPiQRd+ypgE= github.com/tealeg/xlsx v1.0.5/go.mod h1:btRS8dz54TDnvKNosuAqxrM1QgN1udgk9O34bDCnORM= +github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.194/go.mod h1:7sCQWVkxcsR38nffDW057DRGk8mUjK1Ing/EFOK8s8Y= +github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/kms v1.0.194/go.mod h1:yrBKWhChnDqNz1xuXdSbWXG56XawEq0G5j1lg4VwBD4= +github.com/tencentyun/cos-go-sdk-v5 v0.7.37 h1:yMRtmXadV/Timk130OUoWDSMQEo5656kaoBfv8VcurM= +github.com/tencentyun/cos-go-sdk-v5 v0.7.37/go.mod h1:4dCEtLHGh8QPxHEkgq+nFaky7yZxQuYwgSJM87icDaw= github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS4MhqMhdFk5YI= github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08= github.com/ugorji/go v1.2.7/go.mod h1:nF9osbDWLy6bDVv/Rtoh6QgnvNDpmCalQV5urGCCS6M= diff --git a/internal/.DS_Store b/internal/.DS_Store new file mode 100644 index 0000000..3036dcf Binary files /dev/null and b/internal/.DS_Store differ diff --git a/internal/alert/alert.go b/internal/alert/alert.go index daea1ef..65ff8e4 100644 --- a/internal/alert/alert.go +++ b/internal/alert/alert.go @@ -1,7 +1,7 @@ package alert import ( - "mini-chat/internal/proposal" + "bindbox-game/internal/proposal" ) func NotifyHandler() func(msg *proposal.AlertMessage) { diff --git a/internal/api/activity/activities_app.go b/internal/api/activity/activities_app.go new file mode 100644 index 0000000..b4b08c2 --- /dev/null +++ b/internal/api/activity/activities_app.go @@ -0,0 +1,138 @@ +package app + +import ( + "net/http" + "strconv" + + "bindbox-game/internal/code" + "bindbox-game/internal/pkg/core" + "bindbox-game/internal/pkg/validation" +) + +type listActivitiesRequest struct { + Name string `form:"name"` + CategoryID int64 `form:"category_id"` + IsBoss int32 `form:"is_boss"` + Status int32 `form:"status"` + Page int `form:"page"` + PageSize int `form:"page_size"` +} + +type activityItem struct { + ID int64 `json:"id"` + Name string `json:"name"` + Banner string `json:"banner"` + ActivityCategoryID int64 `json:"activity_category_id"` + CategoryName string `json:"category_name"` + Status int32 `json:"status"` + PriceDraw int64 `json:"price_draw"` + IsBoss int32 `json:"is_boss"` +} + +type listActivitiesResponse struct { + Page int `json:"page"` + PageSize int `json:"page_size"` + Total int64 `json:"total"` + List []activityItem `json:"list"` +} + +// ListActivities 活动列表 +// @Summary 活动列表 +// @Description 获取活动列表,支持分类、Boss、状态过滤与分页 +// @Tags APP端.活动 +// @Accept json +// @Produce json +// @Param name query string false "活动名称(模糊)" +// @Param category_id query int false "活动分类ID" +// @Param is_boss query int false "是否Boss(0/1)" +// @Param status query int false "状态(1进行中 2下线)" +// @Param page query int true "页码" default(1) +// @Param page_size query int true "每页数量,最多100" default(20) +// @Success 200 {object} listActivitiesResponse +// @Failure 400 {object} code.Failure +// @Router /api/app/activities [get] +func (h *handler) ListActivities() core.HandlerFunc { + return func(ctx core.Context) { + req := new(listActivitiesRequest) + res := new(listActivitiesResponse) + if err := ctx.ShouldBindForm(req); err != nil { + ctx.AbortWithError(core.Error(http.StatusBadRequest, code.ParamBindError, validation.Error(err))) + return + } + var isBossPtr *int32 + if req.IsBoss == 0 || req.IsBoss == 1 { + isBossPtr = &req.IsBoss + } + var statusPtr *int32 + if req.Status == 1 || req.Status == 2 { + statusPtr = &req.Status + } + items, total, err := h.activity.ListActivities(ctx.RequestContext(), struct { + Name string + CategoryID int64 + IsBoss *int32 + Status *int32 + Page int + PageSize int + }{Name: req.Name, CategoryID: req.CategoryID, IsBoss: isBossPtr, Status: statusPtr, Page: req.Page, PageSize: req.PageSize}) + if err != nil { + ctx.AbortWithError(core.Error(http.StatusBadRequest, code.ListActivitiesError, err.Error())) + return + } + res.Page = req.Page + res.PageSize = req.PageSize + res.Total = total + res.List = make([]activityItem, len(items)) + // collect category ids + var catIDs []int64 + catSet := make(map[int64]struct{}) + for _, v := range items { + if v.ActivityCategoryID != 0 { + if _, ok := catSet[v.ActivityCategoryID]; !ok { + catSet[v.ActivityCategoryID] = struct{}{} + catIDs = append(catIDs, v.ActivityCategoryID) + } + } + } + nameMap, _ := h.activity.GetCategoryNames(ctx.RequestContext(), catIDs) + for i, v := range items { + res.List[i] = activityItem{ + ID: v.ID, + Name: v.Name, + Banner: v.Banner, + ActivityCategoryID: v.ActivityCategoryID, + CategoryName: nameMap[v.ActivityCategoryID], + Status: v.Status, + PriceDraw: v.PriceDraw, + IsBoss: v.IsBoss, + } + } + ctx.Payload(res) + } +} + +// GetActivityDetail 活动详情 +// @Summary 活动详情 +// @Description 获取指定活动的详细信息 +// @Tags APP端.活动 +// @Accept json +// @Produce json +// @Param activity_id path integer true "活动ID" +// @Success 200 {object} model.Activities +// @Failure 400 {object} code.Failure +// @Router /api/app/activities/{activity_id} [get] +func (h *handler) GetActivityDetail() core.HandlerFunc { + return func(ctx core.Context) { + id, err := strconv.ParseInt(ctx.Param("activity_id"), 10, 64) + if err != nil { + ctx.AbortWithError(core.Error(http.StatusBadRequest, code.ParamBindError, "未传递活动ID")) + return + } + item, err := h.activity.GetActivity(ctx.RequestContext(), id) + if err != nil { + ctx.AbortWithError(core.Error(http.StatusBadRequest, code.GetActivityError, err.Error())) + return + } + ctx.Payload(item) + } +} diff --git a/internal/api/activity/app.go b/internal/api/activity/app.go new file mode 100644 index 0000000..26bd215 --- /dev/null +++ b/internal/api/activity/app.go @@ -0,0 +1,24 @@ +package app + +import ( + "bindbox-game/internal/pkg/logger" + "bindbox-game/internal/repository/mysql" + "bindbox-game/internal/repository/mysql/dao" + activitysvc "bindbox-game/internal/service/activity" +) + +type handler struct { + logger logger.CustomLogger + writeDB *dao.Query + readDB *dao.Query + activity activitysvc.Service +} + +func New(logger logger.CustomLogger, db mysql.Repo) *handler { + return &handler{ + logger: logger, + writeDB: dao.Use(db.GetDbW()), + readDB: dao.Use(db.GetDbR()), + activity: activitysvc.New(logger, db), + } +} diff --git a/internal/api/activity/draw_logs_app.go b/internal/api/activity/draw_logs_app.go new file mode 100644 index 0000000..eb584cb --- /dev/null +++ b/internal/api/activity/draw_logs_app.go @@ -0,0 +1,84 @@ +package app + +import ( + "net/http" + "strconv" + + "bindbox-game/internal/code" + "bindbox-game/internal/pkg/core" + "bindbox-game/internal/pkg/validation" +) + +type listDrawLogsRequest struct { + Page int `form:"page"` + PageSize int `form:"page_size"` +} + +type drawLogItem struct { + ID int64 `json:"id"` + UserID int64 `json:"user_id"` + IssueID int64 `json:"issue_id"` + OrderID int64 `json:"order_id"` + RewardID int64 `json:"reward_id"` + IsWinner int32 `json:"is_winner"` + Level int32 `json:"level"` + CurrentLevel int32 `json:"current_level"` +} + +type listDrawLogsResponse struct { + Page int `json:"page"` + PageSize int `json:"page_size"` + Total int64 `json:"total"` + List []drawLogItem `json:"list"` +} + +// ListDrawLogs 抽奖记录列表 +// @Summary 抽奖记录列表 +// @Description 查看指定活动期数的抽奖记录,支持分页 +// @Tags APP端.活动 +// @Accept json +// @Produce json +// @Param activity_id path integer true "活动ID" +// @Param issue_id path integer true "期ID" +// @Param page query int true "页码" default(1) +// @Param page_size query int true "每页数量,最多100" default(20) +// @Success 200 {object} listDrawLogsResponse +// @Failure 400 {object} code.Failure +// @Router /api/app/activities/{activity_id}/issues/{issue_id}/draw_logs [get] +func (h *handler) ListDrawLogs() core.HandlerFunc { + return func(ctx core.Context) { + req := new(listDrawLogsRequest) + res := new(listDrawLogsResponse) + if err := ctx.ShouldBindForm(req); err != nil { + ctx.AbortWithError(core.Error(http.StatusBadRequest, code.ParamBindError, validation.Error(err))) + return + } + issueID, err := strconv.ParseInt(ctx.Param("issue_id"), 10, 64) + if err != nil { + ctx.AbortWithError(core.Error(http.StatusBadRequest, code.ParamBindError, "未传递期ID")) + return + } + items, total, err := h.activity.ListDrawLogs(ctx.RequestContext(), issueID, req.Page, req.PageSize) + if err != nil { + ctx.AbortWithError(core.Error(http.StatusBadRequest, code.ListDrawLogsError, err.Error())) + return + } + res.Page = req.Page + res.PageSize = req.PageSize + res.Total = total + res.List = make([]drawLogItem, len(items)) + for i, v := range items { + res.List[i] = drawLogItem{ + ID: v.ID, + UserID: v.UserID, + IssueID: v.IssueID, + OrderID: v.OrderID, + RewardID: v.RewardID, + IsWinner: v.IsWinner, + Level: v.Level, + CurrentLevel: v.CurrentLevel, + } + } + ctx.Payload(res) + } +} diff --git a/internal/api/activity/issues_app.go b/internal/api/activity/issues_app.go new file mode 100644 index 0000000..11d634c --- /dev/null +++ b/internal/api/activity/issues_app.go @@ -0,0 +1,70 @@ +package app + +import ( + "net/http" + "strconv" + + "bindbox-game/internal/code" + "bindbox-game/internal/pkg/core" + "bindbox-game/internal/pkg/validation" +) + +type listIssuesRequest struct { + Page int `form:"page"` + PageSize int `form:"page_size"` +} + +type issueItem struct { + ID int64 `json:"id"` + IssueNumber string `json:"issue_number"` + Status int32 `json:"status"` + Sort int32 `json:"sort"` +} + +type listIssuesResponse struct { + Page int `json:"page"` + PageSize int `json:"page_size"` + Total int64 `json:"total"` + List []issueItem `json:"list"` +} + +// ListActivityIssues 活动期列表 +// @Summary 活动期列表 +// @Description 获取指定活动的期列表,支持分页 +// @Tags APP端.活动 +// @Accept json +// @Produce json +// @Param activity_id path integer true "活动ID" +// @Param page query int true "页码" default(1) +// @Param page_size query int true "每页数量,最多100" default(20) +// @Success 200 {object} listIssuesResponse +// @Failure 400 {object} code.Failure +// @Router /api/app/activities/{activity_id}/issues [get] +func (h *handler) ListActivityIssues() core.HandlerFunc { + return func(ctx core.Context) { + req := new(listIssuesRequest) + res := new(listIssuesResponse) + if err := ctx.ShouldBindForm(req); err != nil { + ctx.AbortWithError(core.Error(http.StatusBadRequest, code.ParamBindError, validation.Error(err))) + return + } + activityID, err := strconv.ParseInt(ctx.Param("activity_id"), 10, 64) + if err != nil { + ctx.AbortWithError(core.Error(http.StatusBadRequest, code.ParamBindError, "未传递活动ID")) + return + } + items, total, err := h.activity.ListIssues(ctx.RequestContext(), activityID, req.Page, req.PageSize) + if err != nil { + ctx.AbortWithError(core.Error(http.StatusBadRequest, code.ListActivityIssuesError, err.Error())) + return + } + res.Page = req.Page + res.PageSize = req.PageSize + res.Total = total + res.List = make([]issueItem, len(items)) + for i, v := range items { + res.List[i] = issueItem{ID: v.ID, IssueNumber: v.IssueNumber, Status: v.Status, Sort: v.Sort} + } + ctx.Payload(res) + } +} diff --git a/internal/api/activity/rewards_app.go b/internal/api/activity/rewards_app.go new file mode 100644 index 0000000..b11811c --- /dev/null +++ b/internal/api/activity/rewards_app.go @@ -0,0 +1,71 @@ +package app + +import ( + "net/http" + "strconv" + + "bindbox-game/internal/code" + "bindbox-game/internal/pkg/core" + "bindbox-game/internal/pkg/validation" +) + +type rewardItem struct { + ProductID int64 `json:"product_id"` + Name string `json:"name"` + Weight int32 `json:"weight"` + Quantity int64 `json:"quantity"` + OriginalQty int64 `json:"original_qty"` + Level int32 `json:"level"` + Sort int32 `json:"sort"` + IsBoss int32 `json:"is_boss"` +} + +type listRewardsResponse struct { + List []rewardItem `json:"list"` +} + +// ListIssueRewards 奖励配置列表 +// @Summary 奖励配置列表 +// @Description 获取指定期的奖励配置列表 +// @Tags APP端.活动 +// @Accept json +// @Produce json +// @Param activity_id path integer true "活动ID" +// @Param issue_id path integer true "期ID" +// @Success 200 {object} listRewardsResponse +// @Failure 400 {object} code.Failure +// @Router /api/app/activities/{activity_id}/issues/{issue_id}/rewards [get] +func (h *handler) ListIssueRewards() core.HandlerFunc { + return func(ctx core.Context) { + issueIDStr := ctx.Param("issue_id") + if issueIDStr == "" { + ctx.AbortWithError(core.Error(http.StatusBadRequest, code.ParamBindError, "未传递期ID")) + return + } + if _, err := strconv.ParseInt(issueIDStr, 10, 64); err != nil { + ctx.AbortWithError(core.Error(http.StatusBadRequest, code.ParamBindError, validation.Error(err))) + return + } + issueID, _ := strconv.ParseInt(issueIDStr, 10, 64) + items, err := h.activity.ListIssueRewards(ctx.RequestContext(), issueID) + if err != nil { + ctx.AbortWithError(core.Error(http.StatusBadRequest, code.ListIssueRewardsError, err.Error())) + return + } + res := new(listRewardsResponse) + res.List = make([]rewardItem, len(items)) + for i, v := range items { + res.List[i] = rewardItem{ + ProductID: v.ProductID, + Name: v.Name, + Weight: v.Weight, + Quantity: v.Quantity, + OriginalQty: v.OriginalQty, + Level: v.Level, + Sort: v.Sort, + IsBoss: v.IsBoss, + } + } + ctx.Payload(res) + } +} diff --git a/internal/api/admin/activities_admin.go b/internal/api/admin/activities_admin.go new file mode 100644 index 0000000..9afb3ac --- /dev/null +++ b/internal/api/admin/activities_admin.go @@ -0,0 +1,230 @@ +package admin + +import ( + "net/http" + "strconv" + "time" + + "bindbox-game/internal/code" + "bindbox-game/internal/pkg/core" + "bindbox-game/internal/pkg/validation" + activitysvc "bindbox-game/internal/service/activity" +) + +type createActivityRequest struct { + Name string `json:"name" binding:"required"` + Banner string `json:"banner"` + ActivityCategoryID int64 `json:"activity_category_id" binding:"required"` + Status int32 `json:"status"` + PriceDraw int64 `json:"price_draw"` + IsBoss int32 `json:"is_boss"` + StartTime string `json:"start_time"` + EndTime string `json:"end_time"` +} + +type createActivityResponse struct { + ID int64 `json:"id"` + Message string `json:"message"` +} + +// CreateActivity 创建活动 +// @Summary 创建活动 +// @Description 创建活动,配置基本信息与分类、Boss标签 +// @Tags 管理端.活动 +// @Accept json +// @Produce json +// @Param RequestBody body createActivityRequest true "请求参数" +// @Success 200 {object} simpleMessageResponse +// @Failure 400 {object} code.Failure +// @Router /api/admin/activities [post] +// @Security LoginVerifyToken +func (h *handler) CreateActivity() core.HandlerFunc { + return func(ctx core.Context) { + req := new(createActivityRequest) + res := new(createActivityResponse) + + if err := ctx.ShouldBindJSON(req); err != nil { + ctx.AbortWithError(core.Error(http.StatusBadRequest, code.ParamBindError, validation.Error(err))) + return + } + + if req.ActivityCategoryID == 0 { + ctx.AbortWithError(core.Error(http.StatusBadRequest, code.ParamBindError, "活动分类ID不能为空")) + return + } + + if ctx.SessionUserInfo().IsSuper != 1 { + ctx.AbortWithError(core.Error(http.StatusBadRequest, code.CreateActivityError, "禁止操作")) + return + } + + var st, et *time.Time + if req.StartTime != "" { + if t, err := time.Parse(time.RFC3339, req.StartTime); err == nil { + st = &t + } + } + if req.EndTime != "" { + if t, err := time.Parse(time.RFC3339, req.EndTime); err == nil { + et = &t + } + } + + item, err := h.activity.CreateActivity(ctx.RequestContext(), activitysvc.CreateActivityInput{ + Name: req.Name, + Banner: req.Banner, + ActivityCategoryID: req.ActivityCategoryID, + Status: req.Status, + PriceDraw: req.PriceDraw, + IsBoss: req.IsBoss, + StartTime: st, + EndTime: et, + }) + if err != nil { + ctx.AbortWithError(core.Error(http.StatusBadRequest, code.CreateActivityError, err.Error())) + return + } + + res.ID = item.ID + res.Message = "操作成功" + ctx.Payload(res) + } +} + +type modifyActivityRequest struct { + Name string `json:"name"` + Banner string `json:"banner"` + ActivityCategoryID int64 `json:"activity_category_id"` + Status int32 `json:"status"` + PriceDraw int64 `json:"price_draw"` + IsBoss int32 `json:"is_boss"` + StartTime string `json:"start_time"` + EndTime string `json:"end_time"` +} + +// ModifyActivity 修改活动 +// @Summary 修改活动 +// @Description 修改活动基本信息、分类、Boss标签等 +// @Tags 管理端.活动 +// @Accept json +// @Produce json +// @Param activity_id path integer true "活动ID" +// @Param RequestBody body modifyActivityRequest true "请求参数" +// @Success 200 {object} simpleMessageResponse +// @Failure 400 {object} code.Failure +// @Router /api/admin/activities/{activity_id} [put] +// @Security LoginVerifyToken +func (h *handler) ModifyActivity() core.HandlerFunc { + return func(ctx core.Context) { + req := new(modifyActivityRequest) + res := new(simpleMessageResponse) + + if err := ctx.ShouldBindJSON(req); err != nil { + ctx.AbortWithError(core.Error(http.StatusBadRequest, code.ParamBindError, validation.Error(err))) + return + } + + if ctx.SessionUserInfo().IsSuper != 1 { + ctx.AbortWithError(core.Error(http.StatusBadRequest, code.ModifyActivityError, "禁止操作")) + return + } + + id, err := strconv.ParseInt(ctx.Param("activity_id"), 10, 64) + if err != nil { + ctx.AbortWithError(core.Error(http.StatusBadRequest, code.ParamBindError, "未传递活动ID")) + return + } + + var st, et *time.Time + if req.StartTime != "" { + if t, err := time.Parse(time.RFC3339, req.StartTime); err == nil { + st = &t + } + } + if req.EndTime != "" { + if t, err := time.Parse(time.RFC3339, req.EndTime); err == nil { + et = &t + } + } + + if err := h.activity.ModifyActivity(ctx.RequestContext(), id, activitysvc.ModifyActivityInput{ + Name: req.Name, + Banner: req.Banner, + ActivityCategoryID: req.ActivityCategoryID, + Status: req.Status, + PriceDraw: req.PriceDraw, + IsBoss: req.IsBoss, + StartTime: st, + EndTime: et, + }); err != nil { + ctx.AbortWithError(core.Error(http.StatusBadRequest, code.ModifyActivityError, err.Error())) + return + } + + res.Message = "操作成功" + ctx.Payload(res) + } +} + +// DeleteActivity 删除活动 +// @Summary 删除活动 +// @Description 删除指定活动 +// @Tags 管理端.活动 +// @Accept json +// @Produce json +// @Param activity_id path integer true "活动ID" +// @Success 200 {object} simpleMessageResponse +// @Failure 400 {object} code.Failure +// @Router /api/admin/activities/{activity_id} [delete] +// @Security LoginVerifyToken +func (h *handler) DeleteActivity() core.HandlerFunc { + return func(ctx core.Context) { + res := new(simpleMessageResponse) + + if ctx.SessionUserInfo().IsSuper != 1 { + ctx.AbortWithError(core.Error(http.StatusBadRequest, code.DeleteActivityError, "禁止操作")) + return + } + + id, err := strconv.ParseInt(ctx.Param("activity_id"), 10, 64) + if err != nil { + ctx.AbortWithError(core.Error(http.StatusBadRequest, code.ParamBindError, "未传递活动ID")) + return + } + + if err := h.activity.DeleteActivity(ctx.RequestContext(), id); err != nil { + ctx.AbortWithError(core.Error(http.StatusBadRequest, code.DeleteActivityError, err.Error())) + return + } + + res.Message = "操作成功" + ctx.Payload(res) + } +} + +// GetActivityDetail 查看活动详情 +// @Summary 查看活动详情 +// @Description 查看指定活动的详细信息 +// @Tags 管理端.活动 +// @Accept json +// @Produce json +// @Param activity_id path integer true "活动ID" +// @Success 200 {object} model.Activities +// @Failure 400 {object} code.Failure +// @Router /api/admin/activities/{activity_id} [get] +// @Security LoginVerifyToken +func (h *handler) GetActivityDetail() core.HandlerFunc { + return func(ctx core.Context) { + id, err := strconv.ParseInt(ctx.Param("activity_id"), 10, 64) + if err != nil { + ctx.AbortWithError(core.Error(http.StatusBadRequest, code.ParamBindError, "未传递活动ID")) + return + } + item, err := h.activity.GetActivity(ctx.RequestContext(), id) + if err != nil { + ctx.AbortWithError(core.Error(http.StatusBadRequest, code.GetActivityError, err.Error())) + return + } + ctx.Payload(item) + } +} diff --git a/internal/api/admin/activity_categories.go b/internal/api/admin/activity_categories.go new file mode 100644 index 0000000..0ab4bef --- /dev/null +++ b/internal/api/admin/activity_categories.go @@ -0,0 +1,43 @@ +package admin + +import ( + "net/http" + + "bindbox-game/internal/code" + "bindbox-game/internal/pkg/core" +) + +type categoryItem struct { + ID int64 `json:"id"` + Name string `json:"name"` +} + +type listCategoriesResponse struct { + List []categoryItem `json:"list"` +} + +// ListActivityCategories 活动分类列表 +// @Summary 活动分类列表 +// @Description 获取启用状态的活动分类列表 +// @Tags 管理端.活动 +// @Accept json +// @Produce json +// @Success 200 {object} listCategoriesResponse +// @Failure 400 {object} code.Failure +// @Router /api/admin/activity_categories [get] +// @Security LoginVerifyToken +func (h *handler) ListActivityCategories() core.HandlerFunc { + return func(ctx core.Context) { + items, err := h.readDB.ActivityCategories.Where(h.readDB.ActivityCategories.Status.Eq(1)).Find() + if err != nil { + ctx.AbortWithError(core.Error(http.StatusBadRequest, code.ListActivitiesError, err.Error())) + return + } + res := new(listCategoriesResponse) + res.List = make([]categoryItem, len(items)) + for i, v := range items { + res.List[i] = categoryItem{ID: v.ID, Name: v.Name} + } + ctx.Payload(res) + } +} diff --git a/internal/api/admin/admin.go b/internal/api/admin/admin.go index 4841444..e72c3c9 100644 --- a/internal/api/admin/admin.go +++ b/internal/api/admin/admin.go @@ -1,21 +1,39 @@ package admin import ( - "mini-chat/internal/pkg/logger" - "mini-chat/internal/repository/mysql" - "mini-chat/internal/repository/mysql/dao" + "bindbox-game/internal/pkg/logger" + "bindbox-game/internal/repository/mysql" + "bindbox-game/internal/repository/mysql/dao" + activitysvc "bindbox-game/internal/service/activity" + adminsvc "bindbox-game/internal/service/admin" + guildsvc "bindbox-game/internal/service/guild" + productsvc "bindbox-game/internal/service/product" + bannersvc "bindbox-game/internal/service/banner" + usersvc "bindbox-game/internal/service/user" ) type handler struct { - logger logger.CustomLogger - writeDB *dao.Query - readDB *dao.Query + logger logger.CustomLogger + writeDB *dao.Query + readDB *dao.Query + svc adminsvc.Service + activity activitysvc.Service + guild guildsvc.Service + product productsvc.Service + user usersvc.Service + banner bannersvc.Service } func New(logger logger.CustomLogger, db mysql.Repo) *handler { - return &handler{ - logger: logger, - writeDB: dao.Use(db.GetDbW()), - readDB: dao.Use(db.GetDbR()), - } + return &handler{ + logger: logger, + writeDB: dao.Use(db.GetDbW()), + readDB: dao.Use(db.GetDbR()), + svc: adminsvc.New(logger, db), + activity: activitysvc.New(logger, db), + guild: guildsvc.New(logger, db), + product: productsvc.New(logger, db), + user: usersvc.New(logger, db), + banner: bannersvc.New(logger, db), + } } diff --git a/internal/api/admin/admin_create.go b/internal/api/admin/admin_create.go index 3000a36..550e904 100755 --- a/internal/api/admin/admin_create.go +++ b/internal/api/admin/admin_create.go @@ -3,15 +3,11 @@ package admin import ( "fmt" "net/http" - "time" - "mini-chat/internal/code" - "mini-chat/internal/pkg/core" - "mini-chat/internal/pkg/utils" - "mini-chat/internal/pkg/validation" - "mini-chat/internal/repository/mysql/model" - - "gorm.io/gorm" + "bindbox-game/internal/code" + "bindbox-game/internal/pkg/core" + "bindbox-game/internal/pkg/validation" + adminsvc "bindbox-game/internal/service/admin" ) type createAdminRequest struct { @@ -59,48 +55,14 @@ func (h *handler) CreateAdmin() core.HandlerFunc { return } - info, err := h.readDB.Admin.WithContext(ctx.RequestContext()). - Where(h.readDB.Admin.Username.Eq(req.UserName)). - First() - if err != nil && err != gorm.ErrRecordNotFound { - ctx.AbortWithError(core.Error( - http.StatusBadRequest, - code.CreateAdminError, - fmt.Sprintf("%s: %s", code.Text(code.CreateAdminError), err.Error())), - ) - return - } - - if info != nil { - ctx.AbortWithError(core.Error( - http.StatusBadRequest, - code.CreateAdminError, - fmt.Sprintf("%s: %s", code.Text(code.CreateAdminError), "该账号已存在")), - ) - return - } - - hashedPassword, err := utils.GenerateAdminHashedPassword(req.Password) - if err != nil { - ctx.AbortWithError(core.Error( - http.StatusBadRequest, - code.CreateAdminError, - fmt.Sprintf("%s: %s", code.Text(code.CreateAdminError), err.Error())), - ) - return - } - - Admin := new(model.Admin) - Admin.Username = req.UserName - Admin.Nickname = req.NickName - Admin.Mobile = req.Mobile - Admin.Password = hashedPassword - Admin.Avatar = req.Avatar - Admin.LoginStatus = 1 - Admin.IsSuper = 0 - Admin.CreatedUser = ctx.SessionUserInfo().UserName - Admin.CreatedAt = time.Now() - if err := h.writeDB.Admin.WithContext(ctx.RequestContext()).Create(Admin); err != nil { + if err := h.svc.Create(ctx.RequestContext(), adminsvc.CreateInput{ + Username: req.UserName, + Nickname: req.NickName, + Mobile: req.Mobile, + Password: req.Password, + Avatar: req.Avatar, + CreatedBy: ctx.SessionUserInfo().UserName, + }); err != nil { ctx.AbortWithError(core.Error( http.StatusBadRequest, code.CreateAdminError, diff --git a/internal/api/admin/admin_delete.go b/internal/api/admin/admin_delete.go index d3062c1..93d4f2d 100755 --- a/internal/api/admin/admin_delete.go +++ b/internal/api/admin/admin_delete.go @@ -6,10 +6,9 @@ import ( "strconv" "strings" - "mini-chat/internal/code" - "mini-chat/internal/pkg/core" - "mini-chat/internal/pkg/validation" - "mini-chat/internal/repository/mysql/model" + "bindbox-game/internal/code" + "bindbox-game/internal/pkg/core" + "bindbox-game/internal/pkg/validation" ) type deleteAdminRequest struct { @@ -92,10 +91,7 @@ func (h *handler) DeleteAdmin() core.HandlerFunc { return } - if _, err := h.writeDB.Admin.WithContext(ctx.RequestContext()). - Where(h.writeDB.Admin.IsSuper.Eq(0)). - Where(h.writeDB.Admin.ID.In(ids...)). - Delete(&model.Admin{}); err != nil { + if err := h.svc.Delete(ctx.RequestContext(), ids); err != nil { ctx.AbortWithError(core.Error( http.StatusBadRequest, code.DeleteAdminError, diff --git a/internal/api/admin/admin_list.go b/internal/api/admin/admin_list.go index cb2a04d..efc2539 100755 --- a/internal/api/admin/admin_list.go +++ b/internal/api/admin/admin_list.go @@ -4,12 +4,11 @@ import ( "fmt" "net/http" - "mini-chat/internal/code" - "mini-chat/internal/pkg/core" - "mini-chat/internal/pkg/timeutil" - "mini-chat/internal/pkg/validation" - - "gorm.io/gorm" + "bindbox-game/internal/code" + "bindbox-game/internal/pkg/core" + "bindbox-game/internal/pkg/timeutil" + "bindbox-game/internal/pkg/validation" + adminsvc "bindbox-game/internal/service/admin" ) type listRequest struct { @@ -81,8 +80,6 @@ func (h *handler) PageList() core.HandlerFunc { return } - query := h.readDB.Admin.WithContext(ctx.RequestContext()) - if ctx.SessionUserInfo().IsSuper != 1 { ctx.AbortWithError(core.Error( http.StatusBadRequest, @@ -92,31 +89,12 @@ func (h *handler) PageList() core.HandlerFunc { return } - if req.Username != "" { - query = query.Where(h.readDB.Admin.Username.Like(fmt.Sprintf("%%%s%%", req.Username))) - } - - if req.Nickname != "" { - query = query.Where(h.readDB.Admin.Nickname.Like(fmt.Sprintf("%%%s%%", req.Nickname))) - } - - listQueryDB := query.Session(&gorm.Session{}) - countQueryDB := query.Session(&gorm.Session{}) - - resultData, err := listQueryDB. - Order(h.readDB.Admin.ID.Desc()). - Limit(req.PageSize). - Offset((req.Page - 1) * req.PageSize).Find() - if err != nil { - ctx.AbortWithError(core.Error( - http.StatusBadRequest, - code.ListAdminError, - fmt.Sprintf("%s:%s", code.Text(code.ListAdminError), err.Error())), - ) - return - } - - count, err := countQueryDB.Count() + items, total, err := h.svc.List(ctx.RequestContext(), adminsvc.ListInput{ + Username: req.Username, + Nickname: req.Nickname, + Page: req.Page, + PageSize: req.PageSize, + }) if err != nil { ctx.AbortWithError(core.Error( http.StatusBadRequest, @@ -128,10 +106,10 @@ func (h *handler) PageList() core.HandlerFunc { res.Page = req.Page res.PageSize = req.PageSize - res.Total = count - res.List = make([]listData, len(resultData)) + res.Total = total + res.List = make([]listData, len(items)) - for k, v := range resultData { + for k, v := range items { res.List[k] = listData{ ID: v.ID, UserName: v.Username, diff --git a/internal/api/admin/admin_modify.go b/internal/api/admin/admin_modify.go index 6511c9f..79cf925 100644 --- a/internal/api/admin/admin_modify.go +++ b/internal/api/admin/admin_modify.go @@ -4,14 +4,11 @@ import ( "fmt" "net/http" "strconv" - "time" - "mini-chat/internal/code" - "mini-chat/internal/pkg/core" - "mini-chat/internal/pkg/utils" - "mini-chat/internal/pkg/validation" - - "gorm.io/gorm" + "bindbox-game/internal/code" + "bindbox-game/internal/pkg/core" + "bindbox-game/internal/pkg/validation" + adminsvc "bindbox-game/internal/service/admin" ) type modifyAdminRequest struct { @@ -79,10 +76,14 @@ func (h *handler) ModifyAdmin() core.HandlerFunc { return } - checkIdInfo, err := h.readDB.Admin.WithContext(ctx.RequestContext()). - Where(h.readDB.Admin.ID.Eq(int32(id))). - First() - if err != nil && err != gorm.ErrRecordNotFound { + if err := h.svc.Modify(ctx.RequestContext(), id, adminsvc.ModifyInput{ + Username: req.UserName, + Nickname: req.NickName, + Mobile: req.Mobile, + Password: req.Password, + Avatar: req.Avatar, + UpdatedBy: ctx.SessionUserInfo().UserName, + }); err != nil { ctx.AbortWithError(core.Error( http.StatusBadRequest, code.ModifyAdminError, @@ -91,65 +92,6 @@ func (h *handler) ModifyAdmin() core.HandlerFunc { return } - if checkIdInfo == nil { - ctx.AbortWithError(core.Error( - http.StatusBadRequest, - code.ModifyAdminError, - fmt.Sprintf("%s: %s", code.Text(code.ModifyAdminError), "该账号不存在")), - ) - return - } - - checkUserNameInfo, err := h.readDB.Admin.WithContext(ctx.RequestContext()). - Where(h.readDB.Admin.ID.Neq(int32(id))). - Where(h.readDB.Admin.Username.Eq(req.UserName)). - First() - if err != nil && err != gorm.ErrRecordNotFound { - ctx.AbortWithError(core.Error( - http.StatusBadRequest, - code.ModifyAdminError, - fmt.Sprintf("%s: %s", code.Text(code.ModifyAdminError), err.Error())), - ) - return - } - - if checkUserNameInfo != nil { - ctx.AbortWithError(core.Error( - http.StatusBadRequest, - code.ModifyAdminError, - fmt.Sprintf("%s: %s", code.Text(code.ModifyAdminError), "该账号已存在")), - ) - return - } - - if req.Password != "" { - hashedPassword, err := utils.GenerateAdminHashedPassword(req.Password) - if err != nil { - ctx.AbortWithError(core.Error( - http.StatusBadRequest, - code.ModifyAdminError, - fmt.Sprintf("%s: %s", code.Text(code.ModifyAdminError), err.Error())), - ) - return - } - checkIdInfo.Password = hashedPassword - } - - checkIdInfo.Username = req.UserName - checkIdInfo.Nickname = req.NickName - checkIdInfo.Mobile = req.Mobile - checkIdInfo.Avatar = req.Avatar - checkIdInfo.UpdatedUser = ctx.SessionUserInfo().UserName - checkIdInfo.UpdatedAt = time.Now() - if err := h.writeDB.Admin.WithContext(ctx.RequestContext()).Save(checkIdInfo); err != nil { - ctx.AbortWithError(core.Error( - http.StatusBadRequest, - code.ModifyAdminError, - fmt.Sprintf("%s:%s", code.Text(code.ModifyAdminError), err.Error())), - ) - return - } - res.Message = "操作成功" ctx.Payload(res) } diff --git a/internal/api/admin/admin_rel_app.go b/internal/api/admin/admin_rel_app.go deleted file mode 100755 index 0af6208..0000000 --- a/internal/api/admin/admin_rel_app.go +++ /dev/null @@ -1,172 +0,0 @@ -package admin - -import ( - "fmt" - "net/http" - "strconv" - "strings" - "time" - - "mini-chat/internal/code" - "mini-chat/internal/pkg/core" - "mini-chat/internal/pkg/validation" - - "gorm.io/gorm" -) - -type relAppRequest struct { - Ids string `json:"ids" binding:"required"` // 小程序编号(多个用,分割) -} - -type relAppResponse struct { - Message string `json:"message"` // 提示信息 -} - -// RelApp 客服关联小程序 -// @Summary 客服关联小程序 -// @Description 客服关联小程序 -// @Tags 管理端.客服管理 -// @Accept json -// @Produce json -// @Param id path string true "客服编号ID" -// @Param RequestBody body relAppRequest true "请求参数" -// @Success 200 {object} relAppResponse -// @Failure 400 {object} code.Failure -// @Router /api/admin/rel_app/{id} [put] -// @Security LoginVerifyToken -func (h *handler) RelApp() core.HandlerFunc { - return func(ctx core.Context) { - req := new(relAppRequest) - res := new(relAppResponse) - if err := ctx.ShouldBindJSON(req); err != nil { - ctx.AbortWithError(core.Error( - http.StatusBadRequest, - code.ParamBindError, - validation.Error(err)), - ) - return - } - - if ctx.SessionUserInfo().IsSuper != 1 { - ctx.AbortWithError(core.Error( - http.StatusBadRequest, - code.RelAppError, - fmt.Sprintf("%s: %s", code.Text(code.RelAppError), "禁止操作")), - ) - return - } - - idList := strings.Split(req.Ids, ",") - if len(idList) == 0 || (len(idList) == 1 && idList[0] == "") { - ctx.AbortWithError(core.Error( - http.StatusBadRequest, - code.ParamBindError, - "编号不能为空"), - ) - return - } - - var ids []int32 - - for _, strID := range idList { - if strID == "" { - continue - } - - id, err := strconv.Atoi(strID) - if err != nil { - ctx.AbortWithError(core.Error( - http.StatusBadRequest, - code.ParamBindError, - fmt.Sprintf("无效的编号: %s", strID)), - ) - return - } - - ids = append(ids, int32(id)) - } - - if len(ids) == 0 { - ctx.AbortWithError(core.Error( - http.StatusBadRequest, - code.ParamBindError, - "编号不能为空"), - ) - return - } - - adminID, err := strconv.Atoi(ctx.Param("id")) - if err != nil { - ctx.AbortWithError(core.Error( - http.StatusBadRequest, - code.ParamBindError, - "未传递客服编号ID"), - ) - return - } - - checkInfo, err := h.readDB.Admin.WithContext(ctx.RequestContext()). - Where(h.readDB.Admin.ID.Eq(int32(adminID))). - First() - if err != nil && err != gorm.ErrRecordNotFound { - ctx.AbortWithError(core.Error( - http.StatusBadRequest, - code.RelAppError, - fmt.Sprintf("%s: %s", code.Text(code.RelAppError), err.Error())), - ) - return - } - - if checkInfo == nil { - ctx.AbortWithError(core.Error( - http.StatusBadRequest, - code.RelAppError, - fmt.Sprintf("%s: %s", code.Text(code.RelAppError), "该客服不存在")), - ) - return - } - - if checkInfo.IsSuper == 1 { - ctx.AbortWithError(core.Error( - http.StatusBadRequest, - code.RelAppError, - fmt.Sprintf("%s", "作为超级管理员,您拥有无需关联即可查看的权限。")), - ) - return - } - - // 删除原来已经关联过的 - if _, err := h.writeDB.MiniProgram.WithContext(ctx.RequestContext()). - Where(h.writeDB.MiniProgram.AdminID.Eq(int32(adminID))). - Updates(map[string]interface{}{ - "admin_id": 0, - "updated_user": ctx.SessionUserInfo().UserName, - "updated_at": time.Now(), - }); err != nil { - ctx.AbortWithError(core.Error( - http.StatusBadRequest, - code.RelAppError, - fmt.Sprintf("%s: %s", code.Text(code.RelAppError), err.Error())), - ) - return - } - - if _, err := h.writeDB.MiniProgram.WithContext(ctx.RequestContext()). - Where(h.writeDB.MiniProgram.ID.In(ids...)). - Updates(map[string]interface{}{ - "admin_id": adminID, - "updated_user": ctx.SessionUserInfo().UserName, - "updated_at": time.Now(), - }); err != nil { - ctx.AbortWithError(core.Error( - http.StatusBadRequest, - code.RelAppError, - fmt.Sprintf("%s: %s", code.Text(code.RelAppError), err.Error())), - ) - return - } - - res.Message = "操作成功" - ctx.Payload(res) - } -} diff --git a/internal/api/admin/banner.go b/internal/api/admin/banner.go new file mode 100644 index 0000000..e8d4f01 --- /dev/null +++ b/internal/api/admin/banner.go @@ -0,0 +1,181 @@ +package admin + +import ( + "net/http" + "strconv" + + "bindbox-game/internal/code" + "bindbox-game/internal/pkg/core" + "bindbox-game/internal/pkg/validation" + bannersvc "bindbox-game/internal/service/banner" +) + +type createBannerRequest struct { + Title string `json:"title" binding:"required"` + ImageURL string `json:"image_url" binding:"required"` + LinkURL string `json:"link_url"` + Sort int32 `json:"sort"` + Status int32 `json:"status"` +} + +type createBannerResponse struct { + ID int64 `json:"id"` + Message string `json:"message"` +} + +// CreateBanner 创建轮播图 +// @Summary 创建轮播图 +// @Tags 管理端.运营 +// @Accept json +// @Produce json +// @Param RequestBody body createBannerRequest true "请求参数" +// @Success 200 {object} createBannerResponse +// @Failure 400 {object} code.Failure +// @Router /api/admin/banners [post] +// @Security LoginVerifyToken +func (h *handler) CreateBanner() core.HandlerFunc { + return func(ctx core.Context) { + req := new(createBannerRequest) + res := new(createBannerResponse) + if err := ctx.ShouldBindJSON(req); err != nil { + ctx.AbortWithError(core.Error(http.StatusBadRequest, code.ParamBindError, validation.Error(err))) + return + } + if ctx.SessionUserInfo().IsSuper != 1 { + ctx.AbortWithError(core.Error(http.StatusBadRequest, code.CreateAdminError, "禁止操作")) + return + } + item, err := h.banner.Create(ctx.RequestContext(), bannersvc.CreateInput{Title: req.Title, ImageURL: req.ImageURL, LinkURL: req.LinkURL, Sort: req.Sort, Status: req.Status}) + if err != nil { + ctx.AbortWithError(core.Error(http.StatusBadRequest, code.CreateAdminError, err.Error())) + return + } + res.ID = item.ID + res.Message = "操作成功" + ctx.Payload(res) + } +} + +type modifyBannerRequest struct { + Title *string `json:"title"` + ImageURL *string `json:"image_url"` + LinkURL *string `json:"link_url"` + Sort *int32 `json:"sort"` + Status *int32 `json:"status"` +} + +// ModifyBanner 修改轮播图 +// @Summary 修改轮播图 +// @Tags 管理端.运营 +// @Accept json +// @Produce json +// @Param banner_id path string true "轮播图ID" +// @Param RequestBody body modifyBannerRequest true "请求参数" +// @Success 200 {object} pcSimpleMessage +// @Failure 400 {object} code.Failure +// @Router /api/admin/banners/{banner_id} [put] +// @Security LoginVerifyToken +func (h *handler) ModifyBanner() core.HandlerFunc { + return func(ctx core.Context) { + req := new(modifyBannerRequest) + if err := ctx.ShouldBindJSON(req); err != nil { + ctx.AbortWithError(core.Error(http.StatusBadRequest, code.ParamBindError, validation.Error(err))) + return + } + idStr := ctx.Param("banner_id") + id, _ := strconv.ParseInt(idStr, 10, 64) + if ctx.SessionUserInfo().IsSuper != 1 { + ctx.AbortWithError(core.Error(http.StatusBadRequest, code.CreateAdminError, "禁止操作")) + return + } + if err := h.banner.Modify(ctx.RequestContext(), id, bannersvc.ModifyInput{Title: req.Title, ImageURL: req.ImageURL, LinkURL: req.LinkURL, Sort: req.Sort, Status: req.Status}); err != nil { + ctx.AbortWithError(core.Error(http.StatusBadRequest, code.CreateAdminError, err.Error())) + return + } + ctx.Payload(pcSimpleMessage{Message: "操作成功"}) + } +} + +// DeleteBanner 删除轮播图 +// @Summary 删除轮播图 +// @Tags 管理端.运营 +// @Accept json +// @Produce json +// @Param banner_id path string true "轮播图ID" +// @Success 200 {object} pcSimpleMessage +// @Failure 400 {object} code.Failure +// @Router /api/admin/banners/{banner_id} [delete] +// @Security LoginVerifyToken +func (h *handler) DeleteBanner() core.HandlerFunc { + return func(ctx core.Context) { + idStr := ctx.Param("banner_id") + id, _ := strconv.ParseInt(idStr, 10, 64) + if ctx.SessionUserInfo().IsSuper != 1 { + ctx.AbortWithError(core.Error(http.StatusBadRequest, code.CreateAdminError, "禁止操作")) + return + } + if err := h.banner.Delete(ctx.RequestContext(), id); err != nil { + ctx.AbortWithError(core.Error(http.StatusBadRequest, code.CreateAdminError, err.Error())) + return + } + ctx.Payload(pcSimpleMessage{Message: "操作成功"}) + } +} + +type listBannersRequest struct { + Status *int32 `form:"status"` + Page int `form:"page"` + PageSize int `form:"page_size"` +} + +type bannerItem struct { + ID int64 `json:"id"` + Title string `json:"title"` + ImageURL string `json:"image_url"` + LinkURL string `json:"link_url"` + Sort int32 `json:"sort"` + Status int32 `json:"status"` +} + +type listBannersResponse struct { + Page int `json:"page"` + PageSize int `json:"page_size"` + Total int64 `json:"total"` + List []bannerItem `json:"list"` +} + +// ListBanners 查看轮播图列表 +// @Summary 查看轮播图列表 +// @Tags 管理端.运营 +// @Accept json +// @Produce json +// @Param status query int false "状态" +// @Param page query int true "页码" default(1) +// @Param page_size query int true "每页数量" default(20) +// @Success 200 {object} listBannersResponse +// @Failure 400 {object} code.Failure +// @Router /api/admin/banners [get] +// @Security LoginVerifyToken +func (h *handler) ListBanners() core.HandlerFunc { + return func(ctx core.Context) { + req := new(listBannersRequest) + res := new(listBannersResponse) + if err := ctx.ShouldBindForm(req); err != nil { + ctx.AbortWithError(core.Error(http.StatusBadRequest, code.ParamBindError, validation.Error(err))) + return + } + items, total, err := h.banner.List(ctx.RequestContext(), bannersvc.ListInput{Status: req.Status, Page: req.Page, PageSize: req.PageSize}) + if err != nil { + ctx.AbortWithError(core.Error(http.StatusBadRequest, code.CreateAdminError, err.Error())) + return + } + res.Page = req.Page + res.PageSize = req.PageSize + res.Total = total + res.List = make([]bannerItem, len(items)) + for i, it := range items { + res.List[i] = bannerItem{ID: it.ID, Title: it.Title, ImageURL: it.ImageURL, LinkURL: it.LinkURL, Sort: it.Sort, Status: it.Status} + } + ctx.Payload(res) + } +} \ No newline at end of file diff --git a/internal/api/admin/guild_create.go b/internal/api/admin/guild_create.go new file mode 100644 index 0000000..be00c45 --- /dev/null +++ b/internal/api/admin/guild_create.go @@ -0,0 +1,60 @@ +package admin + +import ( + "net/http" + + "bindbox-game/internal/code" + "bindbox-game/internal/pkg/core" + "bindbox-game/internal/pkg/validation" + guildsvc "bindbox-game/internal/service/guild" +) + +type createGuildRequest struct { + Name string `json:"name" binding:"required"` + OwnerID int64 `json:"owner_id" binding:"required"` + Description string `json:"description"` + JoinMode int32 `json:"join_mode"` + ConsumeLimit int64 `json:"consume_limit"` + AvatarURL string `json:"avatar_url"` + IsOpen int32 `json:"is_open"` +} + +type createGuildResponse struct { + Message string `json:"message"` +} + +// CreateGuild 创建工会 +// @Summary 创建工会 +// @Description 创建工会并将首位成员设为会长 +// @Tags 管理端.工会 +// @Accept json +// @Produce json +// @Param RequestBody body createGuildRequest true "请求参数" +// @Success 200 {object} createGuildResponse +// @Failure 400 {object} code.Failure +// @Router /api/admin/guilds [post] +// @Security LoginVerifyToken +func (h *handler) CreateGuild() core.HandlerFunc { + return func(ctx core.Context) { + req := new(createGuildRequest) + res := new(createGuildResponse) + if err := ctx.ShouldBindJSON(req); err != nil { + ctx.AbortWithError(core.Error(http.StatusBadRequest, code.ParamBindError, validation.Error(err))) + return + } + if ctx.SessionUserInfo().IsSuper != 1 { + ctx.AbortWithError(core.Error(http.StatusBadRequest, code.CreateGuildError, "禁止操作")) + return + } + _, err := h.guild.CreateGuild(ctx.RequestContext(), guildsvc.CreateGuildInput{ + Name: req.Name, OwnerID: req.OwnerID, Description: req.Description, + JoinMode: req.JoinMode, ConsumeLimit: req.ConsumeLimit, AvatarURL: req.AvatarURL, IsOpen: req.IsOpen, + }) + if err != nil { + ctx.AbortWithError(core.Error(http.StatusBadRequest, code.CreateGuildError, err.Error())) + return + } + res.Message = "操作成功" + ctx.Payload(res) + } +} diff --git a/internal/api/admin/guild_delete.go b/internal/api/admin/guild_delete.go new file mode 100644 index 0000000..e05438c --- /dev/null +++ b/internal/api/admin/guild_delete.go @@ -0,0 +1,45 @@ +package admin + +import ( + "net/http" + "strconv" + + "bindbox-game/internal/code" + "bindbox-game/internal/pkg/core" +) + +type deleteGuildResponse struct { + Message string `json:"message"` +} + +// DeleteGuild 删除工会 +// @Summary 删除工会 +// @Description 删除指定工会 +// @Tags 管理端.工会 +// @Accept json +// @Produce json +// @Param guild_id path integer true "工会ID" +// @Success 200 {object} deleteGuildResponse +// @Failure 400 {object} code.Failure +// @Router /api/admin/guilds/{guild_id} [delete] +// @Security LoginVerifyToken +func (h *handler) DeleteGuild() core.HandlerFunc { + return func(ctx core.Context) { + res := new(deleteGuildResponse) + if ctx.SessionUserInfo().IsSuper != 1 { + ctx.AbortWithError(core.Error(http.StatusBadRequest, code.DeleteGuildError, "禁止操作")) + return + } + id, err := strconv.ParseInt(ctx.Param("guild_id"), 10, 64) + if err != nil { + ctx.AbortWithError(core.Error(http.StatusBadRequest, code.ParamBindError, "未传递工会ID")) + return + } + if err := h.guild.DeleteGuild(ctx.RequestContext(), id); err != nil { + ctx.AbortWithError(core.Error(http.StatusBadRequest, code.DeleteGuildError, err.Error())) + return + } + res.Message = "操作成功" + ctx.Payload(res) + } +} diff --git a/internal/api/admin/guild_detail.go b/internal/api/admin/guild_detail.go new file mode 100644 index 0000000..8895ccb --- /dev/null +++ b/internal/api/admin/guild_detail.go @@ -0,0 +1,36 @@ +package admin + +import ( + "net/http" + "strconv" + + "bindbox-game/internal/code" + "bindbox-game/internal/pkg/core" +) + +// GetGuildDetail 查看工会详情 +// @Summary 查看工会详情 +// @Description 查看指定工会详情 +// @Tags 管理端.工会 +// @Accept json +// @Produce json +// @Param guild_id path integer true "工会ID" +// @Success 200 {object} model.Guild +// @Failure 400 {object} code.Failure +// @Router /api/admin/guilds/{guild_id} [get] +// @Security LoginVerifyToken +func (h *handler) GetGuildDetail() core.HandlerFunc { + return func(ctx core.Context) { + id, err := strconv.ParseInt(ctx.Param("guild_id"), 10, 64) + if err != nil { + ctx.AbortWithError(core.Error(http.StatusBadRequest, code.ParamBindError, "未传递工会ID")) + return + } + item, err := h.guild.GetGuild(ctx.RequestContext(), id) + if err != nil { + ctx.AbortWithError(core.Error(http.StatusBadRequest, code.GetGuildError, err.Error())) + return + } + ctx.Payload(item) + } +} diff --git a/internal/api/admin/guild_members.go b/internal/api/admin/guild_members.go new file mode 100644 index 0000000..d7db049 --- /dev/null +++ b/internal/api/admin/guild_members.go @@ -0,0 +1,73 @@ +package admin + +import ( + "net/http" + "strconv" + + "bindbox-game/internal/code" + "bindbox-game/internal/pkg/core" + "bindbox-game/internal/pkg/validation" +) + +type listGuildMembersRequest struct { + Page int `form:"page"` + PageSize int `form:"page_size"` +} +type memberItem struct { + ID int64 `json:"id"` + UserID int64 `json:"user_id"` + Role string `json:"role"` + StartTime string `json:"start_time"` +} +type listGuildMembersResponse struct { + Page int `json:"page"` + PageSize int `json:"page_size"` + Total int64 `json:"total"` + List []memberItem `json:"list"` +} + +// ListGuildMembers 查看工会成员 +// @Summary 查看工会成员 +// @Description 查看指定工会的成员列表 +// @Tags 管理端.工会 +// @Accept json +// @Produce json +// @Param guild_id path integer true "工会ID" +// @Param page query int true "页码" default(1) +// @Param page_size query int true "每页数量,最多100" default(20) +// @Success 200 {object} listGuildMembersResponse +// @Failure 400 {object} code.Failure +// @Router /api/admin/guilds/{guild_id}/members [get] +// @Security LoginVerifyToken +func (h *handler) ListGuildMembers() core.HandlerFunc { + return func(ctx core.Context) { + req := new(listGuildMembersRequest) + res := new(listGuildMembersResponse) + if err := ctx.ShouldBindForm(req); err != nil { + ctx.AbortWithError(core.Error(http.StatusBadRequest, code.ParamBindError, validation.Error(err))) + return + } + if ctx.SessionUserInfo().IsSuper != 1 { + ctx.AbortWithError(core.Error(http.StatusBadRequest, code.ListGuildMembersError, "禁止操作")) + return + } + id, err := strconv.ParseInt(ctx.Param("guild_id"), 10, 64) + if err != nil { + ctx.AbortWithError(core.Error(http.StatusBadRequest, code.ParamBindError, "未传递工会ID")) + return + } + items, total, err := h.guild.ListMembers(ctx.RequestContext(), id, req.Page, req.PageSize) + if err != nil { + ctx.AbortWithError(core.Error(http.StatusBadRequest, code.ListGuildMembersError, err.Error())) + return + } + res.Page = req.Page + res.PageSize = req.PageSize + res.Total = total + res.List = make([]memberItem, len(items)) + for i, v := range items { + res.List[i] = memberItem{ID: v.ID, UserID: v.UserID, Role: v.Role, StartTime: v.StartTime.Format("2006-01-02 15:04:05")} + } + ctx.Payload(res) + } +} diff --git a/internal/api/admin/guild_modify.go b/internal/api/admin/guild_modify.go new file mode 100644 index 0000000..fb3188e --- /dev/null +++ b/internal/api/admin/guild_modify.go @@ -0,0 +1,65 @@ +package admin + +import ( + "net/http" + "strconv" + + "bindbox-game/internal/code" + "bindbox-game/internal/pkg/core" + "bindbox-game/internal/pkg/validation" + guildsvc "bindbox-game/internal/service/guild" +) + +type modifyGuildRequest struct { + Name string `json:"name"` + Description string `json:"description"` + JoinMode int32 `json:"join_mode"` + ConsumeLimit int64 `json:"consume_limit"` + AvatarURL string `json:"avatar_url"` + IsOpen int32 `json:"is_open"` + Status int32 `json:"status"` +} + +type modifyGuildResponse struct { + Message string `json:"message"` +} + +// ModifyGuild 修改工会 +// @Summary 修改工会 +// @Description 修改指定工会信息 +// @Tags 管理端.工会 +// @Accept json +// @Produce json +// @Param guild_id path integer true "工会ID" +// @Param RequestBody body modifyGuildRequest true "请求参数" +// @Success 200 {object} modifyGuildResponse +// @Failure 400 {object} code.Failure +// @Router /api/admin/guilds/{guild_id} [put] +// @Security LoginVerifyToken +func (h *handler) ModifyGuild() core.HandlerFunc { + return func(ctx core.Context) { + req := new(modifyGuildRequest) + res := new(modifyGuildResponse) + if err := ctx.ShouldBindJSON(req); err != nil { + ctx.AbortWithError(core.Error(http.StatusBadRequest, code.ParamBindError, validation.Error(err))) + return + } + if ctx.SessionUserInfo().IsSuper != 1 { + ctx.AbortWithError(core.Error(http.StatusBadRequest, code.ModifyGuildError, "禁止操作")) + return + } + id, err := strconv.ParseInt(ctx.Param("guild_id"), 10, 64) + if err != nil { + ctx.AbortWithError(core.Error(http.StatusBadRequest, code.ParamBindError, "未传递工会ID")) + return + } + if err := h.guild.ModifyGuild(ctx.RequestContext(), id, guildsvc.ModifyGuildInput{ + Name: req.Name, Description: req.Description, JoinMode: req.JoinMode, ConsumeLimit: req.ConsumeLimit, AvatarURL: req.AvatarURL, IsOpen: req.IsOpen, Status: req.Status, + }); err != nil { + ctx.AbortWithError(core.Error(http.StatusBadRequest, code.ModifyGuildError, err.Error())) + return + } + res.Message = "操作成功" + ctx.Payload(res) + } +} diff --git a/internal/api/admin/issues_admin.go b/internal/api/admin/issues_admin.go new file mode 100644 index 0000000..2cc6e6d --- /dev/null +++ b/internal/api/admin/issues_admin.go @@ -0,0 +1,223 @@ +package admin + +import ( + "net/http" + "strconv" + + "bindbox-game/internal/code" + "bindbox-game/internal/pkg/core" + "bindbox-game/internal/pkg/validation" + activitysvc "bindbox-game/internal/service/activity" +) + +type listIssuesRequest struct { + Page int `form:"page"` + PageSize int `form:"page_size"` +} + +type listIssuesResponse struct { + Page int `json:"page"` + PageSize int `json:"page_size"` + Total int64 `json:"total"` + List []*activitysvcIssueData `json:"list"` +} + +type activitysvcIssueData struct { + ID int64 `json:"id"` + IssueNumber string `json:"issue_number"` + Status int32 `json:"status"` + Sort int32 `json:"sort"` +} + +// ListActivityIssues 查看活动期数 +// @Summary 查看活动期数 +// @Description 获取指定活动的期数列表,支持分页 +// @Tags 管理端.活动 +// @Accept json +// @Produce json +// @Param activity_id path integer true "活动ID" +// @Param page query int true "页码" default(1) +// @Param page_size query int true "每页数量,最多100" default(20) +// @Success 200 {object} listIssuesResponse +// @Failure 400 {object} code.Failure +// @Router /api/admin/activities/{activity_id}/issues [get] +// @Security LoginVerifyToken +func (h *handler) ListActivityIssues() core.HandlerFunc { + return func(ctx core.Context) { + req := new(listIssuesRequest) + res := new(listIssuesResponse) + if err := ctx.ShouldBindForm(req); err != nil { + ctx.AbortWithError(core.Error(http.StatusBadRequest, code.ParamBindError, validation.Error(err))) + return + } + id, err := strconv.ParseInt(ctx.Param("activity_id"), 10, 64) + if err != nil { + ctx.AbortWithError(core.Error(http.StatusBadRequest, code.ParamBindError, "未传递活动ID")) + return + } + if req.Page <= 0 { + req.Page = 1 + } + if req.PageSize <= 0 { + req.PageSize = 20 + } + items, total, err := h.activity.ListIssues(ctx.RequestContext(), id, req.Page, req.PageSize) + if err != nil { + ctx.AbortWithError(core.Error(http.StatusBadRequest, code.ListActivityIssuesError, err.Error())) + return + } + res.Page = req.Page + res.PageSize = req.PageSize + res.Total = total + res.List = make([]*activitysvcIssueData, len(items)) + for i, v := range items { + res.List[i] = &activitysvcIssueData{ + ID: v.ID, + IssueNumber: v.IssueNumber, + Status: v.Status, + Sort: v.Sort, + } + } + ctx.Payload(res) + } +} + +type createIssueRequest struct { + IssueNumber string `json:"issue_number" binding:"required"` + Status int32 `json:"status"` + Sort int32 `json:"sort"` +} + +type createIssueResp struct { + ID int64 `json:"id"` + Message string `json:"message"` +} +type simpleMessage struct { + Message string `json:"message"` +} + +// CreateActivityIssue 创建活动期数 +// @Summary 创建活动期数 +// @Description 为指定活动创建一个新的期数 +// @Tags 管理端.活动 +// @Accept json +// @Produce json +// @Param activity_id path integer true "活动ID" +// @Param RequestBody body createIssueRequest true "请求参数" +// @Success 200 {object} simpleMessage +// @Failure 400 {object} code.Failure +// @Router /api/admin/activities/{activity_id}/issues [post] +// @Security LoginVerifyToken +func (h *handler) CreateActivityIssue() core.HandlerFunc { + return func(ctx core.Context) { + req := new(createIssueRequest) + res := new(createIssueResp) + if err := ctx.ShouldBindJSON(req); err != nil { + ctx.AbortWithError(core.Error(http.StatusBadRequest, code.ParamBindError, validation.Error(err))) + return + } + if ctx.SessionUserInfo().IsSuper != 1 { + ctx.AbortWithError(core.Error(http.StatusBadRequest, code.CreateActivityIssueError, "禁止操作")) + return + } + id, err := strconv.ParseInt(ctx.Param("activity_id"), 10, 64) + if err != nil { + ctx.AbortWithError(core.Error(http.StatusBadRequest, code.ParamBindError, "未传递活动ID")) + return + } + item, err := h.activity.CreateIssue(ctx.RequestContext(), id, activitysvc.CreateIssueInput{ + IssueNumber: req.IssueNumber, + Status: req.Status, + Sort: req.Sort, + }) + if err != nil { + ctx.AbortWithError(core.Error(http.StatusBadRequest, code.CreateActivityIssueError, err.Error())) + return + } + res.ID = item.ID + res.Message = "操作成功" + ctx.Payload(res) + } +} + +type modifyIssueRequest struct { + IssueNumber string `json:"issue_number"` + Status int32 `json:"status"` + Sort int32 `json:"sort"` +} + +// ModifyActivityIssue 修改活动期数 +// @Summary 修改活动期数 +// @Description 修改指定期数的信息 +// @Tags 管理端.活动 +// @Accept json +// @Produce json +// @Param activity_id path integer true "活动ID" +// @Param issue_id path integer true "期ID" +// @Param RequestBody body modifyIssueRequest true "请求参数" +// @Success 200 {object} simpleMessage +// @Failure 400 {object} code.Failure +// @Router /api/admin/activities/{activity_id}/issues/{issue_id} [put] +// @Security LoginVerifyToken +func (h *handler) ModifyActivityIssue() core.HandlerFunc { + return func(ctx core.Context) { + req := new(modifyIssueRequest) + res := new(simpleMessage) + if err := ctx.ShouldBindJSON(req); err != nil { + ctx.AbortWithError(core.Error(http.StatusBadRequest, code.ParamBindError, validation.Error(err))) + return + } + if ctx.SessionUserInfo().IsSuper != 1 { + ctx.AbortWithError(core.Error(http.StatusBadRequest, code.ModifyActivityIssueError, "禁止操作")) + return + } + issueID, err := strconv.ParseInt(ctx.Param("issue_id"), 10, 64) + if err != nil { + ctx.AbortWithError(core.Error(http.StatusBadRequest, code.ParamBindError, "未传递期ID")) + return + } + if err := h.activity.ModifyIssue(ctx.RequestContext(), issueID, activitysvc.ModifyIssueInput{ + IssueNumber: req.IssueNumber, + Status: req.Status, + Sort: req.Sort, + }); err != nil { + ctx.AbortWithError(core.Error(http.StatusBadRequest, code.ModifyActivityIssueError, err.Error())) + return + } + res.Message = "操作成功" + ctx.Payload(res) + } +} + +// DeleteActivityIssue 删除活动期数 +// @Summary 删除活动期数 +// @Description 删除指定期数 +// @Tags 管理端.活动 +// @Accept json +// @Produce json +// @Param activity_id path integer true "活动ID" +// @Param issue_id path integer true "期ID" +// @Success 200 {object} simpleMessage +// @Failure 400 {object} code.Failure +// @Router /api/admin/activities/{activity_id}/issues/{issue_id} [delete] +// @Security LoginVerifyToken +func (h *handler) DeleteActivityIssue() core.HandlerFunc { + return func(ctx core.Context) { + res := new(simpleMessage) + if ctx.SessionUserInfo().IsSuper != 1 { + ctx.AbortWithError(core.Error(http.StatusBadRequest, code.DeleteActivityIssueError, "禁止操作")) + return + } + issueID, err := strconv.ParseInt(ctx.Param("issue_id"), 10, 64) + if err != nil { + ctx.AbortWithError(core.Error(http.StatusBadRequest, code.ParamBindError, "未传递期ID")) + return + } + if err := h.activity.DeleteIssue(ctx.RequestContext(), issueID); err != nil { + ctx.AbortWithError(core.Error(http.StatusBadRequest, code.DeleteActivityIssueError, err.Error())) + return + } + res.Message = "操作成功" + ctx.Payload(res) + } +} diff --git a/internal/api/admin/item_cards_admin.go b/internal/api/admin/item_cards_admin.go new file mode 100644 index 0000000..dad930e --- /dev/null +++ b/internal/api/admin/item_cards_admin.go @@ -0,0 +1,377 @@ +package admin + +import ( + "net/http" + "strconv" + "time" + + "bindbox-game/internal/code" + "bindbox-game/internal/pkg/core" + "bindbox-game/internal/pkg/validation" + "bindbox-game/internal/repository/mysql/model" +) + +type simpleMessageResponse struct { + Message string `json:"message"` +} + +type createItemCardRequest struct { + Name string `json:"name" binding:"required"` + Status int32 `json:"status"` + CardType int32 `json:"card_type" binding:"required"` + ScopeType int32 `json:"scope_type" binding:"required"` + ActivityCategoryID int64 `json:"activity_category_id"` + ActivityID int64 `json:"activity_id"` + IssueID int64 `json:"issue_id"` + Price int64 `json:"price" binding:"required"` + ValidStartUnix *int64 `json:"valid_start_unix"` + ValidEndUnix *int64 `json:"valid_end_unix"` + EffectType int32 `json:"effect_type" binding:"required"` + RewardMultiplierX1000 int32 `json:"reward_multiplier_x1000"` + BoostRateX1000 int32 `json:"boost_rate_x1000"` + StackingStrategy int32 `json:"stacking_strategy"` + MaxEffectValueX1000 int32 `json:"max_effect_value_x1000"` + Remark string `json:"remark"` +} + +type createItemCardResponse struct { + ID int64 `json:"id"` + Message string `json:"message"` +} + +// CreateSystemItemCard 创建道具卡 +// @Summary 创建道具卡 +// @Description 管理员创建新的道具卡,支持设置类型、效果、有效期等属性 +// @Tags 管理端.运营管理 +// @Accept json +// @Produce json +// @Param RequestBody body createItemCardRequest true "创建道具卡请求参数" +// @Success 200 {object} createItemCardResponse +// @Failure 400 {object} code.Failure "参数错误" +// @Failure 401 {object} code.Failure "未授权" +// @Failure 403 {object} code.Failure "无权限,仅超管可操作" +// @Failure 500 {object} code.Failure "服务器内部错误" +// @Router /api/admin/system_item_cards [post] +func (h *handler) CreateSystemItemCard() core.HandlerFunc { + return func(ctx core.Context) { + req := new(createItemCardRequest) + res := new(createItemCardResponse) + if err := ctx.ShouldBindJSON(req); err != nil { + ctx.AbortWithError(core.Error(http.StatusBadRequest, code.ParamBindError, validation.Error(err))) + return + } + if ctx.SessionUserInfo().IsSuper != 1 { + ctx.AbortWithError(core.Error(http.StatusBadRequest, code.CreateAdminError, "禁止操作")) + return + } + item := &model.SystemItemCards{ + Name: req.Name, + Status: func() int32 { + if req.Status == 0 { + return 1 + } + return req.Status + }(), + CardType: req.CardType, + ScopeType: req.ScopeType, + ActivityCategoryID: req.ActivityCategoryID, + ActivityID: req.ActivityID, + IssueID: req.IssueID, + Price: req.Price, + EffectType: req.EffectType, + RewardMultiplierX1000: req.RewardMultiplierX1000, + BoostRateX1000: req.BoostRateX1000, + StackingStrategy: func() int32 { + if req.StackingStrategy == 0 { + return 1 + } + return req.StackingStrategy + }(), + MaxEffectValueX1000: req.MaxEffectValueX1000, + Remark: req.Remark, + } + do := h.writeDB.SystemItemCards.WithContext(ctx.RequestContext()) + if req.ValidStartUnix != nil { + item.ValidStart = time.Unix(*req.ValidStartUnix, 0) + } + if req.ValidEndUnix != nil { + item.ValidEnd = time.Unix(*req.ValidEndUnix, 0) + } else { + do = do.Omit(h.writeDB.SystemItemCards.ValidEnd) + } + if err := do.Create(item); err != nil { + ctx.AbortWithError(core.Error(http.StatusBadRequest, code.CreateAdminError, err.Error())) + return + } + res.ID = item.ID + res.Message = "操作成功" + ctx.Payload(res) + } +} + +type modifyItemCardRequest struct { + Name *string `json:"name"` + Status *int32 `json:"status"` + CardType *int32 `json:"card_type"` + ScopeType *int32 `json:"scope_type"` + ActivityCategoryID *int64 `json:"activity_category_id"` + ActivityID *int64 `json:"activity_id"` + IssueID *int64 `json:"issue_id"` + Price *int64 `json:"price"` + ValidStartUnix *int64 `json:"valid_start_unix"` + ValidEndUnix *int64 `json:"valid_end_unix"` + EffectType *int32 `json:"effect_type"` + RewardMultiplierX1000 *int32 `json:"reward_multiplier_x1000"` + BoostRateX1000 *int32 `json:"boost_rate_x1000"` + StackingStrategy *int32 `json:"stacking_strategy"` + MaxEffectValueX1000 *int32 `json:"max_effect_value_x1000"` + Remark *string `json:"remark"` +} + +// ModifySystemItemCard 修改道具卡 +// @Summary 修改道具卡 +// @Description 管理员修改道具卡信息,支持修改名称、价格、有效期等属性 +// @Tags 管理端.运营管理 +// @Accept json +// @Produce json +// @Param item_card_id path integer true "道具卡ID" +// @Param RequestBody body modifyItemCardRequest true "修改道具卡请求参数" +// @Success 200 {object} simpleMessageResponse +// @Failure 400 {object} code.Failure "参数错误" +// @Failure 401 {object} code.Failure "未授权" +// @Failure 403 {object} code.Failure "无权限,仅超管可操作" +// @Failure 500 {object} code.Failure "服务器内部错误" +// @Router /api/admin/system_item_cards/{item_card_id} [put] +func (h *handler) ModifySystemItemCard() core.HandlerFunc { + return func(ctx core.Context) { + req := new(modifyItemCardRequest) + if err := ctx.ShouldBindJSON(req); err != nil { + ctx.AbortWithError(core.Error(http.StatusBadRequest, code.ParamBindError, validation.Error(err))) + return + } + idStr := ctx.Param("item_card_id") + id, _ := strconv.ParseInt(idStr, 10, 64) + if ctx.SessionUserInfo().IsSuper != 1 { + ctx.AbortWithError(core.Error(http.StatusBadRequest, code.CreateAdminError, "禁止操作")) + return + } + set := map[string]any{} + if req.Name != nil { + set["name"] = *req.Name + } + if req.Status != nil { + set["status"] = *req.Status + } + if req.CardType != nil { + set["card_type"] = *req.CardType + } + if req.ScopeType != nil { + set["scope_type"] = *req.ScopeType + } + if req.ActivityCategoryID != nil { + set["activity_category_id"] = *req.ActivityCategoryID + } + if req.ActivityID != nil { + set["activity_id"] = *req.ActivityID + } + if req.IssueID != nil { + set["issue_id"] = *req.IssueID + } + if req.Price != nil { + set["price"] = *req.Price + } + if req.EffectType != nil { + set["effect_type"] = *req.EffectType + } + if req.RewardMultiplierX1000 != nil { + set["reward_multiplier_x1000"] = *req.RewardMultiplierX1000 + } + if req.BoostRateX1000 != nil { + set["boost_rate_x1000"] = *req.BoostRateX1000 + } + if req.StackingStrategy != nil { + set["stacking_strategy"] = *req.StackingStrategy + } + if req.MaxEffectValueX1000 != nil { + set["max_effect_value_x1000"] = *req.MaxEffectValueX1000 + } + if req.Remark != nil { + set["remark"] = *req.Remark + } + if req.ValidStartUnix != nil { + set["valid_start"] = time.Unix(*req.ValidStartUnix, 0) + } + if req.ValidEndUnix != nil { + set["valid_end"] = time.Unix(*req.ValidEndUnix, 0) + } + if len(set) == 0 { + ctx.Payload(simpleMessageResponse{Message: "操作成功"}) + return + } + if _, err := h.writeDB.SystemItemCards.WithContext(ctx.RequestContext()).Where(h.writeDB.SystemItemCards.ID.Eq(id)).Updates(set); err != nil { + ctx.AbortWithError(core.Error(http.StatusBadRequest, code.CreateAdminError, err.Error())) + return + } + ctx.Payload(simpleMessageResponse{Message: "操作成功"}) + } +} + +// DeleteSystemItemCard 删除道具卡 +// @Summary 删除道具卡 +// @Description 管理员删除指定的道具卡 +// @Tags 管理端.运营管理 +// @Accept json +// @Produce json +// @Param item_card_id path integer true "道具卡ID" +// @Success 200 {object} simpleMessageResponse +// @Failure 400 {object} code.Failure "参数错误" +// @Failure 401 {object} code.Failure "未授权" +// @Failure 403 {object} code.Failure "无权限,仅超管可操作" +// @Failure 500 {object} code.Failure "服务器内部错误" +// @Router /api/admin/system_item_cards/{item_card_id} [delete] +func (h *handler) DeleteSystemItemCard() core.HandlerFunc { + return func(ctx core.Context) { + idStr := ctx.Param("item_card_id") + id, _ := strconv.ParseInt(idStr, 10, 64) + if ctx.SessionUserInfo().IsSuper != 1 { + ctx.AbortWithError(core.Error(http.StatusBadRequest, code.CreateAdminError, "禁止操作")) + return + } + if _, err := h.writeDB.SystemItemCards.WithContext(ctx.RequestContext()).Where(h.writeDB.SystemItemCards.ID.Eq(id)).Delete(); err != nil { + ctx.AbortWithError(core.Error(http.StatusBadRequest, code.CreateAdminError, err.Error())) + return + } + ctx.Payload(simpleMessageResponse{Message: "操作成功"}) + } +} + +type listItemCardsRequest struct { + Name string `form:"name"` + Status int32 `form:"status"` + CardType int32 `form:"card_type"` + ScopeType int32 `form:"scope_type"` + Page int `form:"page"` + PageSize int `form:"page_size"` +} + +type itemCardListItem struct { + *model.SystemItemCards +} + +type listItemCardsResponse struct { + Page int `json:"page"` + PageSize int `json:"page_size"` + Total int64 `json:"total"` + List []itemCardListItem `json:"list"` +} + +// ListSystemItemCards 获取道具卡列表 +// @Summary 获取道具卡列表 +// @Description 管理员获取道具卡列表,支持按名称、状态、类型等条件筛选 +// @Tags 管理端.运营管理 +// @Accept json +// @Produce json +// @Param name query string false "道具卡名称" +// @Param status query integer false "状态:1启用 2禁用" +// @Param card_type query integer false "道具卡类型:1抽奖卡 2加成卡 3保底卡" +// @Param scope_type query integer false "适用范围:1全局 2活动分类 3活动 4期次" +// @Param page query integer false "页码,默认1" +// @Param page_size query integer false "每页条数,默认10" +// @Success 200 {object} listItemCardsResponse +// @Failure 400 {object} code.Failure "参数错误" +// @Failure 401 {object} code.Failure "未授权" +// @Failure 500 {object} code.Failure "服务器内部错误" +// @Router /api/admin/system_item_cards [get] +func (h *handler) ListSystemItemCards() core.HandlerFunc { + return func(ctx core.Context) { + req := new(listItemCardsRequest) + res := new(listItemCardsResponse) + if err := ctx.ShouldBindForm(req); err != nil { + ctx.AbortWithError(core.Error(http.StatusBadRequest, code.ParamBindError, validation.Error(err))) + return + } + q := h.readDB.SystemItemCards.WithContext(ctx.RequestContext()).ReadDB() + if req.Name != "" { + q = q.Where(h.readDB.SystemItemCards.Name.Like("%" + req.Name + "%")) + } + if req.Status != 0 { + q = q.Where(h.readDB.SystemItemCards.Status.Eq(req.Status)) + } + if req.CardType != 0 { + q = q.Where(h.readDB.SystemItemCards.CardType.Eq(req.CardType)) + } + if req.ScopeType != 0 { + q = q.Where(h.readDB.SystemItemCards.ScopeType.Eq(req.ScopeType)) + } + total, err := q.Count() + if err != nil { + ctx.AbortWithError(core.Error(http.StatusBadRequest, code.ListActivitiesError, err.Error())) + return + } + if req.Page <= 0 { + req.Page = 1 + } + if req.PageSize <= 0 { + req.PageSize = 20 + } + if req.PageSize > 100 { + req.PageSize = 100 + } + rows, err := q.Order(h.readDB.SystemItemCards.ID.Desc()).Offset((req.Page - 1) * req.PageSize).Limit(req.PageSize).Find() + if err != nil { + ctx.AbortWithError(core.Error(http.StatusBadRequest, code.ListActivitiesError, err.Error())) + return + } + res.Page = req.Page + res.PageSize = req.PageSize + res.Total = total + res.List = make([]itemCardListItem, len(rows)) + for i, r := range rows { + res.List[i] = itemCardListItem{SystemItemCards: r} + } + ctx.Payload(res) + } +} + +type assignItemCardRequest struct { + CardID int64 `json:"card_id" binding:"required"` + Quantity int `json:"quantity"` +} + +// AssignUserItemCard 给用户分配道具卡 +// @Summary 给用户分配道具卡 +// @Description 管理员给指定用户分配道具卡,可指定数量 +// @Tags 管理端.运营管理 +// @Accept json +// @Produce json +// @Param user_id path integer true "用户ID" +// @Param RequestBody body assignItemCardRequest true "分配道具卡请求参数" +// @Success 200 {object} simpleMessageResponse +// @Failure 400 {object} code.Failure "参数错误" +// @Failure 401 {object} code.Failure "未授权" +// @Failure 403 {object} code.Failure "无权限,仅超管可操作" +// @Failure 500 {object} code.Failure "服务器内部错误" +// @Router /api/admin/users/{user_id}/item_cards [post] +func (h *handler) AssignUserItemCard() core.HandlerFunc { + return func(ctx core.Context) { + req := new(assignItemCardRequest) + if err := ctx.ShouldBindJSON(req); err != nil { + ctx.AbortWithError(core.Error(http.StatusBadRequest, code.ParamBindError, validation.Error(err))) + return + } + userID, err := strconv.ParseInt(ctx.Param("user_id"), 10, 64) + if err != nil { + ctx.AbortWithError(core.Error(http.StatusBadRequest, code.ParamBindError, "未传递用户ID")) + return + } + if ctx.SessionUserInfo().IsSuper != 1 { + ctx.AbortWithError(core.Error(http.StatusBadRequest, code.CreateAdminError, "禁止操作")) + return + } + if err := h.user.AddItemCard(ctx.RequestContext(), userID, req.CardID, req.Quantity); err != nil { + ctx.AbortWithError(core.Error(http.StatusBadRequest, code.CreateAdminError, err.Error())) + return + } + ctx.Payload(simpleMessageResponse{Message: "操作成功"}) + } +} diff --git a/internal/api/admin/login.go b/internal/api/admin/login.go index 83c8146..c098a43 100644 --- a/internal/api/admin/login.go +++ b/internal/api/admin/login.go @@ -3,17 +3,12 @@ package admin import ( "fmt" "net/http" - "time" - "mini-chat/configs" - "mini-chat/internal/code" - "mini-chat/internal/pkg/core" - "mini-chat/internal/pkg/jwtoken" - "mini-chat/internal/pkg/utils" - "mini-chat/internal/pkg/validation" - "mini-chat/internal/proposal" - - "gorm.io/gorm" + "bindbox-game/internal/code" + "bindbox-game/internal/pkg/core" + "bindbox-game/internal/pkg/utils" + "bindbox-game/internal/pkg/validation" + adminsvc "bindbox-game/internal/service/admin" ) type loginRequest struct { @@ -49,70 +44,12 @@ func (h *handler) Login() core.HandlerFunc { return } - // 验证用户是否存在 - info, err := h.readDB.Admin.WithContext(ctx.RequestContext()).Where(h.readDB.Admin.Username.Eq(req.Username)).First() - if err != nil && err != gorm.ErrRecordNotFound { - ctx.AbortWithError(core.Error( - http.StatusBadRequest, - code.AdminLoginError, - fmt.Sprintf("%s: %s", code.Text(code.AdminLoginError), err.Error())), - ) - return - } - - if err == gorm.ErrRecordNotFound { - ctx.AbortWithError(core.Error( - http.StatusBadRequest, - code.AdminLoginError, - fmt.Sprintf("%s: %s", code.Text(code.AdminLoginError), "账号不存在,请联系管理员。")), - ) - return - } - - // 验证登录状态 - if info.LoginStatus != 1 { - ctx.AbortWithError(core.Error( - http.StatusBadRequest, - code.AdminLoginError, - fmt.Sprintf("%s:账号已被禁用", code.Text(code.AdminLoginError))), - ) - return - } - - // 验证密码 - if !utils.VerifyAdminHashedPassword(info.Password, req.Password) { - ctx.AbortWithError(core.Error( - http.StatusBadRequest, - code.AdminLoginError, - fmt.Sprintf("%s:用户名或密码错误,请联系管理员。", code.Text(code.AdminLoginError))), - ) - return - } - - // 设置 Session 信息 - sessionUserInfo := proposal.SessionUserInfo{ - Id: info.ID, - UserName: info.Username, - NickName: info.Nickname, - IsSuper: info.IsSuper, - Platform: "管理端", - } - - // 设置载荷数据、有效期,生成 JWT Token String - tokenString, err := jwtoken.New(configs.Get().JWT.AdminSecret).Sign(sessionUserInfo, 3*24*time.Hour) + result, err := h.svc.Login(ctx.RequestContext(), adminsvc.LoginInput{ + Username: req.Username, + Password: req.Password, + IP: utils.GetIP(ctx.Request()), + }) if err != nil { - ctx.AbortWithError(core.Error( - http.StatusBadRequest, - code.AdminLoginError, - fmt.Sprintf("%s:token 生成失败(%s)", code.Text(code.AdminLoginError), err.Error())), - ) - return - } - - info.LastLoginTime = time.Now() - info.LastLoginIP = utils.GetIP(ctx.Request()) - info.LastLoginHash = utils.MD5(tokenString) - if err := h.writeDB.Admin.WithContext(ctx.RequestContext()).Save(info); err != nil { ctx.AbortWithError(core.Error( http.StatusBadRequest, code.AdminLoginError, @@ -121,8 +58,8 @@ func (h *handler) Login() core.HandlerFunc { return } - res.Token = tokenString - res.IsSuper = info.IsSuper + res.Token = result.Token + res.IsSuper = result.IsSuper ctx.Payload(res) } } diff --git a/internal/api/admin/product_category_create.go b/internal/api/admin/product_category_create.go new file mode 100644 index 0000000..7fdd262 --- /dev/null +++ b/internal/api/admin/product_category_create.go @@ -0,0 +1,182 @@ +package admin + +import ( + "net/http" + "strconv" + + "bindbox-game/internal/code" + "bindbox-game/internal/pkg/core" + "bindbox-game/internal/pkg/validation" + prodsvc "bindbox-game/internal/service/product" +) + +type createProductCategoryRequest struct { + Name string `json:"name" binding:"required"` + ParentID int64 `json:"parent_id"` + Status int32 `json:"status"` +} + +type createProductCategoryResponse struct { + ID int64 `json:"id"` + Message string `json:"message"` +} + +// CreateProductCategory 创建商品分类 +// @Summary 创建商品分类 +// @Tags 管理端.商品 +// @Accept json +// @Produce json +// @Param RequestBody body createProductCategoryRequest true "请求参数" +// @Success 200 {object} createProductCategoryResponse +// @Failure 400 {object} code.Failure +// @Router /api/admin/product_categories [post] +// @Security LoginVerifyToken +func (h *handler) CreateProductCategory() core.HandlerFunc { + return func(ctx core.Context) { + req := new(createProductCategoryRequest) + res := new(createProductCategoryResponse) + if err := ctx.ShouldBindJSON(req); err != nil { + ctx.AbortWithError(core.Error(http.StatusBadRequest, code.ParamBindError, validation.Error(err))) + return + } + if ctx.SessionUserInfo().IsSuper != 1 { + ctx.AbortWithError(core.Error(http.StatusBadRequest, code.CreateAdminError, "禁止操作")) + return + } + item, err := h.product.CreateCategory(ctx.RequestContext(), prodsvc.CreateCategoryInput{ + Name: req.Name, ParentID: req.ParentID, Status: req.Status, + }) + if err != nil { + ctx.AbortWithError(core.Error(http.StatusBadRequest, code.CreateAdminError, err.Error())) + return + } + res.ID = item.ID + res.Message = "操作成功" + ctx.Payload(res) + } +} + +type modifyProductCategoryRequest struct { + Name *string `json:"name"` + ParentID *int64 `json:"parent_id"` + Status *int32 `json:"status"` +} + +type pcSimpleMessage struct { + Message string `json:"message"` +} + +// ModifyProductCategory 修改商品分类 +// @Summary 修改商品分类 +// @Tags 管理端.商品 +// @Accept json +// @Produce json +// @Param category_id path string true "分类ID" +// @Param RequestBody body modifyProductCategoryRequest true "请求参数" +// @Success 200 {object} pcSimpleMessage +// @Failure 400 {object} code.Failure +// @Router /api/admin/product_categories/{category_id} [put] +// @Security LoginVerifyToken +func (h *handler) ModifyProductCategory() core.HandlerFunc { + return func(ctx core.Context) { + req := new(modifyProductCategoryRequest) + if err := ctx.ShouldBindJSON(req); err != nil { + ctx.AbortWithError(core.Error(http.StatusBadRequest, code.ParamBindError, validation.Error(err))) + return + } + idStr := ctx.Param("category_id") + id, _ := strconv.ParseInt(idStr, 10, 64) + if ctx.SessionUserInfo().IsSuper != 1 { + ctx.AbortWithError(core.Error(http.StatusBadRequest, code.CreateAdminError, "禁止操作")) + return + } + if err := h.product.ModifyCategory(ctx.RequestContext(), id, prodsvc.ModifyCategoryInput{Name: req.Name, ParentID: req.ParentID, Status: req.Status}); err != nil { + ctx.AbortWithError(core.Error(http.StatusBadRequest, code.CreateAdminError, err.Error())) + return + } + ctx.Payload(pcSimpleMessage{Message: "操作成功"}) + } +} + +// DeleteProductCategory 删除商品分类 +// @Summary 删除商品分类 +// @Tags 管理端.商品 +// @Accept json +// @Produce json +// @Param category_id path string true "分类ID" +// @Success 200 {object} pcSimpleMessage +// @Failure 400 {object} code.Failure +// @Router /api/admin/product_categories/{category_id} [delete] +// @Security LoginVerifyToken +func (h *handler) DeleteProductCategory() core.HandlerFunc { + return func(ctx core.Context) { + idStr := ctx.Param("category_id") + id, _ := strconv.ParseInt(idStr, 10, 64) + if ctx.SessionUserInfo().IsSuper != 1 { + ctx.AbortWithError(core.Error(http.StatusBadRequest, code.CreateAdminError, "禁止操作")) + return + } + if err := h.product.DeleteCategory(ctx.RequestContext(), id); err != nil { + ctx.AbortWithError(core.Error(http.StatusBadRequest, code.CreateAdminError, err.Error())) + return + } + ctx.Payload(pcSimpleMessage{Message: "操作成功"}) + } +} + +type listProductCategoriesRequest struct { + Name string `form:"name"` + Status *int32 `form:"status"` + Page int `form:"page"` + PageSize int `form:"page_size"` +} + +type productCategoryListItem struct { + ID int64 `json:"id"` + Name string `json:"name"` + ParentID int64 `json:"parent_id"` + Status int32 `json:"status"` +} +type listProductCategoriesResponse struct { + Page int `json:"page"` + PageSize int `json:"page_size"` + Total int64 `json:"total"` + List []productCategoryListItem `json:"list"` +} + +// ListProductCategories 查看商品分类列表 +// @Summary 查看商品分类列表 +// @Tags 管理端.商品 +// @Accept json +// @Produce json +// @Param name query string false "名称" +// @Param status query int false "状态" +// @Param page query int true "页码" default(1) +// @Param page_size query int true "每页数量" default(20) +// @Success 200 {object} listProductCategoriesResponse +// @Failure 400 {object} code.Failure +// @Router /api/admin/product_categories [get] +// @Security LoginVerifyToken +func (h *handler) ListProductCategories() core.HandlerFunc { + return func(ctx core.Context) { + req := new(listProductCategoriesRequest) + res := new(listProductCategoriesResponse) + if err := ctx.ShouldBindForm(req); err != nil { + ctx.AbortWithError(core.Error(http.StatusBadRequest, code.ParamBindError, validation.Error(err))) + return + } + items, total, err := h.product.ListCategories(ctx.RequestContext(), prodsvc.ListCategoriesInput{Name: req.Name, Status: req.Status, Page: req.Page, PageSize: req.PageSize}) + if err != nil { + ctx.AbortWithError(core.Error(http.StatusBadRequest, code.CreateAdminError, err.Error())) + return + } + res.Page = req.Page + res.PageSize = req.PageSize + res.Total = total + res.List = make([]productCategoryListItem, len(items)) + for i, it := range items { + res.List[i] = productCategoryListItem{ID: it.ID, Name: it.Name, ParentID: it.ParentID, Status: it.Status} + } + ctx.Payload(res) + } +} diff --git a/internal/api/admin/product_create.go b/internal/api/admin/product_create.go new file mode 100644 index 0000000..a889123 --- /dev/null +++ b/internal/api/admin/product_create.go @@ -0,0 +1,188 @@ +package admin + +import ( + "net/http" + "strconv" + + "bindbox-game/internal/code" + "bindbox-game/internal/pkg/core" + "bindbox-game/internal/pkg/validation" + prodsvc "bindbox-game/internal/service/product" +) + +type createProductRequest struct { + Name string `json:"name" binding:"required"` + CategoryID int64 `json:"category_id" binding:"required"` + ImagesJSON string `json:"images_json"` + Price int64 `json:"price" binding:"required"` + Stock int64 `json:"stock" binding:"required"` + Status int32 `json:"status"` +} + +type createProductResponse struct { + ID int64 `json:"id"` + Message string `json:"message"` +} + +// CreateProduct 创建商品 +// @Summary 创建商品 +// @Tags 管理端.商品 +// @Accept json +// @Produce json +// @Param RequestBody body createProductRequest true "请求参数" +// @Success 200 {object} createProductResponse +// @Failure 400 {object} code.Failure +// @Router /api/admin/products [post] +// @Security LoginVerifyToken +func (h *handler) CreateProduct() core.HandlerFunc { + return func(ctx core.Context) { + req := new(createProductRequest) + res := new(createProductResponse) + if err := ctx.ShouldBindJSON(req); err != nil { + ctx.AbortWithError(core.Error(http.StatusBadRequest, code.ParamBindError, validation.Error(err))) + return + } + if ctx.SessionUserInfo().IsSuper != 1 { + ctx.AbortWithError(core.Error(http.StatusBadRequest, code.CreateAdminError, "禁止操作")) + return + } + item, err := h.product.CreateProduct(ctx.RequestContext(), prodsvc.CreateProductInput{Name: req.Name, CategoryID: req.CategoryID, ImagesJSON: req.ImagesJSON, Price: req.Price, Stock: req.Stock, Status: req.Status}) + if err != nil { + ctx.AbortWithError(core.Error(http.StatusBadRequest, code.CreateAdminError, err.Error())) + return + } + res.ID = item.ID + res.Message = "操作成功" + ctx.Payload(res) + } +} + +type modifyProductRequest struct { + Name *string `json:"name"` + CategoryID *int64 `json:"category_id"` + ImagesJSON *string `json:"images_json"` + Price *int64 `json:"price"` + Stock *int64 `json:"stock"` + Status *int32 `json:"status"` +} + +// ModifyProduct 修改商品 +// @Summary 修改商品 +// @Tags 管理端.商品 +// @Accept json +// @Produce json +// @Param product_id path string true "商品ID" +// @Param RequestBody body modifyProductRequest true "请求参数" +// @Success 200 {object} pcSimpleMessage +// @Failure 400 {object} code.Failure +// @Router /api/admin/products/{product_id} [put] +// @Security LoginVerifyToken +func (h *handler) ModifyProduct() core.HandlerFunc { + return func(ctx core.Context) { + req := new(modifyProductRequest) + if err := ctx.ShouldBindJSON(req); err != nil { + ctx.AbortWithError(core.Error(http.StatusBadRequest, code.ParamBindError, validation.Error(err))) + return + } + idStr := ctx.Param("product_id") + id, _ := strconv.ParseInt(idStr, 10, 64) + if ctx.SessionUserInfo().IsSuper != 1 { + ctx.AbortWithError(core.Error(http.StatusBadRequest, code.CreateAdminError, "禁止操作")) + return + } + if err := h.product.ModifyProduct(ctx.RequestContext(), id, prodsvc.ModifyProductInput{Name: req.Name, CategoryID: req.CategoryID, ImagesJSON: req.ImagesJSON, Price: req.Price, Stock: req.Stock, Status: req.Status}); err != nil { + ctx.AbortWithError(core.Error(http.StatusBadRequest, code.CreateAdminError, err.Error())) + return + } + ctx.Payload(pcSimpleMessage{Message: "操作成功"}) + } +} + +// DeleteProduct 删除商品 +// @Summary 删除商品 +// @Tags 管理端.商品 +// @Accept json +// @Produce json +// @Param product_id path string true "商品ID" +// @Success 200 {object} pcSimpleMessage +// @Failure 400 {object} code.Failure +// @Router /api/admin/products/{product_id} [delete] +// @Security LoginVerifyToken +func (h *handler) DeleteProduct() core.HandlerFunc { + return func(ctx core.Context) { + idStr := ctx.Param("product_id") + id, _ := strconv.ParseInt(idStr, 10, 64) + if ctx.SessionUserInfo().IsSuper != 1 { + ctx.AbortWithError(core.Error(http.StatusBadRequest, code.CreateAdminError, "禁止操作")) + return + } + if err := h.product.DeleteProduct(ctx.RequestContext(), id); err != nil { + ctx.AbortWithError(core.Error(http.StatusBadRequest, code.CreateAdminError, err.Error())) + return + } + ctx.Payload(pcSimpleMessage{Message: "操作成功"}) + } +} + +type listProductsRequest struct { + Name string `form:"name"` + CategoryID *int64 `form:"category_id"` + Status *int32 `form:"status"` + Page int `form:"page"` + PageSize int `form:"page_size"` +} + +type productItem struct { + ID int64 `json:"id"` + Name string `json:"name"` + CategoryID int64 `json:"category_id"` + ImagesJSON string `json:"images_json"` + Price int64 `json:"price"` + Stock int64 `json:"stock"` + Sales int64 `json:"sales"` + Status int32 `json:"status"` +} +type listProductsResponse struct { + Page int `json:"page"` + PageSize int `json:"page_size"` + Total int64 `json:"total"` + List []productItem `json:"list"` +} + +// ListProducts 查看商品列表 +// @Summary 查看商品列表 +// @Tags 管理端.商品 +// @Accept json +// @Produce json +// @Param name query string false "名称" +// @Param category_id query int false "分类ID" +// @Param status query int false "状态" +// @Param page query int true "页码" default(1) +// @Param page_size query int true "每页数量" default(20) +// @Success 200 {object} listProductsResponse +// @Failure 400 {object} code.Failure +// @Router /api/admin/products [get] +// @Security LoginVerifyToken +func (h *handler) ListProducts() core.HandlerFunc { + return func(ctx core.Context) { + req := new(listProductsRequest) + res := new(listProductsResponse) + if err := ctx.ShouldBindForm(req); err != nil { + ctx.AbortWithError(core.Error(http.StatusBadRequest, code.ParamBindError, validation.Error(err))) + return + } + items, total, err := h.product.ListProducts(ctx.RequestContext(), prodsvc.ListProductsInput{Name: req.Name, CategoryID: req.CategoryID, Status: req.Status, Page: req.Page, PageSize: req.PageSize}) + if err != nil { + ctx.AbortWithError(core.Error(http.StatusBadRequest, code.CreateAdminError, err.Error())) + return + } + res.Page = req.Page + res.PageSize = req.PageSize + res.Total = total + res.List = make([]productItem, len(items)) + for i, it := range items { + res.List[i] = productItem{ID: it.ID, Name: it.Name, CategoryID: it.CategoryID, ImagesJSON: it.ImagesJSON, Price: it.Price, Stock: it.Stock, Sales: it.Sales, Status: it.Status} + } + ctx.Payload(res) + } +} diff --git a/internal/api/admin/rewards_admin.go b/internal/api/admin/rewards_admin.go new file mode 100644 index 0000000..1738a2a --- /dev/null +++ b/internal/api/admin/rewards_admin.go @@ -0,0 +1,224 @@ +package admin + +import ( + "net/http" + "strconv" + + "bindbox-game/internal/code" + "bindbox-game/internal/pkg/core" + "bindbox-game/internal/pkg/validation" + activitysvc "bindbox-game/internal/service/activity" +) + +type rewardItem struct { + ID int64 `json:"id"` + ProductID int64 `json:"product_id"` + Name string `json:"name" binding:"required"` + Weight int32 `json:"weight" binding:"required"` + Quantity int64 `json:"quantity" binding:"required"` + OriginalQty int64 `json:"original_qty" binding:"required"` + Level int32 `json:"level" binding:"required"` + Sort int32 `json:"sort"` + IsBoss int32 `json:"is_boss"` +} + +type createRewardsRequest struct { + Rewards []rewardItem `json:"rewards" binding:"required"` +} + +type listRewardsResponse struct { + List []rewardItem `json:"list"` +} + +// CreateIssueRewards 创建期数奖品 +// @Summary 创建期数奖品 +// @Description 为指定期数批量创建奖励配置 +// @Tags 管理端.活动 +// @Accept json +// @Produce json +// @Param activity_id path integer true "活动ID" +// @Param issue_id path integer true "期ID" +// @Param RequestBody body createRewardsRequest true "请求参数" +// @Success 200 {object} simpleMessageResponse +// @Failure 400 {object} code.Failure +// @Router /api/admin/activities/{activity_id}/issues/{issue_id}/rewards [post] +// @Security LoginVerifyToken +func (h *handler) CreateIssueRewards() core.HandlerFunc { + return func(ctx core.Context) { + req := new(createRewardsRequest) + res := new(simpleMessageResponse) + + if err := ctx.ShouldBindJSON(req); err != nil { + ctx.AbortWithError(core.Error(http.StatusBadRequest, code.ParamBindError, validation.Error(err))) + return + } + + if ctx.SessionUserInfo().IsSuper != 1 { + ctx.AbortWithError(core.Error(http.StatusBadRequest, code.CreateIssueRewardsError, "禁止操作")) + return + } + + issueID, err := strconv.ParseInt(ctx.Param("issue_id"), 10, 64) + if err != nil { + ctx.AbortWithError(core.Error(http.StatusBadRequest, code.ParamBindError, "未传递期ID")) + return + } + + var rewards []activitysvc.CreateRewardInput + for _, r := range req.Rewards { + rewards = append(rewards, activitysvc.CreateRewardInput{ + ProductID: r.ProductID, + Name: r.Name, + Weight: r.Weight, + Quantity: r.Quantity, + OriginalQty: r.OriginalQty, + Level: r.Level, + Sort: r.Sort, + IsBoss: r.IsBoss, + }) + } + + if err := h.activity.CreateIssueRewards(ctx.RequestContext(), issueID, rewards); err != nil { + ctx.AbortWithError(core.Error(http.StatusBadRequest, code.CreateIssueRewardsError, err.Error())) + return + } + res.Message = "操作成功" + ctx.Payload(res) + } +} + +// ListIssueRewards 查看期数奖品 +// @Summary 查看期数奖品 +// @Description 查看指定期数的奖励配置列表 +// @Tags 管理端.活动 +// @Accept json +// @Produce json +// @Param activity_id path integer true "活动ID" +// @Param issue_id path integer true "期ID" +// @Success 200 {object} listRewardsResponse +// @Failure 400 {object} code.Failure +// @Router /api/admin/activities/{activity_id}/issues/{issue_id}/rewards [get] +// @Security LoginVerifyToken +func (h *handler) ListIssueRewards() core.HandlerFunc { + return func(ctx core.Context) { + issueID, err := strconv.ParseInt(ctx.Param("issue_id"), 10, 64) + if err != nil { + ctx.AbortWithError(core.Error(http.StatusBadRequest, code.ParamBindError, "未传递期ID")) + return + } + items, err := h.activity.ListIssueRewards(ctx.RequestContext(), issueID) + if err != nil { + ctx.AbortWithError(core.Error(http.StatusBadRequest, code.ListIssueRewardsError, err.Error())) + return + } + res := new(listRewardsResponse) + res.List = make([]rewardItem, len(items)) + for i, v := range items { + res.List[i] = rewardItem{ + ID: v.ID, + ProductID: v.ProductID, + Name: v.Name, + Weight: v.Weight, + Quantity: v.Quantity, + OriginalQty: v.OriginalQty, + Level: v.Level, + Sort: v.Sort, + IsBoss: v.IsBoss, + } + } + ctx.Payload(res) + } +} + +type modifyRewardRequest struct { + ProductID *int64 `json:"product_id"` + Name string `json:"name"` + Weight *int32 `json:"weight"` + Quantity *int64 `json:"quantity"` + OriginalQty *int64 `json:"original_qty"` + Level *int32 `json:"level"` + Sort *int32 `json:"sort"` + IsBoss *int32 `json:"is_boss"` +} + +// ModifyIssueReward 更新期数奖励 +// @Summary 更新期数奖励 +// @Tags 管理端.活动 +// @Accept json +// @Produce json +// @Param activity_id path integer true "活动ID" +// @Param issue_id path integer true "期ID" +// @Param reward_id path integer true "奖励ID" +// @Param RequestBody body modifyRewardRequest true "请求参数" +// @Success 200 {object} simpleMessageResponse +// @Failure 400 {object} code.Failure +// @Router /api/admin/activities/{activity_id}/issues/{issue_id}/rewards/{reward_id} [put] +// @Security LoginVerifyToken +func (h *handler) ModifyIssueReward() core.HandlerFunc { + return func(ctx core.Context) { + req := new(modifyRewardRequest) + res := new(simpleMessageResponse) + if err := ctx.ShouldBindJSON(req); err != nil { + ctx.AbortWithError(core.Error(http.StatusBadRequest, code.ParamBindError, validation.Error(err))) + return + } + if ctx.SessionUserInfo().IsSuper != 1 { + ctx.AbortWithError(core.Error(http.StatusBadRequest, code.CreateIssueRewardsError, "禁止操作")) + return + } + rewardID, err := strconv.ParseInt(ctx.Param("reward_id"), 10, 64) + if err != nil { + ctx.AbortWithError(core.Error(http.StatusBadRequest, code.ParamBindError, "未传递奖励ID")) + return + } + in := activitysvc.ModifyRewardInput{ + ProductID: req.ProductID, + Name: req.Name, + Weight: req.Weight, + Quantity: req.Quantity, + OriginalQty: req.OriginalQty, + Level: req.Level, + Sort: req.Sort, + IsBoss: req.IsBoss, + } + if err := h.activity.ModifyIssueReward(ctx.RequestContext(), rewardID, in); err != nil { + ctx.AbortWithError(core.Error(http.StatusBadRequest, code.CreateIssueRewardsError, err.Error())) + return + } + res.Message = "操作成功" + ctx.Payload(res) + } +} + +// DeleteIssueReward 删除期数奖励 +// @Summary 删除期数奖励 +// @Tags 管理端.活动 +// @Accept json +// @Produce json +// @Param activity_id path integer true "活动ID" +// @Param issue_id path integer true "期ID" +// @Param reward_id path integer true "奖励ID" +// @Success 200 {object} simpleMessageResponse +// @Failure 400 {object} code.Failure +// @Router /api/admin/activities/{activity_id}/issues/{issue_id}/rewards/{reward_id} [delete] +// @Security LoginVerifyToken +func (h *handler) DeleteIssueReward() core.HandlerFunc { + return func(ctx core.Context) { + res := new(simpleMessageResponse) + if ctx.SessionUserInfo().IsSuper != 1 { + ctx.AbortWithError(core.Error(http.StatusBadRequest, code.CreateIssueRewardsError, "禁止操作")) + return + } + rewardID, err := strconv.ParseInt(ctx.Param("reward_id"), 10, 64) + if err != nil { + ctx.AbortWithError(core.Error(http.StatusBadRequest, code.ParamBindError, "未传递奖励ID")) + return + } + if err := h.activity.DeleteIssueReward(ctx.RequestContext(), rewardID); err != nil { + ctx.AbortWithError(core.Error(http.StatusBadRequest, code.CreateIssueRewardsError, err.Error())) + return + } + res.Message = "操作成功" + ctx.Payload(res) + } +} diff --git a/internal/api/admin/system_coupons.go b/internal/api/admin/system_coupons.go new file mode 100644 index 0000000..3e3f4fe --- /dev/null +++ b/internal/api/admin/system_coupons.go @@ -0,0 +1,265 @@ +package admin + +import ( + "net/http" + "strconv" + "time" + + "bindbox-game/internal/code" + "bindbox-game/internal/pkg/core" + "bindbox-game/internal/pkg/validation" + "bindbox-game/internal/repository/mysql/model" +) + +type createSystemCouponRequest struct { + Name string `json:"name" binding:"required"` + Status *int32 `json:"status"` + CouponType *int32 `json:"coupon_type"` + DiscountType *int32 `json:"discount_type"` + DiscountValue *int64 `json:"discount_value"` + MinAmount *int64 `json:"min_amount"` + ValidDays *int `json:"valid_days"` + TotalQuantity *int64 `json:"total_quantity"` +} + +type createSystemCouponResponse struct { + ID int64 `json:"id"` + Message string `json:"message"` +} + +func (h *handler) CreateSystemCoupon() core.HandlerFunc { + return func(ctx core.Context) { + req := new(createSystemCouponRequest) + res := new(createSystemCouponResponse) + if err := ctx.ShouldBindJSON(req); err != nil { + ctx.AbortWithError(core.Error(http.StatusBadRequest, code.ParamBindError, validation.Error(err))) + return + } + if ctx.SessionUserInfo().IsSuper != 1 { + ctx.AbortWithError(core.Error(http.StatusBadRequest, code.CreateAdminError, "禁止操作")) + return + } + now := time.Now() + m := &model.SystemCoupons{ + Name: req.Name, + ScopeType: getInt32OrDefault(req.CouponType, 1), + DiscountType: getInt32OrDefault(req.DiscountType, 1), + DiscountValue: getInt64OrDefault(req.DiscountValue, 0), + MinSpend: getInt64OrDefault(req.MinAmount, 0), + Status: getInt32OrDefault(req.Status, 1), + } + if req.ValidDays != nil && *req.ValidDays > 0 { + m.ValidStart = now + m.ValidEnd = now.Add(time.Duration(*req.ValidDays) * 24 * time.Hour) + } + if err := h.writeDB.SystemCoupons.WithContext(ctx.RequestContext()).Create(m); err != nil { + ctx.AbortWithError(core.Error(http.StatusBadRequest, code.CreateAdminError, err.Error())) + return + } + if req.TotalQuantity != nil { + if _, err := h.writeDB.SystemCoupons.WithContext(ctx.RequestContext()).Where(h.writeDB.SystemCoupons.ID.Eq(m.ID)).Updates(map[string]any{"total_quantity": *req.TotalQuantity}); err != nil { + ctx.AbortWithError(core.Error(http.StatusBadRequest, code.CreateAdminError, err.Error())) + return + } + } + res.ID = m.ID + res.Message = "操作成功" + ctx.Payload(res) + } +} + +type modifySystemCouponRequest struct { + Name *string `json:"name"` + Status *int32 `json:"status"` + CouponType *int32 `json:"coupon_type"` + DiscountType *int32 `json:"discount_type"` + DiscountValue *int64 `json:"discount_value"` + MinAmount *int64 `json:"min_amount"` + ValidDays *int `json:"valid_days"` + TotalQuantity *int64 `json:"total_quantity"` +} + +func (h *handler) ModifySystemCoupon() core.HandlerFunc { + return func(ctx core.Context) { + req := new(modifySystemCouponRequest) + if err := ctx.ShouldBindJSON(req); err != nil { + ctx.AbortWithError(core.Error(http.StatusBadRequest, code.ParamBindError, validation.Error(err))) + return + } + idStr := ctx.Param("coupon_id") + id, _ := strconv.ParseInt(idStr, 10, 64) + if ctx.SessionUserInfo().IsSuper != 1 { + ctx.AbortWithError(core.Error(http.StatusBadRequest, code.CreateAdminError, "禁止操作")) + return + } + set := map[string]any{} + if req.Name != nil { + set["name"] = *req.Name + } + if req.Status != nil { + set["status"] = *req.Status + } + if req.CouponType != nil { + set["scope_type"] = *req.CouponType + } + if req.DiscountType != nil { + set["discount_type"] = *req.DiscountType + } + if req.DiscountValue != nil { + set["discount_value"] = *req.DiscountValue + } + if req.MinAmount != nil { + set["min_spend"] = *req.MinAmount + } + if req.ValidDays != nil && *req.ValidDays > 0 { + now := time.Now() + set["valid_start"] = now + set["valid_end"] = now.Add(time.Duration(*req.ValidDays) * 24 * time.Hour) + } + if req.TotalQuantity != nil { + set["total_quantity"] = *req.TotalQuantity + } + if len(set) == 0 { + ctx.Payload(pcSimpleMessage{Message: "操作成功"}) + return + } + if _, err := h.writeDB.SystemCoupons.WithContext(ctx.RequestContext()).Where(h.writeDB.SystemCoupons.ID.Eq(id)).Updates(set); err != nil { + ctx.AbortWithError(core.Error(http.StatusBadRequest, code.CreateAdminError, err.Error())) + return + } + ctx.Payload(pcSimpleMessage{Message: "操作成功"}) + } +} + +func (h *handler) DeleteSystemCoupon() core.HandlerFunc { + return func(ctx core.Context) { + idStr := ctx.Param("coupon_id") + id, _ := strconv.ParseInt(idStr, 10, 64) + if ctx.SessionUserInfo().IsSuper != 1 { + ctx.AbortWithError(core.Error(http.StatusBadRequest, code.CreateAdminError, "禁止操作")) + return + } + if _, err := h.writeDB.SystemCoupons.WithContext(ctx.RequestContext()).Where(h.writeDB.SystemCoupons.ID.Eq(id)).Delete(); err != nil { + ctx.AbortWithError(core.Error(http.StatusBadRequest, code.CreateAdminError, err.Error())) + return + } + ctx.Payload(pcSimpleMessage{Message: "操作成功"}) + } +} + +type listSystemCouponsRequest struct { + Name string `form:"name"` + Status *int32 `form:"status"` + Page int `form:"page"` + PageSize int `form:"page_size"` +} + +type systemCouponItem struct { + ID int64 `json:"id"` + Name string `json:"name"` + Status int32 `json:"status"` + CouponType int32 `json:"coupon_type"` + DiscountType int32 `json:"discount_type"` + DiscountValue int64 `json:"discount_value"` + MinAmount int64 `json:"min_amount"` + MaxDiscount int64 `json:"max_discount"` + ValidDays int `json:"valid_days"` + TotalQuantity int64 `json:"total_quantity"` + UsedQuantity int64 `json:"used_quantity"` + CreatedAt string `json:"created_at"` +} + +type listSystemCouponsResponse struct { + Page int `json:"page"` + PageSize int `json:"page_size"` + Total int64 `json:"total"` + List []systemCouponItem `json:"list"` +} + +func (h *handler) ListSystemCoupons() core.HandlerFunc { + return func(ctx core.Context) { + req := new(listSystemCouponsRequest) + res := new(listSystemCouponsResponse) + if err := ctx.ShouldBindForm(req); err != nil { + ctx.AbortWithError(core.Error(http.StatusBadRequest, code.ParamBindError, validation.Error(err))) + return + } + if req.Page <= 0 { + req.Page = 1 + } + if req.PageSize <= 0 { + req.PageSize = 20 + } + q := h.readDB.SystemCoupons.WithContext(ctx.RequestContext()).ReadDB() + if req.Name != "" { + q = q.Where(h.readDB.SystemCoupons.Name.Like("%" + req.Name + "%")) + } + if req.Status != nil { + q = q.Where(h.readDB.SystemCoupons.Status.Eq(*req.Status)) + } + total, err := q.Count() + if err != nil { + ctx.AbortWithError(core.Error(http.StatusBadRequest, code.ServerError, err.Error())) + return + } + type dbRow struct { + ID int64 + Name string + Status int32 + ScopeType int32 + DiscountType int32 + DiscountValue int64 + MinSpend int64 + ValidStart time.Time + ValidEnd time.Time + CreatedAt time.Time + TotalQuantity int64 + } + var rows []dbRow + if err := q.Order(h.readDB.SystemCoupons.ID.Desc()).Limit(req.PageSize).Offset((req.Page - 1) * req.PageSize).Scan(&rows); err != nil { + ctx.AbortWithError(core.Error(http.StatusBadRequest, code.ServerError, err.Error())) + return + } + res.Page = req.Page + res.PageSize = req.PageSize + res.Total = total + res.List = make([]systemCouponItem, len(rows)) + for i, v := range rows { + validDays := 0 + if !v.ValidStart.IsZero() && !v.ValidEnd.IsZero() { + diff := v.ValidEnd.Sub(v.ValidStart) + validDays = int(diff.Hours() / 24) + } + // 统计已发放数量(用户持券数) + usedCnt, _ := h.readDB.UserCoupons.WithContext(ctx.RequestContext()).Where(h.readDB.UserCoupons.CouponID.Eq(v.ID)).Count() + res.List[i] = systemCouponItem{ + ID: v.ID, + Name: v.Name, + Status: v.Status, + CouponType: v.ScopeType, + DiscountType: v.DiscountType, + DiscountValue: v.DiscountValue, + MinAmount: v.MinSpend, + MaxDiscount: 0, + ValidDays: validDays, + TotalQuantity: v.TotalQuantity, + UsedQuantity: usedCnt, + CreatedAt: v.CreatedAt.Format("2006-01-02 15:04:05"), + } + } + ctx.Payload(res) + } +} + +func getInt32OrDefault(v *int32, d int32) int32 { + if v != nil { + return *v + } + return d +} +func getInt64OrDefault(v *int64, d int64) int64 { + if v != nil { + return *v + } + return d +} diff --git a/internal/api/admin/system_menu.go b/internal/api/admin/system_menu.go new file mode 100644 index 0000000..c8868e8 --- /dev/null +++ b/internal/api/admin/system_menu.go @@ -0,0 +1,272 @@ +package admin + +import ( + "net/http" + "strconv" + + "bindbox-game/internal/pkg/core" + "bindbox-game/internal/repository/mysql/model" +) + +type simpleRoute struct { + Path string `json:"path"` + Name string `json:"name"` + Component string `json:"component"` + Meta map[string]any `json:"meta"` + Children []simpleRoute `json:"children,omitempty"` +} + +// ListSimpleMenus 返回前端所需的简单路由结构 +// @Router /api/v3/system/menus/simple [get] +func (h *handler) ListSimpleMenus() core.HandlerFunc { + return func(ctx core.Context) { + // 读取启用的菜单,构造成前端路由结构 + rows, err := h.readDB.Menus.Where(h.readDB.Menus.Status.Is(true)).Order(h.readDB.Menus.Sort).Find() + if err != nil { + ctx.AbortWithError(core.Error(http.StatusBadRequest, 10021, err.Error())) + return + } + // 构建 parent_id => children + nodeMap := make(map[uint64]*simpleRoute) + var roots []simpleRoute + for _, m := range rows { + r := &simpleRoute{ + Path: m.Path, + Name: m.Name, + Component: m.Component, + Meta: map[string]any{ + "title": m.Name, + "keepAlive": m.KeepAlive, + "isHide": m.IsHide, + "isHideTab": m.IsHideTab, + "icon": m.Icon, + }, + } + nodeMap[uint64(m.ID)] = r + } + // 第二遍挂载到父节点 + for _, m := range rows { + id := uint64(m.ID) + pid := uint64(m.ParentID) + if pid == 0 { + roots = append(roots, *nodeMap[id]) + continue + } + parent := nodeMap[pid] + if parent != nil { + parent.Children = append(parent.Children, *nodeMap[id]) + } else { + // 无父节点,作为根返回 + roots = append(roots, *nodeMap[id]) + } + } + ctx.Payload(roots) + } +} + +type createMenuRequest struct { + ParentID uint64 `json:"parent_id"` + Path string `json:"path"` + Name string `json:"name"` + Component string `json:"component"` + Icon string `json:"icon"` + Sort int `json:"sort"` + Status bool `json:"status"` + KeepAlive bool `json:"keep_alive"` + IsHide bool `json:"is_hide"` + IsHideTab bool `json:"is_hide_tab"` +} + +func (h *handler) CreateMenu() core.HandlerFunc { + return func(ctx core.Context) { + req := new(createMenuRequest) + if err := ctx.ShouldBindJSON(req); err != nil { + ctx.AbortWithError(core.Error(http.StatusBadRequest, 10031, err.Error())) + return + } + err := h.writeDB.Menus.WithContext(ctx.RequestContext()).Create(&model.Menus{ParentID: int64(req.ParentID), Path: req.Path, Name: req.Name, Component: req.Component, Icon: req.Icon, Sort: int32(req.Sort), Status: req.Status, KeepAlive: req.KeepAlive, IsHide: req.IsHide, IsHideTab: req.IsHideTab}) + if err != nil { + ctx.AbortWithError(core.Error(http.StatusBadRequest, 10032, err.Error())) + return + } + ctx.Payload(map[string]string{"message": "ok"}) + } +} + +type modifyMenuRequest struct { + ParentID *uint64 `json:"parent_id"` + Path *string `json:"path"` + Name *string `json:"name"` + Component *string `json:"component"` + Icon *string `json:"icon"` + Sort *int `json:"sort"` + Status *bool `json:"status"` + KeepAlive *bool `json:"keep_alive"` + IsHide *bool `json:"is_hide"` + IsHideTab *bool `json:"is_hide_tab"` +} + +func (h *handler) ModifyMenu() core.HandlerFunc { + return func(ctx core.Context) { + idStr := ctx.Param("menu_id") + id, _ := strconv.ParseInt(idStr, 10, 64) + req := new(modifyMenuRequest) + if err := ctx.ShouldBindJSON(req); err != nil { + ctx.AbortWithError(core.Error(http.StatusBadRequest, 10033, err.Error())) + return + } + set := map[string]any{} + if req.ParentID != nil { + set["parent_id"] = int64(*req.ParentID) + } + if req.Path != nil { + set["path"] = *req.Path + } + if req.Name != nil { + set["name"] = *req.Name + } + if req.Component != nil { + set["component"] = *req.Component + } + if req.Icon != nil { + set["icon"] = *req.Icon + } + if req.Sort != nil { + set["sort"] = *req.Sort + } + if req.Status != nil { + set["status"] = *req.Status + } + if req.KeepAlive != nil { + set["keep_alive"] = *req.KeepAlive + } + if req.IsHide != nil { + set["is_hide"] = *req.IsHide + } + if req.IsHideTab != nil { + set["is_hide_tab"] = *req.IsHideTab + } + if _, err := h.writeDB.Menus.WithContext(ctx.RequestContext()).Where(h.writeDB.Menus.ID.Eq(id)).Updates(set); err != nil { + ctx.AbortWithError(core.Error(http.StatusBadRequest, 10034, err.Error())) + return + } + ctx.Payload(map[string]string{"message": "ok"}) + } +} + +func (h *handler) DeleteMenu() core.HandlerFunc { + return func(ctx core.Context) { + idStr := ctx.Param("menu_id") + id, _ := strconv.ParseInt(idStr, 10, 64) + if _, err := h.writeDB.Menus.WithContext(ctx.RequestContext()).Where(h.writeDB.Menus.ID.Eq(id)).Delete(); err != nil { + ctx.AbortWithError(core.Error(http.StatusBadRequest, 10035, err.Error())) + return + } + ctx.Payload(map[string]string{"message": "ok"}) + } +} + +func (h *handler) ListMenuActions() core.HandlerFunc { + return func(ctx core.Context) { + idStr := ctx.Param("menu_id") + id, _ := strconv.ParseInt(idStr, 10, 64) + rows, err := h.readDB.MenuActions.WithContext(ctx.RequestContext()).Where(h.readDB.MenuActions.MenuID.Eq(id)).Find() + if err != nil { + ctx.AbortWithError(core.Error(http.StatusBadRequest, 10036, err.Error())) + return + } + ctx.Payload(rows) + } +} + +type createActionsRequest struct { + Actions []struct { + ActionMark string `json:"action_mark"` + ActionName string `json:"action_name"` + Status bool `json:"status"` + } `json:"actions"` +} + +func (h *handler) CreateMenuActions() core.HandlerFunc { + return func(ctx core.Context) { + idStr := ctx.Param("menu_id") + id, _ := strconv.ParseInt(idStr, 10, 64) + req := new(createActionsRequest) + if err := ctx.ShouldBindJSON(req); err != nil { + ctx.AbortWithError(core.Error(http.StatusBadRequest, 10037, err.Error())) + return + } + tx := h.writeDB.MenuActions.WithContext(ctx.RequestContext()) + for _, a := range req.Actions { + err := tx.Create(&model.MenuActions{MenuID: id, ActionMark: a.ActionMark, ActionName: a.ActionName, Status: a.Status}) + if err != nil { + ctx.AbortWithError(core.Error(http.StatusBadRequest, 10038, err.Error())) + return + } + } + ctx.Payload(map[string]string{"message": "ok"}) + } +} + +func (h *handler) DeleteMenuAction() core.HandlerFunc { + return func(ctx core.Context) { + idStr := ctx.Param("menu_id") + id, _ := strconv.ParseInt(idStr, 10, 64) + aidStr := ctx.Param("action_id") + aid, _ := strconv.ParseInt(aidStr, 10, 64) + if _, err := h.writeDB.MenuActions.WithContext(ctx.RequestContext()).Where(h.writeDB.MenuActions.ID.Eq(aid), h.writeDB.MenuActions.MenuID.Eq(id)).Delete(); err != nil { + ctx.AbortWithError(core.Error(http.StatusBadRequest, 10039, err.Error())) + return + } + ctx.Payload(map[string]string{"message": "ok"}) + } +} + +type assignMenusRequest struct { + MenuIDs []int64 `json:"menu_ids"` +} +type assignActionsRequest struct { + ActionIDs []int64 `json:"action_ids"` +} + +func (h *handler) AssignRoleMenus() core.HandlerFunc { + return func(ctx core.Context) { + ridStr := ctx.Param("role_id") + rid, _ := strconv.ParseInt(ridStr, 10, 64) + req := new(assignMenusRequest) + if err := ctx.ShouldBindJSON(req); err != nil { + ctx.AbortWithError(core.Error(http.StatusBadRequest, 10041, err.Error())) + return + } + tx := h.writeDB.RoleMenus.WithContext(ctx.RequestContext()) + for _, mid := range req.MenuIDs { + err := tx.Create(&model.RoleMenus{RoleID: rid, MenuID: mid}) + if err != nil { + ctx.AbortWithError(core.Error(http.StatusBadRequest, 10042, err.Error())) + return + } + } + ctx.Payload(map[string]string{"message": "ok"}) + } +} + +func (h *handler) AssignRoleActions() core.HandlerFunc { + return func(ctx core.Context) { + ridStr := ctx.Param("role_id") + rid, _ := strconv.ParseInt(ridStr, 10, 64) + req := new(assignActionsRequest) + if err := ctx.ShouldBindJSON(req); err != nil { + ctx.AbortWithError(core.Error(http.StatusBadRequest, 10043, err.Error())) + return + } + tx := h.writeDB.RoleActions.WithContext(ctx.RequestContext()) + for _, aid := range req.ActionIDs { + err := tx.Create(&model.RoleActions{RoleID: rid, ActionID: aid}) + if err != nil { + ctx.AbortWithError(core.Error(http.StatusBadRequest, 10044, err.Error())) + return + } + } + ctx.Payload(map[string]string{"message": "ok"}) + } +} diff --git a/internal/api/admin/system_role.go b/internal/api/admin/system_role.go new file mode 100644 index 0000000..76f09ad --- /dev/null +++ b/internal/api/admin/system_role.go @@ -0,0 +1,227 @@ +package admin + +import ( + "net/http" + "strconv" + + "bindbox-game/internal/pkg/core" + "bindbox-game/internal/pkg/validation" + "bindbox-game/internal/repository/mysql/model" +) + +type roleListRequest struct { + RoleId int64 `form:"roleId"` + RoleName string `form:"roleName"` + RoleCode string `form:"roleCode"` + Description string `form:"description"` + Enabled *bool `form:"enabled"` + Current int `form:"current"` + Size int `form:"size"` +} + +type roleItem struct { + RoleId int64 `json:"roleId"` + RoleName string `json:"roleName"` + RoleCode string `json:"roleCode"` + Description string `json:"description"` + Enabled bool `json:"enabled"` + CreateTime string `json:"createTime"` +} + +type roleListResponse struct { + Records []roleItem `json:"records"` + Current int `json:"current"` + Size int `json:"size"` + Total int64 `json:"total"` +} + +// ListRoles 角色列表 +// @Summary 角色列表 +// @Tags 管理端.系统 +// @Accept json +// @Produce json +// @Param current query int true "页码" default(1) +// @Param size query int true "每页数量" default(20) +// @Param roleName query string false "角色名称" +// @Param roleCode query string false "角色编码" +// @Param enabled query bool false "是否启用" +// @Success 200 {object} roleListResponse +// @Router /api/role/list [get] +// @Security LoginVerifyToken +func (h *handler) ListRoles() core.HandlerFunc { + return func(ctx core.Context) { + req := new(roleListRequest) + res := new(roleListResponse) + if err := ctx.ShouldBindForm(req); err != nil { + ctx.AbortWithError(core.Error(http.StatusBadRequest, 10011, validation.Error(err))) + return + } + if req.Current <= 0 { + req.Current = 1 + } + if req.Size <= 0 { + req.Size = 20 + } + q := h.readDB.Roles.WithContext(ctx.RequestContext()).ReadDB() + if req.RoleName != "" { + q = q.Where(h.readDB.Roles.RoleName.Like("%" + req.RoleName + "%")) + } + if req.RoleCode != "" { + q = q.Where(h.readDB.Roles.RoleCode.Like("%" + req.RoleCode + "%")) + } + if req.Enabled != nil { + q = q.Where(h.readDB.Roles.Enabled.Is(*req.Enabled)) + } + total, err := q.Count() + if err != nil { + ctx.AbortWithError(core.Error(http.StatusBadRequest, 10012, err.Error())) + return + } + rows, err := q.Offset((req.Current - 1) * req.Size).Limit(req.Size).Find() + if err != nil { + ctx.AbortWithError(core.Error(http.StatusBadRequest, 10013, err.Error())) + return + } + res.Records = make([]roleItem, len(rows)) + for i, r := range rows { + res.Records[i] = roleItem{ + RoleId: r.ID, + RoleName: r.RoleName, + RoleCode: r.RoleCode, + Description: r.Description, + Enabled: r.Enabled, + CreateTime: r.CreatedAt.Format("2006-01-02 15:04:05"), + } + } + res.Current = req.Current + res.Size = req.Size + res.Total = total + ctx.Payload(res) + } +} + +type createRoleRequest struct { + RoleName string `json:"roleName" binding:"required"` + RoleCode string `json:"roleCode" binding:"required"` + Description string `json:"description"` + Enabled bool `json:"enabled"` +} + +func (h *handler) CreateRole() core.HandlerFunc { + return func(ctx core.Context) { + req := new(createRoleRequest) + if err := ctx.ShouldBindJSON(req); err != nil { + ctx.AbortWithError(core.Error(http.StatusBadRequest, 10014, validation.Error(err))) + return + } + err := h.writeDB.Roles.WithContext(ctx.RequestContext()).Create(&model.Roles{RoleName: req.RoleName, RoleCode: req.RoleCode, Description: req.Description, Enabled: req.Enabled}) + if err != nil { + ctx.AbortWithError(core.Error(http.StatusBadRequest, 10015, err.Error())) + return + } + ctx.Payload(map[string]string{"message": "ok"}) + } +} + +type modifyRoleRequest struct { + RoleName *string `json:"roleName"` + Description *string `json:"description"` + Enabled *bool `json:"enabled"` +} + +func (h *handler) ModifyRole() core.HandlerFunc { + return func(ctx core.Context) { + req := new(modifyRoleRequest) + if err := ctx.ShouldBindJSON(req); err != nil { + ctx.AbortWithError(core.Error(http.StatusBadRequest, 10016, validation.Error(err))) + return + } + idStr := ctx.Param("role_id") + id, _ := strconv.ParseInt(idStr, 10, 64) + updater := h.writeDB.Roles.WithContext(ctx.RequestContext()).Where(h.writeDB.Roles.ID.Eq(id)) + set := map[string]any{} + if req.RoleName != nil { + set["role_name"] = *req.RoleName + } + if req.Description != nil { + set["description"] = *req.Description + } + if req.Enabled != nil { + set["enabled"] = *req.Enabled + } + if len(set) == 0 { + ctx.Payload(map[string]string{"message": "ok"}) + return + } + if _, err := updater.Updates(set); err != nil { + ctx.AbortWithError(core.Error(http.StatusBadRequest, 10017, err.Error())) + return + } + ctx.Payload(map[string]string{"message": "ok"}) + } +} + +func (h *handler) DeleteRole() core.HandlerFunc { + return func(ctx core.Context) { + idStr := ctx.Param("role_id") + id, _ := strconv.ParseInt(idStr, 10, 64) + if _, err := h.writeDB.Roles.WithContext(ctx.RequestContext()).Where(h.writeDB.Roles.ID.Eq(id)).Delete(); err != nil { + ctx.AbortWithError(core.Error(http.StatusBadRequest, 10018, err.Error())) + return + } + ctx.Payload(map[string]string{"message": "ok"}) + } +} + +type assignUsersRequest struct { + AdminIDs []int64 `json:"admin_ids" binding:"required"` +} + +func (h *handler) AssignRoleUsers() core.HandlerFunc { + return func(ctx core.Context) { + idStr := ctx.Param("role_id") + id, _ := strconv.ParseInt(idStr, 10, 64) + req := new(assignUsersRequest) + if err := ctx.ShouldBindJSON(req); err != nil { + ctx.AbortWithError(core.Error(http.StatusBadRequest, 10019, validation.Error(err))) + return + } + tx := h.writeDB.RoleUsers.WithContext(ctx.RequestContext()) + for _, uid := range req.AdminIDs { + err := tx.Create(&model.RoleUsers{RoleID: id, AdminID: int32(uid)}) + if err != nil { + ctx.AbortWithError(core.Error(http.StatusBadRequest, 10020, err.Error())) + return + } + } + ctx.Payload(map[string]string{"message": "ok"}) + } +} + +func (h *handler) ListRoleUsers() core.HandlerFunc { + return func(ctx core.Context) { + idStr := ctx.Param("role_id") + id, _ := strconv.ParseInt(idStr, 10, 64) + rows, err := h.readDB.RoleUsers.WithContext(ctx.RequestContext()).Where(h.readDB.RoleUsers.RoleID.Eq(id)).Find() + if err != nil { + ctx.AbortWithError(core.Error(http.StatusBadRequest, 10022, err.Error())) + return + } + ctx.Payload(rows) + } +} + +func (h *handler) RemoveRoleUser() core.HandlerFunc { + return func(ctx core.Context) { + roleIDStr := ctx.Param("role_id") + adminIDStr := ctx.Param("admin_id") + roleID, _ := strconv.ParseInt(roleIDStr, 10, 64) + adminID, _ := strconv.ParseInt(adminIDStr, 10, 64) + _, err := h.writeDB.RoleUsers.WithContext(ctx.RequestContext()).Where(h.writeDB.RoleUsers.RoleID.Eq(roleID), h.writeDB.RoleUsers.AdminID.Eq(int32(adminID))).Delete() + if err != nil { + ctx.AbortWithError(core.Error(http.StatusBadRequest, 10023, err.Error())) + return + } + ctx.Payload(map[string]string{"message": "ok"}) + } +} diff --git a/internal/api/admin/system_user.go b/internal/api/admin/system_user.go new file mode 100644 index 0000000..168d127 --- /dev/null +++ b/internal/api/admin/system_user.go @@ -0,0 +1,138 @@ +package admin + +import ( + "net/http" + "time" + + "bindbox-game/internal/pkg/core" + "bindbox-game/internal/pkg/validation" +) + +type userListRequest struct { + UserName string `form:"userName"` + UserGender string `form:"userGender"` + UserPhone string `form:"userPhone"` + UserEmail string `form:"userEmail"` + Status string `form:"status"` + Current int `form:"current"` + Size int `form:"size"` +} + +type userListItem struct { + ID int32 `json:"id"` + Avatar string `json:"avatar"` + Status string `json:"status"` + UserName string `json:"userName"` + UserGender string `json:"userGender"` + NickName string `json:"nickName"` + UserPhone string `json:"userPhone"` + UserEmail string `json:"userEmail"` + UserRoles []string `json:"userRoles"` + CreateBy string `json:"createBy"` + CreateTime string `json:"createTime"` + UpdateBy string `json:"updateBy"` + UpdateTime string `json:"updateTime"` +} + +type userListResponse struct { + Records []userListItem `json:"records"` + Current int `json:"current"` + Size int `json:"size"` + Total int64 `json:"total"` +} + +// ListUsers 系统用户列表(映射到 Admin 表) +// @Summary 系统用户列表 +// @Description 返回系统用户分页数据 +// @Tags 管理端.系统 +// @Accept json +// @Produce json +// @Param current query int true "页码" default(1) +// @Param size query int true "每页数量" default(20) +// @Param userName query string false "用户名" +// @Param userEmail query string false "邮箱" +// @Param userPhone query string false "手机号" +// @Param status query string false "状态" +// @Success 200 {object} userListResponse +// @Router /api/user/list [get] +// @Security LoginVerifyToken +func (h *handler) ListUsers() core.HandlerFunc { + return func(ctx core.Context) { + req := new(userListRequest) + res := new(userListResponse) + if err := ctx.ShouldBindForm(req); err != nil { + ctx.AbortWithError(core.Error(http.StatusBadRequest, 10001, validation.Error(err))) + return + } + if req.Current <= 0 { + req.Current = 1 + } + if req.Size <= 0 { + req.Size = 20 + } + + q := h.readDB.Admin.WithContext(ctx.RequestContext()).ReadDB() + if req.UserName != "" { + q = q.Where(h.readDB.Admin.Username.Like("%" + req.UserName + "%")) + } + if req.UserEmail != "" { + q = q.Where(h.readDB.Admin.Nickname.Like("%" + req.UserEmail + "%")) + } + if req.UserPhone != "" { + q = q.Where(h.readDB.Admin.Mobile.Like("%" + req.UserPhone + "%")) + } + + total, err := q.Count() + if err != nil { + ctx.AbortWithError(core.Error(http.StatusBadRequest, 10002, err.Error())) + return + } + + admins, err := q.Offset((req.Current - 1) * req.Size).Limit(req.Size).Find() + if err != nil { + ctx.AbortWithError(core.Error(http.StatusBadRequest, 10003, err.Error())) + return + } + + res.Records = make([]userListItem, len(admins)) + for i, a := range admins { + res.Records[i] = userListItem{ + ID: a.ID, + Avatar: a.Avatar, + Status: mapLoginStatus(a.LoginStatus), + UserName: a.Username, + UserGender: "未知", + NickName: a.Nickname, + UserPhone: a.Mobile, + UserEmail: "", + UserRoles: rolesFromAdmin(a.IsSuper), + CreateBy: a.CreatedUser, + CreateTime: a.CreatedAt.Format(time.RFC3339), + UpdateBy: a.UpdatedUser, + UpdateTime: a.UpdatedAt.Format(time.RFC3339), + } + } + res.Current = req.Current + res.Size = req.Size + res.Total = total + ctx.Payload(res) + } +} + +func mapLoginStatus(s int32) string { + switch s { + case 1: + return "1" + case 0: + return "4" + default: + return "2" + } +} + +func rolesFromAdmin(isSuper int32) []string { + if isSuper == 1 { + return []string{"R_SUPER"} + } + return []string{"R_ADMIN"} +} diff --git a/internal/api/admin/users_admin.go b/internal/api/admin/users_admin.go new file mode 100644 index 0000000..8682eee --- /dev/null +++ b/internal/api/admin/users_admin.go @@ -0,0 +1,536 @@ +package admin + +import ( + "net/http" + "strconv" + "time" + + "bindbox-game/internal/code" + "bindbox-game/internal/pkg/core" + "bindbox-game/internal/pkg/validation" + "bindbox-game/internal/repository/mysql/model" + "bindbox-game/internal/service/user" +) + +type listUsersRequest struct { + Page int `form:"page"` + PageSize int `form:"page_size"` +} +type listUsersResponse struct { + Page int `json:"page"` + PageSize int `json:"page_size"` + Total int64 `json:"total"` + List []adminUserItem `json:"list"` +} + +// ListAppUsers 管理端用户列表 +// @Summary 管理端用户列表 +// @Description 查看APP端用户分页列表 +// @Tags 管理端.用户 +// @Accept json +// @Produce json +// @Param page query int true "页码" default(1) +// @Param page_size query int true "每页数量,最多100" default(20) +// @Success 200 {object} listUsersResponse +// @Failure 400 {object} code.Failure +// @Router /api/admin/users [get] +// @Security LoginVerifyToken +func (h *handler) ListAppUsers() core.HandlerFunc { + return func(ctx core.Context) { + req := new(listUsersRequest) + rsp := new(listUsersResponse) + if err := ctx.ShouldBindForm(req); err != nil { + ctx.AbortWithError(core.Error(http.StatusBadRequest, code.ParamBindError, validation.Error(err))) + return + } + if req.Page <= 0 { + req.Page = 1 + } + if req.PageSize <= 0 { + req.PageSize = 20 + } + if req.PageSize > 100 { + req.PageSize = 100 + } + q := h.readDB.Users.WithContext(ctx.RequestContext()).ReadDB() + total, err := q.Count() + if err != nil { + ctx.AbortWithError(core.Error(http.StatusBadRequest, 20101, err.Error())) + return + } + rows, err := q.Order(h.readDB.Users.ID.Desc()).Offset((req.Page - 1) * req.PageSize).Limit(req.PageSize).Find() + if err != nil { + ctx.AbortWithError(core.Error(http.StatusBadRequest, 20102, err.Error())) + return + } + rsp.Page = req.Page + rsp.PageSize = req.PageSize + rsp.Total = total + rsp.List = make([]adminUserItem, len(rows)) + for i, v := range rows { + rsp.List[i] = adminUserItem{ID: v.ID, Nickname: v.Nickname, Avatar: v.Avatar, InviteCode: v.InviteCode, InviterID: v.InviterID, CreatedAt: v.CreatedAt.Format("2006-01-02 15:04:05")} + } + ctx.Payload(rsp) + } +} + +type listInvitesRequest struct { + Page int `form:"page"` + PageSize int `form:"page_size"` +} +type listInvitesResponse struct { + Page int `json:"page"` + PageSize int `json:"page_size"` + Total int64 `json:"total"` + List []adminUserItem `json:"list"` +} + +// ListUserInvites 查看用户邀请列表 +// @Summary 查看用户邀请列表 +// @Description 查看指定用户邀请的用户列表 +// @Tags 管理端.用户 +// @Accept json +// @Produce json +// @Param user_id path integer true "用户ID" +// @Param page query int true "页码" default(1) +// @Param page_size query int true "每页数量,最多100" default(20) +// @Success 200 {object} listInvitesResponse +// @Failure 400 {object} code.Failure +// @Router /api/admin/users/{user_id}/invites [get] +// @Security LoginVerifyToken +func (h *handler) ListUserInvites() core.HandlerFunc { + return func(ctx core.Context) { + req := new(listInvitesRequest) + rsp := new(listInvitesResponse) + if err := ctx.ShouldBindForm(req); err != nil { + ctx.AbortWithError(core.Error(http.StatusBadRequest, code.ParamBindError, validation.Error(err))) + return + } + userID, err := strconv.ParseInt(ctx.Param("user_id"), 10, 64) + if err != nil { + ctx.AbortWithError(core.Error(http.StatusBadRequest, code.ParamBindError, "未传递用户ID")) + return + } + rows, total, err := h.user.ListInvites(ctx.RequestContext(), userID, req.Page, req.PageSize) + if err != nil { + ctx.AbortWithError(core.Error(http.StatusBadRequest, 20103, err.Error())) + return + } + rsp.Page = req.Page + rsp.PageSize = req.PageSize + rsp.Total = total + rsp.List = make([]adminUserItem, len(rows)) + for i, v := range rows { + rsp.List[i] = adminUserItem{ID: v.ID, Nickname: v.Nickname, Avatar: v.Avatar, InviteCode: v.InviteCode, InviterID: v.InviterID, CreatedAt: v.CreatedAt.Format("2006-01-02 15:04:05")} + } + ctx.Payload(rsp) + } +} + +type listOrdersRequest struct { + Page int `form:"page"` + PageSize int `form:"page_size"` +} +type listOrdersResponse struct { + Page int `json:"page"` + PageSize int `json:"page_size"` + Total int64 `json:"total"` + List []*user.OrderWithItems `json:"list"` +} + +type listInventoryRequest struct { + Page int `form:"page"` + PageSize int `form:"page_size"` +} +type listInventoryResponse struct { + Page int `json:"page"` + PageSize int `json:"page_size"` + Total int64 `json:"total"` + List []*user.InventoryWithProduct `json:"list"` +} + +// ListUserOrders 查看用户订单列表 +// @Summary 查看用户订单列表 +// @Description 查看指定用户的订单记录 +// @Tags 管理端.用户 +// @Accept json +// @Produce json +// @Param user_id path integer true "用户ID" +// @Param page query int true "页码" default(1) +// @Param page_size query int true "每页数量,最多100" default(20) +// @Success 200 {object} listOrdersResponse +// @Failure 400 {object} code.Failure +// @Router /api/admin/users/{user_id}/orders [get] +// @Security LoginVerifyToken +func (h *handler) ListUserOrders() core.HandlerFunc { + return func(ctx core.Context) { + req := new(listOrdersRequest) + rsp := new(listOrdersResponse) + if err := ctx.ShouldBindForm(req); err != nil { + ctx.AbortWithError(core.Error(http.StatusBadRequest, code.ParamBindError, validation.Error(err))) + return + } + userID, err := strconv.ParseInt(ctx.Param("user_id"), 10, 64) + if err != nil { + ctx.AbortWithError(core.Error(http.StatusBadRequest, code.ParamBindError, "未传递用户ID")) + return + } + items, total, err := h.user.ListOrdersWithItems(ctx.RequestContext(), userID, req.Page, req.PageSize) + if err != nil { + ctx.AbortWithError(core.Error(http.StatusBadRequest, 20104, err.Error())) + return + } + rsp.Page = req.Page + rsp.PageSize = req.PageSize + rsp.Total = total + rsp.List = items + ctx.Payload(rsp) + } +} + +// 查看用户资产列表 +// @Summary 查看用户资产列表 +// @Description 查看指定用户的资产记录 +// @Tags 管理端.用户 +// @Accept json +// @Produce json +// @Param user_id path integer true "用户ID" +// @Param page query int true "页码" default(1) +// @Param page_size query int true "每页数量,最多100" default(20) +// @Success 200 {object} listInventoryResponse +// @Failure 400 {object} code.Failure +// @Router /api/admin/users/{user_id}/inventory [get] +// @Security LoginVerifyToken +func (h *handler) ListUserInventory() core.HandlerFunc { + return func(ctx core.Context) { + req := new(listInventoryRequest) + rsp := new(listInventoryResponse) + if err := ctx.ShouldBindForm(req); err != nil { + ctx.AbortWithError(core.Error(http.StatusBadRequest, code.ParamBindError, validation.Error(err))) + return + } + userID, err := strconv.ParseInt(ctx.Param("user_id"), 10, 64) + if err != nil { + ctx.AbortWithError(core.Error(http.StatusBadRequest, code.ParamBindError, "未传递用户ID")) + return + } + rows, total, err := h.user.ListInventoryWithProduct(ctx.RequestContext(), userID, req.Page, req.PageSize) + if err != nil { + ctx.AbortWithError(core.Error(http.StatusBadRequest, 20105, err.Error())) + return + } + rsp.Page = req.Page + rsp.PageSize = req.PageSize + rsp.Total = total + rsp.List = rows + ctx.Payload(rsp) + } +} + +type listCouponsRequest struct { + Page int `form:"page"` + PageSize int `form:"page_size"` +} +type adminUserCouponItem struct { + ID int64 `json:"id"` + CouponID int64 `json:"coupon_id"` + Status int32 `json:"status"` + UsedOrderID int64 `json:"used_order_id"` + UsedAt string `json:"used_at"` + ValidStart string `json:"valid_start"` + ValidEnd string `json:"valid_end"` + Name string `json:"name"` + ScopeType int32 `json:"scope_type"` + DiscountType int32 `json:"discount_type"` + DiscountValue int64 `json:"discount_value"` + MinSpend int64 `json:"min_spend"` +} + +type listCouponsResponse struct { + Page int `json:"page"` + PageSize int `json:"page_size"` + Total int64 `json:"total"` + List []adminUserCouponItem `json:"list"` +} + +// ListUserCoupons 查看用户优惠券列表 +// @Summary 查看用户优惠券列表 +// @Description 查看指定用户持有的优惠券列表 +// @Tags 管理端.用户 +// @Accept json +// @Produce json +// @Param user_id path integer true "用户ID" +// @Param page query int true "页码" default(1) +// @Param page_size query int true "每页数量,最多100" default(20) +// @Success 200 {object} listCouponsResponse +// @Failure 400 {object} code.Failure +// @Router /api/admin/users/{user_id}/coupons [get] +// @Security LoginVerifyToken +func (h *handler) ListUserCoupons() core.HandlerFunc { + return func(ctx core.Context) { + req := new(listCouponsRequest) + rsp := new(listCouponsResponse) + if err := ctx.ShouldBindForm(req); err != nil { + ctx.AbortWithError(core.Error(http.StatusBadRequest, code.ParamBindError, validation.Error(err))) + return + } + userID, err := strconv.ParseInt(ctx.Param("user_id"), 10, 64) + if err != nil { + ctx.AbortWithError(core.Error(http.StatusBadRequest, code.ParamBindError, "未传递用户ID")) + return + } + // 统计总数 + base := h.readDB.UserCoupons.WithContext(ctx.RequestContext()).ReadDB().Where(h.readDB.UserCoupons.UserID.Eq(userID)) + total, err := base.Count() + if err != nil { + ctx.AbortWithError(core.Error(http.StatusBadRequest, 20105, err.Error())) + return + } + // 联表查询 system_coupons 获取优惠券模板信息 + type row struct { + ID int64 + CouponID int64 + Status int32 + UsedOrderID int64 + UsedAt *string + ValidStart *string + ValidEnd *string + Name string + ScopeType int32 + DiscountType int32 + DiscountValue int64 + MinSpend int64 + } + q := h.readDB.UserCoupons.WithContext(ctx.RequestContext()).ReadDB(). + LeftJoin(h.readDB.SystemCoupons, h.readDB.SystemCoupons.ID.EqCol(h.readDB.UserCoupons.CouponID)). + Select( + h.readDB.UserCoupons.ID, h.readDB.UserCoupons.CouponID, h.readDB.UserCoupons.Status, + h.readDB.UserCoupons.UsedOrderID, h.readDB.UserCoupons.UsedAt, h.readDB.UserCoupons.ValidStart, h.readDB.UserCoupons.ValidEnd, + h.readDB.SystemCoupons.Name, h.readDB.SystemCoupons.ScopeType, h.readDB.SystemCoupons.DiscountType, + h.readDB.SystemCoupons.DiscountValue, h.readDB.SystemCoupons.MinSpend, + ). + Where(h.readDB.UserCoupons.UserID.Eq(userID)). + Order(h.readDB.UserCoupons.ID.Desc()). + Limit(req.PageSize).Offset((req.Page-1)*req.PageSize) + + var rows []row + if err := q.Scan(&rows); err != nil { + ctx.AbortWithError(core.Error(http.StatusBadRequest, 20105, err.Error())) + return + } + + rsp.Page = req.Page + rsp.PageSize = req.PageSize + rsp.Total = total + rsp.List = make([]adminUserCouponItem, len(rows)) + for i, v := range rows { + rsp.List[i] = adminUserCouponItem{ + ID: v.ID, + CouponID: v.CouponID, + Status: v.Status, + UsedOrderID: v.UsedOrderID, + UsedAt: nullableToString(v.UsedAt), + ValidStart: nullableToString(v.ValidStart), + ValidEnd: nullableToString(v.ValidEnd), + Name: v.Name, + ScopeType: v.ScopeType, + DiscountType: v.DiscountType, + DiscountValue: v.DiscountValue, + MinSpend: v.MinSpend, + } + } + ctx.Payload(rsp) + } +} + +func nullableToString(s *string) string { + if s == nil { + return "" + } + return *s +} + +type listPointsRequest struct { + Page int `form:"page"` + PageSize int `form:"page_size"` +} +type listPointsResponse struct { + Page int `json:"page"` + PageSize int `json:"page_size"` + Total int64 `json:"total"` + List []*model.UserPointsLedger `json:"list"` +} + +// ListUserPoints 查看用户积分记录 +// @Summary 查看用户积分记录 +// @Description 查看指定用户的积分流水记录 +// @Tags 管理端.用户 +// @Accept json +// @Produce json +// @Param user_id path integer true "用户ID" +// @Param page query int true "页码" default(1) +// @Param page_size query int true "每页数量,最多100" default(20) +// @Success 200 {object} listPointsResponse +// @Failure 400 {object} code.Failure +// @Router /api/admin/users/{user_id}/points [get] +// @Security LoginVerifyToken +func (h *handler) ListUserPoints() core.HandlerFunc { + return func(ctx core.Context) { + req := new(listPointsRequest) + rsp := new(listPointsResponse) + if err := ctx.ShouldBindForm(req); err != nil { + ctx.AbortWithError(core.Error(http.StatusBadRequest, code.ParamBindError, validation.Error(err))) + return + } + userID, err := strconv.ParseInt(ctx.Param("user_id"), 10, 64) + if err != nil { + ctx.AbortWithError(core.Error(http.StatusBadRequest, code.ParamBindError, "未传递用户ID")) + return + } + items, total, err := h.user.ListPointsLedger(ctx.RequestContext(), userID, req.Page, req.PageSize) + if err != nil { + ctx.AbortWithError(core.Error(http.StatusBadRequest, 20106, err.Error())) + return + } + rsp.Page = req.Page + rsp.PageSize = req.PageSize + rsp.Total = total + rsp.List = items + ctx.Payload(rsp) + } +} + +type pointsBalanceResponse struct { + Balance int64 `json:"balance"` +} + +type adminUserItem struct { + ID int64 `json:"id"` + Nickname string `json:"nickname"` + Avatar string `json:"avatar"` + InviteCode string `json:"invite_code"` + InviterID int64 `json:"inviter_id"` + CreatedAt string `json:"created_at"` +} + +// GetUserPointsBalance 查看用户积分余额 +// @Summary 查看用户积分余额 +// @Description 查看指定用户当前积分余额(过滤过期) +// @Tags 管理端.用户 +// @Accept json +// @Produce json +// @Param user_id path integer true "用户ID" +// @Success 200 {object} pointsBalanceResponse +// @Failure 400 {object} code.Failure +// @Router /api/admin/users/{user_id}/points/balance [get] +// @Security LoginVerifyToken +func (h *handler) GetUserPointsBalance() core.HandlerFunc { + return func(ctx core.Context) { + rsp := new(pointsBalanceResponse) + userID, err := strconv.ParseInt(ctx.Param("user_id"), 10, 64) + if err != nil { + ctx.AbortWithError(core.Error(http.StatusBadRequest, code.ParamBindError, "未传递用户ID")) + return + } + total, err := h.user.GetPointsBalance(ctx.RequestContext(), userID) + if err != nil { + ctx.AbortWithError(core.Error(http.StatusBadRequest, 20107, err.Error())) + return + } + rsp.Balance = total + ctx.Payload(rsp) + } +} + +type addPointsRequest struct { + Points int64 `json:"points" binding:"required"` + Kind string `json:"kind"` + Remark string `json:"remark"` + ValidDays *int `json:"valid_days"` +} +type addPointsResponse struct { + Success bool `json:"success"` +} + +// AddUserPoints 给用户添加积分 +// @Summary 给用户添加积分 +// @Description 管理端为指定用户发放积分,支持设置有效期 +// @Tags 管理端.用户 +// @Accept json +// @Produce json +// @Param user_id path integer true "用户ID" +// @Param RequestBody body addPointsRequest true "请求参数" +// @Success 200 {object} addPointsResponse +// @Failure 400 {object} code.Failure +// @Router /api/admin/users/{user_id}/points/add [post] +// @Security LoginVerifyToken +func (h *handler) AddUserPoints() core.HandlerFunc { + return func(ctx core.Context) { + req := new(addPointsRequest) + rsp := new(addPointsResponse) + if err := ctx.ShouldBindJSON(req); err != nil { + ctx.AbortWithError(core.Error(http.StatusBadRequest, code.ParamBindError, validation.Error(err))) + return + } + userID, err := strconv.ParseInt(ctx.Param("user_id"), 10, 64) + if err != nil { + ctx.AbortWithError(core.Error(http.StatusBadRequest, code.ParamBindError, "未传递用户ID")) + return + } + var validStart *time.Time + var validEnd *time.Time + now := time.Now() + validStart = &now + if req.ValidDays != nil && *req.ValidDays > 0 { + ve := now.Add(time.Duration(*req.ValidDays) * 24 * time.Hour) + validEnd = &ve + } + if err := h.user.AddPoints(ctx.RequestContext(), userID, req.Points, req.Kind, req.Remark, validStart, validEnd); err != nil { + ctx.AbortWithError(core.Error(http.StatusBadRequest, 20108, err.Error())) + return + } + rsp.Success = true + ctx.Payload(rsp) + } +} + +type addCouponRequest struct { + CouponID int64 `json:"coupon_id" binding:"required"` +} +type addCouponResponse struct { + Success bool `json:"success"` +} + +// AddUserCoupon 给用户添加优惠券 +// @Summary 给用户添加优惠券 +// @Description 管理端为指定用户发放优惠券 +// @Tags 管理端.用户 +// @Accept json +// @Produce json +// @Param user_id path integer true "用户ID" +// @Param RequestBody body addCouponRequest true "请求参数" +// @Success 200 {object} addCouponResponse +// @Failure 400 {object} code.Failure +// @Router /api/admin/users/{user_id}/coupons/add [post] +// @Security LoginVerifyToken +func (h *handler) AddUserCoupon() core.HandlerFunc { + return func(ctx core.Context) { + req := new(addCouponRequest) + rsp := new(addCouponResponse) + if err := ctx.ShouldBindJSON(req); err != nil { + ctx.AbortWithError(core.Error(http.StatusBadRequest, code.ParamBindError, validation.Error(err))) + return + } + userID, err := strconv.ParseInt(ctx.Param("user_id"), 10, 64) + if err != nil { + ctx.AbortWithError(core.Error(http.StatusBadRequest, code.ParamBindError, "未传递用户ID")) + return + } + if err := h.user.AddCoupon(ctx.RequestContext(), userID, req.CouponID); err != nil { + ctx.AbortWithError(core.Error(http.StatusBadRequest, 20109, err.Error())) + return + } + rsp.Success = true + ctx.Payload(rsp) + } +} diff --git a/internal/api/admin/users_reward_admin.go b/internal/api/admin/users_reward_admin.go new file mode 100644 index 0000000..50c2405 --- /dev/null +++ b/internal/api/admin/users_reward_admin.go @@ -0,0 +1,75 @@ +package admin + +import ( + "strconv" + + "bindbox-game/internal/pkg/core" + "bindbox-game/internal/service/user" + + "go.uber.org/zap" +) + +// GrantRewardRequest 奖励发放请求(复用service层的结构体) +type GrantRewardRequest = user.GrantRewardRequest + +// GrantRewardResponse 奖励发放响应(复用service层的结构体) +type GrantRewardResponse = user.GrantRewardResponse + +// GrantReward 给用户发放奖励 +// @Summary 给用户发放奖励 +// @Description 管理员给用户发放奖励,支持实物和虚拟奖品,可选择关联活动和奖励配置 +// @Tags 管理端.用户 +// @Accept json +// @Produce json +// @Param user_id path integer true "用户ID" +// @Param RequestBody body GrantRewardRequest true "请求参数" +// @Success 200 {object} GrantRewardResponse +// @Failure 400 {object} code.Failure +// @Failure 401 {object} code.Failure +// @Failure 403 {object} code.Failure +// @Failure 500 {object} code.Failure +// @Router /api/admin/users/{user_id}/rewards/grant [post] +func (h *handler) GrantReward() core.HandlerFunc { + return func(ctx core.Context) { + userIDStr := ctx.Param("user_id") + if userIDStr == "" { + ctx.AbortWithError(core.Error(400, 40001, "用户ID不能为空")) + return + } + + // 解析用户ID + userID, err := strconv.ParseInt(userIDStr, 10, 64) + if err != nil { + ctx.AbortWithError(core.Error(400, 40001, "用户ID格式错误")) + return + } + + // 权限检查 - 仅超管可以发放奖励 + if ctx.SessionUserInfo().IsSuper != 1 { + ctx.AbortWithError(core.Error(403, 40301, "无权限发放奖励")) + return + } + + // 解析请求参数 + var req GrantRewardRequest + if err := ctx.ShouldBindJSON(&req); err != nil { + zap.L().Error("解析奖励发放请求失败", zap.Error(err)) + ctx.AbortWithError(core.Error(400, 40001, "参数格式错误")) + return + } + + // 调用服务层发放奖励 + resp, err := h.user.GrantReward(ctx.RequestContext(), userID, user.GrantRewardRequest(req)) + if err != nil { + zap.L().Error("发放奖励失败", + zap.Int64("user_id", userID), + zap.Error(err), + ) + ctx.AbortWithError(core.Error(500, 50001, err.Error())) + return + } + + // 返回成功响应 + ctx.Payload(resp) + } +} diff --git a/internal/api/app/app.go b/internal/api/app/app.go deleted file mode 100644 index 5dd4795..0000000 --- a/internal/api/app/app.go +++ /dev/null @@ -1,23 +0,0 @@ -package app - -import ( - "mini-chat/internal/pkg/logger" - "mini-chat/internal/repository/mysql" - "mini-chat/internal/repository/mysql/dao" -) - -type handler struct { - logger logger.CustomLogger - writeDB *dao.Query - readDB *dao.Query - db mysql.Repo -} - -func New(logger logger.CustomLogger, db mysql.Repo) *handler { - return &handler{ - logger: logger, - writeDB: dao.Use(db.GetDbW()), - readDB: dao.Use(db.GetDbR()), - db: db, - } -} diff --git a/internal/api/app/app_check_status.go b/internal/api/app/app_check_status.go deleted file mode 100644 index 1c86f88..0000000 --- a/internal/api/app/app_check_status.go +++ /dev/null @@ -1,114 +0,0 @@ -package app - -import ( - "fmt" - "net/http" - - "mini-chat/internal/code" - "mini-chat/internal/pkg/core" - "mini-chat/internal/pkg/httpclient" - "mini-chat/internal/pkg/validation" - - "go.uber.org/zap" -) - -// checkAppStatusRequest 请求参数 -// 功能描述:用于检查指定小程序(app_id)的运行状态 -// 参数说明: -// - AppID(string): 小程序ID,必填,通过query参数传入(form:"app_id") -// 返回值:无(该函数返回一个core.HandlerFunc处理器,在HTTP请求完成后通过ctx.Payload返回JSON数据) -type checkAppStatusRequest struct { - AppID string `form:"app_id" binding:"required"` // 小程序ID -} - -// checkAppStatusResponse 响应数据结构 -// 功能描述:返回外部验证服务的状态码与状态文本,并提供统一的文字描述 -// 字段说明: -// - AppID(string): 小程序ID -// - Code(int): 外部接口返回的状态码,1表示正常,0表示封禁,其它表示未知 -// - Status(string): 外部接口返回的原始状态描述 -// - CheckStatusText(string): 根据Code映射得到的中文状态文字(正常/封禁/未知) -type checkAppStatusResponse struct { - AppID string `json:"app_id"` // 小程序ID - Code int `json:"code"` // 外部接口返回的状态码 - CheckStatusText string `json:"check_status_text"` // 状态文字描述 -} - -// CheckAppStatus 检查小程序状态 -// @Summary 检查小程序状态 -// @Description 管理端根据 app_id 调用外部验证服务获取状态(正常/封禁/未知) -// @Tags 管理端.小程序 -// @Accept json -// @Produce json -// @Param app_id query string true "小程序ID" -// @Success 200 {object} checkAppStatusResponse -// @Failure 400 {object} code.Failure -// @Router /api/admin/app/check_status [get] -// @Security LoginVerifyToken -func (h *handler) CheckAppStatus() core.HandlerFunc { - return func(ctx core.Context) { - // 绑定请求参数 - req := new(checkAppStatusRequest) - if err := ctx.ShouldBindForm(req); err != nil { - ctx.AbortWithError(core.Error( - http.StatusBadRequest, - code.ParamBindError, - validation.Error(err)), - ) - return - } - - // 调用外部验证服务 - // 外部接口: https://api.wxapi.work/xcx/checkxcx.php?appid= - // 期望返回: {"code":1, "appid":"xxx", "status":"ok"} - type externalCheckResp struct { - Code int `json:"code"` - Appid string `json:"appid"` - Status string `json:"status"` - } - - checkRes := new(externalCheckResp) - response, err := httpclient.GetHttpClientWithContext(ctx.RequestContext()).R(). - SetQueryParams(map[string]string{ - "appid": req.AppID, - }). - SetResult(checkRes). - Get("https://api.wxapi.work/xcx/checkxcx.php") - - if err != nil { - // 记录请求错误 - h.logger.Error("请求APP验证服务失败", zap.Error(err)) - ctx.AbortWithError(core.Error( - http.StatusBadRequest, - code.ListAppError, - fmt.Sprintf("%s:%s", code.Text(code.ListAppError), err.Error()), - )) - return - } - - // 检查响应状态码 - if response.IsError() { - h.logger.Error(fmt.Sprintf("请求APP验证服务异常(%d)", response.StatusCode())) - } - - // 将外部返回的code映射为中文状态 - statusText := "未知" - switch checkRes.Code { - case 1: - statusText = "正常" - case 0: - statusText = "封禁" - default: - statusText = "未知" - } - - // 组织响应数据并返回 - res := &checkAppStatusResponse{ - AppID: req.AppID, - Code: checkRes.Code, - CheckStatusText: statusText, - } - - ctx.Payload(res) - } -} diff --git a/internal/api/app/app_create.go b/internal/api/app/app_create.go deleted file mode 100755 index ae7d227..0000000 --- a/internal/api/app/app_create.go +++ /dev/null @@ -1,104 +0,0 @@ -package app - -import ( - "fmt" - "net/http" - "time" - - "mini-chat/internal/code" - "mini-chat/internal/pkg/core" - "mini-chat/internal/pkg/validation" - "mini-chat/internal/repository/mysql/model" - - "gorm.io/gorm" -) - -type createAppRequest struct { - AppID string `json:"app_id" binding:"required"` // 小程序ID - AppSecret string `json:"app_secret" binding:"required"` // 小程序密钥 - Name string `json:"name" binding:"required"` // 名称 - Description string `json:"description"` // 描述 - Avatar string `json:"avatar"` // 头像 - TemplateID string `json:"template_id"` // 模版ID -} - -type createAppResponse struct { - Message string `json:"message"` // 提示信息 -} - -// CreateApp 新增小程序 -// @Summary 新增小程序 -// @Description 新增小程序 -// @Tags 管理端.小程序 -// @Accept json -// @Produce json -// @Param RequestBody body createAppRequest true "请求参数" -// @Success 200 {object} createAppResponse -// @Failure 400 {object} code.Failure -// @Router /api/admin/app/create [post] -// @Security LoginVerifyToken -func (h *handler) CreateApp() core.HandlerFunc { - return func(ctx core.Context) { - req := new(createAppRequest) - res := new(createAppResponse) - if err := ctx.ShouldBindJSON(req); err != nil { - ctx.AbortWithError(core.Error( - http.StatusBadRequest, - code.ParamBindError, - validation.Error(err)), - ) - return - } - - if ctx.SessionUserInfo().IsSuper != 1 { - ctx.AbortWithError(core.Error( - http.StatusBadRequest, - code.CreateAppError, - fmt.Sprintf("%s: %s", code.Text(code.CreateAppError), "禁止操作")), - ) - return - } - - info, err := h.readDB.MiniProgram.WithContext(ctx.RequestContext()). - Where(h.readDB.MiniProgram.AppID.Eq(req.AppID)). - First() - if err != nil && err != gorm.ErrRecordNotFound { - ctx.AbortWithError(core.Error( - http.StatusBadRequest, - code.CreateAppError, - fmt.Sprintf("%s: %s", code.Text(code.CreateAppError), err.Error())), - ) - return - } - - if info != nil { - ctx.AbortWithError(core.Error( - http.StatusBadRequest, - code.CreateAppError, - fmt.Sprintf("%s: %s", code.Text(code.CreateAppError), "该小程序已存在")), - ) - return - } - - App := new(model.MiniProgram) - App.AppID = req.AppID - App.AppSecret = req.AppSecret - App.Name = req.Name - App.Description = req.Description - App.Avatar = req.Avatar - App.TemplateID = req.TemplateID - App.CreatedUser = ctx.SessionUserInfo().UserName - App.CreatedAt = time.Now() - if err := h.writeDB.MiniProgram.WithContext(ctx.RequestContext()).Create(App); err != nil { - ctx.AbortWithError(core.Error( - http.StatusBadRequest, - code.CreateAppError, - fmt.Sprintf("%s: %s", code.Text(code.CreateAppError), err.Error())), - ) - return - } - - res.Message = "操作成功" - ctx.Payload(res) - } -} diff --git a/internal/api/app/app_delete.go b/internal/api/app/app_delete.go deleted file mode 100755 index 83b78bc..0000000 --- a/internal/api/app/app_delete.go +++ /dev/null @@ -1,108 +0,0 @@ -package app - -import ( - "fmt" - "net/http" - "strconv" - "strings" - - "mini-chat/internal/code" - "mini-chat/internal/pkg/core" - "mini-chat/internal/pkg/validation" - "mini-chat/internal/repository/mysql/model" -) - -type deleteAppRequest struct { - Ids string `json:"ids" binding:"required"` // 小程序编号(多个用,分割) -} - -type deleteAppResponse struct { - Message string `json:"message"` // 提示信息 -} - -// DeleteApp 删除小程序 -// @Summary 删除小程序 -// @Description 删除小程序 -// @Tags 管理端.小程序 -// @Accept json -// @Produce json -// @Param RequestBody body deleteAppRequest true "请求参数" -// @Success 200 {object} deleteAppResponse -// @Failure 400 {object} code.Failure -// @Router /api/admin/app/delete [post] -// @Security LoginVerifyToken -func (h *handler) DeleteApp() core.HandlerFunc { - return func(ctx core.Context) { - req := new(deleteAppRequest) - res := new(deleteAppResponse) - if err := ctx.ShouldBindJSON(req); err != nil { - ctx.AbortWithError(core.Error( - http.StatusBadRequest, - code.ParamBindError, - validation.Error(err)), - ) - return - } - - if ctx.SessionUserInfo().IsSuper != 1 { - ctx.AbortWithError(core.Error( - http.StatusBadRequest, - code.CreateAppError, - fmt.Sprintf("%s: %s", code.Text(code.CreateAppError), "禁止操作")), - ) - return - } - - idList := strings.Split(req.Ids, ",") - if len(idList) == 0 || (len(idList) == 1 && idList[0] == "") { - ctx.AbortWithError(core.Error( - http.StatusBadRequest, - code.ParamBindError, - "小程序编号不能为空"), - ) - return - } - - var ids []int32 - - for _, strID := range idList { - if strID == "" { - continue - } - - id, err := strconv.Atoi(strID) - if err != nil { - ctx.AbortWithError(core.Error( - http.StatusBadRequest, - code.ParamBindError, - fmt.Sprintf("无效的小程序编号: %s", strID)), - ) - return - } - - ids = append(ids, int32(id)) - } - - if len(ids) == 0 { - ctx.AbortWithError(core.Error( - http.StatusBadRequest, - code.ParamBindError, - "小程序编号不能为空"), - ) - return - } - - if _, err := h.writeDB.MiniProgram.WithContext(ctx.RequestContext()). - Where(h.writeDB.MiniProgram.ID.In(ids...)). - Delete(&model.MiniProgram{}); err != nil { - ctx.AbortWithError(core.Error( - http.StatusBadRequest, - code.DeleteAppError, - fmt.Sprintf("%s: %s", code.Text(code.DeleteAppError), err.Error())), - ) - return - } - res.Message = "操作成功" - ctx.Payload(res) - } -} diff --git a/internal/api/app/app_latest_messages.go b/internal/api/app/app_latest_messages.go deleted file mode 100644 index 3afe765..0000000 --- a/internal/api/app/app_latest_messages.go +++ /dev/null @@ -1,163 +0,0 @@ -package app - -import ( - "fmt" - "net/http" - "time" - - "mini-chat/internal/code" - "mini-chat/internal/pkg/core" - "mini-chat/internal/pkg/timeutil" - "mini-chat/internal/pkg/validation" -) - -type latestMessageByAppIdRequest struct { - AppID string `form:"app_id" binding:"required"` // 小程序ID - Page int `form:"page"` // 当前页码,默认1 - PageSize int `form:"page_size"` // 每页返回的数据量,默认20 -} - -type latestMessageData struct { - SendTime string `json:"send_time"` // 发送时间 - SenderID string `json:"sender_id"` // 发送人ID - SenderName string `json:"sender_name"` // 发送人昵称 - SenderAvatar string `json:"sender_avatar"` // 发送人头像 - UnreadCount int `json:"unread_count"` // 未读消息数量 - Content string `json:"content"` // 消息内容 - MsgType int32 `json:"msg_type"` // 消息类型(1:文本 2:图片) -} - -type latestMessageByAppIdResponse struct { - Page int `json:"page"` // 当前页码 - PageSize int `json:"page_size"` // 每页返回的数据量 - Total int64 `json:"total"` // 符合查询条件的总记录数 - List []latestMessageData `json:"list"` -} - -// LatestMessageByAppId 根据appid获取最新消息记录 -// @Summary 根据appid获取最新消息记录 -// @Description 管理端根据appid获取最新消息记录,包含已读未读状态,访问时自动标记为已读 -// @Tags 管理端.小程序 -// @Accept json -// @Produce json -// @Param app_id query string true "小程序ID" -// @Param page query int true "当前页码" default(1) -// @Param page_size query int true "每页返回的数据量,最多 100 条" default(20) -// @Success 200 {object} latestMessageByAppIdResponse -// @Failure 400 {object} code.Failure -// @Router /api/admin/messages/latest [get] -// @Security LoginVerifyToken -func (h *handler) LatestMessageByAppId() core.HandlerFunc { - return func(ctx core.Context) { - req := new(latestMessageByAppIdRequest) - res := new(latestMessageByAppIdResponse) - if err := ctx.ShouldBindForm(req); err != nil { - ctx.AbortWithError(core.Error( - http.StatusBadRequest, - code.ParamBindError, - validation.Error(err)), - ) - return - } - - if req.Page == 0 { - req.Page = 1 - } - - if req.PageSize == 0 { - req.PageSize = 20 - } - - if req.PageSize > 100 { - ctx.AbortWithError(core.Error( - http.StatusBadRequest, - code.ListMessageError, - fmt.Sprintf("%s: 一次最多只能查询 100 条", code.Text(code.ListMessageError)), - )) - return - } - - type unreadMessageResult struct { - SenderID string `json:"sender_id"` - SenderName string `json:"sender_name"` - SendTime time.Time `json:"send_time"` - AvatarURL string `json:"avatar_url"` - UnreadCount int `json:"unread_count"` - Content string `json:"content"` // 消息内容 - MsgType int32 `json:"msg_type"` // 消息类型(1:文本 2:图片) - } - - var results []unreadMessageResult - var total int64 - - countErr := h.db.GetDbR().Table("app_message_log m"). - Select("m.send_time, m.sender_id, m.sender_name, u.user_avatar as avatar_url"). - Joins("LEFT JOIN app_user u ON m.sender_id = u.user_id"). - Where("m.app_id = ? AND m.sender_id != ?", req.AppID, "888888"). - Group("m.sender_id"). - Count(&total). - Error - if countErr != nil { - ctx.AbortWithError(core.Error( - http.StatusBadRequest, - code.ListMessageError, - fmt.Sprintf("%s:%s", code.Text(code.ListMessageError), countErr.Error())), - ) - return - } - - subQuery := h.db.GetDbR().Table("app_message_log"). - Select("sender_id, MAX(send_time) as latest_time"). - Where("app_id = ? AND sender_id != ?", req.AppID, "888888"). - Group("sender_id") - - resultErr := h.db.GetDbR().Table("app_message_log m"). - Select("m.send_time, m.content, m.msg_type, m.sender_id, m.sender_name, u.user_avatar as avatar_url, (SELECT COUNT(*) FROM app_message_log WHERE sender_id = m.sender_id AND is_read = 0) as unread_count"). - Joins("LEFT JOIN app_user u ON m.sender_id = u.user_id"). - Joins("JOIN (?) as latest ON m.sender_id = latest.sender_id AND m.send_time = latest.latest_time", subQuery). - Where("m.app_id = ? AND m.sender_id != ?", req.AppID, "888888"). - Group("m.sender_id"). - Order("unread_count DESC, send_time DESC"). - Offset((req.Page - 1) * req.PageSize). - Limit(req.PageSize). - Find(&results). - Error - if resultErr != nil { - ctx.AbortWithError(core.Error( - http.StatusBadRequest, - code.ListMessageError, - fmt.Sprintf("%s:%s", code.Text(code.ListMessageError), resultErr.Error())), - ) - return - } - - // 自动标记该appid下的所有消息为已读(管理端访问时) - //_, err := h.writeDB.AppMessageLog.WithContext(ctx.RequestContext()). - // Where(h.writeDB.AppMessageLog.AppID.Eq(req.AppID)). - // Where(h.writeDB.AppMessageLog.IsRead.Eq(0)). - // Update(h.writeDB.AppMessageLog.IsRead, 1) - //if err != nil { - // // 记录错误但不影响查询结果 - // // TODO: 可以添加日志记录 - //} - - res.Page = req.Page - res.PageSize = req.PageSize - res.Total = total - res.List = make([]latestMessageData, len(results)) - - for k, v := range results { - res.List[k] = latestMessageData{ - SendTime: timeutil.FriendlyTime(v.SendTime), - SenderID: v.SenderID, - SenderName: v.SenderName, - SenderAvatar: v.AvatarURL, - UnreadCount: v.UnreadCount, - Content: v.Content, - MsgType: v.MsgType, - } - } - - ctx.Payload(res) - } -} diff --git a/internal/api/app/app_list.go b/internal/api/app/app_list.go deleted file mode 100755 index 762ac7f..0000000 --- a/internal/api/app/app_list.go +++ /dev/null @@ -1,168 +0,0 @@ -package app - -import ( - "fmt" - "net/http" - - "mini-chat/internal/code" - "mini-chat/internal/pkg/core" - "mini-chat/internal/pkg/timeutil" - "mini-chat/internal/pkg/validation" - - "gorm.io/gorm" -) - -type listRequest struct { - AppID string `form:"app_id"` // 小程序ID - AdminID int32 `form:"admin_id"` // 客服编号 - Name string `form:"name"` // 小程序名称 - Page int `form:"page"` // 当前页码,默认为第一页 - PageSize int `form:"page_size"` // 每页返回的数据量 -} - -type listData struct { - ID int32 `json:"id"` // 小程序编号 - AppID string `json:"app_id"` // 小程序ID - AppSecret string `json:"app_secret"` // 小程序密钥 - Name string `json:"name"` // 小程序名称 - Description string `json:"description"` // 小程序描述 - Avatar string `json:"avatar"` // 小程序头像 - TemplateID string `json:"template_id"` // 模版ID - CreatedAt string `json:"created_at"` // 创建时间 - UpdatedAt string `json:"updated_at"` // 更新时间 - MessageTotal int64 `json:"message_total"` // 消息总数 - CheckStatusText string `json:"check_status_text"` // 状态文字描述 -} - -type listResponse struct { - Page int `json:"page"` // 当前页码 - PageSize int `json:"page_size"` // 每页返回的数据量 - Total int64 `json:"total"` // 符合查询条件的总记录数 - List []listData `json:"list"` -} - -// PageList 小程序列表 -// @Summary 小程序列表 -// @Description 小程序列表 -// @Tags 管理端.小程序 -// @Accept json -// @Produce json -// @Param name query string false "小程序名称" -// @Param app_id query string false "小程序ID" -// @Param admin_id query int false "客服编号" -// @Param page query int true "当前页码" default(1) -// @Param page_size query int true "每页返回的数据量,最多 100 条" default(20) -// @Success 200 {object} listResponse -// @Failure 400 {object} code.Failure -// @Router /api/admin/apps [get] -// @Security LoginVerifyToken -func (h *handler) PageList() core.HandlerFunc { - return func(ctx core.Context) { - req := new(listRequest) - res := new(listResponse) - - if err := ctx.ShouldBindForm(req); err != nil { - ctx.AbortWithError(core.Error( - http.StatusBadRequest, - code.ParamBindError, - validation.Error(err)), - ) - return - } - - if req.Page == 0 { - req.Page = 1 - } - - if req.PageSize == 0 { - req.PageSize = 20 - } - - if req.PageSize > 100 { - ctx.AbortWithError(core.Error( - http.StatusBadRequest, - code.ListAppError, - fmt.Sprintf("%s: 一次最多只能查询 100 条", code.Text(code.ListAppError)), - )) - return - } - - query := h.readDB.MiniProgram.WithContext(ctx.RequestContext()) - - if ctx.SessionUserInfo().IsSuper != 1 { - query = query.Where(h.readDB.MiniProgram.AdminID.Eq(ctx.SessionUserInfo().Id)) - } else { - if req.AdminID != 0 { - query = query.Where(h.readDB.MiniProgram.AdminID.Eq(req.AdminID)) - } - } - - if req.AppID != "" { - query = query.Where(h.readDB.MiniProgram.AppID.Eq(req.AppID)) - } - - if req.Name != "" { - query = query.Where(h.readDB.MiniProgram.Name.Like(fmt.Sprintf("%%%s%%", req.Name))) - } - - listQueryDB := query.Session(&gorm.Session{}) - countQueryDB := query.Session(&gorm.Session{}) - - resultData, err := listQueryDB. - Order(h.readDB.MiniProgram.ID.Desc()). - Limit(req.PageSize). - Offset((req.Page - 1) * req.PageSize).Find() - if err != nil { - ctx.AbortWithError(core.Error( - http.StatusBadRequest, - code.ListAppError, - fmt.Sprintf("%s:%s", code.Text(code.ListAppError), err.Error())), - ) - return - } - - count, err := countQueryDB.Count() - if err != nil { - ctx.AbortWithError(core.Error( - http.StatusBadRequest, - code.ListAppError, - fmt.Sprintf("%s:%s", code.Text(code.ListAppError), err.Error())), - ) - return - } - - res.Page = req.Page - res.PageSize = req.PageSize - res.Total = count - res.List = make([]listData, len(resultData)) - - for k, v := range resultData { - userTotalCount, _ := h.readDB.AppUser.WithContext(ctx.RequestContext()). - Where(h.readDB.AppUser.AppID.Eq(v.AppID)). - Count() - - checkStatusText := "未知" - if v.Status == 1 { - checkStatusText = "正常" - } else if v.Status == -1 { - checkStatusText = "封禁" - } - - res.List[k] = listData{ - ID: v.ID, - AppID: v.AppID, - AppSecret: v.AppSecret, - Name: v.Name, - Description: v.Description, - Avatar: v.Avatar, - TemplateID: v.TemplateID, - CreatedAt: timeutil.FriendlyTime(v.CreatedAt), - UpdatedAt: timeutil.FriendlyTime(v.UpdatedAt), - MessageTotal: userTotalCount, - CheckStatusText: checkStatusText, - } - } - - ctx.Payload(res) - } -} diff --git a/internal/api/app/app_message_list.go b/internal/api/app/app_message_list.go deleted file mode 100644 index f37ad1a..0000000 --- a/internal/api/app/app_message_list.go +++ /dev/null @@ -1,143 +0,0 @@ -package app - -import ( - "fmt" - "net/http" - - "mini-chat/internal/code" - "mini-chat/internal/pkg/core" - "mini-chat/internal/pkg/validation" - - "gorm.io/gorm" -) - -type appMessagePageListRequest struct { - AppID string `form:"app_id" binding:"required"` // 小程序ID - UserID string `form:"user_id" binding:"required"` // 用户ID - Page int `form:"page"` // 当前页码,默认为第一页 - PageSize int `form:"page_size"` // 每页返回的数据量 -} - -type listMessageData struct { - ID string `json:"id"` // 消息ID - SendTime string `json:"send_time"` // 发送时间 - SenderID string `json:"sender_id"` // 发送人ID - SenderName string `json:"sender_name"` // 发送人昵称 - ReceiverID string `json:"receiver_id"` // 接收人ID - Content string `json:"content"` // 消息内容 - MsgType int32 `json:"msg_type"` // 消息类型(1:文本 2:图片) -} - -type appMessagePageListResponse struct { - Page int `json:"page"` // 当前页码 - PageSize int `json:"page_size"` // 每页返回的数据量 - Total int64 `json:"total"` // 符合查询条件的总记录数 - List []listMessageData `json:"list"` -} - -// AppMessagePageList 获取消息日志 -// @Summary 获取消息日志 -// @Description 获取消息日志 -// @Tags 管理端.小程序 -// @Accept json -// @Produce json -// @Param app_id query string true "小程序ID" -// @Param user_id query string true "用户ID" -// @Param page query int true "当前页码" default(1) -// @Param page_size query int true "每页返回的数据量,最多 100 条" default(20) -// @Success 200 {object} appMessagePageListResponse -// @Failure 400 {object} code.Failure -// @Router /api/admin/messages [get] -// @Security LoginVerifyToken -func (h *handler) AppMessagePageList() core.HandlerFunc { - return func(ctx core.Context) { - req := new(appMessagePageListRequest) - res := new(appMessagePageListResponse) - if err := ctx.ShouldBindForm(req); err != nil { - ctx.AbortWithError(core.Error( - http.StatusBadRequest, - code.ParamBindError, - validation.Error(err)), - ) - return - } - - if req.Page == 0 { - req.Page = 1 - } - - if req.PageSize == 0 { - req.PageSize = 20 - } - - if req.PageSize > 100 { - ctx.AbortWithError(core.Error( - http.StatusBadRequest, - code.ListMessageError, - fmt.Sprintf("%s: 一次最多只能查询 100 条", code.Text(code.ListMessageError)), - )) - return - } - - query := h.readDB.AppMessageLog.WithContext(ctx.RequestContext()). - Where(h.readDB.AppMessageLog.AppID.Eq(req.AppID)). - Where(h.readDB.AppMessageLog.SenderID.Eq(req.UserID)).Or(h.readDB.AppMessageLog.ReceiverID.Eq(req.UserID)) - - listQueryDB := query.Session(&gorm.Session{}) - countQueryDB := query.Session(&gorm.Session{}) - - resultData, err := listQueryDB. - Order(h.readDB.AppMessageLog.SendTime.Desc()). - Limit(req.PageSize). - Offset((req.Page - 1) * req.PageSize). - Find() - if err != nil { - ctx.AbortWithError(core.Error( - http.StatusBadRequest, - code.ListMessageError, - fmt.Sprintf("%s:%s", code.Text(code.ListMessageError), err.Error())), - ) - return - } - - count, err := countQueryDB.Count() - if err != nil { - ctx.AbortWithError(core.Error( - http.StatusBadRequest, - code.ListMessageError, - fmt.Sprintf("%s:%s", code.Text(code.ListMessageError), err.Error())), - ) - return - } - - go func() { - _, err = h.writeDB.AppMessageLog. - Where(h.writeDB.AppMessageLog.AppID.Eq(req.AppID)). - Where(h.writeDB.AppMessageLog.SenderID.Eq(req.UserID)).Or(h.readDB.AppMessageLog.ReceiverID.Eq(req.UserID)). - Where(h.writeDB.AppMessageLog.IsRead.Eq(0)). - Update(h.writeDB.AppMessageLog.IsRead, 1) - if err != nil { - h.logger.Error(fmt.Sprintf("[AppMessagePageList] update app message log error: %s", err.Error())) - } - }() - - res.Page = req.Page - res.PageSize = req.PageSize - res.Total = count - res.List = make([]listMessageData, len(resultData)) - - for k, v := range resultData { - res.List[k] = listMessageData{ - ID: fmt.Sprint(v.ID), - SendTime: v.SendTime.Format("2006-01-02 15:04:05"), - SenderID: v.SenderID, - SenderName: v.SenderName, - ReceiverID: v.ReceiverID, - Content: v.Content, - MsgType: v.MsgType, - } - } - - ctx.Payload(res) - } -} diff --git a/internal/api/app/app_message_send.go b/internal/api/app/app_message_send.go deleted file mode 100644 index db9adc5..0000000 --- a/internal/api/app/app_message_send.go +++ /dev/null @@ -1,69 +0,0 @@ -package app - -import ( - "fmt" - "net/http" - "time" - - "mini-chat/internal/code" - "mini-chat/internal/pkg/core" - "mini-chat/internal/pkg/validation" - "mini-chat/internal/repository/mysql/model" -) - -type adminSendMessageRequest struct { - AppID string `json:"app_id" binding:"required"` // 小程序ID - ToUserID string `json:"to_user_id" binding:"required"` // 接收用户ID - MsgType int32 `json:"msg_type" binding:"required"` // 消息类型(1:文本 2:图片) - Content string `json:"content" binding:"required"` // 内容 -} - -type adminSendMessageResponse struct { - Message string `json:"message"` // 提示信息 -} - -// AdminSendMessage 管理员发送消息 -// @Summary 管理员发送消息 -// @Description 管理员发送消息 -// @Tags 管理端.小程序 -// @Accept json -// @Produce json -// @Param RequestBody body adminSendMessageRequest true "请求参数" -// @Success 200 {object} adminSendMessageResponse -// @Failure 400 {object} code.Failure -// @Router /api/admin/send_message [post] -// @Security LoginVerifyToken -func (h *handler) AdminSendMessage() core.HandlerFunc { - return func(ctx core.Context) { - req := new(adminSendMessageRequest) - res := new(adminSendMessageResponse) - if err := ctx.ShouldBindJSON(req); err != nil { - ctx.AbortWithError(core.Error( - http.StatusBadRequest, - code.ParamBindError, - validation.Error(err)), - ) - return - } - - createData := new(model.AppMessageLog) - createData.AppID = req.AppID - createData.SenderID = "888888" - createData.SenderName = "平台" - createData.Content = req.Content - createData.ReceiverID = req.ToUserID - createData.MsgType = req.MsgType - createData.SendTime = time.Now() - createData.CreatedAt = time.Now() - if err := h.writeDB.AppMessageLog.WithContext(ctx.RequestContext()).Create(createData); err != nil { - ctx.AbortWithError(core.Error( - http.StatusBadRequest, - code.SendMessageError, - fmt.Sprintf("%s: %s", code.Text(code.SendMessageError), err.Error()), - )) - } - - res.Message = "操作成功" - ctx.Payload(res) - } -} diff --git a/internal/api/app/app_modify.go b/internal/api/app/app_modify.go deleted file mode 100644 index 1416612..0000000 --- a/internal/api/app/app_modify.go +++ /dev/null @@ -1,145 +0,0 @@ -package app - -import ( - "fmt" - "net/http" - "strconv" - "time" - - "mini-chat/internal/code" - "mini-chat/internal/pkg/core" - "mini-chat/internal/pkg/validation" - - "gorm.io/gorm" -) - -type modifyAppRequest struct { - AppID string `json:"app_id" binding:"required"` // 小程序ID - AppSecret string `json:"app_secret" binding:"required"` // 小程序密钥 - Name string `json:"name" binding:"required"` // 名称 - Description string `json:"description"` // 描述 - Avatar string `json:"avatar"` // 头像 - TemplateID string `json:"template_id"` // 模版ID -} - -type modifyAppResponse struct { - Message string `json:"message"` // 提示信息 -} - -// ModifyApp 编辑小程序 -// @Summary 编辑小程序 -// @Description 编辑小程序 -// @Tags 管理端.小程序 -// @Accept json -// @Produce json -// @Param id path string true "编号ID" -// @Param RequestBody body modifyAppRequest true "请求参数" -// @Success 200 {object} modifyAppResponse -// @Failure 400 {object} code.Failure -// @Router /api/admin/app/{id} [put] -// @Security LoginVerifyToken -func (h *handler) ModifyApp() core.HandlerFunc { - return func(ctx core.Context) { - req := new(modifyAppRequest) - res := new(modifyAppResponse) - if err := ctx.ShouldBindJSON(req); err != nil { - ctx.AbortWithError(core.Error( - http.StatusBadRequest, - code.ParamBindError, - validation.Error(err)), - ) - return - } - - if ctx.SessionUserInfo().IsSuper != 1 { - ctx.AbortWithError(core.Error( - http.StatusBadRequest, - code.CreateAppError, - fmt.Sprintf("%s: %s", code.Text(code.CreateAppError), "禁止操作")), - ) - return - } - - if req.AppID == "" && req.Name == "" { - ctx.AbortWithError(core.Error( - http.StatusBadRequest, - code.ParamBindError, - "小程序ID和标题不能为空"), - ) - return - } - - id, err := strconv.Atoi(ctx.Param("id")) - if err != nil { - ctx.AbortWithError(core.Error( - http.StatusBadRequest, - code.ParamBindError, - "未传递编号ID"), - ) - return - } - - checkIdInfo, err := h.readDB.MiniProgram.WithContext(ctx.RequestContext()). - Where(h.readDB.MiniProgram.ID.Eq(int32(id))). - First() - if err != nil && err != gorm.ErrRecordNotFound { - ctx.AbortWithError(core.Error( - http.StatusBadRequest, - code.ModifyAppError, - fmt.Sprintf("%s: %s", code.Text(code.ModifyAppError), err.Error())), - ) - return - } - - if checkIdInfo == nil { - ctx.AbortWithError(core.Error( - http.StatusBadRequest, - code.ModifyAppError, - fmt.Sprintf("%s: %s", code.Text(code.ModifyAppError), "该小程序不存在")), - ) - return - } - - checkAppIDInfo, err := h.readDB.MiniProgram.WithContext(ctx.RequestContext()). - Where(h.readDB.MiniProgram.ID.Neq(int32(id))). - Where(h.readDB.MiniProgram.AppID.Eq(req.AppID)). - First() - if err != nil && err != gorm.ErrRecordNotFound { - ctx.AbortWithError(core.Error( - http.StatusBadRequest, - code.ModifyAppError, - fmt.Sprintf("%s: %s", code.Text(code.ModifyAppError), err.Error())), - ) - return - } - - if checkAppIDInfo != nil { - ctx.AbortWithError(core.Error( - http.StatusBadRequest, - code.ModifyAppError, - fmt.Sprintf("%s: %s", code.Text(code.ModifyAppError), "该小程序ID已存在")), - ) - return - } - - checkIdInfo.AppID = req.AppID - checkIdInfo.AppSecret = req.AppSecret - checkIdInfo.Name = req.Name - checkIdInfo.Description = req.Description - checkIdInfo.Avatar = req.Avatar - checkIdInfo.TemplateID = req.TemplateID - checkIdInfo.UpdatedUser = ctx.SessionUserInfo().UserName - checkIdInfo.UpdatedAt = time.Now() - if err := h.writeDB.MiniProgram.WithContext(ctx.RequestContext()).Save(checkIdInfo); err != nil { - ctx.AbortWithError(core.Error( - http.StatusBadRequest, - code.ModifyAppError, - fmt.Sprintf("%s:%s", code.Text(code.ModifyAppError), err.Error())), - ) - return - } - - res.Message = "操作成功" - ctx.Payload(res) - } -} diff --git a/internal/api/app/app_user_create.go b/internal/api/app/app_user_create.go deleted file mode 100755 index daf64bb..0000000 --- a/internal/api/app/app_user_create.go +++ /dev/null @@ -1,85 +0,0 @@ -package app - -import ( - "fmt" - "net/http" - "time" - - "mini-chat/internal/code" - "mini-chat/internal/pkg/core" - "mini-chat/internal/pkg/validation" - "mini-chat/internal/repository/mysql/model" - - "gorm.io/gorm" -) - -type createAppUserRequest struct { - AppID string `json:"app_id" binding:"required"` // 小程序ID - UserID string `json:"user_id" binding:"required"` // 用户ID - UserName string `json:"user_name" binding:"required"` // 用户昵称 - UserMobile string `json:"user_mobile"` // 用户手机号 - UserAvatar string `json:"user_avatar"` // 用户头像 -} - -type createAppUserResponse struct { - Message string `json:"message"` // 提示信息 -} - -// CreateAppUser 新增小程序用户 -// @Summary 新增小程序用户 -// @Description 新增小程序用户 -// @Tags 用户端 -// @Accept json -// @Produce json -// @Param RequestBody body createAppUserRequest true "请求参数" -// @Success 200 {object} createAppUserResponse -// @Failure 400 {object} code.Failure -// @Router /api/app/user/create [post] -func (h *handler) CreateAppUser() core.HandlerFunc { - return func(ctx core.Context) { - req := new(createAppUserRequest) - res := new(createAppUserResponse) - if err := ctx.ShouldBindJSON(req); err != nil { - ctx.AbortWithError(core.Error( - http.StatusBadRequest, - code.ParamBindError, - validation.Error(err)), - ) - return - } - - info, err := h.readDB.AppUser.WithContext(ctx.RequestContext()). - Where(h.readDB.AppUser.AppID.Eq(req.AppID)). - Where(h.readDB.AppUser.UserID.Eq(req.UserID)). - First() - if err != nil && err != gorm.ErrRecordNotFound { - ctx.AbortWithError(core.Error( - http.StatusBadRequest, - code.CreateAppUserError, - fmt.Sprintf("%s: %s", code.Text(code.CreateAppUserError), err.Error())), - ) - return - } - - if info == nil { - AppUser := new(model.AppUser) - AppUser.AppID = req.AppID - AppUser.UserID = req.UserID - AppUser.UserName = req.UserName - AppUser.UserMobile = req.UserMobile - AppUser.UserAvatar = req.UserAvatar - AppUser.CreatedAt = time.Now() - if err := h.writeDB.AppUser.WithContext(ctx.RequestContext()).Create(AppUser); err != nil { - ctx.AbortWithError(core.Error( - http.StatusBadRequest, - code.CreateAppUserError, - fmt.Sprintf("%s: %s", code.Text(code.CreateAppUserError), err.Error())), - ) - return - } - } - - res.Message = "操作成功" - ctx.Payload(res) - } -} diff --git a/internal/api/app/app_user_list.go b/internal/api/app/app_user_list.go deleted file mode 100755 index 24a4b0f..0000000 --- a/internal/api/app/app_user_list.go +++ /dev/null @@ -1,137 +0,0 @@ -package app - -import ( - "fmt" - "net/http" - - "mini-chat/internal/code" - "mini-chat/internal/pkg/core" - "mini-chat/internal/pkg/timeutil" - "mini-chat/internal/pkg/validation" - - "gorm.io/gorm" -) - -type userListRequest struct { - AppID string `form:"app_id"` // 小程序ID - UserID string `form:"user_id"` // 用户ID - UserName string `form:"user_name"` // 用户昵称 - Page int `form:"page"` // 当前页码,默认为第一页 - PageSize int `form:"page_size"` // 每页返回的数据量 -} - -type userListData struct { - UserID string `json:"user_id"` // 用户ID - UserName string `json:"user_name"` // 用户昵称 - UserMobile string `json:"user_mobile"` // 用户手机号 - UserAvatar string `json:"user_avatar"` // 用户头像 - CreatedAt string `json:"created_at"` // 创建时间 -} - -type userListResponse struct { - Page int `json:"page"` // 当前页码 - PageSize int `json:"page_size"` // 每页返回的数据量 - Total int64 `json:"total"` // 符合查询条件的总记录数 - List []userListData `json:"list"` -} - -// UserPageList 小程序用户列表 -// @Summary 小程序用户列表 -// @Description 小程序用户列表 -// @Tags 管理端.小程序 -// @Accept json -// @Produce json -// @Param app_id query string true "小程序ID" -// @Param user_name query string false "用户昵称" -// @Param user_id query string false "用户ID" -// @Param page query int true "当前页码" default(1) -// @Param page_size query int true "每页返回的数据量,最多 100 条" default(20) -// @Success 200 {object} userListResponse -// @Failure 400 {object} code.Failure -// @Router /api/admin/app/users [get] -// @Security LoginVerifyToken -func (h *handler) UserPageList() core.HandlerFunc { - return func(ctx core.Context) { - req := new(userListRequest) - res := new(userListResponse) - - if err := ctx.ShouldBindForm(req); err != nil { - ctx.AbortWithError(core.Error( - http.StatusBadRequest, - code.ParamBindError, - validation.Error(err)), - ) - return - } - - if req.Page == 0 { - req.Page = 1 - } - - if req.PageSize == 0 { - req.PageSize = 20 - } - - if req.PageSize > 100 { - ctx.AbortWithError(core.Error( - http.StatusBadRequest, - code.ListAppUserError, - fmt.Sprintf("%s: 一次最多只能查询 100 条", code.Text(code.ListAppUserError)), - )) - return - } - - query := h.readDB.AppUser.WithContext(ctx.RequestContext()).Where(h.readDB.AppUser.AppID.Eq(req.AppID)) - - if req.UserID != "" { - query = query.Where(h.readDB.AppUser.UserID.Eq(req.UserID)) - } - - if req.UserName != "" { - query = query.Where(h.readDB.AppUser.UserName.Like(fmt.Sprintf("%%%s%%", req.UserName))) - } - - listQueryDB := query.Session(&gorm.Session{}) - countQueryDB := query.Session(&gorm.Session{}) - - resultData, err := listQueryDB. - Order(h.readDB.AppUser.ID.Desc()). - Limit(req.PageSize). - Offset((req.Page - 1) * req.PageSize).Find() - if err != nil { - ctx.AbortWithError(core.Error( - http.StatusBadRequest, - code.ListAppUserError, - fmt.Sprintf("%s:%s", code.Text(code.ListAppUserError), err.Error())), - ) - return - } - - count, err := countQueryDB.Count() - if err != nil { - ctx.AbortWithError(core.Error( - http.StatusBadRequest, - code.ListAppUserError, - fmt.Sprintf("%s:%s", code.Text(code.ListAppUserError), err.Error())), - ) - return - } - - res.Page = req.Page - res.PageSize = req.PageSize - res.Total = count - res.List = make([]userListData, len(resultData)) - - for k, v := range resultData { - res.List[k] = userListData{ - UserID: v.UserID, - UserName: v.UserName, - UserMobile: v.UserMobile, - UserAvatar: v.UserAvatar, - CreatedAt: timeutil.FriendlyTime(v.CreatedAt), - } - } - - ctx.Payload(res) - } -} diff --git a/internal/api/app/banner.go b/internal/api/app/banner.go new file mode 100644 index 0000000..58ecccf --- /dev/null +++ b/internal/api/app/banner.go @@ -0,0 +1,59 @@ +package app + +import ( + "net/http" + + "bindbox-game/internal/code" + "bindbox-game/internal/pkg/core" + "bindbox-game/internal/pkg/validation" + bannersvc "bindbox-game/internal/service/banner" + "bindbox-game/internal/pkg/logger" + "bindbox-game/internal/repository/mysql" + "bindbox-game/internal/repository/mysql/dao" +) + +type bannerHandler struct { + logger logger.CustomLogger + readDB *dao.Query + banner bannersvc.Service +} + +func NewBanner(logger logger.CustomLogger, db mysql.Repo) *bannerHandler { + return &bannerHandler{logger: logger, readDB: dao.Use(db.GetDbR()), banner: bannersvc.New(logger, db)} +} + +type listAppBannersResponse struct { + List []appBannerItem `json:"list"` +} + +type appBannerItem struct { + ID int64 `json:"id"` + Title string `json:"title"` + ImageURL string `json:"image_url"` + LinkURL string `json:"link_url"` + Sort int32 `json:"sort"` +} + +// ListBannersForApp APP端轮播图列表 +// @Summary APP端轮播图列表 +// @Tags APP端.运营 +// @Accept json +// @Produce json +// @Success 200 {object} listAppBannersResponse +// @Failure 400 {object} code.Failure +// @Router /api/app/banners [get] +func (h *bannerHandler) ListBannersForApp() core.HandlerFunc { + return func(ctx core.Context) { + res := new(listAppBannersResponse) + items, err := h.banner.ListEnabled(ctx.RequestContext()) + if err != nil { + ctx.AbortWithError(core.Error(http.StatusBadRequest, code.ServerError, validation.Error(err))) + return + } + res.List = make([]appBannerItem, len(items)) + for i, it := range items { + res.List[i] = appBannerItem{ID: it.ID, Title: it.Title, ImageURL: it.ImageURL, LinkURL: it.LinkURL, Sort: it.Sort} + } + ctx.Payload(res) + } +} \ No newline at end of file diff --git a/internal/api/common/common.go b/internal/api/common/common.go new file mode 100644 index 0000000..0a34326 --- /dev/null +++ b/internal/api/common/common.go @@ -0,0 +1,24 @@ +package common + +import ( + "bindbox-game/internal/pkg/logger" + "bindbox-game/internal/repository/mysql" + "bindbox-game/internal/repository/mysql/dao" + commonsvc "bindbox-game/internal/service/common" +) + +type handler struct { + logger logger.CustomLogger + writeDB *dao.Query + readDB *dao.Query + svc commonsvc.Service +} + +func New(l logger.CustomLogger, db mysql.Repo) *handler { + return &handler{ + logger: l, + writeDB: dao.Use(db.GetDbW()), + readDB: dao.Use(db.GetDbR()), + svc: commonsvc.New(), + } +} diff --git a/internal/api/common/upload_wangeditor.go b/internal/api/common/upload_wangeditor.go new file mode 100644 index 0000000..66aa6ff --- /dev/null +++ b/internal/api/common/upload_wangeditor.go @@ -0,0 +1,44 @@ +package common + +import ( + "net/http" + + "bindbox-game/internal/code" + "bindbox-game/internal/pkg/core" +) + +func (h *handler) UploadWangEditorImage() core.HandlerFunc { + return func(ctx core.Context) { + fh, err := ctx.FormFile("file") + if err != nil { + ctx.AbortWithError(core.Error(http.StatusBadRequest, code.ParamBindError, "缺少文件")) + return + } + f, err := fh.Open() + if err != nil { + ctx.AbortWithError(core.Error(http.StatusBadRequest, code.UploadError, err.Error())) + return + } + defer f.Close() + + ct := fh.Header.Get("Content-Type") + if ct == "" { + ct = "application/octet-stream" + } + + url, err := h.svc.UploadImage(ctx.RequestContext(), fh.Filename, f, ct) + if err != nil { + ctx.AbortWithError(core.Error(http.StatusBadRequest, code.UploadError, err.Error())) + return + } + + resp := map[string]any{ + "errno": 0, + "data": map[string]string{ + "url": url, + }, + } + ctx.Payload(resp) + } +} + diff --git a/internal/api/guild/app.go b/internal/api/guild/app.go new file mode 100644 index 0000000..751b4c8 --- /dev/null +++ b/internal/api/guild/app.go @@ -0,0 +1,19 @@ +package app + +import ( + "bindbox-game/internal/pkg/logger" + "bindbox-game/internal/repository/mysql" + "bindbox-game/internal/repository/mysql/dao" + guildsvc "bindbox-game/internal/service/guild" +) + +type handler struct { + logger logger.CustomLogger + writeDB *dao.Query + readDB *dao.Query + guild guildsvc.Service +} + +func New(logger logger.CustomLogger, db mysql.Repo) *handler { + return &handler{logger: logger, writeDB: dao.Use(db.GetDbW()), readDB: dao.Use(db.GetDbR()), guild: guildsvc.New(logger, db)} +} diff --git a/internal/api/guild/guilds_app.go b/internal/api/guild/guilds_app.go new file mode 100644 index 0000000..04d8079 --- /dev/null +++ b/internal/api/guild/guilds_app.go @@ -0,0 +1,120 @@ +package app + +import ( + "net/http" + "strconv" + + "bindbox-game/internal/code" + "bindbox-game/internal/pkg/core" + "bindbox-game/internal/pkg/validation" +) + +type listGuildsRequest struct { + Name string `form:"name"` + IsOpen int32 `form:"is_open"` + Status int32 `form:"status"` + JoinMode int32 `form:"join_mode"` + Page int `form:"page"` + PageSize int `form:"page_size"` +} + +type guildItem struct { + ID int64 `json:"id"` + Name string `json:"name"` + OwnerID int64 `json:"owner_id"` + Description string `json:"description"` + JoinMode int32 `json:"join_mode"` + ConsumeLimit int64 `json:"consume_limit"` + AvatarURL string `json:"avatar_url"` + IsOpen int32 `json:"is_open"` + Status int32 `json:"status"` +} + +type listGuildsResponse struct { + Page int `json:"page"` + PageSize int `json:"page_size"` + Total int64 `json:"total"` + List []guildItem `json:"list"` +} + +// ListGuilds 工会列表 +// @Summary 浏览工会列表 +// @Description 获取工会列表,支持公开与状态过滤以及分页 +// @Tags APP端.工会 +// @Accept json +// @Produce json +// @Param name query string false "工会名称(模糊)" +// @Param is_open query int false "是否公开(1公开 2私有)" +// @Param status query int false "状态(1正常 2解散)" +// @Param join_mode query int false "加入方式(1审核 2自动 3消费流水)" +// @Param page query int true "页码" default(1) +// @Param page_size query int true "每页数量,最多100" default(20) +// @Success 200 {object} listGuildsResponse +// @Failure 400 {object} code.Failure +// @Router /api/app/guilds [get] +func (h *handler) ListGuilds() core.HandlerFunc { + return func(ctx core.Context) { + req := new(listGuildsRequest) + res := new(listGuildsResponse) + if err := ctx.ShouldBindForm(req); err != nil { + ctx.AbortWithError(core.Error(http.StatusBadRequest, code.ParamBindError, validation.Error(err))) + return + } + var isOpenPtr, statusPtr, joinModePtr *int32 + if req.IsOpen == 1 || req.IsOpen == 2 { + isOpenPtr = &req.IsOpen + } + if req.Status == 1 || req.Status == 2 { + statusPtr = &req.Status + } + if req.JoinMode == 1 || req.JoinMode == 2 || req.JoinMode == 3 { + joinModePtr = &req.JoinMode + } + items, total, err := h.guild.ListGuilds(ctx.RequestContext(), struct { + Name string + IsOpen *int32 + Status *int32 + JoinMode *int32 + Page int + PageSize int + }{Name: req.Name, IsOpen: isOpenPtr, Status: statusPtr, JoinMode: joinModePtr, Page: req.Page, PageSize: req.PageSize}) + if err != nil { + ctx.AbortWithError(core.Error(http.StatusBadRequest, code.ListGuildsError, err.Error())) + return + } + res.Page = req.Page + res.PageSize = req.PageSize + res.Total = total + res.List = make([]guildItem, len(items)) + for i, v := range items { + res.List[i] = guildItem{ID: v.ID, Name: v.Name, OwnerID: v.OwnerID, Description: v.Description, JoinMode: v.JoinMode, ConsumeLimit: v.ConsumeLimit, AvatarURL: v.AvatarURL, IsOpen: v.IsOpen, Status: v.Status} + } + ctx.Payload(res) + } +} + +// GetGuildDetail 工会详情 +// @Summary 查看工会详情 +// @Description 查看指定工会详情 +// @Tags APP端.工会 +// @Accept json +// @Produce json +// @Param guild_id path integer true "工会ID" +// @Success 200 {object} model.Guild +// @Failure 400 {object} code.Failure +// @Router /api/app/guilds/{guild_id} [get] +func (h *handler) GetGuildDetail() core.HandlerFunc { + return func(ctx core.Context) { + id, err := strconv.ParseInt(ctx.Param("guild_id"), 10, 64) + if err != nil { + ctx.AbortWithError(core.Error(http.StatusBadRequest, code.ParamBindError, "未传递工会ID")) + return + } + item, err := h.guild.GetGuild(ctx.RequestContext(), id) + if err != nil { + ctx.AbortWithError(core.Error(http.StatusBadRequest, code.GetGuildError, err.Error())) + return + } + ctx.Payload(item) + } +} diff --git a/internal/api/guild/members_app.go b/internal/api/guild/members_app.go new file mode 100644 index 0000000..214c14b --- /dev/null +++ b/internal/api/guild/members_app.go @@ -0,0 +1,141 @@ +package app + +import ( + "net/http" + "strconv" + + "bindbox-game/internal/code" + "bindbox-game/internal/pkg/core" + "bindbox-game/internal/pkg/validation" +) + +type joinGuildRequest struct { + UserID int64 `json:"user_id" binding:"required"` +} +type simpleMessageResponse struct { + Message string `json:"message"` +} + +// JoinGuild 加入工会 +// @Summary 加入工会 +// @Description 用户加入指定工会 +// @Tags APP端.工会 +// @Accept json +// @Produce json +// @Param guild_id path integer true "工会ID" +// @Param RequestBody body joinGuildRequest true "请求参数" +// @Success 200 {object} simpleMessageResponse +// @Failure 400 {object} code.Failure +// @Router /api/app/guilds/{guild_id}/members [post] +func (h *handler) JoinGuild() core.HandlerFunc { + return func(ctx core.Context) { + req := new(joinGuildRequest) + res := new(simpleMessageResponse) + if err := ctx.ShouldBindJSON(req); err != nil { + ctx.AbortWithError(core.Error(http.StatusBadRequest, code.ParamBindError, validation.Error(err))) + return + } + guildID, err := strconv.ParseInt(ctx.Param("guild_id"), 10, 64) + if err != nil { + ctx.AbortWithError(core.Error(http.StatusBadRequest, code.ParamBindError, "未传递工会ID")) + return + } + if err := h.guild.JoinGuild(ctx.RequestContext(), guildID, struct{ UserID int64 }{UserID: req.UserID}); err != nil { + ctx.AbortWithError(core.Error(http.StatusBadRequest, code.JoinGuildError, err.Error())) + return + } + res.Message = "操作成功" + ctx.Payload(res) + } +} + +// LeaveGuild 离开工会 +// @Summary 离开工会 +// @Description 用户离开指定工会 +// @Tags APP端.工会 +// @Accept json +// @Produce json +// @Param guild_id path integer true "工会ID" +// @Param user_id path integer true "用户ID" +// @Success 200 {object} simpleMessageResponse +// @Failure 400 {object} code.Failure +// @Router /api/app/guilds/{guild_id}/members/{user_id} [delete] +func (h *handler) LeaveGuild() core.HandlerFunc { + return func(ctx core.Context) { + res := new(simpleMessageResponse) + guildID, err := strconv.ParseInt(ctx.Param("guild_id"), 10, 64) + if err != nil { + ctx.AbortWithError(core.Error(http.StatusBadRequest, code.ParamBindError, "未传递工会ID")) + return + } + userID, err := strconv.ParseInt(ctx.Param("user_id"), 10, 64) + if err != nil { + ctx.AbortWithError(core.Error(http.StatusBadRequest, code.ParamBindError, "未传递用户ID")) + return + } + if err := h.guild.LeaveGuild(ctx.RequestContext(), guildID, userID); err != nil { + ctx.AbortWithError(core.Error(http.StatusBadRequest, code.LeaveGuildError, err.Error())) + return + } + res.Message = "操作成功" + ctx.Payload(res) + } +} + +type listMembersRequest struct { + Page int `form:"page"` + PageSize int `form:"page_size"` +} +type memberItem struct { + ID int64 `json:"id"` + UserID int64 `json:"user_id"` + Role string `json:"role"` + StartTime string `json:"start_time"` +} +type listMembersResponse struct { + Page int `json:"page"` + PageSize int `json:"page_size"` + Total int64 `json:"total"` + List []memberItem `json:"list"` +} + +// ListGuildMembers 工会成员列表 +// @Summary 查看工会成员 +// @Description 查看指定工会的成员列表 +// @Tags APP端.工会 +// @Accept json +// @Produce json +// @Param guild_id path integer true "工会ID" +// @Param page query int true "页码" default(1) +// @Param page_size query int true "每页数量,最多100" default(20) +// @Success 200 {object} listMembersResponse +// @Failure 400 {object} code.Failure +// @Router /api/app/guilds/{guild_id}/members [get] +func (h *handler) ListGuildMembers() core.HandlerFunc { + return func(ctx core.Context) { + req := new(listMembersRequest) + res := new(listMembersResponse) + if err := ctx.ShouldBindForm(req); err != nil { + ctx.AbortWithError(core.Error(http.StatusBadRequest, code.ParamBindError, validation.Error(err))) + return + } + guildID, err := strconv.ParseInt(ctx.Param("guild_id"), 10, 64) + if err != nil { + ctx.AbortWithError(core.Error(http.StatusBadRequest, code.ParamBindError, "未传递工会ID")) + return + } + items, total, err := h.guild.ListMembers(ctx.RequestContext(), guildID, req.Page, req.PageSize) + if err != nil { + ctx.AbortWithError(core.Error(http.StatusBadRequest, code.ListGuildMembersError, err.Error())) + return + } + res.Page = req.Page + res.PageSize = req.PageSize + res.Total = total + res.List = make([]memberItem, len(items)) + for i, v := range items { + res.List[i] = memberItem{ID: v.ID, UserID: v.UserID, Role: v.Role, StartTime: v.StartTime.Format("2006-01-02 15:04:05")} + } + ctx.Payload(res) + } +} diff --git a/internal/api/keyword/kenword.go b/internal/api/keyword/kenword.go deleted file mode 100644 index 2a67213..0000000 --- a/internal/api/keyword/kenword.go +++ /dev/null @@ -1,21 +0,0 @@ -package keyword - -import ( - "mini-chat/internal/pkg/logger" - "mini-chat/internal/repository/mysql" - "mini-chat/internal/repository/mysql/dao" -) - -type handler struct { - logger logger.CustomLogger - writeDB *dao.Query - readDB *dao.Query -} - -func New(logger logger.CustomLogger, db mysql.Repo) *handler { - return &handler{ - logger: logger, - writeDB: dao.Use(db.GetDbW()), - readDB: dao.Use(db.GetDbR()), - } -} diff --git a/internal/api/keyword/keyword_create.go b/internal/api/keyword/keyword_create.go deleted file mode 100644 index 86a9612..0000000 --- a/internal/api/keyword/keyword_create.go +++ /dev/null @@ -1,82 +0,0 @@ -package keyword - -import ( - "fmt" - "net/http" - "strings" - "time" - - "mini-chat/internal/code" - "mini-chat/internal/pkg/core" - "mini-chat/internal/pkg/validation" - "mini-chat/internal/repository/mysql/model" -) - -type createKeywordRequest struct { - AppID string `json:"app_id" binding:"required"` // 小程序ID - Keyword string `json:"keyword" binding:"required"` // 关键字 -} - -type createKeywordResponse struct { - Message string `json:"message"` // 提示信息 - ID int32 `json:"id"` // 关键字ID -} - -// CreateKeyword 添加意图关键字 -// @Summary 添加意图关键字 -// @Description 添加意图关键字 -// @Tags 管理端.意图关键字 -// @Accept json -// @Produce json -// @Param RequestBody body createKeywordRequest true "请求参数" -// @Success 200 {object} createKeywordResponse -// @Failure 400 {object} code.Failure -// @Router /api/admin/app/keyword [post] -// @Security LoginVerifyToken -func (h *handler) CreateKeyword() core.HandlerFunc { - return func(ctx core.Context) { - req := new(createKeywordRequest) - res := new(createKeywordResponse) - if err := ctx.ShouldBindJSON(req); err != nil { - ctx.AbortWithError(core.Error( - http.StatusBadRequest, - code.ParamBindError, - validation.Error(err)), - ) - return - } - - req.Keyword = strings.TrimSpace(req.Keyword) - - // 验证关键字是否已存在 - if _, err := h.readDB.AppKeyword.WithContext(ctx.RequestContext()). - Where(h.readDB.AppKeyword.AppID.Eq(req.AppID)). - Where(h.readDB.AppKeyword.Keyword.Eq(req.Keyword)). - First(); err == nil { - ctx.AbortWithError(core.Error( - http.StatusBadRequest, - code.CreateKeywordError, - fmt.Sprintf("%s: 该关键字(%s)已存在", code.Text(code.CreateKeywordError), req.Keyword)), - ) - return - } - - createData := new(model.AppKeyword) - createData.AppID = req.AppID - createData.Keyword = req.Keyword - createData.CreatedUser = ctx.SessionUserInfo().UserName - createData.CreatedAt = time.Now() - - if err := h.writeDB.AppKeyword.WithContext(ctx.RequestContext()).Create(createData); err != nil { - ctx.AbortWithError(core.Error( - http.StatusBadRequest, - code.CreateKeywordError, - fmt.Sprintf("%s: %s", code.Text(code.CreateKeywordError), err.Error()), - )) - } - - res.Message = "操作成功" - res.ID = createData.ID - ctx.Payload(res) - } -} diff --git a/internal/api/keyword/keyword_delete.go b/internal/api/keyword/keyword_delete.go deleted file mode 100644 index 6e9bed1..0000000 --- a/internal/api/keyword/keyword_delete.go +++ /dev/null @@ -1,86 +0,0 @@ -package keyword - -import ( - "fmt" - "net/http" - "strconv" - - "mini-chat/internal/code" - "mini-chat/internal/pkg/core" - - "gorm.io/gorm" -) - -type deleteKeywordResponse struct { - Message string `json:"message"` // 提示信息 -} - -// DeleteKeyword 删除意图关键字 -// @Summary 删除意图关键字 -// @Description 删除意图关键字 -// @Tags 管理端.意图关键字 -// @Accept json -// @Produce json -// @Param id path string true "编号ID" -// @Success 200 {object} deleteKeywordResponse -// @Failure 400 {object} code.Failure -// @Router /api/admin/app/keyword/{id} [delete] -// @Security LoginVerifyToken -func (h *handler) DeleteKeyword() core.HandlerFunc { - return func(ctx core.Context) { - ID, err := strconv.Atoi(ctx.Param("id")) - if err != nil { - ctx.AbortWithError(core.Error( - http.StatusBadRequest, - code.ParamBindError, - "未传递编号ID。"), - ) - return - } - - info, err := h.readDB.AppKeyword.WithContext(ctx.RequestContext()). - Where(h.readDB.AppKeyword.ID.Eq(int32(ID))). - First() - if err != nil && err != gorm.ErrRecordNotFound { - ctx.AbortWithError(core.Error( - http.StatusBadRequest, - code.DeleteKeywordError, - fmt.Sprintf("%s: %s", code.Text(code.DeleteKeywordError), err.Error())), - ) - return - } - - if info == nil { - ctx.AbortWithError(core.Error( - http.StatusBadRequest, - code.DeleteKeywordError, - fmt.Sprintf("%s: 编号(%d)不存在。", code.Text(code.DeleteKeywordError), ID)), - ) - return - } - - if _, err := h.writeDB.AppKeyword.WithContext(ctx.RequestContext()). - Where(h.writeDB.AppKeyword.ID.Eq(int32(ID))). - Delete(); err != nil { - ctx.AbortWithError(core.Error( - http.StatusBadRequest, - code.DeleteKeywordError, - fmt.Sprintf("%s: %s", code.Text(code.DeleteKeywordError), err.Error())), - ) - } - - if _, err := h.writeDB.AppKeywordReply.WithContext(ctx.RequestContext()). - Where(h.writeDB.AppKeywordReply.KeywordID.Eq(int32(ID))). - Delete(); err != nil { - ctx.AbortWithError(core.Error( - http.StatusBadRequest, - code.DeleteKeywordError, - fmt.Sprintf("%s: %s", code.Text(code.DeleteKeywordError), err.Error())), - ) - } - - res := new(deleteKeywordResponse) - res.Message = "操作成功" - ctx.Payload(res) - } -} diff --git a/internal/api/keyword/keyword_list.go b/internal/api/keyword/keyword_list.go deleted file mode 100644 index c85958f..0000000 --- a/internal/api/keyword/keyword_list.go +++ /dev/null @@ -1,212 +0,0 @@ -package keyword - -import ( - "fmt" - "net/http" - "strings" - - "mini-chat/internal/code" - "mini-chat/internal/pkg/core" - "mini-chat/internal/pkg/timeutil" - "mini-chat/internal/pkg/validation" - - "gorm.io/gorm" -) - -type keywordPageListRequest struct { - AppID string `form:"app_id" binding:"required"` // 小程序ID - Keyword string `form:"keyword"` // 意图关键字 - Page int `form:"page"` // 当前页码,默认为第一页 - PageSize int `form:"page_size"` // 每页返回的数据量 -} - -type keywordListData struct { - ID int32 `json:"id"` // 关键字编号 - AppID string `json:"app_id"` // 小程序ID - Keyword string `json:"keyword"` // 意图关键字 - CreatedUser string `json:"created_user"` // 创建人 - CreatedAt string `json:"created_at"` // 创建时间 - UpdatedUser string `json:"updated_user"` // 更新人 - UpdatedAt string `json:"updated_at"` // 更新时间 - MaterialTypeCount string `json:"material_type_count"` // 素材类型数量 -} - -type keywordPageListResponse struct { - Page int `json:"page"` // 当前页码 - PageSize int `json:"page_size"` // 每页返回的数据量 - Total int64 `json:"total"` // 符合查询条件的总记录数 - List []keywordListData `json:"list"` -} - -// KeywordPageList 获取意图关键字列表 -// @Summary 获取意图关键字列表 -// @Description 获取意图关键字列表 -// @Tags 管理端.意图关键字 -// @Accept json -// @Produce json -// @Param app_id query int true "小程序ID" -// @Param keyword query string false "意图关键字" -// @Param page query int true "当前页码" default(1) -// @Param page_size query int true "每页返回的数据量,最多 100 条" default(20) -// @Success 200 {object} keywordPageListResponse -// @Failure 400 {object} code.Failure -// @Router /api/admin/app/keywords [get] -// @Security LoginVerifyToken -func (h *handler) KeywordPageList() core.HandlerFunc { - return func(ctx core.Context) { - req := new(keywordPageListRequest) - res := new(keywordPageListResponse) - if err := ctx.ShouldBindForm(req); err != nil { - ctx.AbortWithError(core.Error( - http.StatusBadRequest, - code.ParamBindError, - validation.Error(err)), - ) - return - } - - if req.Page == 0 { - req.Page = 1 - } - - if req.PageSize == 0 { - req.PageSize = 20 - } - - if req.PageSize > 100 { - ctx.AbortWithError(core.Error( - http.StatusBadRequest, - code.ListKeywordError, - fmt.Sprintf("%s: 一次最多只能查询 100 条", code.Text(code.ListKeywordError)), - )) - return - } - - query := h.readDB.AppKeyword.WithContext(ctx.RequestContext()) - query = query.Where(h.readDB.AppKeyword.AppID.Eq(req.AppID)) - - if req.Keyword != "" { - query = query.Where(h.readDB.AppKeyword.Keyword.Like(fmt.Sprintf("%%%s%%", req.Keyword))) - } - - listQueryDB := query.Session(&gorm.Session{}) - countQueryDB := query.Session(&gorm.Session{}) - - resultData, err := listQueryDB. - Order(h.readDB.AppKeyword.ID.Desc()). - Limit(req.PageSize). - Offset((req.Page - 1) * req.PageSize). - Find() - if err != nil { - ctx.AbortWithError(core.Error( - http.StatusBadRequest, - code.ListKeywordError, - fmt.Sprintf("%s:%s", code.Text(code.ListKeywordError), err.Error())), - ) - return - } - - count, err := countQueryDB.Count() - if err != nil { - ctx.AbortWithError(core.Error( - http.StatusBadRequest, - code.ListKeywordError, - fmt.Sprintf("%s:%s", code.Text(code.ListKeywordError), err.Error())), - ) - return - } - - res.Page = req.Page - res.PageSize = req.PageSize - res.Total = count - res.List = make([]keywordListData, len(resultData)) - - var keywordIDs []int32 - - for _, v := range resultData { - keywordIDs = append(keywordIDs, v.ID) - } - - keywordIDMaterialTypeCountMap, err := h.contactMaterialTypeCount(keywordIDs) - if err != nil { - ctx.AbortWithError(core.Error( - http.StatusBadRequest, - code.ListKeywordError, - fmt.Sprintf("%s:%s", code.Text(code.ListKeywordError), err.Error())), - ) - return - } - - for k, v := range resultData { - res.List[k] = keywordListData{ - ID: v.ID, - AppID: v.AppID, - Keyword: v.Keyword, - CreatedUser: v.CreatedUser, - CreatedAt: timeutil.FriendlyTime(v.CreatedAt), - UpdatedUser: v.UpdatedUser, - UpdatedAt: timeutil.FriendlyTime(v.UpdatedAt), - MaterialTypeCount: keywordIDMaterialTypeCountMap[v.ID], - } - } - - ctx.Payload(res) - } -} - -func (h *handler) contactMaterialTypeCount(keywordIDs []int32) (map[int32]string, error) { - var results []struct { - KeywordID int32 - Type int - Count int `db:"count"` - } - - if err := h.readDB.AppKeywordReply. - Select(h.readDB.AppKeywordReply.KeywordID, h.readDB.AppKeywordReply.Type, h.readDB.AppKeywordReply.ID.Count().As("count")). - Where(h.readDB.AppKeywordReply.KeywordID.In(keywordIDs...)). - Group(h.readDB.AppKeywordReply.KeywordID, h.readDB.AppKeywordReply.Type). - Scan(&results); err != nil { - return nil, err - } - - keywordIDMap := make(map[int32]string) - - typeMap := map[int]string{ - 1: "文本", - 2: "图片", - 3: "语音条", - 4: "视频", - 5: "小程序", - 6: "地理位置", - 7: "链接", - 8: "GIF图", - 9: "名片", - 10: "文件", - 11: "转人工", - } - - for _, result := range results { - keywordID := result.KeywordID - typeDesc := fmt.Sprintf("%d条%s", result.Count, typeMap[result.Type]) - - if currentString, exists := keywordIDMap[keywordID]; exists { - keywordIDMap[keywordID] = currentString + "、" + typeDesc + "、" - } else { - keywordIDMap[keywordID] = "1 组话术(共" + typeDesc - } - } - - for keywordID, resultString := range keywordIDMap { - // 查找最后一个逗号的位置 - commaIndex := strings.LastIndex(resultString, "、") - - // 如果找到逗号,替换为右括号 - if commaIndex != -1 { - keywordIDMap[keywordID] = resultString[:commaIndex] + ")" - } else { - keywordIDMap[keywordID] += ")" - } - } - - return keywordIDMap, nil -} diff --git a/internal/api/keyword/keyword_material_create.go b/internal/api/keyword/keyword_material_create.go deleted file mode 100644 index 85ee9e6..0000000 --- a/internal/api/keyword/keyword_material_create.go +++ /dev/null @@ -1,143 +0,0 @@ -package keyword - -import ( - "fmt" - "net/http" - "strconv" - "time" - - "mini-chat/internal/code" - "mini-chat/internal/pkg/core" - "mini-chat/internal/pkg/validation" - "mini-chat/internal/repository/mysql/model" - - "gorm.io/gorm" -) - -type keywordMaterial struct { - Type int32 `json:"type" binding:"required"` // 素材类型(1:文本 2:图片) - Content string `json:"content" binding:"required"` // 素材内容 - IntervalSeconds int32 `json:"interval_seconds" binding:"required"` // 发送间隔时间(单位:秒) -} - -type createKeywordMaterialRequest struct { - MaterialList []keywordMaterial `json:"material_list" binding:"required"` // 素材列表 -} - -type createKeywordMaterialResponse struct { - Message string `json:"message"` // 提示信息 -} - -// CreateKeywordMaterial 配置意图关键字素材 -// @Summary 配置意图关键字素材 -// @Description 配置意图关键字素材 -// @Tags 管理端.意图关键字 -// @Accept json -// @Produce json -// @Param id path string true "编号ID" -// @Param RequestBody body createKeywordMaterialRequest true "请求参数" -// @Success 200 {object} createKeywordMaterialResponse -// @Failure 400 {object} code.Failure -// @Router /api/admin/app/keyword/material/{id} [post] -// @Security LoginVerifyToken -func (h *handler) CreateKeywordMaterial() core.HandlerFunc { - return func(ctx core.Context) { - req := new(createKeywordMaterialRequest) - res := new(createKeywordMaterialResponse) - if err := ctx.ShouldBindJSON(req); err != nil { - ctx.AbortWithError(core.Error( - http.StatusBadRequest, - code.ParamBindError, - validation.Error(err)), - ) - return - } - - ID, err := strconv.Atoi(ctx.Param("id")) - if err != nil { - ctx.AbortWithError(core.Error( - http.StatusBadRequest, - code.ParamBindError, - "未传递编号ID。"), - ) - return - } - - if len(req.MaterialList) == 0 { - ctx.AbortWithError(core.Error( - http.StatusBadRequest, - code.CreateKeywordMaterialError, - fmt.Sprintf("%s: 未配置素材", code.Text(code.CreateKeywordMaterialError))), - ) - return - } - - info, err := h.readDB.AppKeyword.WithContext(ctx.RequestContext()). - Where(h.readDB.AppKeyword.ID.Eq(int32(ID))). - First() - if err != nil && err != gorm.ErrRecordNotFound { - ctx.AbortWithError(core.Error( - http.StatusBadRequest, - code.CreateKeywordMaterialError, - fmt.Sprintf("%s: %s", code.Text(code.CreateKeywordMaterialError), err.Error())), - ) - return - } - - if info == nil { - ctx.AbortWithError(core.Error( - http.StatusBadRequest, - code.CreateKeywordMaterialError, - fmt.Sprintf("%s: 意图关键字编号(%d)不存在。", code.Text(code.CreateKeywordMaterialError), ID)), - ) - return - } - - // 先删除旧数据 - if _, err := h.writeDB.AppKeywordReply.WithContext(ctx.RequestContext()). - Where(h.writeDB.AppKeywordReply.KeywordID.Eq(int32(ID))). - Delete(); err != nil { - ctx.AbortWithError(core.Error( - http.StatusBadRequest, - code.CreateKeywordMaterialError, - fmt.Sprintf("%s: %s", code.Text(code.CreateKeywordMaterialError), err.Error())), - ) - return - } - - var keywordMaterials []*model.AppKeywordReply - for i := 0; i < len(req.MaterialList); i++ { - if req.MaterialList[i].Type == 0 || req.MaterialList[i].Content == "" || req.MaterialList[i].IntervalSeconds == 0 { - ctx.AbortWithError(core.Error( - http.StatusBadRequest, - code.CreateKeywordMaterialError, - fmt.Sprintf("%s: 配置素材数据不完整,请检查。", code.Text(code.CreateKeywordMaterialError))), - ) - return - } - - keywordMaterials = append(keywordMaterials, &model.AppKeywordReply{ - KeywordID: int32(ID), - AppID: info.AppID, - Type: req.MaterialList[i].Type, - Content: req.MaterialList[i].Content, - IntervalSeconds: req.MaterialList[i].IntervalSeconds, - CreatedUser: ctx.SessionUserInfo().UserName, - CreatedAt: time.Now(), - }) - } - - // 批量插入 - if err := h.writeDB.AppKeywordReply.WithContext(ctx.RequestContext()).CreateInBatches(keywordMaterials, len(req.MaterialList)); err != nil { - ctx.AbortWithError(core.Error( - http.StatusBadRequest, - code.CreateKeywordMaterialError, - fmt.Sprintf("%s: %s", code.Text(code.CreateKeywordMaterialError), err.Error())), - ) - return - } - - res.Message = "操作成功" - ctx.Payload(res) - } -} diff --git a/internal/api/keyword/keyword_material_list.go b/internal/api/keyword/keyword_material_list.go deleted file mode 100644 index 3cd3a04..0000000 --- a/internal/api/keyword/keyword_material_list.go +++ /dev/null @@ -1,130 +0,0 @@ -package keyword - -import ( - "fmt" - "net/http" - - "mini-chat/internal/code" - "mini-chat/internal/pkg/core" - "mini-chat/internal/pkg/timeutil" - "mini-chat/internal/pkg/validation" - - "gorm.io/gorm" -) - -type keywordMaterialPageListRequest struct { - KeywordID int32 `form:"keyword_id" binding:"required"` // 意图关键字ID - Page int `form:"page"` // 当前页码,默认为第一页 - PageSize int `form:"page_size"` // 每页返回的数据量 -} - -type keywordMaterialListData struct { - ID int32 `json:"id"` // 主键ID - KeywordID int32 `json:"keyword_id"` // 意图关键字ID - Type int32 `json:"type"` // 素材类型(1:文本 2:图片) - Content string `json:"content"` // 素材内容 - IntervalSeconds int32 `json:"interval_seconds"` // 素材发送间隔时间(单位:秒) - CreatedUser string `json:"created_user"` // 创建人 - CreatedAt string `json:"created_at"` // 创建时间 -} - -type keywordMaterialPageListResponse struct { - Page int `json:"page"` // 当前页码 - PageSize int `json:"page_size"` // 每页返回的数据量 - Total int64 `json:"total"` // 符合查询条件的总记录数 - List []keywordMaterialListData `json:"list"` -} - -// KeywordMaterialPageList 获取意图关键字素材列表 -// @Summary 获取意图关键字素材列表 -// @Description 获取意图关键字素材列表 -// @Tags 管理端.意图关键字 -// @Accept json -// @Produce json -// @Param keyword_id query int true "意图关键字ID" -// @Param page query int true "当前页码" default(1) -// @Param page_size query int true "每页返回的数据量,最多 100 条" default(20) -// @Success 200 {object} keywordMaterialPageListResponse -// @Failure 400 {object} code.Failure -// @Router /api/admin/app/keyword/materials [get] -// @Security LoginVerifyToken -func (h *handler) KeywordMaterialPageList() core.HandlerFunc { - return func(ctx core.Context) { - req := new(keywordMaterialPageListRequest) - res := new(keywordMaterialPageListResponse) - if err := ctx.ShouldBindForm(req); err != nil { - ctx.AbortWithError(core.Error( - http.StatusBadRequest, - code.ParamBindError, - validation.Error(err)), - ) - return - } - - if req.Page == 0 { - req.Page = 1 - } - - if req.PageSize == 0 { - req.PageSize = 20 - } - - if req.PageSize > 100 { - ctx.AbortWithError(core.Error( - http.StatusBadRequest, - code.ListKeywordMaterialError, - fmt.Sprintf("%s: 一次最多只能查询 100 条", code.Text(code.ListKeywordMaterialError)), - )) - return - } - - query := h.readDB.AppKeywordReply.WithContext(ctx.RequestContext()) - query = query.Where(h.readDB.AppKeywordReply.KeywordID.Eq(req.KeywordID)) - - listQueryDB := query.Session(&gorm.Session{}) - countQueryDB := query.Session(&gorm.Session{}) - - resultData, err := listQueryDB. - Order(h.readDB.AppKeywordReply.ID.Asc()). - Limit(req.PageSize). - Offset((req.Page - 1) * req.PageSize). - Find() - if err != nil { - ctx.AbortWithError(core.Error( - http.StatusBadRequest, - code.ListKeywordMaterialError, - fmt.Sprintf("%s:%s", code.Text(code.ListKeywordMaterialError), err.Error())), - ) - return - } - - count, err := countQueryDB.Count() - if err != nil { - ctx.AbortWithError(core.Error( - http.StatusBadRequest, - code.ListKeywordMaterialError, - fmt.Sprintf("%s:%s", code.Text(code.ListKeywordMaterialError), err.Error())), - ) - return - } - - res.Page = req.Page - res.PageSize = req.PageSize - res.Total = count - res.List = make([]keywordMaterialListData, len(resultData)) - - for k, v := range resultData { - res.List[k] = keywordMaterialListData{ - ID: v.ID, - KeywordID: v.KeywordID, - Type: v.Type, - Content: v.Content, - IntervalSeconds: v.IntervalSeconds, - CreatedUser: v.CreatedUser, - CreatedAt: timeutil.FriendlyTime(v.CreatedAt), - } - } - - ctx.Payload(res) - } -} diff --git a/internal/api/keyword/keyword_material_modify.go b/internal/api/keyword/keyword_material_modify.go deleted file mode 100644 index 6bffa60..0000000 --- a/internal/api/keyword/keyword_material_modify.go +++ /dev/null @@ -1,103 +0,0 @@ -package keyword - -import ( - "fmt" - "net/http" - "strconv" - "time" - - "mini-chat/internal/code" - "mini-chat/internal/pkg/core" - "mini-chat/internal/pkg/validation" - - "gorm.io/gorm" -) - -type modifyKeywordMaterialRequest struct { - Type int32 `json:"type" binding:"required"` // 素材类型(1:文本 2:图片) - Content string `json:"content" binding:"required"` // 素材内容 - IntervalSeconds int32 `json:"interval_seconds" binding:"required"` // 发送间隔时间(单位:秒) -} - -type modifyKeywordMaterialResponse struct { - Message string `json:"message"` // 提示信息 -} - -// ModifyKeywordMaterial 修改意图关键字素材 -// @Summary 修改意图关键字素材 -// @Description 修改意图关键字素材 -// @Tags 管理端.意图关键字 -// @Accept json -// @Produce json -// @Param id path string true "素材编号ID" -// @Param RequestBody body modifyKeywordMaterialRequest true "请求参数" -// @Success 200 {object} modifyKeywordMaterialResponse -// @Failure 400 {object} code.Failure -// @Router /api/admin/app/keyword/material/{id} [put] -// @Security LoginVerifyToken -func (h *handler) ModifyKeywordMaterial() core.HandlerFunc { - return func(ctx core.Context) { - req := new(modifyKeywordMaterialRequest) - res := new(modifyKeywordMaterialResponse) - if err := ctx.ShouldBindJSON(req); err != nil { - ctx.AbortWithError(core.Error( - http.StatusBadRequest, - code.ParamBindError, - validation.Error(err)), - ) - return - } - - ID, err := strconv.Atoi(ctx.Param("id")) - if err != nil { - ctx.AbortWithError(core.Error( - http.StatusBadRequest, - code.ParamBindError, - "未传递编号ID。"), - ) - return - } - - info, err := h.readDB.AppKeywordReply.WithContext(ctx.RequestContext()). - Where(h.readDB.AppKeywordReply.ID.Eq(int32(ID))). - First() - if err != nil && err != gorm.ErrRecordNotFound { - ctx.AbortWithError(core.Error( - http.StatusBadRequest, - code.ModifyKeywordMaterialError, - fmt.Sprintf("%s: %s", code.Text(code.ModifyKeywordMaterialError), err.Error())), - ) - return - } - - if info == nil { - ctx.AbortWithError(core.Error( - http.StatusBadRequest, - code.ModifyKeywordMaterialError, - fmt.Sprintf("%s: 意图关键字素材编号(%d)不存在。", code.Text(code.ModifyKeywordMaterialError), ID)), - ) - return - } - - updateData := map[string]interface{}{ - "type": req.Type, - "content": req.Content, - "interval_seconds": req.IntervalSeconds, - "updated_user": ctx.SessionUserInfo().UserName, - "updated_at": time.Now(), - } - - if _, err := h.writeDB.AppKeywordReply.WithContext(ctx.RequestContext()). - Where(h.writeDB.AppKeywordReply.ID.Eq(int32(ID))). - Updates(updateData); err != nil { - ctx.AbortWithError(core.Error( - http.StatusBadRequest, - code.ModifyKeywordMaterialError, - fmt.Sprintf("%s: %s", code.Text(code.ModifyKeywordMaterialError), err.Error())), - ) - } - - res.Message = "操作成功" - ctx.Payload(res) - } -} diff --git a/internal/api/keyword/keyword_modify.go b/internal/api/keyword/keyword_modify.go deleted file mode 100644 index 1e08cca..0000000 --- a/internal/api/keyword/keyword_modify.go +++ /dev/null @@ -1,117 +0,0 @@ -package keyword - -import ( - "fmt" - "net/http" - "strconv" - "strings" - "time" - - "mini-chat/internal/code" - "mini-chat/internal/pkg/core" - "mini-chat/internal/pkg/validation" - - "gorm.io/gorm" -) - -type modifyKeywordRequest struct { - Keyword string `json:"keyword" binding:"required"` // 意图关键字 -} - -type modifyKeywordResponse struct { - Message string `json:"message"` // 提示信息 -} - -// ModifyKeyword 修改意图关键字 -// @Summary 修改意图关键字 -// @Description 修改意图关键字 -// @Tags 管理端.意图关键字 -// @Accept json -// @Produce json -// @Param id path string true "编号ID" -// @Param RequestBody body modifyKeywordRequest true "请求参数" -// @Success 200 {object} modifyKeywordResponse -// @Failure 400 {object} code.Failure -// @Router /api/admin/app/keyword/{id} [put] -// @Security LoginVerifyToken -func (h *handler) ModifyKeyword() core.HandlerFunc { - return func(ctx core.Context) { - req := new(modifyKeywordRequest) - res := new(modifyKeywordResponse) - if err := ctx.ShouldBindJSON(req); err != nil { - ctx.AbortWithError(core.Error( - http.StatusBadRequest, - code.ParamBindError, - validation.Error(err)), - ) - return - } - - ID, err := strconv.Atoi(ctx.Param("id")) - if err != nil { - ctx.AbortWithError(core.Error( - http.StatusBadRequest, - code.ParamBindError, - "未传递编号ID。"), - ) - return - } - - info, err := h.readDB.AppKeyword.WithContext(ctx.RequestContext()). - Where(h.readDB.AppKeyword.ID.Eq(int32(ID))). - First() - if err != nil && err != gorm.ErrRecordNotFound { - ctx.AbortWithError(core.Error( - http.StatusBadRequest, - code.ModifyKeywordError, - fmt.Sprintf("%s: %s", code.Text(code.ModifyKeywordError), err.Error())), - ) - return - } - - if info == nil { - ctx.AbortWithError(core.Error( - http.StatusBadRequest, - code.ModifyKeywordError, - fmt.Sprintf("%s: 编号(%d)不存在。", code.Text(code.ModifyKeywordError), ID)), - ) - return - } - - req.Keyword = strings.TrimSpace(req.Keyword) - - if info.Keyword != req.Keyword { - // 验证关键字是否已存在 - if _, err := h.readDB.AppKeyword.WithContext(ctx.RequestContext()). - Where(h.readDB.AppKeyword.AppID.Eq(info.AppID)). - Where(h.readDB.AppKeyword.Keyword.Eq(req.Keyword)). - First(); err == nil { - ctx.AbortWithError(core.Error( - http.StatusBadRequest, - code.ModifyKeywordError, - fmt.Sprintf("%s: 该关键字(%s)已存在", code.Text(code.ModifyKeywordError), req.Keyword)), - ) - return - } - } - - updateData := map[string]interface{}{ - "keyword": req.Keyword, - "updated_user": ctx.SessionUserInfo().UserName, - "updated_at": time.Now(), - } - - if _, err := h.writeDB.AppKeyword.WithContext(ctx.RequestContext()). - Where(h.writeDB.AppKeyword.ID.Eq(int32(ID))). - Updates(updateData); err != nil { - ctx.AbortWithError(core.Error( - http.StatusBadRequest, - code.ModifyKeywordError, - fmt.Sprintf("%s: %s", code.Text(code.ModifyKeywordError), err.Error())), - ) - } - - res.Message = "操作成功" - ctx.Payload(res) - } -} diff --git a/internal/api/message/message.go b/internal/api/message/message.go deleted file mode 100644 index 8c8dc4f..0000000 --- a/internal/api/message/message.go +++ /dev/null @@ -1,21 +0,0 @@ -package message - -import ( - "mini-chat/internal/pkg/logger" - "mini-chat/internal/repository/mysql" - "mini-chat/internal/repository/mysql/dao" -) - -type handler struct { - logger logger.CustomLogger - writeDB *dao.Query - readDB *dao.Query -} - -func New(logger logger.CustomLogger, db mysql.Repo) *handler { - return &handler{ - logger: logger, - writeDB: dao.Use(db.GetDbW()), - readDB: dao.Use(db.GetDbR()), - } -} diff --git a/internal/api/message/message_list_user.go b/internal/api/message/message_list_user.go deleted file mode 100644 index 3c47693..0000000 --- a/internal/api/message/message_list_user.go +++ /dev/null @@ -1,135 +0,0 @@ -package message - -import ( - "fmt" - "net/http" - - "mini-chat/internal/code" - "mini-chat/internal/pkg/core" - "mini-chat/internal/pkg/timeutil" - "mini-chat/internal/pkg/validation" - - "gorm.io/gorm" -) - -type appMessagePageListRequest struct { - AppID string `form:"app_id" binding:"required"` // 小程序ID - UserID string `form:"user_id" binding:"required"` // 用户ID - Page int `form:"page"` // 当前页码,默认为第一页 - PageSize int `form:"page_size"` // 每页返回的数据量 -} - -type listMessageData struct { - ID int32 `json:"id"` // 消息ID - SendTime string `json:"send_time"` // 发送时间 - SenderID string `json:"sender_id"` // 发送人ID - SenderName string `json:"sender_name"` // 发送人昵称 - ReceiverID string `json:"receiver_id"` // 接收人ID - Content string `json:"content"` // 消息内容 - MsgType int32 `json:"msg_type"` // 消息类型(1:文本 2:图片) -} - -type appMessagePageListResponse struct { - Page int `json:"page"` // 当前页码 - PageSize int `json:"page_size"` // 每页返回的数据量 - Total int64 `json:"total"` // 符合查询条件的总记录数 - List []listMessageData `json:"list"` -} - -// AppMessagePageList 获取消息日志 -// @Summary 获取消息日志 -// @Description 获取消息日志 -// @Tags 用户端 -// @Accept json -// @Produce json -// @Param app_id query string true "小程序ID" -// @Param user_id query string true "用户ID" -// @Param page query int true "当前页码" default(1) -// @Param page_size query int true "每页返回的数据量,最多 100 条" default(20) -// @Success 200 {object} appMessagePageListResponse -// @Failure 400 {object} code.Failure -// @Router /api/app/messages [get] -func (h *handler) AppMessagePageList() core.HandlerFunc { - return func(ctx core.Context) { - req := new(appMessagePageListRequest) - res := new(appMessagePageListResponse) - if err := ctx.ShouldBindForm(req); err != nil { - ctx.AbortWithError(core.Error( - http.StatusBadRequest, - code.ParamBindError, - validation.Error(err)), - ) - return - } - - if req.Page == 0 { - req.Page = 1 - } - - if req.PageSize == 0 { - req.PageSize = 20 - } - - if req.PageSize > 100 { - ctx.AbortWithError(core.Error( - http.StatusBadRequest, - code.ListMessageError, - fmt.Sprintf("%s: 一次最多只能查询 100 条", code.Text(code.ListMessageError)), - )) - return - } - - query := h.readDB.AppMessageLog.WithContext(ctx.RequestContext()). - Where(h.readDB.AppMessageLog.AppID.Eq(req.AppID)). - Where(h.readDB.AppMessageLog.SenderID.Eq(req.UserID)).Or(h.readDB.AppMessageLog.ReceiverID.Eq(req.UserID)) - - listQueryDB := query.Session(&gorm.Session{}) - countQueryDB := query.Session(&gorm.Session{}) - - // 计算分页偏移量 - offset := (req.Page - 1) * req.PageSize - - resultData, err := listQueryDB. - Order(h.readDB.AppMessageLog.SendTime.Desc()). - Offset(offset). - Limit(req.PageSize). - Find() - if err != nil { - ctx.AbortWithError(core.Error( - http.StatusBadRequest, - code.ListMessageError, - fmt.Sprintf("%s:%s", code.Text(code.ListMessageError), err.Error())), - ) - return - } - - count, err := countQueryDB.Count() - if err != nil { - ctx.AbortWithError(core.Error( - http.StatusBadRequest, - code.ListMessageError, - fmt.Sprintf("%s:%s", code.Text(code.ListMessageError), err.Error())), - ) - return - } - - res.Page = req.Page - res.PageSize = req.PageSize - res.Total = count - res.List = make([]listMessageData, len(resultData)) - - for k, v := range resultData { - res.List[k] = listMessageData{ - ID: v.ID, - SendTime: timeutil.FriendlyTime(v.SendTime), - SenderID: v.SenderID, - SenderName: v.SenderName, - ReceiverID: v.ReceiverID, - Content: v.Content, - MsgType: v.MsgType, - } - } - - ctx.Payload(res) - } -} diff --git a/internal/api/message/message_send_user.go b/internal/api/message/message_send_user.go deleted file mode 100644 index 8d40ac0..0000000 --- a/internal/api/message/message_send_user.go +++ /dev/null @@ -1,128 +0,0 @@ -package message - -import ( - "encoding/json" - "fmt" - "net/http" - "time" - - "mini-chat/internal/code" - "mini-chat/internal/pkg/core" - "mini-chat/internal/pkg/validation" - "mini-chat/internal/repository/mysql/model" - "mini-chat/internal/services" - - "gorm.io/gorm" -) - -type userSendMessageRequest struct { - AppID string `json:"app_id" binding:"required"` // 小程序ID - FormUserID string `json:"from_user_id" binding:"required"` // 发送用户的ID - FormUserName string `json:"from_user_name" binding:"required"` // 发送用户的昵称 - MsgType int32 `json:"msg_type" binding:"required"` // 消息类型(1:文本 2:图片) - Content string `json:"content" binding:"required"` // 内容 -} - -type userSendMessageResponse struct { - Message string `json:"message"` // 提示信息 -} - -// UserSendMessage 用户发送消息 -// @Summary 用户发送消息 -// @Description 用户发送消息 -// @Tags 用户端 -// @Accept json -// @Produce json -// @Param RequestBody body userSendMessageRequest true "请求参数" -// @Success 200 {object} userSendMessageResponse -// @Failure 400 {object} code.Failure -// @Router /api/app/send_message [post] -func (h *handler) UserSendMessage() core.HandlerFunc { - return func(ctx core.Context) { - req := new(userSendMessageRequest) - res := new(userSendMessageResponse) - if err := ctx.ShouldBindJSON(req); err != nil { - ctx.AbortWithError(core.Error( - http.StatusBadRequest, - code.ParamBindError, - validation.Error(err)), - ) - return - } - - createData := new(model.AppMessageLog) - createData.AppID = req.AppID - createData.SenderID = req.FormUserID - createData.SenderName = req.FormUserName - createData.Content = req.Content - createData.ReceiverID = "888888" - createData.MsgType = req.MsgType - createData.SendTime = time.Now() - createData.CreatedAt = time.Now() - if err := h.writeDB.AppMessageLog.WithContext(ctx.RequestContext()).Create(createData); err != nil { - ctx.AbortWithError(core.Error( - http.StatusBadRequest, - code.SendMessageError, - fmt.Sprintf("%s: %s", code.Text(code.SendMessageError), err.Error()), - )) - } - - time.AfterFunc(1*time.Second, func() { - if req.MsgType == 1 { // 自动回复逻辑 - textMsg := new(services.TextMessage) - if err := json.Unmarshal([]byte(req.Content), &textMsg); err != nil { - h.logger.Error(fmt.Sprintf("AppID(%s),用户ID(%s),发送内容(%s) JSON解析失败: %s", req.AppID, req.FormUserID, req.Content, err.Error())) - return - } - - keyword, err := h.readDB.AppKeyword. - Where(h.readDB.AppKeyword.AppID.Eq(req.AppID)). - Where(h.readDB.AppKeyword.Keyword.Eq(textMsg.Message)). - Order(h.readDB.AppKeyword.ID.Asc()). - First() - if err != nil && err != gorm.ErrRecordNotFound { - h.logger.Error(fmt.Sprintf("AppID(%s),用户ID(%s),发送内容(%s) 获取意图关键字失败: %s", req.AppID, req.FormUserID, req.Content, err.Error())) - return - } - - if keyword == nil { - return - } - - // 获取群组关键字回复信息 - reply, err := h.readDB.AppKeywordReply. - Where(h.readDB.AppKeywordReply.AppID.Eq(req.AppID)). - Where(h.readDB.AppKeywordReply.KeywordID.Eq(keyword.ID)). - Find() - if err != nil && err != gorm.ErrRecordNotFound { - h.logger.Error(fmt.Sprintf("AppID(%s),用户ID(%s),发送内容(%s) 获取群组关键字回复失败: %s", req.AppID, req.FormUserID, req.Content, err.Error())) - return - } - - if len(reply) == 0 { - return - } - - for _, v := range reply { - time.Sleep(time.Duration(v.IntervalSeconds) * time.Second) - - replyData := new(model.AppMessageLog) - replyData.AppID = req.AppID - replyData.SenderID = "888888" - replyData.SenderName = "平台" - replyData.Content = v.Content - replyData.ReceiverID = req.FormUserID - replyData.MsgType = v.Type - replyData.SendTime = time.Now() - replyData.CreatedAt = time.Now() - if err := h.writeDB.AppMessageLog.Create(replyData); err != nil { - h.logger.Error(fmt.Sprintf("AppID(%s),用户ID(%s),发送内容(%s) 回复关键字回复失败: %s", req.AppID, req.FormUserID, req.Content, err.Error())) - } - } - } - }) - - res.Message = "操作成功" - ctx.Payload(res) - } -} diff --git a/internal/api/upload/upload.go b/internal/api/upload/upload.go deleted file mode 100644 index 21cbacb..0000000 --- a/internal/api/upload/upload.go +++ /dev/null @@ -1,21 +0,0 @@ -package upload - -import ( - "mini-chat/internal/pkg/logger" - "mini-chat/internal/repository/mysql" - "mini-chat/internal/repository/mysql/dao" -) - -type handler struct { - logger logger.CustomLogger - writeDB *dao.Query - readDB *dao.Query -} - -func New(logger logger.CustomLogger, db mysql.Repo) *handler { - return &handler{ - logger: logger, - writeDB: dao.Use(db.GetDbW()), - readDB: dao.Use(db.GetDbR()), - } -} diff --git a/internal/api/upload/upload_image.go b/internal/api/upload/upload_image.go deleted file mode 100755 index 1b4c476..0000000 --- a/internal/api/upload/upload_image.go +++ /dev/null @@ -1,90 +0,0 @@ -package upload - -import ( - "fmt" - "net/http" - "strings" - - "mini-chat/configs" - "mini-chat/internal/code" - "mini-chat/internal/pkg/core" - "mini-chat/internal/pkg/idgen" -) - -type uploadImageResponse struct { - RealImageUrl string `json:"real_image_url"` // 真实图片地址 - PreviewImageUrl string `json:"preview_image_url"` // 可预览图片地址 -} - -// UploadImage 上传图片 -// @Summary 上传图片 -// @Description 上传图片 -// @Tags 通用 -// @Accept multipart/form-data -// @Produce json -// @Param file formData file true "选择文件" -// @Success 200 {object} uploadImageResponse -// @Failure 400 {object} code.Failure -// @Router /api/admin/upload/image [post] -func (h *handler) UploadImage() core.HandlerFunc { - return func(ctx core.Context) { - file, err := ctx.FormFile("file") - if err != nil { - ctx.AbortWithError(core.Error( - http.StatusBadRequest, - code.UploadError, - fmt.Sprintf("%s: %s", code.Text(code.UploadError), err.Error()), - )) - return - } - - if file == nil { - ctx.AbortWithError(core.Error( - http.StatusBadRequest, - code.UploadError, - fmt.Sprintf("%s: %s", code.Text(code.UploadError), "缺少 file 文件"), - )) - return - } - - // 校验文件后缀 - extension := "" - if dot := strings.LastIndexByte(file.Filename, '.'); dot != -1 { - extension = file.Filename[dot+1:] - } - - allowedExtensions := map[string]bool{ - "jpg": true, - "jpeg": true, - "png": true, - "gif": true, - } - - if !allowedExtensions[strings.ToLower(extension)] { - ctx.AbortWithError(core.Error( - http.StatusBadRequest, - code.UploadError, - fmt.Sprintf("%s: %s", code.Text(code.UploadError), "文件后缀应为 .jpg、.jpeg、.png、.gif"), - )) - return - } - - // 保存文件 - imagePath := fmt.Sprintf("image/%s.%s", idgen.GenerateUniqueID(), strings.ToLower(extension)) - filePath := fmt.Sprintf("%s/%s", configs.GetResourcesFilePath(), imagePath) - if err := ctx.SaveUploadedFile(file, filePath); err != nil { - ctx.AbortWithError(core.Error( - http.StatusBadRequest, - code.UploadError, - fmt.Sprintf("%s: %s", code.Text(code.UploadError), err.Error()), - )) - return - } - - res := new(uploadImageResponse) - res.RealImageUrl = filePath - res.PreviewImageUrl = fmt.Sprintf("resources/%s", imagePath) - - ctx.Payload(res) - } -} diff --git a/internal/api/user/app.go b/internal/api/user/app.go new file mode 100644 index 0000000..56361a0 --- /dev/null +++ b/internal/api/user/app.go @@ -0,0 +1,19 @@ +package app + +import ( + "bindbox-game/internal/pkg/logger" + "bindbox-game/internal/repository/mysql" + "bindbox-game/internal/repository/mysql/dao" + usersvc "bindbox-game/internal/service/user" +) + +type handler struct { + logger logger.CustomLogger + writeDB *dao.Query + readDB *dao.Query + user usersvc.Service +} + +func New(logger logger.CustomLogger, db mysql.Repo) *handler { + return &handler{logger: logger, writeDB: dao.Use(db.GetDbW()), readDB: dao.Use(db.GetDbR()), user: usersvc.New(logger, db)} +} diff --git a/internal/api/user/coupons_app.go b/internal/api/user/coupons_app.go new file mode 100644 index 0000000..3207f30 --- /dev/null +++ b/internal/api/user/coupons_app.go @@ -0,0 +1,60 @@ +package app + +import ( + "net/http" + "strconv" + + "bindbox-game/internal/code" + "bindbox-game/internal/pkg/core" + "bindbox-game/internal/pkg/validation" + "bindbox-game/internal/repository/mysql/model" +) + +type listCouponsRequest struct { + Page int `form:"page"` + PageSize int `form:"page_size"` +} +type listCouponsResponse struct { + Page int `json:"page"` + PageSize int `json:"page_size"` + Total int64 `json:"total"` + List []*model.UserCoupons `json:"list"` +} + +// ListUserCoupons 查看用户优惠券 +// @Summary 查看用户优惠券 +// @Description 查看用户持有的优惠券列表 +// @Tags APP端.用户 +// @Accept json +// @Produce json +// @Param user_id path integer true "用户ID" +// @Param page query int true "页码" default(1) +// @Param page_size query int true "每页数量,最多100" default(20) +// @Success 200 {object} listCouponsResponse +// @Failure 400 {object} code.Failure +// @Router /api/app/users/{user_id}/coupons [get] +func (h *handler) ListUserCoupons() core.HandlerFunc { + return func(ctx core.Context) { + req := new(listCouponsRequest) + rsp := new(listCouponsResponse) + if err := ctx.ShouldBindForm(req); err != nil { + ctx.AbortWithError(core.Error(http.StatusBadRequest, code.ParamBindError, validation.Error(err))) + return + } + userID, err := strconv.ParseInt(ctx.Param("user_id"), 10, 64) + if err != nil { + ctx.AbortWithError(core.Error(http.StatusBadRequest, code.ParamBindError, "未传递用户ID")) + return + } + items, total, err := h.user.ListCoupons(ctx.RequestContext(), userID, req.Page, req.PageSize) + if err != nil { + ctx.AbortWithError(core.Error(http.StatusBadRequest, 10003, err.Error())) + return + } + rsp.Page = req.Page + rsp.PageSize = req.PageSize + rsp.Total = total + rsp.List = items + ctx.Payload(rsp) + } +} diff --git a/internal/api/user/invites_app.go b/internal/api/user/invites_app.go new file mode 100644 index 0000000..0aefeb2 --- /dev/null +++ b/internal/api/user/invites_app.go @@ -0,0 +1,69 @@ +package app + +import ( + "net/http" + "strconv" + + "bindbox-game/internal/code" + "bindbox-game/internal/pkg/core" + "bindbox-game/internal/pkg/validation" +) + +type listInvitesRequest struct { + Page int `form:"page"` + PageSize int `form:"page_size"` +} +type inviteUserItem struct { + ID int64 `json:"id"` + Nickname string `json:"nickname"` + Avatar string `json:"avatar"` + InviteCode string `json:"invite_code"` +} +type listInvitesResponse struct { + Page int `json:"page"` + PageSize int `json:"page_size"` + Total int64 `json:"total"` + List []*inviteUserItem `json:"list"` +} + +// ListUserInvites 查看用户邀请记录 +// @Summary 查看用户邀请记录 +// @Description 查看被该用户邀请的用户列表 +// @Tags APP端.用户 +// @Accept json +// @Produce json +// @Param user_id path integer true "用户ID" +// @Param page query int true "页码" default(1) +// @Param page_size query int true "每页数量,最多100" default(20) +// @Success 200 {object} listInvitesResponse +// @Failure 400 {object} code.Failure +// @Router /api/app/users/{user_id}/invites [get] +func (h *handler) ListUserInvites() core.HandlerFunc { + return func(ctx core.Context) { + req := new(listInvitesRequest) + rsp := new(listInvitesResponse) + if err := ctx.ShouldBindForm(req); err != nil { + ctx.AbortWithError(core.Error(http.StatusBadRequest, code.ParamBindError, validation.Error(err))) + return + } + userID, err := strconv.ParseInt(ctx.Param("user_id"), 10, 64) + if err != nil { + ctx.AbortWithError(core.Error(http.StatusBadRequest, code.ParamBindError, "未传递用户ID")) + return + } + items, total, err := h.user.ListInvites(ctx.RequestContext(), userID, req.Page, req.PageSize) + if err != nil { + ctx.AbortWithError(core.Error(http.StatusBadRequest, 10007, err.Error())) + return + } + rsp.Page = req.Page + rsp.PageSize = req.PageSize + rsp.Total = total + var list = make([]*inviteUserItem, 0, len(items)) + for _, it := range items { + list = append(list, &inviteUserItem{ID: it.ID, Nickname: it.Nickname, Avatar: it.Avatar, InviteCode: it.InviteCode}) + } + rsp.List = list + ctx.Payload(rsp) + } +} diff --git a/internal/api/user/item_cards_app.go b/internal/api/user/item_cards_app.go new file mode 100644 index 0000000..8f48713 --- /dev/null +++ b/internal/api/user/item_cards_app.go @@ -0,0 +1,116 @@ +package app + +import ( + "net/http" + "strconv" + + "bindbox-game/internal/code" + "bindbox-game/internal/pkg/core" + "bindbox-game/internal/pkg/validation" + "bindbox-game/internal/repository/mysql/model" +) + +type listUserItemCardsRequest struct { + Page int `form:"page"` + PageSize int `form:"page_size"` +} + +type listUserItemCardsResponse struct { + Page int `json:"page"` + PageSize int `json:"page_size"` + Total int64 `json:"total"` + List []*model.UserItemCards `json:"list"` +} + +// ListUserItemCards 获取用户道具卡列表 +// @Summary 获取用户道具卡列表 +// @Description 获取指定用户的道具卡列表,支持分页 +// @Tags APP端.用户 +// @Accept json +// @Produce json +// @Param user_id path integer true "用户ID" +// @Param page query integer false "页码,默认1" +// @Param page_size query integer false "每页条数,默认10" +// @Success 200 {object} listUserItemCardsResponse +// @Failure 400 {object} code.Failure "参数错误" +// @Failure 401 {object} code.Failure "未授权" +// @Failure 500 {object} code.Failure "服务器内部错误" +// @Router /api/app/users/{user_id}/item_cards [get] +func (h *handler) ListUserItemCards() core.HandlerFunc { + return func(ctx core.Context) { + req := new(listUserItemCardsRequest) + rsp := new(listUserItemCardsResponse) + if err := ctx.ShouldBindForm(req); err != nil { + ctx.AbortWithError(core.Error(http.StatusBadRequest, code.ParamBindError, validation.Error(err))) + return + } + userID, err := strconv.ParseInt(ctx.Param("user_id"), 10, 64) + if err != nil { + ctx.AbortWithError(core.Error(http.StatusBadRequest, code.ParamBindError, "未传递用户ID")) + return + } + items, total, err := h.user.ListUserItemCards(ctx.RequestContext(), userID, req.Page, req.PageSize) + if err != nil { + ctx.AbortWithError(core.Error(http.StatusBadRequest, 10008, err.Error())) + return + } + rsp.Page = req.Page + rsp.PageSize = req.PageSize + rsp.Total = total + rsp.List = items + ctx.Payload(rsp) + } +} + +type listUserItemCardUsesRequest struct { + Page int `form:"page"` + PageSize int `form:"page_size"` +} + +type listUserItemCardUsesResponse struct { + Page int `json:"page"` + PageSize int `json:"page_size"` + Total int64 `json:"total"` + List []*model.ActivityDrawEffects `json:"list"` +} + +// ListUserItemCardUses 获取用户道具卡使用记录 +// @Summary 获取用户道具卡使用记录 +// @Description 获取指定用户的道具卡使用记录,支持分页 +// @Tags APP端.用户 +// @Accept json +// @Produce json +// @Param user_id path integer true "用户ID" +// @Param page query integer false "页码,默认1" +// @Param page_size query integer false "每页条数,默认10" +// @Success 200 {object} listUserItemCardUsesResponse +// @Failure 400 {object} code.Failure "参数错误" +// @Failure 401 {object} code.Failure "未授权" +// @Failure 500 {object} code.Failure "服务器内部错误" +// @Router /api/app/users/{user_id}/item_cards/uses [get] +func (h *handler) ListUserItemCardUses() core.HandlerFunc { + return func(ctx core.Context) { + req := new(listUserItemCardUsesRequest) + rsp := new(listUserItemCardUsesResponse) + if err := ctx.ShouldBindForm(req); err != nil { + ctx.AbortWithError(core.Error(http.StatusBadRequest, code.ParamBindError, validation.Error(err))) + return + } + userID, err := strconv.ParseInt(ctx.Param("user_id"), 10, 64) + if err != nil { + ctx.AbortWithError(core.Error(http.StatusBadRequest, code.ParamBindError, "未传递用户ID")) + return + } + items, total, err := h.user.ListUserItemCardUses(ctx.RequestContext(), userID, req.Page, req.PageSize) + if err != nil { + ctx.AbortWithError(core.Error(http.StatusBadRequest, 10009, err.Error())) + return + } + rsp.Page = req.Page + rsp.PageSize = req.PageSize + rsp.Total = total + rsp.List = items + ctx.Payload(rsp) + } +} + diff --git a/internal/api/user/login_app.go b/internal/api/user/login_app.go new file mode 100644 index 0000000..3b40c7c --- /dev/null +++ b/internal/api/user/login_app.go @@ -0,0 +1,72 @@ +package app + +import ( + "net/http" + "time" + + "bindbox-game/configs" + "bindbox-game/internal/code" + "bindbox-game/internal/pkg/core" + "bindbox-game/internal/pkg/jwtoken" + "bindbox-game/internal/pkg/validation" + "bindbox-game/internal/pkg/wechat" + "bindbox-game/internal/proposal" + usersvc "bindbox-game/internal/service/user" +) + +type weixinLoginRequest struct { + Code string `json:"code"` + InviteCode string `json:"invite_code"` +} +type weixinLoginResponse struct { + UserID int64 `json:"user_id"` + Nickname string `json:"nickname"` + Avatar string `json:"avatar"` + InviteCode string `json:"invite_code"` + Token string `json:"token"` +} + +// WeixinLogin 微信登录 +// @Summary 微信登录 +// @Description 微信静默登录(需传递 code;可选 invite_code) +// @Tags APP端.用户 +// @Accept json +// @Produce json +// @Param RequestBody body weixinLoginRequest true "请求参数" +// @Success 200 {object} weixinLoginResponse +// @Failure 400 {object} code.Failure +// @Router /api/app/users/weixin/login [post] +func (h *handler) WeixinLogin() core.HandlerFunc { + return func(ctx core.Context) { + req := new(weixinLoginRequest) + rsp := new(weixinLoginResponse) + if err := ctx.ShouldBindJSON(req); err != nil { + ctx.AbortWithError(core.Error(http.StatusBadRequest, code.ParamBindError, validation.Error(err))) + return + } + cfg := configs.Get() + wxcfg := &wechat.WechatConfig{AppID: cfg.Wechat.AppID, AppSecret: cfg.Wechat.AppSecret} + c2s, err := wechat.Code2Session(ctx, wxcfg, req.Code) + if err != nil { + ctx.AbortWithError(core.Error(http.StatusBadRequest, 10006, err.Error())) + return + } + + in := usersvc.LoginWeixinInput{OpenID: c2s.OpenID, UnionID: c2s.UnionID, InviteCode: req.InviteCode} + u, err := h.user.LoginWeixin(ctx.RequestContext(), in) + if err != nil { + ctx.AbortWithError(core.Error(http.StatusBadRequest, 10006, err.Error())) + return + } + rsp.UserID = u.ID + rsp.Nickname = u.Nickname + rsp.Avatar = u.Avatar + rsp.InviteCode = u.InviteCode + sessionUserInfo := proposal.SessionUserInfo{Id: int32(u.ID), UserName: u.Nickname, NickName: u.Nickname, IsSuper: 0, Platform: "APP"} + tokenString, tErr := jwtoken.New(configs.Get().JWT.PatientSecret).Sign(sessionUserInfo, 30*24*time.Hour) + if tErr == nil { + rsp.Token = tokenString + } + ctx.Payload(rsp) + } +} diff --git a/internal/api/user/orders_app.go b/internal/api/user/orders_app.go new file mode 100644 index 0000000..784257e --- /dev/null +++ b/internal/api/user/orders_app.go @@ -0,0 +1,60 @@ +package app + +import ( + "net/http" + "strconv" + + "bindbox-game/internal/code" + "bindbox-game/internal/pkg/core" + "bindbox-game/internal/pkg/validation" + "bindbox-game/internal/repository/mysql/model" +) + +type listOrdersRequest struct { + Page int `form:"page"` + PageSize int `form:"page_size"` +} +type listOrdersResponse struct { + Page int `json:"page"` + PageSize int `json:"page_size"` + Total int64 `json:"total"` + List []*model.Orders `json:"list"` +} + +// ListUserOrders 查看用户订单记录 +// @Summary 查看用户订单记录 +// @Description 查看用户抽奖来源订单记录 +// @Tags APP端.用户 +// @Accept json +// @Produce json +// @Param user_id path integer true "用户ID" +// @Param page query int true "页码" default(1) +// @Param page_size query int true "每页数量,最多100" default(20) +// @Success 200 {object} listOrdersResponse +// @Failure 400 {object} code.Failure +// @Router /api/app/users/{user_id}/orders [get] +func (h *handler) ListUserOrders() core.HandlerFunc { + return func(ctx core.Context) { + req := new(listOrdersRequest) + rsp := new(listOrdersResponse) + if err := ctx.ShouldBindForm(req); err != nil { + ctx.AbortWithError(core.Error(http.StatusBadRequest, code.ParamBindError, validation.Error(err))) + return + } + userID, err := strconv.ParseInt(ctx.Param("user_id"), 10, 64) + if err != nil { + ctx.AbortWithError(core.Error(http.StatusBadRequest, code.ParamBindError, "未传递用户ID")) + return + } + items, total, err := h.user.ListOrders(ctx.RequestContext(), userID, req.Page, req.PageSize) + if err != nil { + ctx.AbortWithError(core.Error(http.StatusBadRequest, 10002, err.Error())) + return + } + rsp.Page = req.Page + rsp.PageSize = req.PageSize + rsp.Total = total + rsp.List = items + ctx.Payload(rsp) + } +} diff --git a/internal/api/user/phone_bind.go b/internal/api/user/phone_bind.go new file mode 100644 index 0000000..547990c --- /dev/null +++ b/internal/api/user/phone_bind.go @@ -0,0 +1,77 @@ +package app + +import ( + "net/http" + "strconv" + + "bindbox-game/configs" + "bindbox-game/internal/code" + "bindbox-game/internal/pkg/core" + "bindbox-game/internal/pkg/miniprogram" + "bindbox-game/internal/pkg/validation" + "bindbox-game/internal/pkg/wechat" +) + +type bindPhoneRequest struct { + Code string `json:"code"` +} + +type bindPhoneResponse struct { + Success bool `json:"success"` + Mobile string `json:"mobile"` +} + +// BindPhone 绑定手机号 +// @Summary 绑定手机号 +// @Description 使用微信手机号 code 换取手机号并绑定到指定用户 +// @Tags APP端.用户 +// @Accept json +// @Produce json +// @Param user_id path integer true "用户ID" +// @Param RequestBody body bindPhoneRequest true "请求参数" +// @Success 200 {object} bindPhoneResponse +// @Failure 400 {object} code.Failure +// @Router /api/app/users/{user_id}/phone/bind [post] +func (h *handler) BindPhone() core.HandlerFunc { + return func(ctx core.Context) { + req := new(bindPhoneRequest) + rsp := new(bindPhoneResponse) + if err := ctx.ShouldBindJSON(req); err != nil { + ctx.AbortWithError(core.Error(http.StatusBadRequest, code.ParamBindError, validation.Error(err))) + return + } + uidStr := ctx.Param("user_id") + userID, _ := strconv.ParseInt(uidStr, 10, 64) + if userID <= 0 || req.Code == "" { + ctx.AbortWithError(core.Error(http.StatusBadRequest, code.ParamBindError, "缺少必要参数")) + return + } + + cfg := configs.Get() + var tokenRes struct { + AccessToken string `json:"access_token"` + } + if err := miniprogram.GetAccessToken(cfg.Wechat.AppID, cfg.Wechat.AppSecret, &tokenRes); err != nil || tokenRes.AccessToken == "" { + ctx.AbortWithError(core.Error(http.StatusBadRequest, code.ParamBindError, "获取微信access_token失败")) + return + } + pn, err := wechat.GetPhoneNumber(ctx, tokenRes.AccessToken, req.Code) + if err != nil { + ctx.AbortWithError(core.Error(http.StatusBadRequest, code.ParamBindError, err.Error())) + return + } + mobile := pn.PhoneInfo.PurePhoneNumber + if mobile == "" { + ctx.AbortWithError(core.Error(http.StatusBadRequest, code.ParamBindError, "手机号为空")) + return + } + + if _, err := h.writeDB.Users.WithContext(ctx.RequestContext()).Where(h.writeDB.Users.ID.Eq(userID)).Updates(map[string]any{"mobile": mobile}); err != nil { + ctx.AbortWithError(core.Error(http.StatusBadRequest, code.ServerError, err.Error())) + return + } + rsp.Success = true + rsp.Mobile = mobile + ctx.Payload(rsp) + } +} diff --git a/internal/api/user/points_app.go b/internal/api/user/points_app.go new file mode 100644 index 0000000..0c0dfb4 --- /dev/null +++ b/internal/api/user/points_app.go @@ -0,0 +1,91 @@ +package app + +import ( + "net/http" + "strconv" + + "bindbox-game/internal/code" + "bindbox-game/internal/pkg/core" + "bindbox-game/internal/pkg/validation" + "bindbox-game/internal/repository/mysql/model" +) + +type listPointsRequest struct { + Page int `form:"page"` + PageSize int `form:"page_size"` +} +type listPointsResponse struct { + Page int `json:"page"` + PageSize int `json:"page_size"` + Total int64 `json:"total"` + List []*model.UserPointsLedger `json:"list"` +} +type pointsBalanceResponse struct { + Balance int64 `json:"balance"` +} + +// ListUserPoints 查看用户积分记录 +// @Summary 查看用户积分记录 +// @Description 查看用户积分流水记录 +// @Tags APP端.用户 +// @Accept json +// @Produce json +// @Param user_id path integer true "用户ID" +// @Param page query int true "页码" default(1) +// @Param page_size query int true "每页数量,最多100" default(20) +// @Success 200 {object} listPointsResponse +// @Failure 400 {object} code.Failure +// @Router /api/app/users/{user_id}/points [get] +func (h *handler) ListUserPoints() core.HandlerFunc { + return func(ctx core.Context) { + req := new(listPointsRequest) + rsp := new(listPointsResponse) + if err := ctx.ShouldBindForm(req); err != nil { + ctx.AbortWithError(core.Error(http.StatusBadRequest, code.ParamBindError, validation.Error(err))) + return + } + userID, err := strconv.ParseInt(ctx.Param("user_id"), 10, 64) + if err != nil { + ctx.AbortWithError(core.Error(http.StatusBadRequest, code.ParamBindError, "未传递用户ID")) + return + } + items, total, err := h.user.ListPointsLedger(ctx.RequestContext(), userID, req.Page, req.PageSize) + if err != nil { + ctx.AbortWithError(core.Error(http.StatusBadRequest, 10004, err.Error())) + return + } + rsp.Page = req.Page + rsp.PageSize = req.PageSize + rsp.Total = total + rsp.List = items + ctx.Payload(rsp) + } +} + +// GetUserPointsBalance 查看用户积分余额 +// @Summary 查看用户积分余额 +// @Description 查看用户积分余额(过滤过期积分) +// @Tags APP端.用户 +// @Accept json +// @Produce json +// @Param user_id path integer true "用户ID" +// @Success 200 {object} pointsBalanceResponse +// @Failure 400 {object} code.Failure +// @Router /api/app/users/{user_id}/points/balance [get] +func (h *handler) GetUserPointsBalance() core.HandlerFunc { + return func(ctx core.Context) { + rsp := new(pointsBalanceResponse) + userID, err := strconv.ParseInt(ctx.Param("user_id"), 10, 64) + if err != nil { + ctx.AbortWithError(core.Error(http.StatusBadRequest, code.ParamBindError, "未传递用户ID")) + return + } + total, err := h.user.GetPointsBalance(ctx.RequestContext(), userID) + if err != nil { + ctx.AbortWithError(core.Error(http.StatusBadRequest, 10005, err.Error())) + return + } + rsp.Balance = total + ctx.Payload(rsp) + } +} diff --git a/internal/api/user/profile_app.go b/internal/api/user/profile_app.go new file mode 100644 index 0000000..6802c30 --- /dev/null +++ b/internal/api/user/profile_app.go @@ -0,0 +1,59 @@ +package app + +import ( + "net/http" + "strconv" + + "bindbox-game/internal/code" + "bindbox-game/internal/pkg/core" + "bindbox-game/internal/pkg/validation" +) + +type modifyUserRequest struct { + Nickname *string `json:"nickname"` + Avatar *string `json:"avatar"` +} +type userItem struct { + ID int64 `json:"id"` + Nickname string `json:"nickname"` + Avatar string `json:"avatar"` + InviteCode string `json:"invite_code"` + InviterID int64 `json:"inviter_id"` +} +type modifyUserResponse struct { + User userItem `json:"user"` +} + +// ModifyUser 修改用户信息 +// @Summary 修改用户信息 +// @Description 修改用户昵称与头像 +// @Tags APP端.用户 +// @Accept json +// @Produce json +// @Param user_id path integer true "用户ID" +// @Param RequestBody body modifyUserRequest true "请求参数" +// @Success 200 {object} modifyUserResponse +// @Failure 400 {object} code.Failure +// @Router /api/app/users/{user_id} [put] +func (h *handler) ModifyUser() core.HandlerFunc { + return func(ctx core.Context) { + req := new(modifyUserRequest) + rsp := new(modifyUserResponse) + if err := ctx.ShouldBindJSON(req); err != nil { + ctx.AbortWithError(core.Error(http.StatusBadRequest, code.ParamBindError, validation.Error(err))) + return + } + userID, err := strconv.ParseInt(ctx.Param("user_id"), 10, 64) + if err != nil { + ctx.AbortWithError(core.Error(http.StatusBadRequest, code.ParamBindError, "未传递用户ID")) + return + } + item, err := h.user.UpdateProfile(ctx.RequestContext(), userID, req.Nickname, req.Avatar) + if err != nil { + ctx.AbortWithError(core.Error(http.StatusBadRequest, 10001, err.Error())) + return + } + rsp.User = userItem{ID: item.ID, Nickname: item.Nickname, Avatar: item.Avatar, InviteCode: item.InviteCode, InviterID: item.InviterID} + ctx.Payload(rsp) + } +} diff --git a/internal/api/wechat/generate_qrcode.go b/internal/api/wechat/generate_qrcode.go deleted file mode 100644 index f783aeb..0000000 --- a/internal/api/wechat/generate_qrcode.go +++ /dev/null @@ -1,71 +0,0 @@ -package wechat - -import ( - "encoding/base64" - "fmt" - "net/http" - - "mini-chat/internal/code" - "mini-chat/internal/pkg/core" - "mini-chat/internal/pkg/wechat" -) - -type generateQRCodeRequest struct { - AppID string `json:"app_id" binding:"required"` // 微信小程序 AppID - AppSecret string `json:"app_secret" binding:"required"` // 微信小程序 AppSecret - Path string `json:"path" binding:"required"` // 小程序页面路径 -} - -type generateQRCodeResponse struct { - Success bool `json:"success"` - Message string `json:"message"` - Data string `json:"data"` // Base64 编码的图片数据 -} - -// GenerateQRCode 生成微信小程序二维码 -// @Summary 生成微信小程序二维码 -// @Description 根据 AppID、AppSecret 和页面路径生成微信小程序二维码 -// @Tags 微信 -// @Accept json -// @Produce json -// @Param request body generateQRCodeRequest true "请求参数" -// @Success 200 {object} generateQRCodeResponse -// @Failure 400 {object} code.Failure -// @Failure 500 {object} code.Failure -// @Router /api/wechat/qrcode [post] -func (h *handler) GenerateQRCode() core.HandlerFunc { - return func(ctx core.Context) { - req := new(generateQRCodeRequest) - if err := ctx.ShouldBindJSON(req); err != nil { - ctx.AbortWithError(core.Error( - http.StatusBadRequest, - code.ParamBindError, - code.Text(code.ParamBindError), - )) - return - } - - // 调用微信小程序二维码生成函数 - imageData, err := wechat.GenerateQRCode(ctx, req.AppID, req.AppSecret, req.Path) - if err != nil { - h.logger.Error(fmt.Sprintf("生成微信小程序二维码失败: %s", err.Error())) - ctx.AbortWithError(core.Error( - http.StatusInternalServerError, - code.ServerError, - err.Error(), - )) - return - } - - // 将图片数据转换为 Base64 编码 - base64Data := base64.StdEncoding.EncodeToString(imageData) - - res := &generateQRCodeResponse{ - Success: true, - Message: "二维码生成成功", - Data: base64Data, - } - - ctx.Payload(res) - } -} diff --git a/internal/api/wechat/mini_template.go b/internal/api/wechat/mini_template.go deleted file mode 100644 index 016e03e..0000000 --- a/internal/api/wechat/mini_template.go +++ /dev/null @@ -1,184 +0,0 @@ -package wechat - -import ( - "fmt" - "net/http" - "time" - - "mini-chat/internal/code" - "mini-chat/internal/pkg/core" - "mini-chat/internal/pkg/miniprogram" - "mini-chat/internal/pkg/validation" - - "go.uber.org/zap" - "gorm.io/gorm" -) - -type templateRequest struct { - AppID string `json:"app_id" binding:"required"` // 微信小程序 AppID -} - -type templateResponse struct { - Success bool `json:"success"` - Message string `json:"message"` - AppID string `json:"app_id"` // 小程序 AppID - TemplateID string `json:"template_id"` // 模板 ID -} - -// GetTemplate 获取微信小程序模板ID -// @Summary 获取微信小程序模板ID -// @Description 根据 AppID 获取微信小程序的模板ID -// @Tags 微信 -// @Accept json -// @Produce json -// @Param request body templateRequest true "请求参数" -// @Success 200 {object} templateResponse -// @Failure 400 {object} code.Failure -// @Failure 404 {object} code.Failure -// @Failure 500 {object} code.Failure -// @Router /api/wechat/template [post] -func (h *handler) GetTemplate() core.HandlerFunc { - return func(ctx core.Context) { - req := new(templateRequest) - res := new(templateResponse) - - if err := ctx.ShouldBindJSON(req); err != nil { - ctx.AbortWithError(core.Error( - http.StatusBadRequest, - code.ParamBindError, - validation.Error(err), - )) - return - } - - // 根据 AppID 查询小程序信息 - miniProgram, err := h.readDB.MiniProgram.WithContext(ctx.RequestContext()). - Where(h.readDB.MiniProgram.AppID.Eq(req.AppID)). - First() - - if err != nil { - if err == gorm.ErrRecordNotFound { - ctx.AbortWithError(core.Error( - http.StatusNotFound, - code.ServerError, - fmt.Sprintf("未找到 AppID 为 %s 的小程序", req.AppID), - )) - return - } - - h.logger.Error(fmt.Sprintf("查询小程序信息失败: %s", err.Error())) - ctx.AbortWithError(core.Error( - http.StatusInternalServerError, - code.ServerError, - "查询小程序信息失败", - )) - return - } - - // 检查模板ID是否存在 - if miniProgram.TemplateID == "" { - ctx.AbortWithError(core.Error( - http.StatusNotFound, - code.ServerError, - "该小程序未配置模板ID", - )) - return - } - - res.Success = true - res.Message = "获取模板ID成功" - res.AppID = miniProgram.AppID - res.TemplateID = miniProgram.TemplateID - - ctx.Payload(res) - } -} - -type sendSubscribeMessageRequest struct { - AppID string `json:"app_id" binding:"required"` // 微信小程序 AppID - TemplateID string `json:"template_id" binding:"required"` // 模板 ID - AppSecret string `json:"app_secret" binding:"required"` // 小程序 AppSecret - Touser string `json:"touser" binding:"required"` // 接收者(用户)的 openid -} - -type sendSubscribeMessageResponse struct { - Success bool `json:"success"` - Message string `json:"message"` -} - -// SendSubscribeMessage 发送订阅消息 -// @Summary 发送订阅消息 -// @Description 根据模板ID发送订阅消息 -// @Tags 微信 -// @Accept json -// @Produce json -// @Param request body sendSubscribeMessageRequest true "请求参数" -// @Success 200 {object} sendSubscribeMessageResponse -// @Failure 400 {object} code.Failure -// @Failure 404 {object} code.Failure -// @Failure 500 {object} code.Failure -// @Router /api/wechat/subscribe [post] -func (h *handler) SendSubscribeMessage() core.HandlerFunc { - return func(ctx core.Context) { - req := new(sendSubscribeMessageRequest) - res := new(sendSubscribeMessageResponse) - - // 参数绑定和验证 - if err := ctx.ShouldBindJSON(req); err != nil { - ctx.AbortWithError(core.Error( - http.StatusBadRequest, - code.ParamBindError, - validation.Error(err), - )) - return - } - - // 调整为实时获取 - accessTokenResponse := new(miniprogram.AccessTokenResponse) - if err := miniprogram.GetAccessToken(req.AppID, req.AppSecret, accessTokenResponse); err != nil { - h.logger.Error("GetAccessToken failed", zap.Error(err), zap.String("app_id", req.AppID), zap.String("app_secret", req.AppSecret)) - ctx.AbortWithError(core.Error( - http.StatusBadRequest, - code.ParamBindError, - fmt.Sprintf("获取 access_token 失败: %s,请稍后重试", err.Error()), - )) - return - } - - if accessTokenResponse.AccessToken == "" { - ctx.AbortWithError(core.Error( - http.StatusBadRequest, - code.ParamBindError, - "未获得到 access_token,请稍后重试", - )) - return - } - - sendSubscribeMessageReq := new(miniprogram.SendSubscribeMessageRequest) - sendSubscribeMessageReq.Touser = req.Touser - sendSubscribeMessageReq.TemplateID = req.TemplateID - sendSubscribeMessageReq.Page = "pages/index/detail?url=1" - sendSubscribeMessageReq.MiniprogramState = "formal" // 需要改成正式版 目前是体验版 跳转小程序类型:developer 为开发版;trial为体验版;formal 为正式版;默认为正式版 - sendSubscribeMessageReq.Lang = "zh_CN" - sendSubscribeMessageReq.Data.Thing1.Value = "留言提醒" - sendSubscribeMessageReq.Data.Time2.Value = time.Now().Format("2006-01-02 15:04:05") - sendSubscribeMessageReq.Data.Thing3.Value = "您有一条新的消息..." - - sendSubscribeMessageRes := new(miniprogram.SendSubscribeMessageResponse) - err := miniprogram.SendSubscribeMessage(accessTokenResponse.AccessToken, sendSubscribeMessageReq, sendSubscribeMessageRes) - if err != nil { - res.Success = false - res.Message = "发送订阅消息失败" + err.Error() - h.logger.Error(fmt.Sprintf("发送模版消息失败: %s", err.Error()), - zap.String("app_id", req.AppID), - zap.String("app_secret", req.AppSecret), - zap.String("template_id", req.TemplateID), - ) - } else { - res.Success = true - res.Message = "订阅消息发送成功" - } - - ctx.Payload(res) - } -} diff --git a/internal/api/wechat/miniprogram_login.go b/internal/api/wechat/miniprogram_login.go deleted file mode 100644 index fc3ec4d..0000000 --- a/internal/api/wechat/miniprogram_login.go +++ /dev/null @@ -1,251 +0,0 @@ -package wechat - -import ( - "crypto/rand" - "encoding/hex" - "encoding/json" - "fmt" - "net/http" - "time" - - "mini-chat/internal/code" - "mini-chat/internal/pkg/core" - "mini-chat/internal/pkg/httpclient" - "mini-chat/internal/pkg/validation" - "mini-chat/internal/repository/mysql/model" - - "github.com/DanPlayer/randomname" -) - -type miniprogramLoginRequest struct { - AppID string `json:"app_id" binding:"required"` // 小程序AppID - JSCode string `json:"js_code" binding:"required"` // 登录时获取的code -} - -type miniprogramLoginResponse struct { - Success bool `json:"success"` - Message string `json:"message"` - Token string `json:"token"` // 登录token - UserID string `json:"user_id"` // 用户ID - UserName string `json:"user_name"` // 用户昵称 - Avatar string `json:"user_avatar"` // 用户头像 - OpenID string `json:"openid,omitempty"` // 用户唯一标识 - UnionID string `json:"unionid,omitempty"` // 用户在开放平台的唯一标识符 -} - -// Code2SessionResponse 微信code2Session接口响应 -type Code2SessionResponse struct { - OpenID string `json:"openid"` // 用户唯一标识 - SessionKey string `json:"session_key"` // 会话密钥 - UnionID string `json:"unionid"` // 用户在开放平台的唯一标识符 - ErrCode int `json:"errcode"` // 错误码 - ErrMsg string `json:"errmsg"` // 错误信息 -} - -// MiniprogramLogin 小程序登录 -// @Summary 小程序登录 -// @Description 通过AppID和code获取用户的openid,系统自动生成用户名和头像 -// @Tags 微信 -// @Accept json -// @Produce json -// @Param request body miniprogramLoginRequest true "请求参数" -// @Success 200 {object} miniprogramLoginResponse -// @Failure 400 {object} code.Failure -// @Failure 500 {object} code.Failure -// @Router /api/wechat/miniprogram/login [post] -func (h *handler) MiniprogramLogin() core.HandlerFunc { - return func(ctx core.Context) { - req := new(miniprogramLoginRequest) - res := new(miniprogramLoginResponse) - - if err := ctx.ShouldBindJSON(req); err != nil { - ctx.AbortWithError(core.Error( - http.StatusBadRequest, - code.ParamBindError, - validation.Error(err), - )) - return - } - - // 根据AppID查询小程序信息获取AppSecret - miniProgram, err := h.readDB.MiniProgram.WithContext(ctx.RequestContext()). - Where(h.readDB.MiniProgram.AppID.Eq(req.AppID)). - First() - if err != nil { - h.logger.Error(fmt.Sprintf("查询小程序信息失败: %s", err.Error())) - ctx.AbortWithError(core.Error( - http.StatusBadRequest, - code.ServerError, - "小程序不存在或查询失败", - )) - return - } - - // 调用微信code2Session接口 - openID, sessionKey, unionID, err := h.callCode2Session(ctx, req.AppID, miniProgram.AppSecret, req.JSCode) - if err != nil { - h.logger.Error(fmt.Sprintf("调用微信code2Session接口失败: %s", err.Error())) - ctx.AbortWithError(core.Error( - http.StatusInternalServerError, - code.ServerError, - err.Error(), - )) - return - } - - // 查询或创建用户 - user, err := h.getOrCreateUser(ctx, req.AppID, openID, unionID) - if err != nil { - h.logger.Error(fmt.Sprintf("获取或创建用户失败: %s", err.Error())) - ctx.AbortWithError(core.Error( - http.StatusInternalServerError, - code.ServerError, - "用户创建失败", - )) - return - } - - // 生成登录token - token, err := h.generateToken(user.UserID, sessionKey) - if err != nil { - h.logger.Error(fmt.Sprintf("生成token失败: %s", err.Error())) - ctx.AbortWithError(core.Error( - http.StatusInternalServerError, - code.ServerError, - "token生成失败", - )) - return - } - - // 授权成功,主动发消息 - createData := new(model.AppMessageLog) - createData.AppID = req.AppID - createData.SenderID = "888888" - createData.SenderName = "平台" - createData.Content = `{"messages":"您好,欢迎开启专属体验之旅!"}` - createData.ReceiverID = openID - createData.MsgType = 1 - createData.SendTime = time.Now() - createData.CreatedAt = time.Now() - if err := h.writeDB.AppMessageLog.WithContext(ctx.RequestContext()).Create(createData); err != nil { - h.logger.Error(fmt.Sprintf("授权成功,主动发消息失败: %s", err.Error())) - } - - res.Success = true - res.Message = "登录成功" - res.Token = token - res.UserID = user.UserID - res.UserName = user.UserName - res.Avatar = user.UserAvatar - res.OpenID = openID - res.UnionID = unionID - - ctx.Payload(res) - } -} - -// getOrCreateUser 获取或创建用户 -func (h *handler) getOrCreateUser(ctx core.Context, appID, openID, unionID string) (*model.AppUser, error) { - // 先查询用户是否存在(使用openID作为用户ID) - user, err := h.readDB.AppUser.WithContext(ctx.RequestContext()). - Where(h.readDB.AppUser.AppID.Eq(appID)). - Where(h.readDB.AppUser.UserID.Eq(openID)). - First() - - if err == nil { - // 用户已存在,直接返回 - return user, nil - } - - username := randomname.GenerateName() - - // 生成头像URL - avatarURL, err := h.generateAvatar(openID) - if err != nil { - h.logger.Warn(fmt.Sprintf("生成头像失败: %s,使用默认头像", err.Error())) - avatarURL = "/static/avatars/default.svg" - } - - // 创建新用户 - newUser := &model.AppUser{ - AppID: appID, - UserID: openID, // 使用openID作为用户ID - UserName: username, - UserMobile: "", // 暂时为空 - UserAvatar: avatarURL, - CreatedAt: time.Now(), - } - - err = h.writeDB.AppUser.WithContext(ctx.RequestContext()).Create(newUser) - if err != nil { - return nil, fmt.Errorf("创建用户失败: %v", err) - } - - return newUser, nil -} - -// generateAvatar 生成头像URL -func (h *handler) generateAvatar(seed string) (string, error) { - // 使用dicebear API生成头像 - // 直接使用seed作为头像种子,确保每个用户有不同的头像 - avatarURL := fmt.Sprintf("https://api.dicebear.com/7.x/avataaars/svg?seed=%s", seed) - fmt.Printf("生成头像URL: %s\n", avatarURL) - return avatarURL, nil -} - -// generateToken 生成登录token -func (h *handler) generateToken(userID, sessionKey string) (string, error) { - // 生成32字节的随机token - bytes := make([]byte, 32) - if _, err := rand.Read(bytes); err != nil { - return "", err - } - - token := hex.EncodeToString(bytes) - - // TODO: 这里应该将token保存到缓存或数据库中,并设置过期时间 - // 可以结合sessionKey一起存储,用于后续的用户身份验证 - - return token, nil -} - -// callCode2Session 调用微信code2Session接口 -func (h *handler) callCode2Session(ctx core.Context, appID, appSecret, jsCode string) (string, string, string, error) { - // 构建请求URL - url := "https://api.weixin.qq.com/sns/jscode2session" - - // 发送HTTP请求 - client := httpclient.GetHttpClientWithContext(ctx.RequestContext()) - resp, err := client.R(). - SetQueryParams(map[string]string{ - "appid": appID, - "secret": appSecret, - "js_code": jsCode, - "grant_type": "authorization_code", - }). - Get(url) - - if err != nil { - return "", "", "", fmt.Errorf("HTTP请求失败: %v", err) - } - - if resp.StatusCode() != http.StatusOK { - return "", "", "", fmt.Errorf("HTTP请求失败,状态码: %d", resp.StatusCode()) - } - - var result Code2SessionResponse - if err := json.Unmarshal(resp.Body(), &result); err != nil { - return "", "", "", fmt.Errorf("解析响应失败: %v", err) - } - - // 检查微信API返回的错误码 - if result.ErrCode != 0 { - return "", "", "", fmt.Errorf("微信API错误: errcode=%d, errmsg=%s", result.ErrCode, result.ErrMsg) - } - - if result.OpenID == "" { - return "", "", "", fmt.Errorf("获取到的openid为空") - } - - return result.OpenID, result.SessionKey, result.UnionID, nil -} diff --git a/internal/api/wechat/wechat.go b/internal/api/wechat/wechat.go deleted file mode 100644 index cac6b14..0000000 --- a/internal/api/wechat/wechat.go +++ /dev/null @@ -1,24 +0,0 @@ -package wechat - -import ( - "mini-chat/internal/pkg/logger" - "mini-chat/internal/repository/mysql" - "mini-chat/internal/repository/mysql/dao" - "mini-chat/internal/services/services_miniprogram" -) - -type handler struct { - logger logger.CustomLogger - writeDB *dao.Query - readDB *dao.Query - servicesMiniProgram services_miniprogram.Service -} - -func New(logger logger.CustomLogger, db mysql.Repo) *handler { - return &handler{ - logger: logger, - writeDB: dao.Use(db.GetDbW()), - readDB: dao.Use(db.GetDbR()), - servicesMiniProgram: services_miniprogram.New(logger, db), - } -} diff --git a/internal/code/code.go b/internal/code/code.go index 01024ef..92ee512 100644 --- a/internal/code/code.go +++ b/internal/code/code.go @@ -3,7 +3,7 @@ package code import ( _ "embed" - "mini-chat/configs" + "bindbox-game/configs" ) //go:embed code.go @@ -56,3 +56,29 @@ func Text(code int) string { return zhCNText[code] } + +const ( + CreateActivityError = 20501 + ModifyActivityError = 20502 + DeleteActivityError = 20503 + GetActivityError = 20504 + ListActivitiesError = 20505 + ListActivityIssuesError = 20506 + CreateActivityIssueError = 20507 + ModifyActivityIssueError = 20508 + DeleteActivityIssueError = 20509 + CreateIssueRewardsError = 20510 + ListIssueRewardsError = 20511 + ListDrawLogsError = 20512 +) + +const ( + CreateGuildError = 20601 + ModifyGuildError = 20602 + DeleteGuildError = 20603 + GetGuildError = 20604 + ListGuildsError = 20605 + ListGuildMembersError = 20606 + JoinGuildError = 20607 + LeaveGuildError = 20608 +) diff --git a/internal/code/zh-cn.go b/internal/code/zh-cn.go index e340253..ffccaf2 100644 --- a/internal/code/zh-cn.go +++ b/internal/code/zh-cn.go @@ -29,6 +29,27 @@ var zhCNText = map[int]string{ ListKeywordMaterialError: "获取关键字素材列表失败", ModifyKeywordMaterialError: "修改关键字素材失败", - SendMessageError: "发送消息失败", - ListMessageError: "获取消息列表失败", + SendMessageError: "发送消息失败", + ListMessageError: "获取消息列表失败", + CreateActivityError: "创建活动失败", + ModifyActivityError: "修改活动失败", + DeleteActivityError: "删除活动失败", + GetActivityError: "获取活动详情失败", + ListActivitiesError: "获取活动列表失败", + ListActivityIssuesError: "获取活动期数失败", + CreateActivityIssueError: "创建活动期数失败", + ModifyActivityIssueError: "修改活动期数失败", + DeleteActivityIssueError: "删除活动期数失败", + CreateIssueRewardsError: "创建期数奖品失败", + ListIssueRewardsError: "获取期数奖品失败", + ListDrawLogsError: "获取抽奖记录失败", + + CreateGuildError: "创建工会失败", + ModifyGuildError: "修改工会失败", + DeleteGuildError: "删除工会失败", + GetGuildError: "获取工会详情失败", + ListGuildsError: "获取工会列表失败", + ListGuildMembersError: "获取工会成员失败", + JoinGuildError: "加入工会失败", + LeaveGuildError: "离开工会失败", } diff --git a/internal/cron/cron.go b/internal/cron/cron.go deleted file mode 100644 index 16a027c..0000000 --- a/internal/cron/cron.go +++ /dev/null @@ -1,96 +0,0 @@ -package cron - -import ( - "context" - "sync" - - "mini-chat/internal/pkg/errors" - "mini-chat/internal/pkg/logger" - "mini-chat/internal/repository/mysql" - - "github.com/jakecoffman/cron" -) - -var _ Server = (*server)(nil) - -type taskCount struct { - wg sync.WaitGroup - exit chan struct{} -} - -func (tc *taskCount) i() {} - -func (tc *taskCount) Add() { - tc.wg.Add(1) -} - -func (tc *taskCount) Done() { - tc.wg.Done() -} - -func (tc *taskCount) Exit() { - tc.wg.Done() - <-tc.exit -} - -func (tc *taskCount) Wait() { - tc.Add() - tc.wg.Wait() - close(tc.exit) -} - -type server struct { - logger logger.CustomLogger - db mysql.Repo - cron *cron.Cron - taskCount *taskCount - taskContext map[string]context.CancelFunc // 存储任务的取消上下文 - mu sync.Mutex // 保护 taskContext 的互斥 -} - -type Server interface { - i() - - // Start 启动 cron 服务 - Start() - - // Stop 停止 cron 服务 - Stop() - - // AddTask 增加定时任务 - AddTask() - - // AddJob 增加定时任务执行的工作内容 - AddJob() cron.FuncJob - - // StopJob 停止定时任务 - StopJob(taskCode string) - - // RemoveTask 删除定时任务 - RemoveTask(taskCode string) - - Entries() []*cron.Entry -} - -func New(logger logger.CustomLogger, db mysql.Repo) (Server, error) { - if logger == nil { - return nil, errors.New("logger required") - } - - return &server{ - logger: logger, - cron: cron.New(), - db: db, - taskCount: &taskCount{ - wg: sync.WaitGroup{}, - exit: make(chan struct{}), - }, - taskContext: make(map[string]context.CancelFunc), - }, nil -} - -func (s *server) i() {} - -func (s *server) Entries() []*cron.Entry { - return s.cron.Entries() -} diff --git a/internal/cron/cron_add_job.go b/internal/cron/cron_add_job.go deleted file mode 100644 index df59c7e..0000000 --- a/internal/cron/cron_add_job.go +++ /dev/null @@ -1,16 +0,0 @@ -package cron - -import ( - "github.com/jakecoffman/cron" -) - -func (s *server) AddJob() cron.FuncJob { - return func() { - s.taskCount.Add() - defer func() { - s.taskCount.Done() - }() - - // 执行任务 - } -} diff --git a/internal/cron/cron_add_task.go b/internal/cron/cron_add_task.go deleted file mode 100644 index e408f07..0000000 --- a/internal/cron/cron_add_task.go +++ /dev/null @@ -1,4 +0,0 @@ -package cron - -func (s *server) AddTask() { -} diff --git a/internal/cron/cron_remove_task.go b/internal/cron/cron_remove_task.go deleted file mode 100644 index e6533e2..0000000 --- a/internal/cron/cron_remove_task.go +++ /dev/null @@ -1,7 +0,0 @@ -package cron - -import "fmt" - -func (s *server) RemoveTask(taskCode string) { - s.cron.RemoveJob(fmt.Sprintf("cron_task_%s", taskCode)) -} diff --git a/internal/cron/cron_start.go b/internal/cron/cron_start.go deleted file mode 100644 index 07cb532..0000000 --- a/internal/cron/cron_start.go +++ /dev/null @@ -1,85 +0,0 @@ -package cron - -import ( - "fmt" - "time" - - "mini-chat/internal/pkg/httpclient" - "mini-chat/internal/repository/mysql/dao" - - "go.uber.org/zap" - "gorm.io/gorm" -) - -func (s *server) Start() { - s.cron.Start() - go s.taskCount.Wait() - - // 每 10 分钟监控小程序状态 - s.cron.AddFunc("0 */10 * * * ?", func() { - s.taskCount.Add() - defer s.taskCount.Done() - - readDB := dao.Use(s.db.GetDbR()) - writeDB := dao.Use(s.db.GetDbW()) - - appList, err := readDB.MiniProgram.Find() - if err != nil && err != gorm.ErrRecordNotFound { - s.logger.Error("获取小程序列表失败", zap.Error(err)) - return - } - - if len(appList) == 0 { - return - } - - for _, app := range appList { - type checkAppResponse struct { - Code int `json:"code"` - Appid string `json:"appid"` - Status string `json:"status"` - } - - checkAppRes := new(checkAppResponse) - response, err := httpclient.GetHttpClient().R(). - SetQueryParams(map[string]string{ - "appid": app.AppID, - }). - SetResult(checkAppRes). - Get("https://api.wxapi.work/xcx/checkxcx.php") - if err != nil { - s.logger.Error(fmt.Sprintf("[更新小程序状态失败]%s 请求APP验证服务失败", app.AppID), zap.Error(err)) - continue - } - if response.IsError() { - s.logger.Error(fmt.Sprintf("[更新小程序状态失败]%s 请求APP验证服务异常(%d)", app.AppID, response.StatusCode())) - } - - status := 0 - if checkAppRes.Code == 1 { - status = 1 - } else if checkAppRes.Code == 0 { - status = -1 - } - - if _, err := writeDB.MiniProgram. - Where(writeDB.MiniProgram.AppID.Eq(app.AppID)). - Updates(map[string]interface{}{ - "status": status, - "updated_user": "cron", - "updated_at": time.Now(), - }); err != nil { - s.logger.Error("更新小程序状态失败", zap.Error(err)) - return - } - } - }, "监控小程序状态") - - // 初始化任务 - s.initTask() -} - -// initTask 初始化任务 -func (s *server) initTask() { - -} diff --git a/internal/cron/cron_stop.go b/internal/cron/cron_stop.go deleted file mode 100644 index b818524..0000000 --- a/internal/cron/cron_stop.go +++ /dev/null @@ -1,6 +0,0 @@ -package cron - -func (s *server) Stop() { - s.cron.Stop() - s.taskCount.Exit() -} diff --git a/internal/cron/cron_stop_job.go b/internal/cron/cron_stop_job.go deleted file mode 100644 index 7540f26..0000000 --- a/internal/cron/cron_stop_job.go +++ /dev/null @@ -1,17 +0,0 @@ -package cron - -import ( - "fmt" -) - -func (s *server) StopJob(taskCode string) { - s.mu.Lock() - cancel, ok := s.taskContext[taskCode] - s.mu.Unlock() - - if ok { - cancel() // 调取消函数停止任务 - } else { - s.logger.Info(fmt.Sprintf("任务未找到: %s", taskCode)) - } -} diff --git a/internal/dblogger/request_logger.go b/internal/dblogger/request_logger.go index 164181e..0c464b2 100644 --- a/internal/dblogger/request_logger.go +++ b/internal/dblogger/request_logger.go @@ -5,10 +5,10 @@ import ( "log" "time" - "mini-chat/internal/proposal" - "mini-chat/internal/repository/mysql" - "mini-chat/internal/repository/mysql/dao" - "mini-chat/internal/repository/mysql/model" + "bindbox-game/internal/proposal" + "bindbox-game/internal/repository/mysql" + "bindbox-game/internal/repository/mysql/dao" + "bindbox-game/internal/repository/mysql/model" "github.com/spf13/cast" ) diff --git a/internal/metrics/metrics.go b/internal/metrics/metrics.go index e267459..4a03a90 100644 --- a/internal/metrics/metrics.go +++ b/internal/metrics/metrics.go @@ -1,7 +1,7 @@ package metrics import ( - "mini-chat/internal/proposal" + "bindbox-game/internal/proposal" ) // RecordHandler 指标处理 diff --git a/internal/pkg/core/context.go b/internal/pkg/core/context.go index 2a7b3cd..d268f6f 100644 --- a/internal/pkg/core/context.go +++ b/internal/pkg/core/context.go @@ -12,9 +12,9 @@ import ( "strings" "sync" - "mini-chat/internal/pkg/logger" - "mini-chat/internal/pkg/trace" - "mini-chat/internal/proposal" + "bindbox-game/internal/pkg/logger" + "bindbox-game/internal/pkg/trace" + "bindbox-game/internal/proposal" "github.com/gin-gonic/gin" "github.com/gin-gonic/gin/binding" diff --git a/internal/pkg/core/core.go b/internal/pkg/core/core.go index 5fb4f2b..af3e13e 100644 --- a/internal/pkg/core/core.go +++ b/internal/pkg/core/core.go @@ -8,17 +8,17 @@ import ( "runtime/debug" "time" - "mini-chat/configs" - _ "mini-chat/docs" - "mini-chat/internal/code" - "mini-chat/internal/pkg/cors" - "mini-chat/internal/pkg/env" - "mini-chat/internal/pkg/errors" - "mini-chat/internal/pkg/logger" - "mini-chat/internal/pkg/startup" - "mini-chat/internal/pkg/timeutil" - "mini-chat/internal/pkg/trace" - "mini-chat/internal/proposal" + "bindbox-game/configs" + _ "bindbox-game/docs" + "bindbox-game/internal/code" + "bindbox-game/internal/pkg/cors" + "bindbox-game/internal/pkg/env" + "bindbox-game/internal/pkg/errors" + "bindbox-game/internal/pkg/logger" + "bindbox-game/internal/pkg/startup" + "bindbox-game/internal/pkg/timeutil" + "bindbox-game/internal/pkg/trace" + "bindbox-game/internal/proposal" "github.com/gin-contrib/pprof" "github.com/gin-gonic/gin" diff --git a/internal/pkg/core/error.go b/internal/pkg/core/error.go index 80c80b1..6722145 100644 --- a/internal/pkg/core/error.go +++ b/internal/pkg/core/error.go @@ -1,7 +1,7 @@ package core import ( - "mini-chat/internal/pkg/errors" + "bindbox-game/internal/pkg/errors" ) var _ BusinessError = (*businessError)(nil) diff --git a/internal/pkg/cryptoaes/cryptoaes_test.go b/internal/pkg/cryptoaes/cryptoaes_test.go index f06e18d..e1a0fe0 100644 --- a/internal/pkg/cryptoaes/cryptoaes_test.go +++ b/internal/pkg/cryptoaes/cryptoaes_test.go @@ -7,7 +7,8 @@ const ( ) func TestEncrypt2(t *testing.T) { - t.Log(Encrypt(key, "mini-chat")) + //t.Log(Encrypt(key, "ishfd@2025")) OP001 + t.Log(Encrypt(key, "xassd@2025")) } func TestDecrypt(t *testing.T) { diff --git a/internal/pkg/debug/logger.go b/internal/pkg/debug/logger.go index 0f16c0c..65d5a4a 100644 --- a/internal/pkg/debug/logger.go +++ b/internal/pkg/debug/logger.go @@ -4,8 +4,8 @@ import ( "runtime" "strconv" - "mini-chat/internal/pkg/core" - "mini-chat/internal/pkg/trace" + "bindbox-game/internal/pkg/core" + "bindbox-game/internal/pkg/trace" ) type debug struct { diff --git a/internal/pkg/httpclient/client.go b/internal/pkg/httpclient/client.go index 427ec05..8a5b1e7 100644 --- a/internal/pkg/httpclient/client.go +++ b/internal/pkg/httpclient/client.go @@ -1,8 +1,8 @@ package httpclient import ( - "mini-chat/internal/pkg/core" - "mini-chat/internal/pkg/trace" + "bindbox-game/internal/pkg/core" + "bindbox-game/internal/pkg/trace" "github.com/bytedance/sonic" "github.com/go-resty/resty/v2" diff --git a/internal/pkg/jwtoken/jwtoken.go b/internal/pkg/jwtoken/jwtoken.go index 2007ecf..9d39be2 100644 --- a/internal/pkg/jwtoken/jwtoken.go +++ b/internal/pkg/jwtoken/jwtoken.go @@ -3,7 +3,7 @@ package jwtoken import ( "time" - "mini-chat/internal/proposal" + "bindbox-game/internal/proposal" "github.com/golang-jwt/jwt/v5" ) diff --git a/internal/pkg/jwtoken/jwtoken_test.go b/internal/pkg/jwtoken/jwtoken_test.go index 3a6d3a2..32287f5 100644 --- a/internal/pkg/jwtoken/jwtoken_test.go +++ b/internal/pkg/jwtoken/jwtoken_test.go @@ -5,7 +5,7 @@ import ( "testing" "time" - "mini-chat/internal/proposal" + "bindbox-game/internal/proposal" ) const secret = "i1ydX9RtHyuJTrw7frcu" diff --git a/internal/pkg/logger/logger.go b/internal/pkg/logger/logger.go index 123c137..1d69f16 100644 --- a/internal/pkg/logger/logger.go +++ b/internal/pkg/logger/logger.go @@ -10,8 +10,8 @@ import ( "path/filepath" "time" - "mini-chat/internal/repository/mysql/dao" - "mini-chat/internal/repository/mysql/model" + "bindbox-game/internal/repository/mysql/dao" + "bindbox-game/internal/repository/mysql/model" "go.uber.org/zap" "go.uber.org/zap/zapcore" diff --git a/internal/pkg/logger/logger_test.go b/internal/pkg/logger/logger_test.go index 7e92e7e..1b2925d 100644 --- a/internal/pkg/logger/logger_test.go +++ b/internal/pkg/logger/logger_test.go @@ -3,7 +3,7 @@ package logger import ( "testing" - "mini-chat/internal/pkg/timeutil" + "bindbox-game/internal/pkg/timeutil" "github.com/pkg/errors" "go.uber.org/zap" diff --git a/internal/pkg/startup/info.go b/internal/pkg/startup/info.go index 4f1ead1..1037408 100644 --- a/internal/pkg/startup/info.go +++ b/internal/pkg/startup/info.go @@ -5,8 +5,8 @@ import ( "runtime" "time" - "mini-chat/configs" - "mini-chat/internal/pkg/env" + "bindbox-game/configs" + "bindbox-game/internal/pkg/env" "github.com/common-nighthawk/go-figure" "github.com/fatih/color" diff --git a/internal/pkg/trace/trace.go b/internal/pkg/trace/trace.go index 1a0e1ae..d0b07a0 100644 --- a/internal/pkg/trace/trace.go +++ b/internal/pkg/trace/trace.go @@ -3,7 +3,7 @@ package trace import ( "sync" - "mini-chat/internal/pkg/idgen" + "bindbox-game/internal/pkg/idgen" ) const Header = "TRACE-ID" diff --git a/internal/pkg/validation/validation.go b/internal/pkg/validation/validation.go index 9f0b157..28ab00a 100644 --- a/internal/pkg/validation/validation.go +++ b/internal/pkg/validation/validation.go @@ -3,7 +3,7 @@ package validation import ( "fmt" - "mini-chat/configs" + "bindbox-game/configs" "github.com/gin-gonic/gin/binding" "github.com/go-playground/locales/en" diff --git a/internal/pkg/wechat/code2session.go b/internal/pkg/wechat/code2session.go new file mode 100644 index 0000000..6a1b5a7 --- /dev/null +++ b/internal/pkg/wechat/code2session.go @@ -0,0 +1,53 @@ +package wechat + +import ( + "encoding/json" + "fmt" + "net/http" + + "bindbox-game/internal/pkg/core" + "bindbox-game/internal/pkg/httpclient" +) + +type Code2SessionResponse struct { + OpenID string `json:"openid"` + UnionID string `json:"unionid,omitempty"` + SessionKey string `json:"session_key"` + ErrCode int `json:"errcode,omitempty"` + ErrMsg string `json:"errmsg,omitempty"` +} + +func Code2Session(ctx core.Context, config *WechatConfig, code string) (*Code2SessionResponse, error) { + if config == nil || config.AppID == "" || config.AppSecret == "" { + return nil, fmt.Errorf("微信配置缺失") + } + if code == "" { + return nil, fmt.Errorf("code 不能为空") + } + client := httpclient.GetHttpClientWithContext(ctx.RequestContext()) + resp, err := client.R(). + SetQueryParams(map[string]string{ + "appid": config.AppID, + "secret": config.AppSecret, + "js_code": code, + "grant_type": "authorization_code", + }). + Get("https://api.weixin.qq.com/sns/jscode2session") + if err != nil { + return nil, err + } + if resp.StatusCode() != http.StatusOK { + return nil, fmt.Errorf("HTTP错误: %d", resp.StatusCode()) + } + var r Code2SessionResponse + if err := json.Unmarshal(resp.Body(), &r); err != nil { + return nil, err + } + if r.ErrCode != 0 { + return nil, fmt.Errorf(r.ErrMsg) + } + if r.OpenID == "" || r.SessionKey == "" { + return nil, fmt.Errorf("响应缺少必要字段") + } + return &r, nil +} diff --git a/internal/pkg/wechat/phone_number.go b/internal/pkg/wechat/phone_number.go new file mode 100644 index 0000000..ca4b48b --- /dev/null +++ b/internal/pkg/wechat/phone_number.go @@ -0,0 +1,50 @@ +package wechat + +import ( + "encoding/json" + "fmt" + "net/http" + + "bindbox-game/internal/pkg/core" + "bindbox-game/internal/pkg/httpclient" +) + +type PhoneNumberResponse struct { + ErrCode int `json:"errcode,omitempty"` + ErrMsg string `json:"errmsg,omitempty"` + PhoneInfo struct { + PhoneNumber string `json:"phoneNumber"` + PurePhoneNumber string `json:"purePhoneNumber"` + CountryCode string `json:"countryCode"` + } `json:"phone_info"` +} + +// GetPhoneNumber 使用微信开放接口换取用户手机号 +// DOC: https://developers.weixin.qq.com/miniprogram/dev/OpenApiDoc/user-info/phone-number/getPhoneNumber.html +func GetPhoneNumber(ctx core.Context, accessToken, code string) (*PhoneNumberResponse, error) { + if accessToken == "" || code == "" { + return nil, fmt.Errorf("参数缺失") + } + client := httpclient.GetHttpClientWithContext(ctx.RequestContext()) + resp, err := client.R(). + SetQueryParam("access_token", accessToken). + SetBody(map[string]string{"code": code}). + Post("https://api.weixin.qq.com/wxa/business/getuserphonenumber") + if err != nil { + return nil, err + } + if resp.StatusCode() != http.StatusOK { + return nil, fmt.Errorf("HTTP错误: %d", resp.StatusCode()) + } + var r PhoneNumberResponse + if err := json.Unmarshal(resp.Body(), &r); err != nil { + return nil, err + } + if r.ErrCode != 0 { + return nil, fmt.Errorf(r.ErrMsg) + } + if r.PhoneInfo.PurePhoneNumber == "" && r.PhoneInfo.PhoneNumber == "" { + return nil, fmt.Errorf("未获取到手机号") + } + return &r, nil +} \ No newline at end of file diff --git a/internal/pkg/wechat/qrcode.go b/internal/pkg/wechat/qrcode.go index e8d63b7..30c7564 100644 --- a/internal/pkg/wechat/qrcode.go +++ b/internal/pkg/wechat/qrcode.go @@ -8,8 +8,8 @@ import ( "sync" "time" - "mini-chat/internal/pkg/core" - "mini-chat/internal/pkg/httpclient" + "bindbox-game/internal/pkg/core" + "bindbox-game/internal/pkg/httpclient" ) // AccessTokenRequest 获取 access_token 请求参数 diff --git a/internal/repository/mysql/dao/activities.gen.go b/internal/repository/mysql/dao/activities.gen.go new file mode 100644 index 0000000..9fd908a --- /dev/null +++ b/internal/repository/mysql/dao/activities.gen.go @@ -0,0 +1,360 @@ +// Code generated by gorm.io/gen. DO NOT EDIT. +// Code generated by gorm.io/gen. DO NOT EDIT. +// Code generated by gorm.io/gen. DO NOT EDIT. + +package dao + +import ( + "context" + + "gorm.io/gorm" + "gorm.io/gorm/clause" + "gorm.io/gorm/schema" + + "gorm.io/gen" + "gorm.io/gen/field" + + "gorm.io/plugin/dbresolver" + + "bindbox-game/internal/repository/mysql/model" +) + +func newActivities(db *gorm.DB, opts ...gen.DOOption) activities { + _activities := activities{} + + _activities.activitiesDo.UseDB(db, opts...) + _activities.activitiesDo.UseModel(&model.Activities{}) + + tableName := _activities.activitiesDo.TableName() + _activities.ALL = field.NewAsterisk(tableName) + _activities.ID = field.NewInt64(tableName, "id") + _activities.CreatedAt = field.NewTime(tableName, "created_at") + _activities.UpdatedAt = field.NewTime(tableName, "updated_at") + _activities.Name = field.NewString(tableName, "name") + _activities.Banner = field.NewString(tableName, "banner") + _activities.ActivityCategoryID = field.NewInt64(tableName, "activity_category_id") + _activities.Status = field.NewInt32(tableName, "status") + _activities.PriceDraw = field.NewInt64(tableName, "price_draw") + _activities.IsBoss = field.NewInt32(tableName, "is_boss") + _activities.StartTime = field.NewTime(tableName, "start_time") + _activities.EndTime = field.NewTime(tableName, "end_time") + + _activities.fillFieldMap() + + return _activities +} + +// activities 活动 +type activities struct { + activitiesDo + + ALL field.Asterisk + ID field.Int64 // 主键ID + CreatedAt field.Time // 创建时间 + UpdatedAt field.Time // 更新时间 + Name field.String // 活动名称 + Banner field.String // 活动横幅/海报URL + ActivityCategoryID field.Int64 // 活动所属分类ID(activity_categories.id,可空) + Status field.Int32 // 状态:1进行中 2下线 + PriceDraw field.Int64 // 活动门票价格 + IsBoss field.Int32 // Boss: 1 是 0 不是 + StartTime field.Time // 开始时间 + EndTime field.Time // 结束时间 + + fieldMap map[string]field.Expr +} + +func (a activities) Table(newTableName string) *activities { + a.activitiesDo.UseTable(newTableName) + return a.updateTableName(newTableName) +} + +func (a activities) As(alias string) *activities { + a.activitiesDo.DO = *(a.activitiesDo.As(alias).(*gen.DO)) + return a.updateTableName(alias) +} + +func (a *activities) updateTableName(table string) *activities { + a.ALL = field.NewAsterisk(table) + a.ID = field.NewInt64(table, "id") + a.CreatedAt = field.NewTime(table, "created_at") + a.UpdatedAt = field.NewTime(table, "updated_at") + a.Name = field.NewString(table, "name") + a.Banner = field.NewString(table, "banner") + a.ActivityCategoryID = field.NewInt64(table, "activity_category_id") + a.Status = field.NewInt32(table, "status") + a.PriceDraw = field.NewInt64(table, "price_draw") + a.IsBoss = field.NewInt32(table, "is_boss") + a.StartTime = field.NewTime(table, "start_time") + a.EndTime = field.NewTime(table, "end_time") + + a.fillFieldMap() + + return a +} + +func (a *activities) GetFieldByName(fieldName string) (field.OrderExpr, bool) { + _f, ok := a.fieldMap[fieldName] + if !ok || _f == nil { + return nil, false + } + _oe, ok := _f.(field.OrderExpr) + return _oe, ok +} + +func (a *activities) fillFieldMap() { + a.fieldMap = make(map[string]field.Expr, 11) + a.fieldMap["id"] = a.ID + a.fieldMap["created_at"] = a.CreatedAt + a.fieldMap["updated_at"] = a.UpdatedAt + a.fieldMap["name"] = a.Name + a.fieldMap["banner"] = a.Banner + a.fieldMap["activity_category_id"] = a.ActivityCategoryID + a.fieldMap["status"] = a.Status + a.fieldMap["price_draw"] = a.PriceDraw + a.fieldMap["is_boss"] = a.IsBoss + a.fieldMap["start_time"] = a.StartTime + a.fieldMap["end_time"] = a.EndTime +} + +func (a activities) clone(db *gorm.DB) activities { + a.activitiesDo.ReplaceConnPool(db.Statement.ConnPool) + return a +} + +func (a activities) replaceDB(db *gorm.DB) activities { + a.activitiesDo.ReplaceDB(db) + return a +} + +type activitiesDo struct{ gen.DO } + +func (a activitiesDo) Debug() *activitiesDo { + return a.withDO(a.DO.Debug()) +} + +func (a activitiesDo) WithContext(ctx context.Context) *activitiesDo { + return a.withDO(a.DO.WithContext(ctx)) +} + +func (a activitiesDo) ReadDB() *activitiesDo { + return a.Clauses(dbresolver.Read) +} + +func (a activitiesDo) WriteDB() *activitiesDo { + return a.Clauses(dbresolver.Write) +} + +func (a activitiesDo) Session(config *gorm.Session) *activitiesDo { + return a.withDO(a.DO.Session(config)) +} + +func (a activitiesDo) Clauses(conds ...clause.Expression) *activitiesDo { + return a.withDO(a.DO.Clauses(conds...)) +} + +func (a activitiesDo) Returning(value interface{}, columns ...string) *activitiesDo { + return a.withDO(a.DO.Returning(value, columns...)) +} + +func (a activitiesDo) Not(conds ...gen.Condition) *activitiesDo { + return a.withDO(a.DO.Not(conds...)) +} + +func (a activitiesDo) Or(conds ...gen.Condition) *activitiesDo { + return a.withDO(a.DO.Or(conds...)) +} + +func (a activitiesDo) Select(conds ...field.Expr) *activitiesDo { + return a.withDO(a.DO.Select(conds...)) +} + +func (a activitiesDo) Where(conds ...gen.Condition) *activitiesDo { + return a.withDO(a.DO.Where(conds...)) +} + +func (a activitiesDo) Order(conds ...field.Expr) *activitiesDo { + return a.withDO(a.DO.Order(conds...)) +} + +func (a activitiesDo) Distinct(cols ...field.Expr) *activitiesDo { + return a.withDO(a.DO.Distinct(cols...)) +} + +func (a activitiesDo) Omit(cols ...field.Expr) *activitiesDo { + return a.withDO(a.DO.Omit(cols...)) +} + +func (a activitiesDo) Join(table schema.Tabler, on ...field.Expr) *activitiesDo { + return a.withDO(a.DO.Join(table, on...)) +} + +func (a activitiesDo) LeftJoin(table schema.Tabler, on ...field.Expr) *activitiesDo { + return a.withDO(a.DO.LeftJoin(table, on...)) +} + +func (a activitiesDo) RightJoin(table schema.Tabler, on ...field.Expr) *activitiesDo { + return a.withDO(a.DO.RightJoin(table, on...)) +} + +func (a activitiesDo) Group(cols ...field.Expr) *activitiesDo { + return a.withDO(a.DO.Group(cols...)) +} + +func (a activitiesDo) Having(conds ...gen.Condition) *activitiesDo { + return a.withDO(a.DO.Having(conds...)) +} + +func (a activitiesDo) Limit(limit int) *activitiesDo { + return a.withDO(a.DO.Limit(limit)) +} + +func (a activitiesDo) Offset(offset int) *activitiesDo { + return a.withDO(a.DO.Offset(offset)) +} + +func (a activitiesDo) Scopes(funcs ...func(gen.Dao) gen.Dao) *activitiesDo { + return a.withDO(a.DO.Scopes(funcs...)) +} + +func (a activitiesDo) Unscoped() *activitiesDo { + return a.withDO(a.DO.Unscoped()) +} + +func (a activitiesDo) Create(values ...*model.Activities) error { + if len(values) == 0 { + return nil + } + return a.DO.Create(values) +} + +func (a activitiesDo) CreateInBatches(values []*model.Activities, batchSize int) error { + return a.DO.CreateInBatches(values, batchSize) +} + +// Save : !!! underlying implementation is different with GORM +// The method is equivalent to executing the statement: db.Clauses(clause.OnConflict{UpdateAll: true}).Create(values) +func (a activitiesDo) Save(values ...*model.Activities) error { + if len(values) == 0 { + return nil + } + return a.DO.Save(values) +} + +func (a activitiesDo) First() (*model.Activities, error) { + if result, err := a.DO.First(); err != nil { + return nil, err + } else { + return result.(*model.Activities), nil + } +} + +func (a activitiesDo) Take() (*model.Activities, error) { + if result, err := a.DO.Take(); err != nil { + return nil, err + } else { + return result.(*model.Activities), nil + } +} + +func (a activitiesDo) Last() (*model.Activities, error) { + if result, err := a.DO.Last(); err != nil { + return nil, err + } else { + return result.(*model.Activities), nil + } +} + +func (a activitiesDo) Find() ([]*model.Activities, error) { + result, err := a.DO.Find() + return result.([]*model.Activities), err +} + +func (a activitiesDo) FindInBatch(batchSize int, fc func(tx gen.Dao, batch int) error) (results []*model.Activities, err error) { + buf := make([]*model.Activities, 0, batchSize) + err = a.DO.FindInBatches(&buf, batchSize, func(tx gen.Dao, batch int) error { + defer func() { results = append(results, buf...) }() + return fc(tx, batch) + }) + return results, err +} + +func (a activitiesDo) FindInBatches(result *[]*model.Activities, batchSize int, fc func(tx gen.Dao, batch int) error) error { + return a.DO.FindInBatches(result, batchSize, fc) +} + +func (a activitiesDo) Attrs(attrs ...field.AssignExpr) *activitiesDo { + return a.withDO(a.DO.Attrs(attrs...)) +} + +func (a activitiesDo) Assign(attrs ...field.AssignExpr) *activitiesDo { + return a.withDO(a.DO.Assign(attrs...)) +} + +func (a activitiesDo) Joins(fields ...field.RelationField) *activitiesDo { + for _, _f := range fields { + a = *a.withDO(a.DO.Joins(_f)) + } + return &a +} + +func (a activitiesDo) Preload(fields ...field.RelationField) *activitiesDo { + for _, _f := range fields { + a = *a.withDO(a.DO.Preload(_f)) + } + return &a +} + +func (a activitiesDo) FirstOrInit() (*model.Activities, error) { + if result, err := a.DO.FirstOrInit(); err != nil { + return nil, err + } else { + return result.(*model.Activities), nil + } +} + +func (a activitiesDo) FirstOrCreate() (*model.Activities, error) { + if result, err := a.DO.FirstOrCreate(); err != nil { + return nil, err + } else { + return result.(*model.Activities), nil + } +} + +func (a activitiesDo) FindByPage(offset int, limit int) (result []*model.Activities, count int64, err error) { + result, err = a.Offset(offset).Limit(limit).Find() + if err != nil { + return + } + + if size := len(result); 0 < limit && 0 < size && size < limit { + count = int64(size + offset) + return + } + + count, err = a.Offset(-1).Limit(-1).Count() + return +} + +func (a activitiesDo) ScanByPage(result interface{}, offset int, limit int) (count int64, err error) { + count, err = a.Count() + if err != nil { + return + } + + err = a.Offset(offset).Limit(limit).Scan(result) + return +} + +func (a activitiesDo) Scan(result interface{}) (err error) { + return a.DO.Scan(result) +} + +func (a activitiesDo) Delete(models ...*model.Activities) (result gen.ResultInfo, err error) { + return a.DO.Delete(models) +} + +func (a *activitiesDo) withDO(do gen.Dao) *activitiesDo { + a.DO = *do.(*gen.DO) + return a +} diff --git a/internal/repository/mysql/dao/activity_categories.gen.go b/internal/repository/mysql/dao/activity_categories.gen.go new file mode 100644 index 0000000..2384e2d --- /dev/null +++ b/internal/repository/mysql/dao/activity_categories.gen.go @@ -0,0 +1,340 @@ +// Code generated by gorm.io/gen. DO NOT EDIT. +// Code generated by gorm.io/gen. DO NOT EDIT. +// Code generated by gorm.io/gen. DO NOT EDIT. + +package dao + +import ( + "context" + + "gorm.io/gorm" + "gorm.io/gorm/clause" + "gorm.io/gorm/schema" + + "gorm.io/gen" + "gorm.io/gen/field" + + "gorm.io/plugin/dbresolver" + + "bindbox-game/internal/repository/mysql/model" +) + +func newActivityCategories(db *gorm.DB, opts ...gen.DOOption) activityCategories { + _activityCategories := activityCategories{} + + _activityCategories.activityCategoriesDo.UseDB(db, opts...) + _activityCategories.activityCategoriesDo.UseModel(&model.ActivityCategories{}) + + tableName := _activityCategories.activityCategoriesDo.TableName() + _activityCategories.ALL = field.NewAsterisk(tableName) + _activityCategories.ID = field.NewInt64(tableName, "id") + _activityCategories.CreatedAt = field.NewTime(tableName, "created_at") + _activityCategories.UpdatedAt = field.NewTime(tableName, "updated_at") + _activityCategories.Name = field.NewString(tableName, "name") + _activityCategories.ParentID = field.NewInt64(tableName, "parent_id") + _activityCategories.Status = field.NewInt32(tableName, "status") + + _activityCategories.fillFieldMap() + + return _activityCategories +} + +// activityCategories 活动分类 +type activityCategories struct { + activityCategoriesDo + + ALL field.Asterisk + ID field.Int64 // 主键ID + CreatedAt field.Time // 创建时间 + UpdatedAt field.Time // 更新时间 + Name field.String // 活动分类名称 + ParentID field.Int64 // 父分类ID(可空) + Status field.Int32 // 状态:1启用 2禁用 + + fieldMap map[string]field.Expr +} + +func (a activityCategories) Table(newTableName string) *activityCategories { + a.activityCategoriesDo.UseTable(newTableName) + return a.updateTableName(newTableName) +} + +func (a activityCategories) As(alias string) *activityCategories { + a.activityCategoriesDo.DO = *(a.activityCategoriesDo.As(alias).(*gen.DO)) + return a.updateTableName(alias) +} + +func (a *activityCategories) updateTableName(table string) *activityCategories { + a.ALL = field.NewAsterisk(table) + a.ID = field.NewInt64(table, "id") + a.CreatedAt = field.NewTime(table, "created_at") + a.UpdatedAt = field.NewTime(table, "updated_at") + a.Name = field.NewString(table, "name") + a.ParentID = field.NewInt64(table, "parent_id") + a.Status = field.NewInt32(table, "status") + + a.fillFieldMap() + + return a +} + +func (a *activityCategories) GetFieldByName(fieldName string) (field.OrderExpr, bool) { + _f, ok := a.fieldMap[fieldName] + if !ok || _f == nil { + return nil, false + } + _oe, ok := _f.(field.OrderExpr) + return _oe, ok +} + +func (a *activityCategories) fillFieldMap() { + a.fieldMap = make(map[string]field.Expr, 6) + a.fieldMap["id"] = a.ID + a.fieldMap["created_at"] = a.CreatedAt + a.fieldMap["updated_at"] = a.UpdatedAt + a.fieldMap["name"] = a.Name + a.fieldMap["parent_id"] = a.ParentID + a.fieldMap["status"] = a.Status +} + +func (a activityCategories) clone(db *gorm.DB) activityCategories { + a.activityCategoriesDo.ReplaceConnPool(db.Statement.ConnPool) + return a +} + +func (a activityCategories) replaceDB(db *gorm.DB) activityCategories { + a.activityCategoriesDo.ReplaceDB(db) + return a +} + +type activityCategoriesDo struct{ gen.DO } + +func (a activityCategoriesDo) Debug() *activityCategoriesDo { + return a.withDO(a.DO.Debug()) +} + +func (a activityCategoriesDo) WithContext(ctx context.Context) *activityCategoriesDo { + return a.withDO(a.DO.WithContext(ctx)) +} + +func (a activityCategoriesDo) ReadDB() *activityCategoriesDo { + return a.Clauses(dbresolver.Read) +} + +func (a activityCategoriesDo) WriteDB() *activityCategoriesDo { + return a.Clauses(dbresolver.Write) +} + +func (a activityCategoriesDo) Session(config *gorm.Session) *activityCategoriesDo { + return a.withDO(a.DO.Session(config)) +} + +func (a activityCategoriesDo) Clauses(conds ...clause.Expression) *activityCategoriesDo { + return a.withDO(a.DO.Clauses(conds...)) +} + +func (a activityCategoriesDo) Returning(value interface{}, columns ...string) *activityCategoriesDo { + return a.withDO(a.DO.Returning(value, columns...)) +} + +func (a activityCategoriesDo) Not(conds ...gen.Condition) *activityCategoriesDo { + return a.withDO(a.DO.Not(conds...)) +} + +func (a activityCategoriesDo) Or(conds ...gen.Condition) *activityCategoriesDo { + return a.withDO(a.DO.Or(conds...)) +} + +func (a activityCategoriesDo) Select(conds ...field.Expr) *activityCategoriesDo { + return a.withDO(a.DO.Select(conds...)) +} + +func (a activityCategoriesDo) Where(conds ...gen.Condition) *activityCategoriesDo { + return a.withDO(a.DO.Where(conds...)) +} + +func (a activityCategoriesDo) Order(conds ...field.Expr) *activityCategoriesDo { + return a.withDO(a.DO.Order(conds...)) +} + +func (a activityCategoriesDo) Distinct(cols ...field.Expr) *activityCategoriesDo { + return a.withDO(a.DO.Distinct(cols...)) +} + +func (a activityCategoriesDo) Omit(cols ...field.Expr) *activityCategoriesDo { + return a.withDO(a.DO.Omit(cols...)) +} + +func (a activityCategoriesDo) Join(table schema.Tabler, on ...field.Expr) *activityCategoriesDo { + return a.withDO(a.DO.Join(table, on...)) +} + +func (a activityCategoriesDo) LeftJoin(table schema.Tabler, on ...field.Expr) *activityCategoriesDo { + return a.withDO(a.DO.LeftJoin(table, on...)) +} + +func (a activityCategoriesDo) RightJoin(table schema.Tabler, on ...field.Expr) *activityCategoriesDo { + return a.withDO(a.DO.RightJoin(table, on...)) +} + +func (a activityCategoriesDo) Group(cols ...field.Expr) *activityCategoriesDo { + return a.withDO(a.DO.Group(cols...)) +} + +func (a activityCategoriesDo) Having(conds ...gen.Condition) *activityCategoriesDo { + return a.withDO(a.DO.Having(conds...)) +} + +func (a activityCategoriesDo) Limit(limit int) *activityCategoriesDo { + return a.withDO(a.DO.Limit(limit)) +} + +func (a activityCategoriesDo) Offset(offset int) *activityCategoriesDo { + return a.withDO(a.DO.Offset(offset)) +} + +func (a activityCategoriesDo) Scopes(funcs ...func(gen.Dao) gen.Dao) *activityCategoriesDo { + return a.withDO(a.DO.Scopes(funcs...)) +} + +func (a activityCategoriesDo) Unscoped() *activityCategoriesDo { + return a.withDO(a.DO.Unscoped()) +} + +func (a activityCategoriesDo) Create(values ...*model.ActivityCategories) error { + if len(values) == 0 { + return nil + } + return a.DO.Create(values) +} + +func (a activityCategoriesDo) CreateInBatches(values []*model.ActivityCategories, batchSize int) error { + return a.DO.CreateInBatches(values, batchSize) +} + +// Save : !!! underlying implementation is different with GORM +// The method is equivalent to executing the statement: db.Clauses(clause.OnConflict{UpdateAll: true}).Create(values) +func (a activityCategoriesDo) Save(values ...*model.ActivityCategories) error { + if len(values) == 0 { + return nil + } + return a.DO.Save(values) +} + +func (a activityCategoriesDo) First() (*model.ActivityCategories, error) { + if result, err := a.DO.First(); err != nil { + return nil, err + } else { + return result.(*model.ActivityCategories), nil + } +} + +func (a activityCategoriesDo) Take() (*model.ActivityCategories, error) { + if result, err := a.DO.Take(); err != nil { + return nil, err + } else { + return result.(*model.ActivityCategories), nil + } +} + +func (a activityCategoriesDo) Last() (*model.ActivityCategories, error) { + if result, err := a.DO.Last(); err != nil { + return nil, err + } else { + return result.(*model.ActivityCategories), nil + } +} + +func (a activityCategoriesDo) Find() ([]*model.ActivityCategories, error) { + result, err := a.DO.Find() + return result.([]*model.ActivityCategories), err +} + +func (a activityCategoriesDo) FindInBatch(batchSize int, fc func(tx gen.Dao, batch int) error) (results []*model.ActivityCategories, err error) { + buf := make([]*model.ActivityCategories, 0, batchSize) + err = a.DO.FindInBatches(&buf, batchSize, func(tx gen.Dao, batch int) error { + defer func() { results = append(results, buf...) }() + return fc(tx, batch) + }) + return results, err +} + +func (a activityCategoriesDo) FindInBatches(result *[]*model.ActivityCategories, batchSize int, fc func(tx gen.Dao, batch int) error) error { + return a.DO.FindInBatches(result, batchSize, fc) +} + +func (a activityCategoriesDo) Attrs(attrs ...field.AssignExpr) *activityCategoriesDo { + return a.withDO(a.DO.Attrs(attrs...)) +} + +func (a activityCategoriesDo) Assign(attrs ...field.AssignExpr) *activityCategoriesDo { + return a.withDO(a.DO.Assign(attrs...)) +} + +func (a activityCategoriesDo) Joins(fields ...field.RelationField) *activityCategoriesDo { + for _, _f := range fields { + a = *a.withDO(a.DO.Joins(_f)) + } + return &a +} + +func (a activityCategoriesDo) Preload(fields ...field.RelationField) *activityCategoriesDo { + for _, _f := range fields { + a = *a.withDO(a.DO.Preload(_f)) + } + return &a +} + +func (a activityCategoriesDo) FirstOrInit() (*model.ActivityCategories, error) { + if result, err := a.DO.FirstOrInit(); err != nil { + return nil, err + } else { + return result.(*model.ActivityCategories), nil + } +} + +func (a activityCategoriesDo) FirstOrCreate() (*model.ActivityCategories, error) { + if result, err := a.DO.FirstOrCreate(); err != nil { + return nil, err + } else { + return result.(*model.ActivityCategories), nil + } +} + +func (a activityCategoriesDo) FindByPage(offset int, limit int) (result []*model.ActivityCategories, count int64, err error) { + result, err = a.Offset(offset).Limit(limit).Find() + if err != nil { + return + } + + if size := len(result); 0 < limit && 0 < size && size < limit { + count = int64(size + offset) + return + } + + count, err = a.Offset(-1).Limit(-1).Count() + return +} + +func (a activityCategoriesDo) ScanByPage(result interface{}, offset int, limit int) (count int64, err error) { + count, err = a.Count() + if err != nil { + return + } + + err = a.Offset(offset).Limit(limit).Scan(result) + return +} + +func (a activityCategoriesDo) Scan(result interface{}) (err error) { + return a.DO.Scan(result) +} + +func (a activityCategoriesDo) Delete(models ...*model.ActivityCategories) (result gen.ResultInfo, err error) { + return a.DO.Delete(models) +} + +func (a *activityCategoriesDo) withDO(do gen.Dao) *activityCategoriesDo { + a.DO = *do.(*gen.DO) + return a +} diff --git a/internal/repository/mysql/dao/activity_draw_effects.gen.go b/internal/repository/mysql/dao/activity_draw_effects.gen.go new file mode 100644 index 0000000..a55a277 --- /dev/null +++ b/internal/repository/mysql/dao/activity_draw_effects.gen.go @@ -0,0 +1,380 @@ +// Code generated by gorm.io/gen. DO NOT EDIT. +// Code generated by gorm.io/gen. DO NOT EDIT. +// Code generated by gorm.io/gen. DO NOT EDIT. + +package dao + +import ( + "context" + + "gorm.io/gorm" + "gorm.io/gorm/clause" + "gorm.io/gorm/schema" + + "gorm.io/gen" + "gorm.io/gen/field" + + "gorm.io/plugin/dbresolver" + + "bindbox-game/internal/repository/mysql/model" +) + +func newActivityDrawEffects(db *gorm.DB, opts ...gen.DOOption) activityDrawEffects { + _activityDrawEffects := activityDrawEffects{} + + _activityDrawEffects.activityDrawEffectsDo.UseDB(db, opts...) + _activityDrawEffects.activityDrawEffectsDo.UseModel(&model.ActivityDrawEffects{}) + + tableName := _activityDrawEffects.activityDrawEffectsDo.TableName() + _activityDrawEffects.ALL = field.NewAsterisk(tableName) + _activityDrawEffects.ID = field.NewInt64(tableName, "id") + _activityDrawEffects.CreatedAt = field.NewTime(tableName, "created_at") + _activityDrawEffects.DrawLogID = field.NewInt64(tableName, "draw_log_id") + _activityDrawEffects.UserID = field.NewInt64(tableName, "user_id") + _activityDrawEffects.UserItemCardID = field.NewInt64(tableName, "user_item_card_id") + _activityDrawEffects.SystemItemCardID = field.NewInt64(tableName, "system_item_card_id") + _activityDrawEffects.Applied = field.NewInt32(tableName, "applied") + _activityDrawEffects.CardType = field.NewInt32(tableName, "card_type") + _activityDrawEffects.EffectType = field.NewInt32(tableName, "effect_type") + _activityDrawEffects.RewardMultiplierX1000 = field.NewInt32(tableName, "reward_multiplier_x1000") + _activityDrawEffects.ProbabilityDeltaX1000 = field.NewInt32(tableName, "probability_delta_x1000") + _activityDrawEffects.ScopeType = field.NewInt32(tableName, "scope_type") + _activityDrawEffects.ActivityCategoryID = field.NewInt64(tableName, "activity_category_id") + _activityDrawEffects.ActivityID = field.NewInt64(tableName, "activity_id") + _activityDrawEffects.IssueID = field.NewInt64(tableName, "issue_id") + _activityDrawEffects.Remark = field.NewString(tableName, "remark") + + _activityDrawEffects.fillFieldMap() + + return _activityDrawEffects +} + +// activityDrawEffects 抽奖效果日志 +type activityDrawEffects struct { + activityDrawEffectsDo + + ALL field.Asterisk + ID field.Int64 // 主键ID + CreatedAt field.Time // 创建时间 + DrawLogID field.Int64 // 抽奖日志ID(activity_draw_logs.id) + UserID field.Int64 // 用户ID(users.id) + UserItemCardID field.Int64 // 用户卡实例ID(user_item_cards.id) + SystemItemCardID field.Int64 // 卡模板ID(system_item_cards.id) + Applied field.Int32 // 是否生效:0否 1是 + CardType field.Int32 // 卡类型快照 + EffectType field.Int32 // 效果类型快照 + RewardMultiplierX1000 field.Int32 // 奖励倍数(千分比) + ProbabilityDeltaX1000 field.Int32 // 概率相对增益(千分比) + ScopeType field.Int32 // 适用范围快照 + ActivityCategoryID field.Int64 // 范围快照-活动分类ID + ActivityID field.Int64 // 范围快照-活动ID + IssueID field.Int64 // 范围快照-期ID + Remark field.String // 备注 + + fieldMap map[string]field.Expr +} + +func (a activityDrawEffects) Table(newTableName string) *activityDrawEffects { + a.activityDrawEffectsDo.UseTable(newTableName) + return a.updateTableName(newTableName) +} + +func (a activityDrawEffects) As(alias string) *activityDrawEffects { + a.activityDrawEffectsDo.DO = *(a.activityDrawEffectsDo.As(alias).(*gen.DO)) + return a.updateTableName(alias) +} + +func (a *activityDrawEffects) updateTableName(table string) *activityDrawEffects { + a.ALL = field.NewAsterisk(table) + a.ID = field.NewInt64(table, "id") + a.CreatedAt = field.NewTime(table, "created_at") + a.DrawLogID = field.NewInt64(table, "draw_log_id") + a.UserID = field.NewInt64(table, "user_id") + a.UserItemCardID = field.NewInt64(table, "user_item_card_id") + a.SystemItemCardID = field.NewInt64(table, "system_item_card_id") + a.Applied = field.NewInt32(table, "applied") + a.CardType = field.NewInt32(table, "card_type") + a.EffectType = field.NewInt32(table, "effect_type") + a.RewardMultiplierX1000 = field.NewInt32(table, "reward_multiplier_x1000") + a.ProbabilityDeltaX1000 = field.NewInt32(table, "probability_delta_x1000") + a.ScopeType = field.NewInt32(table, "scope_type") + a.ActivityCategoryID = field.NewInt64(table, "activity_category_id") + a.ActivityID = field.NewInt64(table, "activity_id") + a.IssueID = field.NewInt64(table, "issue_id") + a.Remark = field.NewString(table, "remark") + + a.fillFieldMap() + + return a +} + +func (a *activityDrawEffects) GetFieldByName(fieldName string) (field.OrderExpr, bool) { + _f, ok := a.fieldMap[fieldName] + if !ok || _f == nil { + return nil, false + } + _oe, ok := _f.(field.OrderExpr) + return _oe, ok +} + +func (a *activityDrawEffects) fillFieldMap() { + a.fieldMap = make(map[string]field.Expr, 16) + a.fieldMap["id"] = a.ID + a.fieldMap["created_at"] = a.CreatedAt + a.fieldMap["draw_log_id"] = a.DrawLogID + a.fieldMap["user_id"] = a.UserID + a.fieldMap["user_item_card_id"] = a.UserItemCardID + a.fieldMap["system_item_card_id"] = a.SystemItemCardID + a.fieldMap["applied"] = a.Applied + a.fieldMap["card_type"] = a.CardType + a.fieldMap["effect_type"] = a.EffectType + a.fieldMap["reward_multiplier_x1000"] = a.RewardMultiplierX1000 + a.fieldMap["probability_delta_x1000"] = a.ProbabilityDeltaX1000 + a.fieldMap["scope_type"] = a.ScopeType + a.fieldMap["activity_category_id"] = a.ActivityCategoryID + a.fieldMap["activity_id"] = a.ActivityID + a.fieldMap["issue_id"] = a.IssueID + a.fieldMap["remark"] = a.Remark +} + +func (a activityDrawEffects) clone(db *gorm.DB) activityDrawEffects { + a.activityDrawEffectsDo.ReplaceConnPool(db.Statement.ConnPool) + return a +} + +func (a activityDrawEffects) replaceDB(db *gorm.DB) activityDrawEffects { + a.activityDrawEffectsDo.ReplaceDB(db) + return a +} + +type activityDrawEffectsDo struct{ gen.DO } + +func (a activityDrawEffectsDo) Debug() *activityDrawEffectsDo { + return a.withDO(a.DO.Debug()) +} + +func (a activityDrawEffectsDo) WithContext(ctx context.Context) *activityDrawEffectsDo { + return a.withDO(a.DO.WithContext(ctx)) +} + +func (a activityDrawEffectsDo) ReadDB() *activityDrawEffectsDo { + return a.Clauses(dbresolver.Read) +} + +func (a activityDrawEffectsDo) WriteDB() *activityDrawEffectsDo { + return a.Clauses(dbresolver.Write) +} + +func (a activityDrawEffectsDo) Session(config *gorm.Session) *activityDrawEffectsDo { + return a.withDO(a.DO.Session(config)) +} + +func (a activityDrawEffectsDo) Clauses(conds ...clause.Expression) *activityDrawEffectsDo { + return a.withDO(a.DO.Clauses(conds...)) +} + +func (a activityDrawEffectsDo) Returning(value interface{}, columns ...string) *activityDrawEffectsDo { + return a.withDO(a.DO.Returning(value, columns...)) +} + +func (a activityDrawEffectsDo) Not(conds ...gen.Condition) *activityDrawEffectsDo { + return a.withDO(a.DO.Not(conds...)) +} + +func (a activityDrawEffectsDo) Or(conds ...gen.Condition) *activityDrawEffectsDo { + return a.withDO(a.DO.Or(conds...)) +} + +func (a activityDrawEffectsDo) Select(conds ...field.Expr) *activityDrawEffectsDo { + return a.withDO(a.DO.Select(conds...)) +} + +func (a activityDrawEffectsDo) Where(conds ...gen.Condition) *activityDrawEffectsDo { + return a.withDO(a.DO.Where(conds...)) +} + +func (a activityDrawEffectsDo) Order(conds ...field.Expr) *activityDrawEffectsDo { + return a.withDO(a.DO.Order(conds...)) +} + +func (a activityDrawEffectsDo) Distinct(cols ...field.Expr) *activityDrawEffectsDo { + return a.withDO(a.DO.Distinct(cols...)) +} + +func (a activityDrawEffectsDo) Omit(cols ...field.Expr) *activityDrawEffectsDo { + return a.withDO(a.DO.Omit(cols...)) +} + +func (a activityDrawEffectsDo) Join(table schema.Tabler, on ...field.Expr) *activityDrawEffectsDo { + return a.withDO(a.DO.Join(table, on...)) +} + +func (a activityDrawEffectsDo) LeftJoin(table schema.Tabler, on ...field.Expr) *activityDrawEffectsDo { + return a.withDO(a.DO.LeftJoin(table, on...)) +} + +func (a activityDrawEffectsDo) RightJoin(table schema.Tabler, on ...field.Expr) *activityDrawEffectsDo { + return a.withDO(a.DO.RightJoin(table, on...)) +} + +func (a activityDrawEffectsDo) Group(cols ...field.Expr) *activityDrawEffectsDo { + return a.withDO(a.DO.Group(cols...)) +} + +func (a activityDrawEffectsDo) Having(conds ...gen.Condition) *activityDrawEffectsDo { + return a.withDO(a.DO.Having(conds...)) +} + +func (a activityDrawEffectsDo) Limit(limit int) *activityDrawEffectsDo { + return a.withDO(a.DO.Limit(limit)) +} + +func (a activityDrawEffectsDo) Offset(offset int) *activityDrawEffectsDo { + return a.withDO(a.DO.Offset(offset)) +} + +func (a activityDrawEffectsDo) Scopes(funcs ...func(gen.Dao) gen.Dao) *activityDrawEffectsDo { + return a.withDO(a.DO.Scopes(funcs...)) +} + +func (a activityDrawEffectsDo) Unscoped() *activityDrawEffectsDo { + return a.withDO(a.DO.Unscoped()) +} + +func (a activityDrawEffectsDo) Create(values ...*model.ActivityDrawEffects) error { + if len(values) == 0 { + return nil + } + return a.DO.Create(values) +} + +func (a activityDrawEffectsDo) CreateInBatches(values []*model.ActivityDrawEffects, batchSize int) error { + return a.DO.CreateInBatches(values, batchSize) +} + +// Save : !!! underlying implementation is different with GORM +// The method is equivalent to executing the statement: db.Clauses(clause.OnConflict{UpdateAll: true}).Create(values) +func (a activityDrawEffectsDo) Save(values ...*model.ActivityDrawEffects) error { + if len(values) == 0 { + return nil + } + return a.DO.Save(values) +} + +func (a activityDrawEffectsDo) First() (*model.ActivityDrawEffects, error) { + if result, err := a.DO.First(); err != nil { + return nil, err + } else { + return result.(*model.ActivityDrawEffects), nil + } +} + +func (a activityDrawEffectsDo) Take() (*model.ActivityDrawEffects, error) { + if result, err := a.DO.Take(); err != nil { + return nil, err + } else { + return result.(*model.ActivityDrawEffects), nil + } +} + +func (a activityDrawEffectsDo) Last() (*model.ActivityDrawEffects, error) { + if result, err := a.DO.Last(); err != nil { + return nil, err + } else { + return result.(*model.ActivityDrawEffects), nil + } +} + +func (a activityDrawEffectsDo) Find() ([]*model.ActivityDrawEffects, error) { + result, err := a.DO.Find() + return result.([]*model.ActivityDrawEffects), err +} + +func (a activityDrawEffectsDo) FindInBatch(batchSize int, fc func(tx gen.Dao, batch int) error) (results []*model.ActivityDrawEffects, err error) { + buf := make([]*model.ActivityDrawEffects, 0, batchSize) + err = a.DO.FindInBatches(&buf, batchSize, func(tx gen.Dao, batch int) error { + defer func() { results = append(results, buf...) }() + return fc(tx, batch) + }) + return results, err +} + +func (a activityDrawEffectsDo) FindInBatches(result *[]*model.ActivityDrawEffects, batchSize int, fc func(tx gen.Dao, batch int) error) error { + return a.DO.FindInBatches(result, batchSize, fc) +} + +func (a activityDrawEffectsDo) Attrs(attrs ...field.AssignExpr) *activityDrawEffectsDo { + return a.withDO(a.DO.Attrs(attrs...)) +} + +func (a activityDrawEffectsDo) Assign(attrs ...field.AssignExpr) *activityDrawEffectsDo { + return a.withDO(a.DO.Assign(attrs...)) +} + +func (a activityDrawEffectsDo) Joins(fields ...field.RelationField) *activityDrawEffectsDo { + for _, _f := range fields { + a = *a.withDO(a.DO.Joins(_f)) + } + return &a +} + +func (a activityDrawEffectsDo) Preload(fields ...field.RelationField) *activityDrawEffectsDo { + for _, _f := range fields { + a = *a.withDO(a.DO.Preload(_f)) + } + return &a +} + +func (a activityDrawEffectsDo) FirstOrInit() (*model.ActivityDrawEffects, error) { + if result, err := a.DO.FirstOrInit(); err != nil { + return nil, err + } else { + return result.(*model.ActivityDrawEffects), nil + } +} + +func (a activityDrawEffectsDo) FirstOrCreate() (*model.ActivityDrawEffects, error) { + if result, err := a.DO.FirstOrCreate(); err != nil { + return nil, err + } else { + return result.(*model.ActivityDrawEffects), nil + } +} + +func (a activityDrawEffectsDo) FindByPage(offset int, limit int) (result []*model.ActivityDrawEffects, count int64, err error) { + result, err = a.Offset(offset).Limit(limit).Find() + if err != nil { + return + } + + if size := len(result); 0 < limit && 0 < size && size < limit { + count = int64(size + offset) + return + } + + count, err = a.Offset(-1).Limit(-1).Count() + return +} + +func (a activityDrawEffectsDo) ScanByPage(result interface{}, offset int, limit int) (count int64, err error) { + count, err = a.Count() + if err != nil { + return + } + + err = a.Offset(offset).Limit(limit).Scan(result) + return +} + +func (a activityDrawEffectsDo) Scan(result interface{}) (err error) { + return a.DO.Scan(result) +} + +func (a activityDrawEffectsDo) Delete(models ...*model.ActivityDrawEffects) (result gen.ResultInfo, err error) { + return a.DO.Delete(models) +} + +func (a *activityDrawEffectsDo) withDO(do gen.Dao) *activityDrawEffectsDo { + a.DO = *do.(*gen.DO) + return a +} diff --git a/internal/repository/mysql/dao/activity_draw_logs.gen.go b/internal/repository/mysql/dao/activity_draw_logs.gen.go new file mode 100644 index 0000000..b7ac991 --- /dev/null +++ b/internal/repository/mysql/dao/activity_draw_logs.gen.go @@ -0,0 +1,352 @@ +// Code generated by gorm.io/gen. DO NOT EDIT. +// Code generated by gorm.io/gen. DO NOT EDIT. +// Code generated by gorm.io/gen. DO NOT EDIT. + +package dao + +import ( + "context" + + "gorm.io/gorm" + "gorm.io/gorm/clause" + "gorm.io/gorm/schema" + + "gorm.io/gen" + "gorm.io/gen/field" + + "gorm.io/plugin/dbresolver" + + "bindbox-game/internal/repository/mysql/model" +) + +func newActivityDrawLogs(db *gorm.DB, opts ...gen.DOOption) activityDrawLogs { + _activityDrawLogs := activityDrawLogs{} + + _activityDrawLogs.activityDrawLogsDo.UseDB(db, opts...) + _activityDrawLogs.activityDrawLogsDo.UseModel(&model.ActivityDrawLogs{}) + + tableName := _activityDrawLogs.activityDrawLogsDo.TableName() + _activityDrawLogs.ALL = field.NewAsterisk(tableName) + _activityDrawLogs.ID = field.NewInt64(tableName, "id") + _activityDrawLogs.CreatedAt = field.NewTime(tableName, "created_at") + _activityDrawLogs.UserID = field.NewInt64(tableName, "user_id") + _activityDrawLogs.IssueID = field.NewInt64(tableName, "issue_id") + _activityDrawLogs.OrderID = field.NewInt64(tableName, "order_id") + _activityDrawLogs.RewardID = field.NewInt64(tableName, "reward_id") + _activityDrawLogs.IsWinner = field.NewInt32(tableName, "is_winner") + _activityDrawLogs.Level = field.NewInt32(tableName, "level") + _activityDrawLogs.CurrentLevel = field.NewInt32(tableName, "current_level") + + _activityDrawLogs.fillFieldMap() + + return _activityDrawLogs +} + +// activityDrawLogs 抽奖日志 +type activityDrawLogs struct { + activityDrawLogsDo + + ALL field.Asterisk + ID field.Int64 // 主键ID + CreatedAt field.Time // 创建时间 + UserID field.Int64 // 用户ID(mall_user.id) + IssueID field.Int64 // 期ID(activity_issues.id) + OrderID field.Int64 // 抽奖票据订单ID(orders.id) + RewardID field.Int64 // 命中奖励ID(activity_reward_settings.id) + IsWinner field.Int32 // 是否中奖:0否 1是 + Level field.Int32 // 中奖等级(如1=S 2=A 3=B) + CurrentLevel field.Int32 // 当前层(针对爬塔)其它默认为1 + + fieldMap map[string]field.Expr +} + +func (a activityDrawLogs) Table(newTableName string) *activityDrawLogs { + a.activityDrawLogsDo.UseTable(newTableName) + return a.updateTableName(newTableName) +} + +func (a activityDrawLogs) As(alias string) *activityDrawLogs { + a.activityDrawLogsDo.DO = *(a.activityDrawLogsDo.As(alias).(*gen.DO)) + return a.updateTableName(alias) +} + +func (a *activityDrawLogs) updateTableName(table string) *activityDrawLogs { + a.ALL = field.NewAsterisk(table) + a.ID = field.NewInt64(table, "id") + a.CreatedAt = field.NewTime(table, "created_at") + a.UserID = field.NewInt64(table, "user_id") + a.IssueID = field.NewInt64(table, "issue_id") + a.OrderID = field.NewInt64(table, "order_id") + a.RewardID = field.NewInt64(table, "reward_id") + a.IsWinner = field.NewInt32(table, "is_winner") + a.Level = field.NewInt32(table, "level") + a.CurrentLevel = field.NewInt32(table, "current_level") + + a.fillFieldMap() + + return a +} + +func (a *activityDrawLogs) GetFieldByName(fieldName string) (field.OrderExpr, bool) { + _f, ok := a.fieldMap[fieldName] + if !ok || _f == nil { + return nil, false + } + _oe, ok := _f.(field.OrderExpr) + return _oe, ok +} + +func (a *activityDrawLogs) fillFieldMap() { + a.fieldMap = make(map[string]field.Expr, 9) + a.fieldMap["id"] = a.ID + a.fieldMap["created_at"] = a.CreatedAt + a.fieldMap["user_id"] = a.UserID + a.fieldMap["issue_id"] = a.IssueID + a.fieldMap["order_id"] = a.OrderID + a.fieldMap["reward_id"] = a.RewardID + a.fieldMap["is_winner"] = a.IsWinner + a.fieldMap["level"] = a.Level + a.fieldMap["current_level"] = a.CurrentLevel +} + +func (a activityDrawLogs) clone(db *gorm.DB) activityDrawLogs { + a.activityDrawLogsDo.ReplaceConnPool(db.Statement.ConnPool) + return a +} + +func (a activityDrawLogs) replaceDB(db *gorm.DB) activityDrawLogs { + a.activityDrawLogsDo.ReplaceDB(db) + return a +} + +type activityDrawLogsDo struct{ gen.DO } + +func (a activityDrawLogsDo) Debug() *activityDrawLogsDo { + return a.withDO(a.DO.Debug()) +} + +func (a activityDrawLogsDo) WithContext(ctx context.Context) *activityDrawLogsDo { + return a.withDO(a.DO.WithContext(ctx)) +} + +func (a activityDrawLogsDo) ReadDB() *activityDrawLogsDo { + return a.Clauses(dbresolver.Read) +} + +func (a activityDrawLogsDo) WriteDB() *activityDrawLogsDo { + return a.Clauses(dbresolver.Write) +} + +func (a activityDrawLogsDo) Session(config *gorm.Session) *activityDrawLogsDo { + return a.withDO(a.DO.Session(config)) +} + +func (a activityDrawLogsDo) Clauses(conds ...clause.Expression) *activityDrawLogsDo { + return a.withDO(a.DO.Clauses(conds...)) +} + +func (a activityDrawLogsDo) Returning(value interface{}, columns ...string) *activityDrawLogsDo { + return a.withDO(a.DO.Returning(value, columns...)) +} + +func (a activityDrawLogsDo) Not(conds ...gen.Condition) *activityDrawLogsDo { + return a.withDO(a.DO.Not(conds...)) +} + +func (a activityDrawLogsDo) Or(conds ...gen.Condition) *activityDrawLogsDo { + return a.withDO(a.DO.Or(conds...)) +} + +func (a activityDrawLogsDo) Select(conds ...field.Expr) *activityDrawLogsDo { + return a.withDO(a.DO.Select(conds...)) +} + +func (a activityDrawLogsDo) Where(conds ...gen.Condition) *activityDrawLogsDo { + return a.withDO(a.DO.Where(conds...)) +} + +func (a activityDrawLogsDo) Order(conds ...field.Expr) *activityDrawLogsDo { + return a.withDO(a.DO.Order(conds...)) +} + +func (a activityDrawLogsDo) Distinct(cols ...field.Expr) *activityDrawLogsDo { + return a.withDO(a.DO.Distinct(cols...)) +} + +func (a activityDrawLogsDo) Omit(cols ...field.Expr) *activityDrawLogsDo { + return a.withDO(a.DO.Omit(cols...)) +} + +func (a activityDrawLogsDo) Join(table schema.Tabler, on ...field.Expr) *activityDrawLogsDo { + return a.withDO(a.DO.Join(table, on...)) +} + +func (a activityDrawLogsDo) LeftJoin(table schema.Tabler, on ...field.Expr) *activityDrawLogsDo { + return a.withDO(a.DO.LeftJoin(table, on...)) +} + +func (a activityDrawLogsDo) RightJoin(table schema.Tabler, on ...field.Expr) *activityDrawLogsDo { + return a.withDO(a.DO.RightJoin(table, on...)) +} + +func (a activityDrawLogsDo) Group(cols ...field.Expr) *activityDrawLogsDo { + return a.withDO(a.DO.Group(cols...)) +} + +func (a activityDrawLogsDo) Having(conds ...gen.Condition) *activityDrawLogsDo { + return a.withDO(a.DO.Having(conds...)) +} + +func (a activityDrawLogsDo) Limit(limit int) *activityDrawLogsDo { + return a.withDO(a.DO.Limit(limit)) +} + +func (a activityDrawLogsDo) Offset(offset int) *activityDrawLogsDo { + return a.withDO(a.DO.Offset(offset)) +} + +func (a activityDrawLogsDo) Scopes(funcs ...func(gen.Dao) gen.Dao) *activityDrawLogsDo { + return a.withDO(a.DO.Scopes(funcs...)) +} + +func (a activityDrawLogsDo) Unscoped() *activityDrawLogsDo { + return a.withDO(a.DO.Unscoped()) +} + +func (a activityDrawLogsDo) Create(values ...*model.ActivityDrawLogs) error { + if len(values) == 0 { + return nil + } + return a.DO.Create(values) +} + +func (a activityDrawLogsDo) CreateInBatches(values []*model.ActivityDrawLogs, batchSize int) error { + return a.DO.CreateInBatches(values, batchSize) +} + +// Save : !!! underlying implementation is different with GORM +// The method is equivalent to executing the statement: db.Clauses(clause.OnConflict{UpdateAll: true}).Create(values) +func (a activityDrawLogsDo) Save(values ...*model.ActivityDrawLogs) error { + if len(values) == 0 { + return nil + } + return a.DO.Save(values) +} + +func (a activityDrawLogsDo) First() (*model.ActivityDrawLogs, error) { + if result, err := a.DO.First(); err != nil { + return nil, err + } else { + return result.(*model.ActivityDrawLogs), nil + } +} + +func (a activityDrawLogsDo) Take() (*model.ActivityDrawLogs, error) { + if result, err := a.DO.Take(); err != nil { + return nil, err + } else { + return result.(*model.ActivityDrawLogs), nil + } +} + +func (a activityDrawLogsDo) Last() (*model.ActivityDrawLogs, error) { + if result, err := a.DO.Last(); err != nil { + return nil, err + } else { + return result.(*model.ActivityDrawLogs), nil + } +} + +func (a activityDrawLogsDo) Find() ([]*model.ActivityDrawLogs, error) { + result, err := a.DO.Find() + return result.([]*model.ActivityDrawLogs), err +} + +func (a activityDrawLogsDo) FindInBatch(batchSize int, fc func(tx gen.Dao, batch int) error) (results []*model.ActivityDrawLogs, err error) { + buf := make([]*model.ActivityDrawLogs, 0, batchSize) + err = a.DO.FindInBatches(&buf, batchSize, func(tx gen.Dao, batch int) error { + defer func() { results = append(results, buf...) }() + return fc(tx, batch) + }) + return results, err +} + +func (a activityDrawLogsDo) FindInBatches(result *[]*model.ActivityDrawLogs, batchSize int, fc func(tx gen.Dao, batch int) error) error { + return a.DO.FindInBatches(result, batchSize, fc) +} + +func (a activityDrawLogsDo) Attrs(attrs ...field.AssignExpr) *activityDrawLogsDo { + return a.withDO(a.DO.Attrs(attrs...)) +} + +func (a activityDrawLogsDo) Assign(attrs ...field.AssignExpr) *activityDrawLogsDo { + return a.withDO(a.DO.Assign(attrs...)) +} + +func (a activityDrawLogsDo) Joins(fields ...field.RelationField) *activityDrawLogsDo { + for _, _f := range fields { + a = *a.withDO(a.DO.Joins(_f)) + } + return &a +} + +func (a activityDrawLogsDo) Preload(fields ...field.RelationField) *activityDrawLogsDo { + for _, _f := range fields { + a = *a.withDO(a.DO.Preload(_f)) + } + return &a +} + +func (a activityDrawLogsDo) FirstOrInit() (*model.ActivityDrawLogs, error) { + if result, err := a.DO.FirstOrInit(); err != nil { + return nil, err + } else { + return result.(*model.ActivityDrawLogs), nil + } +} + +func (a activityDrawLogsDo) FirstOrCreate() (*model.ActivityDrawLogs, error) { + if result, err := a.DO.FirstOrCreate(); err != nil { + return nil, err + } else { + return result.(*model.ActivityDrawLogs), nil + } +} + +func (a activityDrawLogsDo) FindByPage(offset int, limit int) (result []*model.ActivityDrawLogs, count int64, err error) { + result, err = a.Offset(offset).Limit(limit).Find() + if err != nil { + return + } + + if size := len(result); 0 < limit && 0 < size && size < limit { + count = int64(size + offset) + return + } + + count, err = a.Offset(-1).Limit(-1).Count() + return +} + +func (a activityDrawLogsDo) ScanByPage(result interface{}, offset int, limit int) (count int64, err error) { + count, err = a.Count() + if err != nil { + return + } + + err = a.Offset(offset).Limit(limit).Scan(result) + return +} + +func (a activityDrawLogsDo) Scan(result interface{}) (err error) { + return a.DO.Scan(result) +} + +func (a activityDrawLogsDo) Delete(models ...*model.ActivityDrawLogs) (result gen.ResultInfo, err error) { + return a.DO.Delete(models) +} + +func (a *activityDrawLogsDo) withDO(do gen.Dao) *activityDrawLogsDo { + a.DO = *do.(*gen.DO) + return a +} diff --git a/internal/repository/mysql/dao/activity_issues.gen.go b/internal/repository/mysql/dao/activity_issues.gen.go new file mode 100644 index 0000000..bd135a0 --- /dev/null +++ b/internal/repository/mysql/dao/activity_issues.gen.go @@ -0,0 +1,344 @@ +// Code generated by gorm.io/gen. DO NOT EDIT. +// Code generated by gorm.io/gen. DO NOT EDIT. +// Code generated by gorm.io/gen. DO NOT EDIT. + +package dao + +import ( + "context" + + "gorm.io/gorm" + "gorm.io/gorm/clause" + "gorm.io/gorm/schema" + + "gorm.io/gen" + "gorm.io/gen/field" + + "gorm.io/plugin/dbresolver" + + "bindbox-game/internal/repository/mysql/model" +) + +func newActivityIssues(db *gorm.DB, opts ...gen.DOOption) activityIssues { + _activityIssues := activityIssues{} + + _activityIssues.activityIssuesDo.UseDB(db, opts...) + _activityIssues.activityIssuesDo.UseModel(&model.ActivityIssues{}) + + tableName := _activityIssues.activityIssuesDo.TableName() + _activityIssues.ALL = field.NewAsterisk(tableName) + _activityIssues.ID = field.NewInt64(tableName, "id") + _activityIssues.CreatedAt = field.NewTime(tableName, "created_at") + _activityIssues.UpdatedAt = field.NewTime(tableName, "updated_at") + _activityIssues.ActivityID = field.NewInt64(tableName, "activity_id") + _activityIssues.IssueNumber = field.NewString(tableName, "issue_number") + _activityIssues.Status = field.NewInt32(tableName, "status") + _activityIssues.Sort = field.NewInt32(tableName, "sort") + + _activityIssues.fillFieldMap() + + return _activityIssues +} + +// activityIssues 活动期 +type activityIssues struct { + activityIssuesDo + + ALL field.Asterisk + ID field.Int64 // 主键ID + CreatedAt field.Time // 创建时间 + UpdatedAt field.Time // 更新时间 + ActivityID field.Int64 // 活动ID(activities.id) + IssueNumber field.String // 期号(活动内唯一) + Status field.Int32 // 状态:1进行中 2已结束 3未开始 + Sort field.Int32 // 排序 + + fieldMap map[string]field.Expr +} + +func (a activityIssues) Table(newTableName string) *activityIssues { + a.activityIssuesDo.UseTable(newTableName) + return a.updateTableName(newTableName) +} + +func (a activityIssues) As(alias string) *activityIssues { + a.activityIssuesDo.DO = *(a.activityIssuesDo.As(alias).(*gen.DO)) + return a.updateTableName(alias) +} + +func (a *activityIssues) updateTableName(table string) *activityIssues { + a.ALL = field.NewAsterisk(table) + a.ID = field.NewInt64(table, "id") + a.CreatedAt = field.NewTime(table, "created_at") + a.UpdatedAt = field.NewTime(table, "updated_at") + a.ActivityID = field.NewInt64(table, "activity_id") + a.IssueNumber = field.NewString(table, "issue_number") + a.Status = field.NewInt32(table, "status") + a.Sort = field.NewInt32(table, "sort") + + a.fillFieldMap() + + return a +} + +func (a *activityIssues) GetFieldByName(fieldName string) (field.OrderExpr, bool) { + _f, ok := a.fieldMap[fieldName] + if !ok || _f == nil { + return nil, false + } + _oe, ok := _f.(field.OrderExpr) + return _oe, ok +} + +func (a *activityIssues) fillFieldMap() { + a.fieldMap = make(map[string]field.Expr, 7) + a.fieldMap["id"] = a.ID + a.fieldMap["created_at"] = a.CreatedAt + a.fieldMap["updated_at"] = a.UpdatedAt + a.fieldMap["activity_id"] = a.ActivityID + a.fieldMap["issue_number"] = a.IssueNumber + a.fieldMap["status"] = a.Status + a.fieldMap["sort"] = a.Sort +} + +func (a activityIssues) clone(db *gorm.DB) activityIssues { + a.activityIssuesDo.ReplaceConnPool(db.Statement.ConnPool) + return a +} + +func (a activityIssues) replaceDB(db *gorm.DB) activityIssues { + a.activityIssuesDo.ReplaceDB(db) + return a +} + +type activityIssuesDo struct{ gen.DO } + +func (a activityIssuesDo) Debug() *activityIssuesDo { + return a.withDO(a.DO.Debug()) +} + +func (a activityIssuesDo) WithContext(ctx context.Context) *activityIssuesDo { + return a.withDO(a.DO.WithContext(ctx)) +} + +func (a activityIssuesDo) ReadDB() *activityIssuesDo { + return a.Clauses(dbresolver.Read) +} + +func (a activityIssuesDo) WriteDB() *activityIssuesDo { + return a.Clauses(dbresolver.Write) +} + +func (a activityIssuesDo) Session(config *gorm.Session) *activityIssuesDo { + return a.withDO(a.DO.Session(config)) +} + +func (a activityIssuesDo) Clauses(conds ...clause.Expression) *activityIssuesDo { + return a.withDO(a.DO.Clauses(conds...)) +} + +func (a activityIssuesDo) Returning(value interface{}, columns ...string) *activityIssuesDo { + return a.withDO(a.DO.Returning(value, columns...)) +} + +func (a activityIssuesDo) Not(conds ...gen.Condition) *activityIssuesDo { + return a.withDO(a.DO.Not(conds...)) +} + +func (a activityIssuesDo) Or(conds ...gen.Condition) *activityIssuesDo { + return a.withDO(a.DO.Or(conds...)) +} + +func (a activityIssuesDo) Select(conds ...field.Expr) *activityIssuesDo { + return a.withDO(a.DO.Select(conds...)) +} + +func (a activityIssuesDo) Where(conds ...gen.Condition) *activityIssuesDo { + return a.withDO(a.DO.Where(conds...)) +} + +func (a activityIssuesDo) Order(conds ...field.Expr) *activityIssuesDo { + return a.withDO(a.DO.Order(conds...)) +} + +func (a activityIssuesDo) Distinct(cols ...field.Expr) *activityIssuesDo { + return a.withDO(a.DO.Distinct(cols...)) +} + +func (a activityIssuesDo) Omit(cols ...field.Expr) *activityIssuesDo { + return a.withDO(a.DO.Omit(cols...)) +} + +func (a activityIssuesDo) Join(table schema.Tabler, on ...field.Expr) *activityIssuesDo { + return a.withDO(a.DO.Join(table, on...)) +} + +func (a activityIssuesDo) LeftJoin(table schema.Tabler, on ...field.Expr) *activityIssuesDo { + return a.withDO(a.DO.LeftJoin(table, on...)) +} + +func (a activityIssuesDo) RightJoin(table schema.Tabler, on ...field.Expr) *activityIssuesDo { + return a.withDO(a.DO.RightJoin(table, on...)) +} + +func (a activityIssuesDo) Group(cols ...field.Expr) *activityIssuesDo { + return a.withDO(a.DO.Group(cols...)) +} + +func (a activityIssuesDo) Having(conds ...gen.Condition) *activityIssuesDo { + return a.withDO(a.DO.Having(conds...)) +} + +func (a activityIssuesDo) Limit(limit int) *activityIssuesDo { + return a.withDO(a.DO.Limit(limit)) +} + +func (a activityIssuesDo) Offset(offset int) *activityIssuesDo { + return a.withDO(a.DO.Offset(offset)) +} + +func (a activityIssuesDo) Scopes(funcs ...func(gen.Dao) gen.Dao) *activityIssuesDo { + return a.withDO(a.DO.Scopes(funcs...)) +} + +func (a activityIssuesDo) Unscoped() *activityIssuesDo { + return a.withDO(a.DO.Unscoped()) +} + +func (a activityIssuesDo) Create(values ...*model.ActivityIssues) error { + if len(values) == 0 { + return nil + } + return a.DO.Create(values) +} + +func (a activityIssuesDo) CreateInBatches(values []*model.ActivityIssues, batchSize int) error { + return a.DO.CreateInBatches(values, batchSize) +} + +// Save : !!! underlying implementation is different with GORM +// The method is equivalent to executing the statement: db.Clauses(clause.OnConflict{UpdateAll: true}).Create(values) +func (a activityIssuesDo) Save(values ...*model.ActivityIssues) error { + if len(values) == 0 { + return nil + } + return a.DO.Save(values) +} + +func (a activityIssuesDo) First() (*model.ActivityIssues, error) { + if result, err := a.DO.First(); err != nil { + return nil, err + } else { + return result.(*model.ActivityIssues), nil + } +} + +func (a activityIssuesDo) Take() (*model.ActivityIssues, error) { + if result, err := a.DO.Take(); err != nil { + return nil, err + } else { + return result.(*model.ActivityIssues), nil + } +} + +func (a activityIssuesDo) Last() (*model.ActivityIssues, error) { + if result, err := a.DO.Last(); err != nil { + return nil, err + } else { + return result.(*model.ActivityIssues), nil + } +} + +func (a activityIssuesDo) Find() ([]*model.ActivityIssues, error) { + result, err := a.DO.Find() + return result.([]*model.ActivityIssues), err +} + +func (a activityIssuesDo) FindInBatch(batchSize int, fc func(tx gen.Dao, batch int) error) (results []*model.ActivityIssues, err error) { + buf := make([]*model.ActivityIssues, 0, batchSize) + err = a.DO.FindInBatches(&buf, batchSize, func(tx gen.Dao, batch int) error { + defer func() { results = append(results, buf...) }() + return fc(tx, batch) + }) + return results, err +} + +func (a activityIssuesDo) FindInBatches(result *[]*model.ActivityIssues, batchSize int, fc func(tx gen.Dao, batch int) error) error { + return a.DO.FindInBatches(result, batchSize, fc) +} + +func (a activityIssuesDo) Attrs(attrs ...field.AssignExpr) *activityIssuesDo { + return a.withDO(a.DO.Attrs(attrs...)) +} + +func (a activityIssuesDo) Assign(attrs ...field.AssignExpr) *activityIssuesDo { + return a.withDO(a.DO.Assign(attrs...)) +} + +func (a activityIssuesDo) Joins(fields ...field.RelationField) *activityIssuesDo { + for _, _f := range fields { + a = *a.withDO(a.DO.Joins(_f)) + } + return &a +} + +func (a activityIssuesDo) Preload(fields ...field.RelationField) *activityIssuesDo { + for _, _f := range fields { + a = *a.withDO(a.DO.Preload(_f)) + } + return &a +} + +func (a activityIssuesDo) FirstOrInit() (*model.ActivityIssues, error) { + if result, err := a.DO.FirstOrInit(); err != nil { + return nil, err + } else { + return result.(*model.ActivityIssues), nil + } +} + +func (a activityIssuesDo) FirstOrCreate() (*model.ActivityIssues, error) { + if result, err := a.DO.FirstOrCreate(); err != nil { + return nil, err + } else { + return result.(*model.ActivityIssues), nil + } +} + +func (a activityIssuesDo) FindByPage(offset int, limit int) (result []*model.ActivityIssues, count int64, err error) { + result, err = a.Offset(offset).Limit(limit).Find() + if err != nil { + return + } + + if size := len(result); 0 < limit && 0 < size && size < limit { + count = int64(size + offset) + return + } + + count, err = a.Offset(-1).Limit(-1).Count() + return +} + +func (a activityIssuesDo) ScanByPage(result interface{}, offset int, limit int) (count int64, err error) { + count, err = a.Count() + if err != nil { + return + } + + err = a.Offset(offset).Limit(limit).Scan(result) + return +} + +func (a activityIssuesDo) Scan(result interface{}) (err error) { + return a.DO.Scan(result) +} + +func (a activityIssuesDo) Delete(models ...*model.ActivityIssues) (result gen.ResultInfo, err error) { + return a.DO.Delete(models) +} + +func (a *activityIssuesDo) withDO(do gen.Dao) *activityIssuesDo { + a.DO = *do.(*gen.DO) + return a +} diff --git a/internal/repository/mysql/dao/activity_reward_settings.gen.go b/internal/repository/mysql/dao/activity_reward_settings.gen.go new file mode 100644 index 0000000..2bd156b --- /dev/null +++ b/internal/repository/mysql/dao/activity_reward_settings.gen.go @@ -0,0 +1,364 @@ +// Code generated by gorm.io/gen. DO NOT EDIT. +// Code generated by gorm.io/gen. DO NOT EDIT. +// Code generated by gorm.io/gen. DO NOT EDIT. + +package dao + +import ( + "context" + + "gorm.io/gorm" + "gorm.io/gorm/clause" + "gorm.io/gorm/schema" + + "gorm.io/gen" + "gorm.io/gen/field" + + "gorm.io/plugin/dbresolver" + + "bindbox-game/internal/repository/mysql/model" +) + +func newActivityRewardSettings(db *gorm.DB, opts ...gen.DOOption) activityRewardSettings { + _activityRewardSettings := activityRewardSettings{} + + _activityRewardSettings.activityRewardSettingsDo.UseDB(db, opts...) + _activityRewardSettings.activityRewardSettingsDo.UseModel(&model.ActivityRewardSettings{}) + + tableName := _activityRewardSettings.activityRewardSettingsDo.TableName() + _activityRewardSettings.ALL = field.NewAsterisk(tableName) + _activityRewardSettings.ID = field.NewInt64(tableName, "id") + _activityRewardSettings.CreatedAt = field.NewTime(tableName, "created_at") + _activityRewardSettings.UpdatedAt = field.NewTime(tableName, "updated_at") + _activityRewardSettings.IssueID = field.NewInt64(tableName, "issue_id") + _activityRewardSettings.ProductID = field.NewInt64(tableName, "product_id") + _activityRewardSettings.Name = field.NewString(tableName, "name") + _activityRewardSettings.Weight = field.NewInt32(tableName, "weight") + _activityRewardSettings.Quantity = field.NewInt64(tableName, "quantity") + _activityRewardSettings.OriginalQty = field.NewInt64(tableName, "original_qty") + _activityRewardSettings.Level = field.NewInt32(tableName, "level") + _activityRewardSettings.Sort = field.NewInt32(tableName, "sort") + _activityRewardSettings.IsBoss = field.NewInt32(tableName, "is_boss") + + _activityRewardSettings.fillFieldMap() + + return _activityRewardSettings +} + +// activityRewardSettings 活动期-奖励配置 +type activityRewardSettings struct { + activityRewardSettingsDo + + ALL field.Asterisk + ID field.Int64 // 主键ID + CreatedAt field.Time // 创建时间 + UpdatedAt field.Time // 更新时间 + IssueID field.Int64 // 期ID(activity_issues.id) + ProductID field.Int64 // 奖品对应商品ID(实物奖可填) + Name field.String // 奖项名称/道具名称 + Weight field.Int32 // 抽中权重(越大越易中) + Quantity field.Int64 // 当前可发数量(扣减) + OriginalQty field.Int64 // 初始配置数量 + Level field.Int32 // 奖级(如1=S 2=A 3=B) + Sort field.Int32 // 排序 + IsBoss field.Int32 // Boss 1 是 0 不是 + + fieldMap map[string]field.Expr +} + +func (a activityRewardSettings) Table(newTableName string) *activityRewardSettings { + a.activityRewardSettingsDo.UseTable(newTableName) + return a.updateTableName(newTableName) +} + +func (a activityRewardSettings) As(alias string) *activityRewardSettings { + a.activityRewardSettingsDo.DO = *(a.activityRewardSettingsDo.As(alias).(*gen.DO)) + return a.updateTableName(alias) +} + +func (a *activityRewardSettings) updateTableName(table string) *activityRewardSettings { + a.ALL = field.NewAsterisk(table) + a.ID = field.NewInt64(table, "id") + a.CreatedAt = field.NewTime(table, "created_at") + a.UpdatedAt = field.NewTime(table, "updated_at") + a.IssueID = field.NewInt64(table, "issue_id") + a.ProductID = field.NewInt64(table, "product_id") + a.Name = field.NewString(table, "name") + a.Weight = field.NewInt32(table, "weight") + a.Quantity = field.NewInt64(table, "quantity") + a.OriginalQty = field.NewInt64(table, "original_qty") + a.Level = field.NewInt32(table, "level") + a.Sort = field.NewInt32(table, "sort") + a.IsBoss = field.NewInt32(table, "is_boss") + + a.fillFieldMap() + + return a +} + +func (a *activityRewardSettings) GetFieldByName(fieldName string) (field.OrderExpr, bool) { + _f, ok := a.fieldMap[fieldName] + if !ok || _f == nil { + return nil, false + } + _oe, ok := _f.(field.OrderExpr) + return _oe, ok +} + +func (a *activityRewardSettings) fillFieldMap() { + a.fieldMap = make(map[string]field.Expr, 12) + a.fieldMap["id"] = a.ID + a.fieldMap["created_at"] = a.CreatedAt + a.fieldMap["updated_at"] = a.UpdatedAt + a.fieldMap["issue_id"] = a.IssueID + a.fieldMap["product_id"] = a.ProductID + a.fieldMap["name"] = a.Name + a.fieldMap["weight"] = a.Weight + a.fieldMap["quantity"] = a.Quantity + a.fieldMap["original_qty"] = a.OriginalQty + a.fieldMap["level"] = a.Level + a.fieldMap["sort"] = a.Sort + a.fieldMap["is_boss"] = a.IsBoss +} + +func (a activityRewardSettings) clone(db *gorm.DB) activityRewardSettings { + a.activityRewardSettingsDo.ReplaceConnPool(db.Statement.ConnPool) + return a +} + +func (a activityRewardSettings) replaceDB(db *gorm.DB) activityRewardSettings { + a.activityRewardSettingsDo.ReplaceDB(db) + return a +} + +type activityRewardSettingsDo struct{ gen.DO } + +func (a activityRewardSettingsDo) Debug() *activityRewardSettingsDo { + return a.withDO(a.DO.Debug()) +} + +func (a activityRewardSettingsDo) WithContext(ctx context.Context) *activityRewardSettingsDo { + return a.withDO(a.DO.WithContext(ctx)) +} + +func (a activityRewardSettingsDo) ReadDB() *activityRewardSettingsDo { + return a.Clauses(dbresolver.Read) +} + +func (a activityRewardSettingsDo) WriteDB() *activityRewardSettingsDo { + return a.Clauses(dbresolver.Write) +} + +func (a activityRewardSettingsDo) Session(config *gorm.Session) *activityRewardSettingsDo { + return a.withDO(a.DO.Session(config)) +} + +func (a activityRewardSettingsDo) Clauses(conds ...clause.Expression) *activityRewardSettingsDo { + return a.withDO(a.DO.Clauses(conds...)) +} + +func (a activityRewardSettingsDo) Returning(value interface{}, columns ...string) *activityRewardSettingsDo { + return a.withDO(a.DO.Returning(value, columns...)) +} + +func (a activityRewardSettingsDo) Not(conds ...gen.Condition) *activityRewardSettingsDo { + return a.withDO(a.DO.Not(conds...)) +} + +func (a activityRewardSettingsDo) Or(conds ...gen.Condition) *activityRewardSettingsDo { + return a.withDO(a.DO.Or(conds...)) +} + +func (a activityRewardSettingsDo) Select(conds ...field.Expr) *activityRewardSettingsDo { + return a.withDO(a.DO.Select(conds...)) +} + +func (a activityRewardSettingsDo) Where(conds ...gen.Condition) *activityRewardSettingsDo { + return a.withDO(a.DO.Where(conds...)) +} + +func (a activityRewardSettingsDo) Order(conds ...field.Expr) *activityRewardSettingsDo { + return a.withDO(a.DO.Order(conds...)) +} + +func (a activityRewardSettingsDo) Distinct(cols ...field.Expr) *activityRewardSettingsDo { + return a.withDO(a.DO.Distinct(cols...)) +} + +func (a activityRewardSettingsDo) Omit(cols ...field.Expr) *activityRewardSettingsDo { + return a.withDO(a.DO.Omit(cols...)) +} + +func (a activityRewardSettingsDo) Join(table schema.Tabler, on ...field.Expr) *activityRewardSettingsDo { + return a.withDO(a.DO.Join(table, on...)) +} + +func (a activityRewardSettingsDo) LeftJoin(table schema.Tabler, on ...field.Expr) *activityRewardSettingsDo { + return a.withDO(a.DO.LeftJoin(table, on...)) +} + +func (a activityRewardSettingsDo) RightJoin(table schema.Tabler, on ...field.Expr) *activityRewardSettingsDo { + return a.withDO(a.DO.RightJoin(table, on...)) +} + +func (a activityRewardSettingsDo) Group(cols ...field.Expr) *activityRewardSettingsDo { + return a.withDO(a.DO.Group(cols...)) +} + +func (a activityRewardSettingsDo) Having(conds ...gen.Condition) *activityRewardSettingsDo { + return a.withDO(a.DO.Having(conds...)) +} + +func (a activityRewardSettingsDo) Limit(limit int) *activityRewardSettingsDo { + return a.withDO(a.DO.Limit(limit)) +} + +func (a activityRewardSettingsDo) Offset(offset int) *activityRewardSettingsDo { + return a.withDO(a.DO.Offset(offset)) +} + +func (a activityRewardSettingsDo) Scopes(funcs ...func(gen.Dao) gen.Dao) *activityRewardSettingsDo { + return a.withDO(a.DO.Scopes(funcs...)) +} + +func (a activityRewardSettingsDo) Unscoped() *activityRewardSettingsDo { + return a.withDO(a.DO.Unscoped()) +} + +func (a activityRewardSettingsDo) Create(values ...*model.ActivityRewardSettings) error { + if len(values) == 0 { + return nil + } + return a.DO.Create(values) +} + +func (a activityRewardSettingsDo) CreateInBatches(values []*model.ActivityRewardSettings, batchSize int) error { + return a.DO.CreateInBatches(values, batchSize) +} + +// Save : !!! underlying implementation is different with GORM +// The method is equivalent to executing the statement: db.Clauses(clause.OnConflict{UpdateAll: true}).Create(values) +func (a activityRewardSettingsDo) Save(values ...*model.ActivityRewardSettings) error { + if len(values) == 0 { + return nil + } + return a.DO.Save(values) +} + +func (a activityRewardSettingsDo) First() (*model.ActivityRewardSettings, error) { + if result, err := a.DO.First(); err != nil { + return nil, err + } else { + return result.(*model.ActivityRewardSettings), nil + } +} + +func (a activityRewardSettingsDo) Take() (*model.ActivityRewardSettings, error) { + if result, err := a.DO.Take(); err != nil { + return nil, err + } else { + return result.(*model.ActivityRewardSettings), nil + } +} + +func (a activityRewardSettingsDo) Last() (*model.ActivityRewardSettings, error) { + if result, err := a.DO.Last(); err != nil { + return nil, err + } else { + return result.(*model.ActivityRewardSettings), nil + } +} + +func (a activityRewardSettingsDo) Find() ([]*model.ActivityRewardSettings, error) { + result, err := a.DO.Find() + return result.([]*model.ActivityRewardSettings), err +} + +func (a activityRewardSettingsDo) FindInBatch(batchSize int, fc func(tx gen.Dao, batch int) error) (results []*model.ActivityRewardSettings, err error) { + buf := make([]*model.ActivityRewardSettings, 0, batchSize) + err = a.DO.FindInBatches(&buf, batchSize, func(tx gen.Dao, batch int) error { + defer func() { results = append(results, buf...) }() + return fc(tx, batch) + }) + return results, err +} + +func (a activityRewardSettingsDo) FindInBatches(result *[]*model.ActivityRewardSettings, batchSize int, fc func(tx gen.Dao, batch int) error) error { + return a.DO.FindInBatches(result, batchSize, fc) +} + +func (a activityRewardSettingsDo) Attrs(attrs ...field.AssignExpr) *activityRewardSettingsDo { + return a.withDO(a.DO.Attrs(attrs...)) +} + +func (a activityRewardSettingsDo) Assign(attrs ...field.AssignExpr) *activityRewardSettingsDo { + return a.withDO(a.DO.Assign(attrs...)) +} + +func (a activityRewardSettingsDo) Joins(fields ...field.RelationField) *activityRewardSettingsDo { + for _, _f := range fields { + a = *a.withDO(a.DO.Joins(_f)) + } + return &a +} + +func (a activityRewardSettingsDo) Preload(fields ...field.RelationField) *activityRewardSettingsDo { + for _, _f := range fields { + a = *a.withDO(a.DO.Preload(_f)) + } + return &a +} + +func (a activityRewardSettingsDo) FirstOrInit() (*model.ActivityRewardSettings, error) { + if result, err := a.DO.FirstOrInit(); err != nil { + return nil, err + } else { + return result.(*model.ActivityRewardSettings), nil + } +} + +func (a activityRewardSettingsDo) FirstOrCreate() (*model.ActivityRewardSettings, error) { + if result, err := a.DO.FirstOrCreate(); err != nil { + return nil, err + } else { + return result.(*model.ActivityRewardSettings), nil + } +} + +func (a activityRewardSettingsDo) FindByPage(offset int, limit int) (result []*model.ActivityRewardSettings, count int64, err error) { + result, err = a.Offset(offset).Limit(limit).Find() + if err != nil { + return + } + + if size := len(result); 0 < limit && 0 < size && size < limit { + count = int64(size + offset) + return + } + + count, err = a.Offset(-1).Limit(-1).Count() + return +} + +func (a activityRewardSettingsDo) ScanByPage(result interface{}, offset int, limit int) (count int64, err error) { + count, err = a.Count() + if err != nil { + return + } + + err = a.Offset(offset).Limit(limit).Scan(result) + return +} + +func (a activityRewardSettingsDo) Scan(result interface{}) (err error) { + return a.DO.Scan(result) +} + +func (a activityRewardSettingsDo) Delete(models ...*model.ActivityRewardSettings) (result gen.ResultInfo, err error) { + return a.DO.Delete(models) +} + +func (a *activityRewardSettingsDo) withDO(do gen.Dao) *activityRewardSettingsDo { + a.DO = *do.(*gen.DO) + return a +} diff --git a/internal/repository/mysql/dao/admin.gen.go b/internal/repository/mysql/dao/admin.gen.go index 0455cda..d777c27 100644 --- a/internal/repository/mysql/dao/admin.gen.go +++ b/internal/repository/mysql/dao/admin.gen.go @@ -16,7 +16,7 @@ import ( "gorm.io/plugin/dbresolver" - "mini-chat/internal/repository/mysql/model" + "bindbox-game/internal/repository/mysql/model" ) func newAdmin(db *gorm.DB, opts ...gen.DOOption) admin { diff --git a/internal/repository/mysql/dao/app_keyword.gen.go b/internal/repository/mysql/dao/app_keyword.gen.go deleted file mode 100644 index c94fbb0..0000000 --- a/internal/repository/mysql/dao/app_keyword.gen.go +++ /dev/null @@ -1,344 +0,0 @@ -// Code generated by gorm.io/gen. DO NOT EDIT. -// Code generated by gorm.io/gen. DO NOT EDIT. -// Code generated by gorm.io/gen. DO NOT EDIT. - -package dao - -import ( - "context" - - "gorm.io/gorm" - "gorm.io/gorm/clause" - "gorm.io/gorm/schema" - - "gorm.io/gen" - "gorm.io/gen/field" - - "gorm.io/plugin/dbresolver" - - "mini-chat/internal/repository/mysql/model" -) - -func newAppKeyword(db *gorm.DB, opts ...gen.DOOption) appKeyword { - _appKeyword := appKeyword{} - - _appKeyword.appKeywordDo.UseDB(db, opts...) - _appKeyword.appKeywordDo.UseModel(&model.AppKeyword{}) - - tableName := _appKeyword.appKeywordDo.TableName() - _appKeyword.ALL = field.NewAsterisk(tableName) - _appKeyword.ID = field.NewInt32(tableName, "id") - _appKeyword.AppID = field.NewString(tableName, "app_id") - _appKeyword.Keyword = field.NewString(tableName, "keyword") - _appKeyword.CreatedUser = field.NewString(tableName, "created_user") - _appKeyword.CreatedAt = field.NewTime(tableName, "created_at") - _appKeyword.UpdatedUser = field.NewString(tableName, "updated_user") - _appKeyword.UpdatedAt = field.NewTime(tableName, "updated_at") - - _appKeyword.fillFieldMap() - - return _appKeyword -} - -// appKeyword 关键字表 -type appKeyword struct { - appKeywordDo - - ALL field.Asterisk - ID field.Int32 // 主键ID - AppID field.String // 小程序ID - Keyword field.String // 关键字 - CreatedUser field.String // 创建人 - CreatedAt field.Time // 创建时间 - UpdatedUser field.String // 更新人 - UpdatedAt field.Time // 更新时间 - - fieldMap map[string]field.Expr -} - -func (a appKeyword) Table(newTableName string) *appKeyword { - a.appKeywordDo.UseTable(newTableName) - return a.updateTableName(newTableName) -} - -func (a appKeyword) As(alias string) *appKeyword { - a.appKeywordDo.DO = *(a.appKeywordDo.As(alias).(*gen.DO)) - return a.updateTableName(alias) -} - -func (a *appKeyword) updateTableName(table string) *appKeyword { - a.ALL = field.NewAsterisk(table) - a.ID = field.NewInt32(table, "id") - a.AppID = field.NewString(table, "app_id") - a.Keyword = field.NewString(table, "keyword") - a.CreatedUser = field.NewString(table, "created_user") - a.CreatedAt = field.NewTime(table, "created_at") - a.UpdatedUser = field.NewString(table, "updated_user") - a.UpdatedAt = field.NewTime(table, "updated_at") - - a.fillFieldMap() - - return a -} - -func (a *appKeyword) GetFieldByName(fieldName string) (field.OrderExpr, bool) { - _f, ok := a.fieldMap[fieldName] - if !ok || _f == nil { - return nil, false - } - _oe, ok := _f.(field.OrderExpr) - return _oe, ok -} - -func (a *appKeyword) fillFieldMap() { - a.fieldMap = make(map[string]field.Expr, 7) - a.fieldMap["id"] = a.ID - a.fieldMap["app_id"] = a.AppID - a.fieldMap["keyword"] = a.Keyword - a.fieldMap["created_user"] = a.CreatedUser - a.fieldMap["created_at"] = a.CreatedAt - a.fieldMap["updated_user"] = a.UpdatedUser - a.fieldMap["updated_at"] = a.UpdatedAt -} - -func (a appKeyword) clone(db *gorm.DB) appKeyword { - a.appKeywordDo.ReplaceConnPool(db.Statement.ConnPool) - return a -} - -func (a appKeyword) replaceDB(db *gorm.DB) appKeyword { - a.appKeywordDo.ReplaceDB(db) - return a -} - -type appKeywordDo struct{ gen.DO } - -func (a appKeywordDo) Debug() *appKeywordDo { - return a.withDO(a.DO.Debug()) -} - -func (a appKeywordDo) WithContext(ctx context.Context) *appKeywordDo { - return a.withDO(a.DO.WithContext(ctx)) -} - -func (a appKeywordDo) ReadDB() *appKeywordDo { - return a.Clauses(dbresolver.Read) -} - -func (a appKeywordDo) WriteDB() *appKeywordDo { - return a.Clauses(dbresolver.Write) -} - -func (a appKeywordDo) Session(config *gorm.Session) *appKeywordDo { - return a.withDO(a.DO.Session(config)) -} - -func (a appKeywordDo) Clauses(conds ...clause.Expression) *appKeywordDo { - return a.withDO(a.DO.Clauses(conds...)) -} - -func (a appKeywordDo) Returning(value interface{}, columns ...string) *appKeywordDo { - return a.withDO(a.DO.Returning(value, columns...)) -} - -func (a appKeywordDo) Not(conds ...gen.Condition) *appKeywordDo { - return a.withDO(a.DO.Not(conds...)) -} - -func (a appKeywordDo) Or(conds ...gen.Condition) *appKeywordDo { - return a.withDO(a.DO.Or(conds...)) -} - -func (a appKeywordDo) Select(conds ...field.Expr) *appKeywordDo { - return a.withDO(a.DO.Select(conds...)) -} - -func (a appKeywordDo) Where(conds ...gen.Condition) *appKeywordDo { - return a.withDO(a.DO.Where(conds...)) -} - -func (a appKeywordDo) Order(conds ...field.Expr) *appKeywordDo { - return a.withDO(a.DO.Order(conds...)) -} - -func (a appKeywordDo) Distinct(cols ...field.Expr) *appKeywordDo { - return a.withDO(a.DO.Distinct(cols...)) -} - -func (a appKeywordDo) Omit(cols ...field.Expr) *appKeywordDo { - return a.withDO(a.DO.Omit(cols...)) -} - -func (a appKeywordDo) Join(table schema.Tabler, on ...field.Expr) *appKeywordDo { - return a.withDO(a.DO.Join(table, on...)) -} - -func (a appKeywordDo) LeftJoin(table schema.Tabler, on ...field.Expr) *appKeywordDo { - return a.withDO(a.DO.LeftJoin(table, on...)) -} - -func (a appKeywordDo) RightJoin(table schema.Tabler, on ...field.Expr) *appKeywordDo { - return a.withDO(a.DO.RightJoin(table, on...)) -} - -func (a appKeywordDo) Group(cols ...field.Expr) *appKeywordDo { - return a.withDO(a.DO.Group(cols...)) -} - -func (a appKeywordDo) Having(conds ...gen.Condition) *appKeywordDo { - return a.withDO(a.DO.Having(conds...)) -} - -func (a appKeywordDo) Limit(limit int) *appKeywordDo { - return a.withDO(a.DO.Limit(limit)) -} - -func (a appKeywordDo) Offset(offset int) *appKeywordDo { - return a.withDO(a.DO.Offset(offset)) -} - -func (a appKeywordDo) Scopes(funcs ...func(gen.Dao) gen.Dao) *appKeywordDo { - return a.withDO(a.DO.Scopes(funcs...)) -} - -func (a appKeywordDo) Unscoped() *appKeywordDo { - return a.withDO(a.DO.Unscoped()) -} - -func (a appKeywordDo) Create(values ...*model.AppKeyword) error { - if len(values) == 0 { - return nil - } - return a.DO.Create(values) -} - -func (a appKeywordDo) CreateInBatches(values []*model.AppKeyword, batchSize int) error { - return a.DO.CreateInBatches(values, batchSize) -} - -// Save : !!! underlying implementation is different with GORM -// The method is equivalent to executing the statement: db.Clauses(clause.OnConflict{UpdateAll: true}).Create(values) -func (a appKeywordDo) Save(values ...*model.AppKeyword) error { - if len(values) == 0 { - return nil - } - return a.DO.Save(values) -} - -func (a appKeywordDo) First() (*model.AppKeyword, error) { - if result, err := a.DO.First(); err != nil { - return nil, err - } else { - return result.(*model.AppKeyword), nil - } -} - -func (a appKeywordDo) Take() (*model.AppKeyword, error) { - if result, err := a.DO.Take(); err != nil { - return nil, err - } else { - return result.(*model.AppKeyword), nil - } -} - -func (a appKeywordDo) Last() (*model.AppKeyword, error) { - if result, err := a.DO.Last(); err != nil { - return nil, err - } else { - return result.(*model.AppKeyword), nil - } -} - -func (a appKeywordDo) Find() ([]*model.AppKeyword, error) { - result, err := a.DO.Find() - return result.([]*model.AppKeyword), err -} - -func (a appKeywordDo) FindInBatch(batchSize int, fc func(tx gen.Dao, batch int) error) (results []*model.AppKeyword, err error) { - buf := make([]*model.AppKeyword, 0, batchSize) - err = a.DO.FindInBatches(&buf, batchSize, func(tx gen.Dao, batch int) error { - defer func() { results = append(results, buf...) }() - return fc(tx, batch) - }) - return results, err -} - -func (a appKeywordDo) FindInBatches(result *[]*model.AppKeyword, batchSize int, fc func(tx gen.Dao, batch int) error) error { - return a.DO.FindInBatches(result, batchSize, fc) -} - -func (a appKeywordDo) Attrs(attrs ...field.AssignExpr) *appKeywordDo { - return a.withDO(a.DO.Attrs(attrs...)) -} - -func (a appKeywordDo) Assign(attrs ...field.AssignExpr) *appKeywordDo { - return a.withDO(a.DO.Assign(attrs...)) -} - -func (a appKeywordDo) Joins(fields ...field.RelationField) *appKeywordDo { - for _, _f := range fields { - a = *a.withDO(a.DO.Joins(_f)) - } - return &a -} - -func (a appKeywordDo) Preload(fields ...field.RelationField) *appKeywordDo { - for _, _f := range fields { - a = *a.withDO(a.DO.Preload(_f)) - } - return &a -} - -func (a appKeywordDo) FirstOrInit() (*model.AppKeyword, error) { - if result, err := a.DO.FirstOrInit(); err != nil { - return nil, err - } else { - return result.(*model.AppKeyword), nil - } -} - -func (a appKeywordDo) FirstOrCreate() (*model.AppKeyword, error) { - if result, err := a.DO.FirstOrCreate(); err != nil { - return nil, err - } else { - return result.(*model.AppKeyword), nil - } -} - -func (a appKeywordDo) FindByPage(offset int, limit int) (result []*model.AppKeyword, count int64, err error) { - result, err = a.Offset(offset).Limit(limit).Find() - if err != nil { - return - } - - if size := len(result); 0 < limit && 0 < size && size < limit { - count = int64(size + offset) - return - } - - count, err = a.Offset(-1).Limit(-1).Count() - return -} - -func (a appKeywordDo) ScanByPage(result interface{}, offset int, limit int) (count int64, err error) { - count, err = a.Count() - if err != nil { - return - } - - err = a.Offset(offset).Limit(limit).Scan(result) - return -} - -func (a appKeywordDo) Scan(result interface{}) (err error) { - return a.DO.Scan(result) -} - -func (a appKeywordDo) Delete(models ...*model.AppKeyword) (result gen.ResultInfo, err error) { - return a.DO.Delete(models) -} - -func (a *appKeywordDo) withDO(do gen.Dao) *appKeywordDo { - a.DO = *do.(*gen.DO) - return a -} diff --git a/internal/repository/mysql/dao/app_keyword_reply.gen.go b/internal/repository/mysql/dao/app_keyword_reply.gen.go deleted file mode 100644 index 7095803..0000000 --- a/internal/repository/mysql/dao/app_keyword_reply.gen.go +++ /dev/null @@ -1,356 +0,0 @@ -// Code generated by gorm.io/gen. DO NOT EDIT. -// Code generated by gorm.io/gen. DO NOT EDIT. -// Code generated by gorm.io/gen. DO NOT EDIT. - -package dao - -import ( - "context" - - "gorm.io/gorm" - "gorm.io/gorm/clause" - "gorm.io/gorm/schema" - - "gorm.io/gen" - "gorm.io/gen/field" - - "gorm.io/plugin/dbresolver" - - "mini-chat/internal/repository/mysql/model" -) - -func newAppKeywordReply(db *gorm.DB, opts ...gen.DOOption) appKeywordReply { - _appKeywordReply := appKeywordReply{} - - _appKeywordReply.appKeywordReplyDo.UseDB(db, opts...) - _appKeywordReply.appKeywordReplyDo.UseModel(&model.AppKeywordReply{}) - - tableName := _appKeywordReply.appKeywordReplyDo.TableName() - _appKeywordReply.ALL = field.NewAsterisk(tableName) - _appKeywordReply.ID = field.NewInt32(tableName, "id") - _appKeywordReply.AppID = field.NewString(tableName, "app_id") - _appKeywordReply.KeywordID = field.NewInt32(tableName, "keyword_id") - _appKeywordReply.IntervalSeconds = field.NewInt32(tableName, "interval_seconds") - _appKeywordReply.Type = field.NewInt32(tableName, "type") - _appKeywordReply.Content = field.NewString(tableName, "content") - _appKeywordReply.CreatedUser = field.NewString(tableName, "created_user") - _appKeywordReply.CreatedAt = field.NewTime(tableName, "created_at") - _appKeywordReply.UpdatedUser = field.NewString(tableName, "updated_user") - _appKeywordReply.UpdatedAt = field.NewTime(tableName, "updated_at") - - _appKeywordReply.fillFieldMap() - - return _appKeywordReply -} - -// appKeywordReply 关键字回复表 -type appKeywordReply struct { - appKeywordReplyDo - - ALL field.Asterisk - ID field.Int32 // 主键ID - AppID field.String // 小程序ID - KeywordID field.Int32 // 关联 app_keyword 表的ID - IntervalSeconds field.Int32 // 时间间隔,单位为秒 - Type field.Int32 // 类型(1:文本 2:图片 3:语音条 4:视频 5=小程序 6=地理位置 7=链接 8=GIF图 9=名片 10=文件 11=转人工) - Content field.String // 内容 - CreatedUser field.String // 创建人 - CreatedAt field.Time // 创建时间 - UpdatedUser field.String // 更新人 - UpdatedAt field.Time // 更新时间 - - fieldMap map[string]field.Expr -} - -func (a appKeywordReply) Table(newTableName string) *appKeywordReply { - a.appKeywordReplyDo.UseTable(newTableName) - return a.updateTableName(newTableName) -} - -func (a appKeywordReply) As(alias string) *appKeywordReply { - a.appKeywordReplyDo.DO = *(a.appKeywordReplyDo.As(alias).(*gen.DO)) - return a.updateTableName(alias) -} - -func (a *appKeywordReply) updateTableName(table string) *appKeywordReply { - a.ALL = field.NewAsterisk(table) - a.ID = field.NewInt32(table, "id") - a.AppID = field.NewString(table, "app_id") - a.KeywordID = field.NewInt32(table, "keyword_id") - a.IntervalSeconds = field.NewInt32(table, "interval_seconds") - a.Type = field.NewInt32(table, "type") - a.Content = field.NewString(table, "content") - a.CreatedUser = field.NewString(table, "created_user") - a.CreatedAt = field.NewTime(table, "created_at") - a.UpdatedUser = field.NewString(table, "updated_user") - a.UpdatedAt = field.NewTime(table, "updated_at") - - a.fillFieldMap() - - return a -} - -func (a *appKeywordReply) GetFieldByName(fieldName string) (field.OrderExpr, bool) { - _f, ok := a.fieldMap[fieldName] - if !ok || _f == nil { - return nil, false - } - _oe, ok := _f.(field.OrderExpr) - return _oe, ok -} - -func (a *appKeywordReply) fillFieldMap() { - a.fieldMap = make(map[string]field.Expr, 10) - a.fieldMap["id"] = a.ID - a.fieldMap["app_id"] = a.AppID - a.fieldMap["keyword_id"] = a.KeywordID - a.fieldMap["interval_seconds"] = a.IntervalSeconds - a.fieldMap["type"] = a.Type - a.fieldMap["content"] = a.Content - a.fieldMap["created_user"] = a.CreatedUser - a.fieldMap["created_at"] = a.CreatedAt - a.fieldMap["updated_user"] = a.UpdatedUser - a.fieldMap["updated_at"] = a.UpdatedAt -} - -func (a appKeywordReply) clone(db *gorm.DB) appKeywordReply { - a.appKeywordReplyDo.ReplaceConnPool(db.Statement.ConnPool) - return a -} - -func (a appKeywordReply) replaceDB(db *gorm.DB) appKeywordReply { - a.appKeywordReplyDo.ReplaceDB(db) - return a -} - -type appKeywordReplyDo struct{ gen.DO } - -func (a appKeywordReplyDo) Debug() *appKeywordReplyDo { - return a.withDO(a.DO.Debug()) -} - -func (a appKeywordReplyDo) WithContext(ctx context.Context) *appKeywordReplyDo { - return a.withDO(a.DO.WithContext(ctx)) -} - -func (a appKeywordReplyDo) ReadDB() *appKeywordReplyDo { - return a.Clauses(dbresolver.Read) -} - -func (a appKeywordReplyDo) WriteDB() *appKeywordReplyDo { - return a.Clauses(dbresolver.Write) -} - -func (a appKeywordReplyDo) Session(config *gorm.Session) *appKeywordReplyDo { - return a.withDO(a.DO.Session(config)) -} - -func (a appKeywordReplyDo) Clauses(conds ...clause.Expression) *appKeywordReplyDo { - return a.withDO(a.DO.Clauses(conds...)) -} - -func (a appKeywordReplyDo) Returning(value interface{}, columns ...string) *appKeywordReplyDo { - return a.withDO(a.DO.Returning(value, columns...)) -} - -func (a appKeywordReplyDo) Not(conds ...gen.Condition) *appKeywordReplyDo { - return a.withDO(a.DO.Not(conds...)) -} - -func (a appKeywordReplyDo) Or(conds ...gen.Condition) *appKeywordReplyDo { - return a.withDO(a.DO.Or(conds...)) -} - -func (a appKeywordReplyDo) Select(conds ...field.Expr) *appKeywordReplyDo { - return a.withDO(a.DO.Select(conds...)) -} - -func (a appKeywordReplyDo) Where(conds ...gen.Condition) *appKeywordReplyDo { - return a.withDO(a.DO.Where(conds...)) -} - -func (a appKeywordReplyDo) Order(conds ...field.Expr) *appKeywordReplyDo { - return a.withDO(a.DO.Order(conds...)) -} - -func (a appKeywordReplyDo) Distinct(cols ...field.Expr) *appKeywordReplyDo { - return a.withDO(a.DO.Distinct(cols...)) -} - -func (a appKeywordReplyDo) Omit(cols ...field.Expr) *appKeywordReplyDo { - return a.withDO(a.DO.Omit(cols...)) -} - -func (a appKeywordReplyDo) Join(table schema.Tabler, on ...field.Expr) *appKeywordReplyDo { - return a.withDO(a.DO.Join(table, on...)) -} - -func (a appKeywordReplyDo) LeftJoin(table schema.Tabler, on ...field.Expr) *appKeywordReplyDo { - return a.withDO(a.DO.LeftJoin(table, on...)) -} - -func (a appKeywordReplyDo) RightJoin(table schema.Tabler, on ...field.Expr) *appKeywordReplyDo { - return a.withDO(a.DO.RightJoin(table, on...)) -} - -func (a appKeywordReplyDo) Group(cols ...field.Expr) *appKeywordReplyDo { - return a.withDO(a.DO.Group(cols...)) -} - -func (a appKeywordReplyDo) Having(conds ...gen.Condition) *appKeywordReplyDo { - return a.withDO(a.DO.Having(conds...)) -} - -func (a appKeywordReplyDo) Limit(limit int) *appKeywordReplyDo { - return a.withDO(a.DO.Limit(limit)) -} - -func (a appKeywordReplyDo) Offset(offset int) *appKeywordReplyDo { - return a.withDO(a.DO.Offset(offset)) -} - -func (a appKeywordReplyDo) Scopes(funcs ...func(gen.Dao) gen.Dao) *appKeywordReplyDo { - return a.withDO(a.DO.Scopes(funcs...)) -} - -func (a appKeywordReplyDo) Unscoped() *appKeywordReplyDo { - return a.withDO(a.DO.Unscoped()) -} - -func (a appKeywordReplyDo) Create(values ...*model.AppKeywordReply) error { - if len(values) == 0 { - return nil - } - return a.DO.Create(values) -} - -func (a appKeywordReplyDo) CreateInBatches(values []*model.AppKeywordReply, batchSize int) error { - return a.DO.CreateInBatches(values, batchSize) -} - -// Save : !!! underlying implementation is different with GORM -// The method is equivalent to executing the statement: db.Clauses(clause.OnConflict{UpdateAll: true}).Create(values) -func (a appKeywordReplyDo) Save(values ...*model.AppKeywordReply) error { - if len(values) == 0 { - return nil - } - return a.DO.Save(values) -} - -func (a appKeywordReplyDo) First() (*model.AppKeywordReply, error) { - if result, err := a.DO.First(); err != nil { - return nil, err - } else { - return result.(*model.AppKeywordReply), nil - } -} - -func (a appKeywordReplyDo) Take() (*model.AppKeywordReply, error) { - if result, err := a.DO.Take(); err != nil { - return nil, err - } else { - return result.(*model.AppKeywordReply), nil - } -} - -func (a appKeywordReplyDo) Last() (*model.AppKeywordReply, error) { - if result, err := a.DO.Last(); err != nil { - return nil, err - } else { - return result.(*model.AppKeywordReply), nil - } -} - -func (a appKeywordReplyDo) Find() ([]*model.AppKeywordReply, error) { - result, err := a.DO.Find() - return result.([]*model.AppKeywordReply), err -} - -func (a appKeywordReplyDo) FindInBatch(batchSize int, fc func(tx gen.Dao, batch int) error) (results []*model.AppKeywordReply, err error) { - buf := make([]*model.AppKeywordReply, 0, batchSize) - err = a.DO.FindInBatches(&buf, batchSize, func(tx gen.Dao, batch int) error { - defer func() { results = append(results, buf...) }() - return fc(tx, batch) - }) - return results, err -} - -func (a appKeywordReplyDo) FindInBatches(result *[]*model.AppKeywordReply, batchSize int, fc func(tx gen.Dao, batch int) error) error { - return a.DO.FindInBatches(result, batchSize, fc) -} - -func (a appKeywordReplyDo) Attrs(attrs ...field.AssignExpr) *appKeywordReplyDo { - return a.withDO(a.DO.Attrs(attrs...)) -} - -func (a appKeywordReplyDo) Assign(attrs ...field.AssignExpr) *appKeywordReplyDo { - return a.withDO(a.DO.Assign(attrs...)) -} - -func (a appKeywordReplyDo) Joins(fields ...field.RelationField) *appKeywordReplyDo { - for _, _f := range fields { - a = *a.withDO(a.DO.Joins(_f)) - } - return &a -} - -func (a appKeywordReplyDo) Preload(fields ...field.RelationField) *appKeywordReplyDo { - for _, _f := range fields { - a = *a.withDO(a.DO.Preload(_f)) - } - return &a -} - -func (a appKeywordReplyDo) FirstOrInit() (*model.AppKeywordReply, error) { - if result, err := a.DO.FirstOrInit(); err != nil { - return nil, err - } else { - return result.(*model.AppKeywordReply), nil - } -} - -func (a appKeywordReplyDo) FirstOrCreate() (*model.AppKeywordReply, error) { - if result, err := a.DO.FirstOrCreate(); err != nil { - return nil, err - } else { - return result.(*model.AppKeywordReply), nil - } -} - -func (a appKeywordReplyDo) FindByPage(offset int, limit int) (result []*model.AppKeywordReply, count int64, err error) { - result, err = a.Offset(offset).Limit(limit).Find() - if err != nil { - return - } - - if size := len(result); 0 < limit && 0 < size && size < limit { - count = int64(size + offset) - return - } - - count, err = a.Offset(-1).Limit(-1).Count() - return -} - -func (a appKeywordReplyDo) ScanByPage(result interface{}, offset int, limit int) (count int64, err error) { - count, err = a.Count() - if err != nil { - return - } - - err = a.Offset(offset).Limit(limit).Scan(result) - return -} - -func (a appKeywordReplyDo) Scan(result interface{}) (err error) { - return a.DO.Scan(result) -} - -func (a appKeywordReplyDo) Delete(models ...*model.AppKeywordReply) (result gen.ResultInfo, err error) { - return a.DO.Delete(models) -} - -func (a *appKeywordReplyDo) withDO(do gen.Dao) *appKeywordReplyDo { - a.DO = *do.(*gen.DO) - return a -} diff --git a/internal/repository/mysql/dao/app_message_log.gen.go b/internal/repository/mysql/dao/app_message_log.gen.go deleted file mode 100644 index 73db85b..0000000 --- a/internal/repository/mysql/dao/app_message_log.gen.go +++ /dev/null @@ -1,356 +0,0 @@ -// Code generated by gorm.io/gen. DO NOT EDIT. -// Code generated by gorm.io/gen. DO NOT EDIT. -// Code generated by gorm.io/gen. DO NOT EDIT. - -package dao - -import ( - "context" - - "gorm.io/gorm" - "gorm.io/gorm/clause" - "gorm.io/gorm/schema" - - "gorm.io/gen" - "gorm.io/gen/field" - - "gorm.io/plugin/dbresolver" - - "mini-chat/internal/repository/mysql/model" -) - -func newAppMessageLog(db *gorm.DB, opts ...gen.DOOption) appMessageLog { - _appMessageLog := appMessageLog{} - - _appMessageLog.appMessageLogDo.UseDB(db, opts...) - _appMessageLog.appMessageLogDo.UseModel(&model.AppMessageLog{}) - - tableName := _appMessageLog.appMessageLogDo.TableName() - _appMessageLog.ALL = field.NewAsterisk(tableName) - _appMessageLog.ID = field.NewInt32(tableName, "id") - _appMessageLog.AppID = field.NewString(tableName, "app_id") - _appMessageLog.SenderID = field.NewString(tableName, "sender_id") - _appMessageLog.SenderName = field.NewString(tableName, "sender_name") - _appMessageLog.SendTime = field.NewTime(tableName, "send_time") - _appMessageLog.ReceiverID = field.NewString(tableName, "receiver_id") - _appMessageLog.MsgType = field.NewInt32(tableName, "msg_type") - _appMessageLog.Content = field.NewString(tableName, "content") - _appMessageLog.CreatedAt = field.NewTime(tableName, "created_at") - _appMessageLog.IsRead = field.NewInt32(tableName, "is_read") - - _appMessageLog.fillFieldMap() - - return _appMessageLog -} - -// appMessageLog 消息日志表 -type appMessageLog struct { - appMessageLogDo - - ALL field.Asterisk - ID field.Int32 // 主键ID - AppID field.String // 小程序ID - SenderID field.String // 发送人ID - SenderName field.String // 发送人昵称 - SendTime field.Time // 发送时间 - ReceiverID field.String // 接收人ID - MsgType field.Int32 // 消息类型(1:文本 2:图片) - Content field.String // 消息内容 - CreatedAt field.Time // 创建时间 - IsRead field.Int32 // 是否已读(0:未读 1:已读) - - fieldMap map[string]field.Expr -} - -func (a appMessageLog) Table(newTableName string) *appMessageLog { - a.appMessageLogDo.UseTable(newTableName) - return a.updateTableName(newTableName) -} - -func (a appMessageLog) As(alias string) *appMessageLog { - a.appMessageLogDo.DO = *(a.appMessageLogDo.As(alias).(*gen.DO)) - return a.updateTableName(alias) -} - -func (a *appMessageLog) updateTableName(table string) *appMessageLog { - a.ALL = field.NewAsterisk(table) - a.ID = field.NewInt32(table, "id") - a.AppID = field.NewString(table, "app_id") - a.SenderID = field.NewString(table, "sender_id") - a.SenderName = field.NewString(table, "sender_name") - a.SendTime = field.NewTime(table, "send_time") - a.ReceiverID = field.NewString(table, "receiver_id") - a.MsgType = field.NewInt32(table, "msg_type") - a.Content = field.NewString(table, "content") - a.CreatedAt = field.NewTime(table, "created_at") - a.IsRead = field.NewInt32(table, "is_read") - - a.fillFieldMap() - - return a -} - -func (a *appMessageLog) GetFieldByName(fieldName string) (field.OrderExpr, bool) { - _f, ok := a.fieldMap[fieldName] - if !ok || _f == nil { - return nil, false - } - _oe, ok := _f.(field.OrderExpr) - return _oe, ok -} - -func (a *appMessageLog) fillFieldMap() { - a.fieldMap = make(map[string]field.Expr, 10) - a.fieldMap["id"] = a.ID - a.fieldMap["app_id"] = a.AppID - a.fieldMap["sender_id"] = a.SenderID - a.fieldMap["sender_name"] = a.SenderName - a.fieldMap["send_time"] = a.SendTime - a.fieldMap["receiver_id"] = a.ReceiverID - a.fieldMap["msg_type"] = a.MsgType - a.fieldMap["content"] = a.Content - a.fieldMap["created_at"] = a.CreatedAt - a.fieldMap["is_read"] = a.IsRead -} - -func (a appMessageLog) clone(db *gorm.DB) appMessageLog { - a.appMessageLogDo.ReplaceConnPool(db.Statement.ConnPool) - return a -} - -func (a appMessageLog) replaceDB(db *gorm.DB) appMessageLog { - a.appMessageLogDo.ReplaceDB(db) - return a -} - -type appMessageLogDo struct{ gen.DO } - -func (a appMessageLogDo) Debug() *appMessageLogDo { - return a.withDO(a.DO.Debug()) -} - -func (a appMessageLogDo) WithContext(ctx context.Context) *appMessageLogDo { - return a.withDO(a.DO.WithContext(ctx)) -} - -func (a appMessageLogDo) ReadDB() *appMessageLogDo { - return a.Clauses(dbresolver.Read) -} - -func (a appMessageLogDo) WriteDB() *appMessageLogDo { - return a.Clauses(dbresolver.Write) -} - -func (a appMessageLogDo) Session(config *gorm.Session) *appMessageLogDo { - return a.withDO(a.DO.Session(config)) -} - -func (a appMessageLogDo) Clauses(conds ...clause.Expression) *appMessageLogDo { - return a.withDO(a.DO.Clauses(conds...)) -} - -func (a appMessageLogDo) Returning(value interface{}, columns ...string) *appMessageLogDo { - return a.withDO(a.DO.Returning(value, columns...)) -} - -func (a appMessageLogDo) Not(conds ...gen.Condition) *appMessageLogDo { - return a.withDO(a.DO.Not(conds...)) -} - -func (a appMessageLogDo) Or(conds ...gen.Condition) *appMessageLogDo { - return a.withDO(a.DO.Or(conds...)) -} - -func (a appMessageLogDo) Select(conds ...field.Expr) *appMessageLogDo { - return a.withDO(a.DO.Select(conds...)) -} - -func (a appMessageLogDo) Where(conds ...gen.Condition) *appMessageLogDo { - return a.withDO(a.DO.Where(conds...)) -} - -func (a appMessageLogDo) Order(conds ...field.Expr) *appMessageLogDo { - return a.withDO(a.DO.Order(conds...)) -} - -func (a appMessageLogDo) Distinct(cols ...field.Expr) *appMessageLogDo { - return a.withDO(a.DO.Distinct(cols...)) -} - -func (a appMessageLogDo) Omit(cols ...field.Expr) *appMessageLogDo { - return a.withDO(a.DO.Omit(cols...)) -} - -func (a appMessageLogDo) Join(table schema.Tabler, on ...field.Expr) *appMessageLogDo { - return a.withDO(a.DO.Join(table, on...)) -} - -func (a appMessageLogDo) LeftJoin(table schema.Tabler, on ...field.Expr) *appMessageLogDo { - return a.withDO(a.DO.LeftJoin(table, on...)) -} - -func (a appMessageLogDo) RightJoin(table schema.Tabler, on ...field.Expr) *appMessageLogDo { - return a.withDO(a.DO.RightJoin(table, on...)) -} - -func (a appMessageLogDo) Group(cols ...field.Expr) *appMessageLogDo { - return a.withDO(a.DO.Group(cols...)) -} - -func (a appMessageLogDo) Having(conds ...gen.Condition) *appMessageLogDo { - return a.withDO(a.DO.Having(conds...)) -} - -func (a appMessageLogDo) Limit(limit int) *appMessageLogDo { - return a.withDO(a.DO.Limit(limit)) -} - -func (a appMessageLogDo) Offset(offset int) *appMessageLogDo { - return a.withDO(a.DO.Offset(offset)) -} - -func (a appMessageLogDo) Scopes(funcs ...func(gen.Dao) gen.Dao) *appMessageLogDo { - return a.withDO(a.DO.Scopes(funcs...)) -} - -func (a appMessageLogDo) Unscoped() *appMessageLogDo { - return a.withDO(a.DO.Unscoped()) -} - -func (a appMessageLogDo) Create(values ...*model.AppMessageLog) error { - if len(values) == 0 { - return nil - } - return a.DO.Create(values) -} - -func (a appMessageLogDo) CreateInBatches(values []*model.AppMessageLog, batchSize int) error { - return a.DO.CreateInBatches(values, batchSize) -} - -// Save : !!! underlying implementation is different with GORM -// The method is equivalent to executing the statement: db.Clauses(clause.OnConflict{UpdateAll: true}).Create(values) -func (a appMessageLogDo) Save(values ...*model.AppMessageLog) error { - if len(values) == 0 { - return nil - } - return a.DO.Save(values) -} - -func (a appMessageLogDo) First() (*model.AppMessageLog, error) { - if result, err := a.DO.First(); err != nil { - return nil, err - } else { - return result.(*model.AppMessageLog), nil - } -} - -func (a appMessageLogDo) Take() (*model.AppMessageLog, error) { - if result, err := a.DO.Take(); err != nil { - return nil, err - } else { - return result.(*model.AppMessageLog), nil - } -} - -func (a appMessageLogDo) Last() (*model.AppMessageLog, error) { - if result, err := a.DO.Last(); err != nil { - return nil, err - } else { - return result.(*model.AppMessageLog), nil - } -} - -func (a appMessageLogDo) Find() ([]*model.AppMessageLog, error) { - result, err := a.DO.Find() - return result.([]*model.AppMessageLog), err -} - -func (a appMessageLogDo) FindInBatch(batchSize int, fc func(tx gen.Dao, batch int) error) (results []*model.AppMessageLog, err error) { - buf := make([]*model.AppMessageLog, 0, batchSize) - err = a.DO.FindInBatches(&buf, batchSize, func(tx gen.Dao, batch int) error { - defer func() { results = append(results, buf...) }() - return fc(tx, batch) - }) - return results, err -} - -func (a appMessageLogDo) FindInBatches(result *[]*model.AppMessageLog, batchSize int, fc func(tx gen.Dao, batch int) error) error { - return a.DO.FindInBatches(result, batchSize, fc) -} - -func (a appMessageLogDo) Attrs(attrs ...field.AssignExpr) *appMessageLogDo { - return a.withDO(a.DO.Attrs(attrs...)) -} - -func (a appMessageLogDo) Assign(attrs ...field.AssignExpr) *appMessageLogDo { - return a.withDO(a.DO.Assign(attrs...)) -} - -func (a appMessageLogDo) Joins(fields ...field.RelationField) *appMessageLogDo { - for _, _f := range fields { - a = *a.withDO(a.DO.Joins(_f)) - } - return &a -} - -func (a appMessageLogDo) Preload(fields ...field.RelationField) *appMessageLogDo { - for _, _f := range fields { - a = *a.withDO(a.DO.Preload(_f)) - } - return &a -} - -func (a appMessageLogDo) FirstOrInit() (*model.AppMessageLog, error) { - if result, err := a.DO.FirstOrInit(); err != nil { - return nil, err - } else { - return result.(*model.AppMessageLog), nil - } -} - -func (a appMessageLogDo) FirstOrCreate() (*model.AppMessageLog, error) { - if result, err := a.DO.FirstOrCreate(); err != nil { - return nil, err - } else { - return result.(*model.AppMessageLog), nil - } -} - -func (a appMessageLogDo) FindByPage(offset int, limit int) (result []*model.AppMessageLog, count int64, err error) { - result, err = a.Offset(offset).Limit(limit).Find() - if err != nil { - return - } - - if size := len(result); 0 < limit && 0 < size && size < limit { - count = int64(size + offset) - return - } - - count, err = a.Offset(-1).Limit(-1).Count() - return -} - -func (a appMessageLogDo) ScanByPage(result interface{}, offset int, limit int) (count int64, err error) { - count, err = a.Count() - if err != nil { - return - } - - err = a.Offset(offset).Limit(limit).Scan(result) - return -} - -func (a appMessageLogDo) Scan(result interface{}) (err error) { - return a.DO.Scan(result) -} - -func (a appMessageLogDo) Delete(models ...*model.AppMessageLog) (result gen.ResultInfo, err error) { - return a.DO.Delete(models) -} - -func (a *appMessageLogDo) withDO(do gen.Dao) *appMessageLogDo { - a.DO = *do.(*gen.DO) - return a -} diff --git a/internal/repository/mysql/dao/app_user.gen.go b/internal/repository/mysql/dao/app_user.gen.go deleted file mode 100644 index f6041ce..0000000 --- a/internal/repository/mysql/dao/app_user.gen.go +++ /dev/null @@ -1,344 +0,0 @@ -// Code generated by gorm.io/gen. DO NOT EDIT. -// Code generated by gorm.io/gen. DO NOT EDIT. -// Code generated by gorm.io/gen. DO NOT EDIT. - -package dao - -import ( - "context" - - "gorm.io/gorm" - "gorm.io/gorm/clause" - "gorm.io/gorm/schema" - - "gorm.io/gen" - "gorm.io/gen/field" - - "gorm.io/plugin/dbresolver" - - "mini-chat/internal/repository/mysql/model" -) - -func newAppUser(db *gorm.DB, opts ...gen.DOOption) appUser { - _appUser := appUser{} - - _appUser.appUserDo.UseDB(db, opts...) - _appUser.appUserDo.UseModel(&model.AppUser{}) - - tableName := _appUser.appUserDo.TableName() - _appUser.ALL = field.NewAsterisk(tableName) - _appUser.ID = field.NewInt32(tableName, "id") - _appUser.AppID = field.NewString(tableName, "app_id") - _appUser.UserID = field.NewString(tableName, "user_id") - _appUser.UserName = field.NewString(tableName, "user_name") - _appUser.UserMobile = field.NewString(tableName, "user_mobile") - _appUser.UserAvatar = field.NewString(tableName, "user_avatar") - _appUser.CreatedAt = field.NewTime(tableName, "created_at") - - _appUser.fillFieldMap() - - return _appUser -} - -// appUser 小程序的用户表 -type appUser struct { - appUserDo - - ALL field.Asterisk - ID field.Int32 // 主键ID - AppID field.String // 小程序ID - UserID field.String // 用户ID - UserName field.String // 用户昵称 - UserMobile field.String // 用户手机号 - UserAvatar field.String // 用户头像 - CreatedAt field.Time // 创建时间 - - fieldMap map[string]field.Expr -} - -func (a appUser) Table(newTableName string) *appUser { - a.appUserDo.UseTable(newTableName) - return a.updateTableName(newTableName) -} - -func (a appUser) As(alias string) *appUser { - a.appUserDo.DO = *(a.appUserDo.As(alias).(*gen.DO)) - return a.updateTableName(alias) -} - -func (a *appUser) updateTableName(table string) *appUser { - a.ALL = field.NewAsterisk(table) - a.ID = field.NewInt32(table, "id") - a.AppID = field.NewString(table, "app_id") - a.UserID = field.NewString(table, "user_id") - a.UserName = field.NewString(table, "user_name") - a.UserMobile = field.NewString(table, "user_mobile") - a.UserAvatar = field.NewString(table, "user_avatar") - a.CreatedAt = field.NewTime(table, "created_at") - - a.fillFieldMap() - - return a -} - -func (a *appUser) GetFieldByName(fieldName string) (field.OrderExpr, bool) { - _f, ok := a.fieldMap[fieldName] - if !ok || _f == nil { - return nil, false - } - _oe, ok := _f.(field.OrderExpr) - return _oe, ok -} - -func (a *appUser) fillFieldMap() { - a.fieldMap = make(map[string]field.Expr, 7) - a.fieldMap["id"] = a.ID - a.fieldMap["app_id"] = a.AppID - a.fieldMap["user_id"] = a.UserID - a.fieldMap["user_name"] = a.UserName - a.fieldMap["user_mobile"] = a.UserMobile - a.fieldMap["user_avatar"] = a.UserAvatar - a.fieldMap["created_at"] = a.CreatedAt -} - -func (a appUser) clone(db *gorm.DB) appUser { - a.appUserDo.ReplaceConnPool(db.Statement.ConnPool) - return a -} - -func (a appUser) replaceDB(db *gorm.DB) appUser { - a.appUserDo.ReplaceDB(db) - return a -} - -type appUserDo struct{ gen.DO } - -func (a appUserDo) Debug() *appUserDo { - return a.withDO(a.DO.Debug()) -} - -func (a appUserDo) WithContext(ctx context.Context) *appUserDo { - return a.withDO(a.DO.WithContext(ctx)) -} - -func (a appUserDo) ReadDB() *appUserDo { - return a.Clauses(dbresolver.Read) -} - -func (a appUserDo) WriteDB() *appUserDo { - return a.Clauses(dbresolver.Write) -} - -func (a appUserDo) Session(config *gorm.Session) *appUserDo { - return a.withDO(a.DO.Session(config)) -} - -func (a appUserDo) Clauses(conds ...clause.Expression) *appUserDo { - return a.withDO(a.DO.Clauses(conds...)) -} - -func (a appUserDo) Returning(value interface{}, columns ...string) *appUserDo { - return a.withDO(a.DO.Returning(value, columns...)) -} - -func (a appUserDo) Not(conds ...gen.Condition) *appUserDo { - return a.withDO(a.DO.Not(conds...)) -} - -func (a appUserDo) Or(conds ...gen.Condition) *appUserDo { - return a.withDO(a.DO.Or(conds...)) -} - -func (a appUserDo) Select(conds ...field.Expr) *appUserDo { - return a.withDO(a.DO.Select(conds...)) -} - -func (a appUserDo) Where(conds ...gen.Condition) *appUserDo { - return a.withDO(a.DO.Where(conds...)) -} - -func (a appUserDo) Order(conds ...field.Expr) *appUserDo { - return a.withDO(a.DO.Order(conds...)) -} - -func (a appUserDo) Distinct(cols ...field.Expr) *appUserDo { - return a.withDO(a.DO.Distinct(cols...)) -} - -func (a appUserDo) Omit(cols ...field.Expr) *appUserDo { - return a.withDO(a.DO.Omit(cols...)) -} - -func (a appUserDo) Join(table schema.Tabler, on ...field.Expr) *appUserDo { - return a.withDO(a.DO.Join(table, on...)) -} - -func (a appUserDo) LeftJoin(table schema.Tabler, on ...field.Expr) *appUserDo { - return a.withDO(a.DO.LeftJoin(table, on...)) -} - -func (a appUserDo) RightJoin(table schema.Tabler, on ...field.Expr) *appUserDo { - return a.withDO(a.DO.RightJoin(table, on...)) -} - -func (a appUserDo) Group(cols ...field.Expr) *appUserDo { - return a.withDO(a.DO.Group(cols...)) -} - -func (a appUserDo) Having(conds ...gen.Condition) *appUserDo { - return a.withDO(a.DO.Having(conds...)) -} - -func (a appUserDo) Limit(limit int) *appUserDo { - return a.withDO(a.DO.Limit(limit)) -} - -func (a appUserDo) Offset(offset int) *appUserDo { - return a.withDO(a.DO.Offset(offset)) -} - -func (a appUserDo) Scopes(funcs ...func(gen.Dao) gen.Dao) *appUserDo { - return a.withDO(a.DO.Scopes(funcs...)) -} - -func (a appUserDo) Unscoped() *appUserDo { - return a.withDO(a.DO.Unscoped()) -} - -func (a appUserDo) Create(values ...*model.AppUser) error { - if len(values) == 0 { - return nil - } - return a.DO.Create(values) -} - -func (a appUserDo) CreateInBatches(values []*model.AppUser, batchSize int) error { - return a.DO.CreateInBatches(values, batchSize) -} - -// Save : !!! underlying implementation is different with GORM -// The method is equivalent to executing the statement: db.Clauses(clause.OnConflict{UpdateAll: true}).Create(values) -func (a appUserDo) Save(values ...*model.AppUser) error { - if len(values) == 0 { - return nil - } - return a.DO.Save(values) -} - -func (a appUserDo) First() (*model.AppUser, error) { - if result, err := a.DO.First(); err != nil { - return nil, err - } else { - return result.(*model.AppUser), nil - } -} - -func (a appUserDo) Take() (*model.AppUser, error) { - if result, err := a.DO.Take(); err != nil { - return nil, err - } else { - return result.(*model.AppUser), nil - } -} - -func (a appUserDo) Last() (*model.AppUser, error) { - if result, err := a.DO.Last(); err != nil { - return nil, err - } else { - return result.(*model.AppUser), nil - } -} - -func (a appUserDo) Find() ([]*model.AppUser, error) { - result, err := a.DO.Find() - return result.([]*model.AppUser), err -} - -func (a appUserDo) FindInBatch(batchSize int, fc func(tx gen.Dao, batch int) error) (results []*model.AppUser, err error) { - buf := make([]*model.AppUser, 0, batchSize) - err = a.DO.FindInBatches(&buf, batchSize, func(tx gen.Dao, batch int) error { - defer func() { results = append(results, buf...) }() - return fc(tx, batch) - }) - return results, err -} - -func (a appUserDo) FindInBatches(result *[]*model.AppUser, batchSize int, fc func(tx gen.Dao, batch int) error) error { - return a.DO.FindInBatches(result, batchSize, fc) -} - -func (a appUserDo) Attrs(attrs ...field.AssignExpr) *appUserDo { - return a.withDO(a.DO.Attrs(attrs...)) -} - -func (a appUserDo) Assign(attrs ...field.AssignExpr) *appUserDo { - return a.withDO(a.DO.Assign(attrs...)) -} - -func (a appUserDo) Joins(fields ...field.RelationField) *appUserDo { - for _, _f := range fields { - a = *a.withDO(a.DO.Joins(_f)) - } - return &a -} - -func (a appUserDo) Preload(fields ...field.RelationField) *appUserDo { - for _, _f := range fields { - a = *a.withDO(a.DO.Preload(_f)) - } - return &a -} - -func (a appUserDo) FirstOrInit() (*model.AppUser, error) { - if result, err := a.DO.FirstOrInit(); err != nil { - return nil, err - } else { - return result.(*model.AppUser), nil - } -} - -func (a appUserDo) FirstOrCreate() (*model.AppUser, error) { - if result, err := a.DO.FirstOrCreate(); err != nil { - return nil, err - } else { - return result.(*model.AppUser), nil - } -} - -func (a appUserDo) FindByPage(offset int, limit int) (result []*model.AppUser, count int64, err error) { - result, err = a.Offset(offset).Limit(limit).Find() - if err != nil { - return - } - - if size := len(result); 0 < limit && 0 < size && size < limit { - count = int64(size + offset) - return - } - - count, err = a.Offset(-1).Limit(-1).Count() - return -} - -func (a appUserDo) ScanByPage(result interface{}, offset int, limit int) (count int64, err error) { - count, err = a.Count() - if err != nil { - return - } - - err = a.Offset(offset).Limit(limit).Scan(result) - return -} - -func (a appUserDo) Scan(result interface{}) (err error) { - return a.DO.Scan(result) -} - -func (a appUserDo) Delete(models ...*model.AppUser) (result gen.ResultInfo, err error) { - return a.DO.Delete(models) -} - -func (a *appUserDo) withDO(do gen.Dao) *appUserDo { - a.DO = *do.(*gen.DO) - return a -} diff --git a/internal/repository/mysql/dao/banner.gen.go b/internal/repository/mysql/dao/banner.gen.go new file mode 100644 index 0000000..9e28aa2 --- /dev/null +++ b/internal/repository/mysql/dao/banner.gen.go @@ -0,0 +1,348 @@ +// Code generated by gorm.io/gen. DO NOT EDIT. +// Code generated by gorm.io/gen. DO NOT EDIT. +// Code generated by gorm.io/gen. DO NOT EDIT. + +package dao + +import ( + "context" + + "gorm.io/gorm" + "gorm.io/gorm/clause" + "gorm.io/gorm/schema" + + "gorm.io/gen" + "gorm.io/gen/field" + + "gorm.io/plugin/dbresolver" + + "bindbox-game/internal/repository/mysql/model" +) + +func newBanner(db *gorm.DB, opts ...gen.DOOption) banner { + _banner := banner{} + + _banner.bannerDo.UseDB(db, opts...) + _banner.bannerDo.UseModel(&model.Banner{}) + + tableName := _banner.bannerDo.TableName() + _banner.ALL = field.NewAsterisk(tableName) + _banner.ID = field.NewInt64(tableName, "id") + _banner.Title = field.NewString(tableName, "title") + _banner.ImageURL = field.NewString(tableName, "image_url") + _banner.LinkURL = field.NewString(tableName, "link_url") + _banner.Sort = field.NewInt32(tableName, "sort") + _banner.Status = field.NewInt32(tableName, "status") + _banner.CreatedAt = field.NewTime(tableName, "created_at") + _banner.UpdatedAt = field.NewTime(tableName, "updated_at") + + _banner.fillFieldMap() + + return _banner +} + +// banner 轮播图 +type banner struct { + bannerDo + + ALL field.Asterisk + ID field.Int64 + Title field.String // 标题 + ImageURL field.String // 图片URL + LinkURL field.String // 跳转链接(可选) + Sort field.Int32 // 排序,越小越靠前 + Status field.Int32 // 状态:1启用 0禁用 + CreatedAt field.Time + UpdatedAt field.Time + + fieldMap map[string]field.Expr +} + +func (b banner) Table(newTableName string) *banner { + b.bannerDo.UseTable(newTableName) + return b.updateTableName(newTableName) +} + +func (b banner) As(alias string) *banner { + b.bannerDo.DO = *(b.bannerDo.As(alias).(*gen.DO)) + return b.updateTableName(alias) +} + +func (b *banner) updateTableName(table string) *banner { + b.ALL = field.NewAsterisk(table) + b.ID = field.NewInt64(table, "id") + b.Title = field.NewString(table, "title") + b.ImageURL = field.NewString(table, "image_url") + b.LinkURL = field.NewString(table, "link_url") + b.Sort = field.NewInt32(table, "sort") + b.Status = field.NewInt32(table, "status") + b.CreatedAt = field.NewTime(table, "created_at") + b.UpdatedAt = field.NewTime(table, "updated_at") + + b.fillFieldMap() + + return b +} + +func (b *banner) GetFieldByName(fieldName string) (field.OrderExpr, bool) { + _f, ok := b.fieldMap[fieldName] + if !ok || _f == nil { + return nil, false + } + _oe, ok := _f.(field.OrderExpr) + return _oe, ok +} + +func (b *banner) fillFieldMap() { + b.fieldMap = make(map[string]field.Expr, 8) + b.fieldMap["id"] = b.ID + b.fieldMap["title"] = b.Title + b.fieldMap["image_url"] = b.ImageURL + b.fieldMap["link_url"] = b.LinkURL + b.fieldMap["sort"] = b.Sort + b.fieldMap["status"] = b.Status + b.fieldMap["created_at"] = b.CreatedAt + b.fieldMap["updated_at"] = b.UpdatedAt +} + +func (b banner) clone(db *gorm.DB) banner { + b.bannerDo.ReplaceConnPool(db.Statement.ConnPool) + return b +} + +func (b banner) replaceDB(db *gorm.DB) banner { + b.bannerDo.ReplaceDB(db) + return b +} + +type bannerDo struct{ gen.DO } + +func (b bannerDo) Debug() *bannerDo { + return b.withDO(b.DO.Debug()) +} + +func (b bannerDo) WithContext(ctx context.Context) *bannerDo { + return b.withDO(b.DO.WithContext(ctx)) +} + +func (b bannerDo) ReadDB() *bannerDo { + return b.Clauses(dbresolver.Read) +} + +func (b bannerDo) WriteDB() *bannerDo { + return b.Clauses(dbresolver.Write) +} + +func (b bannerDo) Session(config *gorm.Session) *bannerDo { + return b.withDO(b.DO.Session(config)) +} + +func (b bannerDo) Clauses(conds ...clause.Expression) *bannerDo { + return b.withDO(b.DO.Clauses(conds...)) +} + +func (b bannerDo) Returning(value interface{}, columns ...string) *bannerDo { + return b.withDO(b.DO.Returning(value, columns...)) +} + +func (b bannerDo) Not(conds ...gen.Condition) *bannerDo { + return b.withDO(b.DO.Not(conds...)) +} + +func (b bannerDo) Or(conds ...gen.Condition) *bannerDo { + return b.withDO(b.DO.Or(conds...)) +} + +func (b bannerDo) Select(conds ...field.Expr) *bannerDo { + return b.withDO(b.DO.Select(conds...)) +} + +func (b bannerDo) Where(conds ...gen.Condition) *bannerDo { + return b.withDO(b.DO.Where(conds...)) +} + +func (b bannerDo) Order(conds ...field.Expr) *bannerDo { + return b.withDO(b.DO.Order(conds...)) +} + +func (b bannerDo) Distinct(cols ...field.Expr) *bannerDo { + return b.withDO(b.DO.Distinct(cols...)) +} + +func (b bannerDo) Omit(cols ...field.Expr) *bannerDo { + return b.withDO(b.DO.Omit(cols...)) +} + +func (b bannerDo) Join(table schema.Tabler, on ...field.Expr) *bannerDo { + return b.withDO(b.DO.Join(table, on...)) +} + +func (b bannerDo) LeftJoin(table schema.Tabler, on ...field.Expr) *bannerDo { + return b.withDO(b.DO.LeftJoin(table, on...)) +} + +func (b bannerDo) RightJoin(table schema.Tabler, on ...field.Expr) *bannerDo { + return b.withDO(b.DO.RightJoin(table, on...)) +} + +func (b bannerDo) Group(cols ...field.Expr) *bannerDo { + return b.withDO(b.DO.Group(cols...)) +} + +func (b bannerDo) Having(conds ...gen.Condition) *bannerDo { + return b.withDO(b.DO.Having(conds...)) +} + +func (b bannerDo) Limit(limit int) *bannerDo { + return b.withDO(b.DO.Limit(limit)) +} + +func (b bannerDo) Offset(offset int) *bannerDo { + return b.withDO(b.DO.Offset(offset)) +} + +func (b bannerDo) Scopes(funcs ...func(gen.Dao) gen.Dao) *bannerDo { + return b.withDO(b.DO.Scopes(funcs...)) +} + +func (b bannerDo) Unscoped() *bannerDo { + return b.withDO(b.DO.Unscoped()) +} + +func (b bannerDo) Create(values ...*model.Banner) error { + if len(values) == 0 { + return nil + } + return b.DO.Create(values) +} + +func (b bannerDo) CreateInBatches(values []*model.Banner, batchSize int) error { + return b.DO.CreateInBatches(values, batchSize) +} + +// Save : !!! underlying implementation is different with GORM +// The method is equivalent to executing the statement: db.Clauses(clause.OnConflict{UpdateAll: true}).Create(values) +func (b bannerDo) Save(values ...*model.Banner) error { + if len(values) == 0 { + return nil + } + return b.DO.Save(values) +} + +func (b bannerDo) First() (*model.Banner, error) { + if result, err := b.DO.First(); err != nil { + return nil, err + } else { + return result.(*model.Banner), nil + } +} + +func (b bannerDo) Take() (*model.Banner, error) { + if result, err := b.DO.Take(); err != nil { + return nil, err + } else { + return result.(*model.Banner), nil + } +} + +func (b bannerDo) Last() (*model.Banner, error) { + if result, err := b.DO.Last(); err != nil { + return nil, err + } else { + return result.(*model.Banner), nil + } +} + +func (b bannerDo) Find() ([]*model.Banner, error) { + result, err := b.DO.Find() + return result.([]*model.Banner), err +} + +func (b bannerDo) FindInBatch(batchSize int, fc func(tx gen.Dao, batch int) error) (results []*model.Banner, err error) { + buf := make([]*model.Banner, 0, batchSize) + err = b.DO.FindInBatches(&buf, batchSize, func(tx gen.Dao, batch int) error { + defer func() { results = append(results, buf...) }() + return fc(tx, batch) + }) + return results, err +} + +func (b bannerDo) FindInBatches(result *[]*model.Banner, batchSize int, fc func(tx gen.Dao, batch int) error) error { + return b.DO.FindInBatches(result, batchSize, fc) +} + +func (b bannerDo) Attrs(attrs ...field.AssignExpr) *bannerDo { + return b.withDO(b.DO.Attrs(attrs...)) +} + +func (b bannerDo) Assign(attrs ...field.AssignExpr) *bannerDo { + return b.withDO(b.DO.Assign(attrs...)) +} + +func (b bannerDo) Joins(fields ...field.RelationField) *bannerDo { + for _, _f := range fields { + b = *b.withDO(b.DO.Joins(_f)) + } + return &b +} + +func (b bannerDo) Preload(fields ...field.RelationField) *bannerDo { + for _, _f := range fields { + b = *b.withDO(b.DO.Preload(_f)) + } + return &b +} + +func (b bannerDo) FirstOrInit() (*model.Banner, error) { + if result, err := b.DO.FirstOrInit(); err != nil { + return nil, err + } else { + return result.(*model.Banner), nil + } +} + +func (b bannerDo) FirstOrCreate() (*model.Banner, error) { + if result, err := b.DO.FirstOrCreate(); err != nil { + return nil, err + } else { + return result.(*model.Banner), nil + } +} + +func (b bannerDo) FindByPage(offset int, limit int) (result []*model.Banner, count int64, err error) { + result, err = b.Offset(offset).Limit(limit).Find() + if err != nil { + return + } + + if size := len(result); 0 < limit && 0 < size && size < limit { + count = int64(size + offset) + return + } + + count, err = b.Offset(-1).Limit(-1).Count() + return +} + +func (b bannerDo) ScanByPage(result interface{}, offset int, limit int) (count int64, err error) { + count, err = b.Count() + if err != nil { + return + } + + err = b.Offset(offset).Limit(limit).Scan(result) + return +} + +func (b bannerDo) Scan(result interface{}) (err error) { + return b.DO.Scan(result) +} + +func (b bannerDo) Delete(models ...*model.Banner) (result gen.ResultInfo, err error) { + return b.DO.Delete(models) +} + +func (b *bannerDo) withDO(do gen.Dao) *bannerDo { + b.DO = *do.(*gen.DO) + return b +} diff --git a/internal/repository/mysql/dao/gen.go b/internal/repository/mysql/dao/gen.go index 3d78192..f8e007c 100644 --- a/internal/repository/mysql/dao/gen.go +++ b/internal/repository/mysql/dao/gen.go @@ -17,57 +17,165 @@ import ( var ( Q = new(Query) + Activities *activities + ActivityCategories *activityCategories + ActivityDrawEffects *activityDrawEffects + ActivityDrawLogs *activityDrawLogs + ActivityIssues *activityIssues + ActivityRewardSettings *activityRewardSettings Admin *admin - AppKeyword *appKeyword - AppKeywordReply *appKeywordReply - AppMessageLog *appMessageLog - AppUser *appUser + Banner *banner + Guild *guild + GuildBoxes *guildBoxes + GuildContributeLogs *guildContributeLogs + GuildMembers *guildMembers LogOperation *logOperation LogRequest *logRequest - MiniProgram *miniProgram - MiniProgramAccessToken *miniProgramAccessToken + MenuActions *menuActions + Menus *menus + OrderItems *orderItems + Orders *orders + ProductCategories *productCategories + Products *products + RoleActions *roleActions + RoleMenus *roleMenus + RoleUsers *roleUsers + Roles *roles + ShippingRecords *shippingRecords + SystemCoupons *systemCoupons + SystemItemCards *systemItemCards + UserAddresses *userAddresses + UserCoupons *userCoupons + UserInventory *userInventory + UserInventoryTransfers *userInventoryTransfers + UserInvites *userInvites + UserItemCards *userItemCards + UserPoints *userPoints + UserPointsLedger *userPointsLedger + Users *users ) func SetDefault(db *gorm.DB, opts ...gen.DOOption) { *Q = *Use(db, opts...) + Activities = &Q.Activities + ActivityCategories = &Q.ActivityCategories + ActivityDrawEffects = &Q.ActivityDrawEffects + ActivityDrawLogs = &Q.ActivityDrawLogs + ActivityIssues = &Q.ActivityIssues + ActivityRewardSettings = &Q.ActivityRewardSettings Admin = &Q.Admin - AppKeyword = &Q.AppKeyword - AppKeywordReply = &Q.AppKeywordReply - AppMessageLog = &Q.AppMessageLog - AppUser = &Q.AppUser + Banner = &Q.Banner + Guild = &Q.Guild + GuildBoxes = &Q.GuildBoxes + GuildContributeLogs = &Q.GuildContributeLogs + GuildMembers = &Q.GuildMembers LogOperation = &Q.LogOperation LogRequest = &Q.LogRequest - MiniProgram = &Q.MiniProgram - MiniProgramAccessToken = &Q.MiniProgramAccessToken + MenuActions = &Q.MenuActions + Menus = &Q.Menus + OrderItems = &Q.OrderItems + Orders = &Q.Orders + ProductCategories = &Q.ProductCategories + Products = &Q.Products + RoleActions = &Q.RoleActions + RoleMenus = &Q.RoleMenus + RoleUsers = &Q.RoleUsers + Roles = &Q.Roles + ShippingRecords = &Q.ShippingRecords + SystemCoupons = &Q.SystemCoupons + SystemItemCards = &Q.SystemItemCards + UserAddresses = &Q.UserAddresses + UserCoupons = &Q.UserCoupons + UserInventory = &Q.UserInventory + UserInventoryTransfers = &Q.UserInventoryTransfers + UserInvites = &Q.UserInvites + UserItemCards = &Q.UserItemCards + UserPoints = &Q.UserPoints + UserPointsLedger = &Q.UserPointsLedger + Users = &Q.Users } func Use(db *gorm.DB, opts ...gen.DOOption) *Query { return &Query{ db: db, + Activities: newActivities(db, opts...), + ActivityCategories: newActivityCategories(db, opts...), + ActivityDrawEffects: newActivityDrawEffects(db, opts...), + ActivityDrawLogs: newActivityDrawLogs(db, opts...), + ActivityIssues: newActivityIssues(db, opts...), + ActivityRewardSettings: newActivityRewardSettings(db, opts...), Admin: newAdmin(db, opts...), - AppKeyword: newAppKeyword(db, opts...), - AppKeywordReply: newAppKeywordReply(db, opts...), - AppMessageLog: newAppMessageLog(db, opts...), - AppUser: newAppUser(db, opts...), + Banner: newBanner(db, opts...), + Guild: newGuild(db, opts...), + GuildBoxes: newGuildBoxes(db, opts...), + GuildContributeLogs: newGuildContributeLogs(db, opts...), + GuildMembers: newGuildMembers(db, opts...), LogOperation: newLogOperation(db, opts...), LogRequest: newLogRequest(db, opts...), - MiniProgram: newMiniProgram(db, opts...), - MiniProgramAccessToken: newMiniProgramAccessToken(db, opts...), + MenuActions: newMenuActions(db, opts...), + Menus: newMenus(db, opts...), + OrderItems: newOrderItems(db, opts...), + Orders: newOrders(db, opts...), + ProductCategories: newProductCategories(db, opts...), + Products: newProducts(db, opts...), + RoleActions: newRoleActions(db, opts...), + RoleMenus: newRoleMenus(db, opts...), + RoleUsers: newRoleUsers(db, opts...), + Roles: newRoles(db, opts...), + ShippingRecords: newShippingRecords(db, opts...), + SystemCoupons: newSystemCoupons(db, opts...), + SystemItemCards: newSystemItemCards(db, opts...), + UserAddresses: newUserAddresses(db, opts...), + UserCoupons: newUserCoupons(db, opts...), + UserInventory: newUserInventory(db, opts...), + UserInventoryTransfers: newUserInventoryTransfers(db, opts...), + UserInvites: newUserInvites(db, opts...), + UserItemCards: newUserItemCards(db, opts...), + UserPoints: newUserPoints(db, opts...), + UserPointsLedger: newUserPointsLedger(db, opts...), + Users: newUsers(db, opts...), } } type Query struct { db *gorm.DB + Activities activities + ActivityCategories activityCategories + ActivityDrawEffects activityDrawEffects + ActivityDrawLogs activityDrawLogs + ActivityIssues activityIssues + ActivityRewardSettings activityRewardSettings Admin admin - AppKeyword appKeyword - AppKeywordReply appKeywordReply - AppMessageLog appMessageLog - AppUser appUser + Banner banner + Guild guild + GuildBoxes guildBoxes + GuildContributeLogs guildContributeLogs + GuildMembers guildMembers LogOperation logOperation LogRequest logRequest - MiniProgram miniProgram - MiniProgramAccessToken miniProgramAccessToken + MenuActions menuActions + Menus menus + OrderItems orderItems + Orders orders + ProductCategories productCategories + Products products + RoleActions roleActions + RoleMenus roleMenus + RoleUsers roleUsers + Roles roles + ShippingRecords shippingRecords + SystemCoupons systemCoupons + SystemItemCards systemItemCards + UserAddresses userAddresses + UserCoupons userCoupons + UserInventory userInventory + UserInventoryTransfers userInventoryTransfers + UserInvites userInvites + UserItemCards userItemCards + UserPoints userPoints + UserPointsLedger userPointsLedger + Users users } func (q *Query) Available() bool { return q.db != nil } @@ -75,15 +183,42 @@ func (q *Query) Available() bool { return q.db != nil } func (q *Query) clone(db *gorm.DB) *Query { return &Query{ db: db, + Activities: q.Activities.clone(db), + ActivityCategories: q.ActivityCategories.clone(db), + ActivityDrawEffects: q.ActivityDrawEffects.clone(db), + ActivityDrawLogs: q.ActivityDrawLogs.clone(db), + ActivityIssues: q.ActivityIssues.clone(db), + ActivityRewardSettings: q.ActivityRewardSettings.clone(db), Admin: q.Admin.clone(db), - AppKeyword: q.AppKeyword.clone(db), - AppKeywordReply: q.AppKeywordReply.clone(db), - AppMessageLog: q.AppMessageLog.clone(db), - AppUser: q.AppUser.clone(db), + Banner: q.Banner.clone(db), + Guild: q.Guild.clone(db), + GuildBoxes: q.GuildBoxes.clone(db), + GuildContributeLogs: q.GuildContributeLogs.clone(db), + GuildMembers: q.GuildMembers.clone(db), LogOperation: q.LogOperation.clone(db), LogRequest: q.LogRequest.clone(db), - MiniProgram: q.MiniProgram.clone(db), - MiniProgramAccessToken: q.MiniProgramAccessToken.clone(db), + MenuActions: q.MenuActions.clone(db), + Menus: q.Menus.clone(db), + OrderItems: q.OrderItems.clone(db), + Orders: q.Orders.clone(db), + ProductCategories: q.ProductCategories.clone(db), + Products: q.Products.clone(db), + RoleActions: q.RoleActions.clone(db), + RoleMenus: q.RoleMenus.clone(db), + RoleUsers: q.RoleUsers.clone(db), + Roles: q.Roles.clone(db), + ShippingRecords: q.ShippingRecords.clone(db), + SystemCoupons: q.SystemCoupons.clone(db), + SystemItemCards: q.SystemItemCards.clone(db), + UserAddresses: q.UserAddresses.clone(db), + UserCoupons: q.UserCoupons.clone(db), + UserInventory: q.UserInventory.clone(db), + UserInventoryTransfers: q.UserInventoryTransfers.clone(db), + UserInvites: q.UserInvites.clone(db), + UserItemCards: q.UserItemCards.clone(db), + UserPoints: q.UserPoints.clone(db), + UserPointsLedger: q.UserPointsLedger.clone(db), + Users: q.Users.clone(db), } } @@ -98,41 +233,122 @@ func (q *Query) WriteDB() *Query { func (q *Query) ReplaceDB(db *gorm.DB) *Query { return &Query{ db: db, + Activities: q.Activities.replaceDB(db), + ActivityCategories: q.ActivityCategories.replaceDB(db), + ActivityDrawEffects: q.ActivityDrawEffects.replaceDB(db), + ActivityDrawLogs: q.ActivityDrawLogs.replaceDB(db), + ActivityIssues: q.ActivityIssues.replaceDB(db), + ActivityRewardSettings: q.ActivityRewardSettings.replaceDB(db), Admin: q.Admin.replaceDB(db), - AppKeyword: q.AppKeyword.replaceDB(db), - AppKeywordReply: q.AppKeywordReply.replaceDB(db), - AppMessageLog: q.AppMessageLog.replaceDB(db), - AppUser: q.AppUser.replaceDB(db), + Banner: q.Banner.replaceDB(db), + Guild: q.Guild.replaceDB(db), + GuildBoxes: q.GuildBoxes.replaceDB(db), + GuildContributeLogs: q.GuildContributeLogs.replaceDB(db), + GuildMembers: q.GuildMembers.replaceDB(db), LogOperation: q.LogOperation.replaceDB(db), LogRequest: q.LogRequest.replaceDB(db), - MiniProgram: q.MiniProgram.replaceDB(db), - MiniProgramAccessToken: q.MiniProgramAccessToken.replaceDB(db), + MenuActions: q.MenuActions.replaceDB(db), + Menus: q.Menus.replaceDB(db), + OrderItems: q.OrderItems.replaceDB(db), + Orders: q.Orders.replaceDB(db), + ProductCategories: q.ProductCategories.replaceDB(db), + Products: q.Products.replaceDB(db), + RoleActions: q.RoleActions.replaceDB(db), + RoleMenus: q.RoleMenus.replaceDB(db), + RoleUsers: q.RoleUsers.replaceDB(db), + Roles: q.Roles.replaceDB(db), + ShippingRecords: q.ShippingRecords.replaceDB(db), + SystemCoupons: q.SystemCoupons.replaceDB(db), + SystemItemCards: q.SystemItemCards.replaceDB(db), + UserAddresses: q.UserAddresses.replaceDB(db), + UserCoupons: q.UserCoupons.replaceDB(db), + UserInventory: q.UserInventory.replaceDB(db), + UserInventoryTransfers: q.UserInventoryTransfers.replaceDB(db), + UserInvites: q.UserInvites.replaceDB(db), + UserItemCards: q.UserItemCards.replaceDB(db), + UserPoints: q.UserPoints.replaceDB(db), + UserPointsLedger: q.UserPointsLedger.replaceDB(db), + Users: q.Users.replaceDB(db), } } type queryCtx struct { + Activities *activitiesDo + ActivityCategories *activityCategoriesDo + ActivityDrawEffects *activityDrawEffectsDo + ActivityDrawLogs *activityDrawLogsDo + ActivityIssues *activityIssuesDo + ActivityRewardSettings *activityRewardSettingsDo Admin *adminDo - AppKeyword *appKeywordDo - AppKeywordReply *appKeywordReplyDo - AppMessageLog *appMessageLogDo - AppUser *appUserDo + Banner *bannerDo + Guild *guildDo + GuildBoxes *guildBoxesDo + GuildContributeLogs *guildContributeLogsDo + GuildMembers *guildMembersDo LogOperation *logOperationDo LogRequest *logRequestDo - MiniProgram *miniProgramDo - MiniProgramAccessToken *miniProgramAccessTokenDo + MenuActions *menuActionsDo + Menus *menusDo + OrderItems *orderItemsDo + Orders *ordersDo + ProductCategories *productCategoriesDo + Products *productsDo + RoleActions *roleActionsDo + RoleMenus *roleMenusDo + RoleUsers *roleUsersDo + Roles *rolesDo + ShippingRecords *shippingRecordsDo + SystemCoupons *systemCouponsDo + SystemItemCards *systemItemCardsDo + UserAddresses *userAddressesDo + UserCoupons *userCouponsDo + UserInventory *userInventoryDo + UserInventoryTransfers *userInventoryTransfersDo + UserInvites *userInvitesDo + UserItemCards *userItemCardsDo + UserPoints *userPointsDo + UserPointsLedger *userPointsLedgerDo + Users *usersDo } func (q *Query) WithContext(ctx context.Context) *queryCtx { return &queryCtx{ + Activities: q.Activities.WithContext(ctx), + ActivityCategories: q.ActivityCategories.WithContext(ctx), + ActivityDrawEffects: q.ActivityDrawEffects.WithContext(ctx), + ActivityDrawLogs: q.ActivityDrawLogs.WithContext(ctx), + ActivityIssues: q.ActivityIssues.WithContext(ctx), + ActivityRewardSettings: q.ActivityRewardSettings.WithContext(ctx), Admin: q.Admin.WithContext(ctx), - AppKeyword: q.AppKeyword.WithContext(ctx), - AppKeywordReply: q.AppKeywordReply.WithContext(ctx), - AppMessageLog: q.AppMessageLog.WithContext(ctx), - AppUser: q.AppUser.WithContext(ctx), + Banner: q.Banner.WithContext(ctx), + Guild: q.Guild.WithContext(ctx), + GuildBoxes: q.GuildBoxes.WithContext(ctx), + GuildContributeLogs: q.GuildContributeLogs.WithContext(ctx), + GuildMembers: q.GuildMembers.WithContext(ctx), LogOperation: q.LogOperation.WithContext(ctx), LogRequest: q.LogRequest.WithContext(ctx), - MiniProgram: q.MiniProgram.WithContext(ctx), - MiniProgramAccessToken: q.MiniProgramAccessToken.WithContext(ctx), + MenuActions: q.MenuActions.WithContext(ctx), + Menus: q.Menus.WithContext(ctx), + OrderItems: q.OrderItems.WithContext(ctx), + Orders: q.Orders.WithContext(ctx), + ProductCategories: q.ProductCategories.WithContext(ctx), + Products: q.Products.WithContext(ctx), + RoleActions: q.RoleActions.WithContext(ctx), + RoleMenus: q.RoleMenus.WithContext(ctx), + RoleUsers: q.RoleUsers.WithContext(ctx), + Roles: q.Roles.WithContext(ctx), + ShippingRecords: q.ShippingRecords.WithContext(ctx), + SystemCoupons: q.SystemCoupons.WithContext(ctx), + SystemItemCards: q.SystemItemCards.WithContext(ctx), + UserAddresses: q.UserAddresses.WithContext(ctx), + UserCoupons: q.UserCoupons.WithContext(ctx), + UserInventory: q.UserInventory.WithContext(ctx), + UserInventoryTransfers: q.UserInventoryTransfers.WithContext(ctx), + UserInvites: q.UserInvites.WithContext(ctx), + UserItemCards: q.UserItemCards.WithContext(ctx), + UserPoints: q.UserPoints.WithContext(ctx), + UserPointsLedger: q.UserPointsLedger.WithContext(ctx), + Users: q.Users.WithContext(ctx), } } diff --git a/internal/repository/mysql/dao/guild.gen.go b/internal/repository/mysql/dao/guild.gen.go new file mode 100644 index 0000000..a586fac --- /dev/null +++ b/internal/repository/mysql/dao/guild.gen.go @@ -0,0 +1,356 @@ +// Code generated by gorm.io/gen. DO NOT EDIT. +// Code generated by gorm.io/gen. DO NOT EDIT. +// Code generated by gorm.io/gen. DO NOT EDIT. + +package dao + +import ( + "context" + + "gorm.io/gorm" + "gorm.io/gorm/clause" + "gorm.io/gorm/schema" + + "gorm.io/gen" + "gorm.io/gen/field" + + "gorm.io/plugin/dbresolver" + + "bindbox-game/internal/repository/mysql/model" +) + +func newGuild(db *gorm.DB, opts ...gen.DOOption) guild { + _guild := guild{} + + _guild.guildDo.UseDB(db, opts...) + _guild.guildDo.UseModel(&model.Guild{}) + + tableName := _guild.guildDo.TableName() + _guild.ALL = field.NewAsterisk(tableName) + _guild.ID = field.NewInt64(tableName, "id") + _guild.CreatedAt = field.NewTime(tableName, "created_at") + _guild.Name = field.NewString(tableName, "name") + _guild.OwnerID = field.NewInt64(tableName, "owner_id") + _guild.Status = field.NewInt32(tableName, "status") + _guild.Description = field.NewString(tableName, "description") + _guild.JoinMode = field.NewInt32(tableName, "join_mode") + _guild.ConsumeLimit = field.NewInt64(tableName, "consume_limit") + _guild.AvatarURL = field.NewString(tableName, "avatar_url") + _guild.IsOpen = field.NewInt32(tableName, "is_open") + + _guild.fillFieldMap() + + return _guild +} + +// guild 公会 +type guild struct { + guildDo + + ALL field.Asterisk + ID field.Int64 // 主键ID + CreatedAt field.Time // 创建时间 + Name field.String // 公会名称 + OwnerID field.Int64 // 会长用户ID + Status field.Int32 // 状态:1正常 2解散 + Description field.String // 工会描述 + JoinMode field.Int32 // 加入方式 1: 审核通过 2: 自动通过 3. 消费流水 + ConsumeLimit field.Int64 // 加入工会消费流水最低限额(分) + AvatarURL field.String // 工会头像 + IsOpen field.Int32 // 1 公开 2 私有 + + fieldMap map[string]field.Expr +} + +func (g guild) Table(newTableName string) *guild { + g.guildDo.UseTable(newTableName) + return g.updateTableName(newTableName) +} + +func (g guild) As(alias string) *guild { + g.guildDo.DO = *(g.guildDo.As(alias).(*gen.DO)) + return g.updateTableName(alias) +} + +func (g *guild) updateTableName(table string) *guild { + g.ALL = field.NewAsterisk(table) + g.ID = field.NewInt64(table, "id") + g.CreatedAt = field.NewTime(table, "created_at") + g.Name = field.NewString(table, "name") + g.OwnerID = field.NewInt64(table, "owner_id") + g.Status = field.NewInt32(table, "status") + g.Description = field.NewString(table, "description") + g.JoinMode = field.NewInt32(table, "join_mode") + g.ConsumeLimit = field.NewInt64(table, "consume_limit") + g.AvatarURL = field.NewString(table, "avatar_url") + g.IsOpen = field.NewInt32(table, "is_open") + + g.fillFieldMap() + + return g +} + +func (g *guild) GetFieldByName(fieldName string) (field.OrderExpr, bool) { + _f, ok := g.fieldMap[fieldName] + if !ok || _f == nil { + return nil, false + } + _oe, ok := _f.(field.OrderExpr) + return _oe, ok +} + +func (g *guild) fillFieldMap() { + g.fieldMap = make(map[string]field.Expr, 10) + g.fieldMap["id"] = g.ID + g.fieldMap["created_at"] = g.CreatedAt + g.fieldMap["name"] = g.Name + g.fieldMap["owner_id"] = g.OwnerID + g.fieldMap["status"] = g.Status + g.fieldMap["description"] = g.Description + g.fieldMap["join_mode"] = g.JoinMode + g.fieldMap["consume_limit"] = g.ConsumeLimit + g.fieldMap["avatar_url"] = g.AvatarURL + g.fieldMap["is_open"] = g.IsOpen +} + +func (g guild) clone(db *gorm.DB) guild { + g.guildDo.ReplaceConnPool(db.Statement.ConnPool) + return g +} + +func (g guild) replaceDB(db *gorm.DB) guild { + g.guildDo.ReplaceDB(db) + return g +} + +type guildDo struct{ gen.DO } + +func (g guildDo) Debug() *guildDo { + return g.withDO(g.DO.Debug()) +} + +func (g guildDo) WithContext(ctx context.Context) *guildDo { + return g.withDO(g.DO.WithContext(ctx)) +} + +func (g guildDo) ReadDB() *guildDo { + return g.Clauses(dbresolver.Read) +} + +func (g guildDo) WriteDB() *guildDo { + return g.Clauses(dbresolver.Write) +} + +func (g guildDo) Session(config *gorm.Session) *guildDo { + return g.withDO(g.DO.Session(config)) +} + +func (g guildDo) Clauses(conds ...clause.Expression) *guildDo { + return g.withDO(g.DO.Clauses(conds...)) +} + +func (g guildDo) Returning(value interface{}, columns ...string) *guildDo { + return g.withDO(g.DO.Returning(value, columns...)) +} + +func (g guildDo) Not(conds ...gen.Condition) *guildDo { + return g.withDO(g.DO.Not(conds...)) +} + +func (g guildDo) Or(conds ...gen.Condition) *guildDo { + return g.withDO(g.DO.Or(conds...)) +} + +func (g guildDo) Select(conds ...field.Expr) *guildDo { + return g.withDO(g.DO.Select(conds...)) +} + +func (g guildDo) Where(conds ...gen.Condition) *guildDo { + return g.withDO(g.DO.Where(conds...)) +} + +func (g guildDo) Order(conds ...field.Expr) *guildDo { + return g.withDO(g.DO.Order(conds...)) +} + +func (g guildDo) Distinct(cols ...field.Expr) *guildDo { + return g.withDO(g.DO.Distinct(cols...)) +} + +func (g guildDo) Omit(cols ...field.Expr) *guildDo { + return g.withDO(g.DO.Omit(cols...)) +} + +func (g guildDo) Join(table schema.Tabler, on ...field.Expr) *guildDo { + return g.withDO(g.DO.Join(table, on...)) +} + +func (g guildDo) LeftJoin(table schema.Tabler, on ...field.Expr) *guildDo { + return g.withDO(g.DO.LeftJoin(table, on...)) +} + +func (g guildDo) RightJoin(table schema.Tabler, on ...field.Expr) *guildDo { + return g.withDO(g.DO.RightJoin(table, on...)) +} + +func (g guildDo) Group(cols ...field.Expr) *guildDo { + return g.withDO(g.DO.Group(cols...)) +} + +func (g guildDo) Having(conds ...gen.Condition) *guildDo { + return g.withDO(g.DO.Having(conds...)) +} + +func (g guildDo) Limit(limit int) *guildDo { + return g.withDO(g.DO.Limit(limit)) +} + +func (g guildDo) Offset(offset int) *guildDo { + return g.withDO(g.DO.Offset(offset)) +} + +func (g guildDo) Scopes(funcs ...func(gen.Dao) gen.Dao) *guildDo { + return g.withDO(g.DO.Scopes(funcs...)) +} + +func (g guildDo) Unscoped() *guildDo { + return g.withDO(g.DO.Unscoped()) +} + +func (g guildDo) Create(values ...*model.Guild) error { + if len(values) == 0 { + return nil + } + return g.DO.Create(values) +} + +func (g guildDo) CreateInBatches(values []*model.Guild, batchSize int) error { + return g.DO.CreateInBatches(values, batchSize) +} + +// Save : !!! underlying implementation is different with GORM +// The method is equivalent to executing the statement: db.Clauses(clause.OnConflict{UpdateAll: true}).Create(values) +func (g guildDo) Save(values ...*model.Guild) error { + if len(values) == 0 { + return nil + } + return g.DO.Save(values) +} + +func (g guildDo) First() (*model.Guild, error) { + if result, err := g.DO.First(); err != nil { + return nil, err + } else { + return result.(*model.Guild), nil + } +} + +func (g guildDo) Take() (*model.Guild, error) { + if result, err := g.DO.Take(); err != nil { + return nil, err + } else { + return result.(*model.Guild), nil + } +} + +func (g guildDo) Last() (*model.Guild, error) { + if result, err := g.DO.Last(); err != nil { + return nil, err + } else { + return result.(*model.Guild), nil + } +} + +func (g guildDo) Find() ([]*model.Guild, error) { + result, err := g.DO.Find() + return result.([]*model.Guild), err +} + +func (g guildDo) FindInBatch(batchSize int, fc func(tx gen.Dao, batch int) error) (results []*model.Guild, err error) { + buf := make([]*model.Guild, 0, batchSize) + err = g.DO.FindInBatches(&buf, batchSize, func(tx gen.Dao, batch int) error { + defer func() { results = append(results, buf...) }() + return fc(tx, batch) + }) + return results, err +} + +func (g guildDo) FindInBatches(result *[]*model.Guild, batchSize int, fc func(tx gen.Dao, batch int) error) error { + return g.DO.FindInBatches(result, batchSize, fc) +} + +func (g guildDo) Attrs(attrs ...field.AssignExpr) *guildDo { + return g.withDO(g.DO.Attrs(attrs...)) +} + +func (g guildDo) Assign(attrs ...field.AssignExpr) *guildDo { + return g.withDO(g.DO.Assign(attrs...)) +} + +func (g guildDo) Joins(fields ...field.RelationField) *guildDo { + for _, _f := range fields { + g = *g.withDO(g.DO.Joins(_f)) + } + return &g +} + +func (g guildDo) Preload(fields ...field.RelationField) *guildDo { + for _, _f := range fields { + g = *g.withDO(g.DO.Preload(_f)) + } + return &g +} + +func (g guildDo) FirstOrInit() (*model.Guild, error) { + if result, err := g.DO.FirstOrInit(); err != nil { + return nil, err + } else { + return result.(*model.Guild), nil + } +} + +func (g guildDo) FirstOrCreate() (*model.Guild, error) { + if result, err := g.DO.FirstOrCreate(); err != nil { + return nil, err + } else { + return result.(*model.Guild), nil + } +} + +func (g guildDo) FindByPage(offset int, limit int) (result []*model.Guild, count int64, err error) { + result, err = g.Offset(offset).Limit(limit).Find() + if err != nil { + return + } + + if size := len(result); 0 < limit && 0 < size && size < limit { + count = int64(size + offset) + return + } + + count, err = g.Offset(-1).Limit(-1).Count() + return +} + +func (g guildDo) ScanByPage(result interface{}, offset int, limit int) (count int64, err error) { + count, err = g.Count() + if err != nil { + return + } + + err = g.Offset(offset).Limit(limit).Scan(result) + return +} + +func (g guildDo) Scan(result interface{}) (err error) { + return g.DO.Scan(result) +} + +func (g guildDo) Delete(models ...*model.Guild) (result gen.ResultInfo, err error) { + return g.DO.Delete(models) +} + +func (g *guildDo) withDO(do gen.Dao) *guildDo { + g.DO = *do.(*gen.DO) + return g +} diff --git a/internal/repository/mysql/dao/guild_boxes.gen.go b/internal/repository/mysql/dao/guild_boxes.gen.go new file mode 100644 index 0000000..513fbd6 --- /dev/null +++ b/internal/repository/mysql/dao/guild_boxes.gen.go @@ -0,0 +1,340 @@ +// Code generated by gorm.io/gen. DO NOT EDIT. +// Code generated by gorm.io/gen. DO NOT EDIT. +// Code generated by gorm.io/gen. DO NOT EDIT. + +package dao + +import ( + "context" + + "gorm.io/gorm" + "gorm.io/gorm/clause" + "gorm.io/gorm/schema" + + "gorm.io/gen" + "gorm.io/gen/field" + + "gorm.io/plugin/dbresolver" + + "bindbox-game/internal/repository/mysql/model" +) + +func newGuildBoxes(db *gorm.DB, opts ...gen.DOOption) guildBoxes { + _guildBoxes := guildBoxes{} + + _guildBoxes.guildBoxesDo.UseDB(db, opts...) + _guildBoxes.guildBoxesDo.UseModel(&model.GuildBoxes{}) + + tableName := _guildBoxes.guildBoxesDo.TableName() + _guildBoxes.ALL = field.NewAsterisk(tableName) + _guildBoxes.ID = field.NewInt64(tableName, "id") + _guildBoxes.CreatedAt = field.NewTime(tableName, "created_at") + _guildBoxes.GuildID = field.NewInt64(tableName, "guild_id") + _guildBoxes.KindID = field.NewInt64(tableName, "kind_id") + _guildBoxes.Value = field.NewInt64(tableName, "value") + _guildBoxes.KindType = field.NewInt32(tableName, "kind_type") + + _guildBoxes.fillFieldMap() + + return _guildBoxes +} + +// guildBoxes 公会盲盒玩法聚合 +type guildBoxes struct { + guildBoxesDo + + ALL field.Asterisk + ID field.Int64 // 主键ID + CreatedAt field.Time // 创建时间 + GuildID field.Int64 // 公会ID(guild_main.id) + KindID field.Int64 // 奖品id( 如果是 积分可以 空; 商品ID 道具卡ID) + Value field.Int64 // 累计价值/积分等(业务自定义-可以为空) + KindType field.Int32 // 奖品类型: 0 积分 1 优惠券 2 道具卡 + + fieldMap map[string]field.Expr +} + +func (g guildBoxes) Table(newTableName string) *guildBoxes { + g.guildBoxesDo.UseTable(newTableName) + return g.updateTableName(newTableName) +} + +func (g guildBoxes) As(alias string) *guildBoxes { + g.guildBoxesDo.DO = *(g.guildBoxesDo.As(alias).(*gen.DO)) + return g.updateTableName(alias) +} + +func (g *guildBoxes) updateTableName(table string) *guildBoxes { + g.ALL = field.NewAsterisk(table) + g.ID = field.NewInt64(table, "id") + g.CreatedAt = field.NewTime(table, "created_at") + g.GuildID = field.NewInt64(table, "guild_id") + g.KindID = field.NewInt64(table, "kind_id") + g.Value = field.NewInt64(table, "value") + g.KindType = field.NewInt32(table, "kind_type") + + g.fillFieldMap() + + return g +} + +func (g *guildBoxes) GetFieldByName(fieldName string) (field.OrderExpr, bool) { + _f, ok := g.fieldMap[fieldName] + if !ok || _f == nil { + return nil, false + } + _oe, ok := _f.(field.OrderExpr) + return _oe, ok +} + +func (g *guildBoxes) fillFieldMap() { + g.fieldMap = make(map[string]field.Expr, 6) + g.fieldMap["id"] = g.ID + g.fieldMap["created_at"] = g.CreatedAt + g.fieldMap["guild_id"] = g.GuildID + g.fieldMap["kind_id"] = g.KindID + g.fieldMap["value"] = g.Value + g.fieldMap["kind_type"] = g.KindType +} + +func (g guildBoxes) clone(db *gorm.DB) guildBoxes { + g.guildBoxesDo.ReplaceConnPool(db.Statement.ConnPool) + return g +} + +func (g guildBoxes) replaceDB(db *gorm.DB) guildBoxes { + g.guildBoxesDo.ReplaceDB(db) + return g +} + +type guildBoxesDo struct{ gen.DO } + +func (g guildBoxesDo) Debug() *guildBoxesDo { + return g.withDO(g.DO.Debug()) +} + +func (g guildBoxesDo) WithContext(ctx context.Context) *guildBoxesDo { + return g.withDO(g.DO.WithContext(ctx)) +} + +func (g guildBoxesDo) ReadDB() *guildBoxesDo { + return g.Clauses(dbresolver.Read) +} + +func (g guildBoxesDo) WriteDB() *guildBoxesDo { + return g.Clauses(dbresolver.Write) +} + +func (g guildBoxesDo) Session(config *gorm.Session) *guildBoxesDo { + return g.withDO(g.DO.Session(config)) +} + +func (g guildBoxesDo) Clauses(conds ...clause.Expression) *guildBoxesDo { + return g.withDO(g.DO.Clauses(conds...)) +} + +func (g guildBoxesDo) Returning(value interface{}, columns ...string) *guildBoxesDo { + return g.withDO(g.DO.Returning(value, columns...)) +} + +func (g guildBoxesDo) Not(conds ...gen.Condition) *guildBoxesDo { + return g.withDO(g.DO.Not(conds...)) +} + +func (g guildBoxesDo) Or(conds ...gen.Condition) *guildBoxesDo { + return g.withDO(g.DO.Or(conds...)) +} + +func (g guildBoxesDo) Select(conds ...field.Expr) *guildBoxesDo { + return g.withDO(g.DO.Select(conds...)) +} + +func (g guildBoxesDo) Where(conds ...gen.Condition) *guildBoxesDo { + return g.withDO(g.DO.Where(conds...)) +} + +func (g guildBoxesDo) Order(conds ...field.Expr) *guildBoxesDo { + return g.withDO(g.DO.Order(conds...)) +} + +func (g guildBoxesDo) Distinct(cols ...field.Expr) *guildBoxesDo { + return g.withDO(g.DO.Distinct(cols...)) +} + +func (g guildBoxesDo) Omit(cols ...field.Expr) *guildBoxesDo { + return g.withDO(g.DO.Omit(cols...)) +} + +func (g guildBoxesDo) Join(table schema.Tabler, on ...field.Expr) *guildBoxesDo { + return g.withDO(g.DO.Join(table, on...)) +} + +func (g guildBoxesDo) LeftJoin(table schema.Tabler, on ...field.Expr) *guildBoxesDo { + return g.withDO(g.DO.LeftJoin(table, on...)) +} + +func (g guildBoxesDo) RightJoin(table schema.Tabler, on ...field.Expr) *guildBoxesDo { + return g.withDO(g.DO.RightJoin(table, on...)) +} + +func (g guildBoxesDo) Group(cols ...field.Expr) *guildBoxesDo { + return g.withDO(g.DO.Group(cols...)) +} + +func (g guildBoxesDo) Having(conds ...gen.Condition) *guildBoxesDo { + return g.withDO(g.DO.Having(conds...)) +} + +func (g guildBoxesDo) Limit(limit int) *guildBoxesDo { + return g.withDO(g.DO.Limit(limit)) +} + +func (g guildBoxesDo) Offset(offset int) *guildBoxesDo { + return g.withDO(g.DO.Offset(offset)) +} + +func (g guildBoxesDo) Scopes(funcs ...func(gen.Dao) gen.Dao) *guildBoxesDo { + return g.withDO(g.DO.Scopes(funcs...)) +} + +func (g guildBoxesDo) Unscoped() *guildBoxesDo { + return g.withDO(g.DO.Unscoped()) +} + +func (g guildBoxesDo) Create(values ...*model.GuildBoxes) error { + if len(values) == 0 { + return nil + } + return g.DO.Create(values) +} + +func (g guildBoxesDo) CreateInBatches(values []*model.GuildBoxes, batchSize int) error { + return g.DO.CreateInBatches(values, batchSize) +} + +// Save : !!! underlying implementation is different with GORM +// The method is equivalent to executing the statement: db.Clauses(clause.OnConflict{UpdateAll: true}).Create(values) +func (g guildBoxesDo) Save(values ...*model.GuildBoxes) error { + if len(values) == 0 { + return nil + } + return g.DO.Save(values) +} + +func (g guildBoxesDo) First() (*model.GuildBoxes, error) { + if result, err := g.DO.First(); err != nil { + return nil, err + } else { + return result.(*model.GuildBoxes), nil + } +} + +func (g guildBoxesDo) Take() (*model.GuildBoxes, error) { + if result, err := g.DO.Take(); err != nil { + return nil, err + } else { + return result.(*model.GuildBoxes), nil + } +} + +func (g guildBoxesDo) Last() (*model.GuildBoxes, error) { + if result, err := g.DO.Last(); err != nil { + return nil, err + } else { + return result.(*model.GuildBoxes), nil + } +} + +func (g guildBoxesDo) Find() ([]*model.GuildBoxes, error) { + result, err := g.DO.Find() + return result.([]*model.GuildBoxes), err +} + +func (g guildBoxesDo) FindInBatch(batchSize int, fc func(tx gen.Dao, batch int) error) (results []*model.GuildBoxes, err error) { + buf := make([]*model.GuildBoxes, 0, batchSize) + err = g.DO.FindInBatches(&buf, batchSize, func(tx gen.Dao, batch int) error { + defer func() { results = append(results, buf...) }() + return fc(tx, batch) + }) + return results, err +} + +func (g guildBoxesDo) FindInBatches(result *[]*model.GuildBoxes, batchSize int, fc func(tx gen.Dao, batch int) error) error { + return g.DO.FindInBatches(result, batchSize, fc) +} + +func (g guildBoxesDo) Attrs(attrs ...field.AssignExpr) *guildBoxesDo { + return g.withDO(g.DO.Attrs(attrs...)) +} + +func (g guildBoxesDo) Assign(attrs ...field.AssignExpr) *guildBoxesDo { + return g.withDO(g.DO.Assign(attrs...)) +} + +func (g guildBoxesDo) Joins(fields ...field.RelationField) *guildBoxesDo { + for _, _f := range fields { + g = *g.withDO(g.DO.Joins(_f)) + } + return &g +} + +func (g guildBoxesDo) Preload(fields ...field.RelationField) *guildBoxesDo { + for _, _f := range fields { + g = *g.withDO(g.DO.Preload(_f)) + } + return &g +} + +func (g guildBoxesDo) FirstOrInit() (*model.GuildBoxes, error) { + if result, err := g.DO.FirstOrInit(); err != nil { + return nil, err + } else { + return result.(*model.GuildBoxes), nil + } +} + +func (g guildBoxesDo) FirstOrCreate() (*model.GuildBoxes, error) { + if result, err := g.DO.FirstOrCreate(); err != nil { + return nil, err + } else { + return result.(*model.GuildBoxes), nil + } +} + +func (g guildBoxesDo) FindByPage(offset int, limit int) (result []*model.GuildBoxes, count int64, err error) { + result, err = g.Offset(offset).Limit(limit).Find() + if err != nil { + return + } + + if size := len(result); 0 < limit && 0 < size && size < limit { + count = int64(size + offset) + return + } + + count, err = g.Offset(-1).Limit(-1).Count() + return +} + +func (g guildBoxesDo) ScanByPage(result interface{}, offset int, limit int) (count int64, err error) { + count, err = g.Count() + if err != nil { + return + } + + err = g.Offset(offset).Limit(limit).Scan(result) + return +} + +func (g guildBoxesDo) Scan(result interface{}) (err error) { + return g.DO.Scan(result) +} + +func (g guildBoxesDo) Delete(models ...*model.GuildBoxes) (result gen.ResultInfo, err error) { + return g.DO.Delete(models) +} + +func (g *guildBoxesDo) withDO(do gen.Dao) *guildBoxesDo { + g.DO = *do.(*gen.DO) + return g +} diff --git a/internal/repository/mysql/dao/guild_contribute_logs.gen.go b/internal/repository/mysql/dao/guild_contribute_logs.gen.go new file mode 100644 index 0000000..4127d60 --- /dev/null +++ b/internal/repository/mysql/dao/guild_contribute_logs.gen.go @@ -0,0 +1,352 @@ +// Code generated by gorm.io/gen. DO NOT EDIT. +// Code generated by gorm.io/gen. DO NOT EDIT. +// Code generated by gorm.io/gen. DO NOT EDIT. + +package dao + +import ( + "context" + + "gorm.io/gorm" + "gorm.io/gorm/clause" + "gorm.io/gorm/schema" + + "gorm.io/gen" + "gorm.io/gen/field" + + "gorm.io/plugin/dbresolver" + + "bindbox-game/internal/repository/mysql/model" +) + +func newGuildContributeLogs(db *gorm.DB, opts ...gen.DOOption) guildContributeLogs { + _guildContributeLogs := guildContributeLogs{} + + _guildContributeLogs.guildContributeLogsDo.UseDB(db, opts...) + _guildContributeLogs.guildContributeLogsDo.UseModel(&model.GuildContributeLogs{}) + + tableName := _guildContributeLogs.guildContributeLogsDo.TableName() + _guildContributeLogs.ALL = field.NewAsterisk(tableName) + _guildContributeLogs.ID = field.NewInt64(tableName, "id") + _guildContributeLogs.CreatedAt = field.NewTime(tableName, "created_at") + _guildContributeLogs.GuildID = field.NewInt64(tableName, "guild_id") + _guildContributeLogs.UserID = field.NewInt64(tableName, "user_id") + _guildContributeLogs.ActivityID = field.NewInt64(tableName, "activity_id") + _guildContributeLogs.IssuesID = field.NewInt64(tableName, "issues_id") + _guildContributeLogs.Action = field.NewString(tableName, "action") + _guildContributeLogs.Value = field.NewInt64(tableName, "value") + _guildContributeLogs.ProductID = field.NewInt32(tableName, "product_id") + + _guildContributeLogs.fillFieldMap() + + return _guildContributeLogs +} + +// guildContributeLogs 公会贡献流水 +type guildContributeLogs struct { + guildContributeLogsDo + + ALL field.Asterisk + ID field.Int64 // 主键ID + CreatedAt field.Time // 创建时间 + GuildID field.Int64 // 公会ID(guild_main.id) + UserID field.Int64 // 用户ID(user_members.id) + ActivityID field.Int64 // 活动ID(可空) + IssuesID field.Int64 // 活动期ID(可空) + Action field.String // 贡献动作(抽奖/购买/分享等) + Value field.Int64 // 贡献值(业务自定义) + ProductID field.Int32 // 奖品ID (可空) + + fieldMap map[string]field.Expr +} + +func (g guildContributeLogs) Table(newTableName string) *guildContributeLogs { + g.guildContributeLogsDo.UseTable(newTableName) + return g.updateTableName(newTableName) +} + +func (g guildContributeLogs) As(alias string) *guildContributeLogs { + g.guildContributeLogsDo.DO = *(g.guildContributeLogsDo.As(alias).(*gen.DO)) + return g.updateTableName(alias) +} + +func (g *guildContributeLogs) updateTableName(table string) *guildContributeLogs { + g.ALL = field.NewAsterisk(table) + g.ID = field.NewInt64(table, "id") + g.CreatedAt = field.NewTime(table, "created_at") + g.GuildID = field.NewInt64(table, "guild_id") + g.UserID = field.NewInt64(table, "user_id") + g.ActivityID = field.NewInt64(table, "activity_id") + g.IssuesID = field.NewInt64(table, "issues_id") + g.Action = field.NewString(table, "action") + g.Value = field.NewInt64(table, "value") + g.ProductID = field.NewInt32(table, "product_id") + + g.fillFieldMap() + + return g +} + +func (g *guildContributeLogs) GetFieldByName(fieldName string) (field.OrderExpr, bool) { + _f, ok := g.fieldMap[fieldName] + if !ok || _f == nil { + return nil, false + } + _oe, ok := _f.(field.OrderExpr) + return _oe, ok +} + +func (g *guildContributeLogs) fillFieldMap() { + g.fieldMap = make(map[string]field.Expr, 9) + g.fieldMap["id"] = g.ID + g.fieldMap["created_at"] = g.CreatedAt + g.fieldMap["guild_id"] = g.GuildID + g.fieldMap["user_id"] = g.UserID + g.fieldMap["activity_id"] = g.ActivityID + g.fieldMap["issues_id"] = g.IssuesID + g.fieldMap["action"] = g.Action + g.fieldMap["value"] = g.Value + g.fieldMap["product_id"] = g.ProductID +} + +func (g guildContributeLogs) clone(db *gorm.DB) guildContributeLogs { + g.guildContributeLogsDo.ReplaceConnPool(db.Statement.ConnPool) + return g +} + +func (g guildContributeLogs) replaceDB(db *gorm.DB) guildContributeLogs { + g.guildContributeLogsDo.ReplaceDB(db) + return g +} + +type guildContributeLogsDo struct{ gen.DO } + +func (g guildContributeLogsDo) Debug() *guildContributeLogsDo { + return g.withDO(g.DO.Debug()) +} + +func (g guildContributeLogsDo) WithContext(ctx context.Context) *guildContributeLogsDo { + return g.withDO(g.DO.WithContext(ctx)) +} + +func (g guildContributeLogsDo) ReadDB() *guildContributeLogsDo { + return g.Clauses(dbresolver.Read) +} + +func (g guildContributeLogsDo) WriteDB() *guildContributeLogsDo { + return g.Clauses(dbresolver.Write) +} + +func (g guildContributeLogsDo) Session(config *gorm.Session) *guildContributeLogsDo { + return g.withDO(g.DO.Session(config)) +} + +func (g guildContributeLogsDo) Clauses(conds ...clause.Expression) *guildContributeLogsDo { + return g.withDO(g.DO.Clauses(conds...)) +} + +func (g guildContributeLogsDo) Returning(value interface{}, columns ...string) *guildContributeLogsDo { + return g.withDO(g.DO.Returning(value, columns...)) +} + +func (g guildContributeLogsDo) Not(conds ...gen.Condition) *guildContributeLogsDo { + return g.withDO(g.DO.Not(conds...)) +} + +func (g guildContributeLogsDo) Or(conds ...gen.Condition) *guildContributeLogsDo { + return g.withDO(g.DO.Or(conds...)) +} + +func (g guildContributeLogsDo) Select(conds ...field.Expr) *guildContributeLogsDo { + return g.withDO(g.DO.Select(conds...)) +} + +func (g guildContributeLogsDo) Where(conds ...gen.Condition) *guildContributeLogsDo { + return g.withDO(g.DO.Where(conds...)) +} + +func (g guildContributeLogsDo) Order(conds ...field.Expr) *guildContributeLogsDo { + return g.withDO(g.DO.Order(conds...)) +} + +func (g guildContributeLogsDo) Distinct(cols ...field.Expr) *guildContributeLogsDo { + return g.withDO(g.DO.Distinct(cols...)) +} + +func (g guildContributeLogsDo) Omit(cols ...field.Expr) *guildContributeLogsDo { + return g.withDO(g.DO.Omit(cols...)) +} + +func (g guildContributeLogsDo) Join(table schema.Tabler, on ...field.Expr) *guildContributeLogsDo { + return g.withDO(g.DO.Join(table, on...)) +} + +func (g guildContributeLogsDo) LeftJoin(table schema.Tabler, on ...field.Expr) *guildContributeLogsDo { + return g.withDO(g.DO.LeftJoin(table, on...)) +} + +func (g guildContributeLogsDo) RightJoin(table schema.Tabler, on ...field.Expr) *guildContributeLogsDo { + return g.withDO(g.DO.RightJoin(table, on...)) +} + +func (g guildContributeLogsDo) Group(cols ...field.Expr) *guildContributeLogsDo { + return g.withDO(g.DO.Group(cols...)) +} + +func (g guildContributeLogsDo) Having(conds ...gen.Condition) *guildContributeLogsDo { + return g.withDO(g.DO.Having(conds...)) +} + +func (g guildContributeLogsDo) Limit(limit int) *guildContributeLogsDo { + return g.withDO(g.DO.Limit(limit)) +} + +func (g guildContributeLogsDo) Offset(offset int) *guildContributeLogsDo { + return g.withDO(g.DO.Offset(offset)) +} + +func (g guildContributeLogsDo) Scopes(funcs ...func(gen.Dao) gen.Dao) *guildContributeLogsDo { + return g.withDO(g.DO.Scopes(funcs...)) +} + +func (g guildContributeLogsDo) Unscoped() *guildContributeLogsDo { + return g.withDO(g.DO.Unscoped()) +} + +func (g guildContributeLogsDo) Create(values ...*model.GuildContributeLogs) error { + if len(values) == 0 { + return nil + } + return g.DO.Create(values) +} + +func (g guildContributeLogsDo) CreateInBatches(values []*model.GuildContributeLogs, batchSize int) error { + return g.DO.CreateInBatches(values, batchSize) +} + +// Save : !!! underlying implementation is different with GORM +// The method is equivalent to executing the statement: db.Clauses(clause.OnConflict{UpdateAll: true}).Create(values) +func (g guildContributeLogsDo) Save(values ...*model.GuildContributeLogs) error { + if len(values) == 0 { + return nil + } + return g.DO.Save(values) +} + +func (g guildContributeLogsDo) First() (*model.GuildContributeLogs, error) { + if result, err := g.DO.First(); err != nil { + return nil, err + } else { + return result.(*model.GuildContributeLogs), nil + } +} + +func (g guildContributeLogsDo) Take() (*model.GuildContributeLogs, error) { + if result, err := g.DO.Take(); err != nil { + return nil, err + } else { + return result.(*model.GuildContributeLogs), nil + } +} + +func (g guildContributeLogsDo) Last() (*model.GuildContributeLogs, error) { + if result, err := g.DO.Last(); err != nil { + return nil, err + } else { + return result.(*model.GuildContributeLogs), nil + } +} + +func (g guildContributeLogsDo) Find() ([]*model.GuildContributeLogs, error) { + result, err := g.DO.Find() + return result.([]*model.GuildContributeLogs), err +} + +func (g guildContributeLogsDo) FindInBatch(batchSize int, fc func(tx gen.Dao, batch int) error) (results []*model.GuildContributeLogs, err error) { + buf := make([]*model.GuildContributeLogs, 0, batchSize) + err = g.DO.FindInBatches(&buf, batchSize, func(tx gen.Dao, batch int) error { + defer func() { results = append(results, buf...) }() + return fc(tx, batch) + }) + return results, err +} + +func (g guildContributeLogsDo) FindInBatches(result *[]*model.GuildContributeLogs, batchSize int, fc func(tx gen.Dao, batch int) error) error { + return g.DO.FindInBatches(result, batchSize, fc) +} + +func (g guildContributeLogsDo) Attrs(attrs ...field.AssignExpr) *guildContributeLogsDo { + return g.withDO(g.DO.Attrs(attrs...)) +} + +func (g guildContributeLogsDo) Assign(attrs ...field.AssignExpr) *guildContributeLogsDo { + return g.withDO(g.DO.Assign(attrs...)) +} + +func (g guildContributeLogsDo) Joins(fields ...field.RelationField) *guildContributeLogsDo { + for _, _f := range fields { + g = *g.withDO(g.DO.Joins(_f)) + } + return &g +} + +func (g guildContributeLogsDo) Preload(fields ...field.RelationField) *guildContributeLogsDo { + for _, _f := range fields { + g = *g.withDO(g.DO.Preload(_f)) + } + return &g +} + +func (g guildContributeLogsDo) FirstOrInit() (*model.GuildContributeLogs, error) { + if result, err := g.DO.FirstOrInit(); err != nil { + return nil, err + } else { + return result.(*model.GuildContributeLogs), nil + } +} + +func (g guildContributeLogsDo) FirstOrCreate() (*model.GuildContributeLogs, error) { + if result, err := g.DO.FirstOrCreate(); err != nil { + return nil, err + } else { + return result.(*model.GuildContributeLogs), nil + } +} + +func (g guildContributeLogsDo) FindByPage(offset int, limit int) (result []*model.GuildContributeLogs, count int64, err error) { + result, err = g.Offset(offset).Limit(limit).Find() + if err != nil { + return + } + + if size := len(result); 0 < limit && 0 < size && size < limit { + count = int64(size + offset) + return + } + + count, err = g.Offset(-1).Limit(-1).Count() + return +} + +func (g guildContributeLogsDo) ScanByPage(result interface{}, offset int, limit int) (count int64, err error) { + count, err = g.Count() + if err != nil { + return + } + + err = g.Offset(offset).Limit(limit).Scan(result) + return +} + +func (g guildContributeLogsDo) Scan(result interface{}) (err error) { + return g.DO.Scan(result) +} + +func (g guildContributeLogsDo) Delete(models ...*model.GuildContributeLogs) (result gen.ResultInfo, err error) { + return g.DO.Delete(models) +} + +func (g *guildContributeLogsDo) withDO(do gen.Dao) *guildContributeLogsDo { + g.DO = *do.(*gen.DO) + return g +} diff --git a/internal/repository/mysql/dao/guild_members.gen.go b/internal/repository/mysql/dao/guild_members.gen.go new file mode 100644 index 0000000..064b42d --- /dev/null +++ b/internal/repository/mysql/dao/guild_members.gen.go @@ -0,0 +1,348 @@ +// Code generated by gorm.io/gen. DO NOT EDIT. +// Code generated by gorm.io/gen. DO NOT EDIT. +// Code generated by gorm.io/gen. DO NOT EDIT. + +package dao + +import ( + "context" + + "gorm.io/gorm" + "gorm.io/gorm/clause" + "gorm.io/gorm/schema" + + "gorm.io/gen" + "gorm.io/gen/field" + + "gorm.io/plugin/dbresolver" + + "bindbox-game/internal/repository/mysql/model" +) + +func newGuildMembers(db *gorm.DB, opts ...gen.DOOption) guildMembers { + _guildMembers := guildMembers{} + + _guildMembers.guildMembersDo.UseDB(db, opts...) + _guildMembers.guildMembersDo.UseModel(&model.GuildMembers{}) + + tableName := _guildMembers.guildMembersDo.TableName() + _guildMembers.ALL = field.NewAsterisk(tableName) + _guildMembers.ID = field.NewInt64(tableName, "id") + _guildMembers.CreatedAt = field.NewTime(tableName, "created_at") + _guildMembers.GuildID = field.NewInt64(tableName, "guild_id") + _guildMembers.UserID = field.NewInt64(tableName, "user_id") + _guildMembers.Role = field.NewString(tableName, "role") + _guildMembers.StartTime = field.NewTime(tableName, "start_time") + _guildMembers.Status = field.NewInt32(tableName, "status") + _guildMembers.JoinStatus = field.NewInt32(tableName, "join_status") + + _guildMembers.fillFieldMap() + + return _guildMembers +} + +// guildMembers 公会成员 +type guildMembers struct { + guildMembersDo + + ALL field.Asterisk + ID field.Int64 // 主键ID + CreatedAt field.Time // 创建时间 + GuildID field.Int64 // 公会ID(guild_main.id) + UserID field.Int64 // 成员用户ID(user_members.id) + Role field.String // 角色:owner/admin/member + StartTime field.Time // 加入时间 + Status field.Int32 // 状态:1正常 2退出 + JoinStatus field.Int32 // 状态:1 拒绝 2 同意 + + fieldMap map[string]field.Expr +} + +func (g guildMembers) Table(newTableName string) *guildMembers { + g.guildMembersDo.UseTable(newTableName) + return g.updateTableName(newTableName) +} + +func (g guildMembers) As(alias string) *guildMembers { + g.guildMembersDo.DO = *(g.guildMembersDo.As(alias).(*gen.DO)) + return g.updateTableName(alias) +} + +func (g *guildMembers) updateTableName(table string) *guildMembers { + g.ALL = field.NewAsterisk(table) + g.ID = field.NewInt64(table, "id") + g.CreatedAt = field.NewTime(table, "created_at") + g.GuildID = field.NewInt64(table, "guild_id") + g.UserID = field.NewInt64(table, "user_id") + g.Role = field.NewString(table, "role") + g.StartTime = field.NewTime(table, "start_time") + g.Status = field.NewInt32(table, "status") + g.JoinStatus = field.NewInt32(table, "join_status") + + g.fillFieldMap() + + return g +} + +func (g *guildMembers) GetFieldByName(fieldName string) (field.OrderExpr, bool) { + _f, ok := g.fieldMap[fieldName] + if !ok || _f == nil { + return nil, false + } + _oe, ok := _f.(field.OrderExpr) + return _oe, ok +} + +func (g *guildMembers) fillFieldMap() { + g.fieldMap = make(map[string]field.Expr, 8) + g.fieldMap["id"] = g.ID + g.fieldMap["created_at"] = g.CreatedAt + g.fieldMap["guild_id"] = g.GuildID + g.fieldMap["user_id"] = g.UserID + g.fieldMap["role"] = g.Role + g.fieldMap["start_time"] = g.StartTime + g.fieldMap["status"] = g.Status + g.fieldMap["join_status"] = g.JoinStatus +} + +func (g guildMembers) clone(db *gorm.DB) guildMembers { + g.guildMembersDo.ReplaceConnPool(db.Statement.ConnPool) + return g +} + +func (g guildMembers) replaceDB(db *gorm.DB) guildMembers { + g.guildMembersDo.ReplaceDB(db) + return g +} + +type guildMembersDo struct{ gen.DO } + +func (g guildMembersDo) Debug() *guildMembersDo { + return g.withDO(g.DO.Debug()) +} + +func (g guildMembersDo) WithContext(ctx context.Context) *guildMembersDo { + return g.withDO(g.DO.WithContext(ctx)) +} + +func (g guildMembersDo) ReadDB() *guildMembersDo { + return g.Clauses(dbresolver.Read) +} + +func (g guildMembersDo) WriteDB() *guildMembersDo { + return g.Clauses(dbresolver.Write) +} + +func (g guildMembersDo) Session(config *gorm.Session) *guildMembersDo { + return g.withDO(g.DO.Session(config)) +} + +func (g guildMembersDo) Clauses(conds ...clause.Expression) *guildMembersDo { + return g.withDO(g.DO.Clauses(conds...)) +} + +func (g guildMembersDo) Returning(value interface{}, columns ...string) *guildMembersDo { + return g.withDO(g.DO.Returning(value, columns...)) +} + +func (g guildMembersDo) Not(conds ...gen.Condition) *guildMembersDo { + return g.withDO(g.DO.Not(conds...)) +} + +func (g guildMembersDo) Or(conds ...gen.Condition) *guildMembersDo { + return g.withDO(g.DO.Or(conds...)) +} + +func (g guildMembersDo) Select(conds ...field.Expr) *guildMembersDo { + return g.withDO(g.DO.Select(conds...)) +} + +func (g guildMembersDo) Where(conds ...gen.Condition) *guildMembersDo { + return g.withDO(g.DO.Where(conds...)) +} + +func (g guildMembersDo) Order(conds ...field.Expr) *guildMembersDo { + return g.withDO(g.DO.Order(conds...)) +} + +func (g guildMembersDo) Distinct(cols ...field.Expr) *guildMembersDo { + return g.withDO(g.DO.Distinct(cols...)) +} + +func (g guildMembersDo) Omit(cols ...field.Expr) *guildMembersDo { + return g.withDO(g.DO.Omit(cols...)) +} + +func (g guildMembersDo) Join(table schema.Tabler, on ...field.Expr) *guildMembersDo { + return g.withDO(g.DO.Join(table, on...)) +} + +func (g guildMembersDo) LeftJoin(table schema.Tabler, on ...field.Expr) *guildMembersDo { + return g.withDO(g.DO.LeftJoin(table, on...)) +} + +func (g guildMembersDo) RightJoin(table schema.Tabler, on ...field.Expr) *guildMembersDo { + return g.withDO(g.DO.RightJoin(table, on...)) +} + +func (g guildMembersDo) Group(cols ...field.Expr) *guildMembersDo { + return g.withDO(g.DO.Group(cols...)) +} + +func (g guildMembersDo) Having(conds ...gen.Condition) *guildMembersDo { + return g.withDO(g.DO.Having(conds...)) +} + +func (g guildMembersDo) Limit(limit int) *guildMembersDo { + return g.withDO(g.DO.Limit(limit)) +} + +func (g guildMembersDo) Offset(offset int) *guildMembersDo { + return g.withDO(g.DO.Offset(offset)) +} + +func (g guildMembersDo) Scopes(funcs ...func(gen.Dao) gen.Dao) *guildMembersDo { + return g.withDO(g.DO.Scopes(funcs...)) +} + +func (g guildMembersDo) Unscoped() *guildMembersDo { + return g.withDO(g.DO.Unscoped()) +} + +func (g guildMembersDo) Create(values ...*model.GuildMembers) error { + if len(values) == 0 { + return nil + } + return g.DO.Create(values) +} + +func (g guildMembersDo) CreateInBatches(values []*model.GuildMembers, batchSize int) error { + return g.DO.CreateInBatches(values, batchSize) +} + +// Save : !!! underlying implementation is different with GORM +// The method is equivalent to executing the statement: db.Clauses(clause.OnConflict{UpdateAll: true}).Create(values) +func (g guildMembersDo) Save(values ...*model.GuildMembers) error { + if len(values) == 0 { + return nil + } + return g.DO.Save(values) +} + +func (g guildMembersDo) First() (*model.GuildMembers, error) { + if result, err := g.DO.First(); err != nil { + return nil, err + } else { + return result.(*model.GuildMembers), nil + } +} + +func (g guildMembersDo) Take() (*model.GuildMembers, error) { + if result, err := g.DO.Take(); err != nil { + return nil, err + } else { + return result.(*model.GuildMembers), nil + } +} + +func (g guildMembersDo) Last() (*model.GuildMembers, error) { + if result, err := g.DO.Last(); err != nil { + return nil, err + } else { + return result.(*model.GuildMembers), nil + } +} + +func (g guildMembersDo) Find() ([]*model.GuildMembers, error) { + result, err := g.DO.Find() + return result.([]*model.GuildMembers), err +} + +func (g guildMembersDo) FindInBatch(batchSize int, fc func(tx gen.Dao, batch int) error) (results []*model.GuildMembers, err error) { + buf := make([]*model.GuildMembers, 0, batchSize) + err = g.DO.FindInBatches(&buf, batchSize, func(tx gen.Dao, batch int) error { + defer func() { results = append(results, buf...) }() + return fc(tx, batch) + }) + return results, err +} + +func (g guildMembersDo) FindInBatches(result *[]*model.GuildMembers, batchSize int, fc func(tx gen.Dao, batch int) error) error { + return g.DO.FindInBatches(result, batchSize, fc) +} + +func (g guildMembersDo) Attrs(attrs ...field.AssignExpr) *guildMembersDo { + return g.withDO(g.DO.Attrs(attrs...)) +} + +func (g guildMembersDo) Assign(attrs ...field.AssignExpr) *guildMembersDo { + return g.withDO(g.DO.Assign(attrs...)) +} + +func (g guildMembersDo) Joins(fields ...field.RelationField) *guildMembersDo { + for _, _f := range fields { + g = *g.withDO(g.DO.Joins(_f)) + } + return &g +} + +func (g guildMembersDo) Preload(fields ...field.RelationField) *guildMembersDo { + for _, _f := range fields { + g = *g.withDO(g.DO.Preload(_f)) + } + return &g +} + +func (g guildMembersDo) FirstOrInit() (*model.GuildMembers, error) { + if result, err := g.DO.FirstOrInit(); err != nil { + return nil, err + } else { + return result.(*model.GuildMembers), nil + } +} + +func (g guildMembersDo) FirstOrCreate() (*model.GuildMembers, error) { + if result, err := g.DO.FirstOrCreate(); err != nil { + return nil, err + } else { + return result.(*model.GuildMembers), nil + } +} + +func (g guildMembersDo) FindByPage(offset int, limit int) (result []*model.GuildMembers, count int64, err error) { + result, err = g.Offset(offset).Limit(limit).Find() + if err != nil { + return + } + + if size := len(result); 0 < limit && 0 < size && size < limit { + count = int64(size + offset) + return + } + + count, err = g.Offset(-1).Limit(-1).Count() + return +} + +func (g guildMembersDo) ScanByPage(result interface{}, offset int, limit int) (count int64, err error) { + count, err = g.Count() + if err != nil { + return + } + + err = g.Offset(offset).Limit(limit).Scan(result) + return +} + +func (g guildMembersDo) Scan(result interface{}) (err error) { + return g.DO.Scan(result) +} + +func (g guildMembersDo) Delete(models ...*model.GuildMembers) (result gen.ResultInfo, err error) { + return g.DO.Delete(models) +} + +func (g *guildMembersDo) withDO(do gen.Dao) *guildMembersDo { + g.DO = *do.(*gen.DO) + return g +} diff --git a/internal/repository/mysql/dao/log_operation.gen.go b/internal/repository/mysql/dao/log_operation.gen.go index f46a831..db3e6c4 100644 --- a/internal/repository/mysql/dao/log_operation.gen.go +++ b/internal/repository/mysql/dao/log_operation.gen.go @@ -16,7 +16,7 @@ import ( "gorm.io/plugin/dbresolver" - "mini-chat/internal/repository/mysql/model" + "bindbox-game/internal/repository/mysql/model" ) func newLogOperation(db *gorm.DB, opts ...gen.DOOption) logOperation { diff --git a/internal/repository/mysql/dao/log_request.gen.go b/internal/repository/mysql/dao/log_request.gen.go index d0c700a..14a92a4 100644 --- a/internal/repository/mysql/dao/log_request.gen.go +++ b/internal/repository/mysql/dao/log_request.gen.go @@ -16,7 +16,7 @@ import ( "gorm.io/plugin/dbresolver" - "mini-chat/internal/repository/mysql/model" + "bindbox-game/internal/repository/mysql/model" ) func newLogRequest(db *gorm.DB, opts ...gen.DOOption) logRequest { diff --git a/internal/repository/mysql/dao/menu_actions.gen.go b/internal/repository/mysql/dao/menu_actions.gen.go new file mode 100644 index 0000000..d9945cc --- /dev/null +++ b/internal/repository/mysql/dao/menu_actions.gen.go @@ -0,0 +1,351 @@ +// Code generated by gorm.io/gen. DO NOT EDIT. +// Code generated by gorm.io/gen. DO NOT EDIT. +// Code generated by gorm.io/gen. DO NOT EDIT. + +package dao + +import ( + "context" + + "gorm.io/gorm" + "gorm.io/gorm/clause" + "gorm.io/gorm/schema" + + "gorm.io/gen" + "gorm.io/gen/field" + + "gorm.io/plugin/dbresolver" + + "bindbox-game/internal/repository/mysql/model" +) + +func newMenuActions(db *gorm.DB, opts ...gen.DOOption) menuActions { + _menuActions := menuActions{} + + _menuActions.menuActionsDo.UseDB(db, opts...) + _menuActions.menuActionsDo.UseModel(&model.MenuActions{}) + + tableName := _menuActions.menuActionsDo.TableName() + _menuActions.ALL = field.NewAsterisk(tableName) + _menuActions.ID = field.NewInt64(tableName, "id") + _menuActions.MenuID = field.NewInt64(tableName, "menu_id") + _menuActions.ActionMark = field.NewString(tableName, "action_mark") + _menuActions.ActionName = field.NewString(tableName, "action_name") + _menuActions.Status = field.NewBool(tableName, "status") + _menuActions.CreatedUser = field.NewString(tableName, "created_user") + _menuActions.UpdatedUser = field.NewString(tableName, "updated_user") + _menuActions.CreatedAt = field.NewTime(tableName, "created_at") + _menuActions.UpdatedAt = field.NewTime(tableName, "updated_at") + + _menuActions.fillFieldMap() + + return _menuActions +} + +type menuActions struct { + menuActionsDo + + ALL field.Asterisk + ID field.Int64 + MenuID field.Int64 + ActionMark field.String + ActionName field.String + Status field.Bool + CreatedUser field.String + UpdatedUser field.String + CreatedAt field.Time + UpdatedAt field.Time + + fieldMap map[string]field.Expr +} + +func (m menuActions) Table(newTableName string) *menuActions { + m.menuActionsDo.UseTable(newTableName) + return m.updateTableName(newTableName) +} + +func (m menuActions) As(alias string) *menuActions { + m.menuActionsDo.DO = *(m.menuActionsDo.As(alias).(*gen.DO)) + return m.updateTableName(alias) +} + +func (m *menuActions) updateTableName(table string) *menuActions { + m.ALL = field.NewAsterisk(table) + m.ID = field.NewInt64(table, "id") + m.MenuID = field.NewInt64(table, "menu_id") + m.ActionMark = field.NewString(table, "action_mark") + m.ActionName = field.NewString(table, "action_name") + m.Status = field.NewBool(table, "status") + m.CreatedUser = field.NewString(table, "created_user") + m.UpdatedUser = field.NewString(table, "updated_user") + m.CreatedAt = field.NewTime(table, "created_at") + m.UpdatedAt = field.NewTime(table, "updated_at") + + m.fillFieldMap() + + return m +} + +func (m *menuActions) GetFieldByName(fieldName string) (field.OrderExpr, bool) { + _f, ok := m.fieldMap[fieldName] + if !ok || _f == nil { + return nil, false + } + _oe, ok := _f.(field.OrderExpr) + return _oe, ok +} + +func (m *menuActions) fillFieldMap() { + m.fieldMap = make(map[string]field.Expr, 9) + m.fieldMap["id"] = m.ID + m.fieldMap["menu_id"] = m.MenuID + m.fieldMap["action_mark"] = m.ActionMark + m.fieldMap["action_name"] = m.ActionName + m.fieldMap["status"] = m.Status + m.fieldMap["created_user"] = m.CreatedUser + m.fieldMap["updated_user"] = m.UpdatedUser + m.fieldMap["created_at"] = m.CreatedAt + m.fieldMap["updated_at"] = m.UpdatedAt +} + +func (m menuActions) clone(db *gorm.DB) menuActions { + m.menuActionsDo.ReplaceConnPool(db.Statement.ConnPool) + return m +} + +func (m menuActions) replaceDB(db *gorm.DB) menuActions { + m.menuActionsDo.ReplaceDB(db) + return m +} + +type menuActionsDo struct{ gen.DO } + +func (m menuActionsDo) Debug() *menuActionsDo { + return m.withDO(m.DO.Debug()) +} + +func (m menuActionsDo) WithContext(ctx context.Context) *menuActionsDo { + return m.withDO(m.DO.WithContext(ctx)) +} + +func (m menuActionsDo) ReadDB() *menuActionsDo { + return m.Clauses(dbresolver.Read) +} + +func (m menuActionsDo) WriteDB() *menuActionsDo { + return m.Clauses(dbresolver.Write) +} + +func (m menuActionsDo) Session(config *gorm.Session) *menuActionsDo { + return m.withDO(m.DO.Session(config)) +} + +func (m menuActionsDo) Clauses(conds ...clause.Expression) *menuActionsDo { + return m.withDO(m.DO.Clauses(conds...)) +} + +func (m menuActionsDo) Returning(value interface{}, columns ...string) *menuActionsDo { + return m.withDO(m.DO.Returning(value, columns...)) +} + +func (m menuActionsDo) Not(conds ...gen.Condition) *menuActionsDo { + return m.withDO(m.DO.Not(conds...)) +} + +func (m menuActionsDo) Or(conds ...gen.Condition) *menuActionsDo { + return m.withDO(m.DO.Or(conds...)) +} + +func (m menuActionsDo) Select(conds ...field.Expr) *menuActionsDo { + return m.withDO(m.DO.Select(conds...)) +} + +func (m menuActionsDo) Where(conds ...gen.Condition) *menuActionsDo { + return m.withDO(m.DO.Where(conds...)) +} + +func (m menuActionsDo) Order(conds ...field.Expr) *menuActionsDo { + return m.withDO(m.DO.Order(conds...)) +} + +func (m menuActionsDo) Distinct(cols ...field.Expr) *menuActionsDo { + return m.withDO(m.DO.Distinct(cols...)) +} + +func (m menuActionsDo) Omit(cols ...field.Expr) *menuActionsDo { + return m.withDO(m.DO.Omit(cols...)) +} + +func (m menuActionsDo) Join(table schema.Tabler, on ...field.Expr) *menuActionsDo { + return m.withDO(m.DO.Join(table, on...)) +} + +func (m menuActionsDo) LeftJoin(table schema.Tabler, on ...field.Expr) *menuActionsDo { + return m.withDO(m.DO.LeftJoin(table, on...)) +} + +func (m menuActionsDo) RightJoin(table schema.Tabler, on ...field.Expr) *menuActionsDo { + return m.withDO(m.DO.RightJoin(table, on...)) +} + +func (m menuActionsDo) Group(cols ...field.Expr) *menuActionsDo { + return m.withDO(m.DO.Group(cols...)) +} + +func (m menuActionsDo) Having(conds ...gen.Condition) *menuActionsDo { + return m.withDO(m.DO.Having(conds...)) +} + +func (m menuActionsDo) Limit(limit int) *menuActionsDo { + return m.withDO(m.DO.Limit(limit)) +} + +func (m menuActionsDo) Offset(offset int) *menuActionsDo { + return m.withDO(m.DO.Offset(offset)) +} + +func (m menuActionsDo) Scopes(funcs ...func(gen.Dao) gen.Dao) *menuActionsDo { + return m.withDO(m.DO.Scopes(funcs...)) +} + +func (m menuActionsDo) Unscoped() *menuActionsDo { + return m.withDO(m.DO.Unscoped()) +} + +func (m menuActionsDo) Create(values ...*model.MenuActions) error { + if len(values) == 0 { + return nil + } + return m.DO.Create(values) +} + +func (m menuActionsDo) CreateInBatches(values []*model.MenuActions, batchSize int) error { + return m.DO.CreateInBatches(values, batchSize) +} + +// Save : !!! underlying implementation is different with GORM +// The method is equivalent to executing the statement: db.Clauses(clause.OnConflict{UpdateAll: true}).Create(values) +func (m menuActionsDo) Save(values ...*model.MenuActions) error { + if len(values) == 0 { + return nil + } + return m.DO.Save(values) +} + +func (m menuActionsDo) First() (*model.MenuActions, error) { + if result, err := m.DO.First(); err != nil { + return nil, err + } else { + return result.(*model.MenuActions), nil + } +} + +func (m menuActionsDo) Take() (*model.MenuActions, error) { + if result, err := m.DO.Take(); err != nil { + return nil, err + } else { + return result.(*model.MenuActions), nil + } +} + +func (m menuActionsDo) Last() (*model.MenuActions, error) { + if result, err := m.DO.Last(); err != nil { + return nil, err + } else { + return result.(*model.MenuActions), nil + } +} + +func (m menuActionsDo) Find() ([]*model.MenuActions, error) { + result, err := m.DO.Find() + return result.([]*model.MenuActions), err +} + +func (m menuActionsDo) FindInBatch(batchSize int, fc func(tx gen.Dao, batch int) error) (results []*model.MenuActions, err error) { + buf := make([]*model.MenuActions, 0, batchSize) + err = m.DO.FindInBatches(&buf, batchSize, func(tx gen.Dao, batch int) error { + defer func() { results = append(results, buf...) }() + return fc(tx, batch) + }) + return results, err +} + +func (m menuActionsDo) FindInBatches(result *[]*model.MenuActions, batchSize int, fc func(tx gen.Dao, batch int) error) error { + return m.DO.FindInBatches(result, batchSize, fc) +} + +func (m menuActionsDo) Attrs(attrs ...field.AssignExpr) *menuActionsDo { + return m.withDO(m.DO.Attrs(attrs...)) +} + +func (m menuActionsDo) Assign(attrs ...field.AssignExpr) *menuActionsDo { + return m.withDO(m.DO.Assign(attrs...)) +} + +func (m menuActionsDo) Joins(fields ...field.RelationField) *menuActionsDo { + for _, _f := range fields { + m = *m.withDO(m.DO.Joins(_f)) + } + return &m +} + +func (m menuActionsDo) Preload(fields ...field.RelationField) *menuActionsDo { + for _, _f := range fields { + m = *m.withDO(m.DO.Preload(_f)) + } + return &m +} + +func (m menuActionsDo) FirstOrInit() (*model.MenuActions, error) { + if result, err := m.DO.FirstOrInit(); err != nil { + return nil, err + } else { + return result.(*model.MenuActions), nil + } +} + +func (m menuActionsDo) FirstOrCreate() (*model.MenuActions, error) { + if result, err := m.DO.FirstOrCreate(); err != nil { + return nil, err + } else { + return result.(*model.MenuActions), nil + } +} + +func (m menuActionsDo) FindByPage(offset int, limit int) (result []*model.MenuActions, count int64, err error) { + result, err = m.Offset(offset).Limit(limit).Find() + if err != nil { + return + } + + if size := len(result); 0 < limit && 0 < size && size < limit { + count = int64(size + offset) + return + } + + count, err = m.Offset(-1).Limit(-1).Count() + return +} + +func (m menuActionsDo) ScanByPage(result interface{}, offset int, limit int) (count int64, err error) { + count, err = m.Count() + if err != nil { + return + } + + err = m.Offset(offset).Limit(limit).Scan(result) + return +} + +func (m menuActionsDo) Scan(result interface{}) (err error) { + return m.DO.Scan(result) +} + +func (m menuActionsDo) Delete(models ...*model.MenuActions) (result gen.ResultInfo, err error) { + return m.DO.Delete(models) +} + +func (m *menuActionsDo) withDO(do gen.Dao) *menuActionsDo { + m.DO = *do.(*gen.DO) + return m +} diff --git a/internal/repository/mysql/dao/menus.gen.go b/internal/repository/mysql/dao/menus.gen.go new file mode 100644 index 0000000..a62465c --- /dev/null +++ b/internal/repository/mysql/dao/menus.gen.go @@ -0,0 +1,375 @@ +// Code generated by gorm.io/gen. DO NOT EDIT. +// Code generated by gorm.io/gen. DO NOT EDIT. +// Code generated by gorm.io/gen. DO NOT EDIT. + +package dao + +import ( + "context" + + "gorm.io/gorm" + "gorm.io/gorm/clause" + "gorm.io/gorm/schema" + + "gorm.io/gen" + "gorm.io/gen/field" + + "gorm.io/plugin/dbresolver" + + "bindbox-game/internal/repository/mysql/model" +) + +func newMenus(db *gorm.DB, opts ...gen.DOOption) menus { + _menus := menus{} + + _menus.menusDo.UseDB(db, opts...) + _menus.menusDo.UseModel(&model.Menus{}) + + tableName := _menus.menusDo.TableName() + _menus.ALL = field.NewAsterisk(tableName) + _menus.ID = field.NewInt64(tableName, "id") + _menus.ParentID = field.NewInt64(tableName, "parent_id") + _menus.Path = field.NewString(tableName, "path") + _menus.Name = field.NewString(tableName, "name") + _menus.Component = field.NewString(tableName, "component") + _menus.Icon = field.NewString(tableName, "icon") + _menus.Sort = field.NewInt32(tableName, "sort") + _menus.Status = field.NewBool(tableName, "status") + _menus.KeepAlive = field.NewBool(tableName, "keep_alive") + _menus.IsHide = field.NewBool(tableName, "is_hide") + _menus.IsHideTab = field.NewBool(tableName, "is_hide_tab") + _menus.CreatedUser = field.NewString(tableName, "created_user") + _menus.UpdatedUser = field.NewString(tableName, "updated_user") + _menus.CreatedAt = field.NewTime(tableName, "created_at") + _menus.UpdatedAt = field.NewTime(tableName, "updated_at") + + _menus.fillFieldMap() + + return _menus +} + +type menus struct { + menusDo + + ALL field.Asterisk + ID field.Int64 + ParentID field.Int64 + Path field.String + Name field.String + Component field.String + Icon field.String + Sort field.Int32 + Status field.Bool + KeepAlive field.Bool + IsHide field.Bool + IsHideTab field.Bool + CreatedUser field.String + UpdatedUser field.String + CreatedAt field.Time + UpdatedAt field.Time + + fieldMap map[string]field.Expr +} + +func (m menus) Table(newTableName string) *menus { + m.menusDo.UseTable(newTableName) + return m.updateTableName(newTableName) +} + +func (m menus) As(alias string) *menus { + m.menusDo.DO = *(m.menusDo.As(alias).(*gen.DO)) + return m.updateTableName(alias) +} + +func (m *menus) updateTableName(table string) *menus { + m.ALL = field.NewAsterisk(table) + m.ID = field.NewInt64(table, "id") + m.ParentID = field.NewInt64(table, "parent_id") + m.Path = field.NewString(table, "path") + m.Name = field.NewString(table, "name") + m.Component = field.NewString(table, "component") + m.Icon = field.NewString(table, "icon") + m.Sort = field.NewInt32(table, "sort") + m.Status = field.NewBool(table, "status") + m.KeepAlive = field.NewBool(table, "keep_alive") + m.IsHide = field.NewBool(table, "is_hide") + m.IsHideTab = field.NewBool(table, "is_hide_tab") + m.CreatedUser = field.NewString(table, "created_user") + m.UpdatedUser = field.NewString(table, "updated_user") + m.CreatedAt = field.NewTime(table, "created_at") + m.UpdatedAt = field.NewTime(table, "updated_at") + + m.fillFieldMap() + + return m +} + +func (m *menus) GetFieldByName(fieldName string) (field.OrderExpr, bool) { + _f, ok := m.fieldMap[fieldName] + if !ok || _f == nil { + return nil, false + } + _oe, ok := _f.(field.OrderExpr) + return _oe, ok +} + +func (m *menus) fillFieldMap() { + m.fieldMap = make(map[string]field.Expr, 15) + m.fieldMap["id"] = m.ID + m.fieldMap["parent_id"] = m.ParentID + m.fieldMap["path"] = m.Path + m.fieldMap["name"] = m.Name + m.fieldMap["component"] = m.Component + m.fieldMap["icon"] = m.Icon + m.fieldMap["sort"] = m.Sort + m.fieldMap["status"] = m.Status + m.fieldMap["keep_alive"] = m.KeepAlive + m.fieldMap["is_hide"] = m.IsHide + m.fieldMap["is_hide_tab"] = m.IsHideTab + m.fieldMap["created_user"] = m.CreatedUser + m.fieldMap["updated_user"] = m.UpdatedUser + m.fieldMap["created_at"] = m.CreatedAt + m.fieldMap["updated_at"] = m.UpdatedAt +} + +func (m menus) clone(db *gorm.DB) menus { + m.menusDo.ReplaceConnPool(db.Statement.ConnPool) + return m +} + +func (m menus) replaceDB(db *gorm.DB) menus { + m.menusDo.ReplaceDB(db) + return m +} + +type menusDo struct{ gen.DO } + +func (m menusDo) Debug() *menusDo { + return m.withDO(m.DO.Debug()) +} + +func (m menusDo) WithContext(ctx context.Context) *menusDo { + return m.withDO(m.DO.WithContext(ctx)) +} + +func (m menusDo) ReadDB() *menusDo { + return m.Clauses(dbresolver.Read) +} + +func (m menusDo) WriteDB() *menusDo { + return m.Clauses(dbresolver.Write) +} + +func (m menusDo) Session(config *gorm.Session) *menusDo { + return m.withDO(m.DO.Session(config)) +} + +func (m menusDo) Clauses(conds ...clause.Expression) *menusDo { + return m.withDO(m.DO.Clauses(conds...)) +} + +func (m menusDo) Returning(value interface{}, columns ...string) *menusDo { + return m.withDO(m.DO.Returning(value, columns...)) +} + +func (m menusDo) Not(conds ...gen.Condition) *menusDo { + return m.withDO(m.DO.Not(conds...)) +} + +func (m menusDo) Or(conds ...gen.Condition) *menusDo { + return m.withDO(m.DO.Or(conds...)) +} + +func (m menusDo) Select(conds ...field.Expr) *menusDo { + return m.withDO(m.DO.Select(conds...)) +} + +func (m menusDo) Where(conds ...gen.Condition) *menusDo { + return m.withDO(m.DO.Where(conds...)) +} + +func (m menusDo) Order(conds ...field.Expr) *menusDo { + return m.withDO(m.DO.Order(conds...)) +} + +func (m menusDo) Distinct(cols ...field.Expr) *menusDo { + return m.withDO(m.DO.Distinct(cols...)) +} + +func (m menusDo) Omit(cols ...field.Expr) *menusDo { + return m.withDO(m.DO.Omit(cols...)) +} + +func (m menusDo) Join(table schema.Tabler, on ...field.Expr) *menusDo { + return m.withDO(m.DO.Join(table, on...)) +} + +func (m menusDo) LeftJoin(table schema.Tabler, on ...field.Expr) *menusDo { + return m.withDO(m.DO.LeftJoin(table, on...)) +} + +func (m menusDo) RightJoin(table schema.Tabler, on ...field.Expr) *menusDo { + return m.withDO(m.DO.RightJoin(table, on...)) +} + +func (m menusDo) Group(cols ...field.Expr) *menusDo { + return m.withDO(m.DO.Group(cols...)) +} + +func (m menusDo) Having(conds ...gen.Condition) *menusDo { + return m.withDO(m.DO.Having(conds...)) +} + +func (m menusDo) Limit(limit int) *menusDo { + return m.withDO(m.DO.Limit(limit)) +} + +func (m menusDo) Offset(offset int) *menusDo { + return m.withDO(m.DO.Offset(offset)) +} + +func (m menusDo) Scopes(funcs ...func(gen.Dao) gen.Dao) *menusDo { + return m.withDO(m.DO.Scopes(funcs...)) +} + +func (m menusDo) Unscoped() *menusDo { + return m.withDO(m.DO.Unscoped()) +} + +func (m menusDo) Create(values ...*model.Menus) error { + if len(values) == 0 { + return nil + } + return m.DO.Create(values) +} + +func (m menusDo) CreateInBatches(values []*model.Menus, batchSize int) error { + return m.DO.CreateInBatches(values, batchSize) +} + +// Save : !!! underlying implementation is different with GORM +// The method is equivalent to executing the statement: db.Clauses(clause.OnConflict{UpdateAll: true}).Create(values) +func (m menusDo) Save(values ...*model.Menus) error { + if len(values) == 0 { + return nil + } + return m.DO.Save(values) +} + +func (m menusDo) First() (*model.Menus, error) { + if result, err := m.DO.First(); err != nil { + return nil, err + } else { + return result.(*model.Menus), nil + } +} + +func (m menusDo) Take() (*model.Menus, error) { + if result, err := m.DO.Take(); err != nil { + return nil, err + } else { + return result.(*model.Menus), nil + } +} + +func (m menusDo) Last() (*model.Menus, error) { + if result, err := m.DO.Last(); err != nil { + return nil, err + } else { + return result.(*model.Menus), nil + } +} + +func (m menusDo) Find() ([]*model.Menus, error) { + result, err := m.DO.Find() + return result.([]*model.Menus), err +} + +func (m menusDo) FindInBatch(batchSize int, fc func(tx gen.Dao, batch int) error) (results []*model.Menus, err error) { + buf := make([]*model.Menus, 0, batchSize) + err = m.DO.FindInBatches(&buf, batchSize, func(tx gen.Dao, batch int) error { + defer func() { results = append(results, buf...) }() + return fc(tx, batch) + }) + return results, err +} + +func (m menusDo) FindInBatches(result *[]*model.Menus, batchSize int, fc func(tx gen.Dao, batch int) error) error { + return m.DO.FindInBatches(result, batchSize, fc) +} + +func (m menusDo) Attrs(attrs ...field.AssignExpr) *menusDo { + return m.withDO(m.DO.Attrs(attrs...)) +} + +func (m menusDo) Assign(attrs ...field.AssignExpr) *menusDo { + return m.withDO(m.DO.Assign(attrs...)) +} + +func (m menusDo) Joins(fields ...field.RelationField) *menusDo { + for _, _f := range fields { + m = *m.withDO(m.DO.Joins(_f)) + } + return &m +} + +func (m menusDo) Preload(fields ...field.RelationField) *menusDo { + for _, _f := range fields { + m = *m.withDO(m.DO.Preload(_f)) + } + return &m +} + +func (m menusDo) FirstOrInit() (*model.Menus, error) { + if result, err := m.DO.FirstOrInit(); err != nil { + return nil, err + } else { + return result.(*model.Menus), nil + } +} + +func (m menusDo) FirstOrCreate() (*model.Menus, error) { + if result, err := m.DO.FirstOrCreate(); err != nil { + return nil, err + } else { + return result.(*model.Menus), nil + } +} + +func (m menusDo) FindByPage(offset int, limit int) (result []*model.Menus, count int64, err error) { + result, err = m.Offset(offset).Limit(limit).Find() + if err != nil { + return + } + + if size := len(result); 0 < limit && 0 < size && size < limit { + count = int64(size + offset) + return + } + + count, err = m.Offset(-1).Limit(-1).Count() + return +} + +func (m menusDo) ScanByPage(result interface{}, offset int, limit int) (count int64, err error) { + count, err = m.Count() + if err != nil { + return + } + + err = m.Offset(offset).Limit(limit).Scan(result) + return +} + +func (m menusDo) Scan(result interface{}) (err error) { + return m.DO.Scan(result) +} + +func (m menusDo) Delete(models ...*model.Menus) (result gen.ResultInfo, err error) { + return m.DO.Delete(models) +} + +func (m *menusDo) withDO(do gen.Dao) *menusDo { + m.DO = *do.(*gen.DO) + return m +} diff --git a/internal/repository/mysql/dao/mini_program.gen.go b/internal/repository/mysql/dao/mini_program.gen.go deleted file mode 100644 index fa288f4..0000000 --- a/internal/repository/mysql/dao/mini_program.gen.go +++ /dev/null @@ -1,368 +0,0 @@ -// Code generated by gorm.io/gen. DO NOT EDIT. -// Code generated by gorm.io/gen. DO NOT EDIT. -// Code generated by gorm.io/gen. DO NOT EDIT. - -package dao - -import ( - "context" - - "gorm.io/gorm" - "gorm.io/gorm/clause" - "gorm.io/gorm/schema" - - "gorm.io/gen" - "gorm.io/gen/field" - - "gorm.io/plugin/dbresolver" - - "mini-chat/internal/repository/mysql/model" -) - -func newMiniProgram(db *gorm.DB, opts ...gen.DOOption) miniProgram { - _miniProgram := miniProgram{} - - _miniProgram.miniProgramDo.UseDB(db, opts...) - _miniProgram.miniProgramDo.UseModel(&model.MiniProgram{}) - - tableName := _miniProgram.miniProgramDo.TableName() - _miniProgram.ALL = field.NewAsterisk(tableName) - _miniProgram.ID = field.NewInt32(tableName, "id") - _miniProgram.AppID = field.NewString(tableName, "app_id") - _miniProgram.AppSecret = field.NewString(tableName, "app_secret") - _miniProgram.AdminID = field.NewInt32(tableName, "admin_id") - _miniProgram.TemplateID = field.NewString(tableName, "template_id") - _miniProgram.Name = field.NewString(tableName, "name") - _miniProgram.Description = field.NewString(tableName, "description") - _miniProgram.Avatar = field.NewString(tableName, "avatar") - _miniProgram.Status = field.NewInt32(tableName, "status") - _miniProgram.CreatedUser = field.NewString(tableName, "created_user") - _miniProgram.CreatedAt = field.NewTime(tableName, "created_at") - _miniProgram.UpdatedUser = field.NewString(tableName, "updated_user") - _miniProgram.UpdatedAt = field.NewTime(tableName, "updated_at") - - _miniProgram.fillFieldMap() - - return _miniProgram -} - -// miniProgram 小程序表 -type miniProgram struct { - miniProgramDo - - ALL field.Asterisk - ID field.Int32 // 主键ID - AppID field.String // 小程序ID - AppSecret field.String // 小程序密钥 - AdminID field.Int32 // 管理员ID - TemplateID field.String // 模版ID - Name field.String // 名称 - Description field.String // 描述 - Avatar field.String // 头像 - Status field.Int32 // 状态(1:正常 -1:封禁) - CreatedUser field.String // 创建人 - CreatedAt field.Time // 创建时间 - UpdatedUser field.String // 更新人 - UpdatedAt field.Time // 更新时间 - - fieldMap map[string]field.Expr -} - -func (m miniProgram) Table(newTableName string) *miniProgram { - m.miniProgramDo.UseTable(newTableName) - return m.updateTableName(newTableName) -} - -func (m miniProgram) As(alias string) *miniProgram { - m.miniProgramDo.DO = *(m.miniProgramDo.As(alias).(*gen.DO)) - return m.updateTableName(alias) -} - -func (m *miniProgram) updateTableName(table string) *miniProgram { - m.ALL = field.NewAsterisk(table) - m.ID = field.NewInt32(table, "id") - m.AppID = field.NewString(table, "app_id") - m.AppSecret = field.NewString(table, "app_secret") - m.AdminID = field.NewInt32(table, "admin_id") - m.TemplateID = field.NewString(table, "template_id") - m.Name = field.NewString(table, "name") - m.Description = field.NewString(table, "description") - m.Avatar = field.NewString(table, "avatar") - m.Status = field.NewInt32(table, "status") - m.CreatedUser = field.NewString(table, "created_user") - m.CreatedAt = field.NewTime(table, "created_at") - m.UpdatedUser = field.NewString(table, "updated_user") - m.UpdatedAt = field.NewTime(table, "updated_at") - - m.fillFieldMap() - - return m -} - -func (m *miniProgram) GetFieldByName(fieldName string) (field.OrderExpr, bool) { - _f, ok := m.fieldMap[fieldName] - if !ok || _f == nil { - return nil, false - } - _oe, ok := _f.(field.OrderExpr) - return _oe, ok -} - -func (m *miniProgram) fillFieldMap() { - m.fieldMap = make(map[string]field.Expr, 13) - m.fieldMap["id"] = m.ID - m.fieldMap["app_id"] = m.AppID - m.fieldMap["app_secret"] = m.AppSecret - m.fieldMap["admin_id"] = m.AdminID - m.fieldMap["template_id"] = m.TemplateID - m.fieldMap["name"] = m.Name - m.fieldMap["description"] = m.Description - m.fieldMap["avatar"] = m.Avatar - m.fieldMap["status"] = m.Status - m.fieldMap["created_user"] = m.CreatedUser - m.fieldMap["created_at"] = m.CreatedAt - m.fieldMap["updated_user"] = m.UpdatedUser - m.fieldMap["updated_at"] = m.UpdatedAt -} - -func (m miniProgram) clone(db *gorm.DB) miniProgram { - m.miniProgramDo.ReplaceConnPool(db.Statement.ConnPool) - return m -} - -func (m miniProgram) replaceDB(db *gorm.DB) miniProgram { - m.miniProgramDo.ReplaceDB(db) - return m -} - -type miniProgramDo struct{ gen.DO } - -func (m miniProgramDo) Debug() *miniProgramDo { - return m.withDO(m.DO.Debug()) -} - -func (m miniProgramDo) WithContext(ctx context.Context) *miniProgramDo { - return m.withDO(m.DO.WithContext(ctx)) -} - -func (m miniProgramDo) ReadDB() *miniProgramDo { - return m.Clauses(dbresolver.Read) -} - -func (m miniProgramDo) WriteDB() *miniProgramDo { - return m.Clauses(dbresolver.Write) -} - -func (m miniProgramDo) Session(config *gorm.Session) *miniProgramDo { - return m.withDO(m.DO.Session(config)) -} - -func (m miniProgramDo) Clauses(conds ...clause.Expression) *miniProgramDo { - return m.withDO(m.DO.Clauses(conds...)) -} - -func (m miniProgramDo) Returning(value interface{}, columns ...string) *miniProgramDo { - return m.withDO(m.DO.Returning(value, columns...)) -} - -func (m miniProgramDo) Not(conds ...gen.Condition) *miniProgramDo { - return m.withDO(m.DO.Not(conds...)) -} - -func (m miniProgramDo) Or(conds ...gen.Condition) *miniProgramDo { - return m.withDO(m.DO.Or(conds...)) -} - -func (m miniProgramDo) Select(conds ...field.Expr) *miniProgramDo { - return m.withDO(m.DO.Select(conds...)) -} - -func (m miniProgramDo) Where(conds ...gen.Condition) *miniProgramDo { - return m.withDO(m.DO.Where(conds...)) -} - -func (m miniProgramDo) Order(conds ...field.Expr) *miniProgramDo { - return m.withDO(m.DO.Order(conds...)) -} - -func (m miniProgramDo) Distinct(cols ...field.Expr) *miniProgramDo { - return m.withDO(m.DO.Distinct(cols...)) -} - -func (m miniProgramDo) Omit(cols ...field.Expr) *miniProgramDo { - return m.withDO(m.DO.Omit(cols...)) -} - -func (m miniProgramDo) Join(table schema.Tabler, on ...field.Expr) *miniProgramDo { - return m.withDO(m.DO.Join(table, on...)) -} - -func (m miniProgramDo) LeftJoin(table schema.Tabler, on ...field.Expr) *miniProgramDo { - return m.withDO(m.DO.LeftJoin(table, on...)) -} - -func (m miniProgramDo) RightJoin(table schema.Tabler, on ...field.Expr) *miniProgramDo { - return m.withDO(m.DO.RightJoin(table, on...)) -} - -func (m miniProgramDo) Group(cols ...field.Expr) *miniProgramDo { - return m.withDO(m.DO.Group(cols...)) -} - -func (m miniProgramDo) Having(conds ...gen.Condition) *miniProgramDo { - return m.withDO(m.DO.Having(conds...)) -} - -func (m miniProgramDo) Limit(limit int) *miniProgramDo { - return m.withDO(m.DO.Limit(limit)) -} - -func (m miniProgramDo) Offset(offset int) *miniProgramDo { - return m.withDO(m.DO.Offset(offset)) -} - -func (m miniProgramDo) Scopes(funcs ...func(gen.Dao) gen.Dao) *miniProgramDo { - return m.withDO(m.DO.Scopes(funcs...)) -} - -func (m miniProgramDo) Unscoped() *miniProgramDo { - return m.withDO(m.DO.Unscoped()) -} - -func (m miniProgramDo) Create(values ...*model.MiniProgram) error { - if len(values) == 0 { - return nil - } - return m.DO.Create(values) -} - -func (m miniProgramDo) CreateInBatches(values []*model.MiniProgram, batchSize int) error { - return m.DO.CreateInBatches(values, batchSize) -} - -// Save : !!! underlying implementation is different with GORM -// The method is equivalent to executing the statement: db.Clauses(clause.OnConflict{UpdateAll: true}).Create(values) -func (m miniProgramDo) Save(values ...*model.MiniProgram) error { - if len(values) == 0 { - return nil - } - return m.DO.Save(values) -} - -func (m miniProgramDo) First() (*model.MiniProgram, error) { - if result, err := m.DO.First(); err != nil { - return nil, err - } else { - return result.(*model.MiniProgram), nil - } -} - -func (m miniProgramDo) Take() (*model.MiniProgram, error) { - if result, err := m.DO.Take(); err != nil { - return nil, err - } else { - return result.(*model.MiniProgram), nil - } -} - -func (m miniProgramDo) Last() (*model.MiniProgram, error) { - if result, err := m.DO.Last(); err != nil { - return nil, err - } else { - return result.(*model.MiniProgram), nil - } -} - -func (m miniProgramDo) Find() ([]*model.MiniProgram, error) { - result, err := m.DO.Find() - return result.([]*model.MiniProgram), err -} - -func (m miniProgramDo) FindInBatch(batchSize int, fc func(tx gen.Dao, batch int) error) (results []*model.MiniProgram, err error) { - buf := make([]*model.MiniProgram, 0, batchSize) - err = m.DO.FindInBatches(&buf, batchSize, func(tx gen.Dao, batch int) error { - defer func() { results = append(results, buf...) }() - return fc(tx, batch) - }) - return results, err -} - -func (m miniProgramDo) FindInBatches(result *[]*model.MiniProgram, batchSize int, fc func(tx gen.Dao, batch int) error) error { - return m.DO.FindInBatches(result, batchSize, fc) -} - -func (m miniProgramDo) Attrs(attrs ...field.AssignExpr) *miniProgramDo { - return m.withDO(m.DO.Attrs(attrs...)) -} - -func (m miniProgramDo) Assign(attrs ...field.AssignExpr) *miniProgramDo { - return m.withDO(m.DO.Assign(attrs...)) -} - -func (m miniProgramDo) Joins(fields ...field.RelationField) *miniProgramDo { - for _, _f := range fields { - m = *m.withDO(m.DO.Joins(_f)) - } - return &m -} - -func (m miniProgramDo) Preload(fields ...field.RelationField) *miniProgramDo { - for _, _f := range fields { - m = *m.withDO(m.DO.Preload(_f)) - } - return &m -} - -func (m miniProgramDo) FirstOrInit() (*model.MiniProgram, error) { - if result, err := m.DO.FirstOrInit(); err != nil { - return nil, err - } else { - return result.(*model.MiniProgram), nil - } -} - -func (m miniProgramDo) FirstOrCreate() (*model.MiniProgram, error) { - if result, err := m.DO.FirstOrCreate(); err != nil { - return nil, err - } else { - return result.(*model.MiniProgram), nil - } -} - -func (m miniProgramDo) FindByPage(offset int, limit int) (result []*model.MiniProgram, count int64, err error) { - result, err = m.Offset(offset).Limit(limit).Find() - if err != nil { - return - } - - if size := len(result); 0 < limit && 0 < size && size < limit { - count = int64(size + offset) - return - } - - count, err = m.Offset(-1).Limit(-1).Count() - return -} - -func (m miniProgramDo) ScanByPage(result interface{}, offset int, limit int) (count int64, err error) { - count, err = m.Count() - if err != nil { - return - } - - err = m.Offset(offset).Limit(limit).Scan(result) - return -} - -func (m miniProgramDo) Scan(result interface{}) (err error) { - return m.DO.Scan(result) -} - -func (m miniProgramDo) Delete(models ...*model.MiniProgram) (result gen.ResultInfo, err error) { - return m.DO.Delete(models) -} - -func (m *miniProgramDo) withDO(do gen.Dao) *miniProgramDo { - m.DO = *do.(*gen.DO) - return m -} diff --git a/internal/repository/mysql/dao/mini_program_access_token.gen.go b/internal/repository/mysql/dao/mini_program_access_token.gen.go index b7bea45..5a6e5fa 100644 --- a/internal/repository/mysql/dao/mini_program_access_token.gen.go +++ b/internal/repository/mysql/dao/mini_program_access_token.gen.go @@ -16,7 +16,7 @@ import ( "gorm.io/plugin/dbresolver" - "mini-chat/internal/repository/mysql/model" + "bindbox-game/internal/repository/mysql/model" ) func newMiniProgramAccessToken(db *gorm.DB, opts ...gen.DOOption) miniProgramAccessToken { diff --git a/internal/repository/mysql/dao/order_items.gen.go b/internal/repository/mysql/dao/order_items.gen.go new file mode 100644 index 0000000..ed86875 --- /dev/null +++ b/internal/repository/mysql/dao/order_items.gen.go @@ -0,0 +1,356 @@ +// Code generated by gorm.io/gen. DO NOT EDIT. +// Code generated by gorm.io/gen. DO NOT EDIT. +// Code generated by gorm.io/gen. DO NOT EDIT. + +package dao + +import ( + "context" + + "gorm.io/gorm" + "gorm.io/gorm/clause" + "gorm.io/gorm/schema" + + "gorm.io/gen" + "gorm.io/gen/field" + + "gorm.io/plugin/dbresolver" + + "bindbox-game/internal/repository/mysql/model" +) + +func newOrderItems(db *gorm.DB, opts ...gen.DOOption) orderItems { + _orderItems := orderItems{} + + _orderItems.orderItemsDo.UseDB(db, opts...) + _orderItems.orderItemsDo.UseModel(&model.OrderItems{}) + + tableName := _orderItems.orderItemsDo.TableName() + _orderItems.ALL = field.NewAsterisk(tableName) + _orderItems.ID = field.NewInt64(tableName, "id") + _orderItems.CreatedAt = field.NewTime(tableName, "created_at") + _orderItems.OrderID = field.NewInt64(tableName, "order_id") + _orderItems.ProductID = field.NewInt64(tableName, "product_id") + _orderItems.Title = field.NewString(tableName, "title") + _orderItems.Quantity = field.NewInt64(tableName, "quantity") + _orderItems.Price = field.NewInt64(tableName, "price") + _orderItems.TotalAmount = field.NewInt64(tableName, "total_amount") + _orderItems.ProductImages = field.NewString(tableName, "product_images") + _orderItems.Status = field.NewInt32(tableName, "status") + + _orderItems.fillFieldMap() + + return _orderItems +} + +// orderItems 订单明细 +type orderItems struct { + orderItemsDo + + ALL field.Asterisk + ID field.Int64 // 主键ID + CreatedAt field.Time // 创建时间 + OrderID field.Int64 // 订单ID(orders.id) + ProductID field.Int64 // 商品ID(products.id) + Title field.String // 商品标题快照 + Quantity field.Int64 // 购买数量 + Price field.Int64 // 成交单价(分) + TotalAmount field.Int64 // 行应付总额(分) + ProductImages field.String // 商品图片快照(JSON) + Status field.Int32 // 行状态:1正常 2取消 + + fieldMap map[string]field.Expr +} + +func (o orderItems) Table(newTableName string) *orderItems { + o.orderItemsDo.UseTable(newTableName) + return o.updateTableName(newTableName) +} + +func (o orderItems) As(alias string) *orderItems { + o.orderItemsDo.DO = *(o.orderItemsDo.As(alias).(*gen.DO)) + return o.updateTableName(alias) +} + +func (o *orderItems) updateTableName(table string) *orderItems { + o.ALL = field.NewAsterisk(table) + o.ID = field.NewInt64(table, "id") + o.CreatedAt = field.NewTime(table, "created_at") + o.OrderID = field.NewInt64(table, "order_id") + o.ProductID = field.NewInt64(table, "product_id") + o.Title = field.NewString(table, "title") + o.Quantity = field.NewInt64(table, "quantity") + o.Price = field.NewInt64(table, "price") + o.TotalAmount = field.NewInt64(table, "total_amount") + o.ProductImages = field.NewString(table, "product_images") + o.Status = field.NewInt32(table, "status") + + o.fillFieldMap() + + return o +} + +func (o *orderItems) GetFieldByName(fieldName string) (field.OrderExpr, bool) { + _f, ok := o.fieldMap[fieldName] + if !ok || _f == nil { + return nil, false + } + _oe, ok := _f.(field.OrderExpr) + return _oe, ok +} + +func (o *orderItems) fillFieldMap() { + o.fieldMap = make(map[string]field.Expr, 10) + o.fieldMap["id"] = o.ID + o.fieldMap["created_at"] = o.CreatedAt + o.fieldMap["order_id"] = o.OrderID + o.fieldMap["product_id"] = o.ProductID + o.fieldMap["title"] = o.Title + o.fieldMap["quantity"] = o.Quantity + o.fieldMap["price"] = o.Price + o.fieldMap["total_amount"] = o.TotalAmount + o.fieldMap["product_images"] = o.ProductImages + o.fieldMap["status"] = o.Status +} + +func (o orderItems) clone(db *gorm.DB) orderItems { + o.orderItemsDo.ReplaceConnPool(db.Statement.ConnPool) + return o +} + +func (o orderItems) replaceDB(db *gorm.DB) orderItems { + o.orderItemsDo.ReplaceDB(db) + return o +} + +type orderItemsDo struct{ gen.DO } + +func (o orderItemsDo) Debug() *orderItemsDo { + return o.withDO(o.DO.Debug()) +} + +func (o orderItemsDo) WithContext(ctx context.Context) *orderItemsDo { + return o.withDO(o.DO.WithContext(ctx)) +} + +func (o orderItemsDo) ReadDB() *orderItemsDo { + return o.Clauses(dbresolver.Read) +} + +func (o orderItemsDo) WriteDB() *orderItemsDo { + return o.Clauses(dbresolver.Write) +} + +func (o orderItemsDo) Session(config *gorm.Session) *orderItemsDo { + return o.withDO(o.DO.Session(config)) +} + +func (o orderItemsDo) Clauses(conds ...clause.Expression) *orderItemsDo { + return o.withDO(o.DO.Clauses(conds...)) +} + +func (o orderItemsDo) Returning(value interface{}, columns ...string) *orderItemsDo { + return o.withDO(o.DO.Returning(value, columns...)) +} + +func (o orderItemsDo) Not(conds ...gen.Condition) *orderItemsDo { + return o.withDO(o.DO.Not(conds...)) +} + +func (o orderItemsDo) Or(conds ...gen.Condition) *orderItemsDo { + return o.withDO(o.DO.Or(conds...)) +} + +func (o orderItemsDo) Select(conds ...field.Expr) *orderItemsDo { + return o.withDO(o.DO.Select(conds...)) +} + +func (o orderItemsDo) Where(conds ...gen.Condition) *orderItemsDo { + return o.withDO(o.DO.Where(conds...)) +} + +func (o orderItemsDo) Order(conds ...field.Expr) *orderItemsDo { + return o.withDO(o.DO.Order(conds...)) +} + +func (o orderItemsDo) Distinct(cols ...field.Expr) *orderItemsDo { + return o.withDO(o.DO.Distinct(cols...)) +} + +func (o orderItemsDo) Omit(cols ...field.Expr) *orderItemsDo { + return o.withDO(o.DO.Omit(cols...)) +} + +func (o orderItemsDo) Join(table schema.Tabler, on ...field.Expr) *orderItemsDo { + return o.withDO(o.DO.Join(table, on...)) +} + +func (o orderItemsDo) LeftJoin(table schema.Tabler, on ...field.Expr) *orderItemsDo { + return o.withDO(o.DO.LeftJoin(table, on...)) +} + +func (o orderItemsDo) RightJoin(table schema.Tabler, on ...field.Expr) *orderItemsDo { + return o.withDO(o.DO.RightJoin(table, on...)) +} + +func (o orderItemsDo) Group(cols ...field.Expr) *orderItemsDo { + return o.withDO(o.DO.Group(cols...)) +} + +func (o orderItemsDo) Having(conds ...gen.Condition) *orderItemsDo { + return o.withDO(o.DO.Having(conds...)) +} + +func (o orderItemsDo) Limit(limit int) *orderItemsDo { + return o.withDO(o.DO.Limit(limit)) +} + +func (o orderItemsDo) Offset(offset int) *orderItemsDo { + return o.withDO(o.DO.Offset(offset)) +} + +func (o orderItemsDo) Scopes(funcs ...func(gen.Dao) gen.Dao) *orderItemsDo { + return o.withDO(o.DO.Scopes(funcs...)) +} + +func (o orderItemsDo) Unscoped() *orderItemsDo { + return o.withDO(o.DO.Unscoped()) +} + +func (o orderItemsDo) Create(values ...*model.OrderItems) error { + if len(values) == 0 { + return nil + } + return o.DO.Create(values) +} + +func (o orderItemsDo) CreateInBatches(values []*model.OrderItems, batchSize int) error { + return o.DO.CreateInBatches(values, batchSize) +} + +// Save : !!! underlying implementation is different with GORM +// The method is equivalent to executing the statement: db.Clauses(clause.OnConflict{UpdateAll: true}).Create(values) +func (o orderItemsDo) Save(values ...*model.OrderItems) error { + if len(values) == 0 { + return nil + } + return o.DO.Save(values) +} + +func (o orderItemsDo) First() (*model.OrderItems, error) { + if result, err := o.DO.First(); err != nil { + return nil, err + } else { + return result.(*model.OrderItems), nil + } +} + +func (o orderItemsDo) Take() (*model.OrderItems, error) { + if result, err := o.DO.Take(); err != nil { + return nil, err + } else { + return result.(*model.OrderItems), nil + } +} + +func (o orderItemsDo) Last() (*model.OrderItems, error) { + if result, err := o.DO.Last(); err != nil { + return nil, err + } else { + return result.(*model.OrderItems), nil + } +} + +func (o orderItemsDo) Find() ([]*model.OrderItems, error) { + result, err := o.DO.Find() + return result.([]*model.OrderItems), err +} + +func (o orderItemsDo) FindInBatch(batchSize int, fc func(tx gen.Dao, batch int) error) (results []*model.OrderItems, err error) { + buf := make([]*model.OrderItems, 0, batchSize) + err = o.DO.FindInBatches(&buf, batchSize, func(tx gen.Dao, batch int) error { + defer func() { results = append(results, buf...) }() + return fc(tx, batch) + }) + return results, err +} + +func (o orderItemsDo) FindInBatches(result *[]*model.OrderItems, batchSize int, fc func(tx gen.Dao, batch int) error) error { + return o.DO.FindInBatches(result, batchSize, fc) +} + +func (o orderItemsDo) Attrs(attrs ...field.AssignExpr) *orderItemsDo { + return o.withDO(o.DO.Attrs(attrs...)) +} + +func (o orderItemsDo) Assign(attrs ...field.AssignExpr) *orderItemsDo { + return o.withDO(o.DO.Assign(attrs...)) +} + +func (o orderItemsDo) Joins(fields ...field.RelationField) *orderItemsDo { + for _, _f := range fields { + o = *o.withDO(o.DO.Joins(_f)) + } + return &o +} + +func (o orderItemsDo) Preload(fields ...field.RelationField) *orderItemsDo { + for _, _f := range fields { + o = *o.withDO(o.DO.Preload(_f)) + } + return &o +} + +func (o orderItemsDo) FirstOrInit() (*model.OrderItems, error) { + if result, err := o.DO.FirstOrInit(); err != nil { + return nil, err + } else { + return result.(*model.OrderItems), nil + } +} + +func (o orderItemsDo) FirstOrCreate() (*model.OrderItems, error) { + if result, err := o.DO.FirstOrCreate(); err != nil { + return nil, err + } else { + return result.(*model.OrderItems), nil + } +} + +func (o orderItemsDo) FindByPage(offset int, limit int) (result []*model.OrderItems, count int64, err error) { + result, err = o.Offset(offset).Limit(limit).Find() + if err != nil { + return + } + + if size := len(result); 0 < limit && 0 < size && size < limit { + count = int64(size + offset) + return + } + + count, err = o.Offset(-1).Limit(-1).Count() + return +} + +func (o orderItemsDo) ScanByPage(result interface{}, offset int, limit int) (count int64, err error) { + count, err = o.Count() + if err != nil { + return + } + + err = o.Offset(offset).Limit(limit).Scan(result) + return +} + +func (o orderItemsDo) Scan(result interface{}) (err error) { + return o.DO.Scan(result) +} + +func (o orderItemsDo) Delete(models ...*model.OrderItems) (result gen.ResultInfo, err error) { + return o.DO.Delete(models) +} + +func (o *orderItemsDo) withDO(do gen.Dao) *orderItemsDo { + o.DO = *do.(*gen.DO) + return o +} diff --git a/internal/repository/mysql/dao/orders.gen.go b/internal/repository/mysql/dao/orders.gen.go new file mode 100644 index 0000000..0813955 --- /dev/null +++ b/internal/repository/mysql/dao/orders.gen.go @@ -0,0 +1,388 @@ +// Code generated by gorm.io/gen. DO NOT EDIT. +// Code generated by gorm.io/gen. DO NOT EDIT. +// Code generated by gorm.io/gen. DO NOT EDIT. + +package dao + +import ( + "context" + + "gorm.io/gorm" + "gorm.io/gorm/clause" + "gorm.io/gorm/schema" + + "gorm.io/gen" + "gorm.io/gen/field" + + "gorm.io/plugin/dbresolver" + + "bindbox-game/internal/repository/mysql/model" +) + +func newOrders(db *gorm.DB, opts ...gen.DOOption) orders { + _orders := orders{} + + _orders.ordersDo.UseDB(db, opts...) + _orders.ordersDo.UseModel(&model.Orders{}) + + tableName := _orders.ordersDo.TableName() + _orders.ALL = field.NewAsterisk(tableName) + _orders.ID = field.NewInt64(tableName, "id") + _orders.CreatedAt = field.NewTime(tableName, "created_at") + _orders.UpdatedAt = field.NewTime(tableName, "updated_at") + _orders.UserID = field.NewInt64(tableName, "user_id") + _orders.OrderNo = field.NewString(tableName, "order_no") + _orders.SourceType = field.NewInt32(tableName, "source_type") + _orders.TotalAmount = field.NewInt64(tableName, "total_amount") + _orders.DiscountAmount = field.NewInt64(tableName, "discount_amount") + _orders.PointsAmount = field.NewInt64(tableName, "points_amount") + _orders.ActualAmount = field.NewInt64(tableName, "actual_amount") + _orders.Status = field.NewInt32(tableName, "status") + _orders.PayPreorderID = field.NewInt64(tableName, "pay_preorder_id") + _orders.PaidAt = field.NewTime(tableName, "paid_at") + _orders.CancelledAt = field.NewTime(tableName, "cancelled_at") + _orders.UserAddressID = field.NewInt64(tableName, "user_address_id") + _orders.IsConsumed = field.NewInt32(tableName, "is_consumed") + _orders.PointsLedgerID = field.NewInt64(tableName, "points_ledger_id") + _orders.Remark = field.NewString(tableName, "remark") + + _orders.fillFieldMap() + + return _orders +} + +// orders 订单 +type orders struct { + ordersDo + + ALL field.Asterisk + ID field.Int64 // 主键ID + CreatedAt field.Time // 创建时间 + UpdatedAt field.Time // 更新时间 + UserID field.Int64 // 下单用户ID(user_members.id) + OrderNo field.String // 业务订单号(唯一) + SourceType field.Int32 // 来源:1商城直购 2抽奖票据 3其他 + TotalAmount field.Int64 // 订单总金额(分) + DiscountAmount field.Int64 // 优惠券抵扣金额(分) + PointsAmount field.Int64 // 积分抵扣金额(分) + ActualAmount field.Int64 // 实际支付金额(分) + Status field.Int32 // 订单状态:1待支付 2已支付 3已取消 4已退款 + PayPreorderID field.Int64 // 关联预支付单ID(payment_preorder.id) + PaidAt field.Time // 支付完成时间 + CancelledAt field.Time // 取消时间 + UserAddressID field.Int64 // 收货地址ID(user_addresses.id) + IsConsumed field.Int32 // 是否已履约/消耗(对虚拟资产) + PointsLedgerID field.Int64 // 积分扣减流水ID(user_points_ledger.id) + Remark field.String // 备注 + + fieldMap map[string]field.Expr +} + +func (o orders) Table(newTableName string) *orders { + o.ordersDo.UseTable(newTableName) + return o.updateTableName(newTableName) +} + +func (o orders) As(alias string) *orders { + o.ordersDo.DO = *(o.ordersDo.As(alias).(*gen.DO)) + return o.updateTableName(alias) +} + +func (o *orders) updateTableName(table string) *orders { + o.ALL = field.NewAsterisk(table) + o.ID = field.NewInt64(table, "id") + o.CreatedAt = field.NewTime(table, "created_at") + o.UpdatedAt = field.NewTime(table, "updated_at") + o.UserID = field.NewInt64(table, "user_id") + o.OrderNo = field.NewString(table, "order_no") + o.SourceType = field.NewInt32(table, "source_type") + o.TotalAmount = field.NewInt64(table, "total_amount") + o.DiscountAmount = field.NewInt64(table, "discount_amount") + o.PointsAmount = field.NewInt64(table, "points_amount") + o.ActualAmount = field.NewInt64(table, "actual_amount") + o.Status = field.NewInt32(table, "status") + o.PayPreorderID = field.NewInt64(table, "pay_preorder_id") + o.PaidAt = field.NewTime(table, "paid_at") + o.CancelledAt = field.NewTime(table, "cancelled_at") + o.UserAddressID = field.NewInt64(table, "user_address_id") + o.IsConsumed = field.NewInt32(table, "is_consumed") + o.PointsLedgerID = field.NewInt64(table, "points_ledger_id") + o.Remark = field.NewString(table, "remark") + + o.fillFieldMap() + + return o +} + +func (o *orders) GetFieldByName(fieldName string) (field.OrderExpr, bool) { + _f, ok := o.fieldMap[fieldName] + if !ok || _f == nil { + return nil, false + } + _oe, ok := _f.(field.OrderExpr) + return _oe, ok +} + +func (o *orders) fillFieldMap() { + o.fieldMap = make(map[string]field.Expr, 18) + o.fieldMap["id"] = o.ID + o.fieldMap["created_at"] = o.CreatedAt + o.fieldMap["updated_at"] = o.UpdatedAt + o.fieldMap["user_id"] = o.UserID + o.fieldMap["order_no"] = o.OrderNo + o.fieldMap["source_type"] = o.SourceType + o.fieldMap["total_amount"] = o.TotalAmount + o.fieldMap["discount_amount"] = o.DiscountAmount + o.fieldMap["points_amount"] = o.PointsAmount + o.fieldMap["actual_amount"] = o.ActualAmount + o.fieldMap["status"] = o.Status + o.fieldMap["pay_preorder_id"] = o.PayPreorderID + o.fieldMap["paid_at"] = o.PaidAt + o.fieldMap["cancelled_at"] = o.CancelledAt + o.fieldMap["user_address_id"] = o.UserAddressID + o.fieldMap["is_consumed"] = o.IsConsumed + o.fieldMap["points_ledger_id"] = o.PointsLedgerID + o.fieldMap["remark"] = o.Remark +} + +func (o orders) clone(db *gorm.DB) orders { + o.ordersDo.ReplaceConnPool(db.Statement.ConnPool) + return o +} + +func (o orders) replaceDB(db *gorm.DB) orders { + o.ordersDo.ReplaceDB(db) + return o +} + +type ordersDo struct{ gen.DO } + +func (o ordersDo) Debug() *ordersDo { + return o.withDO(o.DO.Debug()) +} + +func (o ordersDo) WithContext(ctx context.Context) *ordersDo { + return o.withDO(o.DO.WithContext(ctx)) +} + +func (o ordersDo) ReadDB() *ordersDo { + return o.Clauses(dbresolver.Read) +} + +func (o ordersDo) WriteDB() *ordersDo { + return o.Clauses(dbresolver.Write) +} + +func (o ordersDo) Session(config *gorm.Session) *ordersDo { + return o.withDO(o.DO.Session(config)) +} + +func (o ordersDo) Clauses(conds ...clause.Expression) *ordersDo { + return o.withDO(o.DO.Clauses(conds...)) +} + +func (o ordersDo) Returning(value interface{}, columns ...string) *ordersDo { + return o.withDO(o.DO.Returning(value, columns...)) +} + +func (o ordersDo) Not(conds ...gen.Condition) *ordersDo { + return o.withDO(o.DO.Not(conds...)) +} + +func (o ordersDo) Or(conds ...gen.Condition) *ordersDo { + return o.withDO(o.DO.Or(conds...)) +} + +func (o ordersDo) Select(conds ...field.Expr) *ordersDo { + return o.withDO(o.DO.Select(conds...)) +} + +func (o ordersDo) Where(conds ...gen.Condition) *ordersDo { + return o.withDO(o.DO.Where(conds...)) +} + +func (o ordersDo) Order(conds ...field.Expr) *ordersDo { + return o.withDO(o.DO.Order(conds...)) +} + +func (o ordersDo) Distinct(cols ...field.Expr) *ordersDo { + return o.withDO(o.DO.Distinct(cols...)) +} + +func (o ordersDo) Omit(cols ...field.Expr) *ordersDo { + return o.withDO(o.DO.Omit(cols...)) +} + +func (o ordersDo) Join(table schema.Tabler, on ...field.Expr) *ordersDo { + return o.withDO(o.DO.Join(table, on...)) +} + +func (o ordersDo) LeftJoin(table schema.Tabler, on ...field.Expr) *ordersDo { + return o.withDO(o.DO.LeftJoin(table, on...)) +} + +func (o ordersDo) RightJoin(table schema.Tabler, on ...field.Expr) *ordersDo { + return o.withDO(o.DO.RightJoin(table, on...)) +} + +func (o ordersDo) Group(cols ...field.Expr) *ordersDo { + return o.withDO(o.DO.Group(cols...)) +} + +func (o ordersDo) Having(conds ...gen.Condition) *ordersDo { + return o.withDO(o.DO.Having(conds...)) +} + +func (o ordersDo) Limit(limit int) *ordersDo { + return o.withDO(o.DO.Limit(limit)) +} + +func (o ordersDo) Offset(offset int) *ordersDo { + return o.withDO(o.DO.Offset(offset)) +} + +func (o ordersDo) Scopes(funcs ...func(gen.Dao) gen.Dao) *ordersDo { + return o.withDO(o.DO.Scopes(funcs...)) +} + +func (o ordersDo) Unscoped() *ordersDo { + return o.withDO(o.DO.Unscoped()) +} + +func (o ordersDo) Create(values ...*model.Orders) error { + if len(values) == 0 { + return nil + } + return o.DO.Create(values) +} + +func (o ordersDo) CreateInBatches(values []*model.Orders, batchSize int) error { + return o.DO.CreateInBatches(values, batchSize) +} + +// Save : !!! underlying implementation is different with GORM +// The method is equivalent to executing the statement: db.Clauses(clause.OnConflict{UpdateAll: true}).Create(values) +func (o ordersDo) Save(values ...*model.Orders) error { + if len(values) == 0 { + return nil + } + return o.DO.Save(values) +} + +func (o ordersDo) First() (*model.Orders, error) { + if result, err := o.DO.First(); err != nil { + return nil, err + } else { + return result.(*model.Orders), nil + } +} + +func (o ordersDo) Take() (*model.Orders, error) { + if result, err := o.DO.Take(); err != nil { + return nil, err + } else { + return result.(*model.Orders), nil + } +} + +func (o ordersDo) Last() (*model.Orders, error) { + if result, err := o.DO.Last(); err != nil { + return nil, err + } else { + return result.(*model.Orders), nil + } +} + +func (o ordersDo) Find() ([]*model.Orders, error) { + result, err := o.DO.Find() + return result.([]*model.Orders), err +} + +func (o ordersDo) FindInBatch(batchSize int, fc func(tx gen.Dao, batch int) error) (results []*model.Orders, err error) { + buf := make([]*model.Orders, 0, batchSize) + err = o.DO.FindInBatches(&buf, batchSize, func(tx gen.Dao, batch int) error { + defer func() { results = append(results, buf...) }() + return fc(tx, batch) + }) + return results, err +} + +func (o ordersDo) FindInBatches(result *[]*model.Orders, batchSize int, fc func(tx gen.Dao, batch int) error) error { + return o.DO.FindInBatches(result, batchSize, fc) +} + +func (o ordersDo) Attrs(attrs ...field.AssignExpr) *ordersDo { + return o.withDO(o.DO.Attrs(attrs...)) +} + +func (o ordersDo) Assign(attrs ...field.AssignExpr) *ordersDo { + return o.withDO(o.DO.Assign(attrs...)) +} + +func (o ordersDo) Joins(fields ...field.RelationField) *ordersDo { + for _, _f := range fields { + o = *o.withDO(o.DO.Joins(_f)) + } + return &o +} + +func (o ordersDo) Preload(fields ...field.RelationField) *ordersDo { + for _, _f := range fields { + o = *o.withDO(o.DO.Preload(_f)) + } + return &o +} + +func (o ordersDo) FirstOrInit() (*model.Orders, error) { + if result, err := o.DO.FirstOrInit(); err != nil { + return nil, err + } else { + return result.(*model.Orders), nil + } +} + +func (o ordersDo) FirstOrCreate() (*model.Orders, error) { + if result, err := o.DO.FirstOrCreate(); err != nil { + return nil, err + } else { + return result.(*model.Orders), nil + } +} + +func (o ordersDo) FindByPage(offset int, limit int) (result []*model.Orders, count int64, err error) { + result, err = o.Offset(offset).Limit(limit).Find() + if err != nil { + return + } + + if size := len(result); 0 < limit && 0 < size && size < limit { + count = int64(size + offset) + return + } + + count, err = o.Offset(-1).Limit(-1).Count() + return +} + +func (o ordersDo) ScanByPage(result interface{}, offset int, limit int) (count int64, err error) { + count, err = o.Count() + if err != nil { + return + } + + err = o.Offset(offset).Limit(limit).Scan(result) + return +} + +func (o ordersDo) Scan(result interface{}) (err error) { + return o.DO.Scan(result) +} + +func (o ordersDo) Delete(models ...*model.Orders) (result gen.ResultInfo, err error) { + return o.DO.Delete(models) +} + +func (o *ordersDo) withDO(do gen.Dao) *ordersDo { + o.DO = *do.(*gen.DO) + return o +} diff --git a/internal/repository/mysql/dao/product_categories.gen.go b/internal/repository/mysql/dao/product_categories.gen.go new file mode 100644 index 0000000..ae07a63 --- /dev/null +++ b/internal/repository/mysql/dao/product_categories.gen.go @@ -0,0 +1,340 @@ +// Code generated by gorm.io/gen. DO NOT EDIT. +// Code generated by gorm.io/gen. DO NOT EDIT. +// Code generated by gorm.io/gen. DO NOT EDIT. + +package dao + +import ( + "context" + + "gorm.io/gorm" + "gorm.io/gorm/clause" + "gorm.io/gorm/schema" + + "gorm.io/gen" + "gorm.io/gen/field" + + "gorm.io/plugin/dbresolver" + + "bindbox-game/internal/repository/mysql/model" +) + +func newProductCategories(db *gorm.DB, opts ...gen.DOOption) productCategories { + _productCategories := productCategories{} + + _productCategories.productCategoriesDo.UseDB(db, opts...) + _productCategories.productCategoriesDo.UseModel(&model.ProductCategories{}) + + tableName := _productCategories.productCategoriesDo.TableName() + _productCategories.ALL = field.NewAsterisk(tableName) + _productCategories.ID = field.NewInt64(tableName, "id") + _productCategories.CreatedAt = field.NewTime(tableName, "created_at") + _productCategories.UpdatedAt = field.NewTime(tableName, "updated_at") + _productCategories.Name = field.NewString(tableName, "name") + _productCategories.ParentID = field.NewInt64(tableName, "parent_id") + _productCategories.Status = field.NewInt32(tableName, "status") + + _productCategories.fillFieldMap() + + return _productCategories +} + +// productCategories 商品分类 +type productCategories struct { + productCategoriesDo + + ALL field.Asterisk + ID field.Int64 // 主键ID + CreatedAt field.Time // 创建时间 + UpdatedAt field.Time // 更新时间 + Name field.String // 分类名称 + ParentID field.Int64 // 父分类ID(可空) + Status field.Int32 // 状态:1启用 2禁用 + + fieldMap map[string]field.Expr +} + +func (p productCategories) Table(newTableName string) *productCategories { + p.productCategoriesDo.UseTable(newTableName) + return p.updateTableName(newTableName) +} + +func (p productCategories) As(alias string) *productCategories { + p.productCategoriesDo.DO = *(p.productCategoriesDo.As(alias).(*gen.DO)) + return p.updateTableName(alias) +} + +func (p *productCategories) updateTableName(table string) *productCategories { + p.ALL = field.NewAsterisk(table) + p.ID = field.NewInt64(table, "id") + p.CreatedAt = field.NewTime(table, "created_at") + p.UpdatedAt = field.NewTime(table, "updated_at") + p.Name = field.NewString(table, "name") + p.ParentID = field.NewInt64(table, "parent_id") + p.Status = field.NewInt32(table, "status") + + p.fillFieldMap() + + return p +} + +func (p *productCategories) GetFieldByName(fieldName string) (field.OrderExpr, bool) { + _f, ok := p.fieldMap[fieldName] + if !ok || _f == nil { + return nil, false + } + _oe, ok := _f.(field.OrderExpr) + return _oe, ok +} + +func (p *productCategories) fillFieldMap() { + p.fieldMap = make(map[string]field.Expr, 6) + p.fieldMap["id"] = p.ID + p.fieldMap["created_at"] = p.CreatedAt + p.fieldMap["updated_at"] = p.UpdatedAt + p.fieldMap["name"] = p.Name + p.fieldMap["parent_id"] = p.ParentID + p.fieldMap["status"] = p.Status +} + +func (p productCategories) clone(db *gorm.DB) productCategories { + p.productCategoriesDo.ReplaceConnPool(db.Statement.ConnPool) + return p +} + +func (p productCategories) replaceDB(db *gorm.DB) productCategories { + p.productCategoriesDo.ReplaceDB(db) + return p +} + +type productCategoriesDo struct{ gen.DO } + +func (p productCategoriesDo) Debug() *productCategoriesDo { + return p.withDO(p.DO.Debug()) +} + +func (p productCategoriesDo) WithContext(ctx context.Context) *productCategoriesDo { + return p.withDO(p.DO.WithContext(ctx)) +} + +func (p productCategoriesDo) ReadDB() *productCategoriesDo { + return p.Clauses(dbresolver.Read) +} + +func (p productCategoriesDo) WriteDB() *productCategoriesDo { + return p.Clauses(dbresolver.Write) +} + +func (p productCategoriesDo) Session(config *gorm.Session) *productCategoriesDo { + return p.withDO(p.DO.Session(config)) +} + +func (p productCategoriesDo) Clauses(conds ...clause.Expression) *productCategoriesDo { + return p.withDO(p.DO.Clauses(conds...)) +} + +func (p productCategoriesDo) Returning(value interface{}, columns ...string) *productCategoriesDo { + return p.withDO(p.DO.Returning(value, columns...)) +} + +func (p productCategoriesDo) Not(conds ...gen.Condition) *productCategoriesDo { + return p.withDO(p.DO.Not(conds...)) +} + +func (p productCategoriesDo) Or(conds ...gen.Condition) *productCategoriesDo { + return p.withDO(p.DO.Or(conds...)) +} + +func (p productCategoriesDo) Select(conds ...field.Expr) *productCategoriesDo { + return p.withDO(p.DO.Select(conds...)) +} + +func (p productCategoriesDo) Where(conds ...gen.Condition) *productCategoriesDo { + return p.withDO(p.DO.Where(conds...)) +} + +func (p productCategoriesDo) Order(conds ...field.Expr) *productCategoriesDo { + return p.withDO(p.DO.Order(conds...)) +} + +func (p productCategoriesDo) Distinct(cols ...field.Expr) *productCategoriesDo { + return p.withDO(p.DO.Distinct(cols...)) +} + +func (p productCategoriesDo) Omit(cols ...field.Expr) *productCategoriesDo { + return p.withDO(p.DO.Omit(cols...)) +} + +func (p productCategoriesDo) Join(table schema.Tabler, on ...field.Expr) *productCategoriesDo { + return p.withDO(p.DO.Join(table, on...)) +} + +func (p productCategoriesDo) LeftJoin(table schema.Tabler, on ...field.Expr) *productCategoriesDo { + return p.withDO(p.DO.LeftJoin(table, on...)) +} + +func (p productCategoriesDo) RightJoin(table schema.Tabler, on ...field.Expr) *productCategoriesDo { + return p.withDO(p.DO.RightJoin(table, on...)) +} + +func (p productCategoriesDo) Group(cols ...field.Expr) *productCategoriesDo { + return p.withDO(p.DO.Group(cols...)) +} + +func (p productCategoriesDo) Having(conds ...gen.Condition) *productCategoriesDo { + return p.withDO(p.DO.Having(conds...)) +} + +func (p productCategoriesDo) Limit(limit int) *productCategoriesDo { + return p.withDO(p.DO.Limit(limit)) +} + +func (p productCategoriesDo) Offset(offset int) *productCategoriesDo { + return p.withDO(p.DO.Offset(offset)) +} + +func (p productCategoriesDo) Scopes(funcs ...func(gen.Dao) gen.Dao) *productCategoriesDo { + return p.withDO(p.DO.Scopes(funcs...)) +} + +func (p productCategoriesDo) Unscoped() *productCategoriesDo { + return p.withDO(p.DO.Unscoped()) +} + +func (p productCategoriesDo) Create(values ...*model.ProductCategories) error { + if len(values) == 0 { + return nil + } + return p.DO.Create(values) +} + +func (p productCategoriesDo) CreateInBatches(values []*model.ProductCategories, batchSize int) error { + return p.DO.CreateInBatches(values, batchSize) +} + +// Save : !!! underlying implementation is different with GORM +// The method is equivalent to executing the statement: db.Clauses(clause.OnConflict{UpdateAll: true}).Create(values) +func (p productCategoriesDo) Save(values ...*model.ProductCategories) error { + if len(values) == 0 { + return nil + } + return p.DO.Save(values) +} + +func (p productCategoriesDo) First() (*model.ProductCategories, error) { + if result, err := p.DO.First(); err != nil { + return nil, err + } else { + return result.(*model.ProductCategories), nil + } +} + +func (p productCategoriesDo) Take() (*model.ProductCategories, error) { + if result, err := p.DO.Take(); err != nil { + return nil, err + } else { + return result.(*model.ProductCategories), nil + } +} + +func (p productCategoriesDo) Last() (*model.ProductCategories, error) { + if result, err := p.DO.Last(); err != nil { + return nil, err + } else { + return result.(*model.ProductCategories), nil + } +} + +func (p productCategoriesDo) Find() ([]*model.ProductCategories, error) { + result, err := p.DO.Find() + return result.([]*model.ProductCategories), err +} + +func (p productCategoriesDo) FindInBatch(batchSize int, fc func(tx gen.Dao, batch int) error) (results []*model.ProductCategories, err error) { + buf := make([]*model.ProductCategories, 0, batchSize) + err = p.DO.FindInBatches(&buf, batchSize, func(tx gen.Dao, batch int) error { + defer func() { results = append(results, buf...) }() + return fc(tx, batch) + }) + return results, err +} + +func (p productCategoriesDo) FindInBatches(result *[]*model.ProductCategories, batchSize int, fc func(tx gen.Dao, batch int) error) error { + return p.DO.FindInBatches(result, batchSize, fc) +} + +func (p productCategoriesDo) Attrs(attrs ...field.AssignExpr) *productCategoriesDo { + return p.withDO(p.DO.Attrs(attrs...)) +} + +func (p productCategoriesDo) Assign(attrs ...field.AssignExpr) *productCategoriesDo { + return p.withDO(p.DO.Assign(attrs...)) +} + +func (p productCategoriesDo) Joins(fields ...field.RelationField) *productCategoriesDo { + for _, _f := range fields { + p = *p.withDO(p.DO.Joins(_f)) + } + return &p +} + +func (p productCategoriesDo) Preload(fields ...field.RelationField) *productCategoriesDo { + for _, _f := range fields { + p = *p.withDO(p.DO.Preload(_f)) + } + return &p +} + +func (p productCategoriesDo) FirstOrInit() (*model.ProductCategories, error) { + if result, err := p.DO.FirstOrInit(); err != nil { + return nil, err + } else { + return result.(*model.ProductCategories), nil + } +} + +func (p productCategoriesDo) FirstOrCreate() (*model.ProductCategories, error) { + if result, err := p.DO.FirstOrCreate(); err != nil { + return nil, err + } else { + return result.(*model.ProductCategories), nil + } +} + +func (p productCategoriesDo) FindByPage(offset int, limit int) (result []*model.ProductCategories, count int64, err error) { + result, err = p.Offset(offset).Limit(limit).Find() + if err != nil { + return + } + + if size := len(result); 0 < limit && 0 < size && size < limit { + count = int64(size + offset) + return + } + + count, err = p.Offset(-1).Limit(-1).Count() + return +} + +func (p productCategoriesDo) ScanByPage(result interface{}, offset int, limit int) (count int64, err error) { + count, err = p.Count() + if err != nil { + return + } + + err = p.Offset(offset).Limit(limit).Scan(result) + return +} + +func (p productCategoriesDo) Scan(result interface{}) (err error) { + return p.DO.Scan(result) +} + +func (p productCategoriesDo) Delete(models ...*model.ProductCategories) (result gen.ResultInfo, err error) { + return p.DO.Delete(models) +} + +func (p *productCategoriesDo) withDO(do gen.Dao) *productCategoriesDo { + p.DO = *do.(*gen.DO) + return p +} diff --git a/internal/repository/mysql/dao/products.gen.go b/internal/repository/mysql/dao/products.gen.go new file mode 100644 index 0000000..04df134 --- /dev/null +++ b/internal/repository/mysql/dao/products.gen.go @@ -0,0 +1,356 @@ +// Code generated by gorm.io/gen. DO NOT EDIT. +// Code generated by gorm.io/gen. DO NOT EDIT. +// Code generated by gorm.io/gen. DO NOT EDIT. + +package dao + +import ( + "context" + + "gorm.io/gorm" + "gorm.io/gorm/clause" + "gorm.io/gorm/schema" + + "gorm.io/gen" + "gorm.io/gen/field" + + "gorm.io/plugin/dbresolver" + + "bindbox-game/internal/repository/mysql/model" +) + +func newProducts(db *gorm.DB, opts ...gen.DOOption) products { + _products := products{} + + _products.productsDo.UseDB(db, opts...) + _products.productsDo.UseModel(&model.Products{}) + + tableName := _products.productsDo.TableName() + _products.ALL = field.NewAsterisk(tableName) + _products.ID = field.NewInt64(tableName, "id") + _products.CreatedAt = field.NewTime(tableName, "created_at") + _products.UpdatedAt = field.NewTime(tableName, "updated_at") + _products.Name = field.NewString(tableName, "name") + _products.CategoryID = field.NewInt64(tableName, "category_id") + _products.ImagesJSON = field.NewString(tableName, "images_json") + _products.Price = field.NewInt64(tableName, "price") + _products.Stock = field.NewInt64(tableName, "stock") + _products.Sales = field.NewInt64(tableName, "sales") + _products.Status = field.NewInt32(tableName, "status") + + _products.fillFieldMap() + + return _products +} + +// products 商品 +type products struct { + productsDo + + ALL field.Asterisk + ID field.Int64 // 主键ID + CreatedAt field.Time // 创建时间 + UpdatedAt field.Time // 更新时间 + Name field.String // 商品名称 + CategoryID field.Int64 // 单一主分类ID(product_categories.id) + ImagesJSON field.String // 商品图片JSON(数组) + Price field.Int64 // 商品售价(分) + Stock field.Int64 // 可售库存 + Sales field.Int64 // 已售数量 + Status field.Int32 // 上下架状态:1上架 2下架 + + fieldMap map[string]field.Expr +} + +func (p products) Table(newTableName string) *products { + p.productsDo.UseTable(newTableName) + return p.updateTableName(newTableName) +} + +func (p products) As(alias string) *products { + p.productsDo.DO = *(p.productsDo.As(alias).(*gen.DO)) + return p.updateTableName(alias) +} + +func (p *products) updateTableName(table string) *products { + p.ALL = field.NewAsterisk(table) + p.ID = field.NewInt64(table, "id") + p.CreatedAt = field.NewTime(table, "created_at") + p.UpdatedAt = field.NewTime(table, "updated_at") + p.Name = field.NewString(table, "name") + p.CategoryID = field.NewInt64(table, "category_id") + p.ImagesJSON = field.NewString(table, "images_json") + p.Price = field.NewInt64(table, "price") + p.Stock = field.NewInt64(table, "stock") + p.Sales = field.NewInt64(table, "sales") + p.Status = field.NewInt32(table, "status") + + p.fillFieldMap() + + return p +} + +func (p *products) GetFieldByName(fieldName string) (field.OrderExpr, bool) { + _f, ok := p.fieldMap[fieldName] + if !ok || _f == nil { + return nil, false + } + _oe, ok := _f.(field.OrderExpr) + return _oe, ok +} + +func (p *products) fillFieldMap() { + p.fieldMap = make(map[string]field.Expr, 10) + p.fieldMap["id"] = p.ID + p.fieldMap["created_at"] = p.CreatedAt + p.fieldMap["updated_at"] = p.UpdatedAt + p.fieldMap["name"] = p.Name + p.fieldMap["category_id"] = p.CategoryID + p.fieldMap["images_json"] = p.ImagesJSON + p.fieldMap["price"] = p.Price + p.fieldMap["stock"] = p.Stock + p.fieldMap["sales"] = p.Sales + p.fieldMap["status"] = p.Status +} + +func (p products) clone(db *gorm.DB) products { + p.productsDo.ReplaceConnPool(db.Statement.ConnPool) + return p +} + +func (p products) replaceDB(db *gorm.DB) products { + p.productsDo.ReplaceDB(db) + return p +} + +type productsDo struct{ gen.DO } + +func (p productsDo) Debug() *productsDo { + return p.withDO(p.DO.Debug()) +} + +func (p productsDo) WithContext(ctx context.Context) *productsDo { + return p.withDO(p.DO.WithContext(ctx)) +} + +func (p productsDo) ReadDB() *productsDo { + return p.Clauses(dbresolver.Read) +} + +func (p productsDo) WriteDB() *productsDo { + return p.Clauses(dbresolver.Write) +} + +func (p productsDo) Session(config *gorm.Session) *productsDo { + return p.withDO(p.DO.Session(config)) +} + +func (p productsDo) Clauses(conds ...clause.Expression) *productsDo { + return p.withDO(p.DO.Clauses(conds...)) +} + +func (p productsDo) Returning(value interface{}, columns ...string) *productsDo { + return p.withDO(p.DO.Returning(value, columns...)) +} + +func (p productsDo) Not(conds ...gen.Condition) *productsDo { + return p.withDO(p.DO.Not(conds...)) +} + +func (p productsDo) Or(conds ...gen.Condition) *productsDo { + return p.withDO(p.DO.Or(conds...)) +} + +func (p productsDo) Select(conds ...field.Expr) *productsDo { + return p.withDO(p.DO.Select(conds...)) +} + +func (p productsDo) Where(conds ...gen.Condition) *productsDo { + return p.withDO(p.DO.Where(conds...)) +} + +func (p productsDo) Order(conds ...field.Expr) *productsDo { + return p.withDO(p.DO.Order(conds...)) +} + +func (p productsDo) Distinct(cols ...field.Expr) *productsDo { + return p.withDO(p.DO.Distinct(cols...)) +} + +func (p productsDo) Omit(cols ...field.Expr) *productsDo { + return p.withDO(p.DO.Omit(cols...)) +} + +func (p productsDo) Join(table schema.Tabler, on ...field.Expr) *productsDo { + return p.withDO(p.DO.Join(table, on...)) +} + +func (p productsDo) LeftJoin(table schema.Tabler, on ...field.Expr) *productsDo { + return p.withDO(p.DO.LeftJoin(table, on...)) +} + +func (p productsDo) RightJoin(table schema.Tabler, on ...field.Expr) *productsDo { + return p.withDO(p.DO.RightJoin(table, on...)) +} + +func (p productsDo) Group(cols ...field.Expr) *productsDo { + return p.withDO(p.DO.Group(cols...)) +} + +func (p productsDo) Having(conds ...gen.Condition) *productsDo { + return p.withDO(p.DO.Having(conds...)) +} + +func (p productsDo) Limit(limit int) *productsDo { + return p.withDO(p.DO.Limit(limit)) +} + +func (p productsDo) Offset(offset int) *productsDo { + return p.withDO(p.DO.Offset(offset)) +} + +func (p productsDo) Scopes(funcs ...func(gen.Dao) gen.Dao) *productsDo { + return p.withDO(p.DO.Scopes(funcs...)) +} + +func (p productsDo) Unscoped() *productsDo { + return p.withDO(p.DO.Unscoped()) +} + +func (p productsDo) Create(values ...*model.Products) error { + if len(values) == 0 { + return nil + } + return p.DO.Create(values) +} + +func (p productsDo) CreateInBatches(values []*model.Products, batchSize int) error { + return p.DO.CreateInBatches(values, batchSize) +} + +// Save : !!! underlying implementation is different with GORM +// The method is equivalent to executing the statement: db.Clauses(clause.OnConflict{UpdateAll: true}).Create(values) +func (p productsDo) Save(values ...*model.Products) error { + if len(values) == 0 { + return nil + } + return p.DO.Save(values) +} + +func (p productsDo) First() (*model.Products, error) { + if result, err := p.DO.First(); err != nil { + return nil, err + } else { + return result.(*model.Products), nil + } +} + +func (p productsDo) Take() (*model.Products, error) { + if result, err := p.DO.Take(); err != nil { + return nil, err + } else { + return result.(*model.Products), nil + } +} + +func (p productsDo) Last() (*model.Products, error) { + if result, err := p.DO.Last(); err != nil { + return nil, err + } else { + return result.(*model.Products), nil + } +} + +func (p productsDo) Find() ([]*model.Products, error) { + result, err := p.DO.Find() + return result.([]*model.Products), err +} + +func (p productsDo) FindInBatch(batchSize int, fc func(tx gen.Dao, batch int) error) (results []*model.Products, err error) { + buf := make([]*model.Products, 0, batchSize) + err = p.DO.FindInBatches(&buf, batchSize, func(tx gen.Dao, batch int) error { + defer func() { results = append(results, buf...) }() + return fc(tx, batch) + }) + return results, err +} + +func (p productsDo) FindInBatches(result *[]*model.Products, batchSize int, fc func(tx gen.Dao, batch int) error) error { + return p.DO.FindInBatches(result, batchSize, fc) +} + +func (p productsDo) Attrs(attrs ...field.AssignExpr) *productsDo { + return p.withDO(p.DO.Attrs(attrs...)) +} + +func (p productsDo) Assign(attrs ...field.AssignExpr) *productsDo { + return p.withDO(p.DO.Assign(attrs...)) +} + +func (p productsDo) Joins(fields ...field.RelationField) *productsDo { + for _, _f := range fields { + p = *p.withDO(p.DO.Joins(_f)) + } + return &p +} + +func (p productsDo) Preload(fields ...field.RelationField) *productsDo { + for _, _f := range fields { + p = *p.withDO(p.DO.Preload(_f)) + } + return &p +} + +func (p productsDo) FirstOrInit() (*model.Products, error) { + if result, err := p.DO.FirstOrInit(); err != nil { + return nil, err + } else { + return result.(*model.Products), nil + } +} + +func (p productsDo) FirstOrCreate() (*model.Products, error) { + if result, err := p.DO.FirstOrCreate(); err != nil { + return nil, err + } else { + return result.(*model.Products), nil + } +} + +func (p productsDo) FindByPage(offset int, limit int) (result []*model.Products, count int64, err error) { + result, err = p.Offset(offset).Limit(limit).Find() + if err != nil { + return + } + + if size := len(result); 0 < limit && 0 < size && size < limit { + count = int64(size + offset) + return + } + + count, err = p.Offset(-1).Limit(-1).Count() + return +} + +func (p productsDo) ScanByPage(result interface{}, offset int, limit int) (count int64, err error) { + count, err = p.Count() + if err != nil { + return + } + + err = p.Offset(offset).Limit(limit).Scan(result) + return +} + +func (p productsDo) Scan(result interface{}) (err error) { + return p.DO.Scan(result) +} + +func (p productsDo) Delete(models ...*model.Products) (result gen.ResultInfo, err error) { + return p.DO.Delete(models) +} + +func (p *productsDo) withDO(do gen.Dao) *productsDo { + p.DO = *do.(*gen.DO) + return p +} diff --git a/internal/repository/mysql/dao/role_actions.gen.go b/internal/repository/mysql/dao/role_actions.gen.go new file mode 100644 index 0000000..f055f1e --- /dev/null +++ b/internal/repository/mysql/dao/role_actions.gen.go @@ -0,0 +1,343 @@ +// Code generated by gorm.io/gen. DO NOT EDIT. +// Code generated by gorm.io/gen. DO NOT EDIT. +// Code generated by gorm.io/gen. DO NOT EDIT. + +package dao + +import ( + "context" + + "gorm.io/gorm" + "gorm.io/gorm/clause" + "gorm.io/gorm/schema" + + "gorm.io/gen" + "gorm.io/gen/field" + + "gorm.io/plugin/dbresolver" + + "bindbox-game/internal/repository/mysql/model" +) + +func newRoleActions(db *gorm.DB, opts ...gen.DOOption) roleActions { + _roleActions := roleActions{} + + _roleActions.roleActionsDo.UseDB(db, opts...) + _roleActions.roleActionsDo.UseModel(&model.RoleActions{}) + + tableName := _roleActions.roleActionsDo.TableName() + _roleActions.ALL = field.NewAsterisk(tableName) + _roleActions.ID = field.NewInt64(tableName, "id") + _roleActions.RoleID = field.NewInt64(tableName, "role_id") + _roleActions.ActionID = field.NewInt64(tableName, "action_id") + _roleActions.CreatedUser = field.NewString(tableName, "created_user") + _roleActions.UpdatedUser = field.NewString(tableName, "updated_user") + _roleActions.CreatedAt = field.NewTime(tableName, "created_at") + _roleActions.UpdatedAt = field.NewTime(tableName, "updated_at") + + _roleActions.fillFieldMap() + + return _roleActions +} + +type roleActions struct { + roleActionsDo + + ALL field.Asterisk + ID field.Int64 + RoleID field.Int64 + ActionID field.Int64 + CreatedUser field.String + UpdatedUser field.String + CreatedAt field.Time + UpdatedAt field.Time + + fieldMap map[string]field.Expr +} + +func (r roleActions) Table(newTableName string) *roleActions { + r.roleActionsDo.UseTable(newTableName) + return r.updateTableName(newTableName) +} + +func (r roleActions) As(alias string) *roleActions { + r.roleActionsDo.DO = *(r.roleActionsDo.As(alias).(*gen.DO)) + return r.updateTableName(alias) +} + +func (r *roleActions) updateTableName(table string) *roleActions { + r.ALL = field.NewAsterisk(table) + r.ID = field.NewInt64(table, "id") + r.RoleID = field.NewInt64(table, "role_id") + r.ActionID = field.NewInt64(table, "action_id") + r.CreatedUser = field.NewString(table, "created_user") + r.UpdatedUser = field.NewString(table, "updated_user") + r.CreatedAt = field.NewTime(table, "created_at") + r.UpdatedAt = field.NewTime(table, "updated_at") + + r.fillFieldMap() + + return r +} + +func (r *roleActions) GetFieldByName(fieldName string) (field.OrderExpr, bool) { + _f, ok := r.fieldMap[fieldName] + if !ok || _f == nil { + return nil, false + } + _oe, ok := _f.(field.OrderExpr) + return _oe, ok +} + +func (r *roleActions) fillFieldMap() { + r.fieldMap = make(map[string]field.Expr, 7) + r.fieldMap["id"] = r.ID + r.fieldMap["role_id"] = r.RoleID + r.fieldMap["action_id"] = r.ActionID + r.fieldMap["created_user"] = r.CreatedUser + r.fieldMap["updated_user"] = r.UpdatedUser + r.fieldMap["created_at"] = r.CreatedAt + r.fieldMap["updated_at"] = r.UpdatedAt +} + +func (r roleActions) clone(db *gorm.DB) roleActions { + r.roleActionsDo.ReplaceConnPool(db.Statement.ConnPool) + return r +} + +func (r roleActions) replaceDB(db *gorm.DB) roleActions { + r.roleActionsDo.ReplaceDB(db) + return r +} + +type roleActionsDo struct{ gen.DO } + +func (r roleActionsDo) Debug() *roleActionsDo { + return r.withDO(r.DO.Debug()) +} + +func (r roleActionsDo) WithContext(ctx context.Context) *roleActionsDo { + return r.withDO(r.DO.WithContext(ctx)) +} + +func (r roleActionsDo) ReadDB() *roleActionsDo { + return r.Clauses(dbresolver.Read) +} + +func (r roleActionsDo) WriteDB() *roleActionsDo { + return r.Clauses(dbresolver.Write) +} + +func (r roleActionsDo) Session(config *gorm.Session) *roleActionsDo { + return r.withDO(r.DO.Session(config)) +} + +func (r roleActionsDo) Clauses(conds ...clause.Expression) *roleActionsDo { + return r.withDO(r.DO.Clauses(conds...)) +} + +func (r roleActionsDo) Returning(value interface{}, columns ...string) *roleActionsDo { + return r.withDO(r.DO.Returning(value, columns...)) +} + +func (r roleActionsDo) Not(conds ...gen.Condition) *roleActionsDo { + return r.withDO(r.DO.Not(conds...)) +} + +func (r roleActionsDo) Or(conds ...gen.Condition) *roleActionsDo { + return r.withDO(r.DO.Or(conds...)) +} + +func (r roleActionsDo) Select(conds ...field.Expr) *roleActionsDo { + return r.withDO(r.DO.Select(conds...)) +} + +func (r roleActionsDo) Where(conds ...gen.Condition) *roleActionsDo { + return r.withDO(r.DO.Where(conds...)) +} + +func (r roleActionsDo) Order(conds ...field.Expr) *roleActionsDo { + return r.withDO(r.DO.Order(conds...)) +} + +func (r roleActionsDo) Distinct(cols ...field.Expr) *roleActionsDo { + return r.withDO(r.DO.Distinct(cols...)) +} + +func (r roleActionsDo) Omit(cols ...field.Expr) *roleActionsDo { + return r.withDO(r.DO.Omit(cols...)) +} + +func (r roleActionsDo) Join(table schema.Tabler, on ...field.Expr) *roleActionsDo { + return r.withDO(r.DO.Join(table, on...)) +} + +func (r roleActionsDo) LeftJoin(table schema.Tabler, on ...field.Expr) *roleActionsDo { + return r.withDO(r.DO.LeftJoin(table, on...)) +} + +func (r roleActionsDo) RightJoin(table schema.Tabler, on ...field.Expr) *roleActionsDo { + return r.withDO(r.DO.RightJoin(table, on...)) +} + +func (r roleActionsDo) Group(cols ...field.Expr) *roleActionsDo { + return r.withDO(r.DO.Group(cols...)) +} + +func (r roleActionsDo) Having(conds ...gen.Condition) *roleActionsDo { + return r.withDO(r.DO.Having(conds...)) +} + +func (r roleActionsDo) Limit(limit int) *roleActionsDo { + return r.withDO(r.DO.Limit(limit)) +} + +func (r roleActionsDo) Offset(offset int) *roleActionsDo { + return r.withDO(r.DO.Offset(offset)) +} + +func (r roleActionsDo) Scopes(funcs ...func(gen.Dao) gen.Dao) *roleActionsDo { + return r.withDO(r.DO.Scopes(funcs...)) +} + +func (r roleActionsDo) Unscoped() *roleActionsDo { + return r.withDO(r.DO.Unscoped()) +} + +func (r roleActionsDo) Create(values ...*model.RoleActions) error { + if len(values) == 0 { + return nil + } + return r.DO.Create(values) +} + +func (r roleActionsDo) CreateInBatches(values []*model.RoleActions, batchSize int) error { + return r.DO.CreateInBatches(values, batchSize) +} + +// Save : !!! underlying implementation is different with GORM +// The method is equivalent to executing the statement: db.Clauses(clause.OnConflict{UpdateAll: true}).Create(values) +func (r roleActionsDo) Save(values ...*model.RoleActions) error { + if len(values) == 0 { + return nil + } + return r.DO.Save(values) +} + +func (r roleActionsDo) First() (*model.RoleActions, error) { + if result, err := r.DO.First(); err != nil { + return nil, err + } else { + return result.(*model.RoleActions), nil + } +} + +func (r roleActionsDo) Take() (*model.RoleActions, error) { + if result, err := r.DO.Take(); err != nil { + return nil, err + } else { + return result.(*model.RoleActions), nil + } +} + +func (r roleActionsDo) Last() (*model.RoleActions, error) { + if result, err := r.DO.Last(); err != nil { + return nil, err + } else { + return result.(*model.RoleActions), nil + } +} + +func (r roleActionsDo) Find() ([]*model.RoleActions, error) { + result, err := r.DO.Find() + return result.([]*model.RoleActions), err +} + +func (r roleActionsDo) FindInBatch(batchSize int, fc func(tx gen.Dao, batch int) error) (results []*model.RoleActions, err error) { + buf := make([]*model.RoleActions, 0, batchSize) + err = r.DO.FindInBatches(&buf, batchSize, func(tx gen.Dao, batch int) error { + defer func() { results = append(results, buf...) }() + return fc(tx, batch) + }) + return results, err +} + +func (r roleActionsDo) FindInBatches(result *[]*model.RoleActions, batchSize int, fc func(tx gen.Dao, batch int) error) error { + return r.DO.FindInBatches(result, batchSize, fc) +} + +func (r roleActionsDo) Attrs(attrs ...field.AssignExpr) *roleActionsDo { + return r.withDO(r.DO.Attrs(attrs...)) +} + +func (r roleActionsDo) Assign(attrs ...field.AssignExpr) *roleActionsDo { + return r.withDO(r.DO.Assign(attrs...)) +} + +func (r roleActionsDo) Joins(fields ...field.RelationField) *roleActionsDo { + for _, _f := range fields { + r = *r.withDO(r.DO.Joins(_f)) + } + return &r +} + +func (r roleActionsDo) Preload(fields ...field.RelationField) *roleActionsDo { + for _, _f := range fields { + r = *r.withDO(r.DO.Preload(_f)) + } + return &r +} + +func (r roleActionsDo) FirstOrInit() (*model.RoleActions, error) { + if result, err := r.DO.FirstOrInit(); err != nil { + return nil, err + } else { + return result.(*model.RoleActions), nil + } +} + +func (r roleActionsDo) FirstOrCreate() (*model.RoleActions, error) { + if result, err := r.DO.FirstOrCreate(); err != nil { + return nil, err + } else { + return result.(*model.RoleActions), nil + } +} + +func (r roleActionsDo) FindByPage(offset int, limit int) (result []*model.RoleActions, count int64, err error) { + result, err = r.Offset(offset).Limit(limit).Find() + if err != nil { + return + } + + if size := len(result); 0 < limit && 0 < size && size < limit { + count = int64(size + offset) + return + } + + count, err = r.Offset(-1).Limit(-1).Count() + return +} + +func (r roleActionsDo) ScanByPage(result interface{}, offset int, limit int) (count int64, err error) { + count, err = r.Count() + if err != nil { + return + } + + err = r.Offset(offset).Limit(limit).Scan(result) + return +} + +func (r roleActionsDo) Scan(result interface{}) (err error) { + return r.DO.Scan(result) +} + +func (r roleActionsDo) Delete(models ...*model.RoleActions) (result gen.ResultInfo, err error) { + return r.DO.Delete(models) +} + +func (r *roleActionsDo) withDO(do gen.Dao) *roleActionsDo { + r.DO = *do.(*gen.DO) + return r +} diff --git a/internal/repository/mysql/dao/role_menus.gen.go b/internal/repository/mysql/dao/role_menus.gen.go new file mode 100644 index 0000000..e8d031b --- /dev/null +++ b/internal/repository/mysql/dao/role_menus.gen.go @@ -0,0 +1,343 @@ +// Code generated by gorm.io/gen. DO NOT EDIT. +// Code generated by gorm.io/gen. DO NOT EDIT. +// Code generated by gorm.io/gen. DO NOT EDIT. + +package dao + +import ( + "context" + + "gorm.io/gorm" + "gorm.io/gorm/clause" + "gorm.io/gorm/schema" + + "gorm.io/gen" + "gorm.io/gen/field" + + "gorm.io/plugin/dbresolver" + + "bindbox-game/internal/repository/mysql/model" +) + +func newRoleMenus(db *gorm.DB, opts ...gen.DOOption) roleMenus { + _roleMenus := roleMenus{} + + _roleMenus.roleMenusDo.UseDB(db, opts...) + _roleMenus.roleMenusDo.UseModel(&model.RoleMenus{}) + + tableName := _roleMenus.roleMenusDo.TableName() + _roleMenus.ALL = field.NewAsterisk(tableName) + _roleMenus.ID = field.NewInt64(tableName, "id") + _roleMenus.RoleID = field.NewInt64(tableName, "role_id") + _roleMenus.MenuID = field.NewInt64(tableName, "menu_id") + _roleMenus.CreatedUser = field.NewString(tableName, "created_user") + _roleMenus.UpdatedUser = field.NewString(tableName, "updated_user") + _roleMenus.CreatedAt = field.NewTime(tableName, "created_at") + _roleMenus.UpdatedAt = field.NewTime(tableName, "updated_at") + + _roleMenus.fillFieldMap() + + return _roleMenus +} + +type roleMenus struct { + roleMenusDo + + ALL field.Asterisk + ID field.Int64 + RoleID field.Int64 + MenuID field.Int64 + CreatedUser field.String + UpdatedUser field.String + CreatedAt field.Time + UpdatedAt field.Time + + fieldMap map[string]field.Expr +} + +func (r roleMenus) Table(newTableName string) *roleMenus { + r.roleMenusDo.UseTable(newTableName) + return r.updateTableName(newTableName) +} + +func (r roleMenus) As(alias string) *roleMenus { + r.roleMenusDo.DO = *(r.roleMenusDo.As(alias).(*gen.DO)) + return r.updateTableName(alias) +} + +func (r *roleMenus) updateTableName(table string) *roleMenus { + r.ALL = field.NewAsterisk(table) + r.ID = field.NewInt64(table, "id") + r.RoleID = field.NewInt64(table, "role_id") + r.MenuID = field.NewInt64(table, "menu_id") + r.CreatedUser = field.NewString(table, "created_user") + r.UpdatedUser = field.NewString(table, "updated_user") + r.CreatedAt = field.NewTime(table, "created_at") + r.UpdatedAt = field.NewTime(table, "updated_at") + + r.fillFieldMap() + + return r +} + +func (r *roleMenus) GetFieldByName(fieldName string) (field.OrderExpr, bool) { + _f, ok := r.fieldMap[fieldName] + if !ok || _f == nil { + return nil, false + } + _oe, ok := _f.(field.OrderExpr) + return _oe, ok +} + +func (r *roleMenus) fillFieldMap() { + r.fieldMap = make(map[string]field.Expr, 7) + r.fieldMap["id"] = r.ID + r.fieldMap["role_id"] = r.RoleID + r.fieldMap["menu_id"] = r.MenuID + r.fieldMap["created_user"] = r.CreatedUser + r.fieldMap["updated_user"] = r.UpdatedUser + r.fieldMap["created_at"] = r.CreatedAt + r.fieldMap["updated_at"] = r.UpdatedAt +} + +func (r roleMenus) clone(db *gorm.DB) roleMenus { + r.roleMenusDo.ReplaceConnPool(db.Statement.ConnPool) + return r +} + +func (r roleMenus) replaceDB(db *gorm.DB) roleMenus { + r.roleMenusDo.ReplaceDB(db) + return r +} + +type roleMenusDo struct{ gen.DO } + +func (r roleMenusDo) Debug() *roleMenusDo { + return r.withDO(r.DO.Debug()) +} + +func (r roleMenusDo) WithContext(ctx context.Context) *roleMenusDo { + return r.withDO(r.DO.WithContext(ctx)) +} + +func (r roleMenusDo) ReadDB() *roleMenusDo { + return r.Clauses(dbresolver.Read) +} + +func (r roleMenusDo) WriteDB() *roleMenusDo { + return r.Clauses(dbresolver.Write) +} + +func (r roleMenusDo) Session(config *gorm.Session) *roleMenusDo { + return r.withDO(r.DO.Session(config)) +} + +func (r roleMenusDo) Clauses(conds ...clause.Expression) *roleMenusDo { + return r.withDO(r.DO.Clauses(conds...)) +} + +func (r roleMenusDo) Returning(value interface{}, columns ...string) *roleMenusDo { + return r.withDO(r.DO.Returning(value, columns...)) +} + +func (r roleMenusDo) Not(conds ...gen.Condition) *roleMenusDo { + return r.withDO(r.DO.Not(conds...)) +} + +func (r roleMenusDo) Or(conds ...gen.Condition) *roleMenusDo { + return r.withDO(r.DO.Or(conds...)) +} + +func (r roleMenusDo) Select(conds ...field.Expr) *roleMenusDo { + return r.withDO(r.DO.Select(conds...)) +} + +func (r roleMenusDo) Where(conds ...gen.Condition) *roleMenusDo { + return r.withDO(r.DO.Where(conds...)) +} + +func (r roleMenusDo) Order(conds ...field.Expr) *roleMenusDo { + return r.withDO(r.DO.Order(conds...)) +} + +func (r roleMenusDo) Distinct(cols ...field.Expr) *roleMenusDo { + return r.withDO(r.DO.Distinct(cols...)) +} + +func (r roleMenusDo) Omit(cols ...field.Expr) *roleMenusDo { + return r.withDO(r.DO.Omit(cols...)) +} + +func (r roleMenusDo) Join(table schema.Tabler, on ...field.Expr) *roleMenusDo { + return r.withDO(r.DO.Join(table, on...)) +} + +func (r roleMenusDo) LeftJoin(table schema.Tabler, on ...field.Expr) *roleMenusDo { + return r.withDO(r.DO.LeftJoin(table, on...)) +} + +func (r roleMenusDo) RightJoin(table schema.Tabler, on ...field.Expr) *roleMenusDo { + return r.withDO(r.DO.RightJoin(table, on...)) +} + +func (r roleMenusDo) Group(cols ...field.Expr) *roleMenusDo { + return r.withDO(r.DO.Group(cols...)) +} + +func (r roleMenusDo) Having(conds ...gen.Condition) *roleMenusDo { + return r.withDO(r.DO.Having(conds...)) +} + +func (r roleMenusDo) Limit(limit int) *roleMenusDo { + return r.withDO(r.DO.Limit(limit)) +} + +func (r roleMenusDo) Offset(offset int) *roleMenusDo { + return r.withDO(r.DO.Offset(offset)) +} + +func (r roleMenusDo) Scopes(funcs ...func(gen.Dao) gen.Dao) *roleMenusDo { + return r.withDO(r.DO.Scopes(funcs...)) +} + +func (r roleMenusDo) Unscoped() *roleMenusDo { + return r.withDO(r.DO.Unscoped()) +} + +func (r roleMenusDo) Create(values ...*model.RoleMenus) error { + if len(values) == 0 { + return nil + } + return r.DO.Create(values) +} + +func (r roleMenusDo) CreateInBatches(values []*model.RoleMenus, batchSize int) error { + return r.DO.CreateInBatches(values, batchSize) +} + +// Save : !!! underlying implementation is different with GORM +// The method is equivalent to executing the statement: db.Clauses(clause.OnConflict{UpdateAll: true}).Create(values) +func (r roleMenusDo) Save(values ...*model.RoleMenus) error { + if len(values) == 0 { + return nil + } + return r.DO.Save(values) +} + +func (r roleMenusDo) First() (*model.RoleMenus, error) { + if result, err := r.DO.First(); err != nil { + return nil, err + } else { + return result.(*model.RoleMenus), nil + } +} + +func (r roleMenusDo) Take() (*model.RoleMenus, error) { + if result, err := r.DO.Take(); err != nil { + return nil, err + } else { + return result.(*model.RoleMenus), nil + } +} + +func (r roleMenusDo) Last() (*model.RoleMenus, error) { + if result, err := r.DO.Last(); err != nil { + return nil, err + } else { + return result.(*model.RoleMenus), nil + } +} + +func (r roleMenusDo) Find() ([]*model.RoleMenus, error) { + result, err := r.DO.Find() + return result.([]*model.RoleMenus), err +} + +func (r roleMenusDo) FindInBatch(batchSize int, fc func(tx gen.Dao, batch int) error) (results []*model.RoleMenus, err error) { + buf := make([]*model.RoleMenus, 0, batchSize) + err = r.DO.FindInBatches(&buf, batchSize, func(tx gen.Dao, batch int) error { + defer func() { results = append(results, buf...) }() + return fc(tx, batch) + }) + return results, err +} + +func (r roleMenusDo) FindInBatches(result *[]*model.RoleMenus, batchSize int, fc func(tx gen.Dao, batch int) error) error { + return r.DO.FindInBatches(result, batchSize, fc) +} + +func (r roleMenusDo) Attrs(attrs ...field.AssignExpr) *roleMenusDo { + return r.withDO(r.DO.Attrs(attrs...)) +} + +func (r roleMenusDo) Assign(attrs ...field.AssignExpr) *roleMenusDo { + return r.withDO(r.DO.Assign(attrs...)) +} + +func (r roleMenusDo) Joins(fields ...field.RelationField) *roleMenusDo { + for _, _f := range fields { + r = *r.withDO(r.DO.Joins(_f)) + } + return &r +} + +func (r roleMenusDo) Preload(fields ...field.RelationField) *roleMenusDo { + for _, _f := range fields { + r = *r.withDO(r.DO.Preload(_f)) + } + return &r +} + +func (r roleMenusDo) FirstOrInit() (*model.RoleMenus, error) { + if result, err := r.DO.FirstOrInit(); err != nil { + return nil, err + } else { + return result.(*model.RoleMenus), nil + } +} + +func (r roleMenusDo) FirstOrCreate() (*model.RoleMenus, error) { + if result, err := r.DO.FirstOrCreate(); err != nil { + return nil, err + } else { + return result.(*model.RoleMenus), nil + } +} + +func (r roleMenusDo) FindByPage(offset int, limit int) (result []*model.RoleMenus, count int64, err error) { + result, err = r.Offset(offset).Limit(limit).Find() + if err != nil { + return + } + + if size := len(result); 0 < limit && 0 < size && size < limit { + count = int64(size + offset) + return + } + + count, err = r.Offset(-1).Limit(-1).Count() + return +} + +func (r roleMenusDo) ScanByPage(result interface{}, offset int, limit int) (count int64, err error) { + count, err = r.Count() + if err != nil { + return + } + + err = r.Offset(offset).Limit(limit).Scan(result) + return +} + +func (r roleMenusDo) Scan(result interface{}) (err error) { + return r.DO.Scan(result) +} + +func (r roleMenusDo) Delete(models ...*model.RoleMenus) (result gen.ResultInfo, err error) { + return r.DO.Delete(models) +} + +func (r *roleMenusDo) withDO(do gen.Dao) *roleMenusDo { + r.DO = *do.(*gen.DO) + return r +} diff --git a/internal/repository/mysql/dao/role_users.gen.go b/internal/repository/mysql/dao/role_users.gen.go new file mode 100644 index 0000000..dd24388 --- /dev/null +++ b/internal/repository/mysql/dao/role_users.gen.go @@ -0,0 +1,343 @@ +// Code generated by gorm.io/gen. DO NOT EDIT. +// Code generated by gorm.io/gen. DO NOT EDIT. +// Code generated by gorm.io/gen. DO NOT EDIT. + +package dao + +import ( + "context" + + "gorm.io/gorm" + "gorm.io/gorm/clause" + "gorm.io/gorm/schema" + + "gorm.io/gen" + "gorm.io/gen/field" + + "gorm.io/plugin/dbresolver" + + "bindbox-game/internal/repository/mysql/model" +) + +func newRoleUsers(db *gorm.DB, opts ...gen.DOOption) roleUsers { + _roleUsers := roleUsers{} + + _roleUsers.roleUsersDo.UseDB(db, opts...) + _roleUsers.roleUsersDo.UseModel(&model.RoleUsers{}) + + tableName := _roleUsers.roleUsersDo.TableName() + _roleUsers.ALL = field.NewAsterisk(tableName) + _roleUsers.ID = field.NewInt64(tableName, "id") + _roleUsers.RoleID = field.NewInt64(tableName, "role_id") + _roleUsers.AdminID = field.NewInt32(tableName, "admin_id") + _roleUsers.CreatedUser = field.NewString(tableName, "created_user") + _roleUsers.UpdatedUser = field.NewString(tableName, "updated_user") + _roleUsers.CreatedAt = field.NewTime(tableName, "created_at") + _roleUsers.UpdatedAt = field.NewTime(tableName, "updated_at") + + _roleUsers.fillFieldMap() + + return _roleUsers +} + +type roleUsers struct { + roleUsersDo + + ALL field.Asterisk + ID field.Int64 + RoleID field.Int64 + AdminID field.Int32 + CreatedUser field.String + UpdatedUser field.String + CreatedAt field.Time + UpdatedAt field.Time + + fieldMap map[string]field.Expr +} + +func (r roleUsers) Table(newTableName string) *roleUsers { + r.roleUsersDo.UseTable(newTableName) + return r.updateTableName(newTableName) +} + +func (r roleUsers) As(alias string) *roleUsers { + r.roleUsersDo.DO = *(r.roleUsersDo.As(alias).(*gen.DO)) + return r.updateTableName(alias) +} + +func (r *roleUsers) updateTableName(table string) *roleUsers { + r.ALL = field.NewAsterisk(table) + r.ID = field.NewInt64(table, "id") + r.RoleID = field.NewInt64(table, "role_id") + r.AdminID = field.NewInt32(table, "admin_id") + r.CreatedUser = field.NewString(table, "created_user") + r.UpdatedUser = field.NewString(table, "updated_user") + r.CreatedAt = field.NewTime(table, "created_at") + r.UpdatedAt = field.NewTime(table, "updated_at") + + r.fillFieldMap() + + return r +} + +func (r *roleUsers) GetFieldByName(fieldName string) (field.OrderExpr, bool) { + _f, ok := r.fieldMap[fieldName] + if !ok || _f == nil { + return nil, false + } + _oe, ok := _f.(field.OrderExpr) + return _oe, ok +} + +func (r *roleUsers) fillFieldMap() { + r.fieldMap = make(map[string]field.Expr, 7) + r.fieldMap["id"] = r.ID + r.fieldMap["role_id"] = r.RoleID + r.fieldMap["admin_id"] = r.AdminID + r.fieldMap["created_user"] = r.CreatedUser + r.fieldMap["updated_user"] = r.UpdatedUser + r.fieldMap["created_at"] = r.CreatedAt + r.fieldMap["updated_at"] = r.UpdatedAt +} + +func (r roleUsers) clone(db *gorm.DB) roleUsers { + r.roleUsersDo.ReplaceConnPool(db.Statement.ConnPool) + return r +} + +func (r roleUsers) replaceDB(db *gorm.DB) roleUsers { + r.roleUsersDo.ReplaceDB(db) + return r +} + +type roleUsersDo struct{ gen.DO } + +func (r roleUsersDo) Debug() *roleUsersDo { + return r.withDO(r.DO.Debug()) +} + +func (r roleUsersDo) WithContext(ctx context.Context) *roleUsersDo { + return r.withDO(r.DO.WithContext(ctx)) +} + +func (r roleUsersDo) ReadDB() *roleUsersDo { + return r.Clauses(dbresolver.Read) +} + +func (r roleUsersDo) WriteDB() *roleUsersDo { + return r.Clauses(dbresolver.Write) +} + +func (r roleUsersDo) Session(config *gorm.Session) *roleUsersDo { + return r.withDO(r.DO.Session(config)) +} + +func (r roleUsersDo) Clauses(conds ...clause.Expression) *roleUsersDo { + return r.withDO(r.DO.Clauses(conds...)) +} + +func (r roleUsersDo) Returning(value interface{}, columns ...string) *roleUsersDo { + return r.withDO(r.DO.Returning(value, columns...)) +} + +func (r roleUsersDo) Not(conds ...gen.Condition) *roleUsersDo { + return r.withDO(r.DO.Not(conds...)) +} + +func (r roleUsersDo) Or(conds ...gen.Condition) *roleUsersDo { + return r.withDO(r.DO.Or(conds...)) +} + +func (r roleUsersDo) Select(conds ...field.Expr) *roleUsersDo { + return r.withDO(r.DO.Select(conds...)) +} + +func (r roleUsersDo) Where(conds ...gen.Condition) *roleUsersDo { + return r.withDO(r.DO.Where(conds...)) +} + +func (r roleUsersDo) Order(conds ...field.Expr) *roleUsersDo { + return r.withDO(r.DO.Order(conds...)) +} + +func (r roleUsersDo) Distinct(cols ...field.Expr) *roleUsersDo { + return r.withDO(r.DO.Distinct(cols...)) +} + +func (r roleUsersDo) Omit(cols ...field.Expr) *roleUsersDo { + return r.withDO(r.DO.Omit(cols...)) +} + +func (r roleUsersDo) Join(table schema.Tabler, on ...field.Expr) *roleUsersDo { + return r.withDO(r.DO.Join(table, on...)) +} + +func (r roleUsersDo) LeftJoin(table schema.Tabler, on ...field.Expr) *roleUsersDo { + return r.withDO(r.DO.LeftJoin(table, on...)) +} + +func (r roleUsersDo) RightJoin(table schema.Tabler, on ...field.Expr) *roleUsersDo { + return r.withDO(r.DO.RightJoin(table, on...)) +} + +func (r roleUsersDo) Group(cols ...field.Expr) *roleUsersDo { + return r.withDO(r.DO.Group(cols...)) +} + +func (r roleUsersDo) Having(conds ...gen.Condition) *roleUsersDo { + return r.withDO(r.DO.Having(conds...)) +} + +func (r roleUsersDo) Limit(limit int) *roleUsersDo { + return r.withDO(r.DO.Limit(limit)) +} + +func (r roleUsersDo) Offset(offset int) *roleUsersDo { + return r.withDO(r.DO.Offset(offset)) +} + +func (r roleUsersDo) Scopes(funcs ...func(gen.Dao) gen.Dao) *roleUsersDo { + return r.withDO(r.DO.Scopes(funcs...)) +} + +func (r roleUsersDo) Unscoped() *roleUsersDo { + return r.withDO(r.DO.Unscoped()) +} + +func (r roleUsersDo) Create(values ...*model.RoleUsers) error { + if len(values) == 0 { + return nil + } + return r.DO.Create(values) +} + +func (r roleUsersDo) CreateInBatches(values []*model.RoleUsers, batchSize int) error { + return r.DO.CreateInBatches(values, batchSize) +} + +// Save : !!! underlying implementation is different with GORM +// The method is equivalent to executing the statement: db.Clauses(clause.OnConflict{UpdateAll: true}).Create(values) +func (r roleUsersDo) Save(values ...*model.RoleUsers) error { + if len(values) == 0 { + return nil + } + return r.DO.Save(values) +} + +func (r roleUsersDo) First() (*model.RoleUsers, error) { + if result, err := r.DO.First(); err != nil { + return nil, err + } else { + return result.(*model.RoleUsers), nil + } +} + +func (r roleUsersDo) Take() (*model.RoleUsers, error) { + if result, err := r.DO.Take(); err != nil { + return nil, err + } else { + return result.(*model.RoleUsers), nil + } +} + +func (r roleUsersDo) Last() (*model.RoleUsers, error) { + if result, err := r.DO.Last(); err != nil { + return nil, err + } else { + return result.(*model.RoleUsers), nil + } +} + +func (r roleUsersDo) Find() ([]*model.RoleUsers, error) { + result, err := r.DO.Find() + return result.([]*model.RoleUsers), err +} + +func (r roleUsersDo) FindInBatch(batchSize int, fc func(tx gen.Dao, batch int) error) (results []*model.RoleUsers, err error) { + buf := make([]*model.RoleUsers, 0, batchSize) + err = r.DO.FindInBatches(&buf, batchSize, func(tx gen.Dao, batch int) error { + defer func() { results = append(results, buf...) }() + return fc(tx, batch) + }) + return results, err +} + +func (r roleUsersDo) FindInBatches(result *[]*model.RoleUsers, batchSize int, fc func(tx gen.Dao, batch int) error) error { + return r.DO.FindInBatches(result, batchSize, fc) +} + +func (r roleUsersDo) Attrs(attrs ...field.AssignExpr) *roleUsersDo { + return r.withDO(r.DO.Attrs(attrs...)) +} + +func (r roleUsersDo) Assign(attrs ...field.AssignExpr) *roleUsersDo { + return r.withDO(r.DO.Assign(attrs...)) +} + +func (r roleUsersDo) Joins(fields ...field.RelationField) *roleUsersDo { + for _, _f := range fields { + r = *r.withDO(r.DO.Joins(_f)) + } + return &r +} + +func (r roleUsersDo) Preload(fields ...field.RelationField) *roleUsersDo { + for _, _f := range fields { + r = *r.withDO(r.DO.Preload(_f)) + } + return &r +} + +func (r roleUsersDo) FirstOrInit() (*model.RoleUsers, error) { + if result, err := r.DO.FirstOrInit(); err != nil { + return nil, err + } else { + return result.(*model.RoleUsers), nil + } +} + +func (r roleUsersDo) FirstOrCreate() (*model.RoleUsers, error) { + if result, err := r.DO.FirstOrCreate(); err != nil { + return nil, err + } else { + return result.(*model.RoleUsers), nil + } +} + +func (r roleUsersDo) FindByPage(offset int, limit int) (result []*model.RoleUsers, count int64, err error) { + result, err = r.Offset(offset).Limit(limit).Find() + if err != nil { + return + } + + if size := len(result); 0 < limit && 0 < size && size < limit { + count = int64(size + offset) + return + } + + count, err = r.Offset(-1).Limit(-1).Count() + return +} + +func (r roleUsersDo) ScanByPage(result interface{}, offset int, limit int) (count int64, err error) { + count, err = r.Count() + if err != nil { + return + } + + err = r.Offset(offset).Limit(limit).Scan(result) + return +} + +func (r roleUsersDo) Scan(result interface{}) (err error) { + return r.DO.Scan(result) +} + +func (r roleUsersDo) Delete(models ...*model.RoleUsers) (result gen.ResultInfo, err error) { + return r.DO.Delete(models) +} + +func (r *roleUsersDo) withDO(do gen.Dao) *roleUsersDo { + r.DO = *do.(*gen.DO) + return r +} diff --git a/internal/repository/mysql/dao/roles.gen.go b/internal/repository/mysql/dao/roles.gen.go new file mode 100644 index 0000000..8ae5729 --- /dev/null +++ b/internal/repository/mysql/dao/roles.gen.go @@ -0,0 +1,351 @@ +// Code generated by gorm.io/gen. DO NOT EDIT. +// Code generated by gorm.io/gen. DO NOT EDIT. +// Code generated by gorm.io/gen. DO NOT EDIT. + +package dao + +import ( + "context" + + "gorm.io/gorm" + "gorm.io/gorm/clause" + "gorm.io/gorm/schema" + + "gorm.io/gen" + "gorm.io/gen/field" + + "gorm.io/plugin/dbresolver" + + "bindbox-game/internal/repository/mysql/model" +) + +func newRoles(db *gorm.DB, opts ...gen.DOOption) roles { + _roles := roles{} + + _roles.rolesDo.UseDB(db, opts...) + _roles.rolesDo.UseModel(&model.Roles{}) + + tableName := _roles.rolesDo.TableName() + _roles.ALL = field.NewAsterisk(tableName) + _roles.ID = field.NewInt64(tableName, "id") + _roles.RoleName = field.NewString(tableName, "role_name") + _roles.RoleCode = field.NewString(tableName, "role_code") + _roles.Description = field.NewString(tableName, "description") + _roles.Enabled = field.NewBool(tableName, "enabled") + _roles.CreatedUser = field.NewString(tableName, "created_user") + _roles.UpdatedUser = field.NewString(tableName, "updated_user") + _roles.CreatedAt = field.NewTime(tableName, "created_at") + _roles.UpdatedAt = field.NewTime(tableName, "updated_at") + + _roles.fillFieldMap() + + return _roles +} + +type roles struct { + rolesDo + + ALL field.Asterisk + ID field.Int64 + RoleName field.String + RoleCode field.String + Description field.String + Enabled field.Bool + CreatedUser field.String + UpdatedUser field.String + CreatedAt field.Time + UpdatedAt field.Time + + fieldMap map[string]field.Expr +} + +func (r roles) Table(newTableName string) *roles { + r.rolesDo.UseTable(newTableName) + return r.updateTableName(newTableName) +} + +func (r roles) As(alias string) *roles { + r.rolesDo.DO = *(r.rolesDo.As(alias).(*gen.DO)) + return r.updateTableName(alias) +} + +func (r *roles) updateTableName(table string) *roles { + r.ALL = field.NewAsterisk(table) + r.ID = field.NewInt64(table, "id") + r.RoleName = field.NewString(table, "role_name") + r.RoleCode = field.NewString(table, "role_code") + r.Description = field.NewString(table, "description") + r.Enabled = field.NewBool(table, "enabled") + r.CreatedUser = field.NewString(table, "created_user") + r.UpdatedUser = field.NewString(table, "updated_user") + r.CreatedAt = field.NewTime(table, "created_at") + r.UpdatedAt = field.NewTime(table, "updated_at") + + r.fillFieldMap() + + return r +} + +func (r *roles) GetFieldByName(fieldName string) (field.OrderExpr, bool) { + _f, ok := r.fieldMap[fieldName] + if !ok || _f == nil { + return nil, false + } + _oe, ok := _f.(field.OrderExpr) + return _oe, ok +} + +func (r *roles) fillFieldMap() { + r.fieldMap = make(map[string]field.Expr, 9) + r.fieldMap["id"] = r.ID + r.fieldMap["role_name"] = r.RoleName + r.fieldMap["role_code"] = r.RoleCode + r.fieldMap["description"] = r.Description + r.fieldMap["enabled"] = r.Enabled + r.fieldMap["created_user"] = r.CreatedUser + r.fieldMap["updated_user"] = r.UpdatedUser + r.fieldMap["created_at"] = r.CreatedAt + r.fieldMap["updated_at"] = r.UpdatedAt +} + +func (r roles) clone(db *gorm.DB) roles { + r.rolesDo.ReplaceConnPool(db.Statement.ConnPool) + return r +} + +func (r roles) replaceDB(db *gorm.DB) roles { + r.rolesDo.ReplaceDB(db) + return r +} + +type rolesDo struct{ gen.DO } + +func (r rolesDo) Debug() *rolesDo { + return r.withDO(r.DO.Debug()) +} + +func (r rolesDo) WithContext(ctx context.Context) *rolesDo { + return r.withDO(r.DO.WithContext(ctx)) +} + +func (r rolesDo) ReadDB() *rolesDo { + return r.Clauses(dbresolver.Read) +} + +func (r rolesDo) WriteDB() *rolesDo { + return r.Clauses(dbresolver.Write) +} + +func (r rolesDo) Session(config *gorm.Session) *rolesDo { + return r.withDO(r.DO.Session(config)) +} + +func (r rolesDo) Clauses(conds ...clause.Expression) *rolesDo { + return r.withDO(r.DO.Clauses(conds...)) +} + +func (r rolesDo) Returning(value interface{}, columns ...string) *rolesDo { + return r.withDO(r.DO.Returning(value, columns...)) +} + +func (r rolesDo) Not(conds ...gen.Condition) *rolesDo { + return r.withDO(r.DO.Not(conds...)) +} + +func (r rolesDo) Or(conds ...gen.Condition) *rolesDo { + return r.withDO(r.DO.Or(conds...)) +} + +func (r rolesDo) Select(conds ...field.Expr) *rolesDo { + return r.withDO(r.DO.Select(conds...)) +} + +func (r rolesDo) Where(conds ...gen.Condition) *rolesDo { + return r.withDO(r.DO.Where(conds...)) +} + +func (r rolesDo) Order(conds ...field.Expr) *rolesDo { + return r.withDO(r.DO.Order(conds...)) +} + +func (r rolesDo) Distinct(cols ...field.Expr) *rolesDo { + return r.withDO(r.DO.Distinct(cols...)) +} + +func (r rolesDo) Omit(cols ...field.Expr) *rolesDo { + return r.withDO(r.DO.Omit(cols...)) +} + +func (r rolesDo) Join(table schema.Tabler, on ...field.Expr) *rolesDo { + return r.withDO(r.DO.Join(table, on...)) +} + +func (r rolesDo) LeftJoin(table schema.Tabler, on ...field.Expr) *rolesDo { + return r.withDO(r.DO.LeftJoin(table, on...)) +} + +func (r rolesDo) RightJoin(table schema.Tabler, on ...field.Expr) *rolesDo { + return r.withDO(r.DO.RightJoin(table, on...)) +} + +func (r rolesDo) Group(cols ...field.Expr) *rolesDo { + return r.withDO(r.DO.Group(cols...)) +} + +func (r rolesDo) Having(conds ...gen.Condition) *rolesDo { + return r.withDO(r.DO.Having(conds...)) +} + +func (r rolesDo) Limit(limit int) *rolesDo { + return r.withDO(r.DO.Limit(limit)) +} + +func (r rolesDo) Offset(offset int) *rolesDo { + return r.withDO(r.DO.Offset(offset)) +} + +func (r rolesDo) Scopes(funcs ...func(gen.Dao) gen.Dao) *rolesDo { + return r.withDO(r.DO.Scopes(funcs...)) +} + +func (r rolesDo) Unscoped() *rolesDo { + return r.withDO(r.DO.Unscoped()) +} + +func (r rolesDo) Create(values ...*model.Roles) error { + if len(values) == 0 { + return nil + } + return r.DO.Create(values) +} + +func (r rolesDo) CreateInBatches(values []*model.Roles, batchSize int) error { + return r.DO.CreateInBatches(values, batchSize) +} + +// Save : !!! underlying implementation is different with GORM +// The method is equivalent to executing the statement: db.Clauses(clause.OnConflict{UpdateAll: true}).Create(values) +func (r rolesDo) Save(values ...*model.Roles) error { + if len(values) == 0 { + return nil + } + return r.DO.Save(values) +} + +func (r rolesDo) First() (*model.Roles, error) { + if result, err := r.DO.First(); err != nil { + return nil, err + } else { + return result.(*model.Roles), nil + } +} + +func (r rolesDo) Take() (*model.Roles, error) { + if result, err := r.DO.Take(); err != nil { + return nil, err + } else { + return result.(*model.Roles), nil + } +} + +func (r rolesDo) Last() (*model.Roles, error) { + if result, err := r.DO.Last(); err != nil { + return nil, err + } else { + return result.(*model.Roles), nil + } +} + +func (r rolesDo) Find() ([]*model.Roles, error) { + result, err := r.DO.Find() + return result.([]*model.Roles), err +} + +func (r rolesDo) FindInBatch(batchSize int, fc func(tx gen.Dao, batch int) error) (results []*model.Roles, err error) { + buf := make([]*model.Roles, 0, batchSize) + err = r.DO.FindInBatches(&buf, batchSize, func(tx gen.Dao, batch int) error { + defer func() { results = append(results, buf...) }() + return fc(tx, batch) + }) + return results, err +} + +func (r rolesDo) FindInBatches(result *[]*model.Roles, batchSize int, fc func(tx gen.Dao, batch int) error) error { + return r.DO.FindInBatches(result, batchSize, fc) +} + +func (r rolesDo) Attrs(attrs ...field.AssignExpr) *rolesDo { + return r.withDO(r.DO.Attrs(attrs...)) +} + +func (r rolesDo) Assign(attrs ...field.AssignExpr) *rolesDo { + return r.withDO(r.DO.Assign(attrs...)) +} + +func (r rolesDo) Joins(fields ...field.RelationField) *rolesDo { + for _, _f := range fields { + r = *r.withDO(r.DO.Joins(_f)) + } + return &r +} + +func (r rolesDo) Preload(fields ...field.RelationField) *rolesDo { + for _, _f := range fields { + r = *r.withDO(r.DO.Preload(_f)) + } + return &r +} + +func (r rolesDo) FirstOrInit() (*model.Roles, error) { + if result, err := r.DO.FirstOrInit(); err != nil { + return nil, err + } else { + return result.(*model.Roles), nil + } +} + +func (r rolesDo) FirstOrCreate() (*model.Roles, error) { + if result, err := r.DO.FirstOrCreate(); err != nil { + return nil, err + } else { + return result.(*model.Roles), nil + } +} + +func (r rolesDo) FindByPage(offset int, limit int) (result []*model.Roles, count int64, err error) { + result, err = r.Offset(offset).Limit(limit).Find() + if err != nil { + return + } + + if size := len(result); 0 < limit && 0 < size && size < limit { + count = int64(size + offset) + return + } + + count, err = r.Offset(-1).Limit(-1).Count() + return +} + +func (r rolesDo) ScanByPage(result interface{}, offset int, limit int) (count int64, err error) { + count, err = r.Count() + if err != nil { + return + } + + err = r.Offset(offset).Limit(limit).Scan(result) + return +} + +func (r rolesDo) Scan(result interface{}) (err error) { + return r.DO.Scan(result) +} + +func (r rolesDo) Delete(models ...*model.Roles) (result gen.ResultInfo, err error) { + return r.DO.Delete(models) +} + +func (r *rolesDo) withDO(do gen.Dao) *rolesDo { + r.DO = *do.(*gen.DO) + return r +} diff --git a/internal/repository/mysql/dao/shipping_records.gen.go b/internal/repository/mysql/dao/shipping_records.gen.go new file mode 100644 index 0000000..1061b1a --- /dev/null +++ b/internal/repository/mysql/dao/shipping_records.gen.go @@ -0,0 +1,384 @@ +// Code generated by gorm.io/gen. DO NOT EDIT. +// Code generated by gorm.io/gen. DO NOT EDIT. +// Code generated by gorm.io/gen. DO NOT EDIT. + +package dao + +import ( + "context" + + "gorm.io/gorm" + "gorm.io/gorm/clause" + "gorm.io/gorm/schema" + + "gorm.io/gen" + "gorm.io/gen/field" + + "gorm.io/plugin/dbresolver" + + "bindbox-game/internal/repository/mysql/model" +) + +func newShippingRecords(db *gorm.DB, opts ...gen.DOOption) shippingRecords { + _shippingRecords := shippingRecords{} + + _shippingRecords.shippingRecordsDo.UseDB(db, opts...) + _shippingRecords.shippingRecordsDo.UseModel(&model.ShippingRecords{}) + + tableName := _shippingRecords.shippingRecordsDo.TableName() + _shippingRecords.ALL = field.NewAsterisk(tableName) + _shippingRecords.ID = field.NewInt64(tableName, "id") + _shippingRecords.CreatedAt = field.NewTime(tableName, "created_at") + _shippingRecords.UpdatedAt = field.NewTime(tableName, "updated_at") + _shippingRecords.UserID = field.NewInt64(tableName, "user_id") + _shippingRecords.OrderID = field.NewInt64(tableName, "order_id") + _shippingRecords.OrderItemID = field.NewInt64(tableName, "order_item_id") + _shippingRecords.InventoryID = field.NewInt64(tableName, "inventory_id") + _shippingRecords.ProductID = field.NewInt64(tableName, "product_id") + _shippingRecords.Quantity = field.NewInt64(tableName, "quantity") + _shippingRecords.Price = field.NewInt64(tableName, "price") + _shippingRecords.AddressID = field.NewInt64(tableName, "address_id") + _shippingRecords.Status = field.NewInt32(tableName, "status") + _shippingRecords.ExpressCode = field.NewString(tableName, "express_code") + _shippingRecords.ExpressNo = field.NewString(tableName, "express_no") + _shippingRecords.ShippedAt = field.NewTime(tableName, "shipped_at") + _shippingRecords.ReceivedAt = field.NewTime(tableName, "received_at") + _shippingRecords.Remark = field.NewString(tableName, "remark") + + _shippingRecords.fillFieldMap() + + return _shippingRecords +} + +// shippingRecords 发货记录(合并:单表) +type shippingRecords struct { + shippingRecordsDo + + ALL field.Asterisk + ID field.Int64 // 主键ID + CreatedAt field.Time // 创建时间 + UpdatedAt field.Time // 更新时间 + UserID field.Int64 // 收件用户ID(user_members.id) + OrderID field.Int64 // 关联订单ID(orders.id,抽奖产物可为空) + OrderItemID field.Int64 // 订单行ID(商城直发时使用) + InventoryID field.Int64 // 资产ID(抽奖产物发货时使用) + ProductID field.Int64 // 商品ID(统计/冗余) + Quantity field.Int64 // 发货数量 + Price field.Int64 // 行价格(分,可选) + AddressID field.Int64 // 收货地址ID(user_addresses.id) + Status field.Int32 // 发货状态:1待发货 2已发货 3已签收 4异常 + ExpressCode field.String // 快递公司编码 + ExpressNo field.String // 运单号 + ShippedAt field.Time // 发货时间 + ReceivedAt field.Time // 签收时间 + Remark field.String // 备注 + + fieldMap map[string]field.Expr +} + +func (s shippingRecords) Table(newTableName string) *shippingRecords { + s.shippingRecordsDo.UseTable(newTableName) + return s.updateTableName(newTableName) +} + +func (s shippingRecords) As(alias string) *shippingRecords { + s.shippingRecordsDo.DO = *(s.shippingRecordsDo.As(alias).(*gen.DO)) + return s.updateTableName(alias) +} + +func (s *shippingRecords) updateTableName(table string) *shippingRecords { + s.ALL = field.NewAsterisk(table) + s.ID = field.NewInt64(table, "id") + s.CreatedAt = field.NewTime(table, "created_at") + s.UpdatedAt = field.NewTime(table, "updated_at") + s.UserID = field.NewInt64(table, "user_id") + s.OrderID = field.NewInt64(table, "order_id") + s.OrderItemID = field.NewInt64(table, "order_item_id") + s.InventoryID = field.NewInt64(table, "inventory_id") + s.ProductID = field.NewInt64(table, "product_id") + s.Quantity = field.NewInt64(table, "quantity") + s.Price = field.NewInt64(table, "price") + s.AddressID = field.NewInt64(table, "address_id") + s.Status = field.NewInt32(table, "status") + s.ExpressCode = field.NewString(table, "express_code") + s.ExpressNo = field.NewString(table, "express_no") + s.ShippedAt = field.NewTime(table, "shipped_at") + s.ReceivedAt = field.NewTime(table, "received_at") + s.Remark = field.NewString(table, "remark") + + s.fillFieldMap() + + return s +} + +func (s *shippingRecords) GetFieldByName(fieldName string) (field.OrderExpr, bool) { + _f, ok := s.fieldMap[fieldName] + if !ok || _f == nil { + return nil, false + } + _oe, ok := _f.(field.OrderExpr) + return _oe, ok +} + +func (s *shippingRecords) fillFieldMap() { + s.fieldMap = make(map[string]field.Expr, 17) + s.fieldMap["id"] = s.ID + s.fieldMap["created_at"] = s.CreatedAt + s.fieldMap["updated_at"] = s.UpdatedAt + s.fieldMap["user_id"] = s.UserID + s.fieldMap["order_id"] = s.OrderID + s.fieldMap["order_item_id"] = s.OrderItemID + s.fieldMap["inventory_id"] = s.InventoryID + s.fieldMap["product_id"] = s.ProductID + s.fieldMap["quantity"] = s.Quantity + s.fieldMap["price"] = s.Price + s.fieldMap["address_id"] = s.AddressID + s.fieldMap["status"] = s.Status + s.fieldMap["express_code"] = s.ExpressCode + s.fieldMap["express_no"] = s.ExpressNo + s.fieldMap["shipped_at"] = s.ShippedAt + s.fieldMap["received_at"] = s.ReceivedAt + s.fieldMap["remark"] = s.Remark +} + +func (s shippingRecords) clone(db *gorm.DB) shippingRecords { + s.shippingRecordsDo.ReplaceConnPool(db.Statement.ConnPool) + return s +} + +func (s shippingRecords) replaceDB(db *gorm.DB) shippingRecords { + s.shippingRecordsDo.ReplaceDB(db) + return s +} + +type shippingRecordsDo struct{ gen.DO } + +func (s shippingRecordsDo) Debug() *shippingRecordsDo { + return s.withDO(s.DO.Debug()) +} + +func (s shippingRecordsDo) WithContext(ctx context.Context) *shippingRecordsDo { + return s.withDO(s.DO.WithContext(ctx)) +} + +func (s shippingRecordsDo) ReadDB() *shippingRecordsDo { + return s.Clauses(dbresolver.Read) +} + +func (s shippingRecordsDo) WriteDB() *shippingRecordsDo { + return s.Clauses(dbresolver.Write) +} + +func (s shippingRecordsDo) Session(config *gorm.Session) *shippingRecordsDo { + return s.withDO(s.DO.Session(config)) +} + +func (s shippingRecordsDo) Clauses(conds ...clause.Expression) *shippingRecordsDo { + return s.withDO(s.DO.Clauses(conds...)) +} + +func (s shippingRecordsDo) Returning(value interface{}, columns ...string) *shippingRecordsDo { + return s.withDO(s.DO.Returning(value, columns...)) +} + +func (s shippingRecordsDo) Not(conds ...gen.Condition) *shippingRecordsDo { + return s.withDO(s.DO.Not(conds...)) +} + +func (s shippingRecordsDo) Or(conds ...gen.Condition) *shippingRecordsDo { + return s.withDO(s.DO.Or(conds...)) +} + +func (s shippingRecordsDo) Select(conds ...field.Expr) *shippingRecordsDo { + return s.withDO(s.DO.Select(conds...)) +} + +func (s shippingRecordsDo) Where(conds ...gen.Condition) *shippingRecordsDo { + return s.withDO(s.DO.Where(conds...)) +} + +func (s shippingRecordsDo) Order(conds ...field.Expr) *shippingRecordsDo { + return s.withDO(s.DO.Order(conds...)) +} + +func (s shippingRecordsDo) Distinct(cols ...field.Expr) *shippingRecordsDo { + return s.withDO(s.DO.Distinct(cols...)) +} + +func (s shippingRecordsDo) Omit(cols ...field.Expr) *shippingRecordsDo { + return s.withDO(s.DO.Omit(cols...)) +} + +func (s shippingRecordsDo) Join(table schema.Tabler, on ...field.Expr) *shippingRecordsDo { + return s.withDO(s.DO.Join(table, on...)) +} + +func (s shippingRecordsDo) LeftJoin(table schema.Tabler, on ...field.Expr) *shippingRecordsDo { + return s.withDO(s.DO.LeftJoin(table, on...)) +} + +func (s shippingRecordsDo) RightJoin(table schema.Tabler, on ...field.Expr) *shippingRecordsDo { + return s.withDO(s.DO.RightJoin(table, on...)) +} + +func (s shippingRecordsDo) Group(cols ...field.Expr) *shippingRecordsDo { + return s.withDO(s.DO.Group(cols...)) +} + +func (s shippingRecordsDo) Having(conds ...gen.Condition) *shippingRecordsDo { + return s.withDO(s.DO.Having(conds...)) +} + +func (s shippingRecordsDo) Limit(limit int) *shippingRecordsDo { + return s.withDO(s.DO.Limit(limit)) +} + +func (s shippingRecordsDo) Offset(offset int) *shippingRecordsDo { + return s.withDO(s.DO.Offset(offset)) +} + +func (s shippingRecordsDo) Scopes(funcs ...func(gen.Dao) gen.Dao) *shippingRecordsDo { + return s.withDO(s.DO.Scopes(funcs...)) +} + +func (s shippingRecordsDo) Unscoped() *shippingRecordsDo { + return s.withDO(s.DO.Unscoped()) +} + +func (s shippingRecordsDo) Create(values ...*model.ShippingRecords) error { + if len(values) == 0 { + return nil + } + return s.DO.Create(values) +} + +func (s shippingRecordsDo) CreateInBatches(values []*model.ShippingRecords, batchSize int) error { + return s.DO.CreateInBatches(values, batchSize) +} + +// Save : !!! underlying implementation is different with GORM +// The method is equivalent to executing the statement: db.Clauses(clause.OnConflict{UpdateAll: true}).Create(values) +func (s shippingRecordsDo) Save(values ...*model.ShippingRecords) error { + if len(values) == 0 { + return nil + } + return s.DO.Save(values) +} + +func (s shippingRecordsDo) First() (*model.ShippingRecords, error) { + if result, err := s.DO.First(); err != nil { + return nil, err + } else { + return result.(*model.ShippingRecords), nil + } +} + +func (s shippingRecordsDo) Take() (*model.ShippingRecords, error) { + if result, err := s.DO.Take(); err != nil { + return nil, err + } else { + return result.(*model.ShippingRecords), nil + } +} + +func (s shippingRecordsDo) Last() (*model.ShippingRecords, error) { + if result, err := s.DO.Last(); err != nil { + return nil, err + } else { + return result.(*model.ShippingRecords), nil + } +} + +func (s shippingRecordsDo) Find() ([]*model.ShippingRecords, error) { + result, err := s.DO.Find() + return result.([]*model.ShippingRecords), err +} + +func (s shippingRecordsDo) FindInBatch(batchSize int, fc func(tx gen.Dao, batch int) error) (results []*model.ShippingRecords, err error) { + buf := make([]*model.ShippingRecords, 0, batchSize) + err = s.DO.FindInBatches(&buf, batchSize, func(tx gen.Dao, batch int) error { + defer func() { results = append(results, buf...) }() + return fc(tx, batch) + }) + return results, err +} + +func (s shippingRecordsDo) FindInBatches(result *[]*model.ShippingRecords, batchSize int, fc func(tx gen.Dao, batch int) error) error { + return s.DO.FindInBatches(result, batchSize, fc) +} + +func (s shippingRecordsDo) Attrs(attrs ...field.AssignExpr) *shippingRecordsDo { + return s.withDO(s.DO.Attrs(attrs...)) +} + +func (s shippingRecordsDo) Assign(attrs ...field.AssignExpr) *shippingRecordsDo { + return s.withDO(s.DO.Assign(attrs...)) +} + +func (s shippingRecordsDo) Joins(fields ...field.RelationField) *shippingRecordsDo { + for _, _f := range fields { + s = *s.withDO(s.DO.Joins(_f)) + } + return &s +} + +func (s shippingRecordsDo) Preload(fields ...field.RelationField) *shippingRecordsDo { + for _, _f := range fields { + s = *s.withDO(s.DO.Preload(_f)) + } + return &s +} + +func (s shippingRecordsDo) FirstOrInit() (*model.ShippingRecords, error) { + if result, err := s.DO.FirstOrInit(); err != nil { + return nil, err + } else { + return result.(*model.ShippingRecords), nil + } +} + +func (s shippingRecordsDo) FirstOrCreate() (*model.ShippingRecords, error) { + if result, err := s.DO.FirstOrCreate(); err != nil { + return nil, err + } else { + return result.(*model.ShippingRecords), nil + } +} + +func (s shippingRecordsDo) FindByPage(offset int, limit int) (result []*model.ShippingRecords, count int64, err error) { + result, err = s.Offset(offset).Limit(limit).Find() + if err != nil { + return + } + + if size := len(result); 0 < limit && 0 < size && size < limit { + count = int64(size + offset) + return + } + + count, err = s.Offset(-1).Limit(-1).Count() + return +} + +func (s shippingRecordsDo) ScanByPage(result interface{}, offset int, limit int) (count int64, err error) { + count, err = s.Count() + if err != nil { + return + } + + err = s.Offset(offset).Limit(limit).Scan(result) + return +} + +func (s shippingRecordsDo) Scan(result interface{}) (err error) { + return s.DO.Scan(result) +} + +func (s shippingRecordsDo) Delete(models ...*model.ShippingRecords) (result gen.ResultInfo, err error) { + return s.DO.Delete(models) +} + +func (s *shippingRecordsDo) withDO(do gen.Dao) *shippingRecordsDo { + s.DO = *do.(*gen.DO) + return s +} diff --git a/internal/repository/mysql/dao/system_coupons.gen.go b/internal/repository/mysql/dao/system_coupons.gen.go new file mode 100644 index 0000000..f0c4cf6 --- /dev/null +++ b/internal/repository/mysql/dao/system_coupons.gen.go @@ -0,0 +1,368 @@ +// Code generated by gorm.io/gen. DO NOT EDIT. +// Code generated by gorm.io/gen. DO NOT EDIT. +// Code generated by gorm.io/gen. DO NOT EDIT. + +package dao + +import ( + "context" + + "gorm.io/gorm" + "gorm.io/gorm/clause" + "gorm.io/gorm/schema" + + "gorm.io/gen" + "gorm.io/gen/field" + + "gorm.io/plugin/dbresolver" + + "bindbox-game/internal/repository/mysql/model" +) + +func newSystemCoupons(db *gorm.DB, opts ...gen.DOOption) systemCoupons { + _systemCoupons := systemCoupons{} + + _systemCoupons.systemCouponsDo.UseDB(db, opts...) + _systemCoupons.systemCouponsDo.UseModel(&model.SystemCoupons{}) + + tableName := _systemCoupons.systemCouponsDo.TableName() + _systemCoupons.ALL = field.NewAsterisk(tableName) + _systemCoupons.ID = field.NewInt64(tableName, "id") + _systemCoupons.CreatedAt = field.NewTime(tableName, "created_at") + _systemCoupons.UpdatedAt = field.NewTime(tableName, "updated_at") + _systemCoupons.Name = field.NewString(tableName, "name") + _systemCoupons.ScopeType = field.NewInt32(tableName, "scope_type") + _systemCoupons.ActivityID = field.NewInt64(tableName, "activity_id") + _systemCoupons.ProductID = field.NewInt64(tableName, "product_id") + _systemCoupons.DiscountType = field.NewInt32(tableName, "discount_type") + _systemCoupons.DiscountValue = field.NewInt64(tableName, "discount_value") + _systemCoupons.MinSpend = field.NewInt64(tableName, "min_spend") + _systemCoupons.ValidStart = field.NewTime(tableName, "valid_start") + _systemCoupons.ValidEnd = field.NewTime(tableName, "valid_end") + _systemCoupons.Status = field.NewInt32(tableName, "status") + + _systemCoupons.fillFieldMap() + + return _systemCoupons +} + +// systemCoupons 优惠券模板 +type systemCoupons struct { + systemCouponsDo + + ALL field.Asterisk + ID field.Int64 // 主键ID + CreatedAt field.Time // 创建时间 + UpdatedAt field.Time // 更新时间 + Name field.String // 券名称 + ScopeType field.Int32 // 适用范围:1全局 2活动 3商品 + ActivityID field.Int64 // 指定活动ID(可空) + ProductID field.Int64 // 指定商品ID(可空) + DiscountType field.Int32 // 优惠类型:1直减 2满减 3折扣 + DiscountValue field.Int64 // 优惠面值(直减/满减为分;折扣为千分比) + MinSpend field.Int64 // 使用门槛金额(分) + ValidStart field.Time // 有效期开始 + ValidEnd field.Time // 有效期结束 + Status field.Int32 // 状态:1启用 2停用 + + fieldMap map[string]field.Expr +} + +func (s systemCoupons) Table(newTableName string) *systemCoupons { + s.systemCouponsDo.UseTable(newTableName) + return s.updateTableName(newTableName) +} + +func (s systemCoupons) As(alias string) *systemCoupons { + s.systemCouponsDo.DO = *(s.systemCouponsDo.As(alias).(*gen.DO)) + return s.updateTableName(alias) +} + +func (s *systemCoupons) updateTableName(table string) *systemCoupons { + s.ALL = field.NewAsterisk(table) + s.ID = field.NewInt64(table, "id") + s.CreatedAt = field.NewTime(table, "created_at") + s.UpdatedAt = field.NewTime(table, "updated_at") + s.Name = field.NewString(table, "name") + s.ScopeType = field.NewInt32(table, "scope_type") + s.ActivityID = field.NewInt64(table, "activity_id") + s.ProductID = field.NewInt64(table, "product_id") + s.DiscountType = field.NewInt32(table, "discount_type") + s.DiscountValue = field.NewInt64(table, "discount_value") + s.MinSpend = field.NewInt64(table, "min_spend") + s.ValidStart = field.NewTime(table, "valid_start") + s.ValidEnd = field.NewTime(table, "valid_end") + s.Status = field.NewInt32(table, "status") + + s.fillFieldMap() + + return s +} + +func (s *systemCoupons) GetFieldByName(fieldName string) (field.OrderExpr, bool) { + _f, ok := s.fieldMap[fieldName] + if !ok || _f == nil { + return nil, false + } + _oe, ok := _f.(field.OrderExpr) + return _oe, ok +} + +func (s *systemCoupons) fillFieldMap() { + s.fieldMap = make(map[string]field.Expr, 13) + s.fieldMap["id"] = s.ID + s.fieldMap["created_at"] = s.CreatedAt + s.fieldMap["updated_at"] = s.UpdatedAt + s.fieldMap["name"] = s.Name + s.fieldMap["scope_type"] = s.ScopeType + s.fieldMap["activity_id"] = s.ActivityID + s.fieldMap["product_id"] = s.ProductID + s.fieldMap["discount_type"] = s.DiscountType + s.fieldMap["discount_value"] = s.DiscountValue + s.fieldMap["min_spend"] = s.MinSpend + s.fieldMap["valid_start"] = s.ValidStart + s.fieldMap["valid_end"] = s.ValidEnd + s.fieldMap["status"] = s.Status +} + +func (s systemCoupons) clone(db *gorm.DB) systemCoupons { + s.systemCouponsDo.ReplaceConnPool(db.Statement.ConnPool) + return s +} + +func (s systemCoupons) replaceDB(db *gorm.DB) systemCoupons { + s.systemCouponsDo.ReplaceDB(db) + return s +} + +type systemCouponsDo struct{ gen.DO } + +func (s systemCouponsDo) Debug() *systemCouponsDo { + return s.withDO(s.DO.Debug()) +} + +func (s systemCouponsDo) WithContext(ctx context.Context) *systemCouponsDo { + return s.withDO(s.DO.WithContext(ctx)) +} + +func (s systemCouponsDo) ReadDB() *systemCouponsDo { + return s.Clauses(dbresolver.Read) +} + +func (s systemCouponsDo) WriteDB() *systemCouponsDo { + return s.Clauses(dbresolver.Write) +} + +func (s systemCouponsDo) Session(config *gorm.Session) *systemCouponsDo { + return s.withDO(s.DO.Session(config)) +} + +func (s systemCouponsDo) Clauses(conds ...clause.Expression) *systemCouponsDo { + return s.withDO(s.DO.Clauses(conds...)) +} + +func (s systemCouponsDo) Returning(value interface{}, columns ...string) *systemCouponsDo { + return s.withDO(s.DO.Returning(value, columns...)) +} + +func (s systemCouponsDo) Not(conds ...gen.Condition) *systemCouponsDo { + return s.withDO(s.DO.Not(conds...)) +} + +func (s systemCouponsDo) Or(conds ...gen.Condition) *systemCouponsDo { + return s.withDO(s.DO.Or(conds...)) +} + +func (s systemCouponsDo) Select(conds ...field.Expr) *systemCouponsDo { + return s.withDO(s.DO.Select(conds...)) +} + +func (s systemCouponsDo) Where(conds ...gen.Condition) *systemCouponsDo { + return s.withDO(s.DO.Where(conds...)) +} + +func (s systemCouponsDo) Order(conds ...field.Expr) *systemCouponsDo { + return s.withDO(s.DO.Order(conds...)) +} + +func (s systemCouponsDo) Distinct(cols ...field.Expr) *systemCouponsDo { + return s.withDO(s.DO.Distinct(cols...)) +} + +func (s systemCouponsDo) Omit(cols ...field.Expr) *systemCouponsDo { + return s.withDO(s.DO.Omit(cols...)) +} + +func (s systemCouponsDo) Join(table schema.Tabler, on ...field.Expr) *systemCouponsDo { + return s.withDO(s.DO.Join(table, on...)) +} + +func (s systemCouponsDo) LeftJoin(table schema.Tabler, on ...field.Expr) *systemCouponsDo { + return s.withDO(s.DO.LeftJoin(table, on...)) +} + +func (s systemCouponsDo) RightJoin(table schema.Tabler, on ...field.Expr) *systemCouponsDo { + return s.withDO(s.DO.RightJoin(table, on...)) +} + +func (s systemCouponsDo) Group(cols ...field.Expr) *systemCouponsDo { + return s.withDO(s.DO.Group(cols...)) +} + +func (s systemCouponsDo) Having(conds ...gen.Condition) *systemCouponsDo { + return s.withDO(s.DO.Having(conds...)) +} + +func (s systemCouponsDo) Limit(limit int) *systemCouponsDo { + return s.withDO(s.DO.Limit(limit)) +} + +func (s systemCouponsDo) Offset(offset int) *systemCouponsDo { + return s.withDO(s.DO.Offset(offset)) +} + +func (s systemCouponsDo) Scopes(funcs ...func(gen.Dao) gen.Dao) *systemCouponsDo { + return s.withDO(s.DO.Scopes(funcs...)) +} + +func (s systemCouponsDo) Unscoped() *systemCouponsDo { + return s.withDO(s.DO.Unscoped()) +} + +func (s systemCouponsDo) Create(values ...*model.SystemCoupons) error { + if len(values) == 0 { + return nil + } + return s.DO.Create(values) +} + +func (s systemCouponsDo) CreateInBatches(values []*model.SystemCoupons, batchSize int) error { + return s.DO.CreateInBatches(values, batchSize) +} + +// Save : !!! underlying implementation is different with GORM +// The method is equivalent to executing the statement: db.Clauses(clause.OnConflict{UpdateAll: true}).Create(values) +func (s systemCouponsDo) Save(values ...*model.SystemCoupons) error { + if len(values) == 0 { + return nil + } + return s.DO.Save(values) +} + +func (s systemCouponsDo) First() (*model.SystemCoupons, error) { + if result, err := s.DO.First(); err != nil { + return nil, err + } else { + return result.(*model.SystemCoupons), nil + } +} + +func (s systemCouponsDo) Take() (*model.SystemCoupons, error) { + if result, err := s.DO.Take(); err != nil { + return nil, err + } else { + return result.(*model.SystemCoupons), nil + } +} + +func (s systemCouponsDo) Last() (*model.SystemCoupons, error) { + if result, err := s.DO.Last(); err != nil { + return nil, err + } else { + return result.(*model.SystemCoupons), nil + } +} + +func (s systemCouponsDo) Find() ([]*model.SystemCoupons, error) { + result, err := s.DO.Find() + return result.([]*model.SystemCoupons), err +} + +func (s systemCouponsDo) FindInBatch(batchSize int, fc func(tx gen.Dao, batch int) error) (results []*model.SystemCoupons, err error) { + buf := make([]*model.SystemCoupons, 0, batchSize) + err = s.DO.FindInBatches(&buf, batchSize, func(tx gen.Dao, batch int) error { + defer func() { results = append(results, buf...) }() + return fc(tx, batch) + }) + return results, err +} + +func (s systemCouponsDo) FindInBatches(result *[]*model.SystemCoupons, batchSize int, fc func(tx gen.Dao, batch int) error) error { + return s.DO.FindInBatches(result, batchSize, fc) +} + +func (s systemCouponsDo) Attrs(attrs ...field.AssignExpr) *systemCouponsDo { + return s.withDO(s.DO.Attrs(attrs...)) +} + +func (s systemCouponsDo) Assign(attrs ...field.AssignExpr) *systemCouponsDo { + return s.withDO(s.DO.Assign(attrs...)) +} + +func (s systemCouponsDo) Joins(fields ...field.RelationField) *systemCouponsDo { + for _, _f := range fields { + s = *s.withDO(s.DO.Joins(_f)) + } + return &s +} + +func (s systemCouponsDo) Preload(fields ...field.RelationField) *systemCouponsDo { + for _, _f := range fields { + s = *s.withDO(s.DO.Preload(_f)) + } + return &s +} + +func (s systemCouponsDo) FirstOrInit() (*model.SystemCoupons, error) { + if result, err := s.DO.FirstOrInit(); err != nil { + return nil, err + } else { + return result.(*model.SystemCoupons), nil + } +} + +func (s systemCouponsDo) FirstOrCreate() (*model.SystemCoupons, error) { + if result, err := s.DO.FirstOrCreate(); err != nil { + return nil, err + } else { + return result.(*model.SystemCoupons), nil + } +} + +func (s systemCouponsDo) FindByPage(offset int, limit int) (result []*model.SystemCoupons, count int64, err error) { + result, err = s.Offset(offset).Limit(limit).Find() + if err != nil { + return + } + + if size := len(result); 0 < limit && 0 < size && size < limit { + count = int64(size + offset) + return + } + + count, err = s.Offset(-1).Limit(-1).Count() + return +} + +func (s systemCouponsDo) ScanByPage(result interface{}, offset int, limit int) (count int64, err error) { + count, err = s.Count() + if err != nil { + return + } + + err = s.Offset(offset).Limit(limit).Scan(result) + return +} + +func (s systemCouponsDo) Scan(result interface{}) (err error) { + return s.DO.Scan(result) +} + +func (s systemCouponsDo) Delete(models ...*model.SystemCoupons) (result gen.ResultInfo, err error) { + return s.DO.Delete(models) +} + +func (s *systemCouponsDo) withDO(do gen.Dao) *systemCouponsDo { + s.DO = *do.(*gen.DO) + return s +} diff --git a/internal/repository/mysql/dao/system_item_cards.gen.go b/internal/repository/mysql/dao/system_item_cards.gen.go new file mode 100644 index 0000000..82d7c44 --- /dev/null +++ b/internal/repository/mysql/dao/system_item_cards.gen.go @@ -0,0 +1,392 @@ +// Code generated by gorm.io/gen. DO NOT EDIT. +// Code generated by gorm.io/gen. DO NOT EDIT. +// Code generated by gorm.io/gen. DO NOT EDIT. + +package dao + +import ( + "context" + + "gorm.io/gorm" + "gorm.io/gorm/clause" + "gorm.io/gorm/schema" + + "gorm.io/gen" + "gorm.io/gen/field" + + "gorm.io/plugin/dbresolver" + + "bindbox-game/internal/repository/mysql/model" +) + +func newSystemItemCards(db *gorm.DB, opts ...gen.DOOption) systemItemCards { + _systemItemCards := systemItemCards{} + + _systemItemCards.systemItemCardsDo.UseDB(db, opts...) + _systemItemCards.systemItemCardsDo.UseModel(&model.SystemItemCards{}) + + tableName := _systemItemCards.systemItemCardsDo.TableName() + _systemItemCards.ALL = field.NewAsterisk(tableName) + _systemItemCards.ID = field.NewInt64(tableName, "id") + _systemItemCards.CreatedAt = field.NewTime(tableName, "created_at") + _systemItemCards.UpdatedAt = field.NewTime(tableName, "updated_at") + _systemItemCards.Name = field.NewString(tableName, "name") + _systemItemCards.Status = field.NewInt32(tableName, "status") + _systemItemCards.CardType = field.NewInt32(tableName, "card_type") + _systemItemCards.ScopeType = field.NewInt32(tableName, "scope_type") + _systemItemCards.ActivityCategoryID = field.NewInt64(tableName, "activity_category_id") + _systemItemCards.ActivityID = field.NewInt64(tableName, "activity_id") + _systemItemCards.IssueID = field.NewInt64(tableName, "issue_id") + _systemItemCards.Price = field.NewInt64(tableName, "price") + _systemItemCards.ValidStart = field.NewTime(tableName, "valid_start") + _systemItemCards.ValidEnd = field.NewTime(tableName, "valid_end") + _systemItemCards.EffectType = field.NewInt32(tableName, "effect_type") + _systemItemCards.RewardMultiplierX1000 = field.NewInt32(tableName, "reward_multiplier_x1000") + _systemItemCards.BoostRateX1000 = field.NewInt32(tableName, "boost_rate_x1000") + _systemItemCards.StackingStrategy = field.NewInt32(tableName, "stacking_strategy") + _systemItemCards.MaxEffectValueX1000 = field.NewInt32(tableName, "max_effect_value_x1000") + _systemItemCards.Remark = field.NewString(tableName, "remark") + + _systemItemCards.fillFieldMap() + + return _systemItemCards +} + +// systemItemCards 道具卡模板 +type systemItemCards struct { + systemItemCardsDo + + ALL field.Asterisk + ID field.Int64 // 主键ID + CreatedAt field.Time // 创建时间 + UpdatedAt field.Time // 更新时间 + Name field.String // 卡名称 + Status field.Int32 // 状态:1启用 2停用 + CardType field.Int32 // 卡类型:1双倍奖励 2概率提升 等 + ScopeType field.Int32 // 适用范围:1全局 2活动分类 3活动 4期 + ActivityCategoryID field.Int64 // 指定活动分类ID(可空) + ActivityID field.Int64 // 指定活动ID(可空) + IssueID field.Int64 // 指定期ID(可空) + Price field.Int64 // 售卖价格(分) + ValidStart field.Time // 有效期开始 + ValidEnd field.Time // 有效期结束 + EffectType field.Int32 // 效果类型:1奖励倍数 2概率提升 等 + RewardMultiplierX1000 field.Int32 // 奖励倍数(千分比,×2=2000) + BoostRateX1000 field.Int32 // 概率提升(千分比,+20%=200) + StackingStrategy field.Int32 // 叠加策略:1禁止 2同类叠加-上限 3取最大值 4乘法叠加 + MaxEffectValueX1000 field.Int32 // 效果上限(千分比) + Remark field.String // 备注 + + fieldMap map[string]field.Expr +} + +func (s systemItemCards) Table(newTableName string) *systemItemCards { + s.systemItemCardsDo.UseTable(newTableName) + return s.updateTableName(newTableName) +} + +func (s systemItemCards) As(alias string) *systemItemCards { + s.systemItemCardsDo.DO = *(s.systemItemCardsDo.As(alias).(*gen.DO)) + return s.updateTableName(alias) +} + +func (s *systemItemCards) updateTableName(table string) *systemItemCards { + s.ALL = field.NewAsterisk(table) + s.ID = field.NewInt64(table, "id") + s.CreatedAt = field.NewTime(table, "created_at") + s.UpdatedAt = field.NewTime(table, "updated_at") + s.Name = field.NewString(table, "name") + s.Status = field.NewInt32(table, "status") + s.CardType = field.NewInt32(table, "card_type") + s.ScopeType = field.NewInt32(table, "scope_type") + s.ActivityCategoryID = field.NewInt64(table, "activity_category_id") + s.ActivityID = field.NewInt64(table, "activity_id") + s.IssueID = field.NewInt64(table, "issue_id") + s.Price = field.NewInt64(table, "price") + s.ValidStart = field.NewTime(table, "valid_start") + s.ValidEnd = field.NewTime(table, "valid_end") + s.EffectType = field.NewInt32(table, "effect_type") + s.RewardMultiplierX1000 = field.NewInt32(table, "reward_multiplier_x1000") + s.BoostRateX1000 = field.NewInt32(table, "boost_rate_x1000") + s.StackingStrategy = field.NewInt32(table, "stacking_strategy") + s.MaxEffectValueX1000 = field.NewInt32(table, "max_effect_value_x1000") + s.Remark = field.NewString(table, "remark") + + s.fillFieldMap() + + return s +} + +func (s *systemItemCards) GetFieldByName(fieldName string) (field.OrderExpr, bool) { + _f, ok := s.fieldMap[fieldName] + if !ok || _f == nil { + return nil, false + } + _oe, ok := _f.(field.OrderExpr) + return _oe, ok +} + +func (s *systemItemCards) fillFieldMap() { + s.fieldMap = make(map[string]field.Expr, 19) + s.fieldMap["id"] = s.ID + s.fieldMap["created_at"] = s.CreatedAt + s.fieldMap["updated_at"] = s.UpdatedAt + s.fieldMap["name"] = s.Name + s.fieldMap["status"] = s.Status + s.fieldMap["card_type"] = s.CardType + s.fieldMap["scope_type"] = s.ScopeType + s.fieldMap["activity_category_id"] = s.ActivityCategoryID + s.fieldMap["activity_id"] = s.ActivityID + s.fieldMap["issue_id"] = s.IssueID + s.fieldMap["price"] = s.Price + s.fieldMap["valid_start"] = s.ValidStart + s.fieldMap["valid_end"] = s.ValidEnd + s.fieldMap["effect_type"] = s.EffectType + s.fieldMap["reward_multiplier_x1000"] = s.RewardMultiplierX1000 + s.fieldMap["boost_rate_x1000"] = s.BoostRateX1000 + s.fieldMap["stacking_strategy"] = s.StackingStrategy + s.fieldMap["max_effect_value_x1000"] = s.MaxEffectValueX1000 + s.fieldMap["remark"] = s.Remark +} + +func (s systemItemCards) clone(db *gorm.DB) systemItemCards { + s.systemItemCardsDo.ReplaceConnPool(db.Statement.ConnPool) + return s +} + +func (s systemItemCards) replaceDB(db *gorm.DB) systemItemCards { + s.systemItemCardsDo.ReplaceDB(db) + return s +} + +type systemItemCardsDo struct{ gen.DO } + +func (s systemItemCardsDo) Debug() *systemItemCardsDo { + return s.withDO(s.DO.Debug()) +} + +func (s systemItemCardsDo) WithContext(ctx context.Context) *systemItemCardsDo { + return s.withDO(s.DO.WithContext(ctx)) +} + +func (s systemItemCardsDo) ReadDB() *systemItemCardsDo { + return s.Clauses(dbresolver.Read) +} + +func (s systemItemCardsDo) WriteDB() *systemItemCardsDo { + return s.Clauses(dbresolver.Write) +} + +func (s systemItemCardsDo) Session(config *gorm.Session) *systemItemCardsDo { + return s.withDO(s.DO.Session(config)) +} + +func (s systemItemCardsDo) Clauses(conds ...clause.Expression) *systemItemCardsDo { + return s.withDO(s.DO.Clauses(conds...)) +} + +func (s systemItemCardsDo) Returning(value interface{}, columns ...string) *systemItemCardsDo { + return s.withDO(s.DO.Returning(value, columns...)) +} + +func (s systemItemCardsDo) Not(conds ...gen.Condition) *systemItemCardsDo { + return s.withDO(s.DO.Not(conds...)) +} + +func (s systemItemCardsDo) Or(conds ...gen.Condition) *systemItemCardsDo { + return s.withDO(s.DO.Or(conds...)) +} + +func (s systemItemCardsDo) Select(conds ...field.Expr) *systemItemCardsDo { + return s.withDO(s.DO.Select(conds...)) +} + +func (s systemItemCardsDo) Where(conds ...gen.Condition) *systemItemCardsDo { + return s.withDO(s.DO.Where(conds...)) +} + +func (s systemItemCardsDo) Order(conds ...field.Expr) *systemItemCardsDo { + return s.withDO(s.DO.Order(conds...)) +} + +func (s systemItemCardsDo) Distinct(cols ...field.Expr) *systemItemCardsDo { + return s.withDO(s.DO.Distinct(cols...)) +} + +func (s systemItemCardsDo) Omit(cols ...field.Expr) *systemItemCardsDo { + return s.withDO(s.DO.Omit(cols...)) +} + +func (s systemItemCardsDo) Join(table schema.Tabler, on ...field.Expr) *systemItemCardsDo { + return s.withDO(s.DO.Join(table, on...)) +} + +func (s systemItemCardsDo) LeftJoin(table schema.Tabler, on ...field.Expr) *systemItemCardsDo { + return s.withDO(s.DO.LeftJoin(table, on...)) +} + +func (s systemItemCardsDo) RightJoin(table schema.Tabler, on ...field.Expr) *systemItemCardsDo { + return s.withDO(s.DO.RightJoin(table, on...)) +} + +func (s systemItemCardsDo) Group(cols ...field.Expr) *systemItemCardsDo { + return s.withDO(s.DO.Group(cols...)) +} + +func (s systemItemCardsDo) Having(conds ...gen.Condition) *systemItemCardsDo { + return s.withDO(s.DO.Having(conds...)) +} + +func (s systemItemCardsDo) Limit(limit int) *systemItemCardsDo { + return s.withDO(s.DO.Limit(limit)) +} + +func (s systemItemCardsDo) Offset(offset int) *systemItemCardsDo { + return s.withDO(s.DO.Offset(offset)) +} + +func (s systemItemCardsDo) Scopes(funcs ...func(gen.Dao) gen.Dao) *systemItemCardsDo { + return s.withDO(s.DO.Scopes(funcs...)) +} + +func (s systemItemCardsDo) Unscoped() *systemItemCardsDo { + return s.withDO(s.DO.Unscoped()) +} + +func (s systemItemCardsDo) Create(values ...*model.SystemItemCards) error { + if len(values) == 0 { + return nil + } + return s.DO.Create(values) +} + +func (s systemItemCardsDo) CreateInBatches(values []*model.SystemItemCards, batchSize int) error { + return s.DO.CreateInBatches(values, batchSize) +} + +// Save : !!! underlying implementation is different with GORM +// The method is equivalent to executing the statement: db.Clauses(clause.OnConflict{UpdateAll: true}).Create(values) +func (s systemItemCardsDo) Save(values ...*model.SystemItemCards) error { + if len(values) == 0 { + return nil + } + return s.DO.Save(values) +} + +func (s systemItemCardsDo) First() (*model.SystemItemCards, error) { + if result, err := s.DO.First(); err != nil { + return nil, err + } else { + return result.(*model.SystemItemCards), nil + } +} + +func (s systemItemCardsDo) Take() (*model.SystemItemCards, error) { + if result, err := s.DO.Take(); err != nil { + return nil, err + } else { + return result.(*model.SystemItemCards), nil + } +} + +func (s systemItemCardsDo) Last() (*model.SystemItemCards, error) { + if result, err := s.DO.Last(); err != nil { + return nil, err + } else { + return result.(*model.SystemItemCards), nil + } +} + +func (s systemItemCardsDo) Find() ([]*model.SystemItemCards, error) { + result, err := s.DO.Find() + return result.([]*model.SystemItemCards), err +} + +func (s systemItemCardsDo) FindInBatch(batchSize int, fc func(tx gen.Dao, batch int) error) (results []*model.SystemItemCards, err error) { + buf := make([]*model.SystemItemCards, 0, batchSize) + err = s.DO.FindInBatches(&buf, batchSize, func(tx gen.Dao, batch int) error { + defer func() { results = append(results, buf...) }() + return fc(tx, batch) + }) + return results, err +} + +func (s systemItemCardsDo) FindInBatches(result *[]*model.SystemItemCards, batchSize int, fc func(tx gen.Dao, batch int) error) error { + return s.DO.FindInBatches(result, batchSize, fc) +} + +func (s systemItemCardsDo) Attrs(attrs ...field.AssignExpr) *systemItemCardsDo { + return s.withDO(s.DO.Attrs(attrs...)) +} + +func (s systemItemCardsDo) Assign(attrs ...field.AssignExpr) *systemItemCardsDo { + return s.withDO(s.DO.Assign(attrs...)) +} + +func (s systemItemCardsDo) Joins(fields ...field.RelationField) *systemItemCardsDo { + for _, _f := range fields { + s = *s.withDO(s.DO.Joins(_f)) + } + return &s +} + +func (s systemItemCardsDo) Preload(fields ...field.RelationField) *systemItemCardsDo { + for _, _f := range fields { + s = *s.withDO(s.DO.Preload(_f)) + } + return &s +} + +func (s systemItemCardsDo) FirstOrInit() (*model.SystemItemCards, error) { + if result, err := s.DO.FirstOrInit(); err != nil { + return nil, err + } else { + return result.(*model.SystemItemCards), nil + } +} + +func (s systemItemCardsDo) FirstOrCreate() (*model.SystemItemCards, error) { + if result, err := s.DO.FirstOrCreate(); err != nil { + return nil, err + } else { + return result.(*model.SystemItemCards), nil + } +} + +func (s systemItemCardsDo) FindByPage(offset int, limit int) (result []*model.SystemItemCards, count int64, err error) { + result, err = s.Offset(offset).Limit(limit).Find() + if err != nil { + return + } + + if size := len(result); 0 < limit && 0 < size && size < limit { + count = int64(size + offset) + return + } + + count, err = s.Offset(-1).Limit(-1).Count() + return +} + +func (s systemItemCardsDo) ScanByPage(result interface{}, offset int, limit int) (count int64, err error) { + count, err = s.Count() + if err != nil { + return + } + + err = s.Offset(offset).Limit(limit).Scan(result) + return +} + +func (s systemItemCardsDo) Scan(result interface{}) (err error) { + return s.DO.Scan(result) +} + +func (s systemItemCardsDo) Delete(models ...*model.SystemItemCards) (result gen.ResultInfo, err error) { + return s.DO.Delete(models) +} + +func (s *systemItemCardsDo) withDO(do gen.Dao) *systemItemCardsDo { + s.DO = *do.(*gen.DO) + return s +} diff --git a/internal/repository/mysql/dao/user_addresses.gen.go b/internal/repository/mysql/dao/user_addresses.gen.go new file mode 100644 index 0000000..a86e794 --- /dev/null +++ b/internal/repository/mysql/dao/user_addresses.gen.go @@ -0,0 +1,364 @@ +// Code generated by gorm.io/gen. DO NOT EDIT. +// Code generated by gorm.io/gen. DO NOT EDIT. +// Code generated by gorm.io/gen. DO NOT EDIT. + +package dao + +import ( + "context" + + "gorm.io/gorm" + "gorm.io/gorm/clause" + "gorm.io/gorm/schema" + + "gorm.io/gen" + "gorm.io/gen/field" + + "gorm.io/plugin/dbresolver" + + "bindbox-game/internal/repository/mysql/model" +) + +func newUserAddresses(db *gorm.DB, opts ...gen.DOOption) userAddresses { + _userAddresses := userAddresses{} + + _userAddresses.userAddressesDo.UseDB(db, opts...) + _userAddresses.userAddressesDo.UseModel(&model.UserAddresses{}) + + tableName := _userAddresses.userAddressesDo.TableName() + _userAddresses.ALL = field.NewAsterisk(tableName) + _userAddresses.ID = field.NewInt64(tableName, "id") + _userAddresses.CreatedAt = field.NewTime(tableName, "created_at") + _userAddresses.UpdatedAt = field.NewTime(tableName, "updated_at") + _userAddresses.UserID = field.NewInt64(tableName, "user_id") + _userAddresses.Name = field.NewString(tableName, "name") + _userAddresses.Mobile = field.NewString(tableName, "mobile") + _userAddresses.Province = field.NewString(tableName, "province") + _userAddresses.City = field.NewString(tableName, "city") + _userAddresses.District = field.NewString(tableName, "district") + _userAddresses.Address = field.NewString(tableName, "address") + _userAddresses.IsDefault = field.NewInt32(tableName, "is_default") + _userAddresses.DefaultUserUnique = field.NewInt64(tableName, "default_user_unique") + + _userAddresses.fillFieldMap() + + return _userAddresses +} + +// userAddresses 用户地址 +type userAddresses struct { + userAddressesDo + + ALL field.Asterisk + ID field.Int64 // 主键ID + CreatedAt field.Time // 创建时间 + UpdatedAt field.Time // 更新时间 + UserID field.Int64 // 用户ID(user_members.id) + Name field.String // 收件人姓名 + Mobile field.String // 收件人手机号 + Province field.String // 省 + City field.String // 市 + District field.String // 区/县 + Address field.String // 详细地址 + IsDefault field.Int32 // 是否默认地址:0否 1是 + DefaultUserUnique field.Int64 // 用于唯一约束的生成列:默认地址→user_id + + fieldMap map[string]field.Expr +} + +func (u userAddresses) Table(newTableName string) *userAddresses { + u.userAddressesDo.UseTable(newTableName) + return u.updateTableName(newTableName) +} + +func (u userAddresses) As(alias string) *userAddresses { + u.userAddressesDo.DO = *(u.userAddressesDo.As(alias).(*gen.DO)) + return u.updateTableName(alias) +} + +func (u *userAddresses) updateTableName(table string) *userAddresses { + u.ALL = field.NewAsterisk(table) + u.ID = field.NewInt64(table, "id") + u.CreatedAt = field.NewTime(table, "created_at") + u.UpdatedAt = field.NewTime(table, "updated_at") + u.UserID = field.NewInt64(table, "user_id") + u.Name = field.NewString(table, "name") + u.Mobile = field.NewString(table, "mobile") + u.Province = field.NewString(table, "province") + u.City = field.NewString(table, "city") + u.District = field.NewString(table, "district") + u.Address = field.NewString(table, "address") + u.IsDefault = field.NewInt32(table, "is_default") + u.DefaultUserUnique = field.NewInt64(table, "default_user_unique") + + u.fillFieldMap() + + return u +} + +func (u *userAddresses) GetFieldByName(fieldName string) (field.OrderExpr, bool) { + _f, ok := u.fieldMap[fieldName] + if !ok || _f == nil { + return nil, false + } + _oe, ok := _f.(field.OrderExpr) + return _oe, ok +} + +func (u *userAddresses) fillFieldMap() { + u.fieldMap = make(map[string]field.Expr, 12) + u.fieldMap["id"] = u.ID + u.fieldMap["created_at"] = u.CreatedAt + u.fieldMap["updated_at"] = u.UpdatedAt + u.fieldMap["user_id"] = u.UserID + u.fieldMap["name"] = u.Name + u.fieldMap["mobile"] = u.Mobile + u.fieldMap["province"] = u.Province + u.fieldMap["city"] = u.City + u.fieldMap["district"] = u.District + u.fieldMap["address"] = u.Address + u.fieldMap["is_default"] = u.IsDefault + u.fieldMap["default_user_unique"] = u.DefaultUserUnique +} + +func (u userAddresses) clone(db *gorm.DB) userAddresses { + u.userAddressesDo.ReplaceConnPool(db.Statement.ConnPool) + return u +} + +func (u userAddresses) replaceDB(db *gorm.DB) userAddresses { + u.userAddressesDo.ReplaceDB(db) + return u +} + +type userAddressesDo struct{ gen.DO } + +func (u userAddressesDo) Debug() *userAddressesDo { + return u.withDO(u.DO.Debug()) +} + +func (u userAddressesDo) WithContext(ctx context.Context) *userAddressesDo { + return u.withDO(u.DO.WithContext(ctx)) +} + +func (u userAddressesDo) ReadDB() *userAddressesDo { + return u.Clauses(dbresolver.Read) +} + +func (u userAddressesDo) WriteDB() *userAddressesDo { + return u.Clauses(dbresolver.Write) +} + +func (u userAddressesDo) Session(config *gorm.Session) *userAddressesDo { + return u.withDO(u.DO.Session(config)) +} + +func (u userAddressesDo) Clauses(conds ...clause.Expression) *userAddressesDo { + return u.withDO(u.DO.Clauses(conds...)) +} + +func (u userAddressesDo) Returning(value interface{}, columns ...string) *userAddressesDo { + return u.withDO(u.DO.Returning(value, columns...)) +} + +func (u userAddressesDo) Not(conds ...gen.Condition) *userAddressesDo { + return u.withDO(u.DO.Not(conds...)) +} + +func (u userAddressesDo) Or(conds ...gen.Condition) *userAddressesDo { + return u.withDO(u.DO.Or(conds...)) +} + +func (u userAddressesDo) Select(conds ...field.Expr) *userAddressesDo { + return u.withDO(u.DO.Select(conds...)) +} + +func (u userAddressesDo) Where(conds ...gen.Condition) *userAddressesDo { + return u.withDO(u.DO.Where(conds...)) +} + +func (u userAddressesDo) Order(conds ...field.Expr) *userAddressesDo { + return u.withDO(u.DO.Order(conds...)) +} + +func (u userAddressesDo) Distinct(cols ...field.Expr) *userAddressesDo { + return u.withDO(u.DO.Distinct(cols...)) +} + +func (u userAddressesDo) Omit(cols ...field.Expr) *userAddressesDo { + return u.withDO(u.DO.Omit(cols...)) +} + +func (u userAddressesDo) Join(table schema.Tabler, on ...field.Expr) *userAddressesDo { + return u.withDO(u.DO.Join(table, on...)) +} + +func (u userAddressesDo) LeftJoin(table schema.Tabler, on ...field.Expr) *userAddressesDo { + return u.withDO(u.DO.LeftJoin(table, on...)) +} + +func (u userAddressesDo) RightJoin(table schema.Tabler, on ...field.Expr) *userAddressesDo { + return u.withDO(u.DO.RightJoin(table, on...)) +} + +func (u userAddressesDo) Group(cols ...field.Expr) *userAddressesDo { + return u.withDO(u.DO.Group(cols...)) +} + +func (u userAddressesDo) Having(conds ...gen.Condition) *userAddressesDo { + return u.withDO(u.DO.Having(conds...)) +} + +func (u userAddressesDo) Limit(limit int) *userAddressesDo { + return u.withDO(u.DO.Limit(limit)) +} + +func (u userAddressesDo) Offset(offset int) *userAddressesDo { + return u.withDO(u.DO.Offset(offset)) +} + +func (u userAddressesDo) Scopes(funcs ...func(gen.Dao) gen.Dao) *userAddressesDo { + return u.withDO(u.DO.Scopes(funcs...)) +} + +func (u userAddressesDo) Unscoped() *userAddressesDo { + return u.withDO(u.DO.Unscoped()) +} + +func (u userAddressesDo) Create(values ...*model.UserAddresses) error { + if len(values) == 0 { + return nil + } + return u.DO.Create(values) +} + +func (u userAddressesDo) CreateInBatches(values []*model.UserAddresses, batchSize int) error { + return u.DO.CreateInBatches(values, batchSize) +} + +// Save : !!! underlying implementation is different with GORM +// The method is equivalent to executing the statement: db.Clauses(clause.OnConflict{UpdateAll: true}).Create(values) +func (u userAddressesDo) Save(values ...*model.UserAddresses) error { + if len(values) == 0 { + return nil + } + return u.DO.Save(values) +} + +func (u userAddressesDo) First() (*model.UserAddresses, error) { + if result, err := u.DO.First(); err != nil { + return nil, err + } else { + return result.(*model.UserAddresses), nil + } +} + +func (u userAddressesDo) Take() (*model.UserAddresses, error) { + if result, err := u.DO.Take(); err != nil { + return nil, err + } else { + return result.(*model.UserAddresses), nil + } +} + +func (u userAddressesDo) Last() (*model.UserAddresses, error) { + if result, err := u.DO.Last(); err != nil { + return nil, err + } else { + return result.(*model.UserAddresses), nil + } +} + +func (u userAddressesDo) Find() ([]*model.UserAddresses, error) { + result, err := u.DO.Find() + return result.([]*model.UserAddresses), err +} + +func (u userAddressesDo) FindInBatch(batchSize int, fc func(tx gen.Dao, batch int) error) (results []*model.UserAddresses, err error) { + buf := make([]*model.UserAddresses, 0, batchSize) + err = u.DO.FindInBatches(&buf, batchSize, func(tx gen.Dao, batch int) error { + defer func() { results = append(results, buf...) }() + return fc(tx, batch) + }) + return results, err +} + +func (u userAddressesDo) FindInBatches(result *[]*model.UserAddresses, batchSize int, fc func(tx gen.Dao, batch int) error) error { + return u.DO.FindInBatches(result, batchSize, fc) +} + +func (u userAddressesDo) Attrs(attrs ...field.AssignExpr) *userAddressesDo { + return u.withDO(u.DO.Attrs(attrs...)) +} + +func (u userAddressesDo) Assign(attrs ...field.AssignExpr) *userAddressesDo { + return u.withDO(u.DO.Assign(attrs...)) +} + +func (u userAddressesDo) Joins(fields ...field.RelationField) *userAddressesDo { + for _, _f := range fields { + u = *u.withDO(u.DO.Joins(_f)) + } + return &u +} + +func (u userAddressesDo) Preload(fields ...field.RelationField) *userAddressesDo { + for _, _f := range fields { + u = *u.withDO(u.DO.Preload(_f)) + } + return &u +} + +func (u userAddressesDo) FirstOrInit() (*model.UserAddresses, error) { + if result, err := u.DO.FirstOrInit(); err != nil { + return nil, err + } else { + return result.(*model.UserAddresses), nil + } +} + +func (u userAddressesDo) FirstOrCreate() (*model.UserAddresses, error) { + if result, err := u.DO.FirstOrCreate(); err != nil { + return nil, err + } else { + return result.(*model.UserAddresses), nil + } +} + +func (u userAddressesDo) FindByPage(offset int, limit int) (result []*model.UserAddresses, count int64, err error) { + result, err = u.Offset(offset).Limit(limit).Find() + if err != nil { + return + } + + if size := len(result); 0 < limit && 0 < size && size < limit { + count = int64(size + offset) + return + } + + count, err = u.Offset(-1).Limit(-1).Count() + return +} + +func (u userAddressesDo) ScanByPage(result interface{}, offset int, limit int) (count int64, err error) { + count, err = u.Count() + if err != nil { + return + } + + err = u.Offset(offset).Limit(limit).Scan(result) + return +} + +func (u userAddressesDo) Scan(result interface{}) (err error) { + return u.DO.Scan(result) +} + +func (u userAddressesDo) Delete(models ...*model.UserAddresses) (result gen.ResultInfo, err error) { + return u.DO.Delete(models) +} + +func (u *userAddressesDo) withDO(do gen.Dao) *userAddressesDo { + u.DO = *do.(*gen.DO) + return u +} diff --git a/internal/repository/mysql/dao/user_coupons.gen.go b/internal/repository/mysql/dao/user_coupons.gen.go new file mode 100644 index 0000000..0bc820f --- /dev/null +++ b/internal/repository/mysql/dao/user_coupons.gen.go @@ -0,0 +1,356 @@ +// Code generated by gorm.io/gen. DO NOT EDIT. +// Code generated by gorm.io/gen. DO NOT EDIT. +// Code generated by gorm.io/gen. DO NOT EDIT. + +package dao + +import ( + "context" + + "gorm.io/gorm" + "gorm.io/gorm/clause" + "gorm.io/gorm/schema" + + "gorm.io/gen" + "gorm.io/gen/field" + + "gorm.io/plugin/dbresolver" + + "bindbox-game/internal/repository/mysql/model" +) + +func newUserCoupons(db *gorm.DB, opts ...gen.DOOption) userCoupons { + _userCoupons := userCoupons{} + + _userCoupons.userCouponsDo.UseDB(db, opts...) + _userCoupons.userCouponsDo.UseModel(&model.UserCoupons{}) + + tableName := _userCoupons.userCouponsDo.TableName() + _userCoupons.ALL = field.NewAsterisk(tableName) + _userCoupons.ID = field.NewInt64(tableName, "id") + _userCoupons.CreatedAt = field.NewTime(tableName, "created_at") + _userCoupons.UpdatedAt = field.NewTime(tableName, "updated_at") + _userCoupons.UserID = field.NewInt64(tableName, "user_id") + _userCoupons.CouponID = field.NewInt64(tableName, "coupon_id") + _userCoupons.UsedOrderID = field.NewInt64(tableName, "used_order_id") + _userCoupons.UsedAt = field.NewTime(tableName, "used_at") + _userCoupons.ValidStart = field.NewTime(tableName, "valid_start") + _userCoupons.ValidEnd = field.NewTime(tableName, "valid_end") + _userCoupons.Status = field.NewInt32(tableName, "status") + + _userCoupons.fillFieldMap() + + return _userCoupons +} + +// userCoupons 用户持券 +type userCoupons struct { + userCouponsDo + + ALL field.Asterisk + ID field.Int64 // 主键ID + CreatedAt field.Time // 创建时间 + UpdatedAt field.Time // 更新时间 + UserID field.Int64 // 用户ID(user_members.id) + CouponID field.Int64 // 券模板ID(system_coupons.id) + UsedOrderID field.Int64 // 核销的订单ID(orders.id) + UsedAt field.Time // 核销时间 + ValidStart field.Time // 有效期开始 + ValidEnd field.Time // 有效期结束 + Status field.Int32 // 状态:1未使用 2已使用 3已过期 + + fieldMap map[string]field.Expr +} + +func (u userCoupons) Table(newTableName string) *userCoupons { + u.userCouponsDo.UseTable(newTableName) + return u.updateTableName(newTableName) +} + +func (u userCoupons) As(alias string) *userCoupons { + u.userCouponsDo.DO = *(u.userCouponsDo.As(alias).(*gen.DO)) + return u.updateTableName(alias) +} + +func (u *userCoupons) updateTableName(table string) *userCoupons { + u.ALL = field.NewAsterisk(table) + u.ID = field.NewInt64(table, "id") + u.CreatedAt = field.NewTime(table, "created_at") + u.UpdatedAt = field.NewTime(table, "updated_at") + u.UserID = field.NewInt64(table, "user_id") + u.CouponID = field.NewInt64(table, "coupon_id") + u.UsedOrderID = field.NewInt64(table, "used_order_id") + u.UsedAt = field.NewTime(table, "used_at") + u.ValidStart = field.NewTime(table, "valid_start") + u.ValidEnd = field.NewTime(table, "valid_end") + u.Status = field.NewInt32(table, "status") + + u.fillFieldMap() + + return u +} + +func (u *userCoupons) GetFieldByName(fieldName string) (field.OrderExpr, bool) { + _f, ok := u.fieldMap[fieldName] + if !ok || _f == nil { + return nil, false + } + _oe, ok := _f.(field.OrderExpr) + return _oe, ok +} + +func (u *userCoupons) fillFieldMap() { + u.fieldMap = make(map[string]field.Expr, 10) + u.fieldMap["id"] = u.ID + u.fieldMap["created_at"] = u.CreatedAt + u.fieldMap["updated_at"] = u.UpdatedAt + u.fieldMap["user_id"] = u.UserID + u.fieldMap["coupon_id"] = u.CouponID + u.fieldMap["used_order_id"] = u.UsedOrderID + u.fieldMap["used_at"] = u.UsedAt + u.fieldMap["valid_start"] = u.ValidStart + u.fieldMap["valid_end"] = u.ValidEnd + u.fieldMap["status"] = u.Status +} + +func (u userCoupons) clone(db *gorm.DB) userCoupons { + u.userCouponsDo.ReplaceConnPool(db.Statement.ConnPool) + return u +} + +func (u userCoupons) replaceDB(db *gorm.DB) userCoupons { + u.userCouponsDo.ReplaceDB(db) + return u +} + +type userCouponsDo struct{ gen.DO } + +func (u userCouponsDo) Debug() *userCouponsDo { + return u.withDO(u.DO.Debug()) +} + +func (u userCouponsDo) WithContext(ctx context.Context) *userCouponsDo { + return u.withDO(u.DO.WithContext(ctx)) +} + +func (u userCouponsDo) ReadDB() *userCouponsDo { + return u.Clauses(dbresolver.Read) +} + +func (u userCouponsDo) WriteDB() *userCouponsDo { + return u.Clauses(dbresolver.Write) +} + +func (u userCouponsDo) Session(config *gorm.Session) *userCouponsDo { + return u.withDO(u.DO.Session(config)) +} + +func (u userCouponsDo) Clauses(conds ...clause.Expression) *userCouponsDo { + return u.withDO(u.DO.Clauses(conds...)) +} + +func (u userCouponsDo) Returning(value interface{}, columns ...string) *userCouponsDo { + return u.withDO(u.DO.Returning(value, columns...)) +} + +func (u userCouponsDo) Not(conds ...gen.Condition) *userCouponsDo { + return u.withDO(u.DO.Not(conds...)) +} + +func (u userCouponsDo) Or(conds ...gen.Condition) *userCouponsDo { + return u.withDO(u.DO.Or(conds...)) +} + +func (u userCouponsDo) Select(conds ...field.Expr) *userCouponsDo { + return u.withDO(u.DO.Select(conds...)) +} + +func (u userCouponsDo) Where(conds ...gen.Condition) *userCouponsDo { + return u.withDO(u.DO.Where(conds...)) +} + +func (u userCouponsDo) Order(conds ...field.Expr) *userCouponsDo { + return u.withDO(u.DO.Order(conds...)) +} + +func (u userCouponsDo) Distinct(cols ...field.Expr) *userCouponsDo { + return u.withDO(u.DO.Distinct(cols...)) +} + +func (u userCouponsDo) Omit(cols ...field.Expr) *userCouponsDo { + return u.withDO(u.DO.Omit(cols...)) +} + +func (u userCouponsDo) Join(table schema.Tabler, on ...field.Expr) *userCouponsDo { + return u.withDO(u.DO.Join(table, on...)) +} + +func (u userCouponsDo) LeftJoin(table schema.Tabler, on ...field.Expr) *userCouponsDo { + return u.withDO(u.DO.LeftJoin(table, on...)) +} + +func (u userCouponsDo) RightJoin(table schema.Tabler, on ...field.Expr) *userCouponsDo { + return u.withDO(u.DO.RightJoin(table, on...)) +} + +func (u userCouponsDo) Group(cols ...field.Expr) *userCouponsDo { + return u.withDO(u.DO.Group(cols...)) +} + +func (u userCouponsDo) Having(conds ...gen.Condition) *userCouponsDo { + return u.withDO(u.DO.Having(conds...)) +} + +func (u userCouponsDo) Limit(limit int) *userCouponsDo { + return u.withDO(u.DO.Limit(limit)) +} + +func (u userCouponsDo) Offset(offset int) *userCouponsDo { + return u.withDO(u.DO.Offset(offset)) +} + +func (u userCouponsDo) Scopes(funcs ...func(gen.Dao) gen.Dao) *userCouponsDo { + return u.withDO(u.DO.Scopes(funcs...)) +} + +func (u userCouponsDo) Unscoped() *userCouponsDo { + return u.withDO(u.DO.Unscoped()) +} + +func (u userCouponsDo) Create(values ...*model.UserCoupons) error { + if len(values) == 0 { + return nil + } + return u.DO.Create(values) +} + +func (u userCouponsDo) CreateInBatches(values []*model.UserCoupons, batchSize int) error { + return u.DO.CreateInBatches(values, batchSize) +} + +// Save : !!! underlying implementation is different with GORM +// The method is equivalent to executing the statement: db.Clauses(clause.OnConflict{UpdateAll: true}).Create(values) +func (u userCouponsDo) Save(values ...*model.UserCoupons) error { + if len(values) == 0 { + return nil + } + return u.DO.Save(values) +} + +func (u userCouponsDo) First() (*model.UserCoupons, error) { + if result, err := u.DO.First(); err != nil { + return nil, err + } else { + return result.(*model.UserCoupons), nil + } +} + +func (u userCouponsDo) Take() (*model.UserCoupons, error) { + if result, err := u.DO.Take(); err != nil { + return nil, err + } else { + return result.(*model.UserCoupons), nil + } +} + +func (u userCouponsDo) Last() (*model.UserCoupons, error) { + if result, err := u.DO.Last(); err != nil { + return nil, err + } else { + return result.(*model.UserCoupons), nil + } +} + +func (u userCouponsDo) Find() ([]*model.UserCoupons, error) { + result, err := u.DO.Find() + return result.([]*model.UserCoupons), err +} + +func (u userCouponsDo) FindInBatch(batchSize int, fc func(tx gen.Dao, batch int) error) (results []*model.UserCoupons, err error) { + buf := make([]*model.UserCoupons, 0, batchSize) + err = u.DO.FindInBatches(&buf, batchSize, func(tx gen.Dao, batch int) error { + defer func() { results = append(results, buf...) }() + return fc(tx, batch) + }) + return results, err +} + +func (u userCouponsDo) FindInBatches(result *[]*model.UserCoupons, batchSize int, fc func(tx gen.Dao, batch int) error) error { + return u.DO.FindInBatches(result, batchSize, fc) +} + +func (u userCouponsDo) Attrs(attrs ...field.AssignExpr) *userCouponsDo { + return u.withDO(u.DO.Attrs(attrs...)) +} + +func (u userCouponsDo) Assign(attrs ...field.AssignExpr) *userCouponsDo { + return u.withDO(u.DO.Assign(attrs...)) +} + +func (u userCouponsDo) Joins(fields ...field.RelationField) *userCouponsDo { + for _, _f := range fields { + u = *u.withDO(u.DO.Joins(_f)) + } + return &u +} + +func (u userCouponsDo) Preload(fields ...field.RelationField) *userCouponsDo { + for _, _f := range fields { + u = *u.withDO(u.DO.Preload(_f)) + } + return &u +} + +func (u userCouponsDo) FirstOrInit() (*model.UserCoupons, error) { + if result, err := u.DO.FirstOrInit(); err != nil { + return nil, err + } else { + return result.(*model.UserCoupons), nil + } +} + +func (u userCouponsDo) FirstOrCreate() (*model.UserCoupons, error) { + if result, err := u.DO.FirstOrCreate(); err != nil { + return nil, err + } else { + return result.(*model.UserCoupons), nil + } +} + +func (u userCouponsDo) FindByPage(offset int, limit int) (result []*model.UserCoupons, count int64, err error) { + result, err = u.Offset(offset).Limit(limit).Find() + if err != nil { + return + } + + if size := len(result); 0 < limit && 0 < size && size < limit { + count = int64(size + offset) + return + } + + count, err = u.Offset(-1).Limit(-1).Count() + return +} + +func (u userCouponsDo) ScanByPage(result interface{}, offset int, limit int) (count int64, err error) { + count, err = u.Count() + if err != nil { + return + } + + err = u.Offset(offset).Limit(limit).Scan(result) + return +} + +func (u userCouponsDo) Scan(result interface{}) (err error) { + return u.DO.Scan(result) +} + +func (u userCouponsDo) Delete(models ...*model.UserCoupons) (result gen.ResultInfo, err error) { + return u.DO.Delete(models) +} + +func (u *userCouponsDo) withDO(do gen.Dao) *userCouponsDo { + u.DO = *do.(*gen.DO) + return u +} diff --git a/internal/repository/mysql/dao/user_inventory.gen.go b/internal/repository/mysql/dao/user_inventory.gen.go new file mode 100644 index 0000000..85df988 --- /dev/null +++ b/internal/repository/mysql/dao/user_inventory.gen.go @@ -0,0 +1,356 @@ +// Code generated by gorm.io/gen. DO NOT EDIT. +// Code generated by gorm.io/gen. DO NOT EDIT. +// Code generated by gorm.io/gen. DO NOT EDIT. + +package dao + +import ( + "context" + + "gorm.io/gorm" + "gorm.io/gorm/clause" + "gorm.io/gorm/schema" + + "gorm.io/gen" + "gorm.io/gen/field" + + "gorm.io/plugin/dbresolver" + + "bindbox-game/internal/repository/mysql/model" +) + +func newUserInventory(db *gorm.DB, opts ...gen.DOOption) userInventory { + _userInventory := userInventory{} + + _userInventory.userInventoryDo.UseDB(db, opts...) + _userInventory.userInventoryDo.UseModel(&model.UserInventory{}) + + tableName := _userInventory.userInventoryDo.TableName() + _userInventory.ALL = field.NewAsterisk(tableName) + _userInventory.ID = field.NewInt64(tableName, "id") + _userInventory.CreatedAt = field.NewTime(tableName, "created_at") + _userInventory.UpdatedAt = field.NewTime(tableName, "updated_at") + _userInventory.UserID = field.NewInt64(tableName, "user_id") + _userInventory.ProductID = field.NewInt64(tableName, "product_id") + _userInventory.OrderID = field.NewInt64(tableName, "order_id") + _userInventory.ActivityID = field.NewInt64(tableName, "activity_id") + _userInventory.RewardID = field.NewInt64(tableName, "reward_id") + _userInventory.Status = field.NewInt32(tableName, "status") + _userInventory.Remark = field.NewString(tableName, "remark") + + _userInventory.fillFieldMap() + + return _userInventory +} + +// userInventory 用户资产(资产) +type userInventory struct { + userInventoryDo + + ALL field.Asterisk + ID field.Int64 // 主键ID + CreatedAt field.Time // 创建时间 + UpdatedAt field.Time // 更新时间 + UserID field.Int64 // 资产归属用户ID + ProductID field.Int64 // 资产对应商品ID(实物奖/商品) + OrderID field.Int64 // 来源订单ID + ActivityID field.Int64 // 来源活动ID + RewardID field.Int64 // 来源奖励ID(activity_reward_settings.id) + Status field.Int32 // 状态:1持有 2作废 3已使用/发货 + Remark field.String // 备注 + + fieldMap map[string]field.Expr +} + +func (u userInventory) Table(newTableName string) *userInventory { + u.userInventoryDo.UseTable(newTableName) + return u.updateTableName(newTableName) +} + +func (u userInventory) As(alias string) *userInventory { + u.userInventoryDo.DO = *(u.userInventoryDo.As(alias).(*gen.DO)) + return u.updateTableName(alias) +} + +func (u *userInventory) updateTableName(table string) *userInventory { + u.ALL = field.NewAsterisk(table) + u.ID = field.NewInt64(table, "id") + u.CreatedAt = field.NewTime(table, "created_at") + u.UpdatedAt = field.NewTime(table, "updated_at") + u.UserID = field.NewInt64(table, "user_id") + u.ProductID = field.NewInt64(table, "product_id") + u.OrderID = field.NewInt64(table, "order_id") + u.ActivityID = field.NewInt64(table, "activity_id") + u.RewardID = field.NewInt64(table, "reward_id") + u.Status = field.NewInt32(table, "status") + u.Remark = field.NewString(table, "remark") + + u.fillFieldMap() + + return u +} + +func (u *userInventory) GetFieldByName(fieldName string) (field.OrderExpr, bool) { + _f, ok := u.fieldMap[fieldName] + if !ok || _f == nil { + return nil, false + } + _oe, ok := _f.(field.OrderExpr) + return _oe, ok +} + +func (u *userInventory) fillFieldMap() { + u.fieldMap = make(map[string]field.Expr, 10) + u.fieldMap["id"] = u.ID + u.fieldMap["created_at"] = u.CreatedAt + u.fieldMap["updated_at"] = u.UpdatedAt + u.fieldMap["user_id"] = u.UserID + u.fieldMap["product_id"] = u.ProductID + u.fieldMap["order_id"] = u.OrderID + u.fieldMap["activity_id"] = u.ActivityID + u.fieldMap["reward_id"] = u.RewardID + u.fieldMap["status"] = u.Status + u.fieldMap["remark"] = u.Remark +} + +func (u userInventory) clone(db *gorm.DB) userInventory { + u.userInventoryDo.ReplaceConnPool(db.Statement.ConnPool) + return u +} + +func (u userInventory) replaceDB(db *gorm.DB) userInventory { + u.userInventoryDo.ReplaceDB(db) + return u +} + +type userInventoryDo struct{ gen.DO } + +func (u userInventoryDo) Debug() *userInventoryDo { + return u.withDO(u.DO.Debug()) +} + +func (u userInventoryDo) WithContext(ctx context.Context) *userInventoryDo { + return u.withDO(u.DO.WithContext(ctx)) +} + +func (u userInventoryDo) ReadDB() *userInventoryDo { + return u.Clauses(dbresolver.Read) +} + +func (u userInventoryDo) WriteDB() *userInventoryDo { + return u.Clauses(dbresolver.Write) +} + +func (u userInventoryDo) Session(config *gorm.Session) *userInventoryDo { + return u.withDO(u.DO.Session(config)) +} + +func (u userInventoryDo) Clauses(conds ...clause.Expression) *userInventoryDo { + return u.withDO(u.DO.Clauses(conds...)) +} + +func (u userInventoryDo) Returning(value interface{}, columns ...string) *userInventoryDo { + return u.withDO(u.DO.Returning(value, columns...)) +} + +func (u userInventoryDo) Not(conds ...gen.Condition) *userInventoryDo { + return u.withDO(u.DO.Not(conds...)) +} + +func (u userInventoryDo) Or(conds ...gen.Condition) *userInventoryDo { + return u.withDO(u.DO.Or(conds...)) +} + +func (u userInventoryDo) Select(conds ...field.Expr) *userInventoryDo { + return u.withDO(u.DO.Select(conds...)) +} + +func (u userInventoryDo) Where(conds ...gen.Condition) *userInventoryDo { + return u.withDO(u.DO.Where(conds...)) +} + +func (u userInventoryDo) Order(conds ...field.Expr) *userInventoryDo { + return u.withDO(u.DO.Order(conds...)) +} + +func (u userInventoryDo) Distinct(cols ...field.Expr) *userInventoryDo { + return u.withDO(u.DO.Distinct(cols...)) +} + +func (u userInventoryDo) Omit(cols ...field.Expr) *userInventoryDo { + return u.withDO(u.DO.Omit(cols...)) +} + +func (u userInventoryDo) Join(table schema.Tabler, on ...field.Expr) *userInventoryDo { + return u.withDO(u.DO.Join(table, on...)) +} + +func (u userInventoryDo) LeftJoin(table schema.Tabler, on ...field.Expr) *userInventoryDo { + return u.withDO(u.DO.LeftJoin(table, on...)) +} + +func (u userInventoryDo) RightJoin(table schema.Tabler, on ...field.Expr) *userInventoryDo { + return u.withDO(u.DO.RightJoin(table, on...)) +} + +func (u userInventoryDo) Group(cols ...field.Expr) *userInventoryDo { + return u.withDO(u.DO.Group(cols...)) +} + +func (u userInventoryDo) Having(conds ...gen.Condition) *userInventoryDo { + return u.withDO(u.DO.Having(conds...)) +} + +func (u userInventoryDo) Limit(limit int) *userInventoryDo { + return u.withDO(u.DO.Limit(limit)) +} + +func (u userInventoryDo) Offset(offset int) *userInventoryDo { + return u.withDO(u.DO.Offset(offset)) +} + +func (u userInventoryDo) Scopes(funcs ...func(gen.Dao) gen.Dao) *userInventoryDo { + return u.withDO(u.DO.Scopes(funcs...)) +} + +func (u userInventoryDo) Unscoped() *userInventoryDo { + return u.withDO(u.DO.Unscoped()) +} + +func (u userInventoryDo) Create(values ...*model.UserInventory) error { + if len(values) == 0 { + return nil + } + return u.DO.Create(values) +} + +func (u userInventoryDo) CreateInBatches(values []*model.UserInventory, batchSize int) error { + return u.DO.CreateInBatches(values, batchSize) +} + +// Save : !!! underlying implementation is different with GORM +// The method is equivalent to executing the statement: db.Clauses(clause.OnConflict{UpdateAll: true}).Create(values) +func (u userInventoryDo) Save(values ...*model.UserInventory) error { + if len(values) == 0 { + return nil + } + return u.DO.Save(values) +} + +func (u userInventoryDo) First() (*model.UserInventory, error) { + if result, err := u.DO.First(); err != nil { + return nil, err + } else { + return result.(*model.UserInventory), nil + } +} + +func (u userInventoryDo) Take() (*model.UserInventory, error) { + if result, err := u.DO.Take(); err != nil { + return nil, err + } else { + return result.(*model.UserInventory), nil + } +} + +func (u userInventoryDo) Last() (*model.UserInventory, error) { + if result, err := u.DO.Last(); err != nil { + return nil, err + } else { + return result.(*model.UserInventory), nil + } +} + +func (u userInventoryDo) Find() ([]*model.UserInventory, error) { + result, err := u.DO.Find() + return result.([]*model.UserInventory), err +} + +func (u userInventoryDo) FindInBatch(batchSize int, fc func(tx gen.Dao, batch int) error) (results []*model.UserInventory, err error) { + buf := make([]*model.UserInventory, 0, batchSize) + err = u.DO.FindInBatches(&buf, batchSize, func(tx gen.Dao, batch int) error { + defer func() { results = append(results, buf...) }() + return fc(tx, batch) + }) + return results, err +} + +func (u userInventoryDo) FindInBatches(result *[]*model.UserInventory, batchSize int, fc func(tx gen.Dao, batch int) error) error { + return u.DO.FindInBatches(result, batchSize, fc) +} + +func (u userInventoryDo) Attrs(attrs ...field.AssignExpr) *userInventoryDo { + return u.withDO(u.DO.Attrs(attrs...)) +} + +func (u userInventoryDo) Assign(attrs ...field.AssignExpr) *userInventoryDo { + return u.withDO(u.DO.Assign(attrs...)) +} + +func (u userInventoryDo) Joins(fields ...field.RelationField) *userInventoryDo { + for _, _f := range fields { + u = *u.withDO(u.DO.Joins(_f)) + } + return &u +} + +func (u userInventoryDo) Preload(fields ...field.RelationField) *userInventoryDo { + for _, _f := range fields { + u = *u.withDO(u.DO.Preload(_f)) + } + return &u +} + +func (u userInventoryDo) FirstOrInit() (*model.UserInventory, error) { + if result, err := u.DO.FirstOrInit(); err != nil { + return nil, err + } else { + return result.(*model.UserInventory), nil + } +} + +func (u userInventoryDo) FirstOrCreate() (*model.UserInventory, error) { + if result, err := u.DO.FirstOrCreate(); err != nil { + return nil, err + } else { + return result.(*model.UserInventory), nil + } +} + +func (u userInventoryDo) FindByPage(offset int, limit int) (result []*model.UserInventory, count int64, err error) { + result, err = u.Offset(offset).Limit(limit).Find() + if err != nil { + return + } + + if size := len(result); 0 < limit && 0 < size && size < limit { + count = int64(size + offset) + return + } + + count, err = u.Offset(-1).Limit(-1).Count() + return +} + +func (u userInventoryDo) ScanByPage(result interface{}, offset int, limit int) (count int64, err error) { + count, err = u.Count() + if err != nil { + return + } + + err = u.Offset(offset).Limit(limit).Scan(result) + return +} + +func (u userInventoryDo) Scan(result interface{}) (err error) { + return u.DO.Scan(result) +} + +func (u userInventoryDo) Delete(models ...*model.UserInventory) (result gen.ResultInfo, err error) { + return u.DO.Delete(models) +} + +func (u *userInventoryDo) withDO(do gen.Dao) *userInventoryDo { + u.DO = *do.(*gen.DO) + return u +} diff --git a/internal/repository/mysql/dao/user_inventory_transfers.gen.go b/internal/repository/mysql/dao/user_inventory_transfers.gen.go new file mode 100644 index 0000000..7608efb --- /dev/null +++ b/internal/repository/mysql/dao/user_inventory_transfers.gen.go @@ -0,0 +1,340 @@ +// Code generated by gorm.io/gen. DO NOT EDIT. +// Code generated by gorm.io/gen. DO NOT EDIT. +// Code generated by gorm.io/gen. DO NOT EDIT. + +package dao + +import ( + "context" + + "gorm.io/gorm" + "gorm.io/gorm/clause" + "gorm.io/gorm/schema" + + "gorm.io/gen" + "gorm.io/gen/field" + + "gorm.io/plugin/dbresolver" + + "bindbox-game/internal/repository/mysql/model" +) + +func newUserInventoryTransfers(db *gorm.DB, opts ...gen.DOOption) userInventoryTransfers { + _userInventoryTransfers := userInventoryTransfers{} + + _userInventoryTransfers.userInventoryTransfersDo.UseDB(db, opts...) + _userInventoryTransfers.userInventoryTransfersDo.UseModel(&model.UserInventoryTransfers{}) + + tableName := _userInventoryTransfers.userInventoryTransfersDo.TableName() + _userInventoryTransfers.ALL = field.NewAsterisk(tableName) + _userInventoryTransfers.ID = field.NewInt64(tableName, "id") + _userInventoryTransfers.CreatedAt = field.NewTime(tableName, "created_at") + _userInventoryTransfers.InventoryID = field.NewInt64(tableName, "inventory_id") + _userInventoryTransfers.FromUserID = field.NewInt64(tableName, "from_user_id") + _userInventoryTransfers.ToUserID = field.NewInt64(tableName, "to_user_id") + _userInventoryTransfers.Remark = field.NewString(tableName, "remark") + + _userInventoryTransfers.fillFieldMap() + + return _userInventoryTransfers +} + +// userInventoryTransfers 资产转赠流水 +type userInventoryTransfers struct { + userInventoryTransfersDo + + ALL field.Asterisk + ID field.Int64 // 主键ID + CreatedAt field.Time // 创建时间 + InventoryID field.Int64 // 资产ID(user_inventory.id) + FromUserID field.Int64 // 转出用户ID + ToUserID field.Int64 // 转入用户ID + Remark field.String // 备注 + + fieldMap map[string]field.Expr +} + +func (u userInventoryTransfers) Table(newTableName string) *userInventoryTransfers { + u.userInventoryTransfersDo.UseTable(newTableName) + return u.updateTableName(newTableName) +} + +func (u userInventoryTransfers) As(alias string) *userInventoryTransfers { + u.userInventoryTransfersDo.DO = *(u.userInventoryTransfersDo.As(alias).(*gen.DO)) + return u.updateTableName(alias) +} + +func (u *userInventoryTransfers) updateTableName(table string) *userInventoryTransfers { + u.ALL = field.NewAsterisk(table) + u.ID = field.NewInt64(table, "id") + u.CreatedAt = field.NewTime(table, "created_at") + u.InventoryID = field.NewInt64(table, "inventory_id") + u.FromUserID = field.NewInt64(table, "from_user_id") + u.ToUserID = field.NewInt64(table, "to_user_id") + u.Remark = field.NewString(table, "remark") + + u.fillFieldMap() + + return u +} + +func (u *userInventoryTransfers) GetFieldByName(fieldName string) (field.OrderExpr, bool) { + _f, ok := u.fieldMap[fieldName] + if !ok || _f == nil { + return nil, false + } + _oe, ok := _f.(field.OrderExpr) + return _oe, ok +} + +func (u *userInventoryTransfers) fillFieldMap() { + u.fieldMap = make(map[string]field.Expr, 6) + u.fieldMap["id"] = u.ID + u.fieldMap["created_at"] = u.CreatedAt + u.fieldMap["inventory_id"] = u.InventoryID + u.fieldMap["from_user_id"] = u.FromUserID + u.fieldMap["to_user_id"] = u.ToUserID + u.fieldMap["remark"] = u.Remark +} + +func (u userInventoryTransfers) clone(db *gorm.DB) userInventoryTransfers { + u.userInventoryTransfersDo.ReplaceConnPool(db.Statement.ConnPool) + return u +} + +func (u userInventoryTransfers) replaceDB(db *gorm.DB) userInventoryTransfers { + u.userInventoryTransfersDo.ReplaceDB(db) + return u +} + +type userInventoryTransfersDo struct{ gen.DO } + +func (u userInventoryTransfersDo) Debug() *userInventoryTransfersDo { + return u.withDO(u.DO.Debug()) +} + +func (u userInventoryTransfersDo) WithContext(ctx context.Context) *userInventoryTransfersDo { + return u.withDO(u.DO.WithContext(ctx)) +} + +func (u userInventoryTransfersDo) ReadDB() *userInventoryTransfersDo { + return u.Clauses(dbresolver.Read) +} + +func (u userInventoryTransfersDo) WriteDB() *userInventoryTransfersDo { + return u.Clauses(dbresolver.Write) +} + +func (u userInventoryTransfersDo) Session(config *gorm.Session) *userInventoryTransfersDo { + return u.withDO(u.DO.Session(config)) +} + +func (u userInventoryTransfersDo) Clauses(conds ...clause.Expression) *userInventoryTransfersDo { + return u.withDO(u.DO.Clauses(conds...)) +} + +func (u userInventoryTransfersDo) Returning(value interface{}, columns ...string) *userInventoryTransfersDo { + return u.withDO(u.DO.Returning(value, columns...)) +} + +func (u userInventoryTransfersDo) Not(conds ...gen.Condition) *userInventoryTransfersDo { + return u.withDO(u.DO.Not(conds...)) +} + +func (u userInventoryTransfersDo) Or(conds ...gen.Condition) *userInventoryTransfersDo { + return u.withDO(u.DO.Or(conds...)) +} + +func (u userInventoryTransfersDo) Select(conds ...field.Expr) *userInventoryTransfersDo { + return u.withDO(u.DO.Select(conds...)) +} + +func (u userInventoryTransfersDo) Where(conds ...gen.Condition) *userInventoryTransfersDo { + return u.withDO(u.DO.Where(conds...)) +} + +func (u userInventoryTransfersDo) Order(conds ...field.Expr) *userInventoryTransfersDo { + return u.withDO(u.DO.Order(conds...)) +} + +func (u userInventoryTransfersDo) Distinct(cols ...field.Expr) *userInventoryTransfersDo { + return u.withDO(u.DO.Distinct(cols...)) +} + +func (u userInventoryTransfersDo) Omit(cols ...field.Expr) *userInventoryTransfersDo { + return u.withDO(u.DO.Omit(cols...)) +} + +func (u userInventoryTransfersDo) Join(table schema.Tabler, on ...field.Expr) *userInventoryTransfersDo { + return u.withDO(u.DO.Join(table, on...)) +} + +func (u userInventoryTransfersDo) LeftJoin(table schema.Tabler, on ...field.Expr) *userInventoryTransfersDo { + return u.withDO(u.DO.LeftJoin(table, on...)) +} + +func (u userInventoryTransfersDo) RightJoin(table schema.Tabler, on ...field.Expr) *userInventoryTransfersDo { + return u.withDO(u.DO.RightJoin(table, on...)) +} + +func (u userInventoryTransfersDo) Group(cols ...field.Expr) *userInventoryTransfersDo { + return u.withDO(u.DO.Group(cols...)) +} + +func (u userInventoryTransfersDo) Having(conds ...gen.Condition) *userInventoryTransfersDo { + return u.withDO(u.DO.Having(conds...)) +} + +func (u userInventoryTransfersDo) Limit(limit int) *userInventoryTransfersDo { + return u.withDO(u.DO.Limit(limit)) +} + +func (u userInventoryTransfersDo) Offset(offset int) *userInventoryTransfersDo { + return u.withDO(u.DO.Offset(offset)) +} + +func (u userInventoryTransfersDo) Scopes(funcs ...func(gen.Dao) gen.Dao) *userInventoryTransfersDo { + return u.withDO(u.DO.Scopes(funcs...)) +} + +func (u userInventoryTransfersDo) Unscoped() *userInventoryTransfersDo { + return u.withDO(u.DO.Unscoped()) +} + +func (u userInventoryTransfersDo) Create(values ...*model.UserInventoryTransfers) error { + if len(values) == 0 { + return nil + } + return u.DO.Create(values) +} + +func (u userInventoryTransfersDo) CreateInBatches(values []*model.UserInventoryTransfers, batchSize int) error { + return u.DO.CreateInBatches(values, batchSize) +} + +// Save : !!! underlying implementation is different with GORM +// The method is equivalent to executing the statement: db.Clauses(clause.OnConflict{UpdateAll: true}).Create(values) +func (u userInventoryTransfersDo) Save(values ...*model.UserInventoryTransfers) error { + if len(values) == 0 { + return nil + } + return u.DO.Save(values) +} + +func (u userInventoryTransfersDo) First() (*model.UserInventoryTransfers, error) { + if result, err := u.DO.First(); err != nil { + return nil, err + } else { + return result.(*model.UserInventoryTransfers), nil + } +} + +func (u userInventoryTransfersDo) Take() (*model.UserInventoryTransfers, error) { + if result, err := u.DO.Take(); err != nil { + return nil, err + } else { + return result.(*model.UserInventoryTransfers), nil + } +} + +func (u userInventoryTransfersDo) Last() (*model.UserInventoryTransfers, error) { + if result, err := u.DO.Last(); err != nil { + return nil, err + } else { + return result.(*model.UserInventoryTransfers), nil + } +} + +func (u userInventoryTransfersDo) Find() ([]*model.UserInventoryTransfers, error) { + result, err := u.DO.Find() + return result.([]*model.UserInventoryTransfers), err +} + +func (u userInventoryTransfersDo) FindInBatch(batchSize int, fc func(tx gen.Dao, batch int) error) (results []*model.UserInventoryTransfers, err error) { + buf := make([]*model.UserInventoryTransfers, 0, batchSize) + err = u.DO.FindInBatches(&buf, batchSize, func(tx gen.Dao, batch int) error { + defer func() { results = append(results, buf...) }() + return fc(tx, batch) + }) + return results, err +} + +func (u userInventoryTransfersDo) FindInBatches(result *[]*model.UserInventoryTransfers, batchSize int, fc func(tx gen.Dao, batch int) error) error { + return u.DO.FindInBatches(result, batchSize, fc) +} + +func (u userInventoryTransfersDo) Attrs(attrs ...field.AssignExpr) *userInventoryTransfersDo { + return u.withDO(u.DO.Attrs(attrs...)) +} + +func (u userInventoryTransfersDo) Assign(attrs ...field.AssignExpr) *userInventoryTransfersDo { + return u.withDO(u.DO.Assign(attrs...)) +} + +func (u userInventoryTransfersDo) Joins(fields ...field.RelationField) *userInventoryTransfersDo { + for _, _f := range fields { + u = *u.withDO(u.DO.Joins(_f)) + } + return &u +} + +func (u userInventoryTransfersDo) Preload(fields ...field.RelationField) *userInventoryTransfersDo { + for _, _f := range fields { + u = *u.withDO(u.DO.Preload(_f)) + } + return &u +} + +func (u userInventoryTransfersDo) FirstOrInit() (*model.UserInventoryTransfers, error) { + if result, err := u.DO.FirstOrInit(); err != nil { + return nil, err + } else { + return result.(*model.UserInventoryTransfers), nil + } +} + +func (u userInventoryTransfersDo) FirstOrCreate() (*model.UserInventoryTransfers, error) { + if result, err := u.DO.FirstOrCreate(); err != nil { + return nil, err + } else { + return result.(*model.UserInventoryTransfers), nil + } +} + +func (u userInventoryTransfersDo) FindByPage(offset int, limit int) (result []*model.UserInventoryTransfers, count int64, err error) { + result, err = u.Offset(offset).Limit(limit).Find() + if err != nil { + return + } + + if size := len(result); 0 < limit && 0 < size && size < limit { + count = int64(size + offset) + return + } + + count, err = u.Offset(-1).Limit(-1).Count() + return +} + +func (u userInventoryTransfersDo) ScanByPage(result interface{}, offset int, limit int) (count int64, err error) { + count, err = u.Count() + if err != nil { + return + } + + err = u.Offset(offset).Limit(limit).Scan(result) + return +} + +func (u userInventoryTransfersDo) Scan(result interface{}) (err error) { + return u.DO.Scan(result) +} + +func (u userInventoryTransfersDo) Delete(models ...*model.UserInventoryTransfers) (result gen.ResultInfo, err error) { + return u.DO.Delete(models) +} + +func (u *userInventoryTransfersDo) withDO(do gen.Dao) *userInventoryTransfersDo { + u.DO = *do.(*gen.DO) + return u +} diff --git a/internal/repository/mysql/dao/user_invites.gen.go b/internal/repository/mysql/dao/user_invites.gen.go new file mode 100644 index 0000000..e4fe94a --- /dev/null +++ b/internal/repository/mysql/dao/user_invites.gen.go @@ -0,0 +1,352 @@ +// Code generated by gorm.io/gen. DO NOT EDIT. +// Code generated by gorm.io/gen. DO NOT EDIT. +// Code generated by gorm.io/gen. DO NOT EDIT. + +package dao + +import ( + "context" + + "gorm.io/gorm" + "gorm.io/gorm/clause" + "gorm.io/gorm/schema" + + "gorm.io/gen" + "gorm.io/gen/field" + + "gorm.io/plugin/dbresolver" + + "bindbox-game/internal/repository/mysql/model" +) + +func newUserInvites(db *gorm.DB, opts ...gen.DOOption) userInvites { + _userInvites := userInvites{} + + _userInvites.userInvitesDo.UseDB(db, opts...) + _userInvites.userInvitesDo.UseModel(&model.UserInvites{}) + + tableName := _userInvites.userInvitesDo.TableName() + _userInvites.ALL = field.NewAsterisk(tableName) + _userInvites.ID = field.NewInt64(tableName, "id") + _userInvites.InviterID = field.NewInt64(tableName, "inviter_id") + _userInvites.InviteeID = field.NewInt64(tableName, "invitee_id") + _userInvites.InviteCode = field.NewString(tableName, "invite_code") + _userInvites.RewardPoints = field.NewInt64(tableName, "reward_points") + _userInvites.RewardedAt = field.NewTime(tableName, "rewarded_at") + _userInvites.CreatedAt = field.NewTime(tableName, "created_at") + _userInvites.UpdatedAt = field.NewTime(tableName, "updated_at") + _userInvites.DeletedAt = field.NewField(tableName, "deleted_at") + + _userInvites.fillFieldMap() + + return _userInvites +} + +// userInvites 用户邀请关系表 +type userInvites struct { + userInvitesDo + + ALL field.Asterisk + ID field.Int64 // 主键ID + InviterID field.Int64 // 邀请人用户ID + InviteeID field.Int64 // 被邀请用户ID + InviteCode field.String // 邀请时使用的邀请码 + RewardPoints field.Int64 // 发放的积分数量(用于审计) + RewardedAt field.Time // 奖励发放时间 + CreatedAt field.Time // 创建时间 + UpdatedAt field.Time // 更新时间 + DeletedAt field.Field // 删除时间(软删) + + fieldMap map[string]field.Expr +} + +func (u userInvites) Table(newTableName string) *userInvites { + u.userInvitesDo.UseTable(newTableName) + return u.updateTableName(newTableName) +} + +func (u userInvites) As(alias string) *userInvites { + u.userInvitesDo.DO = *(u.userInvitesDo.As(alias).(*gen.DO)) + return u.updateTableName(alias) +} + +func (u *userInvites) updateTableName(table string) *userInvites { + u.ALL = field.NewAsterisk(table) + u.ID = field.NewInt64(table, "id") + u.InviterID = field.NewInt64(table, "inviter_id") + u.InviteeID = field.NewInt64(table, "invitee_id") + u.InviteCode = field.NewString(table, "invite_code") + u.RewardPoints = field.NewInt64(table, "reward_points") + u.RewardedAt = field.NewTime(table, "rewarded_at") + u.CreatedAt = field.NewTime(table, "created_at") + u.UpdatedAt = field.NewTime(table, "updated_at") + u.DeletedAt = field.NewField(table, "deleted_at") + + u.fillFieldMap() + + return u +} + +func (u *userInvites) GetFieldByName(fieldName string) (field.OrderExpr, bool) { + _f, ok := u.fieldMap[fieldName] + if !ok || _f == nil { + return nil, false + } + _oe, ok := _f.(field.OrderExpr) + return _oe, ok +} + +func (u *userInvites) fillFieldMap() { + u.fieldMap = make(map[string]field.Expr, 9) + u.fieldMap["id"] = u.ID + u.fieldMap["inviter_id"] = u.InviterID + u.fieldMap["invitee_id"] = u.InviteeID + u.fieldMap["invite_code"] = u.InviteCode + u.fieldMap["reward_points"] = u.RewardPoints + u.fieldMap["rewarded_at"] = u.RewardedAt + u.fieldMap["created_at"] = u.CreatedAt + u.fieldMap["updated_at"] = u.UpdatedAt + u.fieldMap["deleted_at"] = u.DeletedAt +} + +func (u userInvites) clone(db *gorm.DB) userInvites { + u.userInvitesDo.ReplaceConnPool(db.Statement.ConnPool) + return u +} + +func (u userInvites) replaceDB(db *gorm.DB) userInvites { + u.userInvitesDo.ReplaceDB(db) + return u +} + +type userInvitesDo struct{ gen.DO } + +func (u userInvitesDo) Debug() *userInvitesDo { + return u.withDO(u.DO.Debug()) +} + +func (u userInvitesDo) WithContext(ctx context.Context) *userInvitesDo { + return u.withDO(u.DO.WithContext(ctx)) +} + +func (u userInvitesDo) ReadDB() *userInvitesDo { + return u.Clauses(dbresolver.Read) +} + +func (u userInvitesDo) WriteDB() *userInvitesDo { + return u.Clauses(dbresolver.Write) +} + +func (u userInvitesDo) Session(config *gorm.Session) *userInvitesDo { + return u.withDO(u.DO.Session(config)) +} + +func (u userInvitesDo) Clauses(conds ...clause.Expression) *userInvitesDo { + return u.withDO(u.DO.Clauses(conds...)) +} + +func (u userInvitesDo) Returning(value interface{}, columns ...string) *userInvitesDo { + return u.withDO(u.DO.Returning(value, columns...)) +} + +func (u userInvitesDo) Not(conds ...gen.Condition) *userInvitesDo { + return u.withDO(u.DO.Not(conds...)) +} + +func (u userInvitesDo) Or(conds ...gen.Condition) *userInvitesDo { + return u.withDO(u.DO.Or(conds...)) +} + +func (u userInvitesDo) Select(conds ...field.Expr) *userInvitesDo { + return u.withDO(u.DO.Select(conds...)) +} + +func (u userInvitesDo) Where(conds ...gen.Condition) *userInvitesDo { + return u.withDO(u.DO.Where(conds...)) +} + +func (u userInvitesDo) Order(conds ...field.Expr) *userInvitesDo { + return u.withDO(u.DO.Order(conds...)) +} + +func (u userInvitesDo) Distinct(cols ...field.Expr) *userInvitesDo { + return u.withDO(u.DO.Distinct(cols...)) +} + +func (u userInvitesDo) Omit(cols ...field.Expr) *userInvitesDo { + return u.withDO(u.DO.Omit(cols...)) +} + +func (u userInvitesDo) Join(table schema.Tabler, on ...field.Expr) *userInvitesDo { + return u.withDO(u.DO.Join(table, on...)) +} + +func (u userInvitesDo) LeftJoin(table schema.Tabler, on ...field.Expr) *userInvitesDo { + return u.withDO(u.DO.LeftJoin(table, on...)) +} + +func (u userInvitesDo) RightJoin(table schema.Tabler, on ...field.Expr) *userInvitesDo { + return u.withDO(u.DO.RightJoin(table, on...)) +} + +func (u userInvitesDo) Group(cols ...field.Expr) *userInvitesDo { + return u.withDO(u.DO.Group(cols...)) +} + +func (u userInvitesDo) Having(conds ...gen.Condition) *userInvitesDo { + return u.withDO(u.DO.Having(conds...)) +} + +func (u userInvitesDo) Limit(limit int) *userInvitesDo { + return u.withDO(u.DO.Limit(limit)) +} + +func (u userInvitesDo) Offset(offset int) *userInvitesDo { + return u.withDO(u.DO.Offset(offset)) +} + +func (u userInvitesDo) Scopes(funcs ...func(gen.Dao) gen.Dao) *userInvitesDo { + return u.withDO(u.DO.Scopes(funcs...)) +} + +func (u userInvitesDo) Unscoped() *userInvitesDo { + return u.withDO(u.DO.Unscoped()) +} + +func (u userInvitesDo) Create(values ...*model.UserInvites) error { + if len(values) == 0 { + return nil + } + return u.DO.Create(values) +} + +func (u userInvitesDo) CreateInBatches(values []*model.UserInvites, batchSize int) error { + return u.DO.CreateInBatches(values, batchSize) +} + +// Save : !!! underlying implementation is different with GORM +// The method is equivalent to executing the statement: db.Clauses(clause.OnConflict{UpdateAll: true}).Create(values) +func (u userInvitesDo) Save(values ...*model.UserInvites) error { + if len(values) == 0 { + return nil + } + return u.DO.Save(values) +} + +func (u userInvitesDo) First() (*model.UserInvites, error) { + if result, err := u.DO.First(); err != nil { + return nil, err + } else { + return result.(*model.UserInvites), nil + } +} + +func (u userInvitesDo) Take() (*model.UserInvites, error) { + if result, err := u.DO.Take(); err != nil { + return nil, err + } else { + return result.(*model.UserInvites), nil + } +} + +func (u userInvitesDo) Last() (*model.UserInvites, error) { + if result, err := u.DO.Last(); err != nil { + return nil, err + } else { + return result.(*model.UserInvites), nil + } +} + +func (u userInvitesDo) Find() ([]*model.UserInvites, error) { + result, err := u.DO.Find() + return result.([]*model.UserInvites), err +} + +func (u userInvitesDo) FindInBatch(batchSize int, fc func(tx gen.Dao, batch int) error) (results []*model.UserInvites, err error) { + buf := make([]*model.UserInvites, 0, batchSize) + err = u.DO.FindInBatches(&buf, batchSize, func(tx gen.Dao, batch int) error { + defer func() { results = append(results, buf...) }() + return fc(tx, batch) + }) + return results, err +} + +func (u userInvitesDo) FindInBatches(result *[]*model.UserInvites, batchSize int, fc func(tx gen.Dao, batch int) error) error { + return u.DO.FindInBatches(result, batchSize, fc) +} + +func (u userInvitesDo) Attrs(attrs ...field.AssignExpr) *userInvitesDo { + return u.withDO(u.DO.Attrs(attrs...)) +} + +func (u userInvitesDo) Assign(attrs ...field.AssignExpr) *userInvitesDo { + return u.withDO(u.DO.Assign(attrs...)) +} + +func (u userInvitesDo) Joins(fields ...field.RelationField) *userInvitesDo { + for _, _f := range fields { + u = *u.withDO(u.DO.Joins(_f)) + } + return &u +} + +func (u userInvitesDo) Preload(fields ...field.RelationField) *userInvitesDo { + for _, _f := range fields { + u = *u.withDO(u.DO.Preload(_f)) + } + return &u +} + +func (u userInvitesDo) FirstOrInit() (*model.UserInvites, error) { + if result, err := u.DO.FirstOrInit(); err != nil { + return nil, err + } else { + return result.(*model.UserInvites), nil + } +} + +func (u userInvitesDo) FirstOrCreate() (*model.UserInvites, error) { + if result, err := u.DO.FirstOrCreate(); err != nil { + return nil, err + } else { + return result.(*model.UserInvites), nil + } +} + +func (u userInvitesDo) FindByPage(offset int, limit int) (result []*model.UserInvites, count int64, err error) { + result, err = u.Offset(offset).Limit(limit).Find() + if err != nil { + return + } + + if size := len(result); 0 < limit && 0 < size && size < limit { + count = int64(size + offset) + return + } + + count, err = u.Offset(-1).Limit(-1).Count() + return +} + +func (u userInvitesDo) ScanByPage(result interface{}, offset int, limit int) (count int64, err error) { + count, err = u.Count() + if err != nil { + return + } + + err = u.Offset(offset).Limit(limit).Scan(result) + return +} + +func (u userInvitesDo) Scan(result interface{}) (err error) { + return u.DO.Scan(result) +} + +func (u userInvitesDo) Delete(models ...*model.UserInvites) (result gen.ResultInfo, err error) { + return u.DO.Delete(models) +} + +func (u *userInvitesDo) withDO(do gen.Dao) *userInvitesDo { + u.DO = *do.(*gen.DO) + return u +} diff --git a/internal/repository/mysql/dao/user_item_cards.gen.go b/internal/repository/mysql/dao/user_item_cards.gen.go new file mode 100644 index 0000000..7a13573 --- /dev/null +++ b/internal/repository/mysql/dao/user_item_cards.gen.go @@ -0,0 +1,368 @@ +// Code generated by gorm.io/gen. DO NOT EDIT. +// Code generated by gorm.io/gen. DO NOT EDIT. +// Code generated by gorm.io/gen. DO NOT EDIT. + +package dao + +import ( + "context" + + "gorm.io/gorm" + "gorm.io/gorm/clause" + "gorm.io/gorm/schema" + + "gorm.io/gen" + "gorm.io/gen/field" + + "gorm.io/plugin/dbresolver" + + "bindbox-game/internal/repository/mysql/model" +) + +func newUserItemCards(db *gorm.DB, opts ...gen.DOOption) userItemCards { + _userItemCards := userItemCards{} + + _userItemCards.userItemCardsDo.UseDB(db, opts...) + _userItemCards.userItemCardsDo.UseModel(&model.UserItemCards{}) + + tableName := _userItemCards.userItemCardsDo.TableName() + _userItemCards.ALL = field.NewAsterisk(tableName) + _userItemCards.ID = field.NewInt64(tableName, "id") + _userItemCards.CreatedAt = field.NewTime(tableName, "created_at") + _userItemCards.UpdatedAt = field.NewTime(tableName, "updated_at") + _userItemCards.UserID = field.NewInt64(tableName, "user_id") + _userItemCards.CardID = field.NewInt64(tableName, "card_id") + _userItemCards.ValidStart = field.NewTime(tableName, "valid_start") + _userItemCards.ValidEnd = field.NewTime(tableName, "valid_end") + _userItemCards.Status = field.NewInt32(tableName, "status") + _userItemCards.UsedDrawLogID = field.NewInt64(tableName, "used_draw_log_id") + _userItemCards.UsedActivityID = field.NewInt64(tableName, "used_activity_id") + _userItemCards.UsedIssueID = field.NewInt64(tableName, "used_issue_id") + _userItemCards.UsedAt = field.NewTime(tableName, "used_at") + _userItemCards.Remark = field.NewString(tableName, "remark") + + _userItemCards.fillFieldMap() + + return _userItemCards +} + +// userItemCards 用户持有道具卡 +type userItemCards struct { + userItemCardsDo + + ALL field.Asterisk + ID field.Int64 // 主键ID + CreatedAt field.Time // 创建时间 + UpdatedAt field.Time // 更新时间 + UserID field.Int64 // 用户ID(users.id) + CardID field.Int64 // 卡模板ID(system_item_cards.id) + ValidStart field.Time // 有效期开始 + ValidEnd field.Time // 有效期结束 + Status field.Int32 // 状态:1未使用 2已使用 3已过期 + UsedDrawLogID field.Int64 // 使用关联抽奖日志ID(activity_draw_logs.id) + UsedActivityID field.Int64 // 使用时活动ID + UsedIssueID field.Int64 // 使用时期ID + UsedAt field.Time // 使用时间 + Remark field.String // 备注 + + fieldMap map[string]field.Expr +} + +func (u userItemCards) Table(newTableName string) *userItemCards { + u.userItemCardsDo.UseTable(newTableName) + return u.updateTableName(newTableName) +} + +func (u userItemCards) As(alias string) *userItemCards { + u.userItemCardsDo.DO = *(u.userItemCardsDo.As(alias).(*gen.DO)) + return u.updateTableName(alias) +} + +func (u *userItemCards) updateTableName(table string) *userItemCards { + u.ALL = field.NewAsterisk(table) + u.ID = field.NewInt64(table, "id") + u.CreatedAt = field.NewTime(table, "created_at") + u.UpdatedAt = field.NewTime(table, "updated_at") + u.UserID = field.NewInt64(table, "user_id") + u.CardID = field.NewInt64(table, "card_id") + u.ValidStart = field.NewTime(table, "valid_start") + u.ValidEnd = field.NewTime(table, "valid_end") + u.Status = field.NewInt32(table, "status") + u.UsedDrawLogID = field.NewInt64(table, "used_draw_log_id") + u.UsedActivityID = field.NewInt64(table, "used_activity_id") + u.UsedIssueID = field.NewInt64(table, "used_issue_id") + u.UsedAt = field.NewTime(table, "used_at") + u.Remark = field.NewString(table, "remark") + + u.fillFieldMap() + + return u +} + +func (u *userItemCards) GetFieldByName(fieldName string) (field.OrderExpr, bool) { + _f, ok := u.fieldMap[fieldName] + if !ok || _f == nil { + return nil, false + } + _oe, ok := _f.(field.OrderExpr) + return _oe, ok +} + +func (u *userItemCards) fillFieldMap() { + u.fieldMap = make(map[string]field.Expr, 13) + u.fieldMap["id"] = u.ID + u.fieldMap["created_at"] = u.CreatedAt + u.fieldMap["updated_at"] = u.UpdatedAt + u.fieldMap["user_id"] = u.UserID + u.fieldMap["card_id"] = u.CardID + u.fieldMap["valid_start"] = u.ValidStart + u.fieldMap["valid_end"] = u.ValidEnd + u.fieldMap["status"] = u.Status + u.fieldMap["used_draw_log_id"] = u.UsedDrawLogID + u.fieldMap["used_activity_id"] = u.UsedActivityID + u.fieldMap["used_issue_id"] = u.UsedIssueID + u.fieldMap["used_at"] = u.UsedAt + u.fieldMap["remark"] = u.Remark +} + +func (u userItemCards) clone(db *gorm.DB) userItemCards { + u.userItemCardsDo.ReplaceConnPool(db.Statement.ConnPool) + return u +} + +func (u userItemCards) replaceDB(db *gorm.DB) userItemCards { + u.userItemCardsDo.ReplaceDB(db) + return u +} + +type userItemCardsDo struct{ gen.DO } + +func (u userItemCardsDo) Debug() *userItemCardsDo { + return u.withDO(u.DO.Debug()) +} + +func (u userItemCardsDo) WithContext(ctx context.Context) *userItemCardsDo { + return u.withDO(u.DO.WithContext(ctx)) +} + +func (u userItemCardsDo) ReadDB() *userItemCardsDo { + return u.Clauses(dbresolver.Read) +} + +func (u userItemCardsDo) WriteDB() *userItemCardsDo { + return u.Clauses(dbresolver.Write) +} + +func (u userItemCardsDo) Session(config *gorm.Session) *userItemCardsDo { + return u.withDO(u.DO.Session(config)) +} + +func (u userItemCardsDo) Clauses(conds ...clause.Expression) *userItemCardsDo { + return u.withDO(u.DO.Clauses(conds...)) +} + +func (u userItemCardsDo) Returning(value interface{}, columns ...string) *userItemCardsDo { + return u.withDO(u.DO.Returning(value, columns...)) +} + +func (u userItemCardsDo) Not(conds ...gen.Condition) *userItemCardsDo { + return u.withDO(u.DO.Not(conds...)) +} + +func (u userItemCardsDo) Or(conds ...gen.Condition) *userItemCardsDo { + return u.withDO(u.DO.Or(conds...)) +} + +func (u userItemCardsDo) Select(conds ...field.Expr) *userItemCardsDo { + return u.withDO(u.DO.Select(conds...)) +} + +func (u userItemCardsDo) Where(conds ...gen.Condition) *userItemCardsDo { + return u.withDO(u.DO.Where(conds...)) +} + +func (u userItemCardsDo) Order(conds ...field.Expr) *userItemCardsDo { + return u.withDO(u.DO.Order(conds...)) +} + +func (u userItemCardsDo) Distinct(cols ...field.Expr) *userItemCardsDo { + return u.withDO(u.DO.Distinct(cols...)) +} + +func (u userItemCardsDo) Omit(cols ...field.Expr) *userItemCardsDo { + return u.withDO(u.DO.Omit(cols...)) +} + +func (u userItemCardsDo) Join(table schema.Tabler, on ...field.Expr) *userItemCardsDo { + return u.withDO(u.DO.Join(table, on...)) +} + +func (u userItemCardsDo) LeftJoin(table schema.Tabler, on ...field.Expr) *userItemCardsDo { + return u.withDO(u.DO.LeftJoin(table, on...)) +} + +func (u userItemCardsDo) RightJoin(table schema.Tabler, on ...field.Expr) *userItemCardsDo { + return u.withDO(u.DO.RightJoin(table, on...)) +} + +func (u userItemCardsDo) Group(cols ...field.Expr) *userItemCardsDo { + return u.withDO(u.DO.Group(cols...)) +} + +func (u userItemCardsDo) Having(conds ...gen.Condition) *userItemCardsDo { + return u.withDO(u.DO.Having(conds...)) +} + +func (u userItemCardsDo) Limit(limit int) *userItemCardsDo { + return u.withDO(u.DO.Limit(limit)) +} + +func (u userItemCardsDo) Offset(offset int) *userItemCardsDo { + return u.withDO(u.DO.Offset(offset)) +} + +func (u userItemCardsDo) Scopes(funcs ...func(gen.Dao) gen.Dao) *userItemCardsDo { + return u.withDO(u.DO.Scopes(funcs...)) +} + +func (u userItemCardsDo) Unscoped() *userItemCardsDo { + return u.withDO(u.DO.Unscoped()) +} + +func (u userItemCardsDo) Create(values ...*model.UserItemCards) error { + if len(values) == 0 { + return nil + } + return u.DO.Create(values) +} + +func (u userItemCardsDo) CreateInBatches(values []*model.UserItemCards, batchSize int) error { + return u.DO.CreateInBatches(values, batchSize) +} + +// Save : !!! underlying implementation is different with GORM +// The method is equivalent to executing the statement: db.Clauses(clause.OnConflict{UpdateAll: true}).Create(values) +func (u userItemCardsDo) Save(values ...*model.UserItemCards) error { + if len(values) == 0 { + return nil + } + return u.DO.Save(values) +} + +func (u userItemCardsDo) First() (*model.UserItemCards, error) { + if result, err := u.DO.First(); err != nil { + return nil, err + } else { + return result.(*model.UserItemCards), nil + } +} + +func (u userItemCardsDo) Take() (*model.UserItemCards, error) { + if result, err := u.DO.Take(); err != nil { + return nil, err + } else { + return result.(*model.UserItemCards), nil + } +} + +func (u userItemCardsDo) Last() (*model.UserItemCards, error) { + if result, err := u.DO.Last(); err != nil { + return nil, err + } else { + return result.(*model.UserItemCards), nil + } +} + +func (u userItemCardsDo) Find() ([]*model.UserItemCards, error) { + result, err := u.DO.Find() + return result.([]*model.UserItemCards), err +} + +func (u userItemCardsDo) FindInBatch(batchSize int, fc func(tx gen.Dao, batch int) error) (results []*model.UserItemCards, err error) { + buf := make([]*model.UserItemCards, 0, batchSize) + err = u.DO.FindInBatches(&buf, batchSize, func(tx gen.Dao, batch int) error { + defer func() { results = append(results, buf...) }() + return fc(tx, batch) + }) + return results, err +} + +func (u userItemCardsDo) FindInBatches(result *[]*model.UserItemCards, batchSize int, fc func(tx gen.Dao, batch int) error) error { + return u.DO.FindInBatches(result, batchSize, fc) +} + +func (u userItemCardsDo) Attrs(attrs ...field.AssignExpr) *userItemCardsDo { + return u.withDO(u.DO.Attrs(attrs...)) +} + +func (u userItemCardsDo) Assign(attrs ...field.AssignExpr) *userItemCardsDo { + return u.withDO(u.DO.Assign(attrs...)) +} + +func (u userItemCardsDo) Joins(fields ...field.RelationField) *userItemCardsDo { + for _, _f := range fields { + u = *u.withDO(u.DO.Joins(_f)) + } + return &u +} + +func (u userItemCardsDo) Preload(fields ...field.RelationField) *userItemCardsDo { + for _, _f := range fields { + u = *u.withDO(u.DO.Preload(_f)) + } + return &u +} + +func (u userItemCardsDo) FirstOrInit() (*model.UserItemCards, error) { + if result, err := u.DO.FirstOrInit(); err != nil { + return nil, err + } else { + return result.(*model.UserItemCards), nil + } +} + +func (u userItemCardsDo) FirstOrCreate() (*model.UserItemCards, error) { + if result, err := u.DO.FirstOrCreate(); err != nil { + return nil, err + } else { + return result.(*model.UserItemCards), nil + } +} + +func (u userItemCardsDo) FindByPage(offset int, limit int) (result []*model.UserItemCards, count int64, err error) { + result, err = u.Offset(offset).Limit(limit).Find() + if err != nil { + return + } + + if size := len(result); 0 < limit && 0 < size && size < limit { + count = int64(size + offset) + return + } + + count, err = u.Offset(-1).Limit(-1).Count() + return +} + +func (u userItemCardsDo) ScanByPage(result interface{}, offset int, limit int) (count int64, err error) { + count, err = u.Count() + if err != nil { + return + } + + err = u.Offset(offset).Limit(limit).Scan(result) + return +} + +func (u userItemCardsDo) Scan(result interface{}) (err error) { + return u.DO.Scan(result) +} + +func (u userItemCardsDo) Delete(models ...*model.UserItemCards) (result gen.ResultInfo, err error) { + return u.DO.Delete(models) +} + +func (u *userItemCardsDo) withDO(do gen.Dao) *userItemCardsDo { + u.DO = *do.(*gen.DO) + return u +} diff --git a/internal/repository/mysql/dao/user_points.gen.go b/internal/repository/mysql/dao/user_points.gen.go new file mode 100644 index 0000000..cedddc2 --- /dev/null +++ b/internal/repository/mysql/dao/user_points.gen.go @@ -0,0 +1,352 @@ +// Code generated by gorm.io/gen. DO NOT EDIT. +// Code generated by gorm.io/gen. DO NOT EDIT. +// Code generated by gorm.io/gen. DO NOT EDIT. + +package dao + +import ( + "context" + + "gorm.io/gorm" + "gorm.io/gorm/clause" + "gorm.io/gorm/schema" + + "gorm.io/gen" + "gorm.io/gen/field" + + "gorm.io/plugin/dbresolver" + + "bindbox-game/internal/repository/mysql/model" +) + +func newUserPoints(db *gorm.DB, opts ...gen.DOOption) userPoints { + _userPoints := userPoints{} + + _userPoints.userPointsDo.UseDB(db, opts...) + _userPoints.userPointsDo.UseModel(&model.UserPoints{}) + + tableName := _userPoints.userPointsDo.TableName() + _userPoints.ALL = field.NewAsterisk(tableName) + _userPoints.ID = field.NewInt64(tableName, "id") + _userPoints.CreatedAt = field.NewTime(tableName, "created_at") + _userPoints.UpdatedAt = field.NewTime(tableName, "updated_at") + _userPoints.UserID = field.NewInt64(tableName, "user_id") + _userPoints.Kind = field.NewString(tableName, "kind") + _userPoints.Points = field.NewInt64(tableName, "points") + _userPoints.ValidStart = field.NewTime(tableName, "valid_start") + _userPoints.ValidEnd = field.NewTime(tableName, "valid_end") + _userPoints.Version = field.NewInt32(tableName, "version") + + _userPoints.fillFieldMap() + + return _userPoints +} + +// userPoints 用户积分(余额表) +type userPoints struct { + userPointsDo + + ALL field.Asterisk + ID field.Int64 // 主键ID + CreatedAt field.Time // 创建时间 + UpdatedAt field.Time // 更新时间 + UserID field.Int64 // 用户ID( + Kind field.String // 积分类别:signin、task、exchange等 + Points field.Int64 // 积分值(整数点) + ValidStart field.Time // 有效期开始(用于每日一次等约束) + ValidEnd field.Time // 有效期结束 + Version field.Int32 // 乐观锁版本号 + + fieldMap map[string]field.Expr +} + +func (u userPoints) Table(newTableName string) *userPoints { + u.userPointsDo.UseTable(newTableName) + return u.updateTableName(newTableName) +} + +func (u userPoints) As(alias string) *userPoints { + u.userPointsDo.DO = *(u.userPointsDo.As(alias).(*gen.DO)) + return u.updateTableName(alias) +} + +func (u *userPoints) updateTableName(table string) *userPoints { + u.ALL = field.NewAsterisk(table) + u.ID = field.NewInt64(table, "id") + u.CreatedAt = field.NewTime(table, "created_at") + u.UpdatedAt = field.NewTime(table, "updated_at") + u.UserID = field.NewInt64(table, "user_id") + u.Kind = field.NewString(table, "kind") + u.Points = field.NewInt64(table, "points") + u.ValidStart = field.NewTime(table, "valid_start") + u.ValidEnd = field.NewTime(table, "valid_end") + u.Version = field.NewInt32(table, "version") + + u.fillFieldMap() + + return u +} + +func (u *userPoints) GetFieldByName(fieldName string) (field.OrderExpr, bool) { + _f, ok := u.fieldMap[fieldName] + if !ok || _f == nil { + return nil, false + } + _oe, ok := _f.(field.OrderExpr) + return _oe, ok +} + +func (u *userPoints) fillFieldMap() { + u.fieldMap = make(map[string]field.Expr, 9) + u.fieldMap["id"] = u.ID + u.fieldMap["created_at"] = u.CreatedAt + u.fieldMap["updated_at"] = u.UpdatedAt + u.fieldMap["user_id"] = u.UserID + u.fieldMap["kind"] = u.Kind + u.fieldMap["points"] = u.Points + u.fieldMap["valid_start"] = u.ValidStart + u.fieldMap["valid_end"] = u.ValidEnd + u.fieldMap["version"] = u.Version +} + +func (u userPoints) clone(db *gorm.DB) userPoints { + u.userPointsDo.ReplaceConnPool(db.Statement.ConnPool) + return u +} + +func (u userPoints) replaceDB(db *gorm.DB) userPoints { + u.userPointsDo.ReplaceDB(db) + return u +} + +type userPointsDo struct{ gen.DO } + +func (u userPointsDo) Debug() *userPointsDo { + return u.withDO(u.DO.Debug()) +} + +func (u userPointsDo) WithContext(ctx context.Context) *userPointsDo { + return u.withDO(u.DO.WithContext(ctx)) +} + +func (u userPointsDo) ReadDB() *userPointsDo { + return u.Clauses(dbresolver.Read) +} + +func (u userPointsDo) WriteDB() *userPointsDo { + return u.Clauses(dbresolver.Write) +} + +func (u userPointsDo) Session(config *gorm.Session) *userPointsDo { + return u.withDO(u.DO.Session(config)) +} + +func (u userPointsDo) Clauses(conds ...clause.Expression) *userPointsDo { + return u.withDO(u.DO.Clauses(conds...)) +} + +func (u userPointsDo) Returning(value interface{}, columns ...string) *userPointsDo { + return u.withDO(u.DO.Returning(value, columns...)) +} + +func (u userPointsDo) Not(conds ...gen.Condition) *userPointsDo { + return u.withDO(u.DO.Not(conds...)) +} + +func (u userPointsDo) Or(conds ...gen.Condition) *userPointsDo { + return u.withDO(u.DO.Or(conds...)) +} + +func (u userPointsDo) Select(conds ...field.Expr) *userPointsDo { + return u.withDO(u.DO.Select(conds...)) +} + +func (u userPointsDo) Where(conds ...gen.Condition) *userPointsDo { + return u.withDO(u.DO.Where(conds...)) +} + +func (u userPointsDo) Order(conds ...field.Expr) *userPointsDo { + return u.withDO(u.DO.Order(conds...)) +} + +func (u userPointsDo) Distinct(cols ...field.Expr) *userPointsDo { + return u.withDO(u.DO.Distinct(cols...)) +} + +func (u userPointsDo) Omit(cols ...field.Expr) *userPointsDo { + return u.withDO(u.DO.Omit(cols...)) +} + +func (u userPointsDo) Join(table schema.Tabler, on ...field.Expr) *userPointsDo { + return u.withDO(u.DO.Join(table, on...)) +} + +func (u userPointsDo) LeftJoin(table schema.Tabler, on ...field.Expr) *userPointsDo { + return u.withDO(u.DO.LeftJoin(table, on...)) +} + +func (u userPointsDo) RightJoin(table schema.Tabler, on ...field.Expr) *userPointsDo { + return u.withDO(u.DO.RightJoin(table, on...)) +} + +func (u userPointsDo) Group(cols ...field.Expr) *userPointsDo { + return u.withDO(u.DO.Group(cols...)) +} + +func (u userPointsDo) Having(conds ...gen.Condition) *userPointsDo { + return u.withDO(u.DO.Having(conds...)) +} + +func (u userPointsDo) Limit(limit int) *userPointsDo { + return u.withDO(u.DO.Limit(limit)) +} + +func (u userPointsDo) Offset(offset int) *userPointsDo { + return u.withDO(u.DO.Offset(offset)) +} + +func (u userPointsDo) Scopes(funcs ...func(gen.Dao) gen.Dao) *userPointsDo { + return u.withDO(u.DO.Scopes(funcs...)) +} + +func (u userPointsDo) Unscoped() *userPointsDo { + return u.withDO(u.DO.Unscoped()) +} + +func (u userPointsDo) Create(values ...*model.UserPoints) error { + if len(values) == 0 { + return nil + } + return u.DO.Create(values) +} + +func (u userPointsDo) CreateInBatches(values []*model.UserPoints, batchSize int) error { + return u.DO.CreateInBatches(values, batchSize) +} + +// Save : !!! underlying implementation is different with GORM +// The method is equivalent to executing the statement: db.Clauses(clause.OnConflict{UpdateAll: true}).Create(values) +func (u userPointsDo) Save(values ...*model.UserPoints) error { + if len(values) == 0 { + return nil + } + return u.DO.Save(values) +} + +func (u userPointsDo) First() (*model.UserPoints, error) { + if result, err := u.DO.First(); err != nil { + return nil, err + } else { + return result.(*model.UserPoints), nil + } +} + +func (u userPointsDo) Take() (*model.UserPoints, error) { + if result, err := u.DO.Take(); err != nil { + return nil, err + } else { + return result.(*model.UserPoints), nil + } +} + +func (u userPointsDo) Last() (*model.UserPoints, error) { + if result, err := u.DO.Last(); err != nil { + return nil, err + } else { + return result.(*model.UserPoints), nil + } +} + +func (u userPointsDo) Find() ([]*model.UserPoints, error) { + result, err := u.DO.Find() + return result.([]*model.UserPoints), err +} + +func (u userPointsDo) FindInBatch(batchSize int, fc func(tx gen.Dao, batch int) error) (results []*model.UserPoints, err error) { + buf := make([]*model.UserPoints, 0, batchSize) + err = u.DO.FindInBatches(&buf, batchSize, func(tx gen.Dao, batch int) error { + defer func() { results = append(results, buf...) }() + return fc(tx, batch) + }) + return results, err +} + +func (u userPointsDo) FindInBatches(result *[]*model.UserPoints, batchSize int, fc func(tx gen.Dao, batch int) error) error { + return u.DO.FindInBatches(result, batchSize, fc) +} + +func (u userPointsDo) Attrs(attrs ...field.AssignExpr) *userPointsDo { + return u.withDO(u.DO.Attrs(attrs...)) +} + +func (u userPointsDo) Assign(attrs ...field.AssignExpr) *userPointsDo { + return u.withDO(u.DO.Assign(attrs...)) +} + +func (u userPointsDo) Joins(fields ...field.RelationField) *userPointsDo { + for _, _f := range fields { + u = *u.withDO(u.DO.Joins(_f)) + } + return &u +} + +func (u userPointsDo) Preload(fields ...field.RelationField) *userPointsDo { + for _, _f := range fields { + u = *u.withDO(u.DO.Preload(_f)) + } + return &u +} + +func (u userPointsDo) FirstOrInit() (*model.UserPoints, error) { + if result, err := u.DO.FirstOrInit(); err != nil { + return nil, err + } else { + return result.(*model.UserPoints), nil + } +} + +func (u userPointsDo) FirstOrCreate() (*model.UserPoints, error) { + if result, err := u.DO.FirstOrCreate(); err != nil { + return nil, err + } else { + return result.(*model.UserPoints), nil + } +} + +func (u userPointsDo) FindByPage(offset int, limit int) (result []*model.UserPoints, count int64, err error) { + result, err = u.Offset(offset).Limit(limit).Find() + if err != nil { + return + } + + if size := len(result); 0 < limit && 0 < size && size < limit { + count = int64(size + offset) + return + } + + count, err = u.Offset(-1).Limit(-1).Count() + return +} + +func (u userPointsDo) ScanByPage(result interface{}, offset int, limit int) (count int64, err error) { + count, err = u.Count() + if err != nil { + return + } + + err = u.Offset(offset).Limit(limit).Scan(result) + return +} + +func (u userPointsDo) Scan(result interface{}) (err error) { + return u.DO.Scan(result) +} + +func (u userPointsDo) Delete(models ...*model.UserPoints) (result gen.ResultInfo, err error) { + return u.DO.Delete(models) +} + +func (u *userPointsDo) withDO(do gen.Dao) *userPointsDo { + u.DO = *do.(*gen.DO) + return u +} diff --git a/internal/repository/mysql/dao/user_points_ledger.gen.go b/internal/repository/mysql/dao/user_points_ledger.gen.go new file mode 100644 index 0000000..0f17df8 --- /dev/null +++ b/internal/repository/mysql/dao/user_points_ledger.gen.go @@ -0,0 +1,348 @@ +// Code generated by gorm.io/gen. DO NOT EDIT. +// Code generated by gorm.io/gen. DO NOT EDIT. +// Code generated by gorm.io/gen. DO NOT EDIT. + +package dao + +import ( + "context" + + "gorm.io/gorm" + "gorm.io/gorm/clause" + "gorm.io/gorm/schema" + + "gorm.io/gen" + "gorm.io/gen/field" + + "gorm.io/plugin/dbresolver" + + "bindbox-game/internal/repository/mysql/model" +) + +func newUserPointsLedger(db *gorm.DB, opts ...gen.DOOption) userPointsLedger { + _userPointsLedger := userPointsLedger{} + + _userPointsLedger.userPointsLedgerDo.UseDB(db, opts...) + _userPointsLedger.userPointsLedgerDo.UseModel(&model.UserPointsLedger{}) + + tableName := _userPointsLedger.userPointsLedgerDo.TableName() + _userPointsLedger.ALL = field.NewAsterisk(tableName) + _userPointsLedger.ID = field.NewInt64(tableName, "id") + _userPointsLedger.CreatedAt = field.NewTime(tableName, "created_at") + _userPointsLedger.UserID = field.NewInt64(tableName, "user_id") + _userPointsLedger.Action = field.NewString(tableName, "action") + _userPointsLedger.Points = field.NewInt64(tableName, "points") + _userPointsLedger.RefTable = field.NewString(tableName, "ref_table") + _userPointsLedger.RefID = field.NewString(tableName, "ref_id") + _userPointsLedger.Remark = field.NewString(tableName, "remark") + + _userPointsLedger.fillFieldMap() + + return _userPointsLedger +} + +// userPointsLedger 用户积分流水(总账) +type userPointsLedger struct { + userPointsLedgerDo + + ALL field.Asterisk + ID field.Int64 // 主键ID + CreatedAt field.Time // 创建时间 + UserID field.Int64 // 用户ID(user_members.id) + Action field.String // 变更动作:signin/order_deduct/refund_restore/manual + Points field.Int64 // 积分变动值(正增负减) + RefTable field.String // 关联表名(如orders/payment_refund) + RefID field.String // 关联ID(如订单号/记录ID) + Remark field.String // 备注 + + fieldMap map[string]field.Expr +} + +func (u userPointsLedger) Table(newTableName string) *userPointsLedger { + u.userPointsLedgerDo.UseTable(newTableName) + return u.updateTableName(newTableName) +} + +func (u userPointsLedger) As(alias string) *userPointsLedger { + u.userPointsLedgerDo.DO = *(u.userPointsLedgerDo.As(alias).(*gen.DO)) + return u.updateTableName(alias) +} + +func (u *userPointsLedger) updateTableName(table string) *userPointsLedger { + u.ALL = field.NewAsterisk(table) + u.ID = field.NewInt64(table, "id") + u.CreatedAt = field.NewTime(table, "created_at") + u.UserID = field.NewInt64(table, "user_id") + u.Action = field.NewString(table, "action") + u.Points = field.NewInt64(table, "points") + u.RefTable = field.NewString(table, "ref_table") + u.RefID = field.NewString(table, "ref_id") + u.Remark = field.NewString(table, "remark") + + u.fillFieldMap() + + return u +} + +func (u *userPointsLedger) GetFieldByName(fieldName string) (field.OrderExpr, bool) { + _f, ok := u.fieldMap[fieldName] + if !ok || _f == nil { + return nil, false + } + _oe, ok := _f.(field.OrderExpr) + return _oe, ok +} + +func (u *userPointsLedger) fillFieldMap() { + u.fieldMap = make(map[string]field.Expr, 8) + u.fieldMap["id"] = u.ID + u.fieldMap["created_at"] = u.CreatedAt + u.fieldMap["user_id"] = u.UserID + u.fieldMap["action"] = u.Action + u.fieldMap["points"] = u.Points + u.fieldMap["ref_table"] = u.RefTable + u.fieldMap["ref_id"] = u.RefID + u.fieldMap["remark"] = u.Remark +} + +func (u userPointsLedger) clone(db *gorm.DB) userPointsLedger { + u.userPointsLedgerDo.ReplaceConnPool(db.Statement.ConnPool) + return u +} + +func (u userPointsLedger) replaceDB(db *gorm.DB) userPointsLedger { + u.userPointsLedgerDo.ReplaceDB(db) + return u +} + +type userPointsLedgerDo struct{ gen.DO } + +func (u userPointsLedgerDo) Debug() *userPointsLedgerDo { + return u.withDO(u.DO.Debug()) +} + +func (u userPointsLedgerDo) WithContext(ctx context.Context) *userPointsLedgerDo { + return u.withDO(u.DO.WithContext(ctx)) +} + +func (u userPointsLedgerDo) ReadDB() *userPointsLedgerDo { + return u.Clauses(dbresolver.Read) +} + +func (u userPointsLedgerDo) WriteDB() *userPointsLedgerDo { + return u.Clauses(dbresolver.Write) +} + +func (u userPointsLedgerDo) Session(config *gorm.Session) *userPointsLedgerDo { + return u.withDO(u.DO.Session(config)) +} + +func (u userPointsLedgerDo) Clauses(conds ...clause.Expression) *userPointsLedgerDo { + return u.withDO(u.DO.Clauses(conds...)) +} + +func (u userPointsLedgerDo) Returning(value interface{}, columns ...string) *userPointsLedgerDo { + return u.withDO(u.DO.Returning(value, columns...)) +} + +func (u userPointsLedgerDo) Not(conds ...gen.Condition) *userPointsLedgerDo { + return u.withDO(u.DO.Not(conds...)) +} + +func (u userPointsLedgerDo) Or(conds ...gen.Condition) *userPointsLedgerDo { + return u.withDO(u.DO.Or(conds...)) +} + +func (u userPointsLedgerDo) Select(conds ...field.Expr) *userPointsLedgerDo { + return u.withDO(u.DO.Select(conds...)) +} + +func (u userPointsLedgerDo) Where(conds ...gen.Condition) *userPointsLedgerDo { + return u.withDO(u.DO.Where(conds...)) +} + +func (u userPointsLedgerDo) Order(conds ...field.Expr) *userPointsLedgerDo { + return u.withDO(u.DO.Order(conds...)) +} + +func (u userPointsLedgerDo) Distinct(cols ...field.Expr) *userPointsLedgerDo { + return u.withDO(u.DO.Distinct(cols...)) +} + +func (u userPointsLedgerDo) Omit(cols ...field.Expr) *userPointsLedgerDo { + return u.withDO(u.DO.Omit(cols...)) +} + +func (u userPointsLedgerDo) Join(table schema.Tabler, on ...field.Expr) *userPointsLedgerDo { + return u.withDO(u.DO.Join(table, on...)) +} + +func (u userPointsLedgerDo) LeftJoin(table schema.Tabler, on ...field.Expr) *userPointsLedgerDo { + return u.withDO(u.DO.LeftJoin(table, on...)) +} + +func (u userPointsLedgerDo) RightJoin(table schema.Tabler, on ...field.Expr) *userPointsLedgerDo { + return u.withDO(u.DO.RightJoin(table, on...)) +} + +func (u userPointsLedgerDo) Group(cols ...field.Expr) *userPointsLedgerDo { + return u.withDO(u.DO.Group(cols...)) +} + +func (u userPointsLedgerDo) Having(conds ...gen.Condition) *userPointsLedgerDo { + return u.withDO(u.DO.Having(conds...)) +} + +func (u userPointsLedgerDo) Limit(limit int) *userPointsLedgerDo { + return u.withDO(u.DO.Limit(limit)) +} + +func (u userPointsLedgerDo) Offset(offset int) *userPointsLedgerDo { + return u.withDO(u.DO.Offset(offset)) +} + +func (u userPointsLedgerDo) Scopes(funcs ...func(gen.Dao) gen.Dao) *userPointsLedgerDo { + return u.withDO(u.DO.Scopes(funcs...)) +} + +func (u userPointsLedgerDo) Unscoped() *userPointsLedgerDo { + return u.withDO(u.DO.Unscoped()) +} + +func (u userPointsLedgerDo) Create(values ...*model.UserPointsLedger) error { + if len(values) == 0 { + return nil + } + return u.DO.Create(values) +} + +func (u userPointsLedgerDo) CreateInBatches(values []*model.UserPointsLedger, batchSize int) error { + return u.DO.CreateInBatches(values, batchSize) +} + +// Save : !!! underlying implementation is different with GORM +// The method is equivalent to executing the statement: db.Clauses(clause.OnConflict{UpdateAll: true}).Create(values) +func (u userPointsLedgerDo) Save(values ...*model.UserPointsLedger) error { + if len(values) == 0 { + return nil + } + return u.DO.Save(values) +} + +func (u userPointsLedgerDo) First() (*model.UserPointsLedger, error) { + if result, err := u.DO.First(); err != nil { + return nil, err + } else { + return result.(*model.UserPointsLedger), nil + } +} + +func (u userPointsLedgerDo) Take() (*model.UserPointsLedger, error) { + if result, err := u.DO.Take(); err != nil { + return nil, err + } else { + return result.(*model.UserPointsLedger), nil + } +} + +func (u userPointsLedgerDo) Last() (*model.UserPointsLedger, error) { + if result, err := u.DO.Last(); err != nil { + return nil, err + } else { + return result.(*model.UserPointsLedger), nil + } +} + +func (u userPointsLedgerDo) Find() ([]*model.UserPointsLedger, error) { + result, err := u.DO.Find() + return result.([]*model.UserPointsLedger), err +} + +func (u userPointsLedgerDo) FindInBatch(batchSize int, fc func(tx gen.Dao, batch int) error) (results []*model.UserPointsLedger, err error) { + buf := make([]*model.UserPointsLedger, 0, batchSize) + err = u.DO.FindInBatches(&buf, batchSize, func(tx gen.Dao, batch int) error { + defer func() { results = append(results, buf...) }() + return fc(tx, batch) + }) + return results, err +} + +func (u userPointsLedgerDo) FindInBatches(result *[]*model.UserPointsLedger, batchSize int, fc func(tx gen.Dao, batch int) error) error { + return u.DO.FindInBatches(result, batchSize, fc) +} + +func (u userPointsLedgerDo) Attrs(attrs ...field.AssignExpr) *userPointsLedgerDo { + return u.withDO(u.DO.Attrs(attrs...)) +} + +func (u userPointsLedgerDo) Assign(attrs ...field.AssignExpr) *userPointsLedgerDo { + return u.withDO(u.DO.Assign(attrs...)) +} + +func (u userPointsLedgerDo) Joins(fields ...field.RelationField) *userPointsLedgerDo { + for _, _f := range fields { + u = *u.withDO(u.DO.Joins(_f)) + } + return &u +} + +func (u userPointsLedgerDo) Preload(fields ...field.RelationField) *userPointsLedgerDo { + for _, _f := range fields { + u = *u.withDO(u.DO.Preload(_f)) + } + return &u +} + +func (u userPointsLedgerDo) FirstOrInit() (*model.UserPointsLedger, error) { + if result, err := u.DO.FirstOrInit(); err != nil { + return nil, err + } else { + return result.(*model.UserPointsLedger), nil + } +} + +func (u userPointsLedgerDo) FirstOrCreate() (*model.UserPointsLedger, error) { + if result, err := u.DO.FirstOrCreate(); err != nil { + return nil, err + } else { + return result.(*model.UserPointsLedger), nil + } +} + +func (u userPointsLedgerDo) FindByPage(offset int, limit int) (result []*model.UserPointsLedger, count int64, err error) { + result, err = u.Offset(offset).Limit(limit).Find() + if err != nil { + return + } + + if size := len(result); 0 < limit && 0 < size && size < limit { + count = int64(size + offset) + return + } + + count, err = u.Offset(-1).Limit(-1).Count() + return +} + +func (u userPointsLedgerDo) ScanByPage(result interface{}, offset int, limit int) (count int64, err error) { + count, err = u.Count() + if err != nil { + return + } + + err = u.Offset(offset).Limit(limit).Scan(result) + return +} + +func (u userPointsLedgerDo) Scan(result interface{}) (err error) { + return u.DO.Scan(result) +} + +func (u userPointsLedgerDo) Delete(models ...*model.UserPointsLedger) (result gen.ResultInfo, err error) { + return u.DO.Delete(models) +} + +func (u *userPointsLedgerDo) withDO(do gen.Dao) *userPointsLedgerDo { + u.DO = *do.(*gen.DO) + return u +} diff --git a/internal/repository/mysql/dao/users.gen.go b/internal/repository/mysql/dao/users.gen.go new file mode 100644 index 0000000..7ea9644 --- /dev/null +++ b/internal/repository/mysql/dao/users.gen.go @@ -0,0 +1,364 @@ +// Code generated by gorm.io/gen. DO NOT EDIT. +// Code generated by gorm.io/gen. DO NOT EDIT. +// Code generated by gorm.io/gen. DO NOT EDIT. + +package dao + +import ( + "context" + + "gorm.io/gorm" + "gorm.io/gorm/clause" + "gorm.io/gorm/schema" + + "gorm.io/gen" + "gorm.io/gen/field" + + "gorm.io/plugin/dbresolver" + + "bindbox-game/internal/repository/mysql/model" +) + +func newUsers(db *gorm.DB, opts ...gen.DOOption) users { + _users := users{} + + _users.usersDo.UseDB(db, opts...) + _users.usersDo.UseModel(&model.Users{}) + + tableName := _users.usersDo.TableName() + _users.ALL = field.NewAsterisk(tableName) + _users.ID = field.NewInt64(tableName, "id") + _users.CreatedAt = field.NewTime(tableName, "created_at") + _users.UpdatedAt = field.NewTime(tableName, "updated_at") + _users.DeletedAt = field.NewField(tableName, "deleted_at") + _users.Nickname = field.NewString(tableName, "nickname") + _users.Avatar = field.NewString(tableName, "avatar") + _users.Mobile = field.NewString(tableName, "mobile") + _users.Openid = field.NewString(tableName, "openid") + _users.Unionid = field.NewString(tableName, "unionid") + _users.InviteCode = field.NewString(tableName, "invite_code") + _users.InviterID = field.NewInt64(tableName, "inviter_id") + _users.Status = field.NewInt32(tableName, "status") + + _users.fillFieldMap() + + return _users +} + +// users 用户表 +type users struct { + usersDo + + ALL field.Asterisk + ID field.Int64 // 主键ID + CreatedAt field.Time // 创建时间 + UpdatedAt field.Time // 更新时间 + DeletedAt field.Field // 删除时间(软删) + Nickname field.String // 昵称 + Avatar field.String // 头像URL + Mobile field.String // 手机号 + Openid field.String // 微信openid + Unionid field.String // 微信unionid + InviteCode field.String // 用户唯一邀请码 + InviterID field.Int64 // 邀请人用户ID + Status field.Int32 // 状态:1正常 2禁用 + + fieldMap map[string]field.Expr +} + +func (u users) Table(newTableName string) *users { + u.usersDo.UseTable(newTableName) + return u.updateTableName(newTableName) +} + +func (u users) As(alias string) *users { + u.usersDo.DO = *(u.usersDo.As(alias).(*gen.DO)) + return u.updateTableName(alias) +} + +func (u *users) updateTableName(table string) *users { + u.ALL = field.NewAsterisk(table) + u.ID = field.NewInt64(table, "id") + u.CreatedAt = field.NewTime(table, "created_at") + u.UpdatedAt = field.NewTime(table, "updated_at") + u.DeletedAt = field.NewField(table, "deleted_at") + u.Nickname = field.NewString(table, "nickname") + u.Avatar = field.NewString(table, "avatar") + u.Mobile = field.NewString(table, "mobile") + u.Openid = field.NewString(table, "openid") + u.Unionid = field.NewString(table, "unionid") + u.InviteCode = field.NewString(table, "invite_code") + u.InviterID = field.NewInt64(table, "inviter_id") + u.Status = field.NewInt32(table, "status") + + u.fillFieldMap() + + return u +} + +func (u *users) GetFieldByName(fieldName string) (field.OrderExpr, bool) { + _f, ok := u.fieldMap[fieldName] + if !ok || _f == nil { + return nil, false + } + _oe, ok := _f.(field.OrderExpr) + return _oe, ok +} + +func (u *users) fillFieldMap() { + u.fieldMap = make(map[string]field.Expr, 12) + u.fieldMap["id"] = u.ID + u.fieldMap["created_at"] = u.CreatedAt + u.fieldMap["updated_at"] = u.UpdatedAt + u.fieldMap["deleted_at"] = u.DeletedAt + u.fieldMap["nickname"] = u.Nickname + u.fieldMap["avatar"] = u.Avatar + u.fieldMap["mobile"] = u.Mobile + u.fieldMap["openid"] = u.Openid + u.fieldMap["unionid"] = u.Unionid + u.fieldMap["invite_code"] = u.InviteCode + u.fieldMap["inviter_id"] = u.InviterID + u.fieldMap["status"] = u.Status +} + +func (u users) clone(db *gorm.DB) users { + u.usersDo.ReplaceConnPool(db.Statement.ConnPool) + return u +} + +func (u users) replaceDB(db *gorm.DB) users { + u.usersDo.ReplaceDB(db) + return u +} + +type usersDo struct{ gen.DO } + +func (u usersDo) Debug() *usersDo { + return u.withDO(u.DO.Debug()) +} + +func (u usersDo) WithContext(ctx context.Context) *usersDo { + return u.withDO(u.DO.WithContext(ctx)) +} + +func (u usersDo) ReadDB() *usersDo { + return u.Clauses(dbresolver.Read) +} + +func (u usersDo) WriteDB() *usersDo { + return u.Clauses(dbresolver.Write) +} + +func (u usersDo) Session(config *gorm.Session) *usersDo { + return u.withDO(u.DO.Session(config)) +} + +func (u usersDo) Clauses(conds ...clause.Expression) *usersDo { + return u.withDO(u.DO.Clauses(conds...)) +} + +func (u usersDo) Returning(value interface{}, columns ...string) *usersDo { + return u.withDO(u.DO.Returning(value, columns...)) +} + +func (u usersDo) Not(conds ...gen.Condition) *usersDo { + return u.withDO(u.DO.Not(conds...)) +} + +func (u usersDo) Or(conds ...gen.Condition) *usersDo { + return u.withDO(u.DO.Or(conds...)) +} + +func (u usersDo) Select(conds ...field.Expr) *usersDo { + return u.withDO(u.DO.Select(conds...)) +} + +func (u usersDo) Where(conds ...gen.Condition) *usersDo { + return u.withDO(u.DO.Where(conds...)) +} + +func (u usersDo) Order(conds ...field.Expr) *usersDo { + return u.withDO(u.DO.Order(conds...)) +} + +func (u usersDo) Distinct(cols ...field.Expr) *usersDo { + return u.withDO(u.DO.Distinct(cols...)) +} + +func (u usersDo) Omit(cols ...field.Expr) *usersDo { + return u.withDO(u.DO.Omit(cols...)) +} + +func (u usersDo) Join(table schema.Tabler, on ...field.Expr) *usersDo { + return u.withDO(u.DO.Join(table, on...)) +} + +func (u usersDo) LeftJoin(table schema.Tabler, on ...field.Expr) *usersDo { + return u.withDO(u.DO.LeftJoin(table, on...)) +} + +func (u usersDo) RightJoin(table schema.Tabler, on ...field.Expr) *usersDo { + return u.withDO(u.DO.RightJoin(table, on...)) +} + +func (u usersDo) Group(cols ...field.Expr) *usersDo { + return u.withDO(u.DO.Group(cols...)) +} + +func (u usersDo) Having(conds ...gen.Condition) *usersDo { + return u.withDO(u.DO.Having(conds...)) +} + +func (u usersDo) Limit(limit int) *usersDo { + return u.withDO(u.DO.Limit(limit)) +} + +func (u usersDo) Offset(offset int) *usersDo { + return u.withDO(u.DO.Offset(offset)) +} + +func (u usersDo) Scopes(funcs ...func(gen.Dao) gen.Dao) *usersDo { + return u.withDO(u.DO.Scopes(funcs...)) +} + +func (u usersDo) Unscoped() *usersDo { + return u.withDO(u.DO.Unscoped()) +} + +func (u usersDo) Create(values ...*model.Users) error { + if len(values) == 0 { + return nil + } + return u.DO.Create(values) +} + +func (u usersDo) CreateInBatches(values []*model.Users, batchSize int) error { + return u.DO.CreateInBatches(values, batchSize) +} + +// Save : !!! underlying implementation is different with GORM +// The method is equivalent to executing the statement: db.Clauses(clause.OnConflict{UpdateAll: true}).Create(values) +func (u usersDo) Save(values ...*model.Users) error { + if len(values) == 0 { + return nil + } + return u.DO.Save(values) +} + +func (u usersDo) First() (*model.Users, error) { + if result, err := u.DO.First(); err != nil { + return nil, err + } else { + return result.(*model.Users), nil + } +} + +func (u usersDo) Take() (*model.Users, error) { + if result, err := u.DO.Take(); err != nil { + return nil, err + } else { + return result.(*model.Users), nil + } +} + +func (u usersDo) Last() (*model.Users, error) { + if result, err := u.DO.Last(); err != nil { + return nil, err + } else { + return result.(*model.Users), nil + } +} + +func (u usersDo) Find() ([]*model.Users, error) { + result, err := u.DO.Find() + return result.([]*model.Users), err +} + +func (u usersDo) FindInBatch(batchSize int, fc func(tx gen.Dao, batch int) error) (results []*model.Users, err error) { + buf := make([]*model.Users, 0, batchSize) + err = u.DO.FindInBatches(&buf, batchSize, func(tx gen.Dao, batch int) error { + defer func() { results = append(results, buf...) }() + return fc(tx, batch) + }) + return results, err +} + +func (u usersDo) FindInBatches(result *[]*model.Users, batchSize int, fc func(tx gen.Dao, batch int) error) error { + return u.DO.FindInBatches(result, batchSize, fc) +} + +func (u usersDo) Attrs(attrs ...field.AssignExpr) *usersDo { + return u.withDO(u.DO.Attrs(attrs...)) +} + +func (u usersDo) Assign(attrs ...field.AssignExpr) *usersDo { + return u.withDO(u.DO.Assign(attrs...)) +} + +func (u usersDo) Joins(fields ...field.RelationField) *usersDo { + for _, _f := range fields { + u = *u.withDO(u.DO.Joins(_f)) + } + return &u +} + +func (u usersDo) Preload(fields ...field.RelationField) *usersDo { + for _, _f := range fields { + u = *u.withDO(u.DO.Preload(_f)) + } + return &u +} + +func (u usersDo) FirstOrInit() (*model.Users, error) { + if result, err := u.DO.FirstOrInit(); err != nil { + return nil, err + } else { + return result.(*model.Users), nil + } +} + +func (u usersDo) FirstOrCreate() (*model.Users, error) { + if result, err := u.DO.FirstOrCreate(); err != nil { + return nil, err + } else { + return result.(*model.Users), nil + } +} + +func (u usersDo) FindByPage(offset int, limit int) (result []*model.Users, count int64, err error) { + result, err = u.Offset(offset).Limit(limit).Find() + if err != nil { + return + } + + if size := len(result); 0 < limit && 0 < size && size < limit { + count = int64(size + offset) + return + } + + count, err = u.Offset(-1).Limit(-1).Count() + return +} + +func (u usersDo) ScanByPage(result interface{}, offset int, limit int) (count int64, err error) { + count, err = u.Count() + if err != nil { + return + } + + err = u.Offset(offset).Limit(limit).Scan(result) + return +} + +func (u usersDo) Scan(result interface{}) (err error) { + return u.DO.Scan(result) +} + +func (u usersDo) Delete(models ...*model.Users) (result gen.ResultInfo, err error) { + return u.DO.Delete(models) +} + +func (u *usersDo) withDO(do gen.Dao) *usersDo { + u.DO = *do.(*gen.DO) + return u +} diff --git a/internal/repository/mysql/model/activities.gen.go b/internal/repository/mysql/model/activities.gen.go new file mode 100644 index 0000000..ada7e7c --- /dev/null +++ b/internal/repository/mysql/model/activities.gen.go @@ -0,0 +1,31 @@ +// Code generated by gorm.io/gen. DO NOT EDIT. +// Code generated by gorm.io/gen. DO NOT EDIT. +// Code generated by gorm.io/gen. DO NOT EDIT. + +package model + +import ( + "time" +) + +const TableNameActivities = "activities" + +// Activities 活动 +type Activities struct { + ID int64 `gorm:"column:id;primaryKey;autoIncrement:true;comment:主键ID" json:"id"` // 主键ID + CreatedAt time.Time `gorm:"column:created_at;not null;default:CURRENT_TIMESTAMP(3);comment:创建时间" json:"created_at"` // 创建时间 + UpdatedAt time.Time `gorm:"column:updated_at;not null;default:CURRENT_TIMESTAMP(3);comment:更新时间" json:"updated_at"` // 更新时间 + Name string `gorm:"column:name;not null;comment:活动名称" json:"name"` // 活动名称 + Banner string `gorm:"column:banner;comment:活动横幅/海报URL" json:"banner"` // 活动横幅/海报URL + ActivityCategoryID int64 `gorm:"column:activity_category_id;comment:活动所属分类ID(activity_categories.id,可空)" json:"activity_category_id"` // 活动所属分类ID(activity_categories.id,可空) + Status int32 `gorm:"column:status;not null;default:1;comment:状态:1进行中 2下线" json:"status"` // 状态:1进行中 2下线 + PriceDraw int64 `gorm:"column:price_draw;comment:活动门票价格" json:"price_draw"` // 活动门票价格 + IsBoss int32 `gorm:"column:is_boss;comment:Boss: 1 是 0 不是" json:"is_boss"` // Boss: 1 是 0 不是 + StartTime time.Time `gorm:"column:start_time;comment:开始时间" json:"start_time"` // 开始时间 + EndTime time.Time `gorm:"column:end_time;comment:结束时间" json:"end_time"` // 结束时间 +} + +// TableName Activities's table name +func (*Activities) TableName() string { + return TableNameActivities +} diff --git a/internal/repository/mysql/model/activity_categories.gen.go b/internal/repository/mysql/model/activity_categories.gen.go new file mode 100644 index 0000000..b132f9c --- /dev/null +++ b/internal/repository/mysql/model/activity_categories.gen.go @@ -0,0 +1,26 @@ +// Code generated by gorm.io/gen. DO NOT EDIT. +// Code generated by gorm.io/gen. DO NOT EDIT. +// Code generated by gorm.io/gen. DO NOT EDIT. + +package model + +import ( + "time" +) + +const TableNameActivityCategories = "activity_categories" + +// ActivityCategories 活动分类 +type ActivityCategories struct { + ID int64 `gorm:"column:id;primaryKey;autoIncrement:true;comment:主键ID" json:"id"` // 主键ID + CreatedAt time.Time `gorm:"column:created_at;not null;default:CURRENT_TIMESTAMP(3);comment:创建时间" json:"created_at"` // 创建时间 + UpdatedAt time.Time `gorm:"column:updated_at;not null;default:CURRENT_TIMESTAMP(3);comment:更新时间" json:"updated_at"` // 更新时间 + Name string `gorm:"column:name;not null;comment:活动分类名称" json:"name"` // 活动分类名称 + ParentID int64 `gorm:"column:parent_id;comment:父分类ID(可空)" json:"parent_id"` // 父分类ID(可空) + Status int32 `gorm:"column:status;not null;default:1;comment:状态:1启用 2禁用" json:"status"` // 状态:1启用 2禁用 +} + +// TableName ActivityCategories's table name +func (*ActivityCategories) TableName() string { + return TableNameActivityCategories +} diff --git a/internal/repository/mysql/model/activity_draw_effects.gen.go b/internal/repository/mysql/model/activity_draw_effects.gen.go new file mode 100644 index 0000000..2fcd1b0 --- /dev/null +++ b/internal/repository/mysql/model/activity_draw_effects.gen.go @@ -0,0 +1,36 @@ +// Code generated by gorm.io/gen. DO NOT EDIT. +// Code generated by gorm.io/gen. DO NOT EDIT. +// Code generated by gorm.io/gen. DO NOT EDIT. + +package model + +import ( + "time" +) + +const TableNameActivityDrawEffects = "activity_draw_effects" + +// ActivityDrawEffects 抽奖效果日志 +type ActivityDrawEffects struct { + ID int64 `gorm:"column:id;primaryKey;autoIncrement:true;comment:主键ID" json:"id"` // 主键ID + CreatedAt time.Time `gorm:"column:created_at;not null;default:CURRENT_TIMESTAMP(3);comment:创建时间" json:"created_at"` // 创建时间 + DrawLogID int64 `gorm:"column:draw_log_id;not null;comment:抽奖日志ID(activity_draw_logs.id)" json:"draw_log_id"` // 抽奖日志ID(activity_draw_logs.id) + UserID int64 `gorm:"column:user_id;not null;comment:用户ID(users.id)" json:"user_id"` // 用户ID(users.id) + UserItemCardID int64 `gorm:"column:user_item_card_id;comment:用户卡实例ID(user_item_cards.id)" json:"user_item_card_id"` // 用户卡实例ID(user_item_cards.id) + SystemItemCardID int64 `gorm:"column:system_item_card_id;comment:卡模板ID(system_item_cards.id)" json:"system_item_card_id"` // 卡模板ID(system_item_cards.id) + Applied int32 `gorm:"column:applied;not null;default:1;comment:是否生效:0否 1是" json:"applied"` // 是否生效:0否 1是 + CardType int32 `gorm:"column:card_type;not null;comment:卡类型快照" json:"card_type"` // 卡类型快照 + EffectType int32 `gorm:"column:effect_type;not null;comment:效果类型快照" json:"effect_type"` // 效果类型快照 + RewardMultiplierX1000 int32 `gorm:"column:reward_multiplier_x1000;not null;comment:奖励倍数(千分比)" json:"reward_multiplier_x1000"` // 奖励倍数(千分比) + ProbabilityDeltaX1000 int32 `gorm:"column:probability_delta_x1000;not null;comment:概率相对增益(千分比)" json:"probability_delta_x1000"` // 概率相对增益(千分比) + ScopeType int32 `gorm:"column:scope_type;not null;comment:适用范围快照" json:"scope_type"` // 适用范围快照 + ActivityCategoryID int64 `gorm:"column:activity_category_id;comment:范围快照-活动分类ID" json:"activity_category_id"` // 范围快照-活动分类ID + ActivityID int64 `gorm:"column:activity_id;comment:范围快照-活动ID" json:"activity_id"` // 范围快照-活动ID + IssueID int64 `gorm:"column:issue_id;comment:范围快照-期ID" json:"issue_id"` // 范围快照-期ID + Remark string `gorm:"column:remark;comment:备注" json:"remark"` // 备注 +} + +// TableName ActivityDrawEffects's table name +func (*ActivityDrawEffects) TableName() string { + return TableNameActivityDrawEffects +} diff --git a/internal/repository/mysql/model/activity_draw_logs.gen.go b/internal/repository/mysql/model/activity_draw_logs.gen.go new file mode 100644 index 0000000..2d0eade --- /dev/null +++ b/internal/repository/mysql/model/activity_draw_logs.gen.go @@ -0,0 +1,29 @@ +// Code generated by gorm.io/gen. DO NOT EDIT. +// Code generated by gorm.io/gen. DO NOT EDIT. +// Code generated by gorm.io/gen. DO NOT EDIT. + +package model + +import ( + "time" +) + +const TableNameActivityDrawLogs = "activity_draw_logs" + +// ActivityDrawLogs 抽奖日志 +type ActivityDrawLogs struct { + ID int64 `gorm:"column:id;primaryKey;autoIncrement:true;comment:主键ID" json:"id"` // 主键ID + CreatedAt time.Time `gorm:"column:created_at;not null;default:CURRENT_TIMESTAMP(3);comment:创建时间" json:"created_at"` // 创建时间 + UserID int64 `gorm:"column:user_id;not null;comment:用户ID(mall_user.id)" json:"user_id"` // 用户ID(mall_user.id) + IssueID int64 `gorm:"column:issue_id;not null;comment:期ID(activity_issues.id)" json:"issue_id"` // 期ID(activity_issues.id) + OrderID int64 `gorm:"column:order_id;comment:抽奖票据订单ID(orders.id)" json:"order_id"` // 抽奖票据订单ID(orders.id) + RewardID int64 `gorm:"column:reward_id;comment:命中奖励ID(activity_reward_settings.id)" json:"reward_id"` // 命中奖励ID(activity_reward_settings.id) + IsWinner int32 `gorm:"column:is_winner;not null;comment:是否中奖:0否 1是" json:"is_winner"` // 是否中奖:0否 1是 + Level int32 `gorm:"column:level;not null;comment:中奖等级(如1=S 2=A 3=B)" json:"level"` // 中奖等级(如1=S 2=A 3=B) + CurrentLevel int32 `gorm:"column:current_level;comment:当前层(针对爬塔)其它默认为1" json:"current_level"` // 当前层(针对爬塔)其它默认为1 +} + +// TableName ActivityDrawLogs's table name +func (*ActivityDrawLogs) TableName() string { + return TableNameActivityDrawLogs +} diff --git a/internal/repository/mysql/model/activity_issues.gen.go b/internal/repository/mysql/model/activity_issues.gen.go new file mode 100644 index 0000000..c9ec14c --- /dev/null +++ b/internal/repository/mysql/model/activity_issues.gen.go @@ -0,0 +1,27 @@ +// Code generated by gorm.io/gen. DO NOT EDIT. +// Code generated by gorm.io/gen. DO NOT EDIT. +// Code generated by gorm.io/gen. DO NOT EDIT. + +package model + +import ( + "time" +) + +const TableNameActivityIssues = "activity_issues" + +// ActivityIssues 活动期 +type ActivityIssues struct { + ID int64 `gorm:"column:id;primaryKey;autoIncrement:true;comment:主键ID" json:"id"` // 主键ID + CreatedAt time.Time `gorm:"column:created_at;not null;default:CURRENT_TIMESTAMP(3);comment:创建时间" json:"created_at"` // 创建时间 + UpdatedAt time.Time `gorm:"column:updated_at;not null;default:CURRENT_TIMESTAMP(3);comment:更新时间" json:"updated_at"` // 更新时间 + ActivityID int64 `gorm:"column:activity_id;not null;comment:活动ID(activities.id)" json:"activity_id"` // 活动ID(activities.id) + IssueNumber string `gorm:"column:issue_number;not null;comment:期号(活动内唯一)" json:"issue_number"` // 期号(活动内唯一) + Status int32 `gorm:"column:status;not null;default:1;comment:状态:1进行中 2已结束 3未开始" json:"status"` // 状态:1进行中 2已结束 3未开始 + Sort int32 `gorm:"column:sort;default:1;comment:排序" json:"sort"` // 排序 +} + +// TableName ActivityIssues's table name +func (*ActivityIssues) TableName() string { + return TableNameActivityIssues +} diff --git a/internal/repository/mysql/model/activity_reward_settings.gen.go b/internal/repository/mysql/model/activity_reward_settings.gen.go new file mode 100644 index 0000000..8087ad6 --- /dev/null +++ b/internal/repository/mysql/model/activity_reward_settings.gen.go @@ -0,0 +1,32 @@ +// Code generated by gorm.io/gen. DO NOT EDIT. +// Code generated by gorm.io/gen. DO NOT EDIT. +// Code generated by gorm.io/gen. DO NOT EDIT. + +package model + +import ( + "time" +) + +const TableNameActivityRewardSettings = "activity_reward_settings" + +// ActivityRewardSettings 活动期-奖励配置 +type ActivityRewardSettings struct { + ID int64 `gorm:"column:id;primaryKey;autoIncrement:true;comment:主键ID" json:"id"` // 主键ID + CreatedAt time.Time `gorm:"column:created_at;not null;default:CURRENT_TIMESTAMP(3);comment:创建时间" json:"created_at"` // 创建时间 + UpdatedAt time.Time `gorm:"column:updated_at;not null;default:CURRENT_TIMESTAMP(3);comment:更新时间" json:"updated_at"` // 更新时间 + IssueID int64 `gorm:"column:issue_id;not null;comment:期ID(activity_issues.id)" json:"issue_id"` // 期ID(activity_issues.id) + ProductID int64 `gorm:"column:product_id;comment:奖品对应商品ID(实物奖可填)" json:"product_id"` // 奖品对应商品ID(实物奖可填) + Name string `gorm:"column:name;not null;comment:奖项名称/道具名称" json:"name"` // 奖项名称/道具名称 + Weight int32 `gorm:"column:weight;not null;comment:抽中权重(越大越易中)" json:"weight"` // 抽中权重(越大越易中) + Quantity int64 `gorm:"column:quantity;not null;comment:当前可发数量(扣减)" json:"quantity"` // 当前可发数量(扣减) + OriginalQty int64 `gorm:"column:original_qty;not null;comment:初始配置数量" json:"original_qty"` // 初始配置数量 + Level int32 `gorm:"column:level;not null;comment:奖级(如1=S 2=A 3=B)" json:"level"` // 奖级(如1=S 2=A 3=B) + Sort int32 `gorm:"column:sort;comment:排序" json:"sort"` // 排序 + IsBoss int32 `gorm:"column:is_boss;comment:Boss 1 是 0 不是" json:"is_boss"` // Boss 1 是 0 不是 +} + +// TableName ActivityRewardSettings's table name +func (*ActivityRewardSettings) TableName() string { + return TableNameActivityRewardSettings +} diff --git a/internal/repository/mysql/model/app_keyword.gen.go b/internal/repository/mysql/model/app_keyword.gen.go deleted file mode 100644 index 0bf1ada..0000000 --- a/internal/repository/mysql/model/app_keyword.gen.go +++ /dev/null @@ -1,27 +0,0 @@ -// Code generated by gorm.io/gen. DO NOT EDIT. -// Code generated by gorm.io/gen. DO NOT EDIT. -// Code generated by gorm.io/gen. DO NOT EDIT. - -package model - -import ( - "time" -) - -const TableNameAppKeyword = "app_keyword" - -// AppKeyword 关键字表 -type AppKeyword struct { - ID int32 `gorm:"column:id;primaryKey;autoIncrement:true;comment:主键ID" json:"id"` // 主键ID - AppID string `gorm:"column:app_id;not null;comment:小程序ID" json:"app_id"` // 小程序ID - Keyword string `gorm:"column:keyword;not null;comment:关键字" json:"keyword"` // 关键字 - CreatedUser string `gorm:"column:created_user;not null;comment:创建人" json:"created_user"` // 创建人 - CreatedAt time.Time `gorm:"column:created_at;not null;default:CURRENT_TIMESTAMP;comment:创建时间" json:"created_at"` // 创建时间 - UpdatedUser string `gorm:"column:updated_user;not null;comment:更新人" json:"updated_user"` // 更新人 - UpdatedAt time.Time `gorm:"column:updated_at;not null;default:CURRENT_TIMESTAMP;comment:更新时间" json:"updated_at"` // 更新时间 -} - -// TableName AppKeyword's table name -func (*AppKeyword) TableName() string { - return TableNameAppKeyword -} diff --git a/internal/repository/mysql/model/app_keyword_reply.gen.go b/internal/repository/mysql/model/app_keyword_reply.gen.go deleted file mode 100644 index f007ddb..0000000 --- a/internal/repository/mysql/model/app_keyword_reply.gen.go +++ /dev/null @@ -1,30 +0,0 @@ -// Code generated by gorm.io/gen. DO NOT EDIT. -// Code generated by gorm.io/gen. DO NOT EDIT. -// Code generated by gorm.io/gen. DO NOT EDIT. - -package model - -import ( - "time" -) - -const TableNameAppKeywordReply = "app_keyword_reply" - -// AppKeywordReply 关键字回复表 -type AppKeywordReply struct { - ID int32 `gorm:"column:id;primaryKey;autoIncrement:true;comment:主键ID" json:"id"` // 主键ID - AppID string `gorm:"column:app_id;not null;comment:小程序ID" json:"app_id"` // 小程序ID - KeywordID int32 `gorm:"column:keyword_id;not null;comment:关联 app_keyword 表的ID" json:"keyword_id"` // 关联 app_keyword 表的ID - IntervalSeconds int32 `gorm:"column:interval_seconds;not null;comment:时间间隔,单位为秒" json:"interval_seconds"` // 时间间隔,单位为秒 - Type int32 `gorm:"column:type;not null;comment:类型(1:文本 2:图片 3:语音条 4:视频 5=小程序 6=地理位置 7=链接 8=GIF图 9=名片 10=文件 11=转人工)" json:"type"` // 类型(1:文本 2:图片 3:语音条 4:视频 5=小程序 6=地理位置 7=链接 8=GIF图 9=名片 10=文件 11=转人工) - Content string `gorm:"column:content;not null;comment:内容" json:"content"` // 内容 - CreatedUser string `gorm:"column:created_user;not null;comment:创建人" json:"created_user"` // 创建人 - CreatedAt time.Time `gorm:"column:created_at;not null;default:CURRENT_TIMESTAMP;comment:创建时间" json:"created_at"` // 创建时间 - UpdatedUser string `gorm:"column:updated_user;not null;comment:更新人" json:"updated_user"` // 更新人 - UpdatedAt time.Time `gorm:"column:updated_at;not null;default:CURRENT_TIMESTAMP;comment:更新时间" json:"updated_at"` // 更新时间 -} - -// TableName AppKeywordReply's table name -func (*AppKeywordReply) TableName() string { - return TableNameAppKeywordReply -} diff --git a/internal/repository/mysql/model/app_message_log.gen.go b/internal/repository/mysql/model/app_message_log.gen.go deleted file mode 100644 index b8dc38d..0000000 --- a/internal/repository/mysql/model/app_message_log.gen.go +++ /dev/null @@ -1,30 +0,0 @@ -// Code generated by gorm.io/gen. DO NOT EDIT. -// Code generated by gorm.io/gen. DO NOT EDIT. -// Code generated by gorm.io/gen. DO NOT EDIT. - -package model - -import ( - "time" -) - -const TableNameAppMessageLog = "app_message_log" - -// AppMessageLog 消息日志表 -type AppMessageLog struct { - ID int32 `gorm:"column:id;primaryKey;autoIncrement:true;comment:主键ID" json:"id"` // 主键ID - AppID string `gorm:"column:app_id;not null;comment:小程序ID" json:"app_id"` // 小程序ID - SenderID string `gorm:"column:sender_id;not null;comment:发送人ID" json:"sender_id"` // 发送人ID - SenderName string `gorm:"column:sender_name;not null;comment:发送人昵称" json:"sender_name"` // 发送人昵称 - SendTime time.Time `gorm:"column:send_time;comment:发送时间" json:"send_time"` // 发送时间 - ReceiverID string `gorm:"column:receiver_id;not null;comment:接收人ID" json:"receiver_id"` // 接收人ID - MsgType int32 `gorm:"column:msg_type;not null;comment:消息类型(1:文本 2:图片)" json:"msg_type"` // 消息类型(1:文本 2:图片) - Content string `gorm:"column:content;not null;comment:消息内容" json:"content"` // 消息内容 - CreatedAt time.Time `gorm:"column:created_at;not null;default:CURRENT_TIMESTAMP;comment:创建时间" json:"created_at"` // 创建时间 - IsRead int32 `gorm:"column:is_read;comment:是否已读(0:未读 1:已读)" json:"is_read"` // 是否已读(0:未读 1:已读) -} - -// TableName AppMessageLog's table name -func (*AppMessageLog) TableName() string { - return TableNameAppMessageLog -} diff --git a/internal/repository/mysql/model/app_user.gen.go b/internal/repository/mysql/model/app_user.gen.go deleted file mode 100644 index 0f8a349..0000000 --- a/internal/repository/mysql/model/app_user.gen.go +++ /dev/null @@ -1,27 +0,0 @@ -// Code generated by gorm.io/gen. DO NOT EDIT. -// Code generated by gorm.io/gen. DO NOT EDIT. -// Code generated by gorm.io/gen. DO NOT EDIT. - -package model - -import ( - "time" -) - -const TableNameAppUser = "app_user" - -// AppUser 小程序的用户表 -type AppUser struct { - ID int32 `gorm:"column:id;primaryKey;autoIncrement:true;comment:主键ID" json:"id"` // 主键ID - AppID string `gorm:"column:app_id;not null;comment:小程序ID" json:"app_id"` // 小程序ID - UserID string `gorm:"column:user_id;not null;comment:用户ID" json:"user_id"` // 用户ID - UserName string `gorm:"column:user_name;not null;comment:用户昵称" json:"user_name"` // 用户昵称 - UserMobile string `gorm:"column:user_mobile;not null;comment:用户手机号" json:"user_mobile"` // 用户手机号 - UserAvatar string `gorm:"column:user_avatar;not null;comment:用户头像" json:"user_avatar"` // 用户头像 - CreatedAt time.Time `gorm:"column:created_at;not null;default:CURRENT_TIMESTAMP;comment:创建时间" json:"created_at"` // 创建时间 -} - -// TableName AppUser's table name -func (*AppUser) TableName() string { - return TableNameAppUser -} diff --git a/internal/repository/mysql/model/banner.gen.go b/internal/repository/mysql/model/banner.gen.go new file mode 100644 index 0000000..eae3ba8 --- /dev/null +++ b/internal/repository/mysql/model/banner.gen.go @@ -0,0 +1,28 @@ +// Code generated by gorm.io/gen. DO NOT EDIT. +// Code generated by gorm.io/gen. DO NOT EDIT. +// Code generated by gorm.io/gen. DO NOT EDIT. + +package model + +import ( + "time" +) + +const TableNameBanner = "banner" + +// Banner 轮播图 +type Banner struct { + ID int64 `gorm:"column:id;primaryKey;autoIncrement:true" json:"id"` + Title string `gorm:"column:title;not null;comment:标题" json:"title"` // 标题 + ImageURL string `gorm:"column:image_url;not null;comment:图片URL" json:"image_url"` // 图片URL + LinkURL string `gorm:"column:link_url;not null;comment:跳转链接(可选)" json:"link_url"` // 跳转链接(可选) + Sort int32 `gorm:"column:sort;not null;comment:排序,越小越靠前" json:"sort"` // 排序,越小越靠前 + Status int32 `gorm:"column:status;not null;default:1;comment:状态:1启用 0禁用" json:"status"` // 状态:1启用 0禁用 + CreatedAt time.Time `gorm:"column:created_at;not null;default:CURRENT_TIMESTAMP" json:"created_at"` + UpdatedAt time.Time `gorm:"column:updated_at;not null;default:CURRENT_TIMESTAMP" json:"updated_at"` +} + +// TableName Banner's table name +func (*Banner) TableName() string { + return TableNameBanner +} diff --git a/internal/repository/mysql/model/guild.gen.go b/internal/repository/mysql/model/guild.gen.go new file mode 100644 index 0000000..52f37f8 --- /dev/null +++ b/internal/repository/mysql/model/guild.gen.go @@ -0,0 +1,30 @@ +// Code generated by gorm.io/gen. DO NOT EDIT. +// Code generated by gorm.io/gen. DO NOT EDIT. +// Code generated by gorm.io/gen. DO NOT EDIT. + +package model + +import ( + "time" +) + +const TableNameGuild = "guild" + +// Guild 公会 +type Guild struct { + ID int64 `gorm:"column:id;primaryKey;autoIncrement:true;comment:主键ID" json:"id"` // 主键ID + CreatedAt time.Time `gorm:"column:created_at;not null;default:CURRENT_TIMESTAMP(3);comment:创建时间" json:"created_at"` // 创建时间 + Name string `gorm:"column:name;not null;comment:公会名称" json:"name"` // 公会名称 + OwnerID int64 `gorm:"column:owner_id;not null;comment:会长用户ID" json:"owner_id"` // 会长用户ID + Status int32 `gorm:"column:status;not null;default:1;comment:状态:1正常 2解散" json:"status"` // 状态:1正常 2解散 + Description string `gorm:"column:description;comment:工会描述" json:"description"` // 工会描述 + JoinMode int32 `gorm:"column:join_mode;default:2;comment:加入方式 1: 审核通过 2: 自动通过 3. 消费流水" json:"join_mode"` // 加入方式 1: 审核通过 2: 自动通过 3. 消费流水 + ConsumeLimit int64 `gorm:"column:consume_limit;comment:加入工会消费流水最低限额(分)" json:"consume_limit"` // 加入工会消费流水最低限额(分) + AvatarURL string `gorm:"column:avatar_url;comment:工会头像" json:"avatar_url"` // 工会头像 + IsOpen int32 `gorm:"column:is_open;default:1;comment:1 公开 2 私有" json:"is_open"` // 1 公开 2 私有 +} + +// TableName Guild's table name +func (*Guild) TableName() string { + return TableNameGuild +} diff --git a/internal/repository/mysql/model/guild_boxes.gen.go b/internal/repository/mysql/model/guild_boxes.gen.go new file mode 100644 index 0000000..7430028 --- /dev/null +++ b/internal/repository/mysql/model/guild_boxes.gen.go @@ -0,0 +1,26 @@ +// Code generated by gorm.io/gen. DO NOT EDIT. +// Code generated by gorm.io/gen. DO NOT EDIT. +// Code generated by gorm.io/gen. DO NOT EDIT. + +package model + +import ( + "time" +) + +const TableNameGuildBoxes = "guild_boxes" + +// GuildBoxes 公会盲盒玩法聚合 +type GuildBoxes struct { + ID int64 `gorm:"column:id;primaryKey;autoIncrement:true;comment:主键ID" json:"id"` // 主键ID + CreatedAt time.Time `gorm:"column:created_at;not null;default:CURRENT_TIMESTAMP(3);comment:创建时间" json:"created_at"` // 创建时间 + GuildID int64 `gorm:"column:guild_id;not null;comment:公会ID(guild_main.id)" json:"guild_id"` // 公会ID(guild_main.id) + KindID int64 `gorm:"column:kind_id;not null;comment:奖品id( 如果是 积分可以 空; 商品ID 道具卡ID)" json:"kind_id"` // 奖品id( 如果是 积分可以 空; 商品ID 道具卡ID) + Value int64 `gorm:"column:value;comment:累计价值/积分等(业务自定义-可以为空)" json:"value"` // 累计价值/积分等(业务自定义-可以为空) + KindType int32 `gorm:"column:kind_type;not null;comment:奖品类型: 0 积分 1 优惠券 2 道具卡" json:"kind_type"` // 奖品类型: 0 积分 1 优惠券 2 道具卡 +} + +// TableName GuildBoxes's table name +func (*GuildBoxes) TableName() string { + return TableNameGuildBoxes +} diff --git a/internal/repository/mysql/model/guild_contribute_logs.gen.go b/internal/repository/mysql/model/guild_contribute_logs.gen.go new file mode 100644 index 0000000..9950320 --- /dev/null +++ b/internal/repository/mysql/model/guild_contribute_logs.gen.go @@ -0,0 +1,29 @@ +// Code generated by gorm.io/gen. DO NOT EDIT. +// Code generated by gorm.io/gen. DO NOT EDIT. +// Code generated by gorm.io/gen. DO NOT EDIT. + +package model + +import ( + "time" +) + +const TableNameGuildContributeLogs = "guild_contribute_logs" + +// GuildContributeLogs 公会贡献流水 +type GuildContributeLogs struct { + ID int64 `gorm:"column:id;primaryKey;autoIncrement:true;comment:主键ID" json:"id"` // 主键ID + CreatedAt time.Time `gorm:"column:created_at;not null;default:CURRENT_TIMESTAMP(3);comment:创建时间" json:"created_at"` // 创建时间 + GuildID int64 `gorm:"column:guild_id;not null;comment:公会ID(guild_main.id)" json:"guild_id"` // 公会ID(guild_main.id) + UserID int64 `gorm:"column:user_id;not null;comment:用户ID(user_members.id)" json:"user_id"` // 用户ID(user_members.id) + ActivityID int64 `gorm:"column:activity_id;comment:活动ID(可空)" json:"activity_id"` // 活动ID(可空) + IssuesID int64 `gorm:"column:issues_id;comment:活动期ID(可空)" json:"issues_id"` // 活动期ID(可空) + Action string `gorm:"column:action;not null;comment:贡献动作(抽奖/购买/分享等)" json:"action"` // 贡献动作(抽奖/购买/分享等) + Value int64 `gorm:"column:value;not null;comment:贡献值(业务自定义)" json:"value"` // 贡献值(业务自定义) + ProductID int32 `gorm:"column:product_id;comment:奖品ID (可空)" json:"product_id"` // 奖品ID (可空) +} + +// TableName GuildContributeLogs's table name +func (*GuildContributeLogs) TableName() string { + return TableNameGuildContributeLogs +} diff --git a/internal/repository/mysql/model/guild_members.gen.go b/internal/repository/mysql/model/guild_members.gen.go new file mode 100644 index 0000000..47855dd --- /dev/null +++ b/internal/repository/mysql/model/guild_members.gen.go @@ -0,0 +1,28 @@ +// Code generated by gorm.io/gen. DO NOT EDIT. +// Code generated by gorm.io/gen. DO NOT EDIT. +// Code generated by gorm.io/gen. DO NOT EDIT. + +package model + +import ( + "time" +) + +const TableNameGuildMembers = "guild_members" + +// GuildMembers 公会成员 +type GuildMembers struct { + ID int64 `gorm:"column:id;primaryKey;autoIncrement:true;comment:主键ID" json:"id"` // 主键ID + CreatedAt time.Time `gorm:"column:created_at;not null;default:CURRENT_TIMESTAMP(3);comment:创建时间" json:"created_at"` // 创建时间 + GuildID int64 `gorm:"column:guild_id;not null;comment:公会ID(guild_main.id)" json:"guild_id"` // 公会ID(guild_main.id) + UserID int64 `gorm:"column:user_id;not null;comment:成员用户ID(user_members.id)" json:"user_id"` // 成员用户ID(user_members.id) + Role string `gorm:"column:role;not null;default:member;comment:角色:owner/admin/member" json:"role"` // 角色:owner/admin/member + StartTime time.Time `gorm:"column:start_time;comment:加入时间" json:"start_time"` // 加入时间 + Status int32 `gorm:"column:status;not null;default:1;comment:状态:1正常 2退出" json:"status"` // 状态:1正常 2退出 + JoinStatus int32 `gorm:"column:join_status;not null;default:1;comment:状态:1 拒绝 2 同意" json:"join_status"` // 状态:1 拒绝 2 同意 +} + +// TableName GuildMembers's table name +func (*GuildMembers) TableName() string { + return TableNameGuildMembers +} diff --git a/internal/repository/mysql/model/menu_actions.gen.go b/internal/repository/mysql/model/menu_actions.gen.go new file mode 100644 index 0000000..67c29a0 --- /dev/null +++ b/internal/repository/mysql/model/menu_actions.gen.go @@ -0,0 +1,29 @@ +// Code generated by gorm.io/gen. DO NOT EDIT. +// Code generated by gorm.io/gen. DO NOT EDIT. +// Code generated by gorm.io/gen. DO NOT EDIT. + +package model + +import ( + "time" +) + +const TableNameMenuActions = "menu_actions" + +// MenuActions mapped from table +type MenuActions struct { + ID int64 `gorm:"column:id;primaryKey;autoIncrement:true" json:"id"` + MenuID int64 `gorm:"column:menu_id;not null" json:"menu_id"` + ActionMark string `gorm:"column:action_mark;not null" json:"action_mark"` + ActionName string `gorm:"column:action_name;not null" json:"action_name"` + Status bool `gorm:"column:status;not null;default:1" json:"status"` + CreatedUser string `gorm:"column:created_user;not null" json:"created_user"` + UpdatedUser string `gorm:"column:updated_user;not null" json:"updated_user"` + CreatedAt time.Time `gorm:"column:created_at;not null;default:CURRENT_TIMESTAMP(3)" json:"created_at"` + UpdatedAt time.Time `gorm:"column:updated_at;not null;default:CURRENT_TIMESTAMP(3)" json:"updated_at"` +} + +// TableName MenuActions's table name +func (*MenuActions) TableName() string { + return TableNameMenuActions +} diff --git a/internal/repository/mysql/model/menus.gen.go b/internal/repository/mysql/model/menus.gen.go new file mode 100644 index 0000000..10ef4ca --- /dev/null +++ b/internal/repository/mysql/model/menus.gen.go @@ -0,0 +1,35 @@ +// Code generated by gorm.io/gen. DO NOT EDIT. +// Code generated by gorm.io/gen. DO NOT EDIT. +// Code generated by gorm.io/gen. DO NOT EDIT. + +package model + +import ( + "time" +) + +const TableNameMenus = "menus" + +// Menus mapped from table +type Menus struct { + ID int64 `gorm:"column:id;primaryKey;autoIncrement:true" json:"id"` + ParentID int64 `gorm:"column:parent_id;not null" json:"parent_id"` + Path string `gorm:"column:path;not null" json:"path"` + Name string `gorm:"column:name;not null" json:"name"` + Component string `gorm:"column:component;not null" json:"component"` + Icon string `gorm:"column:icon" json:"icon"` + Sort int32 `gorm:"column:sort;not null" json:"sort"` + Status bool `gorm:"column:status;not null;default:1" json:"status"` + KeepAlive bool `gorm:"column:keep_alive;not null" json:"keep_alive"` + IsHide bool `gorm:"column:is_hide;not null" json:"is_hide"` + IsHideTab bool `gorm:"column:is_hide_tab;not null" json:"is_hide_tab"` + CreatedUser string `gorm:"column:created_user;not null" json:"created_user"` + UpdatedUser string `gorm:"column:updated_user;not null" json:"updated_user"` + CreatedAt time.Time `gorm:"column:created_at;not null;default:CURRENT_TIMESTAMP(3)" json:"created_at"` + UpdatedAt time.Time `gorm:"column:updated_at;not null;default:CURRENT_TIMESTAMP(3)" json:"updated_at"` +} + +// TableName Menus's table name +func (*Menus) TableName() string { + return TableNameMenus +} diff --git a/internal/repository/mysql/model/mini_program.gen.go b/internal/repository/mysql/model/mini_program.gen.go deleted file mode 100644 index f7a0db8..0000000 --- a/internal/repository/mysql/model/mini_program.gen.go +++ /dev/null @@ -1,33 +0,0 @@ -// Code generated by gorm.io/gen. DO NOT EDIT. -// Code generated by gorm.io/gen. DO NOT EDIT. -// Code generated by gorm.io/gen. DO NOT EDIT. - -package model - -import ( - "time" -) - -const TableNameMiniProgram = "mini_program" - -// MiniProgram 小程序表 -type MiniProgram struct { - ID int32 `gorm:"column:id;primaryKey;autoIncrement:true;comment:主键ID" json:"id"` // 主键ID - AppID string `gorm:"column:app_id;not null;comment:小程序ID" json:"app_id"` // 小程序ID - AppSecret string `gorm:"column:app_secret;not null;comment:小程序密钥" json:"app_secret"` // 小程序密钥 - AdminID int32 `gorm:"column:admin_id;not null;comment:管理员ID" json:"admin_id"` // 管理员ID - TemplateID string `gorm:"column:template_id;not null;comment:模版ID" json:"template_id"` // 模版ID - Name string `gorm:"column:name;not null;comment:名称" json:"name"` // 名称 - Description string `gorm:"column:description;not null;comment:描述" json:"description"` // 描述 - Avatar string `gorm:"column:avatar;not null;comment:头像" json:"avatar"` // 头像 - Status int32 `gorm:"column:status;not null;comment:状态(1:正常 -1:封禁)" json:"status"` // 状态(1:正常 -1:封禁) - CreatedUser string `gorm:"column:created_user;not null;comment:创建人" json:"created_user"` // 创建人 - CreatedAt time.Time `gorm:"column:created_at;not null;default:CURRENT_TIMESTAMP;comment:创建时间" json:"created_at"` // 创建时间 - UpdatedUser string `gorm:"column:updated_user;not null;comment:更新人" json:"updated_user"` // 更新人 - UpdatedAt time.Time `gorm:"column:updated_at;not null;default:CURRENT_TIMESTAMP;comment:更新时间" json:"updated_at"` // 更新时间 -} - -// TableName MiniProgram's table name -func (*MiniProgram) TableName() string { - return TableNameMiniProgram -} diff --git a/internal/repository/mysql/model/order_items.gen.go b/internal/repository/mysql/model/order_items.gen.go new file mode 100644 index 0000000..5139aaf --- /dev/null +++ b/internal/repository/mysql/model/order_items.gen.go @@ -0,0 +1,30 @@ +// Code generated by gorm.io/gen. DO NOT EDIT. +// Code generated by gorm.io/gen. DO NOT EDIT. +// Code generated by gorm.io/gen. DO NOT EDIT. + +package model + +import ( + "time" +) + +const TableNameOrderItems = "order_items" + +// OrderItems 订单明细 +type OrderItems struct { + ID int64 `gorm:"column:id;primaryKey;autoIncrement:true;comment:主键ID" json:"id"` // 主键ID + CreatedAt time.Time `gorm:"column:created_at;not null;default:CURRENT_TIMESTAMP(3);comment:创建时间" json:"created_at"` // 创建时间 + OrderID int64 `gorm:"column:order_id;not null;comment:订单ID(orders.id)" json:"order_id"` // 订单ID(orders.id) + ProductID int64 `gorm:"column:product_id;not null;comment:商品ID(products.id)" json:"product_id"` // 商品ID(products.id) + Title string `gorm:"column:title;not null;comment:商品标题快照" json:"title"` // 商品标题快照 + Quantity int64 `gorm:"column:quantity;not null;default:1;comment:购买数量" json:"quantity"` // 购买数量 + Price int64 `gorm:"column:price;not null;comment:成交单价(分)" json:"price"` // 成交单价(分) + TotalAmount int64 `gorm:"column:total_amount;not null;comment:行应付总额(分)" json:"total_amount"` // 行应付总额(分) + ProductImages string `gorm:"column:product_images;comment:商品图片快照(JSON)" json:"product_images"` // 商品图片快照(JSON) + Status int32 `gorm:"column:status;not null;default:1;comment:行状态:1正常 2取消" json:"status"` // 行状态:1正常 2取消 +} + +// TableName OrderItems's table name +func (*OrderItems) TableName() string { + return TableNameOrderItems +} diff --git a/internal/repository/mysql/model/orders.gen.go b/internal/repository/mysql/model/orders.gen.go new file mode 100644 index 0000000..80b4453 --- /dev/null +++ b/internal/repository/mysql/model/orders.gen.go @@ -0,0 +1,38 @@ +// Code generated by gorm.io/gen. DO NOT EDIT. +// Code generated by gorm.io/gen. DO NOT EDIT. +// Code generated by gorm.io/gen. DO NOT EDIT. + +package model + +import ( + "time" +) + +const TableNameOrders = "orders" + +// Orders 订单 +type Orders struct { + ID int64 `gorm:"column:id;primaryKey;autoIncrement:true;comment:主键ID" json:"id"` // 主键ID + CreatedAt time.Time `gorm:"column:created_at;not null;default:CURRENT_TIMESTAMP(3);comment:创建时间" json:"created_at"` // 创建时间 + UpdatedAt time.Time `gorm:"column:updated_at;not null;default:CURRENT_TIMESTAMP(3);comment:更新时间" json:"updated_at"` // 更新时间 + UserID int64 `gorm:"column:user_id;not null;comment:下单用户ID(user_members.id)" json:"user_id"` // 下单用户ID(user_members.id) + OrderNo string `gorm:"column:order_no;not null;comment:业务订单号(唯一)" json:"order_no"` // 业务订单号(唯一) + SourceType int32 `gorm:"column:source_type;not null;default:1;comment:来源:1商城直购 2抽奖票据 3其他" json:"source_type"` // 来源:1商城直购 2抽奖票据 3其他 + TotalAmount int64 `gorm:"column:total_amount;not null;comment:订单总金额(分)" json:"total_amount"` // 订单总金额(分) + DiscountAmount int64 `gorm:"column:discount_amount;not null;comment:优惠券抵扣金额(分)" json:"discount_amount"` // 优惠券抵扣金额(分) + PointsAmount int64 `gorm:"column:points_amount;not null;comment:积分抵扣金额(分)" json:"points_amount"` // 积分抵扣金额(分) + ActualAmount int64 `gorm:"column:actual_amount;not null;comment:实际支付金额(分)" json:"actual_amount"` // 实际支付金额(分) + Status int32 `gorm:"column:status;not null;default:1;comment:订单状态:1待支付 2已支付 3已取消 4已退款" json:"status"` // 订单状态:1待支付 2已支付 3已取消 4已退款 + PayPreorderID int64 `gorm:"column:pay_preorder_id;comment:关联预支付单ID(payment_preorder.id)" json:"pay_preorder_id"` // 关联预支付单ID(payment_preorder.id) + PaidAt time.Time `gorm:"column:paid_at;comment:支付完成时间" json:"paid_at"` // 支付完成时间 + CancelledAt time.Time `gorm:"column:cancelled_at;comment:取消时间" json:"cancelled_at"` // 取消时间 + UserAddressID int64 `gorm:"column:user_address_id;comment:收货地址ID(user_addresses.id)" json:"user_address_id"` // 收货地址ID(user_addresses.id) + IsConsumed int32 `gorm:"column:is_consumed;not null;comment:是否已履约/消耗(对虚拟资产)" json:"is_consumed"` // 是否已履约/消耗(对虚拟资产) + PointsLedgerID int64 `gorm:"column:points_ledger_id;comment:积分扣减流水ID(user_points_ledger.id)" json:"points_ledger_id"` // 积分扣减流水ID(user_points_ledger.id) + Remark string `gorm:"column:remark;comment:备注" json:"remark"` // 备注 +} + +// TableName Orders's table name +func (*Orders) TableName() string { + return TableNameOrders +} diff --git a/internal/repository/mysql/model/product_categories.gen.go b/internal/repository/mysql/model/product_categories.gen.go new file mode 100644 index 0000000..281b699 --- /dev/null +++ b/internal/repository/mysql/model/product_categories.gen.go @@ -0,0 +1,26 @@ +// Code generated by gorm.io/gen. DO NOT EDIT. +// Code generated by gorm.io/gen. DO NOT EDIT. +// Code generated by gorm.io/gen. DO NOT EDIT. + +package model + +import ( + "time" +) + +const TableNameProductCategories = "product_categories" + +// ProductCategories 商品分类 +type ProductCategories struct { + ID int64 `gorm:"column:id;primaryKey;autoIncrement:true;comment:主键ID" json:"id"` // 主键ID + CreatedAt time.Time `gorm:"column:created_at;not null;default:CURRENT_TIMESTAMP(3);comment:创建时间" json:"created_at"` // 创建时间 + UpdatedAt time.Time `gorm:"column:updated_at;not null;default:CURRENT_TIMESTAMP(3);comment:更新时间" json:"updated_at"` // 更新时间 + Name string `gorm:"column:name;not null;comment:分类名称" json:"name"` // 分类名称 + ParentID int64 `gorm:"column:parent_id;comment:父分类ID(可空)" json:"parent_id"` // 父分类ID(可空) + Status int32 `gorm:"column:status;not null;default:1;comment:状态:1启用 2禁用" json:"status"` // 状态:1启用 2禁用 +} + +// TableName ProductCategories's table name +func (*ProductCategories) TableName() string { + return TableNameProductCategories +} diff --git a/internal/repository/mysql/model/products.gen.go b/internal/repository/mysql/model/products.gen.go new file mode 100644 index 0000000..25f8e8a --- /dev/null +++ b/internal/repository/mysql/model/products.gen.go @@ -0,0 +1,30 @@ +// Code generated by gorm.io/gen. DO NOT EDIT. +// Code generated by gorm.io/gen. DO NOT EDIT. +// Code generated by gorm.io/gen. DO NOT EDIT. + +package model + +import ( + "time" +) + +const TableNameProducts = "products" + +// Products 商品 +type Products struct { + ID int64 `gorm:"column:id;primaryKey;autoIncrement:true;comment:主键ID" json:"id"` // 主键ID + CreatedAt time.Time `gorm:"column:created_at;not null;default:CURRENT_TIMESTAMP(3);comment:创建时间" json:"created_at"` // 创建时间 + UpdatedAt time.Time `gorm:"column:updated_at;not null;default:CURRENT_TIMESTAMP(3);comment:更新时间" json:"updated_at"` // 更新时间 + Name string `gorm:"column:name;not null;comment:商品名称" json:"name"` // 商品名称 + CategoryID int64 `gorm:"column:category_id;comment:单一主分类ID(product_categories.id)" json:"category_id"` // 单一主分类ID(product_categories.id) + ImagesJSON string `gorm:"column:images_json;comment:商品图片JSON(数组)" json:"images_json"` // 商品图片JSON(数组) + Price int64 `gorm:"column:price;not null;comment:商品售价(分)" json:"price"` // 商品售价(分) + Stock int64 `gorm:"column:stock;not null;comment:可售库存" json:"stock"` // 可售库存 + Sales int64 `gorm:"column:sales;not null;comment:已售数量" json:"sales"` // 已售数量 + Status int32 `gorm:"column:status;not null;default:1;comment:上下架状态:1上架 2下架" json:"status"` // 上下架状态:1上架 2下架 +} + +// TableName Products's table name +func (*Products) TableName() string { + return TableNameProducts +} diff --git a/internal/repository/mysql/model/role_actions.gen.go b/internal/repository/mysql/model/role_actions.gen.go new file mode 100644 index 0000000..e97ef88 --- /dev/null +++ b/internal/repository/mysql/model/role_actions.gen.go @@ -0,0 +1,27 @@ +// Code generated by gorm.io/gen. DO NOT EDIT. +// Code generated by gorm.io/gen. DO NOT EDIT. +// Code generated by gorm.io/gen. DO NOT EDIT. + +package model + +import ( + "time" +) + +const TableNameRoleActions = "role_actions" + +// RoleActions mapped from table +type RoleActions struct { + ID int64 `gorm:"column:id;primaryKey;autoIncrement:true" json:"id"` + RoleID int64 `gorm:"column:role_id;not null" json:"role_id"` + ActionID int64 `gorm:"column:action_id;not null" json:"action_id"` + CreatedUser string `gorm:"column:created_user;not null" json:"created_user"` + UpdatedUser string `gorm:"column:updated_user;not null" json:"updated_user"` + CreatedAt time.Time `gorm:"column:created_at;not null;default:CURRENT_TIMESTAMP(3)" json:"created_at"` + UpdatedAt time.Time `gorm:"column:updated_at;not null;default:CURRENT_TIMESTAMP(3)" json:"updated_at"` +} + +// TableName RoleActions's table name +func (*RoleActions) TableName() string { + return TableNameRoleActions +} diff --git a/internal/repository/mysql/model/role_menus.gen.go b/internal/repository/mysql/model/role_menus.gen.go new file mode 100644 index 0000000..fa71342 --- /dev/null +++ b/internal/repository/mysql/model/role_menus.gen.go @@ -0,0 +1,27 @@ +// Code generated by gorm.io/gen. DO NOT EDIT. +// Code generated by gorm.io/gen. DO NOT EDIT. +// Code generated by gorm.io/gen. DO NOT EDIT. + +package model + +import ( + "time" +) + +const TableNameRoleMenus = "role_menus" + +// RoleMenus mapped from table +type RoleMenus struct { + ID int64 `gorm:"column:id;primaryKey;autoIncrement:true" json:"id"` + RoleID int64 `gorm:"column:role_id;not null" json:"role_id"` + MenuID int64 `gorm:"column:menu_id;not null" json:"menu_id"` + CreatedUser string `gorm:"column:created_user;not null" json:"created_user"` + UpdatedUser string `gorm:"column:updated_user;not null" json:"updated_user"` + CreatedAt time.Time `gorm:"column:created_at;not null;default:CURRENT_TIMESTAMP(3)" json:"created_at"` + UpdatedAt time.Time `gorm:"column:updated_at;not null;default:CURRENT_TIMESTAMP(3)" json:"updated_at"` +} + +// TableName RoleMenus's table name +func (*RoleMenus) TableName() string { + return TableNameRoleMenus +} diff --git a/internal/repository/mysql/model/role_users.gen.go b/internal/repository/mysql/model/role_users.gen.go new file mode 100644 index 0000000..d67d5a2 --- /dev/null +++ b/internal/repository/mysql/model/role_users.gen.go @@ -0,0 +1,27 @@ +// Code generated by gorm.io/gen. DO NOT EDIT. +// Code generated by gorm.io/gen. DO NOT EDIT. +// Code generated by gorm.io/gen. DO NOT EDIT. + +package model + +import ( + "time" +) + +const TableNameRoleUsers = "role_users" + +// RoleUsers mapped from table +type RoleUsers struct { + ID int64 `gorm:"column:id;primaryKey;autoIncrement:true" json:"id"` + RoleID int64 `gorm:"column:role_id;not null" json:"role_id"` + AdminID int32 `gorm:"column:admin_id;not null" json:"admin_id"` + CreatedUser string `gorm:"column:created_user;not null" json:"created_user"` + UpdatedUser string `gorm:"column:updated_user;not null" json:"updated_user"` + CreatedAt time.Time `gorm:"column:created_at;not null;default:CURRENT_TIMESTAMP(3)" json:"created_at"` + UpdatedAt time.Time `gorm:"column:updated_at;not null;default:CURRENT_TIMESTAMP(3)" json:"updated_at"` +} + +// TableName RoleUsers's table name +func (*RoleUsers) TableName() string { + return TableNameRoleUsers +} diff --git a/internal/repository/mysql/model/roles.gen.go b/internal/repository/mysql/model/roles.gen.go new file mode 100644 index 0000000..60ef2d8 --- /dev/null +++ b/internal/repository/mysql/model/roles.gen.go @@ -0,0 +1,29 @@ +// Code generated by gorm.io/gen. DO NOT EDIT. +// Code generated by gorm.io/gen. DO NOT EDIT. +// Code generated by gorm.io/gen. DO NOT EDIT. + +package model + +import ( + "time" +) + +const TableNameRoles = "roles" + +// Roles mapped from table +type Roles struct { + ID int64 `gorm:"column:id;primaryKey;autoIncrement:true" json:"id"` + RoleName string `gorm:"column:role_name;not null" json:"role_name"` + RoleCode string `gorm:"column:role_code;not null" json:"role_code"` + Description string `gorm:"column:description" json:"description"` + Enabled bool `gorm:"column:enabled;not null;default:1" json:"enabled"` + CreatedUser string `gorm:"column:created_user;not null" json:"created_user"` + UpdatedUser string `gorm:"column:updated_user;not null" json:"updated_user"` + CreatedAt time.Time `gorm:"column:created_at;not null;default:CURRENT_TIMESTAMP(3)" json:"created_at"` + UpdatedAt time.Time `gorm:"column:updated_at;not null;default:CURRENT_TIMESTAMP(3)" json:"updated_at"` +} + +// TableName Roles's table name +func (*Roles) TableName() string { + return TableNameRoles +} diff --git a/internal/repository/mysql/model/shipping_records.gen.go b/internal/repository/mysql/model/shipping_records.gen.go new file mode 100644 index 0000000..097dee1 --- /dev/null +++ b/internal/repository/mysql/model/shipping_records.gen.go @@ -0,0 +1,37 @@ +// Code generated by gorm.io/gen. DO NOT EDIT. +// Code generated by gorm.io/gen. DO NOT EDIT. +// Code generated by gorm.io/gen. DO NOT EDIT. + +package model + +import ( + "time" +) + +const TableNameShippingRecords = "shipping_records" + +// ShippingRecords 发货记录(合并:单表) +type ShippingRecords struct { + ID int64 `gorm:"column:id;primaryKey;autoIncrement:true;comment:主键ID" json:"id"` // 主键ID + CreatedAt time.Time `gorm:"column:created_at;not null;default:CURRENT_TIMESTAMP(3);comment:创建时间" json:"created_at"` // 创建时间 + UpdatedAt time.Time `gorm:"column:updated_at;not null;default:CURRENT_TIMESTAMP(3);comment:更新时间" json:"updated_at"` // 更新时间 + UserID int64 `gorm:"column:user_id;not null;comment:收件用户ID(user_members.id)" json:"user_id"` // 收件用户ID(user_members.id) + OrderID int64 `gorm:"column:order_id;comment:关联订单ID(orders.id,抽奖产物可为空)" json:"order_id"` // 关联订单ID(orders.id,抽奖产物可为空) + OrderItemID int64 `gorm:"column:order_item_id;comment:订单行ID(商城直发时使用)" json:"order_item_id"` // 订单行ID(商城直发时使用) + InventoryID int64 `gorm:"column:inventory_id;comment:资产ID(抽奖产物发货时使用)" json:"inventory_id"` // 资产ID(抽奖产物发货时使用) + ProductID int64 `gorm:"column:product_id;comment:商品ID(统计/冗余)" json:"product_id"` // 商品ID(统计/冗余) + Quantity int64 `gorm:"column:quantity;not null;default:1;comment:发货数量" json:"quantity"` // 发货数量 + Price int64 `gorm:"column:price;comment:行价格(分,可选)" json:"price"` // 行价格(分,可选) + AddressID int64 `gorm:"column:address_id;comment:收货地址ID(user_addresses.id)" json:"address_id"` // 收货地址ID(user_addresses.id) + Status int32 `gorm:"column:status;not null;default:1;comment:发货状态:1待发货 2已发货 3已签收 4异常" json:"status"` // 发货状态:1待发货 2已发货 3已签收 4异常 + ExpressCode string `gorm:"column:express_code;comment:快递公司编码" json:"express_code"` // 快递公司编码 + ExpressNo string `gorm:"column:express_no;comment:运单号" json:"express_no"` // 运单号 + ShippedAt time.Time `gorm:"column:shipped_at;comment:发货时间" json:"shipped_at"` // 发货时间 + ReceivedAt time.Time `gorm:"column:received_at;comment:签收时间" json:"received_at"` // 签收时间 + Remark string `gorm:"column:remark;comment:备注" json:"remark"` // 备注 +} + +// TableName ShippingRecords's table name +func (*ShippingRecords) TableName() string { + return TableNameShippingRecords +} diff --git a/internal/repository/mysql/model/system_coupons.gen.go b/internal/repository/mysql/model/system_coupons.gen.go new file mode 100644 index 0000000..db9ca27 --- /dev/null +++ b/internal/repository/mysql/model/system_coupons.gen.go @@ -0,0 +1,33 @@ +// Code generated by gorm.io/gen. DO NOT EDIT. +// Code generated by gorm.io/gen. DO NOT EDIT. +// Code generated by gorm.io/gen. DO NOT EDIT. + +package model + +import ( + "time" +) + +const TableNameSystemCoupons = "system_coupons" + +// SystemCoupons 优惠券模板 +type SystemCoupons struct { + ID int64 `gorm:"column:id;primaryKey;autoIncrement:true;comment:主键ID" json:"id"` // 主键ID + CreatedAt time.Time `gorm:"column:created_at;not null;default:CURRENT_TIMESTAMP(3);comment:创建时间" json:"created_at"` // 创建时间 + UpdatedAt time.Time `gorm:"column:updated_at;not null;default:CURRENT_TIMESTAMP(3);comment:更新时间" json:"updated_at"` // 更新时间 + Name string `gorm:"column:name;not null;comment:券名称" json:"name"` // 券名称 + ScopeType int32 `gorm:"column:scope_type;not null;default:1;comment:适用范围:1全局 2活动 3商品" json:"scope_type"` // 适用范围:1全局 2活动 3商品 + ActivityID int64 `gorm:"column:activity_id;comment:指定活动ID(可空)" json:"activity_id"` // 指定活动ID(可空) + ProductID int64 `gorm:"column:product_id;comment:指定商品ID(可空)" json:"product_id"` // 指定商品ID(可空) + DiscountType int32 `gorm:"column:discount_type;not null;default:1;comment:优惠类型:1直减 2满减 3折扣" json:"discount_type"` // 优惠类型:1直减 2满减 3折扣 + DiscountValue int64 `gorm:"column:discount_value;not null;comment:优惠面值(直减/满减为分;折扣为千分比)" json:"discount_value"` // 优惠面值(直减/满减为分;折扣为千分比) + MinSpend int64 `gorm:"column:min_spend;not null;comment:使用门槛金额(分)" json:"min_spend"` // 使用门槛金额(分) + ValidStart time.Time `gorm:"column:valid_start;comment:有效期开始" json:"valid_start"` // 有效期开始 + ValidEnd time.Time `gorm:"column:valid_end;comment:有效期结束" json:"valid_end"` // 有效期结束 + Status int32 `gorm:"column:status;not null;default:1;comment:状态:1启用 2停用" json:"status"` // 状态:1启用 2停用 +} + +// TableName SystemCoupons's table name +func (*SystemCoupons) TableName() string { + return TableNameSystemCoupons +} diff --git a/internal/repository/mysql/model/system_item_cards.gen.go b/internal/repository/mysql/model/system_item_cards.gen.go new file mode 100644 index 0000000..66eab91 --- /dev/null +++ b/internal/repository/mysql/model/system_item_cards.gen.go @@ -0,0 +1,39 @@ +// Code generated by gorm.io/gen. DO NOT EDIT. +// Code generated by gorm.io/gen. DO NOT EDIT. +// Code generated by gorm.io/gen. DO NOT EDIT. + +package model + +import ( + "time" +) + +const TableNameSystemItemCards = "system_item_cards" + +// SystemItemCards 道具卡模板 +type SystemItemCards struct { + ID int64 `gorm:"column:id;primaryKey;autoIncrement:true;comment:主键ID" json:"id"` // 主键ID + CreatedAt time.Time `gorm:"column:created_at;not null;default:CURRENT_TIMESTAMP(3);comment:创建时间" json:"created_at"` // 创建时间 + UpdatedAt time.Time `gorm:"column:updated_at;not null;default:CURRENT_TIMESTAMP(3);comment:更新时间" json:"updated_at"` // 更新时间 + Name string `gorm:"column:name;not null;comment:卡名称" json:"name"` // 卡名称 + Status int32 `gorm:"column:status;not null;default:1;comment:状态:1启用 2停用" json:"status"` // 状态:1启用 2停用 + CardType int32 `gorm:"column:card_type;not null;comment:卡类型:1双倍奖励 2概率提升 等" json:"card_type"` // 卡类型:1双倍奖励 2概率提升 等 + ScopeType int32 `gorm:"column:scope_type;not null;default:1;comment:适用范围:1全局 2活动分类 3活动 4期" json:"scope_type"` // 适用范围:1全局 2活动分类 3活动 4期 + ActivityCategoryID int64 `gorm:"column:activity_category_id;comment:指定活动分类ID(可空)" json:"activity_category_id"` // 指定活动分类ID(可空) + ActivityID int64 `gorm:"column:activity_id;comment:指定活动ID(可空)" json:"activity_id"` // 指定活动ID(可空) + IssueID int64 `gorm:"column:issue_id;comment:指定期ID(可空)" json:"issue_id"` // 指定期ID(可空) + Price int64 `gorm:"column:price;not null;comment:售卖价格(分)" json:"price"` // 售卖价格(分) + ValidStart time.Time `gorm:"column:valid_start;comment:有效期开始" json:"valid_start"` // 有效期开始 + ValidEnd time.Time `gorm:"column:valid_end;comment:有效期结束" json:"valid_end"` // 有效期结束 + EffectType int32 `gorm:"column:effect_type;not null;comment:效果类型:1奖励倍数 2概率提升 等" json:"effect_type"` // 效果类型:1奖励倍数 2概率提升 等 + RewardMultiplierX1000 int32 `gorm:"column:reward_multiplier_x1000;not null;comment:奖励倍数(千分比,×2=2000)" json:"reward_multiplier_x1000"` // 奖励倍数(千分比,×2=2000) + BoostRateX1000 int32 `gorm:"column:boost_rate_x1000;not null;comment:概率提升(千分比,+20%=200)" json:"boost_rate_x1000"` // 概率提升(千分比,+20%=200) + StackingStrategy int32 `gorm:"column:stacking_strategy;not null;default:1;comment:叠加策略:1禁止 2同类叠加-上限 3取最大值 4乘法叠加" json:"stacking_strategy"` // 叠加策略:1禁止 2同类叠加-上限 3取最大值 4乘法叠加 + MaxEffectValueX1000 int32 `gorm:"column:max_effect_value_x1000;not null;comment:效果上限(千分比)" json:"max_effect_value_x1000"` // 效果上限(千分比) + Remark string `gorm:"column:remark;comment:备注" json:"remark"` // 备注 +} + +// TableName SystemItemCards's table name +func (*SystemItemCards) TableName() string { + return TableNameSystemItemCards +} diff --git a/internal/repository/mysql/model/user_addresses.gen.go b/internal/repository/mysql/model/user_addresses.gen.go new file mode 100644 index 0000000..4fa0391 --- /dev/null +++ b/internal/repository/mysql/model/user_addresses.gen.go @@ -0,0 +1,32 @@ +// Code generated by gorm.io/gen. DO NOT EDIT. +// Code generated by gorm.io/gen. DO NOT EDIT. +// Code generated by gorm.io/gen. DO NOT EDIT. + +package model + +import ( + "time" +) + +const TableNameUserAddresses = "user_addresses" + +// UserAddresses 用户地址 +type UserAddresses struct { + ID int64 `gorm:"column:id;primaryKey;autoIncrement:true;comment:主键ID" json:"id"` // 主键ID + CreatedAt time.Time `gorm:"column:created_at;not null;default:CURRENT_TIMESTAMP(3);comment:创建时间" json:"created_at"` // 创建时间 + UpdatedAt time.Time `gorm:"column:updated_at;not null;default:CURRENT_TIMESTAMP(3);comment:更新时间" json:"updated_at"` // 更新时间 + UserID int64 `gorm:"column:user_id;not null;comment:用户ID(user_members.id)" json:"user_id"` // 用户ID(user_members.id) + Name string `gorm:"column:name;not null;comment:收件人姓名" json:"name"` // 收件人姓名 + Mobile string `gorm:"column:mobile;not null;comment:收件人手机号" json:"mobile"` // 收件人手机号 + Province string `gorm:"column:province;not null;comment:省" json:"province"` // 省 + City string `gorm:"column:city;not null;comment:市" json:"city"` // 市 + District string `gorm:"column:district;not null;comment:区/县" json:"district"` // 区/县 + Address string `gorm:"column:address;not null;comment:详细地址" json:"address"` // 详细地址 + IsDefault int32 `gorm:"column:is_default;not null;comment:是否默认地址:0否 1是" json:"is_default"` // 是否默认地址:0否 1是 + DefaultUserUnique int64 `gorm:"column:default_user_unique;comment:用于唯一约束的生成列:默认地址→user_id" json:"default_user_unique"` // 用于唯一约束的生成列:默认地址→user_id +} + +// TableName UserAddresses's table name +func (*UserAddresses) TableName() string { + return TableNameUserAddresses +} diff --git a/internal/repository/mysql/model/user_coupons.gen.go b/internal/repository/mysql/model/user_coupons.gen.go new file mode 100644 index 0000000..abef6c8 --- /dev/null +++ b/internal/repository/mysql/model/user_coupons.gen.go @@ -0,0 +1,30 @@ +// Code generated by gorm.io/gen. DO NOT EDIT. +// Code generated by gorm.io/gen. DO NOT EDIT. +// Code generated by gorm.io/gen. DO NOT EDIT. + +package model + +import ( + "time" +) + +const TableNameUserCoupons = "user_coupons" + +// UserCoupons 用户持券 +type UserCoupons struct { + ID int64 `gorm:"column:id;primaryKey;autoIncrement:true;comment:主键ID" json:"id"` // 主键ID + CreatedAt time.Time `gorm:"column:created_at;not null;default:CURRENT_TIMESTAMP(3);comment:创建时间" json:"created_at"` // 创建时间 + UpdatedAt time.Time `gorm:"column:updated_at;not null;default:CURRENT_TIMESTAMP(3);comment:更新时间" json:"updated_at"` // 更新时间 + UserID int64 `gorm:"column:user_id;not null;comment:用户ID(user_members.id)" json:"user_id"` // 用户ID(user_members.id) + CouponID int64 `gorm:"column:coupon_id;not null;comment:券模板ID(system_coupons.id)" json:"coupon_id"` // 券模板ID(system_coupons.id) + UsedOrderID int64 `gorm:"column:used_order_id;comment:核销的订单ID(orders.id)" json:"used_order_id"` // 核销的订单ID(orders.id) + UsedAt time.Time `gorm:"column:used_at;comment:核销时间" json:"used_at"` // 核销时间 + ValidStart time.Time `gorm:"column:valid_start;comment:有效期开始" json:"valid_start"` // 有效期开始 + ValidEnd time.Time `gorm:"column:valid_end;comment:有效期结束" json:"valid_end"` // 有效期结束 + Status int32 `gorm:"column:status;not null;default:1;comment:状态:1未使用 2已使用 3已过期" json:"status"` // 状态:1未使用 2已使用 3已过期 +} + +// TableName UserCoupons's table name +func (*UserCoupons) TableName() string { + return TableNameUserCoupons +} diff --git a/internal/repository/mysql/model/user_inventory.gen.go b/internal/repository/mysql/model/user_inventory.gen.go new file mode 100644 index 0000000..9f0402b --- /dev/null +++ b/internal/repository/mysql/model/user_inventory.gen.go @@ -0,0 +1,30 @@ +// Code generated by gorm.io/gen. DO NOT EDIT. +// Code generated by gorm.io/gen. DO NOT EDIT. +// Code generated by gorm.io/gen. DO NOT EDIT. + +package model + +import ( + "time" +) + +const TableNameUserInventory = "user_inventory" + +// UserInventory 用户资产(资产) +type UserInventory struct { + ID int64 `gorm:"column:id;primaryKey;autoIncrement:true;comment:主键ID" json:"id"` // 主键ID + CreatedAt time.Time `gorm:"column:created_at;not null;default:CURRENT_TIMESTAMP(3);comment:创建时间" json:"created_at"` // 创建时间 + UpdatedAt time.Time `gorm:"column:updated_at;not null;default:CURRENT_TIMESTAMP(3);comment:更新时间" json:"updated_at"` // 更新时间 + UserID int64 `gorm:"column:user_id;not null;comment:资产归属用户ID" json:"user_id"` // 资产归属用户ID + ProductID int64 `gorm:"column:product_id;comment:资产对应商品ID(实物奖/商品)" json:"product_id"` // 资产对应商品ID(实物奖/商品) + OrderID int64 `gorm:"column:order_id;comment:来源订单ID" json:"order_id"` // 来源订单ID + ActivityID int64 `gorm:"column:activity_id;comment:来源活动ID" json:"activity_id"` // 来源活动ID + RewardID int64 `gorm:"column:reward_id;comment:来源奖励ID(activity_reward_settings.id)" json:"reward_id"` // 来源奖励ID(activity_reward_settings.id) + Status int32 `gorm:"column:status;not null;default:1;comment:状态:1持有 2作废 3已使用/发货" json:"status"` // 状态:1持有 2作废 3已使用/发货 + Remark string `gorm:"column:remark;comment:备注" json:"remark"` // 备注 +} + +// TableName UserInventory's table name +func (*UserInventory) TableName() string { + return TableNameUserInventory +} diff --git a/internal/repository/mysql/model/user_inventory_transfers.gen.go b/internal/repository/mysql/model/user_inventory_transfers.gen.go new file mode 100644 index 0000000..ca73ad8 --- /dev/null +++ b/internal/repository/mysql/model/user_inventory_transfers.gen.go @@ -0,0 +1,26 @@ +// Code generated by gorm.io/gen. DO NOT EDIT. +// Code generated by gorm.io/gen. DO NOT EDIT. +// Code generated by gorm.io/gen. DO NOT EDIT. + +package model + +import ( + "time" +) + +const TableNameUserInventoryTransfers = "user_inventory_transfers" + +// UserInventoryTransfers 资产转赠流水 +type UserInventoryTransfers struct { + ID int64 `gorm:"column:id;primaryKey;autoIncrement:true;comment:主键ID" json:"id"` // 主键ID + CreatedAt time.Time `gorm:"column:created_at;not null;default:CURRENT_TIMESTAMP(3);comment:创建时间" json:"created_at"` // 创建时间 + InventoryID int64 `gorm:"column:inventory_id;not null;comment:资产ID(user_inventory.id)" json:"inventory_id"` // 资产ID(user_inventory.id) + FromUserID int64 `gorm:"column:from_user_id;not null;comment:转出用户ID" json:"from_user_id"` // 转出用户ID + ToUserID int64 `gorm:"column:to_user_id;not null;comment:转入用户ID" json:"to_user_id"` // 转入用户ID + Remark string `gorm:"column:remark;comment:备注" json:"remark"` // 备注 +} + +// TableName UserInventoryTransfers's table name +func (*UserInventoryTransfers) TableName() string { + return TableNameUserInventoryTransfers +} diff --git a/internal/repository/mysql/model/user_invites.gen.go b/internal/repository/mysql/model/user_invites.gen.go new file mode 100644 index 0000000..b7c0ee8 --- /dev/null +++ b/internal/repository/mysql/model/user_invites.gen.go @@ -0,0 +1,31 @@ +// Code generated by gorm.io/gen. DO NOT EDIT. +// Code generated by gorm.io/gen. DO NOT EDIT. +// Code generated by gorm.io/gen. DO NOT EDIT. + +package model + +import ( + "time" + + "gorm.io/gorm" +) + +const TableNameUserInvites = "user_invites" + +// UserInvites 用户邀请关系表 +type UserInvites struct { + ID int64 `gorm:"column:id;primaryKey;autoIncrement:true;comment:主键ID" json:"id"` // 主键ID + InviterID int64 `gorm:"column:inviter_id;not null;comment:邀请人用户ID" json:"inviter_id"` // 邀请人用户ID + InviteeID int64 `gorm:"column:invitee_id;not null;comment:被邀请用户ID" json:"invitee_id"` // 被邀请用户ID + InviteCode string `gorm:"column:invite_code;not null;comment:邀请时使用的邀请码" json:"invite_code"` // 邀请时使用的邀请码 + RewardPoints int64 `gorm:"column:reward_points;not null;comment:发放的积分数量(用于审计)" json:"reward_points"` // 发放的积分数量(用于审计) + RewardedAt time.Time `gorm:"column:rewarded_at;comment:奖励发放时间" json:"rewarded_at"` // 奖励发放时间 + CreatedAt time.Time `gorm:"column:created_at;not null;default:CURRENT_TIMESTAMP(3);comment:创建时间" json:"created_at"` // 创建时间 + UpdatedAt time.Time `gorm:"column:updated_at;not null;default:CURRENT_TIMESTAMP(3);comment:更新时间" json:"updated_at"` // 更新时间 + DeletedAt gorm.DeletedAt `gorm:"column:deleted_at;comment:删除时间(软删)" json:"deleted_at"` // 删除时间(软删) +} + +// TableName UserInvites's table name +func (*UserInvites) TableName() string { + return TableNameUserInvites +} diff --git a/internal/repository/mysql/model/user_item_cards.gen.go b/internal/repository/mysql/model/user_item_cards.gen.go new file mode 100644 index 0000000..651d4bd --- /dev/null +++ b/internal/repository/mysql/model/user_item_cards.gen.go @@ -0,0 +1,33 @@ +// Code generated by gorm.io/gen. DO NOT EDIT. +// Code generated by gorm.io/gen. DO NOT EDIT. +// Code generated by gorm.io/gen. DO NOT EDIT. + +package model + +import ( + "time" +) + +const TableNameUserItemCards = "user_item_cards" + +// UserItemCards 用户持有道具卡 +type UserItemCards struct { + ID int64 `gorm:"column:id;primaryKey;autoIncrement:true;comment:主键ID" json:"id"` // 主键ID + CreatedAt time.Time `gorm:"column:created_at;not null;default:CURRENT_TIMESTAMP(3);comment:创建时间" json:"created_at"` // 创建时间 + UpdatedAt time.Time `gorm:"column:updated_at;not null;default:CURRENT_TIMESTAMP(3);comment:更新时间" json:"updated_at"` // 更新时间 + UserID int64 `gorm:"column:user_id;not null;comment:用户ID(users.id)" json:"user_id"` // 用户ID(users.id) + CardID int64 `gorm:"column:card_id;not null;comment:卡模板ID(system_item_cards.id)" json:"card_id"` // 卡模板ID(system_item_cards.id) + ValidStart time.Time `gorm:"column:valid_start;comment:有效期开始" json:"valid_start"` // 有效期开始 + ValidEnd time.Time `gorm:"column:valid_end;comment:有效期结束" json:"valid_end"` // 有效期结束 + Status int32 `gorm:"column:status;not null;default:1;comment:状态:1未使用 2已使用 3已过期" json:"status"` // 状态:1未使用 2已使用 3已过期 + UsedDrawLogID int64 `gorm:"column:used_draw_log_id;comment:使用关联抽奖日志ID(activity_draw_logs.id)" json:"used_draw_log_id"` // 使用关联抽奖日志ID(activity_draw_logs.id) + UsedActivityID int64 `gorm:"column:used_activity_id;comment:使用时活动ID" json:"used_activity_id"` // 使用时活动ID + UsedIssueID int64 `gorm:"column:used_issue_id;comment:使用时期ID" json:"used_issue_id"` // 使用时期ID + UsedAt time.Time `gorm:"column:used_at;comment:使用时间" json:"used_at"` // 使用时间 + Remark string `gorm:"column:remark;comment:备注" json:"remark"` // 备注 +} + +// TableName UserItemCards's table name +func (*UserItemCards) TableName() string { + return TableNameUserItemCards +} diff --git a/internal/repository/mysql/model/user_points.gen.go b/internal/repository/mysql/model/user_points.gen.go new file mode 100644 index 0000000..330e23d --- /dev/null +++ b/internal/repository/mysql/model/user_points.gen.go @@ -0,0 +1,29 @@ +// Code generated by gorm.io/gen. DO NOT EDIT. +// Code generated by gorm.io/gen. DO NOT EDIT. +// Code generated by gorm.io/gen. DO NOT EDIT. + +package model + +import ( + "time" +) + +const TableNameUserPoints = "user_points" + +// UserPoints 用户积分(余额表) +type UserPoints struct { + ID int64 `gorm:"column:id;primaryKey;autoIncrement:true;comment:主键ID" json:"id"` // 主键ID + CreatedAt time.Time `gorm:"column:created_at;not null;default:CURRENT_TIMESTAMP(3);comment:创建时间" json:"created_at"` // 创建时间 + UpdatedAt time.Time `gorm:"column:updated_at;not null;default:CURRENT_TIMESTAMP(3);comment:更新时间" json:"updated_at"` // 更新时间 + UserID int64 `gorm:"column:user_id;not null;comment:用户ID(" json:"user_id"` // 用户ID( + Kind string `gorm:"column:kind;not null;comment:积分类别:signin、task、exchange等" json:"kind"` // 积分类别:signin、task、exchange等 + Points int64 `gorm:"column:points;not null;comment:积分值(整数点)" json:"points"` // 积分值(整数点) + ValidStart time.Time `gorm:"column:valid_start;comment:有效期开始(用于每日一次等约束)" json:"valid_start"` // 有效期开始(用于每日一次等约束) + ValidEnd time.Time `gorm:"column:valid_end;comment:有效期结束" json:"valid_end"` // 有效期结束 + Version int32 `gorm:"column:version;not null;comment:乐观锁版本号" json:"version"` // 乐观锁版本号 +} + +// TableName UserPoints's table name +func (*UserPoints) TableName() string { + return TableNameUserPoints +} diff --git a/internal/repository/mysql/model/user_points_ledger.gen.go b/internal/repository/mysql/model/user_points_ledger.gen.go new file mode 100644 index 0000000..2b83cde --- /dev/null +++ b/internal/repository/mysql/model/user_points_ledger.gen.go @@ -0,0 +1,28 @@ +// Code generated by gorm.io/gen. DO NOT EDIT. +// Code generated by gorm.io/gen. DO NOT EDIT. +// Code generated by gorm.io/gen. DO NOT EDIT. + +package model + +import ( + "time" +) + +const TableNameUserPointsLedger = "user_points_ledger" + +// UserPointsLedger 用户积分流水(总账) +type UserPointsLedger struct { + ID int64 `gorm:"column:id;primaryKey;autoIncrement:true;comment:主键ID" json:"id"` // 主键ID + CreatedAt time.Time `gorm:"column:created_at;not null;default:CURRENT_TIMESTAMP(3);comment:创建时间" json:"created_at"` // 创建时间 + UserID int64 `gorm:"column:user_id;not null;comment:用户ID(user_members.id)" json:"user_id"` // 用户ID(user_members.id) + Action string `gorm:"column:action;not null;comment:变更动作:signin/order_deduct/refund_restore/manual" json:"action"` // 变更动作:signin/order_deduct/refund_restore/manual + Points int64 `gorm:"column:points;not null;comment:积分变动值(正增负减)" json:"points"` // 积分变动值(正增负减) + RefTable string `gorm:"column:ref_table;comment:关联表名(如orders/payment_refund)" json:"ref_table"` // 关联表名(如orders/payment_refund) + RefID string `gorm:"column:ref_id;comment:关联ID(如订单号/记录ID)" json:"ref_id"` // 关联ID(如订单号/记录ID) + Remark string `gorm:"column:remark;comment:备注" json:"remark"` // 备注 +} + +// TableName UserPointsLedger's table name +func (*UserPointsLedger) TableName() string { + return TableNameUserPointsLedger +} diff --git a/internal/repository/mysql/model/users.gen.go b/internal/repository/mysql/model/users.gen.go new file mode 100644 index 0000000..0fd988b --- /dev/null +++ b/internal/repository/mysql/model/users.gen.go @@ -0,0 +1,34 @@ +// Code generated by gorm.io/gen. DO NOT EDIT. +// Code generated by gorm.io/gen. DO NOT EDIT. +// Code generated by gorm.io/gen. DO NOT EDIT. + +package model + +import ( + "time" + + "gorm.io/gorm" +) + +const TableNameUsers = "users" + +// Users 用户表 +type Users struct { + ID int64 `gorm:"column:id;primaryKey;autoIncrement:true;comment:主键ID" json:"id"` // 主键ID + CreatedAt time.Time `gorm:"column:created_at;not null;default:CURRENT_TIMESTAMP(3);comment:创建时间" json:"created_at"` // 创建时间 + UpdatedAt time.Time `gorm:"column:updated_at;not null;default:CURRENT_TIMESTAMP(3);comment:更新时间" json:"updated_at"` // 更新时间 + DeletedAt gorm.DeletedAt `gorm:"column:deleted_at;comment:删除时间(软删)" json:"deleted_at"` // 删除时间(软删) + Nickname string `gorm:"column:nickname;not null;comment:昵称" json:"nickname"` // 昵称 + Avatar string `gorm:"column:avatar;comment:头像URL" json:"avatar"` // 头像URL + Mobile string `gorm:"column:mobile;comment:手机号" json:"mobile"` // 手机号 + Openid string `gorm:"column:openid;comment:微信openid" json:"openid"` // 微信openid + Unionid string `gorm:"column:unionid;comment:微信unionid" json:"unionid"` // 微信unionid + InviteCode string `gorm:"column:invite_code;not null;comment:用户唯一邀请码" json:"invite_code"` // 用户唯一邀请码 + InviterID int64 `gorm:"column:inviter_id;comment:邀请人用户ID" json:"inviter_id"` // 邀请人用户ID + Status int32 `gorm:"column:status;not null;default:1;comment:状态:1正常 2禁用" json:"status"` // 状态:1正常 2禁用 +} + +// TableName Users's table name +func (*Users) TableName() string { + return TableNameUsers +} diff --git a/internal/repository/mysql/mysql.go b/internal/repository/mysql/mysql.go index 83db938..6c074dd 100644 --- a/internal/repository/mysql/mysql.go +++ b/internal/repository/mysql/mysql.go @@ -6,8 +6,8 @@ import ( "os" "time" - "mini-chat/configs" - "mini-chat/internal/pkg/errors" + "bindbox-game/configs" + "bindbox-game/internal/pkg/errors" "gorm.io/driver/mysql" "gorm.io/gorm" diff --git a/internal/repository/mysql/plugin.go b/internal/repository/mysql/plugin.go index 3362e9b..9c3f865 100644 --- a/internal/repository/mysql/plugin.go +++ b/internal/repository/mysql/plugin.go @@ -3,9 +3,9 @@ package mysql import ( "time" - "mini-chat/internal/pkg/core" - "mini-chat/internal/pkg/timeutil" - "mini-chat/internal/pkg/trace" + "bindbox-game/internal/pkg/core" + "bindbox-game/internal/pkg/timeutil" + "bindbox-game/internal/pkg/trace" "gorm.io/gorm" "gorm.io/gorm/utils" diff --git a/internal/router/interceptor/admin_auth.go b/internal/router/interceptor/admin_auth.go index 3014b3a..c026f86 100644 --- a/internal/router/interceptor/admin_auth.go +++ b/internal/router/interceptor/admin_auth.go @@ -3,13 +3,13 @@ package interceptor import ( "net/http" - "mini-chat/configs" - "mini-chat/internal/code" - "mini-chat/internal/pkg/core" - "mini-chat/internal/pkg/jwtoken" - "mini-chat/internal/pkg/utils" - "mini-chat/internal/proposal" - "mini-chat/internal/repository/mysql/dao" + "bindbox-game/configs" + "bindbox-game/internal/code" + "bindbox-game/internal/pkg/core" + "bindbox-game/internal/pkg/jwtoken" + "bindbox-game/internal/pkg/utils" + "bindbox-game/internal/proposal" + "bindbox-game/internal/repository/mysql/dao" "gorm.io/gorm" ) diff --git a/internal/router/interceptor/interceptor.go b/internal/router/interceptor/interceptor.go index d804e10..125207e 100644 --- a/internal/router/interceptor/interceptor.go +++ b/internal/router/interceptor/interceptor.go @@ -1,10 +1,10 @@ package interceptor import ( - "mini-chat/internal/pkg/core" - "mini-chat/internal/pkg/logger" - "mini-chat/internal/proposal" - "mini-chat/internal/repository/mysql" + "bindbox-game/internal/pkg/core" + "bindbox-game/internal/pkg/logger" + "bindbox-game/internal/proposal" + "bindbox-game/internal/repository/mysql" ) var _ Interceptor = (*interceptor)(nil) diff --git a/internal/router/router.go b/internal/router/router.go index d129b56..b0b1be6 100644 --- a/internal/router/router.go +++ b/internal/router/router.go @@ -1,25 +1,24 @@ package router import ( - "mini-chat/internal/alert" - "mini-chat/internal/api/admin" - "mini-chat/internal/api/app" - "mini-chat/internal/api/keyword" - "mini-chat/internal/api/message" - "mini-chat/internal/api/upload" - "mini-chat/internal/api/wechat" - "mini-chat/internal/cron" - "mini-chat/internal/dblogger" - "mini-chat/internal/pkg/core" - "mini-chat/internal/pkg/logger" - "mini-chat/internal/pkg/startup" - "mini-chat/internal/repository/mysql" - "mini-chat/internal/router/interceptor" + "bindbox-game/internal/alert" + activityapi "bindbox-game/internal/api/activity" + "bindbox-game/internal/api/admin" + commonapi "bindbox-game/internal/api/common" + appapi "bindbox-game/internal/api/app" + guildapi "bindbox-game/internal/api/guild" + userapi "bindbox-game/internal/api/user" + "bindbox-game/internal/dblogger" + "bindbox-game/internal/pkg/core" + "bindbox-game/internal/pkg/logger" + "bindbox-game/internal/pkg/startup" + "bindbox-game/internal/repository/mysql" + "bindbox-game/internal/router/interceptor" "github.com/pkg/errors" ) -func NewHTTPMux(logger logger.CustomLogger, db mysql.Repo, cron cron.Server) (core.Mux, error) { +func NewHTTPMux(logger logger.CustomLogger, db mysql.Repo) (core.Mux, error) { if logger == nil { return nil, errors.New("logger required") } @@ -41,14 +40,12 @@ func NewHTTPMux(logger logger.CustomLogger, db mysql.Repo, cron cron.Server) (co } // 实例化拦截器 - interceptorHandler := interceptor.New(logger, db) - adminHandler := admin.New(logger, db) - appHandler := app.New(logger, db) - uploadHandler := upload.New(logger, db) - keywordHandler := keyword.New(logger, db) - messageHandler := message.New(logger, db) - wechatHandler := wechat.New(logger, db) + activityHandler := activityapi.New(logger, db) + guildHandler := guildapi.New(logger, db) + userHandler := userapi.New(logger, db) + commonHandler := commonapi.New(logger, db) + intc := interceptor.New(logger, db) // 管理端非认证接口路由组 adminNonAuthApiRouter := mux.Group("/api/admin") @@ -57,53 +54,132 @@ func NewHTTPMux(logger logger.CustomLogger, db mysql.Repo, cron cron.Server) (co ctx.Payload(startup.Info()) }) - adminNonAuthApiRouter.POST("/login", adminHandler.Login()) // 登录 - adminNonAuthApiRouter.POST("/upload/image", uploadHandler.UploadImage()) // 上传图片 - } - - appNonAuthApiRouter := mux.Group("/api/app") - { - appNonAuthApiRouter.POST("/user/create", appHandler.CreateAppUser()) // 新增小程序用户 - appNonAuthApiRouter.GET("/messages", messageHandler.AppMessagePageList()) // 消息列表 - appNonAuthApiRouter.POST("/send_message", messageHandler.UserSendMessage()) // 发送消息 - } - - // 微信 API 路由组 - wechatApiRouter := mux.Group("/api/wechat") - { - wechatApiRouter.POST("/qrcode", wechatHandler.GenerateQRCode()) // 生成微信小程序二维码(返回 Base64) - wechatApiRouter.POST("/miniprogram/login", wechatHandler.MiniprogramLogin()) // 小程序登录 - wechatApiRouter.POST("/template", wechatHandler.GetTemplate()) // 生成微信小程序模板消息 - wechatApiRouter.POST("/subscribe", wechatHandler.SendSubscribeMessage()) // 发送订阅消息 + adminNonAuthApiRouter.POST("/login", adminHandler.Login()) // 登录 } // 管理端认证接口路由组 - adminAuthApiRouter := mux.Group("/api/admin", core.WrapAuthHandler(interceptorHandler.AdminTokenAuthVerify)) + adminAuthApiRouter := mux.Group("/api/admin", core.WrapAuthHandler(intc.AdminTokenAuthVerify)) + + // 系统管理接口(为前端模板路径兼容,挂载到 /api) + systemApiRouter := mux.Group("/api", core.WrapAuthHandler(intc.AdminTokenAuthVerify)) { - adminAuthApiRouter.POST("/app/create", appHandler.CreateApp()) // 关联小程序 - adminAuthApiRouter.POST("/app/delete", appHandler.DeleteApp()) // 删除小程序 - adminAuthApiRouter.PUT("/app/:id", appHandler.ModifyApp()) // 修改小程序 - adminAuthApiRouter.GET("/apps", appHandler.PageList()) // 小程序列表 - adminAuthApiRouter.GET("/app/check_status", appHandler.CheckAppStatus()) // 检查小程序状态 + adminAuthApiRouter.POST("/create", adminHandler.CreateAdmin()) + adminAuthApiRouter.PUT("/:id", adminHandler.ModifyAdmin()) + adminAuthApiRouter.POST("/delete", adminHandler.DeleteAdmin()) + adminAuthApiRouter.GET("/list", adminHandler.PageList()) - adminAuthApiRouter.POST("/create", adminHandler.CreateAdmin()) // 新增客服 - adminAuthApiRouter.POST("/delete", adminHandler.DeleteAdmin()) // 删除客服 - adminAuthApiRouter.PUT("/:id", adminHandler.ModifyAdmin()) // 编辑客服 - adminAuthApiRouter.GET("/list", adminHandler.PageList()) // 客服列表 - adminAuthApiRouter.PUT("/rel_app/:id", adminHandler.RelApp()) // 关联小程序 + adminAuthApiRouter.GET("/activity_categories", adminHandler.ListActivityCategories()) + adminAuthApiRouter.POST("/activities", adminHandler.CreateActivity()) + adminAuthApiRouter.PUT("/activities/:activity_id", adminHandler.ModifyActivity()) + adminAuthApiRouter.DELETE("/activities/:activity_id", adminHandler.DeleteActivity()) + adminAuthApiRouter.GET("/activities/:activity_id", adminHandler.GetActivityDetail()) + adminAuthApiRouter.GET("/activities/:activity_id/issues", adminHandler.ListActivityIssues()) + adminAuthApiRouter.POST("/activities/:activity_id/issues", adminHandler.CreateActivityIssue()) + adminAuthApiRouter.PUT("/activities/:activity_id/issues/:issue_id", adminHandler.ModifyActivityIssue()) + adminAuthApiRouter.DELETE("/activities/:activity_id/issues/:issue_id", adminHandler.DeleteActivityIssue()) + adminAuthApiRouter.POST("/activities/:activity_id/issues/:issue_id/rewards", adminHandler.CreateIssueRewards()) + adminAuthApiRouter.GET("/activities/:activity_id/issues/:issue_id/rewards", adminHandler.ListIssueRewards()) + adminAuthApiRouter.PUT("/activities/:activity_id/issues/:issue_id/rewards/:reward_id", adminHandler.ModifyIssueReward()) + adminAuthApiRouter.DELETE("/activities/:activity_id/issues/:issue_id/rewards/:reward_id", adminHandler.DeleteIssueReward()) - adminAuthApiRouter.POST("/app/keyword", keywordHandler.CreateKeyword()) // 添加意图关键字 - adminAuthApiRouter.PUT("/app/keyword/:id", keywordHandler.ModifyKeyword()) // 修改意图关键字 - adminAuthApiRouter.DELETE("/app/keyword/:id", keywordHandler.DeleteKeyword()) // 删除意图关键字 - adminAuthApiRouter.GET("/app/keywords", keywordHandler.KeywordPageList()) // 获取意图关键字列表 - adminAuthApiRouter.POST("/app/keyword/material/:id", keywordHandler.CreateKeywordMaterial()) // 配置意图关键字素材 - adminAuthApiRouter.PUT("/app/keyword/material/:id", keywordHandler.ModifyKeywordMaterial()) // 修改意图关键字素材 - adminAuthApiRouter.GET("/app/keyword/materials", keywordHandler.KeywordMaterialPageList()) // 获取意图关键字素材列表 + adminAuthApiRouter.POST("/guilds", adminHandler.CreateGuild()) + adminAuthApiRouter.PUT("/guilds/:guild_id", adminHandler.ModifyGuild()) + adminAuthApiRouter.DELETE("/guilds/:guild_id", adminHandler.DeleteGuild()) + adminAuthApiRouter.GET("/guilds/:guild_id", adminHandler.GetGuildDetail()) + adminAuthApiRouter.GET("/guilds/:guild_id/members", adminHandler.ListGuildMembers()) - adminAuthApiRouter.GET("/app/users", appHandler.UserPageList()) // 获取小程序用户列表 - adminAuthApiRouter.POST("/send_message", appHandler.AdminSendMessage()) // 发送消息 - adminAuthApiRouter.GET("/messages", appHandler.AppMessagePageList()) // 获取小程序用户消息列表 - adminAuthApiRouter.GET("/messages/latest", appHandler.LatestMessageByAppId()) // 根据appid获取最新消息记录 + // 商品管理:分类与商品 + adminAuthApiRouter.POST("/product_categories", adminHandler.CreateProductCategory()) + adminAuthApiRouter.PUT("/product_categories/:category_id", adminHandler.ModifyProductCategory()) + adminAuthApiRouter.DELETE("/product_categories/:category_id", adminHandler.DeleteProductCategory()) + adminAuthApiRouter.GET("/product_categories", adminHandler.ListProductCategories()) + adminAuthApiRouter.POST("/products", adminHandler.CreateProduct()) + adminAuthApiRouter.PUT("/products/:product_id", adminHandler.ModifyProduct()) + adminAuthApiRouter.DELETE("/products/:product_id", adminHandler.DeleteProduct()) + adminAuthApiRouter.GET("/products", adminHandler.ListProducts()) + + // 轮播图管理 + adminAuthApiRouter.POST("/banners", adminHandler.CreateBanner()) + adminAuthApiRouter.PUT("/banners/:banner_id", adminHandler.ModifyBanner()) + adminAuthApiRouter.DELETE("/banners/:banner_id", adminHandler.DeleteBanner()) + adminAuthApiRouter.GET("/banners", adminHandler.ListBanners()) + + // 用户管理 + adminAuthApiRouter.GET("/users", adminHandler.ListAppUsers()) + adminAuthApiRouter.GET("/users/:user_id/invites", adminHandler.ListUserInvites()) + adminAuthApiRouter.GET("/users/:user_id/orders", adminHandler.ListUserOrders()) + adminAuthApiRouter.GET("/users/:user_id/coupons", adminHandler.ListUserCoupons()) + adminAuthApiRouter.GET("/users/:user_id/points", adminHandler.ListUserPoints()) + adminAuthApiRouter.GET("/users/:user_id/points/balance", adminHandler.GetUserPointsBalance()) + adminAuthApiRouter.POST("/users/:user_id/points/add", adminHandler.AddUserPoints()) + adminAuthApiRouter.POST("/users/:user_id/coupons/add", adminHandler.AddUserCoupon()) + adminAuthApiRouter.POST("/users/:user_id/rewards/grant", adminHandler.GrantReward()) + adminAuthApiRouter.GET("/users/:user_id/inventory", adminHandler.ListUserInventory()) + + // 道具卡管理 + adminAuthApiRouter.POST("/system_item_cards", adminHandler.CreateSystemItemCard()) + adminAuthApiRouter.PUT("/system_item_cards/:item_card_id", adminHandler.ModifySystemItemCard()) + adminAuthApiRouter.DELETE("/system_item_cards/:item_card_id", adminHandler.DeleteSystemItemCard()) + adminAuthApiRouter.GET("/system_item_cards", adminHandler.ListSystemItemCards()) + // 优惠券管理 + adminAuthApiRouter.POST("/system_coupons", adminHandler.CreateSystemCoupon()) + adminAuthApiRouter.PUT("/system_coupons/:coupon_id", adminHandler.ModifySystemCoupon()) + adminAuthApiRouter.DELETE("/system_coupons/:coupon_id", adminHandler.DeleteSystemCoupon()) + adminAuthApiRouter.GET("/system_coupons", adminHandler.ListSystemCoupons()) + adminAuthApiRouter.POST("/users/:user_id/item_cards", adminHandler.AssignUserItemCard()) + // 通用上传 + systemApiRouter.POST("/common/upload/wangeditor", commonHandler.UploadWangEditorImage()) + } + + // 系统管理:用户/角色/菜单 + { + systemApiRouter.GET("/user/list", adminHandler.ListUsers()) + systemApiRouter.GET("/role/list", adminHandler.ListRoles()) + systemApiRouter.GET("/v3/system/menus/simple", adminHandler.ListSimpleMenus()) + systemApiRouter.POST("/role", adminHandler.CreateRole()) + systemApiRouter.PUT("/role/:role_id", adminHandler.ModifyRole()) + systemApiRouter.DELETE("/role/:role_id", adminHandler.DeleteRole()) + systemApiRouter.POST("/role/:role_id/users", adminHandler.AssignRoleUsers()) + systemApiRouter.GET("/role/:role_id/users", adminHandler.ListRoleUsers()) + systemApiRouter.DELETE("/role/:role_id/users/:admin_id", adminHandler.RemoveRoleUser()) + systemApiRouter.POST("/menu", adminHandler.CreateMenu()) + systemApiRouter.PUT("/menu/:menu_id", adminHandler.ModifyMenu()) + systemApiRouter.DELETE("/menu/:menu_id", adminHandler.DeleteMenu()) + systemApiRouter.GET("/menu/:menu_id/actions", adminHandler.ListMenuActions()) + systemApiRouter.POST("/menu/:menu_id/actions", adminHandler.CreateMenuActions()) + systemApiRouter.DELETE("/menu/:menu_id/actions/:action_id", adminHandler.DeleteMenuAction()) + systemApiRouter.POST("/role/:role_id/menus", adminHandler.AssignRoleMenus()) + systemApiRouter.POST("/role/:role_id/actions", adminHandler.AssignRoleActions()) + } + + // APP 端接口路由组 + appApiRouter := mux.Group("/api/app") + { + appApiRouter.GET("/activities", activityHandler.ListActivities()) + appApiRouter.GET("/activities/:activity_id", activityHandler.GetActivityDetail()) + appApiRouter.GET("/activities/:activity_id/issues", activityHandler.ListActivityIssues()) + appApiRouter.GET("/activities/:activity_id/issues/:issue_id/rewards", activityHandler.ListIssueRewards()) + appApiRouter.GET("/activities/:activity_id/issues/:issue_id/draw_logs", activityHandler.ListDrawLogs()) + + appApiRouter.GET("/guilds", guildHandler.ListGuilds()) + appApiRouter.GET("/guilds/:guild_id", guildHandler.GetGuildDetail()) + appApiRouter.POST("/guilds/:guild_id/members", guildHandler.JoinGuild()) + appApiRouter.DELETE("/guilds/:guild_id/members/:user_id", guildHandler.LeaveGuild()) + appApiRouter.GET("/guilds/:guild_id/members", guildHandler.ListGuildMembers()) + + // APP 端轮播图 + appApiRouter.GET("/banners", appapi.NewBanner(logger, db).ListBannersForApp()) + + appApiRouter.PUT("/users/:user_id", userHandler.ModifyUser()) + appApiRouter.GET("/users/:user_id/orders", userHandler.ListUserOrders()) + appApiRouter.GET("/users/:user_id/coupons", userHandler.ListUserCoupons()) + appApiRouter.GET("/users/:user_id/points", userHandler.ListUserPoints()) + appApiRouter.GET("/users/:user_id/points/balance", userHandler.GetUserPointsBalance()) + appApiRouter.POST("/users/weixin/login", userHandler.WeixinLogin()) + appApiRouter.POST("/users/:user_id/phone/bind", userHandler.BindPhone()) + appApiRouter.GET("/users/:user_id/invites", userHandler.ListUserInvites()) + appApiRouter.GET("/users/:user_id/item_cards", userHandler.ListUserItemCards()) + appApiRouter.GET("/users/:user_id/item_cards/uses", userHandler.ListUserItemCardUses()) } return mux, nil diff --git a/internal/service/activity/activities_list.go b/internal/service/activity/activities_list.go new file mode 100644 index 0000000..492aefb --- /dev/null +++ b/internal/service/activity/activities_list.go @@ -0,0 +1,45 @@ +package activity + +import ( + "context" + + "bindbox-game/internal/repository/mysql/model" +) + +func (s *service) ListActivities(ctx context.Context, in ListActivitiesInput) (items []*model.Activities, total int64, err error) { + q := s.readDB.Activities.WithContext(ctx).ReadDB() + + if in.Name != "" { + q = q.Where(s.readDB.Activities.Name.Like("%" + in.Name + "%")) + } + if in.CategoryID != 0 { + q = q.Where(s.readDB.Activities.ActivityCategoryID.Eq(in.CategoryID)) + } + if in.IsBoss != nil { + q = q.Where(s.readDB.Activities.IsBoss.Eq(*in.IsBoss)) + } + if in.Status != nil { + q = q.Where(s.readDB.Activities.Status.Eq(*in.Status)) + } + + total, err = q.Count() + if err != nil { + return nil, 0, err + } + + if in.Page <= 0 { + in.Page = 1 + } + if in.PageSize <= 0 { + in.PageSize = 20 + } + if in.PageSize > 100 { + in.PageSize = 100 + } + + items, err = q.Order(s.readDB.Activities.ID.Desc()).Offset((in.Page - 1) * in.PageSize).Limit(in.PageSize).Find() + if err != nil { + return nil, 0, err + } + return items, total, nil +} diff --git a/internal/service/activity/activity.go b/internal/service/activity/activity.go new file mode 100644 index 0000000..dcfced4 --- /dev/null +++ b/internal/service/activity/activity.go @@ -0,0 +1,112 @@ +package activity + +import ( + "context" + "time" + + "bindbox-game/internal/pkg/logger" + "bindbox-game/internal/repository/mysql" + "bindbox-game/internal/repository/mysql/dao" + "bindbox-game/internal/repository/mysql/model" +) + +type Service interface { + CreateActivity(ctx context.Context, in CreateActivityInput) (*model.Activities, error) + ModifyActivity(ctx context.Context, id int64, in ModifyActivityInput) error + DeleteActivity(ctx context.Context, id int64) error + GetActivity(ctx context.Context, id int64) (*model.Activities, error) + ListActivities(ctx context.Context, in ListActivitiesInput) (items []*model.Activities, total int64, err error) + + ListIssues(ctx context.Context, activityID int64, page, pageSize int) (items []*model.ActivityIssues, total int64, err error) + CreateIssue(ctx context.Context, activityID int64, in CreateIssueInput) (*model.ActivityIssues, error) + ModifyIssue(ctx context.Context, issueID int64, in ModifyIssueInput) error + DeleteIssue(ctx context.Context, issueID int64) error + + CreateIssueRewards(ctx context.Context, issueID int64, rewards []CreateRewardInput) error + ListIssueRewards(ctx context.Context, issueID int64) (items []*model.ActivityRewardSettings, err error) + ModifyIssueReward(ctx context.Context, rewardID int64, in ModifyRewardInput) error + DeleteIssueReward(ctx context.Context, rewardID int64) error + + ListDrawLogs(ctx context.Context, issueID int64, page, pageSize int) (items []*model.ActivityDrawLogs, total int64, err error) + + GetCategoryNames(ctx context.Context, ids []int64) (map[int64]string, error) +} + +type service struct { + logger logger.CustomLogger + readDB *dao.Query + writeDB *dao.Query +} + +func New(l logger.CustomLogger, db mysql.Repo) Service { + return &service{ + logger: l, + readDB: dao.Use(db.GetDbR()), + writeDB: dao.Use(db.GetDbW()), + } +} + +type CreateActivityInput struct { + Name string + Banner string + ActivityCategoryID int64 + Status int32 + PriceDraw int64 + IsBoss int32 + StartTime *time.Time + EndTime *time.Time +} + +type ModifyActivityInput struct { + Name string + Banner string + ActivityCategoryID int64 + Status int32 + PriceDraw int64 + IsBoss int32 + StartTime *time.Time + EndTime *time.Time +} + +type ListActivitiesInput struct { + Name string + CategoryID int64 + IsBoss *int32 + Status *int32 + Page int + PageSize int +} + +type CreateIssueInput struct { + IssueNumber string + Status int32 + Sort int32 +} + +type ModifyIssueInput struct { + IssueNumber string + Status int32 + Sort int32 +} + +type CreateRewardInput struct { + ProductID int64 + Name string + Weight int32 + Quantity int64 + OriginalQty int64 + Level int32 + Sort int32 + IsBoss int32 +} + +type ModifyRewardInput struct { + ProductID *int64 + Name string + Weight *int32 + Quantity *int64 + OriginalQty *int64 + Level *int32 + Sort *int32 + IsBoss *int32 +} diff --git a/internal/service/activity/activity_create.go b/internal/service/activity/activity_create.go new file mode 100644 index 0000000..05eef5a --- /dev/null +++ b/internal/service/activity/activity_create.go @@ -0,0 +1,38 @@ +package activity + +import ( + "context" + + "bindbox-game/internal/repository/mysql/model" +) + +func (s *service) CreateActivity(ctx context.Context, in CreateActivityInput) (*model.Activities, error) { + item := &model.Activities{ + Name: in.Name, + Banner: in.Banner, + ActivityCategoryID: in.ActivityCategoryID, + Status: in.Status, + PriceDraw: in.PriceDraw, + IsBoss: in.IsBoss, + } + + if in.StartTime != nil { + item.StartTime = *in.StartTime + } + if in.EndTime != nil { + item.EndTime = *in.EndTime + } + + do := s.writeDB.Activities.WithContext(ctx) + if in.StartTime == nil { + do = do.Omit(s.writeDB.Activities.StartTime) + } + if in.EndTime == nil { + do = do.Omit(s.writeDB.Activities.EndTime) + } + err := do.Create(item) + if err != nil { + return nil, err + } + return item, nil +} diff --git a/internal/service/activity/activity_delete.go b/internal/service/activity/activity_delete.go new file mode 100644 index 0000000..a73f431 --- /dev/null +++ b/internal/service/activity/activity_delete.go @@ -0,0 +1,8 @@ +package activity + +import "context" + +func (s *service) DeleteActivity(ctx context.Context, id int64) error { + _, err := s.writeDB.Activities.WithContext(ctx).Where(s.writeDB.Activities.ID.Eq(id)).Delete() + return err +} diff --git a/internal/service/activity/activity_get.go b/internal/service/activity/activity_get.go new file mode 100644 index 0000000..04e96bc --- /dev/null +++ b/internal/service/activity/activity_get.go @@ -0,0 +1,21 @@ +package activity + +import ( + "context" + "errors" + + "gorm.io/gorm" + + "bindbox-game/internal/repository/mysql/model" +) + +func (s *service) GetActivity(ctx context.Context, id int64) (*model.Activities, error) { + item, err := s.readDB.Activities.WithContext(ctx).Where(s.readDB.Activities.ID.Eq(id)).First() + if err != nil { + if errors.Is(err, gorm.ErrRecordNotFound) { + return nil, err + } + return nil, err + } + return item, nil +} diff --git a/internal/service/activity/activity_modify.go b/internal/service/activity/activity_modify.go new file mode 100644 index 0000000..18fe024 --- /dev/null +++ b/internal/service/activity/activity_modify.go @@ -0,0 +1,39 @@ +package activity + +import ( + "context" + "time" +) + +func (s *service) ModifyActivity(ctx context.Context, id int64, in ModifyActivityInput) error { + item, err := s.readDB.Activities.WithContext(ctx).Where(s.readDB.Activities.ID.Eq(id)).First() + if err != nil { + return err + } + if in.Name != "" { + item.Name = in.Name + } + if in.Banner != "" { + item.Banner = in.Banner + } + if in.ActivityCategoryID != 0 { + item.ActivityCategoryID = in.ActivityCategoryID + } + if in.Status != 0 { + item.Status = in.Status + } + if in.PriceDraw != 0 { + item.PriceDraw = in.PriceDraw + } + if in.IsBoss != 0 { + item.IsBoss = in.IsBoss + } + if in.StartTime != nil { + item.StartTime = *in.StartTime + } + if in.EndTime != nil { + item.EndTime = *in.EndTime + } + item.UpdatedAt = time.Now() + return s.writeDB.Activities.WithContext(ctx).Save(item) +} diff --git a/internal/service/activity/category_lookup.go b/internal/service/activity/category_lookup.go new file mode 100644 index 0000000..a4db351 --- /dev/null +++ b/internal/service/activity/category_lookup.go @@ -0,0 +1,20 @@ +package activity + +import ( + "context" +) + +func (s *service) GetCategoryNames(ctx context.Context, ids []int64) (map[int64]string, error) { + result := make(map[int64]string) + if len(ids) == 0 { + return result, nil + } + items, err := s.readDB.ActivityCategories.WithContext(ctx).Where(s.readDB.ActivityCategories.ID.In(ids...)).Find() + if err != nil { + return nil, err + } + for _, v := range items { + result[v.ID] = v.Name + } + return result, nil +} diff --git a/internal/service/activity/draw_logs_list.go b/internal/service/activity/draw_logs_list.go new file mode 100644 index 0000000..207e17c --- /dev/null +++ b/internal/service/activity/draw_logs_list.go @@ -0,0 +1,29 @@ +package activity + +import ( + "context" + + "bindbox-game/internal/repository/mysql/model" +) + +func (s *service) ListDrawLogs(ctx context.Context, issueID int64, page, pageSize int) (items []*model.ActivityDrawLogs, total int64, err error) { + q := s.readDB.ActivityDrawLogs.WithContext(ctx).ReadDB().Where(s.readDB.ActivityDrawLogs.IssueID.Eq(issueID)) + total, err = q.Count() + if err != nil { + return nil, 0, err + } + if page <= 0 { + page = 1 + } + if pageSize <= 0 { + pageSize = 20 + } + if pageSize > 100 { + pageSize = 100 + } + items, err = q.Order(s.readDB.ActivityDrawLogs.ID.Desc()).Offset((page - 1) * pageSize).Limit(pageSize).Find() + if err != nil { + return nil, 0, err + } + return items, total, nil +} diff --git a/internal/service/activity/issue_create.go b/internal/service/activity/issue_create.go new file mode 100644 index 0000000..e8772e5 --- /dev/null +++ b/internal/service/activity/issue_create.go @@ -0,0 +1,29 @@ +package activity + +import ( + "context" + "errors" + + "bindbox-game/internal/repository/mysql/model" +) + +func (s *service) CreateIssue(ctx context.Context, activityID int64, in CreateIssueInput) (*model.ActivityIssues, error) { + exists, err := s.readDB.ActivityIssues.WithContext(ctx).Where(s.readDB.ActivityIssues.ActivityID.Eq(activityID), s.readDB.ActivityIssues.IssueNumber.Eq(in.IssueNumber)).Count() + if err != nil { + return nil, err + } + if exists > 0 { + return nil, errors.New("issue_number already exists") + } + item := &model.ActivityIssues{ + ActivityID: activityID, + IssueNumber: in.IssueNumber, + Status: in.Status, + Sort: in.Sort, + } + err = s.writeDB.ActivityIssues.WithContext(ctx).Create(item) + if err != nil { + return nil, err + } + return item, nil +} diff --git a/internal/service/activity/issue_delete.go b/internal/service/activity/issue_delete.go new file mode 100644 index 0000000..60cbc8e --- /dev/null +++ b/internal/service/activity/issue_delete.go @@ -0,0 +1,8 @@ +package activity + +import "context" + +func (s *service) DeleteIssue(ctx context.Context, issueID int64) error { + _, err := s.writeDB.ActivityIssues.WithContext(ctx).Where(s.writeDB.ActivityIssues.ID.Eq(issueID)).Delete() + return err +} diff --git a/internal/service/activity/issue_modify.go b/internal/service/activity/issue_modify.go new file mode 100644 index 0000000..d09a5eb --- /dev/null +++ b/internal/service/activity/issue_modify.go @@ -0,0 +1,24 @@ +package activity + +import ( + "context" + "time" +) + +func (s *service) ModifyIssue(ctx context.Context, issueID int64, in ModifyIssueInput) error { + item, err := s.readDB.ActivityIssues.WithContext(ctx).Where(s.readDB.ActivityIssues.ID.Eq(issueID)).First() + if err != nil { + return err + } + if in.IssueNumber != "" { + item.IssueNumber = in.IssueNumber + } + if in.Status != 0 { + item.Status = in.Status + } + if in.Sort != 0 { + item.Sort = in.Sort + } + item.UpdatedAt = time.Now() + return s.writeDB.ActivityIssues.WithContext(ctx).Save(item) +} diff --git a/internal/service/activity/issues_list.go b/internal/service/activity/issues_list.go new file mode 100644 index 0000000..ef7fbce --- /dev/null +++ b/internal/service/activity/issues_list.go @@ -0,0 +1,29 @@ +package activity + +import ( + "context" + + "bindbox-game/internal/repository/mysql/model" +) + +func (s *service) ListIssues(ctx context.Context, activityID int64, page, pageSize int) (items []*model.ActivityIssues, total int64, err error) { + q := s.readDB.ActivityIssues.WithContext(ctx).ReadDB().Where(s.readDB.ActivityIssues.ActivityID.Eq(activityID)) + total, err = q.Count() + if err != nil { + return nil, 0, err + } + if page <= 0 { + page = 1 + } + if pageSize <= 0 { + pageSize = 20 + } + if pageSize > 100 { + pageSize = 100 + } + items, err = q.Order(s.readDB.ActivityIssues.Sort.Desc()).Offset((page - 1) * pageSize).Limit(pageSize).Find() + if err != nil { + return nil, 0, err + } + return items, total, nil +} diff --git a/internal/service/activity/rewards_create.go b/internal/service/activity/rewards_create.go new file mode 100644 index 0000000..16c3502 --- /dev/null +++ b/internal/service/activity/rewards_create.go @@ -0,0 +1,30 @@ +package activity + +import ( + "context" + + "bindbox-game/internal/repository/mysql/dao" + "bindbox-game/internal/repository/mysql/model" +) + +func (s *service) CreateIssueRewards(ctx context.Context, issueID int64, rewards []CreateRewardInput) error { + return s.writeDB.Transaction(func(tx *dao.Query) error { + for _, r := range rewards { + item := &model.ActivityRewardSettings{ + IssueID: issueID, + ProductID: r.ProductID, + Name: r.Name, + Weight: r.Weight, + Quantity: r.Quantity, + OriginalQty: r.OriginalQty, + Level: r.Level, + Sort: r.Sort, + IsBoss: r.IsBoss, + } + if err := tx.ActivityRewardSettings.WithContext(ctx).Create(item); err != nil { + return err + } + } + return nil + }) +} diff --git a/internal/service/activity/rewards_list.go b/internal/service/activity/rewards_list.go new file mode 100644 index 0000000..3214233 --- /dev/null +++ b/internal/service/activity/rewards_list.go @@ -0,0 +1,15 @@ +package activity + +import ( + "context" + + "bindbox-game/internal/repository/mysql/model" +) + +func (s *service) ListIssueRewards(ctx context.Context, issueID int64) (items []*model.ActivityRewardSettings, err error) { + items, err = s.readDB.ActivityRewardSettings.WithContext(ctx).Where(s.readDB.ActivityRewardSettings.IssueID.Eq(issueID)).Order(s.readDB.ActivityRewardSettings.Sort.Asc()).Find() + if err != nil { + return nil, err + } + return items, nil +} diff --git a/internal/service/activity/rewards_modify.go b/internal/service/activity/rewards_modify.go new file mode 100644 index 0000000..4dbb59d --- /dev/null +++ b/internal/service/activity/rewards_modify.go @@ -0,0 +1,46 @@ +package activity + +import ( + "context" + "time" + + "bindbox-game/internal/repository/mysql/model" +) + +func (s *service) ModifyIssueReward(ctx context.Context, rewardID int64, in ModifyRewardInput) error { + item, err := s.readDB.ActivityRewardSettings.WithContext(ctx).Where(s.readDB.ActivityRewardSettings.ID.Eq(rewardID)).First() + if err != nil { + return err + } + if in.ProductID != nil { + item.ProductID = *in.ProductID + } + if in.Name != "" { + item.Name = in.Name + } + if in.Weight != nil { + item.Weight = *in.Weight + } + if in.Quantity != nil { + item.Quantity = *in.Quantity + } + if in.OriginalQty != nil { + item.OriginalQty = *in.OriginalQty + } + if in.Level != nil { + item.Level = *in.Level + } + if in.Sort != nil { + item.Sort = *in.Sort + } + if in.IsBoss != nil { + item.IsBoss = *in.IsBoss + } + item.UpdatedAt = time.Now() + return s.writeDB.ActivityRewardSettings.WithContext(ctx).Save(item) +} + +func (s *service) DeleteIssueReward(ctx context.Context, rewardID int64) error { + _, err := s.writeDB.ActivityRewardSettings.WithContext(ctx).Where(s.writeDB.ActivityRewardSettings.ID.Eq(rewardID)).Delete(&model.ActivityRewardSettings{}) + return err +} diff --git a/internal/service/admin/admin.go b/internal/service/admin/admin.go new file mode 100644 index 0000000..24745e3 --- /dev/null +++ b/internal/service/admin/admin.go @@ -0,0 +1,32 @@ +package admin + +import ( + "context" + + "bindbox-game/internal/pkg/logger" + "bindbox-game/internal/repository/mysql" + "bindbox-game/internal/repository/mysql/dao" + "bindbox-game/internal/repository/mysql/model" +) + +type Service interface { + Login(ctx context.Context, in LoginInput) (LoginResult, error) + Create(ctx context.Context, in CreateInput) error + Modify(ctx context.Context, id int, in ModifyInput) error + Delete(ctx context.Context, ids []int32) error + List(ctx context.Context, in ListInput) (items []*model.Admin, total int64, err error) +} + +type service struct { + logger logger.CustomLogger + readDB *dao.Query + writeDB *dao.Query +} + +func New(l logger.CustomLogger, db mysql.Repo) Service { + return &service{ + logger: l, + readDB: dao.Use(db.GetDbR()), + writeDB: dao.Use(db.GetDbW()), + } +} diff --git a/internal/service/admin/admin_create.go b/internal/service/admin/admin_create.go new file mode 100644 index 0000000..682b6c3 --- /dev/null +++ b/internal/service/admin/admin_create.go @@ -0,0 +1,51 @@ +package admin + +import ( + "context" + "fmt" + "time" + + "bindbox-game/internal/pkg/utils" + "bindbox-game/internal/repository/mysql/model" + + "gorm.io/gorm" +) + +type CreateInput struct { + Username string + Nickname string + Mobile string + Password string + Avatar string + CreatedBy string +} + +func (s *service) Create(ctx context.Context, in CreateInput) error { + info, err := s.readDB.Admin.WithContext(ctx). + Where(s.readDB.Admin.Username.Eq(in.Username)). + First() + if err != nil && err != gorm.ErrRecordNotFound { + return err + } + if info != nil { + return fmt.Errorf("该账号已存在") + } + + hashedPassword, err := utils.GenerateAdminHashedPassword(in.Password) + if err != nil { + return err + } + + admin := &model.Admin{ + Username: in.Username, + Nickname: in.Nickname, + Mobile: in.Mobile, + Password: hashedPassword, + Avatar: in.Avatar, + LoginStatus: 1, + IsSuper: 0, + CreatedUser: in.CreatedBy, + CreatedAt: time.Now(), + } + return s.writeDB.Admin.WithContext(ctx).Create(admin) +} diff --git a/internal/service/admin/admin_delete.go b/internal/service/admin/admin_delete.go new file mode 100644 index 0000000..4799191 --- /dev/null +++ b/internal/service/admin/admin_delete.go @@ -0,0 +1,15 @@ +package admin + +import ( + "context" + + "bindbox-game/internal/repository/mysql/model" +) + +func (s *service) Delete(ctx context.Context, ids []int32) error { + _, err := s.writeDB.Admin.WithContext(ctx). + Where(s.writeDB.Admin.IsSuper.Eq(0)). + Where(s.writeDB.Admin.ID.In(ids...)). + Delete(&model.Admin{}) + return err +} diff --git a/internal/service/admin/admin_list.go b/internal/service/admin/admin_list.go new file mode 100644 index 0000000..6f3bcc2 --- /dev/null +++ b/internal/service/admin/admin_list.go @@ -0,0 +1,45 @@ +package admin + +import ( + "context" + "fmt" + + "bindbox-game/internal/repository/mysql/model" + + "gorm.io/gorm" +) + +type ListInput struct { + Username string + Nickname string + Page int + PageSize int +} + +func (s *service) List(ctx context.Context, in ListInput) ([]*model.Admin, int64, error) { + query := s.readDB.Admin.WithContext(ctx) + if in.Username != "" { + query = query.Where(s.readDB.Admin.Username.Like(fmt.Sprintf("%%%s%%", in.Username))) + } + if in.Nickname != "" { + query = query.Where(s.readDB.Admin.Nickname.Like(fmt.Sprintf("%%%s%%", in.Nickname))) + } + + listQueryDB := query.Session(&gorm.Session{}) + countQueryDB := query.Session(&gorm.Session{}) + + resultData, err := listQueryDB. + Order(s.readDB.Admin.ID.Desc()). + Limit(in.PageSize). + Offset((in.Page - 1) * in.PageSize).Find() + if err != nil { + return nil, 0, err + } + + count, err := countQueryDB.Count() + if err != nil { + return nil, 0, err + } + + return resultData, count, nil +} diff --git a/internal/service/admin/admin_modify.go b/internal/service/admin/admin_modify.go new file mode 100644 index 0000000..09261bd --- /dev/null +++ b/internal/service/admin/admin_modify.go @@ -0,0 +1,59 @@ +package admin + +import ( + "context" + "fmt" + "time" + + "bindbox-game/internal/pkg/utils" + + "gorm.io/gorm" +) + +type ModifyInput struct { + Username string + Nickname string + Mobile string + Password string + Avatar string + UpdatedBy string +} + +func (s *service) Modify(ctx context.Context, id int, in ModifyInput) error { + checkIdInfo, err := s.readDB.Admin.WithContext(ctx). + Where(s.readDB.Admin.ID.Eq(int32(id))). + First() + if err != nil && err != gorm.ErrRecordNotFound { + return err + } + if checkIdInfo == nil { + return fmt.Errorf("该账号不存在") + } + + checkUserNameInfo, err := s.readDB.Admin.WithContext(ctx). + Where(s.readDB.Admin.ID.Neq(int32(id))). + Where(s.readDB.Admin.Username.Eq(in.Username)). + First() + if err != nil && err != gorm.ErrRecordNotFound { + return err + } + if checkUserNameInfo != nil { + return fmt.Errorf("该账号已存在") + } + + if in.Password != "" { + hashedPassword, err := utils.GenerateAdminHashedPassword(in.Password) + if err != nil { + return err + } + checkIdInfo.Password = hashedPassword + } + + checkIdInfo.Username = in.Username + checkIdInfo.Nickname = in.Nickname + checkIdInfo.Mobile = in.Mobile + checkIdInfo.Avatar = in.Avatar + checkIdInfo.UpdatedUser = in.UpdatedBy + checkIdInfo.UpdatedAt = time.Now() + return s.writeDB.Admin.WithContext(ctx).Save(checkIdInfo) +} diff --git a/internal/service/admin/login.go b/internal/service/admin/login.go new file mode 100644 index 0000000..4bf533c --- /dev/null +++ b/internal/service/admin/login.go @@ -0,0 +1,63 @@ +package admin + +import ( + "context" + "fmt" + "time" + + "bindbox-game/configs" + "bindbox-game/internal/pkg/jwtoken" + "bindbox-game/internal/pkg/utils" + "bindbox-game/internal/proposal" + + "gorm.io/gorm" +) + +type LoginInput struct { + Username string + Password string + IP string +} + +type LoginResult struct { + Token string + IsSuper int32 +} + +func (s *service) Login(ctx context.Context, in LoginInput) (LoginResult, error) { + info, err := s.readDB.Admin.WithContext(ctx).Where(s.readDB.Admin.Username.Eq(in.Username)).First() + if err != nil && err != gorm.ErrRecordNotFound { + return LoginResult{}, err + } + if err == gorm.ErrRecordNotFound { + return LoginResult{}, fmt.Errorf("账号不存在,请联系管理员。") + } + if info.LoginStatus != 1 { + return LoginResult{}, fmt.Errorf("账号已被禁用") + } + if !utils.VerifyAdminHashedPassword(info.Password, in.Password) { + return LoginResult{}, fmt.Errorf("用户名或密码错误,请联系管理员。") + } + + sessionUserInfo := proposal.SessionUserInfo{ + Id: info.ID, + UserName: info.Username, + NickName: info.Nickname, + IsSuper: info.IsSuper, + Platform: "管理端", + } + + tokenString, err := jwtoken.New(configs.Get().JWT.AdminSecret).Sign(sessionUserInfo, 3*24*time.Hour) + if err != nil { + return LoginResult{}, fmt.Errorf("token 生成失败(%s)", err.Error()) + } + + info.LastLoginTime = time.Now() + info.LastLoginIP = in.IP + info.LastLoginHash = utils.MD5(tokenString) + if err := s.writeDB.Admin.WithContext(ctx).Save(info); err != nil { + return LoginResult{}, err + } + + return LoginResult{Token: tokenString, IsSuper: info.IsSuper}, nil +} diff --git a/internal/service/banner/banner.go b/internal/service/banner/banner.go new file mode 100644 index 0000000..c41fa39 --- /dev/null +++ b/internal/service/banner/banner.go @@ -0,0 +1,111 @@ +package banner + +import ( + "context" + + "bindbox-game/internal/pkg/logger" + "bindbox-game/internal/repository/mysql" + "bindbox-game/internal/repository/mysql/dao" + "bindbox-game/internal/repository/mysql/model" +) + +type Service interface { + Create(ctx context.Context, in CreateInput) (*model.Banner, error) + Modify(ctx context.Context, id int64, in ModifyInput) error + Delete(ctx context.Context, id int64) error + List(ctx context.Context, in ListInput) (items []*model.Banner, total int64, err error) + ListEnabled(ctx context.Context) ([]*model.Banner, error) +} + +type service struct { + logger logger.CustomLogger + readDB *dao.Query + writeDB *dao.Query +} + +func New(l logger.CustomLogger, db mysql.Repo) Service { + return &service{logger: l, readDB: dao.Use(db.GetDbR()), writeDB: dao.Use(db.GetDbW())} +} + +type CreateInput struct { + Title string + ImageURL string + LinkURL string + Sort int32 + Status int32 +} + +type ModifyInput struct { + Title *string + ImageURL *string + LinkURL *string + Sort *int32 + Status *int32 +} + +type ListInput struct { + Status *int32 + Page int + PageSize int +} + +func (s *service) Create(ctx context.Context, in CreateInput) (*model.Banner, error) { + m := &model.Banner{Title: in.Title, ImageURL: in.ImageURL, LinkURL: in.LinkURL, Sort: in.Sort, Status: in.Status} + if err := s.writeDB.Banner.WithContext(ctx).Create(m); err != nil { + return nil, err + } + return m, nil +} + +func (s *service) Modify(ctx context.Context, id int64, in ModifyInput) error { + updater := s.writeDB.Banner.WithContext(ctx).Where(s.writeDB.Banner.ID.Eq(id)) + set := map[string]any{} + if in.Title != nil { + set["title"] = *in.Title + } + if in.ImageURL != nil { + set["image_url"] = *in.ImageURL + } + if in.LinkURL != nil { + set["link_url"] = *in.LinkURL + } + if in.Sort != nil { + set["sort"] = *in.Sort + } + if in.Status != nil { + set["status"] = *in.Status + } + if len(set) == 0 { + return nil + } + _, err := updater.Updates(set) + return err +} + +func (s *service) Delete(ctx context.Context, id int64) error { + _, err := s.writeDB.Banner.WithContext(ctx).Where(s.writeDB.Banner.ID.Eq(id)).Delete() + return err +} + +func (s *service) List(ctx context.Context, in ListInput) (items []*model.Banner, total int64, err error) { + if in.Page <= 0 { + in.Page = 1 + } + if in.PageSize <= 0 { + in.PageSize = 20 + } + q := s.readDB.Banner.WithContext(ctx).ReadDB() + if in.Status != nil { + q = q.Where(s.readDB.Banner.Status.Eq(*in.Status)) + } + total, err = q.Count() + if err != nil { + return + } + items, err = q.Order(s.readDB.Banner.Sort.Asc()).Order(s.readDB.Banner.ID.Desc()).Limit(in.PageSize).Offset((in.Page-1)*in.PageSize).Find() + return +} + +func (s *service) ListEnabled(ctx context.Context) ([]*model.Banner, error) { + return s.readDB.Banner.WithContext(ctx).ReadDB().Where(s.readDB.Banner.Status.Eq(1)).Order(s.readDB.Banner.Sort.Asc()).Order(s.readDB.Banner.ID.Desc()).Find() +} \ No newline at end of file diff --git a/internal/service/common/common.go b/internal/service/common/common.go new file mode 100644 index 0000000..673c22d --- /dev/null +++ b/internal/service/common/common.go @@ -0,0 +1,79 @@ +package common + +import ( + "context" + "fmt" + "io" + "net/http" + "net/url" + "path" + "strings" + "time" + + "bindbox-game/configs" + + cos "github.com/tencentyun/cos-go-sdk-v5" +) + +type Service interface { + UploadImage(ctx context.Context, filename string, reader io.Reader, contentType string) (string, error) +} + +type service struct { + client *cos.Client + bucketURL string + publicBase string +} + +func New() Service { + cfg := configs.Get() + bucket := cfg.COS.Bucket + region := cfg.COS.Region + base := fmt.Sprintf("https://%s.cos.%s.myqcloud.com", bucket, region) + bu, _ := url.Parse(base) + client := cos.NewClient(&cos.BaseURL{BucketURL: bu}, &http.Client{ + Transport: &cos.AuthorizationTransport{SecretID: cfg.COS.SecretID, SecretKey: cfg.COS.SecretKey}, + }) + return &service{client: client, bucketURL: base, publicBase: strings.TrimSpace(cfg.COS.BaseURL)} +} + +func (s *service) UploadImage(ctx context.Context, filename string, reader io.Reader, contentType string) (string, error) { + date := time.Now().Format("2006/01/02") + ext := strings.ToLower(path.Ext(filename)) + if ext == "" { + ext = ".jpg" + } + ct := contentType + if ct == "" || ct == "application/octet-stream" { + switch ext { + case ".jpg", ".jpeg": + ct = "image/jpeg" + case ".png": + ct = "image/png" + case ".gif": + ct = "image/gif" + case ".webp": + ct = "image/webp" + case ".bmp": + ct = "image/bmp" + default: + ct = "application/octet-stream" + } + } + key := fmt.Sprintf("images/%s/%d%s", date, time.Now().UnixNano(), ext) + _, err := s.client.Object.Put(ctx, key, reader, &cos.ObjectPutOptions{ + ObjectPutHeaderOptions: &cos.ObjectPutHeaderOptions{ + ContentType: ct, + }, + ACLHeaderOptions: &cos.ACLHeaderOptions{ + XCosACL: "public-read", + }, + }) + if err != nil { + return "", err + } + if s.publicBase != "" { + return strings.TrimRight(s.publicBase, "/") + "/" + key, nil + } + return s.bucketURL + "/" + key, nil +} diff --git a/internal/service/guild/guild.go b/internal/service/guild/guild.go new file mode 100644 index 0000000..f332d4f --- /dev/null +++ b/internal/service/guild/guild.go @@ -0,0 +1,64 @@ +package guild + +import ( + "context" + + "bindbox-game/internal/pkg/logger" + "bindbox-game/internal/repository/mysql" + "bindbox-game/internal/repository/mysql/dao" + "bindbox-game/internal/repository/mysql/model" +) + +type Service interface { + CreateGuild(ctx context.Context, in CreateGuildInput) (*model.Guild, error) + ModifyGuild(ctx context.Context, id int64, in ModifyGuildInput) error + DeleteGuild(ctx context.Context, id int64) error + GetGuild(ctx context.Context, id int64) (*model.Guild, error) + ListGuilds(ctx context.Context, in ListGuildsInput) (items []*model.Guild, total int64, err error) + ListMembers(ctx context.Context, guildID int64, page, pageSize int) (items []*model.GuildMembers, total int64, err error) + JoinGuild(ctx context.Context, guildID int64, in JoinGuildInput) error + LeaveGuild(ctx context.Context, guildID int64, userID int64) error +} + +type service struct { + logger logger.CustomLogger + readDB *dao.Query + writeDB *dao.Query +} + +func New(l logger.CustomLogger, db mysql.Repo) Service { + return &service{logger: l, readDB: dao.Use(db.GetDbR()), writeDB: dao.Use(db.GetDbW())} +} + +type CreateGuildInput struct { + Name string + OwnerID int64 + Description string + JoinMode int32 + ConsumeLimit int64 + AvatarURL string + IsOpen int32 +} + +type ModifyGuildInput struct { + Name string + Description string + JoinMode int32 + ConsumeLimit int64 + AvatarURL string + IsOpen int32 + Status int32 +} + +type ListGuildsInput struct { + Name string + IsOpen *int32 + Status *int32 + JoinMode *int32 + Page int + PageSize int +} + +type JoinGuildInput struct { + UserID int64 +} diff --git a/internal/service/guild/guild_create.go b/internal/service/guild/guild_create.go new file mode 100644 index 0000000..e673226 --- /dev/null +++ b/internal/service/guild/guild_create.go @@ -0,0 +1,36 @@ +package guild + +import ( + "context" + "time" + + "bindbox-game/internal/repository/mysql/model" +) + +func (s *service) CreateGuild(ctx context.Context, in CreateGuildInput) (*model.Guild, error) { + g := &model.Guild{ + Name: in.Name, + OwnerID: in.OwnerID, + Description: in.Description, + JoinMode: in.JoinMode, + ConsumeLimit: in.ConsumeLimit, + AvatarURL: in.AvatarURL, + IsOpen: in.IsOpen, + Status: 1, + } + if err := s.writeDB.Guild.WithContext(ctx).Create(g); err != nil { + return nil, err + } + m := &model.GuildMembers{ + GuildID: g.ID, + UserID: in.OwnerID, + Role: "owner", + StartTime: time.Now(), + Status: 1, + JoinStatus: 2, + } + if err := s.writeDB.GuildMembers.WithContext(ctx).Create(m); err != nil { + return nil, err + } + return g, nil +} diff --git a/internal/service/guild/guild_delete.go b/internal/service/guild/guild_delete.go new file mode 100644 index 0000000..43207fe --- /dev/null +++ b/internal/service/guild/guild_delete.go @@ -0,0 +1,8 @@ +package guild + +import "context" + +func (s *service) DeleteGuild(ctx context.Context, id int64) error { + _, err := s.writeDB.Guild.WithContext(ctx).Where(s.readDB.Guild.ID.Eq(id)).Delete() + return err +} diff --git a/internal/service/guild/guild_get.go b/internal/service/guild/guild_get.go new file mode 100644 index 0000000..70684d7 --- /dev/null +++ b/internal/service/guild/guild_get.go @@ -0,0 +1,15 @@ +package guild + +import ( + "context" + + "bindbox-game/internal/repository/mysql/model" +) + +func (s *service) GetGuild(ctx context.Context, id int64) (*model.Guild, error) { + g, err := s.readDB.Guild.WithContext(ctx).Where(s.readDB.Guild.ID.Eq(id)).First() + if err != nil { + return nil, err + } + return g, nil +} diff --git a/internal/service/guild/guild_modify.go b/internal/service/guild/guild_modify.go new file mode 100644 index 0000000..7c21090 --- /dev/null +++ b/internal/service/guild/guild_modify.go @@ -0,0 +1,34 @@ +package guild + +import ( + "context" +) + +func (s *service) ModifyGuild(ctx context.Context, id int64, in ModifyGuildInput) error { + g, err := s.readDB.Guild.WithContext(ctx).Where(s.readDB.Guild.ID.Eq(id)).First() + if err != nil { + return err + } + if in.Name != "" { + g.Name = in.Name + } + if in.Description != "" { + g.Description = in.Description + } + if in.JoinMode != 0 { + g.JoinMode = in.JoinMode + } + if in.ConsumeLimit != 0 { + g.ConsumeLimit = in.ConsumeLimit + } + if in.AvatarURL != "" { + g.AvatarURL = in.AvatarURL + } + if in.IsOpen != 0 { + g.IsOpen = in.IsOpen + } + if in.Status != 0 { + g.Status = in.Status + } + return s.writeDB.Guild.WithContext(ctx).Save(g) +} diff --git a/internal/service/guild/guilds_list.go b/internal/service/guild/guilds_list.go new file mode 100644 index 0000000..4798214 --- /dev/null +++ b/internal/service/guild/guilds_list.go @@ -0,0 +1,41 @@ +package guild + +import ( + "context" + + "bindbox-game/internal/repository/mysql/model" +) + +func (s *service) ListGuilds(ctx context.Context, in ListGuildsInput) (items []*model.Guild, total int64, err error) { + q := s.readDB.Guild.WithContext(ctx).ReadDB() + if in.Name != "" { + q = q.Where(s.readDB.Guild.Name.Like("%" + in.Name + "%")) + } + if in.IsOpen != nil { + q = q.Where(s.readDB.Guild.IsOpen.Eq(*in.IsOpen)) + } + if in.Status != nil { + q = q.Where(s.readDB.Guild.Status.Eq(*in.Status)) + } + if in.JoinMode != nil { + q = q.Where(s.readDB.Guild.JoinMode.Eq(*in.JoinMode)) + } + total, err = q.Count() + if err != nil { + return nil, 0, err + } + if in.Page <= 0 { + in.Page = 1 + } + if in.PageSize <= 0 { + in.PageSize = 20 + } + if in.PageSize > 100 { + in.PageSize = 100 + } + items, err = q.Order(s.readDB.Guild.ID.Desc()).Offset((in.Page - 1) * in.PageSize).Limit(in.PageSize).Find() + if err != nil { + return nil, 0, err + } + return items, total, nil +} diff --git a/internal/service/guild/join.go b/internal/service/guild/join.go new file mode 100644 index 0000000..142ce1b --- /dev/null +++ b/internal/service/guild/join.go @@ -0,0 +1,48 @@ +package guild + +import ( + "context" + "errors" + "time" + + "gorm.io/gorm" + + "bindbox-game/internal/repository/mysql/model" +) + +func (s *service) JoinGuild(ctx context.Context, guildID int64, in JoinGuildInput) error { + lastExit, err := s.readDB.GuildMembers.WithContext(ctx). + Where(s.readDB.GuildMembers.UserID.Eq(in.UserID)). + Where(s.readDB.GuildMembers.Status.Eq(2)). + Order(s.readDB.GuildMembers.ID.Desc()). + Limit(1).Find() + if err != nil && !errors.Is(err, gorm.ErrRecordNotFound) { + return err + } + if len(lastExit) > 0 { + exitAt := lastExit[0].StartTime + if time.Since(exitAt) < 24*time.Hour { + return errors.New("recently left a guild, join limited within 24h") + } + } + exists, err := s.readDB.GuildMembers.WithContext(ctx). + Where(s.readDB.GuildMembers.GuildID.Eq(guildID)). + Where(s.readDB.GuildMembers.UserID.Eq(in.UserID)). + Where(s.readDB.GuildMembers.Status.Eq(1)).Count() + if err != nil { + return err + } + if exists > 0 { + return errors.New("already a member") + } + + m := &model.GuildMembers{ + GuildID: guildID, + UserID: in.UserID, + Role: "member", + StartTime: time.Now(), + Status: 1, + JoinStatus: 2, + } + return s.writeDB.GuildMembers.WithContext(ctx).Create(m) +} diff --git a/internal/service/guild/leave.go b/internal/service/guild/leave.go new file mode 100644 index 0000000..19ab552 --- /dev/null +++ b/internal/service/guild/leave.go @@ -0,0 +1,15 @@ +package guild + +import ( + "context" + "time" +) + +func (s *service) LeaveGuild(ctx context.Context, guildID int64, userID int64) error { + _, err := s.writeDB.GuildMembers.WithContext(ctx). + Where(s.readDB.GuildMembers.GuildID.Eq(guildID)). + Where(s.readDB.GuildMembers.UserID.Eq(userID)). + Where(s.readDB.GuildMembers.Status.Eq(1)). + Updates(map[string]any{s.readDB.GuildMembers.Status.ColumnName().String(): int32(2), s.readDB.GuildMembers.StartTime.ColumnName().String(): time.Now()}) + return err +} diff --git a/internal/service/guild/members_list.go b/internal/service/guild/members_list.go new file mode 100644 index 0000000..3c121d0 --- /dev/null +++ b/internal/service/guild/members_list.go @@ -0,0 +1,29 @@ +package guild + +import ( + "context" + + "bindbox-game/internal/repository/mysql/model" +) + +func (s *service) ListMembers(ctx context.Context, guildID int64, page, pageSize int) (items []*model.GuildMembers, total int64, err error) { + q := s.readDB.GuildMembers.WithContext(ctx).ReadDB().Where(s.readDB.GuildMembers.GuildID.Eq(guildID)).Where(s.readDB.GuildMembers.Status.Eq(1)) + total, err = q.Count() + if err != nil { + return nil, 0, err + } + if page <= 0 { + page = 1 + } + if pageSize <= 0 { + pageSize = 20 + } + if pageSize > 100 { + pageSize = 100 + } + items, err = q.Order(s.readDB.GuildMembers.ID.Desc()).Offset((page - 1) * pageSize).Limit(pageSize).Find() + if err != nil { + return nil, 0, err + } + return items, total, nil +} diff --git a/internal/service/product/product.go b/internal/service/product/product.go new file mode 100644 index 0000000..71fa83c --- /dev/null +++ b/internal/service/product/product.go @@ -0,0 +1,210 @@ +package product + +import ( + "context" + "encoding/json" + "strings" + + "bindbox-game/internal/pkg/logger" + "bindbox-game/internal/repository/mysql" + "bindbox-game/internal/repository/mysql/dao" + "bindbox-game/internal/repository/mysql/model" +) + +type Service interface { + CreateCategory(ctx context.Context, in CreateCategoryInput) (*model.ProductCategories, error) + ModifyCategory(ctx context.Context, id int64, in ModifyCategoryInput) error + DeleteCategory(ctx context.Context, id int64) error + ListCategories(ctx context.Context, in ListCategoriesInput) (items []*model.ProductCategories, total int64, err error) + + CreateProduct(ctx context.Context, in CreateProductInput) (*model.Products, error) + ModifyProduct(ctx context.Context, id int64, in ModifyProductInput) error + DeleteProduct(ctx context.Context, id int64) error + ListProducts(ctx context.Context, in ListProductsInput) (items []*model.Products, total int64, err error) +} + +type service struct { + logger logger.CustomLogger + readDB *dao.Query + writeDB *dao.Query +} + +func New(l logger.CustomLogger, db mysql.Repo) Service { + return &service{logger: l, readDB: dao.Use(db.GetDbR()), writeDB: dao.Use(db.GetDbW())} +} + +type CreateCategoryInput struct { + Name string + ParentID int64 + Status int32 +} + +type ModifyCategoryInput struct { + Name *string + ParentID *int64 + Status *int32 +} + +type ListCategoriesInput struct { + Name string + Status *int32 + Page int + PageSize int +} + +func (s *service) CreateCategory(ctx context.Context, in CreateCategoryInput) (*model.ProductCategories, error) { + m := &model.ProductCategories{Name: in.Name, ParentID: in.ParentID, Status: in.Status} + if err := s.writeDB.ProductCategories.WithContext(ctx).Create(m); err != nil { + return nil, err + } + return m, nil +} + +func (s *service) ModifyCategory(ctx context.Context, id int64, in ModifyCategoryInput) error { + updater := s.writeDB.ProductCategories.WithContext(ctx).Where(s.writeDB.ProductCategories.ID.Eq(id)) + set := map[string]any{} + if in.Name != nil { + set["name"] = *in.Name + } + if in.ParentID != nil { + set["parent_id"] = *in.ParentID + } + if in.Status != nil { + set["status"] = *in.Status + } + if len(set) == 0 { + return nil + } + _, err := updater.Updates(set) + return err +} + +func (s *service) DeleteCategory(ctx context.Context, id int64) error { + _, err := s.writeDB.ProductCategories.WithContext(ctx).Where(s.writeDB.ProductCategories.ID.Eq(id)).Delete() + return err +} + +func (s *service) ListCategories(ctx context.Context, in ListCategoriesInput) (items []*model.ProductCategories, total int64, err error) { + if in.Page <= 0 { + in.Page = 1 + } + if in.PageSize <= 0 { + in.PageSize = 20 + } + q := s.readDB.ProductCategories.WithContext(ctx).ReadDB() + if in.Name != "" { + q = q.Where(s.readDB.ProductCategories.Name.Like("%" + in.Name + "%")) + } + if in.Status != nil { + q = q.Where(s.readDB.ProductCategories.Status.Eq(*in.Status)) + } + total, err = q.Count() + if err != nil { + return + } + items, err = q.Order(s.readDB.ProductCategories.ID.Desc()).Limit(in.PageSize).Offset((in.Page - 1) * in.PageSize).Find() + return +} + +type CreateProductInput struct { + Name string + CategoryID int64 + ImagesJSON string + Price int64 + Stock int64 + Status int32 +} + +type ModifyProductInput struct { + Name *string + CategoryID *int64 + ImagesJSON *string + Price *int64 + Stock *int64 + Status *int32 +} + +type ListProductsInput struct { + Name string + CategoryID *int64 + Status *int32 + Page int + PageSize int +} + +func (s *service) CreateProduct(ctx context.Context, in CreateProductInput) (*model.Products, error) { + m := &model.Products{Name: in.Name, CategoryID: in.CategoryID, ImagesJSON: normalizeJSON(in.ImagesJSON), Price: in.Price, Stock: in.Stock, Status: in.Status} + if err := s.writeDB.Products.WithContext(ctx).Create(m); err != nil { + return nil, err + } + return m, nil +} + +func (s *service) ModifyProduct(ctx context.Context, id int64, in ModifyProductInput) error { + updater := s.writeDB.Products.WithContext(ctx).Where(s.writeDB.Products.ID.Eq(id)) + set := map[string]any{} + if in.Name != nil { + set["name"] = *in.Name + } + if in.CategoryID != nil { + set["category_id"] = *in.CategoryID + } + if in.ImagesJSON != nil { + set["images_json"] = normalizeJSON(*in.ImagesJSON) + } + if in.Price != nil { + set["price"] = *in.Price + } + if in.Stock != nil { + set["stock"] = *in.Stock + } + if in.Status != nil { + set["status"] = *in.Status + } + if len(set) == 0 { + return nil + } + _, err := updater.Updates(set) + return err +} + +func (s *service) DeleteProduct(ctx context.Context, id int64) error { + _, err := s.writeDB.Products.WithContext(ctx).Where(s.writeDB.Products.ID.Eq(id)).Delete() + return err +} + +func (s *service) ListProducts(ctx context.Context, in ListProductsInput) (items []*model.Products, total int64, err error) { + if in.Page <= 0 { + in.Page = 1 + } + if in.PageSize <= 0 { + in.PageSize = 20 + } + q := s.readDB.Products.WithContext(ctx).ReadDB() + if in.Name != "" { + q = q.Where(s.readDB.Products.Name.Like("%" + in.Name + "%")) + } + if in.CategoryID != nil { + q = q.Where(s.readDB.Products.CategoryID.Eq(*in.CategoryID)) + } + if in.Status != nil { + q = q.Where(s.readDB.Products.Status.Eq(*in.Status)) + } + total, err = q.Count() + if err != nil { + return + } + items, err = q.Order(s.readDB.Products.ID.Desc()).Limit(in.PageSize).Offset((in.Page - 1) * in.PageSize).Find() + return +} + +func normalizeJSON(s string) string { + if strings.TrimSpace(s) == "" { + return "[]" + } + var v any + if json.Unmarshal([]byte(s), &v) != nil { + return "[]" + } + return s +} diff --git a/internal/service/user/coupon_add.go b/internal/service/user/coupon_add.go new file mode 100644 index 0000000..f7867a3 --- /dev/null +++ b/internal/service/user/coupon_add.go @@ -0,0 +1,33 @@ +package user + +import ( + "context" + "time" + + "bindbox-game/internal/repository/mysql/model" +) + +func (s *service) AddCoupon(ctx context.Context, userID int64, couponID int64) error { + tpl, err := s.readDB.SystemCoupons.WithContext(ctx).Where(s.readDB.SystemCoupons.ID.Eq(couponID)).First() + if err != nil { + return err + } + if tpl == nil || tpl.Status != 1 { + return nil + } + item := &model.UserCoupons{UserID: userID, CouponID: couponID, Status: 1} + if !tpl.ValidStart.IsZero() { + item.ValidStart = tpl.ValidStart + } else { + item.ValidStart = time.Now() + } + if !tpl.ValidEnd.IsZero() { + item.ValidEnd = tpl.ValidEnd + } + do := s.writeDB.UserCoupons.WithContext(ctx).Omit(s.readDB.UserCoupons.UsedAt, s.readDB.UserCoupons.UsedOrderID) + if tpl.ValidEnd.IsZero() { + do = do.Omit(s.writeDB.UserCoupons.ValidEnd) + } + return do.Create(item) +} + diff --git a/internal/service/user/coupons_list.go b/internal/service/user/coupons_list.go new file mode 100644 index 0000000..b13783e --- /dev/null +++ b/internal/service/user/coupons_list.go @@ -0,0 +1,29 @@ +package user + +import ( + "context" + + "bindbox-game/internal/repository/mysql/model" +) + +func (s *service) ListCoupons(ctx context.Context, userID int64, page, pageSize int) (items []*model.UserCoupons, total int64, err error) { + q := s.readDB.UserCoupons.WithContext(ctx).ReadDB().Where(s.readDB.UserCoupons.UserID.Eq(userID)) + total, err = q.Count() + if err != nil { + return nil, 0, err + } + if page <= 0 { + page = 1 + } + if pageSize <= 0 { + pageSize = 20 + } + if pageSize > 100 { + pageSize = 100 + } + items, err = q.Order(s.readDB.UserCoupons.ID.Desc()).Offset((page - 1) * pageSize).Limit(pageSize).Find() + if err != nil { + return nil, 0, err + } + return items, total, nil +} diff --git a/internal/service/user/inventory_list.go b/internal/service/user/inventory_list.go new file mode 100644 index 0000000..1780027 --- /dev/null +++ b/internal/service/user/inventory_list.go @@ -0,0 +1,66 @@ +package user + +import ( + "context" + + "bindbox-game/internal/repository/mysql/model" +) + +type InventoryWithProduct struct { + *model.UserInventory + ProductName string `json:"product_name"` + ProductImages string `json:"product_images"` +} + +func (s *service) ListInventoryWithProduct(ctx context.Context, userID int64, page, pageSize int) (items []*InventoryWithProduct, total int64, err error) { + q := s.readDB.UserInventory.WithContext(ctx).ReadDB().Where(s.readDB.UserInventory.UserID.Eq(userID)) + total, err = q.Count() + if err != nil { + return nil, 0, err + } + if page <= 0 { + page = 1 + } + if pageSize <= 0 { + pageSize = 20 + } + if pageSize > 100 { + pageSize = 100 + } + rows, err := q.Order(s.readDB.UserInventory.ID.Desc()).Offset((page-1)*pageSize).Limit(pageSize).Find() + if err != nil { + return nil, 0, err + } + pidMap := make(map[int64]struct{}) + for _, r := range rows { + if r.ProductID > 0 { + pidMap[r.ProductID] = struct{}{} + } + } + products := map[int64]*model.Products{} + if len(pidMap) > 0 { + ids := make([]int64, 0, len(pidMap)) + for id := range pidMap { + ids = append(ids, id) + } + pros, err := s.readDB.Products.WithContext(ctx).ReadDB().Where(s.readDB.Products.ID.In(ids...)).Find() + if err != nil { + return nil, 0, err + } + for _, p := range pros { + products[p.ID] = p + } + } + items = make([]*InventoryWithProduct, len(rows)) + for i, r := range rows { + p := products[r.ProductID] + name := "" + images := "" + if p != nil { + name = p.Name + images = p.ImagesJSON + } + items[i] = &InventoryWithProduct{UserInventory: r, ProductName: name, ProductImages: images} + } + return items, total, nil +} \ No newline at end of file diff --git a/internal/service/user/invite_code.go b/internal/service/user/invite_code.go new file mode 100644 index 0000000..8345adc --- /dev/null +++ b/internal/service/user/invite_code.go @@ -0,0 +1,22 @@ +package user + +import ( + "context" + "crypto/rand" + "math/big" +) + +func (s *service) generateInviteCode(ctx context.Context) string { + const letters = "ABCDEFGHJKLMNPQRSTUVWXYZ23456789" + b := make([]byte, 8) + for i := 0; i < 8; i++ { + n, _ := rand.Int(rand.Reader, big.NewInt(int64(len(letters)))) + b[i] = letters[n.Int64()] + } + code := string(b) + exists, _ := s.readDB.Users.WithContext(ctx).Where(s.readDB.Users.InviteCode.Eq(code)).First() + if exists != nil { + return s.generateInviteCode(ctx) + } + return code +} diff --git a/internal/service/user/invites_list.go b/internal/service/user/invites_list.go new file mode 100644 index 0000000..80bf0a7 --- /dev/null +++ b/internal/service/user/invites_list.go @@ -0,0 +1,29 @@ +package user + +import ( + "context" + + "bindbox-game/internal/repository/mysql/model" +) + +func (s *service) ListInvites(ctx context.Context, userID int64, page, pageSize int) (items []*model.Users, total int64, err error) { + q := s.readDB.Users.WithContext(ctx).ReadDB().Where(s.readDB.Users.InviterID.Eq(userID)) + total, err = q.Count() + if err != nil { + return nil, 0, err + } + if page <= 0 { + page = 1 + } + if pageSize <= 0 { + pageSize = 20 + } + if pageSize > 100 { + pageSize = 100 + } + items, err = q.Order(s.readDB.Users.ID.Desc()).Offset((page - 1) * pageSize).Limit(pageSize).Find() + if err != nil { + return nil, 0, err + } + return items, total, nil +} diff --git a/internal/service/user/item_card_add.go b/internal/service/user/item_card_add.go new file mode 100644 index 0000000..e68e768 --- /dev/null +++ b/internal/service/user/item_card_add.go @@ -0,0 +1,57 @@ +package user + +import ( + "context" + "time" + + "bindbox-game/internal/repository/mysql/model" +) + +// AddItemCard 给用户添加道具卡 +// 功能描述: +// - 根据道具卡模板ID查询模板信息 +// - 验证道具卡状态是否有效(status=1) +// - 创建用户道具卡记录,继承模板的有效期设置 +// - 支持批量添加,quantity参数控制数量 +// +// 参数说明: +// - ctx: 上下文 +// - userID: 用户ID +// - cardID: 道具卡模板ID +// - quantity: 添加数量,如果<=0则默认为1 +// +// 返回说明: +// - error: 错误信息,包括数据库查询失败、模板不存在等情况 +func (s *service) AddItemCard(ctx context.Context, userID int64, cardID int64, quantity int) error { + if quantity <= 0 { + quantity = 1 + } + tpl, err := s.readDB.SystemItemCards.WithContext(ctx).Where(s.readDB.SystemItemCards.ID.Eq(cardID)).First() + if err != nil { + return err + } + if tpl == nil || tpl.Status != 1 { + return nil + } + now := time.Now() + for i := 0; i < quantity; i++ { + item := &model.UserItemCards{UserID: userID, CardID: cardID, Status: 1} + if !tpl.ValidStart.IsZero() { + item.ValidStart = tpl.ValidStart + } else { + item.ValidStart = now + } + if !tpl.ValidEnd.IsZero() { + item.ValidEnd = tpl.ValidEnd + } + do := s.writeDB.UserItemCards.WithContext(ctx) + if tpl.ValidEnd.IsZero() { + do = do.Omit(s.writeDB.UserItemCards.ValidEnd) + } + if err := do.Create(item); err != nil { + return err + } + } + return nil +} + diff --git a/internal/service/user/item_card_uses_list.go b/internal/service/user/item_card_uses_list.go new file mode 100644 index 0000000..31ad29d --- /dev/null +++ b/internal/service/user/item_card_uses_list.go @@ -0,0 +1,46 @@ +package user + +import ( + "context" + + "bindbox-game/internal/repository/mysql/model" +) + +// ListUserItemCardUses 获取用户道具卡使用记录 +// 功能描述: +// - 查询指定用户的道具卡使用记录 +// - 支持分页查询,默认每页20条,最大100条 +// - 按创建时间倒序排列 +// +// 参数说明: +// - ctx: 上下文 +// - userID: 用户ID +// - page: 页码,从1开始,小于1时自动设为1 +// - pageSize: 每页条数,小于1时设为20,大于100时设为100 +// +// 返回说明: +// - items: 道具卡使用记录列表 +// - total: 总记录数 +// - err: 错误信息 +func (s *service) ListUserItemCardUses(ctx context.Context, userID int64, page, pageSize int) (items []*model.ActivityDrawEffects, total int64, err error) { + q := s.readDB.ActivityDrawEffects.WithContext(ctx).ReadDB().Where(s.readDB.ActivityDrawEffects.UserID.Eq(userID)) + total, err = q.Count() + if err != nil { + return nil, 0, err + } + if page <= 0 { + page = 1 + } + if pageSize <= 0 { + pageSize = 20 + } + if pageSize > 100 { + pageSize = 100 + } + items, err = q.Order(s.readDB.ActivityDrawEffects.ID.Desc()).Offset((page-1)*pageSize).Limit(pageSize).Find() + if err != nil { + return nil, 0, err + } + return items, total, nil +} + diff --git a/internal/service/user/item_cards_list.go b/internal/service/user/item_cards_list.go new file mode 100644 index 0000000..eb9bd6c --- /dev/null +++ b/internal/service/user/item_cards_list.go @@ -0,0 +1,46 @@ +package user + +import ( + "context" + + "bindbox-game/internal/repository/mysql/model" +) + +// ListUserItemCards 获取用户道具卡列表 +// 功能描述: +// - 查询指定用户的道具卡列表 +// - 支持分页查询,默认每页20条,最大100条 +// - 按创建时间倒序排列 +// +// 参数说明: +// - ctx: 上下文 +// - userID: 用户ID +// - page: 页码,从1开始,小于1时自动设为1 +// - pageSize: 每页条数,小于1时设为20,大于100时设为100 +// +// 返回说明: +// - items: 道具卡列表 +// - total: 总记录数 +// - err: 错误信息 +func (s *service) ListUserItemCards(ctx context.Context, userID int64, page, pageSize int) (items []*model.UserItemCards, total int64, err error) { + q := s.readDB.UserItemCards.WithContext(ctx).ReadDB().Where(s.readDB.UserItemCards.UserID.Eq(userID)) + total, err = q.Count() + if err != nil { + return nil, 0, err + } + if page <= 0 { + page = 1 + } + if pageSize <= 0 { + pageSize = 20 + } + if pageSize > 100 { + pageSize = 100 + } + items, err = q.Order(s.readDB.UserItemCards.ID.Desc()).Offset((page-1)*pageSize).Limit(pageSize).Find() + if err != nil { + return nil, 0, err + } + return items, total, nil +} + diff --git a/internal/service/user/login_weixin.go b/internal/service/user/login_weixin.go new file mode 100644 index 0000000..cfc8e04 --- /dev/null +++ b/internal/service/user/login_weixin.go @@ -0,0 +1,118 @@ +package user + +import ( + "bytes" + "context" + "encoding/base64" + "image/png" + "strconv" + "time" + + "bindbox-game/internal/repository/mysql/dao" + "bindbox-game/internal/repository/mysql/model" + + randomname "github.com/DanPlayer/randomname" + identicon "github.com/issue9/identicon/v2" +) + +type LoginWeixinInput struct { + OpenID string + UnionID string + Nickname string + AvatarURL string + InviteCode string +} + +func (s *service) LoginWeixin(ctx context.Context, in LoginWeixinInput) (*model.Users, error) { + var u *model.Users + if in.OpenID != "" { + u, _ = s.readDB.Users.WithContext(ctx).Where(s.readDB.Users.Openid.Eq(in.OpenID)).First() + } + if u == nil && in.UnionID != "" { + u, _ = s.readDB.Users.WithContext(ctx).Where(s.readDB.Users.Unionid.Eq(in.UnionID)).First() + } + + if u == nil { + code := s.generateInviteCode(ctx) + nickname := in.Nickname + if nickname == "" { + nickname = randomname.GenerateName() + } + avatar := in.AvatarURL + if avatar == "" { + seed := in.OpenID + if seed == "" { + seed = nickname + } + img := identicon.S2(128).Make([]byte(seed)) + var buf bytes.Buffer + _ = png.Encode(&buf, img) + avatar = "data:image/png;base64," + base64.StdEncoding.EncodeToString(buf.Bytes()) + } + u = &model.Users{Nickname: nickname, Avatar: avatar, Openid: in.OpenID, Unionid: in.UnionID, InviteCode: code, Status: 1} + if err := s.writeDB.Users.WithContext(ctx).Create(u); err != nil { + return nil, err + } + } else { + set := map[string]any{} + if in.Nickname != "" { + set["nickname"] = in.Nickname + } + if in.AvatarURL != "" { + set["avatar"] = in.AvatarURL + } + if len(set) > 0 { + if _, err := s.writeDB.Users.WithContext(ctx).Where(s.writeDB.Users.ID.Eq(u.ID)).Updates(set); err != nil { + return nil, err + } + u, _ = s.readDB.Users.WithContext(ctx).Where(s.readDB.Users.ID.Eq(u.ID)).First() + } + } + + if in.InviteCode != "" { + if err := s.writeDB.Transaction(func(tx *dao.Query) error { + existed, _ := tx.UserInvites.WithContext(ctx).Where(tx.UserInvites.InviteeID.Eq(u.ID)).First() + if existed != nil { + return nil + } + inviter, _ := tx.Users.WithContext(ctx).Where(tx.Users.InviteCode.Eq(in.InviteCode)).First() + if inviter == nil || inviter.ID == u.ID { + return nil + } + reward := int64(10) + inv := &model.UserInvites{InviterID: inviter.ID, InviteeID: u.ID, InviteCode: in.InviteCode, RewardPoints: reward, RewardedAt: time.Now()} + if err := tx.UserInvites.WithContext(ctx).Create(inv); err != nil { + return err + } + if u.InviterID == 0 { + if _, err := tx.Users.WithContext(ctx).Where(tx.Users.ID.Eq(u.ID)).Updates(map[string]any{"inviter_id": inviter.ID}); err != nil { + return err + } + } + points, _ := tx.UserPoints.WithContext(ctx).Where(tx.UserPoints.UserID.Eq(inviter.ID)).Where(tx.UserPoints.Kind.Eq("invite")).First() + if points == nil { + points = &model.UserPoints{UserID: inviter.ID, Kind: "invite", Points: reward, ValidStart: time.Now()} + do := tx.UserPoints.WithContext(ctx) + if points.ValidEnd.IsZero() { + do = do.Omit(tx.UserPoints.ValidEnd) + } + if err := do.Create(points); err != nil { + return err + } + } else { + if _, err := tx.UserPoints.WithContext(ctx).Where(tx.UserPoints.ID.Eq(points.ID)).Updates(map[string]any{"points": points.Points + reward}); err != nil { + return err + } + } + ledger := &model.UserPointsLedger{UserID: inviter.ID, Action: "invite_reward", Points: reward, RefTable: "user_invites", RefID: strconv.FormatInt(inv.ID, 10), Remark: "invite_reward"} + if err := tx.UserPointsLedger.WithContext(ctx).Create(ledger); err != nil { + return err + } + return nil + }); err != nil { + return nil, err + } + } + + return u, nil +} diff --git a/internal/service/user/orders_list.go b/internal/service/user/orders_list.go new file mode 100644 index 0000000..bd5d0c9 --- /dev/null +++ b/internal/service/user/orders_list.go @@ -0,0 +1,126 @@ +package user + +import ( + "context" + "strings" + + "bindbox-game/internal/repository/mysql/model" +) + +// OrderWithItems 包含订单项的订单信息 +type OrderWithItems struct { + *model.Orders + Items []*model.OrderItems `json:"items"` +} + +func (s *service) ListOrders(ctx context.Context, userID int64, page, pageSize int) (items []*model.Orders, total int64, err error) { + // 查询用户的所有订单,包括商城直购(1)、抽奖票据(2)和系统发放(3) + q := s.readDB.Orders.WithContext(ctx).ReadDB().Where(s.readDB.Orders.UserID.Eq(userID)) + total, err = q.Count() + if err != nil { + return nil, 0, err + } + if page <= 0 { + page = 1 + } + if pageSize <= 0 { + pageSize = 20 + } + if pageSize > 100 { + pageSize = 100 + } + items, err = q.Order(s.readDB.Orders.ID.Desc()).Offset((page - 1) * pageSize).Limit(pageSize).Find() + if err != nil { + return nil, 0, err + } + return items, total, nil +} + +// ListOrdersWithItems 查询用户的订单列表,包含订单项详情 +func (s *service) ListOrdersWithItems(ctx context.Context, userID int64, page, pageSize int) (items []*OrderWithItems, total int64, err error) { + // 查询用户的所有订单,包括商城直购(1)、抽奖票据(2)和系统发放(3) + q := s.readDB.Orders.WithContext(ctx).ReadDB().Where(s.readDB.Orders.UserID.Eq(userID)) + total, err = q.Count() + if err != nil { + return nil, 0, err + } + if page <= 0 { + page = 1 + } + if pageSize <= 0 { + pageSize = 20 + } + if pageSize > 100 { + pageSize = 100 + } + + // 查询订单列表 + orders, err := q.Order(s.readDB.Orders.ID.Desc()).Offset((page - 1) * pageSize).Limit(pageSize).Find() + if err != nil { + return nil, 0, err + } + + // 构建订单ID列表 + orderIDs := make([]int64, len(orders)) + for i, order := range orders { + orderIDs[i] = order.ID + } + + var allItems []*model.OrderItems + if len(orderIDs) > 0 { + allItems, err = s.readDB.OrderItems.WithContext(ctx).ReadDB().Where(s.readDB.OrderItems.OrderID.In(orderIDs...)).Find() + if err != nil { + return nil, 0, err + } + + ids := make(map[int64]struct{}) + for _, it := range allItems { + if strings.TrimSpace(it.Title) == "" || strings.TrimSpace(it.Title) == "系统发放奖励" || it.ProductImages == "" || it.ProductImages == "[]" { + ids[it.ProductID] = struct{}{} + } + } + if len(ids) > 0 { + pidList := make([]int64, 0, len(ids)) + for id := range ids { + pidList = append(pidList, id) + } + pros, err2 := s.readDB.Products.WithContext(ctx).ReadDB().Where(s.readDB.Products.ID.In(pidList...)).Find() + if err2 != nil { + return nil, 0, err2 + } + pm := make(map[int64]*model.Products, len(pros)) + for _, p := range pros { + pm[p.ID] = p + } + for _, it := range allItems { + p := pm[it.ProductID] + if p == nil { + continue + } + if strings.TrimSpace(it.Title) == "" || strings.TrimSpace(it.Title) == "系统发放奖励" { + it.Title = p.Name + } + if it.ProductImages == "" || it.ProductImages == "[]" { + it.ProductImages = p.ImagesJSON + } + } + } + } + + // 构建订单ID到订单项的映射 + itemsMap := make(map[int64][]*model.OrderItems) + for _, item := range allItems { + itemsMap[item.OrderID] = append(itemsMap[item.OrderID], item) + } + + // 构建返回结果 + items = make([]*OrderWithItems, len(orders)) + for i, order := range orders { + items[i] = &OrderWithItems{ + Orders: order, + Items: itemsMap[order.ID], + } + } + + return items, total, nil +} diff --git a/internal/service/user/points_add.go b/internal/service/user/points_add.go new file mode 100644 index 0000000..60d44d7 --- /dev/null +++ b/internal/service/user/points_add.go @@ -0,0 +1,57 @@ +package user + +import ( + "context" + "strconv" + "time" + + "bindbox-game/internal/repository/mysql/dao" + "bindbox-game/internal/repository/mysql/model" +) + +func (s *service) AddPoints(ctx context.Context, userID int64, points int64, kind string, remark string, validStart *time.Time, validEnd *time.Time) error { + if points == 0 { + return nil + } + return s.writeDB.Transaction(func(tx *dao.Query) error { + var existing *model.UserPoints + if kind != "" { + existing, _ = tx.UserPoints.WithContext(ctx).Where(tx.UserPoints.UserID.Eq(userID)).Where(tx.UserPoints.Kind.Eq(kind)).First() + } else { + existing, _ = tx.UserPoints.WithContext(ctx).Where(tx.UserPoints.UserID.Eq(userID)).First() + } + if existing == nil { + item := &model.UserPoints{UserID: userID, Kind: kind, Points: points} + if validStart != nil { + item.ValidStart = *validStart + } + if validEnd != nil { + item.ValidEnd = *validEnd + } + do := tx.UserPoints.WithContext(ctx) + if validEnd == nil || validEnd.IsZero() { + do = do.Omit(tx.UserPoints.ValidEnd) + } + if err := do.Create(item); err != nil { + return err + } + } else { + set := map[string]any{"points": existing.Points + points} + if validStart != nil { + set["valid_start"] = *validStart + } + if validEnd != nil { + set["valid_end"] = *validEnd + } + if _, err := tx.UserPoints.WithContext(ctx).Where(tx.UserPoints.ID.Eq(existing.ID)).Updates(set); err != nil { + return err + } + } + ledger := &model.UserPointsLedger{UserID: userID, Action: "manual_add", Points: points, RefTable: "user_points", RefID: strconv.FormatInt(userID, 10), Remark: remark} + if err := tx.UserPointsLedger.WithContext(ctx).Create(ledger); err != nil { + return err + } + return nil + }) +} + diff --git a/internal/service/user/points_balance.go b/internal/service/user/points_balance.go new file mode 100644 index 0000000..fe2a9d3 --- /dev/null +++ b/internal/service/user/points_balance.go @@ -0,0 +1,22 @@ +package user + +import ( + "context" + "time" +) + +func (s *service) GetPointsBalance(ctx context.Context, userID int64) (int64, error) { + rows, err := s.readDB.UserPoints.WithContext(ctx).Where(s.readDB.UserPoints.UserID.Eq(userID)).Find() + if err != nil { + return 0, err + } + var total int64 + now := time.Now() + for _, r := range rows { + if !r.ValidEnd.IsZero() && r.ValidEnd.Before(now) { + continue + } + total += r.Points + } + return total, nil +} diff --git a/internal/service/user/points_ledger_list.go b/internal/service/user/points_ledger_list.go new file mode 100644 index 0000000..02e7c52 --- /dev/null +++ b/internal/service/user/points_ledger_list.go @@ -0,0 +1,29 @@ +package user + +import ( + "context" + + "bindbox-game/internal/repository/mysql/model" +) + +func (s *service) ListPointsLedger(ctx context.Context, userID int64, page, pageSize int) (items []*model.UserPointsLedger, total int64, err error) { + q := s.readDB.UserPointsLedger.WithContext(ctx).ReadDB().Where(s.readDB.UserPointsLedger.UserID.Eq(userID)) + total, err = q.Count() + if err != nil { + return nil, 0, err + } + if page <= 0 { + page = 1 + } + if pageSize <= 0 { + pageSize = 20 + } + if pageSize > 100 { + pageSize = 100 + } + items, err = q.Order(s.readDB.UserPointsLedger.ID.Desc()).Offset((page - 1) * pageSize).Limit(pageSize).Find() + if err != nil { + return nil, 0, err + } + return items, total, nil +} diff --git a/internal/service/user/reward_grant.go b/internal/service/user/reward_grant.go new file mode 100644 index 0000000..b3a0089 --- /dev/null +++ b/internal/service/user/reward_grant.go @@ -0,0 +1,227 @@ +package user + +import ( + "context" + "fmt" + "time" + + "go.uber.org/zap" + + "bindbox-game/internal/repository/mysql/dao" + "bindbox-game/internal/repository/mysql/model" +) + +// GrantRewardRequest 奖励发放请求 +type GrantRewardRequest struct { + ProductID int64 `json:"product_id" binding:"required"` // 商品ID + Quantity int `json:"quantity" binding:"min=1"` // 发放数量 + ActivityID *int64 `json:"activity_id,omitempty"` // 活动ID(可选) + RewardID *int64 `json:"reward_id,omitempty"` // 奖励配置ID(可选) + AddressID *int64 `json:"address_id,omitempty"` // 收货地址ID(可选,实物商品需要) + Remark string `json:"remark,omitempty"` // 备注 +} + +// GrantRewardResponse 奖励发放响应 +type GrantRewardResponse struct { + Success bool `json:"success"` + OrderID int64 `json:"order_id"` + InventoryIDs []int64 `json:"inventory_ids"` + Message string `json:"message,omitempty"` +} + +// GrantReward 给用户发放奖励(事务处理) +func (s *service) GrantReward(ctx context.Context, userID int64, req GrantRewardRequest) (*GrantRewardResponse, error) { + logger := zap.L().With(zap.Int64("user_id", userID), zap.Int64("product_id", req.ProductID)) + + var ( + orderID int64 + inventoryIDs []int64 + ) + + logger.Info("开始发放奖励", zap.Any("request", req)) + + // 执行事务 + err := s.writeDB.Transaction(func(tx *dao.Query) error { + logger.Info("开始事务处理") + + // 1. 检查奖励配置库存(如果提供了reward_id) + if req.RewardID != nil { + logger.Info("检查奖励配置", zap.Int64("reward_id", *req.RewardID)) + rewardSetting, err := tx.ActivityRewardSettings.WithContext(ctx).Where( + tx.ActivityRewardSettings.ID.Eq(*req.RewardID), + ).First() + if err != nil { + logger.Error("查询奖励配置失败", zap.Error(err)) + return fmt.Errorf("查询奖励配置失败: %w", err) + } + if rewardSetting == nil { + return fmt.Errorf("奖励配置不存在") + } + if rewardSetting.Quantity < int64(req.Quantity) { + return fmt.Errorf("奖励库存不足,剩余%d,需要%d", rewardSetting.Quantity, req.Quantity) + } + + // 扣减奖励库存 + _, err = tx.ActivityRewardSettings.WithContext(ctx).Where( + tx.ActivityRewardSettings.ID.Eq(*req.RewardID), + ).Update(tx.ActivityRewardSettings.Quantity, rewardSetting.Quantity-int64(req.Quantity)) + if err != nil { + logger.Error("扣减奖励库存失败", zap.Error(err)) + return fmt.Errorf("扣减奖励库存失败: %w", err) + } + logger.Info("奖励库存扣减成功") + } + + // 2. 生成订单号 + orderNo := generateOrderNo() + logger.Info("生成订单号", zap.String("order_no", orderNo)) + + // 3. 创建系统发放订单 + now := time.Now() + // 对于已支付的订单,设置取消时间为MySQL可接受的最小有效时间(1970-01-01) + // 避免使用零时间导致MySQL的'0000-00-00'错误 + minValidTime := time.Date(1970, 1, 1, 0, 0, 0, 0, time.UTC) + order := &model.Orders{ + OrderNo: orderNo, + UserID: userID, + SourceType: 3, // 系统发放 + Status: 2, // 已支付 + TotalAmount: 0, + DiscountAmount: 0, + PointsAmount: 0, + ActualAmount: 0, + IsConsumed: 0, + PaidAt: now, // 设置支付时间为当前时间 + CancelledAt: minValidTime, // 设置取消时间为最小有效时间,避免MySQL错误 + Remark: req.Remark, + CreatedAt: now, + UpdatedAt: now, + } + + logger.Info("创建订单", zap.Any("order", order)) + err := tx.Orders.WithContext(ctx).Create(order) + if err != nil { + logger.Error("创建订单失败", zap.Error(err)) + return fmt.Errorf("创建订单失败: %w", err) + } + orderID = order.ID + logger.Info("订单创建成功", zap.Int64("order_id", orderID)) + + // 4. 查询商品信息快照 + product, err := tx.Products.WithContext(ctx).Where(tx.Products.ID.Eq(req.ProductID)).First() + if err != nil { + logger.Error("查询商品失败", zap.Error(err)) + return fmt.Errorf("查询商品失败: %w", err) + } + + // 5. 创建订单项(按数量创建多个) + for i := 0; i < req.Quantity; i++ { + orderItem := &model.OrderItems{ + OrderID: orderID, + ProductID: req.ProductID, + Title: product.Name, + Quantity: 1, + Price: 0, // 成交单价(分) + TotalAmount: 0, // 行应付总额(分) + ProductImages: product.ImagesJSON, + Status: 1, // 行状态:1正常 + } + + err := tx.OrderItems.WithContext(ctx).Create(orderItem) + if err != nil { + logger.Error("创建订单项失败", zap.Error(err)) + return fmt.Errorf("创建订单项失败: %w", err) + } + + // 6. 创建用户资产记录 + inventory := &model.UserInventory{ + UserID: userID, + ProductID: req.ProductID, + OrderID: orderID, + ActivityID: func() int64 { + if req.ActivityID != nil { + return *req.ActivityID + } else { + return 0 + } + }(), + RewardID: func() int64 { + if req.RewardID != nil { + return *req.RewardID + } else { + return 0 + } + }(), + Status: 1, // 持有状态 + Remark: product.Name, + } + + err = tx.UserInventory.WithContext(ctx).Create(inventory) + if err != nil { + logger.Error("创建用户资产失败", zap.Error(err)) + return fmt.Errorf("创建用户资产失败: %w", err) + } + + inventoryIDs = append(inventoryIDs, inventory.ID) + + // 7. 如果需要发货(提供了地址ID),创建发货记录 + if req.AddressID != nil { + // 设置发货和签收时间为MySQL可接受的最小有效时间(1970-01-01) + // 避免使用零时间导致MySQL的'0000-00-00'错误 + minValidTime := time.Date(1970, 1, 1, 0, 0, 0, 0, time.UTC) + shippingRecord := &model.ShippingRecords{ + UserID: userID, + OrderID: orderID, + OrderItemID: orderItem.ID, + InventoryID: inventory.ID, + ProductID: req.ProductID, + AddressID: *req.AddressID, + Quantity: 1, + Status: 1, // 待发货 + ShippedAt: minValidTime, // 设置发货时间为最小有效时间 + ReceivedAt: minValidTime, // 设置签收时间为最小有效时间 + CreatedAt: time.Now(), + UpdatedAt: time.Now(), + } + + err := tx.ShippingRecords.WithContext(ctx).Create(shippingRecord) + if err != nil { + logger.Error("创建发货记录失败", zap.Error(err)) + return fmt.Errorf("创建发货记录失败: %w", err) + } + } + } + + return nil + }) + + if err != nil { + return &GrantRewardResponse{ + Success: false, + Message: err.Error(), + }, err + } + + logger.Info("奖励发放成功", + zap.Int64("order_id", orderID), + zap.Int64s("inventory_ids", inventoryIDs), + zap.Int("quantity", req.Quantity), + ) + + return &GrantRewardResponse{ + Success: true, + OrderID: orderID, + InventoryIDs: inventoryIDs, + Message: fmt.Sprintf("成功发放%d个奖励", req.Quantity), + }, nil +} + +// generateOrderNo 生成订单号 +func generateOrderNo() string { + // 使用当前时间戳 + 随机数生成订单号 + // 格式:RG + 年月日时分秒 + 6位随机数 + return fmt.Sprintf("RG%s%d", + time.Now().Format("20060102150405"), + time.Now().UnixNano()%1000000, + ) +} diff --git a/internal/service/user/update_profile.go b/internal/service/user/update_profile.go new file mode 100644 index 0000000..a6f989b --- /dev/null +++ b/internal/service/user/update_profile.go @@ -0,0 +1,24 @@ +package user + +import ( + "context" + + "bindbox-game/internal/repository/mysql/model" +) + +func (s *service) UpdateProfile(ctx context.Context, userID int64, nickname *string, avatar *string) (*model.Users, error) { + updater := s.writeDB.Users.WithContext(ctx).Where(s.writeDB.Users.ID.Eq(userID)) + set := map[string]any{} + if nickname != nil { + set["nickname"] = *nickname + } + if avatar != nil { + set["avatar"] = *avatar + } + if len(set) > 0 { + if _, err := updater.Updates(set); err != nil { + return nil, err + } + } + return s.readDB.Users.WithContext(ctx).Where(s.readDB.Users.ID.Eq(userID)).First() +} diff --git a/internal/service/user/user.go b/internal/service/user/user.go new file mode 100644 index 0000000..ad1094d --- /dev/null +++ b/internal/service/user/user.go @@ -0,0 +1,38 @@ +package user + +import ( + "bindbox-game/internal/pkg/logger" + "bindbox-game/internal/repository/mysql" + "bindbox-game/internal/repository/mysql/dao" + "bindbox-game/internal/repository/mysql/model" + "context" + "time" +) + +type Service interface { + UpdateProfile(ctx context.Context, userID int64, nickname *string, avatar *string) (*model.Users, error) + ListOrders(ctx context.Context, userID int64, page, pageSize int) (items []*model.Orders, total int64, err error) + ListOrdersWithItems(ctx context.Context, userID int64, page, pageSize int) (items []*OrderWithItems, total int64, err error) + ListInventoryWithProduct(ctx context.Context, userID int64, page, pageSize int) (items []*InventoryWithProduct, total int64, err error) + ListCoupons(ctx context.Context, userID int64, page, pageSize int) (items []*model.UserCoupons, total int64, err error) + ListPointsLedger(ctx context.Context, userID int64, page, pageSize int) (items []*model.UserPointsLedger, total int64, err error) + GetPointsBalance(ctx context.Context, userID int64) (int64, error) + LoginWeixin(ctx context.Context, in LoginWeixinInput) (*model.Users, error) + ListInvites(ctx context.Context, userID int64, page, pageSize int) (items []*model.Users, total int64, err error) + AddPoints(ctx context.Context, userID int64, points int64, kind string, remark string, validStart *time.Time, validEnd *time.Time) error + AddCoupon(ctx context.Context, userID int64, couponID int64) error + GrantReward(ctx context.Context, userID int64, req GrantRewardRequest) (*GrantRewardResponse, error) + AddItemCard(ctx context.Context, userID int64, cardID int64, quantity int) error + ListUserItemCards(ctx context.Context, userID int64, page, pageSize int) (items []*model.UserItemCards, total int64, err error) + ListUserItemCardUses(ctx context.Context, userID int64, page, pageSize int) (items []*model.ActivityDrawEffects, total int64, err error) +} + +type service struct { + logger logger.CustomLogger + readDB *dao.Query + writeDB *dao.Query +} + +func New(l logger.CustomLogger, db mysql.Repo) Service { + return &service{logger: l, readDB: dao.Use(db.GetDbR()), writeDB: dao.Use(db.GetDbW())} +} diff --git a/internal/services/material.go b/internal/services/material.go deleted file mode 100644 index c29fe43..0000000 --- a/internal/services/material.go +++ /dev/null @@ -1,9 +0,0 @@ -package services - -type TextMessage struct { - Message string `json:"message"` -} - -type PictureMessage struct { - ImgURL string `json:"img_url"` -} diff --git a/internal/services/services_miniprogram/miniprogram.go b/internal/services/services_miniprogram/miniprogram.go deleted file mode 100644 index 26db2e6..0000000 --- a/internal/services/services_miniprogram/miniprogram.go +++ /dev/null @@ -1,32 +0,0 @@ -package services_miniprogram - -import ( - "mini-chat/internal/pkg/core" - "mini-chat/internal/pkg/logger" - "mini-chat/internal/repository/mysql" - "mini-chat/internal/repository/mysql/dao" -) - -var _ Service = (*service)(nil) - -type Service interface { - i() - - GetAccessToken(appID, appSecret string, ctx core.Context) (string, error) -} - -type service struct { - logger logger.CustomLogger - writeDB *dao.Query - readDB *dao.Query -} - -func New(logger logger.CustomLogger, db mysql.Repo) Service { - return &service{ - logger: logger, - writeDB: dao.Use(db.GetDbW()), - readDB: dao.Use(db.GetDbR()), - } -} - -func (s *service) i() {} diff --git a/internal/services/services_miniprogram/miniprogram_access_token.go b/internal/services/services_miniprogram/miniprogram_access_token.go deleted file mode 100644 index 5e6098a..0000000 --- a/internal/services/services_miniprogram/miniprogram_access_token.go +++ /dev/null @@ -1,53 +0,0 @@ -package services_miniprogram - -import ( - "fmt" - "time" - - "mini-chat/internal/pkg/core" - "mini-chat/internal/pkg/miniprogram" - "mini-chat/internal/repository/mysql/model" - - "go.uber.org/zap" - "gorm.io/gorm" -) - -func (s *service) GetAccessToken(appID, appSecret string, ctx core.Context) (string, error) { - info, err := s.readDB.MiniProgramAccessToken.WithContext(ctx.RequestContext()). - Where(s.readDB.MiniProgramAccessToken.AppID.Eq(appID)). - Where(s.readDB.MiniProgramAccessToken.ExpiredAt.Gte(time.Now())).First() - if err != nil && err != gorm.ErrRecordNotFound { - return "", err - } - - accessToken := "" - - if err == gorm.ErrRecordNotFound { - // 生成 access_token - accessTokenResponse := new(miniprogram.AccessTokenResponse) - if err := miniprogram.GetAccessToken(appID, appSecret, accessTokenResponse); err != nil { - s.logger.Error("GetAccessToken failed", zap.Error(err)) - return "", err - } - - if accessTokenResponse.AccessToken == "" { - return "", fmt.Errorf("access_token is empty") - } - - // 保存 access_token - accessTokenData := new(model.MiniProgramAccessToken) - accessTokenData.AppID = appID - accessTokenData.AccessToken = accessTokenResponse.AccessToken - accessTokenData.CreatedAt = time.Now() - accessTokenData.ExpiredAt = time.Now().Add(time.Duration(accessTokenResponse.ExpiresIn) * time.Second) - if err := s.writeDB.MiniProgramAccessToken.WithContext(ctx.RequestContext()).Create(accessTokenData); err != nil { - return "", err - } - - accessToken = accessTokenResponse.AccessToken - } else { - accessToken = info.AccessToken - } - - return accessToken, nil -} diff --git a/logs/mini-chat-access.log b/logs/mini-chat-access.log index ea85b83..021d497 100644 --- a/logs/mini-chat-access.log +++ b/logs/mini-chat-access.log @@ -1 +1,5 @@ -{"level":"error","time":"2025-10-19 01:01:27","caller":"logger/logger.go:327","msg":"调用微信code2Session接口失败: 微信API错误: errcode=40163, errmsg=code been used, rid: 68f3c7e7-707fb9af-5df0aff4","domain":"mini-chat[fat]"} +{"level":"fatal","time":"2025-11-13 19:04:21","caller":"logger/logger.go:333","msg":"http server startup err","domain":"mini-chat[fat]","error":"listen tcp :9991: bind: address already in use"} +{"level":"fatal","time":"2025-11-14 15:10:49","caller":"logger/logger.go:333","msg":"http server startup err","domain":"mini-chat[fat]","error":"listen tcp :9991: bind: address already in use"} +{"level":"fatal","time":"2025-11-14 15:16:49","caller":"logger/logger.go:333","msg":"http server startup err","domain":"mini-chat[fat]","error":"listen tcp :9991: bind: address already in use"} +{"level":"fatal","time":"2025-11-14 16:52:42","caller":"logger/logger.go:333","msg":"http server startup err","domain":"mini-chat[fat]","error":"listen tcp :9991: bind: address already in use"} +{"level":"fatal","time":"2025-11-14 18:32:56","caller":"logger/logger.go:333","msg":"http server startup err","domain":"mini-chat[fat]","error":"listen tcp :9991: bind: address already in use"} diff --git a/main.go b/main.go index c0a7107..960c23c 100644 --- a/main.go +++ b/main.go @@ -5,15 +5,14 @@ import ( "fmt" "net/http" - "mini-chat/configs" - "mini-chat/internal/cron" - "mini-chat/internal/pkg/env" - "mini-chat/internal/pkg/logger" - "mini-chat/internal/pkg/shutdown" - "mini-chat/internal/pkg/timeutil" - "mini-chat/internal/repository/mysql" - "mini-chat/internal/repository/mysql/dao" - "mini-chat/internal/router" + "bindbox-game/configs" + "bindbox-game/internal/pkg/env" + "bindbox-game/internal/pkg/logger" + "bindbox-game/internal/pkg/shutdown" + "bindbox-game/internal/pkg/timeutil" + "bindbox-game/internal/repository/mysql" + "bindbox-game/internal/repository/mysql/dao" + "bindbox-game/internal/router" "go.uber.org/zap" ) @@ -50,15 +49,8 @@ func main() { _ = customLogger.Sync() }() - // 初始化 Cron - cronServer, err := cron.New(customLogger, dbRepo) - if err != nil { - panic(err) - } - cronServer.Start() - // 初始化 HTTP 服务 - mux, err := router.NewHTTPMux(customLogger, dbRepo, cronServer) + mux, err := router.NewHTTPMux(customLogger, dbRepo) if err != nil { panic(err) } @@ -92,10 +84,6 @@ func main() { customLogger.Error("dbr close err", zap.Error(err)) } - // 关闭 cron - if cronServer != nil { - cronServer.Stop() - } }, ) } diff --git a/test_item_card.sh b/test_item_card.sh new file mode 100644 index 0000000..a5d7439 --- /dev/null +++ b/test_item_card.sh @@ -0,0 +1,36 @@ +#!/bin/bash + +# 测试创建道具卡的脚本 + +# 登录获取token(假设有默认管理员账号) +echo "尝试登录获取token..." +LOGIN_RESPONSE=$(curl -s -X POST http://localhost:9991/api/admin/login \ + -H "Content-Type: application/json" \ + -d '{ + "username": "admin", + "password": "21232f297a57a5a743894a0e4a801fc3" + }') + +echo "登录响应: $LOGIN_RESPONSE" + +# 提取token(如果登录成功) +TOKEN=$(echo $LOGIN_RESPONSE | grep -o '"token":"[^"]*"' | cut -d'"' -f4) + +if [ -n "$TOKEN" ]; then + echo "获取到token: $TOKEN" + + # 创建测试道具卡 + echo "创建测试道具卡..." + CREATE_RESPONSE=$(curl -s -X POST http://localhost:9991/api/admin/system_item_cards \ + -H "Content-Type: application/json" \ + -H "Authorization: $TOKEN" \ + -d '{ + "name": "测试抽奖卡", + "card_type": 1, + "scope_type": 1, + "price": 100, + "effect_type": 1, + "reward_multiplier_x1000": 2000, + "boost_rate_x1000": 0, + "stacking_strategy": 1, + "max_effect_value_x100 \ No newline at end of file diff --git a/vercel.json b/vercel.json new file mode 100644 index 0000000..77f6206 --- /dev/null +++ b/vercel.json @@ -0,0 +1 @@ +{"rewrites":[{"source ":"/(.*)","destination":"/index.html"}]} \ No newline at end of file diff --git a/web/admin b/web/admin new file mode 160000 index 0000000..817b854 --- /dev/null +++ b/web/admin @@ -0,0 +1 @@ +Subproject commit 817b854fb143dd5125d9bfadbf0f16ff1d0478f9