|
1 | 1 | <template> |
2 | | - <div class="command-preview"> |
3 | | - <div class="preview-header"> |
4 | | - <span class="preview-title">{{ title }}</span> |
5 | | - <Button |
6 | | - v-if="showCopy" |
7 | | - icon="pi pi-copy" |
8 | | - text |
9 | | - rounded |
10 | | - size="small" |
11 | | - @click="copyCommand" |
12 | | - v-tooltip.top="'复制'" |
13 | | - /> |
| 2 | + <div class="terminal-window"> |
| 3 | + <div class="terminal-header"> |
| 4 | + <div class="traffic-lights"> |
| 5 | + <span class="dot red"></span> |
| 6 | + <span class="dot yellow"></span> |
| 7 | + <span class="dot green"></span> |
| 8 | + </div> |
| 9 | + <span class="terminal-title">{{ title }}</span> |
| 10 | + <div class="terminal-actions"> |
| 11 | + <button |
| 12 | + v-if="showCopy" |
| 13 | + class="copy-btn" |
| 14 | + @click="copyCommand" |
| 15 | + v-tooltip.top="'复制'" |
| 16 | + > |
| 17 | + <i class="pi pi-copy"></i> |
| 18 | + </button> |
| 19 | + </div> |
| 20 | + </div> |
| 21 | + <div class="terminal-body"> |
| 22 | + <pre><code><span class="prompt">$ </span><span v-html="highlightedCommand"></span></code></pre> |
14 | 23 | </div> |
15 | | - <pre class="preview-content"><code v-html="highlightedCommand"></code></pre> |
16 | 24 | </div> |
17 | 25 | </template> |
18 | 26 |
|
19 | 27 | <script setup lang="ts"> |
20 | 28 | import { computed } from 'vue' |
21 | | -import Button from 'primevue/button' |
22 | 29 | import { useToast } from 'primevue/usetoast' |
23 | 30 |
|
24 | 31 | interface Props { |
@@ -98,63 +105,128 @@ async function copyCommand() { |
98 | 105 | </script> |
99 | 106 |
|
100 | 107 | <style scoped> |
101 | | -.command-preview { |
102 | | - border: 1px solid var(--p-surface-border); |
103 | | - border-radius: var(--p-border-radius); |
| 108 | +/* ===== Terminal Window ===== */ |
| 109 | +.terminal-window { |
| 110 | + border-radius: 8px; |
104 | 111 | overflow: hidden; |
| 112 | + border: 1px solid #30363d; |
| 113 | + box-shadow: 0 4px 12px rgba(0, 0, 0, 0.4); |
105 | 114 | } |
106 | 115 |
|
107 | | -.preview-header { |
| 116 | +/* ===== Title Bar ===== */ |
| 117 | +.terminal-header { |
108 | 118 | display: flex; |
109 | | - justify-content: space-between; |
110 | 119 | align-items: center; |
111 | | - padding: 0.5rem 0.75rem; |
112 | | - background: var(--p-surface-section); |
113 | | - border-bottom: 1px solid var(--p-surface-border); |
| 120 | + padding: 10px 14px; |
| 121 | + background: #161b22; |
| 122 | + border-bottom: 1px solid #30363d; |
114 | 123 | } |
115 | 124 |
|
116 | | -.preview-title { |
117 | | - font-size: 0.875rem; |
118 | | - font-weight: 500; |
119 | | - color: var(--p-text-secondary-color); |
| 125 | +.traffic-lights { |
| 126 | + display: flex; |
| 127 | + gap: 8px; |
| 128 | + flex-shrink: 0; |
120 | 129 | } |
121 | 130 |
|
122 | | -.preview-content { |
123 | | - margin: 0; |
124 | | - padding: 0.75rem; |
125 | | - background: var(--p-surface-card); |
126 | | - font-family: 'Monaco', 'Menlo', 'Ubuntu Mono', monospace; |
| 131 | +.traffic-lights .dot { |
| 132 | + width: 12px; |
| 133 | + height: 12px; |
| 134 | + border-radius: 50%; |
| 135 | +} |
| 136 | +
|
| 137 | +.traffic-lights .dot.red { |
| 138 | + background: #ff5f56; |
| 139 | +} |
| 140 | +
|
| 141 | +.traffic-lights .dot.yellow { |
| 142 | + background: #ffbd2e; |
| 143 | +} |
| 144 | +
|
| 145 | +.traffic-lights .dot.green { |
| 146 | + background: #27c93f; |
| 147 | +} |
| 148 | +
|
| 149 | +.terminal-title { |
| 150 | + flex: 1; |
| 151 | + text-align: center; |
127 | 152 | font-size: 13px; |
128 | | - line-height: 1.5; |
| 153 | + font-weight: 500; |
| 154 | + color: #8b949e; |
| 155 | + user-select: none; |
| 156 | +} |
| 157 | +
|
| 158 | +.terminal-actions { |
| 159 | + display: flex; |
| 160 | + align-items: center; |
| 161 | + flex-shrink: 0; |
| 162 | +} |
| 163 | +
|
| 164 | +.copy-btn { |
| 165 | + display: flex; |
| 166 | + align-items: center; |
| 167 | + justify-content: center; |
| 168 | + width: 28px; |
| 169 | + height: 28px; |
| 170 | + border: none; |
| 171 | + border-radius: 6px; |
| 172 | + background: transparent; |
| 173 | + color: #8b949e; |
| 174 | + cursor: pointer; |
| 175 | + transition: background 0.2s, color 0.2s; |
| 176 | +} |
| 177 | +
|
| 178 | +.copy-btn:hover { |
| 179 | + background: #30363d; |
| 180 | + color: #e6edf3; |
| 181 | +} |
| 182 | +
|
| 183 | +.copy-btn i { |
| 184 | + font-size: 14px; |
| 185 | +} |
| 186 | +
|
| 187 | +/* ===== Terminal Body ===== */ |
| 188 | +.terminal-body { |
| 189 | + background: #0d1117; |
| 190 | + padding: 16px; |
129 | 191 | overflow-x: auto; |
| 192 | +} |
| 193 | +
|
| 194 | +.terminal-body pre { |
| 195 | + margin: 0; |
130 | 196 | white-space: pre-wrap; |
131 | 197 | word-break: break-all; |
132 | | - color: var(--p-text-color); |
133 | 198 | } |
134 | 199 |
|
135 | | -.preview-content :deep(.param) { |
136 | | - color: var(--p-primary-color); |
137 | | - font-weight: 500; |
| 200 | +.terminal-body code { |
| 201 | + font-family: 'JetBrains Mono', 'SF Mono', Monaco, 'Cascadia Code', Consolas, 'Courier New', monospace; |
| 202 | + font-size: 13px; |
| 203 | + line-height: 1.6; |
| 204 | + color: #e6edf3; |
138 | 205 | } |
139 | 206 |
|
140 | | -.preview-content :deep(.flag) { |
141 | | - color: var(--p-primary-color); |
142 | | - font-weight: 500; |
| 207 | +/* ===== Prompt ===== */ |
| 208 | +.prompt { |
| 209 | + color: #7ee787; |
| 210 | + font-weight: 600; |
| 211 | + user-select: none; |
143 | 212 | } |
144 | 213 |
|
145 | | -.preview-content :deep(.string) { |
146 | | - color: var(--p-green-500); |
| 214 | +/* ===== Syntax Highlighting - GitHub Dark Default ===== */ |
| 215 | +.terminal-body :deep(.param) { |
| 216 | + color: #79c0ff; |
| 217 | + font-weight: 500; |
147 | 218 | } |
148 | 219 |
|
149 | | -.preview-content :deep(.number) { |
150 | | - color: var(--p-orange-500); |
| 220 | +.terminal-body :deep(.flag) { |
| 221 | + color: #d2a8ff; |
| 222 | + font-weight: 500; |
151 | 223 | } |
152 | 224 |
|
153 | | -:deep(.app-dark) .preview-content :deep(.string) { |
154 | | - color: var(--p-green-400); |
| 225 | +.terminal-body :deep(.string) { |
| 226 | + color: #a5d6ff; |
155 | 227 | } |
156 | 228 |
|
157 | | -:deep(.app-dark) .preview-content :deep(.number) { |
158 | | - color: var(--p-orange-400); |
| 229 | +.terminal-body :deep(.number) { |
| 230 | + color: #ffa657; |
159 | 231 | } |
160 | 232 | </style> |
0 commit comments