feat: 公共表更名 common/member 前缀 + 插件命令自动加载 + 版本 1.1.1

- 18 张公共表更名(addon/attachment/configure/links/spider_log/spider_stat/sms/notice/ad/task/prop/medal/help/card -> common_*,member_wallets->member_wallet,score_rule/score_log -> member_*,addon_config->common_addonconf),模型全部对齐新表名,Db 直引用清零
- Attachment 模型补  表名绑定,修复富文本上传查 wxapp_attachment 1146 隐患
- install.sql + 迁移 SQL:backend_admin/backend_role delete_at 默认 0,修复软删除(NULL != 0)误过滤导致后台菜单为空
- AppService::boot() 支持插件 info.php 声明 commands 自动注册插件命令(psr-4 自动加载,坏类名自动跳过)
- 各插件(haonav/mqttbroker/wxchat/articles/blog/forum 等)字段与配置同步调整
- 框架版本 1.1.0 -> 1.1.1
This commit is contained in:
ywxapp
2026-08-20 20:19:15 +08:00
parent 303f548664
commit 1d49e6f5ee
395 changed files with 13342 additions and 2012 deletions
+133
View File
@@ -0,0 +1,133 @@
<?php
// +----------------------------------------------------------------------
// | YwxApp [ WE CAN DO IT JUST THINK ]
// +----------------------------------------------------------------------
// | Copyright (c) 2026-2036 http://ywxapp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Author: ywxapp<admin@ywxapp.cn>
// +----------------------------------------------------------------------
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;
}
}