<!--
 * @Author: wlo_o
 * @Date: 2022-02-15 16:43:31
 * @LastEditors: Jone
 * @LastEditTime: 2022-07-04 11:06:10
 * @FilePath: /frontend/lib/components/MdSetElementList.vue
 * @Description: 集合元素（数据元、值域、统计指标)
 *
 * Copyright (c) 2022 by 青岛百洋智能科技股份有限公司, All Rights Reserved.
-->
<template>
  <div class="oecp-md-set-element-list">
    <el-row v-if="showHeader||showGoBack||!!$slots.actionBar||$slots.title||showSearch||editable">
      <el-col :span="12">
        <el-row type="flex">
          <el-col :span="24">
            <template v-if="showGoBack">
              <el-page-header
                @back="goBack"
                title=''
              >
                <div slot="content">
                  <template v-if="!!$slots.title">
                    <slot name="title"></slot>
                  </template>
                  <div v-else-if="!!title">{{title}}</div>
                  <div v-else>&nbsp;</div>
                </div>
              </el-page-header>
            </template>
            <template v-else>
              <template v-if="!!$slots.title">
                <slot name="title"></slot>
              </template>
              <div v-else-if="!!title">{{title}}</div>
              <div v-else>&nbsp;</div>
            </template>
          </el-col>
        </el-row>
      </el-col>
      <el-col
        v-if="!!$slots.actionBar||showSearch||editable"
        :span="12"
      >
        <template v-if="!!$slots.actionBar">
          <slot name="actionBar"></slot>
        </template>
        <template v-else>
          <el-row
            type="flex"
            justify="end"
            style="padding: 0 0 10px"
          >
            <el-input
              v-if="showSearch"
              v-model="searchName"
              clearable
              @clear="()=>{pagination.page==1?getList():(pagination.page=1)}"
              @keyup.enter.native="()=>{pagination.page==1?getList():(pagination.page=1)}"
            >
              <el-button
                @click="()=>{pagination.page==1?getList():(pagination.page=1)}"
                slot="append"
                icon="el-icon-search"
              />
            </el-input>
            <el-button
              v-if="showImport"
              @click="handleImportClick"
              type="primary"
              size="small"
              class="addBtn"
              icon="el-icon-circle-plus"
            >导入</el-button>
            <el-button
              v-if="editable&&showAddModule"
              :disabled="!id"
              @click="handleModuleAddClick()"
              style="margin-left:5px;"
              size="small"
              type="primary"
              class="addBtn"
            >添加模块</el-button>
          </el-row>
        </template>
      </el-col>
    </el-row>
    <el-row>
      <el-table
        :header-cell-style="{background:'#F2F7FF',color:'#323232',height:'46px'}"
        v-loading="loading"
        :data="tableData"
        row-key="uuid"
        style="width: 100%"
        stripe
      >
        <el-table-column
          type="index"
          width="50"
        >
          <div slot="header">序号</div>
          <!-- <template scope="scope">{{(pagination.page-1)*pagination.pageSize+scope.$index+1}}</template> -->
        </el-table-column>
        <el-table-column
          v-for="(column,idx) in columns"
          :key="`column_${idx}`"
          v-bind="column"
        >
          <template
            v-for="(render,key) in column.slots"
            v-slot:[key]="scope"
          >
            <md-slot-shim
              :key="`slot_${key}`"
              :render="render"
              :data="scope"
            />
          </template>
        </el-table-column>
        <el-table-column
          v-if="editable&&displayType==='table'"
          :width="showRowBtnText?200:100"
          label="操作"
        >
          <template slot-scope="scope">
            <el-button
              :disabled="allowDelete?false:(scope.row.isSys==1)"
              @click="handleRowDel(scope.row)"
              type="text"
              size="medium"
            >
              <i
                :style="!(allowDelete?false:(scope.row.isSys==1))?{color:'#F56C6C'}:{}"
                class="el-icon-close delBtn"
              ></i>
              <span v-if="showRowBtnText">删除</span>
            </el-button>
          </template>
        </el-table-column>
      </el-table>
    </el-row>
    <el-row
      v-show="pagination.total"
      type="flex"
      justify="end"
    >
      <el-pagination
        :loading="loading"
        :total="pagination.total"
        :page-sizes="pagination.pageSizes"
        :page-size.sync="pagination.pageSize"
        :current-page.sync="pagination.page"
        layout="prev,pager,next,sizes,jumper"
        background
      />
    </el-row>
    <md-set-module-dialog
      :id="id"
      :visible="dialogVisible"
      :editable="true"
      @close="dialogVisible=false"
    />
    <md-import-from-element-dialog
      v-if="showImport"
      :visible="importVisible"
      :setId="id"
      @close="importVisible=false"
      @success="getList()"
    />
  </div>
