<template>
    <view class="waterfalls-flow">
        <view
            v-for="(item, index) in data.column"
            :key="index"
            class="waterfalls-flow-column"
            :id="`waterfalls_flow_column_${index + 1}`"
            :msg="msg"
            :style="{ width: w, 'margin-left': index == 0 ? 0 : m }"
        >
            <view
                :class="['column-value', { 'column-value-show': item2.o }]"
                v-for="(item2, index2) in columnValue(index)"
                :key="index2"
                :style="[s1]"
                @click.stop="wapperClick(item2)"
            >
                <view class="inner" v-if="data.seat == 1">
                    <!-- #ifdef MP-WEIXIN -->
                    <!-- #ifdef VUE2 -->
                    <slot name="slot{{item2.index}}"></slot>
                    <!-- #endif -->
                    <!-- #ifdef VUE3 -->
                    <slot :name="`slot${item2.index}`"></slot>
                    <!-- #endif -->
                    <!-- #endif -->
                    <!-- #ifndef MP-WEIXIN -->
                    <slot v-bind="item2"></slot>
                    <!-- #endif -->
                </view>
                <image
                    :class="[
                        'img',
                        { 'img-hide': item2[hideImageKey] == true || item2[hideImageKey] == 1 },
                        { 'img-error': !item2[data.imageKey] },
                    ]"
                    :src="item2[data.imageKey]"
                    mode="widthFix"
                    @load="imgLoad(item2, index + 1)"
                    @error="imgError(item2, index + 1)"
                    @click.stop="imageClick(item2)"
                ></image>
                <view class="inner" v-if="data.seat == 2">
                    <!-- #ifdef MP-WEIXIN -->
                    <!-- #ifdef VUE2 -->
                    <slot name="slot{{item2.index}}"></slot>
                    <!-- #endif -->
                    <!-- #ifdef VUE3 -->
                    <slot :name="`slot${item2.index}`"></slot>
                    <!-- #endif -->
                    <!-- #endif -->
                    <!-- #ifndef MP-WEIXIN -->
                    <slot v-bind="item2"></slot>
                    <!-- #endif -->
                </view>
            </view>
        </view>
    </view>
