preface

This article is mainly to record, I encountered some problems in the use of tag tags, because it is the back-end management system in the tag management page, so only the basic add, delete, change and check functions… Well, without further ado, let’s get right to it

The Tag label

Because we need to make changes to the Tag, we use the dynamic edit Tag inside the Tag directly to use the code

<el-tag
  :key="tag"
  v-for="tag in dynamicTags"
  closable
  :disable-transitions="false"
  @close="handleClose(tag)">
  {{tag}}
</el-tag>
<el-input
  class="input-new-tag"
  v-if="inputVisible"
  v-model="inputValue"
  ref="saveTagInput"
  size="small"
  @keyup.enter.native="handleInputConfirm"
  @blur="handleInputConfirm"
>
</el-input>
<el-button v-else class="button-new-tag" size="small" @click="showInput">+ New Tag</el-button>

<style>
.el-tag + .el-tag {
  margin-left: 10px;
}
.button-new-tag {
  margin-left: 10px;
  height: 32px;
  line-height: 30px;
  padding-top: 0;
  padding-bottom: 0;
}
.input-new-tag {
  width: 90px;
  margin-left: 10px;
  vertical-align: bottom;
}
</style>

<script>
export default {
  data() {
    return {
      dynamicTags: ["Tag 1"."Tag 2"."Tag 3"].inputVisible: false.inputValue: ""}; },methods: {
    handleClose(tag) {
      this.dynamicTags.splice(this.dynamicTags.indexOf(tag), 1);
    },

    showInput() {
      this.inputVisible = true;
      this.$nextTick((_) = > {
        this.$refs.saveTagInput.$refs.input.focus();
      });
    },

    handleInputConfirm() {
      let inputValue = this.inputValue;
      if (inputValue) {
        this.dynamicTags.push(inputValue);
      }
      this.inputVisible = false;
      this.inputValue = ""; ,}}};</script>

Copy the code

This gives you a basic Tag page directly

Fetch data acquisition interface

Call their own encapsulated data interface, take the data returned by the back end… After I saw my data format returned to the back end, I knew that the add, delete, change and search function after this page would not be very easy to implement… And the data looks like this…

When I see the continuous nesting of data, I feel like MY head is getting a little too big… Call the interface directly to get the data:

  
    // Get data
    getdata() {
      getwarninglabel({
        pageNum: this.pageNum,
        pageSize: this.pageSize,
      }).then((res) = > {
        console.log(res);
        this.total = res.data.count; / / paging
        this.tagtitle = res.data.results; According to the total / /
      });
    },
Copy the code

The first layer is traversed to get the data of each keyword through item.keywords, and then the item.keywords is traversed again to cycle the data in the keywords. The code is as follows:

<div v-for="(item, ki) in tagtitle" :key="ki" class="text item"<span> {{item.label_name}}</span> // tag title </div> <div> <el-tag :key="indext" // loop item.keywords, V -for="(tag, indext) in item.keywords" :disable-transitions="false" closable @close="handleClose(tag)" > {{ tag }} </el-tag>Copy the code

At this point, the basic rendering of the page data is complete, and the additional functionality can be added

Button to add

According to requirements, the delete icon will appear after the tag tag only when the edit button is clicked, and the edit button will become the save submit button. Therefore, whether the delete icon appears and the switch of the Edit/save button need to be processed

  1. Add edit/Save and module delete buttons
<el-button
            @click="hangdelDelete(item.id)"
            style="float: right; padding: 3px 0; color: red"
            type="text"</el-button > <el-button v-show="activeIndex! = ki" @click="handelUpdata(item.id, ki)" style="float: right; padding: </el-button > <el-button v-show="activeIndex === ki" @click="handelUpdatat(item.id, ki)" style="float: right; Padding-right: 3px 0" type="text" > </el-button >Copy the code

2. To control whether the deletion button of the tag tag appears, I directly deleted the deletion icon of the tag tag, that is, closable. Then I added an icon icon at the end of the tag to check whether it is displayed by v-show

<el-tag
            :key="indext"
            v-for="(tag, indext) in item.keywords"
            :disable-transitions="false"
          >
            {{ tag }}
            <i
              v-show="activeIndex === ki"
              class="el-icon-circle-close"
              @click="handleClose(tag,indext)"
            ></i>
          </el-tag>
Copy the code

