小程序一些功能更新
This commit is contained in:
111
internal/logic/event_query_log.go
Normal file
111
internal/logic/event_query_log.go
Normal file
@@ -0,0 +1,111 @@
|
||||
package logic
|
||||
|
||||
import (
|
||||
"context"
|
||||
"strings"
|
||||
|
||||
"github.com/gogf/gf/v2/frame/g"
|
||||
|
||||
v1 "tool-api/api/admin/v1"
|
||||
"tool-api/internal/consts"
|
||||
"tool-api/internal/model/entity"
|
||||
)
|
||||
|
||||
// ============================================================================
|
||||
// 年会域:查座审计列表(A19,架构 §5.2 遗漏项补录)
|
||||
//
|
||||
// 数据源 event_seat_queries(架构 §3.2.9),与公开查座(event_query.go)共用同一张表:
|
||||
// - phone_masked 落库时已脱敏(writeSeatAudit → maskPhone),此处原样返回,不再二次脱敏;
|
||||
// - openid 不做落库脱敏(限流需要原始值),输出时二次脱敏(前 6 位 + ***);
|
||||
// - event_title 通过一次 IN 查询批量补齐,避免逐条查(N+1)。
|
||||
// ============================================================================
|
||||
|
||||
// AdminEventQueryLog 查座审计列表。
|
||||
//
|
||||
// EventId = 0 表示全部活动;
|
||||
// Result = -1 表示全部结果,0 失败 / 1 成功(其余取值同样视为全部,避免前端漏传时误过滤)。
|
||||
func AdminEventQueryLog(ctx context.Context, req *v1.EventQueryLogReq) (*v1.EventQueryLogRes, error) {
|
||||
model := g.Model(consts.TableEventSeatQueries)
|
||||
if req.EventId > 0 {
|
||||
model = model.Where("event_id", req.EventId)
|
||||
}
|
||||
if req.Result == consts.SeatResultFail || req.Result == consts.SeatResultSuccess {
|
||||
model = model.Where("result", req.Result)
|
||||
}
|
||||
|
||||
total, err := model.Count()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
page, size := normalizeAdminPage(req.Page, req.PageSize)
|
||||
records, err := model.OrderDesc("id").Page(page, size).All()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// 解析实体 + 收集去重后的活动 id
|
||||
rows := make([]*entity.EventSeatQueries, 0, len(records))
|
||||
eventIds := make([]int64, 0)
|
||||
seen := make(map[int64]bool)
|
||||
for _, r := range records {
|
||||
item := &entity.EventSeatQueries{}
|
||||
if err = r.Struct(item); err != nil {
|
||||
continue
|
||||
}
|
||||
rows = append(rows, item)
|
||||
if item.EventId > 0 && !seen[item.EventId] {
|
||||
seen[item.EventId] = true
|
||||
eventIds = append(eventIds, item.EventId)
|
||||
}
|
||||
}
|
||||
|
||||
// 批量补齐活动标题(一次 IN 查询,避免 N+1)
|
||||
titleMap, err := loadEventTitles(ctx, eventIds)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
list := make([]v1.QueryLogItem, 0, len(rows))
|
||||
for _, item := range rows {
|
||||
list = append(list, v1.QueryLogItem{
|
||||
Id: item.Id,
|
||||
EventId: item.EventId,
|
||||
EventTitle: titleMap[item.EventId],
|
||||
Ip: item.Ip,
|
||||
PhoneMasked: item.PhoneMasked,
|
||||
OpenidMasked: maskOpenid(item.Openid),
|
||||
Result: item.Result,
|
||||
CreatedAt: formatGTime(item.CreatedAt),
|
||||
})
|
||||
}
|
||||
return &v1.EventQueryLogRes{List: list, Total: total}, nil
|
||||
}
|
||||
|
||||
// loadEventTitles 批量读取活动标题:id -> title(一次 IN 查询,避免 N+1)。
|
||||
func loadEventTitles(ctx context.Context, eventIds []int64) (map[int64]string, error) {
|
||||
out := make(map[int64]string, len(eventIds))
|
||||
if len(eventIds) == 0 {
|
||||
return out, nil
|
||||
}
|
||||
records, err := g.Model(consts.TableAnnualEvents).Fields("id", "title").WhereIn("id", eventIds).All()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for _, r := range records {
|
||||
out[r["id"].Int64()] = r["title"].String()
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
// maskOpenid openid 脱敏:保留前 6 位 + "***";空串返回空串。
|
||||
// 说明:openid 落库未脱敏(限流需原始值比对),仅在审计列表输出时脱敏。
|
||||
func maskOpenid(openid string) string {
|
||||
openid = strings.TrimSpace(openid)
|
||||
if openid == "" {
|
||||
return ""
|
||||
}
|
||||
if len(openid) <= 6 {
|
||||
return openid + "***"
|
||||
}
|
||||
return openid[:6] + "***"
|
||||
}
|
||||
Reference in New Issue
Block a user