mirror of
https://github.com/crmeb/CRMEB.git
synced 2026-10-28 13:31:04 +00:00
feat(移动端): 命名检查与规范覆盖 pages-modules 插件模块
check-naming 目录规则覆盖 pages-modules(snake_case 页面目录、_ 前缀排除区),并强制页面入口唯一形态:非排除位置的 .vue 必须 index.vue,防止 PascalCase 文件被扫描器误注册为路由。docs/命名规范.md 新增 §2.1 插件模块命名细则(模块目录=插件标识、语义后缀惯例、固定文件)与常用营销插件对照表(seckill/combination/bargain/presell/integral/coupon/sign/lottery/distribution)。
This commit is contained in:
parent
9167aca15c
commit
787ecc2400
@ -16,6 +16,7 @@
|
||||
|---|---|---|---|
|
||||
| `src/` 顶层目录 | 全小写单词或 kebab-case | `api/`、`dynamic-pages/` | 已合规 |
|
||||
| `pages/` 页面目录 | **snake_case**,页面入口固定 `index.vue` | `pages/users/user_address/index.vue` | 存量路径冻结(见 §3-1);新页面必须遵守 |
|
||||
| `pages-modules/` 插件模块(免注册分包) | 模块目录 **snake_case**(=插件标识);页面 = snake_case 子目录 + `index.vue`;细则与营销插件对照见 §2.1 | `pages-modules/seckill/goods_details/index.vue` | 新层,无存量 |
|
||||
| `.vue` 组件(`components/`、`dynamic-pages/`、页面内 `components/`) | **PascalCase.vue**;easycom 组件目录与文件同名 | `components/BaseMoney/`、`LogisticsTimeline.vue`、局部组件 `InvoiceModal.vue` | 存量 camelCase(`emptyPage.vue` 等)冻结 |
|
||||
| `subpackage/diyComponents/` DIY 组件 | **契约冻结层,不适用本规范**;新 DIY 组件文件名必须与数据库 `eb_diy.value` 下发的 `name` 字段一致(camelCase) | `homeComb.vue` ↔ name `homeComb` | 冻结 |
|
||||
| `composables/` | `useXxx.js`(camelCase) | `useColorTheme.js` | 已合规 |
|
||||
@ -28,6 +29,28 @@
|
||||
- **页面内局部组件**放在页面目录旁的 `components/` 子目录(复数,勿用单数 `component/`),命名 PascalCase。
|
||||
- 第三方/移植库目录(`mp-html`、`easy-loadimage`、`zb-code`、verify 验证码树、`*.min.js`)保持原名,不适用本规范。
|
||||
|
||||
### 2.1 `pages-modules/` 插件模块命名(免注册分包)
|
||||
|
||||
营销/插件页面(秒杀类)统一投放 `src/pages-modules/`,丢入即自动注册为分包(机制见 `frontend/uni-app/AGENTS.md` 专节)。命名细则:
|
||||
|
||||
1. **模块目录 = 插件标识**:snake_case 英文全拼,与后端模块/插件标识及自有表前缀 `eb_{插件标识}_*` 对齐;一个插件一个模块目录,禁止多插件混放。
|
||||
2. **页面 = snake_case 子目录 + `index.vue`**(`lint:naming` 强制,PascalCase 文件会被扫描器误注册为路由);模块根 `index.vue` 即模块首页。页面目录**不重复模块名**——路径已含前缀,写 `seckill/goods_details/index.vue` 而非 `seckill/seckill_goods_details/`。
|
||||
3. **语义后缀惯例**(对齐存量 `goods_seckill_details` 风格):入口/会场 `index`、子列表 `*_list`、详情 `*_details`、结果/状态 `*_status`、记录 `*_record`、规则说明 `rule`。
|
||||
4. **模块固定/常用文件**:`routes.js` 路由常量(必备,模块内外跳转统一引用,禁止硬编码路径);可选 `api.js`(接口封装,camelCase)、`components/`(局部组件 PascalCase)、`static/`(图片 kebab-case,同 §2 静态资源行)。
|
||||
5. 常用营销插件模块名对照(新增插件参考命名,存量系统页面不受影响):
|
||||
|
||||
| 功能 | 模块目录 | 典型页面(模块内) |
|
||||
|---|---|---|
|
||||
| 秒杀 | `seckill` | `index`(会场)、`goods_details`、`record` |
|
||||
| 拼团 | `combination` | `index`、`goods_details`、`order_status` |
|
||||
| 砍价 | `bargain` | `index`、`goods_details` |
|
||||
| 预售 | `presell` | `index`、`goods_details` |
|
||||
| 积分商城 | `integral` | `index`、`goods_list`、`exchange_record` |
|
||||
| 优惠券 | `coupon` | `index`、`receive_record` |
|
||||
| 签到 | `sign` | `index`、`record` |
|
||||
| 抽奖 | `lottery` | `index`、`record` |
|
||||
| 分销 | `distribution` | `index`、`poster`、`record` |
|
||||
|
||||
## 3. 红线:契约冻结清单(改名即断线上功能,禁止触碰)
|
||||
|
||||
1. **pages.json 已注册的所有页面 path 与分包 root**。
|
||||
|
||||
@ -75,6 +75,14 @@ for (const f of files) {
|
||||
const stem = name.slice(0, name.length - ext.length);
|
||||
if (!IMG_RE.test(stem) || !/[a-z]/.test(stem)) addViolation(relPath, '图片须 kebab-case 全小写且含字母(禁下划线/大写/拼音/纯数字)');
|
||||
}
|
||||
// pages-modules 页面入口唯一形态:snake_case 目录 + index.vue(PascalCase 文件会被误注册为路由)
|
||||
if (ext === '.vue' && name !== 'index.vue' && relPath.startsWith('src/pages-modules/')) {
|
||||
const segs = relPath.split('/');
|
||||
const inner = segs.slice(2, -1); // ['pages-modules', 模块名, ...页面目录祖先]
|
||||
if (!inner.some((s) => ROLE_DIRS.has(s) || s.startsWith('_'))) {
|
||||
addViolation(relPath, 'pages-modules/ 页面必须为 snake_case 目录 + index.vue(局部组件放 components/,细则见 docs/命名规范.md §2.1)');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (const d of dirs) {
|
||||
@ -83,10 +91,14 @@ for (const d of dirs) {
|
||||
const name = segs[segs.length - 1];
|
||||
if (segs.length === 2) {
|
||||
if (!TOP_DIR_RE.test(name)) addViolation(relPath, 'src 顶层目录须全小写或 kebab-case');
|
||||
} else if (segs[1] === 'pages') {
|
||||
} else if (segs[1] === 'pages' || segs[1] === 'pages-modules') {
|
||||
const inner = segs.slice(2, -1); // 该目录的所有祖先段
|
||||
if (!inner.some((s) => ROLE_DIRS.has(s)) && !PAGE_DIR_RE.test(name)) {
|
||||
addViolation(relPath, 'pages/ 页面目录须 snake_case 或全小写单词');
|
||||
// pages-modules 下 `_` 前缀目录为扫描器排除区(_template 模板等),不按页面目录规则校验
|
||||
const exempt =
|
||||
inner.some((s) => ROLE_DIRS.has(s)) ||
|
||||
(segs[1] === 'pages-modules' && (name.startsWith('_') || inner.some((s) => s.startsWith('_'))));
|
||||
if (!exempt && !PAGE_DIR_RE.test(name)) {
|
||||
addViolation(relPath, 'pages/(及 pages-modules/)页面目录须 snake_case 或全小写单词');
|
||||
}
|
||||
} else if (segs[1] === 'components' && segs.length === 3 && !PASCAL_DIR_RE.test(name)) {
|
||||
addViolation(relPath, 'components/ 组件目录须 PascalCase');
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user