新增:文档体系重构+CHANGELOG补充+发布产物清理
This commit is contained in:
@@ -50,7 +50,7 @@ npm install
|
||||
npm run build
|
||||
```
|
||||
|
||||
这会生成 `web/dist` 目录,包含前端构建产物。
|
||||
这会生成 `frontend/dist` 目录,包含前端构建产物。
|
||||
|
||||
### 4. 开发模式运行
|
||||
|
||||
@@ -79,7 +79,7 @@ wails dev
|
||||
|
||||
## 常见问题
|
||||
|
||||
### 问题1:找不到 web/dist 目录
|
||||
### 问题1:找不到 frontend/dist 目录
|
||||
|
||||
**解决**:需要先构建前端
|
||||
```bash
|
||||
|
||||
@@ -38,7 +38,7 @@ go-desk/
|
||||
├── wails.json # Wails 配置文件
|
||||
├── go.mod # Go 模块依赖
|
||||
├── go.sum # Go 依赖校验
|
||||
├── web/ # 前端代码目录
|
||||
├── frontend/ # 前端代码目录
|
||||
│ ├── package.json # 前端依赖配置
|
||||
│ ├── package-lock.json # 依赖锁定文件
|
||||
│ ├── vite.config.js # Vite 构建配置
|
||||
@@ -62,8 +62,8 @@ go-desk/
|
||||
**目录说明:**
|
||||
- `app.go`: 定义应用结构体和方法,供前端调用
|
||||
- `main.go`: 程序入口,配置窗口、资源等
|
||||
- `web/`: 前端 Vue 项目,使用 Vite 构建
|
||||
- `web/dist/`: 前端构建产物,会被嵌入到 Go 二进制文件
|
||||
- `frontend/`: 前端 Vue 项目,使用 Vite 构建
|
||||
- `frontend/dist/`: 前端构建产物,会被嵌入到 Go 二进制文件
|
||||
- `build/`: 应用图标等构建资源
|
||||
|
||||
## 配置调整
|
||||
@@ -87,7 +87,7 @@ cd web
|
||||
npm install --save @arco-design/web-vue
|
||||
```
|
||||
|
||||
### 3. 修改 `web/src/main.js`
|
||||
### 3. 修改 `frontend/src/main.js`
|
||||
|
||||
```javascript
|
||||
import { createApp } from 'vue'
|
||||
@@ -101,7 +101,7 @@ app.use(ArcoVue)
|
||||
app.mount('#app')
|
||||
```
|
||||
|
||||
### 4. 修改 `web/src/App.vue`
|
||||
### 4. 修改 `frontend/src/App.vue`
|
||||
|
||||
```vue
|
||||
<template>
|
||||
@@ -217,7 +217,7 @@ import (
|
||||
"github.com/wailsapp/wails/v2/pkg/options/assetserver"
|
||||
)
|
||||
|
||||
//go:embed all:web/dist
|
||||
//go:embed all:frontend/dist
|
||||
var assets embed.FS
|
||||
|
||||
func main() {
|
||||
@@ -280,7 +280,7 @@ wails build -platform linux/amd64
|
||||
|
||||
## 注意事项
|
||||
|
||||
1. **前端构建**:每次修改前端代码后需要重新构建 `npm run build`,Wails 会使用 `web/dist` 目录
|
||||
1. **前端构建**:每次修改前端代码后需要重新构建 `npm run build`,Wails 会使用 `frontend/dist` 目录
|
||||
2. **Go 方法暴露**:在 `app.go` 中定义的方法会自动暴露给前端,通过 `window.go.main.MethodName` 调用
|
||||
3. **热重载**:开发模式下,Go 代码修改需要重启 `wails dev`,前端代码修改需要重新构建
|
||||
4. **资源嵌入**:使用 `//go:embed` 将前端构建产物嵌入到 Go 二进制文件中
|
||||
|
||||
@@ -252,7 +252,7 @@ go-desk/
|
||||
│ └── filesystem/
|
||||
│ └── fs.go # 文件系统操作
|
||||
├── app.go # 添加系统调用方法
|
||||
└── web/src/
|
||||
└── frontend/src/
|
||||
└── components/
|
||||
├── SystemInfo.vue # 系统信息组件
|
||||
└── FileSystem.vue # 文件系统组件
|
||||
|
||||
@@ -37,7 +37,7 @@
|
||||
|
||||
### 6. 前端错误处理可能不够完善 ⚠️
|
||||
|
||||
**位置**:`go-desk/web/src/views/db-cli/composables/useSqlExecution.ts`
|
||||
**位置**:`go-desk/frontend/src/views/db-cli/composables/useSqlExecution.ts`
|
||||
|
||||
**问题**:错误处理中使用了 `error.toString()`,可能在某些情况下无法正确显示错误信息。
|
||||
|
||||
|
||||
@@ -352,7 +352,7 @@ func (a *App) GetIndexes(connectionId uint, database, tableName string) ([]map[s
|
||||
### 2. 前端实现(Vue)
|
||||
|
||||
#### 表结构展示组件
|
||||
**文件**: `go-desk/web/src/views/db-cli/components/TableStructure.vue`
|
||||
**文件**: `go-desk/frontend/src/views/db-cli/components/TableStructure.vue`
|
||||
|
||||
```vue
|
||||
<template>
|
||||
@@ -589,7 +589,7 @@ onMounted(() => {
|
||||
```
|
||||
|
||||
#### 集成到主页面
|
||||
**文件**: `go-desk/web/src/views/db-cli/index.vue`
|
||||
**文件**: `go-desk/frontend/src/views/db-cli/index.vue`
|
||||
|
||||
```vue
|
||||
<!-- 表结构对话框 -->
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
### 2.1 核心实现 ✅
|
||||
|
||||
#### useStructureEdit.ts ✅
|
||||
- **位置**:`go-desk/web/src/views/db-cli/composables/useStructureEdit.ts`
|
||||
- **位置**:`go-desk/frontend/src/views/db-cli/composables/useStructureEdit.ts`
|
||||
- **功能**:
|
||||
- ✅ 编辑模式状态管理
|
||||
- ✅ 编辑数据管理(字段、索引)
|
||||
@@ -33,7 +33,7 @@
|
||||
- ✅ 字段/索引操作方法
|
||||
|
||||
#### ResultPanel.vue ✅
|
||||
- **位置**:`go-desk/web/src/views/db-cli/components/ResultPanel.vue`
|
||||
- **位置**:`go-desk/frontend/src/views/db-cli/components/ResultPanel.vue`
|
||||
- **功能**:
|
||||
- ✅ 添加结构操作栏
|
||||
- ✅ 模式切换按钮
|
||||
@@ -41,7 +41,7 @@
|
||||
- ✅ 根据模式显示不同按钮
|
||||
|
||||
#### index.vue ✅
|
||||
- **位置**:`go-desk/web/src/views/db-cli/index.vue`
|
||||
- **位置**:`go-desk/frontend/src/views/db-cli/index.vue`
|
||||
- **功能**:
|
||||
- ✅ 集成 useStructureEdit
|
||||
- ✅ 传递 editMode 到 ResultPanel
|
||||
|
||||
@@ -47,7 +47,7 @@
|
||||
|
||||
**行动步骤**:
|
||||
1. **创建ContextMenu组件**
|
||||
- 位置:`go-desk/web/src/views/db-cli/components/ContextMenu.vue`
|
||||
- 位置:`go-desk/frontend/src/views/db-cli/components/ContextMenu.vue`
|
||||
- 使用Arco Design Dropdown或自定义实现
|
||||
- 实现菜单定位、显示、隐藏逻辑
|
||||
|
||||
|
||||
@@ -273,5 +273,5 @@ components/
|
||||
## 十、相关文档
|
||||
|
||||
- [前端布局样式系统设计.md](../需求设计/前端布局样式系统设计.md)
|
||||
- [ConnectionTree.vue](../../../../go-desk/web/src/views/db-cli/components/ConnectionTree.vue)
|
||||
- [ConnectionTree.vue](../../../../go-desk/frontend/src/views/db-cli/components/ConnectionTree.vue)
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
**文档版本**:v2.0
|
||||
**维护者**:JueChen
|
||||
**更新日期**:2026-01-28
|
||||
**源码路径**:`go-desk/web/src/views/db-cli/`
|
||||
**源码路径**:`go-desk/frontend/src/views/db-cli/`
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -984,7 +984,7 @@ const handleEditorResultDividerMouseDown = (e: MouseEvent) => {
|
||||
### 8.5 滚动条处理
|
||||
|
||||
#### 全局滚动条样式
|
||||
系统使用统一的滚动条样式(定义在 `web/src/style.css`):
|
||||
系统使用统一的滚动条样式(定义在 `frontend/src/style.css`):
|
||||
|
||||
```css
|
||||
/* Webkit浏览器 (Chrome, Safari, Edge) */
|
||||
|
||||
69
docs/04-功能迭代/GO-DESK-5.Git集成/Git集成方案.md
Normal file
69
docs/04-功能迭代/GO-DESK-5.Git集成/Git集成方案.md
Normal file
@@ -0,0 +1,69 @@
|
||||
# Git 集成方案
|
||||
|
||||
> 调研日期:2026-04-11
|
||||
> 状态:已调研,待实现
|
||||
|
||||
## 1. 判定 Git 仓库
|
||||
|
||||
从目标路径逐级向上查找 `.git` 目录:
|
||||
|
||||
```bash
|
||||
git -C <path> rev-parse --is-inside-work-tree
|
||||
# 返回 "true" = 是 git 仓库
|
||||
```
|
||||
|
||||
Go 实现:`filepath.Walk` 向上遍历,检查 `.git` 目录存在性。
|
||||
|
||||
## 2. 可实现功能
|
||||
|
||||
| 功能 | 难度 | 命令 |
|
||||
|------|------|------|
|
||||
| 文件状态(修改/新增/删除/未跟踪) | 低 | `git status --porcelain=v1 <file>` |
|
||||
| 文件/文件夹提交历史 | 低 | `git log --oneline -20 -- <path>` |
|
||||
| 当前文件与 HEAD 的 diff | 中 | `git diff HEAD -- <file>` |
|
||||
| 某行代码 blame | 低 | `git blame <file>` |
|
||||
| 当前分支名 | 低 | `git branch --show-current` |
|
||||
|
||||
## 3. 实现架构
|
||||
|
||||
### Go 后端(~200 行)
|
||||
|
||||
```
|
||||
internal/git/
|
||||
├── git.go # 核心逻辑:判定仓库、执行命令、解析输出
|
||||
├── status.go # 文件状态查询
|
||||
├── history.go # 提交历史
|
||||
├── diff.go # 文件差异
|
||||
└── blame.go # 行级追溯
|
||||
```
|
||||
|
||||
关键接口设计:
|
||||
- `IsGitRepo(path string) bool` — 判定是否为 git 仓库
|
||||
- `GetFileStatus(path string) (string, error)` — 返回 M/A/D/? 状态码
|
||||
- `GetFileHistory(path string, limit int) ([]Commit, error)` — 提交历史
|
||||
- `GetFileDiff(path string) (string, error)` — diff 文本
|
||||
- `BlameFile(path string) ([]BlameLine, error)` — blame 结果
|
||||
|
||||
### 前端(~100 行)
|
||||
|
||||
- **文件列表**:图标列增加 git 状态小标记(M=修改, A=新增, D=删除, ?=未跟踪)
|
||||
- **右键菜单**:git 仓库内显示「查看历史」「查看 Diff」「Blame」等选项
|
||||
- **弹窗组件**:提交历史列表 / Diff 查看 / Blame 视图
|
||||
|
||||
### 调用方式
|
||||
|
||||
Go 侧通过 `os/exec.Command("git", "-C", repoPath, ...)` 执行系统 git 命令,
|
||||
解析 stdout 返回结构化数据给前端。
|
||||
|
||||
## 4. 前提条件
|
||||
|
||||
- 系统需安装 Git(Windows 上基本都有)
|
||||
- 仅在有 `.git` 的目录下激活相关功能
|
||||
- 大文件/二进制文件不做 diff/blame
|
||||
|
||||
## 5. 注意事项
|
||||
|
||||
- `git -C <path>` 确保 git 命令在正确仓库上下文执行
|
||||
- `--porcelain=v1` 输出格式稳定,适合程序解析
|
||||
- 中文路径需注意编码(UTF-8)
|
||||
- 性能:避免频繁调用 git 命令,考虑缓存结果
|
||||
320
docs/04-功能迭代/GO-DESK-6.文件操作增强/文件操作增强方案.md
Normal file
320
docs/04-功能迭代/GO-DESK-6.文件操作增强/文件操作增强方案.md
Normal file
@@ -0,0 +1,320 @@
|
||||
# 文件操作增强:多选 / 复制粘贴剪切 / 移动
|
||||
|
||||
> 状态:方案设计完成,待实施
|
||||
> 日期:2026-04-12
|
||||
|
||||
## 一、现状
|
||||
|
||||
| 功能 | 前端 | 后端 | 状态 |
|
||||
|------|------|------|------|
|
||||
| **多选** (Ctrl+Click / Shift+Click) | 无,单选 `selectedFileItem: FileItem \| null` | N/A | **缺失** |
|
||||
| **全选** (Ctrl+A) | 无 | N/A | **缺失** |
|
||||
| **复制文件** (Ctrl+C) | TODO stub(弹"暂未实现") | 无 API | **缺失** |
|
||||
| **剪切文件** (Ctrl+X) | 无 | 无 API | **缺失** |
|
||||
| **粘贴文件** (Ctrl+V) | 仅支持图片粘贴 | 无 API | **部分** |
|
||||
| **移动文件** | TODO stub(弹"暂未实现") | 无 API | **缺失** |
|
||||
| **重命名** (F2) | 完整 | 完整 | 已完成 |
|
||||
| **删除** (Del) | 完整(含回收站) | 完整 | 已完成 |
|
||||
| **右键菜单 Copy/Cut/Paste** | 无菜单项 | N/A | 缺失 |
|
||||
|
||||
### 关键发现
|
||||
|
||||
1. `useFileOperations.ts` 中 `copy()` 和 `move()` 已有函数签名但都是 TODO stub
|
||||
2. 回收站模块 (`recycle_bin.go`) 内部有 `copyRecursively`/`copyFile`/`copyDirectory` 私有方法可复用
|
||||
3. 快捷键已有 F5/F2/Del/Ctrl+S 等 12 个,缺 Ctrl+C/V/X/A 四个
|
||||
4. 右键菜单只有:新建文件、新建文件夹、系统打开、重命名、删除 — 缺复制/剪切/粘贴/移动
|
||||
|
||||
## 二、方案架构
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────┐
|
||||
│ 前端 (Vue 3) │
|
||||
│ │
|
||||
│ 1. 多选状态管理 (selectedFiles: FileItem[]) │
|
||||
│ 2. 剪贴板状态 (clipboard: {op, files[]}) │
|
||||
│ 3. FileListPanel: Ctrl+Click / Shift+Click │
|
||||
│ 4. ContextMenu: +Copy / Cut / Paste 项 │
|
||||
│ 5. 快捷键: Ctrl+C / V / X / A │
|
||||
└──────────────────┬──────────────────────────┘
|
||||
│ window.go.main.App.*
|
||||
┌──────────────────▼──────────────────────────┐
|
||||
│ 后端 (Go) │
|
||||
│ │
|
||||
│ 6. App.CopyPath(src, dst) → FileSystemService │
|
||||
│ 7. App.MovePath(src, dst) → os.Rename │
|
||||
│ 8. 复用 recycle_bin.go 的 copy 辅助函数 │
|
||||
└─────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
## 三、实施步骤
|
||||
|
||||
### Step 1:后端 — 新增 Copy / Move API
|
||||
|
||||
**文件**: `internal/filesystem/service.go`
|
||||
|
||||
新增两个公开方法(复用已有的私有 copy 函数):
|
||||
|
||||
```go
|
||||
// CopyPath 复制文件或目录
|
||||
func (s *FileSystemService) CopyPath(src, dst string) error {
|
||||
return copyRecursively(src, dst)
|
||||
}
|
||||
|
||||
// MovePath 移动文件或目录(跨盘需 copy+delete)
|
||||
func (s *FileSystemService) MovePath(src, dst string) error {
|
||||
// 同盘: os.Rename (原子操作)
|
||||
// 跨盘: copyRecursively + DeletePathWithContext
|
||||
}
|
||||
```
|
||||
|
||||
**文件**: `app.go`
|
||||
|
||||
新增两个绑定方法 + 请求结构体:
|
||||
|
||||
```go
|
||||
type CopyMoveRequest struct {
|
||||
Src string `json:"src"`
|
||||
Dst string `json:"dst"`
|
||||
}
|
||||
|
||||
func (a *App) CopyPath(req CopyMoveRequest) error {
|
||||
return a.filesystem.CopyPath(req.Src, req.Dst)
|
||||
}
|
||||
|
||||
func (a *App) MovePath(req CopyMoveRequest) error {
|
||||
return a.filesystem.MovePath(req.Src, req.Dst)
|
||||
}
|
||||
```
|
||||
|
||||
**文件**: `frontend/src/api/system.ts`
|
||||
|
||||
```ts
|
||||
export async function copyPath(src: string, dst: string): Promise<void>
|
||||
export async function movePath(src: string, dst: string): Promise<void>
|
||||
```
|
||||
|
||||
### Step 2:前端 — 多选状态管理
|
||||
|
||||
**文件**: `frontend/src/components/FileSystem/index.vue`
|
||||
|
||||
核心改动:`selectedFileItem: FileItem | null` → `selectedFiles: FileItem[]`
|
||||
|
||||
```ts
|
||||
// 改前
|
||||
const selectedFileItem = ref<FileItem | null>(null)
|
||||
|
||||
// 改后
|
||||
const selectedFiles = ref<FileItem[]>([])
|
||||
const selectedFileItem = computed(() => selectedFiles.value[0] || null) // 兼容现有单选逻辑
|
||||
```
|
||||
|
||||
**文件**: `frontend/src/types/file-system.ts`
|
||||
|
||||
`FileListPanelConfig.selectedFileItem` 类型改为 `selectedFiles: FileItem[]`
|
||||
|
||||
**文件**: `frontend/src/components/FileSystem/components/FileListPanel.vue`
|
||||
|
||||
改造行点击支持多选:
|
||||
|
||||
```ts
|
||||
const handleRowClick = (record: FileItem, ev: MouseEvent) => {
|
||||
if (target.closest('.arco-btn') || target.closest('.arco-input-wrapper')) return
|
||||
|
||||
if (ev.ctrlKey || ev.metaKey) {
|
||||
emit('toggleSelect', record) // Ctrl+Click: 切换选中
|
||||
} else if (ev.shiftKey && props.selectedFiles.length > 0) {
|
||||
emit('rangeSelect', record) // Shift+Click: 范围选择
|
||||
} else {
|
||||
emit('fileClick', record) // 普通点击: 单选
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
`getRowClassName` 改为匹配数组:
|
||||
```ts
|
||||
const getRowClassName = (record: FileItem): string => [
|
||||
props.selectedFiles.some(f => f.path === record.path) && 'row-selected',
|
||||
props.config.editingFilePath === record.path && 'row-editing'
|
||||
].filter(Boolean).join(' ')
|
||||
```
|
||||
|
||||
Props 变更:
|
||||
```ts
|
||||
// 改前
|
||||
selectedFileItem: FileItem | null
|
||||
// 改后
|
||||
selectedFiles: FileItem[]
|
||||
```
|
||||
|
||||
新增 Emits:
|
||||
```ts
|
||||
(e: 'toggleSelect', file: FileItem): void
|
||||
(e: 'rangeSelect', file: FileItem): void
|
||||
```
|
||||
|
||||
### Step 3:前端 — 剪贴板状态(应用级)
|
||||
|
||||
**新建文件**: `frontend/src/components/FileSystem/composables/useClipboard.ts`
|
||||
|
||||
```ts
|
||||
type ClipboardOp = 'copy' | 'cut'
|
||||
|
||||
interface ClipboardState {
|
||||
op: ClipboardOp | null
|
||||
files: FileItem[] // 源文件列表
|
||||
sourceDir: string // 来源目录
|
||||
}
|
||||
|
||||
const clipboard = reactive<ClipboardState>({
|
||||
op: null, files: [], sourceDir: '',
|
||||
})
|
||||
|
||||
export function useClipboard() {
|
||||
const copy = (files: FileItem[]) => { /* ... */ }
|
||||
const cut = (files: FileItem[]) => { /* ... */ }
|
||||
const clear = () => { clipboard.op = null; clipboard.files = [] }
|
||||
const canPaste = computed(() => clipboard.op !== null && clipboard.files.length > 0)
|
||||
return { clipboard, copy, cut, clear, canPaste }
|
||||
}
|
||||
```
|
||||
|
||||
### Step 4:前端 — 右键菜单扩展
|
||||
|
||||
**文件**: `frontend/src/components/FileSystem/components/ContextMenu.vue`
|
||||
|
||||
文件菜单追加 Copy / Cut:
|
||||
```vue
|
||||
<div class="context-menu-item" @click="handleCopy">
|
||||
<span>📋</span><span>复制</span><span class="shortcut">Ctrl+C</span>
|
||||
</div>
|
||||
<div class="context-menu-item" @click="handleCut">
|
||||
<span>✂️</span><span>剪切</span><span class="shortcut">Ctrl+X</span>
|
||||
</div>
|
||||
<div class="context-menu-divider"></div>
|
||||
<!-- 现有重命名/删除保持不变 -->
|
||||
```
|
||||
|
||||
空白区域菜单追加 Paste:
|
||||
```vue
|
||||
<div class="context-menu-divider"></div>
|
||||
<div class="context-menu-item" :disabled="!canPaste" @click="handlePaste">
|
||||
<span>📌</span><span>粘贴</span><span class="shortcut">Ctrl+V</span>
|
||||
</div>
|
||||
```
|
||||
|
||||
新增 Props: `selectedCount?: number`, `canPaste?: boolean`
|
||||
新增 Emits: `'action': 'copy' | 'cut' | 'paste'`
|
||||
|
||||
### Step 5:前端 — 快捷键扩展
|
||||
|
||||
**文件**: `frontend/src/components/FileSystem/index.vue` 的 `handleKeyDown`
|
||||
|
||||
在 Delete 处理之后追加:
|
||||
|
||||
```ts
|
||||
// Ctrl+C 复制
|
||||
if ((event.ctrlKey || event.metaKey) && event.key === 'c' && selectedFiles.value.length > 0) {
|
||||
event.preventDefault(); handleCopy(); return
|
||||
}
|
||||
// Ctrl+X 剪切
|
||||
if ((event.ctrlKey || event.metaKey) && event.key === 'x' && selectedFiles.value.length > 0) {
|
||||
event.preventDefault(); handleCut(); return
|
||||
}
|
||||
// Ctrl+V 粘贴
|
||||
if ((event.ctrlKey || event.metaKey) && event.key === 'v') {
|
||||
event.preventDefault(); await handlePaste(); return
|
||||
}
|
||||
// Ctrl+A 全选
|
||||
if ((event.ctrlKey || event.metaKey) && event.key === 'a') {
|
||||
event.preventDefault()
|
||||
selectedFiles.value = [...fileList.value]
|
||||
return
|
||||
}
|
||||
```
|
||||
|
||||
### Step 6:前端 — 操作执行逻辑
|
||||
|
||||
**文件**: `frontend/src/components/FileSystem/composables/useFileOperations.ts`
|
||||
|
||||
实现 `copy()` 和 `move()`(替换 TODO stub):
|
||||
|
||||
```ts
|
||||
const copy = async (fromPath: string, toPath: string): Promise<void> => {
|
||||
await copyPathApi(fromPath, toPath)
|
||||
Message.success('复制完成')
|
||||
}
|
||||
const move = async (fromPath: string, toPath: string): Promise<void> => {
|
||||
await movePathApi(fromPath, toPath)
|
||||
Message.success('移动完成')
|
||||
}
|
||||
```
|
||||
|
||||
**文件**: `frontend/src/components/FileSystem/index.vue`
|
||||
|
||||
核心处理函数:
|
||||
|
||||
```ts
|
||||
const { clipboard, copy: clipCopy, cut: clipCut, canPaste } = useClipboard()
|
||||
|
||||
const handleCopy = () => {
|
||||
clipCopy(selectedFiles.value)
|
||||
Message.info(`已复制 ${selectedFiles.value.length} 项`)
|
||||
}
|
||||
const handleCut = () => {
|
||||
clipCut(selectedFiles.value)
|
||||
Message.info(`已剪切 ${selectedFiles.value.length} 项`)
|
||||
}
|
||||
const handlePaste = async () => {
|
||||
for (const file of clipboard.files) {
|
||||
const dst = filePath.value + '/' + file.name
|
||||
clipboard.op === 'cut'
|
||||
? await fileOps.move(file.path, dst)
|
||||
: await fileOps.copy(file.path, dst)
|
||||
}
|
||||
if (clipboard.op === 'cut') clipClear()
|
||||
loadDirectory(filePath.value)
|
||||
}
|
||||
const handleToggleSelect = (file: FileItem) => { /* 切换单项 */ }
|
||||
const handleRangeSelect = (file: FileItem) => { /* 范围选择 */ }
|
||||
|
||||
// handleContextMenuAction 扩展
|
||||
case 'copy': handleCopy(); break
|
||||
case 'cut': handleCut(); break
|
||||
case 'paste': await handlePaste(); break
|
||||
```
|
||||
|
||||
## 四、改动文件清单
|
||||
|
||||
| 文件 | 改动类型 | 说明 |
|
||||
|------|---------|------|
|
||||
| `internal/filesystem/service.go` | 修改 | 新增 `CopyPath()`、`MovePath()` |
|
||||
| `app.go` | 修改 | 新增绑定方法 + `CopyMoveRequest` 结构体 |
|
||||
| `frontend/src/api/system.ts` | 修改 | 新增 `copyPath()`、`movePath()` |
|
||||
| `frontend/src/types/file-system.ts` | 修改 | `selectedFileItem` → `selectedFiles` 数组 |
|
||||
| `frontend/src/components/FileSystem/composables/useClipboard.ts` | **新建** | 剪贴板 composable |
|
||||
| `frontend/src/components/FileSystem/composables/useFileOperations.ts` | 修改 | 实现 copy/move TODO |
|
||||
| `frontend/src/components/FileSystem/components/FileListPanel.vue` | 修改 | 多选行点击 + 行样式 |
|
||||
| `frontend/src/components/FileSystem/components/ContextMenu.vue` | 修改 | 追加 Copy/Cut/Paste 菜单项 |
|
||||
| `frontend/src/components/FileSystem/index.vue` | 修改 | 多选状态 + 快捷键 + 操作函数 |
|
||||
|
||||
共 **9 个文件**(1 个新建 + 8 个修改)
|
||||
|
||||
## 五、验证标准
|
||||
|
||||
1. **Ctrl+Click** 切换单文件选中状态,高亮多行
|
||||
2. **Shift+Click** 选中范围文件
|
||||
3. **Ctrl+A** 全选当前目录所有文件
|
||||
4. **Ctrl+C** 复制选中文件 → 提示"N 项已复制"
|
||||
5. **Ctrl+X** 剪切选中文件 → 提示"N 项已剪切"
|
||||
6. **Ctrl+V** 在目标目录粘贴 → 文件出现
|
||||
7. **右键菜单** 显示 Copy / Cut / Paste(空白区)
|
||||
8. **跨目录粘贴** 正确复制到目标路径
|
||||
9. **剪切粘贴** 源文件消失(移动效果)
|
||||
10. **大文件夹** 复制不卡顿(Go io.Copy 流式)
|
||||
|
||||
## 六、不做(明确边界)
|
||||
|
||||
- **拖拽移动文件** — 本轮不做,后续可加
|
||||
- **外部文件粘贴** — 不支持从系统资源管理器粘贴到 u-desk(Wails 限制)
|
||||
- **进度条** — 大文件复制暂不加进度条
|
||||
- **撤销(Ctrl+Z)** — 仅保留编辑器内容重置,不做操作历史撤销
|
||||
1463
docs/04-功能迭代/GO-DESK-7.u-fs-agent远程文件服务/设计文档.md
Normal file
1463
docs/04-功能迭代/GO-DESK-7.u-fs-agent远程文件服务/设计文档.md
Normal file
File diff suppressed because it is too large
Load Diff
126
docs/04-功能迭代/GO-DESK-8.Wails-v3迁移.md
Normal file
126
docs/04-功能迭代/GO-DESK-8.Wails-v3迁移.md
Normal file
@@ -0,0 +1,126 @@
|
||||
# GO-DESK-8: Wails v3 迁移变更分析
|
||||
|
||||
> 范围: `44847e0`(v0.4.0) → `f54bf1c`(fs-only-v3) | 提交数: 1 | 日期: 2026-05-01
|
||||
|
||||
## 变更总览
|
||||
|
||||
| 类别 | 数量 | 说明 |
|
||||
|------|------|------|
|
||||
| 重命名 | 77 | web/ → frontend/(git rename,历史保留) |
|
||||
| 新增 | 94 | v3 构建模板 + bindings + 新文件 |
|
||||
| 删除 | 4 | 旧文件(clipboard png、md5、v2 transport/types) |
|
||||
| 修改 | 10 | 核心代码适配 v3 API |
|
||||
| **合计** | **185** | **+7,772 / -918 行** |
|
||||
|
||||
---
|
||||
|
||||
## 一、框架升级(核心)
|
||||
|
||||
### Wails v2 → v3 API 映射
|
||||
|
||||
| v2 (旧) | v3 (新) | 文件 |
|
||||
|---------|---------|------|
|
||||
| `wails.Run(&options.App{...})` | `application.New()` + `Window.NewWithOptions()` | main.go |
|
||||
| `options.App.Bind: []interface{}{app}` | `Services: []application.Service{application.NewService(app)}` | main.go |
|
||||
| `AssetServer: &assetserver.Options{}` | `Assets: application.AssetOptions{Handler, Middleware}` | main.go |
|
||||
| `app.Startup(ctx)` / `app.Shutdown(ctx)` | `app.ServiceStartup(ctx, opts)` / `app.ServiceShutdown()` | app.go |
|
||||
| `runtime.Window(ctx)` | `a.mainWindow`(手动注入) | app.go |
|
||||
| `runtime.*` 函数调用 | `window.*` 方法 + v3-bindings 自动生成 | 前端 |
|
||||
| `//go:embed all:web/dist` | `//go:embed all:frontend/dist` | main.go |
|
||||
|
||||
### main.go 实质性变更
|
||||
- **Middleware 中间件**: 拦截 `/wails/custom.js` 返回空 200,消除控制台 404
|
||||
- **DevTools**: 延迟 2s 调用 `window.OpenDevTools()`(production + devtools build tag)
|
||||
- **窗口主题**: Windows CustomTheme 配置亮/暗模式标题栏颜色
|
||||
|
||||
### app.go 实质性变更
|
||||
- **新增** `SetMainWindow()` — v3 需要手动注入窗口引用
|
||||
- **新增** `SetWindowTitleBarColor()` — v3 窗口主题色动态切换
|
||||
- **新增** `sync.Mutex` — 并发安全保护 mainWindow
|
||||
- **生命周期**: `Startup/Shutdown` → `ServiceStartup/ServiceShutdown`(返回 error)
|
||||
- **错误处理**: panic → return error(符合 Go 惯例)
|
||||
|
||||
---
|
||||
|
||||
## 二、前端代码修改(有业务逻辑变化的)
|
||||
|
||||
### App.vue (+375/-60 行)
|
||||
- Tabs padding-top 覆盖(Arco Design 默认 16px → 0)
|
||||
- import 路径更新:`@/wailsjs/v3-bindings/u-desk/app`
|
||||
- 窗口控制方法改用 v3 binding 导入
|
||||
|
||||
### Sidebar.vue (+406 行)
|
||||
- **新架构**: 双区块折叠(收藏夹 + 帮助文档),各自独立 header + content
|
||||
- **滚动优化**: `.sidebar overflow:hidden` + 收藏内容区 `overflow-y:auto` 内部滚动
|
||||
- **帮助区块**: 固定底部 `flex-shrink:0`,默认展开
|
||||
- 折叠动画: max-height + opacity CSS transition
|
||||
|
||||
### useFavorites.ts (+259 行)
|
||||
- **修复**: `longPressTimer` const → let(解决 Assignment to constant variable TypeError)
|
||||
|
||||
### stores/ (config/theme/update)
|
||||
- **config.ts**: Wails v3 绑定加载方式调整
|
||||
- **theme.ts**: 窗口主题色通过 v3 API 设置
|
||||
- **update.ts**: 更新检查逻辑适配 v3 事件系统
|
||||
|
||||
### wails-transport.ts (+121 行)
|
||||
- **全新**: v3 transport 层实现(替代 v2 的 runtime 调用)
|
||||
|
||||
### UpdateNotification.vue / UpdatePanel.vue
|
||||
- 事件监听从 v2 runtime 改为 v3 OffAll/events 模式
|
||||
|
||||
---
|
||||
|
||||
## 三、依赖变更
|
||||
|
||||
```diff
|
||||
- github.com/wailsapp/wails/v2 v2.12.0
|
||||
+ github.com/wailsapp/wails/v3 v3.0.0-alpha.80
|
||||
|
||||
- go 1.25.6
|
||||
+ go 1.26
|
||||
|
||||
+ github.com/wailsapp/wails/v3/pkg/w32 # Win32 直接调用
|
||||
+ dario.cat/mergo v1.0.2 # 结构体合并
|
||||
```
|
||||
|
||||
移除: `go-toast/v2`(v3 自带通知)、`gosod`/`slicer`(v2 工具库)
|
||||
|
||||
---
|
||||
|
||||
## 四、新增构建基础设施(94 个文件,均为 Wails v3 标准模板)
|
||||
|
||||
以下由 `wails3 task generate` 自动生成,无自定义逻辑:
|
||||
|
||||
| 目录 | 用途 |
|
||||
|------|------|
|
||||
| `build/config.yml` | 项目配置(dev mode executes 流水线) |
|
||||
| `Taskfile.yml` | 根级任务定义(dev/build/run) |
|
||||
| `build/android/` | Android 构建模板(Gradle + Java Bridge) |
|
||||
| `build/darwin/` | macOS 构建(Info.plist + Icons) |
|
||||
| `build/ios/` | iOS 构建(Xcode project) |
|
||||
| `build/linux/` | Linux 构建(AppImage + nfpm) |
|
||||
| `build/docker/` | Docker 交叉编译 |
|
||||
| `build/windows/nsis/` | NSIS 安装包脚本 |
|
||||
| `build/windows/msix/` | MSIX 打包配置 |
|
||||
| `frontend/src/wailsjs/v3-bindings/` | v3 TypeScript 绑定(自动生成) |
|
||||
| `frontend/bindings/` | v3 绑定副本(备用路径) |
|
||||
|
||||
---
|
||||
|
||||
## 五、删除项(4 个文件)
|
||||
|
||||
| 文件 | 原因 |
|
||||
|------|------|
|
||||
| `cmd/agent/clipboard_*.png` | 截图残留,已归档到 `.archive/` |
|
||||
| `web/package.json.md5` | 旧完整性校验文件 |
|
||||
| `web/src/api/wails-transport.ts` | v2 版本,已被 frontend 下新版替代 |
|
||||
| `web/src/types/window.d.ts` | v2 类型声明,已被 frontend 下新版替代 |
|
||||
|
||||
---
|
||||
|
||||
## 六、风险点
|
||||
|
||||
1. **alpha.80 稳定性**: Wails v3 仍为 alpha,部分 API 可能后续 breaking change
|
||||
2. **OpenDevTools sleep hack**: 2s 硬编码延迟不够可靠,待 OnDomReady 稳定后替换
|
||||
3. **v2 bindings 残留**: `frontend/src/wailsjs/wailsjs/`(v2)仍随重命名保留在 frontend/ 下,如不再使用应清理
|
||||
Reference in New Issue
Block a user