mirror of
https://github.com/CzBiX/qb-web.git
synced 2026-04-14 02:10:31 +08:00
Add files panel
This commit is contained in:
10
src/Api.ts
10
src/Api.ts
@@ -159,6 +159,16 @@ class Api {
|
||||
}).then(Api.handleResponse);
|
||||
}
|
||||
|
||||
public getTorrentFiles(hash: string) {
|
||||
const params = {
|
||||
hash,
|
||||
};
|
||||
|
||||
return this.axios.get('/torrents/files', {
|
||||
params,
|
||||
}).then(Api.handleResponse);
|
||||
}
|
||||
|
||||
private actionTorrents(action: string, hashes: string[], extra?: any) {
|
||||
const params: any = {
|
||||
hashes: hashes.join('|'),
|
||||
|
||||
@@ -23,9 +23,9 @@
|
||||
<v-tab href="#peers">
|
||||
Peers
|
||||
</v-tab>
|
||||
<!-- <v-tab>
|
||||
<v-tab href="#content">
|
||||
Content
|
||||
</v-tab> -->
|
||||
</v-tab>
|
||||
</v-tabs>
|
||||
<v-tabs-items :value="mTab" touchless>
|
||||
<v-tab-item value="general">
|
||||
@@ -67,6 +67,19 @@
|
||||
/>
|
||||
</panel>
|
||||
</v-tab-item>
|
||||
<v-tab-item value="content">
|
||||
<panel
|
||||
v-for="torrent in torrents"
|
||||
:key="torrent.hash"
|
||||
:title="torrent.name"
|
||||
:single="torrents.length === 1"
|
||||
>
|
||||
<torrent-content
|
||||
:hash="torrent.hash"
|
||||
:isActive="mTab === 'content'"
|
||||
/>
|
||||
</panel>
|
||||
</v-tab-item>
|
||||
</v-tabs-items>
|
||||
</v-card-text>
|
||||
<v-card-actions>
|
||||
@@ -81,6 +94,7 @@
|
||||
import _ from 'lodash';
|
||||
import Vue from 'vue';
|
||||
import TorrentInfo from './TorrentInfo.vue';
|
||||
import TorrentContent from './TorrentContent.vue';
|
||||
import Trackers from './Trackers.vue';
|
||||
import Peers from './Peers.vue';
|
||||
import Panel from './Panel.vue';
|
||||
@@ -88,6 +102,7 @@ import Panel from './Panel.vue';
|
||||
export default Vue.extend({
|
||||
components: {
|
||||
TorrentInfo,
|
||||
TorrentContent,
|
||||
Trackers,
|
||||
Peers,
|
||||
Panel,
|
||||
|
||||
136
src/components/dialogs/TorrentContent.vue
Normal file
136
src/components/dialogs/TorrentContent.vue
Normal file
@@ -0,0 +1,136 @@
|
||||
<template>
|
||||
<div class="torrent-content">
|
||||
<v-treeview
|
||||
open-on-click
|
||||
:items="fileTree"
|
||||
>
|
||||
<template v-slot:prepend="item">
|
||||
<v-icon v-text="getItemIcon(item)" />
|
||||
</template>
|
||||
</v-treeview>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import _ from 'lodash';
|
||||
import Vue from 'vue';
|
||||
import api from '../../Api';
|
||||
import Taskable from '@/mixins/taskable';
|
||||
|
||||
interface File {
|
||||
name: string;
|
||||
size: number;
|
||||
progress: number;
|
||||
priority: number;
|
||||
is_seed: boolean;
|
||||
piece_range: Array<number>;
|
||||
availability: number;
|
||||
};
|
||||
|
||||
interface TreeItem {
|
||||
name: string;
|
||||
item?: File;
|
||||
children?: Array<TreeItem>;
|
||||
}
|
||||
|
||||
interface Data {
|
||||
files: Array<File>;
|
||||
};
|
||||
|
||||
const FILE_KEY = '/FILE/';
|
||||
|
||||
export default Vue.extend({
|
||||
mixins: [Taskable],
|
||||
|
||||
props: {
|
||||
hash: String,
|
||||
isActive: Boolean,
|
||||
},
|
||||
data(): Data {
|
||||
return {
|
||||
files: [],
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
fileTree() {
|
||||
return this.buildTree(this.files, 0);
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
async getFiles() {
|
||||
this.files = await api.getTorrentFiles(this.hash);
|
||||
if (!this.isActive || this.destroy) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.task = setTimeout(this.getFiles, 5000);
|
||||
},
|
||||
getItemIcon(item: any) {
|
||||
if (item.item.item) {
|
||||
return 'mdi-file';
|
||||
}
|
||||
|
||||
return item.open ? 'mdi-folder-open' : 'mdi-folder';
|
||||
},
|
||||
getFileFolder(item: File, start: number) {
|
||||
const name = item.name;
|
||||
const index = name.indexOf('/', start);
|
||||
if (index === -1) {
|
||||
return FILE_KEY;
|
||||
}
|
||||
|
||||
return name.substring(start, index);
|
||||
},
|
||||
buildTree(files: Array<File>, start: number): Array<TreeItem> {
|
||||
if (!files.length) {
|
||||
return [];
|
||||
}
|
||||
|
||||
const entries = _.groupBy(files, (item) => this.getFileFolder(item, start));
|
||||
|
||||
const result = [];
|
||||
for (const [folder, values] of _.entries(entries)) {
|
||||
if (folder !== FILE_KEY) {
|
||||
const subTree = this.buildTree(values, start + folder.length + 1);
|
||||
result.push({
|
||||
name: folder,
|
||||
children: subTree,
|
||||
})
|
||||
continue;
|
||||
}
|
||||
|
||||
for (const item of values) {
|
||||
result.push({
|
||||
name: item.name.substring(start),
|
||||
item: item,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
},
|
||||
},
|
||||
async created() {
|
||||
if (this.isActive) {
|
||||
await this.getFiles();
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
async isActive(v) {
|
||||
if (v) {
|
||||
await this.getFiles();
|
||||
} else {
|
||||
this.cancelTask();
|
||||
}
|
||||
},
|
||||
},
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.torrent-content {
|
||||
::v-deep .v-treeview-node__root {
|
||||
min-height: 0;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user