Compare commits
6 Commits
9fbbd17e1f
...
tab2026020
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5cce73902d | ||
|
|
25db88333d | ||
|
|
ddb542d89b | ||
|
|
01e9657d49 | ||
| 01f15d8352 | |||
|
|
da7d02474f |
@@ -27,7 +27,7 @@
|
|||||||
v-for="(it, idx) in item.list"
|
v-for="(it, idx) in item.list"
|
||||||
:key="idx"
|
:key="idx"
|
||||||
draggable="true"
|
draggable="true"
|
||||||
@dragstart="dragStart(it.code)"
|
@dragstart="dragStart(it.code, $event)"
|
||||||
@dragend="dragEnd()"
|
@dragend="dragEnd()"
|
||||||
>
|
>
|
||||||
<div class="tools-item">
|
<div class="tools-item">
|
||||||
@@ -290,6 +290,8 @@
|
|||||||
:type="widget.type"
|
:type="widget.type"
|
||||||
:bigscreen="{ bigscreenWidth, bigscreenHeight }"
|
:bigscreen="{ bigscreenWidth, bigscreenHeight }"
|
||||||
@onActivated="setOptionsOnClickWidget"
|
@onActivated="setOptionsOnClickWidget"
|
||||||
|
@onChildActivated="setOptionsOnClickInnerWidget"
|
||||||
|
@onTabsHeaderMouseDown="onTabsHeaderMouseDown($event)"
|
||||||
@contextmenu.prevent.native="rightClick($event, index)"
|
@contextmenu.prevent.native="rightClick($event, index)"
|
||||||
@mousedown.prevent.native="widgetsClick($event, index)"
|
@mousedown.prevent.native="widgetsClick($event, index)"
|
||||||
@mouseup.prevent.native="grade = false"
|
@mouseup.prevent.native="grade = false"
|
||||||
@@ -449,6 +451,8 @@ export default {
|
|||||||
rect : null, //框选矩形对象
|
rect : null, //框选矩形对象
|
||||||
openMulDrag: false, //批量拖拽开关
|
openMulDrag: false, //批量拖拽开关
|
||||||
moveWidgets:{}, //记录移动的组件的起始left和top属性
|
moveWidgets:{}, //记录移动的组件的起始left和top属性
|
||||||
|
// 记录当前是否选中了 Tabs 内部子组件,如果为 null 则表示选中的是顶层组件或大屏
|
||||||
|
innerWidgetSelected: null,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
@@ -988,9 +992,14 @@ export default {
|
|||||||
getPXUnderScale(px) {
|
getPXUnderScale(px) {
|
||||||
return this.bigscreenScaleInWorkbench * px;
|
return this.bigscreenScaleInWorkbench * px;
|
||||||
},
|
},
|
||||||
dragStart(widgetCode) {
|
dragStart(widgetCode, evt) {
|
||||||
this.dragWidgetCode = widgetCode;
|
this.dragWidgetCode = widgetCode;
|
||||||
this.currentWidgetTotal = this.widgets.length; // 当前操作面板上有多少各组件
|
this.currentWidgetTotal = this.widgets.length; // 当前操作面板上有多少各组件
|
||||||
|
// 通过 dataTransfer 传递组件 code,便于 Tabs 等嵌套容器在 drop 时读取(不依赖父组件链)
|
||||||
|
if (evt && evt.dataTransfer) {
|
||||||
|
evt.dataTransfer.setData("application/x-widget-code", widgetCode);
|
||||||
|
evt.dataTransfer.effectAllowed = "copy";
|
||||||
|
}
|
||||||
},
|
},
|
||||||
dragEnd() {
|
dragEnd() {
|
||||||
/**
|
/**
|
||||||
@@ -1017,12 +1026,48 @@ export default {
|
|||||||
});
|
});
|
||||||
},
|
},
|
||||||
dragOver(evt) {
|
dragOver(evt) {
|
||||||
|
// 鼠标在 Tabs 标签内容区内时不处理,让 tab 内容区成为 drop 目标,避免工作台抢走
|
||||||
|
if (evt.target && evt.target.closest && (evt.target.closest(".tab-content") || evt.target.closest("[data-tab-content]"))) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
evt.preventDefault();
|
evt.preventDefault();
|
||||||
evt.stopPropagation();
|
evt.stopPropagation();
|
||||||
evt.dataTransfer.dropEffect = "copy";
|
evt.dataTransfer.dropEffect = "copy";
|
||||||
},
|
},
|
||||||
// 拖动一个组件放到工作区中去,在拖动结束时,放到工作区对应的坐标点上去
|
// 拖动一个组件放到工作区中去,在拖动结束时,放到工作区对应的坐标点上去
|
||||||
widgetOnDragged(evt) {
|
widgetOnDragged(evt) {
|
||||||
|
// 若落在 Tabs 标签内容区内,由 widgetTabs 自己处理,不在此处添加到主画布
|
||||||
|
if (evt.target && evt.target.closest && (evt.target.closest(".tab-content") || evt.target.closest("[data-tab-content]"))) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// 若落在 Tabs 组件的外层容器上(如 avue-draggable),委托给对应 Tabs 加入当前激活的 tab
|
||||||
|
const widgetsRef = this.$refs.widgets;
|
||||||
|
const widgetList = Array.isArray(widgetsRef) ? widgetsRef : (widgetsRef ? [widgetsRef] : []);
|
||||||
|
if (evt.target && widgetList.length) {
|
||||||
|
for (let i = 0; i < widgetList.length; i++) {
|
||||||
|
const w = widgetList[i];
|
||||||
|
if (!w || !w.$el || !w.$el.contains(evt.target)) continue;
|
||||||
|
if (this.widgets[i] && this.widgets[i].type === "widget-tabs") {
|
||||||
|
const findTabs = (comp) => {
|
||||||
|
if (!comp) return null;
|
||||||
|
if (typeof comp.addWidgetFromDrop === "function") return comp;
|
||||||
|
if (comp.$children && comp.$children.length) {
|
||||||
|
for (let j = 0; j < comp.$children.length; j++) {
|
||||||
|
const found = findTabs(comp.$children[j]);
|
||||||
|
if (found) return found;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
};
|
||||||
|
const tabsComp = findTabs(w);
|
||||||
|
if (tabsComp) {
|
||||||
|
tabsComp.addWidgetFromDrop(evt);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
let widgetType = this.dragWidgetCode;
|
let widgetType = this.dragWidgetCode;
|
||||||
|
|
||||||
// 获取结束坐标和列名
|
// 获取结束坐标和列名
|
||||||
@@ -1058,6 +1103,7 @@ export default {
|
|||||||
options: tool.options,
|
options: tool.options,
|
||||||
};
|
};
|
||||||
// 处理默认值
|
// 处理默认值
|
||||||
|
console.log(widgetType)
|
||||||
const widgetJsonValue = this.getWidgetConfigValue(widgetJson);
|
const widgetJsonValue = this.getWidgetConfigValue(widgetJson);
|
||||||
|
|
||||||
widgetJsonValue.value.position.left =
|
widgetJsonValue.value.position.left =
|
||||||
@@ -1138,6 +1184,118 @@ export default {
|
|||||||
});
|
});
|
||||||
this.widgetOptions = this.deepClone(this.widgets[obj.index]["options"]);
|
this.widgetOptions = this.deepClone(this.widgets[obj.index]["options"]);
|
||||||
},
|
},
|
||||||
|
/**
|
||||||
|
* 选中 Tabs 组件内部的子组件,展示该子组件的右侧配置
|
||||||
|
*/
|
||||||
|
setOptionsOnClickInnerWidget(payload) {
|
||||||
|
if (!payload) return;
|
||||||
|
console.log('setOptionsOnClickInnerWidget payload:', payload);
|
||||||
|
|
||||||
|
const { rootWidgetIndex, tabIndex, childIndex } = payload;
|
||||||
|
const rootIndex = typeof rootWidgetIndex === "number" ? rootWidgetIndex : 0;
|
||||||
|
const rootWidget = this.widgets[rootIndex];
|
||||||
|
if (!rootWidget || !rootWidget.value) return;
|
||||||
|
|
||||||
|
// 1. 兼容两种存储位置:value.setup.tabsList / options.setup 里的 tabsList
|
||||||
|
const setupObj = rootWidget.value.setup || {};
|
||||||
|
let tabsList = setupObj.tabsList;
|
||||||
|
if (!tabsList || !tabsList.length) {
|
||||||
|
const setupArr = rootWidget.options && rootWidget.options.setup ? rootWidget.options.setup : [];
|
||||||
|
const tabsItem = setupArr.find(it => it.name === "tabsList");
|
||||||
|
if (tabsItem && Array.isArray(tabsItem.value)) {
|
||||||
|
tabsList = tabsItem.value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
tabsList = tabsList || [];
|
||||||
|
|
||||||
|
const targetTab = tabsList[tabIndex];
|
||||||
|
if (!targetTab || !targetTab.children || !targetTab.children[childIndex]) {
|
||||||
|
console.warn("Tabs 子组件未找到:", { rootIndex, tabIndex, childIndex, tabsList });
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let childWidget = targetTab.children[childIndex];
|
||||||
|
|
||||||
|
// 2. 确保子组件有 options(老数据里可能只有 type + value)
|
||||||
|
if (!childWidget.options) {
|
||||||
|
try {
|
||||||
|
const tool = getToolByCode(childWidget.type);
|
||||||
|
if (tool && tool.options) {
|
||||||
|
childWidget.options = this.deepClone(tool.options);
|
||||||
|
} else {
|
||||||
|
console.warn("未找到子组件 options 配置:", childWidget.type);
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
console.error("为子组件补全 options 失败:", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 3. 用实际 position 回填到 options.position 中,保证坐标表单显示正确
|
||||||
|
if (childWidget.options && Array.isArray(childWidget.options.position)) {
|
||||||
|
const pos = (childWidget.value && childWidget.value.position) ? childWidget.value.position : {};
|
||||||
|
childWidget.options.position.forEach((el) => {
|
||||||
|
if (pos.hasOwnProperty(el.name)) {
|
||||||
|
el.value = pos[el.name];
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// 4. 记录当前选中的内部子组件路径 & 切换右侧到子组件配置
|
||||||
|
this.innerWidgetSelected = {
|
||||||
|
rootWidgetIndex: rootIndex,
|
||||||
|
tabIndex,
|
||||||
|
childIndex,
|
||||||
|
};
|
||||||
|
this.screenCode = "";
|
||||||
|
this.widgetIndex = rootIndex;
|
||||||
|
this.activeName = "first";
|
||||||
|
|
||||||
|
this.widgetOptions = this.deepClone(childWidget.options || {});
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* Tabs 标题栏按下:启动整块 Tabs 的拖动(因 Tabs 外层 avue-draggable 已禁用)
|
||||||
|
*/
|
||||||
|
onTabsHeaderMouseDown(payload) {
|
||||||
|
if (!payload || !payload.event || typeof payload.rootWidgetIndex !== 'number') return;
|
||||||
|
const rootIndex = payload.rootWidgetIndex;
|
||||||
|
const widget = this.widgets[rootIndex];
|
||||||
|
if (!widget || !widget.value || !widget.value.position) return;
|
||||||
|
// 选中 Tabs 组件本身,触发蓝色点框和右侧配置
|
||||||
|
this.innerWidgetSelected = null;
|
||||||
|
this.widgetsClickFocus(rootIndex);
|
||||||
|
const evt = payload.event;
|
||||||
|
const workbenchRect = document.getElementById('workbench') && document.getElementById('workbench').getBoundingClientRect();
|
||||||
|
if (!workbenchRect) return;
|
||||||
|
const scale = this.currentSizeRangeIndex === this.defaultSize.index
|
||||||
|
? this.bigscreenScaleInWorkbench
|
||||||
|
: this.sizeRange[this.currentSizeRangeIndex] / 100;
|
||||||
|
const startX = evt.clientX;
|
||||||
|
const startY = evt.clientY;
|
||||||
|
const startLeft = widget.value.position.left;
|
||||||
|
const startTop = widget.value.position.top;
|
||||||
|
const onMove = (e) => {
|
||||||
|
const dx = (e.clientX - startX) / scale;
|
||||||
|
const dy = (e.clientY - startY) / scale;
|
||||||
|
let newLeft = startLeft + dx;
|
||||||
|
let newTop = startTop + dy;
|
||||||
|
if (newLeft < 0) newLeft = 0;
|
||||||
|
if (newTop < 0) newTop = 0;
|
||||||
|
if (newLeft + widget.value.position.width > this.bigscreenWidth) {
|
||||||
|
newLeft = this.bigscreenWidth - widget.value.position.width;
|
||||||
|
}
|
||||||
|
if (newTop + widget.value.position.height > this.bigscreenHeight) {
|
||||||
|
newTop = this.bigscreenHeight - widget.value.position.height;
|
||||||
|
}
|
||||||
|
this.$set(widget.value.position, 'left', newLeft);
|
||||||
|
this.$set(widget.value.position, 'top', newTop);
|
||||||
|
};
|
||||||
|
const onUp = () => {
|
||||||
|
document.removeEventListener('mousemove', onMove);
|
||||||
|
document.removeEventListener('mouseup', onUp);
|
||||||
|
};
|
||||||
|
document.addEventListener('mousemove', onMove);
|
||||||
|
document.addEventListener('mouseup', onUp);
|
||||||
|
},
|
||||||
widgetsClick(event,index) {
|
widgetsClick(event,index) {
|
||||||
console.log("widgetsClick");
|
console.log("widgetsClick");
|
||||||
//判断是否按住了Ctrl按钮,表示Ctrl多选
|
//判断是否按住了Ctrl按钮,表示Ctrl多选
|
||||||
@@ -1237,10 +1395,40 @@ export default {
|
|||||||
console.log(newSetup);
|
console.log(newSetup);
|
||||||
this.widgetOptions.setup = newSetup;
|
this.widgetOptions.setup = newSetup;
|
||||||
} else {
|
} else {
|
||||||
for (let i = 0; i < this.widgets.length; i++) {
|
// 如果当前选中的是 Tabs 内部子组件,优先更新内部子组件的配置
|
||||||
if (this.widgetIndex == i) {
|
if (this.innerWidgetSelected) {
|
||||||
this.widgets[i].value[key] = this.deepClone(val);
|
const { rootWidgetIndex, tabIndex, childIndex } = this.innerWidgetSelected;
|
||||||
this.setDefaultValue(this.widgets[i].options[key], val);
|
const rootWidget = this.widgets[rootWidgetIndex];
|
||||||
|
if (rootWidget && rootWidget.value && rootWidget.value.setup) {
|
||||||
|
const tabsList = rootWidget.value.setup.tabsList || [];
|
||||||
|
const targetTab = tabsList[tabIndex];
|
||||||
|
if (targetTab && targetTab.children && targetTab.children[childIndex]) {
|
||||||
|
const childWidget = targetTab.children[childIndex];
|
||||||
|
// 更新子组件的 value 和 options
|
||||||
|
if (!childWidget.value) {
|
||||||
|
this.$set(childWidget, "value", {});
|
||||||
|
}
|
||||||
|
childWidget.value[key] = this.deepClone(val);
|
||||||
|
if (childWidget.options && childWidget.options[key]) {
|
||||||
|
this.setDefaultValue(childWidget.options[key], val);
|
||||||
|
}
|
||||||
|
// 回写到 rootWidget 的 setup 中,保证 Tabs 组件保存时能带上最新配置
|
||||||
|
rootWidget.value.setup.tabsList = tabsList;
|
||||||
|
const setupArr = rootWidget.options && rootWidget.options.setup ? rootWidget.options.setup : [];
|
||||||
|
setupArr.forEach((item) => {
|
||||||
|
if (item.name === "tabsList") {
|
||||||
|
item.value = tabsList;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// 普通顶层组件的配置更新逻辑保持不变
|
||||||
|
for (let i = 0; i < this.widgets.length; i++) {
|
||||||
|
if (this.widgetIndex == i) {
|
||||||
|
this.widgets[i].value[key] = this.deepClone(val);
|
||||||
|
this.setDefaultValue(this.widgets[i].options[key], val);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -320,6 +320,26 @@
|
|||||||
@handleCollapse="handleCollapse"
|
@handleCollapse="handleCollapse"
|
||||||
@onChanged="(val) => widgetValueChanged('setup', val)"
|
@onChanged="(val) => widgetValueChanged('setup', val)"
|
||||||
/>
|
/>
|
||||||
|
<!-- 如果当前选中的是 Tabs 内部子组件,在配置表单底部显示删除按钮 -->
|
||||||
|
<div
|
||||||
|
v-if="innerWidgetSelected"
|
||||||
|
style="text-align: right; margin-top: 12px;"
|
||||||
|
>
|
||||||
|
<el-popconfirm
|
||||||
|
title="确定删除该子组件吗?"
|
||||||
|
@onConfirm="deleteInnerWidget"
|
||||||
|
@confirm="deleteInnerWidget"
|
||||||
|
>
|
||||||
|
<el-button
|
||||||
|
slot="reference"
|
||||||
|
type="danger"
|
||||||
|
size="mini"
|
||||||
|
plain
|
||||||
|
>
|
||||||
|
删除该子组件
|
||||||
|
</el-button>
|
||||||
|
</el-popconfirm>
|
||||||
|
</div>
|
||||||
</el-tab-pane>
|
</el-tab-pane>
|
||||||
<el-tab-pane
|
<el-tab-pane
|
||||||
v-if="isNotNull(widgetOptions.data)"
|
v-if="isNotNull(widgetOptions.data)"
|
||||||
@@ -718,9 +738,9 @@ export default {
|
|||||||
const rootIndex = payload.rootWidgetIndex;
|
const rootIndex = payload.rootWidgetIndex;
|
||||||
const widget = this.widgets[rootIndex];
|
const widget = this.widgets[rootIndex];
|
||||||
if (!widget || !widget.value || !widget.value.position) return;
|
if (!widget || !widget.value || !widget.value.position) return;
|
||||||
|
// 选中 Tabs 组件本身,触发蓝色点框和右侧配置
|
||||||
this.innerWidgetSelected = null;
|
this.innerWidgetSelected = null;
|
||||||
this.widgetIndex = rootIndex;
|
this.widgetsClickFocus(rootIndex);
|
||||||
this.setOptionsOnClickWidget(rootIndex);
|
|
||||||
const evt = payload.event;
|
const evt = payload.event;
|
||||||
const workbenchRect = document.getElementById('workbench') && document.getElementById('workbench').getBoundingClientRect();
|
const workbenchRect = document.getElementById('workbench') && document.getElementById('workbench').getBoundingClientRect();
|
||||||
if (!workbenchRect) return;
|
if (!workbenchRect) return;
|
||||||
@@ -797,12 +817,58 @@ export default {
|
|||||||
*/
|
*/
|
||||||
setOptionsOnClickInnerWidget(payload) {
|
setOptionsOnClickInnerWidget(payload) {
|
||||||
if (!payload) return;
|
if (!payload) return;
|
||||||
const { rootWidgetIndex, tabIndex, childIndex, widget } = payload;
|
console.log('setOptionsOnClickInnerWidget payload:', payload);
|
||||||
|
|
||||||
|
const { rootWidgetIndex, tabIndex, childIndex } = payload;
|
||||||
const rootIndex = typeof rootWidgetIndex === "number" ? rootWidgetIndex : 0;
|
const rootIndex = typeof rootWidgetIndex === "number" ? rootWidgetIndex : 0;
|
||||||
const rootWidget = this.widgets[rootIndex];
|
const rootWidget = this.widgets[rootIndex];
|
||||||
if (!rootWidget || !rootWidget.value || !rootWidget.value.setup) return;
|
if (!rootWidget || !rootWidget.value) return;
|
||||||
|
|
||||||
// 记录当前选中的内部子组件路径
|
// 1. 兼容两种存储位置:value.setup.tabsList / options.setup 里的 tabsList
|
||||||
|
const setupObj = rootWidget.value.setup || {};
|
||||||
|
let tabsList = setupObj.tabsList;
|
||||||
|
if (!tabsList || !tabsList.length) {
|
||||||
|
const setupArr = rootWidget.options && rootWidget.options.setup ? rootWidget.options.setup : [];
|
||||||
|
const tabsItem = setupArr.find(it => it.name === "tabsList");
|
||||||
|
if (tabsItem && Array.isArray(tabsItem.value)) {
|
||||||
|
tabsList = tabsItem.value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
tabsList = tabsList || [];
|
||||||
|
|
||||||
|
const targetTab = tabsList[tabIndex];
|
||||||
|
if (!targetTab || !targetTab.children || !targetTab.children[childIndex]) {
|
||||||
|
console.warn("Tabs 子组件未找到:", { rootIndex, tabIndex, childIndex, tabsList });
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let childWidget = targetTab.children[childIndex];
|
||||||
|
|
||||||
|
// 2. 确保子组件有 options(老数据里可能只有 type + value)
|
||||||
|
if (!childWidget.options) {
|
||||||
|
try {
|
||||||
|
const tool = getToolByCode(childWidget.type);
|
||||||
|
if (tool && tool.options) {
|
||||||
|
childWidget.options = this.deepClone(tool.options);
|
||||||
|
} else {
|
||||||
|
console.warn("未找到子组件 options 配置:", childWidget.type);
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
console.error("为子组件补全 options 失败:", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 3. 用实际 position 回填到 options.position 中,保证坐标表单显示正确
|
||||||
|
if (childWidget.options && Array.isArray(childWidget.options.position)) {
|
||||||
|
const pos = (childWidget.value && childWidget.value.position) ? childWidget.value.position : {};
|
||||||
|
childWidget.options.position.forEach((el) => {
|
||||||
|
if (pos.hasOwnProperty(el.name)) {
|
||||||
|
el.value = pos[el.name];
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// 4. 记录当前选中的内部子组件路径 & 切换右侧到子组件配置
|
||||||
this.innerWidgetSelected = {
|
this.innerWidgetSelected = {
|
||||||
rootWidgetIndex: rootIndex,
|
rootWidgetIndex: rootIndex,
|
||||||
tabIndex,
|
tabIndex,
|
||||||
@@ -812,51 +878,53 @@ export default {
|
|||||||
this.widgetIndex = rootIndex;
|
this.widgetIndex = rootIndex;
|
||||||
this.activeName = "first";
|
this.activeName = "first";
|
||||||
|
|
||||||
// 找到真正的子组件对象
|
this.widgetOptions = this.deepClone(childWidget.options || {});
|
||||||
const tabsList = (rootWidget.value.setup && rootWidget.value.setup.tabsList) || [];
|
},
|
||||||
|
/**
|
||||||
|
* 删除当前选中的 Tabs 内部子组件
|
||||||
|
*/
|
||||||
|
deleteInnerWidget() {
|
||||||
|
if (!this.innerWidgetSelected) return;
|
||||||
|
const { rootWidgetIndex, tabIndex, childIndex } = this.innerWidgetSelected;
|
||||||
|
const rootWidget = this.widgets[rootWidgetIndex];
|
||||||
|
if (!rootWidget || !rootWidget.value) return;
|
||||||
|
|
||||||
|
// 永远只操作“真实绑定”的数据:rootWidget.value.setup.tabsList
|
||||||
|
if (!rootWidget.value.setup) {
|
||||||
|
this.$set(rootWidget.value, "setup", {});
|
||||||
|
}
|
||||||
|
if (!Array.isArray(rootWidget.value.setup.tabsList)) {
|
||||||
|
this.$set(rootWidget.value.setup, "tabsList", []);
|
||||||
|
}
|
||||||
|
const tabsList = rootWidget.value.setup.tabsList;
|
||||||
|
|
||||||
const targetTab = tabsList[tabIndex];
|
const targetTab = tabsList[tabIndex];
|
||||||
if (!targetTab || !targetTab.children || !targetTab.children[childIndex]) {
|
if (!targetTab || !targetTab.children || !targetTab.children.length) return;
|
||||||
return;
|
|
||||||
}
|
|
||||||
const childWidget = widget || targetTab.children[childIndex];
|
|
||||||
|
|
||||||
// 用实际 position 值回填到 options.position 中,保证坐标表单显示正确
|
targetTab.children.splice(childIndex, 1);
|
||||||
if (childWidget.options && Array.isArray(childWidget.options.position)) {
|
|
||||||
const pos = childWidget.value && childWidget.value.position ? childWidget.value.position : {};
|
|
||||||
childWidget.options.position.forEach((el) => {
|
|
||||||
if (pos.hasOwnProperty(el.name)) {
|
|
||||||
el.value = pos[el.name];
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
this.widgetOptions = this.deepClone(childWidget.options);
|
// 同步回 rootWidget 的 setup / options
|
||||||
|
rootWidget.value.setup.tabsList = tabsList;
|
||||||
|
const setupArr = rootWidget.options && rootWidget.options.setup ? rootWidget.options.setup : [];
|
||||||
|
setupArr.forEach((item) => {
|
||||||
|
if (item.name === "tabsList") {
|
||||||
|
item.value = tabsList;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// 清空内部选中状态,并回到 Tabs 本身配置
|
||||||
|
this.innerWidgetSelected = null;
|
||||||
|
this.widgetIndex = rootWidgetIndex;
|
||||||
|
this.widgetOptions = this.deepClone(rootWidget.options || {});
|
||||||
|
this.activeName = "first";
|
||||||
},
|
},
|
||||||
widgetsClick(event,index) {
|
widgetsClick(event,index) {
|
||||||
console.log("widgetsClick");
|
console.log("widgetsClick");
|
||||||
// 如果点击发生在 Tabs 组件内部的子组件上,优先选中内部组件
|
// 如果是 Tabs 组件,内部点击由 widgetTabs 自己处理,这里只负责选中 Tabs 整体
|
||||||
if (event && event.target && event.target.closest) {
|
const rootWidget = this.widgets[index];
|
||||||
const tabChildWrapper = event.target.closest(".tab-child-wrapper");
|
if (rootWidget && rootWidget.type === "widget-tabs") {
|
||||||
const tabsRootEl = event.target.closest(".widget-tabs");
|
this.widgetsClickFocus(index);
|
||||||
if (tabChildWrapper && tabsRootEl) {
|
return;
|
||||||
const tabIndexAttr = tabChildWrapper.getAttribute("data-tab-index");
|
|
||||||
const childIndexAttr = tabChildWrapper.getAttribute("data-child-index");
|
|
||||||
const tabIndex = Number(tabIndexAttr);
|
|
||||||
const childIndex = Number(childIndexAttr);
|
|
||||||
if (!isNaN(tabIndex) && !isNaN(childIndex)) {
|
|
||||||
this.setOptionsOnClickInnerWidget({
|
|
||||||
rootWidgetIndex: index,
|
|
||||||
tabIndex,
|
|
||||||
childIndex,
|
|
||||||
});
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// 如果只是点击在 Tabs 内容区的空白处,则交给 Tabs 自己内部处理,避免整个 Tabs 组件被选中
|
|
||||||
const tabContentEl = event.target.closest(".tab-content");
|
|
||||||
if (tabContentEl && tabsRootEl) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
//判断是否按住了Ctrl按钮,表示Ctrl多选
|
//判断是否按住了Ctrl按钮,表示Ctrl多选
|
||||||
let _this = this;
|
let _this = this;
|
||||||
|
|||||||
@@ -119,5 +119,10 @@ export default {
|
|||||||
}
|
}
|
||||||
.pickWrap{
|
.pickWrap{
|
||||||
display:flex;
|
display:flex;
|
||||||
|
&::v-deep() {
|
||||||
|
.el-input__prefix{
|
||||||
|
height:28px;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -29,6 +29,7 @@
|
|||||||
class="tab-content"
|
class="tab-content"
|
||||||
data-tab-content
|
data-tab-content
|
||||||
:style="contentStyle"
|
:style="contentStyle"
|
||||||
|
@click.capture="onTabContentClick($event, index)"
|
||||||
@drop="handleTabDrop($event, tab, index)"
|
@drop="handleTabDrop($event, tab, index)"
|
||||||
@dragover.capture.prevent="handleTabDragOver($event)"
|
@dragover.capture.prevent="handleTabDragOver($event)"
|
||||||
@dragover.prevent="handleTabDragOver($event)"
|
@dragover.prevent="handleTabDragOver($event)"
|
||||||
@@ -42,8 +43,8 @@
|
|||||||
:key="childWidget.value.widgetId || `child-${index}-${childIndex}`"
|
:key="childWidget.value.widgetId || `child-${index}-${childIndex}`"
|
||||||
class="tab-child-draggable"
|
class="tab-child-draggable"
|
||||||
:style="{
|
:style="{
|
||||||
left: (childWidget.value.position && typeof childWidget.value.position.left === 'number') ? childWidget.value.position.left + 'px' : '0px',
|
marginLeft: (childWidget.value.position && typeof childWidget.value.position.left === 'number') ? childWidget.value.position.left + 'px' : '0px',
|
||||||
top: (childWidget.value.position && typeof childWidget.value.position.top === 'number') ? childWidget.value.position.top + 'px' : '0px',
|
marginTop: (childWidget.value.position && typeof childWidget.value.position.top === 'number') ? childWidget.value.position.top + 'px' : '0px',
|
||||||
width: (childWidget.value.position && childWidget.value.position.width) ? childWidget.value.position.width + 'px' : '100px',
|
width: (childWidget.value.position && childWidget.value.position.width) ? childWidget.value.position.width + 'px' : '100px',
|
||||||
height: (childWidget.value.position && childWidget.value.position.height) ? childWidget.value.position.height + 'px' : '50px',
|
height: (childWidget.value.position && childWidget.value.position.height) ? childWidget.value.position.height + 'px' : '50px',
|
||||||
}"
|
}"
|
||||||
@@ -52,9 +53,15 @@
|
|||||||
class="tab-child-wrapper"
|
class="tab-child-wrapper"
|
||||||
:data-tab-index="index"
|
:data-tab-index="index"
|
||||||
:data-child-index="childIndex"
|
:data-child-index="childIndex"
|
||||||
@mousedown.capture="onTabChildMouseDown($event, index, childIndex)"
|
|
||||||
@contextmenu.prevent.stop="handleChildWidgetRightClick($event, childIndex, index)"
|
|
||||||
>
|
>
|
||||||
|
<!-- 选中子组件的小手柄:点击后触发右侧显示该子组件配置 -->
|
||||||
|
<span
|
||||||
|
class="tab-child-select-handle"
|
||||||
|
title="选中并配置该组件"
|
||||||
|
@mousedown.stop.prevent="onTabChildHandleDown(index, childIndex)"
|
||||||
|
>
|
||||||
|
<i class="el-icon-setting tab-child-select-icon"></i>
|
||||||
|
</span>
|
||||||
<component
|
<component
|
||||||
:is="getComponentName(childWidget.type)"
|
:is="getComponentName(childWidget.type)"
|
||||||
:value="childWidget.value"
|
:value="childWidget.value"
|
||||||
@@ -62,14 +69,6 @@
|
|||||||
:ispreview="ispreview"
|
:ispreview="ispreview"
|
||||||
class="tab-child-component"
|
class="tab-child-component"
|
||||||
/>
|
/>
|
||||||
<span
|
|
||||||
class="tab-child-delete"
|
|
||||||
title="删除组件"
|
|
||||||
@mousedown.stop
|
|
||||||
@click.stop="removeChildWidget(index, childIndex)"
|
|
||||||
>
|
|
||||||
×
|
|
||||||
</span>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
@@ -310,7 +309,6 @@ export default {
|
|||||||
* 触发 Tabs 内部子组件选中事件,让设计器右侧展示该子组件的配置
|
* 触发 Tabs 内部子组件选中事件,让设计器右侧展示该子组件的配置
|
||||||
*/
|
*/
|
||||||
emitChildActivated(tabIndex, childIndex) {
|
emitChildActivated(tabIndex, childIndex) {
|
||||||
// 预览模式下不需要触发设计事件
|
|
||||||
if (this.ispreview) return;
|
if (this.ispreview) return;
|
||||||
const currentTabsList = this.tabsList;
|
const currentTabsList = this.tabsList;
|
||||||
const targetTab = currentTabsList[tabIndex];
|
const targetTab = currentTabsList[tabIndex];
|
||||||
@@ -323,11 +321,50 @@ export default {
|
|||||||
widget: childWidget,
|
widget: childWidget,
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
/**
|
||||||
|
* tab 内容区域点击:单击子组件 => 选中子组件;双击空白 => 选中整个 Tabs
|
||||||
|
*/
|
||||||
|
onTabContentClick(evt, tabIndex) {
|
||||||
|
if (this.ispreview || !evt.target || !evt.target.closest) return;
|
||||||
|
// 1)如果点在某个子组件包装层上,优先选中该子组件
|
||||||
|
const wrapper = evt.target.closest(".tab-child-wrapper");
|
||||||
|
if (wrapper) {
|
||||||
|
const childIndexAttr = wrapper.getAttribute("data-child-index");
|
||||||
|
const childIndex = Number(childIndexAttr);
|
||||||
|
if (!isNaN(childIndex)) {
|
||||||
|
this.emitChildActivated(tabIndex, childIndex);
|
||||||
|
}
|
||||||
|
evt.stopPropagation();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// 2)双击内容区空白,通知外层选中整个 Tabs
|
||||||
|
const contentEl = evt.currentTarget;
|
||||||
|
const hasChildWrapper = contentEl.querySelector(".tab-child-wrapper");
|
||||||
|
if (!hasChildWrapper && evt.detail === 2) {
|
||||||
|
this.$emit("tabsContentDblClick", { tabIndex, event: evt });
|
||||||
|
evt.stopPropagation();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* 点击左上角选择手柄:只做“选中内部子组件”的动作
|
||||||
|
*/
|
||||||
|
onTabChildHandleDown(tabIndex, childIndex) {
|
||||||
|
if (this.ispreview) return;
|
||||||
|
this.emitChildActivated(tabIndex, childIndex);
|
||||||
|
},
|
||||||
setActiveTab() {
|
setActiveTab() {
|
||||||
const tabs = this.tabsList;
|
const tabs = this.tabsList;
|
||||||
if (tabs && tabs.length > 0) {
|
if (!tabs || tabs.length === 0) return;
|
||||||
this.activeTab = tabs[0].name || 'tab0';
|
|
||||||
|
// 如果当前 activeTab 还在 tabs 中,则保持不变,避免每次数据变化都跳回第一个标签
|
||||||
|
if (this.activeTab) {
|
||||||
|
const exist = tabs.some((t, i) => (t.name || `tab${i}`) === this.activeTab);
|
||||||
|
if (exist) return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 当前没有选中标签,或原选中标签已被删除时,才默认选中第一个
|
||||||
|
this.activeTab = tabs[0].name || 'tab0';
|
||||||
},
|
},
|
||||||
handleTabClick(tab) {
|
handleTabClick(tab) {
|
||||||
const currentTab = this.tabsList.find(t => (t.name || `tab${this.tabsList.indexOf(t)}`) === tab.name);
|
const currentTab = this.tabsList.find(t => (t.name || `tab${this.tabsList.indexOf(t)}`) === tab.name);
|
||||||
@@ -445,24 +482,9 @@ export default {
|
|||||||
|
|
||||||
// 处理默认值
|
// 处理默认值
|
||||||
const widgetJsonValue = this.getWidgetConfigValue(widgetJson);
|
const widgetJsonValue = this.getWidgetConfigValue(widgetJson);
|
||||||
|
// Tabs 内部子组件:默认边距统一从 0 开始,由右侧“坐标”面板控制间距
|
||||||
// 设置位置(相对于tab内容区域)
|
widgetJsonValue.value.position.left = 0;
|
||||||
widgetJsonValue.value.position.left = x - widgetJsonValue.value.position.width / 2;
|
widgetJsonValue.value.position.top = 0;
|
||||||
widgetJsonValue.value.position.top = y - widgetJsonValue.value.position.height / 2;
|
|
||||||
|
|
||||||
// 确保位置在容器内
|
|
||||||
if (widgetJsonValue.value.position.left < 0) {
|
|
||||||
widgetJsonValue.value.position.left = 0;
|
|
||||||
}
|
|
||||||
if (widgetJsonValue.value.position.top < 0) {
|
|
||||||
widgetJsonValue.value.position.top = 0;
|
|
||||||
}
|
|
||||||
if (widgetJsonValue.value.position.left + widgetJsonValue.value.position.width > this.optionsStyle.width) {
|
|
||||||
widgetJsonValue.value.position.left = this.optionsStyle.width - widgetJsonValue.value.position.width;
|
|
||||||
}
|
|
||||||
if (widgetJsonValue.value.position.top + widgetJsonValue.value.position.height > this.optionsStyle.height) {
|
|
||||||
widgetJsonValue.value.position.top = this.optionsStyle.height - widgetJsonValue.value.position.height;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 生成唯一ID
|
// 生成唯一ID
|
||||||
const uuid = Number(Math.random().toString().substr(2)).toString(36);
|
const uuid = Number(Math.random().toString().substr(2)).toString(36);
|
||||||
@@ -537,14 +559,9 @@ export default {
|
|||||||
options: this.deepClone(tool.options),
|
options: this.deepClone(tool.options),
|
||||||
};
|
};
|
||||||
const widgetJsonValue = this.getWidgetConfigValue(widgetJson);
|
const widgetJsonValue = this.getWidgetConfigValue(widgetJson);
|
||||||
widgetJsonValue.value.position.left = Math.max(0, x - widgetJsonValue.value.position.width / 2);
|
// 同样,外层 drop 到 Tabs 上时,内部子组件也从 0 边距起步
|
||||||
widgetJsonValue.value.position.top = Math.max(0, y - widgetJsonValue.value.position.height / 2);
|
widgetJsonValue.value.position.left = 0;
|
||||||
if (widgetJsonValue.value.position.left + widgetJsonValue.value.position.width > this.optionsStyle.width) {
|
widgetJsonValue.value.position.top = 0;
|
||||||
widgetJsonValue.value.position.left = this.optionsStyle.width - widgetJsonValue.value.position.width;
|
|
||||||
}
|
|
||||||
if (widgetJsonValue.value.position.top + widgetJsonValue.value.position.height > this.optionsStyle.height) {
|
|
||||||
widgetJsonValue.value.position.top = this.optionsStyle.height - widgetJsonValue.value.position.height;
|
|
||||||
}
|
|
||||||
const uuid = Number(Math.random().toString().substr(2)).toString(36);
|
const uuid = Number(Math.random().toString().substr(2)).toString(36);
|
||||||
widgetJsonValue.value.widgetId = uuid;
|
widgetJsonValue.value.widgetId = uuid;
|
||||||
widgetJsonValue.value.widgetCode = dragWidgetCode;
|
widgetJsonValue.value.widgetCode = dragWidgetCode;
|
||||||
@@ -611,16 +628,19 @@ export default {
|
|||||||
* 根节点捕获:仅当点击在标题栏时发出事件,让设计器拖动整块 Tabs(外层 avue-draggable 已禁用)
|
* 根节点捕获:仅当点击在标题栏时发出事件,让设计器拖动整块 Tabs(外层 avue-draggable 已禁用)
|
||||||
*/
|
*/
|
||||||
onTabsRootCapture(evt) {
|
onTabsRootCapture(evt) {
|
||||||
if (this.ispreview) return;
|
if (this.ispreview || !evt.target || !evt.target.closest) return;
|
||||||
if (evt.target && evt.target.closest && evt.target.closest('.el-tabs__header')) {
|
const headerEl = evt.target.closest(".el-tabs__header");
|
||||||
|
if (headerEl) {
|
||||||
|
// 点击在 Tabs 头部:阻止事件冒泡到外层 draggable,并通知外层开始拖动整块 Tabs
|
||||||
evt.stopPropagation();
|
evt.stopPropagation();
|
||||||
this.$emit('tabsHeaderMouseDown', evt);
|
this.$emit("tabsHeaderMouseDown", evt);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
onTabChildMouseDown(event, tabIndex, childIndex) {
|
onTabChildMouseDown(event, tabIndex, childIndex) {
|
||||||
if (event.target && event.target.closest && event.target.closest('.tab-child-delete')) {
|
if (event.target && event.target.closest && event.target.closest('.tab-child-delete')) {
|
||||||
return; // 点在删除按钮上,不拦截,删除按钮的 @mousedown.stop 会阻止冒泡到外层
|
return; // 点在删除按钮上,不拦截,删除按钮的 @mousedown.stop 会阻止冒泡到外层
|
||||||
}
|
}
|
||||||
|
console.log('onTabChildMouseDown:', tabIndex, childIndex);
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
event.stopPropagation();
|
event.stopPropagation();
|
||||||
// 选中内部组件并通知外层暂时禁用拖拽
|
// 选中内部组件并通知外层暂时禁用拖拽
|
||||||
@@ -726,35 +746,6 @@ export default {
|
|||||||
// 通知外层 Widget:内部拖拽结束,恢复外层 avue-draggable
|
// 通知外层 Widget:内部拖拽结束,恢复外层 avue-draggable
|
||||||
this.$emit("innerDragEnd");
|
this.$emit("innerDragEnd");
|
||||||
},
|
},
|
||||||
handleChildWidgetRightClick(event, childIndex, tabIndex) {
|
|
||||||
// 处理子组件右键 - 支持直接删除
|
|
||||||
event.stopPropagation();
|
|
||||||
this.$confirm("确定删除该组件吗?", "提示", {
|
|
||||||
type: "warning",
|
|
||||||
confirmButtonText: "确定",
|
|
||||||
cancelButtonText: "取消",
|
|
||||||
})
|
|
||||||
.then(() => {
|
|
||||||
this.removeChildWidget(tabIndex, childIndex);
|
|
||||||
})
|
|
||||||
.catch(() => {});
|
|
||||||
},
|
|
||||||
/**
|
|
||||||
* 从指定 tab 中移除一个子组件
|
|
||||||
*/
|
|
||||||
removeChildWidget(tabIndex, childIndex) {
|
|
||||||
const currentTabsList = this.tabsList;
|
|
||||||
const targetTab = currentTabsList[tabIndex];
|
|
||||||
if (!targetTab || !targetTab.children) return;
|
|
||||||
targetTab.children.splice(childIndex, 1);
|
|
||||||
|
|
||||||
this.optionsSetup.tabsList = currentTabsList;
|
|
||||||
if (!this.value.setup) {
|
|
||||||
this.$set(this.value, "setup", {});
|
|
||||||
}
|
|
||||||
this.value.setup.tabsList = currentTabsList;
|
|
||||||
this.$emit("input", this.value);
|
|
||||||
},
|
|
||||||
// 将组件类型字符串转换为组件名称
|
// 将组件类型字符串转换为组件名称
|
||||||
getComponentName(type) {
|
getComponentName(type) {
|
||||||
// 将 widget-text 转换为 widgetText
|
// 将 widget-text 转换为 widgetText
|
||||||
@@ -808,34 +799,39 @@ export default {
|
|||||||
position: relative;
|
position: relative;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.tab-child-select-handle {
|
||||||
|
position: absolute;
|
||||||
|
top: -6px;
|
||||||
|
right: -2px;
|
||||||
|
width: 18px;
|
||||||
|
height: 18px;
|
||||||
|
border-radius: 50%;
|
||||||
|
background: rgba(0, 0, 0, 0.45);
|
||||||
|
z-index: 30;
|
||||||
|
cursor: pointer;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tab-child-select-handle:hover {
|
||||||
|
background: rgba(64, 158, 255, 0.9);
|
||||||
|
}
|
||||||
|
|
||||||
|
.tab-child-select-icon {
|
||||||
|
font-size: 14px;
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
.tab-child-component {
|
.tab-child-component {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
.tab-child-delete {
|
|
||||||
position: absolute;
|
|
||||||
right: 2px;
|
|
||||||
top: 2px;
|
|
||||||
width: 14px;
|
|
||||||
height: 14px;
|
|
||||||
line-height: 14px;
|
|
||||||
text-align: center;
|
|
||||||
font-size: 12px;
|
|
||||||
border-radius: 50%;
|
|
||||||
background: rgba(0, 0, 0, 0.4);
|
|
||||||
color: #fff;
|
|
||||||
cursor: pointer;
|
|
||||||
z-index: 20;
|
|
||||||
}
|
|
||||||
|
|
||||||
.tab-child-delete:hover {
|
|
||||||
background: rgba(255, 0, 0, 0.8);
|
|
||||||
}
|
|
||||||
|
|
||||||
.tab-content-empty {
|
.tab-content-empty {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
|
min-height: 200px;
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
|
|||||||
@@ -21,6 +21,7 @@
|
|||||||
@innerDragStart="handleInnerDragStart"
|
@innerDragStart="handleInnerDragStart"
|
||||||
@innerDragEnd="handleInnerDragEnd"
|
@innerDragEnd="handleInnerDragEnd"
|
||||||
@tabsHeaderMouseDown="handleTabsHeaderMouseDown"
|
@tabsHeaderMouseDown="handleTabsHeaderMouseDown"
|
||||||
|
@tabsContentDblClick="handleTabsContentDblClick"
|
||||||
/>
|
/>
|
||||||
</avue-draggable>
|
</avue-draggable>
|
||||||
</template>
|
</template>
|
||||||
@@ -178,10 +179,9 @@ export default {
|
|||||||
return this.value.position.zIndex || 1;
|
return this.value.position.zIndex || 1;
|
||||||
},
|
},
|
||||||
widgetDisabled() {
|
widgetDisabled() {
|
||||||
// Tabs 必须禁用外层拖拽,内部子组件才能选中;Tabs 整体拖动改由标题栏单独处理
|
// 统一走一套逻辑:
|
||||||
if (this.type === 'widget-tabs') {
|
// - 当内部子组件正在拖拽时禁用外层拖拽,避免误拖整块组件
|
||||||
return true;
|
// - 其余情况按组件自身的 disabled 控制
|
||||||
}
|
|
||||||
return this.value.position.disabled || this.innerDragging || false;
|
return this.value.position.disabled || this.innerDragging || false;
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -239,6 +239,7 @@ export default {
|
|||||||
* 接收 Tabs 内部子组件发出的激活事件,并转发给设计器主页面
|
* 接收 Tabs 内部子组件发出的激活事件,并转发给设计器主页面
|
||||||
*/
|
*/
|
||||||
handleChildActivated(payload) {
|
handleChildActivated(payload) {
|
||||||
|
console.log('handleChildActivated in widget.vue:', payload);
|
||||||
const info = Object.assign({}, payload || {});
|
const info = Object.assign({}, payload || {});
|
||||||
if (info.rootWidgetIndex === undefined || info.rootWidgetIndex === null) {
|
if (info.rootWidgetIndex === undefined || info.rootWidgetIndex === null) {
|
||||||
info.rootWidgetIndex = this.index;
|
info.rootWidgetIndex = this.index;
|
||||||
@@ -255,6 +256,11 @@ export default {
|
|||||||
handleTabsHeaderMouseDown(evt) {
|
handleTabsHeaderMouseDown(evt) {
|
||||||
this.$emit('onTabsHeaderMouseDown', { event: evt, rootWidgetIndex: this.index });
|
this.$emit('onTabsHeaderMouseDown', { event: evt, rootWidgetIndex: this.index });
|
||||||
},
|
},
|
||||||
|
// Tabs 内容区双击空白时,也视为选中整个 Tabs
|
||||||
|
handleTabsContentDblClick(payload) {
|
||||||
|
if (!payload || !payload.event) return;
|
||||||
|
this.$emit('onTabsHeaderMouseDown', { event: payload.event, rootWidgetIndex: this.index });
|
||||||
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
Reference in New Issue
Block a user