admin:permission:nodes 是查看型命令(实时扫描注解、不写库、改注解即生效),但文档/注释多处用一键更新/自动更新/生成等动作词描述,导致开发者系统性误以为它是更新权限节点命令。本次校准 8 个文件 10 处误导措辞,并在命令输出末尾追加机制提示。@NodeAnotation 拼写保持不变(框架故意少一个 t)。
28 KiB
name, description
| name | description |
|---|---|
| ulthon-admin-table | 后台列表页表格机制与定制完整指南:核心机制(ua 命名空间、三件套)、字段配置、内置渲染器、按钮系统(含页面分类标准 A/B/C/D)、搜索系统(前端配置 + 后端 buildTableParames)、后端配套、常见模式与排错。需要业务定制 CURD 生成的列表页(加按钮、改字段、调搜索)或排查按钮/搜索不生效时调用。 |
后台表格机制与定制(ulthon-admin-table)
本技能是后台列表页(基于 layui table 的 ua.table.render)完整指南。涵盖核心机制、字段配置、按钮系统、搜索机制、后端配套,以及实战中的常见模式与排错。
CURD 生成器生成列表页骨架后,所有业务定制(按钮、字段渲染、搜索)都在本技能范畴内。生成流程本身见 ulthon-scheme-curd-workflow。
何时调用
- 业务定制 CURD 生成的列表页(加/改字段、加按钮、调搜索)
- 排查"按钮不显示"、"搜索不生效"、"字段渲染不对"
- 自定义字段渲染(图片、状态、关联数据)
- 实现状态流转按钮(带
_if显隐) - 跨控制器跳转按钮
一、核心机制总览
1.1 ua 命名空间
ua = ulthon-admin 的 JS 全局对象,定义在 public/static/plugs/ulthon-admin/:
| 文件 | 作用 |
|---|---|
admin-table.js (1650 行) |
表格核心:render / formatCols / renderOperat / 内置渲染器 / 搜索监听 |
admin-core.js |
ua 全局组装、headers、url、parame 等工具 |
admin-utils.js |
ua.getDataBrage 等数据读取工具 |
admin-listen.js |
事件监听(ua.listen) |
admin-api.js |
AJAX 请求封装(ua.request) |
ulthon-admin.js |
入口(把 UA_ADMIN 挂到 window.ua) |
1.2 表格三件套
每个 CURD 模块的列表页由三个文件配合:
app/admin/view/<module>/
├── index.html # 极简 HTML,仅 table 元素 + data-auth-* 权限标记
├── _common.js # init 对象(URL 配置等)
└── index.js # ua.table.render({init, cols, toolbar?})
index.html(典型示例,仅 11 行):
<div class="layuimini-container">
<div class="layuimini-main">
<table id="currentTable" class="layui-table layui-hide"
data-auth-index="{:auth('system.timer_config/index')}"
data-auth-edit="{:auth('system.timer_config/edit')}"
data-auth-export="{:auth('system.timer_config/export')}"
data-auth-modify="{:auth('system.timer_config/modify')}"
lay-filter="currentTable">
</table>
</div>
</div>
data-auth-X 是按钮权限显隐的关键:JS 里的 auth: 'X' 必须能在 HTML 找到对应的 data-auth-X,且值为 1 才显示。详见第六章。
1.3 前后端链路
[前端] index.js 的 cols 配置
│
├─ search: 'select'/'range'/false ──► [前端] renderSearch 自动生成搜索表单
│ │
│ ▼ 用户提交
│ [前端] listenTableSearch 构造 {filter, op} JSON
│ │
└─ templet: ua.table.xxx ──► [前端] tool/image/switch 渲染单元格
│
▼ GET /admin/<module>/index?filter={...}&op={...}
[后端] AdminControllerBase::buildTableParames()
│
├─ 解析 filter + op 为 WHERE 数组(按 op 操作符构造)
├─ relationSearch:关联表搜索时自动加 `table.field` 前缀
└─ 返回 [$page, $limit, $where, $excludes, $request_options, $group]
│
▼
[后端] 模型查询 → 分页数据 → JSON 返回 → 前端表格渲染
二、init 对象(_common.js 内容)
init 是表格的"配置中心",在 _common.js 中定义,被 index.js 引用。
完整字段表:
| 字段 | 类型 | 说明 |
|---|---|---|
tableElem |
string | 表格元素选择器,默认 '#currentTable' |
tableRenderId |
string | 表格实例 ID,用于 reload,默认 'currentTableRenderId' |
indexUrl |
string | 列表数据 URL(如 'system.timer_config/index') |
addUrl |
string | '' | 新增页 URL,空字符串则不显示新增按钮 |
editUrl |
string | '' | 编辑页 URL |
readUrl |
string | '' | 详情页 URL |
deleteUrl |
string | '' | 删除接口 URL |
exportUrl |
string | '' | 导出接口 URL |
modifyUrl |
string | '' | 状态开关修改接口 URL(switch 渲染器自动调用) |
formFullScreen |
'true' | 'false' | 表单是否全屏(字符串) |
典型示例(app/admin/view/system/timer_log/_common.js):
var init = {
tableElem: '#currentTable',
tableRenderId: 'currentTableRenderId',
indexUrl: 'system.timer_log/index',
addUrl: '',
editUrl: '',
readUrl: 'system.timer_log/read',
deleteUrl: '',
exportUrl: '',
modifyUrl: '',
};
只读列表(B 类页面,详见第六章)的所有写按钮 URL 留空字符串即可。
三、字段配置(cols 数组项)
ua.table.render({ cols: [[...]] }) 的 cols 是二维数组(layui 标准),每个列项支持以下参数。
3.1 基础参数
| 参数 | 类型 | 说明 |
|---|---|---|
field |
string | 数据字段名;支持关联字段如 appCodeBind.tube_code |
title |
string | 表头文字 |
width |
number | 列宽(像素) |
minWidth |
number | 最小列宽 |
sort |
boolean | 是否允许排序 |
type |
string | 特殊列:'checkbox'(多选)/ 'radio'(单选) |
fixed |
'left' | 'right' | 固定列 |
edit |
'text' | 行内编辑(更新到 modifyUrl) |
hide |
boolean | 默认隐藏(用户可在列配置里开启) |
3.2 渲染参数
| 参数 | 类型 | 说明 |
|---|---|---|
templet |
function | 渲染函数,接收 data 返回 HTML。可用内置渲染器(见第五章)或自定义函数 |
defaultValue |
string | 数据为空时的默认显示值 |
3.3 搜索参数(详见第七章)
| 参数 | 类型 | 默认值 | 说明 |
|---|---|---|---|
search |
boolean | string | true |
搜索类型:true(文本)/ false(不搜索)/ 'select'(下拉)/ 'number_limit'(数值区间)/ 'time_limit'(时间区间)/ 'range'(范围) |
searchOp |
string | '%*%' |
搜索操作符,对应后端 WHERE 构造(见 7.1) |
selectList |
object | {} |
下拉选项;常用 ua.getDataBrage('select_list_xxx') 从页面字典读取 |
searchUrl |
string | - | 远程下拉数据源(如 'system.timer_log/index?selectFields=task_name') |
searchValue |
string | - | 搜索框默认值 |
defaultSearchValue |
string | - | 默认搜索值(可从 URL query 自动回填) |
searchHide |
boolean | false | 是否默认隐藏该搜索项 |
fieldAlias |
string | = field |
搜索参数别名(用于关联表搜索时指定 table.field) |
searchTip |
string | '请输入' + title |
搜索框 placeholder |
timeType |
string | 'datetime' |
时间搜索组件类型 |
注意:
search默认是true(每列默认参与搜索),要关闭必须显式search: false。
四、内置渲染器(templet 取值)
通过 templet: ua.table.xxx 使用框架内置渲染器。
4.1 内置渲染器清单
| 渲染器 | 用途 | 关键参数 |
|---|---|---|
ua.table.image |
单图/多图显示 | imageWidth(默认 200)/ imageHeight(默认 26)/ imageSplit(默认 |)/ imageJoin(默认 <br>) |
ua.table.switch |
开关组件(自动调 modify 接口) | filter(默认 = field)/ checked(默认 1,等于该值时勾选) |
ua.table.list |
根据 selectList 映射显示文本 | selectList |
ua.table.date |
日期格式化 | (从字段值自动格式化) |
ua.table.url |
链接显示 | urlNameField(链接显示文字字段,可为 string 或 function) |
ua.table.filePreview |
文件预览(图片或图标) | (根据 mime_type 自动判断) |
ua.table.tool |
行操作按钮渲染器(特殊,见第六章) | operat(按钮配置数组) |
4.2 使用示例
// 图片字段(自动识别多图,按 | 分隔)
{field: 'head_img', title: '头像', search: false, templet: ua.table.image}
// 状态开关(自动调 modifyUrl,data 字段为 id,value 为 0/1)
{field: 'status', title: '状态', search: 'select',
selectList: {0: '禁用', 1: '启用'}, templet: ua.table.switch}
// 状态徽章(用 list 把 0/1 映射成文字)
{field: 'status', title: '状态', search: 'select',
selectList: {0: '禁用', 1: '启用'}, templet: ua.table.list}
// 时间字段
{field: 'create_time', title: '创建时间', search: 'range', templet: ua.table.date}
4.3 自定义 templet 函数
{field: 'is_synced', title: '同步状态', width: 100, templet: function(d) {
if (d.is_synced == 1) {
return '<span class="layui-badge layui-bg-green">已同步</span>';
}
return '<span class="layui-badge">未同步</span>';
}}
自定义 templet 接收行数据 d,返回 HTML 字符串。
五、按钮系统
后台表格有两类按钮:顶部工具栏(toolbar)和行级操作按钮(operat)。
5.1 顶部工具栏(toolbar)
通过 ua.table.render({ toolbar: [...] }) 配置。不声明时默认 ['refresh', 'add', 'delete', 'export']——这意味着只读页面如果不覆盖,会显示无用的"新增/删除"按钮(见 9.2 常见错误)。
字符串简写(自动检查权限):
| 值 | 行为 | 权限节点 |
|---|---|---|
'refresh' |
刷新按钮(不带权限) | - |
'add' |
新增按钮,打开 init.addUrl |
<module>/add |
'delete' |
批量删除(需配合 checkbox) | <module>/delete |
'export' |
导出按钮,请求 init.exportUrl |
<module>/export |
'selectConfirm' |
选择器模式的"确定选择"按钮 | - |
自定义按钮对象:
ua.table.render({
toolbar: [
'add', // 简写可与自定义混用
[{
text: '导入',
url: 'demo.index/import',
method: 'open', // 见 5.3 method 表
auth: 'import', // 对应 data-auth-import
class: 'layui-btn layui-btn-warm layui-btn-sm',
icon: 'fa fa-upload',
title: '导入数据',
extend: 'data-full="true"' // 额外 HTML 属性
}]
],
// ...
});
自定义按钮对象参数与行按钮通用,详见 5.4。
5.2 行级操作按钮(operat)
在 cols 最后一列配置 templet: ua.table.tool + operat 数组。不声明 operat 时,tool 函数内自动填充 ['edit', 'delete'](admin-table.js:1055)。
{
field: '',
title: '操作',
width: 250,
fixed: 'right',
templet: ua.table.tool,
operat: [
'edit', // 字符串简写
[{
text: '设置密码',
url: init.password_url, // 来自 _common.js
method: 'open',
auth: 'password',
class: 'layui-btn layui-btn-normal layui-btn-xs',
field: 'id', // URL 拼接的主键字段
titleField: 'username', // 弹窗标题用某字段值(如"设置密码 - admin")
}],
'delete'
]
}
字符串简写:
| 值 | 行为 | 默认 method | 权限节点 |
|---|---|---|---|
'edit' |
编辑按钮 | 'tab'(标签页打开) |
<module>/edit |
'delete' |
删除按钮(带确认) | 'get' |
<module>/delete |
5.3 method 方法表
| method | 行为 | 适用场景 |
|---|---|---|
'tab' |
主内容区导航(layuimini-content-href) | 详情页、编辑页(全页面跳转) |
'open' |
弹窗打开(layer.open iframe) | 添加、导入等弹窗表单 |
'request' |
AJAX GET 请求 + 自动 confirm | 危险/不可逆操作:解绑、撤销、封闭 |
'blank' |
新标签页打开 | 外部链接、文件预览 |
'get' |
直接 GET 请求(不带 confirm) | 内置 'delete' 用此方法 |
'none' |
不绑定行为,配合 extend 自定义监听 | 自定义 JS 交互 |
5.4 自定义按钮对象完整参数表
| 参数 | 类型 | 默认值 | 说明 |
|---|---|---|---|
text |
string | - | 按钮文字 |
title |
string | = text |
提示文字 / 弹窗标题 / request 方法的 confirm 文案 |
url |
string | function | '' |
请求 URL;为 function 时接收 (data, operat) 动态构造 |
method |
string | 'open' |
见 5.3 method 表 |
field |
string | function | 'id' |
URL 拼接的主键字段名;为 function 时可动态构造 URL |
auth |
string | 'add' |
权限节点名(对应 HTML 的 data-auth-X) |
class |
string | '' |
HTML class(layui-btn 样式) |
icon |
string | '' |
图标 class |
extend |
string | '' |
额外 HTML 属性(如 data-full="true") |
titleField |
string | - | 用数据中某字段值作为标题(如"编辑 - 张三") |
extra |
string | - | 标题附加字段(自动拼到 title 前) |
_if |
function | string | 始终显示 | 显隐条件:function 接收 (data, operat) 返回布尔;string 时按字段名取值 |
callback |
function | - | 点击回调(覆盖默认行为) |
checkbox |
boolean | false | 是否需要选中行 |
data |
string[] | ['id'] |
绑定到 HTML 的数据字段,生成 data-{key}="{value}" |
5.5 按钮颜色语义约定
| 颜色 | class | 语义 |
|---|---|---|
| 灰色 | layui-btn-primary |
查看 / 中性操作 |
| 绿色 | layui-btn-success |
编辑 / 正向操作(内置 'edit' 默认) |
| 蓝色 | layui-btn-normal |
恢复 / 新增入口 |
| 橙色 | layui-btn-warm |
警告 / 可逆危险操作 |
| 红色 | layui-btn-danger |
危险 / 不可逆操作(内置 'delete' 默认) |
5.6 _if 条件显隐(最常用的进阶特性)
operat: [
'edit',
[{
text: '触发',
url: init.triggerUrl,
method: 'request',
auth: 'trigger',
class: 'layui-btn layui-btn-warm layui-btn-xs',
// 仅 run_type='manual' 时显示
_if: function(data) {
return data.run_type === 'manual';
}
}]
]
_if 支持两种形式:
- 函数:
function(data) { return boolean },data 是当前行数据 - 字符串:传字段名,该字段为真才显示(如
'_if': 'is_active')
未声明 _if 时默认恒真(总是显示)。条件按钮缺少 _if 是常见错误(见 9.2)。
5.7 跨控制器权限检查
按钮跳转到其他控制器的页面时(如 box_sn 页面的"绑定"按钮跳转 code_bind/scan),auth 的权限节点不在当前控制器下。需要在 HTML 用自定义 key 声明跨控制器的 data-auth 属性。
HTML:
<table ... data-auth-bind="{:auth('app.code_bind/scan')}" ...>
JS:
[{
class: 'layui-btn layui-btn-normal layui-btn-sm',
method: 'tab',
text: '绑定',
title: '扫码绑定',
auth: 'bind', // 对应 HTML 中的 data-auth-bind
url: 'app.code_bind/scan', // 跨控制器 URL
icon: 'fa fa-link'
}]
框架通过 data-auth-{auth值} 查找 HTML 属性做权限校验:有权限显示按钮,无权限自动隐藏。
5.8 operat 数组结构
operat 是一个数组,元素有两种形态,可混用:
operat: [
[/* 按钮组1:每个对象是一个按钮 */],
[/* 按钮组2 */],
'edit', // 字符串简写
'delete'
]
每个 [] 内的对象是独立按钮,按顺序渲染。renderOperat(admin-table.js:769)做权限整列裁剪:只要任意一个按钮组内有按钮有权限,整列就保留。
六、页面分类标准(A/B/C/D)
根据数据的来源和维护方式,每个列表页必定属于以下某一类。每个页面都应显式声明属于哪一类,并按对应标准配置 toolbar + operat。
A 类:完整 CRUD
数据由后台用户主动创建和维护,支持完整的增删改查。
toolbar: [/* 自定义按钮(如有) */, 'add', 'delete', 'export'],
operat: [[/* 详情 */], [/* 业务操作(如有) */], 'edit', 'delete']
B 类:只读列表
数据由系统流程生成或外部同步,后台仅查看,不支持增删改。
toolbar: [],
defaultToolbar: ['filter'],
operat: [[/* 仅详情 */]]
C 类:有限操作
数据由系统流程生成,不支持通用 add/edit/delete,但支持特定的业务操作(状态流转、撤销等)。
toolbar: [[/* 特定入口按钮 */]/* , 'export'(如需) */],
operat: [[/* 详情 */], [/* 业务按钮(带 _if) */]]
// 不含 'edit' / 'delete',除非有明确的业务需求
D 类:表单交互
非标准列表页,以表单/扫码交互为主,表格仅作为结果展示。
toolbar: [],
// 通常无操作列,或仅详情
七、搜索系统
7.1 前端配置:searchOp 操作符表
cols 项的 searchOp 决定后端如何构造 WHERE:
| searchOp | 后端 WHERE 构造 | 适用场景 |
|---|---|---|
'%*%'(默认) |
LIKE '%val%' |
通用文本模糊搜索 |
'*%' |
LIKE 'val%' |
前缀匹配(如编号) |
'%*' |
LIKE '%val' |
后缀匹配 |
'=' |
= val |
精确匹配(如状态) |
'in' |
IN (val) |
多值匹配 |
'min' |
>= val |
数值最小值 |
'max' |
<= val |
数值最大值 |
'min_date' |
>= strtotime(val) |
日期最小值(前端传字符串,后端转时间戳) |
'max_date' |
<= strtotime(val) |
日期最大值 |
'range' |
>= strtotime(begin) AND <= strtotime(end) |
时间范围(前端用 search: 'range' 自动生成起止输入) |
'none' |
不进 where,作为 request_options |
业务自定义参数(不查库) |
默认操作符是
%*%'(LIKE 模糊匹配)。搜索"不灵活"的错觉来源于不知道可以覆盖searchOp。
7.2 搜索类型与 searchOp 的关系
search 值 |
UI 类型 | 默认提交参数 | 常配 searchOp |
|---|---|---|---|
true(默认) |
文本输入框 | filter[field]=val |
%*% 或自定义 |
false |
不显示搜索项 | - | - |
'select' |
下拉选择 | filter[field]=val |
= |
'number_limit' |
数值区间(生成 [field]min/[field]max) |
filter[field]min=val&filter[field]max=val |
自动用 min/max |
'time_limit' |
时间区间 | 同上但格式为日期 | 自动用 min_date/max_date |
'range' |
时间范围选择器 | filter[field]=begin - end |
range |
7.3 select_list_* 字典通道(下拉数据来源)
下拉选项的标准通道,三处对齐:
- 后端 assign(控制器里):
$this->assign('select_list_{名}', $字典数组, true);- 第三个参数
true表示同时压入data_brage通道 - 例:
$this->assign('select_list_status', StatusService::SN_STATUS_OPTIONS, true);
- 第三个参数
- 页面渲染:所有 assign 变量被打包成 JSON,渲染进隐藏元素
<script id="data-brage" type="text/plain">{$data_brage|raw|default='[]'}</script>(位于 layout) - 前端读取:
ua.getDataBrage('select_list_{名}')从#data-brage解析取值
// cols 中引用:
{field: 'status', search: 'select', selectList: ua.getDataBrage('select_list_status'), ...}
口诀:控制器
assign的 key 必须等于 cols 里ua.getDataBrage('xxx')的参数,否则下拉为空。
7.4 后端处理:buildTableParames
AdminControllerBase::buildTableParames() 自动解析前端传入的 filter + op 参数为 WHERE 数组(extend/base/common/controller/AdminControllerBase.php:405):
// 控制器 index 方法典型用法
public function index()
{
list($page, $limit, $where, $excludes, $request_options, $group) = $this->buildTableParames();
$list = $this->model
->where($where)
->page($page, $limit)
->select();
// ...
}
支持:
$excludeFields:buildTableParames(['field_to_exclude'])排除某些字段不进 whererelationSearch:控制器属性$relationSearch = true时,自动给字段加table.field前缀$request_options:op='none'的字段会进入此变量(业务自定义参数)
八、后端控制器配套
| 配套项 | 说明 |
|---|---|
index() |
使用 buildTableParames() 构造查询 |
$relationSearch |
bool 属性,开启关联表搜索(默认 false) |
$selectWhere |
array 属性,selectList() 方法的过滤条件 |
modify() |
状态开关接口,switch 渲染器自动调用,接收 id/field/value |
selectList() |
下拉数据源接口,接收 selectFields 参数 |
@NodeAnnotation |
控制器方法注解,生成权限节点(与 data-auth-X 对应) |
关联搜索示例(extend/base/admin/controller/mall/GoodsBase.php):
class GoodsBase extends AdminController
{
protected $relationSearch = true;
// 此时 cols 中 field: 'cate.title' 会自动转为 where: ['mall_goods.cate_id' => ...]
// 注意:关联字段需在模型里定义好 with 关系
}
九、常见模式与排错
9.1 常见模式速查(参考示例)
| 场景 | 参考文件 |
|---|---|
| 标准列表(增删改查 + 状态开关) | extend/base/admin/view/system/admin/index.js |
| 行内排序(edit: 'text') | extend/base/admin/view/system/admin/index.js(sort 字段) |
| 多按钮(设置密码 + 编辑 + 删除) | extend/base/admin/view/system/admin/index.js |
_if 控制按钮显隐 |
app/admin/view/system/timer_config/index.js(仅 manual 显示触发按钮) |
| 详情按钮 + 状态徽章 | app/admin/view/system/timer_config/index.js |
| 关联表数据展示 | extend/base/admin/view/mall/goods/index.js(含 cate 信息) |
| 树形列表 | extend/base/admin/view/system/menu/index.js |
| 文件管理(图标预览) | extend/base/admin/view/system/uploadfile/index.js |
| 权限分配 UI(双表格) | extend/base/admin/view/system/auth/assign_users.js |
| 时间范围搜索 | app/admin/view/system/timer_log/index.js(start_time 用 search: 'range') |
| 自定义 templet(多状态徽章) | app/admin/view/system/timer_log/index.js(status 字段) |
9.2 常见错误模式
错误 1:operat 未声明 → CURD 默认 edit/delete
// 错误:依赖默认值
{ title: '操作', templet: ua.table.tool }
// tool 函数内自动填充 operat = ['edit', 'delete'],即使业务不需要
// 正确:显式声明,哪怕只保留详情
{ title: '操作', templet: ua.table.tool, operat: [[/* 详情 */]] }
错误 2:toolbar 未声明 → 默认含 add/delete/export
// 错误:只读页面(B 类)不覆盖 toolbar
ua.table.render({ init: init, cols: [[...]] });
// 默认 toolbar = ['refresh', 'add', 'delete', 'export'],但 addUrl/deleteUrl 可能为空,按钮仍显示但点击报错
// 正确:只读页面显式清空
ua.table.render({ init: init, toolbar: [], defaultToolbar: ['filter'], cols: [[...]] });
错误 3:条件按钮缺少 _if
// 错误:按钮始终显示,后端校验拒绝
{ text: '解绑', method: 'request', url: init.unbindUrl }
// 正确:前端条件过滤,减少无效点击
{ text: '解绑', method: 'request', url: init.unbindUrl,
_if: function (data) { return data.status == 可解绑状态值; } }
错误 4:CURD 关联残留列
CURD 生成时会将关联模型的全部字段(如 systemAdmin.*)输出为列。每个页面应清理掉不需要展示的关联残留列,只保留业务需要的字段。
错误 5:select_list_ 不对应(下拉为空)*
控制器 assign('select_list_xxx', ...) 的 key 必须与 cols 里 ua.getDataBrage('select_list_xxx') 的参数完全一致(大小写敏感)。
错误 6:权限节点不匹配(按钮不显示)
- HTML 的
data-auth-X必须存在 - JS 里的
auth: 'X'必须能找到对应的data-auth-X {:auth('controller/action')}的节点路径必须与控制器@NodeAnnotation一致
排查工具:php think admin:permission:nodes(见 ulthon-permission-cli)
9.3 排错指南
"按钮不显示"排查步骤:
- 检查 HTML 是否声明了对应的
data-auth-X(用浏览器开发者工具看 table 元素) - 检查
{:auth('xxx/yyy')}的返回值是否为 1(用超管账号测试排除权限问题) - 检查 JS 里
auth: 'X'的 X 与 HTMLdata-auth-X是否完全一致(大小写) - 查看权限节点列表:
php think admin:permission:nodes
"搜索不生效"排查步骤:
- 浏览器抓 network 看请求是否带
filter和op参数 - 检查
filterJSON 是否包含期望的字段 - 检查对应字段的
op值是否符合预期(默认%*%) - 后端用
php think tools:db:query "SELECT ... WHERE ..."直接查表确认数据存在 - 检查控制器是否调用了
buildTableParames()而不是手动where()
十、实测代码引用表
每个特性都标注实测来源(文件:行),若代码与本文档冲突,以代码为准。
| 特性 | 实测来源 |
|---|---|
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 |
#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 |
| 实际示例:标准 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 |
相关技能
- ulthon-scheme-curd-workflow:CURD 代码生成流程(生成本技能所定制的列表页骨架)
- ulthon-scheme-definition:Scheme 定义(决定生成哪些字段、字段类型)
- ulthon-page-api-dual-mode:页面/接口同体机制(列表接口的 JSON 返回模式)
- ulthon-permission-cli:权限节点核对(
data-auth-X与@NodeAnnotation对不上时) - ulthon-tools-http-call:CLI 模拟请求验证列表接口