|
8 | 8 | </h3>
|
9 | 9 |
|
10 | 10 | <div class="space-y-4">
|
11 |
| - <!-- 当前日志目录 --> |
12 |
| - <div> |
13 |
| - <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-2"> |
14 |
| - 当前日志目录 |
15 |
| - </label> |
| 11 | + <Label label="当前日志目录"> |
16 | 12 | <div class="bg-gray-50 dark:bg-gray-700 rounded-lg p-3 text-sm text-gray-600 dark:text-gray-400 font-mono">
|
17 | 13 | {{ currentLogDir || '加载中...' }}
|
18 | 14 | </div>
|
19 |
| - </div> |
| 15 | + </Label> |
20 | 16 |
|
21 |
| - <!-- 修改日志目录 --> |
22 |
| - <div> |
23 |
| - <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-2"> |
24 |
| - 选择新的日志目录 |
25 |
| - </label> |
| 17 | + <Label label="选择新的日志目录"> |
26 | 18 | <div class="flex gap-2">
|
27 | 19 | <input v-model="newLogDir"
|
28 | 20 | type="text"
|
|
36 | 28 | @click="selectLogDirectory">
|
37 | 29 | </Button>
|
38 | 30 | </div>
|
39 |
| - </div> |
| 31 | + </Label> |
40 | 32 |
|
41 | 33 | <!-- 操作按钮 -->
|
42 | 34 | <div class="flex gap-3 pt-0.5">
|
|
54 | 46 | </Button>
|
55 | 47 | </div>
|
56 | 48 |
|
57 |
| - <!-- 日志文件列表 --> |
58 |
| - <div v-if="logFiles.length > 0"> |
59 |
| - <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-2"> |
60 |
| - 最近的日志文件 |
61 |
| - </label> |
| 49 | + <Label v-if="logFiles.length > 0" label="最近的日志文件"> |
62 | 50 | <div class="bg-gray-50 dark:bg-gray-700 rounded-lg p-3 max-h-32 overflow-y-auto">
|
63 | 51 | <div v-for="file in logFiles.slice(0, 5)" :key="file"
|
64 | 52 | class="text-sm text-gray-600 dark:text-gray-400 font-mono py-1 hover:text-blue-600 dark:hover:text-blue-400 cursor-pointer"
|
65 | 53 | @click="openLogFile(file)">
|
66 | 54 | {{ file }}
|
67 | 55 | </div>
|
68 | 56 | </div>
|
69 |
| - </div> |
| 57 | + </Label> |
70 | 58 | </div>
|
71 | 59 | </div>
|
72 | 60 |
|
|
78 | 66 | </h3>
|
79 | 67 |
|
80 | 68 | <div class="space-y-4">
|
81 |
| - <!-- 清理旧日志 --> |
82 |
| - <div> |
83 |
| - <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-2"> |
84 |
| - 自动清理日志 |
85 |
| - </label> |
| 69 | + <Label label="清理日志"> |
86 | 70 | <div class="flex items-center gap-3">
|
87 | 71 | <Select v-model="keepDays"
|
88 | 72 | class="w-36"
|
|
93 | 77 | 立即清理
|
94 | 78 | </Button>
|
95 | 79 | </div>
|
96 |
| - </div> |
| 80 | + </Label> |
97 | 81 | </div>
|
98 | 82 | </div>
|
99 | 83 | </div>
|
100 | 84 | </template>
|
101 | 85 |
|
102 | 86 | <script setup lang="ts">
|
103 |
| -import { onMounted, ref } from 'vue' |
104 |
| -import { invoke } from '@tauri-apps/api/core' |
105 |
| -import { open as openDialog } from '@tauri-apps/plugin-dialog' |
106 |
| -import { openPath } from '@tauri-apps/plugin-opener' |
| 87 | +import { onMounted } from 'vue' |
107 | 88 | import { FileText, Folder, Settings2 } from 'lucide-vue-next'
|
108 | 89 | import Select from '../../ui/Select.vue'
|
109 | 90 | import Button from '../../ui/Button.vue'
|
110 |
| -import { useToast } from '../../plugins/toast' |
| 91 | +import Label from '../../ui/Label.vue' |
| 92 | +import { useLogDirectory } from '../../composables/useLogDirectory' |
| 93 | +import { useLogCleanup } from '../../composables/useLogCleanup' |
111 | 94 |
|
112 | 95 | const emit = defineEmits<{
|
113 | 96 | 'settings-changed': [type: string, value: any]
|
114 | 97 | 'error': [message: string]
|
115 | 98 | }>()
|
116 | 99 |
|
117 |
| -const toast = useToast() |
118 |
| -
|
119 |
| -const currentLogDir = ref('') |
120 |
| -const newLogDir = ref('') |
121 |
| -const logFiles = ref<string[]>([]) |
122 |
| -const keepDays = ref(30) |
123 |
| -
|
124 |
| -const keepDaysOptions = [ |
125 |
| - { label: '保留 1 天', value: 1 }, |
126 |
| - { label: '保留 7 天', value: 7 }, |
127 |
| - { label: '保留 14 天', value: 14 }, |
128 |
| - { label: '保留 30 天', value: 30 }, |
129 |
| - { label: '保留 90 天', value: 90 } |
130 |
| -] |
131 |
| -
|
132 |
| -const loadLogDirectory = async () => { |
133 |
| - try { |
134 |
| - const logDir = await invoke<string>('get_log_directory') |
135 |
| - currentLogDir.value = logDir |
136 |
| - newLogDir.value = logDir |
137 |
| - } |
138 |
| - catch (error) { |
139 |
| - console.error('Failed to get current log directory:', error) |
140 |
| - toast.error('获取日志目录失败 - 错误信息: ' + error) |
141 |
| - emit('error', '获取日志目录失败') |
142 |
| - } |
143 |
| -} |
144 |
| -
|
145 |
| -const loadLogFiles = async () => { |
146 |
| - try { |
147 |
| - logFiles.value = await invoke<string[]>('get_log_files') |
148 |
| - } |
149 |
| - catch (error) { |
150 |
| - console.error('Failed to get log files:', error) |
151 |
| - emit('error', '获取日志文件列表失败') |
152 |
| - } |
153 |
| -} |
154 |
| -
|
155 |
| -const selectLogDirectory = async () => { |
156 |
| - try { |
157 |
| - const selected = await openDialog({ |
158 |
| - directory: true, |
159 |
| - multiple: false, |
160 |
| - title: '选择日志目录' |
161 |
| - }) |
162 |
| -
|
163 |
| - if (selected) { |
164 |
| - newLogDir.value = selected as string |
165 |
| - } |
166 |
| - } |
167 |
| - catch (error) { |
168 |
| - console.error('Failed to select directory:', error) |
169 |
| - emit('error', '选择目录失败') |
170 |
| - } |
171 |
| -} |
172 |
| -
|
173 |
| -const applyLogDirChange = async () => { |
174 |
| - try { |
175 |
| - await invoke('set_log_directory', { path: newLogDir.value }) |
176 |
| - currentLogDir.value = newLogDir.value |
177 |
| - await loadLogFiles() |
178 |
| - toast.success('日志目录已更新') |
179 |
| - emit('settings-changed', 'logDirectory', newLogDir.value) |
180 |
| - } |
181 |
| - catch (error) { |
182 |
| - console.error('Failed to set log directory:', error) |
183 |
| - const errorMessage = '日志目录更新失败, 错误信息: ' + error |
184 |
| - toast.error(errorMessage) |
185 |
| - emit('error', errorMessage) |
186 |
| - } |
187 |
| -} |
188 |
| -
|
189 |
| -const openLogDirectory = async () => { |
190 |
| - try { |
191 |
| - await openPath(currentLogDir.value) |
192 |
| - } |
193 |
| - catch (error) { |
194 |
| - console.error('Failed to open log directory:', error) |
195 |
| - emit('error', '打开日志目录失败') |
196 |
| - } |
197 |
| -} |
198 |
| -
|
199 |
| -const resetLogDirectory = async () => { |
200 |
| - try { |
201 |
| - await invoke('reset_log_directory') |
202 |
| - await loadLogDirectory() |
203 |
| - await loadLogFiles() |
204 |
| - toast.success('日志目录已重置为默认') |
205 |
| - emit('settings-changed', 'logDirectory', 'reset') |
206 |
| - } |
207 |
| - catch (error) { |
208 |
| - console.error('Failed to reset log directory:', error) |
209 |
| - const errorMessage = '日志目录重置失败, 错误信息: ' + error |
210 |
| - toast.error(errorMessage) |
211 |
| - emit('error', errorMessage) |
212 |
| - } |
213 |
| -} |
214 |
| -
|
215 |
| -const openLogFile = async (filename: string) => { |
216 |
| - try { |
217 |
| - const logPath = `${ currentLogDir.value }/${ filename }` |
218 |
| - await openPath(logPath) |
219 |
| - } |
220 |
| - catch (error) { |
221 |
| - console.error('Failed to open log file:', error) |
222 |
| - toast.error('打开日志文件失败 - 错误信息: ' + error) |
223 |
| - emit('error', '打开日志文件失败') |
224 |
| - } |
225 |
| -} |
226 |
| -
|
227 |
| -const clearLogs = async () => { |
228 |
| - try { |
229 |
| - await invoke('clear_logs', { keepDays: parseInt(keepDays.value.toString()) }) |
230 |
| - await loadLogFiles() |
231 |
| - toast.success(`已清理 ${ keepDays.value } 天前的日志`) |
232 |
| - emit('settings-changed', 'logCleanup', keepDays.value) |
233 |
| - } |
234 |
| - catch (error) { |
235 |
| - console.error('Failed to clear old logs:', error) |
236 |
| - const errorMessage = '清理日志失败, 错误信息: ' + error |
237 |
| - toast.error(errorMessage) |
238 |
| - emit('error', errorMessage) |
239 |
| - } |
240 |
| -} |
| 100 | +const { |
| 101 | + currentLogDir, |
| 102 | + newLogDir, |
| 103 | + logFiles, |
| 104 | + loadLogDirectory, |
| 105 | + loadLogFiles, |
| 106 | + selectLogDirectory, |
| 107 | + applyLogDirChange, |
| 108 | + openLogDirectory, |
| 109 | + resetLogDirectory, |
| 110 | + openLogFile |
| 111 | +} = useLogDirectory(emit) |
| 112 | +
|
| 113 | +const { |
| 114 | + keepDays, |
| 115 | + keepDaysOptions, |
| 116 | + clearLogs |
| 117 | +} = useLogCleanup(emit, loadLogFiles) |
241 | 118 |
|
242 | 119 | // 暴露方法给父组件
|
243 | 120 | defineExpose({
|
|
0 commit comments