This commit is contained in:
2025-05-27 18:35:01 +08:00
parent ca66cc91d4
commit 79e1ba2616
115 changed files with 22039 additions and 1045 deletions

View File

@@ -0,0 +1,45 @@
package admin_feature
import (
"context"
"tyc-server/app/main/api/internal/svc"
"tyc-server/app/main/api/internal/types"
"tyc-server/app/main/model"
"tyc-server/common/xerr"
"github.com/pkg/errors"
"github.com/zeromicro/go-zero/core/logx"
)
type AdminCreateFeatureLogic struct {
logx.Logger
ctx context.Context
svcCtx *svc.ServiceContext
}
func NewAdminCreateFeatureLogic(ctx context.Context, svcCtx *svc.ServiceContext) *AdminCreateFeatureLogic {
return &AdminCreateFeatureLogic{
Logger: logx.WithContext(ctx),
ctx: ctx,
svcCtx: svcCtx,
}
}
func (l *AdminCreateFeatureLogic) AdminCreateFeature(req *types.AdminCreateFeatureReq) (resp *types.AdminCreateFeatureResp, err error) {
// 1. 数据转换
data := &model.Feature{
ApiId: req.ApiId,
Name: req.Name,
}
// 2. 数据库操作
result, err := l.svcCtx.FeatureModel.Insert(l.ctx, nil, data)
if err != nil {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR),
"创建功能失败, err: %v, req: %+v", err, req)
}
// 3. 返回结果
id, _ := result.LastInsertId()
return &types.AdminCreateFeatureResp{Id: id}, nil
}

View File

@@ -0,0 +1,44 @@
package admin_feature
import (
"context"
"tyc-server/app/main/api/internal/svc"
"tyc-server/app/main/api/internal/types"
"tyc-server/common/xerr"
"github.com/pkg/errors"
"github.com/zeromicro/go-zero/core/logx"
)
type AdminDeleteFeatureLogic struct {
logx.Logger
ctx context.Context
svcCtx *svc.ServiceContext
}
func NewAdminDeleteFeatureLogic(ctx context.Context, svcCtx *svc.ServiceContext) *AdminDeleteFeatureLogic {
return &AdminDeleteFeatureLogic{
Logger: logx.WithContext(ctx),
ctx: ctx,
svcCtx: svcCtx,
}
}
func (l *AdminDeleteFeatureLogic) AdminDeleteFeature(req *types.AdminDeleteFeatureReq) (resp *types.AdminDeleteFeatureResp, err error) {
// 1. 查询记录是否存在
record, err := l.svcCtx.FeatureModel.FindOne(l.ctx, req.Id)
if err != nil {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR),
"查找功能失败, err: %v, id: %d", err, req.Id)
}
// 2. 执行软删除
err = l.svcCtx.FeatureModel.DeleteSoft(l.ctx, nil, record)
if err != nil {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR),
"删除功能失败, err: %v, id: %d", err, req.Id)
}
// 3. 返回结果
return &types.AdminDeleteFeatureResp{Success: true}, nil
}

View File

@@ -0,0 +1,45 @@
package admin_feature
import (
"context"
"tyc-server/app/main/api/internal/svc"
"tyc-server/app/main/api/internal/types"
"tyc-server/common/xerr"
"github.com/pkg/errors"
"github.com/zeromicro/go-zero/core/logx"
)
type AdminGetFeatureDetailLogic struct {
logx.Logger
ctx context.Context
svcCtx *svc.ServiceContext
}
func NewAdminGetFeatureDetailLogic(ctx context.Context, svcCtx *svc.ServiceContext) *AdminGetFeatureDetailLogic {
return &AdminGetFeatureDetailLogic{
Logger: logx.WithContext(ctx),
ctx: ctx,
svcCtx: svcCtx,
}
}
func (l *AdminGetFeatureDetailLogic) AdminGetFeatureDetail(req *types.AdminGetFeatureDetailReq) (resp *types.AdminGetFeatureDetailResp, err error) {
// 1. 查询记录
record, err := l.svcCtx.FeatureModel.FindOne(l.ctx, req.Id)
if err != nil {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR),
"查找功能失败, err: %v, id: %d", err, req.Id)
}
// 2. 构建响应
resp = &types.AdminGetFeatureDetailResp{
Id: record.Id,
ApiId: record.ApiId,
Name: record.Name,
CreateTime: record.CreateTime.Format("2006-01-02 15:04:05"),
UpdateTime: record.UpdateTime.Format("2006-01-02 15:04:05"),
}
return resp, nil
}

View File

@@ -0,0 +1,65 @@
package admin_feature
import (
"context"
"tyc-server/app/main/api/internal/svc"
"tyc-server/app/main/api/internal/types"
"tyc-server/common/xerr"
"github.com/pkg/errors"
"github.com/zeromicro/go-zero/core/logx"
)
type AdminGetFeatureListLogic struct {
logx.Logger
ctx context.Context
svcCtx *svc.ServiceContext
}
func NewAdminGetFeatureListLogic(ctx context.Context, svcCtx *svc.ServiceContext) *AdminGetFeatureListLogic {
return &AdminGetFeatureListLogic{
Logger: logx.WithContext(ctx),
ctx: ctx,
svcCtx: svcCtx,
}
}
func (l *AdminGetFeatureListLogic) AdminGetFeatureList(req *types.AdminGetFeatureListReq) (resp *types.AdminGetFeatureListResp, err error) {
// 1. 构建查询条件
builder := l.svcCtx.FeatureModel.SelectBuilder()
// 2. 添加查询条件
if req.ApiId != nil && *req.ApiId != "" {
builder = builder.Where("api_id LIKE ?", "%"+*req.ApiId+"%")
}
if req.Name != nil && *req.Name != "" {
builder = builder.Where("name LIKE ?", "%"+*req.Name+"%")
}
// 3. 执行分页查询
list, total, err := l.svcCtx.FeatureModel.FindPageListByPageWithTotal(
l.ctx, builder, req.Page, req.PageSize, "id DESC")
if err != nil {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR),
"查询功能列表失败, err: %v, req: %+v", err, req)
}
// 4. 构建响应列表
items := make([]types.FeatureListItem, 0, len(list))
for _, item := range list {
listItem := types.FeatureListItem{
Id: item.Id,
ApiId: item.ApiId,
Name: item.Name,
CreateTime: item.CreateTime.Format("2006-01-02 15:04:05"),
UpdateTime: item.UpdateTime.Format("2006-01-02 15:04:05"),
}
items = append(items, listItem)
}
// 5. 返回结果
return &types.AdminGetFeatureListResp{
Total: total,
Items: items,
}, nil
}

View File

@@ -0,0 +1,30 @@
package admin_feature
import (
"context"
"tyc-server/app/main/api/internal/svc"
"tyc-server/app/main/api/internal/types"
"github.com/zeromicro/go-zero/core/logx"
)
type AdminUpdateFeatureLogic struct {
logx.Logger
ctx context.Context
svcCtx *svc.ServiceContext
}
func NewAdminUpdateFeatureLogic(ctx context.Context, svcCtx *svc.ServiceContext) *AdminUpdateFeatureLogic {
return &AdminUpdateFeatureLogic{
Logger: logx.WithContext(ctx),
ctx: ctx,
svcCtx: svcCtx,
}
}
func (l *AdminUpdateFeatureLogic) AdminUpdateFeature(req *types.AdminUpdateFeatureReq) (resp *types.AdminUpdateFeatureResp, err error) {
// todo: add your logic here and delete this line
return
}

View File

@@ -0,0 +1,49 @@
package admin_notification
import (
"context"
"database/sql"
"time"
"tyc-server/app/main/api/internal/svc"
"tyc-server/app/main/api/internal/types"
"tyc-server/app/main/model"
"tyc-server/common/xerr"
"github.com/pkg/errors"
"github.com/zeromicro/go-zero/core/logx"
)
type AdminCreateNotificationLogic struct {
logx.Logger
ctx context.Context
svcCtx *svc.ServiceContext
}
func NewAdminCreateNotificationLogic(ctx context.Context, svcCtx *svc.ServiceContext) *AdminCreateNotificationLogic {
return &AdminCreateNotificationLogic{
Logger: logx.WithContext(ctx),
ctx: ctx,
svcCtx: svcCtx,
}
}
func (l *AdminCreateNotificationLogic) AdminCreateNotification(req *types.AdminCreateNotificationReq) (resp *types.AdminCreateNotificationResp, err error) {
startDate, _ := time.Parse("2006-01-02", req.StartDate)
endDate, _ := time.Parse("2006-01-02", req.EndDate)
data := &model.GlobalNotifications{
Title: req.Title,
Content: req.Content,
NotificationPage: req.NotificationPage,
StartDate: sql.NullTime{Time: startDate, Valid: req.StartDate != ""},
EndDate: sql.NullTime{Time: endDate, Valid: req.EndDate != ""},
StartTime: req.StartTime,
EndTime: req.EndTime,
Status: req.Status,
}
result, err := l.svcCtx.GlobalNotificationsModel.Insert(l.ctx, nil, data)
if err != nil {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "创建通知失败, err: %v, req: %+v", err, req)
}
id, _ := result.LastInsertId()
return &types.AdminCreateNotificationResp{Id: id}, nil
}

View File

@@ -0,0 +1,38 @@
package admin_notification
import (
"context"
"tyc-server/app/main/api/internal/svc"
"tyc-server/app/main/api/internal/types"
"tyc-server/common/xerr"
"github.com/pkg/errors"
"github.com/zeromicro/go-zero/core/logx"
)
type AdminDeleteNotificationLogic struct {
logx.Logger
ctx context.Context
svcCtx *svc.ServiceContext
}
func NewAdminDeleteNotificationLogic(ctx context.Context, svcCtx *svc.ServiceContext) *AdminDeleteNotificationLogic {
return &AdminDeleteNotificationLogic{
Logger: logx.WithContext(ctx),
ctx: ctx,
svcCtx: svcCtx,
}
}
func (l *AdminDeleteNotificationLogic) AdminDeleteNotification(req *types.AdminDeleteNotificationReq) (resp *types.AdminDeleteNotificationResp, err error) {
notification, err := l.svcCtx.GlobalNotificationsModel.FindOne(l.ctx, req.Id)
if err != nil {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "查找通知失败, err: %v, id: %d", err, req.Id)
}
err = l.svcCtx.GlobalNotificationsModel.DeleteSoft(l.ctx, nil, notification)
if err != nil {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "删除通知失败, err: %v, id: %d", err, req.Id)
}
return &types.AdminDeleteNotificationResp{Success: true}, nil
}

