// ==UserScript== // @name 腾讯会议-录制批量导出 // @description 腾讯会议录制批量导出文档视频 // @namespace http://tampermonkey.net/ // @version 2024-04-01 // @description try to take over the world! // @author ss // @license MIT // @match https://meeting.tencent.com/user-center/meeting-record // @icon http://javatt.top:9000/musi/x.jpg // @grant none // @downloadURL https://update.greasyfork.icu/scripts/552870/%E8%85%BE%E8%AE%AF%E4%BC%9A%E8%AE%AE-%E5%BD%95%E5%88%B6%E6%89%B9%E9%87%8F%E5%AF%BC%E5%87%BA.user.js // @updateURL https://update.greasyfork.icu/scripts/552870/%E8%85%BE%E8%AE%AF%E4%BC%9A%E8%AE%AE-%E5%BD%95%E5%88%B6%E6%89%B9%E9%87%8F%E5%AF%BC%E5%87%BA.meta.js // ==/UserScript== (function () { 'use strict'; // ==================== 配置区域 ==================== // 目标元素选择器 const TARGET_SELECTOR = 'li'; // 目标元素文本内容 const TARGET_TEXT = '导出'; // 检查间隔隔(毫秒) const CHECK_INTERVAL = 1000; // 触发动作类型:'click'(点击), 'dblclick'(双击), 'hover'(悬停) const ACTION_TYPE = 'click'; // 是否在控制台显示日志 const SHOW_LOGS = true; // ================================================== // 全局变量 let foundAndClicked = false; /** * 弹出Element UI风格的消息 * @param msg 消息内容 * @param type 消息类型:success, warning, error, info * @param time 显示时长(毫秒) */ function msg(msg, type, time) { console.log(msg); // 消息类型配置 const typeConfig = { success: { backgroundColor: '#f0f9eb', borderColor: '#e1f3d8', textColor: '#67c23a', icon: '✓' }, warning: { backgroundColor: '#fdf6ec', borderColor: '#faecd8', textColor: '#e6a23c', icon: '⚠' }, error: { backgroundColor: '#fef0f0', borderColor: '#fde2e2', textColor: '#f56c6c', icon: '✗' }, info: { backgroundColor: '#f4f4f5', borderColor: '#ebeef5', textColor: '#909399', icon: 'i' } }; // 默认为信息类型 const config = typeConfig[type] || typeConfig.info; // 创建消息容器 let messageContainer = document.createElement("div"); messageContainer.className = "el-message"; messageContainer.innerHTML = ` ${config.icon}
${msg}
`; // 设置样式 Object.assign(messageContainer.style, { position: 'fixed', top: '20px', left: '50%', transform: 'translateX(-50%)', padding: '10px 16px', backgroundColor: config.backgroundColor, border: `1px solid ${config.borderColor}`, borderRadius: '4px', color: config.textColor, fontSize: '14px', zIndex: '9999', boxShadow: '0 2px 4px rgba(0, 0, 0, 0.12), 0 0 6px rgba(0, 0, 0, 0.04)', display: 'flex', alignItems: 'center', justifyContent: 'center', minWidth: '280px', maxWidth: '50%', transition: 'all 0.3s cubic-bezier(0.645, 0.045, 0.355, 1)', opacity: '0', marginTop: '-10px', boxSizing: 'border-box', textAlign: 'center' }); // 设置图标样式 const icon = messageContainer.querySelector('.el-message__icon'); if (icon) { Object.assign(icon.style, { marginRight: '8px', fontSize: '16px', fontWeight: 'bold' }); } time = time || 3000; // 将所有现有消息向下移动 const existingMessages = document.querySelectorAll('.el-message'); const messageHeight = 50; // 每条消息的高度(包括边距) existingMessages.forEach((msg, index) => { const currentTop = parseFloat(msg.style.top) || 20; msg.style.top = (currentTop + messageHeight) + 'px'; }); // 添加到页面 document.body.appendChild(messageContainer); // 触发动画 setTimeout(() => { messageContainer.style.opacity = '1'; messageContainer.style.marginTop = '0'; }, 10); // 消息自动消失 setTimeout(() => { // 淡出效果 messageContainer.style.opacity = '0'; messageContainer.style.marginTop = '-10px'; // 等待淡出动画完成后移除元素 setTimeout(() => { if (document.body.contains(messageContainer)) { document.body.removeChild(messageContainer); } // 重新调整剩余消息的位置 const remainingMessages = document.querySelectorAll('.el-message'); remainingMessages.forEach((msg, index) => { msg.style.top = (20 + index * messageHeight) + 'px'; }); }, 30); }, time); } // 初始化函数 function init() { msg('批量导出脚本已经加载'); addPanel('批量导出脚本'); appendButtonToPanel('开始导出', findSelected) } function addPanel(title) { const panel = document.createElement('div'); panel.id = 'myPanel'; panel.style.cssText = ` position: fixed; top: 30%; right: 30%; z-index: 9999; padding: 5px; background-color: aqua; border: 1px solid #ccc; border-radius: 4px; box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1); `; panel.innerHTML = `

${title}

