<template>
    <!-- 人员选择弹层 -->
    <super-dialog
        v-bind="$attrs"
        v-model="isShowDialog"
        :width="width"
        :modal="false"
        :top="top"
        @open="open"
        @closed="closed"
    >
        <div class="super-table-selector-dialog" :style="{height}">
            <div class="tree-module" v-if="isShowTree">
                <tree-side
                    :activeName="treeActiveTabName"
                    v-bind="$attrs"
                    :tabList="treeTabList"
                    :data-loading="treeLoading"
                    :treeData="treeData"
                    :default-expand-all="false"
                    isDeselect
                    :defaultProps="treeOptions"
                    :nodeKey="treeKey"
                    @tabChange="treeTabChange"
                    @currentChange="currentChange"
                    ref="treeSide"
                ></tree-side>
            </div>
            <div class="table-module">
                <div class="search-content" v-if="isShowSearch">
                    <el-button
                        type="primary"
                        size="small"
                        icon="el-icon-plus"
                        v-if="isShowAddButton"
                        @click="handleAdd"
                        >添加</el-button
                    >
                    <SearchCommon
                        @search="handleSearch"
                        :optionList="searchOption"
                        ref="searchCommon"
                    />
                </div>
                <div class="table-content" ref="tableRef">
                    <el-table
                        stripe
                        v-loading="tableLoading"
                        element-loading-background="rgba(10 ,38 ,61, 0.9)"
                        ref="multipleSelection"
                        :data="enhancedTableData"
                        :row-key="(row) => row[selectKey]"
                        :max-height="tableMaxHeight"
                        border
                        @row-click="(row) => tableRowClick(row, !row.checked)"
                        :row-class-name="rowClassName"
                        @sort-change="(e) => $emit('sort-change', e)"
                    >
                        <el-table-column
                            width="60"
                            align="center"
                            v-if="!isSingleChoice && isShowTableCheckbox"
                        >
                            <template v-slot:header>
                                <el-checkbox
                                    :indeterminate="tableIsIndeterminate"
                                    v-model="tableCheckAll"
                                    @change="tableHandleCheckAllChange"
                                    :disabled="
                                        isSingleChoice ||
                                        enhancedTableData.every(
                                            (i) => i.disabled
                                        )
                                    "
                                />
                            </template>
                            <template v-slot:default="{row}">
                                <el-checkbox
                                    :disabled="row.disabled"
                                    @change="tableRowClick(row, !row.checked)"
                                    v-model="row.checked"
                                />
                            </template>
                        </el-table-column>
                        <el-table-column
                            type="index"
                            width="60"
                            label="序号"
                            align="center"
                            :index="
                                (index) =>
                                    index +
                                    1 +
                                    (tableParams.pageBean.page - 1) *
                                        tableParams.pageBean.pageSize
                            "
                        />
                        <el-table-column
                            v-for="item in tableOptions"
                            :key="item.prop"
                            :prop="item.prop"
                            show-overflow-tooltip
                            :min-width="item.minWidth"
                            align="center"
                            :label="item.label"
                            :formatter="
                                (row) =>
                                    item.formatter
                                        ? item.formatter(row)
                                        : row[item.prop]
                            "
                            :sortable="item.sortable ? 'custom' : false"
                        />
                        <slot name="tableHandler"></slot>
                    </el-table>
                    <div class="table-content-bottom" v-if="!isShowSelect">
                        <pagination
                            ref="paginationPanel"
                            style="margin-top: 10px"
                            :pageResult="tableParams.pageBean"
                            @size-change="handleSizeChange"
                            @current-change="handleCurrentChange"
                            v-if="isShowPagination"
                        />
                        <div class="btn-box">
                            <el-button
                                size="small"
                                @click="isShowDialog = false"
                            >
                                取 消
                            </el-button>
                            <el-button
                                :disabled="tableLoading"
                                size="small"
                                type="primary"
                                @click="confirm"
                            >
                                确 定
                            </el-button>
                        </div>
                    </div>
                    <pagination
                        v-if="isShowSelect && isShowPagination"
                        ref="paginationPanel"
                        style="margin-top: 10px"
                        :pageResult="tableParams.pageBean"
                        @size-change="handleSizeChange"
                        @current-change="handleCurrentChange"
                    />
                </div>
            </div>
            <div class="select-module" v-show="isShowSelect">
                <div class="title-box">
                    <span class="title-box-left">
                        <el-checkbox
                            :indeterminate="isIndeterminate"
                            v-model="checkAll"
                            @change="handleCheckAllChange"
                            :disabled="
                                !checkboxOpt.length ||
                                checkboxOpt.every((i) => i.disabled) ||
                                tableLoading
                            "
                        />
                        {{ selectTitleName }}
                    </span>
                    <div class="title-box-right">
                        {{ checkboxSelect.length }}/{{ checkboxOpt.length }}
                    </div>
                </div>
                <div class="select-content">
                    <div class="select-content-center">
                        <el-checkbox-group
                            v-model="checkboxSelect"
                            size="medium"
                            ref="checkboxGroup"
                        >
                            <el-checkbox
                                @change="
                                    (status) =>
                                        handleCheckedChange(
                                            status,
                                            item,
                                            checkboxSelect
                                        )
                                "
                                v-for="(item, index) in checkboxOpt"
                                :key="index"
                                :label="item[selectKey]"
                                border
                                :disabled="item.disabled || tableLoading"
                            >
                                <span :title="item[selectLabel]">
                                    {{ isSingleChoice ? '' : `${index + 1}. `
                                    }}{{ item[selectLabel] }}
                                </span>
                            </el-checkbox>
                        </el-checkbox-group>
                    </div>
                    <div class="select-content-bottom">
                        <el-button size="small" @click="isShowDialog = false">
                            取 消
                        </el-button>
                        <el-button
                            :disabled="tableLoading"
                            size="small"
                            type="primary"
                            @click="confirm"
                        >
                            确 定
                        </el-button>
                    </div>
                </div>
            </div>
        </div>
    </super-dialog>
