├── .browserslistrc ├── .editorconfig ├── .eslintignore ├── .eslintrc.js ├── .gitignore ├── .husky ├── commit-msg └── pre-commit ├── .lintstagedrc ├── .prettierrc ├── LICENSE ├── README-ZH.md ├── README.md ├── babel.config.js ├── commitlint.config.js ├── coverage ├── clover.xml ├── coverage-final.json ├── lcov-report │ ├── base.css │ ├── block-navigation.js │ ├── index.html │ ├── prettify.css │ ├── prettify.js │ ├── sort-arrow-sprite.png │ ├── sorter.js │ └── src │ │ ├── core │ │ ├── date.ts.html │ │ ├── format.ts.html │ │ ├── index.html │ │ ├── index.ts.html │ │ ├── is.ts.html │ │ ├── lodash-tool.ts.html │ │ ├── math.ts.html │ │ ├── method.ts.html │ │ ├── url.ts.html │ │ ├── uuid.ts.html │ │ └── verify.ts.html │ │ ├── enum │ │ ├── index.html │ │ └── system.ts.html │ │ ├── index.html │ │ ├── index.ts.html │ │ └── tools │ │ ├── index.html │ │ └── index.ts.html └── lcov.info ├── dist ├── index.js └── types │ ├── core │ ├── date.d.ts │ ├── format.d.ts │ ├── index.d.ts │ ├── is.d.ts │ ├── lodash-tool.d.ts │ ├── math.d.ts │ ├── method.d.ts │ ├── url.d.ts │ ├── uuid.d.ts │ └── verify.d.ts │ ├── enum │ └── system.d.ts │ ├── index.d.ts │ ├── tools │ └── index.d.ts │ └── types │ └── index.d.ts ├── docs ├── assets │ ├── css │ │ └── main.css │ ├── images │ │ ├── icons.png │ │ ├── icons@2x.png │ │ ├── widgets.png │ │ └── widgets@2x.png │ └── js │ │ ├── main.js │ │ └── search.json ├── globals.html ├── index.html └── interfaces │ ├── datefromat.html │ ├── format.html │ ├── index.html │ ├── is.html │ ├── lodashtool.html │ ├── math.html │ ├── method.html │ ├── url.html │ ├── uuid.html │ └── verify.html ├── gulpfile.js ├── home ├── App.vue ├── assets │ └── logo.png ├── components │ └── HelloWorld.vue ├── main.ts ├── shims-tsx.d.ts └── shims-vue.d.ts ├── index.html ├── jest.config.js ├── package-lock.json ├── package.json ├── public ├── favicon.png └── index.html ├── src ├── core │ ├── date.ts │ ├── format.ts │ ├── index.ts │ ├── is.ts │ ├── lodash-tool.ts │ ├── math.ts │ ├── method.ts │ ├── url.ts │ ├── uuid.ts │ └── verify.ts ├── enum │ └── system.ts ├── index.ts ├── tools │ └── index.ts └── types │ └── index.ts ├── tests └── unit │ ├── core │ ├── date.spec.ts │ ├── format.spec.ts │ ├── index.spec.ts │ ├── is.spec.ts │ ├── math.spec.ts │ ├── method.spec.ts │ ├── url.spec.ts │ ├── uuid.spec.ts │ └── verify.spec.ts │ └── index.spec.ts ├── tsconfig.json ├── tslint.json ├── typedoc.json └── vue.config.js /.browserslistrc: -------------------------------------------------------------------------------- 1 | > 1% 2 | last 2 versions 3 | not dead 4 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | #root = true 2 | 3 | [*] 4 | indent_style = space 5 | end_of_line = lf 6 | charset = utf-8 7 | trim_trailing_whitespace = true 8 | insert_final_newline = true 9 | max_line_length = 100 10 | indent_size = 2 11 | 12 | [*.md] 13 | trim_trailing_whitespace = false 14 | -------------------------------------------------------------------------------- /.eslintignore: -------------------------------------------------------------------------------- 1 | /dist/ 2 | /*.js 3 | /.vscode/ 4 | -------------------------------------------------------------------------------- /.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | root: true, 3 | 4 | env: { 5 | node: true 6 | }, 7 | 8 | 'extends': [ 9 | 'plugin:vue/essential', 10 | 'eslint:recommended', 11 | '@vue/typescript/recommended' 12 | ], 13 | 14 | parserOptions: { 15 | ecmaVersion: 2020 16 | }, 17 | 18 | rules: { 19 | "@typescript-eslint/no-explicit-any": ["off"], 20 | "@typescript-eslint/ban-ts-ignore": ["off"], 21 | "@typescript-eslint/member-delimiter-style": ["off"], 22 | 'no-console': process.env.NODE_ENV === 'production' ? 'warn' : 'off', 23 | 'no-debugger': process.env.NODE_ENV === 'production' ? 'warn' : 'off' 24 | }, 25 | 26 | overrides: [ 27 | { 28 | files: [ 29 | '**/__tests__/*.{j,t}s?(x)', 30 | '**/tests/unit/**/*.spec.{j,t}s?(x)' 31 | ], 32 | env: { 33 | jest: true 34 | } 35 | } 36 | ] 37 | } 38 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Created by .ignore support plugin 2 | ### Node template 3 | # Logs 4 | logs 5 | *.log 6 | npm-debug.log* 7 | yarn-debug.log* 8 | yarn-error.log* 9 | pnpm-lock.yaml 10 | 11 | # Runtime data 12 | pids 13 | *.pid 14 | *.seed 15 | *.pid.lock 16 | .vscode 17 | # Directory for instrumented libs generated by jscoverage/JSCover 18 | lib-cov 19 | 20 | # nyc test coverage 21 | .nyc_output 22 | 23 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 24 | .grunt 25 | 26 | # Bower dependency directory (https://bower.io/) 27 | bower_components 28 | 29 | # node-waf configuration 30 | .lock-wscript 31 | 32 | # Compiled binary addons (https://nodejs.org/api/addons.html) 33 | build/Release 34 | 35 | # Dependency directories 36 | node_modules/ 37 | jspm_packages/ 38 | 39 | # TypeScript v1 declaration files 40 | typings/ 41 | 42 | # Optional npm cache directory 43 | .npm 44 | 45 | # Optional eslint cache 46 | .eslintcache 47 | 48 | # Optional REPL history 49 | .node_repl_history 50 | 51 | # Output of 'npm pack' 52 | *.tgz 53 | 54 | # Yarn Integrity file 55 | .yarn-integrity 56 | 57 | # dotenv environment variables file 58 | .env 59 | 60 | # parcel-bundler cache (https://parceljs.org/) 61 | .cache 62 | 63 | # next.js build output 64 | .next 65 | 66 | # nuxt.js build output 67 | .nuxt 68 | 69 | .rpt2_cache 70 | 71 | # vuepress build output 72 | .vuepress/dist 73 | 74 | # Serverless directories 75 | .serverless 76 | 77 | # IDE 78 | .idea 79 | -------------------------------------------------------------------------------- /.husky/commit-msg: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | . "$(dirname "$0")/_/husky.sh" 3 | 4 | npx --no-install commitlint --edit $1 5 | -------------------------------------------------------------------------------- /.husky/pre-commit: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | . "$(dirname "$0")/_/husky.sh" 3 | 4 | npx --no-install lint-staged 5 | -------------------------------------------------------------------------------- /.lintstagedrc: -------------------------------------------------------------------------------- 1 | { 2 | "*.ts": [ 3 | "prettier --write" 4 | ] 5 | } -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "semi": false, 3 | "singleQuote": true, 4 | "vueIndentScriptAndStyle": true, 5 | "arrowParens": "avoid" 6 | } -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 Jarvan 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README-ZH.md: -------------------------------------------------------------------------------- 1 | # utils 2 | [![License](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE) 3 | [![PRs Welcome](https://img.shields.io/badge/PRs-welcome-brightgreen.svg)](https://github.com/BestJarvan/utils-tools) 4 | [![npm](https://img.shields.io/bundlephobia/min/@jarvannnn/utils/0.0.11)](https://www.npmjs.com/package/@jarvannnn/utils) 5 | 6 | [doc文档](https://bestjarvan.github.io/utils-tools/) 7 | 8 | Welcome to Start、Fork。thx~ XD 9 | 10 | [English](./README.md)|中文简体 11 | 12 | > 项目中虽然有大量的第三方类库存在,但是每个公司都会有自己的定制化工具包存在,这些工具包就可以通过这种方式改造成npm包安装到项目中。 13 | 14 | ##### 使用说明 15 | 16 | ``` 17 | // 通过npm安装 18 | npm i --save @jarvannnn/utils 19 | ``` 20 | 21 | #### 调试说明 22 | ``` 23 | npm i 24 | 25 | // 自动启动vue2方便调试、新增方法 26 | npm run serve 27 | 28 | // 跑单测 29 | npm run test 30 | 31 | // 打包生成文档 32 | npm run build 33 | ``` 34 | 35 | ![代码补全](https://fastly.jsdelivr.net/gh/BestJarvan/pic-imgs/imgs/202201171509895.png) 36 | 37 | ### 前言 38 | 1. 项目中经常会用到某些方法,比如格式化时间戳,比如判断环境等等。 39 | 笔者最初是把这些方法抽离出来写成公共方法,但由于后期项目扩展每次都要复制这个工具文件很是麻烦且效率低下,发布npm包正好解决了这个痛点,正好借此机会重构成ts文件并发布npm包。 40 | 41 | 2. 本工具内置`vue2.x + ts`,方便开发中调试代码。 42 | 本工具包内部集成了`lodash`的一些方法,详见[文档](https://bestjarvan.github.io/utils-tools/docs/interfaces/lodashtool.html)或者`src/core/lodash-tool` 43 | 44 | 3. 本工具使用`typedoc`根据注释自动生成文档,可搜索方法 45 | 46 | 4. 本项目npm包单元测试通过率100%,同时经过公司多个项目沉淀,且稳定运行,大家如有需要可直接下载拓展使用 47 | 48 | [博客传送门](https://bestjarvan.gitee.io/2020/04/14/npm/Typescript+verdaccio/index.html) 49 | 50 | 本文只简要介绍下整个流程,具体项目[GitHub](https://github.com/BestJarvan/utils-tools),欢迎Start、Fork。thx~ XD 51 | 52 | 53 | ### 插件 54 | > 本工具包使用下列插件规范开发,定制团队开发规范 55 | - eslint 56 | - tslint 57 | - prettier 58 | - commitlint 59 | - husky 60 | 61 | ### 目录结构 62 | ``` 63 | . 64 | ├── LICENSE 65 | ├── README.md 66 | ├── docs // typedoc生成的文档 67 | │   ├── assets 68 | │   ├── globals.html 69 | │   ├── index.html 70 | │   └── interfaces 71 | ├── gulpfile.js // gulp+rollup配置文件 72 | ├── package.json 73 | ├── public // vue相关 74 | ├── home // vue调试页面 75 | ├── src // 代码模块 76 | │   ├── core // 核心代码块 77 | │   │   ├── env.ts 78 | │   │   └── ***.ts 79 | │   ├── index.ts // 入口文件 80 | │   ├── tools 81 | │   │   └── index.ts 82 | │   └── types // 声明文件 83 | │   └── index.ts 84 | ├── test // 单元测试 85 | │   ├── core // 核心代码单元测试 86 | │   │   ├── env.spec.ts 87 | │   │   └── ***.spec.ts 88 | │   └── index.spec.ts 89 | ├── tsconfig.json // ts配置 90 | ├── tslint.json // tslint配置 91 | ├── .prettierrc // prettier配置 92 | ├── .lintstagedrc // lintstage配置 93 | └── typedoc.json // typedoc配置 94 | ``` 95 | 96 | ### 100%测试通过率 97 | 98 | ![测试结果](https://fastly.jsdelivr.net/gh/BestJarvan/pic-imgs/imgs/202201171509157.png) 99 | 100 | ### 文档输出 101 | 1. 配置typedoc 102 | ``` 103 | // package.json scripts片段 104 | { 105 | "build": "npm run lint && gulp && typedoc", 106 | } 107 | // typedoc 自动识别根目录下typedoc.json配置文件 108 | 109 | ``` 110 | 111 | #### 版本说明 112 | 113 | ``` 114 | ----------|------------------------ 115 | 版本号 | 备注 116 | ----------|------------------------ 117 | v0.0.1 | 基础搭建 118 | v0.1.0 | 新增vue2.x调试 119 | v0.1.2 | 修复bug,维护更新 120 | v1.1.0 | 优化math方法,新增thumbnail, formatToNumber, dealNumber, getGuid方法 121 | v1.1.1 | 开启命名空间 122 | v1.1.2 | 修复thumbnail方法判断,若传入空数组报错的bug 123 | v1.1.3 | 修复throttle、debounce,标识变量移动到函数内部,thumbnail方法支持更大图片格式 124 | v1.1.5 | 新增方法,正常迭代 125 | v1.2.0 | 新增isWxImg,envInfo,isThirdPC方法,兼容多平台和企微头像识别 126 | v1.2.1 | 修复toFixed方法遇见0.1浮点数计算精度出错问题 127 | v1.2.3 | 拓展thumbnail方法 128 | v1.3.0 | 植入lodash方法 129 | v1.3.3 | 拓展lodash方法 130 | v1.3.4 | 节流防抖,新增修饰符 131 | v1.3.5 | envInfo,isThirdPC优化展示方法,返回当前环境 132 | v1.3.6 | thumbnail: 支持API 导入进来的图片不渲染缩略图 133 | v1.4.0 | hexToRgba: 新增16进制转rgba方法 134 | v1.4.1 | thumbnail: 新增1080 135 | v1.5.0 | lodash: 新增_padStart, _padEnd 136 | ----------|------------------------ 137 | ``` 138 | 139 | #### 参与贡献 140 | 141 | 1. 新建 feature/xxx 分支 142 | 2. 提交代码 143 | 3. 新建 Merge Request 144 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # utils 2 | [![License](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE) 3 | [![PRs Welcome](https://img.shields.io/badge/PRs-welcome-brightgreen.svg)](https://github.com/BestJarvan/utils-tools) 4 | [![npm](https://img.shields.io/bundlephobia/min/@jarvannnn/utils/0.0.11)](https://www.npmjs.com/package/@jarvannnn/utils) 5 | 6 | [docs](https://bestjarvan.github.io/utils-tools/) 7 | 8 | Welcome to Start、Fork。thx~ XD 9 | 10 | English|[中文简体](./README-ZH.md) 11 | 12 | > Although there are a large number of third-party class libraries in the project, each company will have its own customized toolkits, which can be transformed into npm packages and installed in the project in this way. 13 | 14 | ##### Instructions for use 15 | 16 | ``` 17 | // install utils 18 | npm i --save @jarvannnn/utils 19 | ``` 20 | 21 | #### Debugging instructions 22 | ``` 23 | npm i 24 | 25 | // Automatically start vue2 to facilitate debugging and add new methods 26 | npm run serve 27 | 28 | // Unit test 29 | npm run test 30 | 31 | // Build dist 32 | npm run build 33 | ``` 34 | 35 | ![project](https://fastly.jsdelivr.net/gh/BestJarvan/pic-imgs/imgs/202201171509895.png) 36 | 37 | ### Foreword 38 | 1. Certain methods are often used in projects, such as formatting timestamps, judging the environment, and so on. 39 | The author originally extracted these methods and wrote them as public methods, but because it is very troublesome and inefficient to copy this tool file every time the project is expanded in the later stage, releasing the npm package just solved this pain point, and just took this opportunity to reconstruct the ts file And publish the npm package. 40 | 41 | 2. This tool has built-in `vue2.x + ts`, which is convenient for debugging code during development. 42 | This toolkit integrates some methods of `lodash`, see[docs](https://bestjarvan.github.io/utils-tools/docs/interfaces/lodashtool.html) or `src/core/lodash-tool` 43 | 44 | 3. This tool uses `typedoc` to automatically generate documentation based on comments, searchable methods 45 | 46 | 4. The npm package unit test pass rate of this project is 100%. At the same time, it has been precipitated by multiple projects of the company and is running stably. If you need it, you can directly download it and expand it. 47 | 48 | [Blogs](https://bestjarvan.gitee.io/2020/04/14/npm/Typescript+verdaccio/index.html) 49 | 50 | 51 | 52 | ### Plugins 53 | > This toolkit is developed using the following plug-in specifications, custom team development specifications 54 | - eslint 55 | - tslint 56 | - prettier 57 | - commitlint 58 | - husky 59 | 60 | ### Directory 61 | ``` 62 | . 63 | ├── LICENSE 64 | ├── README.md 65 | ├── docs // typedoc output 66 | │   ├── assets 67 | │   ├── globals.html 68 | │   ├── index.html 69 | │   └── interfaces 70 | ├── gulpfile.js // gulp+rollup config 71 | ├── package.json 72 | ├── public // vue 73 | ├── home // vue enter 74 | ├── src // code 75 | │   ├── core // core code block 76 | │   │   ├── env.ts 77 | │   │   └── ***.ts 78 | │   ├── index.ts // main 79 | │   ├── tools 80 | │   │   └── index.ts 81 | │   └── types // declare 82 | │   └── index.ts 83 | ├── test 84 | │   ├── core 85 | │   │   ├── env.spec.ts 86 | │   │   └── ***.spec.ts 87 | │   └── index.spec.ts 88 | ├── tsconfig.json 89 | ├── tslint.json 90 | ├── .prettierrc 91 | ├── .lintstagedrc 92 | └── typedoc.json 93 | ``` 94 | 95 | ### 100% Test pass 96 | 97 | ![test](https://fastly.jsdelivr.net/gh/BestJarvan/pic-imgs/imgs/202201171509157.png) 98 | 99 | ### Docs output 100 | ``` 101 | { 102 | "build": "npm run lint && gulp && typedoc", 103 | } 104 | 105 | ``` 106 | 107 | #### Version 108 | 109 | ``` 110 | ----------|------------------------ 111 | Version | Remark 112 | ----------|------------------------ 113 | v0.0.1 | init 114 | v0.1.0 | add vue2.6 115 | v0.1.2 | fix bug 116 | v1.1.1 | add namespace 117 | v1.1.2 | fix thumbnail method judgment, if an empty array is passed in, an error will be reported 118 | v1.1.3 | fix throttle, debounce, move the identification variable to the inside of the function, thumbnail method supports larger image format 119 | v1.1.5 | update 120 | v1.2.0 | added isWxImg, envInfo, isThirdPC methods, compatible with multi-platform and Qiwei avatar recognition 121 | v1.2.1 | fix toFixed method encountered 0.1 floating-point calculation precision error problem 122 | v1.3.0 | add lodash 123 | v1.3.3 | update lodash 124 | v1.3.4 | add debounce, throttle 125 | v1.4.0 | hexToRgba: added hexadecimal to rgba method 126 | v1.4.1 | thumbnail: added 1080 127 | ----------|------------------------ 128 | ``` 129 | -------------------------------------------------------------------------------- /babel.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | presets: [ 3 | '@vue/cli-plugin-babel/preset' 4 | ] 5 | } 6 | -------------------------------------------------------------------------------- /commitlint.config.js: -------------------------------------------------------------------------------- 1 | /* 2 | * build:主要目的是修改项目构建系统(例如 glup,webpack,rollup 的配置等)的提交或打前端包 3 | * docs:文档更新 4 | * feat:新增功能 5 | * merge:分支合并 Merge branch ? of ? 6 | * fix:bug 修复 7 | * perf:性能, 体验优化 8 | * refactor:重构代码(既没有新增功能,也没有修复 bug) 9 | * style:不影响程序逻辑的代码修改(修改空白字符,格式缩进,补全缺失的分号等,没有改变代码逻辑) 10 | * test:新增测试用例或是更新现有测试 11 | * revert:回滚某个更早之前的提交 12 | * chore:不属于以上类型的其他类型 13 | */ 14 | 15 | module.exports = { 16 | extends: ['@commitlint/config-conventional'], 17 | rules: { 18 | 'type-enum': [2, 'always', [ 19 | 'build', 'docs', 'feat', 'merge', 'fix', 'perf', 'refactor', 'style', 'test', 'revert', 'chore' 20 | ]], 21 | 'subject-full-stop': [0, 'never'], 22 | 'subject-case': [0, 'never'] 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /coverage/lcov-report/base.css: -------------------------------------------------------------------------------- 1 | body, html { 2 | margin:0; padding: 0; 3 | height: 100%; 4 | } 5 | body { 6 | font-family: Helvetica Neue, Helvetica, Arial; 7 | font-size: 14px; 8 | color:#333; 9 | } 10 | .small { font-size: 12px; } 11 | *, *:after, *:before { 12 | -webkit-box-sizing:border-box; 13 | -moz-box-sizing:border-box; 14 | box-sizing:border-box; 15 | } 16 | h1 { font-size: 20px; margin: 0;} 17 | h2 { font-size: 14px; } 18 | pre { 19 | font: 12px/1.4 Consolas, "Liberation Mono", Menlo, Courier, monospace; 20 | margin: 0; 21 | padding: 0; 22 | -moz-tab-size: 2; 23 | -o-tab-size: 2; 24 | tab-size: 2; 25 | } 26 | a { color:#0074D9; text-decoration:none; } 27 | a:hover { text-decoration:underline; } 28 | .strong { font-weight: bold; } 29 | .space-top1 { padding: 10px 0 0 0; } 30 | .pad2y { padding: 20px 0; } 31 | .pad1y { padding: 10px 0; } 32 | .pad2x { padding: 0 20px; } 33 | .pad2 { padding: 20px; } 34 | .pad1 { padding: 10px; } 35 | .space-left2 { padding-left:55px; } 36 | .space-right2 { padding-right:20px; } 37 | .center { text-align:center; } 38 | .clearfix { display:block; } 39 | .clearfix:after { 40 | content:''; 41 | display:block; 42 | height:0; 43 | clear:both; 44 | visibility:hidden; 45 | } 46 | .fl { float: left; } 47 | @media only screen and (max-width:640px) { 48 | .col3 { width:100%; max-width:100%; } 49 | .hide-mobile { display:none!important; } 50 | } 51 | 52 | .quiet { 53 | color: #7f7f7f; 54 | color: rgba(0,0,0,0.5); 55 | } 56 | .quiet a { opacity: 0.7; } 57 | 58 | .fraction { 59 | font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; 60 | font-size: 10px; 61 | color: #555; 62 | background: #E8E8E8; 63 | padding: 4px 5px; 64 | border-radius: 3px; 65 | vertical-align: middle; 66 | } 67 | 68 | div.path a:link, div.path a:visited { color: #333; } 69 | table.coverage { 70 | border-collapse: collapse; 71 | margin: 10px 0 0 0; 72 | padding: 0; 73 | } 74 | 75 | table.coverage td { 76 | margin: 0; 77 | padding: 0; 78 | vertical-align: top; 79 | } 80 | table.coverage td.line-count { 81 | text-align: right; 82 | padding: 0 5px 0 20px; 83 | } 84 | table.coverage td.line-coverage { 85 | text-align: right; 86 | padding-right: 10px; 87 | min-width:20px; 88 | } 89 | 90 | table.coverage td span.cline-any { 91 | display: inline-block; 92 | padding: 0 5px; 93 | width: 100%; 94 | } 95 | .missing-if-branch { 96 | display: inline-block; 97 | margin-right: 5px; 98 | border-radius: 3px; 99 | position: relative; 100 | padding: 0 4px; 101 | background: #333; 102 | color: yellow; 103 | } 104 | 105 | .skip-if-branch { 106 | display: none; 107 | margin-right: 10px; 108 | position: relative; 109 | padding: 0 4px; 110 | background: #ccc; 111 | color: white; 112 | } 113 | .missing-if-branch .typ, .skip-if-branch .typ { 114 | color: inherit !important; 115 | } 116 | .coverage-summary { 117 | border-collapse: collapse; 118 | width: 100%; 119 | } 120 | .coverage-summary tr { border-bottom: 1px solid #bbb; } 121 | .keyline-all { border: 1px solid #ddd; } 122 | .coverage-summary td, .coverage-summary th { padding: 10px; } 123 | .coverage-summary tbody { border: 1px solid #bbb; } 124 | .coverage-summary td { border-right: 1px solid #bbb; } 125 | .coverage-summary td:last-child { border-right: none; } 126 | .coverage-summary th { 127 | text-align: left; 128 | font-weight: normal; 129 | white-space: nowrap; 130 | } 131 | .coverage-summary th.file { border-right: none !important; } 132 | .coverage-summary th.pct { } 133 | .coverage-summary th.pic, 134 | .coverage-summary th.abs, 135 | .coverage-summary td.pct, 136 | .coverage-summary td.abs { text-align: right; } 137 | .coverage-summary td.file { white-space: nowrap; } 138 | .coverage-summary td.pic { min-width: 120px !important; } 139 | .coverage-summary tfoot td { } 140 | 141 | .coverage-summary .sorter { 142 | height: 10px; 143 | width: 7px; 144 | display: inline-block; 145 | margin-left: 0.5em; 146 | background: url(sort-arrow-sprite.png) no-repeat scroll 0 0 transparent; 147 | } 148 | .coverage-summary .sorted .sorter { 149 | background-position: 0 -20px; 150 | } 151 | .coverage-summary .sorted-desc .sorter { 152 | background-position: 0 -10px; 153 | } 154 | .status-line { height: 10px; } 155 | /* yellow */ 156 | .cbranch-no { background: yellow !important; color: #111; } 157 | /* dark red */ 158 | .red.solid, .status-line.low, .low .cover-fill { background:#C21F39 } 159 | .low .chart { border:1px solid #C21F39 } 160 | .highlighted, 161 | .highlighted .cstat-no, .highlighted .fstat-no, .highlighted .cbranch-no{ 162 | background: #C21F39 !important; 163 | } 164 | /* medium red */ 165 | .cstat-no, .fstat-no, .cbranch-no, .cbranch-no { background:#F6C6CE } 166 | /* light red */ 167 | .low, .cline-no { background:#FCE1E5 } 168 | /* light green */ 169 | .high, .cline-yes { background:rgb(230,245,208) } 170 | /* medium green */ 171 | .cstat-yes { background:rgb(161,215,106) } 172 | /* dark green */ 173 | .status-line.high, .high .cover-fill { background:rgb(77,146,33) } 174 | .high .chart { border:1px solid rgb(77,146,33) } 175 | /* dark yellow (gold) */ 176 | .status-line.medium, .medium .cover-fill { background: #f9cd0b; } 177 | .medium .chart { border:1px solid #f9cd0b; } 178 | /* light yellow */ 179 | .medium { background: #fff4c2; } 180 | 181 | .cstat-skip { background: #ddd; color: #111; } 182 | .fstat-skip { background: #ddd; color: #111 !important; } 183 | .cbranch-skip { background: #ddd !important; color: #111; } 184 | 185 | span.cline-neutral { background: #eaeaea; } 186 | 187 | .coverage-summary td.empty { 188 | opacity: .5; 189 | padding-top: 4px; 190 | padding-bottom: 4px; 191 | line-height: 1; 192 | color: #888; 193 | } 194 | 195 | .cover-fill, .cover-empty { 196 | display:inline-block; 197 | height: 12px; 198 | } 199 | .chart { 200 | line-height: 0; 201 | } 202 | .cover-empty { 203 | background: white; 204 | } 205 | .cover-full { 206 | border-right: none !important; 207 | } 208 | pre.prettyprint { 209 | border: none !important; 210 | padding: 0 !important; 211 | margin: 0 !important; 212 | } 213 | .com { color: #999 !important; } 214 | .ignore-none { color: #999; font-weight: normal; } 215 | 216 | .wrapper { 217 | min-height: 100%; 218 | height: auto !important; 219 | height: 100%; 220 | margin: 0 auto -48px; 221 | } 222 | .footer, .push { 223 | height: 48px; 224 | } 225 | -------------------------------------------------------------------------------- /coverage/lcov-report/block-navigation.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable */ 2 | var jumpToCode = (function init() { 3 | // Classes of code we would like to highlight in the file view 4 | var missingCoverageClasses = ['.cbranch-no', '.cstat-no', '.fstat-no']; 5 | 6 | // Elements to highlight in the file listing view 7 | var fileListingElements = ['td.pct.low']; 8 | 9 | // We don't want to select elements that are direct descendants of another match 10 | var notSelector = ':not(' + missingCoverageClasses.join('):not(') + ') > '; // becomes `:not(a):not(b) > ` 11 | 12 | // Selecter that finds elements on the page to which we can jump 13 | var selector = 14 | fileListingElements.join(', ') + 15 | ', ' + 16 | notSelector + 17 | missingCoverageClasses.join(', ' + notSelector); // becomes `:not(a):not(b) > a, :not(a):not(b) > b` 18 | 19 | // The NodeList of matching elements 20 | var missingCoverageElements = document.querySelectorAll(selector); 21 | 22 | var currentIndex; 23 | 24 | function toggleClass(index) { 25 | missingCoverageElements 26 | .item(currentIndex) 27 | .classList.remove('highlighted'); 28 | missingCoverageElements.item(index).classList.add('highlighted'); 29 | } 30 | 31 | function makeCurrent(index) { 32 | toggleClass(index); 33 | currentIndex = index; 34 | missingCoverageElements.item(index).scrollIntoView({ 35 | behavior: 'smooth', 36 | block: 'center', 37 | inline: 'center' 38 | }); 39 | } 40 | 41 | function goToPrevious() { 42 | var nextIndex = 0; 43 | if (typeof currentIndex !== 'number' || currentIndex === 0) { 44 | nextIndex = missingCoverageElements.length - 1; 45 | } else if (missingCoverageElements.length > 1) { 46 | nextIndex = currentIndex - 1; 47 | } 48 | 49 | makeCurrent(nextIndex); 50 | } 51 | 52 | function goToNext() { 53 | var nextIndex = 0; 54 | 55 | if ( 56 | typeof currentIndex === 'number' && 57 | currentIndex < missingCoverageElements.length - 1 58 | ) { 59 | nextIndex = currentIndex + 1; 60 | } 61 | 62 | makeCurrent(nextIndex); 63 | } 64 | 65 | return function jump(event) { 66 | switch (event.which) { 67 | case 78: // n 68 | case 74: // j 69 | goToNext(); 70 | break; 71 | case 66: // b 72 | case 75: // k 73 | case 80: // p 74 | goToPrevious(); 75 | break; 76 | } 77 | }; 78 | })(); 79 | window.addEventListener('keydown', jumpToCode); 80 | -------------------------------------------------------------------------------- /coverage/lcov-report/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Code coverage report for All files 7 | 8 | 9 | 10 | 11 | 16 | 17 | 18 | 19 |
20 |
21 |

