feat: introduce a new Config page for managing site settings and proxy configurations, and add a Team Registration page with backend API support.

This commit is contained in:
2026-02-01 07:33:35 +08:00
parent 0c5beddebe
commit 28bdc9d509
3 changed files with 295 additions and 52 deletions

View File

@@ -44,6 +44,10 @@ type TeamRegState struct {
cmd *exec.Cmd
cancel context.CancelFunc
stdin io.WriteCloser
// 自动导入与退出控制
autoImporting bool
autoImported bool
exitSignaled bool
// 403 错误检测
error403Count int // 403 错误计数
error403Start time.Time // 计数开始时间
@@ -104,6 +108,9 @@ func HandleTeamRegStart(w http.ResponseWriter, r *http.Request) {
teamRegState.Logs = make([]string, 0)
teamRegState.OutputFile = ""
teamRegState.Imported = 0
teamRegState.autoImporting = false
teamRegState.autoImported = false
teamRegState.exitSignaled = false
teamRegState.error403Count = 0
teamRegState.error403Start = time.Now()
teamRegState.mu.Unlock()
@@ -368,42 +375,25 @@ func runTeamRegProcess(config TeamRegConfig) {
addTeamRegLog("[系统] 进程正常完成")
}
// 查找输出文件
outputFile := findLatestOutputFile(workDir)
if outputFile != "" {
teamRegState.mu.Lock()
teamRegState.OutputFile = outputFile
teamRegState.mu.Unlock()
addTeamRegLog(fmt.Sprintf("[系统] 输出文件: %s", filepath.Base(outputFile)))
// 查找输出文件
outputFile := findLatestOutputFile(workDir)
if outputFile != "" {
teamRegState.mu.Lock()
teamRegState.OutputFile = outputFile
teamRegState.mu.Unlock()
addTeamRegLog(fmt.Sprintf("[系统] 输出文件: %s", filepath.Base(outputFile)))
// 自动导入
if config.AutoImport {
addTeamRegLog("[系统] 自动导入账号到数据库...")
count, err := importAccountsFromJSON(outputFile)
if err != nil {
addTeamRegLog(fmt.Sprintf("[错误] 导入失败: %v", err))
} else {
teamRegState.mu.Lock()
teamRegState.Imported = count
teamRegState.mu.Unlock()
addTeamRegLog(fmt.Sprintf("[系统] 成功导入 %d 个账号", count))
// 导入成功后删除 JSON 文件
if err := os.Remove(outputFile); err != nil {
addTeamRegLog(fmt.Sprintf("[警告] 删除临时文件失败: %v", err))
} else {
addTeamRegLog(fmt.Sprintf("[系统] 已清理临时文件: %s", filepath.Base(outputFile)))
}
// 自动导入
if config.AutoImport {
addTeamRegLog("[系统] 自动导入账号到数据库...")
tryAutoImport(outputFile, config)
}
}
}
// 发送回车退出程序(如果还在运行)
time.Sleep(500 * time.Millisecond)
if stdin != nil {
fmt.Fprintf(stdin, "\n")
// 发送回车退出程序(如果还在运行)
time.Sleep(500 * time.Millisecond)
signalTeamRegExit()
}
}
// readOutput 读取进程输出
func readOutput(reader io.Reader, workDir string, config TeamRegConfig) {
@@ -415,23 +405,26 @@ func readOutput(reader io.Reader, workDir string, config TeamRegConfig) {
if trimmed != "" {
addTeamRegLog(trimmed)
// 检测输出文件名(例如:结果已保存到: accounts-2-20260201-071558.json
if strings.Contains(trimmed, "结果已保存到") || strings.Contains(trimmed, "accounts-") && strings.Contains(trimmed, ".json") {
// 尝试提取文件名
if idx := strings.Index(trimmed, "accounts-"); idx >= 0 {
endIdx := strings.Index(trimmed[idx:], ".json")
if endIdx > 0 {
fileName := trimmed[idx : idx+endIdx+5] // 包含 .json
// 构建完整路径
fullPath := filepath.Join(workDir, fileName)
if _, err := os.Stat(fullPath); err == nil {
// 检测输出文件名(例如:结果已保存到: accounts-2-20260201-071558.json
if strings.Contains(trimmed, "结果已保存到") || strings.Contains(trimmed, "accounts-") && strings.Contains(trimmed, ".json") {
// 尝试提取文件名
if idx := strings.Index(trimmed, "accounts-"); idx >= 0 {
endIdx := strings.Index(trimmed[idx:], ".json")
if endIdx > 0 {
fileName := trimmed[idx : idx+endIdx+5] // 包含 .json
// 构建完整路径
fullPath := filepath.Join(workDir, fileName)
teamRegState.mu.Lock()
teamRegState.OutputFile = fullPath
teamRegState.mu.Unlock()
if config.AutoImport {
go tryAutoImport(fullPath, config)
}
// 发送回车提示退出(有些程序会在完成后等待回车)
signalTeamRegExit()
}
}
}
}
// 检测 403 错误
if strings.Contains(trimmed, "403") {
@@ -482,6 +475,80 @@ func check403AndStop() bool {
return false
}
// tryAutoImport 尝试自动导入(仅执行一次)
func tryAutoImport(filePath string, config TeamRegConfig) {
if !config.AutoImport || filePath == "" {
return
}
teamRegState.mu.Lock()
if teamRegState.autoImported || teamRegState.autoImporting {
teamRegState.mu.Unlock()
return
}
teamRegState.autoImporting = true
teamRegState.mu.Unlock()
var (
count int
err error
)
// 等待文件稳定写入(最多重试几次)
for i := 0; i < 5; i++ {
if _, statErr := os.Stat(filePath); statErr != nil {
err = statErr
} else {
count, err = importAccountsFromJSON(filePath)
}
if err == nil {
break
}
time.Sleep(300 * time.Millisecond)
}
teamRegState.mu.Lock()
teamRegState.autoImporting = false
if err == nil {
teamRegState.Imported = count
teamRegState.autoImported = true
}
teamRegState.mu.Unlock()
if err != nil {
addTeamRegLog(fmt.Sprintf("[错误] 导入失败: %v", err))
return
}
addTeamRegLog(fmt.Sprintf("[系统] 成功导入 %d 个账号", count))
// 导入成功后删除 JSON 文件
if err := os.Remove(filePath); err != nil {
addTeamRegLog(fmt.Sprintf("[警告] 删除临时文件失败: %v", err))
} else {
addTeamRegLog(fmt.Sprintf("[系统] 已清理临时文件: %s", filepath.Base(filePath)))
}
}
// signalTeamRegExit 发送回车并关闭 stdin提示程序退出
func signalTeamRegExit() {
teamRegState.mu.Lock()
if teamRegState.exitSignaled {
teamRegState.mu.Unlock()
return
}
teamRegState.exitSignaled = true
stdin := teamRegState.stdin
teamRegState.mu.Unlock()
if stdin == nil {
return
}
_, _ = fmt.Fprintln(stdin)
_ = stdin.Close()
}
// addTeamRegLog 添加日志
func addTeamRegLog(log string) {
teamRegState.mu.Lock()