From b3a47cb555076c25c64d83dd455a472509291245 Mon Sep 17 00:00:00 2001
From: liujiandao <274878379@qq.com>
Date: 星期一, 13 十一月 2023 16:09:35 +0800
Subject: [PATCH] Merge branch 'master' of http://192.168.5.5:10010/r/aps/crm

---
 service/user.go            |   18 
 proto/user/user.pb.go      |  103 +++--
 model/plan.go              |   19 
 source/user.go             |  132 +++---
 api/v1/getAllData.go       |    2 
 api/v1/salesReturn.go      |    2 
 api/v1/salesRefund.go      |    2 
 proto/user.proto           |    3 
 model/serviceFeeManage.go  |   11 
 service/assign.go          |   84 ++--
 api/v1/invoice.go          |    7 
 api/v1/salesLeads.go       |    2 
 model/user.go              |   58 ++
 model/invoice.go           |   21 
 model/subOrder.go          |    4 
 model/salesLeads.go        |    5 
 service/dataServer.go      |   14 
 api/v1/masterOrder.go      |    2 
 service/invoice.go         |    2 
 model/followRecord.go      |    4 
 model/request/invoice.go   |    5 
 model/receipt.go           |   21 
 constvar/const.go          |    7 
 model/serviceOrder.go      |    2 
 middleware/jwt.go          |   18 
 main.go                    |    8 
 service/initdb.go          |    4 
 model/request/jwt.go       |    5 
 api/v1/serviceFollowup.go  |    2 
 source/menu.go             |  101 ++--
 api/v1/plan.go             |    5 
 api/v1/client.go           |   32 -
 model/contract.go          |    4 
 api/v1/contact.go          |    2 
 api/v1/contract.go         |    2 
 model/contact.go           |    4 
 api/v1/quotation.go        |    2 
 api/v1/receipt.go          |    7 
 model/masterOrder.go       |    4 
 middleware/user.go         |   21 
 api/v1/salesDetails.go     |    2 
 model/client.go            |   16 
 api/v1/subOrder.go         |    2 
 model/saleChance.go        |    4 
 model/quotation.go         |    4 
 api/v1/serviceOrder.go     |    2 
 api/v1/saleChance.go       |    2 
 api/v1/assign.go           |   93 ++--
 middleware/refresh_user.go |  138 +++++++
 model/request/receipt.go   |    7 
 service/lru.go             |   37 +
 api/v1/serviceContract.go  |    2 
 api/v1/followRecord.go     |    2 
 service/receipt.go         |    1 
 54 files changed, 698 insertions(+), 365 deletions(-)

diff --git a/api/v1/assign.go b/api/v1/assign.go
index c4218df..f7618e5 100644
--- a/api/v1/assign.go
+++ b/api/v1/assign.go
@@ -1,49 +1,44 @@
-package v1
-
-import (
-	"aps_crm/model/request"
-	"aps_crm/pkg/contextx"
-	"aps_crm/pkg/ecode"
-	"github.com/gin-gonic/gin"
-)
-
-type AssignApi struct{}
-
-// Assign
-//
-//	@Tags		Assign
-//	@Summary	鍒嗛厤
-//	@Produce	application/json
-//	@Param		object	body		request.Assign true	"鏌ヨ鍙傛暟"
-//	@Success	200		{object}	contextx.Response{}
-//	@Router		/api/assign/assign [post]
-func (au *AssignApi) Assign(c *gin.Context) {
-	var params request.Assign
-	ctx, ok := contextx.NewContext(c, &params)
-	if !ok {
-		return
-	}
-
-	if params.MemberId == 0 {
-		ctx.Fail(ecode.AssignWrongMemberId)
-		return
-	}
-
-	if len(params.Ids) == 0 {
-		ctx.Fail(ecode.AssignWrongId)
-		return
-	}
-
-	if params.Type == "" {
-		ctx.Fail(ecode.AssignWrongModelType)
-		return
-	}
-
-	errCode := assignService.Assign(params.MemberId, params.Ids, params.Type)
-	if errCode != ecode.OK {
-		ctx.Fail(errCode)
-		return
-	}
-
-	ctx.Ok()
-}
+package v1
+
+import (
+	"aps_crm/model/request"
+	"aps_crm/pkg/contextx"
+	"aps_crm/pkg/ecode"
+	"github.com/gin-gonic/gin"
+)
+
+type AssignApi struct{}
+
+// Assign
+//
+//	@Tags		Assign
+//	@Summary	鍒嗛厤
+//	@Produce	application/json
+//	@Param		object	body		request.Assign true	"鏌ヨ鍙傛暟"
+//	@Success	200		{object}	contextx.Response{}
+//	@Router		/api/assign/assign [post]
+func (au *AssignApi) Assign(c *gin.Context) {
+	var params request.Assign
+	ctx, ok := contextx.NewContext(c, &params)
+	if !ok {
+		return
+	}
+
+	if len(params.Ids) == 0 {
+		ctx.Fail(ecode.AssignWrongId)
+		return
+	}
+
+	if params.Type == "" {
+		ctx.Fail(ecode.AssignWrongModelType)
+		return
+	}
+
+	errCode := assignService.Assign(params.MemberId, params.Ids, params.Type)
+	if errCode != ecode.OK {
+		ctx.Fail(errCode)
+		return
+	}
+
+	ctx.Ok()
+}
diff --git a/api/v1/client.go b/api/v1/client.go
index d7dc42e..ff33fad 100644
--- a/api/v1/client.go
+++ b/api/v1/client.go
@@ -28,13 +28,6 @@
 		return
 	}
 
-	if params.MemberId == 0 {
-		userInfo := utils.GetUserInfo(c)
-		if userInfo.UserType == constvar.UserTypeSub {
-			params.MemberId = userInfo.CrmUserId
-		}
-	}
-
 	errCode, client := checkClientParams(params.Client)
 	if errCode != ecode.OK {
 		ctx.Fail(errCode)
@@ -116,12 +109,7 @@
 	client.Business.IndustryId = params.IndustryId
 	client.Business.EnterpriseNatureId = params.EnterpriseNatureId
 	client.Business.EnterpriseScaleId = params.EnterpriseScaleId
-	//閿�鍞礋璐d汉涓虹┖鏃朵负鍏捣瀹㈡埛
-	if params.MemberId == 0 {
-		client.MemberId = 1
-	} else {
-		client.MemberId = params.MemberId
-	}
+	client.MemberId = params.MemberId
 	client.CodeStandID = params.CodeStandID
 
 	//if params.Contact.Name != "" {
@@ -215,12 +203,20 @@
 		return
 	}
 
-	userInfo := utils.GetUserInfo(c)
-	if userInfo.UserType == constvar.UserTypeSub {
-		if params.SearchMap == nil {
-			params.SearchMap = make(map[string]interface{}, 0)
+	var isPublic bool
+	if params.SearchMap != nil && params.SearchMap["is_public"] != nil {
+		if v, ok := params.SearchMap["is_public"].(bool); ok {
+			isPublic = v
 		}
-		params.SearchMap["member_id"] = userInfo.CrmUserId
+	}
+	if !isPublic {
+		userInfo := utils.GetUserInfo(c)
+		if userInfo.UserType == constvar.UserTypeSub {
+			if params.SearchMap == nil {
+				params.SearchMap = make(map[string]interface{}, 0)
+			}
+			params.SearchMap["member_ids"] = userInfo.SubUserIds
+		}
 	}
 
 	clients, total, errCode := clientService.GetClientList(params.Page, params.PageSize, params.SearchMap)
diff --git a/api/v1/contact.go b/api/v1/contact.go
index 2a6b72e..97068ca 100644
--- a/api/v1/contact.go
+++ b/api/v1/contact.go
@@ -181,7 +181,7 @@
 		if params.SearchMap == nil {
 			params.SearchMap = make(map[string]interface{}, 0)
 		}
-		params.SearchMap["member_id"] = userInfo.CrmUserId
+		params.SearchMap["member_ids"] = userInfo.SubUserIds
 	}
 
 	contacts, total, errCode := contactService.GetContactList(params.Page, params.PageSize, params.SearchMap, params.ClientId)
diff --git a/api/v1/contract.go b/api/v1/contract.go
index 5a0dcdd..5cfdd31 100644
--- a/api/v1/contract.go
+++ b/api/v1/contract.go
@@ -166,7 +166,7 @@
 		if params.SearchMap == nil {
 			params.SearchMap = make(map[string]interface{}, 0)
 		}
-		params.SearchMap["member_id"] = userInfo.CrmUserId
+		params.SearchMap["member_ids"] = userInfo.SubUserIds
 	}
 
 	contracts, total, errCode := contractService.GetContractList(params.Page, params.PageSize, params.SearchMap)
diff --git a/api/v1/followRecord.go b/api/v1/followRecord.go
index 1fe90dd..666ea35 100644
--- a/api/v1/followRecord.go
+++ b/api/v1/followRecord.go
@@ -246,7 +246,7 @@
 		if params.SearchMap == nil {
 			params.SearchMap = make(map[string]interface{}, 0)
 		}
-		params.SearchMap["member_id"] = userInfo.CrmUserId
+		params.SearchMap["member_ids"] = userInfo.SubUserIds
 	}
 
 	followRecords, total, errCode := followRecordService.GetFollowRecordList(params.Page, params.PageSize, params.SearchMap)
diff --git a/api/v1/getAllData.go b/api/v1/getAllData.go
index 08c983d..6ddb884 100644
--- a/api/v1/getAllData.go
+++ b/api/v1/getAllData.go
@@ -21,7 +21,7 @@
 		return
 	}
 
