Browse Source

卡片布局

qianduan 6 months ago
parent
commit
1655f75308

+ 19 - 10
src/components/drag/resizable.vue

@@ -6,6 +6,7 @@
         @dragging="print('dragging')" @drag-end="print('drag-end')" @resize-end="print('resize-end')" @activated="activated"
         @deactivated="deactivated" @click.native="clickHandler">
         <component :is="getWidget(currentItem.type)" :config="currentItem"></component>
+        <!-- 锁定 -->
         <div class="card_lock center_in" v-if="active && lock">
             <span class="iconfont lock_icon_img icon-suo"></span>
         </div>
@@ -29,18 +30,26 @@ const resizable1 = ref(true) //默认true允许
 const lock = ref(false) // 组件是否锁定
 // 组件是否可拖动
 const draggable = computed(() => {
-    if (lock.value) {
-        return false
+    if (draggable1.value) {
+        if (lock.value) {
+            return false
+        } else {
+            return draggable1.value
+        }
     } else {
-        return draggable1.value
+        return false
     }
 });
 // 组件是否可调整大小
 const resizable = computed(() => {
-    if (lock.value) {
-        return false
+    if (resizable1.value) {
+        if (lock.value) {
+            return false
+        } else {
+            return resizable1.value
+        }
     } else {
-        return resizable1.value
+        return false
     }
 });
 const sticks = ref([])
@@ -63,10 +72,12 @@ watch(() => props.dargData, (newValue) => {
         h.value = newValue.css.height
         top.value = newValue.css.top
         left.value = newValue.css.left
-        if (newValue.config.draggable) {
+        if ('draggable' in newValue.config) {
             draggable1.value = newValue.config.draggable
         }
-        resizable1.value = newValue.config.resizable
+        if ('resizable' in newValue.config) {
+            resizable1.value = newValue.config.resizable
+        }
         lock.value = newValue.config.lock
         isResizable.value = newValue.config.isResizable
         sticks.value = newValue.config.sticks
@@ -125,8 +136,6 @@ function clickHandler() {
     height: auto !important;
 }
 
-.vdr-container.active {}
-
 .card_lock {
     position: absolute;
     top: 0;

+ 26 - 0
src/components/widgets/CardView.vue

@@ -0,0 +1,26 @@
+<template>
+    <div class="card_view_hint center_in" :style="{ width: configData.css.width + 'px', height: configData.css.height + 'px', }">
+        拖入组件</div>
+</template>
+  
+<script setup lang="ts">
+import { watch, ref } from "vue";
+const props = defineProps(["config"])
+
+const configData: any = ref({})
+watch(() => props.config, (newValue) => {
+    if (newValue) {
+        console.log(newValue,35);
+        
+        configData.value = newValue
+    }
+}, { immediate: true, deep: true })
+</script>
+  
+<style lang="scss" scoped>
+.card_view_hint{
+    font-size: 20px;
+    overflow: hidden auto;
+}
+</style>
+  

+ 1 - 0
src/module/config/input.ts

@@ -4,6 +4,7 @@ const configList1 = {
     size: 30,
     color: "#158cfb",
     isResizable: true, //禁止缩放
+    draggable: true, //组件是否可拖动
     // sticks:['tl', 'tm', 'tr', 'mr', 'br', 'bm', 'bl', 'ml'],
     sticks: ['mr', 'ml'],
     aspectRatio: false, //禁止等比例缩放

+ 1 - 0
src/module/config/picture.ts

@@ -3,6 +3,7 @@ const pictureConfig = {
     isResizable: true, //禁止缩放
     aspectRatio: false, //禁止等比例缩放
     resizable: true, //禁止调整大小false禁止
+    draggable: true, //组件是否可拖动
     lock: false, //锁定
     pictureMode: 'contain',//适应contain,fill拉伸
     picture: '', //图片地址名称

+ 2 - 2
src/module/config/text.ts

@@ -12,8 +12,8 @@ const TextConfig = {
 }
 
 const TextCss = {
-    top: 200,
-    left: 30,
+    top: 0,
+    left: 0,
     width: 100,
     height: 'auto',
     fontSize: 14,

+ 1 - 0
src/stores/index.ts

@@ -11,6 +11,7 @@ export const useUserStore = defineStore('user', {
             inputFlag: false,
             name: '卡片',
             icon: 'icon-kapian',
+            proportion: 1,
             viewData: [],
         }, {
             id: 2,

+ 203 - 36
src/views/HomeView.vue

@@ -98,9 +98,36 @@
       </div>
       <!-- 中间 -->
       <div class="panel_center">
-        <div class="card_home">
-          <img class="head_image_url" :src="imageUrl" />
-          <div class="Bzu">
+        <div class="card_selectSize" :style="{ width: (viewName == '卡片' ? cardWidth + 'px' : '375px') }">
+          <div style="display: flex;" v-if="viewName == '卡片'">
+            <el-popover :visible="cardSizeVisible" popper-style="padding: 10px 0px;" :width="80" trigger="click">
+              <template #reference>
+                <div class="card_size_select" @click="cardSizeVisible = true">
+                  <span>选择卡片尺寸:</span>
+                  <div class="size_title_select">{{ currentCardName }}</div>
+                </div>
+              </template>
+              <div style="display: flex;flex-direction: column;" v-click-outside="onClickOutside">
+                <div class="card_size_item" v-for="(item, index) in cardSizeData" :key="index"
+                  @click="changeCardSize(item)">
+                  <span :style="{ color: (item.flag ? '#409EFF' : '') }">{{ item.title }}</span>
+                </div>
+              </div>
+            </el-popover>
+          </div>
+        </div>
+        <div class="card_home" :style="{ width: (viewName == '卡片' ? cardWidth + 'px' : '375px') }">
+          <img class="head_image_url" :src="imageUrl" v-if="viewName != '卡片'" />
+          <div class="card_title_bar" v-if="viewName != '卡片'">
+            <div class="left_back">
+              <el-icon size="24">
+                <ArrowLeft />
+              </el-icon>
+            </div>
+            <span class="title_headline_head">头部栏标题</span>
+          </div>
+          <div class="Bzu"
+            :style="{ width: (viewName == '卡片' ? cardWidth + 'px' : '375px'), height: (viewName == '卡片' ? cardHeight + 'px' : '603px') }">
             <DraggableContainer>
               <draggable class="Bzuil" v-model="extraImgs1" itemKey="soleId" :handle="'.forbid'" group="itxst"
                 ghostClass="ghost">
@@ -112,6 +139,7 @@
                 </template>
               </draggable>
             </DraggableContainer>
+            <div class="card_hint_title center_in" v-if="extraImgs1.length == 0 && viewName == '卡片'">拖入组件</div>
           </div>
         </div>
       </div>
@@ -128,7 +156,7 @@
         <div class="card_alignment">
           <div class="bg_ment">
             <div class="icon_item_align" :class="activate ? 'active_icon' : 'icon_item_gray'"
-              v-for="(  item, index  ) in btnAlignment  " :key="index" @click="alignment(item)">
+              v-for="(item, index) in btnAlignment" :key="index" @click="alignment(item)">
               <el-tooltip class="box-item" :content="item.label" placement="left" effect="light">
                 <span class="iconfont icon_alignment" :class="item.value"></span>
               </el-tooltip>
@@ -180,7 +208,7 @@ import additionPage from './additionPage.vue'
 import { baseComponent, attributeValue, layout } from '../module/index';
 import { ref, computed } from "vue";
 import { useRouter } from 'vue-router'
-import { ElMessageBox } from 'element-plus'
+import { ElMessageBox, ClickOutside as vClickOutside } from 'element-plus'
 // 存储
 import { useUserStore } from '../stores/index'
 import { storeToRefs } from 'pinia';
@@ -202,18 +230,83 @@ const componentLibrary: any = ref([])
 componentLibrary.value = JSON.parse(JSON.stringify(extraImgs.value))
 // 视图库
 const extraImgs1: any = ref([]);
+const viewName: any = ref('')
 viewList.value.forEach(item => {
   if (item.flag) {
+    viewName.value = item.name
     extraImgs1.value = item.viewData
   }
 })
+// 选择页面
 function switchPage() {
   viewList.value.forEach(item => {
     if (item.flag) {
+      viewName.value = item.name
       extraImgs1.value = item.viewData
     }
   })
 }
+// 判断卡片获取视图宽高
+const widthNum = ref(375)
+const cardWidth = computed(() => {
+  if (viewCurrent.value == 1) {
+    widthNum.value = 180
+  }
+  if (viewCurrent.value == 2) {
+    widthNum.value = 375
+  }
+  if (viewCurrent.value == 3) {
+    widthNum.value = 375
+  }
+  return widthNum.value
+});
+const heightNum = ref(603)
+const cardHeight = computed(() => {
+  if (viewCurrent.value == 1) {
+    heightNum.value = 180
+  }
+  if (viewCurrent.value == 2) {
+    heightNum.value = 180
+  }
+  if (viewCurrent.value == 3) {
+    heightNum.value = 375
+  }
+  return heightNum.value
+});
+// 当前选择尺寸默认1*1
+const currentCardName: any = ref('1 * 1')
+const viewCurrent: any = ref(1)
+// 卡片选择尺寸
+const cardSizeData: any = ref([{
+  id: 1,
+  flag: true,
+  title: '1 * 1',
+}, {
+  id: 2,
+  flag: false,
+  title: '1 * 2',
+}, {
+  id: 3,
+  flag: false,
+  title: '2 * 2',
+}])
+const cardSizeVisible = ref(false)
+const onClickOutside = () => {
+  cardSizeVisible.value = false
+}
+// 选择卡片尺寸
+function changeCardSize(params: any) {
+  cardSizeData.value.forEach(item => {
+    if (params.id == item.id) {
+      item.flag = true
+      cardSizeVisible.value = false
+      currentCardName.value = item.title
+      viewCurrent.value = item.id
+    } else {
+      item.flag = false
+    }
+  })
+}
 // 撤销操作的栈
 const undoStack: any = ref([]);
 // 恢复操作的栈
@@ -306,7 +399,7 @@ const onStart = () => {
 //拖拽结束的事件
 const onEnd = (value) => {
   if (value.originalEvent.cancelable && value.to.className == 'Bzuil') {
-    const num = (375 / 2) - (cloneItem.value.css.width / 2)
+    const num = (widthNum.value / 2) - (cloneItem.value.css.width / 2)
     cloneItem.value.css.left = Math.round(num)
     cloneItem.value.css.top = value.originalEvent.offsetY
     cloneItem.value.active = true
@@ -412,6 +505,12 @@ function operationalView(type: any) {
       redoStack.value = []
       extraImgs1.value = []
       currentMove.value = {}
+      viewList.value.forEach(item => {
+        if (item.flag) {
+          viewName.value = item.name
+          item.viewData = extraImgs1.value
+        }
+      })
     }).catch((err) => {
       console.log(err);
     })
@@ -475,19 +574,19 @@ function alignment(params: any) {
         extraImgs1.value[currentIndex.value].css.left = 0
       } else if (params.type == 'centerHorizontally') {
         // 水平居中
-        const num = (375 / 2) - (extraImgs1.value[currentIndex.value].css.width / 2)
+        const num = (widthNum.value / 2) - (extraImgs1.value[currentIndex.value].css.width / 2)
         extraImgs1.value[currentIndex.value].css.left = Math.round(num)
       } else if (params.type == 'right') {
-        const num = 375 - extraImgs1.value[currentIndex.value].css.width
+        const num = widthNum.value - extraImgs1.value[currentIndex.value].css.width
         extraImgs1.value[currentIndex.value].css.left = Math.round(num)
       } else if (params.type == 'top') {
         extraImgs1.value[currentIndex.value].css.top = 0
       } else if (params.type == 'verticalCenter') {
         // 垂直居中
-        const num = (647 / 2) - (extraImgs1.value[currentIndex.value].css.height / 2)
+        const num = (heightNum.value / 2) - (extraImgs1.value[currentIndex.value].css.height / 2)
         extraImgs1.value[currentIndex.value].css.top = Math.round(num)
       } else if (params.type == 'bottom') {
-        const num = 647 - extraImgs1.value[currentIndex.value].css.height
+        const num = heightNum.value - extraImgs1.value[currentIndex.value].css.height
         extraImgs1.value[currentIndex.value].css.top = Math.round(num)
       }
     }
@@ -795,14 +894,79 @@ function getIconSelection(params: any) {
   width: calc(100% - 380px);
 }
 
+.card_selectSize {
+  position: relative;
+  // width: 375px;
+  margin: 40px auto 0px;
+  display: flex;
+  justify-content: flex-end;
+}
+
+.card_size_select {
+  display: flex;
+  align-items: center;
+  cursor: pointer;
+
+  span {
+    font-size: 14px;
+    margin-right: 10px;
+    color: #606266;
+  }
+}
+
+.size_title_select {
+  font-size: 17px;
+  font-weight: 600;
+  margin-right: 10px;
+}
+
+.card_size_item {
+  display: flex;
+  align-items: center;
+  height: 35px;
+  padding: 0px 10px;
+  cursor: pointer;
+
+  span {
+    font-size: 20px;
+    font-weight: 600;
+  }
+}
+
+.card_size_item:hover {
+  background-color: #F2F6FC;
+}
+
 .card_home {
-  width: 375px;
-  margin: 30px auto 0px;
-  height: 667px;
+  // width: 375px;
+  margin: 10px auto 0px;
+  // height: 667px;
   // background-color: red;
   background-color: #fafafa;
   position: relative;
-  overflow: hidden;
+  // overflow: hidden;
+  height: auto;
+}
+
+.card_title_bar {
+  position: relative;
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  height: 44px;
+  margin-right: 6px;
+  margin-left: 6px;
+}
+
+.left_back {
+  position: absolute;
+  left: 0px;
+  margin-right: 6px;
+  margin-left: 6px;
+}
+
+.title_headline_head {
+  font-size: 16px;
 }
 
 .head_image_url {
@@ -812,6 +976,31 @@ function getIconSelection(params: any) {
   user-select: none;
 }
 
+.Bzu {
+  position: relative;
+  overflow: hidden;
+}
+
+.Bzu .ghost {
+  opacity: 0;
+}
+
+.Bzuil {
+  height: 100%;
+}
+
+.card_hint_title {
+  position: absolute;
+  top: 0;
+  left: 0;
+  right: 0;
+  bottom: 0;
+  background-color: rgba(158, 219, 255, 0.2);
+  pointer-events: none;
+  color: rgb(35, 125, 229);
+  font-size: 15px;
+}
+
 .item_module_left {
   cursor: grab;
   width: 100%;
@@ -950,28 +1139,6 @@ img {
   padding: 20px;
 }
 
-.chosenClass {
-  opacity: 1;
-}
-
-.Bzu {
-  height: calc(100% - 20px);
-  position: absolute;
-  top: 20px;
-  bottom: 0;
-  left: 0;
-  right: 0;
-  // overflow: hidden;
-}
-
-.Bzu .ghost {
-  opacity: 0;
-}
-
-.Bzuil {
-  height: 100%;
-}
-
 // 图标篇
 .card_bottom_hint {
   position: absolute;