Menu.php 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186
  1. <?php
  2. namespace app\common\model;
  3. use app\common\library\Service;
  4. use fast\Tree;
  5. use think\Cache;
  6. use think\Db;
  7. use think\Model;
  8. /**
  9. * 模型
  10. */
  11. class Menu extends Model
  12. {
  13. // 表名
  14. protected $name = 'shop_menu';
  15. // 开启自动写入时间戳字段
  16. protected $autoWriteTimestamp = 'int';
  17. // 定义时间戳字段名
  18. protected $createTime = 'createtime';
  19. protected $updateTime = '';
  20. // 追加属性
  21. protected $append = [
  22. ];
  23. protected static $tagCount = 0;
  24. protected static $parentIds = null;
  25. protected static $outlinkParentIds = null;
  26. protected static $navParentIds = null;
  27. /**
  28. * 获取分类列表
  29. * @param $params
  30. * @return false|\PDOStatement|string|\think\Collection
  31. */
  32. public static function getMenuList($params)
  33. {
  34. $type = empty($params['type']) ? '' : $params['type'];
  35. $typeid = !isset($params['typeid']) ? '' : $params['typeid'];
  36. $condition = empty($params['condition']) ? '' : $params['condition'];
  37. $field = empty($params['field']) ? '*' : $params['field'];
  38. $row = empty($params['row']) ? 10 : (int)$params['row'];
  39. $flag = empty($params['flag']) ? '' : $params['flag'];
  40. $orderby = empty($params['orderby']) ? 'weigh' : $params['orderby'];
  41. $orderway = empty($params['orderway']) ? 'desc' : strtolower($params['orderway']);
  42. $limit = empty($params['limit']) ? $row : $params['limit'];
  43. $orderway = in_array($orderway, ['asc', 'desc']) ? $orderway : 'desc';
  44. $paginate = !isset($params['paginate']) ? false : $params['paginate'];
  45. list($cacheKey, $cacheExpire) = Service::getCacheKeyExpire('menulist', $params);
  46. $where = ['status' => 'normal'];
  47. self::$tagCount++;
  48. if ($type === 'top') {
  49. //顶级分类
  50. $where['pid'] = 0;
  51. } elseif ($type === 'brother') {
  52. $subQuery = self::where('id', 'in', $typeid)->field('pid')->buildSql();
  53. //同级
  54. $where['pid'] = ['exp', Db::raw(' IN ' . '(' . $subQuery . ')')];
  55. } elseif ($type === 'son') {
  56. $subQuery = self::where('pid', 'in', $typeid)->field('id')->buildSql();
  57. //子级
  58. $where['id'] = ['exp', Db::raw(' IN ' . '(' . $subQuery . ')')];
  59. } elseif ($type === 'sons') {
  60. //所有子级
  61. $where['id'] = ['in', self::getMenuChildrenIds($typeid)];
  62. } else {
  63. if ($typeid !== '') {
  64. $where['id'] = ['in', $typeid];
  65. }
  66. }
  67. //如果有设置标志,则拆分标志信息并构造condition条件
  68. if ($flag !== '') {
  69. if (stripos($flag, '&') !== false) {
  70. $arr = [];
  71. foreach (explode('&', $flag) as $k => $v) {
  72. $arr[] = "FIND_IN_SET('{$v}', flag)";
  73. }
  74. if ($arr) {
  75. $condition .= "(" . implode(' AND ', $arr) . ")";
  76. }
  77. } else {
  78. $condition .= ($condition ? ' AND ' : '');
  79. $arr = [];
  80. foreach (explode(',', str_replace('|', ',', $flag)) as $k => $v) {
  81. $arr[] = "FIND_IN_SET('{$v}', flag)";
  82. }
  83. if ($arr) {
  84. $condition .= "(" . implode(' OR ', $arr) . ")";
  85. }
  86. }
  87. }
  88. $order = $orderby == 'rand' ? Db::raw('rand()') : (preg_match("/\,|\s/", $orderby) ? $orderby : "{$orderby} {$orderway}");
  89. $order = $orderby == 'weigh' ? $order . ',id DESC' : $order;
  90. $MenuModel = self::where($where)
  91. ->where($condition)
  92. ->field($field)
  93. ->orderRaw($order);
  94. if ($paginate) {
  95. $paginateArr = explode(',', $paginate);
  96. $listRows = is_numeric($paginate) ? $paginate : (is_numeric($paginateArr[0]) ? $paginateArr[0] : $row);
  97. $config = [];
  98. $config['var_page'] = $paginateArr[2] ?? 'mpage' . self::$tagCount;
  99. $config['path'] = $paginateArr[3] ?? '';
  100. $config['fragment'] = $paginateArr[4] ?? '';
  101. $config['query'] = request()->get();
  102. $list = $MenuModel->paginate($listRows, ($paginateArr[1] ?? false), $config);
  103. } else {
  104. $list = $MenuModel->limit($limit)->cache($cacheKey, $cacheExpire, 'shop')->select();
  105. }
  106. return $list;
  107. }
  108. /**
  109. * 获取菜单列表HTML
  110. * @param array $params
  111. * @return mixed|string
  112. */
  113. public static function getMenu($params = [])
  114. {
  115. $config = get_addon_config('shop');
  116. $condition = empty($params['condition']) ? '' : $params['condition'];
  117. $maxLevel = !isset($params['maxlevel']) ? 0 : $params['maxlevel'];
  118. list($cacheKey, $cacheExpire) = Service::getCacheKeyExpire('menu', $params);
  119. $menuList = Menu::where($condition)
  120. ->where('status', 'normal')
  121. ->field('id,pid,name,url')
  122. ->order('weigh desc,id desc')
  123. ->cache($cacheKey, $cacheExpire, 'shop')
  124. ->select();
  125. $tree = \fast\Tree::instance();
  126. $tree->init(collection($menuList)->toArray(), 'pid');
  127. $result = self::getTreeUl($tree, 0, '', '', 1, $maxLevel);
  128. return $result;
  129. }
  130. public static function getTreeUl($tree, $myid, $selectedids = '', $disabledids = '', $level = 1, $maxlevel = 0)
  131. {
  132. $str = '';
  133. $childs = $tree->getChild($myid);
  134. if ($childs) {
  135. foreach ($childs as $value) {
  136. $id = $value['id'];
  137. unset($value['child']);
  138. $selected = $selectedids && in_array($id, (is_array($selectedids) ? $selectedids : explode(',', $selectedids))) ? 'active' : '';
  139. $disabled = $disabledids && in_array($id, (is_array($disabledids) ? $disabledids : explode(',', $disabledids))) ? 'disabled' : '';
  140. if (!$selected && request()->url(substr($value['url'], 0, 1) !== '/' ? true : null) == $value['url']) {
  141. $selected = 'active';
  142. }
  143. $value = array_merge($value, array('selected' => $selected, 'disabled' => $disabled));
  144. $value = array_combine(array_map(function ($k) {
  145. return '@' . $k;
  146. }, array_keys($value)), $value);
  147. $itemtpl = '<li class="@dropdown @selected" value=@id @disabled><a data-toggle="@toggle" data-target="#" href="@url">@name@caret</a> @childlist</li>';
  148. $nstr = strtr($itemtpl, $value);
  149. $childlist = '';
  150. if (!$maxlevel || $level < $maxlevel) {
  151. $childdata = self::getTreeUl($tree, $id, $selectedids, $disabledids, $level + 1, $maxlevel);
  152. $childlist = $childdata ? '<ul class="dropdown-menu" role="menu">' . $childdata . '</ul>' : "";
  153. }
  154. $str .= strtr($nstr, [
  155. '@childlist' => $childlist,
  156. '@caret' => $childlist ? ($level == 1 ? '<span class="indicator"><i class="fa fa-angle-down"></i></span>' : '<span class="indicator"><i class="fa fa-angle-right"></i></span>') : '',
  157. '@dropdown' => $childlist ? ($level == 1 ? 'dropdown' : 'dropdown-submenu') : '',
  158. '@toggle' => $childlist ? 'dropdown' : ''
  159. ]);
  160. }
  161. }
  162. return $str;
  163. }
  164. }