</template>

<script>
import SuperDialog from '@/components/SuperDialog/index.vue'
import treeSide from '@/components/treeSide/index.vue'
import {setQueryValue} from '@/utils/requestWrappers'
import SearchCommon from '@/components/SearchCommon/index.vue'
import pagination from '@/components/SuperPagination/index.vue'
import _ from 'lodash'
import {TableMixin} from '@/mixins/tableMixin'

export default {
    name: 'SuperTableSelectorDialog',
    inheritAttrs: false,
    mixins: [TableMixin],
    props: {
        isShow: {
            default: false,
            type: Boolean,
        },
        selectedContent: {
            default: () => [],
            type: [Array, Object],
        },
        top: {
            default: '14vh',
            type: String,
        },
        width: {
            default: '80%',
            type: String,
        },
        height: {
            default: '65vh',
            type: String,
        },
        isShowTree: {
            default: true,
            type: Boolean,
        },
        treeOptions: {
            default: () => ({children: 'children', label: 'name'}),
            type: Object,
        },
        treeTabList: {
            default: () => [],
            type: Array,
        },
        treeActiveTabName: {
            default: '',
            type: String,
        },
        treeLoading: {
            default: false,
            type: Boolean,
        },
        treeItem: {
            default: () => ({}),
            type: Object,
        },
        tableLoading: {
            default: false,
            type: Boolean,
        },
        tableParams: {
            default: () => ({
                pageBean: {pageSize: 0, page: 0, total: 0},
                querys: [],
                sorter: [],
            }),
            type: Object,
        },
        tableData: {
            default: () => [],
            type: Array,
        },
        treeData: {
            default: () => [],
            type: Array,
        },
        searchOption: {
            default: () => [],
            type: Array,
        },
        tableOptions: {
            default: () => [],
            type: Array,
        },
        treeKey: {
            default: 'id',
            type: String,
        },
        selectKey: {
            default: 'id',
            type: String,
        },
        selectLabel: {
            default: 'name',
            type: String,
        },
        selectTitleName: {
            default: '已选择',
            type: String,
        },
        treeValueKey: {
            default: '',
            type: String,
        },
        defaultTreeExpandLevel: {
            default: -1,
            type: Number,
        },
        isSingleChoice: {
            default: false,
            type: Boolean,
        },
        isShowSelect: {
            default: true,
            type: Boolean,
        },
        isShowTableCheckbox: {
            default: true,
            type: Boolean,
        },
        confirmCloseDialog: {
            default: true,
            type: Boolean,
        },
        isShowPagination: {
            default: true,
            type: Boolean,
        },
        isShowSearch: {
            default: true,
            type: Boolean,
        },
        isShowAddButton: {
            default: false,
            type: Boolean,
        },
    },
    components: {
        pagination,
        SearchCommon,
        treeSide,
        SuperDialog,
    },
    data() {
        return {
            initializeRendering: false, // 弹层内容初始化渲染
            tableMaxHeight: '600px',
            enhancedTableData: [], // 增强的表格数据（增加额外特性）
            allSelection: [], // 表格选中
            checkboxOpt: [], // 多选框配置数组
            checkboxSelect: [], // 多选框选中
            checkAll: false, // 全选
            tableCheckAll: false, // 表格全选
            tableIsIndeterminate: false, // 表格多选框不确定
            isIndeterminate: false, // 多选框不确定
        }
    },
    computed: {
        isShowDialog: {
            get() {
                return this.isShow
            },
            set(val) {
                this.$emit('update:isShow', val)
            },
        },
    },
    watch: {
        treeData: {
            handler() {
                if (!this.isShowTree) return
                this.$nextTick((_) => {
                    this.$refs.treeSide?.setCurrentKey(
                        this.treeItem?.[this.treeKey] || ''
                    )
                    this.$refs.treeSide?.expandHandle(
                        true,
                        this.defaultTreeExpandLevel
                    )
                })
            },
            immediate: true,
        },
        tableData: {
            handler(data) {
                this.enhancedTableData = data.map((item) => ({
                    ...item,
                    checked: this.allSelection.some(
                        (i) => i[this.selectKey] === item[this.selectKey]
                    ),
                    disabled:
                        this.allSelection.find(
                            (i) => i[this.selectKey] === item[this.selectKey]
                        )?.disabled ?? false,
                }))
                this.tableCheckAll = this.enhancedTableData.length
                    ? this.enhancedTableData.every((i) => i.checked)
                    : false
                this.tableIsIndeterminate =
                    this.enhancedTableData.some((i) => i.checked) &&
                    !this.tableCheckAll
            },
            immediate: true,
            deep: true,
        },
        selectedContent: {
            handler(data) {
                let allSelection
                if (this.isSingleChoice) {
                    if (
                        Object.prototype.toString.call(data) ===
                            '[object Object]' &&
                        Object.keys(data).length
                    ) {
                        allSelection = [_.cloneDeep(data)] || []
                    } else {
                        allSelection = []
                    }
                } else {
                    allSelection = _.cloneDeep(data) || []
                }
                this.allSelection = allSelection.map((i) => ({
                    ...i,
                    checked: true,
                }))
                this.updateCheckboxOpt()
            },
            immediate: true,
            deep: true,
        },
    },
    mounted() {
        this.$root.$on('resize', () => {
            this.calcTableHeight(500)
        })
    },
    methods: {
        treeTabChange(treeActiveTabName) {
            this.$emit('update:treeActiveTabName', treeActiveTabName)
            this.$emit('treeTabChange', treeActiveTabName)
        },
        // 打开弹层时触发
        open() {
            if (!this.initializeRendering) this.$emit('initializeRendering')
            let allSelection
            if (this.isSingleChoice) {
                if (
                    Object.prototype.toString.call(this.selectedContent) ===
                        '[object Object]' &&
                    Object.keys(this.selectedContent).length
                ) {
                    allSelection = [_.cloneDeep(this.selectedContent)] || []
                } else {
                    allSelection = []
                }
            } else {
                allSelection = _.cloneDeep(this.selectedContent) || []
            }
            this.allSelection = allSelection.map((i) => ({...i, checked: true}))
            this.updateCheckboxOpt()

            // 初始化首次打开弹层选中效果,
            if (this.isShowTree && !this.initializeRendering) {
                this.$nextTick((_) => {
                    this.$refs.treeSide?.setCurrentKey(
                        this.treeItem?.[this.treeKey] || ''
                    )
                    this.$refs.treeSide?.expandHandle(
                        true,
                        this.defaultTreeExpandLevel
                    )
                })
            }

            this.$emit('open', this.initializeRendering)
            this.initializeRendering = true
        },

        // 关闭弹层后触发
        closed() {
            Object.assign(this.$data, this.$options.data.call(this)) // 重置data中的数据
            // 重置打开弹层选中效果,
            this.$nextTick((_) => {
                if (this.isShowTree) {
                    this.$refs.treeSide?.setCurrentKey(
                        this.treeItem?.[this.treeKey] || ''
                    )
                    this.$refs.treeSide?.expandHandle(
                        true,
                        this.defaultTreeExpandLevel
                    )
                }
                this.$refs.searchCommon?.deleteChoose('all', false) // 清空搜索选中
                this.$refs.multipleSelection?.clearSort() // 用于清空排序条件，数据会恢复成未排序的状态
            })
            this.$emit('closed')
        },

        // 表格行样式自定义
        rowClassName({row}) {
            const classArr = []
            if (
                this.allSelection.some(
                    (i) => i[this.selectKey] === row[this.selectKey]
                )
            ) {
                classArr.push('current-row')
            }
            if (row.disabled) {
                classArr.push('disabled-row')
            }
            return classArr.join(' ')
        },

        //左边树节选中改变
        currentChange(nodeItem) {
            this.tableParams.pageBean.page = 1
            // 为了避免左侧树勾选的参数用于表格查询中的方式有不确定性，则把修改查询项功能留给父组件自己做
            this.$emit('update:treeItem', nodeItem || {})
            this.$emit('treeChange', nodeItem)
        },

        // 顶部搜索逻辑触发
        handleSearch(data) {
            this.tableParams.pageBean.page = 1
            data.forEach((item) => {
                if (Array.isArray(item.prop) && item.prop.length) {
                    item.prop.forEach((prop) => {
                        setQueryValue(this.tableParams, prop, item.value)
                    })
                } else if (typeof item.prop === 'string') {
                    setQueryValue(this.tableParams, item.prop, item.value)
                }
                console.log(this.tableParams.querys)
            })
            console.log(data, this.tableParams.querys)

            this.$emit('tableRefresh', this.tableParams)
        },

        //分页页数
        handleCurrentChange(page) {
            this.tableParams.pageBean.page = page
            this.$emit('tableRefresh', this.tableParams)
        },

        //分页大小
        handleSizeChange(pageSize) {
            this.tableParams.pageBean.pageSize = pageSize
            this.$emit('tableRefresh', this.tableParams)
        },

        // 表格行点击
        tableRowClick(row, status) {
            this.tableSelection(row, status)
            this.updateCheckboxOpt()
        },

        // 表格勾选或取消勾选
        tableSelection(item, status) {
            if (item.disabled) return
            const tableIndex = this.enhancedTableData.findIndex(
                (i) => i[this.selectKey] === item[this.selectKey]
            )
            const findIndex = this.allSelection.findIndex(
                (i) => i[this.selectKey] === item[this.selectKey]
            )
            if (tableIndex !== -1)
                this.enhancedTableData[tableIndex].checked = status
            if (status) {
                if (this.isSingleChoice) {
                    this.allSelection = [item]
                    this.enhancedTableData.forEach((i) => {
                        if (i[this.selectKey] !== item[this.selectKey])
                            i.checked = false
                    })
                } else {
                    if (findIndex === -1) this.allSelection.push(item)
                }
            } else {
                if (findIndex !== -1) this.allSelection.splice(findIndex, 1)
            }

            this.tableCheckAll = this.enhancedTableData.every((i) => i.checked)
            this.tableIsIndeterminate =
                this.enhancedTableData.some((i) => i.checked) &&
                !this.tableCheckAll
        },

        // 多选框列表滚动到底部
        checkboxScrollBottom() {
            this.$nextTick((_) => {
                const container = this.$refs.checkboxGroup?.$el
                container?.scrollTo({
                    top: container.scrollHeight,
                    behavior: 'smooth',
                })
            })
        },

        // 表格滚动到某一行
        tableTrScroll(item) {
            this.$nextTick((_) => {
                const tableElement = this.$refs.multipleSelection
                const theTableRowArr =
                    tableElement.bodyWrapper.querySelectorAll(
                        '.el-table__body tbody .el-table__row'
                    )
                const rowIndex = this.enhancedTableData.findIndex(
                    (i) => i[this.selectKey] === item[this.selectKey]
                )
                if (rowIndex === -1) return

                let top = [...theTableRowArr].reduce((topSum, i, index) => {
                    if (index < rowIndex) {
                        return topSum + theTableRowArr[index].offsetHeight
                    } else {
                        return topSum
                    }
                }, 0)
                tableElement.bodyWrapper?.scrollTo({top, behavior: 'smooth'})
            })
        },

        // 更新多选框配置项
        updateCheckboxOpt() {
            this.checkboxOpt = _.cloneDeep(this.allSelection)
            this.checkboxSelect = this.checkboxOpt.map((i) => i[this.selectKey])
            this.checkAll = !!this.checkboxSelect.length
            this.isIndeterminate = false
            this.checkboxScrollBottom()
        },

        // 表格全选改变
        tableHandleCheckAllChange(val) {
            this.enhancedTableData.forEach((i) => this.tableRowClick(i, val))
            this.isIndeterminate = false
        },

        // 多选框列表全选框改变
        handleCheckAllChange(val) {
            if (val) {
                this.checkboxSelect = this.checkboxOpt.map(
                    (i) => i[this.selectKey]
                )
                this.allSelection = this.checkboxOpt
            } else {
                this.checkboxSelect = this.checkboxOpt.flatMap((i) =>
                    i.disabled ? i[this.selectKey] : []
                )
                this.allSelection = this.allSelection.flatMap((i) =>
                    i.disabled && i.checked ? i : []
                )
                this.isIndeterminate = !!this.checkboxSelect.length
            }
            this.checkboxOpt.forEach((i) => {
                const findItem = this.enhancedTableData.find(
                    (_i) => _i[this.selectKey] === i[this.selectKey]
                )
                if (!findItem) return
                this.tableSelection(findItem, val)
            })
        },

        // 多选框列表多选框改变
        handleCheckedChange(status, item, value) {
            this.tableTrScroll(item)
            this.tableSelection(item, status)
            let checkedCount = value.length
            this.checkAll = checkedCount === this.checkboxOpt.length
            this.isIndeterminate =
                checkedCount > 0 && checkedCount < this.checkboxOpt.length
        },

        // 确认按钮点击
        confirm() {
            let selectedContent = this.allSelection.filter((i) => {
                return this.checkboxSelect.some(
                    (selectKey) => selectKey === i[this.selectKey]
                )
            })
            selectedContent = this.isSingleChoice
                ? selectedContent[0] || {}
                : selectedContent
            this.$emit('update:selectedContent', selectedContent)
            this.$emit('confirm', selectedContent)
            if (this.confirmCloseDialog) this.isShowDialog = false
        },
        handleAdd() {
            this.$emit('add')
        },
        handleClearRow(row, status) {
            // 表格行点击
            this.tableRowClick(row, status)
        },
    },
}
</script>

