git-proxy / src /views /UploadView.vue
github-actions[bot]
Update from GitHub Actions
01ab30b
<script setup lang="ts">
import { ref, watch } from 'vue';
import { useRoute, useRouter } from 'vue-router';
import { MessagePlugin, type UploadFile, type UploadInstanceFunctions, type UploadProps } from 'tdesign-vue-next';
import { UploadIcon } from 'tdesign-icons-vue-next';
import { useAccountStore } from '../stores/accountStorage';
import { repoApi } from '../services/repoApi';
import RepoHeader from '../components/RepoHeader.vue';
const route = useRoute();
const router = useRouter();
const store = useAccountStore();
const selectedAccount = ref<number | ''>('');
const currentPath = ref('');
const loading = ref(false);
const uploadRef = ref<UploadInstanceFunctions>();
const uploadFiles = ref<UploadProps['value']>([]);
const commitMessage = ref('');
const commitDescription = ref('');
const selectedFile = ref<File | null>(null);
// Watch route query params and sync with local state
watch(() => route.query, async (query) => {
if (route.path !== '/upload') return;
const { id, path } = query;
if (id) {
await store.fetchAccounts();
const account = store.accounts.find(acc => acc.id === Number(id));
if (account) {
selectedAccount.value = account.id;
}
currentPath.value = path ? path as string : '';
}
uploadFiles.value = [];
}, { immediate: true });
const handlePathClick = (path: string) => {
router.push({
path: '/repo',
query: {
id: selectedAccount.value,
path
}
});
};
const handleRootClick = () => {
router.push({
path: '/repo',
query: {
id: selectedAccount.value,
}
});
};
const handleAccountChange = (val: number) => {
selectedAccount.value = val;
currentPath.value = '';
router.push({
path: '/repo',
query: {
id: selectedAccount.value,
}
});
};
const handleUpload = async (files: UploadFile[]) => {
if (!selectedAccount.value) {
MessagePlugin.error('请先选择仓库');
return;
}
if (!files || files.length === 0) {
MessagePlugin.error('请选择要上传的文件');
return;
}
selectedFile.value = files[0].raw as File;
};
const handleConfirmUpload = async () => {
if (!selectedFile.value || !selectedAccount.value) return;
const account = store.accounts.find(acc => acc.id === selectedAccount.value);
if (!account) {
MessagePlugin.error('未找到账户信息');
return;
}
loading.value = true;
try {
// Verify that selectedFile.value is actually a File object
if (!(selectedFile.value instanceof File)) {
throw new Error('Invalid file object');
}
const content = await new Promise<Uint8Array>((resolve, reject) => {
const reader = new FileReader();
reader.onload = (e) => {
if (e.target?.result) {
resolve(e.target.result as Uint8Array);
} else {
reject(new Error('Failed to read file content'));
}
};
reader.onerror = () => reject(reader.error);
// 使用 readAsDataURL 来处理所有类型的文件
reader.readAsArrayBuffer(selectedFile.value as File);
});
const filePath = currentPath.value
? `${currentPath.value}/${selectedFile.value.name}`
: selectedFile.value.name;
const finalCommitMessage = commitMessage.value.trim() +
(commitDescription.value ? '\n\n' + commitDescription.value.trim() : '') ||
`上传文件: ${selectedFile.value.name}`;
// GitHub API 要求 base64 编码的内容
const response = await repoApi.createAsset(
account,
filePath,
content,
finalCommitMessage
);
MessagePlugin.success('上传成功');
commitMessage.value = '';
commitDescription.value = '';
selectedFile.value = null;
router.push({
path: '/repo',
query: {
id: selectedAccount.value,
path: currentPath.value
}
});
} catch (error) {
console.error(error);
MessagePlugin.error('上传失败');
} finally {
loading.value = false;
}
};
const handleCancelUpload = () => {
commitMessage.value = '';
commitDescription.value = '';
selectedFile.value = null;
};
</script>
<template>
<div class="upload-container w-full flex flex-col p-3 md:p-5 gap-3 md:gap-5 bg-gray-50">
<RepoHeader :selected-account="selectedAccount" :current-path="currentPath" :accounts="store.accounts"
:is-upload-file="true" @path-click="handlePathClick" @root-click="handleRootClick"
@update:selected-account="handleAccountChange" />
<div class="content-section flex-1 bg-white rounded-lg shadow-sm p-6">
<t-upload ref="uploadRef" v-model="uploadFiles" class="w-full flex items-center justify-center" theme="image" :auto-upload="false"
:multiple="false" :draggable="true" :allow-upload-duplicate-file="true" @change="handleUpload">
</t-upload>
<!-- 提交表单 -->
<div class="mt-6 pt-4">
<div class="flex flex-col gap-4">
<t-input v-model:value="commitMessage" placeholder="请输入提交标题" :autofocus="true" />
<t-textarea v-model:value="commitDescription" placeholder="请输入详细的提交说明(可选)"
class="commit-description-textarea" />
<div class="flex gap-2 justify-end">
<t-button theme="default" @click="handleCancelUpload">
取消
</t-button>
<t-button theme="primary" @click="handleConfirmUpload" :loading="loading">
确认上传
</t-button>
</div>
</div>
</div>
</div>
</div>
</template>
<style scoped>
.upload-container {
min-height: 600px;
}
:deep(.t-upload__dragger){
@apply w-full;
}
</style>