<template>
  <div class="app-container" v-loading="state.loading">
    <el-card class="search-container" v-if="!(props.hideSearch && props.hideSetColums)">
      <el-form :inline="true" v-if="!props.hideSearch">
        <el-form-item 
          v-auth="(props.authName || props.apiName) + state.searchBtnOptions['search'].auth"
          v-for="(item,index) in props.searchOptions"
          :key="index"
          :label="item.label">
          <!-- 文本 -->
          <el-input 
            v-if="item.type == 'input' && !item.hide"
            v-model="props.searchFilter[item.prop]" 
            :placeholder="item.label" 
            :clearable="!item.noClear"
          />
          <!-- 数字 -->
          <el-input-number 
            v-if="item.type == 'number' && !item.hide"
            v-model="props.searchFilter[item.prop]" 
            :min="item.min"
            :max="item.max"
          />
          <!-- 时间区域 -->
          <el-date-picker
            v-if="item.type == 'datetimerange' && !item.hide"
            v-model="props.searchFilter[item.prop]"
            type="datetimerange"
            start-placeholder="起始时间"
            end-placeholder="结束时间"
            format="YYYY-MM-DD HH:mm:ss"
            value-format="YYYY-MM-DD HH:mm:ss"
            style="width:370px"
          />
          <!-- 选择框 -->
          <el-select
            v-if="item.type == 'select' && !item.hide"
            v-model="props.searchFilter[item.prop]"
            :filterable="!item.noSearch"
            placeholder="请选择"
            style="width: 240px"
            :clearable="!item.noClear"
          >
            <el-option
              v-for="(op,op_index) in item.options"
              :key="op_index"
              :label="op.label"
              :value="op.value"
            />
          </el-select>
        </el-form-item>
        <el-form-item>
          <div style="margin-right:10px" v-for="(btn,btn_key) in props.searchButtons" :key="btn_key">
            <!-- 导出 -->
            <el-dropdown 
              v-auth="(props.authName || props.apiName) + state.searchBtnOptions[btn].auth"
              :hide-on-click="false" 
              v-if="state.searchBtnOptions[btn].auth == ':export'"
            >
              <el-button 
                :icon="state.searchBtnOptions[btn].icon" 
                :type="state.searchBtnOptions[btn].type">
                {{state.searchBtnOptions[btn].label}}
                <el-icon class="el-icon--right"><arrow-down /></el-icon>
              </el-button>
              <template #dropdown>
                <el-dropdown-menu>
                  <el-dropdown-item @click="exportHandle()">按条件导出【当前页】</el-dropdown-item>
                  <el-dropdown-item divided @click="exportHandle(true)">按条件导出【全部】</el-dropdown-item>
                </el-dropdown-menu>
              </template>
            </el-dropdown>
            <!-- 其他按钮 -->
            <el-button
              v-else
              :icon="state.searchBtnOptions[btn].icon"
              v-auth="(props.authName || props.apiName) + state.searchBtnOptions[btn].auth"
              :type="state.searchBtnOptions[btn].type"
              @click="searchBtnHandle(btn)"
            >{{state.searchBtnOptions[btn].label}}</el-button>
          </div>
        </el-form-item>
      </el-form>
      <!-- 字段设置 -->
      <setColumsPop 
        style="margin-left: auto;"
        v-if="!props.hideSetColums && state.innerTableColumns"
        :localTableColumnsName="state.localTableColumnsName" 
        :initTableColums="state.initTableColums" 
        :tableColumns="state.innerTableColumns"
      ></setColumsPop>
    </el-card>

    <el-card class="paged-table-container">
      <elTable 
        v-if="state.innerTableColumns"
        :specialLocalColumnName="props.specialLocalColumnName"
        :columnWidth="props.columnWidth"
        :columnHeaderAlign="props.columnHeaderAlign"
        :columnAlign="props.columnAlign"
        :tableData="state.tableData"
        :tableColumns="state.innerTableColumns"
        @sortChange="sortChange"
        :leftOperation="props.leftOperation"
        @leftOperationHadel="leftOperationHadel"
        :leftOperationColumnWidth="props.leftOperationColumnWidth"
        :rightOperation="getRightOperation()"
        @rightOperationHadel="rightOperationHadel"
        :multipleTable="props.multipleTable"
        @tableSelectionHandle="tableSelectionHandle"
        :tableRowClassName="props.tableRowClassName"
        :tableCellClassName="props.tableCellClassName"
      ></elTable>

      <elPager
        style="margin-top: 15px;float:right"
        :pager="state.pager"
        @pageSizeChange="pageSizeChange"
        @pageCurrentChange="pageCurrentChange"
      ></elPager>
    </el-card>

    <!-- 导入弹窗 -->
    <importPop 
      ref="importPopRef" 
      :apiName="props.apiName"
      @success="importSuccess"
    />

    <!-- 编辑弹窗 -->
    <apiEditPop 
      ref="apiEditPopRef" 
      :apiName="props.apiName"
      @submitEditForm="submitEditForm"
      :formRules="props.apiEditFormRules"
    />
  </div>