View File

@@ -0,0 +1,53 @@
package admin_notification
import (
"context"
"tyc-server/app/main/api/internal/svc"
"tyc-server/app/main/api/internal/types"
"tyc-server/common/xerr"
"github.com/pkg/errors"
"github.com/zeromicro/go-zero/core/logx"
)
type AdminGetNotificationDetailLogic struct {
logx.Logger
ctx context.Context
svcCtx *svc.ServiceContext
}
func NewAdminGetNotificationDetailLogic(ctx context.Context, svcCtx *svc.ServiceContext) *AdminGetNotificationDetailLogic {
return &AdminGetNotificationDetailLogic{
Logger: logx.WithContext(ctx),
ctx: ctx,
svcCtx: svcCtx,
}
}
func (l *AdminGetNotificationDetailLogic) AdminGetNotificationDetail(req *types.AdminGetNotificationDetailReq) (resp *types.AdminGetNotificationDetailResp, err error) {
notification, err := l.svcCtx.GlobalNotificationsModel.FindOne(l.ctx, req.Id)
if err != nil {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "查找通知失败, err: %v, id: %d", err, req.Id)
}
resp = &types.AdminGetNotificationDetailResp{
Id: notification.Id,
Title: notification.Title,
Content: notification.Content,
NotificationPage: notification.NotificationPage,
StartDate: "",
StartTime: notification.StartTime,
EndDate: "",
EndTime: notification.EndTime,
Status: notification.Status,
CreateTime: notification.CreateTime.Format("2006-01-02 15:04:05"),
UpdateTime: notification.UpdateTime.Format("2006-01-02 15:04:05"),
}
if notification.StartDate.Valid {
resp.StartDate = notification.StartDate.Time.Format("2006-01-02")
}
if notification.EndDate.Valid {
resp.EndDate = notification.EndDate.Time.Format("2006-01-02")
}
return resp, nil
}

View File

@@ -0,0 +1,83 @@
package admin_notification
import (
"context"
"tyc-server/app/main/api/internal/svc"
"tyc-server/app/main/api/internal/types"
"tyc-server/common/xerr"
"time"
"github.com/pkg/errors"
"github.com/zeromicro/go-zero/core/logx"
)
type AdminGetNotificationListLogic struct {
logx.Logger
ctx context.Context
svcCtx *svc.ServiceContext
}
func NewAdminGetNotificationListLogic(ctx context.Context, svcCtx *svc.ServiceContext) *AdminGetNotificationListLogic {
return &AdminGetNotificationListLogic{
Logger: logx.WithContext(ctx),
ctx: ctx,
svcCtx: svcCtx,
}
}
func (l *AdminGetNotificationListLogic) AdminGetNotificationList(req *types.AdminGetNotificationListReq) (resp *types.AdminGetNotificationListResp, err error) {
builder := l.svcCtx.GlobalNotificationsModel.SelectBuilder()
if req.Title != nil {
builder = builder.Where("title LIKE ?", "%"+*req.Title+"%")
}
if req.NotificationPage != nil {
builder = builder.Where("notification_page = ?", *req.NotificationPage)
}
if req.Status != nil {
builder = builder.Where("status = ?", *req.Status)
}
if req.StartDate != nil {
if t, err := time.Parse("2006-01-02", *req.StartDate); err == nil {
builder = builder.Where("start_date >= ?", t)
}
}
if req.EndDate != nil {
if t, err := time.Parse("2006-01-02", *req.EndDate); err == nil {
builder = builder.Where("end_date <= ?", t)
}
}
list, total, err := l.svcCtx.GlobalNotificationsModel.FindPageListByPageWithTotal(l.ctx, builder, req.Page, req.PageSize, "id DESC")
if err != nil {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "查询通知列表失败, err: %v, req: %+v", err, req)
}
items := make([]types.NotificationListItem, 0, len(list))
for _, n := range list {
item := types.NotificationListItem{
Id: n.Id,
Title: n.Title,
NotificationPage: n.NotificationPage,
Content: n.Content,
StartDate: "",
StartTime: n.StartTime,
EndDate: "",
EndTime: n.EndTime,
Status: n.Status,
CreateTime: n.CreateTime.Format("2006-01-02 15:04:05"),
UpdateTime: n.UpdateTime.Format("2006-01-02 15:04:05"),
}
if n.StartDate.Valid {
item.StartDate = n.StartDate.Time.Format("2006-01-02")
}
if n.EndDate.Valid {
item.EndDate = n.EndDate.Time.Format("2006-01-02")
}
items = append(items, item)
}
resp = &types.AdminGetNotificationListResp{
Total: total,
Items: items,
}
return resp, nil
}

View File

@@ -0,0 +1,65 @@
package admin_notification
import (
"context"
"database/sql"
"time"
"tyc-server/app/main/api/internal/svc"
"tyc-server/app/main/api/internal/types"
"tyc-server/common/xerr"
"github.com/pkg/errors"
"github.com/zeromicro/go-zero/core/logx"
)
type AdminUpdateNotificationLogic struct {
logx.Logger
ctx context.Context
svcCtx *svc.ServiceContext
}
func NewAdminUpdateNotificationLogic(ctx context.Context, svcCtx *svc.ServiceContext) *AdminUpdateNotificationLogic {
return &AdminUpdateNotificationLogic{
Logger: logx.WithContext(ctx),
ctx: ctx,
svcCtx: svcCtx,
}
}
func (l *AdminUpdateNotificationLogic) AdminUpdateNotification(req *types.AdminUpdateNotificationReq) (resp *types.AdminUpdateNotificationResp, err error) {
notification, err := l.svcCtx.GlobalNotificationsModel.FindOne(l.ctx, req.Id)
if err != nil {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "查找通知失败, err: %v, id: %d", err, req.Id)
}
if req.StartDate != nil {
startDate, _ := time.Parse("2006-01-02", *req.StartDate)
notification.StartDate = sql.NullTime{Time: startDate, Valid: true}
}
if req.EndDate != nil {
endDate, _ := time.Parse("2006-01-02", *req.EndDate)
notification.EndDate = sql.NullTime{Time: endDate, Valid: true}
}
if req.Title != nil {
notification.Title = *req.Title
}
if req.Content != nil {
notification.Content = *req.Content
}
if req.NotificationPage != nil {
notification.NotificationPage = *req.NotificationPage
}
if req.StartTime != nil {
notification.StartTime = *req.StartTime
}
if req.EndTime != nil {
notification.EndTime = *req.EndTime
}
if req.Status != nil {
notification.Status = *req.Status
}
_, err = l.svcCtx.GlobalNotificationsModel.Update(l.ctx, nil, notification)
if err != nil {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "更新通知失败, err: %v, req: %+v", err, req)
}
return &types.AdminUpdateNotificationResp{Success: true}, nil
}

View File

@@ -0,0 +1,99 @@
package admin_order
import (
"context"
"database/sql"
"fmt"
"time"
"tyc-server/app/main/api/internal/svc"
"tyc-server/app/main/api/internal/types"
"tyc-server/app/main/model"
"tyc-server/common/xerr"
"github.com/pkg/errors"
"github.com/zeromicro/go-zero/core/logx"
"github.com/zeromicro/go-zero/core/stores/sqlx"
)
type AdminCreateOrderLogic struct {
logx.Logger
ctx context.Context
svcCtx *svc.ServiceContext
}
func NewAdminCreateOrderLogic(ctx context.Context, svcCtx *svc.ServiceContext) *AdminCreateOrderLogic {
return &AdminCreateOrderLogic{
Logger: logx.WithContext(ctx),
ctx: ctx,
svcCtx: svcCtx,
}
}
func (l *AdminCreateOrderLogic) AdminCreateOrder(req *types.AdminCreateOrderReq) (resp *types.AdminCreateOrderResp, err error) {
// 生成订单号
orderNo := fmt.Sprintf("%dADMIN", time.Now().UnixNano())
// 根据产品名称查询产品ID
builder := l.svcCtx.ProductModel.SelectBuilder()
builder = builder.Where("product_name = ? AND del_state = ?", req.ProductName, 0)
products, err := l.svcCtx.ProductModel.FindAll(l.ctx, builder, "")
if err != nil {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "AdminCreateOrder, 查询产品失败 err: %v", err)
}
if len(products) == 0 {
return nil, errors.Wrapf(xerr.NewErrMsg(fmt.Sprintf("产品不存在: %s", req.ProductName)), "AdminCreateOrder, 查询产品失败 err: %v", err)
}
product := products[0]
// 创建订单对象
order := &model.Order{
OrderNo: orderNo,
PlatformOrderId: sql.NullString{String: req.PlatformOrderId, Valid: req.PlatformOrderId != ""},
ProductId: product.Id,
PaymentPlatform: req.PaymentPlatform,
PaymentScene: req.PaymentScene,
Amount: req.Amount,
Status: req.Status,
}
// 使用事务处理订单创建
var orderId int64
err = l.svcCtx.OrderModel.Trans(l.ctx, func(ctx context.Context, session sqlx.Session) error {
// 插入订单
result, err := l.svcCtx.OrderModel.Insert(ctx, session, order)
if err != nil {
return errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "AdminCreateOrder, 创建订单失败 err: %v", err)
}
// 获取订单ID
orderId, err = result.LastInsertId()
if err != nil {
return errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "AdminCreateOrder, 获取订单ID失败 err: %v", err)
}
// 如果是推广订单,创建推广订单记录
if req.IsPromotion == 1 {
promotionOrder := &model.AdminPromotionOrder{
OrderId: orderId,
Version: 1,
CreateTime: time.Now(),
UpdateTime: time.Now(),
}
_, err = l.svcCtx.AdminPromotionOrderModel.Insert(ctx, session, promotionOrder)
if err != nil {
return errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "AdminCreateOrder, 创建推广订单失败 err: %v", err)
}
}
return nil
})
if err != nil {
return nil, err
}
return &types.AdminCreateOrderResp{
Id: orderId,
}, nil
}

View File

