SharePoint 用户查询

输入关键字查询SharePoint用户详细信息和查看该用户所有文章,方便确认作者身份。按 Ctrl+Q 激活功能。

// ==UserScript==
// @name         SharePoint 用户查询
// @namespace    http://tampermonkey.net/
// @version      2025-01-23
// @license    GPL-3.0-only
// @description  输入关键字查询SharePoint用户详细信息和查看该用户所有文章,方便确认作者身份。按 Ctrl+Q 激活功能。
// @author       Kingron
// @match        https://*.sharepoint.com/sites/*
// @match        https://*.sharepoint.cn/sites/*
// @icon         https://www.google.com/s2/favicons?sz=64&domain=sharepoint.com
// @grant        GM_xmlhttpRequest
// ==/UserScript==

(function() {
    'use strict';

    // 监听 Ctrl+Q 快捷键
    window.addEventListener('keydown', function(event) {
        if (event.ctrlKey && event.key === 'q') {
            event.preventDefault(); // 阻止默认行为

            const keyword = prompt("请输入关键字进行搜索:");
            if (keyword) {
                const siteName = getSiteNameFromURL(); // 获取当前 SharePoint 站点名称
                console.log("SharePoint站点名称: ", siteName);
                if (siteName) {
                    searchUsers(siteName, keyword);
                } else {
                    alert("无法从 URL 获取 SharePoint 站点名!");
                }
            }
        }
    });

    // 从当前 URL 中提取 SharePoint 站点名称,支持 .com 和 .cn 域名
    function getSiteNameFromURL() {
        let regex = /https:\/\/.*\.sharepoint\.(com|cn)\/sites\/(.*)\/(SitePages|_layouts|Lists|Shared%20Documents|SiteAssets|Pages)/;
        let match = window.location.href.match(regex);

        if (match) {
            return match[2];
        }

        regex = /https:\/\/.*\.sharepoint\.(com|cn)\/sites\/([^\/?]+)/;
        match = window.location.href.match(regex);
        return match ? match[2] : null;
    }

    function copyTable(tableElement) {
        const range = document.createRange();
        const selection = window.getSelection();
        selection.removeAllRanges();
        range.selectNode(tableElement);
        selection.addRange(range);
        try {
            document.execCommand('copy');
            alert('表格已复制到剪切板!');
        } catch (err) {
            alert('复制失败:' + err);
        }
        selection.removeAllRanges();
    }

    // 调用 SharePoint API 获取用户数据
    function searchUsers(siteName, keyword) {
        const apiUrl = `/sites/${siteName}/_api/Web/SiteUsers`;
        const headers = {
            "Accept": "application/json"
        };

        GM_xmlhttpRequest({
            method: "GET",
            url: apiUrl,
            headers: headers,
            onload: function(response) {
                const data = JSON.parse(response.responseText);
                const users = data.value || [];

                // 过滤匹配关键字的用户
                const regex = new RegExp(keyword, 'i');
                const filteredUsers = users.filter(user => {
                    return regex.test(user.Title) || regex.test(user.Email) || regex.test(user.UserPrincipalName);
                });

                if (filteredUsers.length === 0) {
                    alert("没有找到匹配的用户。");
                } else {
                    displayResults(siteName, filteredUsers);
                }
            },
            onerror: function(error) {
                alert("请求失败!请稍后再试。");
            }
        });
    }

    // 在页面上展示搜索结果
    function displayResults(site, users) {
        const container = document.createElement('div');
        container.innerHTML = `
        <div tabindex=0 style="position: fixed; top: 50%; left: 50%; transform: translate(-50%, -50%); max-width: 90%; max-height: 70%; overflow: hidden; background-color: #fff; border: 1px solid #ccc; border-radius: 8px; box-shadow: 0 0 10px rgba(0, 0, 0, 0.3); padding: 10px; z-index: 9999; display: flex; flex-direction: column;"}">
            <div style="flex: 1; overflow-y: auto">
                <style>
                    #_rl_table td { padding: 5px; border-bottom: 1px solid #ddd; }
                </style>
                <table id="_rl_table" style="width: 100%; border-collapse: collapse; background-color: #fff; border: 1px solid #ddd; border-radius: 5px">
                    <thead style="position: sticky; top: 0; background-color: #f8f8f8;">
                        <tr>
                            <th>Title</th>
                            <th>Email</th>
                            <th>UserPrincipalName</th>
                        </tr>
                    </thead>
                    <tbody>
                        ${users.map(user => `
                            <tr>
                                <td><a href="/sites/${site}/SitePages/Forms/AllPages.aspx?view=7&q=author: *&useFiltersInViewXml=0&viewpath=/sites/${site}/SitePages/Forms/AllPages.aspx&FilterField1=Editor&FilterValue1=${user.Title}&FilterField1=DocIcon&FilterValue1=aspx&FilterType1=Computed&FilterOp1=In&FilterField2=Author&FilterValue2=${user.Title}&FilterType2=User&FilterOp2=In" target="_blank">${user.Title}</a></td>
                                <td><a href="mailto:${user.Email}">${user.Email}</a></td>
                                <td><a href="${user['odata.id']}" target="_blank">${user.UserPrincipalName}</a></td>
                            </tr>
                        `).join('')}
                    </tbody>
                </table>
            </div>

            <div style="padding-top:10px; display: flex; align-items: center; justify-content: flex-end">按 Esc 关闭&nbsp;&nbsp;
                <button id="copyButton" style="padding: 10px 20px; background-color: #3CB371; color: white; border: none; border-radius: 5px; cursor: pointer; font-size: 14px;outline: none;">复制表格</button>&nbsp;&nbsp;
                <button id="closeButton" style="padding: 10px 20px; background-color: #ff4d4f; color: white; border: none; border-radius: 5px; cursor: pointer; font-size: 14px;outline: none;">关闭</button>
            </div>
        </div>
        `;
        document.body.appendChild(container);

        const copyButton = container.querySelector('#copyButton');
        copyButton.addEventListener('click', function() {
            copyTable(document.getElementById('_rl_table'));
        });

        const closeButton = container.querySelector('#closeButton');
        closeButton.addEventListener('click', function() {
            document.body.removeChild(container);
        });
        container.addEventListener('keydown', function(event) {
            if (event.key === 'Escape') { document.body.removeChild(container); };
        });
        closeButton.focus();
    }
})();