The results are as follows:

Have a problem

Already written the edit/save, delete delete icon button and tag the labels, and to determine whether or not they show also, this is met the first question, however, that is when click the edit button, all the tag label behind the icon icon, all of the edit button at the same time also turned out to be saved, displayed the following problems:

At this point, the need to deal with is how to achieve click which label module, which note module to change, rather than all changes, the solution is as follows:

Define a field and give it an initial value, such as -1, because index sorts from0Start, so it can't be assigned to0
 activeIndex: -1, two, will v-show whether the displaytrue/falseTo judge, change to assign the obtained index value to the value after activeIndex when clicking, equal totrue, to show, not equalfalse, do not displayCopy the code

The code is as follows:

<div v-for="(item, ki) in tagtitle" :key="ki" class="text item"> 
<el-button
            @click="handelUpdata(item.id, ki)"// Take the render sort valuestyle="float: right; padding: 3px 0"
            type="text"
            ></el-button > // method handelUpdata(id, ki) {//ki index sort console.log(id); console.log(ki); this.activeIndex = ki; // Assign the sort value to activeIndex} // use<i
              v-show="activeIndex === ki"// Can be used to determine whether to displayclass="el-icon-circle-close"
              @click="handleClose(tag,indext)"
            ></i>
Copy the code

The functions are as follows:

Delete function

Module deletion function is relatively simple, directly pass the module ID from the back end, pass the ID to the back end, the main solution here is to delete the tag tag, these tags have no ID, open the tag, check the implementation of the deletion function:

Use this method directly, but you will suddenly find that the data format returned by the back end is different from the required data format:

Element UI data format:

Data format returned from the back end:

In other words, if you use Element UI’s built-in methods, you need to use the same data format as results[0].

Through this comparison, it is easy to think through the module index value, when click, put the value of the index in the results []. Keywords, can get the data in each of the keywords, after in the newly defined in the array, way to tag the labels used to own:

this.dynamicTags.splice(this.dynamicTags.indexOf(tag), 1); The implementation code is as follows:

Define a new array

 deleIndex: [],
Copy the code

Define a new field to get the index value of the module

  numberid: "".Copy the code

Take index and assign it to numberId

/ / edit
handelUpdata(id, ki) { / / ki index sequence
    this.activeIndex = ki;
    this.numberid = ki; // Get index
    }
Copy the code

Add numberID to results[]. Keywords, and place it in deleIndex

// Get data
 getdata() {
   getwarninglabel({
     pageNum: this.pageNum,
     pageSize: this.pageSize,
   }).then((res) = > {
     console.log(res);
     this.total = res.data.count;
     this.tagtitle = res.data.results;
      console.log(res.data.results[0].keywords);
      console.log(res.data.results[this.numberid].keywords);
      console.log(res.data.results[this.numberid].label_name);
      this.deleIndex = res.data.results[this.numberid].keywords; / / assignment
      this.deletitle = res.data.results[this.numberid].label_name;
   
   });
 },
Copy the code

5. Use the tag deletion method

// Delete method
    handleClose(tag, indext) {
        console.log(indext)
         this.deleIndex.splice(this.deleIndex.indexOf(tag), 1);
    },
Copy the code

Label deletion function:

New features

The implementation of the new function is relatively simple, the only trouble is how to convert the input string format data into an array, and merge the new label data with other unchanged data, that is, merge the two arrays:

1. New data format:

Fetch the value of name and put it into an array to generate the data format required by the back end. The code is as follows:

// Create an array to get the new data
mileEdit: []// Perform data processing
 this.mileEdit = this.ruleForm.options;
      console.log(this.mileEdit);
      // Define a new array to hold the processed data
      const eddvalue = this.mileEdit.map((value) = > { 
        return value.name;
      });
Copy the code

2. The results after treatment are as follows:

