# 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
Cyan **基于 Nuxt 4 构建的现代化校园广播站数字化管理解决方案** [![Nuxt](https://img.shields.io/badge/Nuxt-4.3.1-00DC82?logo=nuxt.js)](https://nuxt.com) [![Vue](https://img.shields.io/badge/Vue-3.5.29-4FC08D?logo=vue.js)](https://vuejs.org) [![TDesign Vue Next](https://img.shields.io/badge/TDesign-1.18.2-blue.svg)](https://github.com/tencent/tdesign-vue-next) [![License](https://img.shields.io/badge/License-AGPL--3.0-green.svg)](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 文件。