-	errCode, data := allDataServer.GetAllData()
+	errCode, data := allDataServer.GetAllData(c)
 	if errCode != ecode.OK {
 		ctx.Fail(errCode)
 		return
diff --git a/api/v1/invoice.go b/api/v1/invoice.go
index 3c51eb3..89edcd4 100644
--- a/api/v1/invoice.go
+++ b/api/v1/invoice.go
@@ -1,6 +1,7 @@
 package v1
 
 import (
+	"aps_crm/constvar"
 	"aps_crm/model"
 	"aps_crm/model/request"
 	"aps_crm/model/response"
@@ -8,6 +9,7 @@
 	"aps_crm/pkg/ecode"
 	"aps_crm/pkg/structx"
 	"aps_crm/service"
+	"aps_crm/utils"
 	"github.com/gin-gonic/gin"
 	"strconv"
 )
@@ -123,6 +125,11 @@
 		return
 	}
 
+	userInfo := utils.GetUserInfo(c)
+	if userInfo.UserType == constvar.UserTypeSub {
+		params.PrincipalIds = userInfo.SubUserIds
+	}
+
 	invoice, total, errCode := service.NewInvoiceService().GetInvoiceList(params)
 	if errCode != ecode.OK {
 		ctx.Fail(errCode)
diff --git a/api/v1/masterOrder.go b/api/v1/masterOrder.go
index af2fb9d..6362d0d 100644
--- a/api/v1/masterOrder.go
+++ b/api/v1/masterOrder.go
@@ -168,7 +168,7 @@
 		if params.SearchMap == nil {
 			params.SearchMap = make(map[string]interface{}, 0)
 		}
-		params.SearchMap["member_id"] = userInfo.CrmUserId
+		params.SearchMap["member_ids"] = userInfo.SubUserIds
 	}
 
 	masterOrders, total, errCode := masterOrderService.GetMasterOrderList(params.Page, params.PageSize, params.SearchMap)
diff --git a/api/v1/plan.go b/api/v1/plan.go
index f09f7d9..2b59b8a 100644
--- a/api/v1/plan.go
+++ b/api/v1/plan.go
@@ -98,7 +98,6 @@
 	ctx.Ok()
 }
 
-
 func checkPlanParams(plan request.Plan) (errCode int, p model.Plan) {
 	//if plan.Number == "" {
 	//	return ecode.InvalidParams, p
@@ -155,7 +154,7 @@
 	}
 
 	ctx.OkWithDetailed(response.PlanResponse{
-		List: plans,
+		List:  plans,
 		Count: int(total),
 	})
-}
\ No newline at end of file
+}
diff --git a/api/v1/quotation.go b/api/v1/quotation.go
index 3fd3552..d237955 100644
--- a/api/v1/quotation.go
+++ b/api/v1/quotation.go
@@ -186,7 +186,7 @@
 		if params.SearchMap == nil {
 			params.SearchMap = make(map[string]interface{}, 0)
 		}
-		params.SearchMap["member_id"] = userInfo.CrmUserId
+		params.SearchMap["member_ids"] = userInfo.SubUserIds
 	}
 
 	quotations, total, errCode := quotationService.GetQuotationList(params.Page, params.PageSize, params.SearchMap)
diff --git a/api/v1/receipt.go b/api/v1/receipt.go
index 3367e14..44b0bb2 100644
--- a/api/v1/receipt.go
+++ b/api/v1/receipt.go
@@ -1,11 +1,13 @@
 package v1
 
 import (
+	"aps_crm/constvar"
 	"aps_crm/model/request"
 	"aps_crm/model/response"
 	"aps_crm/pkg/contextx"
 	"aps_crm/pkg/ecode"
 	"aps_crm/service"
+	"aps_crm/utils"
 	"github.com/gin-gonic/gin"
 	"strconv"
 )
@@ -99,6 +101,11 @@
 		return
 	}
 
+	userInfo := utils.GetUserInfo(c)
+	if userInfo.UserType == constvar.UserTypeSub {
+		params.PrincipleIds = userInfo.SubUserIds
+	}
+
 	receipt, total, errCode := service.NewReceiptService().GetReceiptList(params)
 	if errCode != ecode.OK {
 		ctx.Fail(errCode)
diff --git a/api/v1/saleChance.go b/api/v1/saleChance.go
index 73bcdb0..addf56e 100644
--- a/api/v1/saleChance.go
+++ b/api/v1/saleChance.go
@@ -226,7 +226,7 @@
 		if params.SearchMap == nil {
 			params.SearchMap = make(map[string]interface{}, 0)
 		}
-		params.SearchMap["member_id"] = userInfo.CrmUserId
+		params.SearchMap["member_ids"] = userInfo.SubUserIds
 	}
 
 	saleChances, total, errCode := saleChanceService.GetSaleChanceList(params.Page, params.PageSize, params.SearchMap)
diff --git a/api/v1/salesDetails.go b/api/v1/salesDetails.go
index 805084a..d417eca 100644
--- a/api/v1/salesDetails.go
+++ b/api/v1/salesDetails.go
@@ -190,7 +190,7 @@
 	var memberIds []int
 	userInfo := utils.GetUserInfo(c)
 	if userInfo.UserType == constvar.UserTypeSub {
-		memberIds = []int{userInfo.CrmUserId}
+		memberIds = userInfo.SubUserIds
 	}
 
 	salesDetailss, total, errCode := salesDetailsService.GetSalesDetailsList(params, memberIds)
diff --git a/api/v1/salesLeads.go b/api/v1/salesLeads.go
index e0d305e..530a1bf 100644
--- a/api/v1/salesLeads.go
+++ b/api/v1/salesLeads.go
@@ -175,7 +175,7 @@
 		if params.SearchMap == nil {
 			params.SearchMap = make(map[string]interface{}, 0)
 		}
-		params.SearchMap["member_id"] = userInfo.CrmUserId
+		params.SearchMap["member_ids"] = userInfo.SubUserIds
 	}
 
 	salesLeadss, total, errCode := salesLeadsService.GetSalesLeadsList(params.Page, params.PageSize, params.SearchMap)
diff --git a/api/v1/salesRefund.go b/api/v1/salesRefund.go
index 00ce774..174077c 100644
--- a/api/v1/salesRefund.go
+++ b/api/v1/salesRefund.go
@@ -184,7 +184,7 @@
 	var memberIds []int
 	userInfo := utils.GetUserInfo(c)
 	if userInfo.UserType == constvar.UserTypeSub {
-		memberIds = []int{userInfo.CrmUserId}
+		memberIds = userInfo.SubUserIds
 	}
 
 	salesRefunds, total, errCode := salesRefundService.GetSalesRefundList(params.Page, params.PageSize, params.KeywordType, params.Keyword, params.SourceId, memberIds)
diff --git a/api/v1/salesReturn.go b/api/v1/salesReturn.go
index 4e21782..70d3643 100644
--- a/api/v1/salesReturn.go
+++ b/api/v1/salesReturn.go
@@ -179,7 +179,7 @@
 	var memberIds []int
 	userInfo := utils.GetUserInfo(c)
 	if userInfo.UserType == constvar.UserTypeSub {
-		memberIds = []int{userInfo.CrmUserId}
+		memberIds = userInfo.SubUserIds
 	}
 
 	salesReturns, total, errCode := salesReturnService.GetSalesReturnList(params, memberIds)
diff --git a/api/v1/serviceContract.go b/api/v1/serviceContract.go
index 1edad01..e5b97d9 100644
--- a/api/v1/serviceContract.go
+++ b/api/v1/serviceContract.go
@@ -134,7 +134,7 @@
 	var memberIds []int
 	userInfo := utils.GetUserInfo(c)
 	if userInfo.UserType == constvar.UserTypeSub {
-		memberIds = []int{userInfo.CrmUserId}
+		memberIds = userInfo.SubUserIds
 	}
 
 	serviceContracts, total, errCode := serviceContractService.GetServiceContractList(params, memberIds)
diff --git a/api/v1/serviceFollowup.go b/api/v1/serviceFollowup.go
index d457ead..ce3bbc5 100644
--- a/api/v1/serviceFollowup.go
+++ b/api/v1/serviceFollowup.go
@@ -165,7 +165,7 @@
 	var memberIds []int
 	userInfo := utils.GetUserInfo(c)
 	if userInfo.UserType == constvar.UserTypeSub {
-		memberIds = []int{userInfo.CrmUserId}
+		memberIds = userInfo.SubUserIds
 	}
 
 	serviceFollowups, total, errCode := serviceFollowupService.GetServiceFollowupList(params.Page, params.PageSize, params.KeywordType, params.Keyword, params.ServiceOrderId, memberIds)
diff --git a/api/v1/serviceOrder.go b/api/v1/serviceOrder.go
index e557bd7..b03eb64 100644
--- a/api/v1/serviceOrder.go
+++ b/api/v1/serviceOrder.go
@@ -153,7 +153,7 @@
 	var memberIds []int
 	userInfo := utils.GetUserInfo(c)
 	if userInfo.UserType == constvar.UserTypeSub {
-		memberIds = []int{userInfo.CrmUserId}
+		memberIds = userInfo.SubUserIds
 	}
 
 	serviceOrder, total, errCode := service.NewServiceOrderService().GetServiceOrderList(params.Page, params.PageSize, params.QueryClass, params.KeywordType, params.Keyword, params.ServiceContractId, params.SalesDetailsId, memberIds)
diff --git a/api/v1/subOrder.go b/api/v1/subOrder.go
index 188e036..7f1e53a 100644
--- a/api/v1/subOrder.go
+++ b/api/v1/subOrder.go
@@ -157,7 +157,7 @@
 		if params.SearchMap == nil {
 			params.SearchMap = make(map[string]interface{}, 0)
 		}
-		params.SearchMap["member_id"] = userInfo.CrmUserId
+		params.SearchMap["member_ids"] = userInfo.SubUserIds
 	}
 
 	subOrders, total, errCode := subOrderService.GetSubOrderList(params.Page, params.PageSize, params.SearchMap)
