修复资金流水和数据库初始化

This commit is contained in:
yml
2026-06-06 14:40:03 +08:00
parent 3640111b8b
commit 13543b3dcb
4 changed files with 100 additions and 20 deletions
@@ -168,7 +168,7 @@ func (r *Repository) AdminLedger(query AdminLedgerQuery) (*PaginatedResult, erro
} }
offset := (query.Page - 1) * query.PageSize offset := (query.Page - 1) * query.PageSize
var items []AdminLedgerDTO items := make([]AdminLedgerDTO, 0, query.PageSize)
if err := db.Order("wl.id DESC").Offset(offset).Limit(query.PageSize).Scan(&items).Error; err != nil { if err := db.Order("wl.id DESC").Offset(offset).Limit(query.PageSize).Scan(&items).Error; err != nil {
return nil, err return nil, err
} }
+86 -16
View File
@@ -250,6 +250,52 @@ CREATE TABLE IF NOT EXISTS payment_orders (
KEY idx_payment_orders_status (status) KEY idx_payment_orders_status (status)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='支付订单表'; ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='支付订单表';
-- 支付商户配置表:支持多商户、多渠道支付配置
CREATE TABLE IF NOT EXISTS payment_merchant_configs (
id BIGINT UNSIGNED PRIMARY KEY AUTO_INCREMENT,
name VARCHAR(128) NOT NULL COMMENT '商户配置名称(用于识别)',
provider VARCHAR(32) NOT NULL COMMENT '支付服务商: leshua乐刷, alipay支付宝, wechat微信, mock模拟',
merchant_id VARCHAR(128) NOT NULL COMMENT '商户号',
gateway_url VARCHAR(512) NOT NULL DEFAULT '' COMMENT '支付网关地址',
sign_key VARCHAR(512) NOT NULL DEFAULT '' COMMENT '签名密钥(加密存储)',
notify_key VARCHAR(512) NOT NULL DEFAULT '' COMMENT '通知验签密钥(加密存储)',
notify_url VARCHAR(512) NOT NULL DEFAULT '' COMMENT '异步通知回调地址',
jump_url VARCHAR(512) NOT NULL DEFAULT '' COMMENT '支付完成跳转地址',
pay_way VARCHAR(32) NOT NULL DEFAULT 'ZFBZF' COMMENT '支付方式: ZFBZF支付宝, WXZF微信',
jspay_flag VARCHAR(8) NOT NULL DEFAULT '2' COMMENT 'JS支付标识: 1 H5, 2 小程序',
sign_type VARCHAR(16) NOT NULL DEFAULT 'MD5' COMMENT '签名类型: MD5, SHA256',
extra_config JSON NULL COMMENT '扩展配置(JSON格式)',
is_default TINYINT(1) NOT NULL DEFAULT 0 COMMENT '是否默认商户: 0否, 1是(每个provider只能有一个默认)',
status VARCHAR(32) NOT NULL DEFAULT 'active' COMMENT '状态: active启用, disabled禁用, testing测试中',
environment VARCHAR(16) NOT NULL DEFAULT 'production' COMMENT '环境: production生产, sandbox测试',
business_tags JSON NULL COMMENT '业务场景标签,如 ["order_pay", "wallet_recharge"]',
total_transactions BIGINT NOT NULL DEFAULT 0 COMMENT '总交易笔数',
total_amount_cent BIGINT NOT NULL DEFAULT 0 COMMENT '总交易金额(分)',
last_used_at DATETIME NULL COMMENT '最后使用时间',
created_by BIGINT UNSIGNED NULL COMMENT '创建人(管理员ID',
updated_by BIGINT UNSIGNED NULL COMMENT '最后更新人(管理员ID',
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
KEY idx_payment_merchant_configs_provider (provider, status),
KEY idx_payment_merchant_configs_default (provider, is_default),
KEY idx_payment_merchant_configs_merchant_id (merchant_id),
KEY idx_payment_merchant_configs_status (status)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='支付商户配置表';
-- 支付配置使用日志:用于追踪支付配置命中情况
CREATE TABLE IF NOT EXISTS payment_config_usage_logs (
id BIGINT UNSIGNED PRIMARY KEY AUTO_INCREMENT,
config_id BIGINT UNSIGNED NOT NULL COMMENT '商户配置ID',
payment_order_id BIGINT UNSIGNED NOT NULL COMMENT '支付订单ID',
provider VARCHAR(32) NOT NULL COMMENT '支付服务商',
merchant_id VARCHAR(128) NOT NULL COMMENT '商户号',
amount_cent BIGINT NOT NULL COMMENT '交易金额(分)',
biz_type VARCHAR(32) NOT NULL COMMENT '业务类型',
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
KEY idx_payment_config_usage_logs_config (config_id, created_at),
KEY idx_payment_config_usage_logs_payment (payment_order_id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='支付配置使用日志';
-- ------------------------------------------- -- -------------------------------------------
-- 纠纷和通知表 -- 纠纷和通知表
-- ------------------------------------------- -- -------------------------------------------
@@ -515,6 +561,17 @@ INSERT INTO permissions (code, name, resource, action) VALUES
('chat:view', '查看客服群聊', 'chat', 'view'), ('chat:view', '查看客服群聊', 'chat', 'view'),
('chat:send', '发送客服消息', 'chat', 'send'), ('chat:send', '发送客服消息', 'chat', 'send'),
('wallet:view', '查看资金流水', 'wallet', 'view'), ('wallet:view', '查看资金流水', 'wallet', 'view'),
('wallet:admin_ledger', '查看资金流水', 'wallet', 'admin_ledger'),
('withdrawal:list', '查看提现列表', 'withdrawal', 'list'),
('withdrawal:review', '审核提现', 'withdrawal', 'review'),
('withdrawal:pay', '确认打款', 'withdrawal', 'pay'),
('withdrawal:detail', '查看提现详情', 'withdrawal', 'detail'),
('withdrawal:approve', '提现审核', 'withdrawal', 'approve'),
('payment_config:list', '查看支付配置', 'payment_config', 'list'),
('payment_config:create', '创建支付配置', 'payment_config', 'create'),
('payment_config:update', '更新支付配置', 'payment_config', 'update'),
('payment_config:delete', '删除支付配置', 'payment_config', 'delete'),
('payment_config:view_secret', '查看支付密钥', 'payment_config', 'view_secret'),
('admin_user:manage', '管理员管理', 'admin_user', 'manage'), ('admin_user:manage', '管理员管理', 'admin_user', 'manage'),
('role:manage', '角色管理', 'role', 'manage'), ('role:manage', '角色管理', 'role', 'manage'),
('system_config:view', '查看系统配置', 'system_config', 'view'), ('system_config:view', '查看系统配置', 'system_config', 'view'),
@@ -557,7 +614,19 @@ WHERE r.code = 'ops' AND p.code IN ('dashboard:view', 'user:view', 'user:freeze'
-- finance 角色权限 -- finance 角色权限
INSERT IGNORE INTO role_permissions (role_id, permission_id) INSERT IGNORE INTO role_permissions (role_id, permission_id)
SELECT r.id, p.id FROM roles r, permissions p SELECT r.id, p.id FROM roles r, permissions p
WHERE r.code = 'finance' AND p.code IN ('dashboard:view', 'wallet:view', 'order:view'); WHERE r.code = 'finance' AND p.code IN (
'dashboard:view',
'wallet:view',
'wallet:admin_ledger',
'order:view',
'withdrawal:list',
'withdrawal:review',
'withdrawal:pay',
'withdrawal:detail',
'withdrawal:approve',
'payment_config:list',
'payment_config:view_secret'
);
-- ------------------------------------------- -- -------------------------------------------
-- 管理员账号初始化 -- 管理员账号初始化
@@ -766,25 +835,26 @@ CREATE TABLE IF NOT EXISTS withdrawal_requests (
KEY idx_withdrawal_requests_created (created_at DESC) KEY idx_withdrawal_requests_created (created_at DESC)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='提现申请表'; ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='提现申请表';
-- ------------------------------------------- -- 确保超级管理员包含所有已初始化权限
-- 提现相关权限 INSERT IGNORE INTO role_permissions (role_id, permission_id)
-- ------------------------------------------- SELECT r.id, p.id FROM roles r
CROSS JOIN permissions p
WHERE r.code = 'super_admin';
-- 添加提现相关权限 -- 确保财务角色包含提现和支付配置权限
INSERT IGNORE INTO permissions (code, name, resource, action) VALUES
('withdrawal:list', '查看提现列表', 'withdrawal', 'list'),
('withdrawal:review', '审核提现', 'withdrawal', 'review'),
('withdrawal:pay', '确认打款', 'withdrawal', 'pay'),
('withdrawal:detail', '查看提现详情', 'withdrawal', 'detail'),
('withdrawal:approve', '提现审核', 'withdrawal', 'approve'),
('wallet:admin_ledger', '查看资金流水', 'wallet', 'admin_ledger');
-- 关联提现权限到财务角色
INSERT IGNORE INTO role_permissions (role_id, permission_id) INSERT IGNORE INTO role_permissions (role_id, permission_id)
SELECT r.id, p.id FROM roles r, permissions p SELECT r.id, p.id FROM roles r, permissions p
WHERE r.code = 'finance' AND p.code IN ('withdrawal:list', 'withdrawal:review', 'withdrawal:pay', 'withdrawal:detail', 'withdrawal:approve', 'wallet:admin_ledger'); WHERE r.code = 'finance' AND p.code IN (
'withdrawal:list',
'withdrawal:review',
'withdrawal:pay',
'withdrawal:detail',
'withdrawal:approve',
'wallet:admin_ledger',
'payment_config:list',
'payment_config:view_secret'
);
-- ============================================ -- ============================================
-- 数据库初始化完成 -- 数据库初始化完成
-- ============================================ -- ============================================
@@ -32,5 +32,11 @@ export interface AdminWalletLedgerQuery {
export async function fetchAdminWalletLedger(query: AdminWalletLedgerQuery = {}) { export async function fetchAdminWalletLedger(query: AdminWalletLedgerQuery = {}) {
const params = Object.fromEntries(Object.entries(query).filter(([, value]) => value !== '' && value !== undefined)) const params = Object.fromEntries(Object.entries(query).filter(([, value]) => value !== '' && value !== undefined))
const { data } = await apiClient.get<ApiResponse<PaginatedResult<AdminWalletLedger>>>('/admin/wallet/ledger', { params }) const { data } = await apiClient.get<ApiResponse<PaginatedResult<AdminWalletLedger>>>('/admin/wallet/ledger', { params })
return data.data const result = data.data
return {
items: Array.isArray(result?.items) ? result.items : [],
total: Number(result?.total ?? 0),
page: Number(result?.page ?? query.page ?? 1),
page_size: Number(result?.page_size ?? query.page_size ?? 20),
}
} }
@@ -36,8 +36,12 @@ async function loadLedger() {
page_size: currentPageSize.value, page_size: currentPageSize.value,
} }
const result = await fetchAdminWalletLedger(query) const result = await fetchAdminWalletLedger(query)
ledger.value = result.items const rows = Array.isArray(result.items) ? result.items : []
total.value = result.total ledger.value = rows
total.value = Number(result.total ?? rows.length)
} catch {
ledger.value = []
total.value = 0
} finally { } finally {
loading.value = false loading.value = false
} }