diff --git a/app/user/cmd/api/desc/query.api b/app/user/cmd/api/desc/query.api index 71f5b00..19c141a 100644 --- a/app/user/cmd/api/desc/query.api +++ b/app/user/cmd/api/desc/query.api @@ -106,8 +106,22 @@ service main { @doc "更新查询数据" @handler updateQueryData post /query/update_data (UpdateQueryDataReq) returns (UpdateQueryDataResp) + + @doc "生成分享链接" + @handler QueryGenerateShareLink + post /query/generate_share_link (QueryGenerateShareLinkReq) returns (QueryGenerateShareLinkResp) } +type ( + QueryGenerateShareLinkReq { + OrderId int64 `path:"order_id,optional"` + OrderNo string `path:"order_no,optional"` + } + QueryGenerateShareLinkResp { + ShareLink string `json:"share_link"` + } +) + // 获取查询临时订单 type ( QueryProvisionalOrderReq { @@ -141,14 +155,6 @@ type ( } ) -type ( - QueryDetailReq { - Id int64 `path:"id"` - } - QueryDetailResp { - Query - } -) type ( QueryDetailByOrderIdReq { @@ -198,14 +204,22 @@ service main { post /query/single/test (QuerySingleTestReq) returns (QuerySingleTestResp) @doc "查询详情" - @handler queryDetail - get /query/:id (QueryDetailReq) returns (QueryDetailResp) + @handler queryShareDetail + get /query/share/:id (QueryShareDetailReq) returns (QueryShareDetailResp) @doc "查询示例" @handler queryExample get /query/example (QueryExampleReq) returns (QueryExampleResp) } +type ( + QueryShareDetailReq { + Id string `path:"id"` + } + QueryShareDetailResp { + Query + } +) type QuerySingleTestReq { Params map[string]interface{} `json:"params"` diff --git a/app/user/cmd/api/etc/main.dev.yaml b/app/user/cmd/api/etc/main.dev.yaml index b61e0e7..efb6e3f 100644 --- a/app/user/cmd/api/etc/main.dev.yaml +++ b/app/user/cmd/api/etc/main.dev.yaml @@ -64,3 +64,5 @@ SystemConfig: WechatH5: AppID: "wxa581992dc74d860e" AppSecret: "ba37510206df321279222cecb8614e00" +Query: + ShareLinkExpire: 604800 # 7天 = 7 * 24 * 60 * 60 = 604800秒 diff --git a/app/user/cmd/api/etc/main.yaml b/app/user/cmd/api/etc/main.yaml index d68ab0d..7d64c35 100644 --- a/app/user/cmd/api/etc/main.yaml +++ b/app/user/cmd/api/etc/main.yaml @@ -65,3 +65,5 @@ SystemConfig: WechatH5: AppID: "wxa581992dc74d860e" AppSecret: "ba37510206df321279222cecb8614e00" +Query: + ShareLinkExpire: 604800 # 7天 = 7 * 24 * 60 * 60 = 604800秒 diff --git a/app/user/cmd/api/internal/config/config.go b/app/user/cmd/api/internal/config/config.go index aacc028..2c09786 100644 --- a/app/user/cmd/api/internal/config/config.go +++ b/app/user/cmd/api/internal/config/config.go @@ -20,6 +20,7 @@ type Config struct { YushanConfig YushanConfig SystemConfig SystemConfig WechatH5 WechatH5Config + Query QueryConfig } // JwtAuth 用于 JWT 鉴权配置 @@ -92,3 +93,6 @@ type WechatH5Config struct { AppID string AppSecret string } +type QueryConfig struct { + ShareLinkExpire int64 +} diff --git a/app/user/cmd/api/internal/handler/query/querygeneratesharelinkhandler.go b/app/user/cmd/api/internal/handler/query/querygeneratesharelinkhandler.go new file mode 100644 index 0000000..887756e --- /dev/null +++ b/app/user/cmd/api/internal/handler/query/querygeneratesharelinkhandler.go @@ -0,0 +1,29 @@ +package query + +import ( + "net/http" + + "github.com/zeromicro/go-zero/rest/httpx" + "tydata-server/app/user/cmd/api/internal/logic/query" + "tydata-server/app/user/cmd/api/internal/svc" + "tydata-server/app/user/cmd/api/internal/types" + "tydata-server/common/result" + "tydata-server/pkg/lzkit/validator" +) + +func QueryGenerateShareLinkHandler(svcCtx *svc.ServiceContext) http.HandlerFunc { + return func(w http.ResponseWriter, r *http.Request) { + var req types.QueryGenerateShareLinkReq + 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 := query.NewQueryGenerateShareLinkLogic(r.Context(), svcCtx) + resp, err := l.QueryGenerateShareLink(&req) + result.HttpResult(r, w, resp, err) + } +} diff --git a/app/user/cmd/api/internal/handler/query/querydetailhandler.go b/app/user/cmd/api/internal/handler/query/querysharedetailhandler.go similarity index 74% rename from app/user/cmd/api/internal/handler/query/querydetailhandler.go rename to app/user/cmd/api/internal/handler/query/querysharedetailhandler.go index bbd9884..d676e14 100644 --- a/app/user/cmd/api/internal/handler/query/querydetailhandler.go +++ b/app/user/cmd/api/internal/handler/query/querysharedetailhandler.go @@ -3,18 +3,17 @@ package query import ( "net/http" + "github.com/zeromicro/go-zero/rest/httpx" "tydata-server/app/user/cmd/api/internal/logic/query" "tydata-server/app/user/cmd/api/internal/svc" "tydata-server/app/user/cmd/api/internal/types" "tydata-server/common/result" "tydata-server/pkg/lzkit/validator" - - "github.com/zeromicro/go-zero/rest/httpx" ) -func QueryDetailHandler(svcCtx *svc.ServiceContext) http.HandlerFunc { +func QueryShareDetailHandler(svcCtx *svc.ServiceContext) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { - var req types.QueryDetailReq + var req types.QueryShareDetailReq if err := httpx.Parse(r, &req); err != nil { result.ParamErrorResult(r, w, err) return @@ -23,8 +22,8 @@ func QueryDetailHandler(svcCtx *svc.ServiceContext) http.HandlerFunc { result.ParamValidateErrorResult(r, w, err) return } - l := query.NewQueryDetailLogic(r.Context(), svcCtx) - resp, err := l.QueryDetail(&req) + l := query.NewQueryShareDetailLogic(r.Context(), svcCtx) + resp, err := l.QueryShareDetail(&req) result.HttpResult(r, w, resp, err) } } diff --git a/app/user/cmd/api/internal/handler/routes.go b/app/user/cmd/api/internal/handler/routes.go index 68c8936..b4c593d 100644 --- a/app/user/cmd/api/internal/handler/routes.go +++ b/app/user/cmd/api/internal/handler/routes.go @@ -275,6 +275,12 @@ func RegisterHandlers(server *rest.Server, serverCtx *svc.ServiceContext) { server.AddRoutes( []rest.Route{ + { + // 生成分享链接 + Method: http.MethodPost, + Path: "/query/generate_share_link", + Handler: query.QueryGenerateShareLinkHandler(serverCtx), + }, { // 查询列表 Method: http.MethodGet, @@ -318,18 +324,18 @@ func RegisterHandlers(server *rest.Server, serverCtx *svc.ServiceContext) { server.AddRoutes( []rest.Route{ - { - // 查询详情 - Method: http.MethodGet, - Path: "/query/:id", - Handler: query.QueryDetailHandler(serverCtx), - }, { // 查询示例 Method: http.MethodGet, Path: "/query/example", Handler: query.QueryExampleHandler(serverCtx), }, + { + // 查询详情 + Method: http.MethodGet, + Path: "/query/share/:id", + Handler: query.QueryShareDetailHandler(serverCtx), + }, { Method: http.MethodPost, Path: "/query/single/test", diff --git a/app/user/cmd/api/internal/logic/query/querydetailbyorderidlogic.go b/app/user/cmd/api/internal/logic/query/querydetailbyorderidlogic.go index 93fbb34..a947745 100644 --- a/app/user/cmd/api/internal/logic/query/querydetailbyorderidlogic.go +++ b/app/user/cmd/api/internal/logic/query/querydetailbyorderidlogic.go @@ -6,11 +6,9 @@ import ( "encoding/hex" "encoding/json" "fmt" - "time" "tydata-server/common/ctxdata" "tydata-server/common/xerr" "tydata-server/pkg/lzkit/crypto" - "tydata-server/pkg/lzkit/delay" "tydata-server/pkg/lzkit/lzUtils" "github.com/jinzhu/copier" @@ -63,71 +61,17 @@ func (l *QueryDetailByOrderIdLogic) QueryDetailByOrderId(req *types.QueryDetailB } } - // 创建渐进式延迟策略实例 - progressiveDelayOrder, err := delay.New(200*time.Millisecond, 3*time.Second, 10*time.Second, 1.5) - if err != nil { - return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "初始化渐进式延迟策略失败: %v", err) - } - - // 等待订单状态变为 "paid" - startTime := time.Now() - for order.Status == "pending" { - if time.Since(startTime) > 10*time.Second { - return nil, errors.Wrapf(xerr.NewErrCodeMsg(xerr.LOGIC_QUERY_WAIT, ""), "") - } - - // 使用渐进式延迟,获取下次延迟时间 - nextDelay, _ := progressiveDelayOrder.NextDelay() - - // 等待一段时间后再查一次订单状态 - time.Sleep(nextDelay) - - // 再次查找订单 - order, err = l.svcCtx.OrderModel.FindOne(l.ctx, req.OrderId) - if err != nil { - return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "报告查询, 查找订单错误: %v", err) - } - } + // 检查订单状态 if order.Status != "paid" { - return nil, errors.Wrapf(xerr.NewErrCodeMsg(xerr.LOGIC_QUERY_ERROR, ""), "") + return nil, errors.Wrapf(xerr.NewErrMsg("订单未支付,无法查看报告"), "") } + // 获取报告信息 queryModel, err := l.svcCtx.QueryModel.FindOneByOrderId(l.ctx, req.OrderId) if err != nil { return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "报告查询, 查找报告错误: %v", err) } - // 创建渐进式延迟实例 - progressiveDelayQuery, err := delay.New(200*time.Millisecond, 3*time.Second, 10*time.Second, 1.5) - if err != nil { - return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "初始化渐进式延迟策略失败: %v", err) - } - - // 等待 queryModel.QueryState 不再是 "pending" - startTime = time.Now() - for queryModel.QueryState == "pending" { - if time.Since(startTime) > 10*time.Second { - return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "报告查询超时,查询状态长时间为 'pending'") - } - - // 使用渐进式延迟,获取下次延迟时间 - nextDelay, _ := progressiveDelayQuery.NextDelay() - - // 每隔一段时间检查一次查询状态 - time.Sleep(nextDelay) - - // 再次查询 report 状态 - queryModel, err = l.svcCtx.QueryModel.FindOneByOrderId(l.ctx, req.OrderId) - if err != nil { - return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "报告查询, 查找报告错误: %v", err) - } - } - - // 根据 QueryState 做后续处理 - if queryModel.QueryState == "failed" { - return nil, errors.Wrapf(xerr.NewErrCodeMsg(xerr.LOGIC_QUERY_ERROR, ""), "") - } - var query types.Query query.CreateTime = queryModel.CreateTime.Format("2006-01-02 15:04:05") query.UpdateTime = queryModel.UpdateTime.Format("2006-01-02 15:04:05") diff --git a/app/user/cmd/api/internal/logic/query/querydetailbyordernologic.go b/app/user/cmd/api/internal/logic/query/querydetailbyordernologic.go index 6ce8650..0ef26bb 100644 --- a/app/user/cmd/api/internal/logic/query/querydetailbyordernologic.go +++ b/app/user/cmd/api/internal/logic/query/querydetailbyordernologic.go @@ -4,10 +4,8 @@ import ( "context" "encoding/hex" "fmt" - "time" "tydata-server/common/ctxdata" "tydata-server/common/xerr" - "tydata-server/pkg/lzkit/delay" "github.com/jinzhu/copier" "github.com/pkg/errors" @@ -54,71 +52,17 @@ func (l *QueryDetailByOrderNoLogic) QueryDetailByOrderNo(req *types.QueryDetailB return nil, errors.Wrapf(xerr.NewErrCode(xerr.LOGIC_QUERY_NOT_FOUND), "无权查看此订单报告") } - // 创建渐进式延迟策略实例 - progressiveDelayOrder, err := delay.New(200*time.Millisecond, 3*time.Second, 10*time.Second, 1.5) - if err != nil { - return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "初始化渐进式延迟策略失败: %v", err) - } - - // 等待订单状态变为 "paid" - startTime := time.Now() - for order.Status == "pending" { - if time.Since(startTime) > 10*time.Second { - return nil, errors.Wrapf(xerr.NewErrCodeMsg(xerr.LOGIC_QUERY_WAIT, ""), "") - } - - // 使用渐进式延迟,获取下次延迟时间 - nextDelay, _ := progressiveDelayOrder.NextDelay() - - // 等待一段时间后再查一次订单状态 - time.Sleep(nextDelay) - - // 再次查找订单 - order, err = l.svcCtx.OrderModel.FindOneByOrderNo(l.ctx, req.OrderNo) - if err != nil { - return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "报告查询, 查找订单错误: %v", err) - } - } + // 检查订单状态 if order.Status != "paid" { - return nil, errors.Wrapf(xerr.NewErrCodeMsg(xerr.LOGIC_QUERY_ERROR, ""), "") + return nil, errors.Wrapf(xerr.NewErrMsg("订单未支付,无法查看报告"), "") } + // 获取报告信息 queryModel, err := l.svcCtx.QueryModel.FindOneByOrderId(l.ctx, order.Id) if err != nil { return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "报告查询, 查找报告错误: %v", err) } - // 创建渐进式延迟实例 - progressiveDelayQuery, err := delay.New(200*time.Millisecond, 3*time.Second, 10*time.Second, 1.5) - if err != nil { - return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "初始化渐进式延迟策略失败: %v", err) - } - - // 等待 queryModel.QueryState 不再是 "pending" - startTime = time.Now() - for queryModel.QueryState == "pending" { - if time.Since(startTime) > 10*time.Second { - return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "报告查询超时,查询状态长时间为 'pending'") - } - - // 使用渐进式延迟,获取下次延迟时间 - nextDelay, _ := progressiveDelayQuery.NextDelay() - - // 每隔一段时间检查一次查询状态 - time.Sleep(nextDelay) - - // 再次查询 report 状态 - queryModel, err = l.svcCtx.QueryModel.FindOneByOrderId(l.ctx, order.Id) - if err != nil { - return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "报告查询, 查找报告错误: %v", err) - } - } - - // 根据 QueryState 做后续处理 - if queryModel.QueryState == "failed" { - return nil, errors.Wrapf(xerr.NewErrCodeMsg(xerr.LOGIC_QUERY_ERROR, ""), "") - } - var query types.Query query.CreateTime = queryModel.CreateTime.Format("2006-01-02 15:04:05") query.UpdateTime = queryModel.UpdateTime.Format("2006-01-02 15:04:05") @@ -155,6 +99,7 @@ func (l *QueryDetailByOrderNoLogic) QueryDetailByOrderNo(req *types.QueryDetailB Query: query, }, nil } + func (l *QueryDetailByOrderNoLogic) UpdateFeatureAndProductFeature(productID int64, target *[]types.QueryItem) error { // 遍历 target 数组,使用倒序遍历,以便删除元素时不影响索引 for i := len(*target) - 1; i >= 0; i-- { diff --git a/app/user/cmd/api/internal/logic/query/querydetaillogic.go b/app/user/cmd/api/internal/logic/query/querydetaillogic.go deleted file mode 100644 index 08e6879..0000000 --- a/app/user/cmd/api/internal/logic/query/querydetaillogic.go +++ /dev/null @@ -1,70 +0,0 @@ -package query - -import ( - "context" - "encoding/hex" - "encoding/json" - "tydata-server/common/xerr" - "tydata-server/pkg/lzkit/crypto" - "tydata-server/pkg/lzkit/lzUtils" - - "github.com/jinzhu/copier" - "github.com/pkg/errors" - - "tydata-server/app/user/cmd/api/internal/svc" - "tydata-server/app/user/cmd/api/internal/types" - - "github.com/zeromicro/go-zero/core/logx" -) - -type QueryDetailLogic struct { - logx.Logger - ctx context.Context - svcCtx *svc.ServiceContext -} - -func NewQueryDetailLogic(ctx context.Context, svcCtx *svc.ServiceContext) *QueryDetailLogic { - return &QueryDetailLogic{ - Logger: logx.WithContext(ctx), - ctx: ctx, - svcCtx: svcCtx, - } -} - -func (l *QueryDetailLogic) QueryDetail(req *types.QueryDetailReq) (resp *types.QueryDetailResp, err error) { - queryModel, err := l.svcCtx.QueryModel.FindOne(l.ctx, req.Id) - if err != nil { - return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "报告查询, 查找报告错误: %v", err) - } - - var query types.Query - query.CreateTime = queryModel.CreateTime.Format("2006-01-02 15:04:05") - query.UpdateTime = queryModel.UpdateTime.Format("2006-01-02 15:04:05") - 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", err) - } - if lzUtils.NullStringToString(queryModel.QueryData) != "" { - queryData, decryptErr := crypto.AesDecrypt(lzUtils.NullStringToString(queryModel.QueryData), key) - if decryptErr != nil { - return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "报告查询, 报告结果解密失败, %+v", decryptErr) - } - unmarshalErr := json.Unmarshal(queryData, &query.QueryData) - if unmarshalErr != nil { - return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "报告查询, 报告结构体处理失败, %+v", unmarshalErr) - } - } - err = copier.Copy(&query, queryModel) - if err != nil { - return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "报告查询, 报告结构体复制失败, %v", err) - } - product, err := l.svcCtx.ProductModel.FindOne(l.ctx, queryModel.ProductId) - if err != nil { - return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "报告查询, 获取商品信息失败, %v", err) - } - query.ProductName = product.ProductName - return &types.QueryDetailResp{ - Query: query, - }, nil -} diff --git a/app/user/cmd/api/internal/logic/query/querygeneratesharelinklogic.go b/app/user/cmd/api/internal/logic/query/querygeneratesharelinklogic.go new file mode 100644 index 0000000..5db6bec --- /dev/null +++ b/app/user/cmd/api/internal/logic/query/querygeneratesharelinklogic.go @@ -0,0 +1,104 @@ +package query + +import ( + "context" + "encoding/hex" + "encoding/json" + "time" + + "tydata-server/app/user/cmd/api/internal/svc" + "tydata-server/app/user/cmd/api/internal/types" + "tydata-server/app/user/model" + "tydata-server/common/ctxdata" + "tydata-server/common/xerr" + "tydata-server/pkg/lzkit/crypto" + + "github.com/pkg/errors" + "github.com/zeromicro/go-zero/core/logx" +) + +type QueryGenerateShareLinkLogic struct { + logx.Logger + ctx context.Context + svcCtx *svc.ServiceContext +} + +func NewQueryGenerateShareLinkLogic(ctx context.Context, svcCtx *svc.ServiceContext) *QueryGenerateShareLinkLogic { + return &QueryGenerateShareLinkLogic{ + Logger: logx.WithContext(ctx), + ctx: ctx, + svcCtx: svcCtx, + } +} + +func (l *QueryGenerateShareLinkLogic) QueryGenerateShareLink(req *types.QueryGenerateShareLinkReq) (resp *types.QueryGenerateShareLinkResp, err error) { + userId, err := ctxdata.GetUidFromCtx(l.ctx) + if err != nil { + return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "生成分享链接, 获取用户ID失败: %v", err) + } + + // 检查参数 + if req.OrderId == 0 && req.OrderNo == "" { + return nil, errors.Wrapf(xerr.NewErrMsg("订单ID和订单号不能同时为空"), "") + } + + var order *model.Order + // 优先使用OrderId查询 + if req.OrderId != 0 { + order, err = l.svcCtx.OrderModel.FindOne(l.ctx, req.OrderId) + if err != nil { + if errors.Is(err, model.ErrNotFound) { + return nil, errors.Wrapf(xerr.NewErrMsg("订单不存在"), "") + } + return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "生成分享链接, 获取订单失败: %v", err) + } + } else { + // 使用OrderNo查询 + order, err = l.svcCtx.OrderModel.FindOneByOrderNo(l.ctx, req.OrderNo) + if err != nil { + if errors.Is(err, model.ErrNotFound) { + return nil, errors.Wrapf(xerr.NewErrMsg("订单不存在"), "") + } + return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "生成分享链接, 获取订单失败: %v", err) + } + } + + if order.Status != model.OrderStatusPaid { + return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "生成分享链接, 订单未支付") + } + + query, err := l.svcCtx.QueryModel.FindOneByOrderId(l.ctx, order.Id) + if err != nil { + return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "生成分享链接, 获取查询失败: %v", err) + } + + if query.QueryState != model.QueryStateSuccess { + return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "生成分享链接, 查询未成功") + } + + if order.UserId != userId { + return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "生成分享链接, 无权操作此订单") + } + + expireAt := time.Now().Add(time.Duration(l.svcCtx.Config.Query.ShareLinkExpire) * time.Second) + payload := types.QueryShareLinkPayload{ + OrderId: order.Id, // 使用查询到的订单ID + ExpireAt: expireAt.Unix(), + } + secretKey := l.svcCtx.Config.Encrypt.SecretKey + key, err := hex.DecodeString(secretKey) + if err != nil { + return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "生成分享链接, 解密失败: %v", err) + } + payloadBytes, err := json.Marshal(payload) + if err != nil { + return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "生成分享链接, 序列化失败: %v", err) + } + encryptedPayload, err := crypto.AesEncrypt(payloadBytes, key) + if err != nil { + return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "生成分享链接, 加密失败: %v", err) + } + return &types.QueryGenerateShareLinkResp{ + ShareLink: encryptedPayload, + }, nil +} diff --git a/app/user/cmd/api/internal/logic/query/querysharedetaillogic.go b/app/user/cmd/api/internal/logic/query/querysharedetaillogic.go new file mode 100644 index 0000000..b3385c2 --- /dev/null +++ b/app/user/cmd/api/internal/logic/query/querysharedetaillogic.go @@ -0,0 +1,151 @@ +package query + +import ( + "context" + "encoding/hex" + "fmt" + "strconv" + + "tydata-server/app/user/cmd/api/internal/svc" + "tydata-server/app/user/cmd/api/internal/types" + "tydata-server/app/user/model" + "tydata-server/common/xerr" + "tydata-server/pkg/lzkit/crypto" + + "github.com/jinzhu/copier" + "github.com/pkg/errors" + "github.com/zeromicro/go-zero/core/logx" +) + +type QueryShareDetailLogic struct { + logx.Logger + ctx context.Context + svcCtx *svc.ServiceContext +} + +func NewQueryShareDetailLogic(ctx context.Context, svcCtx *svc.ServiceContext) *QueryShareDetailLogic { + return &QueryShareDetailLogic{ + Logger: logx.WithContext(ctx), + ctx: ctx, + svcCtx: svcCtx, + } +} + +func (l *QueryShareDetailLogic) QueryShareDetail(req *types.QueryShareDetailReq) (resp *types.QueryShareDetailResp, err error) { + 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", err) + } + decryptedID, decryptErr := crypto.AesDecrypt(req.Id, key) + if decryptErr != nil { + return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "报告查询, 解密数据失败: %v", decryptErr) + } + // 获取订单信息 + orderID, err := strconv.ParseInt(string(decryptedID), 10, 64) + if err != nil { + return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "报告查询, 解密ID转换失败: %v", err) + } + order, err := l.svcCtx.OrderModel.FindOne(l.ctx, orderID) + if err != nil { + if errors.Is(err, model.ErrNotFound) { + return nil, errors.Wrapf(xerr.NewErrCode(xerr.LOGIC_QUERY_NOT_FOUND), "报告查询, 订单不存在: %v", err) + } + return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "报告查询, 查找报告错误: %v", err) + } + + // 检查订单状态 + if order.Status != "paid" { + return nil, errors.Wrapf(xerr.NewErrMsg("订单未支付,无法查看报告"), "") + } + + // 获取报告信息 + queryModel, err := l.svcCtx.QueryModel.FindOneByOrderId(l.ctx, order.Id) + if err != nil { + return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "报告查询, 查找报告错误: %v", err) + } + + var query types.Query + query.CreateTime = queryModel.CreateTime.Format("2006-01-02 15:04:05") + query.UpdateTime = queryModel.UpdateTime.Format("2006-01-02 15:04:05") + + processParamsErr := ProcessQueryParams(queryModel.QueryParams, &query.QueryParams, key) + if processParamsErr != nil { + return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "报告查询, 报告参数处理失败: %v", processParamsErr) + } + processErr := ProcessQueryData(queryModel.QueryData, &query.QueryData, key) + if processErr != nil { + return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "报告查询, 报告结果处理失败: %v", processErr) + } + updateFeatureAndProductFeatureErr := l.UpdateFeatureAndProductFeature(queryModel.ProductId, &query.QueryData) + if updateFeatureAndProductFeatureErr != nil { + return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "报告查询, 报告结果处理失败: %v", updateFeatureAndProductFeatureErr) + } + // 复制报告数据 + err = copier.Copy(&query, queryModel) + if err != nil { + return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "报告查询, 报告结构体复制失败, %v", err) + } + product, err := l.svcCtx.ProductModel.FindOne(l.ctx, queryModel.ProductId) + if err != nil { + return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "报告查询, 获取商品信息失败, %v", err) + } + query.ProductName = product.ProductName + return &types.QueryShareDetailResp{ + Query: query, + }, nil +} + +func (l *QueryShareDetailLogic) UpdateFeatureAndProductFeature(productID int64, target *[]types.QueryItem) error { + // 遍历 target 数组,使用倒序遍历,以便删除元素时不影响索引 + for i := len(*target) - 1; i >= 0; i-- { + queryItem := &(*target)[i] + + // 确保 Data 为 map 类型 + data, ok := queryItem.Data.(map[string]interface{}) + if !ok { + return fmt.Errorf("queryItem.Data 必须是 map[string]interface{} 类型") + } + + // 从 Data 中获取 apiID + apiID, ok := data["apiID"].(string) + if !ok { + return fmt.Errorf("queryItem.Data 中的 apiID 必须是字符串类型") + } + + // 查询 Feature + feature, err := l.svcCtx.FeatureModel.FindOneByApiId(l.ctx, apiID) + if err != nil { + // 如果 Feature 查不到,也要删除当前 QueryItem + *target = append((*target)[:i], (*target)[i+1:]...) + continue + } + + // 查询 ProductFeatureModel + builder := l.svcCtx.ProductFeatureModel.SelectBuilder().Where("product_id = ?", productID) + productFeatures, err := l.svcCtx.ProductFeatureModel.FindAll(l.ctx, builder, "") + if err != nil { + return fmt.Errorf("查询 ProductFeatureModel 错误: %v", err) + } + + // 遍历 productFeatures,找到与 feature.ID 关联且 enable == 1 的项 + var featureData map[string]interface{} + // foundFeature := false + sort := 0 + for _, pf := range productFeatures { + if pf.FeatureId == feature.Id { // 确保和 Feature 关联 + sort = int(pf.Sort) + break // 找到第一个符合条件的就退出循环 + } + } + featureData = map[string]interface{}{ + "featureName": feature.Name, + "sort": sort, + } + + // 更新 queryItem 的 Feature 字段(不是数组) + queryItem.Feature = featureData + } + + return nil +} diff --git a/app/user/cmd/api/internal/types/encrypPayload.go b/app/user/cmd/api/internal/types/encrypPayload.go new file mode 100644 index 0000000..3c6e385 --- /dev/null +++ b/app/user/cmd/api/internal/types/encrypPayload.go @@ -0,0 +1,6 @@ +package types + +type QueryShareLinkPayload struct { + OrderId int64 `json:"order_id"` + ExpireAt int64 `json:"expire_at"` +} diff --git a/app/user/cmd/api/internal/types/types.go b/app/user/cmd/api/internal/types/types.go index a5b215e..cddc0df 100644 --- a/app/user/cmd/api/internal/types/types.go +++ b/app/user/cmd/api/internal/types/types.go @@ -363,14 +363,6 @@ type QueryDetailByOrderNoResp struct { Query } -type QueryDetailReq struct { - Id int64 `path:"id"` -} - -type QueryDetailResp struct { - Query -} - type QueryExampleReq struct { Feature string `form:"feature"` } @@ -379,6 +371,15 @@ type QueryExampleResp struct { Query } +type QueryGenerateShareLinkReq struct { + OrderId int64 `path:"order_id,optional"` + OrderNo string `path:"order_no,optional"` +} + +type QueryGenerateShareLinkResp struct { + ShareLink string `json:"share_link"` +} + type QueryItem struct { Feature interface{} `json:"feature"` Data interface{} `json:"data"` // 这里可以是 map 或 具体的 struct @@ -435,6 +436,14 @@ type QueryServiceResp struct { RefreshAfter int64 `json:"refreshAfter"` } +type QueryShareDetailReq struct { + Id string `path:"id"` +} + +type QueryShareDetailResp struct { + Query +} + type QuerySingleTestReq struct { Params map[string]interface{} `json:"params"` Api string `json:"api"` diff --git a/app/user/model/vars.go b/app/user/model/vars.go index 5716cca..cb455aa 100644 --- a/app/user/model/vars.go +++ b/app/user/model/vars.go @@ -31,3 +31,42 @@ var AgentRewardsTypeDescendantWithdraw string = "descendant_withdraw" var AgentLeveNameNormal string = "normal" var AgentLeveNameVIP string = "VIP" var AgentLeveNameSVIP string = "SVIP" + +const ( + OrderStatusPending = "pending" + OrderStatusPaid = "paid" + OrderStatusFailed = "failed" + OrderStatusRefunded = "refunded" + OrderStatusClosed = "closed" +) + +const ( + QueryStatePending = "pending" + QueryStateFailed = "failed" + QueryStateSuccess = "success" + QueryStateProcessing = "processing" +) + +const ( + GrantTypeFace string = "face" +) +const ( + AuthorizationStatusPending = "pending" + AuthorizationStatusSuccess = "success" + AuthorizationStatusFailed = "failed" + AuthorizationStatusExpired = "expired" + AuthorizationStatusRevoked = "revoked" + AuthorizationStatusRejected = "rejected" +) + +const ( + AuthorizationFaceStatusPending = "pending" + AuthorizationFaceStatusSuccess = "success" + AuthorizationFaceStatusFailed = "failed" +) + +const ( + AgentRealNameStatusPending = "pending" + AgentRealNameStatusApproved = "approved" + AgentRealNameStatusRejected = "rejected" +) diff --git a/temp/agent/agent.api b/temp/agent/agent.api deleted file mode 100644 index 92e0ca6..0000000 --- a/temp/agent/agent.api +++ /dev/null @@ -1,211 +0,0 @@ -syntax = "v1" - -info ( - title: "代理服务" - desc: "代理服务接口" - author: "Liangzai" - email: "2440983361@qq.com" - version: "v1" -) - -type AgentProductConfig { - ProductID int64 `json:"product_id"` - CostPrice float64 `json:"cost_price"` - PriceRangeMin float64 `json:"price_range_min"` - PriceRangeMax float64 `json:"price_range_max"` - PPricingStandard float64 `json:"p_pricing_standard"` - POverpricingRatio float64 `json:"p_overpricing_ratio"` - APricingStandard float64 `json:"a_pricing_standard"` - APricingEnd float64 `json:"a_pricing_end"` - AOverpricingRatio float64 `json:"a_overpricing_ratio"` -} - -type AgentMembershipUserConfig { - ProductID int64 `json:"product_id"` - PriceIncreaseAmount float64 `json:"price_increase_amount"` - PriceRangeFrom float64 `json:"price_range_from"` - PriceRangeTo float64 `json:"price_range_to"` - PriceRatio float64 `json:"price_ratio"` -} - -type ProductConfig { - ProductID int64 `json:"product_id"` - CostPrice float64 `json:"cost_price"` - PriceRangeMin float64 `json:"price_range_min"` - PriceRangeMax float64 `json:"price_range_max"` -} - -type ( - AgentInfoResp { - status int64 `json:"status"` // 0=待审核,1=审核通过,2=审核未通过,3=未申请 - isAgent bool `json:"is_agent"` - agentID int64 `json:"agent_id"` - level string `json:"level"` - region string `json:"region"` - mobile string `json:"mobile"` - wechatID string `json:"wechat_id"` - } - // 代理申请请求参数 - AgentApplyReq { - Region string `json:"region"` - Mobile string `json:"mobile"` - WechatID string `json:"wechat_id"` - Code string `json:"code"` - Ancestor string `json:"ancestor,optional"` - } - AgentApplyResp{ - AccessToken string `json:"accessToken"` - AccessExpire int64 `json:"accessExpire"` - RefreshAfter int64 `json:"refreshAfter"` - } - // 查询代理申请状态响应 - AgentAuditStatusResp { - Status int64 `json:"status"` // 0=待审核,1=审核通过,2=审核未通过 - AuditReason string `json:"audit_reason"` - } - AgentGeneratingLinkReq { - Product string `json:"product"` - Price string `json:"price"` - } - AgentGeneratingLinkResp { - LinkIdentifier string `json:"link_identifier"` - } - GetLinkDataReq { - LinkIdentifier string `form:"link_identifier"` - } - GetLinkDataResp { - Product - } - AgentProductConfigResp { - AgentProductConfig []AgentProductConfig - } - // 开通代理会员请求参数 - AgentActivateMembershipReq { - Mobile string `json:"mobile"` - Type string `json:"type,oneof=VIP SVIP"` // 会员类型:vip/svip - Amount float64 `json:"amount"` - PaymentMethod string `json:"payment_method"` - TransactionId string `json:"transaction_id"` - } - // 开通代理会员响应 - AgentActivateMembershipResp { - MembershipType string `json:"membership_type"` // 最终开通的会员类型 - ExpireTime string `json:"expire_time"` // 到期时间 - } - // 获取会员当前配置 - AgentMembershipProductConfigReq { - ProductID int64 `form:"product_id"` - } - // 获取会员当前配置 - AgentMembershipProductConfigResp { - AgentMembershipUserConfig AgentMembershipUserConfig `json:"agent_membership_user_config"` - ProductConfig ProductConfig `json:"product_config"` - PriceIncreaseMax float64 `json:"price_increase_max"` - PriceIncreaseAmount float64 `json:"price_increase_amount"` - PriceRatio float64 `json:"price_ratio"` - } - SaveAgentMembershipUserConfigReq { - ProductID int64 `json:"product_id"` - PriceIncreaseAmount float64 `json:"price_increase_amount"` - PriceRangeFrom float64 `json:"price_range_from"` - PriceRangeTo float64 `json:"price_range_to"` - PriceRatio float64 `json:"price_ratio"` - } -) - -type ( - // 收益信息 - GetAgentRevenueInfoReq {} - GetAgentRevenueInfoResp { - Balance float64 `json:"balance"` - FrozenBalance float64 `json:"frozen_balance"` - TotalEarnings float64 `json:"total_earnings"` - DirectPush DirectPushReport `json:"direct_push"` // 直推报告数据 - ActiveReward ActiveReward `json:"active_reward"` // 活跃下级奖励数据 - } - // 直推报告数据结构 - DirectPushReport { - TotalCommission float64 `json:"total_commission"` - TotalReport int `json:"total_report"` - Today TimeRangeReport `json:"today"` // 近24小时数据 - Last7D TimeRangeReport `json:"last7d"` // 近7天数据 - Last30D TimeRangeReport `json:"last30d"` // 近30天数据 - } - // 活跃下级奖励数据结构 - ActiveReward { - TotalReward float64 `json:"total_reward"` - Today ActiveRewardData `json:"today"` // 今日数据 - Last7D ActiveRewardData `json:"last7d"` // 近7天数据 - Last30D ActiveRewardData `json:"last30d"` // 近30天数据 - } - // 通用时间范围报告结构 - TimeRangeReport { - Commission float64 `json:"commission"` // 佣金 - Report int `json:"report"` // 报告量 - } - // 活跃奖励专用结构 - ActiveRewardData { - NewActiveReward float64 `json:"active_reward"` - SubPromoteReward float64 `json:"sub_promote_reward"` - SubUpgradeReward float64 `json:"sub_upgrade_reward"` - SubWithdrawReward float64 `json:"sub_withdraw_reward"` - } -) - -type ( - Commission { - ProductName string `json:"product_name"` - Amount float64 `json:"amount"` - CreateTime string `json:"create_time"` - } - GetCommissionReq { - Page int64 `form:"page"` // 页码 - PageSize int64 `form:"page_size"` // 每页数据量 - } - GetCommissionResp { - Total int64 `json:"total"` // 总记录数 - List []Commission `json:"list"` // 查询列表 - } - Rewards { - Type string `json:"type"` - Amount float64 `json:"amount"` - CreateTime string `json:"create_time"` - } - GetRewardsReq { - Page int64 `form:"page"` // 页码 - PageSize int64 `form:"page_size"` // 每页数据量 - } - GetRewardsResp { - Total int64 `json:"total"` // 总记录数 - List []Rewards `json:"list"` // 查询列表 - } - Withdrawal { - Status int64 `json:"status"` - Amount float64 `json:"amount"` - WithdrawalNo string `json:"withdrawal_no"` - Remark string `json:"remark"` - payeeAccount string `json:"payee_account"` - CreateTime string `json:"create_time"` - } - GetWithdrawalReq { - Page int64 `form:"page"` // 页码 - PageSize int64 `form:"page_size"` // 每页数据量 - } - GetWithdrawalResp { - Total int64 `json:"total"` // 总记录数 - List []Withdrawal `json:"list"` // 查询列表 - } -) - -type ( - WithdrawalReq { - Amount float64 `json:"amount"` // 提现金额 - payeeAccount string `json:"payee_account"` - payeeName string `json:"payee_name"` - } - WithdrawalResp { - Status int64 `json:"status"` // 1申请中 2成功 3失败 - failMsg string `json:"fail_msg"` - } -) - diff --git a/temp/app/app.api b/temp/app/app.api deleted file mode 100644 index 6f091d2..0000000 --- a/temp/app/app.api +++ /dev/null @@ -1,17 +0,0 @@ -syntax = "v1" - -info ( - title: "APP服务" - desc: "APP服务" - author: "Liangzai" - email: "2440983361@qq.com" - version: "v1" -) - -type ( - getAppVersionResp { - version string `json:"version"` - wgtUrl string `json:"wgtUrl"` - } -) - diff --git a/temp/auth/auth.api b/temp/auth/auth.api deleted file mode 100644 index e35c414..0000000 --- a/temp/auth/auth.api +++ /dev/null @@ -1,16 +0,0 @@ -syntax = "v1" - -info ( - title: "认证服务" - desc: "认证服务" - author: "Liangzai" - email: "2440983361@qq.com" -) - -type ( - sendSmsReq { - Mobile string `json:"mobile" validate:"required,mobile"` - ActionType string `json:"actionType" validate:"required,oneof=login register query agentApply"` - } -) - diff --git a/temp/pay/pay.api b/temp/pay/pay.api deleted file mode 100644 index 2d80db1..0000000 --- a/temp/pay/pay.api +++ /dev/null @@ -1,28 +0,0 @@ -syntax = "v1" - -info ( - title: "产品支付服务" - desc: "产品支付服务" - author: "Liangzai" - email: "2440983361@qq.com" -) - -type ( - PaymentReq { - Id string `json:"id"` - PayMethod string `json:"pay_method"` - } - PaymentResp { - prepayData interface{} `json:"prepay_data"` - prepayId string `json:"prepay_id"` - OrderID int64 `json:"order_id"` - } -) - -type ( - IapCallbackReq { - OrderID int64 `json:"order_id" validate:"required"` - TransactionReceipt string `json:"transaction_receipt" validate:"required"` - } -) - diff --git a/temp/product/product.api b/temp/product/product.api deleted file mode 100644 index 9d69933..0000000 --- a/temp/product/product.api +++ /dev/null @@ -1,36 +0,0 @@ -syntax = "v1" - -info ( - title: "产品查询服务" - desc: "产品查询服务" - author: "Liangzai" - email: "2440983361@qq.com" -) - -type Product { - ProductName string `json:"product_name"` - ProductEn string `json:"product_en"` - Description string `json:"description"` - Notes string `json:"notes,optional"` - SellPrice float64 `json:"sell_price"` - Features []Feature `json:"features"` // 关联功能列表 -} - -type Feature { - ID int64 `json:"id"` // 功能ID - ApiID string `json:"api_id"` // API标识 - Name string `json:"name"` // 功能描述 -} - -type GetProductByIDRequest { - Id int64 `path:"id"` -} - -type GetProductByEnRequest { - ProductEn string `path:"product_en"` -} - -type ProductResponse { - Product -} - diff --git a/temp/query/query.api b/temp/query/query.api deleted file mode 100644 index 1d3d3f5..0000000 --- a/temp/query/query.api +++ /dev/null @@ -1,127 +0,0 @@ -syntax = "v1" - -info ( - title: "产品查询服务" - desc: "产品查询服务" - author: "Liangzai" - email: "2440983361@qq.com" -) - -type ( - QueryReq { - Data string `json:"data" validate:"required"` - } - QueryResp { - id string `json:"id"` - } -) - -type ( - QueryServiceReq { - Product string `path:"product"` - Data string `json:"data" validate:"required"` - AgentIdentifier string `json:"agent_identifier,optional"` - App bool `json:"app,optional"` - } - QueryServiceResp { - id string `json:"id"` - AccessToken string `json:"accessToken"` - AccessExpire int64 `json:"accessExpire"` - RefreshAfter int64 `json:"refreshAfter"` - } -) - -type Query { - Id int64 `json:"id"` // 主键ID - OrderId int64 `json:"order_id"` // 订单ID - UserId int64 `json:"user_id"` // 用户ID - ProductName string `json:"product_name"` // 产品ID - QueryParams map[string]interface{} `json:"query_params"` - QueryData []QueryItem `json:"query_data"` - CreateTime string `json:"create_time"` // 创建时间 - UpdateTime string `json:"update_time"` // 更新时间 - QueryState string `json:"query_state"` // 查询状态 -} - -type QueryItem { - Feature interface{} `json:"feature"` - Data interface{} `json:"data"` // 这里可以是 map 或 具体的 struct -} - -// 获取查询临时订单 -type ( - QueryProvisionalOrderReq { - Id string `path:"id"` - } - QueryProvisionalOrderResp { - Name string `json:"name"` - IdCard string `json:"id_card"` - Mobile string `json:"mobile"` - Product Product `json:"product"` - } -) - -type ( - QueryListReq { - Page int64 `form:"page"` // 页码 - PageSize int64 `form:"page_size"` // 每页数据量 - } - QueryListResp { - Total int64 `json:"total"` // 总记录数 - List []Query `json:"list"` // 查询列表 - } -) - -type ( - QueryExampleReq { - feature string `form:"feature"` - } - QueryExampleResp { - Query - } -) - -type ( - QueryDetailReq { - Id int64 `path:"id"` - } - QueryDetailResp { - Query - } -) - -type ( - QueryDetailByOrderIdReq { - OrderId int64 `path:"order_id"` - } - QueryDetailByOrderIdResp { - Query - } -) - -type ( - QueryDetailByOrderNoReq { - OrderNo string `path:"order_no"` - } - QueryDetailByOrderNoResp { - Query - } -) - -type ( - QueryRetryReq { - Id int64 `path:"id"` - } - QueryRetryResp {} -) - -type QuerySingleTestReq { - params map[string]interface{} `json:"params"` - Api string `json:"api"` -} - -type QuerySingleTestResp { - Data interface{} `json:"data"` - Api string `json:"api"` -} - diff --git a/temp/user/user.api b/temp/user/user.api deleted file mode 100644 index 56931e0..0000000 --- a/temp/user/user.api +++ /dev/null @@ -1,101 +0,0 @@ -syntax = "v1" - -info ( - title: "用户实例" - desc: "用户实例" - author: "Liangzai" - email: "2440983361@qq.com" -) - -type User { - Id int64 `json:"id"` - Mobile string `json:"mobile"` - NickName string `json:"nickName"` -} - -type ( - RegisterReq { - Mobile string `json:"mobile" validate:"required,mobile"` - Password string `json:"password" validate:"required,min=11,max=11,password"` - Code string `json:"code" validate:"required"` - } - RegisterResp { - AccessToken string `json:"accessToken"` - AccessExpire int64 `json:"accessExpire"` - RefreshAfter int64 `json:"refreshAfter"` - } -) - -type ( - MobileLoginReq { - Mobile string `json:"mobile" validate:"required,mobile"` - Password string `json:"password" validate:"required"` - } - MobileLoginResp { - AccessToken string `json:"accessToken"` - AccessExpire int64 `json:"accessExpire"` - RefreshAfter int64 `json:"refreshAfter"` - } -) - -type ( - MobileCodeLoginReq { - Mobile string `json:"mobile"` - Code string `json:"code" validate:"required"` - } - MobileCodeLoginResp { - AccessToken string `json:"accessToken"` - AccessExpire int64 `json:"accessExpire"` - RefreshAfter int64 `json:"refreshAfter"` - } -) - -type ( - WXMiniAuthReq { - Code string `json:"code"` - IV string `json:"iv"` - EncryptedData string `json:"encryptedData"` - } - WXMiniAuthResp { - AccessToken string `json:"accessToken"` - AccessExpire int64 `json:"accessExpire"` - RefreshAfter int64 `json:"refreshAfter"` - } -) - -type ( - WXH5AuthReq { - Code string `json:"code"` - } - WXH5AuthResp { - AccessToken string `json:"accessToken"` - AccessExpire int64 `json:"accessExpire"` - RefreshAfter int64 `json:"refreshAfter"` - } -) - -type ( - UserInfoResp { - UserInfo User `json:"userInfo"` - } -) - -//============================> notification v1 <============================ -type Notification { - Title string `json:"title"` // 通知标题 - Content string `json:"content"` // 通知内容 (富文本) - NotificationPage string `json:"notificationPage"` // 通知页面 - StartDate string `json:"startDate"` // 通知开始日期,格式 "YYYY-MM-DD" - EndDate string `json:"endDate"` // 通知结束日期,格式 "YYYY-MM-DD" - StartTime string `json:"startTime"` // 每天通知开始时间,格式 "HH:MM:SS" - EndTime string `json:"endTime"` // 每天通知结束时间,格式 "HH:MM:SS" -} - -type ( - // 获取通知响应体(分页) - GetNotificationsResp { - Notifications []Notification `json:"notifications"` // 通知列表 - Total int64 `json:"total"` // 总记录数 - } -) -