zen-gitsync 2.0.6 → 2.0.8

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,7 +1,7 @@
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, Edit } from "@element-plus/icons-vue";
4
+ import { Setting, Edit, Check, Upload, RefreshRight, Delete, Position, Download, Connection } from "@element-plus/icons-vue";
5
5
  import { useGitLogStore } from "../stores/gitLogStore";
6
6
  import { useGitStore } from "../stores/gitStore";
7
7
 
@@ -10,6 +10,11 @@ const gitStore = useGitStore();
10
10
  const commitMessage = ref("");
11
11
  const isPushing = ref(false);
12
12
  // 添加提交并推送的状态变量
13
+ const showPushSuccess = ref(false);
14
+ // 添加git pull和fetch操作相关状态变量
15
+ const isGitPulling = ref(false);
16
+ const isGitFetching = ref(false);
17
+ // 添加placeholder变量
13
18
  const placeholder = ref("输入提交信息...");
14
19
  // 添加默认提交信息变量
15
20
  const defaultCommitMessage = ref("");
@@ -39,6 +44,10 @@ const isEditingScope = ref(false);
39
44
  const originalScopeTemplate = ref("");
40
45
  const editingScopeIndex = ref(-1);
41
46
 
47
+ // 默认提交信息设置相关变量
48
+ const defaultMessageDialogVisible = ref(false);
49
+ const newDefaultMessage = ref("");
50
+
42
51
  // 跳过钩子
43
52
  const skipHooks = ref(false);
44
53
 
@@ -53,6 +62,12 @@ const commitTypeOptions = [
53
62
  { value: "chore", label: "chore: 构建/工具修改" },
54
63
  ];
55
64
 
65
+ // 添加默认提交信息模板相关变量
66
+ const messageTemplates = ref<string[]>([]);
67
+ const isEditingMessage = ref(false);
68
+ const originalMessageTemplate = ref("");
69
+ const editingMessageIndex = ref(-1);
70
+
56
71
  // 监听标准化提交状态变化,保存到localStorage
