From 5ef483c830b75fb8a646b02ec32e70c3abc130b4 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E7=BB=9D=E5=B0=98?= <237809796@qq.com>
Date: Mon, 26 Jan 2026 02:02:39 +0800
Subject: [PATCH] =?UTF-8?q?=E6=96=B0=E5=A2=9E=EF=BC=9A=E7=8B=AC=E7=AB=8B?=
=?UTF-8?q?=E7=9A=84=E6=96=87=E4=BB=B6=E7=AE=A1=E7=90=86=E6=A8=A1=E5=9D=97?=
=?UTF-8?q?=EF=BC=8C=E4=BC=98=E5=8C=96=E6=96=87=E4=BB=B6=E6=93=8D=E4=BD=9C?=
=?UTF-8?q?=E5=8A=9F=E8=83=BD?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
web/src/App.vue | 5 +
web/src/components/DeviceTest.vue | 192 +++++++++-
web/src/components/FileSystem.vue | 559 ++++++++++++++++++++++++++++++
3 files changed, 750 insertions(+), 6 deletions(-)
create mode 100644 web/src/components/FileSystem.vue
diff --git a/web/src/App.vue b/web/src/App.vue
index 3b213d4..927be5b 100644
--- a/web/src/App.vue
+++ b/web/src/App.vue
@@ -5,6 +5,7 @@
Go Desk
@@ -24,6 +25,9 @@
+
+
+
@@ -110,6 +114,7 @@ import DeviceTest from './components/DeviceTest.vue'
import DbCli from './views/db-cli/index.vue'
import ThemeToggle from './components/ThemeToggle.vue'
import UpdatePanel from './components/UpdatePanel.vue'
+import FileSystem from './components/FileSystem.vue'
const activeTab = ref('db-cli')
const showUpdateModal = ref(false)
diff --git a/web/src/components/DeviceTest.vue b/web/src/components/DeviceTest.vue
index 16663c5..b652b56 100644
--- a/web/src/components/DeviceTest.vue
+++ b/web/src/components/DeviceTest.vue
@@ -63,6 +63,26 @@
浏览
列出目录
+
+
+
+
+
+
+ {{ fav.is_dir ? '📁' : '📄' }}
+
+ {{ fav.name }}
+
+
+
+
@@ -78,6 +98,14 @@
{{ item.is_dir ? '📁' : '📄' }}
{{ item.name }}
+
+ {{ isFavorite(item.path) ? '⭐' : '☆' }}
+
@@ -93,11 +121,23 @@
-
+
+
读取文件
写入文件
@@ -145,7 +185,9 @@ const STORAGE_KEYS = {
FILE_PATH: 'device-test-file-path',
FILE_LIST: 'device-test-file-list',
FILE_CONTENT: 'device-test-file-content',
- PATH_HISTORY: 'device-test-path-history'
+ PATH_HISTORY: 'device-test-path-history',
+ FILE_CONTENT_HEIGHT: 'device-test-file-content-height',
+ FAVORITE_FILES: 'device-test-favorite-files'
}
const systemInfo = ref(null)
@@ -159,6 +201,9 @@ const fileLoading = ref(false)
const envVars = ref(null)
const envLoading = ref(false)
const pathHistory = ref([]) // 路径历史记录
+const fileContentHeight = ref(200) // 文件内容区域高度(默认200px)
+const isResizing = ref(false) // 是否正在拖拽
+const favoriteFiles = ref([]) // 收藏的文件列表
const diskColumns = [
{title: '设备', dataIndex: 'device', width: 120},
@@ -317,6 +362,37 @@ const formatBytes = (bytes) => {
return (bytes / Math.pow(unit, exp)).toFixed(2) + ' ' + 'KMGTPE'[exp - 1] + 'B'
}
+// 开始拖拽
+const startResize = (e) => {
+ isResizing.value = true
+ const startY = e.clientY
+ const startHeight = fileContentHeight.value
+
+ const onMouseMove = (moveEvent) => {
+ if (!isResizing.value) return
+
+ const deltaY = moveEvent.clientY - startY
+ const newHeight = startHeight + deltaY
+
+ // 限制高度范围
+ if (newHeight >= 100 && newHeight <= 800) {
+ fileContentHeight.value = newHeight
+ }
+ }
+
+ const onMouseUp = () => {
+ isResizing.value = false
+ document.removeEventListener('mousemove', onMouseMove)
+ document.removeEventListener('mouseup', onMouseUp)
+
+ // 保存高度到 localStorage
+ saveToStorage(STORAGE_KEYS.FILE_CONTENT_HEIGHT, fileContentHeight.value.toString())
+ }
+
+ document.addEventListener('mousemove', onMouseMove)
+ document.addEventListener('mouseup', onMouseUp)
+}
+
// 从 localStorage 加载数据
const loadFromStorage = () => {
try {
@@ -324,11 +400,20 @@ const loadFromStorage = () => {
const savedFileList = localStorage.getItem(STORAGE_KEYS.FILE_LIST)
const savedFileContent = localStorage.getItem(STORAGE_KEYS.FILE_CONTENT)
const savedHistory = localStorage.getItem(STORAGE_KEYS.PATH_HISTORY)
+ const savedHeight = localStorage.getItem(STORAGE_KEYS.FILE_CONTENT_HEIGHT)
+ const savedFavorites = localStorage.getItem(STORAGE_KEYS.FAVORITE_FILES)
if (savedPath) filePath.value = savedPath
if (savedFileList) fileList.value = JSON.parse(savedFileList)
if (savedFileContent) fileContent.value = savedFileContent
if (savedHistory) pathHistory.value = JSON.parse(savedHistory)
+ if (savedFavorites) favoriteFiles.value = JSON.parse(savedFavorites)
+ if (savedHeight) {
+ const height = parseInt(savedHeight)
+ if (!isNaN(height) && height >= 100 && height <= 800) {
+ fileContentHeight.value = height
+ }
+ }
} catch (error) {
console.error('从 localStorage 加载数据失败:', error)
}
@@ -368,6 +453,58 @@ const addToHistory = (path) => {
saveToStorage(STORAGE_KEYS.PATH_HISTORY, pathHistory.value)
}
+// 检查是否已收藏
+const isFavorite = (path) => {
+ return favoriteFiles.value.some(fav => fav.path === path)
+}
+
+// 切换收藏状态
+const toggleFavorite = (item) => {
+ const index = favoriteFiles.value.findIndex(fav => fav.path === item.path)
+
+ if (index > -1) {
+ // 已收藏,取消收藏
+ favoriteFiles.value.splice(index, 1)
+ Message.info('已取消收藏: ' + item.name)
+ } else {
+ // 未收藏,添加收藏
+ favoriteFiles.value.push({
+ path: item.path,
+ name: item.name,
+ is_dir: item.is_dir
+ })
+ Message.success('已收藏: ' + item.name)
+ }
+
+ // 保存到 localStorage
+ saveToStorage(STORAGE_KEYS.FAVORITE_FILES, favoriteFiles.value)
+}
+
+// 移除收藏
+const removeFavorite = (path) => {
+ const index = favoriteFiles.value.findIndex(fav => fav.path === path)
+ if (index > -1) {
+ const name = favoriteFiles.value[index].name
+ favoriteFiles.value.splice(index, 1)
+ saveToStorage(STORAGE_KEYS.FAVORITE_FILES, favoriteFiles.value)
+ Message.info('已取消收藏: ' + name)
+ }
+}
+
+// 打开收藏的文件
+const openFavoriteFile = (path) => {
+ filePath.value = path
+ addToHistory(path)
+
+ // 判断是文件还是目录
+ const fav = favoriteFiles.value.find(f => f.path === path)
+ if (fav && fav.is_dir) {
+ listDirectory()
+ } else {
+ readFile()
+ }
+}
+
// 监听数据变化自动保存
watch(filePath, (newPath) => {
saveToStorage(STORAGE_KEYS.FILE_PATH, newPath)
@@ -397,4 +534,47 @@ onMounted(() => {
.test-card {
margin-bottom: 16px;
}
+
+/* 文件内容区域容器 */
+.file-content-wrapper {
+ position: relative;
+ overflow: hidden;
+ transition: height 0.1s ease;
+}
+
+/* 文件内容文本框 */
+.file-content-textarea {
+ width: 100%;
+ height: 100%;
+ resize: none;
+}
+
+/* 拖拽手柄 */
+.resize-handle {
+ height: 8px;
+ cursor: ns-resize;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ background: var(--color-fill-2);
+ border-radius: 4px;
+ margin: 4px 0;
+ transition: background 0.2s;
+}
+
+.resize-handle:hover {
+ background: var(--color-fill-3);
+}
+
+/* 拖拽手柄的视觉指示条 */
+.resize-handle-bar {
+ width: 40px;
+ height: 3px;
+ background: var(--color-border-3);
+ border-radius: 2px;
+}
+
+.resize-handle:hover .resize-handle-bar {
+ background: rgb(var(--primary-6));
+}
diff --git a/web/src/components/FileSystem.vue b/web/src/components/FileSystem.vue
new file mode 100644
index 0000000..b6b7536
--- /dev/null
+++ b/web/src/components/FileSystem.vue
@@ -0,0 +1,559 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 浏览
+
+
+
+
+
+ 列出目录
+
+
+
+
+
+
+
+
+
+ {{ shortcut.name }}
+
+
+
+
+
+
+
+
+
+
+ {{ fav.is_dir ? '📁' : '📄' }}
+
+ {{ fav.name }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ item.is_dir ? '📁' : '📄' }}
+ {{ item.name }}
+
+
+
+
+
+
+
+
+
+
+ {{ formatBytes(item.size) }}
+ {{ item.mod_time }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 读取
+
+
+
+
+
+ 保存
+
+
+
+
+
+ 删除
+
+
+
+
+
+ 清空
+
+
+
+
+
+
+
+
+
+
+
+
+