From 157bc47f3c8dbd54727f0d7faf3457d18f773c75 Mon Sep 17 00:00:00 2001
From: Jasery
Date: Tue, 28 Oct 2025 17:26:25 +0800
Subject: [PATCH] =?UTF-8?q?feat:=20=E6=B7=BB=E5=8A=A0=20TypeScript=20?=
=?UTF-8?q?=E7=B1=BB=E5=9E=8B=E6=A3=80=E6=9F=A5=E5=91=BD=E4=BB=A4=EF=BC=8C?=
=?UTF-8?q?=E4=BC=98=E5=8C=96=E6=A8=A1=E6=9D=BF=E5=88=9B=E5=BB=BA=E6=B5=81?=
=?UTF-8?q?=E7=A8=8B=EF=BC=8C=E7=A7=BB=E9=99=A4=E4=B8=8D=E5=BF=85=E8=A6=81?=
=?UTF-8?q?=E7=9A=84=E4=B8=8A=E4=B8=8B=E6=96=87=E8=8F=9C=E5=8D=95=E9=80=BB?=
=?UTF-8?q?=E8=BE=91?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
QWEN.md | 10 +-
package.json | 3 +-
src/renderer/components/TemplateTree.vue | 86 ++++---------
src/renderer/screens/CreateTemplateScreen.vue | 115 +++++++-----------
4 files changed, 70 insertions(+), 144 deletions(-)
diff --git a/QWEN.md b/QWEN.md
index a28acea..0cc7f30 100644
--- a/QWEN.md
+++ b/QWEN.md
@@ -64,6 +64,9 @@ pnpm dev:debug
# Force reinstall dependencies and start development
pnpm dev:debug:force
+
+# run Typescript Type check
+pnpm typecheck
```
### Building
@@ -103,11 +106,6 @@ pnpm lint
# Fix linting issues automatically
pnpm lint:fix
-# Format code with Prettier
-pnpm format
-
-# Format and fix code automatically
-pnpm format:fix
```
## Key Features
@@ -231,4 +229,6 @@ Building creates different distribution formats based on the platform:
Artifacts are named with the format `${productName} ${version}_${arch}.${ext}` and stored in the `release/${version}` directory.
+run `pnpm typecheck` before finish the task
+
Always respond in 中文
diff --git a/package.json b/package.json
index 4cbe0a0..7e3d8c8 100644
--- a/package.json
+++ b/package.json
@@ -24,6 +24,7 @@
"dev": "vite",
"dev:debug": "vite -d",
"dev:debug:force": "vite -d --force",
+ "typecheck": "vue-tsc --noEmit",
"build": "npm run build:pre && electron-builder --config=buildAssets/builder/config.js",
"build:pre": "vue-tsc --noEmit && vite build",
"build:all": "npm run build:pre && electron-builder --config=buildAssets/builder/config.js -wml",
@@ -33,8 +34,6 @@
"build:win": "npm run build:pre && electron-builder --config=buildAssets/builder/config.js --windows",
"lint": "eslint . --ext .js,.ts,.vue .",
"lint:fix": "eslint . --ext .js,.ts,.vue --fix .",
- "format": "prettier .",
- "format:fix": "prettier . --write",
"test": "npm run build:pre && playwright test",
"test:linux": "npm run build:pre && xvfb-run --auto-servernum --server-args='-screen 0, 1280x960x24' -- playwright test"
},
diff --git a/src/renderer/components/TemplateTree.vue b/src/renderer/components/TemplateTree.vue
index b3527f9..3ea3b49 100644
--- a/src/renderer/components/TemplateTree.vue
+++ b/src/renderer/components/TemplateTree.vue
@@ -3,7 +3,6 @@
variant="outlined"
class="pa-2"
:height="height"
- @contextmenu.prevent="emit('showContextMenu', $event, null)"
>
{{ item.name }}
-
- mdi-plus
-
- 添加到目录
-
-
@@ -61,23 +42,24 @@
class="d-flex align-center ga-1"
>
- mdi-pencil
+ mdi-folder-plus
- {{ item.type === 'file' ? '编辑文件' : '编辑目录' }}
+ 添加到目录
+
+ mdi-pencil
+
+ {{ item.type === 'file' ? '编辑文件' : '编辑目录' }}
+
+
+
@@ -133,39 +129,12 @@
v-if="!readOnly"
class="text-caption"
>
- 右键点击空白区域添加根目录或文件
+ 点击上方按钮添加根目录或文件
-
-
-
-
-
- mdi-folder-plus
-
-
- {{ currentContextItem ? '添加子目录' : '添加根目录' }}
-
-
-
-
- mdi-file-plus
-
-
- {{ currentContextItem ? '添加子文件' : '添加根文件' }}
-
-
-
-
diff --git a/src/renderer/screens/CreateTemplateScreen.vue b/src/renderer/screens/CreateTemplateScreen.vue
index 2f663b0..a7a29f7 100644
--- a/src/renderer/screens/CreateTemplateScreen.vue
+++ b/src/renderer/screens/CreateTemplateScreen.vue
@@ -142,19 +142,12 @@
:items="treeItems"
:height="treeHeight"
v-model:expanded="expandedNodes"
- v-model:showContextMenuVar="showContextMenuVar"
- :context-menu-x="contextMenuX"
- :context-menu-y="contextMenuY"
- :current-context-item="currentContextItem"
:empty-text="'暂无文件或目录'"
:read-only="false"
- @showContextMenu="showContextMenu"
@add-new-item-to-current-directory="addNewItemToCurrentDirectory"
@edit-file="editFile"
@edit-item="editItem"
@delete-item="deleteItem"
- @add-directory="addDirectory"
- @add-file="addFile"
@add-file-to-directory="addFileToDirectory"
/>
@@ -183,10 +176,10 @@
-
- 取消
+ >
+ 取消
-
+
-
+
@@ -245,7 +238,7 @@
{{ selectedSourcePath }}
-
+
自动寻找文件夹内的文件
-
+
-
- 取消
+ >
+ 取消
(null)
const fileInputRef = ref(null)
-// Context menu
-const showContextMenuVar = ref(false)
-const contextMenuX = ref(0)
-const contextMenuY = ref(0)
-const currentContextItem = ref(null)
+
// Snackbar variables
const snackbarVisible = ref(false)
@@ -440,10 +429,10 @@ const treeItems = computed(() => {
for (let i = 0; i < pathParts.length; i++) {
const part = pathParts[i]
const isLastPart = i === pathParts.length - 1
-
+
// Check if this part already exists in the current level
let existingItem = currentLevel.find(item => item.name === part)
-
+
if (!existingItem) {
// Create new directory item
const newDir: TreeItem = {
@@ -455,7 +444,7 @@ const treeItems = computed(() => {
currentLevel.push(newDir)
existingItem = newDir
}
-
+
// Move to the next level if not the last part
if (!isLastPart && existingItem.children) {
currentLevel = existingItem.children
@@ -467,16 +456,16 @@ const treeItems = computed(() => {
files.value.forEach((file) => {
const pathParts = file.path.split('/').filter(part => part !== '')
const fileName = pathParts.pop() // Get the last part as filename
-
+
if (!fileName) return // Skip if no filename
-
+
let currentLevel = root.children || []
-
+
// Navigate to the appropriate directory for the file
for (let i = 0; i < pathParts.length; i++) {
const part = pathParts[i]
const dirItem = currentLevel.find(item => item.name === part && item.type === 'directory')
-
+
if (dirItem && dirItem.children) {
currentLevel = dirItem.children
} else {
@@ -491,7 +480,7 @@ const treeItems = computed(() => {
currentLevel = newDir.children || []
}
}
-
+
// Add the file to the current level
currentLevel.push({
id: `file-${fileName}-${Date.now()}-${Math.random()}`,
@@ -554,18 +543,7 @@ const updateTreeHeight = () => {
treeHeight.value = window.innerHeight - 200
}
-const showContextMenu = (event: MouseEvent, item: TreeItem | null) => {
- event.preventDefault()
- contextMenuX.value = event.clientX
- contextMenuY.value = event.clientY
- currentContextItem.value = item
- showContextMenuVar.value = false // Close first to reset position
- nextTick(() => {
- contextMenuX.value = event.clientX
- contextMenuY.value = event.clientY
- showContextMenuVar.value = true
- })
-}
+
const addRootDirectory = () => {
newDirectoryPath.value = ''
@@ -580,8 +558,6 @@ const addRootFile = () => {
}
const addDirectory = (parentItem: TreeItem | null = null) => {
- showContextMenuVar.value = false
- currentContextItem.value = parentItem
parentDirectoryForNewItems.value = parentItem ? parentItem.name : null // Store parent context
newDirectoryPath.value = '' // Don't pre-fill the path
showDirectoryDialog.value = true
@@ -589,7 +565,6 @@ const addDirectory = (parentItem: TreeItem | null = null) => {
}
const addFile = (parentItem: TreeItem | null = null) => {
- showContextMenuVar.value = false
parentDirectoryForNewItems.value = parentItem ? parentItem.name : null // Store parent context
newFilePath.value = '' // Don't pre-fill the path
showFileDialog.value = true
@@ -598,7 +573,6 @@ const addFile = (parentItem: TreeItem | null = null) => {
// Add a file directly to a specific directory
const addFileToDirectory = (directoryItem: TreeItem) => {
- showContextMenuVar.value = false
parentDirectoryForNewItems.value = directoryItem.name // Store the directory as parent
newFilePath.value = '' // Don't pre-fill the path
showFileDialog.value = true
@@ -606,7 +580,6 @@ const addFileToDirectory = (directoryItem: TreeItem) => {
}
const addNewItemToCurrentDirectory = (directoryItem: TreeItem) => {
- currentContextItem.value = directoryItem
parentDirectoryForNewItems.value = directoryItem.name // Store parent context
newDirectoryPath.value = '' // Don't pre-fill the path
showDirectoryDialog.value = true
@@ -620,8 +593,8 @@ const confirmAddDirectory = () => {
let fullPath = newDirectoryPath.value
if (parentDirectoryForNewItems.value) {
// Make sure parent directory ends with a slash before appending
- const parentPath = parentDirectoryForNewItems.value.endsWith('/')
- ? parentDirectoryForNewItems.value
+ const parentPath = parentDirectoryForNewItems.value.endsWith('/')
+ ? parentDirectoryForNewItems.value
: parentDirectoryForNewItems.value + '/'
fullPath = parentPath + newDirectoryPath.value
}
@@ -632,7 +605,7 @@ const confirmAddDirectory = () => {
if (index !== -1) {
// Update the existing directory path
directories.value[index].path = fullPath
-
+
// If the directory path changes, update any files/dirs that were inside it
updatePathsForRenamedDirectory(currentEditingItem.value.path, fullPath)
}
@@ -654,9 +627,8 @@ const confirmAddDirectory = () => {
showDirectoryDialog.value = false
newDirectoryPath.value = ''
parentDirectoryForNewItems.value = null // Clear parent context after creation
- currentContextItem.value = null
currentEditingItem.value = null
-
+
// If we added to a parent directory, make sure it's expanded
if (parentDirectoryForNewItems.value) {
if (!expandedNodes.value.includes(`dir-${parentDirectoryForNewItems.value}`)) {
@@ -677,7 +649,7 @@ const updatePathsForRenamedDirectory = (oldPath: string, newPath: string) => {
}
return file
})
-
+
// Update all directories that were under the old directory
directories.value = directories.value.map(dir => {
if (dir.path.startsWith(oldPath + '/') || dir.path === oldPath) {
@@ -695,7 +667,6 @@ const closeDirectoryDialog = () => {
showDirectoryDialog.value = false
newDirectoryPath.value = ''
parentDirectoryForNewItems.value = null
- currentContextItem.value = null
currentEditingItem.value = null
}
@@ -703,7 +674,6 @@ const closeFileDialog = () => {
showFileDialog.value = false
newFilePath.value = ''
parentDirectoryForNewItems.value = null
- currentContextItem.value = null
currentEditingItem.value = null
selectedSourcePath.value = ''
isAutoFindMode.value = false
@@ -716,8 +686,8 @@ const selectAndAddFile = async () => {
let fullPath = newFilePath.value
if (parentDirectoryForNewItems.value) {
// Make sure parent directory ends with a slash before appending
- const parentPath = parentDirectoryForNewItems.value.endsWith('/')
- ? parentDirectoryForNewItems.value
+ const parentPath = parentDirectoryForNewItems.value.endsWith('/')
+ ? parentDirectoryForNewItems.value
: parentDirectoryForNewItems.value + '/'
fullPath = parentPath + newFilePath.value
}
@@ -744,13 +714,13 @@ const selectAndAddFile = async () => {
if (isAutoFindMode.value && selectedSourcePath.value) {
// Auto-find files in the selected folder
const foundFiles = await window.mainApi.invoke('msgFindFilesInFolder', selectedSourcePath.value)
-
+
// Add all found files as template files
for (const foundFile of foundFiles) {
// Calculate relative path from selected folder to the found file
const relativePath = foundFile.replace(selectedSourcePath.value, '').substring(1) // Remove leading slash
const fullTargetPath = fullPath ? `${fullPath}/${relativePath}` : relativePath
-
+
// Check for duplicates
const duplicate = files.value.some(f => f.path === fullTargetPath)
if (!duplicate) {
@@ -761,19 +731,18 @@ const selectAndAddFile = async () => {
files.value.push(newFile)
}
}
-
+
// Reset selection state
selectedSourcePath.value = ''
isAutoFindMode.value = false
-
+
showFileDialog.value = false
newFilePath.value = ''
parentDirectoryForNewItems.value = null // Clear parent context after creation
- currentContextItem.value = null
currentEditingItem.value = null
return
}
-
+
// If we have a selected file, just add it
if (selectedSourcePath.value) {
const newFile = {
@@ -790,11 +759,10 @@ const selectAndAddFile = async () => {
showFileDialog.value = false
newFilePath.value = ''
parentDirectoryForNewItems.value = null // Clear parent context after creation
- currentContextItem.value = null
currentEditingItem.value = null
return
}
-
+
// Otherwise, show file selection dialog
showSnackbar('请先选择一个文件或文件夹', 'warning')
return
@@ -803,11 +771,10 @@ const selectAndAddFile = async () => {
// Reset selection state after editing
selectedSourcePath.value = ''
isAutoFindMode.value = false
-
+
showFileDialog.value = false
newFilePath.value = ''
parentDirectoryForNewItems.value = null
- currentContextItem.value = null
currentEditingItem.value = null
}
@@ -820,7 +787,7 @@ const goBack = async () => {
cancelText: '取消',
confirmColor: 'warning'
})
-
+
if (confirmed) {
router.push('/templates')
}
@@ -831,7 +798,7 @@ const goBack = async () => {
const expandAll = () => {
const allIds: string[] = []
-
+
const collectIds = (items: TreeItem[]) => {
items.forEach(item => {
if (item.children && item.children.length > 0) {
@@ -840,7 +807,7 @@ const expandAll = () => {
}
})
}
-
+
collectIds(treeItems.value)
expandedNodes.value = allIds
}
@@ -899,13 +866,13 @@ const showEditFileDialog = (file: { path: string; content?: string; sourceFilePa
// Set up for editing an existing file
currentEditingItem.value = { ...file, type: 'file' }
newFilePath.value = file.path // Set the current path for editing
-
+
// If the file has a source file path, set it in the selection state
if (file.sourceFilePath) {
selectedSourcePath.value = file.sourceFilePath
isAutoFindMode.value = false
}
-
+
showFileDialog.value = true
autoFocusFileInput()
}
@@ -921,7 +888,7 @@ const deleteItem = async (item: TreeItem) => {
cancelText: '取消',
confirmColor: 'error'
})
-
+
if (!confirmed) return
if (item.type === 'directory') {
@@ -931,7 +898,7 @@ const deleteItem = async (item: TreeItem) => {
// Exclude if exact match or it's a subdirectory
return !isSubPath(d.path, item.name);
});
-
+
// Also remove files that are inside this directory
files.value = files.value.filter(f => {
// Exclude if it's inside the directory being deleted