57
72
  watch(isStandardCommit, (newValue) => {
58
73
  localStorage.setItem("zen-gitsync-standard-commit", newValue.toString());
@@ -122,6 +137,11 @@ async function loadConfig() {
122
137
  if (config.scopeTemplates && Array.isArray(config.scopeTemplates)) {
123
138
  scopeTemplates.value = config.scopeTemplates;
124
139
  }
140
+
141
+ // 加载提交信息模板
142
+ if (config.messageTemplates && Array.isArray(config.messageTemplates)) {
143
+ messageTemplates.value = config.messageTemplates;
144
+ }
125
145
  } catch (error) {
126
146
  console.error("加载配置失败:", error);
127
147
  }
@@ -530,6 +550,9 @@ async function commitChanges() {
530
550
  // 触发成功事件
531
551
  gitLogStore.fetchStatus();
532
552
  gitLogStore.fetchLog();
553
+
554
+ // 手动更新分支状态
555
+ gitStore.getBranchStatus();
533
556
  }
534
557
  } catch (error) {
535
558
  ElMessage({
@@ -539,25 +562,65 @@ async function commitChanges() {
539
562
  }
540
563
  }
541
564
 
565
+ // 显示推送成功提示
566
+ function showPushSuccessIndicator() {
567
+ showPushSuccess.value = true;
568
+ setTimeout(() => {
569
+ showPushSuccess.value = false;
570
+ }, 2000);
571
+ }
572
+
542
573
  // 推送到远程 (git push)
543
574
  async function pushToRemote() {
575
+ isPushing.value = true;
544
576
  try {
545
- isPushing.value = true
546
- // 使用Store推送更改
547
- const result = await gitLogStore.pushToRemote();
548
-
549
- if (result) {
550
- // 触发成功事件
551
- gitStore.getCurrentBranch();
552
- gitLogStore.fetchLog();
553
- }
577
+ await gitLogStore.pushToRemote();
578
+ // 显示推送成功提示
579
+ showPushSuccessIndicator();
580
+
581
+ // 手动更新分支状态
582
+ gitStore.getBranchStatus();
554
583
  } catch (error) {
555
584
  ElMessage({
556
585
  message: `推送失败: ${(error as Error).message}`,
557
- type: "error",
586
+ type: 'error',
558
587
  });
559
588
  } finally {
560
- isPushing.value = false
589
+ isPushing.value = false;
590
+ }
591
+ }
592
+
593
+ // 处理git pull操作
594
+ async function handleGitPull() {
595
+ isGitPulling.value = true;
596
+ try {
597
+ await gitStore.gitPull();
598
+ // 刷新状态
599
+ await gitLogStore.fetchStatus();
600
+ } catch (error) {
601
+ ElMessage({
602
+ message: `拉取失败: ${(error as Error).message}`,
603
+ type: 'error',
604
+ });
605
+ } finally {
606
+ isGitPulling.value = false;
607
+ }
608
+ }
609
+
610
+ // 处理git fetch --all操作
611
+ async function handleGitFetchAll() {
612
+ isGitFetching.value = true;
613
+ try {
614
+ await gitStore.gitFetchAll();
615
+ // 刷新状态
616
+ await gitLogStore.fetchStatus();
617
+ } catch (error) {
618
+ ElMessage({
619
+ message: `获取远程分支信息失败: ${(error as Error).message}`,
620
+ type: 'error',
621
+ });
622
+ } finally {
623
+ isGitFetching.value = false;
561
624
  }
562
625
  }
563
626
 
@@ -599,22 +662,31 @@ async function addCommitAndPush() {
599
662
  }
600
663
 
601
664
  try {
665
+ isPushing.value = true
602
666
  await gitLogStore.addCommitAndPush(finalCommitMessage.value, skipHooks.value);
603
667
 
604
-
605
668
  // 清空提交信息
606
669
  clearCommitFields();
607
670
 
608
671
  // 触发成功事件
609
672
  gitStore.getCurrentBranch();
673
+
674
+ // 确保通过fetchLog获取的是最新的第1页数据
610
675
  gitLogStore.fetchLog();
676
+
677
+ // 手动更新分支状态
678
+ gitStore.getBranchStatus();
679
+
680
+ // 显示成功动画
681
+ isPushing.value = false
682
+ showPushSuccessIndicator();
611
683
 
612
684
  } catch (error) {
613
685
  ElMessage({
614
686
  message: `暂存、提交并推送失败: ${(error as Error).message}`,
615
687
  type: "error",
616
688
  });
617
- } finally {
689
+ isPushing.value = false
618
690
  }
619
691
  }
620
692
 
@@ -657,6 +729,288 @@ function clearCommitFields() {
657
729
  commitFooter.value = "";
658
730
  }
659
731
 
732
+ // 打开默认提交信息设置弹窗
733
+ function openDefaultMessageSettings() {
734
+ newDefaultMessage.value = defaultCommitMessage.value;
735
+ defaultMessageDialogVisible.value = true;
736
+ }
737
+
738
+ // 保存默认提交信息
739
+ async function saveDefaultMessage() {
740
+ if (!newDefaultMessage.value.trim()) {
741
+ ElMessage({
742
+ message: "请输入默认提交信息",
743
+ type: "warning",
744
+ });
745
+ return;
746
+ }
747
+
748
+ try {
749
+ // 保存到服务器
750
+ const response = await fetch("/api/config/saveDefaultMessage", {
751
+ method: "POST",
752
+ headers: {
753
+ "Content-Type": "application/json",
754
+ },
755
+ body: JSON.stringify({
756
+ defaultCommitMessage: newDefaultMessage.value,
757
+ }),
758
+ });
759
+
760
+ const result = await response.json();
761
+ if (result.success) {
762
+ // 更新本地状态
763
+ defaultCommitMessage.value = newDefaultMessage.value;
764
+ placeholder.value = `输入提交信息 (默认: ${defaultCommitMessage.value})`;
765
+
766
+ ElMessage({
767
+ message: "默认提交信息保存成功!",
768
+ type: "success",
769
+ });
770
+
771
+ // 不再关闭弹窗,而是保留当前编辑状态
772
+ // defaultMessageDialogVisible.value = false;
773
+ } else {
774
+ ElMessage({
775
+ message: "保存失败: " + result.error,
776
+ type: "error",
777
+ });
778
+ }
779
+ } catch (error) {
780
+ ElMessage({
781
+ message: "保存失败: " + (error as Error).message,
782
+ type: "error",
783
+ });
784
+ }
785
+ }
786
+
787
+ // 根据Git状态计算按钮禁用状态
788
+ const hasUnstagedChanges = computed(() => {
789
+ return gitLogStore.fileList.some(file => ['modified', 'deleted', 'untracked'].includes(file.type));
790
+ });
791
+
792
+ // 计算未暂存文件数量
793
+ const unstagedFilesCount = computed(() => {
794
+ return gitLogStore.fileList.filter(file => ['modified', 'deleted', 'untracked'].includes(file.type)).length;
795
+ });
796
+
797
+ // 计算已暂存文件数量
798
+ const stagedFilesCount = computed(() => {
799
+ return gitLogStore.fileList.filter(file => file.type === 'added').length;
800
+ });
801
+
802
+ const hasStagedChanges = computed(() => {
803
+ return stagedFilesCount.value > 0;
804
+ });
805
+
806
+ const hasAnyChanges = computed(() => {
807
+ return gitLogStore.fileList.length > 0;
808
+ });
809
+
810
+ const needsPush = computed(() => {
811
+ return gitStore.branchAhead > 0;
812
+ });
813
+
814
+ const needsPull = computed(() => {
815
+ return gitStore.branchBehind > 0;
816
+ });
817
+
818
+ const canPush = computed(() => {
819
+ // 修改条件判断:
820
+ // 1. 如果分支有上游并且领先提交,可以推送
821
+ // 2. 如果有已暂存的更改但未提交,不能推送
822
+ // 3. 如果有已提交未推送的更改,可以推送
823
+ return gitStore.hasUpstream && (needsPush.value || (hasStagedChanges.value && finalCommitMessage.value.trim()));
824
+ });
825
+
826
+ const canReset = computed(() => {
827
+ return hasStagedChanges.value;
828
+ });
829
+
830
+ const canResetToRemote = computed(() => {
831
+ return gitStore.hasUpstream && (needsPush.value || needsPull.value || hasAnyChanges.value);
832
+ });
833
+
834
+ // 保存默认提交信息模板
835
+ async function saveMessageTemplate() {
836
+ if (!newDefaultMessage.value.trim()) {
837
+ ElMessage({
838
+ message: "请输入模板内容",
839
+ type: "warning",
840
+ });
841
+ return;
842
+ }
843
+
844
+ try {
845
+ // 判断是编辑还是新建
846
+ if (isEditingMessage.value) {
847
+ // 编辑现有模板
848
+ await updateMessageTemplate();
849
+ } else {
850
+ // 新建模板
851
+ // 检查是否已存在相同模板
852
+ if (messageTemplates.value.includes(newDefaultMessage.value)) {
853
+ ElMessage({
854
+ message: "该模板已存在",
855
+ type: "warning",
856
+ });
857
+ return;
858
+ }
859
+
860
+ // 添加到本地数组
861
+ messageTemplates.value.push(newDefaultMessage.value);
862
+
863
+ // 保存到服务器
864
+ const response = await fetch("/api/config/save-template", {
865
+ method: "POST",
866
+ headers: {
867
+ "Content-Type": "application/json",
868
+ },
869
+ body: JSON.stringify({
870
+ template: newDefaultMessage.value,
871
+ type: "message",
872
+ }),
873
+ });
874
+
875
+ const result = await response.json();
876
+ if (result.success) {
877
+ ElMessage({
878
+ message: "提交信息模板保存成功!",
879
+ type: "success",
880
+ });
881
+ newDefaultMessage.value = "";
882
+ } else {
883
+ ElMessage({
884
+ message: "模板保存失败: " + result.error,
885
+ type: "error",
886
+ });
887
+ }
888
+ }
889
+ } catch (error) {
890
+ ElMessage({
891
+ message: "模板保存失败: " + (error as Error).message,
892
+ type: "error",
893
+ });
894
+ }
895
+ }
896
+
897
+ // 更新提交信息模板
898
+ async function updateMessageTemplate() {
899
+ try {
900
+ // 先从本地数组中更新
901
+ if (editingMessageIndex.value >= 0) {
902
+ // 保存原模板和新模板
903
+ const oldTemplate = originalMessageTemplate.value;
904
+ const newTemplate = newDefaultMessage.value;
905
+
906
+ // 更新本地数组
907
+ messageTemplates.value[editingMessageIndex.value] = newTemplate;
908
+
909
+ // 调用API更新服务器
910
+ const response = await fetch("/api/config/update-template", {
911
+ method: "POST",
912
+ headers: {
913
+ "Content-Type": "application/json",
914
+ },
915
+ body: JSON.stringify({
916
+ oldTemplate,
917
+ newTemplate,
918
+ type: "message",
919
+ }),
920
+ });
921
+
922
+ const result = await response.json();
923
+ if (result.success) {
924
+ ElMessage({
925
+ message: "提交信息模板更新成功!",
926
+ type: "success",
927
+ });
928
+
929
+ // 重置编辑状态
930
+ isEditingMessage.value = false;
931
+ originalMessageTemplate.value = "";
932
+ editingMessageIndex.value = -1;
933
+ newDefaultMessage.value = "";
934
+ } else {
935
+ ElMessage({
936
+ message: "模板更新失败: " + result.error,
937
+ type: "error",
938
+ });
939
+ }
940
+ }
941
+ } catch (error) {
942
+ ElMessage({
943
+ message: "模板更新失败: " + (error as Error).message,
944
+ type: "error",
945
+ });
946
+ }
947
+ }
948
+
949
+ // 开始编辑提交信息模板
950
+ function startEditMessageTemplate(template: string, index: number) {
951
+ isEditingMessage.value = true;
952
+ originalMessageTemplate.value = template;
953
+ editingMessageIndex.value = index;
954
+ newDefaultMessage.value = template;
955
+ }
956
+
957
+ // 取消编辑提交信息模板
958
+ function cancelEditMessageTemplate() {
959
+ isEditingMessage.value = false;
960
+ originalMessageTemplate.value = "";
961
+ editingMessageIndex.value = -1;
962
+ newDefaultMessage.value = "";
963
+ }
964
+
965
+ // 删除提交信息模板
966
+ async function deleteMessageTemplate(template: string) {
967
+ try {
968
+ // 从本地数组中删除
969
+ const index = messageTemplates.value.indexOf(template);
970
+ if (index !== -1) {
971
+ messageTemplates.value.splice(index, 1);
972
+ }
973
+
974
+ // 从服务器删除
975
+ const response = await fetch("/api/config/delete-template", {
976
+ method: "POST",
977
+ headers: {
978
+ "Content-Type": "application/json",
979
+ },
980
+ body: JSON.stringify({
981
+ template,
982
+ type: "message",
983
+ }),
984
+ });
985
+
986
+ const result = await response.json();
987
+ if (result.success) {
988
+ ElMessage({
989
+ message: "提交信息模板删除成功!",
990
+ type: "success",
991
+ });
992
+ } else {
993
+ ElMessage({
994
+ message: "模板删除失败: " + result.error,
995
+ type: "error",
996
+ });
997
+ }
998
+ } catch (error) {
999
+ ElMessage({
1000
+ message: "模板删除失败: " + (error as Error).message,
1001
+ type: "error",
1002
+ });
1003
+ }
1004
+ }
1005
+
1006
+ // 使用默认提交信息模板
1007
+ function useMessageTemplate(template: string) {
1008
+ // 设置为当前提交信息
1009
+ commitMessage.value = template;
1010
+ // 设置为默认提交信息编辑框的内容
1011
+ newDefaultMessage.value = template;
1012
+ }
1013
+
660
1014
  onMounted(() => {
661
1015
  loadConfig();
662
1016
 
@@ -671,6 +1025,9 @@ onMounted(() => {
671
1025
  if (savedSkipHooks !== null) {
672
1026
  skipHooks.value = savedSkipHooks === "true";
673
1027
  }
1028
+
1029
+ // 获取一次分支状态
1030
+ gitStore.getBranchStatus();
674
1031
  });
675
1032
  </script>
676
1033
 
@@ -680,6 +1037,26 @@ onMounted(() => {
680
1037
  <h2>提交更改</h2>
681
1038
  </div>
682
1039
 
1040
+ <!-- 添加推送中指示器 -->
1041
+ <transition name="el-fade-in-linear">
1042
+ <div v-if="isPushing" class="pushing-indicator">
1043
+ <div class="pushing-spinner">
1044
+ <svg viewBox="0 0 50 50" class="circular">
1045
+ <circle class="path" cx="25" cy="25" r="20" fill="none" />
1046
+ </svg>
1047
+ </div>
1048
+ <div class="pushing-text">正在推送...</div>
1049
+ </div>
1050
+ </transition>
1051
+
1052
+ <!-- 添加推送成功指示器 -->
1053
+ <transition name="el-fade-in-linear">
1054
+ <div v-if="showPushSuccess" class="push-success-indicator">
1055
+ <el-icon class="push-success-icon"><Check /></el-icon>
1056
+ <div class="push-success-text">推送成功!</div>
1057
+ </div>
1058
+ </transition>
1059
+
683
1060
  <div class="card-content">
684
1061
  <div class="layout-container">
685
1062
  <!-- 如果没有配置Git用户信息,显示提示 -->
@@ -716,7 +1093,27 @@ git config --global user.email "your.email@example.com"</pre>
716
1093
 
717
1094
  <!-- 普通提交表单 -->
718
1095
  <div v-if="!isStandardCommit" class="commit-form">
719
- <el-input v-model="commitMessage" :placeholder="placeholder" clearable />
1096
+ <div class="description-container">
1097
+ <el-input
1098
+ v-model="commitMessage"
1099
+ :placeholder="placeholder"
1100
+ type="textarea"
1101
+ :rows="6"
1102
+ resize="none"
1103
+ class="commit-message-input"
1104
+ />
1105
+ <div class="input-actions">
1106
+ <el-button type="primary" :icon="Setting" circle size="small" class="settings-button"
1107
+ @click="openDefaultMessageSettings">
1108
+ </el-button>
1109
+ </div>
1110
+ </div>
1111
+
1112
+ <!-- 添加Git命令预览区域 -->
1113
+ <div class="preview-section">
1114
+ <div class="preview-title">Git提交命令预览:</div>
1115
+ <pre class="preview-content code-command">git commit -m "{{ finalCommitMessage || '<提交信息>' }}"{{ skipHooks ? ' --no-verify' : '' }}</pre>
1116
+ </div>
720
1117
  </div>
721
1118
 
722
1119
  <!-- 标准化提交表单 -->
@@ -750,7 +1147,7 @@ git config --global user.email "your.email@example.com"</pre>
750
1147
  <div class="preview-title">提交信息预览:</div>
751
1148
  <pre class="preview-content">{{ finalCommitMessage }}</pre>
752
1149
 
753
- <div class="preview-title" style="margin-top: 10px;">Git命令预览:</div>
1150
+ <div class="preview-title" style="margin-top: 10px;">Git提交命令预览:</div>
754
1151
  <pre class="preview-content code-command">{{ gitCommandPreview }}</pre>
755
1152
  </div>
756
1153
  </div>
@@ -760,89 +1157,144 @@ git config --global user.email "your.email@example.com"</pre>
760
1157
  <div class="actions-section">
761
1158
  <h3>Git 操作</h3>
762
1159
  <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>
1160
+ <div class="operations-wrapper">
1161
+ <!-- 基础操作 -->
1162
+ <div class="action-group">
1163
+ <div class="group-title">基础操作</div>
1164
+ <div class="group-buttons">
1165
+ <el-tooltip :content="hasUnstagedChanges ? `暂存${unstagedFilesCount}个待更改文件` : 'git add .'" placement="top" effect="light" popper-class="git-cmd-tooltip">
1166
+ <el-button
1167
+ type="primary"
1168
+ @click="addToStage"
1169
+ :loading="gitLogStore.isAddingFiles"
1170
+ :disabled="!hasUnstagedChanges"
1171
+ class="action-button"
1172
+ >
1173
+ 暂存更改
1174
+ <span v-if="unstagedFilesCount > 0">({{unstagedFilesCount}})</span>
1175
+ </el-button>
1176
+ </el-tooltip>
1177
+
1178
+ <el-tooltip :content="hasStagedChanges ? `提交${stagedFilesCount}个已暂存文件` : 'git commit'" placement="top" effect="light" popper-class="git-cmd-tooltip">
1179
+ <el-button
1180
+ type="primary"
1181
+ @click="commitChanges"
1182
+ :loading="gitLogStore.isLoadingStatus"
1183
+ :disabled="!hasStagedChanges || !finalCommitMessage.trim()"
1184
+ class="action-button"
1185
+ >
1186
+ 提交
1187
+ <span v-if="stagedFilesCount > 0">({{stagedFilesCount}})</span>
1188
+ </el-button>
1189
+ </el-tooltip>
1190
+
1191
+ <el-tooltip :content="needsPush ? `推送${gitStore.branchAhead}个本地提交` : 'git push'" placement="top" effect="light" popper-class="git-cmd-tooltip">
1192
+ <el-button
1193
+ type="primary"
1194
+ :icon="Upload"
1195
+ @click="pushToRemote"
1196
+ :loading="gitLogStore.isPushing"
1197
+ :disabled="!canPush"
1198
+ :class="['action-button', 'push-button', { 'is-loading': gitLogStore.isPushing || isPushing }]"
1199
+ :style="needsPush ? {backgroundColor: '#67c23a !important', borderColor: '#67c23a !important'} : {}"
1200
+ >
1201
+ 推送
1202
+ <span v-if="needsPush">({{gitStore.branchAhead}})</span>
1203
+ </el-button>
1204
+ </el-tooltip>
1205
+
1206
+ <el-tooltip :content="needsPull ? `拉取${gitStore.branchBehind}个远程提交` : 'git pull'" placement="top" effect="light" popper-class="git-cmd-tooltip">
1207
+ <el-button
1208
+ type="primary"
1209
+ :icon="Download"
1210
+ @click="handleGitPull"
1211
+ :loading="isGitPulling"
1212
+ :disabled="!gitStore.hasUpstream"
1213
+ class="action-button"
1214
+ :style="needsPull ? {color: 'white', backgroundColor: '#E6A23C', borderColor: '#E6A23C'} : {}"
1215
+ >
1216
+ 拉取
1217
+ <span v-if="needsPull">({{gitStore.branchBehind}})</span>
1218
+ </el-button>
1219
+ </el-tooltip>
1220
+
1221
+ <el-tooltip content="git fetch --all" placement="top" effect="light" popper-class="git-cmd-tooltip">
1222
+ <el-button
1223
+ type="info"
1224
+ :icon="Connection"
1225
+ @click="handleGitFetchAll"
1226
+ :loading="isGitFetching"
1227
+ class="action-button"
1228
+ >
1229
+ 获取所有远程分支
1230
+ </el-button>
1231
+ </el-tooltip>
1232
+ </div>
795
1233
  </div>
796
- </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
1234
 
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>
1235
+ <!-- 组合操作 -->
1236
+ <div class="action-group">
1237
+ <div class="group-title">组合操作</div>
1238
+ <div class="group-buttons">
1239
+ <el-tooltip content="git add + git commit" placement="top" effect="light" popper-class="git-cmd-tooltip">
1240
+ <el-button
1241
+ type="primary"
1242
+ :icon="Edit"
1243
+ @click="addAndCommit"
1244
+ :loading="gitLogStore.isAddingFiles || gitLogStore.isCommiting"
1245
+ :disabled="!hasUnstagedChanges || !finalCommitMessage.trim()"
1246
+ class="action-button"
1247
+ >
1248
+ 暂存并提交
1249
+ </el-button>
1250
+ </el-tooltip>
1251
+
1252
+ <el-tooltip content="git add + git commit + git push" placement="top" effect="light" popper-class="git-cmd-tooltip">
1253
+ <el-button
1254
+ type="success"
1255
+ :icon="Position"
1256
+ @click="addCommitAndPush"
1257
+ :loading="gitLogStore.isAddingFiles || gitLogStore.isCommiting || gitLogStore.isPushing"
1258
+ :disabled="!hasAnyChanges || !finalCommitMessage.trim() || !gitStore.hasUpstream"
1259
+ :class="['action-button', 'one-click-push', { 'is-loading': gitLogStore.isAddingFiles || gitLogStore.isCommiting || gitLogStore.isPushing }]"
1260
+ >
1261
+ 一键推送
1262
+ </el-button>
1263
+ </el-tooltip>
1264
+ </div>
820
1265
  </div>
821
1266
  </div>
822
1267
 
823
- <div class="action-group">
1268
+ <!-- 重置操作 -->
1269
+ <div class="action-group reset-group">
824
1270
  <div class="group-title">重置操作</div>
825
1271
  <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>
1272
+ <el-tooltip :content="canReset ? `撤销${stagedFilesCount}个已暂存文件` : 'git reset HEAD'" placement="top" effect="light" popper-class="git-cmd-tooltip">
1273
+ <el-button
1274
+ type="warning"
1275
+ :icon="RefreshRight"
1276
+ @click="gitLogStore.resetHead"
1277
+ :loading="gitLogStore.isResetting"
1278
+ :disabled="!canReset"
1279
+ class="action-button reset-button"
1280
+ >
1281
+ 重置暂存区
1282
+ <span v-if="stagedFilesCount > 0">({{stagedFilesCount}})</span>
1283
+ </el-button>
1284
+ </el-tooltip>
1285
+
1286
+ <el-tooltip content="git reset --hard origin/branch" placement="top" effect="light" popper-class="git-cmd-tooltip">
1287
+ <el-button
1288
+ type="danger"
1289
+ :icon="Delete"
1290
+ @click="resetToRemote"
1291
+ :loading="gitLogStore.isResetting"
1292
+ :disabled="!canResetToRemote"
1293
+ class="action-button danger-button"
1294
+ >
1295
+ 重置到远程
1296
+ </el-button>
1297
+ </el-tooltip>
846
1298
  </div>
847
1299
  </div>
848
1300
  </div>
@@ -851,7 +1303,15 @@ git config --global user.email "your.email@example.com"</pre>
851
1303
  </div>
852
1304
 
853
1305
  <!-- 简短描述设置弹窗 -->
854
- <el-dialog title="简短描述模板设置" v-model="descriptionDialogVisible" width="80vw" style="height: 80vh">
1306
+ <el-dialog
1307
+ title="简短描述模板设置"
1308
+ v-model="descriptionDialogVisible"
1309
+ width="80vw"
1310
+ top="70px"
1311
+ style="height: calc(100vh - 140px);"
1312
+ :close-on-click-modal="false"
1313
+ class="template-dialog"
1314
+ >
855
1315
  <div class="template-container">
856
1316
  <div class="template-form">
857
1317
  <el-input v-model="newTemplateName" :placeholder="isEditingDescription ? '编辑模板内容' : '输入新模板内容'"
@@ -883,7 +1343,15 @@ git config --global user.email "your.email@example.com"</pre>
883
1343
  </el-dialog>
884
1344
 
885
1345
  <!-- 作用域设置弹窗 -->
886
- <el-dialog title="作用域模板设置" v-model="scopeDialogVisible" width="80%" style="height: 80vh">
1346
+ <el-dialog
1347
+ title="作用域模板设置"
1348
+ v-model="scopeDialogVisible"
1349
+ width="80vw"
1350
+ top="70px"
1351
+ style="height: calc(100vh - 140px);"
1352
+ :close-on-click-modal="false"
1353
+ class="template-dialog"
1354
+ >
887
1355
  <div class="template-container">
888
1356
  <div class="template-form">
889
1357
  <el-input v-model="newScopeTemplate" :placeholder="isEditingScope ? '编辑作用域模板内容' : '输入新作用域模板'"
@@ -912,6 +1380,66 @@ git config --global user.email "your.email@example.com"</pre>
912
1380
  </div>
913
1381
  </div>
914
1382
  </el-dialog>
1383
+
1384
+ <!-- 默认提交信息设置弹窗 -->
1385
+ <el-dialog
1386
+ title="默认提交信息设置"
1387
+ v-model="defaultMessageDialogVisible"
1388
+ width="80vw"
1389
+ top="70px"
1390
+ style="height: calc(100vh - 140px);"
1391
+ :close-on-click-modal="false"
1392
+ class="message-template-dialog"
1393
+ >
1394
+ <div class="template-container message-template-container">
1395
+ <div class="template-form">
1396
+ <el-input v-model="newDefaultMessage" :placeholder="isEditingMessage ? '编辑模板内容' : '输入新模板内容'" class="template-input" clearable />
1397
+ <div class="template-form-buttons">
1398
+ <el-button v-if="isEditingMessage" @click="cancelEditMessageTemplate">取消</el-button>
1399
+ <el-button type="primary" @click="saveMessageTemplate" :disabled="!newDefaultMessage.trim()">
1400
+ {{ isEditingMessage ? '更新模板' : '添加模板' }}
1401
+ </el-button>
1402
+ <el-button type="success" @click="saveDefaultMessage" :disabled="!newDefaultMessage.trim()">
1403
+ 设为默认提交信息
1404
+ </el-button>
1405
+ </div>
1406
+ </div>
1407
+
1408
+ <div class="templates-container">
1409
+ <div class="message-templates-list">
1410
+ <h3>已保存模板</h3>
1411
+ <div class="templates-scroll-area">
1412
+ <el-empty v-if="messageTemplates.length === 0" description="暂无保存的模板" />
1413
+ <el-card v-for="(template, index) in messageTemplates" :key="index" class="template-item">
1414
+ <el-row justify="space-between" align="middle" style="width: 100%">
1415
+ <div class="template-content">{{ template }}</div>
1416
+ <div class="template-actions">
1417
+ <el-button type="primary" size="small" @click="useMessageTemplate(template)">使用</el-button>
1418
+ <el-button type="warning" size="small" :icon="Edit"
1419
+ @click="startEditMessageTemplate(template, index)">编辑</el-button>
1420
+ <el-button type="danger" size="small" @click="deleteMessageTemplate(template)">删除</el-button>
1421
+ </div>
1422
+ </el-row>
1423
+ </el-card>
1424
+ </div>
1425
+ </div>
1426
+
1427
+ <div class="current-default-message">
1428
+ <h3>当前默认提交信息</h3>
1429
+ <el-card class="default-message-card" v-if="defaultCommitMessage">
1430
+ <div class="default-message-content">{{ defaultCommitMessage }}</div>
1431
+ </el-card>
1432
+ <el-empty v-else description="尚未设置默认提交信息" :image-size="100" />
1433
+
1434
+ <div class="message-help-text">
1435
+ <h4>关于默认提交信息</h4>
1436
+ <p>默认提交信息将在未输入提交信息时自动使用。</p>
1437
+ <p>你可以通过点击左侧模板的<el-tag size="small" type="primary">使用</el-tag>按钮先选择喜欢的模板,然后点击上方<el-tag size="small" type="success">设为默认提交信息</el-tag>按钮保存。</p>
1438
+ </div>
1439
+ </div>
1440
+ </div>
1441
+ </div>
1442
+ </el-dialog>
915
1443
  </div>
916
1444
  </div>
917
1445
  </template>
@@ -960,6 +1488,7 @@ git config --global user.email "your.email@example.com"</pre>
960
1488
  display: flex;
961
1489
  flex-direction: column;
962
1490
  overflow: hidden;
1491
+ position: relative;
963
1492
  }
964
1493
 
965
1494
  .card-header {
@@ -986,7 +1515,8 @@ git config --global user.email "your.email@example.com"</pre>
986
1515
 
987
1516
  .layout-container {
988
1517
  display: flex;
989
- gap: 20px;
1518
+ flex-direction: column;
1519
+ gap: 15px;
990
1520
  height: 100%;
991
1521
  }
992
1522
 
@@ -996,45 +1526,41 @@ git config --global user.email "your.email@example.com"</pre>
996
1526
  }
997
1527
 
998
1528
  .actions-section {
999
- width: 300px;
1529
+ width: 100%;
1000
1530
  flex-shrink: 0;
1001
1531
  }
1002
1532
 
1003
1533
  .actions-section h3 {
1004
1534
  margin-top: 0;
1005
- margin-bottom: 15px;
1006
- padding-bottom: 10px;
1535
+ margin-bottom: 10px;
1536
+ padding-bottom: 8px;
1007
1537
  border-bottom: 1px solid #dcdfe6;
1008
- font-size: 18px;
1538
+ font-size: 16px;
1009
1539
  color: #303133;
1010
1540
  font-weight: 500;
1011
1541
  }
1012
1542
 
1013
- .commit-form {
1543
+ .operations-wrapper {
1014
1544
  display: flex;
1015
- margin-bottom: 15px;
1016
1545
  gap: 10px;
1017
1546
  }
1018
1547
 
1019
- .git-actions {
1020
- margin-top: 20px;
1021
- }
1022
-
1023
1548
  .action-groups {
1024
1549
  display: flex;
1025
1550
  flex-direction: column;
1026
- gap: 15px;
1551
+ gap: 12px;
1027
1552
  }
1028
1553
 
1029
1554
  .action-group {
1030
1555
  background-color: #f9f9f9;
1031
- border-radius: 8px;
1032
- padding: 12px 15px;
1556
+ border-radius: 6px;
1557
+ padding: 8px 10px;
1033
1558
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.05);
1034
- border-left: 4px solid #409EFF;
1035
- overflow: hidden; /* 确保子元素不会溢出 */
1559
+ border-left: 3px solid #409EFF;
1560
+ flex: 1;
1036
1561
  }
1037
1562
 
1563
+
1038
1564
  .action-group:nth-child(2) {
1039
1565
  border-left-color: #E6A23C;
1040
1566
  }
@@ -1044,82 +1570,51 @@ git config --global user.email "your.email@example.com"</pre>
1044
1570
  }
1045
1571
 
1046
1572
  .group-title {
1047
- font-size: 14px;
1573
+ font-size: 13px;
1048
1574
  font-weight: bold;
1049
- margin-bottom: 10px;
1575
+ margin-bottom: 8px;
1050
1576
  color: #606266;
1051
1577
  text-align: left;
1052
1578
  display: block;
1053
1579
  position: relative;
1054
- padding-left: 10px;
1580
+ padding-left: 6px;
1055
1581
  border-bottom: 1px solid rgba(0, 0, 0, 0.06);
1056
- padding-bottom: 8px;
1582
+ padding-bottom: 6px;
1057
1583
  }
1058
1584
 
1059
1585
  .group-buttons {
1060
1586
  display: flex;
1061
- flex-direction: column;
1587
+ flex-direction: row;
1588
+ flex-wrap: wrap;
1062
1589
  gap: 8px;
1063
- padding: 0 2px;
1590
+ padding: 0;
1064
1591
  }
1065
1592
 
1066
1593
  .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;
1594
+ font-size: 14px;
1595
+ font-weight: 500;
1596
+ flex: 1;
1597
+ min-width: 100px;
1598
+ border-radius: 4px;
1599
+ height: 36px;
1600
+ padding: 0 10px;
1079
1601
  }
1080
1602
 
1081
1603
  .action-button:hover {
1082
- transform: translateY(-2px);
1083
- box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);
1604
+ transform: translateY(-1px);
1605
+ box-shadow: 0 2px 5px rgba(0, 0, 0, 0.15);
1084
1606
  }
1085
1607
 
1086
1608
  .action-button:active {
1087
1609
  transform: translateY(0);
1088
1610
  }
1089
1611
 
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不会改变按钮高度 */
1097
- }
1098
-
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
1612
  .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;
1613
+ display: none;
1614
+ }
1122
1615
 
