Files
2026-08-07 16:18:11 +08:00

180 lines
5.4 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# @windychen/trans-form-middleware — Design (Q1–Q61)
> 设计基线:grill-me 61 题访谈结论(2026-08-06)。配套包:`@windychen/trans-form-component`(Vue 3 动态查询表单)。
## 角色定位
接收组件输出的 filter 数组,解析为结构化条件 `{ field, query, op, value, logic?, values?, empty? }[]`。**不生成 SQL** —— 由上层 ORM/DAO 适配器消费输出。
```js
import { parseFilters } from '@windychen/trans-form-middleware';
const filters = parseFilters(
[
{ field: 'name', value: 'xx', query: 'EQ' },
{ field: 'age', value: '18,30', query: 'BETWEEN', logic: 'AND' }
],
{ allowedFields: ['name', 'age'] }
);
// → [{ field: 'name', query: 'EQ', op: '=', value: 'xx' },
// { field: 'age', query: 'BETWEEN', op: 'BETWEEN', value: '18,30', values: ['18', '30'], logic: 'AND' }]
```
---
## 一、架构与发布
| # | 决策 |
|---|------|
| 1 | middleware:**Node.js 纯 JS** |
| 2 | middleware 输出:**结构化过滤器**,不碰 SQL |
| 3 | **两个独立 Gitea 仓库**,各自 CI、各自发版 |
| 24 | middleware:**零依赖**;后续另做 Knex/TypeORM 适配包 |
| 25 | middleware 发布:**ESM only** |
| 27 | middleware 构建:**不打包**,`package.json` 指向 `src/index.js` |
| 28 | 测试:**Vitest**,CI 里 `npm test` 通过才发布 |
| 29 | 版本号:**完全独立**,兼容性写 README |
| 21 | CI:**复制 windychen-utils 模式**(三关键词 → Verdaccio + Gitea Packages + Release + 钉钉) |
---
## 二、解析规则
### 输出形态
| # | 决策 |
|---|------|
| 8 | 输出同时保留 **`query`(原始码)和 `op`(标准符号)** |
| 14 | `parseOptions.mode`:flat / tree / pass-through,**默认透传 logic** |
| 46 | 多值:同时保留 **`value`(原串)和 `values`(解析数组)** |
### 过滤与校验
| # | 决策 |
|---|------|
| 44 | `parseOptions.strict`,**默认 false(宽松)** |
| 49 | 必须传 **`parseOptions.allowedFields` 白名单** |
| 50 | `unknownField: 'error' \| 'skip'`,**默认 `'error'`** |
### 状态标记处理(Q60–Q61)
| # | 决策 |
|---|------|
| 60 | 组件 filters **全部带状态标记**输出;middleware **默认忽略 disabled**,readOnly 正常解析 |
| 61 | `hidden: true` **默认跳过**(与 disabled 一致);`empty: true` **默认保留**(原样透传),可通过 `parseOptions.skipEmpty: true/false` 控制是否跳过 |
### 空值
| # | 决策 |
|---|------|
| 38 | `empty: true`:**原样保留**,调用方自行过滤(`skipEmpty` 可覆盖) |
| 9 | 组件侧空 value 带 `empty: true` 标记输出 |
---
## 三、操作符
### 内置码表(Q39)
| # | 决策 |
|---|------|
| 39 | 内置默认 **`DEFAULT_OPERATOR_MAP`**,可 merge/覆盖(`operatorMap` 选项) |
| 12 | v1 操作符:比较 + LIKE/IN/NOT_IN + BETWEEN/IS_NULL/IS_NOT_NULL |
| 码 | 符号 | 说明 |
|----|------|------|
| `EQ` | `=` | 等于 |
| `NE` | `<>` | 不等于 |
| `GT` | `>` | 大于 |
| `GTE` | `>=` | 大于等于 |
| `LT` | `<` | 小于 |
| `LTE` | `<=` | 小于等于 |
| `LIKE` | `LIKE` | 模糊 |
| `IN` | `IN` | 属于 |
| `NOT_IN` | `NOT IN` | 不属于 |
| `BETWEEN` | `BETWEEN` | 区间 |
| `IS_NULL` | `IS NULL` | 为空 |
| `IS_NOT_NULL` | `IS NOT NULL` | 非空 |
---
## 四、API 表面
| # | 决策 |
|---|------|
| 40 | 回填能力在 **component 侧**(`setFilters()` / `loadFilters()` / `reset()` ref API,见 component DESIGN 输出协议);middleware 只做单向解析 |
| 41 | 多函数导出:`parseFilters` / `toTree` / `mapOperators` / `splitMultiValue` 等 |
### 导出函数
| 函数 | 作用 |
|------|------|
| `parseFilters(filters, parseOptions?)` | 主入口:校验白名单、映射操作符、处理状态标记、多值拆分 |
| `toTree(filters, parseOptions?)` | 按 `logic` 组装嵌套分组树 |
| `mapOperators(filters, operatorMap?)` | 只做操作符码 → 符号映射 |
| `splitMultiValue(value, separator?)` | 逗号分隔字符串 → 数组 |
### parseOptions 汇总
| 选项 | 默认 | 说明 |
|------|------|------|
| `allowedFields` | **必传** | 字段白名单 |
| `unknownField` | `'error'` | 未知字段:报错或跳过 |
| `strict` | `false` | 宽松/严格模式 |
| `mode` | `pass-through` | flat / tree / pass-through |
| `operatorMap` | `DEFAULT_OPERATOR_MAP` | 合并/覆盖码表 |
| `skipEmpty` | `false` | 是否跳过 `empty: true` 项 |
| `skipFlags` | `['disabled', 'hidden']` | 默认跳过的状态标记 |
---
## 五、输出示例
```json
[
{
"field": "name",
"query": "EQ",
"op": "=",
"value": "xx"
},
{
"field": "tags",
"query": "IN",
"op": "IN",
"value": "a,b,c",
"values": ["a", "b", "c"],
"logic": "OR"
},
{
"field": "status",
"query": "IS_NULL",
"op": "IS NULL",
"value": "",
"empty": true,
"logic": "AND"
}
]
```
---
## 六、与 component 的协议对齐
| 项 | 约定 |
|----|------|
| 输入 | component `getFilters()` / `@change` 输出 |
| 输出字段 | `field`、`value`、`query`、`op`、`logic?`、`values?`、`empty?` |
| 状态标记 | `disabled` / `hidden` 默认跳过;`readOnly` 正常解析 |
| 空值 | `empty: true` 默认保留,`skipEmpty` 可配 |
---
## 七、CI 触发约定
commit message 必须同时包含 `chore` + `版本` + `更新` 才触发构建发布;否则 job 显示 skipped(设计行为,防误触)。
```bash
git commit -m "chore: 版本 0.1.0 更新 ..."
```