fix(manifest): 新增首页的动态组件

This commit is contained in:
chengcheng 2025-08-29 18:02:27 +08:00
parent 6e3253af8c
commit 68d0048393
10 changed files with 1281 additions and 5 deletions

23
app.vue
View File

@ -1,22 +1,39 @@
<template>
<div>
<!-- 调试对象-->
<!-- 绘画面板-图片上传组件-->
<ImageUpload />
<!-- 首页-所有应用组件-->
<AllApps/>
</div>
</template>
<script lang="ts" setup>
import {
GlobalInjectKeyConst,
type GlobalInjectMaterials,
type GlobalInjectMaterials, type GlobalInjectWorkflowAppStatus
} from "~/types/common";
import { MockMaterials } from "~/composables/mock/material.data";
import { MorkWorkflows } from "~/composables/mock/workflow.data";
const materialData = ref(MockMaterials);
/**
* EasyAI平台已全局注入素材库库信息这里使用mock数据用于调试
* EasyAI平台已全局注入素材库库信息这里使用mock数据用于调试
*/
provide<GlobalInjectMaterials>(GlobalInjectKeyConst.AllMaterials, {
materials: materialData,
refreshMaterials: async () => [],
refreshMaterials: async () => void 0,
});
const workflowData = ref(MorkWorkflows)
/**
* EasyAI平台已全局注入工作流应用信息这里使用mock数据用于调试
*/
provide<GlobalInjectWorkflowAppStatus>(GlobalInjectKeyConst.AllWorkFlowApps, {
workflows : workflowData,
refreshAllWorkflows: async () => void 0,
});
</script>

View File

@ -0,0 +1,107 @@
<script setup lang="ts">
interface Props {
data?: any
srcLabel?: string
avatarLabel?: string
usernameLabel?: string
}
const props = withDefaults(defineProps<Props>(), {
srcLabel: 'src',
avatarLabel: 'avatar_url',
usernameLabel: 'username'
})
const isVideo = (src: string) => {
return typeof src === 'string' && src.includes('.mp4')
}
const default_avatar = 'https://oss.gptpro.ink/temps/image/1720368128128.png'
const default_nickname = ''
const linkUrl = computed(() => `/appshows/${props.data['name']}/${props.data['_id']}`)
const handleAccessUrl = () => {
if (props.data?.customAccessUrl) {
navigateTo(props.data?.customAccessUrl, { external: true })
} else {
navigateTo(`/draw/${props.data['name']}/${props.data['_id']}`)
}
}
</script>
<template>
<div>
<NuxtLinkLocale :to="linkUrl">
<div
hoverable
class="relative overflow-hidden cursor-pointer group !p-0"
data-component-id="app-card"
data-component-name="应用"
>
<!-- 视频/图片封面 -->
<div class="overflow-hidden rounded-lg">
<video
v-if="isVideo(data[srcLabel])"
autoplay
loop
muted
playsinline
class="w-full object-cover aspect-[3/4] transition-transform duration-300 group-hover:scale-105"
:src="data[srcLabel]"
type="video/mp4"
/>
<img
v-else
class="w-full object-cover aspect-[3/4] transition-transform duration-300 group-hover:scale-105"
:src="data[srcLabel]"
:alt="data['title']"
/>
</div>
<!-- hover 信息层 -->
<div
class="absolute bottom-0 left-0 w-full h-2/5 rounded-lg invisible group-hover:visible bg-black/50 backdrop-blur-md overflow-hidden transition-all duration-300 flex flex-col justify-start items-start text-white px-3 py-2"
data-component-id="app-card-info"
data-component-name="应用信息"
>
<!-- 标题和描述 -->
<span
class="font-medium truncate w-full"
data-component-id="app-card-info-title"
>
{{ data["title"] }}
</span>
<p
class="text-xs opacity-80 truncate w-full"
data-component-id="app-card-info-description"
>
{{ data["description"] }}
</p>
<!-- 作者信息 -->
<div class="flex items-center mt-auto w-full">
<a-avatar
:src="data['user']?.[avatarLabel] || default_avatar"
size="small"
class="mr-2"
/>
<span class="text-xs opacity-80">
{{ data["user"]?.["nickname"] || default_nickname }}
</span>
</div>
<!-- 操作按钮 -->
<div class="w-full flex justify-center mt-2">
<button
class="w-4/5 rounded-full px-4 py-0.5 border-gray-300 bg-blue-500"
@click.stop.prevent="handleAccessUrl"
>
一键使用
</button>
</div>
</div>
</div>
</NuxtLinkLocale>
</div>
</template>

