<!--
@name: tableListPagination
@description: 通用table表格 + pagination分页组件
@author: zc
@time: 2023/11/16
@引入:

  <table-list-pagination ref='tableListPagination' :tableListPaginationConfig="tableListPaginationConfig"></table-list-pagination>
  import tableListPagination from "@/components/tableListPagination/tableListPagination.vue";
  components: {
    tableListPagination
  },
  //此方法用于调用组件内列表数据获取
  refTableListPagination(){
    this.$refs.tableListPagination.getList();
  },
  //此方法用于接受组件内事件传参
  moduleDataCommunication(row,item){

  },

@必要参数:

  tableListPaginationConfig:{
    getApi:demoApi,                 //列表接口数据                  必要(需要父级组件引用)
    titleAlign:'center',            //表头对齐方向                  非必要(不传时默认居中)
    align:'right',                  //表格内容对齐方向              非必要(不传时默认靠左)
    queryParams:{                   //列表接口请求参数              必要
      pageNum:1,                    //页码                          必要
      pageSize:20,                  //数量                          必要
      自定义参数:''                 //其他自定义参数                非必要(可增加其他检索条件)
    },
    tableConfig:[                   //table表格设置                 必要
      {                             type === text
        label:'单文本模式',         //标题名称                      必要
        prop:'name',                //绑定参数                      必要
        type:'text',                //类型                          必要
        defaultSymbol:'--',         //缺省符                        非必要(默认显示-)
        width:'340',                //表格宽度                      非必要(不传时自动分配)
        color:'red'                 //字体颜色                      非必要(不传时默认#333)
        timeFormat:'{y}-{m}-{d}'    //时间格式                      非必要(传值时自动转换时间格式-非时间不要传)
        matchingList:[              //匹配参数                      非必要(存在时开启匹配模式)
          {
            label:'未完成',         //匹配名称                      必要
            value:'0',              //匹配参数                      必要
            color:'#a52a2a',        //字体颜色                      非必要(不传时默认#333)
          },
          {
            label:'已完成',         //匹配名称                      必要
            value:'1',              //匹配参数                      必要
            color:'#00ff00',        //字体颜色                      非必要(不传时默认#333)
          },
        ],
      },
      {                             type === multiText
        label:'多个文本模式',       //标题名称                      必要
        width:'340',                //表格宽度                          非必要(不传时自动分配)
        type:'multiText',           //类型                          必要
        spliceSymbol:'/',           //多文本分割符                  必要
        multiTextProp:[             //多文本数据                    必要
          {
            prop:'createBy',        //绑定参数                      必要
            defaultSymbol:'--',     //缺省符                        非必要(默认显示-)
            color:'#00ced1',        //文本颜色                      非必要(不传时默认#333)
            timeFormat:'{y}-{m}-{d} {h}:{i}:{s}', //时间格式        非必要(传值时自动转换时间格式-非时间不要传)
            matchingList:[              //匹配参数                  非必要(存在时开启匹配模式)
              {
                label:'未完成',         //匹配名称                  必要
                value:'0',              //匹配参数                  必要
                color:'#a52a2a',        //字体颜色                  非必要(不传时默认#333)
              },
              {
                label:'已完成',         //匹配名称                  必要
                value:'1',              //匹配参数                  必要
                color:'#00ff00',        //字体颜色                  非必要(不传时默认#333)
              },
            ],
          },
        ],
      },
      {                             type === switch
        label:'开关模式',           //标题名称                      必要
        prop:'name',                //绑定参数                      必要(api开启时接口会自动传入此参数)
        type:'switch',              //类型                          必要
        openParameter:1,            //开启参数                      必要
        closeParameter:0,           //关闭参数                      必要
        width:'340',                //表格宽度                      非必要(不传时自动分配)
        api:demoApi,                //接口数据                      非必要(需要父级组件引用,不传时事件会抛出至父级moduleDataCommunication)
        apiData:['id'],             //接口参数                      非必要(用于api接口传参,只能获取列表数据内已有的数据)
        openColor:'#0183FA',        //开启参数                      非必要(默认)
        closeColor:'#999',          //关闭颜色                      非必要(默认)
        openText:'打开',            //开启描述                      非必要(默认-启用)
        closeText:'关闭',           //关闭描述                      非必要(默认-停用)
      },
      {
        label:'按钮模式',           //标题名称                      必要
        type:'button',              //类型                          必要
        width:'340',                //表格宽度                      非必要(不传时自动分配)
        permissionsList:['demo1','demo2'],  //操作栏所有权限        非必要(改列下所有权限字段)
        buttonList:[                //按钮列表                      必要
          {
            type:'button',          //按钮类型                      必要(button 普通按钮)
            buttonLabel:'详情',     //按钮名称                      必要
            buttonKey:'1',          //按钮唯一标识                  必要
            permissions:['demo-1'], //按钮权限                      非必要
            api:demoApi,            //接口数据                      非必要(需要父级组件引用,不传时事件会抛出至父级moduleDataCommunication)
            apiData:['id'],         //接口参数                      非必要(用于api接口传参,只能获取列表数据内已有的数据)
          },
          {
            type:'dropDown',        //按钮类型                      必要(dropDown 下啦按钮)
            buttonLabel:'更多>>',   //按钮名称                      必要
            permissionsList:['demo-1','demo-2'], //下拉按钮所有权限 非必要(下拉按钮下所有按钮权限字段)
            dropDownList:[          //下啦按钮数组                  必要
              {
                buttonLabel:'删除', //下拉按钮名称                  必要
                buttonKey:'2',      //按钮唯一标识                  必要
                permissions:['de'], //按钮权限                      非必要
                api:demoApi,        //接口数据                      非必要(需要父级组件引用,不传时事件会抛出至父级moduleDataCommunication)
                apiData:['id'],     //接口参数                      非必要(用于api接口传参,只能获取列表数据内已有的数据)
              },
            ],
          },
        ],
      },
      {                             type === input
        label:'输入模式',           //标题名称                      必要
        prop:'deptName',            //绑定参数                      必要(api开启时接口会自动传入此参数)
        type:'input',               //类型                          必要
        maxLength:'20',             //输入长度限制                  非必要(默认10)
        inputWidth:'200',           //input长度                     非必要(默认100)
        width:'340',                //表格宽度                      非必要(不传时自动分配)
        placeholder:'请输入',       //输入提示                      非必要(不传时默认显示请输入)
        api:demoApi,                //接口数据                      非必要(需要父级组件引用,不传时事件会抛出至父级moduleDataCommunication)
        apiData:['id'],             //接口参数                      非必要(用于api接口传参,只能获取列表数据内已有的数据)
      },
    ],
  },

