first commit

This commit is contained in:
2026-06-03 10:09:03 +08:00
commit 81f5039458
6266 changed files with 188236 additions and 0 deletions
+255
View File
@@ -0,0 +1,255 @@
package controllers
import (
"fmt"
"strconv"
"strings"
"time"
"server/models"
"github.com/beego/beego/v2/client/orm"
beego "github.com/beego/beego/v2/server/web"
)
// PlatformHomeController 平台首页统计(需登录)
type PlatformHomeController struct {
beego.Controller
}
func cellToDateKey(v interface{}) string {
if v == nil {
return ""
}
switch x := v.(type) {
case []byte:
s := strings.TrimSpace(string(x))
if len(s) >= 10 {
return s[:10]
}
return s
case string:
s := strings.TrimSpace(x)
if len(s) >= 10 {
return s[:10]
}
return s
case time.Time:
if x.IsZero() {
return ""
}
return x.In(time.Local).Format("2006-01-02")
default:
s := strings.TrimSpace(fmt.Sprint(x))
if len(s) >= 10 {
return s[:10]
}
return s
}
}
func cellToInt64(v interface{}) int64 {
if v == nil {
return 0
}
switch x := v.(type) {
case []byte:
n, _ := strconv.ParseInt(strings.TrimSpace(string(x)), 10, 64)
return n
case int64:
return x
case int32:
return int64(x)
case int:
return int64(x)
default:
n, _ := strconv.ParseInt(strings.TrimSpace(fmt.Sprint(x)), 10, 64)
return n
}
}
func queryExtractedCountByDay(table string, start, endExclusive time.Time) (map[string]int64, error) {
// 不按 delete_time 过滤:部分库未删除行存 0000-00-00 或非 NULL,会导致统计全空。
// Raw + QueryRows 对别名映射不稳定,改用 Values 解析 d/c。
sql := fmt.Sprintf(`
SELECT DATE(extracted_time) AS d, COUNT(*) AS c
FROM %s
WHERE is_extracted IN (1, 2)
AND extracted_time IS NOT NULL
AND extracted_time >= ?
AND extracted_time < ?
GROUP BY DATE(extracted_time)
ORDER BY d
`, table)
var maps []orm.Params
_, err := models.Orm.Raw(sql, start, endExclusive).Values(&maps)
if err != nil {
return nil, err
}
out := make(map[string]int64, len(maps))
for _, m := range maps {
var dk, ck interface{}
for _, k := range []string{"d", "D"} {
if v, ok := m[k]; ok {
dk = v
break
}
}
for _, k := range []string{"c", "C"} {
if v, ok := m[k]; ok {
ck = v
break
}
}
key := cellToDateKey(dk)
if key == "" {
continue
}
out[key] = cellToInt64(ck)
}
return out, nil
}
// AccountPoolDailyExtract GET /platform/home/accountPoolDailyExtract?days=14
// 按天统计各号池「已提取」数量,依据 extracted_time 落在当天的记录。
func (c *PlatformHomeController) AccountPoolDailyExtract() {
if _, err := requirePlatformAuth(&c.Controller); err != nil {
poolJSONErr(&c.Controller, 401, 401, err.Error())
return
}
n, _ := c.GetInt("days", 14)
if n < 1 {
n = 1
}
if n > 90 {
n = 90
}
now := time.Now().In(time.Local)
today0 := time.Date(now.Year(), now.Month(), now.Day(), 0, 0, 0, 0, time.Local)
firstDay := today0.AddDate(0, 0, -(n - 1))
endExclusive := today0.AddDate(0, 0, 1)
cursorTable := (&models.PlatformAccountPoolCursor{}).TableName()
windsurfTable := (&models.PlatformAccountPoolWindsurf{}).TableName()
kiroTable := (&models.PlatformAccountPoolKiro{}).TableName()
mCursor, err := queryExtractedCountByDay(cursorTable, firstDay, endExclusive)
if err != nil {
poolJSONErr(&c.Controller, 500, 500, "统计 Cursor 失败: "+err.Error())
return
}
mWindsurf, err := queryExtractedCountByDay(windsurfTable, firstDay, endExclusive)
if err != nil {
poolJSONErr(&c.Controller, 500, 500, "统计 Windsurf 失败: "+err.Error())
return
}
mKiro, err := queryExtractedCountByDay(kiroTable, firstDay, endExclusive)
if err != nil {
poolJSONErr(&c.Controller, 500, 500, "统计 Kiro 失败: "+err.Error())
return
}
dayKeys := make([]string, 0, n)
dayLabels := make([]string, 0, n)
cursorVals := make([]int64, 0, n)
windsurfVals := make([]int64, 0, n)
kiroVals := make([]int64, 0, n)
for i := 0; i < n; i++ {
d := firstDay.AddDate(0, 0, i)
key := d.Format("2006-01-02")
dayKeys = append(dayKeys, key)
dayLabels = append(dayLabels, d.Format("01/02"))
cursorVals = append(cursorVals, mCursor[key])
windsurfVals = append(windsurfVals, mWindsurf[key])
kiroVals = append(kiroVals, mKiro[key])
}
c.Data["json"] = map[string]interface{}{
"code": 200,
"msg": "success",
"data": map[string]interface{}{
"days": dayLabels,
"dayKeys": dayKeys,
"cursor": int64SliceToInt(cursorVals),
"windsurf": int64SliceToInt(windsurfVals),
"kiro": int64SliceToInt(kiroVals),
"daysLength": n,
},
}
_ = c.ServeJSON()
}
func int64SliceToInt(in []int64) []int {
out := make([]int, len(in))
for i, v := range in {
out[i] = int(v)
}
return out
}
func countPoolInventory(mi interface{}, soldOnly bool) (int64, error) {
qs := models.Orm.QueryTable(mi).Filter("delete_time__isnull", true)
if soldOnly {
qs = qs.Filter("is_extracted__in", 1, 2)
}
n, err := qs.Count()
return n, err
}
// AccountPoolInventoryTotals GET /platform/home/accountPoolInventoryTotals
// 各号池:账号总数(未删)、已售卖(is_extracted 为 1 或 2
func (c *PlatformHomeController) AccountPoolInventoryTotals() {
if _, err := requirePlatformAuth(&c.Controller); err != nil {
poolJSONErr(&c.Controller, 401, 401, err.Error())
return
}
type invModule struct {
Key string `json:"key"`
Label string `json:"label"`
Total int64 `json:"total"`
Sold int64 `json:"sold"`
}
modules := []invModule{
{Key: "cursor", Label: "Cursor"},
{Key: "krio", Label: "Kiro"},
{Key: "windsurf", Label: "Windsurf"},
}
modelsList := []interface{}{
new(models.PlatformAccountPoolCursor),
new(models.PlatformAccountPoolKiro),
new(models.PlatformAccountPoolWindsurf),
}
var grandTotal, grandSold int64
for i := range modules {
tot, err := countPoolInventory(modelsList[i], false)
if err != nil {
poolJSONErr(&c.Controller, 500, 500, "统计失败: "+err.Error())
return
}
sd, err := countPoolInventory(modelsList[i], true)
if err != nil {
poolJSONErr(&c.Controller, 500, 500, "统计失败: "+err.Error())
return
}
modules[i].Total = tot
modules[i].Sold = sd
grandTotal += tot
grandSold += sd
}
c.Data["json"] = map[string]interface{}{
"code": 200,
"msg": "success",
"data": map[string]interface{}{
"modules": modules,
"grandTotal": grandTotal,
"grandSold": grandSold,
},
}
_ = c.ServeJSON()
}