feat:UI及部分后端

This commit is contained in:
Tianpao
2025-09-13 21:05:14 +08:00
parent d32768afea
commit c61563c484
29 changed files with 2952 additions and 237 deletions

1229
backend/package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -7,15 +7,26 @@
"type": "module",
"main": "main.js",
"scripts": {
"test": "node main.js"
"test": "tsc&&node dist/main.js",
"rollup": "rollup -c rollup.config.js",
"nexe": "nexe -i ./dist/bundle.js --ico Dex.ico --build -t x86-22.13.0 --output ./dist/Dex-v3-core.exe",
"build": "npm run rollup && npm run nexe"
},
"devDependencies": {
"@rollup/plugin-commonjs": "^28.0.6",
"@rollup/plugin-json": "^6.1.0",
"@rollup/plugin-node-resolve": "^16.0.1",
"@rollup/plugin-typescript": "^12.1.4",
"nexe": "^5.0.0-beta.4",
"rollup": "^4.50.1",
"typescript": "^5.9.2"
},
"dependencies": {
"fs-extra": "^11.3.1",
"got": "^14.4.8",
"p-map": "^7.0.3"
"inquirer": "^12.9.4",
"p-map": "^7.0.3",
"picocolors": "^1.1.1",
"yauzl-promise": "^4.0.0"
}
}

16
backend/src/main.ts Normal file
View File

@@ -0,0 +1,16 @@
import config,{ Config } from "./utils/config.js";
const input = process.argv[2];
switch (input) {
case 'getconfig': //读取配置
process.stdout.write(JSON.stringify(config));
break;
case 'writeconfig': //写入配置
if(process.argv.length < 4){
process.exit(1);
}
Config.write_config(JSON.parse(process.argv[3]));
break;
case 'start':
}

View File

@@ -0,0 +1,73 @@
import got from "got";
import { join } from "node:path";
import { fastdownload, usemirror } from "../utils/utils.js";
import { modpack_info, XPlatform } from "./index.js";
const cf_url = (() => {
if (usemirror) {
return "https://mod.mcimirror.top/curseforge";
} else {
return "https://api.curseforge.com";
}
})();
export interface CurseForgeManifest {
minecraft: {
version: string;
modLoaders: Array<{ id: string }>;
};
files: Array<{ projectID: number; fileID: number }>;
}
export class CurseForge implements XPlatform {
async getinfo(manifest: object): Promise<modpack_info> {
let result: modpack_info = Object.create({});
const local_manifest = manifest as CurseForgeManifest;
if (result && local_manifest)
result.minecraft = local_manifest.minecraft.version;
const id = local_manifest.minecraft.modLoaders[0].id;
const loader_all = id.match(/(.*)-/) as RegExpMatchArray;
result.loader = loader_all[1];
result.loader_version = id.replace(loader_all[0], "");
return result;
}
async downloadfile(manifest: object, path: string): Promise<void> {
const local_manifest = manifest as CurseForgeManifest;
const FileID = JSON.stringify({
fileIds: local_manifest.files.map(
(file: { fileID: number }) => file.fileID
),
});
let tmp: [string, string] | string[][] = [];
await got
.post(cf_url + "/v1/mods/files", {
body: FileID,
headers: {
"Content-Type": "application/json",
"x-api-key":
"$2a$10$ydk0TLDG/Gc6uPMdz7mad.iisj2TaMDytVcIW4gcVP231VKngLBKy",
"User-Agent": "DeEarthX",
},
})
.json()
.then((res: any) => {
res.data.forEach(
(e: { fileName: string; downloadUrl: null | string }) => {
if (e.fileName.endsWith(".zip") || e.downloadUrl == null) {
return;
}
const unpath = join(path + "/mods/", e.fileName);
if (usemirror) {
tmp.push([
"https://mod.mcimirror.top" + new URL(e.downloadUrl).pathname,
unpath,
]);
} else {
tmp.push([e.downloadUrl, unpath]);
}
}
);
});
await fastdownload(tmp as unknown as [string, string]); //下载文件
}
}

View File

