best-unit 1.0.0 → 1.0.3

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 (48) hide show
  1. package/README.md +1 -0
  2. package/dist/best-unit.cjs +60 -0
  3. package/dist/best-unit.js +3988 -0
  4. package/dist/types/global.d.ts +64 -0
  5. package/dist/types/index.ts +17 -0
  6. package/dist/types/preact-custom-element.d.ts +1 -0
  7. package/index.html +2 -2
  8. package/package.json +14 -7
  9. package/src/api/axiosInstance.ts +94 -0
  10. package/src/api/index.ts +118 -15
  11. package/src/api/proxy.ts +11 -0
  12. package/src/components/business/recharge-sdk/components/Button.tsx +42 -0
  13. package/src/components/business/recharge-sdk/components/OfflineTransferForm.tsx +365 -0
  14. package/src/components/business/recharge-sdk/components/OnlineRechargeForm.tsx +389 -0
  15. package/src/components/business/recharge-sdk/components/Recharge.tsx +288 -0
  16. package/src/components/business/recharge-sdk/index.tsx +39 -0
  17. package/src/components/business/statistical-balance/index.tsx +206 -0
  18. package/src/components/common/HoverPopover.tsx +215 -0
  19. package/src/components/common/Message.tsx +324 -0
  20. package/src/components/common/Select.tsx +278 -0
  21. package/src/components/common/Upload.tsx +207 -0
  22. package/src/demo/App.tsx +429 -0
  23. package/src/demo/index.tsx +4 -0
  24. package/src/local/en.ts +61 -0
  25. package/src/local/index.ts +36 -0
  26. package/src/local/zh.ts +60 -0
  27. package/src/main.ts +10 -0
  28. package/src/types/global.d.ts +64 -0
  29. package/src/types/index.ts +17 -0
  30. package/src/types/preact-custom-element.d.ts +1 -0
  31. package/src/utils/business/index.ts +48 -0
  32. package/src/utils/common/index.ts +8 -0
  33. package/src/vite-env.d.ts +1 -0
  34. package/tsconfig.app.json +31 -0
  35. package/tsconfig.json +15 -0
  36. package/tsconfig.node.json +24 -0
  37. package/vite.config.ts +18 -0
  38. package/example/index.html +0 -24
  39. package/public/vite.svg +0 -1
  40. package/src/App.jsx +0 -6
  41. package/src/api/define-api.ts +0 -49
  42. package/src/javascript.svg +0 -1
  43. package/src/main.jsx +0 -4
  44. package/src/sdk/index.ts +0 -33
  45. package/src/style.css +0 -96
  46. package/src/views/AccountModal.jsx +0 -125
  47. package/src/views/Home.jsx +0 -53
  48. package/vite.config.js +0 -31
