站点拖动排序

This commit is contained in:
jxxghp
2024-05-23 19:39:33 +08:00
parent 11b649dc8c
commit 52cf517a91
17 changed files with 218 additions and 239 deletions
+15 -17
View File
@@ -167,6 +167,12 @@ watch(resourceDialog, value => {
if (!value) getSiteStats() if (!value) getSiteStats()
}) })
// 保存站点
function saveSite() {
siteEditDialog.value = false
emit('update')
}
// 装载时查询站点图标 // 装载时查询站点图标
onMounted(() => { onMounted(() => {
getSiteIcon() getSiteIcon()
@@ -175,6 +181,7 @@ onMounted(() => {
</script> </script>
<template> <template>
<div>
<VCard <VCard
:height="cardProps.height" :height="cardProps.height"
:width="cardProps.width" :width="cardProps.width"
@@ -187,7 +194,6 @@ onMounted(() => {
<VImg :src="siteIcon" /> <VImg :src="siteIcon" />
</VAvatar> </VAvatar>
</template> </template>
<VCardItem> <VCardItem>
<VCardTitle class="font-bold"> <VCardTitle class="font-bold">
<span @click.stop="openSitePage">{{ cardProps.site?.name }}</span> <span @click.stop="openSitePage">{{ cardProps.site?.name }}</span>
@@ -196,37 +202,29 @@ onMounted(() => {
<span @click.stop="openSitePage">{{ cardProps.site?.url }}</span> <span @click.stop="openSitePage">{{ cardProps.site?.url }}</span>
</VCardSubtitle> </VCardSubtitle>
</VCardItem> </VCardItem>
<StatIcon v-if="cardProps.site?.is_active" :color="statColor" />
<VCardText class="py-2"> <VCardText class="py-2">
<VTooltip v-if="cardProps.site?.render === 1" text="浏览器仿真"> <VTooltip v-if="cardProps.site?.render === 1" text="浏览器仿真">
<template #activator="{ props }"> <template #activator="{ props }">
<VIcon color="primary" class="me-2" v-bind="props" icon="mdi-apple-safari" /> <VIcon color="primary" class="me-2" v-bind="props" icon="mdi-apple-safari" />
</template> </template>
</VTooltip> </VTooltip>
<VTooltip v-if="cardProps.site?.proxy === 1" text="代理"> <VTooltip v-if="cardProps.site?.proxy === 1" text="代理">
<template #activator="{ props }"> <template #activator="{ props }">
<VIcon color="primary" class="me-2" v-bind="props" icon="mdi-network-outline" /> <VIcon color="primary" class="me-2" v-bind="props" icon="mdi-network-outline" />
</template> </template>
</VTooltip> </VTooltip>
<VTooltip v-if="cardProps.site?.limit_interval" text="流控"> <VTooltip v-if="cardProps.site?.limit_interval" text="流控">
<template #activator="{ props }"> <template #activator="{ props }">
<VIcon color="primary" class="me-2" v-bind="props" icon="mdi-speedometer" /> <VIcon color="primary" class="me-2" v-bind="props" icon="mdi-speedometer" />
</template> </template>
</VTooltip> </VTooltip>
<VTooltip v-if="cardProps.site?.filter" text="过滤"> <VTooltip v-if="cardProps.site?.filter" text="过滤">
<template #activator="{ props }"> <template #activator="{ props }">
<VIcon color="primary" class="me-2" v-bind="props" icon="mdi-filter-cog-outline" /> <VIcon color="primary" class="me-2" v-bind="props" icon="mdi-filter-cog-outline" />
</template> </template>
</VTooltip> </VTooltip>
</VCardText> </VCardText>
<VDivider /> <VDivider />
<VCardActions> <VCardActions>
<VBtn v-if="!cardProps.site?.public" :disabled="updateButtonDisable" @click.stop="handleSiteUpdate"> <VBtn v-if="!cardProps.site?.public" :disabled="updateButtonDisable" @click.stop="handleSiteUpdate">
<template #prepend> <template #prepend>
@@ -247,6 +245,10 @@ onMounted(() => {
浏览 浏览
</VBtn> </VBtn>
</VCardActions> </VCardActions>
<StatIcon v-if="cardProps.site?.is_active" :color="statColor" />
<span class="absolute top-1 right-8">
<VIcon class="cursor-move">mdi-drag</VIcon>
</span>
</VCard> </VCard>
<!-- 更新站点Cookie & UA弹窗 --> <!-- 更新站点Cookie & UA弹窗 -->
<VDialog v-model="siteCookieDialog" max-width="50rem"> <VDialog v-model="siteCookieDialog" max-width="50rem">
@@ -283,16 +285,12 @@ onMounted(() => {
</VCardActions> </VCardActions>
</VCard> </VCard>
</VDialog> </VDialog>
<!-- 站点编辑弹窗 -->
<SiteAddEditDialog <SiteAddEditDialog
v-if="siteEditDialog" v-if="siteEditDialog"
v-model="siteEditDialog" v-model="siteEditDialog"
:siteid="cardProps.site?.id" :siteid="cardProps.site?.id"
@save=" @save="saveSite"
() => {
siteEditDialog = false
emit('update')
}
"
@remove="emit('remove')" @remove="emit('remove')"
@close="siteEditDialog = false" @close="siteEditDialog = false"
/> />
@@ -305,7 +303,6 @@ onMounted(() => {
z-index="1010" z-index="1010"
:fullscreen="!display.mdAndUp.value" :fullscreen="!display.mdAndUp.value"
> >
<!-- Dialog Content -->
<VCard :title="`浏览站点 - ${cardProps.site?.name}`"> <VCard :title="`浏览站点 - ${cardProps.site?.name}`">
<DialogCloseBtn @click="resourceDialog = false" /> <DialogCloseBtn @click="resourceDialog = false" />
<VDivider /> <VDivider />
@@ -316,9 +313,10 @@ onMounted(() => {
</VDialog> </VDialog>
<!-- 进度框 --> <!-- 进度框 -->
<ProgressDialog v-if="progressDialog" v-model="progressDialog" :text="progressText" /> <ProgressDialog v-if="progressDialog" v-model="progressDialog" :text="progressText" />
</div>
</template> </template>
<style lang="scss"> <style lang="scss" scoped>
.v-table th { .v-table th {
white-space: nowrap; white-space: nowrap;
} }
+1 -1
View File
@@ -48,7 +48,7 @@ const statusItems = [
// 生成1到50的优先级下拉框选项 // 生成1到50的优先级下拉框选项
const priorityItems = ref( const priorityItems = ref(
Array.from({ length: 50 }, (_, i) => i + 1).map(item => ({ Array.from({ length: 100 }, (_, i) => i + 1).map(item => ({
title: item, title: item,
value: item, value: item,
})), })),
+49
View File
@@ -139,3 +139,52 @@
.apexcharts-title-text { .apexcharts-title-text {
color: rgba(var(--v-theme-on-surface), var(--v-high-emphasis-opacity)) !important; color: rgba(var(--v-theme-on-surface), var(--v-high-emphasis-opacity)) !important;
} }
.grid-site-card {
grid-template-columns: repeat(auto-fill, minmax(20rem, 1fr));
padding-block-end: 1rem;
}
.grid-media-card {
grid-template-columns: repeat(auto-fill, minmax(9.375rem, 1fr));
}
.grid-backdrop-card {
grid-template-columns: repeat(auto-fill, minmax(15rem, 1fr));
padding-block-end: 1rem;
}
.grid-torrent-card {
grid-template-columns: repeat(auto-fill, minmax(18rem, 1fr));
padding-block-end: 1rem;
}
.grid-plugin-card {
grid-template-columns: repeat(auto-fill, minmax(15rem, 1fr));
padding-block-end: 1rem;
}
.grid-downloading-card {
grid-template-columns: repeat(auto-fill, minmax(20rem, 1fr));
padding-block-end: 1rem;
}
.grid-directory-card {
grid-template-columns: repeat(auto-fill, minmax(20rem, 1fr));
padding-block-end: 1rem;
}
.grid-filterrule-card {
grid-template-columns: repeat(auto-fill, minmax(20rem, 1fr));
padding-block-end: 1rem;
}
.grid-subscribe-card {
grid-template-columns: repeat(auto-fill, minmax(18rem, 1fr));
padding-block-end: 1rem;
}
.v-tabs:not(.v-tabs-pill).v-tabs--horizontal {
border-block-end: 1px solid rgba(var(--v-border-color), var(--v-border-opacity));
}
@@ -38,9 +38,3 @@ onMounted(() => {
</template> </template>
</VHover> </VHover>
</template> </template>
<style lang="scss">
.grid-media-card {
grid-template-columns: repeat(auto-fill, minmax(9.375rem, 1fr));
}
</style>
@@ -38,10 +38,3 @@ onMounted(() => {
</template> </template>
</VHover> </VHover>
</template> </template>
<style lang="scss">
.grid-backdrop-card {
grid-template-columns: repeat(auto-fill, minmax(15rem, 1fr));
padding-block-end: 1rem;
}
</style>
@@ -38,10 +38,3 @@ onMounted(() => {
</template> </template>
</VHover> </VHover>
</template> </template>
<style lang="scss">
.grid-backdrop-card {
grid-template-columns: repeat(auto-fill, minmax(15rem, 1fr));
padding-block-end: 1rem;
}
</style>
+1 -3
View File
@@ -125,7 +125,5 @@ async function fetchData({ done }: { done: any }) {
</template> </template>
<style lang="scss"> <style lang="scss">
.grid-media-card {
grid-template-columns: repeat(auto-fill, minmax(9.375rem, 1fr));
}
</style> </style>
@@ -124,9 +124,3 @@ async function fetchData({ done }: { done: any }) {
/> />
</VInfiniteScroll> </VInfiniteScroll>
</template> </template>
<style lang="scss">
.grid-media-card {
grid-template-columns: repeat(auto-fill, minmax(9.375rem, 1fr));
}
</style>
+1 -4
View File
@@ -233,8 +233,5 @@ watchEffect(() => {
</template> </template>
<style lang="scss"> <style lang="scss">
.grid-torrent-card {
grid-template-columns: repeat(auto-fill, minmax(18rem, 1fr));
padding-block-end: 1rem;
}
</style> </style>
-11
View File
@@ -516,14 +516,3 @@ onBeforeMount(async () => {
</VCard> </VCard>
</VDialog> </VDialog>
</template> </template>
<style lang="scss">
.grid-plugin-card {
grid-template-columns: repeat(auto-fill, minmax(15rem, 1fr));
padding-block-end: 1rem;
}
.v-tabs:not(.v-tabs-pill).v-tabs--horizontal {
border-block-end: 1px solid rgba(var(--v-border-color), var(--v-border-opacity));
}
</style>
@@ -93,10 +93,3 @@ onUnmounted(() => {
/> />
</PullRefresh> </PullRefresh>
</template> </template>
<style lang="scss">
.grid-downloading-card {
grid-template-columns: repeat(auto-fill, minmax(20rem, 1fr));
padding-block-end: 1rem;
}
</style>
@@ -310,9 +310,3 @@ onMounted(() => {
</VCol> </VCol>
</VRow> </VRow>
</template> </template>
<style lang="scss">
.grid-directory-card {
grid-template-columns: repeat(auto-fill, minmax(20rem, 1fr));
padding-block-end: 1rem;
}
</style>
@@ -440,10 +440,3 @@ onMounted(() => {
<ImportCodeDialog v-model="importCodeString" title="导入优先级规则" @close="importCodeDialog = false" /> <ImportCodeDialog v-model="importCodeString" title="导入优先级规则" @close="importCodeDialog = false" />
</VDialog> </VDialog>
</template> </template>
<style lang="scss">
.grid-filterrule-card {
grid-template-columns: repeat(auto-fill, minmax(20rem, 1fr));
padding-block-end: 1rem;
}
</style>
@@ -550,10 +550,3 @@ onMounted(() => {
<ImportCodeDialog v-model="importCodeString" title="导入优先级规则" @close="importCodeDialog = false" /> <ImportCodeDialog v-model="importCodeString" title="导入优先级规则" @close="importCodeDialog = false" />
</VDialog> </VDialog>
</template> </template>
<style lang="scss">
.grid-filterrule-card {
grid-template-columns: repeat(auto-fill, minmax(20rem, 1fr));
padding-block-end: 1rem;
}
</style>
+29 -11
View File
@@ -1,4 +1,5 @@
<script lang="ts" setup> <script lang="ts" setup>
import draggable from 'vuedraggable'
import api from '@/api' import api from '@/api'
import type { Site } from '@/api/types' import type { Site } from '@/api/types'
import SiteCard from '@/components/cards/SiteCard.vue' import SiteCard from '@/components/cards/SiteCard.vue'
@@ -24,16 +25,40 @@ async function fetchData() {
} }
} }
// 保存站点排序
async function savaSitesPriority() {
// 重新排序
const priorities = dataList.value.map((site, index) => ({ id: site.id, pri: index + 1 }))
try {
const result: { [key: string]: any } = await api.post('site/priorities', priorities)
if (result.success) {
fetchData()
}
} catch (error) {
console.error(error)
}
}
// 加载时获取数据 // 加载时获取数据
onBeforeMount(fetchData) onBeforeMount(fetchData)
</script> </script>
<template> <template>
<LoadingBanner v-if="!isRefreshed" class="mt-12" /> <LoadingBanner v-if="!isRefreshed" class="mt-12" />
<div v-if="dataList.length > 0" class="grid gap-3 grid-site-card"> <div>
<div v-for="(data, index) in dataList" :key="index"> <draggable
<SiteCard :key="data.id" :site="data" @remove="fetchData" @update="fetchData" /> v-if="dataList.length > 0"
</div> v-model="dataList"
@end="savaSitesPriority"
handle=".cursor-move"
item-key="id"
tag="div"
:component-data="{ 'class': 'grid gap-3 grid-site-card' }"
>
<template #item="{ element }">
<SiteCard :site="element" @remove="fetchData" @update="fetchData" />
</template>
</draggable>
</div> </div>
<NoDataFound <NoDataFound
v-if="dataList.length === 0 && isRefreshed" v-if="dataList.length === 0 && isRefreshed"
@@ -57,10 +82,3 @@ onBeforeMount(fetchData)
@close="siteAddDialog = false" @close="siteAddDialog = false"
/> />
</template> </template>
<style lang="scss">
.grid-site-card {
grid-template-columns: repeat(auto-fill, minmax(20rem, 1fr));
padding-block-end: 1rem;
}
</style>
@@ -123,10 +123,3 @@ const filteredDataList = computed(() => {
" "
/> />
</template> </template>
<style lang="scss">
.grid-subscribe-card {
grid-template-columns: repeat(auto-fill, minmax(18rem, 1fr));
padding-block-end: 1rem;
}
</style>
@@ -129,13 +129,3 @@ async function fetchData({ done }: { done: any }) {
/> />
</VInfiniteScroll> </VInfiniteScroll>
</template> </template>
<style lang="scss">
.grid-media-card {
grid-template-columns: repeat(auto-fill, minmax(9.375rem, 1fr));
}
.v-tabs:not(.v-tabs-pill).v-tabs--horizontal {
border-block-end: 1px solid rgba(var(--v-border-color), var(--v-border-opacity));
}
</style>