Merge branch 'main' of ssh://18.167.251.121:10002/aidlab/FiDA_Front

This commit is contained in:
2026-03-30 17:11:59 +08:00
12 changed files with 105 additions and 35 deletions

View File

@@ -1,5 +1,5 @@
# VITE_APP_URL = http://192.168.31.82:8771
VITE_APP_URL = http://18.167.251.121:10015
# VITE_APP_URL = http://192.168.31.118:8080
# VITE_APP_URL = http://192.168.31.82:8755
VITE_APP_URL = http://192.168.31.82:8755
VITE_GOOGLE_CLIENT_ID = 216037134725-7q8vqp0ohtmohlosltkfg7bd2v29rm5a.apps.googleusercontent.com

View File

@@ -1,7 +1,7 @@
<template>
<!-- <RouteCache /> -->
<router-view></router-view>
<div id="loading" v-if="loading" v-loading="true"></div>
<div id="loading" v-show="loading" v-loading="true"></div>
</template>
<script setup lang="ts">

View File

@@ -47,7 +47,8 @@ export const getProjectList = (params) => {
return request({
url: `/api/project/list`,
method: 'get',
params
params,
loading: true,
})
}
@@ -66,7 +67,8 @@ export const updateProject = (id: string, data: Object) => {
return request({
url: `/api/project/${id}`,
method: 'put',
data
data,
loading: true,
})
}
/**
@@ -77,7 +79,8 @@ export const updateProject = (id: string, data: Object) => {
export const deleteProject = (id: string) => {
return request({
url: `/api/project/${id}`,
method: 'delete'
method: 'delete',
loading: true,
})
}

View File

@@ -38,10 +38,10 @@
<button class="export" @click="emit('import-local')">
<span class="text">本地导入</span>
</button> -->
<button class="workbench" @click="onWorkbench">
<!-- <button class="workbench" @click="onWorkbench">
<span class="icon"><svg-icon name="dc-workbench" size="20" /></span>
<span class="text">{{ $t('DepthCanvas.save') }}</span>
</button>
</button> -->
</div>
</template>

View File

@@ -189,6 +189,10 @@
// const canvas = canvasManager.processCanvasDisUrlJSON(object)
// console.log(canvas)
}
defineExpose({
onWorkbench
})
</script>
<style lang="less">
@import '@vue-flow/core/dist/style.css';

View File

@@ -1,7 +1,7 @@
<template>
<fullscreen-dialog v-model="dialogVisible" @close="onClose" hide-destroy>
<div class="canvas-box">
<depth-canvas :config="config" @workbench="onWorkbench" />
<depth-canvas ref="depthCanvasRef" :config="config" @workbench="onWorkbench" />
</div>
</fullscreen-dialog>
</template>
@@ -22,6 +22,7 @@
onWorkbench(options) {},
onClose() {}
})
const depthCanvasRef = ref(null)
const open = async (options) => {
config.value = options
@@ -61,8 +62,9 @@
}
// 关闭
const onClose = () => {
dialogVisible.value = false
config.value.onClose?.()
depthCanvasRef.value.onWorkbench()
// dialogVisible.value = false
// config.value.onClose?.()
}
defineExpose({

View File

@@ -100,6 +100,7 @@ export class AISelectboxToolManager {
this.demoObject = null
}
createIndicatorObject() {
this.clearIndicatorObject()
const rect = new fabric.Rect({
left: this.startX,
top: this.startY,
@@ -198,8 +199,8 @@ export class AISelectboxToolManager {
if (!this.isDragging) return;
this.isDragging = false;
const object = this.indicatorObject.toJSON("evented")
if (object.width === 0) object.width = 100
if (object.height === 0) object.height = 100
// if (object.width === 0) object.width = 100
// if (object.height === 0) object.height = 100
this.clearIndicatorObject()
this.canvasManager.canvas.renderAll()

View File

@@ -15,13 +15,7 @@ fabric.Object.prototype.toObject_ = fabric.Object.prototype.toObject
fabric.Object.prototype.toObject = function () {
const args = [...arguments]
const arr = [...fabric.Object.prototype.customProperties]
args.forEach(v => {
if (typeof v === 'string') {
arr.push(v)
} else if (Array.isArray(v)) {
arr.push(...v)
}
})
args.forEach(v => (Array.isArray(v) ? arr.push(...v) : arr.push(v)))
if (this.fill?.source === null) {
let image = new Image()
image.crossOrigin = 'anonymous'
@@ -159,6 +153,7 @@ export class CanvasManager {
this.canvas.add(obj)
const id = obj?.info?.id || ""
if (id) {
this.sortActiveObject(obj)
await this.layerManager.updateLayers(!!obj.info.parentId)
this.renderAll()
await this.layerManager.updateLayerThumbnailsById(id)
@@ -173,6 +168,21 @@ export class CanvasManager {
this.renderAll()
}
}
/** 根据激活对象排序当前对象 */
async sortActiveObject(object: any) {
const activeID = this.layerManager.activeID.value;
if (!activeID) return
const activeObject = this.getObjectById(activeID)
if (!activeObject) return
if (object.type !== "group") {
const parentId = activeObject.info?.parentId
if (!object.info.parentId) object.info.parentId = parentId
}
const index = this.getObjects().indexOf(activeObject)
this.canvas.moveTo(object, index + 1)
// await this.sortObjectByIds(ids, isRecord)
}
/** 更新子图层裁剪区域 */
async updateSubLayerClipPath() {

View File

@@ -3,9 +3,42 @@ import { NODE_TYPE, NODE_DATATYPE } from '../tools/index.d'
import { ElMessageBox } from 'element-plus'
import i18n from '@/lang'
import { putSketchFlowCanvas } from '@/api/flow-canvas'
import myEvent from '@/utils/myEvent'
const t = i18n.global.t
//推送到对话框的助手
const chatAssistant = {
[NODE_DATATYPE.TO_REAL_STYLE]:{
content: t('flowCanvas.toRealStyleDesignAssistant'),
nodeType:NODE_DATATYPE.TO_REAL_STYLE,
},
[NODE_DATATYPE.CANVAS_MODE]:{
content: t('flowCanvas.surfaceEditCanvasDesignAssistant'),
nodeType:NODE_DATATYPE.CANVAS_MODE,
},
[NODE_DATATYPE.SURFACE_EDIT]:{
content: t('flowCanvas.surfaceEditAIDesignAssistant'),
nodeType:NODE_DATATYPE.SURFACE_EDIT,
},
[NODE_DATATYPE.COLOR_PALETTE]:{
content: t('flowCanvas.colorPaletteDesignAssistant'),
nodeType:NODE_DATATYPE.COLOR_PALETTE,
},
[NODE_DATATYPE.SCENE_COMPOSITION]:{
content: t('flowCanvas.threeModelDesignAssistant'),
nodeType:NODE_DATATYPE.SCENE_COMPOSITION,
},
[NODE_DATATYPE.TO_3D_MODEL]:{
content: t('flowCanvas.threeModelDesignAssistant'),
nodeType:NODE_DATATYPE.TO_3D_MODEL,
},
[NODE_DATATYPE.TO_3VIEW]:{
content: t('flowCanvas.threeModelDesignAssistant'),
nodeType:NODE_DATATYPE.TO_3VIEW,
},
}
export interface NodesItem {
id: string
type: string
@@ -117,6 +150,7 @@ export class StateManager {
this.nodes.value.push(node);
this.recordState()
this.exportFlow()
if(chatAssistant[node.data.type])myEvent.emit('assistantPushChat',chatAssistant[node.data.type])
}
/** 删除节点 */
async deleteNode(id: string) {
@@ -133,7 +167,7 @@ export class StateManager {
getSuperiorNodeImage(superiorID: string) {
const superiorNode = this.getNodeById(superiorID)
if(!superiorNode){
ElMessage.error(t('flowCanvas.cannotFindSuperiorImage'))
// ElMessage.error(t('flowCanvas.cannotFindSuperiorImage'))
return null
}
const superiorNodeUrl = superiorNode.data.data.imageProcessTasks.filter((item)=>{

View File

@@ -194,7 +194,15 @@ export default {
confirmLeave: 'Are you sure you want to leave? You may have unsaved changes.',
cannotFindSuperiorImage: 'Cannot find the superior image',
deleteSubordinateCard: 'After deletion, all the function cards will also be deleted.',
initialNodeProhibited: 'Initial node is prohibited from being deleted.'
initialNodeProhibited: 'Initial node is prohibited from being deleted.',
toRealStyleDesignAssistant: "🎨 This is one of my favorite parts — just bring in your sketch and I'll take care of the lighting, materials, and rendering to give you a photorealistic result. If the first one doesn't feel quite right, let me try a few more times — I'll give you something a little different each time.",
surfaceEditCanvasDesignAssistant: "🪡 If you have something specific in mind for the materials, this is the mode for that. I can help you swap to fabric, leather, wood, or whatever fits your vision — and if you have your own print, you can upload it directly. This mode gives you full manual control so you can fine-tune exactly what you want. If you'd rather move faster, just switch over and I'll handle it with AI Smart Mapping.",
surfaceEditAIDesignAssistant: "🪡 Want to see how a different material looks without the extra steps? Tell me what you're going for and I'll apply it using AI Smart Mapping — quick and automatic. If you want to dial in the details afterward, just switch to Canvas Mode and we can keep refining.",
colorPaletteDesignAssistant: "🎨 Let me handle the color combinations for you — just pick a few colors you like, and I'll mix and apply them to your product automatically. I can generate several options at once so you can compare and go with the one that feels right.",
sceneCompositionDesignAssistant: "🛋️ I'll place your product into a real interior scene and match the lighting automatically so everything looks like it belongs together. My suggestion: let me make one clean hero shot with a simple background first, then one lifestyle image with more atmosphere — the two together tend to work really well for presentations.",
threeModelDesignAssistant: "🔄 I'll turn your render into a 3D model you can rotate and look at from any angle. I'd recommend paying close attention to the corner joints, leg proportions, and seat depth — these are the spots that are easy to miss in a sketch but tend to cause the most trouble during prototyping. Better to catch them now while it's easy to fix.",
to3DViewDesignAssistant: "📐 We're at the final step! I'll export your 3D model as front, side, and top view!",
},
assistant: {
inputPlaceholder: 'Ask anything'

View File

@@ -190,7 +190,14 @@ export default {
cancel: '取消',
confirmLeave: '您可能有未保存的更改,确定要离开吗?',
cannotFindSuperiorImage: '找不到上级图片',
initialNodeProhibited: 'Initial node is prohibited from being deleted.'
initialNodeProhibited: '初始节点不能删除',
toRealStyleDesignAssistant: "🎨 这个功能我很喜欢——你只需要把草图丢进来,我来帮你把光影和材质都处理好,直接生成真实感效果图。出来不满意的话就多试几次,每次我都会给你不一样的结果。",
surfaceEditCanvasDesignAssistant: "🪡 如果你对材质有具体想法,可以用这个模式来做。布艺、皮革、木材这些都可以换,也可以把你自己的印花上传进来。这个模式支持你手动精细编辑,想细调哪里都可以——当然如果想快一点,也可以切换到 AI 智能贴图帮你完成。",
surfaceEditAIDesignAssistant: "🪡 想快速看看换材质之后的效果用这个模式把你想要的材质或印花告诉我AI 智能贴图帮你一步到位。如果觉得还想再调整细节,随时可以切换到 Canvas 模式继续编辑。",
colorPaletteDesignAssistant: "🎨 配色交给我来帮你——你选几种喜欢的颜色,我来帮你搭配应用到产品上。我可以一次给你生成好几个方案,你对比着挑就好。",
sceneCompositionDesignAssistant: "🛋️ 我来帮你把产品放进一个真实的空间场景里,光影我会自动帮你匹配。我的建议是先出一张背景干净的主图,再出一张有生活感的氛围图,两张配合着用,展示效果会好很多。",
threeModelDesignAssistant: "🔄 我把你的效果图变成可以转着看的立体模型,你可以从各个角度检查一下结构。我建议重点看看转角、腿脚比例和座面厚度——这几个地方在草图里不容易发现问题,但打样的时候最容易出偏差,现在发现比较好改。",
to3DViewDesignAssistant: "📐 我们到最后一步了!我来帮你把 3D 模型导出为前视图、侧视图和俯视图!",
},
assistant: {
inputPlaceholder: '请输入'

View File

@@ -23,7 +23,7 @@
</span>
</div>
<div class="history-list mini-scrollbar" v-show="!isCollapse && showHistory">
<div v-for="item in list" :key="item.name" class="history-item">
<div v-for="item in list" :key="item.id" class="history-item">
<div v-if="item.title" class="title">{{ item.name }}</div>
<div
v-else
@@ -43,18 +43,18 @@
/>
<span class="label" v-show="!item.edit">{{ item.name }}</span>
<el-popover
ref="popoverRef"
placement="right"
trigger="contextmenu"
trigger="click"
width="10rem"
popper-style="
padding: .6rem 0.7rem;
border-radius: 1rem;
min-width: 10rem;
"
v-model:visible="item.visible"
>
<template #reference>
<span @click.stop="openPopover(item)" class="icon">
<span @click.stop class="icon">
<svg-icon name="more" size="16" />
</span>
</template>
@@ -119,8 +119,12 @@
router.push({ name: 'agent', params: { id: item.id } })
}
const inputRef = ref(null)
const popoverRef = ref(null)
const hidePopover = () => {
popoverRef.value.forEach((v: any) => v.hide())
}
const onRenameHistoryItem = (item: any) => {
item.visible = false
hidePopover()
item.edit = true
nextTick(() => {
inputRef.value.forEach((v: any) => {
@@ -142,7 +146,7 @@
})
}
const onDeleteHistoryItem = (item: any) => {
item.visible = false
hidePopover()
deleteProject(item.id).then(() => {
GetProjectList()
if (item.id == id.value) {
@@ -165,7 +169,7 @@
const yesterdayList = []
const earlierChatList = []
arr.forEach((item: any) => {
const obj = { ...item, edit: false, visible: false }
const obj = { ...item, edit: false }
const date = FormatDate(obj.updateTime * 1000, str)
if (date == today) {
todayList.push(obj)
@@ -177,6 +181,7 @@
})
if (todayList.length > 0) {
list.value.push({
id: 'today',
title: true,
name: $t('Home.today')
})
@@ -184,6 +189,7 @@
}
if (yesterdayList.length > 0) {
list.value.push({
id: 'yesterday',
title: true,
name: $t('Home.yesterday')
})
@@ -191,6 +197,7 @@
}
if (earlierChatList.length > 0) {
list.value.push({
id: 'earlierChat',
title: true,
name: $t('Home.earlierChat')
})
@@ -207,12 +214,6 @@
}
})
}
const openPopover = (item: any) => {
list.value.forEach((item: any) => {
item.visible = false
})
item.visible = !item.visible
}
onMounted(() => {
MyEvent.add('newTitle', replaceTitle)
})