@@ -0,0 +1,63 @@
package admin_order
import (
"context"
"tyc-server/app/main/api/internal/svc"
"tyc-server/app/main/api/internal/types"
"tyc-server/common/xerr"
"github.com/pkg/errors"
"github.com/zeromicro/go-zero/core/logx"
"github.com/zeromicro/go-zero/core/stores/sqlx"
)
type AdminDeleteOrderLogic struct {
logx.Logger
ctx context.Context
svcCtx *svc.ServiceContext
}
func NewAdminDeleteOrderLogic(ctx context.Context, svcCtx *svc.ServiceContext) *AdminDeleteOrderLogic {
return &AdminDeleteOrderLogic{
Logger: logx.WithContext(ctx),
ctx: ctx,
svcCtx: svcCtx,
}
}
func (l *AdminDeleteOrderLogic) AdminDeleteOrder(req *types.AdminDeleteOrderReq) (resp *types.AdminDeleteOrderResp, err error) {
// 获取订单信息
order, err := l.svcCtx.OrderModel.FindOne(l.ctx, req.Id)
if err != nil {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "AdminDeleteOrder, 查询订单失败 err: %v", err)
}
// 使用事务删除订单
err = l.svcCtx.OrderModel.Trans(l.ctx, func(ctx context.Context, session sqlx.Session) error {
// 软删除订单
err := l.svcCtx.OrderModel.DeleteSoft(ctx, session, order)
if err != nil {
return errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "AdminDeleteOrder, 删除订单失败 err: %v", err)
}
// 删除关联的推广订单记录
promotionOrder, err := l.svcCtx.AdminPromotionOrderModel.FindOneByOrderId(ctx, order.Id)
if err == nil && promotionOrder != nil {
err = l.svcCtx.AdminPromotionOrderModel.DeleteSoft(ctx, session, promotionOrder)
if err != nil {
return errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "AdminDeleteOrder, 删除推广订单失败 err: %v", err)
}
}
return nil
})
if err != nil {
return nil, err
}
return &types.AdminDeleteOrderResp{
Success: true,
}, nil
}

View File

@@ -0,0 +1,72 @@
package admin_order
import (
"context"
"tyc-server/app/main/api/internal/svc"
"tyc-server/app/main/api/internal/types"
"tyc-server/common/xerr"
"github.com/pkg/errors"
"github.com/zeromicro/go-zero/core/logx"
)
type AdminGetOrderDetailLogic struct {
logx.Logger
ctx context.Context
svcCtx *svc.ServiceContext
}
func NewAdminGetOrderDetailLogic(ctx context.Context, svcCtx *svc.ServiceContext) *AdminGetOrderDetailLogic {
return &AdminGetOrderDetailLogic{
Logger: logx.WithContext(ctx),
ctx: ctx,
svcCtx: svcCtx,
}
}
func (l *AdminGetOrderDetailLogic) AdminGetOrderDetail(req *types.AdminGetOrderDetailReq) (resp *types.AdminGetOrderDetailResp, err error) {
// 获取订单信息
order, err := l.svcCtx.OrderModel.FindOne(l.ctx, req.Id)
if err != nil {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "AdminGetOrderDetail, 查询订单失败 err: %v", err)
}
// 获取产品信息
product, err := l.svcCtx.ProductModel.FindOne(l.ctx, order.ProductId)
if err != nil {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "AdminGetOrderDetail, 查询产品失败 err: %v", err)
}
// 判断是否为推广订单
var isPromotion int64
promotionOrder, err := l.svcCtx.AdminPromotionOrderModel.FindOneByOrderId(l.ctx, order.Id)
if err == nil && promotionOrder != nil {
isPromotion = 1
}
// 构建响应
resp = &types.AdminGetOrderDetailResp{
Id: order.Id,
OrderNo: order.OrderNo,
PlatformOrderId: order.PlatformOrderId.String,
ProductName: product.ProductName,
PaymentPlatform: order.PaymentPlatform,
PaymentScene: order.PaymentScene,
Amount: order.Amount,
Status: order.Status,
CreateTime: order.CreateTime.Format("2006-01-02 15:04:05"),
UpdateTime: order.UpdateTime.Format("2006-01-02 15:04:05"),
IsPromotion: isPromotion,
}
// 处理可选字段
if order.PayTime.Valid {
resp.PayTime = order.PayTime.Time.Format("2006-01-02 15:04:05")
}
if order.RefundTime.Valid {
resp.RefundTime = order.RefundTime.Time.Format("2006-01-02 15:04:05")
}
return resp, nil
}

View File

@@ -0,0 +1,159 @@
package admin_order
import (
"context"
"sync"
"tyc-server/app/main/api/internal/svc"
"tyc-server/app/main/api/internal/types"
"tyc-server/app/main/model"
"tyc-server/common/xerr"
"github.com/pkg/errors"
"github.com/zeromicro/go-zero/core/logx"
"github.com/zeromicro/go-zero/core/mr"
)
type AdminGetOrderListLogic struct {
logx.Logger
ctx context.Context
svcCtx *svc.ServiceContext
}
func NewAdminGetOrderListLogic(ctx context.Context, svcCtx *svc.ServiceContext) *AdminGetOrderListLogic {
return &AdminGetOrderListLogic{
Logger: logx.WithContext(ctx),
ctx: ctx,
svcCtx: svcCtx,
}
}
func (l *AdminGetOrderListLogic) AdminGetOrderList(req *types.AdminGetOrderListReq) (resp *types.AdminGetOrderListResp, err error) {
// 构建查询条件
builder := l.svcCtx.OrderModel.SelectBuilder()
if req.OrderNo != "" {
builder = builder.Where("order_no = ?", req.OrderNo)
}
if req.PlatformOrderId != "" {
builder = builder.Where("platform_order_id = ?", req.PlatformOrderId)
}
if req.ProductName != "" {
builder = builder.Where("product_id IN (SELECT id FROM product WHERE product_name LIKE ?)", "%"+req.ProductName+"%")
}
if req.PaymentPlatform != "" {
builder = builder.Where("payment_platform = ?", req.PaymentPlatform)
}
if req.PaymentScene != "" {
builder = builder.Where("payment_scene = ?", req.PaymentScene)
}
if req.Amount > 0 {
builder = builder.Where("amount = ?", req.Amount)
}
if req.Status != "" {
builder = builder.Where("status = ?", req.Status)
}
if req.IsPromotion != -1 {
builder = builder.Where("id IN (SELECT order_id FROM admin_promotion_order WHERE del_state = 0)")
}
// 时间范围查询
if req.CreateTimeStart != "" {
builder = builder.Where("create_time >= ?", req.CreateTimeStart)
}
if req.CreateTimeEnd != "" {
builder = builder.Where("create_time <= ?", req.CreateTimeEnd)
}
if req.PayTimeStart != "" {
builder = builder.Where("pay_time >= ?", req.PayTimeStart)
}
if req.PayTimeEnd != "" {
builder = builder.Where("pay_time <= ?", req.PayTimeEnd)
}
if req.RefundTimeStart != "" {
builder = builder.Where("refund_time >= ?", req.RefundTimeStart)
}
if req.RefundTimeEnd != "" {
builder = builder.Where("refund_time <= ?", req.RefundTimeEnd)
}
// 并发获取总数和列表
var total int64
var orders []*model.Order
err = mr.Finish(func() error {
var err error
total, err = l.svcCtx.OrderModel.FindCount(l.ctx, builder, "id")
if err != nil {
return errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "AdminGetOrderList, 查询订单总数失败 err: %v", err)
}
return nil
}, func() error {
var err error
orders, err = l.svcCtx.OrderModel.FindPageListByPage(l.ctx, builder, req.Page, req.PageSize, "id DESC")
if err != nil {
return errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "AdminGetOrderList, 查询订单列表失败 err: %v", err)
}
return nil
})
if err != nil {
return nil, err
}
// 并发获取产品信息
productMap := make(map[int64]string)
var mu sync.Mutex
err = mr.MapReduceVoid(func(source chan<- interface{}) {
for _, order := range orders {
source <- order.ProductId
}
}, func(item interface{}, writer mr.Writer[struct{}], cancel func(error)) {
productId := item.(int64)
product, err := l.svcCtx.ProductModel.FindOne(l.ctx, productId)
if err != nil {
cancel(errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "AdminGetOrderList, 查询产品信息失败 err: %v", err))
return
}
mu.Lock()
productMap[product.Id] = product.ProductName
mu.Unlock()
writer.Write(struct{}{})
}, func(pipe <-chan struct{}, cancel func(error)) {
for range pipe {
}
})
if err != nil {
return nil, err
}
// 构建响应
resp = &types.AdminGetOrderListResp{
Total: total,
Items: make([]types.OrderListItem, 0, len(orders)),
}
for _, order := range orders {
item := types.OrderListItem{
Id: order.Id,
OrderNo: order.OrderNo,
PlatformOrderId: order.PlatformOrderId.String,
ProductName: productMap[order.ProductId],
PaymentPlatform: order.PaymentPlatform,
PaymentScene: order.PaymentScene,
Amount: order.Amount,
Status: order.Status,
CreateTime: order.CreateTime.Format("2006-01-02 15:04:05"),
}
if order.PayTime.Valid {
item.PayTime = order.PayTime.Time.Format("2006-01-02 15:04:05")
}
if order.RefundTime.Valid {
item.RefundTime = order.RefundTime.Time.Format("2006-01-02 15:04:05")
}
// 判断是否为推广订单
promotionOrder, err := l.svcCtx.AdminPromotionOrderModel.FindOneByOrderId(l.ctx, order.Id)
if err == nil && promotionOrder != nil {
item.IsPromotion = 1
}
resp.Items = append(resp.Items, item)
}
return resp, nil
}

View File

