best-unit 1.2.19 → 1.2.21

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (49) hide show
  1. package/BEST_UNIT_USAGE.md +402 -0
  2. package/dist/best-unit.cjs +13 -13
  3. package/dist/best-unit.js +1352 -1328
  4. package/index.html +13 -0
  5. package/package.json +1 -4
  6. package/src/api/axiosInstance.ts +111 -0
  7. package/src/api/index.ts +136 -0
  8. package/src/api/proxy.ts +11 -0
  9. package/src/components/business/recharge-sdk/components/offline-transfer-form/index.tsx +158 -0
  10. package/src/components/business/recharge-sdk/components/offline-transfer-form/theme.tsx +238 -0
  11. package/src/components/business/recharge-sdk/components/online-recharge-form/index.tsx +199 -0
  12. package/src/components/business/recharge-sdk/components/online-recharge-form/theme.tsx +159 -0
  13. package/src/components/business/recharge-sdk/components/recharge/index.tsx +152 -0
  14. package/src/components/business/recharge-sdk/components/recharge/theme.tsx +68 -0
  15. package/src/components/business/recharge-sdk/index.tsx +37 -0
  16. package/src/components/business/refresh-button/index.tsx +99 -0
  17. package/src/components/business/refresh-button/theme.tsx +58 -0
  18. package/src/components/business/statistical-balance/index.tsx +190 -0
  19. package/src/components/business/statistical-balance/theme.tsx +117 -0
  20. package/src/components/common/button/index.tsx +17 -0
  21. package/src/components/common/button/theme.tsx +56 -0
  22. package/src/components/common/hover-popover/index.tsx +182 -0
  23. package/src/components/common/hover-popover/theme.tsx +39 -0
  24. package/src/components/common/message/index.tsx +321 -0
  25. package/src/components/common/message/theme.tsx +25 -0
  26. package/src/components/common/modal/index.tsx +99 -0
  27. package/src/components/common/modal/theme.tsx +99 -0
  28. package/src/components/common/select/index.tsx +229 -0
  29. package/src/components/common/select/theme.tsx +104 -0
  30. package/src/components/common/upload/index.tsx +140 -0
  31. package/src/components/common/upload/theme.tsx +95 -0
  32. package/src/demo/App.tsx +685 -0
  33. package/src/demo/index.tsx +4 -0
  34. package/src/demo/testBalanceData.tsx +79 -0
  35. package/src/demo/theme-config-example.tsx +1 -0
  36. package/src/local/en.ts +64 -0
  37. package/src/local/index.ts +36 -0
  38. package/src/local/zh.ts +63 -0
  39. package/src/main.ts +26 -0
  40. package/src/types/global.d.ts +146 -0
  41. package/src/types/index.ts +31 -0
  42. package/src/types/preact-custom-element.d.ts +1 -0
  43. package/src/utils/business/index.ts +132 -0
  44. package/src/utils/common/index.ts +8 -0
  45. package/src/vite-env.d.ts +8 -0
  46. package/tsconfig.app.json +33 -0
  47. package/tsconfig.json +15 -0
  48. package/tsconfig.node.json +24 -0
  49. package/vite.config.ts +24 -0
