frontend: add workspace context, file content and conflict apis with frontend type contracts

补齐 FE-002:服务端新增 workspace/context、mappings/check-target、files/content、
conflicts 明细与 apply 路由,核心层补充本地文件内容与冲突查询/应用能力及二进制/大文件约束;
前端补齐统一领域类型契约与类型化端点封装。

gradle build / pnpm typecheck 均通过。

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
fenghp
2026-06-09 20:35:15 +08:00
co-authored by Cursor
parent 5c633fd024
commit ca4089a885
8 changed files with 921 additions and 13 deletions
+229
View File
@@ -0,0 +1,229 @@
import { apiClient } from "./client"
import type {
AppConfig,
CheckMappingTargetResult,
CheckinResult,
Collection,
ConflictInfo,
ConflictResolution,
ConflictResolutionResult,
ConnectResult,
FileContent,
FileOperationResult,
FolderDiffItem,
GetLatestResult,
HistoryEntry,
MappingInfo,
OperationLogEntry,
PendingChange,
ServerItem,
TextDiff,
WorkspaceContext,
WorkspaceInfo,
} from "./types"
// 文件类操作(checkout / add / delete / undo)的统一请求体。
type FileActionBody = { paths: string[]; recursive?: boolean }
/**
* 读取服务端持久化配置。
*/
export function getConfig() {
return apiClient.get<{ config: AppConfig }>("/api/config")
}
/**
* 保存服务端持久化配置。
*/
export function saveConfig(config: AppConfig) {
return apiClient.put<{ config: AppConfig }>("/api/config", { body: config })
}
/**
* 使用给定连接信息连接 TFS,成功后服务端会保存配置并建立会话。
*/
export function connect(config: Partial<AppConfig> = {}) {
return apiClient.post<ConnectResult>("/api/session/connect", { body: config })
}
/**
* 列出当前账号可见的 Collection。
*/
export function listCollections() {
return apiClient.get<{ collections: Collection[] }>("/api/collections")
}
/**
* 浏览服务端目录树节点。
*/
export function getServerTree(params: { path?: string; collection?: string } = {}) {
return apiClient.get<{ path: string; items: ServerItem[] }>("/api/server-tree", { query: params })
}
/**
* 读取当前目录下一级文件与文件夹列表。
*/
export function getFolderItems(params: { path?: string; collection?: string } = {}) {
return apiClient.get<{ path: string; items: ServerItem[] }>("/api/server-folder/items", { query: params })
}
/**
* 读取当前 Workspace 名称与 Mapping 列表。
*/
export function getWorkspace() {
return apiClient.get<{ workspace: string; mappings: MappingInfo[] }>("/api/workspace")
}
/**
* 确保当前 Collection 的默认 Workspace 存在,必要时创建。
*/
export function ensureWorkspace(body: { collection?: string; workspace?: string; comment?: string } = {}) {
return apiClient.post<{ workspace: WorkspaceInfo }>("/api/workspace/ensure", { body })
}
/**
* 读取工作台固定上下文(serverUri / collection / workspace / mappings)。
*/
export function getWorkspaceContext() {
return apiClient.get<{ context: WorkspaceContext }>("/api/workspace/context")
}
/**
* 读取当前 Workspace 的 Mapping 列表。
*/
export function listMappings() {
return apiClient.get<{ mappings: MappingInfo[] }>("/api/mappings")
}
/**
* 预校验 Mapping 目标路径,返回最终本地目标路径及是否已存在。
*/
export function checkMappingTarget(body: { serverPath: string; localParentPath: string }) {
return apiClient.post<CheckMappingTargetResult>("/api/mappings/check-target", { body })
}
/**
* 创建 Mapping,可选立即 Get Latest。
*/
export function addMapping(body: { serverPath: string; localPath: string; getLatest?: boolean }) {
return apiClient.post<{ mapping: MappingInfo; getLatest?: GetLatestResult }>("/api/mappings", { body })
}
/**
* 删除 Mapping,仅解除映射不删除本地文件。
*/
export function deleteMapping(body: { serverPath?: string; localPath?: string }) {
return apiClient.delete<{ mappings: MappingInfo[] }>("/api/mappings", { body })
}
/**
* 获取指定服务端路径的最新文件。
*/
export function getLatest(body: { serverPath?: string; recursive?: boolean } = {}) {
return apiClient.post<{ result: GetLatestResult }>("/api/files/get-latest", { body })
}
/**
* 对已存在文件或目录执行 checkout。
*/
export function checkout(body: FileActionBody) {
return apiClient.post<{ result: FileOperationResult }>("/api/files/checkout", { body })
}
/**
* 将本地新增文件加入 pending add。
*/
export function addFiles(body: FileActionBody) {
return apiClient.post<{ result: FileOperationResult }>("/api/files/add", { body })
}
/**
* 对已版本控制文件或目录执行 pending delete。
*/
export function deleteFiles(body: FileActionBody) {
return apiClient.post<{ result: FileOperationResult }>("/api/files/delete", { body })
}
/**
* 撤销指定路径上的挂起更改。
*/
export function undoFiles(body: FileActionBody) {
return apiClient.post<{ result: FileOperationResult }>("/api/files/undo", { body })
}
/**
* 读取当前 Workspace 的挂起更改。
*/
export function getPendingChanges(params: { serverPath?: string } = {}) {
return apiClient.get<{ pendingChanges: PendingChange[] }>("/api/pending-changes", { query: params })
}
/**
* 提交带注释的签入,paths 为空时签入全部挂起更改。
*/
export function checkin(body: { paths?: string[]; comment: string }) {
return apiClient.post<{ checkin: CheckinResult }>("/api/checkin", { body })
}
/**
* 读取服务器内容(latest 或指定 changeset),或读取本地映射文件内容。
*/
export function getFileContent(params: { serverPath?: string; localPath?: string; changeset?: number }) {
return apiClient.get<{ content: FileContent }>("/api/files/content", { query: params })
}
/**
* 对已映射目录执行目录对比。
*/
export function compareFolder(body: { serverPath: string; localPath?: string; recursive?: boolean }) {
return apiClient.post<{ diffs: FolderDiffItem[] }>("/api/compare/folder", { body })
}
/**
* 查询文件或目录历史。
*/
export function getHistory(params: { path: string; folder?: boolean }) {
return apiClient.get<{ history: HistoryEntry[] }>("/api/history", { query: params })
}
/**
* 查询指定 changeset 影响的文件列表。
*/
export function getChangesetFiles(params: { changeset: number }) {
return apiClient.get<{ files: HistoryEntry[] }>("/api/history/changeset", { query: params })
}
/**
* 生成本地文件与服务器 latest 的文本 Diff。
*/
export function diffLocalLatest(body: { serverPath: string; localPath: string }) {
return apiClient.post<{ diff: TextDiff }>("/api/diff/local-latest", { body })
}
/**
* 生成同一服务端文件两个 changeset 之间的文本 Diff。
*/
export function diffRevisions(body: { serverPath: string; sourceChangeset: number; targetChangeset: number }) {
return apiClient.post<{ diff: TextDiff }>("/api/diff/revisions", { body })
}
/**
* 查询当前 Workspace 的冲突明细。
*/
export function listConflicts(params: { serverPath?: string; recursive?: boolean } = {}) {
return apiClient.get<{ conflicts: ConflictInfo[] }>("/api/conflicts", { query: params })
}
/**
* 对单个冲突应用取舍(采用服务器版本或保留本地版本)。
*/
export function applyConflict(body: { conflictId: number; resolution: ConflictResolution }) {
return apiClient.post<{ resolution: ConflictResolutionResult }>("/api/conflicts/apply", { body })
}
/**
* 读取最近操作日志。
*/
export function getLogs() {
return apiClient.get<{ logs: OperationLogEntry[] }>("/api/logs")
}