feat: 更新发布工作流,优化 Git 配置,添加文件和文件夹选择功能,调整模板列表标题
This commit is contained in:
1 parent
c59dc5c159
commit
56acfb275b
9 files changed
+120
-122
No files matched your search
@@ -6,8 +6,7 @@
|
||||
<v-row class="fill-height">
|
||||
<!-- Left Panel - Template Info -->
|
||||
<v-col
|
||||
cols="12"
|
||||
md="4"
|
||||
cols="4"
|
||||
class="pa-4 border-e"
|
||||
>
|
||||
<div class="d-flex align-center mb-4">
|
||||
@@ -38,7 +37,7 @@
|
||||
v-model="templateName"
|
||||
label="模板名称 *"
|
||||
placeholder="输入模板名称"
|
||||
:rules="[requiredRule]"
|
||||
:rules="[requiredRule('模板名称')]"
|
||||
required
|
||||
clearable
|
||||
density="comfortable"
|
||||
@@ -73,8 +72,7 @@
|
||||
|
||||
<!-- Right Panel - Tree Structure -->
|
||||
<v-col
|
||||
cols="12"
|
||||
md="8"
|
||||
cols="8"
|
||||
class="pa-4"
|
||||
>
|
||||
<div class="d-flex align-center mb-4">
|
||||
@@ -164,9 +162,9 @@
|
||||
<v-form v-model="directoryFormValid">
|
||||
<v-text-field
|
||||
v-model="newDirectoryPath"
|
||||
:label="currentEditingItem ? '新目录路径 *' : '目录路径 *'"
|
||||
:placeholder="currentEditingItem ? '例如: src/new-components' : '例如: src/components'"
|
||||
:rules="[requiredRule]"
|
||||
:label="'目录名称'"
|
||||
:placeholder="'请输入目录名称'"
|
||||
:rules="[requiredRule('目录名称')]"
|
||||
required
|
||||
density="comfortable"
|
||||
ref="directoryInputRef"
|
||||
@@ -203,34 +201,39 @@
|
||||
<v-form v-model="fileFormValid">
|
||||
<v-text-field
|
||||
v-model="newFilePath"
|
||||
:label="currentEditingItem ? '新文件路径 *' : '目标文件路径 *'"
|
||||
:placeholder="currentEditingItem ? '例如: src/new-index.js' : '例如: src/index.js'"
|
||||
:rules="[requiredRule]"
|
||||
:label="'文件名'"
|
||||
:placeholder="'文件名需要带上后缀,如:style skech.doc'"
|
||||
:rules="[requiredRule('文件名')]"
|
||||
required
|
||||
density="comfortable"
|
||||
ref="fileInputRef"
|
||||
@keydown.enter="selectAndAddFile"
|
||||
/>
|
||||
<v-file-input webkitdirectory directory label="选择文件或文件夹" density="comfortable"></v-file-input>
|
||||
|
||||
<div class="d-flex align-center my-4">
|
||||
<v-btn
|
||||
@click="selectSourceFile"
|
||||
@click="selectSourceFileOrFolder"
|
||||
variant="outlined"
|
||||
class="mr-2"
|
||||
:disabled="!!currentEditingItem"
|
||||
>
|
||||
选择文件
|
||||
</v-btn>
|
||||
<v-btn
|
||||
@click="selectSourceFolder"
|
||||
variant="outlined"
|
||||
class="mr-2"
|
||||
:disabled="!!currentEditingItem"
|
||||
>
|
||||
选择文件夹
|
||||
选择文件或文件夹
|
||||
</v-btn>
|
||||
</div>
|
||||
|
||||
<!-- 选择提示 -->
|
||||
<v-alert
|
||||
type="info"
|
||||
variant="tonal"
|
||||
class="mt-2"
|
||||
>
|
||||
<div class="d-flex align-start flex-column">
|
||||
<span>选择文件会直接复制到目标位置</span>
|
||||
<span>选择文件夹则会自动匹配该文件夹下的文件进行复制并且重命名</span>
|
||||
</div>
|
||||
</v-alert>
|
||||
|
||||
<!-- Display selected source -->
|
||||
<div v-if="selectedSourcePath" class="d-flex align-center">
|
||||
<v-icon :color="isAutoFindMode ? 'warning' : 'info'" class="mr-2">
|
||||
@@ -238,32 +241,6 @@
|
||||
</v-icon>
|
||||
<span class="text-truncate">{{ selectedSourcePath }}</span>
|
||||
</div>
|
||||
|
||||
<!-- Auto-find indicator -->
|
||||
<v-alert
|
||||
v-if="isAutoFindMode"
|
||||
type="info"
|
||||
variant="tonal"
|
||||
class="mt-2"
|
||||
>
|
||||
<div class="d-flex align-center">
|
||||
<v-icon class="mr-2">mdi-auto-fix</v-icon>
|
||||
<span>自动寻找文件夹内的文件</span>
|
||||
</div>
|
||||
</v-alert>
|
||||
|
||||
<!-- Note when editing -->
|
||||
<v-alert
|
||||
v-if="currentEditingItem"
|
||||
type="warning"
|
||||
variant="tonal"
|
||||
class="mt-2"
|
||||
>
|
||||
<div class="d-flex align-center">
|
||||
<v-icon class="mr-2">mdi-information</v-icon>
|
||||
<span>正在编辑现有文件路径,文件源不会改变</span>
|
||||
</div>
|
||||
</v-alert>
|
||||
</v-form>
|
||||
</v-card-text>
|
||||
<v-card-actions>
|
||||
@@ -430,7 +407,7 @@ const convertToTreeItem = (node: TreeNode): TreeItem => {
|
||||
}
|
||||
|
||||
// Validation rules
|
||||
const requiredRule = (v: string | null | undefined) => !!v || '此字段为必填项'
|
||||
const requiredRule = (fieldName: string) => (v: string | null | undefined) => !!v || `${fieldName}为必填项`
|
||||
|
||||
// Watch for changes to detect unsaved changes
|
||||
watch(
|
||||
@@ -542,7 +519,7 @@ const confirmAddDirectory = () => {
|
||||
// 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 =>
|
||||
const duplicateExists = parentNode.children.some(child =>
|
||||
child.name === newDirectoryPath.value
|
||||
);
|
||||
if (duplicateExists) {
|
||||
@@ -552,7 +529,7 @@ const confirmAddDirectory = () => {
|
||||
}
|
||||
} else {
|
||||
// Check at root level for duplicates
|
||||
const duplicateExists = treeStructure.value.some(node =>
|
||||
const duplicateExists = treeStructure.value.some(node =>
|
||||
node.name === newDirectoryPath.value
|
||||
);
|
||||
if (duplicateExists) {
|
||||
@@ -692,7 +669,7 @@ const selectAndAddFile = async () => {
|
||||
// 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 =>
|
||||
const duplicateExists = parentNode.children.some(child =>
|
||||
child.name === newFilePath.value
|
||||
);
|
||||
if (duplicateExists) {
|
||||
@@ -702,7 +679,7 @@ const selectAndAddFile = async () => {
|
||||
}
|
||||
} else {
|
||||
// Check at root level for duplicates
|
||||
const duplicateExists = treeStructure.value.some(node =>
|
||||
const duplicateExists = treeStructure.value.some(node =>
|
||||
node.name === newFilePath.value
|
||||
);
|
||||
if (duplicateExists) {
|
||||
@@ -710,7 +687,7 @@ const selectAndAddFile = async () => {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Also check for duplicates using the full path (for backward compatibility)
|
||||
const hasDuplicate = checkForDuplicateInTree(treeStructure.value, fullPath);
|
||||
if (hasDuplicate) {
|
||||
@@ -733,24 +710,24 @@ const selectAndAddFile = async () => {
|
||||
const hasDuplicateInTree = checkForDuplicateInTree(treeStructure.value, fullTargetPath);
|
||||
if (!hasDuplicateInTree) {
|
||||
const fileName = fullTargetPath.split('/').pop() || fullTargetPath;
|
||||
|
||||
|
||||
// Additionally, check for duplicate names in the same parent directory
|
||||
let duplicateNameExists = false;
|
||||
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) {
|
||||
duplicateNameExists = parentNode.children.some(child =>
|
||||
duplicateNameExists = parentNode.children.some(child =>
|
||||
child.name === fileName
|
||||
);
|
||||
}
|
||||
} else {
|
||||
// Check at root level for duplicates
|
||||
duplicateNameExists = treeStructure.value.some(node =>
|
||||
duplicateNameExists = treeStructure.value.some(node =>
|
||||
node.name === fileName
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
if (duplicateNameExists) {
|
||||
showSnackbar(`当前目录下已存在同名节点:${fileName}`, 'error');
|
||||
} else {
|
||||
@@ -799,17 +776,17 @@ const selectAndAddFile = async () => {
|
||||
// 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) {
|
||||
duplicateNameExists = parentNode.children.some(child =>
|
||||
duplicateNameExists = parentNode.children.some(child =>
|
||||
child.name === newFilePath.value
|
||||
);
|
||||
}
|
||||
} else {
|
||||
// Check at root level for duplicates
|
||||
duplicateNameExists = treeStructure.value.some(node =>
|
||||
duplicateNameExists = treeStructure.value.some(node =>
|
||||
node.name === newFilePath.value
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
if (duplicateNameExists) {
|
||||
showSnackbar('当前目录下已存在同名节点!', 'error');
|
||||
} else {
|
||||
@@ -1062,19 +1039,13 @@ const showSnackbar = (message: string, color: string = 'error') => {
|
||||
}
|
||||
|
||||
// Methods for file/folder selection
|
||||
const selectSourceFile = async () => {
|
||||
const result = await window.mainApi.invoke('msgOpenFile', 'any')
|
||||
if (!result.canceled && result.filePaths && result.filePaths.length > 0) {
|
||||
selectedSourcePath.value = result.filePaths[0]
|
||||
isAutoFindMode.value = false // Not in auto-find mode when selecting a specific file
|
||||
}
|
||||
}
|
||||
const selectSourceFileOrFolder = async () => {
|
||||
// 使用现有的主进程API来选择文件或文件夹
|
||||
const result = await window.mainApi.invoke('msgSelectFileOrFolder')
|
||||
|
||||
const selectSourceFolder = async () => {
|
||||
const result = await window.mainApi.invoke('msgSelectDirectory')
|
||||
if (!result.canceled && result.filePath) {
|
||||
if (result && result.filePath) {
|
||||
selectedSourcePath.value = result.filePath
|
||||
isAutoFindMode.value = true // In auto-find mode when selecting a folder
|
||||
isAutoFindMode.value = result.isDirectory // 如果是目录,则启用自动查找模式
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in new issue
Block a user