<!--本文件由FirstUI授权予新疆天衡创新研究院有限公司（手机号： 186   14   07 2 5 49，身份证尾号：5A07X5）专用，请尊重知识产权，勿私下传播，违者追究法律责任。-->
<template>
	<view class="fui-cascader__wrap">
		<view class="fui-cascader__header-wrap">
			<scroll-view :scroll-x="true" scroll-with-animation :show-scrollbar="false" :scroll-into-view="scrollViewId"
				:style="{ background: headBackground }" class="fui-cascader__scroll">
				<view class="fui-cascader__header" :style="{ height: headHeight+'rpx'}">
					<view class="fui-cascader__header-item" :id="`fui_cr_${idx}`" v-for="(item, idx) in selectedArr"
						:key="idx" @tap.stop="swichTabs(idx)">
						<text class="fui-cascader__header-text"
							:class="{'fui-cascader__hi-width':item.text.length>6,'fui-cascader__color':idx === current && !getActiveColor}"
							:style="{ color: idx === current ? getActiveColor : color, fontSize: size + 'rpx',fontWeight:idx === current?'bold':'normal' }">{{ item.text }}</text>
						<view class="fui-cascader__header-line" :class="{'fui-cascader__bg':!getActiveColor}"
							:style="{ background: getActiveColor }" v-if="idx === current && showLine"></view>
					</view>
				</view>
			</scroll-view>
			<view class="fui-cascader__border" :style="{background:borderColor}" v-if="showBorder"></view>
		</view>
		<!-- #ifdef MP-TOUTIAO -->
		<view :style="{ height: height+'rpx', background: background}">
			<swiper class="fui-cascader__list" :current="defCurrent" :circular="false" :duration="300"
				@change="switchTab" :style="{ height: height+'rpx', background: background}" v-if="isShow">
				<!-- #endif -->
				<!-- #ifndef MP-TOUTIAO -->
				<swiper class="fui-cascader__list" :current="defCurrent" :circular="false" :duration="300"
					@change="switchTab" :style="{ height: height+'rpx', background: background}">
					<!-- #endif -->
					<swiper-item v-for="(item, index) in selectedArr" :key="index">
						<scroll-view :show-scrollbar="false" scroll-y :scroll-into-view="item.scrollViewId"
							class="fui-cascader__item-scroll" :style="{ height: height+'rpx', background: background }">
							<view class="fui-cascader__seat"></view>
							<view class="fui-cascader__cell" :id="`fui_c_${subi}`" v-for="(sub, subi) in item.data"
								:key="subi" @tap.stop="change(index, subi, sub)">
								<view class="fui-cascader__checkmark"
									:class="{'fui-cascader__icon-border':!getActiveColor}"
									:style="{borderBottomColor:checkMarkColor || getActiveColor,borderRightColor:checkMarkColor || getActiveColor}"
									v-if="item.index === subi"></view>
								<image :src="sub.src" v-if="sub.src" class="fui-cascader__img"
									:style="{ width: imgWidth+'rpx', height: imgHeight+'rpx', borderRadius: radius+'rpx' }">
								</image>
								<text class="fui-cascader__text"
									:style="{ color: item.index === subi ? textActiveColor : textColor, fontSize: textSize + 'rpx',fontWeight:item.index === subi?'bold':'normal' }">{{ sub.text }}</text>
							</view>
							<view class="fui-cascader__seat"></view>
						</scroll-view>
					</swiper-item>
				</swiper>
				<!-- #ifdef MP-TOUTIAO -->
		</view>
		<!-- #endif -->
	</view>
</template>

