2026-02-02 23:28:29 +08:00
|
|
|
|
<template>
|
|
|
|
|
|
<avue-draggable
|
2026-02-10 07:32:43 +08:00
|
|
|
|
:data-widget-index="index"
|
2026-02-02 23:28:29 +08:00
|
|
|
|
:step="step"
|
|
|
|
|
|
:width="widgetsWidth"
|
|
|
|
|
|
:height="widgetsHeight"
|
|
|
|
|
|
:disabled="widgetDisabled"
|
|
|
|
|
|
:left="widgetsLeft"
|
|
|
|
|
|
:top="widgetsTop"
|
|
|
|
|
|
ref="draggable"
|
|
|
|
|
|
:index="index"
|
|
|
|
|
|
@focus="handleFocus"
|
|
|
|
|
|
@blur="handleBlur"
|
|
|
|
|
|
>
|
|
|
|
|
|
<!-- :z-index="-1" -->
|
2026-02-10 07:32:43 +08:00
|
|
|
|
<component
|
|
|
|
|
|
:is="type"
|
|
|
|
|
|
:widget-index="index"
|
|
|
|
|
|
:value="value"
|
|
|
|
|
|
@childActivated="handleChildActivated"
|
|
|
|
|
|
@innerDragStart="handleInnerDragStart"
|
|
|
|
|
|
@innerDragEnd="handleInnerDragEnd"
|
|
|
|
|
|
@tabsHeaderMouseDown="handleTabsHeaderMouseDown"
|
|
|
|
|
|
/>
|
2026-02-02 23:28:29 +08:00
|
|
|
|
</avue-draggable>
|
|
|
|
|
|
</template>
|
|
|
|
|
|
|
|
|
|
|
|
<script>
|
|
|
|
|
|
import widgetHref from "./texts/widgetHref.vue";
|
|
|
|
|
|
import widgetText from "./texts/widgetText.vue";
|
|
|
|
|
|
import widgetButton from './form/widgetButton.vue';
|
2026-02-09 01:22:20 +08:00
|
|
|
|
import widgetTabs from './form/widgetTabs.vue';
|
2026-02-02 23:28:29 +08:00
|
|
|
|
import WidgetMarquee from "./texts/widgetMarquee.vue";
|
|
|
|
|
|
import widgetTime from "./texts/widgetTime.vue";
|
|
|
|
|
|
import widgetImage from "./texts/widgetImage.vue";
|
|
|
|
|
|
import widgetSlider from "./texts/widgetSlider.vue";
|
|
|
|
|
|
import widgetVideo from "./texts/widgetVideo.vue";
|
|
|
|
|
|
import widgetVideoMonitor from "./texts/widgetVideoMonitor.vue";
|
|
|
|
|
|
import WidgetIframe from "./texts/widgetIframe.vue";
|
|
|
|
|
|
import widgetCalendar from "./texts/widgetCalendar.vue";
|
|
|
|
|
|
import widgetBarchart from "./bar/widgetBarchart.vue";
|
|
|
|
|
|
import widgetScatter from "./scatter/widgetScatter.vue";
|
|
|
|
|
|
import widgetGradientColorBarchart from "./bar/widgetGradientColorBarchart.vue";
|
|
|
|
|
|
import widgetLinechart from "./line/widgetLinechart.vue";
|
|
|
|
|
|
import widgetBarlinechart from "./barline/widgetBarlinechart";
|
|
|
|
|
|
import WidgetPiechart from "./pie/widgetPiechart.vue";
|
|
|
|
|
|
import WidgetFunnel from "./funnel/widgetFunnel.vue";
|
|
|
|
|
|
import WidgetGauge from "./percent/widgetGauge.vue";
|
|
|
|
|
|
import WidgetPieNightingaleRoseArea from "./pie/widgetPieNightingaleRose";
|
|
|
|
|
|
import widgetTable from "./texts/widgetTable.vue";
|
|
|
|
|
|
import widgetLineMap from "./map/widgetLineMap.vue";
|
|
|
|
|
|
import widgetPiePercentageChart from "./percent/widgetPiePercentageChart";
|
|
|
|
|
|
import widgetAirBubbleMap from "./map/widgetAirBubbleMap";
|
|
|
|
|
|
import widgetBarStackChart from "./bar/widgetBarStackChart";
|
|
|
|
|
|
import widgetLineStackChart from "./line/widgetLineStackChart";
|
|
|
|
|
|
import widgetBarCompareChart from "./bar/widgetBarCompareChart";
|
|
|
|
|
|
import widgetLineCompareChart from "./line/widgetLineCompareChart";
|
|
|
|
|
|
import widgetDecoratePieChart from "./styleWidget/widgetDecoratePieChart.vue";
|
|
|
|
|
|
import widgetMoreBarLineChart from "./barline/widgetMoreBarLineChart";
|
|
|
|
|
|
import widgetWordCloud from "./wordcloud/widgetWordCloud";
|
|
|
|
|
|
import widgetHeatmap from "./heatmap/widgetHeatmap";
|
|
|
|
|
|
import widgetRadar from "./radar/widgetRadar";
|
|
|
|
|
|
import widgetBarLineStackChart from "./barline/widgetBarLineStackChart";
|
|
|
|
|
|
import widgetSelect from "./form/widgetSelect";
|
|
|
|
|
|
import widgetInput from "./form/widgetInput.vue";
|
|
|
|
|
|
import widgetFormTime from "./form/widgetFormTime.vue";
|
|
|
|
|
|
import widgetScaleVertical from "./scale/widgetScaleVertical.vue";
|
|
|
|
|
|
import widgetScaleHorizontal from "./scale/widgetScaleHorizontal.vue";
|
|
|
|
|
|
import widgetBarDoubleYaxisChart from "./bar/widgetBarDoubleYaxisChart.vue";
|
|
|
|
|
|
import widgetBorder from "./styleWidget/widgetBorder.vue";
|
|
|
|
|
|
import widgetDecorateFlowLine from "./styleWidget/widgetDecorateFlowLine.vue";
|
|
|
|
|
|
import widgetDecoration from "./styleWidget/widgetDecoration.vue";
|
|
|
|
|
|
import widgetBarMap from "./map/widgetBarMap.vue";
|
|
|
|
|
|
import widgetChinaMap from "./map/widgetChinaMap.vue";
|
|
|
|
|
|
import widgetGlobalMap from "./map/widgetGlobalMap.vue";
|
|
|
|
|
|
import widgetBarStackMoreShowChart from "./bar/widgetBarStackMoreShowChart.vue";
|
|
|
|
|
|
import widgetBarLineSingleChart from "./barline/widgetBarLineSingleChart.vue";
|
|
|
|
|
|
|
|
|
|
|
|
export default {
|
|
|
|
|
|
name: "Widget",
|
|
|
|
|
|
components: {
|
|
|
|
|
|
widgetHref,
|
|
|
|
|
|
widgetText,
|
|
|
|
|
|
widgetButton,
|
2026-02-09 01:22:20 +08:00
|
|
|
|
widgetTabs,
|
2026-02-02 23:28:29 +08:00
|
|
|
|
widgetBorder,
|
|
|
|
|
|
widgetDecorateFlowLine,
|
|
|
|
|
|
widgetDecoration,
|
|
|
|
|
|
WidgetMarquee,
|
|
|
|
|
|
widgetTime,
|
|
|
|
|
|
widgetImage,
|
|
|
|
|
|
widgetSlider,
|
|
|
|
|
|
widgetVideo,
|
|
|
|
|
|
widgetVideoMonitor,
|
|
|
|
|
|
WidgetIframe,
|
|
|
|
|
|
widgetCalendar,
|
|
|
|
|
|
widgetBarchart,
|
|
|
|
|
|
widgetGradientColorBarchart,
|
|
|
|
|
|
widgetLinechart,
|
|
|
|
|
|
widgetBarlinechart,
|
|
|
|
|
|
WidgetPiechart,
|
|
|
|
|
|
WidgetFunnel,
|
|
|
|
|
|
WidgetGauge,
|
|
|
|
|
|
WidgetPieNightingaleRoseArea,
|
|
|
|
|
|
widgetTable,
|
|
|
|
|
|
widgetLineMap,
|
|
|
|
|
|
widgetPiePercentageChart,
|
|
|
|
|
|
widgetAirBubbleMap,
|
|
|
|
|
|
widgetBarStackChart,
|
|
|
|
|
|
widgetLineStackChart,
|
|
|
|
|
|
widgetBarCompareChart,
|
|
|
|
|
|
widgetLineCompareChart,
|
|
|
|
|
|
widgetDecoratePieChart,
|
|
|
|
|
|
widgetMoreBarLineChart,
|
|
|
|
|
|
widgetWordCloud,
|
|
|
|
|
|
widgetHeatmap,
|
|
|
|
|
|
widgetRadar,
|
|
|
|
|
|
widgetBarLineStackChart,
|
|
|
|
|
|
widgetScaleVertical,
|
|
|
|
|
|
widgetScaleHorizontal,
|
|
|
|
|
|
widgetSelect,
|
|
|
|
|
|
//widgetInput,
|
|
|
|
|
|
widgetFormTime,
|
|
|
|
|
|
widgetBarDoubleYaxisChart,
|
|
|
|
|
|
widgetBarMap,
|
|
|
|
|
|
widgetChinaMap,
|
|
|
|
|
|
widgetGlobalMap,
|
|
|
|
|
|
widgetScatter,
|
|
|
|
|
|
widgetBarStackMoreShowChart,
|
|
|
|
|
|
widgetBarLineSingleChart
|
|
|
|
|
|
},
|
|
|
|
|
|
model: {
|
|
|
|
|
|
prop: "value",
|
|
|
|
|
|
event: "input",
|
|
|
|
|
|
},
|
|
|
|
|
|
props: {
|
|
|
|
|
|
/*
|
|
|
|
|
|
widget-text widget-marquee widget-href widget-time widget-image widget-slider widget-video widget-table widget-iframe widget-universal
|
|
|
|
|
|
widget-linechart widget-barlinechart widget-piechart widget-hollow-piechart widget-funnel widget-gauge widget-china-map
|
|
|
|
|
|
*/
|
|
|
|
|
|
index: Number, // 当前组件,在工作区变量widgetInWorkbench中的索引
|
|
|
|
|
|
type: String,
|
|
|
|
|
|
bigscreen: Object,
|
|
|
|
|
|
value: {
|
|
|
|
|
|
type: [Object],
|
|
|
|
|
|
default: () => {
|
|
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
step: Number,
|
|
|
|
|
|
},
|
|
|
|
|
|
data() {
|
|
|
|
|
|
return {
|
|
|
|
|
|
data: {
|
|
|
|
|
|
setup: {},
|
|
|
|
|
|
data: {},
|
|
|
|
|
|
position: {},
|
|
|
|
|
|
/* leftMargin: null,
|
|
|
|
|
|
topMargin: null*/
|
|
|
|
|
|
},
|
2026-02-10 07:32:43 +08:00
|
|
|
|
// 当 Tabs 内部拖拽子组件时,暂时禁用外层 avue-draggable,防止整个 Tabs 被拖动
|
|
|
|
|
|
innerDragging: false,
|
2026-02-02 23:28:29 +08:00
|
|
|
|
};
|
|
|
|
|
|
},
|
|
|
|
|
|
computed: {
|
|
|
|
|
|
widgetsWidth() {
|
|
|
|
|
|
return this.value.position.width;
|
|
|
|
|
|
},
|
|
|
|
|
|
widgetsHeight() {
|
|
|
|
|
|
return this.value.position.height;
|
|
|
|
|
|
},
|
|
|
|
|
|
widgetsLeft() {
|
|
|
|
|
|
return this.value.position.left; // >= this.leftMargin ? this.leftMargin : this.value.position.left;
|
|
|
|
|
|
},
|
|
|
|
|
|
widgetsTop() {
|
|
|
|
|
|
return this.value.position.top; // >= this.topMargin ? this.topMargin : this.value.position.top;
|
|
|
|
|
|
},
|
|
|
|
|
|
widgetsZIndex() {
|
|
|
|
|
|
return this.value.position.zIndex || 1;
|
|
|
|
|
|
},
|
|
|
|
|
|
widgetDisabled() {
|
2026-02-10 07:32:43 +08:00
|
|
|
|
// Tabs 必须禁用外层拖拽,内部子组件才能选中;Tabs 整体拖动改由标题栏单独处理
|
|
|
|
|
|
if (this.type === 'widget-tabs') {
|
|
|
|
|
|
return true;
|
|
|
|
|
|
}
|
|
|
|
|
|
return this.value.position.disabled || this.innerDragging || false;
|
2026-02-02 23:28:29 +08:00
|
|
|
|
},
|
|
|
|
|
|
},
|
|
|
|
|
|
mounted() {
|
|
|
|
|
|
},
|
|
|
|
|
|
methods: {
|
|
|
|
|
|
handleFocus({index, left, top, width, height}) {
|
|
|
|
|
|
},
|
|
|
|
|
|
handleBlur({index, left, top, width, height}) {
|
|
|
|
|
|
this.$emit("onActivated", {index, left, top, width, height});
|
|
|
|
|
|
this.$refs.draggable.setActive(true);
|
|
|
|
|
|
// 处理widget超出workbench的问题
|
|
|
|
|
|
//this.handleBoundary({ index, left, top, width, height })
|
|
|
|
|
|
},
|
|
|
|
|
|
handleBoundary({index, left, top, width, height}) {
|
|
|
|
|
|
// 计算workbench的X轴边界值
|
|
|
|
|
|
// 组件距离左侧宽度 + 组件宽度 > 大屏总宽度时,右侧边界值 = (大屏宽度 - 组件宽度);左侧边界值 = 0
|
|
|
|
|
|
const {bigscreenWidth, bigscreenHeight} = this.bigscreen;
|
|
|
|
|
|
const xBoundaryValue =
|
|
|
|
|
|
left + width > bigscreenWidth
|
|
|
|
|
|
? bigscreenWidth - width
|
|
|
|
|
|
: left < 0
|
|
|
|
|
|
? 0
|
|
|
|
|
|
: left;
|
|
|
|
|
|
// 初始化X轴边界值
|
|
|
|
|
|
this.leftMargin = left;
|
|
|
|
|
|
// 计算Y轴边界值
|
|
|
|
|
|
const yBoundaryValue =
|
|
|
|
|
|
top + height > bigscreenHeight
|
|
|
|
|
|
? bigscreenHeight - height
|
|
|
|
|
|
: top < 0
|
|
|
|
|
|
? 0
|
|
|
|
|
|
: top;
|
|
|
|
|
|
// 初始化Y轴边界值
|
|
|
|
|
|
this.topMargin = top;
|
|
|
|
|
|
// 若位置超出边界值则重新设置位置
|
|
|
|
|
|
if (
|
|
|
|
|
|
this.leftMargin != xBoundaryValue ||
|
|
|
|
|
|
this.topMargin != yBoundaryValue
|
|
|
|
|
|
) {
|
|
|
|
|
|
this.$nextTick(() => {
|
|
|
|
|
|
this.leftMargin = xBoundaryValue;
|
|
|
|
|
|
this.topMargin = yBoundaryValue;
|
|
|
|
|
|
this.$emit("onActivated", {
|
|
|
|
|
|
index,
|
|
|
|
|
|
left: xBoundaryValue,
|
|
|
|
|
|
top: yBoundaryValue,
|
|
|
|
|
|
width,
|
|
|
|
|
|
height,
|
|
|
|
|
|
});
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
},
|
2026-02-10 07:32:43 +08:00
|
|
|
|
/**
|
|
|
|
|
|
* 接收 Tabs 内部子组件发出的激活事件,并转发给设计器主页面
|
|
|
|
|
|
*/
|
|
|
|
|
|
handleChildActivated(payload) {
|
|
|
|
|
|
const info = Object.assign({}, payload || {});
|
|
|
|
|
|
if (info.rootWidgetIndex === undefined || info.rootWidgetIndex === null) {
|
|
|
|
|
|
info.rootWidgetIndex = this.index;
|
|
|
|
|
|
}
|
|
|
|
|
|
this.$emit("onChildActivated", info);
|
|
|
|
|
|
},
|
|
|
|
|
|
// Tabs 内部开始拖拽/点击子组件时,暂时禁用外层拖拽
|
|
|
|
|
|
handleInnerDragStart() {
|
|
|
|
|
|
this.innerDragging = true;
|
|
|
|
|
|
},
|
|
|
|
|
|
handleInnerDragEnd() {
|
|
|
|
|
|
this.innerDragging = false;
|
|
|
|
|
|
},
|
|
|
|
|
|
handleTabsHeaderMouseDown(evt) {
|
|
|
|
|
|
this.$emit('onTabsHeaderMouseDown', { event: evt, rootWidgetIndex: this.index });
|
|
|
|
|
|
},
|
2026-02-02 23:28:29 +08:00
|
|
|
|
},
|
|
|
|
|
|
};
|
|
|
|
|
|
</script>
|
|
|
|
|
|
|
|
|
|
|
|
<style scoped lang="scss">
|
|
|
|
|
|
.vue-draggalbe {
|
|
|
|
|
|
position: absolute;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.widget-active {
|
|
|
|
|
|
cursor: move;
|
|
|
|
|
|
border: 1px dashed #09f;
|
|
|
|
|
|
background-color: rgba(115, 170, 229, 0.5);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.avue-draggable {
|
|
|
|
|
|
padding: 0 !important;
|
|
|
|
|
|
}
|
|
|
|
|
|
</style>
|