</template>
<script>
export default {
    props: {
        value: Array,
        column: {
            // 列的数量
            type: [String, Number],
            default: 2,
        },
        maxColumn: {
            // 最大列数
            type: [String, Number],
            default: 5,
        },
        columnSpace: {
            // 列之间的间距 百分比
            type: [String, Number],
            default: 2,
        },
        imageKey: {
            // 图片key
            type: [String],
            default: 'image',
        },
        hideImageKey: {
            // 隐藏图片key
            type: [String],
            default: 'hide',
        },
        seat: {
            // 文本的位置，1图片之上 2图片之下
            type: [String, Number],
            default: 2,
        },
        listStyle: {
            // 单个展示项的样式：eg:{'background':'red'}
            type: Object,
        },
    },
    data() {
        return {
            data: {
                list: this.value ? this.value : [],
                column: this.column < 2 ? 2 : this.column,
                columnSpace: this.columnSpace <= 5 ? this.columnSpace : 5,
                imageKey: this.imageKey,
                seat: this.seat,
            },
            msg: 0,
            listInitStyle: {
                'border-radius': '12rpx',
                'margin-bottom': '20rpx',
                'background-color': '#fff',
            },
            adds: [], //预置数据
            isLoaded: true,
            curIndex: 0,
            isRefresh: true,
            flag: false,
            refreshDatas: [],
        };
    },
    computed: {
        // 计算列宽
        w() {
            const column_rate = `${100 / this.data.column - +this.data.columnSpace}%`;
            return column_rate;
        },
        // 计算margin
        m() {
            const column_margin = `${
                (100 - (100 / this.data.column - +this.data.columnSpace).toFixed(5) * this.data.column) /
                (this.data.column - 1)
            }%`;
            return column_margin;
        },
        // list样式
        s1() {
            return { ...this.listInitStyle, ...this.listStyle };
        },
    },
    created() {
        // 初始化
        this.refresh();
    },
    methods: {
        // 预加载图片
        loadImages(idx = 0) {
            let count = 0;
            const newList = this.data.list.filter((item, index) => index >= idx);
            for (let i = 0; i < newList.length; i++) {
                // #ifndef APP-PLUS
                uni.getImageInfo({
                    src: `${newList[i][this.imageKey]}.jpg`,
                    complete: (res) => {
                        count++;
                        if (count == newList.length) this.initValue(idx);
                    },
                });
                // #endif
                // #ifdef APP-PLUS
                plus.io.getImageInfo({
                    src: `${newList[i][this.imageKey]}.jpg`,
                    complete: (res) => {
                        count++;
                        if (count == newList.length) this.initValue(idx);
                    },
                });
                // #endif
            }
        },
        // 刷新
        refresh() {
            if (!this.isLoaded) {
                this.refreshDatas = this.value;
                return false;
            }
            setTimeout(() => {
                this.refreshDatas = [];
                this.isRefresh = true;
                this.adds = [];
                this.data.list = this.value ? this.value : [];
                this.data.column = this.column < 2 ? 2 : this.column >= this.maxColumn ? this.maxColumn : this.column;
                this.data.columnSpace = this.columnSpace <= 5 ? this.columnSpace : 5;
                this.data.imageKey = this.imageKey;
                this.data.seat = this.seat;
                this.curIndex = 0;
                // 每列的数据初始化
                for (let i = 1; i <= this.data.column; i++) {
                    this.data[`column_${i}_values`] = [];
                    this.msg++;
                }
                this.$nextTick(() => {
                    this.initValue(this.curIndex, 'refresh==>');
                });
            }, 1);
        },
        columnValue(index) {
            return this.data[`column_${index + 1}_values`];
        },
        change(newValue) {
            for (let i = 0; i < this.data.list.length; i++) {
                const cv = this.data[`column_${this.data.list[i].column}_values`];
                for (let j = 0; j < cv.length; j++) {
                    if (newValue[i] && i === cv[j].index) {
                        this.data[`column_${this.data.list[i].column}_values`][j] = Object.assign(cv[j], newValue[i]);
                        this.msg++;
                        break;
                    }
                }
            }
        },
        getMin(a, s) {
            let m = a[0][s];
            let mo = a[0];
            for (var i = a.length - 1; i >= 0; i--) {
                if (a[i][s] < m) {
                    m = a[i][s];
                }
            }
            mo = a.filter((i) => i[s] == m);
            return mo[0];
        },
        // 计算每列的高度
        getMinColumnHeight() {
            return new Promise((resolve) => {
                const heightArr = [];
                for (let i = 1; i <= this.data.column; i++) {
                    const query = uni.createSelectorQuery().in(this);
                    query
                        .select(`#waterfalls_flow_column_${i}`)
                        .boundingClientRect((data) => {
                            // 添加 null 检查，防止 data 为 null 时访问 height 属性
                            if (data && data.height !== undefined) {
                                heightArr.push({ column: i, height: data.height });
                            } else {
                                // 如果元素不存在或高度未定义，使用默认高度 0
                                heightArr.push({ column: i, height: 0 });
                            }
                        })
                        .exec(() => {
                            if (this.data.column <= heightArr.length) {
                                resolve(this.getMin(heightArr, 'height'));
                            }
                        });
                }
            });
        },
        async initValue(i, from) {
            this.isLoaded = false;
            if (i >= this.data.list.length || this.refreshDatas.length) {
                this.msg++;
                this.loaded();
                return false;
            }
            const minHeightRes = await this.getMinColumnHeight();
            const c = this.data[`column_${minHeightRes.column}_values`];
            this.data.list[i].column = minHeightRes.column;
            c.push({ ...this.data.list[i], cIndex: c.length, index: i, o: 0 });
            this.msg++;
        },
        // 图片加载完成
        imgLoad(item, c) {
            const i = item.index;
            item.o = 1;
            this.$set(this.data[`column_${c}_values`], item.cIndex, JSON.parse(JSON.stringify(item)));
            this.initValue(i + 1);
        },
        // 图片加载失败
        imgError(item, c) {
            const i = item.index;
            item.o = 1;
            item[this.data.imageKey] = null;
            this.$set(this.data[`column_${c}_values`], item.cIndex, JSON.parse(JSON.stringify(item)));
            this.initValue(i + 1);
        },
        // 渲染结束
        loaded() {
            if (this.refreshDatas.length) {
                this.isLoaded = true;
                this.refresh();
                return false;
            }
            this.curIndex = this.data.list.length;
            if (this.adds.length) {
                this.data.list = this.adds[0];
                this.adds.splice(0, 1);
                this.initValue(this.curIndex);
            } else {
                if (this.data.list.length) this.$emit('loaded');
                this.isLoaded = true;
                this.isRefresh = false;
            }
        },
        // 单项点击事件
        wapperClick(item) {
            this.$emit('wapperClick', item);
        },
        // 图片点击事件
        imageClick(item) {
            this.$emit('imageClick', item);
        },
    },
    watch: {
        value: {
            deep: true,
            handler(newValue, oldValue) {
                setTimeout(() => {
                    this.$nextTick(() => {
                        if (this.isRefresh) return false;
                        if (this.isLoaded) {
                            // if (newValue.length <= this.curIndex) return this.refresh();
                            if (newValue.length <= this.curIndex) return this.change(newValue);
                            this.data.list = newValue;
                            this.$nextTick(() => {
                                this.initValue(this.curIndex, 'watch==>');
                            });
                        } else {
                            this.adds.push(newValue);
                        }
                    });
                }, 10);
            },
        },
        column(newValue) {
            this.refresh();
        },
    },
};
</script>
<style lang="scss" scoped>
.waterfalls-flow {
    overflow: hidden;

    &-column {
        float: left;
    }
}

.column-value {
    width: 100%;
    font-size: 0;
    overflow: hidden;
    transition: opacity 0.4s;
    opacity: 0;

    &-show {
        opacity: 1;
    }

    .inner {
        font-size: 30rpx;
    }

    .img {
        width: 100%;

        &-hide {
            display: none;
        }

        &-error {
            background: #f2f2f2
                url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAC4AAAAiAQMAAAAatXkPAAAABlBMVEUAAADMzMzIT8AyAAAAAXRSTlMAQObYZgAAAIZJREFUCNdlzjEKwkAUBNAfEGyCuYBkLyLuxRYW2SKlV1JSeA2tUiZg4YrLjv9PGsHqNTPMSAQuyAJgRDHSyvBPwtZoSJXakeJI9iuRLGDygdl6V0yKDtyMAeMPZySj8yfD+UapvRPj2JOwkyAooSV5IwdDjPdCPspe8LyTl9IKJvDETKKRv6vnlUasgg0fAAAAAElFTkSuQmCC)
                no-repeat center center;
        }
    }
}
</style>
