feat:星系广场的彻底实现

This commit is contained in:
Tianpao
2026-02-02 23:05:20 +08:00
parent b8b09fdb99
commit 45b28b3b34
9 changed files with 422 additions and 17 deletions

View File

@@ -11,9 +11,225 @@
</h1>
<p class="tw:text-gray-500 tw:mt-2">让所有的模组都在这里发光</p>
</div>
<!-- 模组提交 -->
<div class="tw:bg-white tw:rounded-lg tw:shadow-sm tw:p-6 tw:mb-6">
<h2 class="tw:text-lg tw:font-semibold tw:text-gray-800 tw:mb-4 tw:flex tw:items-center tw:gap-2">
<span class="tw:w-2 tw:h-2 tw:bg-purple-500 tw:rounded-full"></span>
模组提交
</h2>
<div class="tw:flex tw:flex-col tw:gap-4">
<div>
<label class="tw:block tw:text-sm tw:font-medium tw:text-gray-700 tw:mb-2">
模组类型
</label>
<a-radio-group v-model:value="modType" size="default" button-style="solid">
<a-radio-button value="client">客户端模组</a-radio-button>
<a-radio-button value="server">服务端模组</a-radio-button>
</a-radio-group>
</div>
<div>
<label class="tw:block tw:text-sm tw:font-medium tw:text-gray-700 tw:mb-2">
Modid
</label>
<a-input
v-model:value="modidInput"
placeholder="请输入 Modid多个用逗号分隔或上传文件自动获取"
size="large"
allow-clear
/>
<p class="tw:text-xs tw:text-gray-400 tw:mt-1">
当前已添加 {{ modidList.length }} Modid
</p>
</div>
<div>
<label class="tw:block tw:text-sm tw:font-medium tw:text-gray-700 tw:mb-2">
上传文件
</label>
<a-upload-dragger
:fileList="fileList"
:before-upload="beforeUpload"
@remove="handleRemove"
accept=".jar"
multiple
>
<p class="tw-ant-upload-drag-icon">
<InboxOutlined />
</p>
<p class="tw-ant-upload-text">点击或拖拽文件到此区域上传</p>
<p class="tw-ant-upload-hint">
支持 .jar 格式文件可多选
</p>
</a-upload-dragger>
<div v-if="fileList.length > 0" class="tw:mt-4">
<p class="tw:text-sm tw:font-medium tw:text-gray-700 tw:mb-2">
已选择 {{ fileList.length }} 个文件
</p>
<a-button
type="primary"
size="large"
:loading="uploading"
block
@click="handleUpload"
>
<template #icon>
<UploadOutlined />
</template>
{{ uploading ? '上传中...' : '开始上传' }}
</a-button>
</div>
</div>
<div v-if="modidList.length > 0" class="tw:mt-2">
<a-button
type="primary"
size="large"
:loading="submitting"
block
@click="handleSubmit"
>
<template #icon>
<SendOutlined />
</template>
{{ submitting ? '提交中...' : `提交${modType === 'client' ? '客户端' : '服务端'}模组` }}
</a-button>
</div>
</div>
</div>
</div>
</div>
</template>
<script lang="ts" setup>
</script>
import { ref, computed } from 'vue';
import { UploadOutlined, InboxOutlined, SendOutlined } from '@ant-design/icons-vue';
import { message, Modal } from 'ant-design-vue';
import type { UploadFile, UploadProps } from 'ant-design-vue';
const modType = ref<'client' | 'server'>('client');
const modidList = ref<string[]>([]);
const uploading = ref(false);
const submitting = ref(false);
const fileList = ref<UploadFile[]>([]);
const modidInput = computed({
get: () => modidList.value.join(','),
set: (value: string) => {
modidList.value = value
.split(',')
.map(id => id.trim())
.filter(id => id.length > 0);
}
});
const beforeUpload: UploadProps['beforeUpload'] = (file) => {
console.log(file.name);
const uploadFile: UploadFile = {
uid: `${Date.now()}-${Math.random()}`,
name: file.name,
status: 'done',
url: '',
originFileObj: file,
};
fileList.value = [...fileList.value, uploadFile];
return false;
};
const handleRemove: UploadProps['onRemove'] = (file) => {
const index = fileList.value.indexOf(file);
const newFileList = fileList.value.slice();
newFileList.splice(index, 1);
fileList.value = newFileList;
};
const handleUpload = async () => {
if (fileList.value.length === 0) {
message.warning('请先选择文件');
return;
}
uploading.value = true;
const formData = new FormData();
fileList.value.forEach((file) => {
if (file.originFileObj) {
const blob = file.originFileObj;
const encodedFileName = encodeURIComponent(file.name);
const fileWithCorrectName = new File([blob], encodedFileName, { type: blob.type });
formData.append('files', fileWithCorrectName);
}
});
try {
const response = await fetch('http://localhost:37019/galaxy/upload', {
method: 'POST',
body: formData,
});
if (response.ok) {
const data = await response.json();
console.log(data);
if (data.modids && Array.isArray(data.modids)) {
let addedCount = 0;
data.modids.forEach((modid: string) => {
if (modid && !modidList.value.includes(modid)) {
modidList.value.push(modid);
addedCount++;
}
});
message.success(`成功上传 ${addedCount} 个文件`);
} else {
message.error('返回数据格式错误');
}
} else {
message.error('上传失败');
}
} catch (error) {
message.error('上传出错,请重试');
} finally {
uploading.value = false;
fileList.value = [];
}
};
const handleSubmit = () => {
Modal.confirm({
title: '确认提交',
content: `确定要提交 ${modidList.value.length}${modType.value === 'client' ? '客户端' : '服务端'}模组吗?`,
okText: '确定',
cancelText: '取消',
onOk: async () => {
submitting.value = true;
try {
const apiUrl = modType.value === 'client'
? 'http://localhost:37019/galaxy/submit/client'
: 'http://localhost:37019/galaxy/submit/server';
const response = await fetch(apiUrl, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
modids: modidList.value,
}),
});
if (response.ok) {
message.success(`${modType.value === 'client' ? '客户端' : '服务端'}模组提交成功`);
modidList.value = [];
} else {
message.error('提交失败');
}
} catch (error) {
message.error('提交出错,请重试');
} finally {
submitting.value = false;
}
},
});
};
</script>

View File

@@ -60,8 +60,8 @@ const settings: SettingCategory[] = [
},
{
key: 'dexpub',
name: 'DePIS过滤',
description: '过滤 DeEarth Public Info Services 平台中记录的客户端文件',
name: 'Galaxy Square 过滤',
description: '过滤 Galaxy Square 平台中记录的客户端文件',
path: 'filter.dexpub',
defaultValue: false
},