# DuihaoCMS
**Repository Path**: duihao/duihaocms
## Basic Information
- **Project Name**: DuihaoCMS
- **Description**: > 基于 PHP 8 原生的轻量级网站内容管理系统
> 单入口 · 双库兼容 · 动态 + 页面缓存 · 零依赖
> 项目由借助AI平台WorkBuddy零写代码完成
> AI友好 天然衔接AI 可作为基础标准框架 使用AI进行维护
> 已上架WorkBuddy 技能中心
- **Primary Language**: PHP
- **License**: MIT
- **Default Branch**: main
- **Homepage**: None
- **GVP Project**: No
## Statistics
- **Stars**: 0
- **Forks**: 0
- **Created**: 2026-10-05
- **Last Updated**: 2026-10-12
## Categories & Tags
**Categories**: Uncategorized
**Tags**: None
## README
# DuihaoCMS
> 一套**为 AI 建站而生**的 PHP 8 原生企业站内容管理系统
> 单入口 · 双库兼容 · 动态 + 页面缓存 · 零依赖 · **MIT 开源**
**对号开源计划 Jo! 家族成员** —— 开源代号 **JoCMS**,对号建网系统软件(软著号:2008SRBJ1048)的**单站轻量版本**,来自对号建网 **20 年智能建站服务经验与思想在 AI 时代的新实践**。
> 💡 **推荐**:完整 AI 建站服务亦可进入对号建网官网 [DUIHAO.NET](http://www.duihao.net) 购买。
## 🚀 快速体验(demo 分支,开箱即用)
`main` 分支是**纯产品代码**(克隆后走安装向导从零建站);想**直接看到一个配置完整的真实站点**,
请切到 **`demo` 分支**——里面预置了清洗后的演示数据库、全部演示图片视频与可用配置,**克隆即可访问**:
```bash
git clone -b demo https://gitee.com/duihao/duihaocms.git duihaocms-demo
# Web 站点根指向 duihaocms-demo,浏览器打开即可
# 后台 /admin · 账号 admin · 密码 demo123456
```
demo 分支内置内容:15 栏目 / 55 条内容(软件产品详情页含架构图、软著、典型案例)/ 11 个招聘岗位 +
简历投递表单 / 15 种页面区块。**敏感信息已全部清空**(SMTP、地图 Key、备案号),仅用于演示。
详细说明见 demo 分支的 [docs/演示包README.md](https://gitee.com/duihao/duihaocms/blob/demo/docs/演示包README.md)。
## 🤖 为 AI 建站而生的「无缝衔接」
DuihaoCMS **完全从零基于 AI 平台 WorkBuddy 原生打造**——不是"事后加了几个 AI 功能"的传统 CMS,
而是**架构层面就为 AI 交互优化**过的系统。这让它天然更适合基于 AI 的建站交互能力:
- **AI 写得出** —— 全部原生 PHP 8 + 纯函数式模型,无框架魔法、无 Composer 依赖树,AI 一眼看懂上下文,改得准、改得对
- **AI 说得清** —— 内容类型、扩展字段、模板映射全部**单一数据源**收口(如 `content_extra_schema()`),AI 只改一处即全链路生效,不必跨十几个文件拼装
- **AI 验得了** —— 内置自动迁移(版本门控、幂等)、`debug=true` 页面直印告警、`X-Cache` 响应头可观测,AI 能自己做完改完就自测
- **AI 落得快** —— 独创**站点配置包**(`duihao.site.pack`):AI 按规范输出一份 JSON → 后台一键落地成完整站点骨架(栏目树 / 扩展字段 / 询盘表单 / 占位内容),**先干跑预览、再确认导入、可事务回滚**
- **AI 有全套上下文** —— 项目**附赠 AI 生成全过程文档包**(`docs/`):完整技术方案、数据库设计、配置包规范、可视化总览,**直接扔给 AI 即可重新生成一套完整代码**,也便于 AI 续写与二次开发
> 💡 **一句话**:把 `docs/` 连同源码交给 AI,你就能拿到一套可运行、可迁移、可继续迭代的完整 CMS。
## 📜 源码授权(MIT)
本项目采用 **MIT 协议**开源,**任何个人、商业组织均可免费使用**(含商用、修改、分发、二次销售),
唯一要求是保留原始版权声明。详见 [LICENSE](LICENSE)。
```
Copyright (c) 2026 北京对号科技有限责任公司
Author: 对号东-刘亚东 Email: lyd@duihao.com
```
## 🗂️ 附赠:AI 生成全过程文件
`docs/` 目录保留了本项目由 AI 生成的**全过程产物**——方案、设计、规范、示例一应俱全。
它既是项目文档,也是**给 AI 的完整上下文素材**:
| 文件 | 用途 |
|---|---|
| [项目方案.md](docs/项目方案.md) | 完整技术方案(15 章),决策依据与边界 |
| [项目方案总览.html](docs/项目方案总览.html) | 可视化总览,浏览器直接打开 |
| [数据库设计.md](docs/数据库设计.md) | 7 表双库建表说明 + 设计要点 |
| [配置包规范.md](docs/配置包规范.md) | 配置包格式规范(含给 AI 的提示词骨架) |
| [配置包示例.json](docs/配置包示例.json) | 可直接导入的示例包 |
**用法**:把这些文件交给 AI,配合一句"按这份方案和规范,帮我生成/改造一套 DuihaoCMS",
即可从零复刻或按需定制——这正是本项目「AI 原生」设计想要达到的效果。
---
## 项目信息
| 项 | 值 |
|---|---|
| **项目名** | DuihaoCMS |
| **开源代号** | JoCMS(对号开源计划 Jo! · 单站轻量版) |
| **项目来源** | 对号建网系统软件(软著号:2008SRBJ1048)单站轻量版 · 对号建网 20 年智能建站服务经验在 AI 时代的新实践 |
| **本地路径** | `E:\wwwroot\duihaocms` |
| **技术栈** | PHP 8 原生 + PDO + SQLite/MySQL + Tailwind CSS |
| **授权** | MIT(个人 / 商业组织均可免费使用) |
| **版本** | v1.0(已实测交付) |
---
## 部署路径约定
本项目代码固定放在 `E:\wwwroot\duihaocms`,对应的 Web 配置:
### Nginx(推荐)
仓库已提供可直接复制的完整示例 **`nginx.conf.example`**(含敏感目录保护 / 上传禁执行 / 静态缓存)。下面是最小骨架:
```nginx
server {
listen 80;
server_name your-domain.com;
root E:/wwwroot/duihaocms;
index index.php;
# 单入口 rewrite
location / {
try_files $uri $uri/ /index.php?$query_string;
}
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;
}
# ── 敏感目录保护 ──
location ~ ^/(data|cache|backups)/ { deny all; }
location ~ \.(db|db-wal|db-shm|sqlite)$ { deny all; }
# ── 主题目录:只放行静态资源(theme.css / 图片 / 字体)──
# themes/ 下的 .php 一律拒绝「直接执行」:它们是给引擎 include 的模板,
# 直接访问会因缺变量而报错,也可能把模板源码片段暴露出来。
location ~ ^/themes/.*\.php$ { deny all; }
location ~ ^/themes/.*\.(json|md|txt)$ { deny all; }
# ── 上传目录禁止执行 PHP ──
location /uploads/ {
location ~ \.php$ { deny all; }
}
# ── 静态资源缓存 ──
location /assets/ {
expires 1y;
add_header Cache-Control "public, immutable";
gzip_static on;
}
}
```
### Apache
```apache
ServerName your-domain.com
DocumentRoot "E:/wwwroot/duihaocms"
AllowOverride All
Require all granted
```
配合根目录 `.htaccess`(**已随仓库提供,开箱即用**):
它已包含全部规则 —— 伪静态(单入口)、敏感目录 403(`data/ app/ cache/ install/ backups/ src/ docs/` 及 `.git` 等)、敏感文件禁止下载(`.db` / `.secret` / `.lock` / `.md` …)、`config.php` 保护,以及 `Options -Indexes`。**无需手动粘贴任何规则**,只要保证上面的 `AllowOverride All` 即可。
> ⚠️ 若整站返回 500,说明主机未开放 `AllowOverride` —— 请改为在 vhost / 主机面板里配置,或删除根 `.htaccess`。
> ⚠️ 各敏感目录另有各自的 `.htaccess` 作为纵深防御,即使根规则被忽略也仍然生效。
> ⚠️ `php -S`(PHP 内置服务器)不读取 `.htaccess`,本地开发预览不受保护,**请勿用它对外服务**。
---
## 目录结构
```
duihaocms/
├── index.php # 唯一入口
├── config.php # 配置(driver / 路径 / 缓存开关 / 密钥)
├── install.php # 安装向导(装完即删)
├── install/ # 安装期专属代码(装完即删,运行时不加载)
│ ├── db_install.php # 安装引导(建表 + 种子)
│ ├── schema.sqlite.php # SQLite 建表语句
│ ├── schema.mysql.php # MySQL 建表语句
│ └── seed.php # 初始数据填充
├── LICENSE # MIT 开源协议
├── .htaccess # Apache 配置(伪静态 + 敏感目录 / 文件保护,开箱即用)
├── nginx.conf.example # nginx 站点配置示例(含同等保护规则)
│
├── app/ # 核心运行时
│ ├── bootstrap.php # 初始化
│ ├── db.php # PDO 工厂 + 方言适配
│ ├── router.php / routes.php# 路由
│ ├── auth.php # 认证 / CSRF
│ ├── helpers.php # 工具函数
│ ├── cache.php # 页面缓存
│ ├── upload.php # 上传
│ ├── sanitize.php # HTML 过滤
│ ├── models/ # 数据访问层
│ ├── pack.php # 站点配置包(导入 / 导出 / 示例)
│ ├── theme.php # 主题引擎(清单 / 令牌 / 回退链 / 模板路径出口 theme_file())
│ ├── theme_lint.php # 主题静态体检(L1~L16)+ 桩数据试渲染(S0~S6)
│ ├── theme_pack.php # 主题包 duihao.theme.v1(导入 / 导出 / AI 提示词)
│ ├── components.php # 前台组件库 dh_*(卡片 / 首屏 / 分页 / 字段 / 表单…)
│ ├── admin/ # 后台控制器
│ └── front/ # 前台控制器
│
├── themes/ # ★ 前台主题(一目录一主题;禁 Web 执行 PHP)
│ ├── default/ # 基准主题(前台模板唯一真源)
│ │ ├── theme.json # 清单:templates(32)+ tokens(6)+ assets
│ │ ├── layout.php # 前台骨架
│ │ ├── partials/ # 组件(nav / footer / page-header / form-fields…)
│ │ ├── categorys/ # 栏目页模板(列表 list-* + 单页 page*)
│ │ ├── details/ # 详情页模板(detail-*,按内容类型)
│ │ └── blocks/ # 区块模板(15 种)
│ ├── example-cards/ # 参考实现:只用 dh_* 组件写列表 + 详情
│ └── example-minimal/ # 参考实现:只覆写令牌与 theme.css,不写模板
│
├── templates/ # 模板(**只剩后台**)
│ ├── admin-layout.php # 后台骨架
│ └── admin/ # 后台页面
│ └── partials/ # 后台组件(media-picker / extra-fields / mirror-form-fields 镜像副本)
│
├── assets/ # 静态资源
│ ├── app.css # Tailwind 构建产物(preflight + 原子类;已编译随仓库分发,零 Node 依赖)
│ ├── dh-core.css # ★ 前台核心样式(**手写源**:令牌默认值 / .prose-dh / .dh-* 组件 / 关键帧)——永不编译,引擎只在前台注入
│ ├── admin.css # ★ 后台专属样式(**手写源**:栏目树 / 折叠区…)——永不编译,仅 admin-layout.php 引入
│ ├── app.js
│ └── wangeditor.js / .css
│
├── src/input.css # Tailwind 构建源(只剩 @import / @source / @theme 声明)
├── uploads/ # 用户上传(禁执行 PHP)
├── data/ # 数据库(禁 Web 访问)
├── cache/ # 页面缓存(禁 Web 访问)
├── backups/ # 备份
└── docs/ # 文档
├── 项目方案.md
├── 项目方案总览.html
├── 数据库设计.md
├── 配置包规范.md # duihao.site.pack v1 规范(给 AI / 人看)
├── 配置包示例.json # 可直接导入的示例包
└── 主题包规范.md # duihao.theme.v1 规范 + AI 提示词
```
> **前台模板去哪了**:`themes/<当前主题>/`。模板路径**只能**通过 `theme_file('相对路径')`
> 拼接(4 级回退:当前主题 → 父主题 → `default` → `templates/`),`templates/` 已不参与前台渲染,
> 后台**零跨界**引用主题目录(开发环境由本地守卫脚本校验 I1~I5)。
---
## 环境要求
| 项 | 要求 |
|---|---|
| PHP | 8.0+(推荐 8.3) |
| 扩展 | PDO、pdo_sqlite(或 pdo_mysql)、fileinfo、mbstring、gd(可选) |
| Web 服务器 | Nginx / Apache(需 rewrite) |
| 数据库 | SQLite(内置,默认)或 MySQL 5.7+ |
---
## 安装步骤
1. 把代码放到 `E:\wwwroot\duihaocms`
2. 配置 Web 服务器(见上方 Nginx/Apache 配置)
3. 确保 `data/`、`cache/`、`uploads/` 可写
4. 浏览器访问 `http://your-domain/install.php`
5. 填写数据库信息 + 管理员账号,完成安装
6. **删除 `install.php` 和 `install/` 目录**
> **安装期生成物**:向导会在运行时写入 `config.php`、`data/install.lock`、`data/.schema_version`。
> 这三项已在 `.gitignore` 中排除,**不要提交回仓库** —— 否则从仓库克隆出来的站点会被直接判定为
> 「已安装」:`index.php` 不再引导安装向导,且 `migrate_run()` 认为版本已是最新而**跳过全部迁移**。
> 因此克隆后直接访问站点,会自动 302 跳转到安装向导(该路径已实测)。
---
## 前端样式(CSS 编译说明)
**CSS 编译是「非必须」的** —— 仓库已附带两份样式,部署和运行**零 Node 依赖**:
拿到代码即可直接上线,**无需 `npm install`、无需任何构建步骤**。
| 文件 | 大小 | 性质 | 何时重建 |
|---|---|---|---|
| `assets/app.css` | ≈66 KB | Tailwind v4 产物(preflight + 原子类) | **仅当**页面里用了产物中**没有**的新原子类 |
| `assets/dh-core.css` | ≈34 KB | **手写源·前台**:令牌默认值 / `.prose-dh` 正文排版 / `.dh-*` 组件 / 关键帧 | **永不** —— 直接编辑、直接提交 |
| `assets/admin.css` | ≈3 KB | **手写源·后台**:栏目树 `.cat-tree` / 折叠区 `.dh-fold` | **永不** —— 直接编辑、直接提交 |
**两份手写样式的分工**:`dh-core.css` 由引擎只在前台注入(不随主题切换、不进后台);
`admin.css` 只由 `templates/admin-layout.php` 引入(前台不引、不参与 `--dh-*` 令牌)。
⚠️ 后台**不要**引 `dh-core.css` —— 它是无 `@layer` 的裸样式,优先级高于 `app.css` 的一切
`@layer`,引入会把后台的 Tailwind 样式整体压掉。后台手写样式一律进 `admin.css`。
### 想改前端样式?三条路都不用编译
| 想改什么 | 改哪 |
|---|---|
| 换颜色 / 圆角 / 内容宽度 | 后台「外观主题」的设计令牌,或主题 `theme.json` 的 `tokens` |
| 版式 / 组件外观 / 正文排版 | 主题自带的 `theme.css`,或 `assets/dh-core.css` |
| 想用**产物里没有的新 Tailwind 类** | 只能重编译一次(见下节) |
前台 `
` 的加载顺序固定为 `app.css → 令牌 → dh-core.css → 主题 theme.css`,**后者覆盖前者**。
其中令牌、`dh-core.css`、主题 `theme.css` 由引擎统一注入 —— **主题模板不需要、也不应自己写 ``**。
### 什么时候才需要编译
Tailwind 按**源码扫描**生成 CSS(扫描范围见 `src/input.css` 的 `@source` 声明:
`templates/`、**`themes/`**、`app/`、`assets/app.js`、`index.php`、`install.php`),
只有页面里真实出现的类名才会进产物。因此:
- **需要重新编译**:页面(前台主题模板 / 后台页面)里**新增了产物中没有的原子类**
- **完全不用编译**:改 `assets/dh-core.css`、改主题 `theme.css`、调令牌、改 PHP 业务逻辑、后台发内容、换数据库
编译完成后,把新的 `assets/app.css` 随代码一起提交 / 发布即可——**线上服务器依旧不需要 Node**。
### 编译命令(仅开发者需要,本机需 Node.js 20+)
```bash
npm install # 首次安装构建依赖(仅 2 个 devDependencies,不进生产)
npx @tailwindcss/cli -i src/input.css -o assets/app.css --minify
```
> 💡 **验证小技巧**:重建后可先 `grep "目标类名" assets/app.css` 确认新类名已进产物
> (注意 CSS 里类名中的 `:` 会被转义成 `\:`,如 `lg\:pl-6`)。
>
> ⚠️ **铁律**:模板里的 Tailwind 类名必须写**完整字面量**(禁止 `text-{$color}` 这类运行时拼接),
> 否则 Tailwind 扫描不到,该类名不会出现在编译产物里。
>
> ⛔ **`assets/dh-core.css` 不要挪进主题目录**(`themes/*/theme.css`):`theme_asset()` 沿主题链
> **只取首个命中**,子主题只要自带 `theme.css`,核心样式就被**整份遮蔽**(卡片 / 按钮 / 正文排版全丢,且不报错)。
> 它由 `theme_head_inject()` 引擎注入,**放在 `assets/` 下就对了**,不需要任何主题去引它。
---
## 站点配置包(AI 一键建站)
这是 DuihaoCMS「AI 原生」设计的核心落地能力:后台「站点配置包」(`/admin/pack`)支持把一份 JSON 直接落成一个可用的站点骨架——**AI 说得出结构,系统就落得了地**。
```
AI 按规范输出 JSON → 后台上传 / 粘贴 → 预览计划(干跑,不写库) → 确认导入
栏目树(含栏目扩展字段 / SEO / 导航 / 排序)
内容类型扩展字段与显示名
询盘表单及其字段
占位内容(一律草稿)
```
**包格式**:`duihao.site.pack` v1,规范见 [docs/配置包规范.md](docs/配置包规范.md),示例见 [docs/配置包示例.json](docs/配置包示例.json)(也可在后台直接「下载示例包」)。
**安全边界(设计原则)**:
- **只增不删** —— 绝不删除栏目 / 内容 / 表单,也不覆盖内容正文
- **先看后做** —— 导入前先出「计划表」,看清新建 / 更新 / 跳过哪些条目
- **可回滚** —— 真实导入整体包在数据库事务里,任一步异常全部回退
- **幂等** —— 同一份包重复导入不会产生重复栏目
- **不落盘** —— 上传 / 粘贴的包只在内存解析,不写进 Web 目录
- **白名单** —— 只能导入 5 项站点设置,改不了缓存开关等运行时配置
**导出**:同一入口可把当前站点反推成配置包(默认只导结构,勾选后含内容正文,用于整站迁移)。
---
## 开发进度(全部完成 ✅)
| 模块 | 状态 |
|---|---|
| 完整方案设计 | ✅ 定稿 |
| 双库建表 SQL | ✅ 完成并实测 |
| 种子数据 + 安装引导 | ✅ 完成并实测(全新安装冒烟通过) |
| 项目目录骨架 | ✅ 完成 |
| 核心运行时(bootstrap/db/router/cache) | ✅ 完成并实测 |
| 数据模型层(models) | ✅ 完成并实测 |
| 后台功能(内容/栏目/表单/留言/文件/设置/用户) | ✅ 完成并实测 |
| 前台渲染 + 模板(区块式布局) | ✅ 完成并实测 |
| Tailwind 构建流程(v4 CLI)+ 核心样式拆出 `dh-core.css` | ✅ 完成 |
| 全流程调试(CRUD/缓存联动/安全/视觉截图) | ✅ 完成 |
| 站点配置包(导入/导出/干跑预览/事务回滚) | ✅ 完成并实测 |
| 多主题体系(`themes/` · `theme.json` · 设计令牌 `--dh-*`) | ✅ 完成并实测 |
| 前台组件库 `dh_*` | ✅ 完成(19 个函数 + 参考主题) |
| 主题包(导入/导出/静态体检/桩数据试渲染/回滚) | ✅ 完成并实测 |
| 后台令牌实时预览(同源 iframe,未保存即生效) | ✅ 完成并实测 |
### 实测验证清单
- 安装向导:环境检测 → SQLite/MySQL 切换 → 管理员创建 → config.php 生成 → install.lock
- **双库全流程实测**:同一套代码分别全新安装到 SQLite 与 MySQL(MariaDB 10.11),7 表建表、种子数据、登录、CRUD、缓存联动、表单提交全部通过;utf8mb4 中文 + emoji(🚀🎉)MySQL 写读完整
- 登录安全:CSRF + 算术验证码 + 登录限流 + password_hash(bcrypt)
- 内容管理:新建/编辑/删除文章,slug 自动生成,状态/置顶;**修改密码闭环**(编辑用户时留空不改、填了即更新,新密码登录实测通过)
- 缓存主线:内容一变缓存全清(HIT → 写操作 → MISS 已实测),手动清理,开关切换(OFF)
- 表单系统:自定义字段(6 种类型)→ 前台提交 → 服务端校验(必填/邮箱/长度)→ 留言管理(未读角标/标记已读/删除)
- 文件上传:扩展名白名单 + MIME 校验 + 强制重命名,.php 上传被拒;AJAX 上传回填封面
- XSS 防护:`