|
|
@@ -78,6 +78,7 @@ export default {
|
|
|
index(newValue, oldValue) {
|
|
|
if (this.isEmpty) return
|
|
|
this.saveCanvasSnapshot(oldValue)
|
|
|
+ this.destroyCanvasInstance()
|
|
|
this.$nextTick(() => {
|
|
|
this.init()
|
|
|
})
|
|
|
@@ -185,6 +186,7 @@ export default {
|
|
|
height:this.canvasForm.height,
|
|
|
bg_color:this.canvasForm.bg_color,
|
|
|
canvas_json:'',
|
|
|
+ preview:''
|
|
|
})
|
|
|
const nextIndex = this.data.length - 1
|
|
|
this.$emit('update:index',nextIndex)
|
|
|
@@ -236,14 +238,17 @@ export default {
|
|
|
},
|
|
|
canvasBodyStyle(item){
|
|
|
const height = Number(item?.height)
|
|
|
- if(!height || Number.isNaN(height)){
|
|
|
- return {
|
|
|
- minHeight: '200px'
|
|
|
- }
|
|
|
+ const width = Number(item?.width) || FIXED_CANVAS_WIDTH
|
|
|
+ const style = {
|
|
|
+ width: `${width}px`,
|
|
|
+ margin: '0 auto'
|
|
|
}
|
|
|
- return {
|
|
|
- height: `${height}px`
|
|
|
+ if(!height || Number.isNaN(height)){
|
|
|
+ style.minHeight = '200px'
|
|
|
+ }else{
|
|
|
+ style.height = `${height}px`
|
|
|
}
|
|
|
+ return style
|
|
|
},
|
|
|
saveCanvasSnapshot(targetIndex){
|
|
|
const snapshotIndex = typeof targetIndex === 'number' ? targetIndex : this.index
|
|
|
@@ -251,23 +256,50 @@ export default {
|
|
|
const canvasData = this.data[snapshotIndex]
|
|
|
if(!canvasData) return
|
|
|
const json = JSON.stringify(this.fcanvas.toJSON(['name','sort','mtr','id','selectable','erasable','data-key','data-value']))
|
|
|
- if(Object.prototype.hasOwnProperty.call(canvasData, 'canvas_json')){
|
|
|
- canvasData.canvas_json = json
|
|
|
- }else{
|
|
|
- const updated = {
|
|
|
- ...canvasData,
|
|
|
- canvas_json: json
|
|
|
- }
|
|
|
- this.data.splice(snapshotIndex, 1, updated)
|
|
|
+ let preview = canvasData.preview || ''
|
|
|
+ try{
|
|
|
+ preview = this.fcanvas.toDataURL({
|
|
|
+ format: 'png',
|
|
|
+ multiplier: 1,
|
|
|
+ enableRetinaScaling: true
|
|
|
+ })
|
|
|
+ }catch (err){
|
|
|
+ console.warn('[marketingEdit] snapshot preview failed', err)
|
|
|
}
|
|
|
+ const updated = {
|
|
|
+ ...canvasData,
|
|
|
+ canvas_json: json,
|
|
|
+ preview
|
|
|
+ }
|
|
|
+ this.data.splice(snapshotIndex, 1, updated)
|
|
|
},
|
|
|
destroyCanvasInstance(){
|
|
|
- if(!this.fcanvas) return
|
|
|
+ if(!this.fcanvas && !this.fcanvasId) return
|
|
|
+ const canvasEl = this.fcanvas && this.fcanvas.getElement ? this.fcanvas.getElement() : document.getElementById(this.fcanvasId)
|
|
|
+ const wrapper = canvasEl && canvasEl.parentNode && canvasEl.parentNode.classList?.contains('fcanvas')
|
|
|
+ ? canvasEl.parentNode
|
|
|
+ : null
|
|
|
+ const parentNode = wrapper ? wrapper.parentNode : (canvasEl ? canvasEl.parentNode : null)
|
|
|
+ const nextSibling = wrapper ? wrapper.nextSibling : (canvasEl ? canvasEl.nextSibling : null)
|
|
|
try{
|
|
|
- this.fcanvas.dispose()
|
|
|
+ this.fcanvas && this.fcanvas.dispose()
|
|
|
}catch(err){
|
|
|
console.warn('[marketingEdit] dispose canvas failed', err)
|
|
|
}finally{
|
|
|
+ if(wrapper && parentNode){
|
|
|
+ parentNode.removeChild(wrapper)
|
|
|
+ }else if(canvasEl && parentNode){
|
|
|
+ parentNode.removeChild(canvasEl)
|
|
|
+ }
|
|
|
+ if(parentNode && this.fcanvasId){
|
|
|
+ const placeholder = document.createElement('canvas')
|
|
|
+ placeholder.id = this.fcanvasId
|
|
|
+ placeholder.width = Number(this.this_canvas?.width) || FIXED_CANVAS_WIDTH
|
|
|
+ placeholder.height = Number(this.this_canvas?.height) || 0
|
|
|
+ placeholder.style.width = '100%'
|
|
|
+ placeholder.style.height = '100%'
|
|
|
+ parentNode.insertBefore(placeholder, nextSibling || null)
|
|
|
+ }
|
|
|
this.fcanvas = null
|
|
|
this.fcanvasId = ''
|
|
|
}
|
|
|
@@ -357,51 +389,69 @@ export default {
|
|
|
width: 100%;
|
|
|
display: flex;
|
|
|
flex-direction: column;
|
|
|
- gap: 20px;
|
|
|
- padding-bottom: 40px;
|
|
|
+ gap: 0;
|
|
|
}
|
|
|
|
|
|
.canvas-stack_item {
|
|
|
width: 100%;
|
|
|
- border-radius: 8px;
|
|
|
- box-shadow: 0 6px 16px rgba(0,0,0,0.06);
|
|
|
- padding: 16px;
|
|
|
+ border-radius: 0;
|
|
|
+ box-shadow: none;
|
|
|
+ padding: 0;
|
|
|
box-sizing: border-box;
|
|
|
+ position: relative;
|
|
|
+ border-bottom: 1px solid #f0f0f0;
|
|
|
}
|
|
|
|
|
|
-.canvas-stack_header {
|
|
|
- display: flex;
|
|
|
- justify-content: space-between;
|
|
|
- align-items: center;
|
|
|
- margin-bottom: 12px;
|
|
|
+.canvas-stack_body {
|
|
|
+ background: transparent;
|
|
|
+ border-radius: 0;
|
|
|
+ padding: 0;
|
|
|
+ box-sizing: border-box;
|
|
|
+ position: relative;
|
|
|
+ min-height: 200px;
|
|
|
+ overflow: hidden;
|
|
|
+ transition: background 0.2s, box-shadow 0.2s, border 0.2s;
|
|
|
}
|
|
|
|
|
|
-.canvas-stack_title {
|
|
|
- display: flex;
|
|
|
- gap: 12px;
|
|
|
- font-size: 16px;
|
|
|
- font-weight: 600;
|
|
|
+.canvas-stack_body.active {
|
|
|
+ background: #f6fbff;
|
|
|
+ box-shadow: inset 0 0 0 2px $primary1;
|
|
|
}
|
|
|
|
|
|
-.canvas-stack_title .size {
|
|
|
- font-size: 13px;
|
|
|
- color: #666;
|
|
|
+.canvas-stack_body canvas {
|
|
|
+ display: block;
|
|
|
+ margin: 0 auto;
|
|
|
}
|
|
|
|
|
|
-.canvas-stack_body {
|
|
|
- background: #fff;
|
|
|
- border-radius: 6px;
|
|
|
- padding: 12px;
|
|
|
- box-sizing: border-box;
|
|
|
+.canvas-stack_body .fcanvas {
|
|
|
+ width: 100% !important;
|
|
|
+ height: 100% !important;
|
|
|
}
|
|
|
|
|
|
-.canvas-stack_body canvas {
|
|
|
- display: block;
|
|
|
- margin: 0 auto;
|
|
|
+.canvas-stack_body .upper-canvas,
|
|
|
+.canvas-stack_body .lower-canvas {
|
|
|
+ width: 100% !important;
|
|
|
+ height: 100% !important;
|
|
|
+}
|
|
|
+
|
|
|
+.canvas-stack_switch {
|
|
|
+ position: absolute;
|
|
|
+ top: 12px;
|
|
|
+ right: 12px;
|
|
|
+ background: rgba($primary1, 0.1);
|
|
|
+ border-color: rgba($primary1, 0.3);
|
|
|
+ color: $primary1;
|
|
|
+}
|
|
|
+
|
|
|
+.canvas-stack_body.active .canvas-stack_switch {
|
|
|
+ background: $primary1;
|
|
|
+ border-color: $primary1;
|
|
|
+ color: #fff;
|
|
|
}
|
|
|
|
|
|
.canvas-stack_placeholder {
|
|
|
height: 100%;
|
|
|
+ width: 100%;
|
|
|
display: flex;
|
|
|
align-items: center;
|
|
|
justify-content: center;
|
|
|
@@ -409,6 +459,8 @@ export default {
|
|
|
color: #888;
|
|
|
font-size: 14px;
|
|
|
text-align: center;
|
|
|
+ padding: 40px 0;
|
|
|
+ box-sizing: border-box;
|
|
|
}
|
|
|
|
|
|
.canvas-stack_placeholder img {
|
|
|
@@ -420,8 +472,9 @@ export default {
|
|
|
.canvas-stack_empty {
|
|
|
width: 100%;
|
|
|
text-align: center;
|
|
|
- padding: 80px 0;
|
|
|
+ padding: 40px 0;
|
|
|
color: #666;
|
|
|
+ border-bottom: 1px solid #f0f0f0;
|
|
|
}
|
|
|
|
|
|
.fixed-width-tip {
|