@ruovea/codingrule
v1.0.8
Published
编码规则模块(源码包,Vue 3 插件化依赖注入)
Readme
@ruovea/codingrule
编码规则模块,以 pnpm 源码包 形式提供给各宿主项目复用。
- 不打 dist、不发 npm——exports 直指
./src/*,由宿主 Vite 编译 - 依赖注入解耦——request / auth / i18n 由宿主装配时注入
- 零侵入——包内不含
/@/等宿主别名引用,可独立运行,不绑定特定宿主
一、目录结构
src/
├─ index.ts # 入口:导出 CodingRulePlugin + API + 类型 + useCodingRuleSN
├─ plugin.ts # Vue install(校验必填项 / provide / mergeLocaleMessage)
├─ context.ts # InjectionKey + useCodingRuleContext()
├─ types.ts # CodingRulePluginOptions
├─ routes.ts # 1 条静态路由(可选使用)
├─ api/
│ ├─ index.ts # 9 个 API 函数
│ ├─ http.ts # request 注入点
│ ├─ endpoints.ts # URL 前缀(可覆盖)
│ └─ codingRule.ts # 编码规则 CRUD + 生成流水号(支持 inputChar)+ 生成记录分页查询
├─ i18n/locales/ # 6 语言(en / fr-fr / ja-jp / vi-vn / zh-cn / zh-tw)
├─ components/
│ ├─ searchExpand.vue # 搜索区展开/收起按钮
│ └─ codingRuleSNInput.vue # 单据编码输入框 + SN 取号按钮(自包含)
├─ composables/
│ ├─ useSearchExpand.ts # 搜索区展开/收起状态
│ └─ useCodingRuleSN.ts # 取号逻辑(可复用于自定义 UI)
└─ views/codingRule/
├─ index.vue # 编码规则列表页(展示最大长度/是否补齐列;生成编码弹窗可传 inputChar;「生成记录」弹窗查看 BasCodingRuleRecord)
└─ component/editCodingRule.vue # 新增/编辑弹窗(规则明细展示精简表格,新增/编辑走独立弹窗表单)一·五、编辑弹窗支持的规则分段与规则级配置
与后端
RuoVea.OmiApi.CodingRule对齐(后端已支持,前端表单同步补齐)。
规则明细在编辑弹窗内用精简表格展示(序号 / 规则类型 / 分段长度 / 各类型字段 / 编辑 / 删除),新增或编辑某条明细时弹出独立表单按规则类型联动字段;行列已按类型展示对应字段,未涉及的列显示 -。序号即排序值:明细的 sort 由行号自动生成(从 1 连续递增),无需手动填写。
四种分段类型
| type | 说明 | 需填参数 |
|------|------|----------|
| Fixeds | 固定字符,原样拼接 | 固定值 |
| RuleFixed | 日期时间,按格式输出 | 日期格式 |
| Serial | 自增流水号(支持循环归零) | 流水长度 / 起始值 / 步长 / 补位码 |
| InputChar | 输入字符,取值 = 生成时传入的 inputChar | 无(生成时传入) |
InputChar分段本身不需要配置值,由「生成编码」弹窗传入的inputChar决定。
每段公共字段
- 分段长度
length:该段生成内容超过此长度时截断;流水号补零位数仍由「流水长度」决定。
流水号循环归零(Serial 段)
| 字段 | 说明 |
|------|------|
| cycleFlag | 是否循环,开启后流水号在周期结束时自动归零回起始值 |
| cycleMethod | 循环方式:按年(1)/按月(2)/按天(3)/按小时(4)/按分钟(5)/按传入字符(10) |
规则级补齐 / 截断(作用于拼接后的完整编码)
| 字段 | 说明 |
|------|------|
| maxLength | 编码最大长度 |
| padded | 是否补齐 |
| paddedChar | 补齐字符(默认 0) |
| paddedMethod | 补齐方式:左补齐(1) / 右补齐(2) |
分段级
length管「每一段内部」;规则级maxLength管「拼接后整串」。
inputChar 双用语义
inputChar 是唯一的生成入口参数,同时服务两个目的:
- 输入字符段(
InputChar):inputChar作为该分段内容,原样拼入编码; - 流水号按传入字符循环(
cycleMethod=10):inputChar作为流水号的分桶 key,不同值各自独立计数。
同一规则同时存在「输入字符段 + 按字符循环流水号」时,同一字符串双用:既拼进编码,又作为分桶 key。改传不同 inputChar 会切换分桶并从起始值重新累计。
二、宿主接入
2.1 安装
宿主 package.json 用 link: 协议指向本仓库:
{
"dependencies": {
"@ruovea/codingrule": "link:../../codingrule-module/packages/codingrule"
}
}cd <codingrule-module 目录> && pnpm install # 包内依赖
cd <宿主> && pnpm install # 建立 link⚠️
link:方式下包的真实路径在宿主根目录之外,宿主vite.config.ts必须显式 dedupe,否则包内import 'element-plus'会解析失败(构建期报Rollup failed to resolve import "element-plus"):resolve: { alias, dedupe: ['vue', 'element-plus', 'vue-i18n', 'axios'], },
peerDependencies: vue / element-plus / axios / vue-i18n,由宿主提供,包内不重复安装。
2.2 装配插件
// plugins/codingrule.ts
import type { App } from 'vue';
import { CodingRulePlugin } from '@ruovea/codingrule';
import request from '/@/utils/request';
import { auth } from '/@/utils/authFunction';
import { i18n } from '/@/i18n/index';
export function setupCodingRule(app: App) {
app.use(CodingRulePlugin, {
request: request as any,
auth,
i18n: i18n as any,
});
}// main.ts
import { setupCodingRule } from '/@/plugins/codingrule';
// ... app.use(pinia) 之后
setupCodingRule(app);三、CodingRulePluginOptions 说明
| 字段 | 必填 | 说明 |
|---|---|---|
| request | ✅ | 宿主 axios 实例(已配 baseURL / token / 拦截器) |
| auth | ➖ | (code: string) => boolean,按钮权限校验,缺省 () => true |
| i18n | ➖ | 宿主 vue-i18n 实例(用于 mergeLocaleMessage) |
| endpoints | ➖ | 覆盖 API URL 前缀(见下方 Endpoints 章节) |
| registerI18n | ➖ | 是否自动 merge i18n,默认 true |
与 article 模块不同,codingrule 无需注入宿主组件,所有 UI 均使用 element-plus 自包含。
子路径导出:
@ruovea/codingrule(插件 / API / 类型 / composables)、/api、/routes、/types、/views/*、/components/*、/composables/*。
i18n 注入约定
包内视图使用 message.codingrule.xxx / message.router.codingRule 格式的 key。插件 merge 时同时注册到顶层和 message 层,兼容宿主两级结构。
四、Endpoints 说明
interface CodingRuleEndpoints {
basCodingRulePages: '/BasCodingRule/Pages'
basCodingRuleData: '/BasCodingRule/Data'
basCodingRuleList: '/BasCodingRule/List'
basCodingRuleAdd: '/BasCodingRule/AddData'
basCodingRuleUpdate: '/BasCodingRule/UpdateData'
basCodingRuleDelete: '/BasCodingRule/DeleteData'
basCodingRuleDeleteBatch: '/BasCodingRule/DeleteBatch'
basCodingRuleSN: '/BasCodingRule/SN'
basCodingRuleRecordPages: '/BasCodingRuleRecord/Pages'
}五、权限编码清单
| 编码 | 位置 | 说明 |
|---|---|---|
| codingRule:add | 编码规则列表 | 新增按钮 |
| codingRule:edit | 编码规则列表 | 编辑按钮 |
| codingRule:delete | 编码规则列表 | 删除按钮 |
| codingRule:sn | 编码规则列表 | 生成编码按钮 |
六、单据编码取号控件
业务编辑页需要「单据编码输入框 + SN 取号按钮」时,直接用包内自包含组件,不要在各页面重复实现 generateNo。
6.1 组件 CodingRuleSNInput
<el-form-item label="单据编码" prop="no" :rules="[{ required: true, message: '单据编码不能为空', trigger: 'blur' }]">
<CodingRuleSNInput ref="snRef" v-model="state.ruleForm.no" code="SO" :disabled="state.ruleForm.id > 0" />
</el-form-item>import CodingRuleSNInput from '@ruovea/codingrule/components/codingRuleSNInput.vue';
const snRef = ref();
const openDialog = (row: any) => {
state.ruleForm = JSON.parse(JSON.stringify(row));
// 新增态自动取号(等价于原先的 if (!no) generateNo())
if (!state.ruleForm.no) snRef.value?.generate();
state.isShowDialog = true;
};| 属性 | 类型 | 说明 |
|---|---|---|
| modelValue | string | 单号,配合 v-model |
| code | string | 编码规则编码(必填),如 PO / SO / IN / OUT / RT / MOR / DOC |
| disabled | boolean | 只读 + 禁用取号按钮(编辑态通常传 id > 0) |
| placeholder | string | 占位文案,缺省取 message.codingrule.pleaseEnterCode |
| inputChar | string | 动态字符:作 InputChar 分段内容,或作按字符循环的分组 key |
| buttonText | string | 取号按钮文案,默认 SN,可传「生成」「取号」等 |
| 事件 | 说明 |
|---|---|
| update:modelValue | 单号变化 |
| generated | 取号成功,参数为新单号 |
| generated-failed | 取号失败(组件内已弹错误提示) |
暴露方法:generate(inputChar?)(手动取号,返回 Promise<void>;不传 inputChar 时用 prop 上的值)、loading。
inputChar对应后端BasCodingRuleService.GetSNAsync(code, inputChar)的第二个参数,语义双用:既是「输入字符」分段的取值,也是流水号「按传入字符循环」的分桶 key。同一规则两者并存时,同一字符串同时承担两种用途。每次调用都会推进服务端流水号,不要做防抖/节流封装。
6.2 逻辑复用 useCodingRuleSN
需要自定义 UI 时只复用逻辑,不引入组件:
import { useCodingRuleSN } from '@ruovea/codingrule';
import { useI18n } from 'vue-i18n';
const { t } = useI18n();
const { loading, generate } = useCodingRuleSN();
const no = await generate('SO');
if (!no) ElMessage.error(t('message.codingrule.generateSNFailed'));注意:
generate()内部已用包内 i18n 提示失败,不要再叠加一次ElMessage.error。取号每次都会推进服务端流水号,不要做防抖/节流封装。
七、路由
| path | name | keepAlive | 说明 |
|---|---|---|---|
| /business/codingRule | codingRule | ✅ | 编码规则列表 |
路由
meta.title使用硬编码中文'编码规则',菜单国际化通过包内 locale 文件的router.codingRule键实现(插件 merge 后t('router.codingRule')可命中)。
八、Vite 预构建排除
⚠️ 宿主
vite.config.ts的optimizeDeps.exclude必须包含@ruovea/codingrule,否则会出现"页面进入即报『查询失败』、但 Network 面板无任何请求"的诡异现象。
现象
- 列表页一打开就
ElMessage.error('查询失败'); - 浏览器 DevTools Network 面板没有发出任何 HTTP 请求;
- 控制台抛出
[@ruovea/codingrule] request 未注入,请先 install 插件。
根因
本包是 pnpm 源码包,package.json 的 exports 把 . 与 ./api 都指向 ./src/*。若不排除预构建,Vite 会把主入口 @ruovea/codingrule 预打包成 node_modules/.vite/deps/@ruovea_codingrule.js,但 ./api 子路径仍走源码 src/api/index.ts → src/api/http.ts。两端各持一份模块级 _request:
main.ts中setupCodingrule(app)→CodingRulePlugin.install→__setRequest(request)写入的是预构建产物里的_request;- 视图层
import { apiBasCodingRulePagesPost } from '@ruovea/codingrule/api'拿到的是源码 http.ts 的_request,永远是undefined; - 视图调
apiBasCodingRulePagesPost(params)→http()→ throw → catch →ElMessage.error('查询失败'),全程不进 axios,所以无网络请求。
修复
宿主 vite.config.ts:
optimizeDeps: {
exclude: ['vue-demi', '@ruovea/codingrule'],
},改完清除 Vite 预构建缓存后重启 dev:
rm -rf Web/node_modules/.vite/deps
pnpm dev验证
重启后进入"编码规则"菜单,DevTools Network 应能看到 GET /BasCodingRule/Pages?... 请求,列表正常渲染。
九、License
MIT