diff --git a/constvar/const.go b/constvar/const.go
index cd33794..1107c6f 100644
--- a/constvar/const.go
+++ b/constvar/const.go
@@ -32,13 +32,6 @@
 	UserTypeSub                         // 瀛愯处鎴�
 )
 
-type NotAdmin int
-
-const (
-	NotAdminAll NotAdmin = iota // 鍏捣
-	NotAdminYes                 // 鎴戠殑瀹㈡埛
-)
-
 type SalesStatus int
 
 const (
diff --git a/main.go b/main.go
index 18843c8..9bdf14c 100644
--- a/main.go
+++ b/main.go
@@ -48,7 +48,6 @@
 		ReadTimeout:  5 * time.Second,
 		WriteTimeout: 5 * time.Second,
 	}
-
 	//鍚姩grpc瀹㈡埛绔�
 	go v1.InitProductServiceConn()
 	go middleware.InitUserConn()
@@ -70,9 +69,9 @@
 			panic(fmt.Sprintf("grpc server init error: %v", err.Error()))
 		}
 	}()
-	//c := cron.New()
-	//c.AddFunc("@every 15s", service.SyncUserInfo) // 姣�15绉掑悓姝ヤ竴娆�
-	//c.Start()
+
+	middleware.InitRefreshUserManager(5, 5, 3600)
+	middleware.RunRefreshUser() ///瀹氭椂瀵规椿璺冪敤鎴锋洿鏂扮敤鎴疯鎯�
 
 	logx.Error(server.ListenAndServe().Error())
 }
@@ -82,6 +81,7 @@
 	signal.Notify(quit, syscall.SIGKILL, syscall.SIGQUIT, syscall.SIGINT, syscall.SIGTERM)
 	<-quit
 
+	middleware.StopRefreshUser()
 	v1.CloseProductServiceConn()
 	v1.CloseCodeServiceConn()
 	v1.CloseProductInventoryServiceConn()
diff --git a/middleware/jwt.go b/middleware/jwt.go
index 240bf09..907a1d0 100644
--- a/middleware/jwt.go
+++ b/middleware/jwt.go
@@ -98,20 +98,26 @@
 		// parseToken 瑙f瀽token鍖呭惈鐨勪俊鎭�
 		claims, err := j.ParseToken(token)
 		if err != nil {
-			if err == utils.TokenExpired {
-				c.Next()
-				return
-			}
-			c.Next()
+			ctx.Fail(ecode.JWTDisabled)
+			c.Abort()
 			return
 		}
 		userInfo := service.GetUserBaseCache(claims.UserId)
 		if userInfo == nil {
-			SyncUserInfo()
+			SyncUserInfo([]string{claims.UserId})
 			userInfo = service.GetUserBaseCache(claims.UserId)
 		}
+		if userInfo == nil {
+			ctx.Fail(ecode.JWTDisabled)
+			c.Abort()
+			return
+		}
+
+		SetActiveTime(claims.UserId)
+
 		claims.CrmUserId = userInfo.UserId
 		claims.NickName = userInfo.NickName
+		claims.SubUserIds = userInfo.SubUserIds
 		c.Set("claims", claims)
 		if CheckAuth(c.Request.URL.Path, token) {
 			c.Next()
diff --git a/middleware/refresh_user.go b/middleware/refresh_user.go
new file mode 100644
index 0000000..54ebd3e
--- /dev/null
+++ b/middleware/refresh_user.go
@@ -0,0 +1,138 @@
+package middleware
+
+import (
+	"aps_crm/pkg/logx"
+	"context"
+	"fmt"
+	"sync"
+	"sync/atomic"
+	"time"
+)
+
+// RefreshUserManager 瀹氭椂鎷夊彇娲昏穬鐢ㄦ埛鐨勪俊鎭紙鍖呭惈涓嬪睘id锛�
+type RefreshUserManager struct {
+	RunFlag                   int32
+	StartRemoveUserFlag       int32
+	StartRefreshUserFlag      int32
+	Users                     map[string]*CurrentActiveUser
+	mu                        sync.RWMutex
+	ctx                       context.Context
+	expireSecond              int64
+	intervalRemoveUserMinute  int
+	intervalRefreshUserMinute int
+	cancel                    func()
+}
+
+type CurrentActiveUser struct {
+	UserID         string
+	lastActiveTime int64
+}
+
+var defaultRefreshUserManager *RefreshUserManager
+
+func InitRefreshUserManager(intervalRefreshUserMinute, intervalRemoveMinute int, expireSecond int64) {
+	if intervalRefreshUserMinute == 0 {
+		intervalRefreshUserMinute = 5
+	}
+	if intervalRemoveMinute > 0 && expireSecond == 0 {
+		expireSecond = int64(intervalRemoveMinute * 60 * 12)
+	}
+	ctx, cancel := context.WithCancel(context.Background())
+	defaultRefreshUserManager = &RefreshUserManager{
+		expireSecond:              expireSecond,
+		intervalRemoveUserMinute:  intervalRemoveMinute,
+		intervalRefreshUserMinute: intervalRefreshUserMinute,
+		ctx:                       ctx,
+		cancel:                    cancel,
+		Users:                     map[string]*CurrentActiveUser{},
+	}
+}
+
+func RunRefreshUser() {
+	if !atomic.CompareAndSwapInt32(&defaultRefreshUserManager.RunFlag, 0, 1) {
+		return
+	}
+	go defaultRefreshUserManager.refreshUserInfo()
+	go defaultRefreshUserManager.removeInActiveUser()
+}
+func StopRefreshUser() {
+	defaultRefreshUserManager.cancel()
+}
+
+func SetActiveTime(userID string) {
+	defaultRefreshUserManager.setActiveTime(userID)
+}
+
+// RefreshActiveTime 鏇存柊鐢ㄦ埛娲昏穬鏃堕棿
+func (r *RefreshUserManager) setActiveTime(userID string) {
+	r.mu.Lock()
+	defer r.mu.Unlock()
+	if r.Users[userID] == nil {
+		r.Users[userID] = &CurrentActiveUser{
+			UserID:         userID,
+			lastActiveTime: time.Now().Unix(),
+		}
+		logx.Infof("add active user :%+v", r.Users[userID])
+	} else {
+		r.Users[userID].lastActiveTime = time.Now().Unix()
+		logx.Infof("refresh active time, user:%+v", r.Users[userID])
+	}
+}
+
+func (r *RefreshUserManager) removeInActiveUser() {
+	if !atomic.CompareAndSwapInt32(&r.StartRemoveUserFlag, 0, 1) {
+		return
+	}
+	if r.intervalRemoveUserMinute == 0 { //涓嶆竻鐞�
+		return
+	}
+	ticker := time.NewTicker(time.Minute * time.Duration(r.intervalRemoveUserMinute))
+	for {
+		select {
+		case <-ticker.C:
+			nowTs := time.Now().Unix()
+			var users []*CurrentActiveUser
+			r.mu.RLock()
+			for _, user := range r.Users {
+				users = append(users, user)
+			}
+			r.mu.RUnlock()
+			for _, user := range users {
+				if nowTs-user.lastActiveTime > r.expireSecond {
+					r.mu.Lock()
+					logx.Infof("removed in active user:%+v", user)
+					delete(r.Users, user.UserID)
+					r.mu.Unlock()
+				}
+			}
+		case <-r.ctx.Done():
+			fmt.Println("stop RemoveInActiveUser.")
+			return
+		}
+	}
+}
+
+func (r *RefreshUserManager) refreshUserInfo() {
+	if !atomic.CompareAndSwapInt32(&r.StartRefreshUserFlag, 0, 1) {
+		return
+	}
+	ticker := time.NewTicker(time.Minute * time.Duration(r.intervalRefreshUserMinute))
+	for {
+		select {
+		case <-ticker.C:
+			r.mu.RLock()
+			userIds := make([]string, len(r.Users))
+			for userID := range r.Users {
+				userIds = append(userIds, userID)
+			}
+			r.mu.RUnlock()
+			if len(userIds) != 0 {
+				logx.Infof("RefreshUserInfo, user ids: ", userIds)
+				SyncUserInfo(userIds)
+			}
+		case <-r.ctx.Done():
+			fmt.Println("stop RefreshUserInfo.")
+			return
+		}
+	}
+}
diff --git a/middleware/user.go b/middleware/user.go
index f1e4487..198b328 100644
--- a/middleware/user.go
+++ b/middleware/user.go
@@ -7,9 +7,9 @@
 	"aps_crm/pkg/logx"
 	"aps_crm/proto/user"
 	"context"
-	"fmt"
 	"google.golang.org/grpc"
 	"google.golang.org/grpc/credentials/insecure"
+	"strings"
 	"time"
 )
 
@@ -59,11 +59,14 @@
 	return rsp.Result
 }
 
