zen-gitsync 2.0.3 → 2.0.5

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.
@@ -5,10 +5,10 @@
5
5
  <link rel="icon" type="image/svg+xml" href="/favicon.svg" />
6
6
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
7
7
  <title>Zen-GitSync - Git同步工具</title>
8
- <script type="module" crossorigin src="/assets/index-kfMX1bxz.js"></script>
9
- <link rel="modulepreload" crossorigin href="/assets/vendor-DxvF30ca.js">
8
+ <script type="module" crossorigin src="/assets/index-CALk9kKc.js"></script>
9
+ <link rel="modulepreload" crossorigin href="/assets/vendor-BfXVsoKv.js">
10
10
  <link rel="stylesheet" crossorigin href="/assets/vendor-Dp0FkvMe.css">
11
- <link rel="stylesheet" crossorigin href="/assets/index-BHmYZROy.css">
11
+ <link rel="stylesheet" crossorigin href="/assets/index-D3zIiSNw.css">
12
12
  </head>
13
13
  <body>
14
14
  <div id="app"></div>
@@ -7,6 +7,7 @@ import open from 'open';
7
7
  import config from '../../config.js';
8
8
  import chalk from 'chalk';
9
9
  import fs from 'fs/promises';
10
+ import os from 'os';
10
11
  // import { Server } from 'socket.io';
11
12
  // import { exec } from 'child_process';
12
13
 