package/index.html ADDED
@@ -0,0 +1,13 @@
1
+ <!doctype html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8" />
5
+ <link rel="icon" type="image/svg+xml" href="/vite.svg" />
6
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
7
+ <title>Best Unit</title>
8
+ </head>
9
+ <body>
10
+ <div id="app"></div>
11
+ <script type="module" src="/src/demo/index.tsx"></script>
12
+ </body>
13
+ </html>
package/package.json CHANGED
@@ -1,14 +1,11 @@
1
1
  {
2
2
  "name": "best-unit",
3
3
  "private": false,
4
- "version": "1.2.19",
4
+ "version": "1.2.21",
5
5
  "type": "module",
6
6
  "main": "dist/best-unit.cjs",
7
7
  "module": "dist/best-unit.js",
8
8
  "types": "dist/types/global.d.ts",
9
- "files": [
10
- "dist"
11
- ],
12
9
  "scripts": {
13
10
  "dev": "vite",
14
11
  "build": "tsc --noEmit && vite build && cp -r src/types dist/types",
@@ -0,0 +1,111 @@
1
+ import axios from "axios";
2
+ import type {
3
+ AxiosInstance,
4
+ AxiosResponse,
5
+ InternalAxiosRequestConfig,
6
+ } from "axios";
7
+ import { message } from "@/components/common/message";
8
+ import { Env, Locale } from "@/types";
9
+
10
+ export interface CreateAxiosOptions {
11
+ baseURL?: string;
12
+ timeout?: number;
13
+ onError?: (msg: string, error: any) => void;
14
+ }
15
+
16
+ export function createAxiosInstance(options: CreateAxiosOptions = {}) {
17
+ // 根据 fund_unit_params 中的 env 参数选择 API URL
18
+ const fundUnitParams = JSON.parse(
19
+ sessionStorage.getItem("fund_unit_params") || "{}"
20
+ );
21
+
22
+ console.log("fundUnitParams", fundUnitParams);
23
+ const { env } = fundUnitParams;
24
+
25
+ let apiUrl: string;
26
+ switch (env) {
27
+ case Env.DEV:
28
+ case Env.DEVELOPMENT:
29
+ apiUrl = "/api";
30
+ break;
31
+ case Env.TEST:
32
+ apiUrl = "https://fund.bestfulfill.tech/api/sdk";
33
+ break;
34
+ case Env.PROD:
35
+ case Env.PRODUCTION:
36
+ default:
37
+ apiUrl = "https://fund.bestfulfill.com/api/sdk";
38
+ break;
39
+ }
40
+
41
+ const { baseURL = apiUrl, timeout = 10000, onError } = options;
42
+
43
+ const instance: AxiosInstance = axios.create({ baseURL, timeout });
44
+
45
+ // 请求拦截:加 token、国际化
46
+ instance.interceptors.request.use((config: InternalAxiosRequestConfig) => {
47
+ const { token, locale } = fundUnitParams;
48
+ config.headers = {
49
+ ...config.headers,
50
+ Authorization: token,
51
+ "x-locale": locale === Locale.ZH ? "zh-CN" : "en-US",
52
+ } as any;
53
+
54
+ return config;
55
+ });
56
+
57
+ // 响应拦截:code=0判定成功,其他走 onError
58
+ instance.interceptors.response.use(
59
+ (response: AxiosResponse) => {
60
+ if (response.data && response.data.code === 0) {
61
+ return response.data;
62
+ }
63
+ const errorMsg =
64
+ response.data?.msg || response.data?.message || "未知错误";
65
+
66
+ // 显示错误消息
67
+ message.error(errorMsg);
68
+
69
+ if (onError) {
70
+ onError(errorMsg, response);
71
+ }
72
+ return Promise.reject(response.data || { message: "未知错误" });
73
+ },
74
+ (error) => {
75
+ const errorMsg =
76
+ error.response?.data?.msg ||
77
+ error.response?.data?.message ||
78
+ error.message ||
79
+ "网络请求失败";
80
+
81
+ // 显示错误消息
82
+ message.error(errorMsg);
83
+
84
+ if (onError) {
85
+ onError(errorMsg, error);
86
+ }
87
+ return Promise.reject(error);
88
+ }
89
+ );
90
+
91
+ return instance;
92
+ }
93
+
94
+ // 缓存 axios 实例
95
+ let httpInstance: AxiosInstance | null = null;
96
+
97
+ // 获取 axios 实例的函数
98
+ export function http(): AxiosInstance {
99
+ if (!httpInstance) {
100
+ httpInstance = createAxiosInstance();
101
+ }
102
+ return httpInstance;
103
+ }
104
+
105
+ // 重置 axios 实例(当 fund_unit_params 更新时调用)
106
+ export function resetHttpInstance(): void {
107
+ httpInstance = null;
108
+ }
109
+
110
+ // 默认导出获取实例的函数
111
+ export default http;
@@ -0,0 +1,136 @@
1
+ import { http } from "./axiosInstance";
2
+ import type { AxiosProgressEvent } from "axios";
3
+ // 获取余额
4
+ export function getBalance() {
5
+ const fundUnitParams = JSON.parse(
6
+ sessionStorage.getItem("fund_unit_params") || "{}"
7
+ );
8
+ return http()
9
+ .get("/balance", {
10
+ params: {
11
+ merchant_id: fundUnitParams.merchantId,
12
+ biz_type: fundUnitParams.bizType,
13
+ fund_balance_id: fundUnitParams.fundBalanceId,
14
+ },
15
+ })
16
+ .then((res) => {
17
+ const data = res.data;
18
+ const balanceData = {
19
+ fundBalanceId: data.fund_balance_id,
20
+ merchantId: data.merchant_id,
21
+ bizType: data.biz_type,
22
+ currency: data.currency,
23
+ totalAmount: data.total_amount,
24
+ frozenAmount: data.frozen_amount,
25
+ creditLimit: data.credit_config?.credit_limit,
26
+ creditUsed: data.credit_used,
27
+ isCredit: data.credit_config ? true : false,
28
+ availableAmount: data.available_amount,
29
+ pendingAmount: data.pending_amount,
30
+ status: data.status,
31
+ createdAt: data.created_at,
32
+ };
33
+ sessionStorage.setItem("balanceData", JSON.stringify(balanceData));
34
+ return balanceData;
35
+ });
36
+ }
37
+
38
+ // 获取所有字典
39
+ export const getAllDicts = async () => {
40
+ return http()
41
+ .get("/all-dicts", {})
42
+ .then((res) => {
43
+ sessionStorage.setItem("all_dicts", JSON.stringify(res.data));
44
+ return res.data || {};
45
+ });
46
+ };
47
+
48
+ // 上传文件
49
+ export const uploadFile = async (
50
+ file: any,
51
+ onProgress?: (percent: number) => void
52
+ ) => {
53
+ return http()
54
+ .post("/oss/upload", file, {
55
+ headers: {
56
+ "Content-Type": "multipart/form-data",
57
+ },
58
+ onUploadProgress: (progressEvent: AxiosProgressEvent) => {
59
+ if (progressEvent.total) {
60
+ const percent = Math.round(
61
+ (progressEvent.loaded * 100) / progressEvent.total
62
+ );
63
+ onProgress && onProgress(percent);
64
+ }
65
+ },
66
+ })
67
+ .then((res) => {
68
+ return res.data?.url || "";
69
+ });
70
+ };
71
+
72
+ // 创建离线充值
73
+ export const createOfflineRecharge = async (data: any) => {
74
+ const fundUnitParams = JSON.parse(
75
+ sessionStorage.getItem("fund_unit_params") || "{}"
76
+ );
77
+
78
+ const params = {
79
+ merchant_id: Number(fundUnitParams.merchantId),
80
+ biz_type: fundUnitParams.bizType,
81
+ fund_balance_id: fundUnitParams.fundBalanceId,
82
+ source_operator: fundUnitParams.userId
83
+ ? String(fundUnitParams.userId)
84
+ : undefined,
85
+ transfer_no: data.transferNo,
86
+ transfer_channel: data.transferChannel,
87
+ voucher_urls: data.voucherUrls,
88
+ };
89
+ return http().post("/offline/recharge/create", params, {});
90
+ };
91
+
92
+ // 创建在线充值
93
+ export const createOnlineRecharge = async (data: any) => {
94
+ const fundUnitParams = JSON.parse(
95
+ sessionStorage.getItem("fund_unit_params") || "{}"
96
+ );
97
+
98
+ const params = {
99
+ merchant_id: Number(fundUnitParams.merchantId),
100
+ biz_type: fundUnitParams.bizType,
101
+ fund_balance_id: fundUnitParams.fundBalanceId,
102
+ source_operator: fundUnitParams.userId
103
+ ? String(fundUnitParams.userId)
104
+ : undefined,
105
+ amount: data.amount,
106
+ currency: data.currency,
107
+ recharge_channel: data.rechargeChannel,
108
+ return_url: window.location.href,
109
+ };
110
+ return http()
111
+ .post("/online/recharge/create", params, {})
112
+ .then((res) => {
113
+ return res.data.redirect_url;
114
+ });
115
+ };
116
+
117
+ interface CalcPaymentAmountParams {
118
+ channel: string; // 支付平台,如 "stripe"
119
+ amount: string; // 充值金额,如 "10"
120
+ currency: string; // 币种,如 "USD"
121
+ }
122
+
123
+ // 计算支付金额
124
+ export const calcPaymentAmount = async (data: CalcPaymentAmountParams) => {
125
+ return http()
126
+ .get("/calc-payment-amount", {
127
+ params: data,
128
+ })
129
+ .then((res) => {
130
+ const data = res.data;
131
+ return data.payment_amount;
132
+ });
133
+ };
134
+
135
+ // 示例用法:
136
+ // getBalance({ merchant_id: '1128', biz_type: 'ad', token: 'xxx' }).then(res => console.log(res));
@@ -0,0 +1,11 @@
1
+ // Vite 配置用的代理对象
2
+ const viteProxy = {
3
+ "/api": {
4
+ target: "https://fund.bestfulfill.tech/api/sdk",
5
+ changeOrigin: true,
6
+ rewrite: (path: string) => path.replace(/^\/api/, ""),
7
+ secure: false,
8
+ },
9
+ };
10
+
11
+ export { viteProxy };
@@ -0,0 +1,158 @@
1
+ import type { FunctionalComponent } from "preact";
2
+ import { Upload } from "@/components/common/upload";
3
+ import { createOfflineRecharge } from "@/api";
4
+ import { message } from "@/components/common/message";
5
+ import { t } from "@/local";
6
+ import { Select } from "@/components/common/select";
7
+ import { getOfflineTransferFormTheme } from "./theme";
8
+
9
+ interface OfflineTransferFormProps {
10
+ formState: {
11
+ platform: string;
12
+ transactionId: string;
13
+ files: string[]; // 绑定url数组
14
+ platformError?: string;
15
+ transactionIdError?: string;
16
+ filesError?: string;
17
+ loading?: boolean;
18
+ };
19
+ setFormState: (fn: (state: any) => any) => void;
20
+ onClose: () => void;
21
+ loading: boolean;
22
+ }
23
+
24
+ export const OfflineTransferForm: FunctionalComponent<
25
+ OfflineTransferFormProps
26
+ > = ({ formState, setFormState, onClose, loading }) => {
27
+ const allDicts = JSON.parse(sessionStorage.getItem("all_dicts") || "{}");
28
+ console.log(allDicts, "allDicts");
29
+ const channelDict = allDicts?.channel || [];
30
+ const theme = getOfflineTransferFormTheme();
31
+
32
+ const handleSubmit = async (e: any) => {
33
+ e.preventDefault();
34
+ let valid = true;
35
+ setFormState((state: any) => ({
36
+ ...state,
37
+ platformError: "",
38
+ transactionIdError: "",
39
+ filesError: "",
40
+ }));
41
+ if (!formState.platform) {
42
+ setFormState((state: any) => ({
43
+ ...state,
44
+ platformError: t("请选择支付平台"),
45
+ }));
46
+ valid = false;
47
+ }
48
+ if (!formState.transactionId.trim()) {
49
+ setFormState((state: any) => ({
50
+ ...state,
51
+ transactionIdError: t("请输入转账交易ID"),
52
+ }));
53
+ valid = false;
54
+ }
55
+ if (!formState.files || formState.files.length === 0) {
56
+ setFormState((state: any) => ({
57
+ ...state,
58
+ filesError: t("请上传转账凭证"),
59
+ }));
60
+ valid = false;
61
+ }
62
+ if (!valid) return;
63
+ await createOfflineRecharge({
64
+ transferChannel: formState.platform,
65
+ transferNo: formState.transactionId,
66
+ voucherUrls: formState.files,
67
+ });
68
+ onClose();
69
+ message.success(t("离线充值创建成功"));
70
+ };
71
+
72
+ return (
73
+ <form onSubmit={handleSubmit}>
74
+ <div style={{ marginBottom: 18 }}>
75
+ <div style={theme.label}>
76
+ <span style={{ color: "#F53F3F" }}>*</span> {t("第三方支付平台")}
77
+ </div>
78
+ <Select
79
+ value={formState.platform}
80
+ onChange={(value) => {
81
+ setFormState((state: any) => ({
82
+ ...state,
83
+ platform: value,
84
+ platformError: value ? "" : state.platformError,
85
+ }));
86
+ }}
87
+ options={[
88
+ ...channelDict?.map((item: any) => ({
89
+ value: item.value,
90
+ label: item.label,
91
+ })),
92
+ ]}
93
+ placeholder={t("请选择支付平台")}
94
+ />
95
+ {formState.platformError && (
96
+ <div style={theme.error}>{formState.platformError}</div>
97
+ )}
98
+ </div>
99
+ <div style={{ marginBottom: 18 }}>
100
+ <div style={theme.label}>
101
+ <span style={{ color: "#F53F3F" }}>*</span> {t("交易ID")}
102
+ </div>
103
+ <input
104
+ type="text"
105
+ placeholder={t("请输入转账交易ID")}
106
+ value={formState.transactionId}
107
+ maxLength={200}
108
+ onInput={(e) => {
109
+ let value = (e.target as HTMLInputElement).value;
110
+ if (value.length > 200) value = value.slice(0, 200);
111
+ setFormState((state: any) => ({
112
+ ...state,
113
+ transactionId: value,
114
+ transactionIdError: value ? "" : state.transactionIdError,
115
+ }));
116
+ }}
117
+ style={{
118
+ ...theme.input,
119
+ ...(formState.transactionIdError ? theme.inputError : {}),
120
+ }}
121
+ />
122
+ {formState.transactionIdError && (
123
+ <div style={theme.error}>{formState.transactionIdError}</div>
124
+ )}
125
+ </div>
126
+ <div style={{ marginBottom: 24 }}>
127
+ <div style={theme.label}>
128
+ <span style={{ color: "#F53F3F" }}>*</span> {t("上传文件")}
129
+ </div>
130
+ <Upload
131
+ value={formState.files}
132
+ onChange={(urls) =>
133
+ setFormState((state: any) => ({
134
+ ...state,
135
+ files: urls,
136
+ filesError: "",
137
+ }))
138
+ }
139
+ maxCount={10}
140
+ accept={".jpg,.jpeg,.png,.pdf"}
141
+ multiple={true}
142
+ />
143
+ {formState.filesError && (
144
+ <div style={theme.error}>{formState.filesError}</div>
145
+ )}
146
+ </div>
147
+ {/* 按钮区 */}
148
+ <div style={{ display: "flex", justifyContent: "flex-end", gap: 12 }}>
149
+ <button type="button" onClick={onClose} style={theme.buttonCancel}>
150
+ {t("取消")}
151
+ </button>
152
+ <button type="submit" disabled={loading} style={theme.buttonSubmit}>
153
+ {t("确定")}
154
+ </button>
155
+ </div>
156
+ </form>
157
+ );
158
+ };
@@ -0,0 +1,238 @@
1
+ import { Size, Theme, type ThemeConfig } from "@/types";
2
+ import { getInitParams } from "@/utils/business";
3
+
4
+ // 动态生成主题配置的函数
5
+ function createOfflineTransferFormThemes() {
6
+ const size = getInitParams<Size>("size"); // 每次调用时重新获取最新值
7
+
8
+ return {
9
+ white: {
10
+ label: {
11
+ marginBottom: size === Size.SMALL ? 6 : 8,
12
+ fontSize: size === Size.SMALL ? 12 : 14,
13
+ color: "#222",
14
+ textAlign: "left",
15
+ display: "block",
16
+ },
17
+ input: {
18
+ width: "100%",
19
+ padding: size === Size.SMALL ? "8px 10px" : "10px 12px",
20
+ borderRadius: 6,
21
+ boxSizing: "border-box",
22
+ border: "1px solid #E5E6EB",
23
+ background: "#fff",
24
+ color: "#222",
25
+ fontSize: size === Size.SMALL ? 12 : 15,
26
+ outline: "none",
27
+ marginBottom: 0,
28
+ },
29
+ inputError: {
30
+ border: "1px solid #ff4d4f",
31
+ },
32
+ select: {
33
+ width: "100%",
34
+ padding: size === Size.SMALL ? "8px 10px" : "10px 12px",
35
+ borderRadius: 6,
36
+ border: "1px solid #E5E6EB",
37
+ background: "#fff",
38
+ color: "#222",
39
+ fontSize: size === Size.SMALL ? 12 : 15,
40
+ outline: "none",
41
+ },
42
+ selectError: {
43
+ border: "1px solid #ff4d4f",
44
+ },
45
+ upload: {
46
+ border: "1px dashed #E5E6EB",
47
+ borderRadius: 8,
48
+ background: "#FCFCFD",
49
+ padding: size === Size.SMALL ? 12 : 24,
50
+ textAlign: "center",
51
+ cursor: "pointer",
52
+ minHeight: size === Size.SMALL ? 100 : 120,
53
+ display: "flex",
54
+ flexDirection: "column",
55
+ alignItems: "center",
56
+ justifyContent: "center",
57
+ color: "#999",
58
+ fontSize: size === Size.SMALL ? 12 : 15,
59
+ },
60
+ uploadError: {
61
+ border: "1px dashed #ff4d4f",
62
+ },
63
+ fileItem: {
64
+ display: "flex",
65
+ alignItems: "center",
66
+ background: "#F7F8FA",
67
+ borderRadius: 8,
68
+ padding: size === Size.SMALL ? "8px 10px" : "12px 16px",
69
+ marginBottom: size === Size.SMALL ? 6 : 8,
70
+ fontSize: size === Size.SMALL ? 12 : 15,
71
+ color: "#222",
72
+ justifyContent: "space-between",
73
+ },
74
+ buttonCancel: {
75
+ background: "#fff",
76
+ color: "#222",
77
+ border: "1px solid #E5E6EB",
78
+ borderRadius: 6,
79
+ padding: size === Size.SMALL ? "6px 18px" : "8px 24px",
80
+ cursor: "pointer",
81
+ },
82
+ buttonSubmit: {
83
+ background: "#1890ff",
84
+ color: "#fff",
85
+ border: "none",
86
+ borderRadius: 6,
87
+ padding: size === Size.SMALL ? "6px 18px" : "8px 24px",
88
+ cursor: "pointer",
89
+ fontWeight: 600,
90
+ },
91
+ removeBtn: {
92
+ background: "#FF4D4F",
93
+ color: "#fff",
94
+ border: "none",
95
+ borderRadius: 6,
96
+ padding: size === Size.SMALL ? "6px 18px" : "4px 14px",
97
+ fontSize: size === Size.SMALL ? 12 : 15,
98
+ marginLeft: size === Size.SMALL ? 8 : 16,
99
+ cursor: "pointer",
100
+ },
101
+ error: {
102
+ color: "#ff4d4f",
103
+ fontSize: size === Size.SMALL ? 12 : 13,
104
+ marginTop: size === Size.SMALL ? 2 : 4,
105
+ textAlign: "left",
106
+ },
107
+ },
108
+ dark: {
109
+ label: {
110
+ marginBottom: size === Size.SMALL ? 4 : 8,
111
+ fontSize: size === Size.SMALL ? 12 : 14,
112
+ color: "#fff",
113
+ textAlign: "left",
114
+ display: "block",
115
+ },
116
+ input: {
117
+ width: "100%",
118
+ padding: size === Size.SMALL ? "8px 10px" : "10px 12px",
119
+ borderRadius: 6,
120
+ boxSizing: "border-box",
121
+ border: "1px solid #374151",
122
+ background: "#23262F",
123
+ color: "#fff",
124
+ fontSize: size === Size.SMALL ? 12 : 15,
125
+ outline: "none",
126
+ marginBottom: 0,
127
+ },
128
+ inputError: {
129
+ border: "1px solid #ff4d4f",
130
+ },
131
+ select: {
132
+ width: "100%",
133
+ padding: size === Size.SMALL ? "8px 10px" : "10px 12px",
134
+ borderRadius: 6,
135
+ border: "1px solid #374151",
136
+ background: "#23262F",
137
+ color: "#fff",
138
+ fontSize: size === Size.SMALL ? 12 : 15,
139
+ outline: "none",
140
+ },
141
+ selectError: {
142
+ border: "1px solid #ff4d4f",
143
+ },
144
+ upload: {
145
+ border: "1px dashed #374151",
146
+ borderRadius: 8,
147
+ background: "#181A20",
148
+ padding: size === Size.SMALL ? 12 : 24,
149
+ textAlign: "center",
150
+ cursor: "pointer",
151
+ minHeight: size === Size.SMALL ? 100 : 120,
152
+ display: "flex",
153
+ flexDirection: "column",
154
+ alignItems: "center",
155
+ justifyContent: "center",
156
+ color: "#999",
157
+ fontSize: size === Size.SMALL ? 12 : 14,
158
+ },
159
+ uploadError: {
160
+ border: "1px dashed #ff4d4f",
161
+ },
162
+ fileItem: {
163
+ display: "flex",
164
+ alignItems: "center",
165
+ background: "#23262F",
166
+ borderRadius: 8,
167
+ padding: size === Size.SMALL ? "8px 10px" : "12px 16px",
168
+ marginBottom: size === Size.SMALL ? 6 : 8,
169
+ fontSize: size === Size.SMALL ? 12 : 15,
170
+ color: "#fff",
171
+ justifyContent: "space-between",
172
+ },
173
+ buttonCancel: {
174
+ background: "#23262F",
175
+ color: "#fff",
176
+ border: "none",
177
+ borderRadius: 6,
178
+ padding: size === Size.SMALL ? "6px 18px" : "8px 24px",
179
+ fontSize: size === Size.SMALL ? 12 : 15,
180
+ cursor: "pointer",
181
+ },
182
+ buttonSubmit: {
183
+ background: "#00E8C6",
184
+ color: "#fff",
185
+ border: "none",
186
+ borderRadius: 6,
187
+ padding: size === Size.SMALL ? "6px 18px" : "8px 24px",
188
+ fontSize: size === Size.SMALL ? 12 : 14,
189
+ cursor: "pointer",
190
+ fontWeight: 600,
191
+ },
192
+ removeBtn: {
193
+ background: "#FF4D4F",
194
+ color: "#fff",
195
+ border: "none",
196
+ borderRadius: 6,
197
+ padding: size === Size.SMALL ? "6px 18px" : "4px 14px",
198
+ fontSize: size === Size.SMALL ? 12 : 15,
199
+ marginLeft: size === Size.SMALL ? 8 : 16,
200
+ cursor: "pointer",
201
+ },
202
+ error: {
203
+ color: "#ff4d4f",
204
+ fontSize: size === Size.SMALL ? 12 : 13,
205
+ marginTop: size === Size.SMALL ? 2 : 4,
206
+ textAlign: "left",
207
+ },
208
+ },
209
+ };
210
+ }
211
+
212
+ export function getOfflineTransferFormTheme() {
213
+ const theme = getInitParams<Theme>("theme");
214
+ const themeConfig = getInitParams<ThemeConfig>("themeConfig");
215
+ const whiteTheme = theme === Theme.WHITE;
216
+
217
+ // 每次调用时重新生成主题配置
218
+ const offlineTransferFormThemes = createOfflineTransferFormThemes();
219
+ const baseTheme = whiteTheme
220
+ ? offlineTransferFormThemes.white
221
+ : offlineTransferFormThemes.dark;
222
+ console.log(themeConfig, "themeConfig");
223
+ // 如果初始化时传入了按钮配置,则覆盖默认配置
224
+ if (themeConfig) {
225
+ const config = whiteTheme ? themeConfig.white : themeConfig.dark;
226
+ if (config?.color) {
227
+ return {
228
+ ...baseTheme,
229
+ buttonSubmit: {
230
+ ...baseTheme.buttonSubmit,
231
+ background: config.color,
232
+ },
233
+ };
234
+ }
235
+ }
236
+
237
+ return baseTheme;
238
+ }