合并分支 'test' 到 'master'
Test 查看合并请求 !2
正在显示
13 个修改的文件
包含
178 行增加
和
58 行删除
@@ -21,6 +21,13 @@ func main() { | @@ -21,6 +21,13 @@ func main() { | ||
21 | w, _ := logrus.NewKafkaWriter(constant.KAFKA_HOST, constant.TOPIC_LOG_STASH, false) | 21 | w, _ := logrus.NewKafkaWriter(constant.KAFKA_HOST, constant.TOPIC_LOG_STASH, false) |
22 | log.Logger.AddHook(w) | 22 | log.Logger.AddHook(w) |
23 | } | 23 | } |
24 | + bw := log.NewBeegoLogWriter(log.LoggerConfig{ | ||
25 | + Filename: constant.LOG_FILE, | ||
26 | + Level: 7, | ||
27 | + MaxSize: 1024 * 1024 * 2, | ||
28 | + }) | ||
29 | + log.Logger.AddHook(bw) | ||
30 | + | ||
24 | log.Logger.Info("server start!") | 31 | log.Logger.Info("server start!") |
25 | web.Run() | 32 | web.Run() |
26 | } | 33 | } |
@@ -228,6 +228,7 @@ func (roleService *RoleService) GetRoleRelatedUsers(getRoleRelatedUsersQuery *qu | @@ -228,6 +228,7 @@ func (roleService *RoleService) GetRoleRelatedUsers(getRoleRelatedUsersQuery *qu | ||
228 | queryOptions["organizationId"] = getRoleRelatedUsersQuery.OrgId | 228 | queryOptions["organizationId"] = getRoleRelatedUsersQuery.OrgId |
229 | } | 229 | } |
230 | queryOptions["userType"] = domain.UserTypeEmployee | 230 | queryOptions["userType"] = domain.UserTypeEmployee |
231 | + queryOptions["limit"] = domain.MaxQueryRow | ||
231 | _, users, err := userRepository.Find(queryOptions) | 232 | _, users, err := userRepository.Find(queryOptions) |
232 | if err != nil { | 233 | if err != nil { |
233 | return nil, application.ThrowError(application.INTERNAL_SERVER_ERROR, err.Error()) | 234 | return nil, application.ThrowError(application.INTERNAL_SERVER_ERROR, err.Error()) |
@@ -81,5 +81,10 @@ func (dto *UserDto) LoadDto(user *domain.User, company *domain.Company) error { | @@ -81,5 +81,10 @@ func (dto *UserDto) LoadDto(user *domain.User, company *domain.Company) error { | ||
81 | dto.Organization = user.Organization | 81 | dto.Organization = user.Organization |
82 | dto.Department = user.Department | 82 | dto.Department = user.Department |
83 | dto.CreatedAt = user.CreatedAt | 83 | dto.CreatedAt = user.CreatedAt |
84 | + if user.UserType == domain.UserTypeCooperation { | ||
85 | + dto.Department = &domain.Department{ | ||
86 | + DepartmentName: "共创用户", | ||
87 | + } | ||
88 | + } | ||
84 | return nil | 89 | return nil |
85 | } | 90 | } |
@@ -18,35 +18,35 @@ type UserService struct { | @@ -18,35 +18,35 @@ type UserService struct { | ||
18 | } | 18 | } |
19 | 19 | ||
20 | // 批量添加用户 | 20 | // 批量添加用户 |
21 | -func (userService *UserService) BatchAdd(batchAddCommand *command.BatchAddCommand) (interface{}, error) { | ||
22 | - if err := batchAddCommand.ValidateCommand(); err != nil { | ||
23 | - return nil, application.ThrowError(application.ARG_ERROR, err.Error()) | ||
24 | - } | ||
25 | - transactionContext, err := factory.CreateTransactionContext(nil) | ||
26 | - if err != nil { | ||
27 | - return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error()) | ||
28 | - } | ||
29 | - if err := transactionContext.StartTransaction(); err != nil { | ||
30 | - return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error()) | ||
31 | - } | ||
32 | - defer func() { | ||
33 | - transactionContext.RollbackTransaction() | ||
34 | - }() | ||
35 | - | ||
36 | - batchAddUserService, _ := factory.CreateBatchAddUserService(map[string]interface{}{ | ||
37 | - "transactionContext": transactionContext, | ||
38 | - }) | ||
39 | - if err = batchAddUserService.BatchAddUser(batchAddCommand.OperateInfo, batchAddCommand.Users, batchAddCommand.Password); err != nil { | ||
40 | - return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error()) | ||
41 | - } | ||
42 | - | ||
43 | - if err := transactionContext.CommitTransaction(); err != nil { | ||
44 | - return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error()) | ||
45 | - } | ||
46 | - return nil, nil | ||
47 | -} | ||
48 | - | ||
49 | -// 批量添加用户 | 21 | +//func (userService *UserService) BatchAdd(batchAddCommand *command.BatchAddCommand) (interface{}, error) { |
22 | +// if err := batchAddCommand.ValidateCommand(); err != nil { | ||
23 | +// return nil, application.ThrowError(application.ARG_ERROR, err.Error()) | ||
24 | +// } | ||
25 | +// transactionContext, err := factory.CreateTransactionContext(nil) | ||
26 | +// if err != nil { | ||
27 | +// return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error()) | ||
28 | +// } | ||
29 | +// if err := transactionContext.StartTransaction(); err != nil { | ||
30 | +// return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error()) | ||
31 | +// } | ||
32 | +// defer func() { | ||
33 | +// transactionContext.RollbackTransaction() | ||
34 | +// }() | ||
35 | +// | ||
36 | +// batchAddUserService, _ := factory.CreateBatchAddUserService(map[string]interface{}{ | ||
37 | +// "transactionContext": transactionContext, | ||
38 | +// }) | ||
39 | +// if err = batchAddUserService.BatchAddUser(batchAddCommand.OperateInfo, batchAddCommand.Users, batchAddCommand.Password); err != nil { | ||
40 | +// return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error()) | ||
41 | +// } | ||
42 | +// | ||
43 | +// if err := transactionContext.CommitTransaction(); err != nil { | ||
44 | +// return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error()) | ||
45 | +// } | ||
46 | +// return nil, nil | ||
47 | +//} | ||
48 | + | ||
49 | +// BatchAdd2 批量添加用户 | ||
50 | func (userService *UserService) BatchAdd2(batchAddCommand *command.BatchAdd2Command) (interface{}, error) { | 50 | func (userService *UserService) BatchAdd2(batchAddCommand *command.BatchAdd2Command) (interface{}, error) { |
51 | if err := batchAddCommand.ValidateCommand(); err != nil { | 51 | if err := batchAddCommand.ValidateCommand(); err != nil { |
52 | return nil, application.ThrowError(application.ARG_ERROR, err.Error()) | 52 | return nil, application.ThrowError(application.ARG_ERROR, err.Error()) |
@@ -12,6 +12,7 @@ var SERVICE_ENV = "dev" | @@ -12,6 +12,7 @@ var SERVICE_ENV = "dev" | ||
12 | var HTTP_PORT int = 8081 | 12 | var HTTP_PORT int = 8081 |
13 | var CACHE_PREFIX = "allied-creation-user-dev" | 13 | var CACHE_PREFIX = "allied-creation-user-dev" |
14 | var LOG_LEVEL = "debug" | 14 | var LOG_LEVEL = "debug" |
15 | +var LOG_FILE = "app.log" | ||
15 | 16 | ||
16 | var CUSTOMER_ACCOUNT = []int64{3129687560814592, 3129687690100739, 3492238958608384} | 17 | var CUSTOMER_ACCOUNT = []int64{3129687560814592, 3129687690100739, 3492238958608384} |
17 | 18 |
@@ -13,7 +13,7 @@ type PgBatchAddUserService struct { | @@ -13,7 +13,7 @@ type PgBatchAddUserService struct { | ||
13 | transactionContext *pgTransaction.TransactionContext | 13 | transactionContext *pgTransaction.TransactionContext |
14 | } | 14 | } |
15 | 15 | ||
16 | -// CreateUser 批量添加用户服务 | 16 | +// BatchAddUser 批量添加用户服务 |
17 | // | 17 | // |
18 | // optUser 操作用户 | 18 | // optUser 操作用户 |
19 | // users 待添加用户列表数据 | 19 | // users 待添加用户列表数据 |
@@ -107,7 +107,6 @@ func (ptr *PgBatchAddUserService) BatchAddUser2(optUser *domain.OperateInfo, use | @@ -107,7 +107,6 @@ func (ptr *PgBatchAddUserService) BatchAddUser2(optUser *domain.OperateInfo, use | ||
107 | user.FailReason = err.Error() | 107 | user.FailReason = err.Error() |
108 | failRows = append(failRows, user) | 108 | failRows = append(failRows, user) |
109 | continue | 109 | continue |
110 | - //return err | ||
111 | } | 110 | } |
112 | var org, dep *domain.Org | 111 | var org, dep *domain.Org |
113 | var ok bool | 112 | var ok bool |
@@ -115,26 +114,22 @@ func (ptr *PgBatchAddUserService) BatchAddUser2(optUser *domain.OperateInfo, use | @@ -115,26 +114,22 @@ func (ptr *PgBatchAddUserService) BatchAddUser2(optUser *domain.OperateInfo, use | ||
115 | user.FailReason = "导入的组织机构不存在:" + user.Org | 114 | user.FailReason = "导入的组织机构不存在:" + user.Org |
116 | failRows = append(failRows, user) | 115 | failRows = append(failRows, user) |
117 | continue | 116 | continue |
118 | - //return fmt.Errorf("导入的组织机构不存在:" + user.Org) | ||
119 | } | 117 | } |
120 | if dep, ok = mapOrg[user.Department]; !ok && user.UserType != domain.UserTypeCooperation { | 118 | if dep, ok = mapOrg[user.Department]; !ok && user.UserType != domain.UserTypeCooperation { |
121 | user.FailReason = "导入的所属部门不存在:" + user.Department | 119 | user.FailReason = "导入的所属部门不存在:" + user.Department |
122 | failRows = append(failRows, user) | 120 | failRows = append(failRows, user) |
123 | continue | 121 | continue |
124 | - //return fmt.Errorf("导入的所属部门不存在:" + user.Department) | ||
125 | } | 122 | } |
126 | newUser := &domain.User{ | 123 | newUser := &domain.User{ |
127 | CompanyId: user.CompanyId, | 124 | CompanyId: user.CompanyId, |
128 | UserType: user.UserType, | 125 | UserType: user.UserType, |
129 | UserCode: user.UserCode, | 126 | UserCode: user.UserCode, |
130 | OrganizationId: org.OrgId, | 127 | OrganizationId: org.OrgId, |
131 | - //DepartmentId: dep.OrgId, | ||
132 | - UserOrg: []*domain.Org{}, | ||
133 | - UserRole: []*domain.Role{}, | ||
134 | - FavoriteMenus: []string{}, | 128 | + UserOrg: []*domain.Org{}, |
129 | + UserRole: []*domain.Role{}, | ||
130 | + FavoriteMenus: []string{}, | ||
135 | CooperationInfo: &domain.CooperationInfo{ | 131 | CooperationInfo: &domain.CooperationInfo{ |
136 | CooperationCompany: user.CooperationCompany, | 132 | CooperationCompany: user.CooperationCompany, |
137 | - //CooperationDeadline: user.CooperationDeadline, | ||
138 | }, | 133 | }, |
139 | UserInfo: &domain.UserInfo{ | 134 | UserInfo: &domain.UserInfo{ |
140 | UserName: user.UserName, | 135 | UserName: user.UserName, |
@@ -147,7 +142,6 @@ func (ptr *PgBatchAddUserService) BatchAddUser2(optUser *domain.OperateInfo, use | @@ -147,7 +142,6 @@ func (ptr *PgBatchAddUserService) BatchAddUser2(optUser *domain.OperateInfo, use | ||
147 | Phone: user.Phone, | 142 | Phone: user.Phone, |
148 | UserName: user.UserName, | 143 | UserName: user.UserName, |
149 | OrgName: org.OrgName, | 144 | OrgName: org.OrgName, |
150 | - //DepName: dep.OrgName, | ||
151 | }, | 145 | }, |
152 | CreatedAt: time.Now(), | 146 | CreatedAt: time.Now(), |
153 | UpdatedAt: time.Now(), | 147 | UpdatedAt: time.Now(), |
@@ -164,11 +158,13 @@ func (ptr *PgBatchAddUserService) BatchAddUser2(optUser *domain.OperateInfo, use | @@ -164,11 +158,13 @@ func (ptr *PgBatchAddUserService) BatchAddUser2(optUser *domain.OperateInfo, use | ||
164 | continue | 158 | continue |
165 | } | 159 | } |
166 | } | 160 | } |
161 | + if user.UserType == domain.UserTypeEmployee { | ||
162 | + newUser.UserOrg = append(newUser.UserOrg, org.CloneSample()) | ||
163 | + } | ||
167 | if newUser, err = createUserService.CreateUser(nil, newUser, password); err != nil { | 164 | if newUser, err = createUserService.CreateUser(nil, newUser, password); err != nil { |
168 | user.FailReason = err.Error() | 165 | user.FailReason = err.Error() |
169 | failRows = append(failRows, user) | 166 | failRows = append(failRows, user) |
170 | continue | 167 | continue |
171 | - //return fmt.Errorf("%v %v", user.UserName, err.Error()) | ||
172 | } | 168 | } |
173 | } | 169 | } |
174 | return failRows, nil | 170 | return failRows, nil |
@@ -181,7 +177,7 @@ func (ptr *PgBatchAddUserService) preCheck(user *domain.User) error { | @@ -181,7 +177,7 @@ func (ptr *PgBatchAddUserService) preCheck(user *domain.User) error { | ||
181 | if len(user.UserInfo.UserName) == 0 { | 177 | if len(user.UserInfo.UserName) == 0 { |
182 | return fmt.Errorf("导入的用户姓名为空值") | 178 | return fmt.Errorf("导入的用户姓名为空值") |
183 | } | 179 | } |
184 | - if len(user.UserInfo.Phone) == 0 { | 180 | + if len(user.UserInfo.Phone) == 0 || len(user.UserInfo.Phone) != 11 { |
185 | return fmt.Errorf("导入的手机号不是有效手机号") | 181 | return fmt.Errorf("导入的手机号不是有效手机号") |
186 | } | 182 | } |
187 | if user.OrganizationId == 0 { | 183 | if user.OrganizationId == 0 { |
@@ -203,15 +199,9 @@ func (ptr *PgBatchAddUserService) preCheck2(user *domain.BatchAddUserItem) error | @@ -203,15 +199,9 @@ func (ptr *PgBatchAddUserService) preCheck2(user *domain.BatchAddUserItem) error | ||
203 | if len(user.UserName) == 0 { | 199 | if len(user.UserName) == 0 { |
204 | return fmt.Errorf("导入的用户姓名为空值") | 200 | return fmt.Errorf("导入的用户姓名为空值") |
205 | } | 201 | } |
206 | - if len(user.Phone) == 0 { | 202 | + if len(user.Phone) == 0 || len(user.Phone) != 11 { |
207 | return fmt.Errorf("导入的手机号不是有效手机号") | 203 | return fmt.Errorf("导入的手机号不是有效手机号") |
208 | } | 204 | } |
209 | - //if len(user.Org) == 0 { | ||
210 | - // return fmt.Errorf("导入的组织机构不存在") | ||
211 | - //} | ||
212 | - //if len(user.Department) == 0 && user.UserType == domain.UserTypeEmployee { | ||
213 | - // return fmt.Errorf("导入的所属部门不存在") | ||
214 | - //} | ||
215 | return nil | 205 | return nil |
216 | } | 206 | } |
217 | 207 |
@@ -3,6 +3,7 @@ package pg | @@ -3,6 +3,7 @@ package pg | ||
3 | import ( | 3 | import ( |
4 | "context" | 4 | "context" |
5 | "fmt" | 5 | "fmt" |
6 | + "github.com/beego/beego/v2/core/logs" | ||
6 | "gitlab.fjmaimaimai.com/allied-creation/allied-creation-user/pkg/infrastructure/pg/models" | 7 | "gitlab.fjmaimaimai.com/allied-creation/allied-creation-user/pkg/infrastructure/pg/models" |
7 | "log" | 8 | "log" |
8 | "reflect" | 9 | "reflect" |
@@ -63,6 +64,7 @@ func (hook SqlGeneratePrintHook) AfterQuery(c context.Context, q *pg.QueryEvent) | @@ -63,6 +64,7 @@ func (hook SqlGeneratePrintHook) AfterQuery(c context.Context, q *pg.QueryEvent) | ||
63 | } | 64 | } |
64 | //log.Logger.Debug(string(sqlStr)) | 65 | //log.Logger.Debug(string(sqlStr)) |
65 | log.Println(string(sqlStr)) | 66 | log.Println(string(sqlStr)) |
67 | + logs.Debug(string(sqlStr)) | ||
66 | return nil | 68 | return nil |
67 | } | 69 | } |
68 | 70 |
pkg/log/logrus_hook.go
0 → 100644
1 | +package log | ||
2 | + | ||
3 | +import ( | ||
4 | + "encoding/json" | ||
5 | + "errors" | ||
6 | + "fmt" | ||
7 | + "github.com/beego/beego/v2/core/logs" | ||
8 | + "io" | ||
9 | + "sync/atomic" | ||
10 | +) | ||
11 | + | ||
12 | +var errOutOfMaxSize = errors.New("msg size is out of limit ") | ||
13 | + | ||
14 | +type BaseHook struct { | ||
15 | + syncWrite bool | ||
16 | + msgChan chan []byte | ||
17 | + maxSize int32 | ||
18 | + currentSize int32 | ||
19 | + closeChan chan struct{} | ||
20 | + w io.Writer | ||
21 | +} | ||
22 | + | ||
23 | +func (b *BaseHook) Write(p []byte) (n int, err error) { | ||
24 | + if b.syncWrite { | ||
25 | + return b.w.Write(p) | ||
26 | + } | ||
27 | + if b.currentSize >= b.maxSize { | ||
28 | + fmt.Println(errOutOfMaxSize.Error(), b.currentSize) | ||
29 | + return 0, errOutOfMaxSize | ||
30 | + } | ||
31 | + b.msgChan <- p | ||
32 | + atomic.AddInt32(&b.currentSize, 1) | ||
33 | + | ||
34 | + return len(p), nil | ||
35 | +} | ||
36 | + | ||
37 | +// NewBaseHook | ||
38 | +// syncWriteFlag 同步写标识 true:同步写 false:异步写 | ||
39 | +func NewBaseHook(syncWriteFlag bool, internalIo io.WriteCloser) (*BaseHook, error) { | ||
40 | + writer := &BaseHook{ | ||
41 | + syncWrite: syncWriteFlag, | ||
42 | + maxSize: 10000, | ||
43 | + msgChan: make(chan []byte, 10000), | ||
44 | + closeChan: make(chan struct{}), | ||
45 | + w: internalIo, | ||
46 | + } | ||
47 | + go writer.ConsumeMsg() | ||
48 | + return writer, nil | ||
49 | +} | ||
50 | + | ||
51 | +func (b *BaseHook) ConsumeMsg() { | ||
52 | + for { | ||
53 | + select { | ||
54 | + case <-b.closeChan: | ||
55 | + return | ||
56 | + case m, ok := <-b.msgChan: | ||
57 | + if ok { | ||
58 | + atomic.AddInt32(&b.currentSize, -1) | ||
59 | + if _, err := b.w.Write(m); err != nil { | ||
60 | + fmt.Println(err) | ||
61 | + } | ||
62 | + } | ||
63 | + } | ||
64 | + } | ||
65 | +} | ||
66 | + | ||
67 | +func (b *BaseHook) Close() { | ||
68 | + close(b.msgChan) | ||
69 | + b.closeChan <- struct{}{} | ||
70 | + //b.wc.Close() | ||
71 | +} | ||
72 | + | ||
73 | +type LoggerConfig struct { | ||
74 | + Level int `json:"level,omitempty"` | ||
75 | + Filename string `json:"filename,omitempty"` | ||
76 | + MaxSize int `json:"maxsize,omitempty"` | ||
77 | + //MaxBackups int `json:"max_backups,omitempty"` | ||
78 | + //MaxAge int `json:"max_age,omitempty"` | ||
79 | + //Compress bool `json:"compress,omitempty"` | ||
80 | +} | ||
81 | + | ||
82 | +type internalLog struct { | ||
83 | + *logs.BeeLogger | ||
84 | +} | ||
85 | + | ||
86 | +func NewBeegoLogWriter(conf LoggerConfig) io.Writer { | ||
87 | + logger := logs.GetBeeLogger() | ||
88 | + logger.SetLevel(conf.Level) | ||
89 | + logger.EnableFuncCallDepth(true) | ||
90 | + logger.SetLogFuncCallDepth(2) | ||
91 | + confByte, _ := json.Marshal(conf) | ||
92 | + err := logger.SetLogger(logs.AdapterFile, string(confByte)) | ||
93 | + if err != nil { | ||
94 | + fmt.Println(err.Error()) | ||
95 | + } | ||
96 | + return &internalLog{logger} | ||
97 | +} | ||
98 | + | ||
99 | +func (l *internalLog) Write(p []byte) (n int, err error) { | ||
100 | + l.Debug(string(p)) | ||
101 | + return len(p), nil | ||
102 | +} |
@@ -84,14 +84,14 @@ func (controller *UserController) GetUserProfile() { | @@ -84,14 +84,14 @@ func (controller *UserController) GetUserProfile() { | ||
84 | controller.Response(data, err) | 84 | controller.Response(data, err) |
85 | } | 85 | } |
86 | 86 | ||
87 | -func (controller *UserController) BatchAdd() { | ||
88 | - userService := service.NewUserService(nil) | ||
89 | - batchAddCommand := &command.BatchAddCommand{} | ||
90 | - Must(controller.Unmarshal(batchAddCommand)) | ||
91 | - batchAddCommand.OperateInfo = ParseOperateInfo(controller.BaseController) | ||
92 | - data, err := userService.BatchAdd(batchAddCommand) | ||
93 | - controller.Response(data, err) | ||
94 | -} | 87 | +//func (controller *UserController) BatchAdd() { |
88 | +// userService := service.NewUserService(nil) | ||
89 | +// batchAddCommand := &command.BatchAddCommand{} | ||
90 | +// Must(controller.Unmarshal(batchAddCommand)) | ||
91 | +// batchAddCommand.OperateInfo = ParseOperateInfo(controller.BaseController) | ||
92 | +// data, err := userService.BatchAdd(batchAddCommand) | ||
93 | +// controller.Response(data, err) | ||
94 | +//} | ||
95 | 95 | ||
96 | func (controller *UserController) BatchAdd2() { | 96 | func (controller *UserController) BatchAdd2() { |
97 | userService := service.NewUserService(nil) | 97 | userService := service.NewUserService(nil) |
pkg/port/beego/routers/logger_router.go
0 → 100644
@@ -13,7 +13,7 @@ func init() { | @@ -13,7 +13,7 @@ func init() { | ||
13 | web.Router("/user/search", &controllers.UserController{}, "Post:SearchUser") | 13 | web.Router("/user/search", &controllers.UserController{}, "Post:SearchUser") |
14 | web.Router("/user/:userId/access-menus", &controllers.UserController{}, "Get:GetUserAccessMenus") | 14 | web.Router("/user/:userId/access-menus", &controllers.UserController{}, "Get:GetUserAccessMenus") |
15 | web.Router("/user/:userId/profile", &controllers.UserController{}, "Get:GetUserProfile") | 15 | web.Router("/user/:userId/profile", &controllers.UserController{}, "Get:GetUserProfile") |
16 | - web.Router("/user/batch-add", &controllers.UserController{}, "Post:BatchAdd") | 16 | + //web.Router("/user/batch-add", &controllers.UserController{}, "Post:BatchAdd") |
17 | web.Router("/user/batch-add2", &controllers.UserController{}, "Post:BatchAdd2") | 17 | web.Router("/user/batch-add2", &controllers.UserController{}, "Post:BatchAdd2") |
18 | web.Router("/user/batch-enable", &controllers.UserController{}, "Post:BatchEnable") | 18 | web.Router("/user/batch-enable", &controllers.UserController{}, "Post:BatchEnable") |
19 | web.Router("/user/batch-reset-password", &controllers.UserController{}, "Post:BatchResetPassword") | 19 | web.Router("/user/batch-reset-password", &controllers.UserController{}, "Post:BatchResetPassword") |
-
请 注册 或 登录 后发表评论