All files

22 |
23 | 24 |
25 | 100% 26 | Statements 27 | 537/537 28 |
29 | 30 | 31 |
32 | 100% 33 | Branches 34 | 257/257 35 |
36 | 37 | 38 |
39 | 100% 40 | Functions 41 | 103/103 42 |
43 | 44 | 45 |
46 | 100% 47 | Lines 48 | 505/505 49 |
50 | 51 | 52 |
53 |

54 | Press n or j to go to the next uncovered block, b, p or k for the previous block. 55 |

56 |
57 |
58 |
59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 |
FileStatementsBranchesFunctionsLines
src 77 |
78 |
100%18/18100%0/0100%1/1100%18/18
src/core 92 |
93 |
100%509/509100%255/255100%98/98100%477/477
src/enum 107 |
108 |
100%5/5100%2/2100%1/1100%5/5
src/tools 122 |
123 |
100%5/5100%0/0100%3/3100%5/5
136 |
137 |
138 |
139 | 144 | 145 | 146 | 151 | 152 | 153 | 154 | 155 | -------------------------------------------------------------------------------- /coverage/lcov-report/prettify.css: -------------------------------------------------------------------------------- 1 | .pln{color:#000}@media screen{.str{color:#080}.kwd{color:#008}.com{color:#800}.typ{color:#606}.lit{color:#066}.pun,.opn,.clo{color:#660}.tag{color:#008}.atn{color:#606}.atv{color:#080}.dec,.var{color:#606}.fun{color:red}}@media print,projection{.str{color:#060}.kwd{color:#006;font-weight:bold}.com{color:#600;font-style:italic}.typ{color:#404;font-weight:bold}.lit{color:#044}.pun,.opn,.clo{color:#440}.tag{color:#006;font-weight:bold}.atn{color:#404}.atv{color:#060}}pre.prettyprint{padding:2px;border:1px solid #888}ol.linenums{margin-top:0;margin-bottom:0}li.L0,li.L1,li.L2,li.L3,li.L5,li.L6,li.L7,li.L8{list-style-type:none}li.L1,li.L3,li.L5,li.L7,li.L9{background:#eee} 2 | -------------------------------------------------------------------------------- /coverage/lcov-report/sort-arrow-sprite.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BestJarvan/utils-tools/7f2402da2fee250ead14ad75c8cf4cd63419a843/coverage/lcov-report/sort-arrow-sprite.png -------------------------------------------------------------------------------- /coverage/lcov-report/sorter.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable */ 2 | var addSorting = (function() { 3 | 'use strict'; 4 | var cols, 5 | currentSort = { 6 | index: 0, 7 | desc: false 8 | }; 9 | 10 | // returns the summary table element 11 | function getTable() { 12 | return document.querySelector('.coverage-summary'); 13 | } 14 | // returns the thead element of the summary table 15 | function getTableHeader() { 16 | return getTable().querySelector('thead tr'); 17 | } 18 | // returns the tbody element of the summary table 19 | function getTableBody() { 20 | return getTable().querySelector('tbody'); 21 | } 22 | // returns the th element for nth column 23 | function getNthColumn(n) { 24 | return getTableHeader().querySelectorAll('th')[n]; 25 | } 26 | 27 | // loads all columns 28 | function loadColumns() { 29 | var colNodes = getTableHeader().querySelectorAll('th'), 30 | colNode, 31 | cols = [], 32 | col, 33 | i; 34 | 35 | for (i = 0; i < colNodes.length; i += 1) { 36 | colNode = colNodes[i]; 37 | col = { 38 | key: colNode.getAttribute('data-col'), 39 | sortable: !colNode.getAttribute('data-nosort'), 40 | type: colNode.getAttribute('data-type') || 'string' 41 | }; 42 | cols.push(col); 43 | if (col.sortable) { 44 | col.defaultDescSort = col.type === 'number'; 45 | colNode.innerHTML = 46 | colNode.innerHTML + ''; 47 | } 48 | } 49 | return cols; 50 | } 51 | // attaches a data attribute to every tr element with an object 52 | // of data values keyed by column name 53 | function loadRowData(tableRow) { 54 | var tableCols = tableRow.querySelectorAll('td'), 55 | colNode, 56 | col, 57 | data = {}, 58 | i, 59 | val; 60 | for (i = 0; i < tableCols.length; i += 1) { 61 | colNode = tableCols[i]; 62 | col = cols[i]; 63 | val = colNode.getAttribute('data-value'); 64 | if (col.type === 'number') { 65 | val = Number(val); 66 | } 67 | data[col.key] = val; 68 | } 69 | return data; 70 | } 71 | // loads all row data 72 | function loadData() { 73 | var rows = getTableBody().querySelectorAll('tr'), 74 | i; 75 | 76 | for (i = 0; i < rows.length; i += 1) { 77 | rows[i].data = loadRowData(rows[i]); 78 | } 79 | } 80 | // sorts the table using the data for the ith column 81 | function sortByIndex(index, desc) { 82 | var key = cols[index].key, 83 | sorter = function(a, b) { 84 | a = a.data[key]; 85 | b = b.data[key]; 86 | return a < b ? -1 : a > b ? 1 : 0; 87 | }, 88 | finalSorter = sorter, 89 | tableBody = document.querySelector('.coverage-summary tbody'), 90 | rowNodes = tableBody.querySelectorAll('tr'), 91 | rows = [], 92 | i; 93 | 94 | if (desc) { 95 | finalSorter = function(a, b) { 96 | return -1 * sorter(a, b); 97 | }; 98 | } 99 | 100 | for (i = 0; i < rowNodes.length; i += 1) { 101 | rows.push(rowNodes[i]); 102 | tableBody.removeChild(rowNodes[i]); 103 | } 104 | 105 | rows.sort(finalSorter); 106 | 107 | for (i = 0; i < rows.length; i += 1) { 108 | tableBody.appendChild(rows[i]); 109 | } 110 | } 111 | // removes sort indicators for current column being sorted 112 | function removeSortIndicators() { 113 | var col = getNthColumn(currentSort.index), 114 | cls = col.className; 115 | 116 | cls = cls.replace(/ sorted$/, '').replace(/ sorted-desc$/, ''); 117 | col.className = cls; 118 | } 119 | // adds sort indicators for current column being sorted 120 | function addSortIndicators() { 121 | getNthColumn(currentSort.index).className += currentSort.desc 122 | ? ' sorted-desc' 123 | : ' sorted'; 124 | } 125 | // adds event listeners for all sorter widgets 126 | function enableUI() { 127 | var i, 128 | el, 129 | ithSorter = function ithSorter(i) { 130 | var col = cols[i]; 131 | 132 | return function() { 133 | var desc = col.defaultDescSort; 134 | 135 | if (currentSort.index === i) { 136 | desc = !currentSort.desc; 137 | } 138 | sortByIndex(i, desc); 139 | removeSortIndicators(); 140 | currentSort.index = i; 141 | currentSort.desc = desc; 142 | addSortIndicators(); 143 | }; 144 | }; 145 | for (i = 0; i < cols.length; i += 1) { 146 | if (cols[i].sortable) { 147 | // add the click event handler on the th so users 148 | // dont have to click on those tiny arrows 149 | el = getNthColumn(i).querySelector('.sorter').parentElement; 150 | if (el.addEventListener) { 151 | el.addEventListener('click', ithSorter(i)); 152 | } else { 153 | el.attachEvent('onclick', ithSorter(i)); 154 | } 155 | } 156 | } 157 | } 158 | // adds sorting functionality to the UI 159 | return function() { 160 | if (!getTable()) { 161 | return; 162 | } 163 | cols = loadColumns(); 164 | loadData(); 165 | addSortIndicators(); 166 | enableUI(); 167 | }; 168 | })(); 169 | 170 | window.addEventListener('load', addSorting); 171 | -------------------------------------------------------------------------------- /coverage/lcov-report/src/core/lodash-tool.ts.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Code coverage report for src/core/lodash-tool.ts 7 | 8 | 9 | 10 | 11 | 16 | 17 | 18 | 19 |
20 |
21 |

All files / src/core lodash-tool.ts

22 |
23 | 24 |
25 | 100% 26 | Statements 27 | 32/32 28 |
29 | 30 | 31 |
32 | 100% 33 | Branches 34 | 0/0 35 |
36 | 37 | 38 |
39 | 100% 40 | Functions 41 | 0/0 42 |
43 | 44 | 45 |
46 | 100% 47 | Lines 48 | 32/32 49 |
50 | 51 | 52 |
53 |

54 | Press n or j to go to the next uncovered block, b, p or k for the previous block. 55 |

56 |
57 |
58 |

 59 | 
1 60 | 2 61 | 3 62 | 4 63 | 5 64 | 6 65 | 7 66 | 8 67 | 9 68 | 10 69 | 11 70 | 12 71 | 13 72 | 14 73 | 15 74 | 16 75 | 17 76 | 18 77 | 19 78 | 20 79 | 21 80 | 22 81 | 23 82 | 24 83 | 25 84 | 26 85 | 27 86 | 28 87 | 29 88 | 30 89 | 31 90 | 32 91 | 33 92 | 34 93 | 35 94 | 3610x 95 | 10x 96 | 10x 97 | 10x 98 | 10x 99 | 10x 100 | 10x 101 | 10x 102 | 10x 103 | 10x 104 | 10x 105 | 10x 106 | 10x 107 | 10x 108 | 10x 109 | 10x 110 |   111 |   112 | 10x 113 | 10x 114 | 10x 115 | 10x 116 | 10x 117 | 10x 118 | 10x 119 | 10x 120 | 10x 121 | 10x 122 | 10x 123 | 10x 124 | 10x 125 | 10x 126 | 10x 127 | 10x 128 |   129 |  
import _get from 'lodash/get'
130 | import _map from 'lodash/map'
131 | import _uniq from 'lodash/uniq'
132 | import _pick from 'lodash/pick'
133 | import _omit from 'lodash/omit'
134 | import _isNaN from 'lodash/isNaN'
135 | import _property from 'lodash/property'
136 | import _findIndex from 'lodash/findIndex'
137 | import _findLastIndex from 'lodash/findLastIndex'
138 | import _trim from 'lodash/trim'
139 | import _isEmpty from 'lodash/isEmpty'
140 | import _isEqual from 'lodash/isEqual'
141 | import _debounce from 'lodash/debounce'
142 | import _throttle from 'lodash/throttle'
143 | import _padStart from 'lodash/padStart'
144 | import _padEnd from 'lodash/padEnd'
145 |  
146 | export {
147 |   _get,
148 |   _map,
149 |   _property,
150 |   _findIndex,
151 |   _findLastIndex,
152 |   _uniq,
153 |   _pick,
154 |   _omit,
155 |   _isNaN,
156 |   _trim,
157 |   _isEmpty,
158 |   _isEqual,
159 |   _debounce,
160 |   _throttle,
161 |   _padStart,
162 |   _padEnd,
163 | }
164 |  
165 | 166 |
167 |
168 | 173 | 174 | 175 | 180 | 181 | 182 | 183 | 184 | -------------------------------------------------------------------------------- /coverage/lcov-report/src/core/method.ts.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Code coverage report for src/core/method.ts 7 | 8 | 9 | 10 | 11 | 16 | 17 | 18 | 19 |
20 |
21 |

All files / src/core method.ts

22 |
23 | 24 |
25 | 100% 26 | Statements 27 | 21/21 28 |
29 | 30 | 31 |
32 | 100% 33 | Branches 34 | 16/16 35 |
36 | 37 | 38 |
39 | 100% 40 | Functions 41 | 6/6 42 |
43 | 44 | 45 |
46 | 100% 47 | Lines 48 | 13/13 49 |
50 | 51 | 52 |
53 |

54 | Press n or j to go to the next uncovered block, b, p or k for the previous block. 55 |

56 |
57 |
58 |

 59 | 
1 60 | 2 61 | 3 62 | 4 63 | 5 64 | 6 65 | 7 66 | 8 67 | 9 68 | 10 69 | 11 70 | 12 71 | 13 72 | 14 73 | 15 74 | 16 75 | 17 76 | 18 77 | 19 78 | 20 79 | 21 80 | 22 81 | 23 82 | 24 83 | 25 84 | 26 85 | 27 86 | 28 87 | 29 88 | 30 89 | 31 90 | 32 91 | 33 92 | 34 93 | 35 94 | 36 95 | 37 96 | 38 97 | 39 98 | 40 99 | 41 100 | 42 101 | 43 102 | 44 103 | 45 104 | 46 105 | 47 106 | 48 107 | 4910x 108 |   109 |   110 |   111 |   112 |   113 |   114 |   115 |   116 |   117 |   118 |   119 | 12x 120 | 8x 121 |   122 |   123 |   124 |   125 |   126 |   127 |   128 | 12x 129 | 8x 130 | 8x 131 | 8x 132 |   133 |   134 |   135 |   136 |   137 |   138 |   139 |   140 | 12x 141 | 8x 142 |   143 |   144 |   145 |   146 |   147 |   148 |   149 | 12x 150 | 8x 151 | 8x 152 | 8x 153 |   154 |   155 |  
import { _debounce, _throttle } from './lodash-tool'
156 |  
157 | /**
158 |  * @ignore
159 |  * 方法类
160 |  */
161 |  
162 | /**
163 |  * @ignore
164 |  * 防抖函数
165 |  * 默认调用在防抖开始后
166 |  */
167 | export function debounce(fn: any, delay = 500, option = {}) {
168 |   return _debounce(fn, delay, option)
169 | }
170 |  
171 | /**
172 |  * @ignore
173 |  * 防抖装饰器
174 |  * 默认调用在防抖开始后
175 |  */
176 | export function debounceWrap(delay = 500, option = {}) {
177 |   return function (target: any, propertyKey: string, descriptor: PropertyDescriptor) {
178 |     descriptor.value = _debounce(descriptor.value, delay, option)
179 |     return descriptor
180 |   }
181 | }
182 |  
183 | /**
184 |  * @ignore
185 |  * 节流函数
186 |  * 默认调用在节流开始前
187 |  */
188 | export function throttle(fn: any, delay = 500, option = {}) {
189 |   return _throttle(fn, delay, option)
190 | }
191 |  
192 | /**
193 |  * @ignore
194 |  * 节流装饰器
195 |  * 默认调用在节流开始前
196 |  */
197 | export function throttleWrap(delay = 500, option = {}) {
198 |   return function (target: any, propertyKey: string, descriptor: PropertyDescriptor) {
199 |     descriptor.value = _throttle(descriptor.value, delay, option)
200 |     return descriptor
201 |   }
202 | }
203 |  
204 | 205 |
206 |
207 | 212 | 213 | 214 | 219 | 220 | 221 | 222 | 223 | -------------------------------------------------------------------------------- /coverage/lcov-report/src/core/url.ts.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Code coverage report for src/core/url.ts 7 | 8 | 9 | 10 | 11 | 16 | 17 | 18 | 19 |
20 |
21 |

All files / src/core url.ts

22 |
23 | 24 |
25 | 100% 26 | Statements 27 | 20/20 28 |
29 | 30 | 31 |
32 | 100% 33 | Branches 34 | 8/8 35 |
36 | 37 | 38 |
39 | 100% 40 | Functions 41 | 5/5 42 |
43 | 44 | 45 |
46 | 100% 47 | Lines 48 | 17/17 49 |
50 | 51 | 52 |
53 |

54 | Press n or j to go to the next uncovered block, b, p or k for the previous block. 55 |

56 |
57 |
58 |

 59 | 
1 60 | 2 61 | 3 62 | 4 63 | 5 64 | 6 65 | 7 66 | 8 67 | 9 68 | 10 69 | 11 70 | 12 71 | 13 72 | 14 73 | 15 74 | 16 75 | 17 76 | 18 77 | 19 78 | 20 79 | 21 80 | 22 81 | 23 82 | 24 83 | 25 84 | 26 85 | 27 86 | 28 87 | 29 88 | 30 89 | 31 90 | 32 91 | 33 92 | 34 93 | 35 94 | 36 95 | 37 96 | 38 97 | 39 98 | 40 99 | 41 100 | 42 101 | 43 102 | 44 103 | 45 104 | 46 105 | 47 106 | 48 107 | 49 108 | 50 109 | 51 110 | 52 111 | 53 112 | 54 113 | 55 114 | 56  115 |   116 |   117 |   118 |   119 |   120 | 10x 121 | 5x 122 | 5x 123 | 15x 124 | 11x 125 |   126 |   127 | 5x 128 |   129 |   130 |   131 |   132 |   133 |   134 |   135 |   136 | 10x 137 | 4x 138 | 3x 139 |   140 | 9x 141 | 7x 142 |   143 |   144 |   145 |   146 |   147 |   148 |   149 |   150 |   151 |   152 |   153 |   154 |   155 |   156 |   157 |   158 |   159 | 10x 160 | 4x 161 | 4x 162 |   163 | 4x 164 |   165 | 5x 166 |   167 | 4x 168 |   169 |  
/**
170 |  *
171 |  * @ignore
172 |  * @return {Array} 过滤出url的非空值
173 |  *
174 |  */
175 | export function cleanArray(actual: any): Array<any> {
176 |   const newArray: Array<any> = []
177 |   for (let i = 0; i < actual.length; i++) {
178 |     if (actual[i]) {
179 |       newArray.push(actual[i])
180 |     }
181 |   }
182 |   return newArray
183 | }
184 |  
185 | /**
186 |  *
187 |  * @ignore
188 |  * @return {string} 对象转成url的param
189 |  *
190 |  */
191 | export function param(json: Record<string, any>): string {
192 |   if (JSON.stringify(json) === '{}') return ''
193 |   return cleanArray(
194 |     Object.keys(json).map(key => {
195 |       if (json[key] === undefined) return ''
196 |       return encodeURIComponent(key) + '=' + encodeURIComponent(json[key])
197 |     })
198 |   ).join('&')
199 | }
200 |  
201 | /**
202 |  *
203 |  * @ignore
204 |  * @return {object}
205 |  *
206 |  */
207 |  
208 | /**
209 |  *
210 |  * @ignore
211 |  * @return {object} 解析url中的参数
212 |  *
213 |  */
214 | export function param2Obj(search: string): Record<string, any> {
215 |   const str: string = search || window.location.search
216 |   const objURL: object = {}
217 |  
218 |   str.replace(new RegExp('([^?=&]+)(=([^&]*))?', 'g'), ($0, $1, $2, $3): any => {
219 |     // 明明没有返回为啥不能定义成void
220 |     objURL[$1] = $3
221 |   })
222 |   return objURL
223 | }
224 |  
225 | 226 |
227 |
228 | 233 | 234 | 235 | 240 | 241 | 242 | 243 | 244 | -------------------------------------------------------------------------------- /coverage/lcov-report/src/core/uuid.ts.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Code coverage report for src/core/uuid.ts 7 | 8 | 9 | 10 | 11 | 16 | 17 | 18 | 19 |
20 |
21 |

All files / src/core uuid.ts

22 |
23 | 24 |
25 | 100% 26 | Statements 27 | 8/8 28 |
29 | 30 | 31 |
32 | 100% 33 | Branches 34 | 2/2 35 |
36 | 37 | 38 |
39 | 100% 40 | Functions 41 | 4/4 42 |
43 | 44 | 45 |
46 | 100% 47 | Lines 48 | 8/8 49 |
50 | 51 | 52 |
53 |

54 | Press n or j to go to the next uncovered block, b, p or k for the previous block. 55 |

56 |
57 |
58 |

 59 | 
1 60 | 2 61 | 3 62 | 4 63 | 5 64 | 6 65 | 7 66 | 8 67 | 9 68 | 10 69 | 11 70 | 12 71 | 13 72 | 14 73 | 15 74 | 16 75 | 17 76 | 18 77 | 19 78 | 20 79 | 21 80 | 22 81 | 23 82 | 24  83 |   84 |   85 |   86 | 10x 87 |   88 |   89 | 16x 90 |   91 | 2x 92 |   93 |   94 |   95 |   96 |   97 |   98 | 10x 99 | 1x 100 | 31x 101 | 31x 102 | 31x 103 |   104 |   105 |  
/**
106 |  * @ignore
107 |  * @description 生成唯一码uuid
108 |  */
109 | export function guid(): string {
110 |   // 生成随机码
111 |   function S4(): string {
112 |     return (((1 + Math.random()) * 0x10000) | 0).toString(16).substring(1)
113 |   }
114 |   return S4() + S4() + '-' + S4() + '-' + S4() + '-' + S4() + '-' + S4() + S4() + S4()
115 | }
116 |  
117 | /**
118 |  * @ignore
119 |  * @description guid
120 |  */
121 | export function getGuid(): string {
122 |   return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, c => {
123 |     const r = (Math.random() * 16) | 0
124 |     const v = c === 'x' ? r : (r & 0x3) | 0x8
125 |     return v.toString(16)
126 |   })
127 | }
128 |  
129 | 130 |
131 |
132 | 137 | 138 | 139 | 144 | 145 | 146 | 147 | 148 | -------------------------------------------------------------------------------- /coverage/lcov-report/src/core/verify.ts.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Code coverage report for src/core/verify.ts 7 | 8 | 9 | 10 | 11 | 16 | 17 | 18 | 19 |
20 |
21 |

