fastadmin 分类可以叠加展开

define(['jquery', 'bootstrap', 'backend', 'table', 'form'], function ($, undefined, Backend, Table, Form) {

var Controller = {

index: function () {

// 初始化表格参数配置

Table.api.init({

extend: {

index_url: 'category/index',

add_url: 'category/add',

edit_url: 'category/edit',

del_url: 'category/del',

multi_url: 'category/multi',

dragsort_url: 'ajax/weigh',

table: 'category',

}

});

var table = $("#table");

var tableOptions = {

url: $.fn.bootstrapTable.defaults.extend.index_url,

pk: 'id',

pagination: false,//隐藏分页

search: true,//隐藏搜索框

commonSearch: false,//隐藏搜索按钮

showToggle: false,//表格视图两种模式

showColumns: false,//隐藏列

showExport: false,//隐藏导出

dbClickToEdit:false,

clickToSelect:false,

/*columns: [

{ checkbox: true }, { field: 'id', title: __('Id') }, { field: 'type', title: __('Type'), operate: false, searchList: Config.searchList, formatter: Table.api.formatter.label }, { field: 'name', title: __('Name'), align: 'left', formatter: function (value, row, index) { return value.toString().replace(/(\&\|\&)nbsp;/g, '\ '); } }, { field: 'nickname', title: __('Nickname') }, { field: 'flag', title: __('Flag'), formatter: Table.api.formatter.flag }, { field: 'image', title: __('Image'), operate: false, events: Table.api.events.image, formatter: Table.api.formatter.image }, { field: 'weigh', title: __('Weigh') }, { field: 'is_gyqg', title:'供应求购',formatter:function(value,row,index){ return value==1?'\是 \':' '; }}, { field: 'status', title: __('Status'), operate: false, formatter: Table.api.formatter.status }, { field: 'operate', title: __('Operate'), table: table, events: Table.api.events.operate, formatter: Table.api.formatter.operate }

] */

columns: [

{checkbox: true}, {field: 'id', title: __('Id')}, { field: 'type', title: __('Type'), operate: false, searchList: Config.searchList, formatter: Table.api.formatter.label }, {field: 'name', title: __('Name'), align: 'left', formatter:function (value, row, index) {return value.toString().replace(/(\&\|\&)nbsp;/g, '\ ');}}, {field: 'image', title: __('Image'), events: Table.api.events.image, formatter: Table.api.formatter.image}, {field: 'pid', title: __('Pid')}, { field: 'weigh', title: __('Weigh'), editable: { type: 'number', // 数字输入类型 title: '请输入权重值', validate: function (value) { if (value === '') { return '权重值不能为空'; } if (!/\^\\d+$/.test(value)) { return '权重值必须为数字'; } if (parseInt(value) \< 0) { return '权重值不能小于0'; } return ''; } } }, { field: 'flag', title: __('Flag'), formatter: Table.api.formatter.flag }, {field: 'id', title: '展开', operate: false, formatter: Controller.api.formatter.subnode}, { field: 'is_gyqg', title:'供应求购',formatter:function(value,row,index){ return value==1?'\是 \':' '; }}, { field: 'status', title: __('Status'), operate: false, formatter: Table.api.formatter.status }, {field: 'operate', title: __('Operate'), table: table, events: Table.api.events.operate, formatter: Table.api.formatter.operate}

],

};

// 初始化表格

table.bootstrapTable(tableOptions);

//绑定TAB事件

$('a[data-toggle="tab"]').on('shown.bs.tab', function (e) {

// var options = table.bootstrapTable(tableOptions);

var typeStr = $(this).attr("href").replace('#', '');

var options = table.bootstrapTable('getOptions');

options.pageNumber = 1;

options.queryParams = function (params) {

// params.filter = JSON.stringify({type: typeStr});

params.type = typeStr;

return params;

};

table.bootstrapTable('refresh', {});

return false;

});

// 为表格绑定事件

Table.api.bindevent(table);

table.off('dbl-click-row.bs.table');

//当内容渲染完成后

table.on('post-body.bs.table', function (e, settings, json, xhr) {

//默认隐藏所有子节点

$("a.btn[data-id][data-pid][data-pid!=0]").closest("tr").hide();

// $(".btn-node-sub.disabled").closest("tr").hide();

//显示隐藏子节点

$(".btn-node-sub").off("click").on("click", function (e) {

var status = $(this).data("shown") ? true : false;

("a.btn\[data-pid='" + (this).data("id") + "']").each(function () {

$(this).closest("tr").toggle(!status);

});

$(this).data("shown", !status);

return false;

});

//点击切换/排序/删除操作后刷新左侧菜单

$(".btn-change[data-id],.btn-delone,.btn-dragsort").data("success", function (data, ret) {

Fast.api.refreshmenu();

return false;

});

});

//批量删除后的回调

$(".toolbar > .btn-del,.toolbar .btn-more~ul>li>a").data("success", function (e) {

Fast.api.refreshmenu();

});

//展开隐藏一级

$(document.body).on("click", ".btn-toggle", function (e) {

$("a.btn[data-id][data-pid][data-pid!=0].disabled").closest("tr").hide();

var that = this;

var show = $("i", that).hasClass("fa-chevron-down");

$("i", that).toggleClass("fa-chevron-down", !show);

$("i", that).toggleClass("fa-chevron-up", show);

$("a.btn[data-id][data-pid][data-pid!=0]").not('.disabled').closest("tr").toggle(show);

$(".btn-node-sub[data-pid=0]").data("shown", show);

});

//展开隐藏全部

$(document.body).on("click", ".btn-toggle-all", function (e) {

var that = this;

var show = $("i", that).hasClass("fa-plus");

$("i", that).toggleClass("fa-plus", !show);

$("i", that).toggleClass("fa-minus", show);

$(".btn-node-sub.disabled").closest("tr").toggle(show);

$(".btn-node-sub").data("shown", show);

});

},

add: function () {

Controller.api.bindevent();

setTimeout(function () {

$("#c-type").trigger("change");

}, 100);

},

edit: function () {

Controller.api.bindevent();

},

api: {

formatter: {

subnode: function (value, row, index) {

return '<a href="javascript:;" data-toggle="tooltip" title="' + __('Toggle sub menu') + '" data-id="' + row.id + '" data-pid="' + row.pid + '" class="btn btn-xs '

  • (row.haschild == 1 || row.ismenu == 1 ? 'btn-success' : 'btn-default disabled') + ' btn-node-sub"><i class="fa fa-sitemap"></i></a>';

}

},

bindevent: function () {

Form.api.bindevent($("form[role=form]"));

}

}

};

return Controller;

});

修改后台分类方法

public function _initialize()

{

parent::_initialize();

$this->model = model('app\common\model\Category');

// 必须将结果集转换为数组

ruleList = collection(this->model->field('*')->order('id ASC')->select())->toArray();

foreach (ruleList as k => &$v) {

v\['name'\] = __(v['name']);

unset(ruleList\[k]['classify_id']);

}

Tree::instance()->init($ruleList);

$this->categorylist = Tree::instance()->getTreeList(Tree::instance()->getTreeArray(0), 'name');

$ruledata = [0 => __('None')];

foreach (this-\>categorylist as k => &$v) {

ruledata\[v['id']] = $v['name'];

}

// $tree = Tree::instance();

// tree-\>init(collection(this->model->order('weigh desc,id desc')->select())->toArray(), 'pid');

// this-\>categorylist = tree->getTreeList($tree->getTreeArray(0), 'name');

// $categorydata = [0 => ['type' => 'all', 'name' => __('None')]];

foreach (this-\>categorylist as k => $v) {

if (isset(v\['level'\]) \&\& v['level'] <= 2) { // level从0开始,0=一级,1=二级,2=三级

categorydata\[v['id']] = $v;

} else if (!isset($v['level'])) {

// 如果没有level字段,可能是根节点,也加入

categorydata\[v['id']] = $v;

}

}

$typeList = CategoryModel::getTypeList();

this-\>view-\>assign("flagList", this->model->getFlagList());

this-\>view-\>assign("typeList", typeList);

this-\>view-\>assign("parentList", categorydata);

this-\>assignconfig('typeList', typeList);

}

public function index()

{

//设置过滤方法

$this->request->filter(['strip_tags']);

if ($this->request->isAjax()) {

// 获取搜索和筛选参数

search = this->request->request("search");

type = this->request->request("type");

// 构建查询条件

$where = [];

if (type \&\& type !== 'all') {

where\['type'\] = type;

}

// 执行查询获取所有数据

query = this->model->where($where);

// 获取所有符合条件的数据

allData = query->order('weigh desc,id desc')->select();

allDataArray = collection(allData)->toArray();

// 添加 haschild 字段,标识每个分类是否有子分类

foreach (allDataArray as \&item) {

hasChild = this->model->where('pid', $item['id'])->count() > 0;

item\['haschild'\] = hasChild ? 1 : 0;

}

// 如果有搜索关键词,则找出所有匹配的节点及其父节点

if ($search) {

$matchedNodes = [];

allNodes = allDataArray;

// 首先找出直接匹配的节点

foreach (allNodes as node) {

if (

strpos(node\['name'\], search) !== false ||

strpos(node\['nickname'\], search) !== false

) {

matchedNodes\[\] = node['id'];

// 同时收集其所有父节点ID

parentId = node['pid'];

while ($parentId != 0) {

$parentNode = null;

foreach (allNodes as n) {

if (n\['id'\] == parentId) {

parentNode = n;

break;

}

}

if ($parentNode) {

matchedNodes\[\] = parentNode['id'];

parentId = parentNode['pid'];

} else {

break;

}

}

}

}

// 过滤出匹配的节点数据

$filteredData = [];

foreach (allDataArray as item) {

if (in_array(item\['id'\], matchedNodes)) {

filteredData\[\] = item;

}

}

// 重新构建树形结构

$tree = Tree::instance();

tree-\>init(filteredData, 'pid');

list = tree->getTreeList($tree->getTreeArray(0), 'name');

} else {

// 没有搜索时,正常构建树形结构

$tree = Tree::instance();

tree-\>init(allDataArray, 'pid');

list = tree->getTreeList($tree->getTreeArray(0), 'name');

}

// 对结果进行处理,确保每个节点都有 haschild 字段

list = this->processTreeData($list);

total = count(list);

result = array("total" =\> total, "rows" => $list);

return json($result);

}

return $this->view->fetch();

}

相关推荐
Tony Bai14 小时前
告别 Flaky Tests:Go 官方拟引入 testing/nettest,重塑内存网络测试标准
开发语言·网络·后端·golang·php
GIS追梦人18 小时前
笔记-Laravel12 开发API前置准备
php·laravel
程序猿_极客19 小时前
【2026】分享一套优质的 Php+MySQL的 校园二手交易平台的设计与实现(万字文档+源码+视频讲解)
vue.js·毕业设计·php·mysql数据库·二手交易系统
ZHOUPUYU20 小时前
PHP 8.0+ 千万级订单系统的分布式事务实战:TCC模式破解高并发难题
php
VXbishe1 天前
基于Spring Boot的老年社区资源分享平台设计与实现-计算机毕设 附源码 25337
javascript·vue.js·spring boot·python·node.js·php·html5
样子20181 天前
PHP 之分片上传
开发语言·php
爱敲代码的小冰1 天前
php dockerfile安装依赖详解
android·开发语言·php
hartyu1 天前
纯PHP + Selenium + ChromeDriver方案实现原理,半自动化内容抓取
开发语言·selenium·php
FJW0208141 天前
Nginx + Redis + srcache + PHP-FPM架构部署
redis·nginx·php
不是二师兄的八戒1 天前
PHP字符串模糊匹配技术深度解析:从Levenshtein到中文优化
开发语言·php