嘉立创购物车辅助工具

嘉立创辅助工具,购物车辅助增强工具

目前為 2024-04-04 提交的版本,檢視 最新版本

您需要先安裝使用者腳本管理器擴展,如 TampermonkeyGreasemonkeyViolentmonkey 之後才能安裝該腳本。

You will need to install an extension such as Tampermonkey to install this script.

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyViolentmonkey 後才能安裝該腳本。

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyUserscripts 後才能安裝該腳本。

你需要先安裝一款使用者腳本管理器擴展,比如 Tampermonkey,才能安裝此腳本

您需要先安裝使用者腳本管理器擴充功能後才能安裝該腳本。

(我已經安裝了使用者腳本管理器,讓我安裝!)

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

(我已經安裝了使用者樣式管理器,讓我安裝!)

// ==UserScript==
// @name         嘉立创购物车辅助工具
// @namespace    http://tampermonkey.net/
// @version      1.2.6
// @description  嘉立创辅助工具,购物车辅助增强工具
// @author       You
// @match        https://cart.szlcsc.com/cart/display.html**
// @icon         https://www.google.com/s2/favicons?sz=64&domain=szlcsc.com
// @require      https://cdn.bootcdn.net/ajax/libs/jquery/3.6.0/jquery.min.js
// @require      https://update.greasyfork.org/scripts/455576/1122361/Qmsg.js
// @resource customCSS https://gitee.com/snwjas/message.js/raw/master/dist/message.min.css
// @grant        GM_xmlhttpRequest
// @grant        GM_addStyle
// @grant        GM_getResourceText
// @license      MIT
// ==/UserScript==

