// ==UserScript==
// @name 文档复制助手Plus复制后有标题时间(支持生财有术、小报童、飞书文档)
// @namespace http://tampermonkey.net/
// @version 3.12
// @description 让飞书文档更好用:添加标题和时间、解除复制限制、支持右键菜单
// @author 微信11208596
// @match *://*.feishu.cn/*
// @match *://*.larkoffice.com/*
// @match *://scys.com/*
// @match *://xiaobot.net/*
// @grant none
// @run-at document-start
// @license UNLICENSED
// ==/UserScript==
(function() {
'use strict';
// 覆盖事件监听器以处理复制和右键菜单事件
const overrideEventListeners = () => {
const rawAddEventListener = EventTarget.prototype.addEventListener;
EventTarget.prototype.addEventListener = function (type, listener, options) {
if (type === 'copy') {
rawAddEventListener.call(this, type, event => {
event.stopImmediatePropagation();
return null;
}, options);
return;
}
if (type === 'contextmenu') {
rawAddEventListener.call(this, type, event => {
event.stopImmediatePropagation();
return listener(event);
}, options);
return;
}
rawAddEventListener.call(this, type, listener, options);
};
};
// 覆盖XMLHttpRequest以修改权限响应
const overrideXHR = () => {
const rawOpen = XMLHttpRequest.prototype.open;
XMLHttpRequest.prototype.open = function (method, url, ...rest) {
this.addEventListener('readystatechange', function () {
if (this.readyState === 4 && url.includes('space/api/suite/permission/document/actions/state/')) {
let response = this.responseText;
try {
response = JSON.parse(response);
if (response.data && response.data.actions && response.data.actions.copy !== 1) {
response.data.actions.copy = 1;
Object.defineProperty(this, 'responseText', { value: JSON.stringify(response) });
Object.defineProperty(this, 'response', { value: response });
}
} catch (e) {
console.log('修改响应失败:', e);
}
}
}, false);
rawOpen.call(this, method, url, ...rest);
};
};
// 获取格式化的当前时间
function getFormattedTime() {
const now = new Date();
const year = now.getFullYear();
const month = String(now.getMonth() + 1).padStart(2, '0');
const day = String(now.getDate()).padStart(2, '0');
const hours = String(now.getHours()).padStart(2, '0');
const minutes = String(now.getMinutes()).padStart(2, '0');
return `${year}-${month}-${day} ${hours}:${minutes}`;
}
// 处理链接
function processLink(link) {
return link.split('?')[0];
}
// 格式化文本
function formatText(title, link) {
return `📄 文件「${title}」\n🔗 链接:\n${processLink(link)}\n🕐 时间「${getFormattedTime()}」\n💡 文件已分享,欢迎查阅,有任何问题都可以随时交流~`;
}
// 解除文本复制粘贴限制
const enableCopyFunctionality = () => {
// 隐藏 .toast-wrap 元素
const style = document.createElement('style');
style.type = 'text/css';
style.innerHTML = `
.toast-wrap {
display: none !important;
}
`;
document.head.appendChild(style);
// 解除禁用右键菜单和文本选择的限制
document.addEventListener('contextmenu', function(e) {
e.stopPropagation();
}, true);
document.addEventListener('selectstart', function(e) {
e.stopPropagation();
}, true);
document.addEventListener('copy', function(e) {
e.stopPropagation();
}, true);
// 创建自定义右键菜单
document.addEventListener('contextmenu', function(event) {
event.preventDefault();
// 移除现有的自定义菜单(如果存在)
const existingMenu = document.getElementById('custom-context-menu');
if (existingMenu) {
existingMenu.remove();
}
// 创建菜单容器
const menu = document.createElement('div');
menu.id = 'custom-context-menu';
menu.style.position = 'fixed';
menu.style.top = event.clientY + 'px';
menu.style.left = event.clientX + 'px';
menu.style.backgroundColor = '#fff';
menu.style.border = '1px solid #ccc';
menu.style.boxShadow = '0 2px 10px rgba(0, 0, 0, 0.2)';
menu.style.zIndex = '10000';
menu.style.padding = '5px';
menu.style.cursor = 'pointer';
// 创建复制选项
const copyOption = document.createElement('div');
copyOption.innerText = '复制';
copyOption.style.padding = '5px';
copyOption.style.whiteSpace = 'nowrap';
// 复制选项点击事件
copyOption.addEventListener('click', function() {
document.execCommand('copy');
menu.remove();
});
menu.appendChild(copyOption);
document.body.appendChild(menu);
// 点击页面其他地方时移除自定义菜单
document.addEventListener('click', function onClickOutside() {
menu.remove();
document.removeEventListener('click', onClickOutside);
});
});
// 启用复制功能
document.addEventListener('copy', function(event) {
const selection = document.getSelection();
event.clipboardData.setData('text/plain', selection.toString());
event.preventDefault();
});
};
// 在文档加载完成后添加复制助手功能
document.addEventListener('DOMContentLoaded', () => {
// 监听复制事件
document.addEventListener('copy', function(e) {
try {
const text = window.getSelection().toString();
if (!text || !text.includes('feishu.cn/')) return;
const title = document.title.split(' - ')[0].trim();
if (!title || text.includes(title)) return;
e.preventDefault();
e.clipboardData.setData('text/plain', formatText(title, text));
console.log('已添加标题和时间到链接');
} catch (err) {
console.log('复制处理出错:', err);
}
});
// 监听点击事件
document.addEventListener('click', function(e) {
const target = e.target;
if (!target) return;
if (target.textContent?.includes('复制链接') ||
target.closest('.lark-link-entry-v2__copylink') ||
target.closest('[data-test-id="copy-share-link"]')) {
setTimeout(function() {
try {
const title = document.title.split(' - ')[0].trim();
if (!title) return;
navigator.clipboard.readText().then(function(text) {
if (!text || !text.includes('feishu.cn/') || text.includes(title)) return;
navigator.clipboard.writeText(formatText(title, text)).catch(function(err) {
console.log('写入剪贴板失败:', err);
});
}).catch(function(err) {
console.log('读取剪贴板失败:', err);
});
} catch (err) {
console.log('处理复制按钮点击失败:', err);
}
}, 100);
}
});
// 启用复制功能
enableCopyFunctionality();
});
// 立即运行覆盖函数
overrideEventListeners();
overrideXHR();
console.log('飞书文档标题复制助手Plus已加载,版本3.1');
})();