<template>
	<div class="st-search-condition flex lt grid" :class="{'none':!isShow , 'pt pr' : !allHide}">
		<div class="inline pl pb" :class="{'none' : !item.isShow}" v-for="item in optionsSync" :key="item.name">
			<div class="flex lt cv bd rds4" style="height: 34px;">
				<label class="w100 flex lt bold pl10 br">{{item.label}}</label>
				<div class="w240">

					<el-date-picker
							v-if="item.is == 'el-date-picker'"
							type="daterange"
							v-model="condition[item.name]"
							:type="item.type"
							:range-separator="item.rangeSeparator"
							:start-placeholder="item.startPlaceholder"
							:end-placeholder="item.endPlaceholder"
							:format="item.format"
							:value-format="item.valueFormat"
							:disabled-date="item.disabledDateFn"
							:default-hide="item.defaultHide"
							@change="_onChange(item,$event)"
							@calendar-change="_onCalendarChange(item,$event)"></el-date-picker>

					<st-data-cascader
							v-else-if="item.is == 'st-data-cascader'"
							v-model="condition[item.name]"
							@change="_onChange(item,$event)"
							:label-key="item.labelKey"
							:value-key="item.valueKey"
							:children-key="item.childrenKey"
							:api="item.api"
							:params="item.params"
							:checkStrictly="item.checkStrictly"></st-data-cascader>

					<st-data-select
							v-else-if="item.is == 'st-data-select'"
							v-model="condition[item.name]"
							@change="_onChange(item,$event)"
							:placeholder="item.placeholder"
							:label-key="item.labelKey"
							:value-key="item.valueKey"
							:api="item.api"
							:params="item.params"></st-data-select>

					<st-tree-select
							v-else-if="item.is == 'st-tree-select'"
							v-model="condition[item.name]"
							v-bind="item"
							@change="_onChange(item,$event)"
							:placeholder="item.placeholder"
							:label-key="item.labelKey"
							:value-key="item.valueKey"
							:children-key="item.childrenKey"
							:list="item.list"></st-tree-select>

                    <el-input
                        v-else-if="item.is == 'el-input'"
                        v-bind="item"
                        v-model.trim="condition[item.name]"
                        @change="_onChange(item,$event)"
                        :placeholder="item.placeholder"
                        size="default"
                        clearable></el-input>

					<component v-else
					           v-bind="item"
					           v-model="condition[item.name]"
					           @change="_onChange(item,$event)"
					           :is="item.is"
					           :placeholder="item.placeholder"
					           :list="item.list"
					           :options="item.list"
					           :props="item.props"
					           :label-key="item.labelKey"
					           :value-key="item.valueKey"
					           :api="item.api"
					           :params="item.params"
					           :type="item.type"
					           :maxlength="item.maxlength"
					           :filterable="true"
					           size="default"
					           clearable>

						<template v-if="item.is == 'el-select'">
							<el-option v-for="option in item.list" :key="option[item.valueKey]"
							           :label="option[item.labelKey]" :value="option[item.valueKey]"></el-option>
						</template>

						<template v-if="item.is == 'el-input' && !condition[item.name]" #suffix>
							<div class="bIcon-search op4"></div>
						</template>

					</component>
				</div>
			</div>

		</div>

		<slot :data="condition"></slot>

		<div v-if="!allHide" class="inline pl pb">
			<el-button type="default" @click="search">查询</el-button>
			<el-button type="default" @click="reset">重置</el-button>
			<slot name="btns"></slot>
		</div>

	</div>
