feat 站点资源

This commit is contained in:
jxxghp
2023-08-06 08:57:35 +08:00
parent 74cb7d017e
commit 1d15c7f916
2 changed files with 245 additions and 87 deletions

View File

@@ -1,9 +1,10 @@
<script lang="ts" setup>
import type { PropType } from 'vue'
import { useToast } from 'vue-toast-notification'
import { formatFileSize } from '@core/utils/formatters'
import { numberValidator, requiredValidator } from '@/@validators'
import api from '@/api'
import type { Site } from '@/api/types'
import type { Site, TorrentInfo } from '@/api/types'
import ExistIcon from '@core/components/ExistIcon.vue'
// 输入参数
@@ -40,85 +41,48 @@ const siteCookieDialog = ref(false)
// 站点编辑弹窗
const siteInfoDialog = ref(false)
// 资源浏览弹窗
const resourceDialog = ref(false)
// 资源浏览表头
const resourceHeaders = [
{ title: '标题', key: 'title', sortable: false },
{ title: '时间', key: 'pubdate', sortable: false },
{ title: '大小', key: 'size', sortable: false },
{ title: '做种', key: 'seeders', sortable: false },
{ title: '下载', key: 'peers', sortable: false },
{ title: '', key: 'actions', sortable: false },
]
// 数据列表
const resourceDataList = ref<TorrentInfo[]>([])
// 搜索
const resourceSearch = ref('')
// 加载状态
const resourceLoading = ref(false)
// 总条数
const resourceTotalItems = ref(1000)
// 每页条数
const resourceItemsPerPage = ref(100)
// 当前页码
const resourceCurrentPage = ref(1)
// 用户名密码表单
const userPwForm = ref({
username: '',
password: '',
})
// 查询站点图标
async function getSiteIcon() {
try {
siteIcon.value = (await api.get(`site/icon/${cardProps.site?.id}`)).data.icon
}
catch (error) {
console.error(error)
}
}
// 测试站点连通性
async function testSite() {
try {
testButtonText.value = '测试中 ...'
testButtonDisable.value = true
const result: { [key: string]: any } = await api.get(`site/test/${cardProps.site?.id}`)
if (result.success)
$toast.success(`${cardProps.site?.name} 连通性测试成功,可正常使用!`)
else
$toast.error(`${cardProps.site?.name} 连通性测试失败:${result.message}`)
testButtonText.value = '测试'
testButtonDisable.value = false
}
catch (error) {
console.error(error)
}
}
// 打开更新站点Cookie UA弹窗
async function handleSiteUpdate() {
siteCookieDialog.value = true
}
// 打开站点编辑弹窗
async function handleSiteInfo() {
siteInfoDialog.value = true
}
// 调用API更新站点Cookie UA
async function updateSiteCookie() {
try {
if (!userPwForm.value.username || !userPwForm.value.password)
return
// 更新按钮状态
siteCookieDialog.value = false
updateButtonText.value = '更新中 ...'
updateButtonDisable.value = true
const result: { [key: string]: any } = await api.get(
`site/cookie/${cardProps.site?.id}`,
{
params: {
username: userPwForm.value.username,
password: userPwForm.value.password,
},
},
)
if (result.success)
$toast.success(`${cardProps.site?.name} 更新Cookie & UA 成功!`)
else
$toast.error(`${cardProps.site?.name} 更新失败:${result.message}`)
updateButtonText.value = '更新'
updateButtonDisable.value = false
}
catch (error) {
console.error(error)
}
}
// 状态下拉项
const statusItems = [
{ title: '启用', value: true },
{ title: '停用', value: false },
]
// 站点编辑表单数据
const siteForm = reactive({
@@ -174,6 +138,96 @@ const siteForm = reactive({
is_active: cardProps.site?.is_active,
})
// 打开种子详情页面
function openTorrentDetail(page_url: string) {
window.open(page_url, '_blank')
}
// 下载种子文件
async function downloadTorrentFile(enclosure: string) {
window.open(enclosure, '_blank')
}
// 查询站点图标
async function getSiteIcon() {
try {
siteIcon.value = (await api.get(`site/icon/${cardProps.site?.id}`)).data.icon
}
catch (error) {
console.error(error)
}
}
// 测试站点连通性
async function testSite() {
try {
testButtonText.value = '测试中 ...'
testButtonDisable.value = true
const result: { [key: string]: any } = await api.get(`site/test/${cardProps.site?.id}`)
if (result.success)
$toast.success(`${cardProps.site?.name} 连通性测试成功,可正常使用!`)
else
$toast.error(`${cardProps.site?.name} 连通性测试失败:${result.message}`)
testButtonText.value = '测试'
testButtonDisable.value = false
}
catch (error) {
console.error(error)
}
}
// 打开更新站点Cookie UA弹窗
async function handleSiteUpdate() {
siteCookieDialog.value = true
}
// 打开站点编辑弹窗
async function handleSiteInfo() {
siteInfoDialog.value = true
}
// 打开资源浏览弹窗
async function handleResourceBrowse() {
resourceDialog.value = true
getResourceList()
}
// 调用API更新站点Cookie UA
async function updateSiteCookie() {
try {
if (!userPwForm.value.username || !userPwForm.value.password)
return
// 更新按钮状态
siteCookieDialog.value = false
updateButtonText.value = '更新中 ...'
updateButtonDisable.value = true
const result: { [key: string]: any } = await api.get(
`site/cookie/${cardProps.site?.id}`,
{
params: {
username: userPwForm.value.username,
password: userPwForm.value.password,
},
},
)
if (result.success)
$toast.success(`${cardProps.site?.name} 更新Cookie & UA 成功!`)
else
$toast.error(`${cardProps.site?.name} 更新失败:${result.message}`)
updateButtonText.value = '更新'
updateButtonDisable.value = false
}
catch (error) {
console.error(error)
}
}
// 调用API更新站点信息
async function updateSiteInfo() {
try {
@@ -192,11 +246,23 @@ async function updateSiteInfo() {
}
}
// 状态下拉项
const statusItems = [
{ title: '启用', value: true },
{ title: '停用', value: false },
]
// 调用API查询站点资源
async function getResourceList() {
resourceLoading.value = true
try {
resourceDataList.value = await api.get('search/title', {
params: {
keyword: resourceSearch.value,
page: resourceCurrentPage.value,
site: cardProps.site?.id,
},
})
resourceLoading.value = false
}
catch (error) {
console.error(error)
}
}
// 装载时查询站点图标
onMounted(() => {
@@ -210,7 +276,7 @@ onMounted(() => {
:width="cardProps.width"
:flat="!siteForm.is_active"
class="overflow-hidden"
@click="siteInfoDialog = true"
@click="handleSiteInfo"
>
<template #image>
<VAvatar
@@ -299,12 +365,6 @@ onMounted(() => {
</template>
{{ updateButtonText }}
</VBtn>
<VBtn @click.stop="handleSiteInfo">
<template #prepend>
<VIcon icon="mdi-square-edit-outline" />
</template>
编辑
</VBtn>
<VBtn
:disabled="testButtonDisable"
@click.stop="testSite"
@@ -314,6 +374,12 @@ onMounted(() => {
</template>
{{ testButtonText }}
</VBtn>
<VBtn @click.stop="handleResourceBrowse">
<template #prepend>
<VIcon icon="mdi-web" />
</template>
浏览
</VBtn>
</VCardActions>
</VCard>
<!-- 更新站点Cookie & UA弹窗 -->
@@ -488,4 +554,96 @@ onMounted(() => {
</VCardActions>
</VCard>
</VDialog>
<!-- 站点资源弹窗 -->
<VDialog
v-model="resourceDialog"
max-width="1600"
scrollable
>
<!-- Dialog Content -->
<VCard :title="`浏览站点 - ${cardProps.site?.name}`">
<DialogCloseBtn @click="resourceDialog = false" />
<VCardText class="pt-2">
<VDataTable
v-model:items-per-page="resourceItemsPerPage"
:headers="resourceHeaders"
:items="resourceDataList"
:items-length="resourceTotalItems"
:search="resourceSearch"
:loading="resourceLoading"
density="compact"
item-value="id"
return-object
fixed-header
items-per-page-text="每页条数"
page-text="{0}-{1} {2} "
>
<template #item.title="{ item }">
<div>{{ item.raw.title }}</div>
<small>{{ item.raw.description }}</small>
<VChip
v-for="(label, index) in item.raw?.labels"
:key="index"
variant="elevated"
size="small"
color="primary"
class="me-1 mb-1"
>
{{ label }}
</VChip>
</template>
<template #item.pubdate="{ item }">
<div>{{ item.raw.date_elapsed }}</div>
<small>{{ item.raw.pubdate }}</small>
</template>
<template #item.size="{ item }">
<div>{{ formatFileSize(item.raw.size) }}</div>
</template>
<template #item.seeders="{ item }">
<div>{{ item.raw.seeders }}</div>
</template>
<template #item.peers="{ item }">
<div>{{ item.raw.peers }}</div>
</template>
<template #item.actions="{ item }">
<div class="me-n3">
<IconBtn>
<VIcon
icon="mdi-dots-vertical"
/>
<VMenu
activator="parent"
close-on-content-click
>
<VList>
<VListItem
variant="plain"
@click="openTorrentDetail(item.raw.page_url)"
>
<template #prepend>
<VIcon icon="mdi-information" />
</template>
<VListItemTitle>查看详情</VListItemTitle>
</VListItem>
<VListItem
variant="plain"
@click="downloadTorrentFile(item.raw.enclosure)"
>
<template #prepend>
<VIcon icon="mdi-download" />
</template>
<VListItemTitle>下载种子</VListItemTitle>
</VListItem>
</VList>
</VMenu>
</IconBtn>
</div>
</template>
<template #no-data>
没有数据
</template>
</VDataTable>
</VCardText>
</VCard>
</VDialog>
</template>