vueはお腹が空きましたか?UIを使ってteambitionの選別機能をまねる。


問題の説明
teambitionソフトウェアは企業のオフィス協同ソフトウェアです。一部の友達の会社がこのソフトを使ったことがあると信じています。この文章はその機能をまねることです。まず最終的に作った効果図を見ます。

大体の機能効果は以下の通りです。
  • 需要の一:常用フィルタ条件は上に置いて直接見て、常用フィルタ条件は追加フィルタ条件の中に置かれていません。
  • デマンド二:スクリーニングの方式は入力枠スクリーニング、プルダウン枠スクリーニング、タイムセレクタスクリーニングなどの
  • があります。
  • 需要3:もし、常用フィルタ条件が多いと感じたら、マウスをクリックして削除し、非常用のフィルタ条件に入れることができます。
  • 需要四:よく使われているスクリーニング条件から対応するスクリーニング条件をクリックして「跳ぶ」ようにすることもできます。
  • 需要5:リセットをクリックして、初回試験のスクリーニング条件
  • に戻す。
  • 需要六:もしユーザが内容を入力していないなら、確認ボタンをクリックすると、スクリーニング条件を入力するようにユーザに促す。
  • 考え方の分析
    需要の1と需要の2つについては、まず2つのフルスクリーン弾のフレームを作って、dataで2つの配列を定義します。一つは常用条件を入れる行列で、もう一つは非常用条件の行列です。常用条件v-forは第1弾のボックスの中に入っています。常用条件v-forは第2弾のボックスの中に入っていません。配列内の各項目には、名前や年齢など、フィルタフィールドの名前が必要です。フィルタフィールドの名前があったら、タイプタイプタイプタイプのタイプがあります。これには3つのタイプのコンポーネント、たとえばinput入力ボックスのコンポーネント、selectコンポーネント、タイムセレクタのコンポーネントを書きます。typeの種類に応じて対応するフィールドをv-showで表示します。例えば、inputのtypeは1、selectのtypeは2、時間セレクタのtypeは3です。どのタイプかを表示します。
    対応する2つの配列は以下の通りです。
    
    topData: [ //         
        {
         wordTitle: "  ",
         type: 1, // 1  input 2 select 3 DatePicker
         content: "", // content           
         options: [], // options         ,          ,     
         optionArr: [], // optionArr         
         timeArr: [], // timeArr       
        },
        {
         wordTitle: "  ",
         type: 1,
         content: "",
         options: [],
         optionArr: [],
         timeArr: [],
        },
        {
         wordTitle: "    ",
         type: 2,
         content: "",
         options: [ //           
          {
           id: 1,
           value: "  ",
          },
          {
           id: 2,
           value: "  ",
          },
          {
           id: 3,
           value: "  ",
          },
         ],
         optionArr: [],
         timeArr: [],
        },
        {
         wordTitle: "    ",
         type: 3, 
         content: "", 
         options: [], 
         optionArr: [], 
         timeArr: [], 
        },
       ],
       bottomData: [ //          
        {
         wordTitle: "  ",
         type: 1,
         content: "",
         options: [],
         optionArr: [],
         timeArr: [],
        },
        {
         wordTitle: "  ",
         type: 2,
         content: "",
         options: [
          {
           id: 1,
           value: " ",
          },
          {
           id: 2,
           value: " ",
          },
         ],
         optionArr: [],
         timeArr: [],
        },
       ],
    対応するhtmlコードは以下の通りです。
    
            <div class="rightright">
             <el-input
              v-model.trim="item.content"
              clearable
              v-show="item.type == 1"
              placeholder="   "
              size="small"
              :popper-append-to-body="false"
             ></el-input>
             <el-select
              v-model="item.optionArr"
              v-show="item.type == 2"
              multiple
              placeholder="   "
             >
              <el-option
               v-for="whatItem in item.options"
               :key="whatItem.id"
               :label="whatItem.value"
               :value="whatItem.id"
               size="small"
              >
              </el-option>
             </el-select>
             <el-date-picker
              v-model="item.timeArr"
              v-show="item.type == 3"
              type="daterange"
              range-separator=" "
              start-placeholder="    "
              end-placeholder="    "
              format="yyyy-MM-dd"
              value-format="yyyy-MM-dd"
             >
             </el-date-picker>
            </div>
    
    完全なコードは最後になります。みんなは先に考えに沿って見ます。
    需要三の需要四については、上のものを削除して下に落ちると記述することができる。下のをクリックして上にジャンプしてください。したがって、対応する操作は、上の配列のいずれかを下の配列に追加し、上の配列の項目を削除します。下の配列の項目を上の配列に追加して、この行を削除します。注意インデックスがもう一つあります。対応コードは以下の通りです。
    
    /*            ,       bottomData   
               topData      (          ) 
                         -1  */
      clickIcon(i) {
       this.bottomData.push(this.topData[i]);
       this.topData.splice(i, 1);
       this.whichIndex = -1;
      },
      //          ,      ,            
      //             topData     ,   bottom  
      //          
      clickBottomItem(event) {
       this.bottomData.forEach((item, index) => {
        if (item.wordTitle == event.target.innerText) {
         this.topData.push(item);
         this.bottomData.splice(index, 1);
        }
       });
      },
    
    需要五の需要六については簡単です。対応コードは以下の通りです。完全なコードの注釈にもう書きました。
    完全コード
    
    <template>
     <div id="app">
      <div class="filterBtn">
       <el-button type="primary" size="small" @click="filterMaskOne = true">
            <i class="el-icon-s-operation el-icon--right"></i>
       </el-button>
       <transition name="fade">
        <div
         class="filterMaskOne"
         v-show="filterMaskOne"
         @click="filterMaskOne = false"
        >
         <div class="filterMaskOneContent" @click.stop>
          <div class="filterHeader">
           <span>    </span>
          </div>
          <div class="filterBody">
           <div class="outPrompt" v-show="topData.length == 0">
                  ,       ...
           </div>
           <div
            class="filterBodyCondition"
            v-for="(item, index) in topData"
            :key="index"
           >
            <div
             class="leftleft"
             @mouseenter="mouseEnterItem(index)"
             @mouseleave="mouseLeaveItem(index)"
            >
             <span
              >{{ item.wordTitle }}:
              <i
               class="el-icon-error"
               v-show="whichIndex == index"
               @click="clickIcon(index)"
              ></i>
             </span>
            </div>
            <div class="rightright">
             <el-input
              v-model.trim="item.content"
              clearable
              v-show="item.type == 1"
              placeholder="   "
              size="small"
              :popper-append-to-body="false"
             ></el-input>
             <el-select
              v-model="item.optionArr"
              v-show="item.type == 2"
              multiple
              placeholder="   "
             >
              <el-option
               v-for="whatItem in item.options"
               :key="whatItem.id"
               :label="whatItem.value"
               :value="whatItem.id"
               size="small"
              >
              </el-option>
             </el-select>
             <el-date-picker
              v-model="item.timeArr"
              v-show="item.type == 3"
              type="daterange"
              range-separator=" "
              start-placeholder="    "
              end-placeholder="    "
              format="yyyy-MM-dd"
              value-format="yyyy-MM-dd"
             >
             </el-date-picker>
            </div>
           </div>
          </div>
          <div class="filterFooter">
           <div class="filterBtn">
            <el-button
             type="text"
             icon="el-icon-circle-plus-outline"
             @click="filterMaskTwo = true"
             >      </el-button
            >
            <transition name="fade">
             <div
              class="filterMaskTwo"
              v-show="filterMaskTwo"
              @click="filterMaskTwo = false"
             >
              <div class="filterMaskContentTwo" @click.stop>
               <div class="innerPrompt" v-show="bottomData.length == 0">
                    ...
               </div>
               <div
                class="contentTwoItem"
                @click="clickBottomItem"
                v-for="(item, index) in bottomData"
                :key="index"
               >
                <div class="mingzi">
                 {{ item.wordTitle }}
                </div>
               </div>
              </div>
             </div>
            </transition>
           </div>
           <div class="resetAndConfirmBtns">
            <el-button size="small" @click="resetFilter">  </el-button>
            <el-button type="primary" size="small" @click="confirmFilter"
             >  </el-button
            >
           </div>
          </div>
         </div>
        </div>
       </transition>
      </div>
     </div>
    </template>
    
    <script>
    export default {
     name: "app",
     data() {
      return {
       filterMaskOne: false, //                 
       filterMaskTwo: false,
       whichIndex: -1, //          
       apiFilterArr:[], //           
       topData: [ //         
        {
         wordTitle: "  ",
         type: 1, // 1  input 2 select 3 DatePicker
         content: "", // content           
         options: [], // options         
         optionArr: [], // optionArr         
         timeArr: [], // timeArr       
        },
        {
         wordTitle: "  ",
         type: 1,
         content: "",
         options: [],
         optionArr: [],
         timeArr: [],
        },
        {
         wordTitle: "    ",
         type: 2,
         content: "",
         options: [ //           
          {
           id: 1,
           value: "  ",
          },
          {
           id: 2,
           value: "  ",
          },
          {
           id: 3,
           value: "  ",
          },
         ],
         optionArr: [],
         timeArr: [],
        },
        {
         wordTitle: "    ",
         type: 3, 
         content: "", 
         options: [], 
         optionArr: [], 
         timeArr: [], 
        },
       ],
       bottomData: [ //          
        {
         wordTitle: "  ",
         type: 1,
         content: "",
         options: [],
         optionArr: [],
         timeArr: [],
        },
        {
         wordTitle: "  ",
         type: 2,
         content: "",
         options: [
          {
           id: 1,
           value: " ",
          },
          {
           id: 2,
           value: " ",
          },
         ],
         optionArr: [],
         timeArr: [],
        },
       ],
      };
     },
     mounted() {
      //          ,                       
      //             ,                  
      sessionStorage.setItem("topData",JSON.stringify(this.topData))
      sessionStorage.setItem("bottomData",JSON.stringify(this.bottomData))
     },
     methods: {
      //           
      mouseEnterItem(index) {
       this.whichIndex = index;
      },
      //             -1
      mouseLeaveItem() {
       this.whichIndex = -1;
      },
      /*            ,       bottomData   
               topData      (          ) 
                         -1  */
      clickIcon(i) {
       this.bottomData.push(this.topData[i]);
       this.topData.splice(i, 1);
       this.whichIndex = -1;
      },
      //          ,      ,            
      //             topData     ,   bottom  
      //          
      clickBottomItem(event) {
       this.bottomData.forEach((item, index) => {
        if (item.wordTitle == event.target.innerText) {
         this.topData.push(item);
         this.bottomData.splice(index, 1);
        }
       });
      },
      //       
      async confirmFilter() {
       //          content    ,           ,             
       //            ,                     
       let isEmpty = this.topData.every((item)=>{
        return (item.content == "") && (item.optionArr.length == 0) && (item.timeArr.length == 0)
       })
       if(isEmpty == true){
         this.$alert('            ', '    ', {
         confirmButtonText: '  '
        });
       }else{
        //          ,      ,              
        //              ,        。
        this.topData.forEach((item)=>{
         if(item.type == 1){
          if(item.content != ""){
           let filterItem = {
            field:item.wordTitle,
            value:item.content
           }
           this.apiFilterArr.push(filterItem)
          }
         }else if(item.type == 2){
          if(item.optionArr.length > 0){
           let filterItem = {
            field:item.wordTitle,
            value:item.optionArr
           }
           this.apiFilterArr.push(filterItem)
          }
         }else if(item.type == 3){
          if(item.timeArr.length > 0){
           let filterItem = {
            field:item.wordTitle,
            value:item.timeArr
           }
           this.apiFilterArr.push(filterItem)
          }
         } 
        })
        //               ,     (              )
        //              ,      
        console.log("         ",this.apiFilterArr);
       }
      },
      //    ,                      
      resetFilter() {
       this.topData = JSON.parse(sessionStorage.getItem("topData"))
       this.bottomData = JSON.parse(sessionStorage.getItem("bottomData"))
      },
     },
    };
    </script>
    <style lang="less" scoped>
    .filterBtn {
     width: 114px;
     height: 40px;
     .filterMaskOne {
      top: 0;
      left: 0;
      position: fixed;
      width: 100%;
      height: 100%;
      z-index: 999;
      background-color: rgba(0, 0, 0, 0.3);
      .filterMaskOneContent {
       position: absolute;
       top: 152px;
       right: 38px;
       width: 344px;
       height: 371px;
       background-color: #fff;
       box-shadow: 0px 0px 4px 3px rgba(194, 194, 194, 0.25);
       border-radius: 4px;
       .filterHeader {
        width: 344px;
        height: 48px;
        border-bottom: 1px solid #e9e9e9;
        span {
         display: inline-block;
         font-weight: 600;
         font-size: 16px;
         margin-left: 24px;
         margin-top: 16px;
        }
       }
       .filterBody {
        width: 344px;
        height: 275px;
        overflow-y: auto;
        overflow-x: hidden;
        box-sizing: border-box;
        padding: 12px 24px 0 24px;
        .outPrompt {
         color: #666;
        }
        .filterBodyCondition {
         width: 100%;
         min-height: 40px;
         display: flex;
         margin-bottom: 14px;
         .leftleft {
          width: 88px;
          height: 40px;
          display: flex;
          align-items: center;
          margin-right: 20px;
          span {
           position: relative;
           font-size: 14px;
           color: #333;
           i {
            color: #666;
            right: -8px;
            top: -8px;
            position: absolute;
            font-size: 15px;
            cursor: pointer;
           }
           i:hover {
            color: #5f95f7;
           }
          }
         }
         .rightright {
          width: calc(100% - 70px);
          height: 100%;
          /deep/ input::placeholder {
           color: rgba(0, 0, 0, 0.25);
           font-size: 13px;
          }
          /deep/ .el-input__inner {
           height: 40px;
           line-height: 40px;
          }
          /deep/ .el-select {
           .el-input--suffix {
            /deep/ input::placeholder {
             color: rgba(0, 0, 0, 0.25);
             font-size: 13px;
            }
            .el-input__inner {
             border: none;
            }
            .el-input__inner:hover {
             background: rgba(95, 149, 247, 0.05);
            }
           }
          }
          .el-date-editor {
           width: 100%;
           font-size: 12px;
          }
          .el-range-editor.el-input__inner {
           padding-left: 2px;
           padding-right: 0;
          }
          /deep/.el-range-input {
           font-size: 13px !important;
          }
          /deep/ .el-range-separator {
           padding: 0 !important;
           font-size: 12px !important;
           width: 8% !important;
           margin: 0;
          }
          /deep/ .el-range__close-icon {
           width: 16px;
          }
         }
        }
       }
       .filterFooter {
        width: 344px;
        height: 48px;
        display: flex;
        justify-content: space-between;
        align-items: center;
        box-sizing: border-box;
        padding-left: 24px;
        padding-right: 12px;
        border-top: 1px solid #e9e9e9;
        .filterBtn {
         .filterMaskTwo {
          position: fixed;
          top: 0;
          left: 0;
          width: 100%;
          height: 100%;
          background-color: rgba(0, 0, 0, 0.3);
          z-index: 1000;
          .filterMaskContentTwo {
           width: 240px;
           height: 320px;
           background: #ffffff;
           box-shadow: 0px 0px 4px 3px rgba(194, 194, 194, 0.25);
           border-radius: 4px;
           position: absolute;
           top: 360px;
           right: 180px;
           overflow-y: auto;
           box-sizing: border-box;
           padding: 12px 0 18px 0;
           overflow-x: hidden;
           .innerPrompt {
            color: #666;
            width: 100%;
            padding-left: 20px;
            margin-top: 12px;
           }
           .contentTwoItem {
            width: 100%;
            height: 36px;
            line-height: 36px;
            font-size: 14px;
            color: #333333;
            cursor: pointer;
            .mingzi {
             width: 100%;
             height: 36px;
             box-sizing: border-box;
             padding-left: 18px;
            }
           }
           .contentTwoItem:hover {
            background: rgba(95, 149, 247, 0.05);
           }
          }
         }
        }
       }
      }
     }
    }
    //         
    .fade-enter-active,
    .fade-leave-active {
     transition: opacity 0.3s;
    }
    .fade-enter,
    .fade-leave-to {
     opacity: 0;
    }
    </style>
    
    
    締め括りをつける
    この中で注意したいのは、マウスを移動して対応する削除アイコンを表示します。考えは大体このようにして、コードを打つのは容易ではないです。私達は共に努力します。
    以上はvueを使ってお腹が空きましたか?UIを使ってteambitionの選別機能の詳しい内容をまねるということです。もっと多いのはvue模写teambitionの選別機能に関する資料です。他の関連記事に注目してください。