标签 自部署 下的文章

// ==UserScript== // @name         GitLab - 一键导出所有项目 // @namespace    http://tampermonkey.net/ // @version      1.0 // @description  在 GitLab 项目页面顶部添加自定义按钮用于一键导出所有项目 // @author       LeonShaw // @match        *://*/dashboard/projects // @grant        none // @run-at       document-idle // ==/UserScript==

(function () {
    'use strict';

    const { protocol, host } = window.location;
    const baseUrl = `${protocol}//${host}`;
    const apiUrl = `${baseUrl}/api/v4/projects`;

    // 获取所有项目(分页) async function fetchAllProjects() {
        const statusEl = document.getElementById('clone-status');
        statusEl.style.display = 'block';
        statusEl.textContent = '正在加载项目...';

        let page = 1;
        let allProjects = [];
        try {
            while (true) {
                const url = `${apiUrl}?per_page=100&page=${page}&order_by=created_at&sort=desc`;
                const res = await fetch(url, {
                    credentials: 'include' // 携带 cookie,确保认证
                });

                if (!res.ok) {
                    throw new Error(`HTTP ${res.status}: ${await res.text()}`);
                }

                const data = await res.json();
                if (!Array.isArray(data) || data.length === 0) break;

                allProjects.push(...data);
                statusEl.textContent = `已加载 ${allProjects.length} 个项目...`;
                page++;
            }

            generateAndDownloadScript(allProjects);
            statusEl.textContent = `完成!共 ${allProjects.length} 个项目。`;
        } catch (err) {
            console.error('获取项目失败:', err);
            statusEl.textContent = `错误: ${err.message || '未知错误'}`;
        } finally {
            setTimeout(() => {
                statusEl.style.display = 'none';
                statusEl.textContent = '';
            }, 30000);
        }
    }

    // 生成并下载 .sh 脚本 function generateAndDownloadScript(projects) {
        const lines = ['#!/bin/bash\n'];

        projects.forEach(proj => {
            if (!proj.ssh_url_to_repo) return;

            const sshUrl = proj.ssh_url_to_repo;

            const localPath = proj.path_with_namespace;
            lines.push(`git clone "${sshUrl}" "./${localPath}"`);
        });

        const scriptContent = lines.join('\n') + '\n';
        const blob = new Blob([scriptContent], { type: 'text/plain;charset=utf-8' });
        const filename = `clone-all-git-repos(${host}).sh`;

        // 创建下载链接 const link = document.createElement('a');
        link.href = URL.createObjectURL(blob);
        link.download = filename;
        link.click();
        URL.revokeObjectURL(link.href);
    }

    function addButton() {
        const breadcrumbWrapper = document.querySelector('#js-vue-page-breadcrumbs-wrapper');
        if (!breadcrumbWrapper) return;

        // 防止重复添加 if (breadcrumbWrapper.querySelector('.custom-gitlab-button')) return;

        // 创建按钮 const button = document.createElement('button');
        button.textContent = '一键导出所有项目';
        button.className = 'custom-gitlab-button gl-button btn btn-default btn-sm gl-mx-2';
        button.style.marginLeft = '10px';
        button.addEventListener('click', function () {
            fetchAllProjects();
        });


        breadcrumbWrapper.appendChild(button);

        const statusElement = document.createElement('span');
        statusElement.id = 'clone-status';
        statusElement.className = 'custom-gitlab-status gl-ml-3 gl-font-sm gl-font-weight-bold';
        statusElement.style.padding = '4px 8px';
        statusElement.style.borderRadius = '4px';
        statusElement.style.backgroundColor = '#e9ecef';
        statusElement.style.color = '#495057';
        statusElement.textContent = '';
        statusElement.style.display = 'none';


        breadcrumbWrapper.appendChild(statusElement);
    }

    addButton();

    const observer = new MutationObserver(() => {
        addButton();
    });
    observer.observe(document.body, { childList: true, subtree: true });
})();

AIGC 声明:本脚本部分函数由 通义千问 辅助创造,本人已验证其生成内容的真实性和有效性

使用方法


本脚本已在 Gitlab v18.0.1 - v18.8.1 验证


📌 转载信息
原作者:
LeonShaw
转载时间:
2026/1/23 15:40:54

全新版本,可能有点问题(但我目前没发现)如果有的话麻烦佬友提 issue 或者 pr 了

大致使用就是接入 OIDC 后,
首先新建渠道

然后创建个配置,定义一下模型输入和输出格式就好


然后添加以下渠道

如下是一些配置项:
Cursor 自带的 Opus-4.5 带 thinking 的模型名称为
claude-4.5-opus-high-thinking
不带 thinking 的叫
claude-4.5-opus-high

其中响应处理器 [“thinkingTags”] 的作用是将响应的 reason 转为 content 中的 … ,如此就能在 Cursor 中展示思考内容

仓库地址:GitHub - NickJerome/tiny-ai-api-hub

虽然最后的目标是想实现 Claude Code 也可用(测了下好像可以,但是感觉哪里怪怪的)


📌 转载信息
转载时间:
2026/1/14 11:03:21

已经开放注册,仅作为学习演示。

请勿投入正式使用,仅作为功能对比演示。

此站点为临时部署,任何时候都有可能清空数据库。

如有需要商用或者正式使用,请自部署或者寻求官方服务,本人不对任何数据丢失负责。

Bitwarden Lite
Vaultwarden

地区限制;仅 内地以及港澳台


📌 转载信息
原作者:
preacher
转载时间:
2026/1/4 10:06:16