(async function() {
    'use strict';

    // 引入message的css文件并加入html中
    const css = GM_getResourceText("customCSS");
    GM_addStyle(css);

    /**
     * rgb颜色随机
     * @returns
     */
    const rgb = () => {
        var r = Math.floor(Math.random() * 256);
        var g = Math.floor(Math.random() * 256);
        var b = Math.floor(Math.random() * 256);
        var rgb = 'rgb(' + r + ',' + g + ',' + b + ')';
        return rgb;
    }

    /**
     * rgba颜色随机
     * @param {*} a
     * @returns
     */
    const rgba = (a = 1) => {
        var r = Math.floor(Math.random() * 256);
        var g = Math.floor(Math.random() * 256);
        var b = Math.floor(Math.random() * 256);
        var rgb = 'rgba(' + r + ',' + g + ',' + b + ',' + a + ')';
        return rgb;
    }

    /**
     * 十六进制颜色随机
     * @returns
     */
    const color16 = () => {
        var r = Math.floor(Math.random() * 256);
        var g = Math.floor(Math.random() * 256);
        var b = Math.floor(Math.random() * 256);
        var color = '#' + r.toString(16) + g.toString(16) + b.toString(16);
        return color;
    }

    /**
     * 正则获取品牌名称,需要传入xxxx(品牌名称) 这样的字符
     * @param {*} text
     * @returns
     */
    const getBrandNameByRe = (text) => {
        return /\(.+\)/g.exec(text)[0].replace(/\((.*?)\)/, '$1')
    }

    // 后续支持强排序按钮

    // 商品清单集合暂存
    const dataMp = new Map()
        // 品牌对应颜色,用于快速查找位置。
    const dataBrandColorMp = new Map()
        // 优惠券页面,数据暂存。只保存16-15的优惠券
    const couponMp = new Map()

    // 消息弹框全局参数配置
    Qmsg.config({
        showClose: true,
        timeout: 2500,
    })

    /**
     * 根据value排序Map
     * @param {*} map
     * @returns
     */
    const sortMapByValue = (map) => {
        var arrayObj = Array.from(map);
        //按照value值降序排序
        arrayObj.sort(function(a, b) { return a[1] - b[1] });
        return arrayObj
    }


    // 控制按钮的生成
    const buttonListFactory = () => {
        return `
            <div class='mr10 flex flex-sx-center'><label style="font-size: 14px">自动领取优惠券</label><input style="zoom: 80%; margin: 0 8px;" type="checkbox" class="checkbox"/>(功能暂未开发)</div>
        `
    }


    /**
     * 追加的html
     * @returns
     */
    const htmlFactory = () => {
        let tempHtml = `<div class="bd">
        ${buttonListFactory()}
        <ul>`

        const head = `
        <li class='li-cs'>
                <div>
                    <span style='font-weight: 1000; color: black;width: 110px;' class="flex flex-zy-center">品牌名称</br>(现货)</span>
                    <span style='font-weight: 1000; color: black; width: 80px;' class="flex flex-zy-center">总金额</span>
                    <span style='font-weight: 1000; color: black;' class="flex flex-zy-center">优惠券</br>(16-15) </span>
                </div>
            </li>
        `

        tempHtml += head

        for (var [key, val] of sortMapByValue(dataMp)) {
            // <a href='https://www.szlcsc.com/huodong.html?from=dh' class="to_cou" target="_blank">优惠券入口</a>
            tempHtml += `
            <li class='li-cs click-hv'>
                <div>
                    <span class='key' style="width: 110px;">${key}</span>
                    <span class='val' style="width: 80px;">${val}</span>
                    ${conponHTMLFactory(key)}
                </div>
            </li>
            `
        }

        return tempHtml + '</ul></div>'
    }

    /**
     * 优惠券按钮的html生成
     * @param {*} brandName  品牌名称
     */
    const conponHTMLFactory = (brandName) => {

        // 优惠券实体
        const couponEntity = couponMp.get(brandName)

        let buttonLine = ''

        if (!$.isEmptyObject(couponEntity)) {

            // 是否已经领取
            if (couponEntity.isHaved === true) {
                buttonLine = `<span class='val' style="text-align: center; ">
                    <span style="font-size: 12px;">已领取-${couponEntity.isNew === false ? '普通券' : '新人券'}</span>
                </span> `
            } else {
                buttonLine = `<span class='flex-sx-center flex-zy-center flex' style="padding: 0; width: 160px; text-align: center; ">
                    <button type="button" class="to_cou">${couponEntity.isNew === false ? '普通券' : '新人券'}</button>
                 </span> `
            }
        }

        return $.isEmptyObject(buttonLine) ? '<span></span>' : buttonLine
    }


    /**
     * 追加的css
     * @returns
     */
    const cssFactory = () => `
    <style id="myCss">
    .bd {
        position: fixed;
        top: 40px;
        right: 40px;
        background-color: white;
        border: 2px solid #3498db;
        width: 320px;
        padding: 3px;
        border-radius: 5px;
        z-index: 10;
        overflow: auto;
    }

    .mr10 {
        margin: 10px;
    }

    .flex {
        display: flex;
    }

    .flex-sx-center {
        /*上下居中*/
        align-items: center;
    }

    .flex-zy-center {
        /*左右居中*/
        justify-content: center;
    }

    .li-cs{
     margin: 5px;
     font-size: 14px;
     box-sizing:border-box;
    }

    .click-hv:hover span, .li-cs button:hover {
      color: #444 !important;
      cursor: pointer;
    }

    .li-cs div {
        display: flex;
        width: 100%;
        border: 2px solid #3498db;
        border-radius: 5px;
    }

    .li-cs span {
        padding: 10px;
        width: 50%;
        color: white;
        text-shadow: 1px 1px 1px white;
        box-sizing:border-box;
    }

    .li-cs .to_cou {
        border: 1px solid white;
        border-radius: 3px;
        background-color: rgba(255, 255, 255, 0.6);
        padding: 3px 4px;
        color: #2c4985;
        text-shadow: 1px 1px 1px white;
    }

    .cart-li-pro-info div:hover {
        color:rgba(57, 46, 74, 0.9) !important;
        text-shadow: 1px 1px 1px white;
    }
     .li-cs .to_cou:hover {
        color:black !important;
        text-shadow: 1px 1px 1px white;
    }

    .checkbox {
        appearance: none;
        width: 64px;
        height: 32px;
        position: relative;
        border-radius: 16px;
        cursor: pointer;
        background-color: #777;
    }

    .checkbox:before {
        content: "";
        position: absolute;
        width: 28px;
        height: 28px;
        background: white;
        left: 2px;
        top: 2px;
        border-radius: 50%;
        transition: left cubic-bezier(0.3, 1.5, 0.7, 1) 0.3s;
    }

    .checkbox:after {
        content: "开 关";
        text-indent: 12px;
        word-spacing: 4px;
        display: inline-block;
        white-space: nowrap;
        color: white;
        font: 14px/30px monospace;
        font-weight: bold;
    }

    ..checkbox:hover:before {
        box-shadow: inset 0px 0px 5px 0px #3498db;
    }
    .checkbox:checked {
        background-color: limegreen;
    }
    .checkbox:checked:before {
        left: 34px;
    }
    .checkbox:checked:after {
        color: black;
    }
    </style>
    `


    /**
     * 追加到body
     */
    const appendHtml = () => {

        $('#myCss').remove()
        $('.bd').remove()

        $('body').append(cssFactory())
            .append(htmlFactory())
    }

    /**
     * 基础配置优化
     */
    const basicSettings = () => {
        // 多选框放大
        $('input[type*=checkbox]').css('zoom', '150%')

        // 点击物料图片,操作多选框
        $('.product-img').each(function() {
            $(this).on('click', function(target) {
                $(this).prev('.check-box').click()
            })
        })

        // 购物车列表 点击品牌跳转到该品牌下的商品
        let brandElement = $('.product-item li.cart-li-pro-info').find('div:eq(2)')
        brandElement.css({ cursor: 'pointer' })
        brandElement.on('click', function() {
            window.open(`https://so.szlcsc.com/global.html?k=${getBrandNameByRe(this.innerText)}`)
        })
    }


    /**
     * 遍历购物车清单,并计算品牌总金额
     */
    const eachCartList = () => {
        dataMp.clear()

        getHavedLineInfo().each(function(i) {

            // 物料编号
            let productId = $(this).find('ul li:eq(1) a').text().trim()

            // 品牌名称
            let brandName = $(this).find('.cart-li-pro-info div:eq(2)').text().trim()

            // 查找到品牌名称
            brandName = getBrandNameByRe(brandName.split('\n')[brandName.split('\n').length - 1].trim())

            if ($(this).find('input:checked').length === 0) {
                return
            }

            // 品牌下的单个商品总价
            let linePrice = parseFloat($(this).find('.line-total-price').text().trim().replace('¥', ''))

            // 日志打印控制台
            // console.log(productId, brandName, linePrice)

            let mpVal = $.isEmptyObject(dataMp.get(brandName)) ? 0 : dataMp.get(brandName)

            // 保存到Map中
            dataMp.set(brandName, parseFloat((mpVal + linePrice).toFixed(2)))


            if ($.isEmptyObject(dataBrandColorMp.get(brandName))) {
                // 对品牌进行随机色设置
                dataBrandColorMp.set(brandName, rgba('0.9'))
            }
        })
    }

    /**
     * 对品牌进行随机色设置
     */
    const setBrandColor = () => {

        //弹框 对品牌进行随机色设置
        $('.li-cs').each(function(i) {
            $(this).css('background', dataBrandColorMp.get($(this).find('span:eq(0)').text().trim()))
        })

        // 购物车列表颜色设置
        dataBrandColorMp.forEach((v, k) => {
            let brandElement = getHavedLineInfoByBrandName(k).find('ul li.cart-li-pro-info')
            brandElement.css({
                'background-color': v,
                'text-shadow': '0px 1px 1px white',
                'color': 'white'
            })

            brandElement.find('a').css({
                'text-shadow': '0px 1px 1px white',
                'color': 'white'
            })
        })
    }

    /**
     * 通过品牌名称,查找购物车中所在行的元素(包含现货、订货)
     */
    const getAllLineInfoByBrandName = (brandName) => {
        return $('.product-list .product-item:contains(' + brandName + ')')
    }

    /**
     * 通过品牌名称,查找购物车中所在行的元素(只获取现货商品)
     */
    const getHavedLineInfoByBrandName = (brandName) => {
        return $('.product-list .product-list-dl:eq(0) .product-item:contains(' + brandName + ')')
    }

    /**
     * 查找购物车中所在行的元素(只获取现货商品)
     */
    const getHavedLineInfo = () => {
        return $('.product-list .product-list-dl:eq(0) .product-item')
    }

    /**
     * 点击小窗口的品牌按钮,实现该品牌下的单选
     * 且该品牌下的物料,会自动排到购物车的前面几条
     */
    const clickBrand = () => {
        $('.click-hv .key').on('click', function(target) {
            let brandName = $(this).text().trim()

            let cutHtmlElement = []

            // 查找购物车 现货商品
            getHavedLineInfoByBrandName(brandName).each(function(i) {
                cutHtmlElement.push($(this))
            })

            cutHtmlElement.forEach(item => {
                $('.product-list .product-list-dl:eq(0) .product-item').insertAfter(item)
            })
        })
    }

    /**
     * 多选框变化,刷新小窗口的计算结果
     */
    const checkStatusChangeHandler = () => {
        $(".check-box").change(refresh);
    }


    /**
     * GET请求封装
     * @param {} data
     */
    const getAjax = (url) => {
        return new Promise((resolve, reject) => {
            GM_xmlhttpRequest({
                url,
                method: 'GET',
                onload: (r) => {
                    resolve(r.response)
                },
                onerror: (err) => {
                    reject(err)
                }
            });
        });
    }

    /**
     * POST请求封装
     * @param {} data
     */
    const postAjax = (url, data) => {
        return new Promise((resolve, reject) => {
            GM_xmlhttpRequest({
                url,
                method: 'POST',
                headers: { 'Content-Type': 'application/json' },
                data: JSON.stringify(data),
                onload: (r) => {
                    resolve(r.response)
                },
                onerror: (err) => {
                    reject(err)
                }
            });
        });
    }


    /**
     * 获取优惠券列表信息,并暂存在变量集合中
     */
    const getCouponHTML = async() => {
        let couponHTML = await getAjax('https://www.szlcsc.com/huodong.html?from=dh#coupon2')

        $(couponHTML).find('.coupon-item:contains(满16可用) div[data-id]').each(function() {

            let $this = $(this)

            // 优惠券id
            let couponId = $this.attr('data-id')

            // 是否已经领取
            let isHaved = $this.find(':contains(立即使用)').length > 0

            // 优惠券金额
            let couponPrice = $this.attr('data-name').replace(/^.*?\>(.*?)元.*$/, '$1')
                // 品牌名称
            let brandName = $this.attr('data-name').replace(/^.*?元(.*?)品牌.*$/, '$1')

            // 是否新人优惠券
            let isNew = $this.attr('data-name').split('新人专享').length >= 2

            couponMp.set(brandName, {
                isNew, // 是否新人专享
                couponPrice, //优惠券金额减免
                brandName, // 品牌名称
                couponId, // 优惠券id
                isHaved, // 是否已经领取
                couponLink: `https://www.szlcsc.com/getCoupon/${couponId}`, // 领券接口地址
            })

            // console.log(couponPrice, brandName)
        })


        // console.log(couponMp)
    }

    /**
     * 优惠券领取按钮的绑定事件
     */
    const getCouponClickHandler = () => {
        $('.to_cou').click(async function(target) {
            let brandName = $(this).parents('span').siblings('.key').text()

            // 优惠券实体
            let couponEntity = couponMp.get(brandName)

            if (!$.isEmptyObject(couponEntity)) {
                let res = await getAjax(couponEntity.couponLink)
                    // console.log(res);

                let resParseData = JSON.parse(res)
                if (resParseData.result === 'success') {
                    Qmsg.info('领取成功!')
                    refresh(true)
                } else {
                    Qmsg.error(resParseData.msg)
                }
            }
        })
    }

    /**
     * 刷新小窗口数据
     * @param {*} notRefreshCouponHtml 是否更新优惠券集合数据
     */
    const refresh = async(notRefreshCouponHtml) => {

        // 是否更新优惠券集合数据,主要更新是否领取的状态
        if (notRefreshCouponHtml === true) {
            await getCouponHTML()
        }

        eachCartList()
        appendHtml()
        setBrandColor()
        clickBrand()
        getCouponClickHandler()
    }


    /**
     * 重置小窗口的高度
     */
    const resizeHeght = () => {

        let bdHeight = parseFloat($('.bd').css('height').replace('px', ''))

        if ((window.innerHeight - 120) < bdHeight) {
            $('.bd').css({ height: '82vh' })
        } else {
            $('.bd').css({ height: 'auto' })
        }
    }

    window.addEventListener('resize', resizeHeght);

    basicSettings()
    eachCartList()
    await getCouponHTML()
    appendHtml()
    setBrandColor()
    clickBrand()
    checkStatusChangeHandler()
    getCouponClickHandler()

    // console.log(dataMp)
    // console.log(dataBrandColorMp)


})();