2023年5月

使用Java8的Stream操作,同样可以非常方便地完成三个List的left join操作。假设有三个List、List和List<C>,我们想要通过A、B和C中的某些字段进行left join操作,可以按照以下步骤进行:

  1. 将B和C中的数据转换为Map,以相同字段值作为Key。
Map<KeyType, B> bMap = bList.stream().collect(Collectors.toMap(B::getFieldValue, b -> b));
Map<KeyType, C> cMap = cList.stream().collect(Collectors.toMap(C::getFieldValue, c -> c));
  1. 对于每一个A中的数据项,从bMap和cMap中查找是否存在相同字段值的数据项,并将其合并到A中。
aList.forEach(a -> {
    B b = bMap.get(a.getFieldValue());
    if (b != null) {
        a.setOtherFieldFromB(b.getOtherFieldValue());
    }
    C c = cMap.get(a.getFieldValue());
    if (c != null) {
        a.setOtherFieldFromC(c.getOtherFieldValue());
    }
});

需要注意的是,在使用Stream操作时,需要确保三个List中的元素类型匹配,并且要注意空指针异常等问题。使用Stream操作可以大大简化代码,并提高效率和可读性。

使用Java8的Stream操作,可以更加简洁高效地完成left join的操作。假设有两个List和List,我们想要通过A和B中的某个字段进行left join操作,可以按照以下步骤进行:

  1. 将B中的数据转换为Map,以相同字段值作为Key。
Map<KeyType, B> bMap = bList.stream().collect(Collectors.toMap(B::getFieldValue, b -> b));
  1. 对于每一个A中的数据项,从bMap中查找是否存在相同字段值的数据项,并将其合并到A中。
aList.forEach(a -> {
    B b = bMap.get(a.getFieldValue());
    if (b != null) {
        a.setOtherField(b.getOtherFieldValue());
    }
});

需要注意的是,在使用Stream操作时,需要确保两个List中的元素类型匹配,并且要注意空指针异常等问题。使用Stream操作可以大大简化代码,并提高效率和可读性。

uni-app——规格选择判断库存(类似电商商品加购)