@@ -0,0 +1,60 @@
package admin_order
import (
"context"
"tyc-server/app/main/api/internal/service"
"tyc-server/app/main/api/internal/svc"
"tyc-server/app/main/api/internal/types"
"tyc-server/common/xerr"
"github.com/pkg/errors"
"github.com/zeromicro/go-zero/core/logx"
)
type AdminRefundOrderLogic struct {
logx.Logger
ctx context.Context
svcCtx *svc.ServiceContext
}
func NewAdminRefundOrderLogic(ctx context.Context, svcCtx *svc.ServiceContext) *AdminRefundOrderLogic {
return &AdminRefundOrderLogic{
Logger: logx.WithContext(ctx),
ctx: ctx,
svcCtx: svcCtx,
}
}
func (l *AdminRefundOrderLogic) AdminRefundOrder(req *types.AdminRefundOrderReq) (resp *types.AdminRefundOrderResp, err error) {
// 获取订单信息
order, err := l.svcCtx.OrderModel.FindOne(l.ctx, req.Id)
if err != nil {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "AdminRefundOrder, 查询订单失败 err: %v", err)
}
// 检查订单状态
if order.Status != "paid" {
return nil, errors.Wrapf(xerr.NewErrMsg("订单状态不正确,无法退款"), "AdminRefundOrder, 订单状态不正确,无法退款 err: %v", err)
}
// 检查退款金额
if req.RefundAmount > order.Amount {
return nil, errors.Wrapf(xerr.NewErrMsg("退款金额不能大于订单金额"), "AdminRefundOrder, 退款金额不能大于订单金额 err: %v", err)
}
refundResp, err := l.svcCtx.PayService.Refund(l.ctx, &service.RefundRequest{
OrderId: order.Id,
RefundAmount: req.RefundAmount,
Reason: req.RefundReason,
})
if err != nil {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "AdminRefundOrder, 退款失败 err: %v", err)
}
return &types.AdminRefundOrderResp{
Status: refundResp.Status,
RefundNo: refundResp.RefundNo,
Amount: refundResp.Amount,
}, nil
}

View File

@@ -0,0 +1,113 @@
package admin_order
import (
"context"
"database/sql"
"time"
"tyc-server/app/main/api/internal/svc"
"tyc-server/app/main/api/internal/types"
"tyc-server/app/main/model"
"tyc-server/common/xerr"
"github.com/pkg/errors"
"github.com/zeromicro/go-zero/core/logx"
"github.com/zeromicro/go-zero/core/stores/sqlx"
)
type AdminUpdateOrderLogic struct {
logx.Logger
ctx context.Context
svcCtx *svc.ServiceContext
}
func NewAdminUpdateOrderLogic(ctx context.Context, svcCtx *svc.ServiceContext) *AdminUpdateOrderLogic {
return &AdminUpdateOrderLogic{
Logger: logx.WithContext(ctx),
ctx: ctx,
svcCtx: svcCtx,
}
}
func (l *AdminUpdateOrderLogic) AdminUpdateOrder(req *types.AdminUpdateOrderReq) (resp *types.AdminUpdateOrderResp, err error) {
// 获取原订单信息
order, err := l.svcCtx.OrderModel.FindOne(l.ctx, req.Id)
if err != nil {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "AdminUpdateOrder, 查询订单失败 err: %v", err)
}
// 更新订单字段
if req.OrderNo != nil {
order.OrderNo = *req.OrderNo
}
if req.PlatformOrderId != nil {
order.PlatformOrderId = sql.NullString{String: *req.PlatformOrderId, Valid: true}
}
if req.PaymentPlatform != nil {
order.PaymentPlatform = *req.PaymentPlatform
}
if req.PaymentScene != nil {
order.PaymentScene = *req.PaymentScene
}
if req.Amount != nil {
order.Amount = *req.Amount
}
if req.Status != nil {
order.Status = *req.Status
}
if req.PayTime != nil {
payTime, err := time.Parse("2006-01-02 15:04:05", *req.PayTime)
if err == nil {
order.PayTime = sql.NullTime{Time: payTime, Valid: true}
}
}
if req.RefundTime != nil {
refundTime, err := time.Parse("2006-01-02 15:04:05", *req.RefundTime)
if err == nil {
order.RefundTime = sql.NullTime{Time: refundTime, Valid: true}
}
}
// 使用事务更新订单
err = l.svcCtx.OrderModel.Trans(l.ctx, func(ctx context.Context, session sqlx.Session) error {
// 更新订单
_, err := l.svcCtx.OrderModel.Update(ctx, session, order)
if err != nil {
return errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "AdminUpdateOrder, 更新订单失败 err: %v", err)
}
// 处理推广订单状态
if req.IsPromotion != nil {
promotionOrder, err := l.svcCtx.AdminPromotionOrderModel.FindOneByOrderId(ctx, order.Id)
if err == nil && promotionOrder != nil {
// 如果存在推广订单记录但不需要推广,则删除
if *req.IsPromotion == 0 {
err = l.svcCtx.AdminPromotionOrderModel.DeleteSoft(ctx, session, promotionOrder)
if err != nil {
return errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "AdminUpdateOrder, 删除推广订单失败 err: %v", err)
}
}
} else if *req.IsPromotion == 1 {
// 如果需要推广但不存在记录,则创建
newPromotionOrder := &model.AdminPromotionOrder{
OrderId: order.Id,
Version: 1,
}
_, err = l.svcCtx.AdminPromotionOrderModel.Insert(ctx, session, newPromotionOrder)
if err != nil {
return errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "AdminUpdateOrder, 创建推广订单失败 err: %v", err)
}
}
}
return nil
})
if err != nil {
return nil, err
}
return &types.AdminUpdateOrderResp{
Success: true,
}, nil
}

View File

@@ -0,0 +1,57 @@
package admin_platform_user
import (
"context"
"database/sql"
"tyc-server/app/main/api/internal/svc"
"tyc-server/app/main/api/internal/types"
"tyc-server/app/main/model"
"tyc-server/common/xerr"
"github.com/pkg/errors"
"github.com/zeromicro/go-zero/core/logx"
)
type AdminCreatePlatformUserLogic struct {
logx.Logger
ctx context.Context
svcCtx *svc.ServiceContext
}
func NewAdminCreatePlatformUserLogic(ctx context.Context, svcCtx *svc.ServiceContext) *AdminCreatePlatformUserLogic {
return &AdminCreatePlatformUserLogic{
Logger: logx.WithContext(ctx),
ctx: ctx,
svcCtx: svcCtx,
}
}
func (l *AdminCreatePlatformUserLogic) AdminCreatePlatformUser(req *types.AdminCreatePlatformUserReq) (resp *types.AdminCreatePlatformUserResp, err error) {
// 校验手机号唯一性
_, err = l.svcCtx.UserModel.FindOneByMobile(l.ctx, req.Mobile)
if err == nil {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "手机号已存在: %s", req.Mobile)
}
if err != model.ErrNotFound {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "查询手机号失败: %v", err)
}
user := &model.User{
Mobile: req.Mobile,
Password: sql.NullString{String: req.Password, Valid: req.Password != ""},
Nickname: sql.NullString{String: req.Nickname, Valid: req.Nickname != ""},
Info: req.Info,
Inside: req.Inside,
}
result, err := l.svcCtx.UserModel.Insert(l.ctx, nil, user)
if err != nil {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "创建用户失败: %v", err)
}
id, err := result.LastInsertId()
if err != nil {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "获取用户ID失败: %v", err)
}
resp = &types.AdminCreatePlatformUserResp{Id: id}
return resp, nil
}

View File

@@ -0,0 +1,44 @@
package admin_platform_user
import (
"context"
"tyc-server/app/main/api/internal/svc"
"tyc-server/app/main/api/internal/types"
"time"
"tyc-server/common/xerr"
"github.com/pkg/errors"
"github.com/zeromicro/go-zero/core/logx"
)
type AdminDeletePlatformUserLogic struct {
logx.Logger
ctx context.Context
svcCtx *svc.ServiceContext
}
func NewAdminDeletePlatformUserLogic(ctx context.Context, svcCtx *svc.ServiceContext) *AdminDeletePlatformUserLogic {
return &AdminDeletePlatformUserLogic{
Logger: logx.WithContext(ctx),
ctx: ctx,
svcCtx: svcCtx,
}
}
func (l *AdminDeletePlatformUserLogic) AdminDeletePlatformUser(req *types.AdminDeletePlatformUserReq) (resp *types.AdminDeletePlatformUserResp, err error) {
user, err := l.svcCtx.UserModel.FindOne(l.ctx, req.Id)
if err != nil {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "用户不存在: %d, err: %v", req.Id, err)
}
user.DelState = 1
user.DeleteTime.Time = time.Now()
user.DeleteTime.Valid = true
err = l.svcCtx.UserModel.DeleteSoft(l.ctx, nil, user)
if err != nil {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "软删除用户失败: %v", err)
}
resp = &types.AdminDeletePlatformUserResp{Success: true}
return resp, nil
}

View File

@@ -0,0 +1,54 @@
package admin_platform_user
import (
"context"
"tyc-server/app/main/api/internal/svc"
"tyc-server/app/main/api/internal/types"
"tyc-server/pkg/lzkit/crypto"
"tyc-server/common/xerr"
"github.com/pkg/errors"
"github.com/zeromicro/go-zero/core/logx"
)
type AdminGetPlatformUserDetailLogic struct {
logx.Logger
ctx context.Context
svcCtx *svc.ServiceContext
}
func NewAdminGetPlatformUserDetailLogic(ctx context.Context, svcCtx *svc.ServiceContext) *AdminGetPlatformUserDetailLogic {
return &AdminGetPlatformUserDetailLogic{
Logger: logx.WithContext(ctx),
ctx: ctx,
svcCtx: svcCtx,
}
}
func (l *AdminGetPlatformUserDetailLogic) AdminGetPlatformUserDetail(req *types.AdminGetPlatformUserDetailReq) (resp *types.AdminGetPlatformUserDetailResp, err error) {
user, err := l.svcCtx.UserModel.FindOne(l.ctx, req.Id)
if err != nil {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "用户不存在: %d, err: %v", req.Id, err)
}
key := l.svcCtx.Config.Encrypt.SecretKey
DecryptMobile, err := crypto.DecryptMobile(user.Mobile, key)
if err != nil {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "解密手机号失败: %v", err)
}
// 查询平台类型取第一个user_auth
resp = &types.AdminGetPlatformUserDetailResp{
Id: user.Id,
Mobile: DecryptMobile,
Nickname: "",
Info: user.Info,
Inside: user.Inside,
CreateTime: user.CreateTime.Format("2006-01-02 15:04:05"),
UpdateTime: user.UpdateTime.Format("2006-01-02 15:04:05"),
}
if user.Nickname.Valid {
resp.Nickname = user.Nickname.String
}
return resp, nil
}

View File

