feat: 添加抖音商品奖励功能,并增强后台用户列表统计数据、邀请人数及道具数量展示。
This commit is contained in:
parent
e3a96e68d8
commit
b21e2db8ef
26
Dockerfile
26
Dockerfile
@ -1,5 +1,5 @@
|
||||
# Build stage
|
||||
FROM golang:1.23-alpine AS builder
|
||||
FROM golang:1.24-alpine AS builder
|
||||
|
||||
# Set working directory
|
||||
WORKDIR /app
|
||||
@ -12,20 +12,20 @@ COPY go.mod go.sum ./
|
||||
|
||||
# Set Go environment variables and proxy
|
||||
ENV GO111MODULE=on \
|
||||
CGO_ENABLED=0 \
|
||||
GOOS=linux \
|
||||
GOARCH=amd64 \
|
||||
GOPROXY=https://goproxy.cn,https://goproxy.io,direct \
|
||||
GOSUMDB=sum.golang.google.cn
|
||||
CGO_ENABLED=0 \
|
||||
GOOS=linux \
|
||||
GOARCH=amd64 \
|
||||
GOPROXY=https://goproxy.cn,https://goproxy.io,direct \
|
||||
GOSUMDB=sum.golang.google.cn
|
||||
|
||||
# Download dependencies with retry mechanism
|
||||
RUN go mod download || \
|
||||
(echo "Retrying with different proxy..." && \
|
||||
go env -w GOPROXY=https://goproxy.io,https://mirrors.aliyun.com/goproxy/,direct && \
|
||||
go mod download) || \
|
||||
(echo "Final retry with direct mode..." && \
|
||||
go env -w GOPROXY=direct && \
|
||||
go mod download)
|
||||
(echo "Retrying with different proxy..." && \
|
||||
go env -w GOPROXY=https://goproxy.io,https://mirrors.aliyun.com/goproxy/,direct && \
|
||||
go mod download) || \
|
||||
(echo "Final retry with direct mode..." && \
|
||||
go env -w GOPROXY=direct && \
|
||||
go mod download)
|
||||
|
||||
# Copy source code
|
||||
COPY . .
|
||||
@ -62,4 +62,4 @@ HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \
|
||||
CMD wget --no-verbose --tries=1 --spider http://localhost:9991/system/health || exit 1
|
||||
|
||||
# Run the application
|
||||
CMD ["./miniChat"]
|
||||
CMD ["sh", "-c", "./miniChat -env=${ACTIVE_ENV}"]
|
||||
21
backend.log
Normal file
21
backend.log
Normal file
@ -0,0 +1,21 @@
|
||||
{"level":"info","time":"2026-01-08 00:53:15","caller":"logger/logger.go:309","msg":"Connected to Redis","domain":"mini-chat[fat]","addr":"118.25.13.43:8379"}
|
||||
|
||||
[32m ____ _ _ _ ____[0m
|
||||
[32m | __ ) (_) _ __ __| | | |__ ___ __ __ / ___| __ _ _ __ ___ ___[0m
|
||||
[32m | _ \ | | | '_ \ / _` | | '_ \ / _ \ \ \/ / | | _ / _` | | '_ ` _ \ / _ \[0m
|
||||
[32m | |_) | | | | | | | | (_| | | |_) | | (_) | > < | |_| | | (_| | | | | | | | | __/[0m
|
||||
[32m |____/ |_| |_| |_| \__,_| |_.__/ \___/ /_/\_\ \____| \__,_| |_| |_| |_| \___|[0m
|
||||
▌ 客户项目: 盲盒游戏
|
||||
▌ 项目版本: Release-2025111111
|
||||
▌ 启动时间: 2026-01-08 00:53:15
|
||||
▌ 运行环境: darwin go1.24.2
|
||||
▌ 服务端口: [:9991]
|
||||
▌ 服务配置: [fat]
|
||||
|
||||
▌ 数据库连接: ✔ 已建立
|
||||
|
||||
{"level":"info","time":"2026-01-08 00:53:15","caller":"logger/logger.go:309","msg":"Task center worker started","domain":"mini-chat[fat]"}
|
||||
{"level":"info","time":"2026-01-08 00:53:15","caller":"logger/logger.go:309","msg":"对对碰自动开奖: 后台任务已启动","domain":"mini-chat[fat]"}
|
||||
{"level":"fatal","time":"2026-01-08 00:53:15","caller":"logger/logger.go:333","msg":"http server startup err","domain":"mini-chat[fat]","error":"listen tcp :9991: bind: address already in use"}
|
||||
{"level":"info","time":"2026-01-08 00:53:15","caller":"logger/logger.go:309","msg":"[抖店定时同步] 定时任务已启动","domain":"mini-chat[fat]"}
|
||||
exit status 1
|
||||
127
backend_assets.log
Normal file
127
backend_assets.log
Normal file
@ -0,0 +1,127 @@
|
||||
{"level":"info","time":"2026-01-08 01:00:31","caller":"logger/logger.go:309","msg":"Connected to Redis","domain":"mini-chat[fat]","addr":"118.25.13.43:8379"}
|
||||
|
||||
[32m ____ _ _ _ ____[0m
|
||||
[32m | __ ) (_) _ __ __| | | |__ ___ __ __ / ___| __ _ _ __ ___ ___[0m
|
||||
[32m | _ \ | | | '_ \ / _` | | '_ \ / _ \ \ \/ / | | _ / _` | | '_ ` _ \ / _ \[0m
|
||||
[32m | |_) | | | | | | | | (_| | | |_) | | (_) | > < | |_| | | (_| | | | | | | | | __/[0m
|
||||
[32m |____/ |_| |_| |_| \__,_| |_.__/ \___/ /_/\_\ \____| \__,_| |_| |_| |_| \___|[0m
|
||||
▌ 客户项目: 盲盒游戏
|
||||
▌ 项目版本: Release-2025111111
|
||||
▌ 启动时间: 2026-01-08 01:00:31
|
||||
▌ 运行环境: darwin go1.24.2
|
||||
▌ 服务端口: [:9991]
|
||||
▌ 服务配置: [fat]
|
||||
|
||||
▌ 数据库连接: ✔ 已建立
|
||||
|
||||
{"level":"info","time":"2026-01-08 01:00:31","caller":"logger/logger.go:309","msg":"Task center worker started","domain":"mini-chat[fat]"}
|
||||
{"level":"info","time":"2026-01-08 01:00:31","caller":"logger/logger.go:309","msg":"对对碰自动开奖: 后台任务已启动","domain":"mini-chat[fat]"}
|
||||
{"level":"info","time":"2026-01-08 01:00:31","caller":"logger/logger.go:309","msg":"[抖店定时同步] 定时任务已启动","domain":"mini-chat[fat]"}
|
||||
{"level":"info","time":"2026-01-08 01:00:31","caller":"logger/logger.go:309","msg":"Worker routine started","domain":"mini-chat[fat]","worker_id":4}
|
||||
{"level":"info","time":"2026-01-08 01:00:31","caller":"logger/logger.go:309","msg":"Worker routine started","domain":"mini-chat[fat]","worker_id":2}
|
||||
{"level":"info","time":"2026-01-08 01:00:31","caller":"logger/logger.go:309","msg":"Worker routine started","domain":"mini-chat[fat]","worker_id":3}
|
||||
{"level":"info","time":"2026-01-08 01:00:31","caller":"logger/logger.go:309","msg":"Worker routine started","domain":"mini-chat[fat]","worker_id":0}
|
||||
{"level":"info","time":"2026-01-08 01:00:31","caller":"logger/logger.go:309","msg":"Worker routine started","domain":"mini-chat[fat]","worker_id":1}
|
||||
{"level":"error","time":"2026-01-08 01:00:32","caller":"logger/logger.go:327","msg":"解密配置失败","domain":"mini-chat[fat]","key":"douyin.app_secret","error":"ciphertext is not a multiple of the block size"}
|
||||
{"level":"info","time":"2026-01-08 01:00:32","caller":"logger/logger.go:309","msg":"动态配置加载完成","domain":"mini-chat[fat]","count":26}
|
||||
{"level":"info","time":"2026-01-08 01:00:44","caller":"logger/logger.go:309","msg":"refund: ActualAmount=0, skip wechat refund: order=O20260107213341575","domain":"mini-chat[fat]"}
|
||||
{"level":"info","time":"2026-01-08 01:00:45","caller":"logger/logger.go:309","msg":"清理一番赏占位成功","domain":"mini-chat[fat]","order_id":4002,"rows":0}
|
||||
{"level":"info","time":"2026-01-08 01:00:45","caller":"logger/logger.go:309","msg":"refund restore game_pass success: order=O20260107213341575 gp_id=66 count=1","domain":"mini-chat[fat]"}
|
||||
{"level":"info","time":"2026-01-08 01:00:45","caller":"logger/logger.go:309","msg":"refund: ActualAmount=0, skip wechat refund: order=O20260107213340076","domain":"mini-chat[fat]"}
|
||||
{"level":"info","time":"2026-01-08 01:00:45","caller":"logger/logger.go:309","msg":"清理一番赏占位成功","domain":"mini-chat[fat]","order_id":4001,"rows":0}
|
||||
{"level":"info","time":"2026-01-08 01:00:45","caller":"logger/logger.go:309","msg":"refund restore game_pass success: order=O20260107213340076 gp_id=66 count=1","domain":"mini-chat[fat]"}
|
||||
{"level":"info","time":"2026-01-08 01:00:45","caller":"logger/logger.go:309","msg":"refund: ActualAmount=0, skip wechat refund: order=O20260107213339935","domain":"mini-chat[fat]"}
|
||||
{"level":"info","time":"2026-01-08 01:00:45","caller":"logger/logger.go:309","msg":"清理一番赏占位成功","domain":"mini-chat[fat]","order_id":4000,"rows":0}
|
||||
{"level":"info","time":"2026-01-08 01:00:46","caller":"logger/logger.go:309","msg":"refund restore game_pass success: order=O20260107213339935 gp_id=66 count=1","domain":"mini-chat[fat]"}
|
||||
{"level":"info","time":"2026-01-08 01:00:46","caller":"logger/logger.go:309","msg":"refund: ActualAmount=0, skip wechat refund: order=O20260107213338161","domain":"mini-chat[fat]"}
|
||||
{"level":"info","time":"2026-01-08 01:00:46","caller":"logger/logger.go:309","msg":"清理一番赏占位成功","domain":"mini-chat[fat]","order_id":3999,"rows":0}
|
||||
{"level":"info","time":"2026-01-08 01:00:46","caller":"logger/logger.go:309","msg":"refund restore game_pass success: order=O20260107213338161 gp_id=66 count=1","domain":"mini-chat[fat]"}
|
||||
{"level":"info","time":"2026-01-08 01:00:46","caller":"logger/logger.go:309","msg":"refund: ActualAmount=0, skip wechat refund: order=O20260107213337885","domain":"mini-chat[fat]"}
|
||||
{"level":"info","time":"2026-01-08 01:00:46","caller":"logger/logger.go:309","msg":"清理一番赏占位成功","domain":"mini-chat[fat]","order_id":3998,"rows":0}
|
||||
{"level":"info","time":"2026-01-08 01:00:47","caller":"logger/logger.go:309","msg":"refund restore game_pass success: order=O20260107213337885 gp_id=66 count=1","domain":"mini-chat[fat]"}
|
||||
{"level":"info","time":"2026-01-08 01:00:49","caller":"logger/logger.go:309","msg":"清理一番赏占位成功","domain":"mini-chat[fat]","order_id":3997,"rows":0}
|
||||
{"level":"info","time":"2026-01-08 01:00:51","caller":"logger/logger.go:309","msg":"清理一番赏占位成功","domain":"mini-chat[fat]","order_id":3996,"rows":0}
|
||||
{"level":"info","time":"2026-01-08 01:00:52","caller":"logger/logger.go:309","msg":"清理一番赏占位成功","domain":"mini-chat[fat]","order_id":3995,"rows":0}
|
||||
{"level":"info","time":"2026-01-08 01:00:52","caller":"logger/logger.go:309","msg":"refund: ActualAmount=0, skip wechat refund: order=GP202601071823419722","domain":"mini-chat[fat]"}
|
||||
{"level":"info","time":"2026-01-08 01:00:53","caller":"logger/logger.go:309","msg":"清理一番赏占位成功","domain":"mini-chat[fat]","order_id":3994,"rows":0}
|
||||
{"level":"info","time":"2026-01-08 01:00:53","caller":"logger/logger.go:309","msg":"refund restore game_pass success: order=GP202601071823419722 game_pass_id=65","domain":"mini-chat[fat]"}
|
||||
{"level":"info","time":"2026-01-08 01:00:54","caller":"logger/logger.go:309","msg":"清理一番赏占位成功","domain":"mini-chat[fat]","order_id":3993,"rows":0}
|
||||
{"level":"info","time":"2026-01-08 01:00:54","caller":"logger/logger.go:309","msg":"refund: ActualAmount=0, skip wechat refund: order=O20260107182203580","domain":"mini-chat[fat]"}
|
||||
{"level":"info","time":"2026-01-08 01:00:54","caller":"logger/logger.go:309","msg":"清理一番赏占位成功","domain":"mini-chat[fat]","order_id":3992,"rows":0}
|
||||
{"level":"info","time":"2026-01-08 01:00:54","caller":"logger/logger.go:309","msg":"refund restore game_pass success: order=O20260107182203580 gp_id=64 count=1","domain":"mini-chat[fat]"}
|
||||
{"level":"info","time":"2026-01-08 01:00:56","caller":"logger/logger.go:309","msg":"清理一番赏占位成功","domain":"mini-chat[fat]","order_id":3991,"rows":0}
|
||||
{"level":"info","time":"2026-01-08 01:00:57","caller":"logger/logger.go:309","msg":"清理一番赏占位成功","domain":"mini-chat[fat]","order_id":3984,"rows":0}
|
||||
{"level":"info","time":"2026-01-08 01:00:57","caller":"logger/logger.go:309","msg":"refund: ActualAmount=0, skip wechat refund: order=RG20260107092128879615","domain":"mini-chat[fat]"}
|
||||
{"level":"info","time":"2026-01-08 01:00:57","caller":"logger/logger.go:309","msg":"清理一番赏占位成功","domain":"mini-chat[fat]","order_id":3973,"rows":0}
|
||||
{"level":"info","time":"2026-01-08 01:00:59","caller":"logger/logger.go:309","msg":"清理一番赏占位成功","domain":"mini-chat[fat]","order_id":3972,"rows":0}
|
||||
{"level":"info","time":"2026-01-08 01:01:00","caller":"logger/logger.go:309","msg":"清理一番赏占位成功","domain":"mini-chat[fat]","order_id":3971,"rows":0}
|
||||
{"level":"info","time":"2026-01-08 01:01:00","caller":"logger/logger.go:309","msg":"refund: ActualAmount=0, skip wechat refund: order=GP202601070918119626","domain":"mini-chat[fat]"}
|
||||
{"level":"info","time":"2026-01-08 01:01:00","caller":"logger/logger.go:309","msg":"清理一番赏占位成功","domain":"mini-chat[fat]","order_id":3969,"rows":0}
|
||||
{"level":"info","time":"2026-01-08 01:01:01","caller":"logger/logger.go:309","msg":"refund restore game_pass success: order=GP202601070918119626 game_pass_id=62","domain":"mini-chat[fat]"}
|
||||
{"level":"debug","time":"2026-01-08 01:01:01","caller":"logger/logger.go:315","msg":"定时开奖: 开始检查","domain":"mini-chat[fat]","now":"2026-01-08 01:01:01"}
|
||||
{"level":"info","time":"2026-01-08 01:01:01","caller":"logger/logger.go:309","msg":"[抖店定时同步] 开始同步","domain":"mini-chat[fat]","interval_minutes":1}
|
||||
{"level":"debug","time":"2026-01-08 01:01:02","caller":"logger/logger.go:315","msg":"定时开奖: 查询到活动","domain":"mini-chat[fat]","count":9}
|
||||
{"level":"debug","time":"2026-01-08 01:01:02","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":52,"play_type":"ichiban","interval":3,"scheduled_time":"2026-01-08T01:03:14.807+08:00","last_settled":"2026-01-08T01:00:14.807+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 01:01:02","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":52,"st":"2026-01-08 01:03:14","now":"2026-01-08 01:01:01","skip":true}
|
||||
[DEBUG] 开始全量同步,共 3 个绑定用户
|
||||
[DEBUG] 正在同步用户 ID: 9018 (昵称: 现实的迪斯蒂法诺, 抖音号: wyl0423333) 的订单...
|
||||
{"level":"debug","time":"2026-01-08 01:01:02","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":65,"play_type":"ichiban","interval":3,"scheduled_time":"2026-01-08T01:02:59.385+08:00","last_settled":"2026-01-08T00:59:59.385+08:00"}
|
||||
{"level":"info","time":"2026-01-08 01:01:02","caller":"logger/logger.go:309","msg":"清理一番赏占位成功","domain":"mini-chat[fat]","order_id":3968,"rows":0}
|
||||
{"level":"debug","time":"2026-01-08 01:01:02","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":65,"st":"2026-01-08 01:02:59","now":"2026-01-08 01:01:01","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 01:01:02","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":77,"play_type":"ichiban","interval":5,"scheduled_time":"2026-01-08T01:03:44.807+08:00","last_settled":"2026-01-08T00:58:44.807+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 01:01:02","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":77,"st":"2026-01-08 01:03:44","now":"2026-01-08 01:01:01","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 01:01:02","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":79,"play_type":"ichiban","interval":5,"scheduled_time":"2026-01-08T01:05:14.807+08:00","last_settled":"2026-01-08T01:00:14.807+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 01:01:02","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":79,"st":"2026-01-08 01:05:14","now":"2026-01-08 01:01:01","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 01:01:02","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":80,"play_type":"ichiban","interval":10,"scheduled_time":"2026-01-08T01:04:18.148+08:00","last_settled":"2026-01-08T00:54:18.148+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 01:01:02","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":80,"st":"2026-01-08 01:04:18","now":"2026-01-08 01:01:01","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 01:01:02","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":81,"play_type":"ichiban","interval":15,"scheduled_time":"2026-01-08T01:10:14.807+08:00","last_settled":"2026-01-08T00:55:14.807+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 01:01:02","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":81,"st":"2026-01-08 01:10:14","now":"2026-01-08 01:01:01","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 01:01:02","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":82,"play_type":"ichiban","interval":15,"scheduled_time":"2026-01-08T01:10:14.807+08:00","last_settled":"2026-01-08T00:55:14.807+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 01:01:02","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":82,"st":"2026-01-08 01:10:14","now":"2026-01-08 01:01:01","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 01:01:02","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":83,"play_type":"ichiban","interval":30,"scheduled_time":"2026-01-08T01:05:26.489+08:00","last_settled":"2026-01-08T00:35:26.489+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 01:01:02","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":83,"st":"2026-01-08 01:05:26","now":"2026-01-08 01:01:01","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 01:01:02","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":84,"play_type":"ichiban","interval":60,"scheduled_time":"2026-01-08T01:27:44.808+08:00","last_settled":"2026-01-08T00:27:44.808+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 01:01:02","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":84,"st":"2026-01-08 01:27:44","now":"2026-01-08 01:01:01","skip":true}
|
||||
{"level":"info","time":"2026-01-08 01:01:03","caller":"logger/logger.go:309","msg":"清理一番赏占位成功","domain":"mini-chat[fat]","order_id":3965,"rows":0}
|
||||
[DEBUG] 正在同步用户 ID: 9019 (昵称: 约翰掐指一算, 抖音号: xrw200947752) 的订单...
|
||||
[DEBUG] 正在同步用户 ID: 9047 (昵称: 巴乔横扫六合, 抖音号: 请输入您的抖店订单号即可完成绑定) 的订单...
|
||||
{"level":"info","time":"2026-01-08 01:01:06","caller":"logger/logger.go:309","msg":"[抖店同步] 全量同步完成","domain":"mini-chat[fat]","users_count":3,"total_fetched":45,"new_orders":0,"matched_users":45}
|
||||
{"level":"info","time":"2026-01-08 01:01:06","caller":"logger/logger.go:309","msg":"[抖店定时同步] 同步成功","domain":"mini-chat[fat]","total_fetched":45,"new_orders":0,"matched_users":45}
|
||||
|
||||
2026/01/08 01:01:06 /Users/win/aicode/bindbox/bindbox_game/internal/api/admin/dashboard_spending.go:113 Error 1054 (42S22): Unknown column 'orders.activity_id' in 'on clause'
|
||||
[11.786ms] [rows:-] SELECT
|
||||
orders.user_id,
|
||||
SUM(orders.actual_amount) as total_amount,
|
||||
COUNT(orders.id) as order_count,
|
||||
SUM(orders.discount_amount) as total_discount,
|
||||
SUM(orders.points_amount) as total_points,
|
||||
SUM(CASE WHEN orders.source_type = 4 THEN 1 ELSE 0 END) as game_pass_count,
|
||||
SUM(CASE WHEN orders.item_card_id > 0 THEN 1 ELSE 0 END) as item_card_count,
|
||||
SUM(CASE WHEN activities.play_type = 'ichiban' THEN orders.actual_amount ELSE 0 END) as ichiban_spending,
|
||||
SUM(CASE WHEN activities.play_type = 'ichiban' THEN 1 ELSE 0 END) as ichiban_count,
|
||||
SUM(CASE WHEN activities.play_type IN ('infinite', 'box') THEN orders.actual_amount ELSE 0 END) as infinite_spending,
|
||||
SUM(CASE WHEN activities.play_type IN ('infinite', 'box') THEN 1 ELSE 0 END) as infinite_count,
|
||||
SUM(CASE WHEN activities.play_type = 'matching' THEN orders.actual_amount ELSE 0 END) as matching_spending,
|
||||
SUM(CASE WHEN activities.play_type = 'matching' THEN 1 ELSE 0 END) as matching_count
|
||||
FROM `orders` LEFT JOIN activities ON activities.id = orders.activity_id WHERE orders.status = 2 AND orders.created_at >= '2026-01-01 01:01:06.706' AND orders.created_at <= '2026-01-08 01:01:06.706' GROUP BY `orders`.`user_id` ORDER BY total_amount DESC LIMIT 500
|
||||
{"level":"debug","time":"2026-01-08 01:01:31","caller":"logger/logger.go:315","msg":"定时开奖: 开始检查","domain":"mini-chat[fat]","now":"2026-01-08 01:01:31"}
|
||||
{"level":"debug","time":"2026-01-08 01:01:32","caller":"logger/logger.go:315","msg":"定时开奖: 查询到活动","domain":"mini-chat[fat]","count":9}
|
||||
{"level":"debug","time":"2026-01-08 01:01:32","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":52,"play_type":"ichiban","interval":3,"scheduled_time":"2026-01-08T01:03:14.807+08:00","last_settled":"2026-01-08T01:00:14.807+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 01:01:32","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":52,"st":"2026-01-08 01:03:14","now":"2026-01-08 01:01:31","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 01:01:32","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":65,"play_type":"ichiban","interval":3,"scheduled_time":"2026-01-08T01:02:59.385+08:00","last_settled":"2026-01-08T00:59:59.385+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 01:01:32","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":65,"st":"2026-01-08 01:02:59","now":"2026-01-08 01:01:31","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 01:01:32","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":77,"play_type":"ichiban","interval":5,"scheduled_time":"2026-01-08T01:03:44.807+08:00","last_settled":"2026-01-08T00:58:44.807+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 01:01:32","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":77,"st":"2026-01-08 01:03:44","now":"2026-01-08 01:01:31","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 01:01:32","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":79,"play_type":"ichiban","interval":5,"scheduled_time":"2026-01-08T01:05:14.807+08:00","last_settled":"2026-01-08T01:00:14.807+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 01:01:32","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":79,"st":"2026-01-08 01:05:14","now":"2026-01-08 01:01:31","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 01:01:32","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":80,"play_type":"ichiban","interval":10,"scheduled_time":"2026-01-08T01:04:18.148+08:00","last_settled":"2026-01-08T00:54:18.148+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 01:01:32","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":80,"st":"2026-01-08 01:04:18","now":"2026-01-08 01:01:31","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 01:01:32","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":81,"play_type":"ichiban","interval":15,"scheduled_time":"2026-01-08T01:10:14.807+08:00","last_settled":"2026-01-08T00:55:14.807+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 01:01:32","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":81,"st":"2026-01-08 01:10:14","now":"2026-01-08 01:01:31","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 01:01:32","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":82,"play_type":"ichiban","interval":15,"scheduled_time":"2026-01-08T01:10:14.807+08:00","last_settled":"2026-01-08T00:55:14.807+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 01:01:32","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":82,"st":"2026-01-08 01:10:14","now":"2026-01-08 01:01:31","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 01:01:32","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":83,"play_type":"ichiban","interval":30,"scheduled_time":"2026-01-08T01:05:26.489+08:00","last_settled":"2026-01-08T00:35:26.489+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 01:01:32","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":83,"st":"2026-01-08 01:05:26","now":"2026-01-08 01:01:31","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 01:01:32","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":84,"play_type":"ichiban","interval":60,"scheduled_time":"2026-01-08T01:27:44.808+08:00","last_settled":"2026-01-08T00:27:44.808+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 01:01:32","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":84,"st":"2026-01-08 01:27:44","now":"2026-01-08 01:01:31","skip":true}
|
||||
signal: killed
|
||||
397
backend_debug.log
Normal file
397
backend_debug.log
Normal file
@ -0,0 +1,397 @@
|
||||
{"level":"info","time":"2026-01-08 01:32:46","caller":"logger/logger.go:309","msg":"Connected to Redis","domain":"mini-chat[fat]","addr":"118.25.13.43:8379"}
|
||||
|
||||
[32m ____ _ _ _ ____[0m
|
||||
[32m | __ ) (_) _ __ __| | | |__ ___ __ __ / ___| __ _ _ __ ___ ___[0m
|
||||
[32m | _ \ | | | '_ \ / _` | | '_ \ / _ \ \ \/ / | | _ / _` | | '_ ` _ \ / _ \[0m
|
||||
[32m | |_) | | | | | | | | (_| | | |_) | | (_) | > < | |_| | | (_| | | | | | | | | __/[0m
|
||||
[32m |____/ |_| |_| |_| \__,_| |_.__/ \___/ /_/\_\ \____| \__,_| |_| |_| |_| \___|[0m
|
||||
▌ 客户项目: 盲盒游戏
|
||||
▌ 项目版本: Release-2025111111
|
||||
▌ 启动时间: 2026-01-08 01:32:46
|
||||
▌ 运行环境: darwin go1.24.2
|
||||
▌ 服务端口: [:9991]
|
||||
▌ 服务配置: [fat]
|
||||
|
||||
▌ 数据库连接: ✔ 已建立
|
||||
|
||||
{"level":"info","time":"2026-01-08 01:32:46","caller":"logger/logger.go:309","msg":"Task center worker started","domain":"mini-chat[fat]"}
|
||||
{"level":"info","time":"2026-01-08 01:32:46","caller":"logger/logger.go:309","msg":"对对碰自动开奖: 后台任务已启动","domain":"mini-chat[fat]"}
|
||||
{"level":"info","time":"2026-01-08 01:32:46","caller":"logger/logger.go:309","msg":"[抖店定时同步] 定时任务已启动","domain":"mini-chat[fat]"}
|
||||
{"level":"info","time":"2026-01-08 01:32:46","caller":"logger/logger.go:309","msg":"Worker routine started","domain":"mini-chat[fat]","worker_id":4}
|
||||
{"level":"info","time":"2026-01-08 01:32:46","caller":"logger/logger.go:309","msg":"Worker routine started","domain":"mini-chat[fat]","worker_id":1}
|
||||
{"level":"info","time":"2026-01-08 01:32:46","caller":"logger/logger.go:309","msg":"Worker routine started","domain":"mini-chat[fat]","worker_id":2}
|
||||
{"level":"info","time":"2026-01-08 01:32:46","caller":"logger/logger.go:309","msg":"Worker routine started","domain":"mini-chat[fat]","worker_id":0}
|
||||
{"level":"info","time":"2026-01-08 01:32:46","caller":"logger/logger.go:309","msg":"Worker routine started","domain":"mini-chat[fat]","worker_id":3}
|
||||
{"level":"error","time":"2026-01-08 01:32:46","caller":"logger/logger.go:327","msg":"解密配置失败","domain":"mini-chat[fat]","key":"douyin.app_secret","error":"ciphertext is not a multiple of the block size"}
|
||||
{"level":"info","time":"2026-01-08 01:32:46","caller":"logger/logger.go:309","msg":"动态配置加载完成","domain":"mini-chat[fat]","count":26}
|
||||
{"level":"info","time":"2026-01-08 01:33:08","caller":"logger/logger.go:309","msg":"SpendingLeaderboard range: start=2026-01-01 01:33:08.823091 +0800 CST m=-604777.351307833, end=2026-01-08 01:33:08.823091 +0800 CST m=+22.648692167, type=7d","domain":"mini-chat[fat]"}
|
||||
{"level":"info","time":"2026-01-08 01:33:08","caller":"logger/logger.go:309","msg":"SpendingLeaderboard SQL done: count=0","domain":"mini-chat[fat]"}
|
||||
{"level":"info","time":"2026-01-08 01:33:09","caller":"logger/logger.go:309","msg":"SpendingLeaderboard range: start=2026-01-01 01:33:09.794643 +0800 CST m=-604776.379748124, end=2026-01-08 01:33:09.794643 +0800 CST m=+23.620251876, type=7d","domain":"mini-chat[fat]"}
|
||||
{"level":"info","time":"2026-01-08 01:33:09","caller":"logger/logger.go:309","msg":"SpendingLeaderboard SQL done: count=0","domain":"mini-chat[fat]"}
|
||||
{"level":"info","time":"2026-01-08 01:33:10","caller":"logger/logger.go:309","msg":"SpendingLeaderboard range: start=2026-01-01 01:33:10.404066 +0800 CST m=-604775.770320333, end=2026-01-08 01:33:10.404066 +0800 CST m=+24.229679667, type=7d","domain":"mini-chat[fat]"}
|
||||
{"level":"info","time":"2026-01-08 01:33:10","caller":"logger/logger.go:309","msg":"SpendingLeaderboard SQL done: count=0","domain":"mini-chat[fat]"}
|
||||
{"level":"info","time":"2026-01-08 01:33:11","caller":"logger/logger.go:309","msg":"SpendingLeaderboard range: start=2026-01-01 01:33:11.624776 +0800 CST m=-604774.549601249, end=2026-01-08 01:33:11.624776 +0800 CST m=+25.450398751, type=7d","domain":"mini-chat[fat]"}
|
||||
{"level":"info","time":"2026-01-08 01:33:11","caller":"logger/logger.go:309","msg":"SpendingLeaderboard SQL done: count=0","domain":"mini-chat[fat]"}
|
||||
{"level":"debug","time":"2026-01-08 01:33:16","caller":"logger/logger.go:315","msg":"定时开奖: 开始检查","domain":"mini-chat[fat]","now":"2026-01-08 01:33:16"}
|
||||
{"level":"info","time":"2026-01-08 01:33:16","caller":"logger/logger.go:309","msg":"[抖店定时同步] 开始同步","domain":"mini-chat[fat]","interval_minutes":1}
|
||||
{"level":"debug","time":"2026-01-08 01:33:16","caller":"logger/logger.go:315","msg":"定时开奖: 查询到活动","domain":"mini-chat[fat]","count":9}
|
||||
{"level":"debug","time":"2026-01-08 01:33:16","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":52,"play_type":"ichiban","interval":3,"scheduled_time":"2026-01-08T01:33:59.385+08:00","last_settled":"2026-01-08T01:30:59.385+08:00"}
|
||||
[DEBUG] 开始全量同步,共 3 个绑定用户
|
||||
[DEBUG] 正在同步用户 ID: 9018 (昵称: 现实的迪斯蒂法诺, 抖音号: wyl0423333) 的订单...
|
||||
{"level":"debug","time":"2026-01-08 01:33:16","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":52,"st":"2026-01-08 01:33:59","now":"2026-01-08 01:33:16","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 01:33:16","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":65,"play_type":"ichiban","interval":3,"scheduled_time":"2026-01-08T01:33:29.385+08:00","last_settled":"2026-01-08T01:30:29.385+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 01:33:16","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":65,"st":"2026-01-08 01:33:29","now":"2026-01-08 01:33:16","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 01:33:16","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":77,"play_type":"ichiban","interval":5,"scheduled_time":"2026-01-08T01:33:59.385+08:00","last_settled":"2026-01-08T01:28:59.385+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 01:33:16","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":77,"st":"2026-01-08 01:33:59","now":"2026-01-08 01:33:16","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 01:33:16","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":79,"play_type":"ichiban","interval":5,"scheduled_time":"2026-01-08T01:35:59.385+08:00","last_settled":"2026-01-08T01:30:59.385+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 01:33:16","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":79,"st":"2026-01-08 01:35:59","now":"2026-01-08 01:33:16","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 01:33:16","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":80,"play_type":"ichiban","interval":10,"scheduled_time":"2026-01-08T01:34:29.385+08:00","last_settled":"2026-01-08T01:24:29.385+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 01:33:17","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":80,"st":"2026-01-08 01:34:29","now":"2026-01-08 01:33:16","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 01:33:17","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":81,"play_type":"ichiban","interval":15,"scheduled_time":"2026-01-08T01:40:44.808+08:00","last_settled":"2026-01-08T01:25:44.808+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 01:33:17","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":81,"st":"2026-01-08 01:40:44","now":"2026-01-08 01:33:16","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 01:33:17","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":82,"play_type":"ichiban","interval":15,"scheduled_time":"2026-01-08T01:40:44.808+08:00","last_settled":"2026-01-08T01:25:44.808+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 01:33:17","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":82,"st":"2026-01-08 01:40:44","now":"2026-01-08 01:33:16","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 01:33:17","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":83,"play_type":"ichiban","interval":30,"scheduled_time":"2026-01-08T01:35:29.385+08:00","last_settled":"2026-01-08T01:05:29.385+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 01:33:17","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":83,"st":"2026-01-08 01:35:29","now":"2026-01-08 01:33:16","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 01:33:17","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":84,"play_type":"ichiban","interval":60,"scheduled_time":"2026-01-08T02:27:59.386+08:00","last_settled":"2026-01-08T01:27:59.386+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 01:33:17","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":84,"st":"2026-01-08 02:27:59","now":"2026-01-08 01:33:16","skip":true}
|
||||
[DEBUG] 正在同步用户 ID: 9019 (昵称: 约翰掐指一算, 抖音号: xrw200947752) 的订单...
|
||||
[DEBUG] 正在同步用户 ID: 9047 (昵称: 巴乔横扫六合, 抖音号: 请输入您的抖店订单号即可完成绑定) 的订单...
|
||||
{"level":"info","time":"2026-01-08 01:33:21","caller":"logger/logger.go:309","msg":"[抖店同步] 全量同步完成","domain":"mini-chat[fat]","users_count":3,"total_fetched":45,"new_orders":0,"matched_users":45}
|
||||
{"level":"info","time":"2026-01-08 01:33:21","caller":"logger/logger.go:309","msg":"[抖店定时同步] 同步成功","domain":"mini-chat[fat]","total_fetched":45,"new_orders":0,"matched_users":45}
|
||||
{"level":"info","time":"2026-01-08 01:33:21","caller":"logger/logger.go:309","msg":"SpendingLeaderboard range: ALL TIME","domain":"mini-chat[fat]"}
|
||||
{"level":"info","time":"2026-01-08 01:33:22","caller":"logger/logger.go:309","msg":"SpendingLeaderboard SQL done: count=0","domain":"mini-chat[fat]"}
|
||||
{"level":"info","time":"2026-01-08 01:33:22","caller":"logger/logger.go:309","msg":"SpendingLeaderboard range: ALL TIME","domain":"mini-chat[fat]"}
|
||||
{"level":"info","time":"2026-01-08 01:33:22","caller":"logger/logger.go:309","msg":"SpendingLeaderboard SQL done: count=0","domain":"mini-chat[fat]"}
|
||||
|
||||
2026/01/08 01:33:27 /Users/win/aicode/bindbox/bindbox_game/internal/api/admin/dashboard_activity.go:269 Error 1054 (42S22): Unknown column 'products.image' in 'field list'
|
||||
[10.836ms] [rows:-] SELECT
|
||||
activity_draw_logs.id,
|
||||
activity_draw_logs.user_id,
|
||||
users.nickname,
|
||||
users.avatar,
|
||||
activity_reward_settings.product_id,
|
||||
products.name as product_name,
|
||||
products.image as product_image,
|
||||
products.price as product_price,
|
||||
orders.actual_amount as order_amount,
|
||||
activity_draw_logs.created_at
|
||||
FROM `activity_draw_logs` JOIN activity_issues ON activity_issues.id = activity_draw_logs.issue_id LEFT JOIN users ON users.id = activity_draw_logs.user_id LEFT JOIN activity_reward_settings ON activity_reward_settings.id = activity_draw_logs.reward_id LEFT JOIN products ON products.id = activity_reward_settings.product_id LEFT JOIN orders ON orders.id = activity_draw_logs.order_id WHERE activity_issues.activity_id = 88 ORDER BY activity_draw_logs.id DESC LIMIT 10
|
||||
{"level":"error","time":"2026-01-08 01:33:27","caller":"logger/logger.go:327","msg":"GetActivityLogs error: Error 1054 (42S22): Unknown column 'products.image' in 'field list'","domain":"mini-chat[fat]"}
|
||||
{"level":"debug","time":"2026-01-08 01:33:46","caller":"logger/logger.go:315","msg":"定时开奖: 开始检查","domain":"mini-chat[fat]","now":"2026-01-08 01:33:46"}
|
||||
{"level":"debug","time":"2026-01-08 01:33:46","caller":"logger/logger.go:315","msg":"定时开奖: 查询到活动","domain":"mini-chat[fat]","count":9}
|
||||
{"level":"debug","time":"2026-01-08 01:33:46","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":52,"play_type":"ichiban","interval":3,"scheduled_time":"2026-01-08T01:33:59.385+08:00","last_settled":"2026-01-08T01:30:59.385+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 01:33:46","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":52,"st":"2026-01-08 01:33:59","now":"2026-01-08 01:33:46","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 01:33:46","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":65,"play_type":"ichiban","interval":3,"scheduled_time":"2026-01-08T01:36:44.808+08:00","last_settled":"2026-01-08T01:33:44.808+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 01:33:46","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":65,"st":"2026-01-08 01:36:44","now":"2026-01-08 01:33:46","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 01:33:46","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":77,"play_type":"ichiban","interval":5,"scheduled_time":"2026-01-08T01:33:59.385+08:00","last_settled":"2026-01-08T01:28:59.385+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 01:33:46","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":77,"st":"2026-01-08 01:33:59","now":"2026-01-08 01:33:46","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 01:33:46","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":79,"play_type":"ichiban","interval":5,"scheduled_time":"2026-01-08T01:35:59.385+08:00","last_settled":"2026-01-08T01:30:59.385+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 01:33:46","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":79,"st":"2026-01-08 01:35:59","now":"2026-01-08 01:33:46","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 01:33:46","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":80,"play_type":"ichiban","interval":10,"scheduled_time":"2026-01-08T01:34:29.385+08:00","last_settled":"2026-01-08T01:24:29.385+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 01:33:47","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":80,"st":"2026-01-08 01:34:29","now":"2026-01-08 01:33:46","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 01:33:47","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":81,"play_type":"ichiban","interval":15,"scheduled_time":"2026-01-08T01:40:44.808+08:00","last_settled":"2026-01-08T01:25:44.808+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 01:33:47","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":81,"st":"2026-01-08 01:40:44","now":"2026-01-08 01:33:46","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 01:33:47","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":82,"play_type":"ichiban","interval":15,"scheduled_time":"2026-01-08T01:40:44.808+08:00","last_settled":"2026-01-08T01:25:44.808+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 01:33:47","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":82,"st":"2026-01-08 01:40:44","now":"2026-01-08 01:33:46","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 01:33:47","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":83,"play_type":"ichiban","interval":30,"scheduled_time":"2026-01-08T01:35:29.385+08:00","last_settled":"2026-01-08T01:05:29.385+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 01:33:47","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":83,"st":"2026-01-08 01:35:29","now":"2026-01-08 01:33:46","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 01:33:47","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":84,"play_type":"ichiban","interval":60,"scheduled_time":"2026-01-08T02:27:59.386+08:00","last_settled":"2026-01-08T01:27:59.386+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 01:33:47","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":84,"st":"2026-01-08 02:27:59","now":"2026-01-08 01:33:46","skip":true}
|
||||
|
||||
2026/01/08 01:34:09 /Users/win/aicode/bindbox/bindbox_game/internal/api/admin/dashboard_activity.go:269 Error 1054 (42S22): Unknown column 'products.image' in 'field list'
|
||||
[11.527ms] [rows:-] SELECT
|
||||
activity_draw_logs.id,
|
||||
activity_draw_logs.user_id,
|
||||
users.nickname,
|
||||
users.avatar,
|
||||
activity_reward_settings.product_id,
|
||||
products.name as product_name,
|
||||
products.image as product_image,
|
||||
products.price as product_price,
|
||||
orders.actual_amount as order_amount,
|
||||
activity_draw_logs.created_at
|
||||
FROM `activity_draw_logs` JOIN activity_issues ON activity_issues.id = activity_draw_logs.issue_id LEFT JOIN users ON users.id = activity_draw_logs.user_id LEFT JOIN activity_reward_settings ON activity_reward_settings.id = activity_draw_logs.reward_id LEFT JOIN products ON products.id = activity_reward_settings.product_id LEFT JOIN orders ON orders.id = activity_draw_logs.order_id WHERE activity_issues.activity_id = 88 ORDER BY activity_draw_logs.id DESC LIMIT 10
|
||||
{"level":"error","time":"2026-01-08 01:34:09","caller":"logger/logger.go:327","msg":"GetActivityLogs error: Error 1054 (42S22): Unknown column 'products.image' in 'field list'","domain":"mini-chat[fat]"}
|
||||
{"level":"debug","time":"2026-01-08 01:34:16","caller":"logger/logger.go:315","msg":"定时开奖: 开始检查","domain":"mini-chat[fat]","now":"2026-01-08 01:34:16"}
|
||||
{"level":"debug","time":"2026-01-08 01:34:16","caller":"logger/logger.go:315","msg":"定时开奖: 查询到活动","domain":"mini-chat[fat]","count":9}
|
||||
{"level":"debug","time":"2026-01-08 01:34:16","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":52,"play_type":"ichiban","interval":3,"scheduled_time":"2026-01-08T01:37:14.807+08:00","last_settled":"2026-01-08T01:34:14.807+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 01:34:16","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":52,"st":"2026-01-08 01:37:14","now":"2026-01-08 01:34:16","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 01:34:16","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":65,"play_type":"ichiban","interval":3,"scheduled_time":"2026-01-08T01:36:44.808+08:00","last_settled":"2026-01-08T01:33:44.808+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 01:34:16","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":65,"st":"2026-01-08 01:36:44","now":"2026-01-08 01:34:16","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 01:34:16","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":77,"play_type":"ichiban","interval":5,"scheduled_time":"2026-01-08T01:39:14.807+08:00","last_settled":"2026-01-08T01:34:14.807+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 01:34:16","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":77,"st":"2026-01-08 01:39:14","now":"2026-01-08 01:34:16","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 01:34:16","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":79,"play_type":"ichiban","interval":5,"scheduled_time":"2026-01-08T01:35:59.385+08:00","last_settled":"2026-01-08T01:30:59.385+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 01:34:16","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":79,"st":"2026-01-08 01:35:59","now":"2026-01-08 01:34:16","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 01:34:16","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":80,"play_type":"ichiban","interval":10,"scheduled_time":"2026-01-08T01:34:29.385+08:00","last_settled":"2026-01-08T01:24:29.385+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 01:34:16","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":80,"st":"2026-01-08 01:34:29","now":"2026-01-08 01:34:16","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 01:34:17","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":81,"play_type":"ichiban","interval":15,"scheduled_time":"2026-01-08T01:40:44.808+08:00","last_settled":"2026-01-08T01:25:44.808+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 01:34:17","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":81,"st":"2026-01-08 01:40:44","now":"2026-01-08 01:34:16","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 01:34:17","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":82,"play_type":"ichiban","interval":15,"scheduled_time":"2026-01-08T01:40:44.808+08:00","last_settled":"2026-01-08T01:25:44.808+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 01:34:17","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":82,"st":"2026-01-08 01:40:44","now":"2026-01-08 01:34:16","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 01:34:17","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":83,"play_type":"ichiban","interval":30,"scheduled_time":"2026-01-08T01:35:29.385+08:00","last_settled":"2026-01-08T01:05:29.385+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 01:34:17","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":83,"st":"2026-01-08 01:35:29","now":"2026-01-08 01:34:16","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 01:34:17","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":84,"play_type":"ichiban","interval":60,"scheduled_time":"2026-01-08T02:27:59.386+08:00","last_settled":"2026-01-08T01:27:59.386+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 01:34:17","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":84,"st":"2026-01-08 02:27:59","now":"2026-01-08 01:34:16","skip":true}
|
||||
{"level":"info","time":"2026-01-08 01:34:21","caller":"logger/logger.go:309","msg":"[抖店定时同步] 开始同步","domain":"mini-chat[fat]","interval_minutes":1}
|
||||
[DEBUG] 开始全量同步,共 3 个绑定用户
|
||||
[DEBUG] 正在同步用户 ID: 9018 (昵称: 现实的迪斯蒂法诺, 抖音号: wyl0423333) 的订单...
|
||||
{"level":"info","time":"2026-01-08 01:34:22","caller":"logger/logger.go:309","msg":"SpendingLeaderboard range: ALL TIME","domain":"mini-chat[fat]"}
|
||||
{"level":"info","time":"2026-01-08 01:34:22","caller":"logger/logger.go:309","msg":"SpendingLeaderboard SQL done: count=0","domain":"mini-chat[fat]"}
|
||||
{"level":"info","time":"2026-01-08 01:34:23","caller":"logger/logger.go:309","msg":"SpendingLeaderboard range: ALL TIME","domain":"mini-chat[fat]"}
|
||||
{"level":"info","time":"2026-01-08 01:34:23","caller":"logger/logger.go:309","msg":"SpendingLeaderboard SQL done: count=0","domain":"mini-chat[fat]"}
|
||||
[DEBUG] 正在同步用户 ID: 9019 (昵称: 约翰掐指一算, 抖音号: xrw200947752) 的订单...
|
||||
[DEBUG] 正在同步用户 ID: 9047 (昵称: 巴乔横扫六合, 抖音号: 请输入您的抖店订单号即可完成绑定) 的订单...
|
||||
{"level":"info","time":"2026-01-08 01:34:26","caller":"logger/logger.go:309","msg":"[抖店同步] 全量同步完成","domain":"mini-chat[fat]","users_count":3,"total_fetched":45,"new_orders":0,"matched_users":45}
|
||||
{"level":"info","time":"2026-01-08 01:34:26","caller":"logger/logger.go:309","msg":"[抖店定时同步] 同步成功","domain":"mini-chat[fat]","total_fetched":45,"new_orders":0,"matched_users":45}
|
||||
{"level":"debug","time":"2026-01-08 01:34:46","caller":"logger/logger.go:315","msg":"定时开奖: 开始检查","domain":"mini-chat[fat]","now":"2026-01-08 01:34:46"}
|
||||
{"level":"debug","time":"2026-01-08 01:34:46","caller":"logger/logger.go:315","msg":"定时开奖: 查询到活动","domain":"mini-chat[fat]","count":9}
|
||||
{"level":"debug","time":"2026-01-08 01:34:46","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":52,"play_type":"ichiban","interval":3,"scheduled_time":"2026-01-08T01:37:14.807+08:00","last_settled":"2026-01-08T01:34:14.807+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 01:34:46","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":52,"st":"2026-01-08 01:37:14","now":"2026-01-08 01:34:46","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 01:34:46","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":65,"play_type":"ichiban","interval":3,"scheduled_time":"2026-01-08T01:36:44.808+08:00","last_settled":"2026-01-08T01:33:44.808+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 01:34:46","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":65,"st":"2026-01-08 01:36:44","now":"2026-01-08 01:34:46","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 01:34:46","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":77,"play_type":"ichiban","interval":5,"scheduled_time":"2026-01-08T01:39:14.807+08:00","last_settled":"2026-01-08T01:34:14.807+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 01:34:46","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":77,"st":"2026-01-08 01:39:14","now":"2026-01-08 01:34:46","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 01:34:46","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":79,"play_type":"ichiban","interval":5,"scheduled_time":"2026-01-08T01:35:59.385+08:00","last_settled":"2026-01-08T01:30:59.385+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 01:34:46","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":79,"st":"2026-01-08 01:35:59","now":"2026-01-08 01:34:46","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 01:34:46","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":80,"play_type":"ichiban","interval":10,"scheduled_time":"2026-01-08T01:44:44.807+08:00","last_settled":"2026-01-08T01:34:44.807+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 01:34:47","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":80,"st":"2026-01-08 01:44:44","now":"2026-01-08 01:34:46","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 01:34:47","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":81,"play_type":"ichiban","interval":15,"scheduled_time":"2026-01-08T01:40:44.808+08:00","last_settled":"2026-01-08T01:25:44.808+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 01:34:47","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":81,"st":"2026-01-08 01:40:44","now":"2026-01-08 01:34:46","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 01:34:47","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":82,"play_type":"ichiban","interval":15,"scheduled_time":"2026-01-08T01:40:44.808+08:00","last_settled":"2026-01-08T01:25:44.808+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 01:34:47","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":82,"st":"2026-01-08 01:40:44","now":"2026-01-08 01:34:46","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 01:34:47","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":83,"play_type":"ichiban","interval":30,"scheduled_time":"2026-01-08T01:35:29.385+08:00","last_settled":"2026-01-08T01:05:29.385+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 01:34:47","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":83,"st":"2026-01-08 01:35:29","now":"2026-01-08 01:34:46","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 01:34:47","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":84,"play_type":"ichiban","interval":60,"scheduled_time":"2026-01-08T02:27:59.386+08:00","last_settled":"2026-01-08T01:27:59.386+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 01:34:47","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":84,"st":"2026-01-08 02:27:59","now":"2026-01-08 01:34:46","skip":true}
|
||||
{"level":"info","time":"2026-01-08 01:34:54","caller":"logger/logger.go:309","msg":"SpendingLeaderboard range: ALL TIME","domain":"mini-chat[fat]"}
|
||||
{"level":"info","time":"2026-01-08 01:34:54","caller":"logger/logger.go:309","msg":"SpendingLeaderboard SQL done: count=0","domain":"mini-chat[fat]"}
|
||||
{"level":"debug","time":"2026-01-08 01:35:16","caller":"logger/logger.go:315","msg":"定时开奖: 开始检查","domain":"mini-chat[fat]","now":"2026-01-08 01:35:16"}
|
||||
{"level":"debug","time":"2026-01-08 01:35:16","caller":"logger/logger.go:315","msg":"定时开奖: 查询到活动","domain":"mini-chat[fat]","count":9}
|
||||
{"level":"debug","time":"2026-01-08 01:35:16","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":52,"play_type":"ichiban","interval":3,"scheduled_time":"2026-01-08T01:37:14.807+08:00","last_settled":"2026-01-08T01:34:14.807+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 01:35:16","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":52,"st":"2026-01-08 01:37:14","now":"2026-01-08 01:35:16","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 01:35:16","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":65,"play_type":"ichiban","interval":3,"scheduled_time":"2026-01-08T01:36:44.808+08:00","last_settled":"2026-01-08T01:33:44.808+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 01:35:16","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":65,"st":"2026-01-08 01:36:44","now":"2026-01-08 01:35:16","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 01:35:16","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":77,"play_type":"ichiban","interval":5,"scheduled_time":"2026-01-08T01:39:14.807+08:00","last_settled":"2026-01-08T01:34:14.807+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 01:35:16","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":77,"st":"2026-01-08 01:39:14","now":"2026-01-08 01:35:16","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 01:35:16","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":79,"play_type":"ichiban","interval":5,"scheduled_time":"2026-01-08T01:35:59.385+08:00","last_settled":"2026-01-08T01:30:59.385+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 01:35:16","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":79,"st":"2026-01-08 01:35:59","now":"2026-01-08 01:35:16","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 01:35:16","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":80,"play_type":"ichiban","interval":10,"scheduled_time":"2026-01-08T01:44:44.807+08:00","last_settled":"2026-01-08T01:34:44.807+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 01:35:16","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":80,"st":"2026-01-08 01:44:44","now":"2026-01-08 01:35:16","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 01:35:17","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":81,"play_type":"ichiban","interval":15,"scheduled_time":"2026-01-08T01:40:44.808+08:00","last_settled":"2026-01-08T01:25:44.808+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 01:35:17","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":81,"st":"2026-01-08 01:40:44","now":"2026-01-08 01:35:16","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 01:35:17","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":82,"play_type":"ichiban","interval":15,"scheduled_time":"2026-01-08T01:40:44.808+08:00","last_settled":"2026-01-08T01:25:44.808+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 01:35:17","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":82,"st":"2026-01-08 01:40:44","now":"2026-01-08 01:35:16","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 01:35:17","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":83,"play_type":"ichiban","interval":30,"scheduled_time":"2026-01-08T01:35:29.385+08:00","last_settled":"2026-01-08T01:05:29.385+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 01:35:17","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":83,"st":"2026-01-08 01:35:29","now":"2026-01-08 01:35:16","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 01:35:17","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":84,"play_type":"ichiban","interval":60,"scheduled_time":"2026-01-08T02:27:59.386+08:00","last_settled":"2026-01-08T01:27:59.386+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 01:35:17","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":84,"st":"2026-01-08 02:27:59","now":"2026-01-08 01:35:16","skip":true}
|
||||
{"level":"info","time":"2026-01-08 01:35:26","caller":"logger/logger.go:309","msg":"[抖店定时同步] 开始同步","domain":"mini-chat[fat]","interval_minutes":1}
|
||||
[DEBUG] 开始全量同步,共 3 个绑定用户
|
||||
[DEBUG] 正在同步用户 ID: 9018 (昵称: 现实的迪斯蒂法诺, 抖音号: wyl0423333) 的订单...
|
||||
[DEBUG] 正在同步用户 ID: 9019 (昵称: 约翰掐指一算, 抖音号: xrw200947752) 的订单...
|
||||
[DEBUG] 正在同步用户 ID: 9047 (昵称: 巴乔横扫六合, 抖音号: 请输入您的抖店订单号即可完成绑定) 的订单...
|
||||
{"level":"info","time":"2026-01-08 01:35:31","caller":"logger/logger.go:309","msg":"[抖店同步] 全量同步完成","domain":"mini-chat[fat]","users_count":3,"total_fetched":45,"new_orders":0,"matched_users":45}
|
||||
{"level":"info","time":"2026-01-08 01:35:31","caller":"logger/logger.go:309","msg":"[抖店定时同步] 同步成功","domain":"mini-chat[fat]","total_fetched":45,"new_orders":0,"matched_users":45}
|
||||
{"level":"debug","time":"2026-01-08 01:35:46","caller":"logger/logger.go:315","msg":"定时开奖: 开始检查","domain":"mini-chat[fat]","now":"2026-01-08 01:35:46"}
|
||||
{"level":"debug","time":"2026-01-08 01:35:46","caller":"logger/logger.go:315","msg":"定时开奖: 查询到活动","domain":"mini-chat[fat]","count":9}
|
||||
{"level":"debug","time":"2026-01-08 01:35:46","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":52,"play_type":"ichiban","interval":3,"scheduled_time":"2026-01-08T01:37:14.807+08:00","last_settled":"2026-01-08T01:34:14.807+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 01:35:46","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":52,"st":"2026-01-08 01:37:14","now":"2026-01-08 01:35:46","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 01:35:46","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":65,"play_type":"ichiban","interval":3,"scheduled_time":"2026-01-08T01:36:44.808+08:00","last_settled":"2026-01-08T01:33:44.808+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 01:35:46","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":65,"st":"2026-01-08 01:36:44","now":"2026-01-08 01:35:46","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 01:35:46","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":77,"play_type":"ichiban","interval":5,"scheduled_time":"2026-01-08T01:39:14.807+08:00","last_settled":"2026-01-08T01:34:14.807+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 01:35:46","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":77,"st":"2026-01-08 01:39:14","now":"2026-01-08 01:35:46","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 01:35:46","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":79,"play_type":"ichiban","interval":5,"scheduled_time":"2026-01-08T01:35:59.385+08:00","last_settled":"2026-01-08T01:30:59.385+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 01:35:46","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":79,"st":"2026-01-08 01:35:59","now":"2026-01-08 01:35:46","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 01:35:46","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":80,"play_type":"ichiban","interval":10,"scheduled_time":"2026-01-08T01:44:44.807+08:00","last_settled":"2026-01-08T01:34:44.807+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 01:35:46","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":80,"st":"2026-01-08 01:44:44","now":"2026-01-08 01:35:46","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 01:35:47","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":81,"play_type":"ichiban","interval":15,"scheduled_time":"2026-01-08T01:40:44.808+08:00","last_settled":"2026-01-08T01:25:44.808+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 01:35:47","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":81,"st":"2026-01-08 01:40:44","now":"2026-01-08 01:35:46","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 01:35:47","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":82,"play_type":"ichiban","interval":15,"scheduled_time":"2026-01-08T01:40:44.808+08:00","last_settled":"2026-01-08T01:25:44.808+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 01:35:47","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":82,"st":"2026-01-08 01:40:44","now":"2026-01-08 01:35:46","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 01:35:47","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":83,"play_type":"ichiban","interval":30,"scheduled_time":"2026-01-08T02:05:29.386+08:00","last_settled":"2026-01-08T01:35:29.386+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 01:35:47","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":83,"st":"2026-01-08 02:05:29","now":"2026-01-08 01:35:46","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 01:35:47","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":84,"play_type":"ichiban","interval":60,"scheduled_time":"2026-01-08T02:27:59.386+08:00","last_settled":"2026-01-08T01:27:59.386+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 01:35:47","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":84,"st":"2026-01-08 02:27:59","now":"2026-01-08 01:35:46","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 01:36:16","caller":"logger/logger.go:315","msg":"定时开奖: 开始检查","domain":"mini-chat[fat]","now":"2026-01-08 01:36:16"}
|
||||
{"level":"debug","time":"2026-01-08 01:36:16","caller":"logger/logger.go:315","msg":"定时开奖: 查询到活动","domain":"mini-chat[fat]","count":9}
|
||||
{"level":"debug","time":"2026-01-08 01:36:16","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":52,"play_type":"ichiban","interval":3,"scheduled_time":"2026-01-08T01:37:14.807+08:00","last_settled":"2026-01-08T01:34:14.807+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 01:36:16","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":52,"st":"2026-01-08 01:37:14","now":"2026-01-08 01:36:16","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 01:36:16","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":65,"play_type":"ichiban","interval":3,"scheduled_time":"2026-01-08T01:36:44.808+08:00","last_settled":"2026-01-08T01:33:44.808+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 01:36:16","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":65,"st":"2026-01-08 01:36:44","now":"2026-01-08 01:36:16","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 01:36:16","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":77,"play_type":"ichiban","interval":5,"scheduled_time":"2026-01-08T01:39:14.807+08:00","last_settled":"2026-01-08T01:34:14.807+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 01:36:16","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":77,"st":"2026-01-08 01:39:14","now":"2026-01-08 01:36:16","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 01:36:16","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":79,"play_type":"ichiban","interval":5,"scheduled_time":"2026-01-08T01:41:14.808+08:00","last_settled":"2026-01-08T01:36:14.808+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 01:36:16","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":79,"st":"2026-01-08 01:41:14","now":"2026-01-08 01:36:16","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 01:36:16","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":80,"play_type":"ichiban","interval":10,"scheduled_time":"2026-01-08T01:44:44.807+08:00","last_settled":"2026-01-08T01:34:44.807+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 01:36:16","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":80,"st":"2026-01-08 01:44:44","now":"2026-01-08 01:36:16","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 01:36:17","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":81,"play_type":"ichiban","interval":15,"scheduled_time":"2026-01-08T01:40:44.808+08:00","last_settled":"2026-01-08T01:25:44.808+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 01:36:17","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":81,"st":"2026-01-08 01:40:44","now":"2026-01-08 01:36:16","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 01:36:17","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":82,"play_type":"ichiban","interval":15,"scheduled_time":"2026-01-08T01:40:44.808+08:00","last_settled":"2026-01-08T01:25:44.808+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 01:36:17","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":82,"st":"2026-01-08 01:40:44","now":"2026-01-08 01:36:16","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 01:36:17","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":83,"play_type":"ichiban","interval":30,"scheduled_time":"2026-01-08T02:05:29.386+08:00","last_settled":"2026-01-08T01:35:29.386+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 01:36:17","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":83,"st":"2026-01-08 02:05:29","now":"2026-01-08 01:36:16","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 01:36:17","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":84,"play_type":"ichiban","interval":60,"scheduled_time":"2026-01-08T02:27:59.386+08:00","last_settled":"2026-01-08T01:27:59.386+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 01:36:17","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":84,"st":"2026-01-08 02:27:59","now":"2026-01-08 01:36:16","skip":true}
|
||||
{"level":"info","time":"2026-01-08 01:36:23","caller":"logger/logger.go:309","msg":"SpendingLeaderboard range: ALL TIME","domain":"mini-chat[fat]"}
|
||||
{"level":"info","time":"2026-01-08 01:36:23","caller":"logger/logger.go:309","msg":"SpendingLeaderboard SQL done: count=0","domain":"mini-chat[fat]"}
|
||||
{"level":"info","time":"2026-01-08 01:36:24","caller":"logger/logger.go:309","msg":"SpendingLeaderboard range: ALL TIME","domain":"mini-chat[fat]"}
|
||||
{"level":"info","time":"2026-01-08 01:36:24","caller":"logger/logger.go:309","msg":"SpendingLeaderboard SQL done: count=0","domain":"mini-chat[fat]"}
|
||||
{"level":"info","time":"2026-01-08 01:36:24","caller":"logger/logger.go:309","msg":"SpendingLeaderboard range: ALL TIME","domain":"mini-chat[fat]"}
|
||||
{"level":"info","time":"2026-01-08 01:36:24","caller":"logger/logger.go:309","msg":"SpendingLeaderboard SQL done: count=0","domain":"mini-chat[fat]"}
|
||||
{"level":"info","time":"2026-01-08 01:36:25","caller":"logger/logger.go:309","msg":"SpendingLeaderboard range: ALL TIME","domain":"mini-chat[fat]"}
|
||||
{"level":"info","time":"2026-01-08 01:36:26","caller":"logger/logger.go:309","msg":"SpendingLeaderboard SQL done: count=0","domain":"mini-chat[fat]"}
|
||||
{"level":"info","time":"2026-01-08 01:36:31","caller":"logger/logger.go:309","msg":"SpendingLeaderboard range: start=2026-01-08 00:00:00 +0800 CST, end=2026-01-08 23:59:59 +0800 CST, type=today","domain":"mini-chat[fat]"}
|
||||
{"level":"info","time":"2026-01-08 01:36:31","caller":"logger/logger.go:309","msg":"SpendingLeaderboard SQL done: count=0","domain":"mini-chat[fat]"}
|
||||
{"level":"info","time":"2026-01-08 01:36:31","caller":"logger/logger.go:309","msg":"[抖店定时同步] 开始同步","domain":"mini-chat[fat]","interval_minutes":1}
|
||||
[DEBUG] 开始全量同步,共 3 个绑定用户
|
||||
[DEBUG] 正在同步用户 ID: 9018 (昵称: 现实的迪斯蒂法诺, 抖音号: wyl0423333) 的订单...
|
||||
{"level":"info","time":"2026-01-08 01:36:32","caller":"logger/logger.go:309","msg":"SpendingLeaderboard range: start=2026-01-01 01:36:32.749472 +0800 CST m=-604573.445416541, end=2026-01-08 01:36:32.749472 +0800 CST m=+226.554583459, type=7d","domain":"mini-chat[fat]"}
|
||||
{"level":"info","time":"2026-01-08 01:36:32","caller":"logger/logger.go:309","msg":"SpendingLeaderboard SQL done: count=0","domain":"mini-chat[fat]"}
|
||||
[DEBUG] 正在同步用户 ID: 9019 (昵称: 约翰掐指一算, 抖音号: xrw200947752) 的订单...
|
||||
[DEBUG] 正在同步用户 ID: 9047 (昵称: 巴乔横扫六合, 抖音号: 请输入您的抖店订单号即可完成绑定) 的订单...
|
||||
{"level":"info","time":"2026-01-08 01:36:35","caller":"logger/logger.go:309","msg":"[抖店同步] 全量同步完成","domain":"mini-chat[fat]","users_count":3,"total_fetched":45,"new_orders":0,"matched_users":45}
|
||||
{"level":"info","time":"2026-01-08 01:36:35","caller":"logger/logger.go:309","msg":"[抖店定时同步] 同步成功","domain":"mini-chat[fat]","total_fetched":45,"new_orders":0,"matched_users":45}
|
||||
{"level":"debug","time":"2026-01-08 01:36:46","caller":"logger/logger.go:315","msg":"定时开奖: 开始检查","domain":"mini-chat[fat]","now":"2026-01-08 01:36:46"}
|
||||
{"level":"debug","time":"2026-01-08 01:36:46","caller":"logger/logger.go:315","msg":"定时开奖: 查询到活动","domain":"mini-chat[fat]","count":9}
|
||||
{"level":"debug","time":"2026-01-08 01:36:46","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":52,"play_type":"ichiban","interval":3,"scheduled_time":"2026-01-08T01:37:14.807+08:00","last_settled":"2026-01-08T01:34:14.807+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 01:36:46","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":52,"st":"2026-01-08 01:37:14","now":"2026-01-08 01:36:46","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 01:36:46","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":65,"play_type":"ichiban","interval":3,"scheduled_time":"2026-01-08T01:36:44.808+08:00","last_settled":"2026-01-08T01:33:44.808+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 01:36:46","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":65,"st":"2026-01-08 01:36:44","now":"2026-01-08 01:36:46","skip":false}
|
||||
{"level":"debug","time":"2026-01-08 01:36:46","caller":"logger/logger.go:315","msg":"定时开奖: 查询订单范围","domain":"mini-chat[fat]","id":65,"last":"2026-01-08 01:33:44","now":"2026-01-08 01:36:46"}
|
||||
{"level":"debug","time":"2026-01-08 01:36:46","caller":"logger/logger.go:315","msg":"定时开奖: 查询到订单","domain":"mini-chat[fat]","id":65,"count":0,"min":1}
|
||||
{"level":"info","time":"2026-01-08 01:36:46","caller":"logger/logger.go:309","msg":"定时开奖: 人数满足,开始开奖处理","domain":"mini-chat[fat]","id":65}
|
||||
{"level":"info","time":"2026-01-08 01:36:46","caller":"logger/logger.go:309","msg":"定时开奖: 更新活动下次结算时间","domain":"mini-chat[fat]","id":65,"last":"2026-01-08 01:36:46","next":"2026-01-08 01:39:46"}
|
||||
{"level":"debug","time":"2026-01-08 01:36:47","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":77,"play_type":"ichiban","interval":5,"scheduled_time":"2026-01-08T01:39:14.807+08:00","last_settled":"2026-01-08T01:34:14.807+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 01:36:47","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":77,"st":"2026-01-08 01:39:14","now":"2026-01-08 01:36:46","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 01:36:47","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":79,"play_type":"ichiban","interval":5,"scheduled_time":"2026-01-08T01:41:14.808+08:00","last_settled":"2026-01-08T01:36:14.808+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 01:36:47","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":79,"st":"2026-01-08 01:41:14","now":"2026-01-08 01:36:46","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 01:36:47","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":80,"play_type":"ichiban","interval":10,"scheduled_time":"2026-01-08T01:44:44.807+08:00","last_settled":"2026-01-08T01:34:44.807+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 01:36:47","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":80,"st":"2026-01-08 01:44:44","now":"2026-01-08 01:36:46","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 01:36:47","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":81,"play_type":"ichiban","interval":15,"scheduled_time":"2026-01-08T01:40:44.808+08:00","last_settled":"2026-01-08T01:25:44.808+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 01:36:47","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":81,"st":"2026-01-08 01:40:44","now":"2026-01-08 01:36:46","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 01:36:47","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":82,"play_type":"ichiban","interval":15,"scheduled_time":"2026-01-08T01:40:44.808+08:00","last_settled":"2026-01-08T01:25:44.808+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 01:36:47","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":82,"st":"2026-01-08 01:40:44","now":"2026-01-08 01:36:46","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 01:36:47","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":83,"play_type":"ichiban","interval":30,"scheduled_time":"2026-01-08T02:05:29.386+08:00","last_settled":"2026-01-08T01:35:29.386+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 01:36:47","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":83,"st":"2026-01-08 02:05:29","now":"2026-01-08 01:36:46","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 01:36:47","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":84,"play_type":"ichiban","interval":60,"scheduled_time":"2026-01-08T02:27:59.386+08:00","last_settled":"2026-01-08T01:27:59.386+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 01:36:47","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":84,"st":"2026-01-08 02:27:59","now":"2026-01-08 01:36:46","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 01:37:16","caller":"logger/logger.go:315","msg":"定时开奖: 开始检查","domain":"mini-chat[fat]","now":"2026-01-08 01:37:16"}
|
||||
{"level":"debug","time":"2026-01-08 01:37:16","caller":"logger/logger.go:315","msg":"定时开奖: 查询到活动","domain":"mini-chat[fat]","count":9}
|
||||
{"level":"debug","time":"2026-01-08 01:37:16","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":52,"play_type":"ichiban","interval":3,"scheduled_time":"2026-01-08T01:40:14.807+08:00","last_settled":"2026-01-08T01:37:14.807+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 01:37:16","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":52,"st":"2026-01-08 01:40:14","now":"2026-01-08 01:37:16","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 01:37:16","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":65,"play_type":"ichiban","interval":3,"scheduled_time":"2026-01-08T01:39:46.48+08:00","last_settled":"2026-01-08T01:36:46.48+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 01:37:16","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":65,"st":"2026-01-08 01:39:46","now":"2026-01-08 01:37:16","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 01:37:16","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":77,"play_type":"ichiban","interval":5,"scheduled_time":"2026-01-08T01:39:14.807+08:00","last_settled":"2026-01-08T01:34:14.807+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 01:37:16","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":77,"st":"2026-01-08 01:39:14","now":"2026-01-08 01:37:16","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 01:37:16","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":79,"play_type":"ichiban","interval":5,"scheduled_time":"2026-01-08T01:41:14.808+08:00","last_settled":"2026-01-08T01:36:14.808+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 01:37:16","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":79,"st":"2026-01-08 01:41:14","now":"2026-01-08 01:37:16","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 01:37:16","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":80,"play_type":"ichiban","interval":10,"scheduled_time":"2026-01-08T01:44:44.807+08:00","last_settled":"2026-01-08T01:34:44.807+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 01:37:17","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":80,"st":"2026-01-08 01:44:44","now":"2026-01-08 01:37:16","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 01:37:17","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":81,"play_type":"ichiban","interval":15,"scheduled_time":"2026-01-08T01:40:44.808+08:00","last_settled":"2026-01-08T01:25:44.808+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 01:37:17","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":81,"st":"2026-01-08 01:40:44","now":"2026-01-08 01:37:16","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 01:37:17","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":82,"play_type":"ichiban","interval":15,"scheduled_time":"2026-01-08T01:40:44.808+08:00","last_settled":"2026-01-08T01:25:44.808+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 01:37:17","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":82,"st":"2026-01-08 01:40:44","now":"2026-01-08 01:37:16","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 01:37:17","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":83,"play_type":"ichiban","interval":30,"scheduled_time":"2026-01-08T02:05:29.386+08:00","last_settled":"2026-01-08T01:35:29.386+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 01:37:17","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":83,"st":"2026-01-08 02:05:29","now":"2026-01-08 01:37:16","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 01:37:17","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":84,"play_type":"ichiban","interval":60,"scheduled_time":"2026-01-08T02:27:59.386+08:00","last_settled":"2026-01-08T01:27:59.386+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 01:37:17","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":84,"st":"2026-01-08 02:27:59","now":"2026-01-08 01:37:16","skip":true}
|
||||
{"level":"info","time":"2026-01-08 01:37:24","caller":"logger/logger.go:309","msg":"SpendingLeaderboard range: start=2026-01-01 01:37:24.748226 +0800 CST m=-604521.447255708, end=2026-01-08 01:37:24.748226 +0800 CST m=+278.552744292, type=7d","domain":"mini-chat[fat]"}
|
||||
{"level":"info","time":"2026-01-08 01:37:24","caller":"logger/logger.go:309","msg":"SpendingLeaderboard SQL done: count=0","domain":"mini-chat[fat]"}
|
||||
{"level":"info","time":"2026-01-08 01:37:25","caller":"logger/logger.go:309","msg":"SpendingLeaderboard range: start=2026-01-01 01:37:25.231434 +0800 CST m=-604520.964047291, end=2026-01-08 01:37:25.231434 +0800 CST m=+279.035952709, type=7d","domain":"mini-chat[fat]"}
|
||||
{"level":"info","time":"2026-01-08 01:37:25","caller":"logger/logger.go:309","msg":"SpendingLeaderboard SQL done: count=0","domain":"mini-chat[fat]"}
|
||||
{"level":"info","time":"2026-01-08 01:37:25","caller":"logger/logger.go:309","msg":"SpendingLeaderboard range: start=2026-01-01 01:37:25.639354 +0800 CST m=-604520.556125666, end=2026-01-08 01:37:25.639354 +0800 CST m=+279.443874334, type=7d","domain":"mini-chat[fat]"}
|
||||
{"level":"info","time":"2026-01-08 01:37:25","caller":"logger/logger.go:309","msg":"SpendingLeaderboard SQL done: count=0","domain":"mini-chat[fat]"}
|
||||
|
||||
2026/01/08 01:37:28 /Users/win/aicode/bindbox/bindbox_game/internal/api/admin/dashboard_activity.go:269 Error 1054 (42S22): Unknown column 'products.image' in 'field list'
|
||||
[16.963ms] [rows:-] SELECT
|
||||
activity_draw_logs.id,
|
||||
activity_draw_logs.user_id,
|
||||
users.nickname,
|
||||
users.avatar,
|
||||
activity_reward_settings.product_id,
|
||||
products.name as product_name,
|
||||
products.image as product_image,
|
||||
products.price as product_price,
|
||||
orders.actual_amount as order_amount,
|
||||
activity_draw_logs.created_at
|
||||
FROM `activity_draw_logs` JOIN activity_issues ON activity_issues.id = activity_draw_logs.issue_id LEFT JOIN users ON users.id = activity_draw_logs.user_id LEFT JOIN activity_reward_settings ON activity_reward_settings.id = activity_draw_logs.reward_id LEFT JOIN products ON products.id = activity_reward_settings.product_id LEFT JOIN orders ON orders.id = activity_draw_logs.order_id WHERE activity_issues.activity_id = 89 ORDER BY activity_draw_logs.id DESC LIMIT 10
|
||||
{"level":"error","time":"2026-01-08 01:37:28","caller":"logger/logger.go:327","msg":"GetActivityLogs error: Error 1054 (42S22): Unknown column 'products.image' in 'field list'","domain":"mini-chat[fat]"}
|
||||
{"level":"info","time":"2026-01-08 01:37:35","caller":"logger/logger.go:309","msg":"[抖店定时同步] 开始同步","domain":"mini-chat[fat]","interval_minutes":1}
|
||||
[DEBUG] 开始全量同步,共 3 个绑定用户
|
||||
[DEBUG] 正在同步用户 ID: 9018 (昵称: 现实的迪斯蒂法诺, 抖音号: wyl0423333) 的订单...
|
||||
[DEBUG] 正在同步用户 ID: 9019 (昵称: 约翰掐指一算, 抖音号: xrw200947752) 的订单...
|
||||
[DEBUG] 正在同步用户 ID: 9047 (昵称: 巴乔横扫六合, 抖音号: 请输入您的抖店订单号即可完成绑定) 的订单...
|
||||
{"level":"info","time":"2026-01-08 01:37:40","caller":"logger/logger.go:309","msg":"[抖店同步] 全量同步完成","domain":"mini-chat[fat]","users_count":3,"total_fetched":45,"new_orders":0,"matched_users":45}
|
||||
{"level":"info","time":"2026-01-08 01:37:40","caller":"logger/logger.go:309","msg":"[抖店定时同步] 同步成功","domain":"mini-chat[fat]","total_fetched":45,"new_orders":0,"matched_users":45}
|
||||
{"level":"debug","time":"2026-01-08 01:37:46","caller":"logger/logger.go:315","msg":"定时开奖: 开始检查","domain":"mini-chat[fat]","now":"2026-01-08 01:37:46"}
|
||||
{"level":"debug","time":"2026-01-08 01:37:46","caller":"logger/logger.go:315","msg":"定时开奖: 查询到活动","domain":"mini-chat[fat]","count":9}
|
||||
{"level":"debug","time":"2026-01-08 01:37:46","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":52,"play_type":"ichiban","interval":3,"scheduled_time":"2026-01-08T01:40:14.807+08:00","last_settled":"2026-01-08T01:37:14.807+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 01:37:46","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":52,"st":"2026-01-08 01:40:14","now":"2026-01-08 01:37:46","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 01:37:46","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":65,"play_type":"ichiban","interval":3,"scheduled_time":"2026-01-08T01:39:46.48+08:00","last_settled":"2026-01-08T01:36:46.48+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 01:37:46","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":65,"st":"2026-01-08 01:39:46","now":"2026-01-08 01:37:46","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 01:37:46","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":77,"play_type":"ichiban","interval":5,"scheduled_time":"2026-01-08T01:39:14.807+08:00","last_settled":"2026-01-08T01:34:14.807+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 01:37:46","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":77,"st":"2026-01-08 01:39:14","now":"2026-01-08 01:37:46","skip":true}
|
||||
{"level":"info","time":"2026-01-08 01:37:47","caller":"logger/logger.go:309","msg":"SpendingLeaderboard range: ALL TIME","domain":"mini-chat[fat]"}
|
||||
{"level":"debug","time":"2026-01-08 01:37:47","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":79,"play_type":"ichiban","interval":5,"scheduled_time":"2026-01-08T01:41:14.808+08:00","last_settled":"2026-01-08T01:36:14.808+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 01:37:47","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":79,"st":"2026-01-08 01:41:14","now":"2026-01-08 01:37:46","skip":true}
|
||||
{"level":"info","time":"2026-01-08 01:37:47","caller":"logger/logger.go:309","msg":"SpendingLeaderboard SQL done: count=0","domain":"mini-chat[fat]"}
|
||||
{"level":"debug","time":"2026-01-08 01:37:47","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":80,"play_type":"ichiban","interval":10,"scheduled_time":"2026-01-08T01:44:44.807+08:00","last_settled":"2026-01-08T01:34:44.807+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 01:37:47","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":80,"st":"2026-01-08 01:44:44","now":"2026-01-08 01:37:46","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 01:37:47","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":81,"play_type":"ichiban","interval":15,"scheduled_time":"2026-01-08T01:40:44.808+08:00","last_settled":"2026-01-08T01:25:44.808+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 01:37:47","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":81,"st":"2026-01-08 01:40:44","now":"2026-01-08 01:37:46","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 01:37:47","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":82,"play_type":"ichiban","interval":15,"scheduled_time":"2026-01-08T01:40:44.808+08:00","last_settled":"2026-01-08T01:25:44.808+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 01:37:47","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":82,"st":"2026-01-08 01:40:44","now":"2026-01-08 01:37:46","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 01:37:47","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":83,"play_type":"ichiban","interval":30,"scheduled_time":"2026-01-08T02:05:29.386+08:00","last_settled":"2026-01-08T01:35:29.386+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 01:37:47","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":83,"st":"2026-01-08 02:05:29","now":"2026-01-08 01:37:46","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 01:37:47","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":84,"play_type":"ichiban","interval":60,"scheduled_time":"2026-01-08T02:27:59.386+08:00","last_settled":"2026-01-08T01:27:59.386+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 01:37:47","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":84,"st":"2026-01-08 02:27:59","now":"2026-01-08 01:37:46","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 01:38:16","caller":"logger/logger.go:315","msg":"定时开奖: 开始检查","domain":"mini-chat[fat]","now":"2026-01-08 01:38:16"}
|
||||
{"level":"debug","time":"2026-01-08 01:38:16","caller":"logger/logger.go:315","msg":"定时开奖: 查询到活动","domain":"mini-chat[fat]","count":9}
|
||||
{"level":"debug","time":"2026-01-08 01:38:16","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":52,"play_type":"ichiban","interval":3,"scheduled_time":"2026-01-08T01:40:14.807+08:00","last_settled":"2026-01-08T01:37:14.807+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 01:38:16","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":52,"st":"2026-01-08 01:40:14","now":"2026-01-08 01:38:16","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 01:38:16","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":65,"play_type":"ichiban","interval":3,"scheduled_time":"2026-01-08T01:39:46.48+08:00","last_settled":"2026-01-08T01:36:46.48+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 01:38:16","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":65,"st":"2026-01-08 01:39:46","now":"2026-01-08 01:38:16","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 01:38:16","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":77,"play_type":"ichiban","interval":5,"scheduled_time":"2026-01-08T01:39:14.807+08:00","last_settled":"2026-01-08T01:34:14.807+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 01:38:16","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":77,"st":"2026-01-08 01:39:14","now":"2026-01-08 01:38:16","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 01:38:16","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":79,"play_type":"ichiban","interval":5,"scheduled_time":"2026-01-08T01:41:14.808+08:00","last_settled":"2026-01-08T01:36:14.808+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 01:38:16","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":79,"st":"2026-01-08 01:41:14","now":"2026-01-08 01:38:16","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 01:38:16","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":80,"play_type":"ichiban","interval":10,"scheduled_time":"2026-01-08T01:44:44.807+08:00","last_settled":"2026-01-08T01:34:44.807+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 01:38:16","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":80,"st":"2026-01-08 01:44:44","now":"2026-01-08 01:38:16","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 01:38:16","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":81,"play_type":"ichiban","interval":15,"scheduled_time":"2026-01-08T01:40:44.808+08:00","last_settled":"2026-01-08T01:25:44.808+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 01:38:17","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":81,"st":"2026-01-08 01:40:44","now":"2026-01-08 01:38:16","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 01:38:17","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":82,"play_type":"ichiban","interval":15,"scheduled_time":"2026-01-08T01:40:44.808+08:00","last_settled":"2026-01-08T01:25:44.808+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 01:38:17","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":82,"st":"2026-01-08 01:40:44","now":"2026-01-08 01:38:16","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 01:38:17","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":83,"play_type":"ichiban","interval":30,"scheduled_time":"2026-01-08T02:05:29.386+08:00","last_settled":"2026-01-08T01:35:29.386+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 01:38:17","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":83,"st":"2026-01-08 02:05:29","now":"2026-01-08 01:38:16","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 01:38:17","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":84,"play_type":"ichiban","interval":60,"scheduled_time":"2026-01-08T02:27:59.386+08:00","last_settled":"2026-01-08T01:27:59.386+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 01:38:17","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":84,"st":"2026-01-08 02:27:59","now":"2026-01-08 01:38:16","skip":true}
|
||||
{"level":"info","time":"2026-01-08 01:38:40","caller":"logger/logger.go:309","msg":"[抖店定时同步] 开始同步","domain":"mini-chat[fat]","interval_minutes":1}
|
||||
[DEBUG] 开始全量同步,共 3 个绑定用户
|
||||
[DEBUG] 正在同步用户 ID: 9018 (昵称: 现实的迪斯蒂法诺, 抖音号: wyl0423333) 的订单...
|
||||
{"level":"info","time":"2026-01-08 01:38:44","caller":"logger/logger.go:309","msg":"SpendingLeaderboard range: ALL TIME","domain":"mini-chat[fat]"}
|
||||
{"level":"info","time":"2026-01-08 01:38:44","caller":"logger/logger.go:309","msg":"SpendingLeaderboard SQL done: count=0","domain":"mini-chat[fat]"}
|
||||
[DEBUG] 正在同步用户 ID: 9019 (昵称: 约翰掐指一算, 抖音号: xrw200947752) 的订单...
|
||||
[DEBUG] 正在同步用户 ID: 9047 (昵称: 巴乔横扫六合, 抖音号: 请输入您的抖店订单号即可完成绑定) 的订单...
|
||||
{"level":"info","time":"2026-01-08 01:38:45","caller":"logger/logger.go:309","msg":"[抖店同步] 全量同步完成","domain":"mini-chat[fat]","users_count":3,"total_fetched":45,"new_orders":0,"matched_users":45}
|
||||
{"level":"info","time":"2026-01-08 01:38:45","caller":"logger/logger.go:309","msg":"[抖店定时同步] 同步成功","domain":"mini-chat[fat]","total_fetched":45,"new_orders":0,"matched_users":45}
|
||||
{"level":"debug","time":"2026-01-08 01:38:46","caller":"logger/logger.go:315","msg":"定时开奖: 开始检查","domain":"mini-chat[fat]","now":"2026-01-08 01:38:46"}
|
||||
{"level":"debug","time":"2026-01-08 01:38:46","caller":"logger/logger.go:315","msg":"定时开奖: 查询到活动","domain":"mini-chat[fat]","count":9}
|
||||
{"level":"debug","time":"2026-01-08 01:38:46","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":52,"play_type":"ichiban","interval":3,"scheduled_time":"2026-01-08T01:40:14.807+08:00","last_settled":"2026-01-08T01:37:14.807+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 01:38:46","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":52,"st":"2026-01-08 01:40:14","now":"2026-01-08 01:38:46","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 01:38:46","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":65,"play_type":"ichiban","interval":3,"scheduled_time":"2026-01-08T01:39:46.48+08:00","last_settled":"2026-01-08T01:36:46.48+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 01:38:46","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":65,"st":"2026-01-08 01:39:46","now":"2026-01-08 01:38:46","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 01:38:46","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":77,"play_type":"ichiban","interval":5,"scheduled_time":"2026-01-08T01:39:14.807+08:00","last_settled":"2026-01-08T01:34:14.807+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 01:38:46","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":77,"st":"2026-01-08 01:39:14","now":"2026-01-08 01:38:46","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 01:38:46","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":79,"play_type":"ichiban","interval":5,"scheduled_time":"2026-01-08T01:41:14.808+08:00","last_settled":"2026-01-08T01:36:14.808+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 01:38:46","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":79,"st":"2026-01-08 01:41:14","now":"2026-01-08 01:38:46","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 01:38:46","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":80,"play_type":"ichiban","interval":10,"scheduled_time":"2026-01-08T01:44:44.807+08:00","last_settled":"2026-01-08T01:34:44.807+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 01:38:46","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":80,"st":"2026-01-08 01:44:44","now":"2026-01-08 01:38:46","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 01:38:47","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":81,"play_type":"ichiban","interval":15,"scheduled_time":"2026-01-08T01:40:44.808+08:00","last_settled":"2026-01-08T01:25:44.808+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 01:38:47","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":81,"st":"2026-01-08 01:40:44","now":"2026-01-08 01:38:46","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 01:38:47","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":82,"play_type":"ichiban","interval":15,"scheduled_time":"2026-01-08T01:40:44.808+08:00","last_settled":"2026-01-08T01:25:44.808+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 01:38:47","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":82,"st":"2026-01-08 01:40:44","now":"2026-01-08 01:38:46","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 01:38:47","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":83,"play_type":"ichiban","interval":30,"scheduled_time":"2026-01-08T02:05:29.386+08:00","last_settled":"2026-01-08T01:35:29.386+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 01:38:47","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":83,"st":"2026-01-08 02:05:29","now":"2026-01-08 01:38:46","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 01:38:47","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":84,"play_type":"ichiban","interval":60,"scheduled_time":"2026-01-08T02:27:59.386+08:00","last_settled":"2026-01-08T01:27:59.386+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 01:38:47","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":84,"st":"2026-01-08 02:27:59","now":"2026-01-08 01:38:46","skip":true}
|
||||
193
backend_debug_sql.log
Normal file
193
backend_debug_sql.log
Normal file
@ -0,0 +1,193 @@
|
||||
{"level":"info","time":"2026-01-08 01:15:05","caller":"logger/logger.go:309","msg":"Connected to Redis","domain":"mini-chat[fat]","addr":"118.25.13.43:8379"}
|
||||
|
||||
[32m ____ _ _ _ ____[0m
|
||||
[32m | __ ) (_) _ __ __| | | |__ ___ __ __ / ___| __ _ _ __ ___ ___[0m
|
||||
[32m | _ \ | | | '_ \ / _` | | '_ \ / _ \ \ \/ / | | _ / _` | | '_ ` _ \ / _ \[0m
|
||||
[32m | |_) | | | | | | | | (_| | | |_) | | (_) | > < | |_| | | (_| | | | | | | | | __/[0m
|
||||
[32m |____/ |_| |_| |_| \__,_| |_.__/ \___/ /_/\_\ \____| \__,_| |_| |_| |_| \___|[0m
|
||||
▌ 客户项目: 盲盒游戏
|
||||
▌ 项目版本: Release-2025111111
|
||||
▌ 启动时间: 2026-01-08 01:15:05
|
||||
▌ 运行环境: darwin go1.24.2
|
||||
▌ 服务端口: [:9991]
|
||||
▌ 服务配置: [fat]
|
||||
|
||||
▌ 数据库连接: ✔ 已建立
|
||||
|
||||
{"level":"info","time":"2026-01-08 01:15:05","caller":"logger/logger.go:309","msg":"Task center worker started","domain":"mini-chat[fat]"}
|
||||
{"level":"info","time":"2026-01-08 01:15:05","caller":"logger/logger.go:309","msg":"对对碰自动开奖: 后台任务已启动","domain":"mini-chat[fat]"}
|
||||
{"level":"info","time":"2026-01-08 01:15:05","caller":"logger/logger.go:309","msg":"[抖店定时同步] 定时任务已启动","domain":"mini-chat[fat]"}
|
||||
{"level":"info","time":"2026-01-08 01:15:05","caller":"logger/logger.go:309","msg":"Worker routine started","domain":"mini-chat[fat]","worker_id":4}
|
||||
{"level":"info","time":"2026-01-08 01:15:05","caller":"logger/logger.go:309","msg":"Worker routine started","domain":"mini-chat[fat]","worker_id":3}
|
||||
{"level":"info","time":"2026-01-08 01:15:05","caller":"logger/logger.go:309","msg":"Worker routine started","domain":"mini-chat[fat]","worker_id":2}
|
||||
{"level":"info","time":"2026-01-08 01:15:05","caller":"logger/logger.go:309","msg":"Worker routine started","domain":"mini-chat[fat]","worker_id":1}
|
||||
{"level":"info","time":"2026-01-08 01:15:05","caller":"logger/logger.go:309","msg":"Worker routine started","domain":"mini-chat[fat]","worker_id":0}
|
||||
{"level":"error","time":"2026-01-08 01:15:06","caller":"logger/logger.go:327","msg":"解密配置失败","domain":"mini-chat[fat]","key":"douyin.app_secret","error":"ciphertext is not a multiple of the block size"}
|
||||
{"level":"info","time":"2026-01-08 01:15:06","caller":"logger/logger.go:309","msg":"动态配置加载完成","domain":"mini-chat[fat]","count":26}
|
||||
|
||||
2026/01/08 01:15:11 /Users/win/aicode/bindbox/bindbox_game/internal/api/admin/dashboard_spending.go:116
|
||||
[22.453ms] [rows:0] SELECT
|
||||
orders.user_id,
|
||||
SUM(orders.actual_amount) as total_amount,
|
||||
COUNT(orders.id) as order_count,
|
||||
SUM(orders.discount_amount) as total_discount,
|
||||
SUM(orders.points_amount) as total_points,
|
||||
SUM(CASE WHEN orders.source_type = 4 THEN 1 ELSE 0 END) as game_pass_count,
|
||||
SUM(CASE WHEN orders.item_card_id > 0 THEN 1 ELSE 0 END) as item_card_count,
|
||||
SUM(CASE WHEN oa.play_type = 'ichiban' THEN orders.actual_amount ELSE 0 END) as ichiban_spending,
|
||||
SUM(CASE WHEN oa.play_type = 'ichiban' THEN 1 ELSE 0 END) as ichiban_count,
|
||||
SUM(CASE WHEN oa.play_type IN ('infinite', 'box') THEN orders.actual_amount ELSE 0 END) as infinite_spending,
|
||||
SUM(CASE WHEN oa.play_type IN ('infinite', 'box') THEN 1 ELSE 0 END) as infinite_count,
|
||||
SUM(CASE WHEN oa.play_type = 'matching' THEN orders.actual_amount ELSE 0 END) as matching_spending,
|
||||
SUM(CASE WHEN oa.play_type = 'matching' THEN 1 ELSE 0 END) as matching_count
|
||||
FROM `orders` LEFT JOIN (SELECT l.order_id, MAX(a.play_type) as play_type FROM activity_draw_logs l JOIN activity_issues i ON i.id = l.issue_id JOIN activities a ON a.id = i.activity_id WHERE l.created_at >= '2025-12-08 01:15:11.202' GROUP BY l.order_id) oa ON oa.order_id = orders.id WHERE orders.status = 2 AND orders.created_at >= '2025-12-09 01:15:11.202' AND orders.created_at <= '2026-01-08 01:15:11.202' GROUP BY `orders`.`user_id` ORDER BY total_amount DESC LIMIT 50
|
||||
|
||||
2026/01/08 01:15:13 /Users/win/aicode/bindbox/bindbox_game/internal/api/admin/dashboard_spending.go:116
|
||||
[23.908ms] [rows:0] SELECT
|
||||
orders.user_id,
|
||||
SUM(orders.actual_amount) as total_amount,
|
||||
COUNT(orders.id) as order_count,
|
||||
SUM(orders.discount_amount) as total_discount,
|
||||
SUM(orders.points_amount) as total_points,
|
||||
SUM(CASE WHEN orders.source_type = 4 THEN 1 ELSE 0 END) as game_pass_count,
|
||||
SUM(CASE WHEN orders.item_card_id > 0 THEN 1 ELSE 0 END) as item_card_count,
|
||||
SUM(CASE WHEN oa.play_type = 'ichiban' THEN orders.actual_amount ELSE 0 END) as ichiban_spending,
|
||||
SUM(CASE WHEN oa.play_type = 'ichiban' THEN 1 ELSE 0 END) as ichiban_count,
|
||||
SUM(CASE WHEN oa.play_type IN ('infinite', 'box') THEN orders.actual_amount ELSE 0 END) as infinite_spending,
|
||||
SUM(CASE WHEN oa.play_type IN ('infinite', 'box') THEN 1 ELSE 0 END) as infinite_count,
|
||||
SUM(CASE WHEN oa.play_type = 'matching' THEN orders.actual_amount ELSE 0 END) as matching_spending,
|
||||
SUM(CASE WHEN oa.play_type = 'matching' THEN 1 ELSE 0 END) as matching_count
|
||||
FROM `orders` LEFT JOIN (SELECT l.order_id, MAX(a.play_type) as play_type FROM activity_draw_logs l JOIN activity_issues i ON i.id = l.issue_id JOIN activities a ON a.id = i.activity_id WHERE l.created_at >= '2025-12-08 01:15:13.54' GROUP BY l.order_id) oa ON oa.order_id = orders.id WHERE orders.status = 2 AND orders.created_at >= '2025-12-09 01:15:13.54' AND orders.created_at <= '2026-01-08 01:15:13.54' GROUP BY `orders`.`user_id` ORDER BY total_amount DESC LIMIT 50
|
||||
|
||||
2026/01/08 01:15:14 /Users/win/aicode/bindbox/bindbox_game/internal/api/admin/dashboard_spending.go:116
|
||||
[21.376ms] [rows:0] SELECT
|
||||
orders.user_id,
|
||||
SUM(orders.actual_amount) as total_amount,
|
||||
COUNT(orders.id) as order_count,
|
||||
SUM(orders.discount_amount) as total_discount,
|
||||
SUM(orders.points_amount) as total_points,
|
||||
SUM(CASE WHEN orders.source_type = 4 THEN 1 ELSE 0 END) as game_pass_count,
|
||||
SUM(CASE WHEN orders.item_card_id > 0 THEN 1 ELSE 0 END) as item_card_count,
|
||||
SUM(CASE WHEN oa.play_type = 'ichiban' THEN orders.actual_amount ELSE 0 END) as ichiban_spending,
|
||||
SUM(CASE WHEN oa.play_type = 'ichiban' THEN 1 ELSE 0 END) as ichiban_count,
|
||||
SUM(CASE WHEN oa.play_type IN ('infinite', 'box') THEN orders.actual_amount ELSE 0 END) as infinite_spending,
|
||||
SUM(CASE WHEN oa.play_type IN ('infinite', 'box') THEN 1 ELSE 0 END) as infinite_count,
|
||||
SUM(CASE WHEN oa.play_type = 'matching' THEN orders.actual_amount ELSE 0 END) as matching_spending,
|
||||
SUM(CASE WHEN oa.play_type = 'matching' THEN 1 ELSE 0 END) as matching_count
|
||||
FROM `orders` LEFT JOIN (SELECT l.order_id, MAX(a.play_type) as play_type FROM activity_draw_logs l JOIN activity_issues i ON i.id = l.issue_id JOIN activities a ON a.id = i.activity_id WHERE l.created_at >= '2025-12-08 01:15:13.982' GROUP BY l.order_id) oa ON oa.order_id = orders.id WHERE orders.status = 2 AND orders.created_at >= '2025-12-09 01:15:13.982' AND orders.created_at <= '2026-01-08 01:15:13.982' GROUP BY `orders`.`user_id` ORDER BY total_amount DESC LIMIT 50
|
||||
|
||||
2026/01/08 01:15:14 /Users/win/aicode/bindbox/bindbox_game/internal/api/admin/dashboard_spending.go:116
|
||||
[20.622ms] [rows:0] SELECT
|
||||
orders.user_id,
|
||||
SUM(orders.actual_amount) as total_amount,
|
||||
COUNT(orders.id) as order_count,
|
||||
SUM(orders.discount_amount) as total_discount,
|
||||
SUM(orders.points_amount) as total_points,
|
||||
SUM(CASE WHEN orders.source_type = 4 THEN 1 ELSE 0 END) as game_pass_count,
|
||||
SUM(CASE WHEN orders.item_card_id > 0 THEN 1 ELSE 0 END) as item_card_count,
|
||||
SUM(CASE WHEN oa.play_type = 'ichiban' THEN orders.actual_amount ELSE 0 END) as ichiban_spending,
|
||||
SUM(CASE WHEN oa.play_type = 'ichiban' THEN 1 ELSE 0 END) as ichiban_count,
|
||||
SUM(CASE WHEN oa.play_type IN ('infinite', 'box') THEN orders.actual_amount ELSE 0 END) as infinite_spending,
|
||||
SUM(CASE WHEN oa.play_type IN ('infinite', 'box') THEN 1 ELSE 0 END) as infinite_count,
|
||||
SUM(CASE WHEN oa.play_type = 'matching' THEN orders.actual_amount ELSE 0 END) as matching_spending,
|
||||
SUM(CASE WHEN oa.play_type = 'matching' THEN 1 ELSE 0 END) as matching_count
|
||||
FROM `orders` LEFT JOIN (SELECT l.order_id, MAX(a.play_type) as play_type FROM activity_draw_logs l JOIN activity_issues i ON i.id = l.issue_id JOIN activities a ON a.id = i.activity_id WHERE l.created_at >= '2025-12-08 01:15:14.549' GROUP BY l.order_id) oa ON oa.order_id = orders.id WHERE orders.status = 2 AND orders.created_at >= '2025-12-09 01:15:14.549' AND orders.created_at <= '2026-01-08 01:15:14.549' GROUP BY `orders`.`user_id` ORDER BY total_amount DESC LIMIT 50
|
||||
{"level":"debug","time":"2026-01-08 01:15:35","caller":"logger/logger.go:315","msg":"定时开奖: 开始检查","domain":"mini-chat[fat]","now":"2026-01-08 01:15:35"}
|
||||
{"level":"info","time":"2026-01-08 01:15:35","caller":"logger/logger.go:309","msg":"[抖店定时同步] 开始同步","domain":"mini-chat[fat]","interval_minutes":1}
|
||||
{"level":"debug","time":"2026-01-08 01:15:35","caller":"logger/logger.go:315","msg":"定时开奖: 查询到活动","domain":"mini-chat[fat]","count":9}
|
||||
{"level":"debug","time":"2026-01-08 01:15:35","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":52,"play_type":"ichiban","interval":3,"scheduled_time":"2026-01-08T01:15:44.807+08:00","last_settled":"2026-01-08T01:12:44.807+08:00"}
|
||||
[DEBUG] 开始全量同步,共 3 个绑定用户
|
||||
[DEBUG] 正在同步用户 ID: 9018 (昵称: 现实的迪斯蒂法诺, 抖音号: wyl0423333) 的订单...
|
||||
{"level":"debug","time":"2026-01-08 01:15:36","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":52,"st":"2026-01-08 01:15:44","now":"2026-01-08 01:15:35","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 01:15:36","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":65,"play_type":"ichiban","interval":3,"scheduled_time":"2026-01-08T01:18:29.385+08:00","last_settled":"2026-01-08T01:15:29.385+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 01:15:36","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":65,"st":"2026-01-08 01:18:29","now":"2026-01-08 01:15:35","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 01:15:36","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":77,"play_type":"ichiban","interval":5,"scheduled_time":"2026-01-08T01:18:44.808+08:00","last_settled":"2026-01-08T01:13:44.808+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 01:15:36","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":77,"st":"2026-01-08 01:18:44","now":"2026-01-08 01:15:35","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 01:15:36","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":79,"play_type":"ichiban","interval":5,"scheduled_time":"2026-01-08T01:15:29.386+08:00","last_settled":"2026-01-08T01:10:29.386+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 01:15:36","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":79,"st":"2026-01-08 01:15:29","now":"2026-01-08 01:15:35","skip":false}
|
||||
{"level":"debug","time":"2026-01-08 01:15:36","caller":"logger/logger.go:315","msg":"定时开奖: 查询订单范围","domain":"mini-chat[fat]","id":79,"last":"2026-01-08 01:10:29","now":"2026-01-08 01:15:35"}
|
||||
{"level":"debug","time":"2026-01-08 01:15:36","caller":"logger/logger.go:315","msg":"定时开奖: 查询到订单","domain":"mini-chat[fat]","id":79,"count":0,"min":1}
|
||||
{"level":"debug","time":"2026-01-08 01:15:36","caller":"logger/logger.go:315","msg":"定时开奖-一番赏: 检查售罄","domain":"mini-chat[fat]","issue_id":86,"sold":0,"total":5}
|
||||
{"level":"info","time":"2026-01-08 01:15:36","caller":"logger/logger.go:309","msg":"定时开奖-一番赏: 未售罄,执行全额退款","domain":"mini-chat[fat]","issue_id":86}
|
||||
{"level":"debug","time":"2026-01-08 01:15:36","caller":"logger/logger.go:315","msg":"定时开奖-一番赏: 剩余未处理订单记录","domain":"mini-chat[fat]","issue_id":86,"count":0}
|
||||
{"level":"info","time":"2026-01-08 01:15:36","caller":"logger/logger.go:309","msg":"定时开奖-一番赏: 格位已重置,新一轮可以开始","domain":"mini-chat[fat]","issue_id":86}
|
||||
{"level":"info","time":"2026-01-08 01:15:36","caller":"logger/logger.go:309","msg":"定时开奖: 人数满足,开始开奖处理","domain":"mini-chat[fat]","id":79}
|
||||
{"level":"info","time":"2026-01-08 01:15:36","caller":"logger/logger.go:309","msg":"定时开奖: 更新活动下次结算时间","domain":"mini-chat[fat]","id":79,"last":"2026-01-08 01:15:35","next":"2026-01-08 01:20:35"}
|
||||
{"level":"debug","time":"2026-01-08 01:15:36","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":80,"play_type":"ichiban","interval":10,"scheduled_time":"2026-01-08T01:24:29.385+08:00","last_settled":"2026-01-08T01:14:29.385+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 01:15:36","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":80,"st":"2026-01-08 01:24:29","now":"2026-01-08 01:15:35","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 01:15:36","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":81,"play_type":"ichiban","interval":15,"scheduled_time":"2026-01-08T01:25:29.386+08:00","last_settled":"2026-01-08T01:10:29.386+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 01:15:36","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":81,"st":"2026-01-08 01:25:29","now":"2026-01-08 01:15:35","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 01:15:36","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":82,"play_type":"ichiban","interval":15,"scheduled_time":"2026-01-08T01:25:29.386+08:00","last_settled":"2026-01-08T01:10:29.386+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 01:15:37","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":82,"st":"2026-01-08 01:25:29","now":"2026-01-08 01:15:35","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 01:15:37","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":83,"play_type":"ichiban","interval":30,"scheduled_time":"2026-01-08T01:35:29.385+08:00","last_settled":"2026-01-08T01:05:29.385+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 01:15:37","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":83,"st":"2026-01-08 01:35:29","now":"2026-01-08 01:15:35","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 01:15:37","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":84,"play_type":"ichiban","interval":60,"scheduled_time":"2026-01-08T01:27:44.808+08:00","last_settled":"2026-01-08T00:27:44.808+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 01:15:37","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":84,"st":"2026-01-08 01:27:44","now":"2026-01-08 01:15:35","skip":true}
|
||||
[DEBUG] 正在同步用户 ID: 9019 (昵称: 约翰掐指一算, 抖音号: xrw200947752) 的订单...
|
||||
[DEBUG] 正在同步用户 ID: 9047 (昵称: 巴乔横扫六合, 抖音号: 请输入您的抖店订单号即可完成绑定) 的订单...
|
||||
{"level":"info","time":"2026-01-08 01:15:40","caller":"logger/logger.go:309","msg":"[抖店同步] 全量同步完成","domain":"mini-chat[fat]","users_count":3,"total_fetched":45,"new_orders":0,"matched_users":45}
|
||||
{"level":"info","time":"2026-01-08 01:15:40","caller":"logger/logger.go:309","msg":"[抖店定时同步] 同步成功","domain":"mini-chat[fat]","total_fetched":45,"new_orders":0,"matched_users":45}
|
||||
{"level":"debug","time":"2026-01-08 01:16:05","caller":"logger/logger.go:315","msg":"定时开奖: 开始检查","domain":"mini-chat[fat]","now":"2026-01-08 01:16:05"}
|
||||
{"level":"debug","time":"2026-01-08 01:16:05","caller":"logger/logger.go:315","msg":"定时开奖: 查询到活动","domain":"mini-chat[fat]","count":9}
|
||||
{"level":"debug","time":"2026-01-08 01:16:05","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":52,"play_type":"ichiban","interval":3,"scheduled_time":"2026-01-08T01:18:44.807+08:00","last_settled":"2026-01-08T01:15:44.807+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 01:16:06","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":52,"st":"2026-01-08 01:18:44","now":"2026-01-08 01:16:05","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 01:16:06","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":65,"play_type":"ichiban","interval":3,"scheduled_time":"2026-01-08T01:18:29.385+08:00","last_settled":"2026-01-08T01:15:29.385+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 01:16:06","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":65,"st":"2026-01-08 01:18:29","now":"2026-01-08 01:16:05","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 01:16:06","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":77,"play_type":"ichiban","interval":5,"scheduled_time":"2026-01-08T01:18:44.808+08:00","last_settled":"2026-01-08T01:13:44.808+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 01:16:06","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":77,"st":"2026-01-08 01:18:44","now":"2026-01-08 01:16:05","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 01:16:06","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":79,"play_type":"ichiban","interval":5,"scheduled_time":"2026-01-08T01:20:35.866+08:00","last_settled":"2026-01-08T01:15:35.866+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 01:16:06","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":79,"st":"2026-01-08 01:20:35","now":"2026-01-08 01:16:05","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 01:16:06","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":80,"play_type":"ichiban","interval":10,"scheduled_time":"2026-01-08T01:24:29.385+08:00","last_settled":"2026-01-08T01:14:29.385+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 01:16:06","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":80,"st":"2026-01-08 01:24:29","now":"2026-01-08 01:16:05","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 01:16:06","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":81,"play_type":"ichiban","interval":15,"scheduled_time":"2026-01-08T01:25:29.386+08:00","last_settled":"2026-01-08T01:10:29.386+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 01:16:06","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":81,"st":"2026-01-08 01:25:29","now":"2026-01-08 01:16:05","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 01:16:06","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":82,"play_type":"ichiban","interval":15,"scheduled_time":"2026-01-08T01:25:29.386+08:00","last_settled":"2026-01-08T01:10:29.386+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 01:16:06","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":82,"st":"2026-01-08 01:25:29","now":"2026-01-08 01:16:05","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 01:16:06","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":83,"play_type":"ichiban","interval":30,"scheduled_time":"2026-01-08T01:35:29.385+08:00","last_settled":"2026-01-08T01:05:29.385+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 01:16:06","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":83,"st":"2026-01-08 01:35:29","now":"2026-01-08 01:16:05","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 01:16:06","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":84,"play_type":"ichiban","interval":60,"scheduled_time":"2026-01-08T01:27:44.808+08:00","last_settled":"2026-01-08T00:27:44.808+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 01:16:06","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":84,"st":"2026-01-08 01:27:44","now":"2026-01-08 01:16:05","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 01:16:35","caller":"logger/logger.go:315","msg":"定时开奖: 开始检查","domain":"mini-chat[fat]","now":"2026-01-08 01:16:35"}
|
||||
{"level":"debug","time":"2026-01-08 01:16:35","caller":"logger/logger.go:315","msg":"定时开奖: 查询到活动","domain":"mini-chat[fat]","count":9}
|
||||
{"level":"debug","time":"2026-01-08 01:16:35","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":52,"play_type":"ichiban","interval":3,"scheduled_time":"2026-01-08T01:18:44.807+08:00","last_settled":"2026-01-08T01:15:44.807+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 01:16:36","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":52,"st":"2026-01-08 01:18:44","now":"2026-01-08 01:16:35","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 01:16:36","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":65,"play_type":"ichiban","interval":3,"scheduled_time":"2026-01-08T01:18:29.385+08:00","last_settled":"2026-01-08T01:15:29.385+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 01:16:36","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":65,"st":"2026-01-08 01:18:29","now":"2026-01-08 01:16:35","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 01:16:36","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":77,"play_type":"ichiban","interval":5,"scheduled_time":"2026-01-08T01:18:44.808+08:00","last_settled":"2026-01-08T01:13:44.808+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 01:16:36","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":77,"st":"2026-01-08 01:18:44","now":"2026-01-08 01:16:35","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 01:16:36","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":79,"play_type":"ichiban","interval":5,"scheduled_time":"2026-01-08T01:20:35.866+08:00","last_settled":"2026-01-08T01:15:35.866+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 01:16:36","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":79,"st":"2026-01-08 01:20:35","now":"2026-01-08 01:16:35","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 01:16:36","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":80,"play_type":"ichiban","interval":10,"scheduled_time":"2026-01-08T01:24:29.385+08:00","last_settled":"2026-01-08T01:14:29.385+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 01:16:36","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":80,"st":"2026-01-08 01:24:29","now":"2026-01-08 01:16:35","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 01:16:36","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":81,"play_type":"ichiban","interval":15,"scheduled_time":"2026-01-08T01:25:29.386+08:00","last_settled":"2026-01-08T01:10:29.386+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 01:16:36","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":81,"st":"2026-01-08 01:25:29","now":"2026-01-08 01:16:35","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 01:16:36","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":82,"play_type":"ichiban","interval":15,"scheduled_time":"2026-01-08T01:25:29.386+08:00","last_settled":"2026-01-08T01:10:29.386+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 01:16:36","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":82,"st":"2026-01-08 01:25:29","now":"2026-01-08 01:16:35","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 01:16:36","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":83,"play_type":"ichiban","interval":30,"scheduled_time":"2026-01-08T01:35:29.385+08:00","last_settled":"2026-01-08T01:05:29.385+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 01:16:36","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":83,"st":"2026-01-08 01:35:29","now":"2026-01-08 01:16:35","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 01:16:36","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":84,"play_type":"ichiban","interval":60,"scheduled_time":"2026-01-08T01:27:44.808+08:00","last_settled":"2026-01-08T00:27:44.808+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 01:16:36","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":84,"st":"2026-01-08 01:27:44","now":"2026-01-08 01:16:35","skip":true}
|
||||
|
||||
2026/01/08 01:16:38 /Users/win/aicode/bindbox/bindbox_game/internal/api/admin/dashboard_spending.go:116
|
||||
[24.774ms] [rows:0] SELECT
|
||||
orders.user_id,
|
||||
SUM(orders.actual_amount) as total_amount,
|
||||
COUNT(orders.id) as order_count,
|
||||
SUM(orders.discount_amount) as total_discount,
|
||||
SUM(orders.points_amount) as total_points,
|
||||
SUM(CASE WHEN orders.source_type = 4 THEN 1 ELSE 0 END) as game_pass_count,
|
||||
SUM(CASE WHEN orders.item_card_id > 0 THEN 1 ELSE 0 END) as item_card_count,
|
||||
SUM(CASE WHEN oa.play_type = 'ichiban' THEN orders.actual_amount ELSE 0 END) as ichiban_spending,
|
||||
SUM(CASE WHEN oa.play_type = 'ichiban' THEN 1 ELSE 0 END) as ichiban_count,
|
||||
SUM(CASE WHEN oa.play_type IN ('infinite', 'box') THEN orders.actual_amount ELSE 0 END) as infinite_spending,
|
||||
SUM(CASE WHEN oa.play_type IN ('infinite', 'box') THEN 1 ELSE 0 END) as infinite_count,
|
||||
SUM(CASE WHEN oa.play_type = 'matching' THEN orders.actual_amount ELSE 0 END) as matching_spending,
|
||||
SUM(CASE WHEN oa.play_type = 'matching' THEN 1 ELSE 0 END) as matching_count
|
||||
FROM `orders` LEFT JOIN (SELECT l.order_id, MAX(a.play_type) as play_type FROM activity_draw_logs l JOIN activity_issues i ON i.id = l.issue_id JOIN activities a ON a.id = i.activity_id WHERE l.created_at >= '2025-12-31 01:16:38.634' GROUP BY l.order_id) oa ON oa.order_id = orders.id WHERE orders.status = 2 AND orders.created_at >= '2026-01-01 01:16:38.634' AND orders.created_at <= '2026-01-08 01:16:38.634' GROUP BY `orders`.`user_id` ORDER BY total_amount DESC LIMIT 50
|
||||
{"level":"info","time":"2026-01-08 01:16:40","caller":"logger/logger.go:309","msg":"[抖店定时同步] 开始同步","domain":"mini-chat[fat]","interval_minutes":1}
|
||||
[DEBUG] 开始全量同步,共 3 个绑定用户
|
||||
[DEBUG] 正在同步用户 ID: 9018 (昵称: 现实的迪斯蒂法诺, 抖音号: wyl0423333) 的订单...
|
||||
[DEBUG] 正在同步用户 ID: 9019 (昵称: 约翰掐指一算, 抖音号: xrw200947752) 的订单...
|
||||
[DEBUG] 正在同步用户 ID: 9047 (昵称: 巴乔横扫六合, 抖音号: 请输入您的抖店订单号即可完成绑定) 的订单...
|
||||
{"level":"info","time":"2026-01-08 01:16:45","caller":"logger/logger.go:309","msg":"[抖店同步] 全量同步完成","domain":"mini-chat[fat]","users_count":3,"total_fetched":45,"new_orders":0,"matched_users":45}
|
||||
{"level":"info","time":"2026-01-08 01:16:45","caller":"logger/logger.go:309","msg":"[抖店定时同步] 同步成功","domain":"mini-chat[fat]","total_fetched":45,"new_orders":0,"matched_users":45}
|
||||
4
backend_final.log
Normal file
4
backend_final.log
Normal file
@ -0,0 +1,4 @@
|
||||
# bindbox-game/internal/api/admin
|
||||
internal/api/admin/dashboard_spending.go:118:68: undefined: logger.Any
|
||||
internal/api/admin/users_admin.go:112:58: undefined: logger.Any
|
||||
internal/api/admin/users_admin.go:319:58: undefined: logger.Any
|
||||
360
backend_fix_sql.log
Normal file
360
backend_fix_sql.log
Normal file
@ -0,0 +1,360 @@
|
||||
{"level":"info","time":"2026-01-08 01:03:00","caller":"logger/logger.go:309","msg":"Connected to Redis","domain":"mini-chat[fat]","addr":"118.25.13.43:8379"}
|
||||
|
||||
[32m ____ _ _ _ ____[0m
|
||||
[32m | __ ) (_) _ __ __| | | |__ ___ __ __ / ___| __ _ _ __ ___ ___[0m
|
||||
[32m | _ \ | | | '_ \ / _` | | '_ \ / _ \ \ \/ / | | _ / _` | | '_ ` _ \ / _ \[0m
|
||||
[32m | |_) | | | | | | | | (_| | | |_) | | (_) | > < | |_| | | (_| | | | | | | | | __/[0m
|
||||
[32m |____/ |_| |_| |_| \__,_| |_.__/ \___/ /_/\_\ \____| \__,_| |_| |_| |_| \___|[0m
|
||||
▌ 客户项目: 盲盒游戏
|
||||
▌ 项目版本: Release-2025111111
|
||||
▌ 启动时间: 2026-01-08 01:03:00
|
||||
▌ 运行环境: darwin go1.24.2
|
||||
▌ 服务端口: [:9991]
|
||||
▌ 服务配置: [fat]
|
||||
|
||||
▌ 数据库连接: ✔ 已建立
|
||||
|
||||
{"level":"info","time":"2026-01-08 01:03:00","caller":"logger/logger.go:309","msg":"Task center worker started","domain":"mini-chat[fat]"}
|
||||
{"level":"info","time":"2026-01-08 01:03:00","caller":"logger/logger.go:309","msg":"对对碰自动开奖: 后台任务已启动","domain":"mini-chat[fat]"}
|
||||
{"level":"info","time":"2026-01-08 01:03:00","caller":"logger/logger.go:309","msg":"[抖店定时同步] 定时任务已启动","domain":"mini-chat[fat]"}
|
||||
{"level":"info","time":"2026-01-08 01:03:00","caller":"logger/logger.go:309","msg":"Worker routine started","domain":"mini-chat[fat]","worker_id":1}
|
||||
{"level":"info","time":"2026-01-08 01:03:00","caller":"logger/logger.go:309","msg":"Worker routine started","domain":"mini-chat[fat]","worker_id":4}
|
||||
{"level":"info","time":"2026-01-08 01:03:00","caller":"logger/logger.go:309","msg":"Worker routine started","domain":"mini-chat[fat]","worker_id":0}
|
||||
{"level":"info","time":"2026-01-08 01:03:00","caller":"logger/logger.go:309","msg":"Worker routine started","domain":"mini-chat[fat]","worker_id":2}
|
||||
{"level":"info","time":"2026-01-08 01:03:00","caller":"logger/logger.go:309","msg":"Worker routine started","domain":"mini-chat[fat]","worker_id":3}
|
||||
{"level":"error","time":"2026-01-08 01:03:00","caller":"logger/logger.go:327","msg":"解密配置失败","domain":"mini-chat[fat]","key":"douyin.app_secret","error":"ciphertext is not a multiple of the block size"}
|
||||
{"level":"info","time":"2026-01-08 01:03:00","caller":"logger/logger.go:309","msg":"动态配置加载完成","domain":"mini-chat[fat]","count":26}
|
||||
{"level":"debug","time":"2026-01-08 01:03:30","caller":"logger/logger.go:315","msg":"定时开奖: 开始检查","domain":"mini-chat[fat]","now":"2026-01-08 01:03:30"}
|
||||
{"level":"info","time":"2026-01-08 01:03:30","caller":"logger/logger.go:309","msg":"[抖店定时同步] 开始同步","domain":"mini-chat[fat]","interval_minutes":1}
|
||||
[DEBUG] 开始全量同步,共 3 个绑定用户
|
||||
[DEBUG] 正在同步用户 ID: 9018 (昵称: 现实的迪斯蒂法诺, 抖音号: wyl0423333) 的订单...
|
||||
{"level":"debug","time":"2026-01-08 01:03:30","caller":"logger/logger.go:315","msg":"定时开奖: 查询到活动","domain":"mini-chat[fat]","count":9}
|
||||
{"level":"debug","time":"2026-01-08 01:03:30","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":52,"play_type":"ichiban","interval":3,"scheduled_time":"2026-01-08T01:06:14.807+08:00","last_settled":"2026-01-08T01:03:14.807+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 01:03:30","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":52,"st":"2026-01-08 01:06:14","now":"2026-01-08 01:03:30","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 01:03:30","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":65,"play_type":"ichiban","interval":3,"scheduled_time":"2026-01-08T01:05:59.385+08:00","last_settled":"2026-01-08T01:02:59.385+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 01:03:30","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":65,"st":"2026-01-08 01:05:59","now":"2026-01-08 01:03:30","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 01:03:30","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":77,"play_type":"ichiban","interval":5,"scheduled_time":"2026-01-08T01:03:44.807+08:00","last_settled":"2026-01-08T00:58:44.807+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 01:03:30","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":77,"st":"2026-01-08 01:03:44","now":"2026-01-08 01:03:30","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 01:03:31","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":79,"play_type":"ichiban","interval":5,"scheduled_time":"2026-01-08T01:05:14.807+08:00","last_settled":"2026-01-08T01:00:14.807+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 01:03:31","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":79,"st":"2026-01-08 01:05:14","now":"2026-01-08 01:03:30","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 01:03:31","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":80,"play_type":"ichiban","interval":10,"scheduled_time":"2026-01-08T01:04:18.148+08:00","last_settled":"2026-01-08T00:54:18.148+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 01:03:31","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":80,"st":"2026-01-08 01:04:18","now":"2026-01-08 01:03:30","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 01:03:31","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":81,"play_type":"ichiban","interval":15,"scheduled_time":"2026-01-08T01:10:14.807+08:00","last_settled":"2026-01-08T00:55:14.807+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 01:03:31","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":81,"st":"2026-01-08 01:10:14","now":"2026-01-08 01:03:30","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 01:03:31","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":82,"play_type":"ichiban","interval":15,"scheduled_time":"2026-01-08T01:10:14.807+08:00","last_settled":"2026-01-08T00:55:14.807+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 01:03:31","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":82,"st":"2026-01-08 01:10:14","now":"2026-01-08 01:03:30","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 01:03:31","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":83,"play_type":"ichiban","interval":30,"scheduled_time":"2026-01-08T01:05:26.489+08:00","last_settled":"2026-01-08T00:35:26.489+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 01:03:31","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":83,"st":"2026-01-08 01:05:26","now":"2026-01-08 01:03:30","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 01:03:31","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":84,"play_type":"ichiban","interval":60,"scheduled_time":"2026-01-08T01:27:44.808+08:00","last_settled":"2026-01-08T00:27:44.808+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 01:03:31","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":84,"st":"2026-01-08 01:27:44","now":"2026-01-08 01:03:30","skip":true}
|
||||
[DEBUG] 正在同步用户 ID: 9019 (昵称: 约翰掐指一算, 抖音号: xrw200947752) 的订单...
|
||||
[DEBUG] 正在同步用户 ID: 9047 (昵称: 巴乔横扫六合, 抖音号: 请输入您的抖店订单号即可完成绑定) 的订单...
|
||||
{"level":"info","time":"2026-01-08 01:03:35","caller":"logger/logger.go:309","msg":"[抖店同步] 全量同步完成","domain":"mini-chat[fat]","users_count":3,"total_fetched":45,"new_orders":0,"matched_users":45}
|
||||
{"level":"info","time":"2026-01-08 01:03:35","caller":"logger/logger.go:309","msg":"[抖店定时同步] 同步成功","domain":"mini-chat[fat]","total_fetched":45,"new_orders":0,"matched_users":45}
|
||||
{"level":"debug","time":"2026-01-08 01:04:00","caller":"logger/logger.go:315","msg":"定时开奖: 开始检查","domain":"mini-chat[fat]","now":"2026-01-08 01:04:00"}
|
||||
{"level":"debug","time":"2026-01-08 01:04:00","caller":"logger/logger.go:315","msg":"定时开奖: 查询到活动","domain":"mini-chat[fat]","count":9}
|
||||
{"level":"debug","time":"2026-01-08 01:04:00","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":52,"play_type":"ichiban","interval":3,"scheduled_time":"2026-01-08T01:06:14.807+08:00","last_settled":"2026-01-08T01:03:14.807+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 01:04:00","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":52,"st":"2026-01-08 01:06:14","now":"2026-01-08 01:04:00","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 01:04:00","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":65,"play_type":"ichiban","interval":3,"scheduled_time":"2026-01-08T01:05:59.385+08:00","last_settled":"2026-01-08T01:02:59.385+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 01:04:00","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":65,"st":"2026-01-08 01:05:59","now":"2026-01-08 01:04:00","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 01:04:00","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":77,"play_type":"ichiban","interval":5,"scheduled_time":"2026-01-08T01:08:44.807+08:00","last_settled":"2026-01-08T01:03:44.807+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 01:04:00","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":77,"st":"2026-01-08 01:08:44","now":"2026-01-08 01:04:00","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 01:04:00","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":79,"play_type":"ichiban","interval":5,"scheduled_time":"2026-01-08T01:05:14.807+08:00","last_settled":"2026-01-08T01:00:14.807+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 01:04:01","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":79,"st":"2026-01-08 01:05:14","now":"2026-01-08 01:04:00","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 01:04:01","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":80,"play_type":"ichiban","interval":10,"scheduled_time":"2026-01-08T01:04:18.148+08:00","last_settled":"2026-01-08T00:54:18.148+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 01:04:01","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":80,"st":"2026-01-08 01:04:18","now":"2026-01-08 01:04:00","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 01:04:01","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":81,"play_type":"ichiban","interval":15,"scheduled_time":"2026-01-08T01:10:14.807+08:00","last_settled":"2026-01-08T00:55:14.807+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 01:04:01","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":81,"st":"2026-01-08 01:10:14","now":"2026-01-08 01:04:00","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 01:04:01","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":82,"play_type":"ichiban","interval":15,"scheduled_time":"2026-01-08T01:10:14.807+08:00","last_settled":"2026-01-08T00:55:14.807+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 01:04:01","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":82,"st":"2026-01-08 01:10:14","now":"2026-01-08 01:04:00","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 01:04:01","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":83,"play_type":"ichiban","interval":30,"scheduled_time":"2026-01-08T01:05:26.489+08:00","last_settled":"2026-01-08T00:35:26.489+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 01:04:01","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":83,"st":"2026-01-08 01:05:26","now":"2026-01-08 01:04:00","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 01:04:01","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":84,"play_type":"ichiban","interval":60,"scheduled_time":"2026-01-08T01:27:44.808+08:00","last_settled":"2026-01-08T00:27:44.808+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 01:04:01","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":84,"st":"2026-01-08 01:27:44","now":"2026-01-08 01:04:00","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 01:04:30","caller":"logger/logger.go:315","msg":"定时开奖: 开始检查","domain":"mini-chat[fat]","now":"2026-01-08 01:04:30"}
|
||||
{"level":"debug","time":"2026-01-08 01:04:30","caller":"logger/logger.go:315","msg":"定时开奖: 查询到活动","domain":"mini-chat[fat]","count":9}
|
||||
{"level":"debug","time":"2026-01-08 01:04:30","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":52,"play_type":"ichiban","interval":3,"scheduled_time":"2026-01-08T01:06:14.807+08:00","last_settled":"2026-01-08T01:03:14.807+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 01:04:30","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":52,"st":"2026-01-08 01:06:14","now":"2026-01-08 01:04:30","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 01:04:30","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":65,"play_type":"ichiban","interval":3,"scheduled_time":"2026-01-08T01:05:59.385+08:00","last_settled":"2026-01-08T01:02:59.385+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 01:04:30","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":65,"st":"2026-01-08 01:05:59","now":"2026-01-08 01:04:30","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 01:04:30","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":77,"play_type":"ichiban","interval":5,"scheduled_time":"2026-01-08T01:08:44.807+08:00","last_settled":"2026-01-08T01:03:44.807+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 01:04:30","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":77,"st":"2026-01-08 01:08:44","now":"2026-01-08 01:04:30","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 01:04:30","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":79,"play_type":"ichiban","interval":5,"scheduled_time":"2026-01-08T01:05:14.807+08:00","last_settled":"2026-01-08T01:00:14.807+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 01:04:31","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":79,"st":"2026-01-08 01:05:14","now":"2026-01-08 01:04:30","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 01:04:31","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":80,"play_type":"ichiban","interval":10,"scheduled_time":"2026-01-08T01:14:29.385+08:00","last_settled":"2026-01-08T01:04:29.385+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 01:04:31","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":80,"st":"2026-01-08 01:14:29","now":"2026-01-08 01:04:30","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 01:04:31","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":81,"play_type":"ichiban","interval":15,"scheduled_time":"2026-01-08T01:10:14.807+08:00","last_settled":"2026-01-08T00:55:14.807+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 01:04:31","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":81,"st":"2026-01-08 01:10:14","now":"2026-01-08 01:04:30","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 01:04:31","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":82,"play_type":"ichiban","interval":15,"scheduled_time":"2026-01-08T01:10:14.807+08:00","last_settled":"2026-01-08T00:55:14.807+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 01:04:31","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":82,"st":"2026-01-08 01:10:14","now":"2026-01-08 01:04:30","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 01:04:31","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":83,"play_type":"ichiban","interval":30,"scheduled_time":"2026-01-08T01:05:26.489+08:00","last_settled":"2026-01-08T00:35:26.489+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 01:04:31","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":83,"st":"2026-01-08 01:05:26","now":"2026-01-08 01:04:30","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 01:04:31","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":84,"play_type":"ichiban","interval":60,"scheduled_time":"2026-01-08T01:27:44.808+08:00","last_settled":"2026-01-08T00:27:44.808+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 01:04:31","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":84,"st":"2026-01-08 01:27:44","now":"2026-01-08 01:04:30","skip":true}
|
||||
{"level":"info","time":"2026-01-08 01:04:35","caller":"logger/logger.go:309","msg":"[抖店定时同步] 开始同步","domain":"mini-chat[fat]","interval_minutes":1}
|
||||
[DEBUG] 开始全量同步,共 3 个绑定用户
|
||||
[DEBUG] 正在同步用户 ID: 9018 (昵称: 现实的迪斯蒂法诺, 抖音号: wyl0423333) 的订单...
|
||||
[DEBUG] 正在同步用户 ID: 9019 (昵称: 约翰掐指一算, 抖音号: xrw200947752) 的订单...
|
||||
[DEBUG] 正在同步用户 ID: 9047 (昵称: 巴乔横扫六合, 抖音号: 请输入您的抖店订单号即可完成绑定) 的订单...
|
||||
{"level":"info","time":"2026-01-08 01:04:40","caller":"logger/logger.go:309","msg":"[抖店同步] 全量同步完成","domain":"mini-chat[fat]","users_count":3,"total_fetched":45,"new_orders":0,"matched_users":45}
|
||||
{"level":"info","time":"2026-01-08 01:04:40","caller":"logger/logger.go:309","msg":"[抖店定时同步] 同步成功","domain":"mini-chat[fat]","total_fetched":45,"new_orders":0,"matched_users":45}
|
||||
{"level":"debug","time":"2026-01-08 01:05:00","caller":"logger/logger.go:315","msg":"定时开奖: 开始检查","domain":"mini-chat[fat]","now":"2026-01-08 01:05:00"}
|
||||
{"level":"debug","time":"2026-01-08 01:05:00","caller":"logger/logger.go:315","msg":"定时开奖: 查询到活动","domain":"mini-chat[fat]","count":9}
|
||||
{"level":"debug","time":"2026-01-08 01:05:00","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":52,"play_type":"ichiban","interval":3,"scheduled_time":"2026-01-08T01:06:14.807+08:00","last_settled":"2026-01-08T01:03:14.807+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 01:05:00","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":52,"st":"2026-01-08 01:06:14","now":"2026-01-08 01:05:00","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 01:05:00","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":65,"play_type":"ichiban","interval":3,"scheduled_time":"2026-01-08T01:05:59.385+08:00","last_settled":"2026-01-08T01:02:59.385+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 01:05:00","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":65,"st":"2026-01-08 01:05:59","now":"2026-01-08 01:05:00","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 01:05:00","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":77,"play_type":"ichiban","interval":5,"scheduled_time":"2026-01-08T01:08:44.807+08:00","last_settled":"2026-01-08T01:03:44.807+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 01:05:00","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":77,"st":"2026-01-08 01:08:44","now":"2026-01-08 01:05:00","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 01:05:00","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":79,"play_type":"ichiban","interval":5,"scheduled_time":"2026-01-08T01:05:14.807+08:00","last_settled":"2026-01-08T01:00:14.807+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 01:05:01","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":79,"st":"2026-01-08 01:05:14","now":"2026-01-08 01:05:00","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 01:05:01","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":80,"play_type":"ichiban","interval":10,"scheduled_time":"2026-01-08T01:14:29.385+08:00","last_settled":"2026-01-08T01:04:29.385+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 01:05:01","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":80,"st":"2026-01-08 01:14:29","now":"2026-01-08 01:05:00","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 01:05:01","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":81,"play_type":"ichiban","interval":15,"scheduled_time":"2026-01-08T01:10:14.807+08:00","last_settled":"2026-01-08T00:55:14.807+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 01:05:01","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":81,"st":"2026-01-08 01:10:14","now":"2026-01-08 01:05:00","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 01:05:01","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":82,"play_type":"ichiban","interval":15,"scheduled_time":"2026-01-08T01:10:14.807+08:00","last_settled":"2026-01-08T00:55:14.807+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 01:05:01","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":82,"st":"2026-01-08 01:10:14","now":"2026-01-08 01:05:00","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 01:05:01","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":83,"play_type":"ichiban","interval":30,"scheduled_time":"2026-01-08T01:05:26.489+08:00","last_settled":"2026-01-08T00:35:26.489+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 01:05:01","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":83,"st":"2026-01-08 01:05:26","now":"2026-01-08 01:05:00","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 01:05:01","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":84,"play_type":"ichiban","interval":60,"scheduled_time":"2026-01-08T01:27:44.808+08:00","last_settled":"2026-01-08T00:27:44.808+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 01:05:01","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":84,"st":"2026-01-08 01:27:44","now":"2026-01-08 01:05:00","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 01:05:30","caller":"logger/logger.go:315","msg":"定时开奖: 开始检查","domain":"mini-chat[fat]","now":"2026-01-08 01:05:30"}
|
||||
{"level":"debug","time":"2026-01-08 01:05:30","caller":"logger/logger.go:315","msg":"定时开奖: 查询到活动","domain":"mini-chat[fat]","count":9}
|
||||
{"level":"debug","time":"2026-01-08 01:05:30","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":52,"play_type":"ichiban","interval":3,"scheduled_time":"2026-01-08T01:06:14.807+08:00","last_settled":"2026-01-08T01:03:14.807+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 01:05:30","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":52,"st":"2026-01-08 01:06:14","now":"2026-01-08 01:05:30","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 01:05:30","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":65,"play_type":"ichiban","interval":3,"scheduled_time":"2026-01-08T01:05:59.385+08:00","last_settled":"2026-01-08T01:02:59.385+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 01:05:30","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":65,"st":"2026-01-08 01:05:59","now":"2026-01-08 01:05:30","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 01:05:30","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":77,"play_type":"ichiban","interval":5,"scheduled_time":"2026-01-08T01:08:44.807+08:00","last_settled":"2026-01-08T01:03:44.807+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 01:05:30","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":77,"st":"2026-01-08 01:08:44","now":"2026-01-08 01:05:30","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 01:05:30","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":79,"play_type":"ichiban","interval":5,"scheduled_time":"2026-01-08T01:10:14.808+08:00","last_settled":"2026-01-08T01:05:14.808+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 01:05:30","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":79,"st":"2026-01-08 01:10:14","now":"2026-01-08 01:05:30","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 01:05:31","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":80,"play_type":"ichiban","interval":10,"scheduled_time":"2026-01-08T01:14:29.385+08:00","last_settled":"2026-01-08T01:04:29.385+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 01:05:31","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":80,"st":"2026-01-08 01:14:29","now":"2026-01-08 01:05:30","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 01:05:31","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":81,"play_type":"ichiban","interval":15,"scheduled_time":"2026-01-08T01:10:14.807+08:00","last_settled":"2026-01-08T00:55:14.807+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 01:05:31","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":81,"st":"2026-01-08 01:10:14","now":"2026-01-08 01:05:30","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 01:05:31","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":82,"play_type":"ichiban","interval":15,"scheduled_time":"2026-01-08T01:10:14.807+08:00","last_settled":"2026-01-08T00:55:14.807+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 01:05:31","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":82,"st":"2026-01-08 01:10:14","now":"2026-01-08 01:05:30","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 01:05:31","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":83,"play_type":"ichiban","interval":30,"scheduled_time":"2026-01-08T01:35:29.385+08:00","last_settled":"2026-01-08T01:05:29.385+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 01:05:31","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":83,"st":"2026-01-08 01:35:29","now":"2026-01-08 01:05:30","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 01:05:31","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":84,"play_type":"ichiban","interval":60,"scheduled_time":"2026-01-08T01:27:44.808+08:00","last_settled":"2026-01-08T00:27:44.808+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 01:05:31","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":84,"st":"2026-01-08 01:27:44","now":"2026-01-08 01:05:30","skip":true}
|
||||
{"level":"info","time":"2026-01-08 01:05:40","caller":"logger/logger.go:309","msg":"[抖店定时同步] 开始同步","domain":"mini-chat[fat]","interval_minutes":1}
|
||||
[DEBUG] 开始全量同步,共 3 个绑定用户
|
||||
[DEBUG] 正在同步用户 ID: 9018 (昵称: 现实的迪斯蒂法诺, 抖音号: wyl0423333) 的订单...
|
||||
[DEBUG] 正在同步用户 ID: 9019 (昵称: 约翰掐指一算, 抖音号: xrw200947752) 的订单...
|
||||
[DEBUG] 正在同步用户 ID: 9047 (昵称: 巴乔横扫六合, 抖音号: 请输入您的抖店订单号即可完成绑定) 的订单...
|
||||
{"level":"info","time":"2026-01-08 01:05:45","caller":"logger/logger.go:309","msg":"[抖店同步] 全量同步完成","domain":"mini-chat[fat]","users_count":3,"total_fetched":45,"new_orders":0,"matched_users":45}
|
||||
{"level":"info","time":"2026-01-08 01:05:45","caller":"logger/logger.go:309","msg":"[抖店定时同步] 同步成功","domain":"mini-chat[fat]","total_fetched":45,"new_orders":0,"matched_users":45}
|
||||
{"level":"debug","time":"2026-01-08 01:06:00","caller":"logger/logger.go:315","msg":"定时开奖: 开始检查","domain":"mini-chat[fat]","now":"2026-01-08 01:06:00"}
|
||||
{"level":"debug","time":"2026-01-08 01:06:00","caller":"logger/logger.go:315","msg":"定时开奖: 查询到活动","domain":"mini-chat[fat]","count":9}
|
||||
{"level":"debug","time":"2026-01-08 01:06:00","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":52,"play_type":"ichiban","interval":3,"scheduled_time":"2026-01-08T01:06:14.807+08:00","last_settled":"2026-01-08T01:03:14.807+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 01:06:00","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":52,"st":"2026-01-08 01:06:14","now":"2026-01-08 01:06:00","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 01:06:00","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":65,"play_type":"ichiban","interval":3,"scheduled_time":"2026-01-08T01:08:59.386+08:00","last_settled":"2026-01-08T01:05:59.386+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 01:06:00","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":65,"st":"2026-01-08 01:08:59","now":"2026-01-08 01:06:00","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 01:06:00","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":77,"play_type":"ichiban","interval":5,"scheduled_time":"2026-01-08T01:08:44.807+08:00","last_settled":"2026-01-08T01:03:44.807+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 01:06:00","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":77,"st":"2026-01-08 01:08:44","now":"2026-01-08 01:06:00","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 01:06:00","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":79,"play_type":"ichiban","interval":5,"scheduled_time":"2026-01-08T01:10:14.808+08:00","last_settled":"2026-01-08T01:05:14.808+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 01:06:00","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":79,"st":"2026-01-08 01:10:14","now":"2026-01-08 01:06:00","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 01:06:00","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":80,"play_type":"ichiban","interval":10,"scheduled_time":"2026-01-08T01:14:29.385+08:00","last_settled":"2026-01-08T01:04:29.385+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 01:06:01","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":80,"st":"2026-01-08 01:14:29","now":"2026-01-08 01:06:00","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 01:06:01","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":81,"play_type":"ichiban","interval":15,"scheduled_time":"2026-01-08T01:10:14.807+08:00","last_settled":"2026-01-08T00:55:14.807+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 01:06:01","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":81,"st":"2026-01-08 01:10:14","now":"2026-01-08 01:06:00","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 01:06:01","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":82,"play_type":"ichiban","interval":15,"scheduled_time":"2026-01-08T01:10:14.807+08:00","last_settled":"2026-01-08T00:55:14.807+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 01:06:01","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":82,"st":"2026-01-08 01:10:14","now":"2026-01-08 01:06:00","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 01:06:01","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":83,"play_type":"ichiban","interval":30,"scheduled_time":"2026-01-08T01:35:29.385+08:00","last_settled":"2026-01-08T01:05:29.385+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 01:06:01","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":83,"st":"2026-01-08 01:35:29","now":"2026-01-08 01:06:00","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 01:06:01","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":84,"play_type":"ichiban","interval":60,"scheduled_time":"2026-01-08T01:27:44.808+08:00","last_settled":"2026-01-08T00:27:44.808+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 01:06:01","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":84,"st":"2026-01-08 01:27:44","now":"2026-01-08 01:06:00","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 01:06:30","caller":"logger/logger.go:315","msg":"定时开奖: 开始检查","domain":"mini-chat[fat]","now":"2026-01-08 01:06:30"}
|
||||
{"level":"debug","time":"2026-01-08 01:06:30","caller":"logger/logger.go:315","msg":"定时开奖: 查询到活动","domain":"mini-chat[fat]","count":9}
|
||||
{"level":"debug","time":"2026-01-08 01:06:30","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":52,"play_type":"ichiban","interval":3,"scheduled_time":"2026-01-08T01:09:14.808+08:00","last_settled":"2026-01-08T01:06:14.808+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 01:06:30","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":52,"st":"2026-01-08 01:09:14","now":"2026-01-08 01:06:30","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 01:06:30","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":65,"play_type":"ichiban","interval":3,"scheduled_time":"2026-01-08T01:08:59.386+08:00","last_settled":"2026-01-08T01:05:59.386+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 01:06:30","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":65,"st":"2026-01-08 01:08:59","now":"2026-01-08 01:06:30","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 01:06:30","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":77,"play_type":"ichiban","interval":5,"scheduled_time":"2026-01-08T01:08:44.807+08:00","last_settled":"2026-01-08T01:03:44.807+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 01:06:30","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":77,"st":"2026-01-08 01:08:44","now":"2026-01-08 01:06:30","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 01:06:30","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":79,"play_type":"ichiban","interval":5,"scheduled_time":"2026-01-08T01:10:14.808+08:00","last_settled":"2026-01-08T01:05:14.808+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 01:06:30","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":79,"st":"2026-01-08 01:10:14","now":"2026-01-08 01:06:30","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 01:06:31","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":80,"play_type":"ichiban","interval":10,"scheduled_time":"2026-01-08T01:14:29.385+08:00","last_settled":"2026-01-08T01:04:29.385+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 01:06:31","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":80,"st":"2026-01-08 01:14:29","now":"2026-01-08 01:06:30","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 01:06:31","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":81,"play_type":"ichiban","interval":15,"scheduled_time":"2026-01-08T01:10:14.807+08:00","last_settled":"2026-01-08T00:55:14.807+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 01:06:31","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":81,"st":"2026-01-08 01:10:14","now":"2026-01-08 01:06:30","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 01:06:31","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":82,"play_type":"ichiban","interval":15,"scheduled_time":"2026-01-08T01:10:14.807+08:00","last_settled":"2026-01-08T00:55:14.807+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 01:06:31","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":82,"st":"2026-01-08 01:10:14","now":"2026-01-08 01:06:30","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 01:06:31","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":83,"play_type":"ichiban","interval":30,"scheduled_time":"2026-01-08T01:35:29.385+08:00","last_settled":"2026-01-08T01:05:29.385+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 01:06:31","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":83,"st":"2026-01-08 01:35:29","now":"2026-01-08 01:06:30","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 01:06:31","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":84,"play_type":"ichiban","interval":60,"scheduled_time":"2026-01-08T01:27:44.808+08:00","last_settled":"2026-01-08T00:27:44.808+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 01:06:31","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":84,"st":"2026-01-08 01:27:44","now":"2026-01-08 01:06:30","skip":true}
|
||||
{"level":"info","time":"2026-01-08 01:06:45","caller":"logger/logger.go:309","msg":"[抖店定时同步] 开始同步","domain":"mini-chat[fat]","interval_minutes":1}
|
||||
[DEBUG] 开始全量同步,共 3 个绑定用户
|
||||
[DEBUG] 正在同步用户 ID: 9018 (昵称: 现实的迪斯蒂法诺, 抖音号: wyl0423333) 的订单...
|
||||
[DEBUG] 正在同步用户 ID: 9019 (昵称: 约翰掐指一算, 抖音号: xrw200947752) 的订单...
|
||||
[DEBUG] 正在同步用户 ID: 9047 (昵称: 巴乔横扫六合, 抖音号: 请输入您的抖店订单号即可完成绑定) 的订单...
|
||||
{"level":"info","time":"2026-01-08 01:06:50","caller":"logger/logger.go:309","msg":"[抖店同步] 全量同步完成","domain":"mini-chat[fat]","users_count":3,"total_fetched":45,"new_orders":0,"matched_users":45}
|
||||
{"level":"info","time":"2026-01-08 01:06:50","caller":"logger/logger.go:309","msg":"[抖店定时同步] 同步成功","domain":"mini-chat[fat]","total_fetched":45,"new_orders":0,"matched_users":45}
|
||||
{"level":"debug","time":"2026-01-08 01:07:00","caller":"logger/logger.go:315","msg":"定时开奖: 开始检查","domain":"mini-chat[fat]","now":"2026-01-08 01:07:00"}
|
||||
{"level":"debug","time":"2026-01-08 01:07:00","caller":"logger/logger.go:315","msg":"定时开奖: 查询到活动","domain":"mini-chat[fat]","count":9}
|
||||
{"level":"debug","time":"2026-01-08 01:07:00","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":52,"play_type":"ichiban","interval":3,"scheduled_time":"2026-01-08T01:09:14.808+08:00","last_settled":"2026-01-08T01:06:14.808+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 01:07:00","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":52,"st":"2026-01-08 01:09:14","now":"2026-01-08 01:07:00","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 01:07:00","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":65,"play_type":"ichiban","interval":3,"scheduled_time":"2026-01-08T01:08:59.386+08:00","last_settled":"2026-01-08T01:05:59.386+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 01:07:00","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":65,"st":"2026-01-08 01:08:59","now":"2026-01-08 01:07:00","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 01:07:00","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":77,"play_type":"ichiban","interval":5,"scheduled_time":"2026-01-08T01:08:44.807+08:00","last_settled":"2026-01-08T01:03:44.807+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 01:07:00","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":77,"st":"2026-01-08 01:08:44","now":"2026-01-08 01:07:00","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 01:07:00","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":79,"play_type":"ichiban","interval":5,"scheduled_time":"2026-01-08T01:10:14.808+08:00","last_settled":"2026-01-08T01:05:14.808+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 01:07:00","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":79,"st":"2026-01-08 01:10:14","now":"2026-01-08 01:07:00","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 01:07:00","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":80,"play_type":"ichiban","interval":10,"scheduled_time":"2026-01-08T01:14:29.385+08:00","last_settled":"2026-01-08T01:04:29.385+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 01:07:01","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":80,"st":"2026-01-08 01:14:29","now":"2026-01-08 01:07:00","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 01:07:01","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":81,"play_type":"ichiban","interval":15,"scheduled_time":"2026-01-08T01:10:14.807+08:00","last_settled":"2026-01-08T00:55:14.807+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 01:07:01","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":81,"st":"2026-01-08 01:10:14","now":"2026-01-08 01:07:00","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 01:07:01","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":82,"play_type":"ichiban","interval":15,"scheduled_time":"2026-01-08T01:10:14.807+08:00","last_settled":"2026-01-08T00:55:14.807+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 01:07:01","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":82,"st":"2026-01-08 01:10:14","now":"2026-01-08 01:07:00","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 01:07:01","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":83,"play_type":"ichiban","interval":30,"scheduled_time":"2026-01-08T01:35:29.385+08:00","last_settled":"2026-01-08T01:05:29.385+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 01:07:01","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":83,"st":"2026-01-08 01:35:29","now":"2026-01-08 01:07:00","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 01:07:01","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":84,"play_type":"ichiban","interval":60,"scheduled_time":"2026-01-08T01:27:44.808+08:00","last_settled":"2026-01-08T00:27:44.808+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 01:07:01","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":84,"st":"2026-01-08 01:27:44","now":"2026-01-08 01:07:00","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 01:07:30","caller":"logger/logger.go:315","msg":"定时开奖: 开始检查","domain":"mini-chat[fat]","now":"2026-01-08 01:07:30"}
|
||||
{"level":"debug","time":"2026-01-08 01:07:30","caller":"logger/logger.go:315","msg":"定时开奖: 查询到活动","domain":"mini-chat[fat]","count":9}
|
||||
{"level":"debug","time":"2026-01-08 01:07:30","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":52,"play_type":"ichiban","interval":3,"scheduled_time":"2026-01-08T01:09:14.808+08:00","last_settled":"2026-01-08T01:06:14.808+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 01:07:30","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":52,"st":"2026-01-08 01:09:14","now":"2026-01-08 01:07:30","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 01:07:30","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":65,"play_type":"ichiban","interval":3,"scheduled_time":"2026-01-08T01:08:59.386+08:00","last_settled":"2026-01-08T01:05:59.386+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 01:07:30","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":65,"st":"2026-01-08 01:08:59","now":"2026-01-08 01:07:30","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 01:07:30","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":77,"play_type":"ichiban","interval":5,"scheduled_time":"2026-01-08T01:08:44.807+08:00","last_settled":"2026-01-08T01:03:44.807+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 01:07:30","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":77,"st":"2026-01-08 01:08:44","now":"2026-01-08 01:07:30","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 01:07:30","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":79,"play_type":"ichiban","interval":5,"scheduled_time":"2026-01-08T01:10:14.808+08:00","last_settled":"2026-01-08T01:05:14.808+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 01:07:30","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":79,"st":"2026-01-08 01:10:14","now":"2026-01-08 01:07:30","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 01:07:30","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":80,"play_type":"ichiban","interval":10,"scheduled_time":"2026-01-08T01:14:29.385+08:00","last_settled":"2026-01-08T01:04:29.385+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 01:07:31","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":80,"st":"2026-01-08 01:14:29","now":"2026-01-08 01:07:30","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 01:07:31","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":81,"play_type":"ichiban","interval":15,"scheduled_time":"2026-01-08T01:10:14.807+08:00","last_settled":"2026-01-08T00:55:14.807+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 01:07:31","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":81,"st":"2026-01-08 01:10:14","now":"2026-01-08 01:07:30","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 01:07:31","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":82,"play_type":"ichiban","interval":15,"scheduled_time":"2026-01-08T01:10:14.807+08:00","last_settled":"2026-01-08T00:55:14.807+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 01:07:31","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":82,"st":"2026-01-08 01:10:14","now":"2026-01-08 01:07:30","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 01:07:31","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":83,"play_type":"ichiban","interval":30,"scheduled_time":"2026-01-08T01:35:29.385+08:00","last_settled":"2026-01-08T01:05:29.385+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 01:07:31","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":83,"st":"2026-01-08 01:35:29","now":"2026-01-08 01:07:30","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 01:07:31","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":84,"play_type":"ichiban","interval":60,"scheduled_time":"2026-01-08T01:27:44.808+08:00","last_settled":"2026-01-08T00:27:44.808+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 01:07:31","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":84,"st":"2026-01-08 01:27:44","now":"2026-01-08 01:07:30","skip":true}
|
||||
{"level":"info","time":"2026-01-08 01:07:50","caller":"logger/logger.go:309","msg":"[抖店定时同步] 开始同步","domain":"mini-chat[fat]","interval_minutes":1}
|
||||
[DEBUG] 开始全量同步,共 3 个绑定用户
|
||||
[DEBUG] 正在同步用户 ID: 9018 (昵称: 现实的迪斯蒂法诺, 抖音号: wyl0423333) 的订单...
|
||||
[DEBUG] 正在同步用户 ID: 9019 (昵称: 约翰掐指一算, 抖音号: xrw200947752) 的订单...
|
||||
[DEBUG] 正在同步用户 ID: 9047 (昵称: 巴乔横扫六合, 抖音号: 请输入您的抖店订单号即可完成绑定) 的订单...
|
||||
{"level":"info","time":"2026-01-08 01:07:54","caller":"logger/logger.go:309","msg":"[抖店同步] 全量同步完成","domain":"mini-chat[fat]","users_count":3,"total_fetched":45,"new_orders":0,"matched_users":45}
|
||||
{"level":"info","time":"2026-01-08 01:07:54","caller":"logger/logger.go:309","msg":"[抖店定时同步] 同步成功","domain":"mini-chat[fat]","total_fetched":45,"new_orders":0,"matched_users":45}
|
||||
{"level":"debug","time":"2026-01-08 01:08:00","caller":"logger/logger.go:315","msg":"定时开奖: 开始检查","domain":"mini-chat[fat]","now":"2026-01-08 01:08:00"}
|
||||
{"level":"debug","time":"2026-01-08 01:08:00","caller":"logger/logger.go:315","msg":"定时开奖: 查询到活动","domain":"mini-chat[fat]","count":9}
|
||||
{"level":"debug","time":"2026-01-08 01:08:00","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":52,"play_type":"ichiban","interval":3,"scheduled_time":"2026-01-08T01:09:14.808+08:00","last_settled":"2026-01-08T01:06:14.808+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 01:08:00","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":52,"st":"2026-01-08 01:09:14","now":"2026-01-08 01:08:00","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 01:08:00","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":65,"play_type":"ichiban","interval":3,"scheduled_time":"2026-01-08T01:08:59.386+08:00","last_settled":"2026-01-08T01:05:59.386+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 01:08:00","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":65,"st":"2026-01-08 01:08:59","now":"2026-01-08 01:08:00","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 01:08:00","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":77,"play_type":"ichiban","interval":5,"scheduled_time":"2026-01-08T01:08:44.807+08:00","last_settled":"2026-01-08T01:03:44.807+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 01:08:00","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":77,"st":"2026-01-08 01:08:44","now":"2026-01-08 01:08:00","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 01:08:01","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":79,"play_type":"ichiban","interval":5,"scheduled_time":"2026-01-08T01:10:14.808+08:00","last_settled":"2026-01-08T01:05:14.808+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 01:08:01","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":79,"st":"2026-01-08 01:10:14","now":"2026-01-08 01:08:00","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 01:08:01","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":80,"play_type":"ichiban","interval":10,"scheduled_time":"2026-01-08T01:14:29.385+08:00","last_settled":"2026-01-08T01:04:29.385+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 01:08:01","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":80,"st":"2026-01-08 01:14:29","now":"2026-01-08 01:08:00","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 01:08:01","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":81,"play_type":"ichiban","interval":15,"scheduled_time":"2026-01-08T01:10:14.807+08:00","last_settled":"2026-01-08T00:55:14.807+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 01:08:01","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":81,"st":"2026-01-08 01:10:14","now":"2026-01-08 01:08:00","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 01:08:01","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":82,"play_type":"ichiban","interval":15,"scheduled_time":"2026-01-08T01:10:14.807+08:00","last_settled":"2026-01-08T00:55:14.807+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 01:08:01","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":82,"st":"2026-01-08 01:10:14","now":"2026-01-08 01:08:00","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 01:08:01","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":83,"play_type":"ichiban","interval":30,"scheduled_time":"2026-01-08T01:35:29.385+08:00","last_settled":"2026-01-08T01:05:29.385+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 01:08:01","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":83,"st":"2026-01-08 01:35:29","now":"2026-01-08 01:08:00","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 01:08:01","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":84,"play_type":"ichiban","interval":60,"scheduled_time":"2026-01-08T01:27:44.808+08:00","last_settled":"2026-01-08T00:27:44.808+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 01:08:01","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":84,"st":"2026-01-08 01:27:44","now":"2026-01-08 01:08:00","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 01:08:30","caller":"logger/logger.go:315","msg":"定时开奖: 开始检查","domain":"mini-chat[fat]","now":"2026-01-08 01:08:30"}
|
||||
{"level":"debug","time":"2026-01-08 01:08:30","caller":"logger/logger.go:315","msg":"定时开奖: 查询到活动","domain":"mini-chat[fat]","count":9}
|
||||
{"level":"debug","time":"2026-01-08 01:08:30","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":52,"play_type":"ichiban","interval":3,"scheduled_time":"2026-01-08T01:09:14.808+08:00","last_settled":"2026-01-08T01:06:14.808+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 01:08:30","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":52,"st":"2026-01-08 01:09:14","now":"2026-01-08 01:08:30","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 01:08:30","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":65,"play_type":"ichiban","interval":3,"scheduled_time":"2026-01-08T01:08:59.386+08:00","last_settled":"2026-01-08T01:05:59.386+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 01:08:30","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":65,"st":"2026-01-08 01:08:59","now":"2026-01-08 01:08:30","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 01:08:30","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":77,"play_type":"ichiban","interval":5,"scheduled_time":"2026-01-08T01:08:44.807+08:00","last_settled":"2026-01-08T01:03:44.807+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 01:08:30","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":77,"st":"2026-01-08 01:08:44","now":"2026-01-08 01:08:30","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 01:08:30","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":79,"play_type":"ichiban","interval":5,"scheduled_time":"2026-01-08T01:10:14.808+08:00","last_settled":"2026-01-08T01:05:14.808+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 01:08:30","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":79,"st":"2026-01-08 01:10:14","now":"2026-01-08 01:08:30","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 01:08:31","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":80,"play_type":"ichiban","interval":10,"scheduled_time":"2026-01-08T01:14:29.385+08:00","last_settled":"2026-01-08T01:04:29.385+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 01:08:31","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":80,"st":"2026-01-08 01:14:29","now":"2026-01-08 01:08:30","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 01:08:31","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":81,"play_type":"ichiban","interval":15,"scheduled_time":"2026-01-08T01:10:14.807+08:00","last_settled":"2026-01-08T00:55:14.807+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 01:08:31","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":81,"st":"2026-01-08 01:10:14","now":"2026-01-08 01:08:30","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 01:08:31","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":82,"play_type":"ichiban","interval":15,"scheduled_time":"2026-01-08T01:10:14.807+08:00","last_settled":"2026-01-08T00:55:14.807+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 01:08:31","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":82,"st":"2026-01-08 01:10:14","now":"2026-01-08 01:08:30","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 01:08:31","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":83,"play_type":"ichiban","interval":30,"scheduled_time":"2026-01-08T01:35:29.385+08:00","last_settled":"2026-01-08T01:05:29.385+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 01:08:31","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":83,"st":"2026-01-08 01:35:29","now":"2026-01-08 01:08:30","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 01:08:31","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":84,"play_type":"ichiban","interval":60,"scheduled_time":"2026-01-08T01:27:44.808+08:00","last_settled":"2026-01-08T00:27:44.808+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 01:08:31","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":84,"st":"2026-01-08 01:27:44","now":"2026-01-08 01:08:30","skip":true}
|
||||
{"level":"info","time":"2026-01-08 01:08:54","caller":"logger/logger.go:309","msg":"[抖店定时同步] 开始同步","domain":"mini-chat[fat]","interval_minutes":1}
|
||||
[DEBUG] 开始全量同步,共 3 个绑定用户
|
||||
[DEBUG] 正在同步用户 ID: 9018 (昵称: 现实的迪斯蒂法诺, 抖音号: wyl0423333) 的订单...
|
||||
[DEBUG] 正在同步用户 ID: 9019 (昵称: 约翰掐指一算, 抖音号: xrw200947752) 的订单...
|
||||
[DEBUG] 正在同步用户 ID: 9047 (昵称: 巴乔横扫六合, 抖音号: 请输入您的抖店订单号即可完成绑定) 的订单...
|
||||
{"level":"info","time":"2026-01-08 01:08:59","caller":"logger/logger.go:309","msg":"[抖店同步] 全量同步完成","domain":"mini-chat[fat]","users_count":3,"total_fetched":45,"new_orders":0,"matched_users":45}
|
||||
{"level":"info","time":"2026-01-08 01:08:59","caller":"logger/logger.go:309","msg":"[抖店定时同步] 同步成功","domain":"mini-chat[fat]","total_fetched":45,"new_orders":0,"matched_users":45}
|
||||
{"level":"debug","time":"2026-01-08 01:09:00","caller":"logger/logger.go:315","msg":"定时开奖: 开始检查","domain":"mini-chat[fat]","now":"2026-01-08 01:09:00"}
|
||||
{"level":"debug","time":"2026-01-08 01:09:00","caller":"logger/logger.go:315","msg":"定时开奖: 查询到活动","domain":"mini-chat[fat]","count":9}
|
||||
{"level":"debug","time":"2026-01-08 01:09:00","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":52,"play_type":"ichiban","interval":3,"scheduled_time":"2026-01-08T01:09:14.808+08:00","last_settled":"2026-01-08T01:06:14.808+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 01:09:00","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":52,"st":"2026-01-08 01:09:14","now":"2026-01-08 01:09:00","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 01:09:00","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":65,"play_type":"ichiban","interval":3,"scheduled_time":"2026-01-08T01:08:59.386+08:00","last_settled":"2026-01-08T01:05:59.386+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 01:09:00","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":65,"st":"2026-01-08 01:08:59","now":"2026-01-08 01:09:00","skip":false}
|
||||
{"level":"debug","time":"2026-01-08 01:09:00","caller":"logger/logger.go:315","msg":"定时开奖: 查询订单范围","domain":"mini-chat[fat]","id":65,"last":"2026-01-08 01:05:59","now":"2026-01-08 01:09:00"}
|
||||
{"level":"debug","time":"2026-01-08 01:09:00","caller":"logger/logger.go:315","msg":"定时开奖: 查询到订单","domain":"mini-chat[fat]","id":65,"count":0,"min":1}
|
||||
{"level":"info","time":"2026-01-08 01:09:00","caller":"logger/logger.go:309","msg":"定时开奖: 人数满足,开始开奖处理","domain":"mini-chat[fat]","id":65}
|
||||
{"level":"info","time":"2026-01-08 01:09:00","caller":"logger/logger.go:309","msg":"定时开奖: 更新活动下次结算时间","domain":"mini-chat[fat]","id":65,"last":"2026-01-08 01:09:00","next":"2026-01-08 01:12:00"}
|
||||
{"level":"debug","time":"2026-01-08 01:09:01","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":77,"play_type":"ichiban","interval":5,"scheduled_time":"2026-01-08T01:13:44.807+08:00","last_settled":"2026-01-08T01:08:44.807+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 01:09:01","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":77,"st":"2026-01-08 01:13:44","now":"2026-01-08 01:09:00","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 01:09:01","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":79,"play_type":"ichiban","interval":5,"scheduled_time":"2026-01-08T01:10:14.808+08:00","last_settled":"2026-01-08T01:05:14.808+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 01:09:01","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":79,"st":"2026-01-08 01:10:14","now":"2026-01-08 01:09:00","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 01:09:01","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":80,"play_type":"ichiban","interval":10,"scheduled_time":"2026-01-08T01:14:29.385+08:00","last_settled":"2026-01-08T01:04:29.385+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 01:09:01","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":80,"st":"2026-01-08 01:14:29","now":"2026-01-08 01:09:00","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 01:09:01","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":81,"play_type":"ichiban","interval":15,"scheduled_time":"2026-01-08T01:10:14.807+08:00","last_settled":"2026-01-08T00:55:14.807+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 01:09:01","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":81,"st":"2026-01-08 01:10:14","now":"2026-01-08 01:09:00","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 01:09:01","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":82,"play_type":"ichiban","interval":15,"scheduled_time":"2026-01-08T01:10:14.807+08:00","last_settled":"2026-01-08T00:55:14.807+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 01:09:01","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":82,"st":"2026-01-08 01:10:14","now":"2026-01-08 01:09:00","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 01:09:01","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":83,"play_type":"ichiban","interval":30,"scheduled_time":"2026-01-08T01:35:29.385+08:00","last_settled":"2026-01-08T01:05:29.385+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 01:09:01","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":83,"st":"2026-01-08 01:35:29","now":"2026-01-08 01:09:00","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 01:09:01","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":84,"play_type":"ichiban","interval":60,"scheduled_time":"2026-01-08T01:27:44.808+08:00","last_settled":"2026-01-08T00:27:44.808+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 01:09:01","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":84,"st":"2026-01-08 01:27:44","now":"2026-01-08 01:09:00","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 01:09:30","caller":"logger/logger.go:315","msg":"定时开奖: 开始检查","domain":"mini-chat[fat]","now":"2026-01-08 01:09:30"}
|
||||
{"level":"debug","time":"2026-01-08 01:09:30","caller":"logger/logger.go:315","msg":"定时开奖: 查询到活动","domain":"mini-chat[fat]","count":9}
|
||||
{"level":"debug","time":"2026-01-08 01:09:30","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":52,"play_type":"ichiban","interval":3,"scheduled_time":"2026-01-08T01:12:29.386+08:00","last_settled":"2026-01-08T01:09:29.386+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 01:09:30","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":52,"st":"2026-01-08 01:12:29","now":"2026-01-08 01:09:30","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 01:09:30","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":65,"play_type":"ichiban","interval":3,"scheduled_time":"2026-01-08T01:12:00.509+08:00","last_settled":"2026-01-08T01:09:00.509+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 01:09:30","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":65,"st":"2026-01-08 01:12:00","now":"2026-01-08 01:09:30","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 01:09:30","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":77,"play_type":"ichiban","interval":5,"scheduled_time":"2026-01-08T01:13:44.807+08:00","last_settled":"2026-01-08T01:08:44.807+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 01:09:30","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":77,"st":"2026-01-08 01:13:44","now":"2026-01-08 01:09:30","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 01:09:30","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":79,"play_type":"ichiban","interval":5,"scheduled_time":"2026-01-08T01:10:14.808+08:00","last_settled":"2026-01-08T01:05:14.808+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 01:09:30","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":79,"st":"2026-01-08 01:10:14","now":"2026-01-08 01:09:30","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 01:09:31","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":80,"play_type":"ichiban","interval":10,"scheduled_time":"2026-01-08T01:14:29.385+08:00","last_settled":"2026-01-08T01:04:29.385+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 01:09:31","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":80,"st":"2026-01-08 01:14:29","now":"2026-01-08 01:09:30","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 01:09:31","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":81,"play_type":"ichiban","interval":15,"scheduled_time":"2026-01-08T01:10:14.807+08:00","last_settled":"2026-01-08T00:55:14.807+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 01:09:31","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":81,"st":"2026-01-08 01:10:14","now":"2026-01-08 01:09:30","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 01:09:31","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":82,"play_type":"ichiban","interval":15,"scheduled_time":"2026-01-08T01:10:14.807+08:00","last_settled":"2026-01-08T00:55:14.807+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 01:09:31","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":82,"st":"2026-01-08 01:10:14","now":"2026-01-08 01:09:30","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 01:09:31","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":83,"play_type":"ichiban","interval":30,"scheduled_time":"2026-01-08T01:35:29.385+08:00","last_settled":"2026-01-08T01:05:29.385+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 01:09:31","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":83,"st":"2026-01-08 01:35:29","now":"2026-01-08 01:09:30","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 01:09:31","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":84,"play_type":"ichiban","interval":60,"scheduled_time":"2026-01-08T01:27:44.808+08:00","last_settled":"2026-01-08T00:27:44.808+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 01:09:31","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":84,"st":"2026-01-08 01:27:44","now":"2026-01-08 01:09:30","skip":true}
|
||||
{"level":"info","time":"2026-01-08 01:09:59","caller":"logger/logger.go:309","msg":"[抖店定时同步] 开始同步","domain":"mini-chat[fat]","interval_minutes":1}
|
||||
[DEBUG] 开始全量同步,共 3 个绑定用户
|
||||
[DEBUG] 正在同步用户 ID: 9018 (昵称: 现实的迪斯蒂法诺, 抖音号: wyl0423333) 的订单...
|
||||
{"level":"debug","time":"2026-01-08 01:10:00","caller":"logger/logger.go:315","msg":"定时开奖: 开始检查","domain":"mini-chat[fat]","now":"2026-01-08 01:10:00"}
|
||||
{"level":"debug","time":"2026-01-08 01:10:00","caller":"logger/logger.go:315","msg":"定时开奖: 查询到活动","domain":"mini-chat[fat]","count":9}
|
||||
{"level":"debug","time":"2026-01-08 01:10:00","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":52,"play_type":"ichiban","interval":3,"scheduled_time":"2026-01-08T01:12:29.386+08:00","last_settled":"2026-01-08T01:09:29.386+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 01:10:00","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":52,"st":"2026-01-08 01:12:29","now":"2026-01-08 01:10:00","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 01:10:00","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":65,"play_type":"ichiban","interval":3,"scheduled_time":"2026-01-08T01:12:00.509+08:00","last_settled":"2026-01-08T01:09:00.509+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 01:10:00","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":65,"st":"2026-01-08 01:12:00","now":"2026-01-08 01:10:00","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 01:10:00","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":77,"play_type":"ichiban","interval":5,"scheduled_time":"2026-01-08T01:13:44.807+08:00","last_settled":"2026-01-08T01:08:44.807+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 01:10:00","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":77,"st":"2026-01-08 01:13:44","now":"2026-01-08 01:10:00","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 01:10:00","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":79,"play_type":"ichiban","interval":5,"scheduled_time":"2026-01-08T01:10:14.808+08:00","last_settled":"2026-01-08T01:05:14.808+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 01:10:00","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":79,"st":"2026-01-08 01:10:14","now":"2026-01-08 01:10:00","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 01:10:01","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":80,"play_type":"ichiban","interval":10,"scheduled_time":"2026-01-08T01:14:29.385+08:00","last_settled":"2026-01-08T01:04:29.385+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 01:10:01","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":80,"st":"2026-01-08 01:14:29","now":"2026-01-08 01:10:00","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 01:10:01","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":81,"play_type":"ichiban","interval":15,"scheduled_time":"2026-01-08T01:10:14.807+08:00","last_settled":"2026-01-08T00:55:14.807+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 01:10:01","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":81,"st":"2026-01-08 01:10:14","now":"2026-01-08 01:10:00","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 01:10:01","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":82,"play_type":"ichiban","interval":15,"scheduled_time":"2026-01-08T01:10:14.807+08:00","last_settled":"2026-01-08T00:55:14.807+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 01:10:01","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":82,"st":"2026-01-08 01:10:14","now":"2026-01-08 01:10:00","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 01:10:01","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":83,"play_type":"ichiban","interval":30,"scheduled_time":"2026-01-08T01:35:29.385+08:00","last_settled":"2026-01-08T01:05:29.385+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 01:10:01","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":83,"st":"2026-01-08 01:35:29","now":"2026-01-08 01:10:00","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 01:10:01","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":84,"play_type":"ichiban","interval":60,"scheduled_time":"2026-01-08T01:27:44.808+08:00","last_settled":"2026-01-08T00:27:44.808+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 01:10:01","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":84,"st":"2026-01-08 01:27:44","now":"2026-01-08 01:10:00","skip":true}
|
||||
[DEBUG] 正在同步用户 ID: 9019 (昵称: 约翰掐指一算, 抖音号: xrw200947752) 的订单...
|
||||
[DEBUG] 正在同步用户 ID: 9047 (昵称: 巴乔横扫六合, 抖音号: 请输入您的抖店订单号即可完成绑定) 的订单...
|
||||
{"level":"info","time":"2026-01-08 01:10:04","caller":"logger/logger.go:309","msg":"[抖店同步] 全量同步完成","domain":"mini-chat[fat]","users_count":3,"total_fetched":45,"new_orders":0,"matched_users":45}
|
||||
{"level":"info","time":"2026-01-08 01:10:04","caller":"logger/logger.go:309","msg":"[抖店定时同步] 同步成功","domain":"mini-chat[fat]","total_fetched":45,"new_orders":0,"matched_users":45}
|
||||
signal: killed
|
||||
195
backend_new.log
Normal file
195
backend_new.log
Normal file
@ -0,0 +1,195 @@
|
||||
{"level":"info","time":"2026-01-08 00:56:40","caller":"logger/logger.go:309","msg":"Connected to Redis","domain":"mini-chat[fat]","addr":"118.25.13.43:8379"}
|
||||
|
||||
[32m ____ _ _ _ ____[0m
|
||||
[32m | __ ) (_) _ __ __| | | |__ ___ __ __ / ___| __ _ _ __ ___ ___[0m
|
||||
[32m | _ \ | | | '_ \ / _` | | '_ \ / _ \ \ \/ / | | _ / _` | | '_ ` _ \ / _ \[0m
|
||||
[32m | |_) | | | | | | | | (_| | | |_) | | (_) | > < | |_| | | (_| | | | | | | | | __/[0m
|
||||
[32m |____/ |_| |_| |_| \__,_| |_.__/ \___/ /_/\_\ \____| \__,_| |_| |_| |_| \___|[0m
|
||||
▌ 客户项目: 盲盒游戏
|
||||
▌ 项目版本: Release-2025111111
|
||||
▌ 启动时间: 2026-01-08 00:56:40
|
||||
▌ 运行环境: darwin go1.24.2
|
||||
▌ 服务端口: [:9991]
|
||||
▌ 服务配置: [fat]
|
||||
|
||||
▌ 数据库连接: ✔ 已建立
|
||||
|
||||
{"level":"info","time":"2026-01-08 00:56:40","caller":"logger/logger.go:309","msg":"Task center worker started","domain":"mini-chat[fat]"}
|
||||
{"level":"info","time":"2026-01-08 00:56:40","caller":"logger/logger.go:309","msg":"对对碰自动开奖: 后台任务已启动","domain":"mini-chat[fat]"}
|
||||
{"level":"info","time":"2026-01-08 00:56:40","caller":"logger/logger.go:309","msg":"[抖店定时同步] 定时任务已启动","domain":"mini-chat[fat]"}
|
||||
{"level":"info","time":"2026-01-08 00:56:40","caller":"logger/logger.go:309","msg":"Worker routine started","domain":"mini-chat[fat]","worker_id":4}
|
||||
{"level":"info","time":"2026-01-08 00:56:40","caller":"logger/logger.go:309","msg":"Worker routine started","domain":"mini-chat[fat]","worker_id":0}
|
||||
{"level":"info","time":"2026-01-08 00:56:40","caller":"logger/logger.go:309","msg":"Worker routine started","domain":"mini-chat[fat]","worker_id":3}
|
||||
{"level":"info","time":"2026-01-08 00:56:40","caller":"logger/logger.go:309","msg":"Worker routine started","domain":"mini-chat[fat]","worker_id":1}
|
||||
{"level":"info","time":"2026-01-08 00:56:40","caller":"logger/logger.go:309","msg":"Worker routine started","domain":"mini-chat[fat]","worker_id":2}
|
||||
{"level":"error","time":"2026-01-08 00:56:40","caller":"logger/logger.go:327","msg":"解密配置失败","domain":"mini-chat[fat]","key":"douyin.app_secret","error":"ciphertext is not a multiple of the block size"}
|
||||
{"level":"info","time":"2026-01-08 00:56:40","caller":"logger/logger.go:309","msg":"动态配置加载完成","domain":"mini-chat[fat]","count":26}
|
||||
{"level":"debug","time":"2026-01-08 00:57:10","caller":"logger/logger.go:315","msg":"定时开奖: 开始检查","domain":"mini-chat[fat]","now":"2026-01-08 00:57:10"}
|
||||
{"level":"info","time":"2026-01-08 00:57:10","caller":"logger/logger.go:309","msg":"[抖店定时同步] 开始同步","domain":"mini-chat[fat]","interval_minutes":1}
|
||||
[DEBUG] 开始全量同步,共 3 个绑定用户
|
||||
[DEBUG] 正在同步用户 ID: 9018 (昵称: 现实的迪斯蒂法诺, 抖音号: wyl0423333) 的订单...
|
||||
{"level":"debug","time":"2026-01-08 00:57:10","caller":"logger/logger.go:315","msg":"定时开奖: 查询到活动","domain":"mini-chat[fat]","count":9}
|
||||
{"level":"debug","time":"2026-01-08 00:57:10","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":52,"play_type":"ichiban","interval":3,"scheduled_time":"2026-01-08T00:56:59.386+08:00","last_settled":"2026-01-08T00:53:59.386+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 00:57:10","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":52,"st":"2026-01-08 00:56:59","now":"2026-01-08 00:57:10","skip":false}
|
||||
{"level":"debug","time":"2026-01-08 00:57:10","caller":"logger/logger.go:315","msg":"定时开奖: 查询订单范围","domain":"mini-chat[fat]","id":52,"last":"2026-01-08 00:53:59","now":"2026-01-08 00:57:10"}
|
||||
{"level":"debug","time":"2026-01-08 00:57:10","caller":"logger/logger.go:315","msg":"定时开奖: 查询到订单","domain":"mini-chat[fat]","id":52,"count":0,"min":1}
|
||||
{"level":"info","time":"2026-01-08 00:57:10","caller":"logger/logger.go:309","msg":"定时开奖: 人数满足,开始开奖处理","domain":"mini-chat[fat]","id":52}
|
||||
{"level":"info","time":"2026-01-08 00:57:10","caller":"logger/logger.go:309","msg":"定时开奖: 更新活动下次结算时间","domain":"mini-chat[fat]","id":52,"last":"2026-01-08 00:57:10","next":"2026-01-08 01:00:10"}
|
||||
{"level":"debug","time":"2026-01-08 00:57:10","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":65,"play_type":"ichiban","interval":3,"scheduled_time":"2026-01-08T00:59:44.808+08:00","last_settled":"2026-01-08T00:56:44.808+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 00:57:10","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":65,"st":"2026-01-08 00:59:44","now":"2026-01-08 00:57:10","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 00:57:10","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":77,"play_type":"ichiban","interval":5,"scheduled_time":"2026-01-08T00:58:44.807+08:00","last_settled":"2026-01-08T00:53:44.807+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 00:57:10","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":77,"st":"2026-01-08 00:58:44","now":"2026-01-08 00:57:10","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 00:57:10","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":79,"play_type":"ichiban","interval":5,"scheduled_time":"2026-01-08T01:00:14.807+08:00","last_settled":"2026-01-08T00:55:14.807+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 00:57:10","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":79,"st":"2026-01-08 01:00:14","now":"2026-01-08 00:57:10","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 00:57:10","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":80,"play_type":"ichiban","interval":10,"scheduled_time":"2026-01-08T01:04:18.148+08:00","last_settled":"2026-01-08T00:54:18.148+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 00:57:10","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":80,"st":"2026-01-08 01:04:18","now":"2026-01-08 00:57:10","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 00:57:11","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":81,"play_type":"ichiban","interval":15,"scheduled_time":"2026-01-08T01:10:14.807+08:00","last_settled":"2026-01-08T00:55:14.807+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 00:57:11","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":81,"st":"2026-01-08 01:10:14","now":"2026-01-08 00:57:10","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 00:57:11","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":82,"play_type":"ichiban","interval":15,"scheduled_time":"2026-01-08T01:10:14.807+08:00","last_settled":"2026-01-08T00:55:14.807+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 00:57:11","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":82,"st":"2026-01-08 01:10:14","now":"2026-01-08 00:57:10","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 00:57:11","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":83,"play_type":"ichiban","interval":30,"scheduled_time":"2026-01-08T01:05:26.489+08:00","last_settled":"2026-01-08T00:35:26.489+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 00:57:11","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":83,"st":"2026-01-08 01:05:26","now":"2026-01-08 00:57:10","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 00:57:11","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":84,"play_type":"ichiban","interval":60,"scheduled_time":"2026-01-08T01:27:44.808+08:00","last_settled":"2026-01-08T00:27:44.808+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 00:57:11","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":84,"st":"2026-01-08 01:27:44","now":"2026-01-08 00:57:10","skip":true}
|
||||
[DEBUG] 正在同步用户 ID: 9019 (昵称: 约翰掐指一算, 抖音号: xrw200947752) 的订单...
|
||||
[DEBUG] 正在同步用户 ID: 9047 (昵称: 巴乔横扫六合, 抖音号: 请输入您的抖店订单号即可完成绑定) 的订单...
|
||||
{"level":"info","time":"2026-01-08 00:57:14","caller":"logger/logger.go:309","msg":"[抖店同步] 全量同步完成","domain":"mini-chat[fat]","users_count":3,"total_fetched":45,"new_orders":0,"matched_users":45}
|
||||
{"level":"info","time":"2026-01-08 00:57:14","caller":"logger/logger.go:309","msg":"[抖店定时同步] 同步成功","domain":"mini-chat[fat]","total_fetched":45,"new_orders":0,"matched_users":45}
|
||||
{"level":"debug","time":"2026-01-08 00:57:40","caller":"logger/logger.go:315","msg":"定时开奖: 开始检查","domain":"mini-chat[fat]","now":"2026-01-08 00:57:40"}
|
||||
{"level":"debug","time":"2026-01-08 00:57:40","caller":"logger/logger.go:315","msg":"定时开奖: 查询到活动","domain":"mini-chat[fat]","count":9}
|
||||
{"level":"debug","time":"2026-01-08 00:57:40","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":52,"play_type":"ichiban","interval":3,"scheduled_time":"2026-01-08T01:00:10.204+08:00","last_settled":"2026-01-08T00:57:10.204+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 00:57:40","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":52,"st":"2026-01-08 01:00:10","now":"2026-01-08 00:57:40","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 00:57:40","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":65,"play_type":"ichiban","interval":3,"scheduled_time":"2026-01-08T00:59:44.808+08:00","last_settled":"2026-01-08T00:56:44.808+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 00:57:40","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":65,"st":"2026-01-08 00:59:44","now":"2026-01-08 00:57:40","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 00:57:40","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":77,"play_type":"ichiban","interval":5,"scheduled_time":"2026-01-08T00:58:44.807+08:00","last_settled":"2026-01-08T00:53:44.807+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 00:57:40","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":77,"st":"2026-01-08 00:58:44","now":"2026-01-08 00:57:40","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 00:57:40","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":79,"play_type":"ichiban","interval":5,"scheduled_time":"2026-01-08T01:00:14.807+08:00","last_settled":"2026-01-08T00:55:14.807+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 00:57:40","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":79,"st":"2026-01-08 01:00:14","now":"2026-01-08 00:57:40","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 00:57:40","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":80,"play_type":"ichiban","interval":10,"scheduled_time":"2026-01-08T01:04:18.148+08:00","last_settled":"2026-01-08T00:54:18.148+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 00:57:40","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":80,"st":"2026-01-08 01:04:18","now":"2026-01-08 00:57:40","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 00:57:40","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":81,"play_type":"ichiban","interval":15,"scheduled_time":"2026-01-08T01:10:14.807+08:00","last_settled":"2026-01-08T00:55:14.807+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 00:57:40","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":81,"st":"2026-01-08 01:10:14","now":"2026-01-08 00:57:40","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 00:57:40","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":82,"play_type":"ichiban","interval":15,"scheduled_time":"2026-01-08T01:10:14.807+08:00","last_settled":"2026-01-08T00:55:14.807+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 00:57:40","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":82,"st":"2026-01-08 01:10:14","now":"2026-01-08 00:57:40","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 00:57:40","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":83,"play_type":"ichiban","interval":30,"scheduled_time":"2026-01-08T01:05:26.489+08:00","last_settled":"2026-01-08T00:35:26.489+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 00:57:40","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":83,"st":"2026-01-08 01:05:26","now":"2026-01-08 00:57:40","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 00:57:40","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":84,"play_type":"ichiban","interval":60,"scheduled_time":"2026-01-08T01:27:44.808+08:00","last_settled":"2026-01-08T00:27:44.808+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 00:57:40","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":84,"st":"2026-01-08 01:27:44","now":"2026-01-08 00:57:40","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 00:58:10","caller":"logger/logger.go:315","msg":"定时开奖: 开始检查","domain":"mini-chat[fat]","now":"2026-01-08 00:58:10"}
|
||||
{"level":"debug","time":"2026-01-08 00:58:10","caller":"logger/logger.go:315","msg":"定时开奖: 查询到活动","domain":"mini-chat[fat]","count":9}
|
||||
{"level":"debug","time":"2026-01-08 00:58:10","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":52,"play_type":"ichiban","interval":3,"scheduled_time":"2026-01-08T01:00:10.204+08:00","last_settled":"2026-01-08T00:57:10.204+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 00:58:10","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":52,"st":"2026-01-08 01:00:10","now":"2026-01-08 00:58:10","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 00:58:10","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":65,"play_type":"ichiban","interval":3,"scheduled_time":"2026-01-08T00:59:44.808+08:00","last_settled":"2026-01-08T00:56:44.808+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 00:58:10","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":65,"st":"2026-01-08 00:59:44","now":"2026-01-08 00:58:10","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 00:58:10","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":77,"play_type":"ichiban","interval":5,"scheduled_time":"2026-01-08T00:58:44.807+08:00","last_settled":"2026-01-08T00:53:44.807+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 00:58:10","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":77,"st":"2026-01-08 00:58:44","now":"2026-01-08 00:58:10","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 00:58:10","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":79,"play_type":"ichiban","interval":5,"scheduled_time":"2026-01-08T01:00:14.807+08:00","last_settled":"2026-01-08T00:55:14.807+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 00:58:10","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":79,"st":"2026-01-08 01:00:14","now":"2026-01-08 00:58:10","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 00:58:10","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":80,"play_type":"ichiban","interval":10,"scheduled_time":"2026-01-08T01:04:18.148+08:00","last_settled":"2026-01-08T00:54:18.148+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 00:58:10","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":80,"st":"2026-01-08 01:04:18","now":"2026-01-08 00:58:10","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 00:58:10","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":81,"play_type":"ichiban","interval":15,"scheduled_time":"2026-01-08T01:10:14.807+08:00","last_settled":"2026-01-08T00:55:14.807+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 00:58:10","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":81,"st":"2026-01-08 01:10:14","now":"2026-01-08 00:58:10","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 00:58:10","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":82,"play_type":"ichiban","interval":15,"scheduled_time":"2026-01-08T01:10:14.807+08:00","last_settled":"2026-01-08T00:55:14.807+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 00:58:10","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":82,"st":"2026-01-08 01:10:14","now":"2026-01-08 00:58:10","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 00:58:10","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":83,"play_type":"ichiban","interval":30,"scheduled_time":"2026-01-08T01:05:26.489+08:00","last_settled":"2026-01-08T00:35:26.489+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 00:58:10","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":83,"st":"2026-01-08 01:05:26","now":"2026-01-08 00:58:10","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 00:58:11","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":84,"play_type":"ichiban","interval":60,"scheduled_time":"2026-01-08T01:27:44.808+08:00","last_settled":"2026-01-08T00:27:44.808+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 00:58:11","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":84,"st":"2026-01-08 01:27:44","now":"2026-01-08 00:58:10","skip":true}
|
||||
{"level":"info","time":"2026-01-08 00:58:14","caller":"logger/logger.go:309","msg":"[抖店定时同步] 开始同步","domain":"mini-chat[fat]","interval_minutes":1}
|
||||
[DEBUG] 开始全量同步,共 3 个绑定用户
|
||||
[DEBUG] 正在同步用户 ID: 9018 (昵称: 现实的迪斯蒂法诺, 抖音号: wyl0423333) 的订单...
|
||||
[DEBUG] 正在同步用户 ID: 9019 (昵称: 约翰掐指一算, 抖音号: xrw200947752) 的订单...
|
||||
[DEBUG] 正在同步用户 ID: 9047 (昵称: 巴乔横扫六合, 抖音号: 请输入您的抖店订单号即可完成绑定) 的订单...
|
||||
{"level":"info","time":"2026-01-08 00:58:19","caller":"logger/logger.go:309","msg":"[抖店同步] 全量同步完成","domain":"mini-chat[fat]","users_count":3,"total_fetched":45,"new_orders":0,"matched_users":45}
|
||||
{"level":"info","time":"2026-01-08 00:58:19","caller":"logger/logger.go:309","msg":"[抖店定时同步] 同步成功","domain":"mini-chat[fat]","total_fetched":45,"new_orders":0,"matched_users":45}
|
||||
{"level":"debug","time":"2026-01-08 00:58:40","caller":"logger/logger.go:315","msg":"定时开奖: 开始检查","domain":"mini-chat[fat]","now":"2026-01-08 00:58:40"}
|
||||
{"level":"debug","time":"2026-01-08 00:58:40","caller":"logger/logger.go:315","msg":"定时开奖: 查询到活动","domain":"mini-chat[fat]","count":9}
|
||||
{"level":"debug","time":"2026-01-08 00:58:40","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":52,"play_type":"ichiban","interval":3,"scheduled_time":"2026-01-08T01:00:10.204+08:00","last_settled":"2026-01-08T00:57:10.204+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 00:58:40","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":52,"st":"2026-01-08 01:00:10","now":"2026-01-08 00:58:40","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 00:58:40","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":65,"play_type":"ichiban","interval":3,"scheduled_time":"2026-01-08T00:59:44.808+08:00","last_settled":"2026-01-08T00:56:44.808+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 00:58:40","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":65,"st":"2026-01-08 00:59:44","now":"2026-01-08 00:58:40","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 00:58:40","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":77,"play_type":"ichiban","interval":5,"scheduled_time":"2026-01-08T00:58:44.807+08:00","last_settled":"2026-01-08T00:53:44.807+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 00:58:40","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":77,"st":"2026-01-08 00:58:44","now":"2026-01-08 00:58:40","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 00:58:40","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":79,"play_type":"ichiban","interval":5,"scheduled_time":"2026-01-08T01:00:14.807+08:00","last_settled":"2026-01-08T00:55:14.807+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 00:58:40","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":79,"st":"2026-01-08 01:00:14","now":"2026-01-08 00:58:40","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 00:58:40","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":80,"play_type":"ichiban","interval":10,"scheduled_time":"2026-01-08T01:04:18.148+08:00","last_settled":"2026-01-08T00:54:18.148+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 00:58:40","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":80,"st":"2026-01-08 01:04:18","now":"2026-01-08 00:58:40","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 00:58:40","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":81,"play_type":"ichiban","interval":15,"scheduled_time":"2026-01-08T01:10:14.807+08:00","last_settled":"2026-01-08T00:55:14.807+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 00:58:40","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":81,"st":"2026-01-08 01:10:14","now":"2026-01-08 00:58:40","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 00:58:40","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":82,"play_type":"ichiban","interval":15,"scheduled_time":"2026-01-08T01:10:14.807+08:00","last_settled":"2026-01-08T00:55:14.807+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 00:58:40","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":82,"st":"2026-01-08 01:10:14","now":"2026-01-08 00:58:40","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 00:58:41","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":83,"play_type":"ichiban","interval":30,"scheduled_time":"2026-01-08T01:05:26.489+08:00","last_settled":"2026-01-08T00:35:26.489+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 00:58:41","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":83,"st":"2026-01-08 01:05:26","now":"2026-01-08 00:58:40","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 00:58:41","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":84,"play_type":"ichiban","interval":60,"scheduled_time":"2026-01-08T01:27:44.808+08:00","last_settled":"2026-01-08T00:27:44.808+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 00:58:41","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":84,"st":"2026-01-08 01:27:44","now":"2026-01-08 00:58:40","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 00:59:10","caller":"logger/logger.go:315","msg":"定时开奖: 开始检查","domain":"mini-chat[fat]","now":"2026-01-08 00:59:10"}
|
||||
{"level":"debug","time":"2026-01-08 00:59:10","caller":"logger/logger.go:315","msg":"定时开奖: 查询到活动","domain":"mini-chat[fat]","count":9}
|
||||
{"level":"debug","time":"2026-01-08 00:59:10","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":52,"play_type":"ichiban","interval":3,"scheduled_time":"2026-01-08T01:00:10.204+08:00","last_settled":"2026-01-08T00:57:10.204+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 00:59:10","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":52,"st":"2026-01-08 01:00:10","now":"2026-01-08 00:59:10","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 00:59:10","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":65,"play_type":"ichiban","interval":3,"scheduled_time":"2026-01-08T00:59:44.808+08:00","last_settled":"2026-01-08T00:56:44.808+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 00:59:10","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":65,"st":"2026-01-08 00:59:44","now":"2026-01-08 00:59:10","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 00:59:10","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":77,"play_type":"ichiban","interval":5,"scheduled_time":"2026-01-08T01:03:44.807+08:00","last_settled":"2026-01-08T00:58:44.807+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 00:59:10","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":77,"st":"2026-01-08 01:03:44","now":"2026-01-08 00:59:10","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 00:59:10","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":79,"play_type":"ichiban","interval":5,"scheduled_time":"2026-01-08T01:00:14.807+08:00","last_settled":"2026-01-08T00:55:14.807+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 00:59:10","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":79,"st":"2026-01-08 01:00:14","now":"2026-01-08 00:59:10","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 00:59:10","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":80,"play_type":"ichiban","interval":10,"scheduled_time":"2026-01-08T01:04:18.148+08:00","last_settled":"2026-01-08T00:54:18.148+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 00:59:10","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":80,"st":"2026-01-08 01:04:18","now":"2026-01-08 00:59:10","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 00:59:10","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":81,"play_type":"ichiban","interval":15,"scheduled_time":"2026-01-08T01:10:14.807+08:00","last_settled":"2026-01-08T00:55:14.807+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 00:59:10","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":81,"st":"2026-01-08 01:10:14","now":"2026-01-08 00:59:10","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 00:59:10","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":82,"play_type":"ichiban","interval":15,"scheduled_time":"2026-01-08T01:10:14.807+08:00","last_settled":"2026-01-08T00:55:14.807+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 00:59:10","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":82,"st":"2026-01-08 01:10:14","now":"2026-01-08 00:59:10","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 00:59:10","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":83,"play_type":"ichiban","interval":30,"scheduled_time":"2026-01-08T01:05:26.489+08:00","last_settled":"2026-01-08T00:35:26.489+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 00:59:11","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":83,"st":"2026-01-08 01:05:26","now":"2026-01-08 00:59:10","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 00:59:11","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":84,"play_type":"ichiban","interval":60,"scheduled_time":"2026-01-08T01:27:44.808+08:00","last_settled":"2026-01-08T00:27:44.808+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 00:59:11","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":84,"st":"2026-01-08 01:27:44","now":"2026-01-08 00:59:10","skip":true}
|
||||
{"level":"info","time":"2026-01-08 00:59:19","caller":"logger/logger.go:309","msg":"[抖店定时同步] 开始同步","domain":"mini-chat[fat]","interval_minutes":1}
|
||||
[DEBUG] 开始全量同步,共 3 个绑定用户
|
||||
[DEBUG] 正在同步用户 ID: 9018 (昵称: 现实的迪斯蒂法诺, 抖音号: wyl0423333) 的订单...
|
||||
[DEBUG] 正在同步用户 ID: 9019 (昵称: 约翰掐指一算, 抖音号: xrw200947752) 的订单...
|
||||
[DEBUG] 正在同步用户 ID: 9047 (昵称: 巴乔横扫六合, 抖音号: 请输入您的抖店订单号即可完成绑定) 的订单...
|
||||
{"level":"info","time":"2026-01-08 00:59:24","caller":"logger/logger.go:309","msg":"[抖店同步] 全量同步完成","domain":"mini-chat[fat]","users_count":3,"total_fetched":45,"new_orders":0,"matched_users":45}
|
||||
{"level":"info","time":"2026-01-08 00:59:24","caller":"logger/logger.go:309","msg":"[抖店定时同步] 同步成功","domain":"mini-chat[fat]","total_fetched":45,"new_orders":0,"matched_users":45}
|
||||
{"level":"debug","time":"2026-01-08 00:59:40","caller":"logger/logger.go:315","msg":"定时开奖: 开始检查","domain":"mini-chat[fat]","now":"2026-01-08 00:59:40"}
|
||||
{"level":"debug","time":"2026-01-08 00:59:40","caller":"logger/logger.go:315","msg":"定时开奖: 查询到活动","domain":"mini-chat[fat]","count":9}
|
||||
{"level":"debug","time":"2026-01-08 00:59:40","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":52,"play_type":"ichiban","interval":3,"scheduled_time":"2026-01-08T01:00:10.204+08:00","last_settled":"2026-01-08T00:57:10.204+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 00:59:40","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":52,"st":"2026-01-08 01:00:10","now":"2026-01-08 00:59:40","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 00:59:40","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":65,"play_type":"ichiban","interval":3,"scheduled_time":"2026-01-08T00:59:44.808+08:00","last_settled":"2026-01-08T00:56:44.808+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 00:59:40","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":65,"st":"2026-01-08 00:59:44","now":"2026-01-08 00:59:40","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 00:59:40","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":77,"play_type":"ichiban","interval":5,"scheduled_time":"2026-01-08T01:03:44.807+08:00","last_settled":"2026-01-08T00:58:44.807+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 00:59:40","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":77,"st":"2026-01-08 01:03:44","now":"2026-01-08 00:59:40","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 00:59:40","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":79,"play_type":"ichiban","interval":5,"scheduled_time":"2026-01-08T01:00:14.807+08:00","last_settled":"2026-01-08T00:55:14.807+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 00:59:40","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":79,"st":"2026-01-08 01:00:14","now":"2026-01-08 00:59:40","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 00:59:40","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":80,"play_type":"ichiban","interval":10,"scheduled_time":"2026-01-08T01:04:18.148+08:00","last_settled":"2026-01-08T00:54:18.148+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 00:59:40","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":80,"st":"2026-01-08 01:04:18","now":"2026-01-08 00:59:40","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 00:59:40","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":81,"play_type":"ichiban","interval":15,"scheduled_time":"2026-01-08T01:10:14.807+08:00","last_settled":"2026-01-08T00:55:14.807+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 00:59:40","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":81,"st":"2026-01-08 01:10:14","now":"2026-01-08 00:59:40","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 00:59:40","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":82,"play_type":"ichiban","interval":15,"scheduled_time":"2026-01-08T01:10:14.807+08:00","last_settled":"2026-01-08T00:55:14.807+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 00:59:40","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":82,"st":"2026-01-08 01:10:14","now":"2026-01-08 00:59:40","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 00:59:40","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":83,"play_type":"ichiban","interval":30,"scheduled_time":"2026-01-08T01:05:26.489+08:00","last_settled":"2026-01-08T00:35:26.489+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 00:59:40","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":83,"st":"2026-01-08 01:05:26","now":"2026-01-08 00:59:40","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 00:59:41","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":84,"play_type":"ichiban","interval":60,"scheduled_time":"2026-01-08T01:27:44.808+08:00","last_settled":"2026-01-08T00:27:44.808+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 00:59:41","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":84,"st":"2026-01-08 01:27:44","now":"2026-01-08 00:59:40","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 01:00:10","caller":"logger/logger.go:315","msg":"定时开奖: 开始检查","domain":"mini-chat[fat]","now":"2026-01-08 01:00:10"}
|
||||
{"level":"debug","time":"2026-01-08 01:00:10","caller":"logger/logger.go:315","msg":"定时开奖: 查询到活动","domain":"mini-chat[fat]","count":9}
|
||||
{"level":"debug","time":"2026-01-08 01:00:10","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":52,"play_type":"ichiban","interval":3,"scheduled_time":"2026-01-08T01:00:10.204+08:00","last_settled":"2026-01-08T00:57:10.204+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 01:00:10","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":52,"st":"2026-01-08 01:00:10","now":"2026-01-08 01:00:10","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 01:00:10","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":65,"play_type":"ichiban","interval":3,"scheduled_time":"2026-01-08T01:02:59.385+08:00","last_settled":"2026-01-08T00:59:59.385+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 01:00:10","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":65,"st":"2026-01-08 01:02:59","now":"2026-01-08 01:00:10","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 01:00:10","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":77,"play_type":"ichiban","interval":5,"scheduled_time":"2026-01-08T01:03:44.807+08:00","last_settled":"2026-01-08T00:58:44.807+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 01:00:10","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":77,"st":"2026-01-08 01:03:44","now":"2026-01-08 01:00:10","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 01:00:10","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":79,"play_type":"ichiban","interval":5,"scheduled_time":"2026-01-08T01:00:14.807+08:00","last_settled":"2026-01-08T00:55:14.807+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 01:00:10","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":79,"st":"2026-01-08 01:00:14","now":"2026-01-08 01:00:10","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 01:00:10","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":80,"play_type":"ichiban","interval":10,"scheduled_time":"2026-01-08T01:04:18.148+08:00","last_settled":"2026-01-08T00:54:18.148+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 01:00:10","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":80,"st":"2026-01-08 01:04:18","now":"2026-01-08 01:00:10","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 01:00:10","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":81,"play_type":"ichiban","interval":15,"scheduled_time":"2026-01-08T01:10:14.807+08:00","last_settled":"2026-01-08T00:55:14.807+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 01:00:10","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":81,"st":"2026-01-08 01:10:14","now":"2026-01-08 01:00:10","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 01:00:10","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":82,"play_type":"ichiban","interval":15,"scheduled_time":"2026-01-08T01:10:14.807+08:00","last_settled":"2026-01-08T00:55:14.807+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 01:00:10","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":82,"st":"2026-01-08 01:10:14","now":"2026-01-08 01:00:10","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 01:00:10","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":83,"play_type":"ichiban","interval":30,"scheduled_time":"2026-01-08T01:05:26.489+08:00","last_settled":"2026-01-08T00:35:26.489+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 01:00:11","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":83,"st":"2026-01-08 01:05:26","now":"2026-01-08 01:00:10","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 01:00:11","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":84,"play_type":"ichiban","interval":60,"scheduled_time":"2026-01-08T01:27:44.808+08:00","last_settled":"2026-01-08T00:27:44.808+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 01:00:11","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":84,"st":"2026-01-08 01:27:44","now":"2026-01-08 01:00:10","skip":true}
|
||||
{"level":"info","time":"2026-01-08 01:00:24","caller":"logger/logger.go:309","msg":"[抖店定时同步] 开始同步","domain":"mini-chat[fat]","interval_minutes":1}
|
||||
[DEBUG] 开始全量同步,共 3 个绑定用户
|
||||
[DEBUG] 正在同步用户 ID: 9018 (昵称: 现实的迪斯蒂法诺, 抖音号: wyl0423333) 的订单...
|
||||
signal: killed
|
||||
147
backend_prod.log
Normal file
147
backend_prod.log
Normal file
@ -0,0 +1,147 @@
|
||||
{"level":"info","time":"2026-01-08 01:11:58","caller":"logger/logger.go:309","msg":"Connected to Redis","domain":"mini-chat[fat]","addr":"118.25.13.43:8379"}
|
||||
|
||||
[32m ____ _ _ _ ____[0m
|
||||
[32m | __ ) (_) _ __ __| | | |__ ___ __ __ / ___| __ _ _ __ ___ ___[0m
|
||||
[32m | _ \ | | | '_ \ / _` | | '_ \ / _ \ \ \/ / | | _ / _` | | '_ ` _ \ / _ \[0m
|
||||
[32m | |_) | | | | | | | | (_| | | |_) | | (_) | > < | |_| | | (_| | | | | | | | | __/[0m
|
||||
[32m |____/ |_| |_| |_| \__,_| |_.__/ \___/ /_/\_\ \____| \__,_| |_| |_| |_| \___|[0m
|
||||
▌ 客户项目: 盲盒游戏
|
||||
▌ 项目版本: Release-2025111111
|
||||
▌ 启动时间: 2026-01-08 01:11:58
|
||||
▌ 运行环境: darwin go1.24.2
|
||||
▌ 服务端口: [:9991]
|
||||
▌ 服务配置: [fat]
|
||||
|
||||
▌ 数据库连接: ✔ 已建立
|
||||
|
||||
{"level":"info","time":"2026-01-08 01:11:58","caller":"logger/logger.go:309","msg":"Task center worker started","domain":"mini-chat[fat]"}
|
||||
{"level":"info","time":"2026-01-08 01:11:58","caller":"logger/logger.go:309","msg":"对对碰自动开奖: 后台任务已启动","domain":"mini-chat[fat]"}
|
||||
{"level":"info","time":"2026-01-08 01:11:58","caller":"logger/logger.go:309","msg":"[抖店定时同步] 定时任务已启动","domain":"mini-chat[fat]"}
|
||||
{"level":"info","time":"2026-01-08 01:11:58","caller":"logger/logger.go:309","msg":"Worker routine started","domain":"mini-chat[fat]","worker_id":4}
|
||||
{"level":"info","time":"2026-01-08 01:11:58","caller":"logger/logger.go:309","msg":"Worker routine started","domain":"mini-chat[fat]","worker_id":1}
|
||||
{"level":"info","time":"2026-01-08 01:11:58","caller":"logger/logger.go:309","msg":"Worker routine started","domain":"mini-chat[fat]","worker_id":2}
|
||||
{"level":"info","time":"2026-01-08 01:11:58","caller":"logger/logger.go:309","msg":"Worker routine started","domain":"mini-chat[fat]","worker_id":0}
|
||||
{"level":"info","time":"2026-01-08 01:11:58","caller":"logger/logger.go:309","msg":"Worker routine started","domain":"mini-chat[fat]","worker_id":3}
|
||||
{"level":"error","time":"2026-01-08 01:11:58","caller":"logger/logger.go:327","msg":"解密配置失败","domain":"mini-chat[fat]","key":"douyin.app_secret","error":"ciphertext is not a multiple of the block size"}
|
||||
{"level":"info","time":"2026-01-08 01:11:58","caller":"logger/logger.go:309","msg":"动态配置加载完成","domain":"mini-chat[fat]","count":26}
|
||||
{"level":"debug","time":"2026-01-08 01:12:28","caller":"logger/logger.go:315","msg":"定时开奖: 开始检查","domain":"mini-chat[fat]","now":"2026-01-08 01:12:28"}
|
||||
{"level":"info","time":"2026-01-08 01:12:28","caller":"logger/logger.go:309","msg":"[抖店定时同步] 开始同步","domain":"mini-chat[fat]","interval_minutes":1}
|
||||
{"level":"debug","time":"2026-01-08 01:12:28","caller":"logger/logger.go:315","msg":"定时开奖: 查询到活动","domain":"mini-chat[fat]","count":9}
|
||||
{"level":"debug","time":"2026-01-08 01:12:28","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":52,"play_type":"ichiban","interval":3,"scheduled_time":"2026-01-08T01:12:29.386+08:00","last_settled":"2026-01-08T01:09:29.386+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 01:12:28","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":52,"st":"2026-01-08 01:12:29","now":"2026-01-08 01:12:28","skip":true}
|
||||
[DEBUG] 开始全量同步,共 3 个绑定用户
|
||||
[DEBUG] 正在同步用户 ID: 9018 (昵称: 现实的迪斯蒂法诺, 抖音号: wyl0423333) 的订单...
|
||||
{"level":"debug","time":"2026-01-08 01:12:28","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":65,"play_type":"ichiban","interval":3,"scheduled_time":"2026-01-08T01:15:14.808+08:00","last_settled":"2026-01-08T01:12:14.808+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 01:12:28","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":65,"st":"2026-01-08 01:15:14","now":"2026-01-08 01:12:28","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 01:12:28","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":77,"play_type":"ichiban","interval":5,"scheduled_time":"2026-01-08T01:13:44.807+08:00","last_settled":"2026-01-08T01:08:44.807+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 01:12:28","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":77,"st":"2026-01-08 01:13:44","now":"2026-01-08 01:12:28","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 01:12:28","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":79,"play_type":"ichiban","interval":5,"scheduled_time":"2026-01-08T01:15:29.386+08:00","last_settled":"2026-01-08T01:10:29.386+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 01:12:28","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":79,"st":"2026-01-08 01:15:29","now":"2026-01-08 01:12:28","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 01:12:28","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":80,"play_type":"ichiban","interval":10,"scheduled_time":"2026-01-08T01:14:29.385+08:00","last_settled":"2026-01-08T01:04:29.385+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 01:12:28","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":80,"st":"2026-01-08 01:14:29","now":"2026-01-08 01:12:28","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 01:12:29","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":81,"play_type":"ichiban","interval":15,"scheduled_time":"2026-01-08T01:25:29.386+08:00","last_settled":"2026-01-08T01:10:29.386+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 01:12:29","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":81,"st":"2026-01-08 01:25:29","now":"2026-01-08 01:12:28","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 01:12:29","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":82,"play_type":"ichiban","interval":15,"scheduled_time":"2026-01-08T01:25:29.386+08:00","last_settled":"2026-01-08T01:10:29.386+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 01:12:29","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":82,"st":"2026-01-08 01:25:29","now":"2026-01-08 01:12:28","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 01:12:29","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":83,"play_type":"ichiban","interval":30,"scheduled_time":"2026-01-08T01:35:29.385+08:00","last_settled":"2026-01-08T01:05:29.385+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 01:12:29","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":83,"st":"2026-01-08 01:35:29","now":"2026-01-08 01:12:28","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 01:12:29","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":84,"play_type":"ichiban","interval":60,"scheduled_time":"2026-01-08T01:27:44.808+08:00","last_settled":"2026-01-08T00:27:44.808+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 01:12:29","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":84,"st":"2026-01-08 01:27:44","now":"2026-01-08 01:12:28","skip":true}
|
||||
[DEBUG] 正在同步用户 ID: 9019 (昵称: 约翰掐指一算, 抖音号: xrw200947752) 的订单...
|
||||
[DEBUG] 正在同步用户 ID: 9047 (昵称: 巴乔横扫六合, 抖音号: 请输入您的抖店订单号即可完成绑定) 的订单...
|
||||
{"level":"info","time":"2026-01-08 01:12:32","caller":"logger/logger.go:309","msg":"[抖店同步] 全量同步完成","domain":"mini-chat[fat]","users_count":3,"total_fetched":45,"new_orders":0,"matched_users":45}
|
||||
{"level":"info","time":"2026-01-08 01:12:32","caller":"logger/logger.go:309","msg":"[抖店定时同步] 同步成功","domain":"mini-chat[fat]","total_fetched":45,"new_orders":0,"matched_users":45}
|
||||
{"level":"debug","time":"2026-01-08 01:12:58","caller":"logger/logger.go:315","msg":"定时开奖: 开始检查","domain":"mini-chat[fat]","now":"2026-01-08 01:12:58"}
|
||||
{"level":"debug","time":"2026-01-08 01:12:58","caller":"logger/logger.go:315","msg":"定时开奖: 查询到活动","domain":"mini-chat[fat]","count":9}
|
||||
{"level":"debug","time":"2026-01-08 01:12:58","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":52,"play_type":"ichiban","interval":3,"scheduled_time":"2026-01-08T01:15:44.807+08:00","last_settled":"2026-01-08T01:12:44.807+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 01:12:58","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":52,"st":"2026-01-08 01:15:44","now":"2026-01-08 01:12:58","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 01:12:58","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":65,"play_type":"ichiban","interval":3,"scheduled_time":"2026-01-08T01:15:14.808+08:00","last_settled":"2026-01-08T01:12:14.808+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 01:12:58","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":65,"st":"2026-01-08 01:15:14","now":"2026-01-08 01:12:58","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 01:12:58","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":77,"play_type":"ichiban","interval":5,"scheduled_time":"2026-01-08T01:13:44.807+08:00","last_settled":"2026-01-08T01:08:44.807+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 01:12:58","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":77,"st":"2026-01-08 01:13:44","now":"2026-01-08 01:12:58","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 01:12:58","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":79,"play_type":"ichiban","interval":5,"scheduled_time":"2026-01-08T01:15:29.386+08:00","last_settled":"2026-01-08T01:10:29.386+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 01:12:58","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":79,"st":"2026-01-08 01:15:29","now":"2026-01-08 01:12:58","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 01:12:58","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":80,"play_type":"ichiban","interval":10,"scheduled_time":"2026-01-08T01:14:29.385+08:00","last_settled":"2026-01-08T01:04:29.385+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 01:12:58","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":80,"st":"2026-01-08 01:14:29","now":"2026-01-08 01:12:58","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 01:12:59","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":81,"play_type":"ichiban","interval":15,"scheduled_time":"2026-01-08T01:25:29.386+08:00","last_settled":"2026-01-08T01:10:29.386+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 01:12:59","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":81,"st":"2026-01-08 01:25:29","now":"2026-01-08 01:12:58","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 01:12:59","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":82,"play_type":"ichiban","interval":15,"scheduled_time":"2026-01-08T01:25:29.386+08:00","last_settled":"2026-01-08T01:10:29.386+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 01:12:59","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":82,"st":"2026-01-08 01:25:29","now":"2026-01-08 01:12:58","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 01:12:59","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":83,"play_type":"ichiban","interval":30,"scheduled_time":"2026-01-08T01:35:29.385+08:00","last_settled":"2026-01-08T01:05:29.385+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 01:12:59","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":83,"st":"2026-01-08 01:35:29","now":"2026-01-08 01:12:58","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 01:12:59","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":84,"play_type":"ichiban","interval":60,"scheduled_time":"2026-01-08T01:27:44.808+08:00","last_settled":"2026-01-08T00:27:44.808+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 01:12:59","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":84,"st":"2026-01-08 01:27:44","now":"2026-01-08 01:12:58","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 01:13:28","caller":"logger/logger.go:315","msg":"定时开奖: 开始检查","domain":"mini-chat[fat]","now":"2026-01-08 01:13:28"}
|
||||
{"level":"debug","time":"2026-01-08 01:13:28","caller":"logger/logger.go:315","msg":"定时开奖: 查询到活动","domain":"mini-chat[fat]","count":9}
|
||||
{"level":"debug","time":"2026-01-08 01:13:28","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":52,"play_type":"ichiban","interval":3,"scheduled_time":"2026-01-08T01:15:44.807+08:00","last_settled":"2026-01-08T01:12:44.807+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 01:13:28","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":52,"st":"2026-01-08 01:15:44","now":"2026-01-08 01:13:28","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 01:13:28","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":65,"play_type":"ichiban","interval":3,"scheduled_time":"2026-01-08T01:15:14.808+08:00","last_settled":"2026-01-08T01:12:14.808+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 01:13:28","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":65,"st":"2026-01-08 01:15:14","now":"2026-01-08 01:13:28","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 01:13:28","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":77,"play_type":"ichiban","interval":5,"scheduled_time":"2026-01-08T01:13:44.807+08:00","last_settled":"2026-01-08T01:08:44.807+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 01:13:28","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":77,"st":"2026-01-08 01:13:44","now":"2026-01-08 01:13:28","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 01:13:28","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":79,"play_type":"ichiban","interval":5,"scheduled_time":"2026-01-08T01:15:29.386+08:00","last_settled":"2026-01-08T01:10:29.386+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 01:13:28","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":79,"st":"2026-01-08 01:15:29","now":"2026-01-08 01:13:28","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 01:13:28","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":80,"play_type":"ichiban","interval":10,"scheduled_time":"2026-01-08T01:14:29.385+08:00","last_settled":"2026-01-08T01:04:29.385+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 01:13:28","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":80,"st":"2026-01-08 01:14:29","now":"2026-01-08 01:13:28","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 01:13:29","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":81,"play_type":"ichiban","interval":15,"scheduled_time":"2026-01-08T01:25:29.386+08:00","last_settled":"2026-01-08T01:10:29.386+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 01:13:29","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":81,"st":"2026-01-08 01:25:29","now":"2026-01-08 01:13:28","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 01:13:29","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":82,"play_type":"ichiban","interval":15,"scheduled_time":"2026-01-08T01:25:29.386+08:00","last_settled":"2026-01-08T01:10:29.386+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 01:13:29","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":82,"st":"2026-01-08 01:25:29","now":"2026-01-08 01:13:28","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 01:13:29","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":83,"play_type":"ichiban","interval":30,"scheduled_time":"2026-01-08T01:35:29.385+08:00","last_settled":"2026-01-08T01:05:29.385+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 01:13:29","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":83,"st":"2026-01-08 01:35:29","now":"2026-01-08 01:13:28","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 01:13:29","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":84,"play_type":"ichiban","interval":60,"scheduled_time":"2026-01-08T01:27:44.808+08:00","last_settled":"2026-01-08T00:27:44.808+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 01:13:29","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":84,"st":"2026-01-08 01:27:44","now":"2026-01-08 01:13:28","skip":true}
|
||||
{"level":"info","time":"2026-01-08 01:13:32","caller":"logger/logger.go:309","msg":"[抖店定时同步] 开始同步","domain":"mini-chat[fat]","interval_minutes":1}
|
||||
[DEBUG] 开始全量同步,共 3 个绑定用户
|
||||
[DEBUG] 正在同步用户 ID: 9018 (昵称: 现实的迪斯蒂法诺, 抖音号: wyl0423333) 的订单...
|
||||
[DEBUG] 正在同步用户 ID: 9019 (昵称: 约翰掐指一算, 抖音号: xrw200947752) 的订单...
|
||||
[DEBUG] 正在同步用户 ID: 9047 (昵称: 巴乔横扫六合, 抖音号: 请输入您的抖店订单号即可完成绑定) 的订单...
|
||||
{"level":"info","time":"2026-01-08 01:13:37","caller":"logger/logger.go:309","msg":"[抖店同步] 全量同步完成","domain":"mini-chat[fat]","users_count":3,"total_fetched":45,"new_orders":0,"matched_users":45}
|
||||
{"level":"info","time":"2026-01-08 01:13:37","caller":"logger/logger.go:309","msg":"[抖店定时同步] 同步成功","domain":"mini-chat[fat]","total_fetched":45,"new_orders":0,"matched_users":45}
|
||||
{"level":"debug","time":"2026-01-08 01:13:58","caller":"logger/logger.go:315","msg":"定时开奖: 开始检查","domain":"mini-chat[fat]","now":"2026-01-08 01:13:58"}
|
||||
{"level":"debug","time":"2026-01-08 01:13:58","caller":"logger/logger.go:315","msg":"定时开奖: 查询到活动","domain":"mini-chat[fat]","count":9}
|
||||
{"level":"debug","time":"2026-01-08 01:13:58","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":52,"play_type":"ichiban","interval":3,"scheduled_time":"2026-01-08T01:15:44.807+08:00","last_settled":"2026-01-08T01:12:44.807+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 01:13:58","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":52,"st":"2026-01-08 01:15:44","now":"2026-01-08 01:13:58","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 01:13:58","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":65,"play_type":"ichiban","interval":3,"scheduled_time":"2026-01-08T01:15:14.808+08:00","last_settled":"2026-01-08T01:12:14.808+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 01:13:58","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":65,"st":"2026-01-08 01:15:14","now":"2026-01-08 01:13:58","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 01:13:58","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":77,"play_type":"ichiban","interval":5,"scheduled_time":"2026-01-08T01:18:44.808+08:00","last_settled":"2026-01-08T01:13:44.808+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 01:13:58","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":77,"st":"2026-01-08 01:18:44","now":"2026-01-08 01:13:58","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 01:13:58","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":79,"play_type":"ichiban","interval":5,"scheduled_time":"2026-01-08T01:15:29.386+08:00","last_settled":"2026-01-08T01:10:29.386+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 01:13:58","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":79,"st":"2026-01-08 01:15:29","now":"2026-01-08 01:13:58","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 01:13:58","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":80,"play_type":"ichiban","interval":10,"scheduled_time":"2026-01-08T01:14:29.385+08:00","last_settled":"2026-01-08T01:04:29.385+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 01:13:59","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":80,"st":"2026-01-08 01:14:29","now":"2026-01-08 01:13:58","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 01:13:59","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":81,"play_type":"ichiban","interval":15,"scheduled_time":"2026-01-08T01:25:29.386+08:00","last_settled":"2026-01-08T01:10:29.386+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 01:13:59","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":81,"st":"2026-01-08 01:25:29","now":"2026-01-08 01:13:58","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 01:13:59","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":82,"play_type":"ichiban","interval":15,"scheduled_time":"2026-01-08T01:25:29.386+08:00","last_settled":"2026-01-08T01:10:29.386+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 01:13:59","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":82,"st":"2026-01-08 01:25:29","now":"2026-01-08 01:13:58","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 01:13:59","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":83,"play_type":"ichiban","interval":30,"scheduled_time":"2026-01-08T01:35:29.385+08:00","last_settled":"2026-01-08T01:05:29.385+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 01:13:59","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":83,"st":"2026-01-08 01:35:29","now":"2026-01-08 01:13:58","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 01:13:59","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":84,"play_type":"ichiban","interval":60,"scheduled_time":"2026-01-08T01:27:44.808+08:00","last_settled":"2026-01-08T00:27:44.808+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 01:13:59","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":84,"st":"2026-01-08 01:27:44","now":"2026-01-08 01:13:58","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 01:14:28","caller":"logger/logger.go:315","msg":"定时开奖: 开始检查","domain":"mini-chat[fat]","now":"2026-01-08 01:14:28"}
|
||||
{"level":"debug","time":"2026-01-08 01:14:28","caller":"logger/logger.go:315","msg":"定时开奖: 查询到活动","domain":"mini-chat[fat]","count":9}
|
||||
{"level":"debug","time":"2026-01-08 01:14:28","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":52,"play_type":"ichiban","interval":3,"scheduled_time":"2026-01-08T01:15:44.807+08:00","last_settled":"2026-01-08T01:12:44.807+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 01:14:28","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":52,"st":"2026-01-08 01:15:44","now":"2026-01-08 01:14:28","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 01:14:28","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":65,"play_type":"ichiban","interval":3,"scheduled_time":"2026-01-08T01:15:14.808+08:00","last_settled":"2026-01-08T01:12:14.808+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 01:14:28","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":65,"st":"2026-01-08 01:15:14","now":"2026-01-08 01:14:28","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 01:14:28","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":77,"play_type":"ichiban","interval":5,"scheduled_time":"2026-01-08T01:18:44.808+08:00","last_settled":"2026-01-08T01:13:44.808+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 01:14:28","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":77,"st":"2026-01-08 01:18:44","now":"2026-01-08 01:14:28","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 01:14:28","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":79,"play_type":"ichiban","interval":5,"scheduled_time":"2026-01-08T01:15:29.386+08:00","last_settled":"2026-01-08T01:10:29.386+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 01:14:28","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":79,"st":"2026-01-08 01:15:29","now":"2026-01-08 01:14:28","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 01:14:28","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":80,"play_type":"ichiban","interval":10,"scheduled_time":"2026-01-08T01:14:29.385+08:00","last_settled":"2026-01-08T01:04:29.385+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 01:14:28","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":80,"st":"2026-01-08 01:14:29","now":"2026-01-08 01:14:28","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 01:14:29","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":81,"play_type":"ichiban","interval":15,"scheduled_time":"2026-01-08T01:25:29.386+08:00","last_settled":"2026-01-08T01:10:29.386+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 01:14:29","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":81,"st":"2026-01-08 01:25:29","now":"2026-01-08 01:14:28","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 01:14:29","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":82,"play_type":"ichiban","interval":15,"scheduled_time":"2026-01-08T01:25:29.386+08:00","last_settled":"2026-01-08T01:10:29.386+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 01:14:29","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":82,"st":"2026-01-08 01:25:29","now":"2026-01-08 01:14:28","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 01:14:29","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":83,"play_type":"ichiban","interval":30,"scheduled_time":"2026-01-08T01:35:29.385+08:00","last_settled":"2026-01-08T01:05:29.385+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 01:14:29","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":83,"st":"2026-01-08 01:35:29","now":"2026-01-08 01:14:28","skip":true}
|
||||
{"level":"debug","time":"2026-01-08 01:14:29","caller":"logger/logger.go:315","msg":"定时开奖: 检查活动","domain":"mini-chat[fat]","id":84,"play_type":"ichiban","interval":60,"scheduled_time":"2026-01-08T01:27:44.808+08:00","last_settled":"2026-01-08T00:27:44.808+08:00"}
|
||||
{"level":"debug","time":"2026-01-08 01:14:29","caller":"logger/logger.go:315","msg":"定时开奖: 计算开奖时间","domain":"mini-chat[fat]","id":84,"st":"2026-01-08 01:27:44","now":"2026-01-08 01:14:28","skip":true}
|
||||
{"level":"info","time":"2026-01-08 01:14:37","caller":"logger/logger.go:309","msg":"[抖店定时同步] 开始同步","domain":"mini-chat[fat]","interval_minutes":1}
|
||||
[DEBUG] 开始全量同步,共 3 个绑定用户
|
||||
[DEBUG] 正在同步用户 ID: 9018 (昵称: 现实的迪斯蒂法诺, 抖音号: wyl0423333) 的订单...
|
||||
[DEBUG] 正在同步用户 ID: 9019 (昵称: 约翰掐指一算, 抖音号: xrw200947752) 的订单...
|
||||
[DEBUG] 正在同步用户 ID: 9047 (昵称: 巴乔横扫六合, 抖音号: 请输入您的抖店订单号即可完成绑定) 的订单...
|
||||
{"level":"info","time":"2026-01-08 01:14:42","caller":"logger/logger.go:309","msg":"[抖店同步] 全量同步完成","domain":"mini-chat[fat]","users_count":3,"total_fetched":45,"new_orders":0,"matched_users":45}
|
||||
{"level":"info","time":"2026-01-08 01:14:42","caller":"logger/logger.go:309","msg":"[抖店定时同步] 同步成功","domain":"mini-chat[fat]","total_fetched":45,"new_orders":0,"matched_users":45}
|
||||
1
check_config.sql
Normal file
1
check_config.sql
Normal file
@ -0,0 +1 @@
|
||||
SELECT config_key, config_value FROM sys_configs WHERE config_key = 'wechat_miniprogram_lottery_result_template_id';
|
||||
74
cmd/diagnose_order/main.go
Normal file
74
cmd/diagnose_order/main.go
Normal file
@ -0,0 +1,74 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"gorm.io/driver/mysql"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
// 简单的 struct 映射
|
||||
type Orders struct {
|
||||
ID int64
|
||||
OrderNo string
|
||||
SourceType int32
|
||||
Status int32
|
||||
Remark string
|
||||
UserID int64
|
||||
TotalAmount int64
|
||||
ActualAmount int64
|
||||
CreatedAt time.Time
|
||||
}
|
||||
|
||||
type IssuePositionClaims struct {
|
||||
ID int64
|
||||
IssueID int64
|
||||
SlotIndex int64
|
||||
OrderID int64
|
||||
UserID int64
|
||||
}
|
||||
|
||||
// 表名映射
|
||||
func (Orders) TableName() string { return "orders" }
|
||||
func (IssuePositionClaims) TableName() string { return "issue_position_claims" }
|
||||
|
||||
func main() {
|
||||
// 尝试使用 config 中的密码
|
||||
dsn := "root:api2api..@tcp(sh-cynosdbmysql-grp-88th45wy.sql.tencentcdb.com:28555)/bindbox_game?charset=utf8mb4&parseTime=True&loc=Local"
|
||||
db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{})
|
||||
if err != nil {
|
||||
panic("failed to connect database: " + err.Error())
|
||||
}
|
||||
|
||||
targetOrderNo := "O20260107092217073"
|
||||
|
||||
var order Orders
|
||||
if err := db.Where("order_no = ?", targetOrderNo).First(&order).Error; err != nil {
|
||||
fmt.Printf("Error finding order: %v\n", err)
|
||||
return
|
||||
}
|
||||
|
||||
fmt.Printf("========== Order Info ==========\n")
|
||||
fmt.Printf("ID: %d\n", order.ID)
|
||||
fmt.Printf("OrderNo: %s\n", order.OrderNo)
|
||||
fmt.Printf("UserID: %d\n", order.UserID)
|
||||
fmt.Printf("SourceType: %d\n", order.SourceType)
|
||||
fmt.Printf("Status: %d (2=Paid)\n", order.Status)
|
||||
fmt.Printf("Amount: Total=%d, Actual=%d\n", order.TotalAmount, order.ActualAmount)
|
||||
fmt.Printf("Remark Length: %d\n", len(order.Remark))
|
||||
fmt.Printf("Remark Content: %s\n", order.Remark)
|
||||
fmt.Printf("================================\n")
|
||||
|
||||
var claims []IssuePositionClaims
|
||||
if err := db.Where("order_id = ?", order.ID).Find(&claims).Error; err != nil {
|
||||
fmt.Printf("Error checking claims: %v\n", err)
|
||||
}
|
||||
|
||||
fmt.Printf("========== Claims Info ==========\n")
|
||||
fmt.Printf("Claims Count: %d\n", len(claims))
|
||||
for _, c := range claims {
|
||||
fmt.Printf("- Claim: SlotIndex=%d IssueID=%d\n", c.SlotIndex, c.IssueID)
|
||||
}
|
||||
fmt.Printf("=================================\n")
|
||||
}
|
||||
@ -89,6 +89,11 @@ type Config struct {
|
||||
AppSecret string `mapstructure:"app_secret" toml:"app_secret"`
|
||||
NotifyURL string `mapstructure:"notify_url" toml:"notify_url"`
|
||||
} `mapstructure:"douyin" toml:"douyin"`
|
||||
|
||||
Otel struct {
|
||||
Enabled bool `mapstructure:"enabled" toml:"enabled"`
|
||||
Endpoint string `mapstructure:"endpoint" toml:"endpoint"`
|
||||
} `mapstructure:"otel" toml:"otel"`
|
||||
}
|
||||
|
||||
var (
|
||||
@ -166,6 +171,38 @@ func init() {
|
||||
if v := os.Getenv("ALIYUN_SMS_TEMPLATE_CODE"); v != "" {
|
||||
config.AliyunSMS.TemplateCode = v
|
||||
}
|
||||
|
||||
// MySQL 配置环境变量覆盖
|
||||
if v := os.Getenv("MYSQL_ADDR"); v != "" {
|
||||
config.MySQL.Read.Addr = v
|
||||
config.MySQL.Write.Addr = v
|
||||
}
|
||||
if v := os.Getenv("MYSQL_READ_ADDR"); v != "" {
|
||||
config.MySQL.Read.Addr = v
|
||||
}
|
||||
if v := os.Getenv("MYSQL_WRITE_ADDR"); v != "" {
|
||||
config.MySQL.Write.Addr = v
|
||||
}
|
||||
if v := os.Getenv("MYSQL_USER"); v != "" {
|
||||
config.MySQL.Read.User = v
|
||||
config.MySQL.Write.User = v
|
||||
}
|
||||
if v := os.Getenv("MYSQL_PASS"); v != "" {
|
||||
config.MySQL.Read.Pass = v
|
||||
config.MySQL.Write.Pass = v
|
||||
}
|
||||
if v := os.Getenv("MYSQL_NAME"); v != "" {
|
||||
config.MySQL.Read.Name = v
|
||||
config.MySQL.Write.Name = v
|
||||
}
|
||||
|
||||
// Redis 配置环境变量覆盖
|
||||
if v := os.Getenv("REDIS_ADDR"); v != "" {
|
||||
config.Redis.Addr = v
|
||||
}
|
||||
if v := os.Getenv("REDIS_PASS"); v != "" {
|
||||
config.Redis.Pass = v
|
||||
}
|
||||
}
|
||||
|
||||
func Get() Config {
|
||||
|
||||
@ -1,42 +1,60 @@
|
||||
[mysql]
|
||||
[mysql.read]
|
||||
addr = "127.0.0.1:3306"
|
||||
user = "root"
|
||||
pass = "123456"
|
||||
name = "bindbox_game"
|
||||
[mysql.write]
|
||||
addr = "127.0.0.1:3306"
|
||||
user = "root"
|
||||
pass = "123456"
|
||||
name = "bindbox_game"
|
||||
[language]
|
||||
local = 'zh-cn'
|
||||
|
||||
[mysql.read]
|
||||
addr = "mysql:3306"
|
||||
user = "root"
|
||||
pass = "bindbox2025kdy"
|
||||
name = "bindbox_game"
|
||||
|
||||
[mysql.write]
|
||||
addr = "mysql:3306"
|
||||
user = "root"
|
||||
pass = "bindbox2025kdy"
|
||||
name = "bindbox_game"
|
||||
|
||||
[redis]
|
||||
addr = "127.0.0.1:6379"
|
||||
pass = ""
|
||||
db = 0
|
||||
addr = "redis:6379"
|
||||
pass = ""
|
||||
db = 0
|
||||
|
||||
[jwt]
|
||||
admin_secret = "m9ycX9RTPyuYTWw9FrCc"
|
||||
patient_secret = "AppUserJwtSecret2025"
|
||||
|
||||
[random]
|
||||
|
||||
commit_master_key = "a1b2c3d4e5f6789012345678901234567890abcdef1234567890abcdef123456"
|
||||
|
||||
[wechat]
|
||||
app_id = ""
|
||||
app_secret = ""
|
||||
lottery_result_template_id = ""
|
||||
app_id = "wx26ad074017e1e63f"
|
||||
app_secret = "026c19ce4f3bb090c56573024c59a8be"
|
||||
lottery_result_template_id = "O2eqJQD3pn-vQ6g2z9DWzINVwOmPoz8yW-172J_YcpI"
|
||||
|
||||
[cos]
|
||||
bucket = "keaiya-1259195914"
|
||||
region = "ap-shanghai"
|
||||
secret_id = "AKIDtjPtAFPNDuR1UnxvoUCoRAnJgw164Zv6"
|
||||
secret_key = "B0vvjMoMsKcipnJlLnFyWt6A2JRSJ0Wr"
|
||||
base_url = ""
|
||||
|
||||
[random]
|
||||
commit_master_key = "4d7a3b8f9c2e1a5d6b4f8c0e3a7d2b1c6f9e4a5d8c1b3f7a2e5d6c4b8f0e3a7d2b1c"
|
||||
|
||||
[wechatpay]
|
||||
mchid = ""
|
||||
serial_no = ""
|
||||
private_key_path = ""
|
||||
api_v3_key = ""
|
||||
notify_url = "https://example.com/api/pay/wechat/notify"
|
||||
mchid = "1610439635"
|
||||
serial_no = "3AFD505D597831F8E931EBFFEEB5976B81F66F03"
|
||||
private_key_path = "./configs/cert/apiclient_key.pem"
|
||||
api_v3_key = "3tbwEFZV3fZtOslpUJC7Sacb8qjzhm05"
|
||||
notify_url = "https://kdy.1024tool.vip/api/pay/wechat/notify"
|
||||
public_key_id = "PUB_KEY_ID_0116104396352025041000211519001600"
|
||||
public_key_path = "./configs/cert/pub_key.pem"
|
||||
|
||||
[aliyun_sms]
|
||||
access_key_id = ""
|
||||
access_key_secret = ""
|
||||
sign_name = ""
|
||||
template_code = ""
|
||||
template_code = ""
|
||||
|
||||
[internal]
|
||||
api_key = "bindbox-internal-secret-2024"
|
||||
|
||||
[otel]
|
||||
enabled = true
|
||||
endpoint = "tempo:4318"
|
||||
47
docs/loki_integration/ALIGNMENT_loki_integration.md
Normal file
47
docs/loki_integration/ALIGNMENT_loki_integration.md
Normal file
@ -0,0 +1,47 @@
|
||||
# 任务:后台Go项目接入 Loki 成本评估与实施方案 (ALIGNMENT) - 性能分析版
|
||||
|
||||
## 1. 核心问题:性能消耗分析
|
||||
用户疑问:**"Loki + Promtail + Grafana 这个组合消耗性能么"**
|
||||
|
||||
### 1.1 结论先行
|
||||
在**极简模式**(只采服务端日志)下,**消耗非常低**。
|
||||
对于现代开发机(或 2核4G 以上服务器),**几乎无感**。
|
||||
|
||||
### 1.2 详细资源开销预估 (以每天产生 100MB 日志为例)
|
||||
|
||||
| 组件 | 作用 | 内存 (RAM) | CPU (平时) | CPU (查询时) | 磁盘 IO | 评价 |
|
||||
| :--- | :--- | :--- | :--- | :--- | :--- | :--- |
|
||||
| **Promtail** | 搬运工 | ~50MB | < 1% | - | 极低 (仅读取) | **极轻**,就像运行了一个 `tail -f` 命令 |
|
||||
| **Loki** | 存储 | ~150MB - 300MB | < 2% | 10% - 30% | 低 (顺序写入) | **轻量**,不像 ES 那样建全文索引,只压缩存储,不做繁重计算 |
|
||||
| **Grafana** | 界面 | ~100MB - 200MB | 0% (Idle) | 5% - 10% | 忽略不计 | **静默**,没人访问网页时几乎不干活 |
|
||||
| **总计** | **全套** | **约 400MB - 600MB** | **日常忽略不计** | **查询时微升** | **可控** | **安全** |
|
||||
|
||||
### 1.3 为什么这么省?
|
||||
1. **不建全文索引**: Loki 的设计哲学是 "Log everything, index only labels"。它不像 Elasticsearch (ELK) 那样对每个词都建索引(那样极耗内存和CPU)。Loki 只索引 "时间" 和 "标签" (如 `app=bindbox-game`)。
|
||||
2. **流式压缩**: 日志被压缩成块存储,占用很少写 IO。
|
||||
3. **按需计算**: 只有当你发起查询(比如搜 "error")时,CPU 才会工作去解压和匹配数据。平时它只是在静静地写文件。
|
||||
|
||||
### 1.4 极端情况
|
||||
- **甚至可以更省**: 我们可以限制 docker 容器的内存上限。
|
||||
- **对比 ELK**: ELK 动辄需要 2G-4G 起步内存,Loki 是专为云原生和低资源环境设计的轻量级替代品。
|
||||
|
||||
---
|
||||
|
||||
## 2. 极简实施方案 (Server Logs Only)
|
||||
### 2.1 架构调整
|
||||
- **Log Source**: 仅采集 `bindbox-game` 容器。
|
||||
- **采集过滤**: 在 Promtail 配置中设置 Filter,**丢弃** 所有非 `bindbox-game` 的日志。
|
||||
|
||||
### 2.2 资源进一步优化
|
||||
- 由于只采集核心服务,Loki 和 Promtail 的 CPU/内存消耗将降至最低。
|
||||
- 磁盘占用将非常小。
|
||||
|
||||
---
|
||||
|
||||
## 3. 实施步骤
|
||||
1. **配置 Promtail**: 编写 `promtail-config.yaml`,只监听 `container_name="bindbox-game"`。
|
||||
2. **配置 Docker Compose**: 添加 Loki, Promtail, Grafana 服务。
|
||||
3. **配置 Grafana**: 预配置好 Loki 数据源,开箱即用。
|
||||
|
||||
## 4. 结论
|
||||
可以放心接入。这套组合主要消耗的是**几百兆内存**,对 CPU 和磁盘的影响极小,完全适合本地开发和中小型服务器部署。
|
||||
@ -0,0 +1,67 @@
|
||||
# 架构设计:统一积分与元比例 (Design)
|
||||
|
||||
## 1. 总体架构
|
||||
本次改造主要涉及 **计算逻辑层的标准化** 和 **配置数据的动态化**,不涉及大规模架构重构。
|
||||
核心思路:**后端收敛计算逻辑,前端收敛展示逻辑**。
|
||||
|
||||
```mermaid
|
||||
graph TD
|
||||
A[Admin User] -->|配置 ExchangeRate| B(Admin Panel)
|
||||
B -->|API: upsertSystemConfig| C(Backend API)
|
||||
C -->|Update| D[(MySQL: sys_configs)]
|
||||
|
||||
E[App User] -->|Action: Pay/Refund| F(Backend Service)
|
||||
F -->|Read Config| D
|
||||
F -->|Call| G{pkg/points/convert}
|
||||
G -->|Calculate based on Rate| F
|
||||
F -->|Save Integer Points| D
|
||||
|
||||
H[Mini App] -->|Read Points| F
|
||||
H -->|Display Raw Integer| I[UI Display]
|
||||
```
|
||||
|
||||
## 2. 模块设计
|
||||
|
||||
### 2.1 后端 (`bindbox_game`)
|
||||
- **`internal/pkg/points`**: 核心计算包。
|
||||
- 职责:提供基于汇率的 `Cents <-> Points` 转换函数。
|
||||
- 变更:
|
||||
- `CentsToPoints(cents, rate)`: 逻辑改为 `cents * rate / 100`。
|
||||
- `PointsToCents(points, rate)`: 逻辑改为 `points * 100 / rate`。
|
||||
- **`internal/service/user`**: 业务服务层。
|
||||
- 职责:在积分变动(增加、扣减、退款)时,从 `sys_configs` 读取最新 `points_exchange_rate` 并传入计算包。
|
||||
- 变更:检查所有调用点,确保不再硬编码。
|
||||
|
||||
### 2.2 数据库 (`MySQL`)
|
||||
- **Schema**: 无变更。
|
||||
- **Data Migration**:
|
||||
- 需执行数据清洗,将现有的积分数值 `x` 更新为 `x / 100` (假设之前是按分存的)。
|
||||
- **Risk**: 需要用户确认是否执行此 SQL。**默认提供 SQL 但不自动运行**。
|
||||
|
||||
### 2.3 管理后台 (`web/admin`)
|
||||
- **SystemConfigs**:
|
||||
- 新增 "积分配置" Section。
|
||||
- Key: `points_exchange_rate`。
|
||||
- 验证:必须为正整数,默认为 1。
|
||||
|
||||
### 2.4 小程序 (`bindbox-mini`)
|
||||
- **Utils**:
|
||||
- `formatPoints`: 移除除以 100 的逻辑,仅保留千分位格式化。
|
||||
- **Pages**:
|
||||
- 检查积分明细、下单抵扣、商品兑换等页面的展示。
|
||||
- **Vue Filters/Formatters**: 全局搜索使用 `/ 100` 展示积分的地方进行替换。
|
||||
|
||||
## 3. 接口规范
|
||||
- **API**: `POST /admin/system/configs` (现有)
|
||||
- Payload: `{ "key": "points_exchange_rate", "value": "1" }`
|
||||
|
||||
## 4. 迁移策略
|
||||
1. **停机维护** (建议): 防止数据在迁移过程中变动。
|
||||
2. **代码部署**: 部署新版后端(新算法)。
|
||||
3. **数据清洗**:
|
||||
```sql
|
||||
-- 假设所有用户的积分都需要缩小 100 倍以适配新算法
|
||||
UPDATE user_points SET points = FLOOR(points / 100);
|
||||
UPDATE user_points_ledger SET points = FLOOR(points / 100);
|
||||
```
|
||||
4. **验证**: 检查某测试账号积分是否符合预期。
|
||||
@ -0,0 +1,45 @@
|
||||
# 任务任务:统一积分与元比例 (Task List)
|
||||
|
||||
## 0. 预备工作
|
||||
- [ ] **确认数据备份**: 提醒用户备份数据库。
|
||||
- [ ] **代码同步**: 确保本地代码是最新的。
|
||||
|
||||
## 1. 后端改造 (Backend)
|
||||
- [ ] **修改核心计算包 (`internal/pkg/points/convert.go`)**
|
||||
- [ ] 修改 `CentsToPoints` 为 `(cents * rate) / 100`
|
||||
- [ ] 修改 `PointsToCents` 为 `(points * 100) / rate`
|
||||
- [ ] 修改 `RefundPointsAmount` 适配新公式
|
||||
- [ ] **业务逻辑适配 (`internal/service/user`)**
|
||||
- [ ] 检查 `points_convert.go` 中的 `CentsToPoints` 调用,确保读取配置 Key `points_exchange_rate` (或复用旧 Key 但明确含义)。
|
||||
- [ ] 检查 `points_consume.go` 等文件,确保无其他硬编码。
|
||||
- [ ] **单元测试**
|
||||
- [ ] 运行 `internal/pkg/points` 的测试,确保 100 分钱在 Rate=1 时转为 1 积分。
|
||||
|
||||
## 2. 管理后台改造 (Admin Frontend)
|
||||
- [ ] **更新系统配置页 (`web/admin/src/views/system/configs/index.vue`)**
|
||||
- [ ] 新增 "积分配置" 卡片。
|
||||
- [ ] 添加 `points_exchange_rate` 编辑项。
|
||||
- [ ] 添加说明: "1元 = ? 积分"。
|
||||
|
||||
## 3. 小程序改造 (Mini Program)
|
||||
- [ ] **全局搜索积分展示**
|
||||
- [ ] 搜索 `/ 100` 或 `* 0.01` 相关的积分代码。
|
||||
- [ ] **修复工具函数**
|
||||
- [ ] 修改 `utils/format.js` 或类似文件中的 `formatPoints`。
|
||||
- [ ] **修复页面展示**
|
||||
- [ ] `pages-user/points/index.vue` (积分明细)
|
||||
- [ ] `pages-user/orders/detail.vue` (如果有积分抵扣展示)
|
||||
- [ ] 其他涉及积分展示的页面。
|
||||
|
||||
## 4. 数据迁移 (Migration)
|
||||
- [ ] **提供 SQL 脚本**
|
||||
- [ ] 存入 `docs/standardize_points_ratio/migration.sql`。
|
||||
- [ ] **(Optional) 执行迁移**
|
||||
- [ ] 根据用户指示决定是否执行。
|
||||
|
||||
## 5. 验证 (Verification)
|
||||
- [ ] **后端验证**
|
||||
- [ ] 重启服务。
|
||||
- [ ] 模拟支付 1 元,查看数据库增加 1 积分。
|
||||
- [ ] **前端验证**
|
||||
- [ ] 查看积分列表,显示为 1 (而不是 0.01 或 100)。
|
||||
62
docs/standardize_points_ratio/migration.sql
Normal file
62
docs/standardize_points_ratio/migration.sql
Normal file
@ -0,0 +1,62 @@
|
||||
-- Standardize Points Ratio Migration Script
|
||||
-- Purpose: Convert point values from "1 Yuan = 100 Points" (Cents) to "1 Yuan = 1 Point" (Integer).
|
||||
-- Target Tables: user_points, user_points_ledger, orders.
|
||||
|
||||
BEGIN;
|
||||
|
||||
-- 1. Update User Points Current Balance
|
||||
-- Description: Reduce all current point balances by factor of 100.
|
||||
UPDATE user_points
|
||||
SET points = FLOOR(points / 100);
|
||||
|
||||
-- 2. Update User Points Ledger (History)
|
||||
-- Description: Adjust historical records to reflect the new unit.
|
||||
UPDATE user_points_ledger
|
||||
SET points = FLOOR(points / 100);
|
||||
|
||||
-- 3. Update Orders Points Usage
|
||||
-- Description: Adjust recorded points usage in orders.
|
||||
UPDATE orders
|
||||
SET points_amount = FLOOR(points_amount / 100)
|
||||
WHERE points_amount > 0;
|
||||
|
||||
-- 4. Update Task Center Rewards (Points)
|
||||
-- Description: Adjust configured point rewards in Task Center.
|
||||
-- Note: Logic prioritizes 'points' in JSON payload, then 'quantity'.
|
||||
-- Updating 'quantity' is safe. Updating JSON is complex in standard SQL without knowing exact structure/version.
|
||||
-- Assuming simple structure {"points": 100} or similar.
|
||||
-- 4a. Update Quantity for type 'points'
|
||||
UPDATE task_center_task_rewards
|
||||
SET quantity = FLOOR(quantity / 100)
|
||||
WHERE reward_type = 'points' AND quantity >= 100;
|
||||
|
||||
-- 4b. Update RewardPayload? (Optional/Manual)
|
||||
-- Warning: Modifying JSON string requires robust parsing.
|
||||
-- Providing a best-effort text replacement for simple cases {"points": 100} -> {"points": 1}
|
||||
-- This relies on the pattern '"points": ' followed by numbers.
|
||||
-- Recommendation: Manually verify Task Center configurations in Admin Panel after migration.
|
||||
|
||||
|
||||
-- 5. System Config Update (Values)
|
||||
-- Description: Convert known config values if they represent points.
|
||||
-- Example: 'register_points', 'daily_sign_in_points' (if they exist).
|
||||
-- This attempts to update common point-related configs.
|
||||
UPDATE system_configs
|
||||
SET config_value = FLOOR(config_value / 100)
|
||||
WHERE config_key IN ('register_reward_points', 'daily_sign_in_reward_points') AND config_value REGEXP '^[0-9]+$';
|
||||
|
||||
-- 6. System Config Update (Exchange Rate)
|
||||
-- Description: Ensure the new config key is set.
|
||||
INSERT INTO system_configs (config_key, config_value, remark, created_at, updated_at)
|
||||
VALUES ('points_exchange_rate', '1', '1元对应多少积分', NOW(), NOW())
|
||||
ON DUPLICATE KEY UPDATE config_value = '1';
|
||||
|
||||
COMMIT;
|
||||
|
||||
-- NOTE on 'user_inventory':
|
||||
-- Some points data might be embedded in 'remark' field (e.g. '|redeemed_points=100').
|
||||
-- Updating these embedded strings via SQL is complex and risky.
|
||||
-- Refunds for OLD items (redeemed before migration) might fail or deduct excessive points
|
||||
-- if this field is not updated.
|
||||
-- Recommendation: Handle 'refund' logic gracefully for legacy items in code if possible,
|
||||
-- or accept that old items cannot be refunded automatically.
|
||||
52
docs/standardize_points_ratio/walkthrough.md
Normal file
52
docs/standardize_points_ratio/walkthrough.md
Normal file
@ -0,0 +1,52 @@
|
||||
# Walkthrough: Standardize Points Ratio
|
||||
|
||||
## 1. Goal
|
||||
Standardize the Points-to-Yuan ratio to **1 Yuan = 1 Point**, and remove the decimal display logic (previous 100 Points = 1 Yuan) across the system.
|
||||
|
||||
## 2. Changes
|
||||
|
||||
### Backend (`bindbox_game`)
|
||||
- **Core Logic (`internal/pkg/points/convert.go`)**:
|
||||
- Updated `CentsToPoints` to `(cents * rate) / 100`.
|
||||
- Updated `PointsToCents` to `(points * 100) / rate`.
|
||||
- Added unit tests to verify 100 Cents = 1 Point.
|
||||
- **Service Layer (`internal/service/user`)**:
|
||||
- Updated `points_convert.go` to use `points_exchange_rate` config key.
|
||||
- Added `PointsToCents` method for reverse calculation.
|
||||
- Updated `lottery_app.go` to use `PointsToCents` for accurate deduction calculation.
|
||||
- **DB Config**:
|
||||
- Expects `points_exchange_rate` (default 1) instead of `points_exchange_per_cent`.
|
||||
|
||||
### Admin Frontend (`web/admin`)
|
||||
- **System Configs**:
|
||||
- Added "Points Configuration" section.
|
||||
- Allows setting "1 Yuan = N Points" (Default 1).
|
||||
|
||||
### Mini-Program Frontend Display Logic
|
||||
- **Goal**: Ensure Points are displayed as integers and values are consistent.
|
||||
- **Files Modified**:
|
||||
- `pages-user/points/index.vue`
|
||||
- `pages-user/orders/detail.vue`
|
||||
- `pages-user/tasks/index.vue`
|
||||
- `pages/shop/index.vue` (Fixed `/ 100` division for points)
|
||||
- `pages-shop/shop/detail.vue` (Fixed `/ 100` division for points)
|
||||
- **Changes**:
|
||||
- Removed incorrect `/ 100` division for Points display while keeping it for Money (Yuan) display.
|
||||
- formated points to use `.toFixed(0)` to remove decimal places.
|
||||
|
||||
### Database Migration
|
||||
- **Script**: `docs/standardize_points_ratio/migration.sql`
|
||||
- **Action Required**: Run this script to shrink existing point values by 100x to match the new 1:1 definition.
|
||||
|
||||
## 3. Verification
|
||||
- **Unit Tests**:
|
||||
- `go test internal/pkg/points/...` passed.
|
||||
- **Manual Check**:
|
||||
- `TestCentsToPoints` confirmed 100 Cents -> 1 Point.
|
||||
- `TestRefundPointsAmount` confirmed proportional refund works with integer points.
|
||||
|
||||
## 4. Next Steps for User
|
||||
1. **Backup Database**.
|
||||
2. **Deploy Backend & Admin**.
|
||||
3. **Run Migration Script** (`docs/standardize_points_ratio/migration.sql`).
|
||||
4. **Deploy Mini Program**.
|
||||
@ -0,0 +1,46 @@
|
||||
# 任务:修复一番赏次数卡支付与退款逻辑
|
||||
|
||||
## 1. 项目上下文分析
|
||||
- **项目**: BindBox (Blind Box / Ichiban Kuji Game Platform)
|
||||
- **技术栈**: Go (Backend), Vue3/UniApp (Frontend)
|
||||
- **涉及模块**:
|
||||
- 前端:一番赏活动页 (`bindbox-mini/pages-activity/activity/yifanshang/index.vue`)
|
||||
- 后端:抽奖接口 (`internal/api/activity/lottery_app.go`)
|
||||
- 后端:退款接口 (`internal/api/admin/pay_refund_admin.go`)
|
||||
|
||||
## 2. 需求理解与确认
|
||||
### 原始需求
|
||||
1. **不掉支付**: 使用次数卡(Count Card)进行一番赏抽奖时,不应拉起微信支付(因为金额应为0)。
|
||||
2. **退款退卡**: 对使用次数卡支付的订单进行退款时,应退还次数卡(次数),而非退款金额(因为金额为0)或无操作。
|
||||
|
||||
### 问题分析
|
||||
通过代码审查,发现以下问题:
|
||||
1. **前端支付逻辑缺陷**: `index.vue` 在调用 `joinLottery` 后,未根据返回的订单状态或金额判断是否需要支付,而是无条件调用 `createWechatOrder` 并拉起支付。
|
||||
2. **后端抽奖逻辑缺陷**: `lottery_app.go` 在使用次数卡扣费时,虽然将 `ActualAmount` 设为 0,但在 `order.Remark` 中仅记录了 `use_game_pass`,未记录具体使用的次数卡 ID 和扣除数量。
|
||||
3. **后端退款逻辑缺陷**: `pay_refund_admin.go` 在退款时尝试从 `order.Remark` 解析 `game_pass:ID`,但由于上述原因无法解析。且当前逻辑仅尝试恢复 `remaining + 1`,未考虑到一单多抽(Count > 1)的情况。
|
||||
|
||||
## 3. 智能决策策略
|
||||
### 决策点 1:前端如何判断跳过支付?
|
||||
- **方案**: 检查 `joinLottery` 返回的 `actual_amount` 或 `status`。
|
||||
- **依据**: `lottery_app.go` 中,若金额为 0,`Status` 会被置为 2 (Paid),且 `ActualAmount` 为 0。
|
||||
- **实现**: 若 `res.actual_amount === 0` 或 `res.status === 2`,则直接进入抽奖结果展示流程。
|
||||
|
||||
### 决策点 2:后端如何记录次数卡使用情况?
|
||||
- **方案**: 修改 `lottery_app.go`,在 Deduction 循环中记录所有使用的 Pass ID 和对应扣除数。
|
||||
- **格式建议**: `gp_use:ID1:Count1|gp_use:ID2:Count2`
|
||||
- **兼容性**: 需确保不破坏现有 Remark 的其他信息。
|
||||
|
||||
### 决策点 3:退款如何恢复次数?
|
||||
- **方案**: 修改 `pay_refund_admin.go`,解析新的 Remark 格式。
|
||||
- **逻辑**: 遍历所有记录的 ID,按记录的扣除数执行 `UPDATE user_game_passes SET remaining = remaining + ?, total_used = total_used - ? WHERE id = ?`。
|
||||
|
||||
## 4. 最终共识 (Consensus)
|
||||
### 任务边界
|
||||
1. **Frontend**: 修改 `yifanshang/index.vue` 的 `onPaymentConfirm` 方法。
|
||||
2. **Backend**: 修改 `lottery_app.go` 记录 Game Pass Usage。
|
||||
3. **Backend**: 修改 `pay_refund_admin.go` 实现精准的次数卡退还。
|
||||
|
||||
### 验收标准
|
||||
1. **支付测试**: 使用次数卡购买一番赏(单抽或多抽),前端不弹出微信支付,直接显示抽奖结果。
|
||||
2. **数据验证**: 数据库 `orders` 表的 `remark` 字段包含具体的次数卡使用记录(如 `gp_use:101:5`)。
|
||||
3. **退款测试**: 对该订单执行全额退款,对应的次数卡(ID 101)的 `remaining` 增加 5,`total_used` 减少 5。
|
||||
@ -0,0 +1,43 @@
|
||||
# 共识:修复一番赏次数卡支付与退款逻辑
|
||||
|
||||
## 1. 需求描述与验收标准
|
||||
### 需求描述
|
||||
- **不掉支付**: 使用次数卡支付时,若订单金额为0,前端不应拉起微信支付,直接视为支付成功。
|
||||
- **退款退卡**: 次数卡支付的订单退款时,需准确退还使用的次数卡次数。
|
||||
|
||||
### 验收标准
|
||||
1. **前端支付流程**:
|
||||
- [ ] 使用次数卡全额抵扣时,点击“去支付”后直接弹出成功/翻牌界面,无微信支付弹窗。
|
||||
- [ ] 混合支付(次数卡不足补差价)时,仍正常拉起支付(本次主要关注全额抵扣)。
|
||||
2. **后端订单记录**:
|
||||
- [ ] 数据库 `orders.remark` 字段正确记录 `gp_use:<ID>:<Count>`。
|
||||
- [ ] 支持单次使用多张次数卡的情况(如 `gp_use:101:5|gp_use:102:1`)。
|
||||
3. **退款流程**:
|
||||
- [ ] 对次数卡订单执行退款,对应的 `user_game_passes` 记录 `remaining` 增加,`total_used` 减少。
|
||||
- [ ] 退还数量与扣除数量完全一致。
|
||||
- [ ] 退款流水清晰。
|
||||
|
||||
## 2. 技术实现方案
|
||||
### 前端 (Mini-Program)
|
||||
- 修改 `bindbox-mini/pages-activity/activity/yifanshang/index.vue`。
|
||||
- 在 `onPaymentConfirm` 中,接收 `joinLottery` 响应后,判断 `order.ActualAmount == 0` 或 `Status == 2`。
|
||||
- 若满足,直接调用 `onPaymentSuccess` 或模拟成功逻辑,跳过 `createWechatOrder`。
|
||||
|
||||
### 后端 (Go)
|
||||
- **抽奖 (Lottery)**:
|
||||
- 修改 `internal/api/activity/lottery_app.go`。
|
||||
- 在扣除 Game Pass 的循环中,动态构建 Remark 字符串,记录每个 Pass 的扣除量。
|
||||
- **退款 (Refund)**:
|
||||
- 修改 `internal/api/admin/pay_refund_admin.go`。
|
||||
- 升级 Remark 解析逻辑,支持 `gp_use:ID:Count` 格式。
|
||||
- 遍历所有使用的 Pass,逐一执行恢复 SQL。
|
||||
|
||||
## 3. 任务边界限制
|
||||
- 仅针对一番赏业务(Ichiban)。
|
||||
- 仅针对 Game Pass (次数卡) 支付方式。
|
||||
- 不涉及优惠券退款逻辑变更(除非受全额退款逻辑影响,需确保兼容)。
|
||||
|
||||
## 4. 确认所有不确定性已解决
|
||||
- 已确认当前 Frontend 无条件拉起支付是 Bug。
|
||||
- 已确认当前 Backend 未记录详细 Pass ID 是导致无法精确退款的原因。
|
||||
- 已确认 Refund 逻辑需升级以支持多卡/多数量退还。
|
||||
@ -0,0 +1,85 @@
|
||||
# 设计:修复一番赏次数卡支付与退款逻辑
|
||||
|
||||
## 1. 整体架构与流程
|
||||
### 支付流程 (Modified)
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
participant User
|
||||
participant Frontend (Vue)
|
||||
participant Backend (API)
|
||||
participant DB
|
||||
|
||||
User->>Frontend: 选择一番赏格位,点击支付 (使用次数卡)
|
||||
Frontend->>Backend: API: /api/app/lottery/join (use_game_pass=true)
|
||||
Backend->>DB: Check Game Pass Balance
|
||||
Backend->>DB: Deduct Game Pass (Remaining - N)
|
||||
Backend->>DB: Create Order (Amount=0, Status=2, Remark="gp_use:ID:N")
|
||||
Backend-->>Frontend: Response (Success, Amount=0, Status=2)
|
||||
|
||||
alt Amount == 0
|
||||
Frontend->>Frontend: Skip WeChat Pay
|
||||
Frontend->>Frontend: Show Result / Flip Cards
|
||||
else Amount > 0
|
||||
Frontend->>Backend: Create WeChat Order
|
||||
Frontend->>WeChat: Request Payment
|
||||
end
|
||||
```
|
||||
|
||||
### 退款流程 (Modified)
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
participant Admin
|
||||
participant Backend (Refund API)
|
||||
participant DB
|
||||
|
||||
Admin->>Backend: API: /api/admin/refund (OrderNo)
|
||||
Backend->>DB: Get Order & Remark
|
||||
Backend->>Backend: Parse Remark for "gp_use:ID:Count" pairs
|
||||
loop For Each Pass
|
||||
Backend->>DB: Update user_game_passes SET remaining+=Count
|
||||
end
|
||||
Backend->>DB: Update Order Status = Refunded
|
||||
Backend-->>Admin: Success
|
||||
```
|
||||
|
||||
## 2. 核心组件设计
|
||||
### 2.1 Lottery App (`lottery_app.go`)
|
||||
- **Logic**: In `JoinLottery` handler, inside the transaction where `useGamePass` is true.
|
||||
- **Change**:
|
||||
```go
|
||||
// Before
|
||||
deducted += canDeduct
|
||||
// After
|
||||
deducted += canDeduct
|
||||
gamePassUsage = append(gamePassUsage, fmt.Sprintf("gp_use:%d:%d", p.ID, canDeduct))
|
||||
...
|
||||
order.Remark += "|" + strings.Join(gamePassUsage, "|")
|
||||
```
|
||||
|
||||
### 2.2 Refund Admin (`pay_refund_admin.go`)
|
||||
- **Logic**: In `CreateRefund`.
|
||||
- **Change**:
|
||||
- Remove simple regex `game_pass:(\d+)`.
|
||||
- Add loop to find all `gp_use:(\d+):(\d+)`.
|
||||
- Execute restoration for each match.
|
||||
|
||||
### 2.3 Frontend (`index.vue`)
|
||||
- **Logic**: `onPaymentConfirm`.
|
||||
- **Change**:
|
||||
```javascript
|
||||
if (joinResult.actual_amount === 0 || joinResult.status === 2 || joinResult.status === 'paid') {
|
||||
// Direct Success
|
||||
onPaymentSuccess({ result: lotteryResult })
|
||||
return
|
||||
}
|
||||
```
|
||||
|
||||
## 3. 接口契约
|
||||
- 无新增接口。
|
||||
- `JoinLottery` 响应保持不变,前端需利用现有的 `actual_amount` 和 `status` 字段。
|
||||
|
||||
## 4. 异常处理
|
||||
- **Refund Partial Failure**: Cannot easily happen in transaction. If one update fails, whole refund fails.
|
||||
- **Legacy Orders**: Old orders have `use_game_pass` but no `gp_use:ID`. Refund logic should fallback to old behavior (try to find 1 pass or just warn/skip).
|
||||
- *Fallback Strategy*: If no `gp_use` found but `use_game_pass` is present, log warning or try to restore 1 count to *any* valid pass of user?
|
||||
- *Decision*: Since user specifically asked for this fix, we assume it's for FUTURE/NEW orders or current testing. For legacy orders, we can leave as is or try best effort. Given "Strict" requirement, we will implement the new logic. Legacy fallback: Scan `game_pass:ID` (old format if any?) - wait, old code didn't write ID at all. So legacy orders cannot be automatically restored safely. This is acceptable for a "Fix".
|
||||
@ -0,0 +1,28 @@
|
||||
# 项目总结报告:修复一番赏次数卡支付与退款逻辑
|
||||
|
||||
## 1. 任务概述
|
||||
本任务旨在修复“一番赏”业务中,使用次数卡(Game Pass)支付时前端仍拉起微信支付的问题,以及退款时未能正确退还次数卡次数的问题。
|
||||
|
||||
## 2. 完成情况
|
||||
### 2.1 需求实现
|
||||
- [x] **前端支付优化**: `yifanshang/index.vue` 已增加判断逻辑,当 `ActualAmount == 0` 或 `Status == 2` 时,直接跳过微信支付流程,进入开奖结果查询。
|
||||
- [x] **后端记录优化**: `lottery_app.go` 现在会在订单 `Remark` 中以 `gp_use:ID:Count` 格式记录具体的次数卡使用明细。
|
||||
- [x] **后端退款优化**: `pay_refund_admin.go` 已支持解析新的 `gp_use` 格式,并能准确恢复多张卡、多数量的消耗。同时保留了对旧格式 `game_pass:ID` 的兼容支持。
|
||||
|
||||
### 2.2 代码变更
|
||||
- `internal/api/activity/lottery_app.go`: 记录 Game Pass 扣除明细。
|
||||
- `internal/api/admin/pay_refund_admin.go`: 增强退款逻辑,支持多卡恢复。
|
||||
- `bindbox-mini/pages-activity/activity/yifanshang/index.vue`: 优化支付流程,支持 0 元订单。
|
||||
|
||||
## 3. 质量评估
|
||||
- **编译通过**: 后端代码 `go build` 成功,无语法错误。
|
||||
- **逻辑完备性**:
|
||||
- 覆盖了“不掉支付”的核心诉求。
|
||||
- 覆盖了“精准退卡”的核心诉求。
|
||||
- 考虑了新旧数据格式兼容性。
|
||||
- **风险控制**:
|
||||
- 仅针对 `Ichiban` 逻辑生效,不影响其他业务。
|
||||
- 前端改动范围局限于支付确认回调,风险可控。
|
||||
|
||||
## 4. 交付结论
|
||||
以完成所有关键路径的修复,代码已准备就绪,可以部署测试。
|
||||
@ -0,0 +1,40 @@
|
||||
# 任务拆解:修复一番赏次数卡支付与退款逻辑
|
||||
|
||||
## 1. Backend Tasks
|
||||
### 1.1 Update Lottery Logic (Atomize)
|
||||
- **File**: `internal/api/activity/lottery_app.go`
|
||||
- **Goal**: Record specific Game Pass usage in Order Remark.
|
||||
- **Steps**:
|
||||
- Locate `JoinLottery` function.
|
||||
- Inside `useGamePass` block, accumulate used pass IDs and counts.
|
||||
- Append formatted string `gp_use:ID:Count` to `order.Remark`.
|
||||
- **Verification**: Run local test, buy with count card, check DB `orders` table remark.
|
||||
|
||||
### 1.2 Update Refund Logic (Atomize)
|
||||
- **File**: `internal/api/admin/pay_refund_admin.go`
|
||||
- **Goal**: Parse `gp_use` and restore counts.
|
||||
- **Steps**:
|
||||
- Locate `CreateRefund` function.
|
||||
- Replace/Extend existing Game Pass restoration logic.
|
||||
- Implement regex to find all `gp_use:(\d+):(\d+)`.
|
||||
- Loop and execute SQL updates.
|
||||
- **Verification**: Create order with count card (using 1.1), then call refund API, check `user_game_passes` table restoration.
|
||||
|
||||
## 2. Frontend Tasks
|
||||
### 2.1 Update Payment Flow (Atomize)
|
||||
- **File**: `bindbox-mini/pages-activity/activity/yifanshang/index.vue`
|
||||
- **Goal**: Skip WeChat Pay for 0-amount orders.
|
||||
- **Steps**:
|
||||
- Locate `onPaymentConfirm`.
|
||||
- After `joinLottery` returns, check `joinResult.actual_amount === 0` or `status`.
|
||||
- If true, directly call logic to show results (e.g. `onPaymentSuccess` or equivalent logic to flip cards).
|
||||
- Ensure `getLotteryResult` is called (which is already there in logic, just need to skip `createWechatOrder`).
|
||||
- **Verification**: UI test with count card.
|
||||
|
||||
## 3. Dependency Graph
|
||||
```mermaid
|
||||
graph TD
|
||||
B1[Backend: Lottery Logic] --> B2[Backend: Refund Logic]
|
||||
B1 --> F1[Frontend: Payment Flow]
|
||||
```
|
||||
(B2 and F1 can be parallel, but B1 is prerequisite for B2 to be testable with new data).
|
||||
@ -0,0 +1,12 @@
|
||||
# 待办事项:一番赏次数卡修复后续
|
||||
|
||||
## 1. 测试与验证
|
||||
- [ ] **真机验证**: 需要在真机小程序环境测试使用次数卡购买一番赏,确认是否直接跳过支付。
|
||||
- [ ] **退款验证**: 需要在管理后台对生成的次数卡订单进行退款,并检查数据库 `user_game_passes` 表确认次数是否正确恢复。
|
||||
|
||||
## 2. 遗留/潜在问题
|
||||
- [ ] **历史订单处理**: 此修复仅对新生成的订单生效(因为旧订单缺少 `gp_use:ID:Count` 记录)。旧订单退款仍将使用旧逻辑(仅退 1 次)。如果需要处理大量历史订单的批量退款,建议通过 SQL 手动修复或编写一次性脚本。
|
||||
- [ ] **多端兼容**: 目前仅修改了 `bindbox-mini`(小程序端)。如果存在 App 端或 H5 端,需确认是否复用相同逻辑或需要单独修改。
|
||||
|
||||
## 3. 配置建议
|
||||
- 无新增配置项。
|
||||
95
docs/玩家管理Bug修复/ALIGNMENT_玩家管理Bug修复.md
Normal file
95
docs/玩家管理Bug修复/ALIGNMENT_玩家管理Bug修复.md
Normal file
@ -0,0 +1,95 @@
|
||||
# 玩家管理Bug修复 - 需求对齐
|
||||
|
||||
## 项目上下文
|
||||
- **前端**: Vue 3 + TypeScript + Element Plus
|
||||
- **后端**: Go (Gin框架)
|
||||
- **关键文件**:
|
||||
- 玩家列表: `web/admin/src/views/player-manage/index.vue`
|
||||
- 分页Hook: `web/admin/src/hooks/core/useTable.ts`
|
||||
- 用户详情抽屉: `web/admin/src/views/player-manage/modules/player-detail-drawer.vue`
|
||||
- 用户盈亏图表: `web/admin/src/views/player-manage/modules/player-profit-loss-chart.vue`
|
||||
- 活动分析抽屉: `web/admin/src/views/activity/manage/components/ActivityAnalysisDrawer.vue`
|
||||
|
||||
---
|
||||
|
||||
## Bug列表
|
||||
|
||||
### Bug 1: 玩家列表分页失效
|
||||
**现象**: 点击下一页后会自动跳回第1页
|
||||
|
||||
**初步分析**:
|
||||
- 玩家列表使用 `useTable` hook 管理分页
|
||||
- `handleCurrentChange` 函数会修改 `pagination.current` 并调用 `getData`
|
||||
- 可能原因:
|
||||
1. `handleSearch` 函数在搜索时重置了页码但没有正确更新
|
||||
2. `getDataDebounced` 使用的参数可能覆盖了新的页码值
|
||||
3. 搜索参数和分页参数同步问题
|
||||
|
||||
**需要确认**: 具体是在什么场景下触发?是否有搜索条件?
|
||||
|
||||
---
|
||||
|
||||
### Bug 2: 活动的游戏盈亏仪表盘
|
||||
**现象描述不清,需要澄清**
|
||||
|
||||
**可能的理解**:
|
||||
1. 需要在仪表盘(Dashboard)添加活动的游戏盈亏分析组件?
|
||||
2. 现有的 `ActivityAnalysisDrawer` 有问题需要修复?
|
||||
3. 需要一个全局的活动盈亏汇总仪表盘?
|
||||
|
||||
**当前现有功能**:
|
||||
- `ActivityAnalysisDrawer.vue`: 单个活动的数据分析抽屉,包含总营收、总成本、毛利润、参与人数等
|
||||
|
||||
**需要澄清**: 具体需要什么功能?是新增组件还是修复现有问题?
|
||||
|
||||
---
|
||||
|
||||
### Bug 3: 用户盈亏分析需要明细
|
||||
**需求理解**:
|
||||
- 当前 `player-profit-loss-chart.vue` 显示用户盈亏趋势图表和汇总数据
|
||||
- 需要增加订单明细列表,可以点击查看每笔订单的盈亏
|
||||
- 明细需包含: 道具卡、优惠券等使用情况
|
||||
|
||||
**当前支持**:
|
||||
- 有资产分项概览: 商品产出、积分收益、道具卡价值、优惠券价值
|
||||
- 有趋势图表展示投入、产出、净盈亏
|
||||
|
||||
**待实现**:
|
||||
- 盈亏明细列表(可分页、可搜索)
|
||||
- 每条记录显示: 订单信息、支付金额、获得奖品价值、使用的优惠券/道具卡及其价值
|
||||
|
||||
---
|
||||
|
||||
### Bug 4: 用户资产加一个搜索
|
||||
**需求理解**:
|
||||
- 在用户详情抽屉的"资产"Tab中增加搜索功能
|
||||
- 当前资产列表使用 `ArtDataListCard` 组件展示
|
||||
|
||||
**待实现**:
|
||||
- 搜索框(按商品名称、订单号等搜索)
|
||||
- 可能需要修改后端API支持搜索参数
|
||||
|
||||
---
|
||||
|
||||
## 疑问澄清
|
||||
|
||||
### 优先级问题
|
||||
1. **Bug 2** 描述不够清晰,需要进一步说明具体需求:
|
||||
- 是否需要在主仪表盘添加新组件?
|
||||
- 还是修复现有 `ActivityAnalysisDrawer` 的问题?
|
||||
- 需要展示哪些数据?
|
||||
|
||||
### 技术问题
|
||||
2. **Bug 1** 分页问题:
|
||||
- 是否只在有搜索条件时出现?
|
||||
- 是否与特定浏览器相关?
|
||||
|
||||
### 范围确认
|
||||
3. **Bug 3** 盈亏明细:
|
||||
- 明细是否需要导出功能?
|
||||
- 是否需要按时间范围筛选?
|
||||
- 每条明细需要展示哪些具体字段?
|
||||
|
||||
4. **Bug 4** 资产搜索:
|
||||
- 支持哪些搜索条件?商品名称?订单号?
|
||||
- 是否需要后端支持模糊搜索?
|
||||
59
docs/玩家管理Bug修复/CONSENSUS_玩家管理Bug修复.md
Normal file
59
docs/玩家管理Bug修复/CONSENSUS_玩家管理Bug修复.md
Normal file
@ -0,0 +1,59 @@
|
||||
# 玩家管理Bug修复 - 共识文档
|
||||
|
||||
## 需求确认
|
||||
|
||||
### Bug 1: 玩家列表分页失效
|
||||
**现象**: 点击下一页后自动跳回第1页
|
||||
**确认范围**: 在玩家列表页面点击分页控件的下一页时出现
|
||||
|
||||
### Bug 2: 活动游戏盈亏仪表盘
|
||||
**确认理解**: 需要修复/完善活动的盈亏分析功能
|
||||
- 目标:完善现有的 `ActivityAnalysisDrawer` 组件功能
|
||||
|
||||
### Bug 3: 用户盈亏分析明细
|
||||
**确认理解**: 在用户盈亏分析中增加订单级明细列表
|
||||
- 每条明细显示:订单信息、支付金额、获得奖品价值
|
||||
- 包含使用的优惠券、道具卡及其价值
|
||||
|
||||
### Bug 4: 用户资产搜索
|
||||
**确认理解**: 在用户详情抽屉的资产Tab中增加搜索功能
|
||||
|
||||
---
|
||||
|
||||
## 技术实现方案
|
||||
|
||||
### Bug 1 修复方案
|
||||
**根因分析**:
|
||||
- 玩家管理页面使用 `useTable` hook 管理分页
|
||||
- `ArtTable` 组件通过 `pagination:current-change` 事件通知页码变化
|
||||
- 页面监听该事件调用 `handleCurrentChange` → `getData(params)`
|
||||
- 问题可能出在 `useTable.ts` 中搜索参数和分页参数的同步逻辑
|
||||
|
||||
**修复方案**:
|
||||
- 检查 `handleCurrentChange` 函数中页码参数的传递
|
||||
- 确保分页参数不被搜索参数覆盖
|
||||
|
||||
### Bug 2 修复方案
|
||||
**现有功能**: `ActivityAnalysisDrawer.vue` 已有活动数据分析功能
|
||||
**待完善**: 确认功能是否正常工作,是否需要增强
|
||||
|
||||
### Bug 3 实现方案
|
||||
**新增功能**:
|
||||
1. 后端新增API: `GET /api/admin/users/{user_id}/profit_loss/details`
|
||||
- 返回每笔订单的盈亏明细
|
||||
- 包含:订单信息、支付金额、获得价值、使用的优惠券/道具卡
|
||||
2. 前端增加明细列表组件
|
||||
|
||||
### Bug 4 实现方案
|
||||
**新增功能**:
|
||||
1. 后端API修改: `GET /api/admin/users/{user_id}/inventory` 支持搜索参数
|
||||
2. 前端在资产Tab增加搜索框
|
||||
|
||||
---
|
||||
|
||||
## 验收标准
|
||||
|
||||
1. **Bug 1**: 玩家列表可以正常翻页,页码不会跳回第一页
|
||||
2. **Bug 2**: 活动盈亏仪表盘功能正常工作
|
||||
3. **Bug 3**: 用户盈亏分析页可以查看订单明细列表
|
||||
4. **Bug 4**: 用户资产列表可以按商品名称搜索
|
||||
177
docs/玩家管理Bug修复/DESIGN_玩家管理Bug修复.md
Normal file
177
docs/玩家管理Bug修复/DESIGN_玩家管理Bug修复.md
Normal file
@ -0,0 +1,177 @@
|
||||
# 玩家管理Bug修复 - 架构设计
|
||||
|
||||
## 整体架构图
|
||||
|
||||
```mermaid
|
||||
graph TB
|
||||
subgraph Frontend["前端 Vue3"]
|
||||
PM[玩家管理页面]
|
||||
PD[用户详情抽屉]
|
||||
PL[盈亏分析组件]
|
||||
AD["活动分析抽屉(已有)"]
|
||||
end
|
||||
|
||||
subgraph Backend["后端 Go/Gin"]
|
||||
UA[users_admin.go]
|
||||
UP[users_profit_loss.go]
|
||||
AA[activities_admin.go]
|
||||
end
|
||||
|
||||
PM --> |分页请求| UA
|
||||
PD --> |资产列表+搜索| UA
|
||||
PL --> |盈亏趋势| UP
|
||||
PL --> |盈亏明细| UP
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Bug 1: 分页修复
|
||||
|
||||
### 问题分析
|
||||
```
|
||||
player-manage/index.vue
|
||||
└── useTable hook
|
||||
├── handleCurrentChange(newCurrent)
|
||||
│ └── getData(params) // params中需要包含正确的page参数
|
||||
└── 问题:searchParams可能覆盖新的页码
|
||||
```
|
||||
|
||||
### 修复方案
|
||||
在 `index.vue` 中,`handleSearch` 函数调用 `getDataDebounced` 时传递了搜索参数,这可能导致分页参数被覆盖。
|
||||
|
||||
需要检查的代码路径:
|
||||
1. `ArtTable` 组件发出 `pagination:current-change` 事件
|
||||
2. `useTable` 的 `handleCurrentChange` 接收新页码
|
||||
3. 确保页码正确传递给 API 请求
|
||||
|
||||
---
|
||||
|
||||
## Bug 2: 活动盈亏仪表盘
|
||||
|
||||
### 现有组件
|
||||
- `ActivityAnalysisDrawer.vue`: 单活动数据分析
|
||||
- 计算: 总营收、总成本、毛利润、参与人数
|
||||
|
||||
### 待确认/完善
|
||||
- 检查计算逻辑是否正确
|
||||
- 确保数据展示完整
|
||||
|
||||
---
|
||||
|
||||
## Bug 3: 用户盈亏明细
|
||||
|
||||
### 新增API
|
||||
|
||||
#### 后端: `GET /api/admin/users/{user_id}/stats/profit_loss_details`
|
||||
|
||||
**请求参数**:
|
||||
```go
|
||||
type profitLossDetailsRequest struct {
|
||||
Page int `form:"page"`
|
||||
PageSize int `form:"page_size"`
|
||||
RangeType string `form:"rangeType"` // today, 7d, 30d, all
|
||||
}
|
||||
```
|
||||
|
||||
**响应结构**:
|
||||
```go
|
||||
type profitLossDetailItem struct {
|
||||
OrderID int64 `json:"order_id"`
|
||||
OrderNo string `json:"order_no"`
|
||||
CreatedAt string `json:"created_at"`
|
||||
ActualAmount int64 `json:"actual_amount"` // 实际支付金额(分)
|
||||
RefundAmount int64 `json:"refund_amount"` // 退款金额(分)
|
||||
NetCost int64 `json:"net_cost"` // 净投入(分)
|
||||
PrizeValue int64 `json:"prize_value"` // 获得奖品价值(分)
|
||||
PointsEarned int64 `json:"points_earned"` // 获得积分
|
||||
PointsValue int64 `json:"points_value"` // 积分价值(分)
|
||||
CouponUsedValue int64 `json:"coupon_used_value"` // 使用优惠券价值(分)
|
||||
ItemCardUsed string `json:"item_card_used"` // 使用的道具卡名称
|
||||
ItemCardValue int64 `json:"item_card_value"` // 道具卡价值(分)
|
||||
NetProfit int64 `json:"net_profit"` // 净盈亏
|
||||
ActivityName string `json:"activity_name"` // 活动名称
|
||||
PrizeName string `json:"prize_name"` // 奖品名称
|
||||
SourceType int `json:"source_type"` // 来源类型
|
||||
}
|
||||
|
||||
type profitLossDetailsResponse struct {
|
||||
Page int `json:"page"`
|
||||
PageSize int `json:"page_size"`
|
||||
Total int64 `json:"total"`
|
||||
List []profitLossDetailItem `json:"list"`
|
||||
Summary struct {
|
||||
TotalCost int64 `json:"total_cost"`
|
||||
TotalValue int64 `json:"total_value"`
|
||||
TotalProfit int64 `json:"total_profit"`
|
||||
} `json:"summary"`
|
||||
}
|
||||
```
|
||||
|
||||
### 前端组件修改
|
||||
|
||||
在 `player-profit-loss-chart.vue` 中增加:
|
||||
1. "查看明细" 按钮
|
||||
2. 明细表格(支持分页)
|
||||
3. 显示字段:时间、订单号、支付金额、获得价值、使用优惠券/道具卡、净盈亏
|
||||
|
||||
---
|
||||
|
||||
## Bug 4: 资产搜索
|
||||
|
||||
### 后端修改
|
||||
|
||||
修改 `users_admin.go` 中的 `ListUserInventory`:
|
||||
```go
|
||||
type listInventoryRequest struct {
|
||||
Page int `form:"page"`
|
||||
PageSize int `form:"page_size"`
|
||||
Keyword string `form:"keyword"` // 新增:搜索关键词
|
||||
}
|
||||
```
|
||||
|
||||
查询逻辑增加:
|
||||
```go
|
||||
if req.Keyword != "" {
|
||||
query = query.Where(db.Products.Name.Like("%" + req.Keyword + "%"))
|
||||
}
|
||||
```
|
||||
|
||||
### 前端修改
|
||||
|
||||
在 `player-detail-drawer.vue` 资产Tab中:
|
||||
1. 增加搜索输入框
|
||||
2. 调用API时传递 `keyword` 参数
|
||||
|
||||
---
|
||||
|
||||
## 数据流图
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
participant User as 用户
|
||||
participant FE as 前端
|
||||
participant BE as 后端
|
||||
participant DB as 数据库
|
||||
|
||||
Note over User, DB: Bug 3: 盈亏明细查询
|
||||
User->>FE: 点击"查看明细"
|
||||
FE->>BE: GET /users/:id/stats/profit_loss_details
|
||||
BE->>DB: 查询订单+奖品+优惠券+道具卡
|
||||
DB-->>BE: 返回数据
|
||||
BE-->>FE: JSON响应
|
||||
FE-->>User: 展示明细列表
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 文件变更清单
|
||||
|
||||
| 文件 | 变更类型 | 说明 |
|
||||
|------|---------|------|
|
||||
| `web/admin/src/views/player-manage/index.vue` | 修改 | 修复分页问题 |
|
||||
| `web/admin/src/hooks/core/useTable.ts` | 检查 | 确认分页逻辑 |
|
||||
| `web/admin/src/views/player-manage/modules/player-profit-loss-chart.vue` | 修改 | 添加明细列表 |
|
||||
| `web/admin/src/views/player-manage/modules/player-detail-drawer.vue` | 修改 | 添加资产搜索 |
|
||||
| `web/admin/src/api/player-manage.ts` | 修改 | 添加明细API调用 |
|
||||
| `internal/api/admin/users_profit_loss.go` | 修改 | 添加明细API |
|
||||
| `internal/api/admin/users_admin.go` | 修改 | 资产列表添加搜索 |
|
||||
40
go.mod
40
go.mod
@ -1,6 +1,8 @@
|
||||
module bindbox-game
|
||||
|
||||
go 1.19
|
||||
go 1.24.0
|
||||
|
||||
toolchain go1.24.2
|
||||
|
||||
require (
|
||||
github.com/DATA-DOG/go-sqlmock v1.5.2
|
||||
@ -26,17 +28,22 @@ require (
|
||||
github.com/rs/cors/wrapper/gin v0.0.0-20231013084403-73f81b45a644
|
||||
github.com/spf13/cast v1.5.1
|
||||
github.com/spf13/viper v1.17.0
|
||||
github.com/stretchr/testify v1.8.4
|
||||
github.com/stretchr/testify v1.11.1
|
||||
github.com/swaggo/files v1.0.1
|
||||
github.com/swaggo/gin-swagger v1.6.0
|
||||
github.com/swaggo/swag v1.16.2
|
||||
github.com/tealeg/xlsx v1.0.5
|
||||
github.com/tencentyun/cos-go-sdk-v5 v0.7.37
|
||||
github.com/wechatpay-apiv3/wechatpay-go v0.2.21
|
||||
go.opentelemetry.io/otel v1.39.0
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.39.0
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.39.0
|
||||
go.opentelemetry.io/otel/sdk v1.39.0
|
||||
go.opentelemetry.io/otel/trace v1.39.0
|
||||
go.uber.org/multierr v1.10.0
|
||||
go.uber.org/zap v1.26.0
|
||||
golang.org/x/crypto v0.27.0
|
||||
golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d
|
||||
golang.org/x/crypto v0.44.0
|
||||
golang.org/x/tools v0.38.0
|
||||
gopkg.in/natefinch/lumberjack.v2 v2.2.1
|
||||
gorm.io/datatypes v1.1.1-0.20230130040222-c43177d3cf8c
|
||||
gorm.io/driver/mysql v1.5.2
|
||||
@ -58,6 +65,7 @@ require (
|
||||
github.com/aliyun/credentials-go v1.4.5 // indirect
|
||||
github.com/beorn7/perks v1.0.1 // indirect
|
||||
github.com/bytedance/sonic/loader v0.2.4 // indirect
|
||||
github.com/cenkalti/backoff/v5 v5.0.3 // indirect
|
||||
github.com/cespare/xxhash/v2 v2.3.0 // indirect
|
||||
github.com/clbanning/mxj v1.8.4 // indirect
|
||||
github.com/clbanning/mxj/v2 v2.7.0 // indirect
|
||||
@ -67,14 +75,18 @@ require (
|
||||
github.com/fsnotify/fsnotify v1.7.0 // indirect
|
||||
github.com/gabriel-vasile/mimetype v1.4.2 // indirect
|
||||
github.com/gin-contrib/sse v0.1.0 // indirect
|
||||
github.com/go-logr/logr v1.4.3 // indirect
|
||||
github.com/go-logr/stdr v1.2.2 // indirect
|
||||
github.com/go-openapi/jsonpointer v0.19.5 // indirect
|
||||
github.com/go-openapi/jsonreference v0.19.6 // indirect
|
||||
github.com/go-openapi/spec v0.20.4 // indirect
|
||||
github.com/go-openapi/swag v0.19.15 // indirect
|
||||
github.com/go-sql-driver/mysql v1.7.0 // indirect
|
||||
github.com/goccy/go-json v0.10.2 // indirect
|
||||
github.com/golang/protobuf v1.5.3 // indirect
|
||||
github.com/golang/protobuf v1.5.4 // indirect
|
||||
github.com/google/go-querystring v1.0.0 // indirect
|
||||
github.com/google/uuid v1.6.0 // indirect
|
||||
github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.3 // indirect
|
||||
github.com/hashicorp/hcl v1.0.0 // indirect
|
||||
github.com/jinzhu/inflection v1.0.0 // indirect
|
||||
github.com/jinzhu/now v1.1.5 // indirect
|
||||
@ -107,14 +119,20 @@ require (
|
||||
github.com/tjfoc/gmsm v1.4.1 // indirect
|
||||
github.com/twitchyliquid64/golang-asm v0.15.1 // indirect
|
||||
github.com/ugorji/go/codec v1.2.11 // indirect
|
||||
go.opentelemetry.io/auto/sdk v1.2.1 // indirect
|
||||
go.opentelemetry.io/otel/metric v1.39.0 // indirect
|
||||
go.opentelemetry.io/proto/otlp v1.9.0 // indirect
|
||||
golang.org/x/arch v0.4.0 // indirect
|
||||
golang.org/x/exp v0.0.0-20230905200255-921286631fa9 // indirect
|
||||
golang.org/x/mod v0.17.0 // indirect
|
||||
golang.org/x/net v0.29.0 // indirect
|
||||
golang.org/x/sync v0.8.0 // indirect
|
||||
golang.org/x/sys v0.25.0 // indirect
|
||||
golang.org/x/text v0.18.0 // indirect
|
||||
google.golang.org/protobuf v1.31.0 // indirect
|
||||
golang.org/x/mod v0.29.0 // indirect
|
||||
golang.org/x/net v0.47.0 // indirect
|
||||
golang.org/x/sync v0.18.0 // indirect
|
||||
golang.org/x/sys v0.39.0 // indirect
|
||||
golang.org/x/text v0.31.0 // indirect
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20251202230838-ff82c1b0f217 // indirect
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20251202230838-ff82c1b0f217 // indirect
|
||||
google.golang.org/grpc v1.77.0 // indirect
|
||||
google.golang.org/protobuf v1.36.10 // indirect
|
||||
gopkg.in/ini.v1 v1.67.0 // indirect
|
||||
gopkg.in/yaml.v2 v2.4.0 // indirect
|
||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||
|
||||
105
go.sum
105
go.sum
@ -104,7 +104,9 @@ github.com/aliyun/credentials-go v1.4.5/go.mod h1:Jm6d+xIgwJVLVWT561vy67ZRP4lPTQ
|
||||
github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
|
||||
github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
|
||||
github.com/bsm/ginkgo/v2 v2.12.0 h1:Ny8MWAHyOepLGlLKYmXG4IEkioBysk6GpaRTLC8zwWs=
|
||||
github.com/bsm/ginkgo/v2 v2.12.0/go.mod h1:SwYbGRRDovPVboqFv0tPTcG1sN61LM1Z4ARdbAV9g4c=
|
||||
github.com/bsm/gomega v1.27.10 h1:yeMWxP2pV2fG3FgAODIY8EiRE3dy0aeFYt4l7wh6yKA=
|
||||
github.com/bsm/gomega v1.27.10/go.mod h1:JyEr/xRbxbtgWNi8tIEVPUYZ5Dzef52k01W3YH0H+O0=
|
||||
github.com/bwmarrin/snowflake v0.3.0 h1:xm67bEhkKh6ij1790JB83OujPR5CzNe8QuQqAgISZN0=
|
||||
github.com/bwmarrin/snowflake v0.3.0/go.mod h1:NdZxfVWX+oR6y2K0o6qAYv6gIOP9rjG0/E9WsDpxqwE=
|
||||
github.com/bytedance/sonic v1.13.2 h1:8/H1FempDZqC4VqjptGo14QQlJx8VdZJegxs6wwfqpQ=
|
||||
@ -112,6 +114,8 @@ github.com/bytedance/sonic v1.13.2/go.mod h1:o68xyaF9u2gvVBuGHPlUVCy+ZfmNNO5ETf1
|
||||
github.com/bytedance/sonic/loader v0.1.1/go.mod h1:ncP89zfokxS5LZrJxl5z0UJcsk4M4yY2JpfqGeCtNLU=
|
||||
github.com/bytedance/sonic/loader v0.2.4 h1:ZWCw4stuXUsn1/+zQDqeE7JKP+QO47tz7QCNan80NzY=
|
||||
github.com/bytedance/sonic/loader v0.2.4/go.mod h1:N8A3vUdtUebEY2/VQC0MyhYeKUFosQU6FxH2JmUe6VI=
|
||||
github.com/cenkalti/backoff/v5 v5.0.3 h1:ZN+IMa753KfX5hd8vVaMixjnqRZ3y8CuJKRKj1xcsSM=
|
||||
github.com/cenkalti/backoff/v5 v5.0.3/go.mod h1:rkhZdG3JZukswDf7f0cwqPNk4K0sa+F97BxZthm/crw=
|
||||
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
|
||||
github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs=
|
||||
github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
||||
@ -148,11 +152,13 @@ github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7
|
||||
github.com/fatih/color v1.14.1 h1:qfhVLaG5s+nCROl1zJsZRxFeYrHLqWroPOQ8BWiNb4w=
|
||||
github.com/fatih/color v1.14.1/go.mod h1:2oHN61fhTpgcxD3TSWCgKDiH1+x4OiDVVGH8WlgGZGg=
|
||||
github.com/frankban/quicktest v1.14.4 h1:g2rn0vABPOOXmZUj+vbmUp0lPoXEMuhTpIluN0XL9UY=
|
||||
github.com/frankban/quicktest v1.14.4/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0=
|
||||
github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA=
|
||||
github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM=
|
||||
github.com/gabriel-vasile/mimetype v1.4.2 h1:w5qFW6JKBz9Y393Y4q372O9A7cUSequkh1Q7OhCmWKU=
|
||||
github.com/gabriel-vasile/mimetype v1.4.2/go.mod h1:zApsH/mKG4w07erKIaJPFiX0Tsq9BFQgN3qGY5GnNgA=
|
||||
github.com/gin-contrib/gzip v0.0.6 h1:NjcunTcGAj5CO1gn4N8jHOSIeRFHIbn51z6K+xaN4d4=
|
||||
github.com/gin-contrib/gzip v0.0.6/go.mod h1:QOJlmV2xmayAjkNS2Y8NQsMneuRShOU/kjovCXNuzzk=
|
||||
github.com/gin-contrib/pprof v1.4.0 h1:XxiBSf5jWZ5i16lNOPbMTVdgHBdhfGRD5PZ1LWazzvg=
|
||||
github.com/gin-contrib/pprof v1.4.0/go.mod h1:RrehPJasUVBPK6yTUwOl8/NP6i0vbUgmxtis+Z5KE90=
|
||||
github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE=
|
||||
@ -163,6 +169,11 @@ github.com/gin-gonic/gin v1.9.1/go.mod h1:hPrL7YrpYKXt5YId3A/Tnip5kqbEAP+KLuI3SU
|
||||
github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU=
|
||||
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
|
||||
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
|
||||
github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
|
||||
github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI=
|
||||
github.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
|
||||
github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
|
||||
github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=
|
||||
github.com/go-openapi/jsonpointer v0.19.3/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg=
|
||||
github.com/go-openapi/jsonpointer v0.19.5 h1:gZr+CIYByUqjcgeLXnQu2gHYQC9o73G2XUeOFYEICuY=
|
||||
github.com/go-openapi/jsonpointer v0.19.5/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg=
|
||||
@ -175,6 +186,7 @@ github.com/go-openapi/swag v0.19.15 h1:D2NRCBzS9/pEY3gP9Nl8aDqGUcPFrwG2p+CNFrLyr
|
||||
github.com/go-openapi/swag v0.19.15/go.mod h1:QYRuS/SOXUCsnplDa677K7+DxSOj6IPNl/eQntq43wQ=
|
||||
github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4=
|
||||
github.com/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s=
|
||||
github.com/go-playground/assert/v2 v2.2.0/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4=
|
||||
github.com/go-playground/locales v0.14.0/go.mod h1:sawfccIbzZTqEDETgFXqTho0QybSa7l++s0DH+LDiLs=
|
||||
github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA=
|
||||
github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY=
|
||||
@ -195,7 +207,9 @@ github.com/goccy/go-json v0.10.2/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MG
|
||||
github.com/golang-jwt/jwt/v5 v5.2.0 h1:d/ix8ftRUorsN+5eMIlF4T6J8CAt9rch3My2winC1Jw=
|
||||
github.com/golang-jwt/jwt/v5 v5.2.0/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk=
|
||||
github.com/golang-sql/civil v0.0.0-20220223132316-b832511892a9 h1:au07oEsX2xN0ktxqI+Sida1w446QrXBRJ0nee3SNZlA=
|
||||
github.com/golang-sql/civil v0.0.0-20220223132316-b832511892a9/go.mod h1:8vg3r2VgvsThLBIFL93Qb5yWzgyZWhEmBwUJWevAkK0=
|
||||
github.com/golang-sql/sqlexp v0.1.0 h1:ZCD6MBpcuOVfGVqsEmY5/4FtYiKz6tSyUv9LPEDei6A=
|
||||
github.com/golang-sql/sqlexp v0.1.0/go.mod h1:J4ad9Vo8ZCWQ2GMrC4UCQy1JpCbwU9m3EOqtpKwwwHI=
|
||||
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
|
||||
github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||
github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||
@ -222,8 +236,8 @@ github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QD
|
||||
github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
|
||||
github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
|
||||
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
|
||||
github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg=
|
||||
github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
|
||||
github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek=
|
||||
github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps=
|
||||
github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
|
||||
github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
|
||||
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
|
||||
@ -236,8 +250,9 @@ github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/
|
||||
github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
|
||||
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
||||
github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
|
||||
github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
|
||||
github.com/google/go-querystring v1.0.0 h1:Xkwi/a1rcvNg1PPYe5vI8GbeBY/jrVuDX5ASuANWTrk=
|
||||
github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck=
|
||||
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
||||
@ -256,13 +271,16 @@ github.com/google/pprof v0.0.0-20201203190320-1bf35d6f28c2/go.mod h1:kpwsk12EmLe
|
||||
github.com/google/pprof v0.0.0-20201218002935-b9804c9f04c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
|
||||
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
|
||||
github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/google/uuid v1.1.2 h1:EVhdT+1Kseyi1/pUmXKaFxYsDNy9RQYkMWRH68J/W7Y=
|
||||
github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
|
||||
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg=
|
||||
github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk=
|
||||
github.com/googleapis/google-cloud-go-testing v0.0.0-20200911160855-bcd43fbb19e8/go.mod h1:dvDLG8qkwmyD9a/MJJN3XJcT3xFxOKAvTZGvuZmac9g=
|
||||
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
|
||||
github.com/gopherjs/gopherjs v0.0.0-20200217142428-fce0ec30dd00/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
|
||||
github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.3 h1:NmZ1PKzSTQbuGHw9DGPFomqkkLWMC+vZCkfs+FHv1Vg=
|
||||
github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.3/go.mod h1:zQrxl1YP88HQlA6i9c63DSVPFklWpGX4OWAc9bFuaH4=
|
||||
github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
|
||||
github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
|
||||
github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4=
|
||||
@ -270,16 +288,25 @@ github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T
|
||||
github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
|
||||
github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
|
||||
github.com/issue9/assert/v4 v4.1.1 h1:OhPE8SB8n/qZCNGLQa+6MQtr/B3oON0JAVj68k8jJlc=
|
||||
github.com/issue9/assert/v4 v4.1.1/go.mod h1:v7qDRXi7AsaZZNh8eAK2rkLJg5/clztqQGA1DRv9Lv4=
|
||||
github.com/issue9/identicon/v2 v2.1.2 h1:tu+4vveoiJNXfmWYvl1pDcZSAHCG37+lsoEc2UfCzkI=
|
||||
github.com/issue9/identicon/v2 v2.1.2/go.mod h1:h5JXMtcgkqxltElhpF7PPicNyvFDWzi8VCSHdNjG7KY=
|
||||
github.com/jackc/chunkreader/v2 v2.0.1 h1:i+RDz65UE+mmpjTfyz0MoVTnzeYxroil2G82ki7MGG8=
|
||||
github.com/jackc/chunkreader/v2 v2.0.1/go.mod h1:odVSm741yZoC3dpHEUXIqA9tQRhFrgOHwnPIn9lDKlk=
|
||||
github.com/jackc/pgconn v1.13.0 h1:3L1XMNV2Zvca/8BYhzcRFS70Lr0WlDg16Di6SFGAbys=
|
||||
github.com/jackc/pgconn v1.13.0/go.mod h1:AnowpAqO4CMIIJNZl2VJp+KrkAZciAkhEl0W0JIobpI=
|
||||
github.com/jackc/pgio v1.0.0 h1:g12B9UwVnzGhueNavwioyEEpAmqMe1E/BN9ES+8ovkE=
|
||||
github.com/jackc/pgio v1.0.0/go.mod h1:oP+2QK2wFfUWgr+gxjoBH9KGBb31Eio69xUb0w5bYf8=
|
||||
github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsIM=
|
||||
github.com/jackc/pgpassfile v1.0.0/go.mod h1:CEx0iS5ambNFdcRtxPj5JhEz+xB6uRky5eyVu/W2HEg=
|
||||
github.com/jackc/pgproto3/v2 v2.3.1 h1:nwj7qwf0S+Q7ISFfBndqeLwSwxs+4DPsbRFjECT1Y4Y=
|
||||
github.com/jackc/pgproto3/v2 v2.3.1/go.mod h1:WfJCnwN3HIg9Ish/j3sgWXnAfK8A9Y0bwXYU5xKaEdA=
|
||||
github.com/jackc/pgservicefile v0.0.0-20200714003250-2b9c44734f2b h1:C8S2+VttkHFdOOCXJe+YGfa4vHYwlt4Zx+IVXQ97jYg=
|
||||
github.com/jackc/pgservicefile v0.0.0-20200714003250-2b9c44734f2b/go.mod h1:vsD4gTJCa9TptPL8sPkXrLZ+hDuNrZCnj29CQpr4X1E=
|
||||
github.com/jackc/pgtype v1.12.0 h1:Dlq8Qvcch7kiehm8wPGIW0W3KsCCHJnRacKW0UM8n5w=
|
||||
github.com/jackc/pgtype v1.12.0/go.mod h1:LUMuVrfsFfdKGLw+AFFVv6KtHOFMwRgDDzBt76IqCA4=
|
||||
github.com/jackc/pgx/v4 v4.17.2 h1:0Ut0rpeKwvIVbMQ1KbMBU4h6wxehBI535LK6Flheh8E=
|
||||
github.com/jackc/pgx/v4 v4.17.2/go.mod h1:lcxIZN44yMIrWI78a5CpucdD14hX0SBDbNRvjDBItsw=
|
||||
github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E=
|
||||
github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc=
|
||||
github.com/jinzhu/now v1.1.2/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8=
|
||||
@ -305,6 +332,7 @@ github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORN
|
||||
github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
|
||||
github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk=
|
||||
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
|
||||
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
|
||||
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
||||
@ -330,6 +358,7 @@ github.com/mattn/go-sqlite3 v1.14.15/go.mod h1:2eHXhiwb8IkHr+BDWZGa96P6+rkvnG63S
|
||||
github.com/matttproud/golang_protobuf_extensions v1.0.4 h1:mmDVorXM7PCGKw94cs5zkfA9PSy5pEvNWRP0ET0TIVo=
|
||||
github.com/matttproud/golang_protobuf_extensions v1.0.4/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4=
|
||||
github.com/microsoft/go-mssqldb v0.17.0 h1:Fto83dMZPnYv1Zwx5vHHxpNraeEaUlQ/hhHLgZiaenE=
|
||||
github.com/microsoft/go-mssqldb v0.17.0/go.mod h1:OkoNGhGEs8EZqchVTtochlXruEhEOaO4S0d2sB5aeGQ=
|
||||
github.com/mitchellh/mapstructure v1.4.3/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
|
||||
github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY=
|
||||
github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
|
||||
@ -367,7 +396,8 @@ github.com/redis/go-redis/v9 v9.17.2/go.mod h1:u410H11HMLoB+TP67dz8rL9s6QW2j76l0
|
||||
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
|
||||
github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc=
|
||||
github.com/rogpeppe/go-internal v1.8.0/go.mod h1:WmiCO8CzOY8rg0OYDC4/i/2WRWAB6poM+XZ2dLUbcbE=
|
||||
github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ=
|
||||
github.com/rogpeppe/go-internal v1.14.1 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0tI/otEQ=
|
||||
github.com/rogpeppe/go-internal v1.14.1/go.mod h1:MaRKkUm5W0goXpeCfT7UZI6fk/L7L7so1lCWt35ZSgc=
|
||||
github.com/rs/cors v1.8.1 h1:OrP+y5H+5Md29ACTA9imbALaKHwOSUZkcizaG0LT5ow=
|
||||
github.com/rs/cors v1.8.1/go.mod h1:XyqrcTp5zjWr1wsJ8PIRZssZ8b/WMcMf71DJnit4EMU=
|
||||
github.com/rs/cors/wrapper/gin v0.0.0-20231013084403-73f81b45a644 h1:BBwREPixt0iE77C9z7DOenoeh5OGFrzyL1cWOp5oQTs=
|
||||
@ -402,8 +432,9 @@ github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/
|
||||
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
|
||||
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
|
||||
github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
|
||||
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
|
||||
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
|
||||
github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U=
|
||||
github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U=
|
||||
github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8=
|
||||
github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU=
|
||||
github.com/swaggo/files v1.0.1 h1:J1bVJ4XHZNq0I46UU90611i9/YzdrF7x92oX1ig5IdE=
|
||||
@ -441,7 +472,26 @@ go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
|
||||
go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
|
||||
go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
|
||||
go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk=
|
||||
go.uber.org/goleak v1.2.0 h1:xqgm/S+aQvhWFTtR0XK3Jvg7z8kGV8P4X14IzwN3Eqk=
|
||||
go.opentelemetry.io/auto/sdk v1.2.1 h1:jXsnJ4Lmnqd11kwkBV2LgLoFMZKizbCi5fNZ/ipaZ64=
|
||||
go.opentelemetry.io/auto/sdk v1.2.1/go.mod h1:KRTj+aOaElaLi+wW1kO/DZRXwkF4C5xPbEe3ZiIhN7Y=
|
||||
go.opentelemetry.io/otel v1.39.0 h1:8yPrr/S0ND9QEfTfdP9V+SiwT4E0G7Y5MO7p85nis48=
|
||||
go.opentelemetry.io/otel v1.39.0/go.mod h1:kLlFTywNWrFyEdH0oj2xK0bFYZtHRYUdv1NklR/tgc8=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.39.0 h1:f0cb2XPmrqn4XMy9PNliTgRKJgS5WcL/u0/WRYGz4t0=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.39.0/go.mod h1:vnakAaFckOMiMtOIhFI2MNH4FYrZzXCYxmb1LlhoGz8=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.39.0 h1:Ckwye2FpXkYgiHX7fyVrN1uA/UYd9ounqqTuSNAv0k4=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.39.0/go.mod h1:teIFJh5pW2y+AN7riv6IBPX2DuesS3HgP39mwOspKwU=
|
||||
go.opentelemetry.io/otel/metric v1.39.0 h1:d1UzonvEZriVfpNKEVmHXbdf909uGTOQjA0HF0Ls5Q0=
|
||||
go.opentelemetry.io/otel/metric v1.39.0/go.mod h1:jrZSWL33sD7bBxg1xjrqyDjnuzTUB0x1nBERXd7Ftcs=
|
||||
go.opentelemetry.io/otel/sdk v1.39.0 h1:nMLYcjVsvdui1B/4FRkwjzoRVsMK8uL/cj0OyhKzt18=
|
||||
go.opentelemetry.io/otel/sdk v1.39.0/go.mod h1:vDojkC4/jsTJsE+kh+LXYQlbL8CgrEcwmt1ENZszdJE=
|
||||
go.opentelemetry.io/otel/sdk/metric v1.39.0 h1:cXMVVFVgsIf2YL6QkRF4Urbr/aMInf+2WKg+sEJTtB8=
|
||||
go.opentelemetry.io/otel/sdk/metric v1.39.0/go.mod h1:xq9HEVH7qeX69/JnwEfp6fVq5wosJsY1mt4lLfYdVew=
|
||||
go.opentelemetry.io/otel/trace v1.39.0 h1:2d2vfpEDmCJ5zVYz7ijaJdOF59xLomrvj7bjt6/qCJI=
|
||||
go.opentelemetry.io/otel/trace v1.39.0/go.mod h1:88w4/PnZSazkGzz/w84VHpQafiU4EtqqlVdxWy+rNOA=
|
||||
go.opentelemetry.io/proto/otlp v1.9.0 h1:l706jCMITVouPOqEnii2fIAuO3IVGBRPV5ICjceRb/A=
|
||||
go.opentelemetry.io/proto/otlp v1.9.0/go.mod h1:xE+Cx5E/eEHw+ISFkwPLwCZefwVjY+pqKg1qcK03+/4=
|
||||
go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
|
||||
go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE=
|
||||
go.uber.org/multierr v1.10.0 h1:S0h4aNzvfcFsC3dRF1jLoaov7oRaKqRGC/pUEJ2yvPQ=
|
||||
go.uber.org/multierr v1.10.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y=
|
||||
go.uber.org/zap v1.26.0 h1:sI7k6L95XOKS281NhVKOFCUNIvv9e0w4BF8N3u+tCRo=
|
||||
@ -467,8 +517,8 @@ golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDf
|
||||
golang.org/x/crypto v0.21.0/go.mod h1:0BP7YvVV9gBbVKyeTG0Gyn+gZm94bibOW5BjDEYAOMs=
|
||||
golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8=
|
||||
golang.org/x/crypto v0.24.0/go.mod h1:Z1PMYSOR5nyMcyAVAIQSKCDwalqy85Aqn1x3Ws4L5DM=
|
||||
golang.org/x/crypto v0.27.0 h1:GXm2NjJrPaiv/h1tb2UH8QfgC/hOf/+z0p6PT8o1w7A=
|
||||
golang.org/x/crypto v0.27.0/go.mod h1:1Xngt8kV6Dvbssa53Ziq6Eqn0HqbZi5Z6R0ZpwQzt70=
|
||||
golang.org/x/crypto v0.44.0 h1:A97SsFvM3AIwEEmTBiaxPPTYpDC47w720rdiiUvgoAU=
|
||||
golang.org/x/crypto v0.44.0/go.mod h1:013i+Nw79BMiQiMsOPcVCB5ZIJbYkerPrGnOa00tvmc=
|
||||
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
|
||||
@ -508,8 +558,9 @@ golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91
|
||||
golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
|
||||
golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
|
||||
golang.org/x/mod v0.15.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
|
||||
golang.org/x/mod v0.17.0 h1:zY54UmvipHiNd+pm+m0x9KhZ9hl1/7QNMyxXbc6ICqA=
|
||||
golang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
|
||||
golang.org/x/mod v0.29.0 h1:HV8lRxZC4l2cr3Zq1LvtOsi/ThTgWnUk/y64QSs8GwA=
|
||||
golang.org/x/mod v0.29.0/go.mod h1:NyhrlYXJ2H4eJiRy/WDBO6HMqZQ6q9nk4JzS3NuCK+w=
|
||||
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
@ -555,8 +606,8 @@ golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44=
|
||||
golang.org/x/net v0.23.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg=
|
||||
golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM=
|
||||
golang.org/x/net v0.26.0/go.mod h1:5YKkiSynbBIh3p6iOc/vibscux0x38BZDkn8sCUPxHE=
|
||||
golang.org/x/net v0.29.0 h1:5ORfpBpCs4HzDYoodCDBbwHzdR5UrLBZ3sOnUJmFoHo=
|
||||
golang.org/x/net v0.29.0/go.mod h1:gLkgy8jTGERgjzMic6DS9+SP0ajcu6Xu3Orq/SpETg0=
|
||||
golang.org/x/net v0.47.0 h1:Mx+4dIFzqraBXUugkia1OOvlD6LemFo1ALMHjrXDOhY=
|
||||
golang.org/x/net v0.47.0/go.mod h1:/jNxtkgq5yWUGYkaZGqo27cfGZ1c5Nen03aYrrKpVRU=
|
||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||
@ -581,8 +632,8 @@ golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y=
|
||||
golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
||||
golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
||||
golang.org/x/sync v0.8.0 h1:3NFvSEYkUoMifnESzZl15y791HH1qU2xm6eCJU5ZPXQ=
|
||||
golang.org/x/sync v0.8.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
||||
golang.org/x/sync v0.18.0 h1:kr88TuHDroi+UVf+0hZnirlk8o8T+4MrK6mr60WkH/I=
|
||||
golang.org/x/sync v0.18.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI=
|
||||
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
@ -635,8 +686,8 @@ golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/sys v0.21.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/sys v0.25.0 h1:r+8e+loiHxRqhXVl6ML1nO3l1+oFoWbnlu2Ehimmi34=
|
||||
golang.org/x/sys v0.25.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/sys v0.39.0 h1:CvCKL8MeisomCi6qNZ+wbb0DN9E5AATixKsvNtMoMFk=
|
||||
golang.org/x/sys v0.39.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
|
||||
golang.org/x/telemetry v0.0.0-20240228155512-f48c80bd79b2/go.mod h1:TeRTkGYfJXctD9OcfyVLyj2J3IxLnKwHJR8f4D8a3YE=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||
@ -663,8 +714,8 @@ golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
|
||||
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
|
||||
golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
|
||||
golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI=
|
||||
golang.org/x/text v0.18.0 h1:XvMDiNzPAl0jr17s6W9lcaIhGUfUORdGCNsuLmPG224=
|
||||
golang.org/x/text v0.18.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY=
|
||||
golang.org/x/text v0.31.0 h1:aC8ghyu4JhP8VojJ2lEHBnochRno1sgL6nEi9WGFGMM=
|
||||
golang.org/x/text v0.31.0/go.mod h1:tKRAlv61yKIjGGHX/4tP1LTbc13YSec1pxVEWXzfoeM=
|
||||
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
@ -722,12 +773,15 @@ golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0=
|
||||
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
|
||||
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
|
||||
golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58=
|
||||
golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d h1:vU5i/LfpvrRCpgM/VPfJLg5KjxD3E+hfT1SH+d9zLwg=
|
||||
golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk=
|
||||
golang.org/x/tools v0.38.0 h1:Hx2Xv8hISq8Lm16jvBZ2VQf+RLmbd7wVUsALibYI/IQ=
|
||||
golang.org/x/tools v0.38.0/go.mod h1:yEsQ/d/YK8cjh0L6rZlY8tgtlKiBNTL14pGDJPJpYQs=
|
||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
gonum.org/v1/gonum v0.16.0 h1:5+ul4Swaf3ESvrOnidPp4GZbzf0mxVQpDCYUQE7OJfk=
|
||||
gonum.org/v1/gonum v0.16.0/go.mod h1:fef3am4MQ93R2HHpKnLk4/Tbh/s0+wqD5nfa6Pnwy4E=
|
||||
google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE=
|
||||
google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M=
|
||||
google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg=
|
||||
@ -790,6 +844,10 @@ google.golang.org/genproto v0.0.0-20201210142538-e3217bee35cc/go.mod h1:FWY/as6D
|
||||
google.golang.org/genproto v0.0.0-20201214200347-8c77b98c765d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||
google.golang.org/genproto v0.0.0-20210108203827-ffc7fda8c3d7/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||
google.golang.org/genproto v0.0.0-20210226172003-ab064af71705/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20251202230838-ff82c1b0f217 h1:fCvbg86sFXwdrl5LgVcTEvNC+2txB5mgROGmRL5mrls=
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20251202230838-ff82c1b0f217/go.mod h1:+rXWjjaukWZun3mLfjmVnQi18E1AsFbDN9QdJ5YXLto=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20251202230838-ff82c1b0f217 h1:gRkg/vSppuSQoDjxyiGfN4Upv/h/DQmIR10ZU8dh4Ww=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20251202230838-ff82c1b0f217/go.mod h1:7i2o+ce6H/6BluujYR+kqX3GKH+dChPTQU19wjRPiGk=
|
||||
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
|
||||
google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38=
|
||||
google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM=
|
||||
@ -806,6 +864,8 @@ google.golang.org/grpc v1.31.1/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM
|
||||
google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc=
|
||||
google.golang.org/grpc v1.34.0/go.mod h1:WotjhfgOW/POjDeRt8vscBtXq+2VjORFy659qA51WJ8=
|
||||
google.golang.org/grpc v1.35.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU=
|
||||
google.golang.org/grpc v1.77.0 h1:wVVY6/8cGA6vvffn+wWK5ToddbgdU3d8MNENr4evgXM=
|
||||
google.golang.org/grpc v1.77.0/go.mod h1:z0BY1iVj0q8E1uSQCjL9cppRj+gnZjzDnzV0dHhrNig=
|
||||
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
|
||||
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
|
||||
google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
|
||||
@ -817,10 +877,9 @@ google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpAD
|
||||
google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4=
|
||||
google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c=
|
||||
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
|
||||
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
|
||||
google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
|
||||
google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8=
|
||||
google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
|
||||
google.golang.org/protobuf v1.36.10 h1:AYd7cD/uASjIL6Q9LiTjz8JLcrh/88q5UObnmY3aOOE=
|
||||
google.golang.org/protobuf v1.36.10/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
@ -848,10 +907,12 @@ gorm.io/driver/mysql v1.4.3/go.mod h1:sSIebwZAVPiT+27jK9HIwvsqOGKx3YMPmrA3mBJR10
|
||||
gorm.io/driver/mysql v1.5.2 h1:QC2HRskSE75wBuOxe0+iCkyJZ+RqpudsQtqkp+IMuXs=
|
||||
gorm.io/driver/mysql v1.5.2/go.mod h1:pQLhh1Ut/WUAySdTHwBpBv6+JKcj+ua4ZFx1QQTBzb8=
|
||||
gorm.io/driver/postgres v1.4.5 h1:mTeXTTtHAgnS9PgmhN2YeUbazYpLhUI1doLnw42XUZc=
|
||||
gorm.io/driver/postgres v1.4.5/go.mod h1:GKNQYSJ14qvWkvPwXljMGehpKrhlDNsqYRr5HnYGncg=
|
||||
gorm.io/driver/sqlite v1.1.6/go.mod h1:W8LmC/6UvVbHKah0+QOC7Ja66EaZXHwUTjgXY8YNWX8=
|
||||
gorm.io/driver/sqlite v1.4.3 h1:HBBcZSDnWi5BW3B3rwvVTc510KGkBkexlOg0QrmLUuU=
|
||||
gorm.io/driver/sqlite v1.4.3/go.mod h1:0Aq3iPO+v9ZKbcdiz8gLWRw5VOPcBOPUQJFLq5e2ecI=
|
||||
gorm.io/driver/sqlserver v1.4.1 h1:t4r4r6Jam5E6ejqP7N82qAJIJAht27EGT41HyPfXRw0=
|
||||
gorm.io/driver/sqlserver v1.4.1/go.mod h1:DJ4P+MeZbc5rvY58PnmN1Lnyvb5gw5NPzGshHDnJLig=
|
||||
gorm.io/gen v0.3.26 h1:sFf1j7vNStimPRRAtH4zz5NiHM+1dr6eA9aaRdplyhY=
|
||||
gorm.io/gen v0.3.26/go.mod h1:a5lq5y3w4g5LMxBcw0wnO6tYUCdNutWODq5LrIt75LE=
|
||||
gorm.io/gorm v1.21.15/go.mod h1:F+OptMscr0P2F2qU97WT1WimdH9GaQPoDW7AYd5i2Y0=
|
||||
|
||||
@ -64,6 +64,10 @@ func (h *handler) JoinLottery() core.HandlerFunc {
|
||||
ctx.AbortWithError(core.Error(http.StatusBadRequest, code.ParamBindError, validation.Error(err)))
|
||||
return
|
||||
}
|
||||
// DEBUG LOG: Print request params to diagnose frontend issue
|
||||
reqBytes, _ := json.Marshal(req)
|
||||
h.logger.Info(fmt.Sprintf("JoinLottery Request Params: UserID=%d Payload=%s", ctx.SessionUserInfo().Id, string(reqBytes)))
|
||||
|
||||
userID := int64(ctx.SessionUserInfo().Id)
|
||||
h.logger.Info(fmt.Sprintf("JoinLottery Start: UserID=%d ActivityID=%d IssueID=%d", userID, req.ActivityID, req.IssueID))
|
||||
activity, err := h.activity.GetActivity(ctx.RequestContext(), req.ActivityID)
|
||||
@ -263,6 +267,13 @@ func (h *handler) JoinLottery() core.HandlerFunc {
|
||||
return err
|
||||
}
|
||||
deducted += canDeduct
|
||||
|
||||
// Record usage for remark (Format: gp_use:ID:Count)
|
||||
if order.Remark == "" {
|
||||
order.Remark = fmt.Sprintf("gp_use:%d:%d", p.ID, canDeduct)
|
||||
} else {
|
||||
order.Remark += fmt.Sprintf("|gp_use:%d:%d", p.ID, canDeduct)
|
||||
}
|
||||
}
|
||||
|
||||
if deducted < count {
|
||||
@ -273,15 +284,8 @@ func (h *handler) JoinLottery() core.HandlerFunc {
|
||||
order.ActualAmount = 0
|
||||
order.SourceType = 4 // Cleanly mark as Game Pass source
|
||||
|
||||
// existing lottery logic sets SourceType based on "h.orderModel" which defaults to something?
|
||||
// h.orderModel(..., c) implementation needs to be checked or inferred.
|
||||
// Assuming orderModel sets SourceType based on activity or defaults.
|
||||
// Let's explicitly mark it or rely on Remark.
|
||||
if order.Remark == "" {
|
||||
order.Remark = "use_game_pass"
|
||||
} else {
|
||||
order.Remark += "|use_game_pass"
|
||||
}
|
||||
// Legacy marker for backward compatibility or simple check
|
||||
order.Remark += "|use_game_pass"
|
||||
// Note: If we change SourceType to 4, ProcessOrderLottery might skip it if checks SourceType.
|
||||
// Lottery app usually expects SourceType=2 or similar.
|
||||
// Let's KEEP SourceType as is (likely 2 for ichiban), but Amount=0 ensures it's treated as Paid.
|
||||
@ -289,24 +293,21 @@ func (h *handler) JoinLottery() core.HandlerFunc {
|
||||
|
||||
if !useGamePass && req.UsePoints != nil && *req.UsePoints > 0 {
|
||||
bal, _ := h.user.GetPointsBalance(ctx.RequestContext(), userID)
|
||||
usePts := *req.UsePoints
|
||||
if bal > 0 && usePts > bal {
|
||||
usePts = bal
|
||||
// req.UsePoints 是前端传入的积分数,需要转换为分
|
||||
usePtsCents, _ := h.user.PointsToCents(ctx.RequestContext(), *req.UsePoints)
|
||||
// bal 已经是分单位
|
||||
if bal > 0 && usePtsCents > bal {
|
||||
usePtsCents = bal
|
||||
}
|
||||
ratePtsPerCent, _ := h.user.CentsToPoints(ctx.RequestContext(), 1)
|
||||
if ratePtsPerCent <= 0 {
|
||||
ratePtsPerCent = 1
|
||||
}
|
||||
deductCents := usePts / ratePtsPerCent
|
||||
// deductCents 是要从订单金额中抵扣的分数
|
||||
deductCents := usePtsCents
|
||||
if deductCents > order.ActualAmount {
|
||||
deductCents = order.ActualAmount
|
||||
}
|
||||
|
||||
if deductCents > 0 {
|
||||
needPts := deductCents * ratePtsPerCent
|
||||
if needPts > usePts {
|
||||
needPts = usePts
|
||||
}
|
||||
// needPts 是实际需要扣除的分数
|
||||
needPts := deductCents
|
||||
// Inline ConsumePointsFor logic using tx
|
||||
// Lock rows
|
||||
rows, errFind := tx.UserPoints.WithContext(ctx.RequestContext()).Clauses(clause.Locking{Strength: "UPDATE"}).Where(tx.UserPoints.UserID.Eq(userID)).Order(tx.UserPoints.ValidEnd.Asc()).Find()
|
||||
@ -618,32 +619,34 @@ func (h *handler) validateIchibanSlots(ctx core.Context, req *joinLotteryRequest
|
||||
if totalSlots <= 0 {
|
||||
return core.Error(http.StatusBadRequest, 170008, "no slots")
|
||||
}
|
||||
if len(req.SlotIndex) > 0 {
|
||||
if req.Count <= 0 || req.Count != int64(len(req.SlotIndex)) {
|
||||
return core.Error(http.StatusBadRequest, code.ParamBindError, "参数错误")
|
||||
}
|
||||
// 1. 强制校验:必须选择位置
|
||||
if len(req.SlotIndex) == 0 {
|
||||
return core.Error(http.StatusBadRequest, code.ParamBindError, "一番赏必须选择位置")
|
||||
}
|
||||
if req.Count <= 0 || req.Count != int64(len(req.SlotIndex)) {
|
||||
return core.Error(http.StatusBadRequest, code.ParamBindError, "参数错误:数量与位置不匹配")
|
||||
}
|
||||
|
||||
// 1. 内存中去重和范围检查
|
||||
selectedSlots := make([]int64, 0, len(req.SlotIndex))
|
||||
seen := make(map[int64]struct{}, len(req.SlotIndex))
|
||||
for _, si := range req.SlotIndex {
|
||||
if _, ok := seen[si]; ok {
|
||||
return core.Error(http.StatusBadRequest, 170011, "duplicate slots not allowed")
|
||||
}
|
||||
seen[si] = struct{}{}
|
||||
if si < 1 || si > totalSlots {
|
||||
return core.Error(http.StatusBadRequest, 170008, "slot out of range")
|
||||
}
|
||||
selectedSlots = append(selectedSlots, si-1)
|
||||
// 2. 内存中去重和范围检查
|
||||
selectedSlots := make([]int64, 0, len(req.SlotIndex))
|
||||
seen := make(map[int64]struct{}, len(req.SlotIndex))
|
||||
for _, si := range req.SlotIndex {
|
||||
if _, ok := seen[si]; ok {
|
||||
return core.Error(http.StatusBadRequest, 170011, "duplicate slots not allowed")
|
||||
}
|
||||
seen[si] = struct{}{}
|
||||
if si < 1 || si > totalSlots {
|
||||
return core.Error(http.StatusBadRequest, 170008, "slot out of range")
|
||||
}
|
||||
selectedSlots = append(selectedSlots, si-1)
|
||||
}
|
||||
|
||||
// 2. 批量查询数据库检查格位是否已被占用
|
||||
var occupiedCount int64
|
||||
_ = h.repo.GetDbR().Raw("SELECT COUNT(*) FROM issue_position_claims WHERE issue_id=? AND slot_index IN ?", req.IssueID, selectedSlots).Scan(&occupiedCount).Error
|
||||
if occupiedCount > 0 {
|
||||
// 如果有占用,为了告知具体是哪个位置,可以打个 log 或者简单的直接返回错误
|
||||
return core.Error(http.StatusBadRequest, 170007, "部分位置已被占用,请刷新重试")
|
||||
}
|
||||
// 3. 批量查询数据库检查格位是否已被占用
|
||||
var occupiedCount int64
|
||||
_ = h.repo.GetDbR().Raw("SELECT COUNT(*) FROM issue_position_claims WHERE issue_id=? AND slot_index IN ?", req.IssueID, selectedSlots).Scan(&occupiedCount).Error
|
||||
if occupiedCount > 0 {
|
||||
// 即使是并发场景,这里做一个 Pre-check 也能拦截大部分冲突
|
||||
return core.Error(http.StatusBadRequest, 170007, "部分位置已被占用,请刷新重试")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@ -30,6 +30,7 @@ type matchingGamePreOrderRequest struct {
|
||||
CouponID *int64 `json:"coupon_id"`
|
||||
ItemCardID *int64 `json:"item_card_id"`
|
||||
UseGamePass bool `json:"use_game_pass"` // 新增:是否使用次数卡
|
||||
Count int64 `json:"count"` // 新增:购买数量
|
||||
}
|
||||
|
||||
type matchingGamePreOrderResponse struct {
|
||||
@ -82,6 +83,12 @@ func (h *handler) PreOrderMatchingGame() core.HandlerFunc {
|
||||
return
|
||||
}
|
||||
|
||||
// 校验 Count:对对碰只能单次购买
|
||||
if req.Count > 1 {
|
||||
ctx.AbortWithError(core.Error(http.StatusBadRequest, 170013, "对对碰游戏暂不支持批量购买,请单次支付"))
|
||||
return
|
||||
}
|
||||
|
||||
// 1. Get Activity/Issue Info (Mocking price for now or fetching if available)
|
||||
// Assuming price is fixed or fetched. Let's fetch basic activity info if possible, or assume config.
|
||||
// Since Request has IssueID, let's fetch Issue to get ActivityID and Price.
|
||||
|
||||
413
internal/api/admin/dashboard_activity.go
Normal file
413
internal/api/admin/dashboard_activity.go
Normal file
@ -0,0 +1,413 @@
|
||||
package admin
|
||||
|
||||
import (
|
||||
"bindbox-game/internal/code"
|
||||
"bindbox-game/internal/pkg/core"
|
||||
"bindbox-game/internal/pkg/validation"
|
||||
"bindbox-game/internal/repository/mysql/model"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"strconv"
|
||||
"time"
|
||||
)
|
||||
|
||||
type activityProfitLossRequest struct {
|
||||
Page int `form:"page"`
|
||||
PageSize int `form:"page_size"`
|
||||
Name string `form:"name"`
|
||||
Status int32 `form:"status"` // 1进行中 2下线
|
||||
}
|
||||
|
||||
type activityProfitLossItem struct {
|
||||
ActivityID int64 `json:"activity_id"`
|
||||
ActivityName string `json:"activity_name"`
|
||||
Status int32 `json:"status"`
|
||||
DrawCount int64 `json:"draw_count"`
|
||||
PlayerCount int64 `json:"player_count"`
|
||||
TotalRevenue int64 `json:"total_revenue"` // 实际支付金额 (分)
|
||||
TotalCost int64 `json:"total_cost"` // 奖品标价总和 (分)
|
||||
Profit int64 `json:"profit"` // Revenue - Cost
|
||||
ProfitRate float64 `json:"profit_rate"` // Profit / Revenue
|
||||
}
|
||||
|
||||
type activityProfitLossResponse struct {
|
||||
Page int `json:"page"`
|
||||
PageSize int `json:"page_size"`
|
||||
Total int64 `json:"total"`
|
||||
List []activityProfitLossItem `json:"list"`
|
||||
}
|
||||
|
||||
func (h *handler) DashboardActivityProfitLoss() core.HandlerFunc {
|
||||
return func(ctx core.Context) {
|
||||
req := new(activityProfitLossRequest)
|
||||
if err := ctx.ShouldBindForm(req); err != nil {
|
||||
ctx.AbortWithError(core.Error(http.StatusBadRequest, code.ParamBindError, validation.Error(err)))
|
||||
return
|
||||
}
|
||||
if req.Page <= 0 {
|
||||
req.Page = 1
|
||||
}
|
||||
if req.PageSize <= 0 {
|
||||
req.PageSize = 20
|
||||
}
|
||||
|
||||
db := h.repo.GetDbR().WithContext(ctx.RequestContext())
|
||||
|
||||
// 1. 获取活动列表基础信息
|
||||
var activities []model.Activities
|
||||
query := db.Table(model.TableNameActivities)
|
||||
if req.Name != "" {
|
||||
query = query.Where("name LIKE ?", "%"+req.Name+"%")
|
||||
}
|
||||
if req.Status > 0 {
|
||||
query = query.Where("status = ?", req.Status)
|
||||
}
|
||||
|
||||
var total int64
|
||||
query.Count(&total)
|
||||
|
||||
if err := query.Offset((req.Page - 1) * req.PageSize).Limit(req.PageSize).Order("id DESC").Find(&activities).Error; err != nil {
|
||||
h.logger.Error(fmt.Sprintf("GetActivityProfitLoss activities error: %v", err))
|
||||
ctx.AbortWithError(core.Error(http.StatusInternalServerError, 21021, err.Error()))
|
||||
return
|
||||
}
|
||||
|
||||
if len(activities) == 0 {
|
||||
ctx.Payload(&activityProfitLossResponse{
|
||||
Page: req.Page,
|
||||
PageSize: req.PageSize,
|
||||
Total: total,
|
||||
List: []activityProfitLossItem{},
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
activityIDs := make([]int64, len(activities))
|
||||
activityMap := make(map[int64]*activityProfitLossItem)
|
||||
for i, a := range activities {
|
||||
activityIDs[i] = a.ID
|
||||
activityMap[a.ID] = &activityProfitLossItem{
|
||||
ActivityID: a.ID,
|
||||
ActivityName: a.Name,
|
||||
Status: a.Status,
|
||||
}
|
||||
}
|
||||
|
||||
// 2. 统计抽奖次数和人数 (通过 activity_draw_logs 关联 activity_issues)
|
||||
type drawStat struct {
|
||||
ActivityID int64
|
||||
DrawCount int64
|
||||
PlayerCount int64
|
||||
}
|
||||
var drawStats []drawStat
|
||||
db.Table(model.TableNameActivityDrawLogs).
|
||||
Select("activity_issues.activity_id, COUNT(activity_draw_logs.id) as draw_count, COUNT(DISTINCT activity_draw_logs.user_id) as player_count").
|
||||
Joins("JOIN activity_issues ON activity_issues.id = activity_draw_logs.issue_id").
|
||||
Where("activity_issues.activity_id IN ?", activityIDs).
|
||||
Group("activity_issues.activity_id").
|
||||
Scan(&drawStats)
|
||||
|
||||
for _, s := range drawStats {
|
||||
if item, ok := activityMap[s.ActivityID]; ok {
|
||||
item.DrawCount = s.DrawCount
|
||||
item.PlayerCount = s.PlayerCount
|
||||
}
|
||||
}
|
||||
|
||||
// 3. 统计营收 (通过 orders 关联 activity_draw_logs)
|
||||
type revenueStat struct {
|
||||
ActivityID int64
|
||||
TotalRevenue int64
|
||||
}
|
||||
var revenueStats []revenueStat
|
||||
|
||||
// 修正: 先找到每个订单对应的一个 activity_id (去重),再关联 orders 统计 actual_amount。
|
||||
// 避免一个订单包含多个 draw logs 时导致 orders.actual_amount 被重复累加。
|
||||
// 子查询: SELECT order_id, MAX(issue_id) as issue_id FROM activity_draw_logs GROUP BY order_id
|
||||
// 然后通过 issue_id 关联 activity_issues 找到 activity_id
|
||||
var err error
|
||||
err = db.Table(model.TableNameOrders).
|
||||
Select("activity_issues.activity_id, SUM(orders.actual_amount) as total_revenue").
|
||||
Joins("JOIN (SELECT order_id, MAX(issue_id) as issue_id FROM activity_draw_logs GROUP BY order_id) dl ON dl.order_id = orders.id").
|
||||
Joins("JOIN activity_issues ON activity_issues.id = dl.issue_id").
|
||||
Where("orders.status = ?", 2). // 已支付
|
||||
Where("activity_issues.activity_id IN ?", activityIDs).
|
||||
Group("activity_issues.activity_id").
|
||||
Scan(&revenueStats).Error
|
||||
|
||||
if err != nil {
|
||||
h.logger.Error(fmt.Sprintf("GetActivityProfitLoss revenue stats error: %v", err))
|
||||
}
|
||||
|
||||
for _, s := range revenueStats {
|
||||
if item, ok := activityMap[s.ActivityID]; ok {
|
||||
item.TotalRevenue = s.TotalRevenue
|
||||
}
|
||||
}
|
||||
|
||||
// 4. 统计成本 (通过 user_inventory 关联 products)
|
||||
type costStat struct {
|
||||
ActivityID int64
|
||||
TotalCost int64
|
||||
}
|
||||
var costStats []costStat
|
||||
db.Table(model.TableNameUserInventory).
|
||||
Select("user_inventory.activity_id, SUM(products.price) as total_cost").
|
||||
Joins("JOIN products ON products.id = user_inventory.product_id").
|
||||
Where("user_inventory.activity_id IN ?", activityIDs).
|
||||
Group("user_inventory.activity_id").
|
||||
Scan(&costStats)
|
||||
|
||||
for _, s := range costStats {
|
||||
if item, ok := activityMap[s.ActivityID]; ok {
|
||||
item.TotalCost = s.TotalCost
|
||||
}
|
||||
}
|
||||
|
||||
// 5. 计算盈亏和比率
|
||||
finalList := make([]activityProfitLossItem, 0, len(activities))
|
||||
for _, a := range activities {
|
||||
item := activityMap[a.ID]
|
||||
item.Profit = item.TotalRevenue - item.TotalCost
|
||||
if item.TotalRevenue > 0 {
|
||||
item.ProfitRate = float64(item.Profit) / float64(item.TotalRevenue)
|
||||
}
|
||||
finalList = append(finalList, *item)
|
||||
}
|
||||
|
||||
ctx.Payload(&activityProfitLossResponse{
|
||||
Page: req.Page,
|
||||
PageSize: req.PageSize,
|
||||
Total: total,
|
||||
List: finalList,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
type activityLogsRequest struct {
|
||||
Page int `form:"page"`
|
||||
PageSize int `form:"page_size"`
|
||||
}
|
||||
|
||||
type activityLogItem struct {
|
||||
ID int64 `json:"id"`
|
||||
UserID int64 `json:"user_id"`
|
||||
Nickname string `json:"nickname"`
|
||||
Avatar string `json:"avatar"`
|
||||
ProductID int64 `json:"product_id"`
|
||||
ProductName string `json:"product_name"`
|
||||
ProductImage string `json:"product_image"`
|
||||
ProductPrice int64 `json:"product_price"`
|
||||
OrderAmount int64 `json:"order_amount"`
|
||||
DiscountAmount int64 `json:"discount_amount"` // New: 优惠金额
|
||||
PayType string `json:"pay_type"` // New: 支付方式/类型 (现金/道具卡/次数卡)
|
||||
UsedCard string `json:"used_card"` // New: 使用的卡券名称
|
||||
Profit int64 `json:"profit"`
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
}
|
||||
|
||||
type activityLogsResponse struct {
|
||||
Page int `json:"page"`
|
||||
PageSize int `json:"page_size"`
|
||||
Total int64 `json:"total"`
|
||||
List []activityLogItem `json:"list"`
|
||||
}
|
||||
|
||||
func (h *handler) DashboardActivityLogs() core.HandlerFunc {
|
||||
return func(ctx core.Context) {
|
||||
activityID, _ := strconv.ParseInt(ctx.Param("activity_id"), 10, 64)
|
||||
if activityID <= 0 {
|
||||
ctx.AbortWithError(core.Error(http.StatusBadRequest, code.ParamBindError, "Invalid activity ID"))
|
||||
return
|
||||
}
|
||||
|
||||
req := new(activityLogsRequest)
|
||||
if err := ctx.ShouldBindForm(req); err != nil {
|
||||
ctx.AbortWithError(core.Error(http.StatusBadRequest, code.ParamBindError, validation.Error(err)))
|
||||
return
|
||||
}
|
||||
if req.Page <= 0 {
|
||||
req.Page = 1
|
||||
}
|
||||
if req.PageSize <= 0 {
|
||||
req.PageSize = 20
|
||||
}
|
||||
|
||||
db := h.repo.GetDbR().WithContext(ctx.RequestContext())
|
||||
|
||||
var total int64
|
||||
db.Table(model.TableNameActivityDrawLogs).
|
||||
Joins("JOIN activity_issues ON activity_issues.id = activity_draw_logs.issue_id").
|
||||
Where("activity_issues.activity_id = ?", activityID).
|
||||
Count(&total)
|
||||
|
||||
var logs []struct {
|
||||
ID int64
|
||||
UserID int64
|
||||
Nickname string
|
||||
Avatar string
|
||||
ProductID int64
|
||||
ProductName string
|
||||
ImagesJSON string
|
||||
ProductPrice int64
|
||||
OrderAmount int64
|
||||
DiscountAmount int64
|
||||
SourceType int32
|
||||
CouponName string
|
||||
ItemCardName string
|
||||
CreatedAt time.Time
|
||||
}
|
||||
|
||||
err := db.Table(model.TableNameActivityDrawLogs).
|
||||
Select(`
|
||||
activity_draw_logs.id,
|
||||
activity_draw_logs.user_id,
|
||||
COALESCE(users.nickname, '') as nickname,
|
||||
COALESCE(users.avatar, '') as avatar,
|
||||
activity_reward_settings.product_id,
|
||||
COALESCE(products.name, '') as product_name,
|
||||
COALESCE(products.images_json, '[]') as images_json,
|
||||
COALESCE(products.price, 0) as product_price,
|
||||
COALESCE(orders.actual_amount, 0) as order_amount,
|
||||
COALESCE(orders.discount_amount, 0) as discount_amount,
|
||||
orders.source_type,
|
||||
COALESCE(system_coupons.name, '') as coupon_name,
|
||||
COALESCE(system_item_cards.name, '') as item_card_name,
|
||||
activity_draw_logs.created_at
|
||||
`).
|
||||
Joins("JOIN activity_issues ON activity_issues.id = activity_draw_logs.issue_id").
|
||||
Joins("LEFT JOIN users ON users.id = activity_draw_logs.user_id").
|
||||
Joins("LEFT JOIN activity_reward_settings ON activity_reward_settings.id = activity_draw_logs.reward_id").
|
||||
Joins("LEFT JOIN products ON products.id = activity_reward_settings.product_id").
|
||||
Joins("LEFT JOIN orders ON orders.id = activity_draw_logs.order_id").
|
||||
Joins("LEFT JOIN system_coupons ON system_coupons.id = orders.coupon_id").
|
||||
Joins("LEFT JOIN system_item_cards ON system_item_cards.id = orders.item_card_id").
|
||||
Where("activity_issues.activity_id = ?", activityID).
|
||||
Order("activity_draw_logs.id DESC").
|
||||
Offset((req.Page - 1) * req.PageSize).
|
||||
Limit(req.PageSize).
|
||||
Scan(&logs).Error
|
||||
|
||||
if err != nil {
|
||||
h.logger.Error(fmt.Sprintf("GetActivityLogs error: %v", err))
|
||||
ctx.AbortWithError(core.Error(http.StatusInternalServerError, 21022, err.Error()))
|
||||
return
|
||||
}
|
||||
|
||||
list := make([]activityLogItem, len(logs))
|
||||
for i, l := range logs {
|
||||
var images []string
|
||||
_ = json.Unmarshal([]byte(l.ImagesJSON), &images)
|
||||
productImage := ""
|
||||
if len(images) > 0 {
|
||||
productImage = images[0]
|
||||
}
|
||||
|
||||
// Determine PayType and UsedCard
|
||||
payType := "现金支付"
|
||||
usedCard := ""
|
||||
|
||||
if l.SourceType == 2 { // Order SourceType 2 = Ticket/Count Card
|
||||
payType = "次数卡"
|
||||
}
|
||||
|
||||
if l.ItemCardName != "" {
|
||||
usedCard = l.ItemCardName
|
||||
if payType == "现金支付" {
|
||||
payType = "道具卡" // Override if item card is explicitly present
|
||||
}
|
||||
} else if l.CouponName != "" {
|
||||
usedCard = l.CouponName
|
||||
payType = "优惠券"
|
||||
}
|
||||
|
||||
list[i] = activityLogItem{
|
||||
ID: l.ID,
|
||||
UserID: l.UserID,
|
||||
Nickname: l.Nickname,
|
||||
Avatar: l.Avatar,
|
||||
ProductID: l.ProductID,
|
||||
ProductName: l.ProductName,
|
||||
ProductImage: productImage,
|
||||
ProductPrice: l.ProductPrice,
|
||||
OrderAmount: l.OrderAmount,
|
||||
DiscountAmount: l.DiscountAmount,
|
||||
PayType: payType,
|
||||
UsedCard: usedCard,
|
||||
Profit: l.OrderAmount - l.ProductPrice,
|
||||
CreatedAt: l.CreatedAt,
|
||||
}
|
||||
}
|
||||
|
||||
ctx.Payload(&activityLogsResponse{
|
||||
Page: req.Page,
|
||||
PageSize: req.PageSize,
|
||||
Total: total,
|
||||
List: list,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
type ensureActivityProfitLossMenuResponse struct {
|
||||
Ensured bool `json:"ensured"`
|
||||
Parent int64 `json:"parent_id"`
|
||||
MenuID int64 `json:"menu_id"`
|
||||
}
|
||||
|
||||
// EnsureActivityProfitLossMenu 确保运营分析下存在“活动盈亏”菜单
|
||||
func (h *handler) EnsureActivityProfitLossMenu() core.HandlerFunc {
|
||||
return func(ctx core.Context) {
|
||||
// 1. 查找是否存在“控制台”或者“运营中心”类的父菜单
|
||||
// 很多系统会将概览放在 Dashboard 下。根据 titles_seed.go,运营是 Operations。
|
||||
parent, _ := h.readDB.Menus.WithContext(ctx.RequestContext()).Where(h.readDB.Menus.Name.Eq("Operations")).First()
|
||||
var parentID int64
|
||||
if parent == nil {
|
||||
// 如果没有 Operations,尝试查找 Dashboard
|
||||
parent, _ = h.readDB.Menus.WithContext(ctx.RequestContext()).Where(h.readDB.Menus.Name.Eq("Dashboard")).First()
|
||||
}
|
||||
|
||||
if parent != nil {
|
||||
parentID = parent.ID
|
||||
}
|
||||
|
||||
// 2. 查找活动盈亏菜单
|
||||
// 路径指向控制台并带上查参数
|
||||
menuPath := "/dashboard/console?tab=activity-profit"
|
||||
exists, _ := h.readDB.Menus.WithContext(ctx.RequestContext()).Where(h.readDB.Menus.Path.Eq(menuPath)).First()
|
||||
if exists != nil {
|
||||
ctx.Payload(&ensureActivityProfitLossMenuResponse{Ensured: true, Parent: parentID, MenuID: exists.ID})
|
||||
return
|
||||
}
|
||||
|
||||
// 3. 创建菜单
|
||||
newMenu := &model.Menus{
|
||||
ParentID: parentID,
|
||||
Path: menuPath,
|
||||
Name: "活动盈亏",
|
||||
Component: "/dashboard/console/index",
|
||||
Icon: "ri:pie-chart-2-fill",
|
||||
Sort: 60, // 排序在称号之后
|
||||
Status: true,
|
||||
KeepAlive: true,
|
||||
IsHide: false,
|
||||
IsHideTab: false,
|
||||
CreatedUser: "system",
|
||||
UpdatedUser: "system",
|
||||
}
|
||||
|
||||
if err := h.writeDB.Menus.WithContext(ctx.RequestContext()).Create(newMenu); err != nil {
|
||||
ctx.AbortWithError(core.Error(http.StatusInternalServerError, 21023, "创建菜单失败: "+err.Error()))
|
||||
return
|
||||
}
|
||||
|
||||
// 读取新创建的 ID
|
||||
created, _ := h.readDB.Menus.WithContext(ctx.RequestContext()).Where(h.readDB.Menus.Path.Eq(menuPath)).First()
|
||||
menuID := int64(0)
|
||||
if created != nil {
|
||||
menuID = created.ID
|
||||
}
|
||||
|
||||
ctx.Payload(&ensureActivityProfitLossMenuResponse{Ensured: true, Parent: parentID, MenuID: menuID})
|
||||
}
|
||||
}
|
||||
@ -163,7 +163,7 @@ func (h *handler) DashboardCards() core.HandlerFunc {
|
||||
rsp.ItemCardSales = icCur
|
||||
rsp.DrawCount = dlCur
|
||||
rsp.NewUsers = nuCur
|
||||
rsp.TotalPoints = tpCur
|
||||
rsp.TotalPoints = int64(h.userSvc.CentsToPointsFloat(ctx.RequestContext(), tpCur))
|
||||
rsp.TotalCoupons = tcCur
|
||||
rsp.TotalItemCards = ticCur
|
||||
rsp.TotalGamePasses = tgpCur
|
||||
@ -1695,10 +1695,17 @@ func (h *handler) OperationsPointsEconomySummary() core.HandlerFunc {
|
||||
conversionRate = float64(activeUsers) / float64(totalUsers) * 100
|
||||
}
|
||||
|
||||
// Convert from Store Units (Cents) to Display Units (Points)
|
||||
// Assuming 100 StoreUnits = 1 Point (if Rate=1)
|
||||
// Because Store is Cents. 1 Point = 1 Yuan = 100 Cents.
|
||||
issuedPoints := h.userSvc.CentsToPointsFloat(ctx.RequestContext(), issued)
|
||||
consumedPoints := h.userSvc.CentsToPointsFloat(ctx.RequestContext(), consumed)
|
||||
netChangePoints := issuedPoints - consumedPoints
|
||||
|
||||
ctx.Payload(pointsEconomySummaryResponse{
|
||||
TotalIssued: issued,
|
||||
TotalConsumed: consumed,
|
||||
NetChange: issued - consumed,
|
||||
TotalIssued: int64(issuedPoints),
|
||||
TotalConsumed: int64(consumedPoints),
|
||||
NetChange: int64(netChangePoints),
|
||||
ActiveUsersWithPoints: activeUsers,
|
||||
ConversionRate: float64(int(conversionRate*10)) / 10.0,
|
||||
})
|
||||
@ -1757,11 +1764,11 @@ func (h *handler) OperationsPointsTrend() core.HandlerFunc {
|
||||
|
||||
out[i] = pointsTrendItem{
|
||||
Date: b.Label,
|
||||
Issued: issued,
|
||||
Consumed: consumed,
|
||||
Issued: int64(h.userSvc.CentsToPointsFloat(ctx.RequestContext(), issued)),
|
||||
Consumed: int64(h.userSvc.CentsToPointsFloat(ctx.RequestContext(), consumed)),
|
||||
Expired: 0,
|
||||
NetChange: netChange,
|
||||
Balance: runningBalance,
|
||||
NetChange: int64(h.userSvc.CentsToPointsFloat(ctx.RequestContext(), netChange)),
|
||||
Balance: int64(h.userSvc.CentsToPointsFloat(ctx.RequestContext(), runningBalance)),
|
||||
}
|
||||
}
|
||||
|
||||
@ -1834,7 +1841,7 @@ func (h *handler) OperationsPointsStructure() core.HandlerFunc {
|
||||
}
|
||||
out = append(out, pointsStructureItem{
|
||||
Category: name,
|
||||
Amount: r.Total,
|
||||
Amount: int64(h.userSvc.CentsToPointsFloat(ctx.RequestContext(), r.Total)),
|
||||
Percentage: float64(int(pct*10)) / 10.0,
|
||||
Trend: "+0%",
|
||||
})
|
||||
|
||||
256
internal/api/admin/dashboard_spending.go
Normal file
256
internal/api/admin/dashboard_spending.go
Normal file
@ -0,0 +1,256 @@
|
||||
package admin
|
||||
|
||||
import (
|
||||
"bindbox-game/internal/code"
|
||||
"bindbox-game/internal/pkg/core"
|
||||
"bindbox-game/internal/pkg/validation"
|
||||
"bindbox-game/internal/repository/mysql/model"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"sort"
|
||||
"time"
|
||||
)
|
||||
|
||||
type spendingLeaderboardRequest struct {
|
||||
Page int `form:"page"`
|
||||
PageSize int `form:"page_size"`
|
||||
RangeType string `form:"rangeType"` // today, 7d, 30d, custom
|
||||
StartDate string `form:"start"`
|
||||
EndDate string `form:"end"`
|
||||
SortBy string `form:"sort_by"` // spending, profit
|
||||
}
|
||||
|
||||
type spendingLeaderboardItem struct {
|
||||
UserID int64 `json:"user_id"`
|
||||
Nickname string `json:"nickname"`
|
||||
Avatar string `json:"avatar"`
|
||||
OrderCount int64 `json:"order_count"`
|
||||
TotalSpending int64 `json:"total_spending"` // Total Paid Amount (Fen)
|
||||
TotalPrizeValue int64 `json:"total_prize_value"` // Total Product Price (Fen)
|
||||
TotalDiscount int64 `json:"total_discount"` // Total Coupon Discount (Fen)
|
||||
TotalPoints int64 `json:"total_points"` // Total Points Discount (Fen)
|
||||
GamePassCount int64 `json:"game_pass_count"` // Count of SourceType=4
|
||||
ItemCardCount int64 `json:"item_card_count"` // Count where ItemCardID > 0
|
||||
// Breakdown by game type
|
||||
IchibanSpending int64 `json:"ichiban_spending"`
|
||||
IchibanPrize int64 `json:"ichiban_prize"`
|
||||
IchibanCount int64 `json:"ichiban_count"`
|
||||
InfiniteSpending int64 `json:"infinite_spending"`
|
||||
InfinitePrize int64 `json:"infinite_prize"`
|
||||
InfiniteCount int64 `json:"infinite_count"`
|
||||
MatchingSpending int64 `json:"matching_spending"`
|
||||
MatchingPrize int64 `json:"matching_prize"`
|
||||
MatchingCount int64 `json:"matching_count"`
|
||||
|
||||
Profit int64 `json:"profit"` // Spending - PrizeValue
|
||||
ProfitRate float64 `json:"profit_rate"` // Profit / Spending
|
||||
}
|
||||
|
||||
type spendingLeaderboardResponse struct {
|
||||
Page int `json:"page"`
|
||||
PageSize int `json:"page_size"`
|
||||
Total int64 `json:"total"`
|
||||
List []spendingLeaderboardItem `json:"list"`
|
||||
}
|
||||
|
||||
func (h *handler) DashboardPlayerSpendingLeaderboard() core.HandlerFunc {
|
||||
return func(ctx core.Context) {
|
||||
req := new(spendingLeaderboardRequest)
|
||||
if err := ctx.ShouldBindForm(req); err != nil {
|
||||
ctx.AbortWithError(core.Error(http.StatusBadRequest, code.ParamBindError, validation.Error(err)))
|
||||
return
|
||||
}
|
||||
if req.Page <= 0 {
|
||||
req.Page = 1
|
||||
}
|
||||
if req.PageSize <= 0 {
|
||||
req.PageSize = 20
|
||||
}
|
||||
|
||||
var start, end time.Time
|
||||
if req.RangeType != "all" {
|
||||
start, end = parseRange(req.RangeType, req.StartDate, req.EndDate)
|
||||
h.logger.Info(fmt.Sprintf("SpendingLeaderboard range: start=%v, end=%v, type=%s", start, end, req.RangeType))
|
||||
} else {
|
||||
h.logger.Info("SpendingLeaderboard range: ALL TIME")
|
||||
}
|
||||
|
||||
db := h.repo.GetDbR().WithContext(ctx.RequestContext())
|
||||
|
||||
// 1. Get Top Spenders from Orders
|
||||
type orderStat struct {
|
||||
UserID int64
|
||||
TotalAmount int64 // ActualAmount
|
||||
OrderCount int64
|
||||
TotalDiscount int64
|
||||
TotalPoints int64
|
||||
GamePassCount int64
|
||||
ItemCardCount int64
|
||||
IchibanSpending int64
|
||||
IchibanCount int64
|
||||
InfiniteSpending int64
|
||||
InfiniteCount int64
|
||||
MatchingSpending int64
|
||||
MatchingCount int64
|
||||
}
|
||||
var stats []orderStat
|
||||
|
||||
query := db.Table(model.TableNameOrders).
|
||||
Joins("LEFT JOIN (SELECT l.order_id, MAX(a.play_type) as play_type FROM activity_draw_logs l JOIN activity_issues i ON i.id = l.issue_id JOIN activities a ON a.id = i.activity_id GROUP BY l.order_id) oa ON oa.order_id = orders.id").
|
||||
Where("orders.status = ?", 2)
|
||||
|
||||
if req.RangeType != "all" {
|
||||
query = query.Where("orders.created_at >= ?", start).Where("orders.created_at <= ?", end)
|
||||
}
|
||||
|
||||
if err := query.Select(`
|
||||
orders.user_id,
|
||||
SUM(orders.actual_amount) as total_amount,
|
||||
COUNT(orders.id) as order_count,
|
||||
SUM(orders.discount_amount) as total_discount,
|
||||
SUM(orders.points_amount) as total_points,
|
||||
SUM(CASE WHEN orders.source_type = 4 THEN 1 ELSE 0 END) as game_pass_count,
|
||||
SUM(CASE WHEN orders.item_card_id > 0 THEN 1 ELSE 0 END) as item_card_count,
|
||||
SUM(CASE WHEN oa.play_type = 'ichiban' THEN orders.actual_amount ELSE 0 END) as ichiban_spending,
|
||||
SUM(CASE WHEN oa.play_type = 'ichiban' THEN 1 ELSE 0 END) as ichiban_count,
|
||||
SUM(CASE WHEN oa.play_type IN ('infinite', 'box') THEN orders.actual_amount ELSE 0 END) as infinite_spending,
|
||||
SUM(CASE WHEN oa.play_type IN ('infinite', 'box') THEN 1 ELSE 0 END) as infinite_count,
|
||||
SUM(CASE WHEN oa.play_type = 'matching' THEN orders.actual_amount ELSE 0 END) as matching_spending,
|
||||
SUM(CASE WHEN oa.play_type = 'matching' THEN 1 ELSE 0 END) as matching_count
|
||||
`).
|
||||
Group("orders.user_id").
|
||||
Order("total_amount DESC").
|
||||
Limit(50).
|
||||
Scan(&stats).Error; err != nil {
|
||||
h.logger.Error(fmt.Sprintf("SpendingLeaderboard SQL error: %v", err))
|
||||
ctx.AbortWithError(core.Error(http.StatusBadRequest, 21020, err.Error()))
|
||||
return
|
||||
}
|
||||
h.logger.Info(fmt.Sprintf("SpendingLeaderboard SQL done: count=%d", len(stats)))
|
||||
|
||||
// 2. Collect User IDs
|
||||
userIDs := make([]int64, len(stats))
|
||||
statMap := make(map[int64]*spendingLeaderboardItem)
|
||||
for i, s := range stats {
|
||||
userIDs[i] = s.UserID
|
||||
statMap[s.UserID] = &spendingLeaderboardItem{
|
||||
UserID: s.UserID,
|
||||
TotalSpending: s.TotalAmount,
|
||||
OrderCount: s.OrderCount,
|
||||
TotalDiscount: s.TotalDiscount,
|
||||
TotalPoints: s.TotalPoints,
|
||||
GamePassCount: s.GamePassCount,
|
||||
ItemCardCount: s.ItemCardCount,
|
||||
IchibanSpending: s.IchibanSpending,
|
||||
IchibanCount: s.IchibanCount,
|
||||
InfiniteSpending: s.InfiniteSpending,
|
||||
InfiniteCount: s.InfiniteCount,
|
||||
MatchingSpending: s.MatchingSpending,
|
||||
MatchingCount: s.MatchingCount,
|
||||
}
|
||||
}
|
||||
|
||||
if len(userIDs) > 0 {
|
||||
// 3. Get User Info
|
||||
// Use h.readDB.Users (GEN) as it's simple
|
||||
users, _ := h.readDB.Users.WithContext(ctx.RequestContext()).ReadDB().Where(h.readDB.Users.ID.In(userIDs...)).Find()
|
||||
for _, u := range users {
|
||||
if item, ok := statMap[u.ID]; ok {
|
||||
item.Nickname = u.Nickname
|
||||
item.Avatar = u.Avatar
|
||||
}
|
||||
}
|
||||
|
||||
// 4. Calculate Prize Value (Inventory)
|
||||
type invStat struct {
|
||||
UserID int64
|
||||
TotalValue int64
|
||||
IchibanPrize int64
|
||||
InfinitePrize int64
|
||||
MatchingPrize int64
|
||||
}
|
||||
var invStats []invStat
|
||||
|
||||
// Join with Products and Activities
|
||||
query := db.Table(model.TableNameUserInventory).
|
||||
Joins("JOIN products ON products.id = user_inventory.product_id").
|
||||
Joins("LEFT JOIN activities ON activities.id = user_inventory.activity_id").
|
||||
Where("user_inventory.user_id IN ?", userIDs)
|
||||
|
||||
if req.RangeType != "all" {
|
||||
query = query.Where("user_inventory.created_at >= ?", start).
|
||||
Where("user_inventory.created_at <= ?", end)
|
||||
}
|
||||
|
||||
err := query.Select(`
|
||||
user_inventory.user_id,
|
||||
SUM(products.price) as total_value,
|
||||
SUM(CASE WHEN activities.play_type = 'ichiban' THEN products.price ELSE 0 END) as ichiban_prize,
|
||||
SUM(CASE WHEN activities.play_type IN ('infinite', 'box') THEN products.price ELSE 0 END) as infinite_prize,
|
||||
SUM(CASE WHEN activities.play_type = 'matching' THEN products.price ELSE 0 END) as matching_prize
|
||||
`).
|
||||
Group("user_inventory.user_id").
|
||||
Scan(&invStats).Error
|
||||
|
||||
if err == nil {
|
||||
for _, is := range invStats {
|
||||
if item, ok := statMap[is.UserID]; ok {
|
||||
item.TotalPrizeValue = is.TotalValue
|
||||
item.IchibanPrize = is.IchibanPrize
|
||||
item.InfinitePrize = is.InfinitePrize
|
||||
item.MatchingPrize = is.MatchingPrize
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 5. Calculate Profit and Final List
|
||||
list := make([]spendingLeaderboardItem, 0, len(statMap))
|
||||
for _, item := range statMap {
|
||||
item.Profit = item.TotalSpending - item.TotalPrizeValue
|
||||
if item.TotalSpending > 0 {
|
||||
item.ProfitRate = float64(item.Profit) / float64(item.TotalSpending)
|
||||
}
|
||||
list = append(list, *item)
|
||||
}
|
||||
|
||||
// 6. Sort (in memory since we only have top N spenders)
|
||||
sortBy := req.SortBy
|
||||
if sortBy == "" {
|
||||
sortBy = "spending"
|
||||
}
|
||||
|
||||
sort.Slice(list, func(i, j int) bool {
|
||||
switch sortBy {
|
||||
case "profit":
|
||||
return list[i].Profit > list[j].Profit // Higher profit first
|
||||
case "profit_asc":
|
||||
return list[i].Profit < list[j].Profit // Lower profit (loss) first
|
||||
default:
|
||||
return list[i].TotalSpending > list[j].TotalSpending
|
||||
}
|
||||
})
|
||||
|
||||
// Pagination on the result list
|
||||
startIdx := (req.Page - 1) * req.PageSize
|
||||
if startIdx >= len(list) {
|
||||
startIdx = len(list)
|
||||
}
|
||||
endIdx := startIdx + req.PageSize
|
||||
if endIdx > len(list) {
|
||||
endIdx = len(list)
|
||||
}
|
||||
|
||||
finalList := list[startIdx:endIdx]
|
||||
if finalList == nil {
|
||||
finalList = []spendingLeaderboardItem{}
|
||||
}
|
||||
|
||||
ctx.Payload(&spendingLeaderboardResponse{
|
||||
Page: req.Page,
|
||||
PageSize: req.PageSize,
|
||||
Total: int64(len(list)), // Total of the fetched top batch
|
||||
List: finalList,
|
||||
})
|
||||
}
|
||||
}
|
||||
@ -277,12 +277,23 @@ func (h *handler) ListPayOrders() core.HandlerFunc {
|
||||
}
|
||||
}
|
||||
|
||||
type adminOrderPointsLedgerItem struct {
|
||||
ID int64 `json:"id"`
|
||||
UserID int64 `json:"user_id"`
|
||||
Action string `json:"action"`
|
||||
Points int64 `json:"points"`
|
||||
RefTable string `json:"ref_table"`
|
||||
RefID string `json:"ref_id"`
|
||||
Remark string `json:"remark"`
|
||||
CreatedAt string `json:"created_at"`
|
||||
}
|
||||
|
||||
type getPayOrderResponse struct {
|
||||
Order *model.Orders `json:"order"`
|
||||
Items []*model.OrderItems `json:"items"`
|
||||
Shipments []*model.ShippingRecords `json:"shipments"`
|
||||
Ledgers []*model.UserPointsLedger `json:"ledgers"`
|
||||
User *model.Users `json:"user"`
|
||||
Order *model.Orders `json:"order"`
|
||||
Items []*model.OrderItems `json:"items"`
|
||||
Shipments []*model.ShippingRecords `json:"shipments"`
|
||||
Ledgers []adminOrderPointsLedgerItem `json:"ledgers"`
|
||||
User *model.Users `json:"user"`
|
||||
Coupons []*struct {
|
||||
UserCouponID int64 `json:"user_coupon_id"`
|
||||
AppliedAmount int64 `json:"applied_amount"`
|
||||
@ -644,7 +655,19 @@ func (h *handler) GetPayOrderDetail() core.HandlerFunc {
|
||||
rsp.Items = items
|
||||
rsp.Coupons = couponList
|
||||
rsp.Shipments = shipments
|
||||
rsp.Ledgers = ledgers
|
||||
rsp.Ledgers = make([]adminOrderPointsLedgerItem, len(ledgers))
|
||||
for i, l := range ledgers {
|
||||
rsp.Ledgers[i] = adminOrderPointsLedgerItem{
|
||||
ID: l.ID,
|
||||
UserID: l.UserID,
|
||||
Action: l.Action,
|
||||
Points: int64(h.userSvc.CentsToPointsFloat(ctx.RequestContext(), l.Points)),
|
||||
RefTable: l.RefTable,
|
||||
RefID: l.RefID,
|
||||
Remark: l.Remark,
|
||||
CreatedAt: l.CreatedAt.Format("2006-01-02 15:04:05"),
|
||||
}
|
||||
}
|
||||
if order.SourceType == 2 {
|
||||
unit := int64(0)
|
||||
if count > 0 {
|
||||
|
||||
@ -2,7 +2,6 @@ package admin
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
@ -50,14 +49,7 @@ func (h *handler) ExportPayOrders() core.HandlerFunc {
|
||||
ctx.AbortWithError(core.Error(http.StatusBadRequest, 23001, err.Error()))
|
||||
return
|
||||
}
|
||||
var pointsRate int64 = 1
|
||||
if cfgRate, _ := h.readDB.SystemConfigs.WithContext(ctx.RequestContext()).Where(h.readDB.SystemConfigs.ConfigKey.Eq("points_exchange_per_cent")).First(); cfgRate != nil {
|
||||
var r int64
|
||||
_, _ = fmt.Sscanf(cfgRate.ConfigValue, "%d", &r)
|
||||
if r > 0 {
|
||||
pointsRate = r
|
||||
}
|
||||
}
|
||||
|
||||
file := xlsx.NewFile()
|
||||
sheet, _ := file.AddSheet("orders")
|
||||
header := []string{"订单号", "用户ID", "来源", "状态", "总金额", "折扣", "积分抵扣(分)", "积分抵扣(积分)", "优惠券抵扣(分)", "实付", "支付时间", "创建时间"}
|
||||
@ -76,13 +68,17 @@ func (h *handler) ExportPayOrders() core.HandlerFunc {
|
||||
}
|
||||
pa := o.PointsAmount
|
||||
if pa == 0 && consumePointsSum > 0 {
|
||||
pa = consumePointsSum / pointsRate
|
||||
{
|
||||
// Backwards compatibility if o.PointsAmount is missing
|
||||
// If consumePointsSum is Cents, pa is Cents.
|
||||
pa = consumePointsSum
|
||||
}
|
||||
}
|
||||
pu := int64(0)
|
||||
if consumePointsSum > 0 {
|
||||
pu = consumePointsSum
|
||||
} else if pa > 0 {
|
||||
pu = pa * pointsRate
|
||||
// pu is Points Unit
|
||||
pu := int64(h.userSvc.CentsToPointsFloat(ctx.RequestContext(), consumePointsSum))
|
||||
if pu == 0 && pa > 0 {
|
||||
// If no ledger, try converting from Cents
|
||||
pu = int64(h.userSvc.CentsToPointsFloat(ctx.RequestContext(), pa))
|
||||
}
|
||||
ocs, _ := h.readDB.OrderCoupons.WithContext(ctx.RequestContext()).ReadDB().Where(h.readDB.OrderCoupons.OrderID.Eq(o.ID)).Find()
|
||||
var couponApplied int64
|
||||
|
||||
@ -239,17 +239,33 @@ func (h *handler) CreateRefund() core.HandlerFunc {
|
||||
}
|
||||
|
||||
// 全额退款:回退次数卡(user_game_passes)
|
||||
// 解析订单 remark 中的 game_pass:xxx ID
|
||||
reGamePass := regexp.MustCompile(`game_pass:(\d+)`)
|
||||
gamePassMatches := reGamePass.FindStringSubmatch(order.Remark)
|
||||
if len(gamePassMatches) > 1 {
|
||||
gamePassID, _ := strconv.ParseInt(gamePassMatches[1], 10, 64)
|
||||
if gamePassID > 0 {
|
||||
// 恢复次数卡:remaining +1, total_used -1
|
||||
if err := h.repo.GetDbW().Exec("UPDATE user_game_passes SET remaining = remaining + 1, total_used = GREATEST(total_used - 1, 0), updated_at = NOW(3) WHERE id = ?", gamePassID).Error; err != nil {
|
||||
h.logger.Error(fmt.Sprintf("refund restore game_pass failed: order=%s game_pass_id=%d err=%v", order.OrderNo, gamePassID, err))
|
||||
} else {
|
||||
h.logger.Info(fmt.Sprintf("refund restore game_pass success: order=%s game_pass_id=%d", order.OrderNo, gamePassID))
|
||||
// 优先解析新格式: gp_use:ID:Count (支持多张卡、多数量)
|
||||
reGpNew := regexp.MustCompile(`gp_use:(\d+):(\d+)`)
|
||||
matchesNew := reGpNew.FindAllStringSubmatch(order.Remark, -1)
|
||||
if len(matchesNew) > 0 {
|
||||
for _, m := range matchesNew {
|
||||
gpID, _ := strconv.ParseInt(m[1], 10, 64)
|
||||
gpCount, _ := strconv.ParseInt(m[2], 10, 64)
|
||||
if gpID > 0 && gpCount > 0 {
|
||||
if err := h.repo.GetDbW().Exec("UPDATE user_game_passes SET remaining = remaining + ?, total_used = GREATEST(total_used - ?, 0), updated_at = NOW(3) WHERE id = ?", gpCount, gpCount, gpID).Error; err != nil {
|
||||
h.logger.Error(fmt.Sprintf("refund restore game_pass failed: order=%s gp_id=%d count=%d err=%v", order.OrderNo, gpID, gpCount, err))
|
||||
} else {
|
||||
h.logger.Info(fmt.Sprintf("refund restore game_pass success: order=%s gp_id=%d count=%d", order.OrderNo, gpID, gpCount))
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// 兼容旧格式: game_pass:ID (仅恢复 1 次)
|
||||
reGamePass := regexp.MustCompile(`game_pass:(\d+)`)
|
||||
gamePassMatches := reGamePass.FindStringSubmatch(order.Remark)
|
||||
if len(gamePassMatches) > 1 {
|
||||
gamePassID, _ := strconv.ParseInt(gamePassMatches[1], 10, 64)
|
||||
if gamePassID > 0 {
|
||||
if err := h.repo.GetDbW().Exec("UPDATE user_game_passes SET remaining = remaining + 1, total_used = GREATEST(total_used - 1, 0), updated_at = NOW(3) WHERE id = ?", gamePassID).Error; err != nil {
|
||||
h.logger.Error(fmt.Sprintf("refund restore game_pass failed: order=%s game_pass_id=%d err=%v", order.OrderNo, gamePassID, err))
|
||||
} else {
|
||||
h.logger.Info(fmt.Sprintf("refund restore game_pass success: order=%s game_pass_id=%d", order.OrderNo, gamePassID))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -132,21 +132,20 @@ func (h *handler) ModifySystemCoupon() core.HandlerFunc {
|
||||
}
|
||||
|
||||
func (h *handler) DeleteSystemCoupon() core.HandlerFunc {
|
||||
return func(ctx core.Context) {
|
||||
idStr := ctx.Param("coupon_id")
|
||||
id, _ := strconv.ParseInt(idStr, 10, 64)
|
||||
if ctx.SessionUserInfo().IsSuper != 1 {
|
||||
ctx.AbortWithError(core.Error(http.StatusBadRequest, code.CreateAdminError, "禁止操作"))
|
||||
return
|
||||
}
|
||||
uid := int64(ctx.SessionUserInfo().Id)
|
||||
set := map[string]any{"deleted_at": time.Now(), "deleted_by": uid}
|
||||
if _, err := h.writeDB.SystemCoupons.WithContext(ctx.RequestContext()).Where(h.writeDB.SystemCoupons.ID.Eq(id)).Updates(set); err != nil {
|
||||
ctx.AbortWithError(core.Error(http.StatusBadRequest, code.CreateAdminError, err.Error()))
|
||||
return
|
||||
}
|
||||
ctx.Payload(pcSimpleMessage{Message: "操作成功"})
|
||||
}
|
||||
return func(ctx core.Context) {
|
||||
idStr := ctx.Param("coupon_id")
|
||||
id, _ := strconv.ParseInt(idStr, 10, 64)
|
||||
if ctx.SessionUserInfo().IsSuper != 1 {
|
||||
ctx.AbortWithError(core.Error(http.StatusBadRequest, code.CreateAdminError, "禁止操作"))
|
||||
return
|
||||
}
|
||||
set := map[string]any{"deleted_at": time.Now()}
|
||||
if _, err := h.writeDB.SystemCoupons.WithContext(ctx.RequestContext()).Where(h.writeDB.SystemCoupons.ID.Eq(id)).Updates(set); err != nil {
|
||||
ctx.AbortWithError(core.Error(http.StatusBadRequest, code.CreateAdminError, err.Error()))
|
||||
return
|
||||
}
|
||||
ctx.Payload(pcSimpleMessage{Message: "操作成功"})
|
||||
}
|
||||
}
|
||||
|
||||
type listSystemCouponsRequest struct {
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
package admin
|
||||
|
||||
import (
|
||||
"math"
|
||||
"net/http"
|
||||
"strconv"
|
||||
"time"
|
||||
@ -150,7 +151,7 @@ func (h *handler) ListAppUsers() core.HandlerFunc {
|
||||
Group(h.readDB.UserPoints.UserID).
|
||||
Scan(&bRes)
|
||||
for _, b := range bRes {
|
||||
pointBalances[b.UserID] = b.Points
|
||||
pointBalances[b.UserID] = int64(h.userSvc.CentsToPointsFloat(ctx.RequestContext(), b.Points))
|
||||
}
|
||||
}
|
||||
|
||||
@ -298,6 +299,65 @@ func (h *handler) ListAppUsers() core.HandlerFunc {
|
||||
}
|
||||
}
|
||||
|
||||
// 批量查询持有商品价值
|
||||
inventoryValues := make(map[int64]int64)
|
||||
if len(userIDs) > 0 {
|
||||
type invResult struct {
|
||||
UserID int64
|
||||
Value int64
|
||||
}
|
||||
var invRes []invResult
|
||||
h.readDB.UserInventory.WithContext(ctx.RequestContext()).ReadDB().
|
||||
LeftJoin(h.readDB.Products, h.readDB.Products.ID.EqCol(h.readDB.UserInventory.ProductID)).
|
||||
Select(h.readDB.UserInventory.UserID, h.readDB.Products.Price.Sum().As("value")).
|
||||
Where(h.readDB.UserInventory.UserID.In(userIDs...)).
|
||||
Where(h.readDB.UserInventory.Status.Eq(1)). // 1=持有
|
||||
Group(h.readDB.UserInventory.UserID).
|
||||
Scan(&invRes)
|
||||
for _, r := range invRes {
|
||||
inventoryValues[r.UserID] = r.Value
|
||||
}
|
||||
}
|
||||
|
||||
// 批量查询优惠券价值(余额之和)
|
||||
couponValues := make(map[int64]int64)
|
||||
if len(userIDs) > 0 {
|
||||
type valResult struct {
|
||||
UserID int64
|
||||
Value int64
|
||||
}
|
||||
var vRes []valResult
|
||||
h.readDB.UserCoupons.WithContext(ctx.RequestContext()).ReadDB().
|
||||
Select(h.readDB.UserCoupons.UserID, h.readDB.UserCoupons.BalanceAmount.Sum().As("value")).
|
||||
Where(h.readDB.UserCoupons.UserID.In(userIDs...)).
|
||||
Where(h.readDB.UserCoupons.Status.Eq(1)).
|
||||
Group(h.readDB.UserCoupons.UserID).
|
||||
Scan(&vRes)
|
||||
for _, v := range vRes {
|
||||
couponValues[v.UserID] = v.Value
|
||||
}
|
||||
}
|
||||
|
||||
// 批量查询道具卡价值
|
||||
itemCardValues := make(map[int64]int64)
|
||||
if len(userIDs) > 0 {
|
||||
type valResult struct {
|
||||
UserID int64
|
||||
Value int64
|
||||
}
|
||||
var vRes []valResult
|
||||
h.readDB.UserItemCards.WithContext(ctx.RequestContext()).ReadDB().
|
||||
LeftJoin(h.readDB.SystemItemCards, h.readDB.SystemItemCards.ID.EqCol(h.readDB.UserItemCards.CardID)).
|
||||
Select(h.readDB.UserItemCards.UserID, h.readDB.SystemItemCards.Price.Sum().As("value")).
|
||||
Where(h.readDB.UserItemCards.UserID.In(userIDs...)).
|
||||
Where(h.readDB.UserItemCards.Status.Eq(1)).
|
||||
Group(h.readDB.UserItemCards.UserID).
|
||||
Scan(&vRes)
|
||||
for _, v := range vRes {
|
||||
itemCardValues[v.UserID] = v.Value
|
||||
}
|
||||
}
|
||||
|
||||
// 批量查询所有用户的邀请人昵称
|
||||
inviterNicknames := make(map[int64]string)
|
||||
inviterIDs := make([]int64, 0)
|
||||
@ -318,6 +378,16 @@ func (h *handler) ListAppUsers() core.HandlerFunc {
|
||||
rsp.Total = total
|
||||
rsp.List = make([]adminUserItem, len(rows))
|
||||
for i, v := range rows {
|
||||
pointsBal := pointBalances[v.ID]
|
||||
invVal := inventoryValues[v.ID]
|
||||
cpVal := couponValues[v.ID]
|
||||
icVal := itemCardValues[v.ID]
|
||||
gpCount := gamePassCounts[v.ID]
|
||||
gtCount := gameTicketCounts[v.ID]
|
||||
|
||||
// 总资产估值逻辑:积分余额 + 商品价值 + 优惠券价值 + 道具卡价值 + 次数卡(2元/次) + 游戏资格(1元/场)
|
||||
assetVal := pointsBal*100 + invVal + cpVal + icVal + gpCount*200 + gtCount*100
|
||||
|
||||
rsp.List[i] = adminUserItem{
|
||||
ID: v.ID,
|
||||
Nickname: v.Nickname,
|
||||
@ -329,7 +399,7 @@ func (h *handler) ListAppUsers() core.HandlerFunc {
|
||||
DouyinID: v.DouyinID,
|
||||
ChannelName: v.ChannelName,
|
||||
ChannelCode: v.ChannelCode,
|
||||
PointsBalance: pointBalances[v.ID],
|
||||
PointsBalance: pointsBal,
|
||||
CouponsCount: couponCounts[v.ID],
|
||||
ItemCardsCount: cardCounts[v.ID],
|
||||
TodayConsume: todayConsume[v.ID],
|
||||
@ -337,8 +407,10 @@ func (h *handler) ListAppUsers() core.HandlerFunc {
|
||||
ThirtyDayConsume: thirtyDayConsume[v.ID],
|
||||
TotalConsume: totalConsume[v.ID],
|
||||
InviteCount: inviteCounts[v.ID],
|
||||
GamePassCount: gamePassCounts[v.ID],
|
||||
GameTicketCount: gameTicketCounts[v.ID],
|
||||
GamePassCount: gpCount,
|
||||
GameTicketCount: gtCount,
|
||||
InventoryValue: invVal,
|
||||
TotalAssetValue: assetVal,
|
||||
}
|
||||
}
|
||||
ctx.Payload(rsp)
|
||||
@ -410,8 +482,9 @@ type listOrdersResponse struct {
|
||||
}
|
||||
|
||||
type listInventoryRequest struct {
|
||||
Page int `form:"page"`
|
||||
PageSize int `form:"page_size"`
|
||||
Page int `form:"page"`
|
||||
PageSize int `form:"page_size"`
|
||||
Keyword string `form:"keyword"` // 搜索关键词(商品名称)
|
||||
}
|
||||
type listInventoryResponse struct {
|
||||
Page int `json:"page"`
|
||||
@ -485,6 +558,96 @@ func (h *handler) ListUserInventory() core.HandlerFunc {
|
||||
ctx.AbortWithError(core.Error(http.StatusBadRequest, code.ParamBindError, "未传递用户ID"))
|
||||
return
|
||||
}
|
||||
|
||||
// 处理分页参数
|
||||
if req.Page <= 0 {
|
||||
req.Page = 1
|
||||
}
|
||||
if req.PageSize <= 0 {
|
||||
req.PageSize = 20
|
||||
}
|
||||
if req.PageSize > 100 {
|
||||
req.PageSize = 100
|
||||
}
|
||||
|
||||
// 如果有搜索关键词,使用带搜索的查询
|
||||
if req.Keyword != "" {
|
||||
// 联表查询以支持按商品名称搜索
|
||||
ui := h.readDB.UserInventory
|
||||
p := h.readDB.Products
|
||||
|
||||
// 首先统计符合条件的总数
|
||||
countQ := h.readDB.UserInventory.WithContext(ctx.RequestContext()).ReadDB().
|
||||
LeftJoin(p, p.ID.EqCol(ui.ProductID)).
|
||||
Where(ui.UserID.Eq(userID)).
|
||||
Where(p.Name.Like("%" + req.Keyword + "%"))
|
||||
total, err := countQ.Count()
|
||||
if err != nil {
|
||||
ctx.AbortWithError(core.Error(http.StatusBadRequest, 20105, err.Error()))
|
||||
return
|
||||
}
|
||||
|
||||
// 查询资产数据
|
||||
type inventoryRow struct {
|
||||
ID int64
|
||||
UserID int64
|
||||
ProductID int64
|
||||
OrderID int64
|
||||
ActivityID int64
|
||||
RewardID int64
|
||||
Status int32
|
||||
Remark string
|
||||
CreatedAt string
|
||||
UpdatedAt string
|
||||
ProductName string
|
||||
ProductImages string
|
||||
ProductPrice int64
|
||||
}
|
||||
var rows []inventoryRow
|
||||
err = h.repo.GetDbR().Raw(`
|
||||
SELECT ui.id, ui.user_id, ui.product_id, ui.order_id, ui.activity_id, ui.reward_id,
|
||||
ui.status, ui.remark, ui.created_at, ui.updated_at,
|
||||
p.name as product_name, p.images_json as product_images, p.price as product_price
|
||||
FROM user_inventory ui
|
||||
LEFT JOIN products p ON p.id = ui.product_id
|
||||
WHERE ui.user_id = ? AND p.name LIKE ?
|
||||
ORDER BY ui.id DESC
|
||||
LIMIT ? OFFSET ?
|
||||
`, userID, "%"+req.Keyword+"%", req.PageSize, (req.Page-1)*req.PageSize).Scan(&rows).Error
|
||||
if err != nil {
|
||||
ctx.AbortWithError(core.Error(http.StatusBadRequest, 20105, err.Error()))
|
||||
return
|
||||
}
|
||||
|
||||
// 转换结果
|
||||
items := make([]*user.InventoryWithProduct, len(rows))
|
||||
for i, r := range rows {
|
||||
items[i] = &user.InventoryWithProduct{
|
||||
UserInventory: &model.UserInventory{
|
||||
ID: r.ID,
|
||||
UserID: r.UserID,
|
||||
ProductID: r.ProductID,
|
||||
OrderID: r.OrderID,
|
||||
ActivityID: r.ActivityID,
|
||||
RewardID: r.RewardID,
|
||||
Status: r.Status,
|
||||
Remark: r.Remark,
|
||||
},
|
||||
ProductName: r.ProductName,
|
||||
ProductImages: r.ProductImages,
|
||||
ProductPrice: r.ProductPrice,
|
||||
}
|
||||
}
|
||||
|
||||
rsp.Page = req.Page
|
||||
rsp.PageSize = req.PageSize
|
||||
rsp.Total = total
|
||||
rsp.List = items
|
||||
ctx.Payload(rsp)
|
||||
return
|
||||
}
|
||||
|
||||
// 无搜索关键词时使用原有逻辑
|
||||
rows, total, err := h.userSvc.ListInventoryWithProduct(ctx.RequestContext(), userID, req.Page, req.PageSize)
|
||||
if err != nil {
|
||||
ctx.AbortWithError(core.Error(http.StatusBadRequest, 20105, err.Error()))
|
||||
@ -680,11 +843,22 @@ type listPointsRequest struct {
|
||||
Page int `form:"page"`
|
||||
PageSize int `form:"page_size"`
|
||||
}
|
||||
type adminUserPointsLedgerItem struct {
|
||||
ID int64 `json:"id"`
|
||||
UserID int64 `json:"user_id"`
|
||||
Action string `json:"action"`
|
||||
Points int64 `json:"points"`
|
||||
RefTable string `json:"ref_table"`
|
||||
RefID string `json:"ref_id"`
|
||||
Remark string `json:"remark"`
|
||||
CreatedAt string `json:"created_at"`
|
||||
}
|
||||
|
||||
type listPointsResponse struct {
|
||||
Page int `json:"page"`
|
||||
PageSize int `json:"page_size"`
|
||||
Total int64 `json:"total"`
|
||||
List []*model.UserPointsLedger `json:"list"`
|
||||
Page int `json:"page"`
|
||||
PageSize int `json:"page_size"`
|
||||
Total int64 `json:"total"`
|
||||
List []adminUserPointsLedgerItem `json:"list"`
|
||||
}
|
||||
|
||||
// ListUserPoints 查看用户积分记录
|
||||
@ -721,7 +895,20 @@ func (h *handler) ListUserPoints() core.HandlerFunc {
|
||||
rsp.Page = req.Page
|
||||
rsp.PageSize = req.PageSize
|
||||
rsp.Total = total
|
||||
rsp.List = items
|
||||
// Convert ledger items
|
||||
rsp.List = make([]adminUserPointsLedgerItem, len(items))
|
||||
for i, v := range items {
|
||||
rsp.List[i] = adminUserPointsLedgerItem{
|
||||
ID: v.ID,
|
||||
UserID: v.UserID,
|
||||
Action: v.Action,
|
||||
Points: int64(h.userSvc.CentsToPointsFloat(ctx.RequestContext(), v.Points)),
|
||||
RefTable: v.RefTable,
|
||||
RefID: v.RefID,
|
||||
Remark: v.Remark,
|
||||
CreatedAt: v.CreatedAt.Format("2006-01-02 15:04:05"),
|
||||
}
|
||||
}
|
||||
ctx.Payload(rsp)
|
||||
}
|
||||
}
|
||||
@ -751,6 +938,8 @@ type adminUserItem struct {
|
||||
InviteCount int64 `json:"invite_count"` // 邀请人数
|
||||
GamePassCount int64 `json:"game_pass_count"` // 次数卡数量
|
||||
GameTicketCount int64 `json:"game_ticket_count"` // 游戏资格数量
|
||||
InventoryValue int64 `json:"inventory_value"` // 持有商品总价值
|
||||
TotalAssetValue int64 `json:"total_asset_value"` // 总资产估值
|
||||
}
|
||||
|
||||
// ListAppUsers 管理端用户列表GetUserPointsBalance 查看用户积分余额
|
||||
@ -777,16 +966,16 @@ func (h *handler) GetUserPointsBalance() core.HandlerFunc {
|
||||
ctx.AbortWithError(core.Error(http.StatusBadRequest, 20107, err.Error()))
|
||||
return
|
||||
}
|
||||
rsp.Balance = total
|
||||
rsp.Balance = int64(h.userSvc.CentsToPointsFloat(ctx.RequestContext(), total))
|
||||
ctx.Payload(rsp)
|
||||
}
|
||||
}
|
||||
|
||||
type addPointsRequest struct {
|
||||
Points int64 `json:"points"` // 正数=增加,负数=扣减
|
||||
Kind string `json:"kind"`
|
||||
Remark string `json:"remark"`
|
||||
ValidDays *int `json:"valid_days"`
|
||||
Points float64 `json:"points"` // 正数=增加,负数=扣减
|
||||
Kind string `json:"kind"`
|
||||
Remark string `json:"remark"`
|
||||
ValidDays *int `json:"valid_days"`
|
||||
}
|
||||
type addPointsResponse struct {
|
||||
Success bool `json:"success"`
|
||||
@ -822,10 +1011,16 @@ func (h *handler) AddUserPoints() core.HandlerFunc {
|
||||
return
|
||||
}
|
||||
|
||||
// 将浮点数积分转换为分(Cents)
|
||||
// 1 积分 = 1 元 = 100 分
|
||||
// 使用 math.Round 避免精度问题
|
||||
pointsCents := int64(math.Round(req.Points * 100))
|
||||
|
||||
// 如果是扣减积分,先检查余额
|
||||
if req.Points < 0 {
|
||||
if pointsCents < 0 {
|
||||
balance, _ := h.userSvc.GetPointsBalance(ctx.RequestContext(), userID)
|
||||
if balance+req.Points < 0 {
|
||||
deductCents := -pointsCents
|
||||
if balance < deductCents {
|
||||
ctx.AbortWithError(core.Error(http.StatusBadRequest, 20108, "积分余额不足,无法扣减"))
|
||||
return
|
||||
}
|
||||
@ -835,14 +1030,15 @@ func (h *handler) AddUserPoints() core.HandlerFunc {
|
||||
var validEnd *time.Time
|
||||
now := time.Now()
|
||||
// 只有增加积分时才设置有效期
|
||||
if req.Points > 0 {
|
||||
if pointsCents > 0 {
|
||||
validStart = &now
|
||||
if req.ValidDays != nil && *req.ValidDays > 0 {
|
||||
ve := now.Add(time.Duration(*req.ValidDays) * 24 * time.Hour)
|
||||
validEnd = &ve
|
||||
}
|
||||
}
|
||||
if err := h.userSvc.AddPoints(ctx.RequestContext(), userID, req.Points, req.Kind, req.Remark, validStart, validEnd); err != nil {
|
||||
|
||||
if err := h.userSvc.AddPoints(ctx.RequestContext(), userID, pointsCents, req.Kind, req.Remark, validStart, validEnd); err != nil {
|
||||
ctx.AbortWithError(core.Error(http.StatusBadRequest, 20108, err.Error()))
|
||||
return
|
||||
}
|
||||
|
||||
@ -1,144 +1,156 @@
|
||||
package admin
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"net/http"
|
||||
|
||||
"bindbox-game/internal/code"
|
||||
"bindbox-game/internal/pkg/core"
|
||||
"bindbox-game/internal/pkg/validation"
|
||||
usersvc "bindbox-game/internal/service/user"
|
||||
"bindbox-game/internal/code"
|
||||
"bindbox-game/internal/pkg/core"
|
||||
"bindbox-game/internal/pkg/validation"
|
||||
usersvc "bindbox-game/internal/service/user"
|
||||
)
|
||||
|
||||
type batchPointsRequest struct {
|
||||
Users []int64 `json:"users" binding:"required"`
|
||||
Amount int64 `json:"amount" binding:"min=1"`
|
||||
Reason string `json:"reason"`
|
||||
IdempotencyKey string `json:"idempotency_key"`
|
||||
Users []int64 `json:"users" binding:"required"`
|
||||
Amount int64 `json:"amount" binding:"min=1"`
|
||||
Reason string `json:"reason"`
|
||||
IdempotencyKey string `json:"idempotency_key"`
|
||||
}
|
||||
|
||||
type batchCouponsRequest struct {
|
||||
Users []int64 `json:"users" binding:"required"`
|
||||
CouponID int64 `json:"coupon_id" binding:"required"`
|
||||
QuantityPerUser int `json:"quantity_per_user"`
|
||||
IdempotencyKey string `json:"idempotency_key"`
|
||||
Users []int64 `json:"users" binding:"required"`
|
||||
CouponID int64 `json:"coupon_id" binding:"required"`
|
||||
QuantityPerUser int `json:"quantity_per_user"`
|
||||
IdempotencyKey string `json:"idempotency_key"`
|
||||
}
|
||||
|
||||
type batchRewardsRequest struct {
|
||||
Users []int64 `json:"users" binding:"required"`
|
||||
ProductID int64 `json:"product_id" binding:"required"`
|
||||
Quantity int `json:"quantity" binding:"min=1"`
|
||||
ActivityID *int64 `json:"activity_id"`
|
||||
RewardID *int64 `json:"reward_id"`
|
||||
AddressID *int64 `json:"address_id"`
|
||||
Remark string `json:"remark"`
|
||||
IdempotencyKey string `json:"idempotency_key"`
|
||||
Users []int64 `json:"users" binding:"required"`
|
||||
ProductID int64 `json:"product_id" binding:"required"`
|
||||
Quantity int `json:"quantity" binding:"min=1"`
|
||||
ActivityID *int64 `json:"activity_id"`
|
||||
RewardID *int64 `json:"reward_id"`
|
||||
AddressID *int64 `json:"address_id"`
|
||||
Remark string `json:"remark"`
|
||||
IdempotencyKey string `json:"idempotency_key"`
|
||||
}
|
||||
|
||||
type batchItemResult struct {
|
||||
UserID int64 `json:"user_id"`
|
||||
Status string `json:"status"`
|
||||
Message string `json:"message"`
|
||||
UserID int64 `json:"user_id"`
|
||||
Status string `json:"status"`
|
||||
Message string `json:"message"`
|
||||
}
|
||||
|
||||
type batchResponse struct {
|
||||
Success int `json:"success"`
|
||||
Failed int `json:"failed"`
|
||||
Details []batchItemResult `json:"details"`
|
||||
Success int `json:"success"`
|
||||
Failed int `json:"failed"`
|
||||
Details []batchItemResult `json:"details"`
|
||||
}
|
||||
|
||||
func (h *handler) BatchAddUserPoints() core.HandlerFunc {
|
||||
return func(ctx core.Context) {
|
||||
if ctx.SessionUserInfo().IsSuper != 1 {
|
||||
ctx.AbortWithError(core.Error(http.StatusBadRequest, code.CreateAdminError, "禁止操作"))
|
||||
return
|
||||
}
|
||||
req := new(batchPointsRequest)
|
||||
if err := ctx.ShouldBindJSON(req); err != nil {
|
||||
ctx.AbortWithError(core.Error(http.StatusBadRequest, code.ParamBindError, validation.Error(err)))
|
||||
return
|
||||
}
|
||||
if len(req.Users) != 1 {
|
||||
ctx.AbortWithError(core.Error(http.StatusBadRequest, code.ParamBindError, "当前仅支持单用户操作,请仅选择1位用户"))
|
||||
return
|
||||
}
|
||||
res := &batchResponse{Details: make([]batchItemResult, 0, len(req.Users))}
|
||||
for _, uid := range req.Users {
|
||||
if err := h.userSvc.AddPoints(ctx.RequestContext(), uid, req.Amount, "manual", req.Reason, nil, nil); err != nil {
|
||||
res.Failed++
|
||||
res.Details = append(res.Details, batchItemResult{UserID: uid, Status: "failed", Message: err.Error()})
|
||||
} else {
|
||||
res.Success++
|
||||
res.Details = append(res.Details, batchItemResult{UserID: uid, Status: "success"})
|
||||
}
|
||||
}
|
||||
ctx.Payload(res)
|
||||
}
|
||||
return func(ctx core.Context) {
|
||||
if ctx.SessionUserInfo().IsSuper != 1 {
|
||||
ctx.AbortWithError(core.Error(http.StatusBadRequest, code.CreateAdminError, "禁止操作"))
|
||||
return
|
||||
}
|
||||
req := new(batchPointsRequest)
|
||||
if err := ctx.ShouldBindJSON(req); err != nil {
|
||||
ctx.AbortWithError(core.Error(http.StatusBadRequest, code.ParamBindError, validation.Error(err)))
|
||||
return
|
||||
}
|
||||
if len(req.Users) != 1 {
|
||||
ctx.AbortWithError(core.Error(http.StatusBadRequest, code.ParamBindError, "当前仅支持单用户操作,请仅选择1位用户"))
|
||||
return
|
||||
}
|
||||
res := &batchResponse{Details: make([]batchItemResult, 0, len(req.Users))}
|
||||
// 将管理员输入的积分转换为分
|
||||
amountCents, _ := h.userSvc.PointsToCents(ctx.RequestContext(), req.Amount)
|
||||
for _, uid := range req.Users {
|
||||
if err := h.userSvc.AddPoints(ctx.RequestContext(), uid, amountCents, "manual", req.Reason, nil, nil); err != nil {
|
||||
res.Failed++
|
||||
res.Details = append(res.Details, batchItemResult{UserID: uid, Status: "failed", Message: err.Error()})
|
||||
} else {
|
||||
res.Success++
|
||||
res.Details = append(res.Details, batchItemResult{UserID: uid, Status: "success"})
|
||||
}
|
||||
}
|
||||
ctx.Payload(res)
|
||||
}
|
||||
}
|
||||
|
||||
func (h *handler) BatchAddUserCoupons() core.HandlerFunc {
|
||||
return func(ctx core.Context) {
|
||||
if ctx.SessionUserInfo().IsSuper != 1 {
|
||||
ctx.AbortWithError(core.Error(http.StatusBadRequest, code.CreateAdminError, "禁止操作"))
|
||||
return
|
||||
}
|
||||
req := new(batchCouponsRequest)
|
||||
if err := ctx.ShouldBindJSON(req); err != nil {
|
||||
ctx.AbortWithError(core.Error(http.StatusBadRequest, code.ParamBindError, validation.Error(err)))
|
||||
return
|
||||
}
|
||||
if len(req.Users) != 1 {
|
||||
ctx.AbortWithError(core.Error(http.StatusBadRequest, code.ParamBindError, "当前仅支持单用户操作,请仅选择1位用户"))
|
||||
return
|
||||
}
|
||||
if req.QuantityPerUser <= 0 { req.QuantityPerUser = 1 }
|
||||
if req.QuantityPerUser > 5 { req.QuantityPerUser = 5 }
|
||||
res := &batchResponse{Details: make([]batchItemResult, 0, len(req.Users))}
|
||||
for _, uid := range req.Users {
|
||||
ok := true
|
||||
for i := 0; i < req.QuantityPerUser; i++ {
|
||||
if err := h.userSvc.AddCoupon(ctx.RequestContext(), uid, req.CouponID); err != nil { ok = false }
|
||||
}
|
||||
if ok {
|
||||
res.Success++
|
||||
res.Details = append(res.Details, batchItemResult{UserID: uid, Status: "success"})
|
||||
} else {
|
||||
res.Failed++
|
||||
res.Details = append(res.Details, batchItemResult{UserID: uid, Status: "failed"})
|
||||
}
|
||||
}
|
||||
ctx.Payload(res)
|
||||
}
|
||||
return func(ctx core.Context) {
|
||||
if ctx.SessionUserInfo().IsSuper != 1 {
|
||||
ctx.AbortWithError(core.Error(http.StatusBadRequest, code.CreateAdminError, "禁止操作"))
|
||||
return
|
||||
}
|
||||
req := new(batchCouponsRequest)
|
||||
if err := ctx.ShouldBindJSON(req); err != nil {
|
||||
ctx.AbortWithError(core.Error(http.StatusBadRequest, code.ParamBindError, validation.Error(err)))
|
||||
return
|
||||
}
|
||||
if len(req.Users) != 1 {
|
||||
ctx.AbortWithError(core.Error(http.StatusBadRequest, code.ParamBindError, "当前仅支持单用户操作,请仅选择1位用户"))
|
||||
return
|
||||
}
|
||||
if req.QuantityPerUser <= 0 {
|
||||
req.QuantityPerUser = 1
|
||||
}
|
||||
if req.QuantityPerUser > 5 {
|
||||
req.QuantityPerUser = 5
|
||||
}
|
||||
res := &batchResponse{Details: make([]batchItemResult, 0, len(req.Users))}
|
||||
for _, uid := range req.Users {
|
||||
ok := true
|
||||
for i := 0; i < req.QuantityPerUser; i++ {
|
||||
if err := h.userSvc.AddCoupon(ctx.RequestContext(), uid, req.CouponID); err != nil {
|
||||
ok = false
|
||||
}
|
||||
}
|
||||
if ok {
|
||||
res.Success++
|
||||
res.Details = append(res.Details, batchItemResult{UserID: uid, Status: "success"})
|
||||
} else {
|
||||
res.Failed++
|
||||
res.Details = append(res.Details, batchItemResult{UserID: uid, Status: "failed"})
|
||||
}
|
||||
}
|
||||
ctx.Payload(res)
|
||||
}
|
||||
}
|
||||
|
||||
func (h *handler) BatchGrantUserRewards() core.HandlerFunc {
|
||||
return func(ctx core.Context) {
|
||||
if ctx.SessionUserInfo().IsSuper != 1 {
|
||||
ctx.AbortWithError(core.Error(http.StatusBadRequest, code.CreateAdminError, "禁止操作"))
|
||||
return
|
||||
}
|
||||
req := new(batchRewardsRequest)
|
||||
if err := ctx.ShouldBindJSON(req); err != nil {
|
||||
ctx.AbortWithError(core.Error(http.StatusBadRequest, code.ParamBindError, validation.Error(err)))
|
||||
return
|
||||
}
|
||||
if len(req.Users) != 1 {
|
||||
ctx.AbortWithError(core.Error(http.StatusBadRequest, code.ParamBindError, "当前仅支持单用户操作,请仅选择1位用户"))
|
||||
return
|
||||
}
|
||||
if req.Quantity <= 0 { req.Quantity = 1 }
|
||||
if req.Quantity > 10 { req.Quantity = 10 }
|
||||
res := &batchResponse{Details: make([]batchItemResult, 0, len(req.Users))}
|
||||
r := usersvc.GrantRewardRequest{ProductID: req.ProductID, Quantity: req.Quantity, ActivityID: req.ActivityID, RewardID: req.RewardID, AddressID: req.AddressID, Remark: req.Remark}
|
||||
for _, uid := range req.Users {
|
||||
_, err := h.userSvc.GrantReward(ctx.RequestContext(), uid, r)
|
||||
if err != nil {
|
||||
res.Failed++
|
||||
res.Details = append(res.Details, batchItemResult{UserID: uid, Status: "failed", Message: err.Error()})
|
||||
} else {
|
||||
res.Success++
|
||||
res.Details = append(res.Details, batchItemResult{UserID: uid, Status: "success"})
|
||||
}
|
||||
}
|
||||
ctx.Payload(res)
|
||||
}
|
||||
}
|
||||
return func(ctx core.Context) {
|
||||
if ctx.SessionUserInfo().IsSuper != 1 {
|
||||
ctx.AbortWithError(core.Error(http.StatusBadRequest, code.CreateAdminError, "禁止操作"))
|
||||
return
|
||||
}
|
||||
req := new(batchRewardsRequest)
|
||||
if err := ctx.ShouldBindJSON(req); err != nil {
|
||||
ctx.AbortWithError(core.Error(http.StatusBadRequest, code.ParamBindError, validation.Error(err)))
|
||||
return
|
||||
}
|
||||
if len(req.Users) != 1 {
|
||||
ctx.AbortWithError(core.Error(http.StatusBadRequest, code.ParamBindError, "当前仅支持单用户操作,请仅选择1位用户"))
|
||||
return
|
||||
}
|
||||
if req.Quantity <= 0 {
|
||||
req.Quantity = 1
|
||||
}
|
||||
if req.Quantity > 10 {
|
||||
req.Quantity = 10
|
||||
}
|
||||
res := &batchResponse{Details: make([]batchItemResult, 0, len(req.Users))}
|
||||
r := usersvc.GrantRewardRequest{ProductID: req.ProductID, Quantity: req.Quantity, ActivityID: req.ActivityID, RewardID: req.RewardID, AddressID: req.AddressID, Remark: req.Remark}
|
||||
for _, uid := range req.Users {
|
||||
_, err := h.userSvc.GrantReward(ctx.RequestContext(), uid, r)
|
||||
if err != nil {
|
||||
res.Failed++
|
||||
res.Details = append(res.Details, batchItemResult{UserID: uid, Status: "failed", Message: err.Error()})
|
||||
} else {
|
||||
res.Success++
|
||||
res.Details = append(res.Details, batchItemResult{UserID: uid, Status: "success"})
|
||||
}
|
||||
}
|
||||
ctx.Payload(res)
|
||||
}
|
||||
}
|
||||
|
||||
@ -104,11 +104,11 @@ func (h *handler) GetUserProfile() core.HandlerFunc {
|
||||
// 3. 生命周期财务指标
|
||||
// 3.1 消费统计
|
||||
type orderStats struct {
|
||||
TotalPaid int64
|
||||
TotalPaid *int64
|
||||
OrderCount int64
|
||||
TodayPaid int64
|
||||
SevenDayPaid int64
|
||||
ThirtyDayPaid int64
|
||||
TodayPaid *int64
|
||||
SevenDayPaid *int64
|
||||
ThirtyDayPaid *int64
|
||||
}
|
||||
var os orderStats
|
||||
now := time.Now()
|
||||
@ -147,11 +147,19 @@ func (h *handler) GetUserProfile() core.HandlerFunc {
|
||||
Where(h.readDB.Orders.CreatedAt.Gte(thirtyDayStart)).
|
||||
Scan(&os.ThirtyDayPaid)
|
||||
|
||||
rsp.LifetimeStats.TotalPaid = os.TotalPaid
|
||||
if os.TotalPaid != nil {
|
||||
rsp.LifetimeStats.TotalPaid = *os.TotalPaid
|
||||
}
|
||||
rsp.LifetimeStats.OrderCount = os.OrderCount
|
||||
rsp.LifetimeStats.TodayPaid = os.TodayPaid
|
||||
rsp.LifetimeStats.SevenDayPaid = os.SevenDayPaid
|
||||
rsp.LifetimeStats.ThirtyDayPaid = os.ThirtyDayPaid
|
||||
if os.TodayPaid != nil {
|
||||
rsp.LifetimeStats.TodayPaid = *os.TodayPaid
|
||||
}
|
||||
if os.SevenDayPaid != nil {
|
||||
rsp.LifetimeStats.SevenDayPaid = *os.SevenDayPaid
|
||||
}
|
||||
if os.ThirtyDayPaid != nil {
|
||||
rsp.LifetimeStats.ThirtyDayPaid = *os.ThirtyDayPaid
|
||||
}
|
||||
|
||||
// 3.2 累计退款
|
||||
var totalRefunded int64
|
||||
|
||||
@ -94,12 +94,16 @@ func (h *handler) GetUserProfitLossTrend() core.HandlerFunc {
|
||||
// --- 2. 获取订单数据(仅 status=2 已支付) ---
|
||||
// 注意:为了计算累计趋势,我们需要获取 start 之前的所有已支付订单总额作为基数
|
||||
var baseCost int64 = 0
|
||||
_ = h.readDB.Orders.WithContext(ctx.RequestContext()).ReadDB().
|
||||
var baseCostPtr *int64
|
||||
h.readDB.Orders.WithContext(ctx.RequestContext()).ReadDB().
|
||||
Select(h.readDB.Orders.ActualAmount.Sum()).
|
||||
Where(h.readDB.Orders.UserID.Eq(userID)).
|
||||
Where(h.readDB.Orders.Status.Eq(2)).
|
||||
Where(h.readDB.Orders.CreatedAt.Lt(start)).
|
||||
Scan(&baseCost)
|
||||
Scan(&baseCostPtr)
|
||||
if baseCostPtr != nil {
|
||||
baseCost = *baseCostPtr
|
||||
}
|
||||
|
||||
// 扣除历史退款 (如果有的话,此处简化处理,主要关注当前范围内的波动)
|
||||
var baseRefund int64 = 0
|
||||
@ -186,11 +190,15 @@ func (h *handler) GetUserProfitLossTrend() core.HandlerFunc {
|
||||
|
||||
// 汇总数据
|
||||
var totalCost int64 = 0
|
||||
_ = h.readDB.Orders.WithContext(ctx.RequestContext()).ReadDB().
|
||||
var totalCostPtr *int64
|
||||
h.readDB.Orders.WithContext(ctx.RequestContext()).ReadDB().
|
||||
Select(h.readDB.Orders.ActualAmount.Sum()).
|
||||
Where(h.readDB.Orders.UserID.Eq(userID)).
|
||||
Where(h.readDB.Orders.Status.Eq(2)).
|
||||
Scan(&totalCost)
|
||||
Scan(&totalCostPtr)
|
||||
if totalCostPtr != nil {
|
||||
totalCost = *totalCostPtr
|
||||
}
|
||||
|
||||
var totalRefund int64 = 0
|
||||
_ = h.repo.GetDbR().Raw(`
|
||||
@ -227,3 +235,294 @@ func (h *handler) GetUserProfitLossTrend() core.HandlerFunc {
|
||||
ctx.Payload(resp)
|
||||
}
|
||||
}
|
||||
|
||||
// 盈亏明细请求
|
||||
type profitLossDetailsRequest struct {
|
||||
Page int `form:"page"`
|
||||
PageSize int `form:"page_size"`
|
||||
RangeType string `form:"rangeType"`
|
||||
}
|
||||
|
||||
// 盈亏明细项
|
||||
type profitLossDetailItem struct {
|
||||
OrderID int64 `json:"order_id"`
|
||||
OrderNo string `json:"order_no"`
|
||||
CreatedAt string `json:"created_at"`
|
||||
SourceType int32 `json:"source_type"` // 来源类型 1商城 2抽奖 3系统
|
||||
ActivityName string `json:"activity_name"` // 活动名称
|
||||
ActualAmount int64 `json:"actual_amount"` // 实际支付金额(分)
|
||||
RefundAmount int64 `json:"refund_amount"` // 退款金额(分)
|
||||
NetCost int64 `json:"net_cost"` // 净投入(分)
|
||||
PrizeValue int64 `json:"prize_value"` // 获得奖品价值(分)
|
||||
PrizeName string `json:"prize_name"` // 奖品名称
|
||||
PointsEarned int64 `json:"points_earned"` // 获得积分
|
||||
PointsValue int64 `json:"points_value"` // 积分价值(分)
|
||||
CouponUsedValue int64 `json:"coupon_used_value"` // 使用优惠券价值(分)
|
||||
CouponUsedName string `json:"coupon_used_name"` // 使用的优惠券名称
|
||||
ItemCardUsed string `json:"item_card_used"` // 使用的道具卡名称
|
||||
ItemCardValue int64 `json:"item_card_value"` // 道具卡价值(分)
|
||||
NetProfit int64 `json:"net_profit"` // 净盈亏
|
||||
}
|
||||
|
||||
// 盈亏明细响应
|
||||
type profitLossDetailsResponse struct {
|
||||
Page int `json:"page"`
|
||||
PageSize int `json:"page_size"`
|
||||
Total int64 `json:"total"`
|
||||
List []profitLossDetailItem `json:"list"`
|
||||
Summary struct {
|
||||
TotalCost int64 `json:"total_cost"`
|
||||
TotalValue int64 `json:"total_value"`
|
||||
TotalProfit int64 `json:"total_profit"`
|
||||
} `json:"summary"`
|
||||
}
|
||||
|
||||
// GetUserProfitLossDetails 获取用户盈亏明细
|
||||
// @Summary 获取用户盈亏明细
|
||||
// @Description 获取用户每笔订单的详细盈亏信息
|
||||
// @Tags 管理端.用户
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param user_id path integer true "用户ID"
|
||||
// @Param page query int false "页码" default(1)
|
||||
// @Param page_size query int false "每页数量" default(20)
|
||||
// @Param rangeType query string false "时间范围" default("all")
|
||||
// @Success 200 {object} profitLossDetailsResponse
|
||||
// @Failure 400 {object} code.Failure
|
||||
// @Router /api/admin/users/{user_id}/stats/profit_loss_details [get]
|
||||
// @Security LoginVerifyToken
|
||||
func (h *handler) GetUserProfitLossDetails() core.HandlerFunc {
|
||||
return func(ctx core.Context) {
|
||||
userID, err := strconv.ParseInt(ctx.Param("user_id"), 10, 64)
|
||||
if err != nil {
|
||||
ctx.AbortWithError(core.Error(http.StatusBadRequest, code.ParamBindError, "未传递用户ID"))
|
||||
return
|
||||
}
|
||||
|
||||
req := new(profitLossDetailsRequest)
|
||||
if err := ctx.ShouldBindForm(req); err != nil {
|
||||
ctx.AbortWithError(core.Error(http.StatusBadRequest, code.ParamBindError, validation.Error(err)))
|
||||
return
|
||||
}
|
||||
|
||||
if req.Page <= 0 {
|
||||
req.Page = 1
|
||||
}
|
||||
if req.PageSize <= 0 {
|
||||
req.PageSize = 20
|
||||
}
|
||||
if req.PageSize > 100 {
|
||||
req.PageSize = 100
|
||||
}
|
||||
|
||||
// 解析时间范围
|
||||
start, end := parseRange(req.RangeType, "", "")
|
||||
if req.RangeType == "all" {
|
||||
u, _ := h.readDB.Users.WithContext(ctx.RequestContext()).Where(h.readDB.Users.ID.Eq(userID)).First()
|
||||
if u != nil {
|
||||
start = u.CreatedAt
|
||||
} else {
|
||||
start = time.Date(2025, 1, 1, 0, 0, 0, 0, time.Local)
|
||||
}
|
||||
}
|
||||
|
||||
// 查询订单总数
|
||||
orderQ := h.readDB.Orders.WithContext(ctx.RequestContext()).ReadDB().
|
||||
Where(h.readDB.Orders.UserID.Eq(userID)).
|
||||
Where(h.readDB.Orders.Status.Eq(2)).
|
||||
Where(h.readDB.Orders.CreatedAt.Gte(start)).
|
||||
Where(h.readDB.Orders.CreatedAt.Lte(end))
|
||||
|
||||
total, err := orderQ.Count()
|
||||
if err != nil {
|
||||
ctx.AbortWithError(core.Error(http.StatusBadRequest, 20108, err.Error()))
|
||||
return
|
||||
}
|
||||
|
||||
// 分页查询订单
|
||||
orders, err := orderQ.Order(h.readDB.Orders.CreatedAt.Desc()).
|
||||
Offset((req.Page - 1) * req.PageSize).Limit(req.PageSize).Find()
|
||||
if err != nil {
|
||||
ctx.AbortWithError(core.Error(http.StatusBadRequest, 20108, err.Error()))
|
||||
return
|
||||
}
|
||||
|
||||
// 收集订单ID
|
||||
orderIDs := make([]int64, len(orders))
|
||||
orderNos := make([]string, len(orders))
|
||||
for i, o := range orders {
|
||||
orderIDs[i] = o.ID
|
||||
orderNos[i] = o.OrderNo
|
||||
}
|
||||
|
||||
// 批量查询退款信息
|
||||
refundMap := make(map[string]int64)
|
||||
if len(orderNos) > 0 {
|
||||
type refundRow struct {
|
||||
OrderNo string
|
||||
Amount int64
|
||||
}
|
||||
var refunds []refundRow
|
||||
_ = h.repo.GetDbR().Raw(`
|
||||
SELECT order_no, COALESCE(SUM(amount_refund), 0) as amount
|
||||
FROM payment_refunds
|
||||
WHERE order_no IN ? AND status = 'SUCCESS'
|
||||
GROUP BY order_no
|
||||
`, orderNos).Scan(&refunds).Error
|
||||
for _, r := range refunds {
|
||||
refundMap[r.OrderNo] = r.Amount
|
||||
}
|
||||
}
|
||||
|
||||
// 批量查询库存价值(获得的奖品)
|
||||
prizeValueMap := make(map[int64]int64)
|
||||
prizeNameMap := make(map[int64]string)
|
||||
if len(orderIDs) > 0 {
|
||||
type prizeRow struct {
|
||||
OrderID int64
|
||||
Value int64
|
||||
Name string
|
||||
}
|
||||
var prizes []prizeRow
|
||||
_ = h.repo.GetDbR().Raw(`
|
||||
SELECT ui.order_id, COALESCE(SUM(p.price), 0) as value,
|
||||
GROUP_CONCAT(p.name SEPARATOR ', ') as name
|
||||
FROM user_inventory ui
|
||||
LEFT JOIN products p ON p.id = ui.product_id
|
||||
WHERE ui.order_id IN ?
|
||||
GROUP BY ui.order_id
|
||||
`, orderIDs).Scan(&prizes).Error
|
||||
for _, p := range prizes {
|
||||
prizeValueMap[p.OrderID] = p.Value
|
||||
prizeNameMap[p.OrderID] = p.Name
|
||||
}
|
||||
}
|
||||
|
||||
// 批量查询使用的优惠券
|
||||
couponValueMap := make(map[int64]int64)
|
||||
couponNameMap := make(map[int64]string)
|
||||
if len(orderIDs) > 0 {
|
||||
type couponRow struct {
|
||||
OrderID int64
|
||||
Value int64
|
||||
Name string
|
||||
}
|
||||
var coupons []couponRow
|
||||
_ = h.repo.GetDbR().Raw(`
|
||||
SELECT ucu.order_id, COALESCE(SUM(ABS(ucu.change_amount)), 0) as value,
|
||||
GROUP_CONCAT(DISTINCT sc.name SEPARATOR ', ') as name
|
||||
FROM user_coupon_usage ucu
|
||||
LEFT JOIN user_coupons uc ON uc.id = ucu.user_coupon_id
|
||||
LEFT JOIN system_coupons sc ON sc.id = uc.coupon_id
|
||||
WHERE ucu.order_id IN ?
|
||||
GROUP BY ucu.order_id
|
||||
`, orderIDs).Scan(&coupons).Error
|
||||
for _, c := range coupons {
|
||||
couponValueMap[c.OrderID] = c.Value
|
||||
couponNameMap[c.OrderID] = c.Name
|
||||
}
|
||||
}
|
||||
|
||||
// 批量查询活动信息
|
||||
activityNameMap := make(map[int64]string)
|
||||
if len(orderIDs) > 0 {
|
||||
type actRow struct {
|
||||
OrderID int64
|
||||
ActivityName string
|
||||
}
|
||||
var acts []actRow
|
||||
_ = h.repo.GetDbR().Raw(`
|
||||
SELECT o.id as order_id, a.name as activity_name
|
||||
FROM orders o
|
||||
LEFT JOIN activities a ON a.id = o.activity_id
|
||||
WHERE o.id IN ? AND o.activity_id > 0
|
||||
`, orderIDs).Scan(&acts).Error
|
||||
for _, a := range acts {
|
||||
activityNameMap[a.OrderID] = a.ActivityName
|
||||
}
|
||||
}
|
||||
|
||||
// 组装明细数据
|
||||
list := make([]profitLossDetailItem, len(orders))
|
||||
var totalCost, totalValue int64
|
||||
|
||||
for i, o := range orders {
|
||||
refund := refundMap[o.OrderNo]
|
||||
prizeValue := prizeValueMap[o.ID]
|
||||
couponValue := couponValueMap[o.ID]
|
||||
netCost := o.ActualAmount - refund
|
||||
netProfit := prizeValue - netCost
|
||||
|
||||
list[i] = profitLossDetailItem{
|
||||
OrderID: o.ID,
|
||||
OrderNo: o.OrderNo,
|
||||
CreatedAt: o.CreatedAt.Format("2006-01-02 15:04:05"),
|
||||
SourceType: o.SourceType,
|
||||
ActivityName: activityNameMap[o.ID],
|
||||
ActualAmount: o.ActualAmount,
|
||||
RefundAmount: refund,
|
||||
NetCost: netCost,
|
||||
PrizeValue: prizeValue,
|
||||
PrizeName: prizeNameMap[o.ID],
|
||||
PointsEarned: 0, // 简化处理
|
||||
PointsValue: 0,
|
||||
CouponUsedValue: couponValue,
|
||||
CouponUsedName: couponNameMap[o.ID],
|
||||
ItemCardUsed: "", // 从订单备注中解析
|
||||
ItemCardValue: 0,
|
||||
NetProfit: netProfit,
|
||||
}
|
||||
|
||||
// 解析道具卡信息(从订单备注)
|
||||
if o.Remark != "" {
|
||||
list[i].ItemCardUsed = parseItemCardFromRemark(o.Remark)
|
||||
}
|
||||
|
||||
totalCost += netCost
|
||||
totalValue += prizeValue
|
||||
}
|
||||
|
||||
resp := profitLossDetailsResponse{
|
||||
Page: req.Page,
|
||||
PageSize: req.PageSize,
|
||||
Total: total,
|
||||
List: list,
|
||||
}
|
||||
resp.Summary.TotalCost = totalCost
|
||||
resp.Summary.TotalValue = totalValue
|
||||
resp.Summary.TotalProfit = totalValue - totalCost
|
||||
|
||||
ctx.Payload(resp)
|
||||
}
|
||||
}
|
||||
|
||||
// 从订单备注中解析道具卡信息
|
||||
func parseItemCardFromRemark(remark string) string {
|
||||
// 格式: itemcard:xxx|...
|
||||
if len(remark) == 0 {
|
||||
return ""
|
||||
}
|
||||
idx := 0
|
||||
for i := 0; i < len(remark); i++ {
|
||||
if remark[i:] == "itemcard:" || (i+9 <= len(remark) && remark[i:i+9] == "itemcard:") {
|
||||
idx = i
|
||||
break
|
||||
}
|
||||
}
|
||||
if idx == 0 && len(remark) < 9 {
|
||||
return ""
|
||||
}
|
||||
if idx+9 >= len(remark) {
|
||||
return ""
|
||||
}
|
||||
seg := remark[idx+9:]
|
||||
// 找到 | 分隔符
|
||||
end := len(seg)
|
||||
for i := 0; i < len(seg); i++ {
|
||||
if seg[i] == '|' {
|
||||
end = i
|
||||
break
|
||||
}
|
||||
}
|
||||
return seg[:end]
|
||||
}
|
||||
|
||||
@ -38,13 +38,13 @@ type listAppProductsRequest struct {
|
||||
}
|
||||
|
||||
type listAppProductsItem struct {
|
||||
ID int64 `json:"id"`
|
||||
Name string `json:"name"`
|
||||
MainImage string `json:"main_image"`
|
||||
Price int64 `json:"price"`
|
||||
PointsRequired int64 `json:"points_required"`
|
||||
Sales int64 `json:"sales"`
|
||||
InStock bool `json:"in_stock"`
|
||||
ID int64 `json:"id"`
|
||||
Name string `json:"name"`
|
||||
MainImage string `json:"main_image"`
|
||||
Price int64 `json:"price"`
|
||||
PointsRequired float64 `json:"points_required"` // 积分(分/rate)`
|
||||
Sales int64 `json:"sales"`
|
||||
InStock bool `json:"in_stock"`
|
||||
}
|
||||
|
||||
type listAppProductsResponse struct {
|
||||
@ -87,7 +87,7 @@ func (h *productHandler) ListProductsForApp() core.HandlerFunc {
|
||||
}
|
||||
rsp := &listAppProductsResponse{Total: total, CurrentPage: req.Page, PageSize: req.PageSize, List: make([]listAppProductsItem, len(items))}
|
||||
for i, it := range items {
|
||||
pts, _ := h.user.CentsToPoints(ctx.RequestContext(), it.Price)
|
||||
pts := h.user.CentsToPointsFloat(ctx.RequestContext(), it.Price)
|
||||
rsp.List[i] = listAppProductsItem{ID: it.ID, Name: it.Name, MainImage: it.MainImage, Price: it.Price, PointsRequired: pts, Sales: it.Sales, InStock: it.InStock}
|
||||
}
|
||||
ctx.Payload(rsp)
|
||||
@ -99,7 +99,7 @@ type getAppProductDetailResponse struct {
|
||||
Name string `json:"name"`
|
||||
Album []string `json:"album"`
|
||||
Price int64 `json:"price"`
|
||||
PointsRequired int64 `json:"points_required"`
|
||||
PointsRequired float64 `json:"points_required"` // 积分(分/rate)`
|
||||
Sales int64 `json:"sales"`
|
||||
Stock int64 `json:"stock"`
|
||||
Description string `json:"description"`
|
||||
@ -135,10 +135,10 @@ func (h *productHandler) GetProductDetailForApp() core.HandlerFunc {
|
||||
ctx.AbortWithError(core.Error(http.StatusBadRequest, code.ServerError, validation.Error(err)))
|
||||
return
|
||||
}
|
||||
ptsDetail, _ := h.user.CentsToPoints(ctx.RequestContext(), d.Price)
|
||||
ptsDetail := h.user.CentsToPointsFloat(ctx.RequestContext(), d.Price)
|
||||
rsp := &getAppProductDetailResponse{ID: d.ID, Name: d.Name, Album: d.Album, Price: d.Price, PointsRequired: ptsDetail, Sales: d.Sales, Stock: d.Stock, Description: d.Description, Service: d.Service, Recommendations: make([]listAppProductsItem, len(d.Recommendations))}
|
||||
for i, it := range d.Recommendations {
|
||||
ptsRec, _ := h.user.CentsToPoints(ctx.RequestContext(), it.Price)
|
||||
ptsRec := h.user.CentsToPointsFloat(ctx.RequestContext(), it.Price)
|
||||
rsp.Recommendations[i] = listAppProductsItem{ID: it.ID, Name: it.Name, MainImage: it.MainImage, Price: it.Price, PointsRequired: ptsRec, Sales: it.Sales, InStock: it.InStock}
|
||||
}
|
||||
ctx.Payload(rsp)
|
||||
|
||||
@ -25,21 +25,24 @@ type listStoreItemsRequest struct {
|
||||
Kind string `form:"kind"`
|
||||
Page int `form:"page"`
|
||||
PageSize int `form:"page_size"`
|
||||
Keyword string `form:"keyword"` // 关键词搜索
|
||||
PriceMin *int64 `form:"price_min"` // 最低积分价格(积分单位)
|
||||
PriceMax *int64 `form:"price_max"` // 最高积分价格(积分单位)
|
||||
}
|
||||
|
||||
type listStoreItem struct {
|
||||
ID int64 `json:"id"`
|
||||
Kind string `json:"kind"`
|
||||
Name string `json:"name"`
|
||||
MainImage string `json:"main_image"`
|
||||
Price int64 `json:"price"`
|
||||
PointsRequired int64 `json:"points_required"`
|
||||
InStock bool `json:"in_stock"`
|
||||
Status int32 `json:"status"`
|
||||
DiscountType int32 `json:"discount_type"`
|
||||
DiscountValue int64 `json:"discount_value"`
|
||||
MinSpend int64 `json:"min_spend"`
|
||||
Supported bool `json:"supported"`
|
||||
ID int64 `json:"id"`
|
||||
Kind string `json:"kind"`
|
||||
Name string `json:"name"`
|
||||
MainImage string `json:"main_image"`
|
||||
Price int64 `json:"price"`
|
||||
PointsRequired float64 `json:"points_required"` // 积分(分/rate)`
|
||||
InStock bool `json:"in_stock"`
|
||||
Status int32 `json:"status"`
|
||||
DiscountType int32 `json:"discount_type"`
|
||||
DiscountValue int64 `json:"discount_value"`
|
||||
MinSpend int64 `json:"min_spend"`
|
||||
Supported bool `json:"supported"`
|
||||
}
|
||||
|
||||
type listStoreItemsResponse struct {
|
||||
@ -83,32 +86,76 @@ func (h *storeHandler) ListStoreItemsForApp() core.HandlerFunc {
|
||||
offset := (req.Page - 1) * req.PageSize
|
||||
limit := req.PageSize
|
||||
|
||||
// 将积分价格转换为分进行查询
|
||||
var priceMinCents, priceMaxCents int64
|
||||
if req.PriceMin != nil && *req.PriceMin > 0 {
|
||||
centsVal, _ := h.user.PointsToCents(ctx.RequestContext(), *req.PriceMin)
|
||||
priceMinCents = centsVal
|
||||
}
|
||||
if req.PriceMax != nil && *req.PriceMax > 0 {
|
||||
centsVal, _ := h.user.PointsToCents(ctx.RequestContext(), *req.PriceMax)
|
||||
priceMaxCents = centsVal
|
||||
}
|
||||
|
||||
switch req.Kind {
|
||||
case "item_card":
|
||||
q := h.readDB.SystemItemCards.WithContext(ctx.RequestContext()).ReadDB().Where(h.readDB.SystemItemCards.Status.Eq(1))
|
||||
// 关键词筛选
|
||||
if req.Keyword != "" {
|
||||
q = q.Where(h.readDB.SystemItemCards.Name.Like("%" + req.Keyword + "%"))
|
||||
}
|
||||
// 价格区间筛选
|
||||
if priceMinCents > 0 {
|
||||
q = q.Where(h.readDB.SystemItemCards.Price.Gte(priceMinCents))
|
||||
}
|
||||
if priceMaxCents > 0 {
|
||||
q = q.Where(h.readDB.SystemItemCards.Price.Lte(priceMaxCents))
|
||||
}
|
||||
total, _ = q.Count()
|
||||
rows, _ := q.Order(h.readDB.SystemItemCards.ID.Desc()).Offset(offset).Limit(limit).Find()
|
||||
list = make([]listStoreItem, len(rows))
|
||||
for i, it := range rows {
|
||||
pts, _ := h.user.CentsToPoints(ctx.RequestContext(), it.Price)
|
||||
pts := h.user.CentsToPointsFloat(ctx.RequestContext(), it.Price)
|
||||
list[i] = listStoreItem{ID: it.ID, Kind: "item_card", Name: it.Name, Price: it.Price, PointsRequired: pts, Status: it.Status, Supported: true}
|
||||
}
|
||||
case "coupon":
|
||||
q := h.readDB.SystemCoupons.WithContext(ctx.RequestContext()).ReadDB().Where(h.readDB.SystemCoupons.Status.Eq(1))
|
||||
// 关键词筛选
|
||||
if req.Keyword != "" {
|
||||
q = q.Where(h.readDB.SystemCoupons.Name.Like("%" + req.Keyword + "%"))
|
||||
}
|
||||
// 价格区间筛选 (优惠券用 DiscountValue)
|
||||
if priceMinCents > 0 {
|
||||
q = q.Where(h.readDB.SystemCoupons.DiscountValue.Gte(priceMinCents))
|
||||
}
|
||||
if priceMaxCents > 0 {
|
||||
q = q.Where(h.readDB.SystemCoupons.DiscountValue.Lte(priceMaxCents))
|
||||
}
|
||||
total, _ = q.Count()
|
||||
rows, _ := q.Order(h.readDB.SystemCoupons.ID.Desc()).Offset(offset).Limit(limit).Find()
|
||||
list = make([]listStoreItem, len(rows))
|
||||
for i, it := range rows {
|
||||
pts, _ := h.user.CentsToPoints(ctx.RequestContext(), it.DiscountValue)
|
||||
pts := h.user.CentsToPointsFloat(ctx.RequestContext(), it.DiscountValue)
|
||||
list[i] = listStoreItem{ID: it.ID, Kind: "coupon", Name: it.Name, DiscountType: it.DiscountType, DiscountValue: it.DiscountValue, PointsRequired: pts, MinSpend: it.MinSpend, Status: it.Status, Supported: it.DiscountType == 1}
|
||||
}
|
||||
default: // product
|
||||
q := h.readDB.Products.WithContext(ctx.RequestContext()).ReadDB().Where(h.readDB.Products.Status.Eq(1))
|
||||
// 关键词筛选
|
||||
if req.Keyword != "" {
|
||||
q = q.Where(h.readDB.Products.Name.Like("%" + req.Keyword + "%"))
|
||||
}
|
||||
// 价格区间筛选
|
||||
if priceMinCents > 0 {
|
||||
q = q.Where(h.readDB.Products.Price.Gte(priceMinCents))
|
||||
}
|
||||
if priceMaxCents > 0 {
|
||||
q = q.Where(h.readDB.Products.Price.Lte(priceMaxCents))
|
||||
}
|
||||
total, _ = q.Count()
|
||||
rows, _ := q.Order(h.readDB.Products.ID.Desc()).Offset(offset).Limit(limit).Find()
|
||||
list = make([]listStoreItem, len(rows))
|
||||
for i, it := range rows {
|
||||
pts, _ := h.user.CentsToPoints(ctx.RequestContext(), it.Price)
|
||||
pts := h.user.CentsToPointsFloat(ctx.RequestContext(), it.Price)
|
||||
list[i] = listStoreItem{ID: it.ID, Kind: "product", Name: it.Name, MainImage: parseFirstImage(it.ImagesJSON), Price: it.Price, PointsRequired: pts, InStock: it.Stock > 0 && it.Status == 1, Status: it.Status, Supported: true}
|
||||
}
|
||||
}
|
||||
|
||||
38
internal/api/common/config.go
Normal file
38
internal/api/common/config.go
Normal file
@ -0,0 +1,38 @@
|
||||
package common
|
||||
|
||||
import (
|
||||
"bindbox-game/internal/pkg/core"
|
||||
)
|
||||
|
||||
type ConfigResponse struct {
|
||||
SubscribeTemplates map[string]string `json:"subscribe_templates"`
|
||||
}
|
||||
|
||||
// GetPublicConfig 获取公开配置(包含订阅模板ID)
|
||||
// @Summary 获取公开配置
|
||||
// @Description 获取小程序前端需要用到的公开配置,如订阅消息模板ID
|
||||
// @Tags 公共
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Success 200 {object} ConfigResponse
|
||||
// @Router /api/app/config/public [get]
|
||||
func (h *handler) GetPublicConfig() core.HandlerFunc {
|
||||
return func(ctx core.Context) {
|
||||
// 查询订阅消息模板 ID
|
||||
var val string
|
||||
cfg, err := h.readDB.SystemConfigs.WithContext(ctx.RequestContext()).
|
||||
Where(h.readDB.SystemConfigs.ConfigKey.Eq("wechat.lottery_result_template_id")).
|
||||
First()
|
||||
if err == nil && cfg != nil {
|
||||
val = cfg.ConfigValue
|
||||
}
|
||||
|
||||
rsp := ConfigResponse{
|
||||
SubscribeTemplates: map[string]string{
|
||||
"lottery_result": val,
|
||||
},
|
||||
}
|
||||
|
||||
ctx.Payload(rsp)
|
||||
}
|
||||
}
|
||||
@ -1,12 +1,12 @@
|
||||
package app
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"net/http"
|
||||
|
||||
"bindbox-game/internal/code"
|
||||
"bindbox-game/internal/pkg/core"
|
||||
"bindbox-game/internal/pkg/validation"
|
||||
"bindbox-game/internal/repository/mysql/model"
|
||||
"bindbox-game/internal/code"
|
||||
"bindbox-game/internal/pkg/core"
|
||||
"bindbox-game/internal/pkg/validation"
|
||||
"bindbox-game/internal/repository/mysql/model"
|
||||
)
|
||||
|
||||
type listPointsRequest struct {
|
||||
@ -20,7 +20,7 @@ type listPointsResponse struct {
|
||||
List []*model.UserPointsLedger `json:"list"`
|
||||
}
|
||||
type pointsBalanceResponse struct {
|
||||
Balance int64 `json:"balance"`
|
||||
Balance float64 `json:"balance"` // 积分(分/rate)
|
||||
}
|
||||
|
||||
// ListUserPoints 查看用户积分记录
|
||||
@ -29,8 +29,8 @@ type pointsBalanceResponse struct {
|
||||
// @Tags APP端.用户
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param user_id path integer true "用户ID"
|
||||
// @Security LoginVerifyToken
|
||||
// @Param user_id path integer true "用户ID"
|
||||
// @Security LoginVerifyToken
|
||||
// @Param page query int true "页码" default(1)
|
||||
// @Param page_size query int true "每页数量,最多100" default(20)
|
||||
// @Success 200 {object} listPointsResponse
|
||||
@ -44,8 +44,8 @@ func (h *handler) ListUserPoints() core.HandlerFunc {
|
||||
ctx.AbortWithError(core.Error(http.StatusBadRequest, code.ParamBindError, validation.Error(err)))
|
||||
return
|
||||
}
|
||||
userID := int64(ctx.SessionUserInfo().Id)
|
||||
items, total, err := h.user.ListPointsLedger(ctx.RequestContext(), userID, req.Page, req.PageSize)
|
||||
userID := int64(ctx.SessionUserInfo().Id)
|
||||
items, total, err := h.user.ListPointsLedger(ctx.RequestContext(), userID, req.Page, req.PageSize)
|
||||
if err != nil {
|
||||
ctx.AbortWithError(core.Error(http.StatusBadRequest, 10004, err.Error()))
|
||||
return
|
||||
@ -64,21 +64,21 @@ func (h *handler) ListUserPoints() core.HandlerFunc {
|
||||
// @Tags APP端.用户
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param user_id path integer true "用户ID"
|
||||
// @Security LoginVerifyToken
|
||||
// @Param user_id path integer true "用户ID"
|
||||
// @Security LoginVerifyToken
|
||||
// @Success 200 {object} pointsBalanceResponse
|
||||
// @Failure 400 {object} code.Failure
|
||||
// @Router /api/app/users/{user_id}/points/balance [get]
|
||||
func (h *handler) GetUserPointsBalance() core.HandlerFunc {
|
||||
return func(ctx core.Context) {
|
||||
rsp := new(pointsBalanceResponse)
|
||||
userID := int64(ctx.SessionUserInfo().Id)
|
||||
total, err := h.user.GetPointsBalance(ctx.RequestContext(), userID)
|
||||
userID := int64(ctx.SessionUserInfo().Id)
|
||||
total, err := h.user.GetPointsBalance(ctx.RequestContext(), userID)
|
||||
if err != nil {
|
||||
ctx.AbortWithError(core.Error(http.StatusBadRequest, 10005, err.Error()))
|
||||
return
|
||||
}
|
||||
rsp.Balance = total
|
||||
rsp.Balance = h.user.CentsToPointsFloat(ctx.RequestContext(), total)
|
||||
ctx.Payload(rsp)
|
||||
}
|
||||
}
|
||||
|
||||
@ -52,13 +52,19 @@ func (h *handler) RedeemPointsToCoupon() core.HandlerFunc {
|
||||
ctx.AbortWithError(core.Error(http.StatusBadRequest, 150002, "only amount coupons supported"))
|
||||
return
|
||||
}
|
||||
needPoints, _ := h.user.CentsToPoints(ctx.RequestContext(), sc.DiscountValue)
|
||||
if needPoints <= 0 {
|
||||
needPoints = 1
|
||||
// sc.DiscountValue 是优惠券面值(分),直接用于扣除
|
||||
// 例如:30 元优惠券 = 3000 分
|
||||
needCents := sc.DiscountValue
|
||||
if needCents <= 0 {
|
||||
needCents = 1
|
||||
}
|
||||
ledgerID, err := h.user.ConsumePointsFor(ctx.RequestContext(), userID, needPoints, "system_coupons", strconv.FormatInt(req.CouponID, 10), "redeem coupon", "redeem_coupon")
|
||||
ledgerID, err := h.user.ConsumePointsFor(ctx.RequestContext(), userID, needCents, "system_coupons", strconv.FormatInt(req.CouponID, 10), "redeem coupon", "redeem_coupon")
|
||||
if err != nil {
|
||||
ctx.AbortWithError(core.Error(http.StatusBadRequest, 150003, err.Error()))
|
||||
errMsg := err.Error()
|
||||
if errMsg == "insufficient_points" {
|
||||
errMsg = "积分不足,无法兑换"
|
||||
}
|
||||
ctx.AbortWithError(core.Error(http.StatusBadRequest, 150003, errMsg))
|
||||
return
|
||||
}
|
||||
if err := h.user.AddCoupon(ctx.RequestContext(), userID, req.CouponID); err != nil {
|
||||
|
||||
@ -59,12 +59,13 @@ func (h *handler) RedeemPointsToProduct() core.HandlerFunc {
|
||||
ctx.AbortWithError(core.Error(http.StatusBadRequest, 150105, "商品库存不足,请联系客服处理"))
|
||||
return
|
||||
}
|
||||
ptsPerUnit, _ := h.user.CentsToPoints(ctx.RequestContext(), prod.Price)
|
||||
needPoints := ptsPerUnit * int64(req.Quantity)
|
||||
if needPoints <= 0 {
|
||||
needPoints = 1
|
||||
// prod.Price 是商品价格(分),直接用于扣除
|
||||
// 例如:30 元商品 = 3000 分
|
||||
needCents := prod.Price * int64(req.Quantity)
|
||||
if needCents <= 0 {
|
||||
needCents = 1
|
||||
}
|
||||
ledgerID, err := h.user.ConsumePointsFor(ctx.RequestContext(), userID, needPoints, "products", strconv.FormatInt(req.ProductID, 10), "redeem product", "redeem_product")
|
||||
ledgerID, err := h.user.ConsumePointsFor(ctx.RequestContext(), userID, needCents, "products", strconv.FormatInt(req.ProductID, 10), "redeem product", "redeem_product")
|
||||
if err != nil {
|
||||
errMsg := err.Error()
|
||||
if errMsg == "insufficient_points" {
|
||||
@ -73,7 +74,7 @@ func (h *handler) RedeemPointsToProduct() core.HandlerFunc {
|
||||
ctx.AbortWithError(core.Error(http.StatusBadRequest, 150102, errMsg))
|
||||
return
|
||||
}
|
||||
resp, err := h.user.GrantReward(ctx.RequestContext(), userID, usersvc.GrantRewardRequest{ProductID: req.ProductID, Quantity: req.Quantity, Remark: prod.Name, PointsAmount: needPoints})
|
||||
resp, err := h.user.GrantReward(ctx.RequestContext(), userID, usersvc.GrantRewardRequest{ProductID: req.ProductID, Quantity: req.Quantity, Remark: prod.Name, PointsAmount: needCents})
|
||||
if err != nil {
|
||||
ctx.AbortWithError(core.Error(http.StatusBadRequest, 150103, err.Error()))
|
||||
return
|
||||
|
||||
@ -35,15 +35,18 @@ func (h *handler) GetUserProfile() core.HandlerFunc {
|
||||
}
|
||||
|
||||
balance, _ := h.user.GetPointsBalance(ctx.RequestContext(), userID)
|
||||
// 转换为积分(浮点)用于显示
|
||||
balancePoints := h.user.CentsToPointsFloat(ctx.RequestContext(), balance)
|
||||
|
||||
res := userItem{
|
||||
ID: user.ID,
|
||||
Nickname: user.Nickname,
|
||||
Avatar: user.Avatar,
|
||||
InviteCode: user.InviteCode,
|
||||
InviterID: user.InviterID,
|
||||
Mobile: phone,
|
||||
Balance: balance,
|
||||
ID: user.ID,
|
||||
Nickname: user.Nickname,
|
||||
Avatar: user.Avatar,
|
||||
InviteCode: user.InviteCode,
|
||||
InviterID: user.InviterID,
|
||||
Mobile: phone,
|
||||
DouyinUserID: user.DouyinUserID,
|
||||
Balance: balancePoints,
|
||||
}
|
||||
ctx.Payload(res)
|
||||
}
|
||||
@ -54,13 +57,14 @@ type modifyUserRequest struct {
|
||||
Avatar *string `json:"avatar"`
|
||||
}
|
||||
type userItem struct {
|
||||
ID int64 `json:"id"`
|
||||
Nickname string `json:"nickname"`
|
||||
Avatar string `json:"avatar"`
|
||||
InviteCode string `json:"invite_code"`
|
||||
InviterID int64 `json:"inviter_id"`
|
||||
Mobile string `json:"mobile"`
|
||||
Balance int64 `json:"balance"` // Points
|
||||
ID int64 `json:"id"`
|
||||
Nickname string `json:"nickname"`
|
||||
Avatar string `json:"avatar"`
|
||||
InviteCode string `json:"invite_code"`
|
||||
InviterID int64 `json:"inviter_id"`
|
||||
Mobile string `json:"mobile"`
|
||||
DouyinUserID string `json:"douyin_user_id"`
|
||||
Balance float64 `json:"balance"` // 积分(分/rate)
|
||||
}
|
||||
type modifyUserResponse struct {
|
||||
User userItem `json:"user"`
|
||||
@ -101,15 +105,17 @@ func (h *handler) ModifyUser() core.HandlerFunc {
|
||||
}
|
||||
|
||||
balance, _ := h.user.GetPointsBalance(ctx.RequestContext(), userID)
|
||||
balancePoints := h.user.CentsToPointsFloat(ctx.RequestContext(), balance)
|
||||
|
||||
rsp.User = userItem{
|
||||
ID: item.ID,
|
||||
Nickname: item.Nickname,
|
||||
Avatar: item.Avatar,
|
||||
InviteCode: item.InviteCode,
|
||||
InviterID: item.InviterID,
|
||||
Mobile: maskedPhone,
|
||||
Balance: balance,
|
||||
ID: item.ID,
|
||||
Nickname: item.Nickname,
|
||||
Avatar: item.Avatar,
|
||||
InviteCode: item.InviteCode,
|
||||
InviterID: item.InviterID,
|
||||
Mobile: maskedPhone,
|
||||
DouyinUserID: item.DouyinUserID,
|
||||
Balance: balancePoints,
|
||||
}
|
||||
ctx.Payload(rsp)
|
||||
}
|
||||
|
||||
@ -200,6 +200,7 @@ type Mux interface {
|
||||
ServeHTTP(w http.ResponseWriter, req *http.Request)
|
||||
Group(relativePath string, handlers ...HandlerFunc) RouterGroup
|
||||
Routes() gin.RoutesInfo
|
||||
Engine() *gin.Engine
|
||||
}
|
||||
|
||||
type mux struct {
|
||||
@ -220,6 +221,10 @@ func (m *mux) Routes() gin.RoutesInfo {
|
||||
return m.engine.Routes()
|
||||
}
|
||||
|
||||
func (m *mux) Engine() *gin.Engine {
|
||||
return m.engine
|
||||
}
|
||||
|
||||
func New(logger logger.CustomLogger, options ...Option) (Mux, error) {
|
||||
if logger == nil {
|
||||
return nil, errors.New("logger required")
|
||||
|
||||
5
internal/pkg/env/env.go
vendored
5
internal/pkg/env/env.go
vendored
@ -3,6 +3,7 @@ package env
|
||||
import (
|
||||
"flag"
|
||||
"fmt"
|
||||
"os"
|
||||
"strings"
|
||||
"sync"
|
||||
)
|
||||
@ -65,6 +66,10 @@ func setup() {
|
||||
val = *envFlag
|
||||
}
|
||||
|
||||
if val == "" {
|
||||
val = os.Getenv("ACTIVE_ENV")
|
||||
}
|
||||
|
||||
switch strings.ToLower(strings.TrimSpace(val)) {
|
||||
case "dev":
|
||||
active = dev
|
||||
|
||||
66
internal/pkg/otel/middleware.go
Normal file
66
internal/pkg/otel/middleware.go
Normal file
@ -0,0 +1,66 @@
|
||||
package otel
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"go.opentelemetry.io/otel/attribute"
|
||||
"go.opentelemetry.io/otel/propagation"
|
||||
semconv "go.opentelemetry.io/otel/semconv/v1.37.0"
|
||||
"go.opentelemetry.io/otel/trace"
|
||||
)
|
||||
|
||||
// Middleware 返回 Gin 中间件,用于自动创建 span
|
||||
func Middleware(serviceName string) gin.HandlerFunc {
|
||||
return func(c *gin.Context) {
|
||||
// 从请求头提取 trace context
|
||||
ctx := c.Request.Context()
|
||||
propagator := propagation.NewCompositeTextMapPropagator(
|
||||
propagation.TraceContext{},
|
||||
propagation.Baggage{},
|
||||
)
|
||||
ctx = propagator.Extract(ctx, propagation.HeaderCarrier(c.Request.Header))
|
||||
|
||||
// 创建 span
|
||||
spanName := c.Request.Method + " " + c.FullPath()
|
||||
if c.FullPath() == "" {
|
||||
spanName = c.Request.Method + " " + c.Request.URL.Path
|
||||
}
|
||||
|
||||
ctx, span := Tracer().Start(ctx, spanName,
|
||||
trace.WithSpanKind(trace.SpanKindServer),
|
||||
trace.WithAttributes(
|
||||
semconv.HTTPRequestMethodKey.String(c.Request.Method),
|
||||
semconv.URLFull(c.Request.URL.String()),
|
||||
semconv.HTTPRoute(c.FullPath()),
|
||||
semconv.ServerAddress(c.Request.Host),
|
||||
attribute.String("http.client_ip", c.ClientIP()),
|
||||
),
|
||||
)
|
||||
defer span.End()
|
||||
|
||||
// 将新的 context 放入请求
|
||||
c.Request = c.Request.WithContext(ctx)
|
||||
|
||||
// 记录开始时间
|
||||
start := time.Now()
|
||||
|
||||
// 执行后续处理
|
||||
c.Next()
|
||||
|
||||
// 记录响应信息
|
||||
duration := time.Since(start)
|
||||
statusCode := c.Writer.Status()
|
||||
|
||||
span.SetAttributes(
|
||||
semconv.HTTPResponseStatusCode(statusCode),
|
||||
attribute.Int64("http.response_size", int64(c.Writer.Size())),
|
||||
attribute.Float64("http.duration_ms", float64(duration.Milliseconds())),
|
||||
)
|
||||
|
||||
// 如果有错误,记录错误信息
|
||||
if len(c.Errors) > 0 {
|
||||
span.SetAttributes(attribute.String("error.message", c.Errors.String()))
|
||||
}
|
||||
}
|
||||
}
|
||||
114
internal/pkg/otel/otel.go
Normal file
114
internal/pkg/otel/otel.go
Normal file
@ -0,0 +1,114 @@
|
||||
// Package otel 提供 OpenTelemetry 链路追踪功能
|
||||
package otel
|
||||
|
||||
import (
|
||||
"context"
|
||||
"time"
|
||||
|
||||
"go.opentelemetry.io/otel"
|
||||
"go.opentelemetry.io/otel/attribute"
|
||||
"go.opentelemetry.io/otel/exporters/otlp/otlptrace"
|
||||
"go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp"
|
||||
"go.opentelemetry.io/otel/propagation"
|
||||
"go.opentelemetry.io/otel/sdk/resource"
|
||||
sdktrace "go.opentelemetry.io/otel/sdk/trace"
|
||||
semconv "go.opentelemetry.io/otel/semconv/v1.37.0"
|
||||
"go.opentelemetry.io/otel/trace"
|
||||
)
|
||||
|
||||
var tracer trace.Tracer
|
||||
|
||||
// Config OpenTelemetry 配置
|
||||
type Config struct {
|
||||
ServiceName string
|
||||
ServiceVersion string
|
||||
Environment string
|
||||
Endpoint string // Tempo OTLP HTTP endpoint, e.g., "tempo:4318"
|
||||
Enabled bool
|
||||
}
|
||||
|
||||
// Init 初始化 OpenTelemetry
|
||||
// 返回 shutdown 函数,在程序退出时调用
|
||||
func Init(cfg Config) (func(context.Context) error, error) {
|
||||
if !cfg.Enabled {
|
||||
// 如果未启用,返回空的 shutdown 函数
|
||||
tracer = otel.Tracer(cfg.ServiceName)
|
||||
return func(ctx context.Context) error { return nil }, nil
|
||||
}
|
||||
|
||||
ctx := context.Background()
|
||||
|
||||
// 创建 OTLP HTTP exporter
|
||||
client := otlptracehttp.NewClient(
|
||||
otlptracehttp.WithEndpoint(cfg.Endpoint),
|
||||
otlptracehttp.WithInsecure(), // 内网使用,不需要 TLS
|
||||
)
|
||||
exporter, err := otlptrace.New(ctx, client)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// 创建 resource
|
||||
res, err := resource.Merge(
|
||||
resource.Default(),
|
||||
resource.NewWithAttributes(
|
||||
semconv.SchemaURL,
|
||||
semconv.ServiceName(cfg.ServiceName),
|
||||
semconv.ServiceVersion(cfg.ServiceVersion),
|
||||
attribute.String("environment", cfg.Environment),
|
||||
),
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// 创建 TracerProvider
|
||||
tp := sdktrace.NewTracerProvider(
|
||||
sdktrace.WithBatcher(exporter,
|
||||
sdktrace.WithBatchTimeout(5*time.Second),
|
||||
),
|
||||
sdktrace.WithResource(res),
|
||||
sdktrace.WithSampler(sdktrace.AlwaysSample()), // 生产环境可改为采样
|
||||
)
|
||||
|
||||
// 设置全局 TracerProvider 和 Propagator
|
||||
otel.SetTracerProvider(tp)
|
||||
otel.SetTextMapPropagator(propagation.NewCompositeTextMapPropagator(
|
||||
propagation.TraceContext{},
|
||||
propagation.Baggage{},
|
||||
))
|
||||
|
||||
tracer = tp.Tracer(cfg.ServiceName)
|
||||
|
||||
return tp.Shutdown, nil
|
||||
}
|
||||
|
||||
// Tracer 获取全局 Tracer
|
||||
func Tracer() trace.Tracer {
|
||||
if tracer == nil {
|
||||
tracer = otel.Tracer("bindbox-game")
|
||||
}
|
||||
return tracer
|
||||
}
|
||||
|
||||
// StartSpan 开始一个新的 span
|
||||
func StartSpan(ctx context.Context, name string, opts ...trace.SpanStartOption) (context.Context, trace.Span) {
|
||||
return Tracer().Start(ctx, name, opts...)
|
||||
}
|
||||
|
||||
// SpanFromContext 从 context 获取当前 span
|
||||
func SpanFromContext(ctx context.Context) trace.Span {
|
||||
return trace.SpanFromContext(ctx)
|
||||
}
|
||||
|
||||
// AddEvent 为当前 span 添加事件
|
||||
func AddEvent(ctx context.Context, name string, attrs ...attribute.KeyValue) {
|
||||
span := trace.SpanFromContext(ctx)
|
||||
span.AddEvent(name, trace.WithAttributes(attrs...))
|
||||
}
|
||||
|
||||
// SetError 设置 span 错误状态
|
||||
func SetError(ctx context.Context, err error) {
|
||||
span := trace.SpanFromContext(ctx)
|
||||
span.RecordError(err)
|
||||
}
|
||||
@ -1,19 +1,25 @@
|
||||
package points
|
||||
|
||||
func CentsToPoints(cents int64, rate int64) int64 {
|
||||
if cents <= 0 || rate <= 0 { return 0 }
|
||||
return cents * rate
|
||||
import "math"
|
||||
|
||||
// CentsToPoints converts monetary value (in cents) to points based on the exchange rate (X Points per 1 Yuan).
|
||||
// Now: 1 Yuan = 100 Cents.
|
||||
// If Rate = 1 (1 Point = 1 Yuan), then 100 Cents = 1 Point.
|
||||
// Formula: points = (cents * rate) / 100
|
||||
func CentsToPoints(cents int64, rate float64) int64 {
|
||||
if rate <= 0 {
|
||||
rate = 1
|
||||
}
|
||||
// Use rounding to avoid precision loss on division
|
||||
return int64(math.Round((float64(cents) * rate) / 100.0))
|
||||
}
|
||||
|
||||
func PointsToCents(points int64, rate int64) int64 {
|
||||
if points <= 0 || rate <= 0 { return 0 }
|
||||
return points / rate
|
||||
// PointsToCents converts points to monetary value (in cents).
|
||||
// If Rate = 1 (1 Point = 1 Yuan), then 1 Point = 100 Cents.
|
||||
// Formula: cents = (points * 100) / rate
|
||||
func PointsToCents(points int64, rate float64) int64 {
|
||||
if rate <= 0 {
|
||||
rate = 1
|
||||
}
|
||||
return int64(math.Round((float64(points) * 100.0) / rate))
|
||||
}
|
||||
|
||||
func RefundPointsAmount(pointsAmountCents int64, refundedCents int64, totalPaidCents int64, rate int64) int64 {
|
||||
if pointsAmountCents <= 0 || refundedCents <= 0 || totalPaidCents <= 0 || rate <= 0 { return 0 }
|
||||
if refundedCents > totalPaidCents { refundedCents = totalPaidCents }
|
||||
targetCents := (pointsAmountCents * refundedCents) / totalPaidCents
|
||||
return targetCents / 100
|
||||
}
|
||||
|
||||
|
||||
@ -3,20 +3,22 @@ package points
|
||||
import "testing"
|
||||
|
||||
func TestCentsToPoints_DefaultRate(t *testing.T) {
|
||||
if got := CentsToPoints(12345, 1); got != 12345 {
|
||||
t.Fatalf("expected 12345, got %d", got)
|
||||
}
|
||||
if got := CentsToPoints(100, 1); got != 1 {
|
||||
t.Fatalf("expected 1, got %d", got)
|
||||
}
|
||||
}
|
||||
|
||||
func TestPointsToCents_DefaultRate(t *testing.T) {
|
||||
if got := PointsToCents(100, 1); got != 100 {
|
||||
t.Fatalf("expected 100, got %d", got)
|
||||
}
|
||||
if got := PointsToCents(1, 1); got != 100 {
|
||||
t.Fatalf("expected 100, got %d", got)
|
||||
}
|
||||
}
|
||||
|
||||
func TestRefundPointsAmount(t *testing.T) {
|
||||
pts := RefundPointsAmount(5000, 2500, 10000, 1)
|
||||
if pts != 12 {
|
||||
t.Fatalf("expected 12, got %d", pts)
|
||||
}
|
||||
// 100 Points used. Refund 25 Yuan out of 100 Yuan paid.
|
||||
// Expect 25 Points back.
|
||||
pts := RefundPointsAmount(100, 2500, 10000, 1)
|
||||
if pts != 25 {
|
||||
t.Fatalf("expected 25, got %d", pts)
|
||||
}
|
||||
}
|
||||
|
||||
@ -14,6 +14,7 @@ import (
|
||||
"bindbox-game/internal/dblogger"
|
||||
"bindbox-game/internal/pkg/core"
|
||||
"bindbox-game/internal/pkg/logger"
|
||||
"bindbox-game/internal/pkg/otel"
|
||||
"bindbox-game/internal/pkg/redis"
|
||||
"bindbox-game/internal/repository/mysql"
|
||||
"bindbox-game/internal/router/interceptor"
|
||||
@ -47,6 +48,12 @@ func NewHTTPMux(logger logger.CustomLogger, db mysql.Repo) (core.Mux, func(), er
|
||||
panic(err)
|
||||
}
|
||||
|
||||
// 添加 OpenTelemetry 链路追踪中间件
|
||||
cfg := configs.Get()
|
||||
if cfg.Otel.Enabled {
|
||||
mux.Engine().Use(otel.Middleware(configs.ProjectName))
|
||||
}
|
||||
|
||||
// Redis is initialized in main.go
|
||||
rdb := redis.GetClient()
|
||||
|
||||
@ -140,6 +147,9 @@ func NewHTTPMux(logger logger.CustomLogger, db mysql.Repo) (core.Mux, func(), er
|
||||
adminAuthApiRouter.GET("/dashboard/activities", adminHandler.DashboardActivities())
|
||||
adminAuthApiRouter.GET("/dashboard/activity_prize_analysis", adminHandler.DashboardActivityPrizeAnalysis())
|
||||
adminAuthApiRouter.GET("/dashboard/user_overview", adminHandler.DashboardUserOverview())
|
||||
adminAuthApiRouter.GET("/dashboard/player_spending_leaderboard", adminHandler.DashboardPlayerSpendingLeaderboard())
|
||||
adminAuthApiRouter.GET("/dashboard/activity-profit-loss", adminHandler.DashboardActivityProfitLoss())
|
||||
adminAuthApiRouter.GET("/dashboard/activity-profit-loss/:activity_id/logs", adminHandler.DashboardActivityLogs())
|
||||
|
||||
// 运营分析
|
||||
adminAuthApiRouter.GET("/operations/user_economics", adminHandler.DashboardUserEconomics())
|
||||
@ -231,6 +241,7 @@ func NewHTTPMux(logger logger.CustomLogger, db mysql.Repo) (core.Mux, func(), er
|
||||
adminAuthApiRouter.POST("/users/:user_id/rewards/grant", intc.RequireAdminAction("user:rewards:grant"), adminHandler.GrantReward())
|
||||
adminAuthApiRouter.GET("/users/:user_id/titles", intc.RequireAdminAction("user:view"), adminHandler.ListUserTitles())
|
||||
adminAuthApiRouter.GET("/users/:user_id/stats/profit_loss", intc.RequireAdminAction("user:view"), adminHandler.GetUserProfitLossTrend())
|
||||
adminAuthApiRouter.GET("/users/:user_id/stats/profit_loss_details", intc.RequireAdminAction("user:view"), adminHandler.GetUserProfitLossDetails())
|
||||
adminAuthApiRouter.GET("/users/:user_id/profile", intc.RequireAdminAction("user:view"), adminHandler.GetUserProfile())
|
||||
|
||||
adminAuthApiRouter.POST("/users/:user_id/token", intc.RequireAdminAction("user:token:issue"), adminHandler.IssueUserToken())
|
||||
@ -333,6 +344,7 @@ func NewHTTPMux(logger logger.CustomLogger, db mysql.Repo) (core.Mux, func(), er
|
||||
// 通用上传
|
||||
systemApiRouter.POST("/common/upload/wangeditor", commonHandler.UploadWangEditorImage())
|
||||
systemApiRouter.POST("/menu/ensure_titles", adminHandler.EnsureTitlesMenu())
|
||||
systemApiRouter.POST("/menu/ensure_activity_profit_loss", adminHandler.EnsureActivityProfitLossMenu())
|
||||
}
|
||||
|
||||
// 系统管理:用户/角色/菜单
|
||||
@ -388,6 +400,7 @@ func NewHTTPMux(logger logger.CustomLogger, db mysql.Repo) (core.Mux, func(), er
|
||||
|
||||
// 公共工具
|
||||
appPublicApiRouter.POST("/common/openid", commonHandler.GetOpenID())
|
||||
appPublicApiRouter.GET("/config/public", commonHandler.GetPublicConfig())
|
||||
}
|
||||
|
||||
// APP 端认证接口路由组
|
||||
|
||||
@ -46,6 +46,9 @@ func StartScheduledSettlement(l logger.CustomLogger, repo mysql.Repo, rdb *redis
|
||||
|
||||
// 【独立检查】一番赏格位重置:每30秒检查所有售罄的一番赏期号
|
||||
checkAndResetIchibanSlots(ctx, l, repo, r)
|
||||
|
||||
// 【安全优化】清理超过30分钟未支付的一番赏订单,释放预锁
|
||||
cleanupExpiredIchibanOrders(ctx, l, repo, rdb)
|
||||
var acts []struct {
|
||||
ID int64
|
||||
PlayType string
|
||||
@ -383,6 +386,64 @@ func checkAndResetIchibanSlots(ctx context.Context, l logger.CustomLogger, repo
|
||||
}
|
||||
}
|
||||
|
||||
// cleanupExpiredIchibanOrders 清理超过30分钟未支付的一番赏订单,释放 Redis 预锁
|
||||
func cleanupExpiredIchibanOrders(ctx context.Context, l logger.CustomLogger, repo mysql.Repo, rdb *redis.Client) {
|
||||
cutoff := time.Now().Add(-30 * time.Minute)
|
||||
|
||||
// 查找过期未支付的一番赏订单
|
||||
var expiredOrders []struct {
|
||||
ID int64
|
||||
Remark string
|
||||
UserID int64
|
||||
PlayType string
|
||||
}
|
||||
err := repo.GetDbR().Raw(`
|
||||
SELECT o.id, o.remark, o.user_id, a.play_type
|
||||
FROM orders o
|
||||
INNER JOIN activities a ON o.remark LIKE CONCAT('lottery:activity:', a.id, '|%')
|
||||
WHERE o.status = 1
|
||||
AND o.source_type = 2
|
||||
AND o.created_at < ?
|
||||
AND a.play_type = 'ichiban'
|
||||
LIMIT 100
|
||||
`, cutoff).Scan(&expiredOrders).Error
|
||||
|
||||
if err != nil {
|
||||
l.Error("清理过期一番赏订单: 查询失败", zap.Error(err))
|
||||
return
|
||||
}
|
||||
|
||||
if len(expiredOrders) == 0 {
|
||||
return
|
||||
}
|
||||
|
||||
l.Info("清理过期一番赏订单: 开始处理", zap.Int("count", len(expiredOrders)))
|
||||
|
||||
for _, o := range expiredOrders {
|
||||
// 解析 Remark 获取 IssueID 和 Slots
|
||||
rmk := remark.Parse(o.Remark)
|
||||
|
||||
// 释放 Redis 预锁
|
||||
if rdb != nil && rmk.IssueID > 0 {
|
||||
for _, slot := range rmk.Slots {
|
||||
lockKey := fmt.Sprintf("ichiban:slot_lock:%d:%d", rmk.IssueID, slot.SlotIndex)
|
||||
// 只删除属于该用户的锁
|
||||
existingVal, err := rdb.Get(ctx, lockKey).Result()
|
||||
if err == nil && existingVal == fmt.Sprintf("%d", o.UserID) {
|
||||
rdb.Del(ctx, lockKey)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 将订单状态改为已关闭 (status=5)
|
||||
if err := repo.GetDbW().Exec("UPDATE orders SET status = 5, cancelled_at = NOW() WHERE id = ? AND status = 1", o.ID).Error; err != nil {
|
||||
l.Error("清理过期一番赏订单: 更新订单状态失败", zap.Int64("order_id", o.ID), zap.Error(err))
|
||||
} else {
|
||||
l.Info("清理过期一番赏订单: 订单已关闭", zap.Int64("order_id", o.ID))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func parseTime(s string) time.Time {
|
||||
if s == "" {
|
||||
return time.Time{}
|
||||
|
||||
@ -290,20 +290,66 @@ func (s *service) ListTasks(ctx context.Context, in ListTasksInput) (items []Tas
|
||||
func (s *service) GetUserProgress(ctx context.Context, userID int64, taskID int64) (*UserProgress, error) {
|
||||
db := s.repo.GetDbR()
|
||||
|
||||
// 3.0 获取任务的 ActivityID 限制
|
||||
var tiers []tcmodel.TaskTier
|
||||
// 只需要查 ActivityID > 0 的记录即可判断
|
||||
db.Select("activity_id").Where("task_id=? AND activity_id > 0", taskID).Limit(1).Find(&tiers)
|
||||
targetActivityID := int64(0)
|
||||
if len(tiers) > 0 {
|
||||
targetActivityID = tiers[0].ActivityID
|
||||
}
|
||||
|
||||
// 1. 实时统计订单数据
|
||||
var orderCount int64
|
||||
var orderAmount int64
|
||||
db.Model(&model.Orders{}).Where("user_id = ? AND status = 2", userID).Count(&orderCount)
|
||||
db.Model(&model.Orders{}).Where("user_id = ? AND status = 2", userID).Select("COALESCE(SUM(actual_amount), 0)").Scan(&orderAmount)
|
||||
query := db.Model(&model.Orders{}).Where("user_id = ? AND status = 2", userID)
|
||||
if targetActivityID > 0 {
|
||||
// 增加 activity_id 过滤
|
||||
// 格式匹配 activity:{id} 或 lottery:activity:{id}
|
||||
// remark 包分隔符为 |,所以匹配 activity:{id}|... 或 activity:{id} 结尾
|
||||
likePattern := fmt.Sprintf("%%activity:%d%%", targetActivityID)
|
||||
query = query.Where("remark LIKE ?", likePattern)
|
||||
}
|
||||
|
||||
query.Count(&orderCount)
|
||||
// 复用 query 对象需要 clone 或者重新构造,GORM 的 query 是可变的
|
||||
// 这里简单起见,重新构造 query 或者使用 session
|
||||
// 上面的 query.Count 可能会修改 query,保险起见重新构造
|
||||
queryAmount := db.Model(&model.Orders{}).Where("user_id = ? AND status = 2", userID)
|
||||
if targetActivityID > 0 {
|
||||
likePattern := fmt.Sprintf("%%activity:%d%%", targetActivityID)
|
||||
queryAmount = queryAmount.Where("remark LIKE ?", likePattern)
|
||||
}
|
||||
queryAmount.Select("COALESCE(SUM(actual_amount), 0)").Scan(&orderAmount)
|
||||
|
||||
// 2. 实时统计邀请数据(有效邀请:被邀请人有消费记录)
|
||||
// 注意:邀请统计是否也要过滤 ActivityID?
|
||||
// 需求是“消费的是对对碰”,通常指邀请带来的“有效用户”需要在该活动消费。
|
||||
// 之前的逻辑是:INNER JOIN orders,只要有任意消费就算有效。
|
||||
// 如果任务是“对对碰”任务,那么被邀请人应该在“对对碰”消费才算有效邀请吗?
|
||||
// 暂时保持原样,或者也加上过滤。根据常理,特定活动拉新通常要求在该活动消费。
|
||||
// 这里加上过滤更安全。
|
||||
|
||||
var inviteCount int64
|
||||
db.Raw(`
|
||||
inviteQuery := fmt.Sprintf(`
|
||||
SELECT COUNT(DISTINCT ui.invitee_id)
|
||||
FROM user_invites ui
|
||||
INNER JOIN orders o ON o.user_id = ui.invitee_id AND o.status = 2
|
||||
WHERE ui.inviter_id = ?
|
||||
`, userID).Scan(&inviteCount)
|
||||
`)
|
||||
var args []interface{}
|
||||
args = append(args, userID)
|
||||
|
||||
if targetActivityID > 0 {
|
||||
inviteQuery = fmt.Sprintf(`
|
||||
SELECT COUNT(DISTINCT ui.invitee_id)
|
||||
FROM user_invites ui
|
||||
INNER JOIN orders o ON o.user_id = ui.invitee_id AND o.status = 2 AND o.remark LIKE ?
|
||||
WHERE ui.inviter_id = ?
|
||||
`)
|
||||
args = []interface{}{fmt.Sprintf("%%activity:%d%%", targetActivityID), userID}
|
||||
}
|
||||
db.Raw(inviteQuery, args...).Scan(&inviteCount)
|
||||
|
||||
// 3. 首单判断
|
||||
hasFirstOrder := orderCount > 0
|
||||
|
||||
@ -7,6 +7,7 @@ import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"bindbox-game/internal/repository/mysql"
|
||||
tcmodel "bindbox-game/internal/repository/mysql/task_center"
|
||||
|
||||
"gorm.io/datatypes"
|
||||
@ -72,6 +73,13 @@ func CreateTestDB(t *testing.T) *gorm.DB {
|
||||
t.Fatalf("创建数据库失败: %v", err)
|
||||
}
|
||||
|
||||
initTestTables(t, db)
|
||||
|
||||
return db
|
||||
}
|
||||
|
||||
// initTestTables initializes the task center related tables in the given DB.
|
||||
func initTestTables(t *testing.T, db *gorm.DB) {
|
||||
// 创建任务中心相关表
|
||||
if err := db.Exec(`CREATE TABLE task_center_tasks (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
@ -150,8 +158,6 @@ func CreateTestDB(t *testing.T) *gorm.DB {
|
||||
);`).Error; err != nil {
|
||||
t.Fatalf("创建 task_center_event_logs 表失败: %v", err)
|
||||
}
|
||||
|
||||
return db
|
||||
}
|
||||
|
||||
// InsertTaskWithTierAndReward 插入一个完整的任务配置(任务+档位+奖励)
|
||||
@ -334,7 +340,13 @@ func TestOrderCountMetric(t *testing.T) {
|
||||
ClaimedTiers: datatypes.JSON("[]"),
|
||||
}
|
||||
// Upsert 模拟
|
||||
db.Where("user_id = ? AND task_id = ?", userID, taskID).Assign(progress).FirstOrCreate(progress)
|
||||
var existing tcmodel.UserTaskProgress
|
||||
if err := db.Where("user_id = ? AND task_id = ?", userID, taskID).First(&existing).Error; err == nil {
|
||||
existing.OrderCount = int64(i)
|
||||
db.Save(&existing)
|
||||
} else {
|
||||
db.Create(progress)
|
||||
}
|
||||
}
|
||||
|
||||
var p tcmodel.UserTaskProgress
|
||||
@ -629,3 +641,86 @@ func TestClaimedTiersTracking(t *testing.T) {
|
||||
|
||||
t.Logf("已领取档位追踪测试通过: %v", claimed)
|
||||
}
|
||||
|
||||
func TestGetUserProgress_ActivityFilter_Integration(t *testing.T) {
|
||||
repo, err := mysql.NewSQLiteRepoForTest()
|
||||
if err != nil {
|
||||
t.Fatalf("创建 repo 失败: %v", err)
|
||||
}
|
||||
db := repo.GetDbW()
|
||||
|
||||
// 初始化表结构 (直接复用 CreateTestDB 的逻辑,手动执行)
|
||||
initTestTables(t, db)
|
||||
|
||||
// Create orders table manually since initTestTables doesn't create it
|
||||
if !db.Migrator().HasTable("orders") {
|
||||
if err := db.Exec(`CREATE TABLE orders (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
user_id INTEGER NOT NULL,
|
||||
status INTEGER NOT NULL DEFAULT 1,
|
||||
actual_amount INTEGER NOT NULL DEFAULT 0,
|
||||
remark TEXT,
|
||||
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at DATETIME DEFAULT CURRENT_TIMESTAMP
|
||||
);`).Error; err != nil {
|
||||
t.Fatalf("创建 orders 表失败: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
// Create user_invites table
|
||||
if !db.Migrator().HasTable("user_invites") {
|
||||
if err := db.Exec(`CREATE TABLE user_invites (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
inviter_id INTEGER NOT NULL,
|
||||
invitee_id INTEGER NOT NULL,
|
||||
accumulated_amount INTEGER NOT NULL DEFAULT 0,
|
||||
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at DATETIME DEFAULT CURRENT_TIMESTAMP
|
||||
);`).Error; err != nil {
|
||||
t.Fatalf("创建 user_invites 表失败: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
svc := New(nil, repo, nil, nil, nil)
|
||||
|
||||
// 1. 创建带有 ActivityID=100 的任务
|
||||
combo := TaskCombination{
|
||||
Name: "活动专属任务",
|
||||
Metric: MetricOrderCount,
|
||||
Operator: OperatorGTE,
|
||||
Threshold: 1,
|
||||
Window: WindowLifetime,
|
||||
RewardType: RewardTypePoints,
|
||||
}
|
||||
// 手动插入带 ActivityID 的 Tier
|
||||
taskID, _ := InsertTaskWithTierAndReward(t, db, combo)
|
||||
db.Model(&tcmodel.TaskTier{}).Where("task_id=?", taskID).Update("activity_id", 100)
|
||||
|
||||
userID := int64(999)
|
||||
|
||||
// 2. 插入不同类型的订单
|
||||
// 订单 A: 匹配活动 100
|
||||
db.Exec("INSERT INTO orders (user_id, status, actual_amount, remark) VALUES (?, 2, 100, ?)", userID, "activity:100|count:1")
|
||||
// 订单 B: 匹配活动 200 (不应被统计)
|
||||
db.Exec("INSERT INTO orders (user_id, status, actual_amount, remark) VALUES (?, 2, 200, ?)", userID, "activity:200|count:1")
|
||||
// 订单 C: 普通订单 (不应被统计)
|
||||
db.Exec("INSERT INTO orders (user_id, status, actual_amount, remark) VALUES (?, 2, 300, ?)", userID, "normal_order")
|
||||
// 订单 D: 匹配活动 100 但未支付 (不应被统计)
|
||||
db.Exec("INSERT INTO orders (user_id, status, actual_amount, remark) VALUES (?, 1, 100, ?)", userID, "activity:100|count:1")
|
||||
|
||||
// 3. 调用 GetUserProgress
|
||||
progress, err := svc.GetUserProgress(context.Background(), userID, taskID)
|
||||
if err != nil {
|
||||
t.Fatalf("GetUserProgress 失败: %v", err)
|
||||
}
|
||||
|
||||
// 4. 验证
|
||||
if progress.OrderCount != 1 {
|
||||
t.Errorf("OrderCount 错误: 期望 1, 实际 %d", progress.OrderCount)
|
||||
}
|
||||
if progress.OrderAmount != 100 {
|
||||
t.Errorf("OrderAmount 错误: 期望 100, 实际 %d", progress.OrderAmount)
|
||||
}
|
||||
|
||||
t.Logf("ActivityID 过滤测试通过: OrderCount=%d, OrderAmount=%d", progress.OrderCount, progress.OrderAmount)
|
||||
}
|
||||
|
||||
@ -20,15 +20,14 @@ func (s *service) RedeemItemCard(ctx context.Context, userID int64, cardID int64
|
||||
return 0, errors.New("item card not found")
|
||||
}
|
||||
|
||||
// 2. 算分
|
||||
ptsPerUnit, _ := s.CentsToPoints(ctx, tpl.Price)
|
||||
needPoints := ptsPerUnit * int64(quantity)
|
||||
if needPoints <= 0 {
|
||||
needPoints = 1
|
||||
// 2. 算分 - tpl.Price 是道具卡价格(分),直接用于扣除
|
||||
needCents := tpl.Price * int64(quantity)
|
||||
if needCents <= 0 {
|
||||
needCents = 1
|
||||
}
|
||||
|
||||
// 3. 扣分 (调用现有 Service)
|
||||
ledgerID, err = s.ConsumePointsFor(ctx, userID, needPoints, "system_item_cards", strconv.FormatInt(cardID, 10), "redeem item card", "redeem_item_card")
|
||||
ledgerID, err = s.ConsumePointsFor(ctx, userID, needCents, "system_item_cards", strconv.FormatInt(cardID, 10), "redeem item card", "redeem_item_card")
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
@ -42,7 +41,7 @@ func (s *service) RedeemItemCard(ctx context.Context, userID int64, cardID int64
|
||||
zap.Error(err),
|
||||
)
|
||||
// 自动退分
|
||||
_, _ = s.RefundPoints(ctx, userID, needPoints, strconv.FormatInt(ledgerID, 10), "refund: grant item card failed")
|
||||
_, _ = s.RefundPoints(ctx, userID, needCents, strconv.FormatInt(ledgerID, 10), "refund: grant item card failed")
|
||||
return ledgerID, errors.New("failed to grant item card: " + err.Error())
|
||||
}
|
||||
|
||||
|
||||
@ -36,12 +36,8 @@ func (s *service) CancelOrder(ctx context.Context, userID int64, orderID int64,
|
||||
refundReason = refundReason + ":" + reason
|
||||
}
|
||||
|
||||
// Get Rate
|
||||
ratePtsPerCent, _ := s.CentsToPoints(ctx, 1)
|
||||
if ratePtsPerCent <= 0 {
|
||||
ratePtsPerCent = 1
|
||||
}
|
||||
pointsToRefund := order.PointsAmount * ratePtsPerCent
|
||||
// order.PointsAmount 已经是分单位,直接退还
|
||||
pointsToRefund := order.PointsAmount
|
||||
|
||||
// Update User Points
|
||||
existing, _ := tx.UserPoints.WithContext(ctx).Clauses(clause.Locking{Strength: "UPDATE"}).Where(tx.UserPoints.UserID.Eq(userID)).First()
|
||||
|
||||
@ -5,12 +5,15 @@ import (
|
||||
"fmt"
|
||||
)
|
||||
|
||||
func (s *service) CentsToPoints(ctx context.Context, cents int64) (int64, error) {
|
||||
if cents <= 0 {
|
||||
return 0, nil
|
||||
}
|
||||
cfg, _ := s.readDB.SystemConfigs.WithContext(ctx).Where(s.readDB.SystemConfigs.ConfigKey.Eq("points_exchange_per_cent")).First()
|
||||
rate := int64(1)
|
||||
// getExchangeRate 获取积分兑换比率
|
||||
// 配置含义:1 元 = X 积分(后台配置的值)
|
||||
// 计算:分 / (100 / rate) = 分 * rate / 100
|
||||
// 当 rate=1 时:1元=1积分,100分=1积分
|
||||
// 当 rate=2 时:1元=2积分,50分=1积分
|
||||
func (s *service) getExchangeRate(ctx context.Context) int64 {
|
||||
// 读取后台配置的 key:points.exchange_rate
|
||||
cfg, _ := s.readDB.SystemConfigs.WithContext(ctx).Where(s.readDB.SystemConfigs.ConfigKey.Eq("points.exchange_rate")).First()
|
||||
rate := int64(1) // 默认 1 元 = 1 积分
|
||||
if cfg != nil {
|
||||
var r int64
|
||||
_, _ = fmt.Sscanf(cfg.ConfigValue, "%d", &r)
|
||||
@ -18,5 +21,39 @@ func (s *service) CentsToPoints(ctx context.Context, cents int64) (int64, error)
|
||||
rate = r
|
||||
}
|
||||
}
|
||||
return cents * rate, nil
|
||||
return rate
|
||||
}
|
||||
|
||||
// CentsToPointsFloat 分 → 积分(浮点数,用于 API 返回展示)
|
||||
// 公式:积分 = 分 * rate / 100
|
||||
// 例如:rate=1, 3580分 → 35.8积分
|
||||
func (s *service) CentsToPointsFloat(ctx context.Context, cents int64) float64 {
|
||||
if cents <= 0 {
|
||||
return 0
|
||||
}
|
||||
rate := s.getExchangeRate(ctx)
|
||||
return float64(cents) * float64(rate) / 100
|
||||
}
|
||||
|
||||
// CentsToPoints 分 → 积分(整数,向下取整,用于计算)
|
||||
// 公式:积分 = 分 * rate / 100
|
||||
func (s *service) CentsToPoints(ctx context.Context, cents int64) (int64, error) {
|
||||
if cents <= 0 {
|
||||
return 0, nil
|
||||
}
|
||||
rate := s.getExchangeRate(ctx)
|
||||
return (cents * rate) / 100, nil
|
||||
}
|
||||
|
||||
// PointsToCents 积分 → 分(用于将用户输入的积分转为分)
|
||||
// 公式:分 = 积分 * 100 / rate
|
||||
func (s *service) PointsToCents(ctx context.Context, pts int64) (int64, error) {
|
||||
if pts <= 0 {
|
||||
return 0, nil
|
||||
}
|
||||
rate := s.getExchangeRate(ctx)
|
||||
if rate == 0 {
|
||||
rate = 1
|
||||
}
|
||||
return (pts * 100) / rate, nil
|
||||
}
|
||||
|
||||
@ -71,6 +71,8 @@ type Service interface {
|
||||
GetOrderWithItems(ctx context.Context, userID, orderID int64) (*OrderWithItems, error)
|
||||
CancelOrder(ctx context.Context, userID, orderID int64, reason string) (*model.Orders, error)
|
||||
CentsToPoints(ctx context.Context, cents int64) (int64, error)
|
||||
CentsToPointsFloat(ctx context.Context, cents int64) float64
|
||||
PointsToCents(ctx context.Context, points int64) (int64, error)
|
||||
ListUserShipmentGroups(ctx context.Context, userID int64, page, pageSize int) (items []*ShipmentGroup, total int64, err error)
|
||||
ConsumePointsForRefund(ctx context.Context, userID int64, points int64, refTable string, refID string, remark string) (int64, int64, error)
|
||||
// 短信登录
|
||||
|
||||
171
main.go
171
main.go
@ -8,6 +8,7 @@ import (
|
||||
"bindbox-game/configs"
|
||||
"bindbox-game/internal/pkg/env"
|
||||
"bindbox-game/internal/pkg/logger"
|
||||
"bindbox-game/internal/pkg/otel"
|
||||
"bindbox-game/internal/pkg/redis"
|
||||
"bindbox-game/internal/pkg/shutdown"
|
||||
"bindbox-game/internal/pkg/timeutil"
|
||||
@ -35,163 +36,30 @@ import (
|
||||
// @BasePath /
|
||||
func main() {
|
||||
flag.Parse()
|
||||
|
||||
// 初始化 OpenTelemetry
|
||||
cfg := configs.Get()
|
||||
otelShutdown, err := otel.Init(otel.Config{
|
||||
ServiceName: configs.ProjectName,
|
||||
ServiceVersion: "1.0.0",
|
||||
Environment: env.Active().Value(),
|
||||
Endpoint: cfg.Otel.Endpoint,
|
||||
Enabled: cfg.Otel.Enabled,
|
||||
})
|
||||
if err != nil {
|
||||
fmt.Printf("OpenTelemetry init failed: %v\n", err)
|
||||
}
|
||||
|
||||
// 初始化 MySQL
|
||||
dbRepo, err := mysql.New()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
// 修复缺失的列以避免创建活动时报错
|
||||
{
|
||||
db := dbRepo.GetDbW()
|
||||
var cnt int64
|
||||
_ = db.Raw(
|
||||
"SELECT COUNT(*) FROM information_schema.columns WHERE table_schema = ? AND table_name = 'activities' AND column_name = 'image'",
|
||||
configs.Get().MySQL.Write.Name,
|
||||
).Scan(&cnt).Error
|
||||
if cnt == 0 {
|
||||
_ = db.Exec("ALTER TABLE `activities` ADD COLUMN `image` VARCHAR(512) NULL COMMENT '活动主图URL' AFTER `banner`").Error
|
||||
}
|
||||
|
||||
cnt = 0
|
||||
_ = db.Raw(
|
||||
"SELECT COUNT(*) FROM information_schema.columns WHERE table_schema = ? AND table_name = 'activities' AND column_name = 'gameplay_intro'",
|
||||
configs.Get().MySQL.Write.Name,
|
||||
).Scan(&cnt).Error
|
||||
if cnt == 0 {
|
||||
_ = db.Exec("ALTER TABLE `activities` ADD COLUMN `gameplay_intro` TEXT NULL COMMENT '玩法介绍' AFTER `image`").Error
|
||||
}
|
||||
|
||||
cnt = 0
|
||||
_ = db.Raw(
|
||||
"SELECT COUNT(*) FROM information_schema.columns WHERE table_schema = ? AND table_name = 'activities' AND column_name = 'allow_item_cards'",
|
||||
configs.Get().MySQL.Write.Name,
|
||||
).Scan(&cnt).Error
|
||||
if cnt == 0 {
|
||||
_ = db.Exec("ALTER TABLE `activities` ADD COLUMN `allow_item_cards` TINYINT(1) NOT NULL DEFAULT 1 COMMENT '是否允许使用道具卡' AFTER `is_boss`").Error
|
||||
}
|
||||
|
||||
cnt = 0
|
||||
_ = db.Raw(
|
||||
"SELECT COUNT(*) FROM information_schema.columns WHERE table_schema = ? AND table_name = 'activities' AND column_name = 'allow_coupons'",
|
||||
configs.Get().MySQL.Write.Name,
|
||||
).Scan(&cnt).Error
|
||||
if cnt == 0 {
|
||||
_ = db.Exec("ALTER TABLE `activities` ADD COLUMN `allow_coupons` TINYINT(1) NOT NULL DEFAULT 1 COMMENT '是否允许使用优惠券' AFTER `allow_item_cards`").Error
|
||||
}
|
||||
|
||||
// 检查并创建 channels 表
|
||||
if !db.Migrator().HasTable("channels") {
|
||||
_ = db.Exec(`CREATE TABLE IF NOT EXISTS channels (
|
||||
id bigint(20) NOT NULL AUTO_INCREMENT COMMENT '主键ID',
|
||||
name varchar(255) NOT NULL COMMENT '渠道名称',
|
||||
code varchar(255) NOT NULL COMMENT '渠道唯一标识',
|
||||
type varchar(50) NOT NULL DEFAULT 'other' COMMENT '渠道类型',
|
||||
remarks varchar(512) DEFAULT NULL COMMENT '备注',
|
||||
created_at datetime(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT '创建时间',
|
||||
updated_at datetime(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT '更新时间',
|
||||
deleted_at datetime(3) DEFAULT NULL COMMENT '删除时间',
|
||||
PRIMARY KEY (id),
|
||||
UNIQUE KEY uk_code (code)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='推广渠道表';`).Error
|
||||
}
|
||||
|
||||
// users 表新增 channel_id 字段
|
||||
cnt = 0
|
||||
_ = db.Raw(
|
||||
"SELECT COUNT(*) FROM information_schema.columns WHERE table_schema = ? AND table_name = 'users' AND column_name = 'channel_id'",
|
||||
configs.Get().MySQL.Write.Name,
|
||||
).Scan(&cnt).Error
|
||||
if cnt == 0 {
|
||||
_ = db.Exec("ALTER TABLE users ADD COLUMN channel_id bigint(20) DEFAULT 0 COMMENT '渠道ID' AFTER douyin_id").Error
|
||||
}
|
||||
|
||||
// shipping_records 表新增 batch_no 字段(批量发货分组用)
|
||||
cnt = 0
|
||||
_ = db.Raw(
|
||||
"SELECT COUNT(*) FROM information_schema.columns WHERE table_schema = ? AND table_name = 'shipping_records' AND column_name = 'batch_no'",
|
||||
configs.Get().MySQL.Write.Name,
|
||||
).Scan(&cnt).Error
|
||||
if cnt == 0 {
|
||||
_ = db.Exec("ALTER TABLE shipping_records ADD COLUMN batch_no VARCHAR(64) NULL COMMENT '批次号(批量发货时用于聚合)' AFTER express_no").Error
|
||||
_ = db.Exec("CREATE INDEX idx_shipping_records_batch_no ON shipping_records(batch_no)").Error
|
||||
}
|
||||
|
||||
// 抖店订单表
|
||||
if !db.Migrator().HasTable("douyin_orders") {
|
||||
_ = db.Exec(`CREATE TABLE IF NOT EXISTS douyin_orders (
|
||||
id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
|
||||
shop_order_id VARCHAR(64) NOT NULL COMMENT '抖店订单号',
|
||||
order_status INT NOT NULL DEFAULT 0 COMMENT '订单状态: 5=已完成',
|
||||
douyin_user_id VARCHAR(256) NOT NULL COMMENT '抖店用户ID',
|
||||
local_user_id BIGINT DEFAULT 0 COMMENT '匹配到的本地用户ID',
|
||||
actual_receive_amount BIGINT DEFAULT 0 COMMENT '实收金额(分)',
|
||||
pay_type_desc VARCHAR(64) DEFAULT '' COMMENT '支付方式描述',
|
||||
remark VARCHAR(512) DEFAULT '' COMMENT '备注',
|
||||
user_nickname VARCHAR(128) DEFAULT '' COMMENT '抖音昵称',
|
||||
raw_data JSON COMMENT '原始响应数据',
|
||||
created_at DATETIME(3) DEFAULT CURRENT_TIMESTAMP(3),
|
||||
updated_at DATETIME(3) DEFAULT CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3),
|
||||
UNIQUE KEY uk_shop_order_id (shop_order_id),
|
||||
INDEX idx_local_user_id (local_user_id),
|
||||
INDEX idx_douyin_user_id (douyin_user_id),
|
||||
INDEX idx_order_status (order_status)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='抖店订单表';`).Error
|
||||
} else {
|
||||
// 检查并修改 douyin_user_id 列长度
|
||||
_ = db.Exec("ALTER TABLE douyin_orders MODIFY COLUMN douyin_user_id VARCHAR(256) NOT NULL COMMENT '抖店用户ID'").Error
|
||||
// 检查并添加 reward_granted 字段
|
||||
cnt = 0
|
||||
_ = db.Raw(
|
||||
"SELECT COUNT(*) FROM information_schema.columns WHERE table_schema = ? AND table_name = 'douyin_orders' AND column_name = 'reward_granted'",
|
||||
configs.Get().MySQL.Write.Name,
|
||||
).Scan(&cnt).Error
|
||||
if cnt == 0 {
|
||||
_ = db.Exec("ALTER TABLE douyin_orders ADD COLUMN reward_granted TINYINT(1) NOT NULL DEFAULT 0 COMMENT '奖励已发放: 0=否, 1=是'").Error
|
||||
}
|
||||
}
|
||||
|
||||
// 抽奖退款日志表
|
||||
if !db.Migrator().HasTable("lottery_refund_logs") {
|
||||
_ = db.Exec(`CREATE TABLE IF NOT EXISTS lottery_refund_logs (
|
||||
id bigint unsigned AUTO_INCREMENT PRIMARY KEY,
|
||||
issue_id bigint NOT NULL DEFAULT 0,
|
||||
order_id bigint NOT NULL DEFAULT 0,
|
||||
user_id bigint NOT NULL DEFAULT 0,
|
||||
amount bigint NOT NULL DEFAULT 0,
|
||||
coupon_type varchar(64) DEFAULT '',
|
||||
coupon_amount bigint DEFAULT 0,
|
||||
reason varchar(255) DEFAULT '',
|
||||
status varchar(32) DEFAULT '',
|
||||
created_at datetime DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
INDEX idx_issue (issue_id),
|
||||
INDEX idx_order (order_id)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='抽奖退款记录表';`).Error
|
||||
}
|
||||
|
||||
// 抖店商品奖励规则表
|
||||
if !db.Migrator().HasTable("douyin_product_rewards") {
|
||||
_ = db.Exec(`CREATE TABLE IF NOT EXISTS douyin_product_rewards (
|
||||
id BIGINT AUTO_INCREMENT PRIMARY KEY,
|
||||
product_id VARCHAR(64) NOT NULL COMMENT '抖店商品ID',
|
||||
product_name VARCHAR(255) NOT NULL DEFAULT '' COMMENT '商品名称',
|
||||
reward_type VARCHAR(32) NOT NULL COMMENT '奖励类型',
|
||||
reward_payload JSON COMMENT '奖励参数JSON',
|
||||
quantity INT NOT NULL DEFAULT 1 COMMENT '发放数量',
|
||||
status TINYINT NOT NULL DEFAULT 1 COMMENT '状态: 1=启用 0=禁用',
|
||||
created_at DATETIME(3) DEFAULT CURRENT_TIMESTAMP(3),
|
||||
updated_at DATETIME(3) DEFAULT CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3),
|
||||
UNIQUE KEY uk_product_id (product_id),
|
||||
KEY idx_status (status)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='抖店商品奖励规则';`).Error
|
||||
}
|
||||
}
|
||||
|
||||
// 初始化 自定义 Logger
|
||||
customLogger, err := logger.NewCustomLogger(dao.Use(dbRepo.GetDbW()),
|
||||
logger.WithDebugLevel(), // 启用调试级别日志
|
||||
// logger.WithOutputInConsole(), // 启用控制台输出
|
||||
logger.WithDebugLevel(), // 启用调试级别日志
|
||||
logger.WithOutputInConsole(), // 启用控制台输出
|
||||
logger.WithField("domain", fmt.Sprintf("%s[%s]", configs.ProjectName, env.Active().Value())),
|
||||
logger.WithTimeLayout(timeutil.CSTLayout),
|
||||
logger.WithFileRotationP(configs.ProjectAccessLogFile),
|
||||
@ -248,6 +116,11 @@ func main() {
|
||||
cleanup()
|
||||
}
|
||||
|
||||
// 关闭 OpenTelemetry
|
||||
if otelShutdown != nil {
|
||||
_ = otelShutdown(context.Background())
|
||||
}
|
||||
|
||||
// 关闭 http server
|
||||
if err := server.Shutdown(context.TODO()); err != nil {
|
||||
customLogger.Error("server shutdown err", zap.Error(err))
|
||||
|
||||
1
migration_add_template_id.sql
Normal file
1
migration_add_template_id.sql
Normal file
@ -0,0 +1 @@
|
||||
INSERT INTO sys_configs (config_key, config_group, config_value, remark, is_encrypted) VALUES ('wechat_miniprogram_lottery_result_template_id', 'miniprogram', 'O2eqJQD3pn-vQ6g2z9DWzINVwOmPoz8yW-172J_YcpI', '微信小程序开奖结果通知模板ID', 0) ON DUPLICATE KEY UPDATE config_value='O2eqJQD3pn-vQ6g2z9DWzINVwOmPoz8yW-172J_YcpI';
|
||||
1
response.json
Normal file
1
response.json
Normal file
File diff suppressed because one or more lines are too long
1
response_new.json
Normal file
1
response_new.json
Normal file
File diff suppressed because one or more lines are too long
70
scripts/check_points_integrity.go
Normal file
70
scripts/check_points_integrity.go
Normal file
@ -0,0 +1,70 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"bindbox-game/internal/repository/mysql"
|
||||
"bindbox-game/internal/repository/mysql/model"
|
||||
"fmt"
|
||||
"log"
|
||||
)
|
||||
|
||||
func main() {
|
||||
// Initialize DB (Implicitly loads configs via init())
|
||||
db, err := mysql.New()
|
||||
if err != nil {
|
||||
log.Fatalf("failed to init db: %v", err)
|
||||
}
|
||||
|
||||
// 1. Get all users
|
||||
var userIDs []int64
|
||||
if err := db.GetDbR().Model(&model.Users{}).Pluck("id", &userIDs).Error; err != nil {
|
||||
log.Fatalf("failed to get users: %v", err)
|
||||
}
|
||||
|
||||
fmt.Printf("Checking points integrity for %d users...\n", len(userIDs))
|
||||
fmt.Println("UserID | LedgerSum | BalanceSum | Diff")
|
||||
fmt.Println("-------|-----------|------------|------")
|
||||
|
||||
errorCount := 0
|
||||
|
||||
for _, uid := range userIDs {
|
||||
// Sum Ledger
|
||||
var ledgerSum int64
|
||||
if err := db.GetDbR().Model(&model.UserPointsLedger{}).
|
||||
Where("user_id = ?", uid).
|
||||
Select("COALESCE(SUM(points), 0)").
|
||||
Scan(&ledgerSum).Error; err != nil {
|
||||
log.Printf("failed to sum ledger for user %d: %v", uid, err)
|
||||
continue
|
||||
}
|
||||
|
||||
// Sum Balance
|
||||
var balanceSum int64
|
||||
if err := db.GetDbR().Model(&model.UserPoints{}).
|
||||
Where("user_id = ?", uid).
|
||||
Select("COALESCE(SUM(points), 0)").
|
||||
Scan(&balanceSum).Error; err != nil {
|
||||
log.Printf("failed to sum balance for user %d: %v", uid, err)
|
||||
continue
|
||||
}
|
||||
|
||||
diff := ledgerSum - balanceSum
|
||||
if diff != 0 || uid == 9018 {
|
||||
errorCount++
|
||||
fmt.Printf("%6d | %9d | %10d | %4d\n", uid, ledgerSum, balanceSum, diff)
|
||||
// Show ledgers for 9018
|
||||
if uid == 9018 {
|
||||
var ledgers []model.UserPointsLedger
|
||||
db.GetDbR().Where("user_id = ?", uid).Find(&ledgers)
|
||||
for _, l := range ledgers {
|
||||
fmt.Printf(" -> Ledger ID: %d, Action: %s, Points: %d\n", l.ID, l.Action, l.Points)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if errorCount == 0 {
|
||||
fmt.Println("\nAll users verified. No discrepancies found.")
|
||||
} else {
|
||||
fmt.Printf("\nFound %d users with point discrepancies.\n", errorCount)
|
||||
}
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user