7 Commits

Author SHA1 Message Date
TianSL 7ff223fa32 chore(release): 1.2.1 2026-03-26 08:56:15 +08:00
TianSL 154c4c1a51 ci: 🎡 配置.ps1文件的编码及换行符 2026-03-18 16:41:54 +08:00
TianSL da7d53e791 ci: 🎡 publish分离版本号更新 2026-03-18 16:32:27 +08:00
TianSL a8af544e79 chore(release): 1.2.0 2026-03-18 16:31:01 +08:00
TianSL dc114a4835 chore(release): publish v1.0.3 2026-03-18 15:53:43 +08:00
TianSL 5851d40d07 feat(common): 添加input-rules 2026-03-18 15:52:07 +08:00
TianSL 0cecc4df11 ci: 🎡 配置子项目npm仓库地址 2026-03-17 17:45:52 +08:00
27 changed files with 652 additions and 256 deletions
+24 -18
View File
@@ -1,27 +1,33 @@
{
"permissions": {
"defaultMode": "acceptEdits",
"allow": [
"Bash(pnpm --filter @r-utils/vue3 add vue)",
"Bash(grep -A 5 '\"\"dependencies\"\"' /d/Projects/r-util-js/packages/*/package.json)",
"Bash(grep -r \"console.log\" /d/Projects/r-util-js/packages/*/webpack.config.js)",
"Bash(grep -c \"__dirname\" /d/Projects/r-util-js/packages/*/webpack.config.js)",
"Bash(grep -r \"private.*true\" /d/Projects/r-util-js/packages/*/package.json)",
"Bash(grep \"name\" /d/Projects/r-util-js/packages/*/package.json)",
"Bash(git -C /d/Projects/r-util-js status --short)",
"Read(./)",
"Edit(./)",
"Write(./)",
"Bash(npm run *)",
"Bash(npm test *)",
"Bash(npm run build *)",
"Bash(npm view *)",
"Bash(npm list *)",
"Bash(pnpm install)",
"Bash(pnpm build)",
"Bash(pnpm test)",
"Bash(pnpm run *)",
"Bash(pnpm test *)",
"Bash(pnpm run build *)",
"Bash(pnpm view *)",
"Bash(pnpm list *)",
"Bash(git diff *)",
"Bash(git status *)",
"Bash(git log *)",
"Bash(grep *)",
"Bash(pnpm --filter @r-utils/vue3 add vue)",
"Bash(printf 'npm run lint-staged\\\\nnpm test\\\\n')",
"Bash(printf 'npx commitlint --edit \"\"$1\"\"\\\\n')",
"Bash(npm view typescript version)",
"Bash(pnpm update typescript)",
"Bash(npm view @typescript-eslint/parser versions --json)",
"Bash(npm view @typescript-eslint/parser@latest peerDependencies)",
"Bash(npm view @typescript-eslint/parser@latest version)",
"Bash(pnpm list typescript)",
"Bash(pnpm list @typescript-eslint/parser @typescript-eslint/eslint-plugin typescript-eslint)",
"Bash(npm view @commitlint/cz-commitlint@latest peerDependencies)",
"Bash(npm view inquirer@9 version)"
]
"Bash(pnpm update typescript)"
],
"ask": ["Read(./.env)", "Read(./.env.*)", "Read(./secrets/**)", "Bash(git push *)", "Bash(rm -rf *)"]
}
}
+1 -1
View File
@@ -1,3 +1,3 @@
{
"path": "node_modules/cz-git"
"path": "cz-git"
}
+6 -1
View File
@@ -3,7 +3,12 @@ root = true
[*]
charset = utf-8
indent_style = space
# indent_size = 2
indent_size = 2
end_of_line = lf
insert_final_newline = true
trim_trailing_whitespace = true
[*.ps1]
charset = utf-8-bom
end_of_line = crlf
indent_size = 4
+5
View File
@@ -0,0 +1,5 @@
# Default: auto-detect
* text=auto eol=lf
# PowerShell scripts must use CRLF
*.ps1 text eol=crlf
+9
View File
@@ -0,0 +1,9 @@
{
"bumpFiles": [
{ "filename": "package.json", "type": "json" },
{ "filename": "packages/common/package.json", "type": "json" },
{ "filename": "packages/vue3/package.json", "type": "json" },
{ "filename": "packages/uni-app/package.json", "type": "json" },
{ "filename": "packages/vue2/package.json", "type": "json" }
]
}
+8
View File
@@ -0,0 +1,8 @@
{
"recommendations": [
"psioniq.psi-header",
"aaron-bond.better-comments",
"streetsidesoftware.code-spell-checker",
"dbaeumer.vscode-eslint"
]
}
+28 -1
View File
@@ -1,3 +1,30 @@
{
"psi-header.config": {
"forceToTop": true,
"blankLinesAfter": 1,
"overridePathSeparator": "/"
},
"psi-header.changes-tracking": {
"isActive": true,
"autoHeader": "autoSave",
"modDate": "@lastModified:",
"modDateFormat": "YYYY-MM-DD HH:mm:ss",
"modAuthor": "@lastModifiedBy:",
"exclude": ["markdown", "json"],
"excludeGlob": ["**/settings.json"]
},
"psi-header.templates": [
{
"language": "*",
"template": [
"@file: <<filerelativepath>>",
"@description: ",
"@author: <<author>> (<<authoremail>>)",
"@date: <<filecreated('YYYY-MM-DD HH:mm:ss')>>",
"@lastModified: <<dateformat('YYYY-MM-DD HH:mm:ss')>>",
"@lastModifiedBy: <<author>> (<<authoremail>>)"
],
"changeLogNaturalOrder": true
}
]
}
+9
View File
@@ -2,6 +2,15 @@
All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.
### [1.2.1](https://gitee.com/codice_fabbrica/r-util-js/compare/v1.2.0...v1.2.1) (2026-03-26)
## [1.2.0](https://gitee.com/codice_fabbrica/r-util-js/compare/v1.1.0...v1.2.0) (2026-03-18)
### Features
* **common:** :sparkles: 添加input-rules ([5851d40](https://gitee.com/codice_fabbrica/r-util-js/commit/5851d40d079da9818499121b5f576a761f448773))
## 1.1.0 (2026-03-17)
+16
View File
@@ -60,6 +60,22 @@ pnpm commit
**注意**:提交时 husky pre-commit 钩子会自动运行 lint-staged 和 jest 测试,commit-msg 钩子会用 commitlint 校验提交信息格式。
### 发布
发布分两步:先用 `standard-version` 管理版本,再用脚本构建和发布。
```bash
# 1. 版本管理(更新版本号 + 生成 CHANGELOG + git commit/tag
pnpm release # 默认 patch
npx standard-version --release-as minor # 指定版本类型
# 2. 构建并发布到 npm
bash scripts/publish.sh # Linux/macOS
powershell scripts/publish.ps1 # Windows
```
版本配置见 `.versionrc.json`,会同步更新根包和所有子包的版本号。
## 架构说明
### Monorepo 结构
+17 -19
View File
@@ -139,44 +139,42 @@ pnpm commit
## 发布
### 发布到私有 npm 仓库
### 1. 版本管理(standard-version
使用 `standard-version` 更新版本号、生成 CHANGELOG、创建 Git commit 和 tag。版本配置见 `.versionrc.json`,会同步更新根包和所有子包的版本号。
```bash
# 默认 patch 版本
pnpm release
# 指定版本类型
npx standard-version --release-as minor # 1.0.0 -> 1.1.0
npx standard-version --release-as major # 1.0.0 -> 2.0.0
```
### 2. 构建并发布到私有 npm 仓库
项目已配置发布到私有 npm 仓库 `http://npm.nps.yunvip123.cn`
#### Windows (PowerShell)
```powershell
# 发布所有子包(默认 patch 版本)
powershell scripts/publish.ps1
# 指定版本类型
powershell scripts/publish.ps1 patch # 1.0.0 -> 1.0.1
powershell scripts/publish.ps1 minor # 1.0.0 -> 1.1.0
powershell scripts/publish.ps1 major # 1.0.0 -> 2.0.0
```
#### Linux/macOS (Bash)
```bash
# 发布所有子包(默认 patch 版本)
bash scripts/publish.sh
# 指定版本类型
bash scripts/publish.sh patch # 1.0.0 -> 1.0.1
bash scripts/publish.sh minor # 1.0.0 -> 1.1.0
bash scripts/publish.sh major # 1.0.0 -> 2.0.0
```
发布脚本会自动执行以下步骤:
1. 检查 Git 工作区状态
2. 运行测试(确保代码质量)
3. 更新所有子包的版本号
4. 构建所有子包
5. 提交版本更新到 Git
6. 依次发布 `@r-utils/common``@r-utils/vue3``@r-utils/uni-app``@r-utils/vue2`
7. 创建 Git 标签(如 `v1.0.1`
8. 询问是否推送到远程仓库
3. 构建所有子包
4. 依次发布 `@r-utils/common``@r-utils/vue3``@r-utils/uni-app``@r-utils/vue2`
5. 询问是否推送到远程仓库
### 安装已发布的包
+33 -99
View File
@@ -77,105 +77,39 @@ module.exports = {
allowCustomScopes: false,
allowEmptyScopes: true,
messages: {
skip: "跳过",
max: "最多 %d 个字符",
min: "最少 %d 个字符",
emptyWarning: "不能为空",
upperLimitWarning: "超出字数限制",
lowerLimitWarning: "低于字数限制",
},
questions: {
type: {
description: "选择提交类型",
enum: {
feat: {
description: "一个新特性",
title: "新特性",
emoji: "✨",
},
fix: {
description: "一个漏洞修复",
title: "漏洞修复",
emoji: "🐛",
},
docs: {
description: "仅更改文档",
title: "文档",
emoji: "📚",
},
style: {
description: "不影响代码含义的更改(空白符、格式化、缺少分号等)",
title: "样式",
emoji: "💎",
},
refactor: {
description: "既不修复错误也不添加功能的代码更改",
title: "重构",
emoji: "📦",
},
perf: {
description: "提高性能的代码更改",
title: "性能提升",
emoji: "🚀",
},
test: {
description: "添加缺失的测试或纠正现有的测试",
title: "测试",
emoji: "🚨",
},
build: {
description:
"影响构建系统或外部依赖项的更改(例如:gulp、broccoli、npm",
title: "构建",
emoji: "🛠",
},
ci: {
description:
"更改我们的集成配置文件和脚本(例如:Travis、Circle、BrowserStack、SauceLabs",
title: "集成",
emoji: "⚙️",
},
chore: {
description: "不修改源码或测试文件的其他更改",
title: "杂项",
emoji: "♻️",
},
revert: {
description: "恢复之前的提交",
title: "还原",
emoji: "🗑",
},
},
},
scope: {
description: "更改的范围(scope)(例:common、vue3、uni-app",
},
subject: {
description: "主题(subject",
},
body: {
description: "主体(body",
},
isBreaking: {
description: "是否有破坏性更改(BREAKING CHANGE)?",
},
breakingBody: {
description:
"破坏性更改(BREAKING CHANGE)需要一个主体(body),请输入详细描述",
},
breaking: {
description: "描述破坏性更改(BREAKING CHANGE",
},
isIssueAffected: {
description: "此改变是否影响打开的问题(open ssues",
},
issuesBody: {
description: "如果问题关闭,则需要提交一个主体(body),请输入详细描述",
},
issues: {
description:
'添加问题参考(issue references (例: "fix #123"、"re #123"',
},
type: '选择你要提交的类型:',
scope: '选择一个提交范围(可选):',
customScope: '请输入自定义范围:',
subject: '请简短描述这次改动:\n',
body: '请详细描述这次改动(可选,用 "|" 换行):\n',
breaking: '是否有破坏性变更(可选,用 "|" 换行):\n',
footerPrefixesSelect: '选择关联的 ISSUE 类型(可选):',
customFooterPrefix: '输入 ISSUE 前缀:',
footer: '列出关联的 ISSUE,如: #31, #34:\n',
generatingByAI: '正在通过 AI 生成提交信息...',
generatedSelectByAI: '选择一个 AI 生成的 subject:',
confirmCommit: '是否确认提交以上信息?',
},
// subject 最小长度提示(中文化 "[x more chars needed]"
minSubjectLength: 4,
defaultSubject: '',
types: [
{ value: 'feat', name: 'feat: 新增功能', emoji: ':sparkles:' },
{ value: 'fix', name: 'fix: 修复缺陷', emoji: ':bug:' },
{ value: 'docs', name: 'docs: 文档变更', emoji: ':memo:' },
{ value: 'style', name: 'style: 代码格式(不影响逻辑)', emoji: ':lipstick:' },
{ value: 'refactor', name: 'refactor: 重构(既非新功能,也不是修 bug)', emoji: ':recycle:' },
{ value: 'perf', name: 'perf: 性能优化', emoji: ':zap:' },
{ value: 'test', name: 'test: 添加或修改测试', emoji: ':white_check_mark:' },
{ value: 'build', name: 'build: 构建系统或外部依赖变更', emoji: ':package:' },
{ value: 'ci', name: 'ci: CI 配置文件和脚本变更', emoji: ':ferris_wheel:' },
{ value: 'chore', name: 'chore: 其它不修改 src 或测试的改动', emoji: ':hammer:' },
{ value: 'revert', name: 'revert: 回退之前的 commit', emoji: ':rewind:' },
],
// issue 前缀也可以用中文说明
issuePrefixs: [
{ value: 'link', name: 'link: 关联 ISSUE' },
{ value: 'close', name: 'close: 关闭 ISSUE' },
],
},
};
+1
View File
@@ -27,6 +27,7 @@ export default [
"patches/",
"wxcomponents/",
"lib/",
"scripts/",
],
languageOptions: {
globals: {
+9 -5
View File
@@ -1,6 +1,6 @@
{
"name": "@r-utils/root",
"version": "1.1.0",
"version": "1.2.1",
"private": true,
"description": "前端工具库",
"keywords": [
@@ -27,18 +27,20 @@
},
"license": "ISC",
"engines": {
"node": ">=18.12.0"
"node": ">=18.12.0",
"pnpm": ">=10.0.0"
},
"packageManager": "pnpm@8.15.6",
"packageManager": "pnpm@10.32.1",
"type": "module",
"workspaces": [
"packages/*"
],
"scripts": {
"preinstall": "npx only-allow pnpm",
"build": "pnpm -r run build",
"prepare": "husky install",
"lint": "eslint --ext .js,ts --fix src",
"format": "prettier --write src",
"lint": "eslint --fix packages/*/src",
"format": "prettier --write packages/*/src",
"release": "standard-version",
"commit": "cz",
"lint-staged": "lint-staged",
@@ -59,6 +61,8 @@
"eslint": "^10.0.3",
"eslint-config-prettier": "^10.1.8",
"eslint-define-config": "^1.18.0",
"eslint-import-resolver-typescript": "^4.4.4",
"eslint-plugin-import-x": "^4.16.2",
"eslint-plugin-prettier": "^5.5.5",
"globals": "^17.4.0",
"husky": "^9.1.7",
+2 -2
View File
@@ -1,12 +1,12 @@
{
"name": "@r-utils/common",
"version": "1.0.2",
"version": "1.0.3",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "@r-utils/common",
"version": "1.0.2",
"version": "1.0.3",
"dependencies": {
"@r-utils/common": "file:",
"dayjs": "^1.11.13",
+26 -2
View File
@@ -1,6 +1,6 @@
{
"name": "@r-utils/common",
"version": "1.0.2",
"version": "1.2.1",
"private": false,
"description": "js通用工具库",
"type": "module",
@@ -20,6 +20,27 @@
"utils",
"common"
],
"publishConfig": {
"registry": "http://npm.nps.yunvip123.cn"
},
"author": {
"name": "CodiceFabbrica",
"email": "randy1924@163.com",
"url": "https://gitee.com/codice_fabbrica"
},
"homepage": "https://gitee.com/codice_fabbrica/r-util-js",
"repository": {
"url": "https://gitee.com/codice_fabbrica/r-util-js.git",
"type": "git"
},
"bugs": {
"url": "https://gitee.com/codice_fabbrica/r-util-js/issues"
},
"engines": {
"node": ">=18.12.0",
"pnpm": ">=10.0.0"
},
"packageManager": "pnpm@10.32.1",
"scripts": {
"build": "vite build",
"watch": "vite build --watch",
@@ -32,11 +53,14 @@
},
"dependencies": {
"dayjs": "^1.11.13",
"js-easing-functions": "^1.0.3",
"lodash-es": "^4.17.21",
"text-encoding": "^0.7.0"
},
"devDependencies": {
"@types/lodash": "^4.17.16",
"@types/lodash-es": "^4.17.12"
"@types/lodash-es": "^4.17.12",
"vite": "catalog:",
"vite-plugin-dts": "catalog:"
}
}
+1
View File
@@ -3,3 +3,4 @@ export * from "./permission";
export * from "./printer";
export * from "./time";
export * from "./timer";
export * from "./input-rule";
+163
View File
@@ -0,0 +1,163 @@
/*
* @file: /src/input-rule.ts
* @description: 限制输入框输入的规则
* @author: tsl (randy1924@163.com)
* @date: 2026-03-18 13:37:11
* @lastModified: 2026-03-18 15:04:44
* @lastModifiedBy: tsl (randy1924@163.com)
*/
export type InputValue = string | number | null;
export interface InputOptions {
min?: number; // 最小值
max?: number; // 最大值
init?: string | number; // 初始值
digits?: number; // 小数位数
pattern?: string | RegExp; // 匹配模式
required?: boolean; // 是否必填
integer?: boolean; // 是否整数
number?: boolean; // 是否转成数字
text?: boolean; // 是否使用文本模式
floor?: boolean; // 是否向下取数
ceil?: boolean; // 是否向上取数
keepDecimal?: boolean; // 是否保留小数,即使是小数位是0
noSign?: boolean; // 不允许输入正负号
}
/**
* 根据规则获取目标值
* @example
* 限制输入的最小值:0,最大值:99999.99,必填,小数位数:2
* const value = getValueOfRule(e.detail.value, {
* min: 0,
* max: 99999.99,
* required: true,
* digits: 2,
* })
*/
export function getValueOfRule(
value: InputValue,
options: InputOptions,
callback?: (value: InputValue) => void,
): InputValue {
console.log("getValueOfRule", value, options);
const { text } = options;
let targetValue: InputValue;
if (text) {
targetValue = getTextTargetValue(value, options);
} else {
targetValue = getNumberTargetValue(value, options);
}
console.log("targetValue", targetValue);
callback?.(targetValue);
return targetValue;
}
/**
* 根据输入的获取处理后值-文本类型
*/
function getTextTargetValue(innerValue: InputValue, options: InputOptions): InputValue {
const { required, init, pattern, number } = options;
innerValue ??= "";
innerValue = String(innerValue);
let targetValue: string | number = innerValue;
// 如果提供了pattern参数,检查输入是否匹配该模式
if (pattern && !new RegExp(pattern).test(innerValue)) {
return "";
}
if (!/^[+-]?\d+(\.\d+)?$/.test(innerValue)) {
if (required) {
if (init !== undefined) {
targetValue = String(init);
}
}
}
if (number) {
targetValue = Number(targetValue);
}
return targetValue;
}
/**
* 根据 floor/ceil 选项选择取整方式
*/
function getRoundFn(floor?: boolean, ceil?: boolean): (n: number) => number {
if (floor) return Math.floor;
if (ceil) return Math.ceil;
return Math.round;
}
/**
* 判断字符串是否为合法数字输入
*/
function isValidNumberInput(value: string, noSign?: boolean): boolean {
if (!value) return false;
if (!/^[+-]?\d+(\.\d+)?$/.test(value)) return false;
if (noSign && /[+-]/.test(value)) return false;
return true;
}
/**
* 获取非法输入时的回退值
*/
function getFallbackValue(options: InputOptions): string {
const { required, init, min } = options;
if (!required) return "";
if (init != null) return String(init);
return min == null ? "0" : String(min);
}
/**
* 对数字应用精度和取整处理
*/
function applyPrecision(num: number, options: InputOptions): number {
const { digits, integer, floor, ceil, min, max } = options;
let result = num;
if (min != null) result = Math.max(result, min);
if (max != null) result = Math.min(result, max);
const roundFn = getRoundFn(floor, ceil);
if (digits != null) {
const precision = Math.pow(10, digits);
result = roundFn(result * precision) / precision;
}
if (integer) {
result = roundFn(result);
}
return result;
}
/**
* 根据输入的获取处理后值-数字类型
*/
function getNumberTargetValue(innerValue: InputValue, options: InputOptions): InputValue {
const { number, keepDecimal, noSign, digits } = options;
const strValue = String(innerValue ?? "");
let targetValue: string;
if (isValidNumberInput(strValue, noSign)) {
targetValue = String(applyPrecision(Number(strValue), options));
} else {
targetValue = getFallbackValue(options);
}
if (digits != null && keepDecimal) {
targetValue = Number(targetValue).toFixed(digits);
}
return number ? Number(targetValue) : targetValue;
}
+166
View File
@@ -0,0 +1,166 @@
import { test, expect, describe } from "@jest/globals";
import { getValueOfRule, InputOptions } from "../src/input-rule";
describe("getValueOfRule - 文本模式 (text: true)", () => {
const textOpts: InputOptions = { text: true };
test("普通文本直接返回", () => {
expect(getValueOfRule("hello", { ...textOpts })).toBe("hello");
});
test("null 值返回空字符串", () => {
expect(getValueOfRule(null, { ...textOpts })).toBe("");
});
test("required + init:非数字文本回退到 init", () => {
expect(getValueOfRule("abc", { ...textOpts, required: true, init: "默认" })).toBe("默认");
});
test("required 无 init:非数字文本保持原值", () => {
expect(getValueOfRule("abc", { ...textOpts, required: true })).toBe("abc");
});
test("number 选项将结果转为数字", () => {
expect(getValueOfRule("123", { ...textOpts, number: true })).toBe(123);
});
test("pattern 匹配失败返回空字符串", () => {
expect(getValueOfRule("abc", { ...textOpts, pattern: "^\\d+$" })).toBe("");
});
test("pattern 匹配成功返回原值", () => {
expect(getValueOfRule("123", { ...textOpts, pattern: "^\\d+$" })).toBe("123");
});
});
describe("getValueOfRule - 数字模式", () => {
test("正常数字字符串返回字符串", () => {
expect(getValueOfRule("42", {})).toBe("42");
});
test("number 选项返回数字类型", () => {
expect(getValueOfRule("42", { number: true })).toBe(42);
});
test("非法输入 + required 回退到 init", () => {
expect(getValueOfRule("abc", { required: true, init: 10 })).toBe("10");
});
test("非法输入 + required 无 init 回退到 min", () => {
expect(getValueOfRule("abc", { required: true, min: 5 })).toBe("5");
});
test("非法输入 + required 无 init 无 min 回退到 0", () => {
expect(getValueOfRule("abc", { required: true })).toBe("0");
});
test("非法输入 + 非 required 返回空字符串", () => {
expect(getValueOfRule("abc", {})).toBe("");
});
test("null 值 + required 回退到 init", () => {
expect(getValueOfRule(null, { required: true, init: 0 })).toBe("0");
});
test("null 值 + 非 required 返回空字符串", () => {
expect(getValueOfRule(null, {})).toBe("");
});
});
describe("getValueOfRule - min/max 限制", () => {
test("值小于 min 时限制为 min", () => {
expect(getValueOfRule("3", { min: 5 })).toBe("5");
});
test("值大于 max 时限制为 max", () => {
expect(getValueOfRule("100", { max: 50 })).toBe("50");
});
test("值在 min/max 范围内保持不变", () => {
expect(getValueOfRule("25", { min: 0, max: 50 })).toBe("25");
});
test("负数受 min 限制", () => {
expect(getValueOfRule("-10", { min: 0 })).toBe("0");
});
});
describe("getValueOfRule - digits 小数位数", () => {
test("保留 2 位小数(四舍五入)", () => {
expect(getValueOfRule("3.456", { digits: 2 })).toBe("3.46");
});
test("保留 0 位小数", () => {
expect(getValueOfRule("3.6", { digits: 0 })).toBe("4");
});
test("floor 向下取整小数", () => {
expect(getValueOfRule("3.456", { digits: 2, floor: true })).toBe("3.45");
});
test("ceil 向上取整小数", () => {
expect(getValueOfRule("3.451", { digits: 2, ceil: true })).toBe("3.46");
});
test("keepDecimal 保留尾部零", () => {
expect(getValueOfRule("3", { digits: 2, keepDecimal: true })).toBe("3.00");
});
test("keepDecimal + number 返回数字类型", () => {
expect(getValueOfRule("3.10", { digits: 2, keepDecimal: true, number: true })).toBe(3.1);
});
});
describe("getValueOfRule - integer 整数模式", () => {
test("integer 四舍五入取整", () => {
expect(getValueOfRule("3.6", { integer: true })).toBe("4");
});
test("integer + floor 向下取整", () => {
expect(getValueOfRule("3.9", { integer: true, floor: true })).toBe("3");
});
test("integer + ceil 向上取整", () => {
expect(getValueOfRule("3.1", { integer: true, ceil: true })).toBe("4");
});
});
describe("getValueOfRule - noSign 不允许正负号", () => {
test("带正号的输入被视为非法", () => {
expect(getValueOfRule("+5", { noSign: true, required: true, init: 0 })).toBe("0");
});
test("带负号的输入被视为非法", () => {
expect(getValueOfRule("-5", { noSign: true, required: true, init: 0 })).toBe("0");
});
test("无符号数字正常通过", () => {
expect(getValueOfRule("5", { noSign: true })).toBe("5");
});
});
describe("getValueOfRule - callback", () => {
test("callback 接收最终处理后的值", () => {
let received: unknown;
getValueOfRule("42", { number: true }, (v) => { received = v; });
expect(received).toBe(42);
});
});
describe("getValueOfRule - 综合场景", () => {
test("限制输入 min:0, max:99999.99, required, digits:2", () => {
expect(getValueOfRule("100.456", { min: 0, max: 99999.99, required: true, digits: 2 })).toBe("100.46");
});
test("超出 max 时截断到 max", () => {
expect(getValueOfRule("100000", { min: 0, max: 99999.99, required: true, digits: 2 })).toBe("99999.99");
});
test("空输入 required 回退到 min", () => {
expect(getValueOfRule("", { min: 0, max: 99999.99, required: true, digits: 2 })).toBe("0");
});
test("负数输入限制到 min:0", () => {
expect(getValueOfRule("-5", { min: 0, max: 100, required: true })).toBe("0");
});
});
+2 -2
View File
@@ -1,12 +1,12 @@
{
"name": "@r-utils/uni-app",
"version": "1.0.1",
"version": "1.0.2",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "@r-utils/uni-app",
"version": "1.0.1",
"version": "1.0.2",
"dependencies": {
"@r-utils/root": "file:",
"@r-utils/uni-app": "file:",
+38 -2
View File
@@ -1,6 +1,6 @@
{
"name": "@r-utils/uni-app",
"version": "1.0.1",
"version": "1.2.1",
"private": false,
"description": "uni-app工具库",
"type": "module",
@@ -19,6 +19,27 @@
"keywords": [
"uni-app"
],
"publishConfig": {
"registry": "http://npm.nps.yunvip123.cn"
},
"author": {
"name": "CodiceFabbrica",
"email": "randy1924@163.com",
"url": "https://gitee.com/codice_fabbrica"
},
"homepage": "https://gitee.com/codice_fabbrica/r-util-js",
"repository": {
"url": "https://gitee.com/codice_fabbrica/r-util-js.git",
"type": "git"
},
"bugs": {
"url": "https://gitee.com/codice_fabbrica/r-util-js/issues"
},
"engines": {
"node": ">=18.12.0",
"pnpm": ">=10.0.0"
},
"packageManager": "pnpm@10.32.1",
"scripts": {
"build": "vite build",
"watch": "vite build --watch",
@@ -29,13 +50,28 @@
"test": "jest"
},
"dependencies": {
"@r-utils/common": "workspace:^"
"@r-utils/common": "workspace:^",
"chroma-js": "^3.2.0",
"lodash-es": "^4.17.21",
"qs": "^6.15.0"
},
"peerDependencies": {
"@dcloudio/uni-app": ">=3.0.0",
"vue": "^3.3.0"
},
"peerDependenciesMeta": {
"@dcloudio/uni-app": {
"optional": true
}
},
"devDependencies": {
"@dcloudio/types": "^3.0.7",
"@dcloudio/uni-app": "3.0.0-4070520250711001",
"@types/chroma-js": "^3.1.2",
"@types/lodash-es": "^4.17.12",
"@types/qs": "^6.15.0",
"vite": "catalog:",
"vite-plugin-dts": "catalog:",
"vue": "^3.3.0"
}
}
+2 -2
View File
@@ -1,12 +1,12 @@
{
"name": "@r-utils/vue2",
"version": "1.0.1",
"version": "1.0.2",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "@r-utils/vue2",
"version": "1.0.1",
"version": "1.0.2",
"dependencies": {
"@r-utils/vue2": "file:",
"lodash": "^4.17.21"
+24 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@r-utils/vue2",
"version": "1.0.1",
"version": "1.2.1",
"private": false,
"description": "Vue2工具库",
"type": "module",
@@ -19,6 +19,27 @@
"keywords": [
"vue2"
],
"publishConfig": {
"registry": "http://npm.nps.yunvip123.cn"
},
"author": {
"name": "CodiceFabbrica",
"email": "randy1924@163.com",
"url": "https://gitee.com/codice_fabbrica"
},
"homepage": "https://gitee.com/codice_fabbrica/r-util-js",
"repository": {
"url": "https://gitee.com/codice_fabbrica/r-util-js.git",
"type": "git"
},
"bugs": {
"url": "https://gitee.com/codice_fabbrica/r-util-js/issues"
},
"engines": {
"node": ">=18.12.0",
"pnpm": ">=10.0.0"
},
"packageManager": "pnpm@10.32.1",
"scripts": {
"build": "vite build",
"watch": "vite build --watch",
@@ -32,6 +53,8 @@
"vue": "^2.7.0"
},
"devDependencies": {
"vite": "catalog:",
"vite-plugin-dts": "catalog:",
"vue": "^2.7.0"
}
}
+2 -2
View File
@@ -1,12 +1,12 @@
{
"name": "@r-utils/vue3",
"version": "1.0.2",
"version": "1.0.3",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "@r-utils/vue3",
"version": "1.0.2",
"version": "1.0.3",
"license": "ISC",
"dependencies": {
"@r-utils/vue3": "file:",
+28 -3
View File
@@ -1,6 +1,6 @@
{
"name": "@r-utils/vue3",
"version": "1.0.2",
"version": "1.2.1",
"private": false,
"description": "Vue3 工具",
"type": "module",
@@ -19,6 +19,26 @@
"keywords": [
"vue3"
],
"publishConfig": {
"registry": "http://npm.nps.yunvip123.cn"
},
"author": {
"name": "CodiceFabbrica",
"email": "randy1924@163.com",
"url": "https://gitee.com/codice_fabbrica"
},
"homepage": "https://gitee.com/codice_fabbrica/r-util-js",
"repository": {
"url": "https://gitee.com/codice_fabbrica/r-util-js.git",
"type": "git"
},
"bugs": {
"url": "https://gitee.com/codice_fabbrica/r-util-js/issues"
},
"engines": {
"node": ">=18.12.0",
"pnpm": ">=10.0.0"
},
"scripts": {
"build": "vite build",
"watch": "vite build --watch",
@@ -33,7 +53,12 @@
"vue": "^3.3.0"
},
"devDependencies": {
"vue": "^3.3.0"
"vite": "catalog:",
"vite-plugin-dts": "catalog:",
"vue": "^3.5.13"
},
"packageManager": "pnpm@8.15.6"
"packageManager": "pnpm@10.32.1",
"dependencies": {
"@r-utils/common": "workspace:^"
}
}
+7
View File
@@ -24,5 +24,12 @@ export default {
printWidth: 120,
},
},
{
files: ["*.ps1"],
options: {
endOfLine: "crlf",
tabWidth: 4,
},
},
],
};
+12 -49
View File
@@ -1,21 +1,11 @@
# 发布所有子包到私有 npm 仓库
# 使用方法: powershell scripts/publish.ps1 [版本类型]
# 版本类型: major | minor | patch (默认 patch)
# 使用方法: powershell scripts/publish.ps1
# 注意: 发布仓库地址使用各子包 package.json 中的 publishConfig.registry 配置
# 版本管理请先通过 pnpm release (standard-version) 完成,本脚本仅负责构建和发布
$ErrorActionPreference = "Stop"
# 获取版本类型参数,默认为 patch
$VERSION_TYPE = if ($args.Count -gt 0) { $args[0] } else { "patch" }
# 验证版本类型
if ($VERSION_TYPE -notin @("major", "minor", "patch")) {
Write-Host "❌ 无效的版本类型: $VERSION_TYPE" -ForegroundColor Red
Write-Host "使用方法: powershell scripts/publish.ps1 [major|minor|patch]" -ForegroundColor Yellow
exit 1
}
Write-Host "🚀 开始发布流程 (版本类型: $VERSION_TYPE)" -ForegroundColor Green
Write-Host "🚀 开始发布流程" -ForegroundColor Green
Write-Host ""
# 子包列表
@@ -48,19 +38,7 @@ if ($LASTEXITCODE -ne 0) {
}
Write-Host ""
# 3. 更新版本号
Write-Host "📝 更新版本号 ($VERSION_TYPE)..." -ForegroundColor Cyan
foreach ($package in $PACKAGES) {
if (Test-Path $package) {
Write-Host " 更新 $package 版本号..." -ForegroundColor Gray
Push-Location $package
npm version $VERSION_TYPE --no-git-tag-version
Pop-Location
}
}
Write-Host ""
# 4. 构建所有包
# 3. 构建所有包
Write-Host "📦 构建所有包..." -ForegroundColor Cyan
pnpm build
if ($LASTEXITCODE -ne 0) {
@@ -69,22 +47,12 @@ if ($LASTEXITCODE -ne 0) {
}
Write-Host ""
# 5. 更新 README 中的版本信息
Write-Host "📄 更新 README..." -ForegroundColor Cyan
$COMMON_VERSION = node -p "require('./packages/common/package.json').version"
Write-Host " 当前版本: $COMMON_VERSION" -ForegroundColor Gray
# 获取当前版本号
$CURRENT_VERSION = node -p "require('./package.json').version"
Write-Host " 当前版本: v$CURRENT_VERSION" -ForegroundColor Gray
Write-Host ""
# 6. 提交版本更新
Write-Host "💾 提交版本更新..." -ForegroundColor Cyan
git add packages/*/package.json
git commit -m "chore(release): publish v$COMMON_VERSION"
if ($LASTEXITCODE -ne 0) {
Write-Host " 没有需要提交的更改" -ForegroundColor Gray
}
Write-Host ""
# 7. 发布每个包
# 4. 发布每个包
Write-Host "📤 开始发布包到 npm..." -ForegroundColor Cyan
foreach ($package in $PACKAGES) {
if (Test-Path $package) {
@@ -106,23 +74,18 @@ foreach ($package in $PACKAGES) {
}
}
# 8. 创建 Git 标签
Write-Host "🏷️ 创建 Git 标签..." -ForegroundColor Cyan
git tag "v$COMMON_VERSION"
Write-Host ""
# 9. 推送到远程仓库
# 5. 推送到远程仓库
Write-Host "🔼 推送到远程仓库..." -ForegroundColor Cyan
$push = Read-Host "是否推送到远程仓库? (y/N)"
if ($push -eq "y" -or $push -eq "Y") {
git push origin master
git push origin "v$COMMON_VERSION"
git push origin --tags
Write-Host "✅ 已推送到远程仓库" -ForegroundColor Green
} else {
Write-Host "⚠️ 跳过推送,请手动执行:" -ForegroundColor Yellow
Write-Host " git push origin master" -ForegroundColor Gray
Write-Host " git push origin v$COMMON_VERSION" -ForegroundColor Gray
Write-Host " git push origin --tags" -ForegroundColor Gray
}
Write-Host ""
Write-Host "🎉 所有包发布完成!版本: v$COMMON_VERSION" -ForegroundColor Green
Write-Host "🎉 所有包发布完成!版本: v$CURRENT_VERSION" -ForegroundColor Green
+13 -47
View File
@@ -1,23 +1,13 @@
#!/bin/bash
# 发布所有子包到私有 npm 仓库
# 使用方法: bash scripts/publish.sh [版本类型]
# 版本类型: major | minor | patch (默认 patch)
# 使用方法: bash scripts/publish.sh
# 注意: 发布仓库地址使用各子包 package.json 中的 publishConfig.registry 配置
# 版本管理请先通过 pnpm release (standard-version) 完成,本脚本仅负责构建和发布
set -e
# 获取版本类型参数,默认为 patch
VERSION_TYPE=${1:-patch}
# 验证版本类型
if [[ ! "$VERSION_TYPE" =~ ^(major|minor|patch)$ ]]; then
echo "❌ 无效的版本类型: $VERSION_TYPE"
echo "使用方法: bash scripts/publish.sh [major|minor|patch]"
exit 1
fi
echo "🚀 开始发布流程 (版本类型: $VERSION_TYPE)"
echo "🚀 开始发布流程"
echo ""
# 子包列表
@@ -49,39 +39,20 @@ if ! pnpm test; then
fi
echo ""
# 3. 更新版本号
echo "📝 更新版本号 ($VERSION_TYPE)..."
for package in "${PACKAGES[@]}"; do
if [ -d "$package" ]; then
echo " 更新 $package 版本号..."
cd "$package"
npm version $VERSION_TYPE --no-git-tag-version
cd - > /dev/null
fi
done
echo ""
# 4. 构建所有包
# 3. 构建所有包
echo "📦 构建所有包..."
if ! pnpm build; then
echo "❌构建失败,停止发布"
echo "❌ 构建失败,停止发布"
exit 1
fi
echo ""
# 5. 更新 README 中的版本信息
echo "📄 更新 README..."
COMMON_VERSION=$(node -p "require('./packages/common/package.json').version")
echo " 当前版本: $COMMON_VERSION"
# 获取当前版本号
CURRENT_VERSION=$(node -p "require('./package.json').version")
echo " 当前版本: v$CURRENT_VERSION"
echo ""
# 6. 提交版本更新
echo "💾 提交版本更新..."
git add packages/*/package.json
git commit -m "chore(release): publish v$COMMON_VERSION" || echo " 没有需要提交的更改"
echo ""
# 7. 发布每个包
# 4. 发布每个包
echo "📤 开始发布包到 npm..."
for package in "${PACKAGES[@]}"; do
if [ -d "$package" ]; then
@@ -101,24 +72,19 @@ for package in "${PACKAGES[@]}"; do
fi
done
# 8. 创建 Git 标签
echo "🏷️ 创建 Git 标签..."
git tag "v$COMMON_VERSION"
echo ""
# 9. 推送到远程仓库
# 5. 推送到远程仓库
echo "🔼 推送到远程仓库..."
read -p "是否推送到远程仓库? (y/N) " -n 1 -r
echo
if [[ $REPLY =~ ^[Yy]$ ]]; then
git push origin master
git push origin "v$COMMON_VERSION"
git push origin --tags
echo "✅ 已推送到远程仓库"
else
echo "⚠️ 跳过推送,请手动执行:"
echo " git push origin master"
echo " git push origin v$COMMON_VERSION"
echo " git push origin --tags"
fi
echo ""
echo "🎉 所有包发布完成!版本: v$COMMON_VERSION"
echo "🎉 所有包发布完成!版本: v$CURRENT_VERSION"