@@ -0,0 +1,88 @@
package admin_platform_user
import (
"context"
"fmt"
"tyc-server/app/main/api/internal/svc"
"tyc-server/app/main/api/internal/types"
"tyc-server/pkg/lzkit/crypto"
"tyc-server/common/xerr"
"github.com/pkg/errors"
"github.com/zeromicro/go-zero/core/logx"
)
type AdminGetPlatformUserListLogic struct {
logx.Logger
ctx context.Context
svcCtx *svc.ServiceContext
}
func NewAdminGetPlatformUserListLogic(ctx context.Context, svcCtx *svc.ServiceContext) *AdminGetPlatformUserListLogic {
return &AdminGetPlatformUserListLogic{
Logger: logx.WithContext(ctx),
ctx: ctx,
svcCtx: svcCtx,
}
}
func (l *AdminGetPlatformUserListLogic) AdminGetPlatformUserList(req *types.AdminGetPlatformUserListReq) (resp *types.AdminGetPlatformUserListResp, err error) {
builder := l.svcCtx.UserModel.SelectBuilder()
if req.Mobile != "" {
builder = builder.Where("mobile = ?", req.Mobile)
}
if req.Nickname != "" {
builder = builder.Where("nickname = ?", req.Nickname)
}
if req.Inside != 0 {
builder = builder.Where("inside = ?", req.Inside)
}
if req.CreateTimeStart != "" {
builder = builder.Where("create_time >= ?", req.CreateTimeStart)
}
if req.CreateTimeEnd != "" {
builder = builder.Where("create_time <= ?", req.CreateTimeEnd)
}
orderBy := "id DESC"
if req.OrderBy != "" && req.OrderType != "" {
orderBy = fmt.Sprintf("%s %s", req.OrderBy, req.OrderType)
}
users, total, err := l.svcCtx.UserModel.FindPageListByPageWithTotal(l.ctx, builder, req.Page, req.PageSize, orderBy)
if err != nil {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "查询用户分页失败: %v", err)
}
var items []types.PlatformUserListItem
secretKey := l.svcCtx.Config.Encrypt.SecretKey
for _, user := range users {
mobile := user.Mobile
if mobile != "" {
encryptedMobile, err := crypto.DecryptMobile(mobile, secretKey)
if err != nil {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "手机登录, 解密手机号失败: %+v", err)
}
mobile = encryptedMobile
}
itemData := types.PlatformUserListItem{
Id: user.Id,
Mobile: mobile,
Nickname: "",
Info: user.Info,
Inside: user.Inside,
CreateTime: user.CreateTime.Format("2006-01-02 15:04:05"),
UpdateTime: user.UpdateTime.Format("2006-01-02 15:04:05"),
}
if user.Nickname.Valid {
itemData.Nickname = user.Nickname.String
}
items = append(items, itemData)
}
resp = &types.AdminGetPlatformUserListResp{
Total: total,
Items: items,
}
return resp, nil
}

View File

@@ -0,0 +1,64 @@
package admin_platform_user
import (
"context"
"database/sql"
"tyc-server/app/main/api/internal/svc"
"tyc-server/app/main/api/internal/types"
"tyc-server/common/xerr"
"tyc-server/pkg/lzkit/crypto"
"github.com/pkg/errors"
"github.com/zeromicro/go-zero/core/logx"
)
type AdminUpdatePlatformUserLogic struct {
logx.Logger
ctx context.Context
svcCtx *svc.ServiceContext
}
func NewAdminUpdatePlatformUserLogic(ctx context.Context, svcCtx *svc.ServiceContext) *AdminUpdatePlatformUserLogic {
return &AdminUpdatePlatformUserLogic{
Logger: logx.WithContext(ctx),
ctx: ctx,
svcCtx: svcCtx,
}
}
func (l *AdminUpdatePlatformUserLogic) AdminUpdatePlatformUser(req *types.AdminUpdatePlatformUserReq) (resp *types.AdminUpdatePlatformUserResp, err error) {
user, err := l.svcCtx.UserModel.FindOne(l.ctx, req.Id)
if err != nil {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "用户不存在: %d, err: %v", req.Id, err)
}
if req.Mobile != nil {
key := l.svcCtx.Config.Encrypt.SecretKey
EncryptMobile, err := crypto.EncryptMobile(*req.Mobile, key)
if err != nil {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "加密手机号失败: %v", err)
}
user.Mobile = EncryptMobile
}
if req.Nickname != nil {
user.Nickname = sql.NullString{String: *req.Nickname, Valid: *req.Nickname != ""}
}
if req.Info != nil {
user.Info = *req.Info
}
if req.Inside != nil {
if *req.Inside != 1 && *req.Inside != 0 {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "内部用户状态错误: %d", *req.Inside)
}
user.Inside = *req.Inside
}
if req.Password != nil {
user.Password = sql.NullString{String: *req.Password, Valid: *req.Password != ""}
}
_, err = l.svcCtx.UserModel.Update(l.ctx, nil, user)
if err != nil {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "更新用户失败: %v", err)
}
resp = &types.AdminUpdatePlatformUserResp{Success: true}
return resp, nil
}

View File

@@ -0,0 +1,50 @@
package admin_product
import (
"context"
"database/sql"
"tyc-server/app/main/api/internal/svc"
"tyc-server/app/main/api/internal/types"
"tyc-server/app/main/model"
"tyc-server/common/xerr"
"github.com/pkg/errors"
"github.com/zeromicro/go-zero/core/logx"
)
type AdminCreateProductLogic struct {
logx.Logger
ctx context.Context
svcCtx *svc.ServiceContext
}
func NewAdminCreateProductLogic(ctx context.Context, svcCtx *svc.ServiceContext) *AdminCreateProductLogic {
return &AdminCreateProductLogic{
Logger: logx.WithContext(ctx),
ctx: ctx,
svcCtx: svcCtx,
}
}
func (l *AdminCreateProductLogic) AdminCreateProduct(req *types.AdminCreateProductReq) (resp *types.AdminCreateProductResp, err error) {
// 1. 数据转换
data := &model.Product{
ProductName: req.ProductName,
ProductEn: req.ProductEn,
Description: req.Description,
Notes: sql.NullString{String: req.Notes, Valid: req.Notes != ""},
CostPrice: req.CostPrice,
SellPrice: req.SellPrice,
}
// 2. 数据库操作
result, err := l.svcCtx.ProductModel.Insert(l.ctx, nil, data)
if err != nil {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR),
"创建产品失败, err: %v, req: %+v", err, req)
}
// 3. 返回结果
id, _ := result.LastInsertId()
return &types.AdminCreateProductResp{Id: id}, nil
}

View File

@@ -0,0 +1,44 @@
package admin_product
import (
"context"
"tyc-server/app/main/api/internal/svc"
"tyc-server/app/main/api/internal/types"
"tyc-server/common/xerr"
"github.com/pkg/errors"
"github.com/zeromicro/go-zero/core/logx"
)
type AdminDeleteProductLogic struct {
logx.Logger
ctx context.Context
svcCtx *svc.ServiceContext
}
func NewAdminDeleteProductLogic(ctx context.Context, svcCtx *svc.ServiceContext) *AdminDeleteProductLogic {
return &AdminDeleteProductLogic{
Logger: logx.WithContext(ctx),
ctx: ctx,
svcCtx: svcCtx,
}
}
func (l *AdminDeleteProductLogic) AdminDeleteProduct(req *types.AdminDeleteProductReq) (resp *types.AdminDeleteProductResp, err error) {
// 1. 查询记录是否存在
record, err := l.svcCtx.ProductModel.FindOne(l.ctx, req.Id)
if err != nil {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR),
"查找产品失败, err: %v, id: %d", err, req.Id)
}
// 2. 执行软删除
err = l.svcCtx.ProductModel.DeleteSoft(l.ctx, nil, record)
if err != nil {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR),
"删除产品失败, err: %v, id: %d", err, req.Id)
}
// 3. 返回结果
return &types.AdminDeleteProductResp{Success: true}, nil
}

View File

@@ -0,0 +1,49 @@
package admin_product
import (
"context"
"tyc-server/app/main/api/internal/svc"
"tyc-server/app/main/api/internal/types"
"tyc-server/common/xerr"
"github.com/pkg/errors"
"github.com/zeromicro/go-zero/core/logx"
)
type AdminGetProductDetailLogic struct {
logx.Logger
ctx context.Context
svcCtx *svc.ServiceContext
}
func NewAdminGetProductDetailLogic(ctx context.Context, svcCtx *svc.ServiceContext) *AdminGetProductDetailLogic {
return &AdminGetProductDetailLogic{
Logger: logx.WithContext(ctx),
ctx: ctx,
svcCtx: svcCtx,
}
}
func (l *AdminGetProductDetailLogic) AdminGetProductDetail(req *types.AdminGetProductDetailReq) (resp *types.AdminGetProductDetailResp, err error) {
// 1. 查询记录
record, err := l.svcCtx.ProductModel.FindOne(l.ctx, req.Id)
if err != nil {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR),
"查找产品失败, err: %v, id: %d", err, req.Id)
}
// 2. 构建响应
resp = &types.AdminGetProductDetailResp{
Id: record.Id,
ProductName: record.ProductName,
ProductEn: record.ProductEn,
Description: record.Description,
Notes: record.Notes.String,
CostPrice: record.CostPrice,
SellPrice: record.SellPrice,
CreateTime: record.CreateTime.Format("2006-01-02 15:04:05"),
UpdateTime: record.UpdateTime.Format("2006-01-02 15:04:05"),
}
return resp, nil
}

View File

