ChannelUtil.php 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228
  1. <?php
  2. /**
  3. * 渠道工具类
  4. * 提供渠道树形数据获取等公共方法
  5. */
  6. namespace app\common\library;
  7. use think\Db;
  8. class ChannelUtil
  9. {
  10. /**
  11. * 获取渠道树(一级节点,用于初始化树形选择器)
  12. *
  13. * @return array 渠道树形数据
  14. */
  15. public static function getChannelTree()
  16. {
  17. $channelList = Db::name('nw_channel')
  18. ->where(['parent_id' => 0, 'status' => 1])
  19. ->where('id', '>', 0)
  20. ->field('id as value, name, level')
  21. ->order('id', 'asc')
  22. ->select();
  23. $tree = [];
  24. foreach ($channelList as $v) {
  25. $hasChildren = self::hasChildChannels($v['value']);
  26. $tree[] = [
  27. 'name' => $v['name'],
  28. 'value' => (int)$v['value'],
  29. 'children' => $hasChildren ? [] : null,
  30. ];
  31. }
  32. return $tree;
  33. }
  34. /**
  35. * 获取完整渠道树(包含所有层级,用于搜索功能)
  36. *
  37. * @return array 完整渠道树形数据
  38. */
  39. public static function getFullChannelTree()
  40. {
  41. $channelList = Db::name('nw_channel')
  42. ->where('status', 1)
  43. ->where('id', '>', 0)
  44. ->field('id as value, name, parent_id, level')
  45. ->order('id', 'asc')
  46. ->select();
  47. // 构建树形结构
  48. $tree = [];
  49. $map = [];
  50. foreach ($channelList as $v) {
  51. $item = [
  52. 'name' => $v['name'],
  53. 'value' => (int)$v['value'],
  54. 'children' => [],
  55. ];
  56. $map[$v['value']] = $item;
  57. }
  58. foreach ($channelList as $v) {
  59. if ($v['parent_id'] == 0) {
  60. $tree[] = &$map[$v['value']];
  61. } else if (isset($map[$v['parent_id']])) {
  62. $map[$v['parent_id']]['children'][] = &$map[$v['value']];
  63. }
  64. }
  65. // 清理空的 children 数组(叶子节点设为 null)
  66. array_walk_recursive($tree, function(&$item) {
  67. // 不处理
  68. });
  69. // 递归清理空 children
  70. self::cleanEmptyChildren($tree);
  71. return $tree;
  72. }
  73. /**
  74. * 递归清理空的 children 数组
  75. */
  76. private static function cleanEmptyChildren(&$tree)
  77. {
  78. foreach ($tree as &$item) {
  79. if (isset($item['children'])) {
  80. if (empty($item['children'])) {
  81. $item['children'] = null;
  82. } else {
  83. self::cleanEmptyChildren($item['children']);
  84. }
  85. }
  86. }
  87. }
  88. /**
  89. * 获取下级渠道(用于懒加载)
  90. *
  91. * @param int $parentId 父级渠道ID
  92. * @return array 下级渠道数据
  93. */
  94. public static function getChildChannels($parentId)
  95. {
  96. $parentId = intval($parentId);
  97. $channelList = Db::name('nw_channel')
  98. ->where(['parent_id' => $parentId, 'status' => 1])
  99. ->where('id', '>', 0)
  100. ->field('id as value, name, level')
  101. ->order('id', 'asc')
  102. ->select();
  103. $data = [];
  104. foreach ($channelList as $v) {
  105. $hasChildren = self::hasChildChannels($v['value']);
  106. $data[] = [
  107. 'name' => $v['name'],
  108. 'value' => (int)$v['value'],
  109. 'children' => $hasChildren ? [] : null,
  110. ];
  111. }
  112. return $data;
  113. }
  114. /**
  115. * 检查是否有下级渠道
  116. *
  117. * @param int $channelId 渠道ID
  118. * @return bool
  119. */
  120. public static function hasChildChannels($channelId)
  121. {
  122. return Db::name('nw_channel')
  123. ->where(['parent_id' => $channelId, 'status' => 1])
  124. ->count() > 0;
  125. }
  126. /**
  127. * 获取已选中渠道的详细信息(用于前端渲染 initValue)
  128. *
  129. * @param string $channelIds 渠道ID字符串(逗号分隔或'all')
  130. * @return array 已选中渠道信息
  131. */
  132. public static function getSelectedChannels($channelIds)
  133. {
  134. if (empty($channelIds) || $channelIds === 'NULL') {
  135. return [];
  136. }
  137. // 全选模式
  138. if ($channelIds === 'all') {
  139. $level1List = Db::name('nw_channel')
  140. ->where(['parent_id' => 0, 'status' => 1])
  141. ->field('id as value, name')
  142. ->order('id', 'asc')
  143. ->select();
  144. $result = [];
  145. foreach ($level1List as $v) {
  146. $result[] = [
  147. 'name' => $v['name'],
  148. 'value' => (int)$v['value'],
  149. 'selected' => true
  150. ];
  151. }
  152. return $result;
  153. }
  154. $ids = explode(',', $channelIds);
  155. $ids = array_filter(array_map('intval', $ids), function($v) { return $v > 0; });
  156. if (empty($ids)) {
  157. return [];
  158. }
  159. // 获取一级渠道ID列表
  160. $level1Ids = Db::name('nw_channel')
  161. ->where(['parent_id' => 0, 'status' => 1])
  162. ->column('id');
  163. // 判断是否是一级全选模式(所有一级渠道ID都在选中列表中)
  164. $isLevel1All = empty(array_diff($level1Ids, $ids));
  165. if ($isLevel1All) {
  166. // 一级全选模式,只返回一级渠道信息
  167. $level1List = Db::name('nw_channel')
  168. ->where(['parent_id' => 0, 'status' => 1])
  169. ->field('id as value, name')
  170. ->order('id', 'asc')
  171. ->select();
  172. $result = [];
  173. foreach ($level1List as $v) {
  174. $result[] = [
  175. 'name' => $v['name'],
  176. 'value' => (int)$v['value'],
  177. 'selected' => true
  178. ];
  179. }
  180. return $result;
  181. }
  182. // 部分选中模式,返回具体选中的渠道信息
  183. $selectedChannelList = Db::name('nw_channel')
  184. ->where(['id' => ['in', $ids]])
  185. ->field('id as value, name, parent_id')
  186. ->select();
  187. $result = [];
  188. foreach ($selectedChannelList as $sc) {
  189. $item = [
  190. 'name' => $sc['name'],
  191. 'value' => (int)$sc['value'],
  192. 'selected' => true
  193. ];
  194. // 检查是否有子节点,如果有则添加 children 属性(用于树形组件识别父节点)
  195. if (self::hasChildChannels($sc['value'])) {
  196. $item['children'] = [];
  197. }
  198. $result[] = $item;
  199. }
  200. return $result;
  201. }
  202. }