|
|
@@ -91,25 +91,16 @@ export default {
|
|
|
watch: {
|
|
|
index(newValue, oldValue) {
|
|
|
if (this.isEmpty) return
|
|
|
+ const redirectIndex = this.findEditableCanvas(newValue)
|
|
|
const target = this.data[newValue]
|
|
|
// 模特图/场景图不进入编辑,自动跳到下一个普通画布
|
|
|
- if(target && (target.canvas_type === 'model' || target.canvas_type === 'scene')){
|
|
|
- let nextIdx = -1
|
|
|
- for(let i = newValue + 1; i < this.data.length; i++){
|
|
|
- if(this.data[i].canvas_type !== 'model' && this.data[i].canvas_type !== 'scene'){
|
|
|
- nextIdx = i; break
|
|
|
- }
|
|
|
- }
|
|
|
- if(nextIdx === -1){
|
|
|
- for(let i = newValue - 1; i >= 0; i--){
|
|
|
- if(this.data[i].canvas_type !== 'model' && this.data[i].canvas_type !== 'scene'){
|
|
|
- nextIdx = i; break
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
+ if(
|
|
|
+ target &&
|
|
|
+ (target.canvas_type === 'model' || target.canvas_type === 'scene')
|
|
|
+ ){
|
|
|
// 如果没有可切换的普通画布,保持当前索引,避免递归更新
|
|
|
- if(nextIdx !== -1 && nextIdx !== newValue){
|
|
|
- this.$emit('update:index', nextIdx)
|
|
|
+ if(redirectIndex !== -1 && redirectIndex !== newValue){
|
|
|
+ this.$emit('update:index', redirectIndex)
|
|
|
}
|
|
|
return
|
|
|
}
|
|
|
@@ -200,6 +191,10 @@ export default {
|
|
|
// 模特图/场景图不初始化 fabric,直接跳过
|
|
|
const canvasType = this.this_canvas?.canvas_type || 'normal'
|
|
|
if (canvasType === 'model' || canvasType === 'scene') {
|
|
|
+ const redirectIndex = this.findEditableCanvas(this.index)
|
|
|
+ if(redirectIndex !== -1 && redirectIndex !== this.index){
|
|
|
+ this.$emit('update:index', redirectIndex)
|
|
|
+ }
|
|
|
// 模特/场景图不需要 fabric,保持占位
|
|
|
return
|
|
|
}
|
|
|
@@ -520,6 +515,7 @@ export default {
|
|
|
name: item.name || '',
|
|
|
tpl_url: item.tpl_url || '',
|
|
|
image_path: item.image_path || '',
|
|
|
+ canvas_type: item.canvas_type || 'normal',
|
|
|
multi_goods_mode: item.multi_goods_mode || '',
|
|
|
max_goods_count: item.max_goods_count || null,
|
|
|
}
|
|
|
@@ -594,6 +590,56 @@ export default {
|
|
|
}
|
|
|
this.data.splice(snapshotIndex, 1, updated)
|
|
|
},
|
|
|
+ handleMoveCanvas(idx, direction){
|
|
|
+ const offset = direction === 'up' ? -1 : 1
|
|
|
+ const targetIdx = idx + offset
|
|
|
+ if(targetIdx < 0 || targetIdx >= this.data.length) return
|
|
|
+ this.saveCanvasSnapshot()
|
|
|
+ const currentCanvas = this.data[this.index]
|
|
|
+ const [moved] = this.data.splice(idx, 1)
|
|
|
+ this.data.splice(targetIdx, 0, moved)
|
|
|
+ this.$nextTick(() => {
|
|
|
+ const newIndex = this.data.indexOf(currentCanvas)
|
|
|
+ if(newIndex !== -1 && newIndex !== this.index){
|
|
|
+ this.$emit('update:index', newIndex)
|
|
|
+ }else{
|
|
|
+ this.reloadCurrentCanvas(false)
|
|
|
+ }
|
|
|
+ this.reloadAllNormalCanvases()
|
|
|
+ })
|
|
|
+ },
|
|
|
+ reloadCurrentCanvas(scroll = true){
|
|
|
+ if(this.isEmpty) return
|
|
|
+ this.destroyCanvasInstance()
|
|
|
+ const canvasType = this.this_canvas?.canvas_type || 'normal'
|
|
|
+ if(canvasType === 'model' || canvasType === 'scene'){
|
|
|
+ return
|
|
|
+ }
|
|
|
+ this.$nextTick(() => {
|
|
|
+ this.init()
|
|
|
+ if(scroll){
|
|
|
+ this.scrollToCanvas(this.index)
|
|
|
+ }
|
|
|
+ })
|
|
|
+ },
|
|
|
+ reloadAllNormalCanvases(){
|
|
|
+ // 简单策略:重新加载当前画布即可,避免重复显示;其他画布在切换时再加载
|
|
|
+ this.reloadCurrentCanvas(false)
|
|
|
+ },
|
|
|
+ findEditableCanvas(startIndex = 0){
|
|
|
+ if(this.isEmpty) return -1
|
|
|
+ const total = this.data.length
|
|
|
+ const isEditable = (item) =>
|
|
|
+ item && item.canvas_type !== 'model' && item.canvas_type !== 'scene'
|
|
|
+
|
|
|
+ for(let i = startIndex; i < total; i++){
|
|
|
+ if(isEditable(this.data[i])) return i
|
|
|
+ }
|
|
|
+ for(let i = startIndex - 1; i >= 0; i--){
|
|
|
+ if(isEditable(this.data[i])) return i
|
|
|
+ }
|
|
|
+ return -1
|
|
|
+ },
|
|
|
destroyCanvasInstance(){
|
|
|
if(!this.fcanvas && !this.fcanvasId) return
|
|
|
const canvasEl = this.fcanvas && this.fcanvas.getElement ? this.fcanvas.getElement() : document.getElementById(this.fcanvasId)
|
|
|
@@ -631,6 +677,10 @@ export default {
|
|
|
}
|
|
|
</script>
|
|
|
|
|
|
+<style lang="scss" >
|
|
|
+@import './tpl/header.scss';
|
|
|
+
|
|
|
+</style>
|
|
|
<style lang="scss" scoped>
|
|
|
@import '@/styles/fcanvas.scss';
|
|
|
.picture-editor-wrap {
|
|
|
@@ -641,7 +691,6 @@ export default {
|
|
|
bottom:0;
|
|
|
background: #e6e6e6;
|
|
|
overflow: auto;
|
|
|
-
|
|
|
.picture-editor-wrap_canvas {
|
|
|
position: relative;
|
|
|
margin-top: 85px;
|
|
|
@@ -659,7 +708,6 @@ export default {
|
|
|
@import '../PictureEditor/mixin/layer/index.scss';
|
|
|
@import '../PictureEditor/mixin/color/index.scss';
|
|
|
@import '../PictureEditor/mixin/edit/index.scss';
|
|
|
- @import './tpl/header.scss';
|
|
|
|
|
|
|
|
|
.picture-editor-empty {
|
|
|
@@ -764,21 +812,32 @@ export default {
|
|
|
height: 100% !important;
|
|
|
}
|
|
|
|
|
|
-.canvas-stack_switch {
|
|
|
+.canvas-stack_controls {
|
|
|
position: absolute;
|
|
|
- top: 0px;
|
|
|
- right: -25px;
|
|
|
- width: 25px;
|
|
|
+ top: 10px;
|
|
|
+ right: -30px;
|
|
|
+ display: flex;
|
|
|
+ flex-direction: column;
|
|
|
+ align-items: stretch;
|
|
|
+ gap: 6px;
|
|
|
+ width: 30px;
|
|
|
+}
|
|
|
+
|
|
|
+.canvas-stack_switch {
|
|
|
+ width: 100%;
|
|
|
height: 60px;
|
|
|
background: rgba(104, 188, 165, 0.1);
|
|
|
border-color: rgba(104, 188, 165, 0.3);
|
|
|
color: #68BCA5;
|
|
|
- z-index: 10;
|
|
|
- display: block;
|
|
|
- padding: 0px;
|
|
|
white-space: break-spaces;
|
|
|
- border-top-left-radius: 0px;
|
|
|
- border-bottom-left-radius: 0px;
|
|
|
+ padding: 5px !important;
|
|
|
+ ::v-deep {
|
|
|
+ span {
|
|
|
+ display: block;
|
|
|
+ width: 100%;
|
|
|
+ height: 100%;
|
|
|
+ }
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
.canvas-stack_body.active .canvas-stack_switch {
|
|
|
@@ -787,6 +846,19 @@ export default {
|
|
|
color: #fff;
|
|
|
}
|
|
|
|
|
|
+.canvas-stack_sort {
|
|
|
+ display: flex;
|
|
|
+ flex-direction: column;
|
|
|
+ gap: 4px;
|
|
|
+}
|
|
|
+
|
|
|
+.canvas-stack_sort .el-button {
|
|
|
+ width: 100%;
|
|
|
+ padding: 0;
|
|
|
+ height: 28px;
|
|
|
+ margin-left: 0px !important;
|
|
|
+}
|
|
|
+
|
|
|
.canvas-stack_placeholder {
|
|
|
height: 100%;
|
|
|
width: 100%;
|