PuranCMS 系统概述
什么是 PuranCMS?
PuranCMS 是一款基于 ThinkPHP 8.0 框架开发的轻量级内容管理系统(CMS),专为中小企业和个人开发者设计。系统以 ThinkPHP 8.0 为后端核心,后台管理采用 Vue 3 + Element Plus 构建的单页应用(SPA,Vite 构建),前台站点采用 ThinkPHP 原生模板引擎服务端渲染,模板中结合 Layui 与 jQuery 实现交互组件。
设计理念
简洁高效:去除冗余功能,专注于核心内容管理
灵活扩展:采用模型驱动架构,支持自定义内容模型
易于部署:标准 LAMP/LEMP 环境即可运行
安全可靠:内置权限管理、SQL 防注入、XSS 防护
核心特性
多模型内容管理(文章、产品、页面、图片、下载、招聘、分支等)
自定义导航菜单管理
广告位管理
留言管理
后台权限管理
操作日志记录
访客统计
插件扩展机制
wangEditor 富文本编辑器集成
适用场景
PuranCMS 适用于以下场景:
企业官网建设
产品展示网站
新闻资讯网站
个人博客
小型电商网站
功能特性详解
内容管理
系统支持多种内容模型,每种模型对应不同的业务场景:
| 模型 | 说明 | 应用场景 |
|---|---|---|
| Article | 文章模型 | 新闻资讯、博客文章 |
| Product | 产品模型 | 产品展示、产品目录 |
| Page | 单页模型 | 关于我们、联系方式 |
| Image | 图片模型 | 图片画廊、相册 |
| Download | 下载模型 | 文件下载、资源分享 |
| Recruitment | 招聘模型 | 职位发布、招聘信息 |
| Branch | 分支模型 | 分支机构、门店信息 |
除内置模型外,还支持通过后台「模型管理」自定义内容模型与字段。
商城交易
内置完整商城能力:前台购物车(Cart)、结算下单、在线支付(支付宝 / 微信 / 余额)、会员中心订单管理,后台商品与订单联动管理。
表单与文档
动态表单系统(Form / FormField / FormData)支持自定义表单字段与数据收集;文档中心(DocCategory / DocContent)支持分类树与富文本文档展示。
导航管理
支持自定义导航菜单,可绑定不同的内容模型和模板,实现灵活的页面跳转和内容展示。
广告管理
支持多种广告类型(图片广告、文字广告、HTML 代码),可设置广告位置、排序、状态等。
留言管理
前台用户可提交留言,后台管理员可查看、标记已读、删除留言,支持批量操作。
权限管理
基于角色的权限控制(RBAC),支持菜单权限、操作权限的细粒度控制。
数据统计
提供控制台仪表盘,展示访客统计、地区分布、流量统计、操作日志等数据。
技术栈说明
后端技术栈
| 技术 | 版本 | 用途 |
|---|---|---|
| PHP | >= 8.0(当前运行 8.2) | 后端编程语言 |
| ThinkPHP | 8.0 | Web 框架 |
| MySQL | >= 5.7(推荐 8.0) | 关系型数据库 |
| Composer | latest | 依赖管理 |
核心依赖包
| 包名 | 用途 |
|---|---|
| topthink/framework | ThinkPHP 核心框架 |
| topthink/think-orm | ORM 数据库操作 |
| topthink/think-filesystem | 文件系统 / 云存储 |
| topthink/think-captcha | 验证码生成 |
| topthink/think-view | 模板引擎(原生模板) |
| topthink/think-worker | Workerman 支持(异步 / WebSocket) |
| topthink/think-queue | 消息队列 |
| topthink/think-migration | 数据库迁移 |
| topthink/think-cors | 跨域资源共享(CORS) |
| firebase/php-jwt | JWT 鉴权令牌 |
| intervention/image | 图片处理(裁剪 / 水印) |
| bacon/bacon-qr-code | 二维码生成 |
| phpmailer/phpmailer | 邮件发送 |
| workerman/workerman | 长连接 / 异步任务引擎 |
前端技术栈
| 技术 | 用途 |
|---|---|
| Vue 3 + Element Plus | 后台管理界面(单页应用 SPA,Vite 构建) |
| Pinia / vue-router / axios | 状态管理 / 路由 / HTTP 请求 |
| ECharts | 控制台数据可视化图表 |
| wangEditor | 后台富文本编辑器 |
| ThinkPHP 原生模板 + Layui + jQuery | 前台(PC 站点)服务端渲染与交互组件 |
| translate.js | 前台多语言自动翻译 |
服务器环境
Web 服务器:Nginx 1.18+(推荐)/ Apache 2.4+
PHP 扩展:PDO、MBString、OpenSSL、JSON、Fileinfo、GD 或 Imagick
推荐配置:2 核 CPU / 4GB 内存 / 50GB SSD
环境要求与准备
服务器环境要求
PHP:版本 >= 8.0,推荐 8.1 或 8.2
MySQL:版本 >= 5.7,推荐 8.0
Web 服务器:Nginx 1.18+ 或 Apache 2.4+
Composer:版本 >= 2.0
PHP 扩展要求
确保以下 PHP 扩展已启用:
pdo_mysql- 数据库连接mbstring- 多字节字符串处理openssl- 加密支持json- JSON 处理fileinfo- 文件类型检测gd- 图像处理(验证码、二维码、缩略图)
目录权限要求
以下目录需要写入权限:
runtime/- 运行时缓存、日志(runtime/log/)、文件完整性基线等public/uploads/- 文件上传目录public/storage/- 存储目录(如使用本地存储)
检查环境
# 检查 PHP 版本 php -v # 检查 PHP 扩展 php -m | grep -E "pdo_mysql|mbstring|openssl|json|fileinfo|gd" # 检查 Composer 版本 composer -V
安装步骤指南
方式一:通过安装向导安装(推荐)
将项目文件部署到 Web 服务器目录
配置 Web 服务器,将网站根目录指向
public/目录访问
http://your-domain/install进入安装向导按照向导提示完成环境检测、数据库配置、管理员账号设置
安装完成后,访问
http://your-domain/admin登录后台
方式二:手动安装
克隆或下载项目
git clone https://github.com/your-repo/purancms.git cd purancms
安装依赖
composer install
配置环境变量
cp .env.example .env
编辑
.env文件,配置数据库连接信息与 JWT 密钥(JWT_SECRET必须改为随机长字符串)导入数据库
mysql -u root -p your_database < database/install.sql
设置目录权限
chmod -R 755 runtime/ chmod -R 755 public/uploads/
配置 Web 服务器
参考下方 Nginx/Apache 配置示例
Nginx 配置示例
server {
listen 80;
server_name your-domain.com;
root /path/to/purancms/public;
index index.php;
location / {
include /path/to/purancms/public/nginx.htaccess;
}
# 上传目录禁止执行 PHP(必须在 PHP location 之前)
location ~* ^/(storage|uploads)/.*\.(php|phtml|php5|phar)$ {
deny all;
}
location ~ \.php(.*)$ {
fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
}伪静态规则已内置在 public/nginx.htaccess(含上传目录防执行与配置文件保护),通过 include 引入即可。
Apache 配置示例
项目已包含 public/.htaccess 文件,确保 Apache 启用了 mod_rewrite 模块。
配置参数说明
环境变量配置 (.env)
项目根目录的 .env 采用扁平键值格式(模板见 .env.example):
APP_DEBUG = false DEFAULT_LANG = zh-cn JWT_SECRET = 请替换为随机长字符串(>= 48 字节) CORS_ALLOWED_ORIGINS = DB_DRIVER = mysql DB_TYPE = mysql DB_HOST = 127.0.0.1 DB_NAME = purancms DB_USER = root DB_PASS = your_password DB_PORT = 3306 DB_CHARSET = utf8mb4 DB_PREFIX = pr_
生产环境必须设置 APP_DEBUG = false,.env 已被 .gitignore 忽略,切勿提交真实密钥。
配置文件说明
| 文件 | 说明 |
|---|---|
| config/app.php | 应用配置(默认控制器、时区等) |
| config/database.php | 数据库配置 |
| config/cache.php | 缓存配置 |
| config/session.php | Session 配置 |
| config/cookie.php | Cookie 配置 |
| config/jwt.php | JWT 鉴权配置 |
| config/cors.php | 跨域(CORS)配置 |
| config/security.php | 安全中心配置(上传扫描、响应头等) |
| config/filesystem.php | 文件存储配置 |
| config/queue.php | 消息队列配置 |
| config/worker.php | Workerman 配置 |
| config/view.php | 模板引擎配置 |
| config/log.php | 日志配置 |
| config/route.php | 路由配置 |
| config/captcha.php | 验证码配置 |
| config/lang.php | 多语言配置 |
后台系统配置
登录后台后,可在"系统设置"中配置:
站点名称、Logo、后台 Logo
SEO 设置(标题、关键词、描述)
联系方式(电话、邮箱、地址)
版权信息、备案号
后端目录结构
核心目录说明
app/ ├── controller/ # 控制器(按端划分) │ ├── BaseController.php # 基础控制器 │ ├── admin/ # 后台控制器(Dashboard、Content、System、Upload、Security、Shop 等 29 个) │ ├── index/ # 前台控制器(Index、Member、Pay、Shop、Doc、Seo 等) │ ├── api/ # API 接口控制器(Content、Member、Visit、Multilang 等) │ └── install/ # 安装向导(Install.php) ├── common/ # 公共类库 │ ├── BasePlugin.php # 插件基类 │ ├── AddonTemplate.php # 插件脚手架模板 │ ├── IpRegion.php # IP 归属地 │ └── Version.php # 版本信息 ├── middleware/ # 中间件 │ ├── AdminAuth.php # 后台登录验证 │ ├── MemberAuth.php # 会员登录验证 │ ├── InstallCheck.php # 安装状态检查 │ ├── MaintenanceMiddleware.php # 维护模式 │ └── SecurityGuard.php # 安全防护(XSS 拦截、IP 黑白名单等) ├── model/ # 数据模型(45 个) │ ├── BaseModel.php # 模型基类 │ ├── Article.php # 文章模型 │ ├── Product.php # 产品模型 │ └── ... ├── service/ # 服务层(49 个) │ ├── ContentService.php # 内容服务 │ ├── AdminService.php # 管理员服务 │ ├── SecurityService.php # 安全中心服务 │ ├── TokenService.php # JWT 令牌服务 │ └── ... ├── taglib/ # 自定义标签库 │ └── Puran.php # PuranCMS 模板标签 ├── command/ # 命令行指令 │ └── FileIntegrityScan.php # 文件完整性扫描 └── view/ # 模块视图 └── install/ # 安装向导视图 extend/ # 扩展类库(psr-0 自动加载) ├── security/ # 安全组件(FileValidator 等) ├── plugin/ # 插件扩展 └── data/ # 数据组件
目录职责
controller/:处理 HTTP 请求,调用服务层,返回响应(admin / index / api / install 四端)
model/:数据库操作,数据验证,业务数据封装
service/:复杂业务逻辑,组合多个模型操作
middleware/:请求拦截,登录验证,安全防护
taglib/:自定义模板标签,简化前台模板数据调用
command/:命令行任务(
php think指令)extend/:独立扩展类库,不依赖框架模块
后台管理界面为 Vue 3 单页应用,源码位于 view/admin/,后台控制器仅提供 API 接口。
前端目录结构
后台前端(Vue SPA)
后台管理界面为 Vue 3 单页应用,源码位于 view/admin/,构建产物输出至 view/admin/dist/:
view/admin/ ├── src/ │ ├── views/ # 页面组件(system/、security/、doc/、shop/、image/ 等) │ ├── components/ # 公共组件(IconSelect 等) │ ├── layouts/ # 布局(DefaultLayout.vue) │ ├── router/ # 路由(vue-router) │ ├── api/ # 接口封装(axios) │ └── utils/ # 工具函数(TypeScript) ├── dist/ # 构建产物(vite build) └── package.json # 依赖清单
前台静态资源目录
public/static/ ├── index/ # 前台静态资源 │ ├── css/ # 前台样式 │ ├── js/ # 前台脚本(jquery.min.js、main.js 等) │ └── images/ # 前台图片 ├── layui/ # Layui 框架(前台交互组件) ├── vendor/ # 第三方前端库 ├── theme/ # 主题资源(enterprise) └── addons/ # 插件静态资源(multilang/translate.js 等)
前端架构说明
后台采用 Vue 3 + Element Plus + Vite 构建的单页应用(SPA),状态管理使用 Pinia,路由使用 vue-router,HTTP 请求使用 axios
后台图表使用 ECharts,富文本编辑使用 wangEditor
前台为 ThinkPHP 服务端渲染模板,结合 Layui + jQuery 实现交互组件
前台多语言通过 translate.js 插件(multilang)自动翻译
模板目录说明
模板目录结构
template/ ├── default/ # 默认模板主题 │ ├── common/ # 公共模板 │ │ ├── header.html # 页头(导航) │ │ ├── footer.html # 页脚(版权、备案) │ │ └── pagination.html # 分页 │ ├── index/ # 前台页面模板 │ │ ├── index.html # 首页 │ │ ├── article_list.html / article_detail.html # 文章 │ │ ├── product_list.html / product_detail.html # 产品 │ │ ├── page_detail_doc.html # 文档页 │ │ └── ... │ └── user/ # 会员中心模板(login、register、shop_cart 等) └── enterprise/ # 企业主题(目录结构与 default 一致)
主题切换由后台「主题管理」控制,default 与 enterprise 两套主题目录结构保持一致。
模板引擎语法
ThinkPHP 模板引擎支持以下语法:
变量输出:
{$variable}条件判断:
{if condition="$status eq 1"}...{/if}循环遍历:
{foreach $list as $item}...{/foreach}包含文件:
{include file="common/header" /}原始输出:
{$content|raw}(不转义 HTML)
自定义标签
PuranCMS 提供了自定义标签库 Puran(app/taglib/Puran.php),可在模板中直接使用:
{puran:list name="模型标识" limit="10" category_id="分类ID" order="id desc"}{$item.title}{$item.description}{/puran:list}
{puran:detail name="模型标识" id="$id"}{$item.title}{$item.content|raw}{/puran:detail}
{puran:model key="模型标识"}{$modelInfo.name}{/puran:model}可用标签包括:list(列表)、detail(详情)、model(模型信息)、ad / ads(广告位)、nav(导航)、breadcrumb(面包屑)、hotlist(热门列表)、sidebar(侧边栏)、pagination(分页)。
命名空间规范
PSR-4 自动加载规范
项目遵循 PSR-4 自动加载规范,命名空间与目录结构严格对应(见 composer.json 的 autoload 配置):
命名空间映射
| 命名空间 | 对应目录 | 说明 |
|---|---|---|
| app\ | app/ | 应用根命名空间 |
| app\controller\admin\ | app/controller/admin/ | 后台控制器 |
| app\controller\index\ | app/controller/index/ | 前台控制器 |
| app\controller\api\ | app/controller/api/ | API 接口控制器 |
| app\model\ | app/model/ | 数据模型 |
| app\service\ | app/service/ | 服务层 |
| app\middleware\ | app/middleware/ | 中间件 |
| app\common\ | app/common/ | 公共类库 |
| app\taglib\ | app/taglib/ | 自定义标签库 |
| app\command\ | app/command/ | 命令行指令 |
| addons\ | addons/ | 插件(PSR-4) |
| (psr-0 根命名空间) | extend/ | 扩展类库(如 extend\security) |
命名空间声明示例
<?php
namespace app\controller\admin;
use app\controller\BaseController;
class Content extends BaseController
{
}注意事项
所有 PHP 文件必须以
<?php开头命名空间声明必须在文件顶部(
<?php之后第一行)使用
use语句引入外部类,避免使用完整命名空间类名必须与文件名一致(大小写敏感)
文件命名规范
PHP 文件命名
控制器:大驼峰命名(PascalCase),如
Content.php、Dashboard.php模型:大驼峰命名,如
Article.php、Product.php服务:大驼峰命名 + Service 后缀,如
ContentService.php、TokenService.php中间件:大驼峰命名,如
AdminAuth.php、SecurityGuard.php命令行指令:大驼峰命名,如
FileIntegrityScan.php
视图文件命名
前台模板:小写字母 + 下划线,如
article_list.html、page_detail_doc.html公共模板放在
common/目录下,如header.html、footer.html后台页面组件(Vue):PascalCase,如
DefaultLayout.vue
静态资源命名
CSS 文件:小写字母 + 连字符,如
main.cssJavaScript 文件:小写字母 + 连字符,如
main.js、jquery.min.js后台构建产物由 Vite 自动命名(含 hash),无需手工管理
数据库命名
表名:小写字母 + 下划线,前缀
pr_,如pr_article插件表:前缀
pr_addon_插件标识_,如pr_addon_anticode字段名:小写字母 + 下划线,如
create_time、status
代码开发规范
PHP 编码规范
遵循 PSR-12 编码规范
使用 4 个空格缩进
类名使用大驼峰命名(PascalCase)
方法名使用小驼峰命名(camelCase)
属性名使用小驼峰命名
常量使用全大写字母 + 下划线
控制器规范
控制器只负责接收请求、调用服务、返回响应
业务逻辑必须放在 Service 层
后台控制器继承
app\controller\BaseController,前台页面控制器继承BaseIndexController使用
$this->success()和$this->error()返回统一格式
模型规范
所有模型继承
BaseModel开启自动时间戳:
protected $autoWriteTimestamp = true;定义表名:
protected $name = 'table_name';定义关联关系方法
前端规范
后台(Vue 3 + TypeScript):组件使用
<script setup lang="ts">,状态用 Pinia 管理,接口统一封装在src/api/,HTTP 请求使用 axios前台(Layui + jQuery):使用 IIFE 模式封装避免全局污染,通过
layui.use()加载模块,AJAX 请求统一使用 JSON 格式前后端接口统一返回
{code, msg, data}JSON 格式
数据库配置说明
数据库连接配置
数据库配置在 config/database.php 与根目录 .env 文件中(.env 优先):
DB_DRIVER = mysql DB_TYPE = mysql DB_HOST = 127.0.0.1 DB_NAME = purancms DB_USER = root DB_PASS = your_password DB_PORT = 3306 DB_CHARSET = utf8mb4 DB_PREFIX = pr_
数据库表前缀
所有数据表使用 pr_ 前缀,方便多系统部署(共 77 张表):
pr_admin/pr_admin_menu- 管理员与菜单表pr_article/pr_product/pr_page/pr_image/pr_download- 内容模型表pr_nav- 导航表pr_message- 留言表pr_advertisement- 广告表pr_system_config- 系统配置表pr_model/pr_model_field- 自定义内容模型pr_form/pr_form_field/pr_form_data- 动态表单pr_doc_category/pr_doc_content- 文档中心pr_cart等商城相关表 - 购物车与订单pr_addon_*- 插件数据表(如pr_addon_anticode、pr_addon_appointment)pr_auth_group/pr_auth_rule- RBAC 权限
字符集
使用 utf8mb4 字符集,支持 Emoji 和特殊字符。
二次开发指南
开发环境搭建
安装 PHP 8.0+ 和 Composer
克隆项目并安装依赖:
composer install配置
.env文件(复制.env.example)导入数据库:
mysql -u root -p db_name < database/install.sql启动开发服务器:
php think run后台前端开发(可选):
cd view/admin && npm install && npm run dev(Vite 开发服务器),构建用npm run build
添加新功能模块
在
app/controller/admin/创建后台控制器(继承BaseController,提供 API)在
app/model/创建模型(继承BaseModel),如需业务逻辑在app/service/创建服务类在
view/admin/src/views/创建后台页面组件(Vue 3),并在src/api/封装接口调用在
route/app.php添加路由在后台菜单管理中添加菜单项
添加新内容模型
创建数据库表(
pr_前缀)在
app/model/创建模型类,继承BaseModel在后台"模型管理"中注册模型与字段
在导航管理中绑定模型
交互逻辑脑图
用户请求 │ ├─ 前台请求(SSR) │ ├─ app/controller/index 控制器 │ │ ├─ 获取导航 / 内容列表(Service + Model) │ │ └─ 渲染 template/ 模板 │ └─ app/controller/api 接口(会员、访问统计、多语言等) │ └─ 后台请求(Vue SPA) ├─ AdminAuth 中间件 │ └─ JWT 验证登录状态(TokenService) ├─ app/controller/admin 控制器 │ ├─ 接收参数 │ ├─ 调用 Service │ └─ 返回 JSON └─ Service ├─ 业务逻辑处理 ├─ 调用 Model └─ 返回结果
v1.0.0 安全中心模块与项目基础架构
发布信息
| 发布日期 | 2026-05-01 |
|---|---|
| 更新类型 | 重大更新 |
一、项目立项背景
1.1 项目定位
PuranCMS 是一款基于 ThinkPHP 8.0+ 框架开发的企业级内容管理系统(CMS),旨在为企业提供一个功能完善、易于扩展、安全可靠的内容管理解决方案。
核心目标:
| 目标维度 | 具体描述 |
|---|---|
| 企业官网 | 支持企业官网、产品展示、新闻发布、门店展示等常见场景 |
| 内容管理 | 完善的内容管理体系:产品/新闻/单页/门店/招聘/案例/下载/留言等 |
| 安全可靠 | 内置多层安全防护机制,有效防御 SQL 注入、XSS、CSRF 等常见攻击 |
| 易于扩展 | 插件化架构,支持功能模块的独立开发与热插拔 |
| SEO 友好 | 支持静态化生成、伪静态 URL、Sitemap 自动生成等 SEO 优化 |
| 会员体系 | 完整的会员注册/登录/等级/积分/权益体系 |
1.2 技术栈选型
| 层级 | 技术 | 版本 | 说明 |
|---|---|---|---|
| 后端框架 | ThinkPHP | 8.1.4 | PHP MVC 框架 |
| PHP 版本 | PHP | >= 8.0 | 服务端脚本语言 |
| 数据库 | MySQL | >= 5.7 | 关系型数据库 |
| 后台前端 | Layui | 2.13.5 | 后台 UI 框架 |
| 数据可视化 | ECharts | 5.x | 图表库(仪表盘/地图) |
| 模板引擎 | ThinkPHP 原生 | - | 标签定界符 {} |
| IP 解析 | zoujingli/ip2region | ^3.0 | IP 地理位置解析 |
| 邮件发送 | PHPMailer | ^7.0 | 邮件发送库 |
| 包管理 | Composer | 2.x | PHP 包管理器 |
1.3 系统架构设计
┌─────────────────────────────────────────────────────┐ │ 表现层 (Presentation) │ │ ┌──────────────────┐ ┌──────────────────┐ │ │ │ 后台管理视图 │ │ 前台展示模板 │ │ │ │ (Layui + TP模板) │ │ (default/enterprise) │ │ └──────────────────┘ └──────────────────┘ │ ├─────────────────────────────────────────────────────┤ │ 控制层 (Controller) │ │ admin/ | index/ | api/ | common/ │ ├─────────────────────────────────────────────────────┤ │ 中间件层 (Middleware) │ │ AdminCheck │ AuthCheck │ SecurityGuard │ ├─────────────────────────────────────────────────────┤ │ 业务层 (Service) │ │ ContentService │ SecurityService │ MemberService ... │ ├─────────────────────────────────────────────────────┤ │ 模型层 (Model) │ │ Product │ News │ Page │ User │ Admin │ Model ... │ ├─────────────────────────────────────────────────────┤ │ 数据存储层 (Database) │ │ MySQL 5.7+ (utf8mb4) │ └─────────────────────────────────────────────────────┘
1.4 项目目录结构
web.puran.cc/ ├── app/ │ ├── admin/controller/ # 后台控制器 │ ├── index/controller/ # 前台控制器 │ ├── api/controller/ # API 控制器 │ ├── model/ # 数据模型 │ ├── service/ # 业务服务层 │ ├── middleware/ # 中间件 │ ├── taglib/ # 自定义标签库 │ └── common/ # 公共模块 ├── template/ │ └── default/ # 默认前台主题 │ ├── index/ # 首页/列表页 │ ├── user/ # 会员中心 │ └── common/ # 公共组件(header/footer) ├── public/static/ # 静态资源 ├── config/ # 配置文件 ├── database/ # 数据库脚本 ├── route/ # 路由配置 └── extend/ # 扩展类库
二、基础开发历程(v0.1.0 ~ v0.9.0)
2.1 v0.1.0 — 项目初始化(2026-04-01)
引入 ThinkPHP 8.1.4 框架,完成 Composer 依赖配置
配置单应用模式(
auto_multi_app = false)建立项目基础目录结构
初始化路由分组配置
创建入口文件
public/index.php
2.2 v0.5.0 — 项目骨架搭建(2026-04-10)
后台基类控制器
AdminBase.php—— 权限校验、通用方法封装前台基类控制器
Index.php—— 前台公共逻辑路由配置
app/route.php—— 前后台路由分组基础模型层骨架(Admin、SystemConfig、Nav 等)
基础服务层骨架(AdminService、ContentService、AddonService)
Layui 2.13.5 前端框架集成
后台布局模板
layout/main.html登录页面
login/index.html数据库安装脚本
database/install.sql初版
2.3 v0.7.0 — RBAC 权限认证系统(2026-04-15)
权限三表模型:
| 表名 | 说明 |
|---|---|
| pr_auth_rule | 权限规则表(路由规则 + 菜单规则) |
| pr_auth_group | 用户组/角色表 |
| pr_auth_group_access | 用户与角色关联表 |
安装向导(4 步骤):
| 步骤 | 页面 | 功能 |
|---|---|---|
| Step 1 | 许可协议 | 显示许可协议,用户同意后继续 |
| Step 2 | 环境检测 | PHP 版本、扩展、目录权限检查 |
| Step 3 | 数据库配置 | 数据库连接测试 + 管理员创建 |
| Step 4 | 安装完成 | 写入安装锁,跳转后台 |
2.4 v0.8.0 — 内容管理核心(2026-04-20)
8 大内容类型:
| 模型 | 控制器 | 说明 |
|---|---|---|
| 产品管理 | Content.php (product) | 产品分类 + 产品列表/详情 |
| 新闻管理 | Content.php (news) | 新闻分类 + 新闻列表/详情 |
| 单页管理 | Content.php (page) | 关于我们、联系我们等 |
| 门店管理 | BranchManage.php | 门店列表/详情 |
| 招聘管理 | Content.php (recruitment) | 职位列表/详情 |
| 案例展示 | Content.php (showcase) | 案例列表/详情 |
| 下载中心 | Content.php (download) | 文件下载管理 |
| 留言管理 | Message.php | 留言板功能 |
前台控制器:
Index.php—— 首页渲染Doc.php—— 文档详情Dynamic.php—— 动态内容页BranchPage.php—— 门店页面Member.php—— 会员中心
2.5 v0.9.0 — 站点配置与仪表盘增强(2026-04-25)
站点配置:后台 Logo / 前台 Logo(固定+滑动)/ 公安备案号 / 联系信息
仪表盘增强:ECharts 中国地图访客分布 / 访问流量统计图表 / 流量来源分析
新增服务:
DashboardService.php新增数据表:
pr_visitor_log/pr_operation_log
三、v1.0.0 核心新增:安全中心模块
3.1 安全评分仪表盘
ECharts 仪表盘组件展示 0-100 分的安全评分,基于 8 项检测加权计算。
3.2 8 项安全检测
| 检测项 | 说明 | 权重 |
|---|---|---|
| ThinkPHP 版本 | 框架是否为最新版本 | 10% |
| PHP 版本 | 是否 >= 8.0 | 15% |
| 调试模式 | 是否已关闭调试模式 | 15% |
| 默认密码 | 是否存在默认密码账号 | 20% |
| 数据库安全 | 数据库配置安全性 | 10% |
| 上传类型 | 允许上传的文件类型限制 | 10% |
| Session 安全 | Session 配置安全性 | 10% |
| 目录权限 | 关键目录权限检查 | 10% |
3.3 风险等级划分
| 评分范围 | 风险等级 | 颜色 |
|---|---|---|
| 90-100 | 安全 | 绿色 |
| 70-89 | 低风险 | 蓝色 |
| 50-69 | 中风险 | 橙色 |
| 0-49 | 高风险 | 红色 |
3.4 安全策略配置(5 大类)
| 类别 | 配置项示例 |
|---|---|
| 登录安全 | 失败锁定开关 / 最大失败次数(5) / 锁定时间(30分钟) |
| 验证码 | 图形 / 滑块 / 点选 |
| 接口安全 | CSRF防护 / XSS过滤 / SQL注入防护 / 请求限流(100次/分) |
| 后台安全 | 路径伪装 / HTTPS强制 |
| 数据安全 | 自动备份 / 备份周期(日/周/月) |
3.5 IP 黑名单管理
支持精确 IP / CIDR 格式封禁,含封禁原因 + 过期时间(永久可选)
3.6 安全防御中间件 SecurityGuard(7 层防护链)
请求 → IP黑名单拦截 → HTTPS强制 → 请求限流 → CSRF验证 → SQL注入检测 → XSS检测 → 安全响应头 → 控制器
3.7 新增数据表(3 张)
pr_security_config — 安全配置表
pr_ip_blacklist — IP 黑名单表
pr_login_log — 登录日志表(用户名/IP/归属地/状态/时间)
3.8 新增文件清单
后端文件:
app/admin/controller/Security.php— 安全中心控制器app/model/SecurityConfig.php— 安全配置模型app/model/IpBlacklist.php— IP 黑名单模型app/model/LoginLog.php— 登录日志模型app/service/SecurityService.php— 安全服务层app/middleware/SecurityGuard.php— 安全防御中间件
扩展类库:
extend/security/IpTool.php— IP 工具类extend/security/SqlInjectFilter.php— SQL 注入过滤器extend/security/XssClean.php— XSS 过滤器extend/security/PathValidator.php— 目录权限验证器extend/security/PasswordChecker.php— 密码强度检查器
前端文件:
app/admin/view/security/index.html— 安全中心主页面app/admin/view/security/policy.html— 安全策略配置弹窗app/admin/view/security/ip_blacklist.html— IP 黑名单弹窗app/admin/view/security/permission.html— 目录权限检查弹窗app/admin/view/security/login_log.html— 登录日志弹窗public/static/admin/css/security.css— 样式public/static/admin/js/security.js— 前端逻辑
v1.1.0 图片管理增强与 IP 地理位置集成
发布信息
| 发布日期 | 2026-05-02 |
|---|---|
| 更新类型 | 新增 / 优化 |
一、图片管理增强
上传弹窗:120×120 占位框 → 多图选择 → 80×80 缩略图网格预览 → 串行上传
图片列表:时间 Y-m-d H:i:s 格式化 / B/KB/MB/GB 大小格式化 / 复制链接按钮
分类操作:悬停显示编辑/删除图标按钮、"全部图片"节点
二、IP 地理位置(ip2region v3.0 集成)
// 全局函数
$location = ip2region('61.142.118.231');
// 输出:中国广东省中山市【电信】
// 类方式(返回数组:country/province/city/isp/ip/version)
$ip2region = new Ip2Region();
$info = $ip2region->getIpInfo('61.142.118.231');三、Bug 修复
finfo_file / SplFileInfo 报错:move() 前先获取文件信息
前端 renderImageItem 空引用 / deleteCategory $ 未定义 / 按钮布局修复
v1.2.0 页面命名空间重构与安装向导优化
发布信息
| 发布日期 | 2026-05-05 |
|---|---|
| 更新类型 | 优化 / 重构 |
一、8 个页面重构(命名空间隔离)
| 页面 | 命名空间 |
|---|---|
| 标签管理 | #pr-page-content-tag / PR.TagAdmin |
| AI 索引管理 | #pr-page-system-aiindex / PR.AIIndexAdmin |
| 角色管理 | #pr-page-auth-role / PR.RoleAdmin |
| 权限规则 | #pr-page-auth-rule / PR.RuleAdmin |
| 渠道管理 | #pr-page-content-channel / PR.ChannelAdmin |
| 自定义链接 | #pr-page-content-link / PR.LinkAdmin |
| 表单管理 | #pr-page-content-form / PR.FormAdmin |
| 用户管理 | #pr-page-system-user / PR.UserAdmin |
规范:IIFE 包裹 + 命名空间对象 + 事件委托 + XSS 防护(escapeHtml)
二、安装向导重构
| 步骤 | 修改前 | 修改后 |
|---|---|---|
| 步骤1 | 环境检测 | 许可协议 |
| 步骤2 | 数据库配置 | 环境检测 |
| 步骤3 | 管理员创建 | 数据库与管理员(合并) |
| 步骤4 | 安装完成 | 安装进度与完成 |
修复步骤间导航 404 Bug(路由 POST→GET 修正)
v1.3.0 标签库加载修复与登录验证码校验失败修复
发布信息
| 发布日期 | 2026-05-08 |
|---|---|
| 更新类型 | Bug 修复 |
一、标签库加载问题修复
问题:PuranTag 无法正常加载,{puran:xxx} 标签无法解析
根因:PuranTag 缺少 $tagLib = 'puran' 属性
修复:添加属性 → TagLibService 注册 → ViewInitMiddleware 触发
二、登录验证码校验失败修复
2.1 滑块验证
onEnd 中 setTimeout 1秒自动重置导致 token 失效 → 移除自动重置
2.2 点选验证
clickCount≥4 时 500ms 自动刷新 → 移除自动刷新
2.3 坐标不一致
前端显示坐标 vs 后端原始坐标(310×155) → 新增 scaleClickCoords() 换算函数
v1.4.0 导航样式修复与文档完善
发布信息
| 发布日期 | 2026-05-12 |
|---|---|
| 更新类型 | 修复 / 文档 |
更新概述
本版本主要修复顶部导航样式问题,并输出完整开发历程文档。
一、顶部导航样式修复
| 修复项 | 修改前 | 修改后 |
|---|---|---|
| 文字加粗 | font-weight: 500/600/700 | normal |
| 文字颜色 | #333 | #000 |
| 文字阴影 | text-shadow 存在 | 移除 |
涉及文件:style.css / simple_header.css / page_detail.css
二、完整开发历程文档
docs/PuranCMS_完整开发历程文档.md — 含项目立项/技术栈/架构设计/数据库设计/开发阶段记录/功能模块/前后台模板/更新迭代日志/未来规划
v1.5.0 ~ v1.5.1 会员等级功能增强与协议修复
一、v1.5.0 会员等级功能增强
发布信息
| 发布日期 | 2026-05-12 |
|---|---|
| 更新类型 | 功能新增 / 增强 |
1.1 新增功能概览
会员积分系统 — user 表新增 points、total_amount 字段
等级升级条件 — min_points / max_points / min_amount 双重条件判断
会员权益管理 — benefits 字段(JSON 数组),后台动态添加/删除权益项
等级图标与颜色 — icon(layui 图标类名)+ color(如 #FFD700)
自动升级机制 — UserLevelService:checkAndUpgrade / calculateLevel / addPoints / addAmount
1.2 数据库变更
pr_user_level 表新增字段:
| 字段 | 类型 | 说明 |
|---|---|---|
| min_points | int(11) | 最低积分门槛 |
| max_points | int(11) | 最高积分限制(0=不限) |
| min_amount | decimal(10,2) | 最低消费金额门槛 |
| icon | varchar(255) | 等级图标(layui-icon-diamond 等) |
| color | varchar(20) | 等级颜色 |
| benefits | text | 会员权益(JSON数组) |
pr_user 表新增字段:points(积分)、total_amount(累计消费金额)
二、v1.5.1 前台用户协议验证修复
发布信息
| 发布日期 | 2026-05-13 |
|---|---|
| 更新类型 | Bug 修复 |
2.1 问题
前台登录/注册/找回密码页面,未勾选同意协议可绕过验证成功提交。根因:user.js 的 submit handler 与页面内联 handler 冲突,user.js 先执行且无协议检查。
2.2 修复方案
在 user.js 统一添加协议勾选验证(login/register/forgot 三个表单)
移除各 HTML 页面中的重复 submit handler
将"记住我"自动填充逻辑迁移至 user.js
2.3 修改文件
public/static/index/js/user.js— 统一协议验证 + 找回密码 handler + 记住我逻辑template/default/user/login.html— 移除重复 handlertemplate/default/user/register.html— 移除重复 handlertemplate/default/user/forgot_password.html— 移除重复 handler
v1.6.0 会员体系完善与管理增强
发布信息
| 发布日期 | 2026-05-14 ~ 2026-05-18 |
|---|---|
| 更新类型 | 功能新增 |
更新概述
在 v1.5.0/v1.5.1 会员等级基础上,进一步完善会员系统的配套功能:会员设置面板、积分规则配置、标签管理、UEditor 集成、前台会员中心全套页面(16 个页面)。
一、会员设置管理面板
1.1 配置项(group: member)
| 配置项 | 默认值 | 说明 |
|---|---|---|
| member_enable | 1 | 全局启用/关闭会员功能 |
| member_register_enable | 1 | 是否允许新用户注册 |
| member_login_enable | 1 | 是否允许登录 |
| member_close_reason | 会员功能暂未开放 | 关闭时提示文案 |
| auth_page_bg | (空) | 登录/注册背景图 URL |
配套服务:MemberService::getConfig() / isEnabled() / isRegisterEnabled()(带缓存 TTL=3600s)
二、积分规则配置
2.1 规则项(group: points_rule)
| 配置项 | 默认值 | 说明 |
|---|---|---|
| points_register_points | 100 | 注册奖励积分 |
| points_login_points | 5 | 每日首次登录奖励 |
| points_message_points | 10 | 发表留言奖励 |
| points_profile_points | 50 | 完善资料奖励 |
| points_sign_points | 10 | 每日签到奖励 |
| points_invite_points | 200 | 邀请好友奖励 |
| points_consume_rate | 1 | 积分消耗比率 |
配套服务:PointsService::addPoints($userId, $points, $type, $desc)(带日志+缓存)
三、其他新增模块
3.1 标签管理系统
控制器:
TagManage.php| 服务:TagService.php| 模型:Tag.php+TagRelation.php支持 CRUD + 多对多关联 + 删除保护(有内容不可删)+ SEO 字段
3.2 UEditor 富文本编辑器集成
控制器:
Ueditor.php| 支持 7 种 action(config/uploadimage/uploadvideo/uploadfile/listimage/catchimage 等)安全特性:文件类型白名单、大小限制、远程抓取域名白名单、XSS 过滤
3.3 自定义链接管理
控制器:
CustomLinkManage.php| 模型:CustomLink.php三种类型:导航链接 / 友情链接 / 底部链接
四、前台会员中心(16 个页面)
| 页面 | 路径 | 功能 |
|---|---|---|
| login | user/login.html | 会员登录 |
| register | user/register.html | 会员注册 |
| center | user/center.html | 会员中心首页 |
| profile | user/profile.html | 个人资料编辑 |
| password | user/password.html | 修改密码 |
| level | user/level.html | 会员等级展示 |
| points_rule | user/points_rule.html | 积分规则说明 |
| messages | user/messages.html | 站内消息 |
| notifications | user/notifications.html | 系统通知列表 |
| appointment_list | user/appointment_list.html | 预约记录 |
| appointment_detail | user/appointment_detail.html | 预约详情 |
| pay_order | user/pay_order.html | 支付订单 |
| appointment_booking | user/appointment_booking.html | 在线预约下单 |
| forgot_password | user/forgot_password.html | 找回密码 |
| member_closed | user/member_closed.html | 关闭提示 |
| error | user/error.html | 通用错误 |
五、新增数据表(3 张)
pr_custom_link — 自定义链接表(title/url/type/target/icon/status)
pr_tag — 标签表(name/slug/description/cover/SEO字段/article_count/product_count)
pr_tag_relation — 标签关联表(tag_id + target_type + target_id 唯一索引)
v1.7.0 文档管理与动态表单系统
发布信息
| 发布日期 | 2026-05-19 ~ 2026-05-22 |
|---|---|
| 更新类型 | 功能新增 |
更新概述
新增两大核心模块:文档管理系统(树形分类 + 富文本内容)和动态表单系统(12 种字段类型 + JSON 数据收集)。
一、文档管理系统
1.1 模块组成
| 组件 | 文件路径 |
|---|---|
| 分类控制器 | app/admin/controller/DocCategory.php |
| 内容控制器 | app/admin/controller/DocContent.php |
| 服务类 | app/service/DocManageService.php |
| 分类模型 | app/model/DocCategory.php |
| 内容模型 | app/model/DocContent.php |
| 前台模板 | template/default/index/page_detail_doc.html |
1.2 文档分类(DocCategory)字段
| 字段 | 类型 | 说明 |
|---|---|---|
| id / parent_id | int | 主键/父级(0=顶级) |
| name / slug | varchar | 名称/URL别名 |
| description | text | 分类描述 |
| icon / sort / status | - | 图标/排序/状态 |
1.3 文档内容(DocContent)字段
| 字段 | 类型 | 说明 |
|---|---|---|
| category_id | int | 所属分类 |
| title / slug | varchar | 标题/URL别名(唯一) |
| content | longtext | HTML富文本 |
| summary / cover | - | 摘要/封面图 |
| seo_title / seo_keywords / seo_description | varchar/text | SEO 信息 |
二、动态表单系统
2.1 模块组成
| 组件 | 文件路径 |
|---|---|
| 表单控制器 | app/admin/controller/FormManage.php |
| 字段控制器 | app/admin/controller/FormField.php |
| 数据控制器 | app/admin/controller/FormData.php |
| Form / FormField / FormData 模型 | app/model/ 下三个模型 |
2.2 支持的字段类型(12 种)
| type | 说明 |
|---|---|
| text / textarea | 单行/多行文本 |
| number / email / phone | 数字/邮箱/手机号 |
| select / radio / checkbox | 下拉/单选/多选 |
| file / date / datetime | 文件上传/日期/日期时间 |
| image / rich_text | 图片上传/富文本 |
2.3 表单数据存储
所有提交数据以 JSON 格式存储在 FormData.data 字段中,便于灵活扩展。
三、新增数据表(5 张)
pr_doc_category — 文档分类表(树形结构)
pr_doc_content — 文档内容表(富文本)
pr_form — 自定义表单表
pr_form_field — 表单字段定义表
pr_form_data — 表单提交数据表(JSON)
v1.8.0 自定义内容模型、插件系统与主题管理
发布信息
| 发布日期 | 2026-05-20 |
|---|---|
| 更新类型 | 重大功能 |
一、自定义内容模型系统
1.1 功能概述
允许管理员在后台动态创建新的内容类型(如"课程"、"案例"、"FAQ"等),无需修改代码即可扩展平台的内容承载能力。每个模型自动生成对应的数据表。
1.2 核心能力
14 种字段类型:文本/多行文本/富文本/数字/日期时间/单选/多选/下拉框/图片上传/文件上传/开关/评分/关联模型/JSON
保留关键字保护:内置 17 个保留 key 防止与系统表冲突
自动建表:创建模型时根据字段定义自动生成数据库表结构
前台渲染支持:通过
{custom:content}标签在前台展示
二、插件系统(Addon System)
2.1 设计理念
插件系统采用"热插拔"架构设计,开发者可通过标准化的目录结构和接口规范开发独立的功能模块,实现功能的模块化封装与灵活组合。
2.2 插件目录结构
addons/ ├── anticode/ # 示例:防伪码查询插件 │ ├── config.php # 插件配置文件(元数据+钩子+标签) │ ├── Plugin.php # 插件主类(继承 BasePlugin) │ ├── Install.php # 安装脚本 │ ├── Uninstall.php # 卸载脚本 │ ├── route.php # 插件路由规则 │ ├── controller/ # 控制器层 │ │ ├── Admin.php # 后台控制器 │ │ └── Index.php # 前台控制器 │ ├── model/ # 数据模型 │ │ └── Anticode.php │ ├── service/ # 业务服务 │ │ └── Service.php │ ├── view/ # 视图模板 │ │ ├── admin/ # 后台视图 │ │ │ ├── index.html # 列表页 │ │ │ ├── edit.html # 编辑页 │ │ │ ├── settings.html # 设置页 │ │ │ └── nav.html # 导航配置 │ │ ├── index/ # 前台视图 │ │ │ ├── index.html # 列表页 │ │ │ ├── detail.html # 详情页 │ │ │ └── widget.html # 组件模板(可嵌入任意页面) │ │ └── assets/ # 静态资源 │ │ ├── css/admin.css │ │ └── js/admin.js │ ├── logs/ # 运行日志目录 │ └── README.md # 说明文档 ├── appointment/ # 示例:在线预约插件 ├── multilang/ # 示例:多语言切换插件 ├── timeline/ # 示例:时间线展示插件 └── .gitignore
2.3 BasePlugin 抽象基类
所有插件必须继承 app\common\BasePlugin,提供以下核心能力:
| 属性/方法 | 类型 | 说明 |
|---|---|---|
| $name | string | 插件唯一标识(小写字母开头) |
| $title | string | 插件显示名称 |
| $version | string | 版本号(语义化) |
| $description | string | 插件描述 |
| $author | string | 作者 |
| $hooks | array | 注册的钩子列表 |
| $tags | array | 注册的标签列表 |
| install() | abstract | 安装逻辑(必须实现) |
| uninstall() | abstract | 卸载逻辑(必须实现) |
| renderWidget() | public | 组件渲染方法 |
| tagList() / tagDetail() | public | 标签解析方法 |
| createTable() / dropTable() | protected | 建表/删表工具方法 |
| log() | protected | 日志记录(写入 addons/{name}/logs/) |
| loadConfig() / saveConfig() | public | 配置读写(config.php 文件) |
| registerHooks() | public | 向 HookService 注册钩子 |
2.4 config.php 配置文件结构
'my_addon', 'title' => '我的插件', 'description' => '插件功能说明', 'version' => '1.0.0', 'author' => 'AuthorName', 'icon' => 'layui-icon-app', 'status' => 0, // 0=未安装, 1=已安装启用, -1=已停用 // ===== 钩子系统 ===== 'hooks' => [ 'my_addon_widget' => [ 'method' => 'renderWidget', // Plugin 类中的方法名 'description' => '组件(可嵌入任意页面)', ], ], // ===== 标签系统 ===== 'tags' => [ 'list' => ['description' => '列表标签', 'params' => ['limit'=>'显示数量']], 'detail' => ['description' => '详情标签', 'params' => ['id'=>'内容ID']], ], // ===== 业务配置项 ===== 'config' => [ 'pagesize' => 10, 'show_status' => 1, 'nav_menu_show' => ['type'=>'switch', 'title'=>'前台导航显示', 'value'=>1], ], // ===== 导航菜单集成 ===== 'nav_menu' => [ 'enable' => true, 'position' => 'top', 'menus' => [['title'=>'我的插件', 'url'=>'/addons/my_addon/index', ...]], ], ];
2.5 插件生命周期管理
5 大操作流程:
| 操作 | 触发条件 | 执行步骤 |
|---|---|---|
| 创建 | 后台"新建插件"表单提交 | 名称校验 → AddonTemplate::generate() 自动生成完整骨架(22 个文件) |
| 安装 | 点击"安装"按钮 | 读取 config.php → 写入 pr_addon 表 → 执行 Install::install() → 注册钩子/标签 → 清除缓存 |
| 卸载 | 点击"卸载"按钮 | 执行 Uninstall::uninstall() → 删除 pr_addon 记录 → 清理插件目录 → 清除缓存 |
| 启用/停用 | 点击开关按钮 | 切换 status 字段 → 更新 config.php → 启用时重注册钩子/标签 → 清除缓存 |
| 配置 | 点击"设置"按钮 | 读取 config.php 中的 config 段 → 渲染配置表单 → 保存到 pr_addon.config 字段 + config.php |
2.6 钩子机制(HookService)
钩子系统是插件与系统交互的核心桥梁,采用观察者模式实现事件驱动:
请求到达 → 触发钩子 → HookService::trigger('hook_name')
↓
遍历所有已注册的回调函数 → 按优先级排序 → 依次执行
↓
收集所有返回值 → 返回给调用方
// 系统触发示例(在需要的位置)
HookService::trigger('frontend_header_js'); // 输出前端头部JS
HookService::trigger('frontend_footer_js'); // 输出前端底部JS
// 插件注册示例(在 Plugin.php 中)
$this->hooks = [
'frontend_header_js' => ['method' => 'injectHeaderScript'],
];HookService API:
| 方法 | 说明 |
|---|---|
HookService::register($name, $callback, $priority) | 注册钩子回调(支持优先级排序) |
HookService::trigger($name, $params) | 触发钩子,返回所有回调结果数组 |
HookService::triggerFirst($name, $params) | 触发钩子,仅返回第一个结果 |
HookService::hasHook($name) | 检查是否有注册的钩子 |
HookService::getHooks($name) | 获取指定钩子的所有回调 |
HookService::clearCache() | 清除钩子缓存 |
2.7 内置插件一览
| 插件标识 | 名称 | 功能说明 | 主要特性 |
|---|---|---|---|
| anticode | 防伪码查询 | 产品防伪码生成与验证 | 批量生成/导入导出/二维码/查询统计/操作日志 |
| appointment | 在线预约 | 服务预约与订单管理 | 分类/时段/字段自定义/用户端预约/订单管理 |
| multilang | 多语言切换 | 前台多语言支持 | 中英双语/术语映射/前端语言包加载 |
| timeline | 时间线展示 | 发展历程/大事记展示 | 树形分类/富文本详情/前台组件嵌入 |
2.8 插件路由与静态资源
路由:每个插件可定义独立的
route.php,通过/addons/{name}/{action}访问静态资源:后台提供
Addons::asset()方法安全输出 CSS/JS/图片等静态文件,含 MIME 类型检测和目录穿越防护图标上传:后台支持为每个插件上传专属图标(jpg/png/gif)
2.9 新增数据表
pr_addon — 插件主表(name/title/version/status/config/hooks/tags/install_time)
2.10 插件相关新增文件清单
核心框架:
app/common/BasePlugin.php— 插件抽象基类app/common/AddonTemplate.php— 插件代码生成器(22 个文件模板)app/service/HookService.php— 钩子服务(事件驱动引擎)app/service/AddonService.php— 插件生命周期管理服务app/model/Addon.php— 插件数据模型
后台管理:
app/admin/controller/Addons.php— 插件管理控制器(11 个方法:index/list/install/uninstall/toggle/create/config/saveConfig/manage/checkName/uploadIcon/asset)app/admin/view/addons/index.html— 插件列表页app/admin/view/addons/create.html— 创建插件向导app/admin/view/addons/config.html— 插件配置弹窗
内置插件(4 个):
addons/anticode/— 防伪码查询插件(完整 MVC + 服务层 + 日志)addons/appointment/— 在线预约插件(分类/时段/订单/字段自定义)addons/multilang/— 多语言切换插件(中英双语 + 术语映射)addons/timeline/— 时间线展示插件(树形分类 + 组件嵌入)
三、主题管理系统
3.1 功能概述
主题管理系统允许管理员在后台自由切换、预览、配置不同的前台视觉主题,支持多套主题并存,一键切换生效。
3.2 已有主题
| 主题名称 | 目录 | 特点 | 截图 |
|---|---|---|---|
| Default(默认主题) | template/default/ | 企业官网风格,功能最全,包含全部页面模板 | 4 张(首页/列表/详情/总览) |
| Enterprise(企业版) | template/enterprise/ | 精简商务风格,适合正式企业形象展示 | 无(使用默认占位图) |
3.3 theme.json 元数据格式
每个主题根目录下的 theme.json 定义主题基本信息:
{
"name": "default",
"title": "默认主题",
"version": "1.0.0",
"author": "PuranCMS",
"description": "PuranCMS 默认前台主题,适用于企业官网场景",
"screenshots": ["screenshot.png", "screenshot-home.png", "screenshot-list.png", "screenshot-detail.png"],
"config": {
"primary_color": {"type": "color", "title": "主色调", "value": "#1890ff"},
"header_style": {"type": "select", "title": "头部样式", "value": "fixed", "options": ["fixed", "static"]}
},
"required_files": []
}3.4 主题管理功能(ThemeService)
| 功能 | 方法 | 说明 |
|---|---|---|
| 获取所有主题 | getAllThemes() | 扫描 template/ 目录下所有子目录,读取 theme.json 元数据 |
| 获取当前主题 | getCurrentTheme() | 从 system_config 表读取 current_theme 配置项(缓存 1 小时) |
| 切换主题 | switchTheme($name) | 校验完整性 → 写入 system_config → 清除缓存 |
| 主题验证 | validateTheme($name) | 检查必需目录(common/index)和文件(header/footer/layout/index)是否存在 |
| 主题配置 | getThemeConfig() / saveThemeConfig() | 按 theme_{name} 分组读写配置到 system_config 表 |
| 主题预览 | preview($name) | 渲染预览页面(不实际切换) |
| 主题统计 | getThemeStats() | 返回总数/当前主题/有效主题数 |
| 静态资源路径 | getThemeStaticUrl($name) | 返回 /static/theme/{name}/ 路径 |
3.5 后台管理界面(Theme 控制器)
提供 8 个管理方法:
| 方法 | 功能 |
|---|---|
| index() | 主题列表主页 |
| getList() | AJAX 获取主题列表(含 is_current 标识) |
| getDetail() | 获取单个主题详细信息 + 配置 |
| switch() | POST 切换主题 |
| config() / saveConfig() | GET 显示 / POST 保存主题配置 |
| preview() | 主题预览 |
| validate() | 验证主题文件完整性 |
| stats() | 主题统计概览 |
3.6 Default 主题模板清单
公共组件 (common/):
header.html— 公共头部(Logo/导航/搜索/会员入口)footer.html— 公共底部(版权/备案/友情链接)simple_footer.html— 简洁底部pagination.html— 分页组件layout.html— 布局母版
首页 (index/):
index.html— 首页product_list/detail.html— 产品列表/详情article_list/detail.html— 新闻文章列表/详情page_detail.html— 单页详情branch_list/detail.html— 门店列表/详情download_list/detail.html— 下载中心列表/详情recruitment_list/detail.html— 招聘列表/详情image_list/detail.html— 图集列表/详情message.html— 留言板page_detail_contact.html— 联系我们page_detail_doc.html— 开发文档page_detail_anticode.html— 防伪查询(插件页)page_detail_appointment.html— 在线预约(插件页)
会员中心 (user/):
center/login/register/forgot_password/profile/password/level/points_rule/messages/notifications/...— 完整会员体系页面
3.7 Enterprise 主题模板清单
common/layout.html— 企业版布局母版index/index/article_list/detail/product_list/detail/page_detail/contact— 精简版页面user/auth_layout/center/login/register/layout— 企业版会员页面
3.8 主题相关新增文件清单app/service/ThemeService.php — 主题管理服务(15 个方法)
app/admin/controller/Theme.php — 主题管理控制器(8 个方法)
app/admin/view/theme/index.html — 主题列表页
app/admin/view/theme/config.html — 主题配置页
app/admin/view/theme/preview.html — 主题预览页
template/default/theme.json — 默认主题元数据
template/enterprise/theme.json — 企业版主题元数据
template/default/screenshot*.png — 默认主题截图(4 张)
app/service/ThemeService.php — 主题管理服务(15 个方法)
app/admin/controller/Theme.php — 主题管理控制器(8 个方法)
app/admin/view/theme/index.html — 主题列表页
app/admin/view/theme/config.html — 主题配置页
app/admin/view/theme/preview.html — 主题预览页
template/default/theme.json — 默认主题元数据
template/enterprise/theme.json — 企业版主题元数据
template/default/screenshot*.png — 默认主题截图(4 张)
v1.9.0 SEO 管理、缓存管理与 HTML 静态化
发布信息
| 发布日期 | 2026-05-28 ~ 2026-06-02 |
|---|---|
| 更新类型 | 功能新增 |
更新概述
本版本聚焦于 SEO 优化能力、缓存管理 和 HTML 静态化生成 三大基础设施功能。
一、SEO 管理系统
1.1 SEO 配置项(system_config, group=seo)
| 配置项 | 默认值 | 说明 |
|---|---|---|
| seo_title_separator | | - PuranCMS | 标题分隔符及后缀 |
| seo_default_title | PuranCMS 企业内容管理系统 | 默认站点标题 |
| seo_default_keywords | PuranCMS,企业CMS,内容管理 | 默认关键词 |
| seo_default_description | PuranCMS 是一款基于 ThinkPHP... | 默认描述 |
| seo_url_suffix | .html | URL 后缀 |
| seo_lowercase_url | 1 | URL 小写化 |
| seo_structured_data | {} | 结构化数据 LD-JSON |
| seo_site_type | WebSite | 站点类型 |
1.2 Sitemap 自动生成
SitemapService::generateSitemap(); // 生成 Sitemap XML SitemapService::getSitemapUrl(); // 获取访问 URL SitemapService::addUrl($url, $lastmod, $changefreq, $priority); // 添加条目
自动收录:首页、栏目页、详情页、单页、文档页面
1.3 结构化数据(LD-JSON)
{"@context": "https://schema.org", "@type": "WebSite", "name": "PuranCMS", "url": "https://example.com"}二、缓存管理中心
2.1 可管理的缓存类型
| 类型 | 清理目标 | 存储路径 |
|---|---|---|
| template | 模板编译缓存 | runtime/temp/ |
| log | 日志文件 | runtime/log/ |
| html | 静态 HTML 缓存 | public/html/ 或 runtime/html/ |
| cache | 系统 Cache | (TP Cache 驱动) |
| all | 全部一键清理 | |
2.2 API 接口
POST /admin/cache_manage/clear?type=template|log|html|cache|all GET /admin/cache_manage/index → 各类型磁盘占用大小
三、HTML 静态化缓存
3.1 支持的生成类型
| type | 说明 |
|---|---|
| home | 生成首页 |
| nav | 生成栏目页(nav_id) |
| content | 生成内容详情页(content_type + content_id) |
| all | 全站生成 |
3.2 核心方法
HtmlCacheService::generateHome(); HtmlCacheService::generateNavPage($navId); HtmlCacheService::generateContentPage($type, $id); HtmlCacheService::generateAll(); HtmlCacheService::getStatistics(); // 统计:总文件数/总大小/各类型数量
3.3 静态文件存储规则
runtime/html/ ├── index.html # 首页 ├── article/ # 文章 ├── product/ # 产品 ├── page/ # 单页 └── doc/ # 文档
3.4 Nginx 配置建议
location ~ ^/(article|product|page)/ {
try_files /runtime/html/$uri/index.html /runtime/html/$uri.html /index.php?$query_string;
}四、新增文件清单
app/admin/controller/SeoManage.php— SEO 管理app/admin/controller/CacheManage.php— 缓存管理app/admin/controller/HtmlCache.php— 静态化管理app/service/SeoService.php— SEO 服务app/service/SitemapService.php— Sitemap 生成app/service/HtmlCacheService.php— 静态化核心服务对应视图、CSS、JS 文件
v2.0.0 平台级能力全面升级
发布信息
| 发布日期 | 2026-06-06 |
|---|---|
| 更新类型 | 重大版本升级(Major Release) |
更新概述
v2.0.0 是 PuranCMS 发展历程中最重要的里程碑版本。本版本标志着系统从"内容管理系统(CMS)"正式跨越为"综合性应用平台",引入了 RESTful API 接口体系、通知消息系统、图片管理完善化,并整合了此前 v1.6.0 ~ v1.9.0 的全部平台能力。
版本号语义 — 从 v1.x 跳升至 v2.0.0 的理由:
API 体系的引入 — 新增完整的 RESTful API 模块,支持外部系统集成
通知系统的建立 — 站内消息/系统通知的统一管理能力
架构层面的扩展 — 新增 api 独立模块、中间件体系扩展
功能数量翻倍 — 从约 15 个功能模块增长到 30+ 个功能模块
一、RESTful API 接口体系(核心新增)
1.1 目录结构
app/api/ ├── controller/ │ ├── BaseController.php # API 基础控制器 │ ├── v1/ # v1 版本接口 │ │ ├── Content.php # 内容接口 v1 │ │ └── User.php # 用户接口 v1 │ ├── v2/ # v2 版本接口 │ │ ├── Content.php # 内容接口 v2 │ │ └── User.php # 用户接口 v2 │ ├── BranchController.php # 门店 API │ ├── ContentController.php # 内容 API(通用) │ └── MemberController.php # 会员 API ├── middleware/ │ ├── ApiAuth.php # API 身份认证中间件 │ └── ApiRateLimit.php # API 频率限制中间件 └── route/ └── app.php # API 路由配置
1.2 基础控制器(BaseController)
| 能力 | 说明 |
|---|---|
| Token 认证 | 基于 Cache 的 Token 机制 |
| Token 有效期 | 默认 7 天(604800 秒) |
| Token 生成算法 | MD5(uniqid() . $userId . time()) |
| 统一响应格式 | { code: 0/1, msg: '', data: {} } |
1.3 API 中间件
ApiAuth — 身份认证中间件:从 Header "Authorization" 或参数 "token" 获取 Token → Cache 验证 → 注入 userId / 返回 401
ApiRateLimit — 频率限制中间件:以 IP 为 key 计数 → 默认 60次/60秒/IP → 超限返回 429
1.4 版本策略
| 版本 | 路径前缀 | 特点 |
|---|---|---|
| v1 | /api/v1/ | 基础版,核心字段 |
| v2 | /api/v2/ | 扩展版,含更多字段和关联数据 |
1.5 已实现接口清单
内容接口:GET list/detail/search(v1 + v2)
用户接口:POST register/login, GET info/points, PUT profile(v1 + v2)
门店接口:GET list/detail/nearby
会员接口:GET level/points/log/notification/list, PUT notification/read
1.6 认证流程
注册:POST /api/v2/user/register { nickname, email, password }
登录:POST /api/v2/user/login { email, password } → 返回 token + user
认证:GET /api/v2/user/info Header: Authorization: Bearer xxx二、通知消息系统
2.1 通知类型
| 类型常量 | 说明 |
|---|---|
| system | 系统通知 |
| order | 订单通知 |
| activity | 活动通知 |
| message | 留言回复 |
2.2 核心方法
NotificationService::send($userId, $type, $title, $content, $extra); // 单人发送 NotificationService::sendBatch($userIds, $type, $title, $content); // 批量发送 NotificationService::broadcast($type, $title, $content); // 全员广播 NotificationService::markAsRead($notificationId, $userId); // 标记已读 NotificationService::markAllRead($userId); // 全部已读 NotificationService::getUserNotifications($userId, $page, $limit, $type); // 列表 NotificationService::getUnreadCount($userId); // 未读数
2.3 数据表结构(pr_notification)
| 字段 | 类型 | 说明 |
|---|---|---|
| user_id | int | 接收用户ID(0=全员广播) |
| type | varchar(20) | 通知类型 |
| title | varchar(200) | 标题 |
| content | text | 内容 |
| is_read | tinyint | 已读状态 |
| related_id / related_type | int / varchar | 关联业务 |
| extra_data | text | 扩展数据JSON |
三、图片管理完善化
3.1 新增服务类
| 服务类 | 说明 |
|---|---|
| ThumbnailService | 缩略图自动生成(thumb_s/m/l 三尺寸) |
| WatermarkService | 文字/图片水印处理 |
| FileStorageService | 文件上传/删除/URL获取/云存储迁移 |
| ImageCategory | 图片按分类组织管理 |
四、新增文件清单
API 模块(12 文件)
app/api/controller/BaseController.php— API 基础控制器app/api/controller/v1/Content.php,User.php— v1 接口app/api/controller/v2/Content.php,User.php— v2 接口app/api/controller/BranchController.php— 门店 APIapp/api/controller/ContentController.php— 通用内容 APIapp/api/controller/MemberController.php— 会员 APIapp/api/middleware/ApiAuth.php— 认证中间件app/api/middleware/ApiRateLimit.php— 限流中间件app/api/route/app.php— API 路由
通知系统(3 文件)
app/admin/controller/Notification.php— 后台管理app/service/NotificationService.php— 发送服务app/model/Notification.php— 数据模型
图片增强(3+ 文件)
app/service/ThumbnailService.php,WatermarkService.php,FileStorageService.phpapp/admin/controller/ImageCategory.php
服务层补充(5 文件)
AddonLoader.php,HookService.php,ContentManageService.php,MessageService.php,Ip2RegionAdapter.php
五、完整功能矩阵(v2.0.0)
| 领域 | 模块数 | 核心功能 |
|---|---|---|
| 内容管理 | 8 | 产品/新闻/单页/门店/招聘/案例/下载/留言 |
| 文档管理 | 2 | 文档分类树 + 文档内容 |
| 表单系统 | 3 | 自定义表单/字段/数据 |
| 自定义模型 | 3 | 模型/字段/动态内容 |
| 用户权限 | 5 | 管理员/会员/等级/RBAC/菜单 |
| 安全防护 | 8 | 8维度检测/黑名单/登录日志/多层过滤 |
| SEO 优化 | 2 | SEO配置/Sitemap生成 |
| 性能优化 | 3 | HTML静态化/缓存管理/缩略图 |
| 主题系统 | 2 | 多主题切换/资源管理 |
| API 接口 | 6 | v1/v2双版本/认证/限流/内容/用户/门店/会员 |
| 通知消息 | 1 | 站内通知(4种类型) |
| 图片管理 | 4 | 上传/分类/缩略图/水印 |
总计:30+ 功能模块,60+ 控制器/服务/模型文件
v2.1.0 安全中心全面升级
更新概述
v2.1.0 聚焦安全中心的全面升级与体验优化。本次更新完善了安全告警体系、通知系统隔离、操作日志追踪,并对安全中心 UI 进行了全面优化,使安全中心成为真正实用、易用的安全管理平台。
新增功能
1. 安全告警独立模块
功能概述
将安全告警从通用通知系统中独立出来,专属安全中心管理。安全告警(XSS 拦截、SQL 注入、暴力破解等)不再混入普通通知列表,而是集中在安全中心的安全告警模块中统一管理。
模块组成
| 组件 | 文件路径 | 说明 |
|---|---|---|
| 控制器方法 | app/admin/controller/Security.php | 安全告警 CRUD 接口 |
| 视图页面 | app/admin/view/security/alerts.html | 告警列表弹窗页面 |
| JS 逻辑 | public/static/admin/js/security.js | 弹窗交互逻辑 |
| 样式 | public/static/admin/css/security.css | 弹窗样式 |
新增接口
| 方法 | 路由 | 说明 |
|---|---|---|
alerts() | GET /admin/security/alerts | 告警弹窗页面 |
getAlerts() | GET /admin/security/getAlerts | 获取告警列表(含未读数) |
markAlertRead() | POST /admin/security/markAlertRead | 标记单条已读 |
deleteAlert() | POST /admin/security/deleteAlert | 删除单条告警 |
clearAlerts() | POST /admin/security/clearAlerts | 清空所有告警 |
getUnreadAlertCount() | GET /admin/security/getUnreadAlertCount | 获取未读数量 |
顶部导航角标
在后台顶部导航新增盾牌图标,实时显示未读安全告警数量:
有未读告警时显示红色数字角标(超过 99 显示
99+)无未读告警时自动隐藏
点击跳转到安全中心页面
每次页面切换自动刷新角标数量
2. 通知系统用户类型隔离
问题背景
之前安全告警通过 notification 表发送,但 user_id 字段同时被管理员和前台用户共用,导致安全告警可能被前台用户看到。
解决方案
新增 user_type 字段区分通知接收者类型:
| 字段 | 类型 | 说明 |
|---|---|---|
| user_type | varchar(20) | user-前台用户 / admin-后台管理员 |
代码变更
| 文件 | 变更 |
|---|---|
app/model/Notification.php | 新增 TYPE_SECURITY 和 USER_TYPE_* 常量 |
app/service/SecurityService.php | sendSecurityAlert() 设置 user_type='admin' |
app/service/NotificationService.php | 前台查询添加 where('user_type', 'user') 过滤 |
app/admin/controller/Notification.php | 后台列表显示所有通知(管理员视角) |
3. 留言回复通知精准推送
留言回复通知逻辑正确,无需修改:每个用户只收到自己留言的回复通知,互不干扰。
4. 安全中心 UI 优化
安全告警弹窗
采用 iframe 弹窗模式(type:2),与 IP 白名单/黑名单页面风格一致
弹窗尺寸优化为
60% × 80%,适配不同屏幕工具栏布局:左侧按钮组 + 右侧搜索框
空状态显示表情图标 + "暂无数据"文字
模块卡片渐变色
为安全中心 7 个模块卡片补充渐变色:
| 卡片 | 渐变色 |
|---|---|
| 安全策略配置 | #667eea → #764ba2 (紫) |
| IP 黑名单 | #f093fb → #f5576c (粉) |
| IP 白名单 | #4facfe → #00f2fe (蓝) |
| 目录权限检查 | #43e97b → #38f9d7 (绿) |
| 登录日志 | #fa709a → #fee140 (粉橙) |
| 操作日志 | #a18cd1 → #fbc2eb (紫粉) |
| 安全告警 | #fccb90 → #d57eeb (橙紫) |
修复问题
安全告警通知推送给前台用户:新增
user_type字段隔离,安全告警只发送给管理员。后台通知列表为空:后台通知管理显示所有通知(管理员视角),只有前台用户中心才过滤
user_type='user'。删除通知后列表不刷新:统一为
res.code === 0判断成功。安全告警弹窗一直加载中:在
route/app.php补充 5 条安全告警路由。安全告警弹窗样式不一致:在
security.css新增#pr-page-security-alerts专属样式。安全告警弹窗 jQuery 未定义:为 5 个方法全部补充
$声明。
文件变更清单
新增文件
| 文件路径 | 说明 |
|---|---|
app/admin/view/security/alerts.html | 安全告警弹窗页面 |
database/migrations/notify_user_type.sql | 通知表 user_type 字段迁移脚本 |
修改文件
| 文件路径 | 变更说明 |
|---|---|
app/admin/controller/Security.php | 新增 6 个安全告警接口方法 |
app/admin/controller/Notification.php | 移除 user_type 过滤(管理员查看全部) |
app/service/SecurityService.php | sendSecurityAlert 设置 user_type='admin' |
app/service/NotificationService.php | 前台查询添加 user_type='user' 过滤 |
app/model/Notification.php | 新增 TYPE_SECURITY 和 USER_TYPE_* 常量 |
app/admin/view/layout/main.html | 顶部导航新增安全告警盾牌图标 |
app/admin/view/security/index.html | 新增安全告警模块卡片,移除内联弹窗 HTML |
public/static/admin/js/security.js | 新增安全告警弹窗逻辑 |
public/static/admin/js/admin.js | 新增安全告警角标刷新逻辑 |
public/static/admin/css/security.css | 新增 alerts 弹窗样式 + 卡片渐变色 |
route/app.php | 新增 6 条安全告警路由 |
database/install.sql | pr_notification 表新增 user_type 字段 |
数据库变更
ALTER TABLE `pr_notification` ADD COLUMN `user_type` varchar(20) NOT NULL DEFAULT 'user' COMMENT '用户类型:user-前台用户, admin-后台管理员' AFTER `user_id`; ALTER TABLE `pr_notification` ADD INDEX `idx_user_type` (`user_type`); -- 更新 type 字段注释 ALTER TABLE `pr_notification` MODIFY COLUMN `type` varchar(20) NOT NULL DEFAULT 'system' COMMENT '通知类型:system-系统通知, order-订单通知, activity-活动通知, message-留言回复, security-安全告警';
安全告警触发场景
| 场景 | 告警标题 | 触发条件 |
|---|---|---|
| XSS 攻击拦截 | [安全] XSS 攻击拦截 | 请求参数包含 XSS 攻击特征 |
| SQL 注入拦截 | [安全] SQL 注入拦截 | 请求参数包含 SQL 注入特征 |
| 暴力破解 | [安全] 登录暴力破解 | 同一 IP 短时间内多次登录失败 |
| 异常登录 | [安全] 异常登录尝试 | 黑名单 IP 尝试访问后台 |
| 目录遍历 | [安全] 目录遍历尝试 | 请求路径包含 ../ 等遍历特征 |
升级指南
数据库升级:执行
notify_user_type.sql迁移脚本清除缓存:后台访问 缓存管理 → 全部清理
验证安全告警:访问安全中心,点击安全告警卡片,确认弹窗正常显示
v2.2.0 商城功能全面上线
更新概述
v2.2.0 为 PuranCMS 引入完整的商城交易闭环。涵盖前台购物车、结算、支付、会员中心订单管理,以及后台订单管理、商品管理联动等核心功能。同时优化了会员中心菜单布局、多语言插件兼容性等问题。
新增功能
1. 前台商城交易流程
1.1 购物车功能
| 功能 | 说明 |
|---|---|
| 加入购物车 | 产品详情页点击加入购物车,弹窗提示 |
| 全选/单选 | 支持全选和单个商品选择,实时计算总价 |
| 数量调整 | 点击数量增减按钮,自动更新金额 |
| 删除商品 | 支持单个删除和批量删除 |
| 实时金额计算 | 选择商品或调整数量时,合计金额实时更新 |
1.2 结算与支付
| 功能 | 说明 |
|---|---|
| 收货地址选择 | 从用户地址列表中选择或新增 |
| 订单确认 | 展示商品清单、金额明细、收货信息 |
| 支付流程 | 支持在线支付,支付结果页面展示 |
1.3 产品详情页优化
加入购物车弹窗改为系统统一弹窗样式
移除页面调试信息
2. 后台订单管理
2.1 订单列表页面
| 功能 | 说明 |
|---|---|
| 状态 Tab 筛选 | 全部/待付款/待发货/已发货/已完成/已取消/已退款,点击切换筛选 |
| 关键词搜索 | 支持按订单号、收货人姓名、手机号搜索 |
| 日期范围筛选 | 按下单日期范围筛选 |
| 表格列表展示 | 订单号、商品信息、数量、金额、状态、操作列 |
| 顶部固定 | 工具栏上下滑动时固定在顶部 |
| 分页加载 | 支持分页浏览订单列表 |
2.2 订单详情页面
| 功能 | 说明 |
|---|---|
| 订单信息 | 订单号、状态、下单用户、下单时间 |
| 收货信息 | 收货人、联系电话、收货地址 |
| 商品清单 | 商品图片、名称、单价、数量、小计 |
| 金额汇总 | 商品总额、运费、应付金额 |
| 状态操作 | 发货、完成、取消、退款 |
2.3 订单操作
| 操作 | 条件 | 说明 |
|---|---|---|
| 发货 | 待发货状态 | 填写物流公司、运单号 |
| 完成 | 已发货状态 | 确认订单完成 |
| 取消 | 待付款/待发货 | 取消订单 |
| 退款 | 已完成状态 | 处理退款 |
3. 后台一级菜单
新增 订单管理 一级菜单,独立于商城管理
菜单通过 SQL 迁移脚本添加到
pr_admin_menu表
优化改进
1. 会员中心菜单重构
1.1 菜单分组
将会员中心左侧菜单分为三个独立卡片:
| 卡片 | 菜单项 |
|---|---|
| 个人信息 | 个人资料、修改密码、我的地址 |
| 商城功能 | 我的订单、购物车 |
| 预约管理 | 我的预约(原"其他"改为"预约管理") |
1.2 商城功能联动
后台关闭商城功能时,会员中心自动隐藏"商城功能"卡片(我的订单、购物车)
开启商城功能时,自动显示
2. 多语言插件导航修复
问题:打开多语言插件后,后台所有页面都会显示多语言导航菜单。
原因:多语言插件通过 admin_header_nav_left 钩子注入导航,判断逻辑基于 URL 字符串匹配,不够精确。
修复方案:改为通过控制器、动作和参数精确匹配,仅在多语言插件管理页面显示导航。
3. 订单列表样式优化
卡片改为表格:将订单列表从卡片样式改为紧凑的表格列表样式
操作列按钮化:操作列从文字链接改为彩色按钮样式(详情蓝、发货绿、完成橙、取消红、退款黄)
商品图片同步:订单列表和详情页同步显示商品缩略图,无图时显示"无图"占位
4. 金额计算修复
问题:后端返回的价格字段为字符串类型,前端直接调用 .toFixed() 报错。
修复:所有金额显示前使用 parseFloat() 进行类型转换。
5. 调试信息清理
移除购买流程相关页面的所有调试信息代码:购物车页面、结算页面、支付结果页面、产品详情页面。
修复问题
| 问题 | 修复方案 |
|---|---|
| 购物车合计金额始终为0元 | 修正 JS 读取后端返回数据结构 |
| 全选按钮提示"参数错误" | 前端数组转逗号分隔字符串,后端兼容处理 |
| 订单详情页 cancel_time 未定义 | 模板中添加 isset() 检查 |
| 多语言导航在所有后台页面显示 | 改为控制器+动作+参数精确匹配 |
| 订单列表不显示数据 | 修正 status 筛选默认值,搜索按钮读取所有筛选条件 |
| 价格 toFixed 报错 | 添加 parseFloat() 类型转换 |
| 商品图片 404 | 修正字段名 product_thumb → product_image,无图显示占位文字 |
| 加入购物车弹窗样式不统一 | 改为系统统一弹窗样式 |
命名空间隔离
后台订单管理页面采用命名空间隔离方案,避免样式和脚本全局污染:
| 页面 | CSS 命名空间 | JS 命名空间 |
|---|---|---|
| 订单列表 | #pr-page-shop-order | PR.ShopOrderAdmin |
| 订单详情 | #pr-page-shop-order-detail | PR.ShopOrderDetail |
升级指南
执行菜单迁移:
mysql -u root -p webpurancc < database/shop_order_menu_migration.sql清除缓存:后台访问 缓存管理 → 全部清理
验证功能:前台购物车→结算→支付流程;后台订单管理→列表→详情→操作
发布日期:2026-06-22
更新类型:功能增强(Minor Release)
v2.3.0 防伪码与消息通知修复
更新概述
v2.3.0 主要修复了防伪码插件首次查询时间不显示的问题,以及前台会员中心消息通知页面的多个功能缺陷。同时完善了后台通知管理,使其能够展示所有分类的通知数据。
修复问题
1. 防伪码插件 — 首次查询时间不显示
问题描述:
前台查询防伪码后,结果页面"首次查询"字段显示为
-后台防伪码列表页面"首次查询时间"列显示为原始时间戳(如
1782260520)后台防伪码查看/编辑页面"首次查询"和"最后查询"字段显示异常
根本原因:Index.php 的 doSearch() 方法中,设置 first_query_time 的条件判断有误。原代码检查 if ($info['status'] == 0) 来设置首次查询时间,但 status == 0 的记录在前面已被拦截返回错误,导致该条件永远不成立。
修复方案:
将条件改为
if (empty($info['first_query_time']))后台
Admin.php的list()、edit()、view()方法中增加时间格式化逻辑模板文件移除
|date过滤器,改为直接显示控制器已格式化的时间字符串
2. 前台消息通知 — 分类 Tab 切换不生效
问题描述:切换"系统通知"、"订单通知"、"留言回复"、"活动通知"等 Tab 时,列表内容不变,所有消息始终显示在"全部"下。
根本原因:getUserNotifications() 用 where('notify_type', $type) 直接匹配,但数据库 notify_type 存的是 order_created、order_paid 等具体值,前端传的是 order、system 等大类,无法匹配。
修复方案:改为 LIKE 模糊匹配,type=order 时匹配 order_%,type=system 时匹配 system%,以此类推。
3. 前台消息通知 — 留言回复和系统消息不显示
问题描述:前台消息通知页面看不到留言回复和系统消息,但后台这些数据是存在的。
根本原因:系统有两个通知表:
notification表 — 后台管理使用,type字段存system、message、activity等notification_log表 — 订单服务使用,notify_type字段存order_created、order_paid等
前台 getUserNotifications() 只查了 notification_log 表,完全漏掉了 notification 表的数据。
修复方案:重写 NotificationService 中的相关方法,同时查询两个表并合并结果。
4. 前台消息通知 — 删除消息报错
问题描述:点击删除按钮时报错 Call to undefined method app\service\NotificationService::deleteNotification()。
修复方案:在 NotificationService 中添加 deleteNotification() 方法。
5. 前台消息通知 — 已读红点不消失
问题描述:点击查看消息后,左侧列表的红点不会消失。
根本原因:NotificationService 缺少 markAsRead() 和 markAllAsRead() 方法。
修复方案:添加 markAsRead() 和 markAllAsRead() 方法。
6. 前台消息通知 — 未读数字不动态更新
问题描述:标记已读或删除消息后,顶部未读数字不更新。
根本原因:updateUnreadCount() 函数查找 #unreadBadge,但布局模板中实际使用的是 .menu-badge 类名,选择器错误。
修复方案:改为从服务器 /user/center/unreadCount 接口获取真实未读数,并正确更新 .menu-badge 元素。
7. 前台消息通知 — 切换 Tab 时详情面板不重置
问题描述:切换消息分类 Tab 时,右边详情面板仍然显示之前选中的消息内容。
修复方案:在 Tab 点击事件中增加重置详情面板和清除列表选中状态的代码。
8. 前台消息通知 — 删除后按钮失效
问题描述:删除第一条消息成功后,再点击删除按钮没有反应,必须刷新页面才能继续删除。
根本原因:删除成功后 $btn.prop('disabled', true) 没有在回调中恢复为 false,导致按钮永久禁用。
修复方案:将 $btn.prop('disabled', false) 移到请求回调的最前面;同时将事件绑定改为 $(document).on() 事件委托模式。
9. 后台通知管理 — 只显示部分通知
问题描述:后台通知管理列表只显示安全告警和系统通知,看不到订单通知、留言回复等其他分类。
根本原因:后台 Notification.php 控制器只查了 notification 表,没有包含 notification_log 表中的订单相关通知。
修复方案:
list()方法合并两个表的数据,按时间倒序排列后分页返回delete()方法先尝试notification表,再尝试notification_log表batchDelete()方法同时从两个表中删除匹配的记录类型筛选适配两个表的字段差异
10. 后台通知管理 — 安全告警标签样式
问题描述:安全告警类型的标签没有专属样式。
修复方案:添加 .type-badge-security 样式,浅红底 + 深红字,与其他标签风格保持一致。
文件变更清单
| 文件路径 | 变更说明 |
|---|---|
addons/anticode/controller/Index.php | 修复首次查询时间设置条件和格式化 |
addons/anticode/controller/Admin.php | list/edit/view 方法增加时间字段格式化 |
addons/anticode/view/admin/list.html | 移除 |date 过滤器 |
addons/anticode/view/admin/edit.html | 移除 |date 过滤器 |
addons/anticode/view/index/result.html | 移除 |date 过滤器 |
addons/anticode/view/index/query.html | 增加对 - 值的判断 |
app/service/NotificationService.php | 合并两个通知表;新增 deleteNotification/markAsRead/markAllAsRead/sendToUser/sendToUsers/sendBroadcast 方法 |
app/index/controller/Member.php | 修复未读数更新选择器;修复 deleteNotification 调用 |
app/admin/controller/Notification.php | 合并两个表数据;修复删除/批量删除支持两个表 |
template/default/user/notifications.html | 修复 Tab 切换、详情重置、删除按钮禁用、未读数更新 |
template/default/user/layout.html | 修复未读数徽章选择器 |
public/static/admin/css/notification.css | 添加安全告警标签样式 |
升级指南
清除缓存:后台访问 缓存管理 → 全部清理
验证防伪码:前台查询防伪码 → 查看首次查询时间是否正常显示
验证消息通知:前台切换各分类 Tab → 验证列表正确筛选;删除消息 → 验证可连续删除
验证后台通知管理:验证列表显示所有分类通知;类型筛选正常工作
注意事项
两个通知表:系统同时使用
notification和notification_log两个表存储通知数据,前者用于后台发送的系统/活动/留言通知,后者用于订单服务自动生成的订单状态通知时间格式:防伪码的首次查询时间和最后查询时间现在由控制器统一格式化为
Y-m-d H:i:s字符串,模板中不再使用|date过滤器未读数徽章:会员中心布局模板中未读数徽章使用
.menu-badge类名,JS 中已修正选择器
发布日期:2026-06-24
更新类型:Bug 修复(Patch Release)
v2.4.0 图片素材管理与控制台优化
更新概述
v2.4.0 主要新增了后台图片素材引用检测功能,可自动识别全站前后台所有位置引用的图片并显示「已引用」标签,同时支持一键清除未引用图片。此外优化了控制台流量分析、访问统计图表,修复了省市县三级联动、主题颜色统一等多个问题。
新增功能
1. 图片素材引用检测
功能描述:
后台图片素材列表自动检测每张图片是否被全站引用
被引用的图片右上角显示红色「已引用」标签
鼠标悬停标签可查看具体引用来源(如"产品缩略图、文章内容")
检测范围(全站覆盖):
| 检测类型 | 表/字段 | 说明 |
|---|---|---|
| 单字段 | product.thumb | 产品缩略图 |
| 单字段 | article.thumb | 文章缩略图 |
| 单字段 | advertisement.image | 广告图片 |
| 单字段 | branch.thumb / branch.image | 门店图片 |
| 单字段 | nav.thumb | 栏目封面 |
| 单字段 | page.banner | 单页Banner |
| 单字段 | tag.cover | 标签封面 |
| 单字段 | user.avatar | 用户头像 |
| 单字段 | user_level.icon_url | 等级图标 |
| 单字段 | user_level.card_bg_url | 等级卡片背景图 |
| 单字段 | shop_order_item.product_image | 订单商品图 |
| 单字段 | addon_anticode.product_image | 防伪码产品图 |
| 单字段 | image.thumb | 图片内容缩略图 |
| 单字段 | addon.icon | 插件图标 |
| 单字段 | admin_menu.icon | 菜单图标 |
| JSON字段 | product.images / extra_fields / spec_json | 产品图片集/扩展字段/规格 |
| JSON字段 | article.extra_fields / spec_json | 文章扩展字段/规格 |
| JSON字段 | advertisement.slides | 轮播幻灯片 |
| JSON字段 | image.images / extra_fields | 图片素材集/扩展字段 |
| JSON字段 | addon.config | 插件配置 |
| JSON字段 | page.extra_fields | 单页扩展字段 |
| JSON字段 | recruitment.extra_fields | 招聘扩展字段 |
| JSON字段 | download.extra_fields | 下载扩展字段 |
| HTML内容 | product.content | 产品详情富文本 |
| HTML内容 | article.content | 文章富文本内容 |
| HTML内容 | page.content | 单页富文本内容 |
| HTML内容 | image.content | 图片内容详情 |
| HTML内容 | recruitment.content | 招聘详情 |
| 系统配置 | system_config.value | 所有系统配置值 |
匹配策略:
支持带域名完整URL匹配(
https://web.puran.cc/storage/images/...)支持相对路径匹配(
/storage/images/...)支持无斜杠路径匹配(
storage/images/...)支持文件名basename匹配(最宽松,兼容不同路径格式)
修改文件:
| 文件路径 | 变更说明 |
|---|---|
app/service/ImageManageService.php | 新增 checkImageReferences() 方法,实现全站图片引用检测 |
app/service/ImageManageService.php | 新增 cleanUnreferencedImages() 方法,清除未引用图片 |
app/admin/controller/ImageManage.php | 新增 checkReferences() 和 cleanUnreferenced() 接口 |
app/admin/view/image_manage/index.html | 新增「已引用」标签显示和「清除未引用图片」按钮 |
public/static/admin/css/image-manage.css | 新增 .image-referenced-badge 样式(红色渐变) |
public/static/admin/js/image-manage.js | 新增 checkImageReferences() 前端调用逻辑 |
public/static/admin/js/image-manage.js | 新增 cleanUnreferencedImages() 清除未引用图片逻辑 |
route/app.php | 新增 checkReferences 和 cleanUnreferenced 路由 |
2. 清除未引用图片
功能描述:
图片素材页面新增橙色「清除未引用图片」按钮
点击后弹出确认框,确认后自动扫描所有图片
未引用的图片:删除物理文件 + 删除数据库记录
已引用的图片:自动跳过
操作完成后显示删除数量、跳过数量和失败列表
优化改进
3. 控制台流量分析 — 搜索引擎细分
优化内容:
流量来源饼图新增搜索引擎细分展示
自动识别具体搜索引擎(百度、Google、Bing、搜狗、360搜索、Yandex、Yahoo、搜搜、有道、神马等)
搜索引擎数据合并到流量分析饼图中,不再单独显示
小占比数据扇区设置最小角度(minAngle: 3),确保标签可见
修改文件:
| 文件路径 | 变更说明 |
|---|---|
app/service/DashboardService.php | 新增 detectSearchEngine() 方法;修改 getSourceAnalysis() 合并搜索引擎细分 |
app/admin/controller/Dashboard.php | 移除 getSearchEngineAnalysis 接口 |
public/static/admin/js/dashboard.js | 优化 renderSourcePie() 小占比数据显示 |
4. 访问统计图表优化
优化内容:
今日/昨日数据点过少时(≤2个),自动从折线图切换为柱状图
柱状图顶部显示具体数值标签,提高可读性
折线图保留面积填充效果,柱状图移除面积填充
修改文件:
| 文件路径 | 变更说明 |
|---|---|
public/static/admin/js/dashboard.js | renderTrafficChart() 根据数据点数量自动切换图表类型 |
5. 省市县三级联动重构
优化内容:
重构为原生select + 自定义样式,移除Layui依赖
省份下拉框显示10个选项后出现滚动条
修复省份选择后市、县联动不显示的问题
修复行政区划代码(12位)超过JavaScript安全整数范围的精度丢失问题
修复省直市区县无下级时无法保存的问题(如湖北省仙桃市)
加载中提示优化:加载完成后立即显示"请选择",不再残留"加载中"
修改文件:
| 文件路径 | 变更说明 |
|---|---|
template/default/user/shop_address.html | 重构省市县三级联动,使用原生select+自定义样式 |
6. 主题颜色统一
优化内容:
选中颜色由橙红色改为金色(#c8a97e),与主题模板一致
订单页面Tab菜单选中色改为黑色,下划线改为黑色
Tab菜单鼠标悬停色改为黑色
购物车/订单页面"去结算"按钮颜色改为金色主题
修改文件:
| 文件路径 | 变更说明 |
|---|---|
template/default/user/shop_address.html | 选中颜色改为金色 |
template/default/user/shop_cart.html | 去结算按钮改为金色 |
template/default/user/shop_orders.html | Tab菜单选中/悬停色改为黑色,按钮颜色优化 |
Bug 修复
7. 控制台数据获取失败
问题:控制台页面报错 Undefined array key "admin_name" 和 Undefined array key "type"
修复:使用 ?? 空合并运算符替代 ?:,确保数组键不存在时返回默认值
修改文件:app/service/DashboardService.php
8. 图片素材引用检测 — 路由缺失
问题:checkReferences 接口返回整个HTML页面而非JSON数据
修复:在 route/app.php 中添加 checkReferences 和 cleanUnreferenced 路由定义
修改文件:route/app.php
9. 图片素材引用检测 — Db类未导入
问题:报错 Class "app\service\Db" not found
修复:在 ImageManageService.php 顶部添加 use think\facade\Db;
修改文件:app/service/ImageManageService.php
10. 图片素材引用检测 — URL格式不匹配
问题:图片URL存储格式不一致(带域名/带斜杠/不带斜杠),导致匹配失败
修复:
同时保留原始URL(带斜杠)和去斜杠版本的映射
SQL查询合并两种URL变体
PHP匹配逻辑同时检查两种格式
增加basename文件名匹配作为兜底方案
修改文件:app/service/ImageManageService.php
技术要点
URL匹配策略
系统同时支持以下四种格式的匹配,确保无论数据库中存储哪种格式都能正确识别引用关系:
| 格式 | 示例 |
|---|---|
| 完整URL | https://web.puran.cc/storage/images/2026/05/13/xxx.jpg |
| 相对路径 | /storage/images/2026/05/13/xxx.jpg |
| 无斜杠 | storage/images/2026/05/13/xxx.jpg |
| 文件名 | xxx.jpg |
图表自适应
访问统计图表根据数据点数量自动切换图表类型:
var useBar = dates.length
升级注意事项
图片素材引用检测:首次加载图片列表时会自动调用引用检测接口,图片较多时可能有轻微延迟
清除未引用图片:操作不可恢复,建议先确认图片确实未被使用后再执行
路由配置:新增了两个路由,确保 route/app.php 已更新
数据库:无需执行SQL,所有变更通过代码实现
发布日期:2026-06-24
更新类型:功能增强(Minor Release)
v2.5.0 多语言插件优化与主题管理修复
更新概述
v2.5.0 重点优化了多语言插件的专业术语翻译机制,参考 translate.zvo.cn 官方文档修复了术语表无法送达前台、缓存失效等核心问题。同时修复了主题管理中截图不显示、大图不居中等多个界面问题,并优化了联系我们页面的视觉风格统一性。
多语言插件优化
1. 专业术语翻译机制重构
问题描述:
后台设置的自定义术语在前台翻译时有时生效、有时不生效
术语表从未被正确传递到前端,
translate.nomenclature.append()始终收到空数据切换翻译服务后仍请求旧的 zvo.cn API,导致 CORS 和 502 错误
根本原因分析:
Plugin.php::buildInlineConfig()中'nomenclature_map' => []直接置空,注释说"通过 AJAX 加载即可"frontend.js::loadConfigAndInit()在有内联配置时直接 early-return,根本不会发起 AJAX 请求获取术语表Plugin.php::getDisplayConfig()缺少translate_service、source_lang、target_lang、ignore_selectors_raw字段,全部回退到默认值translate.js中temp_nomenclature[local]始终为undefined(变量声明但未赋值的 bug)
修复方案:
1.1 术语表内联输出(核心修复)
参考 translate.zvo.cn 官方文档要求:
translate.nomenclature.append(from, to, properties); 注意,这行要放到 translate.execute(); 上面在 Plugin.php 中新增 buildNomenclatureMap() 方法,从 addons/multilang/data/nomenclature.json 读取术语数据并按目标语言分组构建 原文=译文 字符串,直接内联输出到页面。
修改文件:
addons/multilang/Plugin.php— 新增buildNomenclatureMap()方法;修改buildInlineConfig()调用该方法
执行链路(修复后):
PHP 渲染 HTML 时输出
window.PR_INLINE_CONFIG = {..., nomenclature_map: {en: "你好=Hello\n世界=ShiJie"}}frontend.js加载translate.js(异步)initTranslate()调用translate.nomenclature.append('chinese_simplified', 'english', '你好=Hello\n世界=ShiJie')— 在 execute 之前translate.execute()重置temp_nomenclature后开始扫描节点术语原文被替换为译文且不再被翻译接口处理
1.2 补齐配置字段
getDisplayConfig() 补齐 translate_service、source_lang、target_lang、ignore_selectors_raw 字段,确保用户在后台切换的翻译服务、源/目标语言、忽略选择器真正生效。
修改文件:
addons/multilang/Plugin.php—getDisplayConfig()方法
1.3 修复 temp_nomenclature 变量 bug
原代码中 nomenclatureKeyArray 只声明未赋值,导致 typeof 判断永远为 undefined,push 永远被跳过,最终 temp_nomenclature[local] 始终为 undefined。
修改文件:
public/static/addons/multilang/translate.js— 在循环外初始化var nomenclatureKeyArray = new Array();,移除无效的 typeof 判断;增加已存在时的合并逻辑
2. 翻译服务切换修复
问题:切换翻译服务后仍请求 api.translate.zvo.cn,导致 CORS 和 502 错误
修复:
后台设置页面增加"默认翻译服务 (zvo.cn)"选项
移除 Google 翻译服务(需翻墙,存在合规问题)
保留 Edge 浏览器翻译(免费,国内可用)
修改文件:
addons/multilang/view/admin/settings.html— 翻译服务下拉选项public/static/addons/multilang/translate.js— 条件性跳过版本检查
3. 语言切换按钮图标消失修复
问题:每次修改系统内容保存后,多语言插件的语言切换按钮图标消失,需要重新上传
修复:修改 Admin.php 保存逻辑,仅在提供新值时更新图标字段,保留已有图标路径
修改文件:
addons/multilang/controller/Admin.php— 保存设置时增加条件判断
主题管理修复
4. 主题截图不显示
问题:enterprise 主题在后台主题管理页面不显示截图,只显示默认占位图
原因:ThemeService.php 只查找 screenshot.png,而 enterprise 主题的截图是 screenshot.jpg
修复:
修改
ThemeService.php按优先级查找截图文件(支持png、jpg、jpeg、webp、gif)修正 enterprise 主题
theme.json中screenshots数组的扩展名从.png改为.jpg
修改文件:
app/service/ThemeService.php— 截图查找逻辑template/enterprise/theme.json— screenshots 数组扩展名
5. 主题预览大图不居中
问题:主题预览页面的大图偏左,没有占据左右箭头按钮之间的全部空间
修复:在 .preview-screenshot-container 添加 flex: 1,让它占据剩余空间
修改文件:
public/static/admin/css/theme.css—.preview-screenshot-container样式
界面优化
6. 联系我们页面文字颜色统一
问题:常见问题和保持联系的灰色文字与系统金色主题不一致
修复:将文字颜色改为金色(#c8a97e)
修改文件:
public/static/index/css/page_detail_contact.css— 文字颜色
7. 社交媒体图标悬停效果
问题:联系我们页面的社交媒体图标鼠标悬停时没有显示二维码,与底部不一致
修复:添加悬停事件处理,显示对应的二维码图片
修改文件:
template/default/index/page_detail_contact.html— 社交媒体图标悬停逻辑
Bug 修复
8. CSRF Token 不匹配
问题:多表单页面保存配置时 CSRF token 验证失败
修复:修改 config.js 优先使用全局 globalCsrfToken,而非每个表单的独立 token
修改文件:public/static/admin/js/config.js
9. 数据库路径恢复旧值
问题:清除缓存后,数据库中的图片路径恢复为旧值
原因:pr_system_config 表存在重复记录,缓存清除后读取到旧记录
修复:清理重复记录,确保每个配置项只有一条记录
修改文件:database/pr_system_config.sql
10. PHP autoload 错误
问题:debug_config.php 报错 Failed opening required '/vendor/autoload.php'
修复:确保 Composer 依赖正确安装,autoload.php 路径正确
修改文件:public/debug_config.php
技术要点
术语表数据格式
nomenclature.json 支持两种格式:
新格式(推荐):
[{"source": "你好", "translations": {"en": "Hello", "ja": "こんにちは"}}]旧格式(自动迁移):
[{"source": "你好", "target": "Hello"}]系统会自动将旧格式转换为新格式,按目标语言分组输出。
截图查找优先级
ThemeService.php 按以下优先级查找主题截图:
screenshots数组中声明的文件(精确匹配)screenshot.pngscreenshot.jpgscreenshot.jpegscreenshot.webpscreenshot.gif默认占位图
/static/admin/images/theme-default.png
升级注意事项
多语言术语表:如果之前设置了自定义术语,升级后会自动生效,无需重新配置
翻译服务:建议在后台多语言设置中将翻译服务改为「Edge 浏览器翻译」,避免 zvo.cn 服务不稳定导致的 502 错误
主题截图:enterprise 主题的
theme.json已修正,如果自定义了主题,请检查screenshots数组中的扩展名是否与实际文件匹配数据库:建议执行
database/pr_system_config.sql清理重复记录
发布日期:2026-06-26
更新类型:功能增强与 Bug 修复(Minor Release)
v2.6.0 API 配置管理模块
更新概述
v2.6.0 版本新增了 API 配置管理模块,为 PuranCMS 引入完整的邮件和短信通知能力。管理员可在后台配置 SMTP 服务器、短信服务商参数,并按事件维度开启/关闭各类通知(订单、会员、留言、安全),同时支持短信模板的可视化配置。
核心新增
1. 邮件配置管理(mail.html)
1.1 SMTP 服务器配置
服务器参数:支持配置 SMTP 服务器地址、端口、加密方式(SSL/TLS/不加密)
认证信息:用户名、密码(支持授权码)配置,密码字段支持显示/隐藏切换
发件人信息:可自定义发件人邮箱地址和显示名称
测试功能:支持输入测试邮箱地址,一键发送测试邮件验证配置
配置项说明:
| 字段 | 说明 | 示例 |
|---|---|---|
mail_host | SMTP 服务器地址 | smtp.qq.com |
mail_port | SMTP 端口 | 465(SSL)、587(TLS)、25(非加密) |
mail_secure | 加密方式 | ssl / tls / 空(不加密) |
mail_username | SMTP 登录用户名 | 通常是邮箱地址 |
mail_password | SMTP 登录密码或授权码 | QQ/163 邮箱需使用授权码 |
mail_from_email | 发件人邮箱地址 | |
mail_from_name | 发件人显示名称 |
1.2 邮件通知事件配置
支持按事件维度开启/关闭邮件通知,涵盖 4 大类 10 个事件:
订单通知:
订单创建(
mail_notify_order_created)订单支付成功(
mail_notify_order_paid)订单取消(
mail_notify_order_cancelled)订单发货(
mail_notify_order_shipped)
会员通知:
会员注册(
mail_notify_user_register)找回密码(
mail_notify_user_reset_password)
留言通知:
留言回复(
mail_notify_message_reply)新留言通知(
mail_notify_new_message)
安全通知:
安全告警(
mail_notify_security_alert)—— SQL 注入、XSS 等攻击拦截时通知管理员后台登录(
mail_notify_admin_login)
2. 短信配置管理(sms.html)
2.1 短信服务商配置
多服务商支持:阿里云短信、腾讯云短信、华为云短信
认证参数:AccessKey ID、AccessKey Secret(支持显示/隐藏切换)
短信签名:可自定义短信签名(需在服务商控制台审核通过)
配置项说明:
| 字段 | 说明 | 示例 |
|---|---|---|
sms_provider | 短信服务商 | aliyun / tencent / huawei |
sms_access_key_id | AccessKey ID | |
sms_access_key_secret | AccessKey Secret | |
sms_sign_name | 短信签名 | PuranCMS |
2.2 短信通知事件配置
与邮件通知事件完全一致,同样涵盖 4 大类 10 个事件,字段前缀为 sms_notify_*:
sms_notify_order_created/sms_notify_order_paid/sms_notify_order_cancelled/sms_notify_order_shippedsms_notify_user_register/sms_notify_user_reset_passwordsms_notify_message_reply/sms_notify_new_messagesms_notify_security_alert/sms_notify_admin_login
2.3 短信模板管理
模板 CODE:配置服务商审核通过的模板 CODE
模板内容:填写与服务商处一致的模板内容,支持多种变量语法
启用状态:每个模板可独立启用/停用
变量支持:系统自动识别模板中的占位符并在发送时替换为实际值
支持的变量语法:
| 语法 | 说明 | 适用场景 |
|---|---|---|
{$orderNo} | 命名变量 | 通用 |
${orderNo} | 命名变量(阿里云推荐) | 阿里云 |
{1} | 数字索引(对应第 1 个可用变量) | 腾讯云 |
${1} | 数字索引(华为云) | 华为云 |
界面设计
1. 页面布局
采用 Layui Tab 组件实现多标签切换
邮件配置:「邮箱配置」+「通知事件」两个标签
短信配置:「短信配置」+「通知事件」+「短信模板」三个标签
2. 样式规范
页面容器 ID:
#pr-page-api-mail/#pr-page-api-smsCSS 命名空间:
.pr-page-api-mail/.pr-page-api-sms共用样式文件:
/static/admin/css/api_config.css卡片式布局:
.config-card包裹配置项,标题 + 内容分层
3. 交互细节
密码字段支持显示/隐藏切换(眼睛图标)
开关组件使用 Layui Switch(开启/关闭)
保存操作统一使用 AJAX POST 请求,成功后显示提示消息
测试邮件发送时显示加载动画
路由配置
邮件配置和短信配置的路由定义在 app/admin/route/app.php 中:
// 邮件配置
Route::get('apiConfig/mail', 'apiConfig/mail');
Route::post('apiConfig/mail', 'apiConfig/mail');
Route::post('apiConfig/testMail', 'apiConfig/testMail');
// 短信配置
Route::get('apiConfig/sms', 'apiConfig/sms');
Route::post('apiConfig/sms', 'apiConfig/sms');
Route::post('apiConfig/saveSmsTemplates', 'apiConfig/saveSmsTemplates');数据库变更
新增配置项
邮件和短信配置项存储在 pr_system_config 表中,group 字段为 api_config:
| group | name | value | 说明 |
|---|---|---|---|
| api_config | mail_host | SMTP 服务器 | |
| api_config | mail_port | 465 | SMTP 端口 |
| api_config | mail_secure | ssl | 加密方式 |
| api_config | mail_username | 用户名 | |
| api_config | mail_password | 密码 | |
| api_config | mail_from_email | 发件人邮箱 | |
| api_config | mail_from_name | 发件人名称 | |
| api_config | mail_notify_order_created | 0 | 订单创建通知 |
| api_config | mail_notify_order_paid | 0 | 订单支付通知 |
| api_config | mail_notify_order_cancelled | 0 | 订单取消通知 |
| api_config | mail_notify_order_shipped | 0 | 订单发货通知 |
| api_config | mail_notify_user_register | 0 | 会员注册通知 |
| api_config | mail_notify_user_reset_password | 0 | 找回密码通知 |
| api_config | mail_notify_message_reply | 0 | 留言回复通知 |
| api_config | mail_notify_new_message | 0 | 新留言通知 |
| api_config | mail_notify_security_alert | 1 | 安全告警通知 |
| api_config | mail_notify_admin_login | 0 | 后台登录通知 |
| api_config | sms_provider | aliyun | 短信服务商 |
| api_config | sms_access_key_id | AccessKey ID | |
| api_config | sms_access_key_secret | AccessKey Secret | |
| api_config | sms_sign_name | 短信签名 | |
| api_config | sms_notify_order_created | 0 | 订单创建通知 |
| api_config | sms_notify_order_paid | 0 | 订单支付通知 |
| api_config | sms_notify_order_cancelled | 0 | 订单取消通知 |
| api_config | sms_notify_order_shipped | 0 | 订单发货通知 |
| api_config | sms_notify_user_register | 0 | 会员注册通知 |
| api_config | sms_notify_user_reset_password | 0 | 找回密码通知 |
| api_config | sms_notify_message_reply | 0 | 留言回复通知 |
| api_config | sms_notify_new_message | 0 | 新留言通知 |
| api_config | sms_notify_security_alert | 0 | 安全告警通知 |
| api_config | sms_notify_admin_login | 0 | 后台登录通知 |
短信模板配置
短信模板配置以 JSON 格式存储在 pr_system_config 表中:
| group | name | value | 说明 |
|---|---|---|---|
| api_config | sms_templates | {...} | 短信模板配置 JSON |
JSON 结构示例:
{
"order_created": {
"code": "SMS_123456",
"content": "您的订单 {$orderNo} 已创建成功",
"enabled": 1
},
"order_paid": {
"code": "SMS_123457",
"content": "您的订单 {$orderNo} 已支付成功,金额 {$amount} 元",
"enabled": 1
}
}文件变更
新增文件
| 文件路径 | 说明 |
|---|---|
app/admin/view/api_config/mail.html | 邮件配置页面 |
app/admin/view/api_config/sms.html | 短信配置页面 |
static/admin/css/api_config.css | API 配置页面样式 |
修改文件
| 文件路径 | 说明 |
|---|---|
app/admin/route/app.php | 新增邮件/短信配置路由 |
app/admin/controller/ApiConfig.php | 新增邮件/短信配置控制器方法 |
使用指南
1. 配置邮件通知
进入后台 系统设置 → API 配置 → 邮箱配置
填写 SMTP 服务器信息(以 QQ 邮箱为例):
SMTP 服务器:
smtp.qq.comSMTP 端口:
465加密方式:
SSL用户名:你的 QQ 邮箱地址
密码:QQ 邮箱授权码(非登录密码,需在 QQ 邮箱设置中开启并获取)
发件人邮箱:你的 QQ 邮箱地址
发件人名称:显示在收件人邮箱中的名称
点击「发送测试邮件」验证配置是否正确
切换到「通知事件」标签,开启需要的事件通知
点击「保存配置」和「保存通知设置」
2. 配置短信通知
进入后台 系统设置 → API 配置 → 短信配置
选择短信服务商(阿里云/腾讯云/华为云)
填写 AccessKey ID 和 AccessKey Secret(需在服务商控制台获取)
填写短信签名(需在服务商控制台审核通过)
切换到「通知事件」标签,开启需要的事件通知
切换到「短信模板」标签,为每个事件配置模板 CODE 和内容
点击「保存配置」「保存通知设置」「保存模板设置」
注意事项
邮箱授权码:QQ 邮箱、163 邮箱等需要使用授权码而非登录密码,需在邮箱设置中开启 SMTP 服务并获取授权码
短信签名:短信签名需在服务商控制台申请并审核通过后才能使用
短信模板:模板内容需与服务商控制台审核通过的模板保持一致,变量名需与可用变量一致
安全告警:安全告警通知默认开启,建议保持开启状态以及时发现安全风险
测试邮件:配置完成后务必发送测试邮件验证配置正确性
后续计划
支持邮件模板配置(HTML 模板、变量替换)
支持短信发送记录查看
支持邮件发送记录查看
支持短信/邮件发送失败重试机制
支持批量发送通知(如全员通知)
v2.7.0 安全加固
更新概述
v2.7.0 版本聚焦生产环境安全防护,重点解决「木马植入、前台页面被篡改、页面跳转非法网站」三类高风险问题。通过「上传内容扫描 + 统一安全响应头 + 后台写文件入口检测」三层防御,显著提升站点抗入侵与抗篡改能力。
核心新增
1. 上传文件内容安全扫描(防木马 / 挂马)
新增
extend/security/FileValidator::scanContent():基于特征库对所有上传文件做内容级扫描,可识别 PHP Webshell(eval/base64_decode/system/phpinfo等)、前端挂马(script / iframe / onload= 等事件属性)、页面跳转(window.location / meta refresh)等恶意特征。Upload 控制器(图片与 Logo 接口)统一接入该扫描,命中即拒绝上传并记录原因。
移除 SVG 上传支持:SVG 为 XML 文本格式,可内嵌脚本用于 XSS / 页面跳转 / 挂马,生产环境不再开放上传。
2. 统一安全响应头(防 XSS / 点击劫持 / 跳转挂马)
SecurityGuard 中间件新增 applySecurityHeaders(),对所有响应自动注入:
Content-Security-Policy(默认仅允许同源脚本/样式/资源,禁止外部域名脚本与嵌套框架)X-Frame-Options: DENY(防 iframe 嵌套劫持)X-Content-Type-Options: nosniffReferrer-Policy/X-XSS-Protection/Permissions-PolicyHTTPS 下下发
Strict-Transport-Security
即使页面被植入外链脚本或隐藏 iframe,浏览器也会按策略拦截,是防「跳转非法站」的最后一道客户端防线。可通过安全中心配置 security_headers_enable 关闭、csp_policy 自定义策略。
3. 后台写文件入口内容检测(防篡改落盘)
SecurityService::checkContentSafety()复用扫描能力,供后台可直接写文件的入口调用。SeoService::saveRobotsContent()(robots.txt 保存)已接入,落盘前检测恶意内容并阻止保存。
变更文件清单
| 文件 | 变更说明 |
|---|---|
extend/security/FileValidator.php | 移除 SVG 允许类型;新增 MALICIOUS_PATTERNS 特征库与 scanContent();上传目录 .htaccess 移除 svg 放行 |
app/admin/controller/Upload.php | 移除 SVG 允许类型;logo() 接口接入 FileValidator 统一校验(含内容扫描) |
app/middleware/SecurityGuard.php | 新增 applySecurityHeaders(),统一注入安全响应头 |
app/service/SecurityService.php | 新增 checkContentSafety() 可复用内容安全检测 |
app/service/SeoService.php | saveRobotsContent() 落盘前接入内容安全检测 |
数据库变更
向 pr_security_config 表新增配置项:security_headers_enable(默认 1)、csp_policy(默认空),详见 database/config_v2.7_security_headers.sql。
升级注意事项
执行顺序:先部署代码,再执行本迁移脚本与配置迁移脚本(或顺序不限,配置默认开启)。
SVG 资源兼容:升级后将无法再上传新 SVG,已有 SVG 不受影响,建议过渡期替换为 PNG/WebP。
CSP 兼容性:内置默认 CSP 保留 unsafe-inline(项目含大量内联脚本)。若上线后个别第三方脚本被拦截,可通过 csp_policy 配置收敛白名单,或采用 nonce 方案进一步收紧。
第三方统计/客服脚本:默认 CSP 仅允许同源,外部统计、客服、地图等脚本需将域名加入 csp_policy 白名单,否则会被浏览器拦截。
后续建议
登录双因子 / 后台二次密保验证
登录失败锁定 + 验证码(当前仅有宽松限流)
文件完整性监控(定时比对 app/ public/ template/ 文件哈希,检测篡改)
插件安装包内容扫描(ZIP 解压前扫描 .php 危险特征)
v2.8.0 安全加固(登录锁定 / 插件扫描 / 文件完整性)
更新概述
本版本在 v2.7.0 基础防御之上,补全安全中心三项核心防护能力,进一步收敛"入侵后持久化"与"横向扩散"风险:
登录失败锁定 + 图形验证码:暴力破解防护,锁定后强制验证码。
插件安装包 ZIP 解压前内容扫描:阻断通过上传插件包植入 Webshell。
文件完整性监控:基于哈希基线侦测核心目录被篡改、新增或删除。
一、登录失败锁定 + 图形验证码
失败锁定:同一 IP 连续登录失败达到阈值(
login_max_fails,默认 3 次)后,锁定login_lock_duration(默认 30 分钟),期间禁止登录。配置项位于pr_security_config:login_lock_enable(开关)、login_max_fails(阈值)、login_lock_duration(锁定分钟数)。锁定状态基于缓存(键login_fail_)计数,无需额外表。强制验证码:新增
login_captcha_enable(pr_system_config,默认开启)。当全局开关关闭时,若当前 IP 失败次数达到阈值的 80% 或已被锁定,仍强制启用图形验证码。涉及文件:app/admin/controller/Login.php。
二、插件安装包 ZIP 解压前扫描
新增后台「插件管理 → 上传插件包」入口,支持上传
.zip插件包。解压前通过
ZipArchive遍历包内所有.php文件,复用extend/security/FileValidator::scanContent()做内容级特征扫描,命中危险特征(Webshell / 挂马 / 跳转)即拒绝安装并记录原因。扫描通过后才解压到临时目录,校验
config.php存在后移动到addons/,并触发插件安装流程。涉及文件:
extend/security/FileValidator.php(新增scanZipPackage())、app/service/AddonService.php(新增scanPackage()/installFromUpload()/locatePluginRoot())、app/admin/controller/Addons.php(新增upload())、app/admin/view/addons/index.html+public/static/admin/js/addons.js。
三、文件完整性监控
基线机制:首次使用需在后台安全中心 → 文件完整性 →「建立/重建基线」,对
app/ public/ template/ config/ route/ extend目录计算 SHA-256 哈希,快照存于runtime/file_integrity/baseline.json。扫描比对:手动「立即扫描」或定时任务
php think integrity:scan会重新计算并与基线比对,识别新增 / 修改 / 删除三类变更。告警与记录:发现变更时写入
pr_file_integrity_log并通过既有SecurityService::sendSecurityAlert()推送安全通知。配置项(
pr_security_config,group=integrity):file_integrity_enable(总开关)、file_integrity_paths(监控目录)、file_integrity_exclude(排除项,默认已排除 runtime、uploads、vendor、think、.git 及日志缓存类文件)。涉及文件:
app/service/FileIntegrityService.php、app/model/FileIntegrityLog.php、app/admin/controller/Security.php(7 个接口)、app/command/FileIntegrityScan.php+config/console.php、app/admin/view/security/file_integrity.html+public/static/admin/js/file_integrity.js、route/app.php(7 条路由)、pr_admin_menu(安全中心下「文件完整性」)。
四、数据库变更
执行 database/config_v2.8_security.sql(幂等):
新增数据表
pr_file_integrity_log(文件完整性变更日志)。新增 / 兜底配置项:
pr_security_config的file_integrity_enable/file_integrity_paths/file_integrity_exclude(group=integrity);pr_system_config的login_captcha_enable(默认 1);登录锁定三项(login_lock_enable/login_max_fails/login_lock_duration)去重兜底。新增菜单:安全中心下「文件完整性」。
五、升级步骤
部署代码(含上述新增 / 修改文件)。
执行
database/config_v2.8_security.sql。(可选)执行本脚本将更新日志写入文档系统。
后台安全中心 → 文件完整性 → 保存配置 → 建立基线。
配置系统 cron,例如每日凌晨执行:
php think integrity:scan。
六、升级注意事项
插件上传入口:新增的上传插件包默认接入内容扫描,仅允许结构规范的插件包;若包内
.php含已知危险特征将被拒绝。文件完整性基线:基线建立后应妥善保管
runtime/file_integrity/baseline.json;升级代码(如更新app/)会触发"修改"告警,属正常现象,可在变更记录中标记为已处理。验证码依赖:
login_captcha_enable默认开启;若站点使用第三方登录且无验证码组件,请确认验证码资源可用后再行部署。监控目录性能:首次扫描 / 建立基线会遍历监控目录所有文件并计算哈希,目录较大时耗时较长,建议在低峰期操作。
七、后续计划
登录双因子认证(TOTP)绑定与二维码
后台敏感操作二次密保验证
文件完整性告警自动联动隔离 / 回滚
v2.8.1 文件完整性监控重构(隔离 / 回滚 / 自动扫描调度)
更新概述
本版本在 v2.8.0 文件完整性监控基础上进行系统性重构,补全"监控 → 告警 → 隔离 → 回滚"完整闭环,并完善自动扫描调度逻辑:
自动扫描调度精细化:支持每日/每周指定时间段,自然日/周节流。
隔离覆盖核心目录:public 用 move 隔离,核心目录用 .disabled 停用隔离,不断站。
回滚到修改前干净状态:基线内容副本方案,从 baseline_content 恢复而非隔离副本。
手动/自动时间戳分离:自动扫描与手动扫描各自记录时间,互不阻塞。
一、自动扫描调度精细化
每日模式:指定扫描时间段(如 21:18),到点触发一次自动扫描。
每周模式:选择星期一至星期日 + 指定时间段,仅在所选星期当天到达扫描时间后触发。
调度判定重构:由"24 小时冷却"改为自然日 / 自然周判定,避免修改扫描时间后当天无法再次触发。
手动/自动时间戳分离:
file_integrity_last_auto_scan:仅自动扫描更新,用于调度节流。file_integrity_last_scan:仅手动扫描(立即扫描)更新,不再阻塞自动调度。后台新增展示:
上次自动扫描、上次手动扫描,区分两种扫描来源。
二、扫描路径与基准修正
修复
scanDir()基准路径错误:此前以public/绝对路径为基准,导致相对路径丢失public/前缀,使 public 下文件被误判为"不可隔离"。现以项目根目录为基准,保留顶层目录前缀(如public/index.php)。监控范围覆盖全部风险目录:
public/、template/、app/、extend/、route/、config/,统一纳入基线比对。
三、隔离(Quarantine)能力升级
隔离服务覆盖核心目录,不再局限于 public/。
两种隔离模式:
move(public 等可访问目录):将文件移入runtime/quarantine/。disable(核心目录):追加.disabled后缀停用文件,不断开站点、避免崩站。quarantine_path存储格式改为路径|模式,回滚时据此选择恢复策略。处置列按模式显示「隔离」(move) 或「隔离(停用)」(disable);监控范围外仍显示「不可隔离」。
四、回滚到修改前干净状态(基线内容副本)
原方案隔离前复制当前文件作为回滚副本,但该副本已是挂马内容,无法恢复干净状态。
新方案(方案 A):建立/重建基线时,将干净文件内容副本存入
runtime/file_integrity/baseline_content/,回滚时从基线副本重建文件。相关方法:
baselineContentRoot()、baselineContentPath()、rebuildBaselineContent()、delTree()。
五、取证与回滚安全增强
restoreLog()覆盖目标文件前,先存一份.infected.<时间戳>取证副本,避免误操作丢失被篡改证据。按隔离模式(move/disable)和变更类型(modified/added)分别处理回滚逻辑。
六、后台交互优化
保存设置、建立/初始化基线、立即扫描后自动实时刷新页面(修复此前
loadPage is not defined报错,改用location.href)。页面初始化即加载配置,正确显示"上次自动扫描/上次手动扫描/基线状态",不再硬编码"从未"。
文件完整性告警入口(alerts.html)跳转修复。
七、自动扫描启用前提
依赖外部计划任务:在服务器配置 cron 或宝塔面板计划任务(Shell 脚本)每分钟调用:
cd /www/wwwroot/web.puran.cc /www/server/php/74/bin/php think integrity:scan >> /www/wwwroot/web.puran.cc/runtime/integrity_scan.log 2>&1
命令内部通过
shouldAutoScan()判断频率、星期、时间段,未到周期时输出未到自动扫描周期,跳过。并退出,不会重复扫描。回滚前需先「初始化基线」生成
baseline_content/副本。
八、数据库变更
执行 database/config_v2.8.1_file_integrity_quarantine.sql(幂等):
pr_file_integrity_log新增action/action_time/quarantine_path/backup_path字段。pr_security_config新增 / 兜底:file_integrity_auto_quarantine、file_integrity_scan_freq、file_integrity_scan_time、file_integrity_scan_weekday、file_integrity_last_scan(手动)、file_integrity_last_auto_scan(自动)(group=integrity)。
九、升级步骤
部署代码(含上述新增 / 修改文件)。
执行
database/config_v2.8.1_file_integrity_quarantine.sql。(可选)执行本脚本将更新日志写入文档系统。
后台安全中心 → 文件完整性 → 保存配置 → 初始化/重建基线(生成 baseline_content 干净副本)。
配置服务器计划任务(cron / 宝塔)每分钟调用
php think integrity:scan。
十、升级注意事项
基线重建:升级后请重新初始化基线,否则回滚功能不可用(基线副本未生成)。
自动扫描依赖外部调度:模块本身只提供扫描命令与节流逻辑,需自行配置计划任务。
核心目录隔离:采用 .disabled 后缀停用方式,可在后台「恢复」后自动还原,避免误删导致站点故障。
v2.8.2 前台模板层完成迁移(标签库 / 路由 / 静态资源)
版本:v2.8.2
发布日期:2026-10-19
本期聚焦前台模板层完成迁移:把前台门户从 Nuxt SSR 收敛到 ThinkPHP 原生模板渲染,补齐标签库预加载、全局 hook 函数、广告与站点配置接口、路由匹配规则。
一、前台控制器整体落到单应用命名空间
前台门户统一由
app/controller/index/承载,命名空间appcontrollerindex,包含Index、Member、Shop、Pay、Seo、Doc、BranchPage、Dynamic、Addons与基类BaseIndexController。基类
initialize()按当前主题动态设置view_path,主题取自ThemeService::getCurrentTheme(),即template/<主题标识>/。数据层沿用
app/model、app/service命名空间,与模板层解耦。
二、标签库与模板编译
config/view.php增加taglib_pre_load,预加载app aglibPuran,使{puran:ads}、{puran:list}等标签无需在每个模板中手动引入。关闭模板编译缓存
tpl_cache,避免修改模板后仍命中runtime/temp中的旧编译产物。app/taglib/Puran.php补齐广告、内容列表、内容详情、导航、面包屑等标签的取数与渲染逻辑。
三、全局 hook 函数补齐
app/common.php新增全局函数hook(string $hookName, array $params = []),内部委托HookService::triggerFirst()。此举修复了单页、插件页模板中
{:hook(’appointment_widget’)}、{:hook(’anticode_query_widget’)}、{:hook(’timeline_widget’)}调用报「Call to undefined function hook()」的 500 错误。
四、广告与站点配置接口
app/model/Advertisement.php补齐广告位取数能力,前台首页 Banner、品牌故事背景、门店背景等按position_id读取。app/controller/api/Config.php统一输出扁平化的站点配置键值,前台直接读取site_name、frontend_logo_fixed、frontend_logo_scroll、社交二维码等字段。
五、路由匹配规则修正
前台路由统一
->namespace(’app\controller\index’),静态规则按「由具体到抽象」排列,:slug动态捕获路由置于末尾。修复 ThinkPHP 静态规则前缀匹配吞掉更深子路径的问题:对存在子路径的静态规则补
completeMatch(),例如user/appointment不再劫持user/appointment/detail/:id。
六、升级说明
本版本为纯代码改动,无数据库结构变更。
若站点此前使用 Nuxt 静态产物,需确认
Route::miss已回退到模板渲染,避免旧200.html拦截动态路由。
v2.8.3 商城与支付开关全链路联动
版本:v2.8.3
发布日期:2026-10-19
本期聚焦商城开关与支付开关的全链路联动:修正配置读取分组错误,让后台开关真正控制前台菜单、购买按钮、结算、库存校验与支付入口。
一、配置分组读取统一(关键修复)
商城总开关
shop_enabled与库存开关shop_stock_enabled由后台「商城设置」写入system_config,分组为basic。修复多处读取端误用
->where(’group’, ’shop’)以及一处误查config表的问题,统一为group = basic。此前分组不匹配会查不到记录,导致开关对前后台完全失效。已统一修正的位置包括侧边栏菜单树、前台公共变量注入、购物车服务、订单服务与会员中心计数。
二、前台开关上下文注入
BaseIndexController::getCommonAssigns()统一注入shop_enabled、shop_stock_enabled、payment_enabled,覆盖首页、栏目页、会员中心、商城与支付等全部前台控制器。预约插件的前台入口不经过该基类,已在
addons/appointment/controller/User.php的initialize()中显式注入同名变量,保证预约页也能读到开关。
三、库存校验收口
CartService::isEnabled()判定商城是否开放,CartService::isStockEnabled()判定是否启用库存校验。加入购物车、修改数量、结算、下单扣减库存统一走该判定,关闭库存管理后不再因库存字段为 0 而拦截下单。
四、支付开关控制全部支付入口
PaymentService::isEnabled()统一判定支付开关,兼容basic分组已保存的值与config/payment.php兜底。前台模板按
payment_enabled门控:「立即支付」「去付款」按钮、下单成功后跳转支付页等入口在关闭时自动隐藏,取消订单、取消预约等非支付操作保留。Pay::order()增加兜底守卫,支付关闭时即使直接访问支付地址也返回「支付功能暂未开启」,Pay::doPay()同样拦截。商城订单支付链接需带
type=shop,与预约支付区分。
五、会员中心与后台菜单联动
会员中心商城菜单、待付款订单计数按商城开关显隐,避免关闭商城后仍出现死链入口。
后台商城菜单由
AdminService::getMenuTree()按同一开关过滤。
六、升级说明
无数据库结构变更。
若此前在数据库中手动保存过错误分组(
shop)的开关记录,请在后台「商城设置」重新保存一次,使配置归入basic分组。
v2.8.4 地区三级联动数据源切换
版本:v2.8.4
发布日期:2026-10-19
本期聚焦地区三级联动数据源切换:会员地址、后台地区管理与接口三端统一读取本地地区表,不再依赖外部接口。
一、数据源切换到后台地区管理
Shop::getRegionData()重写为读取pr_region表(status = 1),按parent_code懒加载,排序规则为sort升序、code升序。不再代理外部民政部接口,不再写
runtime/cache/region文件缓存,消除外网依赖与缓存不一致问题。
二、返回结构与前端零改动
省级请求(
code为空):返回省级列表,每项含code、name、type。市级请求(
code为省级编码):返回该省下城市,每项再嵌套区县列表。直辖市:跳过「市辖区」中间层,直接返回区县,
type标记为「直辖市」。孙级数据一次查询后按
parent_code分组装配,避免逐条查询造成的 N+1 开销。港澳台等二级即末级的地区,前端按「直筒子市」兜底(城市名即区县名),表单可正常保存。
三、三端统一
后台「地区管理」(
admin/Region)与会员接口api/Member::region、前台地址编辑页现在读取同一张表、同一套编码,避免省市县名称与编码错位。地址表单的地区弹窗交互与校验逻辑保持不变。
四、升级说明
无数据库结构变更,但要求
pr_region已有数据(后台「地区管理」可一键导入省份/城市/区县)。若地区表为空,地址选择将无数据,请先在后台完成导入。
v2.8.5 主题模板管理重构(配置 / 预览 / 截图分离)
版本:v2.8.5
发布日期:2026-10-19
本期聚焦主题模板管理重构:主题配置与主题预览拆分为独立页面,缩略图与预览图彻底分离,模板改为目录扫描自动识别。
一、页面结构拆分
主题列表页
views/decorate/index.vue只保留「应用、预览、配置、导出、删除」等核心操作。新增独立主题配置页
views/decorate/themeConfig.vue(路由template/config),表单由主题theme.json中的config描述动态渲染,支持select、radio、switch、textarea、text等控件。新增独立主题预览页
views/decorate/themePreview.vue(路由template/preview),展示主题信息、截图轮播与「应用此主题」按钮,预览不再跳转前台。
二、后端接口完善
admin/Template.php新增并完善themeDetail、themeConfig、themeConfigSave:元数据(名称、描述、版本、作者)通过
ThemeService::saveThemeMeta()写回theme.json。配置字段写入
system_config,分组为theme_<主题标识>。switch类型仅在提交值明确为 1 时写库,未提交的字段不覆盖已有值。themeAsset/image路由在鉴权组外公开注册,保证<img src>请求(不带 Bearer 头)可正常加载主题图片。
三、图片命名与存储规范
主题图片统一存放于
public/uploads/template/<主题标识>/。缩略图固定为
cover.<扩展名>,主题卡片与配置页统一读取该文件。预览图为其余图片(
screenshot*等),与缩略图彻底分离,预览页不再重复显示缩略图。上传图片排序规则:
cover优先,其次screenshot主图,其余按文件名升序。删除主题时同步清理其上传目录;主题标识经白名单校验,防止路径穿越。
四、模板安装方式调整
移除「安装模板包」按钮与后端
packInstall方法及对应路由。主题放入
template/目录即被自动扫描识别,无需再走压缩包上传安装。内置 default、enterprise 两套主题的截图已从模板目录迁移至上传目录,
theme.json中的截图字段同步清理。
五、升级说明
无数据库结构变更。
升级后请检查
public/uploads/template/<主题>/cover.*是否存在,缺失时在主题配置页重新上传缩略图。
v2.8.6 通知体系补全(邮件模板 / 事件挂钩)
版本:v2.8.6
发布日期:2026-10-19
本期聚焦通知体系补全:统一邮件模板样式,补齐订单、会员、留言、后台登录与安全告警的发送挂钩点,站内通知与邮件通知同时落库。
一、邮件模板统一
NotificationService统一生成内联样式 HTML 邮件:560px 白色卡片、顶部彩色页头、正文自动换行、底部「系统自动发送」说明。页头颜色按级别区分:普通信息蓝色、成功绿色、警告黄色、需关注橙色、危险红色,便于在邮件列表中快速识别。
邮件正文由
buildEmailTemplate()统一构建,各业务事件只负责传入标题、正文与级别。
二、通知事件挂钩补齐
订单:创建、支付成功、取消、发货四个节点均触发通知。
会员:注册成功、找回密码触发通知。
留言:新留言提交、管理员回复触发通知。
后台:管理员登录触发通知。
安全:安全告警邮件由纯文本改为统一模板,并按危险等级着色。
三、发送链路
邮件通过 PHPMailer 发送,SMTP 参数取自后台「邮箱配置」页(主机、端口、加密方式、账号、授权码、发件人名称)。
每次发送写入
notification_log,站内消息写入notification表,前台会员中心可查看。发送失败不影响主流程,异常仅记录日志,避免阻塞下单与留言提交。
四、事件开关
mail_notify_*共 10 项开关,覆盖订单创建、支付、取消、发货、会员注册、找回密码、留言回复、新留言、安全告警、管理员登录。开关在后台「通知事件」页签统一管理,关闭后该事件不再发送邮件,站内通知不受影响。
五、升级说明
无数据库结构变更。
升级后请在后台「邮箱配置」页发送一封测试邮件,确认 SMTP 可用;再在「通知事件」页按需开启事件。
v2.8.7 在线升级系统(双通道 / 版本链 / 回滚)
版本:v2.8.7
发布日期:2026-10-19
本期聚焦在线升级系统上线:系统升级与插件升级双通道隔离,支持版本链逐级升级、预检、备份回滚、维护模式与进度轮询。
一、版本登记
新增
app/common/Version.php与VersionService,当前版本号存于system_config.app_version,缺失时回落常量并自动补种。升级成功后自动写入新版本号并记入升级历史。
二、双通道隔离
系统升级范围
scope=core,插件升级范围scope=addon:<插件标识>,两条链路的进度文件、升级日志、更新源配置互不覆盖。系统升级记录写
upgrade_log,插件升级记录写独立的addon_upgrade_log表。后台页面同样分离:「系统升级」只处理系统包,「插件管理 → 升级管理」只处理插件包。
三、受保护路径
升级包落地前经过拒绝清单过滤,
template/、public/uploads/、public/static/theme/、addons/、.env、runtime/、vendor/即使出现在包内也不会被写入。被拒绝的路径会记录到升级日志的跳过清单,便于排查。
插件升级只允许写入
addons/<插件标识>/内,越界文件一律拒绝。
四、版本链逐级升级
更新源
feed.json支持versions数组,每项包含version、from_version、changelog、download、sha256。检查更新时按语义化版本排序,定位
from_version等于当前版本的下一级,返回下一版本、下载地址与完整升级路径。后台升级每次仅落地一级:升级完成后自动刷新当前版本与剩余链路,需再次点击升级才会进入下一级,避免一次操作跨越多个版本。
升级包
upgrade.json声明from_version时必须与当前版本一致,禁止跨级跳版本。
五、预检与进度
预检返回包内文件清单,并标注「将覆盖」与「新增」数量、是否包含数据库变更、链路级数。
升级过程分「备份 → 落地 → 数据库迁移 → 收尾 → 写入版本」五步,实时写入进度文件,前端轮询展示。
收尾阶段自动清理
runtime/cache与runtime/temp,并重建文件完整性基线,避免核心文件变化触发误报。
六、备份与回滚
落地前自动备份将被覆盖的文件到
runtime/upgrade_backup/,并记录本次新增文件清单。「升级历史」中最近一次成功的系统升级可逐级回滚:覆盖文件从备份还原,新增文件按清单删除并清理空目录。
数据库变更需人工执行回退脚本,页面已给出提示。
七、维护模式
升级执行期间写入
runtime/.maintenance,前台进入维护状态,后台与接口不受影响。维护标记超过 30 分钟自动失效,避免异常中断导致站点长期不可访问。
八、升级说明
首次访问升级页会自动创建
upgrade_log表并补种在线检查配置。默认关闭在线检查,需在「系统升级 → 更新源设置」中填写
feed.json地址并开启检测。
v2.8.8 插件生态增强(发展历程插件 / 代码生成器)
版本:v2.8.8
发布日期:2026-10-19
本期聚焦插件生态增强:新增发展历程插件,补齐插件代码生成器与插件在线升级支持,统一插件后台列表组件。
一、新增「发展历程」插件
插件标识
timeline,提供后台内容管理(分类与内容)、前台列表页与详情页。注册钩子
timeline_widget,可在任意模板中通过{:hook(’timeline_widget’)}嵌入时间轴组件。注册
list、detail两个模板标签,支持limit、order、id等参数。安装脚本负责建表,卸载脚本负责清理;插件启停后前台组件随钩子加载状态自动显隐。
二、插件代码生成器完善
AddonTemplate::generate()生成的插件骨架包含:config.php、Plugin.php、Install.php、Uninstall.php、Upgrade.php、后台控制器、前台控制器、后台列表与表单页面。生成的
Plugin.php内置钩子方法与标签方法示例,Install.php/Uninstall.php内置建表与删表逻辑。新增的
Upgrade.php用于插件在线升级:核心文件落地后若存在该方法会被自动调用,便于编写幂等的表结构迁移与数据修补。后台控制器改为输出统一表格描述符,由前端
PluginTable渲染,保证所有插件列表样式一致。
三、插件升级通道
插件管理新增升级管理入口,支持配置插件更新源、检查更新、在线升级与升级历史。
插件升级日志写入独立数据表,与系统升级历史完全隔离。
插件包内
upgrade.json支持声明版本、来源版本与升级说明。
四、后台交互优化
插件卡片网格统一视觉规范,图标、版本号、状态标签与操作按钮对齐。
启停插件后同步更新前台导航显示状态,避免插件页面残留死链。
插件静态资源经代理读取,修正路由参数取值方式,解决样式表被当作 HTML 返回的 MIME 报错。
五、升级说明
本版本包含插件目录示例,系统升级不会覆盖
addons/下已有插件,需通过「插件管理」单独上传或升级。启用发展历程插件后,请到「插件管理 → 发展历程 → 插件配置」完成基础设置。
v2.8.9 安全中心强化(Webshell 扫描 / 数据备份 / 错误页)
版本:v2.8.9
发布日期:2026-10-20
本期聚焦安全中心强化与站点健壮性:新增全盘 Webshell 扫描命令、数据库备份管理、目录权限检查,补齐 403/404 错误页与后台登录会话策略。
一、全盘 Webshell 扫描
新增命令行
php think security:webshell,对站点既有 PHP 文件做特征扫描,弥补文件完整性监控只能发现「基线之后变化」的盲区。扫描范围由
webshell_scan_paths配置(默认app,public,template,config,route,extend,view),自动跳过runtime、uploads、storage、vendor、node_modules等目录。脚本按
webshell_scan_min_interval(默认 30 分钟)自行节流,建议由 cron 每小时调用一次。命中文件写入攻击日志(类型
webshell),并推送危险级别安全告警,按文件去重避免重复刷屏。策略开关
webshell_scan_enable默认关闭,需在「安全中心 → 安全策略」开启后生效。
二、安全中心界面重构
仪表盘改为「检测面板 + 模块卡片」结构,模块入口一行三列,卡片含图标、标题、说明与数量徽标。
子模块改为抽屉式加载,支持从 IP 名单等页面跳转到安全策略等关联模块,减少页面往返。
模块覆盖:安全策略、目录权限检查、登录日志、操作日志、攻击日志、IP 黑名单、IP 白名单、文件完整性、数据管理。
三、目录权限检查与修复
新增权限检查接口,逐项核对关键目录的可读写状态并返回明细。
提供「一键修复」,按检查结果纠正目录权限,操作写入操作日志。
四、数据备份管理
新增
DataBackupService:纯 PHP 导出数据库结构与数据,不依赖服务器mysqldump。导出采用分块读取,单批 200 行、每 50 行合并为一条 INSERT,兼顾大表内存占用与导入效率。
备份文件保存于
runtime/data_backup/,该目录在「清除缓存」时按保留规则不会被删除。新增后台「数据管理」:备份列表、立即备份、下载备份、删除备份,文件名经白名单校验,杜绝路径穿越。
五、错误页与请求健壮性
新增 403、404 静态错误页,由异常处理器统一输出,接口路径仍返回标准 JSON,避免前端拿到 HTML。
优化 404 响应头,禁止缓存错误页,防止状态码与内容不一致。
补充
.htaccess与 Nginx 伪静态说明,隐藏敏感文件、拒绝目录遍历。
六、后台登录与会话
登录流程完善失败计数与 IP 锁定判定,失败原因写入登录日志。
新增会话保活接口:保持登录模式下前端定时调用,服务端滑动续期并下发最新会话策略,前端据此启停「无操作退出」。
个人资料页支持修改基本信息与头像,退出登录仅影响当前浏览器,需要强制所有设备下线时由管理员侧触发令牌版本递增。
七、升级说明
无数据库结构变更。
升级后建议执行一次「文件完整性 → 初始化基线」,并在「安全策略」中按需开启全盘 Webshell 扫描。
若需自动扫描,请在服务器计划任务中添加
php think security:webshell。
v2.9.0 升级体系完善(系统单级 / 插件版本链 / 独立备份)
版本:v2.9.0
发布日期:2026-10-20
本期聚焦在线升级体系完善:系统升级改为每次只落地一级、插件升级支持版本链并一键逐级升到最新、插件备份独立目录、升级完成自动清理进度快照、修正插件更新源地址。
一、系统升级:每次只升一级
背景:原逻辑点击一次后会自动把版本链剩余各级连续升完,中途失败难以定位,也不符合逐级确认的发布预期。
现在:一次确认只落地当前这一级(备份 → 落地文件 → 数据库迁移 → 收尾 → 写版本号),完成后自动刷新当前版本、升级历史并重新检查更新,提示「已升级至 X,下一级为 Y,请再次点击升级」,由用户决定是否继续。
预检弹窗新增「升级方式」:版本链共 N 级,本次仅升级 1 级;提示区说明完成后需再次点击进入下一级。
进度弹窗头部由「第 N/M 级」改为「当前版本 → 目标版本」,语义更准确。
升级包
upgrade.json的from_version仍必须与当前版本一致,禁止跨级跳版本。
二、插件升级:版本链 + 一键到最新
更新源
addons.json支持versions数组(每项含version/from_version/download/sha256/changelog),按版本号升序排列。预检时从当前插件版本定位链中下一级(
from_version与当前版本相等),只下载该级的包;sha256以链内声明为准(不再误用顶层「最新版」的哈希);同时校验包内config.php的version与链声明一致。执行成功后返回
next_step(链中from_version等于新版本的下一级),前端据此自动继续:落地 → 预检下一级 → 落地,直到链末——点一次即逐级升到最新版本;每一级独立备份、独立执行该版本自带的Upgrade.php、各记一条升级历史。预检弹窗显示「逐级升级:共 N 级,将自动依次升级到最新」,进度头部显示「第 N/M 级」。
兼容旧清单:不提供
versions时按原单版本逻辑升级;只提供versions而未提供顶层version时,以链尾版本作为最新版。版本链中未提供从当前版本升级的包时,预检明确提示,不会误升。
三、插件备份独立目录
插件升级备份由
runtime/upgrade_backup/addon_<名称>_<时间戳>/迁到独立目录runtime/addon_upgrade_backup/addon_<名称>_<时间戳>/,与系统升级备份(sys_*)彻底分离。升级历史
backup_path同步记录新路径;「清除缓存」的保留规则(任意以backup结尾的目录)自动覆盖新目录,不会被误删。
四、升级完成清理进度快照
系统升级与插件升级成功后,自动删除各自通道的进度文件(
runtime/upgrade_progress.json、runtime/addon_upgrade_progress.json),不再残留过程状态;失败时保留供排查。
五、插件更新源地址修正
插件更新服务器地址由
http://127.0.0.1/addons_update/addons.json改为http://purancms/addons_update/addons.json(127.0.0.1在该环境返回 404,会导致检查更新失败)。addons.json内各插件的download地址同步修正为同一域名。
六、升级说明
本版本无数据库结构变更。
需要逐级升级的插件,请在
addons.json对应插件项内补versions数组,升级包按addons_update/<插件名>/<包名.zip>存放。插件升级没有自动回滚界面,升级前会自动整目录备份到
runtime/addon_upgrade_backup/,需要时可按目录手工恢复,并把pr_addon.version改回旧版本号。
v2.9.1 权限体系生效与控制台体验重构
版本:v2.9.1
发布日期:2026-10-20
本期聚焦RBAC 权限体系真实生效与后台体验重构:接口级节点鉴权、菜单按权限过滤、权限规则按菜单一键同步;控制台精简重构;顶栏新增留言与安全告警通知图标;并修复文件完整性「文件总数」、内容列表工具栏布局等问题。
一、RBAC 权限体系真实生效(核心)
修复前的问题:后台接口只校验登录态,任何登录账号都可以调用全部 admin/* 接口;「权限规则」页的设置对接口访问与菜单显示没有任何约束;且规则标识与后台菜单/接口路径对不上,大量功能(会员、通知、广告、图片、地区、表单、留言、文档、主题、安全中心等)根本没有规则。
本期改动:
新增
AuthRuleService权限判定中枢
权限位规范:与后台菜单 URL 去掉
/admin后的路径一致,如content/index、system/siteSetting、auth/rule、shop/order-list;接口映射:内置全部后台控制器的「路由 → 权限位」映射,采用最长前缀匹配(
system/admin覆盖system/admin-list、system/admin-kick;shop/order覆盖order-list、order-detail、order-ship);未登记路径与「个人资料 / 心跳 / 菜单 / 上传 / 顶栏徽标计数」等通用能力默认放行;判定规则:超级管理员直接放行 → 权限位精确命中 → 任一级父路径命中(目录授权覆盖子页)→ 模块级命中;
旧规则名归一:
admin/addons、system/config、content/add等旧标识自动映射到新权限位,存量授权数据不失效。
接口节点鉴权:
AdminAuth中间件在登录校验之后增加权限判定,无权限返回 403「无权限访问该功能,请联系超级管理员分配权限」;判权异常只记录日志、不阻断后台使用。菜单按权限过滤:侧边栏由
Menu::index()按权限严格过滤,没有可见后代的目录自动隐藏;未分配角色的账号菜单为空(规则表为空时不过滤,防止把后台锁死)。目录授权自动展开:保存角色时,勾选的目录规则会自动带上全部后代规则,勾了目录就等于授权整个模块。
规则按菜单补种:新增「同步菜单规则」能力,按
pr_admin_menu幂等补齐缺失规则(叶子规则标识 = 菜单路径,目录规则用于分组与一键授权)。本次已由 38 条补齐到 67 条,覆盖全部后台页面。即时生效:禁用某条规则、或从角色中移除授权,对应菜单与接口立即失效,无需重新登录。
二、控制台重构(精简)
移除左侧「实时动态」浮动气泡层(模板、脚本、样式全部清理)。
KPI 卡片由 8 张精简为 6 张:内容(文章 + 产品合并)、会员、订单、订单金额、留言(显示未读数)、访问量;移除「产品」「通知」两张卡。
图表由 7 个精简为 3 个:运营趋势(近 30 天,多线)、订单金额趋势(近 30 天,面积图)、地区访问分布 TOP 10(横向条形);移除订单状态、预约状态、会员等级、访问来源 4 个低信息密度饼图。
同步删除不再使用的代码:饼图分支、
PIE_PALETTE、表格主题变量等;趋势图系列由 6 条线减为 5 条。保留:暗/亮主题切换(localStorage 记忆)、点击卡片跳转对应管理页、30 秒自动刷新、窗口缩放自适应。
三、顶栏留言与安全告警通知
「全屏」按钮后新增两个图标:留言通知(铃铛)与安全告警通知(盾牌 + 对勾内联 SVG),均带红色数字徽标(上限 99,为 0 时自动隐藏,间距已微调)。
留言徽标统计未读留言(新增
GET admin/message/unread-count);安全告警徽标复用既有admin/security/alert-unread。实时联动:查看留言、回复、删除留言、标记告警已读、删除/清空告警后,通过全局事件即时刷新顶栏红点,不再需要刷新页面;同时保留 60 秒轮询与路由变化刷新作为兜底。
留言列表:打开详情后该行就地变为「已处理」,关闭抽屉自动刷新列表,无需手动刷新。
安全中心支持
/security?module=alerts直达「安全告警」抽屉(顶栏盾牌图标即走此地址)。
四、内容列表工具栏重构
对齐门店管理页布局:左侧放「新增 + 批量删除」按钮,右侧放搜索标题、状态筛选、搜索、重置并整体靠右显示。
批量删除的显示条件(全部内容视图或非单页模型)保持不变。
五、文件完整性监控修复
修复「本次扫描结果」中文件总数卡片空白的问题:
FileIntegrityService::scan()返回值新增total(本次实际扫描到的文件数),前端四个统计数字统一增加兜底,扫描成功提示与操作日志同步带上总数。
六、升级说明
本版本无数据库结构变更;权限规则数据已按当前菜单补齐(67 条)。
升级后请到「权限管理 → 权限规则」核对规则,新增过菜单的站点可点「同步菜单规则」一键补齐。
请为各管理员分配角色(「权限管理 → 管理员授权」):未分配角色的非超级管理员账号侧边栏为空、接口返回 403,这是预期行为。
若曾使用旧标识(如
admin/addons、system/config)授权,无需重新配置,已自动兼容。
v2.9.2 会员中心体验与待办优化
一、待办事项(会员中心首页)重构 + 实时刷新
修复前的问题:待办统计存在两类缺陷——「留言新回复」统计所有被回复过的留言、回复后永不消失;「待处理预约」把已完成也算入;且待办为一次性渲染、无实时刷新。
- 新增统一统计方法
getTodoCounts()与 AJAX 接口GET /user/center/todoCounts(返回 JSON,30 秒轮询、切回页面刷新)。 - 留言新回复改为统计「未读回复站内通知」(
notification表type=message AND is_read=0),通知中心阅读后消失、新回复即出现。 - 待付款订单
status=0、待确认收货/已发货status=2保持原口径(付款/取消或确认收货后消失)。 - 待处理预约仅计「待支付预约」(
status=0且price>0且pay_status=0) 与「已确认预约」(status=1);待确认属后台管理员任务、已完成/已取消不计。 - 模板
center.html:留言入口改链通知中心/user/center/notifications?type=message;每条待办加data-todo、空状态加data-todo-empty,前端动态更新与隐藏。 - 路由
route/app.php的user/center组新增todoCountsGET 路由,修复此前 404。
二、预约列表新增「已确认」筛选
Member::appointment()新增confirmed筛选(status=1)。- 模板
appointment_list.html筛选 Tab 在「待确认」后新增「已确认」。
三、移动端 UI 对齐
- 地址页
shop_address.html:新增白色面板.address-panel,卡片加浅灰边框,与订单/预约页一致。 - 预约页
appointment_list.html:移动端「新增预约」按钮缩小并与标题同行居右,PC 端不变。
四、移动端「返回个人中心」悬浮按钮
- 会员中心
layout.html统一新增,覆盖所有子页面;PC 端不显示、主页自身隐藏。 - 默认固定右侧 75% 高度(中间偏下),半透明;点击展开文字、再点跳转;点外部收起。
- 线性人物头像图标,折叠态圆形内居中。
- 长按上下拖拽移动(固定居右、仅垂直),
localStorage记忆,刷新恢复;展开以右缘为锚向左展开、不裁剪。
五、升级说明
- 无数据库结构变更:仅新增/调整文档中心内容与版本日志,小幅调整前端模板与会员中心控制器逻辑。
- 升级后会员中心待办实时刷新,预约列表可筛「已确认」,移动端右下角出现「返回个人中心」悬浮按钮。
v3.0.1 发货快递与物流轨迹查询
一、物流配置
- 接入阿里云云市场物流 API,采用 AppCode 头认证。
- 配置简化为只填一个密钥:内置默认接口地址 wuliu.market.alicloudapi.com/kdi,Endpoint/额外参数/缓存/调试收进高级设置折叠面板。
- SSL 兼容:自动探测 CA,无 CA 时跳过校验(兼容 phpstudy/Windows)。
- 提供连通性测试页。
二、快递公司字典
- 新增表 pr_express_company,支持 CRUD 与 22 家种子。
- Logo 上传到 public/storage/express,前台弹窗展示。
三、前后台轨迹查询
- 订单发货写入 shipping_code,打通后台发货弹窗与物流轨迹抽屉。
- 前台订单详情/列表提供查看物流按钮与弹窗。
四、弹窗体验优化
- 600px 圆角、浅蓝头部、公司 Logo 显示、自定义关闭按钮、复制单号、暂无物流信息。
五、升级说明
- 数据库变更:新增 pr_express_company 表、pr_shop_order.shipping_code 字段、菜单与权限,种子 22 家。
- 本升级包为文档更新包,业务代码已随仓库提供。
v3.0.2 会员资产体系与会员中心重构
一、我的钱包(新增 /user/wallet)
- 余额卡:当前余额、累计充值、累计消费、流水笔数;收支明细三个 Tab(全部/充值记录/消费记录)+ 分页。
- 在线充值:预设 50/100/200/500 + 自定义金额,仅支持微信/支付宝(不允许余额给自己充值);开关 member.recharge_enabled(默认开)。
- WalletService:事务 + 行锁记账,扣减不得为负,写 pr_balance_log(recharge/payment/refund/admin)。
- 余额支付:BalancePayService 乐观锁扣款,开关 payment.payment_balance_enabled;支付页余额不足自动禁用并引导其他方式;退款原路退回余额。
- 后台调整余额:POST /admin/user/balance-adjust(写 admin 流水 + 操作日志)。
二、积分体系增强
- awardConsume:按 consume_rate 发放消费积分,同一订单号幂等。
- revokeConsume:退款按比例扣回(上限=已发放-已扣回,不产生负积分),类型 consume_refund。
- getUserSummary:累计获得/累计消费/明细条数;后台积分明细页支持按会员检索。
- 积分账实校准:移除不写流水的 UserLevelService::addPoints 死代码,补记校准流水。
三、会员等级页重构
- 背景图按容器满铺(外扩裁掉图片自带圆角)+ 均匀暗层与文字阴影;图标 contain 不裁剪。
- 升级进度内联进等级卡:双进度条,分母改为等级要求值(target_points/target_amount),达标显示已达成。
- 权益改半透白胶囊;等级一览新增折扣(X 折)与权益标签。
- 累计消费口径统一:consumeTotal=已支付订单实付-退款,钱包与等级页一致;支付成功自动累计并触发等级升级,退款等额扣减,历史数据已校准。
四、个人中心与个人资料
- 资料卡:用户ID 改雪花 user_no;新增余额/积分金色小卡;头像放大、间距加大;快捷入口新增我的钱包。
- 个人资料页新增只读注册时间。
五、升级说明
- 新表 pr_balance_log;system_config 新增 member.recharge_enabled、payment.payment_balance_enabled、basic.snowflake_worker_id。
- 历史 total_amount 与积分存量已校准;本包为文档更新包,业务代码随仓库提供。
v3.0.3 后台管理增强与商城订单体验
一、后台会员管理
- 用户详情公共抽屉 UserDetailDrawer:会员列表与订单列表共用,资产卡/基本信息/登录概况,更多设置(调余额/调积分/会员设置)。
- 会员列表头像显示修复(有头像即显示);新增会员设置(等级/状态,禁用立即踢下线);余额/积分调整接口。
- 会员等级管理:新增等级背景图列与卡片背景图上传;等级名称列更名;图标 contain 不裁剪。
- 会员设置页新增在线充值开关;后台积分明细页新增退款扣回类型。
二、系统设置与上传
- 配置保存缓存联动:member/points_rule 保存后立即生效。
- 配置页重构:分组排序 + 分区渲染 + 7 个社交平台二维码;SEO 生成工具合并进 SEO 设置页。
- 上传改造:10MB 与扩展名白名单、dir 白名单(images/express/avatar)、自动登记图片素材库。
三、商城订单与物流
- 新增订单操作记录 OrderLogService + pr_shop_order_log,历史缺失阶段自动补全。
- 下单/取消/确认挂钩订单记录与站内信;取消已支付订单自动原路退款。
- 后台订单卡片列表 + 四 Tab 详情抽屉(订单记录/发货记录);物流轨迹抽屉。
- 新增支付流水页与退款审核(同意退款:余额退回 + 库存回滚;驳回回待发货)。
- 前台订单新增已退款状态与查看物流;收货地址省市区三级联动重做(直辖市/直筒子市兼容)。
四、预约闭环
- 预约余额支付(支付即确认)、退款/取消原路退余额 + 积分扣回 + 释放时段库存;懒关闭超时未支付预约。
五、雪花 ID
- SnowflakeService:64 位雪花 + 10 位会员编号 memberNo,注册/后台新增写入 user_no;JSON 输出转字符串防 JS 精度丢失;机器号 basic.snowflake_worker_id。
六、插件表格组件增强
- 数组子表、批次号、二维码下载、CSV 导入、详情弹窗、批量操作、表头防截断等。
七、升级器 SQL 拆句修复(热修)
- 问题:2.9.1 升级 2.9.2 报 1064 语法错误——applyDb 用 explode 按分号拆句,文档内容中的 HTML 实体(>、& 等)自带分号,把 INSERT 从字符串中间切断。
- 修复:applyDb 改状态机安全拆句(单引号字符串含转义、行/块注释感知,只在语句真正结束的分号切分);安装向导 importSql 增加引号配对兜底,字符串未闭合时继续累积。
- 验证:2.8.2 ~ 3.0.3 全部 14 个升级包 SQL 拆分 + PREPARE 语法校验通过;install.sql 283 条语句引号配对通过。修复后 2.9.2 包无需重打包即可重试成功(SQL 幂等)。
八、升级说明
- 新表 pr_shop_order_log;system_config 新增 basic.snowflake_worker_id(缺省 1);后台前端已构建同步至 public/admin。
- 本包为文档更新包,业务代码随仓库提供。
v3.1.0 售后体系与自动确认收货
一、前台申请售后(按订单状态动态显示)
- 未发货订单只显示「申请退款(仅退款)」;已发货订单显示「申请换货 / 退货退款 / 仅退款」三选一。
- 退货退款与换货必须填写退货物流公司与单号;未支付订单不可申请。
- 订单列表/详情新增申请入口与售后信息块:售后处理中、已退款、已换货、已驳回可重新申请。
二、后台「售后订单」(原退款记录)
- 菜单与权限名改为「售后订单」(URL 与权限标识不变)。
- 列表:订单号/用户/商品/实际支付/发起退款时间/售后类型/处理状态/售后原因/售后备注/操作,支持状态、类型、关键字筛选。
- 详情抽屉:售后状态、主订单状态、退款金额、退款件数;Tab 分订单信息、商品信息、订单记录。
- 同意退款:余额支付退回余额并写钱包流水,微信/支付宝按渠道退款,换货不退款;驳回后订单恢复处理。
- 售后备注写入订单操作记录,列表与详情同步回显。
三、自动确认收货
- 后台商城设置新增「自动确认收货(天)」,从发货时间起算,填 0 关闭,默认 7 天。
- 到期后系统自动把「已发货」订单确认为「已完成」,售后处理中的订单跳过。
- 无需定时任务:打开订单列表/详情/售后订单时惰性触发。
四、钱包退款明细
- 退款入账统一走钱包服务记账,修复余额退款不产生流水、钱包看不到退款的问题。
- 钱包新增「退款记录」页签,展示商城与预约的全部退款(含原路退回微信/支付宝),并显示退款来源、渠道、关联订单与退款单号。
五、升级说明
- 数据库:pr_refund_log 增加 refund_type/return_company/return_code/return_time;pr_shop_order 增加 refund_type;system_config 增加 basic.shop_auto_confirm_days;菜单与权限改名。
- public/admin 已重新构建,升级后请强制刷新浏览器缓存。
- 升级器不覆盖 template/ 与 addons/,前台模板与预约插件请使用配套的 web 覆盖包手动上传。
v3.1.1 售后与预约体验修复
一、预约详情操作记录倒序
- 操作记录改为倒序显示,最近的记录(如退款成功、系统标记已过期)排在最上方。
- 会员 API 同步返回倒序日志。
二、预约可删除范围扩大
- 已取消 / 已完成 / 已过期(含已退款)的预约均可删除,进行中的预约不可删。
- 删除时同时清理该预约的操作日志,删除后不可恢复。
三、售后订单补齐历史退款订单
- 旧版本直接在订单上标记「已退款」而没有售后单,导致售后订单列表查不到对应记录。
- 现在售后订单列表会同时合并「售后退款单」与「订单表中已退款/售后中但无售后单」的订单,并按时间倒序展示。
- 历史退款订单同样可以打开详情抽屉、填写售后备注。
四、升级说明
- 本期无表结构变更,仅补齐 basic.shop_auto_confirm_days 配置(默认 7 天)。
- public/admin 已重新构建,升级后请强制刷新浏览器缓存。
- 升级器不覆盖 template/,前台预约模板请使用配套的 web 覆盖包手动上传。
v3.1.2 图片引用检测与后台体验优化
一、图片素材引用检测重写
- 旧版只扫描「列名像图片」的字段(image/thumb/url 等),导致会员等级图标 icon_url、等级背景图 card_bg_url、订单商品图 product_image 等明明在用的图片没有「已引用」标签;现在改为逐表扫描所有字符串 / 文本 / JSON 列,只跳过日志表、地区库与素材表自身。
- 改用带前后边界的正则精确匹配(5.png 不再命中 15.png),并支持 JSON 转义斜杠与 URL 编码的中文文件名。
- 引用来源扩展到前台模板 template/、插件源码 addons/、前台主题静态资源 public/static/index 与 theme,鼠标悬停即可看到命中位置(如「会员等级.icon_url」「前台模板(index/home.html)」)。
- 性能:表结构改为一次 information_schema 查询,匹配前先用文件名锚点预筛,54 张图片全库扫描约 0.4 秒。
二、引用状态实时显示
- 素材卡片同时显示「已引用」(绿色)与「未引用」(灰色)标签。
- 工具栏新增「刷新引用状态」按钮与「更新于 HH:mm:ss」提示;页面可见时每 30 秒自动重检,切回标签页、上传 / 编辑 / 删除后即时重检。
- 删除已引用图片时,确认框会列出引用来源,避免误删。
三、顶栏升级图标实时「更新」标签
- 有新版时顶栏升级图标右上角显示红色「更新」,无新版自动隐藏。
- 进入后台立即检测,之后每 60 秒轮询,切回标签页或窗口重新聚焦时补检;不再依赖进入更新管理页面才刷新。
- 与「发现新版本」弹窗的 6 小时节流完全解耦;升级完成后标签立即消失。
四、其他
- 移除「升级历史」页签右上角冗余的「刷新」按钮。
- 本期无表结构变更,升级后请强制刷新浏览器缓存(Ctrl + F5)。
v3.1.3 会员签到中心
一、签到中心
- 会员中心新增「每日签到」入口(资料卡按钮 + 快捷入口角标),签到页地址 /user/center/sign。
- 签到页含积分卡片(当前积分、连续签到、本月已签、累计签到)、按月签到日历(可翻看历史月份、不可翻到未来)、最近签到记录与签到规则。
- 签到按钮提交后即时更新数据、插入记录并给当天打勾,移动端自适应布局。
二、签到规则
- 每次签到发放签到积分(后台「会员设置 → 积分规则 → 签到积分」配置,0 表示关闭签到)。
- 频次支持「每日一次」与「仅一次」,后台为下拉选择。
- 签到积分计入积分明细并触发会员等级检查。
- 并发安全:事务内锁定用户行并二次判定,同一账号不会重复发分。
三、连续签到奖励
- 连续签到每满 N 天额外奖励积分,第 N、2N、3N 天各发放一次。
- 奖励单独记入积分明细(类型「连续签到奖励」),不影响签到天数统计。
- 签到页展示距下次奖励还差的天数,签到成功提示包含额外奖励金额。
- 后台可配置门槛天数与奖励积分,任一项为 0 即关闭。
四、升级说明
- 本期无新增数据表,仅新增两条积分规则配置(连续签到天数默认 7、奖励积分默认 20)。
- 本期新增前台模板,需同时覆盖 web 包(template 目录),否则签到中心页不可用。
- 升级后请强制刷新浏览器缓存(Ctrl + F5)。
v3.1.4 积分商城
一、会员端积分商城
- 会员中心「我的服务」新增兑换记录、优惠券入口,插件停用后自动隐藏。
- 积分商城页含兑换商品、我的兑换、我的优惠券三个标签,支持实物与优惠券两类商品。
- 我的积分 → 积分兑换标签直接展示兑换商品,与独立商城页数据一致。
二、兑换流程
- 实物兑换需填写收件信息,扣积分扣库存后生成兑换订单(待发货)。
- 优惠券兑换即时发放满减券,可在商城结算页选择抵扣现金。
- 后台插件「积分商城」可管理兑换商品、查看兑换订单、发货并查看物流轨迹。
- 会员可查看兑换记录详情、物流轨迹并确认收货。
三、优惠券结算
- 结算页自动拉取本单可用优惠券(按面额降序),默认选中面额最大一张,可切换或选择不使用。
- 下单时在订单事务内二次校验并核销优惠券,核销失败整单回滚。
- 订单取消或超时关闭时自动退回优惠券,已过期则标记为已过期。
- 抵扣后实付为 0 的订单直接标记支付成功。
四、升级说明
- 本期新增三张积分商城业务表,并为商城订单增加 coupon_id 字段(升级 SQL 幂等)。
- 插件本体(addons/points_mall)不在核心包内,需单独部署后在后台「插件管理」安装。
- 本期新增前台模板,需同时覆盖 web 包,否则积分商城页面不可用。
- 升级后请清除后台缓存并强制刷新浏览器(Ctrl + F5)。