@@ -0,0 +1,42 @@
import { CurseForge } from "./curseforge.js";
import { MCBBS } from "./mcbbs.js";
import { Modrinth } from "./modrinth.js";
export interface XPlatform {
getinfo(manifest: object): Promise<modpack_info>;
downloadfile(manifest: object,path:string): Promise<void>;
}
export interface modpack_info {
minecraft: string;
loader: string;
loader_version: string;
}
export function platform(plat: string | undefined): XPlatform {
let platform: XPlatform = Object.create({});
switch (plat) {
case "curseforge":
platform = new CurseForge();
break;
case "modrinth":
platform = new Modrinth();
break;
case "mcbbs":
platform = new MCBBS();
break;
}
return platform;
}
export function what_platform(dud_files: Array<string>) {
if (dud_files.includes("mcbbs.packmeta")) {
return "mcbbs";
} else if (dud_files.includes("manifest.json")) {
return "curseforge";
} else if (dud_files.includes("modrinth.index.json")) {
return "modrinth";
} else {
return undefined;
}
}

View File

@@ -0,0 +1,20 @@
import { CurseForgeManifest } from "./curseforge.js";
import { modpack_info, XPlatform } from "./index.js";
interface MCBBSManifest extends CurseForgeManifest {}
export class MCBBS implements XPlatform {
async getinfo(manifest: object): Promise<modpack_info> {
const result: modpack_info = Object.create({});
const local_manifest = manifest as MCBBSManifest;
if (result && local_manifest)
result.minecraft = local_manifest.minecraft.version;
const id = local_manifest.minecraft.modLoaders[0].id;
const loader_all = id.match(/(.*)-/) as RegExpMatchArray;
result.loader = loader_all[1];
result.loader_version = id.replace(loader_all[0], "");
return result;
}
async downloadfile(urls: [string, string]): Promise<void> {}
}

View File

@@ -0,0 +1,49 @@
import fs from "node:fs";
import { mr_fastdownload, usemirror } from "../utils/utils.js";
import { modpack_info, XPlatform } from "./index.js";
import { join } from "node:path";
interface ModrinthManifest {
files: Array<{ path: string; downloads: string[]; fileSize: number; }>;
dependencies: {
minecraft: string;
forge: string;
neoforge: string;
"fabric-loader": string;
[key: string]: string;
};
}
export class Modrinth implements XPlatform {
async getinfo(manifest: object): Promise<modpack_info> {
let result: modpack_info = Object.create({});
const local_manifest = manifest as ModrinthManifest;
const depkey = Object.keys(local_manifest.dependencies);
const loader = ["forge", "neoforge", "fabric-loader"];
result.minecraft = local_manifest.dependencies.minecraft;
for (let i = 0; i < depkey.length; i++) {
const key = depkey[i];
if (key !== "minecraft" && loader.includes(key)) {
result.loader = key;
result.loader_version = local_manifest.dependencies[key];
}
}
return result;
}
async downloadfile(manifest: object,path:string): Promise<void> {
const index = manifest as ModrinthManifest;
let tmp: [string, string, string][] = []
index.files.forEach(async (e: { path: string; downloads: string[]; fileSize: number;}) => {
if (e.path.endsWith(".zip")) {
return;
}
const unpath = join(path,e.path)
if (usemirror){
tmp.push(["https://mod.mcimirror.top"+new URL(e.downloads[0]).pathname,unpath,String(e.fileSize)])
}else{
tmp.push([e.downloads[0],unpath,String(e.fileSize)])
}
});
await mr_fastdownload(tmp as unknown as [string, string, string])
}
}

View File

@@ -0,0 +1,38 @@
import fs from "fs";
interface IConfig {
mirror: {
bmclapi: boolean;
mcimirror: boolean;
};
filter: {
hashes: boolean;
dexpub: boolean;
mixins: boolean;
};
}
export class Config {
private readonly default_config: IConfig = {
mirror: {
bmclapi: true,
mcimirror: true,
},
filter: {
hashes: true,
dexpub: false,
mixins: true,
},
};
config(): IConfig {
if (!fs.existsSync("./config.json")) {
fs.writeFileSync("./config.json", JSON.stringify(this.default_config));
return this.default_config;
}
return JSON.parse(fs.readFileSync("./config.json", "utf-8"));
}
static write_config(config: IConfig) {
fs.writeFileSync("./config.json", JSON.stringify(config));
}
}
export default new Config().config();