View File

@ -0,0 +1,93 @@
<script setup lang="ts">
import { GlobalInjectKeyConst, type GlobalInjectWorkflowAppStatus } from '~/types'
import AppCard from "~/components/AllApps/AppCard.vue";
const { workflows: apps } = inject<GlobalInjectWorkflowAppStatus>(GlobalInjectKeyConst.AllWorkFlowApps, {})
const fitter = ref<string>('全部')
const tags = computed(() => {
const tags = [] as {
text: string
count: number
}[]
for (const workflow of apps.value) {
if (!workflow.tags) continue
for (const tag of workflow.tags) {
const tagItem = tags.find(t => t.text === tag)
if (tagItem) {
tagItem.count++
} else {
tags.push({ text: tag, count: 1 })
}
}
}
//
return ["全部"].concat(
tags
.filter(v => v.text)
.sort((a, b) => b.count - a.count)
.map(item => item.text)
)
})
/** 过滤后的应用列表 */
const showApps = computed(() => {
if (fitter.value === '全部') {
return apps.value
}
return apps.value.filter(item => item.tags?.includes(fitter.value))
})
</script>
<template>
<div>
<div class="px-2 flex flex-col gap-2">
<div class="text-lg font-bold py-2">
<span>应用中心</span>
</div>
<div>
<!-- 标签选择 -->
<div class="mb-2 flex flex-nowrap overflow-x-auto gap-2 scrollbar-hide">
<a-checkable-tag
v-for="tag in tags"
:key="tag"
:checked="fitter === tag"
@change="() => fitter = tag"
class="px-3 py-1.5 text-sm whitespace-nowrap cursor-pointer"
>
{{ tag }}
</a-checkable-tag>
</div>
<!-- 应用展示 -->
<div class="grid grid-cols-2 md:grid-cols-3 lg:grid-cols-4 xl:grid-cols-6 2xl:grid-cols-6 3xl:grid-cols-8 gap-3">
<div
v-for="item in showApps"
:key="item.id"
class="w-full"
>
<AppCard
:data="item"
src-label="cover"
avatar-label="avatar_url"
/>
</div>
</div>
</div>
</div>
</div>
</template>
<style scoped lang="scss">
.scrollbar-hide {
-ms-overflow-style: none; /* IE & Edge */
scrollbar-width: none; /* Firefox */
}
.scrollbar-hide::-webkit-scrollbar {
display: none; /* Chrome, Safari */
}
</style>

View File

@ -0,0 +1,8 @@
export const BuilderComponentGroupConst = {
HomeTemplate: 'homeTemplate',
Layout: 'layout',
Base: 'base',
} as const
export type BuilderComponentGroupType =
(typeof BuilderComponentGroupConst)[keyof typeof BuilderComponentGroupConst]

View File