@@ -22,6 +23,13 @@ async function startUIServer() {
22
23
  // 添加全局中间件来解析JSON请求体
23
24
  app.use(express.json());
24
25
 
26
+ // 添加请求日志中间件
27
+ app.use((req, res, next) => {
28
+ const now = new Date().toLocaleString();
29
+ console.log(`[${now}] ${req.method} ${req.url}`);
30
+ next();
31
+ });
32
+
25
33
  // // 启动前端Vue应用
26
34
  // const clientPath = path.join(__dirname, '../client');
27
35
  // console.log(`正在启动前端应用,路径: ${clientPath}`);
@@ -148,10 +156,10 @@ async function startUIServer() {
148
156
  // 获取Git用户配置信息
149
157
  app.get('/api/user-info', async (req, res) => {
150
158
  try {
151
- // 获取用户名
152
- const { stdout: userName } = await execGitCommand('git config user.name');
153
- // 获取用户邮箱
154
- const { stdout: userEmail } = await execGitCommand('git config user.email');
159
+ // 获取全局用户名
160
+ const { stdout: userName } = await execGitCommand('git config --global user.name');
161
+ // 获取全局用户邮箱
162
+ const { stdout: userEmail } = await execGitCommand('git config --global user.email');
155
163
 
156
164
  res.json({
157
165
  name: userName.trim(),
@@ -376,6 +384,53 @@ async function startUIServer() {
376
384
  }
377
385
  })
378
386
 
387
+ // 更新模板
388
+ app.post('/api/config/update-template', express.json(), async (req, res) => {
389
+ try {
390
+ const { oldTemplate, newTemplate, type } = req.body
391
+
392
+ if (!oldTemplate || !newTemplate || !type) {
393
+ return res.status(400).json({ success: false, error: '缺少必要参数' })
394
+ }
395
+
396
+ const config = await configManager.loadConfig()
397
+
398
+ if (type === 'description') {
399
+ // 确保描述模板数组存在
400
+ if (config.descriptionTemplates) {
401
+ const index = config.descriptionTemplates.indexOf(oldTemplate)
402
+ if (index !== -1) {
403
+ config.descriptionTemplates[index] = newTemplate
404
+ await configManager.saveConfig(config)
405
+ } else {
406
+ return res.status(404).json({ success: false, error: '未找到原模板' })
407
+ }
408
+ } else {
409
+ return res.status(404).json({ success: false, error: '模板列表不存在' })
410
+ }
411
+ } else if (type === 'scope') {
412
+ // 确保作用域模板数组存在
413
+ if (config.scopeTemplates) {
414
+ const index = config.scopeTemplates.indexOf(oldTemplate)
415
+ if (index !== -1) {
416
+ config.scopeTemplates[index] = newTemplate
417
+ await configManager.saveConfig(config)
418
+ } else {
419
+ return res.status(404).json({ success: false, error: '未找到原模板' })
420
+ }
421
+ } else {
422
+ return res.status(404).json({ success: false, error: '模板列表不存在' })
423
+ }
424
+ } else {
425
+ return res.status(400).json({ success: false, error: '不支持的模板类型' })
426
+ }
427
+
428
+ res.json({ success: true })
429
+ } catch (error) {
430
+ res.status(500).json({ success: false, error: error.message })
431
+ }
432
+ })
433
+
379
434
  // 提交更改
380
435
  app.post('/api/commit', express.json(), async (req, res) => {
381
436
  try {
@@ -440,8 +495,11 @@ async function startUIServer() {
440
495
  // 获取日志
441
496
  app.get('/api/log', async (req, res) => {
442
497
  try {
443
- // 获取请求参数中的数量限制,默认为100
444
- const limit = req.query.all === 'true' ? '' : '-n 100';
498
+ // 获取请求参数中的数量限制,默认为30
499
+ const limit = req.query.all === 'true' ? '' : '-n 30';
500
+
501
+ // graph参数保留但不做特殊处理,避免前端代码重复调用API
502
+ // 由前端统一使用该接口
445
503
 
446
504
  // 修改 git log 命令,添加 %ae 参数来获取作者邮箱
447
505
  const { stdout } = await execGitCommand(`git log --all --pretty=format:"%h|%an|%ae|%ad|%s|%D" --date=short ${limit}`);
@@ -533,6 +591,129 @@ async function startUIServer() {
533
591
  }
534
592
  });
535
593
 
594
+ // 重置暂存区 (git reset HEAD)
595
+ app.post('/api/reset-head', async (req, res) => {
596
+ try {
597
+ // 执行 git reset HEAD 命令
598
+ await execGitCommand('git reset HEAD');
599
+ res.json({ success: true });
600
+ } catch (error) {
601
+ console.error('重置暂存区失败:', error);
602
+ res.status(500).json({
603
+ success: false,
604
+ error: `重置暂存区失败: ${error.message}`
605
+ });
606
+ }
607
+ });
608
+
609
+ // 重置到远程分支 (git reset --hard origin/branch)
610
+ app.post('/api/reset-to-remote', async (req, res) => {
611
+ try {
612
+ const { branch } = req.body;
613
+
614
+ if (!branch) {
615
+ return res.status(400).json({
616
+ success: false,
617
+ error: '缺少分支名称参数'
618
+ });
619
+ }
620
+
621
+ // 执行 git reset --hard origin/branch 命令
622
+ await execGitCommand(`git reset --hard origin/${branch}`);
623
+ res.json({ success: true });
624
+ } catch (error) {
625
+ console.error('重置到远程分支失败:', error);
626
+ res.status(500).json({
627
+ success: false,
628
+ error: `重置到远程分支失败: ${error.message}`
629
+ });
630
+ }
631
+ });
632
+
633
+ // 添加清理Git锁定文件的接口
634
+ app.post('/api/remove-lock', async (req, res) => {
635
+ try {
636
+ const gitDir = path.join(process.cwd(), '.git')
637
+ const indexLockFile = path.join(gitDir, 'index.lock')
638
+
639
+ // 检查文件是否存在
640
+ try {
641
+ await fs.access(indexLockFile)
642
+ // 如果文件存在,尝试删除它
643
+ await fs.unlink(indexLockFile)
644
+ res.json({ success: true, message: '已清理锁定文件' })
645
+ } catch (error) {
646
+ // 如果文件不存在,也返回成功
647
+ if (error.code === 'ENOENT') {
648
+ res.json({ success: true, message: '没有发现锁定文件' })
649
+ } else {
650
+ throw error
651
+ }
652
+ }
653
+ } catch (error) {
654
+ console.error('清理锁定文件失败:', error)
655
+ res.status(500).json({
656
+ success: false,
657
+ error: `清理锁定文件失败: ${error.message}`
658
+ })
659
+ }
660
+ })
661
+
662
+ // 清除Git用户配置
663
+ app.post('/api/clear-user-config', async (req, res) => {
664
+ try {
665
+ // 检查全局配置是否存在,如果存在才删除
666
+ try {
667
+ const { stdout: userName } = await execGitCommand('git config --global user.name');
668
+ if (userName.trim()) {
669
+ await execGitCommand('git config --global --unset user.name');
670
+ }
671
+ } catch (error) {
672
+ console.log('全局用户名配置检查失败,可能不存在:', error.message);
673
+ // 忽略错误继续执行
674
+ }
675
+
676
+ try {
677
+ const { stdout: userEmail } = await execGitCommand('git config --global user.email');
678
+ if (userEmail.trim()) {
679
+ await execGitCommand('git config --global --unset user.email');
680
+ }
681
+ } catch (error) {
682
+ console.log('全局邮箱配置检查失败,可能不存在:', error.message);
683
+ // 忽略错误继续执行
684
+ }
685
+
686
+ res.json({ success: true, message: '已清除全局Git用户配置' });
687
+ } catch (error) {
688
+ res.status(500).json({
689
+ success: false,
690
+ error: `清除全局Git用户配置失败: ${error.message}`
691
+ });
692
+ }
693
+ });
694
+
695
+ // 恢复Git用户配置
696
+ app.post('/api/restore-user-config', async (req, res) => {
697
+ try {
698
+ const { name, email } = req.body;
699
+ if (!name || !email) {
700
+ return res.status(400).json({
701
+ success: false,
702
+ error: '需要提供用户名和邮箱'
703
+ });
704
+ }
705
+
706
+ await execGitCommand(`git config --global user.name "${name}"`);
707
+ await execGitCommand(`git config --global user.email "${email}"`);
708
+ res.json({ success: true, message: '已更新全局Git用户配置' });
709
+ } catch (error) {
710
+ res.status(500).json({
711
+ success: false,
712
+ error: `更新全局Git用户配置失败: ${error.message}`
713
+ });
714
+ }
715
+ });
716
+
536
717
  // Socket.io 实时更新
537
718
  // io.on('connection', (socket) => {
538
719
  // console.log('客户端已连接');
@@ -556,7 +737,11 @@ async function startUIServer() {
556
737
  // 启动服务器
557
738
  const PORT = 3000;
558
739
  httpServer.listen(PORT, () => {
559
- console.log(`后端API服务器已启动: http://localhost:${PORT}`);
740
+ console.log(chalk.green('======================================'));
741
+ console.log(chalk.green(` Zen GitSync 服务器已启动`));
742
+ console.log(chalk.green(` 访问地址: http://localhost:${PORT}`));
743
+ console.log(chalk.green(` 启动时间: ${new Date().toLocaleString()}`));
744
+ console.log(chalk.green('======================================'));
560
745
  open(`http://localhost:${PORT}`);
561
746
  }).on('error', async (err) => {
562
747
  if (err.code === 'EADDRINUSE') {
@@ -566,7 +751,11 @@ async function startUIServer() {
566
751
  try {
567
752
  await new Promise((resolve, reject) => {
568
753
  httpServer.listen(newPort, () => {
569
- console.log(`后端API服务器已启动: http://localhost:${newPort}`);
754
+ console.log(chalk.green('======================================'));
755
+ console.log(chalk.green(` Zen GitSync 服务器已启动`));
756
+ console.log(chalk.green(` 访问地址: http://localhost:${newPort}`));
757
+ console.log(chalk.green(` 启动时间: ${new Date().toLocaleString()}`));
758
+ console.log(chalk.green('======================================'));
570
759
  open(`http://localhost:${newPort}`);
571
760
  resolve();
572
761
  }).on('error', (e) => {
@@ -1 +0,0 @@
1
- .card[data-v-61ea34c7]{background-color:#fff;border-radius:8px;box-shadow:0 2px 12px #0000001a;padding:20px;margin-bottom:20px}.status-header[data-v-61ea34c7]{display:flex;justify-content:space-between;align-items:center;margin-bottom:10px}.status-header h2[data-v-61ea34c7]{margin:0}.status-box[data-v-61ea34c7]{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-61ea34c7]{max-height:300px;overflow-y:auto}.file-item[data-v-61ea34c7]{padding:8px 12px;margin-bottom:5px;border-radius:4px;cursor:pointer;display:flex;align-items:center;justify-content:space-between}.file-item[data-v-61ea34c7]:hover{background-color:#f5f7fa}.file-info[data-v-61ea34c7]{display:flex;align-items:center;flex-grow:1}.file-actions[data-v-61ea34c7]{margin-left:10px;opacity:.5;transition:opacity .2s}.file-item:hover .file-actions[data-v-61ea34c7]{opacity:1}.file-type[data-v-61ea34c7]{font-size:12px;padding:2px 6px;border-radius:10px;margin-right:10px;flex-shrink:0}.added .file-type[data-v-61ea34c7]{background-color:#e1f3d8;color:#67c23a}.modified .file-type[data-v-61ea34c7]{background-color:#e6f1fc;color:#409eff}.deleted .file-type[data-v-61ea34c7]{background-color:#fef0f0;color:#f56c6c}.untracked .file-type[data-v-61ea34c7]{background-color:#fdf6ec;color:#e6a23c}.file-path[data-v-61ea34c7]{font-family:monospace;word-break:break-all}.diff-content[data-v-61ea34c7]{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-61ea34c7]{font-size:14px;line-height:1.5}.file-navigation[data-v-61ea34c7]{display:flex;justify-content:center;align-items:center;margin-top:15px}.file-counter[data-v-61ea34c7]{margin:0 15px;font-size:14px;color:#606266}.current-directory[data-v-61ea34c7]{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-61ea34c7]{margin-right:8px;color:#409eff}.current-directory span[data-v-61ea34c7]{flex-grow:1;word-break:break-all;margin-right:10px}.browser-current-path[data-v-61ea34c7]{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-61ea34c7]{margin-bottom:10px;color:#f56c6c;padding:8px 12px;background-color:#fef0f0;border-radius:4px}.directory-browser[data-v-61ea34c7]{padding:10px;max-height:400px;overflow-y:auto}.browser-nav[data-v-61ea34c7]{margin-bottom:10px;display:flex;justify-content:space-between}.directory-items[data-v-61ea34c7]{list-style:none;padding:0;margin:0}.directory-item[data-v-61ea34c7]{padding:8px 12px;margin-bottom:5px;border-radius:4px;cursor:pointer;display:flex;align-items:center}.directory-item[data-v-61ea34c7]:hover{background-color:#f5f7fa}.directory-item.directory[data-v-61ea34c7]{color:#409eff}.directory-item.file[data-v-61ea34c7]{color:#606266}.directory-item .el-icon[data-v-61ea34c7]{margin-right:10px}.directory-item span[data-v-61ea34c7]{font-family:monospace;word-break:break-all}.directory-buttons[data-v-61ea34c7]{display:flex;gap:10px;margin-top:10px}.no-padding-left[data-v-61ea34c7]{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}.commit-form[data-v-00e49634]{display:flex;margin-bottom:15px;gap:10px}.button-group[data-v-00e49634]{display:flex;gap:10px}.commit-mode-toggle[data-v-00e49634]{margin-bottom:15px}.standard-commit-form[data-v-00e49634]{display:flex;flex-direction:column;gap:15px;margin-bottom:15px}.standard-commit-header[data-v-00e49634]{display:flex;gap:10px;width:100%}.type-select[data-v-00e49634]{width:120px;flex-shrink:0}.scope-container[data-v-00e49634]{display:flex;align-items:center;gap:5px;flex-grow:0;width:200px}.scope-input[data-v-00e49634]{flex-grow:1}.description-container[data-v-00e49634]{display:flex;align-items:center;gap:5px;flex-grow:1}.description-input[data-v-00e49634]{flex-grow:1;min-width:200px}.settings-button[data-v-00e49634]{flex-shrink:0}.preview-section[data-v-00e49634]{background-color:#f5f7fa;padding:10px;border-radius:4px}.preview-title[data-v-00e49634]{font-weight:700;margin-bottom:5px}.preview-content[data-v-00e49634]{white-space:pre-wrap;font-family:monospace;margin:0;padding:10px;background-color:#ebeef5;border-radius:4px}.template-container[data-v-00e49634]{display:flex;flex-direction:column;height:calc(85vh - 100px);overflow-y:auto}.template-form[data-v-00e49634]{margin-bottom:20px}.template-list[data-v-00e49634]{flex:1;overflow-y:auto}.template-input[data-v-00e49634]{flex-grow:1}.template-list[data-v-00e49634]{overflow-y:auto;height:100%}.template-item[data-v-00e49634]{margin-bottom:10px}.template-item[data-v-00e49634]:hover{background-color:#f5f7fa}.template-content[data-v-00e49634]{flex-grow:1;margin-right:10px;word-break:break-all}.template-actions[data-v-00e49634]{display:flex;gap:5px;justify-content:flex-end;min-width:120px;flex-shrink:0}.log-header[data-v-c6b721c7]{display:flex;justify-content:space-between;align-items:center;margin-bottom:10px}.log-actions[data-v-c6b721c7]{display:flex;gap:8px}.branch-container[data-v-c6b721c7]{display:flex;flex-wrap:wrap;gap:4px}.branch-tag[data-v-c6b721c7]{margin-right:4px}.commit-count[data-v-c6b721c7]{margin-bottom:10px;font-size:14px;color:#606266;text-align:right}.graph-container[data-v-c6b721c7]{width:100%;height:600px;overflow:auto;border:1px solid #ebeef5;border-radius:4px;padding:10px;background-color:#fff}.graph-view[data-v-c6b721c7]{width:100%}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{width:150px;margin-left:5px}.branch-select :deep(.el-input__inner){background-color:#ffffff1a;color:#fff;border:none}.branch-select :deep(.el-input__suffix){color:#fff}.logo[data-v-93cc73d5]{will-change:filter;transition:filter .3s}.logo[data-v-93cc73d5]:hover{filter:drop-shadow(0 0 2em #42b883aa)}.main-footer[data-v-93cc73d5]{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}.branch-info[data-v-93cc73d5]{display:flex;align-items:center}.footer-right[data-v-93cc73d5]{color:#ffffffb3;font-size:12px}
@@ -1,9 +0,0 @@
1
- import{d as ce,r as l,o as ue,c as g,a as d,b as a,e as q,f as t,E as xe,w as r,u as S,g as ge,t as w,h as se,i as B,j as Ae,F as K,k as Y,l as he,m as je,n as Be,p as _e,q as ye,s as Ne,v as $e,x as Z,y as Me,z as De,A as Ee,B as Re,C as c,D as Ue,G as Oe,H as ze,I as Ie,J as Ve,K as Fe,L as Ge,M as Pe,N as Le,O as Se,P as Je,Q as He,R as We,S as ne,T as Ze,U as qe,V as Ke,W as Qe,X as Xe}from"./vendor-DxvF30ca.js";(function(){const G=document.createElement("link").relList;if(G&&G.supports&&G.supports("modulepreload"))return;for(const n of document.querySelectorAll('link[rel="modulepreload"]'))y(n);new MutationObserver(n=>{for(const h of n)if(h.type==="childList")for(const z of h.addedNodes)z.tagName==="LINK"&&z.rel==="modulepreload"&&y(z)}).observe(document,{childList:!0,subtree:!0});function p(n){const h={};return n.integrity&&(h.integrity=n.integrity),n.referrerPolicy&&(h.referrerPolicy=n.referrerPolicy),n.crossOrigin==="use-credentials"?h.credentials="include":n.crossOrigin==="anonymous"?h.credentials="omit":h.credentials="same-origin",h}function y(n){if(n.ep)return;n.ep=!0;const h=p(n);fetch(n.href,h)}})();const Ye={class:"card"},et={class:"current-directory"},tt={class:"status-header"},st={class:"status-box"},at={key:0,class:"file-list"},lt=["onClick"],ot={class:"file-type"},nt={class:"file-path"},it={class:"file-actions"},rt={class:"directory-buttons"},ct={class:"browser-current-path"},ut={key:0,class:"browser-error"},dt={class:"directory-browser"},pt={class:"browser-nav"},ft={class:"directory-items"},vt=["onClick"],mt={class:"diff-content"},gt=["innerHTML"],yt={key:1,class:"no-diff"},ht={class:"file-navigation"},_t={class:"file-counter"},wt=ce({__name:"GitStatus",setup(O,{expose:G}){const p=l("加载中..."),y=l(!1),n=l([]),h=l(""),z=l(""),P=l(!1),E=l(!1),L=l(-1),I=l(!1),F=l(""),A=l(!1),J=l(!1),k=l(""),C=l([]),$=l(!1),f=l("");function j(u){if(u===void 0)return;const o=u.split(`
2
- `),V=[];for(const m of o){const s=m.match(/^([ MADRCU\?]{2})\s+(.+)$/);if(s){let e="";const x=s[1].trim();x==="M"||x==="MM"||x==="AM"||x==="RM"?e="modified":x==="A"||x==="AA"?e="added":x==="D"||x==="AD"||x==="DA"?e="deleted":x==="??"?e="untracked":e="other",V.push({path:s[2],type:e})}}n.value=V}const T=l("");async function N(){try{y.value=!0;const o=await(await fetch("/api/current_directory")).json();if(T.value=o.directory||"未知目录",o.isGitRepo===!1){p.value="当前目录不是一个Git仓库",n.value=[],c.warning("当前目录不是一个Git仓库");return}const m=await(await fetch("/api/status")).json();p.value=m.status;const e=await(await fetch("/api/status_porcelain")).json();j(e.status),c({message:"Git 状态已刷新",type:"success"})}catch(u){p.value="加载状态失败: "+u.message,n.value=[],c({message:"刷新失败: "+u.message,type:"error"})}finally{y.value=!1}}function R(u){if(!u)return"";const o=u.split(`
3
- `);function V(m){return m.replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;").replace(/'/g,"&#039;")}return o.map(m=>{const s=V(m);return m.startsWith("diff --git")?`<div class="diff-header">${s}</div>`:m.startsWith("---")?`<div class="diff-old-file">${s}</div>`:m.startsWith("+++")?`<div class="diff-new-file">${s}</div>`:m.startsWith("@@")?`<div class="diff-hunk-header">${s}</div>`:m.startsWith("+")?`<div class="diff-added">${s}</div>`:m.startsWith("-")?`<div class="diff-removed">${s}</div>`:`<div class="diff-context">${s}</div>`}).join("")}async function _(u){try{E.value=!0,h.value=u,L.value=n.value.findIndex(m=>m.path===u);const V=await(await fetch(`/api/diff?file=${encodeURIComponent(u)}`)).json();z.value=V.diff||"没有变更",P.value=!0}catch(o){c({message:"获取文件差异失败: "+o.message,type:"error"}),z.value="获取差异失败: "+o.message}finally{E.value=!1}}async function i(){if(n.value.length===0||L.value<=0)return;const u=L.value-1,o=n.value[u];await _(o.path)}async function H(){if(n.value.length===0||L.value>=n.value.length-1)return;const u=L.value+1,o=n.value[u];await _(o.path)}function te(){F.value=T.value,I.value=!0}function Q(){f.value="",k.value=F.value||T.value,J.value=!0,X(k.value)}async function X(u){try{$.value=!0,f.value="";let o=u;/^[A-Za-z]:$/.test(o)&&(o+="/");const V=await fetch(`/api/browse_directory?path=${encodeURIComponent(o)}`);if(V.status===403){const s=await V.json();f.value=s.error||"目录浏览功能未启用";return}if(!V.ok){const s=await V.json();f.value=s.error||"获取目录内容失败";return}const m=await V.json();m.success?(C.value=m.items,k.value=m.currentPath):f.value=m.error||"获取目录内容失败"}catch(o){f.value=`获取目录内容失败: ${o.message}`}finally{$.value=!1}}function ae(){if(/^[A-Za-z]:$/.test(k.value)||/^[A-Za-z]:[\\/]$/.test(k.value)||k.value==="/")return;let u=k.value.split(/[/\\]/);u.pop();let o=u.join("/");u.length===1&&/^[A-Za-z]:$/.test(u[0])&&(o=u[0]+"/"),o&&X(o)}function ee(u){u.type==="directory"&&X(u.path)}function le(){F.value=k.value,J.value=!1}async function oe(){if(!F.value){c.warning("目录路径不能为空");return}try{A.value=!0;const o=await(await fetch("/api/change_directory",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({path:F.value})})).json();o.success?(c.success("已切换工作目录"),T.value=o.directory,I.value=!1,o.isGitRepo||c.warning("当前目录不是一个Git仓库"),N()):c.error(o.error||"切换目录失败")}catch(u){c.error(`切换目录失败: ${u.message}`)}finally{A.value=!1}}function D(u){_(u.path)}function pe(u){switch(u){case"added":return"新增";case"modified":return"修改";case"deleted":return"删除";case"untracked":return"未跟踪";default:return"其他"}}async function ie(){await N()}async function fe(u){try{await Ie.confirm(`确定要撤回文件 "${u}" 的所有修改吗?此操作无法撤销。`,"撤回修改",{confirmButtonText:"确定",cancelButtonText:"取消",type:"warning"});const V=await(await fetch("/api/revert_file",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({filePath:u})})).json();V.success?(c.success("已撤回文件修改"),await N()):c.error(V.error||"撤回文件修改失败")}catch(o){o.message!=="cancel"&&c.error(`撤回文件修改失败: ${o.message}`)}}return ue(()=>{N()}),G({refreshStatus:ie}),(u,o)=>{const V=xe,m=se,s=ze,e=_e,x=Be,W=je,M=he,U=De;return d(),g("div",Ye,[a("div",et,[t(V,null,{default:r(()=>[t(S(ge))]),_:1}),a("span",null,w(T.value),1),t(m,{type:"primary",size:"small",onClick:te,plain:""},{default:r(()=>o[4]||(o[4]=[B(" 切换目录 ")])),_:1})]),a("div",tt,[o[5]||(o[5]=a("h2",null,"Git 状态",-1)),t(m,{type:"primary",icon:S(Ae),circle:"",size:"small",onClick:ie,loading:y.value},null,8,["icon","loading"])]),a("div",st,w(p.value),1),n.value.length?(d(),g("div",at,[(d(!0),g(K,null,Y(n.value,b=>(d(),g("div",{key:b.path,class:$e(["file-item",b.type])},[a("div",{class:"file-info",onClick:re=>D(b)},[a("span",ot,w(pe(b.type)),1),a("span",nt,w(b.path),1)],8,lt),a("div",it,[t(s,{content:"撤回修改",placement:"top","hide-after":1e3},{default:r(()=>[t(m,{type:"danger",size:"small",icon:S(Oe),circle:"",onClick:Ue(re=>fe(b.path),["stop"])},null,8,["icon","onClick"])]),_:2},1024)])],2))),128))])):q("",!0),t(M,{modelValue:I.value,"onUpdate:modelValue":o[1]||(o[1]=b=>I.value=b),title:"切换工作目录",width:"500px"},{default:r(()=>[t(W,null,{default:r(()=>[t(x,{label:"目录路径"},{default:r(()=>[t(e,{modelValue:F.value,"onUpdate:modelValue":o[0]||(o[0]=b=>F.value=b),placeholder:"请输入目录路径",clearable:""},null,8,["modelValue"]),a("div",rt,[t(m,{onClick:Q,type:"primary",plain:"",class:"no-padding-left"},{default:r(()=>[t(V,null,{default:r(()=>[t(S(ge))]),_:1}),o[6]||(o[6]=B(" 浏览 "))]),_:1}),t(m,{onClick:oe,loading:A.value,type:"primary"},{default:r(()=>o[7]||(o[7]=[B(" 切换 ")])),_:1},8,["loading"])])]),_:1})]),_:1})]),_:1},8,["modelValue"]),t(M,{modelValue:J.value,"onUpdate:modelValue":o[2]||(o[2]=b=>J.value=b),title:"浏览目录",width:"600px"},{default:r(()=>[a("div",ct,[a("span",null,"当前路径: "+w(k.value),1)]),f.value?(d(),g("div",ut,w(f.value),1)):q("",!0),ye((d(),g("div",dt,[a("div",pt,[t(m,{onClick:ae,disabled:!k.value||$.value,size:"small",class:"no-padding-left"},{default:r(()=>[t(V,null,{default:r(()=>[t(S(Ne))]),_:1}),o[8]||(o[8]=B(" 上级目录 "))]),_:1},8,["disabled"]),t(m,{onClick:le,type:"primary",size:"small",class:"no-padding-left"},{default:r(()=>o[9]||(o[9]=[B(" 选择当前目录 ")])),_:1})]),a("ul",ft,[(d(!0),g(K,null,Y(C.value,b=>(d(),g("li",{key:b.path,class:$e(["directory-item",b.type]),onClick:re=>ee(b)},[b.type==="directory"?(d(),Z(V,{key:0},{default:r(()=>[t(S(ge))]),_:1})):(d(),Z(V,{key:1},{default:r(()=>[t(S(Me))]),_:1})),a("span",null,w(b.name),1)],10,vt))),128))])])),[[U,$.value]])]),_:1},8,["modelValue"]),t(M,{modelValue:P.value,"onUpdate:modelValue":o[3]||(o[3]=b=>P.value=b),title:`文件差异: ${h.value}`,width:"80%","destroy-on-close":""},{default:r(()=>[ye((d(),g("div",mt,[z.value?(d(),g("div",{key:0,innerHTML:R(z.value),class:"diff-formatted"},null,8,gt)):(d(),g("div",yt,"该文件没有差异或是新文件"))])),[[U,E.value]]),a("div",ht,[t(m,{icon:S(Ee),onClick:i,disabled:L.value<=0||n.value.length===0,circle:""},null,8,["icon","disabled"]),a("span",_t,w(L.value+1)+" / "+w(n.value.length),1),t(m,{icon:S(Re),onClick:H,disabled:L.value>=n.value.length-1||n.value.length===0,circle:""},null,8,["icon","disabled"])])]),_:1},8,["modelValue","title"])])}}}),de=(O,G)=>{const p=O.__vccOpts||O;for(const[y,n]of G)p[y]=n;return p},bt=de(wt,[["__scopeId","data-v-61ea34c7"]]),kt={class:"card"},Ct={class:"commit-options"},$t={class:"commit-mode-toggle"},Vt={class:"no-verify-toggle"},St={key:0,class:"commit-form"},Tt={key:1,class:"standard-commit-form"},xt={class:"standard-commit-header"},jt={class:"scope-container"},Bt={class:"description-container"},Dt={class:"preview-section"},Ot={class:"preview-content"},zt={class:"button-group"},Pt={class:"template-container"},Lt={class:"template-form"},At={class:"template-list"},Nt={class:"template-content"},Mt={class:"template-actions"},Et={class:"template-container"},Rt={class:"template-form"},Ut={class:"template-list"},It={class:"template-content"},Ft={class:"template-actions"},Gt=ce({__name:"CommitForm",emits:["commit-success","push-success"],setup(O,{emit:G}){const p=G,y=l(""),n=l("提交"),h=l("推送到远程"),z=l(!1),P=l(!1),E=l(!1),L=l("提交并推送"),I=l("输入提交信息..."),F=l(""),A=l(!1),J=l("feat"),k=l(""),C=l(""),$=l(""),f=l(""),j=l([]),T=l(!1),N=l(""),R=l([]),_=l(!1),i=l(""),H=l(!1),te=[{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: 构建/工具修改"}];Ve(A,s=>{localStorage.setItem("zen-gitsync-standard-commit",s.toString())}),Ve(H,s=>{localStorage.setItem("zen-gitsync-skip-hooks",s.toString())});const Q=Fe(()=>{if(!A.value)return y.value||F.value;let s=`${J.value||""}`;return k.value&&(s+=`(${k.value})`),s+=`: ${C.value}`,$.value&&(s+=`
4
-
5
- ${$.value}`),f.value&&(s+=`
6
-
7
- ${f.value}`),s});async function X(){try{const e=await(await fetch("/api/config/getConfig")).json();I.value=`输入提交信息 (默认: ${e.defaultCommitMessage})`,F.value=e.defaultCommitMessage||"",e.descriptionTemplates&&Array.isArray(e.descriptionTemplates)&&(j.value=e.descriptionTemplates),e.scopeTemplates&&Array.isArray(e.scopeTemplates)&&(R.value=e.scopeTemplates)}catch(s){console.error("加载配置失败:",s)}}async function ae(){if(!N.value.trim()){c({message:"请输入模板内容",type:"warning"});return}try{if(j.value.includes(N.value)){c({message:"该模板已存在",type:"warning"});return}j.value.push(N.value);const e=await(await fetch("/api/config/save-template",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({template:N.value,type:"description"})})).json();e.success?(c({message:"模板保存成功!",type:"success"}),N.value=""):c({message:"模板保存失败: "+e.error,type:"error"})}catch(s){c({message:"模板保存失败: "+s.message,type:"error"})}}async function ee(){if(!i.value.trim()){c({message:"请输入模板内容",type:"warning"});return}try{if(R.value.includes(i.value)){c({message:"该模板已存在",type:"warning"});return}R.value.push(i.value);const e=await(await fetch("/api/config/save-template",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({template:i.value,type:"scope"})})).json();e.success?(c({message:"作用域模板保存成功!",type:"success"}),i.value=""):c({message:"作用域模板保存失败: "+e.error,type:"error"})}catch(s){c({message:"作用域模板保存失败: "+s.message,type:"error"})}}async function le(s){try{const e=j.value.indexOf(s);e!==-1&&j.value.splice(e,1);const W=await(await fetch("/api/config/delete-template",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({template:s,type:"description"})})).json();W.success?c({message:"模板删除成功!",type:"success"}):c({message:"模板删除失败: "+W.error,type:"error"})}catch(e){c({message:"模板删除失败: "+e.message,type:"error"})}}async function oe(s){try{const e=R.value.indexOf(s);e!==-1&&R.value.splice(e,1);const W=await(await fetch("/api/config/delete-template",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({template:s,type:"scope"})})).json();W.success?c({message:"作用域模板删除成功!",type:"success"}):c({message:"作用域模板删除失败: "+W.error,type:"error"})}catch(e){c({message:"作用域模板删除失败: "+e.message,type:"error"})}}function D(s){C.value=s,T.value=!1}function pe(s){k.value=s,_.value=!1}function ie(){T.value=!0}function fe(){_.value=!0}function u(){const s=localStorage.getItem("zen-gitsync-standard-commit");s!==null&&(A.value=s==="true");const e=localStorage.getItem("zen-gitsync-skip-hooks");e!==null&&(H.value=e==="true")}async function o(){const s=Q.value;if(!s&&A.value&&!C.value){c({message:"请输入提交描述",type:"warning"});return}try{z.value=!0,n.value="提交中...";const x=await(await fetch("/api/add",{method:"POST"})).json();if(!x.success){c({message:"添加文件失败: "+x.error,type:"error"});return}const M=await(await fetch("/api/commit",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({message:s,hasNewlines:s.includes(`
8
- `),noVerify:H.value})})).json();M.success?(A.value?(C.value="",$.value="",f.value=""):y.value="",c({message:"提交成功!",type:"success"}),p("commit-success")):c({message:"提交失败: "+M.error,type:"error"})}catch(e){c({message:"提交失败: "+e.message,type:"error"})}finally{z.value=!1,n.value="提交"}}async function V(){try{P.value=!0,h.value="推送中...";const e=await(await fetch("/api/push",{method:"POST"})).json();e.success?(c({message:"推送成功!",type:"success"}),p("push-success")):c({message:"推送失败: "+e.error,type:"error"})}catch(s){c({message:"推送失败: "+s.message,type:"error"})}finally{P.value=!1,h.value="推送到远程"}}async function m(){const s=Q.value;if(!s&&A.value&&!C.value){c({message:"请输入提交描述",type:"warning"});return}try{E.value=!0,L.value="处理中...";const x=await(await fetch("/api/add",{method:"POST"})).json();if(!x.success){c({message:"添加文件失败: "+x.error,type:"error"});return}const M=await(await fetch("/api/commit",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({message:s,hasNewlines:s.includes(`
9
- `),noVerify:H.value})})).json();if(!M.success){c({message:"提交失败: "+M.error,type:"error"});return}A.value?(C.value="",$.value="",f.value=""):y.value="";const b=await(await fetch("/api/push",{method:"POST"})).json();b.success?(y.value="",c({message:"提交并推送成功!",type:"success"}),p("commit-success"),p("push-success")):c({message:"推送失败: "+b.error,type:"error"})}catch(e){c({message:"操作失败: "+e.message,type:"error"})}finally{E.value=!1,L.value="提交并推送"}}return ue(()=>{X(),u()}),(s,e)=>{const x=Ge,W=ze,M=_e,U=se,b=Le,re=Pe,we=Je,be=We,ke=He,Ce=he;return d(),g("div",kt,[e[21]||(e[21]=a("h2",null,"提交更改",-1)),a("div",Ct,[a("div",$t,[t(x,{modelValue:A.value,"onUpdate:modelValue":e[0]||(e[0]=v=>A.value=v),"active-text":"标准化提交","inactive-text":"普通提交"},null,8,["modelValue"])]),a("div",Vt,[t(W,{content:"跳过 Git 钩子检查 (--no-verify)",placement:"top"},{default:r(()=>[t(x,{modelValue:H.value,"onUpdate:modelValue":e[1]||(e[1]=v=>H.value=v),"active-text":"跳过钩子 (--no-verify)"},null,8,["modelValue"])]),_:1})])]),A.value?(d(),g("div",Tt,[a("div",xt,[t(re,{modelValue:J.value,"onUpdate:modelValue":e[3]||(e[3]=v=>J.value=v),placeholder:"提交类型",class:"type-select",clearable:""},{default:r(()=>[(d(),g(K,null,Y(te,v=>t(b,{key:v.value,label:v.label,value:v.value},null,8,["label","value"])),64))]),_:1},8,["modelValue"]),a("div",jt,[t(M,{modelValue:k.value,"onUpdate:modelValue":e[4]||(e[4]=v=>k.value=v),placeholder:"作用域(可选)",class:"scope-input",clearable:""},null,8,["modelValue"]),t(U,{type:"primary",icon:S(Se),circle:"",size:"small",class:"settings-button",onClick:fe},null,8,["icon"])]),a("div",Bt,[t(M,{modelValue:C.value,"onUpdate:modelValue":e[5]||(e[5]=v=>C.value=v),placeholder:"简短描述(必填)",class:"description-input",clearable:""},null,8,["modelValue"]),t(U,{type:"primary",icon:S(Se),circle:"",size:"small",class:"settings-button",onClick:ie},null,8,["icon"])])]),t(M,{modelValue:$.value,"onUpdate:modelValue":e[6]||(e[6]=v=>$.value=v),type:"textarea",rows:4,placeholder:"正文(可选):详细描述本次提交的内容和原因",class:"body-input",clearable:""},null,8,["modelValue"]),t(M,{modelValue:f.value,"onUpdate:modelValue":e[7]||(e[7]=v=>f.value=v),placeholder:"页脚(可选):如 Closes #123",class:"footer-input",clearable:""},null,8,["modelValue"]),a("div",Dt,[e[12]||(e[12]=a("div",{class:"preview-title"},"预览:",-1)),a("pre",Ot,w(Q.value),1)]),t(U,{type:"primary",onClick:o,loading:z.value},{default:r(()=>[B(w(n.value),1)]),_:1},8,["loading"])])):(d(),g("div",St,[t(M,{modelValue:y.value,"onUpdate:modelValue":e[2]||(e[2]=v=>y.value=v),placeholder:I.value,clearable:""},null,8,["modelValue","placeholder"]),t(U,{type:"primary",onClick:o,loading:z.value},{default:r(()=>[B(w(n.value),1)]),_:1},8,["loading"])])),a("div",zt,[t(U,{type:"success",onClick:V,loading:P.value},{default:r(()=>[B(w(h.value),1)]),_:1},8,["loading"]),t(U,{type:"warning",onClick:m,loading:E.value},{default:r(()=>[B(w(L.value),1)]),_:1},8,["loading"])]),t(Ce,{title:"简短描述模板设置",modelValue:T.value,"onUpdate:modelValue":e[9]||(e[9]=v=>T.value=v),width:"80vw",style:{height:"80vh"}},{default:r(()=>[a("div",Pt,[a("div",Lt,[t(M,{modelValue:N.value,"onUpdate:modelValue":e[8]||(e[8]=v=>N.value=v),placeholder:"输入新模板内容",class:"template-input",clearable:""},null,8,["modelValue"]),t(U,{type:"primary",onClick:ae,disabled:!N.value.trim()},{default:r(()=>e[13]||(e[13]=[B("添加模板")])),_:1},8,["disabled"])]),a("div",At,[e[16]||(e[16]=a("h3",null,"已保存模板",-1)),j.value.length===0?(d(),Z(we,{key:0,description:"暂无保存的模板"})):q("",!0),(d(!0),g(K,null,Y(j.value,(v,ve)=>(d(),Z(ke,{key:ve,class:"template-item"},{default:r(()=>[t(be,{justify:"space-between",align:"middle",style:{width:"100%"}},{default:r(()=>[a("div",Nt,w(v),1),a("div",Mt,[t(U,{type:"primary",size:"small",onClick:me=>D(v)},{default:r(()=>e[14]||(e[14]=[B("使用")])),_:2},1032,["onClick"]),t(U,{type:"danger",size:"small",onClick:me=>le(v)},{default:r(()=>e[15]||(e[15]=[B("删除")])),_:2},1032,["onClick"])])]),_:2},1024)]),_:2},1024))),128))])])]),_:1},8,["modelValue"]),t(Ce,{title:"作用域模板设置",modelValue:_.value,"onUpdate:modelValue":e[11]||(e[11]=v=>_.value=v),width:"80%",style:{height:"80vh"}},{default:r(()=>[a("div",Et,[a("div",Rt,[t(M,{modelValue:i.value,"onUpdate:modelValue":e[10]||(e[10]=v=>i.value=v),placeholder:"输入新作用域模板",class:"template-input",clearable:""},null,8,["modelValue"]),t(U,{type:"primary",onClick:ee,disabled:!i.value.trim()},{default:r(()=>e[17]||(e[17]=[B("添加模板")])),_:1},8,["disabled"])]),a("div",Ut,[e[20]||(e[20]=a("h3",null,"已保存作用域",-1)),R.value.length===0?(d(),Z(we,{key:0,description:"暂无保存的作用域"})):q("",!0),(d(!0),g(K,null,Y(R.value,(v,ve)=>(d(),Z(ke,{key:ve,class:"template-item"},{default:r(()=>[t(be,{justify:"space-between",align:"middle",style:{width:"100%"}},{default:r(()=>[a("div",It,w(v),1),a("div",Ft,[t(U,{type:"primary",size:"small",onClick:me=>pe(v)},{default:r(()=>e[18]||(e[18]=[B("使用")])),_:2},1032,["onClick"]),t(U,{type:"danger",size:"small",onClick:me=>oe(v)},{default:r(()=>e[19]||(e[19]=[B("删除")])),_:2},1032,["onClick"])])]),_:2},1024)]),_:2},1024))),128))])])]),_:1},8,["modelValue"])])}}}),Jt=de(Gt,[["__scopeId","data-v-00e49634"]]),Ht={class:"card"},Wt={class:"log-header"},Zt={class:"log-actions"},qt={key:0},Kt={key:1},Qt={key:0,class:"graph-view"},Xt={key:0,class:"commit-count"},Yt={key:1},es={key:0,class:"commit-count"},ts={key:0,class:"branch-container"};function Te(O){return O=O.trim().replace(/^HEAD\s*->\s*/,""),O=O.replace(/^origin\//,""),O=O.replace(/^tag:\s*/,""),O.trim()}function ss(O){return O.includes("HEAD")?"success":O.includes("tag:")?"warning":O.includes("origin/")?"info":"primary"}const as=ce({__name:"LogList",setup(O,{expose:G}){const p=l([]),y=l(""),n=l(!1),h=l(!1),z=l(0),P=l(!0),E=l(null);async function L(k=!1){try{n.value=!0,h.value=k;const $=await fetch(k?"/api/log?all=true&graph=true":"/api/log?graph=true");p.value=await $.json(),z.value=p.value.length,y.value="",P.value&&setTimeout(I,0)}catch(C){y.value="加载提交历史失败: "+C.message}finally{n.value=!1}}async function I(){if(!E.value||p.value.length===0)return;E.value.innerHTML="";const k=await fetch("/api/branch"),{branch:C}=await k.json(),$=Ke(E.value,{orientation:"vertical-reverse",template:"metro",author:"提交者 <committer@example.com>"}),f={},j=$.branch(C||"main");f[C||"main"]=j,p.value.forEach(T=>{let N=j;if(T.branch){const R=Te(T.branch.split(",")[0]);f[R]||(f[R]=$.branch(R)),N=f[R]}N.commit({hash:T.hash,subject:T.message,author:`${T.author} <${T.email}>`})})}function F(){P.value=!P.value,P.value&&p.value.length>0&&setTimeout(I,0)}function A(){L(!h.value)}ue(()=>{L()});const J=()=>L(h.value);return G({refreshLog:J}),(k,C)=>{const $=De;return d(),g("div",Ht,[a("div",Wt,[C[1]||(C[1]=a("h2",null,"提交历史",-1)),a("div",Zt,[t(S(se),{type:"primary",size:"small",onClick:F},{default:r(()=>[B(w(P.value?"表格视图":"图表视图"),1)]),_:1}),t(S(se),{type:"primary",size:"small",onClick:A,loading:n.value},{default:r(()=>[B(w(h.value?"显示最近100条":"显示所有提交"),1)]),_:1},8,["loading"]),t(S(se),{icon:S(Oe),circle:"",size:"small",onClick:C[0]||(C[0]=f=>J()),loading:n.value},null,8,["icon","loading"])])]),y.value?(d(),g("div",qt,w(y.value),1)):(d(),g("div",Kt,[P.value?(d(),g("div",Qt,[p.value.length>0?(d(),g("div",Xt," 显示 "+w(p.value.length)+" 条提交记录 "+w(h.value?"(全部)":"(最近100条)"),1)):q("",!0),a("div",{ref_key:"graphContainer",ref:E,class:"graph-container"},null,512)])):(d(),g("div",Yt,[p.value.length>0?(d(),g("div",es," 显示 "+w(p.value.length)+" 条提交记录 "+w(h.value?"(全部)":"(最近100条)"),1)):q("",!0),ye((d(),Z(S(qe),{data:p.value,style:{width:"100%"},stripe:"",border:""},{default:r(()=>[t(S(ne),{prop:"hash",label:"提交哈希",width:"100",resizable:""}),t(S(ne),{prop:"date",label:"日期",width:"180",resizable:""}),t(S(ne),{label:"作者",width:"200",resizable:""},{default:r(f=>[B(w(f.row.author)+" <"+w(f.row.email)+"> ",1)]),_:1}),t(S(ne),{label:"分支",width:"180",resizable:""},{default:r(f=>[f.row.branch?(d(),g("div",ts,[(d(!0),g(K,null,Y(f.row.branch.split(","),(j,T)=>(d(),Z(S(Ze),{key:T,size:"small",type:ss(j),class:"branch-tag"},{default:r(()=>[B(w(Te(j)),1)]),_:2},1032,["type"]))),128))])):q("",!0)]),_:1}),t(S(ne),{prop:"message",label:"提交信息","min-width":"250"})]),_:1},8,["data"])),[[$,n.value]])]))]))])}}}),ls=de(as,[["__scopeId","data-v-c6b721c7"]]),os="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",ns={class:"main-header"},is={class:"header-left"},rs=["src"],cs={class:"header-info"},us={key:0,id:"user-info"},ds={class:"user-name"},ps={class:"user-email"},fs={class:"container"},vs={class:"layout-container"},ms={class:"left-panel"},gs={class:"right-panel"},ys={class:"dialog-footer"},hs={class:"main-footer"},_s={key:0,class:"branch-info"},ws=ce({__name:"App",setup(O){const G=l(""),p=l(null),y=l(null),n=l(""),h=l(""),z=l(""),P=l([]),E=l(!1);async function L(){try{const i=await(await fetch("/api/config/getConfig")).json();G.value=`默认提交信息: ${i.defaultCommitMessage}`}catch(_){console.error("加载配置失败:",_)}}async function I(){try{const i=await(await fetch("/api/branch")).json();i.branch&&(n.value=i.branch)}catch(_){console.error("获取分支信息失败:",_)}}async function F(){try{const i=await(await fetch("/api/branches")).json();i.branches&&Array.isArray(i.branches)&&(P.value=i.branches)}catch(_){console.error("获取所有分支信息失败:",_)}}async function A(_){console.log("切换到分支:",_);try{E.value=!0;const H=await(await fetch("/api/checkout",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({branch:_})})).json();H.success?(c({message:`已切换到分支: ${_}`,type:"success"}),I(),y.value&&y.value.refreshStatus(),p.value&&p.value.refreshLog()):(c({message:`切换分支失败: ${H.error}`,type:"error"}),n.value=n.value)}catch(i){c({message:`切换分支失败: ${i.message}`,type:"error"}),n.value=n.value}finally{E.value=!1}}async function J(){try{const i=await(await fetch("/api/user-info")).json();i.name&&i.email&&(h.value=i.name,z.value=i.email)}catch(_){console.error("获取用户信息失败:",_)}}ue(()=>{L(),I(),F(),J()});function k(){p.value&&p.value.refreshLog(),y.value&&y.value.refreshStatus()}function C(){p.value&&p.value.refreshLog(),y.value&&y.value.refreshStatus(),I()}const $=l(!1),f=l(""),j=l(""),T=l(!1);async function N(){if(!f.value.trim()){c({message:"分支名称不能为空",type:"warning"});return}try{T.value=!0;const i=await(await fetch("/api/create-branch",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({newBranchName:f.value,baseBranch:j.value||n.value})})).json();i.success?(c({message:`已创建并切换到分支: ${f.value}`,type:"success"}),$.value=!1,f.value="",I(),F(),y.value&&y.value.refreshStatus(),p.value&&p.value.refreshLog()):c({message:`创建分支失败: ${i.error}`,type:"error"})}catch(_){c({message:`创建分支失败: ${_.message}`,type:"error"})}finally{T.value=!1}}function R(){j.value=n.value,$.value=!0}return(_,i)=>{const H=_e,te=Be,Q=Le,X=Pe,ae=je,ee=se,le=he,oe=xe;return d(),g(K,null,[a("header",ns,[a("div",is,[a("img",{src:S(os),alt:"Zen GitSync Logo",class:"logo"},null,8,rs),i[5]||(i[5]=a("h1",null,"Zen GitSync UI",-1))]),a("div",cs,[h.value&&z.value?(d(),g("div",us,[i[6]||(i[6]=a("span",{class:"user-label"},"用户:",-1)),a("span",ds,w(h.value),1),a("span",ps,"<"+w(z.value)+">",1)])):q("",!0)])]),a("div",fs,[a("div",vs,[a("div",ms,[t(bt,{ref_key:"gitStatusRef",ref:y},null,512)]),a("div",gs,[t(Jt,{onCommitSuccess:k,onPushSuccess:C}),t(ls,{ref_key:"logListRef",ref:p},null,512)]),t(le,{modelValue:$.value,"onUpdate:modelValue":i[3]||(i[3]=D=>$.value=D),title:"创建新分支",width:"30%","destroy-on-close":""},{footer:r(()=>[a("span",ys,[t(ee,{onClick:i[2]||(i[2]=D=>$.value=!1)},{default:r(()=>i[7]||(i[7]=[B("取消")])),_:1}),t(ee,{type:"primary",onClick:N,loading:T.value},{default:r(()=>i[8]||(i[8]=[B(" 创建 ")])),_:1},8,["loading"])])]),default:r(()=>[t(ae,{model:{newBranchName:f.value,selectedBaseBranch:j.value}},{default:r(()=>[t(te,{label:"新分支名称"},{default:r(()=>[t(H,{modelValue:f.value,"onUpdate:modelValue":i[0]||(i[0]=D=>f.value=D),placeholder:"请输入新分支名称"},null,8,["modelValue"])]),_:1}),t(te,{label:"基于分支"},{default:r(()=>[t(X,{modelValue:j.value,"onUpdate:modelValue":i[1]||(i[1]=D=>j.value=D),placeholder:"选择基础分支",style:{width:"100%"}},{default:r(()=>[(d(!0),g(K,null,Y(P.value,D=>(d(),Z(Q,{key:D,label:D,value:D},null,8,["label","value"]))),128))]),_:1},8,["modelValue"])]),_:1})]),_:1},8,["model"])]),_:1},8,["modelValue"])])]),a("footer",hs,[n.value?(d(),g("div",_s,[i[9]||(i[9]=a("span",{class:"branch-label"},"当前分支:",-1)),t(X,{modelValue:n.value,"onUpdate:modelValue":i[4]||(i[4]=D=>n.value=D),size:"small",onChange:A,loading:E.value,class:"branch-select"},{default:r(()=>[(d(!0),g(K,null,Y(P.value,D=>(d(),Z(Q,{key:D,label:D,value:D},null,8,["label","value"]))),128))]),_:1},8,["modelValue","loading"]),t(ee,{type:"primary",size:"small",onClick:R,style:{"margin-left":"5px"}},{default:r(()=>[t(oe,null,{default:r(()=>[t(S(Qe))]),_:1})]),_:1})])):q("",!0),i[10]||(i[10]=a("div",{class:"footer-right"},null,-1))])],64)}}}),bs=de(ws,[["__scopeId","data-v-93cc73d5"]]),ks=Xe(bs);ks.mount("#app");