refactor(模板创建): 重构模板树结构处理逻辑
- 将 parentDirectory 类型从 string 改为 TreeNode 以直接引用节点 - 移除冗余的 TreeItem 接口和转换逻辑 - 简化文件/目录添加和更新逻辑,直接操作 TreeNode - 使用新的 generateUniqueId 工具函数生成唯一ID - 移除不必要的路径拼接和重复检查逻辑
This commit is contained in:
1 parent
d3f4242445
commit
47fb017e21
4 files changed
+78
-207
No files matched your search
@@ -44,7 +44,7 @@ import { TreeNode } from '@/renderer/store/template'
|
|||||||
interface Props {
|
interface Props {
|
||||||
modelValue: boolean
|
modelValue: boolean
|
||||||
isEditMode?: boolean
|
isEditMode?: boolean
|
||||||
parentDirectory?: string | null
|
parentDirectory?: TreeNode | null
|
||||||
editingItem?: TreeNode | null
|
editingItem?: TreeNode | null
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -70,13 +70,13 @@ import { TreeNode } from '@/renderer/store/template'
|
|||||||
interface Props {
|
interface Props {
|
||||||
modelValue: boolean
|
modelValue: boolean
|
||||||
isEditMode?: boolean
|
isEditMode?: boolean
|
||||||
parentDirectory?: string | null
|
parentDirectory?: TreeNode | null
|
||||||
editingItem?: TreeNode | null
|
editingItem?: TreeNode | null
|
||||||
}
|
}
|
||||||
|
|
||||||
interface Emits {
|
interface Emits {
|
||||||
(e: 'update:modelValue', value: boolean): void
|
(e: 'update:modelValue', value: boolean): void
|
||||||
(e: 'confirm', data: { path: string; fullPath: string; sourceFilePath?: string }): void
|
(e: 'confirm', data: { path: string; sourceFilePath?: string }): void
|
||||||
}
|
}
|
||||||
|
|
||||||
const props = withDefaults(defineProps<Props>(), {
|
const props = withDefaults(defineProps<Props>(), {
|
||||||
@@ -137,19 +137,9 @@ const selectSourceFileOrFolder = async () => {
|
|||||||
const confirm = () => {
|
const confirm = () => {
|
||||||
if (!filePath.value.trim()) return
|
if (!filePath.value.trim()) return
|
||||||
|
|
||||||
// Construct the full path if there's a parent directory
|
|
||||||
let fullPath = filePath.value
|
|
||||||
if (props.parentDirectory) {
|
|
||||||
// Make sure parent directory ends with a slash before appending
|
|
||||||
const parentPath = props.parentDirectory.endsWith('/')
|
|
||||||
? props.parentDirectory
|
|
||||||
: props.parentDirectory + '/'
|
|
||||||
fullPath = parentPath + filePath.value
|
|
||||||
}
|
|
||||||
|
|
||||||
emit('confirm', {
|
emit('confirm', {
|
||||||
path: filePath.value,
|
path: filePath.value,
|
||||||
fullPath,
|
|
||||||
sourceFilePath: selectedSourcePath.value || undefined
|
sourceFilePath: selectedSourcePath.value || undefined
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|||||||
@@ -111,7 +111,7 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<TemplateTree
|
<TemplateTree
|
||||||
:items="treeItems"
|
:items="treeStructure"
|
||||||
:height="treeHeight"
|
:height="treeHeight"
|
||||||
v-model:expanded="expandedNodes"
|
v-model:expanded="expandedNodes"
|
||||||
:empty-text="'暂无文件或目录'"
|
:empty-text="'暂无文件或目录'"
|
||||||
@@ -152,6 +152,7 @@ import TemplateTree from '@/renderer/components/TemplateTree.vue'
|
|||||||
import DirectoryDialog from '@/renderer/components/DirectoryDialog.vue'
|
import DirectoryDialog from '@/renderer/components/DirectoryDialog.vue'
|
||||||
import FileDialog from '@/renderer/components/FileDialog.vue'
|
import FileDialog from '@/renderer/components/FileDialog.vue'
|
||||||
import { ConfirmDialogService } from '@/renderer/utils/confirm-dialog-service'
|
import { ConfirmDialogService } from '@/renderer/utils/confirm-dialog-service'
|
||||||
|
import { generateUniqueId } from '@/renderer/utils'
|
||||||
|
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
const route = useRoute()
|
const route = useRoute()
|
||||||
@@ -172,7 +173,7 @@ const showFileDialog = ref(false)
|
|||||||
|
|
||||||
// Directory dialog state
|
// Directory dialog state
|
||||||
const showDirectoryDialog = ref(false)
|
const showDirectoryDialog = ref(false)
|
||||||
const parentDirectoryForNewItems = ref<string | null>(null)
|
const parentDirectoryForNewItems = ref<TreeNode | null>(null)
|
||||||
const currentEditingItem = ref<TreeNode | null>(null)
|
const currentEditingItem = ref<TreeNode | null>(null)
|
||||||
|
|
||||||
|
|
||||||
@@ -180,38 +181,15 @@ const currentEditingItem = ref<TreeNode | null>(null)
|
|||||||
const expandedNodes = ref<string[]>([])
|
const expandedNodes = ref<string[]>([])
|
||||||
const treeHeight = ref(600)
|
const treeHeight = ref(600)
|
||||||
|
|
||||||
// Define type for tree items
|
|
||||||
interface TreeItem {
|
|
||||||
id: string
|
|
||||||
name: string
|
|
||||||
type: 'directory' | 'file'
|
|
||||||
children?: TreeItem[]
|
|
||||||
}
|
|
||||||
|
|
||||||
// Item state - 使用树状结构
|
// Item state - 使用树状结构
|
||||||
const treeStructure = ref<TreeNode[]>([])
|
const treeStructure = ref<TreeNode[]>([])
|
||||||
|
|
||||||
// Computed
|
// Computed
|
||||||
const isEditMode = computed(() => !!route.params.id)
|
const isEditMode = computed(() => !!route.params.id)
|
||||||
const treeItems = computed<TreeItem[]>(() => {
|
|
||||||
// 直接返回树状结构
|
|
||||||
return treeStructure.value.map((node) => convertToTreeItem(node))
|
|
||||||
})
|
|
||||||
|
|
||||||
// 转换 TreeNode 到 TreeItem 的辅助函数
|
|
||||||
const convertToTreeItem = (node: TreeNode): TreeItem => {
|
|
||||||
const treeItem: TreeItem = {
|
|
||||||
id: node.id,
|
|
||||||
name: node.name,
|
|
||||||
type: node.type
|
|
||||||
}
|
|
||||||
|
|
||||||
if (node.children && node.children.length > 0) {
|
|
||||||
treeItem.children = node.children.map((child) => convertToTreeItem(child))
|
|
||||||
}
|
|
||||||
|
|
||||||
return treeItem
|
|
||||||
}
|
|
||||||
|
|
||||||
// Validation rules
|
// Validation rules
|
||||||
const requiredRule = (fieldName: string) => (v: string | null | undefined) =>
|
const requiredRule = (fieldName: string) => (v: string | null | undefined) =>
|
||||||
@@ -278,49 +256,21 @@ const addRootFile = () => {
|
|||||||
|
|
||||||
|
|
||||||
// Add a file directly to a specific directory
|
// Add a file directly to a specific directory
|
||||||
const addFileToDirectory = (directoryItem: TreeItem) => {
|
const addFileToDirectory = (directoryItem: TreeNode) => {
|
||||||
parentDirectoryForNewItems.value = directoryItem.name // Store the directory as parent
|
parentDirectoryForNewItems.value = directoryItem // Store the directory node as parent
|
||||||
currentEditingItem.value = null
|
currentEditingItem.value = null
|
||||||
showFileDialog.value = true
|
showFileDialog.value = true
|
||||||
}
|
}
|
||||||
|
|
||||||
const addNewItemToCurrentDirectory = (directoryItem: TreeItem) => {
|
const addNewItemToCurrentDirectory = (directoryItem: TreeNode) => {
|
||||||
parentDirectoryForNewItems.value = directoryItem.name // Store parent context
|
parentDirectoryForNewItems.value = directoryItem // Store the directory node as parent
|
||||||
currentEditingItem.value = null
|
currentEditingItem.value = null
|
||||||
showDirectoryDialog.value = true
|
showDirectoryDialog.value = true
|
||||||
}
|
}
|
||||||
|
|
||||||
const handleDirectoryDialogConfirm = (data: { path: string }) => {
|
const handleDirectoryDialogConfirm = (data: { path: string }) => {
|
||||||
const { path } = data
|
const { path } = data
|
||||||
|
const newId = generateUniqueId('dir')
|
||||||
// Check for duplicate names in the same parent directory
|
|
||||||
if (parentDirectoryForNewItems.value) {
|
|
||||||
// In the parent directory, check if a node with the same name already exists
|
|
||||||
const parentNode = findNodeInTreeByName(
|
|
||||||
treeStructure.value,
|
|
||||||
parentDirectoryForNewItems.value
|
|
||||||
)
|
|
||||||
if (parentNode && parentNode.children) {
|
|
||||||
const duplicateExists = parentNode.children.some(
|
|
||||||
(child) => child.name === path
|
|
||||||
)
|
|
||||||
if (duplicateExists) {
|
|
||||||
snackbar.error('当前目录下已存在同名节点!')
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// Check at root level for duplicates
|
|
||||||
const duplicateExists = treeStructure.value.some(
|
|
||||||
(node) => node.name === path
|
|
||||||
)
|
|
||||||
if (duplicateExists) {
|
|
||||||
snackbar.error('根目录下已存在同名节点!')
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const newId = `dir-${Date.now()}-${Math.random()}`
|
|
||||||
|
|
||||||
// Check if we're editing an existing directory
|
// Check if we're editing an existing directory
|
||||||
if (
|
if (
|
||||||
@@ -329,16 +279,18 @@ const handleDirectoryDialogConfirm = (data: { path: string }) => {
|
|||||||
) {
|
) {
|
||||||
// Find and update the existing directory in the tree
|
// Find and update the existing directory in the tree
|
||||||
const updatedNode: TreeNode = {
|
const updatedNode: TreeNode = {
|
||||||
id: currentEditingItem.value.id,
|
...currentEditingItem.value,
|
||||||
name: path,
|
name: path,
|
||||||
path: path,
|
path: path,
|
||||||
type: 'directory'
|
type: 'directory'
|
||||||
}
|
}
|
||||||
|
console.log('updatedNode', updatedNode)
|
||||||
treeStructure.value = updateNodeInTree(
|
treeStructure.value = updateNodeInTree(
|
||||||
treeStructure.value,
|
treeStructure.value,
|
||||||
currentEditingItem.value.path,
|
currentEditingItem.value.path,
|
||||||
updatedNode
|
updatedNode
|
||||||
)
|
)
|
||||||
|
console.log('update treeStructure', treeStructure.value)
|
||||||
} else {
|
} else {
|
||||||
// Create new directory node
|
// Create new directory node
|
||||||
const newNode: TreeNode = {
|
const newNode: TreeNode = {
|
||||||
@@ -350,13 +302,29 @@ const handleDirectoryDialogConfirm = (data: { path: string }) => {
|
|||||||
|
|
||||||
// Add to tree structure
|
// Add to tree structure
|
||||||
if (parentDirectoryForNewItems.value) {
|
if (parentDirectoryForNewItems.value) {
|
||||||
|
// In the parent directory, check if a node with the same name already exists
|
||||||
|
const parentNode = parentDirectoryForNewItems.value
|
||||||
|
if (parentNode.children) {
|
||||||
|
const duplicateExists = parentNode.children.some(
|
||||||
|
(child) => child.name === path
|
||||||
|
)
|
||||||
|
if (duplicateExists) {
|
||||||
|
snackbar.error('当前目录下已存在同名节点!')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
// Add as child to the parent directory
|
// Add as child to the parent directory
|
||||||
treeStructure.value = addChildToNode(
|
parentNode.children = parentNode.children || []
|
||||||
treeStructure.value,
|
parentNode.children.push(newNode)
|
||||||
parentDirectoryForNewItems.value,
|
|
||||||
newNode
|
|
||||||
)
|
|
||||||
} else {
|
} else {
|
||||||
|
// Check at root level for duplicates
|
||||||
|
const duplicateExists = treeStructure.value.some(
|
||||||
|
(node) => node.name === path
|
||||||
|
)
|
||||||
|
if (duplicateExists) {
|
||||||
|
snackbar.error('根目录下已存在同名节点!')
|
||||||
|
return
|
||||||
|
}
|
||||||
// Add as root node
|
// Add as root node
|
||||||
treeStructure.value.push(newNode)
|
treeStructure.value.push(newNode)
|
||||||
}
|
}
|
||||||
@@ -372,45 +340,17 @@ const handleDirectoryDialogConfirm = (data: { path: string }) => {
|
|||||||
// 在树状结构中更新节点的辅助函数
|
// 在树状结构中更新节点的辅助函数
|
||||||
const updateNodeInTree = (
|
const updateNodeInTree = (
|
||||||
nodes: TreeNode[],
|
nodes: TreeNode[],
|
||||||
oldPath: string,
|
oldId: string,
|
||||||
updatedNode: TreeNode
|
updatedNode: TreeNode
|
||||||
): TreeNode[] => {
|
): TreeNode[] => {
|
||||||
return nodes.map((node) => {
|
return nodes.map((node) => {
|
||||||
if (node.path === oldPath) {
|
if (node.id === oldId) {
|
||||||
return updatedNode
|
return updatedNode
|
||||||
}
|
}
|
||||||
if (node.children) {
|
if (node.children) {
|
||||||
return {
|
return {
|
||||||
...node,
|
...node,
|
||||||
children: updateNodeInTree(node.children, oldPath, updatedNode)
|
children: updateNodeInTree(node.children, oldId, updatedNode)
|
||||||
}
|
|
||||||
}
|
|
||||||
return node
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// 向节点添加子节点的辅助函数
|
|
||||||
const addChildToNode = (
|
|
||||||
nodes: TreeNode[],
|
|
||||||
parentName: string,
|
|
||||||
childNode: TreeNode
|
|
||||||
): TreeNode[] => {
|
|
||||||
return nodes.map((node) => {
|
|
||||||
if (
|
|
||||||
node.name === parentName ||
|
|
||||||
(node.path && node.path.endsWith('/' + parentName)) ||
|
|
||||||
node.path === parentName
|
|
||||||
) {
|
|
||||||
const children = node.children || []
|
|
||||||
return {
|
|
||||||
...node,
|
|
||||||
children: [...children, childNode]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (node.children) {
|
|
||||||
return {
|
|
||||||
...node,
|
|
||||||
children: addChildToNode(node.children, parentName, childNode)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return node
|
return node
|
||||||
@@ -418,10 +358,12 @@ const addChildToNode = (
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
const handleFileDialogConfirm = (data: { path: string; fullPath: string; sourceFilePath?: string }) => {
|
|
||||||
const { path, fullPath, sourceFilePath } = data
|
|
||||||
|
|
||||||
const newId = `file-${Date.now()}-${Math.random()}`
|
|
||||||
|
const handleFileDialogConfirm = (data: { path: string; sourceFilePath?: string }) => {
|
||||||
|
const { path, sourceFilePath } = data
|
||||||
|
|
||||||
|
const newId = generateUniqueId('file')
|
||||||
|
|
||||||
// Check if we're editing an existing file
|
// Check if we're editing an existing file
|
||||||
if (currentEditingItem.value && currentEditingItem.value.type === 'file') {
|
if (currentEditingItem.value && currentEditingItem.value.type === 'file') {
|
||||||
@@ -429,24 +371,21 @@ const handleFileDialogConfirm = (data: { path: string; fullPath: string; sourceF
|
|||||||
const updatedNode: TreeNode = {
|
const updatedNode: TreeNode = {
|
||||||
id: currentEditingItem.value.id,
|
id: currentEditingItem.value.id,
|
||||||
name: path,
|
name: path,
|
||||||
path: fullPath,
|
path: path,
|
||||||
type: 'file',
|
type: 'file',
|
||||||
sourceFilePath: sourceFilePath
|
sourceFilePath: sourceFilePath
|
||||||
}
|
}
|
||||||
treeStructure.value = updateNodeInTree(
|
treeStructure.value = updateNodeInTree(
|
||||||
treeStructure.value,
|
treeStructure.value,
|
||||||
currentEditingItem.value.path,
|
currentEditingItem.value.id,
|
||||||
updatedNode
|
updatedNode
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
// Check for duplicate names in the same parent directory
|
// Check for duplicate names in the same parent directory
|
||||||
if (parentDirectoryForNewItems.value) {
|
if (parentDirectoryForNewItems.value) {
|
||||||
// In the parent directory, check if a node with the same name already exists
|
// In the parent directory, check if a node with the same name already exists
|
||||||
const parentNode = findNodeInTreeByName(
|
const parentNode = parentDirectoryForNewItems.value
|
||||||
treeStructure.value,
|
if (parentNode.children) {
|
||||||
parentDirectoryForNewItems.value
|
|
||||||
)
|
|
||||||
if (parentNode && parentNode.children) {
|
|
||||||
const duplicateExists = parentNode.children.some(
|
const duplicateExists = parentNode.children.some(
|
||||||
(child) => child.name === path
|
(child) => child.name === path
|
||||||
)
|
)
|
||||||
@@ -466,65 +405,29 @@ const handleFileDialogConfirm = (data: { path: string; fullPath: string; sourceF
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Also check for duplicates using the full path (for backward compatibility)
|
const newFileNode: TreeNode = {
|
||||||
const hasDuplicate = checkForDuplicateInTree(treeStructure.value, fullPath)
|
id: newId,
|
||||||
if (hasDuplicate) {
|
name: path,
|
||||||
snackbar.error('该文件路径已存在!')
|
path: path,
|
||||||
return
|
type: 'file',
|
||||||
|
sourceFilePath
|
||||||
}
|
}
|
||||||
|
|
||||||
// If we have a selected file, just add it
|
// Add to tree structure
|
||||||
if (sourceFilePath) {
|
if (parentDirectoryForNewItems.value) {
|
||||||
const newFileNode: TreeNode = {
|
// Add as child to the parent directory
|
||||||
id: newId,
|
const parentNode = parentDirectoryForNewItems.value
|
||||||
name: path,
|
parentNode.children = parentNode.children || []
|
||||||
path: fullPath,
|
parentNode.children.push(newFileNode)
|
||||||
type: 'file',
|
|
||||||
sourceFilePath
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add to tree structure
|
|
||||||
if (parentDirectoryForNewItems.value) {
|
|
||||||
// Add as child to the parent directory
|
|
||||||
treeStructure.value = addChildToNode(
|
|
||||||
treeStructure.value,
|
|
||||||
parentDirectoryForNewItems.value,
|
|
||||||
newFileNode
|
|
||||||
)
|
|
||||||
} else {
|
|
||||||
// Add as root node
|
|
||||||
treeStructure.value.push(newFileNode)
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
// Otherwise, show warning
|
// Add as root node
|
||||||
snackbar.warning('请先选择一个文件或文件夹')
|
treeStructure.value.push(newFileNode)
|
||||||
return
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
showFileDialog.value = false
|
showFileDialog.value = false
|
||||||
parentDirectoryForNewItems.value = null // Clear parent context after creation
|
parentDirectoryForNewItems.value = null // Clear parent context after creation
|
||||||
currentEditingItem.value = null
|
currentEditingItem.value = null
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
// 检查树中是否有重复路径的辅助函数
|
|
||||||
const checkForDuplicateInTree = (
|
|
||||||
nodes: TreeNode[],
|
|
||||||
pathToCheck: string
|
|
||||||
): boolean => {
|
|
||||||
for (const node of nodes) {
|
|
||||||
if (node.path === pathToCheck) {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
if (node.children) {
|
|
||||||
if (checkForDuplicateInTree(node.children, pathToCheck)) {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const goBack = async () => {
|
const goBack = async () => {
|
||||||
@@ -547,25 +450,11 @@ const goBack = async () => {
|
|||||||
|
|
||||||
|
|
||||||
// Unified method to edit items (both files and directories)
|
// Unified method to edit items (both files and directories)
|
||||||
// This function needs to find the actual path of the item in our hierarchical tree
|
const editItem = (item: TreeNode) => {
|
||||||
const editItem = (item: TreeItem) => {
|
if (item.type === 'directory') {
|
||||||
// Find the node in the tree structure
|
showEditDirectoryDialog(item)
|
||||||
const node = findNodeInTree(treeStructure.value, item.id)
|
|
||||||
if (node) {
|
|
||||||
const nodeData = {
|
|
||||||
id: node.id,
|
|
||||||
path: node.path,
|
|
||||||
type: node.type,
|
|
||||||
sourceFilePath: node.sourceFilePath, // For files
|
|
||||||
name: node.name
|
|
||||||
}
|
|
||||||
if (node.type === 'directory') {
|
|
||||||
showEditDirectoryDialog(nodeData)
|
|
||||||
} else {
|
|
||||||
showEditFileDialog(nodeData)
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
snackbar.error('无法找到对应的节点')
|
showEditFileDialog(item)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -585,25 +474,6 @@ const findNodeInTree = (nodes: TreeNode[], nodeId: string): TreeNode | null => {
|
|||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
// 通过节点名称查找节点的辅助函数
|
|
||||||
const findNodeInTreeByName = (
|
|
||||||
nodes: TreeNode[],
|
|
||||||
nodeName: string
|
|
||||||
): TreeNode | null => {
|
|
||||||
for (const node of nodes) {
|
|
||||||
if (node.name === nodeName) {
|
|
||||||
return node
|
|
||||||
}
|
|
||||||
if (node.children) {
|
|
||||||
const found = findNodeInTreeByName(node.children, nodeName)
|
|
||||||
if (found) {
|
|
||||||
return found
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Show dialog to edit directory
|
// Show dialog to edit directory
|
||||||
const showEditDirectoryDialog = (directory: TreeNode) => {
|
const showEditDirectoryDialog = (directory: TreeNode) => {
|
||||||
@@ -621,7 +491,7 @@ const showEditFileDialog = (file: TreeNode) => {
|
|||||||
showFileDialog.value = true
|
showFileDialog.value = true
|
||||||
}
|
}
|
||||||
|
|
||||||
const deleteItem = async (item: TreeItem) => {
|
const deleteItem = async (item: TreeNode) => {
|
||||||
const confirmed = await ConfirmDialogService.confirm({
|
const confirmed = await ConfirmDialogService.confirm({
|
||||||
title: '删除确认',
|
title: '删除确认',
|
||||||
message: '确定要删除此项吗?',
|
message: '确定要删除此项吗?',
|
||||||
|
|||||||
@@ -9,3 +9,14 @@ export async function openExternal(url: string): Promise<void> {
|
|||||||
export async function openFile(type: string): Promise<any> {
|
export async function openFile(type: string): Promise<any> {
|
||||||
return window.mainApi.invoke('msgOpenFile', type)
|
return window.mainApi.invoke('msgOpenFile', type)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 生成唯一ID
|
||||||
|
* @param prefix ID前缀,默认为空
|
||||||
|
* @returns 唯一ID字符串
|
||||||
|
*/
|
||||||
|
export function generateUniqueId(prefix: string = ''): string {
|
||||||
|
const timestamp = Date.now().toString(36) // 转换为36进制,更短
|
||||||
|
const randomStr = Math.random().toString(36).substring(2, 9) // 7位随机字符
|
||||||
|
return prefix ? `${prefix}-${timestamp}-${randomStr}` : `${timestamp}-${randomStr}`
|
||||||
|
}
|
||||||
Reference in new issue
Block a user