参与开发
欢迎参与 OpenList to Stream 项目的开发!本文档将帮助您了解项目结构、开发环境搭建、贡献流程等开发相关信息。
项目概览
技术栈
- 前端: Nuxt.js 3 + Vue 3 + JavaScript + Tailwind CSS
- 后端: Spring Boot 3 + Java 21 + MyBatis + SQLite
- 数据库: SQLite + Flyway 数据库迁移
- 构建工具: Gradle (后端) + npm (前端)
- 容器化: Docker + Docker Compose
- CI/CD: GitHub Actions
项目结构
ostrm/
├── frontend/ # Nuxt.js 前端应用
│ ├── components/ # Vue 组件
│ ├── pages/ # 页面文件
│ ├── middleware/ # 路由中间件
│ ├── utils/ # 工具函数
│ └── types/ # TypeScript 类型定义
├── backend/ # Spring Boot 后端应用
│ └── src/main/java/com/hienao/openlist2strm/
│ ├── controller/ # REST API 控制器
│ ├── service/ # 业务逻辑层
│ ├── handler/ # 文件处理器链(责任链模式)
│ │ ├── FileProcessorHandler.java # 处理器接口
│ │ ├── FileProcessorChain.java # 链执行器
│ │ ├── FileDiscoveryHandler.java # Order: 10 - 文件发现
│ │ ├── FileFilterHandler.java # Order: 20 - 文件过滤
│ │ ├── StrmGenerationHandler.java # Order: 30 - STRM生成
│ │ ├── NfoDownloadHandler.java # Order: 40 - NFO下载
│ │ ├── ImageDownloadHandler.java # Order: 41 - 图片下载
│ │ ├── SubtitleCopyHandler.java # Order: 42 - 字幕复制
│ │ ├── MediaScrapingHandler.java # Order: 50 - 媒体刮削
│ │ ├── OrphanCleanupHandler.java # Order: 60 - 孤立文件清理
│ │ └── context/ # 共享上下文
│ ├── mapper/ # MyBatis 数据访问层
│ ├── entity/ # 数据库实体
│ ├── dto/ # 数据传输对象
│ ├── job/ # 定时任务
│ ├── config/ # 配置类
│ └── util/ # 工具类
├── docs/ # 项目文档
├── docker-compose.yml # Docker 编排文件
├── Dockerfile # Docker 镜像构建文件
└── dev-docker.sh # 开发环境脚本开发环境搭建
前置条件
- Node.js: 版本 20 或更高
- Java: 版本 21 或更高
- Docker: 最新版本
- Git: 最新版本
克隆项目
bash
git clone https://github.com/hienao/ostrm.git
cd ostrm环境配置
- 复制环境变量文件
bash
cp .env.docker.example .env- 创建必要目录
bash
mkdir -p ./data/config ./data/db ./logs ./strm启动开发环境
使用 dev-docker.sh(推荐)
bash
# 初始化开发环境(包含依赖检查、环境配置、镜像构建)
./dev-docker.sh install
# 启动完整环境
./dev-docker.sh start
# 开发模式启动(支持热重载)
./dev-docker.sh start-dev
# 查看服务状态
./dev-docker.sh status
# 实时查看日志
./dev-docker.sh logs-f
# 进入容器进行调试
./dev-docker.sh exec
# 执行健康检查
./dev-docker.sh health
# 备份数据
./dev-docker.sh backup
# 停止服务
./dev-docker.sh stop
# 深度清理(删除镜像和卷)
./dev-docker.sh clean-all注意:Windows 用户建议使用 Git Bash 运行 dev-docker.sh。
使用 Docker Compose
bash
# 启动所有服务
docker-compose up -d
# 查看服务状态
docker-compose ps
# 查看日志
docker-compose logs -f本地开发启动
启动后端:
bash
cd backend
./gradlew bootRun启动前端:
bash
cd frontend
npm install
npm run dev访问应用
- 前端开发服务器:
http://localhost:3000 - 后端 API:
http://localhost:8080 - API 文档:
http://localhost:8080/swagger-ui.html - 主应用:
http://localhost:3111
开发指南
前端开发
项目结构
frontend/
├── components/ # 可复用组件
│ ├── AppHeader.vue # 应用头部组件
│ └── [其他组件...] # 其他组件
├── pages/ # 页面组件
│ ├── index.vue # 首页(OpenList 配置管理)
│ ├── login.vue # 登录页
│ ├── register.vue # 注册页
│ ├── settings.vue # 系统设置页
│ ├── logs.vue # 日志查看页
│ ├── change-password.vue # 修改密码页
│ └── task-management/ # 任务管理相关页面
│ └── [id].vue # 任务详情页
├── middleware/ # 路由中间件
│ ├── auth.js # 认证中间件
│ ├── guest.js # 访客中间件
│ └── docker-port.global.js # Docker 端口处理中间件
├── utils/ # 工具函数
├── assets/ # 静态资源
└── plugins/ # Nuxt 插件开发规范
组件命名:
- 使用 PascalCase 命名组件文件
- 组件名应该描述其功能,如
TaskStatusCard.vue - 页面组件放在
pages/目录下
代码风格:
- 使用 Composition API 和
<script setup>语法 - 使用 JavaScript 进行开发(非 TypeScript)
- 遵循 Vue 3 和 Nuxt 3 最佳实践
状态管理:
- 使用 Pinia 进行状态管理
- 将业务逻辑放在 stores 中
- 组件中保持轻量级的状态管理
- 使用
ref和reactive管理响应式数据
API 调用
javascript
// 使用 $fetch 进行 API 调用
const { data } = await $fetch('/api/tasks', {
method: 'GET',
headers: {
'Authorization': `Bearer ${token}`
}
})
// 在 composable 中封装 API 调用
export const useTaskApi = () => {
const createTask = async (taskData) => {
return await $fetch('/api/task-config', {
method: 'POST',
body: taskData
})
}
return { createTask }
}后端开发
项目结构
backend/src/main/java/com/hienao/openlist2strm/
├── controller/ # REST 控制器
├── service/ # 业务逻辑层
├── handler/ # 文件处理器链(责任链模式)
│ ├── FileProcessorHandler.java # 处理器接口
│ ├── FileProcessorChain.java # 链执行器
│ ├── FileDiscoveryHandler.java # Order: 10 - 文件发现
│ ├── FileFilterHandler.java # Order: 20 - 文件过滤
│ ├── StrmGenerationHandler.java # Order: 30 - STRM文件生成
│ ├── NfoDownloadHandler.java # Order: 40 - NFO文件下载
│ ├── ImageDownloadHandler.java # Order: 41 - 图片文件下载
│ ├── SubtitleCopyHandler.java # Order: 42 - 字幕文件复制
│ ├── MediaScrapingHandler.java # Order: 50 - 媒体刮削
│ ├── OrphanCleanupHandler.java # Order: 60 - 孤立文件清理
│ └── context/ # 共享上下文
├── mapper/ # MyBatis 映射器
├── entity/ # 数据库实体
├── dto/ # 数据传输对象
├── config/ # 配置类
├── job/ # 定时任务
├── util/ # 工具类
└── exception/ # 异常处理开发规范
代码风格:
- 使用 Java 编程语言
- 遵循 Spring Boot 最佳实践
- 使用分层架构(Controller → Service → Handler → Mapper)
处理器链设计: 系统采用责任链模式处理文件,使用 @Order 注解定义执行顺序:
| Order | 处理器 | 功能 |
|---|---|---|
| 10 | FileDiscoveryHandler | 文件发现 |
| 20 | FileFilterHandler | 文件过滤 |
| 30 | StrmGenerationHandler | STRM 文件生成 |
| 40 | NfoDownloadHandler | NFO 文件下载(优先级:本地 > OpenList > 刮削) |
| 41 | ImageDownloadHandler | 图片文件下载(海报、背景图、缩略图) |
| 42 | SubtitleCopyHandler | 字幕文件复制 |
| 50 | MediaScrapingHandler | 媒体刮削 |
| 60 | OrphanCleanupHandler | 孤立文件清理 |
API 设计:
- 使用 RESTful API 设计原则
- 统一的响应格式(ApiResponse)
- 合理的 HTTP 状态码使用
- 输入验证和错误处理
数据库操作:
- 使用 MyBatis 进行数据库操作
- 实体类使用 MyBatis 注解
- 数据库迁移使用 Flyway
示例代码
Handler 接口:
java
public interface FileProcessorHandler {
ProcessingResult process(FileProcessingContext context);
Set<FileType> getHandledTypes();
}
// 处理器示例
@Component
@Order(42)
public class SubtitleCopyHandler implements FileProcessorHandler {
@Override
public ProcessingResult process(FileProcessingContext context) {
// 处理字幕文件下载
return ProcessingResult.SUCCESS;
}
@Override
public Set<FileType> getHandledTypes() {
return Set.of(FileType.SUBTITLE, FileType.VIDEO);
}
}Controller 层:
java
@RestController
@RequestMapping("/api/task-config")
@Validated
public class TaskConfigController {
private final TaskConfigService taskConfigService;
public TaskConfigController(TaskConfigService taskConfigService) {
this.taskConfigService = taskConfigService;
}
@GetMapping
public ApiResponse<List<TaskConfigDto>> getTasks() {
return ApiResponse.success(taskConfigService.getAllTasks());
}
@PostMapping
public ApiResponse<TaskConfigDto> createTask(
@Valid @RequestBody TaskConfigDto taskDto
) {
return ApiResponse.success(taskConfigService.createTask(taskDto));
}
}Service 层:
java
@Service
@Transactional
public class TaskConfigService {
private final TaskConfigMapper taskConfigMapper;
private final OpenlistConfigMapper openlistConfigMapper;
public TaskConfigService(TaskConfigMapper taskConfigMapper,
OpenlistConfigMapper openlistConfigMapper) {
this.taskConfigMapper = taskConfigMapper;
this.openlistConfigMapper = openlistConfigMapper;
}
public TaskConfigDto createTask(TaskConfigDto taskDto) {
// 业务逻辑验证
validateTaskConfig(taskDto);
// 数据转换
TaskConfigEntity entity = taskDto.toEntity();
// 保存到数据库
taskConfigMapper.insert(entity);
// 返回 DTO
return entity.toDto();
}
}数据库开发
数据库迁移
使用 Flyway 进行数据库版本管理:
- 创建迁移文件
sql
-- 位置:backend/src/main/resources/db/migration/
-- 文件名:V{version}__{description}.sql
-- 例如:V2__add_task_status.sql
CREATE TABLE task_execution_log (
id INTEGER PRIMARY KEY AUTOINCREMENT,
task_id INTEGER NOT NULL,
status VARCHAR(20) NOT NULL,
start_time DATETIME NOT NULL,
end_time DATETIME,
message TEXT,
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (task_id) REFERENCES task_config(id)
);- 运行迁移 应用启动时会自动执行未运行的迁移文件。
MyBatis 映射
java
@Mapper
public interface TaskConfigMapper {
@Select("SELECT * FROM task_config WHERE deleted = false ORDER BY created_at DESC")
List<TaskConfigEntity> findAllActive();
@Insert("INSERT INTO task_config (name, openlist_config_id, openlist_path, ...) " +
"VALUES (#{name}, #{openlistConfigId}, #{openlistPath}, ...)")
void insert(TaskConfigEntity task);
@Update("UPDATE task_config SET status = #{status}, updated_at = CURRENT_TIMESTAMP " +
"WHERE id = #{id}")
void updateStatus(@Param("id") Long id, @Param("status") String status);
}测试
前端测试
bash
cd frontend
# 运行单元测试
npm run test
# 运行端到端测试
npm run test:e2e
# 生成测试覆盖率报告
npm run test:coverage后端测试
bash
cd backend
# 运行单元测试
./gradlew test
# 运行集成测试
./gradlew integrationTest
# 生成测试覆盖率报告
./gradlew jacocoTestReport集成测试(端到端测试)
使用 Docker 进行集成测试
项目提供了完整的 Docker 集成测试脚本,可以构建完整的镜像并部署测试:
bash
# 初始化开发环境(包含依赖检查、环境配置、镜像构建)
./dev-docker.sh install
# 启动完整环境
./dev-docker.sh start
# 开发模式启动(支持热重载)
./dev-docker.sh start-dev
# 查看服务状态
./dev-docker.sh status
# 实时查看日志
./dev-docker.sh logs-f
# 进入容器进行调试
./dev-docker.sh exec
# 执行健康检查
./dev-docker.sh health
# 备份数据
./dev-docker.sh backup
# 停止服务
./dev-docker.sh stop
# 深度清理(删除镜像和卷)
./dev-docker.sh clean-allDocker 集成测试特性
高级开发脚本功能:
- 依赖检查:自动检查 Docker、docker-compose 等依赖
- 环境配置:自动创建必要的目录和配置文件
- 镜像构建:支持缓存和无缓存构建
- 服务管理:启动、停止、重启服务
- 健康检查:自动检测服务启动状态
- 状态监控:实时查看服务状态和日志
- 调试支持:进入容器内部进行调试
- 数据备份:一键备份配置和数据
- 环境清理:支持普通清理和深度清理
开发模式特性:
- 热重载支持:前端和后端代码修改自动重载
- 多端口映射:同时暴露前端、后端和代理端口
- 调试日志:启用详细的调试日志
- 源码挂载:本地源码直接挂载到容器中
端口映射:
3111:80- 主应用端口(Nginx 代理)3000:3000- 前端开发服务器端口8080:8080- 后端 API 端口
测试规范
- 为新功能编写单元测试
- 为重要业务逻辑编写集成测试
- 保持测试覆盖率在 80% 以上
- 使用有意义的测试数据和断言
- 在提交前运行完整的集成测试
代码质量
代码规范
项目遵循以下代码规范:
前端:
- 使用 Nuxt.js 3 和 Vue 3 最佳实践
- 遵循 JavaScript Standard Style
- 使用 Tailwind CSS 进行样式开发
后端:
- 遵循 Java 编码规范
- 使用 Spring Boot 最佳实践
- 采用分层架构设计
- 处理器链模式处理文件
提交前检查
在提交代码前,请确保:
- 所有测试通过
- 代码能够正常编译和运行
- 功能测试正常
- 遵循项目的代码风格
贡献流程
1. Fork 项目
在 GitHub 上 Fork 项目到您的账户。
2. 创建功能分支
bash
git checkout -b feature/your-feature-name3. 开发和测试
- 实现您的功能
- 编写测试用例
- 运行所有测试确保通过
4. 提交代码
bash
git add .
git commit -m "feat: add new feature description"提交信息规范
使用 Conventional Commits 规范:
feat:新功能fix:修复 bugdocs:文档更新style:代码格式化refactor:代码重构test:测试相关chore:构建或工具相关
5. 推送分支
bash
git push origin feature/your-feature-name6. 创建 Pull Request
- 在 GitHub 上创建 Pull Request
- 填写 PR 模板
- 等待代码审查
- 根据反馈进行修改
7. 合并代码
通过审查后,代码将被合并到主分支。
发布流程
版本发布
- 更新版本号
- 更新 CHANGELOG.md
- 创建 Git 标签
- 构建 Docker 镜像
- 发布到 GitHub Releases
自动化发布
项目使用 GitHub Actions 进行自动化发布:
- 代码推送时自动运行测试
- 创建标签时自动构建和发布
- 自动生成发布文档
开发工具
IDE 配置
推荐使用以下 IDE:
前端:
- VS Code + Volar 扩展
- WebStorm
后端:
- IntelliJ IDEA
- Eclipse
- VS Code(Java 扩展包)
必需扩展
- VS Code: Vue - Official, TypeScript, ESLint, Prettier
- IntelliJ IDEA: Lombok Plugin, MyBatis Plugin
调试配置
项目包含了调试配置文件,可以在 IDE 中直接调试应用。
社区参与
获取帮助
- 查看 项目文档
- 在 GitHub Discussions 中讨论
- 在 GitHub Issues 中报告问题
贡献方式
- 报告 Bug
- 提出新功能建议
- 改进文档
- 提交代码
- 协助翻译
行为准则
请阅读并遵守项目的 行为准则。
感谢您对 OpenList to Stream 项目的关注和贡献!每一个贡献都让这个项目变得更好。如果您在开发过程中遇到任何问题,请随时联系我们。