// +---------------------------------------------------------------------- declare(strict_types=1); namespace ywxapp\model; use think\model\concern\SoftDelete; /** * 前台主导航菜单模型(支持两级下拉). */ class CommonNavMenu extends BaseModel { use SoftDelete; protected $deleteTime = 'delete_at'; protected function getOptions(): array { return [ 'strict' => false, 'autoWriteTimestamp' => 'int', 'createTime' => 'create_at', 'updateTime' => 'update_at', 'deleteTime' => 'delete_at', 'defaultSoftDelete' => 0, 'append' => ['target'], 'hidden' => ['create_at', 'update_at', 'delete_at'], 'readonly' => ['id'], ]; } /** * 运行时自愈:确保 common_nav_menu 主表存在(install.sql 为事实源), * 老库补充 app 字段(跨应用链接,见 ensureColumn). */ public static function ensureSchema(): void { $prefix = BaseModel::currentPrefix(); BaseModel::ensureTableFromInstall($prefix, 'common_nav_menu'); BaseModel::ensureColumn( $prefix . 'common_nav_menu', 'app', "varchar(30) NOT NULL DEFAULT '' COMMENT '所属应用(跨应用链接用,空=当前应用)' AFTER `url`" ); } protected function initialize() { parent::initialize(); self::ensureSchema(); } /** * 获取启用的导航树(两级:父 + 子)。 * @return array [{id,title,url,icon,child:[...]}] */ public static function getNavTree(): array { $list = self::where('status', 1) ->where('delete_at', 0) ->order('sort', 'asc') ->order('id', 'asc') ->field('id,parent_id,title,url,app,icon,sort') ->select() ->toArray(); $parents = []; $childrenMap = []; foreach ($list as $item) { $item['ctrl'] = strtolower(strtok($item['url'], '/') ?: ''); if ((int) $item['parent_id'] === 0) { $item['child'] = []; $parents[] = $item; } else { $childrenMap[$item['parent_id']][] = $item; } } foreach ($parents as &$p) { if (isset($childrenMap[$p['id']])) { $p['child'] = $childrenMap[$p['id']]; } } return $parents; } /** * 后台列表:返回两级扁平树(含隐藏项). * * @param string $title 可选:按菜单名称模糊筛选(命中子项时自动带上其父级) */ public static function getAdminTree(string $title = ''): array { $query = self::where('delete_at', 0); if ($title !== '') { $matchIds = self::where('delete_at', 0)->whereLike('title', "%{$title}%")->column('id'); if (empty($matchIds)) { return []; } $parentIds = self::where('delete_at', 0)->whereIn('parent_id', $matchIds)->column('parent_id'); $ids = array_values(array_unique(array_merge($matchIds, $parentIds))); $query->whereIn('id', $ids); } $list = $query->order('sort', 'asc') ->order('id', 'asc') ->field('id,parent_id,title,url,app,icon,sort,status') ->select() ->toArray(); $parents = []; $childrenMap = []; foreach ($list as $item) { $item['ctrl'] = strtolower(strtok($item['url'], '/') ?: ''); if ((int) $item['parent_id'] === 0) { $item['child'] = []; $parents[] = $item; } else { $childrenMap[$item['parent_id']][] = $item; } } foreach ($parents as &$p) { if (isset($childrenMap[$p['id']])) { $p['child'] = $childrenMap[$p['id']]; } } return $parents; } }