first commit
This commit is contained in:
138
frontend/src/components/TransferPanel.vue
Normal file
138
frontend/src/components/TransferPanel.vue
Normal file
@@ -0,0 +1,138 @@
|
||||
<script setup>
|
||||
import { nextTick, ref, watch } from 'vue'
|
||||
import LocalIcon from './LocalIcon.vue'
|
||||
import TransferQueueItem from './TransferQueueItem.vue'
|
||||
|
||||
const props = defineProps({
|
||||
peerName: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
connectionType: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
items: {
|
||||
type: Array,
|
||||
required: true,
|
||||
},
|
||||
hasPendingItems: {
|
||||
type: Boolean,
|
||||
required: true,
|
||||
},
|
||||
})
|
||||
|
||||
const emit = defineEmits([
|
||||
'close',
|
||||
'send-text',
|
||||
'files-selected',
|
||||
'send-all-pending',
|
||||
'remove-item',
|
||||
'start-upload',
|
||||
'copy-item',
|
||||
])
|
||||
|
||||
const textValue = ref('')
|
||||
const isDragOver = ref(false)
|
||||
const batchContainer = ref(null)
|
||||
const fileInput = ref(null)
|
||||
|
||||
watch(
|
||||
() => props.items.length,
|
||||
async () => {
|
||||
await nextTick()
|
||||
|
||||
if (batchContainer.value) {
|
||||
batchContainer.value.scrollTop = batchContainer.value.scrollHeight
|
||||
}
|
||||
},
|
||||
)
|
||||
|
||||
function triggerFileInput() {
|
||||
fileInput.value?.click()
|
||||
}
|
||||
|
||||
function handleTextSend() {
|
||||
emit('send-text', textValue.value)
|
||||
textValue.value = ''
|
||||
}
|
||||
|
||||
function handleFileChange(event) {
|
||||
const files = Array.from(event.target.files || [])
|
||||
|
||||
if (files.length) {
|
||||
emit('files-selected', files)
|
||||
}
|
||||
|
||||
event.target.value = ''
|
||||
}
|
||||
|
||||
function handleDrop(event) {
|
||||
isDragOver.value = false
|
||||
const files = Array.from(event.dataTransfer?.files || [])
|
||||
|
||||
if (files.length) {
|
||||
emit('files-selected', files)
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="transfer-panel active">
|
||||
<div class="card">
|
||||
<div class="transfer-head">
|
||||
<div class="connected-to">
|
||||
<h2>{{ peerName }}</h2>
|
||||
<p>{{ connectionType }}</p>
|
||||
</div>
|
||||
<button class="close-btn" type="button" @click="$emit('close')">
|
||||
<LocalIcon name="close" size="20" />
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div
|
||||
class="drop-zone"
|
||||
:class="{ 'drop-zone-active': isDragOver }"
|
||||
@click="triggerFileInput"
|
||||
@dragenter.prevent="isDragOver = true"
|
||||
@dragover.prevent="isDragOver = true"
|
||||
@dragleave.prevent="isDragOver = false"
|
||||
@drop.prevent="handleDrop"
|
||||
>
|
||||
<LocalIcon class="drop-zone-icon" name="cloud_upload" size="42" />
|
||||
<p class="drop-zone-text">点击或拖拽多个文件到这里</p>
|
||||
<input ref="fileInput" class="hidden" multiple type="file" @change="handleFileChange" />
|
||||
</div>
|
||||
|
||||
<div class="text-input-group">
|
||||
<input
|
||||
v-model="textValue"
|
||||
placeholder="输入要发送的文本或链接..."
|
||||
type="text"
|
||||
@keyup.enter="handleTextSend"
|
||||
/>
|
||||
<button title="发送文本" type="button" @click="handleTextSend">
|
||||
<LocalIcon name="arrow_upward" size="20" />
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div class="batch-actions" :class="{ active: hasPendingItems }">
|
||||
<button class="btn-small-primary" type="button" @click="$emit('send-all-pending')">
|
||||
<LocalIcon name="send_and_archive" size="16" />
|
||||
一键发送全部
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div v-if="items.length" ref="batchContainer" class="batch-progress-container">
|
||||
<TransferQueueItem
|
||||
v-for="item in items"
|
||||
:key="item.id"
|
||||
:item="item"
|
||||
@copy="$emit('copy-item', $event)"
|
||||
@remove="$emit('remove-item', $event)"
|
||||
@start-upload="$emit('start-upload', $event)"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
Reference in New Issue
Block a user