From 9bbc3f488f612b0c6439807587fe07dd897b045d Mon Sep 17 00:00:00 2001
From: octopus_yan <octopus_yan@foxmail.com>
Date: Wed, 30 Oct 2024 00:11:41 +0800
Subject: [PATCH] =?UTF-8?q?pref:=20=E4=BC=98=E5=8C=96GUI=E6=9B=B4=E6=96=B0?=
 =?UTF-8?q?=E5=8A=9F=E8=83=BD=EF=BC=9B=E9=A1=B9=E7=9B=AE=E5=88=86=E4=B8=BA?=
 =?UTF-8?q?gui=E5=92=8Cupgrade=E4=B8=A4=E4=B8=AA=E6=A8=A1=E5=9D=97?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 .gitignore                                    |   1 +
 gui/pom.xml                                   | 315 ++++++++++++++++
 .../cn/octopusyan/alistgui/AppLauncher.java   |   0
 .../cn/octopusyan/alistgui/Application.java   |  27 +-
 .../octopusyan/alistgui/base/BaseBuilder.java |   0
 .../alistgui/base/BaseController.java         |   3 +-
 .../cn/octopusyan/alistgui/base/BaseTask.java |   0
 .../alistgui/base/BaseViewModel.java          |   0
 .../octopusyan/alistgui/config/Constants.java |   2 +-
 .../octopusyan/alistgui/config/Context.java   |   0
 .../cn/octopusyan/alistgui/config/I18n.java   |   0
 .../ObservableResourceBundleFactory.java      |   0
 .../alistgui/controller/AboutController.java  |   5 -
 .../alistgui/controller/MainController.java   |   9 -
 .../controller/PasswordController.java        |   4 -
 .../alistgui/controller/RootController.java   |   7 -
 .../alistgui/controller/SetupController.java  |  10 -
 .../octopusyan/alistgui/enums/ProxySetup.java |   0
 .../alistgui/manager/AListManager.java        |   0
 .../alistgui/manager/ConfigManager.java       |   0
 .../alistgui/manager/ConsoleLog.java          |   0
 .../alistgui/manager/SystemTrayManager.java   |   0
 .../alistgui/manager/http/HttpConfig.java     |   0
 .../alistgui/manager/http/HttpUtil.java       |   0
 .../manager/http/handler/BodyHandler.java     |   0
 .../manager/thread/ThreadFactory.java         |   0
 .../manager/thread/ThreadPoolManager.java     |   0
 .../alistgui/model/AListConfig.java           |   0
 .../octopusyan/alistgui/model/GuiConfig.java  |   0
 .../octopusyan/alistgui/model/ProxyInfo.java  |   0
 .../alistgui/model/UpgradeConfig.java         |   0
 .../alistgui/model/upgrade/AList.java         |   0
 .../alistgui/model/upgrade/Gui.java           |   0
 .../alistgui/model/upgrade/UpgradeApp.java    |   0
 .../alistgui/task/CheckUpdateTask.java        |   0
 .../alistgui/task/DownloadTask.java           |   0
 .../alistgui/task/ProxyCheckTask.java         |   0
 .../alistgui/task/listener/TaskListener.java  |   0
 .../alistgui/util/DownloadUtil.java           |   6 +-
 .../cn/octopusyan/alistgui/util/FxmlUtil.java |   0
 .../cn/octopusyan/alistgui/util/JsonUtil.java |   0
 .../alistgui/util/ProcessesUtil.java          |   2 +-
 .../alistgui/util/PropertiesUtils.java        |   0
 .../cn/octopusyan/alistgui/util/Registry.java |   6 +-
 .../cn/octopusyan/alistgui/util/ViewUtil.java |   0
 .../octopusyan/alistgui/view/PopupMenu.java   |   0
 .../alistgui/view/ProxySetupCell.java         |   0
 .../alistgui/view/alert/AlertUtil.java        |   0
 .../view/alert/builder/AlertBuilder.java      |   0
 .../view/alert/builder/ChoiceBuilder.java     |   0
 .../view/alert/builder/DefaultBuilder.java    |   0
 .../view/alert/builder/ProgressBuilder.java   |   0
 .../view/alert/builder/TextInputBuilder.java  |   0
 .../alistgui/viewModel/AboutViewModule.java   |  15 +-
 .../viewModel/AdminPanelViewModel.java        |   0
 .../alistgui/viewModel/MainViewModel.java     |   0
 .../alistgui/viewModel/RootViewModel.java     |   0
 .../alistgui/viewModel/SetupViewModel.java    |   0
 {src => gui/src}/main/java/module-info.java   |   1 +
 .../main/resources/application.properties     |   0
 .../src}/main/resources/assets/logo-about.png | Bin
 .../main/resources/assets/logo-disabled.png   | Bin
 .../src}/main/resources/assets/logo.png       | Bin
 .../src}/main/resources/assets/logo.svg       |   0
 .../resources/assets/windows/alist-gui.ico    | Bin
 .../src}/main/resources/css/about-view.scss   |   0
 .../src}/main/resources/css/admin-panel.scss  |   0
 .../src}/main/resources/css/main-view.scss    |   0
 .../src}/main/resources/css/root-view.scss    |   0
 {src => gui/src}/main/resources/css/root.scss |   0
 .../src}/main/resources/css/setup-view.scss   |   0
 .../src}/main/resources/fxml/about-view.fxml  |   0
 .../src}/main/resources/fxml/admin-panel.fxml |   0
 .../src}/main/resources/fxml/main-view.fxml   |   0
 .../src}/main/resources/fxml/root-view.fxml   |   0
 .../src}/main/resources/fxml/setup-view.fxml  |   0
 .../resources/language/language.properties    |   0
 .../resources/language/language_en.properties |   0
 .../language/language_zh_CN.properties        |   0
 {src => gui/src}/main/resources/logback.xml   |   0
 pom.xml                                       | 356 +++++-------------
 upgrade/pom.xml                               | 174 +++++++++
 .../cn/octopusyan/upgrade/AppLauncher.java    |  13 +
 .../cn/octopusyan/upgrade/Application.java    |  35 ++
 .../octopusyan/upgrade/alert/AlertUtil.java   |  75 ++++
 .../upgrade/alert/builder/AlertBuilder.java   | 108 ++++++
 .../upgrade/alert/builder/BaseBuilder.java    |  44 +++
 .../cn/octopusyan/upgrade/util/FxmlUtil.java  |  19 +
 .../upgrade/view/HelloController.java         |  83 ++++
 upgrade/src/main/java/module-info.java        |  16 +
 .../src/main/resources/fxml/hello-view.fxml   |  14 +
 .../resources/language/language.properties    |   7 +
 .../resources/language/language_en.properties |   6 +
 .../language/language_zh_CN.properties        |   6 +
 94 files changed, 1056 insertions(+), 313 deletions(-)
 create mode 100644 gui/pom.xml
 rename {src => gui/src}/main/java/cn/octopusyan/alistgui/AppLauncher.java (100%)
 rename {src => gui/src}/main/java/cn/octopusyan/alistgui/Application.java (88%)
 rename {src => gui/src}/main/java/cn/octopusyan/alistgui/base/BaseBuilder.java (100%)
 rename {src => gui/src}/main/java/cn/octopusyan/alistgui/base/BaseController.java (98%)
 rename {src => gui/src}/main/java/cn/octopusyan/alistgui/base/BaseTask.java (100%)
 rename {src => gui/src}/main/java/cn/octopusyan/alistgui/base/BaseViewModel.java (100%)
 rename {src => gui/src}/main/java/cn/octopusyan/alistgui/config/Constants.java (93%)
 rename {src => gui/src}/main/java/cn/octopusyan/alistgui/config/Context.java (100%)
 rename {src => gui/src}/main/java/cn/octopusyan/alistgui/config/I18n.java (100%)
 rename {src => gui/src}/main/java/cn/octopusyan/alistgui/config/ObservableResourceBundleFactory.java (100%)
 rename {src => gui/src}/main/java/cn/octopusyan/alistgui/controller/AboutController.java (87%)
 rename {src => gui/src}/main/java/cn/octopusyan/alistgui/controller/MainController.java (90%)
 rename {src => gui/src}/main/java/cn/octopusyan/alistgui/controller/PasswordController.java (96%)
 rename {src => gui/src}/main/java/cn/octopusyan/alistgui/controller/RootController.java (94%)
 rename {src => gui/src}/main/java/cn/octopusyan/alistgui/controller/SetupController.java (91%)
 rename {src => gui/src}/main/java/cn/octopusyan/alistgui/enums/ProxySetup.java (100%)
 rename {src => gui/src}/main/java/cn/octopusyan/alistgui/manager/AListManager.java (100%)
 rename {src => gui/src}/main/java/cn/octopusyan/alistgui/manager/ConfigManager.java (100%)
 rename {src => gui/src}/main/java/cn/octopusyan/alistgui/manager/ConsoleLog.java (100%)
 rename {src => gui/src}/main/java/cn/octopusyan/alistgui/manager/SystemTrayManager.java (100%)
 rename {src => gui/src}/main/java/cn/octopusyan/alistgui/manager/http/HttpConfig.java (100%)
 rename {src => gui/src}/main/java/cn/octopusyan/alistgui/manager/http/HttpUtil.java (100%)
 rename {src => gui/src}/main/java/cn/octopusyan/alistgui/manager/http/handler/BodyHandler.java (100%)
 rename {src => gui/src}/main/java/cn/octopusyan/alistgui/manager/thread/ThreadFactory.java (100%)
 rename {src => gui/src}/main/java/cn/octopusyan/alistgui/manager/thread/ThreadPoolManager.java (100%)
 rename {src => gui/src}/main/java/cn/octopusyan/alistgui/model/AListConfig.java (100%)
 rename {src => gui/src}/main/java/cn/octopusyan/alistgui/model/GuiConfig.java (100%)
 rename {src => gui/src}/main/java/cn/octopusyan/alistgui/model/ProxyInfo.java (100%)
 rename {src => gui/src}/main/java/cn/octopusyan/alistgui/model/UpgradeConfig.java (100%)
 rename {src => gui/src}/main/java/cn/octopusyan/alistgui/model/upgrade/AList.java (100%)
 rename {src => gui/src}/main/java/cn/octopusyan/alistgui/model/upgrade/Gui.java (100%)
 rename {src => gui/src}/main/java/cn/octopusyan/alistgui/model/upgrade/UpgradeApp.java (100%)
 rename {src => gui/src}/main/java/cn/octopusyan/alistgui/task/CheckUpdateTask.java (100%)
 rename {src => gui/src}/main/java/cn/octopusyan/alistgui/task/DownloadTask.java (100%)
 rename {src => gui/src}/main/java/cn/octopusyan/alistgui/task/ProxyCheckTask.java (100%)
 rename {src => gui/src}/main/java/cn/octopusyan/alistgui/task/listener/TaskListener.java (100%)
 rename {src => gui/src}/main/java/cn/octopusyan/alistgui/util/DownloadUtil.java (96%)
 rename {src => gui/src}/main/java/cn/octopusyan/alistgui/util/FxmlUtil.java (100%)
 rename {src => gui/src}/main/java/cn/octopusyan/alistgui/util/JsonUtil.java (100%)
 rename {src => gui/src}/main/java/cn/octopusyan/alistgui/util/ProcessesUtil.java (97%)
 rename {src => gui/src}/main/java/cn/octopusyan/alistgui/util/PropertiesUtils.java (100%)
 rename {src => gui/src}/main/java/cn/octopusyan/alistgui/util/Registry.java (96%)
 rename {src => gui/src}/main/java/cn/octopusyan/alistgui/util/ViewUtil.java (100%)
 rename {src => gui/src}/main/java/cn/octopusyan/alistgui/view/PopupMenu.java (100%)
 rename {src => gui/src}/main/java/cn/octopusyan/alistgui/view/ProxySetupCell.java (100%)
 rename {src => gui/src}/main/java/cn/octopusyan/alistgui/view/alert/AlertUtil.java (100%)
 rename {src => gui/src}/main/java/cn/octopusyan/alistgui/view/alert/builder/AlertBuilder.java (100%)
 rename {src => gui/src}/main/java/cn/octopusyan/alistgui/view/alert/builder/ChoiceBuilder.java (100%)
 rename {src => gui/src}/main/java/cn/octopusyan/alistgui/view/alert/builder/DefaultBuilder.java (100%)
 rename {src => gui/src}/main/java/cn/octopusyan/alistgui/view/alert/builder/ProgressBuilder.java (100%)
 rename {src => gui/src}/main/java/cn/octopusyan/alistgui/view/alert/builder/TextInputBuilder.java (100%)
 rename {src => gui/src}/main/java/cn/octopusyan/alistgui/viewModel/AboutViewModule.java (92%)
 rename {src => gui/src}/main/java/cn/octopusyan/alistgui/viewModel/AdminPanelViewModel.java (100%)
 rename {src => gui/src}/main/java/cn/octopusyan/alistgui/viewModel/MainViewModel.java (100%)
 rename {src => gui/src}/main/java/cn/octopusyan/alistgui/viewModel/RootViewModel.java (100%)
 rename {src => gui/src}/main/java/cn/octopusyan/alistgui/viewModel/SetupViewModel.java (100%)
 rename {src => gui/src}/main/java/module-info.java (95%)
 rename {src => gui/src}/main/resources/application.properties (100%)
 rename {src => gui/src}/main/resources/assets/logo-about.png (100%)
 rename {src => gui/src}/main/resources/assets/logo-disabled.png (100%)
 rename {src => gui/src}/main/resources/assets/logo.png (100%)
 rename {src => gui/src}/main/resources/assets/logo.svg (100%)
 rename {src => gui/src}/main/resources/assets/windows/alist-gui.ico (100%)
 rename {src => gui/src}/main/resources/css/about-view.scss (100%)
 rename {src => gui/src}/main/resources/css/admin-panel.scss (100%)
 rename {src => gui/src}/main/resources/css/main-view.scss (100%)
 rename {src => gui/src}/main/resources/css/root-view.scss (100%)
 rename {src => gui/src}/main/resources/css/root.scss (100%)
 rename {src => gui/src}/main/resources/css/setup-view.scss (100%)
 rename {src => gui/src}/main/resources/fxml/about-view.fxml (100%)
 rename {src => gui/src}/main/resources/fxml/admin-panel.fxml (100%)
 rename {src => gui/src}/main/resources/fxml/main-view.fxml (100%)
 rename {src => gui/src}/main/resources/fxml/root-view.fxml (100%)
 rename {src => gui/src}/main/resources/fxml/setup-view.fxml (100%)
 rename {src => gui/src}/main/resources/language/language.properties (100%)
 rename {src => gui/src}/main/resources/language/language_en.properties (100%)
 rename {src => gui/src}/main/resources/language/language_zh_CN.properties (100%)
 rename {src => gui/src}/main/resources/logback.xml (100%)
 create mode 100644 upgrade/pom.xml
 create mode 100644 upgrade/src/main/java/cn/octopusyan/upgrade/AppLauncher.java
 create mode 100644 upgrade/src/main/java/cn/octopusyan/upgrade/Application.java
 create mode 100644 upgrade/src/main/java/cn/octopusyan/upgrade/alert/AlertUtil.java
 create mode 100644 upgrade/src/main/java/cn/octopusyan/upgrade/alert/builder/AlertBuilder.java
 create mode 100644 upgrade/src/main/java/cn/octopusyan/upgrade/alert/builder/BaseBuilder.java
 create mode 100644 upgrade/src/main/java/cn/octopusyan/upgrade/util/FxmlUtil.java
 create mode 100644 upgrade/src/main/java/cn/octopusyan/upgrade/view/HelloController.java
 create mode 100644 upgrade/src/main/java/module-info.java
 create mode 100644 upgrade/src/main/resources/fxml/hello-view.fxml
 create mode 100644 upgrade/src/main/resources/language/language.properties
 create mode 100644 upgrade/src/main/resources/language/language_en.properties
 create mode 100644 upgrade/src/main/resources/language/language_zh_CN.properties

