Greasy Fork is available in English.

【高糖质控】

在指定页面上添加慢病质控按钮,生成双iframe,分别是体检和随访,并上传质控时间

// ==UserScript==
// @name 【高糖质控】
// @namespace http://tampermonkey.net/
// @version 1.0
// @description 在指定页面上添加慢病质控按钮,生成双iframe,分别是体检和随访,并上传质控时间
// @author 大成路旁
// @match http://10.85.36.41/jkda/*
// @run-at document-end
// @grant GM_xmlhttpRequest
// ==/UserScript==
(function() {
    'use strict';
    let hypertensionArchives = [];
    const qualityController = '宋维伟'; // 添加质控人员
    // 加载高血压档案数据
    function loadHypertensionArchives() {
        const url = 'http://192.168.8.188:8000/体检cid.json';
        console.log('开始加载高血压档案数据:', url);
        GM_xmlhttpRequest({
            method: 'GET',
            url: url,
            onload: function(response) {
                if (response.status === 200) {
                    try {
                        const cleanedResponseText = cleanJsonResponse(response.responseText);
                        const data = JSON.parse(cleanedResponseText);
                        console.log('解析到服务器的json数据');
                        hypertensionArchives = data;
                        addEventListeners();
                    } catch (e) {
                        console.error('解析到服务器的json数据失败:', e, { responseText: response.responseText });
                    }
                } else {
                    console.error('获取到服务器的json数据失败:', response.statusText, { status: response.status, responseHeaders: response.responseHeaders, finalUrl: response.finalUrl, statusText: response.statusText });
                }
            },
            onerror: function(error) {
                console.error('请求服务器数据时发生错误:', error, { readyState: this.readyState, responseHeaders: this.responseHeaders, finalUrl: this.finalUrl, status: this.status, statusText: this.statusText });
            }
        });
    }
    // 清洗JSON响应文本
    function cleanJsonResponse(responseText) {
        let cleanedResponseText = responseText.replace(/[\x00-\x1f\x7f-\x9f]/g, '');
        if (!cleanedResponseText.startsWith('[')) cleanedResponseText = '[' + cleanedResponseText;
        if (!cleanedResponseText.endsWith(']')) cleanedResponseText = cleanedResponseText + ']';
        cleanedResponseText = cleanedResponseText.replace(/(\{[^{}]*)(?=\s*,\s*\}|\s*\]|$)/g, '$1}').replace(/(\{[^{}]*)(?=\s*,\s*])/g, '$1},');
        return cleanedResponseText;
    }
    // 构建【随访】URL
    function buildUrlWithParams(baseUrl, params) {
        const query = Object.keys(params).map(key => `dto%5B'${encodeURIComponent(key)}'%5D=${encodeURIComponent(params[key])}`).join('&');
        const randomParam = `_r=${Math.random()}`;
        return `${baseUrl}?${query}&${randomParam}`;
    }
    // 获取【体检】URL
    function getArchiveUrl(archiveId) {
        const archive = hypertensionArchives.find(item => item.档案号 === archiveId);
        if (archive) {
            const baseUrl = 'http://10.85.36.41/jkda/ehr/tPersonBaseInfoAction!viewHealthCheck.do?dto%5B%27c_id%27%5D=';
            const archiveUrl = `${baseUrl}${encodeURIComponent(archive.体检cid)}`;
            return archiveUrl;
        } else {
            alert(`未找到档案号 ${archiveId} 对应的网址,请检查档案数据。`);
            return null;
        }
    }
    // 生成质控页面模板
    function qualityControlTemplate(examUrl, followUpUrl, name, startTime, archiveNumber) {
        return `
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>${decodeURIComponent(name)} - 档案质控</title>
<style>
body, html { margin: 0; padding: 0; height: 100%; overflow: hidden; }
.container { display: flex; height: 100vh; }
iframe { width: 50%; height: 100%; border: none; }
#closeButton {
    position: absolute;
    top: 10px;
    right: 10px;
    z-index: 10000;
    background-color: #ff0000;
    color: white;
    border: none;
    padding: 10px 20px;
    font-size: 16px;
    border-radius: 8px;
    cursor: pointer;
}
</style>
</head>
<body>
<div class="container">
<iframe id="examFrame" src="${examUrl}"></iframe>
<iframe id="followUpFrame" src="${followUpUrl}"></iframe>
</div>
<button id="closeButton">关闭</button>
<script>
const closeButton = document.getElementById('closeButton');
closeButton.addEventListener('click', function() {
    const endTime = new Date().getTime();
    const duration = (endTime - ${startTime}) / 1000;
    console.log('开始时间:', new Date(${startTime}).toISOString());
    console.log('结束时间:', new Date(endTime).toISOString());
    console.log('停留时间(秒):', duration);
    // 向父页面发送消息
    window.parent.postMessage({
        type: 'recordTime',
        archiveNumber: '${archiveNumber}',
        startTime: ${startTime},
        endTime: endTime,
        duration: duration,
        name: '${decodeURIComponent(name)}'
    }, '*');
});
window.addEventListener('message', function(event) {
    if (event.data.type === 'closeWindow') {
        window.parent.document.body.removeChild(window.parent.document.getElementById('qualityControlIframeContainer'));
    }
});
</script>
</body>
</html>
`;
    }
    // 创建质控按钮
    function createQualityControlButton() {
        const qualityControlButton = document.createElement('a');
        qualityControlButton.className = 'publichealthbutton publichealth-blue publichealth-small quality-control-button';
        qualityControlButton.href = 'javascript:void(0)';
        qualityControlButton.textContent = '慢病质控';
        qualityControlButton.style.cssText = `
margin-left: 5px;
background: #228B22;
color: white;
padding: 5px;
border-radius: 2px;
text-decoration: none;
display: inline-block;
line-height: 10px;
vertical-align: middle;
font-size: 12px;
`;
        return qualityControlButton;
    }
    // 处理质控按钮点击事件
    function handleQualityControlButtonClick(e) {
        e.preventDefault();
        const archiveNumber = this.closest('.slick-row').querySelector('.slick-cell.l4.r4').textContent.trim();
        const examUrl = getArchiveUrl(archiveNumber);
        const viewButton = this.closest('.slick-row').querySelector('a[href^="javascript:fn_fileView"]');
        if (viewButton && examUrl) {
            const match = viewButton.href.match(/fn_fileView\('([^']+)','([^']+)','([^']+)','([^']+)','([^']+)','([^']+)','([^']+)','([^']+)'\)/);
            if (match) {
                const [c_id, encodedName, cancel_flag, org_code, recd_type, day, follow_no, no_id] = match.slice(1);
                const decodedName = decodeURIComponent(encodedName); // 解码姓名
                const baseUrl = "http://10.85.36.41/jkda/chronic/chronicDiseaseVisitAction!toHypertensionView.do";
                const followUpParams = { c_id, name: decodedName, cancel_flag, org_code, recd_type, day, follow_no, no_id };
                const followUpUrl = buildUrlWithParams(baseUrl, followUpParams);
                const startTime = new Date().getTime(); // 记录开始时间
                const iframeContainer = document.createElement('div');
                iframeContainer.id = 'qualityControlIframeContainer';
                iframeContainer.style.cssText = `
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
z-index: 9999;
background-color: white;
`;
                const iframe = document.createElement('iframe');
                iframe.srcdoc = qualityControlTemplate(examUrl, followUpUrl, encodedName, startTime, archiveNumber);
                iframe.style.cssText = `
width: 100%;
height: 100%;
border: none;
`;
                iframeContainer.appendChild(iframe);
                document.body.appendChild(iframeContainer);
                // 监听来自子页面的消息
                window.addEventListener('message', function(event) {
                    if (event.data.type === 'recordTime') {
                        const { archiveNumber, startTime, endTime, duration, name } = event.data;
                        const formattedStartTime = new Date(startTime).toLocaleString('zh-CN', { year: 'numeric', month: '2-digit', day: '2-digit', hour: '2-digit', minute: '2-digit', second: '2-digit' }).replace(/\//g, '/');
                        const formattedEndTime = new Date(endTime).toLocaleString('zh-CN', { year: 'numeric', month: '2-digit', day: '2-digit', hour: '2-digit', minute: '2-digit', second: '2-digit' }).replace(/\//g, '/');
                        sendRecordTime({ archiveNumber, name, formattedStartTime, formattedEndTime, duration, qualityController });
                        // 发送消息给子页面,告知可以关闭窗口
                        event.source.postMessage({ type: 'closeWindow' }, '*');
                    }
                }, { once: true }); // 只注册一次
            }
        }
    }
    // 发送记录时间请求
    function sendRecordTime({ archiveNumber, name, formattedStartTime, formattedEndTime, duration, qualityController }) {
        GM_xmlhttpRequest({
            method: "POST",
            url: 'http://192.168.8.188:8000/time',
            headers: {
                "Content-Type": "application/json"
            },
            data: JSON.stringify({
                质控人员: qualityController,
                档案号: archiveNumber,
                姓名: name,
                开始时间: formattedStartTime,
                结束时间: formattedEndTime,
                停留时间: duration
            }),
            onload: function(response) {
                console.log("Server responded:", response.responseText);
            }
        });
    }
    // 添加质控按钮
    function addQualityControlButtons() {
        const deleteButtons = document.querySelectorAll('a.publichealthbutton.publichealth-blue.publichealth-small[href^="javascript:fn_delete"]');
        deleteButtons.forEach(deleteButton => {
            if (!deleteButton.nextElementSibling || !deleteButton.nextElementSibling.classList.contains('quality-control-button')) {
                const qualityControlButton = createQualityControlButton();
                qualityControlButton.addEventListener('click', handleQualityControlButtonClick);
                deleteButton.parentNode.insertBefore(qualityControlButton, deleteButton.nextSibling);
            }
        });
    }
    // 添加事件监听器
    function addEventListeners() {
        const queryButton = document.querySelector('button[id^="tabasicfield_"][id$="_query"]');
        if (queryButton) {
            queryButton.addEventListener('click', () => {
                setTimeout(addQualityControlButtons, 500);
            });
        }
        const observer = new MutationObserver(mutations => {
            mutations.forEach(() => {
                const targetNode = document.querySelector('table.slick-grid');
                if (targetNode) {
                    addQualityControlButtons();
                    observer.disconnect();
                }
            });
        });
        const targetNode = document.querySelector('table.slick-grid');
        if (targetNode) {
            observer.observe(targetNode, { childList: true, subtree: true });
        } else {
            setTimeout(() => {
                const targetNode = document.querySelector('table.slick-grid');
                if (targetNode) {
                    observer.observe(targetNode, { childList: true, subtree: true });
                }
            }, 1000);
        }
    }
    // 初始化加载高血压档案数据
    loadHypertensionArchives();
})();