feat(distribution): 分销站点增加用户数量统计与用户信息展示模块

- 数据模型与迁移: 新增 000082 迁移在 users 表追加 distribution_site_id 并建索引,用户首次在分销站点注册/短信登录时自动绑定站点归属
- 分销管理接口: 新增 GET /admin/distribution/users 接口,聚合本站注册用户与下单客户,返回完整11位手机号、累计消费金额、订单数及来源标签
- 统计与大盘扩展: GET /admin/distribution/sites/:id/analytics 补全今日注册、累计用户、成交客户指标,主站分销商列表追加用户体量展示
- 分销后台前端: 新增「客户与用户」页面 (Users.tsx) 支持一键复制手机号与订单穿透,大盘 (Dashboard.tsx) 增加用户规模核心卡片
- 自动化测试与门禁: 新增 TestListDistributionUsersAndAnalytics 单元测试,通过全量 Go 后端集成测试及前后端构建检查
This commit is contained in:
yml2213
2026-10-10 14:58:33 +08:00
parent 6d34f86765
commit 4ea08e355b
17 changed files with 956 additions and 60 deletions
+4 -4
View File
@@ -193,7 +193,7 @@ func (s *Service) SendSMSCode(ctx context.Context, phone string, captchaID strin
return nil
}
func (s *Service) LoginWithSMS(ctx context.Context, phone string, code string, trackCode ...string) (LoginResult, error) {
func (s *Service) LoginWithSMS(ctx context.Context, phone string, code string, trackCode string, siteCode ...string) (LoginResult, error) {
if s.redis == nil || s.users == nil {
return LoginResult{}, ErrDependencyUnavailable
}
@@ -209,7 +209,7 @@ func (s *Service) LoginWithSMS(ctx context.Context, phone string, code string, t
return LoginResult{}, err
}
user, err := s.users.FindOrCreateByPhone(ctx, phone, trackCode...)
user, err := s.users.FindOrCreateByPhone(ctx, phone, trackCode, siteCode...)
if err != nil {
return LoginResult{}, err
}
@@ -385,7 +385,7 @@ func (s *Service) ResetPassword(ctx context.Context, phone, code, newPassword st
return nil
}
func (s *Service) RegisterWithPassword(ctx context.Context, phone, code, password string, trackCode ...string) (LoginResult, error) {
func (s *Service) RegisterWithPassword(ctx context.Context, phone, code, password string, trackCode string, siteCode ...string) (LoginResult, error) {
if s.redis == nil || s.users == nil {
return LoginResult{}, ErrDependencyUnavailable
}
@@ -418,7 +418,7 @@ func (s *Service) RegisterWithPassword(ctx context.Context, phone, code, passwor
return LoginResult{}, err
}
user, err := s.users.RegisterWithPassword(ctx, phone, string(hash), trackCode...)
user, err := s.users.RegisterWithPassword(ctx, phone, string(hash), trackCode, siteCode...)
if err != nil {
// 并发场景下仍可能因唯一索引冲突,统一按"已注册"处理
return LoginResult{}, ErrUserAlreadyExists