All files / src/core verify.ts

22 |
23 | 24 |
25 | 100% 26 | Statements 27 | 11/11 28 |
29 | 30 | 31 |
32 | 100% 33 | Branches 34 | 0/0 35 |
36 | 37 | 38 |
39 | 100% 40 | Functions 41 | 4/4 42 |
43 | 44 | 45 |
46 | 100% 47 | Lines 48 | 11/11 49 |
50 | 51 | 52 |
53 |

54 | Press n or j to go to the next uncovered block, b, p or k for the previous block. 55 |

56 |
57 |
58 |

 59 | 
1 60 | 2 61 | 3 62 | 4 63 | 5 64 | 6 65 | 7 66 | 8 67 | 9 68 | 10 69 | 11 70 | 12 71 | 13 72 | 14 73 | 15 74 | 16 75 | 17 76 | 18 77 | 19 78 | 20 79 | 21 80 | 22 81 | 23 82 | 24 83 | 25 84 | 26 85 | 27 86 | 28 87 | 29 88 | 30 89 | 31 90 | 32 91 | 33 92 | 34 93 | 35 94 | 36 95 | 37 96 | 38 97 | 39 98 | 40 99 | 41 100 | 42 101 | 43  102 |   103 |   104 |   105 |   106 |   107 | 10x 108 | 3x 109 |   110 |   111 |   112 |   113 |   114 |   115 |   116 |   117 | 10x 118 | 2x 119 | 2x 120 |   121 |   122 |   123 |   124 |   125 |   126 |   127 |   128 | 10x 129 | 2x 130 | 2x 131 |   132 |   133 |   134 |   135 |   136 |   137 |   138 |   139 | 10x 140 | 2x 141 | 2x 142 |   143 |  
/**
144 |  *
145 |  * @ignore
146 |  * @return {boolean} 判断是否是合法链接
147 |  *
148 |  */
149 | export function verifyHttp(value: string): boolean {
150 |   return /^http[s]?:\/\/.*/.test(value.trim())
151 | }
152 |  
153 | /**
154 |  *
155 |  * @ignore
156 |  * @return {boolean} 验证合法手机号
157 |  *
158 |  */
159 | export function verifyMobile(mobile: string): boolean {
160 |   const reg = /^1[3456789]\d{9}$/
161 |   return reg.test(mobile.trim())
162 | }
163 |  
164 | /**
165 |  *
166 |  * @ignore
167 |  * @return {boolean} 判断验证码是否6位
168 |  *
169 |  */
170 | export function verifyCode(code: string): boolean {
171 |   const reg = /^\d{6}$/
172 |   return reg.test(code)
173 | }
174 |  
175 | /**
176 |  *
177 |  * @ignore
178 |  * @return {boolean} 验证是否是合法邮箱格式
179 |  *
180 |  */
181 | export function verifyEmail(email: string): boolean {
182 |   const re = /^(([^<>()[\]\\.,;:\s@"]+(\.[^<>()[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/
183 |   return re.test(email.trim())
184 | }
185 |  
186 | 187 |
188 |
189 | 194 | 195 | 196 | 201 | 202 | 203 | 204 | 205 | -------------------------------------------------------------------------------- /coverage/lcov-report/src/enum/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Code coverage report for src/enum 7 | 8 | 9 | 10 | 11 | 16 | 17 | 18 | 19 |
20 |
21 |

All files src/enum

22 |
23 | 24 |
25 | 100% 26 | Statements 27 | 5/5 28 |
29 | 30 | 31 |
32 | 100% 33 | Branches 34 | 2/2 35 |
36 | 37 | 38 |
39 | 100% 40 | Functions 41 | 1/1 42 |
43 | 44 | 45 |
46 | 100% 47 | Lines 48 | 5/5 49 |
50 | 51 | 52 |
53 |

54 | Press n or j to go to the next uncovered block, b, p or k for the previous block. 55 |

56 |
57 |
58 |
59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 |
FileStatementsBranchesFunctionsLines
system.ts 77 |
78 |
100%5/5100%2/2100%1/1100%5/5
91 |
92 |
93 |
94 | 99 | 100 | 101 | 106 | 107 | 108 | 109 | 110 | -------------------------------------------------------------------------------- /coverage/lcov-report/src/enum/system.ts.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Code coverage report for src/enum/system.ts 7 | 8 | 9 | 10 | 11 | 16 | 17 | 18 | 19 |
20 |
21 |

All files / src/enum system.ts

22 |
23 | 24 |
25 | 100% 26 | Statements 27 | 5/5 28 |
29 | 30 | 31 |
32 | 100% 33 | Branches 34 | 2/2 35 |
36 | 37 | 38 |
39 | 100% 40 | Functions 41 | 1/1 42 |
43 | 44 | 45 |
46 | 100% 47 | Lines 48 | 5/5 49 |
50 | 51 | 52 |
53 |

54 | Press n or j to go to the next uncovered block, b, p or k for the previous block. 55 |

56 |
57 |
58 |

 59 | 
1 60 | 2 61 | 3 62 | 4 63 | 5 64 | 6 65 | 7 66 | 8 67 | 9 68 | 10 69 | 11  70 |   71 |   72 |   73 | 10x 74 | 10x 75 | 10x 76 | 10x 77 | 10x 78 |   79 |  
/**
 80 |  * @ignore
 81 |  * @description 多平台枚举
 82 |  */
 83 | export enum System {
 84 |   'wx' = 'wxwork',
 85 |   'h5' = 'Html5Plus',
 86 |   'lark' = 'Lark',
 87 |   'dd' = 'DingTalk',
 88 | }
 89 |  
90 | 91 |
92 |
93 | 98 | 99 | 100 | 105 | 106 | 107 | 108 | 109 | -------------------------------------------------------------------------------- /coverage/lcov-report/src/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Code coverage report for src 7 | 8 | 9 | 10 | 11 | 16 | 17 | 18 | 19 |
20 |
21 |

All files src

22 |
23 | 24 |
25 | 100% 26 | Statements 27 | 18/18 28 |
29 | 30 | 31 |
32 | 100% 33 | Branches 34 | 0/0 35 |
36 | 37 | 38 |
39 | 100% 40 | Functions 41 | 1/1 42 |
43 | 44 | 45 |
46 | 100% 47 | Lines 48 | 18/18 49 |
50 | 51 | 52 |
53 |

54 | Press n or j to go to the next uncovered block, b, p or k for the previous block. 55 |

56 |
57 |
58 |
59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 |
FileStatementsBranchesFunctionsLines
index.ts 77 |
78 |
100%18/18100%0/0100%1/1100%18/18
91 |
92 |
93 |
94 | 99 | 100 | 101 | 106 | 107 | 108 | 109 | 110 | -------------------------------------------------------------------------------- /coverage/lcov-report/src/index.ts.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Code coverage report for src/index.ts 7 | 8 | 9 | 10 | 11 | 16 | 17 | 18 | 19 |
20 |
21 |

All files / src index.ts

22 |
23 | 24 |
25 | 100% 26 | Statements 27 | 18/18 28 |
29 | 30 | 31 |
32 | 100% 33 | Branches 34 | 0/0 35 |
36 | 37 | 38 |
39 | 100% 40 | Functions 41 | 1/1 42 |
43 | 44 | 45 |
46 | 100% 47 | Lines 48 | 18/18 49 |
50 | 51 | 52 |
53 |

54 | Press n or j to go to the next uncovered block, b, p or k for the previous block. 55 |

56 |
57 |
58 |

 59 | 
1 60 | 2 61 | 3 62 | 4 63 | 5 64 | 6 65 | 7 66 | 8 67 | 9 68 | 10 69 | 11 70 | 12 71 | 13 72 | 14 73 | 15 74 | 16 75 | 17 76 | 18 77 | 19 78 | 20 79 | 21 80 | 22 81 | 23 82 | 24 83 | 25 84 | 26 85 | 27 86 | 28 87 | 29 88 | 30 89 | 31 90 | 32 91 | 33 92 | 3410x 93 | 10x 94 | 10x 95 | 10x 96 | 10x 97 | 10x 98 | 10x 99 | 10x 100 | 10x 101 | 10x 102 |   103 | 10x 104 |   105 |   106 |   107 |   108 |   109 |   110 | 10x 111 | 10x 112 | 10x 113 |   114 | 10x 115 |   116 | 10x 117 |   118 |   119 |   120 |   121 |   122 | 10x 123 |   124 | 10x 125 |  
import * as index from './core/index'
126 | import * as verify from './core/verify'
127 | import * as format from './core/format'
128 | import * as is from './core/is'
129 | import * as date from './core/date'
130 | import * as method from './core/method'
131 | import * as math from './core/math'
132 | import * as url from './core/url'
133 | import * as uuid from './core/uuid'
134 | import * as lodash from './core/lodash-tool'
135 |  
136 | import { mixin } from './tools/index'
137 | import { Types } from './types'
138 |  
139 | /**
140 |  * @ignore
141 |  */
142 | function initUtils(): Types {
143 |   const instance: object = Object.create(null)
144 |   console.log(lodash, 'lodash=======', index)
145 |   const arr: Array<any> = [index, verify, format, is, date, method, math, url, uuid, lodash]
146 |  
147 |   mixin(instance, arr)
148 |  
149 |   return instance as Types
150 | }
151 |  
152 | /**
153 |  * @ignore
154 |  */
155 | const _utils = initUtils()
156 |  
157 | export default _utils
158 |  
159 | 160 |
161 |
162 | 167 | 168 | 169 | 174 | 175 | 176 | 177 | 178 | -------------------------------------------------------------------------------- /coverage/lcov-report/src/tools/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Code coverage report for src/tools 7 | 8 | 9 | 10 | 11 | 16 | 17 | 18 | 19 |
20 |
21 |

All files src/tools

22 |
23 | 24 |
25 | 100% 26 | Statements 27 | 5/5 28 |
29 | 30 | 31 |
32 | 100% 33 | Branches 34 | 0/0 35 |
36 | 37 | 38 |
39 | 100% 40 | Functions 41 | 3/3 42 |
43 | 44 | 45 |
46 | 100% 47 | Lines 48 | 5/5 49 |
50 | 51 | 52 |
53 |

54 | Press n or j to go to the next uncovered block, b, p or k for the previous block. 55 |

56 |
57 |
58 |
59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 |
FileStatementsBranchesFunctionsLines
index.ts 77 |
78 |
100%5/5100%0/0100%3/3100%5/5
91 |
92 |
93 |
94 | 99 | 100 | 101 | 106 | 107 | 108 | 109 | 110 | -------------------------------------------------------------------------------- /coverage/lcov-report/src/tools/index.ts.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Code coverage report for src/tools/index.ts 7 | 8 | 9 | 10 | 11 | 16 | 17 | 18 | 19 |
20 |
21 |

All files / src/tools index.ts

22 |
23 | 24 |
25 | 100% 26 | Statements 27 | 5/5 28 |
29 | 30 | 31 |
32 | 100% 33 | Branches 34 | 0/0 35 |
36 | 37 | 38 |
39 | 100% 40 | Functions 41 | 3/3 42 |
43 | 44 | 45 |
46 | 100% 47 | Lines 48 | 5/5 49 |
50 | 51 | 52 |
53 |

54 | Press n or j to go to the next uncovered block, b, p or k for the previous block. 55 |

56 |
57 |
58 |

 59 | 
1 60 | 2 61 | 3 62 | 4 63 | 5 64 | 6 65 | 7 66 | 8 67 | 9 68 | 10 69 | 11 70 | 12  71 |   72 |   73 | 10x 74 | 10x 75 | 100x 76 | 910x 77 |   78 |   79 | 10x 80 |   81 |  
/**
 82 |  * @ignore
 83 |  */
 84 | export function mixin<T, U>(to: T, from: Array<U>): T {
 85 |   from.forEach(obj => {
 86 |     Object.getOwnPropertyNames(obj).forEach(key => {
 87 |       to[key] = obj[key]
 88 |     })
 89 |   })
 90 |   return to
 91 | }
 92 |  
93 | 94 |
95 |
96 | 101 | 102 | 103 | 108 | 109 | 110 | 111 | 112 | -------------------------------------------------------------------------------- /dist/types/core/date.d.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | * @ignore 4 | * @return {number} 格式化时间 支持自定义分隔符 5 | * 6 | */ 7 | export declare function formatTime(value: number, format?: string): string; 8 | /** 9 | * 10 | * @ignore 11 | * @return {string} 返回格式化后的时间 12 | * 13 | */ 14 | export declare function formatHourTime(value: number, hasHour?: boolean): string; 15 | /** 16 | * 17 | * @ignore 18 | * @return {number} 返回当前系统时间戳 13位 | 10位 19 | * 20 | */ 21 | export declare function now(long?: boolean): number; 22 | /** 23 | * @ignore 24 | * @description 拷贝日期对象 25 | * 26 | */ 27 | export declare function cloneDate(val: Date): Date; 28 | /** 29 | * @ignore 30 | * @description 因为toIOSString默认转为格林尼治时间,所以在转换之前需要额外加上8个小时 31 | */ 32 | export declare function timeZone(time: Date): Date; 33 | /** 34 | * @ignore 35 | * @description 判断日期格式是否正确,有效返回new date()日期格式, 无效返回当前日期 36 | */ 37 | export declare function formatEffectiveDate(date?: any): Date; 38 | /** 39 | * 40 | * @ignore 41 | * @description 转化时间格式 42 | */ 43 | declare type dateType = Date | string | number; 44 | /** 45 | * 46 | * @ignore 47 | * @description 转化时间格式 48 | */ 49 | export declare function formatDate(d: dateType, type?: string): string; 50 | /** 51 | * @ignore 52 | * @description 与现在时间做比较 53 | */ 54 | export declare function formatTimeCompare(time?: number | string): string | void; 55 | /** 56 | * @ignore 57 | * @description 获取指定日期前后n天的日期,如果没有指定日期,则是当前日期n天的前后 58 | */ 59 | export declare function getDay(addDayCount: number, appointedDate: number | string | Date, type?: string): string; 60 | /** 61 | * @ignore 62 | * @description 获取指定日期前后n个月的日期,如果没有指定日期,则是当前日期的前后n个月 63 | */ 64 | export declare function getMonthDay(monthNum: number, appointedDate: string | number | Date, type?: string): string; 65 | /** 66 | * @ignore 67 | * @description 获取指定日期前后n年的日期,如果没有指定日期,则是当前日期n年的前后 68 | */ 69 | export declare function getYearDay(addYearCount: number, appointedDate: any, type?: string): string; 70 | /** 71 | * @ignore 72 | * @description 将时间戳转换为日期格式 73 | */ 74 | export declare function timestampToTime(timestamp: T): object | T; 75 | /** 76 | * @ignore 77 | * @description: 将时间戳转成指定的格式 78 | */ 79 | export declare function timestampToTimeString(timestamp: string | number, type: string): string; 80 | /** 81 | * @ignore 82 | * @description 将日期转换为时间戳的格式 83 | */ 84 | export declare function timeToTimestamp(time: string): string | number; 85 | /** 86 | * @ignore 87 | * @description 将秒数转为HH:MM:SS格式 88 | */ 89 | export declare function formatSecond(s: number): string; 90 | export {}; 91 | -------------------------------------------------------------------------------- /dist/types/core/format.d.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | * @ignore 4 | * @return {string} 不满两位前位补0 5 | * 6 | */ 7 | export declare function formatAddZero(value: number | string): string; 8 | /** 9 | * 10 | * @ignore 11 | * @return {string} 手机号脱敏处理 12 | * 13 | */ 14 | export declare function dstMobile(mobile: string): string; 15 | /** 16 | * 17 | * @ignore 18 | * @return {number} 最大最小值之间取随机数 19 | * 20 | */ 21 | export declare function random(max: number, min?: number): number; 22 | /** 23 | * 24 | * @ignore 25 | * @return {string} 生产随机手机号 26 | * 27 | */ 28 | export declare function creatMobile(dst?: boolean): string; 29 | /** 30 | * 31 | * @ignore 32 | * @return {number} 格式化手机号格式 132 5555 6666 33 | * 34 | */ 35 | export declare function formatPhone(phone: string): string; 36 | /** 37 | * 38 | * @ignore 39 | * @return {object} 解析url拼接参数 返回一个params 对象 40 | * 41 | */ 42 | export declare function parseParams(value: string): object; 43 | /** 44 | * 45 | * @ignore 46 | * @return {object} 解析params对象返回一个url拼接参数 47 | * 48 | */ 49 | export declare function formatParams(params: any): string; 50 | /** 51 | * @ignore 52 | * @return {object} 十六进制颜色转rgba 53 | */ 54 | export declare function hexToRgba(hex: string, opacity?: number | string): string; 55 | -------------------------------------------------------------------------------- /dist/types/core/index.d.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * @ignore 3 | * @description 解析JSON Object,并加入异常处理 4 | */ 5 | export declare function json(str: string, def?: any): any; 6 | /** 7 | * @ignore 8 | * @description 检测是否是钉钉环境 9 | */ 10 | export declare function isDingTalk(): boolean; 11 | /** 12 | * @ignore 13 | * @description 是否为开发环境 14 | */ 15 | export declare function isDevEnv(): boolean; 16 | /** 17 | * @ignore 18 | * @description 计算字符长度:汉字为1,英文字母为0.5,结果取整 19 | */ 20 | export declare function getByteLen(val: string | undefined | null): number; 21 | /** 22 | * @ignore 23 | * @description 深拷贝 24 | */ 25 | export declare function deepClone(source: any, nullVal?: null | undefined): any; 26 | /** 27 | * @ignore 28 | * @description json 返回指定列 29 | */ 30 | export declare function getParamValues(name: number, arr: Array): Array; 31 | /** 32 | * @ignore 33 | * @description 1和0互相转换,取反函数 34 | */ 35 | export declare function reverseNum(num: number | string): number | void; 36 | /** 37 | * @ignore 38 | * @description 检测对象类型 39 | */ 40 | export declare function getObjectType(obj: any): string; 41 | /** 42 | * @ignore 43 | * @description 对象数组去重 44 | */ 45 | export declare function noRepeatArray(repeatArray: Array, attr: string): any[]; 46 | /** 47 | * @ignore 48 | * @description 判断当前是否在外链表单页面中 49 | */ 50 | export declare function isOuterLinkEnv(): boolean; 51 | /** 52 | * 53 | * @ignore 54 | * @description 获取浏览器信息 55 | */ 56 | export declare function browser(): string; 57 | /** 58 | * @ignore 59 | * @description 是否企微图片 60 | */ 61 | export declare function isWxImg(img: string): string; 62 | /** 63 | * @ignore 64 | * @description 获取图片地址 65 | */ 66 | export declare function thumbnail(img: string | string[], size?: number, oss?: number): string; 67 | /** 68 | * @ignore 69 | * @description 移动端判断是否当前多平台环境 70 | */ 71 | export declare function envInfo(name: string[]): string | undefined; 72 | /** 73 | * @ignore 74 | * @description 判断是否第三方pc端 75 | */ 76 | export declare function isThirdPC(name: string[], inBrowser: boolean): string | undefined; 77 | -------------------------------------------------------------------------------- /dist/types/core/is.d.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * @ignore 3 | * 类型判断方法 4 | */ 5 | /** 6 | * @ignore 7 | */ 8 | export declare function isArray(value: any): value is Array; 9 | /** 10 | * @ignore 11 | */ 12 | export declare function isObject(value: any): value is Record; 13 | /** 14 | * @ignore 15 | */ 16 | export declare function isPlainObject(value: any): value is Record; 17 | /** 18 | * @ignore 19 | */ 20 | export declare function isNum(value: any): value is number; 21 | /** 22 | * @ignore 23 | */ 24 | export declare function isFunc(value: any): value is Function; 25 | /** 26 | * @ignore 27 | */ 28 | export declare function isUndefined(value: any): value is undefined; 29 | /** 30 | * @ignore 31 | */ 32 | export declare function isNull(value: any): value is null; 33 | -------------------------------------------------------------------------------- /dist/types/core/lodash-tool.d.ts: -------------------------------------------------------------------------------- 1 | import _get from 'lodash/get'; 2 | import _map from 'lodash/map'; 3 | import _uniq from 'lodash/uniq'; 4 | import _pick from 'lodash/pick'; 5 | import _omit from 'lodash/omit'; 6 | import _isNaN from 'lodash/isNaN'; 7 | import _property from 'lodash/property'; 8 | import _findIndex from 'lodash/findIndex'; 9 | import _findLastIndex from 'lodash/findLastIndex'; 10 | import _trim from 'lodash/trim'; 11 | import _isEmpty from 'lodash/isEmpty'; 12 | import _isEqual from 'lodash/isEqual'; 13 | import _debounce from 'lodash/debounce'; 14 | import _throttle from 'lodash/throttle'; 15 | import _padStart from 'lodash/padStart'; 16 | import _padEnd from 'lodash/padEnd'; 17 | export { _get, _map, _property, _findIndex, _findLastIndex, _uniq, _pick, _omit, _isNaN, _trim, _isEmpty, _isEqual, _debounce, _throttle, _padStart, _padEnd, }; 18 | -------------------------------------------------------------------------------- /dist/types/core/math.d.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * @ignore 3 | * 加法 4 | */ 5 | export declare function plus(num1: number | string, num2: number | string, n?: number): number | string; 6 | /** 7 | * @ignore 8 | * 减法 9 | */ 10 | export declare function subtract(num1: number | string, num2: number | string, n?: number): number | string; 11 | /** 12 | * @ignore 13 | * 乘法 14 | */ 15 | export declare function multiply(num1: number | string, num2: number | string, n?: number): number | string; 16 | /** 17 | * @ignore 18 | * 除法 19 | */ 20 | export declare function divide(num1: number | string, num2: number | string, n?: number): number | string; 21 | /** 22 | * @ignore 23 | * 科学记数法正常显示 24 | */ 25 | export declare function scientificNumber(num: number | string): number | string; 26 | /** 27 | * @ignore 28 | * @description: 用于资金金额的计算(去除',') 29 | */ 30 | export declare function formatToNumber(num: number | string): number; 31 | /** 32 | * @ignore 33 | * @description 千分符,数字三位一隔开 (1000000 => 1,000,000) 34 | */ 35 | export declare function dealNumber(num: number | string): number | string; 36 | -------------------------------------------------------------------------------- /dist/types/core/method.d.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * @ignore 3 | * 方法类 4 | */ 5 | /** 6 | * @ignore 7 | * 防抖函数 8 | * 默认调用在防抖开始后 9 | */ 10 | export declare function debounce(fn: any, delay?: number, option?: {}): import("lodash").DebouncedFunc; 11 | /** 12 | * @ignore 13 | * 防抖装饰器 14 | * 默认调用在防抖开始后 15 | */ 16 | export declare function debounceWrap(delay?: number, option?: {}): (target: any, propertyKey: string, descriptor: PropertyDescriptor) => PropertyDescriptor; 17 | /** 18 | * @ignore 19 | * 节流函数 20 | * 默认调用在节流开始前 21 | */ 22 | export declare function throttle(fn: any, delay?: number, option?: {}): import("lodash").DebouncedFunc; 23 | /** 24 | * @ignore 25 | * 节流装饰器 26 | * 默认调用在节流开始前 27 | */ 28 | export declare function throttleWrap(delay?: number, option?: {}): (target: any, propertyKey: string, descriptor: PropertyDescriptor) => PropertyDescriptor; 29 | -------------------------------------------------------------------------------- /dist/types/core/url.d.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | * @ignore 4 | * @return {Array} 过滤出url的非空值 5 | * 6 | */ 7 | export declare function cleanArray(actual: any): Array; 8 | /** 9 | * 10 | * @ignore 11 | * @return {string} 对象转成url的param 12 | * 13 | */ 14 | export declare function param(json: Record): string; 15 | /** 16 | * 17 | * @ignore 18 | * @return {object} 19 | * 20 | */ 21 | /** 22 | * 23 | * @ignore 24 | * @return {object} 解析url中的参数 25 | * 26 | */ 27 | export declare function param2Obj(search: string): Record; 28 | -------------------------------------------------------------------------------- /dist/types/core/uuid.d.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * @ignore 3 | * @description 生成唯一码uuid 4 | */ 5 | export declare function guid(): string; 6 | /** 7 | * @ignore 8 | * @description guid 9 | */ 10 | export declare function getGuid(): string; 11 | -------------------------------------------------------------------------------- /dist/types/core/verify.d.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | * @ignore 4 | * @return {boolean} 判断是否是合法链接 5 | * 6 | */ 7 | export declare function verifyHttp(value: string): boolean; 8 | /** 9 | * 10 | * @ignore 11 | * @return {boolean} 验证合法手机号 12 | * 13 | */ 14 | export declare function verifyMobile(mobile: string): boolean; 15 | /** 16 | * 17 | * @ignore 18 | * @return {boolean} 判断验证码是否6位 19 | * 20 | */ 21 | export declare function verifyCode(code: string): boolean; 22 | /** 23 | * 24 | * @ignore 25 | * @return {boolean} 验证是否是合法邮箱格式 26 | * 27 | */ 28 | export declare function verifyEmail(email: string): boolean; 29 | -------------------------------------------------------------------------------- /dist/types/enum/system.d.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * @ignore 3 | * @description 多平台枚举 4 | */ 5 | export declare enum System { 6 | 'wx' = "wxwork", 7 | 'h5' = "Html5Plus", 8 | 'lark' = "Lark", 9 | 'dd' = "DingTalk" 10 | } 11 | -------------------------------------------------------------------------------- /dist/types/index.d.ts: -------------------------------------------------------------------------------- 1 | import { Types } from './types'; 2 | /** 3 | * @ignore 4 | */ 5 | declare const _utils: Types; 6 | export default _utils; 7 | -------------------------------------------------------------------------------- /dist/types/tools/index.d.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * @ignore 3 | */ 4 | export declare function mixin(to: T, from: Array): T; 5 | -------------------------------------------------------------------------------- /docs/assets/images/icons.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BestJarvan/utils-tools/7f2402da2fee250ead14ad75c8cf4cd63419a843/docs/assets/images/icons.png -------------------------------------------------------------------------------- /docs/assets/images/icons@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BestJarvan/utils-tools/7f2402da2fee250ead14ad75c8cf4cd63419a843/docs/assets/images/icons@2x.png -------------------------------------------------------------------------------- /docs/assets/images/widgets.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BestJarvan/utils-tools/7f2402da2fee250ead14ad75c8cf4cd63419a843/docs/assets/images/widgets.png -------------------------------------------------------------------------------- /docs/assets/images/widgets@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BestJarvan/utils-tools/7f2402da2fee250ead14ad75c8cf4cd63419a843/docs/assets/images/widgets@2x.png -------------------------------------------------------------------------------- /docs/globals.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | @jarvannnn/utils 7 | 8 | 9 | 10 | 11 | 12 |
13 |
14 |
15 |
16 | 27 |
28 |
29 | Options 30 |
31 |
32 | All 33 |
    34 |
  • Public
  • 35 |
  • Public/Protected
  • 36 |
  • All
  • 37 |
38 |
39 | 40 | 41 | 42 | 43 | 44 | 45 |
46 |
47 | Menu 48 |
49 |
50 |
51 |
52 |
53 |
54 | 59 |

@jarvannnn/utils

60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |

Index

68 |
69 |
70 |
71 |

Interfaces

72 | 84 |
85 |
86 |
87 |
88 |
89 | 132 |
133 |
134 |
135 |
136 |

Legend

137 |
138 |
    139 |
  • Method
  • 140 |
141 |
142 |
143 |
144 |
145 |

Generated using TypeDoc

146 |
147 |
148 | 149 | 150 | -------------------------------------------------------------------------------- /docs/interfaces/uuid.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Uuid | @jarvannnn/utils 7 | 8 | 9 | 10 | 11 | 12 |
13 |
14 |
15 |
16 | 27 |
28 |
29 | Options 30 |
31 |
32 | All 33 |
    34 |
  • Public
  • 35 |
  • Public/Protected
  • 36 |
  • All
  • 37 |
38 |
39 | 40 | 41 | 42 | 43 | 44 | 45 |
46 |
47 | Menu 48 |
49 |
50 |
51 |
52 |
53 |
54 | 62 |

Interface Uuid

63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |

Hierarchy

71 |
    72 |
  • 73 | Uuid 74 |
  • 75 |
76 |
77 |
78 |

Index

79 |
80 |
81 |
82 |

Methods

83 | 87 |
88 |
89 |
90 |
91 |
92 |

Methods

93 |
94 | 95 |

getGuid

96 |
    97 |
  • getGuid(): string
  • 98 |
99 |
    100 |
  • 101 | 106 |
    107 |
    108 |
    description
    109 |

    guid

    110 |
    111 |
    112 |
    113 |

    Returns string

    114 |
  • 115 |
116 |
117 |
118 | 119 |

guid

120 |
    121 |
  • guid(): string
  • 122 |
123 |
    124 |
  • 125 | 130 |
    131 |
    132 |
    description
    133 |

    生成唯一码uuid

    134 |
    135 |
    136 |
    137 |

    Returns string

    138 |

    uuid

    139 |
  • 140 |
141 |
142 |
143 |
144 | 199 |
200 |
201 |
202 |
203 |

Legend

204 |
205 |
    206 |
  • Method
  • 207 |
208 |
209 |
210 |
211 |
212 |

Generated using TypeDoc

213 |
214 |
215 | 216 | 217 | -------------------------------------------------------------------------------- /gulpfile.js: -------------------------------------------------------------------------------- 1 | const gulp = require('gulp') 2 | const del = require('del') 3 | const rollup = require('rollup') 4 | const json = require('rollup-plugin-json') 5 | const commonjs = require('rollup-plugin-commonjs') 6 | const resolve = require('rollup-plugin-node-resolve') 7 | const sourceMaps = require('rollup-plugin-sourcemaps') 8 | const typescript = require('rollup-plugin-typescript2') 9 | const uglify = require('rollup-plugin-uglify').uglify 10 | const pkg = require('./package.json') 11 | 12 | function task_clean (done) { 13 | del.sync('dist') 14 | del.sync('docs') 15 | done() 16 | } 17 | 18 | async function task_ts () { 19 | const bundle = await rollup.rollup({ 20 | input: 'src/index.ts', 21 | plugins: [ 22 | json(), 23 | // Compile TypeScript files 24 | typescript({ useTsconfigDeclarationDir: true }), 25 | // Allow bundling cjs modules (unlike webpack, rollup doesn't understand cjs) 26 | commonjs(), 27 | // Allow node_modules resolution, so you can use 'external' to control 28 | // which external modules to include in the bundle 29 | // https://github.com/rollup/rollup-plugin-node-resolve#usage 30 | resolve(), 31 | 32 | // Resolve source maps to the original source 33 | sourceMaps(), 34 | uglify(), 35 | ], 36 | external: ['lodash'] 37 | }); 38 | 39 | await bundle.write({ 40 | file: pkg.main, 41 | format: 'umd', 42 | name: pkg.name, 43 | sourcemap: false, 44 | globals: { 45 | lodash: 'lodash', 46 | } 47 | }) 48 | } 49 | 50 | gulp.task('default', 51 | gulp.parallel( 52 | task_clean, 53 | task_ts 54 | ) 55 | ) 56 | 57 | -------------------------------------------------------------------------------- /home/App.vue: -------------------------------------------------------------------------------- 1 | 7 | 8 | 50 | 51 | 61 | -------------------------------------------------------------------------------- /home/assets/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BestJarvan/utils-tools/7f2402da2fee250ead14ad75c8cf4cd63419a843/home/assets/logo.png -------------------------------------------------------------------------------- /home/components/HelloWorld.vue: -------------------------------------------------------------------------------- 1 | 33 | 34 | 42 | 43 | 44 | 60 | -------------------------------------------------------------------------------- /home/main.ts: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | import App from './App.vue' 3 | 4 | Vue.config.productionTip = false 5 | 6 | new Vue({ 7 | render: h => h(App), 8 | }).$mount('#app') 9 | -------------------------------------------------------------------------------- /home/shims-tsx.d.ts: -------------------------------------------------------------------------------- 1 | import Vue, { VNode } from 'vue' 2 | 3 | declare global { 4 | namespace JSX { 5 | // tslint:disable no-empty-interface 6 | interface Element extends VNode {} 7 | // tslint:disable no-empty-interface 8 | interface ElementClass extends Vue {} 9 | interface IntrinsicElements { 10 | [elem: string]: any 11 | } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /home/shims-vue.d.ts: -------------------------------------------------------------------------------- 1 | declare module '*.vue' { 2 | import Vue from 'vue' 3 | export default Vue 4 | } 5 | -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | index 8 | 22 | 23 | 24 |
25 | 文档 26 | 覆盖率 27 |
28 | 29 | 30 | -------------------------------------------------------------------------------- /jest.config.js: -------------------------------------------------------------------------------- 1 | // preset: 'ts-jest', 2 | module.exports = { 3 | preset: '@vue/cli-plugin-unit-jest/presets/typescript-and-babel', 4 | testEnvironment: 'jsdom', 5 | collectCoverage: true, 6 | globals: { 7 | navigator: { 8 | userAgent: null 9 | } 10 | }, 11 | coveragePathIgnorePatterns: [ 12 | "home", 13 | "node-modules", 14 | "test" 15 | ], 16 | // 全局通过率 17 | coverageThreshold: { 18 | global: { 19 | branches: 100, 20 | functions: 100, 21 | lines: 100, 22 | statements: -5 23 | } 24 | } 25 | }; -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@jarvannnn/utils", 3 | "version": "1.5.0", 4 | "description": "内置工具包", 5 | "author": "蒋亚辉 ", 6 | "scripts": { 7 | "serve": "vue-cli-service serve", 8 | "test": "vue-cli-service test:unit", 9 | "dev-test": "npx jest --watchAll", 10 | "build": "npm run lint && gulp && typedoc", 11 | "lint": "tslint --project tsconfig.json --fix", 12 | "prepare": "husky install" 13 | }, 14 | "main": "dist/index.js", 15 | "module": "dist/index.js", 16 | "license": "MIT", 17 | "files": [ 18 | "dist" 19 | ], 20 | "dependencies": { 21 | "lodash": "^4.17.21" 22 | }, 23 | "devDependencies": { 24 | "@commitlint/cli": "^17.0.2", 25 | "@commitlint/config-conventional": "^17.0.2", 26 | "@types/jest": "^25.2.3", 27 | "@types/lodash": "^4.14.172", 28 | "@types/node": "^17.0.45", 29 | "@types/webpack-env": "^1.18.0", 30 | "@typescript-eslint/eslint-plugin": "^2.33.0", 31 | "@typescript-eslint/parser": "^2.33.0", 32 | "@vue/cli-plugin-babel": "~4.5.0", 33 | "@vue/cli-plugin-eslint": "~4.5.0", 34 | "@vue/cli-plugin-typescript": "~4.5.0", 35 | "@vue/cli-plugin-unit-jest": "^4.5.9", 36 | "@vue/cli-service": "~4.5.0", 37 | "@vue/eslint-config-typescript": "^5.0.2", 38 | "@vue/test-utils": "^1.0.3", 39 | "core-js": "^3.6.5", 40 | "del": "^5.1.0", 41 | "eslint": "^6.8.0", 42 | "eslint-plugin-vue": "^6.2.2", 43 | "gulp": "^4.0.2", 44 | "husky": "^7.0.4", 45 | "jest": "^26.4.0", 46 | "lint-staged": "^10.1.3", 47 | "prettier": "^2.0.4", 48 | "rollup": "^0.67.0", 49 | "rollup-plugin-commonjs": "^9.1.8", 50 | "rollup-plugin-json": "^3.1.0", 51 | "rollup-plugin-node-resolve": "^3.4.0", 52 | "rollup-plugin-sourcemaps": "^0.4.2", 53 | "rollup-plugin-typescript2": "^0.18.0", 54 | "rollup-plugin-uglify": "^6.0.2", 55 | "ts-jest": "^25.4.0", 56 | "tslib": "^2.5.0", 57 | "tslint": "^6.1.1", 58 | "tslint-config-prettier": "^1.18.0", 59 | "tslint-config-standard": "^9.0.0", 60 | "typedoc": "^0.17.8", 61 | "typescript": "^3.9.10", 62 | "vue": "^2.6.11", 63 | "vue-class-component": "^7.2.3", 64 | "vue-property-decorator": "^8.4.2", 65 | "vue-template-compiler": "^2.6.11" 66 | }, 67 | "keywords": [ 68 | "utils", 69 | "tools", 70 | "gulp", 71 | "rollup", 72 | "vue" 73 | ], 74 | "typings": "dist/types/index.d.ts" 75 | } 76 | -------------------------------------------------------------------------------- /public/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BestJarvan/utils-tools/7f2402da2fee250ead14ad75c8cf4cd63419a843/public/favicon.png -------------------------------------------------------------------------------- /public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | <%= htmlWebpackPlugin.options.title %> 9 | 10 | 11 | 14 |
15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /src/core/format.ts: -------------------------------------------------------------------------------- 1 | import { isObject, isUndefined, isNull, isPlainObject } from './is' 2 | /** 3 | * 4 | * @ignore 5 | * @return {string} 不满两位前位补0 6 | * 7 | */ 8 | export function formatAddZero(value: number | string): string { 9 | let str = '' 10 | if (typeof value === 'number') { 11 | str = value.toString() 12 | } else { 13 | str = value 14 | } 15 | return str[1] ? str : `0${str}` 16 | } 17 | 18 | /** 19 | * 20 | * @ignore 21 | * @return {string} 手机号脱敏处理 22 | * 23 | */ 24 | export function dstMobile(mobile: string): string { 25 | return mobile.replace(/(\d{3})\d{4}(\d{0,4})/, '$1****$2') 26 | } 27 | 28 | /** 29 | * 30 | * @ignore 31 | * @return {number} 最大最小值之间取随机数 32 | * 33 | */ 34 | export function random(max: number, min = 0): number { 35 | return Math.floor(Math.random() * (max - min) + min) 36 | } 37 | 38 | /** 39 | * 40 | * @ignore 41 | * @return {string} 生产随机手机号 42 | * 43 | */ 44 | export function creatMobile(dst = false): string { 45 | let mobile = '1' 46 | const middle: number[] = [3, 5, 6, 7, 8, 9] 47 | const len = dst ? '****' : '' + random(9) + random(9) + random(9) + random(9) 48 | mobile = 49 | mobile + 50 | middle[random(middle.length)] + 51 | random(9) + 52 | len + 53 | random(9) + 54 | random(9) + 55 | random(9) + 56 | random(9) 57 | return mobile 58 | } 59 | 60 | /** 61 | * 62 | * @ignore 63 | * @return {number} 格式化手机号格式 132 5555 6666 64 | * 65 | */ 66 | export function formatPhone(phone: string): string { 67 | if (phone.length !== 11) return '' 68 | return phone.substring(0, 3) + ' ' + phone.substring(3, 7) + ' ' + phone.substring(7) 69 | } 70 | 71 | /** 72 | * 73 | * @ignore 74 | * @return {object} 解析url拼接参数 返回一个params 对象 75 | * 76 | */ 77 | export function parseParams(value: string): object { 78 | if (!value || value.indexOf('&') === -1) return {} 79 | 80 | const arr: string[] = value.split('&') 81 | 82 | const params: { 83 | [prop: string]: any 84 | } = {} 85 | 86 | let i = 0 87 | 88 | while (i < arr.length) { 89 | if (arr[i].indexOf('=') !== -1) { 90 | const cur = arr[i].split('=') 91 | params[cur[0]] = cur[1] 92 | } 93 | i++ 94 | } 95 | 96 | return params 97 | } 98 | 99 | /** 100 | * 101 | * @ignore 102 | * @return {object} 解析params对象返回一个url拼接参数 103 | * 104 | */ 105 | export function formatParams(params: any): string { 106 | if (!isPlainObject(params)) return '' 107 | 108 | let str = '' 109 | 110 | const keys: string[] = Object.keys(params) 111 | 112 | for (let i = 0; i < keys.length; i++) { 113 | if (isNull(params[keys[i]]) || isUndefined(params[keys[i]])) { 114 | continue 115 | } 116 | 117 | if (isObject(params[keys[i]])) { 118 | str += `&${keys[i]}=${JSON.stringify(params[keys[i]])}` 119 | } else { 120 | str += `&${keys[i]}=${params[keys[i]]}` 121 | } 122 | } 123 | 124 | return str.length ? '?' + str.substr(1) : str 125 | } 126 | 127 | /** 128 | * @ignore 129 | * @return {object} 十六进制颜色转rgba 130 | */ 131 | export function hexToRgba(hex: string, opacity?: number | string): string { 132 | return ( 133 | 'rgba(' + 134 | parseInt('0x' + hex.slice(1, 3), 16) + 135 | ', ' + 136 | parseInt('0x' + hex.slice(3, 5), 16) + 137 | ', ' + 138 | parseInt('0x' + hex.slice(5, 7), 16) + 139 | ', ' + 140 | (opacity || 1) + 141 | ')' 142 | ) 143 | } 144 | -------------------------------------------------------------------------------- /src/core/index.ts: -------------------------------------------------------------------------------- 1 | import { isArray } from './is' 2 | import { System } from '../enum/system' 3 | /** 4 | * @ignore 5 | * @description 解析JSON Object,并加入异常处理 6 | */ 7 | export function json(str: string, def?: any): any { 8 | try { 9 | return JSON.parse(str) 10 | } catch (e) { 11 | return def || [] 12 | } 13 | } 14 | 15 | /** 16 | * @ignore 17 | * @description 检测是否是钉钉环境 18 | */ 19 | export function isDingTalk(): boolean { 20 | return /DingTalk/i.test(window.navigator.userAgent) 21 | } 22 | 23 | /** 24 | * @ignore 25 | * @description 是否为开发环境 26 | */ 27 | export function isDevEnv(): boolean { 28 | const hostname: string = window.location.hostname 29 | const isLocalhost: boolean = hostname === 'localhost' 30 | const isIp: boolean = /^\d+\.\d+\.\d+\.\d+$/.test(hostname) 31 | return process.env.NODE_ENV === 'development' || isLocalhost || isIp 32 | } 33 | 34 | /** 35 | * @ignore 36 | * @description 计算字符长度:汉字为1,英文字母为0.5,结果取整 37 | */ 38 | export function getByteLen(val: string | undefined | null): number { 39 | if (val !== undefined && val !== null) { 40 | let len = 0 41 | for (const item of val) { 42 | if (item.match(/[^\\x00-\\xff]/gi) !== null) { 43 | len += 1 44 | } else { 45 | len += 0.5 46 | } 47 | } 48 | return Math.floor(len) 49 | } else { 50 | return 0 51 | } 52 | } 53 | /** 54 | * @ignore 55 | */ 56 | const hasOwnProperty = Object.prototype.hasOwnProperty 57 | /** 58 | * @ignore 59 | * @description 深拷贝 60 | */ 61 | export function deepClone(source: any, nullVal?: null | undefined): any { 62 | if (!source || typeof source !== 'object') { 63 | return source 64 | } 65 | const targetObj: object | any[] = source.constructor === Array ? [] : {} 66 | for (const keys in source) { 67 | if (hasOwnProperty.call(source, keys)) { 68 | if (source[keys] && typeof source[keys] === 'object') { 69 | targetObj[keys] = deepClone(source[keys]) 70 | } else { 71 | // 传null防止undefined被过滤 72 | if (nullVal === null) { 73 | targetObj[keys] = source[keys] === undefined ? nullVal : source[keys] 74 | } else { 75 | targetObj[keys] = source[keys] 76 | } 77 | } 78 | } 79 | } 80 | return targetObj 81 | } 82 | 83 | /** 84 | * @ignore 85 | * @description json 返回指定列 86 | */ 87 | export function getParamValues(name: number, arr: Array): Array { 88 | return arr.map(item => item[name]) 89 | } 90 | 91 | /** 92 | * @ignore 93 | * @description 1和0互相转换,取反函数 94 | */ 95 | export function reverseNum(num: number | string): number | void { 96 | const newNum = Number(num) 97 | if (isNaN(newNum)) { 98 | return 99 | } else { 100 | return Math.abs(newNum - 1) 101 | } 102 | } 103 | /** 104 | * @ignore 105 | * @description 检测对象类型 106 | */ 107 | export function getObjectType(obj: any): string { 108 | return Object.prototype.toString.call(obj).slice(8, -1) 109 | } 110 | 111 | /** 112 | * @ignore 113 | * @description 对象数组去重 114 | */ 115 | export function noRepeatArray(repeatArray: Array, attr: string): any[] { 116 | const result: any[] = [] 117 | const repeatObj: object = {} 118 | repeatArray.forEach(item => { 119 | if (!repeatObj[item[attr]]) { 120 | result.push(item) 121 | repeatObj[item[attr]] = true 122 | } 123 | }) 124 | return result 125 | } 126 | 127 | /** 128 | * @ignore 129 | * @description 判断当前是否在外链表单页面中 130 | */ 131 | export function isOuterLinkEnv(): boolean { 132 | const href = window.location.href 133 | return href.indexOf('/outer-form.html#/') >= 0 134 | } 135 | 136 | /** 137 | * 138 | * @ignore 139 | * @description 获取浏览器信息 140 | */ 141 | export function browser(): string { 142 | // 移动终端浏览器版本信息 143 | const u = navigator.userAgent 144 | const ios = !!u.match(/\(i[^;]+;( U;)? CPU.+Mac OS X/) // ios终端 145 | const android = u.indexOf('Android') > -1 || u.indexOf('Linux') > -1 // android终端或者uc浏览器 146 | const pc = /DingTalk/i.test(u) 147 | if (ios) { 148 | return 'ios' 149 | } 150 | if (android) { 151 | return 'Android' 152 | } 153 | if (pc) { 154 | return 'pc' 155 | } 156 | return '' 157 | } 158 | 159 | /** 160 | * @ignore 161 | * @description 是否企微图片 162 | */ 163 | export function isWxImg(img: string): string { 164 | if (img.indexOf('wework.qpic.cn') > -1) return img.slice(0, -1) + '100' 165 | if (/rescdn.qqmail.com|wx.qlogo.cn/.test(img)) return img 166 | return '' 167 | } 168 | /** 169 | * @ignore 170 | */ 171 | type PrivateDeployInfo = { 172 | oss: number 173 | sms: number 174 | } 175 | /** 176 | * @ignore 177 | * @description 获取图片地址 178 | */ 179 | export function thumbnail(img: string | string[], size?: number, oss?: number): string { 180 | let imgUrl: any = isArray(img) && img[0] ? img[0] : img 181 | // 判断imgURL格式 182 | if (!imgUrl || typeof imgUrl !== 'string') return '' 183 | // 企业微信头像的判断 184 | const wxImg: string = isWxImg(imgUrl) 185 | if (wxImg) return wxImg 186 | // 兼容老数据 187 | imgUrl = imgUrl.replace(/\?\d+$/, '') 188 | // 处理 OSS 信息,优先从入参处取,如果入参没有从 LS 里读 189 | const privateDeployObj = window.localStorage.getItem('privateDeployInfo') || '{"oss":1,"sms":1}' 190 | const privateDeployInfo: PrivateDeployInfo = JSON.parse(privateDeployObj) 191 | const ossType: number = oss || privateDeployInfo.oss 192 | const allowHost = ['xbongbong.com', 'dingtalk.com', 'aliyuncs.com'] 193 | // ossType: 1阿里 2minio 3七牛 194 | switch (ossType) { 195 | case 2: 196 | case 4: 197 | // minio 198 | return imgUrl 199 | case 1: 200 | case 3: 201 | default: 202 | // 阿里 oss 和七牛 203 | // 进了这三种情况 还要判断下域名是否是我们的准入域名 204 | if (!allowHost.find(n => imgUrl.indexOf(n) !== -1)) { 205 | return imgUrl 206 | } 207 | // 判断size是否有效 208 | if (!size || ![40, 50, 80, 100, 150, 200, 250, 1080].includes(size)) { 209 | size = 100 210 | } 211 | return `${imgUrl}_${size}x${size}.jpg` 212 | } 213 | } 214 | 215 | /** 216 | * @ignore 217 | * @description 移动端判断是否当前多平台环境 218 | */ 219 | export function envInfo(name: string[]): string | undefined { 220 | const navigator: string = window.navigator.userAgent 221 | return name.find(item => navigator.indexOf(System[item]) > -1) 222 | } 223 | 224 | /** 225 | * @ignore 226 | * @description 判断是否第三方pc端 227 | */ 228 | export function isThirdPC(name: string[], inBrowser: boolean): string | undefined { 229 | let res: string | undefined 230 | const navigator: string = window.navigator.userAgent 231 | // 企微windows容器 不一样 232 | const winPC = navigator.indexOf('wxwork') > -1 ? 'WindowsWechat' : 'Windows' 233 | const regStr = `${winPC}|Macintosh` 234 | const reg = new RegExp(regStr) 235 | const env: string = window.localStorage.getItem('env') || '' 236 | if (reg.test(navigator)) { 237 | res = envInfo(name) 238 | } 239 | // 兼容在外部浏览器的第三方判断 240 | if (inBrowser && name.indexOf(env) > -1) { 241 | res = env 242 | } 243 | return res 244 | } 245 | -------------------------------------------------------------------------------- /src/core/is.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * @ignore 3 | * 类型判断方法 4 | */ 5 | 6 | /** 7 | * @ignore 8 | */ 9 | const toString = Object.prototype.toString 10 | 11 | /** 12 | * @ignore 13 | */ 14 | export function isArray(value: any): value is Array { 15 | return typeof value !== 'undefined' && value instanceof Array 16 | } 17 | 18 | /** 19 | * @ignore 20 | */ 21 | export function isObject(value: any): value is Record { 22 | return value !== null && typeof value === 'object' 23 | } 24 | 25 | /** 26 | * @ignore 27 | */ 28 | export function isPlainObject(value: any): value is Record { 29 | return toString.call(value) === '[object Object]' 30 | } 31 | 32 | /** 33 | * @ignore 34 | */ 35 | export function isNum(value: any): value is number { 36 | return typeof value === 'number' 37 | } 38 | 39 | /** 40 | * @ignore 41 | */ 42 | export function isFunc(value: any): value is Function { 43 | return typeof value === 'function' 44 | } 45 | 46 | /** 47 | * @ignore 48 | */ 49 | export function isUndefined(value: any): value is undefined { 50 | return typeof value === 'undefined' 51 | } 52 | 53 | /** 54 | * @ignore 55 | */ 56 | export function isNull(value: any): value is null { 57 | return value === null 58 | } 59 | -------------------------------------------------------------------------------- /src/core/lodash-tool.ts: -------------------------------------------------------------------------------- 1 | import _get from 'lodash/get' 2 | import _map from 'lodash/map' 3 | import _uniq from 'lodash/uniq' 4 | import _pick from 'lodash/pick' 5 | import _omit from 'lodash/omit' 6 | import _isNaN from 'lodash/isNaN' 7 | import _property from 'lodash/property' 8 | import _findIndex from 'lodash/findIndex' 9 | import _findLastIndex from 'lodash/findLastIndex' 10 | import _trim from 'lodash/trim' 11 | import _isEmpty from 'lodash/isEmpty' 12 | import _isEqual from 'lodash/isEqual' 13 | import _debounce from 'lodash/debounce' 14 | import _throttle from 'lodash/throttle' 15 | import _padStart from 'lodash/padStart' 16 | import _padEnd from 'lodash/padEnd' 17 | 18 | export { 19 | _get, 20 | _map, 21 | _property, 22 | _findIndex, 23 | _findLastIndex, 24 | _uniq, 25 | _pick, 26 | _omit, 27 | _isNaN, 28 | _trim, 29 | _isEmpty, 30 | _isEqual, 31 | _debounce, 32 | _throttle, 33 | _padStart, 34 | _padEnd, 35 | } 36 | -------------------------------------------------------------------------------- /src/core/math.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * @ignore 3 | * 默认精度 4 | */ 5 | const MAX_PRECISION = 6 6 | 7 | /** 8 | * @ignore 9 | */ 10 | interface FormatObj { 11 | max: number 12 | sum: number 13 | sub: number 14 | } 15 | 16 | /** 17 | * @ignore 18 | * 将科学技术法格式化为普通数字字符串 19 | */ 20 | function toNonExponential(num: number | string): string { 21 | num = +num 22 | try { 23 | const m: any = num.toExponential().match(/\d(?:\.(\d*))?e([+-]\d+)/) 24 | return num.toFixed(Math.max(0, (m[1] || '').length - m[2])) 25 | } catch (e) { 26 | return '0' 27 | } 28 | } 29 | 30 | /** 31 | * @ignore 32 | * 计算两位数应该乘以的数,为加减乘数服务的函数 33 | */ 34 | function formatNumber(num1: number | string, num2: number | string): FormatObj { 35 | let r1: number 36 | let r2: number 37 | try { 38 | r1 = toNonExponential(num1).toString().split('.')[1].length 39 | } catch (e) { 40 | r1 = 0 41 | } 42 | try { 43 | r2 = toNonExponential(num2).toString().split('.')[1].length 44 | } catch (e) { 45 | r2 = 0 46 | } 47 | const sum: number = r1 + r2 48 | const sub: number = r2 - r1 49 | return { max: Math.pow(10, Math.max(r1, r2)), sum: Math.pow(10, sum), sub: Math.pow(10, sub) } 50 | } 51 | 52 | /** 53 | * @ignore 54 | * 优化过的toFixed方法 55 | */ 56 | function toFixed(num: number | string, n: number = MAX_PRECISION): number | string { 57 | const realNum: string = toNonExponential(num) 58 | const float: string = toNonExponential(num).toString().split('.')[1] 59 | const len: number = (float && float.length) || 0 60 | if (n >= len) { 61 | return +realNum 62 | } else { 63 | num = +num 64 | const adjust: number = num >= 0 ? 0.5 : -0.5 65 | return parseInt(num * Math.pow(10, n) + adjust + '', 0) / Math.pow(10, n) 66 | } 67 | } 68 | 69 | /** 70 | * @ignore 71 | * 加法 72 | */ 73 | export function plus(num1: number | string, num2: number | string, n?: number): number | string { 74 | num1 = +num1 75 | num2 = +num2 76 | const formatNum: number = formatNumber(num1, num2).max 77 | const result: number = (num1 * formatNum + num2 * formatNum) / formatNum 78 | return toFixed(result, n) 79 | } 80 | 81 | /** 82 | * @ignore 83 | * 减法 84 | */ 85 | export function subtract( 86 | num1: number | string, 87 | num2: number | string, 88 | n?: number 89 | ): number | string { 90 | num1 = +num1 91 | num2 = +num2 92 | const formatNum: number = formatNumber(num1, num2).max 93 | const result: number = (num1 * formatNum - num2 * formatNum) / formatNum 94 | return toFixed(result, n) 95 | } 96 | 97 | /** 98 | * @ignore 99 | * 乘法 100 | */ 101 | export function multiply( 102 | num1: number | string, 103 | num2: number | string, 104 | n?: number 105 | ): number | string { 106 | const sum: number = formatNumber(num1, num2).sum 107 | const s1 = Number(toNonExponential(num1).toString().replace('.', '')) 108 | const s2 = Number(toNonExponential(num2).toString().replace('.', '')) 109 | const result: number = (s1 * s2) / sum 110 | return toFixed(result, n) 111 | } 112 | 113 | /** 114 | * @ignore 115 | * 除法 116 | */ 117 | export function divide(num1: number | string, num2: number | string, n?: number): number | string { 118 | const sub: number = formatNumber(num1, num2).sub 119 | const r1 = Number(toNonExponential(num1).toString().replace('.', '')) 120 | const r2 = Number(toNonExponential(num2).toString().replace('.', '')) 121 | const result: number = (r1 / r2) * sub 122 | return toFixed(result, n) 123 | } 124 | 125 | /** 126 | * @ignore 127 | * 科学记数法正常显示 128 | */ 129 | export function scientificNumber(num: number | string): number | string { 130 | if (!num) return num 131 | const str = num.toString() 132 | const reg = /^(\d+)(\.\d+)?(e)([+]?\d+)$/ 133 | const reg2 = /^(\d+)(\.\d+)?(e)([-]?\d+)$/ 134 | let arr: any 135 | let len: number 136 | let zero = '' 137 | if (reg.test(str)) { 138 | arr = reg.exec(str) 139 | // 保留小数位数 140 | const arr2 = arr[2] ? arr[2].replace('.', '') : '' 141 | // 此处减去arr2的长度为了兼容有小数情况 142 | len = Math.abs(arr[4]) - (arr2.length || 0) 143 | for (let i = 0; i < len; i++) { 144 | zero += '0' 145 | } 146 | return arr[1] + arr2 + zero 147 | } else if (reg2.test(str)) { 148 | arr = reg2.exec(str) 149 | len = Math.abs(arr[4]) - 1 150 | const arr2 = arr[2] ? arr[2].replace('.', '') : '' 151 | for (let index = 0; index < len; index++) { 152 | zero += '0' 153 | } 154 | return '0.' + zero + arr[1] + arr2 155 | } else { 156 | return num 157 | } 158 | } 159 | 160 | /** 161 | * @ignore 162 | * @description: 用于资金金额的计算(去除',') 163 | */ 164 | export function formatToNumber(num: number | string): number { 165 | const v: number | string = Number(String(num).replace(/,/g, '')) 166 | if (isNaN(v)) { 167 | return 0 168 | } else { 169 | return v 170 | } 171 | } 172 | 173 | /** 174 | * @ignore 175 | * @description 千分符,数字三位一隔开 (1000000 => 1,000,000) 176 | */ 177 | export function dealNumber(num: number | string): number | string { 178 | if (num) { 179 | const num2 = String(num) 180 | const left = num2.split('.')[0] 181 | const right = num2.split('.')[1] 182 | return left.replace(/\B(?=(\d{3})+(?!\d))/g, ',') + (right ? '.' + right : '') 183 | } else { 184 | return num 185 | } 186 | } 187 | -------------------------------------------------------------------------------- /src/core/method.ts: -------------------------------------------------------------------------------- 1 | import { _debounce, _throttle } from './lodash-tool' 2 | 3 | /** 4 | * @ignore 5 | * 方法类 6 | */ 7 | 8 | /** 9 | * @ignore 10 | * 防抖函数 11 | * 默认调用在防抖开始后 12 | */ 13 | export function debounce(fn: any, delay = 500, option = {}) { 14 | return _debounce(fn, delay, option) 15 | } 16 | 17 | /** 18 | * @ignore 19 | * 防抖装饰器 20 | * 默认调用在防抖开始后 21 | */ 22 | export function debounceWrap(delay = 500, option = {}) { 23 | return function (target: any, propertyKey: string, descriptor: PropertyDescriptor) { 24 | descriptor.value = _debounce(descriptor.value, delay, option) 25 | return descriptor 26 | } 27 | } 28 | 29 | /** 30 | * @ignore 31 | * 节流函数 32 | * 默认调用在节流开始前 33 | */ 34 | export function throttle(fn: any, delay = 500, option = {}) { 35 | return _throttle(fn, delay, option) 36 | } 37 | 38 | /** 39 | * @ignore 40 | * 节流装饰器 41 | * 默认调用在节流开始前 42 | */ 43 | export function throttleWrap(delay = 500, option = {}) { 44 | return function (target: any, propertyKey: string, descriptor: PropertyDescriptor) { 45 | descriptor.value = _throttle(descriptor.value, delay, option) 46 | return descriptor 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /src/core/url.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | * @ignore 4 | * @return {Array} 过滤出url的非空值 5 | * 6 | */ 7 | export function cleanArray(actual: any): Array { 8 | const newArray: Array = [] 9 | for (let i = 0; i < actual.length; i++) { 10 | if (actual[i]) { 11 | newArray.push(actual[i]) 12 | } 13 | } 14 | return newArray 15 | } 16 | 17 | /** 18 | * 19 | * @ignore 20 | * @return {string} 对象转成url的param 21 | * 22 | */ 23 | export function param(json: Record): string { 24 | if (JSON.stringify(json) === '{}') return '' 25 | return cleanArray( 26 | Object.keys(json).map(key => { 27 | if (json[key] === undefined) return '' 28 | return encodeURIComponent(key) + '=' + encodeURIComponent(json[key]) 29 | }) 30 | ).join('&') 31 | } 32 | 33 | /** 34 | * 35 | * @ignore 36 | * @return {object} 37 | * 38 | */ 39 | 40 | /** 41 | * 42 | * @ignore 43 | * @return {object} 解析url中的参数 44 | * 45 | */ 46 | export function param2Obj(search: string): Record { 47 | const str: string = search || window.location.search 48 | const objURL: object = {} 49 | 50 | str.replace(new RegExp('([^?=&]+)(=([^&]*))?', 'g'), ($0, $1, $2, $3): any => { 51 | // 明明没有返回为啥不能定义成void 52 | objURL[$1] = $3 53 | }) 54 | return objURL 55 | } 56 | -------------------------------------------------------------------------------- /src/core/uuid.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * @ignore 3 | * @description 生成唯一码uuid 4 | */ 5 | export function guid(): string { 6 | // 生成随机码 7 | function S4(): string { 8 | return (((1 + Math.random()) * 0x10000) | 0).toString(16).substring(1) 9 | } 10 | return S4() + S4() + '-' + S4() + '-' + S4() + '-' + S4() + '-' + S4() + S4() + S4() 11 | } 12 | 13 | /** 14 | * @ignore 15 | * @description guid 16 | */ 17 | export function getGuid(): string { 18 | return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, c => { 19 | const r = (Math.random() * 16) | 0 20 | const v = c === 'x' ? r : (r & 0x3) | 0x8 21 | return v.toString(16) 22 | }) 23 | } 24 | -------------------------------------------------------------------------------- /src/core/verify.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | * @ignore 4 | * @return {boolean} 判断是否是合法链接 5 | * 6 | */ 7 | export function verifyHttp(value: string): boolean { 8 | return /^http[s]?:\/\/.*/.test(value.trim()) 9 | } 10 | 11 | /** 12 | * 13 | * @ignore 14 | * @return {boolean} 验证合法手机号 15 | * 16 | */ 17 | export function verifyMobile(mobile: string): boolean { 18 | const reg = /^1[3456789]\d{9}$/ 19 | return reg.test(mobile.trim()) 20 | } 21 | 22 | /** 23 | * 24 | * @ignore 25 | * @return {boolean} 判断验证码是否6位 26 | * 27 | */ 28 | export function verifyCode(code: string): boolean { 29 | const reg = /^\d{6}$/ 30 | return reg.test(code) 31 | } 32 | 33 | /** 34 | * 35 | * @ignore 36 | * @return {boolean} 验证是否是合法邮箱格式 37 | * 38 | */ 39 | export function verifyEmail(email: string): boolean { 40 | const re = /^(([^<>()[\]\\.,;:\s@"]+(\.[^<>()[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/ 41 | return re.test(email.trim()) 42 | } 43 | -------------------------------------------------------------------------------- /src/enum/system.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * @ignore 3 | * @description 多平台枚举 4 | */ 5 | export enum System { 6 | 'wx' = 'wxwork', 7 | 'h5' = 'Html5Plus', 8 | 'lark' = 'Lark', 9 | 'dd' = 'DingTalk', 10 | } 11 | -------------------------------------------------------------------------------- /src/index.ts: -------------------------------------------------------------------------------- 1 | import * as index from './core/index' 2 | import * as verify from './core/verify' 3 | import * as format from './core/format' 4 | import * as is from './core/is' 5 | import * as date from './core/date' 6 | import * as method from './core/method' 7 | import * as math from './core/math' 8 | import * as url from './core/url' 9 | import * as uuid from './core/uuid' 10 | import * as lodash from './core/lodash-tool' 11 | 12 | import { mixin } from './tools/index' 13 | import { Types } from './types' 14 | 15 | /** 16 | * @ignore 17 | */ 18 | function initUtils(): Types { 19 | const instance: object = Object.create(null) 20 | console.log(lodash, 'lodash=======', index) 21 | const arr: Array = [index, verify, format, is, date, method, math, url, uuid, lodash] 22 | 23 | mixin(instance, arr) 24 | 25 | return instance as Types 26 | } 27 | 28 | /** 29 | * @ignore 30 | */ 31 | const _utils = initUtils() 32 | 33 | export default _utils 34 | -------------------------------------------------------------------------------- /src/tools/index.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * @ignore 3 | */ 4 | export function mixin(to: T, from: Array): T { 5 | from.forEach(obj => { 6 | Object.getOwnPropertyNames(obj).forEach(key => { 7 | to[key] = obj[key] 8 | }) 9 | }) 10 | return to 11 | } 12 | -------------------------------------------------------------------------------- /tests/unit/core/date.spec.ts: -------------------------------------------------------------------------------- 1 | import utils from '../../../src/index' 2 | 3 | describe('Date test', () => { 4 | describe('formatTime must return a string date', () => { 5 | it('function formatTime must return a string time with hours, minutes and seconds', () => { 6 | expect(utils.formatTime(1587823200000)).toBe('2020-04-25 22:00:00') 7 | expect(utils.formatTime(1587823200)).toBe('2020-04-25 22:00:00') 8 | }) 9 | it('function formatTime must return a formatted string time', () => { 10 | expect(utils.formatTime(1587823200000, 'yyyy/M/d HH-mm-ss')).toBe('2020/4/25 22-00-00') 11 | expect(utils.formatTime(1587769200000, 'yyyy/M/d hh-mm-ss')).toBe('2020/4/25 07-00-00') 12 | expect(utils.formatTime(1587769200000, 'yyyy/M/d h-mm-ss')).toBe('2020/4/25 7-00-00') 13 | expect(utils.formatTime(1587823200000, 'yyyy/MM/dd')).toBe('2020/04/25') 14 | expect(utils.formatTime(1587823200000, 'yyyy/MM/DD')).toBe('2020/04/06') 15 | expect(utils.formatTime(1587823200000, 'yyyy/M/D')).toBe('2020/4/6') 16 | expect(utils.formatTime(1587823200, 'yyyy/M/d')).toBe('2020/4/25') 17 | expect(utils.formatTime(1587823200, 'yyyy/M/d HH-mm-ss')).toBe('2020/4/25 22-00-00') 18 | expect(utils.formatTime(1587823200, 'yyyy/M/d hh-mm-ss')).toBe('2020/4/25 10-00-00') 19 | expect(utils.formatTime(1587823200, 'yyyy/M/d H:m:s')).toBe('2020/4/25 22:0:0') 20 | expect(utils.formatTime(1587823200, 'yyyyy/MMM/ddd H:m:s')).toBe('2020y/M/d 22:0:0') 21 | expect(utils.formatTime(1587769200, 'yy/M/d hh:m:s')).toBe('20/4/25 07:0:0') 22 | expect(utils.formatTime(1587769200, 'h-m:s')).toBe('7-0:0') 23 | expect(utils.formatTime(1587769200, 'hh-m:s')).toBe('07-0:0') 24 | expect(utils.formatTime(1587787200, 'h-m:s')).toBe('12-0:0') 25 | expect(utils.formatTime(1587787200, 'hh-m:s')).toBe('12-0:0') 26 | expect(utils.formatTime(1588903200, 'h A')).toBe('10 AM') 27 | expect(utils.formatTime(1588903200, 'h a')).toBe('10 am') 28 | expect(utils.formatTime(1588917600, 'h A')).toBe('2 PM') 29 | expect(utils.formatTime(1588917600, 'h a')).toBe('2 pm') 30 | }) 31 | }) 32 | 33 | describe('formatHourTime must return a string date', () => { 34 | it('function formatHourTime must return a time with hours, minutes and seconds', () => { 35 | expect(utils.formatHourTime(1587823200000, true)).toBe('2020-04-25 22:00:00') 36 | expect(utils.formatHourTime(1587823200, true)).toBe('2020-04-25 22:00:00') 37 | }) 38 | it('function formatHourTime must return a time without hours, minutes and seconds', () => { 39 | expect(utils.formatHourTime(1587823200000)).toBe('2020-04-25') 40 | expect(utils.formatHourTime(1587823200)).toBe('2020-04-25') 41 | }) 42 | }) 43 | 44 | describe('now must return a string date', () => { 45 | it('function now must return a 10-length string time', () => { 46 | expect(utils.now().toString()).toMatch(/^\d{10}$/) 47 | }) 48 | 49 | it('function now must return a 13-length string time', () => { 50 | expect(utils.now(true).toString()).toMatch(/^\d{13}$/) 51 | }) 52 | }) 53 | 54 | test('拷贝日期对象', () => { 55 | const n = new Date('2012-12-14') 56 | expect(utils.cloneDate(n).getTime()).toBe(n.getTime()) 57 | }) 58 | 59 | test('因为toIOSString默认转为格林尼治时间,所以在转换之前需要额外加上8个小时', () => { 60 | const n = new Date('2014.4.5') 61 | expect(utils.timeZone(n)).toEqual(new Date(new Date('2014.4.5').getTime() + 28800000)) 62 | }) 63 | 64 | test('判断日期格式是否正确,有效返回new date()日期格式,无效返回当前日期', () => { 65 | expect(utils.formatEffectiveDate(11).getTime()).toBeLessThanOrEqual(new Date().getTime()) 66 | expect(utils.formatEffectiveDate(1555599999)).toEqual(new Date(1555599999000)) 67 | expect(utils.formatEffectiveDate().getTime()).toBeLessThanOrEqual(new Date().getTime()) 68 | expect(utils.formatEffectiveDate({})).toBeTruthy() 69 | expect(utils.formatEffectiveDate({ length: 2 })).toEqual(new Date()) 70 | expect(Math.floor(utils.formatEffectiveDate('').getTime() / 1000)).toBe( 71 | Math.floor(new Date().getTime() / 1000) 72 | ) 73 | expect(utils.formatEffectiveDate('2012.4.6')).toEqual(new Date('2012.4.6')) 74 | expect(utils.formatEffectiveDate('20012.4.6').getTime()).toBeLessThanOrEqual( 75 | new Date().getTime() 76 | ) 77 | }) 78 | 79 | test('格式化时间', () => { 80 | expect(utils.formatDate('2021-12-12')).toBe( 81 | utils.timeZone(utils.formatEffectiveDate('2021-12-12')).toISOString().slice(0, 10) 82 | ) 83 | expect(utils.formatDate(1555599999, 'datetime')).toBe( 84 | utils 85 | .timeZone(utils.formatEffectiveDate(1555599999)) 86 | .toISOString() 87 | .substring(0, 16) 88 | .replace('T', ' ') 89 | ) 90 | expect(utils.formatDate(1555599999, 'seconds')).toBe( 91 | utils 92 | .timeZone(utils.formatEffectiveDate(1555599999)) 93 | .toISOString() 94 | .substring(0, 19) 95 | .replace('T', ' ') 96 | .substring(11, 19) 97 | ) 98 | expect(utils.formatDate('2014.4.1', 'datetime')).toBeTruthy() 99 | expect(utils.formatDate('2014.4.1', 'seconds')).toBeTruthy() 100 | expect(utils.formatDate(new Date('2015.6.4'), 'datetime')).toBe( 101 | utils 102 | .timeZone(utils.formatEffectiveDate(new Date('2015.6.4'))) 103 | .toISOString() 104 | .substring(0, 16) 105 | .replace('T', ' ') 106 | ) 107 | expect(utils.formatDate(new Date('2015.6.4'), 'seconds')).toBeTruthy() 108 | }) 109 | 110 | test('与现在时间作比较', () => { 111 | expect(utils.formatTimeCompare()).toBeFalsy() 112 | expect( 113 | utils.formatTimeCompare(parseInt(`${new Date('2021.3.16').getTime() / 1000}`)) 114 | ).not.toBeFalsy() 115 | expect(utils.formatTimeCompare(parseInt(`${new Date().getTime() / 1000}`))).toBe('刚刚') 116 | expect(utils.formatTimeCompare(parseInt(`${new Date().getTime() / 1000 - 1000}`))).toBe( 117 | '16分钟前' 118 | ) 119 | expect(utils.formatTimeCompare(parseInt(`${new Date().getTime() / 1000 - 10000}`))).toBe( 120 | '2小时前' 121 | ) 122 | expect( 123 | utils.formatTimeCompare(parseInt(`${new Date('2021.3.17 1:57').getTime() / 1000}`)) 124 | ).toBe('2021-03-17 01:57') 125 | expect( 126 | utils.formatTimeCompare(parseInt(`${new Date().getTime() / 1000 + 43200000}`)) 127 | ).toBeTruthy() 128 | expect(utils.formatTimeCompare(parseInt(`${new Date().getTime() / 1000 + 1000}`))).toBeTruthy() 129 | expect( 130 | utils.formatTimeCompare(parseInt(`${new Date('2021.3.01 11:00').getTime() / 1000}`)) 131 | ).toBe('2021-03-01 11:00') 132 | }) 133 | 134 | test('获取指定日期前后n天的日期,如果没有指定日期,则是当前日期n天的前后', () => { 135 | expect(utils.getDay(2, '2014.12.4')).toBe('2014-12-06') 136 | expect(utils.getDay(2, '2014.12.4', 'datetime')).toBe('2014-12-06 00:00') 137 | }) 138 | 139 | test('获取指定日期前后n个月的日期,如果没有指定日期,则是当前日期的前后n个月', () => { 140 | expect(utils.getMonthDay(1, '2019.12.7')).toBe('2020-01-07') 141 | expect(utils.getMonthDay(11, '2019.7.31')).toBe('2020-06-30') 142 | expect(utils.getMonthDay(1, '2019.1.7')).toBe('2019-02-07') 143 | expect(utils.getMonthDay(-3, '2021.1.7')).toBe('2020-10-07') 144 | expect(utils.getMonthDay(1, '2019.12.7', 'datetime')).toBe('2020-01-07 00:00') 145 | }) 146 | 147 | test('获取指定日期前后n年的日期,如果没有指定日期,则是当前日期n年的前后', () => { 148 | expect(utils.getYearDay(2, '2021.3.17')).toBe('2023-03-17') 149 | expect(utils.getYearDay(2, '2021.3.17', 'datetime')).toBe('2023-03-17 00:00') 150 | }) 151 | 152 | test('将时间戳转换为日期格式', () => { 153 | expect(utils.timestampToTime(new Date('2021.3.8').getTime())).toEqual({ 154 | year: 2021, 155 | month: '03', 156 | day: '08', 157 | hours: '00', 158 | minutes: '00', 159 | }) 160 | expect(utils.timestampToTime(new Date('2021.3.16 15:14').getTime())).toEqual({ 161 | year: 2021, 162 | month: '03', 163 | day: 16, 164 | hours: 15, 165 | minutes: 14, 166 | }) 167 | expect(utils.timestampToTime(new Date('2021.10.16').getTime())).toEqual({ 168 | year: 2021, 169 | month: 10, 170 | day: 16, 171 | hours: '00', 172 | minutes: '00', 173 | }) 174 | expect(utils.timestampToTime(new Date('2021.3.16').getTime().toString().slice(0, 10))).toEqual({ 175 | year: 2021, 176 | month: '03', 177 | day: 16, 178 | hours: '00', 179 | minutes: '00', 180 | }) 181 | expect(utils.timestampToTime('dsad')).toBe('dsad') 182 | }) 183 | 184 | test('将时间戳转成指定的格式', () => { 185 | expect(utils.timestampToTimeString(new Date('2021.3.16').getTime(), 'yyyy-MM-dd')).toBe( 186 | '2021-03-16' 187 | ) 188 | expect(utils.timestampToTimeString(new Date('2021.3.16').getTime(), 'yyyy-MM-dd HH:mm')).toBe( 189 | '2021-03-16 00:00' 190 | ) 191 | }) 192 | 193 | test('将日期转换为时间戳的格式', () => { 194 | expect(utils.timeToTimestamp(new Date('2021.3.16').getTime().toString())).toBe( 195 | new Date('2021.3.16').getTime().toString() 196 | ) 197 | expect(utils.timeToTimestamp('2021.3.16')).toBe(Date.parse('2021.3.16') / 1000) 198 | expect(utils.timeToTimestamp('')).toBe('') 199 | }) 200 | 201 | test('将秒数转为HH:MM:SS格式', () => { 202 | expect(utils.formatSecond(10)).toBe('00:00:10') 203 | expect(utils.formatSecond(60)).toBe('00:01:00') 204 | expect(utils.formatSecond(3000)).toBe('00:50:00') 205 | expect(utils.formatSecond(3600)).toBe('01:00:00') 206 | expect(utils.formatSecond(4215)).toBe('01:10:15') 207 | expect(utils.formatSecond(3660)).toBe('01:01:00') 208 | expect(utils.formatSecond(3670)).toBe('01:01:10') 209 | expect(utils.formatSecond(3610)).toBe('01:00:10') 210 | }) 211 | }) 212 | -------------------------------------------------------------------------------- /tests/unit/core/format.spec.ts: -------------------------------------------------------------------------------- 1 | import utils from '../../../src/index' 2 | 3 | describe('Format test', () => { 4 | test('formatAddZero must return a string', () => { 5 | expect(utils.formatAddZero(1)).toBe('01') 6 | expect(utils.formatAddZero('1')).toBe('01') 7 | expect(utils.formatAddZero(11)).toBe('11') 8 | }) 9 | 10 | test('dstMobile must return a string', () => { 11 | expect(utils.dstMobile('13233334444')).toBe('132****4444') 12 | }) 13 | 14 | test('creatMobile must return a string', () => { 15 | expect(utils.creatMobile()).toMatch(/^1[3456789]\d{9}$/) 16 | expect(utils.creatMobile(true)).toMatch(/(\d{3})\*{4}(\d{4})/) 17 | }) 18 | 19 | test('random must return a number', () => { 20 | const resolve: number = utils.random(9) 21 | expect(resolve >= 0 && resolve < 9).toBeTruthy() 22 | expect(resolve >= 9).toBeFalsy() 23 | 24 | const resolve2: number = utils.random(6, 2) 25 | expect(resolve2 >= 2 && resolve2 < 6).toBeTruthy() 26 | expect(resolve2 >= 6).toBeFalsy() 27 | }) 28 | 29 | test('formatPhone must return a string', () => { 30 | expect(utils.formatPhone('13233334444')).toBe('132 3333 4444') 31 | expect(utils.formatPhone('132333344')).toBe('') 32 | }) 33 | 34 | test('parseParams must return a object', () => { 35 | expect(typeof utils.parseParams('a=1')).toBe('object') 36 | expect(utils.parseParams('1')).toEqual({}) 37 | expect(utils.parseParams('id=1&page=2&pageSize=20')).toEqual({ 38 | id: '1', 39 | page: '2', 40 | pageSize: '20', 41 | }) 42 | expect(utils.parseParams('a=1&b=2&c')).toEqual({ 43 | a: '1', 44 | b: '2', 45 | }) 46 | }) 47 | 48 | test('formatParams must return a string', () => { 49 | expect(utils.formatParams({ id: 1, page: 2, pageSize: 20 })).toBe('?id=1&page=2&pageSize=20') 50 | expect(utils.formatParams('1')).toBe('') 51 | expect(utils.formatParams({ c: null, d: undefined })).toBe('') 52 | expect(utils.formatParams({ id: 1, page: { num: 1, size: 20 } })).toBe( 53 | '?id=1&page={"num":1,"size":20}' 54 | ) 55 | }) 56 | 57 | test('hexToRgba must return a string', () => { 58 | expect(utils.hexToRgba('#3399ff')).toBe('rgba(51, 153, 255, 1)') 59 | expect(utils.hexToRgba('#00965e', 0.5)).toBe('rgba(0, 150, 94, 0.5)') 60 | expect(utils.hexToRgba('#00965e', '0.5')).toBe('rgba(0, 150, 94, 0.5)') 61 | expect(utils.hexToRgba('#00965e', '1')).toBe('rgba(0, 150, 94, 1)') 62 | expect(utils.hexToRgba('#3399ff', '1')).toBe('rgba(51, 153, 255, 1)') 63 | }) 64 | }) 65 | -------------------------------------------------------------------------------- /tests/unit/core/index.spec.ts: -------------------------------------------------------------------------------- 1 | import utils from '../../../src/index' 2 | 3 | Object.defineProperty(window, 'location', { 4 | value: { 5 | hostname: '192.168.1.1', 6 | href: '123', 7 | }, 8 | }) 9 | 10 | // Storage Mock 11 | function storageMock() { 12 | const storage = {} 13 | 14 | return { 15 | setItem: function (key, value) { 16 | storage[key] = value || '' 17 | }, 18 | getItem: function (key) { 19 | return key in storage ? storage[key] : null 20 | }, 21 | removeItem: function (key) { 22 | delete storage[key] 23 | }, 24 | get length() { 25 | return Object.keys(storage).length 26 | }, 27 | key: function (i) { 28 | const keys = Object.keys(storage) 29 | return keys[i] || null 30 | }, 31 | } 32 | } 33 | Object.defineProperty(window, 'localStorage', { 34 | writable: true, 35 | value: storageMock(), 36 | }) 37 | 38 | describe('Index test', () => { 39 | test('json must be a string, def is not required', () => { 40 | expect(utils.json('{"password":"123456","username":"张三"}', {})).toEqual({ 41 | password: '123456', 42 | username: '张三', 43 | }) 44 | expect(utils.json('{"password":"123456","username":"张三"}')).toEqual({ 45 | password: '123456', 46 | username: '张三', 47 | }) 48 | expect(utils.json('{"neme":4}')).toEqual({ neme: 4 }) 49 | expect(utils.json('aa', 11)).toBe(11) 50 | expect(utils.json('aa')).not.toBeFalsy() 51 | }) 52 | 53 | test('检测是否是钉钉环境', () => { 54 | expect(utils.isDingTalk()).toBeFalsy() 55 | }) 56 | 57 | test('是否为开发环境', () => { 58 | expect(utils.isDevEnv()).toBeTruthy() 59 | expect(utils.isDevEnv()).toBeTruthy() 60 | }) 61 | 62 | test('计算字符长度:汉字为1,英文字母为0.5,结果取整', () => { 63 | expect(utils.getByteLen('哈哈哈')).toBe(3) 64 | expect(utils.getByteLen('aa')).toBe(1) 65 | expect(utils.getByteLen(undefined)).toBe(0) 66 | }) 67 | 68 | test('深拷贝', () => { 69 | expect(utils.deepClone([{ name: 1 }])).toContainEqual({ name: 1 }) 70 | expect(utils.deepClone(1)).toBe(1) 71 | expect(utils.deepClone([{ name: 1 }, 2, undefined, null], null)).toEqual([ 72 | { name: 1 }, 73 | 2, 74 | null, 75 | null, 76 | ]) 77 | expect(utils.deepClone('121221')).toBe('121221') 78 | expect(utils.deepClone({ arr: [1] })).toEqual({ arr: [1] }) 79 | expect(utils.deepClone({ a: undefined, b: null }, null)).toEqual({ a: null, b: null }) 80 | const obj = Object.create({ a: 1 }) 81 | Object.defineProperty(obj, 'c', { 82 | writable: false, 83 | value: 2, 84 | }) 85 | expect(utils.deepClone(obj)).toEqual({}) 86 | }) 87 | 88 | test('json返回指定列', () => { 89 | expect( 90 | utils.getParamValues(2, [ 91 | [1, 2, 3], 92 | [2, 4, 6], 93 | ]) 94 | ).toContain(3) 95 | }) 96 | 97 | test('1和0互相转换,取反函数', () => { 98 | expect(utils.reverseNum(1)).toBe(0) 99 | expect(utils.reverseNum(0)).toBe(1) 100 | expect(utils.reverseNum('a')).toBeUndefined() 101 | }) 102 | 103 | test('对象数组去重', () => { 104 | expect( 105 | utils.noRepeatArray( 106 | [ 107 | { name: '24', id: 1, status: 'success' }, 108 | { name: '张三', id: 2, status: 'success' }, 109 | { name: '李四', id: 1, status: 'false' }, 110 | ], 111 | 'id' 112 | ) 113 | ).toMatchObject([ 114 | { name: '24', id: 1, status: 'success' }, 115 | { name: '张三', id: 2, status: 'success' }, 116 | ]) 117 | expect(utils.noRepeatArray([], 'id')).toMatchObject([]) 118 | }) 119 | 120 | test('检测对象类型', () => { 121 | expect(utils.getObjectType('我是一个字符串')).toBe('String') 122 | expect(utils.getObjectType(1314)).toBe('Number') 123 | expect(utils.getObjectType(true)).toBe('Boolean') 124 | expect(utils.getObjectType({ name: '张三', age: 18 })).toBe('Object') 125 | expect(utils.getObjectType([13, 324, 56])).toBe('Array') 126 | }) 127 | 128 | test('判断当前是否在外链表单页面中', () => { 129 | expect(utils.isOuterLinkEnv()).toBeFalsy() 130 | }) 131 | test('判断系统内核', () => { 132 | Object.defineProperty(navigator, 'userAgent', { 133 | writable: true, 134 | value: 135 | 'Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.75 Mobile Safari/537.36', 136 | }) 137 | expect(utils.browser()).toBe('Android') 138 | // @ts-ignore 139 | window.navigator.userAgent = 140 | 'Mozilla/5.0 (iPhone; CPU iPhone OS 10_3_1 like Mac OS X) AppleWebKit/603.1.30 (KHTML, like Gecko) Version/10.0 Mobile/14E304 Safari/602.1' 141 | expect(utils.browser()).toBe('ios') 142 | // @ts-ignore 143 | window.navigator.userAgent = 'DingTalk' 144 | expect(utils.browser()).toBe('pc') 145 | // @ts-ignore 146 | window.navigator.userAgent = '' 147 | expect(utils.browser()).toBe('') 148 | }) 149 | test('获取图片地址', () => { 150 | expect(utils.thumbnail('', 40)).toBe('') 151 | expect(utils.thumbnail('dingtalk.com/123.jpg?1123131', 90, 1)).toBe( 152 | 'dingtalk.com/123.jpg_100x100.jpg' 153 | ) 154 | expect(utils.thumbnail(['xbongbong.com/123.jpg?1123131'], 80, 1)).toBe( 155 | 'xbongbong.com/123.jpg_80x80.jpg' 156 | ) 157 | expect(utils.thumbnail(['aaa?1123131'], 80, 2)).toBe('aaa') 158 | expect(utils.thumbnail(['aaa?1123131'], 1080, 2)).toBe('aaa') 159 | // @ts-ignore 160 | window.localStorage.setItem('privateDeployInfo', '{"oss":3,"sms":1}') 161 | expect( 162 | utils.thumbnail( 163 | 'https://wework.qpic.cn/bizmail/nfSKvz2M9u2KzuCZG068h5mT4h8iaeia0RbT8IslibwwGjOoWj0XhQrsg/0', 164 | 40 165 | ) 166 | ).toBe( 167 | 'https://wework.qpic.cn/bizmail/nfSKvz2M9u2KzuCZG068h5mT4h8iaeia0RbT8IslibwwGjOoWj0XhQrsg/100' 168 | ) 169 | expect( 170 | utils.thumbnail( 171 | [ 172 | 'https://rescdn.qqmail.com/node/wwmng/wwmng/style/images/independent/DefaultAvatar$73ba92b5.png', 173 | ], 174 | 40 175 | ) 176 | ).toBe( 177 | 'https://rescdn.qqmail.com/node/wwmng/wwmng/style/images/independent/DefaultAvatar$73ba92b5.png' 178 | ) 179 | expect(utils.thumbnail(['https://baidu.com/logo.png'], 80)).toBe('https://baidu.com/logo.png') 180 | }) 181 | 182 | test('将秒数转为HH:MM:SS格式', () => { 183 | expect(utils.formatSecond(10)).toBe('00:00:10') 184 | expect(utils.formatSecond(60)).toBe('00:01:00') 185 | expect(utils.formatSecond(3000)).toBe('00:50:00') 186 | expect(utils.formatSecond(3600)).toBe('01:00:00') 187 | expect(utils.formatSecond(4215)).toBe('01:10:15') 188 | expect(utils.formatSecond(3660)).toBe('01:01:00') 189 | expect(utils.formatSecond(3670)).toBe('01:01:10') 190 | expect(utils.formatSecond(3610)).toBe('01:00:10') 191 | }) 192 | 193 | test('移动端判断是否当前多平台环境', () => { 194 | // @ts-ignore 195 | window.navigator.userAgent = 196 | 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) wxwork Chrome/93.0.4577.63 Safari/537.36' 197 | expect(utils.envInfo(['wx', 'lark'])).toBe('wx') 198 | // @ts-ignore 199 | window.navigator.userAgent = 200 | 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) DingTalk Chrome/93.0.4577.63 Safari/537.36' 201 | expect(utils.envInfo(['dd'])).toBe('dd') 202 | // @ts-ignore 203 | window.navigator.userAgent = 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) ' 204 | expect(utils.envInfo(['123'])).toBeUndefined() 205 | }) 206 | 207 | test('判断是否第三方pc端', () => { 208 | // @ts-ignore 209 | window.navigator.userAgent = 210 | 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) wxwork Chrome/93.0.4577.63 Safari/537.36' 211 | expect(utils.isThirdPC(['wx'], false)).toBe('wx') 212 | // @ts-ignore 213 | window.navigator.userAgent = 214 | 'Mozilla/5.0 (WindowsWechat; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) wxwork/3.1.12 (MicroMessenger/6.2) WeChat/2.0.4' 215 | expect(utils.isThirdPC(['wx'], false)).toBe('wx') 216 | // @ts-ignore 217 | window.localStorage.setItem('env', 'lark') 218 | // @ts-ignore 219 | window.navigator.userAgent = '' 220 | expect(utils.isThirdPC(['lark'], true)).toBe('lark') 221 | // @ts-ignore 222 | window.localStorage.setItem('env', 'wx') 223 | expect(utils.isThirdPC(['wx'], false)).toBeUndefined() 224 | expect(utils.isThirdPC(['wx'], true)).toBe('wx') 225 | expect(utils.isThirdPC(['lark'], true)).toBeUndefined() 226 | window.localStorage.setItem('env', '') 227 | expect(utils.isThirdPC(['lark'], true)).toBeUndefined() 228 | }) 229 | 230 | test('是否企微图片', () => { 231 | expect( 232 | utils.isWxImg( 233 | 'https://wework.qpic.cn/bizmail/nfSKvz2M9u2KzuCZG068h5mT4h8iaeia0RbT8IslibwwGjOoWj0XhQrsg/0' 234 | ) 235 | ).toBe( 236 | 'https://wework.qpic.cn/bizmail/nfSKvz2M9u2KzuCZG068h5mT4h8iaeia0RbT8IslibwwGjOoWj0XhQrsg/100' 237 | ) 238 | expect( 239 | utils.isWxImg( 240 | 'https://rescdn.qqmail.com/node/wwmng/wwmng/style/images/independent/DefaultAvatar$73ba92b5.png' 241 | ) 242 | ).toBe( 243 | 'https://rescdn.qqmail.com/node/wwmng/wwmng/style/images/independent/DefaultAvatar$73ba92b5.png' 244 | ) 245 | }) 246 | }) 247 | -------------------------------------------------------------------------------- /tests/unit/core/is.spec.ts: -------------------------------------------------------------------------------- 1 | import utils from '../../../src/index' 2 | 3 | describe('Is test', () => { 4 | test('isArray must return a boolean', () => { 5 | expect(utils.isArray([])).toBeTruthy() 6 | expect(utils.isArray(1)).toBeFalsy() 7 | }) 8 | 9 | test('isObject must return a boolean', () => { 10 | expect(utils.isObject([])).toBeTruthy() 11 | expect(utils.isObject({})).toBeTruthy() 12 | expect(utils.isObject(1)).toBeFalsy() 13 | expect(utils.isObject('1')).toBeFalsy() 14 | }) 15 | 16 | test('isPlainObject must return a boolean', () => { 17 | expect(utils.isPlainObject({})).toBeTruthy() 18 | expect(utils.isPlainObject([])).toBeFalsy() 19 | expect(utils.isPlainObject(null)).toBeFalsy() 20 | expect(utils.isPlainObject(1)).toBeFalsy() 21 | expect(utils.isPlainObject('1')).toBeFalsy() 22 | }) 23 | 24 | test('isNum must return a boolean', () => { 25 | expect(utils.isNum(1)).toBeTruthy() 26 | expect(utils.isNum('1')).toBeFalsy() 27 | }) 28 | 29 | test('isFunc must return a boolean', () => { 30 | function test() { 31 | return 1 32 | } 33 | expect(utils.isFunc(test)).toBeTruthy() 34 | expect(utils.isFunc('1')).toBeFalsy() 35 | }) 36 | 37 | test('isUndefined must return a boolean', () => { 38 | expect(utils.isUndefined(undefined)).toBeTruthy() 39 | expect(utils.isUndefined('undefined')).toBeFalsy() 40 | }) 41 | 42 | test('isNull must return a boolean', () => { 43 | expect(utils.isNull(null)).toBeTruthy() 44 | expect(utils.isNull('null')).toBeFalsy() 45 | }) 46 | }) 47 | -------------------------------------------------------------------------------- /tests/unit/core/math.spec.ts: -------------------------------------------------------------------------------- 1 | import utils from '../../../src/index' 2 | 3 | describe('Math test', () => { 4 | it('plus method must return a number', () => { 5 | expect(utils.plus(1, 2, 0)).toBe(3) 6 | expect(utils.plus(1.2334, 1, 0)).toBe(2) 7 | expect(utils.plus(1.23456, 2, 2)).toBe(3.23) 8 | expect(utils.plus(14, 20)).toBe(34) 9 | expect(utils.plus(1e1, 2)).toBe(12) 10 | expect(utils.plus('a', 2)).toBe(0) 11 | }) 12 | 13 | it('subtract method must return a number', () => { 14 | expect(utils.subtract(1, 2)).toBe(-1) 15 | expect(utils.subtract(1.322, 1, 0)).toBe(0) 16 | expect(utils.subtract(2.3314, 1, 3)).toBe(1.331) 17 | expect(utils.subtract(1e1, 2)).toBe(8) 18 | }) 19 | 20 | it('multiply method must return a number', () => { 21 | expect(utils.multiply(1, 2)).toBe(2) 22 | expect(utils.multiply(1.33, 1, 0)).toBe(1) 23 | expect(utils.multiply(2.4456, 3, 2)).toBe(7.34) 24 | expect(utils.multiply(1.345, 2.6789, 5)).toBe(3.60312) 25 | expect(utils.multiply(1e1, 2)).toBe(20) 26 | }) 27 | 28 | it('divide method must return a number', () => { 29 | expect(utils.divide(2, 1)).toBe(2) 30 | expect(utils.divide(3.2242, 3, 0)).toBe(1) 31 | expect(utils.divide(2.3312, 4, 2)).toBe(0.58) 32 | expect(utils.divide(-2.344, 4, 1)).toBe(-0.6) 33 | expect(utils.divide(1e1, 2)).toBe(5) 34 | }) 35 | 36 | it('scientificNumber method must return a number or string', () => { 37 | expect(utils.scientificNumber(1e23)).toBe('100000000000000000000000') 38 | expect(utils.scientificNumber(1.33e23)).toBe('133000000000000000000000') 39 | expect(utils.scientificNumber(1e-23)).toBe('0.00000000000000000000001') 40 | expect(utils.scientificNumber(1.23e-23)).toBe('0.0000000000000000000000123') 41 | expect(utils.scientificNumber(100)).toBe(100) 42 | expect(utils.scientificNumber(1e10)).toBe(10000000000) 43 | expect(utils.scientificNumber(0)).toBe(0) 44 | expect(utils.scientificNumber('')).toBe('') 45 | }) 46 | test("用于资金金额的计算(去除',')", () => { 47 | expect(utils.formatToNumber('999,882')).toBe(999882) 48 | expect(utils.formatToNumber('aa')).toBe(0) 49 | }) 50 | test('千分符,数字三位一隔开 (1000000 => 1,000,000)', () => { 51 | expect(utils.dealNumber(10000000)).toBe('10,000,000') 52 | expect(utils.dealNumber(1000.54)).toBe('1,000.54') 53 | expect(utils.dealNumber(0)).toBe(0) 54 | }) 55 | }) 56 | -------------------------------------------------------------------------------- /tests/unit/core/method.spec.ts: -------------------------------------------------------------------------------- 1 | import utils from '../../../src/index' 2 | 3 | describe('Method test', () => { 4 | describe('Throttle decorator test', () => { 5 | let mockT: any 6 | let mockTFuncA: jest.Mock 7 | let mockTFuncB: jest.Mock 8 | beforeEach(() => { 9 | mockTFuncA = jest.fn() 10 | mockTFuncB = jest.fn() 11 | class TestT { 12 | @utils.throttleWrap() 13 | fnA() { 14 | mockTFuncA() 15 | return 'hello world' 16 | } 17 | @utils.throttleWrap(500, {}) 18 | fnB() { 19 | mockTFuncB() 20 | } 21 | } 22 | 23 | mockT = new TestT() 24 | }) 25 | 26 | afterEach(() => { 27 | jest.restoreAllMocks() 28 | }) 29 | 30 | it('throttleWrap must return a function', () => { 31 | expect(typeof mockT.fnA).toBe('function') 32 | expect(typeof mockT.fnB).toBe('function') 33 | }) 34 | 35 | it("throttleWrap shouldn't change function", () => { 36 | const res = mockT.fnA() 37 | setTimeout(() => { 38 | expect(res).toBe('hello world') 39 | }, 500) 40 | }) 41 | 42 | it('the function that throttleWrap returns should be called once in the delay time', () => { 43 | mockT.fnA() 44 | expect(mockTFuncA).toBeCalledTimes(1) 45 | mockT.fnA() 46 | expect(mockTFuncA).toBeCalledTimes(1) 47 | let count = 3 48 | const timer = setInterval(() => { 49 | mockT.fnA() 50 | count -= 1 51 | if (count <= 0 && timer) clearInterval(timer) 52 | }, 500) 53 | setTimeout(() => { 54 | expect(mockTFuncA).toBeCalledTimes(4) 55 | }, 1500) 56 | }) 57 | 58 | it('the function that throttleWrap returns should not affect each other', () => { 59 | mockT.fnA() 60 | mockT.fnB() 61 | expect(mockTFuncA).toHaveBeenCalledTimes(1) 62 | expect(mockTFuncB).toHaveBeenCalledTimes(1) 63 | }) 64 | }) 65 | 66 | describe('Throttle function test', () => { 67 | let mockTFuncA: jest.Mock 68 | let mockTFuncB: jest.Mock 69 | let throttleFuncA: Function 70 | let throttleFuncB: Function 71 | 72 | beforeEach(() => { 73 | mockTFuncA = jest.fn(() => 'hello world') 74 | mockTFuncB = jest.fn() 75 | throttleFuncA = utils.throttle(mockTFuncA, 300, {}) 76 | throttleFuncB = utils.throttle(mockTFuncB) 77 | }) 78 | 79 | afterEach(() => { 80 | jest.restoreAllMocks() 81 | }) 82 | 83 | it('throttle must return a function', () => { 84 | expect(typeof throttleFuncA).toBe('function') 85 | expect(typeof throttleFuncB).toBe('function') 86 | }) 87 | 88 | it("throttle shouldn't change function", () => { 89 | const res = throttleFuncA() 90 | setTimeout(() => { 91 | expect(res).toBe('hello world') 92 | }, 500) 93 | }) 94 | 95 | it('the function that throttle returns should be called once in the delay time', () => { 96 | throttleFuncA() 97 | expect(mockTFuncA).toBeCalledTimes(1) 98 | throttleFuncA() 99 | expect(mockTFuncA).toBeCalledTimes(1) 100 | let count = 3 101 | const timer = setInterval(() => { 102 | throttleFuncA() 103 | count -= 1 104 | if (count <= 0 && timer) clearInterval(timer) 105 | }, 500) 106 | setTimeout(() => { 107 | expect(mockTFuncA).toBeCalledTimes(4) 108 | }, 1500) 109 | }) 110 | 111 | it('the functions that throttleWrap returns should not affect each other', () => { 112 | throttleFuncA() 113 | throttleFuncB() 114 | expect(mockTFuncA).toHaveBeenCalledTimes(1) 115 | expect(mockTFuncB).toHaveBeenCalledTimes(1) 116 | }) 117 | }) 118 | describe('Debounce decorator test', () => { 119 | let mockD: any 120 | let mockDFuncA: jest.Mock 121 | let mockDFuncB: jest.Mock 122 | beforeEach(() => { 123 | mockDFuncA = jest.fn() 124 | mockDFuncB = jest.fn() 125 | class TestD1 { 126 | @utils.debounceWrap() 127 | fnA() { 128 | mockDFuncA() 129 | return 'hello world' 130 | } 131 | @utils.debounceWrap(500, {}) 132 | fnB() { 133 | mockDFuncB() 134 | } 135 | } 136 | mockD = new TestD1() 137 | }) 138 | 139 | afterEach(() => { 140 | jest.restoreAllMocks() 141 | }) 142 | 143 | it('debounceWrap must return a function', () => { 144 | expect(typeof mockD.fnA).toBe('function') 145 | }) 146 | 147 | it("debounceWrap shouldn't change function", () => { 148 | const res = mockD.fnA() 149 | setTimeout(() => { 150 | expect(res).toBe('hello world') 151 | }, 500) 152 | }) 153 | 154 | it('the function that debounce returns should not be called before the delay time', () => { 155 | mockD.fnB() 156 | expect(mockDFuncB).toBeCalledTimes(0) 157 | 158 | let count = 3 159 | const timer = setInterval(() => { 160 | mockD.fnB() 161 | count -= 1 162 | if (count <= 0 && timer) clearInterval(timer) 163 | }, 400) 164 | setTimeout(() => { 165 | expect(mockDFuncB).toBeCalledTimes(0) 166 | }, 1200) 167 | setTimeout(() => { 168 | expect(mockDFuncB).toBeCalledTimes(1) 169 | }, 1700) 170 | }) 171 | 172 | it('the functions that debounce returns should not affect each other', () => { 173 | mockD.fnA() 174 | mockD.fnB() 175 | setTimeout(() => { 176 | expect(mockDFuncA).toHaveBeenCalledTimes(1) 177 | expect(mockDFuncB).toHaveBeenCalledTimes(1) 178 | }, 500) 179 | }) 180 | }) 181 | 182 | describe('Debounce function test', () => { 183 | let mockDFuncA: jest.Mock 184 | let mockDFuncB: jest.Mock 185 | let debounceFuncA: Function 186 | let debounceFuncB: Function 187 | 188 | beforeEach(() => { 189 | mockDFuncA = jest.fn(() => 'hello world') 190 | mockDFuncB = jest.fn() 191 | debounceFuncA = utils.debounce(mockDFuncA, 300, {}) 192 | debounceFuncB = utils.debounce(mockDFuncB) 193 | }) 194 | 195 | afterEach(() => { 196 | jest.restoreAllMocks() 197 | }) 198 | 199 | it('debounce must return a function', () => { 200 | expect(typeof debounceFuncA).toBe('function') 201 | expect(typeof debounceFuncB).toBe('function') 202 | }) 203 | 204 | it("debounce shouldn't change function", () => { 205 | const res = debounceFuncA() 206 | setTimeout(() => { 207 | expect(res).toBe('hello world') 208 | }, 500) 209 | }) 210 | 211 | it('the function that debounce returns should be called once in the delay time', () => { 212 | debounceFuncA() 213 | expect(mockDFuncA).toBeCalledTimes(0) 214 | 215 | let count = 3 216 | const timer = setInterval(() => { 217 | debounceFuncA() 218 | count -= 1 219 | if (count <= 0 && timer) clearInterval(timer) 220 | }, 400) 221 | setTimeout(() => { 222 | expect(mockDFuncA).toBeCalledTimes(0) 223 | }, 1200) 224 | setTimeout(() => { 225 | expect(mockDFuncA).toBeCalledTimes(1) 226 | }, 1700) 227 | }) 228 | 229 | it('the functions that debounce returns should not affect each other', () => { 230 | debounceFuncA() 231 | debounceFuncB() 232 | setTimeout(() => { 233 | expect(mockDFuncA).toHaveBeenCalledTimes(1) 234 | expect(mockDFuncB).toHaveBeenCalledTimes(1) 235 | }, 500) 236 | }) 237 | }) 238 | }) 239 | -------------------------------------------------------------------------------- /tests/unit/core/url.spec.ts: -------------------------------------------------------------------------------- 1 | import utils from '../../../src/index' 2 | 3 | describe('url test', () => { 4 | test('cleanArray must return a Array', () => { 5 | expect(utils.cleanArray(['a=1', 'b=2', null, undefined])).toEqual(['a=1', 'b=2']) 6 | expect(utils.cleanArray(['a=1', 'b=2'])).toEqual(['a=1', 'b=2']) 7 | }) 8 | 9 | test('param must return a string', () => { 10 | expect(typeof utils.param({})).toBe('string') 11 | expect( 12 | utils.param({ 13 | id: '1', 14 | page: '2', 15 | pageSize: '20', 16 | }) 17 | ).toEqual('id=1&page=2&pageSize=20') 18 | expect( 19 | utils.param({ 20 | a: '1', 21 | b: '2', 22 | c: undefined, 23 | }) 24 | ).toEqual('a=1&b=2') 25 | expect( 26 | utils.param({ 27 | a: '1', 28 | b: null, 29 | c: undefined, 30 | }) 31 | ).toEqual('a=1&b=null') 32 | }) 33 | 34 | test('param2Obj must return a Record', () => { 35 | expect(typeof utils.param2Obj('')).toBe('object') 36 | expect(typeof utils.param2Obj('a=1')).toBe('object') 37 | expect(utils.param2Obj('1')).toEqual({ 1: undefined }) 38 | expect(utils.param2Obj('id=1&page=2&pageSize=20')).toEqual({ 39 | id: '1', 40 | page: '2', 41 | pageSize: '20', 42 | }) 43 | expect(utils.parseParams('a=1&b=2&c')).toEqual({ 44 | a: '1', 45 | b: '2', 46 | c: undefined, 47 | }) 48 | }) 49 | }) 50 | -------------------------------------------------------------------------------- /tests/unit/core/uuid.spec.ts: -------------------------------------------------------------------------------- 1 | import utils from '../../../src/index' 2 | 3 | describe('uuid test', () => { 4 | test('cleanArray must return a string', () => { 5 | expect(typeof utils.guid()).toBe('string') 6 | expect(utils.guid()).toHaveLength(36) 7 | }) 8 | test('guid', () => { 9 | expect(utils.getGuid()).toBeTruthy() 10 | }) 11 | }) 12 | -------------------------------------------------------------------------------- /tests/unit/core/verify.spec.ts: -------------------------------------------------------------------------------- 1 | import utils from '../../../src/index' 2 | 3 | describe('Verify test', () => { 4 | test('verifyHttp must return a boolean', () => { 5 | let url = 'http://www.jiangyh.cn' 6 | expect(utils.verifyHttp(url)).toBeTruthy() 7 | 8 | url = 'https://www.jiangyh.cn' 9 | expect(utils.verifyHttp(url)).toBeTruthy() 10 | 11 | url = 'jiangyh.cn' 12 | expect(utils.verifyHttp(url)).toBeFalsy() 13 | }) 14 | 15 | test('verifyMobile must return a boolean', () => { 16 | let mobile = '13222222222' 17 | expect(utils.verifyMobile(mobile)).toBeTruthy() 18 | 19 | mobile = '1111111' 20 | expect(utils.verifyMobile(mobile)).toBeFalsy() 21 | }) 22 | 23 | test('verifyCode must return a boolean', () => { 24 | let code = '567890' 25 | expect(utils.verifyCode(code)).toBeTruthy() 26 | 27 | code = '123' 28 | expect(utils.verifyCode(code)).toBeFalsy() 29 | }) 30 | 31 | test('verifyEmail must return a boolean', () => { 32 | let email = 'j532547613@gamil.com' 33 | expect(utils.verifyEmail(email)).toBeTruthy() 34 | 35 | email = '123456' 36 | expect(utils.verifyEmail(email)).toBeFalsy() 37 | }) 38 | }) 39 | -------------------------------------------------------------------------------- /tests/unit/index.spec.ts: -------------------------------------------------------------------------------- 1 | import utils from '../../src/index' 2 | 3 | // 判断Utils是否挂载对应的方法 4 | describe('Utils test', () => { 5 | // format模块 6 | describe('Format test', () => { 7 | test('Utils must have a dstMobile function', () => { 8 | expect(typeof utils.dstMobile).toBe('function') 9 | }) 10 | 11 | test('Utils must have a creatMobile function', () => { 12 | expect(typeof utils.creatMobile).toBe('function') 13 | }) 14 | 15 | test('Utils must have a random function', () => { 16 | expect(typeof utils.random).toBe('function') 17 | }) 18 | 19 | test('Utils must have a formatPhone function', () => { 20 | expect(typeof utils.formatPhone).toBe('function') 21 | }) 22 | 23 | test('Utils must have a parseParams function', () => { 24 | expect(typeof utils.parseParams).toBe('function') 25 | }) 26 | 27 | test('Utils must have a formatParams function', () => { 28 | expect(typeof utils.formatParams).toBe('function') 29 | }) 30 | 31 | test('Utils must have a hexToRgba function', () => { 32 | expect(typeof utils.hexToRgba).toBe('function') 33 | }) 34 | }) 35 | 36 | // is模块 37 | describe('Is test', () => { 38 | test('Utils must have a isArray function', () => { 39 | expect(typeof utils.isArray).toBe('function') 40 | }) 41 | 42 | test('Utils must have a isObject function', () => { 43 | expect(typeof utils.isObject).toBe('function') 44 | }) 45 | 46 | test('Utils must have a isPlainObject function', () => { 47 | expect(typeof utils.isPlainObject).toBe('function') 48 | }) 49 | 50 | test('Utils must have a isNum function', () => { 51 | expect(typeof utils.isNum).toBe('function') 52 | }) 53 | 54 | test('Utils must have a isFunc function', () => { 55 | expect(typeof utils.isFunc).toBe('function') 56 | }) 57 | 58 | test('Utils must have a isUndefined function', () => { 59 | expect(typeof utils.isUndefined).toBe('function') 60 | }) 61 | 62 | test('Utils must have a isNull function', () => { 63 | expect(typeof utils.isNull).toBe('function') 64 | }) 65 | }) 66 | 67 | // verify模块 68 | describe('Verify test', () => { 69 | test('Utils must have a verifyHttp function', () => { 70 | expect(typeof utils.verifyHttp).toBe('function') 71 | }) 72 | 73 | test('Utils must have a verifyMobile function', () => { 74 | expect(typeof utils.verifyMobile).toBe('function') 75 | }) 76 | 77 | test('Utils must have a verifyCode function', () => { 78 | expect(typeof utils.verifyCode).toBe('function') 79 | }) 80 | 81 | test('Utils must have a verifyEmail function', () => { 82 | expect(typeof utils.verifyEmail).toBe('function') 83 | }) 84 | }) 85 | 86 | // date模块 87 | describe('Date test', () => { 88 | test('Utils must have a formatTime function', () => { 89 | expect(typeof utils.formatTime).toBe('function') 90 | }) 91 | 92 | test('Utils must have a formatHourTime function', () => { 93 | expect(typeof utils.formatHourTime).toBe('function') 94 | }) 95 | 96 | test('Utils must have a now function', () => { 97 | expect(typeof utils.now).toBe('function') 98 | }) 99 | }) 100 | 101 | // method模块 102 | describe('Method test', () => { 103 | test('Utils must have a throttle function', () => { 104 | expect(typeof utils.throttle).toBe('function') 105 | }) 106 | 107 | test('Utils must have a debounce function', () => { 108 | expect(typeof utils.debounce).toBe('function') 109 | }) 110 | }) 111 | 112 | // math模块 113 | describe('Math test', () => { 114 | test('Utils must have a plus function', () => { 115 | expect(typeof utils.plus).toBe('function') 116 | }) 117 | 118 | test('Utils must have a subtract function', () => { 119 | expect(typeof utils.subtract).toBe('function') 120 | }) 121 | 122 | test('Utils must have a multiply function', () => { 123 | expect(typeof utils.multiply).toBe('function') 124 | }) 125 | 126 | test('Utils must have a divide function', () => { 127 | expect(typeof utils.divide).toBe('function') 128 | }) 129 | 130 | test('Utils must have a scientificNumber function', () => { 131 | expect(typeof utils.scientificNumber).toBe('function') 132 | }) 133 | 134 | test('Utils must have a dealNumber function', () => { 135 | expect(typeof utils.dealNumber).toBe('function') 136 | }) 137 | }) 138 | 139 | // url模块 140 | describe('Url test', () => { 141 | test('Utils must have a cleanArray function', () => { 142 | expect(typeof utils.cleanArray).toBe('function') 143 | }) 144 | 145 | test('Utils must have a param function', () => { 146 | expect(typeof utils.param).toBe('function') 147 | }) 148 | 149 | test('Utils must have a param2Obj function', () => { 150 | expect(typeof utils.param2Obj).toBe('function') 151 | }) 152 | }) 153 | 154 | // uuid模块 155 | describe('Uuid test', () => { 156 | test('Utils must have a guid function', () => { 157 | expect(typeof utils.guid).toBe('function') 158 | }) 159 | 160 | test('Utils must have a getGuid function', () => { 161 | expect(typeof utils.getGuid).toBe('function') 162 | }) 163 | }) 164 | 165 | // index模块 166 | describe('index test', () => { 167 | test('Utils must hava json function', () => { 168 | expect(typeof utils.json).toBe('function') 169 | }) 170 | 171 | test('Utils must hava isDingTalk function', () => { 172 | expect(typeof utils.isDingTalk).toBe('function') 173 | }) 174 | 175 | test('Utils must hava isDevEnv function', () => { 176 | expect(typeof utils.isDevEnv).toBe('function') 177 | }) 178 | 179 | test('Utils must hava getByteLen function', () => { 180 | expect(typeof utils.getByteLen).toBe('function') 181 | }) 182 | 183 | test('Utils must hava deepClone function', () => { 184 | expect(typeof utils.deepClone).toBe('function') 185 | }) 186 | 187 | test('Utils must hava getParamValues function', () => { 188 | expect(typeof utils.getParamValues).toBe('function') 189 | }) 190 | 191 | test('Utils must hava reverseNum function', () => { 192 | expect(typeof utils.reverseNum).toBe('function') 193 | }) 194 | 195 | test('Utils must hava getObjectType function', () => { 196 | expect(typeof utils.getObjectType).toBe('function') 197 | }) 198 | 199 | test('Utils must hava noRepeatArray function', () => { 200 | expect(typeof utils.noRepeatArray).toBe('function') 201 | }) 202 | 203 | test('Utils must hava isOuterLinkEnv function', () => { 204 | expect(typeof utils.isOuterLinkEnv).toBe('function') 205 | }) 206 | 207 | test('Utils must hava browser function', () => { 208 | expect(typeof utils.browser).toBe('function') 209 | }) 210 | 211 | test('Utils must hava thumbnail function', () => { 212 | expect(typeof utils.thumbnail).toBe('function') 213 | }) 214 | 215 | test('Utils must hava isThirdPC function', () => { 216 | expect(typeof utils.isThirdPC).toBe('function') 217 | }) 218 | 219 | test('Utils must hava envInfo function', () => { 220 | expect(typeof utils.envInfo).toBe('function') 221 | }) 222 | }) 223 | }) 224 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es5", 4 | "module": "es2015", 5 | "strict": true, 6 | "jsx": "preserve", 7 | "importHelpers": true, 8 | "moduleResolution": "node", 9 | "noImplicitAny": false, 10 | "experimentalDecorators": true, 11 | "skipLibCheck": true, 12 | "esModuleInterop": true, 13 | "emitDecoratorMetadata": true, 14 | "allowSyntheticDefaultImports": true, 15 | "sourceMap": true, 16 | "declaration": true, 17 | "declarationDir": "dist/types", 18 | "outDir": "dist/lib", 19 | "baseUrl": ".", 20 | "typeRoots": [ 21 | "node_modules/@types" 22 | ], 23 | "types": [ 24 | "node", 25 | "webpack-env", 26 | "jest" 27 | ], 28 | "paths": { 29 | "@/*": [ 30 | "src/*" 31 | ] 32 | }, 33 | "lib": [ 34 | "esnext", 35 | "dom", 36 | "dom.iterable", 37 | "scripthost" 38 | ] 39 | }, 40 | "include": [ 41 | "src" 42 | ], 43 | "exclude": [ 44 | "node_modules" 45 | ] 46 | } -------------------------------------------------------------------------------- /tslint.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": [ 3 | "tslint-config-standard", 4 | "tslint-config-prettier" 5 | ] 6 | } -------------------------------------------------------------------------------- /typedoc.json: -------------------------------------------------------------------------------- 1 | { 2 | "inputFiles": ["./src"], 3 | "mode": "file", 4 | "out": "docs" 5 | } -------------------------------------------------------------------------------- /vue.config.js: -------------------------------------------------------------------------------- 1 | 2 | // eslint-disable-next-line @typescript-eslint/no-var-requires 3 | const path = require('path') 4 | const resolve = (dir) => path.join(__dirname, dir) 5 | 6 | module.exports = { 7 | publicPath: './', 8 | devServer: { 9 | port: '8080', 10 | open: true 11 | }, 12 | outputDir: resolve('doc'), 13 | pages: { 14 | index: { 15 | entry: resolve('home/main.ts'), 16 | template: 'public/index.html', 17 | filename: 'index.html', 18 | title: 'Utils Tools', 19 | chunks: ['chunk-vendors', 'chunk-common', 'index'] 20 | }, 21 | }, 22 | chainWebpack: config => { 23 | config.plugins.delete('prefetch-index') 24 | }, 25 | } 26 | --------------------------------------------------------------------------------