feat: 更新前端组件 - 改进 App.vue、About.vue 和 Main.vue
This commit is contained in:
@@ -1,5 +1,5 @@
|
|||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { h, ref } from 'vue';
|
import { h, provide, ref } from 'vue';
|
||||||
import { MenuProps, message } from 'ant-design-vue';
|
import { MenuProps, message } from 'ant-design-vue';
|
||||||
import { SettingOutlined, UserOutlined, WindowsOutlined } from '@ant-design/icons-vue';
|
import { SettingOutlined, UserOutlined, WindowsOutlined } from '@ant-design/icons-vue';
|
||||||
import { useRouter } from 'vue-router';
|
import { useRouter } from 'vue-router';
|
||||||
@@ -24,22 +24,35 @@ document.oncontextmenu = (event: any) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
|
let killCoreProcess: (() => void) | null = null;
|
||||||
// 启动后端核心服务
|
// 启动后端核心服务
|
||||||
message.loading("DeEarthX.Core启动中,请勿操作...").then(() => {
|
message.loading("DeEarthX.Core启动中,请勿操作...").then(() => runCoreProcess());
|
||||||
|
|
||||||
|
function runCoreProcess() {
|
||||||
shell.Command.create("core").spawn()
|
shell.Command.create("core").spawn()
|
||||||
.then(() => {
|
.then((e) => {
|
||||||
// 检查后端服务是否成功启动
|
// 检查后端服务是否成功启动
|
||||||
fetch("http://localhost:37019/", { method: "GET" })
|
fetch("http://localhost:37019/", { method: "GET" })
|
||||||
.catch(() => router.push('/error'))
|
.catch(() => router.push('/error'))
|
||||||
.then(() => message.success("DeEarthX.Core 启动成功"));
|
.then(() => message.success("DeEarthX.Core 启动成功"));
|
||||||
console.log("DeEarthX V3 Core");
|
console.log("DeEarthX V3 Core");
|
||||||
|
// 保存进程对象,用于后续终止
|
||||||
|
killCoreProcess = e.kill;
|
||||||
})
|
})
|
||||||
.catch((error) => {
|
.catch((error) => {
|
||||||
console.error(error);
|
console.error(error);
|
||||||
message.error("DeEarthX.Core 启动失败,请检查37019端口是否被占用!");
|
message.error("DeEarthX.Core 启动失败,请检查37019端口是否被占用!");
|
||||||
});
|
});
|
||||||
});
|
}
|
||||||
|
|
||||||
|
provide("killCoreProcess", () => {
|
||||||
|
if (killCoreProcess && typeof killCoreProcess === 'function') {
|
||||||
|
killCoreProcess();
|
||||||
|
killCoreProcess = null;
|
||||||
|
message.info("DeEarthX.Core 重新启动!");
|
||||||
|
runCoreProcess();
|
||||||
|
}
|
||||||
|
}); //全局提供kill方法
|
||||||
|
|
||||||
// 导航菜单配置
|
// 导航菜单配置
|
||||||
const selectedKeys = ref<(string | number)[]>(['main']);
|
const selectedKeys = ref<(string | number)[]>(['main']);
|
||||||
@@ -88,7 +101,7 @@ const theme = ref({
|
|||||||
<a-config-provider :theme="theme">
|
<a-config-provider :theme="theme">
|
||||||
<div class="tw:h-screen tw:w-screen tw:flex tw:flex-col">
|
<div class="tw:h-screen tw:w-screen tw:flex tw:flex-col">
|
||||||
<a-page-header class="tw:h-16" style="border: 1px solid rgb(235, 237, 240)" title="DeEarthX"
|
<a-page-header class="tw:h-16" style="border: 1px solid rgb(235, 237, 240)" title="DeEarthX"
|
||||||
sub-title="V3" :avatar="{ src: './public/dex.png' }">
|
sub-title="V3" :avatar="{ src: './dex.png' }">
|
||||||
<template #extra>
|
<template #extra>
|
||||||
<a-button @click="openAuthorBilibili">作者B站</a-button>
|
<a-button @click="openAuthorBilibili">作者B站</a-button>
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ const sponsors = [
|
|||||||
{
|
{
|
||||||
id: "elfidc",
|
id: "elfidc",
|
||||||
name: "亿讯云",
|
name: "亿讯云",
|
||||||
imageUrl: "../src/assets/elfidc.svg",
|
imageUrl: "./elfidc.svg",
|
||||||
type: "金牌赞助",
|
type: "金牌赞助",
|
||||||
url: "https://www.elfidc.com"
|
url: "https://www.elfidc.com"
|
||||||
}
|
}
|
||||||
@@ -17,18 +17,18 @@ const thanksList = [
|
|||||||
{
|
{
|
||||||
id: "user",
|
id: "user",
|
||||||
name: "天跑",
|
name: "天跑",
|
||||||
avatar: "../src/assets/tianpao.jpg",
|
avatar: "./tianpao.jpg",
|
||||||
contribution: "作者"
|
contribution: "作者"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: "mirror",
|
id: "mirror",
|
||||||
name: "bangbang93",
|
name: "bangbang93",
|
||||||
avatar: "../src/assets/bb93.jpg",
|
avatar: "./bb93.jpg",
|
||||||
contribution: "BMCLAPI镜像"
|
contribution: "BMCLAPI镜像"
|
||||||
},{
|
},{
|
||||||
id: "mirror",
|
id: "mirror",
|
||||||
name: "z0z0r4",
|
name: "z0z0r4",
|
||||||
avatar: "../src/assets/z0z0r4.jpg",
|
avatar: "./z0z0r4.jpg",
|
||||||
contribution: "MCIM镜像"
|
contribution: "MCIM镜像"
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { ref, watch } from 'vue';
|
import { inject, ref, watch } from 'vue';
|
||||||
import { InboxOutlined } from '@ant-design/icons-vue';
|
import { InboxOutlined } from '@ant-design/icons-vue';
|
||||||
import { message, notification, StepsProps } from 'ant-design-vue';
|
import { message, notification, StepsProps } from 'ant-design-vue';
|
||||||
import type { UploadFile, UploadChangeParam } from 'ant-design-vue';
|
import type { UploadFile, UploadChangeParam } from 'ant-design-vue';
|
||||||
@@ -55,6 +55,10 @@ function resetState() {
|
|||||||
currentStep.value = 0;
|
currentStep.value = 0;
|
||||||
unzipProgress.value = { status: 'active', percent: 0, display: true };
|
unzipProgress.value = { status: 'active', percent: 0, display: true };
|
||||||
downloadProgress.value = { status: 'active', percent: 0, display: true };
|
downloadProgress.value = { status: 'active', percent: 0, display: true };
|
||||||
|
const killCoreProcess = inject("killCoreProcess");
|
||||||
|
if (killCoreProcess && typeof killCoreProcess === 'function') {
|
||||||
|
killCoreProcess();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 模式选择相关
|
// 模式选择相关
|
||||||
@@ -90,10 +94,10 @@ const downloadProgress = ref<ProgressStatus>({ status: 'active', percent: 0, dis
|
|||||||
// 运行DeEarthX核心功能
|
// 运行DeEarthX核心功能
|
||||||
async function runDeEarthX(file: Blob) {
|
async function runDeEarthX(file: Blob) {
|
||||||
message.success('开始制作,请勿切换菜单!');
|
message.success('开始制作,请勿切换菜单!');
|
||||||
|
|
||||||
const formData = new FormData();
|
const formData = new FormData();
|
||||||
formData.append('file', file);
|
formData.append('file', file);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const response = await fetch(`http://localhost:37019/start?mode=${selectedMode.value}`, {
|
const response = await fetch(`http://localhost:37019/start?mode=${selectedMode.value}`, {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
@@ -111,11 +115,11 @@ async function runDeEarthX(file: Blob) {
|
|||||||
// 设置WebSocket连接
|
// 设置WebSocket连接
|
||||||
function setupWebSocket() {
|
function setupWebSocket() {
|
||||||
const ws = new WebSocket('ws://localhost:37019/');
|
const ws = new WebSocket('ws://localhost:37019/');
|
||||||
|
|
||||||
ws.addEventListener('message', (event) => {
|
ws.addEventListener('message', (event) => {
|
||||||
try {
|
try {
|
||||||
const data = JSON.parse(event.data) as WebSocketMessage;
|
const data = JSON.parse(event.data) as WebSocketMessage;
|
||||||
|
|
||||||
// 处理不同状态的消息
|
// 处理不同状态的消息
|
||||||
switch (data.status) {
|
switch (data.status) {
|
||||||
case 'error':
|
case 'error':
|
||||||
@@ -139,7 +143,7 @@ function setupWebSocket() {
|
|||||||
notification.error({ message: '错误', description: '解析服务器消息失败' });
|
notification.error({ message: '错误', description: '解析服务器消息失败' });
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
ws.addEventListener('error', () => {
|
ws.addEventListener('error', () => {
|
||||||
notification.error({ message: '错误', description: 'WebSocket连接失败' });
|
notification.error({ message: '错误', description: 'WebSocket连接失败' });
|
||||||
resetState();
|
resetState();
|
||||||
@@ -188,7 +192,7 @@ function handleFinish(result: number) {
|
|||||||
currentStep.value++;
|
currentStep.value++;
|
||||||
message.success(`服务端制作完成!共用时${timeSpent}秒!`);
|
message.success(`服务端制作完成!共用时${timeSpent}秒!`);
|
||||||
sendNotification({ title: 'DeEarthX V3', body: `服务端制作完成!共用时${timeSpent}秒!` });
|
sendNotification({ title: 'DeEarthX V3', body: `服务端制作完成!共用时${timeSpent}秒!` });
|
||||||
|
|
||||||
// 8秒后自动重置状态
|
// 8秒后自动重置状态
|
||||||
setTimeout(resetState, 8000);
|
setTimeout(resetState, 8000);
|
||||||
}
|
}
|
||||||
@@ -199,10 +203,10 @@ function handleStartProcess() {
|
|||||||
message.warning('请先拖拽或选择文件');
|
message.warning('请先拖拽或选择文件');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const file = uploadedFiles.value[0].originFileObj;
|
const file = uploadedFiles.value[0].originFileObj;
|
||||||
if (!file) return;
|
if (!file) return;
|
||||||
|
|
||||||
runDeEarthX(file);
|
runDeEarthX(file);
|
||||||
startButtonDisabled.value = true;
|
startButtonDisabled.value = true;
|
||||||
uploadDisabled.value = true;
|
uploadDisabled.value = true;
|
||||||
@@ -217,9 +221,9 @@ function handleStartProcess() {
|
|||||||
<h1 class="tw:text-4xl tw:text-center tw:animate-pulse">DeEarthX</h1>
|
<h1 class="tw:text-4xl tw:text-center tw:animate-pulse">DeEarthX</h1>
|
||||||
<h1 class="tw:text-sm tw:text-gray-500 tw:text-center">让开服变成随时随地的事情!</h1>
|
<h1 class="tw:text-sm tw:text-gray-500 tw:text-center">让开服变成随时随地的事情!</h1>
|
||||||
</div>
|
</div>
|
||||||
<a-upload-dragger :disabled="uploadDisabled" class="tw:w-full tw:max-w-md tw:h-48" name="file" action="/" :multiple="false"
|
<a-upload-dragger :disabled="uploadDisabled" class="tw:w-full tw:max-w-md tw:h-48" name="file"
|
||||||
:before-upload="beforeUpload" @change="handleFileChange" @drop="handleFileDrop" v-model:fileList="uploadedFiles"
|
action="/" :multiple="false" :before-upload="beforeUpload" @change="handleFileChange"
|
||||||
accept=".zip,.mrpack">
|
@drop="handleFileDrop" v-model:fileList="uploadedFiles" accept=".zip,.mrpack">
|
||||||
<p class="ant-upload-drag-icon">
|
<p class="ant-upload-drag-icon">
|
||||||
<inbox-outlined></inbox-outlined>
|
<inbox-outlined></inbox-outlined>
|
||||||
</p>
|
</p>
|
||||||
@@ -227,32 +231,33 @@ function handleStartProcess() {
|
|||||||
<p class="ant-upload-hint">
|
<p class="ant-upload-hint">
|
||||||
请使用.zip(CurseForge、MCBBS)和.mrpack(Modrinth)文件
|
请使用.zip(CurseForge、MCBBS)和.mrpack(Modrinth)文件
|
||||||
</p>
|
</p>
|
||||||
|
<p class="ant-upload-hint">
|
||||||
|
PCL导出的zip整合包请拖拽里面的modpack.mrpack至DeX
|
||||||
|
</p>
|
||||||
</a-upload-dragger>
|
</a-upload-dragger>
|
||||||
<a-select
|
<a-select ref="select" :options="modeOptions" :value="selectedMode"
|
||||||
ref="select"
|
style="width: 120px;margin-top: 32px" @select="handleModeSelect"></a-select>
|
||||||
:options="modeOptions"
|
<a-button :disabled="startButtonDisabled" type="primary" @click="handleStartProcess"
|
||||||
:value="selectedMode"
|
style="margin-top: 6px">
|
||||||
style="width: 120px;margin-top: 32px"
|
|
||||||
@select="handleModeSelect"
|
|
||||||
></a-select>
|
|
||||||
<a-button :disabled="startButtonDisabled" type="primary" @click="handleStartProcess" style="margin-top: 6px">
|
|
||||||
开始
|
开始
|
||||||
</a-button>
|
</a-button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div v-if="showSteps" class="tw:fixed tw:bottom-2 tw:left-1/2 tw:-translate-x-1/2 tw:w-full tw:max-w-3xl tw:h-16 tw:flex tw:justify-center tw:items-center tw:text-sm">
|
<div v-if="showSteps"
|
||||||
|
class="tw:fixed tw:bottom-2 tw:left-1/2 tw:-translate-x-1/2 tw:w-full tw:max-w-3xl tw:h-16 tw:flex tw:justify-center tw:items-center tw:text-sm">
|
||||||
<a-steps :current="currentStep" :items="stepItems" />
|
<a-steps :current="currentStep" :items="stepItems" />
|
||||||
</div>
|
</div>
|
||||||
<div v-if="showSteps" ref="logContainer" class="tw:absolute tw:right-2 tw:bottom-20 tw:h-80 tw:w-64 tw:rounded-xl tw:overflow-y-auto">
|
<div v-if="showSteps" ref="logContainer"
|
||||||
<a-card title="制作进度" :bordered="true" class="tw:h-full">
|
class="tw:absolute tw:right-2 tw:bottom-20 tw:h-80 tw:w-64 tw:rounded-xl tw:overflow-y-auto">
|
||||||
<div v-if="unzipProgress.display">
|
<a-card title="制作进度" :bordered="true" class="tw:h-full">
|
||||||
<h1 class="tw:text-sm">解压进度</h1>
|
<div v-if="unzipProgress.display">
|
||||||
<a-progress :percent="unzipProgress.percent" :status="unzipProgress.status" size="small" />
|
<h1 class="tw:text-sm">解压进度</h1>
|
||||||
</div>
|
<a-progress :percent="unzipProgress.percent" :status="unzipProgress.status" size="small" />
|
||||||
<div v-if="downloadProgress.display">
|
</div>
|
||||||
<h1 class="tw:text-sm">下载进度</h1>
|
<div v-if="downloadProgress.display">
|
||||||
<a-progress :percent="downloadProgress.percent" :status="downloadProgress.status" size="small" />
|
<h1 class="tw:text-sm">下载进度</h1>
|
||||||
</div>
|
<a-progress :percent="downloadProgress.percent" :status="downloadProgress.status" size="small" />
|
||||||
|
</div>
|
||||||
</a-card>
|
</a-card>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
Reference in New Issue
Block a user