zoukankan      html  css  js  c++  java
  • Element-UI实现数据库表关联模型

    效果预览

    父组件

    <template>
      <div id="assoModel">
        <!-- 标题 -->
        <div class="addOptions title-container">
          <div
            class="grid-content title-gap"
            v-for="title in titleList"
            :key="title.label"
            :class="title.class"
          >
            <span>{{ title.label }}</span>
          </div>
        </div>
        <!-- 内容 -->
        <div class="addOptions">
          <div
            v-for="(itemData, itemIndex) in tableData"
            :key="itemData.value"
            class="container"
            :class="{ 'remove-line': tableData.length == 1 }"
          >
            <content-table
              :tableData="tableData"
              :itemData="itemData"
              :itemIndex="itemIndex"
            ></content-table>
          </div>
        </div>
        <div class="footer">
          <el-button type="primary" @click="addOptinons">添加关联条件</el-button>
        </div>
      </div>
    </template>
    
    <script>
    import ContentTable from "./content";
    export default {
      components: {
        ContentTable,
      },
      data() {
        return {
          titleList: [
            {
              label: "数据集字段",
              class: "title-dataSet",
            },
            {
              label: "关联方式",
              class: "type",
            },
            {
              label: "关联维表名",
              class: "title-tableName",
            },
            {
              label: "关联字段",
              class: "fields",
            },
            {
              label: "操作",
              class: "handle",
            },
          ],
          tableData: [
            {
              dataSet: {
                name: "data-set",
                class: "dataSet",
                data: [
                  {
                    label: "商品ID",
                    value: "id",
                  },
                  {
                    label: "价格",
                    value: "price",
                  },
                  {
                    label: "数量",
                    value: "number",
                  },
                ],
              },
              type: {
                name: "type",
                class: "mode",
                data: ["关联方式"],
              },
    
              table: {
                name: "tables",
                class: "tables",
                data: [
                  {
                    label: "airbnb_listings",
                    value: "airbnb_listings",
                  },
                  {
                    label: "aipl_user_online",
                    value: "aipl_user_online",
                  },
                  {
                    label: "airbnb_calendar",
                    value: "airbnb_calendar",
                  },
                ],
              },
              field: {
                name: "field",
                class: "fields",
                data: [
                  {
                    label: "date",
                    value: "date",
                  },
                  {
                    label: "listing_id",
                    value: "listing_id",
                  },
                  {
                    label: "price",
                    value: "price",
                  },
                ],
              },
              delete: {
                name: "delete",
                class: "delete",
              },
            },
          ],
        };
      },
      methods: {
        addOptinons() {
          this.tableData.push({
            dataSet: {
              name: "data-set",
              class: "dataSet",
              data: [
                {
                  label: "商品ID",
                  value: "id",
                },
                {
                  label: "价格",
                  value: "price",
                },
                {
                  label: "数量",
                  value: "number",
                },
              ],
            },
            type: {
              name: "type",
              class: "mode",
            },
            table: {
              name: "tables",
              class: "tables",
            },
            field: {
              name: "field",
              class: "fields",
              data: [
                {
                  label: "date",
                  value: "date",
                },
                {
                  label: "listing_id",
                  value: "listing_id",
                },
                {
                  label: "price",
                  value: "price",
                },
              ],
            },
            delete: {
              name: "delete",
              class: "delete",
            },
          });
        },
      },
    };
    </script>
    
    <style scoped>
    #assoModel {
      min-height: 500px;
    }
    #assoModel .addOptions .container {
      padding: 2px 10px;
      display: flex;
      flex-wrap: nowrap;
      border: none;
    }
    
    #assoModel .addOptions {
      position: relative;
      height: auto;
    }
    #assoModel .grid-content {
      display: inline-block;
      height: auto;
    }
    #assoModel .title-container {
      padding: 5px 10px;
      display: flex;
      flex-wrap: nowrap;
      /* justify-content: space-around; */
    }
    #assoModel .grid-content.dataSet {
       23%;
      text-align: center;
    }
    #assoModel .grid-content.title-dataSet {
       23%;
      text-align: center;
    }
    #assoModel .grid-content.type {
       10%;
      text-align: center;
    }
    #assoModel .grid-content.tableName {
       24%;
      text-align: center;
    }
    #assoModel .grid-content.title-tableName {
       24%;
      text-align: center;
    }
    #assoModel .grid-content.fields {
       16%;
      text-align: center;
    }
    #assoModel .grid-content.handle {
       10%;
      text-align: center;
    }
    #assoModel .title-gap {
      margin-right: 30px;
    }
    #assoModel .el-select {
       100%;
    }
    #assoModel .grid-content.mode {
       10%;
      height: calc(100% - 20px);
      text-align: center;
    }
    
    #assoModel .grid-content.tables {
       24%;
      height: calc(100% - 20px);
      text-align: center;
    }
    
    #assoModel .footer {
      padding: 10px;
    }
    #assoModel .footer .el-button--primary {
       100%;
      background-color: #476dbe;
      border-color: #476dbe;
    }
    </style>
    <style >
    .remove-line.container:last-child
      #add-relation
      .el-input.el-input--suffix:after {
       0px;
    }
    .remove-line.container:last-child #field .el-input.el-input--suffix:before {
       0px;
    }
    </style>
    

    子组件

    content.vue
    <template>
      <div style=" 100%">
        <div
          v-for="item in itemData"
          :key="item.name"
          class="grid-content title-gap"
          :class="item.class"
        >
          <component
            v-if="item.name"
            :is="item.name"
            :itemData="item"
            :itemIndex="itemIndex"
            :tableData="tableData"
            :ref="item.name"
          ></component>
        </div>
      </div>
    </template>
    </template>
    
    <script>
    export default {
      props: {
        tableData: Array,
        itemData: Object,
        itemIndex: Number,
      },
      data() {
        return {
          name: "data-set",
        };
      },
    };
    </script>
    
    <style scoped>
    .grid-content {
      display: inline-block;
      height: auto;
    }
    .title-gap {
      margin-right: 30px;
    }
    .grid-content.dataSet {
       23%;
      text-align: center;
    }
    .grid-content.mode {
       10%;
      height: calc(100% - 20px);
      text-align: center;
    }
    .grid-content.mode .mode-content {
      position: absolute;
      margin: auto;
      top: 0px;
      bottom: 0;
      height: 30px;
       9.5%;
      border: 1px solid #ccc;
    }
    .grid-content.tables {
       24%;
      height: calc(100% - 20px);
      text-align: center;
    }
    .grid-content.fields {
       16%;
      text-align: center;
    }
    .grid-content.delete {
       6%;
      /*  10%; */
      text-align: center;
    }
    </style>
    
    dataset.vue
    <template>
    <!-- 数据集字段 -->
      <div id="add-relation">
        <el-select v-model="dataSet" placeholder="请选择">
          <el-option
            v-for="item in itemData.data"
            :key="item.value"
            :label="item.label"
            :value="item.value"
          >
          </el-option>
        </el-select>
      </div>
    </template>
    <script>
    export default {
      props: { itemData: Object },
      data() {
        return {
          dataSet: [],
        };
      },
    };
    </script>
    
    <style>
    #add-relation .el-input.el-input--suffix:after {
      content: "";
       10px;
      height: 49px;
      border-right: 1px solid #ccc;
      border-top: 1px solid #ccc;
      position: absolute;
      top: 17px;
    }
    #add-relation .el-input.el-input--suffix:before {
      position: absolute;
      content: "";
       5px;
      height: 100%;
      background-color: #42a948;
    }
    #assoModel
      .container:last-child
      #add-relation
      .el-input.el-input--suffix:after {
      height: 0px;
    }
    </style>
    
    delete.vue
    <template>
    <!-- 操作 -->
      <div class="grid-content">
        <span v-html="svgImg.delete" @click="handleDelete" class="iconfont"></span>
      </div>
    </template>
    
    <script>
    export default {
      props: {
        tableData: Array,
        itemIndex: Number,
      },
      data() {
        return {
          svgImg: this.$svgImg,
        };
      },
      methods: {
        handleDelete() {
          if (this.tableData.length <= 1) {
            return;
          }
          this.tableData.splice(this.itemIndex, 1);
        },
      },
    };
    </script>
    
    <style scoped>
    </style>
    
    field.vue
    <template>
      <!-- 关联字段 -->
      <div id="field">
        <el-select v-model="selectdField" placeholder="">
          <el-option
            v-for="item in itemData.data"
            :key="item.value"
            :label="item.label"
            :value="item.value"
          >
          </el-option>
        </el-select>
      </div>
    </template>
    
    <script>
    export default {
      props: {
        itemData: Object,
      },
      data() {
        return {
          selectdField: [],
        };
      },
    };
    </script>
    
    <style>
    #field .el-input.el-input--suffix:before {
      content: "";
       10px;
      height: 49px;
      border-left: 1px solid #ccc;
      border-top: 1px solid #ccc;
      position: absolute;
      top: 17px;
      left: -10px;
    }
    #field .el-input.el-input--suffix:after {
      position: absolute;
      content: "";
       5px;
      height: 100%;
      background-color: #42a948;
      left: 0px;
    }
    #assoModel .container:last-child #field .el-input.el-input--suffix:before {
      height: 0px;
    }
    </style>
    
    tables.vue
    <template>
      <!-- 关联维表名 -->
      <div class="tables-content" v-if="itemData && itemData.data">
        <el-select v-model="selectdField" placeholder="请选择">
          <el-option
            v-for="item in itemData.data"
            :key="item.value"
            :label="item.label"
            :value="item.value"
          >
          </el-option>
        </el-select>
      </div>
    </template>
    
    <script>
    export default {
      props: {
        itemData: Object,
      },
      data() {
        return {
          selectdField: "",
        };
      },
    };
    </script>
    
    <style scoped>
    .grid-content.tables .tables-content {
      position: absolute;
      margin: auto;
      top: 0px;
      bottom: 0;
      height: 30px;
       23.5%;
      top: -4px;
    }
    /* 关联维表名 */
    .tables-content:after {
      position: absolute;
      content: "";
       15px;
      height: 1px;
      background-color: #ccc;
      right: -20px;
      top: 19.5px;
    }
    </style>
    
    type.vue
    <template>
      <!-- 关联方式 -->
      <div id="type-container" v-if="itemData && itemData.data">
        <div class="mode-content">
          <el-select
            v-model="selectedTypeLabel"
            placeholder=""
            @change="changeSelection"
            ref="select"
          >
            <el-option
              v-for="item in typeOptions"
              :key="item.value"
              :label="item.label"
              :value="item.value"
            >
              <img :src="item.label" class="imgSize" />
            </el-option>
          </el-select>
        </div>
      </div>
    </template>
    
    <script>
    export default {
      props: {
        itemData: Object,
        tableData: Array,
      },
      data() {
        return {
          svgImg: this.$svgImg,
          selectedType: "",
          selectedTypeLabel: "",
          typeOptions: [
            {
              label: require("../../../assets/imgs/left-join.png"),
              value: "left",
            },
            {
              label: require("../../../assets/imgs/inner-join.png"),
              value: "inner",
            },
          ],
        };
      },
      mounted() {
        this.changeSelection("inner");
      },
      methods: {
        changeSelection(e) {
          this.itemData.selectedTypeLabel = this.$lodash.clone(
            this.selectedTypeLabel
          );
          this.selectedTypeLabel = "";
          this.itemData;
          for (let index in this.typeOptions) {
            let obj = this.typeOptions[index];
            if (obj.value == e) {
              console.log("ffff");
              this.$refs["select"].$el.children[0].children[0].setAttribute(
                "style",
                "background:url(" +
                  obj.label +
                  ") no-repeat;color:#fff;text-indent: -9999px;background-position: 18% center;background-size:contain;background-size:43%"
              );
            }
          }
        },
      },
      watch: {
        tableData: {
          handler(e) {
            // console.log(e);
            console.log("watch");
            if (this.itemData.selectedTypeLabel) {
              this.changeSelection(this.itemData.selectedTypeLabel);
            }
          },
          deep: true,
        },
      },
    };
    </script>
    
    <style scoped>
    .mode-content {
      position: absolute;
      margin: auto;
      top: 0px;
      bottom: 0;
      height: 30px;
       9.5%;
      top: -4px;
    }
    
    .type-switch {
      position: absolute;
       100%;
      height: 55px;
      border: 1px solid #ddd;
      z-index: 9999;
      top: 33px;
      background-color: #fff;
    }
    .type-switch .switch-icon-left {
      position: absolute;
       100%;
      height: 50%;
      left: 0px;
    }
    .type-switch .switch-icon-inner {
      position: absolute;
       100%;
      height: 50%;
      left: 0px;
      bottom: 0px;
    }
    .imgSize {
       30px;
    }
    </style>
    <style >
    .switch-icon-color > svg {
      font-size: 15px;
       24px;
      height: 30px;
      fill: #09c;
    }
    
    #type-container .el-input.el-input--suffix:before {
      position: absolute;
      content: "";
       15px;
      height: 1px;
      background-color: #ccc;
      left: -20px;
      top: 19px;
    }
    </style>
    
  • 相关阅读:
    hdu4417 Super Mario
    bzoj3110 zjoi2013 K大数查询
    转:如何理解c和c ++的复杂类型声明
    UVa 489 刽子手游戏
    bzoj1006 神奇的国度
    bzoj2764 基因补全
    bzoj2338 数矩形
    bzoj3720 gty的妹子树
    Struts2(一)入门及工作原理
    输入人民币/美元后自动判断,输出转换后相对应的值
  • 原文地址:https://www.cnblogs.com/xxr0218/p/14096868.html
Copyright © 2011-2022 走看看