-->
<template>
  <div id="table-list-pagination">
    <el-table v-loading="loading" border :data="tableData"
      :class="!tableListPaginationConfig.align?'leftAlign':(
              tableListPaginationConfig.align==='left'?'leftAlign':(
              tableListPaginationConfig.align==='center'?'centerAlign':(
              tableListPaginationConfig.align==='right'?'rightAlign':'leftAlign')))">
      <template v-for="item in tableListPaginationConfig.tableConfig">
        <!--输入模式-->
        <el-table-column
          v-if="item.type === 'input'"
          :label="item.label" :prop="item.prop"
          :align="!tableListPaginationConfig.titleAlign?'center':(
                  tableListPaginationConfig.titleAlign === 'left'?'left':(
                  tableListPaginationConfig.titleAlign === 'center'?'center':(
                  tableListPaginationConfig.titleAlign === 'right'?'right':'center')))"
          :width="item.width?item.width:''">
          <template slot-scope="scope">
            <el-input
              :maxlength="item.maxlength?item.maxlength:'10'"
              v-model="scope.row[item.prop]"
              :placeholder="item.placeholder?item.placeholder:'请输入'"
              :style="item.inputWidth?'width:'+item.inputWidth+'px;':'100px'"
            />
          </template>
        </el-table-column>
        <!--单文本模式-->
        <el-table-column
          v-if="item.type === 'text'"
          :label="item.label" :prop="item.prop"
          :align="!tableListPaginationConfig.titleAlign?'center':(
                  tableListPaginationConfig.titleAlign === 'left'?'left':(
                  tableListPaginationConfig.titleAlign === 'center'?'center':(
                  tableListPaginationConfig.titleAlign === 'right'?'right':'center')))"
          :width="item.width?item.width:''"
          :show-overflow-tooltip="true">
          <template slot-scope="scope">
            <span v-if="item.matchingList">
              <template v-for="minItem in item.matchingList">
                <span v-if="minItem.value == scope.row[item.prop]"  :style="minItem.color?'color:'+minItem.color+';':''">{{minItem.label}}</span>
              </template>
            </span>
            <span v-else>
              <span :style="item.color?'color:'+item.color+';':''" v-if="item.timeFormat">{{scope.row[item.prop]?parseTime(scope.row[item.prop],item.timeFormat):item.defaultSymbol?item.defaultSymbol:'--'}}</span>
              <span :style="item.color?'color:'+item.color+';':''" v-else>{{scope.row[item.prop]?scope.row[item.prop]:item.defaultSymbol?item.defaultSymbol:'--'}}</span>
            </span>
          </template>
        </el-table-column>
        <!--多文本模式-->
        <el-table-column
          v-if="item.type === 'multiText' && item.multiTextProp && item.spliceSymbol"
          :label="item.label"
          :align="!tableListPaginationConfig.titleAlign?'center':(
                  tableListPaginationConfig.titleAlign === 'left'?'left':(
                  tableListPaginationConfig.titleAlign === 'center'?'center':(
                  tableListPaginationConfig.titleAlign === 'right'?'right':'center')))"
          :width="item.width?item.width:''"
          :show-overflow-tooltip="true">
          <template slot-scope="scope">
            <template v-for="(minItem,minIndex) in item.multiTextProp">
              <span v-if="minItem.matchingList">
                <span v-if="minIndex !== 0"> {{item.spliceSymbol}} </span>
                <template v-for="minItemMin in minItem.matchingList">
                  <span v-if="minItemMin.value == scope.row[minItem.prop]"
                        :style="minItemMin.color?'color:'+minItemMin.color+';':''">{{minItemMin.label}}</span>
                </template>
              </span>
              <span v-else>
                <span v-if="minIndex !== 0"> {{item.spliceSymbol}} </span>
                <span :style="minItem.color?'color:'+minItem.color+';':''" v-if="minItem.timeFormat">{{scope.row[minItem.prop]?parseTime(scope.row[minItem.prop],minItem.timeFormat):item.defaultSymbol?item.defaultSymbol:'--'}}</span>
                <span :style="minItem.color?'color:'+minItem.color+';':''" v-else>{{scope.row[minItem.prop]?scope.row[minItem.prop]:item.defaultSymbol?item.defaultSymbol:'--'}}</span>
              </span>
            </template>
          </template>
        </el-table-column>
        <!--开关模式-->
        <el-table-column
          v-if="item.type === 'switch'"
          :label="item.label"
          :align="!tableListPaginationConfig.titleAlign?'center':(
                  tableListPaginationConfig.titleAlign === 'left'?'left':(
                  tableListPaginationConfig.titleAlign === 'center'?'center':(
                  tableListPaginationConfig.titleAlign === 'right'?'right':'center')))"
          :width="item.width?item.width:''"
          :show-overflow-tooltip="true">
          <template slot-scope="scope">
            <div class="tableListPaginationSwitch">
              <div class="tableListPaginationSwitchL"
                   v-if="!tableListPaginationConfig.align || tableListPaginationConfig.align === 'right' || tableListPaginationConfig.align === 'center'">
              </div>
              <div>
                <el-switch
                  @click.native="switchClick(scope.row,item)"
                  class="switch captcha-img"
                  :active-value="item.openParameter"
                  :inactive-value="item.closeParameter"
                  :active-color="item.openColor?item.openColor:'#0183FA'"
                  :inactive-color="item.closeColor?item.closeColor:'#999'"
                  v-model="scope.row[item.prop]"
                  :active-text="item.openText?item.openText:'打开'"
                  :inactive-text="item.closeText?item.closeText:'关闭'"
                  disabled
                ></el-switch>
              </div>
              <div class="tableListPaginationSwitchR"
                   v-if="!tableListPaginationConfig.align || tableListPaginationConfig.align === 'left' || tableListPaginationConfig.align === 'center'">
              </div>
            </div>
          </template>
        </el-table-column>
        <!--按钮模式-->
        <el-table-column
          v-if="item.type === 'button' && (item.permissionsList?hasPermiDom(item.permissionsList):true)"
          :label="item.label"
          :align="!tableListPaginationConfig.titleAlign?'center':(
                  tableListPaginationConfig.titleAlign === 'left'?'left':(
                  tableListPaginationConfig.titleAlign === 'center'?'center':(
                  tableListPaginationConfig.titleAlign === 'right'?'right':'center')))"
          :width="item.width?item.width:''">
          <template slot-scope="scope">
            <div class="table-button-box">
              <p class="table-button-null"
                 v-if="!tableListPaginationConfig.align || tableListPaginationConfig.align === 'right' || tableListPaginationConfig.align === 'center'"></p>
              <template v-for="minItem in item.buttonList">
                <p v-if="minItem.type === 'button' && minItem.permissions"
                   class="table-button-p"
                   v-hasPermiAnd="minItem.permissions"
                   @click="buttonClick(scope.row,minItem)"
                >{{minItem.buttonLabel}}</p>
                <p v-if="minItem.type === 'button' && !minItem.permissions"
                   class="table-button-p"
                   @click="buttonClick(scope.row,minItem)"
                >{{minItem.buttonLabel}}</p>
                <el-dropdown v-if="minItem.type === 'dropDown' && (minItem.permissionsList?hasPermiDom(minItem.permissionsList):true)"
                  size="mini" @command="(command) => dropDownClick(scope.row,minItem,command)">
                  <p class="table-button-p">{{minItem.buttonLabel}}</p>
                  <el-dropdown-menu slot="dropdown">
                    <template v-for="minItemMin in minItem.dropDownList">
                      <el-dropdown-item
                        v-if="minItemMin.permissions"
                        :command="minItemMin.buttonKey"
                        v-hasPermiAnd="minItemMin.permissions"
                      >{{minItemMin.buttonLabel}}
                      </el-dropdown-item>
                      <el-dropdown-item
                        v-else
                        :command="minItemMin.buttonKey"
                      >{{minItemMin.buttonLabel}}
                      </el-dropdown-item>
                    </template>
                  </el-dropdown-menu>
                </el-dropdown>
              </template>
              <p class="table-button-null"
                 v-if="!tableListPaginationConfig.align || tableListPaginationConfig.align === 'left' || tableListPaginationConfig.align === 'center'"></p>
            </div>
          </template>
        </el-table-column>
      </template>
    </el-table>
    <pagination :page-sizes="[20, 30, 40, 50]"
                :total="total"
                layout="total, prev, pager, next, sizes, jumper"
                :page.sync="tableListPaginationConfig.queryParams.pageNum"
                :limit.sync="tableListPaginationConfig.queryParams.pageSize"
                @pagination="getList"
    />
  </div>
