<template>
	<el-container>
		<div v-if="(hasSearchSlot || hasExtendSearchSlot) && show" class="extend">
			<el-collapse-transition>
				<div class="extend-panel">
					<slot name="extend"></slot>
				</div>
			</el-collapse-transition>
		</div>
		<el-header v-if="hasSearchSlot || hasExtendSearchSlot || hasDoSlot">
			<div class="left-panel">
				<slot name="do"></slot>
			</div>
			<div class="right-panel">
				<slot name="search"></slot>
				<el-button v-if="hasExtendSearchSlot" type="primary" icon="el-icon-filter" @click="show = !show"
						   :plain="show"/>
			</div>
		</el-header>
		<el-main class="nopadding">
			<div :style="{'height':_height}" v-loading="loading">
				<el-scrollbar :view-style="{ 'overflow-x': 'hidden' }" class="pi-table-card"
							  :style="{'height':_table_height}">
					<el-empty v-if="total===0" :description="emptyText" :image-size="100"></el-empty>
					<el-row :gutter="20">
						<el-col :sm="24" :md="12" :lg="8" v-for="(row, index) in tableData" :key="index"
								style="position: relative">
							<div class="index">#{{ index + 1 }}</div>
							<div class="check">
								<el-checkbox v-model="checkedIds[index]"
											 @change="(val) => checkChange(val, row, index)"/>
							</div>
							<slot name="default" :row="row" :index="index"></slot>
						</el-col>
					</el-row>
				</el-scrollbar>
				<div class="pi-table-page" v-if="!hidePagination || !hideDo">
					<div class="pi-table-pagination">
						<el-pagination v-if="!hidePagination" background size="small" :layout="paginationLayout"
									   :total="total" :page-size="piPageSize" :page-sizes="pageSizes"
									   v-model:currentPage="currentPage" @current-change="paginationChange"
									   @update:page-size="pageSizeChange"></el-pagination>
					</div>
					<div class="pi-table-do" v-if="!hideDo">
						<el-button v-if="!hideRefresh" @click="refresh" icon="el-icon-refresh" circle
								   style="margin-left:15px"></el-button>
					</div>
				</div>
			</div>
		</el-main>
	</el-container>
</template>

<script setup>
import tools from "@/utils/tools"
import config from "@/config/tableCard"
import {ref, watch, computed, onMounted, onDeactivated, useSlots} from "vue"

defineOptions({
	name: 'piTableCard'
})

defineExpose({
	refresh,
	upData,
	reload
})

const emit = defineEmits(['dataChange', 'selectionChange'])
const slots = useSlots()

const hasSearchSlot = computed(() => !!slots.search)
const hasExtendSearchSlot = computed(() => !!slots.extend)
const hasDoSlot = computed(() => !!slots.do)

const props = defineProps({
	tableName: {type: String, default: ""},
	api: {
		type: Function, default: () => {
		}
	},
	workbench: {type: Boolean, default: false},
	params: {type: Object, default: () => ({})},
	data: {
		type: Object, default: () => {
		}
	},
	height: {type: [String, Number], default: "100%"},
	pageSize: {type: Number, default: config.pageSize},
	pageSizes: {type: Array, default: config.pageSizes},
	hidePagination: {type: Boolean, default: false},
	hideDo: {type: Boolean, default: false},
	hideRefresh: {type: Boolean, default: false},
	paginationLayout: {type: String, default: config.paginationLayout}
})

let piPageSize = ref(props.pageSize)
let isActive = ref(true)
let emptyText = ref("暂无数据")
let tableData = ref([])
let total = ref(0)
let currentPage = ref(1)
let prop = ref(null)
let order = ref(null)
let loading = ref(false)
let tableParams = ref(props.params)
let show = ref(false)
let checkedIds = ref({})

watch(() => props.data, () => {
	tableData.value = props.data;
	total.value = tableData.value.length;
})

watch(() => props.api, () => {
	tableParams.value = props.params;
	refresh();
})

const _height = computed(() => {
	return Number(props.height) ? Number(props.height) + 'px' : props.height
})

const _table_height = computed(() => {
	return props.hidePagination && props.hideDo ? "100%" : "calc(100% - 50px)"
})

onMounted(() => {
	//判断是否静态数据
	if (props.api) {
		getData()
	} else if (props.data) {
		tableData.value = props.data
		total.value = tableData.value.length
	}
})

onDeactivated(() => {
	isActive.value = false
})

async function getData() {
	loading.value = true;
	var reqData = {
		[config.request.page]: currentPage.value,
		[config.request.pageSize]: piPageSize.value,
		[config.request.prop]: prop.value,
		[config.request.order]: order.value
	}
	if (props.hidePagination) {
		delete reqData[config.request.page]
		delete reqData[config.request.pageSize]
	}
	Object.assign(reqData, tableParams.value)
	try {
		var res = await props.api(reqData)
	} catch (error) {
		loading.value = false;
		emptyText.value = error.statusText;
		return false;
	}
	try {
		var response = config.parseData(res);
	} catch (error) {
		loading.value = false;
		emptyText.value = "数据格式错误";
		return false;
	}
	if (response.code !== config.successCode) {
		loading.value = false;
		emptyText.value = response.msg;
	} else {
		emptyText.value = "暂无数据";
		if (props.hidePagination) {
			tableData.value = response.data || [];
		} else {
			tableData.value = response.rows || [];
		}
		if (props.rowKey) {
			tableData.value = tools.makeTreeData(tableData.value, 0, props.rowKey)
		}
		total.value = response.total || 0;
		loading.value = false;
	}
	emit('dataChange', res, tableData.value)
}

//分页点击
function paginationChange() {
	getData();
}

//条数变化
function pageSizeChange(size) {
	piPageSize.value = size
	getData()
}

//刷新数据
function refresh() {
	clearSelection()
	getData()
}

//更新数据 合并上一次params
function upData(params, page = 1) {
	currentPage.value = page;
	clearSelection();
	Object.assign(tableParams.value, params || {})
	getData()
}

//重载数据 替换params
function reload(params, page = 1) {
	currentPage.value = page;
	tableParams.value = params || {}
	clearSelection()
	getData()
}

function checkChange(e, item, index) {
	if (e) {
		checkedIds.value[index] = true
	} else {
		checkedIds.value[index] = false
	}
	// 获取选中项
	const indexes = Object.keys(checkedIds.value).filter(key => checkedIds.value[key]).map(Number)
	emit("selectionChange", tableData.value.filter((_, index) => indexes.includes(index)))
}

function clearSelection() {
	Object.keys(checkedIds.value).map(i => {
		checkedIds.value[i] = false
	})
	emit("selectionChange", [])
}

</script>

<style lang="scss" scoped>
.pi-table-card {
	overflow: hidden;
	padding: 13px 15px;

	.index {
		top: 24px;
		right: 55px;
		position: absolute;
		color: var(--el-text-color-primary);
	}

	.check {
		top: 18px;
		right: 30px;
		position: absolute;
	}
}

.pi-table-page {
	height: 50px;
	display: flex;
	align-items: center;
	justify-content: space-between;
	padding: 0 15px;
}

.pi-extend {
	background: var(--el-bg-color-overlay);
	border-color: var(--el-border-color-light);
	display: flex;
	flex-wrap: wrap;
	max-width: 100%;
}

::v-deep(.el-header) {
	height: auto !important;
}

.extend {
	background: var(--el-bg-color-overlay);
	border-color: var(--el-border-color-light);
	padding: 15px 15px 0 15px;
}

.extend-panel {
	display: inline-flex;
	flex-wrap: wrap;
	gap: 10px;
}
</style>
