Compare commits
9 Commits
faa6a35475
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
| 6e7699965b | |||
| ec380030ca | |||
| 9fa26bc026 | |||
| b1934579c0 | |||
| cd4079c24d | |||
| 0d65a890f6 | |||
| ca373ad91f | |||
| bfca5d7d0b | |||
| e5446bf836 |
@ -1,9 +1,9 @@
|
|||||||
name: Gitea Actions Demo
|
name: ocean
|
||||||
run-name: ${{ gitea.actor }} is testing out Gitea Actions 🚀
|
run-name: ${{ gitea.actor }} is testing out Gitea Actions 🚀
|
||||||
on: [push]
|
on: [push]
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
Explore-Gitea-Actions:
|
Build-and-Deploy-Modules:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- run: echo "🎉 The job was automatically triggered by a ${{ gitea.event_name }} event."
|
- run: echo "🎉 The job was automatically triggered by a ${{ gitea.event_name }} event."
|
||||||
@ -13,8 +13,27 @@ jobs:
|
|||||||
run: git clone ${{ gitea.server_url }}/${{ gitea.repository }} .
|
run: git clone ${{ gitea.server_url }}/${{ gitea.repository }} .
|
||||||
- run: echo "💡 The ${{ gitea.repository }} repository has been cloned to the runner."
|
- run: echo "💡 The ${{ gitea.repository }} repository has been cloned to the runner."
|
||||||
- run: echo "🖥️ The workflow is now ready to test your code on the runner."
|
- run: echo "🖥️ The workflow is now ready to test your code on the runner."
|
||||||
- name: List files in the repository
|
|
||||||
|
- name: Get changed files
|
||||||
|
id: changes
|
||||||
run: |
|
run: |
|
||||||
|
echo "CHANGED=$(git diff --name-only ${{ gitea.before }} ${{ gitea.after }})" >> $GITHUB_ENV
|
||||||
|
echo "gitea.before=${{ gitea.before }}"
|
||||||
|
echo "gitea.after=${{ gitea.after }}"
|
||||||
|
echo "CHANGED=${{ env.CHANGED }}"
|
||||||
|
|
||||||
|
- name: Build file service if changed
|
||||||
|
if: contains(env.CHANGED, 'file/')
|
||||||
|
run: |
|
||||||
|
echo "File module changed, building..."
|
||||||
docker build -t file -f docker/docker-file/Dockerfile .
|
docker build -t file -f docker/docker-file/Dockerfile .
|
||||||
docker compose -f docker/docker-file/docker-compose-prod.yaml up -d
|
docker compose -f docker/docker-file/docker-compose-prod.yaml up -d
|
||||||
|
|
||||||
|
- name: Build user service if changed
|
||||||
|
if: contains(env.CHANGED, 'user/')
|
||||||
|
run: |
|
||||||
|
echo "File module changed, building..."
|
||||||
|
docker build -t file -f docker/docker-user/Dockerfile .
|
||||||
|
docker compose -f docker/docker-user/docker-compose-prod.yaml up -d
|
||||||
|
|
||||||
- run: echo "🍏 This job's status is ${{ job.status }}."
|
- run: echo "🍏 This job's status is ${{ job.status }}."
|
||||||
38
README.md
38
README.md
@ -11,6 +11,7 @@ godemo/ # 项目根目录
|
|||||||
├── go.sum # 依赖校验
|
├── go.sum # 依赖校验
|
||||||
├── docker/ # Docker文件目录
|
├── docker/ # Docker文件目录
|
||||||
└── docker-gateway/ # gateway服务的Docker文件目录
|
└── docker-gateway/ # gateway服务的Docker文件目录
|
||||||
|
├── etc/config.yaml # gateway服务配置文件(用于配置启动服务)(Optional)
|
||||||
├── Dockerfile # gateway服务的Dockerfile文件
|
├── Dockerfile # gateway服务的Dockerfile文件
|
||||||
└── docker-compose.yml # gateway服务的docker-compose文件
|
└── docker-compose.yml # gateway服务的docker-compose文件
|
||||||
├── sql/ # 数据库SQL定义
|
├── sql/ # 数据库SQL定义
|
||||||
@ -144,7 +145,7 @@ networks:
|
|||||||
|
|
||||||
```bash
|
```bash
|
||||||
# 在对应服务的docker目录执行(以file服务为例)
|
# 在对应服务的docker目录执行(以file服务为例)
|
||||||
> docker/docker-file> docker compose up -d
|
docker/docker-file> docker compose up -d
|
||||||
```
|
```
|
||||||
|
|
||||||
## RPC服务测试/调试
|
## RPC服务测试/调试
|
||||||
@ -166,13 +167,37 @@ networks:
|
|||||||
|
|
||||||
**接口定义**
|
**接口定义**
|
||||||
|
|
||||||
|
- 用户注册
|
||||||
- 用户登录
|
- 用户登录
|
||||||
- 获取用户信息
|
- 获取用户信息
|
||||||
- 用户注册
|
|
||||||
- 用户注销
|
- 用户注销
|
||||||
|
|
||||||
## 文件服务
|
## 文件服务
|
||||||
|
|
||||||
|
- 文件上传
|
||||||
|
- 获取文件URL(下载文件)
|
||||||
|
- 文件删除
|
||||||
|
|
||||||
|
**对于存储在MinIO的图片文件**
|
||||||
|
|
||||||
|
```
|
||||||
|
bucket/image_id.png
|
||||||
|
```
|
||||||
|
|
||||||
|
原始图片类似上面的文件名,其中```image_id```支持多级文件夹。支持异步生成缩略图操作,缩略图文件名格式为:缩略图类型/原始图片的bucket/image_id.png。以```thumbnail```为例:```thumbnail/bucket/image_id.png```。
|
||||||
|
|
||||||
|
```dev
|
||||||
|
# 上传文件
|
||||||
|
grpcurl -d '{\"filename\": \"1a.png\", \"folder\": \"zhang san/li si\", \"bucket\": \"wallpaper\", \"content\": \"iVBORw0KGgoAAAANSUhEUgAAAC8AAAAhCAYAAABJLfLcAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAVhSURBVFhH7ZZpbJRFGMd/8777Lu1u6UFpC9tDCqVFDkGOgFDlLHJIQUDQGCFgpOIHvnBpqZRbBEm1FFAwFUzEKxJjKoGABDQoJIggV6jUSmi70O1BW3bb7R7jh22lLPuuQRMbTH/JZLPzzPvMM/95npkRo0aNkjykKP4dDxMdwbcXHcG3F//34AXdJqxg+wfvs+utefQP9bffRbE8zcp3d7CjYD1zU42+TqGgquq/aorwn8mHwb/jfhSEMYSwsM5oTg0dPy1omCIiidQa0QBQSZy2mrWze6B4/9l1IhQPv3++mvXfluP1s+kqryVPJ+e9AvLz81g1oycaICJG8OqWfPK357M5awRRAoQQCCEAgdJGIkVVfQuVEq+USP+GQDFoaJqGZlARBBgjJdLrH/JdhN4NqyXPYcPa6SSo/hYf9Wf38ol1LPMnxKG0ehAGjJ0MKEg8zU7qL+9n/bZjVAaYQXtkBjm5s+llBMeFQnK2HqNSN06JDOBDN3glIoG0+AgUBJ0ff46sKSlo1afYu+coVq+CdDsJG7mYJRO66aZS05V9ZG88isOSgiWs7SiF6CfmkZWRhEFW89NHuzlS5mpjv4u3oYKSiob7UoagwWtGNEUgpUr3SctYMzcNreo423I/5nIjSKkR07svSeFttiY0jWdeyqCHoZIf93/JzzfLuHjOStycDeRmJqCziUHwUF60jlWfXiPQ0nQKNpIRr21i8bDwFlWF77fraJYWjPYNaS5mf85GDl/vRs/Ien4ra0DpHsVEADzcLjnDqeJmQCOuxWuT9QqXyh2YEwfQJ06ltuRXSmo9AGixaTyW1JnG8otctjoxxfejb3df2euhW7C0FKKv/dXZpkANWCYsZ/vOLbz+8miSDCCEvjsAt/U4hXn7OFnpAbxUn/mM/Lw88vJ28vWlO0ig+foR9uQVcsLqW1QwdJSv4/SupZzfI5BSIbpfOsMSQ8FdzaWTZyhrwldEkenEPDmA/r0nMnXg9+y2BsxAHTSSn81l51RfNqtGUxAlA6MzXuJxOrDb7TgcDtwxw5g2axYzx6dgdNix2+3Y7Q4c5ac48kstUkQzZPJILDpS6OF1OXE6W5o7UEkGR3e68KFZrFk0BLOUKMZQjABR6SzJH46U4K44xDsbD3D5h7PYRo4nNnU8GX3O+LsJgovrRZtZ900ZHoykvriJN6d09x8UFB3lQSpGQs1mwsLCMBlbzgnViMlkxmw2Y+7k63MUn+TUtXKunDjGuSr3vU6CohI7agErs7PJzl7GC4MjdI9cPXSVbyo+wJacIpCCyOHzWZKZglZ9kt3bD3LDLZDuBirdgLzKF2tXICWolqlM83eki0J4fBp941v/t5xoD4Cu8q7b5ZSWllL6RynWutbKb6bulpVbNQ00q9Ekp8YR4nsBACADXYO6uLj2VQ6vLFzIwgVZbDhs5UG+Rl/5cNLGjmOgJYrIqCi6JlowAKLLUywtGIOqCkBiO1FAvisSg+Ki2duJhPQRJBoBjxdvgIeYNKUwJjOWrqE+W4hlKBmTmgEIjWlJzc5pjMtMoIv57wtY54Y1MXDR2ywf3SXIVnooP7SVD2/P5I3nU30F3YrjAoXZb/OdTQIaveb+pzesk+qKKhpdIbjqblNju8VNq5WKm7ew2WzYqqqpra2n/s4dROpQamUqca2rlE1cP17Eadv9mjRcOczBczUB3yn3ohA9aDITHzX7G+5BR3kQqgHF68YT0NqGkBh6JkUg3G5cTgf1NTXUNbrb5K+BrmmDSY02IB03OH/uBo57HATCRMKggSSZBO7qYs5erSLQOaYb/MOA7mnzMNARfHvREXx70RF8e/EnBBEDlIbPjKIAAAAASUVORK5CYII=\"}' -plaintext localhost:60200 file.File/Upload
|
||||||
|
|
||||||
|
# 获取文件URL
|
||||||
|
grpcurl -d '{\"file_id\": \"zhangsan/a24c8397-d373-4eb7-a563-b0c9c3f4591c.png\"}' -plaintext localhost:60200 file.File/GetFileUrl
|
||||||
|
|
||||||
|
# 图片处理
|
||||||
|
grpcurl -d '{\"file_id\": \"gallery/tian gou/xiao mao/2d805261-422e-4b2a-ac24-60eb8af7a17b.png\", \"versions\": [1]}' -plaintext localhost:60200 file.File/GenerateImageVersions
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
## 分类服务
|
## 分类服务
|
||||||
|
|
||||||
分类服务(Category Service),这是一个用于统一管理多系统/多模块分类体系的微服务。
|
分类服务(Category Service),这是一个用于统一管理多系统/多模块分类体系的微服务。
|
||||||
@ -193,6 +218,9 @@ grpcurl -plaintext -d '{\"id\": \"d628cf35-539f-4533-a5a2-492d729ecf3b\",\"name\
|
|||||||
# 查
|
# 查
|
||||||
grpcurl -plaintext -d '{\"id\": \"d628cf35-539f-4533-a5a2-492d729ecf3b\"}' localhost:60300 category.Category/GetCategory
|
grpcurl -plaintext -d '{\"id\": \"d628cf35-539f-4533-a5a2-492d729ecf3b\"}' localhost:60300 category.Category/GetCategory
|
||||||
|
|
||||||
|
# 查询某一分类的完整分类(从根分类到当前分类)
|
||||||
|
grpcurl -plaintext -d '{\"id\": \"da24a78c-ad51-4e82-8aa9-b35342f7ef30\"}' localhost:60300 category.Category/GetFullCategories
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|
||||||
## 图库服务
|
## 图库服务
|
||||||
@ -208,7 +236,11 @@ grpcurl -plaintext -d '{\"id\": \"d628cf35-539f-4533-a5a2-492d729ecf3b\"}' local
|
|||||||
- 获取图片URL
|
- 获取图片URL
|
||||||
- 下载图片
|
- 下载图片
|
||||||
|
|
||||||
/api/gallery/v1/
|
```dev
|
||||||
|
# 上传图片
|
||||||
|
grpcurl -d '{\"file_name\": \"1a.png\", \"category_id\": \"da24a78c-ad51-4e82-8aa9-b35342f7ef30\", \"title\": \"背景\", \"file_content\": \"iVBORw0KGgoAAAANSUhEUgAAAC8AAAAhCAYAAABJLfLcAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAVhSURBVFhH7ZZpbJRFGMd/8777Lu1u6UFpC9tDCqVFDkGOgFDlLHJIQUDQGCFgpOIHvnBpqZRbBEm1FFAwFUzEKxJjKoGABDQoJIggV6jUSmi70O1BW3bb7R7jh22lLPuuQRMbTH/JZLPzzPvMM/95npkRo0aNkjykKP4dDxMdwbcXHcG3F//34AXdJqxg+wfvs+utefQP9bffRbE8zcp3d7CjYD1zU42+TqGgquq/aorwn8mHwb/jfhSEMYSwsM5oTg0dPy1omCIiidQa0QBQSZy2mrWze6B4/9l1IhQPv3++mvXfluP1s+kqryVPJ+e9AvLz81g1oycaICJG8OqWfPK357M5awRRAoQQCCEAgdJGIkVVfQuVEq+USP+GQDFoaJqGZlARBBgjJdLrH/JdhN4NqyXPYcPa6SSo/hYf9Wf38ol1LPMnxKG0ehAGjJ0MKEg8zU7qL+9n/bZjVAaYQXtkBjm5s+llBMeFQnK2HqNSN06JDOBDN3glIoG0+AgUBJ0ff46sKSlo1afYu+coVq+CdDsJG7mYJRO66aZS05V9ZG88isOSgiWs7SiF6CfmkZWRhEFW89NHuzlS5mpjv4u3oYKSiob7UoagwWtGNEUgpUr3SctYMzcNreo423I/5nIjSKkR07svSeFttiY0jWdeyqCHoZIf93/JzzfLuHjOStycDeRmJqCziUHwUF60jlWfXiPQ0nQKNpIRr21i8bDwFlWF77fraJYWjPYNaS5mf85GDl/vRs/Ien4ra0DpHsVEADzcLjnDqeJmQCOuxWuT9QqXyh2YEwfQJ06ltuRXSmo9AGixaTyW1JnG8otctjoxxfejb3df2euhW7C0FKKv/dXZpkANWCYsZ/vOLbz+8miSDCCEvjsAt/U4hXn7OFnpAbxUn/mM/Lw88vJ28vWlO0ig+foR9uQVcsLqW1QwdJSv4/SupZzfI5BSIbpfOsMSQ8FdzaWTZyhrwldEkenEPDmA/r0nMnXg9+y2BsxAHTSSn81l51RfNqtGUxAlA6MzXuJxOrDb7TgcDtwxw5g2axYzx6dgdNix2+3Y7Q4c5ac48kstUkQzZPJILDpS6OF1OXE6W5o7UEkGR3e68KFZrFk0BLOUKMZQjABR6SzJH46U4K44xDsbD3D5h7PYRo4nNnU8GX3O+LsJgovrRZtZ900ZHoykvriJN6d09x8UFB3lQSpGQs1mwsLCMBlbzgnViMlkxmw2Y+7k63MUn+TUtXKunDjGuSr3vU6CohI7agErs7PJzl7GC4MjdI9cPXSVbyo+wJacIpCCyOHzWZKZglZ9kt3bD3LDLZDuBirdgLzKF2tXICWolqlM83eki0J4fBp941v/t5xoD4Cu8q7b5ZSWllL6RynWutbKb6bulpVbNQ00q9Ekp8YR4nsBACADXYO6uLj2VQ6vLFzIwgVZbDhs5UG+Rl/5cNLGjmOgJYrIqCi6JlowAKLLUywtGIOqCkBiO1FAvisSg+Ki2duJhPQRJBoBjxdvgIeYNKUwJjOWrqE+W4hlKBmTmgEIjWlJzc5pjMtMoIv57wtY54Y1MXDR2ywf3SXIVnooP7SVD2/P5I3nU30F3YrjAoXZb/OdTQIaveb+pzesk+qKKhpdIbjqblNju8VNq5WKm7ew2WzYqqqpra2n/s4dROpQamUqca2rlE1cP17Eadv9mjRcOczBczUB3yn3ohA9aDITHzX7G+5BR3kQqgHF68YT0NqGkBh6JkUg3G5cTgf1NTXUNbrb5K+BrmmDSY02IB03OH/uBo57HATCRMKggSSZBO7qYs5erSLQOaYb/MOA7mnzMNARfHvREXx70RF8e/EnBBEDlIbPjKIAAAAASUVORK5CYII=\"}' -plaintext localhost:50000 gallery.Gallery/UploadImage
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
138
api/gateway.api
138
api/gateway.api
@ -1,5 +1,12 @@
|
|||||||
syntax = "v1"
|
syntax = "v1"
|
||||||
|
|
||||||
|
// ================== 通用类型定义 ==================
|
||||||
|
type BaseResp {
|
||||||
|
Code int `json:"code"` // 状态码 (0=成功)
|
||||||
|
Message string `json:"message"` // 消息
|
||||||
|
}
|
||||||
|
|
||||||
|
// ================== 用户服务类型 ==================
|
||||||
type RegisterReq {
|
type RegisterReq {
|
||||||
Username string `json:"username"`
|
Username string `json:"username"`
|
||||||
Password string `json:"password"`
|
Password string `json:"password"`
|
||||||
@ -40,22 +47,139 @@ type GetUserInfoResp {
|
|||||||
Roles []string `json:"roles"`
|
Roles []string `json:"roles"`
|
||||||
}
|
}
|
||||||
|
|
||||||
service user-api {
|
// ================== 分类服务类型 ==================
|
||||||
|
type BaseCategory {
|
||||||
|
ID string `json:"id"` // 分类ID (UUID)
|
||||||
|
SystemID string `json:"systemId"` // 所属系统ID
|
||||||
|
Name string `json:"name"` // 分类名称
|
||||||
|
Alias string `json:"alias"` // URL别名
|
||||||
|
ParentID string `json:"parentId"` // 父分类ID (可为空)
|
||||||
|
Description string `json:"description"` // 分类描述
|
||||||
|
CreatedAt string `json:"createdAt"` // 创建时间 (ISO8601)
|
||||||
|
UpdatedAt string `json:"updatedAt"` // 更新时间 (ISO8601)
|
||||||
|
}
|
||||||
|
|
||||||
|
type CategoryDetail {
|
||||||
|
BaseCategory
|
||||||
|
Parent *BaseCategory `json:"parent"` // 父分类信息
|
||||||
|
}
|
||||||
|
|
||||||
|
type TreeNode {
|
||||||
|
BaseCategory
|
||||||
|
Children []*TreeNode `json:"children"` // 子分类列表
|
||||||
|
}
|
||||||
|
|
||||||
|
type CreateCategoryReq {
|
||||||
|
SystemID string `json:"systemId" validate:"required"` // 所属系统ID
|
||||||
|
Name string `json:"name" validate:"required"` // 分类名称
|
||||||
|
Alias string `json:"alias,optional"` // URL别名
|
||||||
|
ParentID string `json:"parentId,optional"` // 父分类ID
|
||||||
|
Description string `json:"description,optional"` // 分类描述
|
||||||
|
}
|
||||||
|
|
||||||
|
type CreateCategoryResp {
|
||||||
|
ID string `json:"id"` // 新创建的分类ID
|
||||||
|
}
|
||||||
|
|
||||||
|
type ListCategoriesReq {
|
||||||
|
SystemID string `form:"systemId,optional"` // 按系统ID过滤
|
||||||
|
ParentID string `form:"parentId,optional"` // 按父分类ID过滤
|
||||||
|
Name string `form:"name,optional"` // 按名称模糊搜索
|
||||||
|
Page int `form:"page,default=1"` // 页码
|
||||||
|
PageSize int `form:"pageSize,default=20"` // 每页数量
|
||||||
|
}
|
||||||
|
|
||||||
|
type ListCategoriesResp {
|
||||||
|
Total int64 `json:"total"` // 总数
|
||||||
|
List []BaseCategory `json:"list"` // 分类列表
|
||||||
|
}
|
||||||
|
|
||||||
|
type GetCategoryReq {
|
||||||
|
ID string `path:"id"` // 分类ID
|
||||||
|
}
|
||||||
|
|
||||||
|
type CategoryDetailResp {
|
||||||
|
CategoryDetail
|
||||||
|
}
|
||||||
|
|
||||||
|
type UpdateCategoryReq {
|
||||||
|
ID string `path:"id"` // 分类ID
|
||||||
|
Name string `json:"name,optional"` // 新名称
|
||||||
|
Alias string `json:"alias,optional"` // 新别名
|
||||||
|
ParentID string `json:"parentId,optional"` // 新父分类ID
|
||||||
|
Description string `json:"description,optional"` // 新描述
|
||||||
|
}
|
||||||
|
|
||||||
|
type GetCategoryTreeReq {
|
||||||
|
ID string `path:"id"` // 起始分类ID
|
||||||
|
}
|
||||||
|
|
||||||
|
type CategoryTreeResp {
|
||||||
|
Root TreeNode `json:"root"` // 分类树根节点
|
||||||
|
}
|
||||||
|
|
||||||
|
type GetSystemCategoriesReq {
|
||||||
|
SystemID string `path:"system_id"` // 系统ID
|
||||||
|
ParentID string `form:"parentId,optional"` // 父分类ID (可选)
|
||||||
|
IncludeDescendants bool `form:"includeDescendants,default=true"` // 是否包含子分类
|
||||||
|
}
|
||||||
|
|
||||||
|
type DeleteCategoryReq {
|
||||||
|
ID string `path:"id"` // 分类ID
|
||||||
|
}
|
||||||
|
|
||||||
|
// ================== 网关服务定义 ==================
|
||||||
|
@server (
|
||||||
|
prefix: /api
|
||||||
|
)
|
||||||
|
service gateway-api {
|
||||||
|
// ===== 用户服务 =====
|
||||||
|
// 公共接口(无需认证)
|
||||||
@handler registerHandler
|
@handler registerHandler
|
||||||
post /api/user/register (RegisterReq) returns (RegisterResp)
|
post /user/register (RegisterReq) returns (RegisterResp)
|
||||||
|
|
||||||
@handler loginHandler
|
@handler loginHandler
|
||||||
post /api/user/login (LoginReq) returns (LoginResp)
|
post /user/login (LoginReq) returns (LoginResp)
|
||||||
}
|
}
|
||||||
|
|
||||||
@server (
|
@server (
|
||||||
jwt: JwtAuth
|
prefix: /api
|
||||||
|
jwt: JwtAuth
|
||||||
)
|
)
|
||||||
service user-api {
|
service gateway-api {
|
||||||
@handler logoutHandler
|
@handler logoutHandler
|
||||||
post /api/user/logout (LogoutReq) returns (LogoutResp)
|
post /user/logout (LogoutReq) returns (LogoutResp)
|
||||||
|
|
||||||
@handler getUserInfoHandler
|
@handler getUserInfoHandler
|
||||||
get /api/user/:user_id (GetUserInfoReq) returns (GetUserInfoResp)
|
get /user/:user_id (GetUserInfoReq) returns (GetUserInfoResp)
|
||||||
|
|
||||||
|
// ===== 分类服务 =====
|
||||||
|
// 创建分类
|
||||||
|
@handler createCategoryHandler
|
||||||
|
post /category/v1 (CreateCategoryReq) returns (CreateCategoryResp)
|
||||||
|
|
||||||
|
// 批量获取分类(带分页和过滤)
|
||||||
|
@handler listCategoriesHandler
|
||||||
|
get /category/v1 (ListCategoriesReq) returns (ListCategoriesResp)
|
||||||
|
|
||||||
|
// 获取单个分类详情
|
||||||
|
@handler getCategoryHandler
|
||||||
|
get /category/v1/:id (GetCategoryReq) returns (CategoryDetailResp)
|
||||||
|
|
||||||
|
// 更新分类
|
||||||
|
@handler updateCategoryHandler
|
||||||
|
put /category/v1/:id (UpdateCategoryReq) returns (BaseResp)
|
||||||
|
|
||||||
|
// 删除分类
|
||||||
|
@handler deleteCategoryHandler
|
||||||
|
delete /category/v1/:id (DeleteCategoryReq) returns (BaseResp)
|
||||||
|
|
||||||
|
// 获取子分类树
|
||||||
|
@handler getCategoryTreeHandler
|
||||||
|
get /category/v1/:id/tree (GetCategoryTreeReq) returns (CategoryTreeResp)
|
||||||
|
|
||||||
|
// 根据系统ID获取分类
|
||||||
|
@handler getSystemCategoriesHandler
|
||||||
|
get /category/v1/system/:system_id (GetSystemCategoriesReq) returns (ListCategoriesResp)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -501,6 +501,51 @@ func (x *GetCategoryRequest) GetId() string {
|
|||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 获取全分类名称的响应
|
||||||
|
type GetFullCategoriesResponse struct {
|
||||||
|
state protoimpl.MessageState `protogen:"open.v1"`
|
||||||
|
FullCategoryName string `protobuf:"bytes,1,opt,name=full_category_name,json=fullCategoryName,proto3" json:"full_category_name,omitempty"`
|
||||||
|
unknownFields protoimpl.UnknownFields
|
||||||
|
sizeCache protoimpl.SizeCache
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *GetFullCategoriesResponse) Reset() {
|
||||||
|
*x = GetFullCategoriesResponse{}
|
||||||
|
mi := &file_rpc_category_proto_msgTypes[8]
|
||||||
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
|
ms.StoreMessageInfo(mi)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *GetFullCategoriesResponse) String() string {
|
||||||
|
return protoimpl.X.MessageStringOf(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (*GetFullCategoriesResponse) ProtoMessage() {}
|
||||||
|
|
||||||
|
func (x *GetFullCategoriesResponse) ProtoReflect() protoreflect.Message {
|
||||||
|
mi := &file_rpc_category_proto_msgTypes[8]
|
||||||
|
if x != nil {
|
||||||
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
|
if ms.LoadMessageInfo() == nil {
|
||||||
|
ms.StoreMessageInfo(mi)
|
||||||
|
}
|
||||||
|
return ms
|
||||||
|
}
|
||||||
|
return mi.MessageOf(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Deprecated: Use GetFullCategoriesResponse.ProtoReflect.Descriptor instead.
|
||||||
|
func (*GetFullCategoriesResponse) Descriptor() ([]byte, []int) {
|
||||||
|
return file_rpc_category_proto_rawDescGZIP(), []int{8}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *GetFullCategoriesResponse) GetFullCategoryName() string {
|
||||||
|
if x != nil {
|
||||||
|
return x.FullCategoryName
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
// 分类信息响应
|
// 分类信息响应
|
||||||
type CategoryInfoResponse struct {
|
type CategoryInfoResponse struct {
|
||||||
state protoimpl.MessageState `protogen:"open.v1"`
|
state protoimpl.MessageState `protogen:"open.v1"`
|
||||||
@ -511,7 +556,7 @@ type CategoryInfoResponse struct {
|
|||||||
|
|
||||||
func (x *CategoryInfoResponse) Reset() {
|
func (x *CategoryInfoResponse) Reset() {
|
||||||
*x = CategoryInfoResponse{}
|
*x = CategoryInfoResponse{}
|
||||||
mi := &file_rpc_category_proto_msgTypes[8]
|
mi := &file_rpc_category_proto_msgTypes[9]
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
ms.StoreMessageInfo(mi)
|
ms.StoreMessageInfo(mi)
|
||||||
}
|
}
|
||||||
@ -523,7 +568,7 @@ func (x *CategoryInfoResponse) String() string {
|
|||||||
func (*CategoryInfoResponse) ProtoMessage() {}
|
func (*CategoryInfoResponse) ProtoMessage() {}
|
||||||
|
|
||||||
func (x *CategoryInfoResponse) ProtoReflect() protoreflect.Message {
|
func (x *CategoryInfoResponse) ProtoReflect() protoreflect.Message {
|
||||||
mi := &file_rpc_category_proto_msgTypes[8]
|
mi := &file_rpc_category_proto_msgTypes[9]
|
||||||
if x != nil {
|
if x != nil {
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
if ms.LoadMessageInfo() == nil {
|
if ms.LoadMessageInfo() == nil {
|
||||||
@ -536,7 +581,7 @@ func (x *CategoryInfoResponse) ProtoReflect() protoreflect.Message {
|
|||||||
|
|
||||||
// Deprecated: Use CategoryInfoResponse.ProtoReflect.Descriptor instead.
|
// Deprecated: Use CategoryInfoResponse.ProtoReflect.Descriptor instead.
|
||||||
func (*CategoryInfoResponse) Descriptor() ([]byte, []int) {
|
func (*CategoryInfoResponse) Descriptor() ([]byte, []int) {
|
||||||
return file_rpc_category_proto_rawDescGZIP(), []int{8}
|
return file_rpc_category_proto_rawDescGZIP(), []int{9}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *CategoryInfoResponse) GetCategory() *CategoryInfo {
|
func (x *CategoryInfoResponse) GetCategory() *CategoryInfo {
|
||||||
@ -557,7 +602,7 @@ type GetChildrenRequest struct {
|
|||||||
|
|
||||||
func (x *GetChildrenRequest) Reset() {
|
func (x *GetChildrenRequest) Reset() {
|
||||||
*x = GetChildrenRequest{}
|
*x = GetChildrenRequest{}
|
||||||
mi := &file_rpc_category_proto_msgTypes[9]
|
mi := &file_rpc_category_proto_msgTypes[10]
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
ms.StoreMessageInfo(mi)
|
ms.StoreMessageInfo(mi)
|
||||||
}
|
}
|
||||||
@ -569,7 +614,7 @@ func (x *GetChildrenRequest) String() string {
|
|||||||
func (*GetChildrenRequest) ProtoMessage() {}
|
func (*GetChildrenRequest) ProtoMessage() {}
|
||||||
|
|
||||||
func (x *GetChildrenRequest) ProtoReflect() protoreflect.Message {
|
func (x *GetChildrenRequest) ProtoReflect() protoreflect.Message {
|
||||||
mi := &file_rpc_category_proto_msgTypes[9]
|
mi := &file_rpc_category_proto_msgTypes[10]
|
||||||
if x != nil {
|
if x != nil {
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
if ms.LoadMessageInfo() == nil {
|
if ms.LoadMessageInfo() == nil {
|
||||||
@ -582,7 +627,7 @@ func (x *GetChildrenRequest) ProtoReflect() protoreflect.Message {
|
|||||||
|
|
||||||
// Deprecated: Use GetChildrenRequest.ProtoReflect.Descriptor instead.
|
// Deprecated: Use GetChildrenRequest.ProtoReflect.Descriptor instead.
|
||||||
func (*GetChildrenRequest) Descriptor() ([]byte, []int) {
|
func (*GetChildrenRequest) Descriptor() ([]byte, []int) {
|
||||||
return file_rpc_category_proto_rawDescGZIP(), []int{9}
|
return file_rpc_category_proto_rawDescGZIP(), []int{10}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *GetChildrenRequest) GetParentId() string {
|
func (x *GetChildrenRequest) GetParentId() string {
|
||||||
@ -610,7 +655,7 @@ type GetTreeRequest struct {
|
|||||||
|
|
||||||
func (x *GetTreeRequest) Reset() {
|
func (x *GetTreeRequest) Reset() {
|
||||||
*x = GetTreeRequest{}
|
*x = GetTreeRequest{}
|
||||||
mi := &file_rpc_category_proto_msgTypes[10]
|
mi := &file_rpc_category_proto_msgTypes[11]
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
ms.StoreMessageInfo(mi)
|
ms.StoreMessageInfo(mi)
|
||||||
}
|
}
|
||||||
@ -622,7 +667,7 @@ func (x *GetTreeRequest) String() string {
|
|||||||
func (*GetTreeRequest) ProtoMessage() {}
|
func (*GetTreeRequest) ProtoMessage() {}
|
||||||
|
|
||||||
func (x *GetTreeRequest) ProtoReflect() protoreflect.Message {
|
func (x *GetTreeRequest) ProtoReflect() protoreflect.Message {
|
||||||
mi := &file_rpc_category_proto_msgTypes[10]
|
mi := &file_rpc_category_proto_msgTypes[11]
|
||||||
if x != nil {
|
if x != nil {
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
if ms.LoadMessageInfo() == nil {
|
if ms.LoadMessageInfo() == nil {
|
||||||
@ -635,7 +680,7 @@ func (x *GetTreeRequest) ProtoReflect() protoreflect.Message {
|
|||||||
|
|
||||||
// Deprecated: Use GetTreeRequest.ProtoReflect.Descriptor instead.
|
// Deprecated: Use GetTreeRequest.ProtoReflect.Descriptor instead.
|
||||||
func (*GetTreeRequest) Descriptor() ([]byte, []int) {
|
func (*GetTreeRequest) Descriptor() ([]byte, []int) {
|
||||||
return file_rpc_category_proto_rawDescGZIP(), []int{10}
|
return file_rpc_category_proto_rawDescGZIP(), []int{11}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *GetTreeRequest) GetSystemId() string {
|
func (x *GetTreeRequest) GetSystemId() string {
|
||||||
@ -663,7 +708,7 @@ type MoveCategoryRequest struct {
|
|||||||
|
|
||||||
func (x *MoveCategoryRequest) Reset() {
|
func (x *MoveCategoryRequest) Reset() {
|
||||||
*x = MoveCategoryRequest{}
|
*x = MoveCategoryRequest{}
|
||||||
mi := &file_rpc_category_proto_msgTypes[11]
|
mi := &file_rpc_category_proto_msgTypes[12]
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
ms.StoreMessageInfo(mi)
|
ms.StoreMessageInfo(mi)
|
||||||
}
|
}
|
||||||
@ -675,7 +720,7 @@ func (x *MoveCategoryRequest) String() string {
|
|||||||
func (*MoveCategoryRequest) ProtoMessage() {}
|
func (*MoveCategoryRequest) ProtoMessage() {}
|
||||||
|
|
||||||
func (x *MoveCategoryRequest) ProtoReflect() protoreflect.Message {
|
func (x *MoveCategoryRequest) ProtoReflect() protoreflect.Message {
|
||||||
mi := &file_rpc_category_proto_msgTypes[11]
|
mi := &file_rpc_category_proto_msgTypes[12]
|
||||||
if x != nil {
|
if x != nil {
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
if ms.LoadMessageInfo() == nil {
|
if ms.LoadMessageInfo() == nil {
|
||||||
@ -688,7 +733,7 @@ func (x *MoveCategoryRequest) ProtoReflect() protoreflect.Message {
|
|||||||
|
|
||||||
// Deprecated: Use MoveCategoryRequest.ProtoReflect.Descriptor instead.
|
// Deprecated: Use MoveCategoryRequest.ProtoReflect.Descriptor instead.
|
||||||
func (*MoveCategoryRequest) Descriptor() ([]byte, []int) {
|
func (*MoveCategoryRequest) Descriptor() ([]byte, []int) {
|
||||||
return file_rpc_category_proto_rawDescGZIP(), []int{11}
|
return file_rpc_category_proto_rawDescGZIP(), []int{12}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *MoveCategoryRequest) GetId() string {
|
func (x *MoveCategoryRequest) GetId() string {
|
||||||
@ -715,7 +760,7 @@ type GetAncestorPathRequest struct {
|
|||||||
|
|
||||||
func (x *GetAncestorPathRequest) Reset() {
|
func (x *GetAncestorPathRequest) Reset() {
|
||||||
*x = GetAncestorPathRequest{}
|
*x = GetAncestorPathRequest{}
|
||||||
mi := &file_rpc_category_proto_msgTypes[12]
|
mi := &file_rpc_category_proto_msgTypes[13]
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
ms.StoreMessageInfo(mi)
|
ms.StoreMessageInfo(mi)
|
||||||
}
|
}
|
||||||
@ -727,7 +772,7 @@ func (x *GetAncestorPathRequest) String() string {
|
|||||||
func (*GetAncestorPathRequest) ProtoMessage() {}
|
func (*GetAncestorPathRequest) ProtoMessage() {}
|
||||||
|
|
||||||
func (x *GetAncestorPathRequest) ProtoReflect() protoreflect.Message {
|
func (x *GetAncestorPathRequest) ProtoReflect() protoreflect.Message {
|
||||||
mi := &file_rpc_category_proto_msgTypes[12]
|
mi := &file_rpc_category_proto_msgTypes[13]
|
||||||
if x != nil {
|
if x != nil {
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
if ms.LoadMessageInfo() == nil {
|
if ms.LoadMessageInfo() == nil {
|
||||||
@ -740,7 +785,7 @@ func (x *GetAncestorPathRequest) ProtoReflect() protoreflect.Message {
|
|||||||
|
|
||||||
// Deprecated: Use GetAncestorPathRequest.ProtoReflect.Descriptor instead.
|
// Deprecated: Use GetAncestorPathRequest.ProtoReflect.Descriptor instead.
|
||||||
func (*GetAncestorPathRequest) Descriptor() ([]byte, []int) {
|
func (*GetAncestorPathRequest) Descriptor() ([]byte, []int) {
|
||||||
return file_rpc_category_proto_rawDescGZIP(), []int{12}
|
return file_rpc_category_proto_rawDescGZIP(), []int{13}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *GetAncestorPathRequest) GetId() string {
|
func (x *GetAncestorPathRequest) GetId() string {
|
||||||
@ -760,7 +805,7 @@ type CategoryPathResponse struct {
|
|||||||
|
|
||||||
func (x *CategoryPathResponse) Reset() {
|
func (x *CategoryPathResponse) Reset() {
|
||||||
*x = CategoryPathResponse{}
|
*x = CategoryPathResponse{}
|
||||||
mi := &file_rpc_category_proto_msgTypes[13]
|
mi := &file_rpc_category_proto_msgTypes[14]
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
ms.StoreMessageInfo(mi)
|
ms.StoreMessageInfo(mi)
|
||||||
}
|
}
|
||||||
@ -772,7 +817,7 @@ func (x *CategoryPathResponse) String() string {
|
|||||||
func (*CategoryPathResponse) ProtoMessage() {}
|
func (*CategoryPathResponse) ProtoMessage() {}
|
||||||
|
|
||||||
func (x *CategoryPathResponse) ProtoReflect() protoreflect.Message {
|
func (x *CategoryPathResponse) ProtoReflect() protoreflect.Message {
|
||||||
mi := &file_rpc_category_proto_msgTypes[13]
|
mi := &file_rpc_category_proto_msgTypes[14]
|
||||||
if x != nil {
|
if x != nil {
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
if ms.LoadMessageInfo() == nil {
|
if ms.LoadMessageInfo() == nil {
|
||||||
@ -785,7 +830,7 @@ func (x *CategoryPathResponse) ProtoReflect() protoreflect.Message {
|
|||||||
|
|
||||||
// Deprecated: Use CategoryPathResponse.ProtoReflect.Descriptor instead.
|
// Deprecated: Use CategoryPathResponse.ProtoReflect.Descriptor instead.
|
||||||
func (*CategoryPathResponse) Descriptor() ([]byte, []int) {
|
func (*CategoryPathResponse) Descriptor() ([]byte, []int) {
|
||||||
return file_rpc_category_proto_rawDescGZIP(), []int{13}
|
return file_rpc_category_proto_rawDescGZIP(), []int{14}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *CategoryPathResponse) GetPath() []*CategoryInfo {
|
func (x *CategoryPathResponse) GetPath() []*CategoryInfo {
|
||||||
@ -805,7 +850,7 @@ type BatchCreateRequest struct {
|
|||||||
|
|
||||||
func (x *BatchCreateRequest) Reset() {
|
func (x *BatchCreateRequest) Reset() {
|
||||||
*x = BatchCreateRequest{}
|
*x = BatchCreateRequest{}
|
||||||
mi := &file_rpc_category_proto_msgTypes[14]
|
mi := &file_rpc_category_proto_msgTypes[15]
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
ms.StoreMessageInfo(mi)
|
ms.StoreMessageInfo(mi)
|
||||||
}
|
}
|
||||||
@ -817,7 +862,7 @@ func (x *BatchCreateRequest) String() string {
|
|||||||
func (*BatchCreateRequest) ProtoMessage() {}
|
func (*BatchCreateRequest) ProtoMessage() {}
|
||||||
|
|
||||||
func (x *BatchCreateRequest) ProtoReflect() protoreflect.Message {
|
func (x *BatchCreateRequest) ProtoReflect() protoreflect.Message {
|
||||||
mi := &file_rpc_category_proto_msgTypes[14]
|
mi := &file_rpc_category_proto_msgTypes[15]
|
||||||
if x != nil {
|
if x != nil {
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
if ms.LoadMessageInfo() == nil {
|
if ms.LoadMessageInfo() == nil {
|
||||||
@ -830,7 +875,7 @@ func (x *BatchCreateRequest) ProtoReflect() protoreflect.Message {
|
|||||||
|
|
||||||
// Deprecated: Use BatchCreateRequest.ProtoReflect.Descriptor instead.
|
// Deprecated: Use BatchCreateRequest.ProtoReflect.Descriptor instead.
|
||||||
func (*BatchCreateRequest) Descriptor() ([]byte, []int) {
|
func (*BatchCreateRequest) Descriptor() ([]byte, []int) {
|
||||||
return file_rpc_category_proto_rawDescGZIP(), []int{14}
|
return file_rpc_category_proto_rawDescGZIP(), []int{15}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *BatchCreateRequest) GetCategories() []*CreateCategoryRequest {
|
func (x *BatchCreateRequest) GetCategories() []*CreateCategoryRequest {
|
||||||
@ -851,7 +896,7 @@ type BatchCreateResponse struct {
|
|||||||
|
|
||||||
func (x *BatchCreateResponse) Reset() {
|
func (x *BatchCreateResponse) Reset() {
|
||||||
*x = BatchCreateResponse{}
|
*x = BatchCreateResponse{}
|
||||||
mi := &file_rpc_category_proto_msgTypes[15]
|
mi := &file_rpc_category_proto_msgTypes[16]
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
ms.StoreMessageInfo(mi)
|
ms.StoreMessageInfo(mi)
|
||||||
}
|
}
|
||||||
@ -863,7 +908,7 @@ func (x *BatchCreateResponse) String() string {
|
|||||||
func (*BatchCreateResponse) ProtoMessage() {}
|
func (*BatchCreateResponse) ProtoMessage() {}
|
||||||
|
|
||||||
func (x *BatchCreateResponse) ProtoReflect() protoreflect.Message {
|
func (x *BatchCreateResponse) ProtoReflect() protoreflect.Message {
|
||||||
mi := &file_rpc_category_proto_msgTypes[15]
|
mi := &file_rpc_category_proto_msgTypes[16]
|
||||||
if x != nil {
|
if x != nil {
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
if ms.LoadMessageInfo() == nil {
|
if ms.LoadMessageInfo() == nil {
|
||||||
@ -876,7 +921,7 @@ func (x *BatchCreateResponse) ProtoReflect() protoreflect.Message {
|
|||||||
|
|
||||||
// Deprecated: Use BatchCreateResponse.ProtoReflect.Descriptor instead.
|
// Deprecated: Use BatchCreateResponse.ProtoReflect.Descriptor instead.
|
||||||
func (*BatchCreateResponse) Descriptor() ([]byte, []int) {
|
func (*BatchCreateResponse) Descriptor() ([]byte, []int) {
|
||||||
return file_rpc_category_proto_rawDescGZIP(), []int{15}
|
return file_rpc_category_proto_rawDescGZIP(), []int{16}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *BatchCreateResponse) GetCreatedCategories() []*CategoryInfo {
|
func (x *BatchCreateResponse) GetCreatedCategories() []*CategoryInfo {
|
||||||
@ -909,7 +954,7 @@ type BatchUpdateRequest struct {
|
|||||||
|
|
||||||
func (x *BatchUpdateRequest) Reset() {
|
func (x *BatchUpdateRequest) Reset() {
|
||||||
*x = BatchUpdateRequest{}
|
*x = BatchUpdateRequest{}
|
||||||
mi := &file_rpc_category_proto_msgTypes[16]
|
mi := &file_rpc_category_proto_msgTypes[17]
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
ms.StoreMessageInfo(mi)
|
ms.StoreMessageInfo(mi)
|
||||||
}
|
}
|
||||||
@ -921,7 +966,7 @@ func (x *BatchUpdateRequest) String() string {
|
|||||||
func (*BatchUpdateRequest) ProtoMessage() {}
|
func (*BatchUpdateRequest) ProtoMessage() {}
|
||||||
|
|
||||||
func (x *BatchUpdateRequest) ProtoReflect() protoreflect.Message {
|
func (x *BatchUpdateRequest) ProtoReflect() protoreflect.Message {
|
||||||
mi := &file_rpc_category_proto_msgTypes[16]
|
mi := &file_rpc_category_proto_msgTypes[17]
|
||||||
if x != nil {
|
if x != nil {
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
if ms.LoadMessageInfo() == nil {
|
if ms.LoadMessageInfo() == nil {
|
||||||
@ -934,7 +979,7 @@ func (x *BatchUpdateRequest) ProtoReflect() protoreflect.Message {
|
|||||||
|
|
||||||
// Deprecated: Use BatchUpdateRequest.ProtoReflect.Descriptor instead.
|
// Deprecated: Use BatchUpdateRequest.ProtoReflect.Descriptor instead.
|
||||||
func (*BatchUpdateRequest) Descriptor() ([]byte, []int) {
|
func (*BatchUpdateRequest) Descriptor() ([]byte, []int) {
|
||||||
return file_rpc_category_proto_rawDescGZIP(), []int{16}
|
return file_rpc_category_proto_rawDescGZIP(), []int{17}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *BatchUpdateRequest) GetCategories() []*UpdateCategoryRequest {
|
func (x *BatchUpdateRequest) GetCategories() []*UpdateCategoryRequest {
|
||||||
@ -955,7 +1000,7 @@ type BatchUpdateResponse struct {
|
|||||||
|
|
||||||
func (x *BatchUpdateResponse) Reset() {
|
func (x *BatchUpdateResponse) Reset() {
|
||||||
*x = BatchUpdateResponse{}
|
*x = BatchUpdateResponse{}
|
||||||
mi := &file_rpc_category_proto_msgTypes[17]
|
mi := &file_rpc_category_proto_msgTypes[18]
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
ms.StoreMessageInfo(mi)
|
ms.StoreMessageInfo(mi)
|
||||||
}
|
}
|
||||||
@ -967,7 +1012,7 @@ func (x *BatchUpdateResponse) String() string {
|
|||||||
func (*BatchUpdateResponse) ProtoMessage() {}
|
func (*BatchUpdateResponse) ProtoMessage() {}
|
||||||
|
|
||||||
func (x *BatchUpdateResponse) ProtoReflect() protoreflect.Message {
|
func (x *BatchUpdateResponse) ProtoReflect() protoreflect.Message {
|
||||||
mi := &file_rpc_category_proto_msgTypes[17]
|
mi := &file_rpc_category_proto_msgTypes[18]
|
||||||
if x != nil {
|
if x != nil {
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
if ms.LoadMessageInfo() == nil {
|
if ms.LoadMessageInfo() == nil {
|
||||||
@ -980,7 +1025,7 @@ func (x *BatchUpdateResponse) ProtoReflect() protoreflect.Message {
|
|||||||
|
|
||||||
// Deprecated: Use BatchUpdateResponse.ProtoReflect.Descriptor instead.
|
// Deprecated: Use BatchUpdateResponse.ProtoReflect.Descriptor instead.
|
||||||
func (*BatchUpdateResponse) Descriptor() ([]byte, []int) {
|
func (*BatchUpdateResponse) Descriptor() ([]byte, []int) {
|
||||||
return file_rpc_category_proto_rawDescGZIP(), []int{17}
|
return file_rpc_category_proto_rawDescGZIP(), []int{18}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *BatchUpdateResponse) GetUpdatedCategories() []*CategoryInfo {
|
func (x *BatchUpdateResponse) GetUpdatedCategories() []*CategoryInfo {
|
||||||
@ -1019,7 +1064,7 @@ type ListCategoryRequest struct {
|
|||||||
|
|
||||||
func (x *ListCategoryRequest) Reset() {
|
func (x *ListCategoryRequest) Reset() {
|
||||||
*x = ListCategoryRequest{}
|
*x = ListCategoryRequest{}
|
||||||
mi := &file_rpc_category_proto_msgTypes[18]
|
mi := &file_rpc_category_proto_msgTypes[19]
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
ms.StoreMessageInfo(mi)
|
ms.StoreMessageInfo(mi)
|
||||||
}
|
}
|
||||||
@ -1031,7 +1076,7 @@ func (x *ListCategoryRequest) String() string {
|
|||||||
func (*ListCategoryRequest) ProtoMessage() {}
|
func (*ListCategoryRequest) ProtoMessage() {}
|
||||||
|
|
||||||
func (x *ListCategoryRequest) ProtoReflect() protoreflect.Message {
|
func (x *ListCategoryRequest) ProtoReflect() protoreflect.Message {
|
||||||
mi := &file_rpc_category_proto_msgTypes[18]
|
mi := &file_rpc_category_proto_msgTypes[19]
|
||||||
if x != nil {
|
if x != nil {
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
if ms.LoadMessageInfo() == nil {
|
if ms.LoadMessageInfo() == nil {
|
||||||
@ -1044,7 +1089,7 @@ func (x *ListCategoryRequest) ProtoReflect() protoreflect.Message {
|
|||||||
|
|
||||||
// Deprecated: Use ListCategoryRequest.ProtoReflect.Descriptor instead.
|
// Deprecated: Use ListCategoryRequest.ProtoReflect.Descriptor instead.
|
||||||
func (*ListCategoryRequest) Descriptor() ([]byte, []int) {
|
func (*ListCategoryRequest) Descriptor() ([]byte, []int) {
|
||||||
return file_rpc_category_proto_rawDescGZIP(), []int{18}
|
return file_rpc_category_proto_rawDescGZIP(), []int{19}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *ListCategoryRequest) GetSystemId() string {
|
func (x *ListCategoryRequest) GetSystemId() string {
|
||||||
@ -1100,7 +1145,7 @@ type CategoryListResponse struct {
|
|||||||
|
|
||||||
func (x *CategoryListResponse) Reset() {
|
func (x *CategoryListResponse) Reset() {
|
||||||
*x = CategoryListResponse{}
|
*x = CategoryListResponse{}
|
||||||
mi := &file_rpc_category_proto_msgTypes[19]
|
mi := &file_rpc_category_proto_msgTypes[20]
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
ms.StoreMessageInfo(mi)
|
ms.StoreMessageInfo(mi)
|
||||||
}
|
}
|
||||||
@ -1112,7 +1157,7 @@ func (x *CategoryListResponse) String() string {
|
|||||||
func (*CategoryListResponse) ProtoMessage() {}
|
func (*CategoryListResponse) ProtoMessage() {}
|
||||||
|
|
||||||
func (x *CategoryListResponse) ProtoReflect() protoreflect.Message {
|
func (x *CategoryListResponse) ProtoReflect() protoreflect.Message {
|
||||||
mi := &file_rpc_category_proto_msgTypes[19]
|
mi := &file_rpc_category_proto_msgTypes[20]
|
||||||
if x != nil {
|
if x != nil {
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
if ms.LoadMessageInfo() == nil {
|
if ms.LoadMessageInfo() == nil {
|
||||||
@ -1125,7 +1170,7 @@ func (x *CategoryListResponse) ProtoReflect() protoreflect.Message {
|
|||||||
|
|
||||||
// Deprecated: Use CategoryListResponse.ProtoReflect.Descriptor instead.
|
// Deprecated: Use CategoryListResponse.ProtoReflect.Descriptor instead.
|
||||||
func (*CategoryListResponse) Descriptor() ([]byte, []int) {
|
func (*CategoryListResponse) Descriptor() ([]byte, []int) {
|
||||||
return file_rpc_category_proto_rawDescGZIP(), []int{19}
|
return file_rpc_category_proto_rawDescGZIP(), []int{20}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *CategoryListResponse) GetCategories() []*CategoryInfo {
|
func (x *CategoryListResponse) GetCategories() []*CategoryInfo {
|
||||||
@ -1152,7 +1197,7 @@ type CategoryTreeResponse struct {
|
|||||||
|
|
||||||
func (x *CategoryTreeResponse) Reset() {
|
func (x *CategoryTreeResponse) Reset() {
|
||||||
*x = CategoryTreeResponse{}
|
*x = CategoryTreeResponse{}
|
||||||
mi := &file_rpc_category_proto_msgTypes[20]
|
mi := &file_rpc_category_proto_msgTypes[21]
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
ms.StoreMessageInfo(mi)
|
ms.StoreMessageInfo(mi)
|
||||||
}
|
}
|
||||||
@ -1164,7 +1209,7 @@ func (x *CategoryTreeResponse) String() string {
|
|||||||
func (*CategoryTreeResponse) ProtoMessage() {}
|
func (*CategoryTreeResponse) ProtoMessage() {}
|
||||||
|
|
||||||
func (x *CategoryTreeResponse) ProtoReflect() protoreflect.Message {
|
func (x *CategoryTreeResponse) ProtoReflect() protoreflect.Message {
|
||||||
mi := &file_rpc_category_proto_msgTypes[20]
|
mi := &file_rpc_category_proto_msgTypes[21]
|
||||||
if x != nil {
|
if x != nil {
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
if ms.LoadMessageInfo() == nil {
|
if ms.LoadMessageInfo() == nil {
|
||||||
@ -1177,7 +1222,7 @@ func (x *CategoryTreeResponse) ProtoReflect() protoreflect.Message {
|
|||||||
|
|
||||||
// Deprecated: Use CategoryTreeResponse.ProtoReflect.Descriptor instead.
|
// Deprecated: Use CategoryTreeResponse.ProtoReflect.Descriptor instead.
|
||||||
func (*CategoryTreeResponse) Descriptor() ([]byte, []int) {
|
func (*CategoryTreeResponse) Descriptor() ([]byte, []int) {
|
||||||
return file_rpc_category_proto_rawDescGZIP(), []int{20}
|
return file_rpc_category_proto_rawDescGZIP(), []int{21}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *CategoryTreeResponse) GetRoot() *CategoryTreeResponse_TreeNode {
|
func (x *CategoryTreeResponse) GetRoot() *CategoryTreeResponse_TreeNode {
|
||||||
@ -1199,7 +1244,7 @@ type CheckAliasRequest struct {
|
|||||||
|
|
||||||
func (x *CheckAliasRequest) Reset() {
|
func (x *CheckAliasRequest) Reset() {
|
||||||
*x = CheckAliasRequest{}
|
*x = CheckAliasRequest{}
|
||||||
mi := &file_rpc_category_proto_msgTypes[21]
|
mi := &file_rpc_category_proto_msgTypes[22]
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
ms.StoreMessageInfo(mi)
|
ms.StoreMessageInfo(mi)
|
||||||
}
|
}
|
||||||
@ -1211,7 +1256,7 @@ func (x *CheckAliasRequest) String() string {
|
|||||||
func (*CheckAliasRequest) ProtoMessage() {}
|
func (*CheckAliasRequest) ProtoMessage() {}
|
||||||
|
|
||||||
func (x *CheckAliasRequest) ProtoReflect() protoreflect.Message {
|
func (x *CheckAliasRequest) ProtoReflect() protoreflect.Message {
|
||||||
mi := &file_rpc_category_proto_msgTypes[21]
|
mi := &file_rpc_category_proto_msgTypes[22]
|
||||||
if x != nil {
|
if x != nil {
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
if ms.LoadMessageInfo() == nil {
|
if ms.LoadMessageInfo() == nil {
|
||||||
@ -1224,7 +1269,7 @@ func (x *CheckAliasRequest) ProtoReflect() protoreflect.Message {
|
|||||||
|
|
||||||
// Deprecated: Use CheckAliasRequest.ProtoReflect.Descriptor instead.
|
// Deprecated: Use CheckAliasRequest.ProtoReflect.Descriptor instead.
|
||||||
func (*CheckAliasRequest) Descriptor() ([]byte, []int) {
|
func (*CheckAliasRequest) Descriptor() ([]byte, []int) {
|
||||||
return file_rpc_category_proto_rawDescGZIP(), []int{21}
|
return file_rpc_category_proto_rawDescGZIP(), []int{22}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *CheckAliasRequest) GetSystemId() string {
|
func (x *CheckAliasRequest) GetSystemId() string {
|
||||||
@ -1259,7 +1304,7 @@ type CheckAliasResponse struct {
|
|||||||
|
|
||||||
func (x *CheckAliasResponse) Reset() {
|
func (x *CheckAliasResponse) Reset() {
|
||||||
*x = CheckAliasResponse{}
|
*x = CheckAliasResponse{}
|
||||||
mi := &file_rpc_category_proto_msgTypes[22]
|
mi := &file_rpc_category_proto_msgTypes[23]
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
ms.StoreMessageInfo(mi)
|
ms.StoreMessageInfo(mi)
|
||||||
}
|
}
|
||||||
@ -1271,7 +1316,7 @@ func (x *CheckAliasResponse) String() string {
|
|||||||
func (*CheckAliasResponse) ProtoMessage() {}
|
func (*CheckAliasResponse) ProtoMessage() {}
|
||||||
|
|
||||||
func (x *CheckAliasResponse) ProtoReflect() protoreflect.Message {
|
func (x *CheckAliasResponse) ProtoReflect() protoreflect.Message {
|
||||||
mi := &file_rpc_category_proto_msgTypes[22]
|
mi := &file_rpc_category_proto_msgTypes[23]
|
||||||
if x != nil {
|
if x != nil {
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
if ms.LoadMessageInfo() == nil {
|
if ms.LoadMessageInfo() == nil {
|
||||||
@ -1284,7 +1329,7 @@ func (x *CheckAliasResponse) ProtoReflect() protoreflect.Message {
|
|||||||
|
|
||||||
// Deprecated: Use CheckAliasResponse.ProtoReflect.Descriptor instead.
|
// Deprecated: Use CheckAliasResponse.ProtoReflect.Descriptor instead.
|
||||||
func (*CheckAliasResponse) Descriptor() ([]byte, []int) {
|
func (*CheckAliasResponse) Descriptor() ([]byte, []int) {
|
||||||
return file_rpc_category_proto_rawDescGZIP(), []int{22}
|
return file_rpc_category_proto_rawDescGZIP(), []int{23}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *CheckAliasResponse) GetIsAvailable() bool {
|
func (x *CheckAliasResponse) GetIsAvailable() bool {
|
||||||
@ -1301,6 +1346,150 @@ func (x *CheckAliasResponse) GetExistingId() string {
|
|||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type GetSystemCategoriesRequest struct {
|
||||||
|
state protoimpl.MessageState `protogen:"open.v1"`
|
||||||
|
SystemId string `protobuf:"bytes,1,opt,name=system_id,json=systemId,proto3" json:"system_id,omitempty"` // 系统标识 (必需)
|
||||||
|
ParentId string `protobuf:"bytes,2,opt,name=parent_id,json=parentId,proto3" json:"parent_id,omitempty"` // 父分类ID (可选)
|
||||||
|
Page int32 `protobuf:"varint,3,opt,name=page,proto3" json:"page,omitempty"` // 分页参数
|
||||||
|
PageSize int32 `protobuf:"varint,4,opt,name=page_size,json=pageSize,proto3" json:"page_size,omitempty"` // 分页参数
|
||||||
|
IncludeDescendants bool `protobuf:"varint,5,opt,name=include_descendants,json=includeDescendants,proto3" json:"include_descendants,omitempty"` // 是否包含后代
|
||||||
|
unknownFields protoimpl.UnknownFields
|
||||||
|
sizeCache protoimpl.SizeCache
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *GetSystemCategoriesRequest) Reset() {
|
||||||
|
*x = GetSystemCategoriesRequest{}
|
||||||
|
mi := &file_rpc_category_proto_msgTypes[24]
|
||||||
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
|
ms.StoreMessageInfo(mi)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *GetSystemCategoriesRequest) String() string {
|
||||||
|
return protoimpl.X.MessageStringOf(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (*GetSystemCategoriesRequest) ProtoMessage() {}
|
||||||
|
|
||||||
|
func (x *GetSystemCategoriesRequest) ProtoReflect() protoreflect.Message {
|
||||||
|
mi := &file_rpc_category_proto_msgTypes[24]
|
||||||
|
if x != nil {
|
||||||
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
|
if ms.LoadMessageInfo() == nil {
|
||||||
|
ms.StoreMessageInfo(mi)
|
||||||
|
}
|
||||||
|
return ms
|
||||||
|
}
|
||||||
|
return mi.MessageOf(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Deprecated: Use GetSystemCategoriesRequest.ProtoReflect.Descriptor instead.
|
||||||
|
func (*GetSystemCategoriesRequest) Descriptor() ([]byte, []int) {
|
||||||
|
return file_rpc_category_proto_rawDescGZIP(), []int{24}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *GetSystemCategoriesRequest) GetSystemId() string {
|
||||||
|
if x != nil {
|
||||||
|
return x.SystemId
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *GetSystemCategoriesRequest) GetParentId() string {
|
||||||
|
if x != nil {
|
||||||
|
return x.ParentId
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *GetSystemCategoriesRequest) GetPage() int32 {
|
||||||
|
if x != nil {
|
||||||
|
return x.Page
|
||||||
|
}
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *GetSystemCategoriesRequest) GetPageSize() int32 {
|
||||||
|
if x != nil {
|
||||||
|
return x.PageSize
|
||||||
|
}
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *GetSystemCategoriesRequest) GetIncludeDescendants() bool {
|
||||||
|
if x != nil {
|
||||||
|
return x.IncludeDescendants
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
type GetSystemCategoriesResponse struct {
|
||||||
|
state protoimpl.MessageState `protogen:"open.v1"`
|
||||||
|
Categories []*CategoryInfo `protobuf:"bytes,1,rep,name=categories,proto3" json:"categories,omitempty"`
|
||||||
|
Total int64 `protobuf:"varint,2,opt,name=total,proto3" json:"total,omitempty"`
|
||||||
|
CurrentPage int32 `protobuf:"varint,3,opt,name=current_page,json=currentPage,proto3" json:"current_page,omitempty"`
|
||||||
|
PageSize int32 `protobuf:"varint,4,opt,name=page_size,json=pageSize,proto3" json:"page_size,omitempty"`
|
||||||
|
unknownFields protoimpl.UnknownFields
|
||||||
|
sizeCache protoimpl.SizeCache
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *GetSystemCategoriesResponse) Reset() {
|
||||||
|
*x = GetSystemCategoriesResponse{}
|
||||||
|
mi := &file_rpc_category_proto_msgTypes[25]
|
||||||
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
|
ms.StoreMessageInfo(mi)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *GetSystemCategoriesResponse) String() string {
|
||||||
|
return protoimpl.X.MessageStringOf(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (*GetSystemCategoriesResponse) ProtoMessage() {}
|
||||||
|
|
||||||
|
func (x *GetSystemCategoriesResponse) ProtoReflect() protoreflect.Message {
|
||||||
|
mi := &file_rpc_category_proto_msgTypes[25]
|
||||||
|
if x != nil {
|
||||||
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
|
if ms.LoadMessageInfo() == nil {
|
||||||
|
ms.StoreMessageInfo(mi)
|
||||||
|
}
|
||||||
|
return ms
|
||||||
|
}
|
||||||
|
return mi.MessageOf(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Deprecated: Use GetSystemCategoriesResponse.ProtoReflect.Descriptor instead.
|
||||||
|
func (*GetSystemCategoriesResponse) Descriptor() ([]byte, []int) {
|
||||||
|
return file_rpc_category_proto_rawDescGZIP(), []int{25}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *GetSystemCategoriesResponse) GetCategories() []*CategoryInfo {
|
||||||
|
if x != nil {
|
||||||
|
return x.Categories
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *GetSystemCategoriesResponse) GetTotal() int64 {
|
||||||
|
if x != nil {
|
||||||
|
return x.Total
|
||||||
|
}
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *GetSystemCategoriesResponse) GetCurrentPage() int32 {
|
||||||
|
if x != nil {
|
||||||
|
return x.CurrentPage
|
||||||
|
}
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *GetSystemCategoriesResponse) GetPageSize() int32 {
|
||||||
|
if x != nil {
|
||||||
|
return x.PageSize
|
||||||
|
}
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
type CategoryTreeResponse_TreeNode struct {
|
type CategoryTreeResponse_TreeNode struct {
|
||||||
state protoimpl.MessageState `protogen:"open.v1"`
|
state protoimpl.MessageState `protogen:"open.v1"`
|
||||||
Category *CategoryInfo `protobuf:"bytes,1,opt,name=category,proto3" json:"category,omitempty"`
|
Category *CategoryInfo `protobuf:"bytes,1,opt,name=category,proto3" json:"category,omitempty"`
|
||||||
@ -1311,7 +1500,7 @@ type CategoryTreeResponse_TreeNode struct {
|
|||||||
|
|
||||||
func (x *CategoryTreeResponse_TreeNode) Reset() {
|
func (x *CategoryTreeResponse_TreeNode) Reset() {
|
||||||
*x = CategoryTreeResponse_TreeNode{}
|
*x = CategoryTreeResponse_TreeNode{}
|
||||||
mi := &file_rpc_category_proto_msgTypes[23]
|
mi := &file_rpc_category_proto_msgTypes[26]
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
ms.StoreMessageInfo(mi)
|
ms.StoreMessageInfo(mi)
|
||||||
}
|
}
|
||||||
@ -1323,7 +1512,7 @@ func (x *CategoryTreeResponse_TreeNode) String() string {
|
|||||||
func (*CategoryTreeResponse_TreeNode) ProtoMessage() {}
|
func (*CategoryTreeResponse_TreeNode) ProtoMessage() {}
|
||||||
|
|
||||||
func (x *CategoryTreeResponse_TreeNode) ProtoReflect() protoreflect.Message {
|
func (x *CategoryTreeResponse_TreeNode) ProtoReflect() protoreflect.Message {
|
||||||
mi := &file_rpc_category_proto_msgTypes[23]
|
mi := &file_rpc_category_proto_msgTypes[26]
|
||||||
if x != nil {
|
if x != nil {
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
if ms.LoadMessageInfo() == nil {
|
if ms.LoadMessageInfo() == nil {
|
||||||
@ -1336,7 +1525,7 @@ func (x *CategoryTreeResponse_TreeNode) ProtoReflect() protoreflect.Message {
|
|||||||
|
|
||||||
// Deprecated: Use CategoryTreeResponse_TreeNode.ProtoReflect.Descriptor instead.
|
// Deprecated: Use CategoryTreeResponse_TreeNode.ProtoReflect.Descriptor instead.
|
||||||
func (*CategoryTreeResponse_TreeNode) Descriptor() ([]byte, []int) {
|
func (*CategoryTreeResponse_TreeNode) Descriptor() ([]byte, []int) {
|
||||||
return file_rpc_category_proto_rawDescGZIP(), []int{20, 0}
|
return file_rpc_category_proto_rawDescGZIP(), []int{21, 0}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *CategoryTreeResponse_TreeNode) GetCategory() *CategoryInfo {
|
func (x *CategoryTreeResponse_TreeNode) GetCategory() *CategoryInfo {
|
||||||
@ -1390,7 +1579,9 @@ const file_rpc_category_proto_rawDesc = "" +
|
|||||||
"\x0eDeleteResponse\x12\x18\n" +
|
"\x0eDeleteResponse\x12\x18\n" +
|
||||||
"\asuccess\x18\x01 \x01(\bR\asuccess\"$\n" +
|
"\asuccess\x18\x01 \x01(\bR\asuccess\"$\n" +
|
||||||
"\x12GetCategoryRequest\x12\x0e\n" +
|
"\x12GetCategoryRequest\x12\x0e\n" +
|
||||||
"\x02id\x18\x01 \x01(\tR\x02id\"J\n" +
|
"\x02id\x18\x01 \x01(\tR\x02id\"I\n" +
|
||||||
|
"\x19GetFullCategoriesResponse\x12,\n" +
|
||||||
|
"\x12full_category_name\x18\x01 \x01(\tR\x10fullCategoryName\"J\n" +
|
||||||
"\x14CategoryInfoResponse\x122\n" +
|
"\x14CategoryInfoResponse\x122\n" +
|
||||||
"\bcategory\x18\x01 \x01(\v2\x16.category.CategoryInfoR\bcategory\"O\n" +
|
"\bcategory\x18\x01 \x01(\v2\x16.category.CategoryInfoR\bcategory\"O\n" +
|
||||||
"\x12GetChildrenRequest\x12\x1b\n" +
|
"\x12GetChildrenRequest\x12\x1b\n" +
|
||||||
@ -1448,7 +1639,20 @@ const file_rpc_category_proto_rawDesc = "" +
|
|||||||
"\x12CheckAliasResponse\x12!\n" +
|
"\x12CheckAliasResponse\x12!\n" +
|
||||||
"\fis_available\x18\x01 \x01(\bR\visAvailable\x12\x1f\n" +
|
"\fis_available\x18\x01 \x01(\bR\visAvailable\x12\x1f\n" +
|
||||||
"\vexisting_id\x18\x02 \x01(\tR\n" +
|
"\vexisting_id\x18\x02 \x01(\tR\n" +
|
||||||
"existingId2\xfd\a\n" +
|
"existingId\"\xb8\x01\n" +
|
||||||
|
"\x1aGetSystemCategoriesRequest\x12\x1b\n" +
|
||||||
|
"\tsystem_id\x18\x01 \x01(\tR\bsystemId\x12\x1b\n" +
|
||||||
|
"\tparent_id\x18\x02 \x01(\tR\bparentId\x12\x12\n" +
|
||||||
|
"\x04page\x18\x03 \x01(\x05R\x04page\x12\x1b\n" +
|
||||||
|
"\tpage_size\x18\x04 \x01(\x05R\bpageSize\x12/\n" +
|
||||||
|
"\x13include_descendants\x18\x05 \x01(\bR\x12includeDescendants\"\xab\x01\n" +
|
||||||
|
"\x1bGetSystemCategoriesResponse\x126\n" +
|
||||||
|
"\n" +
|
||||||
|
"categories\x18\x01 \x03(\v2\x16.category.CategoryInfoR\n" +
|
||||||
|
"categories\x12\x14\n" +
|
||||||
|
"\x05total\x18\x02 \x01(\x03R\x05total\x12!\n" +
|
||||||
|
"\fcurrent_page\x18\x03 \x01(\x05R\vcurrentPage\x12\x1b\n" +
|
||||||
|
"\tpage_size\x18\x04 \x01(\x05R\bpageSize2\xb9\t\n" +
|
||||||
"\bCategory\x125\n" +
|
"\bCategory\x125\n" +
|
||||||
"\x04Ping\x12\x15.category.PingRequest\x1a\x16.category.PingResponse\x12Q\n" +
|
"\x04Ping\x12\x15.category.PingRequest\x1a\x16.category.PingResponse\x12Q\n" +
|
||||||
"\x0eCreateCategory\x12\x1f.category.CreateCategoryRequest\x1a\x1e.category.CategoryInfoResponse\x12Q\n" +
|
"\x0eCreateCategory\x12\x1f.category.CreateCategoryRequest\x1a\x1e.category.CategoryInfoResponse\x12Q\n" +
|
||||||
@ -1463,7 +1667,9 @@ const file_rpc_category_proto_rawDesc = "" +
|
|||||||
"\x15BatchUpdateCategories\x12\x1c.category.BatchUpdateRequest\x1a\x1d.category.BatchUpdateResponse\x12O\n" +
|
"\x15BatchUpdateCategories\x12\x1c.category.BatchUpdateRequest\x1a\x1d.category.BatchUpdateResponse\x12O\n" +
|
||||||
"\x0eListCategories\x12\x1d.category.ListCategoryRequest\x1a\x1e.category.CategoryListResponse\x12G\n" +
|
"\x0eListCategories\x12\x1d.category.ListCategoryRequest\x1a\x1e.category.CategoryListResponse\x12G\n" +
|
||||||
"\n" +
|
"\n" +
|
||||||
"CheckAlias\x12\x1b.category.CheckAliasRequest\x1a\x1c.category.CheckAliasResponseB\fZ\n" +
|
"CheckAlias\x12\x1b.category.CheckAliasRequest\x1a\x1c.category.CheckAliasResponse\x12b\n" +
|
||||||
|
"\x13GetSystemCategories\x12$.category.GetSystemCategoriesRequest\x1a%.category.GetSystemCategoriesResponse\x12V\n" +
|
||||||
|
"\x11GetFullCategories\x12\x1c.category.GetCategoryRequest\x1a#.category.GetFullCategoriesResponseB\fZ\n" +
|
||||||
"./categoryb\x06proto3"
|
"./categoryb\x06proto3"
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@ -1478,7 +1684,7 @@ func file_rpc_category_proto_rawDescGZIP() []byte {
|
|||||||
return file_rpc_category_proto_rawDescData
|
return file_rpc_category_proto_rawDescData
|
||||||
}
|
}
|
||||||
|
|
||||||
var file_rpc_category_proto_msgTypes = make([]protoimpl.MessageInfo, 24)
|
var file_rpc_category_proto_msgTypes = make([]protoimpl.MessageInfo, 27)
|
||||||
var file_rpc_category_proto_goTypes = []any{
|
var file_rpc_category_proto_goTypes = []any{
|
||||||
(*PingRequest)(nil), // 0: category.PingRequest
|
(*PingRequest)(nil), // 0: category.PingRequest
|
||||||
(*PingResponse)(nil), // 1: category.PingResponse
|
(*PingResponse)(nil), // 1: category.PingResponse
|
||||||
@ -1488,22 +1694,25 @@ var file_rpc_category_proto_goTypes = []any{
|
|||||||
(*DeleteCategoryRequest)(nil), // 5: category.DeleteCategoryRequest
|
(*DeleteCategoryRequest)(nil), // 5: category.DeleteCategoryRequest
|
||||||
(*DeleteResponse)(nil), // 6: category.DeleteResponse
|
(*DeleteResponse)(nil), // 6: category.DeleteResponse
|
||||||
(*GetCategoryRequest)(nil), // 7: category.GetCategoryRequest
|
(*GetCategoryRequest)(nil), // 7: category.GetCategoryRequest
|
||||||
(*CategoryInfoResponse)(nil), // 8: category.CategoryInfoResponse
|
(*GetFullCategoriesResponse)(nil), // 8: category.GetFullCategoriesResponse
|
||||||
(*GetChildrenRequest)(nil), // 9: category.GetChildrenRequest
|
(*CategoryInfoResponse)(nil), // 9: category.CategoryInfoResponse
|
||||||
(*GetTreeRequest)(nil), // 10: category.GetTreeRequest
|
(*GetChildrenRequest)(nil), // 10: category.GetChildrenRequest
|
||||||
(*MoveCategoryRequest)(nil), // 11: category.MoveCategoryRequest
|
(*GetTreeRequest)(nil), // 11: category.GetTreeRequest
|
||||||
(*GetAncestorPathRequest)(nil), // 12: category.GetAncestorPathRequest
|
(*MoveCategoryRequest)(nil), // 12: category.MoveCategoryRequest
|
||||||
(*CategoryPathResponse)(nil), // 13: category.CategoryPathResponse
|
(*GetAncestorPathRequest)(nil), // 13: category.GetAncestorPathRequest
|
||||||
(*BatchCreateRequest)(nil), // 14: category.BatchCreateRequest
|
(*CategoryPathResponse)(nil), // 14: category.CategoryPathResponse
|
||||||
(*BatchCreateResponse)(nil), // 15: category.BatchCreateResponse
|
(*BatchCreateRequest)(nil), // 15: category.BatchCreateRequest
|
||||||
(*BatchUpdateRequest)(nil), // 16: category.BatchUpdateRequest
|
(*BatchCreateResponse)(nil), // 16: category.BatchCreateResponse
|
||||||
(*BatchUpdateResponse)(nil), // 17: category.BatchUpdateResponse
|
(*BatchUpdateRequest)(nil), // 17: category.BatchUpdateRequest
|
||||||
(*ListCategoryRequest)(nil), // 18: category.ListCategoryRequest
|
(*BatchUpdateResponse)(nil), // 18: category.BatchUpdateResponse
|
||||||
(*CategoryListResponse)(nil), // 19: category.CategoryListResponse
|
(*ListCategoryRequest)(nil), // 19: category.ListCategoryRequest
|
||||||
(*CategoryTreeResponse)(nil), // 20: category.CategoryTreeResponse
|
(*CategoryListResponse)(nil), // 20: category.CategoryListResponse
|
||||||
(*CheckAliasRequest)(nil), // 21: category.CheckAliasRequest
|
(*CategoryTreeResponse)(nil), // 21: category.CategoryTreeResponse
|
||||||
(*CheckAliasResponse)(nil), // 22: category.CheckAliasResponse
|
(*CheckAliasRequest)(nil), // 22: category.CheckAliasRequest
|
||||||
(*CategoryTreeResponse_TreeNode)(nil), // 23: category.CategoryTreeResponse.TreeNode
|
(*CheckAliasResponse)(nil), // 23: category.CheckAliasResponse
|
||||||
|
(*GetSystemCategoriesRequest)(nil), // 24: category.GetSystemCategoriesRequest
|
||||||
|
(*GetSystemCategoriesResponse)(nil), // 25: category.GetSystemCategoriesResponse
|
||||||
|
(*CategoryTreeResponse_TreeNode)(nil), // 26: category.CategoryTreeResponse.TreeNode
|
||||||
}
|
}
|
||||||
var file_rpc_category_proto_depIdxs = []int32{
|
var file_rpc_category_proto_depIdxs = []int32{
|
||||||
2, // 0: category.CategoryInfoResponse.category:type_name -> category.CategoryInfo
|
2, // 0: category.CategoryInfoResponse.category:type_name -> category.CategoryInfo
|
||||||
@ -1513,40 +1722,45 @@ var file_rpc_category_proto_depIdxs = []int32{
|
|||||||
4, // 4: category.BatchUpdateRequest.categories:type_name -> category.UpdateCategoryRequest
|
4, // 4: category.BatchUpdateRequest.categories:type_name -> category.UpdateCategoryRequest
|
||||||
2, // 5: category.BatchUpdateResponse.updated_categories:type_name -> category.CategoryInfo
|
2, // 5: category.BatchUpdateResponse.updated_categories:type_name -> category.CategoryInfo
|
||||||
2, // 6: category.CategoryListResponse.categories:type_name -> category.CategoryInfo
|
2, // 6: category.CategoryListResponse.categories:type_name -> category.CategoryInfo
|
||||||
23, // 7: category.CategoryTreeResponse.root:type_name -> category.CategoryTreeResponse.TreeNode
|
26, // 7: category.CategoryTreeResponse.root:type_name -> category.CategoryTreeResponse.TreeNode
|
||||||
2, // 8: category.CategoryTreeResponse.TreeNode.category:type_name -> category.CategoryInfo
|
2, // 8: category.GetSystemCategoriesResponse.categories:type_name -> category.CategoryInfo
|
||||||
23, // 9: category.CategoryTreeResponse.TreeNode.children:type_name -> category.CategoryTreeResponse.TreeNode
|
2, // 9: category.CategoryTreeResponse.TreeNode.category:type_name -> category.CategoryInfo
|
||||||
0, // 10: category.Category.Ping:input_type -> category.PingRequest
|
26, // 10: category.CategoryTreeResponse.TreeNode.children:type_name -> category.CategoryTreeResponse.TreeNode
|
||||||
3, // 11: category.Category.CreateCategory:input_type -> category.CreateCategoryRequest
|
0, // 11: category.Category.Ping:input_type -> category.PingRequest
|
||||||
4, // 12: category.Category.UpdateCategory:input_type -> category.UpdateCategoryRequest
|
3, // 12: category.Category.CreateCategory:input_type -> category.CreateCategoryRequest
|
||||||
5, // 13: category.Category.DeleteCategory:input_type -> category.DeleteCategoryRequest
|
4, // 13: category.Category.UpdateCategory:input_type -> category.UpdateCategoryRequest
|
||||||
7, // 14: category.Category.GetCategory:input_type -> category.GetCategoryRequest
|
5, // 14: category.Category.DeleteCategory:input_type -> category.DeleteCategoryRequest
|
||||||
9, // 15: category.Category.GetChildren:input_type -> category.GetChildrenRequest
|
7, // 15: category.Category.GetCategory:input_type -> category.GetCategoryRequest
|
||||||
10, // 16: category.Category.GetTree:input_type -> category.GetTreeRequest
|
10, // 16: category.Category.GetChildren:input_type -> category.GetChildrenRequest
|
||||||
11, // 17: category.Category.MoveCategory:input_type -> category.MoveCategoryRequest
|
11, // 17: category.Category.GetTree:input_type -> category.GetTreeRequest
|
||||||
12, // 18: category.Category.GetAncestorPath:input_type -> category.GetAncestorPathRequest
|
12, // 18: category.Category.MoveCategory:input_type -> category.MoveCategoryRequest
|
||||||
14, // 19: category.Category.BatchCreateCategories:input_type -> category.BatchCreateRequest
|
13, // 19: category.Category.GetAncestorPath:input_type -> category.GetAncestorPathRequest
|
||||||
16, // 20: category.Category.BatchUpdateCategories:input_type -> category.BatchUpdateRequest
|
15, // 20: category.Category.BatchCreateCategories:input_type -> category.BatchCreateRequest
|
||||||
18, // 21: category.Category.ListCategories:input_type -> category.ListCategoryRequest
|
17, // 21: category.Category.BatchUpdateCategories:input_type -> category.BatchUpdateRequest
|
||||||
21, // 22: category.Category.CheckAlias:input_type -> category.CheckAliasRequest
|
19, // 22: category.Category.ListCategories:input_type -> category.ListCategoryRequest
|
||||||
1, // 23: category.Category.Ping:output_type -> category.PingResponse
|
22, // 23: category.Category.CheckAlias:input_type -> category.CheckAliasRequest
|
||||||
8, // 24: category.Category.CreateCategory:output_type -> category.CategoryInfoResponse
|
24, // 24: category.Category.GetSystemCategories:input_type -> category.GetSystemCategoriesRequest
|
||||||
8, // 25: category.Category.UpdateCategory:output_type -> category.CategoryInfoResponse
|
7, // 25: category.Category.GetFullCategories:input_type -> category.GetCategoryRequest
|
||||||
6, // 26: category.Category.DeleteCategory:output_type -> category.DeleteResponse
|
1, // 26: category.Category.Ping:output_type -> category.PingResponse
|
||||||
8, // 27: category.Category.GetCategory:output_type -> category.CategoryInfoResponse
|
9, // 27: category.Category.CreateCategory:output_type -> category.CategoryInfoResponse
|
||||||
19, // 28: category.Category.GetChildren:output_type -> category.CategoryListResponse
|
9, // 28: category.Category.UpdateCategory:output_type -> category.CategoryInfoResponse
|
||||||
20, // 29: category.Category.GetTree:output_type -> category.CategoryTreeResponse
|
6, // 29: category.Category.DeleteCategory:output_type -> category.DeleteResponse
|
||||||
8, // 30: category.Category.MoveCategory:output_type -> category.CategoryInfoResponse
|
9, // 30: category.Category.GetCategory:output_type -> category.CategoryInfoResponse
|
||||||
13, // 31: category.Category.GetAncestorPath:output_type -> category.CategoryPathResponse
|
20, // 31: category.Category.GetChildren:output_type -> category.CategoryListResponse
|
||||||
15, // 32: category.Category.BatchCreateCategories:output_type -> category.BatchCreateResponse
|
21, // 32: category.Category.GetTree:output_type -> category.CategoryTreeResponse
|
||||||
17, // 33: category.Category.BatchUpdateCategories:output_type -> category.BatchUpdateResponse
|
9, // 33: category.Category.MoveCategory:output_type -> category.CategoryInfoResponse
|
||||||
19, // 34: category.Category.ListCategories:output_type -> category.CategoryListResponse
|
14, // 34: category.Category.GetAncestorPath:output_type -> category.CategoryPathResponse
|
||||||
22, // 35: category.Category.CheckAlias:output_type -> category.CheckAliasResponse
|
16, // 35: category.Category.BatchCreateCategories:output_type -> category.BatchCreateResponse
|
||||||
23, // [23:36] is the sub-list for method output_type
|
18, // 36: category.Category.BatchUpdateCategories:output_type -> category.BatchUpdateResponse
|
||||||
10, // [10:23] is the sub-list for method input_type
|
20, // 37: category.Category.ListCategories:output_type -> category.CategoryListResponse
|
||||||
10, // [10:10] is the sub-list for extension type_name
|
23, // 38: category.Category.CheckAlias:output_type -> category.CheckAliasResponse
|
||||||
10, // [10:10] is the sub-list for extension extendee
|
25, // 39: category.Category.GetSystemCategories:output_type -> category.GetSystemCategoriesResponse
|
||||||
0, // [0:10] is the sub-list for field type_name
|
8, // 40: category.Category.GetFullCategories:output_type -> category.GetFullCategoriesResponse
|
||||||
|
26, // [26:41] is the sub-list for method output_type
|
||||||
|
11, // [11:26] is the sub-list for method input_type
|
||||||
|
11, // [11:11] is the sub-list for extension type_name
|
||||||
|
11, // [11:11] is the sub-list for extension extendee
|
||||||
|
0, // [0:11] is the sub-list for field type_name
|
||||||
}
|
}
|
||||||
|
|
||||||
func init() { file_rpc_category_proto_init() }
|
func init() { file_rpc_category_proto_init() }
|
||||||
@ -1560,7 +1774,7 @@ func file_rpc_category_proto_init() {
|
|||||||
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
|
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
|
||||||
RawDescriptor: unsafe.Slice(unsafe.StringData(file_rpc_category_proto_rawDesc), len(file_rpc_category_proto_rawDesc)),
|
RawDescriptor: unsafe.Slice(unsafe.StringData(file_rpc_category_proto_rawDesc), len(file_rpc_category_proto_rawDesc)),
|
||||||
NumEnums: 0,
|
NumEnums: 0,
|
||||||
NumMessages: 24,
|
NumMessages: 27,
|
||||||
NumExtensions: 0,
|
NumExtensions: 0,
|
||||||
NumServices: 1,
|
NumServices: 1,
|
||||||
},
|
},
|
||||||
|
|||||||
@ -32,6 +32,8 @@ const (
|
|||||||
Category_BatchUpdateCategories_FullMethodName = "/category.Category/BatchUpdateCategories"
|
Category_BatchUpdateCategories_FullMethodName = "/category.Category/BatchUpdateCategories"
|
||||||
Category_ListCategories_FullMethodName = "/category.Category/ListCategories"
|
Category_ListCategories_FullMethodName = "/category.Category/ListCategories"
|
||||||
Category_CheckAlias_FullMethodName = "/category.Category/CheckAlias"
|
Category_CheckAlias_FullMethodName = "/category.Category/CheckAlias"
|
||||||
|
Category_GetSystemCategories_FullMethodName = "/category.Category/GetSystemCategories"
|
||||||
|
Category_GetFullCategories_FullMethodName = "/category.Category/GetFullCategories"
|
||||||
)
|
)
|
||||||
|
|
||||||
// CategoryClient is the client API for Category service.
|
// CategoryClient is the client API for Category service.
|
||||||
@ -58,6 +60,10 @@ type CategoryClient interface {
|
|||||||
// 查询过滤
|
// 查询过滤
|
||||||
ListCategories(ctx context.Context, in *ListCategoryRequest, opts ...grpc.CallOption) (*CategoryListResponse, error)
|
ListCategories(ctx context.Context, in *ListCategoryRequest, opts ...grpc.CallOption) (*CategoryListResponse, error)
|
||||||
CheckAlias(ctx context.Context, in *CheckAliasRequest, opts ...grpc.CallOption) (*CheckAliasResponse, error)
|
CheckAlias(ctx context.Context, in *CheckAliasRequest, opts ...grpc.CallOption) (*CheckAliasResponse, error)
|
||||||
|
// 根据系统ID获取分类
|
||||||
|
GetSystemCategories(ctx context.Context, in *GetSystemCategoriesRequest, opts ...grpc.CallOption) (*GetSystemCategoriesResponse, error)
|
||||||
|
// 获取某一个类别的完整类别(从根类别到当前类别的所有类别)
|
||||||
|
GetFullCategories(ctx context.Context, in *GetCategoryRequest, opts ...grpc.CallOption) (*GetFullCategoriesResponse, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
type categoryClient struct {
|
type categoryClient struct {
|
||||||
@ -198,6 +204,26 @@ func (c *categoryClient) CheckAlias(ctx context.Context, in *CheckAliasRequest,
|
|||||||
return out, nil
|
return out, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *categoryClient) GetSystemCategories(ctx context.Context, in *GetSystemCategoriesRequest, opts ...grpc.CallOption) (*GetSystemCategoriesResponse, error) {
|
||||||
|
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
|
||||||
|
out := new(GetSystemCategoriesResponse)
|
||||||
|
err := c.cc.Invoke(ctx, Category_GetSystemCategories_FullMethodName, in, out, cOpts...)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return out, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *categoryClient) GetFullCategories(ctx context.Context, in *GetCategoryRequest, opts ...grpc.CallOption) (*GetFullCategoriesResponse, error) {
|
||||||
|
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
|
||||||
|
out := new(GetFullCategoriesResponse)
|
||||||
|
err := c.cc.Invoke(ctx, Category_GetFullCategories_FullMethodName, in, out, cOpts...)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return out, nil
|
||||||
|
}
|
||||||
|
|
||||||
// CategoryServer is the server API for Category service.
|
// CategoryServer is the server API for Category service.
|
||||||
// All implementations must embed UnimplementedCategoryServer
|
// All implementations must embed UnimplementedCategoryServer
|
||||||
// for forward compatibility.
|
// for forward compatibility.
|
||||||
@ -222,6 +248,10 @@ type CategoryServer interface {
|
|||||||
// 查询过滤
|
// 查询过滤
|
||||||
ListCategories(context.Context, *ListCategoryRequest) (*CategoryListResponse, error)
|
ListCategories(context.Context, *ListCategoryRequest) (*CategoryListResponse, error)
|
||||||
CheckAlias(context.Context, *CheckAliasRequest) (*CheckAliasResponse, error)
|
CheckAlias(context.Context, *CheckAliasRequest) (*CheckAliasResponse, error)
|
||||||
|
// 根据系统ID获取分类
|
||||||
|
GetSystemCategories(context.Context, *GetSystemCategoriesRequest) (*GetSystemCategoriesResponse, error)
|
||||||
|
// 获取某一个类别的完整类别(从根类别到当前类别的所有类别)
|
||||||
|
GetFullCategories(context.Context, *GetCategoryRequest) (*GetFullCategoriesResponse, error)
|
||||||
mustEmbedUnimplementedCategoryServer()
|
mustEmbedUnimplementedCategoryServer()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -271,6 +301,12 @@ func (UnimplementedCategoryServer) ListCategories(context.Context, *ListCategory
|
|||||||
func (UnimplementedCategoryServer) CheckAlias(context.Context, *CheckAliasRequest) (*CheckAliasResponse, error) {
|
func (UnimplementedCategoryServer) CheckAlias(context.Context, *CheckAliasRequest) (*CheckAliasResponse, error) {
|
||||||
return nil, status.Errorf(codes.Unimplemented, "method CheckAlias not implemented")
|
return nil, status.Errorf(codes.Unimplemented, "method CheckAlias not implemented")
|
||||||
}
|
}
|
||||||
|
func (UnimplementedCategoryServer) GetSystemCategories(context.Context, *GetSystemCategoriesRequest) (*GetSystemCategoriesResponse, error) {
|
||||||
|
return nil, status.Errorf(codes.Unimplemented, "method GetSystemCategories not implemented")
|
||||||
|
}
|
||||||
|
func (UnimplementedCategoryServer) GetFullCategories(context.Context, *GetCategoryRequest) (*GetFullCategoriesResponse, error) {
|
||||||
|
return nil, status.Errorf(codes.Unimplemented, "method GetFullCategories not implemented")
|
||||||
|
}
|
||||||
func (UnimplementedCategoryServer) mustEmbedUnimplementedCategoryServer() {}
|
func (UnimplementedCategoryServer) mustEmbedUnimplementedCategoryServer() {}
|
||||||
func (UnimplementedCategoryServer) testEmbeddedByValue() {}
|
func (UnimplementedCategoryServer) testEmbeddedByValue() {}
|
||||||
|
|
||||||
@ -526,6 +562,42 @@ func _Category_CheckAlias_Handler(srv interface{}, ctx context.Context, dec func
|
|||||||
return interceptor(ctx, in, info, handler)
|
return interceptor(ctx, in, info, handler)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func _Category_GetSystemCategories_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||||
|
in := new(GetSystemCategoriesRequest)
|
||||||
|
if err := dec(in); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if interceptor == nil {
|
||||||
|
return srv.(CategoryServer).GetSystemCategories(ctx, in)
|
||||||
|
}
|
||||||
|
info := &grpc.UnaryServerInfo{
|
||||||
|
Server: srv,
|
||||||
|
FullMethod: Category_GetSystemCategories_FullMethodName,
|
||||||
|
}
|
||||||
|
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||||
|
return srv.(CategoryServer).GetSystemCategories(ctx, req.(*GetSystemCategoriesRequest))
|
||||||
|
}
|
||||||
|
return interceptor(ctx, in, info, handler)
|
||||||
|
}
|
||||||
|
|
||||||
|
func _Category_GetFullCategories_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||||
|
in := new(GetCategoryRequest)
|
||||||
|
if err := dec(in); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if interceptor == nil {
|
||||||
|
return srv.(CategoryServer).GetFullCategories(ctx, in)
|
||||||
|
}
|
||||||
|
info := &grpc.UnaryServerInfo{
|
||||||
|
Server: srv,
|
||||||
|
FullMethod: Category_GetFullCategories_FullMethodName,
|
||||||
|
}
|
||||||
|
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||||
|
return srv.(CategoryServer).GetFullCategories(ctx, req.(*GetCategoryRequest))
|
||||||
|
}
|
||||||
|
return interceptor(ctx, in, info, handler)
|
||||||
|
}
|
||||||
|
|
||||||
// Category_ServiceDesc is the grpc.ServiceDesc for Category service.
|
// Category_ServiceDesc is the grpc.ServiceDesc for Category service.
|
||||||
// It's only intended for direct use with grpc.RegisterService,
|
// It's only intended for direct use with grpc.RegisterService,
|
||||||
// and not to be introspected or modified (even as a copy)
|
// and not to be introspected or modified (even as a copy)
|
||||||
@ -585,6 +657,14 @@ var Category_ServiceDesc = grpc.ServiceDesc{
|
|||||||
MethodName: "CheckAlias",
|
MethodName: "CheckAlias",
|
||||||
Handler: _Category_CheckAlias_Handler,
|
Handler: _Category_CheckAlias_Handler,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
MethodName: "GetSystemCategories",
|
||||||
|
Handler: _Category_GetSystemCategories_Handler,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
MethodName: "GetFullCategories",
|
||||||
|
Handler: _Category_GetFullCategories_Handler,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
Streams: []grpc.StreamDesc{},
|
Streams: []grpc.StreamDesc{},
|
||||||
Metadata: "rpc/category.proto",
|
Metadata: "rpc/category.proto",
|
||||||
|
|||||||
@ -32,6 +32,9 @@ type (
|
|||||||
GetAncestorPathRequest = category.GetAncestorPathRequest
|
GetAncestorPathRequest = category.GetAncestorPathRequest
|
||||||
GetCategoryRequest = category.GetCategoryRequest
|
GetCategoryRequest = category.GetCategoryRequest
|
||||||
GetChildrenRequest = category.GetChildrenRequest
|
GetChildrenRequest = category.GetChildrenRequest
|
||||||
|
GetFullCategoriesResponse = category.GetFullCategoriesResponse
|
||||||
|
GetSystemCategoriesRequest = category.GetSystemCategoriesRequest
|
||||||
|
GetSystemCategoriesResponse = category.GetSystemCategoriesResponse
|
||||||
GetTreeRequest = category.GetTreeRequest
|
GetTreeRequest = category.GetTreeRequest
|
||||||
ListCategoryRequest = category.ListCategoryRequest
|
ListCategoryRequest = category.ListCategoryRequest
|
||||||
MoveCategoryRequest = category.MoveCategoryRequest
|
MoveCategoryRequest = category.MoveCategoryRequest
|
||||||
@ -58,6 +61,10 @@ type (
|
|||||||
// 查询过滤
|
// 查询过滤
|
||||||
ListCategories(ctx context.Context, in *ListCategoryRequest, opts ...grpc.CallOption) (*CategoryListResponse, error)
|
ListCategories(ctx context.Context, in *ListCategoryRequest, opts ...grpc.CallOption) (*CategoryListResponse, error)
|
||||||
CheckAlias(ctx context.Context, in *CheckAliasRequest, opts ...grpc.CallOption) (*CheckAliasResponse, error)
|
CheckAlias(ctx context.Context, in *CheckAliasRequest, opts ...grpc.CallOption) (*CheckAliasResponse, error)
|
||||||
|
// 根据系统ID获取分类
|
||||||
|
GetSystemCategories(ctx context.Context, in *GetSystemCategoriesRequest, opts ...grpc.CallOption) (*GetSystemCategoriesResponse, error)
|
||||||
|
// 获取某一个类别的完整类别(从根类别到当前类别的所有类别)
|
||||||
|
GetFullCategories(ctx context.Context, in *GetCategoryRequest, opts ...grpc.CallOption) (*GetFullCategoriesResponse, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
defaultCategory struct {
|
defaultCategory struct {
|
||||||
@ -140,3 +147,15 @@ func (m *defaultCategory) CheckAlias(ctx context.Context, in *CheckAliasRequest,
|
|||||||
client := category.NewCategoryClient(m.cli.Conn())
|
client := category.NewCategoryClient(m.cli.Conn())
|
||||||
return client.CheckAlias(ctx, in, opts...)
|
return client.CheckAlias(ctx, in, opts...)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 根据系统ID获取分类
|
||||||
|
func (m *defaultCategory) GetSystemCategories(ctx context.Context, in *GetSystemCategoriesRequest, opts ...grpc.CallOption) (*GetSystemCategoriesResponse, error) {
|
||||||
|
client := category.NewCategoryClient(m.cli.Conn())
|
||||||
|
return client.GetSystemCategories(ctx, in, opts...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取某一个类别的完整类别(从根类别到当前类别的所有类别)
|
||||||
|
func (m *defaultCategory) GetFullCategories(ctx context.Context, in *GetCategoryRequest, opts ...grpc.CallOption) (*GetFullCategoriesResponse, error) {
|
||||||
|
client := category.NewCategoryClient(m.cli.Conn())
|
||||||
|
return client.GetFullCategories(ctx, in, opts...)
|
||||||
|
}
|
||||||
|
|||||||
@ -7,7 +7,7 @@ Etcd:
|
|||||||
Key: category.rpc
|
Key: category.rpc
|
||||||
|
|
||||||
DB:
|
DB:
|
||||||
DataSource: postgres://postgres:postgres@localhost:5432/godemo?sslmode=disable
|
DataSource: postgres://postgres:postgres@localhost:19732/godemo?sslmode=disable
|
||||||
MaxOpenConns: 100
|
MaxOpenConns: 100
|
||||||
MaxIdleConns: 20
|
MaxIdleConns: 20
|
||||||
ConnMaxLifetime: 3600
|
ConnMaxLifetime: 3600
|
||||||
73
category/internal/logic/getfullcategorieslogic.go
Normal file
73
category/internal/logic/getfullcategorieslogic.go
Normal file
@ -0,0 +1,73 @@
|
|||||||
|
package logic
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"errors"
|
||||||
|
|
||||||
|
"godemo/category/category"
|
||||||
|
"godemo/category/internal/model"
|
||||||
|
"godemo/category/internal/svc"
|
||||||
|
|
||||||
|
"github.com/zeromicro/go-zero/core/logx"
|
||||||
|
"google.golang.org/grpc/codes"
|
||||||
|
"google.golang.org/grpc/status"
|
||||||
|
)
|
||||||
|
|
||||||
|
type GetFullCategoriesLogic struct {
|
||||||
|
ctx context.Context
|
||||||
|
svcCtx *svc.ServiceContext
|
||||||
|
logx.Logger
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewGetFullCategoriesLogic(ctx context.Context, svcCtx *svc.ServiceContext) *GetFullCategoriesLogic {
|
||||||
|
return &GetFullCategoriesLogic{
|
||||||
|
ctx: ctx,
|
||||||
|
svcCtx: svcCtx,
|
||||||
|
Logger: logx.WithContext(ctx),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取某一个类别的完整类别(从根类别到当前类别的所有类别)
|
||||||
|
func (l *GetFullCategoriesLogic) GetFullCategories(in *category.GetCategoryRequest) (*category.GetFullCategoriesResponse, error) {
|
||||||
|
// 1. 参数校验
|
||||||
|
if in.Id == "" {
|
||||||
|
return nil, status.Error(codes.InvalidArgument, "分类ID不能为空")
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2. 查询当前分类
|
||||||
|
current, err := l.svcCtx.CategoryModel.FindOne(l.ctx, in.Id)
|
||||||
|
if err != nil {
|
||||||
|
if errors.Is(err, model.ErrNotFound) {
|
||||||
|
l.Logger.Errorf("分类不存在, ID: %s", in.Id)
|
||||||
|
return nil, status.Error(codes.NotFound, "分类不存在")
|
||||||
|
}
|
||||||
|
l.Logger.Errorf("数据库查询失败: %v", err)
|
||||||
|
return nil, status.Error(codes.Internal, "内部错误")
|
||||||
|
}
|
||||||
|
|
||||||
|
// 3. 初始化路径为当前分类名称
|
||||||
|
fullPath := current.Name
|
||||||
|
|
||||||
|
// 4. 循环获取父分类
|
||||||
|
parentID := current.ParentId
|
||||||
|
for parentID.Valid {
|
||||||
|
// 查询父分类
|
||||||
|
parent, err := l.svcCtx.CategoryModel.FindOne(l.ctx, parentID.String)
|
||||||
|
if err != nil {
|
||||||
|
if errors.Is(err, model.ErrNotFound) {
|
||||||
|
l.Logger.Errorf("父分类不存在, ID: %s", parentID.String)
|
||||||
|
break // 遇到不存在的父分类时停止循环
|
||||||
|
}
|
||||||
|
l.Logger.Errorf("查询父分类失败: %v", err)
|
||||||
|
break // 其他错误也停止循环
|
||||||
|
}
|
||||||
|
|
||||||
|
// 将父分类名称添加到路径前面
|
||||||
|
fullPath = parent.Name + "/" + fullPath
|
||||||
|
parentID = parent.ParentId // 准备查询上一级父分类
|
||||||
|
}
|
||||||
|
|
||||||
|
return &category.GetFullCategoriesResponse{
|
||||||
|
FullCategoryName: fullPath,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
167
category/internal/logic/getsystemcategorieslogic.go
Normal file
167
category/internal/logic/getsystemcategorieslogic.go
Normal file
@ -0,0 +1,167 @@
|
|||||||
|
package logic
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
|
"godemo/category/category"
|
||||||
|
"godemo/category/internal/model"
|
||||||
|
"godemo/category/internal/svc"
|
||||||
|
|
||||||
|
"github.com/zeromicro/go-zero/core/logx"
|
||||||
|
"github.com/zeromicro/go-zero/core/stores/sqlx"
|
||||||
|
"google.golang.org/grpc/codes"
|
||||||
|
"google.golang.org/grpc/status"
|
||||||
|
)
|
||||||
|
|
||||||
|
type GetSystemCategoriesLogic struct {
|
||||||
|
ctx context.Context
|
||||||
|
svcCtx *svc.ServiceContext
|
||||||
|
logx.Logger
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewGetSystemCategoriesLogic(ctx context.Context, svcCtx *svc.ServiceContext) *GetSystemCategoriesLogic {
|
||||||
|
return &GetSystemCategoriesLogic{
|
||||||
|
ctx: ctx,
|
||||||
|
svcCtx: svcCtx,
|
||||||
|
Logger: logx.WithContext(ctx),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 根据系统ID获取分类
|
||||||
|
func (l *GetSystemCategoriesLogic) GetSystemCategories(in *category.GetSystemCategoriesRequest) (*category.GetSystemCategoriesResponse, error) {
|
||||||
|
// 1. 参数验证
|
||||||
|
if in.SystemId == "" {
|
||||||
|
return nil, status.Error(codes.InvalidArgument, "system_id is required")
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2. 设置默认分页值
|
||||||
|
page, pageSize := normalizePagination(in.Page, in.PageSize)
|
||||||
|
|
||||||
|
// 3. 根据是否包含后代选择查询方式
|
||||||
|
var categories []*model.Categories
|
||||||
|
var total int64
|
||||||
|
var err error
|
||||||
|
|
||||||
|
if in.IncludeDescendants {
|
||||||
|
// 递归查询所有后代
|
||||||
|
categories, err = l.getDescendantsRecursively(in.SystemId, in.ParentId)
|
||||||
|
if err != nil {
|
||||||
|
return nil, status.Error(codes.Internal, "failed to get descendant categories")
|
||||||
|
}
|
||||||
|
total = int64(len(categories))
|
||||||
|
} else {
|
||||||
|
// 直接查询子分类
|
||||||
|
categories, total, err = l.getDirectChildren(in.SystemId, in.ParentId, page, pageSize)
|
||||||
|
if err != nil {
|
||||||
|
return nil, status.Error(codes.Internal, "failed to get categories")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 4. 转换模型到protobuf
|
||||||
|
pbCategories := make([]*category.CategoryInfo, 0, len(categories))
|
||||||
|
for _, cat := range categories {
|
||||||
|
pbCategories = append(pbCategories, convertToPbCategory(cat))
|
||||||
|
}
|
||||||
|
|
||||||
|
// 5. 构建响应
|
||||||
|
return &category.GetSystemCategoriesResponse{
|
||||||
|
Categories: pbCategories,
|
||||||
|
Total: total,
|
||||||
|
CurrentPage: int32(page),
|
||||||
|
PageSize: int32(pageSize),
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取直接子分类(非递归)
|
||||||
|
func (l *GetSystemCategoriesLogic) getDirectChildren(systemID, parentID string, page, pageSize int) ([]*model.Categories, int64, error) {
|
||||||
|
// 构建基础查询
|
||||||
|
query := l.svcCtx.CategoryModel.RowBuilder().
|
||||||
|
Where("system_id = $1", systemID)
|
||||||
|
|
||||||
|
// 处理父分类ID
|
||||||
|
if parentID == "" {
|
||||||
|
query = query.Where("(parent_id IS NULL OR parent_id = '')")
|
||||||
|
} else {
|
||||||
|
query = query.Where("parent_id = $2", parentID)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取总数
|
||||||
|
total, err := l.svcCtx.CategoryModel.FindCount(l.ctx, query.RemoveColumns())
|
||||||
|
if err != nil {
|
||||||
|
return nil, 0, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// 分页查询
|
||||||
|
query = query.OrderBy("created_at DESC").
|
||||||
|
Offset(uint64((page - 1) * pageSize)).
|
||||||
|
Limit(uint64(pageSize))
|
||||||
|
|
||||||
|
categories, err := l.svcCtx.CategoryModel.FindAll(l.ctx, query)
|
||||||
|
if err != nil {
|
||||||
|
return nil, 0, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return categories, total, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// 递归获取所有后代分类
|
||||||
|
func (l *GetSystemCategoriesLogic) getDescendantsRecursively(systemID, parentID string) ([]*model.Categories, error) {
|
||||||
|
// 使用递归CTE查询
|
||||||
|
query := `
|
||||||
|
WITH RECURSIVE category_tree AS (
|
||||||
|
SELECT id, system_id, name, alias, parent_id, description, created_at, updated_at
|
||||||
|
FROM categories
|
||||||
|
WHERE system_id = $1
|
||||||
|
AND (
|
||||||
|
CASE
|
||||||
|
WHEN $2 = '' THEN parent_id IS NULL
|
||||||
|
ELSE parent_id = $2
|
||||||
|
END
|
||||||
|
)
|
||||||
|
UNION ALL
|
||||||
|
SELECT c.id, c.system_id, c.name, c.alias, c.parent_id, c.description, c.created_at, c.updated_at
|
||||||
|
FROM categories c
|
||||||
|
INNER JOIN category_tree ct ON c.parent_id = ct.id
|
||||||
|
)
|
||||||
|
SELECT * FROM category_tree
|
||||||
|
`
|
||||||
|
|
||||||
|
var categories []*model.Categories
|
||||||
|
err := l.svcCtx.SqlConn.QueryRowsCtx(l.ctx, &categories, query, systemID, parentID)
|
||||||
|
if err != nil && err != sqlx.ErrNotFound {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return categories, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// 转换模型到protobuf
|
||||||
|
func convertToPbCategory(cat *model.Categories) *category.CategoryInfo {
|
||||||
|
return &category.CategoryInfo{
|
||||||
|
Id: cat.Id,
|
||||||
|
SystemId: cat.SystemId,
|
||||||
|
Name: cat.Name,
|
||||||
|
Alias: cat.Alias.String,
|
||||||
|
ParentId: cat.ParentId.String,
|
||||||
|
Description: cat.Description.String,
|
||||||
|
CreatedAt: cat.CreatedAt.Unix(),
|
||||||
|
UpdatedAt: cat.UpdatedAt.Time.Unix(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 规范化分页参数
|
||||||
|
func normalizePagination(page, pageSize int32) (int, int) {
|
||||||
|
p := int(page)
|
||||||
|
ps := int(pageSize)
|
||||||
|
|
||||||
|
if p <= 0 {
|
||||||
|
p = 1
|
||||||
|
}
|
||||||
|
if ps <= 0 {
|
||||||
|
ps = 20
|
||||||
|
} else if ps > 100 {
|
||||||
|
ps = 100
|
||||||
|
}
|
||||||
|
|
||||||
|
return p, ps
|
||||||
|
}
|
||||||
@ -3,6 +3,7 @@ package model
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
|
||||||
|
"github.com/Masterminds/squirrel"
|
||||||
"github.com/zeromicro/go-zero/core/stores/sqlx"
|
"github.com/zeromicro/go-zero/core/stores/sqlx"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -17,6 +18,11 @@ type (
|
|||||||
Transact(ctx context.Context, fn func(ctx context.Context, session sqlx.Session) error) error
|
Transact(ctx context.Context, fn func(ctx context.Context, session sqlx.Session) error) error
|
||||||
FindBySystemParentName(ctx context.Context, systemID string, parentID string, name string) (*Categories, error)
|
FindBySystemParentName(ctx context.Context, systemID string, parentID string, name string) (*Categories, error)
|
||||||
FindBySystemParentAlias(ctx context.Context, systemID string, parentID string, alias string) (*Categories, error)
|
FindBySystemParentAlias(ctx context.Context, systemID string, parentID string, alias string) (*Categories, error)
|
||||||
|
|
||||||
|
// 新增方法
|
||||||
|
RowBuilder() squirrel.SelectBuilder
|
||||||
|
FindCount(ctx context.Context, builder squirrel.SelectBuilder) (int64, error)
|
||||||
|
FindAll(ctx context.Context, builder squirrel.SelectBuilder) ([]*Categories, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
customCategoriesModel struct {
|
customCategoriesModel struct {
|
||||||
@ -72,3 +78,81 @@ func (m *customCategoriesModel) FindBySystemParentAlias(ctx context.Context, sys
|
|||||||
}
|
}
|
||||||
return &resp, nil
|
return &resp, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// === 新增方法实现 ===
|
||||||
|
|
||||||
|
// RowBuilder 创建一个基本的SELECT查询构建器
|
||||||
|
func (m *customCategoriesModel) RowBuilder() squirrel.SelectBuilder {
|
||||||
|
return squirrel.Select(categoriesRows).From(m.table)
|
||||||
|
}
|
||||||
|
|
||||||
|
// FindCount 执行COUNT查询
|
||||||
|
func (m *customCategoriesModel) FindCount(ctx context.Context, builder squirrel.SelectBuilder) (int64, error) {
|
||||||
|
// 将SELECT转换为COUNT
|
||||||
|
builder = builder.Columns("COUNT(1) AS count")
|
||||||
|
|
||||||
|
query, args, err := builder.ToSql()
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
|
||||||
|
var count int64
|
||||||
|
err = m.conn.QueryRowCtx(ctx, &count, query, args...)
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return count, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// FindAll 执行查询并返回所有结果
|
||||||
|
func (m *customCategoriesModel) FindAll(ctx context.Context, builder squirrel.SelectBuilder) ([]*Categories, error) {
|
||||||
|
query, args, err := builder.ToSql()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
var categories []*Categories
|
||||||
|
err = m.conn.QueryRowsCtx(ctx, &categories, query, args...)
|
||||||
|
if err != nil && err != sqlx.ErrNotFound {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return categories, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// === 辅助函数 ===
|
||||||
|
|
||||||
|
// 添加分页支持
|
||||||
|
func (m *customCategoriesModel) FindAllWithPagination(
|
||||||
|
ctx context.Context,
|
||||||
|
builder squirrel.SelectBuilder,
|
||||||
|
orderBy string,
|
||||||
|
page int,
|
||||||
|
pageSize int,
|
||||||
|
) ([]*Categories, int64, error) {
|
||||||
|
// 获取总数
|
||||||
|
total, err := m.FindCount(ctx, builder)
|
||||||
|
if err != nil {
|
||||||
|
return nil, 0, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// 添加分页
|
||||||
|
if page > 0 && pageSize > 0 {
|
||||||
|
offset := (page - 1) * pageSize
|
||||||
|
builder = builder.Offset(uint64(offset)).Limit(uint64(pageSize))
|
||||||
|
}
|
||||||
|
|
||||||
|
// 添加排序
|
||||||
|
if orderBy != "" {
|
||||||
|
builder = builder.OrderBy(orderBy)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 执行查询
|
||||||
|
categories, err := m.FindAll(ctx, builder)
|
||||||
|
if err != nil {
|
||||||
|
return nil, 0, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return categories, total, nil
|
||||||
|
}
|
||||||
|
|||||||
@ -92,3 +92,15 @@ func (s *CategoryServer) CheckAlias(ctx context.Context, in *category.CheckAlias
|
|||||||
l := logic.NewCheckAliasLogic(ctx, s.svcCtx)
|
l := logic.NewCheckAliasLogic(ctx, s.svcCtx)
|
||||||
return l.CheckAlias(in)
|
return l.CheckAlias(in)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 根据系统ID获取分类
|
||||||
|
func (s *CategoryServer) GetSystemCategories(ctx context.Context, in *category.GetSystemCategoriesRequest) (*category.GetSystemCategoriesResponse, error) {
|
||||||
|
l := logic.NewGetSystemCategoriesLogic(ctx, s.svcCtx)
|
||||||
|
return l.GetSystemCategories(in)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取某一个类别的完整类别(从根类别到当前类别的所有类别)
|
||||||
|
func (s *CategoryServer) GetFullCategories(ctx context.Context, in *category.GetCategoryRequest) (*category.GetFullCategoriesResponse, error) {
|
||||||
|
l := logic.NewGetFullCategoriesLogic(ctx, s.svcCtx)
|
||||||
|
return l.GetFullCategories(in)
|
||||||
|
}
|
||||||
|
|||||||
@ -11,6 +11,7 @@ import (
|
|||||||
type ServiceContext struct {
|
type ServiceContext struct {
|
||||||
Config config.Config
|
Config config.Config
|
||||||
CategoryModel model.CategoriesModel
|
CategoryModel model.CategoriesModel
|
||||||
|
SqlConn sqlx.SqlConn // 添加这个字段
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewServiceContext(c config.Config) *ServiceContext {
|
func NewServiceContext(c config.Config) *ServiceContext {
|
||||||
@ -18,5 +19,6 @@ func NewServiceContext(c config.Config) *ServiceContext {
|
|||||||
return &ServiceContext{
|
return &ServiceContext{
|
||||||
Config: c,
|
Config: c,
|
||||||
CategoryModel: model.NewCategoriesModel(conn),
|
CategoryModel: model.NewCategoriesModel(conn),
|
||||||
|
SqlConn: conn, // 赋值
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -8,6 +8,7 @@ import (
|
|||||||
"godemo/file/internal/config"
|
"godemo/file/internal/config"
|
||||||
"godemo/file/internal/server"
|
"godemo/file/internal/server"
|
||||||
"godemo/file/internal/svc"
|
"godemo/file/internal/svc"
|
||||||
|
"godemo/file/worker"
|
||||||
|
|
||||||
"github.com/zeromicro/go-zero/core/conf"
|
"github.com/zeromicro/go-zero/core/conf"
|
||||||
"github.com/zeromicro/go-zero/core/service"
|
"github.com/zeromicro/go-zero/core/service"
|
||||||
@ -25,6 +26,11 @@ func main() {
|
|||||||
conf.MustLoad(*configFile, &c)
|
conf.MustLoad(*configFile, &c)
|
||||||
ctx := svc.NewServiceContext(c)
|
ctx := svc.NewServiceContext(c)
|
||||||
|
|
||||||
|
// 初始化任务队列
|
||||||
|
worker.InitImageProcessTaskQueue(1000)
|
||||||
|
// 启动worker池
|
||||||
|
worker.StartImageProcessWorkers(5, ctx)
|
||||||
|
|
||||||
s := zrpc.MustNewServer(c.RpcServerConf, func(grpcServer *grpc.Server) {
|
s := zrpc.MustNewServer(c.RpcServerConf, func(grpcServer *grpc.Server) {
|
||||||
file.RegisterFileServer(grpcServer, server.NewFileServer(ctx))
|
file.RegisterFileServer(grpcServer, server.NewFileServer(ctx))
|
||||||
|
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||||
// versions:
|
// versions:
|
||||||
// protoc-gen-go v1.36.6
|
// protoc-gen-go v1.36.6
|
||||||
// protoc v3.20.3
|
// protoc v3.19.4
|
||||||
// source: rpc/file.proto
|
// source: rpc/file.proto
|
||||||
|
|
||||||
package file
|
package file
|
||||||
@ -21,20 +21,179 @@ const (
|
|||||||
_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
|
_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
type ImageVersion int32
|
||||||
|
|
||||||
|
const (
|
||||||
|
ImageVersion_original ImageVersion = 0
|
||||||
|
ImageVersion_thumbnail ImageVersion = 1 // 缩略图
|
||||||
|
ImageVersion_preview ImageVersion = 2 // 预览图
|
||||||
|
ImageVersion_all ImageVersion = 9 // 所有版本
|
||||||
|
)
|
||||||
|
|
||||||
|
// Enum value maps for ImageVersion.
|
||||||
|
var (
|
||||||
|
ImageVersion_name = map[int32]string{
|
||||||
|
0: "original",
|
||||||
|
1: "thumbnail",
|
||||||
|
2: "preview",
|
||||||
|
9: "all",
|
||||||
|
}
|
||||||
|
ImageVersion_value = map[string]int32{
|
||||||
|
"original": 0,
|
||||||
|
"thumbnail": 1,
|
||||||
|
"preview": 2,
|
||||||
|
"all": 9,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
func (x ImageVersion) Enum() *ImageVersion {
|
||||||
|
p := new(ImageVersion)
|
||||||
|
*p = x
|
||||||
|
return p
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x ImageVersion) String() string {
|
||||||
|
return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ImageVersion) Descriptor() protoreflect.EnumDescriptor {
|
||||||
|
return file_rpc_file_proto_enumTypes[0].Descriptor()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ImageVersion) Type() protoreflect.EnumType {
|
||||||
|
return &file_rpc_file_proto_enumTypes[0]
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x ImageVersion) Number() protoreflect.EnumNumber {
|
||||||
|
return protoreflect.EnumNumber(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Deprecated: Use ImageVersion.Descriptor instead.
|
||||||
|
func (ImageVersion) EnumDescriptor() ([]byte, []int) {
|
||||||
|
return file_rpc_file_proto_rawDescGZIP(), []int{0}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 生成图片版本请求
|
||||||
|
type GenerateImageVersionsRequest struct {
|
||||||
|
state protoimpl.MessageState `protogen:"open.v1"`
|
||||||
|
FileId string `protobuf:"bytes,1,opt,name=file_id,json=fileId,proto3" json:"file_id,omitempty"` // 原始图片ID
|
||||||
|
Versions []ImageVersion `protobuf:"varint,2,rep,packed,name=versions,proto3,enum=file.ImageVersion" json:"versions,omitempty"` // 需要生成的版本
|
||||||
|
unknownFields protoimpl.UnknownFields
|
||||||
|
sizeCache protoimpl.SizeCache
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *GenerateImageVersionsRequest) Reset() {
|
||||||
|
*x = GenerateImageVersionsRequest{}
|
||||||
|
mi := &file_rpc_file_proto_msgTypes[0]
|
||||||
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
|
ms.StoreMessageInfo(mi)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *GenerateImageVersionsRequest) String() string {
|
||||||
|
return protoimpl.X.MessageStringOf(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (*GenerateImageVersionsRequest) ProtoMessage() {}
|
||||||
|
|
||||||
|
func (x *GenerateImageVersionsRequest) ProtoReflect() protoreflect.Message {
|
||||||
|
mi := &file_rpc_file_proto_msgTypes[0]
|
||||||
|
if x != nil {
|
||||||
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
|
if ms.LoadMessageInfo() == nil {
|
||||||
|
ms.StoreMessageInfo(mi)
|
||||||
|
}
|
||||||
|
return ms
|
||||||
|
}
|
||||||
|
return mi.MessageOf(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Deprecated: Use GenerateImageVersionsRequest.ProtoReflect.Descriptor instead.
|
||||||
|
func (*GenerateImageVersionsRequest) Descriptor() ([]byte, []int) {
|
||||||
|
return file_rpc_file_proto_rawDescGZIP(), []int{0}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *GenerateImageVersionsRequest) GetFileId() string {
|
||||||
|
if x != nil {
|
||||||
|
return x.FileId
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *GenerateImageVersionsRequest) GetVersions() []ImageVersion {
|
||||||
|
if x != nil {
|
||||||
|
return x.Versions
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// 生成图片版本响应
|
||||||
|
type GenerateImageVersionsResponse struct {
|
||||||
|
state protoimpl.MessageState `protogen:"open.v1"`
|
||||||
|
TaskId string `protobuf:"bytes,1,opt,name=task_id,json=taskId,proto3" json:"task_id,omitempty"` // 异步任务ID
|
||||||
|
Accepted bool `protobuf:"varint,2,opt,name=accepted,proto3" json:"accepted,omitempty"` // 任务是否被接受
|
||||||
|
unknownFields protoimpl.UnknownFields
|
||||||
|
sizeCache protoimpl.SizeCache
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *GenerateImageVersionsResponse) Reset() {
|
||||||
|
*x = GenerateImageVersionsResponse{}
|
||||||
|
mi := &file_rpc_file_proto_msgTypes[1]
|
||||||
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
|
ms.StoreMessageInfo(mi)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *GenerateImageVersionsResponse) String() string {
|
||||||
|
return protoimpl.X.MessageStringOf(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (*GenerateImageVersionsResponse) ProtoMessage() {}
|
||||||
|
|
||||||
|
func (x *GenerateImageVersionsResponse) ProtoReflect() protoreflect.Message {
|
||||||
|
mi := &file_rpc_file_proto_msgTypes[1]
|
||||||
|
if x != nil {
|
||||||
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
|
if ms.LoadMessageInfo() == nil {
|
||||||
|
ms.StoreMessageInfo(mi)
|
||||||
|
}
|
||||||
|
return ms
|
||||||
|
}
|
||||||
|
return mi.MessageOf(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Deprecated: Use GenerateImageVersionsResponse.ProtoReflect.Descriptor instead.
|
||||||
|
func (*GenerateImageVersionsResponse) Descriptor() ([]byte, []int) {
|
||||||
|
return file_rpc_file_proto_rawDescGZIP(), []int{1}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *GenerateImageVersionsResponse) GetTaskId() string {
|
||||||
|
if x != nil {
|
||||||
|
return x.TaskId
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *GenerateImageVersionsResponse) GetAccepted() bool {
|
||||||
|
if x != nil {
|
||||||
|
return x.Accepted
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
// 上传文件请求
|
// 上传文件请求
|
||||||
type UploadRequest struct {
|
type UploadRequest struct {
|
||||||
state protoimpl.MessageState `protogen:"open.v1"`
|
state protoimpl.MessageState `protogen:"open.v1"`
|
||||||
Filename string `protobuf:"bytes,1,opt,name=filename,proto3" json:"filename,omitempty"` // 文件名(建议客户端传原始名,服务端会生成唯一名)
|
Filename string `protobuf:"bytes,1,opt,name=filename,proto3" json:"filename,omitempty"` // 文件名(建议客户端传原始名,服务端会生成唯一名)
|
||||||
ContentType string `protobuf:"bytes,2,opt,name=content_type,json=contentType,proto3" json:"content_type,omitempty"` // 文件类型(如 image/jpeg)
|
ContentType string `protobuf:"bytes,2,opt,name=content_type,json=contentType,proto3" json:"content_type,omitempty"` // 文件类型(如 image/jpeg)
|
||||||
Content []byte `protobuf:"bytes,3,opt,name=content,proto3" json:"content,omitempty"` // 文件二进制内容(base64 编码由客户端完成)
|
Content []byte `protobuf:"bytes,3,opt,name=content,proto3" json:"content,omitempty"` // 文件二进制内容(base64 编码由客户端完成)
|
||||||
Folder string `protobuf:"bytes,4,opt,name=folder,proto3" json:"folder,omitempty"` // 可选,文件夹或分类路径,如 "avatars"、"wallpapers"
|
Folder string `protobuf:"bytes,4,opt,name=folder,proto3" json:"folder,omitempty"` // 可选,文件夹或分类路径,支持多级,如 "avatars"、"wallpapers/animals"
|
||||||
|
Bucket string `protobuf:"bytes,5,opt,name=bucket,proto3" json:"bucket,omitempty"` // bucket name
|
||||||
unknownFields protoimpl.UnknownFields
|
unknownFields protoimpl.UnknownFields
|
||||||
sizeCache protoimpl.SizeCache
|
sizeCache protoimpl.SizeCache
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *UploadRequest) Reset() {
|
func (x *UploadRequest) Reset() {
|
||||||
*x = UploadRequest{}
|
*x = UploadRequest{}
|
||||||
mi := &file_rpc_file_proto_msgTypes[0]
|
mi := &file_rpc_file_proto_msgTypes[2]
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
ms.StoreMessageInfo(mi)
|
ms.StoreMessageInfo(mi)
|
||||||
}
|
}
|
||||||
@ -46,7 +205,7 @@ func (x *UploadRequest) String() string {
|
|||||||
func (*UploadRequest) ProtoMessage() {}
|
func (*UploadRequest) ProtoMessage() {}
|
||||||
|
|
||||||
func (x *UploadRequest) ProtoReflect() protoreflect.Message {
|
func (x *UploadRequest) ProtoReflect() protoreflect.Message {
|
||||||
mi := &file_rpc_file_proto_msgTypes[0]
|
mi := &file_rpc_file_proto_msgTypes[2]
|
||||||
if x != nil {
|
if x != nil {
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
if ms.LoadMessageInfo() == nil {
|
if ms.LoadMessageInfo() == nil {
|
||||||
@ -59,7 +218,7 @@ func (x *UploadRequest) ProtoReflect() protoreflect.Message {
|
|||||||
|
|
||||||
// Deprecated: Use UploadRequest.ProtoReflect.Descriptor instead.
|
// Deprecated: Use UploadRequest.ProtoReflect.Descriptor instead.
|
||||||
func (*UploadRequest) Descriptor() ([]byte, []int) {
|
func (*UploadRequest) Descriptor() ([]byte, []int) {
|
||||||
return file_rpc_file_proto_rawDescGZIP(), []int{0}
|
return file_rpc_file_proto_rawDescGZIP(), []int{2}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *UploadRequest) GetFilename() string {
|
func (x *UploadRequest) GetFilename() string {
|
||||||
@ -90,6 +249,13 @@ func (x *UploadRequest) GetFolder() string {
|
|||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (x *UploadRequest) GetBucket() string {
|
||||||
|
if x != nil {
|
||||||
|
return x.Bucket
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
// 上传响应
|
// 上传响应
|
||||||
type UploadResponse struct {
|
type UploadResponse struct {
|
||||||
state protoimpl.MessageState `protogen:"open.v1"`
|
state protoimpl.MessageState `protogen:"open.v1"`
|
||||||
@ -101,7 +267,7 @@ type UploadResponse struct {
|
|||||||
|
|
||||||
func (x *UploadResponse) Reset() {
|
func (x *UploadResponse) Reset() {
|
||||||
*x = UploadResponse{}
|
*x = UploadResponse{}
|
||||||
mi := &file_rpc_file_proto_msgTypes[1]
|
mi := &file_rpc_file_proto_msgTypes[3]
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
ms.StoreMessageInfo(mi)
|
ms.StoreMessageInfo(mi)
|
||||||
}
|
}
|
||||||
@ -113,7 +279,7 @@ func (x *UploadResponse) String() string {
|
|||||||
func (*UploadResponse) ProtoMessage() {}
|
func (*UploadResponse) ProtoMessage() {}
|
||||||
|
|
||||||
func (x *UploadResponse) ProtoReflect() protoreflect.Message {
|
func (x *UploadResponse) ProtoReflect() protoreflect.Message {
|
||||||
mi := &file_rpc_file_proto_msgTypes[1]
|
mi := &file_rpc_file_proto_msgTypes[3]
|
||||||
if x != nil {
|
if x != nil {
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
if ms.LoadMessageInfo() == nil {
|
if ms.LoadMessageInfo() == nil {
|
||||||
@ -126,7 +292,7 @@ func (x *UploadResponse) ProtoReflect() protoreflect.Message {
|
|||||||
|
|
||||||
// Deprecated: Use UploadResponse.ProtoReflect.Descriptor instead.
|
// Deprecated: Use UploadResponse.ProtoReflect.Descriptor instead.
|
||||||
func (*UploadResponse) Descriptor() ([]byte, []int) {
|
func (*UploadResponse) Descriptor() ([]byte, []int) {
|
||||||
return file_rpc_file_proto_rawDescGZIP(), []int{1}
|
return file_rpc_file_proto_rawDescGZIP(), []int{3}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *UploadResponse) GetFileId() string {
|
func (x *UploadResponse) GetFileId() string {
|
||||||
@ -153,7 +319,7 @@ type GetFileUrlRequest struct {
|
|||||||
|
|
||||||
func (x *GetFileUrlRequest) Reset() {
|
func (x *GetFileUrlRequest) Reset() {
|
||||||
*x = GetFileUrlRequest{}
|
*x = GetFileUrlRequest{}
|
||||||
mi := &file_rpc_file_proto_msgTypes[2]
|
mi := &file_rpc_file_proto_msgTypes[4]
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
ms.StoreMessageInfo(mi)
|
ms.StoreMessageInfo(mi)
|
||||||
}
|
}
|
||||||
@ -165,7 +331,7 @@ func (x *GetFileUrlRequest) String() string {
|
|||||||
func (*GetFileUrlRequest) ProtoMessage() {}
|
func (*GetFileUrlRequest) ProtoMessage() {}
|
||||||
|
|
||||||
func (x *GetFileUrlRequest) ProtoReflect() protoreflect.Message {
|
func (x *GetFileUrlRequest) ProtoReflect() protoreflect.Message {
|
||||||
mi := &file_rpc_file_proto_msgTypes[2]
|
mi := &file_rpc_file_proto_msgTypes[4]
|
||||||
if x != nil {
|
if x != nil {
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
if ms.LoadMessageInfo() == nil {
|
if ms.LoadMessageInfo() == nil {
|
||||||
@ -178,7 +344,7 @@ func (x *GetFileUrlRequest) ProtoReflect() protoreflect.Message {
|
|||||||
|
|
||||||
// Deprecated: Use GetFileUrlRequest.ProtoReflect.Descriptor instead.
|
// Deprecated: Use GetFileUrlRequest.ProtoReflect.Descriptor instead.
|
||||||
func (*GetFileUrlRequest) Descriptor() ([]byte, []int) {
|
func (*GetFileUrlRequest) Descriptor() ([]byte, []int) {
|
||||||
return file_rpc_file_proto_rawDescGZIP(), []int{2}
|
return file_rpc_file_proto_rawDescGZIP(), []int{4}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *GetFileUrlRequest) GetFileId() string {
|
func (x *GetFileUrlRequest) GetFileId() string {
|
||||||
@ -198,7 +364,7 @@ type GetFileUrlResponse struct {
|
|||||||
|
|
||||||
func (x *GetFileUrlResponse) Reset() {
|
func (x *GetFileUrlResponse) Reset() {
|
||||||
*x = GetFileUrlResponse{}
|
*x = GetFileUrlResponse{}
|
||||||
mi := &file_rpc_file_proto_msgTypes[3]
|
mi := &file_rpc_file_proto_msgTypes[5]
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
ms.StoreMessageInfo(mi)
|
ms.StoreMessageInfo(mi)
|
||||||
}
|
}
|
||||||
@ -210,7 +376,7 @@ func (x *GetFileUrlResponse) String() string {
|
|||||||
func (*GetFileUrlResponse) ProtoMessage() {}
|
func (*GetFileUrlResponse) ProtoMessage() {}
|
||||||
|
|
||||||
func (x *GetFileUrlResponse) ProtoReflect() protoreflect.Message {
|
func (x *GetFileUrlResponse) ProtoReflect() protoreflect.Message {
|
||||||
mi := &file_rpc_file_proto_msgTypes[3]
|
mi := &file_rpc_file_proto_msgTypes[5]
|
||||||
if x != nil {
|
if x != nil {
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
if ms.LoadMessageInfo() == nil {
|
if ms.LoadMessageInfo() == nil {
|
||||||
@ -223,7 +389,7 @@ func (x *GetFileUrlResponse) ProtoReflect() protoreflect.Message {
|
|||||||
|
|
||||||
// Deprecated: Use GetFileUrlResponse.ProtoReflect.Descriptor instead.
|
// Deprecated: Use GetFileUrlResponse.ProtoReflect.Descriptor instead.
|
||||||
func (*GetFileUrlResponse) Descriptor() ([]byte, []int) {
|
func (*GetFileUrlResponse) Descriptor() ([]byte, []int) {
|
||||||
return file_rpc_file_proto_rawDescGZIP(), []int{3}
|
return file_rpc_file_proto_rawDescGZIP(), []int{5}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *GetFileUrlResponse) GetUrl() string {
|
func (x *GetFileUrlResponse) GetUrl() string {
|
||||||
@ -243,7 +409,7 @@ type DeleteRequest struct {
|
|||||||
|
|
||||||
func (x *DeleteRequest) Reset() {
|
func (x *DeleteRequest) Reset() {
|
||||||
*x = DeleteRequest{}
|
*x = DeleteRequest{}
|
||||||
mi := &file_rpc_file_proto_msgTypes[4]
|
mi := &file_rpc_file_proto_msgTypes[6]
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
ms.StoreMessageInfo(mi)
|
ms.StoreMessageInfo(mi)
|
||||||
}
|
}
|
||||||
@ -255,7 +421,7 @@ func (x *DeleteRequest) String() string {
|
|||||||
func (*DeleteRequest) ProtoMessage() {}
|
func (*DeleteRequest) ProtoMessage() {}
|
||||||
|
|
||||||
func (x *DeleteRequest) ProtoReflect() protoreflect.Message {
|
func (x *DeleteRequest) ProtoReflect() protoreflect.Message {
|
||||||
mi := &file_rpc_file_proto_msgTypes[4]
|
mi := &file_rpc_file_proto_msgTypes[6]
|
||||||
if x != nil {
|
if x != nil {
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
if ms.LoadMessageInfo() == nil {
|
if ms.LoadMessageInfo() == nil {
|
||||||
@ -268,7 +434,7 @@ func (x *DeleteRequest) ProtoReflect() protoreflect.Message {
|
|||||||
|
|
||||||
// Deprecated: Use DeleteRequest.ProtoReflect.Descriptor instead.
|
// Deprecated: Use DeleteRequest.ProtoReflect.Descriptor instead.
|
||||||
func (*DeleteRequest) Descriptor() ([]byte, []int) {
|
func (*DeleteRequest) Descriptor() ([]byte, []int) {
|
||||||
return file_rpc_file_proto_rawDescGZIP(), []int{4}
|
return file_rpc_file_proto_rawDescGZIP(), []int{6}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *DeleteRequest) GetFileId() string {
|
func (x *DeleteRequest) GetFileId() string {
|
||||||
@ -288,7 +454,7 @@ type DeleteResponse struct {
|
|||||||
|
|
||||||
func (x *DeleteResponse) Reset() {
|
func (x *DeleteResponse) Reset() {
|
||||||
*x = DeleteResponse{}
|
*x = DeleteResponse{}
|
||||||
mi := &file_rpc_file_proto_msgTypes[5]
|
mi := &file_rpc_file_proto_msgTypes[7]
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
ms.StoreMessageInfo(mi)
|
ms.StoreMessageInfo(mi)
|
||||||
}
|
}
|
||||||
@ -300,7 +466,7 @@ func (x *DeleteResponse) String() string {
|
|||||||
func (*DeleteResponse) ProtoMessage() {}
|
func (*DeleteResponse) ProtoMessage() {}
|
||||||
|
|
||||||
func (x *DeleteResponse) ProtoReflect() protoreflect.Message {
|
func (x *DeleteResponse) ProtoReflect() protoreflect.Message {
|
||||||
mi := &file_rpc_file_proto_msgTypes[5]
|
mi := &file_rpc_file_proto_msgTypes[7]
|
||||||
if x != nil {
|
if x != nil {
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
if ms.LoadMessageInfo() == nil {
|
if ms.LoadMessageInfo() == nil {
|
||||||
@ -313,7 +479,7 @@ func (x *DeleteResponse) ProtoReflect() protoreflect.Message {
|
|||||||
|
|
||||||
// Deprecated: Use DeleteResponse.ProtoReflect.Descriptor instead.
|
// Deprecated: Use DeleteResponse.ProtoReflect.Descriptor instead.
|
||||||
func (*DeleteResponse) Descriptor() ([]byte, []int) {
|
func (*DeleteResponse) Descriptor() ([]byte, []int) {
|
||||||
return file_rpc_file_proto_rawDescGZIP(), []int{5}
|
return file_rpc_file_proto_rawDescGZIP(), []int{7}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *DeleteResponse) GetSuccess() bool {
|
func (x *DeleteResponse) GetSuccess() bool {
|
||||||
@ -327,12 +493,19 @@ var File_rpc_file_proto protoreflect.FileDescriptor
|
|||||||
|
|
||||||
const file_rpc_file_proto_rawDesc = "" +
|
const file_rpc_file_proto_rawDesc = "" +
|
||||||
"\n" +
|
"\n" +
|
||||||
"\x0erpc/file.proto\x12\x04file\"\x80\x01\n" +
|
"\x0erpc/file.proto\x12\x04file\"g\n" +
|
||||||
|
"\x1cGenerateImageVersionsRequest\x12\x17\n" +
|
||||||
|
"\afile_id\x18\x01 \x01(\tR\x06fileId\x12.\n" +
|
||||||
|
"\bversions\x18\x02 \x03(\x0e2\x12.file.ImageVersionR\bversions\"T\n" +
|
||||||
|
"\x1dGenerateImageVersionsResponse\x12\x17\n" +
|
||||||
|
"\atask_id\x18\x01 \x01(\tR\x06taskId\x12\x1a\n" +
|
||||||
|
"\baccepted\x18\x02 \x01(\bR\baccepted\"\x98\x01\n" +
|
||||||
"\rUploadRequest\x12\x1a\n" +
|
"\rUploadRequest\x12\x1a\n" +
|
||||||
"\bfilename\x18\x01 \x01(\tR\bfilename\x12!\n" +
|
"\bfilename\x18\x01 \x01(\tR\bfilename\x12!\n" +
|
||||||
"\fcontent_type\x18\x02 \x01(\tR\vcontentType\x12\x18\n" +
|
"\fcontent_type\x18\x02 \x01(\tR\vcontentType\x12\x18\n" +
|
||||||
"\acontent\x18\x03 \x01(\fR\acontent\x12\x16\n" +
|
"\acontent\x18\x03 \x01(\fR\acontent\x12\x16\n" +
|
||||||
"\x06folder\x18\x04 \x01(\tR\x06folder\";\n" +
|
"\x06folder\x18\x04 \x01(\tR\x06folder\x12\x16\n" +
|
||||||
|
"\x06bucket\x18\x05 \x01(\tR\x06bucket\";\n" +
|
||||||
"\x0eUploadResponse\x12\x17\n" +
|
"\x0eUploadResponse\x12\x17\n" +
|
||||||
"\afile_id\x18\x01 \x01(\tR\x06fileId\x12\x10\n" +
|
"\afile_id\x18\x01 \x01(\tR\x06fileId\x12\x10\n" +
|
||||||
"\x03url\x18\x02 \x01(\tR\x03url\",\n" +
|
"\x03url\x18\x02 \x01(\tR\x03url\",\n" +
|
||||||
@ -343,12 +516,18 @@ const file_rpc_file_proto_rawDesc = "" +
|
|||||||
"\rDeleteRequest\x12\x17\n" +
|
"\rDeleteRequest\x12\x17\n" +
|
||||||
"\afile_id\x18\x01 \x01(\tR\x06fileId\"*\n" +
|
"\afile_id\x18\x01 \x01(\tR\x06fileId\"*\n" +
|
||||||
"\x0eDeleteResponse\x12\x18\n" +
|
"\x0eDeleteResponse\x12\x18\n" +
|
||||||
"\asuccess\x18\x01 \x01(\bR\asuccess2\xb1\x01\n" +
|
"\asuccess\x18\x01 \x01(\bR\asuccess*A\n" +
|
||||||
|
"\fImageVersion\x12\f\n" +
|
||||||
|
"\boriginal\x10\x00\x12\r\n" +
|
||||||
|
"\tthumbnail\x10\x01\x12\v\n" +
|
||||||
|
"\apreview\x10\x02\x12\a\n" +
|
||||||
|
"\x03all\x10\t2\x93\x02\n" +
|
||||||
"\x04File\x123\n" +
|
"\x04File\x123\n" +
|
||||||
"\x06Upload\x12\x13.file.UploadRequest\x1a\x14.file.UploadResponse\x12?\n" +
|
"\x06Upload\x12\x13.file.UploadRequest\x1a\x14.file.UploadResponse\x12?\n" +
|
||||||
"\n" +
|
"\n" +
|
||||||
"GetFileUrl\x12\x17.file.GetFileUrlRequest\x1a\x18.file.GetFileUrlResponse\x123\n" +
|
"GetFileUrl\x12\x17.file.GetFileUrlRequest\x1a\x18.file.GetFileUrlResponse\x123\n" +
|
||||||
"\x06Delete\x12\x13.file.DeleteRequest\x1a\x14.file.DeleteResponseB\bZ\x06./fileb\x06proto3"
|
"\x06Delete\x12\x13.file.DeleteRequest\x1a\x14.file.DeleteResponse\x12`\n" +
|
||||||
|
"\x15GenerateImageVersions\x12\".file.GenerateImageVersionsRequest\x1a#.file.GenerateImageVersionsResponseB\bZ\x06./fileb\x06proto3"
|
||||||
|
|
||||||
var (
|
var (
|
||||||
file_rpc_file_proto_rawDescOnce sync.Once
|
file_rpc_file_proto_rawDescOnce sync.Once
|
||||||
@ -362,27 +541,34 @@ func file_rpc_file_proto_rawDescGZIP() []byte {
|
|||||||
return file_rpc_file_proto_rawDescData
|
return file_rpc_file_proto_rawDescData
|
||||||
}
|
}
|
||||||
|
|
||||||
var file_rpc_file_proto_msgTypes = make([]protoimpl.MessageInfo, 6)
|
var file_rpc_file_proto_enumTypes = make([]protoimpl.EnumInfo, 1)
|
||||||
|
var file_rpc_file_proto_msgTypes = make([]protoimpl.MessageInfo, 8)
|
||||||
var file_rpc_file_proto_goTypes = []any{
|
var file_rpc_file_proto_goTypes = []any{
|
||||||
(*UploadRequest)(nil), // 0: file.UploadRequest
|
(ImageVersion)(0), // 0: file.ImageVersion
|
||||||
(*UploadResponse)(nil), // 1: file.UploadResponse
|
(*GenerateImageVersionsRequest)(nil), // 1: file.GenerateImageVersionsRequest
|
||||||
(*GetFileUrlRequest)(nil), // 2: file.GetFileUrlRequest
|
(*GenerateImageVersionsResponse)(nil), // 2: file.GenerateImageVersionsResponse
|
||||||
(*GetFileUrlResponse)(nil), // 3: file.GetFileUrlResponse
|
(*UploadRequest)(nil), // 3: file.UploadRequest
|
||||||
(*DeleteRequest)(nil), // 4: file.DeleteRequest
|
(*UploadResponse)(nil), // 4: file.UploadResponse
|
||||||
(*DeleteResponse)(nil), // 5: file.DeleteResponse
|
(*GetFileUrlRequest)(nil), // 5: file.GetFileUrlRequest
|
||||||
|
(*GetFileUrlResponse)(nil), // 6: file.GetFileUrlResponse
|
||||||
|
(*DeleteRequest)(nil), // 7: file.DeleteRequest
|
||||||
|
(*DeleteResponse)(nil), // 8: file.DeleteResponse
|
||||||
}
|
}
|
||||||
var file_rpc_file_proto_depIdxs = []int32{
|
var file_rpc_file_proto_depIdxs = []int32{
|
||||||
0, // 0: file.File.Upload:input_type -> file.UploadRequest
|
0, // 0: file.GenerateImageVersionsRequest.versions:type_name -> file.ImageVersion
|
||||||
2, // 1: file.File.GetFileUrl:input_type -> file.GetFileUrlRequest
|
3, // 1: file.File.Upload:input_type -> file.UploadRequest
|
||||||
4, // 2: file.File.Delete:input_type -> file.DeleteRequest
|
5, // 2: file.File.GetFileUrl:input_type -> file.GetFileUrlRequest
|
||||||
1, // 3: file.File.Upload:output_type -> file.UploadResponse
|
7, // 3: file.File.Delete:input_type -> file.DeleteRequest
|
||||||
3, // 4: file.File.GetFileUrl:output_type -> file.GetFileUrlResponse
|
1, // 4: file.File.GenerateImageVersions:input_type -> file.GenerateImageVersionsRequest
|
||||||
5, // 5: file.File.Delete:output_type -> file.DeleteResponse
|
4, // 5: file.File.Upload:output_type -> file.UploadResponse
|
||||||
3, // [3:6] is the sub-list for method output_type
|
6, // 6: file.File.GetFileUrl:output_type -> file.GetFileUrlResponse
|
||||||
0, // [0:3] is the sub-list for method input_type
|
8, // 7: file.File.Delete:output_type -> file.DeleteResponse
|
||||||
0, // [0:0] is the sub-list for extension type_name
|
2, // 8: file.File.GenerateImageVersions:output_type -> file.GenerateImageVersionsResponse
|
||||||
0, // [0:0] is the sub-list for extension extendee
|
5, // [5:9] is the sub-list for method output_type
|
||||||
0, // [0:0] is the sub-list for field type_name
|
1, // [1:5] is the sub-list for method input_type
|
||||||
|
1, // [1:1] is the sub-list for extension type_name
|
||||||
|
1, // [1:1] is the sub-list for extension extendee
|
||||||
|
0, // [0:1] is the sub-list for field type_name
|
||||||
}
|
}
|
||||||
|
|
||||||
func init() { file_rpc_file_proto_init() }
|
func init() { file_rpc_file_proto_init() }
|
||||||
@ -395,13 +581,14 @@ func file_rpc_file_proto_init() {
|
|||||||
File: protoimpl.DescBuilder{
|
File: protoimpl.DescBuilder{
|
||||||
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
|
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
|
||||||
RawDescriptor: unsafe.Slice(unsafe.StringData(file_rpc_file_proto_rawDesc), len(file_rpc_file_proto_rawDesc)),
|
RawDescriptor: unsafe.Slice(unsafe.StringData(file_rpc_file_proto_rawDesc), len(file_rpc_file_proto_rawDesc)),
|
||||||
NumEnums: 0,
|
NumEnums: 1,
|
||||||
NumMessages: 6,
|
NumMessages: 8,
|
||||||
NumExtensions: 0,
|
NumExtensions: 0,
|
||||||
NumServices: 1,
|
NumServices: 1,
|
||||||
},
|
},
|
||||||
GoTypes: file_rpc_file_proto_goTypes,
|
GoTypes: file_rpc_file_proto_goTypes,
|
||||||
DependencyIndexes: file_rpc_file_proto_depIdxs,
|
DependencyIndexes: file_rpc_file_proto_depIdxs,
|
||||||
|
EnumInfos: file_rpc_file_proto_enumTypes,
|
||||||
MessageInfos: file_rpc_file_proto_msgTypes,
|
MessageInfos: file_rpc_file_proto_msgTypes,
|
||||||
}.Build()
|
}.Build()
|
||||||
File_rpc_file_proto = out.File
|
File_rpc_file_proto = out.File
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
// Code generated by protoc-gen-go-grpc. DO NOT EDIT.
|
// Code generated by protoc-gen-go-grpc. DO NOT EDIT.
|
||||||
// versions:
|
// versions:
|
||||||
// - protoc-gen-go-grpc v1.5.1
|
// - protoc-gen-go-grpc v1.5.1
|
||||||
// - protoc v3.20.3
|
// - protoc v3.19.4
|
||||||
// source: rpc/file.proto
|
// source: rpc/file.proto
|
||||||
|
|
||||||
package file
|
package file
|
||||||
@ -19,9 +19,10 @@ import (
|
|||||||
const _ = grpc.SupportPackageIsVersion9
|
const _ = grpc.SupportPackageIsVersion9
|
||||||
|
|
||||||
const (
|
const (
|
||||||
File_Upload_FullMethodName = "/file.File/Upload"
|
File_Upload_FullMethodName = "/file.File/Upload"
|
||||||
File_GetFileUrl_FullMethodName = "/file.File/GetFileUrl"
|
File_GetFileUrl_FullMethodName = "/file.File/GetFileUrl"
|
||||||
File_Delete_FullMethodName = "/file.File/Delete"
|
File_Delete_FullMethodName = "/file.File/Delete"
|
||||||
|
File_GenerateImageVersions_FullMethodName = "/file.File/GenerateImageVersions"
|
||||||
)
|
)
|
||||||
|
|
||||||
// FileClient is the client API for File service.
|
// FileClient is the client API for File service.
|
||||||
@ -36,6 +37,8 @@ type FileClient interface {
|
|||||||
GetFileUrl(ctx context.Context, in *GetFileUrlRequest, opts ...grpc.CallOption) (*GetFileUrlResponse, error)
|
GetFileUrl(ctx context.Context, in *GetFileUrlRequest, opts ...grpc.CallOption) (*GetFileUrlResponse, error)
|
||||||
// 删除文件
|
// 删除文件
|
||||||
Delete(ctx context.Context, in *DeleteRequest, opts ...grpc.CallOption) (*DeleteResponse, error)
|
Delete(ctx context.Context, in *DeleteRequest, opts ...grpc.CallOption) (*DeleteResponse, error)
|
||||||
|
// 异步生成图片版本接口
|
||||||
|
GenerateImageVersions(ctx context.Context, in *GenerateImageVersionsRequest, opts ...grpc.CallOption) (*GenerateImageVersionsResponse, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
type fileClient struct {
|
type fileClient struct {
|
||||||
@ -76,6 +79,16 @@ func (c *fileClient) Delete(ctx context.Context, in *DeleteRequest, opts ...grpc
|
|||||||
return out, nil
|
return out, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *fileClient) GenerateImageVersions(ctx context.Context, in *GenerateImageVersionsRequest, opts ...grpc.CallOption) (*GenerateImageVersionsResponse, error) {
|
||||||
|
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
|
||||||
|
out := new(GenerateImageVersionsResponse)
|
||||||
|
err := c.cc.Invoke(ctx, File_GenerateImageVersions_FullMethodName, in, out, cOpts...)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return out, nil
|
||||||
|
}
|
||||||
|
|
||||||
// FileServer is the server API for File service.
|
// FileServer is the server API for File service.
|
||||||
// All implementations must embed UnimplementedFileServer
|
// All implementations must embed UnimplementedFileServer
|
||||||
// for forward compatibility.
|
// for forward compatibility.
|
||||||
@ -88,6 +101,8 @@ type FileServer interface {
|
|||||||
GetFileUrl(context.Context, *GetFileUrlRequest) (*GetFileUrlResponse, error)
|
GetFileUrl(context.Context, *GetFileUrlRequest) (*GetFileUrlResponse, error)
|
||||||
// 删除文件
|
// 删除文件
|
||||||
Delete(context.Context, *DeleteRequest) (*DeleteResponse, error)
|
Delete(context.Context, *DeleteRequest) (*DeleteResponse, error)
|
||||||
|
// 异步生成图片版本接口
|
||||||
|
GenerateImageVersions(context.Context, *GenerateImageVersionsRequest) (*GenerateImageVersionsResponse, error)
|
||||||
mustEmbedUnimplementedFileServer()
|
mustEmbedUnimplementedFileServer()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -107,6 +122,9 @@ func (UnimplementedFileServer) GetFileUrl(context.Context, *GetFileUrlRequest) (
|
|||||||
func (UnimplementedFileServer) Delete(context.Context, *DeleteRequest) (*DeleteResponse, error) {
|
func (UnimplementedFileServer) Delete(context.Context, *DeleteRequest) (*DeleteResponse, error) {
|
||||||
return nil, status.Errorf(codes.Unimplemented, "method Delete not implemented")
|
return nil, status.Errorf(codes.Unimplemented, "method Delete not implemented")
|
||||||
}
|
}
|
||||||
|
func (UnimplementedFileServer) GenerateImageVersions(context.Context, *GenerateImageVersionsRequest) (*GenerateImageVersionsResponse, error) {
|
||||||
|
return nil, status.Errorf(codes.Unimplemented, "method GenerateImageVersions not implemented")
|
||||||
|
}
|
||||||
func (UnimplementedFileServer) mustEmbedUnimplementedFileServer() {}
|
func (UnimplementedFileServer) mustEmbedUnimplementedFileServer() {}
|
||||||
func (UnimplementedFileServer) testEmbeddedByValue() {}
|
func (UnimplementedFileServer) testEmbeddedByValue() {}
|
||||||
|
|
||||||
@ -182,6 +200,24 @@ func _File_Delete_Handler(srv interface{}, ctx context.Context, dec func(interfa
|
|||||||
return interceptor(ctx, in, info, handler)
|
return interceptor(ctx, in, info, handler)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func _File_GenerateImageVersions_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||||
|
in := new(GenerateImageVersionsRequest)
|
||||||
|
if err := dec(in); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if interceptor == nil {
|
||||||
|
return srv.(FileServer).GenerateImageVersions(ctx, in)
|
||||||
|
}
|
||||||
|
info := &grpc.UnaryServerInfo{
|
||||||
|
Server: srv,
|
||||||
|
FullMethod: File_GenerateImageVersions_FullMethodName,
|
||||||
|
}
|
||||||
|
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||||
|
return srv.(FileServer).GenerateImageVersions(ctx, req.(*GenerateImageVersionsRequest))
|
||||||
|
}
|
||||||
|
return interceptor(ctx, in, info, handler)
|
||||||
|
}
|
||||||
|
|
||||||
// File_ServiceDesc is the grpc.ServiceDesc for File service.
|
// File_ServiceDesc is the grpc.ServiceDesc for File service.
|
||||||
// It's only intended for direct use with grpc.RegisterService,
|
// It's only intended for direct use with grpc.RegisterService,
|
||||||
// and not to be introspected or modified (even as a copy)
|
// and not to be introspected or modified (even as a copy)
|
||||||
@ -201,6 +237,10 @@ var File_ServiceDesc = grpc.ServiceDesc{
|
|||||||
MethodName: "Delete",
|
MethodName: "Delete",
|
||||||
Handler: _File_Delete_Handler,
|
Handler: _File_Delete_Handler,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
MethodName: "GenerateImageVersions",
|
||||||
|
Handler: _File_GenerateImageVersions_Handler,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
Streams: []grpc.StreamDesc{},
|
Streams: []grpc.StreamDesc{},
|
||||||
Metadata: "rpc/file.proto",
|
Metadata: "rpc/file.proto",
|
||||||
|
|||||||
@ -14,12 +14,14 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type (
|
type (
|
||||||
DeleteRequest = file.DeleteRequest
|
DeleteRequest = file.DeleteRequest
|
||||||
DeleteResponse = file.DeleteResponse
|
DeleteResponse = file.DeleteResponse
|
||||||
GetFileUrlRequest = file.GetFileUrlRequest
|
GenerateImageVersionsRequest = file.GenerateImageVersionsRequest
|
||||||
GetFileUrlResponse = file.GetFileUrlResponse
|
GenerateImageVersionsResponse = file.GenerateImageVersionsResponse
|
||||||
UploadRequest = file.UploadRequest
|
GetFileUrlRequest = file.GetFileUrlRequest
|
||||||
UploadResponse = file.UploadResponse
|
GetFileUrlResponse = file.GetFileUrlResponse
|
||||||
|
UploadRequest = file.UploadRequest
|
||||||
|
UploadResponse = file.UploadResponse
|
||||||
|
|
||||||
File interface {
|
File interface {
|
||||||
// 上传文件(图片/头像/壁纸等)
|
// 上传文件(图片/头像/壁纸等)
|
||||||
@ -28,6 +30,8 @@ type (
|
|||||||
GetFileUrl(ctx context.Context, in *GetFileUrlRequest, opts ...grpc.CallOption) (*GetFileUrlResponse, error)
|
GetFileUrl(ctx context.Context, in *GetFileUrlRequest, opts ...grpc.CallOption) (*GetFileUrlResponse, error)
|
||||||
// 删除文件
|
// 删除文件
|
||||||
Delete(ctx context.Context, in *DeleteRequest, opts ...grpc.CallOption) (*DeleteResponse, error)
|
Delete(ctx context.Context, in *DeleteRequest, opts ...grpc.CallOption) (*DeleteResponse, error)
|
||||||
|
// 异步生成图片版本接口
|
||||||
|
GenerateImageVersions(ctx context.Context, in *GenerateImageVersionsRequest, opts ...grpc.CallOption) (*GenerateImageVersionsResponse, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
defaultFile struct {
|
defaultFile struct {
|
||||||
@ -58,3 +62,9 @@ func (m *defaultFile) Delete(ctx context.Context, in *DeleteRequest, opts ...grp
|
|||||||
client := file.NewFileClient(m.cli.Conn())
|
client := file.NewFileClient(m.cli.Conn())
|
||||||
return client.Delete(ctx, in, opts...)
|
return client.Delete(ctx, in, opts...)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 异步生成图片版本接口
|
||||||
|
func (m *defaultFile) GenerateImageVersions(ctx context.Context, in *GenerateImageVersionsRequest, opts ...grpc.CallOption) (*GenerateImageVersionsResponse, error) {
|
||||||
|
client := file.NewFileClient(m.cli.Conn())
|
||||||
|
return client.GenerateImageVersions(ctx, in, opts...)
|
||||||
|
}
|
||||||
|
|||||||
49
file/internal/logic/generateimageversionslogic.go
Normal file
49
file/internal/logic/generateimageversionslogic.go
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
package logic
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"godemo/file/file"
|
||||||
|
"godemo/file/internal/svc"
|
||||||
|
"godemo/file/worker"
|
||||||
|
|
||||||
|
"github.com/google/uuid"
|
||||||
|
"github.com/zeromicro/go-zero/core/logx"
|
||||||
|
)
|
||||||
|
|
||||||
|
type GenerateImageVersionsLogic struct {
|
||||||
|
ctx context.Context
|
||||||
|
svcCtx *svc.ServiceContext
|
||||||
|
logx.Logger
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewGenerateImageVersionsLogic(ctx context.Context, svcCtx *svc.ServiceContext) *GenerateImageVersionsLogic {
|
||||||
|
return &GenerateImageVersionsLogic{
|
||||||
|
ctx: ctx,
|
||||||
|
svcCtx: svcCtx,
|
||||||
|
Logger: logx.WithContext(ctx),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 异步生成图片版本接口
|
||||||
|
func (l *GenerateImageVersionsLogic) GenerateImageVersions(in *file.GenerateImageVersionsRequest) (*file.GenerateImageVersionsResponse, error) {
|
||||||
|
// 1. 验证输入参数
|
||||||
|
|
||||||
|
// 2. 检查文件是否存在
|
||||||
|
|
||||||
|
// 3. 创建任务对象,并提交到任务队列
|
||||||
|
requestID := uuid.New().String()
|
||||||
|
worker.ImageProcessTaskQueue <- worker.ImageProcessTask{
|
||||||
|
FileID: in.FileId,
|
||||||
|
Versions: in.Versions,
|
||||||
|
RequestID: requestID,
|
||||||
|
CreatedAt: time.Now(),
|
||||||
|
}
|
||||||
|
|
||||||
|
// 4. 返回响应
|
||||||
|
return &file.GenerateImageVersionsResponse{
|
||||||
|
TaskId: requestID,
|
||||||
|
Accepted: true,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
@ -34,8 +34,8 @@ func NewUploadLogic(ctx context.Context, svcCtx *svc.ServiceContext) *UploadLogi
|
|||||||
// 上传文件(图片/头像/壁纸等)
|
// 上传文件(图片/头像/壁纸等)
|
||||||
func (l *UploadLogic) Upload(in *file.UploadRequest) (*file.UploadResponse, error) {
|
func (l *UploadLogic) Upload(in *file.UploadRequest) (*file.UploadResponse, error) {
|
||||||
bucketName := "default"
|
bucketName := "default"
|
||||||
if in.Folder != "" {
|
if in.Bucket != "" {
|
||||||
bucketName = in.Folder
|
bucketName = in.Bucket
|
||||||
}
|
}
|
||||||
|
|
||||||
// 确保 bucket 存在(自动创建)
|
// 确保 bucket 存在(自动创建)
|
||||||
@ -54,6 +54,10 @@ func (l *UploadLogic) Upload(in *file.UploadRequest) (*file.UploadResponse, erro
|
|||||||
ext := getFileExtension(in.Filename)
|
ext := getFileExtension(in.Filename)
|
||||||
newFileName := uuid.New().String() + ext
|
newFileName := uuid.New().String() + ext
|
||||||
|
|
||||||
|
if in.Folder != "" {
|
||||||
|
newFileName = in.Folder + "/" + newFileName
|
||||||
|
}
|
||||||
|
|
||||||
// 上传对象
|
// 上传对象
|
||||||
_, err = l.svcCtx.MinioClient.PutObject(l.ctx, bucketName, newFileName,
|
_, err = l.svcCtx.MinioClient.PutObject(l.ctx, bucketName, newFileName,
|
||||||
bytes.NewReader(in.Content),
|
bytes.NewReader(in.Content),
|
||||||
|
|||||||
@ -40,3 +40,9 @@ func (s *FileServer) Delete(ctx context.Context, in *file.DeleteRequest) (*file.
|
|||||||
l := logic.NewDeleteLogic(ctx, s.svcCtx)
|
l := logic.NewDeleteLogic(ctx, s.svcCtx)
|
||||||
return l.Delete(in)
|
return l.Delete(in)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 异步生成图片版本接口
|
||||||
|
func (s *FileServer) GenerateImageVersions(ctx context.Context, in *file.GenerateImageVersionsRequest) (*file.GenerateImageVersionsResponse, error) {
|
||||||
|
l := logic.NewGenerateImageVersionsLogic(ctx, s.svcCtx)
|
||||||
|
return l.GenerateImageVersions(in)
|
||||||
|
}
|
||||||
|
|||||||
196
file/worker/imageprocessworker.go
Normal file
196
file/worker/imageprocessworker.go
Normal file
@ -0,0 +1,196 @@
|
|||||||
|
package worker
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"context"
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"godemo/file/file"
|
||||||
|
"godemo/file/internal/svc"
|
||||||
|
"image"
|
||||||
|
"image/jpeg"
|
||||||
|
_ "image/png"
|
||||||
|
"io"
|
||||||
|
"strings"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/minio/minio-go/v7"
|
||||||
|
"github.com/zeromicro/go-zero/core/logx"
|
||||||
|
)
|
||||||
|
|
||||||
|
// 图片处理任务
|
||||||
|
type ImageProcessTask struct {
|
||||||
|
FileID string // 原始文件ID
|
||||||
|
Versions []file.ImageVersion // 需要生成的版本
|
||||||
|
RequestID string // 请求ID(用于追踪)
|
||||||
|
CreatedAt time.Time // 创建时间
|
||||||
|
}
|
||||||
|
|
||||||
|
var ImageProcessTaskQueue chan ImageProcessTask
|
||||||
|
|
||||||
|
func InitImageProcessTaskQueue(bufferSize int) {
|
||||||
|
ImageProcessTaskQueue = make(chan ImageProcessTask, bufferSize)
|
||||||
|
}
|
||||||
|
|
||||||
|
func StartImageProcessWorkers(workerCount int, svcCtx *svc.ServiceContext) {
|
||||||
|
for i := 0; i < workerCount; i++ {
|
||||||
|
go func(workerID int) {
|
||||||
|
for task := range ImageProcessTaskQueue {
|
||||||
|
logx.Infof("Worker %d processing task for FileID: %s", workerID, task.FileID)
|
||||||
|
if err := processImage(task, svcCtx); err != nil {
|
||||||
|
logx.Errorf("Worker %d failed to process FileID: %s, err: %v", workerID, task.FileID, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}(i)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func processImage(task ImageProcessTask, svcCtx *svc.ServiceContext) error {
|
||||||
|
// 加载原始图片(示意,假设你实现了这类方法)
|
||||||
|
originalImage, err := LoadImageFromMinIO(svcCtx.MinioClient, task.FileID, file.ImageVersion_original)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// 如果是 ALL,则转化成 THUMBNAIL + PREVIEW
|
||||||
|
versions := task.Versions
|
||||||
|
if len(versions) == 1 && versions[0] == file.ImageVersion_all {
|
||||||
|
versions = []file.ImageVersion{file.ImageVersion_thumbnail, file.ImageVersion_preview}
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, version := range versions {
|
||||||
|
switch version {
|
||||||
|
case file.ImageVersion_thumbnail:
|
||||||
|
err := generateAndUpload(originalImage, task.FileID, file.ImageVersion_thumbnail, svcCtx)
|
||||||
|
if err != nil {
|
||||||
|
logx.Errorf("Generate thumbnail failed: %v", err)
|
||||||
|
}
|
||||||
|
case file.ImageVersion_preview:
|
||||||
|
err := generateAndUpload(originalImage, task.FileID, file.ImageVersion_preview, svcCtx)
|
||||||
|
if err != nil {
|
||||||
|
logx.Errorf("Generate preview failed: %v", err)
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
logx.Infof("Unsupported image version: %v", version)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func generateAndUpload(originalImage []byte, fileID string, version file.ImageVersion, svcCtx *svc.ServiceContext) error {
|
||||||
|
// 示例尺寸(你可以从配置或常量读取)
|
||||||
|
var width, height int
|
||||||
|
switch version {
|
||||||
|
case file.ImageVersion_thumbnail:
|
||||||
|
width, height = 150, 150
|
||||||
|
case file.ImageVersion_preview:
|
||||||
|
width, height = 800, 600
|
||||||
|
}
|
||||||
|
|
||||||
|
// resize(伪代码:请换成你自己的图像处理库,如 imaging)
|
||||||
|
resizedImage, err := ResizeImage(originalImage, width, height)
|
||||||
|
if err != nil {
|
||||||
|
logx.Errorf("generateAndUpload failed: %v", err)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// 上传到 MinIO
|
||||||
|
return UploadImageToMinIO(svcCtx.MinioClient, fileID, version, resizedImage)
|
||||||
|
}
|
||||||
|
|
||||||
|
func LoadImageFromMinIO(client *minio.Client, fileID string, version file.ImageVersion) ([]byte, error) {
|
||||||
|
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
|
||||||
|
defer cancel()
|
||||||
|
|
||||||
|
bucket, objectKey, _ := GetBucketAndObjectKey(fileID, version)
|
||||||
|
|
||||||
|
object, err := client.GetObject(ctx, bucket, objectKey, minio.GetObjectOptions{})
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("failed to get object from MinIO: %w", err)
|
||||||
|
}
|
||||||
|
defer object.Close()
|
||||||
|
|
||||||
|
buf := new(bytes.Buffer)
|
||||||
|
if _, err := io.Copy(buf, object); err != nil {
|
||||||
|
return nil, fmt.Errorf("failed to read object: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return buf.Bytes(), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetBucketAndObjectKey(fileId string, version file.ImageVersion) (string, string, error) {
|
||||||
|
bucket := version.String()
|
||||||
|
objectKey := fileId
|
||||||
|
if version == file.ImageVersion_original {
|
||||||
|
// fileID = xx/yy/cc/ll.png 获取第一段作为bucket
|
||||||
|
bucket, objectKey, _ = GetBucketAndObjectKeyFromFileID(fileId)
|
||||||
|
}
|
||||||
|
return bucket, objectKey, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetBucketAndObjectKeyFromFileID(fileID string) (string, string, error) {
|
||||||
|
idx := strings.Index(fileID, "/")
|
||||||
|
if idx == -1 {
|
||||||
|
return "", "", fmt.Errorf("invalid fileID: %s", fileID)
|
||||||
|
}
|
||||||
|
return fileID[:idx], fileID[idx+1:], nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func ResizeImage(original []byte, width, height int) ([]byte, error) {
|
||||||
|
img, _, err := image.Decode(bytes.NewReader(original))
|
||||||
|
if err != nil {
|
||||||
|
logx.Errorf("ResizeImage failed: %v", err)
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
srcBounds := img.Bounds()
|
||||||
|
srcWidth := srcBounds.Dx()
|
||||||
|
srcHeight := srcBounds.Dy()
|
||||||
|
|
||||||
|
if srcWidth == 0 || srcHeight == 0 {
|
||||||
|
return nil, errors.New("source image has zero size")
|
||||||
|
}
|
||||||
|
|
||||||
|
// 创建缩放后的图像(RGBA 格式)
|
||||||
|
dst := image.NewRGBA(image.Rect(0, 0, width, height))
|
||||||
|
|
||||||
|
// 最近邻缩放
|
||||||
|
for y := 0; y < height; y++ {
|
||||||
|
for x := 0; x < width; x++ {
|
||||||
|
srcX := x * srcWidth / width
|
||||||
|
srcY := y * srcHeight / height
|
||||||
|
color := img.At(srcX+srcBounds.Min.X, srcY+srcBounds.Min.Y)
|
||||||
|
dst.Set(x, y, color)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 编码为 JPEG
|
||||||
|
var buf bytes.Buffer
|
||||||
|
err = jpeg.Encode(&buf, dst, &jpeg.Options{Quality: 85})
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return buf.Bytes(), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func UploadImageToMinIO(client *minio.Client, fileID string, version file.ImageVersion, data []byte) error {
|
||||||
|
bucket, objectKey, err := GetBucketAndObjectKey(fileID, version)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
|
||||||
|
defer cancel()
|
||||||
|
|
||||||
|
_, err = client.PutObject(ctx, bucket, objectKey, bytes.NewReader(data), int64(len(data)), minio.PutObjectOptions{
|
||||||
|
ContentType: "image/jpeg",
|
||||||
|
})
|
||||||
|
logx.Infof("Uploaded image to MinIO: %s/%s", bucket, objectKey)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("upload to MinIO failed: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
@ -1,5 +1,13 @@
|
|||||||
Name: gallery.rpc
|
Name: gallery.rpc
|
||||||
ListenOn: 0.0.0.0:50000
|
ListenOn: 0.0.0.0:50000
|
||||||
|
Mode: dev
|
||||||
|
|
||||||
|
DB:
|
||||||
|
DataSource: postgres://postgres:postgres@localhost:19732/godemo?sslmode=disable
|
||||||
|
MaxOpenConns: 100
|
||||||
|
MaxIdleConns: 20
|
||||||
|
ConnMaxLifetime: 3600
|
||||||
|
|
||||||
Etcd:
|
Etcd:
|
||||||
Hosts:
|
Hosts:
|
||||||
- 127.0.0.1:2379
|
- 127.0.0.1:2379
|
||||||
@ -10,3 +18,22 @@ FileRpc:
|
|||||||
Hosts:
|
Hosts:
|
||||||
- 127.0.0.1:2379
|
- 127.0.0.1:2379
|
||||||
Key: file.rpc
|
Key: file.rpc
|
||||||
|
|
||||||
|
CategoryRpc:
|
||||||
|
Etcd:
|
||||||
|
Hosts:
|
||||||
|
- 127.0.0.1:2379
|
||||||
|
Key: category.rpc
|
||||||
|
|
||||||
|
BucketName: gallery
|
||||||
|
|
||||||
|
Log:
|
||||||
|
ServiceName: gallery-rpc-service
|
||||||
|
Mode: console # 日志输出模式,支持 console 和 file
|
||||||
|
Encoding: plain # 日志格式,支持 json 和 plain
|
||||||
|
Path: ./logs
|
||||||
|
Level: debug # 日志等级,支持 debug,info,error,severe
|
||||||
|
MaxSize: 10 # MB
|
||||||
|
KeepDays: 30 # 天
|
||||||
|
MaxBackups: 3
|
||||||
|
Compress: false
|
||||||
|
|||||||
@ -2,7 +2,6 @@ package main
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"flag"
|
"flag"
|
||||||
"fmt"
|
|
||||||
|
|
||||||
"godemo/gallery/gallery"
|
"godemo/gallery/gallery"
|
||||||
"godemo/gallery/internal/config"
|
"godemo/gallery/internal/config"
|
||||||
@ -10,6 +9,7 @@ import (
|
|||||||
"godemo/gallery/internal/svc"
|
"godemo/gallery/internal/svc"
|
||||||
|
|
||||||
"github.com/zeromicro/go-zero/core/conf"
|
"github.com/zeromicro/go-zero/core/conf"
|
||||||
|
"github.com/zeromicro/go-zero/core/logx"
|
||||||
"github.com/zeromicro/go-zero/core/service"
|
"github.com/zeromicro/go-zero/core/service"
|
||||||
"github.com/zeromicro/go-zero/zrpc"
|
"github.com/zeromicro/go-zero/zrpc"
|
||||||
"google.golang.org/grpc"
|
"google.golang.org/grpc"
|
||||||
@ -34,6 +34,6 @@ func main() {
|
|||||||
})
|
})
|
||||||
defer s.Stop()
|
defer s.Stop()
|
||||||
|
|
||||||
fmt.Printf("Starting rpc server at %s...\n", c.ListenOn)
|
logx.Infof("Starting rpc server at %s...", c.ListenOn)
|
||||||
s.Start()
|
s.Start()
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,8 +1,18 @@
|
|||||||
package config
|
package config
|
||||||
|
|
||||||
import "github.com/zeromicro/go-zero/zrpc"
|
import (
|
||||||
|
"github.com/zeromicro/go-zero/zrpc"
|
||||||
|
)
|
||||||
|
|
||||||
type Config struct {
|
type Config struct {
|
||||||
zrpc.RpcServerConf
|
zrpc.RpcServerConf
|
||||||
FileRpc zrpc.RpcClientConf
|
FileRpc zrpc.RpcClientConf
|
||||||
|
CategoryRpc zrpc.RpcClientConf
|
||||||
|
DB struct {
|
||||||
|
DataSource string
|
||||||
|
MaxOpenConns int
|
||||||
|
MaxIdleConns int
|
||||||
|
ConnMaxLifetime int
|
||||||
|
}
|
||||||
|
BucketName string
|
||||||
}
|
}
|
||||||
|
|||||||
@ -2,12 +2,19 @@ package logic
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"database/sql"
|
||||||
|
|
||||||
|
"godemo/category/category"
|
||||||
"godemo/file/file"
|
"godemo/file/file"
|
||||||
"godemo/gallery/gallery"
|
"godemo/gallery/gallery"
|
||||||
|
"godemo/gallery/internal/model"
|
||||||
"godemo/gallery/internal/svc"
|
"godemo/gallery/internal/svc"
|
||||||
|
|
||||||
|
"github.com/google/uuid"
|
||||||
|
"github.com/zeromicro/go-zero/core/logc"
|
||||||
"github.com/zeromicro/go-zero/core/logx"
|
"github.com/zeromicro/go-zero/core/logx"
|
||||||
|
"google.golang.org/grpc/codes"
|
||||||
|
"google.golang.org/grpc/status"
|
||||||
)
|
)
|
||||||
|
|
||||||
type UploadImageLogic struct {
|
type UploadImageLogic struct {
|
||||||
@ -27,17 +34,48 @@ func NewUploadImageLogic(ctx context.Context, svcCtx *svc.ServiceContext) *Uploa
|
|||||||
// 图片上传
|
// 图片上传
|
||||||
func (l *UploadImageLogic) UploadImage(in *gallery.UploadImageRequest) (*gallery.UploadImageResponse, error) {
|
func (l *UploadImageLogic) UploadImage(in *gallery.UploadImageRequest) (*gallery.UploadImageResponse, error) {
|
||||||
// 1. 根据 in.CategoryId 查询分类信息,获取分类名称
|
// 1. 根据 in.CategoryId 查询分类信息,获取分类名称
|
||||||
var categoryName string
|
getFullCategoryRpcResp, getFullCategoryRpcErr := l.svcCtx.CategoryRpc.GetFullCategories(l.ctx, &category.GetCategoryRequest{
|
||||||
|
Id: *in.CategoryId,
|
||||||
|
})
|
||||||
|
if getFullCategoryRpcErr != nil {
|
||||||
|
return nil, status.Error(codes.Internal, getFullCategoryRpcErr.Error())
|
||||||
|
}
|
||||||
|
|
||||||
// 2. 调用 file rpc Upload 接口,上传文件到MinIO
|
// 2. 调用 file rpc Upload 接口,上传文件到MinIO
|
||||||
l.svcCtx.FileRpc.Upload(l.ctx, &file.UploadRequest{
|
fileUploadRpcResp, fileUploadRpcErr := l.svcCtx.FileRpc.Upload(l.ctx, &file.UploadRequest{
|
||||||
Filename: in.FileName,
|
Filename: in.FileName,
|
||||||
Content: in.FileContent,
|
Content: in.FileContent,
|
||||||
Folder: categoryName,
|
Folder: getFullCategoryRpcResp.FullCategoryName,
|
||||||
|
Bucket: l.svcCtx.Config.BucketName,
|
||||||
})
|
})
|
||||||
|
if fileUploadRpcErr != nil {
|
||||||
|
return nil, status.Error(codes.Internal, fileUploadRpcErr.Error())
|
||||||
|
}
|
||||||
|
|
||||||
// 3. 图片信息存入数据库
|
// 3. 图片信息存入数据库
|
||||||
|
storageKey := l.svcCtx.Config.BucketName + "/" + fileUploadRpcResp.FileId
|
||||||
|
insertResult, insertErr := l.svcCtx.ImagesModel.Insert(l.ctx, &model.Images{
|
||||||
|
ImageId: uuid.New().String(),
|
||||||
|
StorageKey: storageKey,
|
||||||
|
FileName: *in.Title,
|
||||||
|
MimeType: "image/jpeg",
|
||||||
|
FileSize: 10,
|
||||||
|
CategoryId: sql.NullString{String: *in.CategoryId, Valid: true},
|
||||||
|
})
|
||||||
|
if insertErr != nil {
|
||||||
|
return nil, status.Error(codes.Internal, insertErr.Error())
|
||||||
|
}
|
||||||
|
logc.Infof(l.ctx, "insertResult: %v", insertResult)
|
||||||
|
|
||||||
// 4. 返回接口执行结果
|
// 4. 调用 file rpc GenerateImageVersions 接口,生成缩略图和预览图 (异步)
|
||||||
|
_, generateImageVersionsRpcErr := l.svcCtx.FileRpc.GenerateImageVersions(l.ctx, &file.GenerateImageVersionsRequest{
|
||||||
|
FileId: storageKey,
|
||||||
|
Versions: []file.ImageVersion{file.ImageVersion_thumbnail, file.ImageVersion_preview},
|
||||||
|
})
|
||||||
|
if generateImageVersionsRpcErr != nil {
|
||||||
|
return nil, status.Error(codes.Internal, generateImageVersionsRpcErr.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
// 5. 返回接口执行结果
|
||||||
return &gallery.UploadImageResponse{}, nil
|
return &gallery.UploadImageResponse{}, nil
|
||||||
}
|
}
|
||||||
|
|||||||
29
gallery/internal/model/imagesmodel.go
Normal file
29
gallery/internal/model/imagesmodel.go
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
package model
|
||||||
|
|
||||||
|
import "github.com/zeromicro/go-zero/core/stores/sqlx"
|
||||||
|
|
||||||
|
var _ ImagesModel = (*customImagesModel)(nil)
|
||||||
|
|
||||||
|
type (
|
||||||
|
// ImagesModel is an interface to be customized, add more methods here,
|
||||||
|
// and implement the added methods in customImagesModel.
|
||||||
|
ImagesModel interface {
|
||||||
|
imagesModel
|
||||||
|
withSession(session sqlx.Session) ImagesModel
|
||||||
|
}
|
||||||
|
|
||||||
|
customImagesModel struct {
|
||||||
|
*defaultImagesModel
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
// NewImagesModel returns a model for the database table.
|
||||||
|
func NewImagesModel(conn sqlx.SqlConn) ImagesModel {
|
||||||
|
return &customImagesModel{
|
||||||
|
defaultImagesModel: newImagesModel(conn),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *customImagesModel) withSession(session sqlx.Session) ImagesModel {
|
||||||
|
return NewImagesModel(sqlx.NewSqlConnFromSession(session))
|
||||||
|
}
|
||||||
97
gallery/internal/model/imagesmodel_gen.go
Normal file
97
gallery/internal/model/imagesmodel_gen.go
Normal file
@ -0,0 +1,97 @@
|
|||||||
|
// Code generated by goctl. DO NOT EDIT.
|
||||||
|
// versions:
|
||||||
|
// goctl version: 1.8.3
|
||||||
|
|
||||||
|
package model
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"database/sql"
|
||||||
|
"fmt"
|
||||||
|
"strings"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/lib/pq"
|
||||||
|
"github.com/zeromicro/go-zero/core/stores/builder"
|
||||||
|
"github.com/zeromicro/go-zero/core/stores/sqlx"
|
||||||
|
"github.com/zeromicro/go-zero/core/stringx"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
imagesFieldNames = builder.RawFieldNames(&Images{}, true)
|
||||||
|
imagesRows = strings.Join(imagesFieldNames, ",")
|
||||||
|
imagesRowsExpectAutoSet = strings.Join(stringx.Remove(imagesFieldNames, "create_at", "create_time", "created_at", "update_at", "update_time", "updated_at"), ",")
|
||||||
|
imagesRowsWithPlaceHolder = builder.PostgreSqlJoin(stringx.Remove(imagesFieldNames, "image_id", "create_at", "create_time", "created_at", "update_at", "update_time", "updated_at"))
|
||||||
|
)
|
||||||
|
|
||||||
|
type (
|
||||||
|
imagesModel interface {
|
||||||
|
Insert(ctx context.Context, data *Images) (sql.Result, error)
|
||||||
|
FindOne(ctx context.Context, imageId string) (*Images, error)
|
||||||
|
Update(ctx context.Context, data *Images) error
|
||||||
|
Delete(ctx context.Context, imageId string) error
|
||||||
|
}
|
||||||
|
|
||||||
|
defaultImagesModel struct {
|
||||||
|
conn sqlx.SqlConn
|
||||||
|
table string
|
||||||
|
}
|
||||||
|
|
||||||
|
Images struct {
|
||||||
|
ImageId string `db:"image_id"`
|
||||||
|
StorageKey string `db:"storage_key"`
|
||||||
|
FileName string `db:"file_name"`
|
||||||
|
MimeType string `db:"mime_type"`
|
||||||
|
FileSize int64 `db:"file_size"`
|
||||||
|
Width sql.NullInt64 `db:"width"`
|
||||||
|
Height sql.NullInt64 `db:"height"`
|
||||||
|
CategoryId sql.NullString `db:"category_id"`
|
||||||
|
Tags pq.StringArray `db:"tags"`
|
||||||
|
CreatedAt time.Time `db:"created_at"`
|
||||||
|
UpdatedAt time.Time `db:"updated_at"`
|
||||||
|
IsDeleted bool `db:"is_deleted"`
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
func newImagesModel(conn sqlx.SqlConn) *defaultImagesModel {
|
||||||
|
return &defaultImagesModel{
|
||||||
|
conn: conn,
|
||||||
|
table: `"public"."images"`,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *defaultImagesModel) Delete(ctx context.Context, imageId string) error {
|
||||||
|
query := fmt.Sprintf("delete from %s where image_id = $1", m.table)
|
||||||
|
_, err := m.conn.ExecCtx(ctx, query, imageId)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *defaultImagesModel) FindOne(ctx context.Context, imageId string) (*Images, error) {
|
||||||
|
query := fmt.Sprintf("select %s from %s where image_id = $1 limit 1", imagesRows, m.table)
|
||||||
|
var resp Images
|
||||||
|
err := m.conn.QueryRowCtx(ctx, &resp, query, imageId)
|
||||||
|
switch err {
|
||||||
|
case nil:
|
||||||
|
return &resp, nil
|
||||||
|
case sqlx.ErrNotFound:
|
||||||
|
return nil, ErrNotFound
|
||||||
|
default:
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *defaultImagesModel) Insert(ctx context.Context, data *Images) (sql.Result, error) {
|
||||||
|
query := fmt.Sprintf("insert into %s (%s) values ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10)", m.table, imagesRowsExpectAutoSet)
|
||||||
|
ret, err := m.conn.ExecCtx(ctx, query, data.ImageId, data.StorageKey, data.FileName, data.MimeType, data.FileSize, data.Width, data.Height, data.CategoryId, data.Tags, data.IsDeleted)
|
||||||
|
return ret, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *defaultImagesModel) Update(ctx context.Context, data *Images) error {
|
||||||
|
query := fmt.Sprintf("update %s set %s where image_id = $1", m.table, imagesRowsWithPlaceHolder)
|
||||||
|
_, err := m.conn.ExecCtx(ctx, query, data.ImageId, data.StorageKey, data.FileName, data.MimeType, data.FileSize, data.Width, data.Height, data.CategoryId, data.Tags, data.IsDeleted)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *defaultImagesModel) tableName() string {
|
||||||
|
return m.table
|
||||||
|
}
|
||||||
5
gallery/internal/model/vars.go
Normal file
5
gallery/internal/model/vars.go
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
package model
|
||||||
|
|
||||||
|
import "github.com/zeromicro/go-zero/core/stores/sqlx"
|
||||||
|
|
||||||
|
var ErrNotFound = sqlx.ErrNotFound
|
||||||
@ -1,21 +1,28 @@
|
|||||||
package svc
|
package svc
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"godemo/category/category"
|
||||||
"godemo/file/file"
|
"godemo/file/file"
|
||||||
"godemo/gallery/internal/config"
|
"godemo/gallery/internal/config"
|
||||||
|
"godemo/gallery/internal/model"
|
||||||
|
|
||||||
|
_ "github.com/lib/pq"
|
||||||
|
"github.com/zeromicro/go-zero/core/stores/sqlx"
|
||||||
"github.com/zeromicro/go-zero/zrpc"
|
"github.com/zeromicro/go-zero/zrpc"
|
||||||
)
|
)
|
||||||
|
|
||||||
type ServiceContext struct {
|
type ServiceContext struct {
|
||||||
Config config.Config
|
Config config.Config
|
||||||
FileRpc file.FileClient
|
FileRpc file.FileClient
|
||||||
|
CategoryRpc category.CategoryClient
|
||||||
|
ImagesModel model.ImagesModel
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewServiceContext(c config.Config) *ServiceContext {
|
func NewServiceContext(c config.Config) *ServiceContext {
|
||||||
conn := zrpc.MustNewClient(c.FileRpc).Conn()
|
|
||||||
return &ServiceContext{
|
return &ServiceContext{
|
||||||
Config: c,
|
Config: c,
|
||||||
FileRpc: file.NewFileClient(conn),
|
FileRpc: file.NewFileClient(zrpc.MustNewClient(c.FileRpc).Conn()),
|
||||||
|
CategoryRpc: category.NewCategoryClient(zrpc.MustNewClient(c.CategoryRpc).Conn()),
|
||||||
|
ImagesModel: model.NewImagesModel(sqlx.NewSqlConn("postgres", c.DB.DataSource)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -11,3 +11,9 @@ UserRpc:
|
|||||||
Hosts:
|
Hosts:
|
||||||
- 127.0.0.1:2379
|
- 127.0.0.1:2379
|
||||||
Key: user.rpc
|
Key: user.rpc
|
||||||
|
|
||||||
|
CategoryRpc:
|
||||||
|
Etcd:
|
||||||
|
Hosts:
|
||||||
|
- 127.0.0.1:2379
|
||||||
|
Key: category.rpc
|
||||||
@ -11,5 +11,6 @@ type Config struct {
|
|||||||
AccessSecret string
|
AccessSecret string
|
||||||
AccessExpire int64
|
AccessExpire int64
|
||||||
}
|
}
|
||||||
UserRpc zrpc.RpcClientConf
|
UserRpc zrpc.RpcClientConf
|
||||||
|
CategoryRpc zrpc.RpcClientConf
|
||||||
}
|
}
|
||||||
|
|||||||
50
gateway/internal/handler/createcategoryhandler.go
Normal file
50
gateway/internal/handler/createcategoryhandler.go
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
package handler
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
"godemo/gateway/internal/logic"
|
||||||
|
"godemo/gateway/internal/svc"
|
||||||
|
"godemo/gateway/internal/types"
|
||||||
|
|
||||||
|
"github.com/zeromicro/go-zero/rest/httpx"
|
||||||
|
"google.golang.org/grpc/codes"
|
||||||
|
"google.golang.org/grpc/status"
|
||||||
|
)
|
||||||
|
|
||||||
|
func createCategoryHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
|
||||||
|
return func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
var req types.CreateCategoryReq
|
||||||
|
if err := httpx.Parse(r, &req); err != nil {
|
||||||
|
httpx.ErrorCtx(r.Context(), w, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
l := logic.NewCreateCategoryLogic(r.Context(), svcCtx)
|
||||||
|
resp, err := l.CreateCategory(&req)
|
||||||
|
if err != nil {
|
||||||
|
if s, ok := status.FromError(err); ok {
|
||||||
|
// 判断 gRPC 错误码,并自定义 HTTP 返回
|
||||||
|
var code int
|
||||||
|
switch s.Code() {
|
||||||
|
case codes.NotFound:
|
||||||
|
code = http.StatusNotFound
|
||||||
|
case codes.InvalidArgument:
|
||||||
|
code = http.StatusBadRequest
|
||||||
|
default:
|
||||||
|
code = http.StatusInternalServerError
|
||||||
|
}
|
||||||
|
|
||||||
|
// 自定义 JSON 错误格式
|
||||||
|
httpx.WriteJson(w, code, map[string]interface{}{
|
||||||
|
"code": code,
|
||||||
|
"message": s.Message(),
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
httpx.ErrorCtx(r.Context(), w, err)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
httpx.OkJsonCtx(r.Context(), w, resp)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
28
gateway/internal/handler/deletecategoryhandler.go
Normal file
28
gateway/internal/handler/deletecategoryhandler.go
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
package handler
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
"github.com/zeromicro/go-zero/rest/httpx"
|
||||||
|
"godemo/gateway/internal/logic"
|
||||||
|
"godemo/gateway/internal/svc"
|
||||||
|
"godemo/gateway/internal/types"
|
||||||
|
)
|
||||||
|
|
||||||
|
func deleteCategoryHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
|
||||||
|
return func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
var req types.DeleteCategoryReq
|
||||||
|
if err := httpx.Parse(r, &req); err != nil {
|
||||||
|
httpx.ErrorCtx(r.Context(), w, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
l := logic.NewDeleteCategoryLogic(r.Context(), svcCtx)
|
||||||
|
resp, err := l.DeleteCategory(&req)
|
||||||
|
if err != nil {
|
||||||
|
httpx.ErrorCtx(r.Context(), w, err)
|
||||||
|
} else {
|
||||||
|
httpx.OkJsonCtx(r.Context(), w, resp)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
28
gateway/internal/handler/getcategoryhandler.go
Normal file
28
gateway/internal/handler/getcategoryhandler.go
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
package handler
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
"github.com/zeromicro/go-zero/rest/httpx"
|
||||||
|
"godemo/gateway/internal/logic"
|
||||||
|
"godemo/gateway/internal/svc"
|
||||||
|
"godemo/gateway/internal/types"
|
||||||
|
)
|
||||||
|
|
||||||
|
func getCategoryHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
|
||||||
|
return func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
var req types.GetCategoryReq
|
||||||
|
if err := httpx.Parse(r, &req); err != nil {
|
||||||
|
httpx.ErrorCtx(r.Context(), w, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
l := logic.NewGetCategoryLogic(r.Context(), svcCtx)
|
||||||
|
resp, err := l.GetCategory(&req)
|
||||||
|
if err != nil {
|
||||||
|
httpx.ErrorCtx(r.Context(), w, err)
|
||||||
|
} else {
|
||||||
|
httpx.OkJsonCtx(r.Context(), w, resp)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
28
gateway/internal/handler/getcategorytreehandler.go
Normal file
28
gateway/internal/handler/getcategorytreehandler.go
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
package handler
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
"github.com/zeromicro/go-zero/rest/httpx"
|
||||||
|
"godemo/gateway/internal/logic"
|
||||||
|
"godemo/gateway/internal/svc"
|
||||||
|
"godemo/gateway/internal/types"
|
||||||
|
)
|
||||||
|
|
||||||
|
func getCategoryTreeHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
|
||||||
|
return func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
var req types.GetCategoryTreeReq
|
||||||
|
if err := httpx.Parse(r, &req); err != nil {
|
||||||
|
httpx.ErrorCtx(r.Context(), w, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
l := logic.NewGetCategoryTreeLogic(r.Context(), svcCtx)
|
||||||
|
resp, err := l.GetCategoryTree(&req)
|
||||||
|
if err != nil {
|
||||||
|
httpx.ErrorCtx(r.Context(), w, err)
|
||||||
|
} else {
|
||||||
|
httpx.OkJsonCtx(r.Context(), w, resp)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
28
gateway/internal/handler/getsystemcategorieshandler.go
Normal file
28
gateway/internal/handler/getsystemcategorieshandler.go
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
package handler
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
"github.com/zeromicro/go-zero/rest/httpx"
|
||||||
|
"godemo/gateway/internal/logic"
|
||||||
|
"godemo/gateway/internal/svc"
|
||||||
|
"godemo/gateway/internal/types"
|
||||||
|
)
|
||||||
|
|
||||||
|
func getSystemCategoriesHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
|
||||||
|
return func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
var req types.GetSystemCategoriesReq
|
||||||
|
if err := httpx.Parse(r, &req); err != nil {
|
||||||
|
httpx.ErrorCtx(r.Context(), w, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
l := logic.NewGetSystemCategoriesLogic(r.Context(), svcCtx)
|
||||||
|
resp, err := l.GetSystemCategories(&req)
|
||||||
|
if err != nil {
|
||||||
|
httpx.ErrorCtx(r.Context(), w, err)
|
||||||
|
} else {
|
||||||
|
httpx.OkJsonCtx(r.Context(), w, resp)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
28
gateway/internal/handler/listcategorieshandler.go
Normal file
28
gateway/internal/handler/listcategorieshandler.go
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
package handler
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
"github.com/zeromicro/go-zero/rest/httpx"
|
||||||
|
"godemo/gateway/internal/logic"
|
||||||
|
"godemo/gateway/internal/svc"
|
||||||
|
"godemo/gateway/internal/types"
|
||||||
|
)
|
||||||
|
|
||||||
|
func listCategoriesHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
|
||||||
|
return func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
var req types.ListCategoriesReq
|
||||||
|
if err := httpx.Parse(r, &req); err != nil {
|
||||||
|
httpx.ErrorCtx(r.Context(), w, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
l := logic.NewListCategoriesLogic(r.Context(), svcCtx)
|
||||||
|
resp, err := l.ListCategories(&req)
|
||||||
|
if err != nil {
|
||||||
|
httpx.ErrorCtx(r.Context(), w, err)
|
||||||
|
} else {
|
||||||
|
httpx.OkJsonCtx(r.Context(), w, resp)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -16,30 +16,67 @@ func RegisterHandlers(server *rest.Server, serverCtx *svc.ServiceContext) {
|
|||||||
[]rest.Route{
|
[]rest.Route{
|
||||||
{
|
{
|
||||||
Method: http.MethodPost,
|
Method: http.MethodPost,
|
||||||
Path: "/api/user/login",
|
Path: "/user/login",
|
||||||
Handler: loginHandler(serverCtx),
|
Handler: loginHandler(serverCtx),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Method: http.MethodPost,
|
Method: http.MethodPost,
|
||||||
Path: "/api/user/register",
|
Path: "/user/register",
|
||||||
Handler: registerHandler(serverCtx),
|
Handler: registerHandler(serverCtx),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
rest.WithPrefix("/api"),
|
||||||
)
|
)
|
||||||
|
|
||||||
server.AddRoutes(
|
server.AddRoutes(
|
||||||
[]rest.Route{
|
[]rest.Route{
|
||||||
|
{
|
||||||
|
Method: http.MethodPost,
|
||||||
|
Path: "/category/v1",
|
||||||
|
Handler: createCategoryHandler(serverCtx),
|
||||||
|
},
|
||||||
{
|
{
|
||||||
Method: http.MethodGet,
|
Method: http.MethodGet,
|
||||||
Path: "/api/user/:user_id",
|
Path: "/category/v1",
|
||||||
|
Handler: listCategoriesHandler(serverCtx),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Method: http.MethodGet,
|
||||||
|
Path: "/category/v1/:id",
|
||||||
|
Handler: getCategoryHandler(serverCtx),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Method: http.MethodPut,
|
||||||
|
Path: "/category/v1/:id",
|
||||||
|
Handler: updateCategoryHandler(serverCtx),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Method: http.MethodDelete,
|
||||||
|
Path: "/category/v1/:id",
|
||||||
|
Handler: deleteCategoryHandler(serverCtx),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Method: http.MethodGet,
|
||||||
|
Path: "/category/v1/:id/tree",
|
||||||
|
Handler: getCategoryTreeHandler(serverCtx),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Method: http.MethodGet,
|
||||||
|
Path: "/category/v1/system/:system_id",
|
||||||
|
Handler: getSystemCategoriesHandler(serverCtx),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Method: http.MethodGet,
|
||||||
|
Path: "/user/:user_id",
|
||||||
Handler: getUserInfoHandler(serverCtx),
|
Handler: getUserInfoHandler(serverCtx),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Method: http.MethodPost,
|
Method: http.MethodPost,
|
||||||
Path: "/api/user/logout",
|
Path: "/user/logout",
|
||||||
Handler: logoutHandler(serverCtx),
|
Handler: logoutHandler(serverCtx),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
rest.WithJwt(serverCtx.Config.JwtAuth.AccessSecret),
|
rest.WithJwt(serverCtx.Config.JwtAuth.AccessSecret),
|
||||||
|
rest.WithPrefix("/api"),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
28
gateway/internal/handler/updatecategoryhandler.go
Normal file
28
gateway/internal/handler/updatecategoryhandler.go
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
package handler
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
"github.com/zeromicro/go-zero/rest/httpx"
|
||||||
|
"godemo/gateway/internal/logic"
|
||||||
|
"godemo/gateway/internal/svc"
|
||||||
|
"godemo/gateway/internal/types"
|
||||||
|
)
|
||||||
|
|
||||||
|
func updateCategoryHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
|
||||||
|
return func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
var req types.UpdateCategoryReq
|
||||||
|
if err := httpx.Parse(r, &req); err != nil {
|
||||||
|
httpx.ErrorCtx(r.Context(), w, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
l := logic.NewUpdateCategoryLogic(r.Context(), svcCtx)
|
||||||
|
resp, err := l.UpdateCategory(&req)
|
||||||
|
if err != nil {
|
||||||
|
httpx.ErrorCtx(r.Context(), w, err)
|
||||||
|
} else {
|
||||||
|
httpx.OkJsonCtx(r.Context(), w, resp)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
103
gateway/internal/logic/createcategorylogic.go
Normal file
103
gateway/internal/logic/createcategorylogic.go
Normal file
@ -0,0 +1,103 @@
|
|||||||
|
package logic
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"godemo/category/category"
|
||||||
|
"godemo/gateway/internal/svc"
|
||||||
|
"godemo/gateway/internal/types"
|
||||||
|
|
||||||
|
"github.com/zeromicro/go-zero/core/logx"
|
||||||
|
"google.golang.org/grpc/codes"
|
||||||
|
"google.golang.org/grpc/status"
|
||||||
|
)
|
||||||
|
|
||||||
|
type CreateCategoryLogic struct {
|
||||||
|
logx.Logger
|
||||||
|
ctx context.Context
|
||||||
|
svcCtx *svc.ServiceContext
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewCreateCategoryLogic(ctx context.Context, svcCtx *svc.ServiceContext) *CreateCategoryLogic {
|
||||||
|
return &CreateCategoryLogic{
|
||||||
|
Logger: logx.WithContext(ctx),
|
||||||
|
ctx: ctx,
|
||||||
|
svcCtx: svcCtx,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *CreateCategoryLogic) CreateCategory(req *types.CreateCategoryReq) (resp *types.CreateCategoryResp, err error) {
|
||||||
|
// 1. 参数验证
|
||||||
|
if err := validateCreateRequest(req); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2. 准备 RPC 请求
|
||||||
|
rpcReq := &category.CreateCategoryRequest{
|
||||||
|
SystemId: req.SystemID,
|
||||||
|
Name: req.Name,
|
||||||
|
Description: req.Description,
|
||||||
|
}
|
||||||
|
|
||||||
|
// 可选参数处理
|
||||||
|
if req.Alias != "" {
|
||||||
|
rpcReq.Alias = req.Alias
|
||||||
|
}
|
||||||
|
|
||||||
|
if req.ParentID != "" {
|
||||||
|
rpcReq.ParentId = req.ParentID
|
||||||
|
}
|
||||||
|
|
||||||
|
// 3. 调用 RPC 服务
|
||||||
|
rpcResp, rpcErr := l.svcCtx.CategoryRpc.CreateCategory(l.ctx, rpcReq)
|
||||||
|
if rpcErr != nil {
|
||||||
|
return nil, rpcErr
|
||||||
|
}
|
||||||
|
|
||||||
|
// 4. 构建响应
|
||||||
|
resp = &types.CreateCategoryResp{
|
||||||
|
ID: rpcResp.Category.Id,
|
||||||
|
}
|
||||||
|
|
||||||
|
l.Logger.Infof("Category created successfully: ID=%s, Name=%s", resp.ID, req.Name)
|
||||||
|
return resp, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// validateCreateRequest 验证创建分类请求
|
||||||
|
func validateCreateRequest(req *types.CreateCategoryReq) error {
|
||||||
|
// 必需字段检查
|
||||||
|
if strings.TrimSpace(req.SystemID) == "" {
|
||||||
|
return status.Error(codes.InvalidArgument, "systemId不能为空")
|
||||||
|
}
|
||||||
|
if strings.TrimSpace(req.Name) == "" {
|
||||||
|
return status.Error(codes.InvalidArgument, "name不能为空")
|
||||||
|
}
|
||||||
|
|
||||||
|
// 名称长度限制
|
||||||
|
if len(req.Name) > 50 {
|
||||||
|
return status.Error(codes.InvalidArgument, "alias cannot exceed 50 characters")
|
||||||
|
}
|
||||||
|
|
||||||
|
// 别名格式验证 (只允许字母、数字、连字符和下划线)
|
||||||
|
// if req.Alias != "" {
|
||||||
|
// if len(req.Alias) > 50 {
|
||||||
|
// return errors.New("alias cannot exceed 50 characters")
|
||||||
|
// }
|
||||||
|
// for _, ch := range req.Alias {
|
||||||
|
// if !(ch >= 'a' && ch <= 'z') &&
|
||||||
|
// !(ch >= 'A' && ch <= 'Z') &&
|
||||||
|
// !(ch >= '0' && ch <= '9') &&
|
||||||
|
// ch != '-' && ch != '_' {
|
||||||
|
// return errors.New("alias can only contain letters, numbers, hyphens and underscores")
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
// 描述长度限制
|
||||||
|
if len(req.Description) > 500 {
|
||||||
|
return status.Error(codes.InvalidArgument, "description cannot exceed 500 characters")
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
30
gateway/internal/logic/deletecategorylogic.go
Normal file
30
gateway/internal/logic/deletecategorylogic.go
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
package logic
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
|
"godemo/gateway/internal/svc"
|
||||||
|
"godemo/gateway/internal/types"
|
||||||
|
|
||||||
|
"github.com/zeromicro/go-zero/core/logx"
|
||||||
|
)
|
||||||
|
|
||||||
|
type DeleteCategoryLogic struct {
|
||||||
|
logx.Logger
|
||||||
|
ctx context.Context
|
||||||
|
svcCtx *svc.ServiceContext
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewDeleteCategoryLogic(ctx context.Context, svcCtx *svc.ServiceContext) *DeleteCategoryLogic {
|
||||||
|
return &DeleteCategoryLogic{
|
||||||
|
Logger: logx.WithContext(ctx),
|
||||||
|
ctx: ctx,
|
||||||
|
svcCtx: svcCtx,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *DeleteCategoryLogic) DeleteCategory(req *types.DeleteCategoryReq) (resp *types.BaseResp, err error) {
|
||||||
|
// todo: add your logic here and delete this line
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
59
gateway/internal/logic/getcategorylogic.go
Normal file
59
gateway/internal/logic/getcategorylogic.go
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
package logic
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"godemo/category/category"
|
||||||
|
"godemo/gateway/internal/svc"
|
||||||
|
"godemo/gateway/internal/types"
|
||||||
|
|
||||||
|
"github.com/zeromicro/go-zero/core/logx"
|
||||||
|
)
|
||||||
|
|
||||||
|
type GetCategoryLogic struct {
|
||||||
|
logx.Logger
|
||||||
|
ctx context.Context
|
||||||
|
svcCtx *svc.ServiceContext
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewGetCategoryLogic(ctx context.Context, svcCtx *svc.ServiceContext) *GetCategoryLogic {
|
||||||
|
return &GetCategoryLogic{
|
||||||
|
Logger: logx.WithContext(ctx),
|
||||||
|
ctx: ctx,
|
||||||
|
svcCtx: svcCtx,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *GetCategoryLogic) GetCategory(req *types.GetCategoryReq) (resp *types.CategoryDetailResp, err error) {
|
||||||
|
rpcResp, err := l.svcCtx.CategoryRpc.GetCategory(l.ctx, &category.GetCategoryRequest{
|
||||||
|
Id: req.ID,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
// 转换主分类的时间
|
||||||
|
createdAtStr := time.Unix(rpcResp.Category.CreatedAt, 0).Format(time.RFC3339)
|
||||||
|
updatedAtStr := ""
|
||||||
|
if rpcResp.Category.UpdatedAt != 0 {
|
||||||
|
updatedAtStr = time.Unix(rpcResp.Category.UpdatedAt, 0).Format(time.RFC3339)
|
||||||
|
}
|
||||||
|
|
||||||
|
resp = &types.CategoryDetailResp{
|
||||||
|
CategoryDetail: types.CategoryDetail{
|
||||||
|
BaseCategory: types.BaseCategory{
|
||||||
|
ID: rpcResp.Category.Id,
|
||||||
|
Name: rpcResp.Category.Name,
|
||||||
|
Alias: rpcResp.Category.Alias,
|
||||||
|
Description: rpcResp.Category.Description,
|
||||||
|
ParentID: rpcResp.Category.ParentId,
|
||||||
|
SystemID: rpcResp.Category.SystemId,
|
||||||
|
CreatedAt: createdAtStr,
|
||||||
|
UpdatedAt: updatedAtStr,
|
||||||
|
},
|
||||||
|
Parent: nil,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
30
gateway/internal/logic/getcategorytreelogic.go
Normal file
30
gateway/internal/logic/getcategorytreelogic.go
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
package logic
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
|
"godemo/gateway/internal/svc"
|
||||||
|
"godemo/gateway/internal/types"
|
||||||
|
|
||||||
|
"github.com/zeromicro/go-zero/core/logx"
|
||||||
|
)
|
||||||
|
|
||||||
|
type GetCategoryTreeLogic struct {
|
||||||
|
logx.Logger
|
||||||
|
ctx context.Context
|
||||||
|
svcCtx *svc.ServiceContext
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewGetCategoryTreeLogic(ctx context.Context, svcCtx *svc.ServiceContext) *GetCategoryTreeLogic {
|
||||||
|
return &GetCategoryTreeLogic{
|
||||||
|
Logger: logx.WithContext(ctx),
|
||||||
|
ctx: ctx,
|
||||||
|
svcCtx: svcCtx,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *GetCategoryTreeLogic) GetCategoryTree(req *types.GetCategoryTreeReq) (resp *types.CategoryTreeResp, err error) {
|
||||||
|
// todo: add your logic here and delete this line
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
97
gateway/internal/logic/getsystemcategorieslogic.go
Normal file
97
gateway/internal/logic/getsystemcategorieslogic.go
Normal file
@ -0,0 +1,97 @@
|
|||||||
|
package logic
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"strings"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"godemo/category/category"
|
||||||
|
"godemo/gateway/internal/svc"
|
||||||
|
"godemo/gateway/internal/types"
|
||||||
|
|
||||||
|
"github.com/zeromicro/go-zero/core/logx"
|
||||||
|
"google.golang.org/grpc/codes"
|
||||||
|
"google.golang.org/grpc/status"
|
||||||
|
)
|
||||||
|
|
||||||
|
type GetSystemCategoriesLogic struct {
|
||||||
|
logx.Logger
|
||||||
|
ctx context.Context
|
||||||
|
svcCtx *svc.ServiceContext
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewGetSystemCategoriesLogic(ctx context.Context, svcCtx *svc.ServiceContext) *GetSystemCategoriesLogic {
|
||||||
|
return &GetSystemCategoriesLogic{
|
||||||
|
Logger: logx.WithContext(ctx),
|
||||||
|
ctx: ctx,
|
||||||
|
svcCtx: svcCtx,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *GetSystemCategoriesLogic) GetSystemCategories(req *types.GetSystemCategoriesReq) (resp *types.ListCategoriesResp, err error) {
|
||||||
|
// 1. 验证系统ID
|
||||||
|
if strings.TrimSpace(req.SystemID) == "" {
|
||||||
|
return nil, status.Error(codes.InvalidArgument, "system_id is required")
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2. 准备 RPC 请求
|
||||||
|
rpcReq := &category.GetSystemCategoriesRequest{
|
||||||
|
SystemId: req.SystemID,
|
||||||
|
IncludeDescendants: req.IncludeDescendants,
|
||||||
|
}
|
||||||
|
|
||||||
|
// 添加父分类ID过滤(如果提供)
|
||||||
|
if req.ParentID != "" {
|
||||||
|
rpcReq.ParentId = req.ParentID
|
||||||
|
}
|
||||||
|
|
||||||
|
// 3. 调用 RPC 服务
|
||||||
|
rpcResp, rpcErr := l.svcCtx.CategoryRpc.GetSystemCategories(l.ctx, rpcReq)
|
||||||
|
if rpcErr != nil {
|
||||||
|
st, ok := status.FromError(rpcErr)
|
||||||
|
if ok && st.Code() == codes.NotFound {
|
||||||
|
// 返回空列表而不是错误
|
||||||
|
return &types.ListCategoriesResp{
|
||||||
|
Total: 0,
|
||||||
|
List: []types.BaseCategory{},
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
l.Logger.Errorf("RPC error: %v", rpcErr)
|
||||||
|
return nil, rpcErr
|
||||||
|
}
|
||||||
|
|
||||||
|
// 4. 转换响应数据
|
||||||
|
categories := make([]types.BaseCategory, 0, len(rpcResp.Categories))
|
||||||
|
for _, cat := range rpcResp.Categories {
|
||||||
|
// 转换时间格式
|
||||||
|
createdAt := ""
|
||||||
|
if cat.CreatedAt > 0 {
|
||||||
|
createdAt = time.Unix(cat.CreatedAt, 0).Format(time.RFC3339)
|
||||||
|
}
|
||||||
|
|
||||||
|
updatedAt := ""
|
||||||
|
if cat.UpdatedAt > 0 {
|
||||||
|
updatedAt = time.Unix(cat.UpdatedAt, 0).Format(time.RFC3339)
|
||||||
|
}
|
||||||
|
|
||||||
|
categories = append(categories, types.BaseCategory{
|
||||||
|
ID: cat.Id,
|
||||||
|
SystemID: cat.SystemId,
|
||||||
|
Name: cat.Name,
|
||||||
|
Alias: cat.Alias,
|
||||||
|
ParentID: cat.ParentId,
|
||||||
|
Description: cat.Description,
|
||||||
|
CreatedAt: createdAt,
|
||||||
|
UpdatedAt: updatedAt,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 5. 构建响应
|
||||||
|
resp = &types.ListCategoriesResp{
|
||||||
|
Total: rpcResp.Total,
|
||||||
|
List: categories,
|
||||||
|
}
|
||||||
|
|
||||||
|
l.Logger.Infof("Retrieved %d categories for system %s (parent: %s)", len(categories), req.SystemID, req.ParentID)
|
||||||
|
return resp, nil
|
||||||
|
}
|
||||||
30
gateway/internal/logic/listcategorieslogic.go
Normal file
30
gateway/internal/logic/listcategorieslogic.go
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
package logic
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
|
"godemo/gateway/internal/svc"
|
||||||
|
"godemo/gateway/internal/types"
|
||||||
|
|
||||||
|
"github.com/zeromicro/go-zero/core/logx"
|
||||||
|
)
|
||||||
|
|
||||||
|
type ListCategoriesLogic struct {
|
||||||
|
logx.Logger
|
||||||
|
ctx context.Context
|
||||||
|
svcCtx *svc.ServiceContext
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewListCategoriesLogic(ctx context.Context, svcCtx *svc.ServiceContext) *ListCategoriesLogic {
|
||||||
|
return &ListCategoriesLogic{
|
||||||
|
Logger: logx.WithContext(ctx),
|
||||||
|
ctx: ctx,
|
||||||
|
svcCtx: svcCtx,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *ListCategoriesLogic) ListCategories(req *types.ListCategoriesReq) (resp *types.ListCategoriesResp, err error) {
|
||||||
|
// todo: add your logic here and delete this line
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
30
gateway/internal/logic/updatecategorylogic.go
Normal file
30
gateway/internal/logic/updatecategorylogic.go
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
package logic
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
|
"godemo/gateway/internal/svc"
|
||||||
|
"godemo/gateway/internal/types"
|
||||||
|
|
||||||
|
"github.com/zeromicro/go-zero/core/logx"
|
||||||
|
)
|
||||||
|
|
||||||
|
type UpdateCategoryLogic struct {
|
||||||
|
logx.Logger
|
||||||
|
ctx context.Context
|
||||||
|
svcCtx *svc.ServiceContext
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewUpdateCategoryLogic(ctx context.Context, svcCtx *svc.ServiceContext) *UpdateCategoryLogic {
|
||||||
|
return &UpdateCategoryLogic{
|
||||||
|
Logger: logx.WithContext(ctx),
|
||||||
|
ctx: ctx,
|
||||||
|
svcCtx: svcCtx,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *UpdateCategoryLogic) UpdateCategory(req *types.UpdateCategoryReq) (resp *types.BaseResp, err error) {
|
||||||
|
// todo: add your logic here and delete this line
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
@ -1,6 +1,7 @@
|
|||||||
package svc
|
package svc
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"godemo/category/category"
|
||||||
"godemo/gateway/internal/config"
|
"godemo/gateway/internal/config"
|
||||||
"godemo/user/user"
|
"godemo/user/user"
|
||||||
|
|
||||||
@ -8,14 +9,15 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type ServiceContext struct {
|
type ServiceContext struct {
|
||||||
Config config.Config
|
Config config.Config
|
||||||
UserRpc user.UserClient
|
UserRpc user.UserClient
|
||||||
|
CategoryRpc category.CategoryClient
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewServiceContext(c config.Config) *ServiceContext {
|
func NewServiceContext(c config.Config) *ServiceContext {
|
||||||
conn := zrpc.MustNewClient(c.UserRpc).Conn()
|
|
||||||
return &ServiceContext{
|
return &ServiceContext{
|
||||||
Config: c,
|
Config: c,
|
||||||
UserRpc: user.NewUserClient(conn),
|
UserRpc: user.NewUserClient(zrpc.MustNewClient(c.UserRpc).Conn()),
|
||||||
|
CategoryRpc: category.NewCategoryClient(zrpc.MustNewClient(c.CategoryRpc).Conn()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -3,6 +3,65 @@
|
|||||||
|
|
||||||
package types
|
package types
|
||||||
|
|
||||||
|
type BaseCategory struct {
|
||||||
|
ID string `json:"id"` // 分类ID (UUID)
|
||||||
|
SystemID string `json:"systemId"` // 所属系统ID
|
||||||
|
Name string `json:"name"` // 分类名称
|
||||||
|
Alias string `json:"alias"` // URL别名
|
||||||
|
ParentID string `json:"parentId"` // 父分类ID (可为空)
|
||||||
|
Description string `json:"description"` // 分类描述
|
||||||
|
CreatedAt string `json:"createdAt"` // 创建时间 (ISO8601)
|
||||||
|
UpdatedAt string `json:"updatedAt"` // 更新时间 (ISO8601)
|
||||||
|
}
|
||||||
|
|
||||||
|
type BaseResp struct {
|
||||||
|
Code int `json:"code"` // 状态码 (0=成功)
|
||||||
|
Message string `json:"message"` // 消息
|
||||||
|
}
|
||||||
|
|
||||||
|
type CategoryDetail struct {
|
||||||
|
BaseCategory
|
||||||
|
Parent *BaseCategory `json:"parent"` // 父分类信息
|
||||||
|
}
|
||||||
|
|
||||||
|
type CategoryDetailResp struct {
|
||||||
|
CategoryDetail
|
||||||
|
}
|
||||||
|
|
||||||
|
type CategoryTreeResp struct {
|
||||||
|
Root TreeNode `json:"root"` // 分类树根节点
|
||||||
|
}
|
||||||
|
|
||||||
|
type CreateCategoryReq struct {
|
||||||
|
SystemID string `json:"systemId" validate:"required"` // 所属系统ID
|
||||||
|
Name string `json:"name" validate:"required"` // 分类名称
|
||||||
|
Alias string `json:"alias,optional"` // URL别名
|
||||||
|
ParentID string `json:"parentId,optional"` // 父分类ID
|
||||||
|
Description string `json:"description,optional"` // 分类描述
|
||||||
|
}
|
||||||
|
|
||||||
|
type CreateCategoryResp struct {
|
||||||
|
ID string `json:"id"` // 新创建的分类ID
|
||||||
|
}
|
||||||
|
|
||||||
|
type DeleteCategoryReq struct {
|
||||||
|
ID string `path:"id"` // 分类ID
|
||||||
|
}
|
||||||
|
|
||||||
|
type GetCategoryReq struct {
|
||||||
|
ID string `path:"id"` // 分类ID
|
||||||
|
}
|
||||||
|
|
||||||
|
type GetCategoryTreeReq struct {
|
||||||
|
ID string `path:"id"` // 起始分类ID
|
||||||
|
}
|
||||||
|
|
||||||
|
type GetSystemCategoriesReq struct {
|
||||||
|
SystemID string `path:"system_id"` // 系统ID
|
||||||
|
ParentID string `form:"parentId,optional"` // 父分类ID (可选)
|
||||||
|
IncludeDescendants bool `form:"includeDescendants,default=true"` // 是否包含子分类
|
||||||
|
}
|
||||||
|
|
||||||
type GetUserInfoReq struct {
|
type GetUserInfoReq struct {
|
||||||
UserId string `path:"user_id"`
|
UserId string `path:"user_id"`
|
||||||
}
|
}
|
||||||
@ -15,6 +74,19 @@ type GetUserInfoResp struct {
|
|||||||
Roles []string `json:"roles"`
|
Roles []string `json:"roles"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type ListCategoriesReq struct {
|
||||||
|
SystemID string `form:"systemId,optional"` // 按系统ID过滤
|
||||||
|
ParentID string `form:"parentId,optional"` // 按父分类ID过滤
|
||||||
|
Name string `form:"name,optional"` // 按名称模糊搜索
|
||||||
|
Page int `form:"page,default=1"` // 页码
|
||||||
|
PageSize int `form:"pageSize,default=20"` // 每页数量
|
||||||
|
}
|
||||||
|
|
||||||
|
type ListCategoriesResp struct {
|
||||||
|
Total int64 `json:"total"` // 总数
|
||||||
|
List []BaseCategory `json:"list"` // 分类列表
|
||||||
|
}
|
||||||
|
|
||||||
type LoginReq struct {
|
type LoginReq struct {
|
||||||
Username string `json:"username"`
|
Username string `json:"username"`
|
||||||
Password string `json:"password"`
|
Password string `json:"password"`
|
||||||
@ -42,3 +114,16 @@ type RegisterReq struct {
|
|||||||
type RegisterResp struct {
|
type RegisterResp struct {
|
||||||
UserId string `json:"user_id"`
|
UserId string `json:"user_id"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type TreeNode struct {
|
||||||
|
BaseCategory
|
||||||
|
Children []*TreeNode `json:"children"` // 子分类列表
|
||||||
|
}
|
||||||
|
|
||||||
|
type UpdateCategoryReq struct {
|
||||||
|
ID string `path:"id"` // 分类ID
|
||||||
|
Name string `json:"name,optional"` // 新名称
|
||||||
|
Alias string `json:"alias,optional"` // 新别名
|
||||||
|
ParentID string `json:"parentId,optional"` // 新父分类ID
|
||||||
|
Description string `json:"description,optional"` // 新描述
|
||||||
|
}
|
||||||
|
|||||||
5
go.mod
5
go.mod
@ -8,7 +8,7 @@ require (
|
|||||||
github.com/lib/pq v1.10.9
|
github.com/lib/pq v1.10.9
|
||||||
github.com/zeromicro/go-zero v1.8.3
|
github.com/zeromicro/go-zero v1.8.3
|
||||||
golang.org/x/crypto v0.36.0
|
golang.org/x/crypto v0.36.0
|
||||||
google.golang.org/grpc v1.72.1
|
google.golang.org/grpc v1.72.2
|
||||||
google.golang.org/protobuf v1.36.6
|
google.golang.org/protobuf v1.36.6
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -19,12 +19,15 @@ require (
|
|||||||
github.com/go-sql-driver/mysql v1.9.0 // indirect
|
github.com/go-sql-driver/mysql v1.9.0 // indirect
|
||||||
github.com/goccy/go-json v0.10.5 // indirect
|
github.com/goccy/go-json v0.10.5 // indirect
|
||||||
github.com/klauspost/cpuid/v2 v2.2.10 // indirect
|
github.com/klauspost/cpuid/v2 v2.2.10 // indirect
|
||||||
|
github.com/lann/builder v0.0.0-20180802200727-47ae307949d0 // indirect
|
||||||
|
github.com/lann/ps v0.0.0-20150810152359-62de8c46ede0 // indirect
|
||||||
github.com/minio/crc64nvme v1.0.1 // indirect
|
github.com/minio/crc64nvme v1.0.1 // indirect
|
||||||
github.com/minio/md5-simd v1.1.2 // indirect
|
github.com/minio/md5-simd v1.1.2 // indirect
|
||||||
github.com/rs/xid v1.6.0 // indirect
|
github.com/rs/xid v1.6.0 // indirect
|
||||||
)
|
)
|
||||||
|
|
||||||
require (
|
require (
|
||||||
|
github.com/Masterminds/squirrel v1.5.4
|
||||||
github.com/beorn7/perks v1.0.1 // indirect
|
github.com/beorn7/perks v1.0.1 // indirect
|
||||||
github.com/cenkalti/backoff/v4 v4.3.0 // indirect
|
github.com/cenkalti/backoff/v4 v4.3.0 // indirect
|
||||||
github.com/cespare/xxhash/v2 v2.3.0 // indirect
|
github.com/cespare/xxhash/v2 v2.3.0 // indirect
|
||||||
|
|||||||
11
go.sum
11
go.sum
@ -2,6 +2,8 @@ filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA=
|
|||||||
filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4=
|
filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4=
|
||||||
github.com/DATA-DOG/go-sqlmock v1.5.2 h1:OcvFkGmslmlZibjAjaHm3L//6LiuBgolP7OputlJIzU=
|
github.com/DATA-DOG/go-sqlmock v1.5.2 h1:OcvFkGmslmlZibjAjaHm3L//6LiuBgolP7OputlJIzU=
|
||||||
github.com/DATA-DOG/go-sqlmock v1.5.2/go.mod h1:88MAG/4G7SMwSE3CeA0ZKzrT5CiOU3OJ+JlNzwDqpNU=
|
github.com/DATA-DOG/go-sqlmock v1.5.2/go.mod h1:88MAG/4G7SMwSE3CeA0ZKzrT5CiOU3OJ+JlNzwDqpNU=
|
||||||
|
github.com/Masterminds/squirrel v1.5.4 h1:uUcX/aBc8O7Fg9kaISIUsHXdKuqehiXAMQTYX8afzqM=
|
||||||
|
github.com/Masterminds/squirrel v1.5.4/go.mod h1:NNaOrjSoIDfDA40n7sr2tPNZRfjzjA400rg+riTZj10=
|
||||||
github.com/alicebob/gopher-json v0.0.0-20230218143504-906a9b012302 h1:uvdUDbHQHO85qeSydJtItA4T55Pw6BtAejd0APRJOCE=
|
github.com/alicebob/gopher-json v0.0.0-20230218143504-906a9b012302 h1:uvdUDbHQHO85qeSydJtItA4T55Pw6BtAejd0APRJOCE=
|
||||||
github.com/alicebob/gopher-json v0.0.0-20230218143504-906a9b012302/go.mod h1:SGnFV6hVsYE877CKEZ6tDNTjaSXYUk6QqoIK6PrAtcc=
|
github.com/alicebob/gopher-json v0.0.0-20230218143504-906a9b012302/go.mod h1:SGnFV6hVsYE877CKEZ6tDNTjaSXYUk6QqoIK6PrAtcc=
|
||||||
github.com/alicebob/miniredis/v2 v2.34.0 h1:mBFWMaJSNL9RwdGRyEDoAAv8OQc5UlEhLDQggTglU/0=
|
github.com/alicebob/miniredis/v2 v2.34.0 h1:mBFWMaJSNL9RwdGRyEDoAAv8OQc5UlEhLDQggTglU/0=
|
||||||
@ -103,6 +105,10 @@ github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
|||||||
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
|
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
|
||||||
github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc=
|
github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc=
|
||||||
github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw=
|
github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw=
|
||||||
|
github.com/lann/builder v0.0.0-20180802200727-47ae307949d0 h1:SOEGU9fKiNWd/HOJuq6+3iTQz8KNCLtVX6idSoTLdUw=
|
||||||
|
github.com/lann/builder v0.0.0-20180802200727-47ae307949d0/go.mod h1:dXGbAdH5GtBTC4WfIxhKZfyBF/HBFgRZSWwZ9g/He9o=
|
||||||
|
github.com/lann/ps v0.0.0-20150810152359-62de8c46ede0 h1:P6pPBnrTSX3DEVR4fDembhRWSsG5rVo6hYhAB/ADZrk=
|
||||||
|
github.com/lann/ps v0.0.0-20150810152359-62de8c46ede0/go.mod h1:vmVJ0l/dxyfGW6FmdpVm2joNMFikkuWg0EoCKLGUMNw=
|
||||||
github.com/lib/pq v1.10.9 h1:YXG7RB+JIjhP29X+OtkiDnYaXQwpS4JEWq7dtCCRUEw=
|
github.com/lib/pq v1.10.9 h1:YXG7RB+JIjhP29X+OtkiDnYaXQwpS4JEWq7dtCCRUEw=
|
||||||
github.com/lib/pq v1.10.9/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
|
github.com/lib/pq v1.10.9/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
|
||||||
github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0=
|
github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0=
|
||||||
@ -164,6 +170,7 @@ github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSS
|
|||||||
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
|
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
|
||||||
github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY=
|
github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY=
|
||||||
github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA=
|
github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA=
|
||||||
|
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||||
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||||
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
|
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
|
||||||
@ -276,8 +283,8 @@ google.golang.org/genproto/googleapis/api v0.0.0-20250218202821-56aae31c358a h1:
|
|||||||
google.golang.org/genproto/googleapis/api v0.0.0-20250218202821-56aae31c358a/go.mod h1:3kWAYMk1I75K4vykHtKt2ycnOgpA6974V7bREqbsenU=
|
google.golang.org/genproto/googleapis/api v0.0.0-20250218202821-56aae31c358a/go.mod h1:3kWAYMk1I75K4vykHtKt2ycnOgpA6974V7bREqbsenU=
|
||||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20250218202821-56aae31c358a h1:51aaUVRocpvUOSQKM6Q7VuoaktNIaMCLuhZB6DKksq4=
|
google.golang.org/genproto/googleapis/rpc v0.0.0-20250218202821-56aae31c358a h1:51aaUVRocpvUOSQKM6Q7VuoaktNIaMCLuhZB6DKksq4=
|
||||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20250218202821-56aae31c358a/go.mod h1:uRxBH1mhmO8PGhU89cMcHaXKZqO+OfakD8QQO0oYwlQ=
|
google.golang.org/genproto/googleapis/rpc v0.0.0-20250218202821-56aae31c358a/go.mod h1:uRxBH1mhmO8PGhU89cMcHaXKZqO+OfakD8QQO0oYwlQ=
|
||||||
google.golang.org/grpc v1.72.1 h1:HR03wO6eyZ7lknl75XlxABNVLLFc2PAb6mHlYh756mA=
|
google.golang.org/grpc v1.72.2 h1:TdbGzwb82ty4OusHWepvFWGLgIbNo1/SUynEN0ssqv8=
|
||||||
google.golang.org/grpc v1.72.1/go.mod h1:wH5Aktxcg25y1I3w7H69nHfXdOG3UiadoBtjh3izSDM=
|
google.golang.org/grpc v1.72.2/go.mod h1:wH5Aktxcg25y1I3w7H69nHfXdOG3UiadoBtjh3izSDM=
|
||||||
google.golang.org/protobuf v1.36.6 h1:z1NpPI8ku2WgiWnf+t9wTPsn6eP1L7ksHUlkfLvd9xY=
|
google.golang.org/protobuf v1.36.6 h1:z1NpPI8ku2WgiWnf+t9wTPsn6eP1L7ksHUlkfLvd9xY=
|
||||||
google.golang.org/protobuf v1.36.6/go.mod h1:jduwjTPXsFjZGTmRluh+L6NjiWu7pchiJ2/5YcXBHnY=
|
google.golang.org/protobuf v1.36.6/go.mod h1:jduwjTPXsFjZGTmRluh+L6NjiWu7pchiJ2/5YcXBHnY=
|
||||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
|
|||||||
@ -28,6 +28,12 @@ service Category {
|
|||||||
// 查询过滤
|
// 查询过滤
|
||||||
rpc ListCategories(ListCategoryRequest) returns (CategoryListResponse);
|
rpc ListCategories(ListCategoryRequest) returns (CategoryListResponse);
|
||||||
rpc CheckAlias(CheckAliasRequest) returns (CheckAliasResponse);
|
rpc CheckAlias(CheckAliasRequest) returns (CheckAliasResponse);
|
||||||
|
|
||||||
|
// 根据系统ID获取分类
|
||||||
|
rpc GetSystemCategories(GetSystemCategoriesRequest) returns (GetSystemCategoriesResponse);
|
||||||
|
|
||||||
|
// 获取某一个类别的完整类别(从根类别到当前类别的所有类别)
|
||||||
|
rpc GetFullCategories(GetCategoryRequest) returns (GetFullCategoriesResponse);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 健康检查请求
|
// 健康检查请求
|
||||||
@ -85,6 +91,11 @@ message GetCategoryRequest {
|
|||||||
string id = 1;
|
string id = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 获取全分类名称的响应
|
||||||
|
message GetFullCategoriesResponse {
|
||||||
|
string full_category_name = 1;
|
||||||
|
}
|
||||||
|
|
||||||
// 分类信息响应
|
// 分类信息响应
|
||||||
message CategoryInfoResponse {
|
message CategoryInfoResponse {
|
||||||
CategoryInfo category = 1;
|
CategoryInfo category = 1;
|
||||||
@ -176,3 +187,18 @@ message CheckAliasResponse {
|
|||||||
bool is_available = 1;
|
bool is_available = 1;
|
||||||
string existing_id = 2; // 冲突时返回已存在的分类ID
|
string existing_id = 2; // 冲突时返回已存在的分类ID
|
||||||
}
|
}
|
||||||
|
|
||||||
|
message GetSystemCategoriesRequest {
|
||||||
|
string system_id = 1; // 系统标识 (必需)
|
||||||
|
string parent_id = 2; // 父分类ID (可选)
|
||||||
|
int32 page = 3; // 分页参数
|
||||||
|
int32 page_size = 4; // 分页参数
|
||||||
|
bool include_descendants = 5; // 是否包含后代
|
||||||
|
}
|
||||||
|
|
||||||
|
message GetSystemCategoriesResponse {
|
||||||
|
repeated CategoryInfo categories = 1;
|
||||||
|
int64 total = 2;
|
||||||
|
int32 current_page = 3;
|
||||||
|
int32 page_size = 4;
|
||||||
|
}
|
||||||
@ -4,6 +4,13 @@ package file;
|
|||||||
|
|
||||||
option go_package = "./file";
|
option go_package = "./file";
|
||||||
|
|
||||||
|
enum ImageVersion {
|
||||||
|
original = 0;
|
||||||
|
thumbnail = 1; // 缩略图
|
||||||
|
preview = 2; // 预览图
|
||||||
|
all = 9; // 所有版本
|
||||||
|
}
|
||||||
|
|
||||||
// 文件服务 - 上传图片、获取地址、删除文件等
|
// 文件服务 - 上传图片、获取地址、删除文件等
|
||||||
service File {
|
service File {
|
||||||
// 上传文件(图片/头像/壁纸等)
|
// 上传文件(图片/头像/壁纸等)
|
||||||
@ -14,6 +21,21 @@ service File {
|
|||||||
|
|
||||||
// 删除文件
|
// 删除文件
|
||||||
rpc Delete (DeleteRequest) returns (DeleteResponse);
|
rpc Delete (DeleteRequest) returns (DeleteResponse);
|
||||||
|
|
||||||
|
// 异步生成图片版本接口
|
||||||
|
rpc GenerateImageVersions (GenerateImageVersionsRequest) returns (GenerateImageVersionsResponse);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 生成图片版本请求
|
||||||
|
message GenerateImageVersionsRequest {
|
||||||
|
string file_id = 1; // 原始图片ID
|
||||||
|
repeated ImageVersion versions = 2; // 需要生成的版本
|
||||||
|
}
|
||||||
|
|
||||||
|
// 生成图片版本响应
|
||||||
|
message GenerateImageVersionsResponse {
|
||||||
|
string task_id = 1; // 异步任务ID
|
||||||
|
bool accepted = 2; // 任务是否被接受
|
||||||
}
|
}
|
||||||
|
|
||||||
// 上传文件请求
|
// 上传文件请求
|
||||||
@ -21,7 +43,8 @@ message UploadRequest {
|
|||||||
string filename = 1; // 文件名(建议客户端传原始名,服务端会生成唯一名)
|
string filename = 1; // 文件名(建议客户端传原始名,服务端会生成唯一名)
|
||||||
string content_type = 2; // 文件类型(如 image/jpeg)
|
string content_type = 2; // 文件类型(如 image/jpeg)
|
||||||
bytes content = 3; // 文件二进制内容(base64 编码由客户端完成)
|
bytes content = 3; // 文件二进制内容(base64 编码由客户端完成)
|
||||||
string folder = 4; // 可选,文件夹或分类路径,如 "avatars"、"wallpapers"
|
string folder = 4; // 可选,文件夹或分类路径,支持多级,如 "avatars"、"wallpapers/animals"
|
||||||
|
string bucket = 5; // bucket name
|
||||||
}
|
}
|
||||||
|
|
||||||
// 上传响应
|
// 上传响应
|
||||||
|
|||||||
@ -1,18 +1,18 @@
|
|||||||
-- 图片主表基础版
|
-- 图片主表基础版
|
||||||
CREATE TABLE images (
|
CREATE TABLE images (
|
||||||
-- 核心标识字段
|
-- 核心标识字段
|
||||||
image_id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
image_id VARCHAR(36) PRIMARY KEY DEFAULT gen_random_uuid()::varchar,
|
||||||
|
|
||||||
-- 存储元数据
|
-- 存储元数据
|
||||||
storage_key TEXT NOT NULL CHECK (storage_key ~ '^[a-z0-9/-]+$'),
|
storage_key TEXT NOT NULL, -- 文件存储标识。 bucket/object_id
|
||||||
file_name TEXT NOT NULL,
|
file_name TEXT NOT NULL, -- 文件显示名称
|
||||||
mime_type VARCHAR(32) NOT NULL CHECK (mime_type LIKE 'image/%'),
|
mime_type VARCHAR(32) NOT NULL CHECK (mime_type LIKE 'image/%'),
|
||||||
file_size BIGINT NOT NULL CHECK (file_size > 0),
|
file_size BIGINT NOT NULL CHECK (file_size > 0),
|
||||||
width INT CHECK (width > 0),
|
width INT CHECK (width > 0),
|
||||||
height INT CHECK (height > 0),
|
height INT CHECK (height > 0),
|
||||||
|
|
||||||
-- 业务元数据
|
-- 业务元数据
|
||||||
category_id UUID, -- 分类服务提供的UUID
|
category_id VARCHAR(36), -- 分类服务提供的UUID
|
||||||
tags TEXT[] DEFAULT '{}'::TEXT[],
|
tags TEXT[] DEFAULT '{}'::TEXT[],
|
||||||
|
|
||||||
-- 系统管控字段
|
-- 系统管控字段
|
||||||
|
|||||||
@ -6,8 +6,8 @@ Etcd:
|
|||||||
- localhost:2379
|
- localhost:2379
|
||||||
Key: user.rpc
|
Key: user.rpc
|
||||||
|
|
||||||
DataSource: "postgres://postgres:postgres@localhost:5432/godemo?sslmode=disable"
|
DataSource: "postgres://postgres:postgres@localhost:19732/godemo?sslmode=disable"
|
||||||
|
|
||||||
JwtAuth:
|
JwtAuth:
|
||||||
AccessSecret: "your-secure-secret"
|
AccessSecret: "your-secure-secret"
|
||||||
AccessExpire: 900 # 可选,单位秒,15分钟
|
AccessExpire: 3600 # 可选,单位秒,15分钟
|
||||||
|
|||||||
@ -34,6 +34,6 @@ func main() {
|
|||||||
})
|
})
|
||||||
defer s.Stop()
|
defer s.Stop()
|
||||||
|
|
||||||
fmt.Printf("Starting rpc server at %s...\n", c.ListenOn)
|
fmt.Printf("Starting rpc serverc at %s...\n", c.ListenOn)
|
||||||
s.Start()
|
s.Start()
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user