zen-gitsync 2.0.1 → 2.0.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/src/ui/client/package.json +1 -0
- package/src/ui/client/src/App.vue +174 -171
- package/src/ui/client/src/components/CommitForm.vue +591 -290
- package/src/ui/client/src/components/GitStatus.vue +528 -110
- package/src/ui/client/src/components/LogList.vue +351 -85
- package/src/ui/client/src/main.ts +3 -0
- package/src/ui/client/src/stores/gitLogStore.ts +464 -0
- package/src/ui/client/src/stores/gitStore.ts +216 -0
- package/src/ui/client/stats.html +1 -1
- package/src/ui/public/assets/index-D5irnfho.css +1 -0
- package/src/ui/public/assets/index-DBck3u67.js +8 -0
- package/src/ui/public/assets/vendor-CdJ34PvS.js +45 -0
- package/src/ui/public/index.html +3 -3
- package/src/ui/server/index.js +260 -4
- package/src/ui/public/assets/index-BcTk2R6G.js +0 -9
- package/src/ui/public/assets/index-ChUZ1vPG.css +0 -1
- package/src/ui/public/assets/vendor-BAXrrwNU.js +0 -41
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
|
-
import { ref, onMounted,
|
|
3
|
-
import { ElMessage } from "element-plus";
|
|
4
|
-
import { Setting } from "@element-plus/icons-vue";
|
|
5
|
-
|
|
6
|
-
|
|
2
|
+
import { ref, onMounted, computed, watch } from "vue";
|
|
3
|
+
import { ElMessage, ElMessageBox } from "element-plus";
|
|
4
|
+
import { Setting, Plus, Upload, Refresh, Download, Edit } from "@element-plus/icons-vue";
|
|
5
|
+
import { useGitLogStore } from "../stores/gitLogStore";
|
|
6
|
+
import { useGitStore } from "../stores/gitStore";
|
|
7
|
+
|
|
8
|
+
const gitLogStore = useGitLogStore();
|
|
9
|
+
const gitStore = useGitStore();
|
|
10
|
+
const emit = defineEmits(["commit-success", "push-success", "status-update"]);
|
|
7
11
|
const commitMessage = ref("");
|
|
8
|
-
const commitBtnText = ref("提交");
|
|
9
|
-
const pushBtnText = ref("推送到远程");
|
|
10
|
-
const isCommitting = ref(false);
|
|
11
12
|
const isPushing = ref(false);
|
|
12
13
|
// 添加提交并推送的状态变量
|
|
13
14
|
const isCommitAndPushing = ref(false);
|
|
14
|
-
const commitAndPushBtnText = ref("提交并推送");
|
|
15
15
|
const placeholder = ref("输入提交信息...");
|
|
16
16
|
// 添加默认提交信息变量
|
|
17
17
|
const defaultCommitMessage = ref("");
|
|
@@ -27,11 +27,19 @@ const descriptionTemplates = ref<string[]>([]);
|
|
|
27
27
|
// 添加对话框可见性变量
|
|
28
28
|
const descriptionDialogVisible = ref(false);
|
|
29
29
|
const newTemplateName = ref("");
|
|
30
|
+
// 添加模板编辑相关变量
|
|
31
|
+
const isEditingDescription = ref(false);
|
|
32
|
+
const originalDescriptionTemplate = ref("");
|
|
33
|
+
const editingDescriptionIndex = ref(-1);
|
|
30
34
|
|
|
31
35
|
// 作用域模板相关变量
|
|
32
36
|
const scopeTemplates = ref<string[]>([]);
|
|
33
37
|
const scopeDialogVisible = ref(false);
|
|
34
38
|
const newScopeTemplate = ref("");
|
|
39
|
+
// 添加作用域模板编辑相关变量
|
|
40
|
+
const isEditingScope = ref(false);
|
|
41
|
+
const originalScopeTemplate = ref("");
|
|
42
|
+
const editingScopeIndex = ref(-1);
|
|
35
43
|
|
|
36
44
|
// 跳过钩子
|
|
37
45
|
const skipHooks = ref(false);
|
|
@@ -82,6 +90,19 @@ const finalCommitMessage = computed(() => {
|
|
|
82
90
|
return message;
|
|
83
91
|
});
|
|
84
92
|
|
|
93
|
+
// 计算Git命令预览
|
|
94
|
+
const gitCommandPreview = computed(() => {
|
|
95
|
+
// 基本命令
|
|
96
|
+
let command = `git commit -m "${finalCommitMessage.value}"`
|
|
97
|
+
|
|
98
|
+
// 如果跳过钩子开关打开,添加 --no-verify 参数
|
|
99
|
+
if (skipHooks.value) {
|
|
100
|
+
command += ' --no-verify'
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
return command
|
|
104
|
+
});
|
|
105
|
+
|
|
85
106
|
// 加载配置
|
|
86
107
|
async function loadConfig() {
|
|
87
108
|
try {
|
|
@@ -119,51 +140,126 @@ async function saveDescriptionTemplate() {
|
|
|
119
140
|
}
|
|
120
141
|
|
|
121
142
|
try {
|
|
122
|
-
//
|
|
123
|
-
if (
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
143
|
+
// 判断是编辑还是新建
|
|
144
|
+
if (isEditingDescription.value) {
|
|
145
|
+
// 编辑现有模板
|
|
146
|
+
await updateDescriptionTemplate();
|
|
147
|
+
} else {
|
|
148
|
+
// 新建模板
|
|
149
|
+
// 检查是否已存在相同模板
|
|
150
|
+
if (descriptionTemplates.value.includes(newTemplateName.value)) {
|
|
151
|
+
ElMessage({
|
|
152
|
+
message: "该模板已存在",
|
|
153
|
+
type: "warning",
|
|
154
|
+
});
|
|
155
|
+
return;
|
|
156
|
+
}
|
|
130
157
|
|
|
131
|
-
|
|
132
|
-
|
|
158
|
+
// 添加到本地数组
|
|
159
|
+
descriptionTemplates.value.push(newTemplateName.value);
|
|
160
|
+
|
|
161
|
+
// 保存到服务器
|
|
162
|
+
const response = await fetch("/api/config/save-template", {
|
|
163
|
+
method: "POST",
|
|
164
|
+
headers: {
|
|
165
|
+
"Content-Type": "application/json",
|
|
166
|
+
},
|
|
167
|
+
body: JSON.stringify({
|
|
168
|
+
template: newTemplateName.value,
|
|
169
|
+
type: "description",
|
|
170
|
+
}),
|
|
171
|
+
});
|
|
133
172
|
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
173
|
+
const result = await response.json();
|
|
174
|
+
if (result.success) {
|
|
175
|
+
ElMessage({
|
|
176
|
+
message: "模板保存成功!",
|
|
177
|
+
type: "success",
|
|
178
|
+
});
|
|
179
|
+
newTemplateName.value = "";
|
|
180
|
+
} else {
|
|
181
|
+
ElMessage({
|
|
182
|
+
message: "模板保存失败: " + result.error,
|
|
183
|
+
type: "error",
|
|
184
|
+
});
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
} catch (error) {
|
|
188
|
+
ElMessage({
|
|
189
|
+
message: "模板保存失败: " + (error as Error).message,
|
|
190
|
+
type: "error",
|
|
144
191
|
});
|
|
192
|
+
}
|
|
193
|
+
}
|
|
145
194
|
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
195
|
+
// 编辑描述模板
|
|
196
|
+
async function updateDescriptionTemplate() {
|
|
197
|
+
try {
|
|
198
|
+
// 先从本地数组中更新
|
|
199
|
+
if (editingDescriptionIndex.value >= 0) {
|
|
200
|
+
// 保存原模板和新模板
|
|
201
|
+
const oldTemplate = originalDescriptionTemplate.value;
|
|
202
|
+
const newTemplate = newTemplateName.value;
|
|
203
|
+
|
|
204
|
+
// 更新本地数组
|
|
205
|
+
descriptionTemplates.value[editingDescriptionIndex.value] = newTemplate;
|
|
206
|
+
|
|
207
|
+
// 调用API更新服务器
|
|
208
|
+
const response = await fetch("/api/config/update-template", {
|
|
209
|
+
method: "POST",
|
|
210
|
+
headers: {
|
|
211
|
+
"Content-Type": "application/json",
|
|
212
|
+
},
|
|
213
|
+
body: JSON.stringify({
|
|
214
|
+
oldTemplate,
|
|
215
|
+
newTemplate,
|
|
216
|
+
type: "description",
|
|
217
|
+
}),
|
|
157
218
|
});
|
|
219
|
+
|
|
220
|
+
const result = await response.json();
|
|
221
|
+
if (result.success) {
|
|
222
|
+
ElMessage({
|
|
223
|
+
message: "模板更新成功!",
|
|
224
|
+
type: "success",
|
|
225
|
+
});
|
|
226
|
+
|
|
227
|
+
// 重置编辑状态
|
|
228
|
+
isEditingDescription.value = false;
|
|
229
|
+
originalDescriptionTemplate.value = "";
|
|
230
|
+
editingDescriptionIndex.value = -1;
|
|
231
|
+
newTemplateName.value = "";
|
|
232
|
+
} else {
|
|
233
|
+
ElMessage({
|
|
234
|
+
message: "模板更新失败: " + result.error,
|
|
235
|
+
type: "error",
|
|
236
|
+
});
|
|
237
|
+
}
|
|
158
238
|
}
|
|
159
239
|
} catch (error) {
|
|
160
240
|
ElMessage({
|
|
161
|
-
message: "
|
|
241
|
+
message: "模板更新失败: " + (error as Error).message,
|
|
162
242
|
type: "error",
|
|
163
243
|
});
|
|
164
244
|
}
|
|
165
245
|
}
|
|
166
246
|
|
|
247
|
+
// 开始编辑描述模板
|
|
248
|
+
function startEditDescriptionTemplate(template: string, index: number) {
|
|
249
|
+
isEditingDescription.value = true;
|
|
250
|
+
originalDescriptionTemplate.value = template;
|
|
251
|
+
editingDescriptionIndex.value = index;
|
|
252
|
+
newTemplateName.value = template;
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
// 取消编辑描述模板
|
|
256
|
+
function cancelEditDescriptionTemplate() {
|
|
257
|
+
isEditingDescription.value = false;
|
|
258
|
+
originalDescriptionTemplate.value = "";
|
|
259
|
+
editingDescriptionIndex.value = -1;
|
|
260
|
+
newTemplateName.value = "";
|
|
261
|
+
}
|
|
262
|
+
|
|
167
263
|
// 保存作用域模板
|
|
168
264
|
async function saveScopeTemplate() {
|
|
169
265
|
if (!newScopeTemplate.value.trim()) {
|
|
@@ -175,51 +271,126 @@ async function saveScopeTemplate() {
|
|
|
175
271
|
}
|
|
176
272
|
|
|
177
273
|
try {
|
|
178
|
-
//
|
|
179
|
-
if (
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
274
|
+
// 判断是编辑还是新建
|
|
275
|
+
if (isEditingScope.value) {
|
|
276
|
+
// 编辑现有模板
|
|
277
|
+
await updateScopeTemplate();
|
|
278
|
+
} else {
|
|
279
|
+
// 新建模板
|
|
280
|
+
// 检查是否已存在相同模板
|
|
281
|
+
if (scopeTemplates.value.includes(newScopeTemplate.value)) {
|
|
282
|
+
ElMessage({
|
|
283
|
+
message: "该模板已存在",
|
|
284
|
+
type: "warning",
|
|
285
|
+
});
|
|
286
|
+
return;
|
|
287
|
+
}
|
|
186
288
|
|
|
187
|
-
|
|
188
|
-
|
|
289
|
+
// 添加到本地数组
|
|
290
|
+
scopeTemplates.value.push(newScopeTemplate.value);
|
|
291
|
+
|
|
292
|
+
// 保存到服务器
|
|
293
|
+
const response = await fetch("/api/config/save-template", {
|
|
294
|
+
method: "POST",
|
|
295
|
+
headers: {
|
|
296
|
+
"Content-Type": "application/json",
|
|
297
|
+
},
|
|
298
|
+
body: JSON.stringify({
|
|
299
|
+
template: newScopeTemplate.value,
|
|
300
|
+
type: "scope",
|
|
301
|
+
}),
|
|
302
|
+
});
|
|
189
303
|
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
304
|
+
const result = await response.json();
|
|
305
|
+
if (result.success) {
|
|
306
|
+
ElMessage({
|
|
307
|
+
message: "作用域模板保存成功!",
|
|
308
|
+
type: "success",
|
|
309
|
+
});
|
|
310
|
+
newScopeTemplate.value = "";
|
|
311
|
+
} else {
|
|
312
|
+
ElMessage({
|
|
313
|
+
message: "作用域模板保存失败: " + result.error,
|
|
314
|
+
type: "error",
|
|
315
|
+
});
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
} catch (error) {
|
|
319
|
+
ElMessage({
|
|
320
|
+
message: "作用域模板保存失败: " + (error as Error).message,
|
|
321
|
+
type: "error",
|
|
200
322
|
});
|
|
323
|
+
}
|
|
324
|
+
}
|
|
201
325
|
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
326
|
+
// 更新作用域模板
|
|
327
|
+
async function updateScopeTemplate() {
|
|
328
|
+
try {
|
|
329
|
+
// 先从本地数组中更新
|
|
330
|
+
if (editingScopeIndex.value >= 0) {
|
|
331
|
+
// 保存原模板和新模板
|
|
332
|
+
const oldTemplate = originalScopeTemplate.value;
|
|
333
|
+
const newTemplate = newScopeTemplate.value;
|
|
334
|
+
|
|
335
|
+
// 更新本地数组
|
|
336
|
+
scopeTemplates.value[editingScopeIndex.value] = newTemplate;
|
|
337
|
+
|
|
338
|
+
// 调用API更新服务器
|
|
339
|
+
const response = await fetch("/api/config/update-template", {
|
|
340
|
+
method: "POST",
|
|
341
|
+
headers: {
|
|
342
|
+
"Content-Type": "application/json",
|
|
343
|
+
},
|
|
344
|
+
body: JSON.stringify({
|
|
345
|
+
oldTemplate,
|
|
346
|
+
newTemplate,
|
|
347
|
+
type: "scope",
|
|
348
|
+
}),
|
|
213
349
|
});
|
|
350
|
+
|
|
351
|
+
const result = await response.json();
|
|
352
|
+
if (result.success) {
|
|
353
|
+
ElMessage({
|
|
354
|
+
message: "作用域模板更新成功!",
|
|
355
|
+
type: "success",
|
|
356
|
+
});
|
|
357
|
+
|
|
358
|
+
// 重置编辑状态
|
|
359
|
+
isEditingScope.value = false;
|
|
360
|
+
originalScopeTemplate.value = "";
|
|
361
|
+
editingScopeIndex.value = -1;
|
|
362
|
+
newScopeTemplate.value = "";
|
|
363
|
+
} else {
|
|
364
|
+
ElMessage({
|
|
365
|
+
message: "作用域模板更新失败: " + result.error,
|
|
366
|
+
type: "error",
|
|
367
|
+
});
|
|
368
|
+
}
|
|
214
369
|
}
|
|
215
370
|
} catch (error) {
|
|
216
371
|
ElMessage({
|
|
217
|
-
message: "
|
|
372
|
+
message: "作用域模板更新失败: " + (error as Error).message,
|
|
218
373
|
type: "error",
|
|
219
374
|
});
|
|
220
375
|
}
|
|
221
376
|
}
|
|
222
377
|
|
|
378
|
+
// 开始编辑作用域模板
|
|
379
|
+
function startEditScopeTemplate(template: string, index: number) {
|
|
380
|
+
isEditingScope.value = true;
|
|
381
|
+
originalScopeTemplate.value = template;
|
|
382
|
+
editingScopeIndex.value = index;
|
|
383
|
+
newScopeTemplate.value = template;
|
|
384
|
+
}
|
|
385
|
+
|
|
386
|
+
// 取消编辑作用域模板
|
|
387
|
+
function cancelEditScopeTemplate() {
|
|
388
|
+
isEditingScope.value = false;
|
|
389
|
+
originalScopeTemplate.value = "";
|
|
390
|
+
editingScopeIndex.value = -1;
|
|
391
|
+
newScopeTemplate.value = "";
|
|
392
|
+
}
|
|
393
|
+
|
|
223
394
|
// 删除描述模板
|
|
224
395
|
async function deleteDescriptionTemplate(template: string) {
|
|
225
396
|
try {
|
|
@@ -324,231 +495,225 @@ function openScopeSettings() {
|
|
|
324
495
|
scopeDialogVisible.value = true;
|
|
325
496
|
}
|
|
326
497
|
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
498
|
+
// 添加文件到暂存区 (git add)
|
|
499
|
+
async function addToStage() {
|
|
500
|
+
try {
|
|
501
|
+
const result = await gitLogStore.addToStage();
|
|
502
|
+
if (result) {
|
|
503
|
+
// 触发状态更新事件
|
|
504
|
+
emit("status-update");
|
|
505
|
+
}
|
|
506
|
+
} catch (error) {
|
|
507
|
+
ElMessage({
|
|
508
|
+
message: `添加文件失败: ${(error as Error).message}`,
|
|
509
|
+
type: "error",
|
|
510
|
+
});
|
|
339
511
|
}
|
|
340
512
|
}
|
|
341
513
|
|
|
342
|
-
// 提交更改
|
|
514
|
+
// 提交更改 (git commit)
|
|
343
515
|
async function commitChanges() {
|
|
344
|
-
|
|
345
|
-
if (!message && isStandardCommit.value && !commitDescription.value) {
|
|
516
|
+
if (!finalCommitMessage.value.trim()) {
|
|
346
517
|
ElMessage({
|
|
347
|
-
message: "
|
|
518
|
+
message: "提交信息不能为空",
|
|
348
519
|
type: "warning",
|
|
349
520
|
});
|
|
350
521
|
return;
|
|
351
522
|
}
|
|
352
523
|
|
|
353
524
|
try {
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
// 先执行 git add .
|
|
358
|
-
const addResponse = await fetch("/api/add", {
|
|
359
|
-
method: "POST",
|
|
360
|
-
});
|
|
525
|
+
// 使用Store提交更改
|
|
526
|
+
const result = await gitLogStore.commitChanges(finalCommitMessage.value, skipHooks.value);
|
|
361
527
|
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
});
|
|
368
|
-
return;
|
|
369
|
-
}
|
|
370
|
-
|
|
371
|
-
const response = await fetch("/api/commit", {
|
|
372
|
-
method: "POST",
|
|
373
|
-
headers: {
|
|
374
|
-
"Content-Type": "application/json",
|
|
375
|
-
},
|
|
376
|
-
body: JSON.stringify({
|
|
377
|
-
message,
|
|
378
|
-
// 添加一个标志,表示消息包含换行符
|
|
379
|
-
hasNewlines: message.includes("\n"),
|
|
380
|
-
// 添加 no-verify 选项
|
|
381
|
-
noVerify: skipHooks.value,
|
|
382
|
-
}),
|
|
383
|
-
});
|
|
384
|
-
|
|
385
|
-
const result = await response.json();
|
|
386
|
-
if (result.success) {
|
|
387
|
-
// 清空输入
|
|
388
|
-
if (isStandardCommit.value) {
|
|
389
|
-
commitDescription.value = "";
|
|
390
|
-
commitBody.value = "";
|
|
391
|
-
commitFooter.value = "";
|
|
392
|
-
} else {
|
|
393
|
-
commitMessage.value = "";
|
|
394
|
-
}
|
|
395
|
-
|
|
396
|
-
ElMessage({
|
|
397
|
-
message: "提交成功!",
|
|
398
|
-
type: "success",
|
|
399
|
-
});
|
|
400
|
-
// 发出提交成功事件
|
|
528
|
+
if (result) {
|
|
529
|
+
// 清空提交信息
|
|
530
|
+
clearCommitFields();
|
|
531
|
+
|
|
532
|
+
// 触发成功事件
|
|
401
533
|
emit("commit-success");
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
message: "提交失败: " + result.error,
|
|
405
|
-
type: "error",
|
|
406
|
-
});
|
|
534
|
+
// 触发状态更新事件
|
|
535
|
+
emit("status-update");
|
|
407
536
|
}
|
|
408
537
|
} catch (error) {
|
|
409
538
|
ElMessage({
|
|
410
|
-
message:
|
|
539
|
+
message: `提交失败: ${(error as Error).message}`,
|
|
411
540
|
type: "error",
|
|
412
541
|
});
|
|
413
|
-
} finally {
|
|
414
|
-
isCommitting.value = false;
|
|
415
|
-
commitBtnText.value = "提交";
|
|
416
542
|
}
|
|
417
543
|
}
|
|
418
544
|
|
|
419
|
-
//
|
|
420
|
-
async function
|
|
545
|
+
// 推送到远程 (git push)
|
|
546
|
+
async function pushToRemote() {
|
|
421
547
|
try {
|
|
422
|
-
isPushing.value = true
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
const result = await response.json();
|
|
430
|
-
if (result.success) {
|
|
431
|
-
ElMessage({
|
|
432
|
-
message: "推送成功!",
|
|
433
|
-
type: "success",
|
|
434
|
-
});
|
|
435
|
-
// 发出推送成功事件
|
|
548
|
+
isPushing.value = true
|
|
549
|
+
// 使用Store推送更改
|
|
550
|
+
const result = await gitLogStore.pushToRemote();
|
|
551
|
+
|
|
552
|
+
if (result) {
|
|
553
|
+
// 触发成功事件
|
|
436
554
|
emit("push-success");
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
message: "推送失败: " + result.error,
|
|
440
|
-
type: "error",
|
|
441
|
-
});
|
|
555
|
+
// 触发状态更新事件
|
|
556
|
+
emit("status-update");
|
|
442
557
|
}
|
|
443
558
|
} catch (error) {
|
|
444
559
|
ElMessage({
|
|
445
|
-
message:
|
|
560
|
+
message: `推送失败: ${(error as Error).message}`,
|
|
446
561
|
type: "error",
|
|
447
562
|
});
|
|
448
563
|
} finally {
|
|
449
|
-
isPushing.value = false
|
|
450
|
-
pushBtnText.value = "推送到远程";
|
|
564
|
+
isPushing.value = false
|
|
451
565
|
}
|
|
452
566
|
}
|
|
453
567
|
|
|
454
|
-
//
|
|
455
|
-
async function
|
|
456
|
-
|
|
457
|
-
if (!message && isStandardCommit.value && !commitDescription.value) {
|
|
568
|
+
// 添加并提交 (git add + git commit)
|
|
569
|
+
async function addAndCommit() {
|
|
570
|
+
if (!finalCommitMessage.value.trim()) {
|
|
458
571
|
ElMessage({
|
|
459
|
-
message: "
|
|
572
|
+
message: "提交信息不能为空",
|
|
460
573
|
type: "warning",
|
|
461
574
|
});
|
|
462
575
|
return;
|
|
463
576
|
}
|
|
464
577
|
|
|
465
578
|
try {
|
|
466
|
-
|
|
467
|
-
|
|
579
|
+
const result = await gitLogStore.addAndCommit(finalCommitMessage.value, skipHooks.value);
|
|
580
|
+
|
|
581
|
+
if (result) {
|
|
582
|
+
// 清空提交信息
|
|
583
|
+
clearCommitFields();
|
|
584
|
+
|
|
585
|
+
// 触发成功事件
|
|
586
|
+
emit("commit-success");
|
|
587
|
+
// 触发状态更新事件
|
|
588
|
+
emit("status-update");
|
|
589
|
+
}
|
|
590
|
+
} catch (error) {
|
|
591
|
+
ElMessage({
|
|
592
|
+
message: `暂存并提交失败: ${(error as Error).message}`,
|
|
593
|
+
type: "error",
|
|
594
|
+
});
|
|
595
|
+
}
|
|
596
|
+
}
|
|
468
597
|
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
598
|
+
// 添加、提交并推送 (git add + git commit + git push)
|
|
599
|
+
async function addCommitAndPush() {
|
|
600
|
+
if (!finalCommitMessage.value.trim()) {
|
|
601
|
+
ElMessage({
|
|
602
|
+
message: "提交信息不能为空",
|
|
603
|
+
type: "warning",
|
|
472
604
|
});
|
|
605
|
+
return;
|
|
606
|
+
}
|
|
607
|
+
|
|
608
|
+
try {
|
|
609
|
+
isCommitAndPushing.value = true
|
|
610
|
+
const result = await gitLogStore.addCommitAndPush(finalCommitMessage.value, skipHooks.value);
|
|
473
611
|
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
612
|
+
if (result) {
|
|
613
|
+
// 清空提交信息
|
|
614
|
+
clearCommitFields();
|
|
615
|
+
|
|
616
|
+
// 触发成功事件
|
|
617
|
+
emit("commit-success");
|
|
618
|
+
|
|
619
|
+
// 添加小延迟后再触发推送成功事件,确保提交历史能够刷新
|
|
620
|
+
setTimeout(() => {
|
|
621
|
+
emit("push-success");
|
|
622
|
+
}, 300);
|
|
623
|
+
|
|
624
|
+
// 触发状态更新事件
|
|
625
|
+
emit("status-update");
|
|
481
626
|
}
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
headers: {
|
|
487
|
-
"Content-Type": "application/json",
|
|
488
|
-
},
|
|
489
|
-
body: JSON.stringify({
|
|
490
|
-
message,
|
|
491
|
-
// 添加一个标志,表示消息包含换行符
|
|
492
|
-
hasNewlines: message.includes("\n"),
|
|
493
|
-
// 添加 no-verify 选项
|
|
494
|
-
noVerify: skipHooks.value,
|
|
495
|
-
}),
|
|
627
|
+
} catch (error) {
|
|
628
|
+
ElMessage({
|
|
629
|
+
message: `暂存、提交并推送失败: ${(error as Error).message}`,
|
|
630
|
+
type: "error",
|
|
496
631
|
});
|
|
632
|
+
} finally {
|
|
633
|
+
isCommitAndPushing.value = false
|
|
634
|
+
}
|
|
635
|
+
}
|
|
497
636
|
|
|
498
|
-
|
|
499
|
-
|
|
637
|
+
// 重置暂存区 (git reset HEAD)
|
|
638
|
+
async function resetHead() {
|
|
639
|
+
try {
|
|
640
|
+
await ElMessageBox.confirm(
|
|
641
|
+
'确定要重置暂存区吗?这将取消所有已暂存的更改,但不会影响工作区的文件。',
|
|
642
|
+
'重置暂存区',
|
|
643
|
+
{
|
|
644
|
+
confirmButtonText: '确定',
|
|
645
|
+
cancelButtonText: '取消',
|
|
646
|
+
type: 'warning'
|
|
647
|
+
}
|
|
648
|
+
);
|
|
649
|
+
|
|
650
|
+
const result = await gitLogStore.resetHead();
|
|
651
|
+
if (result) {
|
|
652
|
+
// 触发状态更新事件
|
|
653
|
+
emit("status-update");
|
|
654
|
+
}
|
|
655
|
+
} catch (error) {
|
|
656
|
+
// 用户取消操作,不显示错误
|
|
657
|
+
if ((error as any) !== 'cancel') {
|
|
500
658
|
ElMessage({
|
|
501
|
-
message:
|
|
502
|
-
type:
|
|
659
|
+
message: `重置暂存区失败: ${(error as Error).message}`,
|
|
660
|
+
type: 'error'
|
|
503
661
|
});
|
|
504
|
-
return;
|
|
505
662
|
}
|
|
663
|
+
}
|
|
664
|
+
}
|
|
506
665
|
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
666
|
+
// 重置到远程分支 (git reset --hard origin/branch)
|
|
667
|
+
async function resetToRemote() {
|
|
668
|
+
try {
|
|
669
|
+
await ElMessageBox.confirm(
|
|
670
|
+
`确定要重置当前分支 "${gitStore.currentBranch}" 到远程状态吗?这将丢失所有未推送的提交和本地更改。`,
|
|
671
|
+
'重置到远程分支',
|
|
672
|
+
{
|
|
673
|
+
confirmButtonText: '确定',
|
|
674
|
+
cancelButtonText: '取消',
|
|
675
|
+
type: 'warning'
|
|
676
|
+
}
|
|
677
|
+
);
|
|
678
|
+
|
|
679
|
+
const result = await gitLogStore.resetToRemote(gitStore.currentBranch);
|
|
680
|
+
if (result) {
|
|
681
|
+
// 触发状态更新事件
|
|
682
|
+
emit("status-update");
|
|
514
683
|
}
|
|
515
|
-
|
|
516
|
-
//
|
|
517
|
-
|
|
518
|
-
method: "POST",
|
|
519
|
-
});
|
|
520
|
-
|
|
521
|
-
const pushResult = await pushResponse.json();
|
|
522
|
-
if (pushResult.success) {
|
|
523
|
-
commitMessage.value = "";
|
|
524
|
-
ElMessage({
|
|
525
|
-
message: "提交并推送成功!",
|
|
526
|
-
type: "success",
|
|
527
|
-
});
|
|
528
|
-
// 发出提交和推送成功事件
|
|
529
|
-
emit("commit-success");
|
|
530
|
-
emit("push-success");
|
|
531
|
-
} else {
|
|
684
|
+
} catch (error) {
|
|
685
|
+
// 用户取消操作,不显示错误
|
|
686
|
+
if ((error as any) !== 'cancel') {
|
|
532
687
|
ElMessage({
|
|
533
|
-
message:
|
|
534
|
-
type:
|
|
688
|
+
message: `重置到远程分支失败: ${(error as Error).message}`,
|
|
689
|
+
type: 'error'
|
|
535
690
|
});
|
|
536
691
|
}
|
|
537
|
-
} catch (error) {
|
|
538
|
-
ElMessage({
|
|
539
|
-
message: "操作失败: " + (error as Error).message,
|
|
540
|
-
type: "error",
|
|
541
|
-
});
|
|
542
|
-
} finally {
|
|
543
|
-
isCommitAndPushing.value = false;
|
|
544
|
-
commitAndPushBtnText.value = "提交并推送";
|
|
545
692
|
}
|
|
546
693
|
}
|
|
547
694
|
|
|
695
|
+
// 清空提交字段
|
|
696
|
+
function clearCommitFields() {
|
|
697
|
+
commitMessage.value = "";
|
|
698
|
+
commitDescription.value = "";
|
|
699
|
+
commitBody.value = "";
|
|
700
|
+
commitFooter.value = "";
|
|
701
|
+
}
|
|
548
702
|
|
|
549
703
|
onMounted(() => {
|
|
550
704
|
loadConfig();
|
|
551
|
-
|
|
705
|
+
|
|
706
|
+
// 从 localStorage 中获取标准化提交设置
|
|
707
|
+
const savedStandardCommit = localStorage.getItem("zen-gitsync-standard-commit");
|
|
708
|
+
if (savedStandardCommit !== null) {
|
|
709
|
+
isStandardCommit.value = savedStandardCommit === "true";
|
|
710
|
+
}
|
|
711
|
+
|
|
712
|
+
// 从 localStorage 中获取跳过钩子设置
|
|
713
|
+
const savedSkipHooks = localStorage.getItem("zen-gitsync-skip-hooks");
|
|
714
|
+
if (savedSkipHooks !== null) {
|
|
715
|
+
skipHooks.value = savedSkipHooks === "true";
|
|
716
|
+
}
|
|
552
717
|
});
|
|
553
718
|
</script>
|
|
554
719
|
|
|
@@ -557,30 +722,26 @@ onMounted(() => {
|
|
|
557
722
|
<h2>提交更改</h2>
|
|
558
723
|
|
|
559
724
|
<div class="commit-options">
|
|
560
|
-
<div class="
|
|
561
|
-
<
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
725
|
+
<div class="options-row">
|
|
726
|
+
<div class="commit-mode-toggle">
|
|
727
|
+
<el-switch
|
|
728
|
+
v-model="isStandardCommit"
|
|
729
|
+
active-text="标准化提交"
|
|
730
|
+
inactive-text="普通提交"
|
|
731
|
+
/>
|
|
732
|
+
</div>
|
|
567
733
|
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
734
|
+
<div class="no-verify-toggle">
|
|
735
|
+
<el-tooltip content="跳过 Git 钩子检查 (--no-verify)" placement="top">
|
|
736
|
+
<el-switch v-model="skipHooks" active-text="跳过钩子 (--no-verify)" />
|
|
737
|
+
</el-tooltip>
|
|
738
|
+
</div>
|
|
572
739
|
</div>
|
|
573
740
|
</div>
|
|
574
741
|
|
|
575
742
|
<!-- 普通提交表单 -->
|
|
576
743
|
<div v-if="!isStandardCommit" class="commit-form">
|
|
577
744
|
<el-input v-model="commitMessage" :placeholder="placeholder" clearable />
|
|
578
|
-
<el-button
|
|
579
|
-
type="primary"
|
|
580
|
-
@click="commitChanges"
|
|
581
|
-
:loading="isCommitting"
|
|
582
|
-
>{{ commitBtnText }}</el-button
|
|
583
|
-
>
|
|
584
745
|
</div>
|
|
585
746
|
|
|
586
747
|
<!-- 标准化提交表单 -->
|
|
@@ -654,28 +815,79 @@ onMounted(() => {
|
|
|
654
815
|
/>
|
|
655
816
|
|
|
656
817
|
<div class="preview-section">
|
|
657
|
-
<div class="preview-title"
|
|
818
|
+
<div class="preview-title">提交信息预览:</div>
|
|
658
819
|
<pre class="preview-content">{{ finalCommitMessage }}</pre>
|
|
820
|
+
|
|
821
|
+
<div class="preview-title" style="margin-top: 10px;">Git命令预览:</div>
|
|
822
|
+
<pre class="preview-content code-command">{{ gitCommandPreview }}</pre>
|
|
659
823
|
</div>
|
|
660
|
-
|
|
661
|
-
<el-button
|
|
662
|
-
type="primary"
|
|
663
|
-
@click="commitChanges"
|
|
664
|
-
:loading="isCommitting"
|
|
665
|
-
>{{ commitBtnText }}</el-button
|
|
666
|
-
>
|
|
667
824
|
</div>
|
|
668
825
|
|
|
669
|
-
<div class="
|
|
670
|
-
<
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
826
|
+
<div class="git-actions">
|
|
827
|
+
<div class="action-row">
|
|
828
|
+
<el-button
|
|
829
|
+
type="primary"
|
|
830
|
+
@click="addToStage"
|
|
831
|
+
:loading="gitLogStore.isAddingFiles"
|
|
832
|
+
:icon="Plus"
|
|
833
|
+
>
|
|
834
|
+
添加到暂存区(git add .)
|
|
835
|
+
</el-button>
|
|
836
|
+
|
|
837
|
+
<el-button
|
|
838
|
+
type="primary"
|
|
839
|
+
@click="commitChanges"
|
|
840
|
+
:loading="gitLogStore.isLoadingStatus"
|
|
841
|
+
>
|
|
842
|
+
提交(git commit)
|
|
843
|
+
</el-button>
|
|
844
|
+
|
|
845
|
+
<el-button
|
|
846
|
+
type="success"
|
|
847
|
+
@click="pushToRemote"
|
|
848
|
+
:icon="Upload"
|
|
849
|
+
:loading="isPushing"
|
|
850
|
+
>
|
|
851
|
+
推送(git push)
|
|
852
|
+
</el-button>
|
|
853
|
+
</div>
|
|
854
|
+
|
|
855
|
+
<div class="action-row">
|
|
856
|
+
<el-button
|
|
857
|
+
type="warning"
|
|
858
|
+
@click="addAndCommit"
|
|
859
|
+
>
|
|
860
|
+
添加并提交(git add+commit)
|
|
861
|
+
</el-button>
|
|
862
|
+
|
|
863
|
+
<el-button
|
|
864
|
+
type="danger"
|
|
865
|
+
@click="addCommitAndPush"
|
|
866
|
+
:loading="isCommitAndPushing"
|
|
867
|
+
>
|
|
868
|
+
添加、提交并推送(git add+commit+push)
|
|
869
|
+
</el-button>
|
|
870
|
+
</div>
|
|
871
|
+
|
|
872
|
+
<div class="action-row">
|
|
873
|
+
<el-button
|
|
874
|
+
type="info"
|
|
875
|
+
@click="resetHead"
|
|
876
|
+
:loading="gitLogStore.isResetting"
|
|
877
|
+
:icon="Refresh"
|
|
878
|
+
>
|
|
879
|
+
重置暂存区(git reset HEAD)
|
|
880
|
+
</el-button>
|
|
881
|
+
|
|
882
|
+
<el-button
|
|
883
|
+
type="info"
|
|
884
|
+
@click="resetToRemote"
|
|
885
|
+
:loading="gitLogStore.isResetting"
|
|
886
|
+
:icon="Download"
|
|
887
|
+
>
|
|
888
|
+
重置到远程(git reset --hard origin/branch)
|
|
889
|
+
</el-button>
|
|
890
|
+
</div>
|
|
679
891
|
</div>
|
|
680
892
|
|
|
681
893
|
<!-- 简短描述设置弹窗 -->
|
|
@@ -689,16 +901,23 @@ onMounted(() => {
|
|
|
689
901
|
<div class="template-form">
|
|
690
902
|
<el-input
|
|
691
903
|
v-model="newTemplateName"
|
|
692
|
-
placeholder="输入新模板内容"
|
|
904
|
+
:placeholder="isEditingDescription ? '编辑模板内容' : '输入新模板内容'"
|
|
693
905
|
class="template-input"
|
|
694
906
|
clearable
|
|
695
907
|
/>
|
|
696
|
-
<
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
908
|
+
<div class="template-form-buttons">
|
|
909
|
+
<el-button
|
|
910
|
+
v-if="isEditingDescription"
|
|
911
|
+
@click="cancelEditDescriptionTemplate"
|
|
912
|
+
>取消</el-button
|
|
913
|
+
>
|
|
914
|
+
<el-button
|
|
915
|
+
type="primary"
|
|
916
|
+
@click="saveDescriptionTemplate"
|
|
917
|
+
:disabled="!newTemplateName.trim()"
|
|
918
|
+
>{{ isEditingDescription ? '更新模板' : '添加模板' }}</el-button
|
|
919
|
+
>
|
|
920
|
+
</div>
|
|
702
921
|
</div>
|
|
703
922
|
|
|
704
923
|
<div class="template-list">
|
|
@@ -722,6 +941,13 @@ onMounted(() => {
|
|
|
722
941
|
@click="useTemplate(template)"
|
|
723
942
|
>使用</el-button
|
|
724
943
|
>
|
|
944
|
+
<el-button
|
|
945
|
+
type="warning"
|
|
946
|
+
size="small"
|
|
947
|
+
:icon="Edit"
|
|
948
|
+
@click="startEditDescriptionTemplate(template, index)"
|
|
949
|
+
>编辑</el-button
|
|
950
|
+
>
|
|
725
951
|
<el-button
|
|
726
952
|
type="danger"
|
|
727
953
|
size="small"
|
|
@@ -746,16 +972,23 @@ onMounted(() => {
|
|
|
746
972
|
<div class="template-form">
|
|
747
973
|
<el-input
|
|
748
974
|
v-model="newScopeTemplate"
|
|
749
|
-
placeholder="输入新作用域模板"
|
|
975
|
+
:placeholder="isEditingScope ? '编辑作用域模板内容' : '输入新作用域模板'"
|
|
750
976
|
class="template-input"
|
|
751
977
|
clearable
|
|
752
978
|
/>
|
|
753
|
-
<
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
979
|
+
<div class="template-form-buttons">
|
|
980
|
+
<el-button
|
|
981
|
+
v-if="isEditingScope"
|
|
982
|
+
@click="cancelEditScopeTemplate"
|
|
983
|
+
>取消</el-button
|
|
984
|
+
>
|
|
985
|
+
<el-button
|
|
986
|
+
type="primary"
|
|
987
|
+
@click="saveScopeTemplate"
|
|
988
|
+
:disabled="!newScopeTemplate.trim()"
|
|
989
|
+
>{{ isEditingScope ? '更新模板' : '添加模板' }}</el-button
|
|
990
|
+
>
|
|
991
|
+
</div>
|
|
759
992
|
</div>
|
|
760
993
|
|
|
761
994
|
<div class="template-list">
|
|
@@ -778,6 +1011,13 @@ onMounted(() => {
|
|
|
778
1011
|
@click="useScopeTemplate(template)"
|
|
779
1012
|
>使用</el-button
|
|
780
1013
|
>
|
|
1014
|
+
<el-button
|
|
1015
|
+
type="warning"
|
|
1016
|
+
size="small"
|
|
1017
|
+
:icon="Edit"
|
|
1018
|
+
@click="startEditScopeTemplate(template, index)"
|
|
1019
|
+
>编辑</el-button
|
|
1020
|
+
>
|
|
781
1021
|
<el-button
|
|
782
1022
|
type="danger"
|
|
783
1023
|
size="small"
|
|
@@ -794,33 +1034,55 @@ onMounted(() => {
|
|
|
794
1034
|
</template>
|
|
795
1035
|
|
|
796
1036
|
<style scoped>
|
|
1037
|
+
.card {
|
|
1038
|
+
background-color: white;
|
|
1039
|
+
border-radius: 5px;
|
|
1040
|
+
box-shadow: 0 2px 5px rgba(0,0,0,0.1);
|
|
1041
|
+
margin-bottom: 20px;
|
|
1042
|
+
padding: 20px;
|
|
1043
|
+
}
|
|
1044
|
+
|
|
797
1045
|
.commit-form {
|
|
798
1046
|
display: flex;
|
|
799
1047
|
margin-bottom: 15px;
|
|
800
1048
|
gap: 10px;
|
|
801
1049
|
}
|
|
802
|
-
|
|
1050
|
+
|
|
1051
|
+
.git-actions {
|
|
1052
|
+
margin-top: 20px;
|
|
1053
|
+
display: flex;
|
|
1054
|
+
flex-direction: column;
|
|
1055
|
+
gap: 10px;
|
|
1056
|
+
}
|
|
1057
|
+
|
|
1058
|
+
.action-row {
|
|
803
1059
|
display: flex;
|
|
804
1060
|
gap: 10px;
|
|
1061
|
+
flex-wrap: wrap;
|
|
805
1062
|
}
|
|
1063
|
+
|
|
806
1064
|
.commit-mode-toggle {
|
|
807
|
-
margin-bottom
|
|
1065
|
+
/* 移除margin-bottom */
|
|
808
1066
|
}
|
|
1067
|
+
|
|
809
1068
|
.standard-commit-form {
|
|
810
1069
|
display: flex;
|
|
811
1070
|
flex-direction: column;
|
|
812
1071
|
gap: 15px;
|
|
813
1072
|
margin-bottom: 15px;
|
|
814
1073
|
}
|
|
1074
|
+
|
|
815
1075
|
.standard-commit-header {
|
|
816
1076
|
display: flex;
|
|
817
1077
|
gap: 10px;
|
|
818
1078
|
width: 100%;
|
|
819
1079
|
}
|
|
1080
|
+
|
|
820
1081
|
.type-select {
|
|
821
1082
|
width: 120px;
|
|
822
1083
|
flex-shrink: 0;
|
|
823
1084
|
}
|
|
1085
|
+
|
|
824
1086
|
.scope-container {
|
|
825
1087
|
display: flex;
|
|
826
1088
|
align-items: center;
|
|
@@ -828,31 +1090,38 @@ onMounted(() => {
|
|
|
828
1090
|
flex-grow: 0;
|
|
829
1091
|
width: 200px;
|
|
830
1092
|
}
|
|
1093
|
+
|
|
831
1094
|
.scope-input {
|
|
832
1095
|
flex-grow: 1;
|
|
833
1096
|
}
|
|
1097
|
+
|
|
834
1098
|
.description-container {
|
|
835
1099
|
display: flex;
|
|
836
1100
|
align-items: center;
|
|
837
1101
|
gap: 5px;
|
|
838
1102
|
flex-grow: 1;
|
|
839
1103
|
}
|
|
1104
|
+
|
|
840
1105
|
.description-input {
|
|
841
1106
|
flex-grow: 1;
|
|
842
1107
|
min-width: 200px;
|
|
843
1108
|
}
|
|
1109
|
+
|
|
844
1110
|
.settings-button {
|
|
845
1111
|
flex-shrink: 0;
|
|
846
1112
|
}
|
|
1113
|
+
|
|
847
1114
|
.preview-section {
|
|
848
1115
|
background-color: #f5f7fa;
|
|
849
1116
|
padding: 10px;
|
|
850
1117
|
border-radius: 4px;
|
|
851
1118
|
}
|
|
1119
|
+
|
|
852
1120
|
.preview-title {
|
|
853
1121
|
font-weight: bold;
|
|
854
1122
|
margin-bottom: 5px;
|
|
855
1123
|
}
|
|
1124
|
+
|
|
856
1125
|
.preview-content {
|
|
857
1126
|
white-space: pre-wrap;
|
|
858
1127
|
font-family: monospace;
|
|
@@ -861,6 +1130,7 @@ onMounted(() => {
|
|
|
861
1130
|
background-color: #ebeef5;
|
|
862
1131
|
border-radius: 4px;
|
|
863
1132
|
}
|
|
1133
|
+
|
|
864
1134
|
.template-container {
|
|
865
1135
|
display: flex;
|
|
866
1136
|
flex-direction: column;
|
|
@@ -876,24 +1146,30 @@ onMounted(() => {
|
|
|
876
1146
|
flex: 1;
|
|
877
1147
|
overflow-y: auto;
|
|
878
1148
|
}
|
|
1149
|
+
|
|
879
1150
|
.template-input {
|
|
880
1151
|
flex-grow: 1;
|
|
881
1152
|
}
|
|
1153
|
+
|
|
882
1154
|
.template-list {
|
|
883
1155
|
overflow-y: auto;
|
|
884
1156
|
height: 100%;
|
|
885
1157
|
}
|
|
1158
|
+
|
|
886
1159
|
.template-item {
|
|
887
1160
|
margin-bottom: 10px;
|
|
888
1161
|
}
|
|
1162
|
+
|
|
889
1163
|
.template-item:hover {
|
|
890
1164
|
background-color: #f5f7fa;
|
|
891
1165
|
}
|
|
1166
|
+
|
|
892
1167
|
.template-content {
|
|
893
1168
|
flex-grow: 1;
|
|
894
1169
|
margin-right: 10px;
|
|
895
1170
|
word-break: break-all;
|
|
896
1171
|
}
|
|
1172
|
+
|
|
897
1173
|
.template-actions {
|
|
898
1174
|
display: flex;
|
|
899
1175
|
gap: 5px;
|
|
@@ -901,4 +1177,29 @@ onMounted(() => {
|
|
|
901
1177
|
min-width: 120px;
|
|
902
1178
|
flex-shrink: 0;
|
|
903
1179
|
}
|
|
1180
|
+
|
|
1181
|
+
.options-row {
|
|
1182
|
+
display: flex;
|
|
1183
|
+
justify-content: space-between;
|
|
1184
|
+
align-items: center;
|
|
1185
|
+
margin-bottom: 15px;
|
|
1186
|
+
}
|
|
1187
|
+
|
|
1188
|
+
.code-command {
|
|
1189
|
+
background-color: #2d2d2d;
|
|
1190
|
+
color: #f8f8f2;
|
|
1191
|
+
font-family: 'Courier New', Courier, monospace;
|
|
1192
|
+
padding: 10px;
|
|
1193
|
+
border-radius: 4px;
|
|
1194
|
+
overflow-x: auto;
|
|
1195
|
+
white-space: pre;
|
|
1196
|
+
font-size: 14px;
|
|
1197
|
+
}
|
|
1198
|
+
|
|
1199
|
+
@media (max-width: 768px) {
|
|
1200
|
+
.action-row {
|
|
1201
|
+
flex-direction: column;
|
|
1202
|
+
}
|
|
1203
|
+
}
|
|
904
1204
|
</style>
|
|
1205
|
+
|