Files
junhong_cmp_fiber/internal/model/dto/business_user_group_dto.go
break 22c3e7cc1a
All checks were successful
构建并部署到测试环境(无 SSH) / build-and-deploy (push) Successful in 9m42s
实施业务用户组成员管理
2026-09-21 21:20:38 +08:00

273 lines
18 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package dto
import "github.com/bytedance/sonic"
// 业务用户组 DTO。
// 枚举说明enabled 与 business_line 取值必须与 pkg/constants 的
// StatusDisabled/StatusEnabled 与 BusinessLineStandard/BusinessLineSmart/BusinessLineOther 保持一致。
// CreateBusinessUserGroupRequest 创建业务用户组请求。
type CreateBusinessUserGroupRequest struct {
Code string `json:"code" validate:"required,min=1,max=64" required:"true" minLength:"1" maxLength:"64" description:"业务用户组稳定编码1-64 字符,未删除组内唯一,创建后不可修改"`
Name string `json:"name" validate:"required,min=1,max=100" required:"true" minLength:"1" maxLength:"100" description:"业务用户组名称1-100 字符"`
BusinessLine string `json:"business_line" validate:"omitempty,oneof=standard smart other" enum:"standard,smart,other" description:"所属业务线 (standard:标品, smart:智能产品, other:其他),留空表示不设置"`
Sort *int64 `json:"sort" validate:"omitempty,min=0" minimum:"0" description:"排序值,非负整数,默认 0"`
Enabled *bool `json:"enabled" description:"是否启用,默认启用;停用后不得新增成员,也不得作为批量目标"`
Remark string `json:"remark" validate:"omitempty,max=500" maxLength:"500" description:"备注,最多 500 字符"`
}
// UpdateBusinessUserGroupRequest 更新业务用户组请求。
// 仅传入的字段被修改;稳定编码永不允许修改,本请求不提供该字段。
// business_line 传显式空字符串表示清空业务线。
type UpdateBusinessUserGroupRequest struct {
Name *string `json:"name" validate:"omitempty,min=1,max=100" minLength:"1" maxLength:"100" description:"业务用户组名称1-100 字符"`
BusinessLine *string `json:"business_line" enum:"standard,smart,other" description:"所属业务线 (standard:标品, smart:智能产品, other:其他);字段缺失不修改,传空字符串清空;取值白名单在服务层校验"`
Sort *int64 `json:"sort" validate:"omitempty,min=0" minimum:"0" description:"排序值,非负整数"`
Enabled *bool `json:"enabled" description:"是否启用;停用后不得新增成员,已有成员关系保留并显示已停用"`
Remark *string `json:"remark" validate:"omitempty,max=500" maxLength:"500" description:"备注,最多 500 字符"`
}
// BusinessUserGroupListRequest 查询业务用户组列表请求。
type BusinessUserGroupListRequest struct {
Page int `json:"page" query:"page" validate:"omitempty,min=1" minimum:"1" description:"页码,默认 1"`
PageSize int `json:"page_size" query:"page_size" validate:"omitempty,min=1,max=100" minimum:"1" maximum:"100" description:"每页数量,默认 20最大 100"`
Enabled *bool `json:"enabled" query:"enabled" description:"按启用状态过滤;不传返回全部"`
Keyword string `json:"keyword" query:"keyword" validate:"omitempty,max=100" maxLength:"100" description:"按稳定编码或名称模糊搜索,最多 100 字符"`
BusinessLine *string `json:"business_line" query:"business_line" validate:"omitempty,oneof=standard smart other" enum:"standard,smart,other" description:"按所属业务线过滤 (standard:标品, smart:智能产品, other:其他)"`
}
// BusinessUserGroupResponse 业务用户组响应。
type BusinessUserGroupResponse struct {
ID uint `json:"id" description:"业务用户组ID"`
Code string `json:"code" description:"业务用户组稳定编码,创建后不可修改"`
Name string `json:"name" description:"业务用户组名称"`
BusinessLine string `json:"business_line" description:"所属业务线 (standard:标品, smart:智能产品, other:其他),空字符串表示未设置"`
BusinessLineName string `json:"business_line_name" description:"所属业务线中文名称,未设置时为空字符串"`
Sort int64 `json:"sort" description:"排序值"`
Enabled bool `json:"enabled" description:"是否启用;停用后不得新增成员,也不得作为批量目标"`
Remark string `json:"remark" description:"备注"`
MemberCount int64 `json:"member_count" description:"当前保留成员关系数量,包含禁用或已删除账号"`
CreatedAt string `json:"created_at" description:"创建时间"`
UpdatedAt string `json:"updated_at" description:"更新时间"`
}
// BusinessUserGroupPageResult 业务用户组分页响应。
type BusinessUserGroupPageResult struct {
Items []*BusinessUserGroupResponse `json:"items" description:"业务用户组列表"`
Total int64 `json:"total" description:"总记录数"`
Page int `json:"page" description:"当前页码"`
Size int `json:"size" description:"每页数量"`
}
// BusinessUserGroupMemberListRequest 业务用户组成员分页查询请求。
type BusinessUserGroupMemberListRequest struct {
Page int `json:"page" query:"page" validate:"omitempty,min=1" minimum:"1" description:"页码,默认 1"`
PageSize int `json:"page_size" query:"page_size" validate:"omitempty,min=1,max=100" minimum:"1" maximum:"100" description:"每页数量,默认 20最大 100"`
Keyword string `json:"keyword" query:"keyword" validate:"omitempty,max=100" maxLength:"100" description:"按用户名或手机号模糊搜索,最多 100 字符"`
AccountStatus string `json:"account_status" query:"account_status" validate:"omitempty,oneof=enabled disabled deleted" enum:"enabled,disabled,deleted" description:"账号状态筛选 (enabled:启用, disabled:禁用, deleted:已删除)"`
}
// BusinessUserGroupMemberListParams 业务用户组成员分页查询路径与查询参数。
type BusinessUserGroupMemberListParams struct {
BusinessUserGroupMemberRequest
BusinessUserGroupMemberListRequest
}
// BusinessUserGroupMemberResponse 业务用户组成员响应。
type BusinessUserGroupMemberResponse struct {
AccountID uint `json:"account_id" description:"平台用户账号ID"`
Username string `json:"username" description:"平台用户用户名"`
Phone string `json:"phone" description:"脱敏手机号仅保留前3位和后4位"`
Enabled bool `json:"enabled" description:"账号是否启用"`
StatusName string `json:"status_name" description:"账号启停状态名称"`
Deleted bool `json:"deleted" description:"账号是否已软删除"`
MemberCreatedAt string `json:"member_created_at" description:"成员关系创建时间"`
CurrentGroupID uint `json:"current_group_id" description:"当前业务用户组ID"`
CurrentGroupCode string `json:"current_group_code" description:"当前业务用户组稳定编码"`
CurrentGroupName string `json:"current_group_name" description:"当前业务用户组名称"`
CurrentGroupEnabled bool `json:"current_group_enabled" description:"当前业务用户组是否启用"`
}
// BusinessUserGroupMemberPageResult 业务用户组成员分页响应。
type BusinessUserGroupMemberPageResult struct {
Items []*BusinessUserGroupMemberResponse `json:"items" description:"成员列表"`
Total int64 `json:"total" description:"总记录数"`
Page int `json:"page" description:"当前页码"`
Size int `json:"size" description:"每页数量"`
}
// BusinessUserGroupMemberCandidateRequest 业务用户组成员候选分页查询请求。
type BusinessUserGroupMemberCandidateRequest struct {
Page int `json:"page" query:"page" validate:"omitempty,min=1" minimum:"1" description:"页码,默认 1"`
PageSize int `json:"page_size" query:"page_size" validate:"omitempty,min=1,max=100" minimum:"1" maximum:"100" description:"每页数量,默认 20最大 100"`
Keyword string `json:"keyword" query:"keyword" validate:"omitempty,max=100" maxLength:"100" description:"按用户名或脱敏手机号模糊搜索,最多 100 字符"`
GroupFilter string `json:"group_filter" query:"group_filter" validate:"omitempty,oneof=all ungrouped current other" enum:"all,ungrouped,current,other" description:"归属筛选 (all:全部, ungrouped:未分组, current:当前组, other:其他组)"`
}
// BusinessUserGroupMemberCandidateParams 业务用户组成员候选路径与查询参数。
type BusinessUserGroupMemberCandidateParams struct {
BusinessUserGroupMemberRequest
BusinessUserGroupMemberCandidateRequest
}
// BusinessUserGroupMemberCandidateResponse 业务用户组成员候选响应。
type BusinessUserGroupMemberCandidateResponse struct {
AccountID uint `json:"account_id" description:"平台用户账号ID"`
Username string `json:"username" description:"平台用户用户名"`
Phone string `json:"phone" description:"脱敏手机号仅保留前3位和后4位"`
CurrentGroupID *uint `json:"current_group_id" description:"当前业务用户组ID未分组时为空"`
CurrentGroupCode string `json:"current_group_code" description:"当前业务用户组稳定编码"`
CurrentGroupName string `json:"current_group_name" description:"当前业务用户组名称"`
CurrentGroupEnabled bool `json:"current_group_enabled" description:"当前业务用户组是否启用"`
Action string `json:"action" enum:"add,already_member,move" description:"稳定操作提示 (add:新增, already_member:已在目标组, move:迁入)"`
CanAdd bool `json:"can_add" description:"当前目标组是否允许新增成员"`
}
// BusinessUserGroupMemberCandidatePageResult 业务用户组成员候选分页响应。
type BusinessUserGroupMemberCandidatePageResult struct {
Items []*BusinessUserGroupMemberCandidateResponse `json:"items" description:"成员候选列表"`
Total int64 `json:"total" description:"总记录数"`
Page int `json:"page" description:"当前页码"`
Size int `json:"size" description:"每页数量"`
}
// AddBusinessUserGroupMembersRequest 增量增加业务用户组成员请求。
// account_ids 去重后必须非空,且全部是启用且未删除的平台用户账号。
type AddBusinessUserGroupMembersRequest struct {
AccountIDs []uint `json:"account_ids" validate:"required,min=1,dive,min=1" required:"true" description:"平台用户账号ID列表去重后至少一个全部必须是启用且未删除的平台用户"`
}
// RemoveBusinessUserGroupMembersRequest 组作用域增量移除成员请求。
type RemoveBusinessUserGroupMembersRequest struct {
AccountIDs []uint `json:"account_ids" validate:"required,min=1,dive,min=1" required:"true" description:"当前业务用户组成员账号ID列表去重后至少一个任一不属于目标组时整批拒绝"`
}
// BusinessUserGroupMemberRequest 业务用户组成员维护路径参数。
type BusinessUserGroupMemberRequest struct {
ID uint `json:"-" path:"id" validate:"required,min=1" required:"true" description:"业务用户组ID"`
}
// BusinessUserGroupDeleteRequest 业务用户组删除二次确认请求。
type BusinessUserGroupDeleteRequest struct {
Confirm bool `json:"confirm" validate:"required" required:"true" description:"确认删除,必须为 true仅无成员的用户组可删除有成员时只能停用或先移走成员"`
}
// BusinessUserGroupUpdateParams 更新业务用户组参数(路径参数 + 请求体,用于文档生成)。
type BusinessUserGroupUpdateParams struct {
IDReq
UpdateBusinessUserGroupRequest
}
// BusinessUserGroupDeleteParams 删除业务用户组参数(路径参数 + 二次确认,用于文档生成)。
type BusinessUserGroupDeleteParams struct {
IDReq
BusinessUserGroupDeleteRequest
}
// BusinessUserGroupMemberMutationResult 成员增量维护结果。
type BusinessUserGroupMemberMutationResult struct {
GroupID uint `json:"group_id" description:"目标业务用户组ID"`
AccountIDs []uint `json:"account_ids" description:"本次请求去重后的账号ID列表"`
RequestedCount int `json:"requested_count" description:"本次请求账号数"`
AddedCount int `json:"added_count" description:"实际新增成员数"`
AddedAccountIDs []uint `json:"added_account_ids" description:"实际新增成员账号ID集合"`
MovedCount int `json:"moved_count" description:"从其他组迁入的成员数"`
MovedAccountIDs []uint `json:"moved_account_ids" description:"从其他组迁入的成员账号ID集合"`
UnchangedCount int `json:"unchanged_count" description:"已在目标组而未变化的成员数"`
UnchangedAccountIDs []uint `json:"unchanged_account_ids" description:"已在目标组而未变化的成员账号ID集合"`
RemovedCount int `json:"removed_count" description:"实际移除成员数"`
RemovedAccountIDs []uint `json:"removed_account_ids" description:"实际移除成员账号ID集合"`
}
// business_owner_account_id 缺失时请求非法;显式 null 表示清空负责人。
type BatchUpdateShopBusinessOwnerRequest struct {
ShopIDs []uint `json:"shop_ids" validate:"required,min=1,max=500,dive,min=1" required:"true" minItems:"1" maxItems:"500" description:"店铺ID列表至少一个且去重最多 500 个"`
BusinessOwnerAccountID *uint `json:"business_owner_account_id" nullable:"true" description:"目标平台业务员账号ID显式 null 表示清空负责人"`
BusinessOwnerAccountIDSet bool `json:"-"`
}
// UnmarshalJSON 解析批量交接请求并保留负责人字段「缺失」和「显式 null」的差异。
func (r *BatchUpdateShopBusinessOwnerRequest) UnmarshalJSON(data []byte) error {
type plain BatchUpdateShopBusinessOwnerRequest
var decoded plain
if err := sonic.Unmarshal(data, &decoded); err != nil {
return err
}
var fields map[string]any
if err := sonic.Unmarshal(data, &fields); err != nil {
return err
}
decoded.BusinessOwnerAccountIDSet = false
if _, exists := fields["business_owner_account_id"]; exists {
decoded.BusinessOwnerAccountIDSet = true
}
*r = BatchUpdateShopBusinessOwnerRequest(decoded)
return nil
}
// BatchUpdateShopBusinessOwnerResult 勾选店铺批量交接结果。
type BatchUpdateShopBusinessOwnerResult struct {
BatchKey string `json:"batch_key" description:"批次标识,可用于审计关联时间线"`
ShopCount int `json:"shop_count" description:"本次成功变更的店铺数量"`
Cleared bool `json:"cleared" description:"本次是否为清空负责人操作"`
BusinessOwnerAccountID *uint `json:"business_owner_account_id" description:"目标平台业务员账号ID清空时为 null"`
}
// CreateShopBusinessOwnerImportRequest 创建店铺负责人 CSV 导入任务请求。
type CreateShopBusinessOwnerImportRequest struct {
FileKey string `json:"file_key" validate:"required,min=1,max=500" required:"true" minLength:"1" maxLength:"500" description:"CSV 对象存储 Key必须以 shop-imports/ 开头且扩展名为 .csv通过 POST /api/admin/storage/upload-url 获取)"`
}
// ListShopBusinessOwnerImportRequest 查询店铺负责人导入任务列表请求。
type ListShopBusinessOwnerImportRequest struct {
Page int `json:"page" query:"page" validate:"omitempty,min=1" minimum:"1" description:"页码,默认 1"`
PageSize int `json:"page_size" query:"page_size" validate:"omitempty,min=1,max=100" minimum:"1" maximum:"100" description:"每页数量,默认 20最大 100"`
Status *int `json:"status" query:"status" validate:"omitempty,min=1,max=4" minimum:"1" maximum:"4" description:"任务状态 (1:待处理, 2:处理中, 3:已完成, 4:失败)"`
}
// GetShopBusinessOwnerImportRequest 店铺负责人导入任务详情路径参数。
type GetShopBusinessOwnerImportRequest struct {
ID uint `path:"id" required:"true" description:"导入任务ID"`
}
// ShopBusinessOwnerImportTaskResponse 店铺负责人导入任务响应。
type ShopBusinessOwnerImportTaskResponse struct {
ID uint `json:"id" description:"导入任务ID"`
TaskNo string `json:"task_no" description:"导入任务编号"`
FileName string `json:"file_name" description:"上传的源 CSV 文件名"`
Status int `json:"status" description:"任务状态 (1:待处理, 2:处理中, 3:已完成, 4:失败)"`
StatusName string `json:"status_name" description:"任务状态中文名称"`
TotalCount int `json:"total_count" description:"数据行总数;任务级失败时为 0"`
SuccessCount int `json:"success_count" description:"成功行数"`
FailCount int `json:"fail_count" description:"失败行数"`
ErrorMessage string `json:"error_message" description:"任务级失败原因;与行级失败原因分开记录"`
CreatorName string `json:"creator_name" description:"任务创建人名称快照"`
CreatedAt string `json:"created_at" description:"创建时间"`
StartedAt string `json:"started_at" description:"开始处理时间"`
CompletedAt string `json:"completed_at" description:"完成时间"`
}
// ShopBusinessOwnerImportTaskPageResult 店铺负责人导入任务分页响应。
type ShopBusinessOwnerImportTaskPageResult struct {
Items []*ShopBusinessOwnerImportTaskResponse `json:"items" description:"导入任务列表"`
Total int64 `json:"total" description:"总记录数"`
Page int `json:"page" description:"当前页码"`
Size int `json:"size" description:"每页数量"`
}
// ShopBusinessOwnerImportItemResponse 店铺负责人导入逐行结果。
type ShopBusinessOwnerImportItemResponse struct {
Line int `json:"line" description:"行号,自数据首行起计(表头不计入)"`
ShopCode string `json:"shop_code" description:"店铺编码"`
OperationType string `json:"operation_type" description:"操作类型 (换绑/清空)"`
Status int `json:"status" description:"行状态 (3:成功, 4:失败)"`
StatusName string `json:"status_name" description:"行状态中文名称"`
Reason string `json:"reason" description:"失败原因;成功行为空"`
}
// ShopBusinessOwnerImportTaskDetailResponse 店铺负责人导入任务详情响应。
type ShopBusinessOwnerImportTaskDetailResponse struct {
ShopBusinessOwnerImportTaskResponse
Items []ShopBusinessOwnerImportItemResponse `json:"items" description:"逐行结果明细;任务级失败时为空数组"`
}