123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306 |
- <template>
- <div
- class="component-wrapper"
- ref="componentWrapperRef"
- :style="warpperStyle"
- >
- <Container v-bind="componentData.container" @click="handleSelectComponent">
- <component
- :is="component"
- v-bind="componentData.props"
- :width="getComponentWidth"
- :height="getComponentHeight"
- />
- </Container>
- <div v-if="showEditBox" class="edit-box" :style="editWapperStyle">
- <span class="name-tip">{{ getTip }}</span>
- <UseDraggable
- v-for="item in dragPointList"
- :key="item"
- @move="(_, e) => handleDragPoint(item, e)"
- @start="handleDragStart"
- @end="handleDragEnd"
- >
- <span
- v-if="!componentData.locked"
- class="edit-box-point"
- :class="item"
- ></span>
- </UseDraggable>
- </div>
- </div>
- </template>
- <script setup lang="ts">
- import type { CustomElement } from "#/project";
- import { defineProps, defineAsyncComponent, computed, ref } from "vue";
- import { useStageStore } from "@/store/modules/stage";
- import { useProjectStore } from "@/store/modules/project";
- import { useDraggable } from "@vueuse/core";
- import { UseDraggable } from "@vueuse/components";
- import { asyncComponentAll } from 'shalu-dashboard-ui';
- import Container from "@/components/Container/index.vue";
- const { componentData } = defineProps<{ componentData: CustomElement }>();
- // 动态引入组件
- const component = defineAsyncComponent(
- asyncComponentAll[componentData.componentType]
- );
- const componentWrapperRef = ref<HTMLElement | null>(null);
- const stageStore = useStageStore();
- const projectStore = useProjectStore();
- const editWapperStyle = computed(() => {
- const { width = 400, height = 260 } = componentData.container.props || {};
- return {
- transform: `scale(${1 / stageStore.scale})`,
- transformOrigin: "50% 50%",
- width: `${width * stageStore.scale}px`,
- height: `${height * stageStore.scale}px`,
- border: "1px solid #1890ff",
- left: (width / 2) * (1 - stageStore.scale) + "px",
- top: (height / 2) * (1 - stageStore.scale) + "px",
- };
- });
- // 组件宽--根据边距计算
- const getComponentWidth = computed(() => {
- const { width = 400 } = componentData.container.props || {};
- const { paddingLeft = 0, paddingRight = 0 } = componentData.container.props || {};
- return width - paddingLeft - paddingRight;
- });
- // 组件高--根据边距计算
- const getComponentHeight = computed(() => {
- const { height = 260 } = componentData.container.props || {};
- const { paddingTop = 0, paddingBottom = 0 } = componentData.container.props || {};
- return height - paddingTop - paddingBottom;
- });
- const warpperStyle = computed(() => {
- const {
- width = 400,
- height = 260,
- x,
- y,
- } = componentData.container.props || {};
- // const style = transformStyle(componentData.container?.style || {});
-
- return {
- width: `${width}px`,
- height: `${height}px`,
- left: x + "px",
- top: y + "px",
- };
- });
- // 是否显示编辑框
- const showEditBox = computed(() => {
- return (
- projectStore.mode === "edit" &&
- projectStore.selectedElementKeys.includes(componentData.key)
- );
- });
- // 获取提示信息
- const getTip = computed(() => {
- const { x, y } = componentData.container.props || {};
- return showNameTip.value
- ? componentData.name
- : `x: ${Math.round(x)} y: ${Math.round(y)}`;
- });
- let isPointDragFlag = false;
- const showNameTip = ref(true);
- // 拖拽移动组件
- useDraggable(componentWrapperRef, {
- onMove: (position) => {
- if (isPointDragFlag) return;
- const originPosition = componentWrapperRef.value!.getBoundingClientRect();
- // 计算移动的距离
- const xMoveLength = position.x - originPosition.left;
- const yMoveLentgh = position.y - originPosition.top;
- const { x, y } = componentData.container.props || {};
- projectStore.updateElement(
- componentData.key,
- "container.props.x",
- Math.round(x + xMoveLength)
- );
- projectStore.updateElement(
- componentData.key,
- "container.props.y",
- Math.round(y + yMoveLentgh)
- );
- },
- onStart: () => {
- projectStore.setSelectedElementKeys([componentData.key]);
- showNameTip.value = false;
- },
- onEnd: () => {
- showNameTip.value = true;
- },
- });
- const handleSelectComponent = () => {
- projectStore.setSelectedElementKeys([componentData.key]);
- };
- /* ===============================缩放组件==================================== */
- const dragPointList = [
- "top-left",
- "top-center",
- "top-right",
- "left-center",
- "right-center",
- "bottom-left",
- "bottom-center",
- "bottom-right",
- ];
- const startPoint = {
- x: 0,
- y: 0,
- };
- // 拖拽点移动
- const handleDragPoint = (type: string, e: PointerEvent) => {
- const moveX = (e.x - startPoint.x) / stageStore.scale;
- const moveY = (e.y - startPoint.y) / stageStore.scale;
- let { x, y, width, height } = componentData.container.props || {};
- switch (type) {
- case "top-left":
- width -= moveX;
- height -= moveY;
- x += moveX;
- y += moveY;
- break;
- case "top-center":
- height -= moveY;
- y += moveY;
- break;
- case "top-right":
- width += moveX;
- height -= moveY;
- y += moveY;
- break;
- case "left-center":
- width -= moveX;
- x += moveX;
- break;
- case "right-center":
- width += moveX;
- break;
- case "bottom-left":
- width -= moveX;
- height += moveY;
- x += moveX;
- break;
- case "bottom-center":
- height += moveY;
- break;
- case "bottom-right":
- width += moveX;
- height += moveY;
- break;
- }
- startPoint.x = e.x;
- startPoint.y = e.y;
- if (width < 10 || height < 10) return;
- projectStore.updateElement(componentData.key, "container.props.x", Math.round(x));
- projectStore.updateElement(componentData.key, "container.props.y", Math.round(y));
- projectStore.updateElement(componentData.key, "container.props.width", Math.round(width));
- projectStore.updateElement(
- componentData.key,
- "container.props.height",
- Math.round(height)
- );
- };
- // 拖拽点开始
- const handleDragStart = (_: any, e: PointerEvent) => {
- startPoint.x = e.x;
- startPoint.y = e.y;
- isPointDragFlag = true;
- showNameTip.value = false;
- };
- // 拖拽点结束
- const handleDragEnd = () => {
- isPointDragFlag = false;
- showNameTip.value = true;
- };
- </script>
- <style lang="less" scoped>
- .component-wrapper {
- position: absolute;
- }
- .edit-box {
- position: absolute;
- &-point {
- position: absolute;
- width: 8px;
- height: 8px;
- background: #fff;
- border-radius: 50%;
- border: solid 1px @primary-color;
- }
- .name-tip {
- position: absolute;
- top: -20px;
- left: 4px;
- font-size: 12px;
- color: #fff;
- background: @primary-color;
- padding: 2px 4px;
- }
- .top-left {
- top: -4px;
- left: -4px;
- cursor: nw-resize;
- }
- .top-center {
- top: -4px;
- left: 50%;
- transform: translateX(-50%);
- transform-origin: center;
- cursor: n-resize;
- }
- .top-right {
- top: -4px;
- right: -4px;
- cursor: ne-resize;
- }
- .left-center {
- top: 50%;
- left: -4px;
- transform: translateY(-50%);
- cursor: w-resize;
- }
- .right-center {
- top: 50%;
- right: -4px;
- transform: translateY(-50%);
- cursor: e-resize;
- }
- .bottom-left {
- bottom: -4px;
- left: -4px;
- cursor: sw-resize;
- }
- .bottom-center {
- bottom: -4px;
- left: 50%;
- transform: translateX(-50%);
- cursor: s-resize;
- }
- .bottom-right {
- bottom: -4px;
- right: -4px;
- cursor: se-resize;
- }
- }
- </style>
|