mirror of
https://github.com/jxxghp/MoviePilot-Frontend.git
synced 2026-09-04 23:18:44 +08:00
feat: 更新工作流组件,优化界面布局,添加消息和媒体过滤功能
This commit is contained in:
@@ -178,7 +178,7 @@ onMounted(() => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.dnd-flow aside {
|
.dnd-flow aside {
|
||||||
min-width: 25%;
|
max-width: 25%;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,6 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
|
import api from '@/api'
|
||||||
|
import { Site } from '@/api/types'
|
||||||
import { Handle, Position } from '@vue-flow/core'
|
import { Handle, Position } from '@vue-flow/core'
|
||||||
|
|
||||||
defineProps({
|
defineProps({
|
||||||
@@ -11,6 +13,47 @@ defineProps({
|
|||||||
required: true,
|
required: true,
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
|
// 电影/电视剧下拉框
|
||||||
|
const typeOptions = ref([
|
||||||
|
{
|
||||||
|
title: '电影',
|
||||||
|
value: '电影',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '电视剧',
|
||||||
|
value: '电视剧',
|
||||||
|
},
|
||||||
|
])
|
||||||
|
|
||||||
|
// 站点数据列表
|
||||||
|
const siteList = ref<Site[]>([])
|
||||||
|
|
||||||
|
// 获取站点列表数据
|
||||||
|
async function loadSites() {
|
||||||
|
try {
|
||||||
|
const data: Site[] = await api.get('site/rss')
|
||||||
|
|
||||||
|
// 过滤站点,只有启用的站点才显示
|
||||||
|
siteList.value = data.filter(item => item.is_active)
|
||||||
|
} catch (error) {
|
||||||
|
console.error(error)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 站点选项
|
||||||
|
const siteOptions = computed(() => {
|
||||||
|
return siteList.value.map(item => {
|
||||||
|
return {
|
||||||
|
title: item.name,
|
||||||
|
value: item.id,
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
loadSites()
|
||||||
|
})
|
||||||
</script>
|
</script>
|
||||||
<template>
|
<template>
|
||||||
<VCard max-width="20rem">
|
<VCard max-width="20rem">
|
||||||
@@ -25,7 +68,25 @@ defineProps({
|
|||||||
<VCardSubtitle>根据关键字搜索站点种子资源</VCardSubtitle>
|
<VCardSubtitle>根据关键字搜索站点种子资源</VCardSubtitle>
|
||||||
</VCardItem>
|
</VCardItem>
|
||||||
<VDivider />
|
<VDivider />
|
||||||
<VCardText></VCardText>
|
<VCardText>
|
||||||
|
<VRow>
|
||||||
|
<VCol cols="6">
|
||||||
|
<VTextField v-model="data.name" label="名称" outlined dense />
|
||||||
|
</VCol>
|
||||||
|
<VCol cols="6">
|
||||||
|
<VTextField v-model="data.year" label="年份" outlined dense />
|
||||||
|
</VCol>
|
||||||
|
<VCol cols="6">
|
||||||
|
<VSelect v-model="data.type" label="类型" :items="typeOptions" outlined dense />
|
||||||
|
</VCol>
|
||||||
|
<VCol cols="6">
|
||||||
|
<VTextField v-model="data.season" type="number" label="季" outlined dense />
|
||||||
|
</VCol>
|
||||||
|
<VCol cols="12">
|
||||||
|
<VSelect v-model="data.sites" label="站点" :items="siteOptions" chips multiple outlined dense />
|
||||||
|
</VCol>
|
||||||
|
</VRow>
|
||||||
|
</VCardText>
|
||||||
<Handle id="edge_out" type="source" :position="Position.Right" />
|
<Handle id="edge_out" type="source" :position="Position.Right" />
|
||||||
</VCard>
|
</VCard>
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
@@ -1,7 +1,8 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
|
import api from '@/api'
|
||||||
import { Handle, Position } from '@vue-flow/core'
|
import { Handle, Position } from '@vue-flow/core'
|
||||||
|
|
||||||
defineProps({
|
const props = defineProps({
|
||||||
id: {
|
id: {
|
||||||
type: String,
|
type: String,
|
||||||
required: true,
|
required: true,
|
||||||
@@ -11,6 +12,41 @@ defineProps({
|
|||||||
required: true,
|
required: true,
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
|
// 电影/电视剧下拉框
|
||||||
|
const typeOptions = ref([
|
||||||
|
{
|
||||||
|
title: '电影',
|
||||||
|
value: '电影',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '电视剧',
|
||||||
|
value: '电视剧',
|
||||||
|
},
|
||||||
|
])
|
||||||
|
|
||||||
|
// 二级分类策略
|
||||||
|
const mediaCategories = ref<{ [key: string]: any }>({})
|
||||||
|
|
||||||
|
// 调用API查询自动分类配置
|
||||||
|
async function loadMediaCategories() {
|
||||||
|
try {
|
||||||
|
mediaCategories.value = await api.get('media/category')
|
||||||
|
} catch (error) {
|
||||||
|
console.log(error)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 根据选中的媒体类型,获取对应的媒体类别
|
||||||
|
const getCategories = computed(() => {
|
||||||
|
const default_value = [{ title: '全部', value: '' }]
|
||||||
|
if (!mediaCategories.value || !mediaCategories.value[props.data.type ?? '']) return default_value
|
||||||
|
return default_value.concat(mediaCategories.value[props.data.type ?? ''])
|
||||||
|
})
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
loadMediaCategories()
|
||||||
|
})
|
||||||
</script>
|
</script>
|
||||||
<template>
|
<template>
|
||||||
<VCard max-width="20rem">
|
<VCard max-width="20rem">
|
||||||
@@ -25,7 +61,22 @@ defineProps({
|
|||||||
<VCardSubtitle>对媒体数据列表进行过滤</VCardSubtitle>
|
<VCardSubtitle>对媒体数据列表进行过滤</VCardSubtitle>
|
||||||
</VCardItem>
|
</VCardItem>
|
||||||
<VDivider />
|
<VDivider />
|
||||||
<VCardText></VCardText>
|
<VCardText>
|
||||||
|
<VRow>
|
||||||
|
<VCol cols="12">
|
||||||
|
<VSelect v-model="data.type" label="类型" :items="typeOptions" outlined dense />
|
||||||
|
</VCol>
|
||||||
|
<VCol cols="12">
|
||||||
|
<VSelect v-model="data.category" label="类别" :items="getCategories" outlined dense />
|
||||||
|
</VCol>
|
||||||
|
<VCol cols="6">
|
||||||
|
<VTextField v-model="data.year" label="年份" outlined dense />
|
||||||
|
</VCol>
|
||||||
|
<VCol cols="6">
|
||||||
|
<VTextField v-model="data.vote" type="number" label="评分" outlined dense />
|
||||||
|
</VCol>
|
||||||
|
</VRow>
|
||||||
|
</VCardText>
|
||||||
<Handle id="edge_out" type="source" :position="Position.Right" />
|
<Handle id="edge_out" type="source" :position="Position.Right" />
|
||||||
</VCard>
|
</VCard>
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
@@ -1,4 +1,6 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
|
import api from '@/api'
|
||||||
|
import { FilterRuleGroup } from '@/api/types'
|
||||||
import { Handle, Position } from '@vue-flow/core'
|
import { Handle, Position } from '@vue-flow/core'
|
||||||
|
|
||||||
defineProps({
|
defineProps({
|
||||||
@@ -11,6 +13,115 @@ defineProps({
|
|||||||
required: true,
|
required: true,
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
|
// 质量选择框数据
|
||||||
|
const qualityOptions = ref([
|
||||||
|
{
|
||||||
|
title: '全部',
|
||||||
|
value: '',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '蓝光原盘',
|
||||||
|
value: 'Blu-?Ray.+VC-?1|Blu-?Ray.+AVC|UHD.+blu-?ray.+HEVC|MiniBD',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'Remux',
|
||||||
|
value: 'Remux',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'BluRay',
|
||||||
|
value: 'Blu-?Ray',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'UHD',
|
||||||
|
value: 'UHD|UltraHD',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'WEB-DL',
|
||||||
|
value: 'WEB-?DL|WEB-?RIP',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'HDTV',
|
||||||
|
value: 'HDTV',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'H265',
|
||||||
|
value: '[Hx].?265|HEVC',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'H264',
|
||||||
|
value: '[Hx].?264|AVC',
|
||||||
|
},
|
||||||
|
])
|
||||||
|
|
||||||
|
// 分辨率选择框数据
|
||||||
|
const resolutionOptions = ref([
|
||||||
|
{
|
||||||
|
title: '全部',
|
||||||
|
value: '',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '4k',
|
||||||
|
value: '4K|2160p|x2160',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '1080p',
|
||||||
|
value: '1080[pi]|x1080',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '720p',
|
||||||
|
value: '720[pi]|x720',
|
||||||
|
},
|
||||||
|
])
|
||||||
|
|
||||||
|
// 特效选择框数据
|
||||||
|
const effectOptions = ref([
|
||||||
|
{
|
||||||
|
title: '全部',
|
||||||
|
value: '',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '杜比视界',
|
||||||
|
value: 'Dolby[\\s.]+Vision|DOVI|[\\s.]+DV[\\s.]+',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '杜比全景声',
|
||||||
|
value: 'Dolby[\\s.]*\\+?Atmos|Atmos',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'HDR',
|
||||||
|
value: '[\\s.]+HDR[\\s.]+|HDR10|HDR10\\+',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'SDR',
|
||||||
|
value: '[\\s.]+SDR[\\s.]+',
|
||||||
|
},
|
||||||
|
])
|
||||||
|
|
||||||
|
// 所有规则组列表
|
||||||
|
const filterRuleGroups = ref<FilterRuleGroup[]>([])
|
||||||
|
|
||||||
|
// 加载规则组
|
||||||
|
async function queryFilterRuleGroups() {
|
||||||
|
try {
|
||||||
|
const result: { [key: string]: any } = await api.get('system/setting/UserFilterRuleGroups')
|
||||||
|
filterRuleGroups.value = result.data?.value ?? []
|
||||||
|
} catch (error) {
|
||||||
|
console.log(error)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 计算过滤规则组选择框数据
|
||||||
|
const ruleGroupsOptions = computed(() => {
|
||||||
|
return filterRuleGroups.value.map(group => ({
|
||||||
|
title: group.name,
|
||||||
|
value: group.name,
|
||||||
|
}))
|
||||||
|
})
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
queryFilterRuleGroups()
|
||||||
|
})
|
||||||
</script>
|
</script>
|
||||||
<template>
|
<template>
|
||||||
<VCard max-width="20rem">
|
<VCard max-width="20rem">
|
||||||
@@ -25,7 +136,39 @@ defineProps({
|
|||||||
<VCardSubtitle>对资源列表数据进行过滤</VCardSubtitle>
|
<VCardSubtitle>对资源列表数据进行过滤</VCardSubtitle>
|
||||||
</VCardItem>
|
</VCardItem>
|
||||||
<VDivider />
|
<VDivider />
|
||||||
<VCardText></VCardText>
|
<VCardText>
|
||||||
|
<VRow>
|
||||||
|
<VCol cols="6">
|
||||||
|
<VSelect v-model="data.quality" label="质量" :items="qualityOptions" outlined dense />
|
||||||
|
</VCol>
|
||||||
|
<VCol cols="6">
|
||||||
|
<VSelect v-model="data.resolution" label="分辨率" :items="resolutionOptions" outlined dense />
|
||||||
|
</VCol>
|
||||||
|
<VCol cols="6">
|
||||||
|
<VSelect v-model="data.effect" label="特效" :items="effectOptions" outlined dense />
|
||||||
|
</VCol>
|
||||||
|
<VCol cols="6">
|
||||||
|
<VTextField v-model="data.size" label="大小范围" placeholder="MB" outlined dense />
|
||||||
|
</VCol>
|
||||||
|
<VCol cols="12">
|
||||||
|
<VTextField v-model="data.include" label="包含(关键字、正则式)" outlined dense />
|
||||||
|
</VCol>
|
||||||
|
<VCol cols="12">
|
||||||
|
<VTextField v-model="data.exclude" label="排除(关键字、正则式)" outlined dense />
|
||||||
|
</VCol>
|
||||||
|
<VCol cols="12">
|
||||||
|
<VSelect
|
||||||
|
v-model="data.rule_groups"
|
||||||
|
chips
|
||||||
|
multiple
|
||||||
|
label="过滤规则组"
|
||||||
|
:items="ruleGroupsOptions"
|
||||||
|
outlined
|
||||||
|
dense
|
||||||
|
/>
|
||||||
|
</VCol>
|
||||||
|
</VRow>
|
||||||
|
</VCardText>
|
||||||
<Handle id="edge_out" type="source" :position="Position.Right" />
|
<Handle id="edge_out" type="source" :position="Position.Right" />
|
||||||
</VCard>
|
</VCard>
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
@@ -24,8 +24,6 @@ defineProps({
|
|||||||
<VCardTitle>刮削文件</VCardTitle>
|
<VCardTitle>刮削文件</VCardTitle>
|
||||||
<VCardSubtitle>刮削媒体信息和图片</VCardSubtitle>
|
<VCardSubtitle>刮削媒体信息和图片</VCardSubtitle>
|
||||||
</VCardItem>
|
</VCardItem>
|
||||||
<VDivider />
|
|
||||||
<VCardText></VCardText>
|
|
||||||
<Handle id="edge_out" type="source" :position="Position.Right" />
|
<Handle id="edge_out" type="source" :position="Position.Right" />
|
||||||
</VCard>
|
</VCard>
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
@@ -22,10 +22,8 @@ defineProps({
|
|||||||
</VAvatar>
|
</VAvatar>
|
||||||
</template>
|
</template>
|
||||||
<VCardTitle>发送事件</VCardTitle>
|
<VCardTitle>发送事件</VCardTitle>
|
||||||
<VCardSubtitle>发送特定事件</VCardSubtitle>
|
<VCardSubtitle>发送队列中的所有事件</VCardSubtitle>
|
||||||
</VCardItem>
|
</VCardItem>
|
||||||
<VDivider />
|
|
||||||
<VCardText></VCardText>
|
|
||||||
<Handle id="edge_out" type="source" :position="Position.Right" />
|
<Handle id="edge_out" type="source" :position="Position.Right" />
|
||||||
</VCard>
|
</VCard>
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
@@ -1,4 +1,6 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
|
import api from '@/api'
|
||||||
|
import { NotificationConf } from '@/api/types'
|
||||||
import { Handle, Position } from '@vue-flow/core'
|
import { Handle, Position } from '@vue-flow/core'
|
||||||
|
|
||||||
defineProps({
|
defineProps({
|
||||||
@@ -11,6 +13,33 @@ defineProps({
|
|||||||
required: true,
|
required: true,
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
|
// 所有消息渠道
|
||||||
|
const notifications = ref<NotificationConf[]>([])
|
||||||
|
|
||||||
|
// 调用API查询通知渠道设置
|
||||||
|
async function loadNotificationSetting() {
|
||||||
|
try {
|
||||||
|
const result: { [key: string]: any } = await api.get('system/setting/Notifications')
|
||||||
|
notifications.value = result.data?.value ?? []
|
||||||
|
} catch (error) {
|
||||||
|
console.log(error)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 计算消息渠道选项
|
||||||
|
const sourceOptions = computed(() => {
|
||||||
|
return notifications.value.map(item => {
|
||||||
|
return {
|
||||||
|
title: item.name,
|
||||||
|
value: item.name,
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
loadNotificationSetting()
|
||||||
|
})
|
||||||
</script>
|
</script>
|
||||||
<template>
|
<template>
|
||||||
<VCard max-width="20rem">
|
<VCard max-width="20rem">
|
||||||
@@ -22,10 +51,28 @@ defineProps({
|
|||||||
</VAvatar>
|
</VAvatar>
|
||||||
</template>
|
</template>
|
||||||
<VCardTitle>发送消息</VCardTitle>
|
<VCardTitle>发送消息</VCardTitle>
|
||||||
<VCardSubtitle>发送特定消息</VCardSubtitle>
|
<VCardSubtitle>发送队列中的所有消息</VCardSubtitle>
|
||||||
</VCardItem>
|
</VCardItem>
|
||||||
<VDivider />
|
<VDivider />
|
||||||
<VCardText></VCardText>
|
<VCardText>
|
||||||
|
<VRow>
|
||||||
|
<VCol cols="12">
|
||||||
|
<VSelect
|
||||||
|
v-model="data.client"
|
||||||
|
:items="sourceOptions"
|
||||||
|
label="消息渠道"
|
||||||
|
chips
|
||||||
|
multiple
|
||||||
|
outlined
|
||||||
|
dense
|
||||||
|
clearable
|
||||||
|
/>
|
||||||
|
</VCol>
|
||||||
|
<VCol cols="12">
|
||||||
|
<VTextField v-model="data.userid" label="用户ID" chips multiple outlined dense clearable />
|
||||||
|
</VCol>
|
||||||
|
</VRow>
|
||||||
|
</VCardText>
|
||||||
<Handle id="edge_out" type="source" :position="Position.Right" />
|
<Handle id="edge_out" type="source" :position="Position.Right" />
|
||||||
</VCard>
|
</VCard>
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
@@ -22,10 +22,8 @@ defineProps({
|
|||||||
</VAvatar>
|
</VAvatar>
|
||||||
</template>
|
</template>
|
||||||
<VCardTitle>整理文件</VCardTitle>
|
<VCardTitle>整理文件</VCardTitle>
|
||||||
<VCardSubtitle>转移和重命名文件</VCardSubtitle>
|
<VCardSubtitle>整理下载队列中的文件</VCardSubtitle>
|
||||||
</VCardItem>
|
</VCardItem>
|
||||||
<VDivider />
|
|
||||||
<VCardText></VCardText>
|
|
||||||
<Handle id="edge_out" type="source" :position="Position.Right" />
|
<Handle id="edge_out" type="source" :position="Position.Right" />
|
||||||
</VCard>
|
</VCard>
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
@@ -25,9 +25,9 @@ onMounted(() => {
|
|||||||
<aside>
|
<aside>
|
||||||
<div class="mb-3"><VLabel>可选动作组件:</VLabel></div>
|
<div class="mb-3"><VLabel>可选动作组件:</VLabel></div>
|
||||||
|
|
||||||
<div class="nodes">
|
<div class="nodes flex flex-wrap justify-center">
|
||||||
<div
|
<div
|
||||||
class="vue-flow__node-default"
|
class="vue-flow__node-default cursor-grab mx-1"
|
||||||
v-for="action in actions"
|
v-for="action in actions"
|
||||||
:draggable="true"
|
:draggable="true"
|
||||||
@dragstart="onDragStart($event, action)"
|
@dragstart="onDragStart($event, action)"
|
||||||
|
|||||||
Reference in New Issue
Block a user