diff --git a/frontend/src/views/admin/PaymentChannels.vue b/frontend/src/views/admin/PaymentChannels.vue
index 8d90101..2a246a3 100644
--- a/frontend/src/views/admin/PaymentChannels.vue
+++ b/frontend/src/views/admin/PaymentChannels.vue
@@ -4,9 +4,14 @@
添加通道
-
-
-
+
+
+
+
+
+
+
+
@@ -18,7 +23,7 @@
{{ (row.fee_rate * 100).toFixed(2) }}%
-
+
{{ row.min_amount }} - {{ row.max_amount || '∞' }} 元
@@ -30,7 +35,7 @@
-
+
编辑
@@ -43,7 +48,7 @@
-
+
@@ -51,16 +56,27 @@
-
-
-
-
-
-
+
+
+
+
+ {{ t.label }}
+
+
-
+
@@ -72,9 +88,82 @@
-
-
-
+
+ 通道配置
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -113,18 +202,51 @@ const form = reactive({
sort_order: 0
})
-const typeNames: Record = {
- alipay: '支付宝',
- wechat: '微信支付',
- bank: '银行卡',
- usdt: 'USDT',
- other: '其他'
+const channelConfig = reactive>({})
+
+const channelTypes = [
+ { value: 'alipay', label: '支付宝', icon: '' },
+ { value: 'wechat', label: '微信支付', icon: '' },
+ { value: 'bepusdt', label: 'BepUsdt', icon: '' },
+ { value: 'bank', label: '银行卡', icon: '' },
+ { value: 'other', label: '其他', icon: '' },
+]
+
+const typeNames: Record = {}
+channelTypes.forEach(t => { typeNames[t.value] = t.label })
+
+const availableIcons = [
+ { name: 'alipay', label: '支付宝', svg: '' },
+ { name: 'wechat', label: '微信', svg: '' },
+ { name: 'usdt', label: 'USDT', svg: '' },
+ { name: 'bank', label: '银行卡', svg: '' },
+ { name: 'visa', label: 'VISA', svg: '' },
+ { name: 'mastercard', label: 'MasterCard', svg: '' },
+ { name: 'crypto', label: '加密货币', svg: '' },
+]
+
+const iconSvgMap: Record = {}
+availableIcons.forEach(ic => { iconSvgMap[ic.name] = ic.svg })
+
+function getIconSvg(icon: string) {
+ return iconSvgMap[icon] || iconSvgMap[icon] || ``
}
function getTypeName(type: string) {
return typeNames[type] || type
}
+function onTypeChange(type: string) {
+ const iconMap: Record = {
+ alipay: 'alipay',
+ wechat: 'wechat',
+ bepusdt: 'usdt',
+ bank: 'bank',
+ }
+ form.icon = iconMap[type] || ''
+ Object.keys(channelConfig).forEach(k => delete channelConfig[k])
+}
+
async function fetchChannels() {
try {
const res: any = await adminApi.getPaymentChannels()
@@ -137,34 +259,28 @@ async function fetchChannels() {
function openAdd() {
editing.value = null
Object.assign(form, {
- name: '',
- code: '',
- type: 'alipay',
- icon: '',
- fee_rate: 0,
- min_amount: 0,
- max_amount: 0,
- config: '',
- is_enabled: true,
- sort_order: 0
+ name: '', code: '', type: 'alipay', icon: 'alipay',
+ fee_rate: 0, min_amount: 0, max_amount: 0, config: '',
+ is_enabled: true, sort_order: 0
})
+ Object.keys(channelConfig).forEach(k => delete channelConfig[k])
showAdd.value = true
}
function editChannel(row: any) {
editing.value = row
Object.assign(form, {
- name: row.name,
- code: row.code,
- type: row.type,
- icon: row.icon || '',
- fee_rate: row.fee_rate || 0,
- min_amount: row.min_amount || 0,
- max_amount: row.max_amount || 0,
- config: row.config || '',
- is_enabled: row.is_enabled,
- sort_order: row.sort_order || 0
+ name: row.name, code: row.code, type: row.type, icon: row.icon || '',
+ fee_rate: row.fee_rate || 0, min_amount: row.min_amount || 0, max_amount: row.max_amount || 0,
+ config: row.config || '', is_enabled: row.is_enabled, sort_order: row.sort_order || 0
})
+ Object.keys(channelConfig).forEach(k => delete channelConfig[k])
+ if (row.config) {
+ try {
+ const parsed = JSON.parse(row.config)
+ Object.assign(channelConfig, parsed)
+ } catch {}
+ }
showAdd.value = true
}
@@ -175,10 +291,14 @@ async function saveChannel() {
}
saving.value = true
try {
+ const payload: any = { ...form }
+ if (form.type !== 'other' && Object.keys(channelConfig).length > 0) {
+ payload.config = JSON.stringify(channelConfig)
+ }
if (editing.value) {
- await adminApi.updatePaymentChannel(editing.value.id, form)
+ await adminApi.updatePaymentChannel(editing.value.id, payload)
} else {
- await adminApi.createPaymentChannel(form)
+ await adminApi.createPaymentChannel(payload)
}
ElMessage.success('保存成功')
showAdd.value = false
@@ -217,6 +337,43 @@ onMounted(fetchChannels)
.page-header { display: flex; justify-content: space-between; align-items: center; margin-bottom: 24px; }
.table-card { background: #2d2d44; border: 1px solid rgba(255, 255, 255, 0.06); border-radius: 12px; padding: 20px; }
+.channel-icon {
+ display: inline-flex;
+ align-items: center;
+ justify-content: center;
+ width: 28px;
+ height: 28px;
+}
+
+.icon-selector {
+ display: flex;
+ gap: 8px;
+ flex-wrap: wrap;
+}
+
+.icon-option {
+ width: 40px;
+ height: 40px;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ border: 2px solid rgba(255, 255, 255, 0.08);
+ border-radius: 8px;
+ cursor: pointer;
+ transition: all 0.15s;
+ background: rgba(255, 255, 255, 0.03);
+
+ &:hover {
+ border-color: rgba(78, 110, 242, 0.4);
+ background: rgba(78, 110, 242, 0.08);
+ }
+
+ &.active {
+ border-color: #4e6ef2;
+ background: rgba(78, 110, 242, 0.15);
+ }
+}
+
:deep(.el-table) {
--el-table-bg-color: transparent;
--el-table-tr-bg-color: transparent;
@@ -302,4 +459,9 @@ onMounted(fetchChannels)
color: #fff;
&::placeholder { color: rgba(255, 255, 255, 0.3); }
}
+
+:deep(.el-divider__text) {
+ color: rgba(255, 255, 255, 0.6);
+ background: #2d2d44;
+}
diff --git a/frontend/src/views/admin/Settings.vue b/frontend/src/views/admin/Settings.vue
index 1b57960..9a96ef8 100644
--- a/frontend/src/views/admin/Settings.vue
+++ b/frontend/src/views/admin/Settings.vue
@@ -14,25 +14,6 @@
保存
-
-
-
-
- 余额支付
- 支付宝
- 微信支付
-
-
- 支付宝配置
-
-
- 微信支付配置
-
-
-
- 保存
-
-
@@ -62,9 +43,6 @@ const settings = reactive>({
invite_credit_reward: 0
})
const verifyEnabled = ref('true')
-const enabledPayments = ref(['balance'])
-const alipayConfig = reactive({ app_id: '', private_key: '' })
-const wechatConfig = reactive({ app_id: '', mch_id: '', api_key: '' })
const smtp = reactive({ smtp_host: '', smtp_port: '587', smtp_user: '', smtp_password: '', smtp_from: '' })
async function fetchSettings() {
@@ -72,20 +50,6 @@ async function fetchSettings() {
const data = res.data || {}
Object.keys(settings).forEach(k => { if (data[k] !== undefined) settings[k] = data[k] })
verifyEnabled.value = data.verification_code_enabled || 'true'
-
- if (data.enabled_payments) {
- try {
- enabledPayments.value = JSON.parse(data.enabled_payments)
- } catch { enabledPayments.value = ['balance'] }
- }
-
- if (data.alipay_config) {
- try { Object.assign(alipayConfig, JSON.parse(data.alipay_config)) } catch {}
- }
- if (data.wechat_config) {
- try { Object.assign(wechatConfig, JSON.parse(data.wechat_config)) } catch {}
- }
-
Object.keys(smtp).forEach(k => { if (data[k] !== undefined) (smtp as any)[k] = data[k] })
}
@@ -94,15 +58,6 @@ async function saveSettings() {
ElMessage.success('保存成功')
}
-async function savePayment() {
- await adminApi.updatePayment({
- enabled_payments: JSON.stringify(enabledPayments.value),
- alipay_config: JSON.stringify(alipayConfig),
- wechat_config: JSON.stringify(wechatConfig)
- })
- ElMessage.success('保存成功')
-}
-
async function saveSMTP() {
await adminApi.updateSMTP(smtp)
ElMessage.success('保存成功')