<script>
	export default {
		name: "fui-cascader",
		emits: ['change', 'complete'],
		props: {
			options: {
				type: Array,
				default () {
					return []
				}
			},
			value: {
				type: Array,
				default () {
					return []
				}
			},
			defaultKey: {
				type: String,
				default: 'value'
			},
			stepLoading: {
				type: Boolean,
				default: false
			},
			showBorder: {
				type: Boolean,
				default: true
			},
			borderColor: {
				type: String,
				default: '#eee'
			},
			headHeight: {
				type: [Number, String],
				default: 88
			},
			headBackground: {
				type: String,
				default: '#FFFFFF'
			},
			text: {
				type: String,
				default: '请选择'
			},
			size: {
				type: [Number, String],
				default: 28
			},
			color: {
				type: String,
				default: '#181818'
			},
			//选中颜色
			activeColor: {
				type: String,
				default: ''
			},
			showLine: {
				type: Boolean,
				default: true
			},
			height: {
				type: [Number, String],
				default: 600
			},
			//item  swiper 内容部分背景颜色
			background: {
				type: String,
				default: '#FFFFFF'
			},
			checkMarkColor: {
				type: String,
				default: ''
			},
			imgWidth: {
				type: [Number, String],
				default: 48
			},
			imgHeight: {
				type: [Number, String],
				default: 48
			},
			radius: {
				type: [Number, String],
				default: 0
			},
			textSize: {
				type: [Number, String],
				default: 26
			},
			textColor: {
				type: String,
				default: '#181818'
			},
			textActiveColor: {
				type: String,
				default: '#181818'
			}
		},
		computed: {
			getActiveColor() {
				let color = this.activeColor;
				// #ifdef APP-NVUE
				if (!color || color === true) {
					const app = uni && uni.$fui && uni.$fui.color;
					color = (app && app.primary) || '#465CFF';
				}
				// #endif
				return color;
			}
		},
		data() {
			return {
				current: 0,
				defCurrent: 0,
				selectedArr: [],
				scrollViewId: 'fui_cr__0',
				isShow: true
			};
		},
		watch: {
			options(vals) {
				this.setDefaultOptions(this.value);
			},
			value(vals) {
				this.setDefaultOptions(vals)
			}
		},
		created() {
			this.setDefaultOptions(this.value)
		},
		methods: {
			//重置选择，暴露给用户使用
			reset() {
				this.initData(this.options, -1);
			},
			//设置请求返回数据，暴露给用户使用（分级加载数据）
			setRequestData(data, layer) {
				this.subLevelData(data, layer)
			},
			//无子级数据，选择结束
			end(layer) {
				this.subLevelData([], layer)
			},
			subLevelData(data, layer) {
				if (!data || data.length === 0) {
					if (layer == -1) return;
					let arr = this.selectedArr;
					if (layer < arr.length - 1) {
						let newArr = arr.slice(0, layer + 1);
						this.selectedArr = newArr;
					}
					// #ifdef MP-TOUTIAO
					this.isShow = false
					this.$nextTick(() => {
						setTimeout(() => {
							this.isShow = true
						}, 10)
					})
					// #endif
					let result = JSON.parse(JSON.stringify(this.selectedArr));
					let lastItem = result[result.length - 1] || {};
					let text = [];
					let value = [];
					let src = [];
					result.map(item => {
						text.push(item.text);
						value.push(item.value)
						src.push(item.src)
						delete item['data'];
						delete item['index'];
						delete item['scrollViewId'];
						return item;
					});
					this.$emit('complete', {
						result: result,
						value: value,
						text: text,
						src: src
					});
					setTimeout(() => {
						this.scrollViewId = `fui_cr_${layer}`;
					}, 50)
				} else {
					let item = [{
						text: this.text,
						value: '',
						src: '',
						index: -1,
						scrollViewId: 'fui_c__0',
						data
					}];
					if (layer == -1) {
						this.selectedArr = item;
					} else {
						let retainArr = this.selectedArr.slice(0, layer + 1) || [];
						this.selectedArr = retainArr.concat(item);
					}
					let current = this.selectedArr.length - 1;
					if (current >= this.current) {
						this.defCurrent = this.current
					}
					this.$nextTick(() => {
						setTimeout(() => {
							this.defCurrent = current;
							this.current = current;
							this.scrollViewId = `fui_cr_${this.current > 1?this.current - 1:0}`;
						}, 50)
					});
				}
			},
			getDefaultIndex(arr, val) {
				if (!arr || arr.length === 0 || val === undefined) return -1;
				let key = this.defaultKey || 'value';
				let index = -1;
				for (let i = 0, len = arr.length; i < len; i++) {
					if (arr[i][key] == val) {
						index = i;
						break;
					}
				}
				return index;
			},
			removeChildren(data) {
				let list = data.map(item => {
					delete item['children'];
					return item;
				});
				return list;
			},
			getItemList(layer, index, selectedArr) {
				let list = [];
				let arr = JSON.parse(JSON.stringify(this.options));
				selectedArr = selectedArr || this.selectedArr
				if (layer == -1) {
					list = this.removeChildren(arr);
				} else {
					let subi = selectedArr[0].index;
					subi = subi === undefined || subi == -1 ? index : subi;
					if (arr[subi] && arr[subi].children) {
						list = arr[subi].children
					}
					if (layer > 0) {
						for (let i = 1; i < layer + 1; i++) {
							let val = layer === i ? index : selectedArr[i].index;
							list = val === -1 ? [] : (list[val].children || []);
							if (list.length === 0) break;
						}
					}
					list = this.removeChildren(list);
				}
				return list;
			},
			setDefaultOptions(vals) {
				let options = this.options || []
				if (!options || options.length === 0) return;
				vals = vals || [];
				let selectedArr = []
				if (vals.length > 0) {
					//分级加载
					if (this.stepLoading) {
						options.forEach((item, index) => {
							let subi = this.getDefaultIndex(item, vals[index])
							let obj = item[subi] || {}
							selectedArr.push({
								text: obj.text || this.text,
								value: obj.value || '',
								src: obj.src || '',
								index: subi,
								scrollViewId: `fui_c_${subi}`,
								data: item
							})
						})
					} else {
						let subi = -1
						for (let j = 0, len = vals.length; j < len; j++) {
							let item = vals[j]
							let list = []
							let obj = {}
							if (j === 0) {
								list = this.getItemList(-1)
							} else {
								list = this.getItemList(j - 1, subi, selectedArr)
							}
							subi = this.getDefaultIndex(list, item)
							if (subi !== -1) {
								obj = list[subi]
							}
							selectedArr.push({
								text: obj.text || this.text,
								value: obj.value || '',
								src: obj.src || '',
								index: subi,
								scrollViewId: `fui_c_${subi}`,
								data: list
							})
							if (subi === -1) break;
						}
					}
					this.selectedArr = selectedArr;
					this.defCurrent = this.current;
					let current = selectedArr.length - 1;
					this.$nextTick(() => {
						setTimeout(() => {
							this.defCurrent = current;
							this.current = current;
							this.checkTabs();
						}, 30)
					});
				} else {
					this.initData(options, -1);
				}
			},
			initData(data, layer) {
				if (!data || data.length === 0) return;
				if (this.stepLoading) {
					if (Array.isArray(data[0])) {
						data = data[0]
					}
					this.subLevelData(data, layer);
				} else {
					this.subLevelData(this.getItemList(layer, -1), layer);
				}
			},
			swichTabs(current) {
				if (this.current != current) {
					this.defCurrent = this.current;
					setTimeout(() => {
						this.defCurrent = current;
						this.current = current;
					}, 30)
				}
			},
			checkTabs() {
				let current = this.current;
				let item = this.selectedArr[current] || {};
				item.scrollViewId = 'fui_c__0';
				this.$nextTick(() => {
					setTimeout(() => {
						let index = Number(item.index)
						let val = index < 2 ? 0 : index - 2;
						item.scrollViewId = `fui_c_${val}`;
					}, 30);
				});
				this.scrollViewId = `fui_cr_${current > 1?current - 1:0}`;
			},
			switchTab(e) {
				this.current = e.detail.current;
				this.checkTabs();
			},
			change(index, subi, sub) {
				let item = this.selectedArr[index];
				if (item.index == subi) return;
				item.index = subi;
				item.text = sub.text;
				item.value = sub.value;
				item.src = sub.src || '';
				this.$emit('change', {
					layer: index,
					index: subi,
					...sub
				});
				if (!this.stepLoading) {
					let data = this.getItemList(index, subi);
					this.subLevelData(data, index);
				}
			}
		}
	}