<template>
    <view class="detail_page" v-cloak :class="isShowPopup? 'popup-show': ''">
        <navBar :title="topInfo.title" :url="topInfo.url" :icon_title="topInfo.icon_title" :type="topInfo.type">
        </navBar>
        <view class="pages" v-cloak>
            <view class="info scroll_item" id="scroll0">
                <view class="banner_top">
                    <swiper :swiperConfig="swiperConfig"></swiper>
                </view>
                <view class="page_info page_item">
                    <view class="price">
                        <text class="large">{{listData.price}}</text>
                        元起
                    </view>
                    <view class="title">{{listData.name}}</view>
                    <view class="sub_title">强效清洗,全面爱家,重新焕发地毯新生</view>
                </view>
                <view class="form_box page_item">
                    <uni-forms ref="signUpform" :value="signUpformData" :rules="rules">
                        <uni-forms-item label="小区" name="housing_id" style="display: none;"></uni-forms-item>
                        <uni-forms-item label="地址" name="user_address_id" @tap="goAddress">
                            <text class="picker_lable">{{address}}</text>
                        </uni-forms-item>
                        <uni-forms-item label="规格" name="flag" @tap="chorceSpecs">
                            <text class="picker_lable">{{specs}}</text>
                        </uni-forms-item>
                        <uni-forms-item label="时间" name="start_time" @tap="openDatetimePicker">
                            <text class="picker_lable">{{signUpformData.start_time}}</text>
                        </uni-forms-item>
                    </uni-forms>
                </view>
            
            
            </view>
            
            <view class="details scroll_item " id="scroll1" style="padding-bottom:80px;">
                <view style="color: #a29696;margin-bottom: 20rpx; text-align: center;">——详情——</view>
                <view class="page_detail page_item" v-html="detail_content" style="margin-bottom:70px;">
                    {{detail_content}}
                </view>
            </view>    
            
            <view class="footer">
                <view>
                    <image class="service" mode="aspectFit" @tap="callPhone" src="../../static/images/service.png">
                    </image>
                    <view class="byButton" form-type="submit" @tap="handleBuy">立即购买</view>
                </view>
            </view>
        </view>

        <!-- 页面滚动到详情时再显示锚点 -->
        <view class="fixedtop" v-show="scrollDistance > 100">
            <view class="fixedtop_box">
                <view v-for="(item,index) in fixedList" :key="index" :class="{'active':currentIndex == index}"
                    @tap="changeactive(index)">{{item.name}}
                </view>
            </view>
        </view>
        <!-- 规格 -->
        <uni-popup ref="popup" type="bottom" :mask-click="false">
            <view class="specs_box spec-shade">
                <view class="specs_box_box">
                    <view class="title">
                        <text></text>
                        <text class="title">请选择服务规格</text>
                        <!--   <text @click="closeProp"
                               class="iconfont icon-close"></text> -->
                        <text></text>
                    </view>
                    <view class="spec-cont">
                        <view class="goods-choose-show flex-star">
                            <view class="goods-choose-show-right" v-if="currentItem">
                                <p>¥{{currentItem.price || 0}}</p>
                                <view>库存{{currentItem.all_count || 0}}件</view>
                                <!-- <view>{{specShowString}}</view> -->
                            </view>
                        </view>
                        <view class="spec-linebox" style="max-height: 550rpx;overflow-y: scroll;">
                            <view class="spec-item" v-for="(skuItem,skuIndex) in skuInfo">
                                <p>{{skuItem.title}}</p>
                                <view class="item-cont flex-star">
                                    <span v-for="(item,index) in skuItem.option"
                                        :class="[item.isShow ? '' : 'noProduct',subIndex[skuIndex] == item.id ? 'act' : '']"
                                        @click="item.isShow ? specificationBtn(item.info,skuIndex,item.id) : disabled">{{item.info}}</span>
                                </view>
                            </view>
                        </view>
                    </view>
                    <button class="confirm" @click="confirmSpec">确定</button>
                </view>
            </view>
        </uni-popup>

        <!-- 时间 -->
        <SimpleDateTimePicker ref="myPicker" @submit="handleSubmit" :start-year="year" :end-year="year+20" />
    </view>

</template>

