feat: add @mdi/font and electron-devtools-installer dependencies

- Added @mdi/font for Material Design Icons support.
- Included electron-devtools-installer to facilitate Vue DevTools installation in development.

refactor: enhance CreateTemplateScreen layout and functionality

- Improved layout with a responsive design.
- Added functionality for adding directories and files with validation.
- Implemented a file content editor dialog for editing file contents.
- Updated template save logic to handle changes more effectively.

fix: update TemplateListScreen for better UX

- Enhanced template list display with improved card layout.
- Added action buttons for viewing, executing, editing, and deleting templates.
- Improved dialog handling for template details and execution.

chore: update vuetify plugin configuration

- Removed unused icon set configuration.
- Updated locale settings to use simplified Chinese.

style: clean up HeaderLayout and vuetify styles

- Removed commented-out code and unnecessary styles.
- Improved overall styling for better readability and consistency.
This commit is contained in:
zhanggy committed 2025-10-27 18:19:39 +08:00
1 parent 1aecd5f4b6
commit 4f859a4933
8 files changed
+653 -394

No files matched your search

+103 -115
View File
@@ -2,13 +2,15 @@
<v-container>
<v-row>
<v-col cols="12">
<h2 class="mb-4"> 模板列表 </h2>
<div class="d-flex align-center mb-4 justify-space-between flex-wrap">
<h2 class="mr-2 mb-2"> 模板列表 </h2>
<v-btn @click="navigateToCreateTemplate" color="primary" prepend-icon="mdi-plus" class="mb-2">
创建模板
</v-btn>
</div>
<!-- No templates message -->
<v-card
v-if="templates.length === 0"
class="pa-6 mb-4 text-center"
>
<v-card v-if="templates.length === 0" class="pa-6 mb-4 text-center">
<v-card-title class="text-h5 mb-4">
暂无模板
</v-card-title>
@@ -16,12 +18,7 @@
<p>还没有创建任何模板。创建您的第一个模板以开始批量生成文件和目录。</p>
</v-card-text>
<v-card-actions class="justify-center">
<v-btn
color="primary"
size="x-large"
@click="navigateToCreateTemplate"
prepend-icon="mdi-plus"
>
<v-btn color="primary" size="default" @click="navigateToCreateTemplate" prepend-icon="mdi-plus">
创建模板
</v-btn>
</v-card-actions>
@@ -30,38 +27,61 @@
<!-- Template list -->
<div v-else>
<v-row>
<v-col
v-for="template in templates"
:key="template.id"
cols="12"
md="6"
lg="4"
>
<v-card
class="d-flex flex-column"
height="100%"
>
<v-card-title>{{ template.name }}</v-card-title>
<v-card-subtitle>{{ template.description }}</v-card-subtitle>
<v-card-text class="flex-grow-1">
<p>文件数量: {{ template.files.length }}</p>
<p>目录数量: {{ template.directories.length }}</p>
<v-col v-for="template in templates" :key="template.id" cols="12" sm="6" md="4" lg="3">
<v-card class="d-flex flex-column" height="100%">
<v-card-item>
<v-card-title>{{ template.name }}</v-card-title>
<v-card-subtitle>{{ template.description }}</v-card-subtitle>
</v-card-item>
<v-card-text class="flex-grow-1 py-2">
<v-chip-group column>
<v-chip size="small" color="primary" variant="tonal">
文件: {{ template.files.length }}
</v-chip>
<v-chip size="small" color="success" variant="tonal">
目录: {{ template.directories.length }}
</v-chip>
</v-chip-group>
</v-card-text>
<v-card-actions>
<v-btn
color="primary"
variant="outlined"
@click="viewTemplate(template)"
>
查看
</v-btn>
<v-btn
color="success"
variant="outlined"
@click="executeTemplate(template)"
>
执行
</v-btn>
<v-divider class="mt-auto"></v-divider>
<v-card-actions class="pa-2 justify-space-between">
<div>
<v-btn color="primary" variant="text" size="small" @click="viewTemplate(template)">
查看
</v-btn>
<v-btn color="success" variant="text" size="small" @click="executeTemplate(template)">
执行
</v-btn>
</div>
<v-menu location="bottom end">
<template v-slot:activator="{ props }">
<v-btn v-bind="props" icon variant="text" size="small" density="comfortable">
<v-icon>mdi-dots-vertical</v-icon>
</v-btn>
</template>
<v-list density="compact">
<v-list-item @click="editTemplate(template)">
<template v-slot:prepend>
<v-icon>mdi-pencil</v-icon>
</template>
<v-list-item-title>修改</v-list-item-title>
</v-list-item>
<v-divider></v-divider>
<v-list-item @click="deleteTemplate(template)">
<template v-slot:prepend>
<v-icon color="error">mdi-delete</v-icon>
</template>
<v-list-item-title class="text-error">删除</v-list-item-title>
</v-list-item>
</v-list>
</v-menu>
</v-card-actions>
</v-card>
</v-col>
@@ -71,37 +91,20 @@
</v-row>
<!-- Template detail dialog -->
<v-dialog
v-model="showTemplateDetail"
max-width="800"
>
<v-dialog v-model="showTemplateDetail" max-width="800">
<v-card>
<v-card-title>
<span>模板详情: {{ selectedTemplate?.name }}</span>
<v-spacer />
<v-btn
icon
@click="showTemplateDetail = false"
>
<v-icon>mdi-close</v-icon>
</v-btn>
</v-card-title>
<v-card-text>
<v-treeview
:items="templateTree"
item-title="name"
item-key="id"
item-children="children"
activatable
open-all
>
<template v-slot:prepend="{ item, open }">
<v-treeview :items="templateTree" item-title="name" item-key="id" item-children="children" activatable
open-all>
<template v-slot:prepend="{ item }">
<v-icon>
{{
item.type === 'directory'
? open
? 'mdi-folder-open'
: 'mdi-folder'
? 'mdi-folder'
: 'mdi-file'
}}
</v-icon>
@@ -112,63 +115,27 @@
</v-dialog>
<!-- Execute template dialog -->
<v-dialog
v-model="showExecuteDialog"
max-width="600"
>
<v-dialog v-model="showExecuteDialog" max-width="600">
<v-card>
<v-card-title>执行模板</v-card-title>
<v-card-text>
<v-form v-model="executeFormValid">
<v-text-field
v-model="executePath"
label="选择目录"
readonly
@click="selectDirectory"
prepend-inner-icon="mdi-folder"
:rules="[(v) => !!v || '请选择目录']"
/>
<v-textarea
v-model="baseDirNames"
label="基础目录名 (每行一个,支持批量)"
placeholder="输入基础目录名,每行一个"
:rules="[(v) => !!v || '请输入基础目录名']"
/>
<v-text-field v-model="executePath" label="选择目录" readonly @click="selectDirectory"
prepend-inner-icon="mdi-folder" :rules="[(v) => !!v || '请选择目录']" />
<v-textarea v-model="baseDirNames" label="基础目录名 (每行一个,支持批量)" placeholder="输入基础目录名,每行一个"
:rules="[(v) => !!v || '请输入基础目录名']" />
</v-form>
</v-card-text>
<v-card-actions>
<v-spacer />
<v-btn @click="showExecuteDialog = false"> 取消 </v-btn>
<v-btn
color="success"
@click="confirmExecuteTemplate"
:disabled="!executeFormValid"
>
<v-btn color="success" @click="confirmExecuteTemplate" :disabled="!executeFormValid">
确认执行
</v-btn>
</v-card-actions>
</v-card>
</v-dialog>
<!-- Floating Action Button for creating templates -->
<v-btn
v-if="templates.length > 0"
color="primary"
size="x-large"
icon="mdi-plus"
fixed
location="bottom end"
class="mb-8 mr-8"
style="z-index: 1000;"
@click="navigateToCreateTemplate"
>
<v-tooltip
activator="parent"
location="top"
>
创建模板
</v-tooltip>
</v-btn>
</v-container>
</template>
@@ -176,6 +143,7 @@
import { ref, computed, onMounted } from 'vue'
import { useRouter } from 'vue-router'
import { useTemplateStore } from '@/renderer/store/template'
import { Template } from '@/renderer/store/template'
const router = useRouter()
const templateStore = useTemplateStore()
@@ -185,11 +153,13 @@ onMounted(async () => {
await templateStore.loadTemplates()
})
const { deleteTemplate: storeDeleteTemplate } = templateStore
const templates = computed(() => templateStore.templates)
// Template detail view
const showTemplateDetail = ref(false)
const selectedTemplate = ref(null as any)
const selectedTemplate = ref<Template | null>(null)
// Execute template
const showExecuteDialog = ref(false)
@@ -197,13 +167,21 @@ const executePath = ref('')
const baseDirNames = ref('')
const executeFormValid = ref(false)
const templateTree = computed(() => {
// Define item type for the tree view
interface TreeNode {
id: string
name: string
type: 'directory' | 'file'
children?: TreeNode[]
}
const templateTree = computed<TreeNode[]>(() => {
if (!selectedTemplate.value) return []
const items = []
const items: TreeNode[] = []
// Add directories
selectedTemplate.value.directories.forEach((dir: any) => {
selectedTemplate.value.directories.forEach((dir) => {
items.push({
id: `dir-${dir.path}`,
name: dir.path,
@@ -213,7 +191,7 @@ const templateTree = computed(() => {
})
// Add files
selectedTemplate.value.files.forEach((file: any) => {
selectedTemplate.value.files.forEach((file) => {
items.push({
id: `file-${file.path}`,
name: file.path,
@@ -228,12 +206,22 @@ const navigateToCreateTemplate = () => {
router.push('/create-template')
}
const viewTemplate = (template: any) => {
const viewTemplate = (template: Template) => {
selectedTemplate.value = template
showTemplateDetail.value = true
}
const executeTemplate = (template: any) => {
const editTemplate = (template: Template) => {
router.push(`/create-template/${template.id}`)
}
const deleteTemplate = (template: Template) => {
if (confirm(`确定要删除模板 "${template.name}" 吗?此操作不可撤销。`)) {
storeDeleteTemplate(template.id)
}
}
const executeTemplate = (template: Template) => {
selectedTemplate.value = template
executePath.value = ''
baseDirNames.value = ''
@@ -248,7 +236,7 @@ const selectDirectory = async () => {
}
const confirmExecuteTemplate = () => {
if (!executePath.value || !baseDirNames.value.trim()) return
if (!executePath.value || !baseDirNames.value.trim() || !selectedTemplate.value) return
const dirNames = baseDirNames.value.split('\n').filter((name) => name.trim())