Files
abot/admin/dashboard/templates/file_browser.html
2025-06-05 16:33:30 +08:00

156 lines
6.0 KiB
HTML

{% extends "base.html" %}
{% block title %}文件浏览 - 机器人管理后台{% endblock %}
{% block content %}
<div class="container-fluid">
<div class="row">
<div class="col-12">
<el-card class="box-card">
<div slot="header" class="clearfix">
<span>文件浏览</span>
<div style="float: right;">
<el-input
v-model="currentPath"
placeholder="当前路径"
style="width: 300px; margin-right: 10px;"
readonly>
</el-input>
<el-button type="primary" size="small" @click="navigateUp">
<i class="el-icon-arrow-up"></i> 上级目录
</el-button>
</div>
</div>
<el-table
:data="fileList"
style="width: 100%"
v-loading="loading">
<el-table-column
prop="name"
label="名称"
min-width="200">
<template slot-scope="scope">
<el-link
:type="scope.row.is_dir ? 'primary' : 'info'"
@click="scope.row.is_dir ? navigateTo(scope.row.name) : null">
<i :class="scope.row.is_dir ? 'el-icon-folder' : 'el-icon-document'"></i>
[[ scope.row.name ]]
</el-link>
</template>
</el-table-column>
<el-table-column
prop="type"
label="类型"
width="100">
<template slot-scope="scope">
[[ scope.row.is_dir ? '目录' : '文件' ]]
</template>
</el-table-column>
<el-table-column
prop="size"
label="大小"
width="120">
<template slot-scope="scope">
[[ scope.row.is_dir ? '-' : formatFileSize(scope.row.size) ]]
</template>
</el-table-column>
<el-table-column
prop="modified"
label="修改时间"
width="180">
<template slot-scope="scope">
[[ formatDate(scope.row.modified) ]]
</template>
</el-table-column>
<el-table-column
label="操作"
width="120">
<template slot-scope="scope">
<el-button
v-if="!scope.row.is_dir"
type="primary"
size="mini"
@click="downloadFile(scope.row.name)">
下载
</el-button>
</template>
</el-table-column>
</el-table>
</el-card>
</div>
</div>
</div>
{% endblock %}
{% block scripts %}
<script>
new Vue({
el: '#app',
mixins: [baseApp],
delimiters: ['[[', ']]'],
data() {
return {
currentPath: '',
fileList: [],
loading: false
}
},
created() {
this.currentView = '15';
this.loadFiles('');
},
methods: {
formatFileSize(bytes) {
if (bytes === 0) return '0 B';
const k = 1024;
const sizes = ['B', 'KB', 'MB', 'GB', 'TB'];
const i = Math.floor(Math.log(bytes) / Math.log(k));
return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i];
},
formatDate(timestamp) {
return new Date(timestamp * 1000).toLocaleString();
},
loadFiles(path) {
this.loading = true;
this.currentPath = path || '/';
axios.get('/api/list_files', {
params: { path: path }
})
.then(response => {
if (response.data.success) {
this.fileList = response.data.data.items;
} else {
this.$message.error('加载文件列表失败:' + response.data.message);
}
})
.catch(error => {
this.$message.error('加载文件列表失败');
console.error('Error:', error);
})
.finally(() => {
this.loading = false;
});
},
navigateTo(dirName) {
const newPath = this.currentPath === '/' ? dirName : this.currentPath + '/' + dirName;
this.loadFiles(newPath);
},
navigateUp() {
if (!this.currentPath) return;
const lastSlashIndex = this.currentPath.lastIndexOf('/');
if (lastSlashIndex === -1) {
this.loadFiles('');
} else {
this.loadFiles(this.currentPath.substring(0, lastSlashIndex));
}
},
downloadFile(fileName) {
const filePath = this.currentPath === '/' ? fileName : this.currentPath + '/' + fileName;
window.location.href = '/api/download_file?path=' + encodeURIComponent(filePath);
}
}
});
</script>
{% endblock %}