View File

@@ -0,0 +1,14 @@
import config from "./config.js";
export class Utils{
public modrinth_url: string;
public curseforge_url: string;
constructor(){
this.modrinth_url = "https://api.modrinth.com"
this.curseforge_url = "https://api.curseforge.com"
if(config.mirror.mcimirror){
this.modrinth_url = "https://mod.mcimirror.top/modrinth"
this.curseforge_url = "https://mod.mcimirror.top/curseforge"
}
}
}

View File

@@ -3,6 +3,7 @@
<head>
<meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
<link href="./src/tailwind.css" rel="stylesheet">
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>DeEarthX V3</title>
</head>

1021
front/package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -8,19 +8,25 @@
"build": "vue-tsc --noEmit && vite build",
"preview": "vite preview",
"tauri": "tauri",
"tauri-dev":"tauri dev",
"tauri-build":"tauri build"
"tauri-dev": "tauri dev",
"tauri-build": "tauri build"
},
"dependencies": {
"vue": "^3.5.13",
"@ant-design/icons-vue": "^7.0.1",
"@tailwindcss/vite": "^4.1.13",
"@tauri-apps/api": "^2",
"@tauri-apps/plugin-opener": "^2"
"@tauri-apps/plugin-opener": "^2",
"@tauri-apps/plugin-store": "^2.4.0",
"ant-design-vue": "^4.2.6",
"tailwindcss": "^4.1.13",
"vue": "^3.5.13",
"vue-router": "^4.5.1"
},
"devDependencies": {
"@tauri-apps/cli": "^2",
"@vitejs/plugin-vue": "^5.2.1",
"typescript": "~5.6.2",
"vite": "^6.0.3",
"vue-tsc": "^2.1.10",
"@tauri-apps/cli": "^2"
"vue-tsc": "^2.1.10"
}
}

5
front/src-tauri/2 Normal file
View File

@@ -0,0 +1,5 @@
up to date in 749ms
16 packages are looking for funding
run `npm fund` for details

View File

@@ -697,11 +697,13 @@ dependencies = [
name = "dex-v3-ui"
version = "0.1.0"
dependencies = [
"open",
"serde",
"serde_json",
"tauri",
"tauri-build",
"tauri-plugin-opener",
"tauri-plugin-store",
]
[[package]]
@@ -3725,6 +3727,22 @@ dependencies = [
"zbus",
]
[[package]]
name = "tauri-plugin-store"
version = "2.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d85dd80d60a76ee2c2fdce09e9ef30877b239c2a6bb76e6d7d03708aa5f13a19"
dependencies = [
"dunce",
"serde",
"serde_json",
"tauri",
"tauri-plugin",
"thiserror 2.0.16",
"tokio",
"tracing",
]
[[package]]
name = "tauri-runtime"
version = "2.8.0"
@@ -3943,9 +3961,21 @@ dependencies = [
"pin-project-lite",
"slab",
"socket2",
"tokio-macros",
"windows-sys 0.59.0",
]
[[package]]
name = "tokio-macros"
version = "2.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6e06d43f1345a3bcd39f6a56dbb7dcab2ba47e68e8ac134855e7e2bdbaf8cab8"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.106",
]
[[package]]
name = "tokio-util"
version = "0.7.16"

View File

@@ -22,4 +22,6 @@ tauri = { version = "2", features = [] }
tauri-plugin-opener = "2"
serde = { version = "1", features = ["derive"] }
serde_json = "1"
open = "5.3.2"
tauri-plugin-store = "2"

View File

@@ -2,9 +2,12 @@
"$schema": "../gen/schemas/desktop-schema.json",
"identifier": "default",
"description": "Capability for the main window",
"windows": ["main"],
"windows": [
"main"
],
"permissions": [
"core:default",
"opener:default"
"opener:default",
"store:default"
]
}
}

View File

@@ -4,11 +4,21 @@ fn greet(name: &str) -> String {
format!("Hello, {}! You've been greeted from Rust!", name)
}
#[tauri::command]
fn open_url(url: &str) {
match open::that(url) {
Err(_) => println!("Error opening url"),
Ok(_) => println!("Opened url"),
}
}
#[cfg_attr(mobile, tauri::mobile_entry_point)]
pub fn run() {
tauri::Builder::default()
.plugin(tauri_plugin_store::Builder::new().build())
.plugin(tauri_plugin_opener::init())
.invoke_handler(tauri::generate_handler![greet])
.invoke_handler(tauri::generate_handler![open_url])
.run(tauri::generate_context!())
.expect("error while running tauri application");
}

