Compare commits

...

No commits in common. 'main' and 'Backend' have entirely different histories.

40
Backend/.gitignore vendored

@ -0,0 +1,40 @@
target/
!.mvn/wrapper/maven-wrapper.jar
!**/src/main/**/target/
!**/src/test/**/target/
### IntelliJ IDEA ###
.idea/modules.xml
.idea/jarRepositories.xml
.idea/compiler.xml
.idea/libraries/
*.iws
*.iml
*.ipr
### Eclipse ###
.apt_generated
.classpath
.factorypath
.project
.settings
.springBeans
.sts4-cache
### NetBeans ###
/nbproject/private/
/nbbuild/
/dist/
/nbdist/
/.nb-gradle/
build/
!**/src/main/**/build/
!**/src/test/**/build/
### VS Code ###
.vscode/
### Mac OS ###
.DS_Store
*.db

@ -0,0 +1,8 @@
# 默认忽略的文件
/shelf/
/workspace.xml
# 基于编辑器的 HTTP 客户端请求
/httpRequests/
# Datasource local storage ignored files
/dataSources/
/dataSources.local.xml

@ -0,0 +1,19 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="DataSourceManagerImpl" format="xml" multifile-model="true">
<data-source source="LOCAL" name="users@localhost" uuid="84924da6-4894-472f-a7ba-c8cc77aa85b1">
<driver-ref>mysql.8</driver-ref>
<synchronize>true</synchronize>
<imported>true</imported>
<remarks>$PROJECT_DIR$/src/main/resources/application.properties</remarks>
<jdbc-driver>com.mysql.cj.jdbc.Driver</jdbc-driver>
<jdbc-url>jdbc:mysql://localhost:3306/users?useSSL=false&amp;serverTimezone=UTC&amp;allowPublicKeyRetrieval=true</jdbc-url>
<jdbc-additional-properties>
<property name="com.intellij.clouds.kubernetes.db.host.port" />
<property name="com.intellij.clouds.kubernetes.db.enabled" value="false" />
<property name="com.intellij.clouds.kubernetes.db.container.port" />
</jdbc-additional-properties>
<working-dir>$ProjectFileDir$</working-dir>
</data-source>
</component>
</project>

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="Encoding">
<file url="file://$PROJECT_DIR$/src/main/java" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/src/main/resources" charset="UTF-8" />
</component>
</project>

@ -0,0 +1,14 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ExternalStorageConfigurationManager" enabled="true" />
<component name="MavenProjectsManager">
<option name="originalFiles">
<list>
<option value="$PROJECT_DIR$/pom.xml" />
</list>
</option>
</component>
<component name="ProjectRootManager" version="2" languageLevel="JDK_17" default="true" project-jdk-name="corretto-17" project-jdk-type="JavaSDK">
<output url="file://$PROJECT_DIR$/out" />
</component>
</project>

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="$PROJECT_DIR$/.." vcs="Git" />
</component>
</project>

@ -0,0 +1,78 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.4.3</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.Backend</groupId>
<artifactId>Backend</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<maven.compiler.source>17</maven.compiler.source>
<maven.compiler.target>17</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<!-- pom.xml -->
<dependency>
<groupId>org.springdoc</groupId>
<artifactId>springdoc-openapi-starter-webmvc-ui</artifactId>
<version>2.7.0</version> <!-- 注意使用适配 Spring Boot 3.x 的版本 -->
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.32</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>3.0.3</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>

@ -0,0 +1,13 @@
package mapper;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class MainApp {
public static void main(String[] args) {
SpringApplication.run(MainApp.class, args);
}
}

@ -0,0 +1,10 @@
package mapper;
import lombok.Data;
@Data
public class User {
private Long id;
private String name; // 用户名
private String password; // 密码(存储加密后的值)
}