1616
+ .command-text-long {
1617
+ display: none;
1123
1618
  }
1124
1619
 
1125
1620
  .standard-commit-form {
@@ -1170,6 +1665,7 @@ git config --global user.email "your.email@example.com"</pre>
1170
1665
  background-color: #f5f7fa;
1171
1666
  padding: 10px;
1172
1667
  border-radius: 4px;
1668
+ margin-top: 10px;
1173
1669
  }
1174
1670
 
1175
1671
  .preview-title {
@@ -1191,15 +1687,22 @@ git config --global user.email "your.email@example.com"</pre>
1191
1687
  flex-direction: column;
1192
1688
  height: calc(85vh - 100px);
1193
1689
  overflow-y: auto;
1690
+ padding: 5px;
1194
1691
  }
1195
1692
 
1196
1693
  .template-form {
1197
1694
  margin-bottom: 20px;
1695
+ background-color: #f8f9fa;
1696
+ padding: 15px;
1697
+ border-radius: 6px;
1698
+ border: 1px solid #ebeef5;
1198
1699
  }
1199
1700
 
1200
- .template-list {
1201
- flex: 1;
1202
- overflow-y: auto;
1701
+ .template-form-buttons {
1702
+ display: flex;
1703
+ gap: 10px;
1704
+ margin-top: 12px;
1705
+ justify-content: flex-end;
1203
1706
  }
1204
1707
 
1205
1708
  .template-input {
@@ -1211,25 +1714,42 @@ git config --global user.email "your.email@example.com"</pre>
1211
1714
  height: 100%;
1212
1715
  }
1213
1716
 
1717
+ .template-list h3 {
1718
+ margin-top: 0;
1719
+ margin-bottom: 15px;
1720
+ font-size: 16px;
1721
+ font-weight: 500;
1722
+ color: #303133;
1723
+ padding-bottom: 8px;
1724
+ border-bottom: 1px solid #ebeef5;
1725
+ }
1726
+
1214
1727
  .template-item {
1215
1728
  margin-bottom: 10px;
1729
+ transition: all 0.2s ease;
1730
+ border: 1px solid #ebeef5;
1216
1731
  }
1217
1732
 
1218
1733
  .template-item:hover {
1219
1734
  background-color: #f5f7fa;
1735
+ transform: translateY(-2px);
1736
+ box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
1220
1737
  }
1221
1738
 
1222
1739
  .template-content {
1223
1740
  flex-grow: 1;
1224
1741
  margin-right: 10px;
1225
1742
  word-break: break-all;
1743
+ padding: 5px 0;
1744
+ color: #303133;
1745
+ font-weight: 500;
1226
1746
  }
1227
1747
 
1228
1748
  .template-actions {
1229
1749
  display: flex;
1230
- gap: 5px;
1750
+ gap: 8px;
1231
1751
  justify-content: flex-end;
1232
- min-width: 120px;
1752
+ min-width: 180px;
1233
1753
  flex-shrink: 0;
1234
1754
  }
1235
1755
 
@@ -1251,23 +1771,21 @@ git config --global user.email "your.email@example.com"</pre>
1251
1771
  font-size: 14px;
1252
1772
  }
