Переглянути джерело

表单组布局初步搭建/标签页布局,栅格布局,分割线对应数据收集

lph 1 рік тому
батько
коміт
20e5ed4de4

+ 9 - 0
zkqy-ui/src/main.js

@@ -41,6 +41,8 @@ import "@packages/theme/index.scss";
 // bpmnPro end
 
 
+
+
 import '@/assets/styles/index.scss' // global css
 import '@/assets/styles/zkqy.scss' // zkqy css
 // require('@/assets/styles/index.scss')  // global css
@@ -93,6 +95,13 @@ import '@/assets/iconfont/iconfont.js'
 import * as echarts from 'echarts'
 Vue.prototype.$echarts = echarts
 
+// 引入并挂载ant-design
+import Antd from 'ant-design-vue';
+import 'ant-design-vue/dist/antd.css';
+Vue.use(Antd);
+
+
+
 
 // 全局方法挂载
 Vue.prototype.getDicts = getDicts

+ 78 - 6
zkqy-ui/src/views/system/formGroupMange/component/CenterArea.vue

@@ -1,11 +1,9 @@
 <template>
   <div class="center-area">
-    <p class="hint-text" v-show="data.list.length === 0">
+    <!-- <p class="hint-text" v-show="data.list.length === 0">
       <a-empty description="从左侧选择控件添加" />
-    </p>
-
+    </p> -->
     <draggable
-      v-show="data.list.length !== 0"
       tag="div"
       class="draggable-box"
       v-bind="{
@@ -15,6 +13,7 @@
         handle: '.drag-move',
       }"
       v-model="data.list"
+      @end="endHandler"
       @add="deepClone"
       @start="dragStart($event, data.list)"
     >
