chore: 重写初始提交(清空历史,整理后全量提交)

This commit is contained in:
ywxapp
2026-08-16 16:54:14 +08:00
commit 6c1a106bc1
1808 changed files with 238144 additions and 0 deletions
+113
View File
@@ -0,0 +1,113 @@
<?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 addon\seo;
use think\facade\Db;
use ywxapp\AddonBase;
use ywxapp\model\BaseModel;
/**
* SEO增强插件
*
* 安装时框架自动导入 install.sql 建表(wxapp_seo_config / keywords / snapshots);
* 卸载按统一前缀清理全部表;升级时经 callAddonHook('upgrade') 收敛表结构。
*/
class Addon extends addon
{
/**
* 安装钩子(框架自动导入 install.sql 后调用)。
*/
public function install(): bool
{
return true;
}
/**
* 卸载钩子:清理本插件全部表。
* 与 install.sql 表名前缀严格对齐(wxapp_seo_),直接复用统一前缀,
* 避免依赖 database.prefix 配置(install.sql 为硬写前缀)。
*/
public function uninstall(): bool
{
$prefix = 'wxapp_seo_';
$tables = [
'config', // SEO 配置表
'keywords', // 内链关键词表
'snapshots', // 收录排名快照表
];
foreach ($tables as $t) {
try {
Db::execute("DROP TABLE IF EXISTS `{$prefix}{$t}`");
} catch (\Exception $e) {
// 忽略
}
}
return true;
}
/**
* 升级时确保全部表存在(读 install.sqlCREATE TABLE IF NOT EXISTS 幂等建表)。
* 单一事实源 = install.sql,避免复制 DDL 导致漂移。
*/
private function ensureTablesFromInstallSql(): void
{
$sqlFile = __DIR__ . DIRECTORY_SEPARATOR . 'install.sql';
if (!is_file($sqlFile)) {
return;
}
$content = (string) file_get_contents($sqlFile);
$content = preg_replace('/--.*|\/\*[\s\S]*?\*\//', '', $content);
$stmts = array_filter(
array_map('trim', explode(';', $content)),
function ($s) {
return strlen($s) > 5 && preg_match('/^CREATE\s+TABLE/i', $s);
}
);
foreach ($stmts as $sql) {
if (preg_match('/CREATE\s+TABLE\s+(?:IF\s+NOT\s+EXISTS\s+)?`?([\w]+)`?/i', $sql, $m)) {
BaseModel::ensureTable($m[1], $sql);
}
}
}
/**
* 升级钩子(在线升级 / 后台手动升级均会触发)。
*
* 在线升级(AddonService::onlineUpgrade)已重导 install.sql 补全表;
* 但「已存在表新增列」install.sql 的 CREATE TABLE IF NOT EXISTS 对已有表无效。
* 此处作为升级收敛点:确保全部表存在 + 对已知易漂移列做幂等补列兜底。
* 未来新增列统一在 $columnFixes 登记(须带 DEFAULT x 或 NULL,保证降级安全),
* 避免各控制器/模型重复 ensureColumn/ALTER 导致 DDL 漂移。
*
* @param string $currentVersion 升级前版本号
*/
public function upgrade($currentVersion = ''): bool
{
// 1) 确保全部表存在(幂等,单一事实源 install.sql
$this->ensureTablesFromInstallSql();
// 2) 补列兜底:'完整表名(含前缀)' => ['列名' => '列定义']
// BaseModel::ensureColumn 先探测存在性,重复执行安全。
// install.sql 当前已含全部列,故此处留空;新增列在此登记即可。
$columnFixes = [
// 'wxapp_seo_keywords' => [
// 'new_col' => "varchar(50) NOT NULL DEFAULT '' COMMENT '示例'",
// ],
];
foreach ($columnFixes as $table => $cols) {
foreach ($cols as $column => $def) {
BaseModel::ensureColumn($table, $column, $def);
}
}
return true;
}
}
+57
View File
@@ -0,0 +1,57 @@
<?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 addon\seo\controller;
use ywxapp\controller\FrontendBase;
use think\Response;
/**
* SEO增强前台控制器
*
* 对外提供站点地图、robots 与状态页。无需登录即可访问。
*/
class Index extends FrontendBase
{
protected $noNeedLogin = ['*'];
protected $noNeedVerify = ['*'];
/**
* 前台状态页
*/
public function index()
{
// TODO: 前台展示/状态页
$this->view->assign('title', 'SEO增强');
return $this->view->fetch('index/index');
}
/**
* 站点地图(/seo/sitemap.xml
*/
public function sitemap()
{
// TODO: 遍历站点 URL 生成符合 sitemaps.org 规范的 XML
$xml = '<?xml version="1.0" encoding="UTF-8"?>'
. '<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9"></urlset>';
return Response::create($xml, 'xml')->contentType('application/xml');
}
/**
* robots.txt/seo/robots.txt
*/
public function robots()
{
// TODO: 读取 wxapp_seo_config.robots 输出;此处为默认兜底
$txt = "Member-agent: *\nAllow: /";
return Response::create($txt)->contentType('text/plain');
}
}
+30
View File
@@ -0,0 +1,30 @@
<?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 addon\seo\controller\api;
/**
* SEO增强对外 API(占位)
*
* 非市场类插件,遵循框架统一 Result 契约(code=0 成功)。
* 如需与中心站市场联动再按 Market 系 code=1 契约调整。
*/
class Seo
{
/**
* 示例:对外查询接口
*/
public function lists()
{
// TODO: 返回 SEO 配置/关键词等数据
return json(['code' => 0, 'msg' => 'ok', 'data' => []]);
}
}
+61
View File
@@ -0,0 +1,61 @@
<?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 addon\seo\controller\backend;
/**
* SEO增强后台控制器
*
* 业务占位骨架,四个动作对应 menu.json 的四个菜单项。
* 实际逻辑(读写 wxapp_seo_config/keywords/snapshots)在 TODO 处实现。
*/
class Seo extends SeoBackend
{
/**
* SEO概览:收录/排名/内链数等汇总
*/
public function index()
{
// TODO: 聚合 wxapp_seo_snapshots 与 wxapp_seo_keywords 的数量与概览指标
$this->view->assign('title', 'SEO概览');
return $this->view->fetch('seo/index');
}
/**
* SEO设置:站点标题/关键词/描述模板、robots 等
*/
public function setting()
{
// TODO: 读取/保存 wxapp_seo_config(表单提交经 POST 落库)
$this->view->assign('title', 'SEO设置');
return $this->view->fetch('seo/index');
}
/**
* 内链关键词:增删改查
*/
public function keywords()
{
// TODO: 内链关键词 CRUD(表 wxapp_seo_keywords
$this->view->assign('title', '内链关键词');
return $this->view->fetch('seo/index');
}
/**
* 收录统计:搜索引擎收录/排名趋势
*/
public function stats()
{
// TODO: 收录排名趋势(表 wxapp_seo_snapshots
$this->view->assign('title', '收录统计');
return $this->view->fetch('seo/index');
}
}
@@ -0,0 +1,33 @@
<?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 addon\seo\controller\backend;
use ywxapp\controller\BackendBase;
/**
* SEO增强后台控制器基类
*
* 说明:addon 后台路由(/seo/backend/...)经全局路由分发落在默认 frontend 应用,
* 容器 auth 绑定会解析成前台 Auth(isAdmin=false),后台 token 上下文不匹配会被拒。
* AddonBackend::_initialize() 已统一处理:当 $this->auth 非 AdminAuth 时强制还原为
* AdminAuth 并 tryInitByToken(),再按子类声明的 noNeedLogin/noNeedVerify 做登录与权限校验。
*
* 这里仅声明跳过后台细粒度权限校验,避免权限规则未配置时锁死后台;登录仍强制要求。
*/
class SeoBackend extends BackendBase
{
/**
* 跳过后台细粒度权限校验(权限规则未配置时避免锁死后台)。
* 登录要求仍由 AddonBackend::_initialize() 强制(noNeedLogin 默认空=需要登录)。
*/
protected $noNeedVerify = ['*'];
}
+39
View File
@@ -0,0 +1,39 @@
<?php
return [
'name' => 'seo',
'title' => 'SEO增强工具',
'intro' => '一站式营销与SEO增强:自动站点地图、robots、内链关键词、收录排名统计与AI伪原创占位。',
'author' => 'ywxapp',
'website' => 'https://github.com',
'version' => '1.0.1',
'state' => 0,
'url' => '/seo',
'license' => '',
'licenseto' => 0,
'config' => [
],
'events' => [
'bind' =>
[
],
'listen' =>
[
],
'subscribe' =>
[
],
],
'middleware' => [
'alias' =>
[
],
'priority' =>
[
],
],
'services' => [
],
'install_time' => 0,
'update_time' => 1786365219,
];
+53
View File
@@ -0,0 +1,53 @@
-- ============================================================
-- addon/seo/install.sql —— SEO增强插件数据表
-- 框架约定:插件安装时由 ywxapp\service\AddonService 执行本文件
-- (仅允许 CREATE TABLE / INSERT,见 importsql 白名单)。
-- 表名须为 __PREFIX__seo_*,与 __PREFIX__addon 等核心表命名一致。
-- 注意:种子文案禁用 --(框架会逐行把 -- 起内容当注释删,会砍断字符串)。
-- ============================================================
SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;
CREATE TABLE IF NOT EXISTS `__PREFIX__seo_config` (
`id` int unsigned NOT NULL AUTO_INCREMENT,
`name` varchar(30) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL DEFAULT '' COMMENT '变量名',
`group` varchar(30) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT '' COMMENT '分组',
`title` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT '' COMMENT '变量标题',
`tip` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT '' COMMENT '变量描述',
`type` varchar(30) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT '' COMMENT '类型:string,text,int,bool',
`value` text CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci COMMENT '变量值',
`content` text CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci COMMENT '变量字典数据',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='SEO配置表';
INSERT INTO `__PREFIX__seo_config` (`id`, `name`, `group`, `title`, `tip`, `type`, `value`) VALUES
(1, 'site_title', 'basic', '站点标题模板', '支持变量替换', 'string', '{title} - {name}'),
(2, 'site_keywords', 'basic', '默认关键词', '逗号分隔', 'string', ''),
(3, 'site_description', 'basic', '默认描述', '首页描述', 'text', ''),
(4, 'robots', 'basic', 'robots内容', '留空使用默认', 'text', 'User-agent: * Allow: /');
CREATE TABLE IF NOT EXISTS `__PREFIX__seo_keywords` (
`id` int unsigned NOT NULL AUTO_INCREMENT COMMENT 'ID',
`keyword` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL DEFAULT '' COMMENT '关键词',
`url` varchar(500) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL DEFAULT '' COMMENT '内链目标URL',
`weight` int DEFAULT '0' COMMENT '权重,越大越优先',
`status` tinyint DEFAULT '1' COMMENT '状态:1-启用,0-禁用',
`create_at` int DEFAULT NULL COMMENT '创建时间',
`update_at` int DEFAULT NULL COMMENT '更新时间',
PRIMARY KEY (`id`),
KEY `idx_status` (`status`),
KEY `idx_keyword` (`keyword`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='内链关键词表';
CREATE TABLE IF NOT EXISTS `__PREFIX__seo_snapshots` (
`id` int unsigned NOT NULL AUTO_INCREMENT COMMENT 'ID',
`engine` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT '' COMMENT '搜索引擎:baidu/google/360/sogou',
`url` varchar(500) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT '' COMMENT '被统计页面URL',
`indexed` tinyint DEFAULT '0' COMMENT '是否被收录:1-是,0-否',
`rank` int DEFAULT '0' COMMENT '排名,0=未进入前100',
`snapshot_date` date DEFAULT NULL COMMENT '快照日期',
`create_at` int DEFAULT NULL COMMENT '创建时间',
PRIMARY KEY (`id`),
KEY `idx_engine` (`engine`),
KEY `idx_date` (`snapshot_date`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='收录排名快照表';
+20
View File
@@ -0,0 +1,20 @@
{
"backend": [
{
"name": "seo",
"title": "SEO增强",
"icon": "fa fa-search",
"type": 1,
"sort": 50,
"status": 1,
"child": [
{ "name": "seo/index", "title": "SEO概览", "icon": "fa fa-dashboard", "type": 2, "sort": 0, "route": "/seo/backend/index" },
{ "name": "seo/setting", "title": "SEO设置", "icon": "fa fa-cog", "type": 2, "sort": 1, "route": "/seo/backend/setting" },
{ "name": "seo/keywords", "title": "内链关键词", "icon": "fa fa-link", "type": 2, "sort": 2, "route": "/seo/backend/keywords" },
{ "name": "seo/stats", "title": "收录统计", "icon": "fa fa-bar-chart", "type": 2, "sort": 3, "route": "/seo/backend/stats" }
]
}
],
"member": [],
"frontend": []
}
+38
View File
@@ -0,0 +1,38 @@
<?php
// +----------------------------------------------------------------------
// | YwxApp [ WE CAN DO IT JUST THINK ]
// +----------------------------------------------------------------------
// | Copyright (c) 2026-2036 http://ywxapp.cn All rights reserved.
// +----------------------------------------------------------------------
// +----------------------------------------------------------------------
// | Author: ywxapp<admin@ywxapp.cn>
// +----------------------------------------------------------------------
use think\facade\Route;
// 说明:本文件由 ywxapp/service/AppService::loadAddonRoutes() 在 boot 阶段
// include,并统一被外层 Route::group('seo', ...) 包住,因此下面写的都是
// 【相对规则】,最终自动加 /seo 前缀:
// 顶层规则 -> /seo/*
// backend 组 -> /seo/backend/*
// api 组 -> /seo/api/*
// 前台页面 / 接口(最终地址 /seo/index、/seo/sitemap.xml、/seo/robots.txt
Route::rule('index', 'Index/index');
Route::rule('sitemap.xml', 'Index/sitemap')->completeMatch(true);
Route::rule('robots.txt', 'Index/robots')->completeMatch(true);
// 后台管理路由(对应 controller/backend/ 下的控制器;最终地址 /seo/backend/*
// 注意:全局 route_complete_match=false 时,裸规则会前缀匹配子路径,故必须
// ->completeMatch(true) 强制完整匹配,避免 /seo/backend/setting 被派发到错误动作。
Route::group('backend', function () {
Route::rule('index', 'backend/Seo/index')->completeMatch(true);
Route::rule('setting', 'backend/Seo/setting')->completeMatch(true);
Route::rule('keywords', 'backend/Seo/keywords')->completeMatch(true);
Route::rule('stats', 'backend/Seo/stats')->completeMatch(true);
});
// 对外 API(最终地址 /seo/api/*,按需启用)
Route::group('api', function () {
Route::rule('lists', 'api/Seo/lists')->completeMatch(true);
});
+40
View File
@@ -0,0 +1,40 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>{$title|default='SEO增强'}</title>
<link rel="stylesheet" href="/static/layui/css/layui.css">
</head>
<body>
<div class="layui-fluid">
<div class="layui-card">
<div class="layui-card-header">{$title|default='SEO增强'}</div>
<div class="layui-card-body">
<blockquote class="layui-elem-quote">
骨架占位页 —— 在此实现业务逻辑(SEO概览 / 设置 / 内链关键词 / 收录统计)。
</blockquote>
<div class="layui-tab">
<ul class="layui-tab-title">
<li class="layui-this">概览</li>
<li>设置</li>
<li>内链关键词</li>
<li>收录统计</li>
</ul>
<div class="layui-tab-content">
<div class="layui-tab-item layui-show">TODO:展示收录 / 排名 / 内链汇总指标。</div>
<div class="layui-tab-item">TODO:站点标题 / 关键词 / 描述模板、robots 配置表单(表 wxapp_seo_config)。</div>
<div class="layui-tab-item">TODO:内链关键词增删改查(表 wxapp_seo_keywords)。</div>
<div class="layui-tab-item">TODO:收录排名趋势(表 wxapp_seo_snapshots)。</div>
</div>
</div>
</div>
</div>
</div>
<script src="/static/layui/layui.js"></script>
<script>
layui.use('element', function () {
var element = layui.element;
});
</script>
</body>
</html>
+11
View File
@@ -0,0 +1,11 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>{$title|default='SEO增强'}</title>
</head>
<body>
<h1>{$title|default='SEO增强'}</h1>
<p>SEO增强插件前台占位页。访问 /seo/sitemap.xml 与 /seo/robots.txt 查看对外接口。</p>
</body>
</html>