tag.vue 10.9 KB
<template>
  <div class="admin-refresh" v-loading="loading">

    <div class="section-search search-single">
      <el-form label-width="80px" inline>
        <el-form-item>
          <el-input placeholder="输入标签名搜索" v-model="filterText"></el-input>
        </el-form-item>

        <el-form-item>
          <div class="search-btn-wrapper">
            <!--<el-button @click="onSearch" type="primary" plain>搜索</el-button>-->
            <el-button @click="dialogUser.show = !dialogUser.show;" type="warning" plain>高级搜索</el-button>
            <!--<el-button v-if="!$store.state.readonly" @click="onAdd" type="success" plain>新增标签</el-button>-->
          </div>
        </el-form-item>
      </el-form>
    </div>

    <div class="tag-tree">
      <el-tree
        :data="treeData"
        node-key="id" ref="tagTree"
        :props="{children: 'children', label: 'name'}"
        :indent="40"
        @node-expand="tagExpand"
        @node-collapse="tagCollapse"
        :filter-node-method="filterNode"
        :default-expanded-keys="tagExpanded"
        :expand-on-click-node="true">
        <div class="custom-tree-node" slot-scope="{ node, data }">
          <el-tag class="tag-tree-item" effect="plain" size="medium">{{node.label}}</el-tag>
          <div style="display: flex">
            <!--<span>{{node.data.cover}}</span>-->
            <el-popover
              placement="right-start"
              title="标签备注"
              width="200"
              trigger="hover"
              :disabled="!node.data.cover"
              :content="node.data.cover ? node.data.cover : '暂无备注'">
              <el-link @click.stop class="cover-link" slot="reference" :disabled="!node.data.cover">备注</el-link>
            </el-popover>
            <el-link v-if="node.level < 4 && !$store.state.readonly" type="success" size="mini" plain @click.stop="onAdd(node)">新增子标签 ({{node.level}}级)</el-link>
            <el-link v-if="node.level != 1 && !$store.state.readonly" type="warning" size="mini" plain @click.stop="onEdit(node, data)">编辑</el-link>
          </div>
        </div>
      </el-tree>
    </div>

    <el-dialog :title="dialog.title" :visible.sync="dialog.show" width="500px">
      <el-form ref="dialogForm" :rules="dialog.form.rules" :model="dialog.form" label-width="100px">
        <el-form-item label="ID:" prop="id" style="display: none;">
          <el-input v-model="dialog.form.id" maxlength="10" type="text"></el-input>
        </el-form-item>
        <el-form-item label="PID:" prop="pid" style="display: none;">
          <el-input v-model="dialog.form.pid" maxlength="10" type="text"></el-input>
        </el-form-item>
        <el-form-item label="标签名称:" prop="name">
          <el-input v-model="dialog.form.name" maxlength="10" type="text"></el-input>
        </el-form-item>
        <el-form-item label="标签备注:" prop="cover">
          <el-input v-model="dialog.form.cover" maxlength="50" type="textarea" :rows="3"></el-input>
        </el-form-item>
      </el-form>
      <span slot="footer" class="dialog-footer">
        <el-button @click="dialogToggle">取消</el-button>
        <el-button type="primary" @click="dialogSave">确定</el-button>
      </span>
    </el-dialog>

    <el-dialog :visible.sync="dialogUser.show" width="800px" title="高级搜索">
      <div style="display: flex;margin-bottom: 20px;">
        <el-button style="margin-right: 20px; width: 70px;" type="primary" v-if="!$store.state.readonly && $store.state.export" plain :disabled="!tableData.length" @click="exportExcel">导出</el-button>
        <el-cascader
          style="width: calc(100% - 90px)" placeholder="选择标签" clearable @change="conditionsChange"
          :options="treeDataOrigin" :props="{ value: 'id', label: 'name', multiple: true, checkStrictly: true }"></el-cascader>
      </div>
      <el-table :data="tableData" border>
        <el-table-column className="f-c" label="用户">
          <template slot-scope="scope">
            <img class="avatar" :src="scope.row.avatar">{{scope.row.nickname}}<br>(ID:{{scope.row.user_id}})
          </template>
        </el-table-column>
        <el-table-column prop="baby_name" label="宝宝名称"></el-table-column>
        <el-table-column prop="birthday" label="宝宝生日"></el-table-column>
        <el-table-column prop="sex" label="宝宝性别" :formatter="sexFormatter"></el-table-column>
        <el-table-column prop="mobile" label="手机号码"></el-table-column>
      </el-table>
      <page :total="total" :limit="limit" @pageChange="onPageChange" @sizeChange="onSizeChange"/>
    </el-dialog>
  </div>
</template>

