外观
架构说明
明确定位
每个产品都应该有明确的定位,需要知道自己的目标客户是哪些人群,定位到了目标客户,才能够有针对性的开发。
峰云CMS的定位是面向中小微企业的企业级建站程序。所以我们在架构设计上进行了针对性地调整。
- 我们不会过度强调性能而引入额外的复杂度。比如我们未使用分布式系统架构和消息队列;比如数据库方面我们仅使用了
MySql/MariaDB,未使用Redis、MongoDB等其他类型的数据库。 - 我们不使用特别小众的技术栈,这会导致一定的招人成本和上手速度。
- 我们会尽量让程序容易部署和发布。
- 我们会保持技术栈始终是一个“较新”的状态。一来更容易维护,二来可以使用一些新特性。比如现在Vue3已经出来很久了,我们就不会再使用Vue2了。比如
Node最新LTS版本已经原生支持TypeScript了,这意味着服务端代码可以免去频繁的TypeScript转JavaScript的编译过程了! - 作为企业级程序,我们会使用
TypeScript来提高代码质量。
技术栈
- Node.js v22.18.0:该版本原生支持
TypeScript了。免去服务端代码的编译环节,大大提高了开发和部署时的效率。 - Vue3:前端框架,使用
TypeScript进行开发。 - ElementPlus:前端UI组件库,用于快速搭建后台系统和子应用。
- TypeScript:支持类型声明,提高代码质量和可维护性。
- Express:作为最经典和广泛使用的
Node.js服务端框架,相比其他Node.js框架,学习和使用成本低很多。 - MySql/MariaDB:数据库,用于存储数据。session数据也会持久化到其中。
- knex:SQL构建器,用于生成数据库查询语句和定义数据库表结构。
- zod:用于数据验证和类型推断。
代码目录结构说明
apps目录
该目录用于存放前端子应用代码。
- _base:子应用使用的基础代码,封装了公共方法、通用业务逻辑
- account:账号模块,访问地址为
https://www.example.com/account/ - admin:后台管理模块,访问地址为
https://www.example.com/admin/ - docs:文档模块,底层使用了vitepress,访问地址为
https://www.example.com/docs/,
当你要开发其他前端子应用时,请在apps目录下创建对应的目录。apps目录下除_base目录外,每个目录都是一个相对独立的前端项目。之所以说是“相对独立”,是因为它们的依赖都是统一声明在项目根目录下的package.json中的,并不需要每个子应用里重复安装。
建议
- 现有的子应用都是使用
Vue3+TypeScript+ElementPlus技术栈开发的,新的子应用也推荐使用这一套技术栈(并不强制)。 - 子应用一般不需要支持SEO,所以不建议使用next之类的全栈框架来进行纯前端输出,无故提高了项目的复杂度和编译时间。
apps-home目录
该目录用于存放前端独立项目的代码。
有时候我们希望创建独立的前端项目,或者是为子应用创建一个落地页,这些项目通常需要支持SEO,并且一般使用独立域名下的根路径url来访问,比如https://www.example.com/。
这些项目的代码通常会存放在apps-home目录下,每个子目录都是一个相对独立的前端项目。
assets目录
该目录用于存放供服务端使用的模板文件(但不包括用于SSR输出HTML文件内容的视图模板文件)。
比如:
- 发送邮件时使用的邮件html模板(文件名示例:
email-template.ejs)。 - AI项目使用的系统提示词模板(文件名示例:
ai-prompt-template.md)。 - Excel模板文件。
注意
- 这些模板文件不会直接被前端项目使用,而是会被服务端代码读取(通常,程序只读取这些文件的内容,不应修改其内容)。
- 用于支持接口SSR渲染HTML的视图模板文件不存放于此,而是单独存放于
views目录下。
build目录
存放编译、构建相关的脚本文件。
database目录
用于存放将外部数据导入本项目数据库用的脚本文件。比如:
- 从其他项目迁移数据到本项目数据库。
- 爬虫爬取数据并写入到本项目数据库。
hosts目录
nginx相关的配置文件存在于此。用于将nginx相关配置和SSL证书等于服务器上的版本进行同步。
建议
通常一个子目录对应一台服务器。
localhost目录
本地开发时启动的服务代码存放于此。例如:
- 反cloudflare的代理服务(用于爬取数据时绕过cloudflare的反爬机制)。
logs目录
用于存放服务端程序运行产生的日志文件。
提示
若该目录不存在,程序运行时会自动创建该目录。不需要将该目录提交到代码仓库。
migrations目录
用于存放knex的数据库迁移文件。
node_modules目录
通过 npm install 安装的依赖包会存放在此目录下。
提示
安装依赖时会自动创建该目录。不需要将该目录提交到代码仓库。
patches目录
用于存放供 patch-package 工具打补丁的文件。
patch-package是干嘛的?
有时候我们安装的第三方依赖包的代码有问题,或者是我们需要对依赖包的代码进行一些修改,这时候就可以使用 patch-package 工具来打补丁。
public目录
用于存放静态资源文件。部分编译产物也会生成到这个目录下。
提示
对于生成到该目录下的编译产物,请不要将其提交到代码仓库。
schedules目录
用于存放定时任务脚本。比如:
- 定期优化数据库表格。
- 定期更新用户会员到期状态。
- 定期发送邮件。
- 定期备份数据库。
src目录
服务端源代码。通常来说,这个目录下有你最重要的业务代码。
- bin目录:服务启动脚本(入口)。
- controllers目录:用于存放控制器代码。
- models目录:用于存放模型代码。
- routes目录:用于存放路由代码。
- services目录:用于存放服务代码。
- scripts目录:用于存放工具代码。
- middlewares: 用于存放中间件代码。
提示
- 控制器代码负责处理HTTP请求和响应。
- 模型代码负责定义数据结构和数据库操作。
- 路由代码负责定义URL路由和请求处理函数。
- 服务代码负责实现业务逻辑。
- 工具代码负责提供一些通用的功能。
- 中间件代码负责处理HTTP请求和响应的中间件。
typings目录
用于存放TypeScript类型定义文件。前后端项目均可复用这里的类型声明,减少重复定义。
views目录
服务端SSR渲染HTML文本时使用的视图模板文件存放于此。
根目录
package.json
package.json 比较重要,所以单独拎出来讲。
json
{
// 项目名称
"name": "aimian",
// 软件版本号
"version": "0.0.1",
// 是否为私有仓库
"private": true,
// 项目采用ES Module模块化方案
"type": "module",
// 入口文件
"main": "src/bin/www.mts",
// 模块导入路径别名
"imports": {},
// 脚本命令
"scripts": {},
// 生产依赖
"dependencies": {},
// 开发依赖
"devDependencies": {}
}1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
其他文件
- .editorconfig:通用编辑器配置文件。
- .env:环境变量配置文件。
- .env.int:集成环境变量配置文件。
- .env.pre:预发布环境变量配置文件。
- .env.production:生产环境变量配置文件。
- .gitignore:Git忽略文件。
- .npmrc:npm配置文件。
- .nvmrc:Node版本管理配置文件。
- .prettierignore:Prettier忽略文件。
- .prettierrc:Prettier配置文件。
- .eslint.config.lib.mts:ESLint库配置文件。
- .eslint.config.server.mts:ESLint服务端配置文件。
- .eslint.config.vue.mts:ESLintVue配置文件。
- knexfile.mts:Knex配置文件。
- package-lock.json:npm依赖锁文件。
- README.md:项目README文件。
- tsconfig.json:TypeScript配置文件。
架构模式
1. MVC 架构
项目采用经典的 MVC(Model-View-Controller)架构:
- Model:
src/models/- 数据模型和数据库操作 - View:
views/(服务端模板)+apps/(前端应用) - Controller:
src/controllers/- 处理 HTTP 请求和响应
2. 分层架构
服务端采用分层架构:
Controller 层(控制器)
↓
Service 层(业务逻辑和数据访问)
↓
Model 层(数据模型)
↓
Database(数据库)1
2
3
4
5
6
7
2
3
4
5
6
7
3. 模块导入路径别名
项目使用路径别名简化导入:
typescript
// 在 package.json 中定义
"imports": {
"#controllers/*": "./src/controllers/*.mts",
"#services/*": "./src/services/*.mts",
"#models/*": "./src/models/*.mts",
// ... 等等
}
// 使用示例
import { getUserBalance } from "#services/balance";
import { cGetBalance } from "#controllers/balance";1
2
3
4
5
6
7
8
9
10
11
2
3
4
5
6
7
8
9
10
11
4. 类型定义共享
前后端共享 typings/ 目录下的类型定义,确保类型一致性。
5. 环境配置
所有配置通过环境变量传入,在 src/scripts/ConstantUtils.mts 中统一管理。
主要配置:
- 数据库配置
- 支付配置
- 邮件配置
- 短信配置
- 前端应用端口配置
- 等等...
6. 错误处理
- 使用统一的错误处理中间件
ErrorMiddleware - 使用
TReturn<T>类型表示可能返回错误的函数 - 格式:
[Error | null, T | undefined]
7. 响应格式
使用统一的响应格式:
typescript
// 成功响应
res.success(data);
// 分页响应
res.successPage({ list, total, pageNo, pageSize });
// 失败响应
res.fail(message, statusCode);1
2
3
4
5
6
7
8
2
3
4
5
6
7
8
核心业务模块
1. 用户系统
主要功能:
- 用户注册和登录
- 密码找回
- 用户信息管理
- 角色和权限管理
2. 余额系统
主要功能:
- 余额充值(支持多种支付方式)
- 余额消费
- 余额提现
- 交易记录查询
- 退款处理
详细设计:请参考 余额系统设计文档
3. 支付系统
支付渠道:
- 微信支付(通过第三方支付服务)
4. 用户管理系统
主要功能:
- 用户列表管理(分页、搜索)
- 用户角色管理(查看、修改)
- 用户状态管理(查看、修改)
权限控制:仅超级管理员可访问
详细设计:请参考 用户管理系统设计文档
5. 文章管理系统
主要功能:
- 文章管理(创建、编辑、删除、发布)
- 付费阅读(免费内容和付费内容分离)
- 分类和标签管理
- AI辅助功能(生成标题、摘要、大纲、优化内容)
- 文章统计(浏览量等)
详细设计:请参考 文章系统设计文档
数据库设计
主要数据表
用户相关
user:用户表role:角色表
余额相关
balance_account:余额账户表balance_transaction:余额交易流水表balance_alert_settings:余额提醒设置表balance_alert_log:余额提醒记录表balance_withdraw_account:提现账户表
内容相关
article:文章表(支持付费阅读、分类、标签)article_category:文章分类表post:帖子表product:产品表
订单相关
order:订单表
其他
dict:字典表page_view:页面访问记录表- 等等...
详细的数据库设计说明,请参考 数据库设计文档。