Files
ai-agent/cmd/testdata/agentteam/init.go
T
mlogclub 5d7c10aeab refactor: rename agent widget references to AI agent for consistency
- Updated runtime configuration to use __CS_AI_AGENT_WIDGET_CONFIG__ instead of __CS_AGENT_WIDGET_CONFIG__.
- Changed message types in support host bridge from "cs-agent" to "cs-ai-agent".
- Minified SDK script updated to reflect new AI agent naming conventions.
- Adjusted scrollbar styles in main.scss to use .cs-ai-agent-scrollbar instead of .cs-agent-scrollbar.
2026-05-30 21:19:36 +08:00

220 lines
5.3 KiB
Go

package agentteam
import (
"cs-ai-agent/internal/models"
"cs-ai-agent/internal/pkg/constants"
"cs-ai-agent/internal/pkg/enums"
"cs-ai-agent/internal/repositories"
"fmt"
"time"
"github.com/mlogclub/simple/sqls"
"golang.org/x/crypto/bcrypt"
)
type InitResult struct {
TeamCreated bool
UsersCreated int
ProfilesCreated int
UpdatesApplied int
}
// Init 初始化客服组和客服用户
// 创建:
// 1. 客服组,组长为管理员用户
// 2. 客服A 用户
// 3. 客服B 用户
// 4. 为客服A和客服B创建客服档案,关联到该客服组
func Init() (*InitResult, error) {
result := &InitResult{}
// 获取管理员用户
adminUser := repositories.UserRepository.Take(
sqls.DB(),
"username = ?",
constants.BootstrapAdminUsername,
)
if adminUser == nil {
return result, fmt.Errorf("bootstrap admin user not found")
}
err := sqls.WithTransaction(func(ctx *sqls.TxContext) error {
return initTeamAndUsers(ctx, adminUser, result)
})
if err != nil {
return result, fmt.Errorf("init team and users failed: %w", err)
}
return result, nil
}
func initTeamAndUsers(ctx *sqls.TxContext, leaderUser *models.User, result *InitResult) error {
teamName := "默认客服组"
now := time.Now()
team := repositories.AgentTeamRepository.Take(ctx.Tx, "name = ?", teamName)
if team != nil {
if err := ctx.Tx.Model(team).Updates(map[string]any{
"leader_user_id": leaderUser.ID,
"update_user_id": constants.SystemAuditUserID,
"update_user_name": constants.SystemAuditUserName,
"updated_at": now,
}).Error; err != nil {
return err
}
} else {
team = &models.AgentTeam{
Name: teamName,
LeaderUserID: leaderUser.ID,
Status: enums.StatusOk,
Description: "Local testdata seed - default service team",
AuditFields: models.AuditFields{
CreatedAt: now,
CreateUserID: constants.SystemAuditUserID,
CreateUserName: constants.SystemAuditUserName,
UpdatedAt: now,
UpdateUserID: constants.SystemAuditUserID,
UpdateUserName: constants.SystemAuditUserName,
},
}
if err := ctx.Tx.Create(team).Error; err != nil {
return err
}
result.TeamCreated = true
}
agentUsers := []struct {
username string
nickname string
code string
}{
{
username: leaderUser.Username,
nickname: "客服组长",
code: "AGENT_LEADER_A",
},
{
username: "agent_a",
nickname: "客服A",
code: "AGENT_A",
},
{
username: "agent_b",
nickname: "客服B",
code: "AGENT_B",
},
}
for _, agentUser := range agentUsers {
userID, userCreated, err := createOrGetUser(ctx, agentUser.username, agentUser.nickname)
if err != nil {
return err
}
if userCreated {
result.UsersCreated++
}
// 创建或更新客服档案
profileCreated, err := createOrUpdateProfile(ctx, userID, team.ID, agentUser.code, agentUser.nickname)
if err != nil {
return err
}
if profileCreated {
result.ProfilesCreated++
} else {
result.UpdatesApplied++
}
}
return nil
}
func createOrGetUser(ctx *sqls.TxContext, username, nickname string) (int64, bool, error) {
user := repositories.UserRepository.Take(
ctx.Tx,
"username = ?",
username,
)
if user != nil {
return user.ID, false, nil
}
// 创建新用户
hashedPassword, err := bcrypt.GenerateFromPassword([]byte(constants.BootstrapAdminPassword), bcrypt.DefaultCost)
if err != nil {
return 0, false, err
}
now := time.Now()
newUser := &models.User{
Username: username,
Nickname: nickname,
Password: string(hashedPassword),
Status: enums.StatusOk,
Remark: "Local testdata seed",
AuditFields: models.AuditFields{
CreatedAt: now,
CreateUserID: constants.SystemAuditUserID,
CreateUserName: constants.SystemAuditUserName,
UpdatedAt: now,
UpdateUserID: constants.SystemAuditUserID,
UpdateUserName: constants.SystemAuditUserName,
},
}
if err := ctx.Tx.Create(newUser).Error; err != nil {
return 0, false, err
}
return newUser.ID, true, nil
}
func createOrUpdateProfile(ctx *sqls.TxContext, userID, teamID int64, agentCode, displayName string) (bool, error) {
profile := repositories.AgentProfileRepository.Take(
ctx.Tx,
"user_id = ?",
userID,
)
now := time.Now()
if profile != nil {
// 档案已存在,更新关键信息
return false, ctx.Tx.Model(profile).Updates(map[string]any{
"team_id": teamID,
"agent_code": agentCode,
"display_name": displayName,
"status": enums.StatusOk,
"update_user_id": constants.SystemAuditUserID,
"update_user_name": constants.SystemAuditUserName,
"updated_at": now,
}).Error
}
// 创建新档案
newProfile := &models.AgentProfile{
UserID: userID,
TeamID: teamID,
AgentCode: agentCode,
DisplayName: displayName,
Avatar: "",
ServiceStatus: enums.ServiceStatusIdle,
MaxConcurrentCount: 5,
PriorityLevel: 10,
AutoAssignEnabled: true,
Status: enums.StatusOk,
Remark: "Local testdata seed",
AuditFields: models.AuditFields{
CreatedAt: now,
CreateUserID: constants.SystemAuditUserID,
CreateUserName: constants.SystemAuditUserName,
UpdatedAt: now,
UpdateUserID: constants.SystemAuditUserID,
UpdateUserName: constants.SystemAuditUserName,
},
}
return true, ctx.Tx.Create(newProfile).Error
}