diff --git a/.idea/.gitignore b/.idea/.gitignore
new file mode 100644
index 0000000..ab1f416
--- /dev/null
+++ b/.idea/.gitignore
@@ -0,0 +1,10 @@
+# Default ignored files
+/shelf/
+/workspace.xml
+# Ignored default folder with query files
+/queries/
+# Datasource local storage ignored files
+/dataSources/
+/dataSources.local.xml
+# Editor-based HTTP Client requests
+/httpRequests/
diff --git a/.idea/go.imports.xml b/.idea/go.imports.xml
new file mode 100644
index 0000000..d7202f0
--- /dev/null
+++ b/.idea/go.imports.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/modules.xml b/.idea/modules.xml
new file mode 100644
index 0000000..54a733d
--- /dev/null
+++ b/.idea/modules.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/morning-radio-backend.iml b/.idea/morning-radio-backend.iml
new file mode 100644
index 0000000..5e764c4
--- /dev/null
+++ b/.idea/morning-radio-backend.iml
@@ -0,0 +1,9 @@
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/vcs.xml b/.idea/vcs.xml
new file mode 100644
index 0000000..35eb1dd
--- /dev/null
+++ b/.idea/vcs.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Walkthrough.md b/Walkthrough.md
deleted file mode 100644
index 100c6d0..0000000
--- a/Walkthrough.md
+++ /dev/null
@@ -1,173 +0,0 @@
-# 项目改造 Walkthrough:从"植趣"到"早安电台"
-
-## 一、项目概述
-
-本次改造将后端项目从**植物养护小程序(植趣)**全面转型为**早安电台微信小程序**后端。保留了底层的系统模块(用户认证、OSS 文件管理等),删除了全部植物相关的业务模块,新建了早安电台核心业务模块。
-
----
-
-## 二、技术栈(保持不变)
-
-| 技术 | 版本/框架 | 用途 |
-|------|-----------|------|
-| Go | 1.24 | 后端语言 |
-| Gin | v1.10 | Web 框架 |
-| GORM | v1.26 | ORM 框架 |
-| MySQL | - | 主数据库 |
-| Redis | - | 缓存与分布式锁 |
-| MinIO | - | 对象存储(音频文件) |
-| Viper | v1.20 | 配置管理 |
-| Zap | v1.27 | 结构化日志 |
-| robfig/cron | v3 | 定时任务调度 |
-| JWT | v5 | 接口鉴权 |
-
----
-
-## 三、已删除的模块(植物相关)
-
-### 3.1 删除的目录
-
-| 目录 | 文件数 | 说明 |
-|------|--------|------|
-| `api/v1/plant/` | 12 个文件 | 植物 API 处理器 |
-| `router/plant/` | 12 个文件 | 植物路由定义 |
-| `service/plant/` | 13 个文件 | 植物业务逻辑 |
-| `model/plant/` | 22+ 个文件 | 植物数据模型(含 request/response 子目录) |
-| `task/` | 2 个文件 | 植物养护定时任务 |
-| `config/baidu_img_classify.go` | 1 个文件 | 百度植物识别配置 |
-
-### 3.2 删除的植物功能清单
-
-- 我的植物管理(CRUD、养护计划、养护任务、成长记录)
-- 社区帖子(发帖、评论、点赞、话题)
-- 植物百科(分类、百科条目)
-- 植物 OCR 识别
-- 等级配置系统
-- 徽章成就系统(植物养护相关)
-- 用户资料管理
-- 兑换中心(阳光值兑换商品)
-- 微信内容安全回调
-- 植物养护提醒定时任务
-
----
-
-## 四、新建的模块(早安电台)
-
-### 4.1 数据模型层 `model/radio/`
-
-| 文件 | 表名 | 说明 |
-|------|------|------|
-| `audio_content.go` | `sundynix_audio_content` | 音频内容表:标题、音频URL、封面、专辑名、场景、时长、脚本文本、来源类型、状态 |
-| `crawl_source.go` | `sundynix_crawl_source` | 抓取源配置表:名称、类型(github/producthunt/rss)、API地址、查询参数、场景、抓取间隔 |
-| `crawl_record.go` | `sundynix_crawl_record` | 抓取记录表:原始数据、清洗文本、AI摘要、处理状态、关联音频ID |
-| `play_record.go` | `sundynix_play_record` | 播放记录表:用户ID、音频ID、播放进度(秒)、是否完成、完成时间 |
-| `user_medal.go` | `sundynix_user_medal` | 用户勋章表:用户ID、勋章类型、获得时间 |
-| `user_subscription.go` | `sundynix_user_subscription` | 用户订阅表:用户ID、场景、是否启用、推送时间 |
-| `request/audio.go` | - | 请求参数:音频列表请求、播放状态更新请求、订阅更新请求 |
-| `response/audio.go` | - | 响应参数:音频列表响应、播放状态响应、勋章列表响应、订阅响应 |
-
-### 4.2 服务层 `service/radio/`
-
-| 文件 | 核心功能 |
-|------|----------|
-| `audio_content.go` | 音频列表分页查询(支持场景筛选)、音频详情、最新音频获取 |
-| `crawl.go` | 获取启用的抓取源、创建/更新抓取记录、获取待处理记录 |
-| `play_record.go` | 更新播放进度、断点续传支持、**完成收听时自动触发勋章解锁** |
-| `user_medal.go` | 查询用户勋章列表、检查勋章拥有状态 |
-| `user_subscription.go` | 查询/创建/更新用户订阅偏好 |
-| `enter.go` | ServiceGroup 聚合入口 |
-
-### 4.3 API 处理器层 `api/v1/radio/`
-
-| 文件 | 接口 | 说明 |
-|------|------|------|
-| `audio_content.go` | `GET /audio/list` | 分页获取音频列表,支持 `scene` 筛选 |
-| | `GET /audio/detail` | 根据 ID 获取音频详情 |
-| | `GET /audio/latest` | 获取指定场景的最新音频 |
-| `play_record.go` | `POST /audio/play-status` | 更新播放状态,完成时返回新解锁的勋章 |
-| | `GET /audio/play-record` | 获取播放进度(用于 `startTime` 断点续传) |
-| `user_medal.go` | `GET /medal/list` | 获取当前用户的所有勋章 |
-| `user_subscription.go` | `GET /subscription/info` | 获取用户的场景订阅列表 |
-| | `POST /subscription/update` | 更新/创建订阅设置 |
-
-### 4.4 路由层 `router/radio/`
-
-| 文件 | 路由组前缀 | 注册的 API |
-|------|-----------|-----------|
-| `audio_router.go` | `/audio` | list, detail, latest |
-| `play_record_router.go` | `/audio` | play-status, play-record |
-| `medal_router.go` | `/medal` | list |
-| `subscription_router.go` | `/subscription` | info, update |
-
----
-
-## 五、修改的全局文件
-
-### 5.1 聚合入口文件(enter.go)
-
-- `api/v1/enter.go` — `PlantApiGroup` → `RadioApiGroup`
-- `router/enter.go` — `Plant plant.RouterGroup` → `Radio radio.RouterGroup`
-- `service/enter.go` — `PlantServiceGroup` → `RadioServiceGroup`
-
-### 5.2 初始化文件(initialize/)
-
-- `router.go` — 全部 `plantGroup.InitXxxRouter()` → `radioGroup.InitXxxRouter()`,项目名称更新为 `sundynix-morning-radio`
-- `gorm.go` — 全部 `plant.Xxx{}` 模型迁移 → `radio.Xxx{}` 模型迁移
-- `timer.go` — 植物养护提醒 → 早安电台数据抓取定时任务(每2小时) + 音频生成任务(每天凌晨5点)
-
-### 5.3 全局常量(global/enums.go)
-
-移除植物养护相关常量,新增:
-
-- **勋章类型**:`EARLY_BIRD_7/30/100`, `EXPLORER`, `ALL_ROUNDER`, `FIRST_LISTEN`
-- **场景定义**:`morning_career`, `morning_health`, `morning_life`, `morning_study`
-- **抓取源类型**:`github`, `producthunt`, `rss`, `huggingface`, `webscrape`
-- **音频状态**:草稿(0)、已发布(1)、已下线(2)
-- **抓取状态**:pending、processed、failed
-
-### 5.4 配置文件
-
-- `config/config.go` — 移除 `BaiduImgClassify` 字段
-- `config-dev.yaml` — 移除百度植物识别配置,更新 MinIO bucket 为 `sundynix-audios`,更新 RocketMQ topic,更新 Zap 日志前缀
-
----
-
-## 六、核心业务流程
-
-### 6.1 数据抓取与音频生成流水线
-
-```
-定时任务(每2小时) → 抓取数据源 → 清洗HTML(Goquery) → AI摘要改写 → TTS语音合成 → MinIO存储 → CDN分发
-```
-
-### 6.2 用户收听与勋章系统
-
-```
-获取音频列表 → 播放音频 → 实时上报进度(断点续传) → 完成收听 → 触发勋章检查 → 解锁成就
-```
-
-### 6.3 场景化订阅
-
-```
-用户选择场景(硬核职场/效率健康/极简生活/知识胶囊) → 设置推送时间 → 按需接收个性化早安电台
-```
-
----
-
-## 七、编译验证
-
-```bash
-$ go build ./...
-# 编译通过,无错误
-```
-
----
-
-## 八、后续开发建议(TODO)
-
-1. **抓取服务实现**:接入 GitHub API、Product Hunt GraphQL API、RSS 订阅源
-2. **AI 摘要服务**:集成 DeepSeek/OpenAI API,实现抓取数据 → 口播脚本的自动改写
-3. **TTS 语音合成**:接入腾讯云 TTS 或其他 TTS 服务,生成 AAC 格式音频
-4. **CDN 配置**:为 MinIO 配置 Nginx HTTPS 反向代理 + CDN 边缘缓存
-5. **小程序前端**:集成 `BackgroundAudioManager` 实现后台播放、锁屏控件、断点续传
-6. **AIGC 合规标识**:在前端 UI 添加"AI 生成内容"标识
diff --git a/api/v1/enter.go b/api/v1/enter.go
index 592d642..2f0be2f 100644
--- a/api/v1/enter.go
+++ b/api/v1/enter.go
@@ -1,6 +1,7 @@
package v1
import (
+ "sundynix-go/api/v1/radio"
"sundynix-go/api/v1/system"
)
@@ -9,4 +10,5 @@ var ApiGroupApp = new(ApiGroup)
// ApiGroup 路由组
type ApiGroup struct {
SystemApiGroup system.ApiGroup
+ RadioApiGroup radio.ApiGroup
}
diff --git a/api/v1/radio/category.go b/api/v1/radio/category.go
new file mode 100644
index 0000000..56f6c74
--- /dev/null
+++ b/api/v1/radio/category.go
@@ -0,0 +1,159 @@
+package radio
+
+import (
+ "sundynix-go/global"
+ common "sundynix-go/model/commom/request"
+ "sundynix-go/model/commom/response"
+ "sundynix-go/model/radio/request"
+
+ "github.com/gin-gonic/gin"
+ "go.uber.org/zap"
+)
+
+type CategoryApi struct{}
+
+// GetCategoryPage 获取分类列表
+// @Tags 分类管理
+// @Summary 获取分类列表
+// @Accept application/json
+// @Produce application/json
+// @Param data body request.GetCategoryList true "分页查询"
+// @Success 200 {object} response.Response
+// @Router /radio/category/page [post]
+func (a *CategoryApi) GetCategoryPage(c *gin.Context) {
+ var req request.GetCategoryList
+ err := c.ShouldBindJSON(&req)
+ if err != nil {
+ response.FailWithMsg("参数错误: "+err.Error(), c)
+ return
+ }
+
+ list, total, err := categoryService.GetCategoryList(req)
+ if err != nil {
+ global.Logger.Error("获取分类列表失败!", zap.Error(err))
+ response.FailWithMsg(err.Error(), c)
+ return
+ }
+ response.OkWithData(response.PageResult{
+ List: list,
+ Total: total,
+ Page: req.Current,
+ PageSize: req.PageSize,
+ }, c)
+}
+
+// GetCategoryList 获取分类列表
+// @Tags 分类管理
+// @Summary 获取分类列表
+// @Produce application/json
+// @Success 200 {object} response.Response
+// @Router /radio/category/list [get]
+func (a *CategoryApi) GetCategoryList(c *gin.Context) {
+ list, err := categoryService.GetAllCategory()
+ if err != nil {
+ global.Logger.Error("获取分类列表失败!", zap.Error(err))
+ response.FailWithMsg(err.Error(), c)
+ return
+ }
+ response.OkWithData(response.ListResult{
+ List: list,
+ }, c)
+}
+
+// GetCategoryDetail 获取分类详情
+// @Tags 分类管理
+// @Summary 获取分类详情
+// @Produce application/json
+// @Param id query string true "分类ID"
+// @Success 200 {object} response.Response
+// @Router /radio/category/detail [get]
+func (a *CategoryApi) GetCategoryDetail(c *gin.Context) {
+ id := c.Query("id")
+ if id == "" {
+ response.FailWithMsg("参数错误: id不能为空", c)
+ return
+ }
+
+ category, err := categoryService.GetCategoryById(id)
+ if err != nil {
+ global.Logger.Error("获取分类详情失败!", zap.Error(err))
+ response.FailWithMsg(err.Error(), c)
+ return
+ }
+
+ response.OkWithData(category, c)
+}
+
+// SaveCategory 保存分类
+// @Tags 分类管理
+// @Summary 保存分类
+// @Accept application/json
+// @Produce application/json
+// @Param data body request.SaveCategory true "分类信息"
+// @Success 200 {object} response.Response
+// @Router /radio/category/save [post]
+func (a *CategoryApi) SaveCategory(c *gin.Context) {
+ var req request.SaveCategory
+ err := c.ShouldBindJSON(&req)
+ if err != nil {
+ response.FailWithMsg("参数错误: "+err.Error(), c)
+ return
+ }
+
+ if err := categoryService.SaveCategory(req); err != nil {
+ global.Logger.Error("保存分类失败!", zap.Error(err))
+ response.FailWithMsg(err.Error(), c)
+ return
+ }
+
+ response.OkWithMsg("保存成功", c)
+}
+
+// UpdateCategory 更新分类
+// @Tags 分类管理
+// @Summary 更新分类
+// @Accept application/json
+// @Produce application/json
+// @Param data body request.UpdateCategory true "Success 200 {分类信息"
+// @object} response.Response
+// @Router /radio/category/update [post]
+func (a *CategoryApi) UpdateCategory(c *gin.Context) {
+ var req request.UpdateCategory
+ err := c.ShouldBindJSON(&req)
+ if err != nil {
+ response.FailWithMsg("参数错误: "+err.Error(), c)
+ return
+ }
+
+ if err := categoryService.UpdateCategory(req); err != nil {
+ global.Logger.Error("更新分类失败!", zap.Error(err))
+ response.FailWithMsg(err.Error(), c)
+ return
+ }
+
+ response.OkWithMsg("更新成功", c)
+}
+
+// DeleteCategory 删除分类
+// @Tags 分类管理
+// @Summary 删除分类
+// @Produce application/json
+// @Param data body common.GetById true "分类ID"
+// @Success 200 {object} response.Response
+// @Router /radio/category/delete [post]
+func (a *CategoryApi) DeleteCategory(c *gin.Context) {
+ var req common.IdReq
+ err := c.ShouldBindJSON(&req)
+ if err != nil || req.Id == "" {
+ response.FailWithMsg("参数错误: id不能为空", c)
+ return
+ }
+
+ if err := categoryService.DeleteCategory(req.Id); err != nil {
+ global.Logger.Error("删除分类失败!", zap.Error(err))
+ response.FailWithMsg(err.Error(), c)
+ return
+ }
+
+ response.OkWithMsg("删除成功", c)
+}
diff --git a/api/v1/radio/channel.go b/api/v1/radio/channel.go
new file mode 100644
index 0000000..b3c93b3
--- /dev/null
+++ b/api/v1/radio/channel.go
@@ -0,0 +1,146 @@
+package radio
+
+import (
+ "sundynix-go/global"
+ common "sundynix-go/model/commom/request"
+
+ "sundynix-go/model/commom/response"
+ "sundynix-go/model/radio/request"
+ "sundynix-go/utils/auth"
+
+ "github.com/gin-gonic/gin"
+ "go.uber.org/zap"
+)
+
+type ChannelApi struct{}
+
+// GetChannelList 获取频道列表
+// @Tags 频道管理
+// @Summary 获取频道列表
+// @Accept application/json
+// @Produce application/json
+// @Param data body request.GetChannelList true "分页查询"
+// @Success 200 {object} response.Response
+// @Router /radio/channel/list [post]
+func (a *ChannelApi) GetChannelList(c *gin.Context) {
+ userId := auth.GetUserId(c)
+ var req request.GetChannelList
+ err := c.ShouldBindJSON(&req)
+ if err != nil {
+ response.FailWithMsg("参数错误: "+err.Error(), c)
+ return
+ }
+
+ list, total, err := channelService.GetChannelList(userId, req)
+ if err != nil {
+ global.Logger.Error("获取频道列表失败!", zap.Error(err))
+ response.FailWithMsg(err.Error(), c)
+ return
+ }
+
+ response.OkWithData(response.PageResult{
+ List: list,
+ Total: total,
+ Page: req.Current,
+ PageSize: req.PageSize,
+ }, c)
+}
+
+// GetChannelDetail 获取频道详情
+// @Tags 频道管理
+// @Summary 获取频道详情
+// @Accept application/json
+// @Produce application/json
+// @Param id query string true "频道ID"
+// @Success 200 {object} response.Response
+// @Router /radio/channel/detail [get]
+func (a *ChannelApi) GetChannelDetail(c *gin.Context) {
+ userId := auth.GetUserId(c)
+ id := c.Query("id")
+ if id == "" {
+ response.FailWithMsg("参数错误: id不能为空", c)
+ return
+ }
+
+ channel, err := channelService.GetChannelById(userId, id)
+ if err != nil {
+ global.Logger.Error("获取频道详情失败!", zap.Error(err))
+ response.FailWithMsg(err.Error(), c)
+ return
+ }
+ response.OkWithData(channel, c)
+}
+
+// SaveChannel 保存频道
+// @Tags 频道管理
+// @Summary 保存频道
+// @Accept application/json
+// @Produce application/json
+// @Param data body request.SaveChannel true "频道信息"
+// @Success 200 {object} response.Response
+// @Router /radio/channel/save [post]
+func (a *ChannelApi) SaveChannel(c *gin.Context) {
+ var req request.SaveChannel
+ err := c.ShouldBindJSON(&req)
+ if err != nil {
+ response.FailWithMsg("参数错误: "+err.Error(), c)
+ return
+ }
+
+ if err := channelService.SaveChannel(req); err != nil {
+ global.Logger.Error("保存频道失败!", zap.Error(err))
+ response.FailWithMsg(err.Error(), c)
+ return
+ }
+
+ response.OkWithMsg("保存成功", c)
+}
+
+// UpdateChannel 更新频道
+// @Tags 频道管理
+// @Summary 更新频道
+// @Accept application/json
+// @Produce application/json
+// @Param data body request.UpdateChannel true "频道信息"
+// @Success 200 {object} response.Response
+// @Router /radio/channel/update [post]
+func (a *ChannelApi) UpdateChannel(c *gin.Context) {
+ var req request.UpdateChannel
+ err := c.ShouldBindJSON(&req)
+ if err != nil {
+ response.FailWithMsg("参数错误: "+err.Error(), c)
+ return
+ }
+
+ if err := channelService.UpdateChannel(req); err != nil {
+ global.Logger.Error("更新频道失败!", zap.Error(err))
+ response.FailWithMsg(err.Error(), c)
+ return
+ }
+
+ response.OkWithMsg("更新成功", c)
+}
+
+// DeleteChannel 删除频道
+// @Tags 频道管理
+// @Summary 删除频道
+// @Produce json
+// @Param data body common.GetById true "频道ID"
+// @Success 200 {object} response.Response
+// @Router /radio/channel/delete [post]
+func (a *ChannelApi) DeleteChannel(c *gin.Context) {
+ var req common.IdReq
+ err := c.ShouldBindJSON(&req)
+ if err != nil || req.Id == "" {
+ response.FailWithMsg("参数错误: id不能为空", c)
+ return
+ }
+
+ if err := channelService.DeleteChannel(req.Id); err != nil {
+ global.Logger.Error("删除频道失败!", zap.Error(err))
+ response.FailWithMsg(err.Error(), c)
+ return
+ }
+
+ response.OkWithMsg("删除成功", c)
+}
diff --git a/api/v1/radio/enter.go b/api/v1/radio/enter.go
new file mode 100644
index 0000000..acdf051
--- /dev/null
+++ b/api/v1/radio/enter.go
@@ -0,0 +1,21 @@
+package radio
+
+import "sundynix-go/service"
+
+type ApiGroup struct {
+ CategoryApi
+ ChannelApi
+ ProgramApi
+ SubscriptionApi
+ InteractionApi
+}
+
+var ApiGroupApp = new(ApiGroup)
+
+var (
+ categoryService = service.GroupApp.RadioServiceGroup.CategoryService
+ channelService = service.GroupApp.RadioServiceGroup.ChannelService
+ programService = service.GroupApp.RadioServiceGroup.ProgramService
+ subscriptionService = service.GroupApp.RadioServiceGroup.SubscriptionService
+ interactionService = service.GroupApp.RadioServiceGroup.InteractionService
+)
diff --git a/api/v1/radio/interaction.go b/api/v1/radio/interaction.go
new file mode 100644
index 0000000..39fe50e
--- /dev/null
+++ b/api/v1/radio/interaction.go
@@ -0,0 +1,253 @@
+package radio
+
+import (
+ "sundynix-go/global"
+ "sundynix-go/model/commom/response"
+ "sundynix-go/model/radio/request"
+ "sundynix-go/utils/auth"
+
+ "github.com/gin-gonic/gin"
+ "go.uber.org/zap"
+)
+
+type InteractionApi struct{}
+
+// AddHistory 添加收听历史
+// @Tags 用户互动
+// @Summary 添加收听历史
+// @Produce json
+// @Param data body request.AddHistory true "收听信息"
+// @Success 200 {object} response.Response
+// @Router /radio/history/add [post]
+func (a *InteractionApi) AddHistory(c *gin.Context) {
+ userId := auth.GetUserId(c)
+ var req request.AddHistory
+ err := c.ShouldBindJSON(&req)
+ if err != nil {
+ response.FailWithMsg("参数错误: "+err.Error(), c)
+ return
+ }
+
+ if err := interactionService.AddHistory(userId, req); err != nil {
+ global.Logger.Error("添加收听历史失败!", zap.Error(err))
+ response.FailWithMsg(err.Error(), c)
+ return
+ }
+
+ response.OkWithMsg("添加成功", c)
+}
+
+// GetHistoryList 获取收听历史列表
+// @Tags 用户互动
+// @Summary 获取收听历史列表
+// @Produce json
+// @Param data body request.GetHistoryList true "分页查询"
+// @Success 200 {object} response.Response
+// @Router /radio/history/list [post]
+func (a *InteractionApi) GetHistoryList(c *gin.Context) {
+ userId := auth.GetUserId(c)
+ var req request.GetHistoryList
+ err := c.ShouldBindJSON(&req)
+ if err != nil {
+ response.FailWithMsg("参数错误: "+err.Error(), c)
+ return
+ }
+
+ list, total, err := interactionService.GetHistoryList(userId, req)
+ if err != nil {
+ global.Logger.Error("获取收听历史失败!", zap.Error(err))
+ response.FailWithMsg(err.Error(), c)
+ return
+ }
+
+ response.OkWithData(response.PageResult{
+ List: list,
+ Total: total,
+ Page: req.Current,
+ }, c)
+}
+
+// ToggleLike 切换点赞状态
+// @Tags 用户互动
+// @Summary 切换点赞状态
+// @Produce json
+// @Param data body request.ToggleLike true "节目ID"
+// @Success 200 {object} response.Response
+// @Router /radio/like/toggle [post]
+func (a *InteractionApi) ToggleLike(c *gin.Context) {
+ userId := auth.GetUserId(c)
+ var req request.ToggleLike
+ err := c.ShouldBindJSON(&req)
+ if err != nil {
+ response.FailWithMsg("参数错误: "+err.Error(), c)
+ return
+ }
+
+ isLiked, err := interactionService.ToggleLike(userId, req.ProgramId)
+ if err != nil {
+ global.Logger.Error("操作失败!", zap.Error(err))
+ response.FailWithMsg(err.Error(), c)
+ return
+ }
+
+ response.OkWithData(isLiked, c)
+}
+
+// GetFavoriteList 获取收藏列表
+// @Tags 用户互动
+// @Summary 获取收藏列表
+// @Produce json
+// @Param data body request.GetFavoriteList true "分页查询"
+// @Success 200 {object} response.Response
+// @Router /radio/favorite/list [post]
+func (a *InteractionApi) GetFavoriteList(c *gin.Context) {
+ userId := auth.GetUserId(c)
+ var req request.GetFavoriteList
+ err := c.ShouldBindJSON(&req)
+ if err != nil {
+ response.FailWithMsg("参数错误: "+err.Error(), c)
+ return
+ }
+
+ list, total, err := interactionService.GetFavoriteList(userId, req)
+ if err != nil {
+ global.Logger.Error("获取收藏列表失败!", zap.Error(err))
+ response.FailWithMsg(err.Error(), c)
+ return
+ }
+
+ response.OkWithData(response.PageResult{
+ List: list,
+ Total: total,
+ Page: req.Current,
+ }, c)
+}
+
+// AddFavorite 添加收藏
+// @Tags 用户互动
+// @Summary 添加收藏
+// @Produce json
+// @Param data body request.AddFavorite true "节目ID"
+// @Success 200 {object} response.Response
+// @Router /radio/favorite/add [post]
+func (a *InteractionApi) AddFavorite(c *gin.Context) {
+ userId := auth.GetUserId(c)
+ var req request.AddFavorite
+ err := c.ShouldBindJSON(&req)
+ if err != nil {
+ response.FailWithMsg("参数错误: "+err.Error(), c)
+ return
+ }
+
+ if err := interactionService.AddFavorite(userId, req.ProgramId); err != nil {
+ global.Logger.Error("添加收藏失败!", zap.Error(err))
+ response.FailWithMsg(err.Error(), c)
+ return
+ }
+
+ response.OkWithMsg("收藏成功", c)
+}
+
+// RemoveFavorite 取消收藏
+// @Tags 用户互动
+// @Summary 取消收藏
+// @Produce json
+// @Param data body request.RemoveFavorite true "节目ID"
+// @Success 200 {object} response.Response
+// @Router /radio/favorite/remove [post]
+func (a *InteractionApi) RemoveFavorite(c *gin.Context) {
+ userId := auth.GetUserId(c)
+ var req request.RemoveFavorite
+ err := c.ShouldBindJSON(&req)
+ if err != nil {
+ response.FailWithMsg("参数错误: "+err.Error(), c)
+ return
+ }
+
+ if err := interactionService.RemoveFavorite(userId, req.ProgramId); err != nil {
+ global.Logger.Error("取消收藏失败!", zap.Error(err))
+ response.FailWithMsg(err.Error(), c)
+ return
+ }
+
+ response.OkWithMsg("取消收藏成功", c)
+}
+
+// GetCommentList 获取评论列表
+// @Tags 用户互动
+// @Summary 获取评论列表
+// @Produce json
+// @Param data body request.GetCommentList true "分页查询"
+// @Success 200 {object} response.Response
+// @Router /radio/comment/list [post]
+func (a *InteractionApi) GetCommentList(c *gin.Context) {
+ var req request.GetCommentList
+ err := c.ShouldBindJSON(&req)
+ if err != nil {
+ response.FailWithMsg("参数错误: "+err.Error(), c)
+ return
+ }
+
+ list, total, err := interactionService.GetCommentList(req.ProgramId, req)
+ if err != nil {
+ global.Logger.Error("获取评论列表失败!", zap.Error(err))
+ response.FailWithMsg(err.Error(), c)
+ return
+ }
+
+ response.OkWithData(response.PageResult{
+ List: list,
+ Total: total,
+ Page: req.Current,
+ }, c)
+}
+
+// AddComment 添加评论
+// @Tags 用户互动
+// @Summary 添加评论
+// @Produce json
+// @Param data body request.AddComment true "评论信息"
+// @Success 200 {object} response.Response
+// @Router /radio/comment/add [post]
+func (a *InteractionApi) AddComment(c *gin.Context) {
+ userId := auth.GetUserId(c)
+ var req request.AddComment
+ err := c.ShouldBindJSON(&req)
+ if err != nil {
+ response.FailWithMsg("参数错误: "+err.Error(), c)
+ return
+ }
+
+ if err := interactionService.AddComment(userId, req); err != nil {
+ global.Logger.Error("添加评论失败!", zap.Error(err))
+ response.FailWithMsg(err.Error(), c)
+ return
+ }
+
+ response.OkWithMsg("评论成功", c)
+}
+
+// DeleteComment 删除评论
+// @Tags 用户互动
+// @Summary 删除评论
+// @Produce json
+// @Param data body request.DeleteComment true "评论ID"
+// @Success 200 {object} response.Response
+// @Router /radio/comment/delete [post]
+func (a *InteractionApi) DeleteComment(c *gin.Context) {
+ userId := auth.GetUserId(c)
+ var req request.DeleteComment
+ err := c.ShouldBindJSON(&req)
+ if err != nil {
+ response.FailWithMsg("参数错误: "+err.Error(), c)
+ return
+ }
+
+ if err := interactionService.DeleteComment(userId, req.CommentId); err != nil {
+ global.Logger.Error("删除评论失败!", zap.Error(err))
+ response.FailWithMsg(err.Error(), c)
+ return
+ }
+
+ response.OkWithMsg("删除成功", c)
+}
diff --git a/api/v1/radio/program.go b/api/v1/radio/program.go
new file mode 100644
index 0000000..59f3d50
--- /dev/null
+++ b/api/v1/radio/program.go
@@ -0,0 +1,140 @@
+package radio
+
+import (
+ "sundynix-go/global"
+ common "sundynix-go/model/commom/request"
+ "sundynix-go/model/commom/response"
+ "sundynix-go/model/radio/request"
+
+ "github.com/gin-gonic/gin"
+ "go.uber.org/zap"
+)
+
+type ProgramApi struct{}
+
+// GetProgramList 获取节目列表
+// @Tags 节目管理
+// @Summary 获取节目列表
+// @Produce application/json
+// @Param data body request.GetProgramList true "分页查询"
+// @Success 200 {object} response.Response
+// @Router /radio/program/list [post]
+func (a *ProgramApi) GetProgramList(c *gin.Context) {
+ var req request.GetProgramList
+ err := c.ShouldBindJSON(&req)
+ if err != nil {
+ response.FailWithMsg("参数错误: "+err.Error(), c)
+ return
+ }
+
+ list, total, err := programService.GetProgramList(req)
+ if err != nil {
+ global.Logger.Error("获取节目列表失败!", zap.Error(err))
+ response.FailWithMsg(err.Error(), c)
+ return
+ }
+
+ response.OkWithData(response.PageResult{
+ List: list,
+ Total: total,
+ Page: req.Current,
+ PageSize: req.PageSize,
+ }, c)
+}
+
+// GetProgramDetail 获取节目详情
+// @Tags 节目管理
+// @Summary 获取节目详情
+// @Produce application/json
+// @Param id query string true "节目ID"
+// @Success 200 {object} response.Response
+// @Router /radio/program/detail [get]
+func (a *ProgramApi) GetProgramDetail(c *gin.Context) {
+ id := c.Query("id")
+ if id == "" {
+ response.FailWithMsg("参数错误: id不能为空", c)
+ return
+ }
+ program, err := programService.GetProgramById(id)
+ if err != nil {
+ global.Logger.Error("获取节目详情失败!", zap.Error(err))
+ response.FailWithMsg(err.Error(), c)
+ return
+ }
+
+ response.OkWithData(program, c)
+}
+
+// SaveProgram 保存节目
+// @Tags 节目管理
+// @Summary 保存节目
+// @Accept application/json
+// @Produce application/json
+// @Param data body request.SaveProgram true "节目信息"
+// @Success 200 {object} response.Response
+// @Router /radio/program/save [post]
+func (a *ProgramApi) SaveProgram(c *gin.Context) {
+ var req request.SaveProgram
+ err := c.ShouldBindJSON(&req)
+ if err != nil {
+ response.FailWithMsg("参数错误: "+err.Error(), c)
+ return
+ }
+
+ if err := programService.SaveProgram(req); err != nil {
+ global.Logger.Error("保存节目失败!", zap.Error(err))
+ response.FailWithMsg(err.Error(), c)
+ return
+ }
+
+ response.OkWithMsg("保存成功", c)
+}
+
+// UpdateProgram 更新节目
+// @Tags 节目管理
+// @Summary 更新节目
+// @Accept application/json
+// @Produce application/json
+// @Param data body request.UpdateProgram true "节目信息"
+// @Success 200 {object} response.Response
+// @Router /radio/program/update [post]
+func (a *ProgramApi) UpdateProgram(c *gin.Context) {
+ var req request.UpdateProgram
+ err := c.ShouldBindJSON(&req)
+ if err != nil {
+ response.FailWithMsg("参数错误: "+err.Error(), c)
+ return
+ }
+
+ if err := programService.UpdateProgram(req); err != nil {
+ global.Logger.Error("更新节目失败!", zap.Error(err))
+ response.FailWithMsg(err.Error(), c)
+ return
+ }
+
+ response.OkWithMsg("更新成功", c)
+}
+
+// DeleteProgram 删除节目
+// @Tags 节目管理
+// @Summary 删除节目
+// @Produce json
+// @Param data body common.GetById true "节目ID"
+// @Success 200 {object} response.Response
+// @Router /radio/program/delete [post]
+func (a *ProgramApi) DeleteProgram(c *gin.Context) {
+ var req common.IdsReq
+ err := c.ShouldBindJSON(&req)
+ if err != nil {
+ response.FailWithMsg("参数错误: id不能为空", c)
+ return
+ }
+
+ if err := programService.DeleteProgram(req.Ids); err != nil {
+ global.Logger.Error("删除节目失败!", zap.Error(err))
+ response.FailWithMsg(err.Error(), c)
+ return
+ }
+
+ response.OkWithMsg("删除成功", c)
+}
diff --git a/api/v1/radio/subscription.go b/api/v1/radio/subscription.go
new file mode 100644
index 0000000..a824ce7
--- /dev/null
+++ b/api/v1/radio/subscription.go
@@ -0,0 +1,134 @@
+package radio
+
+import (
+ "sundynix-go/global"
+ common "sundynix-go/model/commom/request"
+ "sundynix-go/model/commom/response"
+ "sundynix-go/model/radio/request"
+ "sundynix-go/utils/auth"
+
+ "github.com/gin-gonic/gin"
+ "go.uber.org/zap"
+)
+
+type SubscriptionApi struct{}
+
+// GetSubscriptionList 获取订阅列表
+// @Tags 订阅管理
+// @Summary 获取我的订阅列表
+// @Accept application/json
+// @Produce application/json
+// @Param data body request.GetSubscriptionList true "分页查询"
+// @Success 200 {object} response.Response
+// @Router /radio/subscription/list [post]
+func (a *SubscriptionApi) GetSubscriptionList(c *gin.Context) {
+ userId := auth.GetUserId(c)
+ var req common.PageInfo
+ err := c.ShouldBindJSON(&req)
+ if err != nil {
+ response.FailWithMsg("参数错误: "+err.Error(), c)
+ return
+ }
+
+ list, total, err := subscriptionService.GetUserSubscription(userId, req)
+ if err != nil {
+ global.Logger.Error("获取订阅列表失败!", zap.Error(err))
+ response.FailWithMsg(err.Error(), c)
+ return
+ }
+
+ response.OkWithData(response.PageResult{
+ List: list,
+ Total: total,
+ Page: req.Current,
+ }, c)
+}
+
+// CanSubscribe 检查是否可以订阅
+// @Tags 订阅管理
+// @Summary 检查是否可以订阅
+// @Produce application/json
+// @Param data body request.SubscribeChannel true "频道ID"
+// @Success 200 {object} response.Response
+// @Router /radio/subscription/can-subscribe [post]
+func (a *SubscriptionApi) CanSubscribe(c *gin.Context) {
+ userId := auth.GetUserId(c)
+ var req request.SubscribeChannel
+ err := c.ShouldBindJSON(&req)
+ if err != nil {
+ response.FailWithMsg("参数错误: "+err.Error(), c)
+ return
+ }
+
+ can, _, err := subscriptionService.CanSubscribe(userId, req.ChannelId)
+ if err != nil {
+ global.Logger.Error("检查订阅权限失败!", zap.Error(err))
+ response.FailWithMsg(err.Error(), c)
+ return
+ }
+
+ response.OkWithData(can, c)
+}
+
+// Subscribe 订阅频道
+// @Tags 订阅管理
+// @Summary 订阅频道
+// @Produce application/json
+// @Param data body request.SubscribeChannel true "频道ID"
+// @Success 200 {object} response.Response
+// @Router /radio/subscription/subscribe [post]
+func (a *SubscriptionApi) Subscribe(c *gin.Context) {
+ userId := auth.GetUserId(c)
+ var req request.SubscribeChannel
+ err := c.ShouldBindJSON(&req)
+ if err != nil {
+ response.FailWithMsg("参数错误: "+err.Error(), c)
+ return
+ }
+
+ can, reason, err := subscriptionService.CanSubscribe(userId, req.ChannelId)
+ if err != nil {
+ global.Logger.Error("订阅失败!", zap.Error(err))
+ response.FailWithMsg(err.Error(), c)
+ return
+ }
+
+ if !can {
+ response.FailWithMsg(reason, c)
+ return
+ }
+
+ // 订阅类型 1:免费
+ if err := subscriptionService.Subscribe(userId, req.ChannelId, 1); err != nil {
+ global.Logger.Error("订阅失败!", zap.Error(err))
+ response.FailWithMsg(err.Error(), c)
+ return
+ }
+
+ response.OkWithMsg("订阅成功", c)
+}
+
+// Unsubscribe 退订频道
+// @Tags 订阅管理
+// @Summary 退订频道
+// @Produce application/json
+// @Param data body request.UnsubscribeChannel true "频道ID"
+// @Success 200 {object} response.Response
+// @Router /radio/subscription/unsubscribe [post]
+func (a *SubscriptionApi) Unsubscribe(c *gin.Context) {
+ userId := auth.GetUserId(c)
+ var req request.UnsubscribeChannel
+ err := c.ShouldBindJSON(&req)
+ if err != nil {
+ response.FailWithMsg("参数错误: "+err.Error(), c)
+ return
+ }
+
+ if err := subscriptionService.Unsubscribe(userId, req.ChannelId); err != nil {
+ global.Logger.Error("退订失败!", zap.Error(err))
+ response.FailWithMsg(err.Error(), c)
+ return
+ }
+
+ response.OkWithMsg("退订成功", c)
+}
diff --git a/api/v1/system/sys_client.go b/api/v1/system/sys_client.go
index 3aea782..9da4bf3 100644
--- a/api/v1/system/sys_client.go
+++ b/api/v1/system/sys_client.go
@@ -17,7 +17,7 @@ type ClientApi struct {
// SaveClient
// @Tags 客户端管理
// @Summary 创建client
-// @Security ApiKeyAuth
+// @Security BasicAuth
// @accept application/json
// @Produce application/json
// @Param data body system.Client true "client"
@@ -42,7 +42,7 @@ func (s *ClientApi) SaveClient(c *gin.Context) {
// UpdateClient
// @Tags 客户端管理
// @Summary 更新client
-// @Security ApiKeyAuth
+// @Security BasicAuth
// @accept application/json
// @Produce application/json
// @Param data body system.Client true "client"
@@ -67,7 +67,7 @@ func (s *ClientApi) UpdateClient(c *gin.Context) {
// GetClientList
// @Tags 客户端管理
// @Summary 获取client列表
-// @Security ApiKeyAuth
+// @Security BasicAuth
// @accept application/json
// @Produce application/json
// @Param data body systemReq.GetClientList true "client"
@@ -97,7 +97,7 @@ func (s *ClientApi) GetClientList(c *gin.Context) {
// Delete
// @Tags 客户端管理
// @Summary 删除client
-// @Security ApiKeyAuth
+// @Security BasicAuth
// @accept application/json
// @Produce application/json
// @Param data body request.IdsReq true "ids"
@@ -123,7 +123,7 @@ func (s *ClientApi) Delete(c *gin.Context) {
// @Tags 客户端管理
// @Summary 获取client详情
// @Description id获取详情
-// @Security ApiKeyAuth
+// @Security BasicAuth
// @Produce application/json
// @Param id query string true "id"
// @Success 200 {object} response.Response{data=system.Client,msg=string} "获取client详情"
diff --git a/api/v1/system/sys_menu.go b/api/v1/system/sys_menu.go
index e5dbe2c..7d1c0b6 100644
--- a/api/v1/system/sys_menu.go
+++ b/api/v1/system/sys_menu.go
@@ -17,7 +17,7 @@ type MenuApi struct {
// SaveMenu
// @Tags 菜单管理
// @Summary 新增菜单
-// @Security ApiKeyAuth
+// @Security BasicAuth
// @accept application/json
// @Produce application/json
// @Param data body system.Menu false "menu"
@@ -42,7 +42,7 @@ func (m *MenuApi) SaveMenu(c *gin.Context) {
// UpdateMenu
// @Tags 菜单管理
// @Summary 更新菜单
-// @Security ApiKeyAuth
+// @Security BasicAuth
// @accept application/json
// @Produce application/json
// @Param data body system.Menu false "menu"
@@ -68,7 +68,7 @@ func (m *MenuApi) UpdateMenu(c *gin.Context) {
// @Tags 菜单管理
// @Summary 删除menu
// @Description 删除menu
-// @Security ApiKeyAuth
+// @Security BasicAuth
// @Produce application/json
// @Param id query string true "id"
// @Success 200 {object} response.Response{msg=string} "详情"
@@ -88,7 +88,7 @@ func (m *MenuApi) DeleteMenu(c *gin.Context) {
// @Tags 菜单管理
// @Summary 获取menu详情
// @Description id获取详情
-// @Security ApiKeyAuth
+// @Security BasicAuth
// @Produce application/json
// @Param id query string true "id"
// @Success 200 {object} response.Response{data=system.Menu,msg=string} "详情"
@@ -107,7 +107,7 @@ func (m *MenuApi) Detail(c *gin.Context) {
// GetAllMenuTree
// @Tags 菜单管理
// @Summary 获取所有菜单树
-// @Security ApiKeyAuth
+// @Security BasicAuth
// @Accept json
// @Produce json
// @Param data body systemReq.GetMenuTree true "菜单信息"
@@ -132,7 +132,7 @@ func (m *MenuApi) GetAllMenuTree(c *gin.Context) {
// GetUserMenuTree
// @Tags 菜单管理
// @Summary 用户菜单数据
-// @Security ApiKeyAuth
+// @Security BasicAuth
// @Produce json
// @Success 200 {object} response.Response{data=[]system.Menu,msg=string} "用户菜单数据"
// @Router /menu/getUserMenuTree [get]
@@ -150,7 +150,7 @@ func (m *MenuApi) GetUserMenuTree(c *gin.Context) {
// Route
// @Tags 菜单管理
// @Summary 用户路由
-// @Security ApiKeyAuth
+// @Security BasicAuth
// @Produce json
// @Success 200 {object} response.Response{data=[]system.Menu,msg=string} "用户route"
// @Router /menu/route [get]
diff --git a/api/v1/system/sys_role.go b/api/v1/system/sys_role.go
index c08bdca..58965ee 100644
--- a/api/v1/system/sys_role.go
+++ b/api/v1/system/sys_role.go
@@ -17,7 +17,7 @@ type RoleApi struct {
// SaveRole
// @tags 角色管理
// @Summary 创建角色
-// @Security ApiKeyAuth
+// @Security BasicAuth
// @accept json
// @Produce json
// @Param data body system.Role true "角色信息"
@@ -42,7 +42,7 @@ func (a *RoleApi) SaveRole(context *gin.Context) {
// UpdateRole
// @tags 角色管理
// @Summary 修改角色
-// @Security ApiKeyAuth
+// @Security BasicAuth
// @accept application/json
// @Produce application/json
// @Param data body system.Role true "角色ID"
@@ -121,7 +121,7 @@ func (a *RoleApi) Delete(context *gin.Context) {
// Detail
// @Tags 角色管理
// @Summary 角色详情
-// @Security ApiKeyAuth
+// @Security BasicAuth
// @Produce application/json
// @Param id query string true "id"
// @Success 200 {object} response.Response{data=system.Role} "角色详情"
@@ -140,7 +140,7 @@ func (a *RoleApi) Detail(context *gin.Context) {
// GrantMenu
// @tags 角色管理
// @Summary 授权菜单给角色
-// @Security ApiKeyAuth
+// @Security BasicAuth
// @accept application/json
// @Produce application/json
// @Param data body systemreq.GrantMenu true "授权菜单给角色"
diff --git a/api/v1/system/sys_user.go b/api/v1/system/sys_user.go
index c0f6824..b133e83 100644
--- a/api/v1/system/sys_user.go
+++ b/api/v1/system/sys_user.go
@@ -18,7 +18,7 @@ type UserApi struct {
// CurrentUser
// @tags 用户管理
// @Summary 当前登录用户
-// @Security ApiKeyAuth
+// @Security BasicAuth
// @Produce json
// @Success 200 {object} response.Response "{"code": 200, "data": {}, "msg": "添加成功"}"
// @Router /user/info [get]
@@ -36,7 +36,7 @@ func (u *UserApi) CurrentUser(c *gin.Context) {
// SaveUser
// @tags 用户管理
// @Summary 新增用户
-// @Security ApiKeyAuth
+// @Security BasicAuth
// @accept json
// @Produce json
// @Param data body system.User true "用户信息"
@@ -60,7 +60,7 @@ func (u *UserApi) SaveUser(c *gin.Context) {
// UpdateUser
// @tags 用户管理
// @Summary 更新用户
-// @Security ApiKeyAuth
+// @Security BasicAuth
// @accept application/json
// @Produce application/json
// @Param data body system.User true "用户ID,用户信息"
@@ -84,7 +84,7 @@ func (u *UserApi) UpdateUser(c *gin.Context) {
// GetUserList
// @tags 用户管理
// @Summary 获取用户列表
-// @Security ApiKeyAuth
+// @Security BasicAuth
// @accept application/json
// @Produce application/json
// @Param data body systemReq.GetUserList true "页码, 每页大小, 搜索条件"
@@ -114,7 +114,7 @@ func (u *UserApi) GetUserList(c *gin.Context) {
// Delete
// @Tags 用户管理
// @Summary 删除用户
-// @Security ApiKeyAuth
+// @Security BasicAuth
// @accept application/json
// @Produce application/json
// @Param data body request.IdsReq true "批量删除用户"
@@ -139,7 +139,7 @@ func (u *UserApi) Delete(c *gin.Context) {
// Detail
// @Tags 用户管理
// @Summary 获取用户详情
-// @Security ApiKeyAuth
+// @Security BasicAuth
// @Produce application/json
// @Param id query string true "id"
// @Success 200 {object} response.Response{data=system.User} "获取用户详情成功"
@@ -158,7 +158,7 @@ func (u *UserApi) Detail(c *gin.Context) {
// ChangePassword
// @Tags 用户管理
// @Summary 修改密码
-// @Security ApiKeyAuth
+// @Security BasicAuth
// @Description 修改密码
// @accept json
// @Produce application/json
@@ -184,7 +184,7 @@ func (u *UserApi) ChangePassword(c *gin.Context) {
// GrantRole
// @Tags 用户管理
// @Summary 给用户分配角色
-// @Security ApiKeyAuth
+// @Security BasicAuth
// @accept application/json
// @Produce application/json
// @Param data body systemReq.GrantRole true "用户ID, 角色ID"
diff --git a/config-dev.yaml b/config-dev.yaml
index e2a7909..60f2690 100644
--- a/config-dev.yaml
+++ b/config-dev.yaml
@@ -17,11 +17,6 @@ mini-program:
app-id: wxb463820bf36dd5d6
app-secret: 731784a74c76c6d31fa00bb847af2c7d
-# 服务号
-service-account:
- app-id: wxc236cddde8e7f863
- app-secret: 26c1fcecfc98a748d8916355623c975c
-
# 微信支付
wechat-pay:
mch-id: 1735188493 # 商户号
@@ -37,8 +32,8 @@ minio:
access-key-id: qP5QXP3g6Axw1hkwX21Y
access-key-secret: sddT6J3S6yDn9m1wfth0pzelPg9KWmbHjMAUF5S9
base-path: ""
- bucket-name: sundynix-audios
- bucket-url: https://res.sundynix.cn/sundynix-audios
+ bucket-name: sundynix-radio
+ bucket-url: https://res.sundynix.cn/sundynix-radio
endpoint: 129.28.103.17:3407
use-ssl: false
@@ -46,7 +41,7 @@ rocket-mq:
name-space: 192.168.100.140:9876
endpoint: 192.168.100.140:8081 # 5.x版本使用了proxy 默认proxy地址是8081
consumer-group: sundynix-radio
- topic: sundynix-radio-audio-generate
+ topic: sundynix-radio-generate
access-key: ""
secret-key: ""
enable-ssl: false
diff --git a/config/config.go b/config/config.go
index 7e7d181..d131e8c 100644
--- a/config/config.go
+++ b/config/config.go
@@ -13,7 +13,6 @@ type Config struct {
RocketMQConfig RocketMQConfig `mapstructure:"rocket-mq" json:"rocket-mq" yaml:"rocket-mq"`
TencentCOS TencentCOS `mapstructure:"tencent-cos" json:"tencent-cos" yaml:"tencent-cos"`
- MiniProgram MiniProgram `mapstructure:"mini-program" json:"mini-program" yaml:"mini-program"` //小程序
- ServiceAccount ServiceAccount `mapstructure:"service-account" json:"service-account" yaml:"service-account"` //服务号
- WechatPay WechatPay `mapstructure:"wechat-pay" json:"wechat-pay" yaml:"wechat-pay"` //微信支付
+ MiniProgram MiniProgram `mapstructure:"mini-program" json:"mini-program" yaml:"mini-program"` //小程序
+ WechatPay WechatPay `mapstructure:"wechat-pay" json:"wechat-pay" yaml:"wechat-pay"` //微信支付
}
diff --git a/config/constans.go b/config/constans.go
deleted file mode 100644
index 1ce60ba..0000000
--- a/config/constans.go
+++ /dev/null
@@ -1,22 +0,0 @@
-package config
-
-// ActionType 定义养护行为类型
-type ActionType string
-
-const (
- ActionWater ActionType = "WATER" // 浇水
- ActionFertilize ActionType = "FERTILIZE" // 施肥
- ActionPrune ActionType = "PRUNE" // 修剪
- ActionPhoto ActionType = "PHOTO" // 拍照
- ActionLogin ActionType = "LOGIN" // 每日签到
-)
-
-// BadgeTier 定义徽章的稀有度
-type BadgeTier int
-
-const (
- TierBronze BadgeTier = 1 // 铜
- TierSilver BadgeTier = 2 // 银
- TierGold BadgeTier = 3 // 金
- TierDiamond BadgeTier = 4 // 钻石
-)
diff --git a/config/service_account.go b/config/service_account.go
deleted file mode 100644
index 3194e2c..0000000
--- a/config/service_account.go
+++ /dev/null
@@ -1,6 +0,0 @@
-package config
-
-type ServiceAccount struct {
- AppId string `mapstructure:"app-id" json:"app-id" yaml:"app-id"`
- AppSecret string `mapstructure:"app-secret" json:"app-secret" yaml:"app-secret"`
-}
diff --git a/docs/docs.go b/docs/docs.go
index 010eaca..55203da 100644
--- a/docs/docs.go
+++ b/docs/docs.go
@@ -244,104 +244,6 @@ const docTemplate = `{
}
}
},
- "/classify/myClassifyLog": {
- "post": {
- "security": [
- {
- "ApiKeyAuth": []
- }
- ],
- "consumes": [
- "application/json"
- ],
- "produces": [
- "application/json"
- ],
- "tags": [
- "识别相关"
- ],
- "summary": "我的植物识别记录",
- "parameters": [
- {
- "description": "分页",
- "name": "data",
- "in": "body",
- "required": true,
- "schema": {
- "$ref": "#/definitions/request.PageInfo"
- }
- }
- ],
- "responses": {
- "200": {
- "description": "识别记录",
- "schema": {
- "allOf": [
- {
- "$ref": "#/definitions/response.Response"
- },
- {
- "type": "object",
- "properties": {
- "msg": {
- "type": "string"
- }
- }
- }
- ]
- }
- }
- }
- }
- },
- "/classify/plant": {
- "post": {
- "security": [
- {
- "ApiKeyAuth": []
- }
- ],
- "consumes": [
- "multipart/form-data"
- ],
- "produces": [
- "application/json"
- ],
- "tags": [
- "识别相关"
- ],
- "summary": "base64植物识别",
- "parameters": [
- {
- "type": "file",
- "description": "植物识别",
- "name": "file",
- "in": "formData",
- "required": true
- }
- ],
- "responses": {
- "200": {
- "description": "文件OCR",
- "schema": {
- "allOf": [
- {
- "$ref": "#/definitions/response.Response"
- },
- {
- "type": "object",
- "properties": {
- "msg": {
- "type": "string"
- }
- }
- }
- ]
- }
- }
- }
- }
- },
"/client/delete": {
"post": {
"security": [
@@ -594,305 +496,6 @@ const docTemplate = `{
}
}
},
- "/config/badge/add": {
- "post": {
- "security": [
- {
- "BearerAuth": []
- }
- ],
- "consumes": [
- "application/json"
- ],
- "produces": [
- "application/json"
- ],
- "tags": [
- "徽章配置"
- ],
- "summary": "添加徽章配置",
- "parameters": [
- {
- "description": "添加徽章配置",
- "name": "data",
- "in": "body",
- "required": true,
- "schema": {
- "$ref": "#/definitions/request.CreateBadge"
- }
- }
- ],
- "responses": {
- "200": {
- "description": "{\"success\":true,\"data\":{},\"msg\":\"添加成功\"}",
- "schema": {
- "type": "string"
- }
- }
- }
- }
- },
- "/config/badge/delete": {
- "get": {
- "security": [
- {
- "BearerAuth": []
- }
- ],
- "produces": [
- "application/json"
- ],
- "tags": [
- "徽章配置"
- ],
- "summary": "删除徽章配置",
- "parameters": [
- {
- "type": "string",
- "description": "id",
- "name": "id",
- "in": "query",
- "required": true
- }
- ],
- "responses": {
- "200": {
- "description": "{\"success\":true,\"data\":{},\"msg\":\"删除成功\"}",
- "schema": {
- "type": "string"
- }
- }
- }
- }
- },
- "/config/badge/find": {
- "get": {
- "security": [
- {
- "BearerAuth": []
- }
- ],
- "produces": [
- "application/json"
- ],
- "tags": [
- "徽章配置"
- ],
- "summary": "根据ID获取徽章配置",
- "parameters": [
- {
- "type": "string",
- "description": "id",
- "name": "id",
- "in": "query",
- "required": true
- }
- ],
- "responses": {
- "200": {
- "description": "{\"success\":true,\"data\":{},\"msg\":\"获取成功\"}",
- "schema": {
- "type": "string"
- }
- }
- }
- }
- },
- "/config/badge/tree": {
- "get": {
- "security": [
- {
- "BearerAuth": []
- }
- ],
- "produces": [
- "application/json"
- ],
- "tags": [
- "徽章配置"
- ],
- "summary": "获取徽章配置树形结构",
- "responses": {
- "200": {
- "description": "{\"success\":true,\"data\":{},\"msg\":\"获取成功\"}",
- "schema": {
- "type": "string"
- }
- }
- }
- }
- },
- "/config/badge/update": {
- "post": {
- "security": [
- {
- "BearerAuth": []
- }
- ],
- "consumes": [
- "application/json"
- ],
- "produces": [
- "application/json"
- ],
- "tags": [
- "徽章配置"
- ],
- "summary": "更新徽章配置",
- "parameters": [
- {
- "description": "更新参数",
- "name": "data",
- "in": "body",
- "required": true,
- "schema": {
- "$ref": "#/definitions/request.UpdateBadge"
- }
- }
- ],
- "responses": {
- "200": {
- "description": "{\"success\":true,\"data\":{},\"msg\":\"更新成功\"}",
- "schema": {
- "type": "string"
- }
- }
- }
- }
- },
- "/config/level/add": {
- "post": {
- "security": [
- {
- "BearerAuth": []
- }
- ],
- "consumes": [
- "application/json"
- ],
- "produces": [
- "application/json"
- ],
- "tags": [
- "等级配置"
- ],
- "summary": "添加等级配置",
- "parameters": [
- {
- "description": "添加等级配置",
- "name": "data",
- "in": "body",
- "required": true,
- "schema": {
- "$ref": "#/definitions/request.CreateLevelConf"
- }
- }
- ],
- "responses": {
- "200": {
- "description": "{\"success\":true,\"data\":{},\"msg\":\"添加成功\"}",
- "schema": {
- "type": "string"
- }
- }
- }
- }
- },
- "/config/level/detail": {
- "get": {
- "security": [
- {
- "BearerAuth": []
- }
- ],
- "produces": [
- "application/json"
- ],
- "tags": [
- "等级配置"
- ],
- "summary": "等级配置详情",
- "parameters": [
- {
- "type": "string",
- "description": "等级配置id",
- "name": "id",
- "in": "query",
- "required": true
- }
- ],
- "responses": {
- "200": {
- "description": "{\"success\":true,\"data\":{},\"msg\":\"查询成功\"}",
- "schema": {
- "type": "string"
- }
- }
- }
- }
- },
- "/config/level/list": {
- "get": {
- "security": [
- {
- "BearerAuth": []
- }
- ],
- "produces": [
- "application/json"
- ],
- "tags": [
- "等级配置"
- ],
- "summary": "等级配置列表",
- "responses": {
- "200": {
- "description": "{\"success\":true,\"data\":{},\"msg\":\"查询成功\"}",
- "schema": {
- "type": "string"
- }
- }
- }
- }
- },
- "/config/level/update": {
- "post": {
- "security": [
- {
- "BearerAuth": []
- }
- ],
- "consumes": [
- "application/json"
- ],
- "produces": [
- "application/json"
- ],
- "tags": [
- "等级配置"
- ],
- "summary": "修改等级配置",
- "parameters": [
- {
- "description": "修改等级配置",
- "name": "data",
- "in": "body",
- "required": true,
- "schema": {
- "$ref": "#/definitions/request.UpdateLevelConf"
- }
- }
- ],
- "responses": {
- "200": {
- "description": "{\"success\":true,\"data\":{},\"msg\":\"修改成功\"}",
- "schema": {
- "type": "string"
- }
- }
- }
- }
- },
"/menu/delete": {
"get": {
"security": [
@@ -1419,657 +1022,6 @@ const docTemplate = `{
}
}
},
- "/plant/add": {
- "post": {
- "security": [
- {
- "BearerAuth": []
- }
- ],
- "consumes": [
- "application/json"
- ],
- "produces": [
- "application/json"
- ],
- "tags": [
- "我的植物"
- ],
- "summary": "添加植物",
- "parameters": [
- {
- "description": "创建植物",
- "name": "data",
- "in": "body",
- "required": true,
- "schema": {
- "$ref": "#/definitions/request.CreateMyPlant"
- }
- }
- ],
- "responses": {
- "200": {
- "description": "{\"success\":true,\"data\":{},\"msg\":\"添加成功\"}",
- "schema": {
- "type": "string"
- }
- }
- }
- }
- },
- "/plant/completeTask": {
- "post": {
- "security": [
- {
- "BearerAuth": []
- }
- ],
- "consumes": [
- "application/json"
- ],
- "produces": [
- "application/json"
- ],
- "tags": [
- "我的植物"
- ],
- "summary": "完成任务",
- "parameters": [
- {
- "description": "完成任务",
- "name": "data",
- "in": "body",
- "required": true,
- "schema": {
- "$ref": "#/definitions/request.CompleteTask"
- }
- }
- ],
- "responses": {
- "200": {
- "description": "{\"success\":true,\"data\":{},\"msg\":\"完成任务\"}",
- "schema": {
- "type": "string"
- }
- }
- }
- }
- },
- "/plant/deletePlan": {
- "post": {
- "security": [
- {
- "BearerAuth": []
- }
- ],
- "consumes": [
- "application/json"
- ],
- "produces": [
- "application/json"
- ],
- "tags": [
- "我的植物"
- ],
- "summary": "删除任务",
- "parameters": [
- {
- "description": "删除植物",
- "name": "data",
- "in": "body",
- "required": true,
- "schema": {
- "$ref": "#/definitions/request.IdsReq"
- }
- }
- ],
- "responses": {
- "200": {
- "description": "{\"success\":true,\"data\":{},\"msg\":\"删除成功\"}",
- "schema": {
- "type": "string"
- }
- }
- }
- }
- },
- "/plant/deletePlant": {
- "post": {
- "security": [
- {
- "BearerAuth": []
- }
- ],
- "consumes": [
- "application/json"
- ],
- "produces": [
- "application/json"
- ],
- "tags": [
- "我的植物"
- ],
- "summary": "删除植物",
- "parameters": [
- {
- "description": "删除植物",
- "name": "data",
- "in": "body",
- "required": true,
- "schema": {
- "$ref": "#/definitions/request.IdsReq"
- }
- }
- ],
- "responses": {
- "200": {
- "description": "{\"success\":true,\"data\":{},\"msg\":\"删除成功\"}",
- "schema": {
- "type": "string"
- }
- }
- }
- }
- },
- "/plant/detail": {
- "get": {
- "security": [
- {
- "BearerAuth": []
- }
- ],
- "produces": [
- "application/json"
- ],
- "tags": [
- "我的植物"
- ],
- "summary": "ById植物详情",
- "parameters": [
- {
- "type": "string",
- "description": "id",
- "name": "id",
- "in": "query",
- "required": true
- }
- ],
- "responses": {
- "200": {
- "description": "{\"success\":true,\"data\":{},\"msg\":\"获取ById成功\"}",
- "schema": {
- "type": "string"
- }
- }
- }
- }
- },
- "/plant/growth/add": {
- "post": {
- "security": [
- {
- "BearerAuth": []
- }
- ],
- "consumes": [
- "application/json"
- ],
- "produces": [
- "application/json"
- ],
- "tags": [
- "我的植物"
- ],
- "summary": "添加成长记录",
- "parameters": [
- {
- "description": "添加成长记录",
- "name": "data",
- "in": "body",
- "required": true,
- "schema": {
- "$ref": "#/definitions/request.CreateGrowthRecord"
- }
- }
- ],
- "responses": {
- "200": {
- "description": "{\"success\":true,\"data\":{},\"msg\":\"添加成功\"}",
- "schema": {
- "type": "string"
- }
- }
- }
- }
- },
- "/plant/page": {
- "post": {
- "security": [
- {
- "BearerAuth": []
- }
- ],
- "consumes": [
- "application/json"
- ],
- "produces": [
- "application/json"
- ],
- "tags": [
- "我的植物"
- ],
- "summary": "植物列表",
- "parameters": [
- {
- "description": "分页获取植物列表",
- "name": "data",
- "in": "body",
- "required": true,
- "schema": {
- "$ref": "#/definitions/request.PageInfo"
- }
- }
- ],
- "responses": {
- "200": {
- "description": "{\"success\":true,\"data\":{},\"msg\":\"获取成功\"}",
- "schema": {
- "type": "string"
- }
- }
- }
- }
- },
- "/plant/plan/add": {
- "post": {
- "security": [
- {
- "BearerAuth": []
- }
- ],
- "consumes": [
- "application/json"
- ],
- "produces": [
- "application/json"
- ],
- "tags": [
- "我的植物"
- ],
- "summary": "添加养护事项",
- "parameters": [
- {
- "description": "添加养护事项",
- "name": "data",
- "in": "body",
- "required": true,
- "schema": {
- "$ref": "#/definitions/request.CreateCarePlan"
- }
- }
- ],
- "responses": {
- "200": {
- "description": "{\"success\":true,\"data\":{},\"msg\":\"添加成功\"}",
- "schema": {
- "type": "string"
- }
- }
- }
- }
- },
- "/plant/plan/delete": {
- "get": {
- "security": [
- {
- "BearerAuth": []
- }
- ],
- "produces": [
- "application/json"
- ],
- "tags": [
- "我的植物"
- ],
- "summary": "删除养护事项",
- "parameters": [
- {
- "type": "string",
- "description": "id",
- "name": "id",
- "in": "query",
- "required": true
- }
- ],
- "responses": {
- "200": {
- "description": "{\"success\":true,\"data\":{},\"msg\":\"删除成功\"}",
- "schema": {
- "type": "string"
- }
- }
- }
- }
- },
- "/plant/todayTask": {
- "get": {
- "security": [
- {
- "BearerAuth": []
- }
- ],
- "consumes": [
- "application/json"
- ],
- "produces": [
- "application/json"
- ],
- "tags": [
- "我的植物"
- ],
- "summary": "今日任务",
- "responses": {
- "200": {
- "description": "{\"success\":true,\"data\":{},\"msg\":\"获取成功\"}",
- "schema": {
- "type": "string"
- }
- }
- }
- }
- },
- "/plant/update": {
- "post": {
- "security": [
- {
- "BearerAuth": []
- }
- ],
- "consumes": [
- "application/json"
- ],
- "produces": [
- "application/json"
- ],
- "tags": [
- "我的植物"
- ],
- "summary": "修改ById植物",
- "parameters": [
- {
- "description": "修改ById植物",
- "name": "data",
- "in": "body",
- "required": true,
- "schema": {
- "$ref": "#/definitions/request.UpdateMyPlant"
- }
- }
- ],
- "responses": {
- "200": {
- "description": "{\"success\":true,\"data\":{},\"msg\":\"修改ById成功\"}",
- "schema": {
- "type": "string"
- }
- }
- }
- }
- },
- "/post/comment": {
- "post": {
- "security": [
- {
- "BearerAuth": []
- }
- ],
- "consumes": [
- "application/json"
- ],
- "produces": [
- "application/json"
- ],
- "tags": [
- "帖子"
- ],
- "summary": "评论帖子",
- "parameters": [
- {
- "description": "评论帖子",
- "name": "data",
- "in": "body",
- "required": true,
- "schema": {
- "$ref": "#/definitions/request.CreateComment"
- }
- }
- ],
- "responses": {
- "200": {
- "description": "{\"success\":true,\"data\":{},\"msg\":\"评论成功\"}",
- "schema": {
- "type": "string"
- }
- }
- }
- }
- },
- "/post/like": {
- "get": {
- "security": [
- {
- "BearerAuth": []
- }
- ],
- "produces": [
- "application/json"
- ],
- "tags": [
- "帖子"
- ],
- "summary": "点赞帖子",
- "parameters": [
- {
- "type": "string",
- "description": "帖子id",
- "name": "id",
- "in": "query",
- "required": true
- },
- {
- "type": "string",
- "description": "点赞类型 1 点赞 2 取消点赞",
- "name": "type",
- "in": "query",
- "required": true
- }
- ],
- "responses": {
- "200": {
- "description": "{\"success\":true,\"data\":{},\"msg\":\"点赞成功\"}",
- "schema": {
- "type": "string"
- }
- }
- }
- }
- },
- "/post/myPost": {
- "post": {
- "security": [
- {
- "BearerAuth": []
- }
- ],
- "consumes": [
- "application/json"
- ],
- "produces": [
- "application/json"
- ],
- "tags": [
- "帖子"
- ],
- "summary": "我的发布",
- "parameters": [
- {
- "description": "分页获取帖子列表",
- "name": "data",
- "in": "body",
- "required": true,
- "schema": {
- "$ref": "#/definitions/request.PostPage"
- }
- }
- ],
- "responses": {
- "200": {
- "description": "{\"success\":true,\"data\":{},\"msg\":\"获取成功\"}",
- "schema": {
- "type": "string"
- }
- }
- }
- }
- },
- "/post/page": {
- "post": {
- "security": [
- {
- "BearerAuth": []
- }
- ],
- "consumes": [
- "application/json"
- ],
- "produces": [
- "application/json"
- ],
- "tags": [
- "帖子"
- ],
- "summary": "帖子列表",
- "parameters": [
- {
- "description": "分页获取帖子列表",
- "name": "data",
- "in": "body",
- "required": true,
- "schema": {
- "$ref": "#/definitions/request.PostPage"
- }
- }
- ],
- "responses": {
- "200": {
- "description": "{\"success\":true,\"data\":{},\"msg\":\"获取成功\"}",
- "schema": {
- "type": "string"
- }
- }
- }
- }
- },
- "/post/publish": {
- "post": {
- "security": [
- {
- "BearerAuth": []
- }
- ],
- "consumes": [
- "application/json"
- ],
- "produces": [
- "application/json"
- ],
- "tags": [
- "帖子"
- ],
- "summary": "发布帖子",
- "parameters": [
- {
- "description": "发布帖子",
- "name": "data",
- "in": "body",
- "required": true,
- "schema": {
- "$ref": "#/definitions/request.CreatePost"
- }
- }
- ],
- "responses": {
- "200": {
- "description": "{\"success\":true,\"data\":{},\"msg\":\"发布成功\"}",
- "schema": {
- "type": "string"
- }
- }
- }
- }
- },
- "/profile/detail": {
- "get": {
- "security": [
- {
- "BearerAuth": []
- }
- ],
- "produces": [
- "application/json"
- ],
- "tags": [
- "个人中心"
- ],
- "summary": "用户详情",
- "responses": {
- "200": {
- "description": "{\"success\":true,\"data\":{},\"msg\":\"查询成功\"}",
- "schema": {
- "type": "string"
- }
- }
- }
- }
- },
- "/profile/update": {
- "post": {
- "security": [
- {
- "BearerAuth": []
- }
- ],
- "consumes": [
- "application/json"
- ],
- "produces": [
- "application/json"
- ],
- "tags": [
- "个人中心"
- ],
- "summary": "修改用户信息",
- "parameters": [
- {
- "description": "修改用户信息",
- "name": "data",
- "in": "body",
- "required": true,
- "schema": {
- "$ref": "#/definitions/request.UpdateProfile"
- }
- }
- ],
- "responses": {
- "200": {
- "description": "{\"success\":true,\"data\":{},\"msg\":\"修改成功\"}",
- "schema": {
- "type": "string"
- }
- }
- }
- }
- },
"/role/delete": {
"post": {
"description": "删除角色",
@@ -2324,177 +1276,6 @@ const docTemplate = `{
}
}
},
- "/topic/add": {
- "post": {
- "security": [
- {
- "BearerAuth": []
- }
- ],
- "consumes": [
- "application/json"
- ],
- "produces": [
- "application/json"
- ],
- "tags": [
- "帖子话题"
- ],
- "summary": "修改话题",
- "parameters": [
- {
- "description": "修改话题",
- "name": "data",
- "in": "body",
- "required": true,
- "schema": {
- "$ref": "#/definitions/request.UpdateTopic"
- }
- }
- ],
- "responses": {
- "200": {
- "description": "{\"success\":true,\"data\":{},\"msg\":\"发布成功\"}",
- "schema": {
- "type": "string"
- }
- }
- }
- }
- },
- "/topic/delete": {
- "post": {
- "security": [
- {
- "BearerAuth": []
- }
- ],
- "consumes": [
- "application/json"
- ],
- "produces": [
- "application/json"
- ],
- "tags": [
- "帖子话题"
- ],
- "summary": "删除任务",
- "parameters": [
- {
- "description": "删除话题",
- "name": "data",
- "in": "body",
- "required": true,
- "schema": {
- "$ref": "#/definitions/request.IdsReq"
- }
- }
- ],
- "responses": {
- "200": {
- "description": "{\"success\":true,\"data\":{},\"msg\":\"删除成功\"}",
- "schema": {
- "type": "string"
- }
- }
- }
- }
- },
- "/topic/detail": {
- "get": {
- "security": [
- {
- "BearerAuth": []
- }
- ],
- "produces": [
- "application/json"
- ],
- "tags": [
- "帖子话题"
- ],
- "summary": "话题详情",
- "parameters": [
- {
- "type": "string",
- "description": "id",
- "name": "id",
- "in": "query",
- "required": true
- }
- ],
- "responses": {
- "200": {
- "description": "{\"success\":true,\"data\":{},\"msg\":\"获取成功\"}",
- "schema": {
- "type": "string"
- }
- }
- }
- }
- },
- "/topic/list": {
- "get": {
- "security": [
- {
- "BearerAuth": []
- }
- ],
- "produces": [
- "application/json"
- ],
- "tags": [
- "帖子话题"
- ],
- "summary": "话题列表",
- "responses": {
- "200": {
- "description": "{\"success\":true,\"data\":{},\"msg\":\"获取成功\"}",
- "schema": {
- "type": "string"
- }
- }
- }
- }
- },
- "/topic/page": {
- "post": {
- "security": [
- {
- "BearerAuth": []
- }
- ],
- "consumes": [
- "application/json"
- ],
- "produces": [
- "application/json"
- ],
- "tags": [
- "帖子话题"
- ],
- "summary": "话题分页",
- "parameters": [
- {
- "description": "分页获取话题列表",
- "name": "data",
- "in": "body",
- "required": true,
- "schema": {
- "$ref": "#/definitions/request.PageInfo"
- }
- }
- ],
- "responses": {
- "200": {
- "description": "{\"success\":true,\"data\":{},\"msg\":\"获取成功\"}",
- "schema": {
- "type": "string"
- }
- }
- }
- }
- },
"/user/changePassword": {
"post": {
"security": [
@@ -2831,382 +1612,9 @@ const docTemplate = `{
}
}
}
- },
- "/wiki-class/add": {
- "post": {
- "security": [
- {
- "BearerAuth": []
- }
- ],
- "consumes": [
- "application/json"
- ],
- "produces": [
- "application/json"
- ],
- "tags": [
- "百科分类"
- ],
- "summary": "添加分类",
- "parameters": [
- {
- "description": "添加分类",
- "name": "data",
- "in": "body",
- "required": true,
- "schema": {
- "$ref": "#/definitions/request.CreateWikiClass"
- }
- }
- ],
- "responses": {
- "200": {
- "description": "{\"success\":true,\"data\":{},\"msg\":\"发布成功\"}",
- "schema": {
- "type": "string"
- }
- }
- }
- }
- },
- "/wiki-class/delete": {
- "post": {
- "security": [
- {
- "BearerAuth": []
- }
- ],
- "consumes": [
- "application/json"
- ],
- "produces": [
- "application/json"
- ],
- "tags": [
- "百科分类"
- ],
- "summary": "删除分类",
- "parameters": [
- {
- "description": "删除分类",
- "name": "data",
- "in": "body",
- "required": true,
- "schema": {
- "$ref": "#/definitions/request.IdsReq"
- }
- }
- ],
- "responses": {
- "200": {
- "description": "{\"success\":true,\"data\":{},\"msg\":\"删除成功\"}",
- "schema": {
- "type": "string"
- }
- }
- }
- }
- },
- "/wiki-class/detail": {
- "get": {
- "security": [
- {
- "BearerAuth": []
- }
- ],
- "produces": [
- "application/json"
- ],
- "tags": [
- "百科分类"
- ],
- "summary": "分类详情",
- "parameters": [
- {
- "type": "string",
- "description": "id",
- "name": "id",
- "in": "query",
- "required": true
- }
- ],
- "responses": {
- "200": {
- "description": "{\"success\":true,\"data\":{},\"msg\":\"获取成功\"}",
- "schema": {
- "type": "string"
- }
- }
- }
- }
- },
- "/wiki-class/list": {
- "get": {
- "security": [
- {
- "BearerAuth": []
- }
- ],
- "produces": [
- "application/json"
- ],
- "tags": [
- "百科分类"
- ],
- "summary": "分类列表",
- "responses": {
- "200": {
- "description": "{\"success\":true,\"data\":{},\"msg\":\"获取成功\"}",
- "schema": {
- "type": "string"
- }
- }
- }
- }
- },
- "/wiki-class/page": {
- "post": {
- "security": [
- {
- "BearerAuth": []
- }
- ],
- "consumes": [
- "application/json"
- ],
- "produces": [
- "application/json"
- ],
- "tags": [
- "百科分类"
- ],
- "summary": "分类分页",
- "parameters": [
- {
- "description": "分页获取分类列表",
- "name": "data",
- "in": "body",
- "required": true,
- "schema": {
- "$ref": "#/definitions/request.PageInfo"
- }
- }
- ],
- "responses": {
- "200": {
- "description": "{\"success\":true,\"data\":{},\"msg\":\"获取成功\"}",
- "schema": {
- "type": "string"
- }
- }
- }
- }
- },
- "/wiki-class/update": {
- "post": {
- "security": [
- {
- "BearerAuth": []
- }
- ],
- "consumes": [
- "application/json"
- ],
- "produces": [
- "application/json"
- ],
- "tags": [
- "百科分类"
- ],
- "summary": "修改分类(可直接传入ossId修改图片)",
- "parameters": [
- {
- "description": "修改分类",
- "name": "data",
- "in": "body",
- "required": true,
- "schema": {
- "$ref": "#/definitions/request.UpdateWikiClass"
- }
- }
- ],
- "responses": {
- "200": {
- "description": "{\"success\":true,\"data\":{},\"msg\":\"发布成功\"}",
- "schema": {
- "type": "string"
- }
- }
- }
- }
- },
- "/wiki/add": {
- "post": {
- "security": [
- {
- "BearerAuth": []
- }
- ],
- "consumes": [
- "application/json"
- ],
- "produces": [
- "application/json"
- ],
- "tags": [
- "百科"
- ],
- "summary": "添加百科",
- "parameters": [
- {
- "description": "添加百科",
- "name": "data",
- "in": "body",
- "required": true,
- "schema": {
- "$ref": "#/definitions/request.CreateWiki"
- }
- }
- ],
- "responses": {
- "200": {
- "description": "{\"success\":true,\"data\":{},\"msg\":\"发布成功\"}",
- "schema": {
- "type": "string"
- }
- }
- }
- }
- },
- "/wiki/detail": {
- "get": {
- "security": [
- {
- "BearerAuth": []
- }
- ],
- "produces": [
- "application/json"
- ],
- "tags": [
- "百科"
- ],
- "summary": "百科详情",
- "parameters": [
- {
- "type": "string",
- "description": "id",
- "name": "id",
- "in": "query",
- "required": true
- }
- ],
- "responses": {
- "200": {
- "description": "{\"success\":true,\"data\":{},\"msg\":\"获取成功\"}",
- "schema": {
- "type": "string"
- }
- }
- }
- }
- },
- "/wiki/page": {
- "post": {
- "security": [
- {
- "BearerAuth": []
- }
- ],
- "consumes": [
- "application/json"
- ],
- "produces": [
- "application/json"
- ],
- "tags": [
- "百科"
- ],
- "summary": "分页",
- "parameters": [
- {
- "description": "百科分页",
- "name": "data",
- "in": "body",
- "required": true,
- "schema": {
- "$ref": "#/definitions/request.WikiPage"
- }
- }
- ],
- "responses": {
- "200": {
- "description": "{\"success\":true,\"data\":{},\"msg\":\"发布成功\"}",
- "schema": {
- "type": "string"
- }
- }
- }
- }
- },
- "/wiki/update": {
- "post": {
- "security": [
- {
- "BearerAuth": []
- }
- ],
- "consumes": [
- "application/json"
- ],
- "produces": [
- "application/json"
- ],
- "tags": [
- "百科"
- ],
- "summary": "修改百科",
- "parameters": [
- {
- "description": "修改百科",
- "name": "data",
- "in": "body",
- "required": true,
- "schema": {
- "$ref": "#/definitions/request.UpdateWiki"
- }
- }
- ],
- "responses": {
- "200": {
- "description": "{\"success\":true,\"data\":{},\"msg\":\"发布成功\"}",
- "schema": {
- "type": "string"
- }
- }
- }
- }
}
},
"definitions": {
- "request.CarePlan": {
- "type": "object",
- "properties": {
- "icon": {
- "description": "icon信息",
- "type": "string"
- },
- "name": {
- "description": "农事名称",
- "type": "string"
- },
- "period": {
- "description": "周期",
- "type": "integer"
- }
- }
- },
"request.ChangePwd": {
"type": "object",
"properties": {
@@ -3218,381 +1626,6 @@ const docTemplate = `{
}
}
},
- "request.CompleteTask": {
- "type": "object",
- "required": [
- "taskId"
- ],
- "properties": {
- "remark": {
- "type": "string"
- },
- "taskId": {
- "type": "string"
- }
- }
- },
- "request.CreateBadge": {
- "type": "object",
- "properties": {
- "comparator": {
- "type": "string"
- },
- "description": {
- "type": "string"
- },
- "dimension": {
- "description": "维度: EXPERTISE(专家), PERSISTENCE(勤勉), JOURNAL(记录)",
- "type": "string"
- },
- "groupId": {
- "description": "组ID: 用于前端聚合显示 (e.g. \"fertilizerMaster\")",
- "type": "string"
- },
- "iconId": {
- "type": "string"
- },
- "name": {
- "type": "string"
- },
- "rewardSunlight": {
- "type": "integer"
- },
- "sort": {
- "type": "integer"
- },
- "targetAction": {
- "description": "触发动作: ACT_FERTILIZE, ACT_WATER...",
- "type": "string"
- },
- "threshold": {
- "type": "integer"
- },
- "tier": {
- "description": "等级: 1=铜, 2=银, 3=金",
- "type": "integer"
- }
- }
- },
- "request.CreateCarePlan": {
- "type": "object",
- "required": [
- "plantId"
- ],
- "properties": {
- "icon": {
- "description": "icon信息",
- "type": "string"
- },
- "name": {
- "description": "农事名称",
- "type": "string"
- },
- "period": {
- "description": "周期",
- "type": "integer"
- },
- "plantId": {
- "type": "string"
- }
- }
- },
- "request.CreateComment": {
- "type": "object",
- "required": [
- "content",
- "postId"
- ],
- "properties": {
- "content": {
- "description": "评论内容",
- "type": "string"
- },
- "postId": {
- "description": "帖子id",
- "type": "string"
- }
- }
- },
- "request.CreateGrowthRecord": {
- "type": "object",
- "required": [
- "plantId"
- ],
- "properties": {
- "content": {
- "type": "string"
- },
- "desc": {
- "type": "string"
- },
- "name": {
- "type": "string"
- },
- "ossIds": {
- "type": "array",
- "items": {
- "type": "string"
- }
- },
- "plantId": {
- "type": "string"
- },
- "tag": {
- "type": "string"
- }
- }
- },
- "request.CreateLevelConf": {
- "type": "object",
- "properties": {
- "level": {
- "description": "等级数值",
- "type": "integer"
- },
- "minSunlight": {
- "description": "达到该等级所需的最小阳光值",
- "type": "integer"
- },
- "perks": {
- "description": "解锁权益描述 (e.g., \"解锁智能诊断\")",
- "type": "string"
- },
- "title": {
- "description": "等级称号 (e.g., \"萌芽园丁\")",
- "type": "string"
- }
- }
- },
- "request.CreateMyPlant": {
- "type": "object",
- "properties": {
- "carePlans": {
- "description": "养护计划",
- "type": "array",
- "items": {
- "$ref": "#/definitions/request.CarePlan"
- }
- },
- "name": {
- "description": "植物名称",
- "type": "string"
- },
- "ossIds": {
- "description": "图片ids",
- "type": "array",
- "items": {
- "type": "string"
- }
- },
- "placement": {
- "description": "摆放位置",
- "type": "string"
- },
- "plantTime": {
- "description": "种植时间",
- "type": "string"
- },
- "plantingMaterial": {
- "description": "植料(即土的材质)",
- "type": "string"
- },
- "potMaterial": {
- "description": "花盆材质",
- "type": "string"
- },
- "potSize": {
- "description": "花盆大小 如直径 20cm × 高度 18cm",
- "type": "string"
- },
- "sunlight": {
- "description": "光照条件如每日12小时",
- "type": "string"
- }
- }
- },
- "request.CreatePost": {
- "type": "object",
- "properties": {
- "content": {
- "description": "内容",
- "type": "string"
- },
- "location": {
- "description": "位置",
- "type": "string"
- },
- "ossIds": {
- "description": "图片id[]",
- "type": "array",
- "items": {
- "type": "string"
- }
- },
- "title": {
- "description": "标题 必须",
- "type": "string"
- }
- }
- },
- "request.CreateTopic": {
- "type": "object",
- "properties": {
- "endTime": {
- "type": "string"
- },
- "remark": {
- "type": "string"
- },
- "startTime": {
- "type": "string"
- },
- "title": {
- "type": "string"
- }
- }
- },
- "request.CreateWiki": {
- "type": "object",
- "required": [
- "name"
- ],
- "properties": {
- "aliases": {
- "description": "别名",
- "type": "string"
- },
- "classIds": {
- "description": "分类id",
- "type": "array",
- "items": {
- "type": "string"
- }
- },
- "difficulty": {
- "description": "种植难度 1-5级",
- "type": "integer"
- },
- "distributionArea": {
- "description": "分布区域",
- "type": "string"
- },
- "flowerDiameter": {
- "description": "花直径(cm)",
- "type": "integer"
- },
- "floweringColor": {
- "description": "花色",
- "type": "string"
- },
- "floweringPeriod": {
- "description": "开花期",
- "type": "string"
- },
- "floweringShape": {
- "description": "花形",
- "type": "string"
- },
- "foliageColor": {
- "description": "叶色",
- "type": "string"
- },
- "foliageShape": {
- "description": "叶形",
- "type": "string"
- },
- "foliageType": {
- "description": "叶型",
- "type": "string"
- },
- "fruit": {
- "description": "果",
- "type": "string"
- },
- "genus": {
- "description": "属",
- "type": "string"
- },
- "growthHabit": {
- "description": "生长习性",
- "type": "string"
- },
- "height": {
- "description": "高度(cm)",
- "type": "integer"
- },
- "isHot": {
- "description": "是否热门",
- "type": "integer"
- },
- "latinName": {
- "description": "拉丁名",
- "type": "string"
- },
- "lifeCycle": {
- "description": "生命周期",
- "type": "string"
- },
- "lightIntensity": {
- "description": "光照强度",
- "type": "string"
- },
- "lightType": {
- "description": "光照类型(直射,散射等)",
- "type": "string"
- },
- "name": {
- "description": "名称",
- "type": "string"
- },
- "optimalTempPeriod": {
- "description": "最佳温度区间",
- "type": "string"
- },
- "ossIds": {
- "description": "图片",
- "type": "array",
- "items": {
- "type": "string"
- }
- },
- "pestsDiseases": {
- "description": "常见病虫害",
- "type": "string"
- },
- "relatedWikiIds": {
- "description": "相关推荐",
- "type": "array",
- "items": {
- "type": "string"
- }
- },
- "reproductionMethod": {
- "description": "繁殖方法",
- "type": "string"
- },
- "stem": {
- "description": "茎",
- "type": "string"
- }
- }
- },
- "request.CreateWikiClass": {
- "type": "object",
- "required": [
- "name"
- ],
- "properties": {
- "name": {
- "description": "分类名称",
- "type": "string"
- },
- "ossId": {
- "description": "图片id",
- "type": "string"
- }
- }
- },
"request.GetClientList": {
"type": "object",
"properties": {
@@ -3749,371 +1782,6 @@ const docTemplate = `{
}
}
},
- "request.PageInfo": {
- "type": "object",
- "properties": {
- "current": {
- "description": "页码",
- "type": "integer"
- },
- "keyword": {
- "description": "关键字",
- "type": "string"
- },
- "pageSize": {
- "description": "每页大小",
- "type": "integer"
- }
- }
- },
- "request.PostPage": {
- "type": "object",
- "properties": {
- "current": {
- "description": "页码",
- "type": "integer"
- },
- "hasReviewed": {
- "description": "是否审核通过",
- "type": "integer"
- },
- "keyword": {
- "description": "关键字",
- "type": "string"
- },
- "pageSize": {
- "description": "每页大小",
- "type": "integer"
- },
- "title": {
- "description": "标题",
- "type": "string"
- }
- }
- },
- "request.UpdateBadge": {
- "type": "object",
- "required": [
- "id"
- ],
- "properties": {
- "comparator": {
- "type": "string"
- },
- "description": {
- "type": "string"
- },
- "dimension": {
- "description": "维度: EXPERTISE(专家), PERSISTENCE(勤勉), JOURNAL(记录)",
- "type": "string"
- },
- "groupId": {
- "description": "组Id: 用于前端聚合显示 (e.g. \"fertilizerMaster\")",
- "type": "string"
- },
- "iconId": {
- "type": "string"
- },
- "id": {
- "type": "string"
- },
- "name": {
- "type": "string"
- },
- "rewardSunlight": {
- "type": "integer"
- },
- "sort": {
- "type": "integer"
- },
- "targetAction": {
- "description": "触发动作: ACT_FERTILIZE, ACT_WATER...",
- "type": "string"
- },
- "threshold": {
- "type": "integer"
- },
- "tier": {
- "description": "等级: 1=铜, 2=银, 3=金",
- "type": "integer"
- }
- }
- },
- "request.UpdateLevelConf": {
- "type": "object",
- "required": [
- "id"
- ],
- "properties": {
- "id": {
- "type": "string"
- },
- "level": {
- "description": "等级数值",
- "type": "integer"
- },
- "minSunlight": {
- "description": "达到该等级所需的最小阳光值",
- "type": "integer"
- },
- "perks": {
- "description": "解锁权益描述 (e.g., \"解锁智能诊断\")",
- "type": "string"
- },
- "title": {
- "description": "等级称号 (e.g., \"萌芽园丁\")",
- "type": "string"
- }
- }
- },
- "request.UpdateMyPlant": {
- "type": "object",
- "required": [
- "id"
- ],
- "properties": {
- "carePlans": {
- "type": "array",
- "items": {
- "$ref": "#/definitions/request.UpdatePlan"
- }
- },
- "id": {
- "type": "string"
- },
- "name": {
- "description": "植物名称",
- "type": "string"
- },
- "placement": {
- "description": "摆放位置",
- "type": "string"
- },
- "plantingMaterial": {
- "description": "植料(即土的材质)",
- "type": "string"
- },
- "potMaterial": {
- "description": "花盆材质",
- "type": "string"
- },
- "potSize": {
- "description": "花盆大小 如直径 20cm × 高度 18cm",
- "type": "string"
- },
- "sunlight": {
- "description": "光照条件如每日12小时",
- "type": "string"
- }
- }
- },
- "request.UpdatePlan": {
- "type": "object",
- "required": [
- "id"
- ],
- "properties": {
- "icon": {
- "description": "icon信息",
- "type": "string"
- },
- "id": {
- "type": "string"
- },
- "name": {
- "description": "农事名称",
- "type": "string"
- },
- "period": {
- "description": "周期",
- "type": "integer"
- }
- }
- },
- "request.UpdateProfile": {
- "type": "object",
- "properties": {
- "avatarId": {
- "type": "string"
- },
- "nickname": {
- "type": "string"
- }
- }
- },
- "request.UpdateTopic": {
- "type": "object",
- "required": [
- "id"
- ],
- "properties": {
- "endTime": {
- "type": "string"
- },
- "id": {
- "type": "integer"
- },
- "remark": {
- "type": "string"
- },
- "startTime": {
- "type": "string"
- },
- "title": {
- "type": "string"
- }
- }
- },
- "request.UpdateWiki": {
- "type": "object",
- "required": [
- "id"
- ],
- "properties": {
- "aliases": {
- "description": "别名",
- "type": "string"
- },
- "difficulty": {
- "description": "种植难度 1-5级",
- "type": "integer"
- },
- "distributionArea": {
- "description": "分布区域",
- "type": "string"
- },
- "flowerDiameter": {
- "description": "花直径(cm)",
- "type": "integer"
- },
- "floweringColor": {
- "description": "花色",
- "type": "string"
- },
- "floweringPeriod": {
- "description": "开花期",
- "type": "string"
- },
- "floweringShape": {
- "description": "花形",
- "type": "string"
- },
- "foliageColor": {
- "description": "叶色",
- "type": "string"
- },
- "foliageShape": {
- "description": "叶形",
- "type": "string"
- },
- "foliageType": {
- "description": "叶型",
- "type": "string"
- },
- "fruit": {
- "description": "果",
- "type": "string"
- },
- "genus": {
- "description": "属",
- "type": "string"
- },
- "growthHabit": {
- "description": "生长习性",
- "type": "string"
- },
- "height": {
- "description": "高度(cm)",
- "type": "integer"
- },
- "id": {
- "type": "string"
- },
- "latinName": {
- "description": "拉丁名",
- "type": "string"
- },
- "lifeCycle": {
- "description": "生命周期",
- "type": "string"
- },
- "lightIntensity": {
- "description": "光照强度",
- "type": "string"
- },
- "lightType": {
- "description": "光照类型(直射,散射等)",
- "type": "string"
- },
- "name": {
- "description": "名称",
- "type": "string"
- },
- "optimalTempPeriod": {
- "description": "最佳温度区间",
- "type": "string"
- },
- "pestsDiseases": {
- "description": "常见病虫害",
- "type": "string"
- },
- "stem": {
- "description": "茎",
- "type": "string"
- }
- }
- },
- "request.UpdateWikiClass": {
- "type": "object",
- "required": [
- "id"
- ],
- "properties": {
- "id": {
- "type": "string"
- },
- "name": {
- "description": "分类名称",
- "type": "string"
- },
- "ossId": {
- "description": "图片id",
- "type": "string"
- }
- }
- },
- "request.WikiPage": {
- "type": "object",
- "properties": {
- "classId": {
- "description": "分类id",
- "type": "array",
- "items": {
- "type": "string"
- }
- },
- "current": {
- "description": "页码",
- "type": "integer"
- },
- "isHot": {
- "description": "是否热门 0否 1是",
- "type": "integer"
- },
- "keyword": {
- "description": "关键字",
- "type": "string"
- },
- "name": {
- "description": "植物名称",
- "type": "string"
- },
- "pageSize": {
- "description": "每页大小",
- "type": "integer"
- }
- }
- },
"response.CaptchaRes": {
"type": "object",
"properties": {
diff --git a/docs/swagger.json b/docs/swagger.json
index 36d7968..a484875 100644
--- a/docs/swagger.json
+++ b/docs/swagger.json
@@ -236,104 +236,6 @@
}
}
},
- "/classify/myClassifyLog": {
- "post": {
- "security": [
- {
- "ApiKeyAuth": []
- }
- ],
- "consumes": [
- "application/json"
- ],
- "produces": [
- "application/json"
- ],
- "tags": [
- "识别相关"
- ],
- "summary": "我的植物识别记录",
- "parameters": [
- {
- "description": "分页",
- "name": "data",
- "in": "body",
- "required": true,
- "schema": {
- "$ref": "#/definitions/request.PageInfo"
- }
- }
- ],
- "responses": {
- "200": {
- "description": "识别记录",
- "schema": {
- "allOf": [
- {
- "$ref": "#/definitions/response.Response"
- },
- {
- "type": "object",
- "properties": {
- "msg": {
- "type": "string"
- }
- }
- }
- ]
- }
- }
- }
- }
- },
- "/classify/plant": {
- "post": {
- "security": [
- {
- "ApiKeyAuth": []
- }
- ],
- "consumes": [
- "multipart/form-data"
- ],
- "produces": [
- "application/json"
- ],
- "tags": [
- "识别相关"
- ],
- "summary": "base64植物识别",
- "parameters": [
- {
- "type": "file",
- "description": "植物识别",
- "name": "file",
- "in": "formData",
- "required": true
- }
- ],
- "responses": {
- "200": {
- "description": "文件OCR",
- "schema": {
- "allOf": [
- {
- "$ref": "#/definitions/response.Response"
- },
- {
- "type": "object",
- "properties": {
- "msg": {
- "type": "string"
- }
- }
- }
- ]
- }
- }
- }
- }
- },
"/client/delete": {
"post": {
"security": [
@@ -586,305 +488,6 @@
}
}
},
- "/config/badge/add": {
- "post": {
- "security": [
- {
- "BearerAuth": []
- }
- ],
- "consumes": [
- "application/json"
- ],
- "produces": [
- "application/json"
- ],
- "tags": [
- "徽章配置"
- ],
- "summary": "添加徽章配置",
- "parameters": [
- {
- "description": "添加徽章配置",
- "name": "data",
- "in": "body",
- "required": true,
- "schema": {
- "$ref": "#/definitions/request.CreateBadge"
- }
- }
- ],
- "responses": {
- "200": {
- "description": "{\"success\":true,\"data\":{},\"msg\":\"添加成功\"}",
- "schema": {
- "type": "string"
- }
- }
- }
- }
- },
- "/config/badge/delete": {
- "get": {
- "security": [
- {
- "BearerAuth": []
- }
- ],
- "produces": [
- "application/json"
- ],
- "tags": [
- "徽章配置"
- ],
- "summary": "删除徽章配置",
- "parameters": [
- {
- "type": "string",
- "description": "id",
- "name": "id",
- "in": "query",
- "required": true
- }
- ],
- "responses": {
- "200": {
- "description": "{\"success\":true,\"data\":{},\"msg\":\"删除成功\"}",
- "schema": {
- "type": "string"
- }
- }
- }
- }
- },
- "/config/badge/find": {
- "get": {
- "security": [
- {
- "BearerAuth": []
- }
- ],
- "produces": [
- "application/json"
- ],
- "tags": [
- "徽章配置"
- ],
- "summary": "根据ID获取徽章配置",
- "parameters": [
- {
- "type": "string",
- "description": "id",
- "name": "id",
- "in": "query",
- "required": true
- }
- ],
- "responses": {
- "200": {
- "description": "{\"success\":true,\"data\":{},\"msg\":\"获取成功\"}",
- "schema": {
- "type": "string"
- }
- }
- }
- }
- },
- "/config/badge/tree": {
- "get": {
- "security": [
- {
- "BearerAuth": []
- }
- ],
- "produces": [
- "application/json"
- ],
- "tags": [
- "徽章配置"
- ],
- "summary": "获取徽章配置树形结构",
- "responses": {
- "200": {
- "description": "{\"success\":true,\"data\":{},\"msg\":\"获取成功\"}",
- "schema": {
- "type": "string"
- }
- }
- }
- }
- },
- "/config/badge/update": {
- "post": {
- "security": [
- {
- "BearerAuth": []
- }
- ],
- "consumes": [
- "application/json"
- ],
- "produces": [
- "application/json"
- ],
- "tags": [
- "徽章配置"
- ],
- "summary": "更新徽章配置",
- "parameters": [
- {
- "description": "更新参数",
- "name": "data",
- "in": "body",
- "required": true,
- "schema": {
- "$ref": "#/definitions/request.UpdateBadge"
- }
- }
- ],
- "responses": {
- "200": {
- "description": "{\"success\":true,\"data\":{},\"msg\":\"更新成功\"}",
- "schema": {
- "type": "string"
- }
- }
- }
- }
- },
- "/config/level/add": {
- "post": {
- "security": [
- {
- "BearerAuth": []
- }
- ],
- "consumes": [
- "application/json"
- ],
- "produces": [
- "application/json"
- ],
- "tags": [
- "等级配置"
- ],
- "summary": "添加等级配置",
- "parameters": [
- {
- "description": "添加等级配置",
- "name": "data",
- "in": "body",
- "required": true,
- "schema": {
- "$ref": "#/definitions/request.CreateLevelConf"
- }
- }
- ],
- "responses": {
- "200": {
- "description": "{\"success\":true,\"data\":{},\"msg\":\"添加成功\"}",
- "schema": {
- "type": "string"
- }
- }
- }
- }
- },
- "/config/level/detail": {
- "get": {
- "security": [
- {
- "BearerAuth": []
- }
- ],
- "produces": [
- "application/json"
- ],
- "tags": [
- "等级配置"
- ],
- "summary": "等级配置详情",
- "parameters": [
- {
- "type": "string",
- "description": "等级配置id",
- "name": "id",
- "in": "query",
- "required": true
- }
- ],
- "responses": {
- "200": {
- "description": "{\"success\":true,\"data\":{},\"msg\":\"查询成功\"}",
- "schema": {
- "type": "string"
- }
- }
- }
- }
- },
- "/config/level/list": {
- "get": {
- "security": [
- {
- "BearerAuth": []
- }
- ],
- "produces": [
- "application/json"
- ],
- "tags": [
- "等级配置"
- ],
- "summary": "等级配置列表",
- "responses": {
- "200": {
- "description": "{\"success\":true,\"data\":{},\"msg\":\"查询成功\"}",
- "schema": {
- "type": "string"
- }
- }
- }
- }
- },
- "/config/level/update": {
- "post": {
- "security": [
- {
- "BearerAuth": []
- }
- ],
- "consumes": [
- "application/json"
- ],
- "produces": [
- "application/json"
- ],
- "tags": [
- "等级配置"
- ],
- "summary": "修改等级配置",
- "parameters": [
- {
- "description": "修改等级配置",
- "name": "data",
- "in": "body",
- "required": true,
- "schema": {
- "$ref": "#/definitions/request.UpdateLevelConf"
- }
- }
- ],
- "responses": {
- "200": {
- "description": "{\"success\":true,\"data\":{},\"msg\":\"修改成功\"}",
- "schema": {
- "type": "string"
- }
- }
- }
- }
- },
"/menu/delete": {
"get": {
"security": [
@@ -1411,657 +1014,6 @@
}
}
},
- "/plant/add": {
- "post": {
- "security": [
- {
- "BearerAuth": []
- }
- ],
- "consumes": [
- "application/json"
- ],
- "produces": [
- "application/json"
- ],
- "tags": [
- "我的植物"
- ],
- "summary": "添加植物",
- "parameters": [
- {
- "description": "创建植物",
- "name": "data",
- "in": "body",
- "required": true,
- "schema": {
- "$ref": "#/definitions/request.CreateMyPlant"
- }
- }
- ],
- "responses": {
- "200": {
- "description": "{\"success\":true,\"data\":{},\"msg\":\"添加成功\"}",
- "schema": {
- "type": "string"
- }
- }
- }
- }
- },
- "/plant/completeTask": {
- "post": {
- "security": [
- {
- "BearerAuth": []
- }
- ],
- "consumes": [
- "application/json"
- ],
- "produces": [
- "application/json"
- ],
- "tags": [
- "我的植物"
- ],
- "summary": "完成任务",
- "parameters": [
- {
- "description": "完成任务",
- "name": "data",
- "in": "body",
- "required": true,
- "schema": {
- "$ref": "#/definitions/request.CompleteTask"
- }
- }
- ],
- "responses": {
- "200": {
- "description": "{\"success\":true,\"data\":{},\"msg\":\"完成任务\"}",
- "schema": {
- "type": "string"
- }
- }
- }
- }
- },
- "/plant/deletePlan": {
- "post": {
- "security": [
- {
- "BearerAuth": []
- }
- ],
- "consumes": [
- "application/json"
- ],
- "produces": [
- "application/json"
- ],
- "tags": [
- "我的植物"
- ],
- "summary": "删除任务",
- "parameters": [
- {
- "description": "删除植物",
- "name": "data",
- "in": "body",
- "required": true,
- "schema": {
- "$ref": "#/definitions/request.IdsReq"
- }
- }
- ],
- "responses": {
- "200": {
- "description": "{\"success\":true,\"data\":{},\"msg\":\"删除成功\"}",
- "schema": {
- "type": "string"
- }
- }
- }
- }
- },
- "/plant/deletePlant": {
- "post": {
- "security": [
- {
- "BearerAuth": []
- }
- ],
- "consumes": [
- "application/json"
- ],
- "produces": [
- "application/json"
- ],
- "tags": [
- "我的植物"
- ],
- "summary": "删除植物",
- "parameters": [
- {
- "description": "删除植物",
- "name": "data",
- "in": "body",
- "required": true,
- "schema": {
- "$ref": "#/definitions/request.IdsReq"
- }
- }
- ],
- "responses": {
- "200": {
- "description": "{\"success\":true,\"data\":{},\"msg\":\"删除成功\"}",
- "schema": {
- "type": "string"
- }
- }
- }
- }
- },
- "/plant/detail": {
- "get": {
- "security": [
- {
- "BearerAuth": []
- }
- ],
- "produces": [
- "application/json"
- ],
- "tags": [
- "我的植物"
- ],
- "summary": "ById植物详情",
- "parameters": [
- {
- "type": "string",
- "description": "id",
- "name": "id",
- "in": "query",
- "required": true
- }
- ],
- "responses": {
- "200": {
- "description": "{\"success\":true,\"data\":{},\"msg\":\"获取ById成功\"}",
- "schema": {
- "type": "string"
- }
- }
- }
- }
- },
- "/plant/growth/add": {
- "post": {
- "security": [
- {
- "BearerAuth": []
- }
- ],
- "consumes": [
- "application/json"
- ],
- "produces": [
- "application/json"
- ],
- "tags": [
- "我的植物"
- ],
- "summary": "添加成长记录",
- "parameters": [
- {
- "description": "添加成长记录",
- "name": "data",
- "in": "body",
- "required": true,
- "schema": {
- "$ref": "#/definitions/request.CreateGrowthRecord"
- }
- }
- ],
- "responses": {
- "200": {
- "description": "{\"success\":true,\"data\":{},\"msg\":\"添加成功\"}",
- "schema": {
- "type": "string"
- }
- }
- }
- }
- },
- "/plant/page": {
- "post": {
- "security": [
- {
- "BearerAuth": []
- }
- ],
- "consumes": [
- "application/json"
- ],
- "produces": [
- "application/json"
- ],
- "tags": [
- "我的植物"
- ],
- "summary": "植物列表",
- "parameters": [
- {
- "description": "分页获取植物列表",
- "name": "data",
- "in": "body",
- "required": true,
- "schema": {
- "$ref": "#/definitions/request.PageInfo"
- }
- }
- ],
- "responses": {
- "200": {
- "description": "{\"success\":true,\"data\":{},\"msg\":\"获取成功\"}",
- "schema": {
- "type": "string"
- }
- }
- }
- }
- },
- "/plant/plan/add": {
- "post": {
- "security": [
- {
- "BearerAuth": []
- }
- ],
- "consumes": [
- "application/json"
- ],
- "produces": [
- "application/json"
- ],
- "tags": [
- "我的植物"
- ],
- "summary": "添加养护事项",
- "parameters": [
- {
- "description": "添加养护事项",
- "name": "data",
- "in": "body",
- "required": true,
- "schema": {
- "$ref": "#/definitions/request.CreateCarePlan"
- }
- }
- ],
- "responses": {
- "200": {
- "description": "{\"success\":true,\"data\":{},\"msg\":\"添加成功\"}",
- "schema": {
- "type": "string"
- }
- }
- }
- }
- },
- "/plant/plan/delete": {
- "get": {
- "security": [
- {
- "BearerAuth": []
- }
- ],
- "produces": [
- "application/json"
- ],
- "tags": [
- "我的植物"
- ],
- "summary": "删除养护事项",
- "parameters": [
- {
- "type": "string",
- "description": "id",
- "name": "id",
- "in": "query",
- "required": true
- }
- ],
- "responses": {
- "200": {
- "description": "{\"success\":true,\"data\":{},\"msg\":\"删除成功\"}",
- "schema": {
- "type": "string"
- }
- }
- }
- }
- },
- "/plant/todayTask": {
- "get": {
- "security": [
- {
- "BearerAuth": []
- }
- ],
- "consumes": [
- "application/json"
- ],
- "produces": [
- "application/json"
- ],
- "tags": [
- "我的植物"
- ],
- "summary": "今日任务",
- "responses": {
- "200": {
- "description": "{\"success\":true,\"data\":{},\"msg\":\"获取成功\"}",
- "schema": {
- "type": "string"
- }
- }
- }
- }
- },
- "/plant/update": {
- "post": {
- "security": [
- {
- "BearerAuth": []
- }
- ],
- "consumes": [
- "application/json"
- ],
- "produces": [
- "application/json"
- ],
- "tags": [
- "我的植物"
- ],
- "summary": "修改ById植物",
- "parameters": [
- {
- "description": "修改ById植物",
- "name": "data",
- "in": "body",
- "required": true,
- "schema": {
- "$ref": "#/definitions/request.UpdateMyPlant"
- }
- }
- ],
- "responses": {
- "200": {
- "description": "{\"success\":true,\"data\":{},\"msg\":\"修改ById成功\"}",
- "schema": {
- "type": "string"
- }
- }
- }
- }
- },
- "/post/comment": {
- "post": {
- "security": [
- {
- "BearerAuth": []
- }
- ],
- "consumes": [
- "application/json"
- ],
- "produces": [
- "application/json"
- ],
- "tags": [
- "帖子"
- ],
- "summary": "评论帖子",
- "parameters": [
- {
- "description": "评论帖子",
- "name": "data",
- "in": "body",
- "required": true,
- "schema": {
- "$ref": "#/definitions/request.CreateComment"
- }
- }
- ],
- "responses": {
- "200": {
- "description": "{\"success\":true,\"data\":{},\"msg\":\"评论成功\"}",
- "schema": {
- "type": "string"
- }
- }
- }
- }
- },
- "/post/like": {
- "get": {
- "security": [
- {
- "BearerAuth": []
- }
- ],
- "produces": [
- "application/json"
- ],
- "tags": [
- "帖子"
- ],
- "summary": "点赞帖子",
- "parameters": [
- {
- "type": "string",
- "description": "帖子id",
- "name": "id",
- "in": "query",
- "required": true
- },
- {
- "type": "string",
- "description": "点赞类型 1 点赞 2 取消点赞",
- "name": "type",
- "in": "query",
- "required": true
- }
- ],
- "responses": {
- "200": {
- "description": "{\"success\":true,\"data\":{},\"msg\":\"点赞成功\"}",
- "schema": {
- "type": "string"
- }
- }
- }
- }
- },
- "/post/myPost": {
- "post": {
- "security": [
- {
- "BearerAuth": []
- }
- ],
- "consumes": [
- "application/json"
- ],
- "produces": [
- "application/json"
- ],
- "tags": [
- "帖子"
- ],
- "summary": "我的发布",
- "parameters": [
- {
- "description": "分页获取帖子列表",
- "name": "data",
- "in": "body",
- "required": true,
- "schema": {
- "$ref": "#/definitions/request.PostPage"
- }
- }
- ],
- "responses": {
- "200": {
- "description": "{\"success\":true,\"data\":{},\"msg\":\"获取成功\"}",
- "schema": {
- "type": "string"
- }
- }
- }
- }
- },
- "/post/page": {
- "post": {
- "security": [
- {
- "BearerAuth": []
- }
- ],
- "consumes": [
- "application/json"
- ],
- "produces": [
- "application/json"
- ],
- "tags": [
- "帖子"
- ],
- "summary": "帖子列表",
- "parameters": [
- {
- "description": "分页获取帖子列表",
- "name": "data",
- "in": "body",
- "required": true,
- "schema": {
- "$ref": "#/definitions/request.PostPage"
- }
- }
- ],
- "responses": {
- "200": {
- "description": "{\"success\":true,\"data\":{},\"msg\":\"获取成功\"}",
- "schema": {
- "type": "string"
- }
- }
- }
- }
- },
- "/post/publish": {
- "post": {
- "security": [
- {
- "BearerAuth": []
- }
- ],
- "consumes": [
- "application/json"
- ],
- "produces": [
- "application/json"
- ],
- "tags": [
- "帖子"
- ],
- "summary": "发布帖子",
- "parameters": [
- {
- "description": "发布帖子",
- "name": "data",
- "in": "body",
- "required": true,
- "schema": {
- "$ref": "#/definitions/request.CreatePost"
- }
- }
- ],
- "responses": {
- "200": {
- "description": "{\"success\":true,\"data\":{},\"msg\":\"发布成功\"}",
- "schema": {
- "type": "string"
- }
- }
- }
- }
- },
- "/profile/detail": {
- "get": {
- "security": [
- {
- "BearerAuth": []
- }
- ],
- "produces": [
- "application/json"
- ],
- "tags": [
- "个人中心"
- ],
- "summary": "用户详情",
- "responses": {
- "200": {
- "description": "{\"success\":true,\"data\":{},\"msg\":\"查询成功\"}",
- "schema": {
- "type": "string"
- }
- }
- }
- }
- },
- "/profile/update": {
- "post": {
- "security": [
- {
- "BearerAuth": []
- }
- ],
- "consumes": [
- "application/json"
- ],
- "produces": [
- "application/json"
- ],
- "tags": [
- "个人中心"
- ],
- "summary": "修改用户信息",
- "parameters": [
- {
- "description": "修改用户信息",
- "name": "data",
- "in": "body",
- "required": true,
- "schema": {
- "$ref": "#/definitions/request.UpdateProfile"
- }
- }
- ],
- "responses": {
- "200": {
- "description": "{\"success\":true,\"data\":{},\"msg\":\"修改成功\"}",
- "schema": {
- "type": "string"
- }
- }
- }
- }
- },
"/role/delete": {
"post": {
"description": "删除角色",
@@ -2316,177 +1268,6 @@
}
}
},
- "/topic/add": {
- "post": {
- "security": [
- {
- "BearerAuth": []
- }
- ],
- "consumes": [
- "application/json"
- ],
- "produces": [
- "application/json"
- ],
- "tags": [
- "帖子话题"
- ],
- "summary": "修改话题",
- "parameters": [
- {
- "description": "修改话题",
- "name": "data",
- "in": "body",
- "required": true,
- "schema": {
- "$ref": "#/definitions/request.UpdateTopic"
- }
- }
- ],
- "responses": {
- "200": {
- "description": "{\"success\":true,\"data\":{},\"msg\":\"发布成功\"}",
- "schema": {
- "type": "string"
- }
- }
- }
- }
- },
- "/topic/delete": {
- "post": {
- "security": [
- {
- "BearerAuth": []
- }
- ],
- "consumes": [
- "application/json"
- ],
- "produces": [
- "application/json"
- ],
- "tags": [
- "帖子话题"
- ],
- "summary": "删除任务",
- "parameters": [
- {
- "description": "删除话题",
- "name": "data",
- "in": "body",
- "required": true,
- "schema": {
- "$ref": "#/definitions/request.IdsReq"
- }
- }
- ],
- "responses": {
- "200": {
- "description": "{\"success\":true,\"data\":{},\"msg\":\"删除成功\"}",
- "schema": {
- "type": "string"
- }
- }
- }
- }
- },
- "/topic/detail": {
- "get": {
- "security": [
- {
- "BearerAuth": []
- }
- ],
- "produces": [
- "application/json"
- ],
- "tags": [
- "帖子话题"
- ],
- "summary": "话题详情",
- "parameters": [
- {
- "type": "string",
- "description": "id",
- "name": "id",
- "in": "query",
- "required": true
- }
- ],
- "responses": {
- "200": {
- "description": "{\"success\":true,\"data\":{},\"msg\":\"获取成功\"}",
- "schema": {
- "type": "string"
- }
- }
- }
- }
- },
- "/topic/list": {
- "get": {
- "security": [
- {
- "BearerAuth": []
- }
- ],
- "produces": [
- "application/json"
- ],
- "tags": [
- "帖子话题"
- ],
- "summary": "话题列表",
- "responses": {
- "200": {
- "description": "{\"success\":true,\"data\":{},\"msg\":\"获取成功\"}",
- "schema": {
- "type": "string"
- }
- }
- }
- }
- },
- "/topic/page": {
- "post": {
- "security": [
- {
- "BearerAuth": []
- }
- ],
- "consumes": [
- "application/json"
- ],
- "produces": [
- "application/json"
- ],
- "tags": [
- "帖子话题"
- ],
- "summary": "话题分页",
- "parameters": [
- {
- "description": "分页获取话题列表",
- "name": "data",
- "in": "body",
- "required": true,
- "schema": {
- "$ref": "#/definitions/request.PageInfo"
- }
- }
- ],
- "responses": {
- "200": {
- "description": "{\"success\":true,\"data\":{},\"msg\":\"获取成功\"}",
- "schema": {
- "type": "string"
- }
- }
- }
- }
- },
"/user/changePassword": {
"post": {
"security": [
@@ -2823,382 +1604,9 @@
}
}
}
- },
- "/wiki-class/add": {
- "post": {
- "security": [
- {
- "BearerAuth": []
- }
- ],
- "consumes": [
- "application/json"
- ],
- "produces": [
- "application/json"
- ],
- "tags": [
- "百科分类"
- ],
- "summary": "添加分类",
- "parameters": [
- {
- "description": "添加分类",
- "name": "data",
- "in": "body",
- "required": true,
- "schema": {
- "$ref": "#/definitions/request.CreateWikiClass"
- }
- }
- ],
- "responses": {
- "200": {
- "description": "{\"success\":true,\"data\":{},\"msg\":\"发布成功\"}",
- "schema": {
- "type": "string"
- }
- }
- }
- }
- },
- "/wiki-class/delete": {
- "post": {
- "security": [
- {
- "BearerAuth": []
- }
- ],
- "consumes": [
- "application/json"
- ],
- "produces": [
- "application/json"
- ],
- "tags": [
- "百科分类"
- ],
- "summary": "删除分类",
- "parameters": [
- {
- "description": "删除分类",
- "name": "data",
- "in": "body",
- "required": true,
- "schema": {
- "$ref": "#/definitions/request.IdsReq"
- }
- }
- ],
- "responses": {
- "200": {
- "description": "{\"success\":true,\"data\":{},\"msg\":\"删除成功\"}",
- "schema": {
- "type": "string"
- }
- }
- }
- }
- },
- "/wiki-class/detail": {
- "get": {
- "security": [
- {
- "BearerAuth": []
- }
- ],
- "produces": [
- "application/json"
- ],
- "tags": [
- "百科分类"
- ],
- "summary": "分类详情",
- "parameters": [
- {
- "type": "string",
- "description": "id",
- "name": "id",
- "in": "query",
- "required": true
- }
- ],
- "responses": {
- "200": {
- "description": "{\"success\":true,\"data\":{},\"msg\":\"获取成功\"}",
- "schema": {
- "type": "string"
- }
- }
- }
- }
- },
- "/wiki-class/list": {
- "get": {
- "security": [
- {
- "BearerAuth": []
- }
- ],
- "produces": [
- "application/json"
- ],
- "tags": [
- "百科分类"
- ],
- "summary": "分类列表",
- "responses": {
- "200": {
- "description": "{\"success\":true,\"data\":{},\"msg\":\"获取成功\"}",
- "schema": {
- "type": "string"
- }
- }
- }
- }
- },
- "/wiki-class/page": {
- "post": {
- "security": [
- {
- "BearerAuth": []
- }
- ],
- "consumes": [
- "application/json"
- ],
- "produces": [
- "application/json"
- ],
- "tags": [
- "百科分类"
- ],
- "summary": "分类分页",
- "parameters": [
- {
- "description": "分页获取分类列表",
- "name": "data",
- "in": "body",
- "required": true,
- "schema": {
- "$ref": "#/definitions/request.PageInfo"
- }
- }
- ],
- "responses": {
- "200": {
- "description": "{\"success\":true,\"data\":{},\"msg\":\"获取成功\"}",
- "schema": {
- "type": "string"
- }
- }
- }
- }
- },
- "/wiki-class/update": {
- "post": {
- "security": [
- {
- "BearerAuth": []
- }
- ],
- "consumes": [
- "application/json"
- ],
- "produces": [
- "application/json"
- ],
- "tags": [
- "百科分类"
- ],
- "summary": "修改分类(可直接传入ossId修改图片)",
- "parameters": [
- {
- "description": "修改分类",
- "name": "data",
- "in": "body",
- "required": true,
- "schema": {
- "$ref": "#/definitions/request.UpdateWikiClass"
- }
- }
- ],
- "responses": {
- "200": {
- "description": "{\"success\":true,\"data\":{},\"msg\":\"发布成功\"}",
- "schema": {
- "type": "string"
- }
- }
- }
- }
- },
- "/wiki/add": {
- "post": {
- "security": [
- {
- "BearerAuth": []
- }
- ],
- "consumes": [
- "application/json"
- ],
- "produces": [
- "application/json"
- ],
- "tags": [
- "百科"
- ],
- "summary": "添加百科",
- "parameters": [
- {
- "description": "添加百科",
- "name": "data",
- "in": "body",
- "required": true,
- "schema": {
- "$ref": "#/definitions/request.CreateWiki"
- }
- }
- ],
- "responses": {
- "200": {
- "description": "{\"success\":true,\"data\":{},\"msg\":\"发布成功\"}",
- "schema": {
- "type": "string"
- }
- }
- }
- }
- },
- "/wiki/detail": {
- "get": {
- "security": [
- {
- "BearerAuth": []
- }
- ],
- "produces": [
- "application/json"
- ],
- "tags": [
- "百科"
- ],
- "summary": "百科详情",
- "parameters": [
- {
- "type": "string",
- "description": "id",
- "name": "id",
- "in": "query",
- "required": true
- }
- ],
- "responses": {
- "200": {
- "description": "{\"success\":true,\"data\":{},\"msg\":\"获取成功\"}",
- "schema": {
- "type": "string"
- }
- }
- }
- }
- },
- "/wiki/page": {
- "post": {
- "security": [
- {
- "BearerAuth": []
- }
- ],
- "consumes": [
- "application/json"
- ],
- "produces": [
- "application/json"
- ],
- "tags": [
- "百科"
- ],
- "summary": "分页",
- "parameters": [
- {
- "description": "百科分页",
- "name": "data",
- "in": "body",
- "required": true,
- "schema": {
- "$ref": "#/definitions/request.WikiPage"
- }
- }
- ],
- "responses": {
- "200": {
- "description": "{\"success\":true,\"data\":{},\"msg\":\"发布成功\"}",
- "schema": {
- "type": "string"
- }
- }
- }
- }
- },
- "/wiki/update": {
- "post": {
- "security": [
- {
- "BearerAuth": []
- }
- ],
- "consumes": [
- "application/json"
- ],
- "produces": [
- "application/json"
- ],
- "tags": [
- "百科"
- ],
- "summary": "修改百科",
- "parameters": [
- {
- "description": "修改百科",
- "name": "data",
- "in": "body",
- "required": true,
- "schema": {
- "$ref": "#/definitions/request.UpdateWiki"
- }
- }
- ],
- "responses": {
- "200": {
- "description": "{\"success\":true,\"data\":{},\"msg\":\"发布成功\"}",
- "schema": {
- "type": "string"
- }
- }
- }
- }
}
},
"definitions": {
- "request.CarePlan": {
- "type": "object",
- "properties": {
- "icon": {
- "description": "icon信息",
- "type": "string"
- },
- "name": {
- "description": "农事名称",
- "type": "string"
- },
- "period": {
- "description": "周期",
- "type": "integer"
- }
- }
- },
"request.ChangePwd": {
"type": "object",
"properties": {
@@ -3210,381 +1618,6 @@
}
}
},
- "request.CompleteTask": {
- "type": "object",
- "required": [
- "taskId"
- ],
- "properties": {
- "remark": {
- "type": "string"
- },
- "taskId": {
- "type": "string"
- }
- }
- },
- "request.CreateBadge": {
- "type": "object",
- "properties": {
- "comparator": {
- "type": "string"
- },
- "description": {
- "type": "string"
- },
- "dimension": {
- "description": "维度: EXPERTISE(专家), PERSISTENCE(勤勉), JOURNAL(记录)",
- "type": "string"
- },
- "groupId": {
- "description": "组ID: 用于前端聚合显示 (e.g. \"fertilizerMaster\")",
- "type": "string"
- },
- "iconId": {
- "type": "string"
- },
- "name": {
- "type": "string"
- },
- "rewardSunlight": {
- "type": "integer"
- },
- "sort": {
- "type": "integer"
- },
- "targetAction": {
- "description": "触发动作: ACT_FERTILIZE, ACT_WATER...",
- "type": "string"
- },
- "threshold": {
- "type": "integer"
- },
- "tier": {
- "description": "等级: 1=铜, 2=银, 3=金",
- "type": "integer"
- }
- }
- },
- "request.CreateCarePlan": {
- "type": "object",
- "required": [
- "plantId"
- ],
- "properties": {
- "icon": {
- "description": "icon信息",
- "type": "string"
- },
- "name": {
- "description": "农事名称",
- "type": "string"
- },
- "period": {
- "description": "周期",
- "type": "integer"
- },
- "plantId": {
- "type": "string"
- }
- }
- },
- "request.CreateComment": {
- "type": "object",
- "required": [
- "content",
- "postId"
- ],
- "properties": {
- "content": {
- "description": "评论内容",
- "type": "string"
- },
- "postId": {
- "description": "帖子id",
- "type": "string"
- }
- }
- },
- "request.CreateGrowthRecord": {
- "type": "object",
- "required": [
- "plantId"
- ],
- "properties": {
- "content": {
- "type": "string"
- },
- "desc": {
- "type": "string"
- },
- "name": {
- "type": "string"
- },
- "ossIds": {
- "type": "array",
- "items": {
- "type": "string"
- }
- },
- "plantId": {
- "type": "string"
- },
- "tag": {
- "type": "string"
- }
- }
- },
- "request.CreateLevelConf": {
- "type": "object",
- "properties": {
- "level": {
- "description": "等级数值",
- "type": "integer"
- },
- "minSunlight": {
- "description": "达到该等级所需的最小阳光值",
- "type": "integer"
- },
- "perks": {
- "description": "解锁权益描述 (e.g., \"解锁智能诊断\")",
- "type": "string"
- },
- "title": {
- "description": "等级称号 (e.g., \"萌芽园丁\")",
- "type": "string"
- }
- }
- },
- "request.CreateMyPlant": {
- "type": "object",
- "properties": {
- "carePlans": {
- "description": "养护计划",
- "type": "array",
- "items": {
- "$ref": "#/definitions/request.CarePlan"
- }
- },
- "name": {
- "description": "植物名称",
- "type": "string"
- },
- "ossIds": {
- "description": "图片ids",
- "type": "array",
- "items": {
- "type": "string"
- }
- },
- "placement": {
- "description": "摆放位置",
- "type": "string"
- },
- "plantTime": {
- "description": "种植时间",
- "type": "string"
- },
- "plantingMaterial": {
- "description": "植料(即土的材质)",
- "type": "string"
- },
- "potMaterial": {
- "description": "花盆材质",
- "type": "string"
- },
- "potSize": {
- "description": "花盆大小 如直径 20cm × 高度 18cm",
- "type": "string"
- },
- "sunlight": {
- "description": "光照条件如每日12小时",
- "type": "string"
- }
- }
- },
- "request.CreatePost": {
- "type": "object",
- "properties": {
- "content": {
- "description": "内容",
- "type": "string"
- },
- "location": {
- "description": "位置",
- "type": "string"
- },
- "ossIds": {
- "description": "图片id[]",
- "type": "array",
- "items": {
- "type": "string"
- }
- },
- "title": {
- "description": "标题 必须",
- "type": "string"
- }
- }
- },
- "request.CreateTopic": {
- "type": "object",
- "properties": {
- "endTime": {
- "type": "string"
- },
- "remark": {
- "type": "string"
- },
- "startTime": {
- "type": "string"
- },
- "title": {
- "type": "string"
- }
- }
- },
- "request.CreateWiki": {
- "type": "object",
- "required": [
- "name"
- ],
- "properties": {
- "aliases": {
- "description": "别名",
- "type": "string"
- },
- "classIds": {
- "description": "分类id",
- "type": "array",
- "items": {
- "type": "string"
- }
- },
- "difficulty": {
- "description": "种植难度 1-5级",
- "type": "integer"
- },
- "distributionArea": {
- "description": "分布区域",
- "type": "string"
- },
- "flowerDiameter": {
- "description": "花直径(cm)",
- "type": "integer"
- },
- "floweringColor": {
- "description": "花色",
- "type": "string"
- },
- "floweringPeriod": {
- "description": "开花期",
- "type": "string"
- },
- "floweringShape": {
- "description": "花形",
- "type": "string"
- },
- "foliageColor": {
- "description": "叶色",
- "type": "string"
- },
- "foliageShape": {
- "description": "叶形",
- "type": "string"
- },
- "foliageType": {
- "description": "叶型",
- "type": "string"
- },
- "fruit": {
- "description": "果",
- "type": "string"
- },
- "genus": {
- "description": "属",
- "type": "string"
- },
- "growthHabit": {
- "description": "生长习性",
- "type": "string"
- },
- "height": {
- "description": "高度(cm)",
- "type": "integer"
- },
- "isHot": {
- "description": "是否热门",
- "type": "integer"
- },
- "latinName": {
- "description": "拉丁名",
- "type": "string"
- },
- "lifeCycle": {
- "description": "生命周期",
- "type": "string"
- },
- "lightIntensity": {
- "description": "光照强度",
- "type": "string"
- },
- "lightType": {
- "description": "光照类型(直射,散射等)",
- "type": "string"
- },
- "name": {
- "description": "名称",
- "type": "string"
- },
- "optimalTempPeriod": {
- "description": "最佳温度区间",
- "type": "string"
- },
- "ossIds": {
- "description": "图片",
- "type": "array",
- "items": {
- "type": "string"
- }
- },
- "pestsDiseases": {
- "description": "常见病虫害",
- "type": "string"
- },
- "relatedWikiIds": {
- "description": "相关推荐",
- "type": "array",
- "items": {
- "type": "string"
- }
- },
- "reproductionMethod": {
- "description": "繁殖方法",
- "type": "string"
- },
- "stem": {
- "description": "茎",
- "type": "string"
- }
- }
- },
- "request.CreateWikiClass": {
- "type": "object",
- "required": [
- "name"
- ],
- "properties": {
- "name": {
- "description": "分类名称",
- "type": "string"
- },
- "ossId": {
- "description": "图片id",
- "type": "string"
- }
- }
- },
"request.GetClientList": {
"type": "object",
"properties": {
@@ -3741,371 +1774,6 @@
}
}
},
- "request.PageInfo": {
- "type": "object",
- "properties": {
- "current": {
- "description": "页码",
- "type": "integer"
- },
- "keyword": {
- "description": "关键字",
- "type": "string"
- },
- "pageSize": {
- "description": "每页大小",
- "type": "integer"
- }
- }
- },
- "request.PostPage": {
- "type": "object",
- "properties": {
- "current": {
- "description": "页码",
- "type": "integer"
- },
- "hasReviewed": {
- "description": "是否审核通过",
- "type": "integer"
- },
- "keyword": {
- "description": "关键字",
- "type": "string"
- },
- "pageSize": {
- "description": "每页大小",
- "type": "integer"
- },
- "title": {
- "description": "标题",
- "type": "string"
- }
- }
- },
- "request.UpdateBadge": {
- "type": "object",
- "required": [
- "id"
- ],
- "properties": {
- "comparator": {
- "type": "string"
- },
- "description": {
- "type": "string"
- },
- "dimension": {
- "description": "维度: EXPERTISE(专家), PERSISTENCE(勤勉), JOURNAL(记录)",
- "type": "string"
- },
- "groupId": {
- "description": "组Id: 用于前端聚合显示 (e.g. \"fertilizerMaster\")",
- "type": "string"
- },
- "iconId": {
- "type": "string"
- },
- "id": {
- "type": "string"
- },
- "name": {
- "type": "string"
- },
- "rewardSunlight": {
- "type": "integer"
- },
- "sort": {
- "type": "integer"
- },
- "targetAction": {
- "description": "触发动作: ACT_FERTILIZE, ACT_WATER...",
- "type": "string"
- },
- "threshold": {
- "type": "integer"
- },
- "tier": {
- "description": "等级: 1=铜, 2=银, 3=金",
- "type": "integer"
- }
- }
- },
- "request.UpdateLevelConf": {
- "type": "object",
- "required": [
- "id"
- ],
- "properties": {
- "id": {
- "type": "string"
- },
- "level": {
- "description": "等级数值",
- "type": "integer"
- },
- "minSunlight": {
- "description": "达到该等级所需的最小阳光值",
- "type": "integer"
- },
- "perks": {
- "description": "解锁权益描述 (e.g., \"解锁智能诊断\")",
- "type": "string"
- },
- "title": {
- "description": "等级称号 (e.g., \"萌芽园丁\")",
- "type": "string"
- }
- }
- },
- "request.UpdateMyPlant": {
- "type": "object",
- "required": [
- "id"
- ],
- "properties": {
- "carePlans": {
- "type": "array",
- "items": {
- "$ref": "#/definitions/request.UpdatePlan"
- }
- },
- "id": {
- "type": "string"
- },
- "name": {
- "description": "植物名称",
- "type": "string"
- },
- "placement": {
- "description": "摆放位置",
- "type": "string"
- },
- "plantingMaterial": {
- "description": "植料(即土的材质)",
- "type": "string"
- },
- "potMaterial": {
- "description": "花盆材质",
- "type": "string"
- },
- "potSize": {
- "description": "花盆大小 如直径 20cm × 高度 18cm",
- "type": "string"
- },
- "sunlight": {
- "description": "光照条件如每日12小时",
- "type": "string"
- }
- }
- },
- "request.UpdatePlan": {
- "type": "object",
- "required": [
- "id"
- ],
- "properties": {
- "icon": {
- "description": "icon信息",
- "type": "string"
- },
- "id": {
- "type": "string"
- },
- "name": {
- "description": "农事名称",
- "type": "string"
- },
- "period": {
- "description": "周期",
- "type": "integer"
- }
- }
- },
- "request.UpdateProfile": {
- "type": "object",
- "properties": {
- "avatarId": {
- "type": "string"
- },
- "nickname": {
- "type": "string"
- }
- }
- },
- "request.UpdateTopic": {
- "type": "object",
- "required": [
- "id"
- ],
- "properties": {
- "endTime": {
- "type": "string"
- },
- "id": {
- "type": "integer"
- },
- "remark": {
- "type": "string"
- },
- "startTime": {
- "type": "string"
- },
- "title": {
- "type": "string"
- }
- }
- },
- "request.UpdateWiki": {
- "type": "object",
- "required": [
- "id"
- ],
- "properties": {
- "aliases": {
- "description": "别名",
- "type": "string"
- },
- "difficulty": {
- "description": "种植难度 1-5级",
- "type": "integer"
- },
- "distributionArea": {
- "description": "分布区域",
- "type": "string"
- },
- "flowerDiameter": {
- "description": "花直径(cm)",
- "type": "integer"
- },
- "floweringColor": {
- "description": "花色",
- "type": "string"
- },
- "floweringPeriod": {
- "description": "开花期",
- "type": "string"
- },
- "floweringShape": {
- "description": "花形",
- "type": "string"
- },
- "foliageColor": {
- "description": "叶色",
- "type": "string"
- },
- "foliageShape": {
- "description": "叶形",
- "type": "string"
- },
- "foliageType": {
- "description": "叶型",
- "type": "string"
- },
- "fruit": {
- "description": "果",
- "type": "string"
- },
- "genus": {
- "description": "属",
- "type": "string"
- },
- "growthHabit": {
- "description": "生长习性",
- "type": "string"
- },
- "height": {
- "description": "高度(cm)",
- "type": "integer"
- },
- "id": {
- "type": "string"
- },
- "latinName": {
- "description": "拉丁名",
- "type": "string"
- },
- "lifeCycle": {
- "description": "生命周期",
- "type": "string"
- },
- "lightIntensity": {
- "description": "光照强度",
- "type": "string"
- },
- "lightType": {
- "description": "光照类型(直射,散射等)",
- "type": "string"
- },
- "name": {
- "description": "名称",
- "type": "string"
- },
- "optimalTempPeriod": {
- "description": "最佳温度区间",
- "type": "string"
- },
- "pestsDiseases": {
- "description": "常见病虫害",
- "type": "string"
- },
- "stem": {
- "description": "茎",
- "type": "string"
- }
- }
- },
- "request.UpdateWikiClass": {
- "type": "object",
- "required": [
- "id"
- ],
- "properties": {
- "id": {
- "type": "string"
- },
- "name": {
- "description": "分类名称",
- "type": "string"
- },
- "ossId": {
- "description": "图片id",
- "type": "string"
- }
- }
- },
- "request.WikiPage": {
- "type": "object",
- "properties": {
- "classId": {
- "description": "分类id",
- "type": "array",
- "items": {
- "type": "string"
- }
- },
- "current": {
- "description": "页码",
- "type": "integer"
- },
- "isHot": {
- "description": "是否热门 0否 1是",
- "type": "integer"
- },
- "keyword": {
- "description": "关键字",
- "type": "string"
- },
- "name": {
- "description": "植物名称",
- "type": "string"
- },
- "pageSize": {
- "description": "每页大小",
- "type": "integer"
- }
- }
- },
"response.CaptchaRes": {
"type": "object",
"properties": {
diff --git a/docs/swagger.yaml b/docs/swagger.yaml
index 0f4c487..b84d07f 100644
--- a/docs/swagger.yaml
+++ b/docs/swagger.yaml
@@ -1,16 +1,4 @@
definitions:
- request.CarePlan:
- properties:
- icon:
- description: icon信息
- type: string
- name:
- description: 农事名称
- type: string
- period:
- description: 周期
- type: integer
- type: object
request.ChangePwd:
properties:
id:
@@ -18,271 +6,6 @@ definitions:
newPwd:
type: string
type: object
- request.CompleteTask:
- properties:
- remark:
- type: string
- taskId:
- type: string
- required:
- - taskId
- type: object
- request.CreateBadge:
- properties:
- comparator:
- type: string
- description:
- type: string
- dimension:
- description: '维度: EXPERTISE(专家), PERSISTENCE(勤勉), JOURNAL(记录)'
- type: string
- groupId:
- description: '组ID: 用于前端聚合显示 (e.g. "fertilizerMaster")'
- type: string
- iconId:
- type: string
- name:
- type: string
- rewardSunlight:
- type: integer
- sort:
- type: integer
- targetAction:
- description: '触发动作: ACT_FERTILIZE, ACT_WATER...'
- type: string
- threshold:
- type: integer
- tier:
- description: '等级: 1=铜, 2=银, 3=金'
- type: integer
- type: object
- request.CreateCarePlan:
- properties:
- icon:
- description: icon信息
- type: string
- name:
- description: 农事名称
- type: string
- period:
- description: 周期
- type: integer
- plantId:
- type: string
- required:
- - plantId
- type: object
- request.CreateComment:
- properties:
- content:
- description: 评论内容
- type: string
- postId:
- description: 帖子id
- type: string
- required:
- - content
- - postId
- type: object
- request.CreateGrowthRecord:
- properties:
- content:
- type: string
- desc:
- type: string
- name:
- type: string
- ossIds:
- items:
- type: string
- type: array
- plantId:
- type: string
- tag:
- type: string
- required:
- - plantId
- type: object
- request.CreateLevelConf:
- properties:
- level:
- description: 等级数值
- type: integer
- minSunlight:
- description: 达到该等级所需的最小阳光值
- type: integer
- perks:
- description: 解锁权益描述 (e.g., "解锁智能诊断")
- type: string
- title:
- description: 等级称号 (e.g., "萌芽园丁")
- type: string
- type: object
- request.CreateMyPlant:
- properties:
- carePlans:
- description: 养护计划
- items:
- $ref: '#/definitions/request.CarePlan'
- type: array
- name:
- description: 植物名称
- type: string
- ossIds:
- description: 图片ids
- items:
- type: string
- type: array
- placement:
- description: 摆放位置
- type: string
- plantTime:
- description: 种植时间
- type: string
- plantingMaterial:
- description: 植料(即土的材质)
- type: string
- potMaterial:
- description: 花盆材质
- type: string
- potSize:
- description: 花盆大小 如直径 20cm × 高度 18cm
- type: string
- sunlight:
- description: 光照条件如每日12小时
- type: string
- type: object
- request.CreatePost:
- properties:
- content:
- description: 内容
- type: string
- location:
- description: 位置
- type: string
- ossIds:
- description: 图片id[]
- items:
- type: string
- type: array
- title:
- description: 标题 必须
- type: string
- type: object
- request.CreateTopic:
- properties:
- endTime:
- type: string
- remark:
- type: string
- startTime:
- type: string
- title:
- type: string
- type: object
- request.CreateWiki:
- properties:
- aliases:
- description: 别名
- type: string
- classIds:
- description: 分类id
- items:
- type: string
- type: array
- difficulty:
- description: 种植难度 1-5级
- type: integer
- distributionArea:
- description: 分布区域
- type: string
- flowerDiameter:
- description: 花直径(cm)
- type: integer
- floweringColor:
- description: 花色
- type: string
- floweringPeriod:
- description: 开花期
- type: string
- floweringShape:
- description: 花形
- type: string
- foliageColor:
- description: 叶色
- type: string
- foliageShape:
- description: 叶形
- type: string
- foliageType:
- description: 叶型
- type: string
- fruit:
- description: 果
- type: string
- genus:
- description: 属
- type: string
- growthHabit:
- description: 生长习性
- type: string
- height:
- description: 高度(cm)
- type: integer
- isHot:
- description: 是否热门
- type: integer
- latinName:
- description: 拉丁名
- type: string
- lifeCycle:
- description: 生命周期
- type: string
- lightIntensity:
- description: 光照强度
- type: string
- lightType:
- description: 光照类型(直射,散射等)
- type: string
- name:
- description: 名称
- type: string
- optimalTempPeriod:
- description: 最佳温度区间
- type: string
- ossIds:
- description: 图片
- items:
- type: string
- type: array
- pestsDiseases:
- description: 常见病虫害
- type: string
- relatedWikiIds:
- description: 相关推荐
- items:
- type: string
- type: array
- reproductionMethod:
- description: 繁殖方法
- type: string
- stem:
- description: 茎
- type: string
- required:
- - name
- type: object
- request.CreateWikiClass:
- properties:
- name:
- description: 分类名称
- type: string
- ossId:
- description: 图片id
- type: string
- required:
- - name
- type: object
request.GetClientList:
properties:
clientId:
@@ -388,264 +111,6 @@ definitions:
password:
type: string
type: object
- request.PageInfo:
- properties:
- current:
- description: 页码
- type: integer
- keyword:
- description: 关键字
- type: string
- pageSize:
- description: 每页大小
- type: integer
- type: object
- request.PostPage:
- properties:
- current:
- description: 页码
- type: integer
- hasReviewed:
- description: 是否审核通过
- type: integer
- keyword:
- description: 关键字
- type: string
- pageSize:
- description: 每页大小
- type: integer
- title:
- description: 标题
- type: string
- type: object
- request.UpdateBadge:
- properties:
- comparator:
- type: string
- description:
- type: string
- dimension:
- description: '维度: EXPERTISE(专家), PERSISTENCE(勤勉), JOURNAL(记录)'
- type: string
- groupId:
- description: '组Id: 用于前端聚合显示 (e.g. "fertilizerMaster")'
- type: string
- iconId:
- type: string
- id:
- type: string
- name:
- type: string
- rewardSunlight:
- type: integer
- sort:
- type: integer
- targetAction:
- description: '触发动作: ACT_FERTILIZE, ACT_WATER...'
- type: string
- threshold:
- type: integer
- tier:
- description: '等级: 1=铜, 2=银, 3=金'
- type: integer
- required:
- - id
- type: object
- request.UpdateLevelConf:
- properties:
- id:
- type: string
- level:
- description: 等级数值
- type: integer
- minSunlight:
- description: 达到该等级所需的最小阳光值
- type: integer
- perks:
- description: 解锁权益描述 (e.g., "解锁智能诊断")
- type: string
- title:
- description: 等级称号 (e.g., "萌芽园丁")
- type: string
- required:
- - id
- type: object
- request.UpdateMyPlant:
- properties:
- carePlans:
- items:
- $ref: '#/definitions/request.UpdatePlan'
- type: array
- id:
- type: string
- name:
- description: 植物名称
- type: string
- placement:
- description: 摆放位置
- type: string
- plantingMaterial:
- description: 植料(即土的材质)
- type: string
- potMaterial:
- description: 花盆材质
- type: string
- potSize:
- description: 花盆大小 如直径 20cm × 高度 18cm
- type: string
- sunlight:
- description: 光照条件如每日12小时
- type: string
- required:
- - id
- type: object
- request.UpdatePlan:
- properties:
- icon:
- description: icon信息
- type: string
- id:
- type: string
- name:
- description: 农事名称
- type: string
- period:
- description: 周期
- type: integer
- required:
- - id
- type: object
- request.UpdateProfile:
- properties:
- avatarId:
- type: string
- nickname:
- type: string
- type: object
- request.UpdateTopic:
- properties:
- endTime:
- type: string
- id:
- type: integer
- remark:
- type: string
- startTime:
- type: string
- title:
- type: string
- required:
- - id
- type: object
- request.UpdateWiki:
- properties:
- aliases:
- description: 别名
- type: string
- difficulty:
- description: 种植难度 1-5级
- type: integer
- distributionArea:
- description: 分布区域
- type: string
- flowerDiameter:
- description: 花直径(cm)
- type: integer
- floweringColor:
- description: 花色
- type: string
- floweringPeriod:
- description: 开花期
- type: string
- floweringShape:
- description: 花形
- type: string
- foliageColor:
- description: 叶色
- type: string
- foliageShape:
- description: 叶形
- type: string
- foliageType:
- description: 叶型
- type: string
- fruit:
- description: 果
- type: string
- genus:
- description: 属
- type: string
- growthHabit:
- description: 生长习性
- type: string
- height:
- description: 高度(cm)
- type: integer
- id:
- type: string
- latinName:
- description: 拉丁名
- type: string
- lifeCycle:
- description: 生命周期
- type: string
- lightIntensity:
- description: 光照强度
- type: string
- lightType:
- description: 光照类型(直射,散射等)
- type: string
- name:
- description: 名称
- type: string
- optimalTempPeriod:
- description: 最佳温度区间
- type: string
- pestsDiseases:
- description: 常见病虫害
- type: string
- stem:
- description: 茎
- type: string
- required:
- - id
- type: object
- request.UpdateWikiClass:
- properties:
- id:
- type: string
- name:
- description: 分类名称
- type: string
- ossId:
- description: 图片id
- type: string
- required:
- - id
- type: object
- request.WikiPage:
- properties:
- classId:
- description: 分类id
- items:
- type: string
- type: array
- current:
- description: 页码
- type: integer
- isHot:
- description: 是否热门 0否 1是
- type: integer
- keyword:
- description: 关键字
- type: string
- name:
- description: 植物名称
- type: string
- pageSize:
- description: 每页大小
- type: integer
- type: object
response.CaptchaRes:
properties:
captcha:
@@ -963,61 +428,6 @@ paths:
summary: 小程序登录
tags:
- 登录相关
- /classify/myClassifyLog:
- post:
- consumes:
- - application/json
- parameters:
- - description: 分页
- in: body
- name: data
- required: true
- schema:
- $ref: '#/definitions/request.PageInfo'
- produces:
- - application/json
- responses:
- "200":
- description: 识别记录
- schema:
- allOf:
- - $ref: '#/definitions/response.Response'
- - properties:
- msg:
- type: string
- type: object
- security:
- - ApiKeyAuth: []
- summary: 我的植物识别记录
- tags:
- - 识别相关
- /classify/plant:
- post:
- consumes:
- - multipart/form-data
- parameters:
- - description: 植物识别
- in: formData
- name: file
- required: true
- type: file
- produces:
- - application/json
- responses:
- "200":
- description: 文件OCR
- schema:
- allOf:
- - $ref: '#/definitions/response.Response'
- - properties:
- msg:
- type: string
- type: object
- security:
- - ApiKeyAuth: []
- summary: base64植物识别
- tags:
- - 识别相关
/client/delete:
post:
consumes:
@@ -1160,186 +570,6 @@ paths:
summary: 更新client
tags:
- 客户端管理
- /config/badge/add:
- post:
- consumes:
- - application/json
- parameters:
- - description: 添加徽章配置
- in: body
- name: data
- required: true
- schema:
- $ref: '#/definitions/request.CreateBadge'
- produces:
- - application/json
- responses:
- "200":
- description: '{"success":true,"data":{},"msg":"添加成功"}'
- schema:
- type: string
- security:
- - BearerAuth: []
- summary: 添加徽章配置
- tags:
- - 徽章配置
- /config/badge/delete:
- get:
- parameters:
- - description: id
- in: query
- name: id
- required: true
- type: string
- produces:
- - application/json
- responses:
- "200":
- description: '{"success":true,"data":{},"msg":"删除成功"}'
- schema:
- type: string
- security:
- - BearerAuth: []
- summary: 删除徽章配置
- tags:
- - 徽章配置
- /config/badge/find:
- get:
- parameters:
- - description: id
- in: query
- name: id
- required: true
- type: string
- produces:
- - application/json
- responses:
- "200":
- description: '{"success":true,"data":{},"msg":"获取成功"}'
- schema:
- type: string
- security:
- - BearerAuth: []
- summary: 根据ID获取徽章配置
- tags:
- - 徽章配置
- /config/badge/tree:
- get:
- produces:
- - application/json
- responses:
- "200":
- description: '{"success":true,"data":{},"msg":"获取成功"}'
- schema:
- type: string
- security:
- - BearerAuth: []
- summary: 获取徽章配置树形结构
- tags:
- - 徽章配置
- /config/badge/update:
- post:
- consumes:
- - application/json
- parameters:
- - description: 更新参数
- in: body
- name: data
- required: true
- schema:
- $ref: '#/definitions/request.UpdateBadge'
- produces:
- - application/json
- responses:
- "200":
- description: '{"success":true,"data":{},"msg":"更新成功"}'
- schema:
- type: string
- security:
- - BearerAuth: []
- summary: 更新徽章配置
- tags:
- - 徽章配置
- /config/level/add:
- post:
- consumes:
- - application/json
- parameters:
- - description: 添加等级配置
- in: body
- name: data
- required: true
- schema:
- $ref: '#/definitions/request.CreateLevelConf'
- produces:
- - application/json
- responses:
- "200":
- description: '{"success":true,"data":{},"msg":"添加成功"}'
- schema:
- type: string
- security:
- - BearerAuth: []
- summary: 添加等级配置
- tags:
- - 等级配置
- /config/level/detail:
- get:
- parameters:
- - description: 等级配置id
- in: query
- name: id
- required: true
- type: string
- produces:
- - application/json
- responses:
- "200":
- description: '{"success":true,"data":{},"msg":"查询成功"}'
- schema:
- type: string
- security:
- - BearerAuth: []
- summary: 等级配置详情
- tags:
- - 等级配置
- /config/level/list:
- get:
- produces:
- - application/json
- responses:
- "200":
- description: '{"success":true,"data":{},"msg":"查询成功"}'
- schema:
- type: string
- security:
- - BearerAuth: []
- summary: 等级配置列表
- tags:
- - 等级配置
- /config/level/update:
- post:
- consumes:
- - application/json
- parameters:
- - description: 修改等级配置
- in: body
- name: data
- required: true
- schema:
- $ref: '#/definitions/request.UpdateLevelConf'
- produces:
- - application/json
- responses:
- "200":
- description: '{"success":true,"data":{},"msg":"修改成功"}'
- schema:
- type: string
- security:
- - BearerAuth: []
- summary: 修改等级配置
- tags:
- - 等级配置
/menu/delete:
get:
description: 删除menu
@@ -1634,400 +864,6 @@ paths:
summary: 文件上传
tags:
- 文件相关
- /plant/add:
- post:
- consumes:
- - application/json
- parameters:
- - description: 创建植物
- in: body
- name: data
- required: true
- schema:
- $ref: '#/definitions/request.CreateMyPlant'
- produces:
- - application/json
- responses:
- "200":
- description: '{"success":true,"data":{},"msg":"添加成功"}'
- schema:
- type: string
- security:
- - BearerAuth: []
- summary: 添加植物
- tags:
- - 我的植物
- /plant/completeTask:
- post:
- consumes:
- - application/json
- parameters:
- - description: 完成任务
- in: body
- name: data
- required: true
- schema:
- $ref: '#/definitions/request.CompleteTask'
- produces:
- - application/json
- responses:
- "200":
- description: '{"success":true,"data":{},"msg":"完成任务"}'
- schema:
- type: string
- security:
- - BearerAuth: []
- summary: 完成任务
- tags:
- - 我的植物
- /plant/deletePlan:
- post:
- consumes:
- - application/json
- parameters:
- - description: 删除植物
- in: body
- name: data
- required: true
- schema:
- $ref: '#/definitions/request.IdsReq'
- produces:
- - application/json
- responses:
- "200":
- description: '{"success":true,"data":{},"msg":"删除成功"}'
- schema:
- type: string
- security:
- - BearerAuth: []
- summary: 删除任务
- tags:
- - 我的植物
- /plant/deletePlant:
- post:
- consumes:
- - application/json
- parameters:
- - description: 删除植物
- in: body
- name: data
- required: true
- schema:
- $ref: '#/definitions/request.IdsReq'
- produces:
- - application/json
- responses:
- "200":
- description: '{"success":true,"data":{},"msg":"删除成功"}'
- schema:
- type: string
- security:
- - BearerAuth: []
- summary: 删除植物
- tags:
- - 我的植物
- /plant/detail:
- get:
- parameters:
- - description: id
- in: query
- name: id
- required: true
- type: string
- produces:
- - application/json
- responses:
- "200":
- description: '{"success":true,"data":{},"msg":"获取ById成功"}'
- schema:
- type: string
- security:
- - BearerAuth: []
- summary: ById植物详情
- tags:
- - 我的植物
- /plant/growth/add:
- post:
- consumes:
- - application/json
- parameters:
- - description: 添加成长记录
- in: body
- name: data
- required: true
- schema:
- $ref: '#/definitions/request.CreateGrowthRecord'
- produces:
- - application/json
- responses:
- "200":
- description: '{"success":true,"data":{},"msg":"添加成功"}'
- schema:
- type: string
- security:
- - BearerAuth: []
- summary: 添加成长记录
- tags:
- - 我的植物
- /plant/page:
- post:
- consumes:
- - application/json
- parameters:
- - description: 分页获取植物列表
- in: body
- name: data
- required: true
- schema:
- $ref: '#/definitions/request.PageInfo'
- produces:
- - application/json
- responses:
- "200":
- description: '{"success":true,"data":{},"msg":"获取成功"}'
- schema:
- type: string
- security:
- - BearerAuth: []
- summary: 植物列表
- tags:
- - 我的植物
- /plant/plan/add:
- post:
- consumes:
- - application/json
- parameters:
- - description: 添加养护事项
- in: body
- name: data
- required: true
- schema:
- $ref: '#/definitions/request.CreateCarePlan'
- produces:
- - application/json
- responses:
- "200":
- description: '{"success":true,"data":{},"msg":"添加成功"}'
- schema:
- type: string
- security:
- - BearerAuth: []
- summary: 添加养护事项
- tags:
- - 我的植物
- /plant/plan/delete:
- get:
- parameters:
- - description: id
- in: query
- name: id
- required: true
- type: string
- produces:
- - application/json
- responses:
- "200":
- description: '{"success":true,"data":{},"msg":"删除成功"}'
- schema:
- type: string
- security:
- - BearerAuth: []
- summary: 删除养护事项
- tags:
- - 我的植物
- /plant/todayTask:
- get:
- consumes:
- - application/json
- produces:
- - application/json
- responses:
- "200":
- description: '{"success":true,"data":{},"msg":"获取成功"}'
- schema:
- type: string
- security:
- - BearerAuth: []
- summary: 今日任务
- tags:
- - 我的植物
- /plant/update:
- post:
- consumes:
- - application/json
- parameters:
- - description: 修改ById植物
- in: body
- name: data
- required: true
- schema:
- $ref: '#/definitions/request.UpdateMyPlant'
- produces:
- - application/json
- responses:
- "200":
- description: '{"success":true,"data":{},"msg":"修改ById成功"}'
- schema:
- type: string
- security:
- - BearerAuth: []
- summary: 修改ById植物
- tags:
- - 我的植物
- /post/comment:
- post:
- consumes:
- - application/json
- parameters:
- - description: 评论帖子
- in: body
- name: data
- required: true
- schema:
- $ref: '#/definitions/request.CreateComment'
- produces:
- - application/json
- responses:
- "200":
- description: '{"success":true,"data":{},"msg":"评论成功"}'
- schema:
- type: string
- security:
- - BearerAuth: []
- summary: 评论帖子
- tags:
- - 帖子
- /post/like:
- get:
- parameters:
- - description: 帖子id
- in: query
- name: id
- required: true
- type: string
- - description: 点赞类型 1 点赞 2 取消点赞
- in: query
- name: type
- required: true
- type: string
- produces:
- - application/json
- responses:
- "200":
- description: '{"success":true,"data":{},"msg":"点赞成功"}'
- schema:
- type: string
- security:
- - BearerAuth: []
- summary: 点赞帖子
- tags:
- - 帖子
- /post/myPost:
- post:
- consumes:
- - application/json
- parameters:
- - description: 分页获取帖子列表
- in: body
- name: data
- required: true
- schema:
- $ref: '#/definitions/request.PostPage'
- produces:
- - application/json
- responses:
- "200":
- description: '{"success":true,"data":{},"msg":"获取成功"}'
- schema:
- type: string
- security:
- - BearerAuth: []
- summary: 我的发布
- tags:
- - 帖子
- /post/page:
- post:
- consumes:
- - application/json
- parameters:
- - description: 分页获取帖子列表
- in: body
- name: data
- required: true
- schema:
- $ref: '#/definitions/request.PostPage'
- produces:
- - application/json
- responses:
- "200":
- description: '{"success":true,"data":{},"msg":"获取成功"}'
- schema:
- type: string
- security:
- - BearerAuth: []
- summary: 帖子列表
- tags:
- - 帖子
- /post/publish:
- post:
- consumes:
- - application/json
- parameters:
- - description: 发布帖子
- in: body
- name: data
- required: true
- schema:
- $ref: '#/definitions/request.CreatePost'
- produces:
- - application/json
- responses:
- "200":
- description: '{"success":true,"data":{},"msg":"发布成功"}'
- schema:
- type: string
- security:
- - BearerAuth: []
- summary: 发布帖子
- tags:
- - 帖子
- /profile/detail:
- get:
- produces:
- - application/json
- responses:
- "200":
- description: '{"success":true,"data":{},"msg":"查询成功"}'
- schema:
- type: string
- security:
- - BearerAuth: []
- summary: 用户详情
- tags:
- - 个人中心
- /profile/update:
- post:
- consumes:
- - application/json
- parameters:
- - description: 修改用户信息
- in: body
- name: data
- required: true
- schema:
- $ref: '#/definitions/request.UpdateProfile'
- produces:
- - application/json
- responses:
- "200":
- description: '{"success":true,"data":{},"msg":"修改成功"}'
- schema:
- type: string
- security:
- - BearerAuth: []
- summary: 修改用户信息
- tags:
- - 个人中心
/role/delete:
post:
consumes:
@@ -2178,109 +1014,6 @@ paths:
summary: 修改角色
tags:
- 角色管理
- /topic/add:
- post:
- consumes:
- - application/json
- parameters:
- - description: 修改话题
- in: body
- name: data
- required: true
- schema:
- $ref: '#/definitions/request.UpdateTopic'
- produces:
- - application/json
- responses:
- "200":
- description: '{"success":true,"data":{},"msg":"发布成功"}'
- schema:
- type: string
- security:
- - BearerAuth: []
- summary: 修改话题
- tags:
- - 帖子话题
- /topic/delete:
- post:
- consumes:
- - application/json
- parameters:
- - description: 删除话题
- in: body
- name: data
- required: true
- schema:
- $ref: '#/definitions/request.IdsReq'
- produces:
- - application/json
- responses:
- "200":
- description: '{"success":true,"data":{},"msg":"删除成功"}'
- schema:
- type: string
- security:
- - BearerAuth: []
- summary: 删除任务
- tags:
- - 帖子话题
- /topic/detail:
- get:
- parameters:
- - description: id
- in: query
- name: id
- required: true
- type: string
- produces:
- - application/json
- responses:
- "200":
- description: '{"success":true,"data":{},"msg":"获取成功"}'
- schema:
- type: string
- security:
- - BearerAuth: []
- summary: 话题详情
- tags:
- - 帖子话题
- /topic/list:
- get:
- produces:
- - application/json
- responses:
- "200":
- description: '{"success":true,"data":{},"msg":"获取成功"}'
- schema:
- type: string
- security:
- - BearerAuth: []
- summary: 话题列表
- tags:
- - 帖子话题
- /topic/page:
- post:
- consumes:
- - application/json
- parameters:
- - description: 分页获取话题列表
- in: body
- name: data
- required: true
- schema:
- $ref: '#/definitions/request.PageInfo'
- produces:
- - application/json
- responses:
- "200":
- description: '{"success":true,"data":{},"msg":"获取成功"}'
- schema:
- type: string
- security:
- - BearerAuth: []
- summary: 话题分页
- tags:
- - 帖子话题
/user/changePassword:
post:
consumes:
@@ -2476,221 +1209,6 @@ paths:
summary: 更新用户
tags:
- 用户管理
- /wiki-class/add:
- post:
- consumes:
- - application/json
- parameters:
- - description: 添加分类
- in: body
- name: data
- required: true
- schema:
- $ref: '#/definitions/request.CreateWikiClass'
- produces:
- - application/json
- responses:
- "200":
- description: '{"success":true,"data":{},"msg":"发布成功"}'
- schema:
- type: string
- security:
- - BearerAuth: []
- summary: 添加分类
- tags:
- - 百科分类
- /wiki-class/delete:
- post:
- consumes:
- - application/json
- parameters:
- - description: 删除分类
- in: body
- name: data
- required: true
- schema:
- $ref: '#/definitions/request.IdsReq'
- produces:
- - application/json
- responses:
- "200":
- description: '{"success":true,"data":{},"msg":"删除成功"}'
- schema:
- type: string
- security:
- - BearerAuth: []
- summary: 删除分类
- tags:
- - 百科分类
- /wiki-class/detail:
- get:
- parameters:
- - description: id
- in: query
- name: id
- required: true
- type: string
- produces:
- - application/json
- responses:
- "200":
- description: '{"success":true,"data":{},"msg":"获取成功"}'
- schema:
- type: string
- security:
- - BearerAuth: []
- summary: 分类详情
- tags:
- - 百科分类
- /wiki-class/list:
- get:
- produces:
- - application/json
- responses:
- "200":
- description: '{"success":true,"data":{},"msg":"获取成功"}'
- schema:
- type: string
- security:
- - BearerAuth: []
- summary: 分类列表
- tags:
- - 百科分类
- /wiki-class/page:
- post:
- consumes:
- - application/json
- parameters:
- - description: 分页获取分类列表
- in: body
- name: data
- required: true
- schema:
- $ref: '#/definitions/request.PageInfo'
- produces:
- - application/json
- responses:
- "200":
- description: '{"success":true,"data":{},"msg":"获取成功"}'
- schema:
- type: string
- security:
- - BearerAuth: []
- summary: 分类分页
- tags:
- - 百科分类
- /wiki-class/update:
- post:
- consumes:
- - application/json
- parameters:
- - description: 修改分类
- in: body
- name: data
- required: true
- schema:
- $ref: '#/definitions/request.UpdateWikiClass'
- produces:
- - application/json
- responses:
- "200":
- description: '{"success":true,"data":{},"msg":"发布成功"}'
- schema:
- type: string
- security:
- - BearerAuth: []
- summary: 修改分类(可直接传入ossId修改图片)
- tags:
- - 百科分类
- /wiki/add:
- post:
- consumes:
- - application/json
- parameters:
- - description: 添加百科
- in: body
- name: data
- required: true
- schema:
- $ref: '#/definitions/request.CreateWiki'
- produces:
- - application/json
- responses:
- "200":
- description: '{"success":true,"data":{},"msg":"发布成功"}'
- schema:
- type: string
- security:
- - BearerAuth: []
- summary: 添加百科
- tags:
- - 百科
- /wiki/detail:
- get:
- parameters:
- - description: id
- in: query
- name: id
- required: true
- type: string
- produces:
- - application/json
- responses:
- "200":
- description: '{"success":true,"data":{},"msg":"获取成功"}'
- schema:
- type: string
- security:
- - BearerAuth: []
- summary: 百科详情
- tags:
- - 百科
- /wiki/page:
- post:
- consumes:
- - application/json
- parameters:
- - description: 百科分页
- in: body
- name: data
- required: true
- schema:
- $ref: '#/definitions/request.WikiPage'
- produces:
- - application/json
- responses:
- "200":
- description: '{"success":true,"data":{},"msg":"发布成功"}'
- schema:
- type: string
- security:
- - BearerAuth: []
- summary: 分页
- tags:
- - 百科
- /wiki/update:
- post:
- consumes:
- - application/json
- parameters:
- - description: 修改百科
- in: body
- name: data
- required: true
- schema:
- $ref: '#/definitions/request.UpdateWiki'
- produces:
- - application/json
- responses:
- "200":
- description: '{"success":true,"data":{},"msg":"发布成功"}'
- schema:
- type: string
- security:
- - BearerAuth: []
- summary: 修改百科
- tags:
- - 百科
securityDefinitions:
BearerAuth:
in: header
diff --git a/initialize/gorm.go b/initialize/gorm.go
index d4499fb..0c61c15 100644
--- a/initialize/gorm.go
+++ b/initialize/gorm.go
@@ -3,6 +3,7 @@ package initialize
import (
"os"
"sundynix-go/global"
+ "sundynix-go/model/radio"
"sundynix-go/model/system"
"go.uber.org/zap"
@@ -37,6 +38,12 @@ func MigrateTable() {
system.Menu{},
system.SysOperationRecord{},
system.Oss{},
+
+ radio.RadioCategory{},
+ radio.RadioChannel{},
+ radio.RadioProgram{},
+ radio.RadioSubscription{},
+ radio.RadioUser{},
)
if err != nil {
global.Logger.Error("Migrate table failed,err:", zap.Error(err))
diff --git a/initialize/router.go b/initialize/router.go
index 5df0eed..65c9f76 100644
--- a/initialize/router.go
+++ b/initialize/router.go
@@ -26,6 +26,8 @@ func Routers() {
// 系统组路由
systemRouter := router.GroupApp.System
+ // Radio组路由
+ radioRouter := router.GroupApp.Radio
NeedAuthGroup := Router.Group(global.Config.System.RouterPrefix)
PublicGroup := Router.Group(global.Config.System.RouterPrefix)
@@ -44,6 +46,13 @@ func Routers() {
systemRouter.InitRoleRouter(NeedAuthGroup) //角色相关
systemRouter.InitMenuRouter(NeedAuthGroup) //菜单相关
systemRouter.InitOssRouter(NeedAuthGroup) //OSS相关
+
+ // Radio模块路由
+ radioRouter.InitCategoryRouter(NeedAuthGroup) //分类相关
+ radioRouter.InitChannelRouter(NeedAuthGroup) //频道相关
+ radioRouter.InitProgramRouter(NeedAuthGroup) //节目相关
+ radioRouter.InitSubscriptionRouter(NeedAuthGroup) //订阅相关
+ radioRouter.InitInteractionRouter(NeedAuthGroup) //用户互动相关
}
address := fmt.Sprintf(":%d", global.Config.System.Addr)
diff --git a/log/2026-02-25/error.log b/log/2026-02-25/error.log
deleted file mode 100644
index f35a507..0000000
--- a/log/2026-02-25/error.log
+++ /dev/null
@@ -1,4 +0,0 @@
-[sundynix-radio-server]2026-02-25 17:24:01 [31merror[0m /Users/blizzard/sourceCode/GolandProjects/src/morning-radio/morning-radio-backend/utils/auth/claims.go:125 获取用户信息失败,请检查请求头是否存在x-token且claims是否为规定结构
-[sundynix-radio-server]2026-02-25 17:24:44 [31merror[0m /Users/blizzard/sourceCode/GolandProjects/src/morning-radio/morning-radio-backend/utils/auth/claims.go:125 获取用户信息失败,请检查请求头是否存在x-token且claims是否为规定结构
-[sundynix-radio-server]2026-02-25 17:25:21 [31merror[0m /Users/blizzard/sourceCode/GolandProjects/src/morning-radio/morning-radio-backend/utils/auth/claims.go:125 获取用户信息失败,请检查请求头是否存在x-token且claims是否为规定结构
-[sundynix-radio-server]2026-02-25 17:26:46 [31merror[0m /Users/blizzard/sourceCode/GolandProjects/src/morning-radio/morning-radio-backend/utils/auth/claims.go:125 获取用户信息失败,请检查请求头是否存在x-token且claims是否为规定结构
diff --git a/log/2026-02-25/info.log b/log/2026-02-25/info.log
deleted file mode 100644
index 876821d..0000000
--- a/log/2026-02-25/info.log
+++ /dev/null
@@ -1,12 +0,0 @@
-[sundynix-radio-server]2026-02-25 16:53:23 [34minfo[0m /Users/blizzard/sourceCode/GolandProjects/src/morning-radio/morning-radio-backend/initialize/gorm_mysql.go:40 Mysql connect success
-[sundynix-radio-server]2026-02-25 16:53:23 [34minfo[0m /Users/blizzard/sourceCode/GolandProjects/src/morning-radio/morning-radio-backend/initialize/redis.go:46 Redis connect ping response: {"name": "", "pong": "PONG"}
-[sundynix-radio-server]2026-02-25 16:53:28 [34minfo[0m /Users/blizzard/sourceCode/GolandProjects/src/morning-radio/morning-radio-backend/initialize/gorm.go:54 Migrate table success
-[sundynix-radio-server]2026-02-25 17:01:39 [34minfo[0m /Users/blizzard/sourceCode/GolandProjects/src/morning-radio/morning-radio-backend/initialize/gorm_mysql.go:40 Mysql connect success
-[sundynix-radio-server]2026-02-25 17:01:39 [34minfo[0m /Users/blizzard/sourceCode/GolandProjects/src/morning-radio/morning-radio-backend/initialize/redis.go:46 Redis connect ping response: {"name": "", "pong": "PONG"}
-[sundynix-radio-server]2026-02-25 17:01:52 [34minfo[0m /Users/blizzard/sourceCode/GolandProjects/src/morning-radio/morning-radio-backend/initialize/gorm.go:54 Migrate table success
-[sundynix-radio-server]2026-02-25 17:12:22 [34minfo[0m /Users/blizzard/sourceCode/GolandProjects/src/morning-radio/morning-radio-backend/initialize/gorm_mysql.go:40 Mysql connect success
-[sundynix-radio-server]2026-02-25 17:12:22 [34minfo[0m /Users/blizzard/sourceCode/GolandProjects/src/morning-radio/morning-radio-backend/initialize/redis.go:46 Redis connect ping response: {"name": "", "pong": "PONG"}
-[sundynix-radio-server]2026-02-25 17:12:37 [34minfo[0m /Users/blizzard/sourceCode/GolandProjects/src/morning-radio/morning-radio-backend/initialize/gorm.go:54 Migrate table success
-[sundynix-radio-server]2026-02-25 17:27:33 [34minfo[0m /Users/blizzard/sourceCode/GolandProjects/src/morning-radio/morning-radio-backend/service/radio/crawl.go:79 没有启用的抓取源,跳过本次抓取
-[sundynix-radio-server]2026-02-25 17:30:50 [34minfo[0m /Users/blizzard/sourceCode/GolandProjects/src/morning-radio/morning-radio-backend/service/radio/crawl.go:95 开始抓取 GitHub 数据 {"source": "GitHub AI 热榜"}
-[sundynix-radio-server]2026-02-25 17:30:51 [34minfo[0m /Users/blizzard/sourceCode/GolandProjects/src/morning-radio/morning-radio-backend/service/radio/crawl.go:158 GitHub 数据抓取完成 {"totalResults": 46, "fetched": 10}
diff --git a/log/2026-02-28/error.log b/log/2026-02-28/error.log
new file mode 100644
index 0000000..360e781
--- /dev/null
+++ b/log/2026-02-28/error.log
@@ -0,0 +1,9 @@
+[sundynix-radio-server]2026-02-28 15:39:45 [31merror[0m /Users/blizzard/sourceCode/GolandProjects/src/morning-radio/morning-radio-backend/initialize/redis.go:43 Redis connect ping failed,err: {"name": "", "error": "dial tcp 127.0.0.1:6379: connect: connection refused"}
+[sundynix-radio-server]2026-02-28 15:39:45 [31merror[0m /Users/blizzard/sourceCode/GolandProjects/src/morning-radio/morning-radio-backend/initialize/redis.go:17 Redis connect failed,err: {"error": "dial tcp 127.0.0.1:6379: connect: connection refused"}
+[sundynix-radio-server]2026-02-28 15:39:45 [31merror[0m /Users/blizzard/sourceCode/GolandProjects/src/morning-radio/morning-radio-backend/initialize/internal/gorm_logger_writer.go:29 [35m[/Users/blizzard/sourceCode/GolandProjects/src/morning-radio/morning-radio-backend/initialize/gorm.go:34 {{ 0001-01-01 00:00:00 +0000 UTC 0001-01-01 00:00:00 +0000 UTC {0001-01-01 00:00:00 +0000 UTC %!s(bool=false)} } %!s(*system.Oss=) %!s(*system.Oss=) %!s(int=0) %!s(int=0)} invalid field found for struct sundynix-go/model/radio.RadioCategory's field Cover: define a valid foreign key for relations or implement the Valuer/Scanner interface]
+[0m[31m[error] [0mfailed to parse value %!v(MISSING), got error %!v(MISSING)
+[sundynix-radio-server]2026-02-28 15:39:51 [31merror[0m /Users/blizzard/sourceCode/GolandProjects/src/morning-radio/morning-radio-backend/initialize/internal/gorm_logger_writer.go:29 [35m[/Users/blizzard/sourceCode/GolandProjects/src/morning-radio/morning-radio-backend/initialize/gorm.go:34 {{ 0001-01-01 00:00:00 +0000 UTC 0001-01-01 00:00:00 +0000 UTC {0001-01-01 00:00:00 +0000 UTC %!s(bool=false)} } %!s(*system.Oss=) %!s(*system.Oss=) %!s(int=0) %!s(int=0)} invalid field found for struct sundynix-go/model/radio.RadioCategory's field Cover: define a valid foreign key for relations or implement the Valuer/Scanner interface]
+[0m[31m[error] [0mfailed to parse value %!v(MISSING), got error %!v(MISSING)
+[sundynix-radio-server]2026-02-28 15:39:51 [31merror[0m /Users/blizzard/sourceCode/GolandProjects/src/morning-radio/morning-radio-backend/initialize/gorm.go:49 Migrate table failed,err: {"error": "invalid field found for struct sundynix-go/model/radio.RadioCategory's field Cover: define a valid foreign key for relations or implement the Valuer/Scanner interface"}
+[sundynix-radio-server]2026-02-28 15:40:52 [31merror[0m /Users/blizzard/sourceCode/GolandProjects/src/morning-radio/morning-radio-backend/initialize/redis.go:43 Redis connect ping failed,err: {"name": "", "error": "dial tcp 127.0.0.1:6379: connect: connection refused"}
+[sundynix-radio-server]2026-02-28 15:40:52 [31merror[0m /Users/blizzard/sourceCode/GolandProjects/src/morning-radio/morning-radio-backend/initialize/redis.go:17 Redis connect failed,err: {"error": "dial tcp 127.0.0.1:6379: connect: connection refused"}
diff --git a/log/2026-02-28/info.log b/log/2026-02-28/info.log
new file mode 100644
index 0000000..2e5d313
--- /dev/null
+++ b/log/2026-02-28/info.log
@@ -0,0 +1,3 @@
+[sundynix-radio-server]2026-02-28 15:39:45 [34minfo[0m /Users/blizzard/sourceCode/GolandProjects/src/morning-radio/morning-radio-backend/initialize/gorm_mysql.go:40 Mysql connect success
+[sundynix-radio-server]2026-02-28 15:40:52 [34minfo[0m /Users/blizzard/sourceCode/GolandProjects/src/morning-radio/morning-radio-backend/initialize/gorm_mysql.go:40 Mysql connect success
+[sundynix-radio-server]2026-02-28 15:41:00 [34minfo[0m /Users/blizzard/sourceCode/GolandProjects/src/morning-radio/morning-radio-backend/initialize/gorm.go:52 Migrate table success
diff --git a/main.go b/main.go
index 41ee800..3b219a5 100644
--- a/main.go
+++ b/main.go
@@ -13,7 +13,7 @@ import (
// @title Swagger API接口文档
// @version v1.0.0
// @description 使用gin + gorm进行极速开发的全栈开发基础平台
-// @securityDefinitions.apikey BearerAuth
+// @securityDefinitions.basic BearerAuth
// @in header
// @name Authorization
// @BasePath /
diff --git a/model/commom/request/common.go b/model/commom/request/common.go
index 0e98c78..fba890f 100644
--- a/model/commom/request/common.go
+++ b/model/commom/request/common.go
@@ -36,6 +36,9 @@ func (r *GetById) Uint() string {
return string(r.ID)
}
+type IdReq struct {
+ Id string `json:"id" form:"id"`
+}
type IdsReq struct {
Ids []string `json:"ids" form:"ids"`
}
diff --git a/model/radio/radio_category.go b/model/radio/radio_category.go
new file mode 100644
index 0000000..6745b2e
--- /dev/null
+++ b/model/radio/radio_category.go
@@ -0,0 +1,23 @@
+package radio
+
+import (
+ "sundynix-go/global"
+ "sundynix-go/model/system"
+)
+
+// RadioCategory 电台分类表
+type RadioCategory struct {
+ global.BaseModel
+ Name string `gorm:"size:50" json:"name"` // 分类名称
+ Description string `gorm:"size:255" json:"description"` // 分类描述
+ IconId string `gorm:"size:50" json:"iconId"` // 图标OSS ID
+ Icon *system.Oss `gorm:"foreignKey:IconId" json:"icon"` // 图标OSS
+ CoverId string `gorm:"size:50" json:"coverId"` // 封面图OSS ID
+ Cover *system.Oss `gorm:"foreignKey:CoverId" json:"cover"` // 封面图OSS
+ Sort int `gorm:"default:0" json:"sort"` // 排序
+ Status int `gorm:"default:1" json:"status"` // 状态 0:禁用 1:启用
+}
+
+func (RadioCategory) TableName() string {
+ return "sundynix_radio_category"
+}
diff --git a/model/radio/radio_channel.go b/model/radio/radio_channel.go
new file mode 100644
index 0000000..ca02696
--- /dev/null
+++ b/model/radio/radio_channel.go
@@ -0,0 +1,26 @@
+package radio
+
+import (
+ "sundynix-go/global"
+ "sundynix-go/model/system"
+)
+
+// RadioChannel 电台频道表
+type RadioChannel struct {
+ global.BaseModel
+ CategoryId string `gorm:"size:50;index" json:"categoryId"` // 分类ID
+ Name string `gorm:"size:50" json:"name"` // 频道名称
+ Description string `gorm:"size:500" json:"description"` // 频道描述
+ Price int `gorm:"default:0;comment:价格,单位,分 " json:"price"` //价格 单位:分
+ CoverId string `gorm:"size:50" json:"coverId"` // 封面图OSS ID
+ Cover *system.Oss `gorm:"foreignKey:CoverId" json:"cover"` // 封面图OSS
+ Tags string `gorm:"size:255" json:"tags"` // 标签,逗号分隔
+ IsVipOnly int `gorm:"default:0" json:"isVipOnly"` // 是否VIP专享 0:否 1:是
+ Sort int `gorm:"default:0" json:"sort"` // 排序
+ Status int `gorm:"default:1" json:"status"` // 状态 0:禁用 1:启用
+ HasSubscribed int `gorm:"-" json:"hasSubscribed"` // 状态 0:未订阅 1:已订阅
+}
+
+func (RadioChannel) TableName() string {
+ return "sundynix_radio_channel"
+}
diff --git a/model/radio/radio_comment.go b/model/radio/radio_comment.go
new file mode 100644
index 0000000..979ac92
--- /dev/null
+++ b/model/radio/radio_comment.go
@@ -0,0 +1,19 @@
+package radio
+
+import (
+ "sundynix-go/global"
+)
+
+// RadioComment 用户评论表
+type RadioComment struct {
+ global.BaseModel
+ ProgramId string `gorm:"size:50;index" json:"programId"` // 节目ID
+ UserId string `gorm:"size:50;index" json:"userId"` // 用户ID
+ ParentId string `gorm:"size:50" json:"parentId"` // 父评论ID
+ Content string `gorm:"type:text" json:"content"` // 评论内容
+ LikeCount int `gorm:"default:0" json:"likeCount"` // 点赞数
+}
+
+func (RadioComment) TableName() string {
+ return "sundynix_radio_comment"
+}
diff --git a/model/radio/radio_favorite.go b/model/radio/radio_favorite.go
new file mode 100644
index 0000000..5f30386
--- /dev/null
+++ b/model/radio/radio_favorite.go
@@ -0,0 +1,16 @@
+package radio
+
+import (
+ "sundynix-go/global"
+)
+
+// RadioFavorite 用户收藏表
+type RadioFavorite struct {
+ global.BaseModel
+ UserId string `gorm:"size:50;index" json:"userId"` // 用户ID
+ ProgramId string `gorm:"size:50;index" json:"programId"` // 节目ID
+}
+
+func (RadioFavorite) TableName() string {
+ return "sundynix_radio_favorite"
+}
diff --git a/model/radio/radio_history.go b/model/radio/radio_history.go
new file mode 100644
index 0000000..ad092fd
--- /dev/null
+++ b/model/radio/radio_history.go
@@ -0,0 +1,18 @@
+package radio
+
+import (
+ "sundynix-go/global"
+)
+
+// RadioHistory 用户收听历史表
+type RadioHistory struct {
+ global.BaseModel
+ UserId string `gorm:"size:50;index" json:"userId"` // 用户ID
+ ProgramId string `gorm:"size:50;index" json:"programId"` // 节目ID
+ Progress int `gorm:"default:0" json:"progress"` // 播放进度(秒)
+ Duration int `gorm:"default:0" json:"duration"` // 节目总时长(秒)
+}
+
+func (RadioHistory) TableName() string {
+ return "sundynix_radio_history"
+}
diff --git a/model/radio/radio_like.go b/model/radio/radio_like.go
new file mode 100644
index 0000000..8b2b581
--- /dev/null
+++ b/model/radio/radio_like.go
@@ -0,0 +1,16 @@
+package radio
+
+import (
+ "sundynix-go/global"
+)
+
+// RadioLike 用户点赞表
+type RadioLike struct {
+ global.BaseModel
+ UserId string `gorm:"size:50;index" json:"userId"` // 用户ID
+ ProgramId string `gorm:"size:50;index" json:"programId"` // 节目ID
+}
+
+func (RadioLike) TableName() string {
+ return "sundynix_radio_like"
+}
diff --git a/model/radio/radio_program.go b/model/radio/radio_program.go
new file mode 100644
index 0000000..711d389
--- /dev/null
+++ b/model/radio/radio_program.go
@@ -0,0 +1,28 @@
+package radio
+
+import (
+ "sundynix-go/global"
+ "sundynix-go/model/system"
+)
+
+// RadioProgram 电台节目表
+type RadioProgram struct {
+ global.BaseModel
+ ChannelId string `gorm:"size:50;index" json:"channelId"` // 频道ID
+ Title string `gorm:"size:100" json:"title"` // 节目标题
+ Description string `gorm:"size:500" json:"description"` // 节目描述
+ Content string `gorm:"type:text" json:"content"`
+ CoverId string `gorm:"size:50" json:"coverId"` // 封面图OSS ID
+ Cover *system.Oss `gorm:"foreignKey:CoverId" json:"coverUrl"` // 封面图OSS
+ AudioId string `gorm:"size:50" json:"audioId"` // 音频OSS ID
+ Audio *system.Oss `gorm:"foreignKey:AudioId" json:"audio"` // 音频OSS
+ Duration int `gorm:"default:0" json:"duration"` // 时长(秒)
+ Tags string `gorm:"size:255" json:"tags"` // 标签,逗号分隔
+ PlayCount int `gorm:"default:0" json:"playCount"` // 播放次数
+ LikeCount int `gorm:"default:0" json:"likeCount"` // 点赞次数
+ Status int `gorm:"default:1" json:"status"` // 状态 0:下架 1:上架
+}
+
+func (RadioProgram) TableName() string {
+ return "sundynix_radio_program"
+}
diff --git a/model/radio/radio_subscription.go b/model/radio/radio_subscription.go
new file mode 100644
index 0000000..beeb3de
--- /dev/null
+++ b/model/radio/radio_subscription.go
@@ -0,0 +1,17 @@
+package radio
+
+import (
+ "sundynix-go/global"
+)
+
+// RadioSubscription 用户订阅表
+type RadioSubscription struct {
+ global.BaseModel
+ UserId string `gorm:"size:50;index;not null;uniqueIndex:idx_user_channel" json:"userId"` // 用户ID
+ ChannelId string `gorm:"size:50;index;uniqueIndex:idx_user_channel" json:"channelId"` // 频道ID
+ Status int `gorm:"type:tinyint;default:1"` //1-订阅中,2-已取消
+}
+
+func (RadioSubscription) TableName() string {
+ return "sundynix_radio_subscription"
+}
diff --git a/model/radio/radio_user.go b/model/radio/radio_user.go
new file mode 100644
index 0000000..9637223
--- /dev/null
+++ b/model/radio/radio_user.go
@@ -0,0 +1,29 @@
+package radio
+
+import (
+ "sundynix-go/global"
+ "sundynix-go/model/system"
+)
+
+// RadioUser 小程序用户信息表
+type RadioUser struct {
+ global.BaseModel
+ UserId string `gorm:"size:50;uniqueIndex" json:"userId"` // 关联system用户ID
+ OpenId string `gorm:"size:80;uniqueIndex" json:"openId"` // 微信openid
+ UnionId string `gorm:"size:80" json:"unionId"` // 微信unionid
+ SessionKey string `gorm:"size:200" json:"sessionKey"` // 会话密钥
+ NickName string `gorm:"size:50" json:"nickName"` // 昵称
+ AvatarId string `gorm:"size:50" json:"avatarId"` // 头像OSS ID
+ Avatar *system.Oss `gorm:"foreignKey:AvatarId" json:"avatar"` // 头像OSS
+ Gender int `gorm:"default:0" json:"gender"` // 性别 0:未知 1:男 2:女
+ Country string `gorm:"size:50" json:"country"` // 国家
+ Province string `gorm:"size:50" json:"province"` // 省份
+ City string `gorm:"size:50" json:"city"` // 城市
+ Language string `gorm:"size:20" json:"language"` // 语言
+ IsVip int `gorm:"default:0" json:"isVip"` // 是否VIP 0:否 1:是
+ VipExpireAt *int64 `gorm:"type:bigint" json:"vipExpireAt"` // VIP过期时间
+}
+
+func (RadioUser) TableName() string {
+ return "sundynix_radio_user"
+}
diff --git a/model/radio/request/category.go b/model/radio/request/category.go
new file mode 100644
index 0000000..4769fbe
--- /dev/null
+++ b/model/radio/request/category.go
@@ -0,0 +1,32 @@
+package request
+
+import common "sundynix-go/model/commom/request"
+
+// GetCategoryList 获取分类列表请求
+type GetCategoryList struct {
+ common.PageInfo
+ Name string `json:"name" form:"name"` // 分类名称
+ Status int `json:"status" form:"status"` // 状态
+}
+
+// SaveCategory 保存分类请求
+type SaveCategory struct {
+ Id string `json:"id" form:"id"` // 分类ID(更新时使用)
+ Name string `json:"name" binding:"required"` // 分类名称
+ Description string `json:"description"` // 分类描述
+ IconId string `json:"iconId"` // 图标URL
+ CoverId string `json:"coverId"` // 封面图URL
+ Sort int `json:"sort"` // 排序
+ Status int `json:"status"` // 状态
+}
+
+// UpdateCategory 更新分类请求
+type UpdateCategory struct {
+ Id string `json:"id" binding:"required"` // 分类ID
+ Name string `json:"name"` // 分类名称
+ Description string `json:"description"` // 分类描述
+ IconId string `json:"iconId"` // 图标URL
+ CoverId string `json:"coverId"` // 封面图URL
+ Sort int `json:"sort"` // 排序
+ Status int `json:"status"` // 状态
+}
diff --git a/model/radio/request/channel.go b/model/radio/request/channel.go
new file mode 100644
index 0000000..ce1c9f2
--- /dev/null
+++ b/model/radio/request/channel.go
@@ -0,0 +1,37 @@
+package request
+
+import common "sundynix-go/model/commom/request"
+
+// GetChannelList 获取频道列表请求
+type GetChannelList struct {
+ common.PageInfo
+ CategoryId string `json:"categoryId" form:"categoryId"` // 分类ID
+ Name string `json:"name" form:"name"` // 频道名称
+ Status int `json:"status" form:"status"` // 状态
+}
+
+// SaveChannel 保存频道请求
+type SaveChannel struct {
+ Id string `json:"id" form:"id"` // 频道ID(更新时使用)
+ CategoryId string `json:"categoryId" binding:"required"` // 分类ID
+ Name string `json:"name" binding:"required"` // 频道名称
+ Description string `json:"description"` // 频道描述
+ CoverId string `json:"coverId"` // 封面图URL
+ Tags string `json:"tags"` // 标签
+ IsVipOnly int `json:"isVipOnly"` // 是否VIP专享
+ Sort int `json:"sort"` // 排序
+ Status int `json:"status"` // 状态
+}
+
+// UpdateChannel 更新频道请求
+type UpdateChannel struct {
+ Id string `json:"id" binding:"required"` // 频道ID
+ CategoryId string `json:"categoryId"` // 分类ID
+ Name string `json:"name"` // 频道名称
+ Description string `json:"description"` // 频道描述
+ CoverId string `json:"coverId"` // 封面图URL
+ Tags string `json:"tags"` // 标签
+ IsVipOnly int `json:"isVipOnly"` // 是否VIP专享
+ Sort int `json:"sort"` // 排序
+ Status int `json:"status"` // 状态
+}
diff --git a/model/radio/request/interaction.go b/model/radio/request/interaction.go
new file mode 100644
index 0000000..79eb655
--- /dev/null
+++ b/model/radio/request/interaction.go
@@ -0,0 +1,68 @@
+package request
+
+import common "sundynix-go/model/commom/request"
+
+// SubscribeChannel 订阅频道请求
+type SubscribeChannel struct {
+ ChannelId string `json:"channelId" binding:"required"` // 频道ID
+}
+
+// UnsubscribeChannel 退订频道请求
+type UnsubscribeChannel struct {
+ ChannelId string `json:"channelId" binding:"required"` // 频道ID
+}
+
+// AddHistory 添加收听历史请求
+type AddHistory struct {
+ ProgramId string `json:"programId" binding:"required"` // 节目ID
+ Progress int `json:"progress"` // 播放进度(秒)
+ Duration int `json:"duration"` // 节目总时长(秒)
+}
+
+// ToggleLike 切换点赞请求
+type ToggleLike struct {
+ ProgramId string `json:"programId" binding:"required"` // 节目ID
+}
+
+// AddFavorite 添加收藏请求
+type AddFavorite struct {
+ ProgramId string `json:"programId" binding:"required"` // 节目ID
+}
+
+// RemoveFavorite 移除收藏请求
+type RemoveFavorite struct {
+ ProgramId string `json:"programId" binding:"required"` // 节目ID
+}
+
+// AddComment 添加评论请求
+type AddComment struct {
+ ProgramId string `json:"programId" binding:"required"` // 节目ID
+ ParentId string `json:"parentId"` // 父评论ID
+ Content string `json:"content" binding:"required"` // 评论内容
+}
+
+// DeleteComment 删除评论请求
+type DeleteComment struct {
+ CommentId string `json:"commentId" binding:"required"` // 评论ID
+}
+
+// GetHistoryList 获取收听历史列表请求
+type GetHistoryList struct {
+ common.PageInfo
+}
+
+// GetFavoriteList 获取收藏列表请求
+type GetFavoriteList struct {
+ common.PageInfo
+}
+
+// GetCommentList 获取评论列表请求
+type GetCommentList struct {
+ common.PageInfo
+ ProgramId string `json:"programId" form:"programId"` // 节目ID
+}
+
+// GetSubscriptionList 获取订阅列表请求
+type GetSubscriptionList struct {
+ common.PageInfo
+}
diff --git a/model/radio/request/program.go b/model/radio/request/program.go
new file mode 100644
index 0000000..72e9476
--- /dev/null
+++ b/model/radio/request/program.go
@@ -0,0 +1,39 @@
+package request
+
+import common "sundynix-go/model/commom/request"
+
+// GetProgramList 获取节目列表请求
+type GetProgramList struct {
+ common.PageInfo
+ ChannelId string `json:"channelId" form:"channelId"` // 频道ID
+ Title string `json:"title" form:"title"` // 节目标题
+ Status int `json:"status" form:"status"` // 状态
+}
+
+// SaveProgram 保存节目请求
+type SaveProgram struct {
+ Id string `json:"id" form:"id"` // 节目ID(更新时使用)
+ ChannelId string `json:"channelId" binding:"required"` // 频道ID
+ Title string `json:"title" binding:"required"` // 节目标题
+ Description string `json:"description"` // 节目描述
+ Content string `json:"content"`
+ CoverId string `json:"coverId"` // 封面图URL
+ AudioId string `json:"audioId"` // 音频URL
+ Duration int `json:"duration"` // 时长(秒)
+ Tags string `json:"tags"` // 标签
+ Status int `json:"status"` // 状态
+}
+
+// UpdateProgram 更新节目请求
+type UpdateProgram struct {
+ Id string `json:"id" binding:"required"` // 节目ID
+ ChannelId string `json:"channelId"` // 频道ID
+ Title string `json:"title"` // 节目标题
+ Description string `json:"description"` // 节目描述
+ Content string `json:"content"`
+ CoverId string `json:"coverId"` // 封面图URL
+ AudioId string `json:"audioId"` // 音频URL
+ Duration int `json:"duration"` // 时长(秒)
+ Tags string `json:"tags"` // 标签
+ Status int `json:"status"` // 状态
+}
diff --git a/model/radio/response/category.go b/model/radio/response/category.go
new file mode 100644
index 0000000..2e0cf4d
--- /dev/null
+++ b/model/radio/response/category.go
@@ -0,0 +1,43 @@
+package response
+
+import "sundynix-go/model/radio"
+
+// CategoryResponse 分类响应
+type CategoryResponse struct {
+ Id string `json:"id"`
+ Name string `json:"name"`
+ Description string `json:"description"`
+ Icon string `json:"icon"`
+ CoverUrl string `json:"coverUrl"`
+ Sort int `json:"sort"`
+ Status int `json:"status"`
+}
+
+// CategoryDetailResponse 分类详情响应
+type CategoryDetailResponse struct {
+ Id string `json:"id"`
+ Name string `json:"name"`
+ Description string `json:"description"`
+ Icon string `json:"icon"`
+ CoverUrl string `json:"coverUrl"`
+ Sort int `json:"sort"`
+ Status int `json:"status"`
+}
+
+// ToCategoryResponse 转换为分类响应
+func ToCategoryResponse(category *radio.RadioCategory) CategoryResponse {
+ resp := CategoryResponse{
+ Id: category.Id,
+ Name: category.Name,
+ Description: category.Description,
+ Sort: category.Sort,
+ Status: category.Status,
+ }
+ if category.Icon != nil {
+ resp.Icon = category.Icon.Url
+ }
+ if category.Cover != nil {
+ resp.CoverUrl = category.Cover.Url
+ }
+ return resp
+}
diff --git a/model/radio/response/channel.go b/model/radio/response/channel.go
new file mode 100644
index 0000000..ce89545
--- /dev/null
+++ b/model/radio/response/channel.go
@@ -0,0 +1,29 @@
+package response
+
+// ChannelResponse 频道响应
+type ChannelResponse struct {
+ Id string `json:"id"`
+ CategoryId string `json:"categoryId"`
+ Name string `json:"name"`
+ Description string `json:"description"`
+ CoverUrl string `json:"coverUrl"`
+ StreamUrl string `json:"streamUrl"`
+ Tags string `json:"tags"`
+ IsVipOnly int `json:"isVipOnly"`
+ Sort int `json:"sort"`
+ Status int `json:"status"`
+}
+
+// ChannelDetailResponse 频道详情响应
+type ChannelDetailResponse struct {
+ Id string `json:"id"`
+ CategoryId string `json:"categoryId"`
+ Name string `json:"name"`
+ Description string `json:"description"`
+ CoverUrl string `json:"coverUrl"`
+ StreamUrl string `json:"streamUrl"`
+ Tags string `json:"tags"`
+ IsVipOnly int `json:"isVipOnly"`
+ Sort int `json:"sort"`
+ Status int `json:"status"`
+}
diff --git a/plans/radio_module_plan.md b/plans/radio_module_plan.md
new file mode 100644
index 0000000..60d1e73
--- /dev/null
+++ b/plans/radio_module_plan.md
@@ -0,0 +1,350 @@
+# Radio 模块开发计划 (v2.0)
+
+## 1. 项目架构分析
+
+### 1.1 现有项目结构
+本项目是基于 Gin + Gorm 的 Go 后端服务,采用典型的分层架构:
+
+```
+morning-radio-backend/
+├── main.go # 程序入口
+├── api/v1/ # API 路由处理层
+├── router/ # 路由定义层
+├── service/ # 业务逻辑层
+├── model/ # 数据模型层
+├── initialize/ # 初始化模块
+├── global/ # 全局变量
+├── middleware/ # 中间件
+├── config/ # 配置管理
+└── utils/ # 工具类
+```
+
+## 2. Radio 模块设计 (v2.0)
+
+### 2.1 功能模块层级
+
+```
+分类 (Category)
+ └── 频道 (Channel)
+ └── 节目 (Program)
+```
+
+### 2.2 用户权限体系
+
+| 权限类型 | 说明 |
+|----------|------|
+| 免费用户 | 可订阅2个频道,解锁对应节目 |
+| 订阅用户 | 支付订阅特定频道,解锁该频道所有节目 |
+| VIP用户 | 解锁全部频道的所有节目 |
+
+### 2.3 数据库表设计
+
+#### 2.3.1 分类表 (radio_category)
+
+| 字段 | 类型 | 说明 |
+|------|------|------|
+| id | string | 主键ID (继承BaseModel) |
+| name | string | 分类名称 |
+| description | string | 分类描述 |
+| icon | string | 图标URL |
+| sort | int | 排序 |
+| status | int | 状态(0:禁用 1:启用) |
+
+#### 2.3.2 频道表 (radio_channel)
+
+| 字段 | 类型 | 说明 |
+|------|------|------|
+| id | string | 主键ID (继承BaseModel) |
+| category_id | string | 分类ID |
+| name | string | 频道名称 |
+| description | string | 频道描述 |
+| cover_url | string | 封面图URL |
+| stream_url | string | 音频流地址 |
+| tags | string | 标签 |
+| is_vip_only | int | 是否VIP专享(0:否 1:是) |
+| sort | int | 排序 |
+| status | int | 状态(0:禁用 1:启用) |
+
+#### 2.3.3 节目表 (radio_program)
+
+| 字段 | 类型 | 说明 |
+|------|------|------|
+| id | string | 主键ID (继承BaseModel) |
+| channel_id | string | 频道ID |
+| title | string | 节目标题 |
+| description | string | 节目描述 |
+| cover_url | string | 封面图URL |
+| audio_url | string | 音频URL |
+| duration | int | 时长(秒) |
+| tags | string | 标签 |
+| play_count | int | 播放次数 |
+| like_count | int | 点赞次数 |
+| status | int | 状态(0:下架 1:上架) |
+
+#### 2.3.4 用户订阅表 (radio_subscription)
+
+| 字段 | 类型 | 说明 |
+|------|------|------|
+| id | string | 主键ID (继承BaseModel) |
+| user_id | string | 用户ID |
+| channel_id | string | 频道ID |
+| subscription_type | int | 订阅类型(1:免费 2:付费 3:VIP) |
+| expire_at | time | 过期时间 |
+| created_at | time | 订阅时间 |
+
+#### 2.3.5 收听历史表 (radio_history)
+
+| 字段 | 类型 | 说明 |
+|------|------|------|
+| id | string | 主键ID (继承BaseModel) |
+| user_id | string | 用户ID |
+| program_id | string | 节目ID |
+| progress | int | 播放进度(秒) |
+| duration | int | 节目总时长 |
+| created_at | time | 收听时间 |
+
+#### 2.3.6 点赞表 (radio_like)
+
+| 字段 | 类型 | 说明 |
+|------|------|------|
+| id | string | 主键ID (继承BaseModel) |
+| user_id | string | 用户ID |
+| program_id | string | 节目ID |
+| created_at | time | 点赞时间 |
+
+#### 2.3.7 收藏表 (radio_favorite)
+
+| 字段 | 类型 | 说明 |
+|------|------|------|
+| id | string | 主键ID (继承BaseModel) |
+| user_id | string | 用户ID |
+| program_id | string | 节目ID |
+| created_at | time | 收藏时间 |
+
+#### 2.3.8 评论表 (radio_comment)
+
+| 字段 | 类型 | 说明 |
+|------|------|------|
+| id | string | 主键ID (继承BaseModel) |
+| program_id | string | 节目ID |
+| user_id | string | 用户ID |
+| parent_id | string | 父评论ID |
+| content | string | 评论内容 |
+| like_count | int | 点赞数 |
+| created_at | time | 评论时间 |
+
+### 2.4 Radio 模块目录结构
+
+```
+model/radio/
+├── radio_category.go # 分类模型
+├── radio_channel.go # 频道模型
+├── radio_program.go # 节目模型
+├── radio_subscription.go # 订阅模型
+├── radio_favorite.go # 收藏模型
+├── radio_history.go # 收听历史模型
+├── radio_like.go # 点赞模型
+├── radio_comment.go # 评论模型
+├── request/
+│ ├── category.go # 分类请求结构
+│ ├── channel.go # 频道请求结构
+│ ├── program.go # 节目请求结构
+│ └── interaction.go # 互动请求结构
+└── response/
+ ├── category.go # 分类响应结构
+ ├── channel.go # 频道响应结构
+ ├── program.go # 节目响应结构
+ └── interaction.go # 互动响应结构
+
+api/v1/radio/
+├── enter.go # Radio API组定义
+├── category.go # 分类API
+├── channel.go # 频道API
+├── program.go # 节目API
+├── subscription.go # 订阅API
+└── interaction.go # 互动API
+
+router/radio/
+├── enter.go # Radio 路由组定义
+├── category_router.go # 分类路由
+├── channel_router.go # 频道路由
+├── program_router.go # 节目路由
+├── subscription_router.go # 订阅路由
+└── interaction_router.go # 互动路由
+
+service/radio/
+├── enter.go # Radio 服务组定义
+├── category_service.go # 分类业务逻辑
+├── channel_service.go # 频道业务逻辑
+├── program_service.go # 节目业务逻辑
+├── subscription_service.go # 订阅业务逻辑
+└── interaction_service.go # 互动业务逻辑
+```
+
+## 3. 开发步骤
+
+### 步骤1: 创建模块目录结构和文件骨架
+
+- [ ] 创建 model/radio/ 目录及子目录
+- [ ] 创建 api/v1/radio/ 目录
+- [ ] 创建 router/radio/ 目录
+- [ ] 创建 service/radio/ 目录
+- [ ] 创建各层级的 enter.go 入口文件
+
+### 步骤2: 实现数据模型层
+
+- [ ] 实现 RadioCategory 分类模型
+- [ ] 实现 RadioChannel 频道模型
+- [ ] 实现 RadioProgram 节目模型
+- [ ] 实现 RadioSubscription 订阅模型
+- [ ] 实现 RadioHistory 收听历史模型
+- [ ] 实现 RadioLike 点赞模型
+- [ ] 实现 RadioFavorite 收藏模型
+- [ ] 实现 RadioComment 评论模型
+
+### 步骤3: 实现请求/响应数据结构
+
+- [ ] 实现分类请求/响应结构
+- [ ] 实现频道请求/响应结构
+- [ ] 实现节目请求/响应结构
+- [ ] 实现订阅请求/响应结构
+- [ ] 实现互动请求/响应结构
+
+### 步骤4: 实现业务逻辑层
+
+- [ ] 实现分类Service (CRUD)
+- [ ] 实现频道Service (CRUD, 获取用户权限下的节目列表)
+- [ ] 实现节目Service (CRUD, 根据用户权限过滤 实现订阅Service ()
+- [ ]订阅/退订/查询/检查权限)
+- [ ] 实现收听历史Service (记录/列表)
+- [ ] 实现点赞Service (点赞/取消/状态)
+- [ ] 实现收藏Service (添加/删除/列表)
+- [ ] 实现评论Service (发表/删除/列表)
+
+### 步骤5: 实现API路由处理层
+
+- [ ] 实现分类API
+- [ ] 实现频道API
+- [ ] 实现节目API
+- [ ] 实现订阅API
+- [ ] 实现互动API
+
+### 步骤6: 实现路由定义层
+
+- [ ] 实现分类路由初始化
+- [ ] 实现频道路由初始化
+- [ ] 实现节目路由初始化
+- [ ] 实现订阅路由初始化
+- [ ] 实现互动路由初始化
+
+### 步骤7: 注册模块到全局
+
+- [ ] 修改 api/v1/enter.go 添加 RadioApiGroup
+- [ ] 修改 router/enter.go 添加 RadioRouterGroup
+- [ ] 修改 service/enter.go 添加 RadioServiceGroup
+- [ ] 修改 initialize/router.go 注册Radio路由
+
+## 4. API 接口设计
+
+### 4.1 分类管理 API
+
+| 方法 | 路径 | 说明 | 权限 |
+|------|------|------|------|
+| GET | /radio/category/list | 获取分类列表 | 公开 |
+| GET | /radio/category/detail | 获取分类详情 | 公开 |
+| POST | /radio/category/save | 新增分类 | 需鉴权 |
+| POST | /radio/category/update | 更新分类 | 需鉴权 |
+| POST | /radio/category/delete | 删除分类 | 需鉴权 |
+
+### 4.2 频道管理 API
+
+| 方法 | 路径 | 说明 | 权限 |
+|------|------|------|------|
+| GET | /radio/channel/list | 获取频道列表(按分类) | 公开 |
+| GET | /radio/channel/detail | 获取频道详情 | 公开 |
+| GET | /radio/channel/programs | 获取频道节目(权限过滤) | 需鉴权 |
+| POST | /radio/channel/save | 新增频道 | 需鉴权 |
+| POST | /radio/channel/update | 更新频道 | 需鉴权 |
+| POST | /radio/channel/delete | 删除频道 | 需鉴权 |
+
+### 4.3 节目管理 API
+
+| 方法 | 路径 | 说明 | 权限 |
+|------|------|------|------|
+| GET | /radio/program/list | 获取节目列表 | 公开 |
+| GET | /radio/program/detail | 获取节目详情(权限验证) | 需鉴权 |
+| POST | /radio/program/save | 新增节目 | 需鉴权 |
+| POST | /radio/program/update | 更新节目 | 需鉴权 |
+| POST | /radio/program/delete | 删除节目 | 需鉴权 |
+
+### 4.4 订阅管理 API
+
+| 方法 | 路径 | 说明 | 权限 |
+|------|------|------|------|
+| GET | /radio/subscription/list | 获取我的订阅列表 | 需鉴权 |
+| GET | /radio/subscription/can-subscribe | 检查是否可以订阅 | 需鉴权 |
+| POST | /radio/subscription/subscribe | 订阅频道 | 需鉴权 |
+| POST | /radio/subscription/unsubscribe | 退订频道 | 需鉴权 |
+| GET | /radio/subscription/my-vip-status | 获取VIP状态 | 需鉴权 |
+
+### 4.5 用户互动 API
+
+| 方法 | 路径 | 说明 | 权限 |
+|------|------|------|------|
+| GET | /radio/history/list | 获取收听历史 | 需鉴权 |
+| POST | /radio/history/add | 添加收听历史 | 需鉴权 |
+| POST | /radio/like/toggle | 切换点赞状态 | 需鉴权 |
+| GET | /radio/favorite/list | 获取收藏列表 | 需鉴权 |
+| POST | /radio/favorite/add | 添加收藏 | 需鉴权 |
+| POST | /radio/favorite/remove | 取消收藏 | 需鉴权 |
+| GET | /radio/comment/list | 获取评论列表 | 公开 |
+| POST | /radio/comment/add | 添加评论 | 需鉴权 |
+| POST | /radio/comment/delete | 删除评论 | 需鉴权 |
+
+## 5. 权限检查逻辑
+
+### 5.1 节目访问权限检查
+
+```go
+func CanAccessProgram(userId, programId string) bool {
+ // 1. 获取节目信息
+ program := GetProgram(programId)
+ channel := GetChannel(program.ChannelId)
+
+ // 2. 检查频道是否为VIP专享
+ if channel.IsVipOnly == 1 {
+ return user.HasVip(userId)
+ }
+
+ // 3. 检查用户是否订阅了该频道
+ return user.HasSubscription(userId, channel.Id)
+}
+```
+
+### 5.2 订阅数量限制检查
+
+```go
+func CanSubscribe(userId string) (bool, string) {
+ // 1. 检查是否为VIP
+ if user.IsVip(userId) {
+ return true, ""
+ }
+
+ // 2. 检查免费订阅数量(上限2个)
+ count := GetFreeSubscriptionCount(userId)
+ if count >= 2 {
+ return false, "免费订阅数量已达上限(2个),请开通VIP或订阅付费频道"
+ }
+
+ return true, ""
+}
+```
+
+## 6. 注意事项
+
+1. **继承BaseModel**: 所有模型必须继承 global.BaseModel
+2. **分层架构**: 严格按照 api -> service -> model 层级开发
+3. **鉴权中间件**: 新增/修改/删除操作需要使用 NeedAuthGroup
+4. **权限验证**: 节目详情API需要验证用户权限
+5. **分页查询**: 使用 common.PageInfo
+6. **响应格式**: 使用 response.OkWithData() 和 response.FailWithMsg()
diff --git a/router/enter.go b/router/enter.go
index f1b3d88..372c4cc 100644
--- a/router/enter.go
+++ b/router/enter.go
@@ -1,6 +1,7 @@
package router
import (
+ "sundynix-go/router/radio"
"sundynix-go/router/system"
)
@@ -9,4 +10,5 @@ var GroupApp = new(Group)
// Group 路由组
type Group struct {
System system.SysRouterGroup
+ Radio radio.RadioRouterGroup
}
diff --git a/router/radio/category_router.go b/router/radio/category_router.go
new file mode 100644
index 0000000..2f8943c
--- /dev/null
+++ b/router/radio/category_router.go
@@ -0,0 +1,19 @@
+package radio
+
+import (
+ "github.com/gin-gonic/gin"
+)
+
+type CategoryRouter struct{}
+
+func (r *CategoryRouter) InitCategoryRouter(Router *gin.RouterGroup) {
+ categoryRouter := Router.Group("/radio/category")
+ {
+ categoryRouter.POST("page", categoryApi.GetCategoryPage)
+ categoryRouter.POST("list", categoryApi.GetCategoryList)
+ categoryRouter.GET("detail", categoryApi.GetCategoryDetail)
+ categoryRouter.POST("save", categoryApi.SaveCategory)
+ categoryRouter.POST("update", categoryApi.UpdateCategory)
+ categoryRouter.POST("delete", categoryApi.DeleteCategory)
+ }
+}
diff --git a/router/radio/channel_router.go b/router/radio/channel_router.go
new file mode 100644
index 0000000..a4d52ff
--- /dev/null
+++ b/router/radio/channel_router.go
@@ -0,0 +1,18 @@
+package radio
+
+import (
+ "github.com/gin-gonic/gin"
+)
+
+type ChannelRouter struct{}
+
+func (r *ChannelRouter) InitChannelRouter(Router *gin.RouterGroup) {
+ channelRouter := Router.Group("/radio/channel")
+ {
+ channelRouter.POST("list", channelApi.GetChannelList)
+ channelRouter.GET("detail", channelApi.GetChannelDetail)
+ channelRouter.POST("save", channelApi.SaveChannel)
+ channelRouter.POST("update", channelApi.UpdateChannel)
+ channelRouter.POST("delete", channelApi.DeleteChannel)
+ }
+}
diff --git a/router/radio/enter.go b/router/radio/enter.go
new file mode 100644
index 0000000..b046952
--- /dev/null
+++ b/router/radio/enter.go
@@ -0,0 +1,21 @@
+package radio
+
+import v1 "sundynix-go/api/v1"
+
+type RadioRouterGroup struct {
+ CategoryRouter
+ ChannelRouter
+ ProgramRouter
+ SubscriptionRouter
+ InteractionRouter
+}
+
+var GroupApp = new(RadioRouterGroup)
+
+var (
+ categoryApi = v1.ApiGroupApp.RadioApiGroup.CategoryApi
+ channelApi = v1.ApiGroupApp.RadioApiGroup.ChannelApi
+ programApi = v1.ApiGroupApp.RadioApiGroup.ProgramApi
+ subscriptionApi = v1.ApiGroupApp.RadioApiGroup.SubscriptionApi
+ interactionApi = v1.ApiGroupApp.RadioApiGroup.InteractionApi
+)
diff --git a/router/radio/interaction_router.go b/router/radio/interaction_router.go
new file mode 100644
index 0000000..db02c7a
--- /dev/null
+++ b/router/radio/interaction_router.go
@@ -0,0 +1,38 @@
+package radio
+
+import (
+ "github.com/gin-gonic/gin"
+)
+
+type InteractionRouter struct{}
+
+func (r *InteractionRouter) InitInteractionRouter(Router *gin.RouterGroup) {
+ // 收听历史
+ historyRouter := Router.Group("history")
+ {
+ historyRouter.POST("list", interactionApi.GetHistoryList)
+ historyRouter.POST("add", interactionApi.AddHistory)
+ }
+
+ // 点赞
+ likeRouter := Router.Group("like")
+ {
+ likeRouter.POST("toggle", interactionApi.ToggleLike)
+ }
+
+ // 收藏
+ favoriteRouter := Router.Group("favorite")
+ {
+ favoriteRouter.POST("list", interactionApi.GetFavoriteList)
+ favoriteRouter.POST("add", interactionApi.AddFavorite)
+ favoriteRouter.POST("remove", interactionApi.RemoveFavorite)
+ }
+
+ // 评论
+ commentRouter := Router.Group("comment")
+ {
+ commentRouter.POST("list", interactionApi.GetCommentList)
+ commentRouter.POST("add", interactionApi.AddComment)
+ commentRouter.POST("delete", interactionApi.DeleteComment)
+ }
+}
diff --git a/router/radio/program_router.go b/router/radio/program_router.go
new file mode 100644
index 0000000..7658d7f
--- /dev/null
+++ b/router/radio/program_router.go
@@ -0,0 +1,18 @@
+package radio
+
+import (
+ "github.com/gin-gonic/gin"
+)
+
+type ProgramRouter struct{}
+
+func (r *ProgramRouter) InitProgramRouter(Router *gin.RouterGroup) {
+ programRouter := Router.Group("/radio/program")
+ {
+ programRouter.POST("list", programApi.GetProgramList)
+ programRouter.GET("detail", programApi.GetProgramDetail)
+ programRouter.POST("save", programApi.SaveProgram)
+ programRouter.POST("update", programApi.UpdateProgram)
+ programRouter.POST("delete", programApi.DeleteProgram)
+ }
+}
diff --git a/router/radio/subscription_router.go b/router/radio/subscription_router.go
new file mode 100644
index 0000000..e0d6d64
--- /dev/null
+++ b/router/radio/subscription_router.go
@@ -0,0 +1,17 @@
+package radio
+
+import (
+ "github.com/gin-gonic/gin"
+)
+
+type SubscriptionRouter struct{}
+
+func (r *SubscriptionRouter) InitSubscriptionRouter(Router *gin.RouterGroup) {
+ subscriptionRouter := Router.Group("radio/subscription")
+ {
+ subscriptionRouter.POST("list", subscriptionApi.GetSubscriptionList)
+ subscriptionRouter.POST("can-subscribe", subscriptionApi.CanSubscribe)
+ subscriptionRouter.POST("subscribe", subscriptionApi.Subscribe)
+ subscriptionRouter.POST("unsubscribe", subscriptionApi.Unsubscribe)
+ }
+}
diff --git a/service/enter.go b/service/enter.go
index 467e190..f7c4575 100644
--- a/service/enter.go
+++ b/service/enter.go
@@ -1,6 +1,7 @@
package service
import (
+ "sundynix-go/service/radio"
"sundynix-go/service/system"
)
@@ -8,4 +9,5 @@ var GroupApp = new(Group)
type Group struct {
SystemServiceGroup system.ServiceGroup
+ RadioServiceGroup radio.ServiceGroup
}
diff --git a/service/radio/category_service.go b/service/radio/category_service.go
new file mode 100644
index 0000000..553a58b
--- /dev/null
+++ b/service/radio/category_service.go
@@ -0,0 +1,87 @@
+package radio
+
+import (
+ "errors"
+ "sundynix-go/global"
+ "sundynix-go/model/radio"
+ radioReq "sundynix-go/model/radio/request"
+
+ "gorm.io/gorm"
+)
+
+type CategoryService struct{}
+
+// GetCategoryList 获取分类列表
+func (s *CategoryService) GetCategoryList(info radioReq.GetCategoryList) ([]radio.RadioCategory, int64, error) {
+ db := global.DB.Model(&radio.RadioCategory{}).Preload("Icon").Preload("Cover")
+ var list []radio.RadioCategory
+ var total int64
+
+ if info.Name != "" {
+ db = db.Where("name LIKE ?", "%"+info.Name+"%")
+ }
+ if info.Status > 0 {
+ db = db.Where("status = ?", info.Status)
+ }
+
+ err := db.Count(&total).Error
+ if err != nil {
+ return nil, 0, err
+ }
+
+ offset := (info.Current - 1) * info.PageSize
+ err = db.Offset(offset).Limit(info.PageSize).Order("sort ASC").Find(&list).Error
+ return list, total, err
+}
+
+func (s *CategoryService) GetAllCategory() ([]radio.RadioCategory, error) {
+ var res []radio.RadioCategory
+ err := global.DB.Find(&res).Preload(":Icon").Preload("Cover").Error
+ return res, err
+}
+
+// GetCategoryById 获取分类详情
+func (s *CategoryService) GetCategoryById(id string) (*radio.RadioCategory, error) {
+ var category radio.RadioCategory
+ err := global.DB.Where("id = ?", id).Preload("Icon").Preload("Cover").First(&category).Error
+ return &category, err
+}
+
+// SaveCategory 保存分类
+func (s *CategoryService) SaveCategory(req radioReq.SaveCategory) error {
+ category := radio.RadioCategory{
+ Name: req.Name,
+ Description: req.Description,
+ IconId: req.IconId,
+ CoverId: req.CoverId,
+ Sort: req.Sort,
+ Status: req.Status,
+ }
+ return global.DB.Create(&category).Error
+}
+
+// UpdateCategory 更新分类
+func (s *CategoryService) UpdateCategory(req radioReq.UpdateCategory) error {
+ updates := map[string]interface{}{
+ "name": req.Name,
+ "description": req.Description,
+ "icon_id": req.IconId,
+ "cover_id": req.CoverId,
+ "sort": req.Sort,
+ "status": req.Status,
+ }
+ return global.DB.Model(&radio.RadioCategory{}).Where("id = ?", req.Id).Updates(updates).Error
+}
+
+// DeleteCategory 删除分类
+func (s *CategoryService) DeleteCategory(id string) error {
+ return global.DB.Transaction(func(tx *gorm.DB) error {
+ // 检查是否有频道使用此分类
+ var count int64
+ tx.Model(&radio.RadioChannel{}).Where("category_id = ?", id).Count(&count)
+ if count > 0 {
+ return errors.New("该分类下存在频道,无法删除")
+ }
+ return tx.Where("id = ?", id).Delete(&radio.RadioCategory{}).Error
+ })
+}
diff --git a/service/radio/channel_service.go b/service/radio/channel_service.go
new file mode 100644
index 0000000..8d0d896
--- /dev/null
+++ b/service/radio/channel_service.go
@@ -0,0 +1,127 @@
+package radio
+
+import (
+ "errors"
+
+ "sundynix-go/global"
+ "sundynix-go/model/radio"
+ radioReq "sundynix-go/model/radio/request"
+
+ "gorm.io/gorm"
+)
+
+type ChannelService struct{}
+
+// GetChannelList 获取频道列表
+func (s *ChannelService) GetChannelList(userId string, info radioReq.GetChannelList) ([]radio.RadioChannel, int64, error) {
+ db := global.DB.Model(&radio.RadioChannel{})
+ var list []radio.RadioChannel
+ var total int64
+
+ if info.CategoryId != "" {
+ db = db.Where("category_id = ?", info.CategoryId)
+ }
+ if info.Name != "" {
+ db = db.Where("name LIKE ?", "%"+info.Name+"%")
+ }
+ if info.Status > 0 {
+ db = db.Where("status = ?", info.Status)
+ }
+
+ err := db.Count(&total).Error
+ if err != nil {
+ return nil, 0, err
+ }
+
+ offset := (info.Current - 1) * info.PageSize
+ err = db.Offset(offset).Limit(info.PageSize).Order("sort ASC").Find(&list).Error
+ if err != nil {
+ return nil, 0, err
+ }
+
+ // 批量查询用户订阅的频道,避免N+1问题
+ if userId != "" {
+ subService := &SubscriptionService{}
+ subscribedChannelIds, _ := subService.GetUserSubscriptionHistory(userId)
+ // 转换为map以便快速查找
+ subscribedMap := make(map[string]bool)
+ for _, cid := range subscribedChannelIds {
+ subscribedMap[cid] = true
+ }
+ // 填充HasSubscribed字段
+ for i := range list {
+ if subscribedMap[list[i].Id] {
+ list[i].HasSubscribed = 1
+ } else {
+ list[i].HasSubscribed = 0
+ }
+ }
+ }
+
+ return list, total, nil
+}
+
+// GetChannelById 获取频道详情
+func (s *ChannelService) GetChannelById(userId, id string) (radio.RadioChannel, error) {
+ var channel radio.RadioChannel
+ err := global.DB.Where("id = ?", id).Preload("Cover").First(&channel).Error
+ if err != nil {
+ return channel, err
+ }
+
+ // 填充HasSubscribed字段
+ if userId != "" {
+ subService := &SubscriptionService{}
+ hasSub, _ := subService.HasSubscription(userId, channel.Id)
+ if hasSub {
+ channel.HasSubscribed = 1
+ } else {
+ channel.HasSubscribed = 0
+ }
+ }
+
+ return channel, nil
+}
+
+// SaveChannel 保存频道
+func (s *ChannelService) SaveChannel(req radioReq.SaveChannel) error {
+ channel := radio.RadioChannel{
+ CategoryId: req.CategoryId,
+ Name: req.Name,
+ Description: req.Description,
+ CoverId: req.CoverId,
+ Tags: req.Tags,
+ IsVipOnly: req.IsVipOnly,
+ Sort: req.Sort,
+ Status: req.Status,
+ }
+ return global.DB.Create(&channel).Error
+}
+
+// UpdateChannel 更新频道
+func (s *ChannelService) UpdateChannel(req radioReq.UpdateChannel) error {
+ updates := map[string]interface{}{
+ "category_id": req.CategoryId,
+ "name": req.Name,
+ "description": req.Description,
+ "cover_id": req.CoverId,
+ "tags": req.Tags,
+ "is_vip_only": req.IsVipOnly,
+ "sort": req.Sort,
+ "status": req.Status,
+ }
+ return global.DB.Model(&radio.RadioChannel{}).Where("id = ?", req.Id).Updates(updates).Error
+}
+
+// DeleteChannel 删除频道
+func (s *ChannelService) DeleteChannel(id string) error {
+ return global.DB.Transaction(func(tx *gorm.DB) error {
+ // 检查是否有节目使用此频道
+ var count int64
+ tx.Model(&radio.RadioProgram{}).Where("channel_id = ?", id).Count(&count)
+ if count > 0 {
+ return errors.New("该频道下存在节目,无法删除")
+ }
+ return tx.Where("id = ?", id).Delete(&radio.RadioChannel{}).Error
+ })
+}
diff --git a/service/radio/enter.go b/service/radio/enter.go
new file mode 100644
index 0000000..a5d9df8
--- /dev/null
+++ b/service/radio/enter.go
@@ -0,0 +1,11 @@
+package radio
+
+type ServiceGroup struct {
+ CategoryService
+ ChannelService
+ ProgramService
+ SubscriptionService
+ InteractionService
+}
+
+var GroupApp = new(ServiceGroup)
diff --git a/service/radio/interaction_service.go b/service/radio/interaction_service.go
new file mode 100644
index 0000000..2b5f241
--- /dev/null
+++ b/service/radio/interaction_service.go
@@ -0,0 +1,176 @@
+package radio
+
+import (
+ "errors"
+ "sundynix-go/global"
+ "sundynix-go/model/radio"
+ radioReq "sundynix-go/model/radio/request"
+
+ "gorm.io/gorm"
+)
+
+type InteractionService struct{}
+
+// AddHistory 添加收听历史
+func (s *InteractionService) AddHistory(userId string, req radioReq.AddHistory) error {
+ // 先查找是否已存在记录
+ var history radio.RadioHistory
+ err := global.DB.Where("user_id = ? AND program_id = ?", userId, req.ProgramId).First(&history).Error
+
+ if errors.Is(err, gorm.ErrRecordNotFound) {
+ // 不存在,创建新记录
+ history = radio.RadioHistory{
+ UserId: userId,
+ ProgramId: req.ProgramId,
+ Progress: req.Progress,
+ Duration: req.Duration,
+ }
+ return global.DB.Create(&history).Error
+ }
+
+ if err != nil {
+ return err
+ }
+
+ // 存在,更新进度
+ return global.DB.Model(&history).Updates(map[string]interface{}{
+ "progress": req.Progress,
+ "duration": req.Duration,
+ }).Error
+}
+
+// GetHistoryList 获取收听历史列表
+func (s *InteractionService) GetHistoryList(userId string, info radioReq.GetHistoryList) ([]radio.RadioHistory, int64, error) {
+ db := global.DB.Model(&radio.RadioHistory{}).Where("user_id = ?", userId)
+ var list []radio.RadioHistory
+ var total int64
+
+ err := db.Count(&total).Error
+ if err != nil {
+ return nil, 0, err
+ }
+
+ offset := (info.Current - 1) * info.PageSize
+ err = db.Offset(offset).Limit(info.PageSize).Order("created_at DESC").Find(&list).Error
+ return list, total, err
+}
+
+// ToggleLike 切换点赞状态
+func (s *InteractionService) ToggleLike(userId, programId string) (bool, error) {
+ var like radio.RadioLike
+ err := global.DB.Where("user_id = ? AND program_id = ?", userId, programId).First(&like).Error
+
+ if errors.Is(err, gorm.ErrRecordNotFound) {
+ // 未点赞,添加点赞
+ like = radio.RadioLike{
+ UserId: userId,
+ ProgramId: programId,
+ }
+ if err := global.DB.Create(&like).Error; err != nil {
+ return false, err
+ }
+ // 增加节目点赞数
+ global.DB.Model(&radio.RadioProgram{}).Where("id = ?", programId).
+ UpdateColumn("like_count", gorm.Expr("like_count + ?", 1))
+ return true, nil
+ }
+
+ if err != nil {
+ return false, err
+ }
+
+ // 已点赞,取消点赞
+ if err := global.DB.Delete(&like).Error; err != nil {
+ return false, err
+ }
+ // 减少节目点赞数
+ global.DB.Model(&radio.RadioProgram{}).Where("id = ?", programId).
+ UpdateColumn("like_count", gorm.Expr("like_count - ?", 1))
+ return false, nil
+}
+
+// IsLiked 检查是否已点赞
+func (s *InteractionService) IsLiked(userId, programId string) (bool, error) {
+ var count int64
+ err := global.DB.Model(&radio.RadioLike{}).Where("user_id = ? AND program_id = ?", userId, programId).Count(&count).Error
+ return count > 0, err
+}
+
+// AddFavorite 添加收藏
+func (s *InteractionService) AddFavorite(userId, programId string) error {
+ // 检查是否已收藏
+ var existing radio.RadioFavorite
+ err := global.DB.Where("user_id = ? AND program_id = ?", userId, programId).First(&existing).Error
+ if err == nil {
+ return errors.New("已经收藏过该节目")
+ }
+ if !errors.Is(err, gorm.ErrRecordNotFound) {
+ return err
+ }
+
+ favorite := radio.RadioFavorite{
+ UserId: userId,
+ ProgramId: programId,
+ }
+ return global.DB.Create(&favorite).Error
+}
+
+// RemoveFavorite 取消收藏
+func (s *InteractionService) RemoveFavorite(userId, programId string) error {
+ return global.DB.Where("user_id = ? AND program_id = ?", userId, programId).Delete(&radio.RadioFavorite{}).Error
+}
+
+// GetFavoriteList 获取收藏列表
+func (s *InteractionService) GetFavoriteList(userId string, info radioReq.GetFavoriteList) ([]radio.RadioFavorite, int64, error) {
+ db := global.DB.Model(&radio.RadioFavorite{}).Where("user_id = ?", userId)
+ var list []radio.RadioFavorite
+ var total int64
+
+ err := db.Count(&total).Error
+ if err != nil {
+ return nil, 0, err
+ }
+
+ offset := (info.Current - 1) * info.PageSize
+ err = db.Offset(offset).Limit(info.PageSize).Order("created_at DESC").Find(&list).Error
+ return list, total, err
+}
+
+// IsFavorited 检查是否已收藏
+func (s *InteractionService) IsFavorited(userId, programId string) (bool, error) {
+ var count int64
+ err := global.DB.Model(&radio.RadioFavorite{}).Where("user_id = ? AND program_id = ?", userId, programId).Count(&count).Error
+ return count > 0, err
+}
+
+// AddComment 添加评论
+func (s *InteractionService) AddComment(userId string, req radioReq.AddComment) error {
+ comment := radio.RadioComment{
+ ProgramId: req.ProgramId,
+ UserId: userId,
+ ParentId: req.ParentId,
+ Content: req.Content,
+ }
+ return global.DB.Create(&comment).Error
+}
+
+// DeleteComment 删除评论
+func (s *InteractionService) DeleteComment(userId, commentId string) error {
+ return global.DB.Where("id = ? AND user_id = ?", commentId, userId).Delete(&radio.RadioComment{}).Error
+}
+
+// GetCommentList 获取评论列表
+func (s *InteractionService) GetCommentList(programId string, info radioReq.GetCommentList) ([]radio.RadioComment, int64, error) {
+ db := global.DB.Model(&radio.RadioComment{}).Where("program_id = ?", programId)
+ var list []radio.RadioComment
+ var total int64
+
+ err := db.Count(&total).Error
+ if err != nil {
+ return nil, 0, err
+ }
+
+ offset := (info.Current - 1) * info.PageSize
+ err = db.Offset(offset).Limit(info.PageSize).Order("created_at DESC").Find(&list).Error
+ return list, total, err
+}
diff --git a/service/radio/program_service.go b/service/radio/program_service.go
new file mode 100644
index 0000000..0693121
--- /dev/null
+++ b/service/radio/program_service.go
@@ -0,0 +1,98 @@
+package radio
+
+import (
+ "sundynix-go/global"
+ "sundynix-go/model/radio"
+ radioReq "sundynix-go/model/radio/request"
+
+ "gorm.io/gorm"
+)
+
+type ProgramService struct{}
+
+// GetProgramList 获取节目列表
+func (s *ProgramService) GetProgramList(info radioReq.GetProgramList) ([]radio.RadioProgram, int64, error) {
+ db := global.DB.Model(&radio.RadioProgram{}).Preload("Cover").Preload("Audio")
+ var list []radio.RadioProgram
+ var total int64
+
+ if info.ChannelId != "" {
+ db = db.Where("channel_id = ?", info.ChannelId)
+ }
+ if info.Title != "" {
+ db = db.Where("title LIKE ?", "%"+info.Title+"%")
+ }
+ if info.Status > 0 {
+ db = db.Where("status = ?", info.Status)
+ }
+
+ err := db.Count(&total).Error
+ if err != nil {
+ return nil, 0, err
+ }
+
+ offset := (info.Current - 1) * info.PageSize
+ err = db.Offset(offset).Limit(info.PageSize).Order("created_at DESC").Find(&list).Error
+ return list, total, err
+}
+
+// GetProgramById 获取节目详情
+func (s *ProgramService) GetProgramById(id string) (*radio.RadioProgram, error) {
+ var program radio.RadioProgram
+ err := global.DB.Where("id = ?", id).Preload("Cover").Preload("Audio").First(&program).Error
+ return &program, err
+}
+
+// SaveProgram 保存节目
+func (s *ProgramService) SaveProgram(req radioReq.SaveProgram) error {
+ program := radio.RadioProgram{
+ ChannelId: req.ChannelId,
+ Title: req.Title,
+ Description: req.Description,
+ Content: req.Content,
+ CoverId: req.CoverId,
+ AudioId: req.AudioId,
+ Duration: req.Duration,
+ Tags: req.Tags,
+ Status: req.Status,
+ }
+ return global.DB.Create(&program).Error
+}
+
+// UpdateProgram 更新节目
+func (s *ProgramService) UpdateProgram(req radioReq.UpdateProgram) error {
+ updates := map[string]interface{}{
+ "channel_id": req.ChannelId,
+ "title": req.Title,
+ "description": req.Description,
+ "content": req.Content,
+ "cover_id": req.CoverId,
+ "audio_id": req.AudioId,
+ "duration": req.Duration,
+ "tags": req.Tags,
+ "status": req.Status,
+ }
+ return global.DB.Model(&radio.RadioProgram{}).Where("id = ?", req.Id).Updates(updates).Error
+}
+
+// DeleteProgram 删除节目
+func (s *ProgramService) DeleteProgram(ids []string) error {
+ return global.DB.Transaction(func(tx *gorm.DB) error {
+ // 删除相关的收藏记录
+ tx.Where("program_id in ?", ids).Delete(&radio.RadioFavorite{})
+ // 删除相关的点赞记录
+ tx.Where("program_id in ?", ids).Delete(&radio.RadioLike{})
+ // 删除相关的历史记录
+ tx.Where("program_id in ?", ids).Delete(&radio.RadioHistory{})
+ // 删除相关的评论
+ tx.Where("program_id in ?", ids).Delete(&radio.RadioComment{})
+ // 删除节目
+ return tx.Where("id in ?", ids).Delete(&radio.RadioProgram{}).Error
+ })
+}
+
+// IncrementPlayCount 增加播放次数
+func (s *ProgramService) IncrementPlayCount(id string) error {
+ return global.DB.Model(&radio.RadioProgram{}).Where("id = ?", id).
+ UpdateColumn("play_count", gorm.Expr("play_count + ?", 1)).Error
+}
diff --git a/service/radio/subscription_service.go b/service/radio/subscription_service.go
new file mode 100644
index 0000000..07fafa7
--- /dev/null
+++ b/service/radio/subscription_service.go
@@ -0,0 +1,144 @@
+package radio
+
+import (
+ "errors"
+ "sundynix-go/global"
+ common "sundynix-go/model/commom/request"
+ "sundynix-go/model/radio"
+ "time"
+
+ "gorm.io/gorm"
+)
+
+type SubscriptionService struct{}
+
+const MaxFreeSubscription = 2
+
+// GetUserSubscription 获取用户订阅列表
+func (s *SubscriptionService) GetUserSubscription(userId string, info common.PageInfo) ([]radio.RadioSubscription, int64, error) {
+ db := global.DB.Model(&radio.RadioSubscription{}).Where("user_id = ?", userId)
+ var list []radio.RadioSubscription
+ var total int64
+
+ err := db.Count(&total).Error
+ if err != nil {
+ return nil, 0, err
+ }
+
+ offset := (info.Current - 1) * info.PageSize
+ err = db.Offset(offset).Limit(info.PageSize).Order("created_at DESC").Find(&list).Error
+ return list, total, err
+}
+
+// GetUserSubscriptionHistory 获取用户历史订阅过的频道ID列表
+func (s *SubscriptionService) GetUserSubscriptionHistory(userId string) ([]string, error) {
+ var channelIds []string
+ err := global.DB.Model(&radio.RadioSubscription{}).
+ Where("user_id = ?", userId).
+ Pluck("channel_id", &channelIds).Error
+ return channelIds, err
+}
+
+// HasEverSubscribed 检查用户是否曾经订阅过该频道(包括已取消的)
+func (s *SubscriptionService) HasEverSubscribed(userId, channelId string) (bool, error) {
+ var count int64
+ // 使用Unscoped查询包括已软删除的记录
+ err := global.DB.Unscoped().Model(&radio.RadioSubscription{}).
+ Where("user_id = ? AND channel_id = ?", userId, channelId).
+ Count(&count).Error
+ return count > 0, err
+}
+
+// HasSubscription 检查用户当前是否订阅该频道(未取消的)
+func (s *SubscriptionService) HasSubscription(userId, channelId string) (bool, error) {
+ var count int64
+ err := global.DB.Model(&radio.RadioSubscription{}).
+ Where("user_id = ? AND channel_id = ?", userId, channelId).
+ Count(&count).Error
+ return count > 0, err
+}
+
+// CanSubscribe 检查是否可以订阅
+// 规则:
+// 1. 如果用户是VIP且未过期,可以订阅任意频道
+// 2. 如果用户曾经订阅过该频道(取消后再订阅),可以免费订阅
+// 3. 否则检查当前有效订阅数量是否达到上限(2个)
+func (s *SubscriptionService) CanSubscribe(userId, channelId string) (bool, string, error) {
+ // 检查是否已经是订阅用户(未取消的订阅)
+ var existing radio.RadioSubscription
+ err := global.DB.Where("user_id = ? AND channel_id = ?", userId, channelId).First(&existing).Error
+ if err == nil {
+ return false, "您已订阅该频道", nil
+ }
+ if !errors.Is(err, gorm.ErrRecordNotFound) {
+ return false, "", err
+ }
+
+ // 获取radio_user检查VIP状态
+ var radioUser radio.RadioUser
+ err = global.DB.Where("user_id = ?", userId).First(&radioUser).Error
+ if err == nil && radioUser.IsVip == 1 {
+ // 检查VIP是否过期
+ if radioUser.VipExpireAt != nil && *radioUser.VipExpireAt > time.Now().Unix() {
+ return true, "", nil
+ }
+ }
+
+ // 检查用户是否曾经订阅过该频道(取消后又订阅的情况)
+ hasEverSubscribed, err := s.HasEverSubscribed(userId, channelId)
+ if err != nil {
+ return false, "", err
+ }
+ if hasEverSubscribed {
+ // 曾今订阅过,可以免费再次订阅
+ return true, "", nil
+ }
+
+ // 非VIP用户,检查当前有效订阅数量(排除已取消的)
+ var count int64
+ err = global.DB.Model(&radio.RadioSubscription{}).Where("user_id = ?", userId).Count(&count).Error
+ if err != nil {
+ return false, "", err
+ }
+ if count >= MaxFreeSubscription {
+ return false, "免费订阅数量已达上限(2个),请开通VIP或订阅付费频道", nil
+ }
+
+ return true, "", nil
+}
+
+// Subscribe 订阅频道
+func (s *SubscriptionService) Subscribe(userId, channelId string, subType int) error {
+ subscription := radio.RadioSubscription{
+ UserId: userId,
+ ChannelId: channelId,
+ }
+ return global.DB.Create(&subscription).Error
+}
+
+// Unsubscribe 退订频道(逻辑删除,更新删除时间表示已取消)
+func (s *SubscriptionService) Unsubscribe(userId, channelId string) error {
+ // 软删除:将DeletedAt设置为当前时间,表示已取消订阅
+ // 这样用户可以再次免费订阅该频道
+ return global.DB.Model(&radio.RadioSubscription{}).
+ Where("user_id = ? AND channel_id = ?", userId, channelId).
+ Update("deleted_at", time.Now()).Error
+}
+
+// GetVipStatus 获取VIP状态
+func (s *SubscriptionService) GetVipStatus(userId string) (bool, int64, error) {
+ var radioUser radio.RadioUser
+ err := global.DB.Where("user_id = ?", userId).First(&radioUser).Error
+ if err != nil {
+ if errors.Is(err, gorm.ErrRecordNotFound) {
+ return false, 0, nil
+ }
+ return false, 0, err
+ }
+
+ if radioUser.IsVip == 1 && radioUser.VipExpireAt != nil && *radioUser.VipExpireAt > time.Now().Unix() {
+ return true, *radioUser.VipExpireAt, nil
+ }
+
+ return false, 0, nil
+}
diff --git a/service/system/sys_user.go b/service/system/sys_user.go
index d6ea35d..c147115 100644
--- a/service/system/sys_user.go
+++ b/service/system/sys_user.go
@@ -12,6 +12,7 @@ import (
"strconv"
"sundynix-go/global"
common "sundynix-go/model/commom/request"
+ "sundynix-go/model/radio"
"sundynix-go/model/system"
systemReq "sundynix-go/model/system/request"
systemResp "sundynix-go/model/system/response"
@@ -157,6 +158,17 @@ func (userService *UserService) MiniLogin(code string) (result *system.User, err
if err := tx.Create(&newUser).Error; err != nil {
return err
}
+ // 创建小程序用户
+ mpUser := radio.RadioUser{
+ UserId: newUser.Id,
+ OpenId: wxResp.Openid,
+ UnionId: wxResp.Unionid,
+ SessionKey: wxResp.SessionKey,
+ }
+ if err := tx.Create(&mpUser).Error; err != nil {
+ return err
+ }
+
// 赋值给外部变量以便返回
user = newUser
return nil