联通内网 - 智慧法治平台

创新与灵感的交汇处

安装此脚本?
作者推荐脚本

您可能也喜欢联通党校-刷课程,可秒刷

安装此脚本
// ==UserScript==
// @name         联通内网 - 智慧法治平台
// @namespace    http://unicom.studio/
// @version      2025-04-08
// @description  创新与灵感的交汇处
// @author       easterNday
// @match        https://lawplatform.chinaunicom.cn/*
// @icon         https://unicom.studio/Unicom.svg
// @grant        GM_xmlhttpRequest
// @require      https://cdnjs.cloudflare.com/ajax/libs/crypto-js/4.2.0/crypto-js.min.js
// @require      data:application/javascript,window.LAYUI_GLOBAL=%7Bdir:'https://unpkg.com/[email protected]/dist/'%7D
// @require      https://unpkg.com/[email protected]/dist/layui.js
// @run-at       document-start
// @license MIT
// ==/UserScript==
(function () {
    'use strict';

    const PASSWORD = 'lawtalkwebfront_';
    const CONCURRENCY_LIMIT = 5;

    // 状态管理对象
    const state = {
        authorization: localStorage.getItem('law_auth') || '', // 持久化存储[5](@ref)
        isRunning: false,
        currentPage: 1,
        ready: false,
    };

    // 用户信息
    const userInfo = {
        name: '',
        pageSize: localStorage.getItem('law_page_size') || 50,
    };


    const articleStore = {
        list: new Map(),
        total: 0,
        get count() {
            return this.list.size;
        }
    };

    // 请求拦截
    (function setupRequestInterceptor() {
        const originalOpen = XMLHttpRequest.prototype.open;
        const originalSetHeader = XMLHttpRequest.prototype.setRequestHeader;

        // 请求头拦截
        XMLHttpRequest.prototype.requestHeaders = {};
        XMLHttpRequest.prototype.setRequestHeader = function (name, value) {
            this.requestHeaders[name] = value;
            originalSetHeader.apply(this, arguments);
        };

        // 核心拦截逻辑
        XMLHttpRequest.prototype.open = function (method, url) {
            this.addEventListener('load', function () {
                // 仅捕获Authorization字段
                if (this.requestHeaders) {
                    const authHeader = this.requestHeaders['Authorization'] || this.requestHeaders['authorization'];
                    if (authHeader && authHeader !== state.authorization) {
                        state.authorization = authHeader;
                        localStorage.setItem('law_auth', authHeader);
                    }
                }

                // TODO: 此处还需要增加用户信息获取功能
                // userName = decodeURIComponent(this.responseURL.split('mm=')[1].split('&')[0])
                // userName = cryptoUtils.decryptECB(atob(userName), PASSWORD)
                // if (userName) {
                //     isGetUserName = true;
                // }
                // TODO: 下面是第一版的实现
                if (url.includes('readPurview') && !userInfo.name) {
                    const mm = new URL(url).searchParams.get('mm');
                    userInfo.name = cryptoUtils.decryptECB(atob(mm));
                }
            });


            originalOpen.apply(this, arguments);
        };
    })();

    // 加密模块
    const cryptoUtils = {
        encryptECB: (text) => {
            const key = CryptoJS.enc.Utf8.parse(PASSWORD.padEnd(16, "\0"));
            return CryptoJS.AES.encrypt(text, key, {
                mode: CryptoJS.mode.ECB,
                padding: CryptoJS.pad.Pkcs7
            }).toString();
        },
        decryptECB: (cipherText) => {
            const key = CryptoJS.enc.Utf8.parse(PASSWORD.padEnd(16, "\0"));
            return CryptoJS.AES.decrypt(cipherText, key, {
                mode: CryptoJS.mode.ECB,
                padding: CryptoJS.pad.Pkcs7
            }).toString(CryptoJS.enc.Utf8);
        }
    };

    // 请求队列系统
    const requestQueue = {
        queue: [],
        active: 0,
        async add(task) {
            this.queue.push(task);
            return this.process();
        },
        async process() {
            return new Promise((resolve) => {
                const runner = async () => {
                    while (this.active < CONCURRENCY_LIMIT && this.queue.length) {
                        const task = this.queue.shift();
                        this.active++;
                        try {
                            await task();
                        } catch (error) {
                            console.error('Task failed:', error);
                        } finally {
                            this.active--;
                            runner();
                        }
                    }
                    if (this.queue.length === 0 && this.active === 0) {
                        resolve();
                    }
                };
                runner();
            });
        }
    };

    // 数据获取逻辑
    const dataService = {
        async getTotal() {
            const params = this.buildParams(1);
            const { total } = await this.fetchData(params);
            articleStore.total = total;
            return total;
        },

        async fetchPage(pageNum) {
            const params = this.buildParams(pageNum);
            const { rows } = await this.fetchData(params);
            rows.forEach(article => {
                articleStore.list.set(article.articleId, article);
            });
            return rows;
        },

        buildParams(pageNum) {
            return {
                pageNum,
                pageSize: userInfo.pageSize,
                sortType: 0,
                columnOne: null,
                columnTwo: null,
                readPurviewValueList: [
                    "52afcdceba40421e85ae255d84611ce1",
                    "c9f4122a68904299b737555e2c13858d",
                    "fb9a92b14df74671840dc9c5bce47b22",
                    "42",
                    "4211",
                    "421121998"
                ],
                readPurviewRoleTypeList: [],
                m_m: userInfo.name
            };
        },

        async fetchData(params) {
            const mm = cryptoUtils.encryptECB(JSON.stringify(params));
            const response = await fetch(
                `https://lawplatform.chinaunicom.cn/api/legal/more/article/list?pageSize=${userInfo.pageSize}&pageNum=${params.pageNum}`,
                {
                    method: 'POST',
                    headers: {
                        authorization: state.authorization,
                        'content-type': 'application/json'
                    },
                    body: JSON.stringify({ mm })
                }
            );
            return response.json();
        }
    };

    // 文章处理
    async function processArticles() {
        try {
            const totalPages = Math.ceil(articleStore.total / userInfo.pageSize);
            const tasks = Array.from({ length: totalPages }, (_, i) =>
                () => dataService.fetchPage(i + 1)
            );

            // 清空队列并添加任务
            requestQueue.queue = tasks;

            // ✅ 等待所有分页完成
            await requestQueue.process();

            layer.msg(`已加载 ${articleStore.count} 篇文章`, { icon: 1 });

            // 创建文章处理任务
            const articleTasks = Array.from(articleStore.list.values(), article =>
                () => Promise.allSettled([
                    processRead(article),
                    processLike(article)
                ])
            );

            // 添加文章处理任务
            requestQueue.queue = articleTasks;
            await requestQueue.process();

            layer.msg('所有操作已完成', { icon: 1 });
        } catch (error) {
            layer.msg('处理失败: ' + error.message, { icon: 2 });
        }
    }

    // 阅读处理
    async function processRead(article) {
        // if (article.isBrowse) return;

        const timestamp = cryptoUtils.encryptECB(Date.now().toString());
        const mm = cryptoUtils.encryptECB(JSON.stringify({
            businessId: article.articleId,
            m_m: userInfo.name
        }));

        await Promise.all([
            fetch(`https://lawplatform.chinaunicom.cn/api/legal-console/integral/checkIntegralForBrowser`, {
                method: 'POST',
                headers: {
                    authorization: state.authorization,
                    'content-type': 'application/json'
                },
                body: JSON.stringify({ mm })
            }),
            // fetch(`https://lawplatform.chinaunicom.cn/api/legal/article/details/readPurview?timeStamp=${btoa(timestamp)}&mm=${btoa(mm)}`, {
            //     headers: { authorization: state.authorization }
            // }),
            fetch(`https://lawplatform.chinaunicom.cn/api/legal/article/details/add-browse-num/${article.articleId}`, {
                headers: { authorization: state.authorization }
            })
        ]);
    }

    // 点赞处理
    async function processLike(article) {
        // if (article.isLike) return;

        const mm = cryptoUtils.encryptECB(JSON.stringify({
            articleId: article.articleId,
            whetherLike: 1,
            m_m: userInfo.name
        }));

        await fetch("https://lawplatform.chinaunicom.cn/api/legal/like-detail", {
            method: 'POST',
            headers: {
                authorization: state.authorization,
                'content-type': 'application/json'
            },
            body: JSON.stringify({ mm })
        });
    }

    // 初始化入口
    async function init() {
        // setupRequestInterceptor();
        await waitForUserInfo().then(() => { layer.msg('基础信息获取完成', { time: 7777, icon: 1 }); });

        await dataService.getTotal();
        await createUI();
    }

    async function waitForUserInfo() {
        return new Promise(resolve => {
            const check = () => {
                if (userInfo.name && state.authorization) {
                    state.ready = true;
                    resolve();
                } else {
                    setTimeout(check, 500);
                }
            };
            check();
        });
    }

    // 创建UI
    async function createUI() {
        // TODO: 完善UI
        let buttonSets = document.createElement("div");
        document.body.appendChild(buttonSets);
        buttonSets.id = "buttonSets";
        buttonSets.style.padding = "8px";
        buttonSets.style.display = "flex";
        buttonSets.style.flexDirection = "row";
        buttonSets.style.justifyContent = "center";
        buttonSets.style.alignItems = "center";
        buttonSets.style.position = "fixed";
        buttonSets.style.bottom = "20px";
        buttonSets.style.right = "20px";
        buttonSets.style.zIndex = "1000";
        buttonSets.innerHTML = `
        <link href="//unpkg.com/[email protected]/dist/css/layui.css" rel="stylesheet">
        <button id="controlPanelButton" type="button" class="layui-btn layui-btn-lg layui-btn-primary layui-btn-radius layui-bg-red">控制面板</button>
        `

        let controlPanelButton = document.getElementById("controlPanelButton")
        controlPanelButton.onclick = () => {
            layer.open({
                type: 1,
                id: "settingsPanel",
                title: "智慧法治平台配置",
                area: ["320px", "100%"],
                offset: 'l',
                anim: 'slideRight', // 从左往右
                shade: 0.1,
                // skin: 'layui-layer-win10',
                icon: 6,
                resize: false,
                move: false,
                content: `
                <div class="layui-input-group">
                    <div class="layui-input-prefix">用户昵称</div>
                    <input type="text" name="username" value="" lay-verify="required" placeholder="${userInfo.name}" class="layui-input" disabled>
                </div>
                <div class="layui-input-group">
                    <div class="layui-input-prefix">文章总数</div>
                    <input type="text" name="username" value="" lay-verify="required" placeholder="${articleStore.total}" class="layui-input" disabled>
                </div>
                <div class="layui-input-group">
                    <div class="layui-input-prefix">单次请求数目</div>
                    <input id="pageSize" type="number" lay-affix="number" value="${userInfo.pageSize}" step="10" min="10" max="50" class="layui-input">
                    <!-- <div class="layui-input-suffix">单次请求数目</div> -->
                </div>
                `,
                btn: ['保存设置', '开始运行'],
                btn1: function (index, layero, that) {
                    localStorage.setItem('law_page_size', document.getElementById("pageSize").value);
                    userInfo.pageSize = document.getElementById("pageSize").value;

                    return false
                },
                btn2: function (index, layero, that) {
                    processArticles();
                    return true
                }
            });

        }
    }

    window.addEventListener('load', init);
})();