-func SyncUserInfo() {
+func SyncUserInfo(uuid []string) {
 	cli := user.NewUserServiceClient(userConn)
-
 	var users []*user.User
-
+	for _, id := range uuid {
+		users = append(users, &user.User{
+			Uuid: id,
+		})
+	}
 	ctx, cancel := context.WithTimeout(context.Background(), time.Second)
 	defer cancel()
 	r, err := cli.SyncUser(ctx, &user.UserRequest{Users: users})
@@ -72,15 +75,19 @@
 		return
 	}
 
-	fmt.Printf("Synced: %v, Message: %s", r.List, r.Message)
+	logx.Infof("Synced: %v, Message: %s", r.List, r.Message)
 
 	for _, member := range r.List {
-		err = model.NewUserSearch(nil).FirstOrCreate(model.User{
+		userRecord := model.User{
 			UUID:     member.Uuid,
 			Username: member.Username,
 			UserType: constvar.UserType(member.Usertype),
 			NickName: member.Nickname,
-		})
+		}
+		if member.SubUserIds != nil {
+			userRecord.SubUserIds = strings.Join(member.SubUserIds, ",")
+		}
+		err = model.NewUserSearch(nil).Upsert(userRecord, member.SubUserQueried)
 		if err != nil {
 			logx.Errorf("sync user error: %v", err.Error())
 			continue
diff --git a/model/client.go b/model/client.go
index 590c079..dea1044 100644
--- a/model/client.go
+++ b/model/client.go
@@ -117,18 +117,22 @@
 					db = db.Joins("Member").Where("Member.username LIKE ?", "%"+v+"%")
 				}
 
-			case int, uint, int64, float64:
+			case int, uint, int64, float64, bool:
 				if key == "id" || key == "client_type_id" || key == "client_status_id" || key == "member_id" {
 					db = db.Where(key+" = ?", v)
 				}
 
-				if key == "not_admin" {
-					if v == float64(constvar.NotAdminYes) {
-						db = db.Where("clients.member_id != ?", constvar.UserTypeSuper)
-					} else {
-						db = db.Where("clients.member_id = ?", constvar.UserTypeSuper)
+				if key == "is_public" {
+					if val, ok := v.(bool); ok {
+						if val {
+							db = db.Where("clients.member_id = ?", 0)
+						}
 					}
 				}
+			case []int:
+				if key == "member_ids" {
+					db = db.Where("clients.member_id in ?", v)
+				}
 
 			}
 		}
diff --git a/model/contact.go b/model/contact.go
index f47d4f3..a01d3be 100644
--- a/model/contact.go
+++ b/model/contact.go
@@ -100,6 +100,10 @@
 				if key == "client_id" {
 					db = db.Where("client_id = ? and is_first = true", v)
 				}
+			case []int:
+				if key == "member_ids" {
+					db = db.Where("contacts.member_id in ?", v)
+				}
 			}
 		}
 	}
diff --git a/model/contract.go b/model/contract.go
index 91e50e8..e437c6c 100644
--- a/model/contract.go
+++ b/model/contract.go
@@ -80,6 +80,10 @@
 				if key == "member_id" {
 					db = db.Where(key+"= ?", v)
 				}
+			case []int:
+				if key == "member_ids" {
+					db = db.Where("contract.member_id in ?", v)
+				}
 			}
 		}
 	}
diff --git a/model/followRecord.go b/model/followRecord.go
index afc27cb..b220de2 100644
--- a/model/followRecord.go
+++ b/model/followRecord.go
@@ -106,6 +106,10 @@
 				if key == "client_id" || key == "contact_id" || key == "sales_leads_id" || key == "sale_chance_id" || key == "member_id" {
 					db = db.Where(key+" = ?", v)
 				}
+			case []int:
+				if key == "member_ids" {
+					db = db.Where("follow_records.member_id in ?", v)
+				}
 			}
 		}
 	}
diff --git a/model/invoice.go b/model/invoice.go
index 0db64fa..7089b18 100644
--- a/model/invoice.go
+++ b/model/invoice.go
@@ -36,12 +36,13 @@
 	// InvoiceSearch 閿�鍞彂绁ㄦ悳绱㈡潯浠�
 	InvoiceSearch struct {
 		Invoice
-		Orm         *gorm.DB
-		QueryClass  constvar.InvoiceQueryClass
-		KeywordType constvar.InvoiceKeywordType
-		Keyword     string
-		PageNum     int
-		PageSize    int
+		Orm          *gorm.DB
+		QueryClass   constvar.InvoiceQueryClass
+		KeywordType  constvar.InvoiceKeywordType
+		Keyword      string
+		PageNum      int
+		PageSize     int
+		PrincipalIds []int
 	}
 )
 
@@ -65,6 +66,11 @@
 	return slf
 }
 
+func (slf *InvoiceSearch) SetPrincipalIds(principalIds []int) *InvoiceSearch {
+	slf.PrincipalIds = principalIds
+	return slf
+}
+
 func (slf *InvoiceSearch) build() *gorm.DB {
 	var db = slf.Orm.Model(&Invoice{})
 	if slf.Id != 0 {
@@ -81,6 +87,9 @@
 	if slf.Number != "" {
 		db.Where("number = ?", slf.Number)
 	}
+	if len(slf.PrincipalIds) > 0 {
+		db = db.Where("principal_id in ?", slf.PrincipalIds)
+	}
 
 	return db
 }
diff --git a/model/masterOrder.go b/model/masterOrder.go
index 112d16f..3b77851 100644
--- a/model/masterOrder.go
+++ b/model/masterOrder.go
@@ -72,6 +72,10 @@
 				if key == "client_id" || key == "member_id" || key == "money" {
 					db = db.Where(key+" = ?", v)
 				}
+			case []int:
+				if key == "member_ids" {
+					db = db.Where("master_order.member_id in ?", v)
+				}
 			}
 		}
 	}
diff --git a/model/plan.go b/model/plan.go
index 0ba2f15..8386692 100644
--- a/model/plan.go
+++ b/model/plan.go
@@ -25,11 +25,12 @@
 	PlanSearch struct {
 		Plan
 
-		Orm      *gorm.DB
-		Keyword  string
-		OrderBy  string
-		PageNum  int
-		PageSize int
+		Orm       *gorm.DB
+		Keyword   string
+		OrderBy   string
+		PageNum   int
+		PageSize  int
+		MemberIds []int
 	}
 )
 
@@ -50,6 +51,9 @@
 	}
 	if slf.Id != 0 {
 		db = db.Where("id = ?", slf.Id)
+	}
+	if len(slf.MemberIds) != 0 {
+		db = db.Where("member_id in ?", slf.MemberIds)
 	}
 
 	return db
@@ -97,6 +101,11 @@
 	return slf
 }
 
+func (slf *PlanSearch) SetMemberIds(ids []int) *PlanSearch {
+	slf.MemberIds = ids
+	return slf
+}
+
 func (slf *PlanSearch) SetKeyword(keyword string) *PlanSearch {
 	slf.Keyword = keyword
 	return slf
diff --git a/model/quotation.go b/model/quotation.go
index 969d34f..1c45c24 100644
--- a/model/quotation.go
+++ b/model/quotation.go
@@ -88,6 +88,10 @@
 				if key == "client_id" || key == "sale_chance_id" || key == "member_id" {
 					db = db.Where(key+" = ?", v)
 				}
+			case []int:
+				if key == "member_ids" {
+					db = db.Where("quotation.member_id in ?", v)
+				}
 			}
 		}
 	}
diff --git a/model/receipt.go b/model/receipt.go
index 2ca94cf..ff0a169 100644
--- a/model/receipt.go
+++ b/model/receipt.go
@@ -34,12 +34,13 @@
 	// ReceiptSearch 鏀舵鍗曟悳绱㈡潯浠�
 	ReceiptSearch struct {
 		Receipt
-		Orm         *gorm.DB
-		QueryClass  constvar.ReceiptQueryClass
-		KeywordType constvar.ReceiptKeywordType
-		Keyword     string
-		PageNum     int
-		PageSize    int
+		Orm          *gorm.DB
+		QueryClass   constvar.ReceiptQueryClass
+		KeywordType  constvar.ReceiptKeywordType
+		Keyword      string
+		PageNum      int
+		PageSize     int
+		PrincipalIds []int
 	}
 )
 
@@ -72,6 +73,11 @@
 	return slf
 }
 
+func (slf *ReceiptSearch) SetPrincipalIds(principalIds []int) *ReceiptSearch {
+	slf.PrincipalIds = principalIds
+	return slf
+}
+
 func (slf *ReceiptSearch) SetPage(page, size int) *ReceiptSearch {
 	slf.PageNum, slf.PageSize = page, size
 	return slf
@@ -91,6 +97,9 @@
 	if slf.ClientId != 0 {
 		db = db.Where("client_id = ?", slf.ClientId)
 	}
+	if len(slf.PrincipalIds) != 0 {
+		db = db.Where("principal_id in ?", slf.PrincipalIds)
+	}
 
 	return db
 }
diff --git a/model/request/invoice.go b/model/request/invoice.go
index fa08e2f..f22f4f1 100644
--- a/model/request/invoice.go
+++ b/model/request/invoice.go
@@ -44,6 +44,7 @@
 
 type GetInvoiceList struct {
 	PageInfo
-	SourceId   int                        `json:"sourceId"`
-	SourceType constvar.InvoiceSourceType `json:"sourceType"` // 婧愬崟绫诲瀷(1閿�鍞槑缁嗗崟2鏈嶅姟鍚堝悓)
+	SourceId     int                        `json:"sourceId"`
+	SourceType   constvar.InvoiceSourceType `json:"sourceType"` // 婧愬崟绫诲瀷(1閿�鍞槑缁嗗崟2鏈嶅姟鍚堝悓)
+	PrincipalIds []int
 }
diff --git a/model/request/jwt.go b/model/request/jwt.go
index e67ab55..606e7b4 100644
--- a/model/request/jwt.go
+++ b/model/request/jwt.go
@@ -10,8 +10,9 @@
 	BaseClaims
 	BufferTime int64
 	jwt.StandardClaims