<script>
  import {getTagApi, postTagApi, putTagApi, getTagUserApi, exportExcelApi} from "../../service/api";
  import page from '../framework/page';

  export default {
    name: "index",
    data() {
      return {
        conditions: [],
        filterText: '',

        tagExpanded: [0],
        tagExpandedWait: '',

        tableData: [],
        treeData: [],
        treeDataOrigin: [],
        dialogUser: {
          show: false
        },
        dialog: {
          title: '',
          show: false,
          form: {
            id: '',
            pid: '',
            name: '',
            cover: '',
            rules: {
              name: [{required: true, message: '请输入', trigger: 'blur'}],
            },
          }
        },

        total: 0,
        nowPage: 1,
        limit: 10,
        loading: false
      }
    },
    components: { page },
    watch: {
      filterText(val) {
        this.$refs.tagTree.filter(val);
      }
    },
    mounted() {
      this.getData()
    },
    methods: {
      sexFormatter(item){
        if(item.sex==0){
          return '保密'
        }
        if(item.sex==1){
          return '男'
        }
        if(item.sex==2){
          return '女'
        }
      },

      onPageChange(val) {
        this.nowPage = val
        this.getUserData()
      },
      onSizeChange(val) {
        this.limit = val;
        this.nowPage = 1;
        this.getUserData()
      },

      getUserData(){ // 搜索用户
        let json = {
          conditions: JSON.stringify(this.conditions),
          limit: this.limit,
          page: this.nowPage
        }
        getTagUserApi(json).then(res=>{
          this.tableData = res.list
        })
      },

      filterNode(value, data) { // 搜索标签
        if (!value) return true;
        return data.name.indexOf(value) !== -1;
      },

      dialogToggle() {
        this.dialog.show = !this.dialog.show;
        if (!this.dialog.show) {
          this.dialogReset();
        }
        /*if (this.tableData.length && this.tableData[0] == 0) { // 未初始化
          this.getUserData();
        }*/
      },
      dialogReset(callback) {
        this.$nextTick(()=>{
          this.$refs['dialogForm'].resetFields();
            //this.$nextTick(()=>{
              callback && callback();
            //})
          //this.dialog.form.id = '';
          //this.dialog.form.pid = '';
        })
      },
      dialogSave() {
        this.$refs['dialogForm'].validate((valid) => {
          if (valid) {
            var json = {
              pid: this.dialog.form.pid,
              name: this.dialog.form.name,
            };
            this.dialog.form.cover ? json.cover = this.dialog.form.cover : '';
            if (this.dialog.form.id) { // 编辑
              json.category_id = this.dialog.form.id;
              putTagApi(json).then(res => {
                this.$message({ type: 'success', message: '编辑成功!' });
                this.dialogToggle();
                this.getData();
              })
            } else { // 新增
              postTagApi(json).then(res => {
                this.$message({ type: 'success', message: '新增成功!' });
                this.tagExpanded.push(this.tagExpandedWait); // 新增时自动展开
                this.dialogToggle();
                this.getData();
              })
            }
          } else {
            console.log('error submit!!');
            return false;
          }
        });
      },

      tagExpand(data, node, el) { // 标签展开(记录树的状态)
        //console.log(node)
        if (node.expanded) {
          this.tagExpanded.push(node.data.id)
        }
      },
      tagCollapse(data, node, el) { // 标签收起(记录树的状态)
        //console.log(node)
        if (node.expanded) {
          this.tagExpanded.splice(this.tagExpanded.findIndex(item => item == node.data.id), 1)
        }
      },

      getData() { // 获取标签
        getTagApi().then(res => {
          this.treeDataOrigin = res;
          this.treeData = [{
            children: res,
            cover: '',
            created_at: '',
            id: 0,
            name: '所有标签',
            pid: 0,
            weight: 0,
          }]
        });
      },

      onAdd(node) {
        this.dialog.title = `新增 ${node.level}级 标签`;
        this.dialog.form.id = '';
        this.tagExpandedWait = node.data.id; // 新增时自动展开
        this.dialogToggle();
        this.$nextTick(()=>{
          this.dialogReset(() => {
            this.dialog.form.pid = node.data.id; // 注意id
          });
        });
      },

      onEdit(node, data) {
        //console.log(node)
        //console.log(data)
        let item = node.data;
        this.dialogToggle();
        this.dialogReset();
        this.$nextTick(()=>{
          this.dialog.title = '编辑标签';
          this.dialog.form.id = item.id;
          this.dialog.form.pid = item.pid;
          this.dialog.form.name = item.name;
          this.dialog.form.cover = item.cover;
        });
      },

      onSearch(){
        this.getData();
      },

      conditionsChange(val){
        //console.log(val);
        let arr = [];
        if(val.length) {
          val.forEach(v => {
            arr.push(v[v.length - 1])
          })
          this.conditions = arr;
          this.getUserData();
        } else {
          this.conditions = arr;
          this.tableData = [];
        }
      },

      exportExcel() {
        let json = {
          conditions: JSON.stringify(this.conditions),
        }
        exportExcelApi(`api/admin/advanced/search/export`, json, '标签用户列表');
      }
    }
  }
</script>

<style lang="less">

  .tag-tree {
    padding: 8px 0;
    background-color: #fff;
    .custom-tree-node {
      display: flex;
      .tag-tree-item {
        margin-right: 10px;
      }
    }

    //
    .el-tree-node {
      padding: 2px 0;
      .el-tree-node__content {
        padding: 6px 0;
      }
    }

    // 取消第一级折叠
    & > .el-tree > .el-tree-node > .el-tree-node__content > .el-tree-node__expand-icon {
      pointer-events: none;
      /*opacity: 0;*/
    }

    .el-link {
      font-size: 12px;

      &.cover-link {
        margin-right: 10px;
        line-height: 28px;
      }

      &:hover:after {
        bottom: 2px;
      }
      & + .el-link {
        margin-left: 10px;
      }
    }
  }

</style>