refactor(submitter): 重构分类处理逻辑,完善提交校验与安装包流程

1.  重构提交器的分类处理,移除硬编码的分类映射,改用后端返回的type字段
2.  添加categoryId同步逻辑,完善表单校验和提交数据
3.  优化图标处理逻辑,支持base64格式图标
4.  完善deb包元数据处理,自动生成规范的文件名
5.  新增更全面的提交字段校验和API业务错误处理
6.  补充安装脚本的目录复制规则
This commit is contained in:
2026-07-16 13:57:39 +08:00
parent 387be920b1
commit 68195a94f6
3 changed files with 141 additions and 76 deletions
+29 -31
View File
@@ -559,7 +559,7 @@
</template>
<script setup lang="ts">
import { ref, reactive, computed } from "vue";
import { ref, reactive, computed, watch } from "vue";
interface HistoryArchInfo {
id: number;
@@ -595,9 +595,19 @@ const formData = reactive({
description: "",
tags: "",
category: "",
categoryId: 0,
remark: "",
});
// 当 category 变化时,从 categoriesList 中同步 categoryId
watch(
() => formData.category,
(val) => {
const found = categoriesList.value.find((c) => c.value === val);
formData.categoryId = found?.id ?? 0;
},
);
const isSubmitting = ref(false);
const submitSuccess = ref(false);
const submitError = ref("");
@@ -634,23 +644,6 @@ interface Category {
value: string;
}
// 服务器分类 id → 英文标识符映射(与后端 submitter.ts 的 categoryNameToIdMap 反向)
// 历史记录中 category 字段存储的就是这些英文标识符
const categoryIdToValueMap: Record<number, string> = {
1: "games",
2: "music",
3: "network",
4: "office",
5: "others",
6: "image_graphics",
7: "development",
8: "reading",
9: "chat",
10: "themes",
11: "tools",
12: "video",
};
interface Tag {
name: string;
value: string;
@@ -667,7 +660,8 @@ const isFormValid = computed(() => {
formData.pkgname.trim() &&
formData.version.trim() &&
formData.category.trim() &&
formData.debFilePath
formData.debFilePath &&
formData.remark.trim()
);
});
@@ -711,12 +705,10 @@ const loadCategoriesList = async (): Promise<void> => {
data.data.length > 0
) {
categoriesList.value = data.data.map(
(item: { id: number; name: string }, index: number) => ({
(item: { id: number; name: string; type?: string }, index: number) => ({
id: typeof item.id === "number" ? item.id : index + 1,
// API 只返回中文 namevalue 通过 id 反向映射为英文标识符
// 英文标识符与历史记录中的 category 字段一致,用于匹配
name: item.name || "",
value: categoryIdToValueMap[item.id] || item.name || "",
value: item.type || String(item.id),
}),
);
categoriesLoadError.value = "";
@@ -726,10 +718,10 @@ const loadCategoriesList = async (): Promise<void> => {
);
} else if (data.code === 0 && Array.isArray(data)) {
categoriesList.value = data.map(
(item: { id: number; name: string }, index: number) => ({
(item: { id: number; name: string; type?: string }, index: number) => ({
id: typeof item.id === "number" ? item.id : index + 1,
name: item.name || "",
value: categoryIdToValueMap[item.id] || item.name || "",
value: item.type || String(item.id),
}),
);
categoriesLoadError.value = "";
@@ -1198,12 +1190,13 @@ const selectIconFile = () => {
const handleIconFileSelect = (event: Event) => {
const target = event.target as HTMLInputElement;
const file = target.files?.[0] as File & { path?: string };
const file = target.files?.[0];
if (file) {
formData.iconPath = file.path || file.name;
const reader = new FileReader();
reader.onload = (e) => {
iconPreview.value = e.target?.result as string;
const dataUrl = e.target?.result as string;
formData.iconPath = dataUrl;
iconPreview.value = dataUrl;
};
reader.readAsDataURL(file);
}
@@ -1211,17 +1204,18 @@ const handleIconFileSelect = (event: Event) => {
const handleIconDrop = (event: DragEvent) => {
event.preventDefault();
const file = event.dataTransfer?.files?.[0] as File & { path?: string };
const file = event.dataTransfer?.files?.[0];
if (
file &&
(file.name.endsWith(".png") ||
file.name.endsWith(".jpg") ||
file.name.endsWith(".jpeg"))
) {
formData.iconPath = file.path || file.name;
const reader = new FileReader();
reader.onload = (e) => {
iconPreview.value = e.target?.result as string;
const dataUrl = e.target?.result as string;
formData.iconPath = dataUrl;
iconPreview.value = dataUrl;
};
reader.readAsDataURL(file);
}
@@ -1273,6 +1267,7 @@ const resetForm = () => {
formData.description = "";
formData.tags = "";
formData.category = "";
formData.categoryId = 0;
formData.remark = "";
submitSuccess.value = false;
submitError.value = "";
@@ -1304,7 +1299,9 @@ const submitForm = async () => {
description: formData.description,
tags: formData.tags,
category: formData.category,
categoryId: formData.categoryId,
remark: formData.remark,
arch: currentDebArch.value,
};
console.log("[Submitter] ============== SUBMIT FORM ==============");
@@ -1361,6 +1358,7 @@ const packageApp = async (storeArch: string) => {
description: formData.description,
tags: formData.tags,
category: formData.category,
categoryId: formData.categoryId,
remark: formData.remark,
storeArch,
};