@ -2,6 +2,7 @@ import type {
ComfyUIProperties,
ComponentGroupType,
} from "~/composables/meta/interface/drawPanne.interface";
import type {BuilderComponentGroupType} from "~/composables/meta/interface/dynamicPage.interface";
export const ComponentSceneConst = {
DynamicPage: "dynamicPage", // 自定义页面
@ -28,7 +29,7 @@ export interface IComponentMateInfo<
export type ComponentDataMap = {
[ComponentSceneConst.DrawPanne]: IDrawPanneData;
[ComponentSceneConst.DynamicPage]?: never;
[ComponentSceneConst.DynamicPage]: IDynamicPageData;
[ComponentSceneConst.Workflow]?: never;
};
@ -53,3 +54,12 @@ export interface IDrawPanneData {
type?: "number" | "string" | "boolean";
isUnique?: boolean;
}
export interface IDynamicPageData {
icon: string // 图标
label: string // 标签
group: BuilderComponentGroupType //分组
props?: Record<string, unknown> // 组件属性
hint?: string // 提示信息
}

View File

@ -0,0 +1,743 @@
export const MorkWorkflows = [
{
"cover": "https://oss.gptpro.ink/temps/image/1725411766663.png",
"user": {
"username": "admin",
"avatar_url": "https://easyai-1253343986.cos.ap-shanghai.myqcloud.com/2025-07-16/663e19cd4fa9d8078385c7c9/upload/20250716100223104-0iCtX1-ComfyUI_00388_.png",
"_id": "663e19cd4fa9d8078385c7c9",
"nickname": "ke ai de guan li"
},
"title": "Flux",
"description": "目前最强的开源模型!",
"_id": "66dee72fa17822e69b17e0b7",
"tags": [
"flux"
],
"name": "flux",
"type": "common",
"params": [
{
"title": "产出节点(必须)",
"name": "output",
"type": [
"26|SaveImage",
"filename_prefix"
],
"param": "",
"outputType": "image",
"timeout": 60,
"componentName": ""
},
{
"title": "提示词(支持中文)",
"name": "positive",
"type": [
"27|ZFTextTranslation",
"text"
],
"param": "cute anime girl with massive fluffy fennec ears and a big fluffy tail blonde messy long hair blue eyes wearing a maid outfit with a long black dress with a gold leaf pattern and a white apron eating a slice of an apple pie in the kitchen of an old dark victorian mansion with a bright window and very expensive stuff everywhere",
"attributes": {
"enableLLM": true,
"presetPrompt": "你是一名知名的设计师,当用户给你一个场景,你不能简单翻译,而是需要根据用户的场景,设一个该场景的物品摆设,用英语直接输出,不需要任何其他修饰和说明"
},
"mcp_description": "用户具体的生成图片的要求",
"mcp_ignore": false,
"mcp_type": "string",
"mcp_required": true,
"mcp_default": "",
"componentName": "Positive"
},
{
"title": "宽度",
"name": "width",
"type": [
"5|EmptyLatentImage",
"width"
],
"param": 1024,
"attributes": {
"min": 0,
"max": 10,
"step": 1
},
"mcp_description": "图像的宽度",
"mcp_ignore": false,
"mcp_type": "number",
"mcp_required": false,
"mcp_default": "1024",
"componentName": "Width"
},
{
"title": "高度",
"name": "height",
"type": [
"5|EmptyLatentImage",
"height"
],
"param": 1024,
"attributes": {
"min": 0,
"max": 10,
"step": 1
},
"mcp_description": "图像高度",
"mcp_ignore": false,
"mcp_type": "number",
"mcp_required": false,
"mcp_default": "1024",
"componentName": "Height"
},
{
"title": "随机种子",
"name": "seed",
"type": [
"25|RandomNoise",
"noise_seed"
],
"param": "",
"attributes": {
"seedLength": 9
},
"mcp_description": "",
"mcp_ignore": false,
"mcp_type": "string",
"mcp_required": false,
"mcp_default": "",
"componentName": "Seed"
},
{
"title": "生图张数",
"name": "batch_size",
"type": [
"5|EmptyLatentImage",
"batch_size"
],
"param": 1,
"mcp_description": "生成的图像张数",
"mcp_ignore": false,
"mcp_type": "string",
"mcp_required": false,
"mcp_default": "",
"componentName": "BatchSize"
}
],
"category": [],
"appType": "workflow",
"sortNumber": 1,
"created_at": 1725884207000,
"likeCount": 0,
"isLiked": false,
"isFavorited": false,
"favoriteCount": 0,
"useCount": 137,
"power": 20
},
{
"cover": "https://oss.gptpro.ink/temps/image/1720445919922.png",
"user": {
"username": "admin",
"avatar_url": "https://easyai-1253343986.cos.ap-shanghai.myqcloud.com/2025-07-16/663e19cd4fa9d8078385c7c9/upload/20250716100223104-0iCtX1-ComfyUI_00388_.png",
"_id": "663e19cd4fa9d8078385c7c9",
"nickname": "ke ai de guan li"
},
"title": "文生图-Kolors(快手)",
"description": "SD3瞬间不香了快手最新开源文生图大模型",
"_id": "66dee72fa17822e69b17e0b5",
"tags": [
"快手可图",
"中文最强",
"局部重绘",
"图生视频",
"图生图",
"AI写真",
"AI摄影"
],
"name": "Kolors-text2img",
"type": "common",
"params": [
{
"title": "产出节点(必须)",
"name": "output",
"type": [
"16|SaveImage",
"filename_prefix"
],
"param": "",
"outputType": "image",
"timeout": 60,
"componentName": ""
},
{
"title": "正向提示词(支持中文)",
"name": "positive",
"type": [
"12|KolorsTextEncode",
"prompt"
],
"param": "cinematic photograph of an astronaut riding a horse in space",
"componentName": "Positive"
},
{
"title": "负向提示词",
"name": "negative",
"type": [
"12|KolorsTextEncode",
"negative_prompt"
],
"param": "",
"componentName": "Negative"
},
{
"title": "宽度",
"name": "width",
"type": [
"14|KolorsSampler",
"width"
],
"param": "1024",
"componentName": "Width"
},
{
"title": "高度",
"name": "height",
"type": [
"14|KolorsSampler",
"height"
],
"param": "1024",
"componentName": "Height"
},
{
"title": "随机种子",
"name": "seed",
"type": [
"14|KolorsSampler",
"seed"
],
"param": "",
"componentName": "Seed"
}
],
"category": [],
"appType": "workflow",
"sortNumber": 2,
"created_at": 1725884207000,
"likeCount": 0,
"isLiked": false,
"isFavorited": false,
"favoriteCount": 0,
"useCount": 2,
"power": 50
},
{
"cover": "https://oss.gptpro.ink/temps/image/1725416239203.png",
"user": {
"username": "admin",
"avatar_url": "https://easyai-1253343986.cos.ap-shanghai.myqcloud.com/2025-07-16/663e19cd4fa9d8078385c7c9/upload/20250716100223104-0iCtX1-ComfyUI_00388_.png",
"_id": "663e19cd4fa9d8078385c7c9",
"nickname": "ke ai de guan li"
},
"title": "AI扩图",
"description": "AI一键扩图",
"_id": "66dee72fa17822e69b17e0b9",
"tags": [
"AI扩图"
],
"name": "expansion",
"type": "common",
"params": [
{
"title": "产出节点(必须)",
"name": "output",
"type": [
"249|SaveImage",
"filename_prefix"
],
"param": "",
"outputType": "image",
"timeout": 120,
"componentName": ""
},
{
"title": "原图",
"name": "image_path_origin",
"type": [
"253|Image Load",
"image_path"
],
"param": "https://oss.gptpro.ink/temps/image/1725416239203.png",
"componentName": "ImageUploadAuto"
},
{
"title": "上",
"name": "custom_number_slider_1",
"type": [
"225|ImpactInt",
"value"
],
"param": 256,
"attributes": "{\r\n \"min\": 50,\r\n \"max\": 1280,\r\n \"step\": 16\r\n}",
"componentName": "CustomNumberSlider"
},
{
"title": "下",
"name": "custom_number_slider_2",
"type": [
"227|ImpactInt",
"value"
],
"param": 256,
"attributes": "{\r\n \"min\": 50,\r\n \"max\": 1280,\r\n \"step\": 16\r\n}",
"componentName": "CustomNumberSlider"
},
{
"title": "左",
"name": "custom_number_slider_3",
"type": [
"224|ImpactInt",
"value"
],
"param": 1280,
"attributes": "{\r\n \"min\": 50,\r\n \"max\": 1280,\r\n \"step\": 16\r\n}",
"componentName": "CustomNumberSlider"
},
{
"title": "右",
"name": "custom_number_slider_4",
"type": [
"226|ImpactInt",
"value"
],
"param": 1280,
"attributes": "{\r\n \"min\": 50,\r\n \"max\": 1280,\r\n \"step\": 16\r\n}",
"componentName": "CustomNumberSlider"
}
],
"category": [],
"appType": "workflow",
"sortNumber": 3,
"created_at": 1725884207000,
"likeCount": 0,
"isLiked": false,
"isFavorited": false,
"favoriteCount": 0,
"useCount": 1,
"power": 50
},
{
"cover": "https://oss.gptpro.ink/temps/image/19659-769977270-woman, flower dress, colorful, darl background,flower armor,green theme,exposure blend, medium shot, bokeh, (hdr.png",
"user": {
"username": "admin",
"avatar_url": "https://easyai-1253343986.cos.ap-shanghai.myqcloud.com/2025-07-16/663e19cd4fa9d8078385c7c9/upload/20250716100223104-0iCtX1-ComfyUI_00388_.png",
"_id": "663e19cd4fa9d8078385c7c9",
"nickname": "ke ai de guan li"
},
"title": "图生图",
"_id": "66dee72fa17822e69b17e0a2",
"tags": [],
"name": "img2img",
"type": "system",
"params": [
{
"title": "大模型",
"name": "ckpt_name",
"type": [
"92|Efficient Loader",
"ckpt_name"
],
"componentName": "ModelSelect"
},
{
"title": "批量任务",
"name": "image_path_origin",
"type": [
"70|Image Load",
"image_path"
],
"param": "https://wangbo0808.oss-cn-shanghai.aliyuncs.com/aidraw/00004-2024-04-11_Restart.png",
"componentName": "ImageUploadAuto"
},
{
"title": "重绘幅度",
"name": "denoise",
"type": [
"85|KSampler (Efficient)",
"denoise"
],
"componentName": "Denoise"
},
{
"title": "产出节点",
"name": "output",
"type": [
"120|SaveImage"
],
"param": "",
"outputType": "image",
"componentName": ""
}
],
"category": [],
"appType": "workflow",
"sortNumber": 10,
"created_at": 1725884207000,
"likeCount": 0,
"isLiked": false,
"isFavorited": false,
"favoriteCount": 0,
"useCount": 10,
"power": 10
},
{
"cover": "https://oss.gptpro.ink/temps/image/1722226025101.png",
"user": {
"username": "admin",
"avatar_url": "https://easyai-1253343986.cos.ap-shanghai.myqcloud.com/2025-07-16/663e19cd4fa9d8078385c7c9/upload/20250716100223104-0iCtX1-ComfyUI_00388_.png",
"_id": "663e19cd4fa9d8078385c7c9",
"nickname": "ke ai de guan li"
},
"title": "去除背景",
"_id": "66dee72fa17822e69b17e0b0",
"tags": [
"去除背景",
"极速抠图"
],
"name": "removebg",
"type": "system",
"params": [
{
"title": "111",
"name": "width",
"type": [],
"param": "",
"componentName": "Width"
},
{
"title": "产出节点",
"name": "output",
"type": [
"74|SaveImage"
],
"param": "",
"outputType": "image",
"timeout": 30,
"componentName": ""
},
{
"title": "3333",
"name": "advance_onlineEdit_origin",
"type": [],
"param": "",
"componentName": "MaskEditor"
}
],
"category": [],
"appType": "workflow",
"sortNumber": 20,
"created_at": 1725884207000,
"likeCount": 0,
"isLiked": false,
"isFavorited": false,
"favoriteCount": 0,
"useCount": 3
},
{
"cover": "https://static.51easyai.com/Runninghub-template.jpg",
"user": {},
"title": "RunningHub模板应用",
"description": "GPT4o风格 单图模式",
"_id": "681c6bc1affa20f8c7ab76cf",
"tags": [
"RunningHub",
"模板应用",
"图生图"
],
"name": "RunningHub-Template",
"type": "common",
"params": [
{
"title": "产出节点(必须)",
"name": "output",
"type": [
"2|OUTPUT"
],
"param": "",
"outputType": "image",
"timeout": 300,
"componentName": ""
},
{
"name": "custom_hint",
"attributes": {
"hint": "RunningHub生成时间不稳定如果遇到超时可以增加超时时间。",
"href": "/pay/charge"
},
"mcp_description": "",
"mcp_ignore": false,
"mcp_type": "string",
"mcp_required": false,
"mcp_default": "",
"componentName": "Hint"
},
{
"name": "image_path",
"mcp_description": "",
"mcp_ignore": false,
"mcp_type": "string",
"mcp_required": false,
"mcp_default": "",
"type": [
"1|INPUT",
"image"
],
"componentName": "ImageUploadAuto",
"param": "https://static.51easyai.com/Mb4lue-ComfyUI_01060_.png"
},
{
"name": "positive",
"attributes": {
"enableLLM": true,
"enableTranslate": false,
"presetPrompt": "你是一名知名的设计师,当用户给你一个场景,你不能简单翻译,而是需要根据用户的场景,设一个该场景的物品摆设,用英语直接输出,不需要任何其他修饰和说明"
},
"mcp_description": "",
"mcp_ignore": false,
"mcp_type": "string",
"mcp_required": false,
"mcp_default": "",
"type": [
"1|INPUT",
"prompt"
],
"param": "转换为吉卜力风格",
"componentName": "Positive"
}
],
"category": [],
"appType": "customWorkflow",
"sortNumber": 999,
"created_at": 1746696665761,
"likeCount": 0,
"isLiked": false,
"isFavorited": false,
"favoriteCount": 0,
"useCount": 4
},
{
"cover": "https://qnoss.51easyai.com//image/temps/67613b9902cefde1bc4c8cb8/电商_模特换装-1.jpg",
"user": {},
"title": "电商_模特换装自由",
"description": "让你的服装产品匹配到合适的模特",
"_id": "6789ad6629ad8e83b45cb28d",
"tags": [
"图生图",
"局部重绘"
],
"name": "flux-fill-redux",
"type": "common",
"params": [
{
"title": "产出节点(必须)",
"name": "output",
"type": [
"71|SaveImage",
"filename_prefix"
],
"param": "",
"outputType": "image",
"timeout": 120,
"componentName": ""
},
{
"title": "",
"name": "advance_onlineEdit_origin",
"type": [
"189|Image Load",
"image_path"
],
"param": "",
"mcp_description": "被迁移到的对象比如将A迁移到B上这个参数表示B的参数而不是A这很重要",
"mcp_ignore": false,
"mcp_type": "string",
"mcp_required": true,
"mcp_default": "",
"componentName": "MaskEditor"
},
{
"title": "提示上传模特图",
"name": "custom_hint_2",
"type": [],
"param": "",
"attributes": {
"hint": "在这个网格图上传你的模特图,点击上面第一个图标"
},
"mcp_description": "",
"mcp_ignore": false,
"mcp_type": "string",
"mcp_required": false,
"mcp_default": "",
"componentName": "Hint"
},
{
"name": "image_path",
"type": [
"188|Image Load",
"image_path"
],
"mcp_description": "待迁移的对象比如将A迁移到B那这里就表示的是A而不是B",
"mcp_ignore": false,
"mcp_type": "string",
"mcp_required": true,
"mcp_default": "",
"componentName": "ImageUploadAuto"
},
{
"title": "提示上传服装产品图",
"name": "custom_hint_1",
"type": [],
"param": "",
"attributes": {
"hint": "在这里上传你的服装产品白底图↑↑↑"
},
"mcp_description": "",
"mcp_ignore": false,
"mcp_type": "string",
"mcp_required": false,
"mcp_default": "",
"componentName": "Hint"
},
{
"title": "随机种子",
"name": "seed",
"type": [
"3|KSampler",
"seed"
],
"param": 179673955724863,
"attributes": {
"seedLength": 9
},
"mcp_description": "",
"mcp_ignore": true,
"mcp_type": "string",
"mcp_required": false,
"mcp_default": "",
"componentName": "Seed"
},
{
"name": "advance_onlineEdit_mask",
"mcp_description": "",
"mcp_ignore": false,
"mcp_type": "string",
"mcp_required": false,
"mcp_default": "",
"type": [
"191|Image Load",
"image_path"
],
"componentName": "MaskEditor"
}
],
"category": [
"Product"
],
"appType": "workflow",
"sortNumber": 999,
"created_at": 1744949551417,
"likeCount": 0,
"isLiked": false,
"isFavorited": false,
"favoriteCount": 0,
"useCount": 4
},
{
"cover": "https://wangbo0808.oss-cn-shanghai.aliyuncs.com/aidraw/image/temps/00100-2234807540v2.png",
"user": {
"username": "admin",
"avatar_url": "https://easyai-1253343986.cos.ap-shanghai.myqcloud.com/2025-07-16/663e19cd4fa9d8078385c7c9/upload/20250716100223104-0iCtX1-ComfyUI_00388_.png",
"_id": "663e19cd4fa9d8078385c7c9",
"nickname": "ke ai de guan li"
},
"title": "Flux Inpaiting4",
"description": "flux重绘工作流",
"_id": "66fd67a4ec2d1cff74bd9ef9",
"tags": [
"局部重绘"
],
"name": "flux-inpaiting",
"type": "common",
"params": [
{
"title": "产出节点(必须)",
"name": "output",
"type": [
"166|SaveImage",
"filename_prefix"
],
"param": "",
"outputType": "image",
"timeout": 300,
"componentName": ""
},
{
"title": "画板编辑",
"name": "advance_onlineEdit_origin",
"type": [
"174|Image Load",
"image_path"
],
"param": "",
"mcp_description": "需要修改的图",
"mcp_ignore": false,
"mcp_type": "string",
"mcp_required": true,
"mcp_default": "",
"componentName": "MaskEditor"
},
{
"title": "画板",
"name": "advance_onlineEdit_mask",
"type": [
"175|Image Load",
"image_path"
],
"param": "",
"mcp_description": "",
"mcp_ignore": false,
"mcp_type": "string",
"mcp_required": false,
"mcp_default": "",
"componentName": "MaskEditor"
},
{
"title": "提示词",
"name": "positive",
"type": [
"165|ZFTextTranslation",
"text"
],
"param": "棕色头发",
"attributes": {
"enableLLM": true,
"presetPrompt": "你是一名知名的设计师,当用户给你一个场景,你不能简单翻译,而是需要根据用户的场景,设一个该场景的物品摆设,用英语直接输出,不需要任何其他修饰和说明"
},
"mcp_description": "具体修改的要求",
"mcp_ignore": false,
"mcp_type": "string",
"mcp_required": true,
"mcp_default": "",
"componentName": "Positive"
}
],
"category": [],
"appType": "workflow",
"sortNumber": 999,
"created_at": 1727883172000,
"likeCount": 0,
"isLiked": false,
"isFavorited": false,
"favoriteCount": 0,
"useCount": 13,
"power": 100
}
]

14
manifest/AllApps.ts Normal file
View File

@ -0,0 +1,14 @@
import {ComponentSceneConst, type IComponentMateInfo} from "~/composables";
import {BuilderComponentGroupConst} from "~/composables/meta/interface/dynamicPage.interface";
export default {
name: "RemoteAllApps", // 组件名称 备注带上特殊标识不要和已有组件重名比如Remote+组件名
path: "./components/AllApps/index.vue", // 组件路径
scenes: ComponentSceneConst.DynamicPage, // 组件场景
description: "",
data: {
icon: "carbon:app", // 组件图标
label: "全部应用", // 组件标签
group: BuilderComponentGroupConst.HomeTemplate
}
} satisfies IComponentMateInfo<ComponentSceneType>;

View File

@ -16,6 +16,7 @@ export default defineNuxtConfig({
"@nuxt/eslint",
"@nuxtjs/tailwindcss",
"~/modules/generate-manifest",
'@ant-design-vue/nuxt',
],
ssr: false,
css: ["~/assets/css/tailwind.css"],

View File

@ -1,3 +1,5 @@
import type { WorkFlow, WorkFlowApp } from "~/types/workflow";
export enum MaterialTypeEnum {
common = "common", // 公共级别,用户素材
personal = "personal", // 个人级别,用户个人素材
@ -28,6 +30,7 @@ export interface IMaterial {
export const GlobalInjectKeyConst = {
AllMaterials: "allMaterials",
UploadFileToOSS: "useUtilsUploadFileToOSS",
AllWorkFlowApps: "allWorkFlowApps"
} as const;
export type GlobalInjectKeyEnum =
@ -39,6 +42,12 @@ export interface GlobalInjectMaterials {
refreshMaterials: () => Promise<void>;
}
/** 全局注入工作流应用状态 */
export interface GlobalInjectWorkflowAppStatus {
workflows: Ref<WorkFlowApp[], WorkFlow[]>
refreshAllWorkflows: () => Promise<void>
}
/** 全局注入函数 */
/**
* OSS函数
@ -46,6 +55,6 @@ export interface GlobalInjectMaterials {
export interface GlobalInjectUploadFileToOSS {
useUtilsUploadFileToOSS: (
file: File | Blob,
filename?: string,
filename?: string
) => Promise<string>;
}

274
types/workflow.ts Normal file
View File

@ -0,0 +1,274 @@
export enum WorkFlowTypeEnum {
system = 'system', // 系统级别,内置工作流
common = 'common', // 公共级别,用户共享工作流
personal = 'personal' // 个人级别,创作者工作流
}
/**
* @property _id id
* @property title
* @property name
* @property params
* @property workflow
* @property cover
* @property preview
* @property is_public
* @property description
* @property power
* @property nodeCount
* @property runTime
* @property sortNumber
* @property tags
* @property useGuide 使使
* @property includeServers
* @property excludeServers
* @property user
* @property type
* @property mainProducts
* @property comment
* @property organizations
* @property salePrice
* @property updated_at
* @property application_id
* @property editor_model 0 1
* @property prem_level_min 访
* @property category
* @property appType
* @property custom_workflow id
* @property customAccessUrl 访
* @property created_at
* @property isLiked
* @property likeCount
* @property isFavorited
* @property favoriteCount
* @property useCount 使
*/
export interface WorkFlow {
_id?: string
title?: string // 显示名称
name: string // 标准名称,需要保持唯一
params: any // 参数
workflow: string | object // 工作流
cover?: string // 封面图
preview?: string // 预览图
is_public?: boolean // 是否公开
description?: string // 工作流描述
description_mcp?: string // 描述用于mcp
power?: number // 算力消耗
nodeCount?: number // 节点数
runTime?: number // 运行时间,秒
timeout_setting: TimeOutConfig
sortNumber?: number // 排序
tags?: string[] // 应用标签
useGuide?: string // 使用指导图,显示在工作流的使用页面
includeServers?: string[] // 指定运行的服务器名
excludeServers?: string[] // 排除运行的服务器名
user?: User
type?: WorkFlowTypeEnum // 工作流类型
mainProducts?: string[] // 代表作
comment?: IComment[] // 评论
organizations?: string[] // 所属组织
salePrice?: number // 销售价格
updated_at?: number // 更新时间
application_id?: string[] // 所属应用
editor_model?: 0 | 1 // editor_model 0表示创造新内容 1表示编辑已有内容
prem_level_min?: number // 默认为空,表示无需权限层级,有值时表示需要相应的权限层级才可以访问
category?: WorkFlowCategoriesEnum[] // 分类
appType: AppTypeEnum
custom_workflow?: string // 自定义工作流id
template_example_data?: Record<string, any>
customAccessUrl?: string // 自定义访问接口
created_at?: number // 创建时间
isLiked?: boolean // 是否喜欢
likeCount?: number // 喜欢数
isFavorited?: boolean // 是否收藏
favoriteCount?: number // 收藏数
useCount?: number // 使用次数
integrationPlatforms?: { _id: string, code: string, isAuthed: boolean }[] // 集成平台
}
export type WorkFlowApp = Pick<
WorkFlow,
| 'cover'
| 'user'
| 'title'
| 'description'
| '_id'
| 'tags'
| 'name'
| 'type'
| 'category'
| 'customAccessUrl'
| 'params'
| 'appType'
| 'sortNumber'
| 'created_at'
| 'isLiked'
| 'likeCount'
| 'isFavorited'
| 'favoriteCount'
| 'useCount'
| 'power'
>
/** 工作流超时设定 */
export interface TimeOutConfig {
timeout: number
timeoutActions?: TimeOutActionEnum[]
}
export const TimeOutActionConst = {
CANCEL: 'cancel',
CONTINUE: 'continue',
RETRY: 'RETRY'
} as const
export type TimeOutActionEnum =
(typeof TimeOutActionConst)[keyof typeof TimeOutActionConst]
/**
*
* @property _id id
* @property nickname
* @property password
* @property username
* @property wx_openid openid
* @property wx_unionid unionid
* @property avatar_url url
* @property email
* @property inviter_uid id
* @property last_login_date
* @property register_date
* @property last_login_ip ip
* @property mobile
* @property my_invite_code
* @property role
* @property token token
* @property socket_id socket id
* @property status
* @property balance
*/
export interface User {
_id: string
nickname?: string
password?: string
username: string
wx_openid?: string
wx_unionid?: string
avatar_url?: string
email?: string
inviter_uid?: string | User
last_login_date?: number
register_date?: number
last_login_ip?: string
mobile?: string
my_invite_code?: string[]
role?: RoleEnum[]
token?: string
refresh_token?: string
socket_id?: string
status?: 0 | 1 | 2 // 0:正常1:禁用2:删除
balance?: number // 余额
points?: number // 积分
organizations?: Array<Pick<IOrganization, '_id' | 'name' | 'admin_ids'>> // 组织id列表
totalPower?: number // 总积分
}
export interface IComment {
_id?: string
rootId?: string
replyTo?: User | string // 回复的评论ID
content: string // 评论内容
author?: User // 评论者
targetType: CommentTypeEnum // 评论对象的类型 (应用|作品|AI模型|项目)
targetId?: string // 评论对象的ID
deleteFlag?: boolean // 删除标记
created_at?: number // 创建时间
likeCount?: number // 点赞数
authorFlag?: boolean // 作者标记
replies?: IComment[] // 回复评论
}
/**
*
* @description
* @enum Marketing
* @enum Design
* @enum Development
* @enum CustomerService
* @enum Product
* @enum Operations
*/
export enum WorkFlowCategoriesEnum {
Marketing = 'Marketing',
Design = 'Design',
Development = 'Development',
CustomerService = 'CustomerService',
Product = 'Product',
Operations = 'Operations'
}
/**
*
* @enum workflow: ComfyUI工作流应用
* @enum custom: 自定义应用,访
* @enum api: 自定义工作流应用EasyAI
*/
export enum AppTypeEnum {
workflow = 'workflow',
custom = 'custom',
customWorkflow = 'customWorkflow'
}
export enum CommentTypeEnum {
app = 'app', // 应用(工作流)
work = 'work', // 作品
aiModel = 'aiModel', // AI模型
project = 'project' // 项目
}
/**
*
* @property PUBLIC
* @property USER
* @property CREATOR
* @property OPERATOR
* @property MANAGER
* @property ADMIN
*/
export enum RoleEnum {
// 游客
PUBLIC = 'public',
// 普通用户
USER = 'user',
// 创作者
CREATOR = 'creator',
// 运营人员
OPERATOR = 'operator',
// 普通管理员
MANAGER = 'manager',
// 超级管理员
ADMIN = 'admin'
}
export interface IOrganization {
_id: string
name: string
description?: string
parent?: string
level?: number // 权限等级
workflows?: string[] | WorkFlow[]
users?: string[] | User[]
created_at?: number
children?: IOrganization[]
admin_ids: Array<string>
balance: number
concurrency_limit: number
is_default_register_org: boolean // 是否是默认注册组织
enableExclusive: boolean // 启用独享部署
}