@@ -0,0 +1,119 @@
package admin_product
import (
"context"
"tyc-server/app/main/api/internal/svc"
"tyc-server/app/main/api/internal/types"
"tyc-server/app/main/model"
"tyc-server/common/xerr"
"github.com/pkg/errors"
"github.com/zeromicro/go-zero/core/logx"
"github.com/zeromicro/go-zero/core/mr"
)
type AdminGetProductFeatureListLogic struct {
logx.Logger
ctx context.Context
svcCtx *svc.ServiceContext
}
func NewAdminGetProductFeatureListLogic(ctx context.Context, svcCtx *svc.ServiceContext) *AdminGetProductFeatureListLogic {
return &AdminGetProductFeatureListLogic{
Logger: logx.WithContext(ctx),
ctx: ctx,
svcCtx: svcCtx,
}
}
func (l *AdminGetProductFeatureListLogic) AdminGetProductFeatureList(req *types.AdminGetProductFeatureListReq) (resp *[]types.AdminGetProductFeatureListResp, err error) {
// 1. 构建查询条件
builder := l.svcCtx.ProductFeatureModel.SelectBuilder().
Where("product_id = ?", req.ProductId)
// 2. 执行查询
list, err := l.svcCtx.ProductFeatureModel.FindAll(l.ctx, builder, "sort ASC")
if err != nil {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR),
"查询产品功能列表失败, err: %v, product_id: %d", err, req.ProductId)
}
// 3. 获取所有功能ID
featureIds := make([]int64, 0, len(list))
for _, item := range list {
featureIds = append(featureIds, item.FeatureId)
}
// 4. 并发查询功能详情
type featureResult struct {
feature *model.Feature
err error
}
results := make([]featureResult, len(featureIds))
err = mr.MapReduceVoid(func(source chan<- interface{}) {
for i, id := range featureIds {
source <- struct {
index int
id int64
}{i, id}
}
}, func(item interface{}, writer mr.Writer[featureResult], cancel func(error)) {
data := item.(struct {
index int
id int64
})
feature, err := l.svcCtx.FeatureModel.FindOne(l.ctx, data.id)
writer.Write(featureResult{
feature: feature,
err: err,
})
}, func(pipe <-chan featureResult, cancel func(error)) {
for result := range pipe {
if result.err != nil {
l.Logger.Errorf("查询功能详情失败, feature_id: %d, err: %v", result.feature.Id, result.err)
continue
}
results = append(results, result)
}
})
if err != nil {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR),
"并发查询功能详情失败, err: %v", err)
}
// 5. 构建功能ID到详情的映射
featureMap := make(map[int64]*model.Feature)
for _, result := range results {
if result.feature != nil {
featureMap[result.feature.Id] = result.feature
}
}
// 6. 构建响应列表
items := make([]types.AdminGetProductFeatureListResp, 0, len(list))
for _, item := range list {
feature, exists := featureMap[item.FeatureId]
if !exists {
continue // 跳过不存在的功能
}
listItem := types.AdminGetProductFeatureListResp{
Id: item.Id,
ProductId: item.ProductId,
FeatureId: item.FeatureId,
ApiId: feature.ApiId,
Name: feature.Name,
Sort: item.Sort,
Enable: item.Enable,
IsImportant: item.IsImportant,
CreateTime: item.CreateTime.Format("2006-01-02 15:04:05"),
UpdateTime: item.UpdateTime.Format("2006-01-02 15:04:05"),
}
items = append(items, listItem)
}
// 7. 返回结果
return &items, nil
}

View File

@@ -0,0 +1,69 @@
package admin_product
import (
"context"
"tyc-server/app/main/api/internal/svc"
"tyc-server/app/main/api/internal/types"
"tyc-server/common/xerr"
"github.com/pkg/errors"
"github.com/zeromicro/go-zero/core/logx"
)
type AdminGetProductListLogic struct {
logx.Logger
ctx context.Context
svcCtx *svc.ServiceContext
}
func NewAdminGetProductListLogic(ctx context.Context, svcCtx *svc.ServiceContext) *AdminGetProductListLogic {
return &AdminGetProductListLogic{
Logger: logx.WithContext(ctx),
ctx: ctx,
svcCtx: svcCtx,
}
}
func (l *AdminGetProductListLogic) AdminGetProductList(req *types.AdminGetProductListReq) (resp *types.AdminGetProductListResp, err error) {
// 1. 构建查询条件
builder := l.svcCtx.ProductModel.SelectBuilder()
// 2. 添加查询条件
if req.ProductName != nil && *req.ProductName != "" {
builder = builder.Where("product_name LIKE ?", "%"+*req.ProductName+"%")
}
if req.ProductEn != nil && *req.ProductEn != "" {
builder = builder.Where("product_en LIKE ?", "%"+*req.ProductEn+"%")
}
// 3. 执行分页查询
list, total, err := l.svcCtx.ProductModel.FindPageListByPageWithTotal(
l.ctx, builder, req.Page, req.PageSize, "id DESC")
if err != nil {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR),
"查询产品列表失败, err: %v, req: %+v", err, req)
}
// 4. 构建响应列表
items := make([]types.ProductListItem, 0, len(list))
for _, item := range list {
listItem := types.ProductListItem{
Id: item.Id,
ProductName: item.ProductName,
ProductEn: item.ProductEn,
Description: item.Description,
Notes: item.Notes.String,
CostPrice: item.CostPrice,
SellPrice: item.SellPrice,
CreateTime: item.CreateTime.Format("2006-01-02 15:04:05"),
UpdateTime: item.UpdateTime.Format("2006-01-02 15:04:05"),
}
items = append(items, listItem)
}
// 5. 返回结果
return &types.AdminGetProductListResp{
Total: total,
Items: items,
}, nil
}

View File

@@ -0,0 +1,159 @@
package admin_product
import (
"context"
"sync"
"tyc-server/app/main/api/internal/svc"
"tyc-server/app/main/api/internal/types"
"tyc-server/app/main/model"
"tyc-server/common/xerr"
"github.com/pkg/errors"
"github.com/zeromicro/go-zero/core/logx"
"github.com/zeromicro/go-zero/core/mr"
"github.com/zeromicro/go-zero/core/stores/sqlx"
)
type AdminUpdateProductFeaturesLogic struct {
logx.Logger
ctx context.Context
svcCtx *svc.ServiceContext
}
func NewAdminUpdateProductFeaturesLogic(ctx context.Context, svcCtx *svc.ServiceContext) *AdminUpdateProductFeaturesLogic {
return &AdminUpdateProductFeaturesLogic{
Logger: logx.WithContext(ctx),
ctx: ctx,
svcCtx: svcCtx,
}
}
func (l *AdminUpdateProductFeaturesLogic) AdminUpdateProductFeatures(req *types.AdminUpdateProductFeaturesReq) (resp *types.AdminUpdateProductFeaturesResp, err error) {
// 1. 查询现有关联
builder := l.svcCtx.ProductFeatureModel.SelectBuilder().
Where("product_id = ?", req.ProductId)
existingList, err := l.svcCtx.ProductFeatureModel.FindAll(l.ctx, builder, "id ASC")
if err != nil {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR),
"查询现有产品功能关联失败, err: %v, product_id: %d", err, req.ProductId)
}
// 2. 构建现有关联的映射
existingMap := make(map[int64]*model.ProductFeature)
for _, item := range existingList {
existingMap[item.FeatureId] = item
}
// 3. 构建新关联的映射
newMap := make(map[int64]*types.ProductFeatureItem)
for _, item := range req.Features {
newMap[item.FeatureId] = &item
}
// 4. 在事务中执行更新操作
err = l.svcCtx.ProductFeatureModel.Trans(l.ctx, func(ctx context.Context, session sqlx.Session) error {
// 4.1 处理需要删除的关联
var mu sync.Mutex
var deleteIds []int64
err = mr.MapReduceVoid(func(source chan<- interface{}) {
for featureId, existing := range existingMap {
if _, exists := newMap[featureId]; !exists {
source <- existing.Id
}
}
}, func(item interface{}, writer mr.Writer[struct{}], cancel func(error)) {
id := item.(int64)
mu.Lock()
deleteIds = append(deleteIds, id)
mu.Unlock()
}, func(pipe <-chan struct{}, cancel func(error)) {
// 等待所有ID收集完成
})
if err != nil {
return errors.Wrapf(err, "收集待删除ID失败")
}
// 批量删除
if len(deleteIds) > 0 {
for _, id := range deleteIds {
err = l.svcCtx.ProductFeatureModel.Delete(ctx, session, id)
if err != nil {
return errors.Wrapf(err, "删除产品功能关联失败, product_id: %d, id: %d",
req.ProductId, id)
}
}
}
// 4.2 并发处理需要新增或更新的关联
var updateErr error
err = mr.MapReduceVoid(func(source chan<- interface{}) {
for featureId, newItem := range newMap {
source <- struct {
featureId int64
newItem *types.ProductFeatureItem
existing *model.ProductFeature
}{
featureId: featureId,
newItem: newItem,
existing: existingMap[featureId],
}
}
}, func(item interface{}, writer mr.Writer[struct{}], cancel func(error)) {
data := item.(struct {
featureId int64
newItem *types.ProductFeatureItem
existing *model.ProductFeature
})
if data.existing != nil {
// 更新现有关联
data.existing.Sort = data.newItem.Sort
data.existing.Enable = data.newItem.Enable
data.existing.IsImportant = data.newItem.IsImportant
_, err = l.svcCtx.ProductFeatureModel.Update(ctx, session, data.existing)
if err != nil {
updateErr = errors.Wrapf(err, "更新产品功能关联失败, product_id: %d, feature_id: %d",
req.ProductId, data.featureId)
cancel(updateErr)
return
}
} else {
// 新增关联
newFeature := &model.ProductFeature{
ProductId: req.ProductId,
FeatureId: data.featureId,
Sort: data.newItem.Sort,
Enable: data.newItem.Enable,
IsImportant: data.newItem.IsImportant,
}
_, err = l.svcCtx.ProductFeatureModel.Insert(ctx, session, newFeature)
if err != nil {
updateErr = errors.Wrapf(err, "新增产品功能关联失败, product_id: %d, feature_id: %d",
req.ProductId, data.featureId)
cancel(updateErr)
return
}
}
}, func(pipe <-chan struct{}, cancel func(error)) {
// 等待所有更新完成
})
if err != nil {
return errors.Wrapf(err, "并发更新产品功能关联失败")
}
if updateErr != nil {
return updateErr
}
return nil
})
if err != nil {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR),
"更新产品功能关联失败, err: %v, req: %+v", err, req)
}
// 5. 返回结果
return &types.AdminUpdateProductFeaturesResp{Success: true}, nil
}

View File

