完成基本功能
This commit is contained in:
24
frontend/.gitignore
vendored
Normal file
24
frontend/.gitignore
vendored
Normal file
@@ -0,0 +1,24 @@
|
||||
# Nuxt dev/build outputs
|
||||
.output
|
||||
.data
|
||||
.nuxt
|
||||
.nitro
|
||||
.cache
|
||||
dist
|
||||
|
||||
# Node dependencies
|
||||
node_modules
|
||||
|
||||
# Logs
|
||||
logs
|
||||
*.log
|
||||
|
||||
# Misc
|
||||
.DS_Store
|
||||
.fleet
|
||||
.idea
|
||||
|
||||
# Local env files
|
||||
.env
|
||||
.env.*
|
||||
!.env.example
|
||||
10
frontend/app/app.vue
Normal file
10
frontend/app/app.vue
Normal file
@@ -0,0 +1,10 @@
|
||||
<script setup>
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<NuxtLayout>
|
||||
<NuxtPage />
|
||||
</NuxtLayout>
|
||||
</template>
|
||||
|
||||
<style></style>
|
||||
1513
frontend/app/components/ContentArea.vue
Normal file
1513
frontend/app/components/ContentArea.vue
Normal file
File diff suppressed because it is too large
Load Diff
220
frontend/app/components/FileTreeNode.vue
Normal file
220
frontend/app/components/FileTreeNode.vue
Normal file
@@ -0,0 +1,220 @@
|
||||
<script setup>
|
||||
import {
|
||||
FileOutlined,
|
||||
FolderOutlined,
|
||||
FolderOpenOutlined,
|
||||
CaretRightOutlined,
|
||||
CaretDownOutlined,
|
||||
PlusOutlined,
|
||||
MinusOutlined,
|
||||
UndoOutlined,
|
||||
} from '@ant-design/icons-vue'
|
||||
|
||||
const props = defineProps({
|
||||
node: { type: Object, required: true },
|
||||
collapsedDirs: { type: Set, default: () => new Set() },
|
||||
selectedFile: { type: Object, default: null },
|
||||
depth: { type: Number, default: 0 },
|
||||
// 'unstaged' | 'staged'
|
||||
mode: { type: String, default: 'unstaged' },
|
||||
})
|
||||
|
||||
const emit = defineEmits([
|
||||
'select-file', 'toggle-dir',
|
||||
'stage-file', 'unstage-file', 'discard-file',
|
||||
'stage-dir', 'unstage-dir', 'discard-dir',
|
||||
])
|
||||
|
||||
function getStatusColor(status) {
|
||||
const colors = { 'M': 'orange', 'A': 'green', 'D': 'red', '?': 'default' }
|
||||
return colors[status] || 'default'
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<!-- 目录节点 -->
|
||||
<div v-if="node.type === 'dir'" class="tree-dir">
|
||||
<div class="tree-dir-header" :style="{ paddingLeft: (8 + depth * 16) + 'px' }" @click="emit('toggle-dir', node.path)">
|
||||
<CaretDownOutlined v-if="!collapsedDirs.has(node.path)" class="tree-arrow" />
|
||||
<CaretRightOutlined v-else class="tree-arrow" />
|
||||
<FolderOpenOutlined v-if="!collapsedDirs.has(node.path)" class="tree-icon dir-icon" />
|
||||
<FolderOutlined v-else class="tree-icon dir-icon" />
|
||||
<span class="tree-dir-name">{{ node.name }}</span>
|
||||
<span class="tree-dir-count">{{ node.fileCount }}</span>
|
||||
<!-- 目录级操作按钮 -->
|
||||
<span class="tree-actions" @click.stop>
|
||||
<template v-if="mode === 'unstaged'">
|
||||
<span class="tree-action-btn" title="暂存目录下所有文件" @click="emit('stage-dir', node.path)"><PlusOutlined /></span>
|
||||
<span class="tree-action-btn danger" title="丢弃目录下所有更改" @click="emit('discard-dir', node.path)"><UndoOutlined /></span>
|
||||
</template>
|
||||
<template v-else>
|
||||
<span class="tree-action-btn" title="取消暂存目录下所有文件" @click="emit('unstage-dir', node.path)"><MinusOutlined /></span>
|
||||
</template>
|
||||
</span>
|
||||
</div>
|
||||
<div v-show="!collapsedDirs.has(node.path)">
|
||||
<FileTreeNode
|
||||
v-for="child in node.children"
|
||||
:key="child.type + '-' + (child.path || child.data?.filePath)"
|
||||
:node="child"
|
||||
:collapsed-dirs="collapsedDirs"
|
||||
:selected-file="selectedFile"
|
||||
:depth="depth + 1"
|
||||
:mode="mode"
|
||||
@select-file="emit('select-file', $event)"
|
||||
@toggle-dir="emit('toggle-dir', $event)"
|
||||
@stage-file="emit('stage-file', $event)"
|
||||
@unstage-file="emit('unstage-file', $event)"
|
||||
@discard-file="emit('discard-file', $event)"
|
||||
@stage-dir="emit('stage-dir', $event)"
|
||||
@unstage-dir="emit('unstage-dir', $event)"
|
||||
@discard-dir="emit('discard-dir', $event)"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 文件节点 -->
|
||||
<div v-else class="tree-file-item"
|
||||
:style="{ paddingLeft: (8 + depth * 16) + 'px' }"
|
||||
:class="{ active: selectedFile?.filePath === node.data.filePath && selectedFile?.staged === node.data.staged }"
|
||||
@click="emit('select-file', node.data)">
|
||||
<FileOutlined class="tree-icon file-icon" />
|
||||
<span class="tree-file-name">{{ node.name }}</span>
|
||||
<a-tag :color="getStatusColor(node.data.status)" size="small" class="tree-status-tag">{{ node.data.statusText }}</a-tag>
|
||||
<!-- 文件级操作按钮 -->
|
||||
<span class="tree-actions" @click.stop>
|
||||
<template v-if="mode === 'unstaged'">
|
||||
<span class="tree-action-btn" title="暂存此文件" @click="emit('stage-file', node.data)"><PlusOutlined /></span>
|
||||
<span class="tree-action-btn danger" title="丢弃更改" @click="emit('discard-file', node.data)"><UndoOutlined /></span>
|
||||
</template>
|
||||
<template v-else>
|
||||
<span class="tree-action-btn" title="取消暂存" @click="emit('unstage-file', node.data)"><MinusOutlined /></span>
|
||||
</template>
|
||||
</span>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
.tree-dir-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 3px 8px;
|
||||
cursor: pointer;
|
||||
gap: 4px;
|
||||
font-size: 13px;
|
||||
font-weight: 500;
|
||||
color: var(--text-primary);
|
||||
transition: background 0.12s;
|
||||
}
|
||||
|
||||
.tree-dir-header:hover {
|
||||
background: var(--bg-hover);
|
||||
}
|
||||
|
||||
.tree-arrow {
|
||||
font-size: 10px;
|
||||
color: var(--text-muted);
|
||||
flex-shrink: 0;
|
||||
width: 14px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.tree-icon {
|
||||
flex-shrink: 0;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.dir-icon {
|
||||
color: var(--accent, #89b4fa);
|
||||
}
|
||||
|
||||
.file-icon {
|
||||
color: var(--text-muted);
|
||||
}
|
||||
|
||||
.tree-dir-name {
|
||||
flex: 1;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.tree-dir-count {
|
||||
font-size: 11px;
|
||||
color: var(--text-muted);
|
||||
background: var(--bg-hover, rgba(255,255,255,0.06));
|
||||
border-radius: 8px;
|
||||
padding: 0 6px;
|
||||
min-width: 18px;
|
||||
text-align: center;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.tree-file-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 3px 8px;
|
||||
cursor: pointer;
|
||||
gap: 6px;
|
||||
font-size: 13px;
|
||||
transition: background 0.12s;
|
||||
}
|
||||
|
||||
.tree-file-item:hover {
|
||||
background: var(--bg-hover);
|
||||
}
|
||||
|
||||
.tree-file-item.active {
|
||||
background: var(--bg-active);
|
||||
}
|
||||
|
||||
.tree-file-name {
|
||||
flex: 1;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.tree-status-tag {
|
||||
flex-shrink: 0;
|
||||
font-size: 11px;
|
||||
}
|
||||
|
||||
/* 操作按钮 */
|
||||
.tree-actions {
|
||||
display: flex;
|
||||
visibility: hidden;
|
||||
align-items: center;
|
||||
gap: 2px;
|
||||
flex-shrink: 0;
|
||||
margin-left: 4px;
|
||||
}
|
||||
|
||||
.tree-dir-header:hover .tree-actions,
|
||||
.tree-file-item:hover .tree-actions {
|
||||
visibility: visible;
|
||||
}
|
||||
|
||||
.tree-action-btn {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
border-radius: 4px;
|
||||
font-size: 12px;
|
||||
color: var(--text-secondary);
|
||||
cursor: pointer;
|
||||
transition: all 0.12s;
|
||||
}
|
||||
|
||||
.tree-action-btn:hover {
|
||||
background: var(--bg-active, rgba(255,255,255,0.12));
|
||||
color: var(--text-primary);
|
||||
}
|
||||
|
||||
.tree-action-btn.danger:hover {
|
||||
background: rgba(243, 139, 168, 0.2);
|
||||
color: var(--danger, #f38ba8);
|
||||
}
|
||||
</style>
|
||||
620
frontend/app/components/Sidebar.vue
Normal file
620
frontend/app/components/Sidebar.vue
Normal file
@@ -0,0 +1,620 @@
|
||||
<script setup>
|
||||
import { ref, onMounted, computed, h } from 'vue'
|
||||
import {
|
||||
FolderOutlined,
|
||||
FolderOpenOutlined,
|
||||
UserOutlined,
|
||||
PlusOutlined,
|
||||
EditOutlined,
|
||||
DeleteOutlined,
|
||||
} from '@ant-design/icons-vue'
|
||||
import { AppService } from '../../bindings/github.com/zhuy1228/GitPilot/internal/app'
|
||||
|
||||
const props = defineProps({
|
||||
selectedProject: { type: Object, default: null }
|
||||
})
|
||||
|
||||
const emit = defineEmits(['select-project', 'tree-updated'])
|
||||
|
||||
const tree = ref([])
|
||||
const expandedKeys = ref([])
|
||||
const selectedKeys = ref([])
|
||||
|
||||
// 添加项目弹窗
|
||||
const showAddDialog = ref(false)
|
||||
const addForm = ref({ platform: '', username: '', name: '', path: '' })
|
||||
|
||||
// 右键菜单
|
||||
const contextMenu = ref({ visible: false, x: 0, y: 0, type: '', data: {} })
|
||||
|
||||
// 平台弹窗
|
||||
const showPlatformDialog = ref(false)
|
||||
const platformDialogMode = ref('add')
|
||||
const platformForm = ref({ name: '', baseUrl: '', oldName: '' })
|
||||
|
||||
// 用户弹窗
|
||||
const showUserDialog = ref(false)
|
||||
const userDialogMode = ref('add')
|
||||
const userForm = ref({ platform: '', username: '', token: '', oldUsername: '' })
|
||||
|
||||
// 构建 key → 原始节点 的映射,避免 a-tree event node 丢失自定义字段
|
||||
const nodeMap = computed(() => {
|
||||
const map = {}
|
||||
;(tree.value || []).forEach(platform => {
|
||||
platform.children?.forEach(user => {
|
||||
user.children?.forEach(proj => {
|
||||
map[proj.key] = proj
|
||||
})
|
||||
})
|
||||
})
|
||||
return map
|
||||
})
|
||||
|
||||
// 转换后端树数据为 a-tree 格式
|
||||
const treeData = computed(() => {
|
||||
return (tree.value || []).map(platform => ({
|
||||
key: platform.key,
|
||||
title: platform.label,
|
||||
type: 'platform',
|
||||
isLeaf: false,
|
||||
children: (platform.children || []).map(user => ({
|
||||
key: user.key,
|
||||
title: user.label,
|
||||
type: 'user',
|
||||
platformKey: platform.key,
|
||||
isLeaf: false,
|
||||
children: (user.children || []).map(proj => ({
|
||||
key: proj.key,
|
||||
title: proj.label,
|
||||
type: 'project',
|
||||
path: proj.path,
|
||||
platformKey: platform.key,
|
||||
username: user.label,
|
||||
isLeaf: true,
|
||||
}))
|
||||
}))
|
||||
}))
|
||||
})
|
||||
|
||||
async function loadTree() {
|
||||
try {
|
||||
const result = await AppService.GetProjectTree()
|
||||
tree.value = result || []
|
||||
const keys = []
|
||||
tree.value.forEach(node => {
|
||||
keys.push(node.key)
|
||||
if (node.children) {
|
||||
node.children.forEach(child => {
|
||||
keys.push(child.key)
|
||||
})
|
||||
}
|
||||
})
|
||||
expandedKeys.value = keys
|
||||
} catch (e) {
|
||||
console.error('加载项目树失败:', e)
|
||||
}
|
||||
}
|
||||
|
||||
function onTreeSelect(keys, { node }) {
|
||||
if (node.type === 'project') {
|
||||
selectedKeys.value = keys
|
||||
// 从 nodeMap 中取 path,避免 a-tree 事件节点丢失自定义字段
|
||||
const raw = nodeMap.value[node.key]
|
||||
const path = raw?.path || node.path || ''
|
||||
console.log('[Sidebar] select project:', node.key, 'path:', path)
|
||||
emit('select-project', { key: node.key, label: node.title || raw?.label, path, type: 'project' })
|
||||
}
|
||||
}
|
||||
|
||||
// --- 右键菜单 ---
|
||||
function onRightClick({ event, node }) {
|
||||
event.preventDefault()
|
||||
const type = node.type
|
||||
const data = {}
|
||||
if (type === 'platform') {
|
||||
data.key = node.key
|
||||
} else if (type === 'user') {
|
||||
data.platformKey = node.platformKey
|
||||
data.username = node.title
|
||||
} else if (type === 'project') {
|
||||
data.platformKey = node.platformKey
|
||||
data.username = node.username
|
||||
data.name = node.title
|
||||
}
|
||||
contextMenu.value = { visible: true, x: event.clientX, y: event.clientY, type, data }
|
||||
}
|
||||
|
||||
function onSidebarContextMenu(e) {
|
||||
e.preventDefault()
|
||||
contextMenu.value = { visible: true, x: e.clientX, y: e.clientY, type: 'empty', data: {} }
|
||||
}
|
||||
|
||||
function hideContextMenu() {
|
||||
contextMenu.value.visible = false
|
||||
}
|
||||
|
||||
function onContextMenuClick({ key: action }) {
|
||||
const { type, data } = contextMenu.value
|
||||
hideContextMenu()
|
||||
switch (action) {
|
||||
case 'add-platform': openAddPlatformDialog(); break
|
||||
case 'add-user': openAddUserDialog(data.key || data.platformKey); break
|
||||
case 'edit-platform': openEditPlatformDialog(data.key); break
|
||||
case 'remove-platform': removePlatform(data.key); break
|
||||
case 'add-project': openAddDialog(data.platformKey, data.username); break
|
||||
case 'edit-user': openEditUserDialog(data.platformKey, data.username); break
|
||||
case 'remove-user': removeUser(data.platformKey, data.username); break
|
||||
case 'remove-project': removeProject(data.platformKey, data.username, data.name); break
|
||||
}
|
||||
}
|
||||
|
||||
const contextMenuItems = computed(() => {
|
||||
const { type } = contextMenu.value
|
||||
if (type === 'empty') {
|
||||
return [{ key: 'add-platform', label: '添加平台', icon: h(PlusOutlined) }]
|
||||
}
|
||||
if (type === 'platform') {
|
||||
return [
|
||||
{ key: 'add-user', label: '添加用户', icon: h(UserOutlined) },
|
||||
{ key: 'edit-platform', label: '编辑平台', icon: h(EditOutlined) },
|
||||
{ type: 'divider' },
|
||||
{ key: 'add-platform', label: '添加平台', icon: h(PlusOutlined) },
|
||||
{ type: 'divider' },
|
||||
{ key: 'remove-platform', label: '删除平台', danger: true, icon: h(DeleteOutlined) },
|
||||
]
|
||||
}
|
||||
if (type === 'user') {
|
||||
return [
|
||||
{ key: 'add-project', label: '添加项目', icon: h(FolderOutlined) },
|
||||
{ key: 'edit-user', label: '编辑用户', icon: h(EditOutlined) },
|
||||
{ type: 'divider' },
|
||||
{ key: 'remove-user', label: '删除用户', danger: true, icon: h(DeleteOutlined) },
|
||||
]
|
||||
}
|
||||
if (type === 'project') {
|
||||
return [
|
||||
{ key: 'add-project', label: '添加项目', icon: h(FolderOutlined) },
|
||||
{ type: 'divider' },
|
||||
{ key: 'remove-project', label: '删除项目', danger: true, icon: h(DeleteOutlined) },
|
||||
]
|
||||
}
|
||||
return []
|
||||
})
|
||||
|
||||
// --- 平台操作 ---
|
||||
function openAddPlatformDialog() {
|
||||
platformDialogMode.value = 'add'
|
||||
platformForm.value = { name: '', baseUrl: '', oldName: '' }
|
||||
showPlatformDialog.value = true
|
||||
}
|
||||
|
||||
async function openEditPlatformDialog(platformKey) {
|
||||
try {
|
||||
const info = await AppService.GetPlatformInfo(platformKey)
|
||||
platformDialogMode.value = 'edit'
|
||||
platformForm.value = { name: info.name, baseUrl: info.baseUrl || '', oldName: info.name }
|
||||
showPlatformDialog.value = true
|
||||
} catch (e) {
|
||||
console.error('获取平台信息失败:', e)
|
||||
}
|
||||
}
|
||||
|
||||
async function savePlatform() {
|
||||
if (!platformForm.value.name) return
|
||||
try {
|
||||
if (platformDialogMode.value === 'add') {
|
||||
await AppService.AddPlatform(platformForm.value.name, platformForm.value.baseUrl)
|
||||
} else {
|
||||
await AppService.UpdatePlatform(platformForm.value.oldName, platformForm.value.baseUrl)
|
||||
}
|
||||
showPlatformDialog.value = false
|
||||
await loadTree()
|
||||
emit('tree-updated')
|
||||
} catch (e) {
|
||||
console.error('操作失败:', e)
|
||||
}
|
||||
}
|
||||
|
||||
async function removePlatform(name) {
|
||||
if (!confirm(`确定删除平台 "${name}" 及其所有用户和项目吗?`)) return
|
||||
try {
|
||||
await AppService.RemovePlatform(name)
|
||||
await loadTree()
|
||||
emit('tree-updated')
|
||||
} catch (e) {
|
||||
console.error('删除失败:', e)
|
||||
}
|
||||
}
|
||||
|
||||
// --- 用户操作 ---
|
||||
function openAddUserDialog(platformKey) {
|
||||
userDialogMode.value = 'add'
|
||||
userForm.value = { platform: platformKey, username: '', token: '', oldUsername: '' }
|
||||
showUserDialog.value = true
|
||||
}
|
||||
|
||||
async function openEditUserDialog(platformKey, username) {
|
||||
try {
|
||||
const info = await AppService.GetUserInfo(platformKey, username)
|
||||
userDialogMode.value = 'edit'
|
||||
userForm.value = {
|
||||
platform: platformKey,
|
||||
username: info.username,
|
||||
token: info.token || '',
|
||||
oldUsername: info.username
|
||||
}
|
||||
showUserDialog.value = true
|
||||
} catch (e) {
|
||||
console.error('获取用户信息失败:', e)
|
||||
}
|
||||
}
|
||||
|
||||
async function saveUser() {
|
||||
if (!userForm.value.username) return
|
||||
try {
|
||||
if (userDialogMode.value === 'add') {
|
||||
await AppService.AddUser(userForm.value.platform, userForm.value.username, userForm.value.token)
|
||||
} else {
|
||||
await AppService.UpdateUser(
|
||||
userForm.value.platform,
|
||||
userForm.value.oldUsername,
|
||||
userForm.value.username,
|
||||
userForm.value.token
|
||||
)
|
||||
}
|
||||
showUserDialog.value = false
|
||||
await loadTree()
|
||||
emit('tree-updated')
|
||||
} catch (e) {
|
||||
console.error('操作失败:', e)
|
||||
}
|
||||
}
|
||||
|
||||
async function removeUser(platform, username) {
|
||||
if (!confirm(`确定删除用户 "${username}" 及其所有项目吗?`)) return
|
||||
try {
|
||||
await AppService.RemoveUser(platform, username)
|
||||
await loadTree()
|
||||
emit('tree-updated')
|
||||
} catch (e) {
|
||||
console.error('删除失败:', e)
|
||||
}
|
||||
}
|
||||
|
||||
// --- 项目操作 ---
|
||||
function openAddDialog(platformKey, username) {
|
||||
addForm.value = { platform: platformKey, username: username, name: '', path: '' }
|
||||
showAddDialog.value = true
|
||||
}
|
||||
|
||||
async function pickDirectory() {
|
||||
try {
|
||||
const path = await AppService.SelectDirectory()
|
||||
if (path) {
|
||||
addForm.value.path = path
|
||||
// 如果项目名称为空,自动用文件夹名称填充
|
||||
if (!addForm.value.name) {
|
||||
const parts = path.replace(/\\/g, '/').split('/')
|
||||
addForm.value.name = parts[parts.length - 1] || ''
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
console.error('选择文件夹失败:', e)
|
||||
}
|
||||
}
|
||||
|
||||
async function addProject() {
|
||||
if (!addForm.value.name || !addForm.value.path) return
|
||||
try {
|
||||
await AppService.AddProject(
|
||||
addForm.value.platform,
|
||||
addForm.value.username,
|
||||
addForm.value.name,
|
||||
addForm.value.path
|
||||
)
|
||||
showAddDialog.value = false
|
||||
await loadTree()
|
||||
emit('tree-updated')
|
||||
} catch (e) {
|
||||
console.error('添加项目失败:', e)
|
||||
}
|
||||
}
|
||||
|
||||
async function removeProject(platform, username, name) {
|
||||
if (!confirm(`确定删除项目 "${name}" 吗?`)) return
|
||||
try {
|
||||
await AppService.RemoveProject(platform, username, name)
|
||||
await loadTree()
|
||||
emit('tree-updated')
|
||||
} catch (e) {
|
||||
console.error('删除项目失败:', e)
|
||||
}
|
||||
}
|
||||
|
||||
// 平台 SVG Logo
|
||||
const platformLogos = {
|
||||
github: `<svg viewBox="0 0 16 16" fill="currentColor"><path d="M8 0C3.58 0 0 3.58 0 8c0 3.54 2.29 6.53 5.47 7.59.4.07.55-.17.55-.38 0-.19-.01-.82-.01-1.49-2.01.37-2.53-.49-2.69-.94-.09-.23-.48-.94-.82-1.13-.28-.15-.68-.52-.01-.53.63-.01 1.08.58 1.23.82.72 1.21 1.87.87 2.33.66.07-.52.28-.87.51-1.07-1.78-.2-3.64-.89-3.64-3.95 0-.87.31-1.59.82-2.15-.08-.2-.36-1.02.08-2.12 0 0 .67-.21 2.2.82.64-.18 1.32-.27 2-.27.68 0 1.36.09 2 .27 1.53-1.04 2.2-.82 2.2-.82.44 1.1.16 1.92.08 2.12.51.56.82 1.27.82 2.15 0 3.07-1.87 3.75-3.65 3.95.29.25.54.73.54 1.48 0 1.07-.01 1.93-.01 2.2 0 .21.15.46.55.38A8.013 8.013 0 0016 8c0-4.42-3.58-8-8-8z"/></svg>`,
|
||||
gitee: `<svg viewBox="0 0 1024 1024" fill="currentColor"><path d="M512 1024C229.222 1024 0 794.778 0 512S229.222 0 512 0s512 229.222 512 512-229.222 512-512 512z m259.149-568.883h-290.74a25.293 25.293 0 0 0-25.292 25.293l-0.026 63.206c0 13.952 11.315 25.293 25.267 25.293h177.024c13.978 0 25.293 11.315 25.293 25.267v12.646a75.853 75.853 0 0 1-75.853 75.853h-240.23a25.293 25.293 0 0 1-25.267-25.293V417.203a75.853 75.853 0 0 1 75.827-75.853h353.946a25.293 25.293 0 0 0 25.267-25.292l0.077-63.207a25.293 25.293 0 0 0-25.268-25.293H417.152a189.62 189.62 0 0 0-189.62 189.645V771.15c0 13.977 11.316 25.293 25.294 25.293h372.94a170.65 170.65 0 0 0 170.65-170.65V480.384a25.293 25.293 0 0 0-25.293-25.267z"/></svg>`,
|
||||
gitea: `<svg viewBox="0 0 640 640" fill="currentColor"><path d="M395.022 297.778c-13.158 0-23.822 10.664-23.822 23.822s10.664 23.822 23.822 23.822 23.822-10.664 23.822-23.822-10.664-23.822-23.822-23.822zM243.2 297.778c-13.158 0-23.822 10.664-23.822 23.822s10.664 23.822 23.822 23.822 23.822-10.664 23.822-23.822-10.664-23.822-23.822-23.822zM319.111 22.756C158.578 22.756 28.444 152.889 28.444 313.422s130.133 290.667 290.667 290.667 290.667-130.133 290.667-290.667S479.644 22.756 319.111 22.756zm165.689 361.244c0 5.333-0.711 10.667-1.778 15.644-20.267 93.867-148.089 167.111-305.067 167.111a360.604 360.604 0 0 1-65.778-5.689c-21.333 18.133-56.889 37.689-101.333 49.422-7.822 2.133-16 3.911-24.889 5.333h-0.711c-4.267 0-7.822-3.556-8.889-7.822v-0.356c-1.067-4.622 2.133-7.467 4.978-10.667 17.067-18.844 36.622-34.844 48-71.467-51.911-36.267-83.911-85.067-83.911-139.733 0-106.311 107.378-192.356 239.644-192.356 118.4 0 220.089 68.267 238.578 160.356 1.778 6.4 3.556 14.578 3.556 22.4-0.356 2.489-0.356 5.333-0.356 7.822z"/></svg>`,
|
||||
default: `<svg viewBox="0 0 16 16" fill="currentColor"><path d="M15 5.6c0-.3-.2-.6-.5-.7L8.3.2a.6.6 0 0 0-.6 0L1.5 4.9c-.3.1-.5.4-.5.7v5.8c0 .3.2.6.5.7l6.2 3.7c.2.1.4.1.6 0l6.2-3.7c.3-.1.5-.4.5-.7V5.6zM8 1.2l5.2 3.1L8 7.5 2.8 4.3 8 1.2zm-6 4.5l5.5 3.2v6.3L2 12V5.7zm7 9.5V9l5.5-3.2V12L9 15.2z"/></svg>`
|
||||
}
|
||||
|
||||
function getPlatformColor(name) {
|
||||
const colors = { github: '#e6edf3', gitee: '#c71d23', gitea: '#609926' }
|
||||
return colors[name] || 'var(--text-secondary)'
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
loadTree()
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<aside class="sidebar">
|
||||
<div class="sidebar-header">
|
||||
<span class="logo">GitPilot</span>
|
||||
<a-button type="text" size="small" @click="openAddPlatformDialog" title="添加平台">
|
||||
<template #icon><PlusOutlined /></template>
|
||||
</a-button>
|
||||
</div>
|
||||
|
||||
<div class="sidebar-content" @contextmenu="onSidebarContextMenu">
|
||||
<a-tree
|
||||
v-if="treeData.length"
|
||||
v-model:expandedKeys="expandedKeys"
|
||||
v-model:selectedKeys="selectedKeys"
|
||||
:tree-data="treeData"
|
||||
block-node
|
||||
:show-icon="true"
|
||||
@select="onTreeSelect"
|
||||
@rightClick="onRightClick"
|
||||
@contextmenu.stop
|
||||
>
|
||||
<template #title="{ title, type, key }">
|
||||
<div class="tree-node-title">
|
||||
<span
|
||||
v-if="type === 'platform'"
|
||||
class="platform-logo"
|
||||
:style="{ color: getPlatformColor(key) }"
|
||||
v-html="platformLogos[key] || platformLogos.default"
|
||||
></span>
|
||||
<UserOutlined v-else-if="type === 'user'" class="node-icon" />
|
||||
<FolderOutlined v-else class="node-icon" />
|
||||
<span class="node-label">{{ title }}</span>
|
||||
</div>
|
||||
</template>
|
||||
</a-tree>
|
||||
<div v-else class="empty-tip">右键可添加平台</div>
|
||||
</div>
|
||||
|
||||
<!-- 右键菜单 -->
|
||||
<Teleport to="body">
|
||||
<div
|
||||
v-if="contextMenu.visible"
|
||||
class="context-menu-mask"
|
||||
@click="hideContextMenu"
|
||||
@contextmenu.prevent="hideContextMenu"
|
||||
>
|
||||
<div @click.stop @contextmenu.stop>
|
||||
<a-menu
|
||||
class="context-menu-popup"
|
||||
:style="{ left: contextMenu.x + 'px', top: contextMenu.y + 'px' }"
|
||||
:items="contextMenuItems"
|
||||
@click="onContextMenuClick"
|
||||
mode="vertical"
|
||||
:selectable="false"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</Teleport>
|
||||
|
||||
<!-- 添加项目弹窗 -->
|
||||
<a-modal
|
||||
v-model:open="showAddDialog"
|
||||
title="添加项目"
|
||||
@ok="addProject"
|
||||
ok-text="添加"
|
||||
cancel-text="取消"
|
||||
:width="420"
|
||||
>
|
||||
<a-form layout="vertical" :style="{ marginTop: '16px' }">
|
||||
<a-form-item label="平台">
|
||||
<a-input :value="addForm.platform" disabled />
|
||||
</a-form-item>
|
||||
<a-form-item label="用户">
|
||||
<a-input :value="addForm.username" disabled />
|
||||
</a-form-item>
|
||||
<a-form-item label="项目名称">
|
||||
<a-input v-model:value="addForm.name" placeholder="my-project" />
|
||||
</a-form-item>
|
||||
<a-form-item label="本地路径">
|
||||
<a-input v-model:value="addForm.path" placeholder="F:/Projects/xxx">
|
||||
<template #suffix>
|
||||
<FolderOpenOutlined
|
||||
style="cursor: pointer; color: var(--accent, #89b4fa);"
|
||||
title="选择文件夹"
|
||||
@click="pickDirectory"
|
||||
/>
|
||||
</template>
|
||||
</a-input>
|
||||
</a-form-item>
|
||||
</a-form>
|
||||
</a-modal>
|
||||
|
||||
<!-- 平台弹窗 -->
|
||||
<a-modal
|
||||
v-model:open="showPlatformDialog"
|
||||
:title="platformDialogMode === 'add' ? '添加平台' : '编辑平台'"
|
||||
@ok="savePlatform"
|
||||
:ok-text="platformDialogMode === 'add' ? '添加' : '保存'"
|
||||
cancel-text="取消"
|
||||
:width="420"
|
||||
>
|
||||
<a-form layout="vertical" :style="{ marginTop: '16px' }">
|
||||
<a-form-item label="平台名称">
|
||||
<a-input
|
||||
v-model:value="platformForm.name"
|
||||
placeholder="github / gitee / gitea"
|
||||
:disabled="platformDialogMode === 'edit'"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item>
|
||||
<template #label>
|
||||
Base URL <span class="form-hint">(自建平台需要填写)</span>
|
||||
</template>
|
||||
<a-input v-model:value="platformForm.baseUrl" placeholder="http://192.168.1.10:3000" />
|
||||
</a-form-item>
|
||||
</a-form>
|
||||
</a-modal>
|
||||
|
||||
<!-- 用户弹窗 -->
|
||||
<a-modal
|
||||
v-model:open="showUserDialog"
|
||||
:title="userDialogMode === 'add' ? '添加用户' : '编辑用户'"
|
||||
@ok="saveUser"
|
||||
:ok-text="userDialogMode === 'add' ? '添加' : '保存'"
|
||||
cancel-text="取消"
|
||||
:width="420"
|
||||
>
|
||||
<a-form layout="vertical" :style="{ marginTop: '16px' }">
|
||||
<a-form-item label="平台">
|
||||
<a-input :value="userForm.platform" disabled />
|
||||
</a-form-item>
|
||||
<a-form-item label="用户名">
|
||||
<a-input v-model:value="userForm.username" placeholder="your-username" />
|
||||
</a-form-item>
|
||||
<a-form-item>
|
||||
<template #label>
|
||||
Token <span class="form-hint">(可选,用于 API 认证)</span>
|
||||
</template>
|
||||
<a-input-password v-model:value="userForm.token" placeholder="ghp_xxxx / Bearer token" />
|
||||
</a-form-item>
|
||||
</a-form>
|
||||
</a-modal>
|
||||
</aside>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
.sidebar {
|
||||
height: 100%;
|
||||
background: var(--bg-secondary);
|
||||
border-right: 1px solid var(--border-color);
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
flex-shrink: 0;
|
||||
min-width: 180px;
|
||||
}
|
||||
|
||||
.sidebar-header {
|
||||
height: var(--header-height);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding: 0 16px;
|
||||
border-bottom: 1px solid var(--border-color);
|
||||
--wails-draggable: drag;
|
||||
}
|
||||
|
||||
.logo {
|
||||
font-size: 15px;
|
||||
font-weight: 600;
|
||||
color: var(--accent);
|
||||
}
|
||||
|
||||
.sidebar-content {
|
||||
flex: 1;
|
||||
overflow-y: auto;
|
||||
padding: 4px 0;
|
||||
}
|
||||
|
||||
.tree-node-title {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 6px;
|
||||
}
|
||||
|
||||
.platform-logo {
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.platform-logo :deep(svg) {
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
}
|
||||
|
||||
.node-icon {
|
||||
font-size: 14px;
|
||||
color: var(--text-muted);
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.node-label {
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.empty-tip {
|
||||
padding: 24px 16px;
|
||||
text-align: center;
|
||||
color: var(--text-muted);
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
.form-hint {
|
||||
font-weight: 400;
|
||||
color: var(--text-muted);
|
||||
font-size: 11px;
|
||||
}
|
||||
|
||||
/* 右键菜单遮罩 */
|
||||
.context-menu-mask {
|
||||
position: fixed;
|
||||
inset: 0;
|
||||
z-index: 2000;
|
||||
}
|
||||
|
||||
.context-menu-popup {
|
||||
position: fixed !important;
|
||||
z-index: 2001;
|
||||
border-radius: 6px !important;
|
||||
box-shadow: 0 6px 24px rgba(0, 0, 0, 0.45) !important;
|
||||
min-width: 160px;
|
||||
}
|
||||
|
||||
/* Ant Design 暗色主题覆盖 */
|
||||
:deep(.ant-tree) {
|
||||
background: transparent;
|
||||
color: var(--text-primary);
|
||||
}
|
||||
|
||||
:deep(.ant-tree .ant-tree-node-content-wrapper) {
|
||||
color: var(--text-primary);
|
||||
}
|
||||
|
||||
:deep(.ant-tree .ant-tree-node-content-wrapper:hover) {
|
||||
background: var(--bg-hover);
|
||||
}
|
||||
|
||||
:deep(.ant-tree .ant-tree-node-content-wrapper.ant-tree-node-selected) {
|
||||
background: var(--bg-active);
|
||||
color: var(--text-primary);
|
||||
}
|
||||
|
||||
:deep(.ant-tree .ant-tree-switcher) {
|
||||
color: var(--text-muted);
|
||||
}
|
||||
|
||||
:deep(.ant-tree .ant-tree-treenode) {
|
||||
padding: 2px 0;
|
||||
}
|
||||
|
||||
:deep(.ant-tree .ant-tree-icon__customize) {
|
||||
display: none;
|
||||
}
|
||||
</style>
|
||||
156
frontend/app/layouts/default.vue
Normal file
156
frontend/app/layouts/default.vue
Normal file
@@ -0,0 +1,156 @@
|
||||
<script setup>
|
||||
import { theme } from 'ant-design-vue'
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<a-config-provider
|
||||
:theme="{
|
||||
algorithm: theme.darkAlgorithm,
|
||||
token: {
|
||||
colorPrimary: '#89b4fa',
|
||||
colorBgContainer: '#252536',
|
||||
colorBgElevated: '#252536',
|
||||
colorBgLayout: '#1e1e2e',
|
||||
colorBgSpotlight: '#313244',
|
||||
colorBorder: '#313244',
|
||||
colorBorderSecondary: '#313244',
|
||||
colorText: '#cdd6f4',
|
||||
colorTextSecondary: '#a6adc8',
|
||||
colorTextTertiary: '#6c7086',
|
||||
colorTextQuaternary: '#6c7086',
|
||||
colorFill: '#313244',
|
||||
colorFillSecondary: '#45475a',
|
||||
colorFillTertiary: '#313244',
|
||||
colorFillQuaternary: '#252536',
|
||||
colorSuccess: '#a6e3a1',
|
||||
colorWarning: '#f9e2af',
|
||||
colorError: '#f38ba8',
|
||||
colorInfo: '#89b4fa',
|
||||
borderRadius: 6,
|
||||
fontFamily: `'Segoe UI', -apple-system, BlinkMacSystemFont, sans-serif`,
|
||||
fontSize: 14,
|
||||
colorBgMask: 'rgba(0, 0, 0, 0.6)',
|
||||
},
|
||||
components: {
|
||||
Tree: {
|
||||
directoryNodeSelectedBg: '#45475a',
|
||||
nodeSelectedBg: '#45475a',
|
||||
nodeHoverBg: '#313244',
|
||||
},
|
||||
Menu: {
|
||||
itemBg: '#252536',
|
||||
itemHoverBg: '#313244',
|
||||
itemSelectedBg: '#45475a',
|
||||
darkItemBg: '#252536',
|
||||
},
|
||||
Modal: {
|
||||
contentBg: '#252536',
|
||||
headerBg: '#252536',
|
||||
footerBg: '#252536',
|
||||
},
|
||||
Button: {
|
||||
defaultBg: '#313244',
|
||||
defaultBorderColor: '#313244',
|
||||
},
|
||||
Input: {
|
||||
activeBg: '#1e1e2e',
|
||||
hoverBg: '#1e1e2e',
|
||||
colorBgContainer: '#1e1e2e',
|
||||
},
|
||||
Select: {
|
||||
colorBgContainer: '#1e1e2e',
|
||||
optionActiveBg: '#313244',
|
||||
optionSelectedBg: '#45475a',
|
||||
},
|
||||
}
|
||||
}"
|
||||
>
|
||||
<div id="app-root">
|
||||
<slot />
|
||||
</div>
|
||||
</a-config-provider>
|
||||
</template>
|
||||
|
||||
<style>
|
||||
* {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
html, body, #app-root, #__nuxt {
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
:root {
|
||||
--sidebar-width: 280px;
|
||||
--header-height: 40px;
|
||||
--bg-primary: #1e1e2e;
|
||||
--bg-secondary: #181825;
|
||||
--bg-surface: #252536;
|
||||
--bg-hover: #313244;
|
||||
--bg-active: #45475a;
|
||||
--text-primary: #cdd6f4;
|
||||
--text-secondary: #a6adc8;
|
||||
--text-muted: #6c7086;
|
||||
--border-color: #313244;
|
||||
--accent: #89b4fa;
|
||||
--accent-hover: #74c7ec;
|
||||
--danger: #f38ba8;
|
||||
--success: #a6e3a1;
|
||||
--warning: #f9e2af;
|
||||
}
|
||||
|
||||
body {
|
||||
font-family: 'Segoe UI', -apple-system, BlinkMacSystemFont, sans-serif;
|
||||
background: var(--bg-primary);
|
||||
color: var(--text-primary);
|
||||
font-size: 14px;
|
||||
user-select: none;
|
||||
-webkit-user-select: none;
|
||||
}
|
||||
|
||||
::-webkit-scrollbar {
|
||||
width: 6px;
|
||||
height: 6px;
|
||||
}
|
||||
|
||||
::-webkit-scrollbar-track {
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
::-webkit-scrollbar-thumb {
|
||||
background: var(--bg-active);
|
||||
border-radius: 3px;
|
||||
}
|
||||
|
||||
::-webkit-scrollbar-thumb:hover {
|
||||
background: var(--text-muted);
|
||||
}
|
||||
|
||||
/* Ant Design 全局暗色覆盖 */
|
||||
.ant-modal-mask {
|
||||
background: rgba(0, 0, 0, 0.6) !important;
|
||||
}
|
||||
|
||||
.ant-btn-text {
|
||||
color: var(--text-secondary) !important;
|
||||
}
|
||||
|
||||
.ant-btn-text:hover {
|
||||
color: var(--text-primary) !important;
|
||||
background: var(--bg-hover) !important;
|
||||
}
|
||||
|
||||
.ant-segmented {
|
||||
background: var(--bg-primary) !important;
|
||||
color: var(--text-secondary) !important;
|
||||
}
|
||||
|
||||
.ant-segmented-item-selected {
|
||||
background: var(--bg-active) !important;
|
||||
color: var(--text-primary) !important;
|
||||
}
|
||||
</style>
|
||||
74
frontend/app/pages/index.vue
Normal file
74
frontend/app/pages/index.vue
Normal file
@@ -0,0 +1,74 @@
|
||||
<script setup>
|
||||
import { ref, onBeforeUnmount } from 'vue'
|
||||
|
||||
const selectedProject = ref(null)
|
||||
|
||||
function onSelectProject(project) {
|
||||
selectedProject.value = project
|
||||
}
|
||||
|
||||
// ---- 侧栏拖拽调整宽度 ----
|
||||
const sidebarWidth = ref(280)
|
||||
const MIN_SIDEBAR = 180
|
||||
const MAX_SIDEBAR = 500
|
||||
let draggingSidebar = false
|
||||
|
||||
function startSidebarResize(e) {
|
||||
e.preventDefault()
|
||||
draggingSidebar = true
|
||||
const startX = e.clientX
|
||||
const startW = sidebarWidth.value
|
||||
|
||||
function onMove(ev) {
|
||||
if (!draggingSidebar) return
|
||||
const delta = ev.clientX - startX
|
||||
sidebarWidth.value = Math.min(MAX_SIDEBAR, Math.max(MIN_SIDEBAR, startW + delta))
|
||||
}
|
||||
function onUp() {
|
||||
draggingSidebar = false
|
||||
document.removeEventListener('mousemove', onMove)
|
||||
document.removeEventListener('mouseup', onUp)
|
||||
document.body.style.cursor = ''
|
||||
document.body.style.userSelect = ''
|
||||
}
|
||||
document.body.style.cursor = 'col-resize'
|
||||
document.body.style.userSelect = 'none'
|
||||
document.addEventListener('mousemove', onMove)
|
||||
document.addEventListener('mouseup', onUp)
|
||||
}
|
||||
|
||||
onBeforeUnmount(() => {
|
||||
draggingSidebar = false
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="main-layout">
|
||||
<Sidebar :selected-project="selectedProject" :style="{ width: sidebarWidth + 'px' }" @select-project="onSelectProject" />
|
||||
<div class="resize-handle" @mousedown="startSidebarResize"></div>
|
||||
<ContentArea :project="selectedProject" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
.main-layout {
|
||||
display: flex;
|
||||
height: 100vh;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.resize-handle {
|
||||
width: 4px;
|
||||
cursor: col-resize;
|
||||
background: transparent;
|
||||
flex-shrink: 0;
|
||||
position: relative;
|
||||
z-index: 10;
|
||||
transition: background 0.15s;
|
||||
}
|
||||
|
||||
.resize-handle:hover,
|
||||
.resize-handle:active {
|
||||
background: var(--accent, #89b4fa);
|
||||
}
|
||||
</style>
|
||||
6
frontend/app/plugins/antd.ts
Normal file
6
frontend/app/plugins/antd.ts
Normal file
@@ -0,0 +1,6 @@
|
||||
import Antd from 'ant-design-vue'
|
||||
import 'ant-design-vue/dist/reset.css'
|
||||
|
||||
export default defineNuxtPlugin((nuxtApp) => {
|
||||
nuxtApp.vueApp.use(Antd)
|
||||
})
|
||||
@@ -0,0 +1,9 @@
|
||||
//@ts-check
|
||||
// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL
|
||||
// This file is automatically generated. DO NOT EDIT
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||
// @ts-ignore: Unused imports
|
||||
import { Create as $Create } from "@wailsio/runtime";
|
||||
|
||||
Object.freeze($Create.Events);
|
||||
2
frontend/bindings/github.com/wailsapp/wails/v3/internal/eventdata.d.ts
vendored
Normal file
2
frontend/bindings/github.com/wailsapp/wails/v3/internal/eventdata.d.ts
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL
|
||||
// This file is automatically generated. DO NOT EDIT
|
||||
@@ -0,0 +1,18 @@
|
||||
// @ts-check
|
||||
// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL
|
||||
// This file is automatically generated. DO NOT EDIT
|
||||
|
||||
export {
|
||||
App,
|
||||
BrowserManager,
|
||||
ClipboardManager,
|
||||
ContextMenuManager,
|
||||
DialogManager,
|
||||
EnvironmentManager,
|
||||
EventManager,
|
||||
KeyBindingManager,
|
||||
MenuManager,
|
||||
ScreenManager,
|
||||
SystemTrayManager,
|
||||
WindowManager
|
||||
} from "./models.js";
|
||||
@@ -0,0 +1,452 @@
|
||||
// @ts-check
|
||||
// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL
|
||||
// This file is automatically generated. DO NOT EDIT
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||
// @ts-ignore: Unused imports
|
||||
import { Create as $Create } from "@wailsio/runtime";
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||
// @ts-ignore: Unused imports
|
||||
import * as slog$0 from "../../../../../../log/slog/models.js";
|
||||
|
||||
export class App {
|
||||
/**
|
||||
* Creates a new App instance.
|
||||
* @param {Partial<App>} [$$source = {}] - The source object to create the App.
|
||||
*/
|
||||
constructor($$source = {}) {
|
||||
if (!("Window" in $$source)) {
|
||||
/**
|
||||
* Manager pattern for organized API
|
||||
* @member
|
||||
* @type {WindowManager | null}
|
||||
*/
|
||||
this["Window"] = null;
|
||||
}
|
||||
if (!("ContextMenu" in $$source)) {
|
||||
/**
|
||||
* @member
|
||||
* @type {ContextMenuManager | null}
|
||||
*/
|
||||
this["ContextMenu"] = null;
|
||||
}
|
||||
if (!("KeyBinding" in $$source)) {
|
||||
/**
|
||||
* @member
|
||||
* @type {KeyBindingManager | null}
|
||||
*/
|
||||
this["KeyBinding"] = null;
|
||||
}
|
||||
if (!("Browser" in $$source)) {
|
||||
/**
|
||||
* @member
|
||||
* @type {BrowserManager | null}
|
||||
*/
|
||||
this["Browser"] = null;
|
||||
}
|
||||
if (!("Env" in $$source)) {
|
||||
/**
|
||||
* @member
|
||||
* @type {EnvironmentManager | null}
|
||||
*/
|
||||
this["Env"] = null;
|
||||
}
|
||||
if (!("Dialog" in $$source)) {
|
||||
/**
|
||||
* @member
|
||||
* @type {DialogManager | null}
|
||||
*/
|
||||
this["Dialog"] = null;
|
||||
}
|
||||
if (!("Event" in $$source)) {
|
||||
/**
|
||||
* @member
|
||||
* @type {EventManager | null}
|
||||
*/
|
||||
this["Event"] = null;
|
||||
}
|
||||
if (!("Menu" in $$source)) {
|
||||
/**
|
||||
* @member
|
||||
* @type {MenuManager | null}
|
||||
*/
|
||||
this["Menu"] = null;
|
||||
}
|
||||
if (!("Screen" in $$source)) {
|
||||
/**
|
||||
* @member
|
||||
* @type {ScreenManager | null}
|
||||
*/
|
||||
this["Screen"] = null;
|
||||
}
|
||||
if (!("Clipboard" in $$source)) {
|
||||
/**
|
||||
* @member
|
||||
* @type {ClipboardManager | null}
|
||||
*/
|
||||
this["Clipboard"] = null;
|
||||
}
|
||||
if (!("SystemTray" in $$source)) {
|
||||
/**
|
||||
* @member
|
||||
* @type {SystemTrayManager | null}
|
||||
*/
|
||||
this["SystemTray"] = null;
|
||||
}
|
||||
if (!("Logger" in $$source)) {
|
||||
/**
|
||||
* @member
|
||||
* @type {slog$0.Logger | null}
|
||||
*/
|
||||
this["Logger"] = null;
|
||||
}
|
||||
|
||||
Object.assign(this, $$source);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new App instance from a string or object.
|
||||
* @param {any} [$$source = {}]
|
||||
* @returns {App}
|
||||
*/
|
||||
static createFrom($$source = {}) {
|
||||
const $$createField0_0 = $$createType1;
|
||||
const $$createField1_0 = $$createType3;
|
||||
const $$createField2_0 = $$createType5;
|
||||
const $$createField3_0 = $$createType7;
|
||||
const $$createField4_0 = $$createType9;
|
||||
const $$createField5_0 = $$createType11;
|
||||
const $$createField6_0 = $$createType13;
|
||||
const $$createField7_0 = $$createType15;
|
||||
const $$createField8_0 = $$createType17;
|
||||
const $$createField9_0 = $$createType19;
|
||||
const $$createField10_0 = $$createType21;
|
||||
const $$createField11_0 = $$createType23;
|
||||
let $$parsedSource = typeof $$source === 'string' ? JSON.parse($$source) : $$source;
|
||||
if ("Window" in $$parsedSource) {
|
||||
$$parsedSource["Window"] = $$createField0_0($$parsedSource["Window"]);
|
||||
}
|
||||
if ("ContextMenu" in $$parsedSource) {
|
||||
$$parsedSource["ContextMenu"] = $$createField1_0($$parsedSource["ContextMenu"]);
|
||||
}
|
||||
if ("KeyBinding" in $$parsedSource) {
|
||||
$$parsedSource["KeyBinding"] = $$createField2_0($$parsedSource["KeyBinding"]);
|
||||
}
|
||||
if ("Browser" in $$parsedSource) {
|
||||
$$parsedSource["Browser"] = $$createField3_0($$parsedSource["Browser"]);
|
||||
}
|
||||
if ("Env" in $$parsedSource) {
|
||||
$$parsedSource["Env"] = $$createField4_0($$parsedSource["Env"]);
|
||||
}
|
||||
if ("Dialog" in $$parsedSource) {
|
||||
$$parsedSource["Dialog"] = $$createField5_0($$parsedSource["Dialog"]);
|
||||
}
|
||||
if ("Event" in $$parsedSource) {
|
||||
$$parsedSource["Event"] = $$createField6_0($$parsedSource["Event"]);
|
||||
}
|
||||
if ("Menu" in $$parsedSource) {
|
||||
$$parsedSource["Menu"] = $$createField7_0($$parsedSource["Menu"]);
|
||||
}
|
||||
if ("Screen" in $$parsedSource) {
|
||||
$$parsedSource["Screen"] = $$createField8_0($$parsedSource["Screen"]);
|
||||
}
|
||||
if ("Clipboard" in $$parsedSource) {
|
||||
$$parsedSource["Clipboard"] = $$createField9_0($$parsedSource["Clipboard"]);
|
||||
}
|
||||
if ("SystemTray" in $$parsedSource) {
|
||||
$$parsedSource["SystemTray"] = $$createField10_0($$parsedSource["SystemTray"]);
|
||||
}
|
||||
if ("Logger" in $$parsedSource) {
|
||||
$$parsedSource["Logger"] = $$createField11_0($$parsedSource["Logger"]);
|
||||
}
|
||||
return new App(/** @type {Partial<App>} */($$parsedSource));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* BrowserManager manages browser-related operations
|
||||
*/
|
||||
export class BrowserManager {
|
||||
/**
|
||||
* Creates a new BrowserManager instance.
|
||||
* @param {Partial<BrowserManager>} [$$source = {}] - The source object to create the BrowserManager.
|
||||
*/
|
||||
constructor($$source = {}) {
|
||||
|
||||
Object.assign(this, $$source);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new BrowserManager instance from a string or object.
|
||||
* @param {any} [$$source = {}]
|
||||
* @returns {BrowserManager}
|
||||
*/
|
||||
static createFrom($$source = {}) {
|
||||
let $$parsedSource = typeof $$source === 'string' ? JSON.parse($$source) : $$source;
|
||||
return new BrowserManager(/** @type {Partial<BrowserManager>} */($$parsedSource));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* ClipboardManager manages clipboard operations
|
||||
*/
|
||||
export class ClipboardManager {
|
||||
/**
|
||||
* Creates a new ClipboardManager instance.
|
||||
* @param {Partial<ClipboardManager>} [$$source = {}] - The source object to create the ClipboardManager.
|
||||
*/
|
||||
constructor($$source = {}) {
|
||||
|
||||
Object.assign(this, $$source);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new ClipboardManager instance from a string or object.
|
||||
* @param {any} [$$source = {}]
|
||||
* @returns {ClipboardManager}
|
||||
*/
|
||||
static createFrom($$source = {}) {
|
||||
let $$parsedSource = typeof $$source === 'string' ? JSON.parse($$source) : $$source;
|
||||
return new ClipboardManager(/** @type {Partial<ClipboardManager>} */($$parsedSource));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* ContextMenuManager manages all context menu operations
|
||||
*/
|
||||
export class ContextMenuManager {
|
||||
/**
|
||||
* Creates a new ContextMenuManager instance.
|
||||
* @param {Partial<ContextMenuManager>} [$$source = {}] - The source object to create the ContextMenuManager.
|
||||
*/
|
||||
constructor($$source = {}) {
|
||||
|
||||
Object.assign(this, $$source);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new ContextMenuManager instance from a string or object.
|
||||
* @param {any} [$$source = {}]
|
||||
* @returns {ContextMenuManager}
|
||||
*/
|
||||
static createFrom($$source = {}) {
|
||||
let $$parsedSource = typeof $$source === 'string' ? JSON.parse($$source) : $$source;
|
||||
return new ContextMenuManager(/** @type {Partial<ContextMenuManager>} */($$parsedSource));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* DialogManager manages dialog-related operations
|
||||
*/
|
||||
export class DialogManager {
|
||||
/**
|
||||
* Creates a new DialogManager instance.
|
||||
* @param {Partial<DialogManager>} [$$source = {}] - The source object to create the DialogManager.
|
||||
*/
|
||||
constructor($$source = {}) {
|
||||
|
||||
Object.assign(this, $$source);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new DialogManager instance from a string or object.
|
||||
* @param {any} [$$source = {}]
|
||||
* @returns {DialogManager}
|
||||
*/
|
||||
static createFrom($$source = {}) {
|
||||
let $$parsedSource = typeof $$source === 'string' ? JSON.parse($$source) : $$source;
|
||||
return new DialogManager(/** @type {Partial<DialogManager>} */($$parsedSource));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* EnvironmentManager manages environment-related operations
|
||||
*/
|
||||
export class EnvironmentManager {
|
||||
/**
|
||||
* Creates a new EnvironmentManager instance.
|
||||
* @param {Partial<EnvironmentManager>} [$$source = {}] - The source object to create the EnvironmentManager.
|
||||
*/
|
||||
constructor($$source = {}) {
|
||||
|
||||
Object.assign(this, $$source);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new EnvironmentManager instance from a string or object.
|
||||
* @param {any} [$$source = {}]
|
||||
* @returns {EnvironmentManager}
|
||||
*/
|
||||
static createFrom($$source = {}) {
|
||||
let $$parsedSource = typeof $$source === 'string' ? JSON.parse($$source) : $$source;
|
||||
return new EnvironmentManager(/** @type {Partial<EnvironmentManager>} */($$parsedSource));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* EventManager manages event-related operations
|
||||
*/
|
||||
export class EventManager {
|
||||
/**
|
||||
* Creates a new EventManager instance.
|
||||
* @param {Partial<EventManager>} [$$source = {}] - The source object to create the EventManager.
|
||||
*/
|
||||
constructor($$source = {}) {
|
||||
|
||||
Object.assign(this, $$source);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new EventManager instance from a string or object.
|
||||
* @param {any} [$$source = {}]
|
||||
* @returns {EventManager}
|
||||
*/
|
||||
static createFrom($$source = {}) {
|
||||
let $$parsedSource = typeof $$source === 'string' ? JSON.parse($$source) : $$source;
|
||||
return new EventManager(/** @type {Partial<EventManager>} */($$parsedSource));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* KeyBindingManager manages all key binding operations
|
||||
*/
|
||||
export class KeyBindingManager {
|
||||
/**
|
||||
* Creates a new KeyBindingManager instance.
|
||||
* @param {Partial<KeyBindingManager>} [$$source = {}] - The source object to create the KeyBindingManager.
|
||||
*/
|
||||
constructor($$source = {}) {
|
||||
|
||||
Object.assign(this, $$source);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new KeyBindingManager instance from a string or object.
|
||||
* @param {any} [$$source = {}]
|
||||
* @returns {KeyBindingManager}
|
||||
*/
|
||||
static createFrom($$source = {}) {
|
||||
let $$parsedSource = typeof $$source === 'string' ? JSON.parse($$source) : $$source;
|
||||
return new KeyBindingManager(/** @type {Partial<KeyBindingManager>} */($$parsedSource));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* MenuManager manages menu-related operations
|
||||
*/
|
||||
export class MenuManager {
|
||||
/**
|
||||
* Creates a new MenuManager instance.
|
||||
* @param {Partial<MenuManager>} [$$source = {}] - The source object to create the MenuManager.
|
||||
*/
|
||||
constructor($$source = {}) {
|
||||
|
||||
Object.assign(this, $$source);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new MenuManager instance from a string or object.
|
||||
* @param {any} [$$source = {}]
|
||||
* @returns {MenuManager}
|
||||
*/
|
||||
static createFrom($$source = {}) {
|
||||
let $$parsedSource = typeof $$source === 'string' ? JSON.parse($$source) : $$source;
|
||||
return new MenuManager(/** @type {Partial<MenuManager>} */($$parsedSource));
|
||||
}
|
||||
}
|
||||
|
||||
export class ScreenManager {
|
||||
/**
|
||||
* Creates a new ScreenManager instance.
|
||||
* @param {Partial<ScreenManager>} [$$source = {}] - The source object to create the ScreenManager.
|
||||
*/
|
||||
constructor($$source = {}) {
|
||||
|
||||
Object.assign(this, $$source);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new ScreenManager instance from a string or object.
|
||||
* @param {any} [$$source = {}]
|
||||
* @returns {ScreenManager}
|
||||
*/
|
||||
static createFrom($$source = {}) {
|
||||
let $$parsedSource = typeof $$source === 'string' ? JSON.parse($$source) : $$source;
|
||||
return new ScreenManager(/** @type {Partial<ScreenManager>} */($$parsedSource));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* SystemTrayManager manages system tray-related operations
|
||||
*/
|
||||
export class SystemTrayManager {
|
||||
/**
|
||||
* Creates a new SystemTrayManager instance.
|
||||
* @param {Partial<SystemTrayManager>} [$$source = {}] - The source object to create the SystemTrayManager.
|
||||
*/
|
||||
constructor($$source = {}) {
|
||||
|
||||
Object.assign(this, $$source);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new SystemTrayManager instance from a string or object.
|
||||
* @param {any} [$$source = {}]
|
||||
* @returns {SystemTrayManager}
|
||||
*/
|
||||
static createFrom($$source = {}) {
|
||||
let $$parsedSource = typeof $$source === 'string' ? JSON.parse($$source) : $$source;
|
||||
return new SystemTrayManager(/** @type {Partial<SystemTrayManager>} */($$parsedSource));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* WindowManager manages all window-related operations
|
||||
*/
|
||||
export class WindowManager {
|
||||
/**
|
||||
* Creates a new WindowManager instance.
|
||||
* @param {Partial<WindowManager>} [$$source = {}] - The source object to create the WindowManager.
|
||||
*/
|
||||
constructor($$source = {}) {
|
||||
|
||||
Object.assign(this, $$source);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new WindowManager instance from a string or object.
|
||||
* @param {any} [$$source = {}]
|
||||
* @returns {WindowManager}
|
||||
*/
|
||||
static createFrom($$source = {}) {
|
||||
let $$parsedSource = typeof $$source === 'string' ? JSON.parse($$source) : $$source;
|
||||
return new WindowManager(/** @type {Partial<WindowManager>} */($$parsedSource));
|
||||
}
|
||||
}
|
||||
|
||||
// Private type creation functions
|
||||
const $$createType0 = WindowManager.createFrom;
|
||||
const $$createType1 = $Create.Nullable($$createType0);
|
||||
const $$createType2 = ContextMenuManager.createFrom;
|
||||
const $$createType3 = $Create.Nullable($$createType2);
|
||||
const $$createType4 = KeyBindingManager.createFrom;
|
||||
const $$createType5 = $Create.Nullable($$createType4);
|
||||
const $$createType6 = BrowserManager.createFrom;
|
||||
const $$createType7 = $Create.Nullable($$createType6);
|
||||
const $$createType8 = EnvironmentManager.createFrom;
|
||||
const $$createType9 = $Create.Nullable($$createType8);
|
||||
const $$createType10 = DialogManager.createFrom;
|
||||
const $$createType11 = $Create.Nullable($$createType10);
|
||||
const $$createType12 = EventManager.createFrom;
|
||||
const $$createType13 = $Create.Nullable($$createType12);
|
||||
const $$createType14 = MenuManager.createFrom;
|
||||
const $$createType15 = $Create.Nullable($$createType14);
|
||||
const $$createType16 = ScreenManager.createFrom;
|
||||
const $$createType17 = $Create.Nullable($$createType16);
|
||||
const $$createType18 = ClipboardManager.createFrom;
|
||||
const $$createType19 = $Create.Nullable($$createType18);
|
||||
const $$createType20 = SystemTrayManager.createFrom;
|
||||
const $$createType21 = $Create.Nullable($$createType20);
|
||||
const $$createType22 = slog$0.Logger.createFrom;
|
||||
const $$createType23 = $Create.Nullable($$createType22);
|
||||
@@ -0,0 +1,387 @@
|
||||
// @ts-check
|
||||
// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL
|
||||
// This file is automatically generated. DO NOT EDIT
|
||||
|
||||
/**
|
||||
* AppService 应用服务,暴露给前端调用
|
||||
* @module
|
||||
*/
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||
// @ts-ignore: Unused imports
|
||||
import { Call as $Call, CancellablePromise as $CancellablePromise, Create as $Create } from "@wailsio/runtime";
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||
// @ts-ignore: Unused imports
|
||||
import * as application$0 from "../../../../wailsapp/wails/v3/pkg/application/models.js";
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||
// @ts-ignore: Unused imports
|
||||
import * as $models from "./models.js";
|
||||
|
||||
/**
|
||||
* AddPlatform 添加新平台
|
||||
* @param {string} name
|
||||
* @param {string} baseURL
|
||||
* @returns {$CancellablePromise<void>}
|
||||
*/
|
||||
export function AddPlatform(name, baseURL) {
|
||||
return $Call.ByID(526003212, name, baseURL);
|
||||
}
|
||||
|
||||
/**
|
||||
* AddProject 添加项目到指定平台/用户下
|
||||
* @param {string} platform
|
||||
* @param {string} username
|
||||
* @param {string} name
|
||||
* @param {string} path
|
||||
* @returns {$CancellablePromise<void>}
|
||||
*/
|
||||
export function AddProject(platform, username, name, path) {
|
||||
return $Call.ByID(2299402672, platform, username, name, path);
|
||||
}
|
||||
|
||||
/**
|
||||
* AddUser 添加用户到指定平台
|
||||
* @param {string} platform
|
||||
* @param {string} username
|
||||
* @param {string} token
|
||||
* @returns {$CancellablePromise<void>}
|
||||
*/
|
||||
export function AddUser(platform, username, token) {
|
||||
return $Call.ByID(2264426704, platform, username, token);
|
||||
}
|
||||
|
||||
/**
|
||||
* CommitChanges 提交已暂存的更改
|
||||
* @param {string} path
|
||||
* @param {string} message
|
||||
* @returns {$CancellablePromise<void>}
|
||||
*/
|
||||
export function CommitChanges(path, message) {
|
||||
return $Call.ByID(921984546, path, message);
|
||||
}
|
||||
|
||||
/**
|
||||
* DiscardFiles 丢弃工作区指定文件的更改
|
||||
* @param {string} path
|
||||
* @param {string[]} files
|
||||
* @returns {$CancellablePromise<void>}
|
||||
*/
|
||||
export function DiscardFiles(path, files) {
|
||||
return $Call.ByID(382904301, path, files);
|
||||
}
|
||||
|
||||
/**
|
||||
* FetchProject 拉取远程信息
|
||||
* @param {string} path
|
||||
* @returns {$CancellablePromise<string>}
|
||||
*/
|
||||
export function FetchProject(path) {
|
||||
return $Call.ByID(3541106829, path);
|
||||
}
|
||||
|
||||
/**
|
||||
* GetBranches 获取所有本地分支
|
||||
* @param {string} path
|
||||
* @returns {$CancellablePromise<$models.BranchInfo[]>}
|
||||
*/
|
||||
export function GetBranches(path) {
|
||||
return $Call.ByID(1686190192, path).then(/** @type {($result: any) => any} */(($result) => {
|
||||
return $$createType1($result);
|
||||
}));
|
||||
}
|
||||
|
||||
/**
|
||||
* GetCommitDiff 获取指定提交的 diff
|
||||
* @param {string} path
|
||||
* @param {string} hash
|
||||
* @returns {$CancellablePromise<string>}
|
||||
*/
|
||||
export function GetCommitDiff(path, hash) {
|
||||
return $Call.ByID(3678609798, path, hash);
|
||||
}
|
||||
|
||||
/**
|
||||
* GetCommitFileDiff 获取指定提交中某个文件的 diff
|
||||
* @param {string} path
|
||||
* @param {string} hash
|
||||
* @param {string} filePath
|
||||
* @returns {$CancellablePromise<string>}
|
||||
*/
|
||||
export function GetCommitFileDiff(path, hash, filePath) {
|
||||
return $Call.ByID(880053428, path, hash, filePath);
|
||||
}
|
||||
|
||||
/**
|
||||
* GetCommitFiles 获取指定提交中变更的文件列表
|
||||
* @param {string} path
|
||||
* @param {string} hash
|
||||
* @returns {$CancellablePromise<$models.CommitFileInfo[]>}
|
||||
*/
|
||||
export function GetCommitFiles(path, hash) {
|
||||
return $Call.ByID(2420707876, path, hash).then(/** @type {($result: any) => any} */(($result) => {
|
||||
return $$createType3($result);
|
||||
}));
|
||||
}
|
||||
|
||||
/**
|
||||
* GetCommitLog 获取提交历史
|
||||
* @param {string} path
|
||||
* @param {number} count
|
||||
* @returns {$CancellablePromise<$models.CommitLog[]>}
|
||||
*/
|
||||
export function GetCommitLog(path, count) {
|
||||
return $Call.ByID(1281870789, path, count).then(/** @type {($result: any) => any} */(($result) => {
|
||||
return $$createType5($result);
|
||||
}));
|
||||
}
|
||||
|
||||
/**
|
||||
* GetFileContent 获取文件内容
|
||||
* @param {string} projectPath
|
||||
* @param {string} filePath
|
||||
* @returns {$CancellablePromise<string>}
|
||||
*/
|
||||
export function GetFileContent(projectPath, filePath) {
|
||||
return $Call.ByID(3085630035, projectPath, filePath);
|
||||
}
|
||||
|
||||
/**
|
||||
* GetFileDiff 获取文件 diff
|
||||
* @param {string} projectPath
|
||||
* @param {string} filePath
|
||||
* @returns {$CancellablePromise<string>}
|
||||
*/
|
||||
export function GetFileDiff(projectPath, filePath) {
|
||||
return $Call.ByID(1694304929, projectPath, filePath);
|
||||
}
|
||||
|
||||
/**
|
||||
* GetFileDiffStaged 获取已暂存文件的 diff
|
||||
* @param {string} projectPath
|
||||
* @param {string} filePath
|
||||
* @returns {$CancellablePromise<string>}
|
||||
*/
|
||||
export function GetFileDiffStaged(projectPath, filePath) {
|
||||
return $Call.ByID(2773256455, projectPath, filePath);
|
||||
}
|
||||
|
||||
/**
|
||||
* GetPlatformInfo 获取平台信息
|
||||
* @param {string} name
|
||||
* @returns {$CancellablePromise<$models.PlatformInfo | null>}
|
||||
*/
|
||||
export function GetPlatformInfo(name) {
|
||||
return $Call.ByID(2668095547, name).then(/** @type {($result: any) => any} */(($result) => {
|
||||
return $$createType7($result);
|
||||
}));
|
||||
}
|
||||
|
||||
/**
|
||||
* GetProjectChangedFiles 获取项目变更文件列表(可能较慢)
|
||||
* @param {string} path
|
||||
* @returns {$CancellablePromise<$models.FileInfo[]>}
|
||||
*/
|
||||
export function GetProjectChangedFiles(path) {
|
||||
return $Call.ByID(2302591462, path).then(/** @type {($result: any) => any} */(($result) => {
|
||||
return $$createType9($result);
|
||||
}));
|
||||
}
|
||||
|
||||
/**
|
||||
* GetProjectStatus 获取项目 git 状态
|
||||
* @param {string} path
|
||||
* @returns {$CancellablePromise<$models.ProjectStatus | null>}
|
||||
*/
|
||||
export function GetProjectStatus(path) {
|
||||
return $Call.ByID(3451089027, path).then(/** @type {($result: any) => any} */(($result) => {
|
||||
return $$createType11($result);
|
||||
}));
|
||||
}
|
||||
|
||||
/**
|
||||
* GetProjectTree 获取项目树,供前端侧边栏渲染
|
||||
* @returns {$CancellablePromise<$models.TreeNode[]>}
|
||||
*/
|
||||
export function GetProjectTree() {
|
||||
return $Call.ByID(651189689).then(/** @type {($result: any) => any} */(($result) => {
|
||||
return $$createType13($result);
|
||||
}));
|
||||
}
|
||||
|
||||
/**
|
||||
* GetUserInfo 获取用户信息
|
||||
* @param {string} platform
|
||||
* @param {string} username
|
||||
* @returns {$CancellablePromise<$models.UserInfo | null>}
|
||||
*/
|
||||
export function GetUserInfo(platform, username) {
|
||||
return $Call.ByID(2674655707, platform, username).then(/** @type {($result: any) => any} */(($result) => {
|
||||
return $$createType15($result);
|
||||
}));
|
||||
}
|
||||
|
||||
/**
|
||||
* PullProject 拉取项目(当前分支)
|
||||
* @param {string} path
|
||||
* @returns {$CancellablePromise<string>}
|
||||
*/
|
||||
export function PullProject(path) {
|
||||
return $Call.ByID(4145813996, path);
|
||||
}
|
||||
|
||||
/**
|
||||
* PushProject 推送项目(当前分支)
|
||||
* @param {string} path
|
||||
* @returns {$CancellablePromise<string>}
|
||||
*/
|
||||
export function PushProject(path) {
|
||||
return $Call.ByID(3887901113, path);
|
||||
}
|
||||
|
||||
/**
|
||||
* RemovePlatform 删除平台
|
||||
* @param {string} name
|
||||
* @returns {$CancellablePromise<void>}
|
||||
*/
|
||||
export function RemovePlatform(name) {
|
||||
return $Call.ByID(2222448051, name);
|
||||
}
|
||||
|
||||
/**
|
||||
* RemoveProject 从指定平台/用户下删除项目
|
||||
* @param {string} platform
|
||||
* @param {string} username
|
||||
* @param {string} name
|
||||
* @returns {$CancellablePromise<void>}
|
||||
*/
|
||||
export function RemoveProject(platform, username, name) {
|
||||
return $Call.ByID(2748109581, platform, username, name);
|
||||
}
|
||||
|
||||
/**
|
||||
* RemoveUser 从平台删除用户
|
||||
* @param {string} platform
|
||||
* @param {string} username
|
||||
* @returns {$CancellablePromise<void>}
|
||||
*/
|
||||
export function RemoveUser(platform, username) {
|
||||
return $Call.ByID(1409517275, platform, username);
|
||||
}
|
||||
|
||||
/**
|
||||
* ResetProject 版本回滚(git reset)
|
||||
* mode: "hard"(丢弃所有更改), "soft"(保留更改到暂存区), "mixed"(保留更改到工作区)
|
||||
* @param {string} path
|
||||
* @param {string} hash
|
||||
* @param {string} mode
|
||||
* @returns {$CancellablePromise<void>}
|
||||
*/
|
||||
export function ResetProject(path, hash, mode) {
|
||||
return $Call.ByID(2061148684, path, hash, mode);
|
||||
}
|
||||
|
||||
/**
|
||||
* SelectDirectory 打开系统文件夹选择器,返回选中的路径
|
||||
* @returns {$CancellablePromise<string>}
|
||||
*/
|
||||
export function SelectDirectory() {
|
||||
return $Call.ByID(2318416763);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {application$0.App | null} app
|
||||
* @returns {$CancellablePromise<void>}
|
||||
*/
|
||||
export function SetApplication(app) {
|
||||
return $Call.ByID(383695022, app);
|
||||
}
|
||||
|
||||
/**
|
||||
* StageAll 暂存所有变更文件
|
||||
* @param {string} path
|
||||
* @returns {$CancellablePromise<void>}
|
||||
*/
|
||||
export function StageAll(path) {
|
||||
return $Call.ByID(2344562461, path);
|
||||
}
|
||||
|
||||
/**
|
||||
* StageFiles 暂存指定文件
|
||||
* @param {string} path
|
||||
* @param {string[]} files
|
||||
* @returns {$CancellablePromise<void>}
|
||||
*/
|
||||
export function StageFiles(path, files) {
|
||||
return $Call.ByID(4064506881, path, files);
|
||||
}
|
||||
|
||||
/**
|
||||
* SwitchBranch 切换分支
|
||||
* @param {string} path
|
||||
* @param {string} branch
|
||||
* @returns {$CancellablePromise<void>}
|
||||
*/
|
||||
export function SwitchBranch(path, branch) {
|
||||
return $Call.ByID(4262224900, path, branch);
|
||||
}
|
||||
|
||||
/**
|
||||
* UnstageAll 取消暂存所有文件
|
||||
* @param {string} path
|
||||
* @returns {$CancellablePromise<void>}
|
||||
*/
|
||||
export function UnstageAll(path) {
|
||||
return $Call.ByID(2417621882, path);
|
||||
}
|
||||
|
||||
/**
|
||||
* UnstageFiles 取消暂存指定文件
|
||||
* @param {string} path
|
||||
* @param {string[]} files
|
||||
* @returns {$CancellablePromise<void>}
|
||||
*/
|
||||
export function UnstageFiles(path, files) {
|
||||
return $Call.ByID(3546473046, path, files);
|
||||
}
|
||||
|
||||
/**
|
||||
* UpdatePlatform 修改平台信息(base_url)
|
||||
* @param {string} name
|
||||
* @param {string} baseURL
|
||||
* @returns {$CancellablePromise<void>}
|
||||
*/
|
||||
export function UpdatePlatform(name, baseURL) {
|
||||
return $Call.ByID(3258014550, name, baseURL);
|
||||
}
|
||||
|
||||
/**
|
||||
* UpdateUser 修改用户信息(用户名、token)
|
||||
* @param {string} platform
|
||||
* @param {string} oldUsername
|
||||
* @param {string} newUsername
|
||||
* @param {string} token
|
||||
* @returns {$CancellablePromise<void>}
|
||||
*/
|
||||
export function UpdateUser(platform, oldUsername, newUsername, token) {
|
||||
return $Call.ByID(1631729342, platform, oldUsername, newUsername, token);
|
||||
}
|
||||
|
||||
// Private type creation functions
|
||||
const $$createType0 = $models.BranchInfo.createFrom;
|
||||
const $$createType1 = $Create.Array($$createType0);
|
||||
const $$createType2 = $models.CommitFileInfo.createFrom;
|
||||
const $$createType3 = $Create.Array($$createType2);
|
||||
const $$createType4 = $models.CommitLog.createFrom;
|
||||
const $$createType5 = $Create.Array($$createType4);
|
||||
const $$createType6 = $models.PlatformInfo.createFrom;
|
||||
const $$createType7 = $Create.Nullable($$createType6);
|
||||
const $$createType8 = $models.FileInfo.createFrom;
|
||||
const $$createType9 = $Create.Array($$createType8);
|
||||
const $$createType10 = $models.ProjectStatus.createFrom;
|
||||
const $$createType11 = $Create.Nullable($$createType10);
|
||||
const $$createType12 = $models.TreeNode.createFrom;
|
||||
const $$createType13 = $Create.Array($$createType12);
|
||||
const $$createType14 = $models.UserInfo.createFrom;
|
||||
const $$createType15 = $Create.Nullable($$createType14);
|
||||
@@ -0,0 +1,19 @@
|
||||
// @ts-check
|
||||
// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL
|
||||
// This file is automatically generated. DO NOT EDIT
|
||||
|
||||
import * as AppService from "./appservice.js";
|
||||
export {
|
||||
AppService
|
||||
};
|
||||
|
||||
export {
|
||||
BranchInfo,
|
||||
CommitFileInfo,
|
||||
CommitLog,
|
||||
FileInfo,
|
||||
PlatformInfo,
|
||||
ProjectStatus,
|
||||
TreeNode,
|
||||
UserInfo
|
||||
} from "./models.js";
|
||||
@@ -0,0 +1,396 @@
|
||||
// @ts-check
|
||||
// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL
|
||||
// This file is automatically generated. DO NOT EDIT
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||
// @ts-ignore: Unused imports
|
||||
import { Create as $Create } from "@wailsio/runtime";
|
||||
|
||||
/**
|
||||
* BranchInfo 分支信息
|
||||
*/
|
||||
export class BranchInfo {
|
||||
/**
|
||||
* Creates a new BranchInfo instance.
|
||||
* @param {Partial<BranchInfo>} [$$source = {}] - The source object to create the BranchInfo.
|
||||
*/
|
||||
constructor($$source = {}) {
|
||||
if (!("name" in $$source)) {
|
||||
/**
|
||||
* @member
|
||||
* @type {string}
|
||||
*/
|
||||
this["name"] = "";
|
||||
}
|
||||
if (!("current" in $$source)) {
|
||||
/**
|
||||
* @member
|
||||
* @type {boolean}
|
||||
*/
|
||||
this["current"] = false;
|
||||
}
|
||||
|
||||
Object.assign(this, $$source);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new BranchInfo instance from a string or object.
|
||||
* @param {any} [$$source = {}]
|
||||
* @returns {BranchInfo}
|
||||
*/
|
||||
static createFrom($$source = {}) {
|
||||
let $$parsedSource = typeof $$source === 'string' ? JSON.parse($$source) : $$source;
|
||||
return new BranchInfo(/** @type {Partial<BranchInfo>} */($$parsedSource));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* CommitFileInfo 提交中的文件变更信息
|
||||
*/
|
||||
export class CommitFileInfo {
|
||||
/**
|
||||
* Creates a new CommitFileInfo instance.
|
||||
* @param {Partial<CommitFileInfo>} [$$source = {}] - The source object to create the CommitFileInfo.
|
||||
*/
|
||||
constructor($$source = {}) {
|
||||
if (!("status" in $$source)) {
|
||||
/**
|
||||
* @member
|
||||
* @type {string}
|
||||
*/
|
||||
this["status"] = "";
|
||||
}
|
||||
if (!("filePath" in $$source)) {
|
||||
/**
|
||||
* @member
|
||||
* @type {string}
|
||||
*/
|
||||
this["filePath"] = "";
|
||||
}
|
||||
|
||||
Object.assign(this, $$source);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new CommitFileInfo instance from a string or object.
|
||||
* @param {any} [$$source = {}]
|
||||
* @returns {CommitFileInfo}
|
||||
*/
|
||||
static createFrom($$source = {}) {
|
||||
let $$parsedSource = typeof $$source === 'string' ? JSON.parse($$source) : $$source;
|
||||
return new CommitFileInfo(/** @type {Partial<CommitFileInfo>} */($$parsedSource));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* CommitLog 提交记录
|
||||
*/
|
||||
export class CommitLog {
|
||||
/**
|
||||
* Creates a new CommitLog instance.
|
||||
* @param {Partial<CommitLog>} [$$source = {}] - The source object to create the CommitLog.
|
||||
*/
|
||||
constructor($$source = {}) {
|
||||
if (!("hash" in $$source)) {
|
||||
/**
|
||||
* @member
|
||||
* @type {string}
|
||||
*/
|
||||
this["hash"] = "";
|
||||
}
|
||||
if (!("shortHash" in $$source)) {
|
||||
/**
|
||||
* @member
|
||||
* @type {string}
|
||||
*/
|
||||
this["shortHash"] = "";
|
||||
}
|
||||
if (!("author" in $$source)) {
|
||||
/**
|
||||
* @member
|
||||
* @type {string}
|
||||
*/
|
||||
this["author"] = "";
|
||||
}
|
||||
if (!("email" in $$source)) {
|
||||
/**
|
||||
* @member
|
||||
* @type {string}
|
||||
*/
|
||||
this["email"] = "";
|
||||
}
|
||||
if (!("timestamp" in $$source)) {
|
||||
/**
|
||||
* @member
|
||||
* @type {number}
|
||||
*/
|
||||
this["timestamp"] = 0;
|
||||
}
|
||||
if (!("message" in $$source)) {
|
||||
/**
|
||||
* @member
|
||||
* @type {string}
|
||||
*/
|
||||
this["message"] = "";
|
||||
}
|
||||
|
||||
Object.assign(this, $$source);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new CommitLog instance from a string or object.
|
||||
* @param {any} [$$source = {}]
|
||||
* @returns {CommitLog}
|
||||
*/
|
||||
static createFrom($$source = {}) {
|
||||
let $$parsedSource = typeof $$source === 'string' ? JSON.parse($$source) : $$source;
|
||||
return new CommitLog(/** @type {Partial<CommitLog>} */($$parsedSource));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* FileInfo 文件信息
|
||||
*/
|
||||
export class FileInfo {
|
||||
/**
|
||||
* Creates a new FileInfo instance.
|
||||
* @param {Partial<FileInfo>} [$$source = {}] - The source object to create the FileInfo.
|
||||
*/
|
||||
constructor($$source = {}) {
|
||||
if (!("status" in $$source)) {
|
||||
/**
|
||||
* @member
|
||||
* @type {string}
|
||||
*/
|
||||
this["status"] = "";
|
||||
}
|
||||
if (!("statusText" in $$source)) {
|
||||
/**
|
||||
* @member
|
||||
* @type {string}
|
||||
*/
|
||||
this["statusText"] = "";
|
||||
}
|
||||
if (!("filePath" in $$source)) {
|
||||
/**
|
||||
* @member
|
||||
* @type {string}
|
||||
*/
|
||||
this["filePath"] = "";
|
||||
}
|
||||
if (!("staged" in $$source)) {
|
||||
/**
|
||||
* @member
|
||||
* @type {boolean}
|
||||
*/
|
||||
this["staged"] = false;
|
||||
}
|
||||
|
||||
Object.assign(this, $$source);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new FileInfo instance from a string or object.
|
||||
* @param {any} [$$source = {}]
|
||||
* @returns {FileInfo}
|
||||
*/
|
||||
static createFrom($$source = {}) {
|
||||
let $$parsedSource = typeof $$source === 'string' ? JSON.parse($$source) : $$source;
|
||||
return new FileInfo(/** @type {Partial<FileInfo>} */($$parsedSource));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* PlatformInfo 平台信息
|
||||
*/
|
||||
export class PlatformInfo {
|
||||
/**
|
||||
* Creates a new PlatformInfo instance.
|
||||
* @param {Partial<PlatformInfo>} [$$source = {}] - The source object to create the PlatformInfo.
|
||||
*/
|
||||
constructor($$source = {}) {
|
||||
if (!("name" in $$source)) {
|
||||
/**
|
||||
* @member
|
||||
* @type {string}
|
||||
*/
|
||||
this["name"] = "";
|
||||
}
|
||||
if (!("baseUrl" in $$source)) {
|
||||
/**
|
||||
* @member
|
||||
* @type {string}
|
||||
*/
|
||||
this["baseUrl"] = "";
|
||||
}
|
||||
|
||||
Object.assign(this, $$source);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new PlatformInfo instance from a string or object.
|
||||
* @param {any} [$$source = {}]
|
||||
* @returns {PlatformInfo}
|
||||
*/
|
||||
static createFrom($$source = {}) {
|
||||
let $$parsedSource = typeof $$source === 'string' ? JSON.parse($$source) : $$source;
|
||||
return new PlatformInfo(/** @type {Partial<PlatformInfo>} */($$parsedSource));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* ProjectStatus 项目状态信息
|
||||
*/
|
||||
export class ProjectStatus {
|
||||
/**
|
||||
* Creates a new ProjectStatus instance.
|
||||
* @param {Partial<ProjectStatus>} [$$source = {}] - The source object to create the ProjectStatus.
|
||||
*/
|
||||
constructor($$source = {}) {
|
||||
if (!("branch" in $$source)) {
|
||||
/**
|
||||
* @member
|
||||
* @type {string}
|
||||
*/
|
||||
this["branch"] = "";
|
||||
}
|
||||
if (!("remoteUrl" in $$source)) {
|
||||
/**
|
||||
* @member
|
||||
* @type {string}
|
||||
*/
|
||||
this["remoteUrl"] = "";
|
||||
}
|
||||
if (!("changedFiles" in $$source)) {
|
||||
/**
|
||||
* @member
|
||||
* @type {FileInfo[]}
|
||||
*/
|
||||
this["changedFiles"] = [];
|
||||
}
|
||||
|
||||
Object.assign(this, $$source);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new ProjectStatus instance from a string or object.
|
||||
* @param {any} [$$source = {}]
|
||||
* @returns {ProjectStatus}
|
||||
*/
|
||||
static createFrom($$source = {}) {
|
||||
const $$createField2_0 = $$createType1;
|
||||
let $$parsedSource = typeof $$source === 'string' ? JSON.parse($$source) : $$source;
|
||||
if ("changedFiles" in $$parsedSource) {
|
||||
$$parsedSource["changedFiles"] = $$createField2_0($$parsedSource["changedFiles"]);
|
||||
}
|
||||
return new ProjectStatus(/** @type {Partial<ProjectStatus>} */($$parsedSource));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* TreeNode 前端侧边栏树节点
|
||||
*/
|
||||
export class TreeNode {
|
||||
/**
|
||||
* Creates a new TreeNode instance.
|
||||
* @param {Partial<TreeNode>} [$$source = {}] - The source object to create the TreeNode.
|
||||
*/
|
||||
constructor($$source = {}) {
|
||||
if (!("key" in $$source)) {
|
||||
/**
|
||||
* @member
|
||||
* @type {string}
|
||||
*/
|
||||
this["key"] = "";
|
||||
}
|
||||
if (!("label" in $$source)) {
|
||||
/**
|
||||
* @member
|
||||
* @type {string}
|
||||
*/
|
||||
this["label"] = "";
|
||||
}
|
||||
if (!("type" in $$source)) {
|
||||
/**
|
||||
* platform, user, project
|
||||
* @member
|
||||
* @type {string}
|
||||
*/
|
||||
this["type"] = "";
|
||||
}
|
||||
if (/** @type {any} */(false)) {
|
||||
/**
|
||||
* @member
|
||||
* @type {string | undefined}
|
||||
*/
|
||||
this["path"] = undefined;
|
||||
}
|
||||
if (/** @type {any} */(false)) {
|
||||
/**
|
||||
* @member
|
||||
* @type {TreeNode[] | undefined}
|
||||
*/
|
||||
this["children"] = undefined;
|
||||
}
|
||||
|
||||
Object.assign(this, $$source);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new TreeNode instance from a string or object.
|
||||
* @param {any} [$$source = {}]
|
||||
* @returns {TreeNode}
|
||||
*/
|
||||
static createFrom($$source = {}) {
|
||||
const $$createField4_0 = $$createType3;
|
||||
let $$parsedSource = typeof $$source === 'string' ? JSON.parse($$source) : $$source;
|
||||
if ("children" in $$parsedSource) {
|
||||
$$parsedSource["children"] = $$createField4_0($$parsedSource["children"]);
|
||||
}
|
||||
return new TreeNode(/** @type {Partial<TreeNode>} */($$parsedSource));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* UserInfo 用户信息
|
||||
*/
|
||||
export class UserInfo {
|
||||
/**
|
||||
* Creates a new UserInfo instance.
|
||||
* @param {Partial<UserInfo>} [$$source = {}] - The source object to create the UserInfo.
|
||||
*/
|
||||
constructor($$source = {}) {
|
||||
if (!("username" in $$source)) {
|
||||
/**
|
||||
* @member
|
||||
* @type {string}
|
||||
*/
|
||||
this["username"] = "";
|
||||
}
|
||||
if (!("token" in $$source)) {
|
||||
/**
|
||||
* @member
|
||||
* @type {string}
|
||||
*/
|
||||
this["token"] = "";
|
||||
}
|
||||
|
||||
Object.assign(this, $$source);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new UserInfo instance from a string or object.
|
||||
* @param {any} [$$source = {}]
|
||||
* @returns {UserInfo}
|
||||
*/
|
||||
static createFrom($$source = {}) {
|
||||
let $$parsedSource = typeof $$source === 'string' ? JSON.parse($$source) : $$source;
|
||||
return new UserInfo(/** @type {Partial<UserInfo>} */($$parsedSource));
|
||||
}
|
||||
}
|
||||
|
||||
// Private type creation functions
|
||||
const $$createType0 = FileInfo.createFrom;
|
||||
const $$createType1 = $Create.Array($$createType0);
|
||||
const $$createType2 = TreeNode.createFrom;
|
||||
const $$createType3 = $Create.Array($$createType2);
|
||||
7
frontend/bindings/log/slog/index.js
Normal file
7
frontend/bindings/log/slog/index.js
Normal file
@@ -0,0 +1,7 @@
|
||||
// @ts-check
|
||||
// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL
|
||||
// This file is automatically generated. DO NOT EDIT
|
||||
|
||||
export {
|
||||
Logger
|
||||
} from "./models.js";
|
||||
36
frontend/bindings/log/slog/models.js
Normal file
36
frontend/bindings/log/slog/models.js
Normal file
@@ -0,0 +1,36 @@
|
||||
// @ts-check
|
||||
// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL
|
||||
// This file is automatically generated. DO NOT EDIT
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||
// @ts-ignore: Unused imports
|
||||
import { Create as $Create } from "@wailsio/runtime";
|
||||
|
||||
/**
|
||||
* A Logger records structured information about each call to its
|
||||
* Log, Debug, Info, Warn, and Error methods.
|
||||
* For each call, it creates a [Record] and passes it to a [Handler].
|
||||
*
|
||||
* To create a new Logger, call [New] or a Logger method
|
||||
* that begins "With".
|
||||
*/
|
||||
export class Logger {
|
||||
/**
|
||||
* Creates a new Logger instance.
|
||||
* @param {Partial<Logger>} [$$source = {}] - The source object to create the Logger.
|
||||
*/
|
||||
constructor($$source = {}) {
|
||||
|
||||
Object.assign(this, $$source);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new Logger instance from a string or object.
|
||||
* @param {any} [$$source = {}]
|
||||
* @returns {Logger}
|
||||
*/
|
||||
static createFrom($$source = {}) {
|
||||
let $$parsedSource = typeof $$source === 'string' ? JSON.parse($$source) : $$source;
|
||||
return new Logger(/** @type {Partial<Logger>} */($$parsedSource));
|
||||
}
|
||||
}
|
||||
20
frontend/nuxt.config.ts
Normal file
20
frontend/nuxt.config.ts
Normal file
@@ -0,0 +1,20 @@
|
||||
export default defineNuxtConfig({
|
||||
compatibilityDate: '2025-07-15',
|
||||
devtools: { enabled: true },
|
||||
ssr: false,
|
||||
nitro: {
|
||||
preset: 'static',
|
||||
output: {
|
||||
publicDir: './dist'
|
||||
}
|
||||
},
|
||||
vite: {
|
||||
optimizeDeps: {
|
||||
exclude: ['@wailsio/runtime']
|
||||
}
|
||||
},
|
||||
plugins: [
|
||||
'~/plugins/antd',
|
||||
],
|
||||
transpile: ['ant-design-vue', '@ant-design/icons-vue']
|
||||
})
|
||||
9975
frontend/package-lock.json
generated
Normal file
9975
frontend/package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
20
frontend/package.json
Normal file
20
frontend/package.json
Normal file
@@ -0,0 +1,20 @@
|
||||
{
|
||||
"name": "gitpilot-frontend",
|
||||
"type": "module",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"build": "nuxt build",
|
||||
"dev": "nuxt dev",
|
||||
"generate": "nuxt generate",
|
||||
"preview": "nuxt preview",
|
||||
"postinstall": "nuxt prepare"
|
||||
},
|
||||
"dependencies": {
|
||||
"@ant-design/icons-vue": "^7.0.1",
|
||||
"@wailsio/runtime": "^3.0.0-alpha.79",
|
||||
"ant-design-vue": "^4.2.6",
|
||||
"nuxt": "^4.1.2",
|
||||
"vue": "^3.5.21",
|
||||
"vue-router": "^4.5.1"
|
||||
}
|
||||
}
|
||||
BIN
frontend/public/appicon.png
Normal file
BIN
frontend/public/appicon.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 25 KiB |
2
frontend/public/robots.txt
Normal file
2
frontend/public/robots.txt
Normal file
@@ -0,0 +1,2 @@
|
||||
User-Agent: *
|
||||
Disallow:
|
||||
58
frontend/public/style.css
Normal file
58
frontend/public/style.css
Normal file
@@ -0,0 +1,58 @@
|
||||
:root {
|
||||
font-family: "Inter", -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto",
|
||||
"Oxygen", "Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue",
|
||||
sans-serif;
|
||||
font-size: 16px;
|
||||
line-height: 24px;
|
||||
font-weight: 400;
|
||||
color-scheme: light dark;
|
||||
color: rgba(255, 255, 255, 0.87);
|
||||
background-color: rgba(27, 38, 54, 1);
|
||||
font-synthesis: none;
|
||||
text-rendering: optimizeLegibility;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
-webkit-text-size-adjust: 100%;
|
||||
}
|
||||
|
||||
* {
|
||||
user-select: none;
|
||||
-webkit-user-select: none;
|
||||
-moz-user-select: none;
|
||||
-ms-user-select: none;
|
||||
}
|
||||
|
||||
body {
|
||||
margin: 0;
|
||||
display: flex;
|
||||
place-items: center;
|
||||
place-content: center;
|
||||
min-width: 320px;
|
||||
min-height: 100vh;
|
||||
}
|
||||
|
||||
h1 {
|
||||
font-size: 3.2em;
|
||||
line-height: 1.1;
|
||||
}
|
||||
|
||||
a {
|
||||
font-weight: 500;
|
||||
color: #646cff;
|
||||
text-decoration: inherit;
|
||||
}
|
||||
|
||||
a:hover {
|
||||
color: #535bf2;
|
||||
}
|
||||
|
||||
@media (prefers-color-scheme: light) {
|
||||
:root {
|
||||
color: #213547;
|
||||
background-color: #ffffff;
|
||||
}
|
||||
|
||||
a:hover {
|
||||
color: #747bff;
|
||||
}
|
||||
}
|
||||
9
frontend/tsconfig.json
Normal file
9
frontend/tsconfig.json
Normal file
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"files": [],
|
||||
"references": [
|
||||
{ "path": "./.nuxt/tsconfig.app.json" },
|
||||
{ "path": "./.nuxt/tsconfig.server.json" },
|
||||
{ "path": "./.nuxt/tsconfig.shared.json" },
|
||||
{ "path": "./.nuxt/tsconfig.node.json" }
|
||||
]
|
||||
}
|
||||
Reference in New Issue
Block a user