<template>
	<div class="header-actions">
		<div class="overflow-box">
			<el-button
				v-for="(item, index) in getActionList"
				:key="index"
				:type="item.type || 'primary'"
        		:plain="item.plain || false"
				v-bind="getHeaderActions(item)"
				@click="item.action"
				:disabled="item.disabled || false"
			>
				{{ item.text }}
			</el-button>
		</div>
	</div>
	<div class="table-list-container by-table">
		<!-- v-if="!hideHeader" -->
		<header v-if="false" class="header">
			<h2>{{ title }}</h2>
		</header>
		<div class="by-search">
			<div style="display: flex;">
				<div class="by-dropdown"  v-for="i in selectConfigCopy" :key="i.prop" style="margin-right:10px">
					<div class="by-dropdown-title">
						{{ i.label }}<i class="el-icon-caret-bottom el-icon--right"></i>
					</div>
					<ul class="by-dropdown-lists">
						<li @click="searchItemSelct('all',i)">全部</li>
						<li v-for="j in i.data" :key="j.value" @click="searchItemSelct(j,i)">{{ j.label }}</li>
					</ul>
				</div>
			</div>
			
			<div style="display: flex">
				<el-input
					placeholder="请输入关键字"
					suffix-icon="search"
					size="mini"
					v-model="keywrod"
					@keyup.enter="searchFn"
				>
				</el-input>
				<el-button
					type="primary"
					style="margin-left: 10px"
					size="default"
					@click="searchFn"
					>搜索</el-button
				>

				<div class="more-icon"><i class="el-icon-wind-power"></i></div>
				<div class="more-icon">
					<i class="el-icon-notebook-2"></i>
				</div>
			</div>
		</div>

		<component :is="containerTag">
			<div class="filter-form-container">
				<slot />
			</div>

			<el-table
				ref="hocElTable"
				v-loading="loading"
				:data="source"
				v-if="!hideTable"
				style="width: 100%"
				v-bind="$attrs"
				v-on="tableEvents"
				row-key="id"
				:tree-props="{ children: 'children', hasChildren: 'hasChildren' }"
			>
				<el-table-column
					v-for="(item, index) in config"
					:key="index"
					v-bind="getAttrsValue(item)"
					:type="item.type || ''"
				>
					
					
					<template #default="scope" v-if="!item.type">
						<slot :name="item.attrs.slot" :item="scope.row"  v-if="item.attrs.slot">
							插槽占位符
						</slot>
						<div v-else-if="isFunction(getValue(scope, item))">
							

							<component
								:is="
									renderTypeList[getMatchRenderFunction(item)]
										.target
								"
								:cell-list="getValue(scope, item)()"
								:row="scope.row"
								:parent="getParent"
								@click="
									($event) => {
										handleNativeClick(
											getAttrsValue(item),
											$event,
											item
										)
									}
								"
							/>
						</div>
						<div v-else>
							{{ getValue(scope, item) }}
						</div>
					</template>
				</el-table-column>
			</el-table>

			<el-row
				v-if="!hidePagination"
				class="table-pagination"
				justify="end"
				type="flex"
			>
				<el-pagination
					background
					layout="total, sizes, prev, pager, next, jumper"
					:current-page="getPagination.pageNum"
					:page-size="getPagination.pageSize"
					:total="getPagination.total"
					@size-change="handleSizeChange"
					@current-change="handlePageChange"
				/>
			</el-row>
		</component>
	</div>
</template>
  
  <script>
