补全一些接口
All checks were successful
构建并部署到测试环境(无 SSH) / build-and-deploy (push) Successful in 8m9s

This commit is contained in:
2026-07-27 17:17:43 +08:00
parent 072ec1db7e
commit d46ccbd319
8 changed files with 221 additions and 43 deletions

View File

@@ -90,6 +90,22 @@ func (s *SceneService) InspectTemplate(ctx context.Context, applicationID uint,
}, nil
}
// ListBusinessFields 返回指定审批场景允许映射的业务快照字段。
func (s *SceneService) ListBusinessFields(ctx context.Context, businessType string) (*dto.WeComBusinessFieldListResponse, error) {
userType := middleware.GetUserTypeFromContext(ctx)
if userType != constants.UserTypeSuperAdmin && userType != constants.UserTypePlatform {
return nil, errors.New(errors.CodeForbidden)
}
businessType = strings.TrimSpace(businessType)
items, ok := sceneBusinessFields(businessType)
if !ok {
return nil, errors.New(errors.CodeInvalidParam, "不支持的审批业务类型")
}
return &dto.WeComBusinessFieldListResponse{
BusinessType: businessType, BusinessTypeName: approvalBusinessTypeName(businessType), Items: items,
}, nil
}
// Save 校验模板控件后创建或替换指定稳定业务场景映射。
func (s *SceneService) Save(ctx context.Context, businessType string, request dto.SaveWeComApprovalSceneRequest) (*dto.WeComApprovalSceneResponse, error) {
if s == nil || s.db == nil || s.provider == nil || s.repo == nil {
@@ -269,40 +285,50 @@ func validateSceneMapping(businessType string, mapping []dto.WeComControlMapping
}
func allowedSceneBusinessField(businessType, businessField string) bool {
allowed := map[string]struct{}{}
switch businessType {
case constants.ApprovalBusinessTypeOfflineRecharge:
allowed = map[string]struct{}{
constants.ApprovalFieldRechargeNo: {},
constants.ApprovalFieldShopID: {},
constants.ApprovalFieldShopName: {},
constants.ApprovalFieldAmount: {},
constants.ApprovalFieldAmountCent: {},
constants.ApprovalFieldPaymentVoucherKey: {},
constants.ApprovalFieldRemark: {},
constants.ApprovalFieldSubmitterID: {},
constants.ApprovalFieldSubmitterName: {},
}
case constants.ApprovalBusinessTypeRefund:
allowed = map[string]struct{}{
constants.ApprovalFieldRefundNo: {},
constants.ApprovalFieldOrderID: {},
constants.ApprovalFieldOrderNo: {},
constants.ApprovalFieldAssetIdentifier: {},
constants.ApprovalFieldAssetType: {},
constants.ApprovalFieldActualReceivedAmount: {},
constants.ApprovalFieldRequestedRefundAmount: {},
constants.ApprovalFieldRefundVoucherKey: {},
constants.ApprovalFieldRefundReason: {},
constants.ApprovalFieldPackageUsageID: {},
constants.ApprovalFieldSubmitterID: {},
constants.ApprovalFieldSubmitterName: {},
}
default:
fields, ok := sceneBusinessFields(businessType)
if !ok {
return false
}
_, exists := allowed[businessField]
return exists
for _, field := range fields {
if field.Code == businessField {
return true
}
}
return false
}
func sceneBusinessFields(businessType string) ([]dto.WeComBusinessFieldResponse, bool) {
switch businessType {
case constants.ApprovalBusinessTypeOfflineRecharge:
return []dto.WeComBusinessFieldResponse{
{Code: constants.ApprovalFieldRechargeNo, Name: "充值单号", ValueType: constants.ApprovalFieldValueTypeString, Description: "员工线下代充值单号"},
{Code: constants.ApprovalFieldShopID, Name: "目标店铺 ID", ValueType: constants.ApprovalFieldValueTypeInteger, Description: "本次充值目标店铺的系统 ID"},
{Code: constants.ApprovalFieldShopName, Name: "目标店铺名称", ValueType: constants.ApprovalFieldValueTypeString, Description: "本次充值目标店铺名称快照"},
{Code: constants.ApprovalFieldAmount, Name: "充值金额", ValueType: constants.ApprovalFieldValueTypeMoney, Description: "以元为单位且保留两位小数的充值金额"},
{Code: constants.ApprovalFieldAmountCent, Name: "充值金额(分)", ValueType: constants.ApprovalFieldValueTypeInteger, Description: "以分为单位的充值金额整数"},
{Code: constants.ApprovalFieldPaymentVoucherKey, Name: "付款凭证", ValueType: constants.ApprovalFieldValueTypeFileList, Description: "提交时上传到企微文件控件的付款凭证列表"},
{Code: constants.ApprovalFieldRemark, Name: "备注", ValueType: constants.ApprovalFieldValueTypeString, Description: "员工提交线下代充值时填写的备注"},
{Code: constants.ApprovalFieldSubmitterID, Name: "提交人账号 ID", ValueType: constants.ApprovalFieldValueTypeInteger, Description: "本系统真实业务提交人账号 ID"},
{Code: constants.ApprovalFieldSubmitterName, Name: "提交人名称", ValueType: constants.ApprovalFieldValueTypeString, Description: "本系统真实业务提交人名称快照"},
}, true
case constants.ApprovalBusinessTypeRefund:
return []dto.WeComBusinessFieldResponse{
{Code: constants.ApprovalFieldRefundNo, Name: "退款单号", ValueType: constants.ApprovalFieldValueTypeString, Description: "本次退款申请单号"},
{Code: constants.ApprovalFieldOrderID, Name: "订单 ID", ValueType: constants.ApprovalFieldValueTypeInteger, Description: "退款关联订单的系统 ID"},
{Code: constants.ApprovalFieldOrderNo, Name: "订单号", ValueType: constants.ApprovalFieldValueTypeString, Description: "退款关联订单号"},
{Code: constants.ApprovalFieldAssetIdentifier, Name: "资产标识", ValueType: constants.ApprovalFieldValueTypeString, Description: "退款关联卡或设备的业务标识"},
{Code: constants.ApprovalFieldAssetType, Name: "资产类型", ValueType: constants.ApprovalFieldValueTypeString, Description: "退款关联资产类型编码"},
{Code: constants.ApprovalFieldActualReceivedAmount, Name: "订单实收金额", ValueType: constants.ApprovalFieldValueTypeMoney, Description: "以元为单位且保留两位小数的订单实收金额"},
{Code: constants.ApprovalFieldRequestedRefundAmount, Name: "申请退款金额", ValueType: constants.ApprovalFieldValueTypeMoney, Description: "以元为单位且保留两位小数的本次申请退款金额"},
{Code: constants.ApprovalFieldRefundVoucherKey, Name: "退款凭证", ValueType: constants.ApprovalFieldValueTypeFileList, Description: "提交时上传到企微文件控件的退款凭证列表"},
{Code: constants.ApprovalFieldRefundReason, Name: "退款原因", ValueType: constants.ApprovalFieldValueTypeString, Description: "业务提交人填写的退款原因"},
{Code: constants.ApprovalFieldPackageUsageID, Name: "套餐使用记录 ID", ValueType: constants.ApprovalFieldValueTypeInteger, Description: "退款关联套餐使用记录 ID无关联记录时可能为空"},
{Code: constants.ApprovalFieldSubmitterID, Name: "提交人账号 ID", ValueType: constants.ApprovalFieldValueTypeInteger, Description: "本系统真实业务提交人账号 ID"},
{Code: constants.ApprovalFieldSubmitterName, Name: "提交人名称", ValueType: constants.ApprovalFieldValueTypeString, Description: "本系统真实业务提交人名称快照"},
}, true
default:
return nil, false
}
}
func normalizeSceneMapping(mapping []dto.WeComControlMappingItem) []dto.WeComControlMappingItem {
@@ -323,6 +349,13 @@ func validApprovalBusinessType(businessType string) bool {
return businessType == constants.ApprovalBusinessTypeRefund || businessType == constants.ApprovalBusinessTypeOfflineRecharge
}
func approvalBusinessTypeName(businessType string) string {
if businessType == constants.ApprovalBusinessTypeRefund {
return "退款审批"
}
return "员工线下代充值审批"
}
func sceneAuditSnapshot(scene *model.WeComApprovalScene) map[string]any {
return map[string]any{
"business_type": scene.BusinessType, "application_id": scene.ApplicationID,
@@ -336,12 +369,8 @@ func sceneResponse(scene model.WeComApprovalScene) (*dto.WeComApprovalSceneRespo
if err := sonic.Unmarshal(scene.ControlMapping, &mapping); err != nil {
return nil, errors.Wrap(errors.CodeInternalError, err, "解析企业微信控件映射失败")
}
name := "员工线下代充值审批"
if scene.BusinessType == constants.ApprovalBusinessTypeRefund {
name = "退款审批"
}
return &dto.WeComApprovalSceneResponse{
ID: scene.ID, BusinessType: scene.BusinessType, BusinessTypeName: name,
ID: scene.ID, BusinessType: scene.BusinessType, BusinessTypeName: approvalBusinessTypeName(scene.BusinessType),
ApplicationID: scene.ApplicationID, TemplateID: scene.TemplateID, TemplateName: scene.TemplateName,
TemplateFingerprint: scene.TemplateFingerprint,
ControlMapping: mapping, Status: scene.Status, StatusName: constants.GetStatusName(scene.Status),

View File

@@ -180,6 +180,19 @@ func (h *WeComHandler) InspectTemplate(c *fiber.Ctx) error {
return response.Success(c, result)
}
// ListSceneFields 查询审批场景允许映射的业务字段。
// GET /api/admin/wecom/scenes/:business_type/fields
func (h *WeComHandler) ListSceneFields(c *fiber.Ctx) error {
if h == nil || h.scenes == nil {
return errors.New(errors.CodeServiceUnavailable, "企业微信审批场景服务未配置")
}
result, err := h.scenes.ListBusinessFields(c.UserContext(), c.Params("business_type"))
if err != nil {
return err
}
return response.Success(c, result)
}
// SaveScene 保存并校验稳定业务类型的企微模板控件映射。
// PUT /api/admin/wecom/scenes/:business_type
func (h *WeComHandler) SaveScene(c *fiber.Ctx) error {

View File

@@ -4,7 +4,7 @@ import "time"
// WeComControlMappingItem 描述一个业务字段到企微模板控件的显式映射。
type WeComControlMappingItem struct {
BusinessField string `json:"business_field" validate:"required,min=1,max=64" description:"稳定业务字段编码"`
BusinessField string `json:"business_field" validate:"required,min=1,max=64" description:"系统业务字段编码;按 business_type 调用 GET /api/admin/wecom/scenes/{business_type}/fields 获取可选值"`
ControlID string `json:"control_id" validate:"required,min=1,max=128" description:"企微模板控件 ID"`
ControlType string `json:"control_type" validate:"required,min=1,max=64" description:"企微模板控件类型,必须与模板详情一致"`
OptionMapping map[string]string `json:"option_mapping" description:"业务枚举值到企微选择项 key 的映射;非选择控件传空对象"`
@@ -21,6 +21,26 @@ type InspectWeComTemplateParams struct {
InspectWeComTemplateRequest
}
// WeComBusinessFieldListParams 查询企业微信审批场景可映射字段路径参数。
type WeComBusinessFieldListParams struct {
BusinessType string `path:"business_type" required:"true" description:"业务类型 (refund_approval:退款审批, offline_recharge_approval:员工线下代充值审批)"`
}
// WeComBusinessFieldResponse 企业微信审批场景可映射业务字段响应。
type WeComBusinessFieldResponse struct {
Code string `json:"code" description:"control_mapping.business_field 应填写的稳定字段编码"`
Name string `json:"name" description:"字段中文名称"`
ValueType string `json:"value_type" description:"字段值类型 (string:字符串, integer:整数, money:两位小数的元金额字符串, file_list:对象存储文件引用列表)"`
Description string `json:"description" description:"字段取值说明"`
}
// WeComBusinessFieldListResponse 企业微信审批场景可映射业务字段列表响应。
type WeComBusinessFieldListResponse struct {
BusinessType string `json:"business_type" description:"业务类型"`
BusinessTypeName string `json:"business_type_name" description:"业务类型名称(中文)"`
Items []WeComBusinessFieldResponse `json:"items" description:"当前业务类型允许写入 control_mapping.business_field 的字段"`
}
// WeComTemplateControlResponse 企业微信审批模板控件响应。
type WeComTemplateControlResponse struct {
ID string `json:"id" description:"企微模板控件 ID"`
@@ -47,7 +67,7 @@ type SaveWeComApprovalSceneRequest struct {
// SaveWeComApprovalSceneParams 保存企业微信审批场景路径与请求参数。
type SaveWeComApprovalSceneParams struct {
BusinessType string `path:"business_type" required:"true" description:"业务类型 (refund_approval:退款审批, offline_recharge_approval:员工线下代充值审批)"`
BusinessType string `path:"business_type" required:"true" description:"业务类型 (refund_approval:退款审批, offline_recharge_approval:员工线下代充值审批);可先调用 GET /api/admin/wecom/scenes/{business_type}/fields 查询允许映射的业务字段"`
SaveWeComApprovalSceneRequest
}

View File

@@ -70,6 +70,13 @@ func registerWeComRoutes(router fiber.Router, handler *admin.WeComHandler, doc *
Output: new(dto.WeComTemplateDetailResponse),
Auth: true,
})
Register(group, doc, groupPath, "GET", "/scenes/:business_type/fields", handler.ListSceneFields, RouteSpec{
Summary: "查询企业微信审批场景可映射字段",
Tags: []string{"企业微信审批"},
Input: new(dto.WeComBusinessFieldListParams),
Output: new(dto.WeComBusinessFieldListResponse),
Auth: true,
})
Register(group, doc, groupPath, "PUT", "/scenes/:business_type", handler.SaveScene, RouteSpec{
Summary: "保存并校验企业微信审批场景模板映射",
Tags: []string{"企业微信审批"},