处理省内OA文件,快速展现主要领导提交的后续人员列表,避免重复提交。
// ==UserScript==
// @name 省内OA流程跟踪提取XXX送办理后续人员(隐藏iframe+通信版)
// @namespace http://tampermonkey.net/
// @version 1.15.0
// @description 无感后台加载流程跟踪页提取后续人员,保留原iframe逻辑与通信机制,手动点击仍可正常显示。
// @author subk
// @match http://XXXXXX/newWorkSheet/*
// @match http://XXXXXX/OADocument/document/*
// @match http://XXXXXX/mocha.component.processtrack.v5/process/processinfo*
// @grant none
// @run-at document-end
// ==/UserScript==
(function () {
'use strict';
const TARGET_HANDLER_NAME = "XXX";
const ACTION_KEYWORD = "送办理";
// ================= 主页面逻辑 =================
if (location.pathname.includes('/newWorkSheet/') ||
location.pathname.includes('/OADocument/document/')) {
function waitForElement(selector, timeout = 15000) {
return new Promise((resolve, reject) => {
const element = document.querySelector(selector);
if (element) { resolve(element); return; }
const observer = new MutationObserver(() => {
const el = document.querySelector(selector);
if (el) { observer.disconnect(); resolve(el); }
});
observer.observe(document.body, { childList: true, subtree: true });
if (timeout > 0) {
setTimeout(() => { observer.disconnect(); reject(new Error(`Timeout waiting for ${selector}`)); }, timeout);
}
});
}
async function openHiddenProcessTrack() {
try {
const trackButton = await waitForElement('button[data-action="trace"]', 10000);
let trackUrl = trackButton.getAttribute('data-url');
if (!trackUrl) {
// 模拟点击获取真实URL
trackButton.click();
const iframeLayer = await waitForElement('.layui-layer-iframe iframe', 5000);
trackUrl = iframeLayer.src;
// 关闭弹窗
const closeBtn = document.querySelector('.layui-layer-close');
if (closeBtn) closeBtn.click();
}
// 创建隐藏 iframe
const hiddenIframe = document.createElement('iframe');
hiddenIframe.style.display = 'none';
hiddenIframe.src = trackUrl;
document.body.appendChild(hiddenIframe);
} catch (error) {
displayNames(['获取流程跟踪URL失败']);
}
}
function displayNames(names) {
if (!Array.isArray(names) || names.length === 0) {
names = ['未找到后续人员'];
}
const existingBox = document.getElementById('tm-next-handlers-display');
if (existingBox) existingBox.remove();
const displayBox = document.createElement('div');
displayBox.id = 'tm-next-handlers-display';
displayBox.style.cssText = 'position:fixed;top:10px;right:10px;background-color:#e8f4ff;border:1px solid #1890ff;border-radius:4px;padding:10px;z-index:999999;font-size:14px;box-shadow:0 2px 8px rgba(0,0,0,0.15);max-width:300px;word-wrap:break-word;font-family:monospace;';
displayBox.innerHTML = `<strong style="color:#1890ff;">${TARGET_HANDLER_NAME}${ACTION_KEYWORD}后续:</strong>
<br>` +
names.map(name => `<span style="display:inline-block;margin:3px 5px;background-color:#f0f0f0;padding:2px 5px;border-radius:3px;">${name}</span>`).join(' ');
document.body.appendChild(displayBox);
}
// 接收 iframe 发来的结果
window.addEventListener('message', (event) => {
if (event.data && event.data.type === 'tm-next-handlers') {
displayNames(event.data.names);
}
});
window.addEventListener('load', openHiddenProcessTrack);
}
// ================= iframe 页面逻辑 =================
if (location.pathname.includes('/mocha.component.processtrack.v5/process/processinfo')) {
// 在流程跟踪页执行原有提取逻辑
function extractNames() {
try {
const handlerSpans = document.querySelectorAll('span.handler');
for (let span of handlerSpans) {
if (span.textContent.trim() === TARGET_HANDLER_NAME) {
const handlerRow = span.closest('tr');
if (!handlerRow) continue;
let submitLink = null;
const nextRow = handlerRow.nextElementSibling;
if (nextRow) {
const linksInNextRow = nextRow.querySelectorAll('a.submit-path-link');
for (const link of linksInNextRow) {
if (link.textContent.includes(ACTION_KEYWORD)) {
submitLink = link; break;
}
}
}
if (!submitLink) {
const linksInRow = handlerRow.querySelectorAll('a.submit-path-link');
for (const link of linksInRow) {
if (link.textContent.includes(ACTION_KEYWORD)) {
submitLink = link; break;
}
}
}
if (submitLink) {
const onMouseOverAttr = submitLink.getAttribute('onmouseover');
if (onMouseOverAttr && onMouseOverAttr.startsWith('showTip')) {
const matches = onMouseOverAttr.match(/showTip\(\s*this\s*,\s*['"]([^'"]*)['"]\s*,\s*['"]([^'"]*)['"]\s*\)/);
if (matches && matches.length >= 3) {
const mc = matches[1], tiid = matches[2];
return fetchNextHandlers(mc, tiid);
}
}
}
}
}
return [];
} catch (e) {
return [];
}
}
function fetchNextHandlers(mc, tiid) {
try {
let basePath = '/mocha.component.processtrack.v5';
if (typeof window.FRAMEWORK_BASE_PATH !== 'undefined') {
basePath = window.FRAMEWORK_BASE_PATH;
}
const xhr = new XMLHttpRequest();
xhr.open('GET', `${basePath}/process/getNextHandlers?mc=${encodeURIComponent(mc)}&tiid=${encodeURIComponent(tiid)}`, false);
xhr.withCredentials = true;
xhr.send();
if (xhr.status === 200) {
const data = JSON.parse(xhr.responseText);
if (data.result === true && data.data && Array.isArray(data.data)) {
return data.data.map(item => item.handler).filter(Boolean);
}
}
} catch (e) {}
return [];
}
window.addEventListener('load', () => {
const names = extractNames();
// 发送给父页面
if (window.parent && window.parent !== window) {
window.parent.postMessage({ type: 'tm-next-handlers', names }, '*');
}
});
}
})();