import { isFunction as isFn, isBoolean } from './type'
import ElementsMapping from './ElementsMapping'
import ComponentsMapping from './ComponentsMapping'
import { computed, defineComponent, getCurrentInstance, ref } from 'vue'
import expand from './expand'
export default defineComponent({
	name: 'Table',
	components: {
		ElementsMapping,
		ComponentsMapping,
	},
	props: {
		hideTable: {
			type: Boolean, 
			default: false,
		},
		//顶部搜索下拉配置
		selectConfig:{
			type: Array,
			default() {
				return []
			},
		},
		// 获取表格元数据时携带的参数
		filterParams: {
			type: Object,
			default() {
				return {}
			},
		},
		// 表格加载 loading
		loading: {
			type: Boolean,
			default: false,
		},
		// 表格名称
		title: {
			type: String,
			default: '',
		},
		// 表格元数据
		source: {
			type: Array,
			required: true,
			default() {
				return []
			},
		},
		searchConfig: {
			type: Object,
			default() {
				return {
					keyword: '',
				}
			},
		},
		// 指定外层容器的渲染组件
		containerTag: {
			type: String,
			default: 'div',
		},
		// 是否隐藏表头
		hideHeader: {
			type: Boolean,
			default: false,
		},
		// 是否隐藏分页
		hidePagination: {
			type: Boolean,
			default: false,
		},
		// 分页配置
		pagination: {
			type: Object,
			default() {
				return {}
			},
		},
		// 表格配置文件
		config: {
			type: Array,
			default() {
				return []
			},
		},
		// 表头右上方的按钮组
		actionList: {
			type: Array,
			default() {
				return [{ text: '', action: () => {} }]
			},
		},
		// element table 原生事件
		tableEvents: {
			type: Object,
			default() {
				return {}
			},
		}
	},
	setup(props) {
		
		const { proxy } = getCurrentInstance()
		const keywrod = ref('')
		const selectConfigCopy = computed(()=>{
			return props.selectConfig.map((item)=>{
				item.labelCopy = item.label
				return item
			})
			 
		})
		console.log(selectConfigCopy)
		const getAttrsValue = (item) => {
			const { attrs } = item
			const result = {
				...attrs,
			}
			delete result.prop
			return result
		}
		const renderTypeList = ref({
			render: {},
			renderHTML: {
				target: 'elements-mapping',
			},
			renderComponent: {
				target: 'components-mapping',
			},
		})
		const getParent = computed(() => {
			return proxy.$parent
		})
		const getPagination = computed(() => {
			const params = {
				pageNum: 1,
				pageSize: 10,
				total: 0,
			}
			return Object.assign({}, params, props.pagination)
		})
		const getActionList = computed(() => {
			return props.actionList
				.slice()
				.reverse()
				.filter((it) => it.text)
		})
		const getValue = (scope, configItem) => {
			const prop = configItem.attrs.prop
			const renderName = getMatchRenderFunction(configItem)
			const renderObj = renderTypeList.value[renderName]
			if (renderObj && isFunction(configItem[renderName])) {
				return renderObj.target
					? getRenderValue(scope, configItem, {
							name: renderName,
							type: 'bind',
					  })
					: getRenderValue(scope, configItem)
			}
			return scope.row[prop]
		}
		const getRenderValue = (
			scope,
			item,
			fn = { name: 'render', type: 'call' }
		) => {
			const prop = item.attrs.prop
			const propValue = prop && scope.row[prop]
			scope.row.$index = scope.$index
			const args = propValue !== undefined ? propValue : scope.row
			
			return item[fn.name][fn.type](getParent.value, args)
		}
		// 匹配 render 开头的函数
		const getMatchRenderFunction = (obj) => {
			return Object.keys(obj).find((key) => {
				const matchRender = key.match(/^render.*/)
				return matchRender && matchRender[0]
			})
		}
		const isFunction = (fn) => {
			return isFn(fn)
		}
		const searchFn = (val) => {
			console.log(keywrod)
			proxy.$emit(
				'getList',
				Object.assign(props.filterParams, { keyword: keywrod.value })
			)
		}
		const handlePageChange = (val) => {
			proxy.$emit(
				'getList',
				Object.assign(props.filterParams, { pageNum: val })
			)
		}
		const handleSizeChange = (val) => {
			proxy.$emit(
				'getList',
				Object.assign(props.filterParams, { pageSize: val })
			)
		}
		const getHeaderActions = (item) => {
			return {
				...item.attrs,
			}
		}
		const stopBubbles = (e) => {
			const event = e || window.event
			if (event && event.stopPropagation) {
				event.stopPropagation()
			} else {
				event.cancelBubble = true
			}
		}
		const handleNativeClick = ({ isBubble }, e,item) => {
			// 考虑到单元格内渲染了组件，并且组件自身可能含有点击事件，故添加了阻止冒泡机制
			// 若指定 isBubble 为 false，则当前单元格恢复冒泡机制
			if (isBoolean(isBubble) && !isBubble) return
			stopBubbles(e)
		}
		//下拉搜索相关
		
		const searchItemSelct = ((item,i) => {
			if(item == 'all') {
				i.label = '全部'
				proxy.$emit(
					'getList',
					Object.assign(props.filterParams, { [i.prop]: '' })
				)
				return
			}
			i.label = item.label
			console.log(item,i)
			proxy.$emit(
				'getList',
				Object.assign(props.filterParams, { [i.prop]: item.value })
			)
		})
		return {
			getParent,
			getPagination,
			renderTypeList,
			getActionList,
			getAttrsValue,
			getValue,
			getRenderValue,
			getMatchRenderFunction,
			isFunction,
			handlePageChange,
			handleSizeChange,
			getHeaderActions,
			stopBubbles,
			handleNativeClick,
			keywrod,
			searchFn,
			searchItemSelct,
			selectConfigCopy
		}
	},
})
</script>
  <style>
