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
+2 -2
View File
@@ -35,7 +35,7 @@ class Addon
if (!isset($info['name'])) {
continue;
}
$installedInfo = Db::name('addon')->where('name', $name)->find();
$installedInfo = Db::name('common_addon')->where('name', $name)->find();
$list[] = [
'name' => $name,
'title' => $info['title'] ?? $name,
@@ -125,7 +125,7 @@ class Addon
} catch (\Exception $e) {
return json(['code' => 404, 'msg' => '插件不存在']);
}
$installed = Db::name('addon')->where('name', $name)->find();
$installed = Db::name('common_addon')->where('name', $name)->find();
return json([
'code' => 200,
+146
View File
@@ -0,0 +1,146 @@
<?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\controller;
use think\App;
/**
* API 控制器基础类(App / 小程序 / 第三方客户端通用)
*
* 统一提供:JWT 登录态注入、未登录 401 拦截、标准响应封装。
* 业务控制器继承本类即可复用登录态(\ywxapp\model\MemberUser)与响应(\ywxapp\library\Result)。
*
* 鉴权约定:
* - 子类通过 $noNeedLogin 声明“免登录即可访问”的 action,['*'] 表示全部放行。
* - 其余 action 在构造阶段统一校验登录态,未登录直接返回 HTTP 401。
* - 统一响应:成功 $this->result->success($data),失败 $this->result->error($msg, $code)。
*
* @package ywxapp\controller
*/
class ApiBase extends BaseController
{
/**
* 无需登录即可访问的 action 列表,['*'] 表示全部放行。
*
* @var array<int, string>
*/
protected $noNeedLogin = [];
/**
* 无需额外校验的 action 列表(兼容旧写法,语义同 $noNeedLogin)。
*
* @var array<int, string>
*/
protected $noNeedVerify = [];
/**
* 构造方法。
*
* 完成父类初始化后,依次调用 initialize()(子类自定义初始化)与
* checkLogin()(统一登录拦截)。
*
* @param App $app 应用实例
*/
public function __construct(App $app)
{
parent::__construct($app);
$this->initialize();
$this->checkLogin();
}
/**
* 控制器初始化钩子,子类可重写以执行构造后的自定义初始化逻辑。
*
* @return void
*/
protected function initialize() {}
/**
* 统一登录拦截。
*
* 当当前 action 不在 $noNeedLogin / $noNeedVerify 白名单,且会员未登录时,
* 直接返回 HTTP 401,阻止后续业务执行。
*
* @return void
*/
protected function checkLogin(): void
{
$action = $this->request->action();
$white = array_merge($this->noNeedLogin, $this->noNeedVerify);
if (in_array('*', $white, true) || in_array($action, $white, true)) {
return;
}
if (!$this->auth || !$this->auth->isLogin) {
$this->result->apiError('请先登录', 401, null, 401);
}
}
/**
* 获取当前登录会员模型(\ywxapp\model\MemberUser)。
*
* 未登录访问已被 checkLogin() 拦截,此处仅作兜底返回。
*
* @return \ywxapp\model\MemberUser 当前登录会员模型
*/
protected function user()
{
if ($this->auth && $this->auth->isLogin) {
return $this->auth->info;
}
$this->result->apiError('请先登录', 401, null, 401);
}
/**
* 获取当前登录会员的主键 ID(uid)。
*
* @return int 会员 uid,未登录时为 0
*/
protected function uid(): int
{
return (int) ($this->auth->model->uid ?? 0);
}
/**
* API 成功响应(强制 JSON,统一契约).
*
* 透传至 \ywxapp\library\Result::apiSuccess():固定 JSON、字段
* code/msg/data/timestamp,自动携带 token 与分页 count。
*
* @param mixed $data 业务数据
* @param string $message 成功提示语
* @param int $count 分页总数(可选)
*
* @return void
*/
protected function apiSuccess($data = null, string $message = 'success', int $count = 0): void
{
$this->result->apiSuccess($data, $message, $count);
}
/**
* API 失败响应(强制 JSON,业务 code 与 HTTP 状态解耦).
*
* 透传至 \ywxapp\library\Result::apiError():固定 JSON、字段
* code/msg/data/timestamp;业务 code 原样透传,HTTP 状态由 $httpStatus 控制。
*
* @param string $message 失败提示语
* @param int $code 业务状态码(默认 1,鉴权失败建议 401)
* @param mixed $data 附加数据(可选)
* @param int $httpStatus HTTP 状态码(默认 200)
*
* @return void
*/
protected function apiError(string $message = 'Error', int $code = 1, $data = null, int $httpStatus = 200): void
{
$this->result->apiError($message, $code, $data, $httpStatus);
}
}
-47
View File
@@ -1,47 +0,0 @@
<?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\controller;
/**
* 控制器基础类
*/
class ApiController extends BaseController
{
// use \ywxapp\traits\Backend;
/**
* 控制器初始化 _initialize
* @return void
*/
public function _initialize()
{
$this->initialize();
}
/** 控制器初始化 initialize
* @return void
*/
protected function initialize() {}
/**
* 获取当前登录用户信息
* \ywxapp\model\Member
*/
protected function user()
{
if ($this->auth && $this->auth->isLogin) {
return $this->auth->info;
}
$this->result->error('获取用户信息失败!');
}
}
+9 -9
View File
@@ -12,10 +12,10 @@ declare(strict_types=1);
namespace ywxapp\controller;
use think\facade\View;
use ywxapp\model\Configure as ConfModel;
use ywxapp\model\Links;
use ywxapp\model\Notice;
use ywxapp\model\Ad;
use ywxapp\model\CommonConfigure as ConfModel;
use ywxapp\model\CommonLinks;
use ywxapp\model\CommonNotice;
use ywxapp\model\CommonAd;
use ywxapp\library\SkinOverlay;
use ywxapp\library\SkinVariables;
use ywxapp\library\TemplateManager;
@@ -77,21 +77,21 @@ abstract class FrontendBase extends BaseController
}
$siteConf = ConfModel::cache(true)->column('value', 'name');
$this->view->assign('siteConf', $siteConf);
$links = Links::cache(true)->where('status', 1)->order('sort desc')->select();
$links = CommonLinks::cache(true)->where('status', 1)->order('sort desc')->select();
$this->view->assign('links', $links);
// 全站置顶公告条(方案 A):仅取当前生效 + 置顶 + 启用的公告
$typeList = Notice::typeList();
$typeList = CommonNotice::typeList();
$topNotices = array_map(function ($n) use ($typeList) {
$n['type_text'] = $typeList[$n['type']] ?? '公告';
return $n;
}, Notice::getActiveTopNotices());
}, CommonNotice::getActiveTopNotices());
$this->view->assign('topNotices', $topNotices);
// 全站广告位:按 position 分组的启用广告,模板可随时调用 {notempty name="adSlots.home_top"}
$this->view->assign('adSlots', Ad::getSlots());
$this->view->assign('adSlots', CommonAd::getSlots());
// 注入站点信息(route_base / site.module / site.controller 等),供前端 route.js 使用
$this->assignSite();
// 前台主导航菜单(后台可配置,两级下拉),供 header.html 渲染
$this->view->assign('navMenus', \app\backend\model\NavMenu::getNavTree());
$this->view->assign('navMenus', \ywxapp\model\CommonNavMenu::getNavTree());
$this->initialize();
}
+2 -2
View File
@@ -81,9 +81,9 @@ class MemberBase extends BaseController
if ($this->auth && $this->auth->isLogin) {
$this->view->assign('member', $this->auth->info);
}
$siteConf = \ywxapp\model\Configure::cache(true)->column('value', 'name');
$siteConf = \ywxapp\model\CommonConfigure::cache(true)->column('value', 'name');
$this->view->assign('siteConf', $siteConf);
$links = \ywxapp\model\Links::cache(true)->where('status', 1)->order('sort desc')->select();
$links = \ywxapp\model\CommonLinks::cache(true)->where('status', 1)->order('sort desc')->select();
$this->view->assign('links', $links);
// 注入站点信息(route_base / site.module / site.controller 等),供前端 route.js 使用
$this->assignSite();
+3 -3
View File
@@ -8,7 +8,7 @@
// +----------------------------------------------------------------------
namespace ywxapp\controller;
use ywxapp\model\Attachment;
use ywxapp\model\CommonAttachment;
use ywxapp\service\FileStorageService;
/**
@@ -141,7 +141,7 @@ class UeditorPlus
{
try {
$user = app()->auth->info;
$datas = Attachment::where('uid', $user->uid)->where('mime', 'like', 'image%')->field('name,url')->select();
$datas = CommonAttachment::where('uid', $user->uid)->where('mime', 'like', 'image%')->field('name,url')->select();
return json([
"state" => "SUCCESS",
"list" => $datas,
@@ -171,7 +171,7 @@ class UeditorPlus
try {
$user = app()->auth->info;
$data['uid'] = $user->uid; // 根据你的登录逻辑获取用户ID
$info = Attachment::create($data);
$info = CommonAttachment::create($data);
return $info;
} catch (\Exception $e) {
// 记录日志,但不要因为入库失败而中断上传流程(或者根据需求决定)