-	CrmUserId int
-	NickName  string
+	CrmUserId  int
+	NickName   string
+	SubUserIds []int //鍖呭惈鑷韩鐨刬d
 }
 
 type BaseClaims struct {
diff --git a/model/request/receipt.go b/model/request/receipt.go
index 2285ea3..626e8d3 100644
--- a/model/request/receipt.go
+++ b/model/request/receipt.go
@@ -16,7 +16,8 @@
 
 type GetReceiptList struct {
 	PageInfo
-	SourceType constvar.ReceiptSourceType `json:"sourceType" form:"sourceType"` //鏉ユ簮绫诲瀷锛�1閿�鍞槑缁嗗崟2鏈嶅姟鍚堝悓3閿�鍞彂绁�4鏀舵璁″垝5鍑哄簱鍗曪級
-	SourceId   int                        `json:"sourceId" form:"sourceId"`
-	ClientId   int                        `json:"clientId"  form:"clientId"` //瀹㈡埛id
+	SourceType   constvar.ReceiptSourceType `json:"sourceType" form:"sourceType"` //鏉ユ簮绫诲瀷锛�1閿�鍞槑缁嗗崟2鏈嶅姟鍚堝悓3閿�鍞彂绁�4鏀舵璁″垝5鍑哄簱鍗曪級
+	SourceId     int                        `json:"sourceId" form:"sourceId"`
+	ClientId     int                        `json:"clientId"  form:"clientId"` //瀹㈡埛id
+	PrincipleIds []int
 }
diff --git a/model/saleChance.go b/model/saleChance.go
index 5f0f37c..9cde56f 100644
--- a/model/saleChance.go
+++ b/model/saleChance.go
@@ -121,6 +121,10 @@
 				if key == "member_id" || key == "budget" || key == "projected_amount" || key == "client_id" {
 					db = db.Where(key+" = ?", v)
 				}
+			case []int:
+				if key == "member_ids" {
+					db = db.Where("sale_chance.member_id in ?", v)
+				}
 			}
 		}
 	}
diff --git a/model/salesLeads.go b/model/salesLeads.go
index 4439bdb..f783ad2 100644
--- a/model/salesLeads.go
+++ b/model/salesLeads.go
@@ -92,8 +92,9 @@
 				}
 
 			case int:
-				if key == "member_id" {
-					db = db.Where("sales_leads.member_id = ?", v)
+			case []int:
+				if key == "member_ids" {
+					db = db.Where("sales_leads.member_id in ?", v)
 				}
 			}
 		}
diff --git a/model/serviceFeeManage.go b/model/serviceFeeManage.go
index 45f4705..f54d3e7 100644
--- a/model/serviceFeeManage.go
+++ b/model/serviceFeeManage.go
@@ -28,6 +28,7 @@
 		OrderBy     string
 		PageNum     int
 		PageSize    int
+		MemberIds   []int
 	}
 )
 
@@ -53,6 +54,11 @@
 	if slf.ClientId != 0 {
 		db.Where("client_id = ?", slf.ClientId)
 	}
+
+	if len(slf.MemberIds) > 0 {
+		db.Where("service_fee_manage.member_id in ?", slf.MemberIds)
+	}
+
 	switch slf.QueryClass {
 	case constvar.ServiceFeeQueryClassExpireLessThen60Days:
 		db = db.Where("latest_date > ? and latest_date < ?", time.Now(), time.Now().AddDate(0, 0, 60))
@@ -120,6 +126,11 @@
 	return slf
 }
 
+func (slf *ServiceFeeManageSearch) SetMemberIds(ids []int) *ServiceFeeManageSearch {
+	slf.MemberIds = ids
+	return slf
+}
+
 func (slf *ServiceFeeManageSearch) SetKeywordType(keyword constvar.ServiceFeeKeywordType) *ServiceFeeManageSearch {
 	slf.KeywordType = keyword
 	return slf
diff --git a/model/serviceOrder.go b/model/serviceOrder.go
index c3d350b..7af464a 100644
--- a/model/serviceOrder.go
+++ b/model/serviceOrder.go
@@ -132,7 +132,7 @@
 	}
 
 	if len(slf.ServiceManIds) > 0 {
-		db = db.Where("service_man_id in ?", slf.ServiceManIds)
+		db = db.Where("service_order.service_man_id in ?", slf.ServiceManIds)
 	}
 	if slf.ServiceNumber != "" {
 		db = db.Where("service_number = ?", slf.ServiceNumber)
diff --git a/model/subOrder.go b/model/subOrder.go
index 930e672..765b112 100644
--- a/model/subOrder.go
+++ b/model/subOrder.go
@@ -81,6 +81,10 @@
 				if key == "member_id" {
 					db = db.Where("sub_order.member_id = ?", v)
 				}
+			case []int:
+				if key == "member_ids" {
+					db = db.Where("sub_order.member_id in ?", v)
+				}
 			}
 		}
 	}
diff --git a/model/user.go b/model/user.go
index 925d6d7..44f7fdc 100644
--- a/model/user.go
+++ b/model/user.go
@@ -11,7 +11,7 @@
 	// User token閲岃竟鎶婄敤鎴稩D銆佺埗鐢ㄦ埛ID銆佽鑹查兘甯︿笂
 	User struct {
 		ID           int               `json:"id" gorm:"column:id;primary_key;AUTO_INCREMENT"`
-		UUID         string            `json:"uuid" gorm:"primaryKey;type:varchar(255);comment:鐢ㄦ埛ID"`
+		UUID         string            `json:"uuid" gorm:"uniqueIndex;type:varchar(255);comment:鐢ㄦ埛ID"`
 		Username     string            `json:"username" gorm:"index;type:varchar(255);comment:鐢ㄦ埛鐧诲綍鍚�"`
 		UserType     constvar.UserType `json:"userType" gorm:"type:int(11);comment:鐢ㄦ埛绫诲瀷 1瓒呯骇绠$悊鍛� 2涓昏处鎴� 3瀛愯处鎴�"`
 		Password     string            `json:"-"  gorm:"type:varchar(255);comment:鐢ㄦ埛鐧诲綍瀵嗙爜"`
@@ -26,6 +26,7 @@
 		MenuIds      []uint            `json:"menuIds" gorm:"-"`                              // 鑿滃崟ID鍒楄〃
 		AuthorityId  uint              `json:"authorityId" gorm:"default:888;comment:鐢ㄦ埛瑙掕壊ID"` // 鐢ㄦ埛瑙掕壊ID
 		Authority    Authority         `json:"authority" gorm:"foreignKey:AuthorityId"`
+		SubUserIds   string            `json:"subUserIds" gorm:"sub_user_ids"` //涓嬪睘鍛樺伐鐢ㄦ埛id,鐢ㄩ�楀彿鍒嗗紑
 		gorm.Model   `json:"-"`
 	}
 
@@ -36,6 +37,7 @@
 		PageNum  int
 		PageSize int
 		Orm      *gorm.DB
+		IDs      []int
 	}
 )
 
@@ -75,6 +77,11 @@
 	return slf
 }
 
+func (slf *UserSearch) SetUserIds(userIds []int) *UserSearch {
+	slf.IDs = userIds
+	return slf
+}
+
 func (slf *UserSearch) SetUserName(username string) *UserSearch {
 	slf.Username = username
 	return slf
@@ -102,6 +109,14 @@
 
 	if slf.Order != "" {
 		db = db.Order(slf.Order)
+	}
+
+	if slf.ID != 0 {
+		db = db.Where("id = ?", slf.ID)
+	}
+
+	if len(slf.IDs) > 0 {
+		db = db.Where("id in ?", slf.IDs)
 	}
 
 	return db
@@ -277,12 +292,45 @@
 	return records, nil
 }
 