@@ -41,13 +40,59 @@ import LayoutItem from "./LayoutItem.vue";
 import draggable from "vuedraggable";
 export default {
   name: "CenterArea",
-  props: ["selectItem", "data"],
+  props: ["selectItem", "data", "noModel"],
   components: { LayoutItem, draggable },
   data() {
     return {};
   },
   computed: {},
   methods: {
+    handleCopy(isCopy = true, data) {
+      const traverse = (array) => {
+        array.forEach((element, index) => {
+          if (element.key === this.selectItem.key) {
+            if (isCopy) {
+              // 复制添加到选择节点后面
+              array.splice(index + 1, 0, element);
+            } else {
+              // 双击添加到选择节点后面
+              array.splice(index + 1, 0, data);
+            }
+            // 复制完成,重置key值
+            const evt = {
+              newIndex: index + 1,
+            };
+            this.handleColAdd(evt, array, true);
+            return;
+          }
+          if (["grid", "tabs", "selectInputList"].includes(element.type)) {
+            // 栅格布局
+            element.columns.forEach((item) => {
+              traverse(item.list);
+            });
+          } else if (element.type === "card") {
+            // 卡片布局
+            traverse(element.list);
+          } else if (element.type === "batch") {
+            // 动态表格内复制
+            if (!isCopy && !this.insertAllowedType.includes(data.type)) {
+              // 插入不允许的字段时,直接return false
+              return false;
+            }
+            traverse(element.list);
+          }
+          if (element.type === "table") {
+            // 表格布局
+            element.trs.forEach((item) => {
+              item.tds.forEach((val) => {
+                traverse(val.list);
+              });
+            });
+          }
+        });
+      };
+      traverse(this.data.list);
+    },
     // 递归 删除已选择
     handleDelete(ele) {
       console.log("删除的元素", ele);
@@ -91,6 +136,7 @@ export default {
       this.data.list = traverse(this.data.list);
     },
     deepClone(evt) {
+      console.log("deepClone", evt);
       const newIndex = evt.newIndex;
       // json深拷贝一次
       const listString = JSON.stringify(this.data.list);
@@ -98,6 +144,8 @@ export default {
       // 删除icon及compoent属性
       delete this.data.list[newIndex].icon;
       delete this.data.list[newIndex].component;
+      // this.data.list[newIndex].key =
+      //   this.data.list[newIndex].type + "_" + new Date().getTime();
       this.$emit("setCurrentTarget", this.data.list[newIndex]);
     },
     dragStart(e, list) {
@@ -161,8 +209,32 @@ export default {
       columns[newIndex] = JSON.parse(listString);
       this.$emit("handleSetSelectItem", columns[newIndex]);
     },
+    endHandler(ent) {
+      console.log(ent);
+    },
   },
 };
 </script>
 
-<style scoped lang="scss"></style>
+<style scoped lang="scss">
+.center-area {
+  // height: calc(100% - 40px);
+  height: 100%;
+  background: rgb(221, 221, 221);
+  padding: 5px;
+  position: relative;
+  .hint-text {
+    position: absolute;
+    top: 50%;
+    left: 50%;
+    transform: translate(-50%, -50%);
+  }
+  .draggable-box {
+    height: 100%;
+    overflow: auto;
+    .list-main {
+      height: 100%;
+    }
+  }
+}
+</style>

+ 196 - 4
zkqy-ui/src/views/system/formGroupMange/component/DragPosition.vue

@@ -2,10 +2,25 @@
   <div class="main-wrap">
     <div class="drag-position">
       <!-- 左侧面板区域 start-->
-      <LetfPanel
+      <!-- <LetfPanel
         :formList="formList"
         @handleClick="panelClickHandler"
-      ></LetfPanel>
+        @start="generateKey"
+      ></LetfPanel> -->
+      <a-collapse style="width: 370px">
+        <a-collapse-panel
+          v-for="(item, index) in schemaGroup"
+          :header="item.title"
+          :key="index"
+        >
+          <collapseItem
+            :list="item.list"
+            @generateKey="generateKey"
+            @handleListPush="handleListPush"
+            @start="handleStart"
+          />
+        </a-collapse-panel>
+      </a-collapse>
       <!-- 左侧面板区域 end-->
       <!-- 中间拖拽区域 start-->
       <div class="drag-wrap">
@@ -13,10 +28,14 @@
           :data="layoutData"
           :selectItem="selectItem"
           @setCurrentTarget="setCurrentTarget"
+          :noModel="noModel"
           ref="centerAreaRef"
         ></CenterArea>
       </div>
       <!-- 中间拖拽区域 end-->
+      <!-- 右侧面板区域 start -->
+      <RightPanel class="right-panel" :selectItem="selectItem"></RightPanel>
+      <!-- 右侧面板区域 end -->
     </div>
   </div>
 </template>
@@ -26,25 +45,165 @@ import { formList } from "./tempJson.js";
 
 import LetfPanel from "./LetfPanel.vue";
 import CenterArea from "./CenterArea.vue";
+import collapseItem from "./collapseItem.vue"; //左侧tab
+import RightPanel from "./RightPanel.vue"; //右侧tab
 export default {
   name: "DragPosition",
   props: [],
-  components: { LetfPanel, CenterArea },
+  components: { LetfPanel, CenterArea, collapseItem, RightPanel },
   data() {
     return {
+      startType: "",
       layoutData: {
         list: [],
       },
       mainList: [], //拖拽区域数据
-      selectItem: null, //当前拖拽对象
+      selectItem: {}, //当前拖拽对象
+      noModel: [
+        "button",
+        "divider",
+        "card",
+        "grid",
+        "tabs",
+        "table",
+        "alert",
+        "text",
+        "html",
+      ],
+      schemaGroup: [
+        {
+          title: "表单控件",
+          list: [],
+        },
+        {
+          title: "布局组件",
+          list: [
+            {
+              label: "标签页布局",
+              type: "tabs",
+              options: {
+                tabBarGutter: null,
+                type: "line",
+                tabPosition: "top",
+                size: "default",
+                noFormItem: true,
+                animated: true,
+              },
+              columns: [
+                {
+                  value: "1",
+                  label: "选项1",
+                  list: [],
+                  tableName: "",
+                },
+                {
+                  value: "2",
+                  label: "选项2",
+                  list: [],
+                  tableName: "",
+                },
+              ],
+              key: "",
+              model: "",
+            },
+            {
+              type: "grid",
+              label: "栅格布局",
+              icon: "icon-zhage",
+              columns: [
+                {
+                  span: 12,
+                  list: [],
+                },
+                {
+                  span: 12,
+                  list: [],
+                },
+              ],
+              options: {
+                noFormItem: true,
+                gutter: 0,
+              },
+              key: "",
+              model: "",
+            },
+            {
+              type: "divider",
+              label: "分割线",
+              icon: "icon-fengexian",
+              options: {
+                orientation: "left",
+                noFormItem: true,
+                title: "提示信息",
+              },
+              key: "",
+              model: "",
+            },
+          ],
+        },
+      ],
     };
   },
+  created() {
+    this.schemaGroup[0].list = formList;
+  },
   computed: {
     formList() {
       return formList;
     },
   },
   methods: {
+    handleStart(type) {
+      this.startType = type;
+    },
+    handleListPush(item) {
+      console.log(this.selectItem);
+      console.log(item);
+      // 生成key值
+      // if (!this.selectItem?.key) {
+      // 在没有选择表单时,将数据push到this.data.list
+      const key = item.type + "_" + new Date().getTime();
+      item = {
+        ...item,
+        key,
+        model: key,
+      };
+      if (this.noModel.includes(item.type)) {
+        // 删除不需要的model属性
+        delete item.model;
+      }
+      const itemString = JSON.stringify(item);
+      const record = JSON.parse(itemString);
+      // 删除icon及compoent属性
+      delete record.icon;
+      delete record.component;
+      this.layoutData.list.push(record);
+      this.handleSetSelectItem(record);
+      return false;
+      // }
+      // this.$refs.centerAreaRef.handleCopy(false, item);
+    },
+    handleSetSelectItem(record) {
+      // 操作间隔不能低于100毫秒
+      const newTime = new Date().getTime();
+      if (newTime - this.updateTime < 100) {
+        return false;
+      }
+
+      this.updateTime = newTime;
+
+      // 设置selectItem的值
+      this.selectItem = record;
+      console.log("this.selectItem", this.selectItem);
+
+      // 判断是否选中控件,如果选中则弹出属性面板,否则关闭属性面板
+      // if (record.key) {
+      //   this.startType = record.type;
+      //   this.changeTab(2);
+      // } else {
+      //   this.changeTab(1);
+      // }
+    },
     panelClickHandler(item) {
       this.selectItem = item;
       this.mainList.push(item);
@@ -56,16 +215,49 @@ export default {
       this.selectItem = item;
       console.log("layoutData", this.layoutData);
     },
+    generateKey(list, index) {
+      const key = list[index].type + "_" + new Date().getTime();
+      this.$set(list, index, {
+        ...list[index],
+        key,
+        model: key,
+      });
+      if (this.noModel.includes(list[index].type)) {
+        // 删除不需要的model属性
+        delete list[index].model;
+      }
+    },
   },
 };
 </script>
 
 <style lang="scss" scoped>
+ul {
+  margin: 0;
+  padding: 0;
+  list-style: none;
+  display: flex;
+  flex-wrap: wrap;
+}
+.main-wrap {
+  height: 100%;
+}
 .drag-position {
+  height: 100%;
   display: flex;
   .drag-wrap {
+    // box-sizing: border-box;
+    position: relative;
+    // height: 100%;
     padding: 10px;
     flex: 1;
   }
 }
+.right-panel {
+  width: 350px;
+  border: 1px solid #dddddd;
+  height: 100%;
+  padding: 5px;
+  border-radius: 5px;
+}
 </style>

+ 4 - 2
zkqy-ui/src/views/system/formGroupMange/component/FormCard.vue

@@ -1,7 +1,7 @@
 <template>
   <div class="card-wrap">
     <i class="el-icon-c-scale-to-original mr10"></i>
-    <span>{{ record.title }}</span>
+    <span>{{ record.label }}</span>
   </div>
 </template>
 
@@ -20,8 +20,10 @@ export default {
 
 <style scoped lang="scss">
 .card-wrap {
+  height: 56px;
   width: 100%;
-  padding: 10px;
+  box-sizing: border-box;
+  padding: 0 10px;
   display: flex;
   align-items: center;
   justify-content: center;

+ 9 - 2
zkqy-ui/src/views/system/formGroupMange/component/LayoutItem.vue

@@ -11,7 +11,7 @@
             v-for="(tabItem, index) in record.columns"
             :key="index"
             :label="tabItem.label"
-            :name="tabItem.value"
+            :name="index + ''"
           >
             <div class="grid-box-content">
               <draggable
@@ -106,7 +106,7 @@
     <template v-else-if="record.type == 'divider'">
       <!-- 分割线 -->
       <div
-        class="grid-box"
+        class="grid-box divider-wrap"
         style="width: 100%"
         :class="{ active: record.key === selectItem.key }"
         @click.stop="handleSelectItem(record)"
@@ -183,4 +183,11 @@ export default {
     color: #ee88e5;
   }
 }
+.divider-wrap {
+  height: 50px;
+  background: #fff;
+  display: flex;
+  border: 1px dashed #ccc;
+  justify-content: center;
+}
 </style>

+ 15 - 5
zkqy-ui/src/views/system/formGroupMange/component/LetfPanel.vue

@@ -15,12 +15,16 @@
             ghostClass: 'moving',
           }"
         >
+          <!-- <transition-group tag="div" name="list" class="list-main"> -->
           <el-menu-item
             @click="handleClick(item)"
-            v-for="item in panelList"
-            :key="item.title"
-            >{{ item.title }}</el-menu-item
+            @dragstart="dragstart"
+            :draggable="true"
+            v-for="(item, index) in panelList"
+            :key="index"
+            >{{ item.dfName }}</el-menu-item
           >
+          <!-- </transition-group> -->
         </draggable>
       </el-submenu>
       <el-submenu index="2">
@@ -37,12 +41,14 @@
             ghostClass: 'moving',
           }"
         >
+          <!-- <transition-group tag="div" name="list" class="list-main"> -->
           <el-menu-item
             @click="handleClick(item)"
             v-for="item in layoutList"
-            :key="item.label"
+            :key="item.type"
             >{{ item.label }}</el-menu-item
           >
+          <!-- </transition-group> -->
         </draggable>
       </el-submenu>
     </el-menu>
@@ -124,7 +130,6 @@ export default {
     panelList() {
       let list = this.formList.map((item) => {
         item.type = "form";
-        item.title = item.dfName;
         return item;
       });
       return list;
@@ -136,6 +141,11 @@ export default {
       item.key = item.type + "_" + new Date().getTime();
       this.$emit("handleClick", item);
     },
+    // 开始拖拽回调
+    dragstart(evt) {
+      console.log(111);
+      console.log(evt);
+    },
   },
 };
 </script>

+ 225 - 0
zkqy-ui/src/views/system/formGroupMange/component/RightPanel.vue

@@ -0,0 +1,225 @@
+<template>
+  <div class="panel-wrap">
+    <div class="layOut-panel">
+      <a-empty
+        class="hint-box"
+        v-show="!selectItem.key || selectItem.type === 'form'"
+        description="未选择布局控件"
+      />
+      <el-form
+        v-show="selectItem.type != 'form' && selectItem.key"
+        ref="form"
+        label-width="100px"
+        :inline="true"
+        size="mini"
+      >
+        <h3 class="title">{{ selectItem.label }}</h3>
+        <!-- tabs布局配置 start-->
+        <el-form-item v-if="selectItem.type == 'tabs'" label="页签配置:">
+          <el-row
+            :gutter="5"
+            v-for="(column, index) in selectItem.columns"
+            :key="index"
+            class="mb5"
+          >
+            <el-col :span="7">
+              <el-input v-model="column.label" size="mini" clearable></el-input>
+            </el-col>
+            <el-col :span="7"
+              ><el-input v-model="column.value" size="mini" clearable></el-input
+            ></el-col>
+            <el-col :span="7">
+              <!-- <el-input
+                v-model="column.tableName"
+                size="mini"
+                clearable
+              ></el-input> -->
+              <el-select v-model="column.tableName" clearable filterable>
+                <el-option
+                  v-for="item in tableList"
+                  :key="item.tableName"
+                  :label="item.tableComment"
+                  :value="item.tableName"
+                >
+                  <span class="discribe" style="float: left">{{
+                    item.tableComment
+                  }}</span>
+                  <span style="float: right; color: #8492a6; font-size: 13px">{{
+                    item.tableName
+                  }}</span>
+                </el-option>
+              </el-select>
+            </el-col>
+            <el-col :span="3"
+              ><el-button
+                type="danger"
+                size="mini"
+                @click="deleteColumnHandler(index)"
+                icon="el-icon-delete"
+              ></el-button>
+            </el-col>
+          </el-row>
+          <el-button
+            type="success"
+            size="mini"
+            @click="addColumnHandler"
+            icon="el-icon-plus"
+            >添加页签</el-button
+          >
+        </el-form-item>
+        <!-- tabs布局配置 end-->
+
+        <!-- 栅格布局配置  start -->
+        <el-form-item
+          v-if="selectItem.type == 'grid'"
+          label="栅格间距:"
+          size="normal"
+        >
+          <el-input-number
+            v-model="selectItem.options.gutter"
+            size="mini"
+            :min="0"
+            :max="100"
+            label="描述文字"
+          ></el-input-number>
+        </el-form-item>
+        <el-form-item
+          v-if="selectItem.type == 'grid'"
+          label="列配置项:"
+          size="normal"
+        >
+          <el-row
+            v-for="(columns, index) in selectItem.columns"
+            :key="index"
+            :gutter="20"
+          >
+            <el-col :span="19">
+              <el-input-number
+                v-model="columns.span"
+                size="mini"
+                :min="0"
+                :max="100"
+                label="描述文字"
+              ></el-input-number>
+            </el-col>
+            <el-col :span="5">
+              <el-button
+                type="danger"
+                icon="el-icon-delete"
+                size="mini"
+                @click="deleteColumnHandler(index)"
+              ></el-button>
+            </el-col>
+          </el-row>
+          <el-button
+            type="primary"
+            icon="el-icon-plus"
+            size="mini"
+            @click="addOneColumn"
+            >添加一列</el-button
+          >
+        </el-form-item>
+        <!-- 栅格布局配置  end -->
+
+        <!-- 分割线配置  start -->
+        <el-form-item
+          v-if="selectItem.type == 'divider'"
+          label="提示位置:"
+          size="normal"
+        >
+          <el-radio-group v-model="selectItem.options.orientation" size="mini">
+            <el-radio-button label="left">左</el-radio-button>
+            <el-radio-button label="center">中</el-radio-button>
+            <el-radio-button label="right">右</el-radio-button>
+          </el-radio-group>
+        </el-form-item>
+        <el-form-item
+          v-if="selectItem.type == 'divider'"
+          label="分割信息:"
+          size="normal"
+        >
+          <el-input
+            v-model="selectItem.options.title"
+            size="mini"
+            clearable
+          ></el-input>
+        </el-form-item>
+        <!-- 分割线配置  end -->
+      </el-form>
+    </div>
+  </div>
+</template>
+
+<script>
+import { getUncommonTable } from "@/utils/other";
+export default {
+  name: "RightPanel",
+  props: ["selectItem"],
+  components: {},
+  data() {
+    return {
+      tableList: [],
+    };
+  },
+  watch: {
+    mySelectItem: {
+      handler(nval) {
+        console.log("selectItem", nval);
+      },
+      immediate: true,
+      deep: true,
+    },
+  },
+  computed: {
+    mySelectItem() {
+      return this.selectItem;
+    },
+  },
+  created() {
+    this.getFormList();
+  },
+  methods: {
+    // 删除页签回调
+    deleteColumnHandler(index) {
+      console.log(index);
+      this.selectItem.columns.splice(index, index);
+    },
+    // 添加页签回调
+    addColumnHandler() {
+      this.selectItem.columns.push({
+        value: this.selectItem.columns.length + 1 + "",
+        label: `选项${this.selectItem.columns.length}`,
+        list: [],
+        tableName: "",
+      });
+    },
+    // 添加栅格一列数据
+    addOneColumn() {
+      this.selectItem.columns.push({
+        span: 12,
+        list: [],
+      });
+    },
+    async getFormList() {
+      let par = {
+        ...this.$store.state.user.dataSource,
+      };
+      let res = await getUncommonTable();
+      this.tableList = res;
+    },
+  },
+};
+</script>
+
+<style scoped lang="scss">
+.panel-wrap {
+  .layOut-panel {
+    .title {
+      display: block;
+      height: 30px;
+      text-align: center;
+      line-height: 30px;
+    }
+  }
+}
+</style>

+ 67 - 0
zkqy-ui/src/views/system/formGroupMange/component/collapseItem.vue

@@ -0,0 +1,67 @@
+<template>
+  <draggable
+    tag="ul"
+    :value="list"
+    v-bind="{
+      group: { name: 'form-draggable', pull: 'clone', put: false },
+      sort: false,
+      animation: 180,
+      ghostClass: 'moving',
+    }"
+    @start="handleStart($event, list)"
+  >
+    <li
+      v-for="(val, index) in list"
+      :key="index"
+      @dragstart="$emit('generateKey', list, index)"
+      @click="$emit('handleListPush', val)"
+    >
+      <!-- <svg v-if="val.icon" class="icon" aria-hidden="true">
+        <use :xlink:href="`#${val.icon}`"></use>
+      </svg> -->
+      {{ val.label }}
+    </li>
+  </draggable>
+</template>
+<script>
+import draggable from "vuedraggable";
+export default {
+  name: "collapseItem",
+  props: ["list"],
+  components: {
+    draggable,
+  },
+  methods: {
+    handleStart(e, list) {
+      this.$emit("start", list[e.oldIndex].type);
+    },
+  },
+};
+</script>
+
+<style scoped lang="scss">
+// .li {
+//   list-style: none;
+// }
+
+li {
+  border-radius: 0;
+  border: 0;
+  -webkit-box-shadow: 1px 0 0 0 #ccc, 0 1px 0 0 #ccc, 1px 1px 0 0 #ccc,
+    1px 0 0 0 #ccc inset, 0 1px 0 0 #ccc inset;
+  box-shadow: 1px 0 0 0 #ccc, 0 1px 0 0 #ccc, 1px 1px 0 0 #ccc,
+    inset 1px 0 0 0 #ccc, inset 0 1px 0 0 #ccc;
+  padding: 8px 12px;
+  width: calc(50% - 6px);
+  margin: 2.7px;
+  height: 36px;
+  line-height: 20px;
+  cursor: move;
+  border: 1px solid transparent;
+  border-radius: 3px;
+  -webkit-transition: all 0.3s;
+  transition: all 0.3s;
+  box-sizing: border-box;
+  text-align: center;
+}
+</style>

Різницю між файлами не показано, бо вона завелика
+ 2 - 0
zkqy-ui/src/views/system/formGroupMange/component/tempJson.js


+ 6 - 1
zkqy-ui/src/views/system/formGroupMange/index.vue

@@ -1150,4 +1150,9 @@ export default {
 };
 </script>
 
-<style scoped lang="scss"></style>
+<style scoped lang="scss">
+::v-deep .el-dialog__body {
+  box-sizing: border-box;
+  height: calc(100% - 60px) !important;
+}
+</style>

Деякі файли не було показано, через те що забагато файлів було змінено