<script>
    import navBar from "@/components/navBar/navBar.vue"
    import swiper from "@/components/swiper/swiper.vue"
    import forms from "@/components/uni-forms/uni-forms.vue"
    import formItems from "@/components/uni-forms-item/uni-forms-item.vue"
    import SimpleDateTimePicker
    from "uni_modules/buuug7-simple-datetime-picker/components/buuug7-simple-datetime-picker/buuug7-simple-datetime-picker.vue";
    import popup from "@/components/uni-popup/uni-popup.vue"
    import {
        mapMutations
    } from 'vuex';

    export default {
        components: {
            navBar,
            swiper,
            formItems,
            forms,
            SimpleDateTimePicker,
            popup
        },

        data() {
            return {
                isShowPopup: false,
                payParams: 0,
                goods_id: 0,
                isInit: 0, // 默认只显示第一组规格
                allCount_id: 0, // 库存为0的id
                stockIndex: 0, //库存为0的id组
                stock_flag: [],
                getSpecs: [],
                topInfo: {
                    url: "../../pages/index/index",
                    title: "预约详情",
                    icon_title: "返回",
                    type: 'tab'
                },
                token: "",
                year: "",
                listData: {},
                swiperConfig: {
                    indicatorDots: true,
                    vertical: false,
                    autoplay: true,
                    interval: 2000,
                    duration: 600,
                    bannerList: [],
                    swiperH_height: "400rpx"
                },
                detail_content: "", //详情内容
                specs: "请选择规格",
                address: "请选择服务地址",
                signUpformData: {
                    user_address_id: "",
                    housing_id: "",
                    flag: "",
                    start_time: "请选择服务时间"
                },
                currentIndex: 0,
                fixedList: [{
                        name: "商品",
                        targetDom: ".info"
                    },
                    {
                        name: "详情",
                        targetDom: ".details"
                    }
                ], // 固定顶部锚点链接
                rules: {
                    address: {
                        rules: [{
                            required: true,
                            errorMessage: "请选择服务地址"
                        }]
                    },
                    type: {
                        rules: [{
                            required: true,
                            errorMessage: "请选择服务规格"
                        }]
                    },
                    serviceTime: {
                        rules: [{
                            required: true,
                            errorMessage: "请选择服务时间"
                        }]
                    }
                },
                elHeight: "",
                scrollDistance: 0,
                doms: "",
                topList: [],
                multiIndex: 0,
                specsList: [],
                isShow: false,
                selectArr: [],
                subIndex: [],
                currentItem: {
                    flag: '',
                    price: 0,
                    all_count: 0,
                    title: ""
                },
                skuInfo: [],
                specShowString: '选择规格',
                goodsData: {
                    priceInfo: [],
                    SKUInfo: [],
                },
                category_type: 0,// 分类id(只针对垃圾回收)
            }
        },

        onLoad(option) {
            console.log('下单确定地址', option);
            /* 获取当前年份 */
            let date = new Date();
            this.year = date.getFullYear();
            /* 设置页面滚动高度 */
            let screenH = uni.getSystemInfoSync().screenHeight;
            this.elHeight = screenH;


            let loginRes = this.checkLogin();
            if (!loginRes) {
                return false;
            } else {
                /* 初始化页面 */
                if (option.id) {
                    uni.setStorageSync("goods_id", option.id);
                }
                if(option.category_type){
                    uni.setStorageSync("category_type", option.category_type);
                }
                this.token = uni.getStorageSync("token");
                this.goods_id = uni.getStorageSync("goods_id");
                this.category_type = uni.getStorageSync("category_type");
            }

            // this.firstStock();
            this.getStock();
            this.getInfo();

            /* 选择地址 */
            if (option.address_id) {
                this.signUpformData.user_address_id = option.address_id;
                this.address = option.address;

            }
            /* 小区id */
            if (option.housing_id) {
                this.signUpformData.housing_id = option.housing_id;
            }


        },
    
        methods: {
            getStock() {
                let _param = {};
                _param.operate = "order.get_price",
                    _param.goods_id = this.goods_id;
                _param.token = this.token;
                _param.flag = [0];

                this.$myRequset({
                    url: "/api?operate=goods.get_price",
                    method: "POST",
                    data: _param,
                }).then((res) => {
                    this.goodsData.priceInfo = res.data.data;
                    // console.log('获取价格', this.goodsData.priceInfo);
                });
            },
            getInfo() {
                this.$myRequset({
                    url: "/api?operate=goods.info",
                    method: "POST",
                    data: {
                        token: this.token,
                        goods_id: this.goods_id
                    },
                }).then((res) => {
                    this.swiperConfig.bannerList = res.data.data.album_images;
                    this.listData.name = this.topInfo.title = res.data.data.name;
                    this.listData.price = res.data.data.price;
                    this.detail_content = res.data.data.content;
                    this.goodsData.SKUInfo = res.data.data.spec_config;
                    this.skuInfo = this.goodsData.SKUInfo;
                    if(this.skuInfo){
                        this.skuInfo.forEach(item => {
                            item.option.forEach(specItem => {
                                specItem.isShow = true;
                            })
                        })
                    }
                    // console.log('规格列表', this.goodsData.SKUInfo);
                    // console.log('规格列表_skuInfo', this.skuInfo);
                });

            },
            disabled() {
                uni.showToast({
                    title: "不可点击"
                })
            },
            /* 规格 */
            chorceSpecs() {
                setInterval(function() {
                    uni.hideKeyboard(); //隐藏软键盘
                }, 10);
                if (!this.signUpformData.user_address_id) {
                    uni.showToast({
                        title: "请先选择地址",
                        icon: "none"
                    })
                } else if (this.specsList) {
                    this.$refs.popup.open();
                    this.isShowPopup = true;
                } else {
                    uni.showToast({
                        title: "暂无规格可选",
                        icon: "none"
                    })
                }
            },
            closeProp() {
                if (this.subIndex.length == 0) {
                    uni.showToast({
                        icon: "error",
                        title: "请选择服务规格"
                    });
                } else {
                    this.$refs.popup.close();
                }
            },
            /* 确定规格 */
            confirmSpec() {
                console.log('当前选择', this.subIndex);
                console.log('当前选择', this.selectArr);
                // this.signUpformData.type = this.subIndex.toString(",");

                this.signUpformData.flag = this.subIndex;
                this.specs = this.specShowString;
                if (this.currentItem.price == 0) {
                    uni.showToast({
                        icon: "none",
                        title: "请选择完整规格"
                    })
                } else {
                    this.$refs.popup.close();
                }
            },

            /**
             * @param {String} specName 当前点击规格按钮的值(黑色,35)
             * @param {Number} specIndex 选择的规格下标(例子中颜色是0,尺码是1)
             * @param {Number} specItemIndex 选择规格值id(例子中35下标是0)
             */
            specificationBtn(specName, specIndex, specItemIndex) {
                if (this.selectArr[specIndex] != specName) { //判断所选规格数组中是否包含当前点击规格
                    this.selectArr[specIndex] = specName; //如果没有则把当前规格添加
                    this.subIndex[specIndex] = Number(specItemIndex); //添加选中样式
                } else {
                    this.selectArr[specIndex] = '';
                    this.subIndex[specIndex] = -1; //去除样式
                }
                this.specShowString = this.spaceRemoveArr(this.selectArr).join(',') || '选择规格'; //所选规格页面中展示,数组为空则变为选择规格
                this.inventoryLookup(); //当规格选完后,去匹配
                this.clickPitch(); //库存判断,实现不可点击
            },
            spaceRemoveArr(arr) { //数组去除空字符串
                let tempArr = []
                arr.forEach(item => {
                    if (item) {
                        tempArr.push(item)
                    }
                })
                return tempArr;
            },
            /* 规格选完后,去匹配 */
            inventoryLookup() {
                try {
                    this.goodsData.priceInfo.forEach((item, index) => {
                        if (item.title == this.specShowString) {
                            this.currentItem = item;
                            this.listData.price = this.currentItem.price;
                            throw new Error();
                        } else {
                            this.currentItem = {
                                flag: '',
                                price: 0,
                                all_count: 0,
                                title: ""
                            };
                        }
                    })
                } catch (e) {}
            },
            /* 库存判断,实现不可点击 */
            clickPitch() {
                let result = [];
                // console.log('库存判断:',this.goodsData.SKUInfo);
                for (let i in this.goodsData.SKUInfo) {
                    result[i] = this.selectArr[i] ? this.selectArr[i] : '';
                }
                //最难理解的大概就是这里了,这里跟着循环里打印结果,多走几遍就大致明白了  假象.jpg
                for (let i in this.goodsData.SKUInfo) {
                    let last = result[i];
                    // console.log("最后点击======",last);
                    for (let k in this.goodsData.SKUInfo[i].option) {
                        result[i] = this.goodsData.SKUInfo[i].option[k].info;
                        // console.log('result--------', result, "last:", last);
                        this.skuInfo[i].option[k].isShow = this.isMay(result)
                    }
                    result[i] = last;
                }
                // console.log('库存结果111:',result);
            },
            isMay(result) {
                for (let i in result) {
                    if (result[i] == '') {
                        return true;
                    }
                }
                for (let i in this.goodsData.priceInfo) {
                    if (this.goodsData.priceInfo[i].title == result.join(",") && this.goodsData.priceInfo[i].all_count >
                        0) {
                        return true;
                    }
                }
            },
            goAddress() {
                console.log('goAddress');
                uni.redirectTo({
                    url: "../addressList/addressList"
                });
            },
            /* 时间 */
            openDatetimePicker() {
                if (!this.signUpformData.user_address_id) {
                    uni.showToast({
                        icon: "none",
                        title: "请选择服务地址"
                    })
                } else if (!this.signUpformData.flag) {
                    uni.showToast({
                        icon: "none",
                        title: "请选择服务规格"
                    })

                } else {
                    this.$refs.myPicker.show();
                }
            },
            /* 选择时间 */
            handleSubmit(e) {
                console.log('times', e);
                this.signUpformData.start_time = `${e.year}-${e.month}-${e.day} ${e.hour}:${e.minute}`;
            },
        // 锚点链接滚动监听
            onPageScroll(res){
                this.scrollDistance = res.scrollTop;
                // console.log('滚动距离',res.scrollTop);//距离页面顶部距离
                if(res.scrollTop >=600){
                    this.currentIndex = 1;
                }else{
                    this.currentIndex = 0;
                }
            },
                      /* 锚点点击*/          
            changeactive(index) {
                console.log('sdsd',index);
                if(index==1){
                    uni.pageScrollTo({
                        duration:300, // 毫秒
                        scrollTop:600 // 位置
                    });
                }else{
                    uni.pageScrollTo({
                        duration:300, // 毫秒
                        scrollTop:0 // 位置
                    });
                }
            },

            /* 表单提交 */
            handleBuy() {
                this.$refs.signUpform.validate().then(res => {
                    console.log('表单数据信息:', res);
                    let _param = res;
                    _param.operate = "wechat.miniapp";
                    _param.token = this.token;
                    _param.goods_id = this.goods_id;
                    
                    // 垃圾回收
                    if(this.category_type == 21){
                        _param.category_type = this.category_type;
                    }
                    console.log('(_param.flag', typeof _param.flag);
                    let _res = this.$myRequset({
                        url: "/api/pay/index",
                        method: "POST",
                        data: _param,
                    }).then((res) => {
                        console.log('_res', res);
                        if (res.data.code == 1) {
                            let signType = res.data.data.signType
                            let nonceStr = res.data.data.nonceStr;
                            let _package = res.data.data.package;
                            let paySign = res.data.data.paySign;
                            let timeStamp = res.data.data.timeStamp;

                            uni.requestPayment({
                                provider: 'wxpay',
                                timeStamp: timeStamp,
                                nonceStr: nonceStr,
                                package: _package,
                                signType: signType,
                                paySign: paySign,
                                success: function(res) {
                                    console.log('pay_success:' + JSON.stringify(res));
                                    uni.reLaunch({
                                        url: "../../pages/order/order"
                                    });
                                },
                                fail: function(err) {
                                    console.log('pay_fail:' + JSON.stringify(err));
                                    uni.reLaunch({
                                        url: "../../pages/order/order",
                                    });
                                }
                            });

                        } else {
                            uni.showToast({
                                icon: "none",
                                title: "请选择规格"
                            })
                            return false;
                        }

                    });


                }).catch(err => {
                    uni.showToast({
                        title: err[0].errorMessage,
                        icon: "none"
                    });
                })
            },
            /* 拨打电话 */
            callPhone() {
                uni.makePhoneCall({
                    phoneNumber: "15902341080"
                });

            },
        }
    }
</script>

https://www.cnblogs.com/LindaBlog/p/15570833.html

接口日志表中经常会使用到blob类型的字段用来存放接口日志,但Navicat用文本工具查看blob字段会出现乱码的情况。

举例:表中BYTES是一个blob类型的字段,咱们点【文本】(也有些版本上面叫备注)查看内容时,发现其中的中文是乱码的。那么如何解决这个问题?

luanma.png

解决方法:使用cast函数转换成char类型,如下:

select cast(字段名 as char) from 表名

成功解决!