chore: 停止上传开发文档并同步代码
- 从仓库索引移除 开发文档/(本地保留) - 忽略 wechat/info.log 与 soul-api-linux - 同步小程序/管理端/API改动 Made-with: Cursor
This commit is contained in:
@@ -58,7 +58,7 @@ func AdminDashboardStats(c *gin.Context) {
|
||||
func AdminDashboardRecentOrders(c *gin.Context) {
|
||||
db := database.DB()
|
||||
var recentOrders []model.Order
|
||||
db.Where("status IN ?", paidStatuses).Order("created_at DESC").Limit(5).Find(&recentOrders)
|
||||
db.Where("status IN ?", paidStatuses).Order("created_at DESC").Limit(10).Find(&recentOrders)
|
||||
c.JSON(http.StatusOK, gin.H{"success": true, "recentOrders": buildRecentOrdersOut(db, recentOrders)})
|
||||
}
|
||||
|
||||
|
||||
@@ -11,7 +11,6 @@ import (
|
||||
)
|
||||
|
||||
// AdminTrackStats GET /api/admin/track/stats 管理端-按钮/标签点击统计(按模块+action聚合)
|
||||
// 查询参数:period=today|week|month|all(默认 today)
|
||||
func AdminTrackStats(c *gin.Context) {
|
||||
period := c.DefaultQuery("period", "today")
|
||||
db := database.DB()
|
||||
@@ -29,25 +28,26 @@ func AdminTrackStats(c *gin.Context) {
|
||||
since = time.Time{}
|
||||
}
|
||||
|
||||
type trackRow struct {
|
||||
type rawRow struct {
|
||||
Action string `gorm:"column:action"`
|
||||
Target string `gorm:"column:target"`
|
||||
ExtraData []byte `gorm:"column:extra_data"`
|
||||
Count int64 `gorm:"column:count"`
|
||||
}
|
||||
|
||||
query := db.Table("user_tracks").
|
||||
Select("action, COALESCE(target, '') as target, extra_data, COUNT(*) as count").
|
||||
Group("action, COALESCE(target, ''), extra_data").
|
||||
Order("count DESC")
|
||||
|
||||
query := db.Table("user_tracks").Select("action, COALESCE(target, '') as target, extra_data")
|
||||
if !since.IsZero() {
|
||||
query = query.Where("created_at >= ?", since)
|
||||
}
|
||||
query = query.Where("action NOT LIKE '%union%' AND action NOT LIKE '%jndi%' AND action NOT LIKE '%SLEEP%'")
|
||||
|
||||
var rows []trackRow
|
||||
query.Find(&rows)
|
||||
var rawRows []rawRow
|
||||
query.Find(&rawRows)
|
||||
|
||||
type statKey struct {
|
||||
Module string
|
||||
Action string
|
||||
Target string
|
||||
}
|
||||
type statItem struct {
|
||||
Action string `json:"action"`
|
||||
Target string `json:"target"`
|
||||
@@ -56,10 +56,10 @@ func AdminTrackStats(c *gin.Context) {
|
||||
Count int64 `json:"count"`
|
||||
}
|
||||
|
||||
byModule := make(map[string][]statItem)
|
||||
aggregated := make(map[statKey]*statItem)
|
||||
total := int64(0)
|
||||
|
||||
for _, r := range rows {
|
||||
for _, r := range rawRows {
|
||||
module := "other"
|
||||
page := ""
|
||||
if len(r.ExtraData) > 0 {
|
||||
@@ -73,15 +73,24 @@ func AdminTrackStats(c *gin.Context) {
|
||||
}
|
||||
}
|
||||
}
|
||||
item := statItem{
|
||||
Action: r.Action,
|
||||
Target: r.Target,
|
||||
Module: module,
|
||||
Page: page,
|
||||
Count: r.Count,
|
||||
key := statKey{Module: module, Action: r.Action, Target: r.Target}
|
||||
if existing, ok := aggregated[key]; ok {
|
||||
existing.Count++
|
||||
} else {
|
||||
aggregated[key] = &statItem{
|
||||
Action: r.Action,
|
||||
Target: r.Target,
|
||||
Module: module,
|
||||
Page: page,
|
||||
Count: 1,
|
||||
}
|
||||
}
|
||||
byModule[module] = append(byModule[module], item)
|
||||
total += r.Count
|
||||
total++
|
||||
}
|
||||
|
||||
byModule := make(map[string][]statItem)
|
||||
for _, item := range aggregated {
|
||||
byModule[item.Module] = append(byModule[item.Module], *item)
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
|
||||
@@ -909,7 +909,26 @@ func DBUsersDelete(c *gin.Context) {
|
||||
c.JSON(http.StatusOK, gin.H{"success": false, "error": "用户ID不能为空"})
|
||||
return
|
||||
}
|
||||
if err := database.DB().Where("id = ?", id).Delete(&model.User{}).Error; err != nil {
|
||||
db := database.DB()
|
||||
cleanupTables := []struct{ table, col string }{
|
||||
{"match_records", "user_id"},
|
||||
{"reading_progress", "user_id"},
|
||||
{"user_tracks", "user_id"},
|
||||
{"referral_bindings", "referrer_id"},
|
||||
{"referral_bindings", "referee_id"},
|
||||
{"referral_visits", "visitor_id"},
|
||||
{"ckb_submit_records", "user_id"},
|
||||
{"ckb_lead_records", "user_id"},
|
||||
{"user_addresses", "user_id"},
|
||||
{"user_balances", "user_id"},
|
||||
{"balance_transactions", "user_id"},
|
||||
{"withdrawals", "user_id"},
|
||||
{"orders", "user_id"},
|
||||
}
|
||||
for _, t := range cleanupTables {
|
||||
db.Exec("DELETE FROM "+t.table+" WHERE "+t.col+" = ?", id)
|
||||
}
|
||||
if err := db.Where("id = ?", id).Delete(&model.User{}).Error; err != nil {
|
||||
c.JSON(http.StatusOK, gin.H{"success": false, "error": err.Error()})
|
||||
return
|
||||
}
|
||||
|
||||
@@ -181,6 +181,12 @@ func computeSectionsWithHotScore(db *gorm.DB, setPinned bool) ([]sectionListItem
|
||||
}
|
||||
}
|
||||
}
|
||||
weightSum := readWeight + payWeight + recencyWeight
|
||||
if weightSum > 3 {
|
||||
readWeight = readWeight / weightSum
|
||||
payWeight = payWeight / weightSum
|
||||
recencyWeight = recencyWeight / weightSum
|
||||
}
|
||||
pinnedIDs := []string{}
|
||||
if setPinned {
|
||||
var cfg2 model.SystemConfig
|
||||
|
||||
@@ -26,12 +26,19 @@ func DBCKBLeadList(c *gin.Context) {
|
||||
pageSize = 20
|
||||
}
|
||||
|
||||
dedup := c.DefaultQuery("dedup", "true")
|
||||
|
||||
if mode == "contact" {
|
||||
// ckb_lead_records:链接卡若留资
|
||||
q := db.Model(&model.CkbLeadRecord{})
|
||||
var total int64
|
||||
q.Count(&total)
|
||||
var records []model.CkbLeadRecord
|
||||
if dedup == "true" {
|
||||
subQ := db.Model(&model.CkbLeadRecord{}).
|
||||
Select("MAX(id) as id").
|
||||
Group("COALESCE(NULLIF(user_id,''), COALESCE(NULLIF(phone,''), COALESCE(NULLIF(wechat_id,''), CAST(id AS CHAR))))")
|
||||
q = db.Model(&model.CkbLeadRecord{}).Where("id IN (?)", subQ)
|
||||
}
|
||||
q.Count(&total)
|
||||
if err := q.Order("created_at DESC").Offset((page - 1) * pageSize).Limit(pageSize).Find(&records).Error; err != nil {
|
||||
c.JSON(http.StatusOK, gin.H{"success": false, "error": err.Error()})
|
||||
return
|
||||
@@ -53,15 +60,21 @@ func DBCKBLeadList(c *gin.Context) {
|
||||
return
|
||||
}
|
||||
|
||||
// mode=submitted: ckb_submit_records
|
||||
q := db.Model(&model.CkbSubmitRecord{})
|
||||
if matchType != "" {
|
||||
// matchType 对应 action: join 时 type 在 params 中,match 时 matchType 在 params 中
|
||||
// 简化:仅按 action 过滤,join 时 params 含 type
|
||||
if matchType == "join" || matchType == "match" {
|
||||
q = q.Where("action = ?", matchType)
|
||||
}
|
||||
}
|
||||
if dedup == "true" {
|
||||
subQ := db.Model(&model.CkbSubmitRecord{}).
|
||||
Select("MAX(id) as id").
|
||||
Group("COALESCE(NULLIF(user_id,''), CAST(id AS CHAR))")
|
||||
if matchType == "join" || matchType == "match" {
|
||||
subQ = subQ.Where("action = ?", matchType)
|
||||
}
|
||||
q = db.Model(&model.CkbSubmitRecord{}).Where("id IN (?)", subQ)
|
||||
}
|
||||
var total int64
|
||||
q.Count(&total)
|
||||
var records []model.CkbSubmitRecord
|
||||
|
||||
Reference in New Issue
Block a user