</template>
<script>
	import tableStore from "@/modules/st-core/js_sdk/store";
	import {ElSelect, ElInput, ElCascader, ElDatePicker} from "element-plus" ;
	import {createAuth} from "@/modules/st-core/js_sdk/util/create-auth";
	import StDataCascader from "@/modules/st-core/components/st-data-cascader/st-data-cascader";
	import StTreeSelect from "@/modules/st-core/components/st-tree-select/st-tree-select";
	import StDataSelect from "@/modules/st-core/components/st-data-select/st-data-select";

	export default {
		name: "st-condition",
		emits: ["update:modelValue", "search", "reset", "change"],
		components: {
			StDataSelect,
			StTreeSelect,
			StDataCascader,
			ElSelect, ElInput, ElCascader, ElDatePicker,
		},
		props: {
			auth: {
				type: Boolean,
				default() {
					return situ.getConfig("auth", false);
				}
			},
			initOnCreated: { //自动从本地缓存、配置的默认值、value初始化筛选条件，将触发@search，开启后可在@search中自动请求数据
				type: Boolean,
				default: true
			},
			modelValue: {
				type: Object,
				default() {
					return {};
				}
			},
			options: {
				type: Array,
				default() {
					return [];
				},
				validator(value) {
					for (let item of value) {
						if (!item.label || !item.name) {
							console.error("columns内部元素的label、name属性为必填项: ", item);
							return false;
						}
					}
					return true;
				}
			}
		},
		data() {
			return {
				condition: {},
				startDate : null
			};
		},
		computed: {
			optionsSync() {
				return this.options.map(item => {
					let value = this.condition[item.name];
					let hasValue = this._hasValue(value);
					let disabledDate = item.disabledDate ;
					if (!disabledDate) {
						item.disabledDateFn = (time) => {
							return time.getTime() > Date.now();
						};
					} else {
						item.disabledDateFn = (time) => {
							return disabledDate(time , this.startDate);
						};
					}
					let defaultAuth = createAuth(item.auth, this.$route.path, item.name)
					let is = item.is || "el-input" ;
					return {
						...item,
						list: item.list || [],
						type: item.type || "daterange",
						rangeSeparator: item.rangeSeparator || "至",
						startPlaceholder: item.startPlaceholder || "开始日期",
						endPlaceholder: item.endPlaceholder || "结束日期",
						format: item.format || "YYYY-MM-DD",
						valueFormat: item.valueFormat || "YYYY-MM-DD",
						defaultAuth ,
						is ,
						placeholder: item.placeholder || ( is == "el-input" ? `请输入${item.label}` : "全部"),
						labelKey: item.labelKey || "label",
						valueKey: item.valueKey || "value",
						maxlength: this.$s.isNull(item.maxlength) ? 30 : item.maxlength,
						isShow: hasValue || !this.hideKeys.includes(item.name)
					};
				}).filter(item => ( this.auth === false && !item.auth ) ||  this.$s.hasAuth(item.defaultAuth) );
			},
			allHide() {
				return this.optionsSync.every(item => !item.isShow);
			},
			hideKeys() {
				return tableStore.state.hideSearchKeys;
			},
			isShow() {
				return tableStore.state.showSearch;
			},
			defaultConditions() {
				return this.optionsSync.reduce((data, cur) => {
					data[cur.name] = cur.defaultValue;
					return data;
				}, {});
			},
			refreshTime() {
				return tableStore.state.refreshTime
			}
		},

		watch: {
			modelValue: {
				handler() {
					this.condition = this.modelValue;
				},
				deep: true
			},
			refreshTime: {
				handler() {
					this.search();
				}
			}
		},

		mounted() {
			this.condition = this.modelValue;
            if(this.initOnCreated) this._initConditions();
		},

		methods: {

			search() {
				if(this.initOnCreated) this._setStorage();
				this.$emit("search", {...this.condition});
			},

			reset() {
				this.condition = {...this.defaultConditions};
				if(this.initOnCreated) this._removeStorage();
				this.$emit("update:modelValue", {...this.condition});
				this.$emit("reset", {...this.condition});
				this.$emit("search", {...this.condition});
			},

			_initConditions() {
				let localData = this.$s.getStorage("searchConditions", {})[this.$route.fullPath] || {};
				this.condition = this.$s.deepMerge({}, this.defaultConditions, this.modelValue, localData);
				this.$emit("update:modelValue", {...this.condition});
				this.$emit("search", {...this.condition});
			},

			_setStorage() {
				let localData = this.$s.getStorage("searchConditions", {});
				localData[this.$route.fullPath] = this.condition;
				this.$s.setStorage("searchConditions", localData);
			},

			_removeStorage() {
				let localData = this.$s.getStorage("searchConditions", {});
				delete localData[this.$route.fullPath];
				this.$s.setStorage("searchConditions", localData);
			},

			_onChange({name, is}, value = '') {
				value = this._dealValue(is, value);
				this.condition[name] = value;
				this.$emit("update:modelValue", {...this.condition});
				this.$emit("change", {name, value, condition: {...this.condition}});
			},

			_onCalendarChange(item, [startDate,endDate] = []){
				this.startDate = startDate ;
				if(endDate) this.startDate = null ;
			},

			_dealValue(is, value) {
				switch (is) {
					case "el-date-picker" :
						return this.$s.isNull(value) ? [] : value;
					case "st-tree-select" :
						return value.value;
					default :
						return value;
				}
			},

			_hasValue(value) {
				if (this.$s.isObject(value)) {
					return !this.$s.isEmptyObject();
				}
				if (this.$s.isArray(value)) {
					return value.length > 0;
				}
				return this.$s.notNull(value);
			}
		}
	}
</script>

<style lang="scss">
	.el-range-editor.el-input__inner {
		width: 240px;
	}

	.w240 {
		width: 240px;
	}

	.el-cascader, .el-select {
		width: 100%;
	}

	.st-search-condition {
		.el-input__inner, .el-select .el-input__inner, .el-select .el-input.is-focus .el-input__inner {
			border: none;
			border-radius: 0;
			box-shadow: none !important;

			&:focus {
				border-color: #dcdfe6;
			}
		}

		.bd {
			border-color: #dcdfe6;
			overflow: hidden;
			transition: 0.4s;

			&:focus, &:hover {
				border-color: $main;

				.el-input__inner {
					border-color: $main;
				}
			}
		}
	}

	.el-select-dropdown {
		max-width: 500px;
	}
</style>