144 lines
3.5 KiB
Vue
144 lines
3.5 KiB
Vue
<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,
|
|
},
|
|
networkHint: {
|
|
type: String,
|
|
default: '',
|
|
},
|
|
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>
|
|
<small v-if="networkHint" class="connection-hint">{{ networkHint }}</small>
|
|
</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>
|