3. Pass the newly added data and unchanged data to the back end together, that is, merge the newly added array with the original array, through concat to realize the array merge, the code is as follows:

 titleEdit(id,{
        label_name: this.deletitle,
        keywords: eddvalue.concat(this.deleIndex) ,// Array merge
      }).then((res) = > {
        console.log(res);
        this.$message({
          message: "Add success!".type: "success"});Copy the code

This completes the function of adding labels

Complete code:

<template>
  <div>
    <el-button type="primary" @click="Addmunu()">新增主类</el-button>
    <div v-for="(item, ki) in tagtitle" :key="ki" class="text item">
      <el-card class="box-card">
        <div slot="header" class="clearfix">
          <span> {{ item.label_name }}</span>
          <el-button
            @click="hangdelDelete(item.id)"
            style="float: right; padding: 3px 0; color: red"
            type="text"
            >删除</el-button
          >
          <el-button
            v-show="activeIndex != ki"
            @click="handelUpdata(item.id, ki)"
            style="float: right; padding: 3px 0"
            type="text"
            >编辑</el-button
          >
          <el-button
            v-show="activeIndex === ki"
            @click="handelUpdatat(item.id, ki)"
            style="float: right; padding: 3px 0"
            type="text"
            >保存</el-button
          >
        </div>
        <div>
          <el-tag
            :key="indext"
            v-for="(tag, indext) in item.keywords"
            :disable-transitions="false"
          >
            {{ tag }}
            <i
              v-show="activeIndex === ki"
              class="el-icon-circle-close"
              @click="handleClose(tag,indext)"
            ></i>
          </el-tag>
          <span v-show="activeIndex === ki">
            <el-form :inline="true" :model="ruleForm" ref="ruleForm">
              <el-form-item
                v-for="(item, index) in ruleForm.options"
                :key="index"
              >
                <el-row>
                  <el-col :span="4">
                    <el-input
                      clearable
                      style="width: 200px"
                      v-model="item.name"
                      placeholder="请输入标签名"
                    ></el-input>
                  </el-col>
                  <!-- <el-col :span="8">
                <el-button type="danger" plain @click="deleteOption(index)"
                  >删除选项</el-button
                >
              </el-col> -->
                </el-row>
              </el-form-item>
              <el-button  type="primary" plain @click="addOption(index)"
                >新增标签</el-button
              >
            </el-form>
          </span>
        </div>
      </el-card>
    </div>
    <!-- 分页 -->
    <pagination
      v-show="total > 0"
      :total="total"
      :page.sync="pageNum"
      :limit.sync="pageSize"
      @pagination="getdata"
    />
    <!-- 新增主类弹窗 -->
    <el-dialog title="添加标签" :visible.sync="dialogruleForm4Visible">
      <el-form
        :model="ruleForm4"
        ref="ruleForm4"
        label-width="100px"
        class="demo-ruleForm"
      >
        <el-form-item label="标签主类" prop="title">
          <el-input v-model="ruleForm4.title"></el-input>
        </el-form-item>
        <template>
          <el-form-item
            :label="'标签' + (index + 1)"
            v-for="(item, index) in ruleForm4.options"
            :key="index"
          >
            <el-row>
              <el-col :span="16">
                <el-input
                  v-model="item.name"
                  placeholder="请输入标签名"
                  style="width: 90%"
                ></el-input>
              </el-col>
              <el-col :span="8"> </el-col>
            </el-row>
          </el-form-item>
          <el-button
            type="primary"
            style="float: left"
            plain
            @click="addppOption"
            >新增标签</el-button
          >
        </template>
        <el-form-item> </el-form-item>
      </el-form>
      <div slot="footer" class="dialog-footer">
        <el-button @click="dialogruleForm4Visible = false">取 消</el-button>
        <el-button type="primary" @click="checkAddppQuestion()"
          >确 定</el-button
        >
      </div>
    </el-dialog>
  </div>
</template>

<script>
import {
  getwarninglabel,
  hangdleadd,
  deletedata,titleEdit
} from "@/api/label/riskwarning";
export default {
  data() {
    return {
      // 分页
      total: "",
      pageNum: 1,
      pageSize: 10,
      //题目排序
      numberid: "",
      deleteadd:"",
      isShow:false,
      deleIndex: [],
      deletitle: "",
      activeIndex: -1,
      tagtitle: [], //标签题目
      milepost: [],//新增数据处理
      mileEdit: [],//修改数据处理
      tagclosable: false,
      dynamicTags: ["标签一", "标签二", "标签三"],
      inputVisible: false,
      inputValue: "",
      //添加标签
      ruleForm: {
        options: [
          {
            name: "", //标签
          },
        ],
      },
      //添加主类
      ruleForm4: {
        title: "", //主类
        options: [
          {
            name: "", //标签
          },
        ],
      },
      dialogruleForm4Visible: false,
    };
  },
  methods: {
    //添加添加标签
    addOption(index) {
      this.ruleForm.options.push({
        name: "",
      });
     this.deleteadd = index
      console.log(888777)
    },
    getdelete(){
        console.log(99999)
         this.ruleForm.options.splice(this.deleteadd, 1);
    },
     
    //添加添加标签
    addppOption() {
      this.ruleForm4.options.push({
        name: "",
      });
    },
    //新增主类
    Addmunu() {
      this.dialogruleForm4Visible = true;
    },
    //新增
    checkAddppQuestion() {
      console.log(this.ruleForm4.options);
      this.milepost = this.ruleForm4.options;
      console.log(this.milepost);
      const checker = this.milepost.map((value) => {
        return value.name;
      });
      console.log(checker);
      hangdleadd({
        label_name: this.ruleForm4.title,
        keywords: checker,
      }).then((res) => {
        console.log(res);
        this.$message({
          message: "新增成功!",
          type: "success",
        });
        this.ruleForm4 = {
          id: 0,
          title: "",
          options: [""],
        };
        this.getdata();
      });
      this.dialogruleForm4Visible = false;
    },
    //标签新增
    
    //获取数据
    getdata() {
      getwarninglabel({
        pageNum: this.pageNum,
        pageSize: this.pageSize,
      }).then((res) => {
        console.log(res);
        this.total = res.data.count;
        this.tagtitle = res.data.results;
         console.log(res.data.results[0].keywords);
          console.log(this.numberid);
         console.log(res.data.results[this.numberid].keywords);
         console.log(res.data.results[this.numberid].label_name);
         this.deleIndex = res.data.results[this.numberid].keywords;
         this.deletitle = res.data.results[this.numberid].label_name;
         console.log(this.deleIndex)
      });
    },
    //编辑
    handelUpdata(id, ki) {
      //ki index排序
      console.log(id);
      console.log(ki);
      this.activeIndex = ki;
      this.numberid = ki;
     
      this.ruleForm = {
          id: 0,
          options: [""],
        };
         this.getdata();
        //  this.addOption();
        this.getdelete();
    },
    //保存
    handelUpdatat(id, ki) {
      console.log(id);
      console.log(ki);
      this.activeIndex = -1;
       console.log(this.ruleForm.options);
      this.mileEdit = this.ruleForm.options;
      console.log(this.mileEdit);
      const eddvalue = this.mileEdit.map((value) => {
        return value.name;
      });
      console.log(eddvalue)
       titleEdit(id,{
        label_name: this.deletitle,
        keywords: eddvalue.concat(this.deleIndex) ,
      }).then((res) => {
        console.log(res);
        this.$message({
          message: "新增成功!",
          type: "success",
        });
        this.ruleForm = {
          options: [""],
        };
        this.getdata();
      });
     this.getdata();
     
    },
    //删除主模块
    hangdelDelete(id) {
      this.$confirm("此操作将永久删除该文件, 是否继续?", "提示", {
        confirmButtonText: "确定",
        cancelButtonText: "取消",
        type: "warning",
        center: true,
      })
        .then(() => {
          deletedata(id).then((res) => {
            console.log(res);
            this.$message({
              type: "success",
              message: "删除成功!",
            });
            this.getdata();
          });
        })
        .catch(() => {
          this.$message({
            type: "info",
            message: "已取消删除",
          });
        });
    },

    //删除方法
    handleClose(tag, indext) {
        console.log(indext)
        // this.deleIndex.splice(indext, 1);
         this.deleIndex.splice(this.deleIndex.indexOf(tag), 1);
    },
  },
  mounted() {     
    console.log(88888);
    this.getdata();
  },
};
</script>

<style  scoped>
/* 卡片 */
.item {
  margin-bottom: 18px;
}

.clearfix:before,
.clearfix:after {
  display: table;
  content: "";
}
.clearfix:after {
  clear: both;
}

.box-card {
  width: 100%;
}
/* 标签 */
.el-tag + .el-tag {
  margin-left: 10px;
}
.button-new-tag {
  margin-left: 10px;
  height: 32px;
  line-height: 30px;
  padding-top: 0;
  padding-bottom: 0;
}
.input-new-tag {
  width: 90px;
  margin-left: 10px;
  vertical-align: bottom;
}
</style>
Copy the code