Merge branch 'main' of http://1.117.67.95:3000/team/ycc-proxy-server
This commit is contained in:
@@ -28,6 +28,10 @@ service main {
|
||||
@handler AdminGetQueryCleanupConfigList
|
||||
get /cleanup/configs (AdminGetQueryCleanupConfigListReq) returns (AdminGetQueryCleanupConfigListResp)
|
||||
|
||||
@doc "按 QueryId+FeatureApiId 补删单条查询的某个模块数据(仅内部运维使用)"
|
||||
@handler AdminDeleteQueryFeatureData
|
||||
post /cleanup/delete/feature (AdminDeleteQueryFeatureDataReq) returns (AdminDeleteQueryFeatureDataResp)
|
||||
|
||||
@doc "更新清理配置"
|
||||
@handler AdminUpdateQueryCleanupConfig
|
||||
put /cleanup/config (AdminUpdateQueryCleanupConfigReq) returns (AdminUpdateQueryCleanupConfigResp)
|
||||
@@ -131,3 +135,14 @@ type AdminGetQueryCleanupConfigListResp {
|
||||
type AdminUpdateQueryCleanupConfigResp {
|
||||
Success bool `json:"success"` // 是否成功
|
||||
}
|
||||
|
||||
// 运维补删接口:按 QueryId+FeatureApiId 删除单条查询中的指定模块数据
|
||||
type AdminDeleteQueryFeatureDataReq {
|
||||
QueryId string `json:"query_id"` // 查询ID(Query表ID)
|
||||
FeatureApiId string `json:"feature_api_id"` // 模块API标识(与前台 OfflineFeature 一致)
|
||||
}
|
||||
|
||||
type AdminDeleteQueryFeatureDataResp {
|
||||
Success bool `json:"success"` // 是否删除成功(或数据本就不存在)
|
||||
Message string `json:"message"` // 结果说明
|
||||
}
|
||||
|
||||
@@ -288,7 +288,7 @@ service main {
|
||||
@handler CheckFeatureWhitelistStatus
|
||||
get /whitelist/check (CheckFeatureWhitelistStatusReq) returns (CheckFeatureWhitelistStatusResp)
|
||||
|
||||
// 下架单个模块(创建订单并支付)
|
||||
// 下架单个模块(统一入口:创建/补充白名单并根据 QueryId 删除本次报告中的模块数据)
|
||||
@handler OfflineFeature
|
||||
post /whitelist/offline (OfflineFeatureReq) returns (OfflineFeatureResp)
|
||||
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
package admin_query
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"github.com/zeromicro/go-zero/rest/httpx"
|
||||
"ycc-server/app/main/api/internal/logic/admin_query"
|
||||
"ycc-server/app/main/api/internal/svc"
|
||||
"ycc-server/app/main/api/internal/types"
|
||||
"ycc-server/common/result"
|
||||
"ycc-server/pkg/lzkit/validator"
|
||||
)
|
||||
|
||||
func AdminDeleteQueryFeatureDataHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
var req types.AdminDeleteQueryFeatureDataReq
|
||||
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_query.NewAdminDeleteQueryFeatureDataLogic(r.Context(), svcCtx)
|
||||
resp, err := l.AdminDeleteQueryFeatureData(&req)
|
||||
result.HttpResult(r, w, resp, err)
|
||||
}
|
||||
}
|
||||
@@ -495,6 +495,12 @@ func RegisterHandlers(server *rest.Server, serverCtx *svc.ServiceContext) {
|
||||
Path: "/cleanup/configs",
|
||||
Handler: admin_query.AdminGetQueryCleanupConfigListHandler(serverCtx),
|
||||
},
|
||||
{
|
||||
// 按 QueryId+FeatureApiId 补删单条查询的某个模块数据(仅内部运维使用)
|
||||
Method: http.MethodPost,
|
||||
Path: "/cleanup/delete/feature",
|
||||
Handler: admin_query.AdminDeleteQueryFeatureDataHandler(serverCtx),
|
||||
},
|
||||
{
|
||||
// 获取清理详情列表
|
||||
Method: http.MethodGet,
|
||||
|
||||
@@ -0,0 +1,51 @@
|
||||
package admin_query
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"ycc-server/app/main/api/internal/svc"
|
||||
"ycc-server/app/main/api/internal/types"
|
||||
"ycc-server/common/xerr"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"github.com/zeromicro/go-zero/core/logx"
|
||||
"github.com/zeromicro/go-zero/core/stores/sqlx"
|
||||
)
|
||||
|
||||
type AdminDeleteQueryFeatureDataLogic struct {
|
||||
logx.Logger
|
||||
ctx context.Context
|
||||
svcCtx *svc.ServiceContext
|
||||
}
|
||||
|
||||
func NewAdminDeleteQueryFeatureDataLogic(ctx context.Context, svcCtx *svc.ServiceContext) *AdminDeleteQueryFeatureDataLogic {
|
||||
return &AdminDeleteQueryFeatureDataLogic{
|
||||
Logger: logx.WithContext(ctx),
|
||||
ctx: ctx,
|
||||
svcCtx: svcCtx,
|
||||
}
|
||||
}
|
||||
|
||||
func (l *AdminDeleteQueryFeatureDataLogic) AdminDeleteQueryFeatureData(req *types.AdminDeleteQueryFeatureDataReq) (resp *types.AdminDeleteQueryFeatureDataResp, err error) {
|
||||
// 基本参数校验
|
||||
if req.QueryId == "" {
|
||||
return nil, errors.Wrapf(xerr.NewErrMsg("QueryId 不能为空"), "")
|
||||
}
|
||||
if req.FeatureApiId == "" {
|
||||
return nil, errors.Wrapf(xerr.NewErrMsg("feature_api_id 不能为空"), "")
|
||||
}
|
||||
|
||||
// 使用事务调用 WhitelistService.DeleteFeatureFromQueryData,保持与其它删除逻辑一致
|
||||
err = l.svcCtx.QueryModel.Trans(l.ctx, func(ctx context.Context, session sqlx.Session) error {
|
||||
return l.svcCtx.WhitelistService.DeleteFeatureFromQueryData(ctx, session, req.QueryId, req.FeatureApiId)
|
||||
})
|
||||
if err != nil {
|
||||
l.Errorf("Admin 删除查询模块数据失败, queryId=%s, featureApiId=%s, err=%+v", req.QueryId, req.FeatureApiId, err)
|
||||
return nil, errors.Wrapf(xerr.NewErrMsg("删除失败,请稍后重试"), "")
|
||||
}
|
||||
|
||||
return &types.AdminDeleteQueryFeatureDataResp{
|
||||
Success: true,
|
||||
Message: "删除成功(如果原本不存在该模块数据,则视为已删除)",
|
||||
}, nil
|
||||
}
|
||||
@@ -6,6 +6,7 @@ import (
|
||||
"ycc-server/app/main/model"
|
||||
"ycc-server/common/ctxdata"
|
||||
"ycc-server/common/xerr"
|
||||
"ycc-server/pkg/lzkit/lzUtils"
|
||||
|
||||
"github.com/google/uuid"
|
||||
"github.com/pkg/errors"
|
||||
@@ -123,6 +124,7 @@ func (l *CreateWhitelistOrderLogic) CreateWhitelistOrder(req *types.CreateWhitel
|
||||
Id: uuid.NewString(),
|
||||
OrderNo: orderNo,
|
||||
UserId: userID,
|
||||
OrderId: lzUtils.StringToNullString(req.OrderId), // 关联的查询订单ID(可选,用于后续支付回调精确删除报告)
|
||||
IdCard: req.IdCard,
|
||||
TotalAmount: totalAmount,
|
||||
Status: 1, // 待支付
|
||||
|
||||
@@ -71,6 +71,8 @@ func (s *WhitelistService) EnsureFreeWhitelist(
|
||||
}
|
||||
}
|
||||
|
||||
// 约定:OrderId 字段在白名单表中用于记录“触发本次白名单的查询记录ID(QueryId)”
|
||||
// 这里的 orderId 即为 OfflineFeature 请求中传入的 QueryId
|
||||
wl := &model.UserFeatureWhitelist{
|
||||
Id: uuid.NewString(),
|
||||
IdCard: idCard,
|
||||
@@ -198,6 +200,8 @@ func (s *WhitelistService) ProcessOfflineFeature(
|
||||
}
|
||||
|
||||
// 3. 检查是否已有白名单
|
||||
// 约定:只要调用 OfflineFeature,下架成功(包含“之前已存在白名单”的情况)都应删除“当前这一次查询”的报告数据
|
||||
// 因此,对于“已存在生效白名单”的场景,这里依然返回 whitelistCreated = true,触发上层 OfflineFeatureLogic 删除本次 QueryId 的模块数据
|
||||
exists, err := s.CheckWhitelistExists(ctx, idCard, feature.Id)
|
||||
if err != nil {
|
||||
return false, 0, false, err
|
||||
@@ -297,6 +301,8 @@ func (s *WhitelistService) createWhitelistFromPaidOrder(
|
||||
paidOrderId string,
|
||||
price float64,
|
||||
) error {
|
||||
// 约定:OrderId 字段在白名单表中用于记录“触发本次白名单的查询记录ID(QueryId)”
|
||||
// 这里的 orderId 即为 OfflineFeature 请求中传入的 QueryId
|
||||
wl := &model.UserFeatureWhitelist{
|
||||
Id: uuid.NewString(),
|
||||
IdCard: idCard,
|
||||
@@ -517,7 +523,7 @@ func (s *WhitelistService) CheckQueryDataContainsFeature(
|
||||
return false, nil
|
||||
}
|
||||
|
||||
// ProcessPaidWhitelistOrder 处理已支付的白名单订单:创建白名单记录并删除报告数据
|
||||
// ProcessPaidWhitelistOrder 处理已支付的白名单订单:创建白名单记录,并在可精确定位时删除对应报告数据
|
||||
// order: 支付订单(Order表)
|
||||
// whitelistOrder: 白名单订单(WhitelistOrder表)
|
||||
func (s *WhitelistService) ProcessPaidWhitelistOrder(
|
||||
@@ -539,8 +545,31 @@ func (s *WhitelistService) ProcessPaidWhitelistOrder(
|
||||
return errors.Wrap(err, "查询白名单订单明细失败")
|
||||
}
|
||||
|
||||
// 为每个明细创建白名单记录并删除报告数据
|
||||
// 为每个明细创建白名单记录,并在能够精确定位 Query 时删除对应报告数据
|
||||
for _, item := range items {
|
||||
var queryId string
|
||||
|
||||
// 如果白名单订单绑定了查询订单ID(order_id),尝试通过 Query.order_id 精确找到对应的查询记录
|
||||
if whitelistOrder.OrderId.Valid && whitelistOrder.OrderId.String != "" {
|
||||
queryModel, qErr := s.QueryModel.FindOneByOrderId(ctx, whitelistOrder.OrderId.String)
|
||||
if qErr != nil {
|
||||
if errors.Is(qErr, model.ErrNotFound) {
|
||||
logx.Infof("白名单订单支付成功:订单 %s 绑定的查询订单 %s 未找到对应查询记录,跳过报告删除", whitelistOrder.OrderNo, whitelistOrder.OrderId.String)
|
||||
} else {
|
||||
return errors.Wrap(qErr, "根据白名单订单的查询订单ID查找查询记录失败")
|
||||
}
|
||||
} else {
|
||||
queryId = queryModel.Id
|
||||
// 精确删除该查询下当前模块的数据
|
||||
if delErr := s.DeleteFeatureFromQueryData(ctx, session, queryId, item.FeatureApiId); delErr != nil {
|
||||
// 删除报告数据失败不影响白名单记录创建,只记录错误日志
|
||||
logx.Errorf("白名单订单支付后删除报告数据失败:查询记录 %s,模块 %s,错误:%v", queryId, item.FeatureApiId, delErr)
|
||||
} else {
|
||||
logx.Infof("白名单订单支付后删除报告数据成功:查询记录 %s,模块 %s", queryId, item.FeatureApiId)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 创建白名单记录
|
||||
wl := &model.UserFeatureWhitelist{
|
||||
Id: uuid.NewString(),
|
||||
@@ -548,7 +577,9 @@ func (s *WhitelistService) ProcessPaidWhitelistOrder(
|
||||
FeatureId: item.FeatureId,
|
||||
FeatureApiId: item.FeatureApiId,
|
||||
UserId: whitelistOrder.UserId,
|
||||
OrderId: lzUtils.StringToNullString(""), // 查询订单ID,如果有的话会在后续步骤中设置
|
||||
// 约定:UserFeatureWhitelist.OrderId 记录触发本次白名单的查询记录ID(QueryId)
|
||||
// 对于支付回调场景,如果成功通过 order_id 找到 Query,则将 QueryId 回写到白名单记录中,便于后续审计
|
||||
OrderId: lzUtils.StringToNullString(queryId),
|
||||
WhitelistOrderId: lzUtils.StringToNullString(whitelistOrder.Id),
|
||||
Amount: item.Price,
|
||||
Status: 1, // 生效
|
||||
@@ -556,13 +587,10 @@ func (s *WhitelistService) ProcessPaidWhitelistOrder(
|
||||
if _, err := s.UserFeatureWhitelistModel.Insert(ctx, session, wl); err != nil {
|
||||
return errors.Wrap(err, "创建白名单记录失败")
|
||||
}
|
||||
|
||||
// 尝试删除报告数据
|
||||
// 注意:由于支付回调时可能不知道具体的查询订单ID,这里先尝试根据 id_card 查找
|
||||
// 如果找不到对应的报告,就跳过删除步骤(不影响主流程)
|
||||
// 实际的报告数据删除应该在 OfflineFeature 接口中完成(如果提供了 orderId)
|
||||
// 这里暂时不删除,因为无法确定是哪个具体的查询订单
|
||||
logx.Infof("白名单订单支付成功:订单 %s,模块 %s,已创建白名单记录。如需删除报告数据,请在 OfflineFeature 接口中提供查询订单ID", whitelistOrder.OrderNo, item.FeatureApiId)
|
||||
// 如果无法通过 order_id 找到 Query,仅创建白名单记录,不删除任何报告数据,避免误删历史记录
|
||||
if !whitelistOrder.OrderId.Valid || whitelistOrder.OrderId.String == "" || queryId == "" {
|
||||
logx.Infof("白名单订单支付成功:订单 %s,模块 %s,已创建白名单记录。由于缺少可用的查询订单ID或对应查询记录,未删除任何报告数据", whitelistOrder.OrderNo, item.FeatureApiId)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
|
||||
@@ -212,6 +212,16 @@ type AdminDeleteProductResp struct {
|
||||
Success bool `json:"success"` // 是否成功
|
||||
}
|
||||
|
||||
type AdminDeleteQueryFeatureDataReq struct {
|
||||
QueryId string `json:"query_id"` // 查询ID(Query表ID)
|
||||
FeatureApiId string `json:"feature_api_id"` // 模块API标识(与前台 OfflineFeature 一致)
|
||||
}
|
||||
|
||||
type AdminDeleteQueryFeatureDataResp struct {
|
||||
Success bool `json:"success"` // 是否删除成功(或数据本就不存在)
|
||||
Message string `json:"message"` // 结果说明
|
||||
}
|
||||
|
||||
type AdminDeleteUserReq struct {
|
||||
Id string `path:"id"` // 用户ID
|
||||
}
|
||||
@@ -2052,8 +2062,8 @@ type ProductListItem struct {
|
||||
ProductEn string `json:"product_en"` // 英文名
|
||||
Description string `json:"description"` // 描述
|
||||
Notes string `json:"notes"` // 备注
|
||||
CostPrice float64 `json:"cost_price"` // 成本价(由功能成本累加得出)
|
||||
SellPrice float64 `json:"sell_price"` // 售价
|
||||
CostPrice float64 `json:"cost_price"` // 成本价(由功能成本累加得出)
|
||||
CreateTime string `json:"create_time"` // 创建时间
|
||||
UpdateTime string `json:"update_time"` // 更新时间
|
||||
}
|
||||
|
||||
@@ -66,6 +66,7 @@ type (
|
||||
Version int64 `db:"version"` // 版本号(乐观锁)
|
||||
OrderNo string `db:"order_no"` // 订单号(唯一)
|
||||
UserId string `db:"user_id"` // 用户ID(代理的user_id)
|
||||
OrderId sql.NullString `db:"order_id"` // 关联的查询订单ID(Query 表对应的订单ID,一般为 order.id)
|
||||
IdCard string `db:"id_card"` // 身份证号(查询对象标识)
|
||||
TotalAmount float64 `db:"total_amount"` // 总金额(单位:元)
|
||||
Status int64 `db:"status"` // 订单状态:1=待支付,2=已支付,3=已取消
|
||||
@@ -89,11 +90,11 @@ func (m *defaultWhitelistOrderModel) Insert(ctx context.Context, session sqlx.Se
|
||||
yccWhitelistOrderIdKey := fmt.Sprintf("%s%v", cacheYccWhitelistOrderIdPrefix, data.Id)
|
||||
yccWhitelistOrderOrderNoKey := fmt.Sprintf("%s%v", cacheYccWhitelistOrderOrderNoPrefix, data.OrderNo)
|
||||
return m.ExecCtx(ctx, func(ctx context.Context, conn sqlx.SqlConn) (result sql.Result, err error) {
|
||||
query := fmt.Sprintf("insert into %s (%s) values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", m.table, whitelistOrderRowsExpectAutoSet)
|
||||
query := fmt.Sprintf("insert into %s (%s) values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", m.table, whitelistOrderRowsExpectAutoSet)
|
||||
if session != nil {
|
||||
return session.ExecCtx(ctx, query, data.Id, data.DeleteTime, data.DelState, data.Version, data.OrderNo, data.UserId, data.IdCard, data.TotalAmount, data.Status, data.PaymentMethod, data.PaymentPlatform, data.PlatformOrderId, data.PayTime)
|
||||
return session.ExecCtx(ctx, query, data.Id, data.DeleteTime, data.DelState, data.Version, data.OrderNo, data.UserId, data.OrderId, data.IdCard, data.TotalAmount, data.Status, data.PaymentMethod, data.PaymentPlatform, data.PlatformOrderId, data.PayTime)
|
||||
}
|
||||
return conn.ExecCtx(ctx, query, data.Id, data.DeleteTime, data.DelState, data.Version, data.OrderNo, data.UserId, data.IdCard, data.TotalAmount, data.Status, data.PaymentMethod, data.PaymentPlatform, data.PlatformOrderId, data.PayTime)
|
||||
return conn.ExecCtx(ctx, query, data.Id, data.DeleteTime, data.DelState, data.Version, data.OrderNo, data.UserId, data.OrderId, data.IdCard, data.TotalAmount, data.Status, data.PaymentMethod, data.PaymentPlatform, data.PlatformOrderId, data.PayTime)
|
||||
}, yccWhitelistOrderIdKey, yccWhitelistOrderOrderNoKey)
|
||||
}
|
||||
func (m *defaultWhitelistOrderModel) insertUUID(data *WhitelistOrder) {
|
||||
@@ -160,9 +161,9 @@ func (m *defaultWhitelistOrderModel) Update(ctx context.Context, session sqlx.Se
|
||||
return m.ExecCtx(ctx, func(ctx context.Context, conn sqlx.SqlConn) (result sql.Result, err error) {
|
||||
query := fmt.Sprintf("update %s set %s where `id` = ?", m.table, whitelistOrderRowsWithPlaceHolder)
|
||||
if session != nil {
|
||||
return session.ExecCtx(ctx, query, newData.DeleteTime, newData.DelState, newData.Version, newData.OrderNo, newData.UserId, newData.IdCard, newData.TotalAmount, newData.Status, newData.PaymentMethod, newData.PaymentPlatform, newData.PlatformOrderId, newData.PayTime, newData.Id)
|
||||
return session.ExecCtx(ctx, query, newData.DeleteTime, newData.DelState, newData.Version, newData.OrderNo, newData.UserId, newData.OrderId, newData.IdCard, newData.TotalAmount, newData.Status, newData.PaymentMethod, newData.PaymentPlatform, newData.PlatformOrderId, newData.PayTime, newData.Id)
|
||||
}
|
||||
return conn.ExecCtx(ctx, query, newData.DeleteTime, newData.DelState, newData.Version, newData.OrderNo, newData.UserId, newData.IdCard, newData.TotalAmount, newData.Status, newData.PaymentMethod, newData.PaymentPlatform, newData.PlatformOrderId, newData.PayTime, newData.Id)
|
||||
return conn.ExecCtx(ctx, query, newData.DeleteTime, newData.DelState, newData.Version, newData.OrderNo, newData.UserId, newData.OrderId, newData.IdCard, newData.TotalAmount, newData.Status, newData.PaymentMethod, newData.PaymentPlatform, newData.PlatformOrderId, newData.PayTime, newData.Id)
|
||||
}, yccWhitelistOrderIdKey, yccWhitelistOrderOrderNoKey)
|
||||
}
|
||||
|
||||
@@ -183,9 +184,9 @@ func (m *defaultWhitelistOrderModel) UpdateWithVersion(ctx context.Context, sess
|
||||
sqlResult, err = m.ExecCtx(ctx, func(ctx context.Context, conn sqlx.SqlConn) (result sql.Result, err error) {
|
||||
query := fmt.Sprintf("update %s set %s where `id` = ? and version = ? ", m.table, whitelistOrderRowsWithPlaceHolder)
|
||||
if session != nil {
|
||||
return session.ExecCtx(ctx, query, newData.DeleteTime, newData.DelState, newData.Version, newData.OrderNo, newData.UserId, newData.IdCard, newData.TotalAmount, newData.Status, newData.PaymentMethod, newData.PaymentPlatform, newData.PlatformOrderId, newData.PayTime, newData.Id, oldVersion)
|
||||
return session.ExecCtx(ctx, query, newData.DeleteTime, newData.DelState, newData.Version, newData.OrderNo, newData.UserId, newData.OrderId, newData.IdCard, newData.TotalAmount, newData.Status, newData.PaymentMethod, newData.PaymentPlatform, newData.PlatformOrderId, newData.PayTime, newData.Id, oldVersion)
|
||||
}
|
||||
return conn.ExecCtx(ctx, query, newData.DeleteTime, newData.DelState, newData.Version, newData.OrderNo, newData.UserId, newData.IdCard, newData.TotalAmount, newData.Status, newData.PaymentMethod, newData.PaymentPlatform, newData.PlatformOrderId, newData.PayTime, newData.Id, oldVersion)
|
||||
return conn.ExecCtx(ctx, query, newData.DeleteTime, newData.DelState, newData.Version, newData.OrderNo, newData.UserId, newData.OrderId, newData.IdCard, newData.TotalAmount, newData.Status, newData.PaymentMethod, newData.PaymentPlatform, newData.PlatformOrderId, newData.PayTime, newData.Id, oldVersion)
|
||||
}, yccWhitelistOrderIdKey, yccWhitelistOrderOrderNoKey)
|
||||
if err != nil {
|
||||
return err
|
||||
|
||||
@@ -58,11 +58,11 @@ $tables = @(
|
||||
# "query_cleanup_log",
|
||||
# "user",
|
||||
# "user_auth"
|
||||
# "whitelist_order",
|
||||
"whitelist_order"
|
||||
# "whitelist_order_item",
|
||||
# "user_feature_whitelist"
|
||||
# "complaint_main",
|
||||
"complaint_alipay"
|
||||
# "complaint_alipay"
|
||||
# "complaint_alipay_trade",
|
||||
# "complaint_manual"
|
||||
# "tianyuanapi_call_log"
|
||||
|
||||
Reference in New Issue
Block a user