</template>
<script>
  export default {
    name: 'tableList',
    props: {
      tableListPaginationConfig:{},
    },
    data () {
      return {
        loading:false,
        tableData:[],
        total:0,
      }
    },
    created(){

    },
    mounted(){

    },
    methods:{
      //switch点击事件
      switchClick(row,item){
        let self = this;
        //switch开关
        if(item.api){
          //api存在,组件内处理逻辑
          this.$confirm('是否确认'+(row[item.prop] === item.openParameter?item.closeText:'')+'?', "", {
            confirmButtonText: "确定",
            cancelButtonText: "取消",
            type: "warning"
          }).then(function() {
            let obj = {
              [item.prop]:row[item.prop] === item.openParameter?item.closeParameter:item.openParameter
            };
            for(let i=0;i<item.apiData.length;i++){
              obj[item.apiData[i]] = row[item.apiData[i]];
            }
            self.commonalityApiTrigger(item.api,obj);
          }).then(() => {}).catch(() => {});
        }else{
          //api不存在,抛出对象到父类
          this.invokeSuperiors(row,item);
        }
      },
      //按钮点击
      buttonClick(row,minItem){
        let self = this;
        if(minItem.api){
          //api存在,组件内处理逻辑
          this.$confirm('是否确认'+minItem.buttonLabel+'?', "", {
            confirmButtonText: "确定",
            cancelButtonText: "取消",
            type: "warning"
          }).then(function() {
            let obj = {};
            for(let i=0;i<minItem.apiData.length;i++){
              obj[minItem.apiData[i]] = row[minItem.apiData[i]];
            }
            self.commonalityApiTrigger(minItem.api,obj);
          }).then(() => {}).catch(() => {});
        }else{
          //api不存在,抛出对象到父类
          this.invokeSuperiors(row,minItem);
        }
      },
      //下啦按钮点击
      dropDownClick(row,minItemMin,command){
        let self = this;
        let data = {};
        for(let i=0;i<minItemMin.dropDownList.length;i++){
          if(command === minItemMin.dropDownList[i].buttonKey){
            data = minItemMin.dropDownList[i];
          }
        }
        if(data.api){
          //api存在,组件内处理逻辑
          this.$confirm('是否确认'+data.buttonLabel+'?', "", {
            confirmButtonText: "确定",
            cancelButtonText: "取消",
            type: "warning"
          }).then(function() {
            let obj = {};
            for(let i=0;i<data.apiData.length;i++){
              obj[data.apiData[i]] = row[data.apiData[i]];
            }
            self.commonalityApiTrigger(data.api,obj);
          }).then(() => {}).catch(() => {});
        }else{
          //api不存在,抛出对象到父类
          this.invokeSuperiors(row,data);
        }
      },
      //按钮通用接口
      commonalityApiTrigger(api,obj){
        api(obj).then(res => {
          this.msgSuccess(res.msg)
          this.getList();
        });
      },
      //调用父级方法
      invokeSuperiors(row,item){
        this.$parent.moduleDataCommunication(row,item);
      },
      //列表数据接口
      getList(){
        this.$set(this,'loading',true)
        this.tableListPaginationConfig.getApi(this.tableListPaginationConfig.queryParams).then(res => {
          this.$set(this,'tableData',res.rows)
          this.$set(this,'total',res.total)
          this.$set(this,'loading',false)
        });
      },
    },
  }
