MenuService.php 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663
  1. <?php
  2. // +----------------------------------------------------------------------
  3. // | Niucloud-admin 企业快速开发的saas管理平台
  4. // +----------------------------------------------------------------------
  5. // | 官方网址:https://www.niucloud.com
  6. // +----------------------------------------------------------------------
  7. // | niucloud团队 版权所有 开源版本可自由商用
  8. // +----------------------------------------------------------------------
  9. // | Author: Niucloud Team
  10. // +----------------------------------------------------------------------
  11. namespace app\service\admin\sys;
  12. use app\dict\sys\MenuDict;
  13. use app\dict\sys\MenuTypeDict;
  14. use app\model\sys\SysMenu;
  15. use app\service\admin\addon\AddonService;
  16. use core\base\BaseAdminService;
  17. use core\dict\DictLoader;
  18. use core\exception\AdminException;
  19. use think\db\exception\DataNotFoundException;
  20. use think\db\exception\DbException;
  21. use think\db\exception\ModelNotFoundException;
  22. use think\facade\Cache;
  23. use think\Model;
  24. /**
  25. * 用户服务层
  26. * Class BaseService
  27. * @package app\service
  28. */
  29. class MenuService extends BaseAdminService
  30. {
  31. public static $cache_tag_name = 'menu_cache';
  32. public function __construct()
  33. {
  34. parent::__construct();
  35. $this->model = new SysMenu();
  36. }
  37. /**
  38. * 新增菜单接口
  39. * @param array $data
  40. * @return SysMenu|Model
  41. */
  42. public function add(array $data)
  43. {
  44. $menu = $this->find($data['menu_key'], $data['app_type']);
  45. if(!$menu->isEmpty()) throw new AdminException('validate_menu.exit_menu_key');//创建失败
  46. $data['source'] = MenuDict::CREATE;
  47. $res = $this->model->create($data);
  48. if(!$res) throw new AdminException('ADD_FAIL');//创建失败
  49. Cache::tag(self::$cache_tag_name)->clear();
  50. return $res;
  51. }
  52. /**
  53. * 更新菜单
  54. * @param string $menu_key
  55. * @param array $data
  56. * @return SysMenu
  57. */
  58. public function edit(string $app_type, string $menu_key, array $data)
  59. {
  60. $where = array(
  61. ['app_type', '=', $app_type],
  62. ['menu_key', '=', $menu_key]
  63. );
  64. $res = $this->model->update($data, $where);
  65. Cache::tag(self::$cache_tag_name)->clear();
  66. return $res;
  67. }
  68. /**
  69. * 获取信息
  70. * @param string $menu_key
  71. * @return array
  72. */
  73. public function get(string $app_type, string $menu_key){
  74. return $this->model->where([['app_type', '=', $app_type],['menu_key', '=', $menu_key]])->findOrEmpty()->toArray();
  75. }
  76. /**
  77. * @param string $menu_key
  78. * @param string $app_type
  79. * @return SysMenu|array|mixed|Model
  80. */
  81. public function find(string $menu_key, string $app_type = ''){
  82. $where = array(
  83. ['menu_key', '=', $menu_key]
  84. );
  85. if(!empty($app_type)){
  86. $where[] = ['app_type', '=', $app_type];
  87. }
  88. $menu = $this->model->where($where)->findOrEmpty();
  89. return $menu;
  90. }
  91. /**
  92. * 菜单删除
  93. * @param string $menu_key
  94. * @return bool
  95. * @throws DbException
  96. */
  97. public function del(string $app_type, string $menu_key){
  98. //查询是否有下级菜单或按钮
  99. $menu = $this->find($menu_key, $app_type);
  100. if($this->model->where([['parent_key', '=', $menu_key], ['app_type', '=', $app_type]])->count() > 0)
  101. throw new AdminException('MENU_NOT_ALLOW_DELETE');
  102. $res = $menu->delete();
  103. Cache::tag(self::$cache_tag_name)->clear();
  104. return $res;
  105. }
  106. /**
  107. * 通过菜单menu_key获取
  108. * @param int $site_id
  109. * @param array $menu_keys
  110. * @param string $app_type
  111. * @param int $is_tree
  112. * @param $addon 用于检测插件筛选
  113. * @return mixed
  114. * @throws DataNotFoundException
  115. * @throws DbException
  116. * @throws ModelNotFoundException
  117. */
  118. public function getMenuListByMenuKeys(int $site_id, array $menu_keys, string $app_type, int $is_tree = 0, $addon = 'all', $is_button = 1)
  119. {
  120. sort($menu_keys);
  121. $cache_name = 'menu' . md5(implode("_", $menu_keys)) . $is_tree.$addon.$site_id;
  122. $menu_list = cache_remember(
  123. $cache_name,
  124. function () use ($site_id, $menu_keys, $app_type, $is_tree, $addon) {
  125. $where = [
  126. ['menu_key', 'in', $menu_keys],
  127. ];
  128. $addons = ( new AddonService() )->getAddonKeysBySiteId($site_id);
  129. $addons[] = '';
  130. $delete_menu_addon = [];
  131. $addon_loader = new DictLoader("Menu");
  132. if($addon != 'all'){
  133. $where[] = ['addon', '=', $addon];
  134. $delete_menu = $addon_loader->load(["addon" => $addon, "app_type" => $app_type])['delete'] ?? [];
  135. if (!empty($delete_menu) && is_array($delete_menu)) $delete_menu_addon[] = $delete_menu;
  136. } else {
  137. $where[] = ['addon', 'in', $addons];
  138. foreach ($addons as $addon) {
  139. $delete_menu = $addon_loader->load(["addon" => $addon, "app_type" => $app_type])['delete'] ?? [];
  140. if (!empty($delete_menu) && is_array($delete_menu)) $delete_menu_addon[] = $delete_menu;
  141. }
  142. }
  143. // 排除插件中delete的菜单
  144. if (!empty($delete_menu_addon)) {
  145. $delete_intersect = array_intersect(...$delete_menu_addon);
  146. if (!empty($delete_intersect)) {
  147. $where[] = ['menu_key', 'not in', $delete_intersect];
  148. }
  149. }
  150. if(!empty($app_type)){
  151. $where[] = ['app_type', '=', $app_type];
  152. }
  153. return $this->model->where($where)->order('sort', 'desc')->select()->toArray();
  154. },
  155. self::$cache_tag_name
  156. );
  157. foreach ($menu_list as &$v)
  158. {
  159. $lang_menu_key = "dict_menu_". $v['app_type']. '.'. $v['menu_key'];
  160. $lang_menu_name = get_lang("dict_menu_". $v['app_type']. '.'. $v['menu_key']);
  161. //语言已定义
  162. if($lang_menu_key != $lang_menu_name)
  163. {
  164. $v['menu_name'] = $lang_menu_name;
  165. }
  166. //首页加载
  167. if($v['menu_key'] == 'overview' && $v['app_type'] == 'site')
  168. {
  169. $view_path = (new ConfigService())->getSiteIndexConfig();
  170. $v['view_path'] = $view_path;
  171. }
  172. if($v['menu_key'] == 'overview' && $v['app_type'] == 'admin')
  173. {
  174. $view_path = (new ConfigService())->getAdminIndexConfig();
  175. $v['view_path'] = $view_path;
  176. }
  177. }
  178. return $is_tree ? $this->menuToTree($menu_list, 'menu_key', 'parent_key', 'children', 'auth', '', $is_button) : $menu_list;
  179. }
  180. /**
  181. * 获取所有接口菜单
  182. */
  183. public function getAllMenuList($app_type = '', $status = 'all', $is_tree = 0, $is_button = 0)
  184. {
  185. $cache_name = 'menu_api_' .$app_type.'_'. $status . '_' . $is_tree . '_' . $is_button;
  186. $menu_list = cache_remember(
  187. $cache_name,
  188. function () use ($status, $is_tree, $is_button, $app_type) {
  189. $where = [
  190. // ['menu_type', 'in', [0,1]]
  191. ['app_type', '=', $app_type],
  192. ];
  193. if ($status != 'all') {
  194. $where[] = ['status', '=', $status];
  195. }
  196. return $this->model->where($where)->order('sort desc')->select()->toArray();
  197. },
  198. self::$cache_tag_name
  199. );
  200. foreach ($menu_list as &$v)
  201. {
  202. $lang_menu_key = "dict_menu_". $v['app_type']. '.'. $v['menu_key'];
  203. $lang_menu_name = get_lang("dict_menu_". $v['app_type']. '.'. $v['menu_key']);
  204. //语言已定义
  205. if($lang_menu_key != $lang_menu_name)
  206. {
  207. $v['menu_name'] = $lang_menu_name;
  208. }
  209. //首页加载
  210. if($v['menu_key'] == 'overview' && $v['app_type'] == 'site')
  211. {
  212. $view_path = (new ConfigService())->getSiteIndexConfig();
  213. $v['view_path'] = $view_path;
  214. }
  215. if($v['menu_key'] == 'overview' && $v['app_type'] == 'admin')
  216. {
  217. $view_path = (new ConfigService())->getAdminIndexConfig();
  218. $v['view_path'] = $view_path;
  219. }
  220. }
  221. return $is_tree ? $this->menuToTree($menu_list, 'menu_key', 'parent_key', 'children', 'auth', '', $is_button) : $menu_list;
  222. }
  223. /**
  224. * 通过菜单menu_key组获取接口数组
  225. * @param array $menu_keys
  226. * @param string $app_type
  227. * @return mixed|string
  228. */
  229. public function getApiListByMenuKeys(array $menu_keys, string $app_type = '')
  230. {
  231. sort($menu_keys);
  232. $cache_name = 'api' . md5(implode("_", $menu_keys));
  233. return cache_remember(
  234. $cache_name,
  235. function () use ($menu_keys, $app_type) {
  236. $where = [
  237. ['menu_key', 'in', $menu_keys]
  238. ];
  239. if(!empty($app_type)){
  240. $where[] = ['app_type', '=', $app_type];
  241. }
  242. $menu_list = (new SysMenu())->where($where)->order('sort', 'desc')->column('api_url,methods');
  243. foreach ($menu_list as $v) {
  244. $auth_menu_list[$v['methods']][] = $v['api_url'];
  245. }
  246. return $auth_menu_list ?? [];
  247. },
  248. self::$cache_tag_name
  249. );
  250. }
  251. /**
  252. * 通过菜单menu_key组获取按钮数组
  253. * @param array $menu_keys
  254. * @param string $app_type
  255. * @return mixed
  256. */
  257. public function getButtonListBuMenuKeys(array $menu_keys, string $app_type = '')
  258. {
  259. sort($menu_keys);
  260. $cache_name = 'button' . md5(implode("_", $menu_keys));
  261. return cache_remember(
  262. $cache_name,
  263. function () use ($menu_keys, $app_type) {
  264. $where = [
  265. ['menu_key', 'in', $menu_keys],
  266. ['menu_type', '=', MenuTypeDict::BUTTON]
  267. ];
  268. if(!empty($app_type)){
  269. $where[] = ['app_type', '=', $app_type];
  270. }
  271. return $this->model->where($where)->order('sort', 'desc')->column('menu_key');
  272. },
  273. self::$cache_tag_name
  274. );
  275. }
  276. /**
  277. * 获取所有接口菜单权限
  278. * @param $app_type
  279. * @param $status
  280. * @return mixed
  281. */
  282. public function getAllApiList($app_type = '', $status = 'all')
  283. {
  284. $cache_name = 'all_api' .$app_type.'_'. $status;
  285. return cache_remember(
  286. $cache_name,
  287. function () use ($status, $app_type) {
  288. $where = [
  289. ['api_url', '<>', ''],
  290. ['app_type', '=', $app_type],
  291. ];
  292. if ($status != 'all') {
  293. $where[] = ['status', '=', $status];
  294. }
  295. $menu_list = $this->model->where($where)->order('sort', 'desc')->column('methods, api_url');
  296. $auth_menu_list = [];
  297. foreach ($menu_list as $v) {
  298. $auth_menu_list[$v['methods']][] = $v['api_url'];
  299. }
  300. return $auth_menu_list;
  301. },
  302. self::$cache_tag_name
  303. );
  304. }
  305. /**
  306. * 通过站点端口获取菜单id
  307. * @param string $app_type
  308. * @param $status
  309. * @return mixed|string
  310. */
  311. public function getAllMenuIdsByAppType(string $app_type, $status = 'all'){
  312. $cache_name = 'menu_id_by_app_type_' .$app_type;
  313. return cache_remember(
  314. $cache_name,
  315. function () use ($app_type, $status) {
  316. $where = [
  317. //
  318. ['app_type', '=', $app_type],
  319. ];
  320. if ($status != 'all') {
  321. $where[] = ['status', '=', $status];
  322. }
  323. return $this->model->where($where)->order('sort desc')->column('menu_key');
  324. },
  325. self::$cache_tag_name
  326. );
  327. }
  328. /**
  329. * 获取所有按钮菜单
  330. */
  331. public function getAllButtonList($app_type = '', $status = 'all', $is_tree = 0)
  332. {
  333. $cache_name = 'menu_api_' .$app_type.'_' . $status . '_' . $is_tree;
  334. return cache_remember(
  335. $cache_name,
  336. function () use ($status, $is_tree, $app_type) {
  337. $where = [
  338. ['menu_type', '=', MenuTypeDict::BUTTON],
  339. ['app_type', '=', $app_type],
  340. ];
  341. if ($status != 'all') {
  342. $where[] = ['status', '=', $status];
  343. }
  344. return $this->model->where($where)->order('sort', 'desc')->column('menu_key');
  345. },
  346. self::$cache_tag_name
  347. );
  348. }
  349. /**
  350. * 把返回的数据集转换成Tree(专属于)
  351. * @param $list 要转换的数据集
  352. * @param string $pk
  353. * @param string $pid
  354. * @param string $child
  355. * @param int $root
  356. * @return array
  357. */
  358. public function menuToTree($list, $pk = 'id', $pid = 'pid', $child = 'child', $button_name = 'auth', $root = '', $is_button = 0)
  359. {
  360. // 创建Tree
  361. $tree = array();
  362. if (is_array($list)) {
  363. // 创建基于主键的数组引用
  364. $refer = array();
  365. foreach ($list as $key => $data) {
  366. $refer[$data[$pk]] =& $list[$key];
  367. }
  368. foreach ($list as $key => $data) {
  369. // 判断是否存在parent
  370. $parent_id = $data[$pid];
  371. if ($root == $parent_id) {
  372. $tree[] =& $list[$key];
  373. } else {
  374. if (isset($refer[$parent_id])) {
  375. $parent =& $refer[$parent_id];
  376. if ($list[$key]['menu_type'] == 2 && $is_button == 1) {
  377. $parent[$button_name][] =& $list[$key]['menu_key'];
  378. } else {
  379. $parent[$child][] =& $list[$key];
  380. }
  381. }
  382. }
  383. }
  384. }
  385. return $tree;
  386. }
  387. /**
  388. * 获取完整的路由地址
  389. * @param $menu_key
  390. * @return string
  391. */
  392. public function getFullRouterPath($menu_key){
  393. $menu = $this->model->where([['menu_key', '=', $menu_key]])->findOrEmpty($menu_key);
  394. if($menu->isEmpty()) return '';
  395. $parents = [];
  396. $this->getParentDirectory($menu, $parents);
  397. $parents = array_reverse($parents);
  398. $router_path = implode('/', $parents);
  399. if(!empty($router_path)){
  400. $router_path .= '/'.$menu['router_path'];
  401. }else{
  402. $router_path = $menu['router_path'];
  403. }
  404. return $router_path;
  405. }
  406. /**
  407. * 递归查询模板集合
  408. * @param SysMenu $menu
  409. * @param $parents
  410. * @return void
  411. */
  412. public function getParentDirectory(SysMenu $menu, &$parents){
  413. if(!$menu->isEmpty() && !empty($menu['parent_key'])){
  414. $parent_menu = $this->model->where([['menu_key', '=', $menu['parent_key']]])->findOrEmpty();
  415. if(!empty($parent_menu)){
  416. if(!empty($parent_menu['router_path'])) $parents[] = $parent_menu['router_path'];
  417. $this->getParentDirectory($parent_menu, $parents);
  418. }
  419. }
  420. }
  421. /**
  422. * 获取系统菜单(站点权限api极限)
  423. * @param string $app_type
  424. * @param array $addons
  425. * @return mixed|string
  426. */
  427. public function getApiListBySystem(string $app_type = '', array $addons = [])
  428. {
  429. sort($addons);
  430. $cache_name = 'system_menu_api_' . $app_type.implode("_", $addons);
  431. return cache_remember(
  432. $cache_name,
  433. function () use ($app_type, $addons) {
  434. $addons[] = '';
  435. $where = [
  436. ['addon', 'in', $addons]
  437. ];
  438. if(!empty($app_type)){
  439. $where[] = ['app_type', '=', $app_type];
  440. }
  441. $menu_list = (new SysMenu())->where($where)->order('sort', 'desc')->column('api_url,methods');
  442. foreach ($menu_list as $v) {
  443. $auth_menu_list[$v['methods']][] = $v['api_url'];
  444. }
  445. return $auth_menu_list ?? [];
  446. },
  447. self::$cache_tag_name
  448. );
  449. }
  450. /**
  451. * 站点所拥有的菜单极限
  452. * @param string $app_type
  453. * @param array $addons
  454. * @param int $is_tree
  455. * @return array|mixed|string
  456. * @throws DataNotFoundException
  457. * @throws DbException
  458. * @throws ModelNotFoundException
  459. */
  460. public function getMenuListBySystem(string $app_type, array $addons, int $is_tree = 0, int $is_button = 1, $status = 'all')
  461. {
  462. sort($addons);
  463. $cache_name = 'menu' . md5(implode("_", $addons)) . $is_tree . $status;
  464. $menu_list = cache_remember(
  465. $cache_name,
  466. function () use ($addons, $app_type, $is_tree, $status) {
  467. $where = [
  468. ['addon', 'in', $addons]
  469. ];
  470. if(!empty($app_type)){
  471. $where[] = ['app_type', '=', $app_type];
  472. }
  473. if ($status != 'all') $where[] = ['status', '=', $status];
  474. // 排除插件中delete的菜单
  475. $delete_menu_addon = [];
  476. $addon_loader = new DictLoader("Menu");
  477. foreach ($addons as $addon) {
  478. $delete_menu = $addon_loader->load(["addon" => $addon, "app_type" => $app_type])['delete'] ?? [];
  479. if (!empty($delete_menu) && is_array($delete_menu)) $delete_menu_addon[] = $delete_menu;
  480. }
  481. if (!empty($delete_menu_addon)) {
  482. $delete_intersect = array_intersect(...$delete_menu_addon);
  483. if (!empty($delete_intersect)) {
  484. $where[] = ['menu_key', 'not in', $delete_intersect];
  485. }
  486. }
  487. return $this->model->where($where)->order('sort', 'desc')->select()->toArray();
  488. },
  489. self::$cache_tag_name
  490. );
  491. foreach ($menu_list as &$v)
  492. {
  493. $lang_menu_key = "dict_menu_". $v['app_type']. '.'. $v['menu_key'];
  494. $lang_menu_name = get_lang("dict_menu_". $v['app_type']. '.'. $v['menu_key']);
  495. //语言已定义
  496. if($lang_menu_key != $lang_menu_name)
  497. {
  498. $v['menu_name'] = $lang_menu_name;
  499. }
  500. //首页加载
  501. if($v['menu_key'] == 'overview' && $v['app_type'] == 'site')
  502. {
  503. $view_path = (new ConfigService())->getSiteIndexConfig();
  504. $v['view_path'] = $view_path;
  505. }
  506. if($v['menu_key'] == 'overview' && $v['app_type'] == 'admin')
  507. {
  508. $view_path = (new ConfigService())->getAdminIndexConfig();
  509. $v['view_path'] = $view_path;
  510. }
  511. }
  512. return $is_tree ? $this->menuToTree($menu_list, 'menu_key', 'parent_key', 'children', 'auth', '', $is_button) : $menu_list;
  513. }
  514. /**
  515. * 通过站点的应用配置获取所有的keys
  516. * @param string $app_type
  517. * @param array $addons
  518. * @return mixed|string
  519. */
  520. public function getMenuKeysBySystem(string $app_type, array $addons){
  521. sort($addons);
  522. $cache_name = 'menu_keys_' . $app_type.implode("_", $addons);
  523. return cache_remember(
  524. $cache_name,
  525. function () use ($app_type, $addons) {
  526. $addons[] = '';
  527. $where = [
  528. ['addon', 'in', $addons]
  529. ];
  530. if(!empty($app_type)){
  531. $where[] = ['app_type', '=', $app_type];
  532. }
  533. return (new SysMenu())->where($where)->order('sort', 'desc')->column('menu_key');
  534. },
  535. self::$cache_tag_name
  536. );
  537. }
  538. public function getSystemMenu($status = 'all', $is_tree = 0, $is_button = 0)
  539. {
  540. if($is_button == 0)
  541. {
  542. $where = [
  543. ['menu_type', 'in', [0,1]]
  544. ];
  545. }
  546. if ($status != 'all') {
  547. $where[] = ['status', '=', $status];
  548. }
  549. $where[] = [ 'addon', '=',''];
  550. $menu_list = (new SysMenu())->where($where)->order('sort desc')->select()->toArray();
  551. foreach ($menu_list as &$v)
  552. {
  553. $lang_menu_key = 'dict_menu_admin' . '.'. $v['menu_key'];
  554. $lang_menu_name = get_lang($lang_menu_key);
  555. //语言已定义
  556. if($lang_menu_key != $lang_menu_name)
  557. {
  558. $v['menu_name'] = $lang_menu_name;
  559. }
  560. }
  561. return $is_tree ? $this->menuToTree($menu_list, 'menu_key', 'parent_key', 'children', 'auth', '', $is_button) : $menu_list;
  562. }
  563. public function getAddonMenu($app_key,$status = 'all', $is_tree = 0, $is_button = 0)
  564. {
  565. if($is_button == 0)
  566. {
  567. $where = [
  568. ['menu_type', 'in', [0,1]]
  569. ];
  570. }
  571. if ($status != 'all') {
  572. $where[] = ['status', '=', $status];
  573. }
  574. $where[] = [ 'addon', '=',$app_key];
  575. $menu_list = (new SysMenu())->where($where)->select()->toArray();
  576. return $is_tree ? $this->menuToTree($menu_list, 'menu_key', 'parent_key', 'children', 'auth', '', $is_button) : $menu_list;
  577. }
  578. /**
  579. * 查询菜单类型为目录的菜单
  580. * @param string $addon
  581. */
  582. public function getMenuByTypeDir(string $addon = 'system') {
  583. $cache_name = 'menu_api_by_type_dir' . $addon;
  584. $menu_list = cache_remember(
  585. $cache_name,
  586. function () use ($addon) {
  587. $where = [
  588. ['menu_type', '=', 0 ],
  589. ['app_type', '=', 'site']
  590. ];
  591. //查询应用
  592. $where[] = ['addon', '=', $addon == 'system' ? '' : $addon ];
  593. return (new SysMenu())->where($where)->order('sort desc')->select()->toArray();
  594. },
  595. self::$cache_tag_name
  596. );
  597. foreach ($menu_list as &$v)
  598. {
  599. $lang_menu_key = 'dict_menu_admin' . '.'. $v['menu_key'];
  600. $lang_menu_name = get_lang($lang_menu_key);
  601. //语言已定义
  602. if($lang_menu_key != $lang_menu_name)
  603. {
  604. $v['menu_name'] = $lang_menu_name;
  605. }
  606. }
  607. return $this->menuToTree($menu_list, 'menu_key', 'parent_key', 'children', 'auth', '', 0);
  608. }
  609. }