Files
kami_backend/internal/logic/camel_oil/account.go
danial 15e2426e85 feat(camel_oil): 新增骆驼加油账号管理模块
- 实现账号增删改查接口和逻辑
- 支持账号状态更新及状态历史记录功能
- 提供账号列表、历史和统计信息查询API
- 实现账号轮询机制,支持按使用时间轮询获取账号
- 增加账号登录流程及批量登录功能,集成接码平台和平台API
- 管理账号订单容量,支持容量检查与账号登录触发
- 提供账号池状态统计接口
- 账号历史记录查询支持多种变更类型文本展示
- 密码等敏感信息采用脱敏展示
- 完善日志记录和错误处理机制,保证业务稳定运行
2025-11-21 00:49:50 +08:00

262 lines
7.8 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package camel_oil
import (
"context"
"github.com/gogf/gf/v2/errors/gerror"
"github.com/gogf/gf/v2/frame/g"
"github.com/gogf/gf/v2/os/glog"
v1 "kami/api/camel_oil/v1"
"kami/internal/consts"
"kami/internal/dao"
"kami/internal/model/do"
"kami/internal/model/entity"
"kami/utility/config"
)
// ====================================================================================
// 账号管理CRUD相关方法
// ====================================================================================
// GetAccountInfo 获取账号信息
func (s *sCamelOil) GetAccountInfo(ctx context.Context, accountId int64) (account *entity.V1CamelOilAccount, err error) {
m := dao.V1CamelOilAccount.Ctx(ctx).DB(config.GetDatabaseV1())
err = m.Where(dao.V1CamelOilAccount.Columns().Id, accountId).Scan(&account)
if err != nil {
return nil, gerror.Wrap(err, "查询账号信息失败")
}
if account == nil {
return nil, gerror.New("账号不存在")
}
return account, nil
}
// CreateAccount 创建账号
func (s *sCamelOil) CreateAccount(ctx context.Context, phoneNumber, remark string) (accountId int64, err error) {
m := dao.V1CamelOilAccount.Ctx(ctx).DB(config.GetDatabaseV1())
result, err := m.Insert(&do.V1CamelOilAccount{
Phone: phoneNumber,
AccountName: phoneNumber,
Status: int(consts.CamelOilAccountStatusPending),
Remark: remark,
})
if err != nil {
return 0, gerror.Wrap(err, "创建账号失败")
}
id, err := result.LastInsertId()
if err != nil {
return 0, gerror.Wrap(err, "获取账号ID失败")
}
// 记录创建历史
_ = s.RecordAccountHistory(ctx, id, consts.CamelOilAccountChangeTypeCreate,
consts.CamelOilAccountStatusPending, consts.CamelOilAccountStatusPending,
"创建账号")
return id, nil
}
// UpdateAccount 更新账号信息
func (s *sCamelOil) UpdateAccount(ctx context.Context, accountId int64, remark string) (err error) {
m := dao.V1CamelOilAccount.Ctx(ctx).DB(config.GetDatabaseV1())
// 获取账号信息
account, err := s.GetAccountInfo(ctx, accountId)
if err != nil {
return err
}
// 更新账号信息
_, err = m.Where(dao.V1CamelOilAccount.Columns().Id, accountId).Update(&do.V1CamelOilAccount{
Remark: remark,
})
if err != nil {
return gerror.Wrap(err, "更新账号信息失败")
}
// 记录更新历史
_ = s.RecordAccountHistory(ctx, accountId, consts.CamelOilAccountChangeTypeUpdate,
consts.CamelOilAccountStatus(account.Status), consts.CamelOilAccountStatus(account.Status),
"更新账号信息")
return nil
}
// DeleteAccount 删除账号(软删除)
func (s *sCamelOil) DeleteAccount(ctx context.Context, accountId int64) (err error) {
m := dao.V1CamelOilAccount.Ctx(ctx).DB(config.GetDatabaseV1())
// 获取账号信息
account, err := s.GetAccountInfo(ctx, accountId)
if err != nil {
return err
}
// 软删除
_, err = m.Where(dao.V1CamelOilAccount.Columns().Id, accountId).Delete()
if err != nil {
return gerror.Wrap(err, "删除账号失败")
}
// 记录删除历史
_ = s.RecordAccountHistory(ctx, accountId, consts.CamelOilAccountChangeTypeDelete,
consts.CamelOilAccountStatus(account.Status), consts.CamelOilAccountStatus(account.Status),
"删除账号")
return nil
}
// ListAccounts 获取账号列表
func (s *sCamelOil) ListAccounts(ctx context.Context, status int, current, pageSize int) (accounts []*entity.V1CamelOilAccount, total int, err error) {
m := dao.V1CamelOilAccount.Ctx(ctx).DB(config.GetDatabaseV1())
// 构建查询条件
if status >= 0 {
m = m.Where(dao.V1CamelOilAccount.Columns().Status, status)
}
// 查询总数
totalCount, err := m.Count()
if err != nil {
return nil, 0, gerror.Wrap(err, "查询账号总数失败")
}
// 分页查询
err = m.Page(current, pageSize).OrderDesc(dao.V1CamelOilAccount.Columns().CreatedAt).Scan(&accounts)
if err != nil {
return nil, 0, gerror.Wrap(err, "查询账号列表失败")
}
return accounts, totalCount, nil
}
// ListAccount 查询账号列表API版本
func (s *sCamelOil) ListAccount(ctx context.Context, req *v1.ListAccountReq) (res *v1.ListAccountRes, err error) {
m := dao.V1CamelOilAccount.Ctx(ctx).DB(config.GetDatabaseV1())
// 构建查询条件
if req.Status > 0 {
m = m.Where(dao.V1CamelOilAccount.Columns().Status, int(req.Status))
}
if req.Keyword != "" {
// 基于账号ID、账号名称或手机号搜索
m = m.Where("(id LIKE ? OR account_name LIKE ? OR phone LIKE ?)",
"%"+req.Keyword+"%", "%"+req.Keyword+"%", "%"+req.Keyword+"%")
}
// 查询总数
total, err := m.Count()
if err != nil {
return nil, gerror.Wrap(err, "查询账号总数失败")
}
// 分页查询
var accounts []*entity.V1CamelOilAccount
err = m.Page(req.Current, req.PageSize).OrderDesc(dao.V1CamelOilAccount.Columns().CreatedAt).Scan(&accounts)
if err != nil {
return nil, gerror.Wrap(err, "查询账号列表失败")
}
// 组装响应数据
items := make([]v1.AccountListItem, 0, len(accounts))
for _, account := range accounts {
dailyOrderDate := ""
if account.DailyOrderDate != nil {
dailyOrderDate = account.DailyOrderDate.Format("Y-m-d")
}
items = append(items, v1.AccountListItem{
AccountId: account.Id,
AccountName: account.AccountName,
Phone: maskPhone(account.Phone),
Status: consts.CamelOilAccountStatus(account.Status),
StatusText: getAccountStatusText(account.Status),
DailyOrderCount: account.DailyOrderCount,
DailyOrderDate: dailyOrderDate,
TotalOrderCount: account.TotalOrderCount,
LastUsedAt: account.LastUsedAt,
LastLoginAt: account.LastLoginAt,
TokenExpireAt: account.TokenExpireAt,
RemainingOrders: 10 - account.DailyOrderCount,
FailureReason: account.FailureReason,
Remark: account.Remark,
CreatedAt: account.CreatedAt,
UpdatedAt: account.UpdatedAt,
})
}
res = &v1.ListAccountRes{}
res.Total = total
res.List = items
return res, nil
}
// UpdateAccountStatus 更新账号状态并记录历史
func (s *sCamelOil) UpdateAccountStatus(ctx context.Context, accountId int64, newStatus consts.CamelOilAccountStatus, operationType consts.CamelOilAccountChangeType, description string) (err error) {
m := dao.V1CamelOilAccount.Ctx(ctx).DB(config.GetDatabaseV1())
// 获取当前账号信息
account, err := s.GetAccountInfo(ctx, accountId)
if err != nil {
return err
}
oldStatus := consts.CamelOilAccountStatus(account.Status)
// 如果状态没有变化,则不更新
if oldStatus == newStatus {
return nil
}
// 更新账号状态
_, err = m.Where(dao.V1CamelOilAccount.Columns().Id, accountId).Update(&do.V1CamelOilAccount{
Status: int(newStatus),
})
if err != nil {
return gerror.Wrap(err, "更新账号状态失败")
}
// 记录状态变更历史
_ = s.RecordAccountHistory(ctx, accountId, operationType, oldStatus, newStatus, description)
return nil
}
// RecordAccountHistory 记录账号历史
func (s *sCamelOil) RecordAccountHistory(ctx context.Context, accountId int64, operationType consts.CamelOilAccountChangeType,
oldStatus, newStatus consts.CamelOilAccountStatus, description string) (err error) {
m := dao.V1CamelOilAccountHistory.Ctx(ctx).DB(config.GetDatabaseV1())
_, err = m.Insert(&do.V1CamelOilAccountHistory{
AccountId: accountId,
ChangeType: string(operationType),
StatusBefore: int(oldStatus),
StatusAfter: int(newStatus),
Remark: description,
})
if err != nil {
glog.Error(ctx, "记录账号历史失败", g.Map{
"accountId": accountId,
"operationType": operationType,
"error": err,
})
}
return err
}
// GetOrderCountByStatus 获取指定状态的订单数量
func (s *sCamelOil) GetOrderCountByStatus(ctx context.Context, status consts.CamelOilAccountStatus) (count int, err error) {
m := dao.V1CamelOilOrder.Ctx(ctx).DB(config.GetDatabaseV1())
count, err = m.Where(dao.V1CamelOilOrder.Columns().Status, status).Count()
return count, nil
}