项目文件夹

文件
wehub-resource-sync 719032b19f
Update Schema / Update configuration json schema (push) Has been cancelled
Memory Benchmark / Memory Test (Full Analysis) (push) Has been cancelled
CI Quality / Lint GitHub Actions (actionlint) (push) Has been cancelled
CI Quality / Lint GitHub Actions (zizmor) (push) Has been cancelled
CI Quality / Check typos (push) Has been cancelled
CI / Test coverage (push) Has been cancelled
CI / Test (22.x, windows-latest) (push) Has been cancelled
CI / Test (24.x, macos-latest) (push) Has been cancelled
CI / Test (24.x, ubuntu-latest) (push) Has been cancelled
CI / Test (24.x, windows-latest) (push) Has been cancelled
CI / Test (26.x, macos-latest) (push) Has been cancelled
CI / Test (26.x, ubuntu-latest) (push) Has been cancelled
CI / Test (26.x, windows-latest) (push) Has been cancelled
CI / Test with Bun (latest, macos-latest) (push) Has been cancelled
CI / Test with Bun (latest, ubuntu-latest) (push) Has been cancelled
CI / Test with Bun (latest, windows-latest) (push) Has been cancelled
CI / Build and run (22.x, macos-latest) (push) Has been cancelled
CI / Build and run (22.x, ubuntu-latest) (push) Has been cancelled
CI / Build and run (22.x, windows-latest) (push) Has been cancelled
autofix.ci / autofix (push) Has been cancelled
CI Browser Extension / Lint Browser Extension (push) Has been cancelled
CI Browser Extension / Test Browser Extension (push) Has been cancelled
Memory Benchmark / Memory Test (push) Has been cancelled
CI Website / Lint Website Client (push) Has been cancelled
CI Website / Lint Website Server (push) Has been cancelled
CI Website / Test Website Server (push) Has been cancelled
CI Website / Bundle Website Server (push) Has been cancelled
CI / Lint Biome (push) Has been cancelled
CI / Lint oxlint (push) Has been cancelled
CI / Lint TypeScript (push) Has been cancelled
CI / Lint Secretlint (push) Has been cancelled
CI / Test (22.x, macos-latest) (push) Has been cancelled
CI / Test (22.x, ubuntu-latest) (push) Has been cancelled
CI / Build and run (24.x, macos-latest) (push) Has been cancelled
CI / Build and run (24.x, ubuntu-latest) (push) Has been cancelled
CI / Build and run (24.x, windows-latest) (push) Has been cancelled
CI / Build and run (26.x, macos-latest) (push) Has been cancelled
CI / Build and run (26.x, ubuntu-latest) (push) Has been cancelled
CI / Build and run (26.x, windows-latest) (push) Has been cancelled
CI / Build and run with Bun (latest, macos-latest) (push) Has been cancelled
CI / Build and run with Bun (latest, ubuntu-latest) (push) Has been cancelled
CI / Build and run with Bun (latest, windows-latest) (push) Has been cancelled
CodeQL / Analyze (javascript-typescript) (push) Has been cancelled
Docker / build (linux/amd64, ubuntu-latest) (push) Has been cancelled
Docker / build (linux/arm/v7, ubuntu-24.04-arm) (push) Has been cancelled
Docker / build (linux/arm64, ubuntu-24.04-arm) (push) Has been cancelled
Docker / merge (push) Has been cancelled
Pack repository with Repomix / pack-repo (push) Has been cancelled
Performance Benchmark History / Benchmark (macos-latest) (push) Has been cancelled
Performance Benchmark History / Benchmark (ubuntu-latest) (push) Has been cancelled
Performance Benchmark History / Benchmark (windows-latest) (push) Has been cancelled
Performance Benchmark History / Store Results (push) Has been cancelled
Test Repomix Action / Test Node.js 22 (push) Has been cancelled
Test Repomix Action / Test Node.js 24 (push) Has been cancelled
Test Repomix Action / Test Node.js 26 (push) Has been cancelled
chore: import upstream snapshot with attribution
2026-07-13 12:39:37 +08:00

236 行
4.8 KiB
Vue