View File

@@ -12,9 +12,10 @@
"app": {
"windows": [
{
"title": "dex-v3-ui",
"width": 800,
"height": 600
"title": "DeEarthX V3",
"width": 1280,
"height": 720,
"dragDropEnabled": false
}
],
"security": {

View File

@@ -1,160 +1,60 @@
<script setup lang="ts">
import { ref } from "vue";
import { invoke } from "@tauri-apps/api/core";
const greetMsg = ref("");
const name = ref("");
async function greet() {
// Learn more about Tauri commands at https://tauri.app/develop/calling-rust/
greetMsg.value = await invoke("greet", { name: name.value });
<script lang="ts" setup>
import { h, ref } from 'vue';
import { MenuProps } from 'ant-design-vue';
import { SettingOutlined, UserOutlined, WindowsOutlined } from '@ant-design/icons-vue';
import { useRouter } from 'vue-router';
const router = useRouter();
const selectedKeys = ref(['main']);
const items: MenuProps['items'] = [
{
key: 'main',
icon: h(WindowsOutlined),
label: '主页',
title: '主页',
},
{
key: 'setting',
icon: h(SettingOutlined),
label: '设置',
title: '设置',
},
{
key: 'about',
icon: h(UserOutlined),
label: '关于',
title: '关于',
}
]
const handleClick: MenuProps['onClick'] = (e) => {
switch (e.key) {
case 'main':
selectedKeys.value[0] = 'main';
router.push('/');
break;
case 'setting':
selectedKeys.value[0] = 'setting';
router.push('/setting');
break;
case 'about':
selectedKeys.value[0] = 'about';
router.push('/about');
break;
default:
break;
}
}
</script>
<template>
<main class="container">
<h1>Welcome to Tauri + Vue</h1>
<div class="row">
<a href="https://vite.dev" target="_blank">
<img src="/vite.svg" class="logo vite" alt="Vite logo" />
</a>
<a href="https://tauri.app" target="_blank">
<img src="/tauri.svg" class="logo tauri" alt="Tauri logo" />
</a>
<a href="https://vuejs.org/" target="_blank">
<img src="./assets/vue.svg" class="logo vue" alt="Vue logo" />
</a>
<div class="tw:h-screen tw:w-screen">
<a-page-header class="tw:fixed tw:h-16" style="border: 1px solid rgb(235, 237, 240)" title="DeEarthX"
sub-title="V3" />
<div class="tw:flex tw:full tw:h-89/100">
<a-menu id="menu" style="width: 144px;" :selectedKeys="selectedKeys" mode="inline" :items="items" @click="handleClick"/>
<RouterView />
</div>
</div>
<p>Click on the Tauri, Vite, and Vue logos to learn more.</p>
<form class="row" @submit.prevent="greet">
<input id="greet-input" v-model="name" placeholder="Enter a name..." />
<button type="submit">Greet</button>
</form>
<p>{{ greetMsg }}</p>
</main>
</template>
<style scoped>
.logo.vite:hover {
filter: drop-shadow(0 0 2em #747bff);
}
.logo.vue:hover {
filter: drop-shadow(0 0 2em #249b73);
}
</style>
<style>
:root {
font-family: Inter, Avenir, Helvetica, Arial, sans-serif;
font-size: 16px;
line-height: 24px;
font-weight: 400;
color: #0f0f0f;
background-color: #f6f6f6;
font-synthesis: none;
text-rendering: optimizeLegibility;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
-webkit-text-size-adjust: 100%;
}
.container {
margin: 0;
padding-top: 10vh;
display: flex;
flex-direction: column;
justify-content: center;
text-align: center;
}
.logo {
height: 6em;
padding: 1.5em;
will-change: filter;
transition: 0.75s;
}
.logo.tauri:hover {
filter: drop-shadow(0 0 2em #24c8db);
}
.row {
display: flex;
justify-content: center;
}
a {
font-weight: 500;
color: #646cff;
text-decoration: inherit;
}
a:hover {
color: #535bf2;
}
h1 {
text-align: center;
}
input,
button {
border-radius: 8px;
border: 1px solid transparent;
padding: 0.6em 1.2em;
font-size: 1em;
font-weight: 500;
font-family: inherit;
color: #0f0f0f;
background-color: #ffffff;
transition: border-color 0.25s;
box-shadow: 0 2px 2px rgba(0, 0, 0, 0.2);
}
button {
cursor: pointer;
}
button:hover {
border-color: #396cd8;
}
button:active {
border-color: #396cd8;
background-color: #e8e8e8;
}
input,
button {
outline: none;
}
#greet-input {
margin-right: 5px;
}
@media (prefers-color-scheme: dark) {
:root {
color: #f6f6f6;
background-color: #2f2f2f;
}
a:hover {
color: #24c8db;
}
input,
button {
color: #ffffff;
background-color: #0f0f0f98;
}
button:active {
background-color: #0f0f0f69;
}
}
</style>
<style scoped></style>

160
front/src/App.vuex111 Normal file
View File

@@ -0,0 +1,160 @@
<script setup lang="ts">
import { ref } from "vue";
import { invoke } from "@tauri-apps/api/core";
const greetMsg = ref("");
const name = ref("");
async function greet() {
// Learn more about Tauri commands at https://tauri.app/develop/calling-rust/
greetMsg.value = await invoke("greet", { name: name.value });
}
</script>
<template>
<main class="container">
<h1>Welcome to Tauri + Vue</h1>
<div class="row">
<a href="https://vite.dev" target="_blank">
<img src="/vite.svg" class="logo vite" alt="Vite logo" />
</a>
<a href="https://tauri.app" target="_blank">
<img src="/tauri.svg" class="logo tauri" alt="Tauri logo" />
</a>
<a href="https://vuejs.org/" target="_blank">
<img src="./assets/vue.svg" class="logo vue" alt="Vue logo" />
</a>
</div>
<p>Click on the Tauri, Vite, and Vue logos to learn more.</p>
<form class="row" @submit.prevent="greet">
<input id="greet-input" v-model="name" placeholder="Enter a name..." />
<button type="submit">Greet</button>
</form>
<p>{{ greetMsg }}</p>
</main>
</template>
<style scoped>
.logo.vite:hover {
filter: drop-shadow(0 0 2em #747bff);
}
.logo.vue:hover {
filter: drop-shadow(0 0 2em #249b73);
}
</style>
<style>
:root {
font-family: Inter, Avenir, Helvetica, Arial, sans-serif;
font-size: 16px;
line-height: 24px;
font-weight: 400;
color: #0f0f0f;
background-color: #f6f6f6;
font-synthesis: none;
text-rendering: optimizeLegibility;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
-webkit-text-size-adjust: 100%;
}
.container {
margin: 0;
padding-top: 10vh;
display: flex;
flex-direction: column;
justify-content: center;
text-align: center;
}
.logo {
height: 6em;
padding: 1.5em;
will-change: filter;
transition: 0.75s;
}
.logo.tauri:hover {
filter: drop-shadow(0 0 2em #24c8db);
}
.row {
display: flex;
justify-content: center;
}
a {
font-weight: 500;
color: #646cff;
text-decoration: inherit;
}
a:hover {
color: #535bf2;
}
h1 {
text-align: center;
}
input,
button {
border-radius: 8px;
border: 1px solid transparent;
padding: 0.6em 1.2em;
font-size: 1em;
font-weight: 500;
font-family: inherit;
color: #0f0f0f;
background-color: #ffffff;
transition: border-color 0.25s;
box-shadow: 0 2px 2px rgba(0, 0, 0, 0.2);
}
button {
cursor: pointer;
}
button:hover {
border-color: #396cd8;
}
button:active {
border-color: #396cd8;
background-color: #e8e8e8;
}
input,
button {
outline: none;
}
#greet-input {
margin-right: 5px;
}
@media (prefers-color-scheme: dark) {
:root {
color: #f6f6f6;
background-color: #2f2f2f;
}
a:hover {
color: #24c8db;
}
input,
button {
color: #ffffff;
background-color: #0f0f0f98;
}
button:active {
background-color: #0f0f0f69;
}
}
</style>

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 30 KiB

View File

@@ -0,0 +1,26 @@
<script lang="ts" setup>
import { invoke } from "@tauri-apps/api/core";
async function contant(idc:string){
let url:string = "";
switch (idc){
case "elfidc":
url = "https://www.elfidc.com";
break;
default:
break;
}
await invoke("open_url",{url})
}
</script>
<template>
<div class="tw:h-full tw:w-full">
<div class="w-full h-64"> <!-- 广告位 -->
<h1 class="tw:text-2xl tw:text-center tw:bg-gradient-to-r tw:from-emerald-500 tw:to-cyan-500 tw:bg-clip-text tw:text-transparent">赞助商广告位</h1>
<div class="tw:flex tw:flex-col tw:w-30 tw:h-30 tw:ml-5 tw:mt-2" @click="contant('elfidc')"> <!-- 亿讯云 -->
<img class="tw:w-24 tw:h-24" src="../assets/elfidc.svg"></img>
<h1 class="tw:text-sm tw:text-center tw:text-yellow-400">亿讯云金牌赞助</h1>
</div>
</div>
</div>
</template>

View File

@@ -0,0 +1,93 @@
<script lang="ts" setup>
import { ref } from 'vue';
import { InboxOutlined } from '@ant-design/icons-vue';
import { message, StepsProps } from 'ant-design-vue';
import type { UploadFile, UploadChangeParam } from 'ant-design-vue';
/* 进度显示区 */
const disp_steps = ref(true);
const setyps_current = ref(0);
const setps_items: StepsProps['items'] = [{
title: '解压整合包',
description: '解压内容 下载文件'
}, {
title: '筛选模组',
description: 'DeEarthX的心脏'
}, {
title: '下载服务端',
description: '安装模组加载器服务端'
}, {
title: '完成',
description: '一切就绪!'
}]
/* 进度显示区 */
/* 获取文件区 */
const FileList = ref<UploadFile[]>([]);
const isDisabled = ref(false);
const BtnisDisabled = ref(false);
function beforeUpload() {
return false;
}
function handleChange(info: UploadChangeParam) {
if (!info.file.name?.endsWith('.zip') && !info.file.name?.endsWith('.mrpack')) {
message.error('只能上传.zip和.mrpack文件');
return;
}
isDisabled.value = true; //禁用
}
function handleDrop(e: DragEvent) {
console.log(e);
}
function handleUpload() {
if (FileList.value.length === 0) {
message.warning('请先拖拽或选择文件')
return
}
let data: ArrayBuffer[] = [];
FileList.value[0].originFileObj?.arrayBuffer().then(buffer => {data=[buffer];console.log(data);}) //获取文件内容
console.log(data);
BtnisDisabled.value = true; //禁用按钮
disp_steps.value = true; //开始显示进度条
}
function runDeEarthX() {
reactFL()
}
function reactFL() {
FileList.value = [];
isDisabled.value = false;
}
runDeEarthX();
/* 获取文件区 */
</script>
<template>
<div class="tw:h-full tw:w-full">
<div class="tw:h-full tw:w-full tw:flex tw:flex-col tw:justify-center tw:items-center">
<div>
<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>
</div>
<a-upload-dragger :disabled="isDisabled" class="tw:w-128 tw:h-48" name="file" action="/" :multiple="false"
:before-upload="beforeUpload" @change="handleChange" @drop="handleDrop" v-model:fileList="FileList"
accept=".zip,.mrpack">
<p class="ant-upload-drag-icon">
<inbox-outlined></inbox-outlined>
</p>
<p class="ant-upload-text">拖拽或点击以上传文件</p>
<p class="ant-upload-hint">
请使用.zipCurseForgeMCBBS.mrpckModrinth文件
</p>
</a-upload-dragger>
<a-button :disabled="BtnisDisabled" type="primary" @click="handleUpload" style="margin-top: 32px">
开始
</a-button>
</div>
<div v-if="disp_steps"
class="tw:fixed tw:bottom-2 tw:ml-4 tw:w-272 tw:h-16 tw:flex tw:justify-center tw:items-center tw:text-sm">
<a-steps :current="setyps_current" :items="setps_items" />
</div>
</div>
</template>

View File

@@ -0,0 +1,45 @@
<script lang="ts" setup>
import { ref } from 'vue';
import * as fs from "@tauri-apps/plugin-store"
const config = ref({})
const checked = ref(false);
</script>
<template>
<div class="tw:h-full tw:w-full">
<h1 class="tw:text-3xl tw:font-black tw:tracking-tight tw:text-center">
<span class="tw:bg-gradient-to-r tw:from-emerald-500 tw:to-cyan-500 tw:bg-clip-text tw:text-transparent">
DeEarth X
</span>
<span>设置</span>
</h1>
<div class="tw:border-t-2 tw:border-gray-400 tw:mt-6 tw:mb-2"></div>
<!-- DeEarth设置 -->
<h1 class="tw:text-xl tw:font-black tw:tracking-tight tw:text-center">模组筛选设置</h1>
<div class="tw:flex">
<div class="tw:flex tw:ml-5 tw:mt-2">
<p class="tw:text-gray-600">哈希过滤</p>
<a-switch class="tw:left-2" v-model:checked="checked" />
</div>
<div class="tw:flex tw:ml-5 tw:mt-2">
<p class="tw:text-gray-600">DeP过滤</p>
<a-switch class="tw:left-2" v-model:checked="checked" />
</div>
<div class="tw:flex tw:ml-5 tw:mt-2">
<p class="tw:text-gray-600">Mixin过滤</p>
<a-switch class="tw:left-2" v-model:checked="checked" />
</div>
</div>
<!-- DeEarth设置 -->
<div class="tw:border-t-2 tw:border-gray-400 tw:mt-6 tw:mb-2"></div>
<!-- 下载源设置 -->
<h1 class="tw:text-xl tw:font-black tw:tracking-tight tw:text-center">下载源设置</h1>
<div class="tw:flex">
<div class="tw:flex tw:ml-5 tw:mt-2">
<p class="tw:text-gray-600">MCIM镜像源</p>
<a-switch class="tw:left-2" v-model:checked="checked" />
</div>
</div>
</div>
</template>

View File

@@ -1,4 +1,14 @@
import { createApp } from "vue";
import App from "./App.vue";
import "./tailwind.css"
import Antd from 'ant-design-vue';
import 'ant-design-vue/dist/reset.css';
import router from "./router";
createApp(App).mount("#app");
const app = createApp(App);
app.use(router)
app.use(Antd)
app.mount("#app");

24
front/src/router/index.ts Normal file
View File

@@ -0,0 +1,24 @@
import { createRouter, createWebHistory } from "vue-router";
import Main from "../component/Main.vue";
import Setting from "../component/Setting.vue";
import About from "../component/About.vue";
const router = createRouter({
history: createWebHistory(),
routes: [
{
path: "/",
component: Main,
},
{
path: "/setting",
component: Setting
},{
path: "/about",
component: About
}
]
})
export default router

1
front/src/tailwind.css Normal file
View File

@@ -0,0 +1 @@
@import "tailwindcss" prefix(tw);

View File

@@ -1,12 +1,15 @@
import { defineConfig } from "vite";
import vue from "@vitejs/plugin-vue";
import tailwindcss from "@tailwindcss/vite";
// @ts-expect-error process is a nodejs global
const host = process.env.TAURI_DEV_HOST;
// https://vite.dev/config/
export default defineConfig(async () => ({
plugins: [vue()],
plugins: [vue(),
tailwindcss()
],
// Vite options tailored for Tauri development and only applied in `tauri dev` or `tauri build`
//

19
package.json Normal file
View File

@@ -0,0 +1,19 @@
{
"name": "deearthx-v3",
"version": "1.0.0",
"description": "main",
"repository": {
"type": "git",
"url": "https://git.tianpao.top/Tianpao/DeEarthX-V3.git"
},
"license": "ISC",
"author": "Tianpao",
"type": "module",
"main": "./.build/build.js",
"scripts": {
"backend":"cd ./backend && npm run build",
"upx":".\\.build\\upx.exe .\\backend\\dist\\Dex-v3-core.exe",
"tauri":"cd ./front && npm run tauri build",
"build":"npm run tauri && npm run backend && npm run upx"
}
}