diff --git a/README.md b/README.md index 96f2208e8b3afbad3844af33b60f03a33ea43649..bf2dce24b883a68f9bd5959a92e952a1690cdcf3 100644 --- a/README.md +++ b/README.md @@ -1,53 +1,46 @@ -# zhycms -一个基于 Flask 的轻量级内容管理系统,内置多主题模板引擎、栏目级模板选择、自定义字段、表单收集、SEO 优化等能力,适合搭建企业官网、资讯门户、产品展示站等。 + +# ZhyCMS + +一个基于 Flask 的轻量级企业内容管理系统,内置多主题模板引擎、栏目级模板选择、自定义字段、表单收集、SEO 优化等能力,适合搭建企业官网、资讯门户、产品展示站等。 ## 特性一览 -- **多主题模板系统**:前台模板按主题组织,后台一键切换,主题之间互不影响。内置 `default`、`blue` 两套通用聚合主题,以及 `manufacturing`(制造业)、`service`(服务业)两套行业专用主题 -- **演示数据一键生成**:初始化时可选择「制造业」或「服务业」示例,自动生成配套栏目、文章、碎片、友情链接与演示图片,并切换到对应行业主题 -- **CMS 标识与企业标识分离**:后台 CMS 名称/版权固定不可改,前台网站名称/版权可独立配置(详见下文「CMS 标识与网站标识」) -- **栏目级模板选择**:每个栏目可指定独立的列表页/内容页/单页模板,未指定自动回退默认 -- **自定义字段**:栏目和文章支持自定义字段(文本/富文本/图片/文件/URL/数字等) -- **表单收集**:可视化表单设计,支持文本/手机/邮箱/单选/多选/文件上传,提交数据可导出 -- **SEO 优化**:每个栏目、文章可单独设置 SEO 标题/关键词/描述 -- **碎片管理**:站点公告、联系方式、二维码等内容可后台维护,模板任意调用 -- **友情链接**:后台管理,前台侧边栏自动展示 -- **图片上传**:内置图片压缩、水印、格式校验、大小限制 -- **验证码登录**:后台登录带图形验证码 -- **可自定义后台路由**:后台访问前缀默认 `admin`,可在「系统设置 → 后台安全」改为任意值,避免后台地址被轻易猜测(详见下文「后台安全(自定义后台路由)」) -- **首次初始化引导**:全新安装自动跳转初始化向导 +- **多主题模板系统**:前台模板按主题组织,后台一键切换。内置 `default`、`blue` 通用聚合主题,以及 `manufacturing`(制造业)、`service`(服务业)两套行业专用主题。 +- **演示数据一键生成**:初始化时可选择「制造业」或「服务业」示例,自动生成配套栏目、文章、碎片、友情链接与演示图片,并切换到对应行业主题。 +- **CMS 标识与企业标识分离**:后台 CMS 名称/版权固定不可改,前台网站名称/版权可独立配置。 +- **栏目级模板选择**:每个栏目可指定独立的列表页/内容页/单页模板,未指定自动回退默认。 +- **自定义字段**:栏目和文章支持自定义字段(文本/富文本/图片/文件/URL/数字等)。 +- **表单收集**:可视化表单设计,支持文本/手机/邮箱/单选/多选/文件上传,提交数据可导出。 +- **SEO 优化**:每个栏目、文章可单独设置 SEO 标题/关键词/描述。 +- **安全加固**:支持自定义后台路由前缀(如 `manage-x8y2`),避免后台地址被轻易猜测。 ## 快速开始 ### 环境要求 - Python 3.9+ -- SQLite(默认,开箱即用)或 MySQL/PostgreSQL +- SQLite(默认)或 MySQL/PostgreSQL ### 安装与运行 ```bash # 克隆代码 -git clone zhycms +git clone https://gitee.com/pollybird/zhycms cd zhycms # 创建虚拟环境 python -m venv .venv source .venv/bin/activate # Windows: .venv\Scripts\activate -# 安装依赖(国内建议使用镜像源加速) -pip install -r requirements.txt -i https://mirrors.aliyun.com/pypi/simple/ -# 清华源:-i https://pypi.tuna.tsinghua.edu.cn/simple +# 安装依赖 +pip install -r requirements.txt # 启动开发服务器 python run.py ``` -> `requirements.txt` 已内置 MySQL 驱动 `PyMySQL` 与 PostgreSQL 驱动 `psycopg2-binary`, -> 初始化时选择对应数据库类型即可,无需额外安装。 - -浏览器访问 [http://127.0.0.1:5000](http://127.0.0.1:5000),首次访问会自动跳转到 `/admin/setup` 初始化向导,按提示设置管理员账号即可。 +浏览器访问 [http://127.0.0.1:5000](http://127.0.0.1:5000),首次访问会自动跳转到 `/admin/setup` 初始化向导。 ### 生产部署 @@ -57,586 +50,84 @@ ZHOCMS_ENV=production ZHOCMS_SECRET_KEY=your-secret python run.py gunicorn -w 4 -b 0.0.0.0:5000 "run:app" ``` -环境变量说明: - -| 变量 | 默认值 | 说明 | -| --- | --- | --- | -| `ZHOCMS_ENV` | `development` | 配置模式:`development` / `production` | -| `ZHOCMS_SECRET_KEY` | 内置默认值 | 会话加密密钥,**生产环境必须修改** | -| `ZHOCMS_DB_URI` | `sqlite:///instance/zhycms.db` | 数据库 URI,可换成 MySQL/PostgreSQL | - ## 目录结构 ``` zhycms/ ├── app/ │ ├── admin/ # 后台模块(栏目、文章、表单、设置等) -│ ├── frontend/ # 前台模块(路由与视图) +│ ├── frontend/ # 前台模块 │ │ └── templates/ -│ │ └── themes/ # ★ 前台主题模板目录 +│ │ └── themes/ # 前台主题模板目录 │ │ ├── default/ # 通用聚合主题 │ │ ├── blue/ # 通用聚合主题(蓝色) -│ │ ├── manufacturing/ # 制造业行业专用主题(产品置顶) -│ │ └── service/ # 服务业行业专用主题(公司介绍置顶) -│ ├── models/ # 数据模型 -│ ├── utils/ # 工具模块(主题、上传、验证码等) -│ ├── static/ # 静态资源(uploads/、admin/) +│ │ ├── manufacturing/ # 制造业专用主题 +│ │ └── service/ # 服务业专用主题 +│ ├── models/ # 数据模型 (Article, Column, User, Setting, etc.) +│ ├── utils/ # 工具模块 (主题、上传、验证码、引导程序等) +│ ├── static/ # 静态资源 (uploads/, admin/) │ ├── __init__.py # 应用工厂 │ ├── config.py # 配置 │ └── extensions.py # 扩展初始化 -├── instance/ # 实例数据(数据库等) +├── instance/ # 实例数据(数据库、配置等) ├── requirements.txt -├── run.py # 启动入口 -└── LICENSE # Apache 2.0 +└── run.py # 启动入口 ``` ---- +## 核心功能详解 -# 演示数据与行业主题 +### 演示数据与行业主题 -首次访问会进入初始化向导 `/admin/setup`,除设置管理员账号外,还可选择是否生成演示数据: +首次访问初始化向导除设置管理员外,可选择生成演示数据: | 选项 | 生成内容 | 自动切换主题 | | --- | --- | --- | -| 不生成 | 仅创建管理员,空站点 | 保持 `default` | -| 制造业 | 精密机械制造企业示例:关于我们、产品中心、新闻中心、联系我们等栏目 + 文章 + 碎片 + 友情链接 + 演示图片 | `manufacturing`(产品置顶) | -| 服务业 | 企业管理咨询公司示例:关于我们、服务项目、行业动态、客户案例、联系我们等栏目 + 文章 + 碎片 + 友情链接 + 演示图片 | `service`(公司介绍置顶) | - -- 演示数据由 [app/utils/bootstrap.py](app/utils/bootstrap.py) 的 `generate_demo_data(industry)` 生成,制造业调用 `_generate_manufacturing_demo()`,服务业调用 `_generate_service_demo()`。 -- 每次生成会先调用 `_clean_demo_data()` 按外键依赖顺序清理旧的演示数据(表单 → 文章 → 栏目 → 碎片 → 友情链接),因此可在两个行业之间反复切换而不会触发 `slug` 唯一约束冲突。 -- 演示图片位于 `app/static/uploads/demo/`(制造业 `mfg_*`、服务业 `svc_*`),无需联网即可正常展示。 -- 演示数据只写入**前台企业信息**(`site_name`、`site_subtitle`、`footer_copyright`、SEO 等),不会改动后台 CMS 名称与版权。 - ---- - -# CMS 标识与网站标识 - -系统严格区分「CMS 自身标识」与「前台企业标识」四个概念,避免演示数据或用户配置误改后台品牌: - -| 概念 | 显示位置 | 取值来源 | 可否修改 | -| --- | --- | --- | --- | -| **CMS 名称** | 后台顶栏 / 登录页 / 后台页面标题 | `Setting.CMS_NAME` 固定常量 | ❌ 不可改 | -| **后台版权** | 后台底部 | `Setting.CMS_COPYRIGHT` 固定常量 | ❌ 不可改 | -| **网站名称** | 前台导航 / 首页 / 页脚 | `Setting 'site_name'`(企业名称) | ✅ 网站设置可改 | -| **前台版权** | 前台底部 | `Setting 'footer_copyright'`(企业版权) | ✅ 网站设置可改 | - -- 两个 CMS 固定常量定义在 [app/models/setting.py](app/models/setting.py)(`CMS_NAME` / `CMS_COPYRIGHT`),不落库、不受设置或演示数据影响。 -- 应用上下文处理器 [app/__init__.py](app/__init__.py) 将其注入为模板变量 `cms_name` / `cms_copyright`。 -- **约定**:后台模板一律使用 `cms_name` / `cms_copyright`,**不得**读取 `site_settings.site_name` / `site_settings.footer_copyright`(那是前台企业信息);前台模板则相反。 - ---- - -# 后台安全(自定义后台路由) - -后台默认挂载在 `/admin` 前缀下(登录页 `/admin/login`)。固定且众所周知的后台地址容易被扫描器猜测并针对登录页发起暴力破解,因此系统允许管理员将后台路由前缀改为任意自定义值以增强安全性。 - -## 使用方法 - -1. 登录后台,进入 **系统设置 → 后台安全**; -2. 在「后台路由前缀」中填写自定义前缀(如 `manage-x8y2`),保存; -3. **重启服务**后,使用新地址 `/<新前缀>/login` 访问后台,旧地址将失效。 - -前缀规则:仅允许字母、数字、连字符(`-`)、下划线(`_`),长度 2-32 位;不能与前台已占用路径(`column`、`article`、`form`、`search`、`captcha` 等)冲突。 - -## 实现说明 - -- 前缀落盘到 `instance/admin_config.json`(权限 `600`),与数据库配置 `db_config.json` 采用同一套落盘/容错模式(见 [app/utils/admin_prefix.py](app/utils/admin_prefix.py))。 -- 因 Flask 的 `register_blueprint(url_prefix=...)` 只在应用启动时执行一次,运行中**无法热切换**前缀,故修改后**必须重启服务**才能生效。应用启动时 [app/__init__.py](app/__init__.py) 在注册后台蓝本前读取该前缀。 -- 后台所有链接与登录跳转均使用 `url_for('admin.*')` / `url_for('admin_auth.*')` 的 endpoint 名,前缀变化后自动跟随,无需改动任何模板或视图。 - -## 忘记路由怎么办 - -若忘记已设置的后台路由,删除服务器上的 `instance/admin_config.json` 文件并重启服务,即可恢复默认的 `/admin`。 - ---- - -# 模板制作详解 - -zhycms 的前台采用 **多主题 + 栏目级模板** 的双层机制,主题可在网站设置一键切换,栏目可单独指定列表/内容/单页模板。模板基于 Jinja2 + Bootstrap 4。 - -## 1. 主题目录结构 - -所有主题存放在 `app/frontend/templates/themes/` 下,每个主题是一个独立目录,目录名即主题名: - -``` -app/frontend/templates/themes/ -├── default/ # 默认主题(通用聚合) -│ ├── base.html # 基础布局(必须) -│ ├── index.html # 首页(必须) -│ ├── list.html # 列表页默认模板(必须) -│ ├── article.html # 文章详情页默认模板(必须) -│ ├── page.html # 单页默认模板(必须) -│ ├── list_card.html # 卡片式列表(可选,作为栏目备选模板) -│ ├── column_children.html# 父栏目展示子栏目列表的模板 -│ ├── search.html # 搜索结果页 -│ ├── form.html # 表单提交页 -│ ├── form_closed.html # 表单关闭提示页 -│ ├── closed.html # 站点关闭提示页 -│ ├── 404.html # 404 页面 -│ └── 500.html # 500 页面 -├── blue/ # 通用聚合主题(蓝色,同 default 一套模板) -├── manufacturing/ # 制造业行业专用主题(首页产品置顶) -└── service/ # 服务业行业专用主题(首页公司介绍置顶) -``` - -> `default` / `blue` 为通用聚合主题,适配任意站点;`manufacturing` / `service` 为随演示数据配套的行业专用主题,首页布局按行业特点定制(制造业突出产品展示,服务业突出公司介绍)。 - -### 必备模板 - -每个主题至少包含以下文件,否则切换后会出现 404: - -| 文件 | 用途 | 备注 | -| --- | --- | --- | -| `base.html` | 全站基础骨架 | 所有页面通过 `{% extends theme_base %}` 继承 | -| `index.html` | 站点首页 | | -| `list.html` | 列表栏目默认列表页 | 名称固定为 `list` | -| `article.html` | 文章详情默认页 | 名称固定为 `article` | -| `page.html` | 单页栏目默认页 | 名称固定为 `page` | -| `404.html` / `500.html` | 错误页 | | -| `closed.html` | 站点关闭时展示 | | - -### 可选模板(栏目级备选) - -凡以 `list`、`article`、`page` 开头的 `.html` 文件,会**自动**出现在后台栏目编辑页的下拉选项中: - -- `list_xxx.html` → 列表栏目可选用 -- `article_xxx.html` → 文章详情页可选用 -- `page_xxx.html` → 单页栏目可选用 - -例如 `list_card.html`(卡片式列表)、`list_image.html`(纯图片列表)、`article_news.html`(新闻专用详情页)都会被自动识别。 - -### 受保护模板(不会出现在选项中) - -以下文件即使以 `list`/`article`/`page` 开头也不会被列为栏目备选,因为它们是系统级模板: - -`base`、`404`、`500`、`closed`、`form_closed`、`index`、`search`、`column_children`、`form` - -## 2. 创建一个新主题 - -以创建名为 `green` 的绿色风格主题为例: - -### 步骤 1:复制默认主题作为起点 - -```bash -cp -r app/frontend/templates/themes/default app/frontend/templates/themes/green -``` - -### 步骤 2:修改 `base.html` 中的样式 - -编辑 `app/frontend/templates/themes/green/base.html`,修改 `