`; // 可拖拽 // 拖拽功能 let isDragging = false; let offsetX, offsetY; panel.addEventListener('mousedown', function (e) { if (e.target === panel || e.target.id === 'myPanelTitle') { isDragging = true; offsetX = e.clientX - panel.getBoundingClientRect().left; offsetY = e.clientY - panel.getBoundingClientRect().top; panel.style.cursor = 'grabbing'; } }); document.addEventListener('mousemove', function (e) { if (!isDragging) return; const x = e.clientX - offsetX; const y = e.clientY - offsetY; // 限制在可视区域内 const maxX = window.innerWidth - panel.offsetWidth; const maxY = window.innerHeight - panel.offsetHeight; const boundedX = Math.max(0, Math.min(x, maxX)); const boundedY = Math.max(0, Math.min(y, maxY)); panel.style.left = boundedX + 'px'; panel.style.top = boundedY + 'px'; panel.style.right = 'auto'; }); document.addEventListener('mouseup', function () { if (isDragging) { isDragging = false; panel.style.cursor = 'move'; } }); document.body.appendChild(panel); } /** * 追加按钮 到面板 * @param text * @param callback */ function appendButtonToPanel(text, callback) { const button = document.createElement('button'); button.textContent = text || '导出'; button.style.padding = '5px 10px'; button.style.backgroundColor = '#4CAF50'; // 追加到面板内容中 document.getElementById('myPanelContent').appendChild(button); button.addEventListener('click', callback); } async function findSelected() { try { // 获取选中的行 const selectedRows = document.querySelectorAll('.RecordListTable_recordListRow__ysjYr.is-selected'); if (selectedRows.length === 0) { msg('请选择一个数据','warning'); return; } msg(`已选择 ${selectedRows.length} 条数据,开始处理...`); await sleep(2000); // 处理每条选中的数据 for (let i = 0; i < selectedRows.length; i++) { const row = selectedRows[i]; const rowIndex = i + 1; try { msg(`开始处理第 ${rowIndex} 个数据`); // 在当前行内查找复制图标,避免全局查找 const icon = row.querySelector('.met-icon-more--outlined'); // 在当前行内查找复制图标,避免全局查找 if (!icon) { msg('未查询到icon','warning'); } // 执行悬停操作 performAction(icon, 'hover'); // 等待下拉菜单显示 await sleep(600); // 查找并点击导出选项 checkAndClickElement('li', "导出", 'click'); performAction(icon, 'leave'); // 等待下一个操作 await sleep(700); } catch (error) { msg(`第 ${rowIndex} 个数据:处理出错 - ${error.message}`,'error'); // 继续处理下一个数据 } } msg('所有选中数据处理完成'); } catch (error) { msg(`处理过程中发生错误:${error.message}`); } } function sleep(ms) { return new Promise(resolve => setTimeout(resolve, ms)); } /** * 检查并点击元素 * @param target_select 目标 选择器 * @param target_text 目标 文本 * @param action_type 操作类型 */ function checkAndClickElement(target_select, target_text, action_type) { try { // 如果已经找到并点击过,不再检查 if (foundAndClicked) return; // 使用选择器查找元素 const elements = document.querySelectorAll(target_select); if (elements.length === 0) { log('未找到匹配选择器的元素: ' + target_select); return; } // 遍历元素查找包含目标文本的元素 let foundElement = null; elements.forEach(element => { if (element.textContent.trim() === target_text) { foundElement = element; } }); if (foundElement) { log('找到目标元素: ' + target_select + ' 文本: ' + target_text); // 执行指定的动作 performAction(foundElement, action_type); // 标记为已找到并点击,防止重复操作 foundAndClicked = false; // 可以选择停止监听或继续 // stopListening(); } else { log('找到 ' + elements.length + ' 个匹配选择器的元素,但未找到包含文本 "' + target_text + '" 的元素'); } } catch (error) { log('检查元素时发生错误: ' + error.message, 'error'); } } /** * 执行动作 * @param element 目标元素 * @param actionType 动作类型 click | dblclick | hover */ function performAction(element, actionType) { switch (actionType) { case 'click': element.click(); break; case 'dblclick': element.dispatchEvent(new Event('dblclick')); break; case 'hover': const event = new MouseEvent('mouseover', { bubbles: true, cancelable: true, view: window }); element.dispatchEvent(event); break; // 移走 case 'leave': const leaveEvent = new MouseEvent('mouseout', { bubbles: true, cancelable: true, view: window }) element.dispatchEvent(leaveEvent); } } // 日志函数 function log(message, type = 'info') { if (!SHOW_LOGS) return; const now = new Date(); const timeString = now.toLocaleTimeString(); let prefix = '[自动点击工具]'; let consoleMethod = console.log; if (type === 'error') { consoleMethod = console.error; prefix = '[自动点击工具-错误]'; } else if (type === 'warning') { consoleMethod = console.warn; prefix = '[自动点击工具-警告]'; } consoleMethod(`%c${prefix} [${timeString}] ${message}`, 'color: #4285F4; font-weight: bold;'); } // 页面加载完成后初始化 window.addEventListener('load', function () { init(); }); })();