增加便捷工具

This commit is contained in:
2026-06-17 17:18:49 +08:00
parent 9e482a12be
commit 673b84a0b3
50 changed files with 3135 additions and 9118 deletions
+24 -2
View File
@@ -33,6 +33,7 @@ var validModules = map[string]bool{
"cursor": true,
"windsurf": true,
"krio": true,
"codex": true,
}
func (c *ApiGetCardController) cardErr(_ int, _ int, msg string) {
@@ -52,7 +53,7 @@ func (c *ApiGetCardController) cardOK(text string) {
//
// 参数:
// - type (必填) 来源平台:xianyu / taobao / pinduoduo / jingdong / local / xubei
// - module (必填) 号池模块:cursor / windsurf / krio
// - module (必填) 号池模块:cursor / windsurf / krio / codex
// - data_type (可选) 账号类型:account / tk / account_tk,不传则取任意未提取的
// - id/start_id/current_id (可选) 起始 ID:从该 ID 开始向后提取,避免传 896 却取到 892
func (c *ApiGetCardController) GetCard() {
@@ -79,7 +80,7 @@ func (c *ApiGetCardController) GetCard() {
return
}
if !validModules[module] {
c.cardErr(400, 400, fmt.Sprintf("不支持的模块: %s,支持: cursor/windsurf/krio", module))
c.cardErr(400, 400, fmt.Sprintf("不支持的模块: %s,支持: cursor/windsurf/krio/codex", module))
return
}
if dataType != "" && !isValidPoolType(dataType) {
@@ -96,6 +97,8 @@ func (c *ApiGetCardController) GetCard() {
c.extractWindsurf(platform, dataType, startID, now)
case "krio":
c.extractKrio(platform, dataType, startID, now)
case "codex":
c.extractCodex(platform, dataType, startID, now)
}
}
@@ -175,6 +178,25 @@ func (c *ApiGetCardController) extractKrio(platform, dataType string, startID ui
})
}
func (c *ApiGetCardController) extractCodex(platform, dataType string, startID uint64, now time.Time) {
c.extractWithProbe("codex", platform, dataType, now, func() (uint64, *string, *string, string, string, *int8, error) {
var row models.PlatformAccountPoolCodex
qs := models.Orm.QueryTable(new(models.PlatformAccountPoolCodex)).
Filter("is_extracted", 0).
Filter("delete_time__isnull", true)
if startID > 0 {
qs = qs.Filter("id__gte", startID)
}
if dataType != "" {
qs = qs.Filter("data_type", dataType)
}
if err := qs.OrderBy("id").One(&row); err != nil {
return 0, nil, nil, "", "", nil, err
}
return row.ID, &row.Account, &row.Password, row.Token, row.DataType, nil, nil
})
}
type poolRowFetcher func() (id uint64, account, password *string, token, rowDataType string, isUsed *int8, err error)
// extractWithProbe 按 id 顺序提取并探测 Token 可用性;不可用则标记已提取并继续下一条。
+134
View File
@@ -20,6 +20,7 @@ import (
type PlatformAccountPoolCursorController struct{ beego.Controller }
type PlatformAccountPoolWindsurfController struct{ beego.Controller }
type PlatformAccountPoolKrioController struct{ beego.Controller }
type PlatformAccountPoolCodexController struct{ beego.Controller }
type accountPoolCreateRow struct {
DataType string `json:"type"`
@@ -265,6 +266,28 @@ func listPoolRows(c *beego.Controller, module string) {
rows = []models.PlatformAccountPoolKiro{}
}
list = rows
case "codex":
table := (&models.PlatformAccountPoolCodex{}).TableName()
total, err = accountPoolCountMySQL(table, where, whereArgs)
if err != nil {
poolJSONErr(c, 500, 500, "获取列表失败: "+err.Error())
return
}
sqlStr := fmt.Sprintf(
"SELECT * FROM `%s` WHERE %s ORDER BY FIELD(is_extracted, 0, 2, 3, 1) ASC, id DESC LIMIT ? OFFSET ?",
table, where,
)
args := append(append([]interface{}{}, whereArgs...), pageSize, offset)
var rows []models.PlatformAccountPoolCodex
_, err = models.Orm.Raw(sqlStr, args...).QueryRows(&rows)
if err != nil && err != orm.ErrNoRows {
poolJSONErr(c, 500, 500, "获取列表失败: "+err.Error())
return
}
if rows == nil {
rows = []models.PlatformAccountPoolCodex{}
}
list = rows
default:
poolJSONErr(c, 400, 400, "无效模块")
return
@@ -332,6 +355,16 @@ func addPoolRow(c *beego.Controller, module string) {
IsExtracted: 0,
}
_, err = models.Orm.Insert(r)
case "codex":
r := &models.PlatformAccountPoolCodex{
DataType: strings.TrimSpace(row.DataType),
Account: strings.TrimSpace(row.Account),
Password: strings.TrimSpace(row.Password),
Token: strings.TrimSpace(row.Token),
Remark: strings.TrimSpace(row.Remark),
IsExtracted: 0,
}
_, err = models.Orm.Insert(r)
default:
poolJSONErr(c, 400, 400, "无效模块")
return
@@ -397,6 +430,15 @@ func batchAddPoolRows(c *beego.Controller, module string) {
Remark: strings.TrimSpace(row.Remark),
IsExtracted: 0,
})
case "codex":
_, err = models.Orm.Insert(&models.PlatformAccountPoolCodex{
DataType: strings.TrimSpace(row.DataType),
Account: strings.TrimSpace(row.Account),
Password: strings.TrimSpace(row.Password),
Token: strings.TrimSpace(row.Token),
Remark: strings.TrimSpace(row.Remark),
IsExtracted: 0,
})
default:
poolJSONErr(c, 400, 400, "无效模块")
return
@@ -443,6 +485,13 @@ func getPoolDetail(c *beego.Controller, module string) {
return
}
c.Data["json"] = map[string]interface{}{"code": 200, "msg": "success", "data": row}
case "codex":
var row models.PlatformAccountPoolCodex
if err := models.Orm.QueryTable(new(models.PlatformAccountPoolCodex)).Filter("id", id).One(&row); err != nil {
poolJSONErr(c, 404, 404, "记录不存在")
return
}
c.Data["json"] = map[string]interface{}{"code": 200, "msg": "success", "data": row}
default:
poolJSONErr(c, 400, 400, "无效模块")
return
@@ -573,6 +622,34 @@ func extractPoolRow(c *beego.Controller, module string) {
row.ExtractedPlatform = &pf
row.Remark = remark
c.Data["json"] = map[string]interface{}{"code": 200, "msg": "提取成功", "data": row}
case "codex":
var row models.PlatformAccountPoolCodex
qs := models.Orm.QueryTable(new(models.PlatformAccountPoolCodex)).Filter("is_extracted", 0)
if payload.ID > 0 {
qs = qs.Filter("id", payload.ID)
} else if payload.Type != "" {
qs = qs.Filter("data_type", payload.Type)
}
if err := qs.OrderBy("id").One(&row); err != nil {
poolJSONErr(c, 404, 404, "没有可提取数据")
return
}
_, err = models.Orm.QueryTable(new(models.PlatformAccountPoolCodex)).Filter("id", row.ID).Update(map[string]interface{}{
"is_extracted": extractStatus,
"extracted_time": now,
"extracted_platform": platform,
"remark": remark,
})
if err != nil {
poolJSONErr(c, 500, 500, "提取失败: "+err.Error())
return
}
row.IsExtracted = extractStatus
row.ExtractedTime = &now
pf := platform
row.ExtractedPlatform = &pf
row.Remark = remark
c.Data["json"] = map[string]interface{}{"code": 200, "msg": "提取成功", "data": row}
default:
poolJSONErr(c, 400, 400, "无效模块")
return
@@ -678,6 +755,22 @@ func replenishWithProbe(c *beego.Controller, module, dataType, platform, remark
id: row.ID, dataType: row.DataType, token: row.Token, row: row,
}, nil
}
case "codex":
fetch = func() (*poolReplenishCandidate, error) {
var row models.PlatformAccountPoolCodex
err := models.Orm.QueryTable(new(models.PlatformAccountPoolCodex)).
Filter("is_extracted", 0).
Filter("data_type", dataType).
Filter("delete_time__isnull", true).
OrderBy("id").
One(&row)
if err != nil {
return nil, err
}
return &poolReplenishCandidate{
id: row.ID, dataType: row.DataType, token: row.Token, row: row,
}, nil
}
default:
poolJSONErr(c, 400, 400, "无效模块")
return
@@ -754,6 +847,12 @@ func replenishApplyResponse(row interface{}, platform, remark string, now time.T
r.ExtractedPlatform = &pf
r.Remark = remark
return r
case models.PlatformAccountPoolCodex:
r.IsExtracted = 2
r.ExtractedTime = &now
r.ExtractedPlatform = &pf
r.Remark = remark
return r
default:
return row
}
@@ -793,6 +892,10 @@ func updatePoolRemark(c *beego.Controller, module string) {
updated, err = models.Orm.QueryTable(new(models.PlatformAccountPoolKiro)).Filter("id", payload.ID).Update(map[string]interface{}{
"remark": remark,
})
case "codex":
updated, err = models.Orm.QueryTable(new(models.PlatformAccountPoolCodex)).Filter("id", payload.ID).Update(map[string]interface{}{
"remark": remark,
})
default:
poolJSONErr(c, 400, 400, "无效模块")
return
@@ -826,6 +929,8 @@ func updatePoolExtractFields(module string, id uint64, fields map[string]interfa
return models.Orm.QueryTable(new(models.PlatformAccountPoolWindsurf)).Filter("id", id).Update(fields)
case "krio":
return models.Orm.QueryTable(new(models.PlatformAccountPoolKiro)).Filter("id", id).Update(fields)
case "codex":
return models.Orm.QueryTable(new(models.PlatformAccountPoolCodex)).Filter("id", id).Update(fields)
default:
return 0, fmt.Errorf("无效模块")
}
@@ -1059,6 +1164,17 @@ func probePoolToken(c *beego.Controller, module string) {
return
}
token = strings.TrimSpace(row.Token)
case "codex":
if payload.ID == 0 {
poolJSONErr(c, 400, 400, "缺少有效 id")
return
}
var row models.PlatformAccountPoolCodex
if err := models.Orm.QueryTable(new(models.PlatformAccountPoolCodex)).Filter("id", payload.ID).One(&row); err != nil {
poolJSONErr(c, 404, 404, "记录不存在")
return
}
token = strings.TrimSpace(row.Token)
default:
poolJSONErr(c, 400, 400, "无效模块")
return
@@ -1182,3 +1298,21 @@ func (c *PlatformAccountPoolKrioController) UpdatePlatform() {
}
func (c *PlatformAccountPoolKrioController) Unextract() { unextractPoolRow(&c.Controller, "krio") }
func (c *PlatformAccountPoolKrioController) ProbeToken() { probePoolToken(&c.Controller, "krio") }
func (c *PlatformAccountPoolCodexController) List() { listPoolRows(&c.Controller, "codex") }
func (c *PlatformAccountPoolCodexController) Add() { addPoolRow(&c.Controller, "codex") }
func (c *PlatformAccountPoolCodexController) BatchAdd() { batchAddPoolRows(&c.Controller, "codex") }
func (c *PlatformAccountPoolCodexController) Detail() { getPoolDetail(&c.Controller, "codex") }
func (c *PlatformAccountPoolCodexController) Extract() { extractPoolRow(&c.Controller, "codex") }
func (c *PlatformAccountPoolCodexController) Replenish() { replenishPoolRow(&c.Controller, "codex") }
func (c *PlatformAccountPoolCodexController) UpdateRemark() {
updatePoolRemark(&c.Controller, "codex")
}
func (c *PlatformAccountPoolCodexController) SetUnavailable() {
setPoolUnavailable(&c.Controller, "codex")
}
func (c *PlatformAccountPoolCodexController) UpdatePlatform() {
updatePoolPlatform(&c.Controller, "codex")
}
func (c *PlatformAccountPoolCodexController) Unextract() { unextractPoolRow(&c.Controller, "codex") }
func (c *PlatformAccountPoolCodexController) ProbeToken() { probePoolToken(&c.Controller, "codex") }
+3
View File
@@ -217,13 +217,16 @@ func (c *PlatformHomeController) AccountPoolInventoryTotals() {
{Key: "cursor", Label: "Cursor"},
{Key: "krio", Label: "Kiro"},
{Key: "windsurf", Label: "Windsurf"},
{Key: "codex", Label: "Codex"},
}
modelsList := []interface{}{
new(models.PlatformAccountPoolCursor),
new(models.PlatformAccountPoolKiro),
new(models.PlatformAccountPoolWindsurf),
new(models.PlatformAccountPoolCodex),
}
var grandTotal, grandSold int64
for i := range modules {
tot, err := countPoolInventory(modelsList[i], false)
+3
View File
@@ -16,7 +16,10 @@ func poolTableName(module string) string {
return new(models.PlatformAccountPoolWindsurf).TableName()
case "krio":
return new(models.PlatformAccountPoolKiro).TableName()
case "codex":
return new(models.PlatformAccountPoolCodex).TableName()
default:
return ""
}
}
+2
View File
@@ -61,6 +61,8 @@ func Init(_ string) {
new(PlatformAccountPoolKiro),
new(PlatformAccountPoolWindsurf),
new(PlatformAccountPoolCursor),
new(PlatformAccountPoolCodex),
new(CmsArticleCategory),
new(CmsArticle),
)
+21
View File
@@ -22,6 +22,27 @@ func (m *PlatformAccountPoolKiro) TableName() string {
return "yz_platform_account_pool_krio"
}
// PlatformAccountPoolCodex 号池表: yz_platform_account_pool_codex
type PlatformAccountPoolCodex struct {
ID uint64 `orm:"column(id);pk;auto" json:"id"`
DataType string `orm:"column(data_type);size(32)" json:"data_type"` // account | tk | account_tk
Account string `orm:"column(account);size(128);default()" json:"account"`
Password string `orm:"column(password);size(255);default()" json:"password"`
Token string `orm:"column(token);type(text);null" json:"token"`
Remark string `orm:"column(remark);size(255);default()" json:"remark"`
IsExtracted int8 `orm:"column(is_extracted);default(0)" json:"is_extracted"`
ExtractedTime *time.Time `orm:"column(extracted_time);type(datetime);null" json:"extracted_time"`
ExtractedPlatform *string `orm:"column(extracted_platform);size(32);null" json:"extracted_platform"`
CreateTime time.Time `orm:"column(create_time);auto_now_add;type(datetime)" json:"create_time"`
UpdateTime *time.Time `orm:"column(update_time);type(datetime);null" json:"update_time"`
DeleteTime *time.Time `orm:"column(delete_time);type(datetime);null" json:"delete_time"`
}
func (m *PlatformAccountPoolCodex) TableName() string {
return "yz_platform_account_pool_codex"
}
// PlatformAccountPoolWindsurf 号池表: yz_platform_account_pool_windsurf
type PlatformAccountPoolWindsurf struct {
ID uint64 `orm:"column(id);pk;auto" json:"id"`
+13 -1
View File
@@ -183,7 +183,7 @@ func Register() {
beego.Router("/platform/cursor/activationcode/disable/:id", &controllers.PlatformCursorActivationCodeController{}, "post:Disable")
beego.Router("/platform/cursor/activationcode/export", &controllers.PlatformCursorActivationCodeController{}, "get:Export")
// 账号池管理(cursor/windsurf/krio
// 账号池管理(cursor/windsurf/krio/codex
beego.Router("/platform/accountPool/cursor/list", &controllers.PlatformAccountPoolCursorController{}, "get:List")
beego.Router("/platform/accountPool/cursor/add", &controllers.PlatformAccountPoolCursorController{}, "post:Add")
beego.Router("/platform/accountPool/cursor/batchAdd", &controllers.PlatformAccountPoolCursorController{}, "post:BatchAdd")
@@ -220,4 +220,16 @@ func Register() {
beego.Router("/platform/accountPool/krio/unextract", &controllers.PlatformAccountPoolKrioController{}, "post:Unextract")
beego.Router("/platform/accountPool/krio/replenish", &controllers.PlatformAccountPoolKrioController{}, "post:Replenish")
beego.Router("/platform/accountPool/krio/probeToken", &controllers.PlatformAccountPoolKrioController{}, "post:ProbeToken")
beego.Router("/platform/accountPool/codex/list", &controllers.PlatformAccountPoolCodexController{}, "get:List")
beego.Router("/platform/accountPool/codex/add", &controllers.PlatformAccountPoolCodexController{}, "post:Add")
beego.Router("/platform/accountPool/codex/batchAdd", &controllers.PlatformAccountPoolCodexController{}, "post:BatchAdd")
beego.Router("/platform/accountPool/codex/detail/:id", &controllers.PlatformAccountPoolCodexController{}, "get:Detail")
beego.Router("/platform/accountPool/codex/extract", &controllers.PlatformAccountPoolCodexController{}, "post:Extract")
beego.Router("/platform/accountPool/codex/updateRemark", &controllers.PlatformAccountPoolCodexController{}, "post:UpdateRemark")
beego.Router("/platform/accountPool/codex/setUnavailable", &controllers.PlatformAccountPoolCodexController{}, "post:SetUnavailable")
beego.Router("/platform/accountPool/codex/updatePlatform", &controllers.PlatformAccountPoolCodexController{}, "post:UpdatePlatform")
beego.Router("/platform/accountPool/codex/unextract", &controllers.PlatformAccountPoolCodexController{}, "post:Unextract")
beego.Router("/platform/accountPool/codex/replenish", &controllers.PlatformAccountPoolCodexController{}, "post:Replenish")
beego.Router("/platform/accountPool/codex/probeToken", &controllers.PlatformAccountPoolCodexController{}, "post:ProbeToken")
}