# Cyan
**Repository Path**: shulinnn/cyan
## Basic Information
- **Project Name**: Cyan
- **Description**: 综合性校园广播站运营平台
- **Primary Language**: TypeScript
- **License**: AGPL-3.0
- **Default Branch**: master
- **Homepage**: None
- **GVP Project**: No
## Statistics
- **Stars**: 2
- **Forks**: 1
- **Created**: 2026-02-25
- **Last Updated**: 2026-03-31
## Categories & Tags
**Categories**: Uncategorized
**Tags**: MySQL, Redis, TypeScript, Vue, Nuxt
## README

**基于 Nuxt 4 构建的现代化校园广播站数字化管理解决方案**
[](https://nuxt.com)
[](https://vuejs.org)
[](https://github.com/tencent/tdesign-vue-next)
[](LICENSE)
[功能特性](#功能特性) • [快速开始](#快速开始) • [技术栈](#技术栈) • [项目结构](#项目结构) • [开发指南](#开发指南)
---
## 项目简介
Cyan 是一个功能完备的综合性校园广播站运营平台,采用全栈一体化架构,为校园广播站提供从内容管理、用户投稿、节目排期到权限控制的完整数字化解决方案。
平台采用现代化的技术栈,包括 **Nuxt 4**、**Casbin 权限系统** 和 **插件化投稿架构**,实现了高度可扩展和易维护的系统设计。
### 核心特性
- 🚀 **全栈一体化** - 基于 Nuxt 4 实现前后端代码统一管理,共享类型定义
- 🎭 **灵活权限系统** - 基于 Casbin 的 RBAC + ABAC 权限模型,支持细粒度权限控制
- 🔌 **插件化架构** - 投稿系统采用插件化设计,支持多种投稿类型扩展
- 📅 **智能排期管理** - 三级数据结构设计,支持栏目复用、拖拽排序、投稿集成
- ⚡ **高性能架构** - Redis 缓存、数据库索引优化、代码分割等技术应用
- 🎨 **现代化 UI** - 基于 TDesign Vue Next 组件库,支持暗色主题
- 📧 **邮件服务** - 集成 SMTP 邮件服务,支持验证码发送
---
## 功能特性
### 用户认证系统
- ✅ 学生信息绑定与验证
- ✅ Session 管理(基于 Redis)
- ✅ 邮箱验证码功能
### 权限管理系统
- ✅ 基于 Casbin 的 RBAC + ABAC 权限模型
- ✅ 五种角色:root、admin、manager、member、user
- ✅ 细粒度权限控制(resource:action 格式)
- ✅ 通配符权限支持(如 `*`、`schedule:*`)
### 通知系统
- ✅ 通知发布与管理
- ✅ 置顶功能
- ✅ 公开/私有通知
- ✅ 软删除支持
### 活动管理
- ✅ 活动创建和编辑
- ✅ 目标受众配置(年级、教师)
- ✅ 信息收集配置
- ✅ 活动状态管理(草稿、已发布)
- ✅ 活动审核流程
### 投稿系统
- ✅ 活动投稿提交
- ✅ 学生信息收集
- ✅ 投稿审核(待审核、已通过、已拒绝)
- ✅ 审核评论功能
- ✅ 投稿状态跟踪
### 插件化投稿系统
- ✅ 可扩展的插件架构
- ✅ 插件自动注册和发现机制
- ✅ 插件生命周期管理(投稿、审核、编排)
- ✅ 数据版本迁移支持
- ✅ 插件开发工具和模板
### 节目排期系统
- ✅ 栏目定义管理(program_column_defs)
- ✅ 每日栏目配置(program_day_columns)
- ✅ 节目项管理(program_day_items)
- ✅ 栏目和节目项的拖拽排序
- ✅ 支持投稿内容和手动添加内容
- ✅ 时长控制和别名管理
- ✅ 与投稿系统的集成
### 管理后台
- ✅ 节目排期管理
- ✅ 动态内容管理
- ✅ 投稿管理
- ✅ 平台配置管理
- ✅ 活动管理
- ✅ 权限管理
- ✅ 插件管理
- ✅ 用户管理
### 学生系统
- ✅ 学生信息管理
- ✅ 班级和年级管理
- ✅ 账号绑定
- ✅ 学生信息验证
---
## 快速开始
### 环境要求
- **Node.js**: 20.x LTS 或更高版本
- **包管理器**: pnpm(推荐)或 npm/yarn/bun
- **数据库**: MySQL 8.0+
- **缓存**: Redis 7.0+
- **浏览器**: Chrome 120+、Edge 120+、Firefox 120+、Safari 17+
### 安装依赖
```bash
# 使用 pnpm(推荐)
pnpm install
# 或使用 npm
npm install
# 或使用 yarn
yarn install
# 或使用 bun
bun install
```
### 环境配置
创建 `.env` 文件并配置以下环境变量:
```bash
# 核心配置
USE_MOCK=false # 是否使用 Mock 模式
API_URL= # API 基础 URL
API_MOCK_URL= # Mock API URL
API_MOCK_TOKEN= # Mock API Token
# Session 配置
NUXT_SESSION_PASSWORD= # Session 加密密钥(必需)
# 数据库配置
DB_HOST=localhost
DB_PORT=3306
DB_DATABASE=cyan
DB_USERNAME=root
DB_PASSWORD=
# Redis 配置
REDIS_HOST=localhost
REDIS_PORT=6379
REDIS_PASSWORD=
# SMTP / 邮件服务配置(可选)
EMAIL_SERVICE= # 可选,填写后优先使用 service 模式(如 qq、163)
EMAIL_HOST= # 未填写 EMAIL_SERVICE 时必填
EMAIL_PORT= # 未填写 EMAIL_SERVICE 时必填
EMAIL_USER=
EMAIL_PASS=
EMAIL_SECURE=false
```
### 启动开发服务器
```bash
# 使用 pnpm
pnpm dev
# 或使用 npm
npm run dev
```
开发服务器将在 `http://localhost:3000` 启动。
### 生产构建
```bash
# 使用 pnpm
pnpm build
# 或使用 npm
npm run build
```
### 预览生产构建
```bash
# 使用 pnpm
pnpm preview
# 或使用 npm
npm run preview
```
### 代码格式化
```bash
# 使用 pnpm
pnpm format
# 或使用 npm
npm run format
```
### Docker 部署
```bash
# 构建镜像
pnpm build:docker
# 启动容器
pnpm start:docker
# 停止并删除容器
pnpm rm:docker
```
---
## 技术栈
### 前端技术
| 技术 | 版本 | 说明 |
|------|------|------|
| **Nuxt 4** | ^4.3.1 | 全栈 Web 应用框架 |
| **Vue 3** | ^3.5.29 | 渐进式 JavaScript 框架 |
| **TDesign Vue Next** | 1.18.2 | 企业级 UI 组件库 |
| **Tailwind CSS** | ^6.14.0 | 实用优先的 CSS 框架 |
| **TypeScript** | 5.9.3 | JavaScript 超集 |
### 后端技术
| 技术 | 版本 | 说明 |
|------|------|------|
| **MySQL 2** | ^3.18.1 | MySQL 数据库客户端 |
| **Redis** | 7.0+ | 内存数据库和缓存系统 |
| **Casbin** | ^5.49.0 | 访问控制库 |
### 安全与认证
| 技术 | 版本 | 说明 |
|------|------|------|
| **WebAuthn** | ^11.0.0 | FIDO2 无密码认证 |
| **nuxt-auth-utils** | 0.5.29 | Nuxt 认证工具库 |
| **Crypto.js** | ^4.2.0 | 加密库 |
### 数据处理与验证
| 技术 | 版本 | 说明 |
|------|------|------|
| **Zod** | ^4.3.6 | TypeScript 数据验证库 |
| **Day.js** | ^1.11.19 | 轻量级日期处理库 |
| **Axios** | 1.13.5 | HTTP 客户端 |
### 第三方服务
| 服务 | 说明 |
|------|------|
| **Nodemailer** | 邮件服务 |
### 开发工具
| 工具 | 版本 | 说明 |
|------|------|------|
| **Prettier** | 3.8.1 | 代码格式化 |
| **Terser** | 5.46.0 | JavaScript 压缩工具 |
| **Docker** | 20.10+ | 容器化平台 |
---
## 项目结构
```
cyan/
├── app/ # 前端应用代码
│ ├── components/ # Vue 组件
│ │ ├── home/ # 首页组件
│ │ ├── submission/ # 投稿相关组件
│ │ │ ├── PluginFormRenderer.vue # 插件投稿表单渲染器
│ │ │ ├── PluginPlaylistCard.vue # 插件节目单卡片
│ │ │ └── PluginReviewRenderer.vue # 插件审核面板渲染器
│ │ ├── AppHeader.vue # 应用头部导航
│ │ ├── AppFooter.vue # 应用底部
│ │ ├── AppSettings.vue # 应用设置
│ │ ├── IdentityTags.vue # 身份标签
│ │ ├── LoginGuideDialog.client.vue # 登录引导对话框
│ │ └── WpWebPlayer.client.vue # 网页播放器
│ ├── composables/ # 组合式函数
│ │ ├── usePermission.ts # 权限检查
│ │ ├── useAdminMenu.ts # 管理后台菜单
│ │ ├── useTheme.ts # 主题管理
│ │ ├── usePluginList.ts # 插件列表管理
│ │ ├── useSubmissionPlugin.ts # 投稿插件操作
│ │ └── useScheduleArrangement.ts # 节目排期编排
│ ├── layouts/ # 布局组件
│ │ ├── default.vue # 默认布局
│ │ ├── auth.vue # 认证布局
│ │ ├── admin.vue # 管理后台布局
│ │ └── install.vue # 安装向导布局
│ ├── middleware/ # 路由中间件
│ │ ├── auth.global.ts # 全局认证中间件
│ │ ├── admin.ts # 管理后台中间件
│ │ └── install.global.ts # 安装流程中间件
│ ├── pages/ # 页面组件(文件路由)
│ │ ├── index.vue # 首页
│ │ ├── activity/ # 活动相关页面
│ │ ├── admin/ # 管理后台页面
│ │ ├── notices/ # 通知页面
│ │ ├── schedule/ # 排期页面
│ │ ├── install/ # 安装向导页面
│ │ ├── user/ # 用户相关页面
│ │ └── [...404].vue # 404 页面
│ ├── plugins/ # Nuxt 插件
│ │ ├── api.ts # API 插件
│ │ ├── directive.ts # 自定义指令
│ │ ├── init-plugins.ts # 插件初始化
│ │ └── theme.ts # 主题插件
│ ├── utils/ # 工具函数
│ │ ├── format.ts # 格式化工具
│ │ ├── plugin-registry.ts # 插件注册中心
│ │ └── useDayjs.ts # Day.js 封装
│ ├── assets/ # 静态资源
│ └── app.vue # 根组件
├── server/ # 服务端代码
│ ├── api/ # API 路由(RESTful)
│ │ ├── admin/ # 管理相关 API
│ │ ├── auth/ # 认证相关 API
│ │ ├── install/ # 安装相关 API
│ │ ├── notices/ # 通知相关 API
│ │ ├── schedule/ # 节目排期相关 API
│ │ ├── user/ # 用户相关 API
│ │ ├── webauthn/ # WebAuthn API
│ │ ├── activities/ # 活动相关 API
│ │ └── submissions.post.ts # 投稿 API
│ ├── plugins/ # Nitro 插件
│ │ └── db-init.ts # 数据库初始化
│ └── utils/ # 服务端工具函数
│ ├── casbin-adapter.ts # Casbin 适配器
│ ├── casbin-model.conf # Casbin 模型配置
│ ├── casbin.ts # Casbin 权限管理
│ ├── db.ts # 数据库连接
│ ├── email.ts # 邮件服务
│ ├── email-code.ts # 邮箱验证码
│ ├── bind-verify.ts # 绑定验证
│ ├── grade.ts # 年级处理
│ ├── id.ts # ID 生成
│ ├── install.ts # 安装状态
│ ├── password.ts # 密码处理
│ ├── protect.ts # 权限保护
│ └── submission.ts # 投稿处理
├── shared/ # 共享代码
│ └── types/ # TypeScript 类型定义
│ ├── api.d.ts # API 响应类型
│ ├── auth.d.ts # 认证相关类型
│ ├── activity.d.ts # 活动类型
│ ├── globel.d.ts # 全局类型
│ ├── hook.d.ts # Hook 类型
│ ├── nodemailer.d.ts # 邮件服务类型
│ ├── submission.d.ts # 投稿类型
│ ├── submission-plugin.d.ts # 投稿插件系统类型
│ ├── schedule.d.ts # 节目排期类型
│ ├── notice.d.ts # 通知类型
│ └── route.d.ts # 路由类型
├── submission_plugins/ # 投稿插件目录
│ ├── README.md # 插件开发指南
│ └── long-text-submission/ # 长文章投稿插件示例
│ ├── index.ts # 导出入口
│ └── app/
│ ├── components/ # 插件组件
│ │ ├── SubmissionForm.vue # 投稿表单
│ │ ├── ReviewPanel.vue # 审核面板
│ │ └── PlaylistCard.vue # 节目单卡片
│ └── composables/ # 插件组合式函数
├── public/ # 静态资源
│ ├── favicon.ico
│ └── pic.webp
├── nuxt.config.ts # Nuxt 配置文件
├── package.json # 项目依赖配置
├── pnpm-lock.yaml # pnpm 锁文件
├── tsconfig.json # TypeScript 配置
├── .prettierrc.json # Prettier 配置
├── .env.example # 环境变量示例
├── .dockerignore # Docker 忽略配置
├── .gitignore # Git 忽略配置
├── README.md # 项目说明文档
├── creation_README.md # 创作说明文档
├── TECHNICAL_README.md # 技术说明文档
├── AGENTS.md # 项目详细文档
├── LICENSE # 开源协议
└── Dockerfile # Docker 配置
```
---
## 开发指南
### API 路由规范
API 路由位于 `server/api/` 目录下,遵循 RESTful 规范
### 权限系统
项目使用 Casbin 实现基于角色的权限控制(RBAC):
**角色定义**:
- `root`: 超级管理员,用作安装时的临时账户
- `admin`: 管理员,拥有平台管理权限
- `member`: 成员,拥有广播站成员权限
- `user`: 普通用户
**权限格式**: `resource:action`,例如:
- `broadcast:read` - 读取广播内容
- `schedule:create` - 创建排期
- `activity:create` - 创建活动
- `submission:review` - 审核投稿
- `*` - 所有权限
使用 `usePermission()` composable 检查权限:
```typescript
const { can } = usePermission();
if (can('create', 'activity')) {
// 用户有创建活动的权限
}
```
### 插件开发
详细的插件开发指南请参考:
- `submission_plugins/README.md`
- `shared/types/submission-plugin.d.ts`
插件目录结构:
```
{pluginId}/
├── index.ts # 导出入口
└── app/
├── components/ # 插件组件
│ ├── SubmissionForm.vue
│ ├── ReviewPanel.vue
│ └── PlaylistCard.vue
└── composables/ # 插件组合式函数(可选)
```
### 数据库初始化
数据库初始化逻辑位于 `server/plugins/db-init.ts`,项目启动时会自动:
1. 创建必要的数据库表
2. 如果是 Mock 模式,插入测试学生数据
3. 初始化 Casbin 权限策略
### Mock 模式
项目支持 Mock 模式用于开发:
1. 设置 `USE_MOCK=true`
2. 配置 `API_MOCK_URL` 和 `API_MOCK_TOKEN`
3. 所有 API 请求将转发到 Mock 服务器
---
## 构建优化
生产环境构建使用 Terser 进行代码压缩和混淆:
- 多次混淆(passes: 2)
- 移除所有注释
- 不美化输出
- 最小化缩进
---
## 实验性功能
本项目使用了 Nitro 的实验性功能:
1. **数据库支持**: 使用 Nitro 实验性数据库支持(`experimental.database: true`)
2. **Cookie Store**: 使用 Nitro 实验性 Cookie Store(`experimental.cookieStore: true`)
这些实验性功能在生产环境中使用需要谨慎,建议关注 Nuxt 官方更新。
---
## 安全注意事项
1. **环境变量**: 生产环境必须配置 `NUXT_SESSION_PASSWORD` 环境变量
2. **数据库安全**: 数据库密码应通过环境变量配置,不应硬编码
3. **HTTPS 要求**: WebAuthn 认证要求使用 HTTPS 协议
4. **密码加密**: 所有用户密码使用 Crypto.js 加密存储
---
## 浏览器兼容性
- Chrome 120+
- Edge 120+
- Firefox 120+
- Safari 17+
注意:WebAuthn 功能需要现代浏览器支持。
---
## 部署要求
### 最小配置
- 2 核 CPU
- 4GB 内存
- 20GB 硬盘
### 推荐配置
- 4 核 CPU
- 8GB 内存
- 50GB 硬盘
### 网络要求
- 支持 HTTPS(WebAuthn 要求)
---
## 常见问题
### WebAuthn 无法使用?
确保:
1. 使用 HTTPS 协议(生产环境)
2. 浏览器支持 WebAuthn
### 数据库连接失败?
检查:
1. MySQL 服务是否运行
2. 环境变量配置是否正确
3. 数据库用户权限是否足够
### Redis 连接失败?
检查:
1. Redis 服务是否运行
2. 环境变量配置是否正确
3. Redis 密码是否正确
---
## 贡献指南
欢迎贡献代码!请遵循以下步骤:
1. Fork 本仓库
2. 创建特性分支 (`git checkout -b feature/AmazingFeature`)
3. 提交更改 (`git commit -m 'Add some AmazingFeature'`)
4. 推送到分支 (`git push origin feature/AmazingFeature`)
5. 开启 Pull Request
---
## 许可证
本项目采用AGPL-3.0开源协议,具体协议信息请参考项目根目录的 LICENSE 文件。