📜 Admin.js
ThinkAdmin 的 admin.js 是后台核心 JavaScript 框架,提供了丰富的工具函数和组件,简化前端开发流程。本文档基于源代码分析,提供完整的使用说明。
🚀 核心模块概览
主要模块
- $.base: 基础工具函数(事件注册、确认回调、规则应用等)
- $.msg: 消息提示组件(成功、错误、警告、确认、通知等)
- $.form: 表单自动化组件(页面加载、跳转、弹窗、iframe等)
- $.menu: 菜单辅助插件(URI 解析、菜单导航、HASH 路由等)
- $.layTable: 表格组件封装(动态表格、分页、搜索、排序等)
- $.vali: 表单验证组件(自动验证、手动验证等)
全局配置
// 应用根路径(自动计算)
window.appRoot = '/static/';
window.baseRoot = '/static/';
window.tapiRoot = '/admin'; // 或通过 window.taAdmin 自定义
// LayUI 配置
layui.config({base: baseRoot + 'plugs/layui_exts/'});
// RequireJS 配置(支持多种插件库)
require.config({
baseUrl: baseRoot,
paths: {
'excel': ['plugs/admin/excel'],
'queue': ['plugs/admin/queue'],
'upload': [tapiRoot + '/api.upload/index?'],
'validate': ['plugs/admin/validate'],
// ... 更多插件
}
});📋 消息提示
基础消息提示
成功提示
// 基础用法
$.msg.success('操作成功!');
// 指定显示时间(秒)
$.msg.success('操作成功!', 3);
// 带回调函数
$.msg.success('操作成功!', 3, function() {
console.log('消息已关闭');
});错误提示
// 基础用法
$.msg.error('操作失败!');
// 指定显示时间(秒,默认3秒)
$.msg.error('操作失败!', 5);
// 带回调函数
$.msg.error('操作失败!', 5, function() {
console.log('错误消息已关闭');
});普通提示
// 基础用法
$.msg.tips('这是一条提示信息');
// 指定显示时间(秒,默认3秒)
$.msg.tips('这是一条提示信息', 5);
// 带回调函数
$.msg.tips('这是一条提示信息', 5, function() {
console.log('提示已关闭');
});警告框
// 基础用法
$.msg.alert('警告信息', function() {
// 关闭后的回调
console.log('警告框已关闭');
});确认对话框
// 基础用法
$.msg.confirm('确认要删除这条记录吗?', function(idx) {
// 点击确认后的回调
console.log('用户点击了确认');
$.msg.close(idx); // 关闭对话框
}, function(idx) {
// 点击取消后的回调(可选)
console.log('用户点击了取消');
$.msg.close(idx); // 关闭对话框
});加载提示
// 显示加载提示
var loadIdx = $.msg.loading('正在加载...');
// 显示加载提示(无文字)
var loadIdx = $.msg.loading();
// 关闭加载提示
$.msg.close(loadIdx);
// 关闭所有消息
$.msg.close();通知提示(Notify)
// 基础用法
$.msg.notify('标题', '内容');
$.msg.notify('标题', '内容', 3000); // 3秒后自动关闭
// 带类型的通知
$.msg.notify('成功', '操作成功', 3000, {
type: 'success',
position: 'top-right'
});
// 错误通知
$.msg.notify('错误', '操作失败', 5000, {
type: 'error',
position: 'top-right'
});
// 信息通知
$.msg.notify('提示', '这是一条提示信息', 3000, {
type: 'info',
position: 'bottom-right'
});
// 高级配置(带按钮和自定义图标)
$.msg.notify('系统通知', '有新的消息需要处理', 5000, {
type: 'info',
position: 'top-right',
width: '400px',
showProgress: true,
animation: {
open: 'fade-in',
close: 'slide-out'
},
image: {
visible: true,
customImage: '/static/plugs/notify/img/info.png'
},
showButtons: true,
buttons: {
action: {
text: '查看',
callback: function(event) {
$.form.open('/admin/oplog/index');
}
},
cancel: {
text: '取消',
callback: function(event) {
console.log('取消');
}
}
}
});参数说明:
title(string): 通知标题message(string): 通知内容time(number, 可选): 自动关闭时间(毫秒),默认 3000option(object, 可选): 配置选项type(string): 通知类型,可选值:alert、success、error、warning、infoposition(string): 显示位置,可选值:top-left、top-right、bottom-left、bottom-right、top-center、bottom-center,默认top-rightwidth(string): 通知框宽度,默认400pxcloseTimeout(number|boolean): 自动关闭延时(毫秒),false表示不自动关闭showProgress(boolean): 是否显示进度条animation(object): 动画配置image(object): 图标配置showButtons(boolean): 是否显示按钮buttons(object): 按钮配置
自动处理响应
// 自动处理服务器返回的 JSON 数据
$.msg.auto({
code: 1, // 状态码,1表示成功,0表示失败
info: '操作成功!', // 提示信息
url: '/admin/user/index', // 跳转地址(可选)
data: 'javascript:console.log("执行JS")' // 或执行JS代码(可选)
}, 3); // 3秒后跳转
// 失败时自动显示错误
$.msg.auto({
code: 0,
info: '操作失败!',
url: '/admin/user/index'
});弹窗管理
// 关闭当前元素所在的弹窗
$.msg.closeThisModal(element);
// 关闭顶层最新弹窗
$.msg.closeLastModal();
// 关闭指定弹窗
$.msg.close(layerIndex);
// 关闭所有消息
$.msg.close();页面加载层
// 检查页面加载层状态
if ($.msg.page.stat()) {
console.log('页面正在加载');
}
// 显示页面加载层
$.msg.page.show();
// 隐藏页面加载层
$.msg.page.hide();
// 完成加载(自动隐藏)
$.msg.page.done();📋 表单组件
页面刷新
// 刷新当前页面(单页应用模式)
$.form.reload();
// 强制刷新(重新加载整个页面)
$.form.reload(true);页面跳转
// 普通页面跳转
$.form.goto('/admin/user/index');
// 执行 JavaScript 代码
$.form.goto('javascript:console.log("执行JS")');异步加载数据
// 基础用法
$.form.load('/admin/user/index', {}, 'GET', function(res, time) {
// 加载成功后的回调
console.log('加载成功', res);
}, true, '正在加载...', 3);
// 参数说明
$.form.load(
url, // 请求地址
data, // 请求数据(对象或表单元素)
method, // 请求方法:'GET' 或 'POST',默认 'GET'
callable, // 成功回调函数(可选)
loading, // 是否显示加载提示,默认 true
tips, // 加载提示文字(可选)
time, // 自动处理响应的时间(可选)
headers // 请求头(可选)
);
// 实际示例
$.form.load('/admin/user/save', {
id: 1,
username: 'test',
_token_: 'token_value' // 表单令牌会自动添加到请求头
}, 'POST', function(res) {
if (res.code > 0) {
$.msg.success(res.info);
$.layTable.reload('UserData');
} else {
$.msg.error(res.info);
}
return false; // 返回 false 阻止自动处理
}, true, '正在保存...');打开页面(HASH 路由)
// 在内容区打开页面(单页应用模式)
$.form.href('/admin/user/index', element, hash);
// 实际使用(通常通过 data-open 属性)
// <a data-open="/admin/user/index">打开页面</a>加载并显示内容
// 加载 HTML 内容并显示在内容区
$.form.open('/admin/user/form', {}, function($dom) {
// 内容加载后的回调
console.log('内容已加载', $dom);
}, true, '正在加载...');
// 参数说明
$.form.open(
url, // 请求地址
data, // 请求数据(可选)
call, // 回调函数(可选)
load, // 是否显示加载提示(可选)
tips // 加载提示文字(可选)
);打开 iframe 弹窗
// 基础用法
var iframeIdx = $.form.iframe('/admin/user/edit?id=1', '编辑用户', ['800px', '600px']);
// 完整参数
var iframeIdx = $.form.iframe(
url, // iframe 地址
name, // 弹窗标题
area, // 弹窗大小 ['宽度', '高度'] 或字符串
offset, // 弹窗位置,默认 'auto'(居中)
destroy, // 关闭时的回调函数(可选)
success, // 打开成功后的回调(可选)
isfull, // 是否全屏,默认 false
maxmin // 是否显示最大化/最小化按钮,默认 false
);
// 实际示例
$.form.iframe('/admin/user/preview?id=1', '用户预览', ['900px', '700px'], 'auto', function() {
// 关闭时刷新表格
$.layTable.reload('UserData');
}, function($dom, idx) {
// 打开成功后的回调
console.log('iframe 已打开', idx);
}, false, true);打开 HTML 弹窗
// 基础用法
var modalIdx = $.form.modal('/admin/user/form', {}, '添加用户', function($dom) {
// 弹窗打开后的回调
console.log('弹窗已打开', $dom);
}, true, '正在加载...', ['800px', '600px']);
// 完整参数
var modalIdx = $.form.modal(
url, // 请求地址
data, // 请求数据(可选)
name, // 弹窗标题,'false' 表示不显示标题
call, // 打开成功后的回调(可选)
load, // 是否显示加载提示(可选)
tips, // 加载提示文字(可选)
area, // 弹窗大小,字符串或数组(可选)
offset, // 弹窗位置,默认 'auto'(可选)
isfull, // 是否全屏,默认 false(可选)
maxmin // 是否显示最大化/最小化按钮,默认 false(可选)
);
// 返回 Promise 对象,可监听事件
var defer = $.form.modal('/admin/user/form', {}, '添加用户');
defer.progress(function(type) {
if (type === 'modal.close') {
console.log('弹窗已关闭');
$.layTable.reload('UserData');
} else if (type === 'modal.success') {
console.log('弹窗打开成功');
}
});内容区域初始化
// 初始化内容区域(自动处理表单、日期选择器等)
var $dom = $.form.reInit($('.think-page-body'));
// 自动处理的功能:
// 1. 渲染 LayUI 表单和元素
// 2. 初始化表单验证监听
// 3. 处理必填字段标签样式
// 4. 处理懒加载图片
// 5. 初始化日期选择器(data-date-input, data-date-range)📋 菜单插件
URI 解析
// 获取 URI 地址
var uri = $.menu.getUri('https://example.com/admin/user/index?id=1');
// 返回: '/admin/user/index'
// 查询菜单节点
var node = $.menu.queryNode('/admin/user/index');
// 返回: 'm-1-2-3' 或空字符串
// 解析完整 URL 为 URI(带参数)
var uri = $.menu.parseUri('/admin/user/index?id=1&name=test', element);
// 返回: '/admin/user/index?spm=m-1-2-3&id=1&name=test'菜单导航
// 页面 HASH 跳转
$.menu.href('#/admin/user/index', 'm-1-2-3');
// 同步菜单状态
$.menu.sync(1); // 1: 同步到缓存
$.menu.sync(2); // 2: 从缓存同步到展示菜单初始化
// 初始化菜单(自动调用)
$.menu.listen();
// 自动处理:
// 1. 菜单折叠/展开
// 2. 窗口大小变化
// 3. HASH 路由切换
// 4. 菜单提示(Mini 模式)📋 表格组件
创建表格
// 基础用法
$('#UserData').layTable({
url: '/admin/user/index',
cols: [[
{checkbox: true},
{field: 'id', title: 'ID', width: 80, sort: true},
{field: 'username', title: '用户名', minWidth: 120},
{field: 'nickname', title: '昵称', minWidth: 120},
{toolbar: '#toolbar', title: '操作', width: 150}
]]
});
// 完整配置
$('#UserData').layTable({
url: '/admin/user/index',
height: 'full', // 自动填充高度
page: true, // 启用分页,false 表示不分页
limit: 20, // 每页显示数量
even: true, // 开启隔行背景
sort: {field: 'id', type: 'desc'}, // 默认排序
autoSort: true, // 自动排序
loading: true, // 显示加载动画
cols: [[
{checkbox: true},
{field: 'id', title: 'ID', width: 80, sort: true},
{field: 'username', title: '用户名', minWidth: 120},
{toolbar: '#toolbar', title: '操作', width: 150}
]],
where: {status: 1}, // 初始查询条件
search: 'form[data-table-id="UserData"]', // 关联搜索表单
checked: '[data-table-id="UserData"]', // 关联选择项
done: function(res, curr, count) {
// 表格渲染完成后的回调
console.log('表格渲染完成', res);
},
filter: function(data, res) {
// 数据过滤回调
return data;
}
});表格操作
// 重新加载表格数据
$.layTable.reload('UserData');
// 重新加载多个表格
$.layTable.reload('UserData,OrderData');
// 重新渲染表格
$.layTable.render('UserData');
// 重新加载并重置到第一页
$('#UserData').trigger('reload', {
page: {curr: 1},
where: {status: 1}
});
// 重新加载并保持当前页
$('#UserData').trigger('reload', {
where: {keyword: 'test'}
});
// 重新加载数据(不重新渲染)
$('#UserData').trigger('reloadData', {
where: {status: 1}
});表格事件
// 监听表格事件
$('#UserData').on('row', function(callback) {
layui.table.on('row(UserData)', callback);
}).on('sort', function(callback) {
layui.table.on('sort(UserData)', callback);
}).on('toolbar', function(callback) {
layui.table.on('toolbar(UserData)', callback);
}).on('checkbox', function(callback) {
layui.table.on('checkbox(UserData)', callback);
}).on('rowDouble', function(callback) {
// 双击行事件
layui.table.on('rowDouble(UserData)', callback);
});表格工具方法
// 显示图片(用于表格列模板)
var html = $.layTable.showImage('/static/image.jpg', true, 'sm', '标题');
// 参数:图片地址、是否圆形、尺寸(ss/sm/md/lg)、标题
// 设置表格全屏高度
$('#UserData').trigger('setFullHeight');表格工具栏模板
<script type="text/html" id="toolbar">
<!--{if auth('edit')}-->
<a data-open='{:url("edit")}?id={{d.id}}'
data-title="编辑用户"
class="layui-btn layui-btn-xs layui-btn-normal">编辑</a>
<!--{/if}-->
<!--{if auth('remove')}-->
<a data-action='{:url("remove")}'
data-value="id#{{d.id}}"
data-confirm="确认要删除这条记录吗?"
class="layui-btn layui-btn-xs layui-btn-danger">删除</a>
<!--{/if}-->
</script>📋 数据属性
data-action 自动提交
<!-- 单条记录操作 -->
<button data-action="{:url('save')}"
data-value="id#{{d.id}};status#1"
data-confirm="确认要启用这条记录吗?"
data-table-id="UserData"
data-csrf="{:systoken('save')}"
class="layui-btn layui-btn-sm">启用</button>
<!-- 批量操作(使用 data-rule) -->
<button data-action="{:url('remove')}"
data-rule="id#{key}"
data-table-id="UserData"
data-confirm="确认要删除选中的记录吗?"
class="layui-btn layui-btn-sm layui-btn-danger">批量删除</button>
<!-- 批量操作(使用 data-table-id + data-rule) -->
<button data-action="{:url('save')}"
data-table-id="UserData"
data-rule="status#1;type#normal"
data-confirm="确认要批量更新吗?"
class="layui-btn layui-btn-sm">批量更新</button>参数说明:
data-action: 提交地址(必需)data-value: 提交的数据,格式:key1#value1;key2#value2data-rule: 提交规则,格式:key1#{key};key2#value,{key}表示从选中项获取值data-table-id: 关联的表格ID,操作成功后自动刷新data-csrf或data-token: 表单令牌data-confirm: 确认提示文字data-method: 请求方法,默认 'POST'data-loading: 是否显示加载提示,默认 true,'false' 表示不显示data-tips: 加载提示文字data-time: 自动处理响应的时间
data-load 异步加载
<!-- 异步加载页面内容 -->
<a data-load="{:url('detail')}?id={{d.id}}"
data-tips="正在加载详情..."
class="layui-btn layui-btn-xs">查看详情</a>
<!-- 加载后刷新表格 -->
<a data-load="{:url('edit')}?id={{d.id}}"
data-table-id="UserData"
class="layui-btn layui-btn-xs">编辑</a>
<!-- 加载后执行回调 -->
<a data-load="{:url('action')}"
data-value="id#{{d.id}}"
data-table-id="UserData"
data-time="false"
class="layui-btn layui-btn-xs">操作</a>参数说明:
data-load: 加载地址(必需)data-value: 提交的数据data-table-id: 关联的表格ID,加载成功后自动刷新data-tips: 加载提示文字data-time: 自动处理响应的时间,'false' 表示不自动处理data-loading: 是否显示加载提示,默认 true
data-open 打开页面
<!-- 打开新页面(单页应用模式) -->
<a data-open="{:url('edit')}?id={{d.id}}"
class="layui-btn layui-btn-xs">编辑</a>
<!-- 打开外部链接 -->
<a data-open="https://example.com"
class="layui-btn layui-btn-xs">外部链接</a>说明:
- 如果 URL 以
http://或https://开头,会直接跳转 - 否则使用 HASH 路由在内容区打开
data-modal 打开弹窗
<!-- 基础用法 -->
<a data-modal="{:url('form')}"
data-title="添加用户"
class="layui-btn layui-btn-xs">添加</a>
<!-- 完整参数 -->
<a data-modal="{:url('form')}?id={{d.id}}"
data-title="编辑用户"
data-area="['800px', '600px']"
data-width="800px"
data-offset="auto"
data-full=""
data-maxmin="true"
data-close-refresh="UserData"
data-value="id#{{d.id}}"
class="layui-btn layui-btn-xs">编辑</a>参数说明:
data-modal: 弹窗地址(必需)data-title: 弹窗标题data-area: 弹窗大小,格式:['宽度', '高度']或字符串data-width: 弹窗宽度(可选,与 data-area 二选一)data-offset: 弹窗位置,默认 'auto'(居中)data-full: 是否全屏,存在即全屏data-maxmin: 是否显示最大化/最小化按钮data-close-refresh: 关闭后刷新的表格IDdata-value: 提交的数据
data-iframe 打开 iframe 弹窗
<!-- 基础用法 -->
<a data-iframe="{:url('preview')}?id={{d.id}}"
data-title="预览内容"
class="layui-btn layui-btn-xs">预览</a>
<!-- 完整参数 -->
<a data-iframe="{:url('preview')}"
data-title="预览内容"
data-area="['900px', '700px']"
data-width="900px"
data-height="700px"
data-offset="auto"
data-full=""
data-maxmin="true"
data-refresh="UserData"
data-value="id#{{d.id}}"
class="layui-btn layui-btn-xs">预览</a>参数说明:
data-iframe: iframe 地址(必需)data-title: 弹窗标题data-area: 弹窗大小,格式:['宽度', '高度']data-width: 弹窗宽度(可选)data-height: 弹窗高度(可选)data-offset: 弹窗位置,默认 'auto'data-full: 是否全屏,存在即全屏data-maxmin: 是否显示最大化/最小化按钮data-refresh: 关闭后刷新的表格IDdata-value: 提交的数据
data-reload 刷新表格
<!-- 刷新指定表格 -->
<button data-reload="UserData"
class="layui-btn layui-btn-sm">刷新</button>
<!-- 刷新所有表格 -->
<button data-reload="true"
class="layui-btn layui-btn-sm">刷新全部</button>data-queue 异步任务
<!-- 执行异步任务 -->
<button data-queue="{:url('export')}"
data-value="id#{{d.id}}"
class="layui-btn layui-btn-sm">导出数据</button>说明:
- 后端返回任务编号(以 'Q' 开头),前端自动显示任务进度
- 需要配合
$.loadQueue()使用
data-file 文件上传
<!-- 基础文件上传 -->
<a data-file
data-path="upload/file"
data-type="pdf,doc,docx"
data-size="10485760"
class="layui-btn">上传文件</a>
<!-- 单图上传 -->
<a data-file="image"
data-path="upload/image"
data-type="jpg,png,gif"
data-size="2097152"
data-field="headimg"
class="layui-btn">上传图片</a>
<!-- 多图选择器 -->
<a data-file="images"
class="layui-btn">选择图片</a>参数说明:
data-file: 文件类型,image表示单图,images表示多图选择器,其他表示普通文件data-path: 上传路径data-type: 允许的文件类型data-size: 文件大小限制(字节)data-field: 关联的表单字段名data-uptype: 存储类型,如 'local'
data-csrf 表单令牌
<!-- 在 data-action 中使用 -->
<button data-action="{:url('save')}"
data-csrf="{:systoken('save')}"
class="layui-btn">保存</button>说明:
- 表单令牌会自动添加到请求头
User-Form-Token - 也可以使用
data-token属性
其他数据属性
<!-- data-check-target: 全选/取消全选 -->
<input type="checkbox" data-check-target=".item-checkbox">
<!-- data-blur-number: 失焦时格式化数字 -->
<input type="number" data-blur-number="2" data-value-min="0" data-value-max="100">
<!-- data-action-blur: 失焦时提交 -->
<input type="text"
data-action-blur="{:url('check')}"
data-value="id#{{d.id}};field#username;value#{value}"
data-loading="false">
<!-- data-href: 页面跳转 -->
<a data-href="/admin/user/index">跳转</a>
<!-- data-copy: 复制到剪贴板 -->
<span data-copy="要复制的内容">点击复制</span>
<!-- data-icon: 图标选择器 -->
<a data-icon data-field="icon">选择图标</a>
<!-- data-video-player: 视频播放器 -->
<a data-video-player="视频地址" data-title="视频标题">播放视频</a>
<!-- data-phone-view: 手机预览 -->
<a data-phone-view="页面地址">手机预览</a>
<!-- data-tips-text: 文字提示 -->
<span data-tips-text="提示内容" data-tips-type="3" data-tips-color="#78BA32">悬停查看</span>
<!-- data-tips-image: 图片提示(悬停) -->
<img data-tips-image="/path/to/image.jpg" data-tips-hover>
<!-- data-tips-image: 图片预览(点击) -->
<img data-tips-image="/path/to/image.jpg">
<!-- data-target-submit: 提交表单 -->
<button data-target-submit="form#myForm">提交</button>
<!-- data-target-backup: 返回上一页 -->
<button data-target-backup="确定要返回吗?">返回</button>
<!-- data-dbclick: 双击事件 -->
<div data-dbclick="[data-edit]">双击编辑</div>📋 表单验证
自动验证表单
<!-- 自动验证表单 -->
<form data-auto="true" method="post" action="{:url('save')}">
<input type="text" name="username" required placeholder="用户名">
<input type="email" name="email" required placeholder="邮箱">
<button type="submit" class="layui-btn">提交</button>
</form>表单属性:
data-auto="true": 启用自动验证data-table-id: 关联的表格ID,提交成功后自动刷新data-tips: 提交时的提示文字data-time: 自动处理响应的时间data-confirm: 提交前的确认提示data-callable: 自定义回调函数名
手动验证表单
// 手动验证表单
$('#userForm').vali(function(data) {
// 验证通过后的回调
console.log('验证通过', data);
$.form.load('/admin/user/save', data, 'POST');
}, function(data, vali) {
// 初始化回调
console.log('表单初始化', data);
});表单搜索
<!-- 搜索表单 -->
<form class="form-search" data-table-id="UserData">
<input type="text" name="keyword" placeholder="搜索关键词">
<button type="submit" class="layui-btn">搜索</button>
</form>说明:
- 搜索表单需要添加
form-search类 data-table-id指定关联的表格ID- 提交后自动刷新表格并重置到第一页
自动监听表单
// 自动监听所有 data-auto="true" 的表单
$.vali.listen();
// 监听指定区域内的表单
$.vali.listen($('.my-container'));📋 文件上传
单图上传
<!-- 单图上传 -->
<input type="text"
name="image"
data-path="upload/image"
data-type="jpg,png,gif"
data-size="2097152"
data-max-width="1920"
data-max-height="1080"
data-cut-width="800"
data-cut-height="600"
placeholder="请上传图片">
<script>
$(function() {
$('input[name="image"]').uploadOneImage();
});
</script>多图上传
<!-- 多图上传 -->
<input type="text"
name="images"
data-path="upload/images"
data-type="jpg,png,gif"
placeholder="请上传图片">
<script>
$(function() {
$('input[name="images"]').uploadMultipleImage();
});
</script>视频上传
<!-- 视频上传 -->
<input type="text"
name="video"
data-path="upload/video"
data-type="mp4"
data-size="104857600"
placeholder="请上传视频">
<script>
$(function() {
$('input[name="video"]').uploadOneVideo();
});
</script>通用文件上传
<!-- 通用文件上传 -->
<a data-file
data-path="upload/file"
data-type="pdf,doc,docx"
data-size="10485760"
data-field="file_url"
class="layui-btn">上传文件</a>📋 基础工具
事件注册
// 注册单次事件(避免重复绑定)
$.base.onEvent('click', '.my-button', function() {
console.log('按钮被点击');
});
// 注册确认回调
$.base.onConfirm('确认要执行此操作吗?', function() {
console.log('用户确认了操作');
});应用规则值
// 应用 data-value 和 data-rule 规则
$.base.applyRuleValue(element, {}, function(data, elem, dset) {
// 处理数据
console.log('应用规则', data);
});获取加载回调
// 获取表格加载回调
var callback = $.base.onConfirm.getLoadCallable('UserData', function() {
console.log('自定义回调');
});📋 其他工具函数
格式化文件大小
var size = $.formatFileSize(1048576); // '1.00M'
var size = $.formatFileSize(1048576, 0); // '1M'预览图片
// 预览单张图片
$.previewImage('/static/image.jpg');
// 预览图片(指定大小)
$.previewImage('/static/image.jpg', '800px');手机预览页面
$.previewPhonePage('https://example.com', '页面标题');文本框插入内容
$('textarea').insertAtCursor('插入的内容');标签输入
<input type="text" name="tags" value="标签1,标签2,标签3">
<script>
$(function() {
$('input[name="tags"]').initTagInput();
});
</script>表单转 JSON
// 将表单数据转换为 JSON 对象
var data = $('form').formToJson();
// 支持复杂表单结构,如:name[0][field] => {name: [{field: value}]}异步任务队列
// 显示任务进度
$.loadQueue('Q1234567890', true, element);
// 参数说明:
// code: 任务编号(以 'Q' 开头)
// doScript: 是否执行脚本,默认 false
// element: 关联的元素(可选)📋 完整示例
用户管理列表页面
{extend name="public/container" /}
{block name="content"}
<!-- 搜索表单 -->
<form class="layui-form layui-card form-search" data-table-id="UserData">
<div class="layui-form-item">
<label class="layui-form-label">关键词</label>
<div class="layui-input-inline">
<input type="text" name="keyword" placeholder="用户名/昵称/手机号" class="layui-input">
</div>
<div class="layui-input-inline">
<button type="submit" class="layui-btn">搜索</button>
<button type="reset" class="layui-btn layui-btn-primary">重置</button>
</div>
</div>
</form>
<!-- 操作按钮 -->
<div class="layui-card">
<div class="layui-card-body">
<button data-modal='{:url("add")}'
data-title="添加用户"
data-table-id="UserData"
class="layui-btn layui-btn-sm layui-btn-primary">添加用户</button>
<button data-action='{:url("remove")}'
data-rule="id#{key}"
data-table-id="UserData"
data-confirm="确认要删除选中的记录吗?"
class="layui-btn layui-btn-sm layui-btn-danger">批量删除</button>
</div>
</div>
<!-- 数据表格 -->
<table id="UserData" lay-filter="UserData"></table>
<!-- 工具栏模板 -->
<script type="text/html" id="toolbar">
<!--{if auth('edit')}-->
<a data-modal='{:url("edit")}?id={{d.id}}'
data-title="编辑用户"
data-table-id="UserData"
class="layui-btn layui-btn-xs layui-btn-normal">编辑</a>
<!--{/if}-->
<!--{if auth('remove')}-->
<a data-action='{:url("remove")}'
data-value="id#{{d.id}}"
data-confirm="确认要删除这条记录吗?"
data-table-id="UserData"
class="layui-btn layui-btn-xs layui-btn-danger">删除</a>
<!--{/if}-->
</script>
<!-- 状态模板 -->
<script type="text/html" id="statusTpl">
{{# if(d.status == 1){ }}
<span class="layui-badge layui-bg-green">正常</span>
{{# } else { }}
<span class="layui-badge">禁用</span>
{{# } }}
</script>
<script>
$(function() {
// 初始化表格
$('#UserData').layTable({
url: '{:url("index")}',
height: 'full',
page: true,
limit: 20,
even: true,
sort: {field: 'id', type: 'desc'},
cols: [[
{checkbox: true},
{field: 'id', title: 'ID', width: 80, sort: true, align: 'center'},
{field: 'username', title: '登录账号', minWidth: 120, sort: true},
{field: 'nickname', title: '用户昵称', minWidth: 120},
{field: 'phone', title: '手机号', minWidth: 120},
{field: 'email', title: '邮箱', minWidth: 150},
{field: 'status', title: '状态', width: 100, align: 'center', templet: '#statusTpl'},
{field: 'create_at', title: '创建时间', minWidth: 170, align: 'center', sort: true},
{toolbar: '#toolbar', title: '操作', align: 'center', fixed: 'right', width: 150}
]],
done: function(res, curr, count) {
console.log('表格渲染完成', res);
}
});
});
</script>
{/block}用户表单页面
{extend name="public/container" /}
{block name="content"}
<form class="layui-form layui-card" data-auto="true" method="post" action="{:url('save')}" data-table-id="UserData" autocomplete="off">
<input type="hidden" name="id" value="{$vo.id|default=''}">
<div class="layui-card-body">
<div class="layui-form-item">
<label class="layui-form-label">登录账号</label>
<div class="layui-input-block">
<input type="text" name="username" value="{$vo.username|default=''}" required
placeholder="请输入登录账号" class="layui-input">
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">用户昵称</label>
<div class="layui-input-block">
<input type="text" name="nickname" value="{$vo.nickname|default=''}" required
placeholder="请输入用户昵称" class="layui-input">
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">头像</label>
<div class="layui-input-block">
<input type="text" name="headimg" value="{$vo.headimg|default=''}"
data-path="upload/headimg"
data-type="jpg,png,gif"
placeholder="请上传头像" class="layui-input">
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">状态</label>
<div class="layui-input-block">
<input type="radio" name="status" value="1" title="正常" checked>
<input type="radio" name="status" value="0" title="禁用">
</div>
</div>
<div class="layui-form-item">
<div class="layui-input-block">
<button type="submit" class="layui-btn">保存</button>
<button type="reset" class="layui-btn layui-btn-primary">重置</button>
<button data-target-backup class="layui-btn layui-btn-primary">返回</button>
</div>
</div>
</div>
</form>
<script>
$(function() {
// 初始化单图上传
$('input[name="headimg"]').uploadOneImage();
});
</script>
{/block}📋 注意事项
单页应用注意事项
- 事件绑定: 由于后台是单页应用,绑定事件需要先
off再on,避免重复绑定 - 对象销毁: 页面切换时及时销毁插件对象,避免内存泄漏
- 表格 ID: 确保表格 ID 唯一,避免冲突
- HASH 路由: 使用
data-open打开页面时,URL 会自动添加spm参数用于菜单定位
最佳实践
- 使用 data 属性: 优先使用
data-action、data-load等属性,简化代码 - 表单验证: 使用
data-auto="true"自动验证表单 - 表格操作: 使用
data-table-id关联表格,自动刷新数据 - 错误处理: 使用
$.msg.auto()自动处理服务器响应 - 加载提示: 合理使用加载提示,提升用户体验
常见问题
Q: data-value 和 data-rule 的区别? A: data-value 用于固定值,格式:key#value;key2#value2。data-rule 用于动态值,支持 {key} 占位符,从选中项或表单中获取值。
Q: data-table-id 的作用? A: 关联表格ID,操作成功后自动刷新表格。支持多个表格ID,用逗号分隔。
Q: 如何自定义回调函数? A: 在 data-callable 中指定全局函数名,或在 $.form.load() 中传入回调函数。
Q: 如何阻止自动处理响应? A: 在回调函数中返回 false,或在 data-time 中设置 'false'。
提示: 更多详细用法请参考源代码
admin.js或查看实际项目中的使用示例。