1253
1773
 
1254
- @media (max-width: 768px) {
1774
+ @media (min-width: 768px) {
1255
1775
  .layout-container {
1256
- flex-direction: column;
1776
+ flex-direction: row;
1257
1777
  }
1258
1778
 
1259
- .actions-section {
1260
- width: 100%;
1779
+ .commit-section {
1780
+ flex: 3;
1261
1781
  }
1262
-
1263
- .group-buttons {
1264
- flex-direction: row;
1265
- flex-wrap: wrap;
1782
+
1783
+ .actions-section {
1784
+ width: 320px;
1266
1785
  }
1267
1786
 
1268
- .action-button {
1269
- flex: 1;
1270
- min-width: 120px;
1787
+ .operations-wrapper {
1788
+ flex-direction: column;
1271
1789
  }
1272
1790
  }
1273
1791
 
@@ -1286,7 +1804,25 @@ git config --global user.email "your.email@example.com"</pre>
1286
1804
  white-space: pre;
1287
1805
  }
1288
1806
 
1289
- /* 特定按钮样式 */
1807
+ /* 推送时的动画效果 */
1808
+ @keyframes pushing-pulse {
1809
+ 0% { box-shadow: 0 0 0 0 rgba(103, 194, 58, 0.4); }
1810
+ 70% { box-shadow: 0 0 0 15px rgba(103, 194, 58, 0); }
1811
+ 100% { box-shadow: 0 0 0 0 rgba(103, 194, 58, 0); }
1812
+ }
1813
+
1814
+ @keyframes pushing-border {
1815
+ 0% { border-color: #67c23a; }
1816
+ 50% { border-color: #85ce61; }
1817
+ 100% { border-color: #67c23a; }
1818
+ }
1819
+
1820
+ .card.is-pushing {
1821
+ animation: pushing-border 1.5s infinite ease-in-out;
1822
+ box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
1823
+ transition: all 0.3s ease;
1824
+ }
1825
+
1290
1826
  .push-button {
1291
1827
  background-color: #67c23a;
1292
1828
  border-color: #67c23a;
@@ -1297,6 +1833,82 @@ git config --global user.email "your.email@example.com"</pre>
1297
1833
  border-color: #85ce61;
1298
1834
  }
1299
1835
 
1836
+ .push-button.is-loading,
1837
+ .push-button.is-loading:hover,
1838
+ .push-button.is-loading:focus {
1839
+ animation: pushing-pulse 1.5s infinite;
1840
+ background-color: #67c23a !important;
1841
+ border-color: #67c23a !important;
1842
+ }
1843
+
1844
+ .el-button.push-button.is-loading .el-loading-spinner {
1845
+ color: #fff !important;
1846
+ }
1847
+
1848
+ /* 一键推送按钮动画 */
1849
+ @keyframes one-click-push-glow {
1850
+ 0% { box-shadow: 0 0 5px rgba(103, 194, 58, 0.5); }
1851
+ 50% { box-shadow: 0 0 20px rgba(103, 194, 58, 0.8); }
1852
+ 100% { box-shadow: 0 0 5px rgba(103, 194, 58, 0.5); }
1853
+ }
1854
+
1855
+ .action-button.one-click-push {
1856
+ position: relative;
1857
+ overflow: hidden;
1858
+ }
1859
+
1860
+ .action-button.one-click-push.is-loading,
1861
+ .action-button.one-click-push.is-loading:hover {
1862
+ animation: one-click-push-glow 1.5s infinite;
1863
+ background-color: #67c23a !important;
1864
+ border-color: #67c23a !important;
1865
+ }
1866
+
1867
+ /* 推送成功动画 */
1868
+ @keyframes push-success {
1869
+ 0% { transform: scale(1); }
1870
+ 50% { transform: scale(1.1); }
1871
+ 100% { transform: scale(1); }
1872
+ }
1873
+
1874
+ .push-success-indicator {
1875
+ position: absolute;
1876
+ inset: 0; /* 同时设置top, right, bottom, left为0 */
1877
+ margin: auto;
1878
+ background-color: rgba(255, 255, 255, 1);
1879
+ border-radius: 12px;
1880
+ padding: 20px 30px;
1881
+ box-shadow: 0 8px 24px rgba(0, 0, 0, 0.15);
1882
+ display: flex;
1883
+ flex-direction: column;
1884
+ align-items: center;
1885
+ justify-content: center;
1886
+ animation: push-success 0.5s ease-out;
1887
+ z-index: 9999;
1888
+ width: 200px;
1889
+ height: 200px;
1890
+ }
1891
+
1892
+ .push-success-icon {
1893
+ font-size: 64px;
1894
+ color: #67c23a;
1895
+ margin-bottom: 16px;
1896
+ animation: bounce 0.8s ease-in-out;
1897
+ }
1898
+
1899
+ @keyframes bounce {
1900
+ 0%, 20%, 50%, 80%, 100% {transform: translateY(0);}
1901
+ 40% {transform: translateY(-20px);}
1902
+ 60% {transform: translateY(-10px);}
1903
+ }
1904
+
1905
+ .push-success-text {
1906
+ font-size: 20px;
1907
+ font-weight: bold;
1908
+ color: #303133;
1909
+ text-align: center;
1910
+ }
1911
+
1300
1912
  .reset-button {
1301
1913
  background-color: #909399;
1302
1914
  border-color: #909399;
@@ -1309,4 +1921,246 @@ git config --global user.email "your.email@example.com"</pre>
1309
1921
  .el-button+.el-button {
1310
1922
  margin-left: 0;
1311
1923
  }
1924
+
1925
+ /* 推送中动画样式 */
1926
+ .pushing-indicator {
1927
+ position: absolute;
1928
+ inset: 0;
1929
+ margin: auto;
1930
+ background-color: rgba(64, 158, 255, 1);
1931
+ border-radius: 12px;
1932
+ padding: 20px 30px;
1933
+ box-shadow: 0 8px 24px rgba(0, 0, 0, 0.15);
1934
+ display: flex;
1935
+ flex-direction: column;
1936
+ align-items: center;
1937
+ justify-content: center;
1938
+ z-index: 9999;
1939
+ width: 200px;
1940
+ height: 200px;
1941
+ color: white;
1942
+ }
1943
+
1944
+ .pushing-spinner {
1945
+ margin-bottom: 16px;
1946
+ }
1947
+
1948
+ .pushing-text {
1949
+ font-size: 20px;
1950
+ font-weight: bold;
1951
+ text-align: center;
1952
+ }
1953
+
1954
+ .circular {
1955
+ height: 64px;
1956
+ width: 64px;
1957
+ animation: pushing-rotate 2s linear infinite;
1958
+ }
1959
+
1960
+ .path {
1961
+ stroke: white;
1962
+ stroke-width: 4;
1963
+ stroke-linecap: round;
1964
+ stroke-dasharray: 90, 150;
1965
+ stroke-dashoffset: 0;
1966
+ animation: pushing-dash 1.5s ease-in-out infinite;
1967
+ }
1968
+
1969
+ @keyframes pushing-rotate {
1970
+ 100% {
1971
+ transform: rotate(360deg);
1972
+ }
1973
+ }
1974
+
1975
+ @keyframes pushing-dash {
1976
+ 0% {
1977
+ stroke-dasharray: 1, 150;
1978
+ stroke-dashoffset: 0;
1979
+ }
1980
+ 50% {
1981
+ stroke-dasharray: 90, 150;
1982
+ stroke-dashoffset: -35;
1983
+ }
1984
+ 100% {
1985
+ stroke-dasharray: 90, 150;
1986
+ stroke-dashoffset: -124;
1987
+ }
1988
+ }
1989
+
1990
+ .message-template-container {
1991
+ display: flex;
1992
+ flex-direction: column;
1993
+ height: calc(100vh - 278px);
1994
+ overflow: hidden;
1995
+ }
1996
+
1997
+ .templates-container {
1998
+ display: flex;
1999
+ gap: 20px;
2000
+ margin-top: 15px;
2001
+ flex: 1;
2002
+ overflow: hidden;
2003
+ }
2004
+
2005
+ .message-templates-list {
2006
+ flex: 3;
2007
+ display: flex;
2008
+ flex-direction: column;
2009
+ border-right: 1px solid #ebeef5;
2010
+ padding-right: 15px;
2011
+ height: calc(100vh - 432px);
2012
+ }
2013
+
2014
+ .message-templates-list h3 {
2015
+ margin-top: 0;
2016
+ margin-bottom: 15px;
2017
+ font-size: 16px;
2018
+ font-weight: 500;
2019
+ color: #303133;
2020
+ padding-bottom: 8px;
2021
+ border-bottom: 1px solid #ebeef5;
2022
+ }
2023
+
2024
+ .current-default-message {
2025
+ flex: 2;
2026
+ display: flex;
2027
+ flex-direction: column;
2028
+ gap: 15px;
2029
+ padding-left: 15px;
2030
+ }
2031
+
2032
+ .current-default-message h3 {
2033
+ margin-top: 0;
2034
+ margin-bottom: 15px;
2035
+ font-size: 16px;
2036
+ font-weight: 500;
2037
+ color: #303133;
2038
+ padding-bottom: 8px;
2039
+ border-bottom: 1px solid #ebeef5;
2040
+ }
2041
+
2042
+ .templates-scroll-area {
2043
+ overflow-y: auto;
2044
+ padding-right: 5px;
2045
+ flex: 1;
2046
+ }
2047
+
2048
+ .default-message-card {
2049
+ margin-bottom: 15px;
2050
+ box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);
2051
+ border-radius: 4px;
2052
+ transition: all 0.3s ease;
2053
+ }
2054
+
2055
+ .default-message-card:hover {
2056
+ box-shadow: 0 4px 12px rgba(0, 0, 0, 0.12);
2057
+ }
2058
+
2059
+ .default-message-content {
2060
+ padding: 12px 15px;
2061
+ background-color: #f0f9eb;
2062
+ border-left: 3px solid #67c23a;
2063
+ font-weight: 500;
2064
+ word-break: break-all;
2065
+ min-height: 60px;
2066
+ display: flex;
2067
+ align-items: center;
2068
+ border-radius: 0 4px 4px 0;
2069
+ color: #303133;
2070
+ }
2071
+
2072
+ .message-help-text {
2073
+ background-color: #f8f9fa;
2074
+ border-radius: 4px;
2075
+ padding: 15px;
2076
+ font-size: 14px;
2077
+ color: #606266;
2078
+ border-left: 3px solid #909399;
2079
+ margin-top: auto;
2080
+ box-shadow: 0 2px 8px rgba(0, 0, 0, 0.05);
2081
+ }
2082
+
2083
+ .message-help-text h4 {
2084
+ margin-top: 0;
2085
+ margin-bottom: 10px;
2086
+ color: #303133;
2087
+ font-size: 15px;
2088
+ }
2089
+
2090
+ .message-help-text p {
2091
+ margin: 8px 0;
2092
+ line-height: 1.5;
2093
+ }
2094
+ </style>
2095
+
2096
+ <!-- 添加全局样式 -->
2097
+ <style>
2098
+ /* Git命令tooltip样式 */
2099
+ .git-cmd-tooltip {
2100
+ font-family: 'Consolas', 'Courier New', monospace !important;
2101
+ font-size: 13px !important;
2102
+ font-weight: 500 !important;
2103
+ color: #303133 !important;
2104
+ background-color: #f5f7fa !important;
2105
+ border: 1px solid #dcdfe6 !important;
2106
+ border-radius: 4px !important;
2107
+ padding: 8px 12px !important;
2108
+ box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1) !important;
2109
+ }
2110
+
2111
+ /* 弹窗样式优化 */
2112
+ .template-dialog .el-dialog__header,
2113
+ .message-template-dialog .el-dialog__header {
2114
+ padding: 15px 20px;
2115
+ margin-right: 0;
2116
+ border-bottom: 1px solid #ebeef5;
2117
+ background-color: #f8f9fa;
2118
+ }
2119
+
2120
+ .template-dialog .el-dialog__title,
2121
+ .message-template-dialog .el-dialog__title {
2122
+ font-size: 16px;
2123
+ font-weight: 600;
2124
+ color: #303133;
2125
+ }
2126
+
2127
+ .template-dialog .el-dialog__body,
2128
+ .message-template-dialog .el-dialog__body {
2129
+ padding: 20px;
2130
+ }
2131
+
2132
+ .template-dialog .el-dialog__headerbtn,
2133
+ .message-template-dialog .el-dialog__headerbtn {
2134
+ top: 15px;
2135
+ right: 20px;
2136
+ }
2137
+
2138
+ .template-dialog .el-input__inner,
2139
+ .message-template-dialog .el-input__inner {
2140
+ height: 40px;
2141
+ line-height: 40px;
2142
+ }
2143
+
2144
+ .template-dialog .el-button,
2145
+ .message-template-dialog .el-button {
2146
+ border-radius: 4px;
2147
+ font-weight: 500;
2148
+ }
2149
+
2150
+ .template-dialog .el-card,
2151
+ .message-template-dialog .el-card {
2152
+ border-radius: 4px;
2153
+ overflow: hidden;
2154
+ }
2155
+
2156
+ .template-dialog .el-card__body,
2157
+ .message-template-dialog .el-card__body {
2158
+ padding: 12px 15px;
2159
+ }
2160
+
2161
+ .template-dialog .el-empty__image,
2162
+ .message-template-dialog .el-empty__image {
2163
+ width: 80px;
2164
+ height: 80px;
2165
+ }
1312
2166
  </style>