MonkeyModifier

Change webpage content

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

  1. // ==UserScript==
  2. // @name MonkeyModifier
  3. // @namespace https://github.com/JiyuShao/greasyfork-scripts
  4. // @version 2024-08-20
  5. // @description Change webpage content
  6. // @author Jiyu Shao <jiyu.shao@gmail.com>
  7. // @license MIT
  8. // @match *://*/*
  9. // @run-at document-start
  10. // @grant unsafeWindow
  11. // ==/UserScript==
  12.  
  13. (function () {
  14. 'use strict';
  15. // ################### common tools
  16. function querySelectorAllWithCurrentNode(node, querySelector) {
  17. let result = [];
  18. if (node.matches(querySelector)) {
  19. result.push(node);
  20. }
  21. result = [...result, ...node.querySelectorAll(querySelector)];
  22. return result;
  23. }
  24.  
  25. function formatTimestamp(timestamp) {
  26. // 创建 Date 对象
  27. const date = new Date(timestamp);
  28.  
  29. // 获取年、月、日、小时、分钟、秒
  30. const year = date.getFullYear();
  31. const month = String(date.getMonth() + 1).padStart(2, '0'); // 月份从 0 开始,所以需要 +1
  32. const day = String(date.getDate()).padStart(2, '0');
  33. const hours = String(date.getHours()).padStart(2, '0');
  34. const minutes = String(date.getMinutes()).padStart(2, '0');
  35. const seconds = String(date.getSeconds()).padStart(2, '0');
  36.  
  37. // 拼接日期和时间
  38. return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`;
  39. }
  40. function replaceTextInNode(node, originalText, replaceText) {
  41. // 如果当前节点是文本节点并且包含 originalText
  42. if (node instanceof Text && node.textContent.includes(originalText)) {
  43. // 替换文本
  44. node.textContent = node.textContent.replace(originalText, replaceText);
  45. }
  46.  
  47. // 如果当前节点有子节点,递归处理每个子节点
  48. if (node.hasChildNodes()) {
  49. node.childNodes.forEach((child) => {
  50. replaceTextInNode(child, originalText, replaceText);
  51. });
  52. }
  53. }
  54.  
  55. function registerMutationObserver(node, config = {}, options = {}) {
  56. const finalConfig = {
  57. attributes: false,
  58. childList: true,
  59. subtree: true,
  60. ...config,
  61. };
  62.  
  63. const finalOptions = {
  64. // 元素的属性发生了变化
  65. attributes: options.attributes || [],
  66. // 子节点列表发生了变化
  67. childList: {
  68. addedNodes:
  69. options.childList.addedNodes ||
  70. [
  71. // {
  72. // filter: (node) => {},
  73. // action: (node) => {},
  74. // }
  75. ],
  76. removedNodes: options.childList.removedNodes || [],
  77. },
  78. // 文本节点的内容发生了变化
  79. characterData: options.characterData || [],
  80. };
  81.  
  82. const observer = new MutationObserver((mutationsList, _observer) => {
  83. mutationsList.forEach((mutation) => {
  84. if (mutation.type === 'attributes') {
  85. finalOptions.attributes.forEach(({ filter, action }) => {
  86. try {
  87. if (filter(mutation.target, mutation)) {
  88. action(mutation.target, mutation);
  89. }
  90. } catch (error) {
  91. console.error(
  92. 'MutationObserver attributes callback failed:',
  93. mutation.target,
  94. error
  95. );
  96. }
  97. });
  98. }
  99. if (mutation.type === 'childList') {
  100. // 检查是否有新增的元素
  101. mutation.addedNodes.forEach((node) => {
  102. finalOptions.childList.addedNodes.forEach(({ filter, action }) => {
  103. try {
  104. if (
  105. [Node.TEXT_NODE, Node.COMMENT_NODE].includes(node.nodeType)
  106. ) {
  107. return;
  108. }
  109. if (filter(node, mutation)) {
  110. action(node, mutation);
  111. }
  112. } catch (error) {
  113. console.error(
  114. 'MutationObserver childList.addedNodes callback failed:',
  115. node,
  116. error
  117. );
  118. }
  119. });
  120. });
  121.  
  122. // 检查是否有删除元素
  123. mutation.removedNodes.forEach((node) => {
  124. finalOptions.childList.removedNodes.forEach((filter, action) => {
  125. try {
  126. if (
  127. [Node.TEXT_NODE, Node.COMMENT_NODE].includes(node.nodeType)
  128. ) {
  129. return;
  130. }
  131. if (filter(node, mutation)) {
  132. action(node, mutation);
  133. }
  134. } catch (error) {
  135. console.error(
  136. 'MutationObserver childList.removedNodes callback failed:',
  137. node,
  138. error
  139. );
  140. }
  141. });
  142. });
  143. }
  144. if (mutation.type === 'characterData') {
  145. finalOptions.characterData.forEach(({ filter, action }) => {
  146. try {
  147. if (filter(mutation.target, mutation)) {
  148. action(mutation.target, mutation);
  149. }
  150. } catch (error) {
  151. console.error(
  152. 'MutationObserver characterData callback failed:',
  153. mutation.target,
  154. error
  155. );
  156. }
  157. });
  158. }
  159. });
  160. });
  161. observer.observe(node, finalConfig);
  162. return observer;
  163. }
  164.  
  165. function registerFetchModifier(modifierList) {
  166. const originalFetch = unsafeWindow.fetch;
  167. unsafeWindow.fetch = function (url, options) {
  168. let finalUrl = url;
  169. let finalOptions = { ...options };
  170. let finalResult = null;
  171. const matchedModifierList = modifierList.filter((e) =>
  172. e.test(finalUrl, finalOptions)
  173. );
  174. for (const currentModifier of matchedModifierList) {
  175. if (currentModifier.prerequest) {
  176. [finalUrl, finalOptions] = currentModifier.prerequest(
  177. finalUrl,
  178. finalOptions
  179. );
  180. }
  181. }
  182. finalResult = originalFetch(finalUrl, finalOptions);
  183. for (const currentModifier of matchedModifierList) {
  184. if (currentModifier.preresponse) {
  185. finalResult = currentModifier.preresponse(finalResult);
  186. }
  187. }
  188. return finalResult;
  189. };
  190. }
  191.  
  192. function registerXMLHttpRequestPolyfill() {
  193. // 保存原始的 XMLHttpRequest 构造函数
  194. const originalXMLHttpRequest = unsafeWindow.XMLHttpRequest;
  195.  
  196. // 定义新的 XMLHttpRequest 构造函数
  197. unsafeWindow.XMLHttpRequest = class extends originalXMLHttpRequest {
  198. constructor() {
  199. super();
  200. this._responseType = ''; // 存储 responseType
  201. this._onreadystatechange = null; // 存储 onreadystatechange 函数
  202. this._onload = null; // 存储 onload 函数
  203. this._onloadend = null; // 存储 onloadend 函数
  204. this._sendData = null; // 存储 send 方法的数据
  205. this._headers = {}; // 存储请求头
  206. this._method = null; // 存储请求方法
  207. this._url = null; // 存储请求 URL
  208. this._async = true; // 存储异步标志
  209. this._user = null; // 存储用户名
  210. this._password = null; // 存储密码
  211. this._readyState = XMLHttpRequest.UNSENT; // 存储 readyState
  212. this._status = 0; // 存储状态码
  213. this._statusText = ''; // 存储状态文本
  214. this._response = null; // 存储响应对象
  215. this._responseText = ''; // 存储响应文本
  216. this._responseURL = ''; // 存储响应 URL
  217. this._responseHeaders = null; // 存储响应头
  218. }
  219.  
  220. get open() {
  221. return this._open;
  222. }
  223. set open(value) {}
  224.  
  225. _open(method, url, async = true, user = null, password = null) {
  226. this._method = method;
  227. this._url = url;
  228. this._async = async;
  229. this._user = user;
  230. this._password = password;
  231. this._readyState = XMLHttpRequest.OPENED;
  232. }
  233.  
  234. get send() {
  235. return this._send;
  236. }
  237. set send(value) {}
  238. _send(data) {
  239. this._sendData = data;
  240. this._sendRequest();
  241. }
  242.  
  243. _sendRequest() {
  244. const self = this;
  245.  
  246. // 根据 responseType 设置 fetch 的返回类型
  247. const fetchOptions = {
  248. method: this._method,
  249. headers: new Headers(this._headers),
  250. credentials: this.withCredentials ? 'include' : 'same-origin',
  251. body: this._sendData || undefined,
  252. };
  253.  
  254. // 发送 fetch 请求
  255. return unsafeWindow
  256. .fetch(this._url, fetchOptions)
  257. .then((response) => {
  258. self._response = response;
  259. self._status = response.status;
  260. self._statusText = response.statusText;
  261. self._responseHeaders = response.headers;
  262. self._readyState = XMLHttpRequest.DONE;
  263. self._responseURL = self._url;
  264. const responseType = self._responseType || 'text';
  265. // 设置响应类型
  266. switch (responseType) {
  267. case 'json':
  268. return response.json().then((json) => {
  269. self._responseText = JSON.stringify(json);
  270. self._response = json;
  271. self._onreadystatechange && self._onreadystatechange();
  272. self._onload && self._onload();
  273. self._onloadend && self._onloadend();
  274. });
  275. case 'text':
  276. return response.text().then((text) => {
  277. self._responseText = text;
  278. self._response = text;
  279. self._onreadystatechange && self._onreadystatechange();
  280. self._onload && self._onload();
  281. self._onloadend && self._onloadend();
  282. });
  283. case 'blob':
  284. return response.blob().then((blob) => {
  285. self._response = blob;
  286. self._onreadystatechange && self._onreadystatechange();
  287. self._onload && self._onload();
  288. self._onloadend && self._onloadend();
  289. });
  290. }
  291. })
  292. .catch((error) => {
  293. self._readyState = XMLHttpRequest.DONE;
  294. self._status = 0;
  295. self._statusText = 'Network Error';
  296. self._onreadystatechange && self._onreadystatechange();
  297. self._onload && self._onload();
  298. });
  299. }
  300.  
  301. setRequestHeader(name, value) {
  302. this._headers[name] = value;
  303. return this;
  304. }
  305.  
  306. getResponseHeader(name) {
  307. return this._responseHeaders ? this._responseHeaders.get(name) : null;
  308. }
  309.  
  310. getAllResponseHeaders() {
  311. return this._responseHeaders
  312. .entries()
  313. .reduce((result, [name, value]) => {
  314. return result + `${name}: ${value}\r\n`;
  315. }, '');
  316. }
  317.  
  318. set onreadystatechange(callback) {
  319. this._onreadystatechange = callback;
  320. }
  321.  
  322. set onload(callback) {
  323. this._onload = callback;
  324. }
  325.  
  326. set onloadend(callback) {
  327. this._onloadend = callback;
  328. }
  329.  
  330. get readyState() {
  331. return this._readyState;
  332. }
  333.  
  334. set readyState(state) {
  335. this._readyState = state;
  336. }
  337.  
  338. get response() {
  339. return this._response;
  340. }
  341.  
  342. set response(value) {
  343. this._response = value;
  344. }
  345.  
  346. get responseText() {
  347. return this._responseText;
  348. }
  349.  
  350. set responseText(value) {
  351. this._responseText = value;
  352. }
  353.  
  354. get responseURL() {
  355. return this._responseURL;
  356. }
  357.  
  358. set responseURL(value) {
  359. this._responseURL = value;
  360. }
  361.  
  362. get status() {
  363. return this._status;
  364. }
  365.  
  366. set status(value) {
  367. this._status = value;
  368. }
  369.  
  370. get statusText() {
  371. return this._statusText;
  372. }
  373.  
  374. set statusText(value) {
  375. this._statusText = value;
  376. }
  377.  
  378. get responseType() {
  379. return this._responseType;
  380. }
  381.  
  382. set responseType(type) {
  383. this._responseType = type;
  384. }
  385. };
  386. }
  387.  
  388. function downloadCSV(arrayOfData, filename) {
  389. // 处理数据,使其适合 CSV 格式
  390. const csvContent = arrayOfData
  391. .map((row) =>
  392. row.map((cell) => `"${(cell || '').replace(/"/g, '""')}"`).join(',')
  393. )
  394. .join('\n');
  395.  
  396. // 在 CSV 内容前加上 BOM
  397. const bom = '\uFEFF';
  398. const csvContentWithBOM = bom + csvContent;
  399.  
  400. // 将内容转换为 Blob
  401. const blob = new Blob([csvContentWithBOM], {
  402. type: 'text/csv;charset=utf-8;',
  403. });
  404.  
  405. // 创建一个隐藏的可下载链接
  406. const url = URL.createObjectURL(blob);
  407. const link = document.createElement('a');
  408. link.href = url;
  409. link.setAttribute('download', `${filename}.csv`); // 指定文件名
  410. document.body.appendChild(link);
  411. link.click(); // 触发点击事件
  412. document.body.removeChild(link); // 清除链接
  413. URL.revokeObjectURL(url); // 释放 URL 对象
  414. }
  415.  
  416. // ################### 加载前插入样式覆盖
  417. const style = document.createElement('style');
  418. const cssRules = `
  419. .dropdown-submenu--viewmode {
  420. display: none !important;
  421. }
  422. [field=modified] {
  423. display: none !important;
  424. }
  425.  
  426. [data-value=modified] {
  427. display: none !important;
  428. }
  429. [data-value=lastmodify] {
  430. display: none !important;
  431. }
  432.  
  433. [data-grid-field=modified] {
  434. display: none !important;
  435. }
  436.  
  437. [data-field-key=modified] {
  438. display: none !important;
  439. }
  440.  
  441. #Revisions {
  442. display: none !important;
  443. }
  444.  
  445. #ContentModified {
  446. display: none !important;
  447. }
  448.  
  449. [title="最后修改时间"] {
  450. display: none !important;
  451. }
  452.  
  453. .left-tree-bottom__manager-company--wide {
  454. display: none !important;
  455. }
  456.  
  457. .left-tree-narrow .left-tree-bottom__personal--icons > a:nth-child(1) {
  458. display: none !important;
  459. }
  460.  
  461. .data_handover_card {
  462. display: none !important;
  463. }
  464.  
  465. .dtd-select-item-option[label='管理组'] {
  466. display: none !important;
  467. }
  468.  
  469. .data-manage-bar-actions > div:nth-child(2) > div.ant-space-item:nth-child(2) {
  470. display: none !important;
  471. }
  472.  
  473. .data-manage-bar-actions > div:nth-child(2) > div.ant-space-item:nth-child(3) {
  474. display: none !important;
  475. }
  476.  
  477. .approve-box .pure-form-container .department-field-view {
  478. display: none !important;
  479. }
  480.  
  481. .approve-box .pure-form-container > div:nth-child(2) {
  482. padding: 0 !important;
  483. }
  484. `;
  485. style.appendChild(document.createTextNode(cssRules));
  486. unsafeWindow.document.head.appendChild(style);
  487.  
  488. // ################### 网页内容加载完成立即执行脚本
  489. unsafeWindow.addEventListener('DOMContentLoaded', function () {
  490. // 监听任务右侧基本信息
  491. const taskRightInfoEles =
  492. unsafeWindow.document.querySelectorAll('#ContentModified');
  493. taskRightInfoEles.forEach((element) => {
  494. const parentDiv = element.closest('div.left_3_col');
  495. if (parentDiv) {
  496. parentDiv.style.display = 'none';
  497. }
  498. });
  499. });
  500.  
  501. // ################### 加载完成动态监听
  502. unsafeWindow.addEventListener('load', function () {
  503. registerMutationObserver(
  504. unsafeWindow.document.body,
  505. {
  506. attributes: false,
  507. childList: true,
  508. subtree: true,
  509. },
  510. {
  511. childList: {
  512. addedNodes: [
  513. // 动态文本替换问题
  514. {
  515. filter: (node, _mutation) => {
  516. return node.textContent.includes('最后修改时间');
  517. },
  518. action: (node, _mutation) => {
  519. replaceTextInNode(node, '最后修改时间', '迭代修改时间');
  520. },
  521. },
  522. // 监听动态弹窗 隐藏设置列表字段-最后修改时间左侧
  523. {
  524. filter: (node, _mutation) => {
  525. return (
  526. node.querySelectorAll('input[value=modified]').length > 0
  527. );
  528. },
  529. action: (node, _mutation) => {
  530. node
  531. .querySelectorAll('input[value=modified]')
  532. .forEach((ele) => {
  533. const parentDiv = ele.closest('div.field');
  534. if (parentDiv) {
  535. parentDiv.style.display = 'none';
  536. }
  537. });
  538. },
  539. },
  540. // 监听动态弹窗 隐藏设置列表字段-最后修改时间右侧
  541. {
  542. filter: (node, _mutation) => {
  543. return (
  544. node.querySelectorAll('span[title=最后修改时间]').length > 0
  545. );
  546. },
  547. action: (node, _mutation) => {
  548. node
  549. .querySelectorAll('span[title=最后修改时间]')
  550. .forEach((ele) => {
  551. const parentDiv = ele.closest('div[role=treeitem]');
  552. if (parentDiv) {
  553. parentDiv.style.display = 'none';
  554. }
  555. });
  556. },
  557. },
  558. // 监听企业微信导出按钮
  559. {
  560. filter: (node, _mutation) => {
  561. return node.querySelectorAll('.js_export').length > 0;
  562. },
  563. action: (node, _mutation) => {
  564. function convertTimestampToTime(timestamp) {
  565. // 创建 Date 对象
  566. const date = new Date(timestamp * 1000); // Unix 时间戳是以秒为单位,而 Date 需要毫秒
  567.  
  568. // 获取小时和分钟
  569. const hours = date.getHours();
  570. const minutes = date.getMinutes();
  571.  
  572. // 确定上午还是下午
  573. const amPm = hours >= 12 ? '下午' : '上午';
  574.  
  575. // 返回格式化的字符串
  576. return `${amPm}${hours}:${minutes
  577. .toString()
  578. .padStart(2, '0')}`;
  579. }
  580. node.querySelectorAll('.js_export').forEach((ele) => {
  581. if (ele.dataset.eventListener === 'true') {
  582. return;
  583. }
  584. ele.dataset.eventListener = 'true';
  585. ele.addEventListener('click', async function (event) {
  586. event.preventDefault();
  587. event.stopPropagation();
  588. const response = await unsafeWindow.fetch(
  589. '/wework_admin/getAdminOperationRecord?lang=zh_CN&f=json&ajax=1&timeZoneInfo%5Bzone_offset%5D=-8',
  590. {
  591. headers: {
  592. 'content-type': 'application/x-www-form-urlencoded',
  593. },
  594. body: unsafeWindow.fetchTmpBody,
  595. method: 'POST',
  596. mode: 'cors',
  597. credentials: 'include',
  598. }
  599. );
  600. const responseJson = await response.json();
  601. const excelData = responseJson.data.operloglist.reduce(
  602. (result, current) => {
  603. const typeMapping = {
  604. 9: '新增部门',
  605. 10: '删除部门',
  606. 11: '移动部门',
  607. 13: '删除成员',
  608. 14: '新增成员',
  609. 15: '更改成员信息',
  610. 21: '更改部门信息',
  611. 23: '登录后台',
  612. 25: '发送邀请',
  613. 36: '修改管理组管理员列表',
  614. 35: '修改管理组应用权限',
  615. 34: '修改管理组通讯录权限',
  616. 88: '修改汇报规则',
  617. 120: '导出相关操作记录',
  618. 162: '批量设置成员信息',
  619. };
  620. const optTypeArray = {
  621. 0: '全部',
  622. 3: '成员与部门变更',
  623. 2: '权限管理变更',
  624. 12: '企业信息管理',
  625. 11: '通讯录与聊天管理',
  626. 13: '外部联系人管理',
  627. 8: '应用变更',
  628. 7: '其他',
  629. };
  630. return [
  631. ...result,
  632. [
  633. convertTimestampToTime(current.operatetime),
  634. current.op_name,
  635. optTypeArray[current.type_oper_1],
  636. typeMapping[current.type] || '其他',
  637. current.data,
  638. current.ip,
  639. ],
  640. ];
  641. },
  642. [
  643. [
  644. '时间',
  645. '操作者',
  646. '操作类型',
  647. '操作行为',
  648. '相关数据',
  649. '操作者IP',
  650. ],
  651. ]
  652. );
  653. downloadCSV(excelData, '管理端操作记录');
  654. });
  655. });
  656. },
  657. },
  658. // 监听钉钉首页-部门修改次数
  659. {
  660. filter: (node, _mutation) => {
  661. const spanDoms = Array.from(
  662. node.querySelectorAll('.admin-panel-v2-module span')
  663. );
  664. return (
  665. spanDoms.filter((e) =>
  666. ['近1月部门修改次数'].includes(e.innerText)
  667. ).length > 0 ||
  668. spanDoms.filter((e) => e.innerText.includes('项指标预警'))
  669. .length > 0
  670. );
  671. },
  672. action: (node, _mutation) => {
  673. const spanDoms = Array.from(
  674. node.querySelectorAll('.admin-panel-v2-module span')
  675. );
  676. spanDoms
  677. .filter((e) => ['近1月部门修改次数'].includes(e.innerText))
  678. .forEach((ele) => {
  679. const parentDiv = ele.parentElement.parentElement;
  680. if (parentDiv) {
  681. parentDiv.childNodes[1].childNodes[0].innerText = 1;
  682. parentDiv.childNodes[1].childNodes[3].style.display =
  683. 'none';
  684. }
  685. });
  686. spanDoms
  687. .filter((e) => e.innerText.includes('项指标预警'))
  688. .forEach((ele) => {
  689. const parentDiv = ele.closest('div');
  690. if (parentDiv) {
  691. parentDiv.style.display = 'none';
  692. }
  693. });
  694. },
  695. },
  696. // 监听钉钉-智能人事花名册成长记录
  697. {
  698. filter: (node, _mutation) => {
  699. return (
  700. Array.from(node.querySelectorAll('.growth-recorder-list'))
  701. .length > 0
  702. );
  703. },
  704. action: (node, _mutation) => {
  705. function isAfterDate(dateString) {
  706. // 将输入的日期字符串转换为 Date 对象
  707. const inputDate = new Date(dateString);
  708.  
  709. // 创建一个表示 2024 年 8 月 12 日的 Date 对象
  710. const august12_2024 = new Date(2024, 7, 11); // 注意:月份是从 0 开始计数的
  711.  
  712. // 比较两个日期
  713. return inputDate > august12_2024;
  714. }
  715. Array.from(
  716. node.querySelectorAll('.growth-recorder-list > li')
  717. ).forEach((ele) => {
  718. const time = ele.querySelector(
  719. '.growth-recorder-time'
  720. ).innerText;
  721. const title = ele.querySelector(
  722. '.growth-recorder-c-title'
  723. ).innerText;
  724.  
  725. if (title.includes('调岗') && isAfterDate(time)) {
  726. ele.style.display = 'none';
  727. }
  728. });
  729. },
  730. },
  731. // 监听钉钉审计日志-导出按钮
  732. {
  733. filter: (node, _mutation) => {
  734. return (
  735. node.querySelectorAll(
  736. '.audit-content .dd-toolbar-btns-container .dd-toolbar-action-btns > div:nth-child(2) button'
  737. ).length > 0
  738. );
  739. },
  740. action: (node, _mutation) => {
  741. node
  742. .querySelectorAll(
  743. '.audit-content .dd-toolbar-btns-container .dd-toolbar-action-btns > div:nth-child(2) button'
  744. )
  745. .forEach((ele) => {
  746. if (ele.dataset.eventListener === 'true') {
  747. return;
  748. }
  749. ele.dataset.eventListener = 'true';
  750. ele.addEventListener('click', async function (event) {
  751. event.preventDefault();
  752. event.stopPropagation();
  753. function getAllCookies() {
  754. const cookiesArray = document.cookie.split('; ');
  755. const cookiesObj = {};
  756. cookiesArray.forEach((cookie) => {
  757. const parts = cookie.split('=');
  758. cookiesObj[parts[0]] = decodeURIComponent(parts[1]);
  759. });
  760. return cookiesObj;
  761. }
  762. const response = await unsafeWindow.fetch(
  763. unsafeWindow.fetchTmpUrl,
  764. {
  765. headers: {
  766. accept: 'application/json, text/plain, */*',
  767. 'x-csrf-token': getAllCookies()['csrf_token'],
  768. },
  769. body: null,
  770. method: 'GET',
  771. mode: 'cors',
  772. credentials: 'include',
  773. }
  774. );
  775. const responseJson = await response.json();
  776. const excelData = responseJson.result.reduce(
  777. (result, current) => {
  778. return [
  779. ...result,
  780. [
  781. formatTimestamp(current.opTime),
  782. current.opName,
  783. current.object.categoryValue,
  784. current.type.categoryValue,
  785. current.content || '',
  786. ],
  787. ];
  788. },
  789. [['时间', '操作者', '事件对象', '事件类型', '详细数据']]
  790. );
  791. downloadCSV(excelData, '审计日志信息');
  792. });
  793. });
  794. },
  795. },
  796. ],
  797. },
  798. }
  799. );
  800. });
  801.  
  802. // ################### 替换请求
  803. if (
  804. unsafeWindow.location.pathname.startsWith('/wework_admin') &&
  805. !unsafeWindow.location.href.includes('loginpage_wx')
  806. ) {
  807. registerFetchModifier([
  808. {
  809. test: (url, options) => {
  810. return url.includes('/wework_admin/getAdminOperationRecord');
  811. },
  812. prerequest: (url, options) => {
  813. options.body = options.body
  814. .split('&')
  815. .reduce((result, current) => {
  816. let [key, value] = current.split('=');
  817. if (key === 'limit') {
  818. value = 500;
  819. }
  820. return [...result, `${key}=${value}`];
  821. }, [])
  822. .join('&');
  823. unsafeWindow.fetchTmpBody = options.body;
  824. return [url, options];
  825. },
  826. preresponse: async (responsePromise) => {
  827. const response = await responsePromise;
  828. let responseJson = await response.json();
  829. responseJson.data.operloglist = responseJson.data.operloglist.filter(
  830. (currentData) => {
  831. if (currentData.type_oper_1 === 3) {
  832. return false;
  833. }
  834. const contentFilterFlag = [
  835. '曾建培',
  836. '张杨洁',
  837. '梁博心',
  838. '李铭',
  839. '刘丽平',
  840. '刘志强',
  841. '冯茜茜',
  842. '吴慧颍',
  843. '吕昱燕',
  844. '李海粤',
  845. '𡈼满',
  846. '冯艺敏',
  847. '陈祁峰',
  848. '张鹏',
  849. '黎耀豪',
  850. '孙佩文',
  851. '周琦',
  852. '李嘉龙',
  853. '李佳玮',
  854. ].reduce((result, current) => {
  855. if (!result) {
  856. return false;
  857. }
  858. return !(currentData.data || '').includes(current);
  859. }, true);
  860. if (!contentFilterFlag) {
  861. return false;
  862. }
  863. return true;
  864. }
  865. );
  866. responseJson.data.total = responseJson.data.operloglist.length;
  867. return new Response(JSON.stringify(responseJson), {
  868. headers: response.headers,
  869. ok: response.ok,
  870. redirected: response.redirected,
  871. status: response.status,
  872. statusText: response.statusText,
  873. type: response.type,
  874. url: response.url,
  875. });
  876. },
  877. },
  878. ]);
  879. registerXMLHttpRequestPolyfill();
  880. }
  881.  
  882. if (unsafeWindow.location.pathname.startsWith('/adminData.htm')) {
  883. registerFetchModifier([
  884. {
  885. test: (url, options) => {
  886. return url.includes('/omp/lwpV2?key=listOpLog');
  887. },
  888. prerequest: (url, options) => {
  889. const finalUrl = url
  890. .split('&')
  891. .reduce((result, current) => {
  892. let [key, value] = current.split('=');
  893. if (key === 'args') {
  894. const parsedValue = JSON.parse(decodeURIComponent(value));
  895. parsedValue[2] = 1000;
  896. value = encodeURIComponent(JSON.stringify(parsedValue));
  897. }
  898. return [...result, `${key}=${value}`];
  899. }, [])
  900. .join('&');
  901. unsafeWindow.fetchTmpUrl = finalUrl;
  902. return [finalUrl, options];
  903. },
  904. preresponse: async (responsePromise) => {
  905. const response = await responsePromise;
  906. let responseJson = await response.json();
  907. responseJson.result = responseJson.result.filter((currentData) => {
  908. if (
  909. ['删除部门', '添加部门', '部门名称修改'].includes(
  910. currentData.type.categoryValue
  911. )
  912. ) {
  913. return false;
  914. }
  915. if (
  916. ['微应用修改'].includes(currentData.type.categoryValue) &&
  917. ['马浩然', '曹宁'].includes(currentData.opName)
  918. ) {
  919. return false;
  920. }
  921. if (
  922. ['智能人事', '管理组'].includes(currentData.object.categoryValue)
  923. ) {
  924. return false;
  925. }
  926. if (
  927. ['通讯录'].includes(currentData.object.categoryValue) &&
  928. formatTimestamp(currentData.opTime).includes('2024-08-20')
  929. ) {
  930. return false;
  931. }
  932.  
  933. const contentFilterFlag = [
  934. '曾建培',
  935. '张杨洁',
  936. '梁博心',
  937. '李铭',
  938. '刘丽平',
  939. '刘志强',
  940. '冯茜茜',
  941. '吴慧颍',
  942. '吕昱燕',
  943. '李海粤',
  944. '𡈼满',
  945. '冯艺敏',
  946. '陈祁峰',
  947. '张鹏',
  948. '黎耀豪',
  949. '孙佩文',
  950. '周琦',
  951. '李嘉龙',
  952. '李佳玮',
  953. ].reduce((result, current) => {
  954. if (!result) {
  955. return false;
  956. }
  957. return !(currentData.content || '').includes(current);
  958. }, true);
  959. if (!contentFilterFlag) {
  960. return false;
  961. }
  962. return true;
  963. });
  964. return new Response(JSON.stringify(responseJson), {
  965. headers: response.headers,
  966. ok: response.ok,
  967. redirected: response.redirected,
  968. status: response.status,
  969. statusText: response.statusText,
  970. type: response.type,
  971. url: response.url,
  972. });
  973. },
  974. },
  975. ]);
  976. registerXMLHttpRequestPolyfill();
  977. }
  978. })();