// ==UserScript== // @name 腾讯会议智能操作 & 自动关闭 // @namespace https://meeting.tencent.com/ // @version 1.0.0 // @description 打开腾讯会议链接后:进行中→加入会议;未开始→添加到会议列表;操作后倒计时关闭页面(可取消) // @author bo Sea // @match https://meeting.tencent.com/dm/* // @match https://meeting.weixin.qq.com/dm/* // @grant window.close // @run-at document-idle // @license MIT // ==/UserScript== (function () { 'use strict'; const THRESHOLD = 5 * 60; const CLOSE_SEC = 5; let cancelFlag = false; let closeTimer = null; function injectStyle() { if (document.getElementById('tm-style')) return; const s = document.createElement('style'); s.id = 'tm-style'; s.textContent = ` @keyframes tm-in { from { transform: translateX(120%); opacity: 0 } to { transform: translateX(0); opacity: 1 } } #tm-box { position: fixed; top: 16px; right: 16px; z-index: 999999; width: 310px; border-radius: 12px; overflow: hidden; box-shadow: 0 8px 32px rgba(0,0,0,.2); font-family: system-ui, -apple-system, sans-serif; animation: tm-in .3s ease-out; } .tm-header { padding: 14px 18px; color: #fff; display: flex; align-items: center; gap: 10px; } .tm-header .tm-icon { font-size: 20px } .tm-header .tm-title { font-weight: 600; font-size: 15px } .tm-body { padding: 14px 18px; background: #fff; font-size: 13px; line-height: 1.8; color: #333; } .tm-subject { font-weight: 600 } .tm-code { color: #999; font-size: 12px } .tm-hint { color: #999; font-size: 12px; margin-top: 4px } .tm-status { margin-top: 6px } .tm-countdown { font-size: 20px; font-weight: 700; margin-top: 8px } .tm-bar { margin-top: 12px; padding: 8px 12px; background: #f5f5f5; border-radius: 6px; display: flex; align-items: center; justify-content: space-between; } .tm-bar .tm-sec { color: #e53935; font-weight: bold } .tm-cancel-btn { padding: 4px 14px; font-size: 12px; border: 1px solid #e53935; color: #e53935; border-radius: 4px; background: #fff; cursor: pointer; } .tm-cancel-btn:hover { background: #fce4ec } .tm-muted { color: #999 } .tm-green { color: #0f9d58 } .tm-amber { color: #f9a825 } `; document.head.appendChild(s); } function getData() { const el = id => document.getElementById(id); const txt = id => (el(id)?.textContent || '').trim(); let start = null; const dm = txt('tm-meeting-start-date').match(/(\d{4})\s*年\s*(\d{1,2})\s*月\s*(\d{1,2})\s*日/); const tm = txt('tm-meeting-start-time').match(/(\d{1,2}):(\d{2})/); if (dm && tm) start = new Date(+dm[1], dm[2] - 1, +dm[3], +tm[1], +tm[2]); return { state: txt('tm-meeting-state'), subject: txt('tm-meeting-subject') || '腾讯会议', code: txt('tm-meeting-code'), duration: txt('tm-meeting-duration'), dateStr: txt('tm-meeting-start-date'), timeStr: txt('tm-meeting-start-time'), start, }; } function toast(bgColor, icon, title, bodyHTML) { injectStyle(); let box = document.getElementById('tm-box'); if (!box) { box = document.createElement('div'); box.id = 'tm-box'; document.body.appendChild(box); } box.innerHTML = `