diff --git a/app/main/api/desc/admin/admin_feature.api b/app/main/api/desc/admin/admin_feature.api index 3249c38..06cedb3 100644 --- a/app/main/api/desc/admin/admin_feature.api +++ b/app/main/api/desc/admin/admin_feature.api @@ -33,6 +33,14 @@ service main { // 获取功能详情 @handler AdminGetFeatureDetail get /detail/:id (AdminGetFeatureDetailReq) returns (AdminGetFeatureDetailResp) + + // 配置功能示例数据 + @handler AdminConfigFeatureExample + post /config-example (AdminConfigFeatureExampleReq) returns (AdminConfigFeatureExampleResp) + + // 查看功能示例数据 + @handler AdminGetFeatureExample + get /example/:feature_id (AdminGetFeatureExampleReq) returns (AdminGetFeatureExampleResp) } type ( @@ -105,4 +113,27 @@ type ( CreateTime string `json:"create_time"` // 创建时间 UpdateTime string `json:"update_time"` // 更新时间 } + + // 配置功能示例数据请求 + AdminConfigFeatureExampleReq { + FeatureId int64 `json:"feature_id"` // 功能ID + Data string `json:"data"` // 示例数据JSON + } + // 配置功能示例数据响应 + AdminConfigFeatureExampleResp { + Success bool `json:"success"` // 是否成功 + } + // 查看功能示例数据请求 + AdminGetFeatureExampleReq { + FeatureId int64 `path:"feature_id"` // 功能ID + } + // 查看功能示例数据响应 + AdminGetFeatureExampleResp { + Id int64 `json:"id"` // 示例数据ID + FeatureId int64 `json:"feature_id"` // 功能ID + ApiId string `json:"api_id"` // API标识 + Data string `json:"data"` // 示例数据JSON + CreateTime string `json:"create_time"` // 创建时间 + UpdateTime string `json:"update_time"` // 更新时间 + } ) \ No newline at end of file diff --git a/app/main/api/internal/handler/admin_feature/adminconfigfeatureexamplehandler.go b/app/main/api/internal/handler/admin_feature/adminconfigfeatureexamplehandler.go new file mode 100644 index 0000000..a0cca3f --- /dev/null +++ b/app/main/api/internal/handler/admin_feature/adminconfigfeatureexamplehandler.go @@ -0,0 +1,29 @@ +package admin_feature + +import ( + "net/http" + + "github.com/zeromicro/go-zero/rest/httpx" + "znc-server/app/main/api/internal/logic/admin_feature" + "znc-server/app/main/api/internal/svc" + "znc-server/app/main/api/internal/types" + "znc-server/common/result" + "znc-server/pkg/lzkit/validator" +) + +func AdminConfigFeatureExampleHandler(svcCtx *svc.ServiceContext) http.HandlerFunc { + return func(w http.ResponseWriter, r *http.Request) { + var req types.AdminConfigFeatureExampleReq + if err := httpx.Parse(r, &req); err != nil { + result.ParamErrorResult(r, w, err) + return + } + if err := validator.Validate(req); err != nil { + result.ParamValidateErrorResult(r, w, err) + return + } + l := admin_feature.NewAdminConfigFeatureExampleLogic(r.Context(), svcCtx) + resp, err := l.AdminConfigFeatureExample(&req) + result.HttpResult(r, w, resp, err) + } +} diff --git a/app/main/api/internal/handler/admin_feature/admingetfeatureexamplehandler.go b/app/main/api/internal/handler/admin_feature/admingetfeatureexamplehandler.go new file mode 100644 index 0000000..0427d87 --- /dev/null +++ b/app/main/api/internal/handler/admin_feature/admingetfeatureexamplehandler.go @@ -0,0 +1,29 @@ +package admin_feature + +import ( + "net/http" + + "github.com/zeromicro/go-zero/rest/httpx" + "znc-server/app/main/api/internal/logic/admin_feature" + "znc-server/app/main/api/internal/svc" + "znc-server/app/main/api/internal/types" + "znc-server/common/result" + "znc-server/pkg/lzkit/validator" +) + +func AdminGetFeatureExampleHandler(svcCtx *svc.ServiceContext) http.HandlerFunc { + return func(w http.ResponseWriter, r *http.Request) { + var req types.AdminGetFeatureExampleReq + if err := httpx.Parse(r, &req); err != nil { + result.ParamErrorResult(r, w, err) + return + } + if err := validator.Validate(req); err != nil { + result.ParamValidateErrorResult(r, w, err) + return + } + l := admin_feature.NewAdminGetFeatureExampleLogic(r.Context(), svcCtx) + resp, err := l.AdminGetFeatureExample(&req) + result.HttpResult(r, w, resp, err) + } +} diff --git a/app/main/api/internal/handler/routes.go b/app/main/api/internal/handler/routes.go index 1ace614..cbcc9b2 100644 --- a/app/main/api/internal/handler/routes.go +++ b/app/main/api/internal/handler/routes.go @@ -110,6 +110,11 @@ func RegisterHandlers(server *rest.Server, serverCtx *svc.ServiceContext) { server.AddRoutes( []rest.Route{ + { + Method: http.MethodPost, + Path: "/config-example", + Handler: admin_feature.AdminConfigFeatureExampleHandler(serverCtx), + }, { Method: http.MethodPost, Path: "/create", @@ -125,6 +130,11 @@ func RegisterHandlers(server *rest.Server, serverCtx *svc.ServiceContext) { Path: "/detail/:id", Handler: admin_feature.AdminGetFeatureDetailHandler(serverCtx), }, + { + Method: http.MethodGet, + Path: "/example/:feature_id", + Handler: admin_feature.AdminGetFeatureExampleHandler(serverCtx), + }, { Method: http.MethodGet, Path: "/list", diff --git a/app/main/api/internal/logic/admin_feature/adminconfigfeatureexamplelogic.go b/app/main/api/internal/logic/admin_feature/adminconfigfeatureexamplelogic.go new file mode 100644 index 0000000..150c105 --- /dev/null +++ b/app/main/api/internal/logic/admin_feature/adminconfigfeatureexamplelogic.go @@ -0,0 +1,92 @@ +package admin_feature + +import ( + "context" + "encoding/hex" + + "znc-server/app/main/api/internal/svc" + "znc-server/app/main/api/internal/types" + "znc-server/app/main/model" + "znc-server/common/xerr" + "znc-server/pkg/lzkit/crypto" + + "github.com/pkg/errors" + "github.com/zeromicro/go-zero/core/logx" +) + +type AdminConfigFeatureExampleLogic struct { + logx.Logger + ctx context.Context + svcCtx *svc.ServiceContext +} + +func NewAdminConfigFeatureExampleLogic(ctx context.Context, svcCtx *svc.ServiceContext) *AdminConfigFeatureExampleLogic { + return &AdminConfigFeatureExampleLogic{ + Logger: logx.WithContext(ctx), + ctx: ctx, + svcCtx: svcCtx, + } +} + +func (l *AdminConfigFeatureExampleLogic) AdminConfigFeatureExample(req *types.AdminConfigFeatureExampleReq) (resp *types.AdminConfigFeatureExampleResp, err error) { +// 1. 验证功能是否存在 +feature, err := l.svcCtx.FeatureModel.FindOne(l.ctx, req.FeatureId) +if err != nil && !errors.Is(err, model.ErrNotFound) { + return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), + "查询功能失败, featureId: %d, err: %v", req.FeatureId, err) +} +if feature == nil { + return nil, errors.Wrapf(xerr.NewErrCode(xerr.REUQEST_PARAM_ERROR), + "功能不存在, featureId: %d", req.FeatureId) +} + +// 2. 检查是否已存在示例数据 +existingExample, err := l.svcCtx.ExampleModel.FindOneByFeatureId(l.ctx, req.FeatureId) +if err != nil && !errors.Is(err, model.ErrNotFound) { + return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), + "查询示例数据失败, featureId: %d, err: %v", req.FeatureId, err) +} + +// 3. 加密示例数据 +secretKey := l.svcCtx.Config.Encrypt.SecretKey +key, decodeErr := hex.DecodeString(secretKey) +if decodeErr != nil { + return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), + "获取AES密钥失败: %v", decodeErr) +} + +encryptedData, aesEncryptErr := crypto.AesEncrypt([]byte(req.Data), key) +if aesEncryptErr != nil { + return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), + "加密示例数据失败: %v", aesEncryptErr) +} + +// 4. 准备示例数据 +exampleData := &model.Example{ + ApiId: feature.ApiId, + FeatureId: req.FeatureId, + Content: encryptedData, +} + +// 4. 根据是否存在决定新增或更新 +if existingExample == nil { + // 新增示例数据 + _, err = l.svcCtx.ExampleModel.Insert(l.ctx, nil, exampleData) + if err != nil { + return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), + "创建示例数据失败, featureId: %d, err: %v", req.FeatureId, err) + } +} else { + // 更新示例数据 + exampleData.Id = existingExample.Id + exampleData.Version = existingExample.Version + _, err = l.svcCtx.ExampleModel.Update(l.ctx, nil, exampleData) + if err != nil { + return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), + "更新示例数据失败, featureId: %d, err: %v", req.FeatureId, err) + } +} + +// 5. 返回成功结果 +return &types.AdminConfigFeatureExampleResp{Success: true}, nil +} diff --git a/app/main/api/internal/logic/admin_feature/admingetfeatureexamplelogic.go b/app/main/api/internal/logic/admin_feature/admingetfeatureexamplelogic.go new file mode 100644 index 0000000..76c4b75 --- /dev/null +++ b/app/main/api/internal/logic/admin_feature/admingetfeatureexamplelogic.go @@ -0,0 +1,82 @@ +package admin_feature + +import ( + "context" + "encoding/hex" + + "znc-server/app/main/api/internal/svc" + "znc-server/app/main/api/internal/types" + "znc-server/app/main/model" + "znc-server/common/xerr" + "znc-server/pkg/lzkit/crypto" + + "github.com/pkg/errors" + "github.com/zeromicro/go-zero/core/logx" +) + +type AdminGetFeatureExampleLogic struct { + logx.Logger + ctx context.Context + svcCtx *svc.ServiceContext +} + +func NewAdminGetFeatureExampleLogic(ctx context.Context, svcCtx *svc.ServiceContext) *AdminGetFeatureExampleLogic { + return &AdminGetFeatureExampleLogic{ + Logger: logx.WithContext(ctx), + ctx: ctx, + svcCtx: svcCtx, + } +} + +func (l *AdminGetFeatureExampleLogic) AdminGetFeatureExample(req *types.AdminGetFeatureExampleReq) (resp *types.AdminGetFeatureExampleResp, err error) { + // 1. 查询示例数据 + example, err := l.svcCtx.ExampleModel.FindOneByFeatureId(l.ctx, req.FeatureId) + if err != nil { + if errors.Is(err, model.ErrNotFound) { + // 示例数据不存在,返回空数据 + return &types.AdminGetFeatureExampleResp{ + Id: 0, + FeatureId: req.FeatureId, + ApiId: "", + Data: "", + CreateTime: "", + UpdateTime: "", + }, nil + } + return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), + "查询示例数据失败, featureId: %d, err: %v", req.FeatureId, err) + } + + // 2. 获取解密密钥 + secretKey := l.svcCtx.Config.Encrypt.SecretKey + key, decodeErr := hex.DecodeString(secretKey) + if decodeErr != nil { + return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), + "获取AES密钥失败: %v", decodeErr) + } + + // 3. 解密示例数据 + var decryptedData string + if example.Content == "000" { + // 特殊值,直接返回 + decryptedData = example.Content + } else { + // 解密数据 + decryptedBytes, decryptErr := crypto.AesDecrypt(example.Content, key) + if decryptErr != nil { + return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), + "解密示例数据失败: %v", decryptErr) + } + decryptedData = string(decryptedBytes) + } + + // 4. 返回解密后的数据 + return &types.AdminGetFeatureExampleResp{ + Id: example.Id, + FeatureId: example.FeatureId, + ApiId: example.ApiId, + Data: decryptedData, + CreateTime: example.CreateTime.Format("2006-01-02 15:04:05"), + UpdateTime: example.UpdateTime.Format("2006-01-02 15:04:05"), + }, nil +} diff --git a/app/main/api/internal/types/types.go b/app/main/api/internal/types/types.go index dd57ff0..f8e0993 100644 --- a/app/main/api/internal/types/types.go +++ b/app/main/api/internal/types/types.go @@ -15,6 +15,15 @@ type ActiveRewardData struct { SubWithdrawReward float64 `json:"sub_withdraw_reward"` } +type AdminConfigFeatureExampleReq struct { + FeatureId int64 `json:"feature_id"` // 功能ID + Data string `json:"data"` // 示例数据JSON +} + +type AdminConfigFeatureExampleResp struct { + Success bool `json:"success"` // 是否成功 +} + type AdminCreateFeatureReq struct { ApiId string `json:"api_id"` // API标识 Name string `json:"name"` // 描述 @@ -281,6 +290,19 @@ type AdminGetFeatureDetailResp struct { UpdateTime string `json:"update_time"` // 更新时间 } +type AdminGetFeatureExampleReq struct { + FeatureId int64 `path:"feature_id"` // 功能ID +} + +type AdminGetFeatureExampleResp struct { + Id int64 `json:"id"` // 示例数据ID + FeatureId int64 `json:"feature_id"` // 功能ID + ApiId string `json:"api_id"` // API标识 + Data string `json:"data"` // 示例数据JSON + CreateTime string `json:"create_time"` // 创建时间 + UpdateTime string `json:"update_time"` // 更新时间 +} + type AdminGetFeatureListReq struct { Page int64 `form:"page"` // 页码 PageSize int64 `form:"pageSize"` // 每页数量