This commit is contained in:
2025-12-02 19:57:10 +08:00
parent 3440744179
commit 08ff223ff8
188 changed files with 12337 additions and 7212 deletions

View File

@@ -1,16 +1,15 @@
# 设置输出编码为UTF-8
[Console]::OutputEncoding = [System.Text.Encoding]::UTF8
# 数据库连接信息 - 修改了URL格式
$DB_URL = "ycc:5vg67b3UNHu8@(127.0.0.1:21001)/ycc"
# 目录配置
$OUTPUT_DIR = "./model"
$TEMPLATE_DIR = "../template"
$TARGET_DIR = "../../app/main/model"
# 表名列表
$tables = @(
# ============================================
# 新代理系统表
# ============================================
"agent",
# "agent",
# "agent_audit",
# "agent_wallet",
# "agent_relation",
@@ -20,9 +19,12 @@ $tables = @(
# "agent_rebate",
# "agent_upgrade",
# "agent_withdrawal",
# "agent_config",
# "agent_product_config",
"agent_real_name"
# "agent_config"
# "agent_product_config"
# "agent_invite_code_usage"
# "agent_freeze_task"
"agent_short_link"
# "agent_real_name"
# "agent_withdrawal_tax"
# "agent_invite_code"
# ============================================
@@ -60,5 +62,68 @@ $tables = @(
# 为每个表生成模型
foreach ($table in $tables) {
Write-Host "正在生成表: $table" -ForegroundColor Green
goctl model mysql datasource -url="ycc:5vg67b3UNHu8@tcp(127.0.0.1:21001)/ycc" -table="$table" -dir="./model" --home="../template" -cache=true --style=goZero
# 移动生成的文件到目标目录
if (Test-Path $OUTPUT_DIR) {
$sourceFiles = Get-ChildItem -Path $OUTPUT_DIR -File
foreach ($file in $sourceFiles) {
$fileName = $file.Name
$targetPath = Join-Path $TARGET_DIR $fileName
$sourcePath = $file.FullName
# 检查文件类型并决定是否移动
$shouldMove = $false
$shouldOverwrite = $false
if ($fileName -eq "vars.go") {
# vars.go: 如果目标目录不存在才移动
if (-not (Test-Path $targetPath)) {
$shouldMove = $true
Write-Host " 移动 $fileName (vars.go 不存在于目标目录)" -ForegroundColor Yellow
}
else {
Write-Host " 跳过 $fileName (vars.go 已存在于目标目录,防止覆盖)" -ForegroundColor Cyan
}
}
elseif ($fileName -match "_gen\.go$") {
# 带 _gen 后缀的文件: 直接覆盖
$shouldMove = $true
$shouldOverwrite = $true
Write-Host " 移动 $fileName (覆盖 _gen 文件)" -ForegroundColor Yellow
}
else {
# 不带 _gen 后缀的文件: 如果目标目录不存在才移动
if (-not (Test-Path $targetPath)) {
$shouldMove = $true
Write-Host " 移动 $fileName (非 _gen 文件不存在于目标目录)" -ForegroundColor Yellow
}
else {
Write-Host " 跳过 $fileName (非 _gen 文件已存在于目标目录,防止覆盖)" -ForegroundColor Cyan
}
}
# 执行移动操作
if ($shouldMove) {
# 确保目标目录存在
if (-not (Test-Path $TARGET_DIR)) {
New-Item -ItemType Directory -Path $TARGET_DIR -Force | Out-Null
}
# 如果目标文件存在且需要覆盖,先删除
if ($shouldOverwrite -and (Test-Path $targetPath)) {
Remove-Item -Path $targetPath -Force
}
# 移动文件
Move-Item -Path $sourcePath -Destination $targetPath -Force
Write-Host " ✓ 已移动到: $targetPath" -ForegroundColor Green
}
}
}
}
Write-Host ""
Write-Host '所有模型文件生成并移动完成!' -ForegroundColor Green

View File

@@ -1,27 +0,0 @@
package model
import (
"github.com/zeromicro/go-zero/core/stores/cache"
"github.com/zeromicro/go-zero/core/stores/sqlx"
)
var _ AgentInviteCodeModel = (*customAgentInviteCodeModel)(nil)
type (
// AgentInviteCodeModel is an interface to be customized, add more methods here,
// and implement the added methods in customAgentInviteCodeModel.
AgentInviteCodeModel interface {
agentInviteCodeModel
}
customAgentInviteCodeModel struct {
*defaultAgentInviteCodeModel
}
)
// NewAgentInviteCodeModel returns a model for the database table.
func NewAgentInviteCodeModel(conn sqlx.SqlConn, c cache.CacheConf) AgentInviteCodeModel {
return &customAgentInviteCodeModel{
defaultAgentInviteCodeModel: newAgentInviteCodeModel(conn, c),
}
}

View File

@@ -1,414 +0,0 @@
// Code generated by goctl. DO NOT EDIT!
package model
import (
"context"
"database/sql"
"fmt"
"strings"
"time"
"github.com/Masterminds/squirrel"
"github.com/pkg/errors"
"github.com/zeromicro/go-zero/core/stores/builder"
"github.com/zeromicro/go-zero/core/stores/cache"
"github.com/zeromicro/go-zero/core/stores/sqlc"
"github.com/zeromicro/go-zero/core/stores/sqlx"
"github.com/zeromicro/go-zero/core/stringx"
"ycc-server/common/globalkey"
)
var (
agentInviteCodeFieldNames = builder.RawFieldNames(&AgentInviteCode{})
agentInviteCodeRows = strings.Join(agentInviteCodeFieldNames, ",")
agentInviteCodeRowsExpectAutoSet = strings.Join(stringx.Remove(agentInviteCodeFieldNames, "`id`", "`create_time`", "`update_time`"), ",")
agentInviteCodeRowsWithPlaceHolder = strings.Join(stringx.Remove(agentInviteCodeFieldNames, "`id`", "`create_time`", "`update_time`"), "=?,") + "=?"
cacheYccAgentInviteCodeIdPrefix = "cache:ycc:agentInviteCode:id:"
cacheYccAgentInviteCodeCodePrefix = "cache:ycc:agentInviteCode:code:"
)
type (
agentInviteCodeModel interface {
Insert(ctx context.Context, session sqlx.Session, data *AgentInviteCode) (sql.Result, error)
FindOne(ctx context.Context, id int64) (*AgentInviteCode, error)
FindOneByCode(ctx context.Context, code string) (*AgentInviteCode, error)
Update(ctx context.Context, session sqlx.Session, data *AgentInviteCode) (sql.Result, error)
UpdateWithVersion(ctx context.Context, session sqlx.Session, data *AgentInviteCode) error
Trans(ctx context.Context, fn func(context context.Context, session sqlx.Session) error) error
SelectBuilder() squirrel.SelectBuilder
DeleteSoft(ctx context.Context, session sqlx.Session, data *AgentInviteCode) error
FindSum(ctx context.Context, sumBuilder squirrel.SelectBuilder, field string) (float64, error)
FindCount(ctx context.Context, countBuilder squirrel.SelectBuilder, field string) (int64, error)
FindAll(ctx context.Context, rowBuilder squirrel.SelectBuilder, orderBy string) ([]*AgentInviteCode, error)
FindPageListByPage(ctx context.Context, rowBuilder squirrel.SelectBuilder, page, pageSize int64, orderBy string) ([]*AgentInviteCode, error)
FindPageListByPageWithTotal(ctx context.Context, rowBuilder squirrel.SelectBuilder, page, pageSize int64, orderBy string) ([]*AgentInviteCode, int64, error)
FindPageListByIdDESC(ctx context.Context, rowBuilder squirrel.SelectBuilder, preMinId, pageSize int64) ([]*AgentInviteCode, error)
FindPageListByIdASC(ctx context.Context, rowBuilder squirrel.SelectBuilder, preMaxId, pageSize int64) ([]*AgentInviteCode, error)
Delete(ctx context.Context, session sqlx.Session, id int64) error
}
defaultAgentInviteCodeModel struct {
sqlc.CachedConn
table string
}
AgentInviteCode struct {
Id int64 `db:"id"` // 主键ID
Code string `db:"code"` // 邀请码(唯一)
AgentId sql.NullInt64 `db:"agent_id"` // 发放代理IDNULL表示平台发放的钻石邀请码
TargetLevel int64 `db:"target_level"` // 目标等级1=普通2=黄金3=钻石
Status int64 `db:"status"` // 状态0=未使用1=已使用2=已失效(所有邀请码只能使用一次,使用后立即失效)
UsedUserId sql.NullInt64 `db:"used_user_id"` // 使用用户ID
UsedAgentId sql.NullInt64 `db:"used_agent_id"` // 使用代理ID
UsedTime sql.NullTime `db:"used_time"` // 使用时间
ExpireTime sql.NullTime `db:"expire_time"` // 过期时间(可选)
Remark sql.NullString `db:"remark"` // 备注
CreateTime time.Time `db:"create_time"` // 创建时间
UpdateTime time.Time `db:"update_time"` // 更新时间
DeleteTime sql.NullTime `db:"delete_time"` // 删除时间
DelState int64 `db:"del_state"` // 删除状态0=未删除1=已删除
Version int64 `db:"version"` // 版本号(乐观锁)
}
)
func newAgentInviteCodeModel(conn sqlx.SqlConn, c cache.CacheConf) *defaultAgentInviteCodeModel {
return &defaultAgentInviteCodeModel{
CachedConn: sqlc.NewConn(conn, c),
table: "`agent_invite_code`",
}
}
func (m *defaultAgentInviteCodeModel) Insert(ctx context.Context, session sqlx.Session, data *AgentInviteCode) (sql.Result, error) {
data.DelState = globalkey.DelStateNo
yccAgentInviteCodeCodeKey := fmt.Sprintf("%s%v", cacheYccAgentInviteCodeCodePrefix, data.Code)
yccAgentInviteCodeIdKey := fmt.Sprintf("%s%v", cacheYccAgentInviteCodeIdPrefix, data.Id)
return m.ExecCtx(ctx, func(ctx context.Context, conn sqlx.SqlConn) (result sql.Result, err error) {
query := fmt.Sprintf("insert into %s (%s) values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", m.table, agentInviteCodeRowsExpectAutoSet)
if session != nil {
return session.ExecCtx(ctx, query, data.Code, data.AgentId, data.TargetLevel, data.Status, data.UsedUserId, data.UsedAgentId, data.UsedTime, data.ExpireTime, data.Remark, data.DeleteTime, data.DelState, data.Version)
}
return conn.ExecCtx(ctx, query, data.Code, data.AgentId, data.TargetLevel, data.Status, data.UsedUserId, data.UsedAgentId, data.UsedTime, data.ExpireTime, data.Remark, data.DeleteTime, data.DelState, data.Version)
}, yccAgentInviteCodeCodeKey, yccAgentInviteCodeIdKey)
}
func (m *defaultAgentInviteCodeModel) FindOne(ctx context.Context, id int64) (*AgentInviteCode, error) {
yccAgentInviteCodeIdKey := fmt.Sprintf("%s%v", cacheYccAgentInviteCodeIdPrefix, id)
var resp AgentInviteCode
err := m.QueryRowCtx(ctx, &resp, yccAgentInviteCodeIdKey, func(ctx context.Context, conn sqlx.SqlConn, v interface{}) error {
query := fmt.Sprintf("select %s from %s where `id` = ? and del_state = ? limit 1", agentInviteCodeRows, m.table)
return conn.QueryRowCtx(ctx, v, query, id, globalkey.DelStateNo)
})
switch err {
case nil:
return &resp, nil
case sqlc.ErrNotFound:
return nil, ErrNotFound
default:
return nil, err
}
}
func (m *defaultAgentInviteCodeModel) FindOneByCode(ctx context.Context, code string) (*AgentInviteCode, error) {
yccAgentInviteCodeCodeKey := fmt.Sprintf("%s%v", cacheYccAgentInviteCodeCodePrefix, code)
var resp AgentInviteCode
err := m.QueryRowIndexCtx(ctx, &resp, yccAgentInviteCodeCodeKey, m.formatPrimary, func(ctx context.Context, conn sqlx.SqlConn, v interface{}) (i interface{}, e error) {
query := fmt.Sprintf("select %s from %s where `code` = ? and del_state = ? limit 1", agentInviteCodeRows, m.table)
if err := conn.QueryRowCtx(ctx, &resp, query, code, globalkey.DelStateNo); err != nil {
return nil, err
}
return resp.Id, nil
}, m.queryPrimary)
switch err {
case nil:
return &resp, nil
case sqlc.ErrNotFound:
return nil, ErrNotFound
default:
return nil, err
}
}
func (m *defaultAgentInviteCodeModel) Update(ctx context.Context, session sqlx.Session, newData *AgentInviteCode) (sql.Result, error) {
data, err := m.FindOne(ctx, newData.Id)
if err != nil {
return nil, err
}
yccAgentInviteCodeCodeKey := fmt.Sprintf("%s%v", cacheYccAgentInviteCodeCodePrefix, data.Code)
yccAgentInviteCodeIdKey := fmt.Sprintf("%s%v", cacheYccAgentInviteCodeIdPrefix, data.Id)
return m.ExecCtx(ctx, func(ctx context.Context, conn sqlx.SqlConn) (result sql.Result, err error) {
query := fmt.Sprintf("update %s set %s where `id` = ?", m.table, agentInviteCodeRowsWithPlaceHolder)
if session != nil {
return session.ExecCtx(ctx, query, newData.Code, newData.AgentId, newData.TargetLevel, newData.Status, newData.UsedUserId, newData.UsedAgentId, newData.UsedTime, newData.ExpireTime, newData.Remark, newData.DeleteTime, newData.DelState, newData.Version, newData.Id)
}
return conn.ExecCtx(ctx, query, newData.Code, newData.AgentId, newData.TargetLevel, newData.Status, newData.UsedUserId, newData.UsedAgentId, newData.UsedTime, newData.ExpireTime, newData.Remark, newData.DeleteTime, newData.DelState, newData.Version, newData.Id)
}, yccAgentInviteCodeCodeKey, yccAgentInviteCodeIdKey)
}
func (m *defaultAgentInviteCodeModel) UpdateWithVersion(ctx context.Context, session sqlx.Session, newData *AgentInviteCode) error {
oldVersion := newData.Version
newData.Version += 1
var sqlResult sql.Result
var err error
data, err := m.FindOne(ctx, newData.Id)
if err != nil {
return err
}
yccAgentInviteCodeCodeKey := fmt.Sprintf("%s%v", cacheYccAgentInviteCodeCodePrefix, data.Code)
yccAgentInviteCodeIdKey := fmt.Sprintf("%s%v", cacheYccAgentInviteCodeIdPrefix, data.Id)
sqlResult, err = m.ExecCtx(ctx, func(ctx context.Context, conn sqlx.SqlConn) (result sql.Result, err error) {
query := fmt.Sprintf("update %s set %s where `id` = ? and version = ? ", m.table, agentInviteCodeRowsWithPlaceHolder)
if session != nil {
return session.ExecCtx(ctx, query, newData.Code, newData.AgentId, newData.TargetLevel, newData.Status, newData.UsedUserId, newData.UsedAgentId, newData.UsedTime, newData.ExpireTime, newData.Remark, newData.DeleteTime, newData.DelState, newData.Version, newData.Id, oldVersion)
}
return conn.ExecCtx(ctx, query, newData.Code, newData.AgentId, newData.TargetLevel, newData.Status, newData.UsedUserId, newData.UsedAgentId, newData.UsedTime, newData.ExpireTime, newData.Remark, newData.DeleteTime, newData.DelState, newData.Version, newData.Id, oldVersion)
}, yccAgentInviteCodeCodeKey, yccAgentInviteCodeIdKey)
if err != nil {
return err
}
updateCount, err := sqlResult.RowsAffected()
if err != nil {
return err
}
if updateCount == 0 {
return ErrNoRowsUpdate
}
return nil
}
func (m *defaultAgentInviteCodeModel) DeleteSoft(ctx context.Context, session sqlx.Session, data *AgentInviteCode) error {
data.DelState = globalkey.DelStateYes
data.DeleteTime = sql.NullTime{Time: time.Now(), Valid: true}
if err := m.UpdateWithVersion(ctx, session, data); err != nil {
return errors.Wrapf(errors.New("delete soft failed "), "AgentInviteCodeModel delete err : %+v", err)
}
return nil
}
func (m *defaultAgentInviteCodeModel) FindSum(ctx context.Context, builder squirrel.SelectBuilder, field string) (float64, error) {
if len(field) == 0 {
return 0, errors.Wrapf(errors.New("FindSum Least One Field"), "FindSum Least One Field")
}
builder = builder.Columns("IFNULL(SUM(" + field + "),0)")
query, values, err := builder.Where("del_state = ?", globalkey.DelStateNo).ToSql()
if err != nil {
return 0, err
}
var resp float64
err = m.QueryRowNoCacheCtx(ctx, &resp, query, values...)
switch err {
case nil:
return resp, nil
default:
return 0, err
}
}
func (m *defaultAgentInviteCodeModel) FindCount(ctx context.Context, builder squirrel.SelectBuilder, field string) (int64, error) {
if len(field) == 0 {
return 0, errors.Wrapf(errors.New("FindCount Least One Field"), "FindCount Least One Field")
}
builder = builder.Columns("COUNT(" + field + ")")
query, values, err := builder.Where("del_state = ?", globalkey.DelStateNo).ToSql()
if err != nil {
return 0, err
}
var resp int64
err = m.QueryRowNoCacheCtx(ctx, &resp, query, values...)
switch err {
case nil:
return resp, nil
default:
return 0, err
}
}
func (m *defaultAgentInviteCodeModel) FindAll(ctx context.Context, builder squirrel.SelectBuilder, orderBy string) ([]*AgentInviteCode, error) {
builder = builder.Columns(agentInviteCodeRows)
if orderBy == "" {
builder = builder.OrderBy("id DESC")
} else {
builder = builder.OrderBy(orderBy)
}
query, values, err := builder.Where("del_state = ?", globalkey.DelStateNo).ToSql()
if err != nil {
return nil, err
}
var resp []*AgentInviteCode
err = m.QueryRowsNoCacheCtx(ctx, &resp, query, values...)
switch err {
case nil:
return resp, nil
default:
return nil, err
}
}
func (m *defaultAgentInviteCodeModel) FindPageListByPage(ctx context.Context, builder squirrel.SelectBuilder, page, pageSize int64, orderBy string) ([]*AgentInviteCode, error) {
builder = builder.Columns(agentInviteCodeRows)
if orderBy == "" {
builder = builder.OrderBy("id DESC")
} else {
builder = builder.OrderBy(orderBy)
}
if page < 1 {
page = 1
}
offset := (page - 1) * pageSize
query, values, err := builder.Where("del_state = ?", globalkey.DelStateNo).Offset(uint64(offset)).Limit(uint64(pageSize)).ToSql()
if err != nil {
return nil, err
}
var resp []*AgentInviteCode
err = m.QueryRowsNoCacheCtx(ctx, &resp, query, values...)
switch err {
case nil:
return resp, nil
default:
return nil, err
}
}
func (m *defaultAgentInviteCodeModel) FindPageListByPageWithTotal(ctx context.Context, builder squirrel.SelectBuilder, page, pageSize int64, orderBy string) ([]*AgentInviteCode, int64, error) {
total, err := m.FindCount(ctx, builder, "id")
if err != nil {
return nil, 0, err
}
builder = builder.Columns(agentInviteCodeRows)
if orderBy == "" {
builder = builder.OrderBy("id DESC")
} else {
builder = builder.OrderBy(orderBy)
}
if page < 1 {
page = 1
}
offset := (page - 1) * pageSize
query, values, err := builder.Where("del_state = ?", globalkey.DelStateNo).Offset(uint64(offset)).Limit(uint64(pageSize)).ToSql()
if err != nil {
return nil, total, err
}
var resp []*AgentInviteCode
err = m.QueryRowsNoCacheCtx(ctx, &resp, query, values...)
switch err {
case nil:
return resp, total, nil
default:
return nil, total, err
}
}
func (m *defaultAgentInviteCodeModel) FindPageListByIdDESC(ctx context.Context, builder squirrel.SelectBuilder, preMinId, pageSize int64) ([]*AgentInviteCode, error) {
builder = builder.Columns(agentInviteCodeRows)
if preMinId > 0 {
builder = builder.Where(" id < ? ", preMinId)
}
query, values, err := builder.Where("del_state = ?", globalkey.DelStateNo).OrderBy("id DESC").Limit(uint64(pageSize)).ToSql()
if err != nil {
return nil, err
}
var resp []*AgentInviteCode
err = m.QueryRowsNoCacheCtx(ctx, &resp, query, values...)
switch err {
case nil:
return resp, nil
default:
return nil, err
}
}
func (m *defaultAgentInviteCodeModel) FindPageListByIdASC(ctx context.Context, builder squirrel.SelectBuilder, preMaxId, pageSize int64) ([]*AgentInviteCode, error) {
builder = builder.Columns(agentInviteCodeRows)
if preMaxId > 0 {
builder = builder.Where(" id > ? ", preMaxId)
}
query, values, err := builder.Where("del_state = ?", globalkey.DelStateNo).OrderBy("id ASC").Limit(uint64(pageSize)).ToSql()
if err != nil {
return nil, err
}
var resp []*AgentInviteCode
err = m.QueryRowsNoCacheCtx(ctx, &resp, query, values...)
switch err {
case nil:
return resp, nil
default:
return nil, err
}
}
func (m *defaultAgentInviteCodeModel) Trans(ctx context.Context, fn func(ctx context.Context, session sqlx.Session) error) error {
return m.TransactCtx(ctx, func(ctx context.Context, session sqlx.Session) error {
return fn(ctx, session)
})
}
func (m *defaultAgentInviteCodeModel) SelectBuilder() squirrel.SelectBuilder {
return squirrel.Select().From(m.table)
}
func (m *defaultAgentInviteCodeModel) Delete(ctx context.Context, session sqlx.Session, id int64) error {
data, err := m.FindOne(ctx, id)
if err != nil {
return err
}
yccAgentInviteCodeCodeKey := fmt.Sprintf("%s%v", cacheYccAgentInviteCodeCodePrefix, data.Code)
yccAgentInviteCodeIdKey := fmt.Sprintf("%s%v", cacheYccAgentInviteCodeIdPrefix, id)
_, err = m.ExecCtx(ctx, func(ctx context.Context, conn sqlx.SqlConn) (result sql.Result, err error) {
query := fmt.Sprintf("delete from %s where `id` = ?", m.table)
if session != nil {
return session.ExecCtx(ctx, query, id)
}
return conn.ExecCtx(ctx, query, id)
}, yccAgentInviteCodeCodeKey, yccAgentInviteCodeIdKey)
return err
}
func (m *defaultAgentInviteCodeModel) formatPrimary(primary interface{}) string {
return fmt.Sprintf("%s%v", cacheYccAgentInviteCodeIdPrefix, primary)
}
func (m *defaultAgentInviteCodeModel) queryPrimary(ctx context.Context, conn sqlx.SqlConn, v, primary interface{}) error {
query := fmt.Sprintf("select %s from %s where `id` = ? and del_state = ? limit 1", agentInviteCodeRows, m.table)
return conn.QueryRowCtx(ctx, v, query, primary, globalkey.DelStateNo)
}
func (m *defaultAgentInviteCodeModel) tableName() string {
return m.table
}

View File

@@ -0,0 +1,47 @@
-- ============================================
-- 代理短链表
-- 说明:存储推广链接和邀请链接的短链映射关系
--
-- 功能说明:
-- 1. 支持两种类型promotion推广报告和 invite邀请好友
-- 2. 为每个链接生成一个短链标识6位随机字符串
-- 3. 短链格式https://推广域名/s/{short_code}
-- 4. 短链重定向到前端传入的target_path
--
-- 执行步骤:
-- 1. 执行此 SQL 创建表
-- 2. 使用 goctl 生成 Modelagent_short_link -> AgentShortLinkModel
-- 3. 在 servicecontext.go 中添加 AgentShortLinkModel
-- ============================================
CREATE TABLE `agent_short_link` (
`id` bigint NOT NULL AUTO_INCREMENT COMMENT '主键ID',
`type` tinyint NOT NULL COMMENT '类型1=推广报告(promotion)2=邀请好友(invite)',
`link_id` bigint DEFAULT NULL COMMENT '推广链接ID关联agent_link表仅推广报告类型使用',
`invite_code_id` bigint DEFAULT NULL COMMENT '邀请码ID关联agent_invite_code表仅邀请好友类型使用',
`link_identifier` varchar(200) DEFAULT NULL COMMENT '推广链接标识(加密,仅推广报告类型使用)',
`invite_code` varchar(50) DEFAULT NULL COMMENT '邀请码(仅邀请好友类型使用)',
`short_code` varchar(20) NOT NULL COMMENT '短链标识6位随机字符串',
`target_path` varchar(500) NOT NULL COMMENT '目标地址(前端传入,如:/agent/promotionInquire/xxx 或 /register?invite_code=xxx',
`promotion_domain` varchar(200) NOT NULL COMMENT '推广域名(生成短链时使用的域名)',
`create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
`delete_time` datetime DEFAULT NULL COMMENT '删除时间',
`del_state` tinyint NOT NULL DEFAULT 0 COMMENT '删除状态0=未删除1=已删除',
`version` bigint NOT NULL DEFAULT 0 COMMENT '版本号(乐观锁)',
PRIMARY KEY (`id`),
UNIQUE KEY `uk_short_code` (`short_code`, `del_state`) COMMENT '短链标识唯一索引',
UNIQUE KEY `uk_link_id_type` (
`link_id`,
`type`,
`del_state`
) COMMENT '同一推广链接同一类型只能有一个有效短链',
UNIQUE KEY `uk_invite_code_id_type` (
`invite_code_id`,
`type`,
`del_state`
) COMMENT '同一邀请码同一类型只能有一个有效短链',
KEY `idx_link_identifier` (`link_identifier`) COMMENT '推广链接标识索引',
KEY `idx_invite_code` (`invite_code`) COMMENT '邀请码索引',
KEY `idx_type` (`type`) COMMENT '类型索引',
KEY `idx_create_time` (`create_time`) COMMENT '创建时间索引'
) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '代理短链表';

View File

@@ -0,0 +1,46 @@
-- ============================================
-- 邀请码使用历史表
-- 说明:记录每次邀请码的使用情况,支持统计和查询
--
-- 功能说明:
-- 1. 记录每个邀请码每次使用的详细信息
-- 2. 支持统计每个邀请码邀请了多少代理
-- 3. 支持查询某个代理是通过哪个邀请码成为代理的
-- 4. 保留完整的使用历史记录
--
-- 执行步骤:
-- 1. 执行此 SQL 创建表和添加字段
-- 2. 使用 goctl 生成 Modelagent_invite_code_usage -> AgentInviteCodeUsageModel
-- 3. 在 servicecontext.go 中添加 AgentInviteCodeUsageModel
-- ============================================
CREATE TABLE `agent_invite_code_usage` (
`id` bigint NOT NULL AUTO_INCREMENT COMMENT '主键ID',
`invite_code_id` bigint NOT NULL COMMENT '邀请码ID关联agent_invite_code表',
`code` varchar(50) NOT NULL COMMENT '邀请码(冗余字段,便于查询)',
`user_id` bigint NOT NULL COMMENT '使用用户ID',
`agent_id` bigint NOT NULL COMMENT '成为的代理ID',
`agent_level` tinyint NOT NULL COMMENT '代理等级1=普通2=黄金3=钻石',
`used_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '使用时间',
`create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
`delete_time` datetime DEFAULT NULL COMMENT '删除时间',
`del_state` tinyint NOT NULL DEFAULT 0 COMMENT '删除状态0=未删除1=已删除',
`version` bigint NOT NULL DEFAULT 0 COMMENT '版本号(乐观锁)',
PRIMARY KEY (`id`),
KEY `idx_invite_code_id` (`invite_code_id`) COMMENT '关联邀请码ID',
KEY `idx_code` (`code`) COMMENT '邀请码索引',
KEY `idx_user_id` (`user_id`) COMMENT '用户ID索引',
KEY `idx_agent_id` (`agent_id`) COMMENT '代理ID索引',
KEY `idx_used_time` (`used_time`) COMMENT '使用时间索引',
KEY `idx_create_time` (`create_time`) COMMENT '创建时间索引',
KEY `idx_code_time` (`code`, `used_time`) COMMENT '邀请码和使用时间复合索引'
) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '邀请码使用历史表';
-- ============================================
-- 在agent表中添加invite_code_id字段可选便于直接查询代理是通过哪个邀请码成为的
-- ============================================
ALTER TABLE `agent`
ADD COLUMN `invite_code_id` bigint DEFAULT NULL COMMENT '通过哪个邀请码成为代理关联agent_invite_code表' AFTER `team_leader_id`;
ALTER TABLE `agent`
ADD KEY `idx_invite_code_id` (`invite_code_id`) COMMENT '邀请码ID索引';

View File

@@ -0,0 +1,56 @@
-- ============================================
-- 代理配置表重构 SQL 脚本
-- 执行顺序:按照下面的顺序依次执行
-- ============================================
-- ============================================
-- 步骤1删除价格相关配置项
-- 说明价格配置已改为在产品配置表agent_product_config中按产品配置
-- ============================================
DELETE FROM `agent_config` WHERE `config_key` IN (
'base_price',
'system_max_price',
'price_threshold',
'price_fee_rate'
);
-- ============================================
-- 步骤2统一配置键命名
-- 说明:修改配置键名称,使其与代码逻辑一致
-- ============================================
-- 修改等级加成配置键
UPDATE `agent_config` SET `config_key` = 'level_1_bonus' WHERE `config_key` = 'level_bonus_normal';
UPDATE `agent_config` SET `config_key` = 'level_2_bonus' WHERE `config_key` = 'level_bonus_gold';
UPDATE `agent_config` SET `config_key` = 'level_3_bonus' WHERE `config_key` = 'level_bonus_diamond';
-- 修改升级费用配置键
UPDATE `agent_config` SET `config_key` = 'upgrade_to_gold_fee' WHERE `config_key` = 'upgrade_fee_normal_to_gold';
UPDATE `agent_config` SET `config_key` = 'upgrade_to_diamond_fee' WHERE `config_key` = 'upgrade_fee_to_diamond';
-- 修改升级返佣配置键
UPDATE `agent_config` SET `config_key` = 'upgrade_to_gold_rebate' WHERE `config_key` = 'upgrade_rebate_normal_to_gold';
UPDATE `agent_config` SET `config_key` = 'upgrade_to_diamond_rebate' WHERE `config_key` = 'upgrade_rebate_to_diamond';
-- ============================================
-- 步骤3添加缺失的配置项
-- 说明:添加免税额度配置项(如果不存在)
-- ============================================
INSERT INTO `agent_config` (`config_key`, `config_value`, `config_type`, `description`)
SELECT 'tax_exemption_amount', '0.00', 'tax', '提现免税额度默认0'
WHERE NOT EXISTS (
SELECT 1 FROM `agent_config` WHERE `config_key` = 'tax_exemption_amount'
);
-- ============================================
-- 验证查询:检查配置项是否正确
-- ============================================
SELECT `config_key`, `config_value`, `config_type`, `description`
FROM `agent_config`
WHERE `del_state` = 0
ORDER BY `config_type`, `config_key`;
-- ============================================
-- 执行完成后,请重新生成 agent_config 相关的 Model 代码
-- ============================================

View File

@@ -0,0 +1,32 @@
-- ============================================
-- 代理佣金冻结任务表
-- 说明:用于记录需要解冻的佣金冻结任务,保证异步任务的一致性和持久化
-- ============================================
CREATE TABLE `agent_freeze_task` (
`id` bigint NOT NULL AUTO_INCREMENT COMMENT '主键ID',
`agent_id` bigint NOT NULL COMMENT '代理ID',
`order_id` bigint NOT NULL COMMENT '订单ID',
`commission_id` bigint NOT NULL COMMENT '佣金记录ID',
`freeze_amount` decimal(10, 2) NOT NULL COMMENT '冻结金额',
`order_price` decimal(10, 2) NOT NULL COMMENT '订单单价',
`freeze_ratio` decimal(5, 4) NOT NULL DEFAULT 0.1000 COMMENT '冻结比例例如0.1000表示10%',
`status` tinyint NOT NULL DEFAULT 1 COMMENT '状态1=待解冻2=已解冻3=已取消',
`freeze_time` datetime NOT NULL COMMENT '冻结时间',
`unfreeze_time` datetime NOT NULL COMMENT '解冻时间(冻结时间+1个月',
`actual_unfreeze_time` datetime DEFAULT NULL COMMENT '实际解冻时间',
`remark` varchar(255) DEFAULT NULL COMMENT '备注',
`create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
`delete_time` datetime DEFAULT NULL COMMENT '删除时间',
`del_state` tinyint NOT NULL DEFAULT 0 COMMENT '删除状态0=未删除1=已删除',
`version` bigint NOT NULL DEFAULT 0 COMMENT '版本号(乐观锁)',
PRIMARY KEY (`id`),
KEY `idx_agent_id` (`agent_id`),
KEY `idx_order_id` (`order_id`),
KEY `idx_commission_id` (`commission_id`),
KEY `idx_status` (`status`),
KEY `idx_unfreeze_time` (`unfreeze_time`),
KEY `idx_agent_status` (`agent_id`, `status`),
KEY `idx_create_time` (`create_time`)
) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '代理佣金冻结任务表';

View File

@@ -0,0 +1,25 @@
-- ============================================
-- 移除代理产品配置表中的 product_name 字段
-- 说明:改为通过 product_id 关联查询 product 表获取产品名称
-- 执行时间2025-01-XX
-- ============================================
-- 删除 product_name 字段
ALTER TABLE `agent_product_config` DROP COLUMN `product_name`;
-- ============================================
-- 验证查询:检查字段是否已删除
-- ============================================
DESC `agent_product_config`;
-- ============================================
-- 验证查询:通过关联查询获取产品名称
-- ============================================
SELECT apc.id, apc.product_id, p.product_name, apc.base_price, apc.system_max_price, apc.price_threshold, apc.price_fee_rate, apc.del_state, apc.create_time
FROM
`agent_product_config` apc
LEFT JOIN `product` p ON apc.product_id = p.id
AND p.del_state = 0
WHERE
apc.del_state = 0
ORDER BY apc.product_id;

View File

@@ -0,0 +1,112 @@
-- ============================================
-- 同步产品表数据到代理产品配置表
-- 说明:为现有产品创建对应的代理产品配置记录
-- 执行时间2025-01-XX
-- ============================================
-- 方式1使用 INSERT IGNORE如果记录已存在则忽略
-- 注意product_name 字段已移除,改为通过 product_id 关联查询 product 表获取
INSERT IGNORE INTO
`agent_product_config` (
`product_id`,
`base_price`,
`system_max_price`,
`price_threshold`,
`price_fee_rate`,
`del_state`,
`version`
)
VALUES (
1,
0.00,
9999.99,
NULL,
NULL,
0,
0
),
(
2,
0.00,
9999.99,
NULL,
NULL,
0,
0
),
(
3,
0.00,
9999.99,
NULL,
NULL,
0,
0
),
(
4,
0.00,
9999.99,
NULL,
NULL,
0,
0
),
(
5,
0.00,
9999.99,
NULL,
NULL,
0,
0
),
(
6,
0.00,
9999.99,
NULL,
NULL,
0,
0
),
(
7,
0.00,
9999.99,
NULL,
NULL,
0,
0
);
-- ============================================
-- 方式2使用 INSERT ... ON DUPLICATE KEY UPDATE如果记录已存在则忽略
-- 注意product_name 字段已移除,不再需要更新
-- ============================================
/*
INSERT INTO `agent_product_config`
(`product_id`, `base_price`, `system_max_price`, `price_threshold`, `price_fee_rate`, `del_state`, `version`)
VALUES
(1, 0.00, 9999.99, NULL, NULL, 0, 0),
(2, 0.00, 9999.99, NULL, NULL, 0, 0),
(3, 0.00, 9999.99, NULL, NULL, 0, 0),
(4, 0.00, 9999.99, NULL, NULL, 0, 0),
(5, 0.00, 9999.99, NULL, NULL, 0, 0),
(6, 0.00, 9999.99, NULL, NULL, 0, 0),
(7, 0.00, 9999.99, NULL, NULL, 0, 0)
ON DUPLICATE KEY UPDATE
`product_id` = VALUES(`product_id`);
*/
-- ============================================
-- 验证查询:检查同步结果
-- ============================================
SELECT apc.id, apc.product_id, p.product_name, apc.base_price, apc.system_max_price, apc.price_threshold, apc.price_fee_rate, apc.del_state, apc.create_time
FROM
`agent_product_config` apc
LEFT JOIN `product` p ON apc.product_id = p.id
AND p.del_state = 0
WHERE
apc.del_state = 0
ORDER BY apc.product_id;