</template>
<script>
import OptionsMixin from '../mixins/OptionsMixin'
import RouterMixin from '../mixins/RouterMixin'
import EventMixin from '../mixins/EventMixin'
import { clone, guid } from '../common/utils.js'
import get from 'lodash/get'
import isEmpty from 'lodash/isEmpty'
import debounce from 'lodash/debounce'
import isFunction from 'lodash/isFunction'
import { fetchApi } from '../common/apis.js'

let extQuery = { ids: [], extNameList: [] } // 查询条件,放在外面规避内部使用循环报错

export default {
  mixins: [OptionsMixin, EventMixin, RouterMixin],
  props: {
    showGoBack: { type: Boolean, default: false }, // 显示返回
    showSearch: { type: Boolean, default: false }, // 显示返回
    showAddModule: { type: Boolean, default: true }, // 显示添加模块
    title: { type: [String, null], default: '' },
    type: { type: [String, null], default: '' },
    id: { type: String, default: null }, // 数据集主键
    showSubsetElement: { type: Boolean, default: false }, // 显示包含子集数据
    editable: { type: Boolean, default: false },
    defaultQuery: { type: [Object, null], default: null }, // 默认查询条件
    showImport: { type: Boolean, default: false },
    allowDelete: { type: Boolean, default: false },
    displayType: { type: String, default: 'table', validator: v => ['table', 'preview'].includes(v) }, // 显示方式
  },
  watch: {
    id: function (id) {
      id && this.loadData()
    },
    showSubsetElement() {
      this.id && this.loadData()
    },
    defaultQuery: function (val = {}) {
      this.defaultQuery = val
    },
    'pagination.page': function () {
      this.getList()
    },
    'pagination.pageSize': function () {
      this.getList()
    },
  },
  computed: {
    showHeader: function () {
      return (!!this.$slots.title || this.title) && this.editable && this.showSaveBtn
    },
    elementTableConfig: function () {
      // 表格、预览两种方式的表格配置。预览方式没有编辑列
      let cfgKey = this.displayType === 'table' ? 'elementTableConfig' : 'elementPreviewConfig'
      let cfg = this.getMbOptionVar(`${cfgKey}${this.type}`)
      return cfg || {}
    },
  },
  data() {
    return {
      extListData: {}, // key: 扩展字段名，value:  {key: value, value: label}
      loading: false,
      showRowBtnText: false,
      tableData: [],
      searchName: '',
      stateDefaultQuery: this.defaultQuery || {},
      columns: this.getColumns(this.showSubsetElement),
      subsetIds: [], // 子集id
      pagination: {
        total: 0,
        page: 1,
        pageSize: 10,
        pageSizes: [10, 20, 50, 100],
      },
      dialogVisible: false,
      importVisible: false,
      extData: {},
      debounceGetExtData: debounce(this.getExtData, 250),
    }
  },
  methods: {
    getColumns(showSubsetElement) {
      let columns = [
        ...(showSubsetElement
          ? [
              { prop: 'name', label: '数据元名称' },
              { prop: 'code', label: '数据元标识符' },
              { prop: 'setName', label: '集合名称' },
              { prop: 'setCode', label: '集合编码' },
            ]
          : [
              { prop: 'elementName', label: '名称' },
              { prop: 'elementAlias', label: '名称别名' },
              { prop: 'code', label: '编码' },
            ]),
        { prop: 'sourceFileCode', label: '来源文件编码' },
        { prop: 'sourceCode', label: '来源标识符' },
        { prop: 'moduleName', label: '模块' },
      ]
      let cfg = this.getElementTableConfig()
      let extColumns = get(cfg, 'elementTable.extColumns')
      if (!isEmpty(extColumns)) {
        columns = [...columns, ...extColumns]
      }
      return columns
    },
    loadSubset() {
      let that = this
      this.subsetIds = []
      let query = { parentId: this.id, page: 1, pageSize: 999999 }
      return new Promise(function (resolve, reject) {
        fetchApi
          .call(that, '/set/pageList', query)
          .then(res => {
            that.subsetIds = (get(res, 'records') || []).reduce((arr, item) => [...arr, item.id], []) || []
            resolve()
          })
          .catch(err => {
            reject(err)
          })
      })
    },
    getExtData(cfg = {}) {
      let that = this
      let { ids, extNameList } = extQuery
      let { type, isPrimaryTable = false } = cfg
      type = type || this.type
      let { component = 'set' } = this.getTypeConfig(type)
      let url = ''
      let query = {}
      if (isPrimaryTable) {
        url = component === 'element' ? '/element/pageList' : '/set/pageList'
        query = { ids, page: 1, pageSize: ids.length + 10 }
      } else {
        url = component === 'element' ? '/element/extList' : '/set/extList'
        query = { ids, extNameList }
      }
      fetchApi.call(that, url, query).then(function (res) {
        let extData = {}
        if (isPrimaryTable) {
          ;(res.records || []).forEach(function ({ id, name }) {
            extData[`${id}`] = name
          })
        } else {
          ;(res || []).forEach(function ({ extName, parentId, extValue }) {
            extData[`${parentId}_${extName}`] = extValue
          })
        }
        that.extData = { ...that.extData, ...extData }
      })
    },
    pushQuery(id = '', extName = '', cfg = {}) {
      if (!id && !extName) return
      cfg = { ...cfg, type: cfg.type || this.type }
      let key = cfg.isPrimaryTable ? `${id}` : `${id}_${extName}`
      // 会出现循环调用，添加判断规避死循环
      if (this.extData.hasOwnProperty(key)) return
      this.extData[key] = ''
      extQuery = {
        ids: [...new Set([...extQuery.ids, id])],
        extNameList: [...new Set([...extQuery.extNameList, extName])],
      }
      this.debounceGetExtData(cfg)
    },
    extColumnRender(h, data, extName = '', customRender) {
      this.loadExtData(h, data, extName, customRender)
    },
    loadExtData(h, data, extName = '', cfg, customRender) {
      let { _self: self, row = {} } = data
      if (isEmpty(row) || !extName || !row.id) return h('div')
      if (isFunction(cfg)) {
        customRender = cfg
        cfg = {}
      }
      cfg = { ...cfg, type: cfg.type || this.type }
      this.pushQuery(row.id, extName, cfg || {})
      if (customRender && isFunction(customRender)) {
        return customRender(h, data, extName, cfg)
      } else {
        let { isPrimaryTable } = cfg
        let key = isPrimaryTable ? `${row.id}` : `${row.id}_${extName}`
        return h('div', { domProps: { innerHTML: self.extData[key] } })
      }
    },
    getTypeConfigList() {
      return get(this.getMbOptionVar('typeConfig'), 'list') || []
    },
    getTypeConfig(type) {
      type = type || this.type
      return this.getTypeConfigList().find(o => o.type === type)
    },
    getCurrentRouteCfg() {
      let current = clone(this.$OecpMetaDataEventBus.component)
      return { ...current, attrs: { ...current.attrs, page: this.pagination.page, type: this.type } }
    },
    handleImportClick() {
      this.importVisible = true
    },
    getElementTableConfig() {
      let prefix = this.displayType === 'table' ? 'elementTableConfig' : 'elementPreviewConfig'
      let cfgKey = `${prefix}${this.type}`
      return this.getMbOptionVar(cfgKey) || {}
    },
    handleModuleAddClick() {
      this.dialogVisible = true
    },
    loadData() {
      let that = this
      this.pagination = { ...this.pagination, page: 1 }
      let dfd = this.showSubsetElement ? this.loadSubset() : Promise.resolve()
      this.showSubsetElement && (this.columns = this.getColumns(this.showSubsetElement))
      dfd.then(function () {
        that.getList()
      })
    },
    getList() {
      let that = this
      let { pageSize, page } = this.pagination
      let { id, stateDefaultQuery: query, searchName: name, showSubsetElement, subsetIds } = this
      let tableData = []
      let total = 0
      this.extData = {}
      let search = { ...query, ...(name && { name }), ...(showSubsetElement ? { ids: [...subsetIds, id] } : { id }), pageSize, page }
      if (this.loading) return
      this.loading = true
      fetchApi
        .call(that, '/element/source', search)
        .then(res => {
          let { records: list = [] } = res
          list.forEach(function (item) {
            item.uuid = guid()
          }) // 集合内元素会有重合，需要使用 row-key 规避数据去重
          tableData = list
          total = res.total || 0
          let dfd = new Promise(function (resolve, reject) {
            if (!list || list.length === 0) return resolve()
            let ids = list.reduce((arr, o) => [...new Set([...arr, o.id])], []) // ⚠️注意 元素id 数据会重复，同一个元素可能在多个集合中
            // 拼装扩展数据
            let cfg = that.getElementTableConfig()
            let extNameList = get(cfg, 'elementTable.extNames')
            if (!isEmpty(extNameList)) {
              fetchApi
                .call(that, '/element/extList', { ids, extNameList })
                .then((arr = []) => {
                  let extList = arr || []
                  let kv = {}
                  extList.forEach(item => {
                    let { parentId, extName: key, extValue: val } = item
                    let o = kv[parentId] || {}
                    kv[parentId] = { ...o, id: parentId, [key]: val }
                  })
                  for (let i = 0; i < list.length; i++) {
                    if (kv.hasOwnProperty(list[i].id)) {
                      list[i] = { ...kv[list[i].id], ...list[i] } // 注意主数据不能被覆盖
                    }
                  }
                  tableData = list
                  resolve()
                })
                .catch(err => {
                  reject(err)
                })
            } else {
              resolve()
            }
          })
          dfd
            .then(function () {
              that.tableData = tableData
              that.pagination.total = total
              that.loading = false
            })
            .catch(() => {
              that.loading = false
            })
        })
        .catch(() => {
          that.loading = false
        })
    },
    handleRowDel(data) {
      let that = this
      this.$confirm('此操作将永久删除本行数据, 是否继续?', '提示', {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'warning',
      }).then(() => {
        console.log(data)
        fetchApi
          .call(this, '/set/delChildren', {
            // setId: data.setId || that.id,
            // elementId: data.id,
            id: data.id || that.id,
          })
          .then(res => {
            that.$message({ type: 'success', message: '删除成功!' })
            setTimeout(function () {
              that.getList()
            }, 200)
          })
      })
    },
  },
  created() {
    this.id && this.loadData()
    window.vm = this
  },
}
</script>
<style>
.ml5 {
  margin-left: 5px;
}
/* checkbox start*/
/deep/.el-table .cell .el-checkbox .el-checkbox__input .el-checkbox__inner {
  border-radius: 100% !important;
  height: 16px;
  width: 16px;
}

