Остання активність 1778119947

在办公室使用gpt会被同事追问:你怎么用上的?怎么翻墙的?能给我用用吗?而你又不想给这类 “等人喂饭” 的人群分享时,那么这个脚本就可以帮助到你了

Версія d2ac4762408ff513acc4ec57654d7f1361031542

change-gpt-logo.user.js Неформатований
1// ==UserScript==
2// @name ChatGPT Logo 换成 DeepSeek
3// @namespace https://gist.doracoin.cc/doracoin/39fd3ec77d3044fc95b408bdf6c0ac13
4// @version 2025.09.12
5// @description 替换 ChatGPT 左上角 sidebar-header 的 SVG logo 为 DeepSeek logo,并实现 #page-header 向上收缩(垂直折叠),支持 SPA 重绘、状态记忆,并增加可配置项与主题适配按钮。
6// @author Doracoin
7// @match https://chatgpt.com/*
8// @icon https://deepseek.com/favicon.ico
9// @run-at document-body
10// @grant GM_addStyle
11// ==/UserScript==
12
13(function () {
14 'use strict';
15
16 // ====== 配置区 ======
17 const CONFIG = {
18 deepseekLogoUrl: 'https://commons.wikimedia.org/wiki/Special:Redirect/file/DeepSeek_logo.svg',
19 storageKey: 'deepseek_header_collapsed_v2',
20 headerMaxHeight: 82, // header 默认高度
21 buttonSize: 36, // 按钮尺寸(px)
22 buttonPosition: { top: 10, right: 12 }, // 按钮固定位置
23 enableLogs: false // 是否启用 console.log 调试
24 };
25 // ====================
26
27 // 动态样式,支持深色/浅色主题自动适配
28 GM_addStyle(`
29 #page-header {
30 --ds-header-max-height: ${CONFIG.headerMaxHeight}px;
31 max-height: var(--ds-header-max-height);
32 overflow: hidden;
33 transition: max-height 260ms ease, padding 260ms ease;
34 }
35 #page-header.collapsed {
36 max-height: 0 !important;
37 padding-top: 0 !important;
38 padding-bottom: 0 !important;
39 }
40 #page-header.collapsed * {
41 visibility: hidden;
42 pointer-events: none;
43 }
44
45 #ds-page-header-toggle {
46 position: fixed;
47 top: ${CONFIG.buttonPosition.top}px;
48 right: ${CONFIG.buttonPosition.right}px;
49 z-index: 2147483647;
50 display: inline-flex;
51 align-items: center;
52 justify-content: center;
53 width: ${CONFIG.buttonSize}px;
54 height: ${CONFIG.buttonSize}px;
55 border-radius: 6px;
56 font-size: 16px;
57 line-height: 1;
58 background: var(--ds-btn-bg, rgba(0,0,0,0.6));
59 color: var(--ds-btn-fg, #fff);
60 cursor: pointer;
61 user-select: none;
62 transition: transform 140ms ease, opacity 140ms ease, background 200ms ease;
63 box-shadow: 0 6px 18px rgba(0,0,0,0.35);
64 margin-top: 38px;
65 }
66 #ds-page-header-toggle:hover {
67 transform: translateY(-2px);
68 }
69
70 @media (prefers-color-scheme: light) {
71 #ds-page-header-toggle {
72 --ds-btn-bg: rgba(255,255,255,0.85);
73 --ds-btn-fg: #000;
74 }
75 }
76 @media (prefers-color-scheme: dark) {
77 #ds-page-header-toggle {
78 --ds-btn-bg: rgba(0,0,0,0.6);
79 --ds-btn-fg: #fff;
80 }
81 }
82 `);
83
84 function log(...args) {
85 if (CONFIG.enableLogs) console.log('[DeepSeek]', ...args);
86 }
87
88 // 替换 sidebar header logo(保留用户调整的宽高逻辑)
89 function replaceLogo() {
90 try {
91 const sidebarHeader = document.querySelector('.sidebar-header') || document.querySelector('.sidebar .header') || document.querySelector('nav[aria-label]');
92 if (!sidebarHeader) return;
93
94 const origSvg = sidebarHeader.querySelector('svg');
95 const origImg = sidebarHeader.querySelector('img');
96
97 if (sidebarHeader.querySelector('img[data-deepseek-logo]')) return;
98
99 const img = document.createElement('img');
100 img.setAttribute('src', CONFIG.deepseekLogoUrl);
101 img.setAttribute('alt', 'DeepSeek');
102 img.setAttribute('data-deepseek-logo', '1');
103 img.style.height = '56px'; // 用户修改的高度
104 img.style.width = 'auto';
105 img.style.objectFit = 'contain';
106 img.style.verticalAlign = 'middle';
107
108 const parent = origSvg?.parentNode || origImg?.parentNode || sidebarHeader.querySelector('a') || sidebarHeader;
109 parent.innerHTML = '';
110 parent.appendChild(img);
111
112 // 调整父容器以适配新 logo 宽高
113 if (parent.classList.contains("w-9")) {
114 parent.classList.remove("w-9");
115 parent.classList.add("w-21");
116 }
117
118 log('logo replaced');
119 } catch (e) {
120 log('replaceLogo error', e);
121 }
122 }
123
124 function ensureToggle() {
125 let btn = document.getElementById('ds-page-header-toggle');
126 if (btn) return btn;
127
128 btn = document.createElement('div');
129 btn.id = 'ds-page-header-toggle';
130 btn.setAttribute('role', 'button');
131 btn.setAttribute('aria-pressed', 'false');
132 btn.setAttribute('title', '折叠/展开页眉 (DeepSeek)');
133 btn.innerText = '▲';
134 btn.addEventListener('click', () => toggleHeader());
135 document.body.appendChild(btn);
136 return btn;
137 }
138
139 function getHeader() {
140 return document.querySelector('#page-header') || document.querySelector('header') || document.querySelector('.page-header');
141 }
142
143 function toggleHeader(forceState) {
144 const header = getHeader();
145 if (!header) return;
146
147 const shouldCollapse = typeof forceState === 'boolean' ? forceState : !header.classList.contains('collapsed');
148 header.classList.toggle('collapsed', shouldCollapse);
149
150 try { localStorage.setItem(CONFIG.storageKey, shouldCollapse ? '1' : '0'); } catch (e) {}
151
152 const btn = ensureToggle();
153 btn.innerText = shouldCollapse ? '▼' : '▲';
154 btn.setAttribute('aria-pressed', shouldCollapse ? 'true' : 'false');
155 }
156
157 function restoreState() {
158 try {
159 const v = localStorage.getItem(CONFIG.storageKey);
160 if (v === '1') toggleHeader(true);
161 } catch (e) {}
162 }
163
164 let debounceTimer = null;
165 function onDomChanged() {
166 if (debounceTimer) clearTimeout(debounceTimer);
167 debounceTimer = setTimeout(() => {
168 replaceLogo();
169 ensureToggle();
170 restoreState();
171 }, 250);
172 }
173
174 const observer = new MutationObserver(onDomChanged);
175 observer.observe(document.body, { childList: true, subtree: true });
176
177 replaceLogo();
178 ensureToggle();
179 restoreState();
180 window.addEventListener('load', () => setTimeout(onDomChanged, 300));
181})();
182