fix: wecom user list
CI / admin (push) Has been skipped
CI / bff (push) Has been skipped
CI / chore (push) Has been skipped
CI / express (push) Has been skipped
CI / product (push) Has been skipped
CI / sale (push) Has been skipped
CI / user (push) Has been skipped
CI / wecom (push) Has been skipped
CI / changes (push) Successful in 12s
CI / ad (push) Successful in 0s

This commit is contained in:
zzw
2026-08-31 15:04:38 +08:00
parent b79d49d399
commit 9111cb26e7
11 changed files with 181 additions and 57 deletions
+22 -13
View File
@@ -20,24 +20,33 @@ type WecomUser struct {
Mobile string `gorm:"column:mobile" json:"mobile"`
Avatar string `gorm:"column:avatar" json:"avatar"`
Status uint8 `gorm:"column:status" json:"status"`
AgentIds string `gorm:"column:agent_ids;type:json" json:"agent_ids"`
CreatedAt utils.CustomTime `gorm:"column:created_at" json:"created_at"`
UpdatedAt utils.CustomTime `gorm:"column:updated_at" json:"updated_at"`
}
// UserAgentItem 用户绑定的应用快照
type UserAgentItem struct {
Id int64 `json:"id"`
AgentId int64 `json:"agent_id"`
Name string `json:"name"`
}
type UserListItem struct {
Id int64 `json:"id"`
UserId int64 `json:"user_id"`
Type uint8 `json:"type"`
TypeText string `json:"type_text"`
Name string `json:"name"`
Mobile string `json:"mobile"`
OriginMobile string `json:"origin_mobile"`
Avatar string `json:"avatar"`
Status uint8 `json:"status"`
BizName string `json:"biz_name"`
WecomUserId string `json:"wecom_user_id"`
CreatedAt string `json:"created_at"`
UpdatedAt string `json:"updated_at"`
Id int64 `json:"id"`
UserId int64 `json:"user_id"`
Type uint8 `json:"type"`
TypeText string `json:"type_text"`
Name string `json:"name"`
Mobile string `json:"mobile"`
OriginMobile string `json:"origin_mobile"`
Avatar string `json:"avatar"`
Status uint8 `json:"status"`
BizName string `json:"biz_name"`
WecomUserId string `json:"wecom_user_id"`
Agents []UserAgentItem `json:"agents"`
CreatedAt string `json:"created_at"`
UpdatedAt string `json:"updated_at"`
}
type UserTypeOption struct {
@@ -80,6 +80,12 @@ func (l *CreateUserLogic) CreateUser(in *wecom.CreateUserReq) (*wecom.Response,
}
}
agentsJSON, aErr := buildAgentsJSON(req.AgentIds)
if aErr != nil {
l.Errorf("wecom create agents: %v", aErr)
return outResponse(utils.ErrorParams, aErr.Error()), nil
}
now := utils.Now()
row := dao.WecomUser{
UserId: req.UserId,
@@ -89,6 +95,7 @@ func (l *CreateUserLogic) CreateUser(in *wecom.CreateUserReq) (*wecom.Response,
Mobile: encryptMobile,
Avatar: req.Avatar,
Status: userStatus,
AgentIds: agentsJSON,
CreatedAt: now,
UpdatedAt: now,
}
+82
View File
@@ -1,8 +1,15 @@
package logic
import (
"fmt"
"strconv"
"lone-services/pkg/modelbase"
"lone-services/pkg/utils"
"lone-services/services/wecom/internal/dao"
"lone-services/services/wecom/internal/model"
jsoniter "github.com/json-iterator/go"
)
func departmentID() int {
@@ -47,3 +54,78 @@ func resolveStatus(reqStatus uint32, current uint8) uint8 {
}
return dao.StatusEnabled
}
// buildAgentsJSON 按 agents 表主键 id 查出应用,落库为 [{id,agent_id,name}]
func buildAgentsJSON(ids []int64) (string, error) {
ids = cleanAgentIds(ids)
if len(ids) == 0 {
return "", fmt.Errorf("应用不能为空")
}
idStrs := make([]string, 0, len(ids))
for _, id := range ids {
idStrs = append(idStrs, strconv.FormatInt(id, utils.NumberTen))
}
var rows []dao.WecomAgent
am := model.AgentModel{}.Init()
if err := am.Items(modelbase.Params{
In: map[string][]string{"id in ?": idStrs},
}, &rows); err != nil {
return "", err
}
byID := make(map[int64]dao.WecomAgent, len(rows))
for _, row := range rows {
byID[row.Id] = row
}
items := make([]dao.UserAgentItem, 0, len(ids))
for _, id := range ids {
row, ok := byID[id]
if !ok {
return "", fmt.Errorf("应用不存在: %d", id)
}
items = append(items, dao.UserAgentItem{
Id: row.Id,
AgentId: row.AgentId,
Name: row.Name,
})
}
buf, err := jsoniter.Marshal(items)
if err != nil {
return "", err
}
return string(buf), nil
}
func parseAgents(raw string) []dao.UserAgentItem {
if raw == utils.StringEmpty {
return []dao.UserAgentItem{}
}
var items []dao.UserAgentItem
if err := jsoniter.Unmarshal([]byte(raw), &items); err != nil {
return []dao.UserAgentItem{}
}
if items == nil {
return []dao.UserAgentItem{}
}
return items
}
func cleanAgentIds(ids []int64) []int64 {
out := make([]int64, 0, len(ids))
seen := make(map[int64]struct{}, len(ids))
for _, id := range ids {
if id < utils.NumberOne {
continue
}
if _, ok := seen[id]; ok {
continue
}
seen[id] = struct{}{}
out = append(out, id)
}
return out
}
@@ -98,6 +98,7 @@ func (l *ItemsUsersLogic) ItemsUsers(in *wecom.ItemsUserReq) (*wecom.Response, e
Status: row.Status,
BizName: bizName,
WecomUserId: row.WecomUserId,
Agents: parseAgents(row.AgentIds),
CreatedAt: row.CreatedAt.Format(),
})
}
@@ -70,7 +70,7 @@ func (l *UpdateUserLogic) UpdateUser(in *wecom.UpdateUserReq) (*wecom.Response,
}
typeVal := row.Type
if req.Type > utils.NumberZero {
typeVal = row.Type
typeVal = uint8(req.Type)
}
userStatus := resolveStatus(req.Status, row.Status)
@@ -109,16 +109,25 @@ func (l *UpdateUserLogic) UpdateUser(in *wecom.UpdateUserReq) (*wecom.Response,
}
}
if _, err := m.Edit(modelbase.Params{
Eq: map[string]string{"id": strconv.FormatInt(row.Id, utils.NumberTen)},
}, map[string]interface{}{
data := map[string]interface{}{
"name": name,
"mobile": encryptMobile,
"avatar": avatar,
"status": userStatus,
"type": typeVal,
"updated_at": utils.Now(),
}); err != nil {
}
if len(req.AgentIds) > utils.NumberZero {
agentsJSON, aErr := buildAgentsJSON(req.AgentIds)
if aErr != nil {
l.Errorf("wecom update agents: %v", aErr)
return outResponse(utils.ErrorParams, aErr.Error()), nil
}
data["agent_ids"] = agentsJSON
}
if _, err := m.Edit(modelbase.Params{
Eq: map[string]string{"id": strconv.FormatInt(row.Id, utils.NumberTen)},
}, data); err != nil {
l.Errorf("wecom update user db: %v", err)
return failResponse(utils.Fail), nil
}
-13
View File
@@ -1,13 +0,0 @@
-- 企业微信应用表(库:dms-wecom,前缀为空时表名为 agents
CREATE TABLE IF NOT EXISTS `agents` (
`id` bigint unsigned NOT NULL AUTO_INCREMENT,
`name` varchar(64) NOT NULL DEFAULT '' COMMENT '应用名称',
`agent_id` bigint NOT NULL DEFAULT 0 COMMENT '企业微信 AgentId',
`created_at` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
UNIQUE KEY `uk_agent_id` (`agent_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='企业微信应用';
INSERT INTO `agents` (`id`, `name`, `agent_id`, `created_at`) VALUES
(1, '审核通知', 100003, '2026-05-22 16:14:31'),
(2, '消息通知', 100004, '2026-05-22 16:14:33');
+29 -23
View File
@@ -3,37 +3,42 @@ package validator
import "lone-services/pkg/validate"
type CreateUserValidator struct {
UserId int64 `validate:"required,min=1"`
Type uint32 `validate:"required,oneof=1 2"`
Name string `validate:"required,max=64"`
Mobile string `validate:"required,mobile"`
Avatar string `validate:"omitempty,max=1024"`
Status uint32 `validate:"omitempty,oneof=1 2"`
UserId int64 `validate:"required,min=1"`
Type uint32 `validate:"required,oneof=1 2"`
Name string `validate:"required,max=64"`
Mobile string `validate:"required,mobile"`
Avatar string `validate:"omitempty,max=1024"`
Status uint32 `validate:"omitempty,oneof=1 2"`
AgentIds []int64 `validate:"required,min=1,dive,gt=0"`
}
func (p CreateUserValidator) GetMessage() validate.ValidatorMessages {
return validate.ValidatorMessages{
"UserId.required": "业务用户ID不能为空",
"UserId.min": "业务用户ID无效",
"Type.required": "类型不能为空",
"Type.oneof": "类型不对,1:管理员 2:销售",
"Name.required": "姓名不能为空",
"Name.max": "姓名长度不能超过64",
"Mobile.required": "手机号不能为空",
"Mobile.mobile": "手机号格式错误",
"Avatar.max": "头像长度不能超过1024",
"Status.oneof": "状态不对,1:启用 2:禁用",
"UserId.required": "业务用户ID不能为空",
"UserId.min": "业务用户ID无效",
"Type.required": "类型不能为空",
"Type.oneof": "类型不对,1:管理员 2:销售",
"Name.required": "姓名不能为空",
"Name.max": "姓名长度不能超过64",
"Mobile.required": "手机号不能为空",
"Mobile.mobile": "手机号格式错误",
"Avatar.max": "头像长度不能超过1024",
"Status.oneof": "状态不对,1:启用 2:禁用",
"AgentIds.required": "应用不能为空",
"AgentIds.min": "至少选择一个应用",
"AgentIds.gt": "应用ID无效",
}
}
type UpdateUserValidator struct {
Id int64 `validate:"omitempty,min=1"`
UserId int64 `validate:"omitempty,min=1"`
Type uint32 `validate:"omitempty,oneof=1 2"`
Name string `validate:"omitempty,max=64"`
Mobile string `validate:"omitempty,mobile"`
Avatar string `validate:"omitempty,max=1024"`
Status uint32 `validate:"omitempty,oneof=1 2"`
Id int64 `validate:"omitempty,min=1"`
UserId int64 `validate:"omitempty,min=1"`
Type uint32 `validate:"omitempty,oneof=1 2"`
Name string `validate:"omitempty,max=64"`
Mobile string `validate:"omitempty,mobile"`
Avatar string `validate:"omitempty,max=1024"`
Status uint32 `validate:"omitempty,oneof=1 2"`
AgentIds []int64 `validate:"omitempty,dive,gt=0"`
}
func (p UpdateUserValidator) GetMessage() validate.ValidatorMessages {
@@ -45,6 +50,7 @@ func (p UpdateUserValidator) GetMessage() validate.ValidatorMessages {
"Mobile.mobile": "手机号格式错误",
"Avatar.max": "头像长度不能超过1024",
"Status.oneof": "状态不对,1:启用 2:禁用",
"AgentIds.gt": "应用ID无效",
}
}