202 lines
5.6 KiB
Go
202 lines
5.6 KiB
Go
package admin
|
|
|
|
import (
|
|
"bindbox-game/internal/code"
|
|
"bindbox-game/internal/pkg/core"
|
|
"bindbox-game/internal/pkg/validation"
|
|
"bindbox-game/internal/service/douyin"
|
|
"fmt"
|
|
"net/http"
|
|
"strconv"
|
|
)
|
|
|
|
// ---------- 抖店配置 API ----------
|
|
|
|
type getDouyinConfigResponse struct {
|
|
Cookie string `json:"cookie"`
|
|
IntervalMinutes int `json:"interval_minutes"`
|
|
}
|
|
|
|
func (h *handler) GetDouyinConfig() core.HandlerFunc {
|
|
return func(ctx core.Context) {
|
|
cfg, err := h.douyinSvc.GetConfig(ctx.RequestContext())
|
|
if err != nil {
|
|
ctx.AbortWithError(core.Error(http.StatusBadRequest, code.ServerError, validation.Error(err)))
|
|
return
|
|
}
|
|
ctx.Payload(getDouyinConfigResponse{
|
|
Cookie: cfg.Cookie,
|
|
IntervalMinutes: cfg.IntervalMinutes,
|
|
})
|
|
}
|
|
}
|
|
|
|
type saveDouyinConfigRequest struct {
|
|
Cookie string `json:"cookie"`
|
|
IntervalMinutes int `json:"interval_minutes"`
|
|
}
|
|
|
|
func (h *handler) SaveDouyinConfig() core.HandlerFunc {
|
|
return func(ctx core.Context) {
|
|
req := new(saveDouyinConfigRequest)
|
|
if err := ctx.ShouldBindJSON(req); err != nil {
|
|
ctx.AbortWithError(core.Error(http.StatusBadRequest, code.ParamBindError, validation.Error(err)))
|
|
return
|
|
}
|
|
|
|
if err := h.douyinSvc.SaveConfig(ctx.RequestContext(), req.Cookie, req.IntervalMinutes); err != nil {
|
|
ctx.AbortWithError(core.Error(http.StatusBadRequest, code.ServerError, validation.Error(err)))
|
|
return
|
|
}
|
|
|
|
ctx.Payload(pcSimpleMessage{Message: "保存成功"})
|
|
}
|
|
}
|
|
|
|
// ---------- 抖店订单列表 API ----------
|
|
|
|
type listDouyinOrdersRequest struct {
|
|
Page int `form:"page"`
|
|
PageSize int `form:"page_size"`
|
|
Status *int `form:"status"`
|
|
}
|
|
|
|
type douyinOrderItem struct {
|
|
ID int64 `json:"id"`
|
|
ShopOrderID string `json:"shop_order_id"`
|
|
OrderStatus int32 `json:"order_status"`
|
|
OrderStatusText string `json:"order_status_text"`
|
|
DouyinUserID string `json:"douyin_user_id"`
|
|
LocalUserID int64 `json:"local_user_id"`
|
|
LocalUserNickname string `json:"local_user_nickname"`
|
|
ActualReceiveAmount string `json:"actual_receive_amount"`
|
|
PayTypeDesc string `json:"pay_type_desc"`
|
|
Remark string `json:"remark"`
|
|
UserNickname string `json:"user_nickname"`
|
|
CreatedAt string `json:"created_at"`
|
|
}
|
|
|
|
type listDouyinOrdersResponse struct {
|
|
Page int `json:"page"`
|
|
PageSize int `json:"page_size"`
|
|
Total int64 `json:"total"`
|
|
List []douyinOrderItem `json:"list"`
|
|
}
|
|
|
|
func (h *handler) ListDouyinOrders() core.HandlerFunc {
|
|
return func(ctx core.Context) {
|
|
req := new(listDouyinOrdersRequest)
|
|
if err := ctx.ShouldBindForm(req); err != nil {
|
|
ctx.AbortWithError(core.Error(http.StatusBadRequest, code.ParamBindError, validation.Error(err)))
|
|
return
|
|
}
|
|
|
|
orders, total, err := h.douyinSvc.ListOrders(ctx.RequestContext(), req.Page, req.PageSize, req.Status)
|
|
if err != nil {
|
|
ctx.AbortWithError(core.Error(http.StatusBadRequest, code.ServerError, validation.Error(err)))
|
|
return
|
|
}
|
|
|
|
// 获取匹配用户的昵称
|
|
userNicknameMap := make(map[int64]string)
|
|
var userIDs []int64
|
|
for _, o := range orders {
|
|
if uid, err := strconv.ParseInt(o.LocalUserID, 10, 64); err == nil && uid > 0 {
|
|
userIDs = append(userIDs, uid)
|
|
}
|
|
}
|
|
if len(userIDs) > 0 {
|
|
var users []struct {
|
|
ID int64
|
|
Nickname string
|
|
}
|
|
h.repo.GetDbR().Table("users").Where("id IN ?", userIDs).Select("id, nickname").Find(&users)
|
|
for _, u := range users {
|
|
userNicknameMap[u.ID] = u.Nickname
|
|
}
|
|
}
|
|
|
|
// 构建响应
|
|
list := make([]douyinOrderItem, len(orders))
|
|
for i, o := range orders {
|
|
uid, _ := strconv.ParseInt(o.LocalUserID, 10, 64)
|
|
list[i] = douyinOrderItem{
|
|
ID: o.ID,
|
|
ShopOrderID: o.ShopOrderID,
|
|
OrderStatus: o.OrderStatus,
|
|
OrderStatusText: getOrderStatusText(o.OrderStatus),
|
|
DouyinUserID: o.DouyinUserID,
|
|
LocalUserID: uid,
|
|
LocalUserNickname: userNicknameMap[uid],
|
|
ActualReceiveAmount: formatAmount(o.ActualReceiveAmount),
|
|
PayTypeDesc: o.PayTypeDesc,
|
|
Remark: o.Remark,
|
|
UserNickname: o.UserNickname,
|
|
CreatedAt: o.CreatedAt.Format("2006-01-02 15:04:05"),
|
|
}
|
|
}
|
|
|
|
ctx.Payload(listDouyinOrdersResponse{
|
|
Page: req.Page,
|
|
PageSize: req.PageSize,
|
|
Total: total,
|
|
List: list,
|
|
})
|
|
}
|
|
}
|
|
|
|
// ---------- 手动同步 API ----------
|
|
|
|
type syncDouyinOrdersResponse struct {
|
|
Message string `json:"message"`
|
|
TotalFetched int `json:"total_fetched"`
|
|
NewOrders int `json:"new_orders"`
|
|
MatchedUsers int `json:"matched_users"`
|
|
}
|
|
|
|
func (h *handler) SyncDouyinOrders() core.HandlerFunc {
|
|
return func(ctx core.Context) {
|
|
result, err := h.douyinSvc.FetchAndSyncOrders(ctx.RequestContext())
|
|
if err != nil {
|
|
ctx.AbortWithError(core.Error(http.StatusBadRequest, code.ServerError, validation.Error(err)))
|
|
return
|
|
}
|
|
|
|
ctx.Payload(syncDouyinOrdersResponse{
|
|
Message: "同步成功",
|
|
TotalFetched: result.TotalFetched,
|
|
NewOrders: result.NewOrders,
|
|
MatchedUsers: result.MatchedUsers,
|
|
})
|
|
}
|
|
}
|
|
|
|
// ---------- 辅助函数 ----------
|
|
|
|
func getOrderStatusText(status int32) string {
|
|
switch status {
|
|
case 1:
|
|
return "待付款"
|
|
case 2:
|
|
return "待发货"
|
|
case 3:
|
|
return "已发货"
|
|
case 4:
|
|
return "已取消"
|
|
case 5:
|
|
return "已完成"
|
|
default:
|
|
return "未知"
|
|
}
|
|
}
|
|
|
|
func formatAmount(amountCents int64) string {
|
|
yuan := float64(amountCents) / 100.0
|
|
return fmt.Sprintf("%.2f", yuan)
|
|
}
|
|
|
|
// SetDouyinService 设置抖店服务 (用于 handler 初始化)
|
|
func (h *handler) SetDouyinService(svc douyin.Service) {
|
|
h.douyinSvc = svc
|
|
}
|