@@ -0,0 +1,207 @@
1
+ import type { FunctionalComponent } from "preact";
2
+ import { useRef, useState } from "preact/hooks";
3
+ import { uploadFile } from "../../api";
4
+ import { t } from "../../local";
5
+ import { Theme } from "../../types";
6
+
7
+ interface UploadProps {
8
+ value?: string[];
9
+ onChange?: (urls: string[]) => void;
10
+ maxCount?: number;
11
+ accept?: string;
12
+ multiple?: boolean;
13
+ disabled?: boolean;
14
+ }
15
+
16
+ const uploadTheme = {
17
+ white: {
18
+ container: {
19
+ border: "1px dashed #E5E6EB",
20
+ borderRadius: 8,
21
+ background: "#FCFCFD",
22
+ padding: 24,
23
+ textAlign: "center",
24
+ cursor: "pointer",
25
+ minHeight: 120,
26
+ display: "flex",
27
+ flexDirection: "column",
28
+ alignItems: "center",
29
+ justifyContent: "center",
30
+ color: "#999",
31
+ fontSize: 15,
32
+ },
33
+ fileItem: {
34
+ display: "flex",
35
+ alignItems: "center",
36
+ background: "#F7F8FA",
37
+ borderRadius: 8,
38
+ padding: "12px 16px",
39
+ marginBottom: 8,
40
+ fontSize: 15,
41
+ color: "#222",
42
+ justifyContent: "space-between",
43
+ },
44
+ removeBtn: {
45
+ background: "#FF4D4F",
46
+ color: "#fff",
47
+ border: "none",
48
+ borderRadius: 6,
49
+ padding: "4px 14px",
50
+ fontSize: 15,
51
+ marginLeft: 16,
52
+ cursor: "pointer",
53
+ },
54
+ },
55
+ dark: {
56
+ container: {
57
+ border: "1.5px dashed #444C5C",
58
+ borderRadius: 8,
59
+ background: "#181A20",
60
+ padding: 24,
61
+ textAlign: "center",
62
+ cursor: "pointer",
63
+ minHeight: 120,
64
+ display: "flex",
65
+ flexDirection: "column",
66
+ alignItems: "center",
67
+ justifyContent: "center",
68
+ color: "#999",
69
+ fontSize: 15,
70
+ },
71
+ fileItem: {
72
+ display: "flex",
73
+ alignItems: "center",
74
+ background: "#23262F",
75
+ borderRadius: 8,
76
+ padding: "12px 16px",
77
+ marginBottom: 8,
78
+ fontSize: 15,
79
+ color: "#fff",
80
+ justifyContent: "space-between",
81
+ },
82
+ removeBtn: {
83
+ background: "#FF4D4F",
84
+ color: "#fff",
85
+ border: "none",
86
+ borderRadius: 6,
87
+ padding: "4px 14px",
88
+ fontSize: 15,
89
+ marginLeft: 16,
90
+ cursor: "pointer",
91
+ },
92
+ },
93
+ };
94
+
95
+ export const Upload: FunctionalComponent<UploadProps> = ({
96
+ value = [],
97
+ onChange,
98
+ maxCount = 10,
99
+ accept = ".jpg,.jpeg,.png,.pdf",
100
+ multiple = true,
101
+ disabled = false,
102
+ }) => {
103
+ const fileInputRef = useRef<HTMLInputElement>(null);
104
+ const [uploading, setUploading] = useState(false);
105
+ const [progress, setProgress] = useState(0);
106
+ const fundUnitParams = JSON.parse(
107
+ sessionStorage.getItem("fund_unit_params") || "{}"
108
+ );
109
+ const whiteTheme = fundUnitParams.theme === Theme.WHITE;
110
+ const themeKey = whiteTheme ? "white" : "dark";
111
+ const theme = uploadTheme[themeKey];
112
+
113
+ const handleFileChange = async (e: any) => {
114
+ const files: File[] = Array.from(e.target.files as FileList).slice(
115
+ 0,
116
+ maxCount
117
+ );
118
+ if (!files.length) return;
119
+ setUploading(true);
120
+ const urls: string[] = [];
121
+ for (let i = 0; i < files.length; i++) {
122
+ setProgress(0);
123
+ const formData = new FormData();
124
+ formData.append("file", files[i]);
125
+ try {
126
+ const url = await uploadFile(formData, (percent) =>
127
+ setProgress(percent)
128
+ );
129
+ if (url) urls.push(url);
130
+ } catch (err) {
131
+ // 可扩展错误处理
132
+ }
133
+ }
134
+ setUploading(false);
135
+ setProgress(0);
136
+ onChange?.([...value, ...urls]);
137
+ if (fileInputRef.current) fileInputRef.current.value = "";
138
+ };
139
+
140
+ const handleRemove = (idx: number) => {
141
+ const newArr = value.filter((_, i) => i !== idx);
142
+ onChange?.(newArr);
143
+ };
144
+
145
+ return (
146
+ <div>
147
+ <div
148
+ style={{
149
+ ...theme.container,
150
+ cursor: disabled ? "not-allowed" : theme.container.cursor,
151
+ opacity: disabled ? 0.6 : 1,
152
+ }}
153
+ onClick={() => !disabled && fileInputRef.current?.click()}
154
+ >
155
+ <div style={{ fontSize: 48, marginBottom: 12 }}>📁</div>
156
+ <div style={{ color: "#222", fontSize: 15, marginBottom: 4 }}>
157
+ {t("点击或拖拽文件到此处上传")}
158
+ </div>
159
+ <div style={{ color: "#999", fontSize: 13 }}>
160
+ {t("支持 JPG、PNG、PDF 格式,单个文件不超过 20MB,最多上传")}{" "}
161
+ {maxCount} {t("个文件")}
162
+ </div>
163
+ <input
164
+ ref={fileInputRef}
165
+ type="file"
166
+ multiple={multiple}
167
+ accept={accept}
168
+ style={{ display: "none" }}
169
+ onChange={handleFileChange}
170
+ disabled={disabled}
171
+ />
172
+ {uploading && (
173
+ <div style={{ marginTop: 12, color: "#1677ff" }}>
174
+ {t("正在上传...")} {progress}%
175
+ </div>
176
+ )}
177
+ </div>
178
+ {value && value.length > 0 && (
179
+ <div style={{ marginTop: 12 }}>
180
+ {value.map((url, idx) => (
181
+ <div key={url} style={theme.fileItem}>
182
+ <div style={{ display: "flex", alignItems: "center", flex: 1 }}>
183
+ <span style={{ fontWeight: 500, wordBreak: "break-all" }}>
184
+ {url.split("/").pop()}
185
+ </span>
186
+ <span style={{ color: "#8C8F93", fontSize: 13, marginLeft: 8 }}>
187
+ [{t("已上传")}]
188
+ </span>
189
+ </div>
190
+ <button
191
+ type="button"
192
+ onClick={(e) => {
193
+ e.stopPropagation();
194
+ handleRemove(idx);
195
+ }}
196
+ style={theme.removeBtn}
197
+ disabled={disabled}
198
+ >
199
+ {t("移除")}
200
+ </button>
201
+ </div>
202
+ ))}
203
+ </div>
204
+ )}
205
+ </div>
206
+ );
207
+ };
@@ -0,0 +1,429 @@
1
+ import { useState } from "preact/hooks";
2
+ import { npmTest, printCurrentTime } from "../main";
3
+ import { BestUnit } from "../components/business/recharge-sdk";
4
+ import { initFundUnit } from "../main";
5
+ import StatisticalBalance from "../components/business/statistical-balance";
6
+ import { t } from "../local";
7
+ import { Env, Locale, Theme } from "../types";
8
+
9
+ export default function DemoApp() {
10
+ const [currentLocale, setCurrentLocale] = useState<Locale>(Locale.ZH);
11
+ const [currentTheme, setCurrentTheme] = useState<Theme>(Theme.WHITE);
12
+ const [currentEnv, setCurrentEnv] = useState<Env>(Env.DEV);
13
+
14
+ const initApp = ({
15
+ locale,
16
+ theme,
17
+ env,
18
+ }: {
19
+ locale?: Locale;
20
+ theme?: Theme;
21
+ env?: Env;
22
+ }) => {
23
+ // 测试代码:每次刷新页面时生成不同的 token
24
+ const generateTestToken = () => {
25
+ const timestamp = Date.now();
26
+ const randomId = Math.floor(Math.random() * 1000);
27
+ return `eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE3NTM0MTM1MjksIm1lcmNoYW50X2lkIjoxMTI4LCJ0aW1lc3RhbXAiOjE3NTMxNTQzMjl9.${timestamp}_${randomId}_TEST_TOKEN`;
28
+ };
29
+
30
+ const testToken = generateTestToken();
31
+ console.log("=== 测试 Token 生成 ===");
32
+ console.log("当前时间戳:", Date.now());
33
+ console.log("生成的测试 Token:", testToken);
34
+ console.log("========================");
35
+
36
+ initFundUnit({
37
+ token:
38
+ "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJtZXJjaGFudF9pZCI6MTAwMiwidGltZXN0YW1wIjoxNzUzNDMwNjkyLCJleHAiOjE3NTM0MzQyOTJ9.OPYKUxLQ3C36rKiAmCnUwxTkvM9eKgtsnoxrB9Ntrag",
39
+ fund_balance_id: "FB1FNZ5Q55M7QP2C",
40
+ user_id: "19b8a77c-d3fc-45da-9520-4a07463123df",
41
+ locale: locale as Locale,
42
+ theme: theme ?? Theme.WHITE,
43
+ env: env ?? currentEnv,
44
+ });
45
+ };
46
+
47
+ // 初始化应用
48
+ initApp({ locale: currentLocale, theme: currentTheme, env: currentEnv });
49
+
50
+ const handleLocaleChange = (locale: Locale) => {
51
+ setCurrentLocale(locale);
52
+ // 重新初始化以更新语言设置
53
+ initApp({ locale, theme: currentTheme, env: currentEnv });
54
+ };
55
+
56
+ const handleThemeChange = (theme: Theme) => {
57
+ setCurrentTheme(theme);
58
+ initApp({ locale: currentLocale, theme, env: currentEnv });
59
+ };
60
+
61
+ const handleEnvChange = (env: Env) => {
62
+ setCurrentEnv(env);
63
+ initApp({ locale: currentLocale, theme: currentTheme, env });
64
+ window.location.reload();
65
+ };
66
+
67
+ const isDark = currentTheme === Theme.DARK;
68
+
69
+ return (
70
+ <div
71
+ style={{
72
+ background: isDark ? "#181A20" : "#fff",
73
+ minHeight: "100vh",
74
+ transition: "background 0.3s",
75
+ color: isDark ? "#F5F6FA" : "#111827",
76
+ }}
77
+ >
78
+ <h2
79
+ style={{
80
+ color: isDark ? "#F5F6FA" : undefined,
81
+ background: isDark ? "#23262F" : undefined,
82
+ padding: isDark ? 8 : undefined,
83
+ borderRadius: isDark ? 8 : undefined,
84
+ }}
85
+ >
86
+ 组件库可视化测试 (Token 测试版本)
87
+ </h2>
88
+
89
+ {/* Token 测试信息显示 */}
90
+ <div
91
+ style={{
92
+ marginBottom: 20,
93
+ padding: 16,
94
+ border: "2px solid #1890ff",
95
+ borderRadius: 8,
96
+ backgroundColor: "#e6f7ff",
97
+ }}
98
+ >
99
+ <h3 style={{ marginTop: 0, marginBottom: 12, color: "#1890ff" }}>
100
+ 🧪 Token 测试信息:
101
+ </h3>
102
+ <p style={{ margin: 0, color: "#1890ff" }}>
103
+ 每次刷新页面都会生成新的测试 Token,请查看控制台输出。
104
+ </p>
105
+ <p style={{ margin: "8px 0 0 0", color: "#1890ff", fontSize: "12px" }}>
106
+ 当前时间戳: {Date.now()}
107
+ </p>
108
+ </div>
109
+
110
+ {/* 国际化切换区域 */}
111
+ <div
112
+ style={{
113
+ marginBottom: 20,
114
+ padding: 16,
115
+ border: isDark ? "1px solid #23262F" : "1px solid #e5e7eb",
116
+ borderRadius: 8,
117
+ backgroundColor: isDark ? "#23262F" : "#f9fafb",
118
+ }}
119
+ >
120
+ <h3
121
+ style={{
122
+ marginTop: 0,
123
+ marginBottom: 12,
124
+ color: isDark ? "#F5F6FA" : undefined,
125
+ }}
126
+ >
127
+ 国际化测试:
128
+ </h3>
129
+ <div style={{ display: "flex", gap: 12, alignItems: "center" }}>
130
+ <span>当前语言:</span>
131
+ <button
132
+ onClick={() => handleLocaleChange("zh" as Locale)}
133
+ style={{
134
+ padding: "8px 16px",
135
+ backgroundColor:
136
+ currentLocale === "zh"
137
+ ? "#1890ff"
138
+ : isDark
139
+ ? "#23262F"
140
+ : "#fff",
141
+ color:
142
+ currentLocale === "zh" ? "#fff" : isDark ? "#F5F6FA" : "#333",
143
+ border: "1px solid #1890ff",
144
+ borderRadius: 6,
145
+ cursor: "pointer",
146
+ fontWeight: currentLocale === "zh" ? "bold" : "normal",
147
+ }}
148
+ >
149
+ 中文
150
+ </button>
151
+ <button
152
+ onClick={() => handleLocaleChange("en" as Locale)}
153
+ style={{
154
+ padding: "8px 16px",
155
+ backgroundColor:
156
+ currentLocale === "en"
157
+ ? "#1890ff"
158
+ : isDark
159
+ ? "#23262F"
160
+ : "#fff",
161
+ color:
162
+ currentLocale === "en" ? "#fff" : isDark ? "#F5F6FA" : "#333",
163
+ border: "1px solid #1890ff",
164
+ borderRadius: 6,
165
+ cursor: "pointer",
166
+ fontWeight: currentLocale === "en" ? "bold" : "normal",
167
+ }}
168
+ >
169
+ English
170
+ </button>
171
+ <span
172
+ style={{
173
+ marginLeft: 12,
174
+ fontSize: 14,
175
+ color: isDark ? "#B5B8BE" : "#666",
176
+ }}
177
+ >
178
+ {currentLocale === "zh"
179
+ ? "当前显示中文"
180
+ : "Currently showing English"}
181
+ </span>
182
+ </div>
183
+ </div>
184
+
185
+ <div>
186
+ <h3 style={{ color: isDark ? "#F5F6FA" : undefined }}>
187
+ BestUnit 主题切换:
188
+ </h3>
189
+ <button
190
+ onClick={() => handleThemeChange(Theme.WHITE)}
191
+ style={{
192
+ padding: "8px 16px",
193
+ backgroundColor:
194
+ currentTheme === Theme.WHITE
195
+ ? "#1890ff"
196
+ : isDark
197
+ ? "#23262F"
198
+ : "#fff",
199
+ color:
200
+ currentTheme === Theme.WHITE
201
+ ? "#fff"
202
+ : isDark
203
+ ? "#F5F6FA"
204
+ : "#333",
205
+ border: "1px solid #1890ff",
206
+ borderRadius: 6,
207
+ cursor: "pointer",
208
+ fontWeight: currentTheme === Theme.WHITE ? "bold" : "normal",
209
+ marginRight: 8,
210
+ }}
211
+ >
212
+ 白色主题
213
+ </button>
214
+ <button
215
+ onClick={() => handleThemeChange(Theme.DARK)}
216
+ style={{
217
+ padding: "8px 16px",
218
+ backgroundColor:
219
+ currentTheme === Theme.DARK
220
+ ? "#1890ff"
221
+ : isDark
222
+ ? "#23262F"
223
+ : "#fff",
224
+ color:
225
+ currentTheme === Theme.DARK
226
+ ? "#fff"
227
+ : isDark
228
+ ? "#F5F6FA"
229
+ : "#333",
230
+ border: "1px solid #1890ff",
231
+ borderRadius: 6,
232
+ cursor: "pointer",
233
+ fontWeight: currentTheme === Theme.DARK ? "bold" : "normal",
234
+ }}
235
+ >
236
+ 暗黑主题
237
+ </button>
238
+ </div>
239
+
240
+ <div>
241
+ <h3 style={{ color: isDark ? "#F5F6FA" : undefined }}>
242
+ BestUnit 环境切换:
243
+ </h3>
244
+ <button
245
+ onClick={() => handleEnvChange(Env.DEV)}
246
+ style={{
247
+ padding: "8px 16px",
248
+ backgroundColor:
249
+ currentEnv === "dev" ? "#52c41a" : isDark ? "#23262F" : "#fff",
250
+ color: currentEnv === "dev" ? "#fff" : isDark ? "#F5F6FA" : "#333",
251
+ border: "1px solid #52c41a",
252
+ borderRadius: 6,
253
+ cursor: "pointer",
254
+ fontWeight: currentEnv === "dev" ? "bold" : "normal",
255
+ marginRight: 8,
256
+ }}
257
+ >
258
+ 开发环境 (dev)
259
+ </button>
260
+ <button
261
+ onClick={() => handleEnvChange(Env.TEST)}
262
+ style={{
263
+ padding: "8px 16px",
264
+ backgroundColor:
265
+ currentEnv === "test" ? "#faad14" : isDark ? "#23262F" : "#fff",
266
+ color: currentEnv === "test" ? "#fff" : isDark ? "#F5F6FA" : "#333",
267
+ border: "1px solid #faad14",
268
+ borderRadius: 6,
269
+ cursor: "pointer",
270
+ fontWeight: currentEnv === "test" ? "bold" : "normal",
271
+ marginRight: 8,
272
+ }}
273
+ >
274
+ 测试环境 (test)
275
+ </button>
276
+ <button
277
+ onClick={() => handleEnvChange(Env.PROD)}
278
+ style={{
279
+ padding: "8px 16px",
280
+ backgroundColor:
281
+ currentEnv === "prod" ? "#ff4d4f" : isDark ? "#23262F" : "#fff",
282
+ color: currentEnv === "prod" ? "#fff" : isDark ? "#F5F6FA" : "#333",
283
+ border: "1px solid #ff4d4f",
284
+ borderRadius: 6,
285
+ cursor: "pointer",
286
+ fontWeight: currentEnv === "prod" ? "bold" : "normal",
287
+ }}
288
+ >
289
+ 生产环境 (prod)
290
+ </button>
291
+ <div
292
+ style={{
293
+ marginTop: 8,
294
+ fontSize: 14,
295
+ color: isDark ? "#B5B8BE" : "#666",
296
+ }}
297
+ >
298
+ 当前环境:{" "}
299
+ {currentEnv === "dev"
300
+ ? "开发环境"
301
+ : currentEnv === "test"
302
+ ? "测试环境"
303
+ : "生产环境"}
304
+ </div>
305
+ </div>
306
+
307
+ <div>
308
+ <h3 style={{ color: isDark ? "#F5F6FA" : undefined }}>
309
+ BestUnit 组件演示:
310
+ </h3>
311
+ <BestUnit />
312
+ </div>
313
+
314
+ <div>
315
+ <h3 style={{ color: isDark ? "#F5F6FA" : undefined }}>方法演示:</h3>
316
+ <button
317
+ onClick={npmTest}
318
+ style={{
319
+ marginRight: 10,
320
+ background: isDark ? "#23262F" : undefined,
321
+ color: isDark ? "#F5F6FA" : undefined,
322
+ border: isDark ? "1px solid #444C5C" : undefined,
323
+ }}
324
+ >
325
+ 调用 npmTest()
326
+ </button>
327
+ <button
328
+ onClick={printCurrentTime}
329
+ style={{
330
+ background: isDark ? "#23262F" : undefined,
331
+ color: isDark ? "#F5F6FA" : undefined,
332
+ border: isDark ? "1px solid #444C5C" : undefined,
333
+ }}
334
+ >
335
+ 调用 printCurrentTime()
336
+ </button>
337
+ </div>
338
+ <div style={{ textAlign: "center" }}>
339
+ <h3 style={{ color: isDark ? "#F5F6FA" : undefined }}>
340
+ 余额卡片组件演示:
341
+ </h3>
342
+ <StatisticalBalance />
343
+ </div>
344
+
345
+ {/* 国际化文本测试区域 */}
346
+ <div
347
+ style={{
348
+ marginTop: 20,
349
+ padding: 16,
350
+ border: isDark ? "1px solid #23262F" : "1px solid #e5e7eb",
351
+ borderRadius: 8,
352
+ backgroundColor: isDark ? "#23262F" : "#f9fafb",
353
+ }}
354
+ >
355
+ <h3
356
+ style={{
357
+ marginTop: 0,
358
+ marginBottom: 12,
359
+ color: isDark ? "#F5F6FA" : undefined,
360
+ }}
361
+ >
362
+ 国际化文本测试:
363
+ </h3>
364
+ <div
365
+ style={{
366
+ display: "grid",
367
+ gridTemplateColumns: "repeat(auto-fit, minmax(200px, 1fr))",
368
+ gap: 12,
369
+ }}
370
+ >
371
+ <div
372
+ style={{
373
+ padding: 8,
374
+ backgroundColor: isDark ? "#181A20" : "#fff",
375
+ borderRadius: 4,
376
+ color: isDark ? "#F5F6FA" : undefined,
377
+ }}
378
+ >
379
+ <strong>余额相关:</strong>
380
+ <br />
381
+ {t("余额详情")}
382
+ <br />
383
+ {t("真实金额")}
384
+ <br />
385
+ {t("冻结金额")}
386
+ <br />
387
+ {t("总可用")}
388
+ </div>
389
+ <div
390
+ style={{
391
+ padding: 8,
392
+ backgroundColor: isDark ? "#181A20" : "#fff",
393
+ borderRadius: 4,
394
+ color: isDark ? "#F5F6FA" : undefined,
395
+ }}
396
+ >
397
+ <strong>充值相关:</strong>
398
+ <br />
399
+ {t("充值 / 转账")}
400
+ <br />
401
+ {t("在线充值")}
402
+ <br />
403
+ {t("线下转账")}
404
+ <br />
405
+ {t("去支付")}
406
+ </div>
407
+ <div
408
+ style={{
409
+ padding: 8,
410
+ backgroundColor: isDark ? "#181A20" : "#fff",
411
+ borderRadius: 4,
412
+ color: isDark ? "#F5F6FA" : undefined,
413
+ }}
414
+ >
415
+ <strong>按钮文本:</strong>
416
+ <br />
417
+ {t("充值/转账")}
418
+ <br />
419
+ {t("取消")}
420
+ <br />
421
+ {t("提交中...")}
422
+ <br />
423
+ {t("关闭")}
424
+ </div>
425
+ </div>
426
+ </div>
427
+ </div>
428
+ );
429
+ }
@@ -0,0 +1,4 @@
1
+ import { render } from 'preact';
2
+ import DemoApp from './App.tsx';
3
+
4
+ render(<DemoApp />, document.getElementById('app')!);
@@ -0,0 +1,61 @@
1
+ // 英文语言包
2
+ export const en: Record<string, string> = {
3
+ // 余额相关
4
+ 余额详情: "Balance Details",
5
+ 真实金额: "Real Amount",
6
+ 冻结金额: "Frozen Amount",
7
+ 总可用: "Total Available",
8
+ 暂无数据: "No Data",
9
+ "金额需在1到999999.99之间": "Amount must be between 1 and 999999.99",
10
+
11
+ // 充值相关
12
+ "充值 / 转账": "Recharge / Transfer",
13
+ 在线充值: "Online Recharge",
14
+ 线下转账: "Offline Transfer",
15
+ 充值币种: "Recharge Currency",
16
+ 充值金额: "Recharge Amount",
17
+ 支付平台: "Payment Platform",
18
+ 请选择充值币种: "Please select recharge currency",
19
+ 请输入充值金额: "Please enter recharge amount",
20
+ 请选择支付平台: "Please select payment platform",
21
+ "需要收取手续费,实际支付金额约为:":
22
+ "requires a handling fee, the actual payment amount is approximately: ",
23
+ "提交失败,请重试": "Submit failed, please try again",
24
+ "提交中...": "Submitting...",
25
+ 去支付: "Go to Pay",
26
+ 取消: "Cancel",
27
+ 关闭: "Close",
28
+
29
+ // 离线转账相关
30
+ 第三方支付平台: "Third-party Payment Platform",
31
+ 交易ID: "Transaction ID",
32
+ 请输入转账交易ID: "Please enter transfer transaction ID",
33
+ 上传文件: "Upload Files",
34
+ 请上传转账凭证: "Please upload transfer voucher",
35
+ 离线充值创建成功: "Offline recharge created successfully",
36
+
37
+ // 通用
38
+ "加载中...": "Loading...",
39
+ 错误: "Error",
40
+ 成功: "Success",
41
+ 必填: "Required",
42
+
43
+ // 按钮文本
44
+ "充值/转账": "Recharge/Transfer",
45
+ 切换为暗黑主题: "Switch to Dark Theme",
46
+ 切换为白色主题: "Switch to Light Theme",
47
+
48
+ // 上传组件相关
49
+ 点击或拖拽文件到此处上传: "Click or drag files here to upload",
50
+ "支持 JPG、PNG、PDF 格式,单个文件不超过 20MB,最多上传":
51
+ "Supports JPG, PNG, PDF formats, single file not exceeding 20MB, maximum",
52
+ 个文件: "files can be uploaded",
53
+ "正在上传...": "Uploading...",
54
+ 已上传: "Uploaded",
55
+ 移除: "Remove",
56
+ };
57
+
58
+ // 根据中文key获取英文文本的函数
59
+ export function getEnText(zhKey: string): string {
60
+ return en[zhKey] || zhKey; // 如果找不到英文,返回中文key
61
+ }