.table-list-container th {
	color: #333 !important;
}
.by-table td .el-button+.el-button{
	margin-left: 0!important;
}
.by-table td .el-button{
	background: none!important;
	margin: 0!important;
	padding:8px 6px!important;
}
</style>
  <style lang="scss" scoped>
.by-search {
	display: flex;
	justify-content: space-between;
	margin-bottom: 10px;
}
.by-dropdown {
	width: 106px;
	position: relative;
	text-align: left;
	height: 32px;
	z-index: 100;
	padding:0 10px;
	transition: all 0.5s ease;
	cursor: pointer;
	line-height: 32px;
	.by-dropdown-title {
		font-size: 14px;
		background-color: #fff;
		
	}
	ul {
		position: absolute;
		left: 0;
		right: 0;
		top: 32px;
		padding: 0;
		margin: 0;
		z-index: 100;
		display: none;
		li {
			list-style: none;
			font-size: 12px;
			height: 30px;
			padding: 0 10px;
		}
		li:hover {
			background-color: #eff6ff;
			color: #0084ff;
		}
	}
}

.by-dropdown::before {
	display: block;
	width: 1px;
	content: ' ';
	position: absolute;
	height: 14px;
	top: 8px;
	background-color: #ddd;
	right: 0;
	z-index: 101;

}

.by-dropdown:hover {
	background: #ffffff;
	
	border-radius: 2px 2px 2px 2px;
	opacity: 1;
	ul {
		background: #ffffff;
		box-shadow: 0px 2px 16px 1px rgba(0, 0, 0, 0.06);
		border-radius: 2px 2px 2px 2px;
		opacity: 1;
		display: block;
		text-align: left;
	}
}
.header-actions {
	flex: 1;
	overflow-x: auto;
	padding: 20px;
	background: #fff;
  margin-bottom: 20px;
	.overflow-box {
		
		:deep() .el-button:nth-child(1) {
			margin-left: 10px;
		}
	}
}
.table-list-container {
	background: #fff;
	padding: 13px 20px 20px;
	.table-pagination {
		padding-top: 20px;
	}
	.header {
		display: flex;
		padding-bottom: 20px;
	}
	.el-table {
		:deep() th {
			font-size: 14px;
		}
		:deep() td {
			font-size: 14px;
		}
	}
}
</style>