zen-gitsync 2.0.1 → 2.0.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/src/ui/client/package.json +1 -0
- package/src/ui/client/src/App.vue +174 -171
- package/src/ui/client/src/components/CommitForm.vue +591 -290
- package/src/ui/client/src/components/GitStatus.vue +528 -110
- package/src/ui/client/src/components/LogList.vue +351 -85
- package/src/ui/client/src/main.ts +3 -0
- package/src/ui/client/src/stores/gitLogStore.ts +464 -0
- package/src/ui/client/src/stores/gitStore.ts +216 -0
- package/src/ui/client/stats.html +1 -1
- package/src/ui/public/assets/index-D5irnfho.css +1 -0
- package/src/ui/public/assets/index-DBck3u67.js +8 -0
- package/src/ui/public/assets/vendor-CdJ34PvS.js +45 -0
- package/src/ui/public/index.html +3 -3
- package/src/ui/server/index.js +260 -4
- package/src/ui/public/assets/index-BcTk2R6G.js +0 -9
- package/src/ui/public/assets/index-ChUZ1vPG.css +0 -1
- package/src/ui/public/assets/vendor-BAXrrwNU.js +0 -41
package/src/ui/public/index.html
CHANGED
|
@@ -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-
|
|
9
|
-
<link rel="modulepreload" crossorigin href="/assets/vendor-
|
|
8
|
+
<script type="module" crossorigin src="/assets/index-DBck3u67.js"></script>
|
|
9
|
+
<link rel="modulepreload" crossorigin href="/assets/vendor-CdJ34PvS.js">
|
|
10
10
|
<link rel="stylesheet" crossorigin href="/assets/vendor-Dp0FkvMe.css">
|
|
11
|
-
<link rel="stylesheet" crossorigin href="/assets/index-
|
|
11
|
+
<link rel="stylesheet" crossorigin href="/assets/index-D5irnfho.css">
|
|
12
12
|
</head>
|
|
13
13
|
<body>
|
|
14
14
|
<div id="app"></div>
|
package/src/ui/server/index.js
CHANGED
|
@@ -5,6 +5,9 @@ import path from 'path';
|
|
|
5
5
|
import { execGitCommand } from '../../utils/index.js';
|
|
6
6
|
import open from 'open';
|
|
7
7
|
import config from '../../config.js';
|
|
8
|
+
import chalk from 'chalk';
|
|
9
|
+
import fs from 'fs/promises';
|
|
10
|
+
import os from 'os';
|
|
8
11
|
// import { Server } from 'socket.io';
|
|
9
12
|
// import { exec } from 'child_process';
|
|
10
13
|
|
|
@@ -20,6 +23,13 @@ async function startUIServer() {
|
|
|
20
23
|
// 添加全局中间件来解析JSON请求体
|
|
21
24
|
app.use(express.json());
|
|
22
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
|
+
|
|
23
33
|
// // 启动前端Vue应用
|
|
24
34
|
// const clientPath = path.join(__dirname, '../client');
|
|
25
35
|
// console.log(`正在启动前端应用,路径: ${clientPath}`);
|
|
@@ -185,6 +195,103 @@ async function startUIServer() {
|
|
|
185
195
|
}
|
|
186
196
|
});
|
|
187
197
|
|
|
198
|
+
// 新增切换工作目录接口
|
|
199
|
+
app.post('/api/change_directory', async (req, res) => {
|
|
200
|
+
try {
|
|
201
|
+
|
|
202
|
+
const { path } = req.body;
|
|
203
|
+
|
|
204
|
+
if (!path) {
|
|
205
|
+
return res.status(400).json({ success: false, error: '目录路径不能为空' });
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
try {
|
|
209
|
+
process.chdir(path);
|
|
210
|
+
const newDirectory = process.cwd();
|
|
211
|
+
|
|
212
|
+
// 检查新目录是否是Git仓库
|
|
213
|
+
try {
|
|
214
|
+
await execGitCommand('git rev-parse --is-inside-work-tree');
|
|
215
|
+
res.json({
|
|
216
|
+
success: true,
|
|
217
|
+
directory: newDirectory,
|
|
218
|
+
isGitRepo: true
|
|
219
|
+
});
|
|
220
|
+
} catch (error) {
|
|
221
|
+
res.json({
|
|
222
|
+
success: true,
|
|
223
|
+
directory: newDirectory,
|
|
224
|
+
isGitRepo: false,
|
|
225
|
+
warning: '新目录不是一个Git仓库'
|
|
226
|
+
});
|
|
227
|
+
}
|
|
228
|
+
} catch (error) {
|
|
229
|
+
res.status(400).json({
|
|
230
|
+
success: false,
|
|
231
|
+
error: `切换到目录 "${path}" 失败: ${error.message}`
|
|
232
|
+
});
|
|
233
|
+
}
|
|
234
|
+
} catch (error) {
|
|
235
|
+
res.status(500).json({ error: error.message });
|
|
236
|
+
}
|
|
237
|
+
});
|
|
238
|
+
|
|
239
|
+
// 获取目录内容(用于浏览目录)
|
|
240
|
+
app.get('/api/browse_directory', async (req, res) => {
|
|
241
|
+
try {
|
|
242
|
+
|
|
243
|
+
// 获取要浏览的目录路径,如果没有提供,则使用当前目录
|
|
244
|
+
const directoryPath = req.query.path || process.cwd();
|
|
245
|
+
|
|
246
|
+
try {
|
|
247
|
+
// 读取目录内容
|
|
248
|
+
const items = await fs.readdir(directoryPath, { withFileTypes: true });
|
|
249
|
+
|
|
250
|
+
// 分离文件夹和文件
|
|
251
|
+
const directories = [];
|
|
252
|
+
const files = [];
|
|
253
|
+
|
|
254
|
+
for (const item of items) {
|
|
255
|
+
const fullPath = path.join(directoryPath, item.name);
|
|
256
|
+
if (item.isDirectory()) {
|
|
257
|
+
directories.push({
|
|
258
|
+
name: item.name,
|
|
259
|
+
path: fullPath,
|
|
260
|
+
type: 'directory'
|
|
261
|
+
});
|
|
262
|
+
} else if (item.isFile()) {
|
|
263
|
+
files.push({
|
|
264
|
+
name: item.name,
|
|
265
|
+
path: fullPath,
|
|
266
|
+
type: 'file'
|
|
267
|
+
});
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
// 优先显示目录,然后是文件,都按字母排序
|
|
272
|
+
directories.sort((a, b) => a.name.localeCompare(b.name));
|
|
273
|
+
files.sort((a, b) => a.name.localeCompare(b.name));
|
|
274
|
+
|
|
275
|
+
// 获取父目录路径
|
|
276
|
+
const parentPath = path.dirname(directoryPath);
|
|
277
|
+
|
|
278
|
+
res.json({
|
|
279
|
+
success: true,
|
|
280
|
+
currentPath: directoryPath,
|
|
281
|
+
parentPath: parentPath !== directoryPath ? parentPath : null,
|
|
282
|
+
items: [...directories, ...files]
|
|
283
|
+
});
|
|
284
|
+
} catch (error) {
|
|
285
|
+
res.status(400).json({
|
|
286
|
+
success: false,
|
|
287
|
+
error: `无法读取目录 "${directoryPath}": ${error.message}`
|
|
288
|
+
});
|
|
289
|
+
}
|
|
290
|
+
} catch (error) {
|
|
291
|
+
res.status(500).json({ error: error.message });
|
|
292
|
+
}
|
|
293
|
+
});
|
|
294
|
+
|
|
188
295
|
// 获取配置
|
|
189
296
|
app.get('/api/config/getConfig', async (req, res) => {
|
|
190
297
|
try {
|
|
@@ -277,6 +384,53 @@ async function startUIServer() {
|
|
|
277
384
|
}
|
|
278
385
|
})
|
|
279
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
|
+
|
|
280
434
|
// 提交更改
|
|
281
435
|
app.post('/api/commit', express.json(), async (req, res) => {
|
|
282
436
|
try {
|
|
@@ -341,8 +495,11 @@ async function startUIServer() {
|
|
|
341
495
|
// 获取日志
|
|
342
496
|
app.get('/api/log', async (req, res) => {
|
|
343
497
|
try {
|
|
344
|
-
// 获取请求参数中的数量限制,默认为
|
|
345
|
-
const limit = req.query.all === 'true' ? '' : '-n
|
|
498
|
+
// 获取请求参数中的数量限制,默认为30
|
|
499
|
+
const limit = req.query.all === 'true' ? '' : '-n 30';
|
|
500
|
+
|
|
501
|
+
// graph参数保留但不做特殊处理,避免前端代码重复调用API
|
|
502
|
+
// 由前端统一使用该接口
|
|
346
503
|
|
|
347
504
|
// 修改 git log 命令,添加 %ae 参数来获取作者邮箱
|
|
348
505
|
const { stdout } = await execGitCommand(`git log --all --pretty=format:"%h|%an|%ae|%ad|%s|%D" --date=short ${limit}`);
|
|
@@ -382,6 +539,97 @@ async function startUIServer() {
|
|
|
382
539
|
}
|
|
383
540
|
});
|
|
384
541
|
|
|
542
|
+
// 撤回文件修改
|
|
543
|
+
app.post('/api/revert_file', async (req, res) => {
|
|
544
|
+
try {
|
|
545
|
+
const { filePath } = req.body;
|
|
546
|
+
|
|
547
|
+
if (!filePath) {
|
|
548
|
+
return res.status(400).json({
|
|
549
|
+
success: false,
|
|
550
|
+
error: '缺少文件路径参数'
|
|
551
|
+
});
|
|
552
|
+
}
|
|
553
|
+
|
|
554
|
+
// 检查文件状态:未跟踪文件需要删除,修改文件需要恢复
|
|
555
|
+
const { stdout: statusOutput } = await execGitCommand(`git status --porcelain -- "${filePath}"`);
|
|
556
|
+
|
|
557
|
+
// 未跟踪的文件 (??), 需要删除它
|
|
558
|
+
if (statusOutput.startsWith('??')) {
|
|
559
|
+
try {
|
|
560
|
+
await fs.unlink(filePath);
|
|
561
|
+
return res.json({ success: true, message: '未跟踪的文件已删除' });
|
|
562
|
+
} catch (error) {
|
|
563
|
+
return res.status(500).json({
|
|
564
|
+
success: false,
|
|
565
|
+
error: `删除文件失败: ${error.message}`
|
|
566
|
+
});
|
|
567
|
+
}
|
|
568
|
+
}
|
|
569
|
+
// 已暂存的文件,先取消暂存
|
|
570
|
+
else if (statusOutput.startsWith('A ') || statusOutput.startsWith('M ') || statusOutput.startsWith('D ')) {
|
|
571
|
+
// 先取消暂存
|
|
572
|
+
await execGitCommand(`git reset HEAD -- "${filePath}"`);
|
|
573
|
+
}
|
|
574
|
+
|
|
575
|
+
// 已修改文件,取消所有本地修改
|
|
576
|
+
if (statusOutput) {
|
|
577
|
+
await execGitCommand(`git checkout -- "${filePath}"`);
|
|
578
|
+
return res.json({ success: true, message: '文件修改已撤回' });
|
|
579
|
+
} else {
|
|
580
|
+
return res.status(400).json({
|
|
581
|
+
success: false,
|
|
582
|
+
error: '文件没有修改或不存在'
|
|
583
|
+
});
|
|
584
|
+
}
|
|
585
|
+
} catch (error) {
|
|
586
|
+
console.error('撤回文件修改失败:', error);
|
|
587
|
+
res.status(500).json({
|
|
588
|
+
success: false,
|
|
589
|
+
error: `撤回文件修改失败: ${error.message}`
|
|
590
|
+
});
|
|
591
|
+
}
|
|
592
|
+
});
|
|
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
|
+
|
|
385
633
|
// Socket.io 实时更新
|
|
386
634
|
// io.on('connection', (socket) => {
|
|
387
635
|
// console.log('客户端已连接');
|
|
@@ -405,7 +653,11 @@ async function startUIServer() {
|
|
|
405
653
|
// 启动服务器
|
|
406
654
|
const PORT = 3000;
|
|
407
655
|
httpServer.listen(PORT, () => {
|
|
408
|
-
console.log(
|
|
656
|
+
console.log(chalk.green('======================================'));
|
|
657
|
+
console.log(chalk.green(` Zen GitSync 服务器已启动`));
|
|
658
|
+
console.log(chalk.green(` 访问地址: http://localhost:${PORT}`));
|
|
659
|
+
console.log(chalk.green(` 启动时间: ${new Date().toLocaleString()}`));
|
|
660
|
+
console.log(chalk.green('======================================'));
|
|
409
661
|
open(`http://localhost:${PORT}`);
|
|
410
662
|
}).on('error', async (err) => {
|
|
411
663
|
if (err.code === 'EADDRINUSE') {
|
|
@@ -415,7 +667,11 @@ async function startUIServer() {
|
|
|
415
667
|
try {
|
|
416
668
|
await new Promise((resolve, reject) => {
|
|
417
669
|
httpServer.listen(newPort, () => {
|
|
418
|
-
console.log(
|
|
670
|
+
console.log(chalk.green('======================================'));
|
|
671
|
+
console.log(chalk.green(` Zen GitSync 服务器已启动`));
|
|
672
|
+
console.log(chalk.green(` 访问地址: http://localhost:${newPort}`));
|
|
673
|
+
console.log(chalk.green(` 启动时间: ${new Date().toLocaleString()}`));
|
|
674
|
+
console.log(chalk.green('======================================'));
|
|
419
675
|
open(`http://localhost:${newPort}`);
|
|
420
676
|
resolve();
|
|
421
677
|
}).on('error', (e) => {
|
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
import{d as ee,r as o,o as te,c as y,a as m,b as l,e as H,f as s,E as he,w as u,u as x,g as Be,t as _,h as K,i as Oe,F as J,j as q,k as re,l as ye,v as _e,m as Le,n as Ne,p as r,q as Ae,s as fe,x as De,y as Ee,z as Me,A as we,B as D,C as be,D as ke,G as ve,H as G,I as Pe,J as Re,K as ze,L as Ie,M as Q,N as Ue,O as Fe,P as Ge,Q as He,R as Je,S as We,T as qe}from"./vendor-BAXrrwNU.js";(function(){const E=document.createElement("link").relList;if(E&&E.supports&&E.supports("modulepreload"))return;for(const a of document.querySelectorAll('link[rel="modulepreload"]'))v(a);new MutationObserver(a=>{for(const g of a)if(g.type==="childList")for(const T of g.addedNodes)T.tagName==="LINK"&&T.rel==="modulepreload"&&v(T)}).observe(document,{childList:!0,subtree:!0});function d(a){const g={};return a.integrity&&(g.integrity=a.integrity),a.referrerPolicy&&(g.referrerPolicy=a.referrerPolicy),a.crossOrigin==="use-credentials"?g.credentials="include":a.crossOrigin==="anonymous"?g.credentials="omit":g.credentials="same-origin",g}function v(a){if(a.ep)return;a.ep=!0;const g=d(a);fetch(a.href,g)}})();const Ke={class:"card"},Ze={class:"current-directory"},Qe={class:"status-header"},Xe={class:"status-box"},Ye={key:0,class:"file-list"},et=["onClick"],tt={class:"file-type"},st={class:"file-path"},at={class:"diff-content"},lt=["innerHTML"],ot={key:1,class:"no-diff"},nt={class:"file-navigation"},it={class:"file-counter"};function rt(w){return w==="added"?"新增":w==="modified"?"修改":w==="deleted"?"删除":w==="untracked"?"未跟踪":"其它"}const ct=ee({__name:"GitStatus",setup(w,{expose:E}){const d=o("加载中..."),v=o(!1),a=o([]),g=o(""),T=o(""),j=o(!1),A=o(!1),B=o(-1);function R(c){if(c===void 0)return;const f=c.split(`
|
|
2
|
-
`),b=[];for(const n of f){const t=n.match(/^([ MADRCU\?]{2})\s+(.+)$/);if(t){let V="";const C=t[1].trim();C==="M"||C==="MM"||C==="AM"||C==="RM"?V="modified":C==="A"||C==="AA"?V="added":C==="D"||C==="AD"||C==="DA"?V="deleted":C==="??"?V="untracked":V="other",b.push({path:t[2],type:V})}}a.value=b}const z=o("");async function L(){try{v.value=!0;const f=await(await fetch("/api/current_directory")).json();if(z.value=f.directory||"未知目录",f.isGitRepo===!1){d.value="当前目录不是一个Git仓库",a.value=[],r.warning("当前目录不是一个Git仓库");return}const n=await(await fetch("/api/status")).json();d.value=n.status;const V=await(await fetch("/api/status_porcelain")).json();R(V.status),r({message:"Git 状态已刷新",type:"success"})}catch(c){d.value="加载状态失败: "+c.message,a.value=[],r({message:"刷新失败: "+c.message,type:"error"})}finally{v.value=!1}}function I(c){if(!c)return"";const f=c.split(`
|
|
3
|
-
`);function b(n){return n.replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,""").replace(/'/g,"'")}return f.map(n=>{const t=b(n);return n.startsWith("diff --git")?`<div class="diff-header">${t}</div>`:n.startsWith("---")?`<div class="diff-old-file">${t}</div>`:n.startsWith("+++")?`<div class="diff-new-file">${t}</div>`:n.startsWith("@@")?`<div class="diff-hunk-header">${t}</div>`:n.startsWith("+")?`<div class="diff-added">${t}</div>`:n.startsWith("-")?`<div class="diff-removed">${t}</div>`:`<div class="diff-context">${t}</div>`}).join("")}async function N(c){try{A.value=!0,g.value=c,B.value=a.value.findIndex(n=>n.path===c);const b=await(await fetch(`/api/diff?file=${encodeURIComponent(c)}`)).json();T.value=b.diff||"没有变更",j.value=!0}catch(f){r({message:"获取文件差异失败: "+f.message,type:"error"}),T.value="获取差异失败: "+f.message}finally{A.value=!1}}async function k(){if(a.value.length===0||B.value<=0)return;const c=B.value-1,f=a.value[c];await N(f.path)}async function S(){if(a.value.length===0||B.value>=a.value.length-1)return;const c=B.value+1,f=a.value[c];await N(f.path)}function h(c){N(c.path)}async function $(){await L()}return te(()=>{L()}),E({refreshStatus:$}),(c,f)=>{const b=he,n=K,t=re,V=_e;return m(),y("div",Ke,[l("div",Ze,[s(b,null,{default:u(()=>[s(x(Be))]),_:1}),l("span",null,_(z.value),1)]),l("div",Qe,[f[1]||(f[1]=l("h2",null,"Git 状态",-1)),s(n,{type:"primary",icon:x(Oe),circle:"",size:"small",onClick:$,loading:v.value},null,8,["icon","loading"])]),l("div",Xe,_(d.value),1),a.value.length?(m(),y("div",Ye,[(m(!0),y(J,null,q(a.value,C=>(m(),y("div",{key:C.path,class:Ae(["file-item",C.type]),onClick:W=>h(C)},[l("span",tt,_(rt(C.type)),1),l("span",st,_(C.path),1)],10,et))),128))])):H("",!0),s(t,{modelValue:j.value,"onUpdate:modelValue":f[0]||(f[0]=C=>j.value=C),title:`文件差异: ${g.value}`,width:"80%","destroy-on-close":""},{default:u(()=>[ye((m(),y("div",at,[T.value?(m(),y("div",{key:0,innerHTML:I(T.value),class:"diff-formatted"},null,8,lt)):(m(),y("div",ot,"该文件没有差异或是新文件"))])),[[V,A.value]]),l("div",nt,[s(n,{icon:x(Le),onClick:k,disabled:B.value<=0||a.value.length===0,circle:""},null,8,["icon","disabled"]),l("span",it,_(B.value+1)+" / "+_(a.value.length),1),s(n,{icon:x(Ne),onClick:S,disabled:B.value>=a.value.length-1||a.value.length===0,circle:""},null,8,["icon","disabled"])])]),_:1},8,["modelValue","title"])])}}}),se=(w,E)=>{const d=w.__vccOpts||w;for(const[v,a]of E)d[v]=a;return d},ut=se(ct,[["__scopeId","data-v-849f0626"]]),dt={class:"card"},pt={class:"commit-options"},mt={class:"commit-mode-toggle"},ft={class:"no-verify-toggle"},vt={key:0,class:"commit-form"},gt={key:1,class:"standard-commit-form"},ht={class:"standard-commit-header"},yt={class:"scope-container"},_t={class:"description-container"},wt={class:"preview-section"},bt={class:"preview-content"},kt={class:"button-group"},Ct={class:"template-container"},$t={class:"template-form"},Vt={class:"template-list"},St={class:"template-content"},Tt={class:"template-actions"},xt={class:"template-container"},jt={class:"template-form"},Bt={class:"template-list"},Ot={class:"template-content"},Lt={class:"template-actions"},Nt=ee({__name:"CommitForm",emits:["commit-success","push-success"],setup(w,{emit:E}){const d=E,v=o(""),a=o("提交"),g=o("推送到远程"),T=o(!1),j=o(!1),A=o(!1),B=o("提交并推送"),R=o("输入提交信息..."),z=o(""),L=o(!1),I=o("feat"),N=o(""),k=o(""),S=o(""),h=o(""),$=o([]),c=o(!1),f=o(""),b=o([]),n=o(!1),t=o(""),V=o(!1),C=[{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: 构建/工具修改"}];fe(L,i=>{localStorage.setItem("zen-gitsync-standard-commit",i.toString())}),fe(V,i=>{localStorage.setItem("zen-gitsync-skip-hooks",i.toString())});const W=De(()=>{if(!L.value)return v.value||z.value;let i=`${I.value||""}`;return N.value&&(i+=`(${N.value})`),i+=`: ${k.value}`,S.value&&(i+=`
|
|
4
|
-
|
|
5
|
-
${S.value}`),h.value&&(i+=`
|
|
6
|
-
|
|
7
|
-
${h.value}`),i});async function X(){try{const e=await(await fetch("/api/config/getConfig")).json();R.value=`输入提交信息 (默认: ${e.defaultCommitMessage})`,z.value=e.defaultCommitMessage||"",e.descriptionTemplates&&Array.isArray(e.descriptionTemplates)&&($.value=e.descriptionTemplates),e.scopeTemplates&&Array.isArray(e.scopeTemplates)&&(b.value=e.scopeTemplates)}catch(i){console.error("加载配置失败:",i)}}async function ae(){if(!f.value.trim()){r({message:"请输入模板内容",type:"warning"});return}try{if($.value.includes(f.value)){r({message:"该模板已存在",type:"warning"});return}$.value.push(f.value);const e=await(await fetch("/api/config/save-template",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({template:f.value,type:"description"})})).json();e.success?(r({message:"模板保存成功!",type:"success"}),f.value=""):r({message:"模板保存失败: "+e.error,type:"error"})}catch(i){r({message:"模板保存失败: "+i.message,type:"error"})}}async function Z(){if(!t.value.trim()){r({message:"请输入模板内容",type:"warning"});return}try{if(b.value.includes(t.value)){r({message:"该模板已存在",type:"warning"});return}b.value.push(t.value);const e=await(await fetch("/api/config/save-template",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({template:t.value,type:"scope"})})).json();e.success?(r({message:"作用域模板保存成功!",type:"success"}),t.value=""):r({message:"作用域模板保存失败: "+e.error,type:"error"})}catch(i){r({message:"作用域模板保存失败: "+i.message,type:"error"})}}async function le(i){try{const e=$.value.indexOf(i);e!==-1&&$.value.splice(e,1);const F=await(await fetch("/api/config/delete-template",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({template:i,type:"description"})})).json();F.success?r({message:"模板删除成功!",type:"success"}):r({message:"模板删除失败: "+F.error,type:"error"})}catch(e){r({message:"模板删除失败: "+e.message,type:"error"})}}async function oe(i){try{const e=b.value.indexOf(i);e!==-1&&b.value.splice(e,1);const F=await(await fetch("/api/config/delete-template",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({template:i,type:"scope"})})).json();F.success?r({message:"作用域模板删除成功!",type:"success"}):r({message:"作用域模板删除失败: "+F.error,type:"error"})}catch(e){r({message:"作用域模板删除失败: "+e.message,type:"error"})}}function O(i){k.value=i,c.value=!1}function Ce(i){N.value=i,n.value=!1}function $e(){c.value=!0}function Ve(){n.value=!0}function Se(){const i=localStorage.getItem("zen-gitsync-standard-commit");i!==null&&(L.value=i==="true");const e=localStorage.getItem("zen-gitsync-skip-hooks");e!==null&&(V.value=e==="true")}async function ce(){const i=W.value;if(!i&&L.value&&!k.value){r({message:"请输入提交描述",type:"warning"});return}try{T.value=!0,a.value="提交中...";const U=await(await fetch("/api/add",{method:"POST"})).json();if(!U.success){r({message:"添加文件失败: "+U.error,type:"error"});return}const M=await(await fetch("/api/commit",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({message:i,hasNewlines:i.includes(`
|
|
8
|
-
`),noVerify:V.value})})).json();M.success?(L.value?(k.value="",S.value="",h.value=""):v.value="",r({message:"提交成功!",type:"success"}),d("commit-success")):r({message:"提交失败: "+M.error,type:"error"})}catch(e){r({message:"提交失败: "+e.message,type:"error"})}finally{T.value=!1,a.value="提交"}}async function Te(){try{j.value=!0,g.value="推送中...";const e=await(await fetch("/api/push",{method:"POST"})).json();e.success?(r({message:"推送成功!",type:"success"}),d("push-success")):r({message:"推送失败: "+e.error,type:"error"})}catch(i){r({message:"推送失败: "+i.message,type:"error"})}finally{j.value=!1,g.value="推送到远程"}}async function xe(){const i=W.value;if(!i&&L.value&&!k.value){r({message:"请输入提交描述",type:"warning"});return}try{A.value=!0,B.value="处理中...";const U=await(await fetch("/api/add",{method:"POST"})).json();if(!U.success){r({message:"添加文件失败: "+U.error,type:"error"});return}const M=await(await fetch("/api/commit",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({message:i,hasNewlines:i.includes(`
|
|
9
|
-
`),noVerify:V.value})})).json();if(!M.success){r({message:"提交失败: "+M.error,type:"error"});return}L.value?(k.value="",S.value="",h.value=""):v.value="";const Y=await(await fetch("/api/push",{method:"POST"})).json();Y.success?(v.value="",r({message:"提交并推送成功!",type:"success"}),d("commit-success"),d("push-success")):r({message:"推送失败: "+Y.error,type:"error"})}catch(e){r({message:"操作失败: "+e.message,type:"error"})}finally{A.value=!1,B.value="提交并推送"}}return te(()=>{X(),Se()}),(i,e)=>{const U=Ee,F=Me,M=we,P=K,Y=ke,je=be,ue=Pe,de=ze,pe=Re,me=re;return m(),y("div",dt,[e[21]||(e[21]=l("h2",null,"提交更改",-1)),l("div",pt,[l("div",mt,[s(U,{modelValue:L.value,"onUpdate:modelValue":e[0]||(e[0]=p=>L.value=p),"active-text":"标准化提交","inactive-text":"普通提交"},null,8,["modelValue"])]),l("div",ft,[s(F,{content:"跳过 Git 钩子检查 (--no-verify)",placement:"top"},{default:u(()=>[s(U,{modelValue:V.value,"onUpdate:modelValue":e[1]||(e[1]=p=>V.value=p),"active-text":"跳过钩子 (--no-verify)"},null,8,["modelValue"])]),_:1})])]),L.value?(m(),y("div",gt,[l("div",ht,[s(je,{modelValue:I.value,"onUpdate:modelValue":e[3]||(e[3]=p=>I.value=p),placeholder:"提交类型",class:"type-select",clearable:""},{default:u(()=>[(m(),y(J,null,q(C,p=>s(Y,{key:p.value,label:p.label,value:p.value},null,8,["label","value"])),64))]),_:1},8,["modelValue"]),l("div",yt,[s(M,{modelValue:N.value,"onUpdate:modelValue":e[4]||(e[4]=p=>N.value=p),placeholder:"作用域(可选)",class:"scope-input",clearable:""},null,8,["modelValue"]),s(P,{type:"primary",icon:x(ve),circle:"",size:"small",class:"settings-button",onClick:Ve},null,8,["icon"])]),l("div",_t,[s(M,{modelValue:k.value,"onUpdate:modelValue":e[5]||(e[5]=p=>k.value=p),placeholder:"简短描述(必填)",class:"description-input",clearable:""},null,8,["modelValue"]),s(P,{type:"primary",icon:x(ve),circle:"",size:"small",class:"settings-button",onClick:$e},null,8,["icon"])])]),s(M,{modelValue:S.value,"onUpdate:modelValue":e[6]||(e[6]=p=>S.value=p),type:"textarea",rows:4,placeholder:"正文(可选):详细描述本次提交的内容和原因",class:"body-input",clearable:""},null,8,["modelValue"]),s(M,{modelValue:h.value,"onUpdate:modelValue":e[7]||(e[7]=p=>h.value=p),placeholder:"页脚(可选):如 Closes #123",class:"footer-input",clearable:""},null,8,["modelValue"]),l("div",wt,[e[12]||(e[12]=l("div",{class:"preview-title"},"预览:",-1)),l("pre",bt,_(W.value),1)]),s(P,{type:"primary",onClick:ce,loading:T.value},{default:u(()=>[D(_(a.value),1)]),_:1},8,["loading"])])):(m(),y("div",vt,[s(M,{modelValue:v.value,"onUpdate:modelValue":e[2]||(e[2]=p=>v.value=p),placeholder:R.value,clearable:""},null,8,["modelValue","placeholder"]),s(P,{type:"primary",onClick:ce,loading:T.value},{default:u(()=>[D(_(a.value),1)]),_:1},8,["loading"])])),l("div",kt,[s(P,{type:"success",onClick:Te,loading:j.value},{default:u(()=>[D(_(g.value),1)]),_:1},8,["loading"]),s(P,{type:"warning",onClick:xe,loading:A.value},{default:u(()=>[D(_(B.value),1)]),_:1},8,["loading"])]),s(me,{title:"简短描述模板设置",modelValue:c.value,"onUpdate:modelValue":e[9]||(e[9]=p=>c.value=p),width:"80vw",style:{height:"80vh"}},{default:u(()=>[l("div",Ct,[l("div",$t,[s(M,{modelValue:f.value,"onUpdate:modelValue":e[8]||(e[8]=p=>f.value=p),placeholder:"输入新模板内容",class:"template-input",clearable:""},null,8,["modelValue"]),s(P,{type:"primary",onClick:ae,disabled:!f.value.trim()},{default:u(()=>e[13]||(e[13]=[D("添加模板")])),_:1},8,["disabled"])]),l("div",Vt,[e[16]||(e[16]=l("h3",null,"已保存模板",-1)),$.value.length===0?(m(),G(ue,{key:0,description:"暂无保存的模板"})):H("",!0),(m(!0),y(J,null,q($.value,(p,ne)=>(m(),G(pe,{key:ne,class:"template-item"},{default:u(()=>[s(de,{justify:"space-between",align:"middle",style:{width:"100%"}},{default:u(()=>[l("div",St,_(p),1),l("div",Tt,[s(P,{type:"primary",size:"small",onClick:ie=>O(p)},{default:u(()=>e[14]||(e[14]=[D("使用")])),_:2},1032,["onClick"]),s(P,{type:"danger",size:"small",onClick:ie=>le(p)},{default:u(()=>e[15]||(e[15]=[D("删除")])),_:2},1032,["onClick"])])]),_:2},1024)]),_:2},1024))),128))])])]),_:1},8,["modelValue"]),s(me,{title:"作用域模板设置",modelValue:n.value,"onUpdate:modelValue":e[11]||(e[11]=p=>n.value=p),width:"80%",style:{height:"80vh"}},{default:u(()=>[l("div",xt,[l("div",jt,[s(M,{modelValue:t.value,"onUpdate:modelValue":e[10]||(e[10]=p=>t.value=p),placeholder:"输入新作用域模板",class:"template-input",clearable:""},null,8,["modelValue"]),s(P,{type:"primary",onClick:Z,disabled:!t.value.trim()},{default:u(()=>e[17]||(e[17]=[D("添加模板")])),_:1},8,["disabled"])]),l("div",Bt,[e[20]||(e[20]=l("h3",null,"已保存作用域",-1)),b.value.length===0?(m(),G(ue,{key:0,description:"暂无保存的作用域"})):H("",!0),(m(!0),y(J,null,q(b.value,(p,ne)=>(m(),G(pe,{key:ne,class:"template-item"},{default:u(()=>[s(de,{justify:"space-between",align:"middle",style:{width:"100%"}},{default:u(()=>[l("div",Ot,_(p),1),l("div",Lt,[s(P,{type:"primary",size:"small",onClick:ie=>Ce(p)},{default:u(()=>e[18]||(e[18]=[D("使用")])),_:2},1032,["onClick"]),s(P,{type:"danger",size:"small",onClick:ie=>oe(p)},{default:u(()=>e[19]||(e[19]=[D("删除")])),_:2},1032,["onClick"])])]),_:2},1024)]),_:2},1024))),128))])])]),_:1},8,["modelValue"])])}}}),At=se(Nt,[["__scopeId","data-v-00e49634"]]),Dt={class:"card"},Et={class:"log-header"},Mt={class:"log-actions"},Pt={key:0},Rt={key:1},zt={key:0,class:"graph-view"},It={key:0,class:"commit-count"},Ut={key:1},Ft={key:0,class:"commit-count"},Gt={key:0,class:"branch-container"};function ge(w){return w=w.trim().replace(/^HEAD\s*->\s*/,""),w=w.replace(/^origin\//,""),w=w.replace(/^tag:\s*/,""),w.trim()}function Ht(w){return w.includes("HEAD")?"success":w.includes("tag:")?"warning":w.includes("origin/")?"info":"primary"}const Jt=ee({__name:"LogList",setup(w,{expose:E}){const d=o([]),v=o(""),a=o(!1),g=o(!1),T=o(0),j=o(!0),A=o(null);async function B(N=!1){try{a.value=!0,g.value=N;const S=await fetch(N?"/api/log?all=true&graph=true":"/api/log?graph=true");d.value=await S.json(),T.value=d.value.length,v.value="",j.value&&setTimeout(R,0)}catch(k){v.value="加载提交历史失败: "+k.message}finally{a.value=!1}}async function R(){if(!A.value||d.value.length===0)return;A.value.innerHTML="";const N=await fetch("/api/branch"),{branch:k}=await N.json(),S=Ge(A.value,{orientation:"vertical-reverse",template:"metro",author:"提交者 <committer@example.com>"}),h={},$=S.branch(k||"main");h[k||"main"]=$,d.value.forEach(c=>{let f=$;if(c.branch){const b=ge(c.branch.split(",")[0]);h[b]||(h[b]=S.branch(b)),f=h[b]}f.commit({hash:c.hash,subject:c.message,author:`${c.author} <${c.email}>`})})}function z(){j.value=!j.value,j.value&&d.value.length>0&&setTimeout(R,0)}function L(){B(!g.value)}te(()=>{B()});const I=()=>B(g.value);return E({refreshLog:I}),(N,k)=>{const S=_e;return m(),y("div",Dt,[l("div",Et,[k[1]||(k[1]=l("h2",null,"提交历史",-1)),l("div",Mt,[s(x(K),{type:"primary",size:"small",onClick:z},{default:u(()=>[D(_(j.value?"表格视图":"图表视图"),1)]),_:1}),s(x(K),{type:"primary",size:"small",onClick:L,loading:a.value},{default:u(()=>[D(_(g.value?"显示最近100条":"显示所有提交"),1)]),_:1},8,["loading"]),s(x(K),{icon:x(Ie),circle:"",size:"small",onClick:k[0]||(k[0]=h=>I()),loading:a.value},null,8,["icon","loading"])])]),v.value?(m(),y("div",Pt,_(v.value),1)):(m(),y("div",Rt,[j.value?(m(),y("div",zt,[d.value.length>0?(m(),y("div",It," 显示 "+_(d.value.length)+" 条提交记录 "+_(g.value?"(全部)":"(最近100条)"),1)):H("",!0),l("div",{ref_key:"graphContainer",ref:A,class:"graph-container"},null,512)])):(m(),y("div",Ut,[d.value.length>0?(m(),y("div",Ft," 显示 "+_(d.value.length)+" 条提交记录 "+_(g.value?"(全部)":"(最近100条)"),1)):H("",!0),ye((m(),G(x(Fe),{data:d.value,style:{width:"100%"},stripe:"",border:""},{default:u(()=>[s(x(Q),{prop:"hash",label:"提交哈希",width:"100",resizable:""}),s(x(Q),{prop:"date",label:"日期",width:"180",resizable:""}),s(x(Q),{label:"作者",width:"200",resizable:""},{default:u(h=>[D(_(h.row.author)+" <"+_(h.row.email)+"> ",1)]),_:1}),s(x(Q),{label:"分支",width:"180",resizable:""},{default:u(h=>[h.row.branch?(m(),y("div",Gt,[(m(!0),y(J,null,q(h.row.branch.split(","),($,c)=>(m(),G(x(Ue),{key:c,size:"small",type:Ht($),class:"branch-tag"},{default:u(()=>[D(_(ge($)),1)]),_:2},1032,["type"]))),128))])):H("",!0)]),_:1}),s(x(Q),{prop:"message",label:"提交信息","min-width":"250"})]),_:1},8,["data"])),[[S,a.value]])]))]))])}}}),Wt=se(Jt,[["__scopeId","data-v-c6b721c7"]]),qt="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",Kt={class:"main-header"},Zt={class:"header-left"},Qt=["src"],Xt={class:"header-info"},Yt={key:0,id:"user-info"},es={class:"user-name"},ts={class:"user-email"},ss={class:"container"},as={class:"layout-container"},ls={class:"left-panel"},os={class:"right-panel"},ns={class:"dialog-footer"},is={class:"main-footer"},rs={key:0,class:"branch-info"},cs=ee({__name:"App",setup(w){const E=o(""),d=o(null),v=o(null),a=o(""),g=o(""),T=o(""),j=o([]),A=o(!1);async function B(){try{const t=await(await fetch("/api/config/getConfig")).json();E.value=`默认提交信息: ${t.defaultCommitMessage}`}catch(n){console.error("加载配置失败:",n)}}async function R(){try{const t=await(await fetch("/api/branch")).json();t.branch&&(a.value=t.branch)}catch(n){console.error("获取分支信息失败:",n)}}async function z(){try{const t=await(await fetch("/api/branches")).json();t.branches&&Array.isArray(t.branches)&&(j.value=t.branches)}catch(n){console.error("获取所有分支信息失败:",n)}}async function L(n){console.log("切换到分支:",n);try{A.value=!0;const V=await(await fetch("/api/checkout",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({branch:n})})).json();V.success?(r({message:`已切换到分支: ${n}`,type:"success"}),R(),v.value&&v.value.refreshStatus(),d.value&&d.value.refreshLog()):(r({message:`切换分支失败: ${V.error}`,type:"error"}),a.value=a.value)}catch(t){r({message:`切换分支失败: ${t.message}`,type:"error"}),a.value=a.value}finally{A.value=!1}}async function I(){try{const t=await(await fetch("/api/user-info")).json();t.name&&t.email&&(g.value=t.name,T.value=t.email)}catch(n){console.error("获取用户信息失败:",n)}}te(()=>{B(),R(),z(),I()});function N(){d.value&&d.value.refreshLog(),v.value&&v.value.refreshStatus()}function k(){d.value&&d.value.refreshLog(),v.value&&v.value.refreshStatus(),R()}const S=o(!1),h=o(""),$=o(""),c=o(!1);async function f(){if(!h.value.trim()){r({message:"分支名称不能为空",type:"warning"});return}try{c.value=!0;const t=await(await fetch("/api/create-branch",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({newBranchName:h.value,baseBranch:$.value||a.value})})).json();t.success?(r({message:`已创建并切换到分支: ${h.value}`,type:"success"}),S.value=!1,h.value="",R(),z(),v.value&&v.value.refreshStatus(),d.value&&d.value.refreshLog()):r({message:`创建分支失败: ${t.error}`,type:"error"})}catch(n){r({message:`创建分支失败: ${n.message}`,type:"error"})}finally{c.value=!1}}function b(){$.value=a.value,S.value=!0}return(n,t)=>{const V=we,C=Je,W=ke,X=be,ae=He,Z=K,le=re,oe=he;return m(),y(J,null,[l("header",Kt,[l("div",Zt,[l("img",{src:x(qt),alt:"Zen GitSync Logo",class:"logo"},null,8,Qt),t[5]||(t[5]=l("h1",null,"Zen GitSync UI",-1))]),l("div",Xt,[g.value&&T.value?(m(),y("div",Yt,[t[6]||(t[6]=l("span",{class:"user-label"},"用户:",-1)),l("span",es,_(g.value),1),l("span",ts,"<"+_(T.value)+">",1)])):H("",!0)])]),l("div",ss,[l("div",as,[l("div",ls,[s(ut,{ref_key:"gitStatusRef",ref:v},null,512)]),l("div",os,[s(At,{onCommitSuccess:N,onPushSuccess:k}),s(Wt,{ref_key:"logListRef",ref:d},null,512)]),s(le,{modelValue:S.value,"onUpdate:modelValue":t[3]||(t[3]=O=>S.value=O),title:"创建新分支",width:"30%","destroy-on-close":""},{footer:u(()=>[l("span",ns,[s(Z,{onClick:t[2]||(t[2]=O=>S.value=!1)},{default:u(()=>t[7]||(t[7]=[D("取消")])),_:1}),s(Z,{type:"primary",onClick:f,loading:c.value},{default:u(()=>t[8]||(t[8]=[D(" 创建 ")])),_:1},8,["loading"])])]),default:u(()=>[s(ae,{model:{newBranchName:h.value,selectedBaseBranch:$.value}},{default:u(()=>[s(C,{label:"新分支名称"},{default:u(()=>[s(V,{modelValue:h.value,"onUpdate:modelValue":t[0]||(t[0]=O=>h.value=O),placeholder:"请输入新分支名称"},null,8,["modelValue"])]),_:1}),s(C,{label:"基于分支"},{default:u(()=>[s(X,{modelValue:$.value,"onUpdate:modelValue":t[1]||(t[1]=O=>$.value=O),placeholder:"选择基础分支",style:{width:"100%"}},{default:u(()=>[(m(!0),y(J,null,q(j.value,O=>(m(),G(W,{key:O,label:O,value:O},null,8,["label","value"]))),128))]),_:1},8,["modelValue"])]),_:1})]),_:1},8,["model"])]),_:1},8,["modelValue"])])]),l("footer",is,[a.value?(m(),y("div",rs,[t[9]||(t[9]=l("span",{class:"branch-label"},"当前分支:",-1)),s(X,{modelValue:a.value,"onUpdate:modelValue":t[4]||(t[4]=O=>a.value=O),size:"small",onChange:L,loading:A.value,class:"branch-select"},{default:u(()=>[(m(!0),y(J,null,q(j.value,O=>(m(),G(W,{key:O,label:O,value:O},null,8,["label","value"]))),128))]),_:1},8,["modelValue","loading"]),s(Z,{type:"primary",size:"small",onClick:b,style:{"margin-left":"5px"}},{default:u(()=>[s(oe,null,{default:u(()=>[s(x(We))]),_:1})]),_:1})])):H("",!0),t[10]||(t[10]=l("div",{class:"footer-right"},null,-1))])],64)}}}),us=se(cs,[["__scopeId","data-v-93cc73d5"]]),ds=qe(us);ds.mount("#app");
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
.status-header[data-v-849f0626]{display:flex;justify-content:space-between;align-items:center;margin-bottom:10px}.status-header h2[data-v-849f0626]{margin:0}.file-list[data-v-849f0626]{margin-top:10px}.file-item[data-v-849f0626]{display:flex;align-items:center;margin-bottom:4px;padding:2px 6px;border-radius:3px;font-size:14px;cursor:pointer;transition:opacity .2s}.file-item[data-v-849f0626]:hover{opacity:.8}.file-item.added[data-v-849f0626]{background:#e6ffed;color:#22863a}.file-item.modified[data-v-849f0626]{background:#fff5b1;color:#b08800}.file-item.deleted[data-v-849f0626]{background:#ffeef0;color:#cb2431}.file-item.untracked[data-v-849f0626]{background:#f1f8ff;color:#0366d6}.file-type[data-v-849f0626]{font-weight:700;margin-right:8px}.file-path[data-v-849f0626]{font-family:monospace}.diff-content[data-v-849f0626]{max-height:70vh;overflow-y:auto;background-color:#f6f8fa;border:1px solid #e1e4e8;border-radius:3px;padding:15px;font-family:monospace;white-space:pre-wrap}.diff-formatted[data-v-849f0626]{margin:0}[data-v-849f0626] .diff-header{color:#24292e;font-weight:700}[data-v-849f0626] .diff-old-file{color:#cb2431;background-color:#ffeef0}[data-v-849f0626] .diff-new-file{color:#22863a;background-color:#e6ffed}[data-v-849f0626] .diff-hunk-header{color:#6f42c1;background-color:#f1f8ff}[data-v-849f0626] .diff-added{color:#22863a;background-color:#e6ffed}[data-v-849f0626] .diff-removed{color:#cb2431;background-color:#ffeef0}[data-v-849f0626] .diff-context{color:#24292e}.no-diff[data-v-849f0626]{text-align:center;padding:20px;color:#666}.file-navigation[data-v-849f0626]{display:flex;justify-content:center;align-items:center;margin-top:15px;gap:10px}.file-counter[data-v-849f0626]{font-size:14px;color:#606266}.current-directory[data-v-849f0626]{padding:10px 15px;background-color:#f0f0f0;border-bottom:1px solid #e1e4e8;display:flex;align-items:center;gap:8px;font-family:monospace}.not-git-repo[data-v-849f0626]{margin:10px 0;padding:10px;background-color:#fffbf6;border:1px solid #f0c78a;border-radius:4px}.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}
|