mirror of
https://gitee.com/ulthon/ulthon_admin.git
synced 2026-11-10 13:00:49 +08:00
docs(skill): 拆分表格与卡片双技能并同步最新代码
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
---
|
||||
name: "ulthon-admin-table"
|
||||
description: "后台列表页表格机制与定制完整指南:核心机制(ua 命名空间、三件套)、字段配置、内置渲染器、按钮系统(含页面分类标准 A/B/C/D)、搜索系统(前端配置 + 后端 buildTableParames)、后端配套、常见模式与排错、多形态渲染(受控默认数据流与 controlled:false 逃生口、layoutList 五级模板协议 tplFunction/tplLay/tplVue/tplLayId/tplVueId、双端自动注入、按端 layoutDefault、卡片形态、渲染上下文)。需要业务定制 CURD 生成的列表页(加按钮、改字段、调搜索)、排查按钮/搜索不生效、自定义卡片/模板形态、或判断页面是否需要 controlled:false 逃生口时调用。"
|
||||
description: "后台列表页表格机制与定制完整指南:核心机制(ua 命名空间、三件套)、字段配置、内置渲染器、按钮系统(含页面分类标准 A/B/C/D)、搜索系统(前端配置 + 后端 buildTableParames)、后端配套、常见模式与排错、多形态渲染机制(受控默认数据流与 controlled:false 逃生口、layoutList 五级模板协议 tplFunction/tplLay/tplVue/tplLayId/tplVueId、双端自动注入、layoutDefault 按端默认与记忆链、卡片形态)。需要业务定制 CURD 生成的列表页(加按钮、改字段、调搜索)、排查按钮/搜索不生效、配置 layoutList/layoutDefault/视图切换,或判断页面是否需要 controlled:false 逃生口时调用;自定义卡片模板的创作(上下文契约、实战配方、设计模式、坑与验收)见 ulthon-card-template 技能。"
|
||||
---
|
||||
|
||||
# 后台表格机制与定制(ulthon-admin-table)
|
||||
@@ -16,7 +16,7 @@ CURD 生成器生成列表页骨架后,所有业务定制(按钮、字段渲
|
||||
- 自定义字段渲染(图片、状态、关联数据)
|
||||
- 实现状态流转按钮(带 `_if` 显隐)
|
||||
- 跨控制器跳转按钮
|
||||
- 列表自定义卡片/模板形态与表格/卡片切换(`layoutList` + `layoutDefault`,见第十一章)
|
||||
- 列表多形态机制与表格/卡片切换(`layoutList` + `layoutDefault`,见第十一章;自定义卡片模板的创作见 [ulthon-card-template](./ulthon-card-template/SKILL.md) 技能)
|
||||
- 判断页面走的是哪种数据流,或是否需要 `controlled: false` 逃生口(见第十一章)
|
||||
|
||||
## 一、核心机制总览
|
||||
@@ -219,7 +219,7 @@ var init = {
|
||||
|
||||
### 5.1 顶部工具栏(toolbar)
|
||||
|
||||
通过 `ua.table.render({ toolbar: [...] })` 配置。**不声明时默认 `['refresh', 'add', 'delete', 'export']`**——这意味着只读页面如果不覆盖,会显示无用的"新增/删除"按钮(见 9.2 常见错误)。
|
||||
通过 `ua.table.render({ toolbar: [...] })` 配置。**不声明时默认 `['refresh', 'add', 'delete', 'export']`**,这意味着只读页面如果不覆盖,会显示无用的"新增/删除"按钮(见 9.2 常见错误)。
|
||||
|
||||
**字符串简写**(自动检查权限):
|
||||
|
||||
@@ -256,7 +256,7 @@ ua.table.render({
|
||||
|
||||
### 5.2 行级操作按钮(operat)
|
||||
|
||||
在 `cols` 最后一列配置 `templet: ua.table.tool` + `operat` 数组。**不声明 operat 时,tool 函数内自动填充 `['edit', 'delete']`**(admin-table.js:1055)。
|
||||
在 `cols` 最后一列配置 `templet: ua.table.tool` + `operat` 数组。**不声明 operat 时,tool 函数内自动填充 `['edit', 'delete']`**。
|
||||
|
||||
```js
|
||||
{
|
||||
@@ -393,7 +393,7 @@ operat: [
|
||||
]
|
||||
```
|
||||
|
||||
每个 `[]` 内的对象是独立按钮,按顺序渲染。`renderOperat`(admin-table.js:769)做权限整列裁剪:只要任意一个按钮组内有按钮有权限,整列就保留。
|
||||
每个 `[]` 内的对象是独立按钮,按顺序渲染。`renderOperat`(定位见第十章速查表)做权限整列裁剪:只要任意一个按钮组内有按钮有权限,整列就保留。
|
||||
|
||||
## 六、页面分类标准(A/B/C/D)
|
||||
|
||||
@@ -619,37 +619,36 @@ CURD 生成时会将关联模型的全部字段(如 `systemAdmin.*`)输出
|
||||
|
||||
## 十、实测代码引用表
|
||||
|
||||
每个特性标注实测来源(多为文件:行;受控/多形态相关特性因行号随迭代漂移,改用 grep 关键词定位),若代码与本文档冲突,以代码为准。
|
||||
每个特性标注实测来源(文件 + grep 关键词定位;行号随迭代漂移,故不逐条标注行号),若代码与本文档冲突,以代码为准。
|
||||
|
||||
| 特性 | 实测来源 |
|
||||
|------|---------|
|
||||
| `ua.table.render` 入口 | `public/static/plugs/ulthon-admin/admin-table.js:14` |
|
||||
| `formatCols`(cols 加工) | `admin-table.js:921` |
|
||||
| `renderOperat`(操作列整列裁剪) | `admin-table.js:769` |
|
||||
| `renderToolbar`(顶部工具栏) | `admin-table.js:251` |
|
||||
| `renderSearch`(搜索表单生成) | `admin-table.js:294` |
|
||||
| `search` 默认 `true` | `admin-table.js:307`(`ua.parame(d.search, true)`) |
|
||||
| `searchOp` 默认 `'%*%'` | `admin-table.js:312` |
|
||||
| `search: 'number_limit'` / `'time_limit'` | `admin-table.js:348-369` |
|
||||
| `listenTableSearch`(filter+op 构造) | `admin-table.js:1334` |
|
||||
| `tool` 函数(自动填充默认 operat) | `admin-table.js:1053`,自动填充在 1055 |
|
||||
| `tool` 内置 'edit' 处理 | `admin-table.js:1061` |
|
||||
| `tool` 内置 'delete' 处理 | `admin-table.js:1082` |
|
||||
| `operat._if` 显隐判定 | `admin-table.js:1113-1124` |
|
||||
| `operat.auth` 默认 `'add'` | `admin-table.js:1105` |
|
||||
| `list` 渲染器 | `admin-table.js:1169` |
|
||||
| `filePreview` 渲染器 | `admin-table.js:1180` |
|
||||
| `image` 渲染器(imageSplit/imageJoin) | `admin-table.js:1195-1213` |
|
||||
| `url` 渲染器(urlNameField) | `admin-table.js:1215` |
|
||||
| `switch` 渲染器(自动调 modify) | `admin-table.js:1245`,modify 调用在 `listenSwitch:1365` |
|
||||
| `date` 渲染器 | `admin-table.js:1281` |
|
||||
| `ua.getDataBrage` 实现 | `public/static/plugs/ulthon-admin/admin-utils.js:63-74` |
|
||||
| `ua.table.render` 入口 | `public/static/plugs/ulthon-admin/admin-table.js`(`grep "render: function (options)"`) |
|
||||
| `formatCols`(cols 加工) | `admin-table.js`(`grep "formatCols: function"`) |
|
||||
| `renderOperat`(操作列整列裁剪) | `admin-table.js`(`grep "renderOperat(data, elem)"`) |
|
||||
| `renderToolbar`(顶部工具栏) | `admin-table.js`(`grep "renderToolbar: function"`) |
|
||||
| `renderSearch`(搜索表单生成) | `admin-table.js`(`grep "renderSearch: function"`) |
|
||||
| `search` 默认 `true` | `admin-table.js`(`grep "d.search, true"`) |
|
||||
| `searchOp` 默认 `'%*%'` | `admin-table.js`(`grep "d.searchOp"`) |
|
||||
| `search: 'number_limit'` / `'time_limit'` | `admin-table.js`(`grep "number_limit"`) |
|
||||
| `listenTableSearch`(filter+op 构造) | `admin-table.js`(`grep "listenTableSearch: function"`) |
|
||||
| `tool` 函数(自动填充默认 operat) | `admin-table.js`(`grep "operat = option.operat"`,tool 函数内) |
|
||||
| `tool` 内置 'edit' / 'delete' 处理 | 同上 tool 函数内 `case 'edit'` / `case 'delete'` 分支 |
|
||||
| `operat._if` 显隐判定 | `admin-table.js`(`grep "operat._if"`) |
|
||||
| `operat.auth` 默认 `'add'` | `admin-table.js`(`grep "operat.auth = operat.auth \|\|"`) |
|
||||
| `list` 渲染器 | `admin-table.js`(`grep "list: function"`) |
|
||||
| `filePreview` 渲染器 | `admin-table.js`(`grep "filePreview: function"`) |
|
||||
| `image` 渲染器(imageSplit/imageJoin) | `admin-table.js`(`grep "image: function"`) |
|
||||
| `url` 渲染器(urlNameField) | `admin-table.js`(`grep "url: function"`) |
|
||||
| `switch` 渲染器(自动调 modify) | `admin-table.js`(`grep "switch: function"`),modify 调用在 `grep "listenSwitch: function"` |
|
||||
| `date` 渲染器 | `admin-table.js`(`grep "date: function"`) |
|
||||
| `ua.getDataBrage` 实现 | `admin-utils.js`(`grep "ua.getDataBrage = function"`) |
|
||||
| `#data-brage` 隐藏元素 | `extend/base/admin/view/layout/default.html`(layout 文件) |
|
||||
| `data_brage` assign | `extend/base/common/controller/AdminControllerBase.php:273` |
|
||||
| `buildTableParames`(filter+op 解析) | `extend/base/common/controller/AdminControllerBase.php:405` |
|
||||
| `$relationSearch` 属性 | `AdminControllerBase.php:69`(默认 false) |
|
||||
| `$selectWhere` 属性 | `AdminControllerBase.php:63` |
|
||||
| `selectList()` 方法 | `AdminControllerBase.php:489` |
|
||||
| `data_brage` assign | `AdminControllerBase.php`(`grep "assign('data_brage'"`) |
|
||||
| `buildTableParames`(filter+op 解析) | `AdminControllerBase.php`(`grep "function buildTableParames"`) |
|
||||
| `$relationSearch` 属性 | `AdminControllerBase.php`(`grep "protected $relationSearch"`,默认 false) |
|
||||
| `$selectWhere` 属性 | `AdminControllerBase.php`(`grep "protected $selectWhere"`) |
|
||||
| `selectList()` 方法 | `AdminControllerBase.php`(`grep "public function selectList"`) |
|
||||
| 实际示例:标准 CRUD | `extend/base/admin/view/system/admin/index.js` |
|
||||
| 实际示例:`_if` 条件按钮 | `app/admin/view/system/timer_config/index.js` |
|
||||
| 实际示例:自定义 templet | `app/admin/view/system/timer_log/index.js` |
|
||||
@@ -671,12 +670,13 @@ CURD 生成时会将关联模型的全部字段(如 `systemAdmin.*`)输出
|
||||
| renderLayoutForm(模板管线入口) | `grep "renderLayoutForm: function" admin-table.js` |
|
||||
| 统一行选中委托(data-table-id + data-id) | `grep "统一行选中委托" admin-table.js` |
|
||||
| getLayoutForm / setLayoutForm | `grep "getLayoutForm" admin-table.js` |
|
||||
| 内置卡片公共样式(`.ua-data-card` 族) | `grep "ua-data-card" public/static/admin/css/public.css` |
|
||||
| `ua.checkMobile` 判定 | `grep "checkMobile" public/static/common/js/app.js`(`admin-utils.js` 转发) |
|
||||
| 实际示例:三形态 + 按端默认 | `extend/base/admin/view/system/admin/index.js`(render 配置块:layoutList 三形态 + layoutDefault 对象式)+ `index.html`(usercardTpl 模板节点) |
|
||||
| 实际示例:三形态 + 按端默认 | `extend/base/admin/view/system/admin/index.js`(render 配置块:layoutList 三形态 + layoutDefault 对象式)+ `index.html`(usercardTpl 模板节点);第二官方范例 `extend/base/admin/view/mall/goods/`(goodscardTpl + `layoutDefault: 'goodscard'` 字符串写法) |
|
||||
|
||||
## 十一、多形态渲染(受控数据流与自定义模板)
|
||||
## 十一、多形态渲染机制(受控数据流与形态协议)
|
||||
|
||||
`ua.table.render` 页面默认运行在受控数据流上,并默认获得表格/卡片两种形态,两者都是零配置即得。开发者只需要回答两个问题:想定制形态怎么配(`layoutList` + `layoutDefault`,见 11.2),以及自己的页面是否属于少数需要逃生口的场景(`controlled: false`,见 11.1)。官方完整范例是用户管理页:`extend/base/admin/view/system/admin/index.js` 顶部 render 配置里的 layoutList 三形态与 layoutDefault 对象式按端默认,建议直接对照源码。
|
||||
`ua.table.render` 页面默认运行在受控数据流上,并默认获得表格/卡片两种形态,两者都是零配置即得。本章只讲机制:数据流与逃生口(11.1)、形态清单协议与解析链(11.2)、双端默认行为(11.3)。要为自己的页面定制专属卡片模板(适用判断、上下文契约、实战配方、设计模式库、坑与验收),见 [ulthon-card-template](./ulthon-card-template/SKILL.md) 技能。
|
||||
|
||||
### 11.1 受控数据流(默认)与逃生口
|
||||
|
||||
@@ -763,92 +763,30 @@ layoutDefault: true, // 旧协议"自动判断",视
|
||||
|
||||
- `layoutList` 条目数 > 1 时工具栏出现「视图」按钮;点击下拉条目即写记忆并切形态,切换用的是 store 当页数据,零网络请求
|
||||
- 页面显式配置了 `defaultToolbar` 时,视图按钮会自动补投进最终工具栏(自动注入场景下去重追加),普通开发者无需关心
|
||||
- 运行期 API:`ua.table.getLayoutForm(id)` 读当前形态、`ua.table.setLayoutForm(id, name)` 切形态
|
||||
- 运行期 API:`ua.table.getLayoutForm(id)` 读当前形态、`ua.table.setLayoutForm(id, name)` 切形态。API 切换**不写记忆**,只有点视图下拉条目才写 `ua.setPageSetting`;API 切换后刷新会回到记忆形态,这是设计行为
|
||||
- **CURD 页面缺省即得双形态**:CURD 生成的列表页不含任何受控/形态配置,自动获得受控数据流 + 双端「表格/卡片」+ 视图按钮,模板零改动;PC 端缺省表格、手机端缺省卡片
|
||||
|
||||
**两条硬约束**:
|
||||
|
||||
1. 模板渲染容器恒带 `layui-form` 类与 lay-filter(框架自建容器已保证,页面无需关心)。表单控件的渲染美化与事件都要求 `.layui-form` 祖先,模板里写 switch/checkbox 依赖这条保证,缺失则全部失效。
|
||||
2. laytpl/Vue 的模板节点(`<script type="text/html">` / `text/x-template`)**必须写在渲染容器之外**(页面根容器之后即可)。节点若写进容器内会被模板引擎编译时吞掉。这是使用者必须遵守的约束:框架不生成也不搬运模板节点。
|
||||
2. 模板作者侧另有一条位置硬约束(模板节点必须写在渲染容器之外,否则被模板引擎编译时吞掉),约束细节、页面写法与模板契约由 [ulthon-card-template](./ulthon-card-template/SKILL.md) 技能第三章承接。
|
||||
|
||||
### 11.3 渲染上下文
|
||||
|
||||
自定义模板拿到的数据由 `ua.table.buildLayoutContext(tableId)` 构建(调试时可直接在控制台调用查看)。
|
||||
|
||||
**行上下文**(tplFunction 第一参 / laytpl 的 `d` / Vue 的 `v-for` 项):
|
||||
|
||||
| 字段 | 说明 |
|
||||
|------|------|
|
||||
| `...row` | 行原始字段全部可用(username、status、create_time 等) |
|
||||
| `_cells` | 对象,field → 该列 templet 渲染后的 HTML。只有配了渲染器的列才有内容;纯文本列恒为空串,勿引用,直接用原始字段 |
|
||||
| `_operatHtml` | 操作列渲染产物(编辑/删除等按钮 HTML,已按 data-auth-* 裁剪权限) |
|
||||
| `_checked` | 该行是否选中(store 选中集合) |
|
||||
| `_disabled` | 该行是否禁选(行数据 LAY_DISABLED) |
|
||||
|
||||
**列表上下文**(tplFunction 第二参):`{tableId, rows, page, count, checkedAll}`。laytpl 形态挂在 `d._list` 上;Vue 形态叫 `list`,因为 Vue 实例不代理 `_`/`$` 前缀的数据键,裸写 `_list` 会 ReferenceError。
|
||||
|
||||
### 11.4 自定义形态示例
|
||||
|
||||
**laytpl 形态(tplLayId)**,简版:
|
||||
|
||||
```html
|
||||
<!-- 页面模板区:渲染容器之外 -->
|
||||
<script type="text/html" id="myCardTpl">
|
||||
<div class="my-card">
|
||||
<h3>{{- d._cells.title }}</h3>
|
||||
<div>{{- d._operatHtml }}</div>
|
||||
{{# if (d._checked) { }}<i class="layui-icon layui-icon-ok-circle"></i>{{# } }}
|
||||
</div>
|
||||
</script>
|
||||
```
|
||||
|
||||
```js
|
||||
layoutList: ['table', {name: 'mycard', title: '自定义卡', tplLayId: '#myCardTpl'}],
|
||||
```
|
||||
|
||||
laytpl 语法实测(layui 2.10.1 内置 laytpl v2.0.0):`{{ d.x }}` 与 `{{= d.x }}` 都会 HTML 转义,`{{- d.x }}` 才是原样输出。`_cells`/`_operatHtml` 是渲染产物 HTML,必须用 `{{- }}`;纯文本用 `{{ }}` 转义更安全;`{{# }}` 写 JS 语句;列表上下文是 `d._list`。
|
||||
|
||||
**Vue 形态(tplVueId)**,简版:
|
||||
|
||||
```html
|
||||
<!-- 页面模板区:渲染容器之外 -->
|
||||
<script type="text/x-template" id="myVueTpl">
|
||||
<div class="my-card" v-for="d in rows" :key="d.id"
|
||||
:data-id="d.id" :data-table-id="list.tableId"
|
||||
:class="{'ua-data-card-checked': d._checked}">
|
||||
<h3 v-html="d._cells.title"></h3>
|
||||
<div v-html="d._operatHtml"></div>
|
||||
</div>
|
||||
</script>
|
||||
```
|
||||
|
||||
```js
|
||||
layoutList: ['table', {name: 'mycard', title: '自定义卡', tplVueId: '#myVueTpl'}],
|
||||
```
|
||||
|
||||
- `v-for="d in rows"` 承接行循环;`_cells`/`_operatHtml` 必须 `v-html` 输出,纯文本字段用 `{{ }}` 原生插值(自动转义);列表上下文是 `list`
|
||||
- 行根元素带 `data-table-id` + `data-id` 两属性即获得统一行选中委托:点卡片切换勾选、选中态经 `:class` 绑 `ua-data-card-checked` 高亮回显;按钮/表单控件自动豁免不误触,零 JS
|
||||
- 事件无需自己绑定:操作按钮(data-open/data-request 等属性)与 switch/checkbox 经页面级委托与 form 事件天然生效;`@click` 可用,但处理函数内不要修改模板数据(渲染上下文被冻结,数据更新一律整卡销毁重建)
|
||||
|
||||
**完整官方范例**:用户管理三形态(表格 + 名片 + 内置卡片),建议直接对照源码:
|
||||
|
||||
| 位置 | 内容 |
|
||||
|------|------|
|
||||
| `extend/base/admin/view/system/admin/index.js` | render 配置块:layoutList 三形态 + layoutDefault 对象式按端默认(`{pc: 'table', mobile: 'card'}`) |
|
||||
| `extend/base/admin/view/system/admin/index.html` | usercardTpl 模板节点(`<script type="text/x-template">`,位于渲染容器之外)+ 页面级网格样式 |
|
||||
|
||||
该范例演示了三种典型取值通道:渲染器列(status)用 `_cells` + v-html 承接框架语义、纯文本列(username/create_time/phone)直接原始字段插值、头像(head_img)因名片需要圆形大图绕开渲染器直接绑原始字段。模板形态的网格布局由模板自带容器承担(Vue 形态不带内置卡片网格类)。
|
||||
|
||||
### 11.5 双端默认行为
|
||||
### 11.3 双端默认行为
|
||||
|
||||
- 双端自动注入后 PC 端同样有视图切换按钮与卡片形态,端差异只体现在缺省形态上:PC 缺省 `table`,手机缺省 `card`(记忆与按端 layoutDefault 的优先级更高,见 11.2 解析链)
|
||||
- 手机端判定 `ua.checkMobile()`(`admin-utils.js` 转发,实现位于 `public/static/common/js/app.js`):UA 关键字(Android/iPhone/iPad 等)或 `window.screen` 宽 < 600 且高 < 800。判的是物理屏幕指标,**浏览器开发者工具仅改视口宽度不会触发**;设备仿真验证手机默认形态时,必须同时覆写 UA 或仿真 screen 尺寸,仅设 viewport 无效
|
||||
- 卡片形态能力边界:工具栏(刷新/新增/批量删除/导出)与搜索区两形态共用、照常可用;勾选语义由卡片勾位图标与选中委托承接(checkbox 列本身不进模板上下文);`_disabled` 行整元素不可勾选
|
||||
- 卡片形态能力边界:工具栏(刷新/新增/批量删除/导出)与搜索区两形态共用、照常可用;行选中、豁免与 `_disabled` 等模板侧语义由卡片模板契约定义(见 11.4)
|
||||
|
||||
### 11.4 自定义模板指引
|
||||
|
||||
自定义卡片/模板形态的创作不在本技能展开,统一由 [ulthon-card-template](./ulthon-card-template/SKILL.md) 技能承接:渲染上下文契约(`_cells`/`_operatHtml`/`_checked`/`_disabled`、上下文冻结、列表上下文命名)、模板节点位置硬约束、行选中委托与豁免名单、取值通道三规则、usercardTpl/goodscardTpl 范例走读、实战配方、设计模式库、模板作者坑与验收 checklist。本技能只负责机制如何把模板跑起来;两个官方范例的 render 配置块(layoutList 三形态、layoutDefault 对象式与字符串式)见第十章引用表末行,可作机制示范直接对照。
|
||||
|
||||
## 相关技能
|
||||
|
||||
- [ulthon-card-template](./ulthon-card-template/SKILL.md):自定义卡片模板的创作(上下文契约、实战配方、设计模式库、坑与验收);本技能第十一章是其机制前提
|
||||
- [ulthon-scheme-curd-workflow](./ulthon-scheme-curd-workflow/SKILL.md):CURD 代码生成流程(生成本技能所定制的列表页骨架)
|
||||
- [ulthon-scheme-definition](./ulthon-scheme-definition/SKILL.md):Scheme 定义(决定生成哪些字段、字段类型)
|
||||
- [ulthon-page-api-dual-mode](./ulthon-page-api-dual-mode/SKILL.md):页面/接口同体机制(列表接口的 JSON 返回模式)
|
||||
- [ulthon-permission-cli](./ulthon-permission-cli/SKILL.md):权限节点核对(`data-auth-X` 与 `@NodeAnnotation` 对不上时)
|
||||
- [ulthon-tools-http-call](./ulthon-tools-http-call/SKILL.md):CLI 模拟请求验证列表接口
|
||||
- [ulthon-page-qa](./ulthon-page-qa/SKILL.md):页面验证(AI 自测)与浏览器断言要点
|
||||
|
||||
Reference in New Issue
Block a user