mirror of
https://github.com/CorentinTh/it-tools.git
synced 2025-05-04 21:37:11 -04:00
feat(new tool): RMB Uppercase Converter
Fix #891. Taken from 6297c10cb0
This commit is contained in:
parent
cb5b462e11
commit
6530d37b1a
5 changed files with 162 additions and 0 deletions
|
@ -6,6 +6,7 @@ import { tool as asciiTextDrawer } from './ascii-text-drawer';
|
|||
|
||||
import { tool as textToUnicode } from './text-to-unicode';
|
||||
import { tool as safelinkDecoder } from './safelink-decoder';
|
||||
import { tool as rmbNumbers } from './rmb-numbers';
|
||||
import { tool as pdfSignatureChecker } from './pdf-signature-checker';
|
||||
import { tool as numeronymGenerator } from './numeronym-generator';
|
||||
import { tool as macAddressGenerator } from './mac-address-generator';
|
||||
|
@ -107,6 +108,7 @@ export const toolsByCategory: ToolCategory[] = [
|
|||
listConverter,
|
||||
tomlToJson,
|
||||
tomlToYaml,
|
||||
rmbNumbers,
|
||||
],
|
||||
},
|
||||
{
|
||||
|
|
12
src/tools/rmb-numbers/index.ts
Normal file
12
src/tools/rmb-numbers/index.ts
Normal file
|
@ -0,0 +1,12 @@
|
|||
import { CurrencyYen } from '@vicons/tabler';
|
||||
import { defineTool } from '../tool';
|
||||
|
||||
export const tool = defineTool({
|
||||
name: 'RMB Uppercase Converter',
|
||||
path: '/rmb-numbers',
|
||||
description: 'RMB/Renminbi Capitalization Conversion Tool',
|
||||
keywords: ['rmb', 'renminbi', 'cny', 'number', 'uppercase', '人民币', '大写', '转换'],
|
||||
component: () => import('./rmb-numbers.vue'),
|
||||
icon: CurrencyYen,
|
||||
createdAt: new Date('2024-04-29'),
|
||||
});
|
37
src/tools/rmb-numbers/rmb-numbers.service.test.ts
Normal file
37
src/tools/rmb-numbers/rmb-numbers.service.test.ts
Normal file
|
@ -0,0 +1,37 @@
|
|||
import { describe, expect, it } from 'vitest';
|
||||
import { rmb } from './rmb-numbers.service';
|
||||
|
||||
describe('rmb-case-converter', () => {
|
||||
it('rmb to convert rmb numbers to uppercase', async () => {
|
||||
expect(rmb(123)).to.deep.equal([
|
||||
{
|
||||
type: 'number',
|
||||
value: '壹',
|
||||
},
|
||||
{
|
||||
type: 'unit',
|
||||
value: '佰',
|
||||
},
|
||||
{
|
||||
type: 'number',
|
||||
value: '贰',
|
||||
},
|
||||
{
|
||||
type: 'unit',
|
||||
value: '拾',
|
||||
},
|
||||
{
|
||||
type: 'number',
|
||||
value: '叁',
|
||||
},
|
||||
{
|
||||
type: 'unit',
|
||||
value: '元',
|
||||
},
|
||||
{
|
||||
type: 'cut',
|
||||
value: '整',
|
||||
},
|
||||
]);
|
||||
});
|
||||
});
|
67
src/tools/rmb-numbers/rmb-numbers.service.ts
Normal file
67
src/tools/rmb-numbers/rmb-numbers.service.ts
Normal file
|
@ -0,0 +1,67 @@
|
|||
export { rmb };
|
||||
|
||||
const numbers = ['零', '壹', '贰', '叁', '肆', '伍', '陆', '柒', '捌', '玖'];
|
||||
const leftUnits = ['元', '拾', '佰', '仟', '万', '拾', '佰', '仟', '亿', '拾', '佰', '仟', '万', '拾', '佰', '仟', '万'];
|
||||
const rightUnits = ['角', '分'];
|
||||
|
||||
function rmb(value: number) {
|
||||
if (Object.prototype.toString.call(value) === '[object Number]' && value >= 0.01) {
|
||||
const fragment: any = [];
|
||||
const [leftValues, rightValues] = String(value).split('.').map(part => part.split('').map(i => Number(i)));
|
||||
|
||||
const leftValueLength = leftValues.length; // 整数部分位数
|
||||
const unit1 = leftValueLength - 1; // 元位
|
||||
const unit5 = leftValueLength - 5; // 万位
|
||||
const unit9 = leftValueLength - 9; // 亿位
|
||||
const unit13 = leftValueLength - 13; // 万亿位
|
||||
const unit17 = leftValueLength - 17; // 万万亿位
|
||||
const hasLeftValue = leftValueLength > 1 || leftValues[0] > 0; // 整数部分不为0
|
||||
const hasRightValue = rightValues && (rightValues[0] > 0 || rightValues[1] > 0); // 小数部分不为0
|
||||
const has678Value = leftValues[unit5 - 1] > 0 || leftValues[unit5 - 2] > 0 || leftValues[unit5 - 3] > 0; // 拾万、佰万或仟万位不为0
|
||||
const overflowIndex = leftValueLength - leftUnits.length; // 溢出位索引
|
||||
|
||||
let leftUnitIndex = 0;
|
||||
for (let i = leftValueLength - 1; i >= 0; i--) {
|
||||
if (leftValues[i] === 0 && (i === unit5 || i === unit9 || i === unit13 || i === unit17) && leftValues[i + 1] > 0) {
|
||||
// 当前位为0,且当前位为万、亿、万亿、万万亿,且低一位不为0
|
||||
fragment.unshift({ type: 'number', value: numbers[leftValues[i]] });
|
||||
}
|
||||
|
||||
if ((leftValues[i] > 0) || (i === unit1 && hasLeftValue) || (i === unit5 && has678Value) || i === unit9 || i === unit13 || i === unit17) {
|
||||
// 元、万、亿、万亿、万万亿或当前位不为0
|
||||
fragment.unshift({ type: 'unit', value: leftUnits[leftUnitIndex] });
|
||||
}
|
||||
|
||||
if (leftValues[i] > 0 || (leftValues[i + 1] > 0 && i !== unit5 && i !== unit9 && i !== unit13 && i !== unit17) || i <= overflowIndex) {
|
||||
// 当前位不为0,或低一位不为0且当前位非万、亿、万亿、万万亿,或当前为溢出位
|
||||
fragment.unshift({ type: 'number', value: numbers[leftValues[i]] });
|
||||
}
|
||||
|
||||
leftUnitIndex++;
|
||||
}
|
||||
|
||||
if (hasRightValue) {
|
||||
// 角
|
||||
if (rightValues[0] > 0 || hasLeftValue) { // 角位不为0,或整数位不为0
|
||||
fragment.push({ type: 'number', value: numbers[rightValues[0]] });
|
||||
}
|
||||
if (rightValues[0] > 0) { // 角位不为0
|
||||
fragment.push({ type: 'unit', value: rightUnits[0] });
|
||||
}
|
||||
// 分
|
||||
if (rightValues[1] > 0) {
|
||||
fragment.push({ type: 'number', value: numbers[rightValues[1]] });
|
||||
fragment.push({ type: 'unit', value: rightUnits[1] });
|
||||
}
|
||||
}
|
||||
else { // 没有小数位
|
||||
fragment.push({ type: 'cut', value: '整' });
|
||||
}
|
||||
return fragment;
|
||||
}
|
||||
return [
|
||||
{ type: 'number', value: '零' },
|
||||
{ type: 'unit', value: '元' },
|
||||
{ type: 'cut', value: '整' },
|
||||
];
|
||||
};
|
44
src/tools/rmb-numbers/rmb-numbers.vue
Normal file
44
src/tools/rmb-numbers/rmb-numbers.vue
Normal file
|
@ -0,0 +1,44 @@
|
|||
<script setup lang="ts">
|
||||
import { useThemeVars } from 'naive-ui';
|
||||
import { rmb } from './rmb-numbers.service';
|
||||
|
||||
const themeVars = useThemeVars();
|
||||
const inputRmb = ref(23);
|
||||
const outputRmb = computed(() => rmb(inputRmb.value)); ;
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div flex flex-col gap-2>
|
||||
<c-card title="Lower Case Amount">
|
||||
<n-input-number v-model:value="inputRmb" max="100000000000" min="0" placeholder="Enter the amount in lowercase (example: 1314.52)" :show-button="false" w-full />
|
||||
</c-card>
|
||||
|
||||
<div my-16px divider />
|
||||
|
||||
<c-card title="Amount in Capital Letters" flex flex-col>
|
||||
<div m-0 m-x-auto>
|
||||
<span
|
||||
v-for="(item, index) in outputRmb"
|
||||
:key="index"
|
||||
:class="item.type"
|
||||
>
|
||||
{{ item.value }}
|
||||
</span>
|
||||
</div>
|
||||
</c-card>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style lang="less" scoped>
|
||||
.unit {
|
||||
font-size: 1.4em;
|
||||
color: v-bind('themeVars.successColor');
|
||||
}
|
||||
.number {
|
||||
font-size: 2.4em;
|
||||
}
|
||||
.cut {
|
||||
font-size: 1.4em;
|
||||
color: v-bind('themeVars.errorColor');
|
||||
}
|
||||
</style>
|
Loading…
Add table
Add a link
Reference in a new issue