调整画布保存机制,把保存画布接口放到状态管理中,完善toRealStyle提示词
This commit is contained in:
@@ -11,10 +11,14 @@
|
|||||||
<svg-icon :name="v.icon" :size="v.iconSize" />
|
<svg-icon :name="v.icon" :size="v.iconSize" />
|
||||||
</span>
|
</span>
|
||||||
</template>
|
</template>
|
||||||
<button class="export" @click="emit('export')">
|
<div>
|
||||||
<span class="icon"><svg-icon name="export" size="11" /></span>
|
<button class="export" @click="emit('export')">
|
||||||
<span class="text">Export</span>
|
<span class="icon"><svg-icon name="export" size="11" /></span>
|
||||||
</button>
|
<span class="text">Export</span>
|
||||||
|
</button>
|
||||||
|
<div v-loading="true" class="mask" v-if="downloadData.status == 'loading'"></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<!-- <button class="import" @click="emit('import')">
|
<!-- <button class="import" @click="emit('import')">
|
||||||
<span class="text">Import</span>
|
<span class="text">Import</span>
|
||||||
</button> -->
|
</button> -->
|
||||||
@@ -26,7 +30,8 @@
|
|||||||
import { TOOLS } from '../manager/ToolManager'
|
import { TOOLS } from '../manager/ToolManager'
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
zoom: { default: 1, type: Number },
|
zoom: { default: 1, type: Number },
|
||||||
step: { default: 0.1, type: Number }
|
step: { default: 0.1, type: Number },
|
||||||
|
downloadData: { default: {}, type: Object }
|
||||||
})
|
})
|
||||||
const emit = defineEmits(['export', 'import'])
|
const emit = defineEmits(['export', 'import'])
|
||||||
const stateManager = inject('stateManager') as any
|
const stateManager = inject('stateManager') as any
|
||||||
@@ -109,8 +114,21 @@
|
|||||||
cursor: not-allowed;
|
cursor: not-allowed;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
> button {
|
> div{
|
||||||
width: 10rem;
|
position: relative;
|
||||||
|
> .mask{
|
||||||
|
position: absolute !important;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
height: 100%;
|
||||||
|
width: 100%;
|
||||||
|
zoom: .6;
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
button {
|
||||||
|
// width: 10rem;
|
||||||
|
padding: 0 2.4rem;
|
||||||
height: 3rem;
|
height: 3rem;
|
||||||
border-radius: 0.4rem;
|
border-radius: 0.4rem;
|
||||||
border: none;
|
border: none;
|
||||||
@@ -118,12 +136,15 @@
|
|||||||
color: #fff;
|
color: #fff;
|
||||||
font-size: 1.1rem;
|
font-size: 1.1rem;
|
||||||
display: flex;
|
display: flex;
|
||||||
|
gap: 0.8rem;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
gap: 0.8rem;
|
position: relative;
|
||||||
|
cursor: pointer;
|
||||||
&:active {
|
&:active {
|
||||||
opacity: 0.8;
|
opacity: 0.8;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -155,12 +155,6 @@
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
stateManager.recordState()
|
|
||||||
// } else {
|
|
||||||
// subordNode.data.data.url =
|
|
||||||
// 'https://s3-alpha-sig.figma.com/img/8ce2/f1a4/12b93da90e5f17109e7430f14837fd14?Expires=1773619200&Key-Pair-Id=APKAQ4GOSFWCW27IBOMQ&Signature=kmLsTFtXJqfvuxj6husWlDkRDMOIRDjzUUjb7zh79GkBKihUHc0f59k5OAImHTPdaiEREUCCpn~8sQ-si5lenuauJpApCmAU~NsxjfQhuh9m5O~GiHenr2fKu0DIJ75-oCE3859fyxoSFXQgZ9PRmeb98kikMR6uRX9nI5TPUHgKO8ZgkhDBTW~iyaDT~1ybnoK7elPa6T2VzfO-bpIyY-MZ71VRq3RxwmZRxduqHEb3Dh-jjrHyh2SoQsHmUjSJOf-uYilfvpGUResZAjAq8ZVLEjvhzKC2bmCNZIp3RmhYO8ctU7pd5t91J6Xaa6jBLtGfMxbqIm652EC79K0RoA__'
|
|
||||||
// setTimeout(() => stateManager.recordState())
|
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
//删除功能卡片
|
//删除功能卡片
|
||||||
const onDeleteClick = ()=>{
|
const onDeleteClick = ()=>{
|
||||||
|
|||||||
@@ -28,23 +28,23 @@
|
|||||||
const shortcutList = ref([
|
const shortcutList = ref([
|
||||||
{
|
{
|
||||||
label: 'Change the...',
|
label: 'Change the...',
|
||||||
value: 'Change the...'
|
value: 'Change the style to a realistic design. '
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: 'Bright Colors...',
|
label: 'Bright Colors...',
|
||||||
value: 'Bright Colors...'
|
value: 'Bright colors with modern patterns, change the style to a realistic furniture design. '
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: 'Make the...',
|
label: 'Make the...',
|
||||||
value: 'Make the...'
|
value: 'Make the structure more refined and balanced, change the style to a realistic furniture style. '
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: 'Imagine...',
|
label: 'Imagine...',
|
||||||
value: 'Imagine...'
|
value: 'Imagine this furniture with detailed fabric textures, change the style to a realistic design. '
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: 'Wood Materials with...',
|
label: 'Wood Materials with...',
|
||||||
value: 'Wood Materials with...'
|
value: 'Wood materials with natural oak texture and soft fabric, change the style to a realistic furniture design.'
|
||||||
}
|
}
|
||||||
])
|
])
|
||||||
const modeList = ref([
|
const modeList = ref([
|
||||||
|
|||||||
@@ -161,6 +161,7 @@
|
|||||||
item.scale.x = -item.scale.x
|
item.scale.x = -item.scale.x
|
||||||
})
|
})
|
||||||
stateManager.recordState()
|
stateManager.recordState()
|
||||||
|
stateManager.exportFlow(stateManager.saveCanvasTimeInterval)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -174,6 +175,7 @@
|
|||||||
item.scale.y = -item.scale.y
|
item.scale.y = -item.scale.y
|
||||||
})
|
})
|
||||||
stateManager.recordState()
|
stateManager.recordState()
|
||||||
|
stateManager.exportFlow(stateManager.saveCanvasTimeInterval)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
])
|
])
|
||||||
|
|||||||
@@ -47,7 +47,7 @@
|
|||||||
</template>
|
</template>
|
||||||
</VueFlow>
|
</VueFlow>
|
||||||
</div>
|
</div>
|
||||||
<header-tools @export="exportFlow" @import="importFlow" />
|
<header-tools @export="exportFlow" @import="importFlow" :downloadData="downloadData" />
|
||||||
<zoom
|
<zoom
|
||||||
:zoom="stateManager.zoom.value"
|
:zoom="stateManager.zoom.value"
|
||||||
:step="0.1"
|
:step="0.1"
|
||||||
@@ -107,9 +107,8 @@
|
|||||||
|
|
||||||
const vueFlow = ref<any>()
|
const vueFlow = ref<any>()
|
||||||
const nodeTypes = ref([NODE_TYPE.INPUT, NODE_TYPE.SECONDARY, NODE_TYPE.OUTPUT, NODE_TYPE.ALONE])
|
const nodeTypes = ref([NODE_TYPE.INPUT, NODE_TYPE.SECONDARY, NODE_TYPE.OUTPUT, NODE_TYPE.ALONE])
|
||||||
|
|
||||||
// 状态管理器
|
// 状态管理器
|
||||||
const stateManager = new StateManager({ vueFlow })
|
const stateManager = new StateManager({ vueFlow,sketchId:props.config.imgId })
|
||||||
provide('stateManager', stateManager)
|
provide('stateManager', stateManager)
|
||||||
|
|
||||||
// 事件管理器
|
// 事件管理器
|
||||||
@@ -191,29 +190,34 @@
|
|||||||
}
|
}
|
||||||
// 导出流程
|
// 导出流程
|
||||||
const getFlowJson = () => {
|
const getFlowJson = () => {
|
||||||
if(!stateManager.isSave.value)return ''
|
|
||||||
return JSON.stringify(stateManager.nodes.value)
|
return JSON.stringify(stateManager.nodes.value)
|
||||||
}
|
}
|
||||||
const exportFlow = () => {
|
const downloadData = ref<any>({
|
||||||
|
amount: 0,
|
||||||
|
progress: 0,
|
||||||
|
status: 'success',//success
|
||||||
|
})
|
||||||
|
const exportFlow = async () => {
|
||||||
// console.log(vueFlow.value)
|
// console.log(vueFlow.value)
|
||||||
// console.log(vueFlow.value.toImage)
|
// console.log(vueFlow.value.toImage)
|
||||||
let arr = stateManager.nodes.value.filter((v) => v.data.type === NODE_COMPONENT.RESULT_IMAGE)
|
let arr = stateManager.nodes.value.filter((v) => v.data.type === NODE_COMPONENT.RESULT_IMAGE)
|
||||||
let imgList = []
|
let imgList = []
|
||||||
arr.forEach((v) => {
|
arr.forEach((v,i) => {
|
||||||
v.data.data.imageProcessTasks.forEach((item,index) => {
|
v.data.data.imageProcessTasks.forEach((item,index) => {
|
||||||
let url = item.url
|
let url = item.url
|
||||||
let name = url?.split(".").pop().split("?").shift();
|
let name = url?.split(".").pop().split("?").shift();
|
||||||
imgList.push({url:url,name:`${v.data.type}${index == 0?'':index}.${name}`})
|
imgList.push({url:url,name:`${v.data.type}${i}-${index == 0?'':index}.${name}`})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
downImgListToZip(imgList)
|
downloadData.value.amount = imgList.length
|
||||||
console.log(imgList)
|
downloadData.value.status = 'loading'
|
||||||
|
await downImgListToZip(imgList,(progress)=>{
|
||||||
|
downloadData.value.progress = progress
|
||||||
|
if(progress == downloadData.value.amount){
|
||||||
|
downloadData.value.status = 'success'
|
||||||
|
}
|
||||||
|
})
|
||||||
return
|
return
|
||||||
// flowManager.exportFlow()
|
|
||||||
const str = getFlowJson()
|
|
||||||
stateManager.isSave.value = false
|
|
||||||
emit('exportFlow', str)
|
|
||||||
// localStorage.setItem('flow_json', str)
|
|
||||||
}
|
}
|
||||||
// 导入流程
|
// 导入流程
|
||||||
const importFlow = async (json) => {
|
const importFlow = async (json) => {
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
<template>
|
<template>
|
||||||
<fullscreen-dialog v-model="dialogVisible" @close="close" hide-destroy>
|
<fullscreen-dialog v-model="dialogVisible" @close="close" hide-destroy>
|
||||||
<flow-canvas ref="flowCanvasRef" :config="config" @exportFlow="exportFlow" />
|
<flow-canvas ref="flowCanvasRef" :config="config" />
|
||||||
</fullscreen-dialog>
|
</fullscreen-dialog>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@@ -31,22 +31,7 @@
|
|||||||
config.value.json = json
|
config.value.json = json
|
||||||
dialogVisible.value = true
|
dialogVisible.value = true
|
||||||
}
|
}
|
||||||
const exportFlow = async (str) => {
|
|
||||||
if(!config.value.imgId || !str)return
|
|
||||||
await new Promise((resolve) => {
|
|
||||||
putSketchFlowCanvas({
|
|
||||||
id: config.value.imgId,
|
|
||||||
canvasData: str },true).then(() => {
|
|
||||||
resolve(true)
|
|
||||||
}).catch(() => {
|
|
||||||
resolve(true)
|
|
||||||
})
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
const close = async () => {
|
const close = async () => {
|
||||||
const str = flowCanvasRef.value?.getFlowJson()
|
|
||||||
await exportFlow(str)
|
|
||||||
dialogVisible.value = false
|
dialogVisible.value = false
|
||||||
}
|
}
|
||||||
const handleBeforeUnload = (event) => {
|
const handleBeforeUnload = (event) => {
|
||||||
@@ -67,7 +52,6 @@
|
|||||||
defineExpose({
|
defineExpose({
|
||||||
open,
|
open,
|
||||||
close,
|
close,
|
||||||
exportFlow
|
|
||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
<style lang="less" scoped>
|
<style lang="less" scoped>
|
||||||
|
|||||||
@@ -38,6 +38,7 @@ export class EventManager {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
this.stateManager.recordState()
|
this.stateManager.recordState()
|
||||||
|
this.stateManager.exportFlow(this.stateManager.saveCanvasTimeInterval)
|
||||||
}
|
}
|
||||||
/** 处理点击 */
|
/** 处理点击 */
|
||||||
handleClick(event: any) {
|
handleClick(event: any) {
|
||||||
|
|||||||
@@ -2,6 +2,8 @@ import { ref, computed } from "vue";
|
|||||||
import { NODE_TYPE, NODE_DATATYPE } 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'
|
||||||
|
import { putSketchFlowCanvas } from '@/api/flow-canvas'
|
||||||
|
|
||||||
const t = i18n.global.t
|
const t = i18n.global.t
|
||||||
|
|
||||||
export interface NodesItem {
|
export interface NodesItem {
|
||||||
@@ -37,8 +39,12 @@ export class StateManager {
|
|||||||
toolManager: any
|
toolManager: any
|
||||||
generateManager: any
|
generateManager: any
|
||||||
|
|
||||||
// 是否有数据没保存
|
// 保存画布数据定时器
|
||||||
isSave: any
|
saveCanvasTime: any
|
||||||
|
// 保存画布数据定时器时间间隔
|
||||||
|
saveCanvasTimeInterval: any
|
||||||
|
// 打开画布线稿id
|
||||||
|
sketchId: any
|
||||||
// 设置管理器
|
// 设置管理器
|
||||||
setManager(options) {
|
setManager(options) {
|
||||||
options.eventManager && (this.eventManager = options.eventManager)
|
options.eventManager && (this.eventManager = options.eventManager)
|
||||||
@@ -57,7 +63,10 @@ export class StateManager {
|
|||||||
this.mxHistory = ref(50)
|
this.mxHistory = ref(50)
|
||||||
this.historyList = ref([])
|
this.historyList = ref([])
|
||||||
this.historyIndex = ref(0)
|
this.historyIndex = ref(0)
|
||||||
this.isSave = ref(false)
|
|
||||||
|
this.sketchId = options.sketchId
|
||||||
|
this.saveCanvasTimeInterval = 6000
|
||||||
|
this.saveCanvasTime = null
|
||||||
|
|
||||||
this.activeNodeID = ref("")
|
this.activeNodeID = ref("")
|
||||||
this.nodes = ref<NodesItem[]>([]);
|
this.nodes = ref<NodesItem[]>([]);
|
||||||
@@ -100,8 +109,6 @@ export class StateManager {
|
|||||||
})
|
})
|
||||||
return arr
|
return arr
|
||||||
})
|
})
|
||||||
window.nodes = this.nodes
|
|
||||||
window.aaa = this
|
|
||||||
|
|
||||||
}
|
}
|
||||||
/** 设置激活节点 */
|
/** 设置激活节点 */
|
||||||
@@ -110,6 +117,7 @@ export class StateManager {
|
|||||||
addNode(node: NodesItem) {
|
addNode(node: NodesItem) {
|
||||||
this.nodes.value.push(node);
|
this.nodes.value.push(node);
|
||||||
this.recordState()
|
this.recordState()
|
||||||
|
this.exportFlow()
|
||||||
}
|
}
|
||||||
/** 删除节点 */
|
/** 删除节点 */
|
||||||
async deleteNode(id: string, { isElMessageBox } = { isElMessageBox: false }) {
|
async deleteNode(id: string, { isElMessageBox } = { isElMessageBox: false }) {
|
||||||
@@ -136,6 +144,7 @@ export class StateManager {
|
|||||||
if (!deletePromise) return console.log('删除操作被取消')
|
if (!deletePromise) return console.log('删除操作被取消')
|
||||||
this.nodes.value = this.nodes.value.filter((node: NodesItem) => node.id !== id)
|
this.nodes.value = this.nodes.value.filter((node: NodesItem) => node.id !== id)
|
||||||
this.recordState()
|
this.recordState()
|
||||||
|
this.exportFlow()
|
||||||
}
|
}
|
||||||
/** 获取节点 */
|
/** 获取节点 */
|
||||||
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) }
|
||||||
@@ -176,8 +185,22 @@ export class StateManager {
|
|||||||
const size = this.historyList.value.length - this.mxHistory.value
|
const size = this.historyList.value.length - this.mxHistory.value
|
||||||
if (size > 0) this.historyList.value.splice(0, size)
|
if (size > 0) this.historyList.value.splice(0, size)
|
||||||
this.historyIndex.value = this.historyList.value.length - 1
|
this.historyIndex.value = this.historyList.value.length - 1
|
||||||
|
}
|
||||||
this.isSave.value = true
|
/** 画布数据存储 */
|
||||||
|
async exportFlow (time:number = 0){
|
||||||
|
if(!this.sketchId)return
|
||||||
|
clearTimeout(this.saveCanvasTime)
|
||||||
|
await new Promise((resolve) => {
|
||||||
|
this.saveCanvasTime = setTimeout(()=>{
|
||||||
|
putSketchFlowCanvas({
|
||||||
|
id: this.sketchId,
|
||||||
|
canvasData: JSON.stringify(this.nodes.value) }).then(() => {
|
||||||
|
resolve(true)
|
||||||
|
}).catch(() => {
|
||||||
|
resolve(true)
|
||||||
|
})
|
||||||
|
},time)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
/** 撤回状态 */
|
/** 撤回状态 */
|
||||||
undoState() {
|
undoState() {
|
||||||
@@ -186,6 +209,7 @@ export class StateManager {
|
|||||||
if (!state) return
|
if (!state) return
|
||||||
this.historyIndex.value = index
|
this.historyIndex.value = index
|
||||||
this.nodes.value = JSON.parse(state.nodes)
|
this.nodes.value = JSON.parse(state.nodes)
|
||||||
|
this.exportFlow(this.saveCanvasTimeInterval)
|
||||||
}
|
}
|
||||||
/** 重做状态 */
|
/** 重做状态 */
|
||||||
redoState() {
|
redoState() {
|
||||||
@@ -194,6 +218,7 @@ export class StateManager {
|
|||||||
if (!state) return
|
if (!state) return
|
||||||
this.historyIndex.value = index
|
this.historyIndex.value = index
|
||||||
this.nodes.value = JSON.parse(state.nodes)
|
this.nodes.value = JSON.parse(state.nodes)
|
||||||
|
this.exportFlow(this.saveCanvasTimeInterval)
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 显示指定子节点和父节点连接线,隐藏父节点和其他子节点链接线, */
|
/** 显示指定子节点和父节点连接线,隐藏父节点和其他子节点链接线, */
|
||||||
@@ -211,7 +236,7 @@ export class StateManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
dispose() {
|
dispose() {
|
||||||
this.isSave.value = false
|
clearTimeout(this.saveCanvasTime)
|
||||||
this.historyList.value = []
|
this.historyList.value = []
|
||||||
this.historyIndex.value = 0
|
this.historyIndex.value = 0
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,10 +19,11 @@ export const downloadImage = (url: string, name: string) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** 批量下载图片 */
|
/** 批量下载图片 */
|
||||||
export const downImgListToZip = async (imagesParams) => {
|
export const downImgListToZip = async (imagesParams,callback) => {
|
||||||
const zip = new JSZip()
|
const zip = new JSZip()
|
||||||
const promises = []
|
const promises = []
|
||||||
// 遍历下载每个图片
|
// 遍历下载每个图片
|
||||||
|
let progress = 0
|
||||||
imagesParams.forEach((img, index) => {
|
imagesParams.forEach((img, index) => {
|
||||||
const promise = new Promise((resolve, reject) => {
|
const promise = new Promise((resolve, reject) => {
|
||||||
const xhr = new XMLHttpRequest()
|
const xhr = new XMLHttpRequest()
|
||||||
@@ -32,18 +33,17 @@ export const downImgListToZip = async (imagesParams) => {
|
|||||||
if (xhr.status === 200) {
|
if (xhr.status === 200) {
|
||||||
const fileName = img.name
|
const fileName = img.name
|
||||||
zip.file(fileName, xhr.response)
|
zip.file(fileName, xhr.response)
|
||||||
|
progress++
|
||||||
|
callback(progress)
|
||||||
resolve('')
|
resolve('')
|
||||||
} else {
|
} else {
|
||||||
reject(new Error(`下载失败: ${img.url}`))
|
reject(new Error(`下载失败: ${img.url}`))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
xhr.onerror = () => reject(new Error(`网络错误: ${img.url}`))
|
xhr.onerror = () => reject(new Error(`网络错误: ${img.url}`))
|
||||||
xhr.send()
|
xhr.send()
|
||||||
})
|
})
|
||||||
|
|
||||||
promises.push(promise)
|
promises.push(promise)
|
||||||
console.log(promises,zip)
|
|
||||||
})
|
})
|
||||||
|
|
||||||
// 等待所有图片下载完成
|
// 等待所有图片下载完成
|
||||||
@@ -56,7 +56,7 @@ export const downImgListToZip = async (imagesParams) => {
|
|||||||
link.href = URL.createObjectURL(content)
|
link.href = URL.createObjectURL(content)
|
||||||
link.download = 'DesignFiles'
|
link.download = 'DesignFiles'
|
||||||
link.click()
|
link.click()
|
||||||
URL.revokeObjectURL(link.href)
|
// URL.revokeObjectURL(link.href)
|
||||||
})
|
})
|
||||||
.catch((error) => console.error('下载失败:', error))
|
.catch((error) => console.error('下载失败:', error))
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user