zen-gitsync 2.0.5 → 2.0.7
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/README.md +31 -2
- package/package.json +3 -1
- package/src/ui/client/components.d.ts +1 -0
- package/src/ui/client/src/App.vue +417 -123
- package/src/ui/client/src/components/CommitForm.vue +553 -285
- package/src/ui/client/src/components/GitStatus.vue +954 -186
- package/src/ui/client/src/components/LogList.vue +1462 -169
- package/src/ui/client/src/stores/gitLogStore.ts +340 -17
- package/src/ui/client/src/stores/gitStore.ts +42 -1
- package/src/ui/client/stats.html +1 -1
- package/src/ui/client/vite.config.ts +2 -0
- package/src/ui/public/assets/index-B1vQ6PC_.js +20 -0
- package/src/ui/public/assets/index-CC5qWyQ-.css +1 -0
- package/src/ui/public/assets/vendor-BmPvvgTD.js +45 -0
- package/src/ui/public/index.html +3 -3
- package/src/ui/server/index.js +552 -54
- package/src/ui/public/assets/index-CALk9kKc.js +0 -9
- package/src/ui/public/assets/index-D3zIiSNw.css +0 -1
- package/src/ui/public/assets/vendor-BfXVsoKv.js +0 -45
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
import{d as Me,r as i,E as o,a as we,c as he,o as be,b as w,e as p,f as e,g as te,h as s,i as Ie,w as n,u as r,j as Ge,t as P,k as le,l as V,m as nt,F as se,n as oe,p as Re,q as Fe,s as Je,v as ze,x as Be,y as it,z as De,A as ee,B as rt,C as He,D as ct,G as ut,H as dt,I as We,J as Ze,K as qe,L as je,M as Ye,N as pt,O as Ke,P as Qe,Q as _e,R as ft,S as Xe,T as mt,U as Ne,V as vt,W as gt,X as yt,Y as pe,Z as ht,_ as _t,$ as wt,a0 as bt,a1 as $t,a2 as Ct}from"./vendor-BfXVsoKv.js";(function(){const h=document.createElement("link").relList;if(h&&h.supports&&h.supports("modulepreload"))return;for(const a of document.querySelectorAll('link[rel="modulepreload"]'))y(a);new MutationObserver(a=>{for(const x of a)if(x.type==="childList")for(const L of x.addedNodes)L.tagName==="LINK"&&L.rel==="modulepreload"&&y(L)}).observe(document,{childList:!0,subtree:!0});function G(a){const x={};return a.integrity&&(x.integrity=a.integrity),a.referrerPolicy&&(x.referrerPolicy=a.referrerPolicy),a.crossOrigin==="use-credentials"?x.credentials="include":a.crossOrigin==="anonymous"?x.credentials="omit":x.credentials="same-origin",x}function y(a){if(a.ep)return;a.ep=!0;const x=G(a);fetch(a.href,x)}})();const ie=Me("git",()=>{const F=i(""),h=i([]),G=i(""),y=i(""),a=i(!1),x=i(!1),L=i(!1),U=i(0);function q(){F.value="",h.value=[],G.value="",y.value="",a.value=!1,x.value=!1,L.value=!1,U.value=0}async function R(){const f=Date.now();if(f-U.value<1e3)return console.log("使用缓存的Git仓库状态:",L.value?"是":"不是"),L.value;try{const M=await(await fetch("/api/current_directory")).json();return L.value=M.isGitRepo===!0,U.value=f,console.log(`当前目录${L.value?"是":"不是"}Git仓库`),L.value}catch(g){return console.error("检查Git仓库状态失败:",g),L.value=!1,U.value=f,!1}}async function T(){try{const g=await(await fetch("/api/branch")).json();g.branch&&(F.value=g.branch)}catch(f){console.error("获取分支信息失败:",f)}}async function D(){try{const g=await(await fetch("/api/branches")).json();g.branches&&Array.isArray(g.branches)&&(h.value=g.branches)}catch(f){console.error("获取所有分支信息失败:",f)}}async function j(f){console.log("切换到分支:",f);try{a.value=!0;const M=await(await fetch("/api/checkout",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({branch:f})})).json();return M.success?(o({message:`已切换到分支: ${f}`,type:"success"}),T(),!0):(o({message:`切换分支失败: ${M.error}`,type:"error"}),!1)}catch(g){return o({message:`切换分支失败: ${g.message}`,type:"error"}),!1}finally{a.value=!1}}async function b(){try{const g=await(await fetch("/api/user-info")).json();g.name&&g.email&&(G.value=g.name,y.value=g.email)}catch(f){console.error("获取用户信息失败:",f)}}async function W(f,g){if(!f.trim())return o({message:"分支名称不能为空",type:"warning"}),!1;try{x.value=!0;const $=await(await fetch("/api/create-branch",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({newBranchName:f,baseBranch:g||F.value})})).json();return $.success?(o({message:`已创建并切换到分支: ${f}`,type:"success"}),T(),D(),!0):(o({message:`创建分支失败: ${$.error}`,type:"error"}),!1)}catch(M){return o({message:`创建分支失败: ${M.message}`,type:"error"}),!1}finally{x.value=!1}}async function C(){await R()?(T(),D(),b()):(F.value="",h.value=[],G.value="",y.value="")}async function E(){try{const g=await(await fetch("/api/clear-user-config",{method:"POST"})).json();return g.success?(G.value="",y.value="",o({message:"已清除Git用户配置",type:"success"}),!0):(o({message:`清除配置失败: ${g.error}`,type:"error"}),!1)}catch(f){return o({message:`清除配置失败: ${f.message}`,type:"error"}),!1}}async function I(f,g){try{const $=await(await fetch("/api/restore-user-config",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({name:f,email:g})})).json();return $.success?(G.value=f,y.value=g,o({message:"已恢复Git用户配置",type:"success"}),!0):(o({message:`恢复配置失败: ${$.error}`,type:"error"}),!1)}catch(M){return o({message:`恢复配置失败: ${M.message}`,type:"error"}),!1}}return{currentBranch:F,allBranches:h,userName:G,userEmail:y,isChangingBranch:a,isCreatingBranch:x,isGitRepo:L,lastCheckedTime:U,$reset:q,checkGitRepo:R,getCurrentBranch:T,getAllBranches:D,changeBranch:j,getUserInfo:b,createBranch:W,loadInitialData:C,clearUserConfig:E,restoreUserConfig:I}}),Le=300,Ee=Me("gitLog",()=>{const F=ie(),h=i([]),G=i({staged:[],unstaged:[],untracked:[]}),y=i(""),a=i([]),x=i(!1),L=i(!1),U=i(!1),q=i(!1),R=i(!1),T=i(!1);function D(m){if(m===void 0||m===""){a.value=[];return}const u=m.split(`
|
|
2
|
-
`),A=[];for(const v of u){const _=v.match(/^([ MADRCU\?]{2})\s+(.+)$/);if(_){let z="";const B=_[1].trim();B==="M"||B==="MM"||B==="AM"||B==="RM"?z="modified":B==="A"||B==="AA"?z="added":B==="D"||B==="AD"||B==="DA"?z="deleted":B==="??"?z="untracked":z="other",A.push({path:_[2],type:z})}}a.value=A}async function j(){if(!F.isGitRepo){console.log("当前目录不是Git仓库,跳过加载提交历史");return}try{x.value=!0,console.log("开始加载提交历史...");const u=await(await fetch("/api/log")).json();u&&Array.isArray(u)&&(h.value=u),console.log(`提交历史加载完成,共 ${h.value.length} 条记录`)}catch(m){console.error("获取提交历史失败:",m),o({message:`获取提交历史失败: ${m.message}`,type:"error"})}finally{x.value=!1}}async function b(){if(!F.isGitRepo){console.log("当前目录不是Git仓库,跳过加载Git状态");return}try{L.value=!0;const u=await(await fetch("/api/status")).json();u.status&&(y.value=u.status,G.value={staged:u.status.staged||[],unstaged:u.status.unstaged||[],untracked:u.status.untracked||[]}),await W()}catch(m){console.error("获取Git状态失败:",m),o({message:`获取Git状态失败: ${m.message}`,type:"error"})}finally{L.value=!1}}async function W(){if(!F.isGitRepo){console.log("当前目录不是Git仓库,跳过加载Git状态");return}try{const u=await(await fetch("/api/status_porcelain")).json();u.status!==void 0?D(u.status):a.value=[]}catch(m){console.error("获取Git状态(porcelain)失败:",m),o({message:`获取Git状态(porcelain)失败: ${m.message}`,type:"error"}),a.value=[]}}async function C(){if(!F.isGitRepo)return o.warning("当前目录不是Git仓库"),!1;try{U.value=!0;const u=await(await fetch("/api/add",{method:"POST"})).json();return u.success?(o({message:"文件已添加到暂存区",type:"success"}),b(),!0):(o({message:`添加文件失败: ${u.error}`,type:"error"}),!1)}catch(m){return o({message:`添加文件失败: ${m.message}`,type:"error"}),!1}finally{U.value=!1}}function E(m){return new Promise(u=>setTimeout(u,m))}async function I(m,u=!1){if(!F.isGitRepo)return o.warning("当前目录不是Git仓库"),!1;try{q.value=!0;const v=await(await fetch("/api/commit",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({message:m,hasNewlines:m.includes(`
|
|
3
|
-
`),noVerify:u})})).json();return v.success?(o({message:"提交成功",type:"success"}),b(),j(),!0):(o({message:`提交失败: ${v.error}`,type:"error"}),!1)}catch(A){return o({message:`提交失败: ${A.message}`,type:"error"}),!1}finally{q.value=!1}}async function f(){if(!F.isGitRepo)return o.warning("当前目录不是Git仓库"),!1;try{R.value=!0;const u=await(await fetch("/api/push",{method:"POST"})).json();return u.success?(o({message:"推送成功",type:"success"}),b(),j(),!0):(o({message:`推送失败: ${u.error}`,type:"error"}),!1)}catch(m){return o({message:`推送失败: ${m.message}`,type:"error"}),!1}finally{R.value=!1}}async function g(m,u=!1){return await C()?(await E(Le),await I(m,u)):!1}async function M(m,u=!1){try{return!await C()||(await E(Le),!await I(m,u))?!1:(await E(Le),await f())}catch(A){try{(await(await fetch("/api/remove-lock",{method:"POST"})).json()).success&&o({message:"已清理锁定文件,请重试操作",type:"warning"})}catch(v){console.error("清理锁定文件失败:",v)}return o({message:`操作失败: ${A.message}`,type:"error"}),!1}}async function $(){if(!F.isGitRepo)return o.warning("当前目录不是Git仓库"),!1;try{T.value=!0;const u=await(await fetch("/api/reset-head",{method:"POST"})).json();return u.success?(o({message:"已重置暂存区",type:"success"}),b(),!0):(o({message:`重置暂存区失败: ${u.error}`,type:"error"}),!1)}catch(m){return o({message:`重置暂存区失败: ${m.message}`,type:"error"}),!1}finally{T.value=!1}}async function l(m){if(!F.isGitRepo)return o.warning("当前目录不是Git仓库"),!1;try{T.value=!0;const A=await(await fetch("/api/reset-to-remote",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({branch:m})})).json();return A.success?(o({message:`已重置分支 ${m} 到远程状态`,type:"success"}),b(),j(),!0):(o({message:`重置分支失败: ${A.error}`,type:"error"}),!1)}catch(u){return o({message:`重置分支失败: ${u.message}`,type:"error"}),!1}finally{T.value=!1}}return{log:h,status:G,statusText:y,fileList:a,isLoadingLog:x,isLoadingStatus:L,isAddingFiles:U,isResetting:T,isCommiting:q,isPushing:R,fetchLog:j,fetchStatus:b,fetchStatusPorcelain:W,parseStatusPorcelain:D,addToStage:C,commitChanges:I,pushToRemote:f,addAndCommit:g,addCommitAndPush:M,resetHead:$,resetToRemote:l}}),kt={class:"card"},St={class:"current-directory"},Tt={class:"status-header"},Vt={class:"status-box"},Gt={key:0,class:"file-list"},Lt=["onClick"],xt={class:"file-type"},Bt={class:"file-path"},Dt={class:"file-actions"},jt={class:"directory-buttons"},Rt={class:"browser-current-path"},zt={key:0,class:"browser-error"},Et={class:"directory-browser"},At={class:"browser-nav"},Ot={class:"directory-items-container"},Pt={class:"directory-items"},Ut=["onClick"],Nt={class:"diff-content"},Mt=["innerHTML"],It={key:1,class:"no-diff"},Ft={class:"file-navigation"},Jt={class:"file-counter"},Ht=we({__name:"GitStatus",props:{initialDirectory:{type:String,default:""}},setup(F,{expose:h}){const G=F,y=Ee(),a=ie(),x=he(()=>y.isLoadingStatus),L=i(""),U=i(""),q=i(!1),R=i(!1),T=i(-1),D=i(!1),j=i(""),b=i(!1),W=i(!1),C=i(""),E=i([]),I=i(!1),f=i(""),g=i(G.initialDirectory||"");async function M(){try{if(!g.value){const d=await(await fetch("/api/current_directory")).json();g.value=d.directory||"未知目录"}if(!a.isGitRepo)return;await y.fetchStatus(),o({message:"Git 状态已刷新",type:"success"})}catch(k){o({message:"刷新失败: "+k.message,type:"error"})}}function $(k){if(!k)return"";const d=k.split(`
|
|
4
|
-
`);function Z(O){return O.replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,""").replace(/'/g,"'")}return d.map(O=>{const Q=Z(O);return O.startsWith("diff --git")?`<div class="diff-header">${Q}</div>`:O.startsWith("---")?`<div class="diff-old-file">${Q}</div>`:O.startsWith("+++")?`<div class="diff-new-file">${Q}</div>`:O.startsWith("@@")?`<div class="diff-hunk-header">${Q}</div>`:O.startsWith("+")?`<div class="diff-added">${Q}</div>`:O.startsWith("-")?`<div class="diff-removed">${Q}</div>`:`<div class="diff-context">${Q}</div>`}).join("")}async function l(k){try{R.value=!0,L.value=k,T.value=y.fileList.findIndex(O=>O.path===k);const Z=await(await fetch(`/api/diff?file=${encodeURIComponent(k)}`)).json();U.value=Z.diff||"没有变更",q.value=!0}catch(d){o({message:"获取文件差异失败: "+d.message,type:"error"}),U.value="获取差异失败: "+d.message}finally{R.value=!1}}async function m(){if(y.fileList.length===0||T.value<=0)return;const k=T.value-1,d=y.fileList[k];await l(d.path)}async function u(){if(y.fileList.length===0||T.value>=y.fileList.length-1)return;const k=T.value+1,d=y.fileList[k];await l(d.path)}function A(){j.value=g.value,D.value=!0}function v(){f.value="",C.value=j.value||g.value,W.value=!0,_(C.value)}async function _(k){try{I.value=!0,f.value="";let d=k;/^[A-Za-z]:$/.test(d)&&(d+="/");const Z=await fetch(`/api/browse_directory?path=${encodeURIComponent(d)}`);if(Z.status===403){const Q=await Z.json();f.value=Q.error||"目录浏览功能未启用";return}if(!Z.ok){const Q=await Z.json();f.value=Q.error||"获取目录内容失败";return}const O=await Z.json();O.success?(E.value=O.items,C.value=O.currentPath):f.value=O.error||"获取目录内容失败"}catch(d){f.value=`获取目录内容失败: ${d.message}`}finally{I.value=!1}}function z(){if(/^[A-Za-z]:$/.test(C.value)||/^[A-Za-z]:[\\/]$/.test(C.value)||C.value==="/")return;let k=C.value.split(/[/\\]/);k.pop();let d=k.join("/");k.length===1&&/^[A-Za-z]:$/.test(k[0])&&(d=k[0]+"/"),d&&_(d)}function B(k){k.type==="directory"&&_(k.path)}function J(){j.value=C.value,W.value=!1}async function K(){if(!j.value){o.warning("目录路径不能为空");return}try{b.value=!0;const d=await(await fetch("/api/change_directory",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({path:j.value})})).json();d.success?(o.success("已切换工作目录"),g.value=d.directory,D.value=!1,a.isGitRepo=d.isGitRepo,d.isGitRepo?(await Promise.all([a.getCurrentBranch(),a.getAllBranches(),a.getUserInfo()]),await M()):(o.warning("当前目录不是一个Git仓库"),a.$reset())):o.error(d.error||"切换目录失败")}catch(k){o.error(`切换目录失败: ${k.message}`)}finally{b.value=!1}}function ae(k){l(k.path)}function N(k){switch(k){case"added":return"新增";case"modified":return"修改";case"deleted":return"删除";case"untracked":return"未跟踪";default:return"其他"}}async function me(){await M()}async function Ce(k){try{await qe.confirm(`确定要撤回文件 "${k}" 的所有修改吗?此操作无法撤销。`,"撤回修改",{confirmButtonText:"确定",cancelButtonText:"取消",type:"warning"});const Z=await(await fetch("/api/revert_file",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({filePath:k})})).json();Z.success?(o.success("已撤回文件修改"),await M()):o.error(Z.error||"撤回文件修改失败")}catch(d){d.message!=="cancel"&&o.error(`撤回文件修改失败: ${d.message}`)}}return be(()=>{M()}),h({refreshStatus:me}),(k,d)=>{const Z=Ie,O=le,Q=Ze,ke=ze,Se=Je,Te=Fe,re=Re,ve=He;return p(),w("div",kt,[e("div",St,[s(Z,null,{default:n(()=>[s(r(Ge))]),_:1}),e("span",null,P(g.value),1),s(O,{type:"primary",size:"small",onClick:A,plain:""},{default:n(()=>d[4]||(d[4]=[V(" 切换目录 ")])),_:1})]),e("div",Tt,[d[5]||(d[5]=e("h2",null,"Git 状态(git status)",-1)),s(O,{type:"primary",icon:r(nt),circle:"",size:"small",onClick:me,loading:x.value},null,8,["icon","loading"])]),e("div",Vt,P(r(a).isGitRepo?r(y).statusText||"加载中...":"当前目录不是一个Git仓库"),1),r(y).fileList.length?(p(),w("div",Gt,[(p(!0),w(se,null,oe(r(y).fileList,H=>(p(),w("div",{key:H.path,class:De(["file-item",H.type])},[e("div",{class:"file-info",onClick:ge=>ae(H)},[e("span",xt,P(N(H.type)),1),e("span",Bt,P(H.path),1)],8,Lt),e("div",Dt,[s(Q,{content:"撤回修改",placement:"top","hide-after":1e3},{default:n(()=>[s(O,{type:"danger",size:"small",icon:r(We),circle:"",onClick:dt(ge=>Ce(H.path),["stop"])},null,8,["icon","onClick"])]),_:2},1024)])],2))),128))])):te("",!0),s(re,{modelValue:D.value,"onUpdate:modelValue":d[1]||(d[1]=H=>D.value=H),title:"切换工作目录",width:"500px"},{default:n(()=>[s(Te,null,{default:n(()=>[s(Se,{label:"目录路径"},{default:n(()=>[s(ke,{modelValue:j.value,"onUpdate:modelValue":d[0]||(d[0]=H=>j.value=H),placeholder:"请输入目录路径",clearable:""},null,8,["modelValue"]),e("div",jt,[s(O,{onClick:v,type:"primary",plain:"",class:"no-padding-left"},{default:n(()=>[s(Z,null,{default:n(()=>[s(r(Ge))]),_:1}),d[6]||(d[6]=V(" 浏览 "))]),_:1}),s(O,{onClick:K,loading:b.value,type:"primary"},{default:n(()=>d[7]||(d[7]=[V(" 切换 ")])),_:1},8,["loading"])])]),_:1})]),_:1})]),_:1},8,["modelValue"]),s(re,{modelValue:W.value,"onUpdate:modelValue":d[2]||(d[2]=H=>W.value=H),title:"浏览目录",width:"600px"},{default:n(()=>[e("div",Rt,[e("span",null,"当前路径: "+P(C.value),1)]),f.value?(p(),w("div",zt,P(f.value),1)):te("",!0),Be((p(),w("div",Et,[e("div",At,[s(O,{onClick:z,disabled:!C.value||I.value,size:"small",class:"no-padding-left"},{default:n(()=>[s(Z,null,{default:n(()=>[s(r(it))]),_:1}),d[8]||(d[8]=V(" 上级目录 "))]),_:1},8,["disabled"]),s(O,{onClick:J,type:"primary",size:"small",class:"no-padding-left"},{default:n(()=>d[9]||(d[9]=[V(" 选择当前目录 ")])),_:1})]),e("div",Ot,[e("ul",Pt,[(p(!0),w(se,null,oe(E.value,H=>(p(),w("li",{key:H.path,class:De(["directory-item",H.type]),onClick:ge=>B(H)},[H.type==="directory"?(p(),ee(Z,{key:0},{default:n(()=>[s(r(Ge))]),_:1})):(p(),ee(Z,{key:1},{default:n(()=>[s(r(rt))]),_:1})),e("span",null,P(H.name),1)],10,Ut))),128))])])])),[[ve,I.value]])]),_:1},8,["modelValue"]),s(re,{modelValue:q.value,"onUpdate:modelValue":d[3]||(d[3]=H=>q.value=H),title:`文件差异: ${L.value}`,width:"80%","destroy-on-close":""},{default:n(()=>[Be((p(),w("div",Nt,[U.value?(p(),w("div",{key:0,innerHTML:$(U.value),class:"diff-formatted"},null,8,Mt)):(p(),w("div",It,"该文件没有差异或是新文件"))])),[[ve,R.value]]),e("div",Ft,[s(O,{icon:r(ct),onClick:m,disabled:T.value<=0||r(y).fileList.length===0,circle:""},null,8,["icon","disabled"]),e("span",Jt,P(T.value+1)+" / "+P(r(y).fileList.length),1),s(O,{icon:r(ut),onClick:u,disabled:T.value>=r(y).fileList.length-1||r(y).fileList.length===0,circle:""},null,8,["icon","disabled"])])]),_:1},8,["modelValue","title"])])}}}),$e=(F,h)=>{const G=F.__vccOpts||F;for(const[y,a]of h)G[y]=a;return G},Wt=$e(Ht,[["__scopeId","data-v-bcbbf547"]]),Zt={class:"card"},qt={class:"layout-container"},Yt={key:0,class:"git-config-warning"},Kt={class:"commit-section"},Qt={class:"commit-options"},Xt={class:"options-row"},es={class:"commit-mode-toggle"},ts={class:"no-verify-toggle"},ss={key:0,class:"commit-form"},as={key:1,class:"standard-commit-form"},ls={class:"standard-commit-header"},os={class:"scope-container"},ns={class:"description-container"},is={class:"preview-section"},rs={class:"preview-content"},cs={class:"preview-content code-command"},us={class:"actions-section"},ds={class:"action-groups"},ps={class:"action-group"},fs={class:"group-buttons"},ms={class:"action-group"},vs={class:"group-buttons"},gs={class:"action-group"},ys={class:"group-buttons"},hs={class:"template-container"},_s={class:"template-form"},ws={class:"template-form-buttons"},bs={class:"template-list"},$s={class:"template-content"},Cs={class:"template-actions"},ks={class:"template-container"},Ss={class:"template-form"},Ts={class:"template-form-buttons"},Vs={class:"template-list"},Gs={class:"template-content"},Ls={class:"template-actions"},xs=we({__name:"CommitForm",setup(F){const h=Ee(),G=ie(),y=i(""),a=i(!1),x=i("输入提交信息..."),L=i(""),U=i(!1),q=i("feat"),R=i(""),T=i(""),D=i(""),j=i(""),b=i([]),W=i(!1),C=i(""),E=i(!1),I=i(""),f=i(-1),g=i([]),M=i(!1),$=i(""),l=i(!1),m=i(""),u=i(-1),A=i(!1),v=[{value:"feat",label:"feat: 新功能"},{value:"fix",label:"fix: 修复bug"},{value:"docs",label:"docs: 文档修改"},{value:"style",label:"style: 样式修改"},{value:"refactor",label:"refactor: 代码重构"},{value:"test",label:"test: 测试代码"},{value:"chore",label:"chore: 构建/工具修改"}];je(U,c=>{localStorage.setItem("zen-gitsync-standard-commit",c.toString())}),je(A,c=>{localStorage.setItem("zen-gitsync-skip-hooks",c.toString())});const _=he(()=>{if(!U.value)return y.value||L.value;let c=`${q.value||""}`;return R.value&&(c+=`(${R.value})`),c+=`: ${T.value}`,D.value&&(c+=`
|
|
5
|
-
|
|
6
|
-
${D.value}`),j.value&&(c+=`
|
|
7
|
-
|
|
8
|
-
${j.value}`),c}),z=he(()=>{let c=`git commit -m "${_.value}"`;return A.value&&(c+=" --no-verify"),c});async function B(){try{const t=await(await fetch("/api/config/getConfig")).json();x.value=`输入提交信息 (默认: ${t.defaultCommitMessage})`,L.value=t.defaultCommitMessage||"",t.descriptionTemplates&&Array.isArray(t.descriptionTemplates)&&(b.value=t.descriptionTemplates),t.scopeTemplates&&Array.isArray(t.scopeTemplates)&&(g.value=t.scopeTemplates)}catch(c){console.error("加载配置失败:",c)}}async function J(){if(!C.value.trim()){o({message:"请输入模板内容",type:"warning"});return}try{if(E.value)await K();else{if(b.value.includes(C.value)){o({message:"该模板已存在",type:"warning"});return}b.value.push(C.value);const t=await(await fetch("/api/config/save-template",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({template:C.value,type:"description"})})).json();t.success?(o({message:"模板保存成功!",type:"success"}),C.value=""):o({message:"模板保存失败: "+t.error,type:"error"})}}catch(c){o({message:"模板保存失败: "+c.message,type:"error"})}}async function K(){try{if(f.value>=0){const c=I.value,t=C.value;b.value[f.value]=t;const X=await(await fetch("/api/config/update-template",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({oldTemplate:c,newTemplate:t,type:"description"})})).json();X.success?(o({message:"模板更新成功!",type:"success"}),E.value=!1,I.value="",f.value=-1,C.value=""):o({message:"模板更新失败: "+X.error,type:"error"})}}catch(c){o({message:"模板更新失败: "+c.message,type:"error"})}}function ae(c,t){E.value=!0,I.value=c,f.value=t,C.value=c}function N(){E.value=!1,I.value="",f.value=-1,C.value=""}async function me(){if(!$.value.trim()){o({message:"请输入模板内容",type:"warning"});return}try{if(l.value)await Ce();else{if(g.value.includes($.value)){o({message:"该模板已存在",type:"warning"});return}g.value.push($.value);const t=await(await fetch("/api/config/save-template",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({template:$.value,type:"scope"})})).json();t.success?(o({message:"作用域模板保存成功!",type:"success"}),$.value=""):o({message:"作用域模板保存失败: "+t.error,type:"error"})}}catch(c){o({message:"作用域模板保存失败: "+c.message,type:"error"})}}async function Ce(){try{if(u.value>=0){const c=m.value,t=$.value;g.value[u.value]=t;const X=await(await fetch("/api/config/update-template",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({oldTemplate:c,newTemplate:t,type:"scope"})})).json();X.success?(o({message:"作用域模板更新成功!",type:"success"}),l.value=!1,m.value="",u.value=-1,$.value=""):o({message:"作用域模板更新失败: "+X.error,type:"error"})}}catch(c){o({message:"作用域模板更新失败: "+c.message,type:"error"})}}function k(c,t){l.value=!0,m.value=c,u.value=t,$.value=c}function d(){l.value=!1,m.value="",u.value=-1,$.value=""}async function Z(c){try{const t=b.value.indexOf(c);t!==-1&&b.value.splice(t,1);const X=await(await fetch("/api/config/delete-template",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({template:c,type:"description"})})).json();X.success?o({message:"模板删除成功!",type:"success"}):o({message:"模板删除失败: "+X.error,type:"error"})}catch(t){o({message:"模板删除失败: "+t.message,type:"error"})}}async function O(c){try{const t=g.value.indexOf(c);t!==-1&&g.value.splice(t,1);const X=await(await fetch("/api/config/delete-template",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({template:c,type:"scope"})})).json();X.success?o({message:"作用域模板删除成功!",type:"success"}):o({message:"作用域模板删除失败: "+X.error,type:"error"})}catch(t){o({message:"作用域模板删除失败: "+t.message,type:"error"})}}function Q(c){T.value=c,W.value=!1}function ke(c){R.value=c,M.value=!1}function Se(){W.value=!0}function Te(){M.value=!0}async function re(){try{await h.addToStage()&&h.fetchStatus()}catch(c){o({message:`添加文件失败: ${c.message}`,type:"error"})}}async function ve(){if(!_.value.trim()){o({message:"提交信息不能为空",type:"warning"});return}try{await h.commitChanges(_.value,A.value)&&(Ve(),h.fetchStatus(),h.fetchLog())}catch(c){o({message:`提交失败: ${c.message}`,type:"error"})}}async function H(){try{a.value=!0,await h.pushToRemote()&&(G.getCurrentBranch(),h.fetchLog())}catch(c){o({message:`推送失败: ${c.message}`,type:"error"})}finally{a.value=!1}}async function ge(){if(!_.value.trim()){o({message:"提交信息不能为空",type:"warning"});return}try{await h.addAndCommit(_.value,A.value),Ve(),h.fetchStatus(),h.fetchLog()}catch(c){o({message:`暂存并提交失败: ${c.message}`,type:"error"})}}async function tt(){if(!_.value.trim()){o({message:"提交信息不能为空",type:"warning"});return}try{await h.addCommitAndPush(_.value,A.value),Ve(),G.getCurrentBranch(),h.fetchLog()}catch(c){o({message:`暂存、提交并推送失败: ${c.message}`,type:"error"})}finally{}}async function st(){try{await qe.confirm(`确定要重置当前分支 "${G.currentBranch}" 到远程状态吗?这将丢失所有未推送的提交和本地更改。`,"重置到远程分支",{confirmButtonText:"确定",cancelButtonText:"取消",type:"warning"}),await h.resetToRemote(G.currentBranch)&&(h.fetchStatus(),h.fetchLog())}catch(c){c!=="cancel"&&o({message:`重置到远程分支失败: ${c.message}`,type:"error"})}}function Ve(){y.value="",T.value="",D.value="",j.value=""}return be(()=>{B();const c=localStorage.getItem("zen-gitsync-standard-commit");c!==null&&(U.value=c==="true");const t=localStorage.getItem("zen-gitsync-skip-hooks");t!==null&&(A.value=t==="true")}),(c,t)=>{const ce=Ye,X=pt,at=Ze,ne=ze,lt=Qe,ot=Ke,Y=le,Ae=ft,Oe=mt,Pe=Xe,Ue=Re;return p(),w("div",Zt,[t[35]||(t[35]=e("h2",null,"提交更改",-1)),e("div",qt,[r(G).userName===""||r(G).userEmail===""?(p(),w("div",Yt,[s(ce,{title:"Git用户信息未配置",type:"warning",closable:!1,"show-icon":""},{default:n(()=>t[12]||(t[12]=[e("p",null,"您需要配置Git用户名和邮箱才能提交代码。请使用以下命令配置:",-1),e("pre",{class:"config-command"},`git config --global user.name "Your Name"
|
|
9
|
-
git config --global user.email "your.email@example.com"`,-1)])),_:1})])):(p(),w(se,{key:1},[e("div",Kt,[e("div",Qt,[e("div",Xt,[e("div",es,[s(X,{modelValue:U.value,"onUpdate:modelValue":t[0]||(t[0]=S=>U.value=S),"active-text":"标准化提交","inactive-text":"普通提交"},null,8,["modelValue"])]),e("div",ts,[s(at,{content:"跳过 Git 钩子检查 (--no-verify)",placement:"top"},{default:n(()=>[s(X,{modelValue:A.value,"onUpdate:modelValue":t[1]||(t[1]=S=>A.value=S),"active-text":"跳过钩子 (--no-verify)"},null,8,["modelValue"])]),_:1})])])]),U.value?(p(),w("div",as,[e("div",ls,[s(ot,{modelValue:q.value,"onUpdate:modelValue":t[3]||(t[3]=S=>q.value=S),placeholder:"提交类型",class:"type-select",clearable:""},{default:n(()=>[(p(),w(se,null,oe(v,S=>s(lt,{key:S.value,label:S.label,value:S.value},null,8,["label","value"])),64))]),_:1},8,["modelValue"]),e("div",os,[s(ne,{modelValue:R.value,"onUpdate:modelValue":t[4]||(t[4]=S=>R.value=S),placeholder:"作用域(可选)",class:"scope-input",clearable:""},null,8,["modelValue"]),s(Y,{type:"primary",icon:r(_e),circle:"",size:"small",class:"settings-button",onClick:Te},null,8,["icon"])]),e("div",ns,[s(ne,{modelValue:T.value,"onUpdate:modelValue":t[5]||(t[5]=S=>T.value=S),placeholder:"简短描述(必填)",class:"description-input",clearable:""},null,8,["modelValue"]),s(Y,{type:"primary",icon:r(_e),circle:"",size:"small",class:"settings-button",onClick:Se},null,8,["icon"])])]),s(ne,{modelValue:D.value,"onUpdate:modelValue":t[6]||(t[6]=S=>D.value=S),type:"textarea",rows:4,placeholder:"正文(可选):详细描述本次提交的内容和原因",class:"body-input",clearable:""},null,8,["modelValue"]),s(ne,{modelValue:j.value,"onUpdate:modelValue":t[7]||(t[7]=S=>j.value=S),placeholder:"页脚(可选):如 Closes #123",class:"footer-input",clearable:""},null,8,["modelValue"]),e("div",is,[t[13]||(t[13]=e("div",{class:"preview-title"},"提交信息预览:",-1)),e("pre",rs,P(_.value),1),t[14]||(t[14]=e("div",{class:"preview-title",style:{"margin-top":"10px"}},"Git命令预览:",-1)),e("pre",cs,P(z.value),1)])])):(p(),w("div",ss,[s(ne,{modelValue:y.value,"onUpdate:modelValue":t[2]||(t[2]=S=>y.value=S),placeholder:x.value,clearable:""},null,8,["modelValue","placeholder"])]))]),e("div",us,[t[24]||(t[24]=e("h3",null,"Git 操作",-1)),e("div",ds,[e("div",ps,[t[18]||(t[18]=e("div",{class:"group-title"},"基础操作",-1)),e("div",fs,[s(Y,{type:"primary",onClick:re,loading:r(h).isAddingFiles,class:"action-button"},{default:n(()=>t[15]||(t[15]=[V(" 暂存更改 "),e("span",{class:"command-text"},"git add .",-1)])),_:1},8,["loading"]),s(Y,{type:"primary",onClick:ve,loading:r(h).isLoadingStatus,class:"action-button"},{default:n(()=>t[16]||(t[16]=[V(" 提交 "),e("span",{class:"command-text"},"git commit",-1)])),_:1},8,["loading"]),s(Y,{type:"success",onClick:H,loading:r(h).isPushing,class:"action-button push-button"},{default:n(()=>t[17]||(t[17]=[V(" 推送 "),e("span",{class:"command-text"},"git push",-1)])),_:1},8,["loading"])])]),e("div",ms,[t[21]||(t[21]=e("div",{class:"group-title"},"组合操作",-1)),e("div",vs,[s(Y,{type:"warning",onClick:ge,loading:r(h).isAddingFiles||r(h).isCommiting,class:"action-button"},{default:n(()=>t[19]||(t[19]=[V(" 暂存并提交 "),e("span",{class:"command-text"},"git add + commit",-1)])),_:1},8,["loading"]),s(Y,{type:"danger",onClick:tt,loading:r(h).isAddingFiles||r(h).isCommiting||r(h).isPushing,class:"action-button"},{default:n(()=>t[20]||(t[20]=[V(" 一键推送 "),e("span",{class:"command-text command-text-long"},"git add + commit + push",-1)])),_:1},8,["loading"])])]),e("div",gs,[t[23]||(t[23]=e("div",{class:"group-title"},"重置操作",-1)),e("div",ys,[s(Y,{type:"info",onClick:st,loading:r(h).isResetting,class:"action-button reset-button"},{default:n(()=>t[22]||(t[22]=[V(" 重置到远程 "),e("span",{class:"command-text command-text-long"},"git reset --hard origin/branch",-1)])),_:1},8,["loading"])])])])])],64))]),s(Ue,{title:"简短描述模板设置",modelValue:W.value,"onUpdate:modelValue":t[9]||(t[9]=S=>W.value=S),width:"80vw",style:{height:"80vh"}},{default:n(()=>[e("div",hs,[e("div",_s,[s(ne,{modelValue:C.value,"onUpdate:modelValue":t[8]||(t[8]=S=>C.value=S),placeholder:E.value?"编辑模板内容":"输入新模板内容",class:"template-input",clearable:""},null,8,["modelValue","placeholder"]),e("div",ws,[E.value?(p(),ee(Y,{key:0,onClick:N},{default:n(()=>t[25]||(t[25]=[V("取消")])),_:1})):te("",!0),s(Y,{type:"primary",onClick:J,disabled:!C.value.trim()},{default:n(()=>[V(P(E.value?"更新模板":"添加模板"),1)]),_:1},8,["disabled"])])]),e("div",bs,[t[29]||(t[29]=e("h3",null,"已保存模板",-1)),b.value.length===0?(p(),ee(Ae,{key:0,description:"暂无保存的模板"})):te("",!0),(p(!0),w(se,null,oe(b.value,(S,ue)=>(p(),ee(Pe,{key:ue,class:"template-item"},{default:n(()=>[s(Oe,{justify:"space-between",align:"middle",style:{width:"100%"}},{default:n(()=>[e("div",$s,P(S),1),e("div",Cs,[s(Y,{type:"primary",size:"small",onClick:de=>Q(S)},{default:n(()=>t[26]||(t[26]=[V("使用")])),_:2},1032,["onClick"]),s(Y,{type:"warning",size:"small",icon:r(Ne),onClick:de=>ae(S,ue)},{default:n(()=>t[27]||(t[27]=[V("编辑")])),_:2},1032,["icon","onClick"]),s(Y,{type:"danger",size:"small",onClick:de=>Z(S)},{default:n(()=>t[28]||(t[28]=[V("删除")])),_:2},1032,["onClick"])])]),_:2},1024)]),_:2},1024))),128))])])]),_:1},8,["modelValue"]),s(Ue,{title:"作用域模板设置",modelValue:M.value,"onUpdate:modelValue":t[11]||(t[11]=S=>M.value=S),width:"80%",style:{height:"80vh"}},{default:n(()=>[e("div",ks,[e("div",Ss,[s(ne,{modelValue:$.value,"onUpdate:modelValue":t[10]||(t[10]=S=>$.value=S),placeholder:l.value?"编辑作用域模板内容":"输入新作用域模板",class:"template-input",clearable:""},null,8,["modelValue","placeholder"]),e("div",Ts,[l.value?(p(),ee(Y,{key:0,onClick:d},{default:n(()=>t[30]||(t[30]=[V("取消")])),_:1})):te("",!0),s(Y,{type:"primary",onClick:me,disabled:!$.value.trim()},{default:n(()=>[V(P(l.value?"更新模板":"添加模板"),1)]),_:1},8,["disabled"])])]),e("div",Vs,[t[34]||(t[34]=e("h3",null,"已保存作用域",-1)),g.value.length===0?(p(),ee(Ae,{key:0,description:"暂无保存的作用域"})):te("",!0),(p(!0),w(se,null,oe(g.value,(S,ue)=>(p(),ee(Pe,{key:ue,class:"template-item"},{default:n(()=>[s(Oe,{justify:"space-between",align:"middle",style:{width:"100%"}},{default:n(()=>[e("div",Gs,P(S),1),e("div",Ls,[s(Y,{type:"primary",size:"small",onClick:de=>ke(S)},{default:n(()=>t[31]||(t[31]=[V("使用")])),_:2},1032,["onClick"]),s(Y,{type:"warning",size:"small",icon:r(Ne),onClick:de=>k(S,ue)},{default:n(()=>t[32]||(t[32]=[V("编辑")])),_:2},1032,["icon","onClick"]),s(Y,{type:"danger",size:"small",onClick:de=>O(S)},{default:n(()=>t[33]||(t[33]=[V("删除")])),_:2},1032,["onClick"])])]),_:2},1024)]),_:2},1024))),128))])])]),_:1},8,["modelValue"])])}}}),Bs=$e(xs,[["__scopeId","data-v-8d105fc1"]]),Ds={class:"card"},js={class:"log-header"},Rs={class:"log-actions"},zs={key:0},Es={key:1},As={key:0,class:"refresh-notification"},Os={key:1,class:"graph-view"},Ps={key:0,class:"commit-count"},Us={class:"graph-controls"},Ns={class:"zoom-controls"},Ms={class:"scale-info"},Is={key:2},Fs={key:0,class:"commit-count"},Js={key:0,class:"branch-container"},fe=.5,ye=1.5,xe=.1,Hs=we({__name:"LogList",setup(F,{expose:h}){const G=Ee(),y=ie();let a=[];const x=i(a),L=i(""),U=i(!1),q=he(()=>G.isLoadingLog||U.value),R=i(!1),T=i(0),D=i(!0),j=i(null),b=i(1),W=i(!1);async function C(v=!1){if(!ie().isGitRepo){L.value="当前目录不是Git仓库";return}try{R.value=v,U.value=!0;const z=v?"/api/log?all=true&graph=true":"/api/log?graph=true";console.log(`加载日志数据: ${z}`);const J=await(await fetch(z)).json();if(a.length=0,Array.isArray(J))console.log(`日志加载完成: 共${J.length}条记录`),J.forEach(K=>a.push(K)),T.value=J.length;else if(J.log&&Array.isArray(J.log))console.log(`日志加载完成: 共${J.log.length}条记录`),J.log.forEach(K=>a.push(K)),T.value=J.log.length;else{console.error("未知的日志数据格式:",J),L.value="日志数据格式错误";return}x.value=[...a],console.log(`logsData长度: ${a.length}`),W.value=!0,setTimeout(()=>{W.value=!1},2e3),D.value&&setTimeout(E,0),L.value=""}catch(z){L.value="加载提交历史失败: "+(z instanceof Error?z.message:String(z)),console.error("加载日志失败:",z)}finally{U.value=!1}}async function E(){if(console.log(`开始渲染图表...数据长度: ${a.length}`),!j.value){console.error("图表容器未找到");return}if(a.length===0){console.error("没有日志数据可渲染");return}try{j.value.innerHTML="",console.log(`创建gitgraph实例,分支: ${y.currentBranch||"main"}`);const v=wt(j.value,{orientation:"vertical-reverse",template:"metro",author:"提交者 <committer@example.com>"}),_={},z=v.branch(y.currentBranch||"main");_[y.currentBranch||"main"]=z,console.log(`开始创建提交图...共${a.length}条提交`),a.forEach((B,J)=>{let K=z;if(B.branch){const ae=g(B.branch.split(",")[0]);_[ae]||(_[ae]=v.branch(ae)),K=_[ae]}K.commit({hash:B.hash,subject:B.message,author:`${B.author} <${B.email}>`}),J%10===0&&console.log(`已渲染 ${J+1}/${a.length} 个提交`)}),console.log("图表渲染完成"),setTimeout(()=>{A()},100)}catch(v){console.error("渲染图表失败:",v),L.value="渲染图表失败: "+(v instanceof Error?v.message:String(v))}}function I(){D.value=!D.value,D.value&&a.length>0&&setTimeout(E,0)}function f(){C(!R.value)}function g(v){return v.includes("HEAD -> ")?v.replace("HEAD -> ",""):v.includes("origin/")?v:v.trim()}function M(v){return v.includes("HEAD")?"success":v.includes("origin/")?"warning":"info"}be(()=>{y.isGitRepo?G.log.length>0?(console.log("使用已加载的日志数据"),a.length=0,G.log.forEach(v=>a.push(v)),T.value=G.log.length,D.value&&setTimeout(()=>{console.log(`准备渲染图表,数据长度: ${a.length}`),E()},100)):(console.log("初始加载日志数据"),C()):L.value="当前目录不是Git仓库"});const $=()=>{if(!y.isGitRepo){L.value="当前目录不是Git仓库";return}C(R.value)};je(()=>G.log,v=>{console.log("监听到gitLogStore.log变化,更新图表数据"),a.length=0,v.forEach(_=>a.push(_)),T.value=v.length;try{x.value=[...a]}catch(_){console.warn("无法更新logs.value:",_)}console.log(`数据更新完成,准备渲染图表(${a.length}条记录)`),D.value&&a.length>0&&setTimeout(E,0)}),h({refreshLog:$});function l(){b.value<ye&&(b.value=Math.min(ye,b.value+xe),u())}function m(){b.value>fe&&(b.value=Math.max(fe,b.value-xe),u())}function u(){if(!j.value)return;const v=j.value.querySelector("svg");v&&(v.style.transform=`scale(${b.value})`,v.style.transformOrigin="top left")}function A(){if(!j.value)return;const v=j.value.querySelector("svg");if(!v)return;const _=v.getBoundingClientRect().width/b.value,z=j.value.clientWidth;_>z?b.value=Math.max(fe,z/_):b.value=1,u()}return(v,_)=>{const z=He;return p(),w("div",Ds,[e("div",js,[_[2]||(_[2]=e("h2",null,"提交历史",-1)),e("div",Rs,[s(r(le),{type:"primary",size:"small",onClick:I},{default:n(()=>[V(P(D.value?"表格视图":"图表视图"),1)]),_:1}),s(r(le),{type:"primary",size:"small",onClick:f,loading:q.value},{default:n(()=>[V(P(R.value?"显示最近30条":"显示所有提交"),1)]),_:1},8,["loading"]),s(r(le),{icon:r(We),circle:"",size:"small",onClick:_[0]||(_[0]=B=>$()),loading:q.value,class:De({"refresh-button-animated":W.value})},null,8,["icon","loading","class"])])]),L.value?(p(),w("div",zs,P(L.value),1)):(p(),w("div",Es,[W.value?(p(),w("div",As," 提交历史已刷新 ")):te("",!0),D.value?(p(),w("div",Os,[r(a).length>0?(p(),w("div",Ps," 显示 "+P(r(a).length)+" 条提交记录 "+P(R.value?"(全部)":"(最近30条)"),1)):te("",!0),e("div",Us,[e("div",Ns,[s(r(le),{type:"primary",icon:r(vt),circle:"",size:"small",onClick:m,disabled:b.value<=fe},null,8,["icon","disabled"]),s(r(gt),{modelValue:b.value,"onUpdate:modelValue":_[1]||(_[1]=B=>b.value=B),min:fe,max:ye,step:xe,onChange:u,class:"zoom-slider"},null,8,["modelValue"]),s(r(le),{type:"primary",icon:r(yt),circle:"",size:"small",onClick:l,disabled:b.value>=ye},null,8,["icon","disabled"]),s(r(le),{type:"primary",size:"small",onClick:A},{default:n(()=>_[3]||(_[3]=[V(" 自适应大小 ")])),_:1})]),e("div",Ms," 缩放: "+P(Math.round(b.value*100))+"% ",1)]),e("div",{ref_key:"graphContainer",ref:j,class:"graph-container"},null,512)])):(p(),w("div",Is,[x.value.length>0?(p(),w("div",Fs," 显示 "+P(x.value.length)+" 条提交记录 "+P(R.value?"(全部)":"(最近30条)"),1)):te("",!0),Be((p(),ee(r(_t),{data:x.value,style:{width:"100%"},stripe:"",border:""},{default:n(()=>[s(r(pe),{prop:"hash",label:"提交哈希",width:"100",resizable:""}),s(r(pe),{prop:"date",label:"日期",width:"180",resizable:""}),s(r(pe),{label:"作者",width:"200",resizable:""},{default:n(B=>[V(P(B.row.author)+" <"+P(B.row.email)+"> ",1)]),_:1}),s(r(pe),{label:"分支",width:"180",resizable:""},{default:n(B=>[B.row.branch?(p(),w("div",Js,[(p(!0),w(se,null,oe(B.row.branch.split(","),(J,K)=>(p(),ee(r(ht),{key:K,size:"small",type:M(J),class:"branch-tag"},{default:n(()=>[V(P(g(J)),1)]),_:2},1032,["type"]))),128))])):te("",!0)]),_:1}),s(r(pe),{prop:"message",label:"提交信息","min-width":"250"})]),_:1},8,["data"])),[[z,q.value]])]))]))])}}}),Ws=$e(Hs,[["__scopeId","data-v-bc81ef7e"]]),Zs="data:image/svg+xml,%3csvg%20width='200'%20height='200'%20viewBox='0%200%20200%20200'%20xmlns='http://www.w3.org/2000/svg'%3e%3c!--%20主分支%20--%3e%3cline%20x1='40'%20y1='40'%20x2='40'%20y2='160'%20stroke='%2334495e'%20stroke-width='8'%20stroke-linecap='round'%20/%3e%3c!--%20特性分支%20--%3e%3cpath%20d='M40,70%20C60,70%2080,90%2080,110%20L80,130'%20stroke='%233498db'%20stroke-width='8'%20stroke-linecap='round'%20stroke-linejoin='round'%20fill='none'%20/%3e%3c!--%20开发分支%20--%3e%3cpath%20d='M40,100%20C60,100%20100,110%20100,130%20L100,160'%20stroke='%232ecc71'%20stroke-width='8'%20stroke-linecap='round'%20stroke-linejoin='round'%20fill='none'%20/%3e%3c!--%20修复分支%20--%3e%3cpath%20d='M40,130%20C60,130%20120,140%20120,160'%20stroke='%23e74c3c'%20stroke-width='8'%20stroke-linecap='round'%20stroke-linejoin='round'%20fill='none'%20/%3e%3c!--%20合并点%20--%3e%3cpath%20d='M80,130%20C80,145%2060,145%2040,145'%20stroke='%233498db'%20stroke-width='8'%20stroke-linecap='round'%20stroke-linejoin='round'%20fill='none'%20/%3e%3c!--%20节点%20--%3e%3ccircle%20cx='40'%20cy='40'%20r='10'%20fill='%2334495e'%20/%3e%3ccircle%20cx='40'%20cy='70'%20r='10'%20fill='%2334495e'%20/%3e%3ccircle%20cx='40'%20cy='100'%20r='10'%20fill='%2334495e'%20/%3e%3ccircle%20cx='40'%20cy='130'%20r='10'%20fill='%2334495e'%20/%3e%3ccircle%20cx='40'%20cy='145'%20r='10'%20fill='%2334495e'%20/%3e%3ccircle%20cx='40'%20cy='160'%20r='10'%20fill='%2334495e'%20/%3e%3ccircle%20cx='80'%20cy='130'%20r='10'%20fill='%233498db'%20/%3e%3ccircle%20cx='100'%20cy='160'%20r='10'%20fill='%232ecc71'%20/%3e%3ccircle%20cx='120'%20cy='160'%20r='10'%20fill='%23e74c3c'%20/%3e%3c/svg%3e",qs={class:"main-header"},Ys={class:"header-left"},Ks=["src"],Qs={class:"header-info"},Xs={key:0,id:"user-info"},ea={class:"user-name"},ta={class:"user-email"},sa={key:1,id:"user-info"},aa={class:"container"},la={key:0,class:"loading-container"},oa={class:"loading-spinner"},na={key:1,class:"layout-container"},ia={class:"left-panel"},ra={key:0,class:"right-panel"},ca={key:0,class:"card"},ua={class:"tips"},da={key:1,class:"right-panel"},pa={class:"dialog-footer"},fa={class:"main-footer"},ma={key:0,class:"branch-info"},va={class:"branch-wrapper"},ga={class:"dialog-footer"},ya=we({__name:"App",setup(F){const h=i(""),G=i(null),y=i(null),a=ie(),x=i(!1),L=i("");async function U(){try{const l=await(await fetch("/api/config/getConfig")).json();h.value=`默认提交信息: ${l.defaultCommitMessage}`}catch($){console.error("加载配置失败:",$)}}async function q(){try{const l=await(await fetch("/api/current_directory")).json();return L.value=l.directory||"未知目录",l}catch($){return console.error("获取当前目录失败:",$),{directory:"未知目录",isGitRepo:!1}}}be(async()=>{console.log("---------- 页面初始化开始 ----------");try{const[$,l]=await Promise.all([U(),q()]);a.isGitRepo=l.isGitRepo===!0,a.lastCheckedTime=Date.now(),a.isGitRepo?await Promise.all([a.getCurrentBranch(),a.getAllBranches(),a.getUserInfo()]):o.warning("当前目录不是Git仓库,部分功能将不可用")}catch($){console.error("初始化失败:",$)}finally{x.value=!0,console.log("---------- 页面初始化完成 ----------")}});const R=i(!1),T=i(""),D=i("");async function j(){await a.createBranch(T.value,D.value)&&(R.value=!1,T.value="",y.value&&y.value.refreshStatus(),G.value&&G.value.refreshLog())}function b(){D.value=a.currentBranch,R.value=!0}async function W($){await a.changeBranch($)&&(y.value&&y.value.refreshStatus(),G.value&&G.value.refreshLog())}const C=i(!1),E=i(""),I=i("");function f(){E.value=a.userName,I.value=a.userEmail,C.value=!0}async function g(){if(!E.value||!I.value){o.warning("用户名和邮箱不能为空");return}await a.restoreUserConfig(E.value,I.value)&&(C.value=!1)}async function M(){await a.clearUserConfig()&&(E.value="",I.value="")}return($,l)=>{const m=Ie,u=le,A=Xe,v=ze,_=Je,z=Qe,B=Ke,J=Fe,K=Re,ae=Ye;return p(),w(se,null,[e("header",qs,[e("div",Ys,[e("img",{src:r(Zs),alt:"Zen GitSync Logo",class:"logo"},null,8,Ks),l[9]||(l[9]=e("h1",null,"Zen GitSync UI",-1))]),e("div",Qs,[r(a).userName&&r(a).userEmail?(p(),w("div",Xs,[l[10]||(l[10]=e("span",{class:"user-label"},"用户:",-1)),e("span",ea,P(r(a).userName),1),e("span",ta,"<"+P(r(a).userEmail)+">",1),s(u,{type:"primary",size:"small",onClick:f,class:"user-settings-btn",circle:""},{default:n(()=>[s(m,null,{default:n(()=>[s(r(_e))]),_:1})]),_:1})])):(p(),w("div",sa,[l[11]||(l[11]=e("span",{class:"user-label"},"用户: ",-1)),l[12]||(l[12]=e("span",{class:"user-warning"},"未配置",-1)),s(u,{type:"primary",size:"small",onClick:f,class:"user-settings-btn",circle:""},{default:n(()=>[s(m,null,{default:n(()=>[s(r(_e))]),_:1})]),_:1})]))])]),e("div",aa,[x.value?(p(),w("div",na,[e("div",ia,[s(Wt,{ref_key:"gitStatusRef",ref:y,"initial-directory":L.value},null,8,["initial-directory"])]),r(a).isGitRepo?(p(),w("div",ra,[!r(a).userName||!r(a).userEmail?(p(),w("div",ca,[l[18]||(l[18]=e("h2",null,"Git用户未配置",-1)),l[19]||(l[19]=e("p",null,"请先配置Git用户信息才能进行提交操作。",-1)),e("div",ua,[l[16]||(l[16]=e("h3",null,"您可以通过以下方式配置:",-1)),l[17]||(l[17]=e("ol",null,[e("li",null,"点击右上角的设置按钮,配置用户名和邮箱"),e("li",null,"或者使用命令行配置:"),e("div",{class:"code-block"},[V(' git config --global user.name "您的用户名"'),e("br"),V(' git config --global user.email "您的邮箱" ')])],-1)),s(u,{type:"primary",onClick:f},{default:n(()=>l[15]||(l[15]=[V(" 立即配置 ")])),_:1})])])):(p(),w(se,{key:1},[s(Bs),s(Ws,{ref_key:"logListRef",ref:G},null,512)],64))])):(p(),w("div",da,l[20]||(l[20]=[e("div",{class:"card"},[e("h2",null,"Git仓库初始化"),e("p",null,"当前目录不是Git仓库,请先初始化Git仓库或切换到Git仓库目录。"),e("div",{class:"tips"},[e("h3",null,"可以使用以下命令初始化仓库:"),e("div",{class:"code-block"},"git init")])],-1)]))),s(K,{modelValue:R.value,"onUpdate:modelValue":l[3]||(l[3]=N=>R.value=N),title:"创建新分支",width:"30%","destroy-on-close":""},{footer:n(()=>[e("span",pa,[s(u,{onClick:l[2]||(l[2]=N=>R.value=!1)},{default:n(()=>l[21]||(l[21]=[V("取消")])),_:1}),s(u,{type:"primary",onClick:j,loading:r(a).isCreatingBranch},{default:n(()=>l[22]||(l[22]=[V(" 创建 ")])),_:1},8,["loading"])])]),default:n(()=>[s(J,{model:{newBranchName:T.value,selectedBaseBranch:D.value}},{default:n(()=>[s(_,{label:"新分支名称"},{default:n(()=>[s(v,{modelValue:T.value,"onUpdate:modelValue":l[0]||(l[0]=N=>T.value=N),placeholder:"请输入新分支名称"},null,8,["modelValue"])]),_:1}),s(_,{label:"基于分支"},{default:n(()=>[s(B,{modelValue:D.value,"onUpdate:modelValue":l[1]||(l[1]=N=>D.value=N),placeholder:"选择基础分支",style:{width:"100%"}},{default:n(()=>[(p(!0),w(se,null,oe(r(a).allBranches,N=>(p(),ee(z,{key:N,label:N,value:N},null,8,["label","value"]))),128))]),_:1},8,["modelValue"])]),_:1})]),_:1},8,["model"])]),_:1},8,["modelValue"])])):(p(),w("div",la,[s(A,{class:"loading-card"},{default:n(()=>[e("div",oa,[s(m,{class:"is-loading"},{default:n(()=>l[13]||(l[13]=[e("svg",{viewBox:"0 0 1024 1024",xmlns:"http://www.w3.org/2000/svg"},[e("path",{fill:"currentColor",d:"M512 64a32 32 0 0 1 32 32v192a32 32 0 0 1-64 0V96a32 32 0 0 1 32-32zm0 640a32 32 0 0 1 32 32v192a32 32 0 1 1-64 0V736a32 32 0 0 1 32-32zm448-192a32 32 0 0 1-32 32H736a32 32 0 1 1 0-64h192a32 32 0 0 1 32 32zm-640 0a32 32 0 0 1-32 32H96a32 32 0 0 1 0-64h192a32 32 0 0 1 32 32zM195.2 195.2a32 32 0 0 1 45.248 0L376.32 331.008a32 32 0 0 1-45.248 45.248L195.2 240.448a32 32 0 0 1 0-45.248zm452.544 452.544a32 32 0 0 1 45.248 0L828.8 783.552a32 32 0 0 1-45.248 45.248L647.744 692.992a32 32 0 0 1 0-45.248zM828.8 195.264a32 32 0 0 1 0 45.184L692.992 376.32a32 32 0 0 1-45.248-45.248l135.808-135.808a32 32 0 0 1 45.248 0zm-452.544 452.48a32 32 0 0 1 0 45.248L240.448 828.8a32 32 0 0 1-45.248-45.248l135.808-135.808a32 32 0 0 1 45.248 0z"})],-1)])),_:1})]),l[14]||(l[14]=e("div",{class:"loading-text"},"加载中...",-1))]),_:1})]))]),e("footer",fa,[r(a).currentBranch?(p(),w("div",ma,[e("div",va,[l[24]||(l[24]=e("span",{class:"branch-label"},"当前分支:",-1)),s(B,{modelValue:r(a).currentBranch,"onUpdate:modelValue":l[4]||(l[4]=N=>r(a).currentBranch=N),size:"small",onChange:W,loading:r(a).isChangingBranch,class:"branch-select"},{default:n(()=>[(p(!0),w(se,null,oe(r(a).allBranches,N=>(p(),ee(z,{key:N,label:N,value:N},null,8,["label","value"]))),128))]),_:1},8,["modelValue","loading"]),s(u,{type:"primary",size:"small",onClick:b,class:"create-branch-btn"},{default:n(()=>[s(m,null,{default:n(()=>[s(r(bt))]),_:1}),l[23]||(l[23]=V(" 新建分支 "))]),_:1})])])):te("",!0),l[25]||(l[25]=e("div",{class:"footer-right"},null,-1))]),s(K,{modelValue:C.value,"onUpdate:modelValue":l[8]||(l[8]=N=>C.value=N),title:"Git用户设置",width:"30%","destroy-on-close":""},{footer:n(()=>[e("span",ga,[s(u,{type:"danger",onClick:M},{default:n(()=>l[27]||(l[27]=[V(" 清除配置 ")])),_:1}),s(u,{onClick:l[7]||(l[7]=N=>C.value=!1)},{default:n(()=>l[28]||(l[28]=[V("取消")])),_:1}),s(u,{type:"primary",onClick:g},{default:n(()=>l[29]||(l[29]=[V(" 保存 ")])),_:1})])]),default:n(()=>[s(J,null,{default:n(()=>[s(_,{label:"用户名"},{default:n(()=>[s(v,{modelValue:E.value,"onUpdate:modelValue":l[5]||(l[5]=N=>E.value=N),placeholder:"请输入Git用户名"},null,8,["modelValue"])]),_:1}),s(_,{label:"邮箱"},{default:n(()=>[s(v,{modelValue:I.value,"onUpdate:modelValue":l[6]||(l[6]=N=>I.value=N),placeholder:"请输入Git邮箱"},null,8,["modelValue"])]),_:1}),s(_,null,{default:n(()=>[s(ae,{type:"info",closable:!1,"show-icon":""},{default:n(()=>l[26]||(l[26]=[V(" 这些设置将影响全局Git配置,对所有Git仓库生效。 ")])),_:1})]),_:1})]),_:1})]),_:1},8,["modelValue"])],64)}}}),ha=$e(ya,[["__scopeId","data-v-0bd851aa"]]),et=$t(ha);et.use(Ct());et.mount("#app");
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
.card[data-v-bcbbf547]{background-color:#fff;border-radius:8px;box-shadow:0 2px 12px #0000001a;padding:20px;margin-bottom:20px}.status-header[data-v-bcbbf547]{display:flex;justify-content:space-between;align-items:center;margin-bottom:10px}.status-header h2[data-v-bcbbf547]{margin:0}.status-box[data-v-bcbbf547]{white-space:pre-wrap;font-family:monospace;background-color:#f5f7fa;padding:15px;border-radius:4px;margin-bottom:15px;max-height:300px;overflow-y:auto}.file-list[data-v-bcbbf547]{max-height:300px;overflow-y:auto}.file-item[data-v-bcbbf547]{padding:8px 12px;margin-bottom:5px;border-radius:4px;cursor:pointer;display:flex;align-items:center;justify-content:space-between}.file-item[data-v-bcbbf547]:hover{background-color:#f5f7fa}.file-info[data-v-bcbbf547]{display:flex;align-items:center;flex-grow:1}.file-actions[data-v-bcbbf547]{margin-left:10px;opacity:.5;transition:opacity .2s}.file-item:hover .file-actions[data-v-bcbbf547]{opacity:1}.file-type[data-v-bcbbf547]{font-size:12px;padding:2px 6px;border-radius:10px;margin-right:10px;flex-shrink:0}.added .file-type[data-v-bcbbf547]{background-color:#e1f3d8;color:#67c23a}.modified .file-type[data-v-bcbbf547]{background-color:#e6f1fc;color:#409eff}.deleted .file-type[data-v-bcbbf547]{background-color:#fef0f0;color:#f56c6c}.untracked .file-type[data-v-bcbbf547]{background-color:#fdf6ec;color:#e6a23c}.file-path[data-v-bcbbf547]{font-family:monospace;word-break:break-all}.diff-content[data-v-bcbbf547]{font-family:monospace;white-space:pre-wrap;max-height:60vh;overflow-y:auto;padding:10px;background-color:#f5f7fa;border-radius:4px}.diff-formatted[data-v-bcbbf547]{font-size:14px;line-height:1.5}.file-navigation[data-v-bcbbf547]{display:flex;justify-content:center;align-items:center;margin-top:15px}.file-counter[data-v-bcbbf547]{margin:0 15px;font-size:14px;color:#606266}.current-directory[data-v-bcbbf547]{display:flex;align-items:center;margin-bottom:15px;padding:8px 12px;background-color:#f5f7fa;border-radius:4px;font-family:monospace}.current-directory .el-icon[data-v-bcbbf547]{margin-right:8px;color:#409eff}.current-directory span[data-v-bcbbf547]{flex-grow:1;word-break:break-all;margin-right:10px}.browser-current-path[data-v-bcbbf547]{margin-bottom:10px;font-size:14px;color:#606266;background-color:#f5f7fa;padding:8px 12px;border-radius:4px;font-family:monospace;word-break:break-all}.browser-error[data-v-bcbbf547]{margin-bottom:10px;color:#f56c6c;padding:8px 12px;background-color:#fef0f0;border-radius:4px}.directory-browser[data-v-bcbbf547]{padding:10px;height:400px;display:flex;flex-direction:column}.browser-nav[data-v-bcbbf547]{margin-bottom:10px;display:flex;justify-content:space-between;position:sticky;top:0;background-color:#fff;z-index:1;padding:10px 0}.directory-items-container[data-v-bcbbf547]{flex:1;overflow-y:auto}.directory-items[data-v-bcbbf547]{list-style:none;padding:0;margin:0}.directory-item[data-v-bcbbf547]{padding:8px 12px;margin-bottom:5px;border-radius:4px;cursor:pointer;display:flex;align-items:center}.directory-item[data-v-bcbbf547]:hover{background-color:#f5f7fa}.directory-item.directory[data-v-bcbbf547]{color:#409eff}.directory-item.file[data-v-bcbbf547]{color:#606266}.directory-item .el-icon[data-v-bcbbf547]{margin-right:10px}.directory-item span[data-v-bcbbf547]{font-family:monospace;word-break:break-all}.directory-buttons[data-v-bcbbf547]{display:flex;gap:10px;margin-top:10px}.no-padding-left[data-v-bcbbf547]{padding-left:8px!important}.diff-header{font-weight:700;background-color:#e6f1fc;padding:3px;margin:5px 0}.diff-old-file,.diff-new-file{color:#888}.diff-hunk-header{color:#6f42c1}.diff-added{background-color:#e6ffed;color:#28a745}.diff-removed{background-color:#ffeef0;color:#d73a49}.diff-context{color:#444}.card[data-v-8d105fc1]{background-color:#fff;border-radius:5px;box-shadow:0 2px 5px #0000001a;margin-bottom:20px;padding:20px}.layout-container[data-v-8d105fc1]{display:flex;gap:20px}.commit-section[data-v-8d105fc1]{flex:1;min-width:0}.actions-section[data-v-8d105fc1]{width:300px;flex-shrink:0}.actions-section h3[data-v-8d105fc1]{margin-top:0;margin-bottom:15px;padding-bottom:10px;border-bottom:1px solid #dcdfe6;font-size:18px;color:#303133;font-weight:500}.commit-form[data-v-8d105fc1]{display:flex;margin-bottom:15px;gap:10px}.git-actions[data-v-8d105fc1]{margin-top:20px}.action-groups[data-v-8d105fc1]{display:flex;flex-direction:column;gap:15px}.action-group[data-v-8d105fc1]{background-color:#f9f9f9;border-radius:8px;padding:12px 15px;box-shadow:0 1px 3px #0000000d;border-left:4px solid #409EFF;overflow:hidden}.action-group[data-v-8d105fc1]:nth-child(2){border-left-color:#e6a23c}.action-group[data-v-8d105fc1]:nth-child(3){border-left-color:#909399}.group-title[data-v-8d105fc1]{font-size:14px;font-weight:700;margin-bottom:10px;color:#606266;text-align:left;display:block;position:relative;padding-left:10px;border-bottom:1px solid rgba(0,0,0,.06);padding-bottom:8px}.group-buttons[data-v-8d105fc1]{display:flex;flex-direction:column;gap:8px;padding:0 2px}.action-button[data-v-8d105fc1]{position:relative;padding:14px 0 24px;width:100%;display:flex;flex-direction:column;align-items:center;justify-content:center;height:auto;text-align:center;font-size:16px;border-radius:6px;border:none}.action-button[data-v-8d105fc1]:hover{transform:translateY(-2px);box-shadow:0 2px 8px #00000026}.action-button[data-v-8d105fc1]:active{transform:translateY(0)}.action-button[data-v-8d105fc1] .el-button__content{display:flex;flex-direction:column;align-items:center;justify-content:center;width:100%}.action-button[data-v-8d105fc1] .el-icon{margin-right:0;margin-bottom:4px;font-size:18px}.command-text[data-v-8d105fc1]{position:absolute;bottom:6px;font-size:14px;font-family:monospace;width:100%;text-align:center;left:0;white-space:nowrap}.standard-commit-form[data-v-8d105fc1]{display:flex;flex-direction:column;gap:15px;margin-bottom:15px}.standard-commit-header[data-v-8d105fc1]{display:flex;flex-direction:column;gap:10px;width:100%}.type-select[data-v-8d105fc1]{width:100%}.scope-container[data-v-8d105fc1]{display:flex;align-items:center;gap:5px;width:100%}.scope-input[data-v-8d105fc1]{flex-grow:1}.description-container[data-v-8d105fc1]{display:flex;align-items:center;gap:5px;width:100%}.description-input[data-v-8d105fc1]{flex-grow:1}.settings-button[data-v-8d105fc1]{flex-shrink:0}.preview-section[data-v-8d105fc1]{background-color:#f5f7fa;padding:10px;border-radius:4px}.preview-title[data-v-8d105fc1]{font-weight:700;margin-bottom:5px}.preview-content[data-v-8d105fc1]{white-space:pre-wrap;font-family:monospace;margin:0;padding:10px;background-color:#ebeef5;border-radius:4px}.template-container[data-v-8d105fc1]{display:flex;flex-direction:column;height:calc(85vh - 100px);overflow-y:auto}.template-form[data-v-8d105fc1]{margin-bottom:20px}.template-list[data-v-8d105fc1]{flex:1;overflow-y:auto}.template-input[data-v-8d105fc1]{flex-grow:1}.template-list[data-v-8d105fc1]{overflow-y:auto;height:100%}.template-item[data-v-8d105fc1]{margin-bottom:10px}.template-item[data-v-8d105fc1]:hover{background-color:#f5f7fa}.template-content[data-v-8d105fc1]{flex-grow:1;margin-right:10px;word-break:break-all}.template-actions[data-v-8d105fc1]{display:flex;gap:5px;justify-content:flex-end;min-width:120px;flex-shrink:0}.options-row[data-v-8d105fc1]{display:flex;justify-content:space-between;align-items:center;margin-bottom:15px}.code-command[data-v-8d105fc1]{background-color:#2d2d2d;color:#f8f8f2;font-family:Courier New,Courier,monospace;padding:10px;border-radius:4px;overflow-x:auto;white-space:pre;font-size:14px}@media (max-width: 768px){.layout-container[data-v-8d105fc1]{flex-direction:column}.actions-section[data-v-8d105fc1]{width:100%}.group-buttons[data-v-8d105fc1]{flex-direction:row;flex-wrap:wrap}.action-button[data-v-8d105fc1]{flex:1;min-width:120px}}.git-config-warning[data-v-8d105fc1]{width:100%}.config-command[data-v-8d105fc1]{background-color:#2d2d2d;color:#f8f8f2;font-family:Courier New,Courier,monospace;padding:10px;border-radius:4px;margin-top:10px;white-space:pre}.push-button[data-v-8d105fc1]{background-color:#67c23a;border-color:#67c23a}.push-button[data-v-8d105fc1]:hover{background-color:#85ce61;border-color:#85ce61}.reset-button[data-v-8d105fc1]{background-color:#909399;border-color:#909399}.reset-button[data-v-8d105fc1]:hover{background-color:#a6a9ad;border-color:#a6a9ad}.el-button+.el-button[data-v-8d105fc1]{margin-left:0}.log-header[data-v-bc81ef7e]{display:flex;justify-content:space-between;align-items:center;margin-bottom:10px}.log-actions[data-v-bc81ef7e]{display:flex;gap:8px}.branch-container[data-v-bc81ef7e]{display:flex;flex-wrap:wrap;gap:4px}.branch-tag[data-v-bc81ef7e]{margin-right:4px}.commit-count[data-v-bc81ef7e]{margin-bottom:10px;font-size:14px;color:#606266;text-align:right}.graph-container[data-v-bc81ef7e]{width:100%;height:600px;overflow:auto;border:1px solid #ebeef5;border-radius:4px;padding:10px;background-color:#fff;position:relative}.graph-container svg[data-v-bc81ef7e]{transform-origin:top left;transition:transform .2s ease}.graph-view[data-v-bc81ef7e]{width:100%}.graph-controls[data-v-bc81ef7e]{display:flex;justify-content:space-between;align-items:center;margin-bottom:10px}.zoom-controls[data-v-bc81ef7e]{display:flex;gap:8px}.zoom-slider[data-v-bc81ef7e]{width:200px}.scale-info[data-v-bc81ef7e]{font-size:14px;color:#606266}.refresh-button-animated[data-v-bc81ef7e]{animation:pulse-bc81ef7e 1s}.refresh-notification[data-v-bc81ef7e]{background-color:#f0f9eb;color:#67c23a;padding:8px;border-radius:4px;margin-bottom:10px;text-align:center;font-size:14px;border-left:4px solid #67c23a;animation:fadeOut-bc81ef7e 2s forwards}@keyframes pulse-bc81ef7e{0%{transform:scale(1)}50%{transform:scale(1.2)}to{transform:scale(1)}}@keyframes fadeOut-bc81ef7e{0%{opacity:1}70%{opacity:1}to{opacity:0}}body{font-family:Arial,sans-serif;margin:0;padding:0;background-color:#f5f5f5}.container{margin:0 auto;padding:20px 30px}.main-header{background-color:#24292e;color:#fff;padding:15px 20px;display:flex;justify-content:space-between;align-items:center}.header-left{display:flex;align-items:center;gap:10px}.logo{height:32px;width:auto}h1{margin:0;font-size:24px}.header-info{display:flex;flex-direction:column;align-items:flex-end;gap:5px}#branch-info,#user-info{background-color:#ffffff1a;padding:4px 8px;border-radius:4px;font-size:14px}.branch-label,.user-label,.user-name{font-weight:700;margin-right:5px}.user-email{color:#e0e0e0}.branch-name{font-family:monospace}.card{background-color:#fff;border-radius:5px;box-shadow:0 2px 5px #0000001a;margin-bottom:20px;padding:20px}.status-box{background-color:#f6f8fa;border:1px solid #e1e4e8;border-radius:3px;padding:15px;white-space:pre-wrap;font-family:monospace;max-height:300px;overflow-y:auto}.layout-container{display:flex;gap:20px}.left-panel{flex:0 0 30%;max-width:30%}.right-panel{flex:0 0 70%;max-width:70%}@media (max-width: 768px){.layout-container{flex-direction:column}.left-panel,.right-panel{flex:0 0 100%;max-width:100%}.header-left{gap:8px}.logo{height:24px}h1{font-size:20px}}.commit-form{display:flex;margin-bottom:15px}.log-item{padding:10px 0;border-bottom:1px solid #eee}.log-item:last-child{border-bottom:none}.log-hash{color:#6f42c1;font-family:monospace}.log-author,.log-date{color:#6a737d}.log-message{font-weight:700}.log-branch{display:inline-block;background-color:#0366d6;color:#fff;border-radius:3px;padding:2px 6px;margin-left:8px;font-size:12px}.branch-select :deep(.el-input__inner){background-color:#ffffff1a;color:#fff;border:none}.branch-select :deep(.el-input__suffix){color:#fff}.tips{margin-top:20px;padding:15px;background-color:#f5f7fa;border-radius:5px;border-left:4px solid #409eff}.tips h3{margin-top:0;font-size:16px;margin-bottom:10px}.code-block{background-color:#2d2d2d;color:#f8f8f2;font-family:monospace;padding:10px 15px;border-radius:4px;margin-bottom:10px}.loading-container{display:flex;justify-content:center;align-items:center;min-height:400px}.loading-card{width:300px;text-align:center;padding:30px}.loading-spinner{font-size:48px;margin-bottom:20px;color:#409eff}.loading-text{font-size:18px;color:#606266}.user-settings-btn{margin-left:10px}.user-warning{color:#e6a23c;font-weight:700}.logo[data-v-0bd851aa]{will-change:filter;transition:filter .3s}.logo[data-v-0bd851aa]:hover{filter:drop-shadow(0 0 2em #42b883aa)}.main-footer[data-v-0bd851aa]{background-color:#24292e;color:#fff;padding:10px 20px;display:flex;justify-content:space-between;align-items:center;position:fixed;bottom:0;left:0;right:0;z-index:100;box-shadow:0 -2px 10px #0000001a}.branch-info[data-v-0bd851aa]{display:flex;align-items:center;gap:10px}.branch-wrapper[data-v-0bd851aa]{display:flex;align-items:center;background-color:#ffffff26;border-radius:4px;padding:8px 12px;box-shadow:0 2px 4px #0003;transition:all .3s}.branch-wrapper[data-v-0bd851aa]:hover{background-color:#fff3}.branch-label[data-v-0bd851aa]{font-weight:700;margin-right:10px;color:#fff}.branch-select[data-v-0bd851aa]{width:200px;margin-right:10px}.create-branch-btn[data-v-0bd851aa]{background-color:#2ea44f;border-color:#2ea44f;transition:all .3s;box-shadow:0 2px 4px #0003}.create-branch-btn[data-v-0bd851aa]:hover{background-color:#3bbc63;border-color:#3bbc63;transform:translateY(-2px);box-shadow:0 4px 8px #0003}.footer-right[data-v-0bd851aa]{display:flex;align-items:center;gap:10px;color:#ffffffe6;font-size:13px;background-color:#ffffff1a;padding:8px 12px;border-radius:4px;box-shadow:0 2px 4px #0003}
|