Files
flaskProject/flask-ui/src/views/HomeView.vue
T
YanLongChangAn 9380af19de fix(download): 修复文件下载和错误处理功能
- 添加了对 text/plain 和 application/zip 格式的支持
- 在详情页面增加了 URL 输出调试信息
- 修复了跳转页面时的 URL 和 referer 处理逻辑
- 添加了下载失败时的错误事件推送和提示
- 在前端实现了错误消息的类型区分和显示
- 优化了侧边栏菜单组件的配置参数
2026-05-11 22:31:30 +08:00

158 lines
4.4 KiB
Vue

<script setup lang="ts">
import {ref, onUnmounted} from "vue";
import {
file_rename,
music_rename,
image_hasTorrent,
video_hasTorrent,
video_deduplication,
torrent_deduplication,
video_findDeduplication,
torrent_statistics
} from "@/api"
// 警告项接口
interface messageItem {
id: number
text: string,
type?: "success" | "error" | "warning" | "info" | "default"
}
interface BtnItem {
id: number
title: string
handle?: () => Promise<{ code: number, message: Array<never> }>
}
const loading = ref(false)
let eventSource: EventSource // 保存 EventSource 实例
const status = ref('closed') // 连接状态:closed, connecting, connected
const messages = ref<messageItem[]>([{id: Date.now(), text: '输出结果'}])
const buttons = [
{id: 0, title: "小说下载"},
{id: 1, title: "文件重命名", handle: file_rename},
{id: 2, title: "视频查找重复", handle: video_findDeduplication},
{id: 3, title: "视频去重", handle: video_deduplication},
{id: 4, title: "种子去重", handle: torrent_deduplication},
{id: 5, title: "判断视频是否有torrent", handle: video_hasTorrent},
{id: 6, title: "判断图片是否有torrent", handle: image_hasTorrent},
{id: 7, title: "音乐文件重命名", handle: music_rename},
{id: 8, title: "种子统计", handle: torrent_statistics}
]
function closeAlert(id: number) {
console.log(id)
messages.value = messages.value.filter(item => item.id !== id)
}
const handleClick = async (btnObj: BtnItem) => {
if (btnObj.title === "断开") return
if (btnObj.title === "小说下载") {
connect("http://192.168.1.32:5000/api/book/download")
return
}
loading.value = true
try {
if (btnObj.handle == undefined) return
const res = await btnObj.handle()
const res_msg = Array.isArray(res.message) ? res.message : [res.message]
messages.value = res_msg.map((msg: string, index: number) => ({
id: Date.now() + index, // 简单生成唯一 ID,生产环境建议使用更可靠的 ID 生成器
text: msg
}))
messages.value.push({id: Date.now() + messages.value.length, text: '已完成'})
messages.value.reverse()
} finally {
loading.value = false
}
}
const connect = (url: string) => {
messages.value = []
if (eventSource) {
eventSource.close()
}
eventSource = new EventSource(url)
// 连接成功
eventSource.addEventListener("open", () => {
console.log('SSE 连接已打开')
status.value = 'connected'
})
// 监听普通消息
eventSource.addEventListener('message', (event) => {
messages.value.unshift({id: Date.now() + messages.value.length, text: event.data})
})
// 监听关闭事件
eventSource.addEventListener('close', (event) => {
messages.value.unshift({id: Date.now() + messages.value.length, text: event.data})
closeConnection()
})
// 错误处理
// eventSource.addEventListener('error', () => {
// console.log('连接断开或失败', new Date());
// // 如果这里也频繁触发,确认了是断连重连
// if (eventSource.readyState === EventSource.CLOSED) {
// console.log('状态为 CLOSED');
// }
// })
eventSource.addEventListener('mes_error', (event) => {
messages.value.unshift({
id: Date.now() + messages.value.length,
text: event.data,
type: "error"
})
})
}
const closeConnection = () => {
if (eventSource) {
eventSource.close()
// eventSource = null
status.value = 'closed'
console.log('SSE 连接已关闭')
}
}
onUnmounted(() => {
closeConnection()
})
</script>
<template>
<el-main>
<el-card>
<template #default>
<div v-loading="loading" :style="{height: '100%'}">
<el-alert v-for="item in messages" :key="item.id" :title="item.text"
:type="item.type?item.type:'primary'"
@close="closeAlert(item.id)"/>
</div>
</template>
<template #footer>
<el-button-group>
<el-button type="primary" v-for="btn in buttons" :key="btn.id"
@click="handleClick(btn)">
{{ btn.title }}
</el-button>
</el-button-group>
</template>
</el-card>
</el-main>
</template>
<style scoped lang="scss">
.el-alert + .el-alert {
margin-top: 20px;
}
:deep(.el-card__footer) {
display: flex;
justify-content: center;
}
:deep(.el-card__body) {
//height: calc(100vh - 211px + 60px);
height: calc(100vh - 211px);
}
</style>