mirror of
https://github.com/jxxghp/MoviePilot-Frontend.git
synced 2026-09-04 23:18:44 +08:00
feat: 优化插件弹窗加载速度
This commit is contained in:
@@ -12,13 +12,13 @@ function getId() {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* In a real world scenario you'd want to avoid creating refs in a global scope like this as they might not be cleaned up properly.
|
* In a real world scenario you'd want to avoid creating refs in a global scope like this as they might not be cleaned up properly.
|
||||||
* @type {{draggedData: Ref<object|null>, isDragOver: Ref<boolean>, isDragging: Ref<boolean>}}
|
* @type {{draggedData: Ref<any>, isDragOver: Ref<boolean>, isDragging: Ref<boolean>}}
|
||||||
*/
|
*/
|
||||||
const state = {
|
const state = {
|
||||||
/**
|
/**
|
||||||
* The type of the node being dragged.
|
* The type of the node being dragged.
|
||||||
*/
|
*/
|
||||||
draggedData: ref(null),
|
draggedData: ref<any | null>({}),
|
||||||
isDragOver: ref(false),
|
isDragOver: ref(false),
|
||||||
isDragging: ref(false),
|
isDragging: ref(false),
|
||||||
}
|
}
|
||||||
@@ -87,9 +87,11 @@ export default function useDragAndDrop() {
|
|||||||
|
|
||||||
const newNode = {
|
const newNode = {
|
||||||
id: nodeId,
|
id: nodeId,
|
||||||
type: undefined,
|
type: draggedData.value?.type,
|
||||||
|
name: draggedData.value?.name,
|
||||||
|
description: draggedData.value?.description,
|
||||||
position,
|
position,
|
||||||
data: draggedData.value,
|
data: draggedData.value?.data,
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -3,19 +3,13 @@ import { useToast } from 'vue-toast-notification'
|
|||||||
import { useConfirm } from 'vuetify-use-dialog'
|
import { useConfirm } from 'vuetify-use-dialog'
|
||||||
import api from '@/api'
|
import api from '@/api'
|
||||||
import type { Plugin } from '@/api/types'
|
import type { Plugin } from '@/api/types'
|
||||||
import FormRender from '@/components/render/FormRender.vue'
|
|
||||||
import PageRender from '@/components/render/PageRender.vue'
|
|
||||||
import VersionHistory from '@/components/misc/VersionHistory.vue'
|
|
||||||
import { isNullOrEmptyObject } from '@core/utils'
|
import { isNullOrEmptyObject } from '@core/utils'
|
||||||
import noImage from '@images/logos/plugin.png'
|
import noImage from '@images/logos/plugin.png'
|
||||||
import { getDominantColor } from '@/@core/utils/image'
|
import { getDominantColor } from '@/@core/utils/image'
|
||||||
import { useDisplay } from 'vuetify'
|
import VersionHistory from '@/components/misc/VersionHistory.vue'
|
||||||
import ProgressDialog from '../dialog/ProgressDialog.vue'
|
import ProgressDialog from '../dialog/ProgressDialog.vue'
|
||||||
|
import PluginConfigDialog from '../dialog/PluginConfigDialog.vue'
|
||||||
// 显示器宽度
|
import PluginDataDialog from '../dialog/PluginDataDialog.vue'
|
||||||
const display = useDisplay()
|
|
||||||
// APP
|
|
||||||
const appMode = inject('pwaMode') && display.mdAndDown.value
|
|
||||||
|
|
||||||
// 输入参数
|
// 输入参数
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
@@ -47,18 +41,12 @@ const isVisible = ref(true)
|
|||||||
// 插件配置页面
|
// 插件配置页面
|
||||||
const pluginConfigDialog = ref(false)
|
const pluginConfigDialog = ref(false)
|
||||||
|
|
||||||
// 插件配置表单数据
|
|
||||||
const pluginConfigForm = ref({})
|
|
||||||
|
|
||||||
// 菜单显示状态
|
// 菜单显示状态
|
||||||
const menuVisible = ref(false)
|
const menuVisible = ref(false)
|
||||||
|
|
||||||
// 进度框
|
// 进度框
|
||||||
const progressDialog = ref(false)
|
const progressDialog = ref(false)
|
||||||
|
|
||||||
// 插件表单配置项
|
|
||||||
let pluginFormItems = reactive([])
|
|
||||||
|
|
||||||
// 插件数据页面
|
// 插件数据页面
|
||||||
const pluginInfoDialog = ref(false)
|
const pluginInfoDialog = ref(false)
|
||||||
|
|
||||||
@@ -68,9 +56,6 @@ const progressText = ref('正在更新插件...')
|
|||||||
// 用户头像是否加载完成
|
// 用户头像是否加载完成
|
||||||
const isAvatarLoaded = ref(false)
|
const isAvatarLoaded = ref(false)
|
||||||
|
|
||||||
// 插件数据页面配置项
|
|
||||||
let pluginPageItems = ref([])
|
|
||||||
|
|
||||||
// 图片是否加载完成
|
// 图片是否加载完成
|
||||||
const isImageLoaded = ref(false)
|
const isImageLoaded = ref(false)
|
||||||
|
|
||||||
@@ -138,75 +123,14 @@ async function uninstallPlugin() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 调用API读取表单页面
|
|
||||||
async function loadPluginForm() {
|
|
||||||
try {
|
|
||||||
const result: { [key: string]: any } = await api.get(`plugin/form/${props.plugin?.id}`)
|
|
||||||
if (result) {
|
|
||||||
pluginFormItems = result.conf
|
|
||||||
if (result.model) pluginConfigForm.value = result.model
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
console.error(error)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 调用API读取数据页面
|
|
||||||
async function loadPluginPage() {
|
|
||||||
try {
|
|
||||||
const result: [] = await api.get(`plugin/page/${props.plugin?.id}`)
|
|
||||||
if (result) pluginPageItems.value = result
|
|
||||||
} catch (error) {
|
|
||||||
console.error(error)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 调用API读取配置数据
|
|
||||||
async function loadPluginConf() {
|
|
||||||
try {
|
|
||||||
const result: { [key: string]: any } = await api.get(`plugin/${props.plugin?.id}`)
|
|
||||||
if (!isNullOrEmptyObject(result)) pluginConfigForm.value = result
|
|
||||||
} catch (error) {
|
|
||||||
console.error(error)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 调用API保存配置数据
|
|
||||||
async function savePluginConf() {
|
|
||||||
// 显示等待提示框
|
|
||||||
progressDialog.value = true
|
|
||||||
progressText.value = `正在保存 ${props.plugin?.plugin_name} 配置...`
|
|
||||||
try {
|
|
||||||
const result: { [key: string]: any } = await api.put(`plugin/${props.plugin?.id}`, pluginConfigForm.value)
|
|
||||||
if (result.success) {
|
|
||||||
progressDialog.value = false
|
|
||||||
pluginConfigDialog.value = false
|
|
||||||
$toast.success(`插件 ${props.plugin?.plugin_name} 配置已保存`)
|
|
||||||
// 通知父组件刷新
|
|
||||||
emit('save')
|
|
||||||
} else {
|
|
||||||
progressDialog.value = false
|
|
||||||
$toast.error(`插件 ${props.plugin?.plugin_name} 配置保存失败:${result.message}}`)
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
console.error(error)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 显示插件数据
|
// 显示插件数据
|
||||||
async function showPluginInfo() {
|
async function showPluginInfo() {
|
||||||
// 加载数据
|
|
||||||
await loadPluginPage()
|
|
||||||
pluginConfigDialog.value = false
|
pluginConfigDialog.value = false
|
||||||
pluginInfoDialog.value = true
|
pluginInfoDialog.value = true
|
||||||
}
|
}
|
||||||
|
|
||||||
// 显示插件配置
|
// 显示插件配置
|
||||||
async function showPluginConfig() {
|
async function showPluginConfig() {
|
||||||
// 加载表单
|
|
||||||
await loadPluginForm()
|
|
||||||
// 加载配置
|
|
||||||
await loadPluginConf()
|
|
||||||
// 显示对话框
|
// 显示对话框
|
||||||
pluginInfoDialog.value = false
|
pluginInfoDialog.value = false
|
||||||
pluginConfigDialog.value = true
|
pluginConfigDialog.value = true
|
||||||
@@ -303,6 +227,12 @@ function openPluginDetail() {
|
|||||||
else showPluginConfig()
|
else showPluginConfig()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 配置完成
|
||||||
|
function configDone() {
|
||||||
|
pluginConfigDialog.value = false
|
||||||
|
emit('save')
|
||||||
|
}
|
||||||
|
|
||||||
// 弹出菜单
|
// 弹出菜单
|
||||||
const dropdownItems = ref([
|
const dropdownItems = ref([
|
||||||
{
|
{
|
||||||
@@ -485,54 +415,23 @@ watch(
|
|||||||
</VHover>
|
</VHover>
|
||||||
|
|
||||||
<!-- 插件配置页面 -->
|
<!-- 插件配置页面 -->
|
||||||
<VDialog
|
<PluginConfigDialog
|
||||||
v-if="pluginConfigDialog"
|
v-if="pluginConfigDialog"
|
||||||
v-model="pluginConfigDialog"
|
v-model="pluginConfigDialog"
|
||||||
scrollable
|
:plugin="props.plugin"
|
||||||
max-width="60rem"
|
@save="configDone"
|
||||||
:fullscreen="!display.mdAndUp.value"
|
@close="pluginConfigDialog = false"
|
||||||
>
|
@switch="showPluginInfo"
|
||||||
<VCard :title="`${props.plugin?.plugin_name} - 配置`" class="rounded-t">
|
/>
|
||||||
<DialogCloseBtn v-model="pluginConfigDialog" />
|
|
||||||
<VDivider />
|
|
||||||
<VCardText>
|
|
||||||
<FormRender v-for="(item, index) in pluginFormItems" :key="index" :config="item" :model="pluginConfigForm" />
|
|
||||||
</VCardText>
|
|
||||||
<VCardActions class="pt-3">
|
|
||||||
<VBtn v-if="pluginPageItems.length > 0" @click="showPluginInfo" variant="outlined" color="info">
|
|
||||||
查看数据
|
|
||||||
</VBtn>
|
|
||||||
<VSpacer />
|
|
||||||
<VBtn @click="savePluginConf" variant="elevated" prepend-icon="mdi-content-save" class="px-5"> 保存 </VBtn>
|
|
||||||
</VCardActions>
|
|
||||||
</VCard>
|
|
||||||
</VDialog>
|
|
||||||
|
|
||||||
<!-- 插件数据页面 -->
|
<!-- 插件数据页面 -->
|
||||||
<VDialog
|
<PluginDataDialog
|
||||||
v-if="pluginInfoDialog"
|
v-if="pluginInfoDialog"
|
||||||
v-model="pluginInfoDialog"
|
v-model="pluginInfoDialog"
|
||||||
scrollable
|
:plugin="props.plugin"
|
||||||
max-width="80rem"
|
@close="pluginInfoDialog = false"
|
||||||
:fullscreen="!display.mdAndUp.value"
|
@switch="showPluginConfig"
|
||||||
>
|
/>
|
||||||
<VCard :title="`${props.plugin?.plugin_name}`" class="rounded-t">
|
|
||||||
<DialogCloseBtn v-model="pluginInfoDialog" />
|
|
||||||
<VCardText class="min-h-40">
|
|
||||||
<PageRender @action="loadPluginPage" v-for="(item, index) in pluginPageItems" :key="index" :config="item" />
|
|
||||||
</VCardText>
|
|
||||||
<VFab
|
|
||||||
icon="mdi-cog"
|
|
||||||
location="bottom"
|
|
||||||
size="x-large"
|
|
||||||
fixed
|
|
||||||
app
|
|
||||||
appear
|
|
||||||
@click="showPluginConfig"
|
|
||||||
:class="{ 'mb-10': appMode }"
|
|
||||||
/>
|
|
||||||
</VCard>
|
|
||||||
</VDialog>
|
|
||||||
|
|
||||||
<!-- 进度框 -->
|
<!-- 进度框 -->
|
||||||
<ProgressDialog v-if="progressDialog" v-model="progressDialog" :text="progressText" />
|
<ProgressDialog v-if="progressDialog" v-model="progressDialog" :text="progressText" />
|
||||||
|
|||||||
@@ -0,0 +1,109 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
import { useDisplay } from 'vuetify'
|
||||||
|
import type { Plugin } from '@/api/types'
|
||||||
|
import { isNullOrEmptyObject } from '@/@core/utils'
|
||||||
|
import api from '@/api'
|
||||||
|
import { useToast } from 'vue-toast-notification'
|
||||||
|
import FormRender from '../render/FormRender.vue'
|
||||||
|
import ProgressDialog from '../dialog/ProgressDialog.vue'
|
||||||
|
|
||||||
|
// 输入参数
|
||||||
|
const props = defineProps({
|
||||||
|
plugin: {
|
||||||
|
type: Object as PropType<Plugin>,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
// 定义事件
|
||||||
|
const emit = defineEmits(['close', 'save', 'switch'])
|
||||||
|
|
||||||
|
// 显示器宽度
|
||||||
|
const display = useDisplay()
|
||||||
|
|
||||||
|
// 插件配置表单数据
|
||||||
|
const pluginConfigForm = ref({})
|
||||||
|
|
||||||
|
// 插件表单配置项
|
||||||
|
let pluginFormItems = reactive([])
|
||||||
|
|
||||||
|
// 进度框
|
||||||
|
const progressDialog = ref(false)
|
||||||
|
|
||||||
|
// 进度文字
|
||||||
|
const progressText = ref('')
|
||||||
|
|
||||||
|
// 提示框
|
||||||
|
const $toast = useToast()
|
||||||
|
|
||||||
|
// 是否刷新
|
||||||
|
const isRefreshed = ref(false)
|
||||||
|
|
||||||
|
// 调用API读取表单页面
|
||||||
|
async function loadPluginForm() {
|
||||||
|
try {
|
||||||
|
const result: { [key: string]: any } = await api.get(`plugin/form/${props.plugin?.id}`)
|
||||||
|
if (result) {
|
||||||
|
pluginFormItems = result.conf
|
||||||
|
if (result.model) pluginConfigForm.value = result.model
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error(error)
|
||||||
|
}
|
||||||
|
isRefreshed.value = true
|
||||||
|
}
|
||||||
|
|
||||||
|
// 调用API读取配置数据
|
||||||
|
async function loadPluginConf() {
|
||||||
|
try {
|
||||||
|
const result: { [key: string]: any } = await api.get(`plugin/${props.plugin?.id}`)
|
||||||
|
if (!isNullOrEmptyObject(result)) pluginConfigForm.value = result
|
||||||
|
} catch (error) {
|
||||||
|
console.error(error)
|
||||||
|
}
|
||||||
|
isRefreshed.value = true
|
||||||
|
}
|
||||||
|
|
||||||
|
// 调用API保存配置数据
|
||||||
|
async function savePluginConf() {
|
||||||
|
// 显示等待提示框
|
||||||
|
progressDialog.value = true
|
||||||
|
progressText.value = `正在保存 ${props.plugin?.plugin_name} 配置...`
|
||||||
|
try {
|
||||||
|
const result: { [key: string]: any } = await api.put(`plugin/${props.plugin?.id}`, pluginConfigForm.value)
|
||||||
|
if (result.success) {
|
||||||
|
progressDialog.value = false
|
||||||
|
$toast.success(`插件 ${props.plugin?.plugin_name} 配置已保存`)
|
||||||
|
// 通知父组件刷新
|
||||||
|
emit('save')
|
||||||
|
} else {
|
||||||
|
progressDialog.value = false
|
||||||
|
$toast.error(`插件 ${props.plugin?.plugin_name} 配置保存失败:${result.message}}`)
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error(error)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
onBeforeMount(async () => {
|
||||||
|
await loadPluginForm()
|
||||||
|
await loadPluginConf()
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
<template>
|
||||||
|
<VDialog scrollable max-width="60rem" :fullscreen="!display.mdAndUp.value">
|
||||||
|
<VCard :title="`${props.plugin?.plugin_name} - 配置`" class="rounded-t">
|
||||||
|
<DialogCloseBtn @click="emit('close')" />
|
||||||
|
<VDivider />
|
||||||
|
<VCardText v-if="isRefreshed">
|
||||||
|
<FormRender v-for="(item, index) in pluginFormItems" :key="index" :config="item" :model="pluginConfigForm" />
|
||||||
|
</VCardText>
|
||||||
|
<VCardActions class="pt-3">
|
||||||
|
<VBtn v-if="props.plugin?.has_page" @click="emit('switch')" variant="outlined" color="info"> 查看数据 </VBtn>
|
||||||
|
<VSpacer />
|
||||||
|
<VBtn @click="savePluginConf" variant="elevated" prepend-icon="mdi-content-save" class="px-5"> 保存 </VBtn>
|
||||||
|
</VCardActions>
|
||||||
|
</VCard>
|
||||||
|
<!-- 进度框 -->
|
||||||
|
<ProgressDialog v-if="progressDialog" v-model="progressDialog" :text="progressText" />
|
||||||
|
</VDialog>
|
||||||
|
</template>
|
||||||
@@ -0,0 +1,63 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
import { useDisplay } from 'vuetify'
|
||||||
|
import type { Plugin } from '@/api/types'
|
||||||
|
import PageRender from '@/components/render/PageRender.vue'
|
||||||
|
import api from '@/api'
|
||||||
|
|
||||||
|
// 输入参数
|
||||||
|
const props = defineProps({
|
||||||
|
plugin: {
|
||||||
|
type: Object as PropType<Plugin>,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
// 定义事件
|
||||||
|
const emit = defineEmits(['close', 'save', 'switch'])
|
||||||
|
|
||||||
|
// 显示器宽度
|
||||||
|
const display = useDisplay()
|
||||||
|
// APP
|
||||||
|
const appMode = inject('pwaMode') && display.mdAndDown.value
|
||||||
|
|
||||||
|
// 是否刷新
|
||||||
|
const isRefreshed = ref(false)
|
||||||
|
|
||||||
|
// 插件数据页面配置项
|
||||||
|
let pluginPageItems = ref([])
|
||||||
|
|
||||||
|
// 调用API读取数据页面
|
||||||
|
async function loadPluginPage() {
|
||||||
|
try {
|
||||||
|
const result: [] = await api.get(`plugin/page/${props.plugin?.id}`)
|
||||||
|
if (result) pluginPageItems.value = result
|
||||||
|
} catch (error) {
|
||||||
|
console.error(error)
|
||||||
|
}
|
||||||
|
isRefreshed.value = true
|
||||||
|
}
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
loadPluginPage()
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
<template>
|
||||||
|
<VDialog scrollable max-width="80rem" :fullscreen="!display.mdAndUp.value">
|
||||||
|
<VCard :title="`${props.plugin?.plugin_name}`" class="rounded-t">
|
||||||
|
<DialogCloseBtn @click="emit('close')" />
|
||||||
|
<LoadingBanner v-if="!isRefreshed" class="mt-5" />
|
||||||
|
<VCardText v-else class="min-h-40">
|
||||||
|
<PageRender @action="loadPluginPage" v-for="(item, index) in pluginPageItems" :key="index" :config="item" />
|
||||||
|
</VCardText>
|
||||||
|
<VFab
|
||||||
|
icon="mdi-cog"
|
||||||
|
location="bottom"
|
||||||
|
size="x-large"
|
||||||
|
fixed
|
||||||
|
app
|
||||||
|
appear
|
||||||
|
@click="emit('switch')"
|
||||||
|
:class="{ 'mb-10': appMode }"
|
||||||
|
/>
|
||||||
|
</VCard>
|
||||||
|
</VDialog>
|
||||||
|
</template>
|
||||||
@@ -6,54 +6,15 @@ import useDragAndDrop from '@core/utils/workflow'
|
|||||||
import { Workflow } from '@/api/types'
|
import { Workflow } from '@/api/types'
|
||||||
import { useToast } from 'vue-toast-notification'
|
import { useToast } from 'vue-toast-notification'
|
||||||
import api from '@/api'
|
import api from '@/api'
|
||||||
import { useConfirm } from 'vuetify-use-dialog'
|
|
||||||
import Sidebar from '../workflow/Sidebar.vue'
|
import Sidebar from '../workflow/Sidebar.vue'
|
||||||
import DropzoneBackground from '../workflow/DropzoneBackground.vue'
|
import DropzoneBackground from '../workflow/DropzoneBackground.vue'
|
||||||
|
|
||||||
const { onConnect, addEdges, nodes, edges, onNodesChange, applyNodeChanges, onEdgesChange, applyEdgeChanges } =
|
const { onConnect, addEdges, nodes, edges } = useVueFlow()
|
||||||
useVueFlow()
|
|
||||||
|
|
||||||
const { onDragOver, onDrop, onDragLeave, isDragOver } = useDragAndDrop()
|
const { onDragOver, onDrop, onDragLeave, isDragOver } = useDragAndDrop()
|
||||||
|
|
||||||
onConnect(addEdges)
|
onConnect(addEdges)
|
||||||
|
|
||||||
onNodesChange(async (changes: any) => {
|
|
||||||
const nextChanges = []
|
|
||||||
for (const change of changes) {
|
|
||||||
if (change.type === 'remove') {
|
|
||||||
const isConfirmed = await createConfirm({
|
|
||||||
title: '确认',
|
|
||||||
content: `确定要删除该节点吗?`,
|
|
||||||
})
|
|
||||||
if (!isConfirmed) {
|
|
||||||
nextChanges.push(change)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
nextChanges.push(change)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
applyNodeChanges(nextChanges)
|
|
||||||
})
|
|
||||||
|
|
||||||
onEdgesChange(async (changes: any) => {
|
|
||||||
const nextChanges = []
|
|
||||||
for (const change of changes) {
|
|
||||||
if (change.type === 'remove') {
|
|
||||||
const isConfirmed = await createConfirm({
|
|
||||||
title: '确认',
|
|
||||||
content: `确定要删除该节点吗?`,
|
|
||||||
})
|
|
||||||
if (isConfirmed) {
|
|
||||||
nextChanges.push(change)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
nextChanges.push(change)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
applyEdgeChanges(nextChanges)
|
|
||||||
})
|
|
||||||
|
|
||||||
// 定义输入参数
|
// 定义输入参数
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
workflow: Object as PropType<Workflow>,
|
workflow: Object as PropType<Workflow>,
|
||||||
@@ -68,9 +29,6 @@ const workflowForm = ref<any>(props.workflow || {})
|
|||||||
// 提示框
|
// 提示框
|
||||||
const $toast = useToast()
|
const $toast = useToast()
|
||||||
|
|
||||||
// 确认框
|
|
||||||
const createConfirm = useConfirm()
|
|
||||||
|
|
||||||
// 调用API 编辑任务
|
// 调用API 编辑任务
|
||||||
async function updateWorkflow() {
|
async function updateWorkflow() {
|
||||||
// 更新节点和流程
|
// 更新节点和流程
|
||||||
@@ -119,7 +77,13 @@ onMounted(() => {
|
|||||||
</div>
|
</div>
|
||||||
<VCardText class="px-0 py-0">
|
<VCardText class="px-0 py-0">
|
||||||
<div class="dnd-flow" @drop="onDrop">
|
<div class="dnd-flow" @drop="onDrop">
|
||||||
<VueFlow :nodes="nodes" :edges="edges" @dragover="onDragOver" @dragleave="onDragLeave">
|
<VueFlow
|
||||||
|
:nodes="nodes"
|
||||||
|
:edges="edges"
|
||||||
|
:default-edge-options="{ type: 'animation', animated: true }"
|
||||||
|
@dragover="onDragOver"
|
||||||
|
@dragleave="onDragLeave"
|
||||||
|
>
|
||||||
<MiniMap />
|
<MiniMap />
|
||||||
<DropzoneBackground
|
<DropzoneBackground
|
||||||
:style="{
|
:style="{
|
||||||
|
|||||||
@@ -1,59 +1,24 @@
|
|||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
|
import api from '@/api'
|
||||||
import useDragAndDrop from '@core/utils/workflow'
|
import useDragAndDrop from '@core/utils/workflow'
|
||||||
|
|
||||||
const { onDragStart } = useDragAndDrop()
|
const { onDragStart } = useDragAndDrop()
|
||||||
|
|
||||||
// 组件列表
|
// 组件列表
|
||||||
const actions = [
|
const actions = ref([])
|
||||||
{
|
|
||||||
type: 'AddDownloadAction',
|
// 加载组件列表
|
||||||
label: '添加下载资源',
|
async function load_actions() {
|
||||||
},
|
try {
|
||||||
{
|
actions.value = await api.get('workflow/actions')
|
||||||
type: 'AddSubscribeAction',
|
} catch (error) {
|
||||||
label: '添加订阅',
|
console.error(error)
|
||||||
},
|
}
|
||||||
{
|
}
|
||||||
type: 'FetchDownloadsAction',
|
|
||||||
label: '获取下载任务',
|
onMounted(() => {
|
||||||
},
|
load_actions()
|
||||||
{
|
})
|
||||||
type: 'FetchMediasAction',
|
|
||||||
label: '获取媒体数据',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
type: 'FetchRssAction',
|
|
||||||
label: '获取RSS数据',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
type: 'FetchTorrentsAction',
|
|
||||||
label: '搜索站点资源',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
type: 'FilterMediasAction',
|
|
||||||
label: '过滤媒体数据',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
type: 'FilterTorrentsAction',
|
|
||||||
label: '过滤资源数据',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
type: 'ScrapeFileAction',
|
|
||||||
label: '刮削文件',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
type: 'SendEventAction',
|
|
||||||
label: '发送事件',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
type: 'SendMessageAction',
|
|
||||||
label: '发送消息',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
type: 'TransferFileAction',
|
|
||||||
label: '整理文件',
|
|
||||||
},
|
|
||||||
]
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
@@ -67,7 +32,7 @@ const actions = [
|
|||||||
:draggable="true"
|
:draggable="true"
|
||||||
@dragstart="onDragStart($event, action)"
|
@dragstart="onDragStart($event, action)"
|
||||||
>
|
>
|
||||||
{{ action['label'] }}
|
{{ action['name'] }}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</aside>
|
</aside>
|
||||||
|
|||||||
Reference in New Issue
Block a user