feat: 更新上传功能,返回文件ID和公共URL;优化实名认证表单数据处理

This commit is contained in:
2026-01-20 01:31:26 +07:00
parent 4fd3a691ee
commit 9710c80a1b
3 changed files with 23 additions and 31 deletions

View File

@@ -9,21 +9,22 @@ interface UploadOptions {
export type UploadFetchOptions = TreatyBody<typeof client.api.file_storage.upload_url.post>;
export async function uploadToS3(file: File, options: UploadOptions): Promise<string> {
export async function uploadToS3(file: File, options: UploadOptions): Promise<{ fileId: string; publicUrl: string }> {
const { onProgress, signal, fetchOptions } = options;
// 1. 获取预签名 URL
const { data, error } = await safeClient(client.api.file_storage.upload_url.post({
...fetchOptions,
accessControl: "public",
}));
if (error.value || !data.value) {
throw new Error("获取上传 URL 失败");
}
const { fileId, uploadUrl, method, headers } = toRefs(data.value);
const { fileId, uploadUrl, method, headers, publicUrl } = toRefs(data.value);
// 2. 上传文件到 S3
return new Promise((resolve, reject) => {
return new Promise<{ fileId: string; publicUrl: string }>((resolve, reject) => {
const xhr = new XMLHttpRequest();
// 监听上传进度
@@ -37,7 +38,10 @@ export async function uploadToS3(file: File, options: UploadOptions): Promise<st
// 上传成功
xhr.addEventListener("load", () => {
if (xhr.status >= 200 && xhr.status < 300) {
resolve(fileId.value);
resolve({
fileId: fileId.value,
publicUrl: publicUrl!.value!,
});
}
else {
reject(new Error(`上传失败: ${xhr.status} ${xhr.statusText}`));

View File

@@ -8,7 +8,6 @@ import { client, safeClient } from "@/api";
const router = useRouter();
interface RealNameFormData {
kycMethod: "id_card";
documentName: string;
documentNumber: string;
fileId1: string;
@@ -16,14 +15,11 @@ interface RealNameFormData {
}
const formData = ref<RealNameFormData>({
kycMethod: "id_card",
documentName: "",
documentNumber: "",
fileId1: "",
fileId2: "",
});
const image1 = ref<string>("");
const image2 = ref<string>("");
const isSubmitting = ref(false);
const status = ref<"unverified" | "pending" | "approved" | "rejected">("unverified");
@@ -123,7 +119,7 @@ async function selectFromGallery(type: "front" | "back") {
"upload.jpeg",
{ type: "image/jpeg" },
);
const fileId = await uploadToS3(file, {
const { publicUrl } = await uploadToS3(file, {
fetchOptions: {
fileName: `idCard_${Date.now()}.jpeg`,
fileSize: image.dataUrl?.length || 0,
@@ -133,12 +129,10 @@ async function selectFromGallery(type: "front" | "back") {
if (image.dataUrl) {
if (type === "front") {
formData.value.fileId1 = fileId;
image1.value = image.dataUrl;
formData.value.fileId1 = publicUrl;
}
else {
formData.value.fileId2 = fileId;
image2.value = image.dataUrl;
formData.value.fileId2 = publicUrl;
}
}
}
@@ -181,9 +175,16 @@ async function handleSubmit() {
isSubmitting.value = true;
try {
await safeClient(client.api.kyc({ kycMethod: "id_card" }).post({
...formData.value,
}));
if (status.value !== "unverified") {
await safeClient(client.api.kyc({ kycMethod: "id_card" }).put({
...formData.value,
}));
}
else {
await safeClient(client.api.kyc({ kycMethod: "id_card" }).post({
...formData.value,
}));
}
await showToast("实名认证提交成功,等待审核", "success");
router.back();
@@ -205,11 +206,6 @@ onMounted(async () => {
formData.value.fileId2 = data.value.fileId2 || "";
status.value = data.value?.status || "unverified";
}
const { data: urls } = await safeClient(client.api.file_storage.access_urls.post({
fileIds: [formData.value.fileId1, formData.value.fileId2],
}));
image1.value = urls.value?.[0].url || "";
image2.value = urls.value?.[1].url || "";
});
</script>
@@ -313,7 +309,7 @@ onMounted(async () => {
</div>
<img
v-else
:src="image1"
:src="formData.fileId1"
alt="身份证正面"
class="uploaded-image"
>
@@ -342,7 +338,7 @@ onMounted(async () => {
</div>
<img
v-else
:src="image2"
:src="formData.fileId2"
alt="身份证反面"
class="uploaded-image"
>