mirror of
https://github.com/jxxghp/MoviePilot-Frontend.git
synced 2026-09-06 08:06:43 +08:00
feat:插件详情支持动态API调用
This commit is contained in:
@@ -1,4 +1,9 @@
|
|||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
|
// 定义输入参数
|
||||||
|
const props = defineProps({
|
||||||
|
// 是否显示
|
||||||
|
innerClass: String,
|
||||||
|
})
|
||||||
// 定义触发的自定义事件
|
// 定义触发的自定义事件
|
||||||
const emit = defineEmits(['click', 'update:modelValue'])
|
const emit = defineEmits(['click', 'update:modelValue'])
|
||||||
// 按钮点击
|
// 按钮点击
|
||||||
@@ -9,10 +14,7 @@ function onClick() {
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<IconBtn
|
<IconBtn :class="props.innerClass ? props.innerClass : 'absolute right-3 top-3'" @click.stop="onClick">
|
||||||
class="absolute right-3 top-3"
|
|
||||||
@click.stop="onClick"
|
|
||||||
>
|
|
||||||
<VIcon icon="mdi-close" />
|
<VIcon icon="mdi-close" />
|
||||||
</IconBtn>
|
</IconBtn>
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
@@ -62,7 +62,7 @@ const pluginInfoDialog = ref(false)
|
|||||||
const progressText = ref('正在更新插件...')
|
const progressText = ref('正在更新插件...')
|
||||||
|
|
||||||
// 插件数据页面配置项
|
// 插件数据页面配置项
|
||||||
let pluginPageItems = reactive([])
|
let pluginPageItems = ref([])
|
||||||
|
|
||||||
// 图片是否加载完成
|
// 图片是否加载完成
|
||||||
const isImageLoaded = ref(false)
|
const isImageLoaded = ref(false)
|
||||||
@@ -156,7 +156,7 @@ async function loadPluginForm() {
|
|||||||
async function loadPluginPage() {
|
async function loadPluginPage() {
|
||||||
try {
|
try {
|
||||||
const result: [] = await api.get(`plugin/page/${props.plugin?.id}`)
|
const result: [] = await api.get(`plugin/page/${props.plugin?.id}`)
|
||||||
if (result) pluginPageItems = result
|
if (result) pluginPageItems.value = result
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error(error)
|
console.error(error)
|
||||||
}
|
}
|
||||||
@@ -443,6 +443,7 @@ watch(
|
|||||||
{{ props.plugin?.plugin_desc }}
|
{{ props.plugin?.plugin_desc }}
|
||||||
</VCardText>
|
</VCardText>
|
||||||
</VCard>
|
</VCard>
|
||||||
|
|
||||||
<!-- 插件配置页面 -->
|
<!-- 插件配置页面 -->
|
||||||
<VDialog v-model="pluginConfigDialog" scrollable max-width="60rem" :fullscreen="!display.mdAndUp.value">
|
<VDialog v-model="pluginConfigDialog" scrollable max-width="60rem" :fullscreen="!display.mdAndUp.value">
|
||||||
<VCard :title="`${props.plugin?.plugin_name} - 配置`" class="rounded-t">
|
<VCard :title="`${props.plugin?.plugin_name} - 配置`" class="rounded-t">
|
||||||
@@ -463,7 +464,7 @@ watch(
|
|||||||
<VCard :title="`${props.plugin?.plugin_name}`" class="rounded-t">
|
<VCard :title="`${props.plugin?.plugin_name}`" class="rounded-t">
|
||||||
<DialogCloseBtn v-model="pluginInfoDialog" />
|
<DialogCloseBtn v-model="pluginInfoDialog" />
|
||||||
<VCardText>
|
<VCardText>
|
||||||
<PageRender v-for="(item, index) in pluginPageItems" :key="index" :config="item" />
|
<PageRender @action="loadPluginPage" v-for="(item, index) in pluginPageItems" :key="index" :config="item" />
|
||||||
</VCardText>
|
</VCardText>
|
||||||
<VCardActions>
|
<VCardActions>
|
||||||
<VBtn @click="showPluginConfig"> 配置 </VBtn>
|
<VBtn @click="showPluginConfig"> 配置 </VBtn>
|
||||||
@@ -472,6 +473,7 @@ watch(
|
|||||||
</VCardActions>
|
</VCardActions>
|
||||||
</VCard>
|
</VCard>
|
||||||
</VDialog>
|
</VDialog>
|
||||||
|
|
||||||
<!-- 更新插件进度框 -->
|
<!-- 更新插件进度框 -->
|
||||||
<VDialog v-model="progressDialog" :scrim="false" width="25rem">
|
<VDialog v-model="progressDialog" :scrim="false" width="25rem">
|
||||||
<VCard color="primary">
|
<VCard color="primary">
|
||||||
@@ -481,6 +483,7 @@ watch(
|
|||||||
</VCardText>
|
</VCardText>
|
||||||
</VCard>
|
</VCard>
|
||||||
</VDialog>
|
</VDialog>
|
||||||
|
|
||||||
<!-- 更新日志 -->
|
<!-- 更新日志 -->
|
||||||
<VDialog v-if="releaseDialog" v-model="releaseDialog" width="600" scrollable>
|
<VDialog v-if="releaseDialog" v-model="releaseDialog" width="600" scrollable>
|
||||||
<VCard>
|
<VCard>
|
||||||
|
|||||||
@@ -1,6 +1,11 @@
|
|||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
|
import { isNullOrEmptyObject } from '@/@core/utils'
|
||||||
|
import api from '@/api'
|
||||||
import { type PropType, ref } from 'vue'
|
import { type PropType, ref } from 'vue'
|
||||||
|
|
||||||
|
// 定议外部事件
|
||||||
|
const emit = defineEmits(['action'])
|
||||||
|
|
||||||
// 组件接口
|
// 组件接口
|
||||||
interface RenderProps {
|
interface RenderProps {
|
||||||
component: string
|
component: string
|
||||||
@@ -9,6 +14,7 @@ interface RenderProps {
|
|||||||
content?: any
|
content?: any
|
||||||
slots?: any
|
slots?: any
|
||||||
props?: any
|
props?: any
|
||||||
|
events?: any
|
||||||
}
|
}
|
||||||
|
|
||||||
// 输入参数
|
// 输入参数
|
||||||
@@ -16,43 +22,64 @@ const elementProps = defineProps({
|
|||||||
config: Object as PropType<RenderProps>,
|
config: Object as PropType<RenderProps>,
|
||||||
})
|
})
|
||||||
|
|
||||||
// 配置元素
|
// 元素API事件响应
|
||||||
const formItem = ref<RenderProps>(elementProps.config ?? {
|
async function commonAction(api_path: string, method: string, params = {}) {
|
||||||
component: 'div',
|
if (!api_path || !method) return
|
||||||
text: '',
|
if (method.toUpperCase() === 'GET') {
|
||||||
html: '',
|
await api.get(api_path, {
|
||||||
props: {},
|
params: params,
|
||||||
content: [],
|
})
|
||||||
slots: {},
|
} else {
|
||||||
})
|
await api.post(api_path, params)
|
||||||
|
}
|
||||||
|
emit('action')
|
||||||
|
}
|
||||||
|
|
||||||
|
// 组装事件
|
||||||
|
let componentEvents: { [key: string]: any } = {}
|
||||||
|
if (!isNullOrEmptyObject(elementProps.config?.events)) {
|
||||||
|
for (const key in elementProps.config?.events) {
|
||||||
|
const attr = elementProps.config?.events[key]
|
||||||
|
const func = async () => {
|
||||||
|
await commonAction(attr['api'], attr['method'], attr['params'])
|
||||||
|
}
|
||||||
|
componentEvents[key] = func
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
componentEvents = {}
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<Component
|
<Component
|
||||||
:is="formItem.component"
|
:is="elementProps.config?.component"
|
||||||
v-if="!formItem.html"
|
v-if="!elementProps.config?.html"
|
||||||
v-bind="formItem.props"
|
v-bind="elementProps.config?.props"
|
||||||
|
v-on="componentEvents"
|
||||||
>
|
>
|
||||||
{{ formItem.text }}
|
{{ elementProps.config?.text }}
|
||||||
<template v-for="(content, name) in (formItem.slots || [])" :key="name" v-slot:[name]="{_props}">
|
<template v-for="(content, name) in elementProps.config?.slots || []" :key="name" v-slot:[name]="{ _props }">
|
||||||
<slot :name="name" v-bind="_props">
|
<slot :name="name" v-bind="_props">
|
||||||
<PageRender
|
<PageRender
|
||||||
v-for="(slotItem, slotIndex) in (content || [])"
|
v-for="(slotItem, slotIndex) in content || []"
|
||||||
:key="slotIndex"
|
:key="slotIndex"
|
||||||
:config="slotItem"
|
:config="slotItem"
|
||||||
|
@action="emit('action')"
|
||||||
/>
|
/>
|
||||||
</slot>
|
</slot>
|
||||||
</template>
|
</template>
|
||||||
<PageRender
|
<PageRender
|
||||||
v-for="(innerItem, innerIndex) in (formItem.content || [])"
|
v-for="(innerItem, innerIndex) in elementProps.config?.content || []"
|
||||||
:key="innerIndex"
|
:key="innerIndex"
|
||||||
:config="innerItem"
|
:config="innerItem"
|
||||||
|
@action="emit('action')"
|
||||||
/>
|
/>
|
||||||
</Component>
|
</Component>
|
||||||
<Component
|
<Component
|
||||||
:is="formItem.component"
|
:is="elementProps.config?.component"
|
||||||
v-if="formItem.html"
|
v-if="elementProps.config?.html"
|
||||||
v-bind="formItem.props"
|
v-bind="elementProps.config?.props"
|
||||||
v-html="formItem.html"
|
v-html="elementProps.config?.html"
|
||||||
|
v-on="componentEvents"
|
||||||
/>
|
/>
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
Reference in New Issue
Block a user