xkjing commited on
Commit
860a3a8
·
verified ·
1 Parent(s): 4303d33

Upload 3 files

Browse files
Files changed (3) hide show
  1. Dockerfile +10 -0
  2. custom.css +344 -0
  3. custom.js +1 -0
Dockerfile CHANGED
@@ -1,5 +1,15 @@
1
  FROM ghcr.io/open-webui/open-webui:main
2
 
 
 
 
 
 
 
 
 
 
 
3
  COPY sync_data.sh sync_data.sh
4
 
5
  RUN chmod -R 777 ./data && \
 
1
  FROM ghcr.io/open-webui/open-webui:main
2
 
3
+ # 复制字体文件
4
+ COPY fonts/* /app/build/assets/fonts/
5
+ # 复制自定义CSS和JS文件
6
+ COPY custom.css /app/build/assets/
7
+ COPY custom.js /app/build/assets/
8
+
9
+ # 在</head>标签前添加custom.css引用
10
+ RUN sed -i 's|</head>|<link rel="stylesheet" href="assets/custom.css"></head>|' /app/build/index.html && \
11
+ sed -i 's|</body>|<script src="assets/custom.js"></script></body>|' /app/build/index.html
12
+
13
  COPY sync_data.sh sync_data.sh
14
 
15
  RUN chmod -R 777 ./data && \
custom.css ADDED
@@ -0,0 +1,344 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ @font-face {
2
+ font-family: 'Dank Mono';
3
+ src: url('../assets/fonts/DankMono-Regular.woff2') format('woff2');
4
+ font-display: swap;
5
+ font-style: normal;
6
+ }
7
+
8
+ @font-face {
9
+ font-family: 'Dank Mono';
10
+ src: url('../assets/fonts/DankMono-Italic.woff2') format('woff2');
11
+ font-display: swap;
12
+ font-style: italic;
13
+ }
14
+
15
+ @font-face {
16
+ font-family: 'JinBuTi';
17
+ src: url('../assets/fonts/DingTalk-JinBuTi.woff2') format('woff2');
18
+ font-display: swap;
19
+ }
20
+
21
+ html {
22
+ scroll-behavior: smooth;
23
+ }
24
+
25
+ body {
26
+ font-family: 'JinBuTi', -apple-system, BlinkMacSystemFont, sans-serif;
27
+ }
28
+
29
+ /* 代码块容器样式 */
30
+ .language-javascript, [class*="language-"] {
31
+ background: #282c34 !important;
32
+ border-radius: 10px !important;
33
+ box-shadow: 0 10px 30px 0 rgba(0, 0, 0, .4) !important;
34
+ position: relative;
35
+ margin: 1.2em 0;
36
+ }
37
+
38
+ /* 代码块顶部栏 */
39
+ .sticky.top-8 {
40
+ background: #21252b !important;
41
+ height: 40px !important;
42
+ display: flex;
43
+ align-items: center;
44
+ border-radius: 10px 10px 0 0;
45
+ padding: 0 15px !important;
46
+ margin-bottom: -60px !important;
47
+ }
48
+
49
+ /* 语言标识 */
50
+ .text-text-300 {
51
+ position: absolute;
52
+ left: 60px;
53
+ /* top: 7px; */
54
+ color: #abb2bf !important;
55
+ font-size: 17px !important;
56
+ font-weight: 500 !important;
57
+ z-index: 11;
58
+ }
59
+
60
+ /* 顶部按钮样式优化 */
61
+ .save-code-button, .copy-code-button, .run-code-button {
62
+ background: #323842 !important;
63
+ color: #abb2bf !important;
64
+ border: 1px solid #3e4451 !important;
65
+ font-size: 12px !important;
66
+ padding: 4px 12px !important;
67
+ border-radius: 4px !important;
68
+ transition: all 0.2s ease-in-out !important;
69
+ }
70
+
71
+ .save-code-button:hover, .copy-code-button:hover {
72
+ background: #3e4451 !important;
73
+ color: #fff !important;
74
+ }
75
+
76
+ /* 代码块顶部装饰圆点 */
77
+ .language-javascript::before, [class*="language-"]::before {
78
+ content: " ";
79
+ position: absolute;
80
+ border-radius: 50%;
81
+ background: #fc625d;
82
+ width: 12px;
83
+ height: 12px;
84
+ left: 15px;
85
+ top: 14px;
86
+ box-shadow: 20px 0 #fdbc40, 40px 0 #35cd4b;
87
+ z-index: 10;
88
+ }
89
+
90
+ /* 代码内容区域 */
91
+ .cm-content {
92
+ font-family: 'Dank Mono', -apple-system, BlinkMacSystemFont, Inter, ui-sans-serif, system-ui, 'Segoe UI', Roboto, Ubuntu, Cantarell, 'Noto Sans', sans-serif, 'Helvetica Neue', Arial, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol', 'Noto Color Emoji';
93
+ font-size: 15px !important;
94
+ line-height: 1.6em !important;
95
+ padding: 20px 1.4em 1em 30px !important;
96
+ color: #abb2bf !important;
97
+ }
98
+
99
+ /* 代码语法高亮 */
100
+ .cm-line .ͼb {
101
+ /* 关键字 */
102
+ color: #c678dd !important;
103
+ }
104
+
105
+ .cm-line .ͼd {
106
+ /* 数字 */
107
+ color: #e5c07b !important;
108
+ }
109
+
110
+ .cm-line .ͼe {
111
+ /* 字符串 */
112
+ color: #98c379 !important;
113
+ }
114
+
115
+ .cm-line .ͼg {
116
+ /* 变量 */
117
+ color: #e06c75 !important;
118
+ font-style: italic;
119
+ }
120
+
121
+ /* 代码语法高亮 - 扩展 */
122
+ .cm-comment {
123
+ /* 注释 */
124
+ color: #7f848e !important;
125
+ font-style: italic;
126
+ }
127
+
128
+ .cm-property {
129
+ color: #61afef !important;
130
+ }
131
+
132
+ .cm-tag {
133
+ color: #e06c75 !important;
134
+ }
135
+
136
+ .cm-attribute {
137
+ color: #d19a66 !important;
138
+ }
139
+
140
+ .cm-string {
141
+ color: #98c379 !important;
142
+ }
143
+
144
+ .cm-operator {
145
+ color: #56b6c2 !important;
146
+ }
147
+
148
+ span.ͼc {
149
+ color: #dd6b7b !important;
150
+ }
151
+
152
+ span.ͼl {
153
+ color: #6bddcd !important;
154
+ }
155
+
156
+ span.ͼt {
157
+ color: #ddb078 !important;
158
+ ;
159
+ font-style: italic;
160
+ }
161
+
162
+ span.ͼr {
163
+ font-style: italic;
164
+ }
165
+
166
+ span.ͼf {
167
+ color: #80a492;
168
+ }
169
+
170
+ span.ͼm {
171
+ color: #3d8e86;
172
+ font-style: italic;
173
+ }
174
+
175
+ span.ͼw {
176
+ font-style: italic;
177
+ }
178
+
179
+ /* 滚动条样式 */
180
+ .cm-scroller::-webkit-scrollbar {
181
+ height: 10px !important;
182
+ width: 10px !important;
183
+ background-color: #282c34 !important;
184
+ }
185
+
186
+ .cm-scroller::-webkit-scrollbar-track {
187
+ box-shadow: inset 0 0 6px rgba(0, 0, 0, .3) !important;
188
+ border-radius: 10px !important;
189
+ background-color: #282c34 !important;
190
+ }
191
+
192
+ .cm-scroller::-webkit-scrollbar-thumb {
193
+ border-radius: 10px !important;
194
+ box-shadow: inset 0 0 6px rgba(0, 0, 0, .5) !important;
195
+ background-color: #3e4451 !important;
196
+ }
197
+
198
+ /* 行号栏样式 */
199
+ .cm-gutters {
200
+ background: #282c34 !important;
201
+ border-right: 1px solid #3e4451 !important;
202
+ color: #495162 !important;
203
+ padding-right: 10px !important;
204
+ }
205
+
206
+ /* 当前行高亮 */
207
+ .cm-activeLine {
208
+ background: #6699ff0b !important;
209
+ }
210
+
211
+ .cm-gutterElement.cm-activeLineGutter {
212
+ background-color: #dd7694;
213
+ }
214
+
215
+ /* 添加代码选中样式 */
216
+ .cm-selectionBackground, .cm-content ::selection {
217
+ background-color: rgba(122, 129, 255, 0.2) !important;
218
+ }
219
+
220
+ .cm-line.cm-selected {
221
+ background-color: rgba(122, 129, 255, 0.2) !important;
222
+ }
223
+
224
+ /* 选中时的文本颜色保持原样,确保可读性 */
225
+ .cm-content ::selection {
226
+ color: rgba(245, 177, 255, 0.9) !important;
227
+ }
228
+
229
+ /* 当有多行选中时的样式 */
230
+ .cm-selectionLayer>.cm-selectionBackground {
231
+ background-color: rgba(122, 129, 255, 0.2) !important;
232
+ }
233
+
234
+ /* 代码块折叠/展开样式添加与修改 */
235
+ .cm-scroller {
236
+ padding-bottom: 40px;
237
+ background-color: #282c34;
238
+ }
239
+
240
+ .cm-scroller {
241
+ overflow: auto !important;
242
+ }
243
+
244
+ .cm-editor {
245
+ transition: height 1s cubic-bezier(0.4, 0, 0.2, 1);
246
+ overflow: hidden !important;
247
+ }
248
+
249
+ /* 只给超高的代码块添加最大高度和内边距 */
250
+ .cm-editor#collapsed {
251
+ height: 400px;
252
+ }
253
+
254
+ /* .cm-editor#expanded { padding-bottom: 40px; } */
255
+ .code-expand-btn {
256
+ position: absolute;
257
+ bottom: 10px;
258
+ left: 50%;
259
+ transform: translateX(-50%);
260
+ display: flex;
261
+ justify-content: center;
262
+ align-items: center;
263
+ padding: 6px 15px;
264
+ border-radius: 15px;
265
+ font-size: 12px;
266
+ cursor: pointer;
267
+ border: none;
268
+ color: #666;
269
+ background: rgba(255, 255, 255, 0.6);
270
+ backdrop-filter: blur(8px);
271
+ box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
272
+ -webkit-backdrop-filter: blur(8px);
273
+ z-index: 11;
274
+ transition: all 0.3s ease;
275
+ }
276
+
277
+ .dark .code-expand-btn {
278
+ background: rgba(45, 45, 45, 0.6);
279
+ color: #fff;
280
+ }
281
+
282
+ .code-expand-btn:hover {
283
+ background: rgba(255, 255, 255, 0.8);
284
+ backdrop-filter: blur(12px);
285
+ -webkit-backdrop-filter: blur(12px);
286
+ transform: translateX(-50%) translateY(-2px);
287
+ box-shadow: 0 6px 8px rgba(0, 0, 0, 0.15);
288
+ }
289
+
290
+ .dark .code-expand-btn:hover {
291
+ background: rgba(45, 45, 45, 0.8);
292
+ }
293
+
294
+ .code-expand-btn:active {
295
+ transform: translateX(-50%) translateY(0);
296
+ box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
297
+ }
298
+
299
+ .code-expand-btn::before {
300
+ content: "⌄";
301
+ display: inline-block;
302
+ margin-right: 4px;
303
+ font-size: 14px;
304
+ transition: transform 0.3s ease;
305
+ }
306
+
307
+ .code-expand-btn#expanded::before {
308
+ transform: rotate(180deg);
309
+ }
310
+
311
+ .code-expand-btn::after {
312
+ content: "展开代码";
313
+ }
314
+
315
+ .code-expand-btn#expanded::after {
316
+ content: "收起代码";
317
+ }
318
+
319
+ /* 渐变遮罩 */
320
+ .cm-editor#collapsed::after {
321
+ content: '';
322
+ position: absolute;
323
+ bottom: 0;
324
+ left: 0;
325
+ right: 0;
326
+ height: 100px;
327
+ background: linear-gradient(transparent 0%, rgba(45, 45, 45, 0.3) 40%, rgba(45, 45, 45, 0.6) 80%, rgba(45, 45, 45, 0.8) 100%);
328
+ pointer-events: none;
329
+ opacity: 0;
330
+ transition: opacity 0.3s ease;
331
+ z-index: 10;
332
+ /* 确保遮罩层覆盖到滚动条 */
333
+ width: calc(100% + 17px);
334
+ /* 17px是标准滚动条宽度 */
335
+ }
336
+
337
+ .dark .cm-editor#collapsed::after {
338
+ background: linear-gradient(transparent 0%, rgba(45, 45, 45, 0.3) 40%, rgba(45, 45, 45, 0.6) 80%, rgba(45, 45, 45, 0.8) 100%);
339
+ }
340
+
341
+ /* 只在折叠状态显示渐变遮罩 */
342
+ .cm-editor#collapsed::after {
343
+ opacity: 1;
344
+ }
custom.js ADDED
@@ -0,0 +1 @@
 
 
1
+ (function () { function checkIsEditPage() { return window.location.href.includes('/functions'); } let isCurrentlyEditPage = checkIsEditPage(); function onRouteChange() { isCurrentlyEditPage = checkIsEditPage(); if (isCurrentlyEditPage) { if (mutationObserverActive) { mutationObserver.disconnect(); mutationObserverActive = false; } } else { initializeAllCodeBlocks(); if (!mutationObserverActive) { mutationObserver.observe(document.body, { childList: true, subtree: true }); mutationObserverActive = true; } } } const originalPushState = history.pushState; history.pushState = function (state, title, url) { originalPushState.apply(history, arguments); onRouteChange(); }; window.addEventListener('popstate', onRouteChange); const observedCodeBlocks = new WeakSet(); const resizeObserver = new ResizeObserver((entries) => { if (isCurrentlyEditPage) return; for (const entry of entries) { const editorRoot = entry.target; if (!editorRoot.classList.contains('cm-editor')) continue; updateCodeBlock(editorRoot); } }); function updateCodeBlock(editorRoot) { if (editorRoot.querySelector('.code-expand-btn')) return; const height = editorRoot.scrollHeight; if (height > 400) { editorRoot.id = 'collapsed'; const expandBtn = document.createElement('button'); expandBtn.className = 'code-expand-btn'; expandBtn.id = 'collapsed'; editorRoot.appendChild(expandBtn); editorRoot.style.height = '400px'; } } function initializeCodeBlock(editorRoot) { if (observedCodeBlocks.has(editorRoot)) return; observedCodeBlocks.add(editorRoot); resizeObserver.observe(editorRoot); updateCodeBlock(editorRoot); } function initializeAllCodeBlocks() { if (isCurrentlyEditPage) return; document.querySelectorAll('.cm-editor').forEach(initializeCodeBlock); } const mutationObserver = new MutationObserver((mutations) => { if (isCurrentlyEditPage) return; let hasNewCodeBlocks = false; mutations.forEach((mutation) => { mutation.addedNodes.forEach((node) => { if (node.nodeType !== 1) return; if (node.classList?.contains('cm-editor')) { initializeCodeBlock(node); hasNewCodeBlocks = true; } else { const matches = node.querySelectorAll?.('.cm-editor') || []; matches.forEach((el) => { initializeCodeBlock(el); hasNewCodeBlocks = true; }); } }); }); if (hasNewCodeBlocks) requestAnimationFrame(initializeAllCodeBlocks); }); let mutationObserverActive = false; document.addEventListener('click', function (evt) { if (!evt.target.classList.contains('code-expand-btn')) return; const editorRoot = evt.target.closest('.cm-editor'); if (!editorRoot) return; const isCollapsed = editorRoot.id === 'collapsed'; requestAnimationFrame(() => { if (isCollapsed) { const scroller = editorRoot.querySelector('.cm-scroller'); editorRoot.style.height = `${scroller.scrollHeight}px`; editorRoot.id = 'expanded'; evt.target.id = 'expanded'; } else { editorRoot.style.height = '400px'; editorRoot.id = 'collapsed'; evt.target.id = 'collapsed'; const scrollTarget = editorRoot.closest('.relative.my-2')?.parentElement; scrollTarget?.scrollIntoView({ behavior: 'smooth', block: 'start' }); } }); }); function init() { isCurrentlyEditPage = checkIsEditPage(); if (!isCurrentlyEditPage) initializeAllCodeBlocks(); mutationObserver.observe(document.body, { childList: true, subtree: true }); mutationObserverActive = true; } if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', init); } else { init(); } window.addEventListener('error', (error) => { console.error('Code block error:', error); }); window.addEventListener('unhandledrejection', (event) => { console.error('Unhandled rejection:', event.reason); }); })();