享耍主站开发文档
覆盖主站前端应用、管理后台、PHP MVC API、鉴权会话、插件体系、数据表、安全基线、部署运维与提示词模板。插件包的独立规范请查看插件仓库文档。
01产品与架构
享耍是一套轻量工作台:主站负责介绍与入口,/app/ 是会员应用,/admin/ 是管理后台,/api/ 是统一 JSON 接口。插件主代码放在插件仓库分发,安装后形成 /app/{slug}/ 独立页面。
- 前端:原生 JS 单页应用,无构建步骤,直接部署静态文件。
- 后端:PHP 8.1 自研 MVC 内核,PSR-4 自动加载,无 Composer 依赖。
- 数据:MySQL 5.7 / utf8mb4,PDO 关闭模拟预处理,统一预处理绑定。
- 插件:仓库上传 zip,业务站按会员安装、启停与卸载。
/api/index.php?r=... 取数据,接口统一返回 {ok, data} 或 {ok:false, message}。02目录结构
wwwroot/
├── index.html 主站介绍页
├── docs/ 主站开发文档(本页)
├── admin/ 管理后台 SPA(独立 tokenKey)
├── app/ 会员应用
│ ├── index.html 应用入口
│ ├── js/ app.js、api.js、config.js、module-*.js
│ ├── css/ module.css
│ ├── styles.css 主应用样式
│ ├── wangzhi/ 网址插件独立页
│ ├── biji/ 记事本插件独立页
│ └── wangpan/ 网盘插件独立页
└── api/
├── index.php 唯一入口
├── bootstrap.php 自动加载与内核启动
├── routes.php 路由表
├── config.php 数据库与站点配置
├── schema.sql 基础表结构
├── src/ 内核、控制器、模型、服务
└── plugins/ 插件目录(manifest.json + src + web)
规则:每个模块独立文件夹、独立链路;新增能力优先做成插件,避免主应用继续膨胀。
03文档结构
源码包内的文档与在线文档保持同一口径,避免「页面一套、文件一套」。
docs/
├── index.html 在线文档(公开可读)
├── ARCHITECTURE.md 架构、目录与请求链路
├── API.md 接口清单与返回约定
├── PLUGINS.md 主站插件体系与仓库接入
└── PROMPTS.md 提示词模板
- 在线地址:
/docs/,无需登录。 - 插件规范:以
https://xiangshua.com/docs为准(插件包结构、manifest、提示词)。 - 更新顺序:先改代码与接口,再同步在线文档,最后更新源码包。
- 版本记录:破坏性接口变更在文档顶部标注日期与迁移方式。
04前端应用
/app/index.html 加载 config.js、api.js、app.js,通过 hash 与 ?view= 切换视图。接口封装在 window.OOOApi。
| 方法 | 说明 |
|---|---|
OOOApi.request(r, options) | JSON 请求,自动带 Bearer 与错误提示。 |
OOOApi.upload(r, file) | 上传文件,返回进度回调。 |
OOOApi.getToken() | 本窗口 sessionStorage 优先,回填共享 localStorage。 |
OOOApi.setToken(t) | 同时写入本窗口与共享键。 |
多窗口登录隔离
- 会员端使用
ooo_token,后台使用ooo_admin_token,互不覆盖。 - 每个窗口优先读自己的
sessionStorage,新窗口才回退到共享localStorage。 - 同一浏览器可同时登录管理员与会员,多窗口可登录不同账号。
样式约定
- 图标卡片:透明背景、62px 炫彩圆角图标、标题居中、最多两行。
- 窄屏侧栏隐藏,改用顶部栏与底部 Tab 栏,模块页保持一行两个图标。
- 深色模式通过
data-theme切换,颜色一律用 CSS 变量。
05管理后台
/admin/ 是独立 SPA,使用 ooo_admin_token,普通入口禁止管理员登录,管理员必须从后台入口进入。
- 面板:概览、用户、卸载反馈、存储维护、会员运营、设置、管理日志。
- 登录:用户名 + 密码 + 图形验证码;验证码一次性、限时、限次数。
- 敏感操作写审计日志;创建/停用用户、清理文件等操作带
audit中间件。 - 存储维护可扫描缺失文件记录与孤立文件,确认后再清理。
06API 与路由
入口 /api/index.php?r={route},路由表在 api/routes.php,每项为 [METHOD, pattern, 'Controller@action', middleware[]]。
array('GET', 'notes', 'NoteController@index', array('auth')),
array('POST', 'notes', 'NoteController@create', array('auth')),
array('PUT', 'notes/{id}', 'NoteController@update', array('auth')),
array('DELETE','notes/{id}', 'NoteController@delete', array('auth')),
{id}编译为正整数;控制器按顺序接收参数。- 中间件:
auth校验 Bearer 会话,admin校验角色,audit写审计日志。 - 成功返回
{ok:true,data:...},失败返回{ok:false,message}与 HTTP 状态码。 - 插件路由由内核自动追加
plugin:{slug},未安装/停用返回 403。
核心接口分组
| 分组 | 路径 | 说明 |
|---|---|---|
| 认证 | auth/captcha auth/login auth/me auth/logout | 验证码、登录、当前用户、退出。 |
| 快捷访问 | shortcuts | 列表、新增、修改、删除。 |
| 笔记 | notes | 列表、新增、修改、删除。 |
| 网盘 | files folders | 上传、下载、移动、删除、文件夹。 |
| 插件 | plugins plugins/nav plugins/{slug}/update plugins/{slug}/backups | 索引、导航、安装(自动最新版)、更新、备份与恢复、卸载、启停。 |
| 后台 | admin/* | 用户、会员、设置、日志、存储与反馈。 |
07鉴权与会话
- 登录成功后签发 64 位 token,写入
sessions表,前端以Authorization: Bearer携带。 - 会话有效期:会员 2 小时、管理员 1 小时,可在「设置 · 站点设置」调整;插件仓库同一套配置。
- 每次登录新建会话,不删除旧会话,因此多设备、多窗口可同时在线。
- 管理员登录必须走
entry=admin;从普通入口登录管理员会返回 403admin_use_admin_entry。 - 脚本登录必须先取验证码;自动化场景使用
oauth_tickets+/oauth/exchange换取 token。
sessionStorage 保存本窗口令牌,localStorage 仅作新窗口回填;后台与会员端使用不同键名。08插件体系
主站本身只保留「会员」「消息」等基础能力,其它功能全部插件化。插件由仓库分发,会员在会员中心安装、启停、卸载。
自营网店(shop)买家前台使用框架内置路由 store/*(仅需会员登录,不依赖插件中间件):完整说明见 网店 README,接口清单见 网店 API。
| 层级 | 路径 / 表 | 说明 |
|---|---|---|
| 清单 | api/plugins/{slug}/manifest.json | slug、名称、版本、表前缀、导航、权限。 |
| 路由 | api/plugins/{slug}/routes.php | 自动追加 plugin:{slug} 中间件。 |
| 后端 | src/ | 命名空间 OOO\Plugins\{Studly}。 |
| 前端 | web/index.html | 安装后复制到 /app/{slug}/。 |
| 安装状态 | user_plugins | user_id + slug 唯一,含启用开关。 |
| 全局包 | plugin_packages | 版本、大小、SHA-256、下载统计。 |
与仓库的对接
- 业务站通过 HMAC-SHA256 签名请求仓库索引、下载包、回报下载 / 安装 / 更新 / 卸载事件。
- 下载后校验
X-Package-Sha256,再解包并执行 migrations;安装一律选择仓库最新版本。 - 仓库地址与接入账号在
api/config.php的plugin_hub配置。
更新与数据备份
- 仓库有新版本时,会员中心卡片在版本号后显示「有更新 vX」,操作区最前出现「更新到最新版」按钮。
- 升级前按插件
table_prefix全量快照到api/data/plugin-backups/{slug}/*.json.gz,默认保留最近 5 份,可随时恢复。 - 升级失败自动恢复数据并尝试回拉旧版代码;恢复入口在卡片的「数据备份」弹窗。
更新包示例(shop 1.1.1 → 1.2.0)
更新包是版本号更高的完整包:slug 与 table_prefix 不变,只递增 version;结构变更时新增迁移文件,全部迁移会在安装 / 更新时重跑,必须幂等。
// manifest.json(只改版本与简介)
{
"slug": "shop",
"name": "自营网店",
"version": "1.2.0",
"table_prefix": "p_shop_",
"intro": "1.2.0:新增订单备注,支持详情编辑与列表检索。"
}
-- migrations/003_order_remarks.sql
CREATE TABLE IF NOT EXISTS p_shop_order_remarks (
id INT UNSIGNED NOT NULL AUTO_INCREMENT,
user_id INT UNSIGNED NOT NULL DEFAULT 0,
order_id INT UNSIGNED NOT NULL DEFAULT 0,
remark VARCHAR(200) NOT NULL DEFAULT '',
created_at DATETIME NOT NULL,
updated_at DATETIME NOT NULL,
PRIMARY KEY (id),
KEY idx_user_order (user_id, order_id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
# 打包(不要带最外层目录)
cd /path/to/shop-1.2.0
zip -r ../shop-1.2.0.zip . -x "node_modules/*" ".git/*" "tests/*" "*.log"
unzip -l ../shop-1.2.0.zip | head -20 # 根目录必须直接是 manifest.json
完整示例(目录变化、MySQL 5.7 加列守卫、更新说明、上架与验证步骤)见 仓库文档 · 09A 更新包制作与发布。
插件包结构、manifest 字段、路由写法与提示词,详见 插件仓库开发文档。
09数据表
| 表 | 用途 | 关键字段 |
|---|---|---|
users | 会员与管理员 | username role status display_name |
sessions | 登录会话 | token user_id expires_at ip ua |
shortcuts | 快捷访问 | user_id title url icon |
notes | 笔记 | user_id title content created_at |
files / folders | 网盘 | user_id name size path |
plugin_packages | 插件包索引 | slug version sha256 |
user_plugins | 会员安装状态 | user_id slug enabled |
plugin_backups | 插件升级 / 手动备份 | slug trigger_type version_from file |
settings | 站点设置 | group key value |
admin_logs | 管理审计 | admin_id action detail |
p_notes_),禁止读写公共表;卸载默认不删表。10安全基线
- SQL:所有查询经
SqlGuard与 PDO 预处理;关闭模拟预处理;LIMIT参数转整数后再拼接。 - SqlGuard:先抹掉字符串字面量,再拒绝多语句与
--、/* */、#注释截断;动态表名/列名走白名单。 - 认证:登录强制图形验证码;密码
password_hash;会话 token 64 位随机。 - 越权:每个接口按
user_id校验数据归属;后台接口额外要求admin中间件。 - 上传:限制类型与大小,文件名重命名,禁止路径穿越;上传目录不允许执行脚本。
- 输出:前端统一转义,富文本白名单过滤;错误不返回堆栈与敏感配置。
- 审计:敏感管理操作写
admin_logs,保留操作人、动作与详情。
PDO 预处理 SqlGuard 拦截 验证码 角色中间件 审计日志
11部署与运维
- 上传
wwwroot内容到站点根目录,保留.htaccess静态化规则。 - 配置
api/config.php的数据库、站点地址、插件仓库与短信/支付参数。 - 首次访问执行安装:写入基础表与管理员账号;升级用
install/upgrade。 - 目录权限:上传目录可写,
api/config.php与源码目录不可写。 - 启用 HTTPS;后台建议限制来源 IP 或加独立域名。
- 定时任务:清理过期会话与临时文件,备份数据库与上传目录。
发布检查
- 静态资源版本号已更新,避免浏览器命中旧缓存。
- 接口返回结构与文档一致,错误码可读。
- 桌面与窄屏均无横向滚动,深色模式可读。
- 登录、退出、多窗口会话与验证码回归通过。
- 数据库变更已写入
schema.sql或迁移脚本。
12提示词模板
替换花括号后直接交给 AI;一次只做一件事,先约束范围再提要求。
A. 新增一个接口 / 模块
你是享耍主站后端开发者。请只新增下面这个接口,不要改动无关路由。
需求:{一句话描述}
路由:{METHOD} {path}
入参:{字段与类型}
返回:{结构}
权限:{登录 / 管理员 / 公开}
数据表:{表名与字段;若需新建请给出幂等 SQL}
约束:
- 路由写进 api/routes.php,控制器放 api/src/Http/Controllers,模型放 api/src/Models。
- 所有 SQL 预处理绑定;分页参数转整数后再拼接 LIMIT。
- 按 user_id 校验数据归属;错误抛 HttpException 并给中文提示。
- 返回统一 $this->ok([...]) 结构。
- 完成后列出改动文件、SQL 变更与自测请求示例。
B. 改造前端页面
你是享耍前端开发者。只修改我指定的页面与样式,不要重构无关代码。
页面:{/app/index.html 或 /app/xxx/index.html}
要改的内容:{逐条描述}
保持不变:{结构、类名、接口、深链}
要求:
- 沿用现有 CSS 变量与组件类名,不引入框架。
- 桌面与 390px 窄屏都要正常,无横向滚动。
- 深色模式可读;按钮可键盘操作。
- 不破坏 ?view= 深链与多窗口登录隔离。
- 完成后说明改了哪些文件与自测步骤。
C. 审查与修复
你是享耍代码审查员。请审查我提供的文件,按严重程度排序输出问题,不要直接大改。
检查项:
1. SQL 是否全部预处理;SqlGuard 是否覆盖;分页是否整数拼接。
2. 接口是否校验 user_id 归属;后台接口是否有 admin 中间件。
3. 登录态是否可能出现跨窗口覆盖;后台与会员 token 是否分离。
4. 上传是否限制类型/大小/路径;输出是否转义。
5. 前端加载/空/错误态是否齐全;窄屏是否一行两个图标。
6. 敏感操作是否写审计日志。
输出格式:P0/P1/P2 分级,每条给出文件、行号、风险与最小修复方案;最后列出待确认问题。
D. 发布插件更新包
你是享耍插件维护者。我要发布 {slug} 的更新包,并确保升级不丢数据。
当前版本:{x.y.z}
目标版本:{x.y.w}
本次改动:{新增 / 修复 / 结构变更}
请完成:
1. 说明版本号该递增哪一段(修订 / 功能 / 不兼容)及理由。
2. 输出 manifest.json:slug 与 table_prefix 不变,version 递增,intro 写明更新内容。
3. 结构变更时新增 migrations/{序号}.sql,必须幂等;不得修改历史迁移文件。
4. 更新 docs/README.md 的更新说明(新增、变更、修复、注意事项)。
5. 打包完整插件包,zip 内不套外层目录,命名 {slug}-{version}.zip;
排除 node_modules、.git、测试脚本与密钥。
6. 到仓库后台「插件包」→ {slug} 分组 → 「上传更新包」,确认新版本置顶并标记「最新」。
7. 说明验收:会员中心出现「有更新 vX」→ 一键更新 → 升级前自动备份 → 失败自动回滚。
E. 会员中心升级与备份改造
你是享耍业务站开发者。目标:会员中心支持「安装自动取最新版 + 有更新提示 + 一键更新 + 数据备份恢复」。
后端(OOO\Plugin\PluginManager):
1. catalog() 返回 latest_version 与 has_update(本地 version vs 仓库索引,version_compare 比较)。
2. install():缺包按仓库最新版下载;本机落后时自动走升级流程。
3. update():校验已安装、非内置、仓库确有更高版本后调用 runUpgrade()。
4. runUpgrade():先按 table_prefix 全量备份 → 下载校验 SHA-256 → 解包 → migrations;
失败恢复备份并尽力回拉旧版本。
5. 备份文件放 api/data/plugin-backups/{slug}/*.json.gz,元数据入 plugin_backups,保留最近 5 份。
6. 路由:plugins/{slug}/update 与 plugins/{slug}/backups(增删查、restore),全部带 auth。
前端(会员中心):
- 版本号后显示「有更新 vX」;动作区顺序:更新到最新版 → 打开 → 启停 → 数据备份 → 删除。
- 备份弹窗展示类型/时间/版本/表数/行数/大小,支持立即备份、恢复、删除;
恢复前提示「插件数据全站共享,会覆盖所有会员」。
输出:改动文件、接口返回示例与验证步骤(含失败回滚验证)。