mirror of
https://github.com/jxxghp/MoviePilot-Frontend.git
synced 2026-09-07 00:36:41 +08:00
es lint fix
This commit is contained in:
@@ -1,82 +1,92 @@
|
||||
<script lang="ts" setup>
|
||||
import api from "@/api";
|
||||
import type { DownloadingInfo } from "@/api/types";
|
||||
import NoDataFound from "@/components/NoDataFound.vue";
|
||||
import DownloadingCard from "@/components/cards/DownloadingCard.vue";
|
||||
import PullRefresh from "pull-refresh-vue3";
|
||||
import PullRefresh from 'pull-refresh-vue3'
|
||||
import api from '@/api'
|
||||
import type { DownloadingInfo } from '@/api/types'
|
||||
import NoDataFound from '@/components/NoDataFound.vue'
|
||||
import DownloadingCard from '@/components/cards/DownloadingCard.vue'
|
||||
|
||||
// 定时器
|
||||
let refreshTimer: NodeJS.Timer | null = null;
|
||||
let refreshTimer: NodeJS.Timer | null = null
|
||||
|
||||
// 数据列表
|
||||
const dataList = ref<DownloadingInfo[]>([]);
|
||||
|
||||
// 获取订阅列表数据
|
||||
const fetchData = async () => {
|
||||
try {
|
||||
dataList.value = await api.get("download");
|
||||
isRefreshed.value = true;
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
}
|
||||
};
|
||||
|
||||
// 刷新状态
|
||||
const loading = ref(false);
|
||||
const dataList = ref<DownloadingInfo[]>([])
|
||||
|
||||
// 是否刷新过
|
||||
const isRefreshed = ref(false);
|
||||
const isRefreshed = ref(false)
|
||||
|
||||
// 获取订阅列表数据
|
||||
async function fetchData() {
|
||||
try {
|
||||
dataList.value = await api.get('download')
|
||||
isRefreshed.value = true
|
||||
}
|
||||
catch (error) {
|
||||
console.error(error)
|
||||
}
|
||||
}
|
||||
|
||||
// 刷新状态
|
||||
const loading = ref(false)
|
||||
|
||||
// 下拉刷新
|
||||
const onRefresh = () => {
|
||||
loading.value = true;
|
||||
fetchData();
|
||||
loading.value = false;
|
||||
};
|
||||
function onRefresh() {
|
||||
loading.value = true
|
||||
fetchData()
|
||||
loading.value = false
|
||||
}
|
||||
|
||||
// 加载时获取数据
|
||||
onBeforeMount(() => {
|
||||
fetchData();
|
||||
fetchData()
|
||||
|
||||
// 启动定时器
|
||||
refreshTimer = setInterval(() => {
|
||||
fetchData();
|
||||
}, 3000);
|
||||
});
|
||||
fetchData()
|
||||
}, 3000)
|
||||
})
|
||||
|
||||
// 组件卸载时停止定时器
|
||||
onUnmounted(() => {
|
||||
if (refreshTimer) {
|
||||
clearInterval(refreshTimer);
|
||||
refreshTimer = null;
|
||||
clearInterval(refreshTimer)
|
||||
refreshTimer = null
|
||||
}
|
||||
});
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<VProgressCircular
|
||||
class="centered"
|
||||
v-if="!isRefreshed"
|
||||
class="centered"
|
||||
indeterminate
|
||||
color="primary"
|
||||
></VProgressCircular>
|
||||
<PullRefresh v-model="loading" @refresh="onRefresh">
|
||||
<div class="grid gap-3 grid-downloading-card" v-if="dataList.length > 0">
|
||||
<DownloadingCard v-for="data in dataList" :key="data.hash" :info="data" />
|
||||
/>
|
||||
<PullRefresh
|
||||
v-model="loading"
|
||||
@refresh="onRefresh"
|
||||
>
|
||||
<div
|
||||
v-if="dataList.length > 0"
|
||||
class="grid gap-3 grid-downloading-card"
|
||||
>
|
||||
<DownloadingCard
|
||||
v-for="data in dataList"
|
||||
:key="data.hash"
|
||||
:info="data"
|
||||
/>
|
||||
</div>
|
||||
<NoDataFound
|
||||
v-if="dataList.length === 0 && isRefreshed"
|
||||
error-code="404"
|
||||
error-title="没有任务"
|
||||
error-description="正在下载的任务将会显示在这里。"
|
||||
>
|
||||
</NoDataFound>
|
||||
/>
|
||||
</PullRefresh>
|
||||
</template>
|
||||
|
||||
<style type="scss">
|
||||
<style lang="scss">
|
||||
.grid-downloading-card {
|
||||
grid-template-columns: repeat(auto-fill, minmax(20rem, 1fr));
|
||||
padding-block-end: 1rem;
|
||||
}
|
||||
|
||||
</style>
|
||||
|
||||
@@ -1,198 +1,209 @@
|
||||
<script setup lang="ts">
|
||||
import { numberValidator, requiredValidator } from "@/@validators";
|
||||
import api from "@/api";
|
||||
import type { TransferHistory } from "@/api/types";
|
||||
import { ref } from "vue";
|
||||
import { useToast } from "vue-toast-notification";
|
||||
import { useConfirm } from "vuetify-use-dialog";
|
||||
import { ref } from 'vue'
|
||||
import { useToast } from 'vue-toast-notification'
|
||||
import { useConfirm } from 'vuetify-use-dialog'
|
||||
import { numberValidator, requiredValidator } from '@/@validators'
|
||||
import api from '@/api'
|
||||
import type { TransferHistory } from '@/api/types'
|
||||
|
||||
// 确认框
|
||||
const createConfirm = useConfirm();
|
||||
const createConfirm = useConfirm()
|
||||
|
||||
// 提示框
|
||||
const $toast = useToast();
|
||||
const $toast = useToast()
|
||||
|
||||
// 重新整理对话框
|
||||
const redoDialog = ref(false);
|
||||
const redoDialog = ref(false)
|
||||
|
||||
// TMDB编号
|
||||
const redoTmdbId = ref("");
|
||||
const redoTmdbId = ref('')
|
||||
|
||||
// 当前操作记录
|
||||
const currentHistory = ref<TransferHistory>();
|
||||
const currentHistory = ref<TransferHistory>()
|
||||
|
||||
// 表头
|
||||
const headers = [
|
||||
{ title: "标题", key: "title", sortable: false },
|
||||
{ title: "目录", key: "src", sortable: false },
|
||||
{ title: "转移方式", key: "mode", sortable: false },
|
||||
{ title: "时间", key: "date", sortable: false },
|
||||
{ title: "状态", key: "status", sortable: false },
|
||||
{ title: "失败原因", key: "errmsg", sortable: false },
|
||||
{ title: "", key: "actions", sortable: false },
|
||||
];
|
||||
{ title: '标题', key: 'title', sortable: false },
|
||||
{ title: '目录', key: 'src', sortable: false },
|
||||
{ title: '转移方式', key: 'mode', sortable: false },
|
||||
{ title: '时间', key: 'date', sortable: false },
|
||||
{ title: '状态', key: 'status', sortable: false },
|
||||
{ title: '失败原因', key: 'errmsg', sortable: false },
|
||||
{ title: '', key: 'actions', sortable: false },
|
||||
]
|
||||
|
||||
// 数据列表
|
||||
const dataList = ref<TransferHistory[]>([]);
|
||||
const dataList = ref<TransferHistory[]>([])
|
||||
|
||||
// 搜索
|
||||
const search = ref("");
|
||||
const search = ref('')
|
||||
|
||||
// 加载状态
|
||||
const loading = ref(false);
|
||||
const loading = ref(false)
|
||||
|
||||
// 总条数
|
||||
const totalItems = ref(0);
|
||||
const totalItems = ref(0)
|
||||
|
||||
// 每页条数
|
||||
const itemsPerPage = ref(25);
|
||||
const itemsPerPage = ref(25)
|
||||
|
||||
// 当前页码
|
||||
const currentPage = ref(1);
|
||||
const currentPage = ref(1)
|
||||
|
||||
// 获取订阅列表数据
|
||||
const fetchData = async ({
|
||||
async function fetchData({
|
||||
page,
|
||||
itemsPerPage,
|
||||
}: {
|
||||
page: number;
|
||||
itemsPerPage: number;
|
||||
}) => {
|
||||
loading.value = true;
|
||||
page: number
|
||||
itemsPerPage: number
|
||||
}) {
|
||||
loading.value = true
|
||||
try {
|
||||
currentPage.value = page;
|
||||
const result: { [key: string]: any } = await api.get("history/transfer", {
|
||||
currentPage.value = page
|
||||
|
||||
const result: { [key: string]: any } = await api.get('history/transfer', {
|
||||
params: {
|
||||
page,
|
||||
count: itemsPerPage,
|
||||
title: search.value,
|
||||
},
|
||||
});
|
||||
dataList.value = result.data.list;
|
||||
totalItems.value = result.data.total;
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
})
|
||||
|
||||
dataList.value = result.data.list
|
||||
totalItems.value = result.data.total
|
||||
}
|
||||
loading.value = false;
|
||||
};
|
||||
catch (error) {
|
||||
console.error(error)
|
||||
}
|
||||
loading.value = false
|
||||
}
|
||||
|
||||
// 根据 type 返回不同的图标
|
||||
const getIcon = (type: string) => {
|
||||
if (type === "电影") {
|
||||
return "mdi-movie";
|
||||
} else if (type === "电视剧") {
|
||||
return "mdi-television-classic";
|
||||
} else {
|
||||
return "mdi-help-circle";
|
||||
}
|
||||
};
|
||||
function getIcon(type: string) {
|
||||
if (type === '电影')
|
||||
return 'mdi-movie'
|
||||
else if (type === '电视剧')
|
||||
return 'mdi-television-classic'
|
||||
else
|
||||
return 'mdi-help-circle'
|
||||
}
|
||||
|
||||
// 计算颜色
|
||||
const getStatusColor = (status: boolean) => {
|
||||
return status ? "success" : "error";
|
||||
};
|
||||
function getStatusColor(status: boolean) {
|
||||
return status ? 'success' : 'error'
|
||||
}
|
||||
|
||||
// 转移方式字典
|
||||
const TransferDict: { [key: string]: string } = {
|
||||
copy: "复制",
|
||||
move: "移动",
|
||||
link: "硬链接",
|
||||
softlink: "软链接",
|
||||
};
|
||||
copy: '复制',
|
||||
move: '移动',
|
||||
link: '硬链接',
|
||||
softlink: '软链接',
|
||||
}
|
||||
|
||||
// 删除历史记录
|
||||
const removeHistory = async (item: TransferHistory) => {
|
||||
async function removeHistory(item: TransferHistory) {
|
||||
try {
|
||||
const isConfirmed = await createConfirm({
|
||||
title: "确认",
|
||||
title: '确认',
|
||||
content: `同步删除 ${item.title} 对应的媒体库文件 ?`,
|
||||
confirmationText: "同步删除文件",
|
||||
cancellationText: "仅删除历史记录",
|
||||
confirmationText: '同步删除文件',
|
||||
cancellationText: '仅删除历史记录',
|
||||
dialogProps: {
|
||||
maxWidth: 600,
|
||||
},
|
||||
});
|
||||
let deleteFile = false;
|
||||
if (isConfirmed) {
|
||||
deleteFile = true;
|
||||
}
|
||||
})
|
||||
|
||||
let deleteFile = false
|
||||
if (isConfirmed)
|
||||
deleteFile = true
|
||||
|
||||
// 调用删除API
|
||||
const result: { [key: string]: any } = await api.delete("history/transfer", {
|
||||
const result: { [key: string]: any } = await api.delete('history/transfer', {
|
||||
data: {
|
||||
...item,
|
||||
delete_file: deleteFile,
|
||||
},
|
||||
});
|
||||
})
|
||||
|
||||
if (result.success) {
|
||||
fetchData({
|
||||
page: currentPage.value,
|
||||
itemsPerPage: itemsPerPage.value,
|
||||
});
|
||||
} else {
|
||||
$toast.error(`删除失败: ${result.msg}`);
|
||||
})
|
||||
}
|
||||
else {
|
||||
$toast.error(`删除失败: ${result.msg}`)
|
||||
}
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
}
|
||||
};
|
||||
catch (error) {
|
||||
console.error(error)
|
||||
}
|
||||
}
|
||||
|
||||
// 重新整理
|
||||
const rehandleHistory = async () => {
|
||||
async function rehandleHistory() {
|
||||
try {
|
||||
if (!redoTmdbId.value) {
|
||||
return;
|
||||
}
|
||||
redoDialog.value = false;
|
||||
$toast.info(`正在重新整理 ${currentHistory.value?.title} ...`);
|
||||
if (!redoTmdbId.value)
|
||||
return
|
||||
|
||||
redoDialog.value = false
|
||||
$toast.info(`正在重新整理 ${currentHistory.value?.title} ...`)
|
||||
|
||||
// 调用API接口重新转移
|
||||
const requestData = {
|
||||
...currentHistory.value,
|
||||
};
|
||||
}
|
||||
|
||||
const result: { [key: string]: any } = await api.post(
|
||||
"history/transfer",
|
||||
'history/transfer',
|
||||
requestData,
|
||||
{
|
||||
params: {
|
||||
new_tmdbid: parseInt(redoTmdbId.value),
|
||||
},
|
||||
}
|
||||
);
|
||||
},
|
||||
)
|
||||
|
||||
if (result.success) {
|
||||
fetchData({
|
||||
page: currentPage.value,
|
||||
itemsPerPage: itemsPerPage.value,
|
||||
});
|
||||
} else {
|
||||
$toast.error(`重新整理失败: ${result.message}!`);
|
||||
})
|
||||
}
|
||||
else {
|
||||
$toast.error(`重新整理失败: ${result.message}!`)
|
||||
}
|
||||
} catch (e) {
|
||||
console.log(e);
|
||||
}
|
||||
};
|
||||
catch (e) {
|
||||
console.log(e)
|
||||
}
|
||||
}
|
||||
|
||||
// 弹出菜单
|
||||
const dropdownItems = ref([
|
||||
{
|
||||
title: "重新整理",
|
||||
title: '重新整理',
|
||||
value: 1,
|
||||
props: {
|
||||
prependIcon: "mdi-redo-variant",
|
||||
prependIcon: 'mdi-redo-variant',
|
||||
click: (item: TransferHistory) => {
|
||||
redoDialog.value = true;
|
||||
currentHistory.value = item;
|
||||
redoDialog.value = true
|
||||
currentHistory.value = item
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
title: "删除",
|
||||
title: '删除',
|
||||
value: 2,
|
||||
props: {
|
||||
prependIcon: "mdi-trash-can-outline",
|
||||
color: "error",
|
||||
prependIcon: 'mdi-trash-can-outline',
|
||||
color: 'error',
|
||||
click: removeHistory,
|
||||
},
|
||||
},
|
||||
]);
|
||||
])
|
||||
</script>
|
||||
|
||||
<template>
|
||||
@@ -226,17 +237,17 @@ const dropdownItems = ref([
|
||||
:items-length="totalItems"
|
||||
:search="search"
|
||||
:loading="loading"
|
||||
@update:options="fetchData"
|
||||
density="compact"
|
||||
item-value="id"
|
||||
return-object
|
||||
fixed-header
|
||||
items-per-page-text="每页条数"
|
||||
page-text="{0}-{1} 共 {2} 条"
|
||||
@update:options="fetchData"
|
||||
>
|
||||
<template #item.title="{ item }">
|
||||
<div class="d-flex">
|
||||
<VAvatar><VIcon :icon="getIcon(item.raw.type || '')"></VIcon></VAvatar>
|
||||
<VAvatar><VIcon :icon="getIcon(item.raw.type || '')" /></VAvatar>
|
||||
<div class="d-flex flex-column ms-1">
|
||||
<span class="d-block whitespace-nowrap text-high-emphasis">
|
||||
{{ item.raw.title }} {{ item.raw.seasons }}{{ item.raw.episodes }}
|
||||
@@ -246,15 +257,24 @@ const dropdownItems = ref([
|
||||
</div>
|
||||
</template>
|
||||
<template #item.src="{ item }">
|
||||
<small>{{ item.raw.src }} <br />=> {{ item.raw.dest }}</small>
|
||||
<small>{{ item.raw.src }} <br>=> {{ item.raw.dest }}</small>
|
||||
</template>
|
||||
<template #item.mode="{ item }">
|
||||
<VChip variant="outlined" color="primary" size="small">{{
|
||||
TransferDict[item.raw.mode]
|
||||
}}</VChip>
|
||||
<VChip
|
||||
variant="outlined"
|
||||
color="primary"
|
||||
size="small"
|
||||
>
|
||||
{{
|
||||
TransferDict[item.raw.mode]
|
||||
}}
|
||||
</VChip>
|
||||
</template>
|
||||
<template #item.status="{ item }">
|
||||
<VChip :color="getStatusColor(item.raw.status)" size="small">
|
||||
<VChip
|
||||
:color="getStatusColor(item.raw.status)"
|
||||
size="small"
|
||||
>
|
||||
{{ item.raw.status ? "成功" : "失败" }}
|
||||
</VChip>
|
||||
</template>
|
||||
@@ -267,28 +287,36 @@ const dropdownItems = ref([
|
||||
<template #item.actions="{ item }">
|
||||
<IconBtn>
|
||||
<VIcon icon="mdi-dots-vertical" />
|
||||
<VMenu activator="parent" close-on-content-click>
|
||||
<VMenu
|
||||
activator="parent"
|
||||
close-on-content-click
|
||||
>
|
||||
<VList>
|
||||
<VListItem
|
||||
v-for="(menu, i) in dropdownItems"
|
||||
:key="i"
|
||||
variant="plain"
|
||||
:base-color="menu.props.color"
|
||||
:key="i"
|
||||
@click="menu.props.click(item.raw)"
|
||||
>
|
||||
<template #prepend>
|
||||
<VIcon :icon="menu.props.prependIcon"></VIcon>
|
||||
<VIcon :icon="menu.props.prependIcon" />
|
||||
</template>
|
||||
<VListItemTitle v-text="menu.title"></VListItemTitle>
|
||||
<VListItemTitle v-text="menu.title" />
|
||||
</VListItem>
|
||||
</VList>
|
||||
</VMenu>
|
||||
</IconBtn>
|
||||
</template>
|
||||
<template #no-data> 没有数据 </template>
|
||||
<template #no-data>
|
||||
没有数据
|
||||
</template>
|
||||
</VDataTableServer>
|
||||
</VCard>
|
||||
<VDialog v-model="redoDialog" max-width="600">
|
||||
<VDialog
|
||||
v-model="redoDialog"
|
||||
max-width="600"
|
||||
>
|
||||
<!-- Dialog Content -->
|
||||
<VCard title="重新整理">
|
||||
<VCardText>
|
||||
@@ -305,13 +333,18 @@ const dropdownItems = ref([
|
||||
|
||||
<VCardActions>
|
||||
<VSpacer />
|
||||
<VBtn @click="rehandleHistory" @keydown.enter="rehandleHistory"> 确定 </VBtn>
|
||||
<VBtn
|
||||
@click="rehandleHistory"
|
||||
@keydown.enter="rehandleHistory"
|
||||
>
|
||||
确定
|
||||
</VBtn>
|
||||
</VCardActions>
|
||||
</VCard>
|
||||
</VDialog>
|
||||
</template>
|
||||
|
||||
<style type="scss">
|
||||
<style lang="scss">
|
||||
.v-table th {
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user