<style lang="scss" scoped>
@import '~@/assets/css/element-variables';

.super-table-selector-dialog {
  width: 100%;
  display: flex;
  column-gap: 16px;
  min-height: 50vh;

  .tree-module {
    height: 100%;
    border-radius: 8px;
    overflow: hidden;
    background-color: $--system-module-color1;
  }

  .table-module {
    width: 0;
    height: 100%;
    flex: 1;
    display: flex;
    flex-direction: column;
    row-gap: 16px;

    .search-content {
      border-radius: 8px;
      padding: 16px;
      background-color: $--system-module-color1;
      display: flex;
      gap: 12px;
    }

    .table-content {
      flex: 1;
      height: 0;
      border-radius: 8px;
      padding: 16px;
      display: flex;
      flex-direction: column;
      justify-content: space-between;
      background-color: $--system-module-color1;

      ::v-deep .el-table {
        .el-table__row {
          cursor: pointer;

          &.current-row {
            cursor: pointer;

            .el-table__cell {
              background-color: $--system-box-color3 !important;

              .cell {
                color: $--system-hover-active-text;
              }
            }
          }

          &.disabled-row {
            cursor: no-drop;

            .el-table__cell {
              background-color: $--system-disabled-bgColor !important;

              .cell {
                color: $--color-text-placeholder;
              }
            }
          }
        }
      }

      .table-content-bottom {
        display: flex;
        justify-content: space-between;
        align-items: flex-end;
      }
    }
  }

  .select-module {
    width: 300px;
    height: 100%;
    display: flex;
    flex-direction: column;
    background-color: $--system-module-color1;
    border-radius: 8px;
    overflow: hidden;

    .title-box {
      box-sizing: border-box;
      height: 52px;
      border-bottom: 1px solid $--system-border-color3;
      display: flex;
      justify-content: space-between;
      align-items: center;
      padding: 16px;

      .title-box-left {
        display: flex;
        align-items: center;
        column-gap: 9px;
        font-size: 16px;
        color: $--color-white;

        .el-checkbox {
          margin-top: 2px;
        }
      }

      .title-box-right {
        font-size: 15px;
        color: $--color-text-placeholder;
      }
    }

    .select-content {
      height: 0;
      flex: 1;
      box-sizing: border-box;
      padding: 16px;
      display: flex;
      flex-direction: column;
      row-gap: 16px;

      .select-content-top {
        padding-left: 11px;
      }

      .select-content-center {
        flex: 1;
        height: 0;
        display: flex;
        flex-direction: column;

        .el-checkbox-group {
          display: flex;
          overflow: auto;
          height: 100%;
          flex-direction: column;
          row-gap: 8px;
          padding-right: 8px;
          margin-right: -8px;

          /* 滚动条整体 */
          &::-webkit-scrollbar {
            width: 4px !important;
            background: transparent !important;
          }

          /* 滚动条滑块 */
          &::-webkit-scrollbar-thumb {
            border-radius: 5px;
            background: $--system-border-color2;
          }

          /* 滚动条轨道 */
          &::-webkit-scrollbar-track {
            color: transparent;
            background: transparent !important;
          }

          ::v-deep .el-checkbox {
            margin: 0;
            height: 32px;
            display: flex;
            box-sizing: border-box;

            .el-checkbox__label {
              flex: 1;
              overflow: hidden;

              span {
                display: block;
                font-size: 14px;
                overflow: hidden;
                white-space: nowrap;
                text-overflow: ellipsis;
              }
            }
          }
        }
      }

      .select-content-bottom {
        display: flex;
        justify-content: flex-end;
      }
    }
  }
}
</style>
