diff --git a/web/src/components/settings/PaymentSetting.js b/web/src/components/settings/PaymentSetting.js
new file mode 100644
index 00000000..91a40a2b
--- /dev/null
+++ b/web/src/components/settings/PaymentSetting.js
@@ -0,0 +1,88 @@
+import React, { useEffect, useState } from 'react';
+import { Card, Spin } from '@douyinfe/semi-ui';
+import SettingsGeneralPayment from '../../pages/Setting/Payment/SettingsGeneralPayment.js';
+import SettingsPaymentGateway from '../../pages/Setting/Payment/SettingsPaymentGateway.js';
+import { API, showError } from '../../helpers';
+import { useTranslation } from 'react-i18next';
+
+const PaymentSetting = () => {
+ const { t } = useTranslation();
+ let [inputs, setInputs] = useState({
+ ServerAddress: '',
+ PayAddress: '',
+ EpayId: '',
+ EpayKey: '',
+ Price: 7.3,
+ MinTopUp: 1,
+ TopupGroupRatio: '',
+ CustomCallbackAddress: '',
+ PayMethods: '',
+ });
+
+ let [loading, setLoading] = useState(false);
+
+ const getOptions = async () => {
+ const res = await API.get('/api/option/');
+ const { success, message, data } = res.data;
+ if (success) {
+ let newInputs = {};
+ data.forEach((item) => {
+ switch (item.key) {
+ case 'TopupGroupRatio':
+ try {
+ newInputs[item.key] = JSON.stringify(JSON.parse(item.value), null, 2);
+ } catch (error) {
+ console.error('解析TopupGroupRatio出错:', error);
+ newInputs[item.key] = item.value;
+ }
+ break;
+ case 'Price':
+ case 'MinTopUp':
+ newInputs[item.key] = parseFloat(item.value);
+ break;
+ default:
+ if (item.key.endsWith('Enabled')) {
+ newInputs[item.key] = item.value === 'true' ? true : false;
+ } else {
+ newInputs[item.key] = item.value;
+ }
+ break;
+ }
+ });
+
+ setInputs(newInputs);
+ } else {
+ showError(t(message));
+ }
+ };
+
+ async function onRefresh() {
+ try {
+ setLoading(true);
+ await getOptions();
+ } catch (error) {
+ showError(t('刷新失败'));
+ } finally {
+ setLoading(false);
+ }
+ }
+
+ useEffect(() => {
+ onRefresh();
+ }, []);
+
+ return (
+ <>
+
+
+
+
+
+
+
+
+ >
+ );
+};
+
+export default PaymentSetting;
\ No newline at end of file
diff --git a/web/src/components/settings/SystemSetting.js b/web/src/components/settings/SystemSetting.js
index 1236ef2e..b5829f31 100644
--- a/web/src/components/settings/SystemSetting.js
+++ b/web/src/components/settings/SystemSetting.js
@@ -17,7 +17,6 @@ import {
removeTrailingSlash,
showError,
showSuccess,
- verifyJSON,
} from '../../helpers';
import axios from 'axios';
@@ -42,17 +41,9 @@ const SystemSetting = () => {
SMTPAccount: '',
SMTPFrom: '',
SMTPToken: '',
- ServerAddress: '',
WorkerUrl: '',
WorkerValidKey: '',
WorkerAllowHttpImageRequestEnabled: '',
- EpayId: '',
- EpayKey: '',
- Price: 7.3,
- MinTopUp: 1,
- TopupGroupRatio: '',
- PayAddress: '',
- CustomCallbackAddress: '',
Footer: '',
WeChatAuthEnabled: '',
WeChatServerAddress: '',
@@ -73,7 +64,6 @@ const SystemSetting = () => {
LinuxDOOAuthEnabled: '',
LinuxDOClientId: '',
LinuxDOClientSecret: '',
- PayMethods: '',
});
const [originInputs, setOriginInputs] = useState({});
@@ -200,11 +190,6 @@ const SystemSetting = () => {
setInputs(values);
};
- const submitServerAddress = async () => {
- let ServerAddress = removeTrailingSlash(inputs.ServerAddress);
- await updateOptions([{ key: 'ServerAddress', value: ServerAddress }]);
- };
-
const submitWorker = async () => {
let WorkerUrl = removeTrailingSlash(inputs.WorkerUrl);
const options = [
@@ -220,56 +205,6 @@ const SystemSetting = () => {
await updateOptions(options);
};
- const submitPayAddress = async () => {
- if (inputs.ServerAddress === '') {
- showError('请先填写服务器地址');
- return;
- }
- if (originInputs['TopupGroupRatio'] !== inputs.TopupGroupRatio) {
- if (!verifyJSON(inputs.TopupGroupRatio)) {
- showError('充值分组倍率不是合法的 JSON 字符串');
- return;
- }
- }
- if (originInputs['PayMethods'] !== inputs.PayMethods) {
- if (!verifyJSON(inputs.PayMethods)) {
- showError('充值方式设置不是合法的 JSON 字符串');
- return;
- }
- }
-
- const options = [
- { key: 'PayAddress', value: removeTrailingSlash(inputs.PayAddress) },
- ];
-
- if (inputs.EpayId !== '') {
- options.push({ key: 'EpayId', value: inputs.EpayId });
- }
- if (inputs.EpayKey !== undefined && inputs.EpayKey !== '') {
- options.push({ key: 'EpayKey', value: inputs.EpayKey });
- }
- if (inputs.Price !== '') {
- options.push({ key: 'Price', value: inputs.Price.toString() });
- }
- if (inputs.MinTopUp !== '') {
- options.push({ key: 'MinTopUp', value: inputs.MinTopUp.toString() });
- }
- if (inputs.CustomCallbackAddress !== '') {
- options.push({
- key: 'CustomCallbackAddress',
- value: inputs.CustomCallbackAddress,
- });
- }
- if (originInputs['TopupGroupRatio'] !== inputs.TopupGroupRatio) {
- options.push({ key: 'TopupGroupRatio', value: inputs.TopupGroupRatio });
- }
- if (originInputs['PayMethods'] !== inputs.PayMethods) {
- options.push({ key: 'PayMethods', value: inputs.PayMethods });
- }
-
- await updateOptions(options);
- };
-
const submitSMTP = async () => {
const options = [];
@@ -551,17 +486,6 @@ const SystemSetting = () => {
marginTop: '10px',
}}
>
-
-
-
-
-
-
@@ -604,80 +528,6 @@ const SystemSetting = () => {
-
-
-
- (当前仅支持易支付接口,默认使用上方服务器地址作为回调地址!)
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
{
+ if (props.options && formApiRef.current) {
+ const currentInputs = { ServerAddress: props.options.ServerAddress || '' };
+ setInputs(currentInputs);
+ formApiRef.current.setValues(currentInputs);
+ }
+ }, [props.options]);
+
+ const handleFormChange = (values) => {
+ setInputs(values);
+ };
+
+ const submitServerAddress = async () => {
+ setLoading(true);
+ try {
+ let ServerAddress = removeTrailingSlash(inputs.ServerAddress);
+ const res = await API.put('/api/option/', {
+ key: 'ServerAddress',
+ value: ServerAddress,
+ });
+ if (res.data.success) {
+ showSuccess(t('更新成功'));
+ props.refresh && props.refresh();
+ } else {
+ showError(res.data.message);
+ }
+ } catch (error) {
+ showError(t('更新失败'));
+ }
+ setLoading(false);
+ };
+
+ return (
+
+
+
+
+
+
+
+ );
+}
\ No newline at end of file
diff --git a/web/src/pages/Setting/Payment/SettingsPaymentGateway.js b/web/src/pages/Setting/Payment/SettingsPaymentGateway.js
new file mode 100644
index 00000000..0bb63b53
--- /dev/null
+++ b/web/src/pages/Setting/Payment/SettingsPaymentGateway.js
@@ -0,0 +1,218 @@
+import React, { useEffect, useState, useRef } from 'react';
+import {
+ Button,
+ Form,
+ Row,
+ Col,
+ Typography,
+ Spin,
+} from '@douyinfe/semi-ui';
+const { Text } = Typography;
+import {
+ API,
+ removeTrailingSlash,
+ showError,
+ showSuccess,
+ verifyJSON,
+} from '../../../helpers';
+import { useTranslation } from 'react-i18next';
+
+export default function SettingsPaymentGateway(props) {
+ const { t } = useTranslation();
+ const [loading, setLoading] = useState(false);
+ const [inputs, setInputs] = useState({
+ PayAddress: '',
+ EpayId: '',
+ EpayKey: '',
+ Price: 7.3,
+ MinTopUp: 1,
+ TopupGroupRatio: '',
+ CustomCallbackAddress: '',
+ PayMethods: '',
+ });
+ const [originInputs, setOriginInputs] = useState({});
+ const formApiRef = useRef(null);
+
+ useEffect(() => {
+ if (props.options && formApiRef.current) {
+ const currentInputs = {
+ PayAddress: props.options.PayAddress || '',
+ EpayId: props.options.EpayId || '',
+ EpayKey: props.options.EpayKey || '',
+ Price: props.options.Price !== undefined ? parseFloat(props.options.Price) : 7.3,
+ MinTopUp: props.options.MinTopUp !== undefined ? parseFloat(props.options.MinTopUp) : 1,
+ TopupGroupRatio: props.options.TopupGroupRatio || '',
+ CustomCallbackAddress: props.options.CustomCallbackAddress || '',
+ PayMethods: props.options.PayMethods || '',
+ };
+ setInputs(currentInputs);
+ setOriginInputs({ ...currentInputs });
+ formApiRef.current.setValues(currentInputs);
+ }
+ }, [props.options]);
+
+ const handleFormChange = (values) => {
+ setInputs(values);
+ };
+
+ const submitPayAddress = async () => {
+ if (props.options.ServerAddress === '') {
+ showError(t('请先填写服务器地址'));
+ return;
+ }
+
+ if (originInputs['TopupGroupRatio'] !== inputs.TopupGroupRatio) {
+ if (!verifyJSON(inputs.TopupGroupRatio)) {
+ showError(t('充值分组倍率不是合法的 JSON 字符串'));
+ return;
+ }
+ }
+
+ if (originInputs['PayMethods'] !== inputs.PayMethods) {
+ if (!verifyJSON(inputs.PayMethods)) {
+ showError(t('充值方式设置不是合法的 JSON 字符串'));
+ return;
+ }
+ }
+
+ setLoading(true);
+ try {
+ const options = [
+ { key: 'PayAddress', value: removeTrailingSlash(inputs.PayAddress) },
+ ];
+
+ if (inputs.EpayId !== '') {
+ options.push({ key: 'EpayId', value: inputs.EpayId });
+ }
+ if (inputs.EpayKey !== undefined && inputs.EpayKey !== '') {
+ options.push({ key: 'EpayKey', value: inputs.EpayKey });
+ }
+ if (inputs.Price !== '') {
+ options.push({ key: 'Price', value: inputs.Price.toString() });
+ }
+ if (inputs.MinTopUp !== '') {
+ options.push({ key: 'MinTopUp', value: inputs.MinTopUp.toString() });
+ }
+ if (inputs.CustomCallbackAddress !== '') {
+ options.push({
+ key: 'CustomCallbackAddress',
+ value: inputs.CustomCallbackAddress,
+ });
+ }
+ if (originInputs['TopupGroupRatio'] !== inputs.TopupGroupRatio) {
+ options.push({ key: 'TopupGroupRatio', value: inputs.TopupGroupRatio });
+ }
+ if (originInputs['PayMethods'] !== inputs.PayMethods) {
+ options.push({ key: 'PayMethods', value: inputs.PayMethods });
+ }
+
+ // 发送请求
+ const requestQueue = options.map(opt =>
+ API.put('/api/option/', {
+ key: opt.key,
+ value: opt.value,
+ })
+ );
+
+ const results = await Promise.all(requestQueue);
+
+ // 检查所有请求是否成功
+ const errorResults = results.filter(res => !res.data.success);
+ if (errorResults.length > 0) {
+ errorResults.forEach(res => {
+ showError(res.data.message);
+ });
+ } else {
+ showSuccess(t('更新成功'));
+ // 更新本地存储的原始值
+ setOriginInputs({ ...inputs });
+ props.refresh && props.refresh();
+ }
+ } catch (error) {
+ showError(t('更新失败'));
+ }
+ setLoading(false);
+ };
+
+ return (
+
+
+
+ {t('(当前仅支持易支付接口,默认使用上方服务器地址作为回调地址!)')}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ );
+}
\ No newline at end of file
diff --git a/web/src/pages/Setting/index.js b/web/src/pages/Setting/index.js
index 09b9acdf..d0ae763b 100644
--- a/web/src/pages/Setting/index.js
+++ b/web/src/pages/Setting/index.js
@@ -11,7 +11,8 @@ import {
MoreHorizontal,
LayoutDashboard,
MessageSquare,
- Palette
+ Palette,
+ CreditCard
} from 'lucide-react';
import SystemSetting from '../../components/settings/SystemSetting.js';
@@ -24,6 +25,7 @@ import DashboardSetting from '../../components/settings/DashboardSetting.js';
import RatioSetting from '../../components/settings/RatioSetting.js';
import ChatsSetting from '../../components/settings/ChatsSetting.js';
import DrawingSetting from '../../components/settings/DrawingSetting.js';
+import PaymentSetting from '../../components/settings/PaymentSetting.js';
const Setting = () => {
const { t } = useTranslation();
@@ -63,6 +65,16 @@ const Setting = () => {
content: ,
itemKey: 'drawing',
});
+ panes.push({
+ tab: (
+
+
+ {t('支付设置')}
+
+ ),
+ content: ,
+ itemKey: 'payment',
+ });
panes.push({
tab: (