新增: 文件操作增强与预览扩展

- 文件剪贴板复制剪切粘贴,重名自动副本
- SFTP下载到本机与外部文件拖入,目录递归
- 传输进度浮动面板,transfer-progress事件链
- Drawio预览,Excel工作线程,冻结看门狗
- cmd与bat自写batch语法高亮,psm1等映射补齐
This commit is contained in:
lxy
2026-09-15 22:26:12 +08:00
parent f1bc5b49f1
commit e7a2c5148e
59 changed files with 3185 additions and 2047 deletions
@@ -0,0 +1,22 @@
// drawio 预览插件注册
// canHandle 严格匹配 .drawio / .dio 扩展名,不认 .xml(避免误吞配置文件,配置文件走代码编辑器)。
import type { Component } from 'vue'
import { registerPreviewHandler } from '../registry'
import type { FilePreviewHandlerDefinition } from '../types'
// 仅 .drawio / .dio;.drawio.png / .drawio.svg 本就走图片预览,不冲突
const DRAWIO_EXT_REGEX = /\.(drawio|dio)$/i
const drawioHandler: FilePreviewHandlerDefinition = {
id: 'drawio-preview',
name: 'Draw.io 查看器',
icon: '📊',
priority: 90,
canHandle: (filename: string): boolean => DRAWIO_EXT_REGEX.test(filename || ''),
getComponent: (): Promise<Component> =>
import('../../components/FileSystem/components/DrawioPreview.vue').then(m => m.default),
supportsEdit: false,
}
registerPreviewHandler(drawioHandler)
+4
View File
@@ -0,0 +1,4 @@
// 内置预览插件聚合:import 此文件即触发注册(副作用模块)
// main.js 顶部 import '@/plugin/built-in' 完成全部内置插件注册。
import './drawio-handler'
+59
View File
@@ -0,0 +1,59 @@
// 预览插件注册中心
// 模块级单例:registerPreviewHandler 注册,resolvePreviewHandler 按优先级解析。
// 现有 9 类预览不进此注册表(仍走 FileEditorPanel 的 v-if/v-else-if 链);
// 仅当 resolvePreviewHandler 返回非 null 时,模板的 <component> 分支命中,优先于老链。
import { defineAsyncComponent, type Component } from 'vue'
import type { FilePreviewHandlerDefinition } from './types'
// 按 priority 降序维护的注册表
const previewHandlers: FilePreviewHandlerDefinition[] = []
/**
* 注册一个文件预览处理器
* 重复 id 会覆盖旧注册(便于热替换/测试),注册后保持 priority 降序。
*/
export function registerPreviewHandler(handler: FilePreviewHandlerDefinition): void {
const idx = previewHandlers.findIndex(h => h.id === handler.id)
if (idx >= 0) {
previewHandlers[idx] = handler
} else {
previewHandlers.push(handler)
}
previewHandlers.sort((a, b) => b.priority - a.priority)
}
/**
* 解析文件名对应的预览处理器
* 按 priority 降序遍历,返回第一个 canHandle=true 的 handler,无匹配返回 null。
*/
export function resolvePreviewHandler(filename: string): FilePreviewHandlerDefinition | null {
if (!filename) return null
for (const handler of previewHandlers) {
try {
if (handler.canHandle(filename)) return handler
} catch (e) {
console.warn(`[PreviewRegistry] handler ${handler.id} canHandle 异常:`, e)
}
}
return null
}
// 组件缓存:同一插件的异步组件只创建一次,避免重复 defineAsyncComponent
const componentCache = new Map<string, Component>()
/**
* 解析文件名对应的预览组件(Vue 异步组件,内部缓存)。
* 供 <component :is> 直接使用;无匹配返回 null。
* 与 resolvePreviewHandler 分离:handler 用于标题(icon/name),component 用于渲染。
*/
export function resolvePreviewComponent(filename: string): Component | null {
const handler = resolvePreviewHandler(filename)
if (!handler?.getComponent) return null
let comp = componentCache.get(handler.id)
if (!comp) {
comp = defineAsyncComponent(handler.getComponent)
componentCache.set(handler.id, comp)
}
return comp
}
+22
View File
@@ -0,0 +1,22 @@
// 预览插件类型定义
// 对齐 docs/02-架构设计/插件化架构方案.md 3.2 节 FilePreviewHandlerDefinition,day-1 简化到 drawio 所需字段。
import type { Component } from 'vue'
/** 文件预览处理器定义 */
export interface FilePreviewHandlerDefinition {
/** 插件唯一标识,如 'drawio-preview' */
id: string
/** 展示名,用于面板标题 */
name: string
/** 图标(emoji 或图标名) */
icon: string
/** 优先级,越大越优先(resolvePreviewHandler 按 priority 降序遍历) */
priority: number
/** 判断是否能处理该文件名(严格扩展名匹配,避免吞其他类型) */
canHandle: (filename: string) => boolean
/** 异步加载预览组件(配合 defineAsyncComponent 懒加载,返回 Promise<Component>) */
getComponent?: () => Promise<Component>
/** 是否支持编辑(day-1 drawio 只读) */
supportsEdit?: boolean
}