Files
bt/app/components/FileTable.vue
T

100 lines
3.7 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<script setup lang="ts">
import type { TorrentFileEntry } from '~/types/api'
const props = defineProps<{
files: TorrentFileEntry[] | null
total: number
resolving?: boolean
resolveError?: string | null
}>()
const emit = defineEmits<{ resolve: []; preview: [file: TorrentFileEntry] }>()
const keyword = ref('')
const sort = ref<'size' | 'name'>('size')
/** 图片且体积没超上限,才值得从 swarm 拉下来预览 */
function previewable(file: TorrentFileEntry): boolean {
return file.length > 0 && file.length <= MAX_IMAGE_PREVIEW_BYTES && isImagePath(file.path)
}
const visible = computed(() => {
let list = props.files || []
if (keyword.value) {
const kw = keyword.value.toLowerCase()
list = list.filter((f) => f.path.toLowerCase().includes(kw))
}
const sorted = [...list]
if (sort.value === 'size') sorted.sort((a, b) => b.length - a.length)
else sorted.sort((a, b) => a.path.localeCompare(b.path))
return sorted.slice(0, 500)
})
const truncated = computed(() => (props.files?.length || 0) > 500)
</script>
<template>
<div>
<div v-if="resolving" class="empty">
<span class="spin" /> 正在通过 DHT / tracker 获取种子元数据,通常几秒到几十秒…
</div>
<div v-else-if="!files" class="stack sm" style="padding: 18px">
<div class="note warn">
这个种子只有 infoHash,还没有文件清单。可以点击下面的按钮在线拉取元数据(需要本机能连上 DHT / tracker)。
</div>
<div v-if="resolveError" class="note err">{{ resolveError }}</div>
<div>
<button class="btn btn-primary" @click="emit('resolve')">在线解析文件清单</button>
</div>
</div>
<template v-else>
<div class="panel-hd" style="border-top: none">
<span class="label">FILE LIST</span>
<span class="mono small dim">{{ formatNumber(files.length) }} 个文件 · {{ formatBytes(total) }}</span>
<span class="spacer" />
<input v-model="keyword" class="input" style="width: 200px" placeholder="过滤文件名…" />
<select v-model="sort" class="select" style="width: 120px">
<option value="size">按大小</option>
<option value="name">按名称</option>
</select>
</div>
<div style="max-height: 520px; overflow: auto">
<table class="table">
<thead>
<tr>
<th style="width: 58%">路径</th>
<th class="right" style="width: 14%">大小</th>
<th class="right" style="width: 10%">占比</th>
<th style="width: 76px" />
</tr>
</thead>
<tbody>
<tr v-for="(f, i) in visible" :key="i">
<td class="file-path">
<span class="file-dir">{{ splitPath(f.path).dir }}</span><span class="file-name">{{ splitPath(f.path).name }}</span>
</td>
<td class="num right">{{ formatBytes(f.length) }}</td>
<td class="num right mute">{{ filePercent(f.length, total) }}</td>
<td class="right">
<button
v-if="previewable(f)"
class="btn btn-sm btn-ghost"
:title="`从做种节点拉取这张图片用于预览:${f.path}`"
@click="emit('preview', f)"
>
预览
</button>
<span v-else-if="isImagePath(f.path)" class="dim small" title="图片体积超出在线预览上限">过大</span>
</td>
</tr>
</tbody>
</table>
</div>
<div v-if="truncated" class="empty">结果较多,表格只展示前 500 条,可用过滤框缩小范围</div>
</template>
</div>
</template>