</script>
<style scoped lang="scss">
  #table-list-pagination{
    flex:1;
    display: flex;
    flex-direction: column;
    overflow: hidden;
    .leftAlign{
      ::v-deep td{
        text-align: left!important;
      }
    }
    .centerAlign{
      ::v-deep td{
        text-align: center!important;
      }
    }
    .rightAlign{
      ::v-deep td{
        text-align: right!important;
      }
    }
    ::v-deep .tableListPaginationSwitch{
      display: flex;
      .tableListPaginationSwitchL, .tableListPaginationSwitchR{
        flex:1;
      }
      .switch .el-switch__label {
        position: absolute;
        display: none;
        color: #fff !important;
      }
      .switch .el-switch__label--right {
        z-index: 1;
      }
      .switch .el-switch__label--right span{
        margin-left: 10px;
      }
      .switch .el-switch__label--left {
        z-index: 1;
      }
      .switch .el-switch__label--left span{
        margin-left: 24px;
      }
      .switch .el-switch__label.is-active {
        display: block;
        text-align: left!important;
      }
      .switch.el-switch .el-switch__core,
      .el-switch .el-switch__label {
        width: 64px !important;
        margin: 0;
      }
    }
    //===========================表格内按钮===========================
    .table-button-box{
      font-weight:500;
      height:23px;
      display: flex;
      margin:0 auto;
      .table-button-null{
        flex:1;
      }
      .table-button-p{
        color:#0183FA;
        line-height:23px;
        font-size:14px;
        cursor:pointer;
        margin:0 10px !important;
        text-align:center;
        i{
          margin:0 5px 0 0;
        }
      }
    }
  }
</style>
