Menu.php 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187
  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. $config = get_addon_config('shop');
  35. $type = empty($params['type']) ? '' : $params['type'];
  36. $typeid = !isset($params['typeid']) ? '' : $params['typeid'];
  37. $condition = empty($params['condition']) ? '' : $params['condition'];
  38. $field = empty($params['field']) ? '*' : $params['field'];
  39. $row = empty($params['row']) ? 10 : (int)$params['row'];
  40. $flag = empty($params['flag']) ? '' : $params['flag'];
  41. $orderby = empty($params['orderby']) ? 'weigh' : $params['orderby'];
  42. $orderway = empty($params['orderway']) ? 'desc' : strtolower($params['orderway']);
  43. $limit = empty($params['limit']) ? $row : $params['limit'];
  44. $orderway = in_array($orderway, ['asc', 'desc']) ? $orderway : 'desc';
  45. $paginate = !isset($params['paginate']) ? false : $params['paginate'];
  46. list($cacheKey, $cacheExpire) = Service::getCacheKeyExpire('menulist', $params);
  47. $where = ['status' => 'normal'];
  48. self::$tagCount++;
  49. if ($type === 'top') {
  50. //顶级分类
  51. $where['pid'] = 0;
  52. } elseif ($type === 'brother') {
  53. $subQuery = self::where('id', 'in', $typeid)->field('pid')->buildSql();
  54. //同级
  55. $where['pid'] = ['exp', Db::raw(' IN ' . '(' . $subQuery . ')')];
  56. } elseif ($type === 'son') {
  57. $subQuery = self::where('pid', 'in', $typeid)->field('id')->buildSql();
  58. //子级
  59. $where['id'] = ['exp', Db::raw(' IN ' . '(' . $subQuery . ')')];
  60. } elseif ($type === 'sons') {
  61. //所有子级
  62. $where['id'] = ['in', self::getMenuChildrenIds($typeid)];
  63. } else {
  64. if ($typeid !== '') {
  65. $where['id'] = ['in', $typeid];
  66. }
  67. }
  68. //如果有设置标志,则拆分标志信息并构造condition条件
  69. if ($flag !== '') {
  70. if (stripos($flag, '&') !== false) {
  71. $arr = [];
  72. foreach (explode('&', $flag) as $k => $v) {
  73. $arr[] = "FIND_IN_SET('{$v}', flag)";
  74. }
  75. if ($arr) {
  76. $condition .= "(" . implode(' AND ', $arr) . ")";
  77. }
  78. } else {
  79. $condition .= ($condition ? ' AND ' : '');
  80. $arr = [];
  81. foreach (explode(',', str_replace('|', ',', $flag)) as $k => $v) {
  82. $arr[] = "FIND_IN_SET('{$v}', flag)";
  83. }
  84. if ($arr) {
  85. $condition .= "(" . implode(' OR ', $arr) . ")";
  86. }
  87. }
  88. }
  89. $order = $orderby == 'rand' ? Db::raw('rand()') : (preg_match("/\,|\s/", $orderby) ? $orderby : "{$orderby} {$orderway}");
  90. $order = $orderby == 'weigh' ? $order . ',id DESC' : $order;
  91. $MenuModel = self::where($where)
  92. ->where($condition)
  93. ->field($field)
  94. ->orderRaw($order);
  95. if ($paginate) {
  96. $paginateArr = explode(',', $paginate);
  97. $listRows = is_numeric($paginate) ? $paginate : (is_numeric($paginateArr[0]) ? $paginateArr[0] : $row);
  98. $config = [];
  99. $config['var_page'] = $paginateArr[2] ?? 'mpage' . self::$tagCount;
  100. $config['path'] = $paginateArr[3] ?? '';
  101. $config['fragment'] = $paginateArr[4] ?? '';
  102. $config['query'] = request()->get();
  103. $list = $MenuModel->paginate($listRows, ($paginateArr[1] ?? false), $config);
  104. } else {
  105. $list = $MenuModel->limit($limit)->cache($cacheKey, $cacheExpire, 'shop')->select();
  106. }
  107. return $list;
  108. }
  109. /**
  110. * 获取菜单列表HTML
  111. * @param array $params
  112. * @return mixed|string
  113. */
  114. public static function getMenu($params = [])
  115. {
  116. $config = get_addon_config('shop');
  117. $condition = empty($params['condition']) ? '' : $params['condition'];
  118. $maxLevel = !isset($params['maxlevel']) ? 0 : $params['maxlevel'];
  119. list($cacheKey, $cacheExpire) = Service::getCacheKeyExpire('menu', $params);
  120. $menuList = Menu::where($condition)
  121. ->where('status', 'normal')
  122. ->field('id,pid,name,url')
  123. ->order('weigh desc,id desc')
  124. ->cache($cacheKey, $cacheExpire, 'shop')
  125. ->select();
  126. $tree = \fast\Tree::instance();
  127. $tree->init(collection($menuList)->toArray(), 'pid');
  128. $result = self::getTreeUl($tree, 0, '', '', 1, $maxLevel);
  129. return $result;
  130. }
  131. public static function getTreeUl($tree, $myid, $selectedids = '', $disabledids = '', $level = 1, $maxlevel = 0)
  132. {
  133. $str = '';
  134. $childs = $tree->getChild($myid);
  135. if ($childs) {
  136. foreach ($childs as $value) {
  137. $id = $value['id'];
  138. unset($value['child']);
  139. $selected = $selectedids && in_array($id, (is_array($selectedids) ? $selectedids : explode(',', $selectedids))) ? 'active' : '';
  140. $disabled = $disabledids && in_array($id, (is_array($disabledids) ? $disabledids : explode(',', $disabledids))) ? 'disabled' : '';
  141. if (!$selected && request()->url(substr($value['url'], 0, 1) !== '/' ? true : null) == $value['url']) {
  142. $selected = 'active';
  143. }
  144. $value = array_merge($value, array('selected' => $selected, 'disabled' => $disabled));
  145. $value = array_combine(array_map(function ($k) {
  146. return '@' . $k;
  147. }, array_keys($value)), $value);
  148. $itemtpl = '<li class="@dropdown @selected" value=@id @disabled><a data-toggle="@toggle" data-target="#" href="@url">@name@caret</a> @childlist</li>';
  149. $nstr = strtr($itemtpl, $value);
  150. $childlist = '';
  151. if (!$maxlevel || $level < $maxlevel) {
  152. $childdata = self::getTreeUl($tree, $id, $selectedids, $disabledids, $level + 1, $maxlevel);
  153. $childlist = $childdata ? '<ul class="dropdown-menu" role="menu">' . $childdata . '</ul>' : "";
  154. }
  155. $str .= strtr($nstr, [
  156. '@childlist' => $childlist,
  157. '@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>') : '',
  158. '@dropdown' => $childlist ? ($level == 1 ? 'dropdown' : 'dropdown-submenu') : '',
  159. '@toggle' => $childlist ? 'dropdown' : ''
  160. ]);
  161. }
  162. }
  163. return $str;
  164. }
  165. }