1、新增自定义用户私人价格2、优化api服务鉴权缓存3、新增管理员端对公充值
This commit is contained in:
@@ -50,6 +50,9 @@ type (
|
||||
UpdateWalletResponse = user.UpdateWalletResponse
|
||||
UserInfoReq = user.UserInfoReq
|
||||
UserInfoResp = user.UserInfoResp
|
||||
UserItem = user.UserItem
|
||||
UserListRequest = user.UserListRequest
|
||||
UserListResponse = user.UserListResponse
|
||||
|
||||
ApiRequestService interface {
|
||||
// 添加API请求记录
|
||||
|
||||
@@ -50,6 +50,9 @@ type (
|
||||
UpdateWalletResponse = user.UpdateWalletResponse
|
||||
UserInfoReq = user.UserInfoReq
|
||||
UserInfoResp = user.UserInfoResp
|
||||
UserItem = user.UserItem
|
||||
UserListRequest = user.UserListRequest
|
||||
UserListResponse = user.UserListResponse
|
||||
|
||||
Auth interface {
|
||||
// 注册接口
|
||||
|
||||
@@ -50,6 +50,9 @@ type (
|
||||
UpdateWalletResponse = user.UpdateWalletResponse
|
||||
UserInfoReq = user.UserInfoReq
|
||||
UserInfoResp = user.UserInfoResp
|
||||
UserItem = user.UserItem
|
||||
UserListRequest = user.UserListRequest
|
||||
UserListResponse = user.UserListResponse
|
||||
|
||||
Enterprise interface {
|
||||
// 获取待审核企业列表
|
||||
|
||||
@@ -50,12 +50,16 @@ type (
|
||||
UpdateWalletResponse = user.UpdateWalletResponse
|
||||
UserInfoReq = user.UserInfoReq
|
||||
UserInfoResp = user.UserInfoResp
|
||||
UserItem = user.UserItem
|
||||
UserListRequest = user.UserListRequest
|
||||
UserListResponse = user.UserListResponse
|
||||
|
||||
User interface {
|
||||
// 获取用户信息
|
||||
UserInfo(ctx context.Context, in *UserInfoReq, opts ...grpc.CallOption) (*UserInfoResp, error)
|
||||
GetUserInfo(ctx context.Context, in *UserInfoReq, opts ...grpc.CallOption) (*GetUserInfoResp, error)
|
||||
GetEnterpriseAuthStatus(ctx context.Context, in *GetEnterpriseAuthStatusReq, opts ...grpc.CallOption) (*GetEnterpriseAuthStatusResp, error)
|
||||
GetUserList(ctx context.Context, in *UserListRequest, opts ...grpc.CallOption) (*UserListResponse, error)
|
||||
}
|
||||
|
||||
defaultUser struct {
|
||||
@@ -84,3 +88,8 @@ func (m *defaultUser) GetEnterpriseAuthStatus(ctx context.Context, in *GetEnterp
|
||||
client := user.NewUserClient(m.cli.Conn())
|
||||
return client.GetEnterpriseAuthStatus(ctx, in, opts...)
|
||||
}
|
||||
|
||||
func (m *defaultUser) GetUserList(ctx context.Context, in *UserListRequest, opts ...grpc.CallOption) (*UserListResponse, error) {
|
||||
client := user.NewUserClient(m.cli.Conn())
|
||||
return client.GetUserList(ctx, in, opts...)
|
||||
}
|
||||
|
||||
@@ -50,6 +50,9 @@ type (
|
||||
UpdateWalletResponse = user.UpdateWalletResponse
|
||||
UserInfoReq = user.UserInfoReq
|
||||
UserInfoResp = user.UserInfoResp
|
||||
UserItem = user.UserItem
|
||||
UserListRequest = user.UserListRequest
|
||||
UserListResponse = user.UserListResponse
|
||||
|
||||
WalletService interface {
|
||||
// 修改钱包余额
|
||||
|
||||
63
apps/user/internal/logic/user/getuserlistlogic.go
Normal file
63
apps/user/internal/logic/user/getuserlistlogic.go
Normal file
@@ -0,0 +1,63 @@
|
||||
package userlogic
|
||||
|
||||
import (
|
||||
"context"
|
||||
"tianyuan-api/apps/user/internal/svc"
|
||||
"tianyuan-api/apps/user/user"
|
||||
|
||||
"github.com/zeromicro/go-zero/core/logx"
|
||||
)
|
||||
|
||||
type GetUserListLogic struct {
|
||||
ctx context.Context
|
||||
svcCtx *svc.ServiceContext
|
||||
logx.Logger
|
||||
}
|
||||
|
||||
func NewGetUserListLogic(ctx context.Context, svcCtx *svc.ServiceContext) *GetUserListLogic {
|
||||
return &GetUserListLogic{
|
||||
ctx: ctx,
|
||||
svcCtx: svcCtx,
|
||||
Logger: logx.WithContext(ctx),
|
||||
}
|
||||
}
|
||||
|
||||
func (l *GetUserListLogic) GetUserList(in *user.UserListRequest) (*user.UserListResponse, error) {
|
||||
list, total, err := l.svcCtx.UserModel.FindUserPageList(l.ctx, in.Page, in.PageSize)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
userIds := make([]int64, len(list))
|
||||
for i, userItem := range list {
|
||||
userIds[i] = userItem.Id
|
||||
}
|
||||
|
||||
walletMap, err := l.svcCtx.WalletsModel.FindWalletsByUserIds(l.ctx, userIds)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var userList []*user.UserItem
|
||||
for _, userItem := range list {
|
||||
balance := float64(0)
|
||||
if wallet, ok := walletMap[userItem.Id]; ok {
|
||||
balance = wallet.Balance
|
||||
}
|
||||
|
||||
userList = append(userList, &user.UserItem{
|
||||
Id: userItem.Id,
|
||||
Username: userItem.Username,
|
||||
Phone: userItem.Phone,
|
||||
Disable: userItem.Disable,
|
||||
QuotaExceeded: userItem.QuotaExceeded,
|
||||
Balance: balance,
|
||||
CreatedAt: userItem.CreatedAt.Format("2006-01-02 15:04:05"),
|
||||
UpdatedAt: userItem.UpdatedAt.Format("2006-01-02 15:04:05"),
|
||||
})
|
||||
}
|
||||
|
||||
return &user.UserListResponse{
|
||||
List: userList,
|
||||
Total: total,
|
||||
}, nil
|
||||
}
|
||||
@@ -6,6 +6,7 @@ import (
|
||||
"errors"
|
||||
"github.com/zeromicro/go-zero/core/stores/sqlx"
|
||||
"tianyuan-api/apps/sentinel/client/product"
|
||||
"tianyuan-api/apps/sentinel/sentinel"
|
||||
"tianyuan-api/apps/user/internal/model"
|
||||
"time"
|
||||
|
||||
@@ -40,7 +41,13 @@ func (l *UpdateWalletLogic) UpdateWallet(in *user.UpdateWalletRequest) (*user.Up
|
||||
if getProductByCodeErr != nil {
|
||||
return nil, getProductByCodeErr
|
||||
}
|
||||
|
||||
userProduct, getUserProductErr := l.svcCtx.UserProductRpc.GetUserProduct(l.ctx, &sentinel.UserProuctRequest{
|
||||
UserId: in.UserId,
|
||||
ProductId: consumeProduct.Id,
|
||||
})
|
||||
if getUserProductErr != nil {
|
||||
return nil, getUserProductErr
|
||||
}
|
||||
// 检查是否已经扣款
|
||||
deduction, FindOneByTransactionIdErr := l.svcCtx.DeductionsModel.FindOneByTransactionId(l.ctx, in.TransactionId)
|
||||
if FindOneByTransactionIdErr != nil {
|
||||
@@ -59,7 +66,7 @@ func (l *UpdateWalletLogic) UpdateWallet(in *user.UpdateWalletRequest) (*user.Up
|
||||
var err error
|
||||
// 尝试多次更新余额(用于乐观锁)
|
||||
for i := 0; i < maxRetries; i++ {
|
||||
err = l.svcCtx.WalletsModel.UpdateBalance(session, l.ctx, in.UserId, -consumeProduct.ProductPrice)
|
||||
err = l.svcCtx.WalletsModel.UpdateBalance(session, l.ctx, in.UserId, -userProduct.ProductPrice)
|
||||
if err == nil {
|
||||
// 成功,退出循环
|
||||
break
|
||||
@@ -82,7 +89,7 @@ func (l *UpdateWalletLogic) UpdateWallet(in *user.UpdateWalletRequest) (*user.Up
|
||||
_, err = l.svcCtx.DeductionsModel.InsertDeductionsTrans(ctx, &model.Deductions{
|
||||
TransactionId: in.TransactionId,
|
||||
UserId: in.UserId,
|
||||
Amount: consumeProduct.ProductPrice,
|
||||
Amount: userProduct.ProductPrice,
|
||||
}, session)
|
||||
if err != nil {
|
||||
return err
|
||||
|
||||
@@ -18,6 +18,7 @@ type (
|
||||
usersModel
|
||||
UpdateUserTrans(ctx context.Context, user *Users, session sqlx.Session) (sql.Result, error)
|
||||
FindOneTrans(ctx context.Context, userId int64, session sqlx.Session) (*Users, error)
|
||||
FindUserPageList(ctx context.Context, page, pageSize int64) ([]Users, int64, error)
|
||||
}
|
||||
|
||||
customUsersModel struct {
|
||||
@@ -76,3 +77,23 @@ func (m *defaultUsersModel) FindOneTrans(ctx context.Context, userId int64, sess
|
||||
// 返回查询结果
|
||||
return &user, nil
|
||||
}
|
||||
func (m *customUsersModel) FindUserPageList(ctx context.Context, page, pageSize int64) ([]Users, int64, error) {
|
||||
offset := (page - 1) * pageSize
|
||||
var users []Users
|
||||
|
||||
query := fmt.Sprintf("SELECT * FROM %s ORDER BY created_at DESC LIMIT ?,?", m.table)
|
||||
err := m.QueryRowsNoCacheCtx(ctx, &users, query, offset, pageSize)
|
||||
if err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
|
||||
// 查询总数量
|
||||
var total int64
|
||||
countQuery := fmt.Sprintf("SELECT COUNT(*) FROM %s", m.table)
|
||||
err = m.QueryRowNoCacheCtx(ctx, &total, countQuery)
|
||||
if err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
|
||||
return users, total, nil
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@ import (
|
||||
"fmt"
|
||||
"github.com/zeromicro/go-zero/core/stores/cache"
|
||||
"github.com/zeromicro/go-zero/core/stores/sqlx"
|
||||
"strings"
|
||||
)
|
||||
|
||||
var _ WalletsModel = (*customWalletsModel)(nil)
|
||||
@@ -19,6 +20,7 @@ type (
|
||||
InsertWalletsTrans(ctx context.Context, wallets *Wallets, session sqlx.Session) (sql.Result, error)
|
||||
UpdateBalance(session sqlx.Session, ctx context.Context, userId int64, amount float64) error
|
||||
TransCtx(ctx context.Context, fn func(ctx context.Context, session sqlx.Session) error) error
|
||||
FindWalletsByUserIds(ctx context.Context, userIds []int64) (map[int64]*Wallets, error)
|
||||
}
|
||||
|
||||
customWalletsModel struct {
|
||||
@@ -88,3 +90,36 @@ func (m *customWalletsModel) InsertWalletsTrans(ctx context.Context, wallets *Wa
|
||||
|
||||
return ret, err
|
||||
}
|
||||
func (m *customWalletsModel) FindWalletsByUserIds(ctx context.Context, userIds []int64) (map[int64]*Wallets, error) {
|
||||
if len(userIds) == 0 {
|
||||
return make(map[int64]*Wallets), nil
|
||||
}
|
||||
|
||||
queryBuilder := strings.Builder{}
|
||||
queryBuilder.WriteString(fmt.Sprintf("SELECT user_id, balance FROM %s WHERE user_id IN (", m.table))
|
||||
|
||||
placeholders := make([]string, len(userIds))
|
||||
args := make([]interface{}, len(userIds))
|
||||
for i, userId := range userIds {
|
||||
placeholders[i] = "?"
|
||||
args[i] = userId
|
||||
}
|
||||
|
||||
queryBuilder.WriteString(strings.Join(placeholders, ","))
|
||||
queryBuilder.WriteString(")")
|
||||
|
||||
query := queryBuilder.String()
|
||||
|
||||
var wallets []*Wallets
|
||||
err := m.QueryRowNoCacheCtx(ctx, &wallets, query, args...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
walletMap := make(map[int64]*Wallets)
|
||||
for _, wallet := range wallets {
|
||||
walletMap[wallet.UserId] = wallet
|
||||
}
|
||||
|
||||
return walletMap, nil
|
||||
}
|
||||
|
||||
@@ -38,3 +38,8 @@ func (s *UserServer) GetEnterpriseAuthStatus(ctx context.Context, in *user.GetEn
|
||||
l := userlogic.NewGetEnterpriseAuthStatusLogic(ctx, s.svcCtx)
|
||||
return l.GetEnterpriseAuthStatus(in)
|
||||
}
|
||||
|
||||
func (s *UserServer) GetUserList(ctx context.Context, in *user.UserListRequest) (*user.UserListResponse, error) {
|
||||
l := userlogic.NewGetUserListLogic(ctx, s.svcCtx)
|
||||
return l.GetUserList(in)
|
||||
}
|
||||
|
||||
@@ -23,6 +23,7 @@ type ServiceContext struct {
|
||||
UserConfigModel model.UserConfigModel
|
||||
SecretRpc sentinel.SecretClient
|
||||
ProductRpc sentinel.ProductClient
|
||||
UserProductRpc sentinel.UserProductClient
|
||||
}
|
||||
|
||||
func NewServiceContext(c config.Config) *ServiceContext {
|
||||
@@ -35,7 +36,7 @@ func NewServiceContext(c config.Config) *ServiceContext {
|
||||
// 初始化 SecretRpc 和 ProductRpc
|
||||
var secretRpc sentinel.SecretClient
|
||||
var productRpc sentinel.ProductClient
|
||||
|
||||
var userProductRpc sentinel.UserProductClient
|
||||
// 捕获RPC初始化时的错误,但不影响服务启动
|
||||
secretClient, err := zrpc.NewClient(c.SentinelRpc)
|
||||
if err != nil {
|
||||
@@ -49,6 +50,7 @@ func NewServiceContext(c config.Config) *ServiceContext {
|
||||
logx.Errorf("Failed to connect to ProductRpc: %v", err)
|
||||
} else {
|
||||
productRpc = sentinel.NewProductClient(productClient.Conn())
|
||||
userProductRpc = sentinel.NewUserProductClient(productClient.Conn())
|
||||
}
|
||||
|
||||
// 使用 MustNewRedis 来初始化 Redis 客户端
|
||||
@@ -66,5 +68,6 @@ func NewServiceContext(c config.Config) *ServiceContext {
|
||||
RechargeModel: model.NewRechargeModel(db, c.CacheRedis),
|
||||
SecretRpc: secretRpc, // 捕获连接错误后,继续运行
|
||||
ProductRpc: productRpc, // 捕获连接错误后,继续运行
|
||||
UserProductRpc: userProductRpc,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -113,7 +113,7 @@ message UserInfoResp{
|
||||
string enterpriseName = 6;
|
||||
string creditCode = 7;
|
||||
string legalPerson = 8;
|
||||
double balance= 9;
|
||||
double balance = 9;
|
||||
}
|
||||
message GetUserInfoResp{
|
||||
string username = 1;
|
||||
@@ -128,6 +128,27 @@ message GetEnterpriseAuthStatusReq {
|
||||
message GetEnterpriseAuthStatusResp {
|
||||
bool isAuth = 1;
|
||||
}
|
||||
|
||||
message UserListRequest {
|
||||
int64 page = 1; // 分页页码
|
||||
int64 page_size = 2; // 每页大小
|
||||
}
|
||||
|
||||
message UserListResponse {
|
||||
repeated UserItem list = 1;
|
||||
int64 total = 2;
|
||||
}
|
||||
|
||||
message UserItem {
|
||||
int64 id = 1; // 主键ID
|
||||
string username = 2;
|
||||
string phone = 3;
|
||||
int64 disable = 4;
|
||||
int64 quotaExceeded = 5;
|
||||
double balance = 6;
|
||||
string created_at = 7; // 创建时间
|
||||
string updated_at = 8; // 更新时间
|
||||
}
|
||||
service User {
|
||||
// 获取用户信息
|
||||
rpc UserInfo(UserInfoReq) returns (UserInfoResp);
|
||||
@@ -135,6 +156,9 @@ service User {
|
||||
rpc GetUserInfo(UserInfoReq) returns (GetUserInfoResp);
|
||||
|
||||
rpc GetEnterpriseAuthStatus(GetEnterpriseAuthStatusReq) returns (GetEnterpriseAuthStatusResp);
|
||||
|
||||
rpc GetUserList(UserListRequest) returns (UserListResponse);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -376,6 +376,7 @@ const (
|
||||
User_UserInfo_FullMethodName = "/User/UserInfo"
|
||||
User_GetUserInfo_FullMethodName = "/User/GetUserInfo"
|
||||
User_GetEnterpriseAuthStatus_FullMethodName = "/User/GetEnterpriseAuthStatus"
|
||||
User_GetUserList_FullMethodName = "/User/GetUserList"
|
||||
)
|
||||
|
||||
// UserClient is the client API for User service.
|
||||
@@ -386,6 +387,7 @@ type UserClient interface {
|
||||
UserInfo(ctx context.Context, in *UserInfoReq, opts ...grpc.CallOption) (*UserInfoResp, error)
|
||||
GetUserInfo(ctx context.Context, in *UserInfoReq, opts ...grpc.CallOption) (*GetUserInfoResp, error)
|
||||
GetEnterpriseAuthStatus(ctx context.Context, in *GetEnterpriseAuthStatusReq, opts ...grpc.CallOption) (*GetEnterpriseAuthStatusResp, error)
|
||||
GetUserList(ctx context.Context, in *UserListRequest, opts ...grpc.CallOption) (*UserListResponse, error)
|
||||
}
|
||||
|
||||
type userClient struct {
|
||||
@@ -426,6 +428,16 @@ func (c *userClient) GetEnterpriseAuthStatus(ctx context.Context, in *GetEnterpr
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (c *userClient) GetUserList(ctx context.Context, in *UserListRequest, opts ...grpc.CallOption) (*UserListResponse, error) {
|
||||
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
|
||||
out := new(UserListResponse)
|
||||
err := c.cc.Invoke(ctx, User_GetUserList_FullMethodName, in, out, cOpts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
// UserServer is the server API for User service.
|
||||
// All implementations must embed UnimplementedUserServer
|
||||
// for forward compatibility
|
||||
@@ -434,6 +446,7 @@ type UserServer interface {
|
||||
UserInfo(context.Context, *UserInfoReq) (*UserInfoResp, error)
|
||||
GetUserInfo(context.Context, *UserInfoReq) (*GetUserInfoResp, error)
|
||||
GetEnterpriseAuthStatus(context.Context, *GetEnterpriseAuthStatusReq) (*GetEnterpriseAuthStatusResp, error)
|
||||
GetUserList(context.Context, *UserListRequest) (*UserListResponse, error)
|
||||
mustEmbedUnimplementedUserServer()
|
||||
}
|
||||
|
||||
@@ -450,6 +463,9 @@ func (UnimplementedUserServer) GetUserInfo(context.Context, *UserInfoReq) (*GetU
|
||||
func (UnimplementedUserServer) GetEnterpriseAuthStatus(context.Context, *GetEnterpriseAuthStatusReq) (*GetEnterpriseAuthStatusResp, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method GetEnterpriseAuthStatus not implemented")
|
||||
}
|
||||
func (UnimplementedUserServer) GetUserList(context.Context, *UserListRequest) (*UserListResponse, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method GetUserList not implemented")
|
||||
}
|
||||
func (UnimplementedUserServer) mustEmbedUnimplementedUserServer() {}
|
||||
|
||||
// UnsafeUserServer may be embedded to opt out of forward compatibility for this service.
|
||||
@@ -517,6 +533,24 @@ func _User_GetEnterpriseAuthStatus_Handler(srv interface{}, ctx context.Context,
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
func _User_GetUserList_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(UserListRequest)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if interceptor == nil {
|
||||
return srv.(UserServer).GetUserList(ctx, in)
|
||||
}
|
||||
info := &grpc.UnaryServerInfo{
|
||||
Server: srv,
|
||||
FullMethod: User_GetUserList_FullMethodName,
|
||||
}
|
||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.(UserServer).GetUserList(ctx, req.(*UserListRequest))
|
||||
}
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
// User_ServiceDesc is the grpc.ServiceDesc for User service.
|
||||
// It's only intended for direct use with grpc.RegisterService,
|
||||
// and not to be introspected or modified (even as a copy)
|
||||
@@ -536,6 +570,10 @@ var User_ServiceDesc = grpc.ServiceDesc{
|
||||
MethodName: "GetEnterpriseAuthStatus",
|
||||
Handler: _User_GetEnterpriseAuthStatus_Handler,
|
||||
},
|
||||
{
|
||||
MethodName: "GetUserList",
|
||||
Handler: _User_GetUserList_Handler,
|
||||
},
|
||||
},
|
||||
Streams: []grpc.StreamDesc{},
|
||||
Metadata: "user.proto",
|
||||
|
||||
Reference in New Issue
Block a user