feat(app): 添加文件清空确认对话框功能

- 引入 ConfirmClearDialog 组件用于清空文件确认
- 添加 clear-files-no-prompt 配置项控制是否显示确认弹窗
- 实现清空文件列表显示和确认逻辑
- 集成 Element Plus 图标组件库
- 优化日志输出格式增加空格分隔
- 重构配置写入方法使用统一的 configModel 枚举
- 添加事件监听处理清空文件操作
- 实现勾选不再提示选项并保存配置
This commit is contained in:
2026-05-01 20:45:17 +08:00
parent 03e4e6f45b
commit 3f6e999783
7 changed files with 195 additions and 33 deletions
+1
View File
@@ -11,6 +11,7 @@
"type-check": "vue-tsc --build" "type-check": "vue-tsc --build"
}, },
"dependencies": { "dependencies": {
"@element-plus/icons-vue": "^2.3.2",
"element-plus": "^2.13.7", "element-plus": "^2.13.7",
"vue": "^3.5.32" "vue": "^3.5.32"
}, },
+1 -1
View File
@@ -1 +1 @@
aa914e6b4676ee4621ced7ad6d81c58c 05225657934ff66d822c925754c951bf
+3
View File
@@ -8,6 +8,9 @@ importers:
.: .:
dependencies: dependencies:
'@element-plus/icons-vue':
specifier: ^2.3.2
version: 2.3.2(vue@3.5.33(typescript@6.0.3))
element-plus: element-plus:
specifier: ^2.13.7 specifier: ^2.13.7
version: 2.13.7(typescript@6.0.3)(vue@3.5.33(typescript@6.0.3)) version: 2.13.7(typescript@6.0.3)(vue@3.5.33(typescript@6.0.3))
+55 -32
View File
@@ -1,11 +1,12 @@
<script lang="ts" setup> <script lang="ts" setup>
import {ref, nextTick, computed} from 'vue' import {computed, nextTick, ref} from 'vue'
import {ElMessage} from 'element-plus' import {ElMessage, ElMessageBox} from 'element-plus'
import {ElMessageBox} from 'element-plus' import ConfirmClearDialog from './components/ConfirmClearDialog.vue'
import {SelectPath, GetConfig, WriteConfig, StartUpload, StopUpload} from '../wailsjs/go/main/App'; import {GetConfig, SelectPath, StartUpload, StopUpload, WriteConfig} from '../wailsjs/go/main/App';
import {config} from "../wailsjs/go/models.ts"; import {config} from "../wailsjs/go/models.ts";
import Config = config.Config;
import {EventsOn, LogPrint} from "../wailsjs/runtime"; import {EventsOn, LogPrint} from "../wailsjs/runtime";
import {configModel} from "@/model.ts";
import Config = config.Config;
// const serverUrl = ref('') // const serverUrl = ref('')
const token = ref('') const token = ref('')
@@ -19,6 +20,10 @@ const logOutput = ref<string[]>([])
const logContentRef = ref<HTMLElement>() const logContentRef = ref<HTMLElement>()
const logRoll = ref(true) const logRoll = ref(true)
const clearDialogVisible = ref(false)
const filesToClear = ref<string[]>([])
const noPromptClear = ref(false)
interface FileProgress { interface FileProgress {
name: string name: string
uploaded: number uploaded: number
@@ -41,7 +46,7 @@ const sortedProgressList = computed(() => {
}) })
const addLog = (msg: string) => { const addLog = (msg: string) => {
logOutput.value.push(`[${new Date().toLocaleString()}]` + msg) logOutput.value.push(`[${new Date().toLocaleString()}] ` + msg)
nextTick(() => { nextTick(() => {
if (logContentRef.value && logRoll.value) { if (logContentRef.value && logRoll.value) {
logContentRef.value.scrollTop = logContentRef.value.scrollHeight logContentRef.value.scrollTop = logContentRef.value.scrollHeight
@@ -52,9 +57,9 @@ const addLog = (msg: string) => {
const selectDirectory = () => { const selectDirectory = () => {
// ElMessage.info('请手动输入检测目录路径') // ElMessage.info('请手动输入检测目录路径')
SelectPath().then((path) => { SelectPath().then((path) => {
if (path){ if (path) {
checkDir.value = path checkDir.value = path
}else { } else {
ElMessage.warning('未选择目录,不更改配置') ElMessage.warning('未选择目录,不更改配置')
} }
}) })
@@ -99,17 +104,17 @@ const clearLog = () => {
// const writeServerUrl =() => { // const writeServerUrl =() => {
// WriteConfig("url", serverUrl.value) // WriteConfig("url", serverUrl.value)
// } // }
const writeToken =() => { const writeToken = () => {
WriteConfig("token", token.value) WriteConfig(configModel.Token, token.value)
} }
const writeCheckDir = () => { const writeCheckDir = () => {
WriteConfig("check-dir", checkDir.value) WriteConfig(configModel.CheckDir, checkDir.value)
} }
const writeConcurrentFiles = () => { const writeConcurrentFiles = () => {
WriteConfig("handle-file-count", concurrentFiles.value) WriteConfig(configModel.HandleFileCount, concurrentFiles.value)
} }
const writeUploadThreads =() => { const writeUploadThreads = () => {
WriteConfig("thread-count", uploadThreads.value) WriteConfig(configModel.ThreadCount, uploadThreads.value)
} }
// const writeAutoStart = () => { // const writeAutoStart = () => {
// WriteConfig("is-run-on-start", autoStart.value) // WriteConfig("is-run-on-start", autoStart.value)
@@ -124,6 +129,7 @@ try {
concurrentFiles.value = config.handle_file_count concurrentFiles.value = config.handle_file_count
uploadThreads.value = config.thread_count uploadThreads.value = config.thread_count
// autoStart.value = config.is_run_on_start // autoStart.value = config.is_run_on_start
noPromptClear.value = config.clear_files_no_prompt
LogPrint(`[${new Date().toLocaleString()}] 配置已加载`) LogPrint(`[${new Date().toLocaleString()}] 配置已加载`)
}) })
@@ -131,24 +137,34 @@ try {
console.log(e) console.log(e)
} }
EventsOn("is-run", (run) => { try {
isRunning.value = run EventsOn("is-run", (run) => {
}) isRunning.value = run
EventsOn("progress", (progress) => { })
progressList.value = progress EventsOn("progress", (progress) => {
}) progressList.value = progress
EventsOn("log", (msg) => { })
addLog(msg) EventsOn("log", (msg) => {
}) addLog(msg)
})
EventsOn("clear-files", (files) => {
filesToClear.value = files
if (!noPromptClear.value) {
clearDialogVisible.value = true
}
})
} catch (e) {
console.log(e)
}
</script> </script>
<template> <template>
<div class="container"> <div class="container">
<div class="left-panel"> <div class="left-panel">
<!-- <div class="form-item">--> <!-- <div class="form-item">-->
<!-- <label>服务器地址</label>--> <!-- <label>服务器地址</label>-->
<!-- <el-input v-model="serverUrl" placeholder="请输入服务器地址" :disabled="isRunning" @change="writeServerUrl()"/>--> <!-- <el-input v-model="serverUrl" placeholder="请输入服务器地址" :disabled="isRunning" @change="writeServerUrl()"/>-->
<!-- </div>--> <!-- </div>-->
<div class="form-item"> <div class="form-item">
<label>Token</label> <label>Token</label>
@@ -165,17 +181,19 @@ EventsOn("log", (msg) => {
<div class="form-item"> <div class="form-item">
<label>同时处理文件数</label> <label>同时处理文件数</label>
<el-input-number v-model="concurrentFiles" :min="1" :max="100" :disabled="isRunning" @change="writeConcurrentFiles()"/> <el-input-number v-model="concurrentFiles" :min="1" :max="100" :disabled="isRunning"
@change="writeConcurrentFiles()"/>
</div> </div>
<div class="form-item"> <div class="form-item">
<label>单文件上传线程</label> <label>单文件上传线程</label>
<el-input-number v-model="uploadThreads" :min="1" :max="100" :disabled="isRunning" @change="writeUploadThreads()"/> <el-input-number v-model="uploadThreads" :min="1" :max="100" :disabled="isRunning"
@change="writeUploadThreads()"/>
</div> </div>
<!-- <div class="form-item">--> <!-- <div class="form-item">-->
<!-- <el-checkbox v-model="autoStart" label="运行时自动启动上传" size="large" :disabled="isRunning" @change="writeAutoStart()"/>--> <!-- <el-checkbox v-model="autoStart" label="运行时自动启动上传" size="large" :disabled="isRunning" @change="writeAutoStart()"/>-->
<!-- </div>--> <!-- </div>-->
<div class="form-item"> <div class="form-item">
<label>上传进度</label> <label>上传进度</label>
@@ -205,6 +223,11 @@ EventsOn("log", (msg) => {
</div> </div>
</div> </div>
</div> </div>
<ConfirmClearDialog
v-model:visible="clearDialogVisible"
:file-list="filesToClear"
/>
</template> </template>
<style scoped> <style scoped>
@@ -0,0 +1,124 @@
<script lang="ts" setup>
import {ref} from 'vue'
import {WriteConfig} from "../../wailsjs/go/main/App";
import {configModel} from "@/model.ts";
import {EventsEmit} from "../../wailsjs/runtime";
import {InfoFilled} from '@element-plus/icons-vue'
const props = defineProps<{
visible: boolean
fileList: string[]
}>()
const emit = defineEmits<{
(e: 'update:visible', value: boolean): void
// (e: 'confirm', dontShowAgain: boolean): void
}>()
const dontShowAgain = ref(false)
const handleClose = () => {
emit('update:visible', false)
EventsEmit('confirm-clear-files', false)
}
const handleConfirm = () => {
// emit('confirm', dontShowAgain.value)
emit('update:visible', false)
WriteConfig(configModel.ClearFilesNoPrompt, dontShowAgain.value)
EventsEmit('confirm-clear-files', true)
}
</script>
<template>
<el-dialog
:model-value="visible"
width="600px"
:close-on-click-modal="false"
@update:model-value="(val: boolean) => emit('update:visible', val)"
@close="handleClose"
align-center
>
<template #header>
是否确认清空上传文件
</template>
<div class="hint-text">以下文件将会被清空并移动到tmp文件夹进行上传,您是否确认</div>
<div class="dialog-content">
<div class="file-list">
<div v-for="(file, index) in fileList" :key="index" class="file-item">
{{ file }}
</div>
<div v-if="fileList.length === 0" class="empty-text">暂无文件</div>
</div>
</div>
<template #footer>
<div class="dialog-footer">
<div class="dialog-footer-checkbox-container">
<el-checkbox v-model="dontShowAgain" label="下次清空文件不再弹出此弹窗确认"/>
<el-tooltip content="此弹窗会在首次运行时弹出您可以选择下次不再弹出此弹窗">
<el-icon>
<InfoFilled/>
</el-icon>
</el-tooltip>
</div>
<div>
<el-button @click="handleClose">取消</el-button>
<el-button type="primary" @click="handleConfirm">确认</el-button>
</div>
</div>
</template>
</el-dialog>
</template>
<style scoped>
.dialog-footer-checkbox-container {
display: flex;
align-items: center;
gap: 5px;
}
.dialog-footer-checkbox-container .el-icon {
color: #909399;
}
.dialog-content {
padding: 10px 0;
}
.hint-text {
font-size: 12px;
color: #909399;
}
.file-list {
max-height: 350px;
overflow-y: auto;
border: 1px solid #e4e7ed;
border-radius: 4px;
padding: 8px;
}
.file-item {
padding: 6px 8px;
font-size: 14px;
color: #606266;
border-bottom: 1px solid #f0f0f0;
}
.file-item:last-child {
border-bottom: none;
}
.empty-text {
text-align: center;
color: #909399;
padding: 20px 0;
}
.dialog-footer {
display: flex;
justify-content: space-between;
align-items: center;
}
</style>
+9
View File
@@ -0,0 +1,9 @@
export enum configModel {
Url = "url",
Token = "token",
ThreadCount = "thread-count",
HandleFileCount = "handle-file-count",
IsRunOnStart = "is-run-on-start",
CheckDir = "check-dir",
ClearFilesNoPrompt = "clear-files-no-prompt",
}
+2
View File
@@ -7,6 +7,7 @@ export namespace config {
handle_file_count: number; handle_file_count: number;
is_run_on_start: boolean; is_run_on_start: boolean;
check_dir: string; check_dir: string;
clear_files_no_prompt: boolean;
static createFrom(source: any = {}) { static createFrom(source: any = {}) {
return new Config(source); return new Config(source);
@@ -20,6 +21,7 @@ export namespace config {
this.handle_file_count = source["handle_file_count"]; this.handle_file_count = source["handle_file_count"];
this.is_run_on_start = source["is_run_on_start"]; this.is_run_on_start = source["is_run_on_start"];
this.check_dir = source["check_dir"]; this.check_dir = source["check_dir"];
this.clear_files_no_prompt = source["clear_files_no_prompt"];
} }
} }