@@ -0,0 +1,65 @@
package admin_product
import (
"context"
"database/sql"
"tyc-server/app/main/api/internal/svc"
"tyc-server/app/main/api/internal/types"
"tyc-server/common/xerr"
"github.com/pkg/errors"
"github.com/zeromicro/go-zero/core/logx"
)
type AdminUpdateProductLogic struct {
logx.Logger
ctx context.Context
svcCtx *svc.ServiceContext
}
func NewAdminUpdateProductLogic(ctx context.Context, svcCtx *svc.ServiceContext) *AdminUpdateProductLogic {
return &AdminUpdateProductLogic{
Logger: logx.WithContext(ctx),
ctx: ctx,
svcCtx: svcCtx,
}
}
func (l *AdminUpdateProductLogic) AdminUpdateProduct(req *types.AdminUpdateProductReq) (resp *types.AdminUpdateProductResp, err error) {
// 1. 查询记录是否存在
record, err := l.svcCtx.ProductModel.FindOne(l.ctx, req.Id)
if err != nil {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR),
"查找产品失败, err: %v, id: %d", err, req.Id)
}
// 2. 更新字段
if req.ProductName != nil {
record.ProductName = *req.ProductName
}
if req.ProductEn != nil {
record.ProductEn = *req.ProductEn
}
if req.Description != nil {
record.Description = *req.Description
}
if req.Notes != nil {
record.Notes = sql.NullString{String: *req.Notes, Valid: *req.Notes != ""}
}
if req.CostPrice != nil {
record.CostPrice = *req.CostPrice
}
if req.SellPrice != nil {
record.SellPrice = *req.SellPrice
}
// 3. 执行更新操作
_, err = l.svcCtx.ProductModel.Update(l.ctx, nil, record)
if err != nil {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR),
"更新产品失败, err: %v, req: %+v", err, req)
}
// 4. 返回结果
return &types.AdminUpdateProductResp{Success: true}, nil
}

View File

@@ -29,7 +29,7 @@ func NewAdminGetUserListLogic(ctx context.Context, svcCtx *svc.ServiceContext) *
func (l *AdminGetUserListLogic) AdminGetUserList(req *types.AdminGetUserListReq) (resp *types.AdminGetUserListResp, err error) {
resp = &types.AdminGetUserListResp{
Items: make([]types.UserListItem, 0),
Items: make([]types.AdminUserListItem, 0),
Total: 0,
}
@@ -102,7 +102,7 @@ func (l *AdminGetUserListLogic) AdminGetUserList(req *types.AdminGetUserListReq)
wg.Wait()
// 并发获取每个用户的角色ID
var userItems []types.UserListItem
var userItems []types.AdminUserListItem
var userItemsMutex sync.Mutex
mr.MapReduceVoid(func(source chan<- interface{}) {
@@ -128,7 +128,7 @@ func (l *AdminGetUserListLogic) AdminGetUserList(req *types.AdminGetUserListReq)
}, func(pipe <-chan []int64, cancel func(error)) {
for _, user := range users {
roleIds := <-pipe
item := types.UserListItem{
item := types.AdminUserListItem{
Id: user.Id,
Username: user.Username,
RealName: user.RealName,

View File

@@ -38,7 +38,7 @@ func (l *GetNotificationsLogic) GetNotifications() (resp *types.GetNotifications
// 构建查询条件
builder := l.svcCtx.GlobalNotificationsModel.SelectBuilder().
Where("status = ?", "active").
Where("status = ?", 1).
Where("(start_date IS NULL OR start_date <= ?)", todayEnd). // start_date 是 NULL 或者小于等于今天结束时间
Where("(end_date IS NULL OR end_date >= ?)", todayStart) // end_date 是 NULL 或者大于等于今天开始时间

View File

@@ -3,8 +3,6 @@ package pay
import (
"context"
"net/http"
"time"
"tyc-server/pkg/lzkit/lzUtils"
"github.com/smartwalle/alipay/v3"
@@ -28,49 +26,11 @@ func NewAlipayCallbackLogic(ctx context.Context, svcCtx *svc.ServiceContext) *Al
}
func (l *AlipayCallbackLogic) AlipayCallback(w http.ResponseWriter, r *http.Request) error {
notification, err := l.svcCtx.AlipayService.HandleAliPaymentNotification(r)
err := l.svcCtx.PayService.HandlePaymentCallback(l.ctx, "alipay", r)
if err != nil {
logx.Errorf("支付宝支付回调,%+v", err)
return nil
}
order, findOrderErr := l.svcCtx.OrderModel.FindOneByOrderNo(l.ctx, notification.OutTradeNo)
if findOrderErr != nil {
logx.Errorf("支付宝支付回调,查找订单失败: %+v", findOrderErr)
return nil
}
if order.Status != "pending" {
alipay.ACKNotification(w)
return nil
}
amount := lzUtils.ToAlipayAmount(order.Amount)
// 确保订单金额和状态正确,防止重复更新
if amount != notification.TotalAmount {
logx.Errorf("支付宝支付回调,金额不一致")
return nil
}
if order.Status != "pending" {
w.WriteHeader(http.StatusOK)
_, _ = w.Write([]byte("success")) // 确保只写入一次响应
return nil
}
switch notification.TradeStatus {
case alipay.TradeStatusSuccess:
order.Status = "paid"
order.PayTime = lzUtils.TimeToNullTime(time.Now())
default:
return nil
}
order.PlatformOrderId = lzUtils.StringToNullString(notification.TradeNo)
if updateErr := l.svcCtx.OrderModel.UpdateWithVersion(l.ctx, nil, order); updateErr != nil {
logx.Errorf("支付宝支付回调,修改订单信息失败: %+v", updateErr)
return nil
}
if order.Status == "paid" {
if asyncErr := l.svcCtx.AsynqService.SendQueryTask(order.Id); asyncErr != nil {
logx.Errorf("异步任务调度失败: %v", asyncErr)
return asyncErr
}
}
alipay.ACKNotification(w)
return nil
}

View File

@@ -4,15 +4,14 @@ import (
"context"
"encoding/json"
"fmt"
"tyc-server/app/main/api/internal/service"
"tyc-server/app/main/api/internal/svc"
"tyc-server/app/main/api/internal/types"
"tyc-server/app/main/model"
"tyc-server/common/ctxdata"
"tyc-server/common/xerr"
"github.com/pkg/errors"
"github.com/zeromicro/go-zero/core/logx"
"github.com/zeromicro/go-zero/core/stores/sqlx"
)
type PaymentLogic struct {
@@ -34,104 +33,45 @@ func (l *PaymentLogic) Payment(req *types.PaymentReq) (resp *types.PaymentResp,
if getUidErr != nil {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "生成订单, 获取用户信息失败, %+v", getUidErr)
}
brand, ok := l.ctx.Value("brand").(string)
if !ok {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "生成订单, 获取平台失败, %+v", getUidErr)
}
// 从缓存中获取订单信息
outTradeNo := req.Id
redisKey := fmt.Sprintf("%d:%s", userID, outTradeNo)
cache, cacheErr := l.svcCtx.Redis.GetCtx(l.ctx, redisKey)
if cacheErr != nil {
return nil, cacheErr
}
var data types.QueryCacheLoad
err = json.Unmarshal([]byte(cache), &data)
if err != nil {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "生成订单, 解析缓存内容失败, %+v", err)
}
product, err := l.svcCtx.ProductModel.FindOneByProductEn(l.ctx, data.Product)
if err != nil {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "生成订单, 查找产品错误: %+v", err)
}
var prepayData interface{}
var amount float64
user, err := l.svcCtx.UserModel.FindOne(l.ctx, userID)
if err != nil {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "生成订单, 获取用户信息失败: %+v", err)
}
if user.Inside == 1 {
amount = 0.01
} else {
amount = product.SellPrice
}
var createOrderErr error
if req.PayMethod == "wechat" {
prepayData, createOrderErr = l.svcCtx.WechatPayService.CreateWechatOrder(l.ctx, amount, product.ProductName, outTradeNo)
} else if req.PayMethod == "alipay" {
prepayData, createOrderErr = l.svcCtx.AlipayService.CreateAlipayOrder(l.ctx, amount, product.ProductName, outTradeNo, brand)
} else if req.PayMethod == "appleiap" {
prepayData = l.svcCtx.ApplePayService.GetIappayAppID(product.ProductEn)
}
if createOrderErr != nil {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "生成订单, 创建支付订单失败: %+v", createOrderErr)
}
var orderID int64
transErr := l.svcCtx.OrderModel.Trans(l.ctx, func(ctx context.Context, session sqlx.Session) error {
order := model.Order{
OrderNo: outTradeNo,
UserId: userID,
ProductId: product.Id,
PaymentPlatform: req.PayMethod,
PaymentScene: "tyc",
Amount: amount,
Status: "pending",
}
orderInsertResult, insertOrderErr := l.svcCtx.OrderModel.Insert(ctx, session, &order)
if insertOrderErr != nil {
return errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "生成订单, 保存订单失败: %+v", insertOrderErr)
}
insertedOrderID, lastInsertIdErr := orderInsertResult.LastInsertId()
if lastInsertIdErr != nil {
return errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "生成订单, 获取保存订单ID失败: %+v", lastInsertIdErr)
}
orderID = insertedOrderID
promoteKey, ok := l.ctx.Value("promoteKey").(string)
if ok && promoteKey != "" {
// TODO: 在这里添加处理 promoteKey 的逻辑
url := fmt.Sprintf("%s/%s", l.svcCtx.Config.AdminPromotion.URLDomain, promoteKey)
promoteLink, err := l.svcCtx.AdminPromotionLinkModel.FindOneByUrl(l.ctx, url)
if err != nil && !errors.Is(err, model.ErrNotFound) {
return errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "生成订单, 查找推广链接失败: %+v", err)
}
if promoteLink != nil {
promoteOrder := &model.AdminPromotionOrder{
OrderId: orderID,
LinkId: promoteLink.Id,
UserId: userID,
AdminUserId: promoteLink.AdminUserId,
}
_, insertPromoteOrderErr := l.svcCtx.AdminPromotionOrderModel.Insert(ctx, session, promoteOrder)
if insertPromoteOrderErr != nil {
return errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "生成订单, 保存推广订单失败: %+v", insertPromoteOrderErr)
}
}
}
return nil
})
if transErr != nil {
return nil, transErr
}
switch v := prepayData.(type) {
case string:
// 如果 prepayData 是字符串类型,直接返回
return &types.PaymentResp{PrepayId: v, OrderID: orderID}, nil
var payMethod service.PayMethod
switch req.PayMethod {
case "alipay":
payMethod = service.PayMethodAlipay
case "wechat":
payMethod = service.PayMethodWechat
// case "apple":
// payMethod = service.PayMethodApple
default:
return &types.PaymentResp{PrepayData: prepayData, OrderID: orderID}, nil
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "生成订单, 不支持的支付方式: %+v", req.PayMethod)
}
// 创建支付订单
orderReq := &service.CreateOrderRequest{
PayMethod: payMethod,
ProductEn: data.Product,
}
orderResp, err := l.svcCtx.PayService.CreateOrder(l.ctx, orderReq)
if err != nil {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "生成订单失败: %+v", err)
}
return &types.PaymentResp{
PrepayData: orderResp.PayData,
PrepayId: orderResp.OrderNo,
OrderID: orderResp.OrderID,
}, nil
}

