Merge branch 'dev_vite' of http://18.167.251.121:10003/aidlab/aida_front into dev_vite

This commit is contained in:
李志鹏
2026-01-13 14:41:53 +08:00
34 changed files with 2059 additions and 586 deletions

1
.gitignore vendored
View File

@@ -24,3 +24,4 @@ dist.rar
*.sw? *.sw?
.eslintrc-auto-import.json .eslintrc-auto-import.json
components.d.ts components.d.ts
.cursor

260
package-lock.json generated
View File

@@ -34,6 +34,7 @@
"vue-draggable-plus": "^0.6.0", "vue-draggable-plus": "^0.6.0",
"vue-i18n": "^9.6.1", "vue-i18n": "^9.6.1",
"vue-router": "^4.0.3", "vue-router": "^4.0.3",
"vue3-moveable": "^0.28.0",
"vuedraggable": "^4.1.0", "vuedraggable": "^4.1.0",
"vuex": "^4.0.0", "vuex": "^4.0.0",
"x-sender": "^1.1.6" "x-sender": "^1.1.6"
@@ -232,6 +233,15 @@
"node": ">=6.9.0" "node": ">=6.9.0"
} }
}, },
"node_modules/@cfcs/core": {
"version": "0.0.6",
"resolved": "https://registry.npmmirror.com/@cfcs/core/-/core-0.0.6.tgz",
"integrity": "sha512-FxfJMwoLB8MEMConeXUCqtMGqxdtePQxRBOiGip9ULcYYam3WfCgoY6xdnMaSkYvRvmosp5iuG+TiPofm65+Pw==",
"license": "MIT",
"dependencies": {
"@egjs/component": "^3.0.2"
}
},
"node_modules/@ctrl/tinycolor": { "node_modules/@ctrl/tinycolor": {
"version": "3.6.1", "version": "3.6.1",
"resolved": "https://registry.npmmirror.com/@ctrl/tinycolor/-/tinycolor-3.6.1.tgz", "resolved": "https://registry.npmmirror.com/@ctrl/tinycolor/-/tinycolor-3.6.1.tgz",
@@ -240,6 +250,39 @@
"node": ">=10" "node": ">=10"
} }
}, },
"node_modules/@daybrush/utils": {
"version": "1.13.0",
"resolved": "https://registry.npmmirror.com/@daybrush/utils/-/utils-1.13.0.tgz",
"integrity": "sha512-ALK12C6SQNNHw1enXK+UO8bdyQ+jaWNQ1Af7Z3FNxeAwjYhQT7do+TRE4RASAJ3ObaS2+TJ7TXR3oz2Gzbw0PQ==",
"license": "MIT"
},
"node_modules/@egjs/agent": {
"version": "2.4.4",
"resolved": "https://registry.npmmirror.com/@egjs/agent/-/agent-2.4.4.tgz",
"integrity": "sha512-cvAPSlUILhBBOakn2krdPnOGv5hAZq92f1YHxYcfu0p7uarix2C6Ia3AVizpS1SGRZGiEkIS5E+IVTLg1I2Iog==",
"license": "MIT"
},
"node_modules/@egjs/children-differ": {
"version": "1.0.1",
"resolved": "https://registry.npmmirror.com/@egjs/children-differ/-/children-differ-1.0.1.tgz",
"integrity": "sha512-DRvyqMf+CPCOzAopQKHtW+X8iN6Hy6SFol+/7zCUiE5y4P/OB8JP8FtU4NxtZwtafvSL4faD5KoQYPj3JHzPFQ==",
"license": "MIT",
"dependencies": {
"@egjs/list-differ": "^1.0.0"
}
},
"node_modules/@egjs/component": {
"version": "3.0.5",
"resolved": "https://registry.npmmirror.com/@egjs/component/-/component-3.0.5.tgz",
"integrity": "sha512-cLcGizTrrUNA2EYE3MBmEDt2tQv1joVP1Q3oDisZ5nw0MZDx2kcgEXM+/kZpfa/PAkFvYVhRUZwytIQWoN3V/w==",
"license": "MIT"
},
"node_modules/@egjs/list-differ": {
"version": "1.0.1",
"resolved": "https://registry.npmmirror.com/@egjs/list-differ/-/list-differ-1.0.1.tgz",
"integrity": "sha512-OTFTDQcWS+1ZREOdCWuk5hCBgYO4OsD30lXcOCyVOAjXMhgL5rBRDnt/otb6Nz8CzU0L/igdcaQBDLWc4t9gvg==",
"license": "MIT"
},
"node_modules/@element-plus/icons-vue": { "node_modules/@element-plus/icons-vue": {
"version": "2.3.1", "version": "2.3.1",
"resolved": "https://registry.npmmirror.com/@element-plus/icons-vue/-/icons-vue-2.3.1.tgz", "resolved": "https://registry.npmmirror.com/@element-plus/icons-vue/-/icons-vue-2.3.1.tgz",
@@ -1224,6 +1267,34 @@
"win32" "win32"
] ]
}, },
"node_modules/@scena/dragscroll": {
"version": "1.4.0",
"resolved": "https://registry.npmmirror.com/@scena/dragscroll/-/dragscroll-1.4.0.tgz",
"integrity": "sha512-3O8daaZD9VXA9CP3dra6xcgt/qrm0mg0xJCwiX6druCteQ9FFsXffkF8PrqxY4Z4VJ58fFKEa0RlKqbsi/XnRA==",
"license": "MIT",
"dependencies": {
"@daybrush/utils": "^1.6.0",
"@scena/event-emitter": "^1.0.2"
}
},
"node_modules/@scena/event-emitter": {
"version": "1.0.5",
"resolved": "https://registry.npmmirror.com/@scena/event-emitter/-/event-emitter-1.0.5.tgz",
"integrity": "sha512-AzY4OTb0+7ynefmWFQ6hxDdk0CySAq/D4efljfhtRHCOP7MBF9zUfhKG3TJiroVjASqVgkRJFdenS8ArZo6Olg==",
"license": "MIT",
"dependencies": {
"@daybrush/utils": "^1.1.1"
}
},
"node_modules/@scena/matrix": {
"version": "1.1.1",
"resolved": "https://registry.npmmirror.com/@scena/matrix/-/matrix-1.1.1.tgz",
"integrity": "sha512-JVKBhN0tm2Srl+Yt+Ywqu0oLgLcdemDQlD1OxmN9jaCTwaFPZ7tY8n6dhVgMEaR9qcR7r+kAlMXnSfNyYdE+Vg==",
"license": "MIT",
"dependencies": {
"@daybrush/utils": "^1.4.0"
}
},
"node_modules/@simonwep/pickr": { "node_modules/@simonwep/pickr": {
"version": "1.8.2", "version": "1.8.2",
"resolved": "https://registry.npmmirror.com/@simonwep/pickr/-/pickr-1.8.2.tgz", "resolved": "https://registry.npmmirror.com/@simonwep/pickr/-/pickr-1.8.2.tgz",
@@ -2904,6 +2975,52 @@
"node": ">= 0.10" "node": ">= 0.10"
} }
}, },
"node_modules/croact": {
"version": "1.0.4",
"resolved": "https://registry.npmmirror.com/croact/-/croact-1.0.4.tgz",
"integrity": "sha512-9GhvyzTY/IVUrMQ2iz/mzgZ8+NcjczmIo/t4FkC1CU0CEcau6v6VsEih4jkTa4ZmRgYTF0qXEZLObCzdDFplpw==",
"license": "MIT",
"dependencies": {
"@daybrush/utils": "^1.13.0",
"@egjs/list-differ": "^1.0.0"
}
},
"node_modules/croact-css-styled": {
"version": "1.1.9",
"resolved": "https://registry.npmmirror.com/croact-css-styled/-/croact-css-styled-1.1.9.tgz",
"integrity": "sha512-G7yvRiVJ3Eoj0ov2h2xR4312hpOzATay2dGS9clK8yJQothjH1sBXIyvOeRP5wBKD9mPcKcoUXPCPsl0tQog4w==",
"license": "MIT",
"dependencies": {
"@daybrush/utils": "^1.13.0",
"css-styled": "~1.0.8",
"framework-utils": "^1.1.0"
}
},
"node_modules/croact-moveable": {
"version": "0.9.0",
"resolved": "https://registry.npmmirror.com/croact-moveable/-/croact-moveable-0.9.0.tgz",
"integrity": "sha512-fc3bieV6CdqqZFtzsSLi9KmvUMFW3oakUfhPCls1BxKjOfUfn8rktteGED2341A/Qghy8tI3Hm6SdocIc68IKg==",
"license": "MIT",
"dependencies": {
"@daybrush/utils": "^1.13.0",
"@egjs/agent": "^2.2.1",
"@egjs/children-differ": "^1.0.1",
"@egjs/list-differ": "^1.0.0",
"@scena/dragscroll": "^1.4.0",
"@scena/event-emitter": "^1.0.5",
"@scena/matrix": "^1.1.1",
"croact-css-styled": "^1.1.9",
"css-to-mat": "^1.1.1",
"framework-utils": "^1.1.0",
"gesto": "^1.19.3",
"overlap-area": "^1.1.0",
"react-css-styled": "^1.1.9",
"react-moveable": "~0.56.0"
},
"peerDependencies": {
"croact": "^1.0.4"
}
},
"node_modules/cross-spawn": { "node_modules/cross-spawn": {
"version": "7.0.6", "version": "7.0.6",
"resolved": "https://registry.npmmirror.com/cross-spawn/-/cross-spawn-7.0.6.tgz", "resolved": "https://registry.npmmirror.com/cross-spawn/-/cross-spawn-7.0.6.tgz",
@@ -3014,6 +3131,25 @@
"url": "https://github.com/fb55/entities?sponsor=1" "url": "https://github.com/fb55/entities?sponsor=1"
} }
}, },
"node_modules/css-styled": {
"version": "1.0.8",
"resolved": "https://registry.npmmirror.com/css-styled/-/css-styled-1.0.8.tgz",
"integrity": "sha512-tCpP7kLRI8dI95rCh3Syl7I+v7PP+2JYOzWkl0bUEoSbJM+u8ITbutjlQVf0NC2/g4ULROJPi16sfwDIO8/84g==",
"license": "MIT",
"dependencies": {
"@daybrush/utils": "^1.13.0"
}
},
"node_modules/css-to-mat": {
"version": "1.1.1",
"resolved": "https://registry.npmmirror.com/css-to-mat/-/css-to-mat-1.1.1.tgz",
"integrity": "sha512-kvpxFYZb27jRd2vium35G7q5XZ2WJ9rWjDUMNT36M3Hc41qCrLXFM5iEKMGXcrPsKfXEN+8l/riB4QzwwwiEyQ==",
"license": "MIT",
"dependencies": {
"@daybrush/utils": "^1.13.0",
"@scena/matrix": "^1.0.0"
}
},
"node_modules/css-tree": { "node_modules/css-tree": {
"version": "1.1.3", "version": "1.1.3",
"resolved": "https://registry.npmmirror.com/css-tree/-/css-tree-1.1.3.tgz", "resolved": "https://registry.npmmirror.com/css-tree/-/css-tree-1.1.3.tgz",
@@ -4354,6 +4490,12 @@
"node": ">=0.10.0" "node": ">=0.10.0"
} }
}, },
"node_modules/framework-utils": {
"version": "1.1.0",
"resolved": "https://registry.npmmirror.com/framework-utils/-/framework-utils-1.1.0.tgz",
"integrity": "sha512-KAfqli5PwpFJ8o3psRNs8svpMGyCSAe8nmGcjQ0zZBWN2H6dZDnq+ABp3N3hdUmFeMrLtjOCTXD4yplUJIWceg==",
"license": "MIT"
},
"node_modules/fs-extra": { "node_modules/fs-extra": {
"version": "10.1.0", "version": "10.1.0",
"resolved": "https://registry.npmmirror.com/fs-extra/-/fs-extra-10.1.0.tgz", "resolved": "https://registry.npmmirror.com/fs-extra/-/fs-extra-10.1.0.tgz",
@@ -4485,6 +4627,16 @@
"node": ">=10" "node": ">=10"
} }
}, },
"node_modules/gesto": {
"version": "1.19.4",
"resolved": "https://registry.npmmirror.com/gesto/-/gesto-1.19.4.tgz",
"integrity": "sha512-hfr/0dWwh0Bnbb88s3QVJd1ZRJeOWcgHPPwmiH6NnafDYvhTsxg+SLYu+q/oPNh9JS3V+nlr6fNs8kvPAtcRDQ==",
"license": "MIT",
"dependencies": {
"@daybrush/utils": "^1.13.0",
"@scena/event-emitter": "^1.0.2"
}
},
"node_modules/get-intrinsic": { "node_modules/get-intrinsic": {
"version": "1.3.0", "version": "1.3.0",
"resolved": "https://registry.npmmirror.com/get-intrinsic/-/get-intrinsic-1.3.0.tgz", "resolved": "https://registry.npmmirror.com/get-intrinsic/-/get-intrinsic-1.3.0.tgz",
@@ -5695,6 +5847,24 @@
"setimmediate": "^1.0.5" "setimmediate": "^1.0.5"
} }
}, },
"node_modules/keycode": {
"version": "2.2.1",
"resolved": "https://registry.npmmirror.com/keycode/-/keycode-2.2.1.tgz",
"integrity": "sha512-Rdgz9Hl9Iv4QKi8b0OlCRQEzp4AgVxyCtz5S/+VIHezDmrDhkp2N2TqBWOLz0/gbeREXOOiI9/4b8BY9uw2vFg==",
"license": "MIT"
},
"node_modules/keycon": {
"version": "1.4.0",
"resolved": "https://registry.npmmirror.com/keycon/-/keycon-1.4.0.tgz",
"integrity": "sha512-p1NAIxiRMH3jYfTeXRs2uWbVJ1WpEjpi8ktzUyBJsX7/wn2qu2VRXktneBLNtKNxJmlUYxRi9gOJt1DuthXR7A==",
"license": "MIT",
"dependencies": {
"@cfcs/core": "^0.0.6",
"@daybrush/utils": "^1.7.1",
"@scena/event-emitter": "^1.0.2",
"keycode": "^2.2.0"
}
},
"node_modules/keyv": { "node_modules/keyv": {
"version": "4.5.4", "version": "4.5.4",
"resolved": "https://registry.npmmirror.com/keyv/-/keyv-4.5.4.tgz", "resolved": "https://registry.npmmirror.com/keyv/-/keyv-4.5.4.tgz",
@@ -6212,6 +6382,19 @@
"pathe": "^2.0.1" "pathe": "^2.0.1"
} }
}, },
"node_modules/moveable": {
"version": "0.53.0",
"resolved": "https://registry.npmmirror.com/moveable/-/moveable-0.53.0.tgz",
"integrity": "sha512-71jS9zIoQzMhnNvduhg4tUEdm23+fO/40FN7muVMbZvVwbTku2MIxxLhnU4qFvxI4oVxn75l79SbtgjuA+s7Pw==",
"license": "MIT",
"dependencies": {
"@daybrush/utils": "^1.13.0",
"@scena/event-emitter": "^1.0.5",
"croact": "^1.0.4",
"croact-moveable": "~0.9.0",
"react-moveable": "~0.56.0"
}
},
"node_modules/ms": { "node_modules/ms": {
"version": "2.1.3", "version": "2.1.3",
"resolved": "https://registry.npmmirror.com/ms/-/ms-2.1.3.tgz", "resolved": "https://registry.npmmirror.com/ms/-/ms-2.1.3.tgz",
@@ -6650,6 +6833,15 @@
"node": ">= 0.8.0" "node": ">= 0.8.0"
} }
}, },
"node_modules/overlap-area": {
"version": "1.1.0",
"resolved": "https://registry.npmmirror.com/overlap-area/-/overlap-area-1.1.0.tgz",
"integrity": "sha512-3dlJgJCaVeXH0/eZjYVJvQiLVVrPO4U1ZGqlATtx6QGO3b5eNM6+JgUKa7oStBTdYuGTk7gVoABCW6Tp+dhRdw==",
"license": "MIT",
"dependencies": {
"@daybrush/utils": "^1.7.1"
}
},
"node_modules/own-keys": { "node_modules/own-keys": {
"version": "1.0.1", "version": "1.0.1",
"resolved": "https://registry.npmmirror.com/own-keys/-/own-keys-1.0.1.tgz", "resolved": "https://registry.npmmirror.com/own-keys/-/own-keys-1.0.1.tgz",
@@ -7037,6 +7229,46 @@
"safe-buffer": "^5.1.0" "safe-buffer": "^5.1.0"
} }
}, },
"node_modules/react-css-styled": {
"version": "1.1.9",
"resolved": "https://registry.npmmirror.com/react-css-styled/-/react-css-styled-1.1.9.tgz",
"integrity": "sha512-M7fJZ3IWFaIHcZEkoFOnkjdiUFmwd8d+gTh2bpqMOcnxy/0Gsykw4dsL4QBiKsxcGow6tETUa4NAUcmJF+/nfw==",
"license": "MIT",
"dependencies": {
"css-styled": "~1.0.8",
"framework-utils": "^1.1.0"
}
},
"node_modules/react-moveable": {
"version": "0.56.0",
"resolved": "https://registry.npmmirror.com/react-moveable/-/react-moveable-0.56.0.tgz",
"integrity": "sha512-FmJNmIOsOA36mdxbrc/huiE4wuXSRlmon/o+/OrfNhSiYYYL0AV5oObtPluEhb2Yr/7EfYWBHTxF5aWAvjg1SA==",
"license": "MIT",
"dependencies": {
"@daybrush/utils": "^1.13.0",
"@egjs/agent": "^2.2.1",
"@egjs/children-differ": "^1.0.1",
"@egjs/list-differ": "^1.0.0",
"@scena/dragscroll": "^1.4.0",
"@scena/event-emitter": "^1.0.5",
"@scena/matrix": "^1.1.1",
"css-to-mat": "^1.1.1",
"framework-utils": "^1.1.0",
"gesto": "^1.19.3",
"overlap-area": "^1.1.0",
"react-css-styled": "^1.1.9",
"react-selecto": "^1.25.0"
}
},
"node_modules/react-selecto": {
"version": "1.26.3",
"resolved": "https://registry.npmmirror.com/react-selecto/-/react-selecto-1.26.3.tgz",
"integrity": "sha512-Ubik7kWSnZyQEBNro+1k38hZaI1tJarE+5aD/qsqCOA1uUBSjgKVBy3EWRzGIbdmVex7DcxznFZLec/6KZNvwQ==",
"license": "MIT",
"dependencies": {
"selecto": "~1.26.3"
}
},
"node_modules/readable-stream": { "node_modules/readable-stream": {
"version": "2.3.8", "version": "2.3.8",
"resolved": "https://registry.npmmirror.com/readable-stream/-/readable-stream-2.3.8.tgz", "resolved": "https://registry.npmmirror.com/readable-stream/-/readable-stream-2.3.8.tgz",
@@ -7507,6 +7739,24 @@
"integrity": "sha512-6FtHJEvt+pVMIB9IBY+IcCJ6Z5f1iQnytgyfKMhDKgmzYG+TeH/wx1y3l27rshSbLiSanrR9ffZDrEsmjlQF2g==", "integrity": "sha512-6FtHJEvt+pVMIB9IBY+IcCJ6Z5f1iQnytgyfKMhDKgmzYG+TeH/wx1y3l27rshSbLiSanrR9ffZDrEsmjlQF2g==",
"dev": true "dev": true
}, },
"node_modules/selecto": {
"version": "1.26.3",
"resolved": "https://registry.npmmirror.com/selecto/-/selecto-1.26.3.tgz",
"integrity": "sha512-gZHgqMy5uyB6/2YDjv3Qqaf7bd2hTDOpPdxXlrez4R3/L0GiEWDCFaUfrflomgqdb3SxHF2IXY0Jw0EamZi7cw==",
"license": "MIT",
"dependencies": {
"@daybrush/utils": "^1.13.0",
"@egjs/children-differ": "^1.0.1",
"@scena/dragscroll": "^1.4.0",
"@scena/event-emitter": "^1.0.5",
"css-styled": "^1.0.8",
"css-to-mat": "^1.1.1",
"framework-utils": "^1.1.0",
"gesto": "^1.19.4",
"keycon": "^1.2.0",
"overlap-area": "^1.1.0"
}
},
"node_modules/semver": { "node_modules/semver": {
"version": "7.7.2", "version": "7.7.2",
"resolved": "https://registry.npmmirror.com/semver/-/semver-7.7.2.tgz", "resolved": "https://registry.npmmirror.com/semver/-/semver-7.7.2.tgz",
@@ -9765,6 +10015,16 @@
"vue": "^3.0.0" "vue": "^3.0.0"
} }
}, },
"node_modules/vue3-moveable": {
"version": "0.28.0",
"resolved": "https://registry.npmmirror.com/vue3-moveable/-/vue3-moveable-0.28.0.tgz",
"integrity": "sha512-vplQO0XkxVEtXMDh2/lZE+c5kMycGXAfYFMvbwFKi8UVYzVk8MTgVHr4fxO9Z+4i4Rb+U/IEIgkhHRMAbx8FJg==",
"license": "MIT",
"dependencies": {
"framework-utils": "^1.1.0",
"moveable": "~0.53.0"
}
},
"node_modules/vuedraggable": { "node_modules/vuedraggable": {
"version": "4.1.0", "version": "4.1.0",
"resolved": "https://registry.npmmirror.com/vuedraggable/-/vuedraggable-4.1.0.tgz", "resolved": "https://registry.npmmirror.com/vuedraggable/-/vuedraggable-4.1.0.tgz",

View File

@@ -40,6 +40,7 @@
"vue-draggable-plus": "^0.6.0", "vue-draggable-plus": "^0.6.0",
"vue-i18n": "^9.6.1", "vue-i18n": "^9.6.1",
"vue-router": "^4.0.3", "vue-router": "^4.0.3",
"vue3-moveable": "^0.28.0",
"vuedraggable": "^4.1.0", "vuedraggable": "^4.1.0",
"vuex": "^4.0.0", "vuex": "^4.0.0",
"x-sender": "^1.1.6" "x-sender": "^1.1.6"

Binary file not shown.

After

Width:  |  Height:  |  Size: 198 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.3 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 80 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 61 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 811 B

View File

@@ -50,7 +50,7 @@
</div> </div>
</div> </div>
<div class="item detailLeft" :class="{isEditPattern:isEditPattern.value}"> <div class="item detailLeft" :class="{isEditPattern:isEditPattern.value}">
<detailLeft v-if="currentDetailType" ref="detailLeft"></detailLeft> <detailLeft v-if="currentDetailType" ref="detailLeft" :detailLeftColorKey="detailLeftColorKey"></detailLeft>
<!-- <detailLeft v-if="selectDetail && selectDetail.id && currentDetailType"></detailLeft> --> <!-- <detailLeft v-if="selectDetail && selectDetail.id && currentDetailType"></detailLeft> -->
<div class="btn" style="margin: 0;" v-show="currentDetailType == 'color'"> <div class="btn" style="margin: 0;" v-show="currentDetailType == 'color'">
<div class="gallery_btn" @click="previwe">{{$t('DesignPrintOperation.Preview')}}</div> <div class="gallery_btn" @click="previwe">{{$t('DesignPrintOperation.Preview')}}</div>
@@ -61,7 +61,6 @@
<model <model
ref="model" ref="model"
:key="positionKey" :key="positionKey"
@addDetail="addDetail"
@canvasReload="canvasReload" @canvasReload="canvasReload"
@detailEdit="detailEdit" @detailEdit="detailEdit"
@addSketch="()=>isEditPattern.value = ''" @addSketch="()=>isEditPattern.value = ''"
@@ -103,15 +102,14 @@
<div class="gallery_btn" @click="previwe">{{$t('DesignPrintOperation.Preview')}}</div> <div class="gallery_btn" @click="previwe">{{$t('DesignPrintOperation.Preview')}}</div>
</div> </div>
</div> </div>
<div class="contentRight" v-if="selectDetail && selectDetail.id && currentDetailType && isEditPattern.value"> <div class="contentRight canvas" v-if="selectDetail && selectDetail.id && currentDetailType" :class="{'active': isEditPattern.value}">
<canvasBox ref="canvasBox" :key="canvasKey || isEditPattern.value" :isEditPattern="isEditPattern.value"></canvasBox> <canvasBox ref="canvasBox" :key="canvasKey" @setSloganData="setSloganData" :isEditPattern="isEditPattern.value" :updateOtherLayers="updateOtherLayers"></canvasBox>
</div> </div>
<!-- 画布 --> <!-- 画布 -->
<!-- <div class="content" v-else-if="selectDetail && selectDetail.id"> <!-- <div class="content" v-else-if="selectDetail && selectDetail.id">
</div> --> </div> -->
</div> </div>
</div> </div>
<addDetails ref="addDetails" @setSloganData="setSloganData"></addDetails>
</a-modal> </a-modal>
<div class="mark_loading" v-show="loadingShow"> <div class="mark_loading" v-show="loadingShow">
<a-spin size="large" /> <a-spin size="large" />
@@ -130,14 +128,13 @@ import canvasBox from './canvas/index.vue'
import { ExclamationCircleOutlined } from '@ant-design/icons-vue'; import { ExclamationCircleOutlined } from '@ant-design/icons-vue';
import { Https } from "@/tool/https"; import { Https } from "@/tool/https";
import { Modal,message } from 'ant-design-vue'; import { Modal,message } from 'ant-design-vue';
import {getUploadUrl,isMoible,setGradual} from '@/tool/util' import {getUploadUrl,segmentImage,setGradual,rgbToHsv,rgbaToHex} from '@/tool/util'
import { useStore } from "vuex"; import { useStore } from "vuex";
import { openGuide,driverObj__ } from "@/tool/guide"; import { openGuide,driverObj__ } from "@/tool/guide";
import { useI18n } from 'vue-i18n' import { useI18n } from 'vue-i18n'
import addDetails from '@/component/Detail/addDetails.vue'
export default defineComponent({ export default defineComponent({
components:{ components:{
detailLeft,model,detailRight,canvasBox,addDetails detailLeft,model,detailRight,canvasBox
}, },
emits:['destroy'], emits:['destroy'],
setup(props,{emit}) { setup(props,{emit}) {
@@ -148,7 +145,6 @@ export default defineComponent({
canvasBox, canvasBox,
detailRight, detailRight,
detailLeft:null as any, detailLeft:null as any,
addDetails:null as any,
}) })
const userDetail = computed(()=>{ const userDetail = computed(()=>{
return store.state.UserHabit.userDetail return store.state.UserHabit.userDetail
@@ -157,10 +153,12 @@ export default defineComponent({
selectObject:computed(()=>store.state.Workspace.probjects) as any,//选择的项目 selectObject:computed(()=>store.state.Workspace.probjects) as any,//选择的项目
designDetail:computed(()=>store.state.DesignDetail.designDetail), designDetail:computed(()=>store.state.DesignDetail.designDetail),
currentDetailType:computed(()=>store.state.DesignDetail.currentDetailType), currentDetailType:computed(()=>store.state.DesignDetail.currentDetailType),
frontBack:computed(()=>store.state.DesignDetail.frontBack),
selectDetail:computed(()=>store.state.DesignDetail.selectDetail), selectDetail:computed(()=>store.state.DesignDetail.selectDetail),
designDetailShow:false, designDetailShow:false,
loadingShow:false, loadingShow:false,
oppositeRevocationShow:-1, oppositeRevocationShow:-1,
imgDomIndex:-1,
revocationShow:-1, revocationShow:-1,
isEditPattern:{ isEditPattern:{
value:'' as any, value:'' as any,
@@ -174,8 +172,13 @@ export default defineComponent({
}, },
positionKey:0, positionKey:0,
isUndividedLayerWithSinglePrint:false, isUndividedLayerWithSinglePrint:false,
detailLeftColorKey:0,
}) })
watch(()=>detailData.selectDetail,(newValue,oldValue)=>{
detailData.imgDomIndex = detailData.frontBack.front.findIndex((item:any)=>item.id == newValue.id)
if(newValue?.undividedLayer)newValue.undividedLayer_ = newValue.undividedLayer
// privewDetail(oldValue)
},{immediate: true})
provide('getCanvasIfEdit',detailData.getCanvasIfEdit) provide('getCanvasIfEdit',detailData.getCanvasIfEdit)
provide('singleOveral',detailData.singleOveral) provide('singleOveral',detailData.singleOveral)
@@ -320,13 +323,15 @@ export default defineComponent({
const setCurrentDetail = (str:string)=>{ const setCurrentDetail = (str:string)=>{
store.commit('DesignDetail/setCurrentDetailType',str) store.commit('DesignDetail/setCurrentDetailType',str)
} }
const setClothes = async (list:any)=>{ const setClothes = async (list:any,str:string)=>{
let clothesList:any = [] let clothesList:any = []
await nextTick() await nextTick()
if(detailData.isEditPattern.value == 'editSketch')await detailDom.canvasBox.submitBase64Data().then((rv)=>{
detailData.selectDetail.sketchString = rv
})
for(let i = 0;i<list.length;i++){ for(let i = 0;i<list.length;i++){
detailData.selectDetail detailData.selectDetail
let {scale,offset,priority,maskUrl,maskMinioUrl} = await (detailDom.model as any).getSubmitData(list[i],detailData.isUndividedLayerWithSinglePrint) let {scale,offset,priority,transpose,rotate,maskUrl,maskMinioUrl} = await (detailDom.model as any).getSubmitData(list[i],detailData.isUndividedLayerWithSinglePrint)
if(detailDom.canvasBox?.privewDetail)await (detailDom.canvasBox as any).privewDetail()
if(detailDom.detailRight?.privewDetail)await (detailDom.detailRight as any).privewDetail() if(detailDom.detailRight?.privewDetail)await (detailDom.detailRight as any).privewDetail()
let gradient = null let gradient = null
let newData = list[i]?.newDetail?.[detailData.currentDetailType] let newData = list[i]?.newDetail?.[detailData.currentDetailType]
@@ -362,7 +367,9 @@ export default defineComponent({
// 406.90964 // 406.90964
// ], // ],
offset, offset,
partialDesign:list[i].partialDesign || {}, transpose,
rotate,
partialDesign:(detailData.currentDetailType == 'sketch' || detailData.isEditPattern.value == 'editSketch')?{}:list[i].partialDesign,
// partialDesign:detailData.isEditPattern.value?list[i].partialDesign:{}, // partialDesign:detailData.isEditPattern.value?list[i].partialDesign:{},
path:(newData && detailData.currentDetailType == 'sketch' && isCurrent && !detailData.isEditPattern.value)?newData.minIOPath:list[i].minIOPath, path:(newData && detailData.currentDetailType == 'sketch' && isCurrent && !detailData.isEditPattern.value)?newData.minIOPath:list[i].minIOPath,
printObject:(newData && detailData.currentDetailType == 'print' && isCurrent && !detailData.isEditPattern.value)?{prints:newData}:list[i].printObject?list[i].printObject:{prints:[]}, printObject:(newData && detailData.currentDetailType == 'print' && isCurrent && !detailData.isEditPattern.value)?{prints:newData}:list[i].printObject?list[i].printObject:{prints:[]},
@@ -392,9 +399,9 @@ export default defineComponent({
if(!detailData?.selectDetail?.path && !detailData?.selectDetail?.newDetail?.sketch?.minIOPath)return if(!detailData?.selectDetail?.path && !detailData?.selectDetail?.newDetail?.sketch?.minIOPath)return
let clothes:any let clothes:any
if(detailData.currentDetailType == 'models' || detailData.isUndividedLayerWithSinglePrint){ if(detailData.currentDetailType == 'models' || detailData.isUndividedLayerWithSinglePrint){
clothes = await setClothes(detailData.designDetail.clothes) clothes = await setClothes(detailData.designDetail.clothes,str)
}else{ }else{
clothes = await setClothes([detailData.selectDetail]) clothes = await setClothes([detailData.selectDetail],str)
} }
let data = { let data = {
designItemId:detailData.designDetail.designItemId, designItemId:detailData.designDetail.designItemId,
@@ -417,7 +424,8 @@ export default defineComponent({
fun:setRevocation fun:setRevocation
} }
if(detailData?.designDetail?.newModel)detailData.designDetail.oldModel = JSON.parse(JSON.stringify(detailData.designDetail.newModel)) if(detailData?.designDetail?.newModel)detailData.designDetail.oldModel = JSON.parse(JSON.stringify(detailData.designDetail.newModel))
delete detailData.designDetail.newModel // delete detailData.designDetail.newModel
detailData.selectDetail.sketchString = null
store.commit('DesignDetail/setPraeview',value) store.commit('DesignDetail/setPraeview',value)
detailData.loadingShow = false detailData.loadingShow = false
detailData.isUndividedLayerWithSinglePrint = false detailData.isUndividedLayerWithSinglePrint = false
@@ -429,7 +437,7 @@ export default defineComponent({
} }
const submit = async ()=>{ const submit = async ()=>{
let workspace = store.state.Workspace.probjects let workspace = store.state.Workspace.probjects
let clothes:any = await setClothes(detailData.designDetail.clothes) let clothes:any = await setClothes(detailData.designDetail.clothes,'sub')
let data = { let data = {
designItemId:detailData.designDetail.designItemId, designItemId:detailData.designDetail.designItemId,
designSingleItemDTOList:clothes, designSingleItemDTOList:clothes,
@@ -466,9 +474,41 @@ export default defineComponent({
detailData.loadingShow = false detailData.loadingShow = false
}); });
} }
const previwe = ()=>{ const previwe = async ()=>{
if((detailData.currentDetailType == 'sketch' && !detailData.isEditPattern.value) || detailData.isEditPattern.value == 'editSketch'){
let data = getSubmitData('preview') let data = getSubmitData('preview')
store.dispatch('DesignDetail/setSubmit',data) store.dispatch('DesignDetail/setSubmit',data)
}else{
//走画布合成图片并且直接分割
if(detailData.isEditPattern.value !== 'canvasEditor'){
if(detailDom.detailRight?.privewDetail)await (detailDom.detailRight as any).privewDetail()
let otherData = await updateOtherLayers('single')
await detailDom.canvasBox.updateOtherLayers(otherData)
}
await detailDom.canvasBox.privewDetail()
let img = new Image()
img.onload = ()=>{
let partialDesign = detailData.selectDetail.partialDesign.partialDesignBase64 || detailData.selectDetail.partialDesign.partialDesignPath
let size = {
width:img.width,
height:img.height,
}
segmentImage(detailData.selectDetail.maskUrl,partialDesign,size).then(async (rv)=>{
let front = detailData.frontBack.front[detailData.imgDomIndex]
let back = detailData.frontBack.back[detailData.imgDomIndex]
if(!front?.oldImageUrl)front.oldImageUrl = front.imageUrl
if(!front?.oldMaskUrl)front.oldMaskUrl = front.maskUrl
if(!back?.oldImageUrl)back.oldImageUrl = back.imageUrl
if(!front?.oldMaskUrl)store.commit('DesignDetail/updataDetailItem',{maskUrl:front.oldMaskUrl})
front.imageUrl = rv.targetFrontUrl
back.imageUrl = rv.targetBackUrl
detailData.selectDetail.undividedLayerWithSinglePrint = partialDesign
store.commit('DesignDetail/canvasPreviewUpdata',{type:detailData.isEditPattern.value?'all':detailData.currentDetailType,callBack:setRevocation})
})
}
img.src = detailData.selectDetail.path
}
} }
const modelOnLoad = ()=>{ const modelOnLoad = ()=>{
if(!detailData.isUndividedLayerWithSinglePrint)return if(!detailData.isUndividedLayerWithSinglePrint)return
@@ -480,31 +520,132 @@ export default defineComponent({
const detailEdit = async (str:any)=>{ const detailEdit = async (str:any)=>{
if(str){ if(str){
if(detailData.isEditPattern.value && detailData.isEditPattern.value == str){ if(detailData.isEditPattern.value && detailData.isEditPattern.value == str){
await detailDom.canvasBox.saveCanvas() // await detailDom.canvasBox.saveCanvas()
await (detailDom.canvasBox as any).privewDetail()
if(detailData.isEditPattern.value == 'canvasEditor')await uploadElement()
detailData.isEditPattern.value = '' detailData.isEditPattern.value = ''
}else{ }else{
if(detailData.isEditPattern.value){ // if(detailData.isEditPattern.value && (str == 'canvasEditor' || str == 'redGreenExample')){
// detailDom.canvasBox.editFront(str)
// }
detailDom.canvasBox.editFront(str) detailDom.canvasBox.editFront(str)
} let otherData = await updateOtherLayers('single')
await detailDom.canvasBox.updateOtherLayers(otherData)
detailData.isEditPattern.value = str detailData.isEditPattern.value = str
} }
}else{ }else{
detailData.isEditPattern.value = '' detailData.isEditPattern.value = ''
} }
} }
const getColorName = (color:any)=>{
let rgb:any = [color.r, color.g, color.b];
let hsv = rgbToHsv(rgb);
let data = [{
h: hsv[0],
s: hsv[1],
v: hsv[2],
}]
return new Promise((resolve, reject) => {
Https.axiosPost(Https.httpUrls.getRgbByHsvBatch, data)
.then((rv) => {
if (rv) {
resolve(rv[0])
}
})
.catch((res) => {
resolve({name:'--',tcx:'--'})
});
})
}
const updateOtherLayers = async (str:any='all')=>{//更新到画布图层
let otherData:any = {}
if(detailDom.detailRight?.privewDetail)await (detailDom.detailRight as any).privewDetail()
if(str == 'all'){
otherData = {
color: detailData.selectDetail.newDetail?.color.r?detailData.selectDetail.newDetail?.color:detailData.selectDetail.color,
printObject: detailData.selectDetail.newDetail?.print?.length>0?{prints:detailData.selectDetail.newDetail?.print}:detailData.selectDetail.printObject || null,
trims: detailData.selectDetail.newDetail?.element?.length>0?detailData.selectDetail.newDetail?.element:detailData.selectDetail.trims || null,
}
}else if(str == 'single'){
otherData = {
color: detailData.selectDetail.color,
printObject: detailData.selectDetail.printObject || null,
trims: detailData.selectDetail.trims || null,
}
if(detailData.currentDetailType == 'color'){
let color = detailData.selectDetail.newDetail?.color
console.log(color)
// let colorData:any = await getColorName(color?.rgba)
if(detailData.selectDetail.newDetail?.color?.rgba?.r){
color.rgba = {r:color.r,g:color.g,b:color.b,a:color.a}
otherData.color = color
}
}
if(detailData.currentDetailType == 'print'){
otherData.printObject = detailData.selectDetail.newDetail?.print?.length>0?{prints:detailData.selectDetail.newDetail?.print}:detailData.selectDetail.printObject || null
}
if(detailData.currentDetailType == 'element'){
otherData.trims = detailData.selectDetail.newDetail?.element?.length>0?detailData.selectDetail.newDetail?.element:detailData.selectDetail.trims || null
}
}
console.log(otherData,'=======',detailData.selectDetail)
return otherData
}
const uploadElement = async ()=>{//取出画布数据更新到detail
if(detailData.isEditPattern.value == 'canvasEditor'){
// await detailDom.canvasBox.saveCanvas()
const allInfo = await (detailDom.canvasBox as any).getCanvasElement()
console.log(allInfo,'allInfo')
if(allInfo.trims?.length > 0){
// detailData.selectDetail.trims.prints = allInfo.trims
let value = {
data:allInfo.trims,
str:'element'
}
store.commit('DesignDetail/setNewDetail',value)
}
if(allInfo.prints?.length > 0){
// detailData.selectDetail.printObject.prints = allInfo.prints
let value = {
data:allInfo.prints,
str:'print'
}
store.commit('DesignDetail/setNewDetail',value)
}
if(allInfo.color?.color?.rgba){
let canvasColor = allInfo.color.color
let colorData:any = await getColorName(allInfo.color.color?.rgba)
let value:any = {
data:{
hsv:{
h:colorData.h,
s:colorData.s,
v:colorData.v,
},
name:colorData.name,
tcx:colorData.tcx,
rgba:canvasColor.rgba,
hex:rgbaToHex([canvasColor.rgba.r,canvasColor.rgba.g,canvasColor.rgba.b]),
},
str:'color'
}
if(canvasColor.gradient){
value.data.gradient = canvasColor.gradient
}
store.commit('DesignDetail/setNewDetail',value)
if(allInfo.color.color.gradient)detailData.selectDetail.color.gradient = allInfo.color.color.gradient
if(detailData.currentDetailType == 'color'){
detailData.detailLeftColorKey++
}
}
}
}
const canvasReload = async ()=>{ const canvasReload = async ()=>{
if(detailData.isEditPattern.value){ if(detailData.isEditPattern.value){
await detailDom.canvasBox.saveCanvas() await detailDom.canvasBox.saveCanvas()
} }
detailData.canvasKey += 1 detailData.canvasKey += 1
} }
let time = null as any
const handleResize = ()=>{
clearTimeout(time)
time = setTimeout(()=>{
store.commit('DesignDetail/setDesignDetail',detailData.designDetail)
},1000)
}
const sketchSysToLibrary = ()=>{//系统sketch添加到library更新library const sketchSysToLibrary = ()=>{//系统sketch添加到library更新library
coverRevocation() coverRevocation()
detailDom.detailLeft.sketchSysToLibrary() detailDom.detailLeft.sketchSysToLibrary()
@@ -516,11 +657,6 @@ export default defineComponent({
sessionStorage.setItem('revocation', JSON.stringify(revocation)); sessionStorage.setItem('revocation', JSON.stringify(revocation));
sessionStorage.setItem('oppositeRevocation',JSON.stringify([])); sessionStorage.setItem('oppositeRevocation',JSON.stringify([]));
} }
const addDetail = () =>{
let addDetails:any = detailDom.addDetails
addDetails.init(detailData.selectDetail,'')
}
const setSloganData = (data:any)=>{ const setSloganData = (data:any)=>{
detailData.selectDetail.sketchString = data detailData.selectDetail.sketchString = data
if(detailData.currentDetailType == 'sketch' && detailData.selectDetail?.newDetail?.sketch){ if(detailData.currentDetailType == 'sketch' && detailData.selectDetail?.newDetail?.sketch){
@@ -528,14 +664,12 @@ export default defineComponent({
} }
} }
onMounted(()=>{ onMounted(()=>{
window.addEventListener('resize', handleResize);
}) })
onBeforeUnmount(()=>{ onBeforeUnmount(()=>{
sessionStorage.removeItem('oppositeRevocation') sessionStorage.removeItem('oppositeRevocation')
sessionStorage.removeItem('revocation') sessionStorage.removeItem('revocation')
store.commit('DesignDetail/clearDesignDetail') store.commit('DesignDetail/clearDesignDetail')
window.removeEventListener('resize', handleResize);
}) })
return{ return{
@@ -553,8 +687,8 @@ export default defineComponent({
canvasReload, canvasReload,
modelOnLoad, modelOnLoad,
sketchSysToLibrary, sketchSysToLibrary,
addDetail,
setSloganData, setSloganData,
updateOtherLayers,//更新到画布图层 再canvasInit中执行
} }
}, },
@@ -680,6 +814,24 @@ export default defineComponent({
flex: 1; flex: 1;
flex-direction: column; flex-direction: column;
overflow: hidden; overflow: hidden;
&.canvas{
opacity: 0;
position: absolute;
flex: auto;
width: 35vw;
height: 80vh;
pointer-events: none;
transform: translate(100vw,100vh);
}
&.active{
position: relative;
opacity: 1;
flex: 1;
width: auto;
height: auto;
pointer-events: auto;
transform: translate(0,0);
}
} }
} }
.btn{ .btn{

View File

@@ -1,98 +0,0 @@
<template>
<div class="addDetailsModal generalModel" ref="addDetailsModal"></div>
<a-modal
class="addDetails_modal generalModel fullScreen"
v-model:visible="addDetails"
:footer="null"
:get-container="() => $refs.addDetailsModal"
width="100%"
height="100%"
:maskClosable="false"
:centered="true"
:closable="false"
:destroyOnClose="true"
wrapClassName="#app"
:keyboard="false"
:mask="false"
>
<div class="generalModel_btn">
<div class="generalModel_closeIcon" @click.stop="cancelDsign()">
<svg width="100%" height="100%" viewBox="0 0 46 46" fill="none" xmlns="http://www.w3.org/2000/svg">
<circle cx="23" cy="23" r="23" fill="white" fill-opacity="0.3"/>
<rect x="32.5063" y="12" width="3" height="29" rx="1.5" transform="rotate(45 32.5063 12)" fill="#000"/>
<rect x="34.6274" y="32.5059" width="3" height="29" rx="1.5" transform="rotate(135 34.6274 32.5059)" fill="#000"/>
</svg>
</div>
</div>
<div class="addDetails_center">
<generalMiniCanvas :imgUrl="imgUrl" @submitBase64Data="submitBase64Data"></generalMiniCanvas>
</div>
<div></div>
</a-modal>
</template>
<script>
import { defineComponent, ref, reactive, watch, onMounted, nextTick, toRefs } from "vue";
import generalMiniCanvas from "../modules/generalMiniCanvas.vue";
export default defineComponent({
components: {
generalMiniCanvas,
},
emits: ['setSloganData'],
setup(props,{emit}) {
let addDetail = reactive({
imgUrl:''
});
let addDetails = ref(false);
let init = (data,index)=>{
addDetails.value = true
addDetail.imgUrl = data.sketchString || data.path
}
let submitBase64Data = (data)=>{
emit('setSloganData',data)
cancelDsign()
}
let cancelDsign = ()=>{
addDetails.value = false
}
return {
...toRefs(addDetail),
addDetails,
init,
submitBase64Data,
cancelDsign,
};
},
data() {
return {
};
},
mounted() {},
methods: {
},
});
</script>
<style lang="less" scoped>
.addDetailsModal{
width: 0;
height: 0;
}
.addDetails_modal {
.closeIcon {
z-index: 2;
}
.addDetails_center{
position: relative;
height: 100%;
display: flex;
flex-direction: column;
margin: 0 auto;
}
.exportCanvasBox_submit{
// margin-top: 2.4rem;
// text-align: center;
}
}
</style>

View File

@@ -6,16 +6,15 @@
<div class="content-bottom" ref="canvasContent"> <div class="content-bottom" ref="canvasContent">
<div class="contet"> <div class="contet">
<!-- :clothingImageUrl="selectDetail?.undividedLayerWithSinglePrint || selectDetail.undividedLayer || selectDetail.path" --> <!-- :clothingImageUrl="selectDetail?.undividedLayerWithSinglePrint || selectDetail.undividedLayer || selectDetail.path" -->
<div class="canvas" v-if="currentView === 'canvasEditor'" @click.stop> <div class="canvas" :class="{'active': currentView === 'canvasEditor'}"@click.stop>
<editCanvas v-if="canvasLoad" :config="canvasConfig" <editCanvas v-if="canvasLoad" :config="canvasConfig"
@canvasInit="canvasInit" @canvasInit="canvasInit"
@changeCanvas="changeCanvas"
is-edit is-edit
:clothingImageUrl="selectDetail.path" :clothingImageUrl="selectDetail.path"
:clothingImageUrl2="selectDetail.undividedLayer" :clothingImageUrl2="selectDetail.undividedLayer_"
showFixedLayer showFixedLayer
:canvasJSON="canvasJSON" :canvasJSON="canvasJSON"
:otherData="otherData" @canvasLoadJsonSuccess="canvasLoadJsonSuccess"
:clothing-image-opts="{ :clothing-image-opts="{
imageMode:'contains', imageMode:'contains',
}" }"
@@ -25,12 +24,6 @@
<!-- <canvasContent ref="canvasContent"></canvasContent> --> <!-- <canvasContent ref="canvasContent"></canvasContent> -->
</div> </div>
<div class="editFrontBack" v-if="currentView === 'redGreenExample'" @click.stop> <div class="editFrontBack" v-if="currentView === 'redGreenExample'" @click.stop>
<!-- <editFrontBack
:patchData="frontBack"
:imgDomIndex="imgDomIndex"
ref="editFrontBack">
</editFrontBack> -->
<editCanvas v-if="canvasLoad" :config="canvasConfig" <editCanvas v-if="canvasLoad" :config="canvasConfig"
@canvasInit="canvasInit" @canvasInit="canvasInit"
:enabledRedGreenMode="true" :enabledRedGreenMode="true"
@@ -45,6 +38,9 @@
ref="editCanvasBackFront"> ref="editCanvasBackFront">
</editCanvas> </editCanvas>
</div> </div>
<div class="editSketch" v-if="currentView === 'editSketch'" @click.stop>
<generalMiniCanvas ref="generalMiniCanvas" :btnShow="false" :imgUrl="selectDetail.sketchString || selectDetail.path"></generalMiniCanvas>
</div>
</div> </div>
<!-- <div class="Finish"> <!-- <div class="Finish">
@@ -69,15 +65,20 @@ import { useI18n } from 'vue-i18n'
import editCanvas from "@/component/Canvas/CanvasEditor/index.vue"; import editCanvas from "@/component/Canvas/CanvasEditor/index.vue";
import { formatTime,segmentImage,getMinioUrl } from "@/tool/util"; import { formatTime,segmentImage,getMinioUrl } from "@/tool/util";
import { useRouter, useRoute } from 'vue-router' import { useRouter, useRoute } from 'vue-router'
import generalMiniCanvas from "../../modules/generalMiniCanvas.vue";
export default defineComponent({ export default defineComponent({
components:{ components:{
editCanvas editCanvas,generalMiniCanvas
}, },
props:{ props:{
isEditPattern:{ isEditPattern:{
type:String, type:String,
default:'' default:''
},
updateOtherLayers:{
type:Function,
default:()=>{}
} }
}, },
setup(props,{emit}) { setup(props,{emit}) {
@@ -90,6 +91,7 @@ export default defineComponent({
editCanvas:null as any, editCanvas:null as any,
editCanvasBackFront:null as any, editCanvasBackFront:null as any,
canvasContent:null as any, canvasContent:null as any,
generalMiniCanvas:null as any,
}) })
const userDetail = computed(()=>{ const userDetail = computed(()=>{
return store.state.UserHabit.userDetail return store.state.UserHabit.userDetail
@@ -130,14 +132,14 @@ export default defineComponent({
if(detailData.currentView === 'canvasEditor'){ if(detailData.currentView === 'canvasEditor'){
sessionStorage.setItem('sketchEdit',detailDom.editCanvas.getJSON()) sessionStorage.setItem('sketchEdit',detailDom.editCanvas.getJSON())
canvasJSON = sessionStorage.getItem('frontBackEdit'); canvasJSON = sessionStorage.getItem('frontBackEdit');
}else{ }else if(detailData.currentView === 'redGreenExample'){
sessionStorage.setItem('frontBackEdit',detailDom.editCanvasBackFront.getJSON()) sessionStorage.setItem('frontBackEdit',detailDom.editCanvasBackFront.getJSON())
canvasJSON = sessionStorage.getItem('sketchEdit'); canvasJSON = sessionStorage.getItem('sketchEdit');
} }
detailData.canvasLoad = false // detailData.canvasLoad = false
detailData.currentView = str detailData.currentView = str
if(canvasJSON){ if(canvasJSON){
detailData.canvasLoad = true // detailData.canvasLoad = true
nextTick(()=>{ nextTick(()=>{
if(detailData.currentView === 'redGreenExample'){ if(detailData.currentView === 'redGreenExample'){
detailDom.editCanvas.loadJSON(canvasJSON) detailDom.editCanvas.loadJSON(canvasJSON)
@@ -149,28 +151,38 @@ export default defineComponent({
if(detailData.currentView === 'redGreenExample'){ if(detailData.currentView === 'redGreenExample'){
nextTick(()=>{ nextTick(()=>{
setCanvas(detailData.selectDetail?.undividedLayerWithSinglePrint || detailData.selectDetail.undividedLayer || detailData.selectDetail.path).then(()=>{ setCanvas(detailData.selectDetail?.undividedLayerWithSinglePrint || detailData.selectDetail.undividedLayer || detailData.selectDetail.path).then(()=>{
detailData.canvasLoad = true // detailData.canvasLoad = true
}) })
}) })
}else{ }else{
nextTick(()=>{ nextTick(()=>{
setCanvas(detailData.frontBack.front[detailData.imgDomIndex].maskUrl).then(()=>{ setCanvas(detailData.frontBack.front[detailData.imgDomIndex].maskUrl).then(()=>{
detailData.canvasLoad = true // detailData.canvasLoad = true
}) })
}) })
} }
} }
} }
const updateOtherLayers = (obj:any)=>{
if(!detailDom.editCanvas)return
return new Promise(async (res,reject)=>{
console.log(obj,'====')
await detailDom?.editCanvas.updateOtherLayers(obj)
res('')
})
}
const privewDetail = async (oldSelectDetail = detailData.selectDetail)=>{ const privewDetail = async (oldSelectDetail = detailData.selectDetail)=>{
if(!detailDom.editCanvas)return // if(!detailDom.editCanvas)return
return new Promise((res,reject)=>{ return new Promise((res,reject)=>{
detailDom.editCanvas.exportImage({isContainBg:false,isContainFixed:false}).then((rv)=>{ detailDom.editCanvas.exportImage({isContainFixedOther:true,isContainFixed:true}).then((rv)=>{
if(oldSelectDetail?.partialDesign)oldSelectDetail.partialDesign.partialDesignBase64 = rv if(oldSelectDetail?.partialDesign)oldSelectDetail.partialDesign.partialDesignBase64 = rv
res('') res('')
}) })
}) })
}
const getCanvasElement = ()=>{
if(!detailDom?.editCanvas)return ''
return detailDom?.editCanvas.exportExtraInfo();
} }
const setFrontBackColor = (data:any)=>{ const setFrontBackColor = (data:any)=>{
detailDom.editFrontBack.setBackground(data) detailDom.editFrontBack.setBackground(data)
@@ -259,6 +271,7 @@ export default defineComponent({
detailData.canvasInstance = value detailData.canvasInstance = value
detailData.getCanvasIfEdit.fun = getCanvasLength detailData.getCanvasIfEdit.fun = getCanvasLength
detailData.isShowMark = false detailData.isShowMark = false
console.log('初始化完成')
} }
const getCanvasLength = ()=>{ const getCanvasLength = ()=>{
return detailData.canvasInstance?.commandManager?.undoStack?.length return detailData.canvasInstance?.commandManager?.undoStack?.length
@@ -297,14 +310,21 @@ export default defineComponent({
}); });
}) })
} }
let time = null as any // let time = null as any
const changeCanvas = ()=>{ // const changeCanvas = ()=>{
clearTimeout(time) // clearTimeout(time)
time = setTimeout(()=>{ // time = setTimeout(()=>{
saveCanvas('auto') // saveCanvas('auto')
},3000) // },3000)
// }
const canvasLoadJsonSuccess = async ()=>{
let otherData = await props.updateOtherLayers()
updateOtherLayers(otherData)
} }
const submitBase64Data = ()=>{
return detailDom.generalMiniCanvas.submitBase64Data()
}
onBeforeUnmount(()=>{ onBeforeUnmount(()=>{
let front = detailData.frontBack.front[detailData.imgDomIndex] let front = detailData.frontBack.front[detailData.imgDomIndex]
let back = detailData.frontBack.back[detailData.imgDomIndex] let back = detailData.frontBack.back[detailData.imgDomIndex]
@@ -353,7 +373,10 @@ export default defineComponent({
frontBackChange, frontBackChange,
canvasInit, canvasInit,
saveCanvas, saveCanvas,
changeCanvas, getCanvasElement,
updateOtherLayers,
canvasLoadJsonSuccess,
submitBase64Data,
} }
}, },
provide() { provide() {
@@ -434,7 +457,15 @@ export default defineComponent({
flex: 1; flex: 1;
overflow: hidden; overflow: hidden;
position: relative; position: relative;
.canvas,.editFrontBack{ .canvas{
opacity: 0;
position: absolute;
&.active{
opacity: 1;
position: relative;
}
}
.canvas,.editFrontBack,.editSketch{
width: 100%; width: 100%;
height: 100%; height: 100%;
} }

View File

@@ -61,6 +61,7 @@ import SelectImages from '@/component/common/SelectImages.vue'
import upload from './upload.vue' import upload from './upload.vue'
import pallet from './pallet.vue' import pallet from './pallet.vue'
import { select } from 'three/tsl';
export default defineComponent({ export default defineComponent({
components:{ components:{
upload,pallet,SelectImages upload,pallet,SelectImages
@@ -99,13 +100,18 @@ export default defineComponent({
tcxToColor:'', tcxToColor:'',
}) })
watch(()=>colorData.selectColor,async (newVal,oldVal)=>{ watch(()=>colorData.selectColor,async (newVal,oldVal)=>{
console.log(newVal)
if(newVal.rgba && newVal.rgba?.r){ if(newVal.rgba && newVal.rgba?.r){
let data:any = await getColorName(newVal.rgba) let data:any = await getColorName(newVal.rgba)
newVal.name = data.name newVal.name = data.name
newVal.tcx = data.tcx newVal.tcx = data.tcx
colorData.colorList.list[colorData.selectDetail.id][colorData.colorList.index] = newVal colorData.colorList.list[colorData.selectDetail.id][colorData.colorList.index] = newVal
data.rgba = newVal.rgba
if(newVal.gradient){
data.gradient = newVal.gradient
}
let value = { let value = {
data:newVal, data:data,
str:'color' str:'color'
} }
store.commit('DesignDetail/setNewDetail',value) store.commit('DesignDetail/setNewDetail',value)
@@ -141,7 +147,6 @@ export default defineComponent({
JSON.stringify(colorData.selectDetail.color.gradient) == JSON.stringify(color?.gradient) JSON.stringify(colorData.selectDetail.color.gradient) == JSON.stringify(color?.gradient)
&& colorData.selectDetail.color.rgba?.r && colorData.selectDetail.color.rgba?.r
){ ){
console.log('---',index)
isNoSelect = true isNoSelect = true
colorData.selectColor = item colorData.selectColor = item
colorData.colorList.index = index colorData.colorList.index = index
@@ -190,52 +195,11 @@ export default defineComponent({
colorData.colorList.index = num colorData.colorList.index = num
colorData.colorList.list[newVal][num] = item colorData.colorList.list[newVal][num] = item
} }
// let newData = colorData.selectDetail?.newDetail?.color
// for (let index = 0; index < 9; index++) { // console.log(newData,colorData.selectColor)
// colorData.allBoardData.colorBoards // if(newData){
// let item:any = {} // newData.hex = rgbaToHex([newData.rgba.r,newData.rgba.g,newData.rgba.b])
// item = colorData.allBoardData.colorBoards[index] // colorData.selectColor = newData
// if(
// colorData.allBoardData.colorBoards?.[index] &&
// colorData.selectDetail.color.rgba?.r == colorData.allBoardData.colorBoards?.[index]?.rgba?.r &&
// colorData.selectDetail.color.rgba?.g == colorData.allBoardData.colorBoards?.[index]?.rgba?.g &&
// colorData.selectDetail.color.rgba?.b == colorData.allBoardData.colorBoards?.[index]?.rgba?.b &&
// JSON.stringify(colorData.selectDetail.color.gradient) == JSON.stringify(colorData.allBoardData.colorBoards?.[index]?.gradient)
// && colorData.selectDetail.color.rgba?.r
// ){
// console.log(13212)
// if(!isOneChecked){
// isOneChecked = true
// if(colorData.allBoardData.colorBoards?.[index].gradient){
// item.gradient = colorData.allBoardData.colorBoards?.[index].gradient
// }
// colorData.selectColor = item
// colorData.colorList.index = index
// }
// }else if(colorData.selectDetail.color.rgba?.r){
// if(!isNoSelect){
// item = {
// hex:rgbaToHex([colorData.selectDetail.color.rgba.r,colorData.selectDetail.color.rgba.g,colorData.selectDetail.color.rgba.b]),
// id:colorData.selectDetail.color.id,
// rgba:{
// r:colorData.selectDetail.color.rgba.r,
// g:colorData.selectDetail.color.rgba.g,
// b:colorData.selectDetail.color.rgba.b,
// },
// tcx:colorData.selectDetail.color.tcx,
// name:colorData.selectDetail.color.name,
// }
// if(colorData.selectDetail.color.gradient){
// item.gradient = colorData.selectDetail.color.gradient
// }
// colorData.colorList.index = index
// colorData.selectColor = item
// isNoSelect = true
// }else{
// item = {}
// }
// }
// colorData.colorList.list[newVal].push(item)
// } // }
},{immediate: true}) },{immediate: true})
const selectImgItem = ()=>{ const selectImgItem = ()=>{
@@ -281,7 +245,6 @@ export default defineComponent({
}) })
} }
const handleShowListChange=(val:boolean)=>{ const handleShowListChange=(val:boolean)=>{
console.log('val',val)
showLibrary.value = !val showLibrary.value = !val
} }

View File

@@ -2,7 +2,7 @@
<div class="detailLeft"> <div class="detailLeft">
<sketch v-show="currentDetailType == 'sketch'" ref="sketch" @addDetail="addDetail"></sketch> <sketch v-show="currentDetailType == 'sketch'" ref="sketch" @addDetail="addDetail"></sketch>
<print v-show="currentDetailType == 'print'"></print> <print v-show="currentDetailType == 'print'"></print>
<color v-if="currentDetailType == 'color'"></color> <color v-if="currentDetailType == 'color'" :key="detailLeftColorKey"></color>
<element v-show="currentDetailType == 'element'"></element> <element v-show="currentDetailType == 'element'"></element>
<accessory v-show="currentDetailType == 'accessory'"></accessory> <accessory v-show="currentDetailType == 'accessory'"></accessory>
<models v-show="currentDetailType == 'models'"></models> <models v-show="currentDetailType == 'models'"></models>
@@ -25,6 +25,12 @@ import models from './models.vue'
export default defineComponent({ export default defineComponent({
components:{ components:{
sketch,print,color,element,models,accessory sketch,print,color,element,models,accessory
},
props:{
detailLeftColorKey:{
type:Number,
default:0,
},
}, },
emit:['addDetail'], emit:['addDetail'],
setup(props,{emit}) { setup(props,{emit}) {

View File

@@ -69,7 +69,6 @@ export default defineComponent({
file.designType = file?.resData?.designType file.designType = file?.resData?.designType
} }
} }
// store.commit('DesignDetail/setNewDetail',file.resData)
emit('selectImgItem',file) emit('selectImgItem',file)
} }

View File

@@ -98,7 +98,6 @@ export default defineComponent({
}) })
const selectImgItem = (file:any)=>{ const selectImgItem = (file:any)=>{
// let data = JSON.parse(JSON.stringify(file)) // let data = JSON.parse(JSON.stringify(file))
// store.commit('DesignDetail/setNewDetail',file)
emit('selectImgItem',file) emit('selectImgItem',file)
} }
const upFileUploadChange = (data:any)=>{ const upFileUploadChange = (data:any)=>{

View File

@@ -88,7 +88,6 @@ export default defineComponent({
}) })
const selectImgItem = (file:any)=>{ const selectImgItem = (file:any)=>{
// let data = JSON.parse(JSON.stringify(file)) // let data = JSON.parse(JSON.stringify(file))
// store.commit('DesignDetail/setNewDetail',file)
emit('selectImgItem',file) emit('selectImgItem',file)
} }
const setUploadImgList = (list:any)=>{ const setUploadImgList = (list:any)=>{

View File

@@ -51,6 +51,25 @@
:tip-formatter="formatter" :tip-formatter="formatter"
> >
</a-slider> </a-slider>
<a-popover
trigger="click"
destroyTooltipOnHide
:title="t('Canvas.repeatSetting')"
>
<template #content>
<repeat-setting
:object="overallDetail"
@inputFillAngle="inputFillAngle"
@inputFillOffset="inputFillOffset"
@inputFillScale="inputFillScale"
@inputFill_Gap="
(x, y) => inputFill_Gap(x, y)"
/>
</template>
<div class="btn">
<i class="iconfont icon-gengduo"></i>
</div>
</a-popover>
</div> </div>
<div class="editPrintElementBox"> <div class="editPrintElementBox">
<div class="designOpenrtion_centent" id="designOpenrtionCentent"> <div class="designOpenrtion_centent" id="designOpenrtionCentent">
@@ -70,9 +89,10 @@
</div> </div>
</div> </div>
<!-- <img :src="selectDetail.path" alt="" class="designOpenrtion_sketch" ref="sketchImg"> --> <!-- <img :src="selectDetail.path" alt="" class="designOpenrtion_sketch" ref="sketchImg"> -->
<img :src="selectDetail?.undividedLayer?selectDetail.undividedLayer:selectDetail.path" alt="" class="designOpenrtion_sketch" ref="sketchImg" @load="()=>isSketchLoad = true"> <img :src="selectDetail?.undividedLayerWithSinglePrint?selectDetail.undividedLayerWithSinglePrint:selectDetail.path" alt="" class="designOpenrtion_sketch" ref="sketchImg" @load="()=>isSketchLoad = true">
<div class="designOpenrtion_btn"> <img :src="selectDetail.sketchMask" alt="" class="designOpenrtion_sketchMask" ref="sketchMask">
<ul v-if="stateOverallSingle == 'single'" v-for="item,index in printStyleList[type][stateOverallSingle]" :key="item" :class="{active:item?.pattern.designOpenrtionBtn?item?.pattern.designOpenrtionBtn:false}" class="designOpenrtion_Mousingle" :style="item?.pattern.style" @mousedown.stop="itemMoveMousedown(index,getMousePosition($event,false))" @touchstart.passive="itemMoveMousedown(index,getMousePosition($event,true))"> <div class="designOpenrtion_btn" v-if="stateOverallSingle == 'single'" >
<ul v-for="item,index in printStyleList[type][stateOverallSingle]" :key="item" :class="{active:item?.pattern.designOpenrtionBtn?item?.pattern.designOpenrtionBtn:false}" class="designOpenrtion_Mousingle" :style="item?.pattern.style" @mousedown.stop="itemMoveMousedown(index,getMousePosition($event,false))" @touchstart.passive="itemMoveMousedown(index,getMousePosition($event,true))">
<li class="designOpenrtion_btn_top" @mousedown.stop="itemSizeMousedown('top',getMousePosition($event,false))" @touchstart.passive="itemSizeMousedown('top',getMousePosition($event,true))"></li> <li class="designOpenrtion_btn_top" @mousedown.stop="itemSizeMousedown('top',getMousePosition($event,false))" @touchstart.passive="itemSizeMousedown('top',getMousePosition($event,true))"></li>
<li class="designOpenrtion_btn_bottom" @mousedown.stop="itemSizeMousedown('bottom',getMousePosition($event,false))" @touchstart.passive="itemSizeMousedown('bottom',getMousePosition($event,true))"></li> <li class="designOpenrtion_btn_bottom" @mousedown.stop="itemSizeMousedown('bottom',getMousePosition($event,false))" @touchstart.passive="itemSizeMousedown('bottom',getMousePosition($event,true))"></li>
<li class="designOpenrtion_btn_left" @mousedown.stop="itemSizeMousedown('left',getMousePosition($event,false))" @touchstart.passive="itemSizeMousedown('left',getMousePosition($event,true))"></li> <li class="designOpenrtion_btn_left" @mousedown.stop="itemSizeMousedown('left',getMousePosition($event,false))" @touchstart.passive="itemSizeMousedown('left',getMousePosition($event,true))"></li>
@@ -82,12 +102,15 @@
<img src="../../../assets/images/homePage/cuowu.svg" alt=""> <img src="../../../assets/images/homePage/cuowu.svg" alt="">
</li> </li>
</ul> </ul>
<div v-show="stateOverallSingle != 'single'"></div> <!-- <div v-show="stateOverallSingle != 'single'"></div>
<ul v-if="stateOverallSingle != 'single' && printStyleList[type][stateOverallSingle][0]" class="designOpenrtion_Mouoverall active" :style="'left:'+printStyleList[type][stateOverallSingle][0]?.pattern?.style?.left+';top:'+printStyleList[type][stateOverallSingle][0]?.pattern?.style?.top+';'" @mousedown.stop="itemMoveMousedown(0,getMousePosition($event,false))" @touchstart.passive="itemMoveMousedown(0,getMousePosition($event,true))"> <ul v-if="stateOverallSingle != 'single' && printStyleList[type][stateOverallSingle][0]" class="designOpenrtion_Mouoverall active" :style="'left:'+printStyleList[type][stateOverallSingle][0]?.pattern?.style?.left+';top:'+printStyleList[type][stateOverallSingle][0]?.pattern?.style?.top+';'" @mousedown.stop="itemMoveMousedown(0,getMousePosition($event,false))" @touchstart.passive="itemMoveMousedown(0,getMousePosition($event,true))">
<i class="fi fi-rr-arrows animtion1"></i> <i class="fi fi-rr-arrows animtion1"></i>
<i class="fi fi-rr-arrows animtion2"></i> <i class="fi fi-rr-arrows animtion2"></i>
<li class="designOpenrtion_rotote" v-rotote.stop="[0,printStyleList[type][stateOverallSingle][0]?.pattern?.transform,type]"></li> <li class="designOpenrtion_rotote" v-rotote.stop="[0,printStyleList[type][stateOverallSingle][0]?.pattern?.transform,type]"></li>
</ul> </ul> -->
</div>
<div class="designOpenrtion_pingpu" v-else>
<pingpu v-if="overallDetail.url" v-bind="overallDetail"></pingpu>
</div> </div>
</div> </div>
</div> </div>
@@ -106,8 +129,13 @@ import { defineComponent,computed,ref,onMounted,nextTick,watch,toRefs, reactive,
// import setDesignItem from '@/component/Detail/setDesignItem2.vue' // import setDesignItem from '@/component/Detail/setDesignItem2.vue'
import { useStore } from "vuex"; import { useStore } from "vuex";
import { getMousePosition } from "@/tool/mdEvent"; import { getMousePosition } from "@/tool/mdEvent";
import { sketchToMask } from "@/tool/util";
import pingpu from '@/component/Canvas/OverallCanvas/index.vue'
import RepeatSetting from "./overallSetting/RepeatSetting.vue";
import { useI18n } from 'vue-i18n'
export default defineComponent({ export default defineComponent({
components:{ components:{
pingpu,RepeatSetting
}, },
props: { props: {
type: { type: {
@@ -116,6 +144,7 @@ export default defineComponent({
} }
}, },
setup(props,{emit}) { setup(props,{emit}) {
const { t } = useI18n()
const store = useStore(); const store = useStore();
const editPrintElementDom = reactive({ const editPrintElementDom = reactive({
imgDom:null as any, imgDom:null as any,
@@ -126,6 +155,15 @@ export default defineComponent({
currentDetailType:computed(()=>store.state.DesignDetail.currentDetailType), currentDetailType:computed(()=>store.state.DesignDetail.currentDetailType),
currentPrintElement:computed(()=>store.state.DesignDetail.currentPrintElement), currentPrintElement:computed(()=>store.state.DesignDetail.currentPrintElement),
systemDesignerPercentage:0, systemDesignerPercentage:0,
overallDetail:{
url: '',
offsetX: 0, // px
offsetY: 0, // px
angle: 0, // 角度
scale: 100, // %
gapX: 0, // px
gapY: 0, // px
},
printStyleList:{ printStyleList:{
print:{ print:{
single:[], single:[],
@@ -215,6 +253,7 @@ export default defineComponent({
path:data.url, path:data.url,
priority:editPrintElementData.printZIndex, priority:editPrintElementData.printZIndex,
scale, scale,
globalCompositeOperation:'',
} }
getItemPosition(item) getItemPosition(item)
setItemPosition() setItemPosition()
@@ -227,6 +266,7 @@ export default defineComponent({
let scale,location let scale,location
let style = item.pattern.style let style = item.pattern.style
let sketchWH = editPrintElementData.sketchWH.scale let sketchWH = editPrintElementData.sketchWH.scale
let overallDetail = {}
if(item.ifSingle){ if(item.ifSingle){
scale = [style.width.replace(/px/g,'')/(editPrintElementData.sketchWH.width),(style.height.replace(/px/g,'')/(editPrintElementData.sketchWH.height))] scale = [style.width.replace(/px/g,'')/(editPrintElementData.sketchWH.width),(style.height.replace(/px/g,'')/(editPrintElementData.sketchWH.height))]
location = [style.left.replace(/px/g,'')*sketchWH[0],style.top.replace(/px/g,'')*sketchWH[1]] location = [style.left.replace(/px/g,'')*sketchWH[0],style.top.replace(/px/g,'')*sketchWH[1]]
@@ -237,6 +277,14 @@ export default defineComponent({
scale =[ editPrintElementData.systemDesignerPercentage/100, editPrintElementData.systemDesignerPercentage/100] scale =[ editPrintElementData.systemDesignerPercentage/100, editPrintElementData.systemDesignerPercentage/100]
// scale = [item.pattern.style.width/item.pattern.style.height,item.pattern.style.height/item.pattern.style.width] // scale = [item.pattern.style.width/item.pattern.style.height,item.pattern.style.height/item.pattern.style.width]
// location = [item.pattern.style.left,item.pattern.style.top] // location = [item.pattern.style.left,item.pattern.style.top]
overallDetail = {
offsetX: editPrintElementData.overallDetail.offsetX, // px
offsetY: editPrintElementData.overallDetail.offsetY, // px
angle: editPrintElementData.overallDetail.angle, // 角度
scale: editPrintElementData.overallDetail.scale, // %
gapX: editPrintElementData.overallDetail.gapX, // px
gapY: editPrintElementData.overallDetail.gapY, // px
}
} }
let value ={ let value ={
angle : item.pattern.transform.rotateZ, angle : item.pattern.transform.rotateZ,
@@ -249,6 +297,9 @@ export default defineComponent({
path:item.path, path:item.path,
minIOPath:item.minIOPath, minIOPath:item.minIOPath,
ifSingle:!!item.ifSingle, ifSingle:!!item.ifSingle,
globalCompositeOperation:'',
object:null,
// ...overallDetail,
} }
return value return value
} }
@@ -316,6 +367,15 @@ export default defineComponent({
editPrintElementData.printStyleList[props.type].single.push(item) editPrintElementData.printStyleList[props.type].single.push(item)
}else{ }else{
editPrintElementData.printStyleList[props.type].overall = [] editPrintElementData.printStyleList[props.type].overall = []
editPrintElementData.overallDetail = {
url: item.path,
offsetX: 0, // px
offsetY: 0, // px
angle: 0, // 角度
scale: 100, // %
gapX: 0, // px
gapY: 0, // px
}
editPrintElementData.printStyleList[props.type].overall.push(item) editPrintElementData.printStyleList[props.type].overall.push(item)
} }
@@ -337,9 +397,9 @@ export default defineComponent({
if(!editPrintElementData.selectDetail.printObject.prints)return if(!editPrintElementData.selectDetail.printObject.prints)return
let state = true let state = true
// editPrintElementData.stateOverallSingle = 'single' // editPrintElementData.stateOverallSingle = 'single'
let arr:any = editPrintElementData.selectDetail.printObject.prints let arr:any = editPrintElementData.selectDetail.newDetail?.print || editPrintElementData.selectDetail.printObject.prints
if(props.type == 'element'){ if(props.type == 'element'){
arr = editPrintElementData.selectDetail.trims.prints arr = editPrintElementData.selectDetail.newDetail?.element || editPrintElementData.selectDetail.trims.prints
} }
if(editPrintElementData.selectDetail.newDetail?.[editPrintElementData.currentDetailType]){ if(editPrintElementData.selectDetail.newDetail?.[editPrintElementData.currentDetailType]){
arr = editPrintElementData.selectDetail.newDetail[editPrintElementData.currentDetailType] arr = editPrintElementData.selectDetail.newDetail[editPrintElementData.currentDetailType]
@@ -384,8 +444,28 @@ export default defineComponent({
single:[], single:[],
overall:[], overall:[],
} }
if(!editPrintElementData.selectDetail.sketchMask){
sketchToMask(newVal).then((res:any)=>{
editPrintElementData.selectDetail.sketchMask = res
})
}
setPosition() setPosition()
},{immediate: true,}) },{immediate: true,})
watch(()=>editPrintElementData.stateOverallSingle,(newVal)=>{
if(newVal == 'overall'){
let overallPrint = editPrintElementData.printStyleList[props.type][editPrintElementData.stateOverallSingle]?.[0]
if(!overallPrint?.path)return
editPrintElementData.overallDetail = {
url: overallPrint.path,
offsetX: overallPrint.offsetX || 0, // px
offsetY: overallPrint.offsetY || 0, // px
angle: overallPrint.angle || 0, // 角度
scale: overallPrint.scale || 100, // %
gapX: overallPrint.gapX || 0, // px
gapY: overallPrint.gapY || 0, // px
}
}
})
//设置移动 //设置移动
const itemMoveMousedown = (index:number,event:any)=>{ const itemMoveMousedown = (index:number,event:any)=>{
if (event.target.tagName === 'IMG' || event.target.nodeName === 'IMG')return if (event.target.tagName === 'IMG' || event.target.nodeName === 'IMG')return
@@ -738,6 +818,20 @@ export default defineComponent({
collItemSize.prentWidth = (collItemSize.padding + remValue) * elArr.length + 'px' collItemSize.prentWidth = (collItemSize.padding + remValue) * elArr.length + 'px'
moveItem() moveItem()
} }
const inputFillAngle = (angle:any)=>{
editPrintElementData.overallDetail.angle = angle
}
const inputFillOffset = (offset:any)=>{
editPrintElementData.overallDetail.offsetX = offset.left
editPrintElementData.overallDetail.offsetY = offset.top
}
const inputFillScale = (scale:any)=>{
editPrintElementData.overallDetail.scale = scale
}
const inputFill_Gap = (x:any,y:any)=>{
editPrintElementData.overallDetail.gapX = x
editPrintElementData.overallDetail.gapY = y
}
onMounted(()=>{ onMounted(()=>{
if(props.type == 'element'){ if(props.type == 'element'){
editPrintElementData.stateOverallSingle = 'single' editPrintElementData.stateOverallSingle = 'single'
@@ -747,6 +841,7 @@ export default defineComponent({
previewDetailPrintData() previewDetailPrintData()
}) })
return{ return{
t,
getMousePosition, getMousePosition,
...toRefs(editPrintElementDom), ...toRefs(editPrintElementDom),
...toRefs(editPrintElementData), ...toRefs(editPrintElementData),
@@ -760,6 +855,10 @@ export default defineComponent({
clearOverall, clearOverall,
designMousedown, designMousedown,
navDelete, navDelete,
inputFillAngle,
inputFillOffset,
inputFillScale,
inputFill_Gap,
} }
}, },
directives:{ directives:{
@@ -983,7 +1082,13 @@ export default defineComponent({
// height: 100%; // height: 100%;
max-width: 100%; max-width: 100%;
// width: 100%; // width: 100%;
&.designOpenrtion_sketchMask{
position: absolute;
z-index: 3;
top: 0;
left: 0;
pointer-events: none;
}
} }
.designOpenrtion_sketch_mask{ .designOpenrtion_sketch_mask{
z-index: 2; z-index: 2;
@@ -1013,8 +1118,13 @@ export default defineComponent({
} }
} }
} }
.designOpenrtion_pingpu{
width: 100%;
height: 100%;
z-index: 2;
}
.designOpenrtion_btn{ .designOpenrtion_btn{
z-index: 3; z-index: 99;
>div{ >div{
width: 100%; width: 100%;
height: 100%; height: 100%;

View File

@@ -0,0 +1,124 @@
<template>
<div class="repeat-setting">
<div class="repeat-setting-item">
<span class="label">{{ t("Canvas.angle") }}</span>
<angle-tool
:angle="angle"
@input="(e) => emit('inputFillAngle', e)"
/>
</div>
<p></p>
<div class="repeat-setting-item">
<span class="label">{{ t("Canvas.scale") }}</span>
<slider
:min="1"
:max="1000"
:step="1"
is-input
:tipFormatter="(v) => `${scale}%`"
:value="scale"
@input="inputFillScale"
/>
</div>
<p></p>
<div class="repeat-setting-item">
<span class="label">Gap X</span>
<slider
:min="0"
:max="1000"
:step="1"
is-input
:tipFormatter="(v) => `${v}px`"
:value="gapX"
@input="(e) => emit('inputFill_Gap', e, gapY)"
@change="(e) => emit('changeFill_Gap', e, gapY)"
/>
</div>
<p></p>
<div class="repeat-setting-item">
<span class="label">Gap Y</span>
<slider
:min="0"
:max="1000"
:step="1"
is-input
:tipFormatter="(v) => `${v}px`"
:value="gapY"
@input="(e) => emit('inputFill_Gap', gapX, e)"
@change="(e) => emit('changeFill_Gap', gapX, e)"
/>
</div>
<p></p>
<div class="repeat-setting-item">
<span class="label">{{ t("Canvas.offset") }}</span>
<offset-tool
:top="(props.object.fill?.offsetY / props.object.height) * 100"
:left="(props.object.fill?.offsetX / props.object.width) * 100"
@input="(e) => emit('inputFillOffset', e)"
@change="(e) => emit('changeFillOffset', e)"
/>
</div>
</div>
</template>
<script setup lang="ts">
import { ref, defineProps, defineEmits, computed } from "vue";
import AngleTool from "./tools/AngleTool.vue";
import OffsetTool from "./tools/OffsetTool.vue";
import Slider from "./tools/Slider.vue";
import { useI18n } from "vue-i18n";
const { t } = useI18n();
const props = defineProps({
object: {
required: true,
type: Object,
},
});
const angle = computed(() => props.object?.angle || 0);
const scale = computed(() => {
// let scaleValue = props.object?.scale/10;
// return props.object?.scale/10;
return props.object?.scale
});
const gapX = computed(() => props.object?.gapX || 0);
const gapY = computed(() => props.object?.gapY || 0);
const emit = defineEmits([
"inputFillAngle",
"changeFillAngle",
"inputFillOffset",
"changeFillOffset",
"inputFillScale",
"changeFillScale",
"inputFill_Gap",
"changeFill_Gap",
]);
const inputFillScale = (e) => {
// const scale = e * 10;
emit("inputFillScale", e);
};
</script>
<style scoped lang="less">
.repeat-setting {
user-select: none;
> .repeat-setting-item {
display: flex;
align-items: center;
//虚线
> .label {
min-width: 50px;
font-size: 14px;
}
> .angle-tool {
width: 120px;
}
}
> p {
margin: 10px 0;
width: 100%;
height: 0;
border-bottom: 1px dashed #e5e5e5;
}
}
</style>

View File

@@ -0,0 +1,122 @@
<template>
<div class="angle-tool">
<div
ref="dishRef"
class="dish"
@mousedown.stop="mousedown"
@touchmove.stop="mousedown"
>
<div class="pointer" :style="{ transform: `rotate(${angle}deg)` }">
<span></span>
</div>
</div>
<div class="input">
<input type="number" v-model="angle" @input="onInput" @change="onChange" />
</div>
</div>
</template>
<script setup lang="ts">
import { ref, defineProps, defineEmits, watch } from "vue";
import { calculateAngle } from "@/component/Canvas/CanvasEditor/utils/helper";
// Props
const props = defineProps({
angle: {
type: Number,
default: 0,
},
});
const emit = defineEmits(["change", "input"]);
const angle = ref(props.angle);
watch(() => props.angle, (value) => {
angle.value = value;
});
const dishRef = ref<HTMLDivElement>();
const mousedown = (e: MouseEvent | TouchEvent) => {
const mousemove = (e: MouseEvent | TouchEvent) => {
if (!dishRef.value) return;
const { left, top, width, height } =
dishRef.value.getBoundingClientRect();
const centerX = left + width / 2;
const centerY = top + height / 2;
const { clientX, clientY } = e?.touches?.[0] || e;
angle.value = calculateAngle(centerX, centerY, clientX, clientY, true);
console.log(angle.value)
onInput();
};
mousemove(e);
const mouseup = () => {
onChange();
document.removeEventListener("mousemove", mousemove);
document.removeEventListener("touchmove", mousemove);
document.removeEventListener("mouseup", mouseup);
document.removeEventListener("touchend", mouseup);
};
document.addEventListener("mousemove", mousemove);
document.addEventListener("touchmove", mousemove);
document.addEventListener("mouseup", mouseup);
document.addEventListener("touchend", mouseup);
};
const onInput = () => emit("input", angle.value);
var changeTime: any = null;
const onChange = () => {
clearTimeout(changeTime);
changeTime = setTimeout(() => emit("change", angle.value), 500);
};
// var angleTime = null;
// watch(angle, (value) => {
// emit("input", value);
// clearTimeout(angleTime);
// angleTime = setTimeout(() => emit("change", value), 50);
// });
// defineExpose({
// open,
// close,
// });
</script>
<style scoped lang="less">
.angle-tool {
display: flex;
align-items: center;
width: 100%;
> .dish {
width: 24px;
height: 24px;
border: 1px solid #000;
border-radius: 50%;
cursor: pointer;
> .pointer {
pointer-events: none;
user-select: none;
position: relative;
width: 100%;
height: 100%;
> span {
position: absolute;
top: 10%;
left: 50%;
transform: translate(-50%, 0);
width: 35%;
height: 35%;
background-color: #000;
border-radius: 50%;
}
}
}
> .input {
margin-left: 5px;
font-size: 14px;
color: #000;
flex: 1;
// min-width: 45px;
// max-width: 80px;
// width: 50px;
> input {
width: 100%;
border-radius: 3px;
outline: none;
}
}
}
</style>

View File

@@ -0,0 +1,66 @@
<template>
<a-select
class="my-select"
:size="size"
@change="change"
:defaultValue="defaultValue"
@dropdownVisibleChange="dropdownVisibleChange"
>
<a-select-option
v-for="v in list"
:key="v.value"
:value="v.value"
:title="v.tip"
@mouseover.stop.prevent="mouseover(v)"
@mouseleave="mouseleave(v)"
>{{ v.label }}</a-select-option
>
</a-select>
</template>
<script setup lang="ts">
import { ref, defineProps, defineEmits, watch } from "vue";
const props = defineProps({
defaultValue: {
default: "",
},
list: {
type: Array,
default: () => [],
},
size: {
type: String,
default: "small",
},
});
const emit = defineEmits(["change", "active"]);
const isChange = ref(false);
const initValue = ref(props.defaultValue);
const activeValue = ref(props.defaultValue);
const timeout = ref(null);
const mouseover = (v) => {
clearTimeout(timeout.value);
if (v.value === activeValue.value) return;
emit("active", v.value, activeValue.value);
activeValue.value = v.value;
};
const mouseleave = () => {
clearTimeout(timeout.value);
timeout.value = setTimeout(() => {
dropdownVisibleChange(false);
}, 100);
};
const change = (v) => {
isChange.value = true;
emit("change", v, initValue.value);
};
const dropdownVisibleChange = (v) => {
if (v) {
isChange.value = false;
initValue.value = props.defaultValue;
} else if (!isChange.value) {
emit("active", initValue.value, activeValue.value);
activeValue.value = initValue.value;
}
};
</script>

View File

@@ -0,0 +1,190 @@
<template>
<div class="offset-tool">
<div
class="dish"
@mousedown="mousedown"
@touchstart="mousedown"
ref="dishRef"
>
<span
:style="{ top: data.top + '%', left: data.left + '%' }"
></span>
</div>
<input
class="top"
type="range"
:min="0"
:max="100"
:step="0.1"
v-model="data.top"
@input="onInput"
@change="onChange"
/>
<input
class="left"
type="range"
:min="0"
:max="100"
:step="0.1"
v-model="data.left"
@input="onInput"
@change="onChange"
/>
<span class="tip"
>x:{{ tofix(data.left) }}% y:{{ tofix(data.top) }}%</span
>
</div>
</template>
<script setup lang="ts">
import { ref, defineProps, defineEmits, watch } from "vue";
const props = defineProps({
top: {
type: Number,
default: 50,
},
left: {
type: Number,
default: 50,
},
});
const tofix = (v: number | string) => Number(Number(v).toFixed(1));
const emit = defineEmits(["change", "input"]);
const data = reactive({
top: tofix(props.top),
left: tofix(props.left),
});
watch(
() => props.top,
(v) => (data.top = tofix(v))
);
watch(
() => props.left,
(v) => (data.left = tofix(v))
);
const dishRef = ref<HTMLDivElement>();
const mousedown = (e: MouseEvent | TouchEvent) => {
if (!dishRef.value) return;
const mousemove = (e: MouseEvent | TouchEvent) => {
if (!dishRef.value) return;
const { left, top, width, height } =
dishRef.value.getBoundingClientRect();
const X = e.clientX || (e as TouchEvent).touches[0].clientX;
const Y = e.clientY || (e as TouchEvent).touches[0].clientY;
var x = ((X - left) / width) * 100;
var y = ((Y - top) / height) * 100;
if (x < 0) x = 0;
if (x > 100) x = 100;
if (y < 0) y = 0;
if (y > 100) y = 100;
data.left = tofix(x);
data.top = tofix(y);
onInput();
};
mousemove(e);
const mouseup = () => {
onChange();
document.removeEventListener("mousemove", mousemove);
document.removeEventListener("touchmove", mousemove);
document.removeEventListener("mouseup", mouseup);
document.removeEventListener("touchend", mouseup);
};
document.addEventListener("mousemove", mousemove);
document.addEventListener("touchmove", mousemove);
document.addEventListener("mouseup", mouseup);
document.addEventListener("touchend", mouseup);
};
const onInput = () => emit("input", { ...data });
var changeTime: any = null;
const onChange = () => {
clearTimeout(changeTime);
changeTime = setTimeout(() => emit("change", { ...data }), 500);
};
// var offsetTime = null;
// watch(data, (v) => {
// const obj = { ...v };
// emit("input", obj);
// clearTimeout(offsetTime);
// offsetTime = setTimeout(() => emit("change", obj), 50);
// });
// defineExpose({
// open,
// close,
// });
</script>
<style scoped lang="less">
.offset-tool {
width: 125px;
height: 125px;
display: flex;
position: relative;
overflow: hidden;
--gap: 15px;
> .dish {
margin: var(--gap) 0 0 var(--gap);
flex: 1;
border: 1px solid #000;
border-radius: 5px;
cursor: pointer;
position: relative;
background-color: #fff;
> span {
pointer-events: none;
user-select: none;
position: absolute;
top: 0%;
left: 0%;
transform: translate(-50%, -50%);
width: 8px;
height: 8px;
background-color: #000;
border-radius: 50%;
}
}
> .tip {
position: absolute;
right: 4px;
bottom: 0;
font-size: 10px;
pointer-events: none;
user-select: none;
color: #666;
}
> input.left {
right: 0;
}
> input.top {
bottom: 0;
left: 0;
transform-origin: left bottom;
transform: rotate(90deg) translateX(-100%);
}
> input {
position: absolute;
width: calc(100% - var(--gap));
-webkit-appearance: none;
appearance: none;
height: 8px;
border-radius: 8px;
background: rgba(0, 0, 0, 0.1); /* 更柔和的颜色 */
// outline: none;
&::-webkit-slider-thumb {
-webkit-appearance: none;
appearance: none;
width: 8px;
height: 8px;
border-radius: 50%;
background: #4285f4; /* 蓝色滑块 */
cursor: pointer;
transition: all 0.2s;
box-shadow: 0 1px 2px rgba(0, 0, 0, 0.1);
}
&::-webkit-slider-thumb:hover {
background: #3b77db;
transform: scale(1.1);
}
}
}
</style>

View File

@@ -0,0 +1,160 @@
<template>
<div class="slider">
<div class="input-range">
<span
class="tip"
:style="{
'--progress': (value - props.min) / (props.max - props.min),
}"
>{{ props.tipFormatter(value) }}</span
>
<input
type="range"
v-model="value"
:min="props.min"
:max="props.max"
:step="props.step"
@input="onInput"
@change="onChange"
/>
</div>
<div class="input" v-show="isInput">
<input
type="number"
v-model="value"
:min="props.min"
:max="props.max"
:step="props.step"
@input="onInput"
@change="onChange"
/>
</div>
</div>
</template>
<script setup lang="ts">
import { ref, defineProps, defineEmits, watch } from "vue";
const props = defineProps({
value: {
type: Number,
default: 0,
},
min: {
type: Number,
default: 0,
},
max: {
type: Number,
default: 100,
},
step: {
type: Number,
default: 1,
},
tipFormatter: {
type: Function,
default: (v) => v,
},
isInput: {
type: Boolean,
default: false,
},
});
const emit = defineEmits(["change", "input"]);
const value = ref(props.value);
watch(
() => props.value,
(v) => (value.value = v)
);
const onInput = () => emit("input", Number(value.value));
var changeTime: any = null;
const onChange = () => {
clearTimeout(changeTime);
changeTime = setTimeout(() => emit("change", Number(value.value)), 500);
};
</script>
<style scoped lang="less">
.slider {
position: relative;
display: flex;
align-items: center;
--input-thumb-size: 12px;
width: 150px;
// &:focus-within,
&:hover {
> .input-range > .tip {
display: block;
}
}
> .input-range {
position: relative;
flex: 2;
> input {
width: 100%;
-webkit-appearance: none;
appearance: none;
height: 5px;
border-radius: 5px;
background: rgba(0, 0, 0, 0.1); /* 更柔和的颜色 */
outline: none;
&::-webkit-slider-thumb {
-webkit-appearance: none;
appearance: none;
width: var(--input-thumb-size);
height: var(--input-thumb-size);
border-radius: 50%;
background: #4285f4; /* 蓝色滑块 */
cursor: pointer;
transition: all 0.2s;
box-shadow: 0 1px 2px rgba(0, 0, 0, 0.1);
}
&::-webkit-slider-thumb:hover {
background: #3b77db;
transform: scale(1.1);
}
}
> .tip {
position: absolute;
font-size: 10px;
pointer-events: none;
user-select: none;
color: #666;
top: 0;
left: calc(
(100% - var(--input-thumb-size)) * var(--progress) +
var(--input-thumb-size) / 2
);
transform: translate(-50%, -100%);
background-color: rgba(0, 0, 0, 0.7);
color: white;
padding: 0.4rem 0.8rem;
border-radius: 0.4rem;
font-size: 1.2rem;
white-space: nowrap;
pointer-events: none;
display: none;
&::after {
content: "";
position: absolute;
top: 97%;
left: 50%;
transform: translateX(-50%);
width: 0;
height: 0;
border-left: 5px solid transparent;
border-right: 5px solid transparent;
border-top: 5px solid rgba(0, 0, 0, 0.8);
}
}
}
> .input {
flex: 1;
margin-left: 10px;
> input {
border-radius: 3px;
width: 100%;
}
}
}
</style>

View File

@@ -4,9 +4,9 @@
<div class="back" v-show="isEditPattern.value"> <div class="back" v-show="isEditPattern.value">
<i class="fi fi-br-angle-left" @click="setBack"></i> <i class="fi fi-br-angle-left" @click="setBack"></i>
</div> </div>
<modelNav @canvasReload="()=>$emit('canvasReload')" @addSketch="()=>$emit('addSketch')" @sketchSysToLibrary="()=>$emit('sketchSysToLibrary')" @deleteItem="deleteItem"></modelNav> <modelNav ref="modelNav" @canvasReload="()=>$emit('canvasReload')" @addSketch="()=>$emit('addSketch')" @sketchSysToLibrary="()=>$emit('sketchSysToLibrary')" @deleteItem="deleteItem"></modelNav>
</div> </div>
<div class="modelindex_right"> <div class="modelindex_right" ref="modelindexRight">
<div class="detail_btn"> <div class="detail_btn">
<!-- 全屏 --> <!-- 全屏 -->
<!-- <i class="fi fi-bs-expand-arrows-alt" @click="showDesignImgDetail('2')"></i> --> <!-- <i class="fi fi-bs-expand-arrows-alt" @click="showDesignImgDetail('2')"></i> -->
@@ -14,7 +14,7 @@
<i class="icon iconfont icon-chehui" @click="revocation"></i> <i class="icon iconfont icon-chehui" @click="revocation"></i>
<i class="icon iconfont icon-fanchehui" @click="oppositeRevocation"></i> <i class="icon iconfont icon-fanchehui" @click="oppositeRevocation"></i>
<!-- 编辑 --> <!-- 编辑 -->
<i class="fi fi-rs-pencil-paintbrush" :title="$t('DesignDetail.editSketchTitle')" :class="{'pointerEventsNone':!selectDetail?.id}" @click="()=>$emit('addDetail')"></i> <i class="fi fi-rs-pencil-paintbrush" :title="$t('DesignDetail.editSketchTitle')" :class="{'pointerEventsNone':!selectDetail?.id,active:isEditPattern.value == 'editSketch'}" @click="showDesignImgDetail('editSketch')"></i>
<i class="fi fi-rr-edit" :title="$t('DesignDetail.editTitle')" :class="{active:isEditPattern.value == 'canvasEditor','pointerEventsNone':!selectDetail?.id}" @click="showDesignImgDetail('canvasEditor')"></i> <i class="fi fi-rr-edit" :title="$t('DesignDetail.editTitle')" :class="{active:isEditPattern.value == 'canvasEditor','pointerEventsNone':!selectDetail?.id}" @click="showDesignImgDetail('canvasEditor')"></i>
<i class="icon iconfont icon-clothes" :title="$t('Canvas.editFrontBack')" style="font-size: 3.2rem;" @click="showDesignImgDetail('redGreenExample')" :class="{active:isEditPattern.value == 'redGreenExample','pointerEventsNone':!selectDetail?.id}"></i> <i class="icon iconfont icon-clothes" :title="$t('Canvas.editFrontBack')" style="font-size: 3.2rem;" @click="showDesignImgDetail('redGreenExample')" :class="{active:isEditPattern.value == 'redGreenExample','pointerEventsNone':!selectDetail?.id}"></i>
@@ -51,7 +51,7 @@ export default defineComponent({
components:{ components:{
position,modelNav position,modelNav
}, },
emits:['detailEdit','canvasReload','addSketch','revocation','oppositeRevocation','modelOnLoad','sketchSysToLibrary','addDetail'], emits:['detailEdit','canvasReload','addSketch','revocation','oppositeRevocation','modelOnLoad','sketchSysToLibrary'],
setup(props,{emit}) { setup(props,{emit}) {
const {t} = useI18n() const {t} = useI18n()
const store = useStore(); const store = useStore();
@@ -68,36 +68,40 @@ export default defineComponent({
const getDetailListDom = reactive({ const getDetailListDom = reactive({
libraryList:null as any, libraryList:null as any,
position:null as any, position:null as any,
modelindexRight:null as any,
modelNav:null as any,
}) })
const getSubmitData = (value:any,boolean)=>{ const getSubmitData = (value:any,boolean)=>{
return getDetailListDom.position.getSubmitData(value,boolean) return getDetailListDom.position.getSubmitData(value,boolean)
} }
const showDesignImgDetail = (str:any)=>{ const showDesignImgDetail = (str:any)=>{
new Promise((resolve, reject) => {
if(
getDetailListData.isEditPattern.value&&
detailData?.getCanvasIfEdit?.fun&&detailData?.getCanvasIfEdit?.fun() > 0
){
Modal.confirm({
title: t('collectionModal.jsContent2'),
icon: createVNode(ExclamationCircleOutlined),
okText: 'Yes',
cancelText: 'No',
mask:false,
centered:true,
onOk() {
resolve(true)
emit('detailEdit',str) emit('detailEdit',str)
},
onCancel(){ // new Promise((resolve, reject) => {
resolve(false) // if(
} // getDetailListData.isEditPattern.value&&
}); // detailData?.getCanvasIfEdit?.fun&&detailData?.getCanvasIfEdit?.fun() > 0
}else{ // ){
resolve(true) // Modal.confirm({
emit('detailEdit',str) // title: t('collectionModal.jsContent2'),
} // icon: createVNode(ExclamationCircleOutlined),
}) // okText: 'Yes',
// cancelText: 'No',
// mask:false,
// centered:true,
// onOk() {
// resolve(true)
// emit('detailEdit',str)
// },
// onCancel(){
// resolve(false)
// }
// });
// }else{
// resolve(true)
// emit('detailEdit',str)
// }
// })
} }
const deleteItem = ()=>{ const deleteItem = ()=>{
setRevocation() setRevocation()
@@ -121,18 +125,25 @@ export default defineComponent({
clearTimeout(time) clearTimeout(time)
time = setTimeout(()=>{ time = setTimeout(()=>{
store.commit('DesignDetail/setDesignDetail',getDetailListData.designDetail) store.commit('DesignDetail/setDesignDetail',getDetailListData.designDetail)
getDetailListDom.position.updataPosition() getDetailListDom.position?.updataPosition?.()
getDetailListDom.modelNav?.setItemPosition?.()
},1000) getDetailListDom.position?.updateRect?.()
},500)
} }
const setBack = ()=>{ const setBack = ()=>{
emit('detailEdit') showDesignImgDetail(getDetailListData.isEditPattern.value)
} }
let observers = null as any
onMounted(()=>{ onMounted(()=>{
window.addEventListener('resize', handleResize); observers = new ResizeObserver(entries => {
for (let entry of entries) {
handleResize()
}
});
observers.observe(getDetailListDom.modelindexRight);
}) })
onBeforeUnmount(()=>{ onBeforeUnmount(()=>{
window.removeEventListener('resize', handleResize); observers.disconnect();
}) })
return{ return{
...toRefs(detailData), ...toRefs(detailData),

View File

@@ -268,17 +268,8 @@ export default defineComponent({
let allPostition = store.state.Workspace.workspaceAllPosition let allPostition = store.state.Workspace.workspaceAllPosition
return allPostition.find(item => item.value === type)?.name return allPostition.find(item => item.value === type)?.name
} }
let observers = null as any
onMounted(()=>{
observers = new ResizeObserver(entries => {
for (let entry of entries) {
setItemPosition()
}
});
observers.observe(detailData.modelNavBox);
})
onBeforeUnmount(()=>{ onBeforeUnmount(()=>{
observers.disconnect();
}) })
return{ return{
...toRefs(detailData), ...toRefs(detailData),

View File

@@ -1,21 +1,17 @@
<template> <template>
<div class="molepositon" :class="{active:!imgDesignImg}"> <div class="molepositon" :class="{active:!imgDesignImg}">
<div class="designOpenrtion_imgMask" v-if="frontBack?.body?.path" :style="frontBack?.body?.style"> <div class="designOpenrtion_imgMask" v-if="frontBack?.body?.path" :style="frontBack?.body?.style">
<div class="designOpenrtion_print" v-for="item,index in frontBack.back" @mousedown.stop="itemMoveMousedown(index,getMousePosition($event,false))" @touchstart.passive="itemMoveMousedown(index,getMousePosition($event,true))" @click="setpitch(item,index)" :style="frontBack.front[index].style"> <div class="designOpenrtion_print" v-for="item,index in frontBack.back" :style="frontBack.front[index].style">
<img :style="item.imageUrl?'':'display:none;'" :src="item.imageUrl" alt=""> <img :style="item.imageUrl?'':'display:none;'" :src="item.imageUrl" alt="">
</div> </div>
<img class="perview_img" @load="setPrintSize()" ref="detailBody" :key="designDetail.designItemId" :src="frontBack?.body?.path" :style="'width:'+ frontBack?.body?.layersObject?.[0].imageSize?.[0] +';height:' + frontBack?.body?.layersObject?.[0].imageSize?.[0] +';'"> <img class="perview_img" @load="setPrintSize()" ref="detailBody" :key="designDetail.designItemId" :src="frontBack?.body?.path" :style="'width:'+ frontBack?.body?.layersObject?.[0].imageSize?.[0] +';height:' + frontBack?.body?.layersObject?.[0].imageSize?.[0] +';'">
<div class="detail_modal_item_front" v-for="item,index in frontBack.front" @mousedown.stop="itemMoveMousedown(index,getMousePosition($event,false))" @touchstart.passive="itemMoveMousedown(index,getMousePosition($event,true))" @click="setpitch(item,index)" :style="item.style"> <!-- <div class="detail_modal_item_front" ref="target" v-for="item,index in frontBack.front" @mousedown.stop="itemMoveMousedown(index,getMousePosition($event,false))" @touchstart.passive="itemMoveMousedown(index,getMousePosition($event,true))" @click="setpitch(item,index)" :style="item.style">
<img :src="item.imageUrl" alt="">
</div> -->
<div class="detail_modal_item_front" :ref="el => { setElementRef(el, index) }" v-for="item,index in frontBack.front" :class="{'active':item.id == selectDetail?.id}" :style="item.style">
<img :src="item.imageUrl" alt=""> <img :src="item.imageUrl" alt="">
</div> </div>
<div class="designOpenrtion_btnBox"> <div ref="moveableContainer" class="moveableContainer"></div>
<ul v-for="item,index in frontBack.front" :key="item" :class="{active:item.designOpenrtionBtn}" class="designOpenrtion_btn" :style="item.style" @mousedown.stop="itemMoveMousedown(index,getMousePosition($event,false))" @touchstart.passive="itemMoveMousedown(index,getMousePosition($event,true))">
<li class="designOpenrtion_btn_top" @mousedown.stop="itemSizeMousedown('top',getMousePosition($event,false))" @touchstart.passive="itemSizeMousedown('top',getMousePosition($event,true))"></li>
<li class="designOpenrtion_btn_bottom" @mousedown.stop="itemSizeMousedown('bottom',getMousePosition($event,false))" @touchstart.passive="itemSizeMousedown('bottom',getMousePosition($event,true))"></li>
<li class="designOpenrtion_btn_left" @mousedown.stop="itemSizeMousedown('left',getMousePosition($event,false))" @touchstart.passive="itemSizeMousedown('left',getMousePosition($event,true))"></li>
<li class="designOpenrtion_btn_right" @mousedown.stop="itemSizeMousedown('right',getMousePosition($event,false))" @touchstart.passive="itemSizeMousedown('right',getMousePosition($event,true))"></li>
</ul>
</div>
</div> </div>
<div class="designOpenrtion_imgMask" v-if="!frontBack?.body?.path"> <div class="designOpenrtion_imgMask" v-if="!frontBack?.body?.path">
<img :src="selectDetail?.undividedLayerWithSinglePrint || selectDetail?.undividedLayer || selectDetail?.path" style="object-fit: cover;" alt=""> <img :src="selectDetail?.undividedLayerWithSinglePrint || selectDetail?.undividedLayer || selectDetail?.path" style="object-fit: cover;" alt="">
@@ -40,8 +36,10 @@ import { Https } from "@/tool/https";
import { useStore } from "vuex"; import { useStore } from "vuex";
import { useI18n } from 'vue-i18n' import { useI18n } from 'vue-i18n'
import { getMousePosition } from "@/tool/mdEvent"; import { getMousePosition } from "@/tool/mdEvent";
import { Modal,message } from 'ant-design-vue'; import Vue3Moveable from 'vue3-moveable';
import newFollowVue from '@/component/Account/message/newFollow.vue'; import Moveable from 'moveable';
import { parse } from 'vue/compiler-sfc';
import { scale } from 'echarts/types/src/scale/helper.js';
export default defineComponent({ export default defineComponent({
components:{ components:{
}, },
@@ -75,10 +73,7 @@ export default defineComponent({
imgDom:null as any, imgDom:null as any,
direction:'', direction:'',
}) })
watch(()=>selectItem.selectDetail,(newValue,oldValue)=>{
if(!newValue && newValue?.id == oldValue?.id)return
selectItem.imgDomIndex = detailData.frontBack.front.findIndex((item:any)=>item.id == newValue.id)
},{immediate: true,})
watch(()=>detailData.frontBack?.body?.path,(newVal)=>{ watch(()=>detailData.frontBack?.body?.path,(newVal)=>{
setPrintSize() setPrintSize()
}) })
@@ -99,7 +94,6 @@ export default defineComponent({
if(entries[0].contentRect.width == 0)return if(entries[0].contentRect.width == 0)return
detailData.observerWH.width = Math.floor(entries[0].contentRect.width) detailData.observerWH.width = Math.floor(entries[0].contentRect.width)
detailData.observerWH.height = Math.floor(entries[0].contentRect.height) detailData.observerWH.height = Math.floor(entries[0].contentRect.height)
console.log(detailData.observerWH)
}) })
detailData.observer.observe(dom) detailData.observer.observe(dom)
@@ -131,6 +125,7 @@ export default defineComponent({
} }
for (const key in detailData.frontBack.back[index].style) { for (const key in detailData.frontBack.back[index].style) {
if(key == 'zIndex')return if(key == 'zIndex')return
if(key == 'transform')return
let value = detailData.frontBack.back[index].style[key] let value = detailData.frontBack.back[index].style[key]
if(typeof value !== 'number'){ if(typeof value !== 'number'){
value = value.replace('px','') value = value.replace('px','')
@@ -143,6 +138,7 @@ export default defineComponent({
}); });
setTimeout(() => { setTimeout(() => {
emit('modelOnLoad') emit('modelOnLoad')
initMoveableForSelected()
},500); },500);
}; };
img.src = detailData.frontBack?.body?.path; img.src = detailData.frontBack?.body?.path;
@@ -150,203 +146,280 @@ export default defineComponent({
} }
const getDetailListDom = reactive({ const getDetailListDom = reactive({
libraryList:null as any, libraryList:null as any,
moveableContainer:null as any,//控件层
}) })
//设置尺寸 const elementRefs = ref([]) as any;
const itemSizeMousedown = (direction:any,event:any)=>{ const moveableInstance = ref(null) as any;
selectItem.direction = direction const setElementRef = (el, index) => {
selectItem.imgDom = document.getElementsByClassName('molepositon')[0].getElementsByClassName("detail_modal_item_front")[selectItem.imgDomIndex] elementRefs.value[index] = el;
detailData.frontBack.front[selectItem.imgDomIndex].designOpenrtionBtn = true };
let imgDomWH = selectItem.imgDom.getBoundingClientRect() const updateRect = ()=>{
let li = (document.getElementsByClassName('molepositon')[0].getElementsByClassName("designOpenrtion_btn_top")[0] as any).offsetWidth/2 setTimeout(() => {
if(selectItem.direction == 'right' || selectItem.direction == 'bottom'){ moveableInstance.value.updateRect()
detailData.frontBack.front[selectItem.imgDomIndex].centers.left = imgDomWH.x+event.offsetX-li }, 500);
detailData.frontBack.front[selectItem.imgDomIndex].centers.top = imgDomWH.y+event.offsetY-li }
const initMoveableForSelected = () => {
// 销毁旧的实例
if(selectItem.imgDomIndex == -1)return
if (moveableInstance.value) {
moveableInstance.value.destroy();
}
const selectedEl = elementRefs.value[selectItem.imgDomIndex];
if (!selectedEl) return;
if(!selectedEl.style.left)return
moveableInstance.value = new Moveable(getDetailListDom.moveableContainer, {
target: selectedEl,
draggable: true,
scalable: true,
rotatable: true,
keepRatio: false, // 等比缩放
snappable: true,
snapThreshold: 5,
edge: false,
});
let startPosition = {//记录初始位置
left: 0,
top: 0,
}
moveableInstance.value.on('scaleStart', ({ target, direction }) => {
const frontStyle = detailData.frontBack.front[selectItem.imgDomIndex];
if (!frontStyle.mirror){
let scaleX = frontStyle.style.transform.match(/scaleX\(([-\d.]+)\)/);
let scaleY = frontStyle.style.transform.match(/scaleY\(([-\d.]+)\)/);
frontStyle.mirror = { x: scaleX[1] == '-1' ? true : false, y: scaleY[1] == '-1' ? true : false };
}
});
moveableInstance.value.on('rotateStart', ({ target, direction }) => {
const frontStyle = detailData.frontBack.front[selectItem.imgDomIndex];
if (!frontStyle.mirror){
let scaleX = frontStyle.style.transform.match(/scaleX\(([-\d.]+)\)/);
let scaleY = frontStyle.style.transform.match(/scaleY\(([-\d.]+)\)/);
frontStyle.mirror = { x: scaleX[1] == '-1' ? true : false, y: scaleY[1] == '-1' ? true : false };
}
});
moveableInstance.value.on('dragStart', ({ target, clientX, clientY }) => {
startPosition = {
left:parseFloat(selectedEl.style.left.replace('px','')) || 0,
top:parseFloat(selectedEl.style.top.replace('px','')) || 0,
}
});
// 拖拽
moveableInstance.value.on('drag', ({ target, beforeTranslate }) => {
let x = startPosition.left + beforeTranslate[0]
let y = startPosition.top + beforeTranslate[1]
detailData.frontBack.front[selectItem.imgDomIndex].style.left = x + 'px'
detailData.frontBack.front[selectItem.imgDomIndex].style.top = y + 'px'
});
const updateElementTransform = (element, rotateDeg = null) => {
const currentTransform = element.style?.transform || '';
// 1. 提取当前的所有rotate
const currentRotates = (currentTransform.match(/rotate[XYZ]?\([^)]+\)/g) || []);
// 2. 获取除镜像和rotate外的其他所有变换
let otherTransforms = currentTransform
.replace(/scaleX\(-1\)|scaleY\(-1\)/g, '') // 移除镜像
.replace(/rotate[XYZ]?\([^)]+\)/g, '') // 移除rotate
.replace(/\s+/g, ' ')
.trim();
// 3. 构建新transform
const transforms = [];
// 镜像部分
if (element.mirror.x) transforms.push('scaleX(-1)');
if (element.mirror.y) transforms.push('scaleY(-1)');
if (otherTransforms) transforms.push(otherTransforms);
if (rotateDeg !== null) {
transforms.push(`rotate(${rotateDeg}deg)`);
} else if (currentRotates.length > 0) {
transforms.push(...currentRotates);
}
element.style.transform = transforms.join(' ').trim();
};
moveableInstance.value.on('scale', ({ target, delta, direction }) => {
const frontStyle = detailData.frontBack.front[selectItem.imgDomIndex];
if (!frontStyle.mirror) frontStyle.mirror = { x: false, y: false };
const width = parseFloat(frontStyle.style.width);
const height = parseFloat(frontStyle.style.height);
let left = parseFloat(frontStyle.style.left) || 0;
let top = parseFloat(frontStyle.style.top) || 0;
let rotation = 0;
// 获取原始比例
const originalRatio = width / height;
if (frontStyle.style.transform) {
const transform = frontStyle.style.transform;
const match = transform.match(/rotate\(([-\d.]+)deg\)/);
if (match) {
rotation = parseFloat(match[1]);
}
}
// 根据旋转角度重新计算控制点的方向
function getAdjustedCorner(originalCorner, rotationAngle) {
const angleRad = rotationAngle * (Math.PI / 180);
const cosA = Math.cos(angleRad);
const sinA = Math.sin(angleRad);
const newX = originalCorner.x * cosA - originalCorner.y * sinA;
const newY = originalCorner.x * sinA + originalCorner.y * cosA;
const threshold = 0.5;
return {
x: Math.abs(newX) > threshold ? (newX > 0 ? 1 : -1) : 0,
y: Math.abs(newY) > threshold ? (newY > 0 ? 1 : -1) : 0
};
}
if (rotation !== 0) {
direction = getAdjustedCorner({x: direction[0], y: direction[1]}, rotation);
direction = [direction.x, direction.y];
}
// 判断是否是对角线方向(需要等比缩放)
const isDiagonal = Math.abs(direction[0]) === 1 && Math.abs(direction[1]) === 1;
// 处理轴缩放,包含镜像翻转逻辑
const processAxis = (axis, val, deltaVal, dir, originalPosition, originalSize, keepRatio = false, otherAxisResult = null) => {
let newVal = val * deltaVal;
const mirrorKey = axis === 'width' ? 'x' : 'y';
const isWidth = axis === 'width';
// 检查是否需要镜像翻转当值小于等于0时
if (newVal <= 0) {
frontStyle.mirror[mirrorKey] = !frontStyle.mirror[mirrorKey];
newVal = Math.abs(newVal);
updateElementTransform(frontStyle);
// 镜像翻转后,位置需要根据原始锚点调整
if (dir === -1) {
// 从左上/右上缩放时,位置保持不变
return {
newVal,
adjustPos: originalPosition,
shouldFlip: true
};
} else { } else {
detailData.frontBack.front[selectItem.imgDomIndex].centers.left = imgDomWH.x+event.offsetX+imgDomWH.width-li // 从左下/右下缩放时,位置需要调整
detailData.frontBack.front[selectItem.imgDomIndex].centers.top = imgDomWH.y+event.offsetY+imgDomWH.height-li const newPosition = originalPosition + (originalSize - newVal) * (frontStyle.mirror[mirrorKey] ? -1 : 1);
return {
newVal,
adjustPos: newPosition,
shouldFlip: true
};
}
}
const shouldMove = (!frontStyle.mirror[mirrorKey] && dir === -1) ||
(frontStyle.mirror[mirrorKey] && dir === 1);
if (keepRatio && otherAxisResult) {
newVal = isWidth ?
otherAxisResult.newVal * originalRatio :
otherAxisResult.newVal / originalRatio;
}
let adjustPos;
if (shouldMove) {
adjustPos = originalPosition - (newVal - originalSize);
} else {
adjustPos = originalPosition;
}
return {
newVal,
adjustPos,
shouldFlip: false
};
};
// 自由缩放
const widthResult = processAxis('width', width, delta[0], direction[0], left, width);
const heightResult = processAxis('height', height, delta[1], direction[1], top, height);
frontStyle.style.left = widthResult.adjustPos + 'px';
frontStyle.style.top = heightResult.adjustPos + 'px';
frontStyle.style.width = widthResult.newVal + 'px';
frontStyle.style.height = heightResult.newVal + 'px';
// }
});
// 旋转
moveableInstance.value.on('rotate', ({ target, beforeRotate }) => {
let frontStyle = detailData.frontBack.front[selectItem.imgDomIndex];
// 确保镜像状态存在
if (!frontStyle.mirror) frontStyle.mirror = { x: false, y: false };
const { x: isMirroredX, y: isMirroredY } = frontStyle.mirror;
// 计算实际旋转角度
let actualRotate = beforeRotate;
// 关键逻辑当镜像状态不同时一个true一个false旋转方向反转
if (isMirroredX !== isMirroredY) {
actualRotate = -beforeRotate;
} }
document.addEventListener('mousemove', sizeMouseMove); // 确保角度在 0-360 度范围内
document.addEventListener('touchmove', sizeTouchmove); actualRotate = actualRotate % 360;
document.addEventListener('mouseup', sizeMouseup);
document.addEventListener('touchend', sizeMouseup);
}
const sizeMouseMove = (event:any)=>{
let e = getMousePosition(event,false)
sizeMouseMoveOperation(e)
}
const sizeTouchmove = (event:any)=>{
let e = getMousePosition(event,true)
sizeMouseMoveOperation(e)
// 如果角度为负数,转换为正数
if (actualRotate < 0) {
actualRotate += 360;
} }
const sizeMouseup = (e:any)=>{
detailData.frontBack.front[selectItem.imgDomIndex].style={ // 确保角度在 [0, 360) 范围内
right:'auto', actualRotate = ((actualRotate % 360) + 360) % 360;
left:selectItem.imgDom.offsetLeft+'px',
bottom:'auto', updateElementTransform(frontStyle, actualRotate.toFixed(2));
top:selectItem.imgDom.offsetTop+'px', });
height:selectItem.imgDom.offsetHeight+'px', // 调整大小
width:selectItem.imgDom.offsetWidth+'px', moveableInstance.value.on('resize', ({ target, width, height }) => {
zIndex:selectItem.imgDom.style.zIndex, // console.log(width, height)
// zIndex:selectItem.printZIndex // detailData.frontBack.front[selectItem.imgDomIndex].style.width = width
// detailData.frontBack.front[selectItem.imgDomIndex].style.height = height
});
moveableInstance.value.on('dragEnd', ({ target, clientX, clientY }) => {
startPosition = {
left:0,
top:0,
} }
// detailData.frontBack.back[selectItem.imgDomIndex].style.zIndex = selectItem.printZIndex upDataDetail()
document.removeEventListener('mousemove',sizeMouseMove) });
document.removeEventListener('touchmove',sizeTouchmove) moveableInstance.value.on('scaleEnd', () => {
document.removeEventListener('mouseup',sizeMouseup) upDataDetail()
document.removeEventListener('touchend',sizeMouseup) });
//鼠标抬起 moveableInstance.value.on('rotateEnd', () => {
setRevocation() upDataDetail()
} });
let isMove = false//表示是否移动,是否需要在鼠标抬起的时候保存数据 };
watch(()=>selectItem.selectDetail,(newValue,oldValue)=>{
if(!newValue && newValue?.id == oldValue?.id)return
selectItem.imgDomIndex = detailData.frontBack.front.findIndex((item:any)=>item.id == newValue.id)
initMoveableForSelected()
},{immediate: true,})
const setRevocation = ()=>{ const setRevocation = ()=>{
if(!isMove)return
isMove = false
let frontBack = JSON.parse(JSON.stringify(detailData.frontBack)) let frontBack = JSON.parse(JSON.stringify(detailData.frontBack))
console.log(frontBack)
let revocation:any = JSON.parse((sessionStorage.getItem("revocation") as any)) let revocation:any = JSON.parse((sessionStorage.getItem("revocation") as any))
revocation.push({designData:null,position:frontBack}) revocation.push({designData:null,position:frontBack})
sessionStorage.setItem('revocation', JSON.stringify(revocation)); sessionStorage.setItem('revocation', JSON.stringify(revocation));
} }
const sizeMouseMoveOperation = (e:any)=> { const upDataDetail = async ()=>{
isMove = true //同步到selectDetail数据中
let imgDomWH = selectItem.imgDom.getBoundingClientRect() // getDetailListData.designDetail
let parentNode =selectItem.imgDom.parentNode let {scale,offset,priority,transpose,rotate,position,imageSize} = await getSubmitData(selectItem.selectDetail,false)
let width = imgDomWH.width selectItem.selectDetail.layersObject[0].scale = scale
let height = imgDomWH.height selectItem.selectDetail.layersObject[1].scale = scale
let w,h selectItem.selectDetail.layersObject[0].offset = offset
let num = height/width selectItem.selectDetail.layersObject[1].offset = offset
//判断移动四个边 selectItem.selectDetail.layersObject[0].priority = priority
if(selectItem.direction == 'right'){ selectItem.selectDetail.layersObject[1].priority = priority
w = (e.clientX - detailData.frontBack.front[selectItem.imgDomIndex].centers.left) selectItem.selectDetail.layersObject[0].rotate = rotate
h = (e.clientX - detailData.frontBack.front[selectItem.imgDomIndex].centers.left)*num selectItem.selectDetail.layersObject[1].rotate = rotate
width = w+'px' selectItem.selectDetail.layersObject[0].transpose = transpose
// height = w*num+'px' selectItem.selectDetail.layersObject[1].transpose = transpose
}else if(selectItem.direction == 'top'){ selectItem.selectDetail.layersObject[0].position = position
num = width/height selectItem.selectDetail.layersObject[1].position = position
detailData.frontBack.front[selectItem.imgDomIndex].style.top = 'auto' selectItem.selectDetail.layersObject[0].imageSize = imageSize
// this.printStyleList[selectItem.imgDomIndex].style.left = 'auto' selectItem.selectDetail.layersObject[1].imageSize = imageSize
detailData.frontBack.front[selectItem.imgDomIndex].style.bottom = parentNode.offsetHeight -imgDomWH.height - selectItem.imgDom.offsetTop+'px'
w = (e.clientX - detailData.frontBack.front[selectItem.imgDomIndex].centers.left)*num
h = (detailData.frontBack.front[selectItem.imgDomIndex].centers.top - e.clientY)
height = h+'px'
// width = h*num+'px'
}else if(selectItem.direction == 'bottom'){
num = width/height
h = (e.clientY - detailData.frontBack.front[selectItem.imgDomIndex].centers.top)
height = h+'px'
// width = h*num+'px'
}else if(selectItem.direction == 'left'){
detailData.frontBack.front[selectItem.imgDomIndex].style.left = 'auto'
detailData.frontBack.front[selectItem.imgDomIndex].style.right = parentNode.offsetWidth -imgDomWH.width - selectItem.imgDom.offsetLeft+'px'
w = (detailData.frontBack.front[selectItem.imgDomIndex].centers.left - e.clientX)
width = w+'px'
// height = w*num+'px'
}
//判断尺寸是否到边
detailData.frontBack.front[selectItem.imgDomIndex].style.width = width
detailData.frontBack.front[selectItem.imgDomIndex].style.height = height
}
// 设置移动
const mouseMove = (event:any)=>{
let e = getMousePosition(event,false)
mouseMoveOperation(e)
}
const touchmove=(event:any)=>{
let e = getMousePosition(event,true)
mouseMoveOperation(e)
}
const mouseup = (e:any)=> {
document.removeEventListener('mousemove',mouseMove)
document.removeEventListener('touchmove',touchmove)
document.removeEventListener('mouseup',mouseup)
document.removeEventListener('touchend',mouseup)
///鼠标抬起
setRevocation() setRevocation()
} }
const mouseMoveOperation = (e:any)=>{
isMove = true
let imgDomWH = selectItem.imgDom.getBoundingClientRect()
let parentNode = document.getElementsByClassName('molepositon')[0].getElementsByClassName("designOpenrtion_imgMask")[0].getBoundingClientRect()
let x = (e.clientX - detailData.frontBack.front[selectItem.imgDomIndex].centers.left)+'px'
let y = ( e.clientY - detailData.frontBack.front[selectItem.imgDomIndex].centers.top)+'px'
detailData.frontBack.front[selectItem.imgDomIndex].style.left = x
detailData.frontBack.front[selectItem.imgDomIndex].style.top = y
}
const clothesOpenActive = (index:number)=>{
// this.designItemDetail.clothes.forEach((item)=>{
// item.clothesOpenItem = false
// })
// if(index != -1){
// this.designItemDetail.clothes[index].clothesOpenItem = true
// }
}
const itemMoveMousedown = async (index:any,e:any)=>{
if(detailData.selectDetail.id != detailData.frontBack.front[index].id)return
let isModal = false
await new Promise((resolve, reject) => {
// if(
// detailData.isEditPattern.value &&
// selectItem.selectDetail?.id &&
// (detailData.frontBack.front[index].id != selectItem.selectDetail.id)
// ){
// isModal = true
// Modal.confirm({
// title: t('collectionModal.jsContent2'),
// icon: createVNode(ExclamationCircleOutlined),
// okText: 'Yes',
// cancelText: 'No',
// mask:false,
// centered:true,
// onOk() {
// resolve(true)
// isOpen = true
// },
// onCancel(){
// resolve(false)
// isOpen = false
// }
// });
// }else{
// if(detailData.frontBack.front[index].id != selectItem.selectDetail.id){
// isOpen = true
// }
// resolve(true)
// isModal = false
// }
resolve(true)
}).then((rv)=>{
})
// emit('canvasReload')
// store.commit('DesignDetail/setDesignColthes',detailData.frontBack.front[index].id)
if(isModal)return
store.commit('DesignDetail/setDesignColthes',detailData.frontBack.front[index].id)
selectItem.imgDomIndex = index
detailData.frontBack.front.forEach((v:any)=>{
v.designOpenrtionBtn = false
})
clothesOpenActive(index)
let event = e||window.event
selectItem.imgDom = document.getElementsByClassName('molepositon')[0].getElementsByClassName("detail_modal_item_front")[selectItem.imgDomIndex]
detailData.frontBack.front[index].designOpenrtionBtn = true
// detailData.frontBack.front[index].style.zIndex = selectItem.printZIndex++
// detailData.frontBack.back[index].style.zIndex = selectItem.printZIndex
let imgDomWH = selectItem.imgDom.getBoundingClientRect()
let left = Number(detailData.frontBack.front[index].style.left.replace(/px/g,''))
let top = Number(detailData.frontBack.front[index].style.top.replace(/px/g,''))
detailData.frontBack.front[index].centers.left = imgDomWH.x+event.offsetX-left
detailData.frontBack.front[index].centers.top = imgDomWH.y+event.offsetY-top
document.addEventListener('mousemove', mouseMove);
document.addEventListener('touchmove', touchmove);
document.addEventListener('mouseup', mouseup);
document.addEventListener('touchend', mouseup);
}
const sort = (arr:any)=>{ const sort = (arr:any)=>{
arr.sort((a:any, b:any) => { arr.sort((a:any, b:any) => {
var a_num = a.style.zIndex; var a_num = a.style.zIndex;
@@ -355,7 +428,7 @@ export default defineComponent({
}); });
return arr return arr
} }
const getSubmitData = (value:any,isNoComputed)=>{ const getSubmitData = async (value:any,isNoComputed)=>{
let parentNode = document.getElementsByClassName('molepositon')[0].getElementsByClassName("designOpenrtion_imgMask")[0].getBoundingClientRect() let parentNode = document.getElementsByClassName('molepositon')[0].getElementsByClassName("designOpenrtion_imgMask")[0].getBoundingClientRect()
if(!detailData.frontBack?.body?.layersObject?.[0]?.imageSize || isNoComputed){ if(!detailData.frontBack?.body?.layersObject?.[0]?.imageSize || isNoComputed){
return{ return{
@@ -365,6 +438,17 @@ export default defineComponent({
} }
} }
let ratio = detailData.frontBack.body.layersObject[0].imageSize[0]/parentNode.width let ratio = detailData.frontBack.body.layersObject[0].imageSize[0]/parentNode.width
let scale = 0
let dom:any = document.querySelector('.molepositon .perview_img')
const img = new Image();
img.src = detailData.frontBack?.body?.path;
await new Promise<void>((resolve, reject) => {
img.onload = () => {
scale = dom.parentNode.offsetWidth / img.width
resolve()
};
})
// let arr:any = sort(detailData.frontBack.front) // let arr:any = sort(detailData.frontBack.front)
let arr:any = sort(JSON.parse(JSON.stringify(detailData.frontBack.front))) let arr:any = sort(JSON.parse(JSON.stringify(detailData.frontBack.front)))
let num = 10 let num = 10
@@ -377,6 +461,8 @@ export default defineComponent({
priority:'', priority:'',
maskUrl:'', maskUrl:'',
maskMinioUrl:'', maskMinioUrl:'',
position:null,
imageSize:null,
} }
let state = false let state = false
for (let index = 0; index < arr.length; index++) { for (let index = 0; index < arr.length; index++) {
@@ -384,13 +470,27 @@ export default defineComponent({
state = true state = true
let y = ((arr[index]?.style?.top.replace(/px/g,'')*ratio).toFixed(0) as any - arr[index]?.position[0]) let y = ((arr[index]?.style?.top.replace(/px/g,'')*ratio).toFixed(0) as any - arr[index]?.position[0])
let x = ((arr[index]?.style?.left.replace(/px/g,'')*ratio).toFixed(0) as any - arr[index]?.position[1]) let x = ((arr[index]?.style?.left.replace(/px/g,'')*ratio).toFixed(0) as any - arr[index]?.position[1])
let positionX = Number((arr[index]?.style?.left.replace(/px/g,'')/scale)).toFixed(2)
let positionY = Number((arr[index]?.style?.top.replace(/px/g,'')/scale)).toFixed(2)
let imageSizeW = Number((arr[index]?.style?.width.replace(/px/g,'')/scale)).toFixed(2)
let imageSizeH = Number((arr[index]?.style?.height.replace(/px/g,'')/scale)).toFixed(2)
let scaleWidth = arr[index]?.imageSize?Number(((arr[index]?.style?.width.replace(/px/g,'')*ratio)/(arr[index]?.imageSize[0]/arr[index].scale[0])).toFixed(2)):1 let scaleWidth = arr[index]?.imageSize?Number(((arr[index]?.style?.width.replace(/px/g,'')*ratio)/(arr[index]?.imageSize[0]/arr[index].scale[0])).toFixed(2)):1
let scaleHeight = arr[index]?.imageSize?Number(((arr[index]?.style?.height.replace(/px/g,'')*ratio)/(arr[index]?.imageSize[1]/arr[index].scale[1])).toFixed(2)):1 let scaleHeight = arr[index]?.imageSize?Number(((arr[index]?.style?.height.replace(/px/g,'')*ratio)/(arr[index]?.imageSize[1]/arr[index].scale[1])).toFixed(2)):1
// let widthScale = (arr[index].style.width.replace(/px/g,'')/arr[index].style.height.replace(/px/g,'')).toFixed(2) // let widthScale = (arr[index].style.width.replace(/px/g,'')/arr[index].style.height.replace(/px/g,'')).toFixed(2)
let transformStr = arr[index]?.style?.transform
let scaleX = transformStr.match(/scaleX\(([-\d.]+)\)/)
let scaleY = transformStr.match(/scaleY\(([-\d.]+)\)/)
let rotate = transformStr.match(/rotate\(([-\d.]+)deg\)/);
data.transpose = [parseFloat(scaleX?.[1] || 1),parseFloat(scaleY?.[1] || 1)]
data.rotate = parseFloat(rotate?.[1] || 0)
data.scale = [scaleWidth,scaleHeight] data.scale = [scaleWidth,scaleHeight]
let top = y == 0 ? value.layersObject[0].offset[1]:y+value.layersObject[0].offset[1] let top = y == 0 ? value.layersObject[0].offset[1]:y+value.layersObject[0].offset[1]
let left = x == 0 ? value.layersObject[0].offset[0]:x+value.layersObject[0].offset[0] let left = x == 0 ? value.layersObject[0].offset[0]:x+value.layersObject[0].offset[0]
data.offset = [left?left:0,top?top:0] data.offset = [left?left:0,top?top:0]
data.position = [positionY,positionX]
data.imageSize = [imageSizeW,imageSizeH]
// data.offset = [left?left:0,top?top:0] // data.offset = [left?left:0,top?top:0]
data.maskUrl = arr[index].maskUrl data.maskUrl = arr[index].maskUrl
data.maskMinioUrl = arr[index].maskMinioUrl data.maskMinioUrl = arr[index].maskMinioUrl
@@ -410,15 +510,6 @@ export default defineComponent({
} }
const deleteNav = ()=>{ const deleteNav = ()=>{
}
const setpitch = (item:any,index:any)=>{
detailData.frontBack.front.forEach((v:any)=>{
v.designOpenrtionBtn = false
})
detailData.frontBack.front[index].designOpenrtionBtn = true
// detailData.frontBack.front[index].style.zIndex = selectItem.printZIndex++
// detailData.frontBack.back[index].style.zIndex = selectItem.printZIndex
clothesOpenActive(index)
} }
const updataPosition = ()=>{ const updataPosition = ()=>{
let url = detailData.frontBack?.body?.path let url = detailData.frontBack?.body?.path
@@ -431,10 +522,12 @@ export default defineComponent({
detailData.frontBack.front.forEach((item:any,index:number) => { detailData.frontBack.front.forEach((item:any,index:number) => {
for (const key in item.style) { for (const key in item.style) {
if(key == 'zIndex')return if(key == 'zIndex')return
if(key == 'transform')return
item.style[key] = item.style[key]*sacle+'px' item.style[key] = item.style[key]*sacle+'px'
} }
for (const key in detailData.frontBack.back[index].style) { for (const key in detailData.frontBack.back[index].style) {
if(key == 'zIndex')return if(key == 'zIndex')return
if(key == 'transform')return
detailData.frontBack.back[index].style[key] = detailData.frontBack.back[index].style[key]*sacle+'px' detailData.frontBack.back[index].style[key] = detailData.frontBack.back[index].style[key]*sacle+'px'
} }
}); });
@@ -445,20 +538,22 @@ export default defineComponent({
if (detailData.observer) { if (detailData.observer) {
detailData.observer.disconnect() detailData.observer.disconnect()
} }
if (moveableInstance.value) {
moveableInstance.value.destroy();
}
}) })
return{ return{
...toRefs(detailData), ...toRefs(detailData),
...toRefs(selectItem), ...toRefs(selectItem),
...toRefs(getDetailListDom), ...toRefs(getDetailListDom),
setElementRef,
setPrintSize, setPrintSize,
itemSizeMousedown,
itemMoveMousedown,
deleteNav, deleteNav,
setpitch,
getSubmitData, getSubmitData,
getMousePosition, getMousePosition,
updataPosition, updataPosition,
updateRect,
} }
}, },
@@ -541,6 +636,11 @@ export default defineComponent({
} }
} }
} }
.moveableContainer{
:deep(.moveable-origin){
opacity: 0;
}
}
> .designOpenrtion_imgMask{ > .designOpenrtion_imgMask{
width: auto; width: auto;
height: auto; height: auto;
@@ -561,10 +661,15 @@ export default defineComponent({
position: absolute; position: absolute;
top: 0; top: 0;
} }
.detail_modal_item_front,.designOpenrtion_print{ .detail_modal_item_front,.designOpenrtion_print{
z-index: 2; z-index: 2;
height: 100%; height: 100%;
width: 100%; width: 100%;
pointer-events: none;
&.active{
pointer-events: auto;
}
img{ img{
width: 100%; width: 100%;
// height: ; // height: ;
@@ -583,94 +688,6 @@ export default defineComponent({
.designOpenrtion_print{ .designOpenrtion_print{
z-index: 1 !important; z-index: 1 !important;
} }
> .designOpenrtion_btnBox{
z-index: 99;
width: 100%;
height: 100%;
left: 0;
ul{
list-style: none;
// width: 100%;
// height: 100%;
position: absolute;
top: 0;
left: 0;
box-sizing: border-box;
border: 2px solid rgb(20, 188, 255);
padding: 0;
-webkit-user-drag: none;
user-select:none;
opacity: 0;
margin: 0;
li{
cursor: pointer;
// border-radius: 50%;
width: calc(2rem*1.2);
height: calc(2rem*1.2);
background-color: rgb(20, 188, 255);
position: absolute;
pointer-events: none;
}
&.active{
opacity: 1;
z-index: 999 !important;
li{
pointer-events: auto;
}
}
.designOpenrtion_btn_top,.designOpenrtion_btn_bottom{
left: 50%;
transform: translate(-50%,-50%) ;
cursor: n-resize;
}
.designOpenrtion_btn_top{
top: 0;
}
.designOpenrtion_btn_bottom{
top: 100%;
}
.designOpenrtion_btn_left,.designOpenrtion_btn_right{
top: 50%;
transform: translate(-50%,-50%) ;
cursor: e-resize;
}
.designOpenrtion_btn_left{
left: 0;
}
.designOpenrtion_btn_right{
left: 100%;
}
.designOpenrtion_rotote{
top: 50%;
left: 50%;
transform: translate(-50%,-50%);
width: 0;
height: 0;
}
.designOpenrtion_rotote::after{
position: absolute;
content: "";
background-color: #14bcff;
width: 2px;
height: 30px;
left: 50%;
bottom: 0;
transform: translateX(-50%);
}
.designOpenrtion_rotote::before{
position: absolute;
content: "";
background-color: #14bcff;
top: calc(50% - 30px);
left: 50%;
transform: translate(-50%,-50%) ;
width: calc(1.5rem*1.2);
height: calc(1.5rem*1.2);
border-radius: 50%;
}
}
}
} }
} }
</style> </style>

View File

@@ -132,9 +132,27 @@ export default defineComponent({
url:rv.url, url:rv.url,
designType:props.item.resData.designType || props.item.designType, designType:props.item.resData.designType || props.item.designType,
} }
rv.type_ = {
type1: "material",
type2: props.level1Type
}
if(props.level1Type == 'Printboard'){
let list = props.list.filter((v:any)=> v.type_?.type1 == "material")
list.unshift(rv)
store.commit("setPrintboardMaterialFiles", list);
}else if(props.level1Type == 'Sketchboard'){
let list = props.list.filter((v:any)=> v.type_?.type1 == "material")
list.unshift(rv)
store.commit("setSketchboardMaterialFiles", list);
}else if(props.level1Type == 'Moodleboard'){
let list = props.list.filter((v:any)=> v.type_?.type1 == "material")
list.unshift(rv)
store.commit("setMoodleboardMaterialFiles", list);
}else{
props.list.unshift(rv) props.list.unshift(rv)
} }
} }
}
).catch(res=>{ ).catch(res=>{
}); });
} }

View File

@@ -9,7 +9,7 @@
:isBackgroundChangeable="false" :isBackgroundChangeable="false"
ref="editCanvas"></editCanvas> ref="editCanvas"></editCanvas>
</div> </div>
<div class="btn"> <div class="btn" v-if="btnShow">
<div class="gallery_btn" @click="canvasSave" style="width: min-content;margin-top: auto;">{{ $t('exportModel.Save') }}</div> <div class="gallery_btn" @click="canvasSave" style="width: min-content;margin-top: auto;">{{ $t('exportModel.Save') }}</div>
<div class="gallery_btn" @click="exportElement">{{ $t('exportModel.Export') }}</div> <div class="gallery_btn" @click="exportElement">{{ $t('exportModel.Export') }}</div>
</div> </div>
@@ -46,7 +46,11 @@ export default defineComponent({
isSubmitCanvasJSON:{ isSubmitCanvasJSON:{
type:Boolean, type:Boolean,
default:false default:false
} },
btnShow:{
type:Boolean,
default:true
},
}, },
emits:['submitBase64Data','canvasChangeGetJSON'], emits:['submitBase64Data','canvasChangeGetJSON'],
setup(props,{emit}) { setup(props,{emit}) {
@@ -99,6 +103,9 @@ export default defineComponent({
} }
} }
const submitBase64Data = (base64Data)=>{
return dataDom.editCanvas.exportImage({isContainBg:true,isContainFixed:true,isCropByBg:true})
}
const exportElement = ()=>{ const exportElement = ()=>{
dataDom.editCanvas.exportImage({isContainBg:true,isContainFixed:false,isCropByBg:true}).then((rv)=>{ dataDom.editCanvas.exportImage({isContainBg:true,isContainFixed:false,isCropByBg:true}).then((rv)=>{
downloadBase64Image(rv,'canvas') downloadBase64Image(rv,'canvas')
@@ -174,6 +181,7 @@ export default defineComponent({
canvasInit, canvasInit,
exportElement, exportElement,
changeCanvas, changeCanvas,
submitBase64Data,
}; };
}, },
data(prop) { data(prop) {

View File

@@ -418,6 +418,14 @@ const routes: Array<RouteRecordRaw> = [
}, },
component: () => import("@/views/userManual.vue"), component: () => import("@/views/userManual.vue"),
}, },
{
path: "/award",
name: "award",
meta: {
enter: "all",
},
component: () => import("@/views/AwardPage/index.vue"),
},
{ {
path: "/:catchAll(.*)", path: "/:catchAll(.*)",
redirect: "/404", redirect: "/404",

View File

@@ -1,6 +1,7 @@
import {Module} from 'vuex' import {Module} from 'vuex'
import {RootState} from '../index' import {RootState} from '../index'
import { forEach } from 'jszip' import { forEach } from 'jszip'
import { transform } from 'typescript'
interface DesignDetail{ interface DesignDetail{
designDetail:any, designDetail:any,
@@ -59,6 +60,7 @@ const DesignDetail : Module<DesignDetail,RootState> = {
left:v.layersObject[i].position?.[1], left:v.layersObject[i].position?.[1],
width:v.layersObject[i].imageSize?.[0], width:v.layersObject[i].imageSize?.[0],
height:v.layersObject[i].imageSize?.[1], height:v.layersObject[i].imageSize?.[1],
transform:`rotate(${v.layersObject[i]?.rotate || 0}deg) scaleX(${v.layersObject[i].transpose?.[0] || 1}) scaleY(${v.layersObject[i].transpose?.[1] || 1})`,
} }
v.layersObject[i].centers={ v.layersObject[i].centers={
left:0, left:0,
@@ -69,7 +71,7 @@ const DesignDetail : Module<DesignDetail,RootState> = {
v.layersObject[i].designOpenrtionBtn = false v.layersObject[i].designOpenrtionBtn = false
if(v.layersObject[i].imageCategory.indexOf("back") == -1){ if(v.layersObject[i].imageCategory.indexOf("back") == -1){
front[index] = v.layersObject[i] front[index] = v.layersObject[i]
// front[index].style.zIndex = v.priority front[index].style.zIndex = v.priority + 10
front[index].id = v.id front[index].id = v.id
front[index].undividedLayer = v.undividedLayer front[index].undividedLayer = v.undividedLayer
front[index].undividedLayerWithSinglePrint = v?.undividedLayerWithSinglePrint front[index].undividedLayerWithSinglePrint = v?.undividedLayerWithSinglePrint
@@ -199,6 +201,9 @@ const DesignDetail : Module<DesignDetail,RootState> = {
trims:null, trims:null,
type:null, type:null,
undividedLayer:null, undividedLayer:null,
undividedLayer_:null,
transpose:[1,1],
rotate:0,
undividedLayerWithSinglePrint:null, undividedLayerWithSinglePrint:null,
} }
if(!state.currentDetailType)state.currentDetailType = 'sketch' if(!state.currentDetailType)state.currentDetailType = 'sketch'
@@ -209,6 +214,28 @@ const DesignDetail : Module<DesignDetail,RootState> = {
}); });
state.selectDetail = data state.selectDetail = data
}, },
canvasPreviewUpdata(state,{type,callBack}){
console.log(state.selectDetail,type)
// state.selectDetail.newDetail?.print?.forEach((item:any) => {
// state.selectDetail.printObject.prints = []
// state.selectDetail.printObject.push({
// })
// });
if(type == 'print' || type == 'all')state.selectDetail.printObject.prints = state.selectDetail.newDetail?.print
if(type == 'color' || type == 'all')state.selectDetail.color = {
...state.selectDetail.newDetail?.color,
...state.selectDetail.newDetail?.color?.rgba,
...state.selectDetail.newDetail?.color?.hsv,
}
console.log(state.selectDetail,type,state.selectDetail.newDetail)
if(type == 'element' || type == 'all')state.selectDetail.trims.prints = state.selectDetail.newDetail?.element
if(type == 'all'){
state.selectDetail.newDetail = {}
}else{
state.selectDetail.newDetail[type] = null
}
callBack()
},
async setPraeview(state,value){//preview async setPraeview(state,value){//preview
let data = value?.rv || value let data = value?.rv || value
let currentType = value?.currentType let currentType = value?.currentType
@@ -228,7 +255,6 @@ const DesignDetail : Module<DesignDetail,RootState> = {
}else{ }else{
id_ = item.id id_ = item.id
} }
console.log(id_)
let el:any = document.querySelector('.molepositon .perview_img') let el:any = document.querySelector('.molepositon .perview_img')
await new Promise((resolve, reject) => { await new Promise((resolve, reject) => {
if(!state.frontBack?.body?.path){ if(!state.frontBack?.body?.path){
@@ -252,7 +278,8 @@ const DesignDetail : Module<DesignDetail,RootState> = {
left:item.layersObject[i].position?.[1] * scale + 'px', left:item.layersObject[i].position?.[1] * scale + 'px',
width:item.layersObject[i].imageSize?.[0] * scale + 'px', width:item.layersObject[i].imageSize?.[0] * scale + 'px',
height:item.layersObject[i].imageSize?.[1] * scale + 'px', height:item.layersObject[i].imageSize?.[1] * scale + 'px',
zIndex:v?.style?.zIndex?v.style.zIndex:v.priority?v.priority:state.frontBack.front.length zIndex:v?.style?.zIndex?v.style.zIndex:v.priority?v.priority:state.frontBack.front.length,
transform:`rotate(${item.layersObject?.[i]?.rotate || 0}deg) scaleX(${item.layersObject[i].transpose?.[0] || 1}) scaleY(${item.layersObject[i].transpose?.[1] || 1})`,
} }
item.layersObject[i].centers={ item.layersObject[i].centers={
left:0, left:0,
@@ -293,6 +320,8 @@ const DesignDetail : Module<DesignDetail,RootState> = {
detailItem.minIOPath = item.minIOPath detailItem.minIOPath = item.minIOPath
detailItem.scale = [1,1] detailItem.scale = [1,1]
detailItem.offset = [0,0] detailItem.offset = [0,0]
detailItem.transpose = item.transpose || [1,1]
detailItem.rotate = item.rotate || 0
detailItem.printObject = item.printObject detailItem.printObject = item.printObject
detailItem.trims = item.trims detailItem.trims = item.trims
detailItem.type = item.type detailItem.type = item.type

View File

@@ -618,6 +618,60 @@ function segmentImage(markerImage,fullImage,size){
} }
}) })
} }
/**
* 处理PNG图片透明度转白色其他颜色转透明
* @param {string} sketchImage - 原始图片
* @returns {Promise} 处理后的ase64
*/
function sketchToMask(sketchImage) {
return new Promise((resolve, reject) => {
const img = new Image();
img.crossOrigin = 'anonymous';
img.onload = function() {
try {
const canvas = document.createElement('canvas');
const ctx = canvas.getContext('2d');
canvas.width = img.width;
canvas.height = img.height;
ctx.drawImage(img, 0, 0);
const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
const data = imageData.data;
for (let i = 0; i < data.length; i += 4) {
const r = data[i];
const g = data[i + 1];
const b = data[i + 2];
const a = data[i + 3];
if (a > 0) {
data[i] = 0;
data[i + 1] = 0;
data[i + 2] = 0;
data[i + 3] = 0;
} else {
// 完全透明的像素 -> 纯白色
data[i] = 255;
data[i + 1] = 255;
data[i + 2] = 255;
data[i + 3] = 255;
}
}
ctx.putImageData(imageData, 0, 0);
const base64 = canvas.toDataURL('image/png');
resolve(base64);
} catch (error) {
reject(error);
}
};
img.onerror = function() {
reject(new Error('图片加载失败'));
};
img.src = sketchImage;
});
}
export { export {
isEmail, isEmail,
getUploadUrl, getUploadUrl,
@@ -640,5 +694,6 @@ export {
setGradual, setGradual,
calculateGradientCoordinate, calculateGradientCoordinate,
segmentImage, segmentImage,
UrlToFile UrlToFile,
sketchToMask
} }

View File

@@ -0,0 +1,251 @@
<template>
<div class="award-page">
<div class="header flex align-center space-between">
<div class="header-left">
<img src="@/assets/images/award/code_create_logo.png" class="logo" />
</div>
<div class="header-right flex align-center">
<div class="text">Submit your Application</div>
<img src="@/assets/images/award/arrow.png" alt="" class="arrow" />
</div>
</div>
<div class="banner"></div>
<div class="blocks-list flex">
<div
class="block-item flex flex-col flex-center"
v-for="item in blocksList"
:key="item.number"
>
<div class="number">{{ item.number }}</div>
<div class="label">{{ item.label }}</div>
<div class="line"></div>
</div>
<div class="block-item flex flex-col flex-center">
<div class="number">
<img src="@/assets/images/award/∞.png" alt="" class="infinity" />
</div>
<div class="label">Possibilites</div>
</div>
</div>
<div class="bloom flex flex-col align-center">
<div class="title">Bloom Your Creativity</div>
<img src="@/assets/images/award/bloom_logo.png" class="logo" />
<div class="season">Theme of 2026</div>
<div class="desc">
Where imagination meets innovation, creativity blooms. This theme celebrates AI as
a catalyst for fashion design, allowing your vision to flourish beyond traditional
boundaries. Let your ideas blossom into extraordinary designs that merge human
artistry with artificial intelligence.
</div>
</div>
<div class="design-container">
<div class="design-title limit">Design Without Borders</div>
<div class="limit">
<img src="@/assets/images/award/bloom_logo.png" class="logo" />
</div>
<div class="global limit">Global Opportunity</div>
<div class="desc">
Open to visionary designers across the globe. From Seoul to Singapore, New York to
Shanghai, we're seeking the next generation of fashion innovators who dare to
reimagine the future of design.
</div>
</div>
<div class="timeline-container flex flex-col align-center">
<!-- <img src="@/assets/images/award/timeline_line.png" class="timeline" /> -->
<div class="timeline-title">Competition Timeline</div>
<img src="@/assets/images/award/bloom_logo.png" alt="" class="logo" />
<div class="desc">Shaping the Future</div>
</div>
</div>
</template>
<script setup lang="ts">
import { ref } from 'vue'
const blocksList = ref([
{
number: '100',
label: 'Semi-finalists'
},
{
number: '20',
label: 'Finalists'
},
{
number: '3',
label: 'Winners'
}
])
</script>
<style lang="less" scoped>
.award-page {
overflow: auto;
height: 100vh;
}
.flex {
display: flex;
}
.flex-col {
flex-direction: column;
}
.flex-center {
justify-content: center;
align-items: center;
}
.align-center {
align-items: center;
}
.space-between {
justify-content: space-between;
}
.justify-center {
justify-content: center;
}
.header {
height: 8rem;
background-color: #232323;
padding-left: 21.5rem;
padding-right: 8.6rem;
.header-left {
.logo {
width: 13rem;
height: 5rem;
}
}
.header-right {
column-gap: 1rem;
.text {
font-size: 1.6rem;
color: #fff;
}
.arrow {
width: 2.4rem;
height: 2.4rem;
}
}
}
.logo {
width: 2.4rem;
height: 2.4rem;
}
.banner {
height: 100rem;
background-color: violet;
}
.blocks-list {
height: 31.4rem;
background: linear-gradient(98.55deg, #232323 18.22%, #898989 101.1%);
.block-item {
flex: 1;
height: 100%;
color: #fff;
position: relative;
.number {
font-size: 6rem;
font-family: 'Poppins';
}
.label {
font-size: 2.8rem;
font-family: 'Arial';
letter-spacing: 0.05em;
}
.line {
position: absolute;
bottom: 50%;
right: 0;
transform: translate(0, 50%);
width: 0.1rem;
height: 27.4rem;
background-color: #8d8d8d;
}
}
}
.bloom {
height: 97rem;
padding-top: 12.8rem;
font-family: 'Poppins';
background: url('@/assets/images/award/bloom_bg.png') no-repeat;
background-size: 100% 100%;
.title {
font-size: 4rem;
color: #232323;
margin-bottom: 2.4rem;
}
.logo {
margin-bottom: 2.2rem;
}
.season {
font-size: 3rem;
color: #c7342c;
margin-bottom: 6.6rem;
}
.desc {
font-family: 'Arial';
font-size: 2.8rem;
color: #585858;
text-align: center;
padding: 0 21.5rem;
line-height: 4.5rem;
margin-bottom: 12.3rem;
}
}
.design-container {
height: 97rem;
background: url('@/assets/images/award/design_bg.png') no-repeat;
background-size: 100% 100%;
padding-left: 21.5rem;
padding-top: 16rem;
.limit {
width: 48.4rem;
text-align: center;
}
.design-title {
color: #fff;
font-size: 4rem;
font-weight: 600;
font-family: 'Poppins';
font-style: SemiBold;
vertical-align: middle;
text-transform: capitalize;
}
.logo {
margin-top: 2.4rem;
margin-bottom: 2.1rem;
}
.global {
font-family: 'Poppins';
font-size: 3rem;
color: #f95750;
margin-bottom: 19.8rem;
}
.desc {
font-family: 'Arial';
font-weight: 400;
font-size: 2.8rem;
color: #e0e0e0;
width: 54rem;
}
}
.timeline-container {
height: 97rem;
background: url('@/assets/images/award/timeline_bg.png') no-repeat;
background-size: 100% 100%;
position: relative;
padding-top: 12.8rem;
// .timeline {
// width: 148.7rem;
// height: 27.58rem;
// }
.logo {
margin: 2.4rem 0 2.2rem 0;
}
.desc {
font-family: 'Arial';
font-size: 3rem;
font-weight: 400;
color: #b10000;
}
}
</style>