/deep/.cell .el-checkbox .el-checkbox__inner::after {
  border: none;
  background: #1a63eb;
  border-radius: 100%;
  width: 9px;
  height: 9px;
  top: 17%;
  left: 17.85%;
}

/* checkbox end*/

.title-style {
  padding-bottom: 0;
  display: flex;
  align-items: center;
  font-size: 18px;
}

.el-input-group {
  border-radius: 30px;
  overflow: hidden;
  /* border: 1px solid #ddd; */
  width: 300px;
  margin-left: 15px;
}

/deep/.el-input-group--append .el-input__inner,
/deep/.el-input-group__prepend {
  border-top-left-radius: 30px !important;
  border-bottom-left-radius: 30px !important;
  height: 36px !important;
  background-color: #fff;
  border: none;
}

/deep/.el-input-group--prepend .el-input__inner,
/deep/.el-input-group__append {
  border-top-right-radius: 30px !important;
  border-bottom-right-radius: 30px !important;
  background-color: #fff;
  border: none;
}

/deep/.el-icon-search {
  color: #2468f2 !important;
  font-size: 20px;
}

/deep/.el-input-group--append .el-input__inner {
  border-top-left-radius: 30px !important;
  border-bottom-left-radius: 30px !important;
  height: 36px !important;
}

/deep/.el-input-group__append {
  padding-right: 8px;
  border-top-right-radius: 30px !important;
  border-bottom-right-radius: 30px !important;
}
/deep/.el-table th.el-table__cell.is-leaf {
  border-bottom: none !important;
}
.addBtn {
  background: #2468f2 !important;
  border-color: #2468f2 !important;
  height: 36px;
  line-height: 36px;
}
.addBtn:hover {
  background: #2469f2d6 !important;
  border-color: #2469f2d6 !important;
}
.oecp-md-set-element-list {
  padding: 20px;
}
.delBtn {
  color: #ff432e;
  background: #ffeeeb;
  border-radius: 100%;
  font-size: 13px;
  padding: 2px;
  font-weight: 600;
}
/deep/.el-icon-close {
  font-size: 18px;
}
/* 分页 */
.el-pagination.is-background .el-pager li:not(.disabled).active {
  background: #2468f2 !important;
}
</style>