此文件含有模棱两可的 Unicode 字符
此文件含有可能会与其他字符混淆的 Unicode 字符。 如果您是想特意这样的,可以安全地忽略该警告。 使用 Escape 按钮显示他们。
<script setup lang="ts">
import { AlertTriangle, FolderArchive } from 'lucide-vue-next';
import { useFileUpload } from '../../composables/useFileUpload';
import { useZipProcessor } from '../../composables/useZipProcessor';
import PackButton from './PackButton.vue';
const props = defineProps<{
loading: boolean;
showButton?: boolean;
}>();
const emit = defineEmits<{
upload: [file: File];
cancel: [];
}>();
const { validateZipFile } = useZipProcessor();
const {
fileInput,
dragActive,
selectedItem: selectedFile,
errorMessage,
hasError,
isValid,
inputAttributes,
handleFileSelect,
handleDragOver,
handleDragLeave,
handleDrop,
triggerFileInput,
clearSelection,
} = useFileUpload({
mode: 'file',
placeholder: 'Drop your ZIP file here or click to browse (max 10MB)',
icon: 'file',
options: {
maxFileSize: 10 * 1024 * 1024, // 10MB
acceptedTypes: ['.zip'],
accept: '.zip',
validateFile: validateZipFile,
},
});
async function onFileSelect(files: FileList | null) {
const result = await handleFileSelect(files);
if (result.success && result.result) {
emit('upload', result.result);
}
}
async function onDrop(event: DragEvent) {
const result = await handleDrop(event);
if (result.success && result.result) {
emit('upload', result.result);
}
}
function clearFile() {
clearSelection();
}
</script>
<template>
<div class="upload-wrapper">
<div
class="upload-container"
:class="{ 'drag-active': dragActive, 'has-error': hasError }"
role="button"
tabindex="0"
aria-label="Upload ZIP file"
@dragover.prevent="handleDragOver"
@dragleave="handleDragLeave"
@drop.prevent="onDrop"
@click="triggerFileInput"
@keydown.enter.self.prevent="triggerFileInput"
@keydown.space.self.prevent="triggerFileInput"
>
<input
ref="fileInput"
v-bind="inputAttributes"
class="hidden-input"
@change="(e) => onFileSelect((e.target as HTMLInputElement).files)"
/>
<div class="upload-content">
<div class="upload-icon">
<AlertTriangle v-if="hasError" class="icon-error" size="20" />
<FolderArchive v-else class="icon-folder" size="20" />
</div>
<div class="upload-text">
<p v-if="errorMessage" class="error-message">
{{ errorMessage }}
</p>
<p v-else-if="selectedFile" class="selected-file">
Selected: {{ selectedFile }}
<button
type="button"
class="clear-button"
aria-label="Clear selected file"
@click.stop="clearFile"
>×</button>
</p>
<template v-else>
<p>Drop your ZIP file here or click to browse (max 10MB)</p>
</template>
</div>
</div>
</div>
</div>
<div v-if="showButton" class="pack-button-container">
<PackButton
:loading="loading"
:isValid="isValid"
@cancel="$emit('cancel')"
/>
</div>
</template>
<style scoped>
.upload-wrapper {
width: 100%;
}
.upload-container {
border: 2px dashed var(--vp-c-border);
border-radius: 8px;
padding: 0 16px;
cursor: pointer;
transition: all 0.2s ease;
height: 50px;
display: flex;
align-items: center;
background: var(--vp-c-bg);
user-select: none;
}
.upload-container:hover {
border-color: var(--vp-c-brand-1);
background-color: var(--vp-c-bg-soft);
}
.upload-container:focus-visible {
outline: 2px solid var(--vp-c-brand-1);
outline-offset: 2px;
}
.drag-active {
border-color: var(--vp-c-brand-1);
background-color: var(--vp-c-bg-soft);
}
.has-error {
border-color: var(--vp-c-danger-1);
}
.hidden-input {
display: none;
}
.upload-content {
display: flex;
flex-direction: row;
align-items: center;
gap: 12px;
width: 100%;
pointer-events: none; /* Allow clicks to pass through to container */
}
.upload-icon {
display: flex;
align-items: center;
justify-content: center;
flex-shrink: 0;
}
.icon-folder {
color: var(--vp-c-text-1);
}
.icon-error {
color: var(--vp-c-danger-1);
}
.upload-text {
flex: 1;
font-size: 14px;
}
.upload-text p {
margin: 0;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.error-message {
color: var(--vp-c-danger-1);
}
.selected-file {
display: flex;
align-items: center;
gap: 8px;
width: 100%;
}
.clear-button {
background: none;
border: none;
color: var(--vp-c-text-2);
cursor: pointer;
font-size: 1.2em;
padding: 0 4px;
line-height: 1;
flex-shrink: 0;
pointer-events: auto; /* Re-enable pointer events for button */
}
.clear-button:hover {
color: var(--vp-c-text-1);
}
.pack-button-container {
width: 100%;
display: flex;
justify-content: center;
margin-top: 16px;
}
@media (max-width: 640px) {
.upload-text p {
font-size: 13px;
}
}
</style>