📜 Admin.js

ThinkAdminadmin.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, 可选): 自动关闭时间(毫秒),默认 3000
  • option (object, 可选): 配置选项
    • type (string): 通知类型,可选值:alertsuccesserrorwarninginfo
    • position (string): 显示位置,可选值:top-lefttop-rightbottom-leftbottom-righttop-centerbottom-center,默认 top-right
    • width (string): 通知框宽度,默认 400px
    • closeTimeout (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#value2
  • data-rule: 提交规则,格式:key1#{key};key2#value{key} 表示从选中项获取值
  • data-table-id: 关联的表格ID,操作成功后自动刷新
  • data-csrfdata-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: 关闭后刷新的表格ID
  • data-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: 关闭后刷新的表格ID
  • data-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}

📋 注意事项

单页应用注意事项

  1. 事件绑定: 由于后台是单页应用,绑定事件需要先 offon,避免重复绑定
  2. 对象销毁: 页面切换时及时销毁插件对象,避免内存泄漏
  3. 表格 ID: 确保表格 ID 唯一,避免冲突
  4. HASH 路由: 使用 data-open 打开页面时,URL 会自动添加 spm 参数用于菜单定位

最佳实践

  1. 使用 data 属性: 优先使用 data-actiondata-load 等属性,简化代码
  2. 表单验证: 使用 data-auto="true" 自动验证表单
  3. 表格操作: 使用 data-table-id 关联表格,自动刷新数据
  4. 错误处理: 使用 $.msg.auto() 自动处理服务器响应
  5. 加载提示: 合理使用加载提示,提升用户体验

常见问题

Q: data-value 和 data-rule 的区别? A: data-value 用于固定值,格式:key#value;key2#value2data-rule 用于动态值,支持 {key} 占位符,从选中项或表单中获取值。

Q: data-table-id 的作用? A: 关联表格ID,操作成功后自动刷新表格。支持多个表格ID,用逗号分隔。

Q: 如何自定义回调函数? A: 在 data-callable 中指定全局函数名,或在 $.form.load() 中传入回调函数。

Q: 如何阻止自动处理响应? A: 在回调函数中返回 false,或在 data-time 中设置 'false'


提示: 更多详细用法请参考源代码 admin.js 或查看实际项目中的使用示例。

最近更新:
Contributors: Anyon