</template>
  
<script setup>
  defineOptions({ name: 'tablePage' })
  import store from '@/stores'
  import apiTableColumns from '@/utils/common/apiTableColumns'
  import { reactive, ref, onMounted,computed,defineExpose } from 'vue'
  import { 
    getCommonPost,
    getCommonPaged,
    getCommonDeatailPaged,
    postCommonExport,
    postCommonCreate,
    putCommonUpdate,
    deleteCommonApi,
    getCommonCustominvoke 
  } from '@/api/common/index'
  import { ElMessageBox, ElMessage,ElTable, ElTableColumn } from 'element-plus'
  import elTable from '@/components/elTable/index.vue'
  import elPager from '@/components/elPager/index.vue'
  import setColumsPop from '@/components/setColumsPop/index.vue'
  import { getPageParamsForFilter,getLocalTableColumnsName } from '@/utils/common/index'
  import { downloadByData } from '@/utils/download'
  import importPop from '@/components/importPop/index.vue'
  import apiEditPop from '@/components/apiEditPop/index.vue'
  import { formatDate } from '@/utils/formatTime'
  import apiServeNames from '@/utils/common/apiServeNames'

  import { useRoute } from 'vue-router'
  const route = useRoute()
  const userStore = store.userStore()
  const userInfo = userStore.state

  const state = reactive({
    loading:false,
    searchBtnOptions:{
      search:{icon:'Search',auth:':page',label:'查询',type:null},
      create:{icon:'Plus',auth:':create',label:'新增',type:'primary'},
      import:{icon:'BottomRight',auth:':import',label:'导入',type:'warning'},
      export:{icon:'TopRight',auth:':export',label:'导出',type:'success'},
      custominvoke:{icon:'Position',auth:':custominvoke',label:'手动开关',type:'primary'},
    },
    innerTableColumns:null,
    tableData:[],
    // table排序处理
    sortFilter:{
      sortBy:undefined,
      isAscending:undefined
    },
    pager:{
      page: 1,
      pageSize: 10,
      total: 1,
    },
    tableSelectList:[],
    initTableColums:[],//初始化表头，未从缓存获取之前
    localTableColumnsName:null
  })

  const props = defineProps({
    // api名称
    apiName: {
      type: String,
      default: null
    },
    // 特殊的分页api
    specialPageApi:{
      type: String,
      default: null
    },
    // 特殊的column名称（没有默认apiName）
    specialColumnName:{
      type: String,
      default: null
    },
    // 特殊的存储column名称（没有默认apiName）
    specialLocalColumnName:{
      type: String,
      default: null
    },
    // 特殊权限前缀（如果没有默认使用apiName）
    authName:{
      type: String,
      default: null
    },
    // api类型 detailApi：走getdetail接口，不传或者pageApi：走getdatapaged接口
    apiType: {
      type: String,
      default: null
    },
    // 隐藏表头搜索
    hideSearch:{
      type: Boolean,
      default: false
    },
    // 行class
    tableRowClassName:{
      type: Function,
      default: null
    },
    // 单元格class
    tableCellClassName:{
      type: Function,
      default: null
    },
    // 多选
    multipleTable:{
      type: Boolean,
      default: false
    },
    // 左侧操作列
    leftOperation:{
      type: Object,
      default: null
    },
    // 左侧操作列宽度
    leftOperationColumnWidth:{
      type: Number,
      default: 120
    },
    // 右侧操作列
    rightOperation:{
      type: [Object,String],
      default: null
    },
    // 右侧操作列，特殊自定义格式下，包含api操作
    showApiRightOperation:{
      type: Object,
      default: null
    },
    // 右侧通用按钮特殊字段判断隐藏规则，默认为编辑删除，writeState=true不可操作，
    // 如有特殊规则，则使用该方法特殊处理,当前判断方式为“=”，如后期有其他需求再进行封装
    apiRightHideConfig:{
      type: Object,
      default: {
        apiUpdate:{prop:'writeState',ruleValue:true},
        apiDelete:{prop:'writeState',ruleValue:true},
      }
    },
    // table表头
    tableColumns: {
      type: Object,
      default: null
    },
    // 查询配置
    searchOptions: {
      type: Object,
      default: []
    },
    // 查询按钮
    searchButtons: {
      type: Object,
      default: ['search','export']
    },
    // table查询数据filter
    searchFilter: {
      type: Object,
      default: {}
    },
    // table查询数据filter的特殊条件，如果没有则走colum中的配置
    // 示例：infoSearchFilterOptions:{ TableName:{action:'=='}},
    searchFilterOptions: {
      type: Object,
      default: {}
    },
    // 表头宽度
    columnWidth:{
      type: Number,
      default: 120
    },
    // 表头对齐
    columnHeaderAlign:{
      type: String,
      default: 'center'
    },
    // 表内容对齐
    columnAlign:{
      type: String,
      default: 'center'
    },
    // 表单规则
    apiEditFormRules:{
      type: Object,
      default: null
    },
    // 隐藏字段设置
    hideSetColums:{
      type: Boolean,
      default: false
    }
  })

  
  // 获取表头  noFilter 不需要处理字段设置（用于编辑和新增）
  function getTableColumns(noFilter){
    if(noFilter){
      return props.tableColumns || apiTableColumns[props.apiName]
    }else{
      // 字段设置中，存入location的名字
      let _localColumName = props.specialLocalColumnName || useRoute().name
      state.localTableColumnsName = getLocalTableColumnsName(_localColumName)
      let _local = JSON.parse(localStorage.getItem(state.localTableColumnsName))
      // 获取列表配置
      let _apiColums = props.specialColumnName || props.apiName
      state.initTableColums = props.tableColumns || apiTableColumns[_apiColums]
      let _list = (_local && _local != null && _local != undefined) ? _local : JSON.parse(JSON.stringify(state.initTableColums))
      state.innerTableColumns = _list
      return _list
    }
  }

  const emits = defineEmits([
    'leftOperationHadel',
    'rightOperationHadel',
    'tableSelectionHandle'
  ])

  // table多选
  function tableSelectionHandle (val){
    state.tableSelectList = val
    emits('tableSelectionHandle',val)
  }

  // 左侧操作列
  function leftOperationHadel(btn,scope) {
    emits('leftOperationHadel',btn,scope)
  }

  // 获取右侧操作列
  function getRightOperation() {
    // 自定义右侧列，且不需要默认api通用操作
    if(typeof props.rightOperation == 'object' && !props.showApiRightOperation){
      return props.rightOperation
    }
    // 无自定义操作，或者有自定义且需要默认api操作
    else if(
      (typeof props.rightOperation == 'object' && props.showApiRightOperation)
      || typeof props.rightOperation == 'string'
    ){
      // 格式化默认api按钮合集
      let _apiArr = props.showApiRightOperation || props.rightOperation.split(',')
      let _config = {
        apiUpdate:{label:'编辑',type:'warning'},
        apiDelete:{label:'删除',type:'danger'},
      }
      let _btns = []
      if(_apiArr && _apiArr.length > 0){
        _apiArr.forEach(item => {
          _btns.push({
            label:_config[item].label,
            name:item,
            link:true,
            type:_config[item].type,
            auth:(props.authName || props.apiName)+':'+item,
            hide:(row,scope) => {return row[props.apiRightHideConfig[item].prop] == props.apiRightHideConfig[item].ruleValue}
          })
        });
      }
      // 如果有自定义按钮，合并默认api按钮
      if(typeof props.rightOperation == 'object'){
        _btns = [..._btns,...props.rightOperation]
      }
      return _btns
    }
  }

  // 右侧操作列操作
  const apiEditPopRef = ref()
  function rightOperationHadel(btn,scope) {
    // 通用编辑
    if(btn.name == 'apiUpdate'){
      let _tableColums = props.tableColumns || apiTableColumns[props.apiName]
      let _list = _tableColums.filter(item => !item.noEdit)
      apiEditPopRef.value.open(_list,scope.row)
    }
    // 通用删除
    if(btn.name == 'apiDelete'){
      ElMessageBox.confirm(`是否确定删除？`, '提示', {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'warning'
      }).then(() => {
        state.loading = true
        deleteCommonApi(props.apiName,scope.row.uId)
        .then(res=>{
          ElMessage.success('操作成功！')      
          getTableData(1);
        })
        .finally(()=>{state.loading = false})
      })
    }
    emits('rightOperationHadel',btn,scope)
  }

  // 编辑表单提交 
  const submitEditForm = async (type,formData,formConfig) => {
    apiEditPopRef.value.validate((valid) => {
      if(valid){
        // 新增
        if(type == 'create'){
          if(formData.hasOwnProperty('createUser')){formData.createUser = userInfo.realName}
          if(formData.hasOwnProperty('createByUser')){formData.createByUser = userInfo.realName}
          if(formData.hasOwnProperty('createTime')){formData.createTime = formatDate(new Date(), "YYYY-mm-dd HH:MM:SS")}
          apiEditPopRef.value.changeLoading(true)
          postCommonCreate(props.apiName,formData)
          .then(res=>{
            apiEditPopRef.value.close()
            ElMessage.success('操作成功！')      
            getTableData(1);
          })
          .catch(err=>{ElMessage.error('操作失败！')})
          .finally(()=>{apiEditPopRef.value.changeLoading(false)})
        }else{
          // 修改人信息处理
          if(
              (formData.hasOwnProperty('updateByUser') && formData.hasOwnProperty('updateTime'))
              || (formData.hasOwnProperty('updateUser') && formData.hasOwnProperty('updateTime'))
          ){
            if(formData.hasOwnProperty('updateByUser')){formData.updateByUser = userInfo.realName}
            if(formData.hasOwnProperty('updateUser')){formData.updateUser = userInfo.realName}
            if(formData.hasOwnProperty('updateTime')){formData.updateTime = formatDate(new Date(), "YYYY-mm-dd HH:MM:SS")}
          }else{
            // 特殊不处理页面
            let _notChange=['taskconifgure','customlog']
            if(_notChange.indexOf(props.apiName) < 0){
              formData.remark= `修改信息：${userInfo.realName} ${formatDate(new Date(), "YYYY-mm-dd HH:MM:SS")}`
            }
          }
          apiEditPopRef.value.changeLoading(true)
          putCommonUpdate(props.apiName,formData)
          .then(res=>{
            apiEditPopRef.value.close()
            ElMessage.success('操作成功！')      
            getTableData(1);
          })
          .catch(err=>{ElMessage.error('操作失败！')})
          .finally(()=>{apiEditPopRef.value.changeLoading(false)})
        }
      }
    })
  }

  // 格式化页面传参
  function getPageParams(pageSize){
    let _filters = []
    if(props.hideSearch){
      _filters = props.searchFilter
    }else{
      function __getAction (prop,action){
        if(props.searchFilterOptions && props.searchFilterOptions[prop] && props.searchFilterOptions[prop].action){
          return props.searchFilterOptions[prop].action
        }else{
          return action
        }
      }
      for(let i in props.searchFilter){
        let _item = props.searchOptions.filter(item=>item.prop == i)
        let _type = (_item && _item.length > 0) ? _item[0].type : null
        if((props.searchFilter[i] || props.searchFilter[i] == 0) && props.searchFilter[i] != ""){
          // 时间区域格式
          if(_type == 'datetimerange'){
            _filters.push(
              {
                logic: "And",
                column: i,
                action: __getAction(i,'>='),
                value: props.searchFilter[i][0]
              }
            )
            _filters.push(
              {
                logic: "And",
                column: i,
                action: __getAction(i,'<='),
                value: props.searchFilter[i][1]
              }
            )
          }else{
            let _action = 'like'
            let _EqualTypes = ['tagFilter','filter','number','select']//等于情况的类型
            if(_EqualTypes.indexOf(_type) >= 0){
              _action =  '=='
            }
            _filters.push(
              {
                logic: "And",
                column: i,
                action: __getAction(i,_action),
                value: props.searchFilter[i]
              }
            )
          }
        }
      }
    }
    let _pageParams = getPageParamsForFilter({
      pageNumber:state.pager.page,
      pageSize:pageSize || state.pager.pageSize,
      sortBy:state.sortFilter.sortBy,
      isAscending:state.sortFilter.isAscending,
      condition:{
        filters:_filters
      }
    })
    return _pageParams
  }

  // 获取页面数据
  function getTableData(page,callback) {
    state.loading = true
    if(!page)page = state.pager.page
    if(page)state.pager.page = page
    if(props.apiType == 'detailApi'){
      getCommonDeatailPaged(props.apiName,getPageParams())
        .then((resp) => {
          state.tableData = resp.data.data
          state.pager.total = resp.data.totalCount
          if(callback)callback(resp)
        })
        .catch(err=>{ElMessage.error('数据获取失败！')})
        .finally(() => (state.loading = false))
    }else if(props.specialPageApi){
      getCommonPost(props.specialPageApi,getPageParams())
        .then((resp) => {
          state.tableData = resp.data.data
          state.pager.total = resp.data.totalCount
          if(callback)callback(resp)
        })
        .catch(err=>{ElMessage.error('数据获取失败！')})
        .finally(() => (state.loading = false))
    }
    else{
      getCommonPaged(props.apiName,getPageParams())
        .then((resp) => {
          state.tableData = resp.data.data
          state.pager.total = resp.data.totalCount
          if(callback)callback(resp)
        })
        .catch(err=>{ElMessage.error('数据获取失败！')})
        .finally(() => (state.loading = false))
    }
  }

  // 导出
  function exportHandle(isAll){
    state.loading = true
    //同步数据查询
    getTableData(1,(res=>{
      let _params = getPageParams()
      if(isAll){_params = getPageParams(res.data.totalCount)}
      postCommonExport(props.apiName,_params)
        .then((res) => {
          let _str = isAll ? '全部' : '当页'
          downloadByData(res.data,route.meta.title+`_按条件导出${_str}.xlsx`)
        })
        .catch(err=>{ElMessage.error('操作失败！')})
        .finally(() => (state.loading = false))
    }))
    
  }

  const importPopRef = ref()
  // 按钮功能
  function searchBtnHandle(btn){
    // 查询
    if(btn == 'search'){
      getTableData(1)
    }
    // 新增
    else if (btn == 'create'){
      let _tableColums = props.tableColumns || apiTableColumns[props.apiName]
      let _list = _tableColums.filter(item => !item.noEdit)
      apiEditPopRef.value.open(_list)
    }
    // 导入
    else if (btn == 'import'){
      importPopRef.value.open()
    }
    // 导出（按条件导出当前页）
    // else if (btn == 'export'){
    //   exportHandle()
    // }
    // 手动开关
    else if (btn == 'custominvoke'){
      ElMessageBox.confirm('是否确定操作手动开关？', '提示', {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'warning'
      }).then(() => {
        state.loading = true
        let _data = {
          taskName:apiServeNames[props.apiName].taskName,
          client:'Chery'
        }
        getCommonCustominvoke(_data)
        .then((res) => {
          ElMessage.success('操作成功！')    
          getTableData(1)//同步数据查询
        })
        .finally(() => (state.loading = false))
      })
    }
  }

  // 排序
  function sortChange(data) {
    const { prop, order } = data;
    if (!prop || !order) {
      state.sortFilter.sortBy = undefined;
      state.sortFilter.isAscending = undefined;
      getTableData(1);
      return;
    }
    state.sortFilter.sortBy = prop;
    state.sortFilter.isAscending = (order == "ascending");
    getTableData(1);
  }
  
  // 导入成功之后todo
  function importSuccess(response,importDate){
    getTableData()
  }
  
  // size-change
  function pageSizeChange(pageSize){
    state.pager.pageSize = pageSize
    getTableData(1)
  }

  // current-change
  function pageCurrentChange(page){
    getTableData(page)
  }

  onMounted(() => {
    getTableColumns()
    getTableData()
  })

  defineExpose({
    state,
    getTableData
  });
</script>

<style scoped lang="scss">
::v-deep .search-container {
  .el-card__body{
    display:flex;
    justify-content: space-between;
  }
}
</style>