drdata commited on
Commit
48d4bfd
·
verified ·
1 Parent(s): f3a9fca

Add 2 files

Browse files
Files changed (2) hide show
  1. README.md +7 -5
  2. index.html +406 -19
README.md CHANGED
@@ -1,10 +1,12 @@
1
  ---
2
- title: Numbers To Chinese Cheque
3
- emoji: 💻
4
- colorFrom: pink
5
- colorTo: green
6
  sdk: static
7
  pinned: false
 
 
8
  ---
9
 
10
- Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
 
1
  ---
2
+ title: numbers-to-chinese-cheque
3
+ emoji: 🐳
4
+ colorFrom: red
5
+ colorTo: pink
6
  sdk: static
7
  pinned: false
8
+ tags:
9
+ - deepsite
10
  ---
11
 
12
+ Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
index.html CHANGED
@@ -1,19 +1,406 @@
1
- <!doctype html>
2
- <html>
3
- <head>
4
- <meta charset="utf-8" />
5
- <meta name="viewport" content="width=device-width" />
6
- <title>My static Space</title>
7
- <link rel="stylesheet" href="style.css" />
8
- </head>
9
- <body>
10
- <div class="card">
11
- <h1>Welcome to your static Space!</h1>
12
- <p>You can modify this app directly by editing <i>index.html</i> in the Files and versions tab.</p>
13
- <p>
14
- Also don't forget to check the
15
- <a href="https://huggingface.co/docs/hub/spaces" target="_blank">Spaces documentation</a>.
16
- </p>
17
- </div>
18
- </body>
19
- </html>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!DOCTYPE html>
2
+ <html lang="zh-CN">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>数字转中文</title>
7
+ <script src="https://cdn.tailwindcss.com"></script>
8
+ <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
9
+ <style>
10
+ @keyframes spin {
11
+ 0% { transform: rotate(0deg); }
12
+ 100% { transform: rotate(360deg); }
13
+ }
14
+ .spinner {
15
+ animation: spin 1s linear infinite;
16
+ }
17
+ .toast {
18
+ transition: all 0.3s ease;
19
+ }
20
+ .toast-enter {
21
+ opacity: 0;
22
+ transform: translateY(20px);
23
+ }
24
+ .toast-enter-active {
25
+ opacity: 1;
26
+ transform: translateY(0);
27
+ }
28
+ .toast-exit {
29
+ opacity: 1;
30
+ transform: translateY(0);
31
+ }
32
+ .toast-exit-active {
33
+ opacity: 0;
34
+ transform: translateY(-20px);
35
+ }
36
+ .btn-scale:hover {
37
+ transform: scale(1.05);
38
+ }
39
+ .btn-scale:active {
40
+ transform: scale(0.98);
41
+ }
42
+ .container-shadow {
43
+ box-shadow: 0 10px 25px -5px rgba(0, 0, 0, 0.1);
44
+ }
45
+ .container-shadow:hover {
46
+ box-shadow: 0 20px 25px -5px rgba(0, 0, 0, 0.1), 0 10px 10px -5px rgba(0, 0, 0, 0.04);
47
+ }
48
+ @media (max-width: 640px) {
49
+ .input-group {
50
+ flex-direction: column;
51
+ }
52
+ .convert-btn {
53
+ width: 100%;
54
+ margin-top: 12px;
55
+ margin-left: 0 !important;
56
+ }
57
+ }
58
+ </style>
59
+ </head>
60
+ <body class="bg-gray-50 min-h-screen flex items-center justify-center p-4 dark:bg-gray-800 transition-colors duration-200">
61
+ <div class="bg-white rounded-xl p-6 w-full max-w-2xl container-shadow transition-all duration-300 dark:bg-gray-700">
62
+ <h1 class="text-3xl font-bold text-center text-gray-800 mb-6 dark:text-white">数字转中文</h1>
63
+
64
+ <div class="mb-6">
65
+ <div class="flex input-group">
66
+ <input
67
+ type="text"
68
+ id="numberInput"
69
+ placeholder="请输入阿拉伯数字"
70
+ class="flex-1 px-4 py-3 border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent dark:bg-gray-600 dark:border-gray-500 dark:text-white dark:placeholder-gray-300"
71
+ aria-label="输入阿拉伯数字"
72
+ >
73
+ <button
74
+ id="convertBtn"
75
+ class="convert-btn ml-3 px-6 py-3 bg-blue-500 text-white font-medium rounded-lg hover:bg-blue-600 transition-colors duration-200 btn-scale disabled:bg-gray-400 disabled:cursor-not-allowed dark:bg-blue-600 dark:hover:bg-blue-700"
76
+ disabled
77
+ >
78
+ 转换
79
+ </button>
80
+ </div>
81
+ <p id="errorText" class="text-red-500 text-sm mt-2 h-5"></p>
82
+ </div>
83
+
84
+ <div id="resultContainer" class="hidden bg-gray-50 rounded-lg p-5 mb-6 dark:bg-gray-600">
85
+ <div class="flex items-center justify-between">
86
+ <p id="chineseResult" class="text-2xl font-semibold text-blue-500 dark:text-blue-300"></p>
87
+ <button
88
+ id="copyBtn"
89
+ class="p-2 rounded-full hover:bg-gray-200 transition-colors duration-200 dark:hover:bg-gray-500"
90
+ aria-label="复制结果"
91
+ >
92
+ <i class="far fa-copy text-gray-600 dark:text-gray-300"></i>
93
+ </button>
94
+ </div>
95
+ </div>
96
+
97
+ <div class="text-sm text-gray-500 dark:text-gray-300">
98
+ <p class="mb-2"><i class="fas fa-info-circle mr-2"></i>支持整数、小数和负数转换</p>
99
+ <p><i class="fas fa-lightbulb mr-2"></i>示例: 1234 → "一千二百三十四", -56.78 → "负五十六元七角八分"</p>
100
+ </div>
101
+ </div>
102
+
103
+ <div id="toast" class="fixed bottom-6 left-1/2 transform -translate-x-1/2 hidden">
104
+ <div class="bg-gray-800 text-white px-4 py-2 rounded-lg flex items-center">
105
+ <i class="fas fa-check-circle mr-2 text-green-400"></i>
106
+ <span>已复制!</span>
107
+ </div>
108
+ </div>
109
+
110
+ <script>
111
+ document.addEventListener('DOMContentLoaded', function() {
112
+ // DOM elements
113
+ const numberInput = document.getElementById('numberInput');
114
+ const convertBtn = document.getElementById('convertBtn');
115
+ const resultContainer = document.getElementById('resultContainer');
116
+ const chineseResult = document.getElementById('chineseResult');
117
+ const copyBtn = document.getElementById('copyBtn');
118
+ const errorText = document.getElementById('errorText');
119
+ const toast = document.getElementById('toast');
120
+
121
+ // Character maps
122
+ const DIGITS = ['零', '一', '二', '三', '四', '五', '六', '七', '八', '九'];
123
+ const UNITS = ['', '十', '百', '千'];
124
+ const GROUP_UNITS = ['', '万', '亿', '兆'];
125
+ const DECIMAL_UNITS = ['元', '角', '分'];
126
+
127
+ // Validation regex
128
+ const NUMBER_REGEX = /^-?\d{1,3}(,\d{3})*(\.\d{0,2})?$/;
129
+ const MAX_NUMBER = 10 ** 16 - 1;
130
+ const MIN_NUMBER = -(10 ** 16 - 1);
131
+
132
+ // Event listeners
133
+ numberInput.addEventListener('input', handleInputChange);
134
+ convertBtn.addEventListener('click', convertNumber);
135
+ copyBtn.addEventListener('click', copyResult);
136
+
137
+ // Input change handler
138
+ function handleInputChange(e) {
139
+ const value = e.target.value;
140
+
141
+ // Format with commas as user types
142
+ if (value && value !== '-') {
143
+ const cursorPos = e.target.selectionStart;
144
+ const cleaned = value.replace(/[^\d.-]/g, '');
145
+
146
+ // Format with commas
147
+ let parts = cleaned.split('.');
148
+ let integerPart = parts[0].replace(/\D/g, '');
149
+ let formatted = '';
150
+
151
+ if (integerPart) {
152
+ // Handle negative numbers
153
+ const isNegative = integerPart.startsWith('-');
154
+ if (isNegative) integerPart = integerPart.substring(1);
155
+
156
+ // Add commas every 3 digits
157
+ formatted = integerPart.replace(/\B(?=(\d{3})+(?!\d))/g, ',');
158
+
159
+ if (isNegative) formatted = '-' + formatted;
160
+ }
161
+
162
+ // Add decimal part if exists
163
+ if (parts.length > 1) {
164
+ formatted += '.' + parts[1].replace(/\D/g, '').substring(0, 2);
165
+ }
166
+
167
+ // Update input value
168
+ e.target.value = formatted;
169
+
170
+ // Restore cursor position
171
+ const diff = formatted.length - value.length;
172
+ e.target.setSelectionRange(cursorPos + diff, cursorPos + diff);
173
+ }
174
+
175
+ // Validate input
176
+ validateInput();
177
+ }
178
+
179
+ // Validate input
180
+ function validateInput() {
181
+ const value = numberInput.value.trim();
182
+
183
+ if (!value) {
184
+ errorText.textContent = '';
185
+ convertBtn.disabled = true;
186
+ return;
187
+ }
188
+
189
+ // Check if valid number format
190
+ if (!NUMBER_REGEX.test(value)) {
191
+ errorText.textContent = '请输入有效数字';
192
+ convertBtn.disabled = true;
193
+ numberInput.classList.add('border-red-500');
194
+ numberInput.classList.remove('border-gray-300');
195
+ return;
196
+ }
197
+
198
+ // Convert to number and check range
199
+ const num = parseFloat(value.replace(/,/g, ''));
200
+
201
+ if (num > MAX_NUMBER || num < MIN_NUMBER) {
202
+ errorText.textContent = `数字必须在 ${MIN_NUMBER} 到 ${MAX_NUMBER} 之间`;
203
+ convertBtn.disabled = true;
204
+ numberInput.classList.add('border-red-500');
205
+ numberInput.classList.remove('border-gray-300');
206
+ return;
207
+ }
208
+
209
+ // Valid input
210
+ errorText.textContent = '';
211
+ convertBtn.disabled = false;
212
+ numberInput.classList.remove('border-red-500');
213
+ numberInput.classList.add('border-gray-300');
214
+ }
215
+
216
+ // Convert number to Chinese
217
+ function convertNumber() {
218
+ const value = numberInput.value.trim();
219
+ if (!value) return;
220
+
221
+ // Show loading state
222
+ convertBtn.innerHTML = '<i class="fas fa-circle-notch spinner mr-2"></i> 转换中...';
223
+ convertBtn.disabled = true;
224
+
225
+ // Simulate processing delay (in a real app, this would be immediate)
226
+ setTimeout(() => {
227
+ try {
228
+ const num = parseFloat(value.replace(/,/g, ''));
229
+ const result = numberToChinese(num);
230
+
231
+ // Display result
232
+ chineseResult.textContent = result;
233
+ resultContainer.classList.remove('hidden');
234
+
235
+ // Save to localStorage
236
+ localStorage.setItem('lastConversion', JSON.stringify({
237
+ number: value,
238
+ chinese: result
239
+ }));
240
+ } catch (error) {
241
+ errorText.textContent = '转换出错,请重试';
242
+ console.error('Conversion error:', error);
243
+ } finally {
244
+ // Reset button
245
+ convertBtn.innerHTML = '转换';
246
+ convertBtn.disabled = false;
247
+ }
248
+ }, 300);
249
+ }
250
+
251
+ // Core conversion function
252
+ function numberToChinese(num) {
253
+ if (isNaN(num)) throw new Error('Invalid number');
254
+
255
+ // Handle zero
256
+ if (num === 0) return '零元整';
257
+
258
+ // Handle negative numbers
259
+ let isNegative = false;
260
+ if (num < 0) {
261
+ isNegative = true;
262
+ num = Math.abs(num);
263
+ }
264
+
265
+ // Split into integer and decimal parts
266
+ const str = num.toString();
267
+ let [integerPart, decimalPart = ''] = str.split('.');
268
+
269
+ // Process integer part
270
+ let chineseInteger = '';
271
+ if (integerPart !== '0') {
272
+ // Split into 4-digit groups (right to left)
273
+ const groups = [];
274
+ let temp = integerPart;
275
+
276
+ while (temp.length > 0) {
277
+ const start = Math.max(0, temp.length - 4);
278
+ groups.unshift(temp.substring(start));
279
+ temp = temp.substring(0, start);
280
+ }
281
+
282
+ // Convert each group
283
+ chineseInteger = groups.map((group, index) => {
284
+ const groupUnit = GROUP_UNITS[groups.length - 1 - index];
285
+ return convertGroup(group) + groupUnit;
286
+ }).join('');
287
+
288
+ // Remove consecutive zeros
289
+ chineseInteger = chineseInteger.replace(/零+/g, '零');
290
+
291
+ // Remove trailing zero
292
+ if (chineseInteger.endsWith('零')) {
293
+ chineseInteger = chineseInteger.substring(0, chineseInteger.length - 1);
294
+ }
295
+
296
+ // Add '元' for financial format
297
+ chineseInteger += '元';
298
+ }
299
+
300
+ // Process decimal part
301
+ let chineseDecimal = '';
302
+ if (decimalPart) {
303
+ // Round to 2 digits
304
+ decimalPart = decimalPart.substring(0, 2).padEnd(2, '0');
305
+
306
+ // Convert each digit
307
+ const jiao = decimalPart[0] !== '0' ? DIGITS[parseInt(decimalPart[0])] + DECIMAL_UNITS[1] : '';
308
+ const fen = decimalPart[1] !== '0' ? DIGITS[parseInt(decimalPart[1])] + DECIMAL_UNITS[2] : '';
309
+
310
+ chineseDecimal = jiao + fen;
311
+
312
+ // Special case: .05 → "五分" not "零元五分"
313
+ if (!chineseInteger && chineseDecimal) {
314
+ chineseInteger = '';
315
+ }
316
+ } else if (integerPart !== '0') {
317
+ // No decimal part but has integer
318
+ chineseDecimal = '整';
319
+ }
320
+
321
+ // Combine parts
322
+ let result = chineseInteger + chineseDecimal;
323
+
324
+ // Handle special cases
325
+ if (result.startsWith('一十')) {
326
+ result = result.replace('一十', '十');
327
+ }
328
+
329
+ // Add negative prefix if needed
330
+ if (isNegative) {
331
+ result = '负' + result;
332
+ }
333
+
334
+ return result;
335
+ }
336
+
337
+ // Convert a 4-digit group
338
+ function convertGroup(group) {
339
+ group = group.padStart(4, '0');
340
+ let result = '';
341
+
342
+ for (let i = 0; i < 4; i++) {
343
+ const digit = parseInt(group[i]);
344
+ const unit = UNITS[4 - 1 - i];
345
+
346
+ if (digit === 0) {
347
+ // Only add zero if not leading or consecutive
348
+ if (result && !result.endsWith('零')) {
349
+ result += DIGITS[0];
350
+ }
351
+ } else {
352
+ result += DIGITS[digit] + unit;
353
+ }
354
+ }
355
+
356
+ // Remove trailing zero
357
+ if (result.endsWith('零')) {
358
+ result = result.substring(0, result.length - 1);
359
+ }
360
+
361
+ return result;
362
+ }
363
+
364
+ // Copy result to clipboard
365
+ function copyResult() {
366
+ const text = chineseResult.textContent;
367
+ if (!text) return;
368
+
369
+ navigator.clipboard.writeText(text).then(() => {
370
+ showToast();
371
+ }).catch(err => {
372
+ console.error('Failed to copy:', err);
373
+ });
374
+ }
375
+
376
+ // Show toast notification
377
+ function showToast() {
378
+ toast.classList.remove('hidden');
379
+
380
+ setTimeout(() => {
381
+ toast.classList.add('hidden');
382
+ }, 2000);
383
+ }
384
+
385
+ // Load last conversion from localStorage
386
+ function loadLastConversion() {
387
+ const lastConversion = localStorage.getItem('lastConversion');
388
+ if (lastConversion) {
389
+ try {
390
+ const { number, chinese } = JSON.parse(lastConversion);
391
+ numberInput.value = number;
392
+ chineseResult.textContent = chinese;
393
+ resultContainer.classList.remove('hidden');
394
+ validateInput();
395
+ } catch (e) {
396
+ console.error('Failed to load last conversion:', e);
397
+ }
398
+ }
399
+ }
400
+
401
+ // Initialize
402
+ loadLastConversion();
403
+ });
404
+ </script>
405
+ <p style="border-radius: 8px; text-align: center; font-size: 12px; color: #fff; margin-top: 16px;position: fixed; left: 8px; bottom: 8px; z-index: 10; background: rgba(0, 0, 0, 0.8); padding: 4px 8px;">Made with <img src="https://enzostvs-deepsite.hf.space/logo.svg" alt="DeepSite Logo" style="width: 16px; height: 16px; vertical-align: middle;display:inline-block;margin-right:3px;filter:brightness(0) invert(1);"><a href="https://enzostvs-deepsite.hf.space" style="color: #fff;text-decoration: underline;" target="_blank" >DeepSite</a> - 🧬 <a href="https://enzostvs-deepsite.hf.space?remix=drdata/numbers-to-chinese-cheque" style="color: #fff;text-decoration: underline;" target="_blank" >Remix</a></p></body>
406
+ </html>