zen-gitsync 2.0.4 → 2.0.6

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.
@@ -1,17 +1,15 @@
1
1
  <script setup lang="ts">
2
2
  import { ref, onMounted, computed, watch } from "vue";
3
3
  import { ElMessage, ElMessageBox } from "element-plus";
4
- import { Setting, Plus, Upload, Refresh, Download, Edit } from "@element-plus/icons-vue";
4
+ import { Setting, Edit } from "@element-plus/icons-vue";
5
5
  import { useGitLogStore } from "../stores/gitLogStore";
6
6
  import { useGitStore } from "../stores/gitStore";
7
7
 
8
8
  const gitLogStore = useGitLogStore();
9
9
  const gitStore = useGitStore();
10
- const emit = defineEmits(["commit-success", "push-success", "status-update"]);
11
10
  const commitMessage = ref("");
12
11
  const isPushing = ref(false);
13
12
  // 添加提交并推送的状态变量
14
- const isCommitAndPushing = ref(false);
15
13
  const placeholder = ref("输入提交信息...");
16
14
  // 添加默认提交信息变量
17
15
  const defaultCommitMessage = ref("");
@@ -94,12 +92,12 @@ const finalCommitMessage = computed(() => {
94
92
  const gitCommandPreview = computed(() => {
95
93
  // 基本命令
96
94
  let command = `git commit -m "${finalCommitMessage.value}"`
97
-
95
+
98
96
  // 如果跳过钩子开关打开,添加 --no-verify 参数
99
97
  if (skipHooks.value) {
100
98
  command += ' --no-verify'
101
99
  }
102
-
100
+
103
101
  return command
104
102
  });
105
103
 
@@ -200,10 +198,10 @@ async function updateDescriptionTemplate() {
200
198
  // 保存原模板和新模板
201
199
  const oldTemplate = originalDescriptionTemplate.value;
202
200
  const newTemplate = newTemplateName.value;
203
-
201
+
204
202
  // 更新本地数组
205
203
  descriptionTemplates.value[editingDescriptionIndex.value] = newTemplate;
206
-
204
+
207
205
  // 调用API更新服务器
208
206
  const response = await fetch("/api/config/update-template", {
209
207
  method: "POST",
@@ -216,14 +214,14 @@ async function updateDescriptionTemplate() {
216
214
  type: "description",
217
215
  }),
218
216
  });
219
-
217
+
220
218
  const result = await response.json();
221
219
  if (result.success) {
222
220
  ElMessage({
223
221
  message: "模板更新成功!",
224
222
  type: "success",
225
223
  });
226
-
224
+
227
225
  // 重置编辑状态
228
226
  isEditingDescription.value = false;
229
227
  originalDescriptionTemplate.value = "";
@@ -331,10 +329,10 @@ async function updateScopeTemplate() {
331
329
  // 保存原模板和新模板
332
330
  const oldTemplate = originalScopeTemplate.value;
333
331
  const newTemplate = newScopeTemplate.value;
334
-
332
+
335
333
  // 更新本地数组
336
334
  scopeTemplates.value[editingScopeIndex.value] = newTemplate;
337
-
335
+
338
336
  // 调用API更新服务器
339
337
  const response = await fetch("/api/config/update-template", {
340
338
  method: "POST",
@@ -347,14 +345,14 @@ async function updateScopeTemplate() {
347
345
  type: "scope",
348
346
  }),
349
347
  });
350
-
348
+
351
349
  const result = await response.json();
352
350
  if (result.success) {
353
351
  ElMessage({
354
352
  message: "作用域模板更新成功!",
355
353
  type: "success",
356
354
  });
357
-
355
+
358
356
  // 重置编辑状态
359
357
  isEditingScope.value = false;
360
358
  originalScopeTemplate.value = "";
@@ -501,7 +499,7 @@ async function addToStage() {
501
499
  const result = await gitLogStore.addToStage();
502
500
  if (result) {
503
501
  // 触发状态更新事件
504
- emit("status-update");
502
+ gitLogStore.fetchStatus();
505
503
  }
506
504
  } catch (error) {
507
505
  ElMessage({
@@ -524,15 +522,14 @@ async function commitChanges() {
524
522
  try {
525
523
  // 使用Store提交更改
526
524
  const result = await gitLogStore.commitChanges(finalCommitMessage.value, skipHooks.value);
527
-
525
+
528
526
  if (result) {
529
527
  // 清空提交信息
530
528
  clearCommitFields();
531
-
529
+
532
530
  // 触发成功事件
533
- emit("commit-success");
534
- // 触发状态更新事件
535
- emit("status-update");
531
+ gitLogStore.fetchStatus();
532
+ gitLogStore.fetchLog();
536
533
  }
537
534
  } catch (error) {
538
535
  ElMessage({
@@ -548,12 +545,11 @@ async function pushToRemote() {
548
545
  isPushing.value = true
549
546
  // 使用Store推送更改
550
547
  const result = await gitLogStore.pushToRemote();
551
-
548
+
552
549
  if (result) {
553
550
  // 触发成功事件
554
- emit("push-success");
555
- // 触发状态更新事件
556
- emit("status-update");
551
+ gitStore.getCurrentBranch();
552
+ gitLogStore.fetchLog();
557
553
  }
558
554
  } catch (error) {
559
555
  ElMessage({
@@ -569,24 +565,21 @@ async function pushToRemote() {
569
565
  async function addAndCommit() {
570
566
  if (!finalCommitMessage.value.trim()) {
571
567
  ElMessage({
572
- message: "提交信息不能为空",
568
+ message: "提交信息不能为空",
573
569
  type: "warning",
574
570
  });
575
571
  return;
576
572
  }
577
573
 
578
574
  try {
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
- }
575
+ await gitLogStore.addAndCommit(finalCommitMessage.value, skipHooks.value);
576
+
577
+ // 清空提交信息
578
+ clearCommitFields();
579
+
580
+ // 触发成功事件
581
+ gitLogStore.fetchStatus();
582
+ gitLogStore.fetchLog();
590
583
  } catch (error) {
591
584
  ElMessage({
592
585
  message: `暂存并提交失败: ${(error as Error).message}`,
@@ -606,60 +599,22 @@ async function addCommitAndPush() {
606
599
  }
607
600
 
608
601
  try {
609
- isCommitAndPushing.value = true
610
- const result = await gitLogStore.addCommitAndPush(finalCommitMessage.value, skipHooks.value);
611
-
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");
626
- }
602
+ await gitLogStore.addCommitAndPush(finalCommitMessage.value, skipHooks.value);
603
+
604
+
605
+ // 清空提交信息
606
+ clearCommitFields();
607
+
608
+ // 触发成功事件
609
+ gitStore.getCurrentBranch();
610
+ gitLogStore.fetchLog();
611
+
627
612
  } catch (error) {
628
613
  ElMessage({
629
614
  message: `暂存、提交并推送失败: ${(error as Error).message}`,
630
615
  type: "error",
631
616
  });
632
617
  } finally {
633
- isCommitAndPushing.value = false
634
- }
635
- }
636
-
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') {
658
- ElMessage({
659
- message: `重置暂存区失败: ${(error as Error).message}`,
660
- type: 'error'
661
- });
662
- }
663
618
  }
664
619
  }
665
620
 
@@ -675,11 +630,13 @@ async function resetToRemote() {
675
630
  type: 'warning'
676
631
  }
677
632
  );
678
-
633
+
679
634
  const result = await gitLogStore.resetToRemote(gitStore.currentBranch);
680
635
  if (result) {
681
636
  // 触发状态更新事件
682
- emit("status-update");
637
+ gitLogStore.fetchStatus();
638
+ // 更新提交历史
639
+ gitLogStore.fetchLog();
683
640
  }
684
641
  } catch (error) {
685
642
  // 用户取消操作,不显示错误
@@ -702,13 +659,13 @@ function clearCommitFields() {
702
659
 
703
660
  onMounted(() => {
704
661
  loadConfig();
705
-
662
+
706
663
  // 从 localStorage 中获取标准化提交设置
707
664
  const savedStandardCommit = localStorage.getItem("zen-gitsync-standard-commit");
708
665
  if (savedStandardCommit !== null) {
709
666
  isStandardCommit.value = savedStandardCommit === "true";
710
667
  }
711
-
668
+
712
669
  // 从 localStorage 中获取跳过钩子设置
713
670
  const savedSkipHooks = localStorage.getItem("zen-gitsync-skip-hooks");
714
671
  if (savedSkipHooks !== null) {
@@ -718,328 +675,339 @@ onMounted(() => {
718
675
  </script>
719
676
 
720
677
  <template>
721
- <div class="card">
722
- <h2>提交更改</h2>
723
-
724
- <div class="commit-options">
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>
733
-
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>
739
- </div>
678
+ <div class="card" :class="{ 'is-pushing': gitLogStore.isPushing || isPushing }">
679
+ <div class="card-header">
680
+ <h2>提交更改</h2>
740
681
  </div>
741
682
 
742
- <!-- 普通提交表单 -->
743
- <div v-if="!isStandardCommit" class="commit-form">
744
- <el-input v-model="commitMessage" :placeholder="placeholder" clearable />
745
- </div>
746
-
747
- <!-- 标准化提交表单 -->
748
- <div v-else class="standard-commit-form">
749
- <div class="standard-commit-header">
750
- <el-select
751
- v-model="commitType"
752
- placeholder="提交类型"
753
- class="type-select"
754
- clearable
755
- >
756
- <el-option
757
- v-for="item in commitTypeOptions"
758
- :key="item.value"
759
- :label="item.label"
760
- :value="item.value"
761
- />
762
- </el-select>
763
-
764
- <div class="scope-container">
765
- <el-input
766
- v-model="commitScope"
767
- placeholder="作用域(可选)"
768
- class="scope-input"
769
- clearable
770
- />
771
- <el-button
772
- type="primary"
773
- :icon="Setting"
774
- circle
775
- size="small"
776
- class="settings-button"
777
- @click="openScopeSettings"
683
+ <div class="card-content">
684
+ <div class="layout-container">
685
+ <!-- 如果没有配置Git用户信息,显示提示 -->
686
+ <div v-if="gitStore.userName === '' || gitStore.userEmail === ''" class="git-config-warning">
687
+ <el-alert
688
+ title="Git用户信息未配置"
689
+ type="warning"
690
+ :closable="false"
691
+ show-icon
778
692
  >
779
- </el-button>
693
+ <p>您需要配置Git用户名和邮箱才能提交代码。请使用以下命令配置:</p>
694
+ <pre class="config-command">git config --global user.name "Your Name"
695
+ git config --global user.email "your.email@example.com"</pre>
696
+ </el-alert>
780
697
  </div>
698
+
699
+ <!-- 正常的提交区域,仅在Git用户信息已配置时显示 -->
700
+ <template v-else>
701
+ <!-- 左侧:提交表单 -->
702
+ <div class="commit-section">
703
+ <div class="commit-options">
704
+ <div class="options-row">
705
+ <div class="commit-mode-toggle">
706
+ <el-switch v-model="isStandardCommit" active-text="标准化提交" inactive-text="普通提交" />
707
+ </div>
708
+
709
+ <div class="no-verify-toggle">
710
+ <el-tooltip content="跳过 Git 钩子检查 (--no-verify)" placement="top">
711
+ <el-switch v-model="skipHooks" active-text="跳过钩子 (--no-verify)" />
712
+ </el-tooltip>
713
+ </div>
714
+ </div>
715
+ </div>
716
+
717
+ <!-- 普通提交表单 -->
718
+ <div v-if="!isStandardCommit" class="commit-form">
719
+ <el-input v-model="commitMessage" :placeholder="placeholder" clearable />
720
+ </div>
721
+
722
+ <!-- 标准化提交表单 -->
723
+ <div v-else class="standard-commit-form">
724
+ <div class="standard-commit-header">
725
+ <el-select v-model="commitType" placeholder="提交类型" class="type-select" clearable>
726
+ <el-option v-for="item in commitTypeOptions" :key="item.value" :label="item.label" :value="item.value" />
727
+ </el-select>
728
+
729
+ <div class="scope-container">
730
+ <el-input v-model="commitScope" placeholder="作用域(可选)" class="scope-input" clearable />
731
+ <el-button type="primary" :icon="Setting" circle size="small" class="settings-button"
732
+ @click="openScopeSettings">
733
+ </el-button>
734
+ </div>
735
+
736
+ <div class="description-container">
737
+ <el-input v-model="commitDescription" placeholder="简短描述(必填)" class="description-input" clearable />
738
+ <el-button type="primary" :icon="Setting" circle size="small" class="settings-button"
739
+ @click="openDescriptionSettings">
740
+ </el-button>
741
+ </div>
742
+ </div>
781
743
 
782
- <div class="description-container">
783
- <el-input
784
- v-model="commitDescription"
785
- placeholder="简短描述(必填)"
786
- class="description-input"
787
- clearable
788
- />
789
- <el-button
790
- type="primary"
791
- :icon="Setting"
792
- circle
793
- size="small"
794
- class="settings-button"
795
- @click="openDescriptionSettings"
796
- >
797
- </el-button>
798
- </div>
799
- </div>
744
+ <el-input v-model="commitBody" type="textarea" :rows="4" placeholder="正文(可选):详细描述本次提交的内容和原因" class="body-input"
745
+ clearable />
800
746
 
801
- <el-input
802
- v-model="commitBody"
803
- type="textarea"
804
- :rows="4"
805
- placeholder="正文(可选):详细描述本次提交的内容和原因"
806
- class="body-input"
807
- clearable
808
- />
809
-
810
- <el-input
811
- v-model="commitFooter"
812
- placeholder="页脚(可选):如 Closes #123"
813
- class="footer-input"
814
- clearable
815
- />
816
-
817
- <div class="preview-section">
818
- <div class="preview-title">提交信息预览:</div>
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>
823
- </div>
824
- </div>
747
+ <el-input v-model="commitFooter" placeholder="页脚(可选):如 Closes #123" class="footer-input" clearable />
825
748
 
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>
891
- </div>
749
+ <div class="preview-section">
750
+ <div class="preview-title">提交信息预览:</div>
751
+ <pre class="preview-content">{{ finalCommitMessage }}</pre>
892
752
 
893
- <!-- 简短描述设置弹窗 -->
894
- <el-dialog
895
- title="简短描述模板设置"
896
- v-model="descriptionDialogVisible"
897
- width="80vw"
898
- style="height: 80vh"
899
- >
900
- <div class="template-container">
901
- <div class="template-form">
902
- <el-input
903
- v-model="newTemplateName"
904
- :placeholder="isEditingDescription ? '编辑模板内容' : '输入新模板内容'"
905
- class="template-input"
906
- clearable
907
- />
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
- >
753
+ <div class="preview-title" style="margin-top: 10px;">Git命令预览:</div>
754
+ <pre class="preview-content code-command">{{ gitCommandPreview }}</pre>
755
+ </div>
756
+ </div>
920
757
  </div>
921
- </div>
922
758
 
923
- <div class="template-list">
924
- <h3>已保存模板</h3>
925
- <el-empty
926
- v-if="descriptionTemplates.length === 0"
927
- description="暂无保存的模板"
928
- />
929
- <el-card
930
- v-for="(template, index) in descriptionTemplates"
931
- :key="index"
932
- class="template-item"
933
- >
934
- <!-- 两端对齐 -->
935
- <el-row justify="space-between" align="middle" style="width: 100%">
936
- <div class="template-content">{{ template }}</div>
937
- <div class="template-actions">
938
- <el-button
939
- type="primary"
940
- size="small"
941
- @click="useTemplate(template)"
942
- >使用</el-button
943
- >
944
- <el-button
945
- type="warning"
946
- size="small"
947
- :icon="Edit"
948
- @click="startEditDescriptionTemplate(template, index)"
949
- >编辑</el-button
950
- >
951
- <el-button
952
- type="danger"
953
- size="small"
954
- @click="deleteDescriptionTemplate(template)"
955
- >删除</el-button
956
- >
759
+ <!-- 右侧:操作区域 -->
760
+ <div class="actions-section">
761
+ <h3>Git 操作</h3>
762
+ <div class="action-groups">
763
+ <div class="action-group">
764
+ <div class="group-title">基础操作</div>
765
+ <div class="group-buttons">
766
+ <el-button
767
+ type="primary"
768
+ @click="addToStage"
769
+ :loading="gitLogStore.isAddingFiles"
770
+ class="action-button"
771
+ >
772
+ 暂存更改
773
+ <span class="command-text">git add .</span>
774
+ </el-button>
775
+
776
+ <el-button
777
+ type="primary"
778
+ @click="commitChanges"
779
+ :loading="gitLogStore.isLoadingStatus"
780
+ class="action-button"
781
+ >
782
+ 提交
783
+ <span class="command-text">git commit</span>
784
+ </el-button>
785
+
786
+ <el-button
787
+ type="success"
788
+ @click="pushToRemote"
789
+ :loading="gitLogStore.isPushing"
790
+ class="action-button push-button"
791
+ >
792
+ 推送
793
+ <span class="command-text">git push</span>
794
+ </el-button>
795
+ </div>
957
796
  </div>
958
- </el-row>
959
- </el-card>
960
- </div>
797
+
798
+ <div class="action-group">
799
+ <div class="group-title">组合操作</div>
800
+ <div class="group-buttons">
801
+ <el-button
802
+ type="warning"
803
+ @click="addAndCommit"
804
+ :loading="gitLogStore.isAddingFiles || gitLogStore.isCommiting"
805
+ class="action-button"
806
+ >
807
+ 暂存并提交
808
+ <span class="command-text">git add + commit</span>
809
+ </el-button>
810
+
811
+ <el-button
812
+ type="danger"
813
+ @click="addCommitAndPush"
814
+ :loading="gitLogStore.isAddingFiles || gitLogStore.isCommiting || gitLogStore.isPushing"
815
+ class="action-button"
816
+ >
817
+ 一键推送
818
+ <span class="command-text command-text-long">git add + commit + push</span>
819
+ </el-button>
820
+ </div>
821
+ </div>
822
+
823
+ <div class="action-group">
824
+ <div class="group-title">重置操作</div>
825
+ <div class="group-buttons">
826
+ <!-- <el-button
827
+ type="info"
828
+ @click="resetHead"
829
+ :loading="gitLogStore.isResetting"
830
+ :icon="Refresh"
831
+ class="action-button reset-button"
832
+ >
833
+ 重置暂存区
834
+ <span class="command-text">git reset HEAD</span>
835
+ </el-button> -->
836
+
837
+ <el-button
838
+ type="info"
839
+ @click="resetToRemote"
840
+ :loading="gitLogStore.isResetting"
841
+ class="action-button reset-button"
842
+ >
843
+ 重置到远程
844
+ <span class="command-text command-text-long">git reset --hard origin/branch</span>
845
+ </el-button>
846
+ </div>
847
+ </div>
848
+ </div>
849
+ </div>
850
+ </template>
961
851
  </div>
962
- </el-dialog>
963
-
964
- <!-- 作用域设置弹窗 -->
965
- <el-dialog
966
- title="作用域模板设置"
967
- v-model="scopeDialogVisible"
968
- width="80%"
969
- style="height: 80vh"
970
- >
971
- <div class="template-container">
972
- <div class="template-form">
973
- <el-input
974
- v-model="newScopeTemplate"
975
- :placeholder="isEditingScope ? '编辑作用域模板内容' : '输入新作用域模板'"
976
- class="template-input"
977
- clearable
978
- />
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
- >
852
+
853
+ <!-- 简短描述设置弹窗 -->
854
+ <el-dialog title="简短描述模板设置" v-model="descriptionDialogVisible" width="80vw" style="height: 80vh">
855
+ <div class="template-container">
856
+ <div class="template-form">
857
+ <el-input v-model="newTemplateName" :placeholder="isEditingDescription ? '编辑模板内容' : '输入新模板内容'"
858
+ class="template-input" clearable />
859
+ <div class="template-form-buttons">
860
+ <el-button v-if="isEditingDescription" @click="cancelEditDescriptionTemplate">取消</el-button>
861
+ <el-button type="primary" @click="saveDescriptionTemplate" :disabled="!newTemplateName.trim()">{{
862
+ isEditingDescription ? '更新模板' : '添加模板' }}</el-button>
863
+ </div>
864
+ </div>
865
+
866
+ <div class="template-list">
867
+ <h3>已保存模板</h3>
868
+ <el-empty v-if="descriptionTemplates.length === 0" description="暂无保存的模板" />
869
+ <el-card v-for="(template, index) in descriptionTemplates" :key="index" class="template-item">
870
+ <!-- 两端对齐 -->
871
+ <el-row justify="space-between" align="middle" style="width: 100%">
872
+ <div class="template-content">{{ template }}</div>
873
+ <div class="template-actions">
874
+ <el-button type="primary" size="small" @click="useTemplate(template)">使用</el-button>
875
+ <el-button type="warning" size="small" :icon="Edit"
876
+ @click="startEditDescriptionTemplate(template, index)">编辑</el-button>
877
+ <el-button type="danger" size="small" @click="deleteDescriptionTemplate(template)">删除</el-button>
878
+ </div>
879
+ </el-row>
880
+ </el-card>
991
881
  </div>
992
882
  </div>
883
+ </el-dialog>
884
+
885
+ <!-- 作用域设置弹窗 -->
886
+ <el-dialog title="作用域模板设置" v-model="scopeDialogVisible" width="80%" style="height: 80vh">
887
+ <div class="template-container">
888
+ <div class="template-form">
889
+ <el-input v-model="newScopeTemplate" :placeholder="isEditingScope ? '编辑作用域模板内容' : '输入新作用域模板'"
890
+ class="template-input" clearable />
891
+ <div class="template-form-buttons">
892
+ <el-button v-if="isEditingScope" @click="cancelEditScopeTemplate">取消</el-button>
893
+ <el-button type="primary" @click="saveScopeTemplate" :disabled="!newScopeTemplate.trim()">{{ isEditingScope
894
+ ? '更新模板' : '添加模板' }}</el-button>
895
+ </div>
896
+ </div>
993
897
 
994
- <div class="template-list">
995
- <h3>已保存作用域</h3>
996
- <el-empty
997
- v-if="scopeTemplates.length === 0"
998
- description="暂无保存的作用域"
999
- />
1000
- <el-card
1001
- v-for="(template, index) in scopeTemplates"
1002
- :key="index"
1003
- class="template-item"
1004
- >
1005
- <el-row justify="space-between" align="middle" style="width: 100%">
1006
- <div class="template-content">{{ template }}</div>
1007
- <div class="template-actions">
1008
- <el-button
1009
- type="primary"
1010
- size="small"
1011
- @click="useScopeTemplate(template)"
1012
- >使用</el-button
1013
- >
1014
- <el-button
1015
- type="warning"
1016
- size="small"
1017
- :icon="Edit"
1018
- @click="startEditScopeTemplate(template, index)"
1019
- >编辑</el-button
1020
- >
1021
- <el-button
1022
- type="danger"
1023
- size="small"
1024
- @click="deleteScopeTemplate(template)"
1025
- >删除</el-button
1026
- >
1027
- </div>
1028
- </el-row>
1029
- </el-card>
898
+ <div class="template-list">
899
+ <h3>已保存作用域</h3>
900
+ <el-empty v-if="scopeTemplates.length === 0" description="暂无保存的作用域" />
901
+ <el-card v-for="(template, index) in scopeTemplates" :key="index" class="template-item">
902
+ <el-row justify="space-between" align="middle" style="width: 100%">
903
+ <div class="template-content">{{ template }}</div>
904
+ <div class="template-actions">
905
+ <el-button type="primary" size="small" @click="useScopeTemplate(template)">使用</el-button>
906
+ <el-button type="warning" size="small" :icon="Edit"
907
+ @click="startEditScopeTemplate(template, index)">编辑</el-button>
908
+ <el-button type="danger" size="small" @click="deleteScopeTemplate(template)">删除</el-button>
909
+ </div>
910
+ </el-row>
911
+ </el-card>
912
+ </div>
1030
913
  </div>
1031
- </div>
1032
- </el-dialog>
914
+ </el-dialog>
915
+ </div>
1033
916
  </div>
1034
917
  </template>
1035
918
 
1036
919
  <style scoped>
920
+ /* 添加动画相关的CSS */
921
+ @keyframes snakeBorder {
922
+ 0%, 100% {
923
+ border-top: 2px solid #409EFF;
924
+ border-right: 2px solid transparent;
925
+ border-bottom: 2px solid transparent;
926
+ border-left: 2px solid transparent;
927
+ }
928
+ 25% {
929
+ border-top: 2px solid #409EFF;
930
+ border-right: 2px solid #67C23A;
931
+ border-bottom: 2px solid transparent;
932
+ border-left: 2px solid transparent;
933
+ }
934
+ 50% {
935
+ border-top: 2px solid transparent;
936
+ border-right: 2px solid #67C23A;
937
+ border-bottom: 2px solid #409EFF;
938
+ border-left: 2px solid transparent;
939
+ }
940
+ 75% {
941
+ border-top: 2px solid transparent;
942
+ border-right: 2px solid transparent;
943
+ border-bottom: 2px solid #409EFF;
944
+ border-left: 2px solid #67C23A;
945
+ }
946
+ }
947
+
948
+ @keyframes glowPulse {
949
+ 0%, 100% { box-shadow: 0 0 8px rgba(64, 158, 255, 0.4); }
950
+ 50% { box-shadow: 0 0 12px rgba(103, 194, 58, 0.5); }
951
+ }
952
+
1037
953
  .card {
1038
954
  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;
955
+ border-radius: 8px;
956
+ box-shadow: 0 2px 10px rgba(0, 0, 0, 0.03);
957
+ border: 1px solid rgba(0, 0, 0, 0.03);
958
+ height: 100%;
959
+ width: 100%;
960
+ display: flex;
961
+ flex-direction: column;
962
+ overflow: hidden;
963
+ }
964
+
965
+ .card-header {
966
+ padding: 8px 16px;
967
+ border-bottom: 1px solid #f0f0f0;
968
+ display: flex;
969
+ justify-content: space-between;
970
+ align-items: center;
971
+ height: 36px;
972
+ }
973
+
974
+ .card-header h2 {
975
+ margin: 0;
976
+ font-size: 16px;
977
+ font-weight: 500;
978
+ color: #303133;
979
+ }
980
+
981
+ .card-content {
982
+ padding: 15px;
983
+ overflow-y: auto;
984
+ flex: 1;
985
+ }
986
+
987
+ .layout-container {
988
+ display: flex;
989
+ gap: 20px;
990
+ height: 100%;
991
+ }
992
+
993
+ .commit-section {
994
+ flex: 1;
995
+ min-width: 0; /* 防止子元素撑开 */
996
+ }
997
+
998
+ .actions-section {
999
+ width: 300px;
1000
+ flex-shrink: 0;
1001
+ }
1002
+
1003
+ .actions-section h3 {
1004
+ margin-top: 0;
1005
+ margin-bottom: 15px;
1006
+ padding-bottom: 10px;
1007
+ border-bottom: 1px solid #dcdfe6;
1008
+ font-size: 18px;
1009
+ color: #303133;
1010
+ font-weight: 500;
1043
1011
  }
1044
1012
 
1045
1013
  .commit-form {
@@ -1050,19 +1018,108 @@ onMounted(() => {
1050
1018
 
1051
1019
  .git-actions {
1052
1020
  margin-top: 20px;
1021
+ }
1022
+
1023
+ .action-groups {
1053
1024
  display: flex;
1054
1025
  flex-direction: column;
1055
- gap: 10px;
1026
+ gap: 15px;
1027
+ }
1028
+
1029
+ .action-group {
1030
+ background-color: #f9f9f9;
1031
+ border-radius: 8px;
1032
+ padding: 12px 15px;
1033
+ box-shadow: 0 1px 3px rgba(0, 0, 0, 0.05);
1034
+ border-left: 4px solid #409EFF;
1035
+ overflow: hidden; /* 确保子元素不会溢出 */
1056
1036
  }
1057
1037
 
1058
- .action-row {
1038
+ .action-group:nth-child(2) {
1039
+ border-left-color: #E6A23C;
1040
+ }
1041
+
1042
+ .action-group:nth-child(3) {
1043
+ border-left-color: #909399;
1044
+ }
1045
+
1046
+ .group-title {
1047
+ font-size: 14px;
1048
+ font-weight: bold;
1049
+ margin-bottom: 10px;
1050
+ color: #606266;
1051
+ text-align: left;
1052
+ display: block;
1053
+ position: relative;
1054
+ padding-left: 10px;
1055
+ border-bottom: 1px solid rgba(0, 0, 0, 0.06);
1056
+ padding-bottom: 8px;
1057
+ }
1058
+
1059
+ .group-buttons {
1059
1060
  display: flex;
1060
- gap: 10px;
1061
- flex-wrap: wrap;
1061
+ flex-direction: column;
1062
+ gap: 8px;
1063
+ padding: 0 2px;
1064
+ }
1065
+
1066
+ .action-button {
1067
+ position: relative;
1068
+ padding: 14px 0 24px 0;
1069
+ width: 100%;
1070
+ display: flex;
1071
+ flex-direction: column;
1072
+ align-items: center;
1073
+ justify-content: center;
1074
+ height: auto;
1075
+ text-align: center;
1076
+ font-size: 16px;
1077
+ border-radius: 6px;
1078
+ border: none;
1079
+ }
1080
+
1081
+ .action-button:hover {
1082
+ transform: translateY(-2px);
1083
+ box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);
1084
+ }
1085
+
1086
+ .action-button:active {
1087
+ transform: translateY(0);
1088
+ }
1089
+
1090
+ .action-button :deep(.el-button__content) {
1091
+ display: flex;
1092
+ flex-direction: column;
1093
+ align-items: center;
1094
+ justify-content: center;
1095
+ width: 100%;
1096
+ min-height: 40px; /* 添加最小高度确保loading不会改变按钮高度 */
1062
1097
  }
1063
1098
 
1064
- .commit-mode-toggle {
1065
- /* 移除margin-bottom */
1099
+ .action-button :deep(.el-icon) {
1100
+ margin-right: 0;
1101
+ margin-bottom: 4px;
1102
+ font-size: 18px;
1103
+ }
1104
+
1105
+ /* 添加loading状态的样式 */
1106
+ .action-button :deep(.el-icon.is-loading) {
1107
+ position: absolute;
1108
+ top: calc(50% - 10px);
1109
+ left: calc(16px);
1110
+ margin-top: 0;
1111
+ }
1112
+
1113
+ .command-text {
1114
+ position: absolute;
1115
+ bottom: 6px;
1116
+ font-size: 14px;
1117
+ font-family: monospace;
1118
+ width: 100%;
1119
+ text-align: center;
1120
+ left: 0;
1121
+ white-space: nowrap;
1122
+
1066
1123
  }
1067
1124
 
1068
1125
  .standard-commit-form {
@@ -1074,21 +1131,20 @@ onMounted(() => {
1074
1131
 
1075
1132
  .standard-commit-header {
1076
1133
  display: flex;
1134
+ flex-direction: column;
1077
1135
  gap: 10px;
1078
1136
  width: 100%;
1079
1137
  }
1080
1138
 
1081
1139
  .type-select {
1082
- width: 120px;
1083
- flex-shrink: 0;
1140
+ width: 100%;
1084
1141
  }
1085
1142
 
1086
1143
  .scope-container {
1087
1144
  display: flex;
1088
1145
  align-items: center;
1089
1146
  gap: 5px;
1090
- flex-grow: 0;
1091
- width: 200px;
1147
+ width: 100%;
1092
1148
  }
1093
1149
 
1094
1150
  .scope-input {
@@ -1099,12 +1155,11 @@ onMounted(() => {
1099
1155
  display: flex;
1100
1156
  align-items: center;
1101
1157
  gap: 5px;
1102
- flex-grow: 1;
1158
+ width: 100%;
1103
1159
  }
1104
1160
 
1105
1161
  .description-input {
1106
1162
  flex-grow: 1;
1107
- min-width: 200px;
1108
1163
  }
1109
1164
 
1110
1165
  .settings-button {
@@ -1197,9 +1252,61 @@ onMounted(() => {
1197
1252
  }
1198
1253
 
1199
1254
  @media (max-width: 768px) {
1200
- .action-row {
1255
+ .layout-container {
1201
1256
  flex-direction: column;
1202
1257
  }
1258
+
1259
+ .actions-section {
1260
+ width: 100%;
1261
+ }
1262
+
1263
+ .group-buttons {
1264
+ flex-direction: row;
1265
+ flex-wrap: wrap;
1266
+ }
1267
+
1268
+ .action-button {
1269
+ flex: 1;
1270
+ min-width: 120px;
1271
+ }
1272
+ }
1273
+
1274
+ .git-config-warning {
1275
+ width: 100%;
1203
1276
  }
1204
- </style>
1205
1277
 
1278
+ .config-command {
1279
+ background-color: #2d2d2d;
1280
+ color: #f8f8f2;
1281
+ font-family: 'Courier New', Courier, monospace;
1282
+ padding: 10px;
1283
+ border-radius:
1284
+ 4px;
1285
+ margin-top: 10px;
1286
+ white-space: pre;
1287
+ }
1288
+
1289
+ /* 特定按钮样式 */
1290
+ .push-button {
1291
+ background-color: #67c23a;
1292
+ border-color: #67c23a;
1293
+ }
1294
+
1295
+ .push-button:hover {
1296
+ background-color: #85ce61;
1297
+ border-color: #85ce61;
1298
+ }
1299
+
1300
+ .reset-button {
1301
+ background-color: #909399;
1302
+ border-color: #909399;
1303
+ }
1304
+
1305
+ .reset-button:hover {
1306
+ background-color: #a6a9ad;
1307
+ border-color: #a6a9ad;
1308
+ }
1309
+ .el-button+.el-button {
1310
+ margin-left: 0;
1311
+ }
1312
+ </style>