-func (slf *UserSearch) FirstOrCreate(record User) error {
-	var db = slf.build()
+func (slf *UserSearch) Upsert(record User, SubUserQueried bool) error {
 
-	if err := db.FirstOrCreate(&User{}, record).Error; err != nil {
-		return fmt.Errorf("first or create err: %v, record: %+v", err, record)
+	var db = slf.SetId(record.UUID).build()
+	old, err := slf.First()
+	if err == gorm.ErrRecordNotFound {
+		if err := db.Create(&record).Error; err != nil {
+			return fmt.Errorf("create user err: %v, record: %+v", err, record)
+		}
+	} else if old.Username != record.Username ||
+		old.UserType != record.UserType ||
+		old.NickName != record.NickName ||
+		SubUserQueried && old.SubUserIds != record.SubUserIds {
+		old.Username = record.Username
+		old.UserType = record.UserType
+		old.NickName = record.NickName
+		old.SubUserIds = record.SubUserIds
+		if err := db.Save(&old).Error; err != nil {
+			return fmt.Errorf("update user err: %v, old record: %+v", err, old)
+		}
 	}
 
 	return nil
 }
+
+type IdPair struct {
+	ID   int    `json:"id" gorm:"column:id;primary_key;AUTO_INCREMENT"`
+	UUID string `json:"uuid" gorm:"unique;type:varchar(255);comment:鐢ㄦ埛ID"`
+}
+
+func (slf *UserSearch) UUID2CrmUserId(userIds []string) ([]*IdPair, error) {
+	var (
+		records = make([]*IdPair, 0)
+		db      = slf.Orm.Model(&User{})
+	)
+
+	db = db.Where("uuid in ?", userIds)
+	if err := db.Select("user.id, user.uuid").Find(&records).Error; err != nil {
+		return records, fmt.Errorf("find all err: %v", err)
+	}
+
+	return records, nil
+}
diff --git a/proto/user.proto b/proto/user.proto
index 50e32f3..8234322 100644
--- a/proto/user.proto
+++ b/proto/user.proto
@@ -14,7 +14,8 @@
   string username = 2;
   int32 usertype = 3;
   string nickname = 4;
-  // ... other fields
+  repeated string sub_user_ids = 5;
+  bool sub_user_queried = 6;
 }
 
 message UserRequest {
diff --git a/proto/user/user.pb.go b/proto/user/user.pb.go
index 399d3aa..ab4f0db 100644
--- a/proto/user/user.pb.go
+++ b/proto/user/user.pb.go
@@ -25,10 +25,12 @@
 	sizeCache     protoimpl.SizeCache
 	unknownFields protoimpl.UnknownFields
 
-	Uuid     string `protobuf:"bytes,1,opt,name=uuid,proto3" json:"uuid,omitempty"`
-	Username string `protobuf:"bytes,2,opt,name=username,proto3" json:"username,omitempty"`
-	Usertype int32  `protobuf:"varint,3,opt,name=usertype,proto3" json:"usertype,omitempty"`
-	Nickname string `protobuf:"bytes,4,opt,name=nickname,proto3" json:"nickname,omitempty"` // ... other fields
+	Uuid           string   `protobuf:"bytes,1,opt,name=uuid,proto3" json:"uuid,omitempty"`
+	Username       string   `protobuf:"bytes,2,opt,name=username,proto3" json:"username,omitempty"`
+	Usertype       int32    `protobuf:"varint,3,opt,name=usertype,proto3" json:"usertype,omitempty"`
+	Nickname       string   `protobuf:"bytes,4,opt,name=nickname,proto3" json:"nickname,omitempty"`
+	SubUserIds     []string `protobuf:"bytes,5,rep,name=sub_user_ids,json=subUserIds,proto3" json:"sub_user_ids,omitempty"`
+	SubUserQueried bool     `protobuf:"varint,6,opt,name=sub_user_queried,json=subUserQueried,proto3" json:"sub_user_queried,omitempty"`
 }
 
 func (x *User) Reset() {
@@ -89,6 +91,20 @@
 		return x.Nickname
 	}
 	return ""
+}
+
+func (x *User) GetSubUserIds() []string {
+	if x != nil {
+		return x.SubUserIds
+	}
+	return nil
+}
+
+func (x *User) GetSubUserQueried() bool {
+	if x != nil {
+		return x.SubUserQueried
+	}
+	return false
 }
 
 type UserRequest struct {
@@ -331,43 +347,48 @@
 
 var file_user_proto_rawDesc = []byte{
 	0x0a, 0x0a, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x04, 0x75, 0x73,
-	0x65, 0x72, 0x22, 0x6e, 0x0a, 0x04, 0x55, 0x73, 0x65, 0x72, 0x12, 0x12, 0x0a, 0x04, 0x75, 0x75,
-	0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x75, 0x75, 0x69, 0x64, 0x12, 0x1a,
-	0x0a, 0x08, 0x75, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09,
-	0x52, 0x08, 0x75, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x75, 0x73,
-	0x65, 0x72, 0x74, 0x79, 0x70, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x05, 0x52, 0x08, 0x75, 0x73,
-	0x65, 0x72, 0x74, 0x79, 0x70, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x6e, 0x69, 0x63, 0x6b, 0x6e, 0x61,
-	0x6d, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x6e, 0x69, 0x63, 0x6b, 0x6e, 0x61,
-	0x6d, 0x65, 0x22, 0x2f, 0x0a, 0x0b, 0x55, 0x73, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73,
-	0x74, 0x12, 0x20, 0x0a, 0x05, 0x75, 0x73, 0x65, 0x72, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b,
-	0x32, 0x0a, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x52, 0x05, 0x75, 0x73,
-	0x65, 0x72, 0x73, 0x22, 0x72, 0x0a, 0x0c, 0x55, 0x73, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f,
-	0x6e, 0x73, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28,
-	0x05, 0x52, 0x04, 0x63, 0x6f, 0x64, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61,
-	0x67, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67,
-	0x65, 0x12, 0x1e, 0x0a, 0x04, 0x4c, 0x69, 0x73, 0x74, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32,
-	0x0a, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x52, 0x04, 0x4c, 0x69, 0x73,
-	0x74, 0x12, 0x14, 0x0a, 0x05, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x18, 0x04, 0x20, 0x01, 0x28, 0x03,
-	0x52, 0x05, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x22, 0x48, 0x0a, 0x0c, 0x43, 0x68, 0x65, 0x63, 0x6b,
-	0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x18, 0x0a, 0x07, 0x61, 0x70, 0x69, 0x50, 0x61,
-	0x74, 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x61, 0x70, 0x69, 0x50, 0x61, 0x74,
-	0x68, 0x12, 0x1e, 0x0a, 0x0a, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x54, 0x79, 0x70, 0x65, 0x18,
-	0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0a, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x54, 0x79, 0x70,
-	0x65, 0x22, 0x55, 0x0a, 0x0d, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e,
-	0x73, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05,
-	0x52, 0x04, 0x63, 0x6f, 0x64, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67,
-	0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65,
-	0x12, 0x16, 0x0a, 0x06, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08,
-	0x52, 0x06, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x32, 0x7a, 0x0a, 0x0b, 0x55, 0x73, 0x65, 0x72,
-	0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x31, 0x0a, 0x08, 0x53, 0x79, 0x6e, 0x63, 0x55,
-	0x73, 0x65, 0x72, 0x12, 0x11, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x52,
-	0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x12, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x55, 0x73,
-	0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x38, 0x0a, 0x0d, 0x55, 0x73,
-	0x65, 0x72, 0x4d, 0x65, 0x6e, 0x75, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x12, 0x12, 0x2e, 0x75, 0x73,
-	0x65, 0x72, 0x2e, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a,
-	0x13, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x52, 0x65, 0x73, 0x70,
-	0x6f, 0x6e, 0x73, 0x65, 0x42, 0x08, 0x5a, 0x06, 0x2e, 0x2f, 0x75, 0x73, 0x65, 0x72, 0x62, 0x06,
-	0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
+	0x65, 0x72, 0x22, 0xba, 0x01, 0x0a, 0x04, 0x55, 0x73, 0x65, 0x72, 0x12, 0x12, 0x0a, 0x04, 0x75,
+	0x75, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x75, 0x75, 0x69, 0x64, 0x12,
+	0x1a, 0x0a, 0x08, 0x75, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28,
+	0x09, 0x52, 0x08, 0x75, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x75,
+	0x73, 0x65, 0x72, 0x74, 0x79, 0x70, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x05, 0x52, 0x08, 0x75,
+	0x73, 0x65, 0x72, 0x74, 0x79, 0x70, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x6e, 0x69, 0x63, 0x6b, 0x6e,
+	0x61, 0x6d, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x6e, 0x69, 0x63, 0x6b, 0x6e,
+	0x61, 0x6d, 0x65, 0x12, 0x20, 0x0a, 0x0c, 0x73, 0x75, 0x62, 0x5f, 0x75, 0x73, 0x65, 0x72, 0x5f,
+	0x69, 0x64, 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0a, 0x73, 0x75, 0x62, 0x55, 0x73,
+	0x65, 0x72, 0x49, 0x64, 0x73, 0x12, 0x28, 0x0a, 0x10, 0x73, 0x75, 0x62, 0x5f, 0x75, 0x73, 0x65,
+	0x72, 0x5f, 0x71, 0x75, 0x65, 0x72, 0x69, 0x65, 0x64, 0x18, 0x06, 0x20, 0x01, 0x28, 0x08, 0x52,
+	0x0e, 0x73, 0x75, 0x62, 0x55, 0x73, 0x65, 0x72, 0x51, 0x75, 0x65, 0x72, 0x69, 0x65, 0x64, 0x22,
+	0x2f, 0x0a, 0x0b, 0x55, 0x73, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x20,
+	0x0a, 0x05, 0x75, 0x73, 0x65, 0x72, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0a, 0x2e,
+	0x75, 0x73, 0x65, 0x72, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x52, 0x05, 0x75, 0x73, 0x65, 0x72, 0x73,
+	0x22, 0x72, 0x0a, 0x0c, 0x55, 0x73, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65,
+	0x12, 0x12, 0x0a, 0x04, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x04,
+	0x63, 0x6f, 0x64, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18,
+	0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x1e,
+	0x0a, 0x04, 0x4c, 0x69, 0x73, 0x74, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0a, 0x2e, 0x75,
+	0x73, 0x65, 0x72, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x52, 0x04, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x14,
+	0x0a, 0x05, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x18, 0x04, 0x20, 0x01, 0x28, 0x03, 0x52, 0x05, 0x74,
+	0x6f, 0x74, 0x61, 0x6c, 0x22, 0x48, 0x0a, 0x0c, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x52, 0x65, 0x71,
+	0x75, 0x65, 0x73, 0x74, 0x12, 0x18, 0x0a, 0x07, 0x61, 0x70, 0x69, 0x50, 0x61, 0x74, 0x68, 0x18,
+	0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x61, 0x70, 0x69, 0x50, 0x61, 0x74, 0x68, 0x12, 0x1e,
+	0x0a, 0x0a, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x54, 0x79, 0x70, 0x65, 0x18, 0x02, 0x20, 0x01,
+	0x28, 0x05, 0x52, 0x0a, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x54, 0x79, 0x70, 0x65, 0x22, 0x55,
+	0x0a, 0x0d, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12,
+	0x12, 0x0a, 0x04, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x04, 0x63,
+	0x6f, 0x64, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x02,
+	0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x16, 0x0a,
+	0x06, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x06, 0x72,
+	0x65, 0x73, 0x75, 0x6c, 0x74, 0x32, 0x7a, 0x0a, 0x0b, 0x55, 0x73, 0x65, 0x72, 0x53, 0x65, 0x72,
+	0x76, 0x69, 0x63, 0x65, 0x12, 0x31, 0x0a, 0x08, 0x53, 0x79, 0x6e, 0x63, 0x55, 0x73, 0x65, 0x72,
+	0x12, 0x11, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75,
+	0x65, 0x73, 0x74, 0x1a, 0x12, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x52,
+	0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x38, 0x0a, 0x0d, 0x55, 0x73, 0x65, 0x72, 0x4d,
+	0x65, 0x6e, 0x75, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x12, 0x12, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e,
+	0x43, 0x68, 0x65, 0x63, 0x6b, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x13, 0x2e, 0x75,
+	0x73, 0x65, 0x72, 0x2e, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73,
+	0x65, 0x42, 0x08, 0x5a, 0x06, 0x2e, 0x2f, 0x75, 0x73, 0x65, 0x72, 0x62, 0x06, 0x70, 0x72, 0x6f,
+	0x74, 0x6f, 0x33,
 }
 
 var (
diff --git a/service/assign.go b/service/assign.go
index 4f6d526..88e789e 100644
--- a/service/assign.go
+++ b/service/assign.go
@@ -1,41 +1,43 @@
-package service
-
-import (
-	"aps_crm/model"
-	"aps_crm/pkg/ecode"
-)
-
-type AssignService struct{}
-
-type Assign interface {
-	Assign(id int) error
-}
-
-func (AssignService) Assign(memberId int, ids []int, modelType string) int {
-	// check member exist
-	_, err := model.NewUserSearch(nil).SetUserId(memberId).First()
-	if err != nil {
-		return ecode.UserNotExist
-	}
-
-	var errCode int
-	switch modelType {
-	case "client":
-		errCode = ClientService{}.Assign(ids, memberId)
-	case "salesLead":
-		errCode = SalesLeadsService{}.Assign(ids, memberId)
-	case "contact":
-		errCode = ContactService{}.Assign(ids, memberId)
-	case "followRecord":
-		errCode = FollowRecordService{}.Assign(ids, memberId)
-
-	default:
-		errCode = ecode.AssignWrongModelType
-	}
-
-	if errCode != ecode.OK {
-		return errCode
-	}
-
-	return ecode.OK
-}
+package service
+
+import (
+	"aps_crm/model"
+	"aps_crm/pkg/ecode"
+)
+
+type AssignService struct{}
+
+type Assign interface {
+	Assign(id int) error
+}
+
+func (AssignService) Assign(memberId int, ids []int, modelType string) int {
+	// check member exist
+	if memberId != 0 {
+		_, err := model.NewUserSearch(nil).SetUserId(memberId).First()
+		if err != nil {
+			return ecode.UserNotExist
+		}
+	}
+
+	var errCode int
+	switch modelType {
+	case "client":
+		errCode = ClientService{}.Assign(ids, memberId)
+	case "salesLead":
+		errCode = SalesLeadsService{}.Assign(ids, memberId)
+	case "contact":
+		errCode = ContactService{}.Assign(ids, memberId)
+	case "followRecord":
+		errCode = FollowRecordService{}.Assign(ids, memberId)
+
+	default:
+		errCode = ecode.AssignWrongModelType
+	}
+
+	if errCode != ecode.OK {
+		return errCode
+	}
+
+	return ecode.OK
+}
diff --git a/service/dataServer.go b/service/dataServer.go
index 4ea3990..63f1d40 100644
--- a/service/dataServer.go
+++ b/service/dataServer.go
@@ -1,13 +1,16 @@
 package service
 
 import (
+	"aps_crm/constvar"
 	"aps_crm/model/response"
 	"aps_crm/pkg/ecode"
+	"aps_crm/utils"
+	"github.com/gin-gonic/gin"
 )
 
 type DataServer struct{}
 
-func (DataServer) GetAllData() (errCode int, data response.DataResponse) {
+func (DataServer) GetAllData(c *gin.Context) (errCode int, data response.DataResponse) {
 	// get country list
 	countryList, _ := ServiceGroup.GetCountryList()
 	data.Country = countryList
@@ -73,7 +76,14 @@
 	data.RegularCustomers = regularCustomerList
 
 	// get Member list
-	memberList, _ := ServiceGroup.GetUserList()
+
+	var memberIds []int
+	userInfo := utils.GetUserInfo(c)
+	if userInfo.UserType == constvar.UserTypeSub {
+		memberIds = userInfo.SubUserIds
+	}
+
+	memberList, _ := ServiceGroup.GetUserList(memberIds)
 	data.Member = memberList
 
 	// get Department list
diff --git a/service/initdb.go b/service/initdb.go
index f377d0d..fd7149e 100644
--- a/service/initdb.go
+++ b/service/initdb.go
@@ -3,7 +3,6 @@
 import (
 	"aps_crm/pkg/logx"
 	"context"
-	"errors"
 	"sort"
 )
 
@@ -63,7 +62,8 @@
 // InitDB 鍒濆鍖�
 func (initDBService *InitDBService) InitDB() (err error) {
 	if len(initializerList) == 0 {
-		return errors.New("鏃犲彲鐢ㄥ垵濮嬪寲杩囩▼锛岃妫�鏌ュ垵濮嬪寲鏄惁宸叉墽琛屽畬鎴�")
+		logx.Warn("鏃犲彲鐢ㄥ垵濮嬪寲杩囩▼锛岃妫�鏌ュ垵濮嬪寲鏄惁宸叉墽琛屽畬鎴�")
+		return nil
 	}
 	sort.Sort(&initializerList) // 淇濊瘉鏈変緷璧栫殑 initializer 鎺掑湪鍚庨潰鎵ц
 
diff --git a/service/invoice.go b/service/invoice.go
index 9aaf90f..339674a 100644
--- a/service/invoice.go
+++ b/service/invoice.go
@@ -140,7 +140,7 @@
 }
 
 func (InvoiceService) GetInvoiceList(params request.GetInvoiceList) ([]*model.Invoice, int64, int) {
-	list, total, err := model.NewInvoiceSearch().SetSourceId(params.SourceId).SetSourceType(params.SourceType).Find()
+	list, total, err := model.NewInvoiceSearch().SetSourceId(params.SourceId).SetSourceType(params.SourceType).SetPrincipalIds(params.PrincipalIds).Find()
 	if err != nil {
 		return nil, 0, ecode.DBErr
 	}
diff --git a/service/lru.go b/service/lru.go
index b212997..888aba5 100644
--- a/service/lru.go
+++ b/service/lru.go
@@ -2,39 +2,52 @@
 
 import (
 	"github.com/hashicorp/golang-lru/v2/expirable"
+	"strings"
 	"time"
 )
 
-type userBaseInfo struct {
-	UserId   int
-	NickName string
+type UserBaseInfo struct {
+	UserId     int
+	NickName   string
+	SubUserIds []int
 }
 
-var userCache *expirable.LRU[string, *userBaseInfo]
+var userCache *expirable.LRU[string, *UserBaseInfo]
 
 func init() {
 	//make cache with 5 minutes TTL and 100 max keys
-	userCache = expirable.NewLRU[string, *userBaseInfo](100, nil, time.Minute*5)
+	userCache = expirable.NewLRU[string, *UserBaseInfo](100, nil, time.Minute*1) //todo zq 鏆傛椂鏀规垚 1鍒嗛挓
 }
 
-func GetUserBaseCache(adminUserId string) *userBaseInfo {
-	userCache, ok := userCache.Get(adminUserId)
+func GetUserBaseCache(adminUserId string) *UserBaseInfo {
+	cache, ok := userCache.Get(adminUserId)
 	if !ok {
 		userService := UserService{}
 		userRecord, err := userService.GetUserInfo(adminUserId)
 		if err != nil {
 			return nil
 		}
-		baseInfo := &userBaseInfo{
-			UserId:   userRecord.ID,
-			NickName: userRecord.NickName,
+		var subIds []int
+		if userRecord.SubUserIds != "" {
+			subIds, _, err = userService.UUID2CrmUserId(strings.Split(userRecord.SubUserIds, ","))
+			if err != nil {
+				return nil
+			}
+		}
+
+		subIds = append(subIds, userRecord.ID)
+
+		baseInfo := &UserBaseInfo{
+			UserId:     userRecord.ID,
+			NickName:   userRecord.NickName,
+			SubUserIds: subIds,
 		}
 		SetUserBaseCache(adminUserId, baseInfo)
 		return baseInfo
 	}
-	return userCache
+	return cache
 }
 
-func SetUserBaseCache(adminUserId string, user *userBaseInfo) {
+func SetUserBaseCache(adminUserId string, user *UserBaseInfo) {
 	_ = userCache.Add(adminUserId, user)
 }
diff --git a/service/receipt.go b/service/receipt.go
index 9ec0ba3..b4999cf 100644
--- a/service/receipt.go
+++ b/service/receipt.go
@@ -136,6 +136,7 @@
 		SetSourceType(params.SourceType).
 		SetSourceId(params.SourceId).
 		SetClientId(params.ClientId).
+		SetPrincipalIds(params.PrincipleIds).
 		Find()
 	if err != nil {
 		return nil, 0, ecode.DBErr
diff --git a/service/user.go b/service/user.go
index 3f40330..923ccc2 100644
--- a/service/user.go
+++ b/service/user.go
@@ -90,6 +90,20 @@
 	})
 }
 
-func (userService *UserService) GetUserList() (userList []*model.User, err error) {
-	return model.NewUserSearch(nil).FindAll()
+func (userService *UserService) GetUserList(userIds []int) (userList []*model.User, err error) {
+	return model.NewUserSearch(nil).SetUserIds(userIds).FindAll()
+}
+
+func (userService *UserService) UUID2CrmUserId(uuids []string) (crmUserIds []int, m map[string]int, err error) {
+	idPairs, err := model.NewUserSearch(nil).UUID2CrmUserId(uuids)
+	if err != nil {
+		return
+	}
+	crmUserIds = make([]int, 0, len(idPairs))
+	m = make(map[string]int, len(idPairs))
+	for _, idPair := range idPairs {
+		crmUserIds = append(crmUserIds, idPair.ID)
+		m[idPair.UUID] = idPair.ID
+	}
+	return
 }
diff --git a/source/menu.go b/source/menu.go
index 18ed3aa..08b1403 100644
--- a/source/menu.go
+++ b/source/menu.go
@@ -1,52 +1,53 @@
 package system
 
-import (
-	"aps_crm/model"
-	"aps_crm/pkg/logx"
-	"aps_crm/service"
-	"context"
-	"github.com/pkg/errors"
-	"gorm.io/gorm"
-)
-
-type initMenu struct{}
-
-// auto run
-func init() {
-	service.RegisterInit(initMenuSequence, &initMenu{})
-}
-
-func (i initMenu) InitializerName() string {
-	return model.Menu{}.TableName()
-}
-
-func (i *initMenu) InitializeData(ctx context.Context) (next context.Context, err error) {
-	entities := []*model.Menu{
-		{ID: 1, ParentId: 0, Path: "", Name: "", Title: "瀹㈡埛绠$悊"},
-		{ID: 2, ParentId: 1, Path: "/client", Name: "", Title: "瀹㈡埛绠$悊"},
-
-		{ID: 3, ParentId: 0, Path: "", Name: "", Title: "閿�鍞鐞�"},
-		{ID: 4, ParentId: 3, Path: "/saleChance", Name: "", Title: "閿�鍞満浼�"},
-
-		{ID: 5, ParentId: 0, Path: "", Name: "", Title: "鏈嶅姟绠$悊"},
-		{ID: 6, ParentId: 5, Path: "/serviceContract", Name: "", Title: "鏈嶅姟鍚堝悓"},
-
-		{ID: 7, ParentId: 0, Path: "", Name: "", Title: "鍚庡彴璁剧疆"},
-		{ID: 8, ParentId: 7, Path: "/member", Name: "", Title: "鎴愬憳绠$悊"},
-		{ID: 9, ParentId: 7, Path: "/role", Name: "", Title: "瑙掕壊绠$悊"},
-	}
-	if err = model.NewMenuSearch(nil).CreateBatch(entities); err != nil {
-		return ctx, errors.Wrap(err, i.InitializerName()+"琛ㄦ暟鎹垵濮嬪寲澶辫触!")
-	}
-	next = context.WithValue(ctx, i.InitializerName(), entities)
-	logx.Infof("InitializeData success initName:%v", i.InitializerName())
-	return next, nil
-}
-
-func (i *initMenu) DataInserted(ctx context.Context) bool {
-	_, err := model.NewMenuSearch(nil).SetId(22).First()
-	if errors.Is(err, gorm.ErrRecordNotFound) { // 鍒ゆ柇鏄惁瀛樺湪鏁版嵁
-		return false
-	}
-	return true
-}
+//
+//import (
+//	"aps_crm/model"
+//	"aps_crm/pkg/logx"
+//	"aps_crm/service"
+//	"context"
+//	"github.com/pkg/errors"
+//	"gorm.io/gorm"
+//)
+//
+//type initMenu struct{}
+//
+//// auto run
+//func init() {
+//	service.RegisterInit(initMenuSequence, &initMenu{})
+//}
+//
+//func (i initMenu) InitializerName() string {
+//	return model.Menu{}.TableName()
+//}
+//
+//func (i *initMenu) InitializeData(ctx context.Context) (next context.Context, err error) {
+//	entities := []*model.Menu{
+//		{ID: 1, ParentId: 0, Path: "", Name: "", Title: "瀹㈡埛绠$悊"},
+//		{ID: 2, ParentId: 1, Path: "/client", Name: "", Title: "瀹㈡埛绠$悊"},
+//
+//		{ID: 3, ParentId: 0, Path: "", Name: "", Title: "閿�鍞鐞�"},
+//		{ID: 4, ParentId: 3, Path: "/saleChance", Name: "", Title: "閿�鍞満浼�"},
+//
+//		{ID: 5, ParentId: 0, Path: "", Name: "", Title: "鏈嶅姟绠$悊"},
+//		{ID: 6, ParentId: 5, Path: "/serviceContract", Name: "", Title: "鏈嶅姟鍚堝悓"},
+//
+//		{ID: 7, ParentId: 0, Path: "", Name: "", Title: "鍚庡彴璁剧疆"},
+//		{ID: 8, ParentId: 7, Path: "/member", Name: "", Title: "鎴愬憳绠$悊"},
+//		{ID: 9, ParentId: 7, Path: "/role", Name: "", Title: "瑙掕壊绠$悊"},
+//	}
+//	if err = model.NewMenuSearch(nil).CreateBatch(entities); err != nil {
+//		return ctx, errors.Wrap(err, i.InitializerName()+"琛ㄦ暟鎹垵濮嬪寲澶辫触!")
+//	}
+//	next = context.WithValue(ctx, i.InitializerName(), entities)
+//	logx.Infof("InitializeData success initName:%v", i.InitializerName())
+//	return next, nil
+//}
+//
+//func (i *initMenu) DataInserted(ctx context.Context) bool {
+//	_, err := model.NewMenuSearch(nil).SetId(22).First()
+//	if errors.Is(err, gorm.ErrRecordNotFound) { // 鍒ゆ柇鏄惁瀛樺湪鏁版嵁
+//		return false
+//	}
+//	return true
+//}
diff --git a/source/user.go b/source/user.go
index b8e334e..c3c3db8 100644
--- a/source/user.go
+++ b/source/user.go
@@ -1,68 +1,68 @@
 package system
 
-import (
-	"aps_crm/constvar"
-	"aps_crm/model"
-	"aps_crm/pkg/encrypt"
-	"aps_crm/pkg/logx"
-	"aps_crm/pkg/snowflake"
-	"aps_crm/service"
-	"context"
-	"fmt"
-	"github.com/pkg/errors"
-	"gorm.io/gorm"
-)
-
-const (
-	initMenuSequence = iota + 1
-	initUserSequence
-)
-
-type initUser struct{}
-
-// auto run
-func init() {
-	service.RegisterInit(initUserSequence, &initUser{})
-}
-
-func (i initUser) InitializerName() string {
-	return model.User{}.TableName()
-}
-
-func (i *initUser) InitializeData(ctx context.Context) (next context.Context, err error) {
-	adminPassword := encrypt.BcryptHash("123456")
-	entities := []*model.User{
-		{
-			UUID:     fmt.Sprintf("u%v", snowflake.GenerateId()),
-			Username: "admin",
-			Password: adminPassword,
-			NickName: "admin",
-			UserType: constvar.UserTypeSuper,
-			//ParentId: "basic", // 瓒呯骇绠$悊鍛樿处鎴风殑鐖朵翰涓虹┖瀛楃涓诧紝鎴栬�呰捣涓悕瀛�
-			//Enable:   true,
-		},
-	}
-	if err = model.NewUserSearch(nil).CreateBatch(entities); err != nil {
-		return ctx, errors.Wrap(err, model.User{}.TableName()+"琛ㄦ暟鎹垵濮嬪寲澶辫触!")
-	}
-	next = context.WithValue(ctx, i.InitializerName(), entities)
-
-	menuEntities, ok := ctx.Value(initMenu{}.InitializerName()).([]*model.Menu)
-	if !ok {
-		return next, errors.New("no find menus")
-	}
-
-	if err = model.NewUserSearch(nil).ReplaceMenu(entities[0], menuEntities); err != nil {
-		return next, err
-	}
-	logx.Infof("InitializeData success initName:%v", i.InitializerName())
-	return next, err
-}
-
-func (i *initUser) DataInserted(ctx context.Context) bool {
-	_, err := model.NewUserSearch(nil).SetUserName("admin").First()
-	if errors.Is(err, gorm.ErrRecordNotFound) { // 鍒ゆ柇鏄惁瀛樺湪鏁版嵁
-		return false
-	}
-	return true
-}
+//import (
+//	"aps_crm/constvar"
+//	"aps_crm/model"
+//	"aps_crm/pkg/encrypt"
+//	"aps_crm/pkg/logx"
+//	"aps_crm/pkg/snowflake"
+//	"aps_crm/service"
+//	"context"
+//	"fmt"
+//	"github.com/pkg/errors"
+//	"gorm.io/gorm"
+//)
+//
+//const (
+//	initMenuSequence = iota + 1
+//	initUserSequence
+//)
+//
+//type initUser struct{}
+//
+//// auto run
+//func init() {
+//	service.RegisterInit(initUserSequence, &initUser{})
+//}
+//
+//func (i initUser) InitializerName() string {
+//	return model.User{}.TableName()
+//}
+//
+//func (i *initUser) InitializeData(ctx context.Context) (next context.Context, err error) {
+//	adminPassword := encrypt.BcryptHash("123456")
+//	entities := []*model.User{
+//		{
+//			UUID:     fmt.Sprintf("u%v", snowflake.GenerateId()),
+//			Username: "admin",
+//			Password: adminPassword,
+//			NickName: "admin",
+//			UserType: constvar.UserTypeSuper,
+//			//ParentId: "basic", // 瓒呯骇绠$悊鍛樿处鎴风殑鐖朵翰涓虹┖瀛楃涓诧紝鎴栬�呰捣涓悕瀛�
+//			//Enable:   true,
+//		},
+//	}
+//	if err = model.NewUserSearch(nil).CreateBatch(entities); err != nil {
+//		return ctx, errors.Wrap(err, model.User{}.TableName()+"琛ㄦ暟鎹垵濮嬪寲澶辫触!")
+//	}
+//	next = context.WithValue(ctx, i.InitializerName(), entities)
+//
+//	menuEntities, ok := ctx.Value(initMenu{}.InitializerName()).([]*model.Menu)
+//	if !ok {
+//		return next, errors.New("no find menus")
+//	}
+//
+//	if err = model.NewUserSearch(nil).ReplaceMenu(entities[0], menuEntities); err != nil {
+//		return next, err
+//	}
+//	logx.Infof("InitializeData success initName:%v", i.InitializerName())
+//	return next, err
+//}
+//
+//func (i *initUser) DataInserted(ctx context.Context) bool {
+//	_, err := model.NewUserSearch(nil).SetUserName("admin").First()
+//	if errors.Is(err, gorm.ErrRecordNotFound) { // 鍒ゆ柇鏄惁瀛樺湪鏁版嵁
+//		return false
+//	}
+//	return true
+//}

--
Gitblit v1.8.0