@ -0,0 +1,86 @@
package mapper;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.media.Content;
import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.v3.oas.annotations.responses.ApiResponse;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.Data;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import java.util.List;
@Tag(name = "用户管理")
@RestController
@RequestMapping(value = "/users") // 通过这里配置使下面的映射都在/users下
public class UserController {
@Autowired
private UserMapper userMapper;
@GetMapping("/")
@Operation(summary = "获取用户列表")
public List<User> getUserList() {
return userMapper.getAllUsers();
}
@PostMapping("/register")
@Operation(summary = "注册用户", description = "根据传入的用户信息进行注册")
public String registerUser(@RequestBody User user) {
userMapper.insertUser(user);
return "注册成功";
}
@GetMapping("/{id}")
@Operation(summary = "获取用户详细信息", description = "根据url的id来获取用户详细信息")
public User getUser(@PathVariable Long id) {
return userMapper.getUserById(id);
}
@PutMapping("/{id}")
@Operation(summary = "更新用户详细信息", description = "根据url的id来指定更新对象,并根据传过来的user信息来更新用户详细信息")
@Parameter(name = "id", description = "用户编号", required = true, example = "1")
public String putUser(@PathVariable Long id, @RequestBody User user) {
userMapper.updateUser(user);
return "success";
}
@DeleteMapping("/{id}")
@Operation(summary = "删除用户", description = "根据url的id来指定删除对象")
public String deleteUser(@PathVariable Long id) {
userMapper.deleteUser(id);
return "success";
}
@PostMapping("/login")
public String login(@RequestBody LoginRequest loginRequest) {
String name = loginRequest.getName();
String password = loginRequest.getPassword();
User user = userMapper.getUserByName(name);
if (user == null) {
return "用户名或密码错误";
}
if (!user.getPassword().equals(password)) {
return "用户名或密码错误";
}
return "登录成功";
}
// 新增内部类
@Data
static class LoginRequest {
private String name;
private String password;
}
}

@ -0,0 +1,27 @@
package mapper;
import org.apache.ibatis.annotations.*;
import java.util.List;
@Mapper
public interface UserMapper {
@Select("SELECT * FROM users")
List<User> getAllUsers();
@Insert("INSERT INTO users(name, password) VALUES(#{name}, #{password})")
void insertUser(User user);
@Select("SELECT * FROM users WHERE id = #{id}")
User getUserById(Long id);
@Update("UPDATE users SET name=#{name}, password=#{password} WHERE id=#{id}")
void updateUser(User user);
@Delete("DELETE FROM users WHERE id = #{id}")
void deleteUser(Long id);
@Select("SELECT * FROM users WHERE name = #{name}")
User getUserByName(String name);
}

@ -0,0 +1,11 @@
spring.datasource.url=jdbc:mysql://localhost:3306/users?useSSL=false&serverTimezone=UTC&allowPublicKeyRetrieval=true
spring.datasource.username=root
spring.datasource.password=230609zxy
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
# MyBatis
mybatis.configuration.mapUnderscoreToCamelCase=true
logging.level.com.mapper.UserMapper=debug
server.port=8081

@ -0,0 +1,21 @@
MIT License
Copyright (c) 2025 雷电影
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