diff --git a/.gitignore b/.gitignore
index a2a9479..2523083 100644
--- a/.gitignore
+++ b/.gitignore
@@ -8,6 +8,7 @@ target/
 !**/src/test/**/target/
 /bin/
 gui.yaml
+upgrade.exe
 
 ### IntelliJ IDEA ###
 .idea/
diff --git a/gui/pom.xml b/gui/pom.xml
new file mode 100644
index 0000000..fbb3bd4
--- /dev/null
+++ b/gui/pom.xml
@@ -0,0 +1,315 @@
+<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+
+    <parent>
+        <groupId>cn.octopusyan</groupId>
+        <artifactId>alist-gui</artifactId>
+        <version>1.0.1</version>
+    </parent>
+
+    <artifactId>gui</artifactId>
+    <version>${parent.version}</version>
+    <name>alist-gui</name>
+
+    <properties>
+        <maven.compiler.source>21</maven.compiler.source>
+        <maven.compiler.target>21</maven.compiler.target>
+        <java.version>21</java.version>
+        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
+
+        <exec.mainClass>cn.octopusyan.alistgui.AppLauncher</exec.mainClass>
+        <cssSrcPath>${project.basedir}/src/main/resources/css</cssSrcPath>
+        <cssTargetPath>${project.basedir}/target/classes/css</cssTargetPath>
+    </properties>
+
+    <dependencies>
+
+        <!-- javafx -->
+        <dependency>
+            <groupId>org.openjfx</groupId>
+            <artifactId>javafx-controls</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.openjfx</groupId>
+            <artifactId>javafx-fxml</artifactId>
+        </dependency>
+
+        <!-- https://mkpaz.github.io/atlantafx/ -->
+        <dependency>
+            <groupId>io.github.mkpaz</groupId>
+            <artifactId>atlantafx-base</artifactId>
+        </dependency>
+
+        <!-- slf4j -->
+        <!-- https://slf4j.org/manual.html -->
+        <dependency>
+            <groupId>org.slf4j</groupId>
+            <artifactId>slf4j-api</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>ch.qos.logback</groupId>
+            <artifactId>logback-classic</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>ch.qos.logback</groupId>
+            <artifactId>logback-core</artifactId>
+        </dependency>
+
+        <!-- common -->
+        <!-- https://mvnrepository.com/artifact/org.apache.commons/commons-lang3 -->
+        <dependency>
+            <groupId>org.apache.commons</groupId>
+            <artifactId>commons-lang3</artifactId>
+        </dependency>
+        <!-- https://mvnrepository.com/artifact/org.apache.commons/commons-exec -->
+        <dependency>
+            <groupId>org.apache.commons</groupId>
+            <artifactId>commons-exec</artifactId>
+        </dependency>
+
+        <!-- hutool -->
+        <dependency>
+            <groupId>cn.hutool</groupId>
+            <artifactId>hutool-core</artifactId>
+        </dependency>
+
+        <!-- lombok -->
+        <dependency>
+            <groupId>org.projectlombok</groupId>
+            <artifactId>lombok</artifactId>
+        </dependency>
+
+        <!-- jackson -->
+        <dependency>
+            <groupId>com.fasterxml.jackson.dataformat</groupId>
+            <artifactId>jackson-dataformat-yaml</artifactId>
+        </dependency>
+
+        <!-- https://kordamp.org/ikonli/ -->
+        <dependency>
+            <groupId>org.kordamp.ikonli</groupId>
+            <artifactId>ikonli-javafx</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.kordamp.ikonli</groupId>
+            <artifactId>ikonli-fontawesome-pack</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>com.gluonhq</groupId>
+            <artifactId>emoji</artifactId>
+        </dependency>
+
+    </dependencies>
+
+    <pluginRepositories>
+        <pluginRepository>
+            <id>nexus</id>
+            <name>nexus-snapshot-repository</name>
+            <url>https://oss.sonatype.org/content/repositories/snapshots</url>
+            <snapshots>
+                <enabled>true</enabled>
+                <updatePolicy>always</updatePolicy>
+            </snapshots>
+            <releases>
+                <enabled>false</enabled>
+            </releases>
+        </pluginRepository>
+    </pluginRepositories>
+
+    <build>
+        <resources>
+            <resource>
+                <directory>src/main/resources</directory>
+                <filtering>true</filtering>
+                <excludes>
+                    <exclude>css/*.scss</exclude>
+                </excludes>
+            </resource>
+        </resources>
+
+        <plugins>
+
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-compiler-plugin</artifactId>
+                <version>3.13.0</version>
+                <configuration>
+                    <source>21</source>
+                    <target>21</target>
+                    <compilerArgs>--enable-preview</compilerArgs>
+                    <encoding>UTF-8</encoding>
+                    <annotationProcessorPaths>
+                        <path>
+                            <groupId>org.projectlombok</groupId>
+                            <artifactId>lombok</artifactId>
+                            <version>${lombok.version}</version>
+                        </path>
+                    </annotationProcessorPaths>
+                </configuration>
+            </plugin>
+
+            <!-- https://github.com/HebiRobotics/sass-cli-maven-plugin -->
+            <plugin>
+                <groupId>us.hebi.sass</groupId>
+                <artifactId>sass-cli-maven-plugin</artifactId>
+                <version>1.0.3</version>
+                <configuration>
+                    <sassVersion>1.78.0</sassVersion>
+                    <args> <!-- Any argument that should be forwarded to the sass cli -->
+                        <arg>${cssSrcPath}/root.scss:${cssTargetPath}/root.css</arg>
+                        <arg>${cssSrcPath}/root-view.scss:${cssTargetPath}/root-view.css</arg>
+                        <arg>${cssSrcPath}/main-view.scss:${cssTargetPath}/main-view.css</arg>
+                        <arg>${cssSrcPath}/setup-view.scss:${cssTargetPath}/setup-view.css</arg>
+                        <arg>${cssSrcPath}/about-view.scss:${cssTargetPath}/about-view.css</arg>
+                        <arg>${cssSrcPath}/admin-panel.scss:${cssTargetPath}/admin-panel.css</arg>
+                        <arg>--no-source-map</arg>
+                    </args>
+                </configuration>
+                <executions>
+                    <execution>
+                        <id>sass-exec</id>
+                        <phase>generate-resources</phase>
+                        <goals>
+                            <goal>run</goal>
+                        </goals>
+                    </execution>
+                </executions>
+            </plugin>
+
+            <plugin>
+                <groupId>org.openjfx</groupId>
+                <artifactId>javafx-maven-plugin</artifactId>
+                <version>0.0.8</version>
+                <configuration>
+                    <stripDebug>true</stripDebug>
+                    <compress>2</compress>
+                    <noHeaderFiles>true</noHeaderFiles>
+                    <noManPages>true</noManPages>
+                    <launcher>alistgui</launcher>
+                    <jlinkImageName>app</jlinkImageName>
+                    <jlinkZipName>app</jlinkZipName>
+                    <mainClass>cn.octopusyan.alistgui/${exec.mainClass}</mainClass>
+                </configuration>
+                <executions>
+                    <execution>
+                        <!-- Default configuration for running with: mvn clean javafx:run -->
+                        <id>default-cli</id>
+                        <configuration>
+                            <stripDebug>true</stripDebug>
+                            <compress>2</compress>
+                            <noHeaderFiles>true</noHeaderFiles>
+                            <noManPages>true</noManPages>
+                            <launcher>alist-gui</launcher>
+                            <jlinkImageName>app</jlinkImageName>
+                            <jlinkZipName>app</jlinkZipName>
+                            <mainClass>cn.octopusyan.alistgui/${exec.mainClass}</mainClass>
+                            <options>
+                                <option>--enable-preview</option>
+                                <!--                                <option>-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=*:5005</option>-->
+                            </options>
+                        </configuration>
+                    </execution>
+                </executions>
+            </plugin>
+
+            <!-- https://github.com/fvarrui/JavaPackager -->
+            <plugin>
+                <groupId>io.github.fvarrui</groupId>
+                <artifactId>javapackager</artifactId>
+                <version>1.7.7-SNAPSHOT</version>
+                <configuration>
+                    <mainClass>${exec.mainClass}</mainClass>
+                    <bundleJre>true</bundleJre>
+                    <generateInstaller>false</generateInstaller>
+                    <copyDependencies>true</copyDependencies>
+                    <assetsDir>${project.basedir}/src/main/resources/assets</assetsDir>
+                    <vmArgs>
+                        <arg>--enable-preview</arg>
+                        <arg>-Xmx100m</arg>
+                    </vmArgs>
+                </configuration>
+                <executions>
+                    <execution>
+                        <id>windows</id>
+                        <phase>package</phase>
+                        <goals>
+                            <goal>package</goal>
+                        </goals>
+                        <configuration>
+                            <platform>windows</platform>
+                            <zipballName>${project.name}-windows</zipballName>
+                            <createZipball>true</createZipball>
+                            <winConfig>
+                                <headerType>gui</headerType>
+                                <generateMsi>false</generateMsi>
+                            </winConfig>
+                            <additionalResources>
+                                <additionalResource>${project.basedir}/src/main/resources/static/upgrade.exe
+                                </additionalResource>
+                            </additionalResources>
+                        </configuration>
+                    </execution>
+                    <execution>
+                        <id>windows-nojre</id>
+                        <phase>package</phase>
+                        <goals>
+                            <goal>package</goal>
+                        </goals>
+                        <configuration>
+                            <zipballName>${project.name}-windows-nojre</zipballName>
+                            <platform>windows</platform>
+                            <createZipball>true</createZipball>
+                            <bundleJre>false</bundleJre>
+                            <winConfig>
+                                <headerType>gui</headerType>
+                                <generateMsi>false</generateMsi>
+                            </winConfig>
+                            <additionalResources>
+                                <additionalResource>${project.basedir}/src/main/resources/static/upgrade.exe
+                                </additionalResource>
+                            </additionalResources>
+                        </configuration>
+                    </execution>
+                </executions>
+            </plugin>
+
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-resources-plugin</artifactId>
+                <version>3.3.1</version>
+                <configuration>
+                    <nonFilteredFileExtensions>
+                        <nonFilteredFileExtension>exe</nonFilteredFileExtension>
+                    </nonFilteredFileExtensions>
+                </configuration>
+                <executions>
+                    <execution>
+                        <id>copy-resources</id>
+                        <phase>package</phase>
+                        <goals>
+                            <goal>copy-resources</goal>
+                        </goals>
+                        <configuration>
+                            <encoding>UTF-8</encoding>
+                            <!--打成jar包后复制到的路径-->
+                            <outputDirectory>../target</outputDirectory>
+                            <resources>
+                                <resource>
+                                    <!--项目中需要复制的文件路径-->
+                                    <directory>${project.basedir}/target</directory>
+                                    <includes>
+                                        <include>*.zip</include>
+                                    </includes>
+                                </resource>
+                            </resources>
+                        </configuration>
+                    </execution>
+                </executions>
+            </plugin>
+        </plugins>
+    </build>
+</project>
\ No newline at end of file
diff --git a/src/main/java/cn/octopusyan/alistgui/AppLauncher.java b/gui/src/main/java/cn/octopusyan/alistgui/AppLauncher.java
similarity index 100%
rename from src/main/java/cn/octopusyan/alistgui/AppLauncher.java
rename to gui/src/main/java/cn/octopusyan/alistgui/AppLauncher.java
diff --git a/src/main/java/cn/octopusyan/alistgui/Application.java b/gui/src/main/java/cn/octopusyan/alistgui/Application.java
similarity index 88%
rename from src/main/java/cn/octopusyan/alistgui/Application.java
rename to gui/src/main/java/cn/octopusyan/alistgui/Application.java
index 79c106f..60e18a6 100644
--- a/src/main/java/cn/octopusyan/alistgui/Application.java
+++ b/gui/src/main/java/cn/octopusyan/alistgui/Application.java
@@ -1,5 +1,6 @@
 package cn.octopusyan.alistgui;
 
+import cn.hutool.core.io.FileUtil;
 import cn.octopusyan.alistgui.config.Constants;
 import cn.octopusyan.alistgui.config.Context;
 import cn.octopusyan.alistgui.manager.ConfigManager;
@@ -7,6 +8,7 @@ import cn.octopusyan.alistgui.manager.SystemTrayManager;
 import cn.octopusyan.alistgui.manager.http.HttpConfig;
 import cn.octopusyan.alistgui.manager.http.HttpUtil;
 import cn.octopusyan.alistgui.manager.thread.ThreadPoolManager;
+import cn.octopusyan.alistgui.model.upgrade.Gui;
 import cn.octopusyan.alistgui.util.ProcessesUtil;
 import cn.octopusyan.alistgui.view.alert.AlertUtil;
 import javafx.application.Platform;
@@ -22,6 +24,8 @@ import java.io.*;
 import java.net.*;
 import java.net.http.HttpClient;
 import java.util.Objects;
+import java.util.Timer;
+import java.util.TimerTask;
 import java.util.UUID;
 import java.util.concurrent.CountDownLatch;
 
@@ -31,11 +35,25 @@ public class Application extends javafx.application.Application {
     private static Stage primaryStage;
 
     @Override
-    public void init() {
+    public void init() throws Exception {
         logger.info("application init ...");
 
-        // 单例模式检查
-        makeSingle();
+        long delay = 0L;
+        // 更新重启检查
+        File upgradeFile = new File(Constants.DATA_DIR_PATH + File.separator + new Gui().getReleaseFile());
+        logger.error("{}{}{}", Constants.DATA_DIR_PATH, File.separator, new Gui().getReleaseFile());
+        if (upgradeFile.exists()) {
+            logger.error("upgradeFile.exists");
+            FileUtil.del(upgradeFile);
+            delay = 1000;
+        }
+        new Timer().schedule(new TimerTask() {
+            @Override
+            public void run() {
+                // 单例模式检查
+                makeSingle();
+            }
+        }, delay);
 
         // 初始化客户端配置
         ConfigManager.load();
@@ -85,7 +103,7 @@ public class Application extends javafx.application.Application {
         // 启动主界面
         primaryStage.getIcons().add(new Image(Objects.requireNonNull(this.getClass().getResourceAsStream("/assets/logo.png"))));
         primaryStage.initStyle(StageStyle.TRANSPARENT);
-        primaryStage.setTitle(String.format("%s v%s", Constants.APP_TITLE, Constants.APP_VERSION));
+        primaryStage.setTitle(String.format("%s %s", Constants.APP_TITLE, Constants.APP_VERSION));
         Scene scene = Context.initScene();
         primaryStage.setScene(scene);
 
@@ -147,6 +165,7 @@ public class Application extends javafx.application.Application {
                 instanceCheckLatch.countDown();
 
                 while (true) {
+                    logger.error(STR."====\{instanceId}====");
                     try (
                             Socket clientSocket = serverSocket.accept();
                             BufferedReader in = new BufferedReader(
diff --git a/src/main/java/cn/octopusyan/alistgui/base/BaseBuilder.java b/gui/src/main/java/cn/octopusyan/alistgui/base/BaseBuilder.java
similarity index 100%
rename from src/main/java/cn/octopusyan/alistgui/base/BaseBuilder.java
rename to gui/src/main/java/cn/octopusyan/alistgui/base/BaseBuilder.java
diff --git a/src/main/java/cn/octopusyan/alistgui/base/BaseController.java b/gui/src/main/java/cn/octopusyan/alistgui/base/BaseController.java
similarity index 98%
rename from src/main/java/cn/octopusyan/alistgui/base/BaseController.java
rename to gui/src/main/java/cn/octopusyan/alistgui/base/BaseController.java
index 87ec59d..585c6ee 100644
--- a/src/main/java/cn/octopusyan/alistgui/base/BaseController.java
+++ b/gui/src/main/java/cn/octopusyan/alistgui/base/BaseController.java
@@ -68,7 +68,8 @@ public abstract class BaseController<VM extends BaseViewModel> implements Initia
                         case Labeled labeled -> labeled.textProperty().bind(Context.getLanguageBinding(i18n.key()));
                         case Tab tab -> tab.textProperty().bind(Context.getLanguageBinding(i18n.key()));
                         case MenuItem mi -> mi.textProperty().bind(Context.getLanguageBinding(i18n.key()));
-                        default -> {}
+                        default -> {
+                        }
                     }
                 }
             }
diff --git a/src/main/java/cn/octopusyan/alistgui/base/BaseTask.java b/gui/src/main/java/cn/octopusyan/alistgui/base/BaseTask.java
similarity index 100%
rename from src/main/java/cn/octopusyan/alistgui/base/BaseTask.java
rename to gui/src/main/java/cn/octopusyan/alistgui/base/BaseTask.java
diff --git a/src/main/java/cn/octopusyan/alistgui/base/BaseViewModel.java b/gui/src/main/java/cn/octopusyan/alistgui/base/BaseViewModel.java
similarity index 100%
rename from src/main/java/cn/octopusyan/alistgui/base/BaseViewModel.java
rename to gui/src/main/java/cn/octopusyan/alistgui/base/BaseViewModel.java
diff --git a/src/main/java/cn/octopusyan/alistgui/config/Constants.java b/gui/src/main/java/cn/octopusyan/alistgui/config/Constants.java
similarity index 93%
rename from src/main/java/cn/octopusyan/alistgui/config/Constants.java
rename to gui/src/main/java/cn/octopusyan/alistgui/config/Constants.java
index 7127f24..41f03f0 100644
--- a/src/main/java/cn/octopusyan/alistgui/config/Constants.java
+++ b/gui/src/main/java/cn/octopusyan/alistgui/config/Constants.java
@@ -15,7 +15,7 @@ public class Constants {
     public static final String APP_NAME = PropertiesUtils.getInstance().getProperty("app.name");
     public static final String APP_VERSION = PropertiesUtils.getInstance().getProperty("app.version");
 
-    public static final String DATA_DIR_PATH = Paths.get(".").toFile().getAbsolutePath();
+    public static final String DATA_DIR_PATH = Paths.get("").toFile().getAbsolutePath();
     public static final String BIN_DIR_PATH = STR."\{DATA_DIR_PATH}\{File.separator}bin";
     public static final String TMP_DIR_PATH = System.getProperty("java.io.tmpdir") + APP_NAME;
 
diff --git a/src/main/java/cn/octopusyan/alistgui/config/Context.java b/gui/src/main/java/cn/octopusyan/alistgui/config/Context.java
similarity index 100%
rename from src/main/java/cn/octopusyan/alistgui/config/Context.java
rename to gui/src/main/java/cn/octopusyan/alistgui/config/Context.java
diff --git a/src/main/java/cn/octopusyan/alistgui/config/I18n.java b/gui/src/main/java/cn/octopusyan/alistgui/config/I18n.java
similarity index 100%
rename from src/main/java/cn/octopusyan/alistgui/config/I18n.java
rename to gui/src/main/java/cn/octopusyan/alistgui/config/I18n.java
diff --git a/src/main/java/cn/octopusyan/alistgui/config/ObservableResourceBundleFactory.java b/gui/src/main/java/cn/octopusyan/alistgui/config/ObservableResourceBundleFactory.java
similarity index 100%
rename from src/main/java/cn/octopusyan/alistgui/config/ObservableResourceBundleFactory.java
rename to gui/src/main/java/cn/octopusyan/alistgui/config/ObservableResourceBundleFactory.java
diff --git a/src/main/java/cn/octopusyan/alistgui/controller/AboutController.java b/gui/src/main/java/cn/octopusyan/alistgui/controller/AboutController.java
similarity index 87%
rename from src/main/java/cn/octopusyan/alistgui/controller/AboutController.java
rename to gui/src/main/java/cn/octopusyan/alistgui/controller/AboutController.java
index c2caeb3..282956e 100644
--- a/src/main/java/cn/octopusyan/alistgui/controller/AboutController.java
+++ b/gui/src/main/java/cn/octopusyan/alistgui/controller/AboutController.java
@@ -1,7 +1,6 @@
 package cn.octopusyan.alistgui.controller;
 
 import cn.octopusyan.alistgui.base.BaseController;
-import cn.octopusyan.alistgui.config.I18n;
 import cn.octopusyan.alistgui.manager.ConfigManager;
 import cn.octopusyan.alistgui.viewModel.AboutViewModule;
 import javafx.scene.control.Button;
@@ -22,16 +21,12 @@ public class AboutController extends BaseController<AboutViewModule> {
 
     public Label aListVersion;
 
-    @I18n(key = "about.alist.version")
     public Label aListVersionLabel;
 
-    @I18n(key = "about.app.version")
     public Label appVersionLabel;
 
-    @I18n(key = "about.app.update")
     public Button checkAppVersion;
 
-    @I18n(key = "about.alist.update")
     public Button checkAListVersion;
 
     @Override
diff --git a/src/main/java/cn/octopusyan/alistgui/controller/MainController.java b/gui/src/main/java/cn/octopusyan/alistgui/controller/MainController.java
similarity index 90%
rename from src/main/java/cn/octopusyan/alistgui/controller/MainController.java
rename to gui/src/main/java/cn/octopusyan/alistgui/controller/MainController.java
index 7e14417..1be9c82 100644
--- a/src/main/java/cn/octopusyan/alistgui/controller/MainController.java
+++ b/gui/src/main/java/cn/octopusyan/alistgui/controller/MainController.java
@@ -2,7 +2,6 @@ package cn.octopusyan.alistgui.controller;
 
 import cn.octopusyan.alistgui.base.BaseController;
 import cn.octopusyan.alistgui.config.Context;
-import cn.octopusyan.alistgui.config.I18n;
 import cn.octopusyan.alistgui.manager.AListManager;
 import cn.octopusyan.alistgui.manager.ConsoleLog;
 import cn.octopusyan.alistgui.util.FxmlUtil;
@@ -32,28 +31,20 @@ public class MainController extends BaseController<MainViewModel> {
     public VBox logArea;
     public ScrollPane logAreaSp;
 
-    @I18n(key = "main.status.label-stop")
     public Button statusLabel;
 
-    @I18n(key = "main.control.start")
     public Button startButton;
 
-    @I18n(key = "main.control.password")
     public Button passwordButton;
 
-    @I18n(key = "main.control.restart")
     public Button restartButton;
 
-    @I18n(key = "main.control.more")
     public MenuButton moreButton;
 
-    @I18n(key = "main.more.browser")
     public MenuItem browserButton;
 
-    @I18n(key = "main.more.open-config")
     public MenuItem configButton;
 
-    @I18n(key = "main.more.open-log")
     public MenuItem logButton;
 
     private PasswordController controller;
diff --git a/src/main/java/cn/octopusyan/alistgui/controller/PasswordController.java b/gui/src/main/java/cn/octopusyan/alistgui/controller/PasswordController.java
similarity index 96%
rename from src/main/java/cn/octopusyan/alistgui/controller/PasswordController.java
rename to gui/src/main/java/cn/octopusyan/alistgui/controller/PasswordController.java
index ccb5546..d1c1bc9 100644
--- a/src/main/java/cn/octopusyan/alistgui/controller/PasswordController.java
+++ b/gui/src/main/java/cn/octopusyan/alistgui/controller/PasswordController.java
@@ -4,7 +4,6 @@ import atlantafx.base.controls.Popover;
 import cn.hutool.core.swing.clipboard.ClipboardUtil;
 import cn.octopusyan.alistgui.base.BaseController;
 import cn.octopusyan.alistgui.config.Context;
-import cn.octopusyan.alistgui.config.I18n;
 import cn.octopusyan.alistgui.manager.AListManager;
 import cn.octopusyan.alistgui.viewModel.AdminPanelViewModel;
 import javafx.beans.value.ChangeListener;
@@ -27,14 +26,11 @@ import org.apache.commons.lang3.StringUtils;
 public class PasswordController extends BaseController<AdminPanelViewModel> {
     public AnchorPane adminPanel;
 
-    @I18n(key = "admin.pwd.toptip")
     public Label toptip;
-    @I18n(key = "admin.pwd.user-field")
     public Label usernameLabel;
     public TextField usernameField;
     @FXML
     public Button copyUsername;
-    @I18n(key = "admin.pwd.pwd-field")
     public Label passwordLabel;
     public PasswordField passwordField;
     public Button refreshPassword;
diff --git a/src/main/java/cn/octopusyan/alistgui/controller/RootController.java b/gui/src/main/java/cn/octopusyan/alistgui/controller/RootController.java
similarity index 94%
rename from src/main/java/cn/octopusyan/alistgui/controller/RootController.java
rename to gui/src/main/java/cn/octopusyan/alistgui/controller/RootController.java
index efd9e83..bebc442 100644
--- a/src/main/java/cn/octopusyan/alistgui/controller/RootController.java
+++ b/gui/src/main/java/cn/octopusyan/alistgui/controller/RootController.java
@@ -3,7 +3,6 @@ package cn.octopusyan.alistgui.controller;
 import atlantafx.base.controls.ModalPane;
 import cn.octopusyan.alistgui.base.BaseController;
 import cn.octopusyan.alistgui.config.Context;
-import cn.octopusyan.alistgui.config.I18n;
 import cn.octopusyan.alistgui.manager.ConfigManager;
 import cn.octopusyan.alistgui.manager.SystemTrayManager;
 import cn.octopusyan.alistgui.util.ViewUtil;
@@ -41,19 +40,13 @@ public class RootController extends BaseController<RootViewModel> {
     // 界面
     public TabPane tabPane;
 
-    @I18n(key = "root.tab.main")
     public Tab mainTab;
-    @I18n(key = "root.tab.setup")
     public Tab setupTab;
-    @I18n(key = "root.tab.about")
     public Tab aboutTab;
 
     // footer
-    @I18n(key = "root.foot.doc")
     public Button document;
-    @I18n(key = "root.foot.github")
     public Button github;
-    @I18n(key = "root.foot.sponsor")
     public Button sponsor;
 
     private final ModalPane modalPane = new ModalPane();
diff --git a/src/main/java/cn/octopusyan/alistgui/controller/SetupController.java b/gui/src/main/java/cn/octopusyan/alistgui/controller/SetupController.java
similarity index 91%
rename from src/main/java/cn/octopusyan/alistgui/controller/SetupController.java
rename to gui/src/main/java/cn/octopusyan/alistgui/controller/SetupController.java
index 1f12631..9aa23a5 100644
--- a/src/main/java/cn/octopusyan/alistgui/controller/SetupController.java
+++ b/gui/src/main/java/cn/octopusyan/alistgui/controller/SetupController.java
@@ -3,7 +3,6 @@ package cn.octopusyan.alistgui.controller;
 import atlantafx.base.theme.Theme;
 import cn.octopusyan.alistgui.base.BaseController;
 import cn.octopusyan.alistgui.config.Context;
-import cn.octopusyan.alistgui.config.I18n;
 import cn.octopusyan.alistgui.enums.ProxySetup;
 import cn.octopusyan.alistgui.manager.ConfigManager;
 import cn.octopusyan.alistgui.view.ProxySetupCell;
@@ -31,29 +30,20 @@ public class SetupController extends BaseController<SetupViewModel> implements I
 
     @FXML
     public VBox setupView;
-    @I18n(key = "setup.auto-start.label")
     public CheckBox autoStartCheckBox;
-    @I18n(key = "setup.silent-startup.label")
     public CheckBox silentStartupCheckBox;
-    @I18n(key = "setup.close-to-tray.label")
     public CheckBox closeToTrayCheckBox;
-    @I18n(key = "setup.theme")
     public Label themeLabel;
     public ComboBox<Theme> themeComboBox;
-    @I18n(key = "setup.language")
     public Label languageLabel;
     public ComboBox<Locale> languageComboBox;
-    @I18n(key = "setup.proxy")
     public Label proxySetupLabel;
     public ComboBox<ProxySetup> proxySetupComboBox;
     public Pane proxySetupPane;
-    @I18n(key = "setup.proxy.test")
     public Button proxyCheck;
     public TextField proxyHost;
     public TextField proxyPort;
-    @I18n(key = "setup.proxy.host")
     public Label hostLabel;
-    @I18n(key = "setup.proxy.port")
     public Label portLabel;
 
     @Override
diff --git a/src/main/java/cn/octopusyan/alistgui/enums/ProxySetup.java b/gui/src/main/java/cn/octopusyan/alistgui/enums/ProxySetup.java
similarity index 100%
rename from src/main/java/cn/octopusyan/alistgui/enums/ProxySetup.java
rename to gui/src/main/java/cn/octopusyan/alistgui/enums/ProxySetup.java
diff --git a/src/main/java/cn/octopusyan/alistgui/manager/AListManager.java b/gui/src/main/java/cn/octopusyan/alistgui/manager/AListManager.java
similarity index 100%
rename from src/main/java/cn/octopusyan/alistgui/manager/AListManager.java
rename to gui/src/main/java/cn/octopusyan/alistgui/manager/AListManager.java
diff --git a/src/main/java/cn/octopusyan/alistgui/manager/ConfigManager.java b/gui/src/main/java/cn/octopusyan/alistgui/manager/ConfigManager.java
similarity index 100%
rename from src/main/java/cn/octopusyan/alistgui/manager/ConfigManager.java
rename to gui/src/main/java/cn/octopusyan/alistgui/manager/ConfigManager.java
diff --git a/src/main/java/cn/octopusyan/alistgui/manager/ConsoleLog.java b/gui/src/main/java/cn/octopusyan/alistgui/manager/ConsoleLog.java
similarity index 100%
rename from src/main/java/cn/octopusyan/alistgui/manager/ConsoleLog.java
rename to gui/src/main/java/cn/octopusyan/alistgui/manager/ConsoleLog.java
diff --git a/src/main/java/cn/octopusyan/alistgui/manager/SystemTrayManager.java b/gui/src/main/java/cn/octopusyan/alistgui/manager/SystemTrayManager.java
similarity index 100%
rename from src/main/java/cn/octopusyan/alistgui/manager/SystemTrayManager.java
rename to gui/src/main/java/cn/octopusyan/alistgui/manager/SystemTrayManager.java
diff --git a/src/main/java/cn/octopusyan/alistgui/manager/http/HttpConfig.java b/gui/src/main/java/cn/octopusyan/alistgui/manager/http/HttpConfig.java
similarity index 100%
rename from src/main/java/cn/octopusyan/alistgui/manager/http/HttpConfig.java
rename to gui/src/main/java/cn/octopusyan/alistgui/manager/http/HttpConfig.java
diff --git a/src/main/java/cn/octopusyan/alistgui/manager/http/HttpUtil.java b/gui/src/main/java/cn/octopusyan/alistgui/manager/http/HttpUtil.java
similarity index 100%
rename from src/main/java/cn/octopusyan/alistgui/manager/http/HttpUtil.java
rename to gui/src/main/java/cn/octopusyan/alistgui/manager/http/HttpUtil.java
diff --git a/src/main/java/cn/octopusyan/alistgui/manager/http/handler/BodyHandler.java b/gui/src/main/java/cn/octopusyan/alistgui/manager/http/handler/BodyHandler.java
similarity index 100%
rename from src/main/java/cn/octopusyan/alistgui/manager/http/handler/BodyHandler.java
rename to gui/src/main/java/cn/octopusyan/alistgui/manager/http/handler/BodyHandler.java
diff --git a/src/main/java/cn/octopusyan/alistgui/manager/thread/ThreadFactory.java b/gui/src/main/java/cn/octopusyan/alistgui/manager/thread/ThreadFactory.java
similarity index 100%
rename from src/main/java/cn/octopusyan/alistgui/manager/thread/ThreadFactory.java
rename to gui/src/main/java/cn/octopusyan/alistgui/manager/thread/ThreadFactory.java
diff --git a/src/main/java/cn/octopusyan/alistgui/manager/thread/ThreadPoolManager.java b/gui/src/main/java/cn/octopusyan/alistgui/manager/thread/ThreadPoolManager.java
similarity index 100%
rename from src/main/java/cn/octopusyan/alistgui/manager/thread/ThreadPoolManager.java
rename to gui/src/main/java/cn/octopusyan/alistgui/manager/thread/ThreadPoolManager.java
diff --git a/src/main/java/cn/octopusyan/alistgui/model/AListConfig.java b/gui/src/main/java/cn/octopusyan/alistgui/model/AListConfig.java
similarity index 100%
rename from src/main/java/cn/octopusyan/alistgui/model/AListConfig.java
rename to gui/src/main/java/cn/octopusyan/alistgui/model/AListConfig.java
diff --git a/src/main/java/cn/octopusyan/alistgui/model/GuiConfig.java b/gui/src/main/java/cn/octopusyan/alistgui/model/GuiConfig.java
similarity index 100%
rename from src/main/java/cn/octopusyan/alistgui/model/GuiConfig.java
rename to gui/src/main/java/cn/octopusyan/alistgui/model/GuiConfig.java
diff --git a/src/main/java/cn/octopusyan/alistgui/model/ProxyInfo.java b/gui/src/main/java/cn/octopusyan/alistgui/model/ProxyInfo.java
similarity index 100%
rename from src/main/java/cn/octopusyan/alistgui/model/ProxyInfo.java
rename to gui/src/main/java/cn/octopusyan/alistgui/model/ProxyInfo.java
diff --git a/src/main/java/cn/octopusyan/alistgui/model/UpgradeConfig.java b/gui/src/main/java/cn/octopusyan/alistgui/model/UpgradeConfig.java
similarity index 100%
rename from src/main/java/cn/octopusyan/alistgui/model/UpgradeConfig.java
rename to gui/src/main/java/cn/octopusyan/alistgui/model/UpgradeConfig.java
diff --git a/src/main/java/cn/octopusyan/alistgui/model/upgrade/AList.java b/gui/src/main/java/cn/octopusyan/alistgui/model/upgrade/AList.java
similarity index 100%
rename from src/main/java/cn/octopusyan/alistgui/model/upgrade/AList.java
rename to gui/src/main/java/cn/octopusyan/alistgui/model/upgrade/AList.java
diff --git a/src/main/java/cn/octopusyan/alistgui/model/upgrade/Gui.java b/gui/src/main/java/cn/octopusyan/alistgui/model/upgrade/Gui.java
similarity index 100%
rename from src/main/java/cn/octopusyan/alistgui/model/upgrade/Gui.java
rename to gui/src/main/java/cn/octopusyan/alistgui/model/upgrade/Gui.java
diff --git a/src/main/java/cn/octopusyan/alistgui/model/upgrade/UpgradeApp.java b/gui/src/main/java/cn/octopusyan/alistgui/model/upgrade/UpgradeApp.java
similarity index 100%
rename from src/main/java/cn/octopusyan/alistgui/model/upgrade/UpgradeApp.java
rename to gui/src/main/java/cn/octopusyan/alistgui/model/upgrade/UpgradeApp.java
diff --git a/src/main/java/cn/octopusyan/alistgui/task/CheckUpdateTask.java b/gui/src/main/java/cn/octopusyan/alistgui/task/CheckUpdateTask.java
similarity index 100%
rename from src/main/java/cn/octopusyan/alistgui/task/CheckUpdateTask.java
rename to gui/src/main/java/cn/octopusyan/alistgui/task/CheckUpdateTask.java
diff --git a/src/main/java/cn/octopusyan/alistgui/task/DownloadTask.java b/gui/src/main/java/cn/octopusyan/alistgui/task/DownloadTask.java
similarity index 100%
rename from src/main/java/cn/octopusyan/alistgui/task/DownloadTask.java
rename to gui/src/main/java/cn/octopusyan/alistgui/task/DownloadTask.java
diff --git a/src/main/java/cn/octopusyan/alistgui/task/ProxyCheckTask.java b/gui/src/main/java/cn/octopusyan/alistgui/task/ProxyCheckTask.java
similarity index 100%
rename from src/main/java/cn/octopusyan/alistgui/task/ProxyCheckTask.java
rename to gui/src/main/java/cn/octopusyan/alistgui/task/ProxyCheckTask.java
diff --git a/src/main/java/cn/octopusyan/alistgui/task/listener/TaskListener.java b/gui/src/main/java/cn/octopusyan/alistgui/task/listener/TaskListener.java
similarity index 100%
rename from src/main/java/cn/octopusyan/alistgui/task/listener/TaskListener.java
rename to gui/src/main/java/cn/octopusyan/alistgui/task/listener/TaskListener.java
diff --git a/src/main/java/cn/octopusyan/alistgui/util/DownloadUtil.java b/gui/src/main/java/cn/octopusyan/alistgui/util/DownloadUtil.java
similarity index 96%
rename from src/main/java/cn/octopusyan/alistgui/util/DownloadUtil.java
rename to gui/src/main/java/cn/octopusyan/alistgui/util/DownloadUtil.java
index d74543d..089bd22 100644
--- a/src/main/java/cn/octopusyan/alistgui/util/DownloadUtil.java
+++ b/gui/src/main/java/cn/octopusyan/alistgui/util/DownloadUtil.java
@@ -62,6 +62,10 @@ public class DownloadUtil {
     }
 
     public static void unzip(UpgradeApp app) {
+        unzip(app, true);
+    }
+
+    public static void unzip(UpgradeApp app, boolean del) {
         String parentPath = app instanceof AList ? Constants.BIN_DIR_PATH : Constants.DATA_DIR_PATH;
 
         File file = new File(parentPath + File.separator + app.getReleaseFile());
@@ -93,6 +97,6 @@ public class DownloadUtil {
         });
 
         // 解压完成后删除
-        FileUtil.del(file);
+        if (del) FileUtil.del(file);
     }
 }
diff --git a/src/main/java/cn/octopusyan/alistgui/util/FxmlUtil.java b/gui/src/main/java/cn/octopusyan/alistgui/util/FxmlUtil.java
similarity index 100%
rename from src/main/java/cn/octopusyan/alistgui/util/FxmlUtil.java
rename to gui/src/main/java/cn/octopusyan/alistgui/util/FxmlUtil.java
diff --git a/src/main/java/cn/octopusyan/alistgui/util/JsonUtil.java b/gui/src/main/java/cn/octopusyan/alistgui/util/JsonUtil.java
similarity index 100%
rename from src/main/java/cn/octopusyan/alistgui/util/JsonUtil.java
rename to gui/src/main/java/cn/octopusyan/alistgui/util/JsonUtil.java
diff --git a/src/main/java/cn/octopusyan/alistgui/util/ProcessesUtil.java b/gui/src/main/java/cn/octopusyan/alistgui/util/ProcessesUtil.java
similarity index 97%
rename from src/main/java/cn/octopusyan/alistgui/util/ProcessesUtil.java
rename to gui/src/main/java/cn/octopusyan/alistgui/util/ProcessesUtil.java
index bae8336..9937ade 100644
--- a/src/main/java/cn/octopusyan/alistgui/util/ProcessesUtil.java
+++ b/gui/src/main/java/cn/octopusyan/alistgui/util/ProcessesUtil.java
@@ -53,7 +53,7 @@ public class ProcessesUtil {
         commandLine = CommandLine.parse(command);
         int execute = 0;
         try {
-            execute = executor.execute(commandLine);
+            executor.execute(commandLine, new DefaultExecuteResultHandler());
         } catch (Exception e) {
             log.error("exec", e);
         }
diff --git a/src/main/java/cn/octopusyan/alistgui/util/PropertiesUtils.java b/gui/src/main/java/cn/octopusyan/alistgui/util/PropertiesUtils.java
similarity index 100%
rename from src/main/java/cn/octopusyan/alistgui/util/PropertiesUtils.java
rename to gui/src/main/java/cn/octopusyan/alistgui/util/PropertiesUtils.java
diff --git a/src/main/java/cn/octopusyan/alistgui/util/Registry.java b/gui/src/main/java/cn/octopusyan/alistgui/util/Registry.java
similarity index 96%
rename from src/main/java/cn/octopusyan/alistgui/util/Registry.java
rename to gui/src/main/java/cn/octopusyan/alistgui/util/Registry.java
index f370e9d..cf58ca6 100644
--- a/src/main/java/cn/octopusyan/alistgui/util/Registry.java
+++ b/gui/src/main/java/cn/octopusyan/alistgui/util/Registry.java
@@ -1,5 +1,7 @@
 package cn.octopusyan.alistgui.util;
 
+import lombok.Getter;
+
 /**
  * 注册表编辑
  *
@@ -45,6 +47,7 @@ public class Registry {
         UNLOAD,
     }
 
+    @Getter
     public enum Root {
         HKCR("HKEY_CLASSES_ROOT"),
         HKCU("HKEY_CURRENT_USER"),
@@ -59,9 +62,6 @@ public class Registry {
             this.path = path;
         }
 
-        public String getPath() {
-            return path;
-        }
     }
 
     public enum DataType {
diff --git a/src/main/java/cn/octopusyan/alistgui/util/ViewUtil.java b/gui/src/main/java/cn/octopusyan/alistgui/util/ViewUtil.java
similarity index 100%
rename from src/main/java/cn/octopusyan/alistgui/util/ViewUtil.java
rename to gui/src/main/java/cn/octopusyan/alistgui/util/ViewUtil.java
diff --git a/src/main/java/cn/octopusyan/alistgui/view/PopupMenu.java b/gui/src/main/java/cn/octopusyan/alistgui/view/PopupMenu.java
similarity index 100%
rename from src/main/java/cn/octopusyan/alistgui/view/PopupMenu.java
rename to gui/src/main/java/cn/octopusyan/alistgui/view/PopupMenu.java
diff --git a/src/main/java/cn/octopusyan/alistgui/view/ProxySetupCell.java b/gui/src/main/java/cn/octopusyan/alistgui/view/ProxySetupCell.java
similarity index 100%
rename from src/main/java/cn/octopusyan/alistgui/view/ProxySetupCell.java
rename to gui/src/main/java/cn/octopusyan/alistgui/view/ProxySetupCell.java
diff --git a/src/main/java/cn/octopusyan/alistgui/view/alert/AlertUtil.java b/gui/src/main/java/cn/octopusyan/alistgui/view/alert/AlertUtil.java
similarity index 100%
rename from src/main/java/cn/octopusyan/alistgui/view/alert/AlertUtil.java
rename to gui/src/main/java/cn/octopusyan/alistgui/view/alert/AlertUtil.java
diff --git a/src/main/java/cn/octopusyan/alistgui/view/alert/builder/AlertBuilder.java b/gui/src/main/java/cn/octopusyan/alistgui/view/alert/builder/AlertBuilder.java
similarity index 100%
rename from src/main/java/cn/octopusyan/alistgui/view/alert/builder/AlertBuilder.java
rename to gui/src/main/java/cn/octopusyan/alistgui/view/alert/builder/AlertBuilder.java
diff --git a/src/main/java/cn/octopusyan/alistgui/view/alert/builder/ChoiceBuilder.java b/gui/src/main/java/cn/octopusyan/alistgui/view/alert/builder/ChoiceBuilder.java
similarity index 100%
rename from src/main/java/cn/octopusyan/alistgui/view/alert/builder/ChoiceBuilder.java
rename to gui/src/main/java/cn/octopusyan/alistgui/view/alert/builder/ChoiceBuilder.java
diff --git a/src/main/java/cn/octopusyan/alistgui/view/alert/builder/DefaultBuilder.java b/gui/src/main/java/cn/octopusyan/alistgui/view/alert/builder/DefaultBuilder.java
similarity index 100%
rename from src/main/java/cn/octopusyan/alistgui/view/alert/builder/DefaultBuilder.java
rename to gui/src/main/java/cn/octopusyan/alistgui/view/alert/builder/DefaultBuilder.java
diff --git a/src/main/java/cn/octopusyan/alistgui/view/alert/builder/ProgressBuilder.java b/gui/src/main/java/cn/octopusyan/alistgui/view/alert/builder/ProgressBuilder.java
similarity index 100%
rename from src/main/java/cn/octopusyan/alistgui/view/alert/builder/ProgressBuilder.java
rename to gui/src/main/java/cn/octopusyan/alistgui/view/alert/builder/ProgressBuilder.java
diff --git a/src/main/java/cn/octopusyan/alistgui/view/alert/builder/TextInputBuilder.java b/gui/src/main/java/cn/octopusyan/alistgui/view/alert/builder/TextInputBuilder.java
similarity index 100%
rename from src/main/java/cn/octopusyan/alistgui/view/alert/builder/TextInputBuilder.java
rename to gui/src/main/java/cn/octopusyan/alistgui/view/alert/builder/TextInputBuilder.java
diff --git a/src/main/java/cn/octopusyan/alistgui/viewModel/AboutViewModule.java b/gui/src/main/java/cn/octopusyan/alistgui/viewModel/AboutViewModule.java
similarity index 92%
rename from src/main/java/cn/octopusyan/alistgui/viewModel/AboutViewModule.java
rename to gui/src/main/java/cn/octopusyan/alistgui/viewModel/AboutViewModule.java
index c36fda3..0a0663f 100644
--- a/src/main/java/cn/octopusyan/alistgui/viewModel/AboutViewModule.java
+++ b/gui/src/main/java/cn/octopusyan/alistgui/viewModel/AboutViewModule.java
@@ -1,6 +1,5 @@
 package cn.octopusyan.alistgui.viewModel;
 
-import cn.octopusyan.alistgui.Application;
 import cn.octopusyan.alistgui.base.BaseViewModel;
 import cn.octopusyan.alistgui.config.Constants;
 import cn.octopusyan.alistgui.config.Context;
@@ -142,24 +141,20 @@ public class AboutViewModule extends BaseViewModel {
                     if (upgrade)
                         DownloadUtil.startDownload(app, newVersion, () -> {
 
-                            // 下载完成后,解压并删除文件
-                            DownloadUtil.unzip(app);
-
-                            // 解压后
                             Platform.runLater(() -> {
                                 switch (app) {
                                     case AList _ -> {
+                                        // 下载完成后,解压并删除文件
+                                        DownloadUtil.unzip(app);
                                         // 设置应用版本
                                         aListVersion.setValue(aListNewVersion.getValue());
                                         AListManager.restart();
                                     }
                                     case Gui _ -> {
                                         log.info(STR."guiNewVersion => \{guiNewVersion.get()}");
-                                        // 重启
-                                        Platform.setImplicitExit(true);
-                                        Application.getPrimaryStage().close();
-
-                                        ProcessesUtil.init(Constants.DATA_DIR_PATH).exec(STR."\{Constants.APP_NAME}.exe");
+                                        // 启动升级程序
+                                        ProcessesUtil.init(Constants.DATA_DIR_PATH).exec("upgrade.exe");
+                                        Platform.exit();
                                     }
                                     default -> throw new IllegalStateException(STR."Unexpected value: \{app}");
                                 }
diff --git a/src/main/java/cn/octopusyan/alistgui/viewModel/AdminPanelViewModel.java b/gui/src/main/java/cn/octopusyan/alistgui/viewModel/AdminPanelViewModel.java
similarity index 100%
rename from src/main/java/cn/octopusyan/alistgui/viewModel/AdminPanelViewModel.java
rename to gui/src/main/java/cn/octopusyan/alistgui/viewModel/AdminPanelViewModel.java
diff --git a/src/main/java/cn/octopusyan/alistgui/viewModel/MainViewModel.java b/gui/src/main/java/cn/octopusyan/alistgui/viewModel/MainViewModel.java
similarity index 100%
rename from src/main/java/cn/octopusyan/alistgui/viewModel/MainViewModel.java
rename to gui/src/main/java/cn/octopusyan/alistgui/viewModel/MainViewModel.java
diff --git a/src/main/java/cn/octopusyan/alistgui/viewModel/RootViewModel.java b/gui/src/main/java/cn/octopusyan/alistgui/viewModel/RootViewModel.java
similarity index 100%
rename from src/main/java/cn/octopusyan/alistgui/viewModel/RootViewModel.java
rename to gui/src/main/java/cn/octopusyan/alistgui/viewModel/RootViewModel.java
diff --git a/src/main/java/cn/octopusyan/alistgui/viewModel/SetupViewModel.java b/gui/src/main/java/cn/octopusyan/alistgui/viewModel/SetupViewModel.java
similarity index 100%
rename from src/main/java/cn/octopusyan/alistgui/viewModel/SetupViewModel.java
rename to gui/src/main/java/cn/octopusyan/alistgui/viewModel/SetupViewModel.java
diff --git a/src/main/java/module-info.java b/gui/src/main/java/module-info.java
similarity index 95%
rename from src/main/java/module-info.java
rename to gui/src/main/java/module-info.java
index 9d4dbf6..68949db 100644
--- a/src/main/java/module-info.java
+++ b/gui/src/main/java/module-info.java
@@ -24,4 +24,5 @@ module cn.octopusyan.alistgui {
     opens cn.octopusyan.alistgui.controller to javafx.fxml;
     opens cn.octopusyan.alistgui.base to com.fasterxml.jackson.databind;
     opens cn.octopusyan.alistgui.model.upgrade to com.fasterxml.jackson.databind;
+    exports cn.octopusyan.alistgui.model.upgrade;
 }
\ No newline at end of file
diff --git a/src/main/resources/application.properties b/gui/src/main/resources/application.properties
similarity index 100%
rename from src/main/resources/application.properties
rename to gui/src/main/resources/application.properties
diff --git a/src/main/resources/assets/logo-about.png b/gui/src/main/resources/assets/logo-about.png
similarity index 100%
rename from src/main/resources/assets/logo-about.png
rename to gui/src/main/resources/assets/logo-about.png
diff --git a/src/main/resources/assets/logo-disabled.png b/gui/src/main/resources/assets/logo-disabled.png
similarity index 100%
rename from src/main/resources/assets/logo-disabled.png
rename to gui/src/main/resources/assets/logo-disabled.png
diff --git a/src/main/resources/assets/logo.png b/gui/src/main/resources/assets/logo.png
similarity index 100%
rename from src/main/resources/assets/logo.png
rename to gui/src/main/resources/assets/logo.png
diff --git a/src/main/resources/assets/logo.svg b/gui/src/main/resources/assets/logo.svg
similarity index 100%
rename from src/main/resources/assets/logo.svg
rename to gui/src/main/resources/assets/logo.svg
diff --git a/src/main/resources/assets/windows/alist-gui.ico b/gui/src/main/resources/assets/windows/alist-gui.ico
similarity index 100%
rename from src/main/resources/assets/windows/alist-gui.ico
rename to gui/src/main/resources/assets/windows/alist-gui.ico
diff --git a/src/main/resources/css/about-view.scss b/gui/src/main/resources/css/about-view.scss
similarity index 100%
rename from src/main/resources/css/about-view.scss
rename to gui/src/main/resources/css/about-view.scss
diff --git a/src/main/resources/css/admin-panel.scss b/gui/src/main/resources/css/admin-panel.scss
similarity index 100%
rename from src/main/resources/css/admin-panel.scss
rename to gui/src/main/resources/css/admin-panel.scss
diff --git a/src/main/resources/css/main-view.scss b/gui/src/main/resources/css/main-view.scss
similarity index 100%
rename from src/main/resources/css/main-view.scss
rename to gui/src/main/resources/css/main-view.scss
diff --git a/src/main/resources/css/root-view.scss b/gui/src/main/resources/css/root-view.scss
similarity index 100%
rename from src/main/resources/css/root-view.scss
rename to gui/src/main/resources/css/root-view.scss
diff --git a/src/main/resources/css/root.scss b/gui/src/main/resources/css/root.scss
similarity index 100%
rename from src/main/resources/css/root.scss
rename to gui/src/main/resources/css/root.scss
diff --git a/src/main/resources/css/setup-view.scss b/gui/src/main/resources/css/setup-view.scss
similarity index 100%
rename from src/main/resources/css/setup-view.scss
rename to gui/src/main/resources/css/setup-view.scss
diff --git a/src/main/resources/fxml/about-view.fxml b/gui/src/main/resources/fxml/about-view.fxml
similarity index 100%
rename from src/main/resources/fxml/about-view.fxml
rename to gui/src/main/resources/fxml/about-view.fxml
diff --git a/src/main/resources/fxml/admin-panel.fxml b/gui/src/main/resources/fxml/admin-panel.fxml
similarity index 100%
rename from src/main/resources/fxml/admin-panel.fxml
rename to gui/src/main/resources/fxml/admin-panel.fxml
diff --git a/src/main/resources/fxml/main-view.fxml b/gui/src/main/resources/fxml/main-view.fxml
similarity index 100%
rename from src/main/resources/fxml/main-view.fxml
rename to gui/src/main/resources/fxml/main-view.fxml
diff --git a/src/main/resources/fxml/root-view.fxml b/gui/src/main/resources/fxml/root-view.fxml
similarity index 100%
rename from src/main/resources/fxml/root-view.fxml
rename to gui/src/main/resources/fxml/root-view.fxml
diff --git a/src/main/resources/fxml/setup-view.fxml b/gui/src/main/resources/fxml/setup-view.fxml
similarity index 100%
rename from src/main/resources/fxml/setup-view.fxml
rename to gui/src/main/resources/fxml/setup-view.fxml
diff --git a/src/main/resources/language/language.properties b/gui/src/main/resources/language/language.properties
similarity index 100%
rename from src/main/resources/language/language.properties
rename to gui/src/main/resources/language/language.properties
diff --git a/src/main/resources/language/language_en.properties b/gui/src/main/resources/language/language_en.properties
similarity index 100%
rename from src/main/resources/language/language_en.properties
rename to gui/src/main/resources/language/language_en.properties
diff --git a/src/main/resources/language/language_zh_CN.properties b/gui/src/main/resources/language/language_zh_CN.properties
similarity index 100%
rename from src/main/resources/language/language_zh_CN.properties
rename to gui/src/main/resources/language/language_zh_CN.properties
diff --git a/src/main/resources/logback.xml b/gui/src/main/resources/logback.xml
similarity index 100%
rename from src/main/resources/logback.xml
rename to gui/src/main/resources/logback.xml
diff --git a/pom.xml b/pom.xml
index 8ef597e..27fb5ed 100644
--- a/pom.xml
+++ b/pom.xml
@@ -6,8 +6,9 @@
 
     <groupId>cn.octopusyan</groupId>
     <artifactId>alist-gui</artifactId>
-    <version>1.0.2</version>
+    <version>1.0.1</version>
     <name>alist-gui</name>
+    <packaging>pom</packaging>
 
     <organization>
         <name>octopus_yan</name>
@@ -17,6 +18,11 @@
     <inceptionYear>2024</inceptionYear>
     <description>AList GUI</description>
 
+    <modules>
+        <module>upgrade</module>
+        <module>gui</module>
+    </modules>
+
     <properties>
         <maven.compiler.source>21</maven.compiler.source>
         <maven.compiler.target>21</maven.compiler.target>
@@ -24,9 +30,7 @@
         <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
         <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
 
-        <exec.mainClass>cn.octopusyan.alistgui.AppLauncher</exec.mainClass>
-        <cssSrcPath>${project.basedir}/src/main/resources/css</cssSrcPath>
-        <cssTargetPath>${project.basedir}/target/classes/css</cssTargetPath>
+        <project.version>1.0.1</project.version>
 
         <junit.version>5.10.0</junit.version>
         <javafx.version>21.0.4</javafx.version>
@@ -42,261 +46,99 @@
         <gluonhq-emoji.version>1.0.1</gluonhq-emoji.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>
+    <dependencyManagement>
 
-        <!-- https://mkpaz.github.io/atlantafx/ -->
-        <dependency>
-            <groupId>io.github.mkpaz</groupId>
-            <artifactId>atlantafx-base</artifactId>
-            <version>2.0.1</version>
-        </dependency>
+        <dependencies>
 
-        <!-- slf4j -->
-        <!-- https://slf4j.org/manual.html -->
-        <dependency>
-            <groupId>org.slf4j</groupId>
-            <artifactId>slf4j-api</artifactId>
-            <version>${slf4j.version}</version>
-        </dependency>
-        <dependency>
-            <groupId>ch.qos.logback</groupId>
-            <artifactId>logback-classic</artifactId>
-            <version>${logback.version}</version>
-        </dependency>
-        <dependency>
-            <groupId>ch.qos.logback</groupId>
-            <artifactId>logback-core</artifactId>
-            <version>${logback.version}</version>
-        </dependency>
-
-        <!-- common -->
-        <!-- https://mvnrepository.com/artifact/org.apache.commons/commons-lang3 -->
-        <dependency>
-            <groupId>org.apache.commons</groupId>
-            <artifactId>commons-lang3</artifactId>
-            <version>${common-lang3.version}</version>
-        </dependency>
-        <!-- https://mvnrepository.com/artifact/org.apache.commons/commons-exec -->
-        <dependency>
-            <groupId>org.apache.commons</groupId>
-            <artifactId>commons-exec</artifactId>
-            <version>${common-exec.version}</version>
-        </dependency>
-
-        <!-- hutool -->
-        <dependency>
-            <groupId>cn.hutool</groupId>
-            <artifactId>hutool-core</artifactId>
-            <version>${hutool.version}</version>
-        </dependency>
-
-        <!-- lombok -->
-        <dependency>
-            <groupId>org.projectlombok</groupId>
-            <artifactId>lombok</artifactId>
-            <version>${lombok.version}</version>
-        </dependency>
-
-        <!-- jackson -->
-        <dependency>
-            <groupId>com.fasterxml.jackson.dataformat</groupId>
-            <artifactId>jackson-dataformat-yaml</artifactId>
-            <version>${jackson.version}</version>
-        </dependency>
-
-        <!-- https://kordamp.org/ikonli/ -->
-        <dependency>
-            <groupId>org.kordamp.ikonli</groupId>
-            <artifactId>ikonli-javafx</artifactId>
-            <version>${ikonli.version}</version>
-        </dependency>
-        <dependency>
-            <groupId>org.kordamp.ikonli</groupId>
-            <artifactId>ikonli-fontawesome-pack</artifactId>
-            <version>${ikonli.version}</version>
-        </dependency>
-        <dependency>
-            <groupId>com.gluonhq</groupId>
-            <artifactId>emoji</artifactId>
-            <version>${gluonhq-emoji.version}</version>
-        </dependency>
-
-    </dependencies>
-
-    <pluginRepositories>
-        <pluginRepository>
-            <id>nexus</id>
-            <name>nexus-snapshot-repository</name>
-            <url>https://oss.sonatype.org/content/repositories/snapshots</url>
-            <snapshots>
-                <enabled>true</enabled>
-                <updatePolicy>always</updatePolicy>
-            </snapshots>
-            <releases>
-                <enabled>false</enabled>
-            </releases>
-        </pluginRepository>
-    </pluginRepositories>
-
-    <build>
-        <resources>
-            <resource>
-                <directory>src/main/resources</directory>
-                <filtering>true</filtering>
-                <excludes>
-                    <exclude>css/*.scss</exclude>
-                </excludes>
-            </resource>
-        </resources>
-
-        <plugins>
-
-            <plugin>
-                <groupId>org.apache.maven.plugins</groupId>
-                <artifactId>maven-compiler-plugin</artifactId>
-                <version>3.13.0</version>
-                <configuration>
-                    <source>21</source>
-                    <target>21</target>
-                    <compilerArgs>--enable-preview</compilerArgs>
-                    <encoding>UTF-8</encoding>
-                    <annotationProcessorPaths>
-                        <path>
-                            <groupId>org.projectlombok</groupId>
-                            <artifactId>lombok</artifactId>
-                            <version>${lombok.version}</version>
-                        </path>
-                    </annotationProcessorPaths>
-                </configuration>
-            </plugin>
-
-            <!-- https://github.com/HebiRobotics/sass-cli-maven-plugin -->
-            <plugin>
-                <groupId>us.hebi.sass</groupId>
-                <artifactId>sass-cli-maven-plugin</artifactId>
-                <version>1.0.3</version>
-                <configuration>
-                    <sassVersion>1.78.0</sassVersion>
-                    <args> <!-- Any argument that should be forwarded to the sass cli -->
-                        <arg>${cssSrcPath}/root.scss:${cssTargetPath}/root.css</arg>
-                        <arg>${cssSrcPath}/root-view.scss:${cssTargetPath}/root-view.css</arg>
-                        <arg>${cssSrcPath}/main-view.scss:${cssTargetPath}/main-view.css</arg>
-                        <arg>${cssSrcPath}/setup-view.scss:${cssTargetPath}/setup-view.css</arg>
-                        <arg>${cssSrcPath}/about-view.scss:${cssTargetPath}/about-view.css</arg>
-                        <arg>${cssSrcPath}/admin-panel.scss:${cssTargetPath}/admin-panel.css</arg>
-                        <arg>--no-source-map</arg>
-                    </args>
-                </configuration>
-                <executions>
-                    <execution>
-                        <id>sass-exec</id>
-                        <phase>generate-resources</phase>
-                        <goals>
-                            <goal>run</goal>
-                        </goals>
-                    </execution>
-                </executions>
-            </plugin>
-
-            <plugin>
+            <!-- javafx -->
+            <dependency>
                 <groupId>org.openjfx</groupId>
-                <artifactId>javafx-maven-plugin</artifactId>
-                <version>0.0.8</version>
-                <configuration>
-                    <stripDebug>true</stripDebug>
-                    <compress>2</compress>
-                    <noHeaderFiles>true</noHeaderFiles>
-                    <noManPages>true</noManPages>
-                    <launcher>alistgui</launcher>
-                    <jlinkImageName>app</jlinkImageName>
-                    <jlinkZipName>app</jlinkZipName>
-                    <mainClass>cn.octopusyan.alistgui/${exec.mainClass}</mainClass>
-                </configuration>
-                <executions>
-                    <execution>
-                        <!-- Default configuration for running with: mvn clean javafx:run -->
-                        <id>default-cli</id>
-                        <configuration>
-                            <stripDebug>true</stripDebug>
-                            <compress>2</compress>
-                            <noHeaderFiles>true</noHeaderFiles>
-                            <noManPages>true</noManPages>
-                            <launcher>alist-gui</launcher>
-                            <jlinkImageName>app</jlinkImageName>
-                            <jlinkZipName>app</jlinkZipName>
-                            <mainClass>cn.octopusyan.alistgui/${exec.mainClass}</mainClass>
-                            <options>
-                                <option>--enable-preview</option>
-<!--                                <option>-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=*:5005</option>-->
-                            </options>
-                        </configuration>
-                    </execution>
-                </executions>
-            </plugin>
+                <artifactId>javafx-controls</artifactId>
+                <version>${javafx.version}</version>
+            </dependency>
+            <dependency>
+                <groupId>org.openjfx</groupId>
+                <artifactId>javafx-fxml</artifactId>
+                <version>${javafx.version}</version>
+            </dependency>
 
-            <!-- https://github.com/fvarrui/JavaPackager -->
-            <plugin>
-                <groupId>io.github.fvarrui</groupId>
-                <artifactId>javapackager</artifactId>
-                <version>1.7.7-SNAPSHOT</version>
-                <configuration>
-                    <mainClass>${exec.mainClass}</mainClass>
-                    <bundleJre>true</bundleJre>
-                    <generateInstaller>false</generateInstaller>
-                    <copyDependencies>true</copyDependencies>
-                    <assetsDir>${project.basedir}/src/main/resources/assets</assetsDir>
-                    <vmArgs>
-                        <arg>--enable-preview</arg>
-                        <arg>-Xmx100m</arg>
-                    </vmArgs>
-                </configuration>
-                <executions>
-                    <execution>
-                        <id>windows</id>
-                        <phase>package</phase>
-                        <goals>
-                            <goal>package</goal>
-                        </goals>
-                        <configuration>
-                            <platform>windows</platform>
-                            <zipballName>${project.name}-windows</zipballName>
-                            <createZipball>true</createZipball>
-                            <winConfig>
-                                <headerType>gui</headerType>
-                                <generateMsi>false</generateMsi>
-                            </winConfig>
-                        </configuration>
-                    </execution>
-                    <execution>
-                        <id>windows-nojre</id>
-                        <phase>package</phase>
-                        <goals>
-                            <goal>package</goal>
-                        </goals>
-                        <configuration>
-                            <zipballName>${project.name}-windows-nojre</zipballName>
-                            <platform>windows</platform>
-                            <createZipball>true</createZipball>
-                            <bundleJre>false</bundleJre>
-                            <winConfig>
-                                <headerType>gui</headerType>
-                                <generateMsi>false</generateMsi>
-                            </winConfig>
-                        </configuration>
-                    </execution>
-                </executions>
-            </plugin>
-        </plugins>
-    </build>
+            <!-- https://mkpaz.github.io/atlantafx/ -->
+            <dependency>
+                <groupId>io.github.mkpaz</groupId>
+                <artifactId>atlantafx-base</artifactId>
+                <version>2.0.1</version>
+            </dependency>
+
+            <!-- slf4j -->
+            <!-- https://slf4j.org/manual.html -->
+            <dependency>
+                <groupId>org.slf4j</groupId>
+                <artifactId>slf4j-api</artifactId>
+                <version>${slf4j.version}</version>
+            </dependency>
+            <dependency>
+                <groupId>ch.qos.logback</groupId>
+                <artifactId>logback-classic</artifactId>
+                <version>${logback.version}</version>
+            </dependency>
+            <dependency>
+                <groupId>ch.qos.logback</groupId>
+                <artifactId>logback-core</artifactId>
+                <version>${logback.version}</version>
+            </dependency>
+
+            <!-- common -->
+            <!-- https://mvnrepository.com/artifact/org.apache.commons/commons-lang3 -->
+            <dependency>
+                <groupId>org.apache.commons</groupId>
+                <artifactId>commons-lang3</artifactId>
+                <version>${common-lang3.version}</version>
+            </dependency>
+            <!-- https://mvnrepository.com/artifact/org.apache.commons/commons-exec -->
+            <dependency>
+                <groupId>org.apache.commons</groupId>
+                <artifactId>commons-exec</artifactId>
+                <version>${common-exec.version}</version>
+            </dependency>
+
+            <!-- hutool -->
+            <dependency>
+                <groupId>cn.hutool</groupId>
+                <artifactId>hutool-core</artifactId>
+                <version>${hutool.version}</version>
+            </dependency>
+
+            <!-- lombok -->
+            <dependency>
+                <groupId>org.projectlombok</groupId>
+                <artifactId>lombok</artifactId>
+                <version>${lombok.version}</version>
+            </dependency>
+
+            <!-- jackson -->
+            <dependency>
+                <groupId>com.fasterxml.jackson.dataformat</groupId>
+                <artifactId>jackson-dataformat-yaml</artifactId>
+                <version>${jackson.version}</version>
+            </dependency>
+
+            <!-- https://kordamp.org/ikonli/ -->
+            <dependency>
+                <groupId>org.kordamp.ikonli</groupId>
+                <artifactId>ikonli-javafx</artifactId>
+                <version>${ikonli.version}</version>
+            </dependency>
+            <dependency>
+                <groupId>org.kordamp.ikonli</groupId>
+                <artifactId>ikonli-fontawesome-pack</artifactId>
+                <version>${ikonli.version}</version>
+            </dependency>
+            <dependency>
+                <groupId>com.gluonhq</groupId>
+                <artifactId>emoji</artifactId>
+                <version>${gluonhq-emoji.version}</version>
+            </dependency>
+
+        </dependencies>
+    </dependencyManagement>
 </project>
\ No newline at end of file
diff --git a/upgrade/pom.xml b/upgrade/pom.xml
new file mode 100644
index 0000000..caf4cca
--- /dev/null
+++ b/upgrade/pom.xml
@@ -0,0 +1,174 @@
+<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+
+    <parent>
+        <groupId>cn.octopusyan</groupId>
+        <artifactId>alist-gui</artifactId>
+        <version>1.0.1</version>
+    </parent>
+
+    <artifactId>upgrade</artifactId>
+    <version>${parent.version}</version>
+    <name>upgrade</name>
+
+    <properties>
+        <maven.compiler.source>21</maven.compiler.source>
+        <maven.compiler.target>21</maven.compiler.target>
+        <java.version>21</java.version>
+        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
+
+        <exec.mainClass>cn.octopusyan.upgrade.AppLauncher</exec.mainClass>
+    </properties>
+
+    <dependencies>
+        <!-- javafx -->
+        <dependency>
+            <groupId>org.openjfx</groupId>
+            <artifactId>javafx-controls</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.openjfx</groupId>
+            <artifactId>javafx-fxml</artifactId>
+        </dependency>
+
+        <!-- https://mkpaz.github.io/atlantafx/ -->
+        <dependency>
+            <groupId>io.github.mkpaz</groupId>
+            <artifactId>atlantafx-base</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>cn.hutool</groupId>
+            <artifactId>hutool-core</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.commons</groupId>
+            <artifactId>commons-lang3</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.projectlombok</groupId>
+            <artifactId>lombok</artifactId>
+        </dependency>
+    </dependencies>
+
+    <build>
+        <plugins>
+
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-compiler-plugin</artifactId>
+                <version>3.13.0</version>
+                <configuration>
+                    <source>21</source>
+                    <target>21</target>
+                    <encoding>UTF-8</encoding>
+                    <annotationProcessorPaths>
+                        <path>
+                            <groupId>org.projectlombok</groupId>
+                            <artifactId>lombok</artifactId>
+                            <version>${lombok.version}</version>
+                        </path>
+                    </annotationProcessorPaths>
+                </configuration>
+            </plugin>
+
+            <plugin>
+                <groupId>org.openjfx</groupId>
+                <artifactId>javafx-maven-plugin</artifactId>
+                <version>0.0.8</version>
+                <configuration>
+                    <stripDebug>true</stripDebug>
+                    <compress>2</compress>
+                    <noHeaderFiles>true</noHeaderFiles>
+                    <noManPages>true</noManPages>
+                    <launcher>upgrade</launcher>
+                    <jlinkImageName>app</jlinkImageName>
+                    <jlinkZipName>app</jlinkZipName>
+                    <mainClass>cn.octopusyan.upgrade/${exec.mainClass}</mainClass>
+                </configuration>
+                <executions>
+                    <execution>
+                        <!-- Default configuration for running with: mvn clean javafx:run -->
+                        <id>default-cli</id>
+                        <configuration>
+                            <stripDebug>true</stripDebug>
+                            <compress>2</compress>
+                            <noHeaderFiles>true</noHeaderFiles>
+                            <noManPages>true</noManPages>
+                            <launcher>upgrade</launcher>
+                            <jlinkImageName>app</jlinkImageName>
+                            <jlinkZipName>app</jlinkZipName>
+                            <mainClass>cn.octopusyan.upgrade/${exec.mainClass}</mainClass>
+                        </configuration>
+                    </execution>
+                </executions>
+            </plugin>
+
+            <!-- https://github.com/fvarrui/JavaPackager -->
+            <plugin>
+                <groupId>io.github.fvarrui</groupId>
+                <artifactId>javapackager</artifactId>
+                <version>1.7.7-SNAPSHOT</version>
+                <configuration>
+                    <mainClass>${exec.mainClass}</mainClass>
+                    <bundleJre>true</bundleJre>
+                    <generateInstaller>false</generateInstaller>
+                    <copyDependencies>true</copyDependencies>
+                    <vmArgs>
+                        <arg>-Xmx100m</arg>
+                    </vmArgs>
+                </configuration>
+                <executions>
+                    <execution>
+                        <id>windows</id>
+                        <phase>package</phase>
+                        <goals>
+                            <goal>package</goal>
+                        </goals>
+                        <configuration>
+                            <platform>windows</platform>
+                            <createZipball>false</createZipball>
+                            <winConfig>
+                                <headerType>gui</headerType>
+                                <generateMsi>false</generateMsi>
+                            </winConfig>
+                        </configuration>
+                    </execution>
+                </executions>
+            </plugin>
+
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-resources-plugin</artifactId>
+                <executions>
+                    <execution>
+                        <id>copy-resources</id>
+                        <phase>package</phase>
+                        <goals>
+                            <goal>copy-resources</goal>
+                        </goals>
+                        <configuration>
+                            <encoding>UTF-8</encoding>
+                            <!--打成jar包后复制到的路径-->
+                            <outputDirectory>../gui/src/main/resources/static</outputDirectory>
+                            <resources>
+                                <resource>
+                                    <!--项目中需要复制的文件路径-->
+                                    <directory>./target/upgrade</directory>
+                                    <includes>
+                                        <include>upgrade.exe</include>
+                                    </includes>
+                                </resource>
+                            </resources>
+                        </configuration>
+                    </execution>
+                    <!--可配置多个提取复制路径只需要 “<id>”名字不一样即可-->
+                </executions>
+            </plugin>
+        </plugins>
+    </build>
+</project>
\ No newline at end of file
diff --git a/upgrade/src/main/java/cn/octopusyan/upgrade/AppLauncher.java b/upgrade/src/main/java/cn/octopusyan/upgrade/AppLauncher.java
new file mode 100644
index 0000000..c8b42b3
--- /dev/null
+++ b/upgrade/src/main/java/cn/octopusyan/upgrade/AppLauncher.java
@@ -0,0 +1,13 @@
+package cn.octopusyan.upgrade;
+
+/**
+ * 启动类
+ *
+ * @author octopus_yan@foxmail.com
+ */
+public class AppLauncher {
+
+    public static void main(String[] args) {
+        Application.launch(Application.class, args);
+    }
+}
diff --git a/upgrade/src/main/java/cn/octopusyan/upgrade/Application.java b/upgrade/src/main/java/cn/octopusyan/upgrade/Application.java
new file mode 100644
index 0000000..1f42806
--- /dev/null
+++ b/upgrade/src/main/java/cn/octopusyan/upgrade/Application.java
@@ -0,0 +1,35 @@
+package cn.octopusyan.upgrade;
+
+import atlantafx.base.theme.PrimerLight;
+import cn.octopusyan.upgrade.util.FxmlUtil;
+import javafx.application.Platform;
+import javafx.scene.Scene;
+import javafx.scene.layout.Pane;
+import javafx.stage.Stage;
+
+import java.io.IOException;
+import java.util.ResourceBundle;
+
+public class Application extends javafx.application.Application {
+
+    @Override
+    public void start(Stage primaryStage) throws IOException {
+
+        // 主题样式
+        Application.setUserAgentStylesheet(new PrimerLight().getUserAgentStylesheet());
+
+        // 启动主界面
+        Pane root = FxmlUtil.init("/fxml/hello-view.fxml").load();
+        Scene scene = new Scene(root, 420, 240);
+        primaryStage.setTitle(ResourceBundle.getBundle("language/language").getString("title"));
+        primaryStage.setScene(scene);
+        primaryStage.show();
+    }
+
+    @Override
+    public void stop() {
+        // 关闭主界面
+        Platform.exit();
+        System.exit(0);
+    }
+}
\ No newline at end of file
diff --git a/upgrade/src/main/java/cn/octopusyan/upgrade/alert/AlertUtil.java b/upgrade/src/main/java/cn/octopusyan/upgrade/alert/AlertUtil.java
new file mode 100644
index 0000000..de41bcd
--- /dev/null
+++ b/upgrade/src/main/java/cn/octopusyan/upgrade/alert/AlertUtil.java
@@ -0,0 +1,75 @@
+package cn.octopusyan.upgrade.alert;
+
+import cn.octopusyan.upgrade.alert.builder.*;
+import javafx.scene.control.Alert;
+import javafx.scene.control.ButtonType;
+import javafx.stage.Stage;
+import javafx.stage.Window;
+
+/**
+ * 弹窗工具
+ *
+ * @author octopus_yan@foxmail.com
+ */
+public class AlertUtil {
+    private static Window mOwner;
+
+    public static void initOwner(Stage stage) {
+        AlertUtil.mOwner = stage;
+    }
+
+    public static AlertBuilder info(String content) {
+        return info().content(content).header(null);
+    }
+
+    public static AlertBuilder info() {
+        return alert(Alert.AlertType.INFORMATION);
+    }
+
+    public static AlertBuilder error(String message) {
+        return alert(Alert.AlertType.ERROR).header(null).content(message);
+    }
+
+    public static AlertBuilder warning() {
+        return alert(Alert.AlertType.WARNING);
+    }
+
+    public static AlertBuilder exception(Exception ex) {
+        return alert(Alert.AlertType.ERROR).exception(ex);
+    }
+
+    /**
+     * 确认对话框
+     */
+    public static AlertBuilder confirm() {
+        return alert(Alert.AlertType.CONFIRMATION);
+    }
+
+    /**
+     * 自定义确认对话框 <p>
+     *
+     * @param buttons <code>"Cancel"</code> OR <code>"取消"</code> 为取消按钮
+     */
+    public static AlertBuilder confirm(String... buttons) {
+        return confirm().buttons(buttons);
+    }
+
+    public static AlertBuilder confirm(ButtonType... buttons) {
+        return confirm().buttons(buttons);
+    }
+
+    public static AlertBuilder alert(Alert.AlertType type) {
+        return new AlertBuilder(mOwner, type);
+    }
+
+    public interface OnChoseListener {
+        void confirm();
+
+        default void cancelOrClose(ButtonType buttonType) {
+        }
+    }
+
+    public interface OnClickListener {
+        void onClicked(String result);
+    }
+}
diff --git a/upgrade/src/main/java/cn/octopusyan/upgrade/alert/builder/AlertBuilder.java b/upgrade/src/main/java/cn/octopusyan/upgrade/alert/builder/AlertBuilder.java
new file mode 100644
index 0000000..73885cc
--- /dev/null
+++ b/upgrade/src/main/java/cn/octopusyan/upgrade/alert/builder/AlertBuilder.java
@@ -0,0 +1,108 @@
+package cn.octopusyan.upgrade.alert.builder;
+
+import cn.octopusyan.upgrade.alert.AlertUtil;
+import javafx.scene.control.*;
+import javafx.scene.layout.GridPane;
+import javafx.scene.layout.Priority;
+import javafx.stage.Window;
+import org.apache.commons.lang3.ArrayUtils;
+import org.apache.commons.lang3.StringUtils;
+
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+import java.util.Optional;
+import java.util.stream.Collectors;
+
+/**
+ * @author octopus_yan
+ */
+public class AlertBuilder extends BaseBuilder<AlertBuilder, Alert> {
+
+    public AlertBuilder(Window owner, Alert.AlertType alertType) {
+        super(new Alert(alertType), owner);
+    }
+
+    public AlertBuilder buttons(String... buttons) {
+        dialog.getButtonTypes().addAll(getButtonList(buttons));
+        return this;
+    }
+
+    public AlertBuilder buttons(ButtonType... buttons) {
+        dialog.getButtonTypes().addAll(buttons);
+        return this;
+    }
+
+    public AlertBuilder exception(Exception ex) {
+        dialog.setTitle("Exception Dialog");
+        dialog.setHeaderText(ex.getClass().getSimpleName());
+        dialog.setContentText(ex.getMessage());
+
+        // 创建可扩展的异常。
+        var sw = new StringWriter();
+        var pw = new PrintWriter(sw);
+        ex.printStackTrace(pw);
+        var exceptionText = sw.toString();
+
+        var label = new Label("The exception stacktrace was :");
+
+        var textArea = new TextArea(exceptionText);
+        textArea.setEditable(false);
+        textArea.setWrapText(true);
+
+        textArea.setMaxWidth(Double.MAX_VALUE);
+        textArea.setMaxHeight(Double.MAX_VALUE);
+        GridPane.setVgrow(textArea, Priority.ALWAYS);
+        GridPane.setHgrow(textArea, Priority.ALWAYS);
+
+        var expContent = new GridPane();
+        expContent.setMaxWidth(Double.MAX_VALUE);
+        expContent.add(label, 0, 0);
+        expContent.add(textArea, 0, 1);
+
+        // 将可扩展异常设置到对话框窗格中。
+        dialog.getDialogPane().setExpandableContent(expContent);
+        return this;
+    }
+
+    /**
+     * 获取按钮列表
+     *
+     * @param buttons "Cancel" / "取消" 为取消按钮
+     */
+    private List<ButtonType> getButtonList(String[] buttons) {
+        if (ArrayUtils.isEmpty(buttons)) return Collections.emptyList();
+
+        return Arrays.stream(buttons).map((type) -> {
+            ButtonBar.ButtonData buttonData = ButtonBar.ButtonData.OTHER;
+            if ("cancel".equals(StringUtils.lowerCase(type)) || "取消".equals(type)) {
+                return ButtonType.CANCEL;
+            }
+            return new ButtonType(type, buttonData);
+        }).collect(Collectors.toList());
+    }
+
+    /**
+     * AlertUtil.confirm
+     */
+    public void show(AlertUtil.OnClickListener listener) {
+        Optional<ButtonType> result = dialog.showAndWait();
+        result.ifPresent(r -> listener.onClicked(r.getText()));
+    }
+
+    /**
+     * AlertUtil.confirm
+     */
+    public void show(AlertUtil.OnChoseListener listener) {
+        Optional<ButtonType> result = dialog.showAndWait();
+        result.ifPresent(r -> {
+            if (r == ButtonType.OK) {
+                listener.confirm();
+            } else {
+                listener.cancelOrClose(r);
+            }
+        });
+    }
+}
\ No newline at end of file
diff --git a/upgrade/src/main/java/cn/octopusyan/upgrade/alert/builder/BaseBuilder.java b/upgrade/src/main/java/cn/octopusyan/upgrade/alert/builder/BaseBuilder.java
new file mode 100644
index 0000000..151ce3b
--- /dev/null
+++ b/upgrade/src/main/java/cn/octopusyan/upgrade/alert/builder/BaseBuilder.java
@@ -0,0 +1,44 @@
+package cn.octopusyan.upgrade.alert.builder;
+
+import javafx.application.Platform;
+import javafx.scene.control.Dialog;
+import javafx.stage.Window;
+import lombok.Getter;
+
+/**
+ * @author octopus_yan
+ */
+@Getter
+public abstract class BaseBuilder<T extends BaseBuilder<T, ?>, D extends Dialog<?>> {
+    protected D dialog;
+
+    public BaseBuilder(D dialog, Window mOwner) {
+        this.dialog = dialog;
+        if (mOwner != null)
+            this.dialog.initOwner(mOwner);
+    }
+
+    public T title(String title) {
+        dialog.setTitle(title);
+        return (T) this;
+    }
+
+    public T header(String header) {
+        dialog.setHeaderText(header);
+        return (T) this;
+    }
+
+    public T content(String content) {
+        dialog.setContentText(content);
+        return (T) this;
+    }
+
+    public void show() {
+        Platform.runLater(() -> dialog.showAndWait());
+    }
+
+    public void close() {
+        if (dialog.isShowing())
+            dialog.close();
+    }
+}
diff --git a/upgrade/src/main/java/cn/octopusyan/upgrade/util/FxmlUtil.java b/upgrade/src/main/java/cn/octopusyan/upgrade/util/FxmlUtil.java
new file mode 100644
index 0000000..d9bd0c5
--- /dev/null
+++ b/upgrade/src/main/java/cn/octopusyan/upgrade/util/FxmlUtil.java
@@ -0,0 +1,19 @@
+package cn.octopusyan.upgrade.util;
+
+import javafx.fxml.FXMLLoader;
+import javafx.fxml.JavaFXBuilderFactory;
+
+import java.nio.charset.StandardCharsets;
+import java.util.ResourceBundle;
+
+public class FxmlUtil {
+    public static FXMLLoader init(String path) {
+        return new FXMLLoader(
+                FxmlUtil.class.getResource(path),
+                ResourceBundle.getBundle("language/language"),
+                new JavaFXBuilderFactory(),
+                null,
+                StandardCharsets.UTF_8
+        );
+    }
+}
diff --git a/upgrade/src/main/java/cn/octopusyan/upgrade/view/HelloController.java b/upgrade/src/main/java/cn/octopusyan/upgrade/view/HelloController.java
new file mode 100644
index 0000000..2c7397c
--- /dev/null
+++ b/upgrade/src/main/java/cn/octopusyan/upgrade/view/HelloController.java
@@ -0,0 +1,83 @@
+package cn.octopusyan.upgrade.view;
+
+import cn.hutool.core.io.FileUtil;
+import cn.hutool.core.util.CharsetUtil;
+import cn.hutool.core.util.StrUtil;
+import cn.hutool.core.util.ZipUtil;
+import cn.octopusyan.upgrade.alert.AlertUtil;
+import javafx.application.Platform;
+import javafx.fxml.FXML;
+
+import java.io.*;
+import java.nio.file.Paths;
+import java.util.zip.ZipFile;
+
+public class HelloController {
+    public static final String APP_NAME = "alist-gui";
+    public static final String PARENT_PATH = Paths.get("").toFile().getAbsolutePath();
+
+    @FXML
+    public void onUpdate() {
+        // 更新检查
+        File file = new File(PARENT_PATH + File.separator + APP_NAME + "-windows-nojre.zip");
+        if (!file.exists()) {
+            AlertUtil.error("The upgrade file does not exist!").show();
+            return;
+        }
+
+        // 解压
+        unzip();
+        // 启动GUI
+        startGui();
+        // 退出
+        onExit();
+    }
+
+    @FXML
+    public void onExit() {
+        Platform.exit();
+    }
+
+    private void startGui() {
+        Runtime runtime = Runtime.getRuntime();  //获取Runtime实例
+        //执行命令
+        String[] command = {APP_NAME + ".exe"};
+        try {
+            Process process = runtime.exec(command);
+        } catch (IOException ignored) {
+
+        }
+    }
+
+
+    private void unzip() {
+
+
+        File file = new File(PARENT_PATH + File.separator + APP_NAME + "-windows-nojre.zip");
+        ZipFile zipFile = ZipUtil.toZipFile(file, CharsetUtil.defaultCharset());
+        ZipUtil.read(zipFile, zipEntry -> {
+            String path = zipEntry.getName();
+            if (FileUtil.isWindows()) {
+                // Win系统下
+                path = StrUtil.replace(path, "*", "_");
+            }
+
+            // 打包后文件都在alist-gui文件夹下,解压时去掉
+            path = path.replaceFirst(APP_NAME, "");
+
+            final File outItemFile = FileUtil.file(PARENT_PATH, path);
+            if (zipEntry.isDirectory()) {
+                // 目录
+                //noinspection ResultOfMethodCallIgnored
+                outItemFile.mkdirs();
+            } else {
+                InputStream in = ZipUtil.getStream(zipFile, zipEntry);
+                // 文件
+                FileUtil.writeFromStream(in, outItemFile, false);
+            }
+        });
+
+        // 解压完成后删除
+        FileUtil.del(file);
+    }
+}
\ No newline at end of file
diff --git a/upgrade/src/main/java/module-info.java b/upgrade/src/main/java/module-info.java
new file mode 100644
index 0000000..442f919
--- /dev/null
+++ b/upgrade/src/main/java/module-info.java
@@ -0,0 +1,16 @@
+module cn.octopusyan.upgrade {
+    requires javafx.controls;
+    requires javafx.fxml;
+    requires atlantafx.base;
+    requires cn.hutool.core;
+    requires static lombok;
+    requires org.apache.commons.lang3;
+
+
+    opens cn.octopusyan.upgrade to javafx.fxml;
+    exports cn.octopusyan.upgrade;
+    exports cn.octopusyan.upgrade.util;
+    opens cn.octopusyan.upgrade.util to javafx.fxml;
+    exports cn.octopusyan.upgrade.view;
+    opens cn.octopusyan.upgrade.view to javafx.fxml;
+}
\ No newline at end of file
diff --git a/upgrade/src/main/resources/fxml/hello-view.fxml b/upgrade/src/main/resources/fxml/hello-view.fxml
new file mode 100644
index 0000000..4ad20ba
--- /dev/null
+++ b/upgrade/src/main/resources/fxml/hello-view.fxml
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<?import javafx.geometry.Insets?>
+<?import javafx.scene.control.Button?>
+<?import javafx.scene.layout.HBox?>
+<HBox alignment="CENTER" spacing="20.0" xmlns:fx="http://javafx.com/fxml/1"
+      xmlns="http://javafx.com/javafx/11.0.14-internal"
+      fx:controller="cn.octopusyan.upgrade.view.HelloController">
+    <padding>
+        <Insets bottom="20.0" left="20.0" right="20.0" top="20.0"/>
+    </padding>
+    <Button onAction="#onUpdate" styleClass="large" text="%update"/>
+    <Button onAction="#onExit" styleClass="large" text="%exit"/>
+</HBox>
diff --git a/upgrade/src/main/resources/language/language.properties b/upgrade/src/main/resources/language/language.properties
new file mode 100644
index 0000000..c0f8d4d
--- /dev/null
+++ b/upgrade/src/main/resources/language/language.properties
@@ -0,0 +1,7 @@
+exit=\u9000\u51FA
+title=\u66F4\u65B0
+update=\u66F4\u65B0
+
+
+
+
diff --git a/upgrade/src/main/resources/language/language_en.properties b/upgrade/src/main/resources/language/language_en.properties
new file mode 100644
index 0000000..c94ddea
--- /dev/null
+++ b/upgrade/src/main/resources/language/language_en.properties
@@ -0,0 +1,6 @@
+exit=Exit
+title=Upgrade App
+update=Upgrade
+
+
+
diff --git a/upgrade/src/main/resources/language/language_zh_CN.properties b/upgrade/src/main/resources/language/language_zh_CN.properties
new file mode 100644
index 0000000..b155a5f
--- /dev/null
+++ b/upgrade/src/main/resources/language/language_zh_CN.properties
@@ -0,0 +1,6 @@
+exit=\u9000\u51FA
+title=\u66F4\u65B0
+update=\u66F4\u65B0
+
+
+