View File

@@ -3,9 +3,6 @@ package pay
import (
"context"
"net/http"
"time"
"tyc-server/app/main/api/internal/service"
"tyc-server/pkg/lzkit/lzUtils"
"tyc-server/app/main/api/internal/svc"
@@ -27,50 +24,11 @@ func NewWechatPayCallbackLogic(ctx context.Context, svcCtx *svc.ServiceContext)
}
func (l *WechatPayCallbackLogic) WechatPayCallback(w http.ResponseWriter, r *http.Request) error {
notification, err := l.svcCtx.WechatPayService.HandleWechatPayNotification(l.ctx, r)
err := l.svcCtx.PayService.HandlePaymentCallback(l.ctx, "wechat", r)
if err != nil {
logx.Errorf("微信支付回调,%+v", err)
return nil
}
order, findOrderErr := l.svcCtx.OrderModel.FindOneByOrderNo(l.ctx, *notification.OutTradeNo)
if findOrderErr != nil {
logx.Errorf("微信支付回调,查找订单信息失败: %+v", findOrderErr)
return nil
}
amount := lzUtils.ToWechatAmount(order.Amount)
if amount != *notification.Amount.Total {
logx.Errorf("微信支付回调,金额不一致")
return nil
}
if order.Status != "pending" {
w.WriteHeader(http.StatusOK)
_, _ = w.Write([]byte("success")) // 确保只写入一次响应
return nil
}
switch *notification.TradeState {
case service.TradeStateSuccess:
order.Status = "paid"
order.PayTime = lzUtils.TimeToNullTime(time.Now())
case service.TradeStateClosed:
order.Status = "closed"
order.CloseTime = lzUtils.TimeToNullTime(time.Now())
case service.TradeStateRevoked:
order.Status = "failed"
default:
return nil
}
order.PlatformOrderId = lzUtils.StringToNullString(*notification.TransactionId)
if updateErr := l.svcCtx.OrderModel.UpdateWithVersion(l.ctx, nil, order); updateErr != nil {
logx.Errorf("微信支付回调,更新订单失败%+v", updateErr)
return nil
}
if order.Status == "paid" {
if asyncErr := l.svcCtx.AsynqService.SendQueryTask(order.Id); asyncErr != nil {
logx.Errorf("异步任务调度失败: %v", asyncErr)
return asyncErr
}
}
// 响应微信回调成功
w.WriteHeader(http.StatusOK)

View File

@@ -5,7 +5,6 @@ import (
"net/http"
"tyc-server/app/main/api/internal/svc"
"github.com/wechatpay-apiv3/wechatpay-go/services/refunddomestic"
"github.com/zeromicro/go-zero/core/logx"
)
@@ -24,32 +23,36 @@ func NewWechatPayRefundCallbackLogic(ctx context.Context, svcCtx *svc.ServiceCon
}
func (l *WechatPayRefundCallbackLogic) WechatPayRefundCallback(w http.ResponseWriter, r *http.Request) error {
notification, err := l.svcCtx.WechatPayService.HandleRefundNotification(l.ctx, r)
if err != nil {
logx.Errorf("微信退款回调,%+v", err)
return nil
}
order, findOrderErr := l.svcCtx.OrderModel.FindOneByOrderNo(l.ctx, *notification.OutTradeNo)
if findOrderErr != nil {
logx.Errorf("微信退款回调,查找订单信息失败: %+v", findOrderErr)
return nil
}
// notification, err := l.svcCtx.PayService.re(l.ctx, r)
// if err != nil {
// logx.Errorf("微信退款回调,%+v", err)
// return nil
// }
// order, findOrderErr := l.svcCtx.OrderModel.FindOneByOrderNo(l.ctx, *notification.OutTradeNo)
// if findOrderErr != nil {
// logx.Errorf("微信退款回调,查找订单信息失败: %+v", findOrderErr)
// return nil
// }
switch *notification.Status {
case refunddomestic.STATUS_SUCCESS:
order.Status = "refunded"
case refunddomestic.STATUS_ABNORMAL:
// 异常
return nil
default:
return nil
}
if updateErr := l.svcCtx.OrderModel.UpdateWithVersion(l.ctx, nil, order); updateErr != nil {
logx.Errorf("微信退款回调,更新订单失败%+v", updateErr)
return nil
}
// 响应微信回调成功
w.WriteHeader(http.StatusOK)
_, _ = w.Write([]byte("success")) // 确保只写入一次响应
// switch *notification.Status {
// case refunddomestic.STATUS_SUCCESS:
// order.Status = "refunded"
// order.RefundTime = sql.NullTime{
// Time: time.Now(),
// Valid: true,
// }
// case refunddomestic.STATUS_ABNORMAL:
// // 异常
// return nil
// default:
// return nil
// }
// if updateErr := l.svcCtx.OrderModel.UpdateWithVersion(l.ctx, nil, order); updateErr != nil {
// logx.Errorf("微信退款回调,更新订单失败%+v", updateErr)
// return nil
// }
// // 响应微信回调成功
// w.WriteHeader(http.StatusOK)
// _, _ = w.Write([]byte("success")) // 确保只写入一次响应
return nil
}

View File

@@ -2,9 +2,12 @@ package query
import (
"context"
"crypto/rand"
"encoding/hex"
"encoding/json"
"fmt"
"strconv"
"sync/atomic"
"time"
"tyc-server/app/main/api/internal/service"
"tyc-server/common/ctxdata"
@@ -140,13 +143,13 @@ func (l *QueryServiceLogic) CacheData(params map[string]interface{}, Product str
if marshalErr != nil {
return "", errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "查询服务, 序列化参数失败: %+v", marshalErr)
}
outTradeNo := l.svcCtx.AlipayService.GenerateOutTradeNo()
redisKey := fmt.Sprintf("%d:%s", userID, outTradeNo)
cacheNo := l.GenerateCacheNo()
redisKey := fmt.Sprintf("%d:%s", userID, cacheNo)
cacheErr := l.svcCtx.Redis.SetexCtx(l.ctx, redisKey, string(jsonData), int(2*time.Hour))
if cacheErr != nil {
return "", cacheErr
}
return outTradeNo, nil
return cacheNo, nil
}
var productProcessors = map[string]func(*QueryServiceLogic, *types.QueryServiceReq) (*types.QueryServiceResp, error){
@@ -2067,3 +2070,27 @@ func (l *QueryServiceLogic) ProcessTocPersonEnterpriseProLogic(req *types.QueryS
return &types.QueryServiceResp{Id: cacheNo}, nil
}
// 全局原子计数器
var CacheNoCounter uint32 = 0
func (l *QueryServiceLogic) GenerateCacheNo() string {
// 获取当前时间戳(秒级)
timestamp := time.Now().Unix()
timeStr := strconv.FormatInt(timestamp, 10)
// 原子递增计数器
counter := atomic.AddUint32(&CacheNoCounter, 1)
// 生成4字节真随机数
randomBytes := make([]byte, 4)
_, err := rand.Read(randomBytes)
if err != nil {
// 如果随机数生成失败,回退到使用时间纳秒数据
randomBytes = []byte(strconv.FormatInt(time.Now().UnixNano()%1000000, 16))
}
randomHex := hex.EncodeToString(randomBytes)
// 组合所有部分: 前缀 + 时间戳 + 计数器 + 随机数
return fmt.Sprintf("query_%s%06x%s", timeStr, counter%0xFFFFFF, randomHex[:6])
}

View File

@@ -79,7 +79,7 @@ func (l *MobileCodeLoginLogic) MobileCodeLogin(req *types.MobileCodeLoginReq) (r
userAuth := new(model.UserAuth)
userAuth.UserId = lastId
userAuth.AuthKey = encryptedMobile
userAuth.AuthType = model.UserAuthTypeAppMobile
userAuth.AuthType = model.UserAuthTypeMobile
if _, userAuthInsertErr := l.svcCtx.UserAuthModel.Insert(ctx, session, userAuth); userAuthInsertErr != nil {
return errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "手机注册, 数据库插入用户认证失败, err:%+v", userAuthInsertErr)
}

View File

@@ -86,7 +86,7 @@ func (l *RegisterLogic) Register(req *types.RegisterReq) (resp *types.RegisterRe
userAuth := new(model.UserAuth)
userAuth.UserId = lastId
userAuth.AuthKey = encryptedMobile
userAuth.AuthType = model.UserAuthTypeAppMobile
userAuth.AuthType = model.UserAuthTypeMobile
if _, userAuthInsertErr := l.svcCtx.UserAuthModel.Insert(ctx, session, userAuth); userAuthInsertErr != nil {
return errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "手机注册, 数据库插入用户认证失败, err:%+v", userAuthInsertErr)
}

View File

@@ -42,7 +42,7 @@ func (l *WxMiniAuthLogic) WxMiniAuth(req *types.WXMiniAuthReq) (resp *types.WXMi
}
// 2. 根据 openid 查找用户
userAuth, findErr := l.svcCtx.UserAuthModel.FindOneByAuthTypeAuthKey(l.ctx, model.UserAuthTypeWxMini, weChatResponse.OpenId)
userAuth, findErr := l.svcCtx.UserAuthModel.FindOneByAuthTypeAuthKey(l.ctx, model.UserAuthTypeWechatMiniOpenID, weChatResponse.OpenId)
if findErr != nil && findErr != model.ErrNotFound {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "微信登录, 读取用户认证信息失败, openid: %s, err: %+v", weChatResponse.OpenId, findErr)
}
@@ -70,7 +70,7 @@ func (l *WxMiniAuthLogic) WxMiniAuth(req *types.WXMiniAuthReq) (resp *types.WXMi
newUserAuth := &model.UserAuth{
UserId: lastId,
AuthKey: weChatResponse.OpenId,
AuthType: model.UserAuthTypeWxMini,
AuthType: model.UserAuthTypeWechatMiniOpenID,
}
if _, userAuthInsertErr := l.svcCtx.UserAuthModel.Insert(ctx, session, newUserAuth); userAuthInsertErr != nil {
return errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "微信登录, 数据库插入用户认证信息失败, err:%+v", userAuthInsertErr)