Files
ai-agent/cmd/testdata/agentteam/init.go
T
mlogclub b743639731 feat: add language support and tests for English and Chinese seed data
- Introduced a new package `seedlang` to handle language parsing and constants for English and Chinese.
- Updated `Init` functions across various modules (kb, quickreply, skill, tag) to accept a language parameter.
- Implemented English seed data for FAQs, quick replies, skills, and tags, ensuring no Chinese text is present in English data.
- Added tests to verify that English seed data does not contain Chinese characters.
- Removed outdated README file from the kb test data directory.
- Created new test files for channel and kb to validate the absence of Chinese text in English seed data.
2026-06-01 12:03:57 +08:00

252 lines
6.1 KiB
Go

package agentteam
import (
"agent-desk/cmd/testdata/seedlang"
"agent-desk/internal/models"
"agent-desk/internal/pkg/constants"
"agent-desk/internal/pkg/enums"
"agent-desk/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(lang seedlang.Language) (*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, lang)
})
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, lang seedlang.Language) error {
teamName := localizedTeamName(lang)
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 := localizedAgentUsers(lang, leaderUser.Username)
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
}
type agentUserSeed struct {
username string
nickname string
code string
}
func localizedTeamName(lang seedlang.Language) string {
if lang == seedlang.English {
return "Default Support Team"
}
return "默认客服组"
}
func localizedAgentUsers(lang seedlang.Language, leaderUsername string) []agentUserSeed {
if lang == seedlang.English {
return []agentUserSeed{
{
username: leaderUsername,
nickname: "Support Lead",
code: "AGENT_LEADER_A",
},
{
username: "agent_a",
nickname: "Agent A",
code: "AGENT_A",
},
{
username: "agent_b",
nickname: "Agent B",
code: "AGENT_B",
},
}
}
return []agentUserSeed{
{
username: leaderUsername,
nickname: "客服组长",
code: "AGENT_LEADER_A",
},
{
username: "agent_a",
nickname: "客服A",
code: "AGENT_A",
},
{
username: "agent_b",
nickname: "客服B",
code: "AGENT_B",
},
}
}
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
}