@ -0,0 +1,36 @@
# MusicPlayer
#### Description
{**When you're done, you can delete the content in this README and update the file with details for others getting started with your repository**}
#### Software Architecture
Software architecture description
#### Installation
1. xxxx
2. xxxx
3. xxxx
#### Instructions
1. xxxx
2. xxxx
3. xxxx
#### Contribution
1. Fork the repository
2. Create Feat_xxx branch
3. Commit your code
4. Create Pull Request
#### Gitee Feature
1. You can use Readme\_XXX.md to support different languages, such as Readme\_en.md, Readme\_zh.md
2. Gitee blog [blog.gitee.com](https://blog.gitee.com)
3. Explore open source project [https://gitee.com/explore](https://gitee.com/explore)
4. The most valuable open source project [GVP](https://gitee.com/gvp)
5. The manual of Gitee [https://gitee.com/help](https://gitee.com/help)
6. The most popular members [https://gitee.com/gitee-stars/](https://gitee.com/gitee-stars/)

@ -1,2 +1,39 @@
# YueQingyinmusicplayer
# MusicPlayer
#### 介绍
{**以下是 Gitee 平台说明,您可以替换此简介**
Gitee 是 OSCHINA 推出的基于 Git 的代码托管平台(同时支持 SVN。专为开发者提供稳定、高效、安全的云端软件开发协作平台
无论是个人、团队、或是企业,都能够用 Gitee 实现代码托管、项目管理、协作开发。企业项目请看 [https://gitee.com/enterprises](https://gitee.com/enterprises)}
#### 软件架构
软件架构说明
#### 安装教程
1. xxxx
2. xxxx
3. xxxx
#### 使用说明
1. xxxx
2. xxxx
3. xxxx
#### 参与贡献
1. Fork 本仓库
2. 新建 Feat_xxx 分支
3. 提交代码
4. 新建 Pull Request
#### 特技
1. 使用 Readme\_XXX.md 来支持不同的语言,例如 Readme\_en.md, Readme\_zh.md
2. Gitee 官方博客 [blog.gitee.com](https://blog.gitee.com)
3. 你可以 [https://gitee.com/explore](https://gitee.com/explore) 这个地址来了解 Gitee 上的优秀开源项目
4. [GVP](https://gitee.com/gvp) 全称是 Gitee 最有价值开源项目,是综合评定出的优秀开源项目
5. Gitee 官方提供的使用手册 [https://gitee.com/help](https://gitee.com/help)
6. Gitee 封面人物是一档用来展示 Gitee 会员风采的栏目 [https://gitee.com/gitee-stars/](https://gitee.com/gitee-stars/)

@ -0,0 +1,46 @@
target/
!.mvn/wrapper/maven-wrapper.jar
!**/src/main/**/target/
!**/src/test/**/target/
### IntelliJ IDEA ###
.idea/
.idea/modules.xml
.idea/jarRepositories.xml
.idea/compiler.xml
.idea/libraries/
*.iws
*.iml
*.ipr
### Eclipse ###
.apt_generated
.classpath
.factorypath
.project
.settings
.springBeans
.sts4-cache
### NetBeans ###
/nbproject/private/
/nbbuild/
/dist/
/nbdist/
/.nb-gradle/
build/
!**/src/main/**/build/
!**/src/test/**/build/
### VS Code ###
.vscode/
### Mac OS ###
.DS_Store
### log ###
*.log
### db ###
*.db
*.sqlite

@ -0,0 +1,8 @@
# 默认忽略的文件
/shelf/
/workspace.xml
# 基于编辑器的 HTTP 客户端请求
/httpRequests/
# Datasource local storage ignored files
/dataSources/
/dataSources.local.xml

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="Encoding">
<file url="file://$PROJECT_DIR$/src/main/java" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/src/main/resources" charset="UTF-8" />
</component>
</project>

@ -0,0 +1,14 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ExternalStorageConfigurationManager" enabled="true" />
<component name="MavenProjectsManager">
<option name="originalFiles">
<list>
<option value="$PROJECT_DIR$/pom.xml" />
</list>
</option>
</component>
<component name="ProjectRootManager" version="2" languageLevel="JDK_17" default="true" project-jdk-name="corretto-17" project-jdk-type="JavaSDK">
<output url="file://$PROJECT_DIR$/out" />
</component>
</project>

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="$PROJECT_DIR$/.." vcs="Git" />
</component>
</project>

Binary file not shown.

@ -0,0 +1,89 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.musicplayer</groupId>
<artifactId>musicplayer</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<maven.compiler.source>17</maven.compiler.source>
<maven.compiler.target>17</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<javafx.version>21.0.2</javafx.version>
</properties>
<dependencies>
<!-- JavaFX -->
<dependency>
<groupId>org.openjfx</groupId>
<artifactId>javafx-controls</artifactId>
<version>${javafx.version}</version>
</dependency>
<dependency>
<groupId>org.openjfx</groupId>
<artifactId>javafx-fxml</artifactId>
<version>${javafx.version}</version>
</dependency>
<dependency>
<groupId>org.openjfx</groupId>
<artifactId>javafx-media</artifactId>
<version>${javafx.version}</version>
</dependency>
<!-- SQLite -->
<dependency>
<groupId>org.xerial</groupId>
<artifactId>sqlite-jdbc</artifactId>
<version>3.45.1.0</version>
</dependency>
<!-- 其他可能需要的依赖 -->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.14.0</version>
</dependency>
<!-- 日志系统配置 -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>2.0.12</version>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.4.14</version>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-core</artifactId>
<version>1.4.14</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.11.0</version>
<configuration>
<source>17</source>
<target>17</target>
</configuration>
</plugin>
<plugin>
<groupId>org.openjfx</groupId>
<artifactId>javafx-maven-plugin</artifactId>
<version>0.0.8</version>
<configuration>
<mainClass>com.musicplayer.MusicPlayerApp</mainClass>
</configuration>
</plugin>
</plugins>
</build>
</project>

@ -0,0 +1,35 @@
package com.musicplayer;
import com.musicplayer.util.DBUtil;
import com.musicplayer.util.FFmpegUtil;
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Stage;
public class MusicPlayerApp extends Application {
@Override
public void start(Stage primaryStage) throws Exception {
// 测试环境配置
testEnvironment();
// 加载主界面
Parent root = FXMLLoader.load(getClass().getResource("/fxml/player.fxml"));
primaryStage.setTitle("Music Player");
primaryStage.setScene(new Scene(root, 800, 600));
primaryStage.show();
}
private void testEnvironment() {
// 测试FFmpeg
FFmpegUtil.testFFmpeg("demo");
// 测试数据库
//DBUtil.testDatabase();
}
public static void main(String[] args) {
launch(args);
}
}

@ -0,0 +1,36 @@
package com.musicplayer.controller;
import javafx.event.ActionEvent;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class PlayerController {
public void handlePause(ActionEvent actionEvent) {
}
public void handleStop(ActionEvent actionEvent) {
}
public void handleAddSongs(ActionEvent actionEvent) {
}
public void handleExit(ActionEvent actionEvent) {
}
private static final Logger logger = LoggerFactory.getLogger(PlayerController.class);
public void initialize() {
logger.debug("控制器初始化完成");
logger.info("加载用户配置...");
}
public void handlePlay(ActionEvent event) {
try {
logger.info("播放按钮点击");
// 播放逻辑...
} catch (Exception e) {
logger.error("播放失败", e);
}
}
}

@ -0,0 +1,4 @@
package com.musicplayer.model;
public class Playlist {
}

@ -0,0 +1,4 @@
package com.musicplayer.model;
public class Song {
}

@ -0,0 +1,40 @@
package com.musicplayer.util;
import java.nio.charset.StandardCharsets;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.sql.Statement;
public class DBUtil {
private static final String DB_URL = "jdbc:sqlite:musicplayer.db";
private static final String INIT_SCRIPT_PATH = "src/main/resources/db/init.sql";
// 精简后的连接获取方法
public static Connection getConnection() throws SQLException {
initializeDatabase(); // 首次连接时自动初始化
return DriverManager.getConnection(DB_URL);
}
// 数据库初始化逻辑
private static void initializeDatabase() {
if (!Files.exists(Paths.get("musicplayer.db"))) {
try {
String sql = new String(
Files.readAllBytes(Paths.get(INIT_SCRIPT_PATH)),
StandardCharsets.UTF_8
);
try (Connection conn = DriverManager.getConnection(DB_URL);
Statement stmt = conn.createStatement()) {
stmt.executeUpdate(sql);
System.out.println("✅ 数据库初始化完成");
}
} catch (Exception e) {
System.err.println("❌ 数据库初始化失败: " + e.getMessage());
}
}
}
}

@ -0,0 +1,72 @@
package com.musicplayer.util;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
public class FFmpegUtil {
private static final String FFMPEG_EXECUTABLE =
System.getProperty("os.name").toLowerCase().contains("win") ? "ffmpeg.exe" : "ffmpeg";
/**
* FFmpeg
* @return FFmpeg null
*/
public static String configureFromEnv() {
// 1. 首先尝试直接调用ffmpeg假设已在PATH中
if (testFFmpeg(FFMPEG_EXECUTABLE)) {
return FFMPEG_EXECUTABLE;
}
// 2. 遍历PATH环境变量查找
String pathEnv = System.getenv("PATH");
if (pathEnv != null) {
String[] paths = pathEnv.split(System.getProperty("path.separator"));
for (String path : paths) {
Path ffmpegPath = Paths.get(path, FFMPEG_EXECUTABLE);
if (Files.isExecutable(ffmpegPath)) {
return ffmpegPath.toString();
}
}
}
return null;
}
/**
* FFmpeg
* @param ffmpegCommand FFmpeg
* @return
*/
public static boolean testFFmpeg(String ffmpegCommand) {
try {
Process process = new ProcessBuilder(ffmpegCommand, "-version").start();
try (BufferedReader reader = new BufferedReader(
new InputStreamReader(process.getInputStream()))) {
// 检查输出是否包含ffmpeg版本信息
String firstLine = reader.readLine();
return firstLine != null
&& firstLine.contains("ffmpeg")
&& process.waitFor() == 0;
}
} catch (IOException | InterruptedException e) {
return false;
}
}
/**
*
* @return
*/
public static String getConfigStatus() {
String path = configureFromEnv();
if (path != null) {
return "✅ FFmpeg配置成功 (路径: " + path + ")";
} else {
return "❌ FFmpeg未找到请确保已添加到PATH环境变量中";
}
}
}

@ -0,0 +1,29 @@
-- 歌曲表
CREATE TABLE IF NOT EXISTS songs (
id INTEGER PRIMARY KEY AUTOINCREMENT,
title TEXT NOT NULL,
artist TEXT,
album TEXT,
file_path TEXT UNIQUE NOT NULL,
duration INTEGER
);
-- 播放列表表
CREATE TABLE IF NOT EXISTS playlists (
id INTEGER PRIMARY KEY AUTOINCREMENT,
name TEXT NOT NULL UNIQUE
);
-- 播放列表-歌曲关联表
CREATE TABLE IF NOT EXISTS playlist_songs (
playlist_id INTEGER,
song_id INTEGER,
position INTEGER,
PRIMARY KEY (playlist_id, song_id),
FOREIGN KEY (playlist_id) REFERENCES playlists(id) ON DELETE CASCADE,
FOREIGN KEY (song_id) REFERENCES songs(id) ON DELETE CASCADE
);
-- 创建索引提升查询性能
CREATE INDEX IF NOT EXISTS idx_song_artist ON songs(artist);
CREATE INDEX IF NOT EXISTS idx_playlist_name ON playlists(name);

@ -0,0 +1,54 @@
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.control.ListView?>
<?import javafx.scene.control.Menu?>
<?import javafx.scene.control.MenuBar?>
<?import javafx.scene.control.MenuItem?>
<?import javafx.scene.control.Slider?>
<?import javafx.scene.control.SplitPane?>
<?import javafx.scene.layout.BorderPane?>
<?import javafx.scene.layout.HBox?>
<?import javafx.scene.layout.VBox?>
<BorderPane xmlns="http://javafx.com/javafx/21.0.1" xmlns:fx="http://javafx.com/fxml/1" fx:controller="com.musicplayer.controller.PlayerController">
<top>
<MenuBar BorderPane.alignment="CENTER">
<menus>
<Menu text="File">
<items>
<MenuItem onAction="#handleAddSongs" text="Add Songs" />
<MenuItem onAction="#handleExit" text="Exit" />
</items>
</Menu>
</menus>
</MenuBar>
</top>
<center>
<SplitPane dividerPositions="0.3">
<items>
<ListView fx:id="playlistView" />
<VBox>
<ListView fx:id="songListView" />
<HBox alignment="CENTER" spacing="10">
<Button onAction="#handlePlay" text="播放" />
<Button onAction="#handlePause" text="暂停" />
<Button onAction="#handleStop" text="停止" />
<Slider fx:id="volumeSlider" max="1" min="0" value="0.5" />
</HBox>
<Slider fx:id="progressSlider" />
</VBox>
</items>
</SplitPane>
</center>
<bottom>
<HBox alignment="CENTER" spacing="10">
<Label fx:id="currentSongLabel" text="No song selected" />
<Label fx:id="timeLabel" text="00:00 / 00:00" />
</HBox>
</bottom>
</BorderPane>

@ -0,0 +1,34 @@
<?xml version="1.0" encoding="UTF-8"?>
<configuration scan="true" scanPeriod="30 seconds">
<!-- 控制台输出 -->
<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%d{HH:mm:ss.SSS} [%thread] %highlight(%-5level) %cyan(%logger{36}) - %msg%n</pattern>
</encoder>
</appender>
<!-- 文件日志 -->
<appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>logs/musicplayer.log</file>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>logs/musicplayer.%d{yyyy-MM-dd}.%i.log</fileNamePattern>
<maxHistory>7</maxHistory>
<timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
<maxFileSize>10MB</maxFileSize>
</timeBasedFileNamingAndTriggeringPolicy>
</rollingPolicy>
<encoder>
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
</encoder>
</appender>
<!-- 日志级别设置 -->
<logger name="com.musicplayer" level="DEBUG"/>
<logger name="org.jaudiotagger" level="WARN"/> <!-- 音频标签库日志控制 -->
<root level="INFO">
<appender-ref ref="CONSOLE"/>
<appender-ref ref="FILE"/>
</root>
</configuration>

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.
Loading…
Cancel
Save