diff --git a/src/views/bigscreenDesigner/designer/index.vue b/src/views/bigscreenDesigner/designer/index.vue index c00963b..43d12ef 100644 --- a/src/views/bigscreenDesigner/designer/index.vue +++ b/src/views/bigscreenDesigner/designer/index.vue @@ -27,7 +27,7 @@ v-for="(it, idx) in item.list" :key="idx" draggable="true" - @dragstart="dragStart(it.code)" + @dragstart="dragStart(it.code, $event)" @dragend="dragEnd()" >
@@ -526,9 +526,14 @@ export default { getPXUnderScale(px) { return this.bigscreenScaleInWorkbench * px; }, - dragStart(widgetCode) { + dragStart(widgetCode, evt) { this.dragWidgetCode = widgetCode; 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() { /** @@ -555,12 +560,48 @@ export default { }); }, 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.stopPropagation(); evt.dataTransfer.dropEffect = "copy"; }, // 拖动一个组件放到工作区中去,在拖动结束时,放到工作区对应的坐标点上去 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; // 获取结束坐标和列名 diff --git a/src/views/bigscreenDesigner/designer/tools/configure/form/widget-tabs.js b/src/views/bigscreenDesigner/designer/tools/configure/form/widget-tabs.js new file mode 100644 index 0000000..efbc991 --- /dev/null +++ b/src/views/bigscreenDesigner/designer/tools/configure/form/widget-tabs.js @@ -0,0 +1,221 @@ +/* + * @Descripttion: Tabs标签组件 + * @version: + * @Author: Devli + * @Date: 2024-01-01 00:00:00 + * @LastEditors: Devli + * @LastEditTime: 2024-01-01 00:00:00 + */ +export const widgetTabs = { + code: 'widget-tabs', + type: 'form', + tabName: '表单', + label: 'Tabs标签', + icon: 'iconkuangjia', + options: { + // 配置 + setup: [ + { + type: 'el-input-text', + label: '图层名称', + name: 'layerName', + required: false, + placeholder: '', + value: 'Tabs标签', + }, + { + type: 'el-select', + label: '标签位置', + name: 'tabPosition', + required: false, + placeholder: '', + selectOptions: [ + { code: 'top', name: '顶部' }, + { code: 'right', name: '右侧' }, + { code: 'bottom', name: '底部' }, + { code: 'left', name: '左侧' }, + ], + value: 'top', + }, + { + type: 'el-select', + label: '标签类型', + name: 'type', + required: false, + placeholder: '', + selectOptions: [ + { code: '', name: '默认' }, + { code: 'border-card', name: '边框卡片' }, + { code: 'card', name: '卡片' }, + ], + value: '', + }, + { + type: 'el-switch', + label: '可关闭', + name: 'closable', + required: false, + placeholder: '', + value: false, + }, + { + type: 'el-switch', + label: '可添加', + name: 'addable', + required: false, + placeholder: '', + value: false, + }, + { + type: 'el-switch', + label: '可拉伸', + name: 'stretch', + required: false, + placeholder: '', + value: false, + }, + { + type: 'vue-color', + label: '标签字体颜色', + name: 'labelColor', + required: false, + placeholder: '', + value: '#303133', + }, + { + type: 'vue-color', + label: '激活标签颜色', + name: 'activeColor', + required: false, + placeholder: '', + value: '#409EFF', + }, + { + type: 'el-input-number', + label: '字体字号', + name: 'fontSize', + required: false, + placeholder: '', + value: 14, + }, + { + type: 'el-button', + label: '标签列表', + name: 'tabsList', + required: false, + placeholder: '', + value: [ + { label: '标签一', name: 'tab1', content: '标签一的内容', children: [] }, + { label: '标签二', name: 'tab2', content: '标签二的内容', children: [] }, + { label: '标签三', name: 'tab3', content: '标签三的内容', children: [] }, + ], + }, + [ + { + name: '组件联动', + list: [ + { + type: 'componentLinkage', + label: '', + name: 'componentLinkage', + required: false, + value: [] + } + ] + } + ] + ], + // 数据 + data: [ + { + type: 'el-radio-group', + label: '数据类型', + name: 'dataType', + require: false, + placeholder: '', + selectValue: true, + selectOptions: [ + { + code: 'staticData', + name: '静态数据', + }, + { + code: 'dynamicData', + name: '动态数据', + }, + ], + value: 'staticData', + }, + { + type: 'el-input-number', + label: '刷新时间(毫秒)', + name: 'refreshTime', + relactiveDom: 'dataType', + relactiveDomValue: 'dynamicData', + value: 30000 + }, + { + type: 'el-button', + label: '静态数据', + name: 'staticData', + required: false, + placeholder: '', + relactiveDom: 'dataType', + relactiveDomValue: 'staticData', + value: [ + { label: '标签一', name: 'tab1', content: '标签一的内容', children: [] }, + { label: '标签二', name: 'tab2', content: '标签二的内容', children: [] }, + { label: '标签三', name: 'tab3', content: '标签三的内容', children: [] }, + ], + }, + { + type: 'dycustComponents', + label: '', + name: 'dynamicData', + required: false, + placeholder: '', + relactiveDom: 'dataType', + relactiveDomValue: 'dynamicData', + chartType: 'widget-tabs', + dictKey: 'TABS_PROPERTIES', + value: '', + }, + ], + // 坐标 + position: [ + { + type: 'el-input-number', + label: '左边距', + name: 'left', + required: false, + placeholder: '', + value: 0, + }, + { + type: 'el-input-number', + label: '上边距', + name: 'top', + required: false, + placeholder: '', + value: 0, + }, + { + type: 'el-input-number', + label: '宽度', + name: 'width', + required: false, + placeholder: '该容器在1920px大屏中的宽度', + value: 400, + }, + { + type: 'el-input-number', + label: '高度', + name: 'height', + required: false, + placeholder: '该容器在1080px大屏中的高度', + value: 300, + }, + ], + } +} + diff --git a/src/views/bigscreenDesigner/designer/tools/main.js b/src/views/bigscreenDesigner/designer/tools/main.js index 12c98fd..a322fb2 100644 --- a/src/views/bigscreenDesigner/designer/tools/main.js +++ b/src/views/bigscreenDesigner/designer/tools/main.js @@ -13,6 +13,7 @@ import {widgetHref} from "./configure/texts/widget-href" import {widgetTime} from "./configure/texts/widget-time" import {widgetImage} from "./configure/texts/widget-image" import {widgetButton} from "./configure/form/widget-button" +import {widgetTabs} from "./configure/form/widget-tabs" import {widgetSliders} from "./configure/texts/widget-slider" import {widgetVideo} from "./configure/texts/widget-video" import {widgetVideoMonitor} from "./configure/texts/widget-videoMonitor" @@ -68,6 +69,7 @@ export const widgetTool = [ widgetTime, widgetImage, widgetButton, + widgetTabs, // widgetSliders, widgetVideo, widgetVideoMonitor, diff --git a/src/views/bigscreenDesigner/designer/widget/form/widgetTabs.vue b/src/views/bigscreenDesigner/designer/widget/form/widgetTabs.vue new file mode 100644 index 0000000..8e5d41f --- /dev/null +++ b/src/views/bigscreenDesigner/designer/widget/form/widgetTabs.vue @@ -0,0 +1,638 @@ + + + + + + + diff --git a/src/views/bigscreenDesigner/designer/widget/widget.vue b/src/views/bigscreenDesigner/designer/widget/widget.vue index 084e9b1..bfe2251 100644 --- a/src/views/bigscreenDesigner/designer/widget/widget.vue +++ b/src/views/bigscreenDesigner/designer/widget/widget.vue @@ -20,6 +20,7 @@ import widgetHref from "./texts/widgetHref.vue"; import widgetText from "./texts/widgetText.vue"; import widgetButton from './form/widgetButton.vue'; +import widgetTabs from './form/widgetTabs.vue'; import WidgetMarquee from "./texts/widgetMarquee.vue"; import widgetTime from "./texts/widgetTime.vue"; import widgetImage from "./texts/widgetImage.vue"; @@ -72,6 +73,7 @@ export default { widgetHref, widgetText, widgetButton, + widgetTabs, widgetBorder, widgetDecorateFlowLine, widgetDecoration,