Merge branch 'main' of http://18.167.251.121:10003/aidlab/FiDA_Front
This commit is contained in:
1835
package-lock.json
generated
1835
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -14,6 +14,7 @@
|
|||||||
"postinstall": "husky install"
|
"postinstall": "husky install"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"@crazydos/vue-markdown": "^1.1.4",
|
||||||
"@vue-flow/core": "^1.48.2",
|
"@vue-flow/core": "^1.48.2",
|
||||||
"axios": "^1.3.6",
|
"axios": "^1.3.6",
|
||||||
"crypto-js": "^4.2.0",
|
"crypto-js": "^4.2.0",
|
||||||
@@ -21,12 +22,12 @@
|
|||||||
"element-plus": "^2.13.2",
|
"element-plus": "^2.13.2",
|
||||||
"fabric-with-all": "^5.3.1",
|
"fabric-with-all": "^5.3.1",
|
||||||
"gsap": "^3.13.0",
|
"gsap": "^3.13.0",
|
||||||
"markdown-it": "^14.1.0",
|
|
||||||
"md5": "^2.3.0",
|
"md5": "^2.3.0",
|
||||||
"normalize.css": "^8.0.1",
|
"normalize.css": "^8.0.1",
|
||||||
"pinia": "^2.0.32",
|
"pinia": "^2.0.32",
|
||||||
"pinia-persistedstate-plugin": "^0.1.0",
|
"pinia-persistedstate-plugin": "^0.1.0",
|
||||||
"pinia-plugin-persistedstate": "^3.1.0",
|
"pinia-plugin-persistedstate": "^3.1.0",
|
||||||
|
"rehype-raw": "^7.0.0",
|
||||||
"three": "^0.148.0",
|
"three": "^0.148.0",
|
||||||
"vue": "^3.2.47",
|
"vue": "^3.2.47",
|
||||||
"vue-draggable-plus": "^0.6.1",
|
"vue-draggable-plus": "^0.6.1",
|
||||||
|
|||||||
@@ -79,17 +79,17 @@ export const getTaskidResult = (data:taskIdList) => {
|
|||||||
* 图片转真是风格
|
* 图片转真是风格
|
||||||
* @param data 图片转真是风格的参数
|
* @param data 图片转真是风格的参数
|
||||||
* @param data.sketchId sketch id
|
* @param data.sketchId sketch id
|
||||||
|
* @param data.imageUrl 进行生成的图片。minio地址和正常地址都可以
|
||||||
* @param data.mode 选择的模型
|
* @param data.mode 选择的模型
|
||||||
* @param data.size 生成图片的大小
|
* @param data.size 生成图片的大小
|
||||||
* @param data.imageUrl 进行生成的图片。minio地址和正常地址都可以
|
|
||||||
* @param data.userPrompt 生成图片的提示词
|
* @param data.userPrompt 生成图片的提示词
|
||||||
* @returns 图片转真是风格
|
* @returns 图片转真是风格
|
||||||
*/
|
*/
|
||||||
export interface toRealStyleData {
|
export interface toRealStyleData {
|
||||||
sketchId?: string
|
sketchId?: string
|
||||||
|
imageUrl?: string
|
||||||
mode?: string
|
mode?: string
|
||||||
size?: string
|
size?: string
|
||||||
imageUrl?: string
|
|
||||||
userPrompt?: string
|
userPrompt?: string
|
||||||
}
|
}
|
||||||
export const toRealStyleApi = (data:toRealStyleData) => {
|
export const toRealStyleApi = (data:toRealStyleData) => {
|
||||||
@@ -98,11 +98,66 @@ export const toRealStyleApi = (data:toRealStyleData) => {
|
|||||||
method: 'post',
|
method: 'post',
|
||||||
data:{
|
data:{
|
||||||
sketchId: data.sketchId,
|
sketchId: data.sketchId,
|
||||||
|
imageUrl: data.imageUrl,
|
||||||
mode: data.mode,
|
mode: data.mode,
|
||||||
size: data.size,
|
size: data.size,
|
||||||
imageUrl: data.imageUrl,
|
|
||||||
userPrompt: data.userPrompt
|
userPrompt: data.userPrompt
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
/**
|
||||||
|
* 线稿图上色
|
||||||
|
* @param data 线稿图上色的参数
|
||||||
|
* @param data.sketchId sketch id
|
||||||
|
* @param data.imageUrl 进行生成的图片。minio地址和正常地址都可以
|
||||||
|
* @param data.variantCount 生成图片的数量
|
||||||
|
* @param data.colors 生成上色的图片颜色列表
|
||||||
|
* @returns 线稿图上色
|
||||||
|
*/
|
||||||
|
export interface toColorPaletteData {
|
||||||
|
sketchId?: string
|
||||||
|
imageUrl?: string
|
||||||
|
variantCount?: string
|
||||||
|
colors?: Array<string>
|
||||||
|
}
|
||||||
|
export const toColorPaletteApi = (data:toColorPaletteData) => {
|
||||||
|
return request({
|
||||||
|
url: `/api/image/color-palette`,
|
||||||
|
method: 'post',
|
||||||
|
data:{
|
||||||
|
sketchId: data.sketchId,
|
||||||
|
imageUrl: data.imageUrl,
|
||||||
|
variantCount: data.variantCount,
|
||||||
|
colors: data.colors
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 场景构图
|
||||||
|
* @param data 场景构图的参数
|
||||||
|
* @param data.sketchId sketch id
|
||||||
|
* @param data.imageUrl 进行生成的图片。minio地址和正常地址都可以
|
||||||
|
* @param data.styles 生成上色的图片颜色列表
|
||||||
|
* @param data.userPrompt 生成上色的图片颜色列表
|
||||||
|
* @returns 场景构图
|
||||||
|
*/
|
||||||
|
export interface toSceneCompositionData {
|
||||||
|
sketchId?: string
|
||||||
|
imageUrl?: string
|
||||||
|
userPrompt?: string
|
||||||
|
styles?: Array<string>
|
||||||
|
}
|
||||||
|
export const toSceneCompositionApi = (data:toSceneCompositionData) => {
|
||||||
|
return request({
|
||||||
|
url: `/api/image/scene-composition`,
|
||||||
|
method: 'post',
|
||||||
|
data:{
|
||||||
|
sketchId: data.sketchId,
|
||||||
|
imageUrl: data.imageUrl,
|
||||||
|
userPrompt: data.userPrompt,
|
||||||
|
styles: data.styles
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
|||||||
BIN
src/assets/images/generateLoading.png
Normal file
BIN
src/assets/images/generateLoading.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.1 KiB |
BIN
src/assets/images/link-card.png
Normal file
BIN
src/assets/images/link-card.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 4.3 KiB |
BIN
src/assets/images/report-card.png
Normal file
BIN
src/assets/images/report-card.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 6.0 KiB |
@@ -21,7 +21,7 @@
|
|||||||
import { Handle, Position } from '@vue-flow/core'
|
import { Handle, Position } from '@vue-flow/core'
|
||||||
import { NODE_TYPE } from '../tools/index.d'
|
import { NODE_TYPE } from '../tools/index.d'
|
||||||
import { NODE_DATATYPE, NODE_DATATIER } from '../tools/index.d'
|
import { NODE_DATATYPE, NODE_DATATIER } from '../tools/index.d'
|
||||||
import { computed, ref } from 'vue'
|
import { computed, ref, inject } from 'vue'
|
||||||
const handles = ref({
|
const handles = ref({
|
||||||
[NODE_TYPE.INPUT]: [{ id: 'Right', type: 'source', position: Position.Right }],
|
[NODE_TYPE.INPUT]: [{ id: 'Right', type: 'source', position: Position.Right }],
|
||||||
[NODE_TYPE.SECONDARY]: [
|
[NODE_TYPE.SECONDARY]: [
|
||||||
@@ -49,14 +49,19 @@
|
|||||||
default: false
|
default: false
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
const stateManager = inject('stateManager') as any
|
||||||
const nodes = computed(() => props.stateManager.nodes.value)
|
const nodes = computed(() => props.stateManager.nodes.value)
|
||||||
const isSubord = computed(() => nodes.value.some((v) => v.data.superiorID === props.node.id))
|
const isSubord = computed(() => nodes.value.some((v) => v.data.superiorID === props.node.id))
|
||||||
const tier = computed(() => Number(props.node?.data?.tier || 0))
|
const tier = computed(() => Number(props.node?.data?.tier || 0))
|
||||||
|
const isReturned = computed(() => {
|
||||||
|
return props.node.data.type == 'result-image' && props.node.data.data.imageProcessTasks[0].status == 'RETURNED'
|
||||||
|
})
|
||||||
const isAdd = computed(
|
const isAdd = computed(
|
||||||
() =>
|
() =>
|
||||||
!isSubord.value &&
|
!isSubord.value &&
|
||||||
NODE_DATATYPE.RESULT_IMAGE === props.node.data.type &&
|
NODE_DATATYPE.RESULT_IMAGE === props.node.data.type &&
|
||||||
!(tier.value === NODE_DATATIER.TO_3VIEW)
|
!(tier.value === NODE_DATATIER.TO_3VIEW) &&
|
||||||
|
isReturned.value
|
||||||
)
|
)
|
||||||
const onAdd = () => {
|
const onAdd = () => {
|
||||||
const tier_ = tier.value + 1
|
const tier_ = tier.value + 1
|
||||||
|
|||||||
@@ -26,6 +26,7 @@
|
|||||||
const data = reactive({
|
const data = reactive({
|
||||||
colors: []
|
colors: []
|
||||||
})
|
})
|
||||||
|
const emit = defineEmits(['update-data'])
|
||||||
const maxColor = 5
|
const maxColor = 5
|
||||||
const delColor = (i: number) => {
|
const delColor = (i: number) => {
|
||||||
data.colors.splice(i, 1)
|
data.colors.splice(i, 1)
|
||||||
@@ -41,7 +42,17 @@
|
|||||||
data.colors.push(target.value)
|
data.colors.push(target.value)
|
||||||
}
|
}
|
||||||
|
|
||||||
defineExpose({ data })
|
const getApiData = ()=>{
|
||||||
|
return {
|
||||||
|
variantCount: '2',
|
||||||
|
colors: data.colors
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
onMounted(()=>{
|
||||||
|
})
|
||||||
|
|
||||||
|
defineExpose({ data, getApiData })
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="less" scoped>
|
<style lang="less" scoped>
|
||||||
|
|||||||
@@ -36,7 +36,7 @@
|
|||||||
import To3View from './to-3view.vue'
|
import To3View from './to-3view.vue'
|
||||||
import To3DModel from './to-3d-model.vue'
|
import To3DModel from './to-3d-model.vue'
|
||||||
|
|
||||||
import { toRealStyleApi } from '@/api/flow-canvas'
|
import { toRealStyleApi, toColorPaletteApi, toSceneCompositionApi } from '@/api/flow-canvas'
|
||||||
|
|
||||||
// import ToVideo from './to-video.vue'
|
// import ToVideo from './to-video.vue'
|
||||||
// import AddPrint from './add-print.vue'
|
// import AddPrint from './add-print.vue'
|
||||||
@@ -67,13 +67,15 @@
|
|||||||
tier: NODE_DATATIER.SCENE_COMPOSITION,
|
tier: NODE_DATATIER.SCENE_COMPOSITION,
|
||||||
type: NODE_DATATYPE.SCENE_COMPOSITION,
|
type: NODE_DATATYPE.SCENE_COMPOSITION,
|
||||||
title: 'Scene Composition',
|
title: 'Scene Composition',
|
||||||
component: SceneComposition
|
component: SceneComposition,
|
||||||
|
api: toSceneCompositionApi
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
tier: NODE_DATATIER.COLOR_PALETTE,
|
tier: NODE_DATATIER.COLOR_PALETTE,
|
||||||
type: NODE_DATATYPE.COLOR_PALETTE,
|
type: NODE_DATATYPE.COLOR_PALETTE,
|
||||||
title: 'Color Palette',
|
title: 'Color Palette',
|
||||||
component: ColorPalette
|
component: ColorPalette,
|
||||||
|
api: toColorPaletteApi
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
tier: NODE_DATATIER.TO_3D_MODEL,
|
tier: NODE_DATATIER.TO_3D_MODEL,
|
||||||
@@ -119,32 +121,36 @@
|
|||||||
const componentRef = ref(null)
|
const componentRef = ref(null)
|
||||||
|
|
||||||
const onGenerateClick = async () => {
|
const onGenerateClick = async () => {
|
||||||
const data = componentRef.value.data
|
const data = componentRef.value?.getApiData?.() || {}
|
||||||
const subordNode = stateManager.getSubordNodeById(attrs.node.id)
|
const subordNode = stateManager.getSubordNodeByID(attrs.node.id)
|
||||||
emit('update-data', data)
|
emit('update-data', componentRef.value?.data)
|
||||||
console.log(attrs.node,data)
|
|
||||||
if(!attrs.node?.data?.originalImage)console.log('originalImage 找不到原始图片')
|
if(!attrs.node?.data?.originalImage)console.log('originalImage 找不到原始图片')
|
||||||
|
|
||||||
const apiData = {
|
const apiData = {
|
||||||
sketchId: props.sketchId,
|
sketchId: props.sketchId,
|
||||||
mode: data.mode,
|
|
||||||
size: data.pixelRatio,
|
|
||||||
imageUrl: attrs.node?.data?.originalImage,
|
imageUrl: attrs.node?.data?.originalImage,
|
||||||
userPrompt: data.prompt,
|
...data,
|
||||||
}
|
}
|
||||||
const taskList = await currentComponent.value.api(apiData).then((rv)=>{
|
const taskList = await currentComponent.value.api(apiData).then((rv)=>{
|
||||||
return rv
|
return rv
|
||||||
}) || []
|
}) || []
|
||||||
|
// const taskList = [{taskId:'123'}]
|
||||||
|
console.log(taskList)
|
||||||
if (!subordNode) {
|
if (!subordNode) {
|
||||||
nodeManager.createResultNode({
|
taskList.forEach((item,index) => {
|
||||||
data: {
|
nodeManager.createResultNode({
|
||||||
superiorID: attrs.node.id,
|
positionY: index * (50 + 250),
|
||||||
tier: currentComponent.value.tier,
|
|
||||||
data: {
|
data: {
|
||||||
imageProcessTasks:taskList,
|
superiorID: attrs.node.id,
|
||||||
selectTaskId:taskList[0].taskId,
|
createIndexPosition: index,
|
||||||
|
tier: currentComponent.value.tier,
|
||||||
|
isActive: index == 0,
|
||||||
|
data: {
|
||||||
|
imageProcessTasks:[item],
|
||||||
|
selectTaskId:item.taskId,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
})
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
subordNode.data.data.url =
|
subordNode.data.data.url =
|
||||||
|
|||||||
@@ -56,7 +56,13 @@
|
|||||||
data.styles.push(value)
|
data.styles.push(value)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
defineExpose({ data })
|
const getApiData = ()=>{
|
||||||
|
return {
|
||||||
|
styles: data.styles,
|
||||||
|
userPrompt: data.prompt,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
defineExpose({ data, getApiData })
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="less" scoped>
|
<style lang="less" scoped>
|
||||||
|
|||||||
@@ -54,10 +54,18 @@
|
|||||||
const data = reactive({
|
const data = reactive({
|
||||||
prompt: '',
|
prompt: '',
|
||||||
pixelRatio: '1:1',
|
pixelRatio: '1:1',
|
||||||
mode: 'Normal'
|
mode: 'Normal',
|
||||||
})
|
})
|
||||||
|
|
||||||
defineExpose({ data })
|
const getApiData = ()=>{
|
||||||
|
return {
|
||||||
|
mode: data.mode,
|
||||||
|
size: data.pixelRatio,
|
||||||
|
userPrompt: data.prompt,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
defineExpose({ data, getApiData })
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="less" scoped>
|
<style lang="less" scoped>
|
||||||
|
|||||||
@@ -4,10 +4,10 @@
|
|||||||
<div class="result-image"
|
<div class="result-image"
|
||||||
v-for="(item, i) in data.imageProcessTasks"
|
v-for="(item, i) in data.imageProcessTasks"
|
||||||
:key="item.taskId"
|
:key="item.taskId"
|
||||||
:class="{'active': item.taskId === data.selectTaskId}"
|
:class="{'active': config.isActive}"
|
||||||
@click="setSelectTaskId(item.taskId)"
|
@click="setSelectTaskId(item.taskId)"
|
||||||
>
|
>
|
||||||
<div class="header" v-show="showHeader && item.taskId === data.selectTaskId" @mousedown.stop>
|
<div class="header" v-if="item.status == 'RETURNED'" v-show="showHeader && item.taskId === data.selectTaskId" @mousedown.stop>
|
||||||
<span class="icon">
|
<span class="icon">
|
||||||
<svg-icon name="chat-compose" size="20" size-unit="px" />
|
<svg-icon name="chat-compose" size="20" size-unit="px" />
|
||||||
</span>
|
</span>
|
||||||
@@ -24,10 +24,19 @@
|
|||||||
</div>
|
</div>
|
||||||
<img
|
<img
|
||||||
class="image"
|
class="image"
|
||||||
|
v-if="item.status == 'RETURNED'"
|
||||||
:src="item?.url"
|
:src="item?.url"
|
||||||
:style="{ transform: `scale(${item?.scale?.x || 1}, ${item?.scale?.y || 1})` }"
|
:style="{ transform: `scale(${item?.scale?.x || 1}, ${item?.scale?.y || 1})` }"
|
||||||
/>
|
/>
|
||||||
<div class="more" @click="clickimageProcessTaskItem(item.taskId)" @mousedown.stop>
|
<div class="status" v-else>
|
||||||
|
<div class="content">
|
||||||
|
<HighlightAdmin>
|
||||||
|
<img src="@/assets/images/generateLoading.png" alt="">
|
||||||
|
<div class="mask"></div>
|
||||||
|
</HighlightAdmin>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="more" v-if="item.status == 'RETURNED'" @click="clickimageProcessTaskItem(item.taskId)" @mousedown.stop>
|
||||||
<svg-icon name="more" size="24" size-unit="px" color="#C9C9C9" />
|
<svg-icon name="more" size="24" size-unit="px" color="#C9C9C9" />
|
||||||
</div>
|
</div>
|
||||||
<div class="menu" v-show="showMenu && item.taskId === clickTaskId" @mousedown.stop>
|
<div class="menu" v-show="showMenu && item.taskId === clickTaskId" @mousedown.stop>
|
||||||
@@ -50,9 +59,14 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import myEvent from '@/utils/myEvent'
|
import myEvent from '@/utils/myEvent'
|
||||||
import { downloadImage } from '../../../tools/tools'
|
import { downloadImage } from '../../../tools/tools'
|
||||||
import { reactive, ref, onBeforeUnmount, useAttrs, inject, watch, } from 'vue'
|
import { reactive, ref, onBeforeUnmount, useAttrs, inject, watch, computed, onMounted } from 'vue'
|
||||||
|
import HighlightAdmin from '@/components/highlightAdmin.vue'
|
||||||
const openImagePreview = inject('openImagePreview') as (url: string) => void
|
const openImagePreview = inject('openImagePreview') as (url: string) => void
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
|
node: {
|
||||||
|
type: Object,
|
||||||
|
default: () => ({})
|
||||||
|
},
|
||||||
config: {
|
config: {
|
||||||
type: Object,
|
type: Object,
|
||||||
default: () => ({})
|
default: () => ({})
|
||||||
@@ -73,25 +87,30 @@
|
|||||||
const showHeader = ref(!!attrs.node?.data?.isHeader)
|
const showHeader = ref(!!attrs.node?.data?.isHeader)
|
||||||
const showMenu = ref(false)
|
const showMenu = ref(false)
|
||||||
const clickTaskId = ref('')
|
const clickTaskId = ref('')
|
||||||
|
const generateManager = inject('generateManager') as any
|
||||||
const clickimageProcessTaskItem = (taskId: string) => {
|
const clickimageProcessTaskItem = (taskId: string) => {
|
||||||
if(clickTaskId.value == taskId){
|
if(clickTaskId.value == taskId){
|
||||||
showMenu.value = !showMenu.value
|
showMenu.value = !showMenu.value
|
||||||
}
|
}
|
||||||
clickTaskId.value = taskId
|
clickTaskId.value = taskId
|
||||||
}
|
}
|
||||||
const data = reactive({
|
const data = reactive({
|
||||||
selectTaskId: props.data?.selectTaskId || '',
|
selectTaskId: props.data?.selectTaskId || '',
|
||||||
imageProcessTasks: props.data?.imageProcessTasks || [],
|
imageProcessTasks: props.data?.imageProcessTasks,
|
||||||
|
isActive: props.data?.isActive || false,
|
||||||
})
|
})
|
||||||
const setSelectTaskId = (taskId: string) => {
|
const setSelectTaskId = (taskId: string) => {
|
||||||
data.selectTaskId = taskId
|
data.selectTaskId = taskId
|
||||||
emit('update-data', data)
|
|
||||||
}
|
}
|
||||||
watch(
|
watch(
|
||||||
() => props.data.url,
|
() => props.data.status,
|
||||||
(newVal) => {
|
(newVal) => {
|
||||||
data.url = newVal
|
let selectNode = data.imageProcessTasks.find((item) => item.taskId === data.selectTaskId)
|
||||||
}
|
if(selectNode.status !== 'RETURNED'){
|
||||||
|
generateManager.addTaskId(selectNode,props.node.id)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{ immediate: true }
|
||||||
)
|
)
|
||||||
const menus = ref([
|
const menus = ref([
|
||||||
{ label: 'Copy', tip: 'Ctrl+C', on: () => emit('copy-node', clickTaskId.value) },
|
{ label: 'Copy', tip: 'Ctrl+C', on: () => emit('copy-node', clickTaskId.value) },
|
||||||
@@ -103,10 +122,9 @@
|
|||||||
if(clickTaskId.value){
|
if(clickTaskId.value){
|
||||||
data.imageProcessTasks = data.imageProcessTasks.filter((item) => item.taskId !== clickTaskId.value)
|
data.imageProcessTasks = data.imageProcessTasks.filter((item) => item.taskId !== clickTaskId.value)
|
||||||
clickTaskId.value = ''
|
clickTaskId.value = ''
|
||||||
emit('update-data', data)
|
|
||||||
}
|
}
|
||||||
}else{
|
}else{
|
||||||
emit('delete-node')
|
emit('delete-node', props.node.id)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
disabled: !!props.config?.disableDelete
|
disabled: !!props.config?.disableDelete
|
||||||
@@ -137,7 +155,6 @@
|
|||||||
}
|
}
|
||||||
item.scale.x = -item.scale.x
|
item.scale.x = -item.scale.x
|
||||||
})
|
})
|
||||||
emit('update-data', data)
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -150,7 +167,6 @@
|
|||||||
}
|
}
|
||||||
item.scale.y = -item.scale.y
|
item.scale.y = -item.scale.y
|
||||||
})
|
})
|
||||||
emit('update-data', data)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
])
|
])
|
||||||
@@ -176,6 +192,9 @@
|
|||||||
onBeforeUnmount(() => {
|
onBeforeUnmount(() => {
|
||||||
document.removeEventListener('mousedown', hideMenu)
|
document.removeEventListener('mousedown', hideMenu)
|
||||||
})
|
})
|
||||||
|
onMounted(()=>{
|
||||||
|
emit('update-data', data)
|
||||||
|
})
|
||||||
defineExpose({ data })
|
defineExpose({ data })
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
@@ -253,6 +272,30 @@
|
|||||||
width: 100%;
|
width: 100%;
|
||||||
height: auto;
|
height: auto;
|
||||||
}
|
}
|
||||||
|
> .status{
|
||||||
|
width: 100%;
|
||||||
|
height: 140px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
> .content{
|
||||||
|
width: 86px;
|
||||||
|
height: 60px;
|
||||||
|
position: relative;
|
||||||
|
.mask{
|
||||||
|
background-color: rgba(255, 255, 255, 0.2);
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
img{
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
position: relative;
|
position: relative;
|
||||||
|
|
||||||
> .more {
|
> .more {
|
||||||
|
|||||||
@@ -38,7 +38,6 @@
|
|||||||
const onInput = () => {
|
const onInput = () => {
|
||||||
const text = inputRef.value.innerHTML
|
const text = inputRef.value.innerHTML
|
||||||
data.text = text
|
data.text = text
|
||||||
emit('update-data', data)
|
|
||||||
}
|
}
|
||||||
// watch(
|
// watch(
|
||||||
// () => props.active,
|
// () => props.active,
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
<VueFlow
|
<VueFlow
|
||||||
ref="vueFlow"
|
ref="vueFlow"
|
||||||
:nodes="nodes"
|
:nodes="nodes"
|
||||||
:edges="edges"
|
:edges="edges_"
|
||||||
:min-zoom="0.1"
|
:min-zoom="0.1"
|
||||||
:max-zoom="10"
|
:max-zoom="10"
|
||||||
:nodes-draggable="nodesDraggable"
|
:nodes-draggable="nodesDraggable"
|
||||||
@@ -12,6 +12,7 @@
|
|||||||
@node-drag-stop="(e) => eventManager.handleNodeDragStop(e)"
|
@node-drag-stop="(e) => eventManager.handleNodeDragStop(e)"
|
||||||
@viewport-change="(e) => eventManager.handleViewportChange(e)"
|
@viewport-change="(e) => eventManager.handleViewportChange(e)"
|
||||||
@pane-click="(e) => eventManager.handleClick(e)"
|
@pane-click="(e) => eventManager.handleClick(e)"
|
||||||
|
@node-click="(e) => clickNode(e)"
|
||||||
:class="{ 'custom-cursor': !!stateManager.cursor.value }"
|
:class="{ 'custom-cursor': !!stateManager.cursor.value }"
|
||||||
:style="{ '--custom-cursor': stateManager.cursor.value }"
|
:style="{ '--custom-cursor': stateManager.cursor.value }"
|
||||||
>
|
>
|
||||||
@@ -61,7 +62,7 @@
|
|||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { VueFlow, useVueFlow } from '@vue-flow/core'
|
import { VueFlow, useVueFlow } from '@vue-flow/core'
|
||||||
import { computed, ref, markRaw, onMounted, nextTick, provide, onBeforeMount } from 'vue'
|
import { computed, ref, watch, onMounted, nextTick, provide, onBeforeMount } from 'vue'
|
||||||
import { useLayout } from '@/utils/treeDiagram'
|
import { useLayout } from '@/utils/treeDiagram'
|
||||||
import { NODE_TYPE, NODE_COMPONENT } from './tools/index.d'
|
import { NODE_TYPE, NODE_COMPONENT } from './tools/index.d'
|
||||||
// 组件
|
// 组件
|
||||||
@@ -91,6 +92,7 @@
|
|||||||
import { FlowManager } from './manager/FlowManager'
|
import { FlowManager } from './manager/FlowManager'
|
||||||
import { NodeManager } from './manager/NodeManager'
|
import { NodeManager } from './manager/NodeManager'
|
||||||
import { ToolManager, TOOLS } from './manager/ToolManager'
|
import { ToolManager, TOOLS } from './manager/ToolManager'
|
||||||
|
import { GenerateManager } from './manager/GenerateManager'
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
config: {
|
config: {
|
||||||
@@ -126,8 +128,17 @@
|
|||||||
stateManager.setManager({ toolManager })
|
stateManager.setManager({ toolManager })
|
||||||
provide('toolManager', toolManager)
|
provide('toolManager', toolManager)
|
||||||
|
|
||||||
|
// 生成管理器
|
||||||
|
const generateManager = new GenerateManager({ stateManager })
|
||||||
|
stateManager.setManager({ generateManager })
|
||||||
|
provide('generateManager', generateManager)
|
||||||
|
|
||||||
const nodes = computed(() => stateManager.nodes_.value)
|
const nodes = computed(() => stateManager.nodes_.value)
|
||||||
const edges = computed(() => stateManager.edges.value)
|
const edges = computed(() => stateManager.edges.value)
|
||||||
|
const edges_ = computed(() => {
|
||||||
|
console.log(123)
|
||||||
|
return edges.value.filter((v) => v.visible)
|
||||||
|
})
|
||||||
const nodesDraggable = computed(() => stateManager.nodesDraggable.value)
|
const nodesDraggable = computed(() => stateManager.nodesDraggable.value)
|
||||||
const panOnDrag = computed(() => stateManager.panOnDrag.value)
|
const panOnDrag = computed(() => stateManager.panOnDrag.value)
|
||||||
|
|
||||||
@@ -153,6 +164,11 @@
|
|||||||
}, 0)
|
}, 0)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** 点击节点 */
|
||||||
|
const clickNode = (event) => {
|
||||||
|
let node = event.node
|
||||||
|
stateManager.showNodeConnections(node.id)
|
||||||
|
}
|
||||||
/** 删除节点 */
|
/** 删除节点 */
|
||||||
const deleteNode = (id) => {
|
const deleteNode = (id) => {
|
||||||
nodeManager.deleteNode(id)
|
nodeManager.deleteNode(id)
|
||||||
@@ -233,11 +249,12 @@
|
|||||||
disableDelete: true,
|
disableDelete: true,
|
||||||
isHeader: false,
|
isHeader: false,
|
||||||
data: {
|
data: {
|
||||||
|
selectable: false,
|
||||||
imageProcessTasks:[
|
imageProcessTasks:[
|
||||||
{
|
{
|
||||||
id: props.config.imgId,
|
id: props.config.imgId,
|
||||||
url: props.config.url,
|
url: props.config.url,
|
||||||
state:'success',
|
status:'RETURNED',
|
||||||
taskId: timestamp + '',
|
taskId: timestamp + '',
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
|||||||
@@ -1,15 +1,11 @@
|
|||||||
import { getTaskidResult } from '@/api/flow-canvas'
|
import { getTaskidResult } from '@/api/flow-canvas'
|
||||||
interface NodeOptions {
|
import { ElMessage } from 'element-plus'
|
||||||
id?: string
|
// interface NodeOptions {
|
||||||
position?: { x: number, y: number }
|
// }
|
||||||
positionX?: number
|
|
||||||
positionY?: number
|
|
||||||
component?: any
|
|
||||||
}
|
|
||||||
|
|
||||||
export class GenerateManager {
|
export class GenerateManager {
|
||||||
stateManager: any
|
stateManager: any
|
||||||
taskIds: string[] = []
|
taskIds: string[] = []
|
||||||
|
getTaskIdsImgTime: any
|
||||||
constructor(options) {
|
constructor(options) {
|
||||||
this.stateManager = options.stateManager;
|
this.stateManager = options.stateManager;
|
||||||
}
|
}
|
||||||
@@ -19,19 +15,63 @@ export class GenerateManager {
|
|||||||
|
|
||||||
}
|
}
|
||||||
/** 添加taskId */
|
/** 添加taskId */
|
||||||
addTaskId(TaskId: any) {
|
addTaskId(generateData: any,nodeId: string) {
|
||||||
this.stateManager.addTaskId(TaskId)
|
this.taskIds.push({
|
||||||
|
...generateData,
|
||||||
|
nodeId,
|
||||||
|
})
|
||||||
|
this.getTasksIdImg()
|
||||||
}
|
}
|
||||||
/** 添加taskId */
|
/** 添加taskId */
|
||||||
async getTasksIdImg(list) {
|
async getTasksIdImg() {
|
||||||
let taskIds = list.map((item)=>item.taskId)
|
clearInterval(this.getTaskIdsImgTime)
|
||||||
getTaskidResult({taskIds}).then((rv)=>{
|
this.getTaskIdsImgTime = setInterval(()=>{
|
||||||
console.log(rv)
|
let taskIds = this.taskIds.map((item)=>item.taskId)
|
||||||
})
|
getTaskidResult({taskIds}).then((rv:any)=>{
|
||||||
|
//找出成功和失败的任务
|
||||||
|
let returnedTasks = rv.filter((item)=>item.status == 'RETURNED' || item.status == 'FAILED')
|
||||||
|
if(returnedTasks.length == 0)return
|
||||||
|
//剔除调成功的
|
||||||
|
let taskIds_ = JSON.parse(JSON.stringify(this.taskIds))
|
||||||
|
this.taskIds = taskIds_.filter(itemA =>
|
||||||
|
!returnedTasks.some(itemB => itemB.taskId === itemA.taskId)
|
||||||
|
)
|
||||||
|
//把成功的提取出来并且更新到node中
|
||||||
|
const result = returnedTasks.filter(itemA =>
|
||||||
|
taskIds_.some(itemB => {
|
||||||
|
itemA.nodeId = itemB.nodeId
|
||||||
|
return itemB.taskId === itemA.taskId
|
||||||
|
})
|
||||||
|
)
|
||||||
|
result.forEach(item => {
|
||||||
|
this.stateManager.getNodeById(item.nodeId).data.data.imageProcessTasks.forEach((nodeDataItem:any)=>{
|
||||||
|
if(item.taskId == nodeDataItem.taskId){
|
||||||
|
if(item.status == 'FAILED'){
|
||||||
|
this.stateManager.deleteNode(item.nodeId)
|
||||||
|
ElMessage.error(item.errorMessage)
|
||||||
|
}else if(item.status == 'RETURNED'){
|
||||||
|
nodeDataItem.url = item.url
|
||||||
|
nodeDataItem.createTime = item.createTime
|
||||||
|
nodeDataItem.status = item.status
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
if(this.taskIds.length == 0)clearInterval(this.getTaskIdsImgTime)
|
||||||
|
}).catch(()=>{
|
||||||
|
clearInterval(this.getTaskIdsImgTime)
|
||||||
|
console.warn('获取taskId图片失败')
|
||||||
|
})
|
||||||
|
}, 3000)
|
||||||
|
}
|
||||||
|
/** 更新taskId */
|
||||||
|
updateTaskId(taskId: string) {
|
||||||
|
this.stateManager.getNodeById()
|
||||||
}
|
}
|
||||||
|
|
||||||
dispose() {
|
dispose() {
|
||||||
this.taskIds = []
|
this.taskIds = []
|
||||||
|
clearInterval(this.getTaskIdsImgTime)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,6 +10,8 @@ interface NodeData {
|
|||||||
disableDelete?: boolean// 是否禁用删除
|
disableDelete?: boolean// 是否禁用删除
|
||||||
disableCopy?: boolean// 是否禁用复制
|
disableCopy?: boolean// 是否禁用复制
|
||||||
originalImage?: string// 要进行生成的图片
|
originalImage?: string// 要进行生成的图片
|
||||||
|
createIndexPosition?: number// 创建索引位置
|
||||||
|
isActive?: boolean// 是否激活
|
||||||
}
|
}
|
||||||
interface NodeOptions {
|
interface NodeOptions {
|
||||||
id?: string
|
id?: string
|
||||||
@@ -68,9 +70,11 @@ export class NodeManager {
|
|||||||
const options_ = {
|
const options_ = {
|
||||||
...(options ? options : {}),
|
...(options ? options : {}),
|
||||||
component: NODE_COMPONENT.RESULT_IMAGE,
|
component: NODE_COMPONENT.RESULT_IMAGE,
|
||||||
|
positionY: options?.positionY || 0,
|
||||||
data: {
|
data: {
|
||||||
tier: NODE_DATATIER.RESULT_IMAGE,
|
tier: NODE_DATATIER.RESULT_IMAGE,
|
||||||
type: NODE_DATATYPE.RESULT_IMAGE,
|
type: NODE_DATATYPE.RESULT_IMAGE,
|
||||||
|
createIndexPosition: options?.data?.createIndexPosition || 1,
|
||||||
isHeader: true,
|
isHeader: true,
|
||||||
...(options?.data || {}),
|
...(options?.data || {}),
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import { ref, computed } from "vue";
|
import { ref, computed } from "vue";
|
||||||
import { NODE_TYPE } from '../tools/index.d'
|
import { NODE_TYPE, NODE_DATATYPE } from '../tools/index.d'
|
||||||
import { ElMessageBox } from 'element-plus'
|
import { ElMessageBox } from 'element-plus'
|
||||||
import i18n from '@/lang'
|
import i18n from '@/lang'
|
||||||
const t = i18n.global.t
|
const t = i18n.global.t
|
||||||
@@ -35,12 +35,14 @@ export class StateManager {
|
|||||||
flowManager: any
|
flowManager: any
|
||||||
nodeManager: any
|
nodeManager: any
|
||||||
toolManager: any
|
toolManager: any
|
||||||
|
generateManager: any
|
||||||
// 设置管理器
|
// 设置管理器
|
||||||
setManager(options) {
|
setManager(options) {
|
||||||
options.eventManager && (this.eventManager = options.eventManager)
|
options.eventManager && (this.eventManager = options.eventManager)
|
||||||
options.flowManager && (this.flowManager = options.flowManager)
|
options.flowManager && (this.flowManager = options.flowManager)
|
||||||
options.nodeManager && (this.nodeManager = options.nodeManager)
|
options.nodeManager && (this.nodeManager = options.nodeManager)
|
||||||
options.toolManager && (this.toolManager = options.toolManager)
|
options.toolManager && (this.toolManager = options.toolManager)
|
||||||
|
options.generateManager && (this.generateManager = options.generateManager)
|
||||||
}
|
}
|
||||||
constructor(options) {
|
constructor(options) {
|
||||||
this.vueFlow = options.vueFlow
|
this.vueFlow = options.vueFlow
|
||||||
@@ -87,12 +89,14 @@ export class StateManager {
|
|||||||
source: source,
|
source: source,
|
||||||
target: target,
|
target: target,
|
||||||
selectable: false,
|
selectable: false,
|
||||||
|
visible: (node.data.type !== NODE_DATATYPE.RESULT_IMAGE || node.data.isActive),
|
||||||
type: 'default'
|
type: 'default'
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
return arr
|
return arr
|
||||||
})
|
})
|
||||||
|
window.nodes = this.nodes
|
||||||
|
|
||||||
}
|
}
|
||||||
/** 设置激活节点 */
|
/** 设置激活节点 */
|
||||||
@@ -131,8 +135,8 @@ export class StateManager {
|
|||||||
/** 获取节点 */
|
/** 获取节点 */
|
||||||
getNodeById(id: string) { return this.nodes.value.find((node: NodesItem) => node.id === id) }
|
getNodeById(id: string) { return this.nodes.value.find((node: NodesItem) => node.id === id) }
|
||||||
/** 获取下级节点 */
|
/** 获取下级节点 */
|
||||||
getSubordNodeById(id: string) { return this.nodes.value.find((node: NodesItem) => node.data.superiorID === id) }
|
getSubordNodeByID(id: string) { return this.nodes.value.find((node: NodesItem) => node.data.superiorID === id) }
|
||||||
getLastNode() { return this.nodes.value[this.nodes.value.length - 1] }
|
getLastNode() { console.log(this.nodes.value); return this.nodes.value[this.nodes.value.length - 1] }
|
||||||
/** 设置工具 */
|
/** 设置工具 */
|
||||||
setTool(tool: string) { this.tool.value = tool }
|
setTool(tool: string) { this.tool.value = tool }
|
||||||
/** 设置光标 */
|
/** 设置光标 */
|
||||||
@@ -183,6 +187,20 @@ export class StateManager {
|
|||||||
this.nodes.value = JSON.parse(state.nodes)
|
this.nodes.value = JSON.parse(state.nodes)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** 显示指定子节点和父节点连接线,隐藏父节点和其他子节点链接线, */
|
||||||
|
showNodeConnections(id: string) {
|
||||||
|
const node = this.getNodeById(id)
|
||||||
|
if(node.data.component != NODE_DATATYPE.RESULT_IMAGE && node.data.superiorID) return
|
||||||
|
let edges_ = JSON.parse(JSON.stringify(this.edges.value))
|
||||||
|
this.nodes.value.forEach((nodeItem) => {
|
||||||
|
if(node.data.superiorID === nodeItem.data.superiorID && nodeItem.id == id) {
|
||||||
|
nodeItem.data.isActive = true
|
||||||
|
}else if(node.data.superiorID == nodeItem.data.superiorID){
|
||||||
|
nodeItem.data.isActive = false
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
dispose() {
|
dispose() {
|
||||||
this.historyList.value = []
|
this.historyList.value = []
|
||||||
this.historyIndex.value = 0
|
this.historyIndex.value = 0
|
||||||
|
|||||||
61
src/components/highlightAdmin.vue
Normal file
61
src/components/highlightAdmin.vue
Normal file
@@ -0,0 +1,61 @@
|
|||||||
|
<template>
|
||||||
|
<div class="loading" ref="textBox">
|
||||||
|
<slot></slot>
|
||||||
|
<div class="loading-dot" ref="dotBox"></div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { onMounted, nextTick, ref } from "vue";
|
||||||
|
import { gsap } from "gsap";
|
||||||
|
|
||||||
|
const dotBox = ref(null)
|
||||||
|
let tl1 = null;
|
||||||
|
const setTl1 = () => {
|
||||||
|
nextTick(() => {
|
||||||
|
let el = dotBox.value
|
||||||
|
let width = el.offsetWidth + el.parentElement.offsetWidth
|
||||||
|
let time = el.parentElement.offsetWidth / el.offsetWidth
|
||||||
|
tl1 = gsap.timeline();
|
||||||
|
tl1.to(el, time,
|
||||||
|
{
|
||||||
|
ease: "power1.in",
|
||||||
|
left: width * 1.5,
|
||||||
|
onComplete: () => {
|
||||||
|
setTimeout(() => {
|
||||||
|
tl1.restart()
|
||||||
|
}, 1000)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
)
|
||||||
|
tl1.progress(0);
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
setTl1()
|
||||||
|
})
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="less" scoped>
|
||||||
|
.loading {
|
||||||
|
position: relative;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
.loading-dot {
|
||||||
|
height: 200%;
|
||||||
|
aspect-ratio: .2/1;
|
||||||
|
background: radial-gradient(ellipse 150% 150% at center, #ffffff, rgba(255, 255, 255, .2), transparent);
|
||||||
|
box-shadow: 0 0 20px rgba(255, 255, 255, 1);
|
||||||
|
border-radius: 50%;
|
||||||
|
position: absolute;
|
||||||
|
top: 50%;
|
||||||
|
left: 0;
|
||||||
|
transform: translate(-175%, -50%) rotate(-45deg);
|
||||||
|
}
|
||||||
|
|
||||||
|
</style>
|
||||||
@@ -150,7 +150,8 @@ export default {
|
|||||||
agent: {
|
agent: {
|
||||||
copySuccess: 'Text copied to clipboard',
|
copySuccess: 'Text copied to clipboard',
|
||||||
copyFaild: 'Copy failed. Your browser may be restricting clipboard access. Please try copying manually.',
|
copyFaild: 'Copy failed. Your browser may be restricting clipboard access. Please try copying manually.',
|
||||||
Download: 'Download'
|
Download: 'Download',
|
||||||
|
deleteSuccess: 'Successfully deleted'
|
||||||
},
|
},
|
||||||
|
|
||||||
// Version Tree
|
// Version Tree
|
||||||
|
|||||||
@@ -145,7 +145,8 @@ export default {
|
|||||||
copySuccess: '文本已复制到剪贴板',
|
copySuccess: '文本已复制到剪贴板',
|
||||||
copyFaild:
|
copyFaild:
|
||||||
'复制失败。您的浏览器可能限制了剪贴板访问,请允许浏览器访问剪贴板或尝试手动复制。',
|
'复制失败。您的浏览器可能限制了剪贴板访问,请允许浏览器访问剪贴板或尝试手动复制。',
|
||||||
Download: '下载'
|
Download: '下载',
|
||||||
|
deleteSuccess:'删除成功'
|
||||||
},
|
},
|
||||||
|
|
||||||
// Version Tree
|
// Version Tree
|
||||||
@@ -180,6 +181,6 @@ export default {
|
|||||||
cancel: '取消'
|
cancel: '取消'
|
||||||
},
|
},
|
||||||
assistant: {
|
assistant: {
|
||||||
inputPlaceholder: '请输入',
|
inputPlaceholder: '请输入'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -252,17 +252,22 @@
|
|||||||
if (event.includes('todo') || event.includes('webAddress')) {
|
if (event.includes('todo') || event.includes('webAddress')) {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
let hasSketch = false
|
||||||
|
if (event.includes('sketchIDAndUrl')) {
|
||||||
|
hasSketch = true
|
||||||
|
}
|
||||||
|
|
||||||
const dataLines = event
|
const dataLines = event
|
||||||
.split(/\n/)
|
.split(/\n/)
|
||||||
.filter((line) => line.startsWith('data:'))
|
.filter((line) => line.startsWith('data:'))
|
||||||
.map((line) => line.replace(/^data:\s*/, '').trim())
|
.map((line) => line.replace(/^data:\s*/, '').trim())
|
||||||
.filter((content) => content.startsWith('{') || content.startsWith('['))
|
.filter((content) => content.startsWith('{') || content.startsWith('['))
|
||||||
// console.log('dataLInes', dataLines)
|
// console.log('dataLInes', dataLines)
|
||||||
if (isNodeIdEvent) {
|
if (isNodeIdEvent) {
|
||||||
params.versionID = dataLines[0]
|
params.versionID = dataLines[0]
|
||||||
projectStore.setProject({ nodeId: dataLines[0] })
|
projectStore.setProject({ nodeId: dataLines[0] })
|
||||||
}
|
}
|
||||||
|
|
||||||
if (event.includes('tool')) {
|
if (event.includes('tool')) {
|
||||||
MyEvent.emit('loading-sketch')
|
MyEvent.emit('loading-sketch')
|
||||||
}
|
}
|
||||||
@@ -274,11 +279,10 @@
|
|||||||
const jsonData = JSON.parse(jsonText)
|
const jsonData = JSON.parse(jsonText)
|
||||||
console.log('jsonData', jsonData)
|
console.log('jsonData', jsonData)
|
||||||
|
|
||||||
// 赋值 project_id 和 version_id
|
if (hasSketch) {
|
||||||
// if (jsonData.project_id) params.projectID = jsonData.project_id
|
sketchList.value.push({
|
||||||
// if (jsonData.version_id) params.versionID = jsonData.version_id
|
[Object.keys(jsonData)[0]]: jsonData[Object.keys(jsonData)[0]]
|
||||||
if (jsonData.image_url) {
|
})
|
||||||
sketchList.value.push(jsonData.image_url)
|
|
||||||
}
|
}
|
||||||
if (
|
if (
|
||||||
jsonData.content &&
|
jsonData.content &&
|
||||||
@@ -382,10 +386,6 @@
|
|||||||
while (i < dialogue.length) {
|
while (i < dialogue.length) {
|
||||||
const item = dialogue[i]
|
const item = dialogue[i]
|
||||||
|
|
||||||
// if (item.image_url) {
|
|
||||||
// existingImgList.push(item.image_url)
|
|
||||||
// }
|
|
||||||
|
|
||||||
if (item.role === 'user') {
|
if (item.role === 'user') {
|
||||||
// user 角色直接添加
|
// user 角色直接添加
|
||||||
result.push({
|
result.push({
|
||||||
@@ -402,9 +402,6 @@
|
|||||||
// 继续往后找连续的 assistant 消息
|
// 继续往后找连续的 assistant 消息
|
||||||
let j = i + 1
|
let j = i + 1
|
||||||
while (j < dialogue.length && dialogue[j].role === 'assistant') {
|
while (j < dialogue.length && dialogue[j].role === 'assistant') {
|
||||||
// if (dialogue[j].image_url) {
|
|
||||||
// existingImgList.push(dialogue[j].image_url)
|
|
||||||
// }
|
|
||||||
combinedContent += dialogue[j].content || ''
|
combinedContent += dialogue[j].content || ''
|
||||||
j++
|
j++
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,8 +19,17 @@
|
|||||||
class="img-item"
|
class="img-item"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div class="message-txt markdown-body">
|
<div class="message-txt markdown-body flex flex-col">
|
||||||
<div v-html="formatMessage"></div>
|
<!-- <div v-html="formatMessage"></div> -->
|
||||||
|
<VueMarkdown
|
||||||
|
:custom-attrs="customAttrs"
|
||||||
|
:markdown="content.text"
|
||||||
|
:rehype-plugins="[rehypeRaw]"
|
||||||
|
>
|
||||||
|
<template v-slot:s-ReportCard="" {children:children,...attrs}>
|
||||||
|
<ReportCard :report="{ title: attrs.title, content: attrs.content }" />
|
||||||
|
</template>
|
||||||
|
</VueMarkdown>
|
||||||
</div>
|
</div>
|
||||||
<div class="operate flex" :class="{ 'is-user': content.isUser }">
|
<div class="operate flex" :class="{ 'is-user': content.isUser }">
|
||||||
<template v-if="content.isUser">
|
<template v-if="content.isUser">
|
||||||
@@ -59,11 +68,6 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="message-context" v-show="content.streaming">
|
|
||||||
<div class="message-txt">
|
|
||||||
<div v-html="formatMessage"></div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
@@ -74,9 +78,11 @@
|
|||||||
import gsap from 'gsap'
|
import gsap from 'gsap'
|
||||||
import userThumb from '@/assets/images/user-thumb.jpg'
|
import userThumb from '@/assets/images/user-thumb.jpg'
|
||||||
import agentThumb from '@/assets/images/agent-thumb.jpg'
|
import agentThumb from '@/assets/images/agent-thumb.jpg'
|
||||||
import markdownIt from 'markdown-it'
|
import ReportCard from './ReportCard.vue'
|
||||||
|
import UrlCard from './UrlCard.vue'
|
||||||
const md = new markdownIt()
|
import { VueMarkdown } from '@crazydos/vue-markdown'
|
||||||
|
import type { CustomAttrs } from '@crazydos/vue-markdown'
|
||||||
|
import rehypeRaw from 'rehype-raw'
|
||||||
|
|
||||||
const { t } = useI18n()
|
const { t } = useI18n()
|
||||||
|
|
||||||
@@ -85,6 +91,8 @@
|
|||||||
isLast: Boolean
|
isLast: Boolean
|
||||||
}>()
|
}>()
|
||||||
|
|
||||||
|
const emit = defineEmits(['regenerate'])
|
||||||
|
|
||||||
const imageList = computed(() => {
|
const imageList = computed(() => {
|
||||||
const { imageUrls } = props.content
|
const { imageUrls } = props.content
|
||||||
const list = []
|
const list = []
|
||||||
@@ -99,12 +107,18 @@
|
|||||||
return list
|
return list
|
||||||
})
|
})
|
||||||
|
|
||||||
const formatMessage = computed(() => {
|
const customAttrs: CustomAttrs = {
|
||||||
const str = md.render(props.content.text)
|
img: {
|
||||||
return str
|
style: 'max-width: 100%;'
|
||||||
})
|
},
|
||||||
|
a: (node, combinedAttrs) => {
|
||||||
const emit = defineEmits(['regenerate'])
|
if (typeof node.properties.href === 'string') {
|
||||||
|
return { target: '_blank', rel: 'noopener noreferrer' }
|
||||||
|
} else {
|
||||||
|
return {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const operateList = ref([
|
const operateList = ref([
|
||||||
{
|
{
|
||||||
@@ -219,7 +233,7 @@
|
|||||||
.message-context {
|
.message-context {
|
||||||
line-height: 2rem;
|
line-height: 2rem;
|
||||||
font-size: 1.4rem;
|
font-size: 1.4rem;
|
||||||
max-width: 82%;
|
width: 82%;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.operate {
|
.operate {
|
||||||
@@ -278,5 +292,8 @@
|
|||||||
code {
|
code {
|
||||||
white-space: pre-wrap;
|
white-space: pre-wrap;
|
||||||
}
|
}
|
||||||
|
img {
|
||||||
|
max-width: 100%;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -64,84 +64,7 @@
|
|||||||
<span>{{ $t('agent.Download') }}</span>
|
<span>{{ $t('agent.Download') }}</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="content">
|
<div class="content"></div>
|
||||||
# 一级标题
|
|
||||||
<br />
|
|
||||||
# 一级标题
|
|
||||||
<br />
|
|
||||||
# 一级标题
|
|
||||||
<br />
|
|
||||||
# 一级标题
|
|
||||||
<br />
|
|
||||||
# 一级标题
|
|
||||||
<br />
|
|
||||||
# 一级标题
|
|
||||||
<br />
|
|
||||||
# 一级标题
|
|
||||||
<br />
|
|
||||||
# 一级标题
|
|
||||||
<br />
|
|
||||||
# 一级标题
|
|
||||||
<br />
|
|
||||||
# 一级标题
|
|
||||||
<br />
|
|
||||||
# 一级标题 <br />
|
|
||||||
# 一级标题
|
|
||||||
<br />
|
|
||||||
# 一级标题 <br />
|
|
||||||
# 一级标题
|
|
||||||
<br />
|
|
||||||
# 一级标题 <br />
|
|
||||||
# 一级标题
|
|
||||||
<br />
|
|
||||||
# 一级标题 <br />
|
|
||||||
# 一级标题
|
|
||||||
<br />
|
|
||||||
# 一级标题 <br />
|
|
||||||
# 一级标题
|
|
||||||
<br />
|
|
||||||
# 一级标题 <br />
|
|
||||||
# 一级标题
|
|
||||||
<br />
|
|
||||||
# 一级标题 <br />
|
|
||||||
# 一级标题
|
|
||||||
<br />
|
|
||||||
# 一级标题 <br />
|
|
||||||
# 一级标题
|
|
||||||
<br />
|
|
||||||
# 一级标题 <br />
|
|
||||||
# 一级标题
|
|
||||||
<br />
|
|
||||||
# 一级标题 <br />
|
|
||||||
# 一级标题 <br />
|
|
||||||
# 一级标题
|
|
||||||
<br />
|
|
||||||
# 一级标题 <br />
|
|
||||||
# 一级标题
|
|
||||||
<br />
|
|
||||||
# 一级标题 <br />
|
|
||||||
# 一级标题
|
|
||||||
<br />
|
|
||||||
# 一级标题 <br />
|
|
||||||
# 一级标题
|
|
||||||
<br />
|
|
||||||
# 一级标题 <br />
|
|
||||||
# 一级标题
|
|
||||||
<br />
|
|
||||||
# 一级标题 <br />
|
|
||||||
# 一级标题
|
|
||||||
<br />
|
|
||||||
# 一级标题 <br />
|
|
||||||
# 一级标题
|
|
||||||
<br />
|
|
||||||
# 一级标题 <br />
|
|
||||||
# 一级标题
|
|
||||||
<br />
|
|
||||||
# 一级标题 <br />
|
|
||||||
# 一级标题
|
|
||||||
<br />
|
|
||||||
# 一级标题
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -158,7 +81,8 @@
|
|||||||
import { useProjectStore } from '@/stores'
|
import { useProjectStore } from '@/stores'
|
||||||
const projectStore = useProjectStore()
|
const projectStore = useProjectStore()
|
||||||
import MyEvent from '@/utils/myEvent'
|
import MyEvent from '@/utils/myEvent'
|
||||||
|
import { useI18n } from 'vue-i18n'
|
||||||
|
const { t } = useI18n()
|
||||||
const emits = defineEmits(['deleteSketch'])
|
const emits = defineEmits(['deleteSketch'])
|
||||||
|
|
||||||
// 存储每个图片的加载状态
|
// 存储每个图片的加载状态
|
||||||
@@ -217,7 +141,7 @@
|
|||||||
versionNodeId: projectStore.state.nodeId
|
versionNodeId: projectStore.state.nodeId
|
||||||
}).then((res) => {
|
}).then((res) => {
|
||||||
if (res) {
|
if (res) {
|
||||||
ElMessage.success('Delete success')
|
ElMessage.success(t('agent.deleteSuccess'))
|
||||||
emits('deleteSketch', Object.keys(item)[0])
|
emits('deleteSketch', Object.keys(item)[0])
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@@ -230,8 +154,6 @@
|
|||||||
watch(
|
watch(
|
||||||
() => props.sketchList,
|
() => props.sketchList,
|
||||||
(val) => {
|
(val) => {
|
||||||
console.log('-sketchList-', val)
|
|
||||||
|
|
||||||
if (val.length > 0) {
|
if (val.length > 0) {
|
||||||
showLoading.value = false
|
showLoading.value = false
|
||||||
}
|
}
|
||||||
|
|||||||
48
src/views/home/agent/components/ReportCard.vue
Normal file
48
src/views/home/agent/components/ReportCard.vue
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
<template>
|
||||||
|
<div class="report-card">
|
||||||
|
<div class="report-card-header">
|
||||||
|
<span>{{ report.title }}</span>
|
||||||
|
</div>
|
||||||
|
<div class="report-card-content">
|
||||||
|
<span>{{ report.content }}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
const props = defineProps<{
|
||||||
|
report: any
|
||||||
|
}>()
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="less" scoped>
|
||||||
|
.report-card {
|
||||||
|
width:100%;
|
||||||
|
margin: 2.4rem 0;
|
||||||
|
min-height: 11.2rem;
|
||||||
|
background: url('@/assets/images/report-card.png') no-repeat;
|
||||||
|
background-size: 100% 100%;
|
||||||
|
padding: 2.9rem;
|
||||||
|
overflow: hidden;
|
||||||
|
&:first-of-type{
|
||||||
|
margin-top: 0;
|
||||||
|
}
|
||||||
|
&-header {
|
||||||
|
font-family: 'Medium';
|
||||||
|
font-size: 1.6rem;
|
||||||
|
margin-bottom: 1.3rem;
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
display: -webkit-box;
|
||||||
|
-webkit-line-clamp: 3;
|
||||||
|
-webkit-box-orient: vertical;
|
||||||
|
line-clamp: 3;
|
||||||
|
}
|
||||||
|
&-content{
|
||||||
|
font-family: 'Regular';
|
||||||
|
font-weight: 300;
|
||||||
|
font-size: 1.6rem;
|
||||||
|
color: #7c7c7c;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
10
src/views/home/agent/components/UrlCard.vue
Normal file
10
src/views/home/agent/components/UrlCard.vue
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
<template>
|
||||||
|
<ReportCard :report="{title: 'WebSources', content: 'Destination URL'}"/>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import ReportCard from './ReportCard.vue'
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="less" scoped>
|
||||||
|
</style>
|
||||||
Reference in New Issue
Block a user