|
@@ -11,10 +11,21 @@
|
|
|
</div>
|
|
|
</div>
|
|
|
<div class="nav_center">
|
|
|
- <div class="item_head_btn" v-for="(item, index) in btnOptions" :key="index">
|
|
|
- <span class="iconfont icon_btn_head" :class="item.value"></span>
|
|
|
- <span class="item_head_label">{{ item.label }}</span>
|
|
|
- </div>
|
|
|
+ <button class="item_head_btn" :class="!canUndo ? 'btn_Void' : 'btn_CDK'" :disabled="!canUndo"
|
|
|
+ @click="operationalView('backout')">
|
|
|
+ <span class="iconfont icon_btn_head icon-chexiao"></span>
|
|
|
+ <span class="item_head_label">撤销</span>
|
|
|
+ </button>
|
|
|
+ <button class="item_head_btn" :class="!canRedo ? 'btn_Void' : 'btn_CDK'" :disabled="!canRedo"
|
|
|
+ @click="operationalView('renewal')">
|
|
|
+ <span class="iconfont icon_btn_head icon-zhongzuo"></span>
|
|
|
+ <span class="item_head_label">重做</span>
|
|
|
+ </button>
|
|
|
+ <button class="item_head_btn" :class="!clearFlag ? 'btn_Void' : 'btn_CDK'" :disabled="!clearFlag"
|
|
|
+ @click="operationalView('clear')">
|
|
|
+ <span class="iconfont icon_btn_head icon-qingchu"></span>
|
|
|
+ <span class="item_head_label">清除</span>
|
|
|
+ </button>
|
|
|
</div>
|
|
|
<div class="nav_right">
|
|
|
<div class="card_right_btn" @click="preview">
|
|
@@ -52,10 +63,9 @@
|
|
|
</div>
|
|
|
<div class="left_paneRight">
|
|
|
<el-scrollbar style="width: 100%; height: 100%" class="component-list scrollbar-wrapper">
|
|
|
- <draggable :list="componentLibrary" itemKey="id" handle=".move" filter=".forbid" :force-fallback="false"
|
|
|
- chosen-class="chosenClass" animation="300" @start="onStart" @end="onEnd" :group="state.groupA"
|
|
|
- :fallback-class="true" :fallback-on-body="true" :touch-start-threshold="50" :fallback-tolerance="50"
|
|
|
- :move="onMove" :sort="false">
|
|
|
+ <draggable :list="componentLibrary" itemKey="id" animation="300" @start="onStart" @end="onEnd"
|
|
|
+ :clone="cloneComponent" :group="{ name: 'itxst', pull: 'clone' }" :touch-start-threshold="50"
|
|
|
+ :fallback-tolerance="50" :sort="false">
|
|
|
<template #item="{ element }">
|
|
|
<div class="item_module_left move">
|
|
|
<component :is="getWidget(element.type)" :config="element"></component>
|
|
@@ -71,12 +81,11 @@
|
|
|
<img class="head_image_url" :src="imageUrl" />
|
|
|
<div class="Bzu">
|
|
|
<DraggableContainer>
|
|
|
- <draggable class="Bzuil" v-model="extraImgs1" itemKey="id" :force-fallback="false" :sort="false"
|
|
|
- :handle="'.forbid'" :fallbackOnBody="false" :group="{ name: 'undraggable', pull: false, put: true }">
|
|
|
+ <draggable class="Bzuil" v-model="extraImgs1" itemKey="soleId" :handle="'.forbid'" group="itxst"
|
|
|
+ ghostClass="ghost">
|
|
|
<template #item="{ element, index }">
|
|
|
<div class="item_module_center move">
|
|
|
- {{ index }}
|
|
|
- <VueDrag :index="index" :dargData="element" :key="index" @passId="getId"></VueDrag>
|
|
|
+ <VueDrag :index="index" :dargData="element" @passId="getId" @modifiedItem="modifiedItem"></VueDrag>
|
|
|
</div>
|
|
|
</template>
|
|
|
</draggable>
|
|
@@ -86,16 +95,14 @@
|
|
|
</div>
|
|
|
<!-- 右侧 -->
|
|
|
<div class="panel_right">
|
|
|
- <el-radio-group v-model="tabPosition">
|
|
|
- <el-radio-button class="radio_card" value="style">样式</el-radio-button>
|
|
|
- <el-radio-button class="radio_card" value="property">属性</el-radio-button>
|
|
|
- </el-radio-group>
|
|
|
- <div class="tabs_radio center_in" v-if="tabPosition == 'style'">
|
|
|
- <el-empty description="暂无样式可调" :image-size="130" />
|
|
|
- </div>
|
|
|
- <div class="tabs_radio center_in" v-if="tabPosition == 'property'">
|
|
|
- <el-empty description="当前无可编辑属性" :image-size="130" />
|
|
|
+ <!-- 样式编辑控件 -->
|
|
|
+ <div class="card_maskedbox">
|
|
|
+ <maskedbox :config="currentMove"></maskedbox>
|
|
|
</div>
|
|
|
+ {{ currentMove }}
|
|
|
+ <!-- <div class="tabs_radio center_in" v-if="tabPosition == 'style'">
|
|
|
+ <el-empty description="暂无样式可调" :image-size="130" />
|
|
|
+ </div> -->
|
|
|
<!-- 右侧对齐方式 -->
|
|
|
<div class="card_alignment">
|
|
|
<div class="bg_ment">
|
|
@@ -122,23 +129,44 @@
|
|
|
import { DraggableContainer } from 'vue3-draggable-resizable'
|
|
|
import Draggable from "vuedraggable";
|
|
|
import moduleLibrary from "../components/moduleLibrary.vue";
|
|
|
-import getName from './widgets/getWidget';
|
|
|
-// import VueDrag from '../components/drag/index.vue'
|
|
|
+import getName from '../components/widgets/getWidget';
|
|
|
import VueDrag from '../components/drag/resizable.vue'
|
|
|
+import maskedbox from './maskedbox.vue'
|
|
|
import { attributeValue, layout } from '../module/index';
|
|
|
-import { ref } from "vue";
|
|
|
+import { ref, computed } from "vue";
|
|
|
import { useRouter } from 'vue-router'
|
|
|
+import { ElMessageBox } from 'element-plus'
|
|
|
|
|
|
-const tabPosition = ref<string>('style');
|
|
|
+// const tabPosition = ref<string>('style');
|
|
|
const activeName = ref<string>('bank');
|
|
|
// 默认选择组件库
|
|
|
const current = ref<string>('1');
|
|
|
const imageUrl = new URL('@/assets/images/head.png', import.meta.url).href;
|
|
|
-const btnOptions = [
|
|
|
- { label: "撤销", value: 'icon-chexiao' },
|
|
|
- { label: "重做", value: 'icon-zhongzuo' },
|
|
|
- { label: "清除", value: 'icon-qingchu' },
|
|
|
-];
|
|
|
+// 组件库
|
|
|
+const extraImgs = ref(attributeValue);
|
|
|
+const componentLibrary = JSON.parse(JSON.stringify(extraImgs.value))
|
|
|
+// 视图库
|
|
|
+const extraImgs1: any = ref([]);
|
|
|
+// 撤销操作的栈
|
|
|
+const undoStack: any = ref([]);
|
|
|
+// 恢复操作的栈
|
|
|
+const redoStack: any = ref([]);
|
|
|
+// 对齐方式状态
|
|
|
+const activate: any = ref(true);
|
|
|
+// 操作组件
|
|
|
+const currentMove: any = ref({})
|
|
|
+// 撤销
|
|
|
+const canUndo = computed(() => {
|
|
|
+ return undoStack.value.length > 0;
|
|
|
+})
|
|
|
+// 恢复
|
|
|
+const canRedo = computed(() => {
|
|
|
+ return redoStack.value.length > 0;
|
|
|
+})
|
|
|
+// 清除
|
|
|
+const clearFlag = computed(() => {
|
|
|
+ return extraImgs1.value.length > 0
|
|
|
+})
|
|
|
const btnAlignment = [
|
|
|
{ type: 'left', label: "左对齐", value: 'icon-zuoduiqi' },
|
|
|
{ type: 'centerHorizontally', label: "水平居中", value: 'icon-hengxiangjuzhong' },
|
|
@@ -151,19 +179,6 @@ function getAssetsImages(name) {
|
|
|
return new URL(`/src/assets/${name}`, import.meta.url).href;
|
|
|
}
|
|
|
|
|
|
-const extraImgs = ref(attributeValue);
|
|
|
-const componentLibrary = JSON.parse(JSON.stringify(extraImgs.value))
|
|
|
-const extraImgs1: any = ref([]);
|
|
|
-const activate: any = ref(true);
|
|
|
-const state = ref({
|
|
|
- message: "拖拽",
|
|
|
- groupA: {
|
|
|
- name: "itxst",
|
|
|
- put: false, //允许拖入
|
|
|
- pull: "clone"
|
|
|
- },
|
|
|
-});
|
|
|
-
|
|
|
//拖拽开始的事件
|
|
|
const onStart = () => {
|
|
|
console.log("开始拖拽");
|
|
@@ -171,15 +186,28 @@ const onStart = () => {
|
|
|
|
|
|
//拖拽结束的事件
|
|
|
const onEnd = (value) => {
|
|
|
- console.log(value, "结束拖拽");
|
|
|
+ if (value.originalEvent.cancelable) {
|
|
|
+ const num = (375 / 2) - (currentMove.value.css.width / 2)
|
|
|
+ currentMove.value.css.left = num
|
|
|
+ currentMove.value.css.top = value.originalEvent.offsetY
|
|
|
+ const arr = JSON.parse(JSON.stringify(currentMove.value))
|
|
|
+ extraImgs1.value.push(arr)
|
|
|
+
|
|
|
+ undoStack.value.push({ type: 'add', item: arr })
|
|
|
+ redoStack.value = [];
|
|
|
+ } else {
|
|
|
+ currentMove.value = {}
|
|
|
+ extraImgs1.value.splice(value.newIndex, 1)
|
|
|
+ }
|
|
|
};
|
|
|
+// 克隆组件
|
|
|
+const cloneComponent = (value) => {
|
|
|
+ currentMove.value = {
|
|
|
+ soleId: "box_" + new Date().getTime(),
|
|
|
+ ...value
|
|
|
+ }
|
|
|
+}
|
|
|
|
|
|
-const onMove = () => {
|
|
|
- // event: MouseEvent
|
|
|
- // console.log(event, 266)
|
|
|
- //不允许停靠
|
|
|
- return true;
|
|
|
-};
|
|
|
const getWidget = (name: string) => {
|
|
|
//组件名映射
|
|
|
return getName[name]
|
|
@@ -196,31 +224,101 @@ const handleReceivedData = (num: any) => {
|
|
|
function handleClick(): void {
|
|
|
console.log(24);
|
|
|
}
|
|
|
-const router = useRouter()
|
|
|
|
|
|
+// 操作视图按钮
|
|
|
+function operationalView(type: any) {
|
|
|
+ if (type == 'backout') {
|
|
|
+ // 撤销
|
|
|
+ const lastAction = undoStack.value.pop();
|
|
|
+ if (lastAction.type === 'add') {
|
|
|
+ const index = extraImgs1.value.findIndex((item) => item.soleId === lastAction.item.soleId);
|
|
|
+ if (index > -1) {
|
|
|
+ extraImgs1.value.splice(index, 1);
|
|
|
+ redoStack.value.push(lastAction);
|
|
|
+ }
|
|
|
+ } else if (lastAction.type === 'drag') {
|
|
|
+ // 将拖拽操作记录添加到redoStack栈
|
|
|
+ redoStack.value.push(lastAction);
|
|
|
+ lastAction.item.css.left = lastAction.startPos.left;
|
|
|
+ lastAction.item.css.top = lastAction.startPos.top;
|
|
|
+ } else if (lastAction.type === 'delete') {
|
|
|
+ extraImgs1.value = lastAction.item
|
|
|
+ redoStack.value.push(lastAction)
|
|
|
+ }
|
|
|
+ } else if (type == 'renewal') {
|
|
|
+ // 重做
|
|
|
+ const lastAction = redoStack.value.pop();
|
|
|
+ if (lastAction.type === 'add') {
|
|
|
+ extraImgs1.value.push(lastAction.item);
|
|
|
+ undoStack.value.push(lastAction);
|
|
|
+ } else if (lastAction.type === 'drag') {
|
|
|
+ // 将拖拽操作记录添加到undoStack栈
|
|
|
+ undoStack.value.push(lastAction);
|
|
|
+ // 还原元素拖拽后的位置
|
|
|
+ lastAction.item.css.left = lastAction.endPos.left;
|
|
|
+ lastAction.item.css.top = lastAction.endPos.top;
|
|
|
+ } else if (lastAction.type === 'delete') {
|
|
|
+ extraImgs1.value = [];
|
|
|
+ undoStack.value.push(lastAction);
|
|
|
+ }
|
|
|
+ } else if (type == 'clear') {
|
|
|
+ ElMessageBox.confirm(
|
|
|
+ '确定删除?',
|
|
|
+ '提示',
|
|
|
+ {
|
|
|
+ confirmButtonText: '确定',
|
|
|
+ cancelButtonText: '取消',
|
|
|
+ type: 'warning',
|
|
|
+ }
|
|
|
+ ).then(() => {
|
|
|
+ undoStack.value.push({ type: 'delete', item: extraImgs1.value })
|
|
|
+ redoStack.value = []
|
|
|
+ extraImgs1.value = []
|
|
|
+ currentMove.value = {}
|
|
|
+ }).catch((err) => {
|
|
|
+ console.log(err);
|
|
|
+ })
|
|
|
+ }
|
|
|
+}
|
|
|
+const router = useRouter()
|
|
|
// 发布
|
|
|
function announce() {
|
|
|
router.push('/TestDrag')
|
|
|
- console.log(extraImgs1.value, 999);
|
|
|
+ // console.log(extraImgs1.value, 999);
|
|
|
}
|
|
|
-
|
|
|
+// 预览
|
|
|
function preview() {
|
|
|
- // console.log(extraImgs1.value[0], 887);
|
|
|
- extraImgs1.value[0].active = true
|
|
|
- extraImgs1.value = extraImgs1.value
|
|
|
+ console.log(extraImgs1.value, '预览');
|
|
|
}
|
|
|
|
|
|
// 激活项索引
|
|
|
const currentIndex: any = ref(null)
|
|
|
+const currentSoleId: any = ref(null)
|
|
|
function getId(params: any) {
|
|
|
- console.log(params, 222);
|
|
|
+ // console.log(params, 8);
|
|
|
+ currentIndex.value = params.index
|
|
|
+ currentSoleId.value = params.soleId
|
|
|
+}
|
|
|
|
|
|
- currentIndex.value = params
|
|
|
+const startX = ref('');
|
|
|
+const startY = ref('');
|
|
|
+function modifiedItem(params: any) {
|
|
|
+ if (params.type == 'drag-start') {
|
|
|
+ startX.value = params.item.css.top
|
|
|
+ startY.value = params.item.css.left
|
|
|
+ }
|
|
|
+ extraImgs1.value.forEach(element => {
|
|
|
+ if (element.soleId == params.item.soleId) {
|
|
|
+ element.css = params.item.css
|
|
|
+ if (params.type == 'drag-end') {
|
|
|
+ undoStack.value.push({ type: 'drag', item: params.item, startPos: { left: startY.value, top: startX.value }, endPos: { left: params.item.css.left, top: params.item.css.top } })
|
|
|
+ redoStack.value = [];
|
|
|
+ }
|
|
|
+ }
|
|
|
+ });
|
|
|
}
|
|
|
// 对齐方式按钮触发
|
|
|
function alignment(params: any) {
|
|
|
- console.log(extraImgs1.value, 222);
|
|
|
-
|
|
|
if (currentIndex.value != null) {
|
|
|
if (params.type == 'left') {
|
|
|
extraImgs1.value[currentIndex.value].css.left = 0
|
|
@@ -240,6 +338,7 @@ function alignment(params: any) {
|
|
|
extraImgs1.value[currentIndex.value].css.top = num
|
|
|
}
|
|
|
}
|
|
|
+ console.log(extraImgs1.value, 5);
|
|
|
}
|
|
|
</script>
|
|
|
|
|
@@ -298,9 +397,18 @@ function alignment(params: any) {
|
|
|
flex-direction: column;
|
|
|
align-items: center;
|
|
|
margin: 0px 16px;
|
|
|
+ border: none;
|
|
|
+ background: none;
|
|
|
+ outline: none;
|
|
|
+ padding: 0px;
|
|
|
+}
|
|
|
+
|
|
|
+.btn_Void {
|
|
|
+ opacity: 0.5;
|
|
|
+ cursor: not-allowed;
|
|
|
}
|
|
|
|
|
|
-.item_head_btn:hover .icon_btn_head {
|
|
|
+.btn_CDK:hover .icon_btn_head {
|
|
|
color: #409EFF;
|
|
|
}
|
|
|
|
|
@@ -429,8 +537,8 @@ function alignment(params: any) {
|
|
|
width: 375px;
|
|
|
margin: 30px auto 0px;
|
|
|
height: 667px;
|
|
|
- background-color: red;
|
|
|
- // background-color: #fafafa;
|
|
|
+ // background-color: red;
|
|
|
+ background-color: #fafafa;
|
|
|
position: relative;
|
|
|
overflow: hidden;
|
|
|
}
|
|
@@ -479,6 +587,11 @@ function alignment(params: any) {
|
|
|
position: absolute !important;
|
|
|
}
|
|
|
|
|
|
+.card_maskedbox {
|
|
|
+ padding: 20px 14px 25px;
|
|
|
+ overflow: hidden overlay;
|
|
|
+}
|
|
|
+
|
|
|
.card_alignment {
|
|
|
max-height: calc(-50px + 100vh);
|
|
|
position: absolute;
|
|
@@ -575,7 +688,10 @@ img {
|
|
|
// overflow: hidden;
|
|
|
}
|
|
|
|
|
|
+.Bzu .ghost {
|
|
|
+ opacity: 0;
|
|
|
+}
|
|
|
+
|
|
|
.Bzuil {
|
|
|
height: 100%;
|
|
|
-}
|
|
|
-</style>
|
|
|
+}</style>
|