Skip to content

Commit

Permalink
Docs: 完善文档
Browse files Browse the repository at this point in the history
Perf: 完善阿拉伯数字转中文数字函数
  • Loading branch information
Maorey committed Feb 19, 2020
1 parent 8f4a901 commit 149713a
Show file tree
Hide file tree
Showing 4 changed files with 140 additions and 107 deletions.
26 changes: 11 additions & 15 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,8 @@ vue + vuex + vue router + TypeScript(支持 JavaScript) 模板
- [目录结构](#目录结构)
- [风格建议](#风格建议)
- [其他建议](#其他建议)
- [优化](#优化)
- [web 页面](#web%20页面)
- [工程](#工程)
- [配置和优化](#配置和优化)
- [优化](优化)
- [部署](<#部署(nginx)>)
- [备忘](#备忘)
- [文档](#文档)
Expand All @@ -33,8 +32,8 @@ vue + vuex + vue router + TypeScript(支持 JavaScript) 模板

## 环境要求

- `Node.js`: 建议 v12.13.1
- `yarn`: 建议 v1.21.1
- `Node.js`: v12 ([fibers](https://github.com/laverdet/node-fibers#supported-platforms) v4.0.2 不支持 Node v13)
- `yarn`: 最新

### 建议开发环境

Expand All @@ -53,7 +52,7 @@ VSCode 插件

- `Vue Devtools`: 最新

> 推荐工具: [`@vue/cli`](https://cli.vuejs.org/zh/guide), 全局安装时可使用 `vue ui` 命令启动图形化界面管理项目
> 推荐工具: [`@vue/cli`](https://cli.vuejs.org/zh/guide)(最新), 全局安装时可使用 `vue ui` 命令启动图形化界面管理项目
> 推荐字体: [FiraCode](https://github.com/tonsky/FiraCode)
Expand All @@ -74,6 +73,8 @@ yarn # 安装依赖
git config core.ignorecase false # 使git对文件名大小写敏感
```

- 安装后需要在 `yarn.lock` (或 `package-lock.json` ) 中, 指定**所有**依赖的 `mini-css-extract-plugin` 的版本为 `package.json` 对应版本然后再次安装(*为了与原插件版本一致, 更新了但没改版本, 导致再次安装的可能是稍旧的版本*, 建议直接下载并替换该依赖)

### 开发环境(开发调试时使用)

```bash
Expand Down Expand Up @@ -561,22 +562,17 @@ yarn vue-cli-service help # [命令] : 比如 yarn vue-cli-service help test:e2e
// ...
```
### 配置 & 优化
### 配置和优化
#### web 页面
可通过 [vue.config.js](vue.config.js) (入口)文件配置工具链; `.env.*` 配置环境变量; 根目录下各配置文件配置相应工具
请参照 [vue.config.js](vue.config.js) 文件中 _chainWebpack_ 的注释进行配置
#### 优化
- 减小图片大小(比如背景图片等)
- 对多个 js chunk 共同依赖的模块进行缓存/单独提取(cacheGroups)
- 视情况对 css 文件进行合并(比如按入口等, 不设置则按 chunk)【webpack 5 支持设置 css chunk 的 minSize/maxSize 啦】
- 相同chunk下的基础样式或各个皮肤样式文件合并(比如css和scss) 或 其他合理的合并策略【webpack 5 支持设置 css chunk 的 minSize/maxSize 啦】
- [现代模式](https://cli.vuejs.org/zh/guide/browser-compatibility.html#现代模式)
#### 工程
- 需要在 `yarn.lock` (或 `package-lock.json` ) 中, 指定**所有** `mini-css-extract-plugin` 的版本为 `package.json` 对应版本
- 相同chunk下的基础样式(非皮肤样式)文件合并(比如css和scss)
## 部署(nginx)
- chunk hash 长度: 修改 [webpack.optimize.SplitChunksPlugin](node_modules/webpack/lib/optimize/SplitChunksPlugin.js)
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "vue-tpl",
"author": "毛瑞 <[email protected]>",
"version": "1.2.2",
"version": "1.2.3",
"private": false,
"license": "MIT",
"keywords": [
Expand Down
135 changes: 75 additions & 60 deletions src/utils/numToCN.ts
Original file line number Diff line number Diff line change
@@ -1,104 +1,119 @@
/** 阿拉伯数字转中文数字(最高支持描述万万亿)
* @param {string|number} number 阿拉伯数字
* @param {number} unit 1: 不需要单位 2: 不需要单位并且保留开头的0
* @param {number} describe 描述 默认:使用描述 1:不使用描述 2:不使用描述且保留开头的0
* @param {number} cases 大小写 默认:中文小写 1:中文小写但是使用大写零 2:中文大写
*
* @returns {string} 中文数字
*/
export default function numToCN(number: string | number, noUnit?: 1 | 2) {
export default function(
number: string | number,
describe?: 0 | 1 | 2,
cases?: 0 | 1 | 2
) {
if (!number && number !== 0) {
return ''
}

let NUM: string // 数字
let UNIT: string // 单位
let ZERO: string
let TRIM_BEFORE: RegExp // 去开头的0和单位
if (cases === 2) {
ZERO = '零'
NUM = '零壹贰叁肆伍陆柒捌玖'
UNIT = '拾佰仟万拾佰仟亿拾佰仟万拾佰仟'
TRIM_BEFORE = /^零*[拾佰仟万亿]*零*/
} else {
ZERO = cases ? '零' : '〇'
NUM = ZERO + '一二三四五六七八九'
UNIT = '十百千万十百千亿十百千万十百千'
TRIM_BEFORE = new RegExp(`^${ZERO}*[十百千万亿]*${ZERO}*`)
cases = 0 // 标识小写
}
const GOLD = '亿' // 最大单位
const SILVER = '万' // 溢出单位 一二万万亿
const POINT = '点'
const NUM = '零一二三四五六七八九'
const UNIT = '十百千万十百千亿十百千万十百千'
const SIGN = { '+': '正', '-': '负' }
const LEN_UNIT = 15 // UNIT.length
const ZERO = '零' // NUM[0]
const UNIT_MAX = '亿' // 最大单位
const TRIPLE = '万' // 溢出单位 一二万万亿
const TRIPLE_POS = 11 // 万的最后位置 十万亿
const TRIM_BEFORE = /^零*[十百千万亿]*/ // 去开头的0和单位
const SILVER_POS = 11 // 万的最后位置 十万亿

return String(number).replace(
/([+-])?(\d+)(\.\d+)?/g,
(match, sign: '+' | '-', integer: string, decimal: string) => {
let result = ''
(char, sign: '+' | '-', integer: string, unit: string) => {
let cn = ''

let index
// 小数部分(保留末尾0)
if (decimal) {
index = decimal.length
if (unit) {
index = unit.length
while (--index) {
result = NUM[decimal[index] as any] + result
cn = NUM[unit[index] as any] + cn
}
result = POINT + result
cn = POINT + cn
}

let char
let unit
let pos
let indexUnit = -1 // [-1, LEN_UNIT)
number = -1 // [-1, LEN_UNIT)
index = integer.length
// 整数部分
while (index--) {
char = NUM[integer[index] as any]
if (!noUnit) {
if (indexUnit < LEN_UNIT) {
if (!describe) {
if (number < LEN_UNIT) {
// 未超过最大可描述数值
unit = UNIT[indexUnit++] || ''
unit = UNIT[number++] || ''
if (ZERO === char) {
char = result[0]
switch (char) {
case (pos = UNIT.indexOf(char)) >= 0 && char:
if ((pos = UNIT.indexOf((char = cn[0]))) >= 0) {
if (number > SILVER_POS && char === GOLD) {
// 万亿
char = unit
} else if (pos < UNIT.indexOf(unit)) {
// 替换上大的单位
if (indexUnit > TRIPLE_POS && char === UNIT_MAX) {
// 万亿
char = unit
} else if ((pos as any) < UNIT.indexOf(unit)) {
char = unit
result = result.substring(1)
} else {
char = ''
}
break

default:
// ZERO POINT falsy ...
char = NUM.indexOf(char) > 0 ? unit + ZERO : unit
char = unit
cn = cn.substring(1)
} else {
char = ''
}
} else {
// POINT falsy ...
char = NUM.indexOf(char) > 0 ? unit + ZERO : unit
}
} else if (unit) {
;(pos = UNIT.indexOf(result[0])) >= 0 &&
;(pos = UNIT.indexOf(cn[0])) >= 0 &&
pos < UNIT.indexOf(unit) &&
(result = result.substring(1))
(cn = cn.substring(1))
char += unit
}
} else if (indexUnit === LEN_UNIT) {
indexUnit++ // 使只执行一次
result = TRIPLE + result
} else if (number === LEN_UNIT) {
number++ // 使只执行一次
cn = SILVER + cn
}
}

result = char + result
cn = char + cn
}

char = result[0] // 兼职首字
if (!char || char === POINT) {
// 补零 0/0.1
result = ZERO + result
} else if (char === NUM[1] && result[1] === UNIT[0]) {
// 一十* => 十*
result = result.substring(1)
} else if (noUnit !== 2 && (char === ZERO || UNIT.indexOf(char) >= 0)) {
// 去零及单位开头的
ZERO ===
(result =
result.replace(
TRIM_BEFORE,
noUnit || indexUnit > LEN_UNIT ? '' : ZERO
) || ZERO) && (sign = 0 as any)
if (describe !== 2) {
char = cn[0] // 兼职首字
if (!char || char === POINT) {
cn = ZERO + cn // 补0 0/0.1
} else {
if (char === ZERO || UNIT.indexOf(char) >= 0) {
// 去0及单位开头的
unit = describe || number > LEN_UNIT ? '' : ZERO
cn = cn.replace(TRIM_BEFORE, unit) || ZERO
unit && (unit = cn[1]) && unit !== POINT && (cn = cn.substring(1))
}
// 0 及 一十* => 十*
ZERO === cn
? (sign = 0 as any)
: cases ||
(char === NUM[1] && cn[1] === UNIT[0] && (cn = cn.substring(1)))
}
}

// 加正负号
return (SIGN[sign] || '') + result
return (SIGN[sign] || '') + cn
}
)
}
84 changes: 53 additions & 31 deletions tests/unit/utils/numToCN.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,16 @@ describe('@/utils/numToCN: 阿拉伯数字和中文转换', () => {
it('numToCN: 阿拉伯数字转中文数字', () => {
expect(numToCN('')).toBe('')

expect(numToCN(0)).toBe('')
expect(numToCN('00')).toBe('')
expect(numToCN('+000000')).toBe('')
expect(numToCN('-0000000000')).toBe('')
expect(numToCN('00000000000000000')).toBe('')
expect(numToCN(0)).toBe('')
expect(numToCN('00')).toBe('')
expect(numToCN('+000000')).toBe('')
expect(numToCN('-0000000000')).toBe('')
expect(numToCN('00000000000000000')).toBe('')

expect(numToCN(-0.1)).toBe('负零点一')
expect(numToCN(0.01)).toBe('零点零一')
expect(numToCN('0.01230')).toBe('零点零一二三零')
expect(numToCN('-00000.01200')).toBe('负零点零一二零零')
expect(numToCN(-0.1)).toBe('负〇点一')
expect(numToCN(0.01)).toBe('〇点〇一')
expect(numToCN('0.01230')).toBe('〇点〇一二三〇')
expect(numToCN('-00000.01200')).toBe('负〇点〇一二〇〇')

expect(numToCN(2)).toBe('二')
expect(numToCN('+2')).toBe('正二')
Expand All @@ -31,44 +31,66 @@ describe('@/utils/numToCN: 阿拉伯数字和中文转换', () => {

expect(numToCN(100)).toBe('一百')
expect(numToCN(120)).toBe('一百二十')
expect(numToCN(103)).toBe('一百零三')
expect(numToCN(103)).toBe('一百〇三')

expect(numToCN(1000)).toBe('一千')
expect(numToCN(1004)).toBe('一千零四')
expect(numToCN(1030)).toBe('一千零三十')
expect(numToCN(1004)).toBe('一千〇四')
expect(numToCN(1030)).toBe('一千〇三十')
expect(numToCN(1200)).toBe('一千二百')

expect(numToCN(10000)).toBe('一万')
expect(numToCN(10005)).toBe('一万零五')
expect(numToCN(10040)).toBe('一万零四十')
expect(numToCN(10045)).toBe('一万零四十五')
expect(numToCN(10300)).toBe('一万零三百')
expect(numToCN(10305)).toBe('一万零三百零五')
expect(numToCN(10340)).toBe('一万零三百四十')
expect(numToCN(10345)).toBe('一万零三百四十五')
expect(numToCN(10005)).toBe('一万〇五')
expect(numToCN(10040)).toBe('一万〇四十')
expect(numToCN(10045)).toBe('一万〇四十五')
expect(numToCN(10300)).toBe('一万〇三百')
expect(numToCN(10305)).toBe('一万〇三百〇五')
expect(numToCN(10340)).toBe('一万〇三百四十')
expect(numToCN(10345)).toBe('一万〇三百四十五')
expect(numToCN(12000)).toBe('一万二千')
expect(numToCN(12005)).toBe('一万二千零五')
expect(numToCN(12040)).toBe('一万二千零四十')
expect(numToCN(12045)).toBe('一万二千零四十五')
expect(numToCN(12005)).toBe('一万二千〇五')
expect(numToCN(12040)).toBe('一万二千〇四十')
expect(numToCN(12045)).toBe('一万二千〇四十五')
expect(numToCN(12300)).toBe('一万二千三百')
expect(numToCN(12305)).toBe('一万二千三百零五')
expect(numToCN(12305)).toBe('一万二千三百〇五')
expect(numToCN(12340)).toBe('一万二千三百四十')
expect(numToCN(12345)).toBe('一万二千三百四十五')

expect(numToCN(100006)).toBe('十万零六')
expect(numToCN(1004067)).toBe('一百万零四千零六十七')
expect(numToCN(1014067)).toBe('一百零一万四千零六十七')
expect(numToCN(100006)).toBe('十万〇六')
expect(numToCN(120406)).toBe('十二万〇四百〇六')
expect(numToCN(1004067)).toBe('一百万〇四千〇六十七')
expect(numToCN(1014067)).toBe('一百〇一万四千〇六十七')
expect(numToCN(123456789000000)).toBe(
'一百二十三万四千五百六十七亿八千九百万'
)
expect(numToCN('012345678909876543210')).toBe(
'一二三四万五千六百七十八万九千零九十八亿七千六百五十四万三千二百一十'
'一二三四万五千六百七十八万九千〇九十八亿七千六百五十四万三千二百一十'
)

expect(numToCN('012345.67890', 1)).toBe('一二三四五点六七八九零')
expect(numToCN('012345.67890', 2)).toBe('零一二三四五点六七八九零')
expect(numToCN('-012345678909876543210', 1)).toBe(
'负一二三四五六七八九零九八七六五四三二一零'
expect(numToCN('012345.67890', 1)).toBe('一二三四五点六七八九〇')
// expect(numToCN('.7890', 2)).toBe('点七八九〇')
expect(numToCN('0123456.7890', 2)).toBe('〇一二三四五六点七八九〇')
expect(numToCN('-012345678909876543210.1', 1)).toBe(
'负一二三四五六七八九〇九八七六五四三二一〇点一'
)

expect(numToCN('012345.67890', 0, 1)).toBe('一万二千三百四十五点六七八九零')
expect(numToCN('0123456.7890', 0, 2)).toBe(
'壹拾贰万叁仟肆佰伍拾陆点柒捌玖零'
)
expect(numToCN('-012345678909876543210.1', 0, 2)).toBe(
'负壹贰叁肆万伍仟陆佰柒拾捌万玖仟零玖拾捌亿柒仟陆佰伍拾肆万叁仟贰佰壹拾点壹'
)

expect(numToCN('012345.67890', 1, 1)).toBe('一二三四五点六七八九零')
expect(numToCN('0123456.7890', 1, 2)).toBe('壹贰叁肆伍陆点柒捌玖零')
expect(numToCN('-012345678909876543210.1', 1, 2)).toBe(
'负壹贰叁肆伍陆柒捌玖零玖捌柒陆伍肆叁贰壹零点壹'
)

expect(numToCN('012345.67890', 2, 1)).toBe('零一二三四五点六七八九零')
expect(numToCN('0123456.7890', 2, 2)).toBe('零壹贰叁肆伍陆点柒捌玖零')
expect(numToCN('-012345678909876543210.1', 2, 2)).toBe(
'负零壹贰叁肆伍陆柒捌玖零玖捌柒陆伍肆叁贰壹零点壹'
)
})
})

0 comments on commit 149713a

Please sign in to comment.