</script>

<style scoped>
	.fui-cascader__wrap {
		/* #ifndef APP-NVUE */
		width: 100%;
		/* #endif */
	}

	.fui-cascader__scroll {
		/* #ifndef APP-NVUE */
		width: 100%;
		/* #endif */
		/* #ifdef APP-NVUE */
		flex: 1;
		flex-direction: row;
		/* #endif */
	}

	.fui-cascader__header-wrap {
		/* #ifndef APP-NVUE */
		width: 100%;
		/* #endif */
		position: relative;
	}

	.fui-cascader__header {
		/* #ifndef APP-NVUE */
		width: 100%;
		display: flex;
		/* #endif */
		flex-direction: row;
		align-items: center;
		justify-content: flex-start;
	}

	.fui-cascader__header-item {
		padding: 24rpx 32rpx;
		/* #ifndef APP-NVUE */
		flex-shrink: 0;
		overflow: hidden;
		/* #endif */
		/* #ifdef H5 */
		cursor: pointer;
		/* #endif */
		position: relative;
	}

	.fui-cascader__header-text {
		/* #ifndef APP-NVUE */
		display: block;
		white-space: nowrap;
		/* #endif */
		overflow: hidden;
		text-overflow: ellipsis;
		/* #ifdef APP-NVUE */
		lines: 1;
		/* #endif */
		text-align: center;
	}

	.fui-cascader__hi-width {
		width: 240rpx;
	}

	.fui-cascader__header-line {
		height: 6rpx;
		border-radius: 4rpx;
		position: absolute;
		bottom: 0;
		left: 32rpx;
		right: 32rpx;
		z-index: 2;
	}

	.fui-cascader__border {
		position: absolute;
		left: 0;
		right: 0;
		bottom: 0;
		/* #ifdef APP-NVUE */
		height: 0.5px;
		z-index: -1;
		/* #endif */
		/* #ifndef APP-NVUE */
		height: 1px;
		-webkit-transform: scaleY(0.5);
		transform: scaleY(0.5);
		transform-origin: 0 100%;
		z-index: 1;
		/* #endif */
	}

	.fui-cascader__list {
		/* #ifndef APP-NVUE */
		width: 100%;
		/* #endif */
	}

	.fui-cascader__seat {
		/* #ifndef APP-NVUE */
		width: 100%;
		/* #endif */
		height: 24rpx;
	}

	.fui-cascader__cell {
		/* #ifndef APP-NVUE */
		width: 100%;
		display: flex;
		box-sizing: border-box;
		/* #endif */
		flex-direction: row;
		align-items: center;
		padding: 20rpx 32rpx;
		/* #ifdef H5 */
		cursor: pointer;
		/* #endif */
	}

	.fui-cascader__checkmark {
		width: 24rpx;
		height: 48rpx;
		border-bottom-style: solid;
		border-bottom-width: 3px;
		border-bottom-color: #FFFFFF;
		border-right-style: solid;
		border-right-width: 3px;
		border-right-color: #FFFFFF;
		/* #ifndef APP-NVUE */
		flex-shrink: 0;
		box-sizing: border-box;
		transform: rotate(45deg) scale(0.5) translateZ(0);
		/* #endif */
		/* #ifdef APP-NVUE */
		transform: rotate(45deg) scale(0.5);
		/* #endif */
		transform-origin: 54% 48%;
		margin-right: 16rpx;
	}

	.fui-cascader__img {
		margin-right: 16rpx;
		/* #ifndef APP-NVUE */
		flex-shrink: 0;
		/* #endif */
	}

	/* #ifndef APP-NVUE */
	.fui-cascader__color {
		color: var(--fui-color-primary, #465CFF) !important;
	}

	.fui-cascader__bg {
		background: var(--fui-color-primary, #465CFF) !important;
	}

	.fui-cascader__icon-border {
		border-bottom-color: var(--fui-color-primary, #465CFF) !important;
		border-right-color: var(--fui-color-primary, #465CFF) !important;
	}

	/* #endif */
</style>