构建上传工具 / build (push) Successful in 2m34s
- 在用户选择目录后调用 writeCheckDir() 方法保存配置 - 确保选中的目录路径能够正确写入到配置文件中
355 lines
8.4 KiB
Vue
355 lines
8.4 KiB
Vue
<script lang="ts" setup>
|
|
import {computed, nextTick, ref} from 'vue'
|
|
import {ElMessage, ElMessageBox} from 'element-plus'
|
|
import ConfirmClearDialog from './components/ConfirmClearDialog.vue'
|
|
import {GetConfig, SelectPath, StartUpload, StopUpload, WriteConfig} from '../wailsjs/go/main/App';
|
|
import {config} from "../wailsjs/go/models.ts";
|
|
import {EventsOn, LogPrint} from "../wailsjs/runtime";
|
|
import {configModel} from "@/model.ts";
|
|
import Config = config.Config;
|
|
|
|
// const serverUrl = ref('')
|
|
const token = ref('')
|
|
const checkDir = ref('')
|
|
const concurrentFiles = ref(1)
|
|
const uploadThreads = ref(1)
|
|
// const autoStart = ref(false)
|
|
|
|
const isRunning = ref(false)
|
|
const logOutput = ref<string[]>([])
|
|
const logContentRef = ref<HTMLElement>()
|
|
const logRoll = ref(true)
|
|
|
|
const clearDialogVisible = ref(false)
|
|
const filesToClear = ref<string[]>([])
|
|
const noPromptClear = ref(false)
|
|
|
|
interface FileProgress {
|
|
name: string
|
|
uploaded: number
|
|
total: number
|
|
percentage: number
|
|
}
|
|
|
|
// {name: '测试文件1.txt', uploaded: 100, total: 500, percentage: 20},
|
|
const progressList = ref<FileProgress[]>([])
|
|
|
|
const sortedProgressList = computed(() => {
|
|
return [...progressList.value].sort((a, b) => {
|
|
const getPriority = (item: FileProgress) => {
|
|
if (item.percentage === 100) return 2
|
|
if (item.percentage === 0) return 1
|
|
return 0
|
|
}
|
|
return getPriority(a) - getPriority(b)
|
|
})
|
|
})
|
|
|
|
const addLog = (msg: string) => {
|
|
logOutput.value.push(`[${new Date().toLocaleString()}] ` + msg)
|
|
nextTick(() => {
|
|
if (logContentRef.value && logRoll.value) {
|
|
logContentRef.value.scrollTop = logContentRef.value.scrollHeight
|
|
}
|
|
})
|
|
}
|
|
|
|
const selectDirectory = () => {
|
|
// ElMessage.info('请手动输入检测目录路径')
|
|
SelectPath().then((path) => {
|
|
if (path) {
|
|
checkDir.value = path
|
|
writeCheckDir()
|
|
} else {
|
|
ElMessage.warning('未选择目录,不更改配置')
|
|
}
|
|
})
|
|
}
|
|
|
|
const startRun = () => {
|
|
// if (!serverUrl.value) {
|
|
// ElMessage.warning('请输入服务器地址')
|
|
// return
|
|
// }
|
|
if (!token.value) {
|
|
ElMessage.error('请输入Token')
|
|
return
|
|
}
|
|
if (!checkDir.value) {
|
|
ElMessage.error('请选择检测目录')
|
|
return
|
|
}
|
|
|
|
StartUpload()
|
|
}
|
|
|
|
const stopRun = () => {
|
|
addLog(`正在停止运行`)
|
|
StopUpload().then(() => {
|
|
ElMessage.success('已停止运行')
|
|
})
|
|
}
|
|
|
|
const clearLog = () => {
|
|
ElMessageBox.confirm('确定要清除日志吗?', '提示', {
|
|
confirmButtonText: '确定',
|
|
cancelButtonText: '取消',
|
|
type: 'warning'
|
|
}).then(() => {
|
|
logOutput.value = []
|
|
ElMessage.success('日志已清除')
|
|
}).catch(() => {
|
|
})
|
|
}
|
|
|
|
// const writeServerUrl =() => {
|
|
// WriteConfig("url", serverUrl.value)
|
|
// }
|
|
const writeToken = () => {
|
|
WriteConfig(configModel.Token, token.value)
|
|
}
|
|
const writeCheckDir = () => {
|
|
WriteConfig(configModel.CheckDir, checkDir.value)
|
|
}
|
|
const writeConcurrentFiles = () => {
|
|
WriteConfig(configModel.HandleFileCount, concurrentFiles.value)
|
|
}
|
|
const writeUploadThreads = () => {
|
|
WriteConfig(configModel.ThreadCount, uploadThreads.value)
|
|
}
|
|
// const writeAutoStart = () => {
|
|
// WriteConfig("is-run-on-start", autoStart.value)
|
|
// }
|
|
|
|
// 加载配置
|
|
try {
|
|
GetConfig().then((config: Config) => {
|
|
// serverUrl.value = config.url
|
|
token.value = config.token
|
|
checkDir.value = config.check_dir
|
|
concurrentFiles.value = config.handle_file_count
|
|
uploadThreads.value = config.thread_count
|
|
// autoStart.value = config.is_run_on_start
|
|
noPromptClear.value = config.clear_files_no_prompt
|
|
|
|
LogPrint(`[${new Date().toLocaleString()}] 配置已加载`)
|
|
})
|
|
} catch (e) {
|
|
console.log(e)
|
|
}
|
|
|
|
try {
|
|
EventsOn("is-run", (run) => {
|
|
isRunning.value = run
|
|
})
|
|
EventsOn("progress", (progress) => {
|
|
progressList.value = progress
|
|
})
|
|
EventsOn("log", (msg) => {
|
|
addLog(msg)
|
|
})
|
|
EventsOn("clear-files", (files) => {
|
|
filesToClear.value = files
|
|
if (!noPromptClear.value) {
|
|
clearDialogVisible.value = true
|
|
}
|
|
})
|
|
} catch (e) {
|
|
console.log(e)
|
|
}
|
|
</script>
|
|
|
|
<template>
|
|
<div class="container">
|
|
<div class="left-panel">
|
|
<!-- <div class="form-item">-->
|
|
<!-- <label>服务器地址</label>-->
|
|
<!-- <el-input v-model="serverUrl" placeholder="请输入服务器地址" :disabled="isRunning" @change="writeServerUrl()"/>-->
|
|
<!-- </div>-->
|
|
|
|
<div class="form-item">
|
|
<label>Token</label>
|
|
<el-input v-model="token" placeholder="请输入Token" :disabled="isRunning" @change="writeToken()"/>
|
|
</div>
|
|
|
|
<div class="form-item">
|
|
<label>检测目录</label>
|
|
<div class="dir-input">
|
|
<el-input v-model="checkDir" placeholder="请选择检测目录" :disabled="isRunning" @change="writeCheckDir()"/>
|
|
<el-button @click="selectDirectory" :disabled="isRunning">选择目录</el-button>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="form-item">
|
|
<label>同时处理文件数</label>
|
|
<el-input-number v-model="concurrentFiles" :min="1" :max="100" :disabled="isRunning"
|
|
@change="writeConcurrentFiles()"/>
|
|
</div>
|
|
|
|
<div class="form-item">
|
|
<label>单文件上传线程</label>
|
|
<el-input-number v-model="uploadThreads" :min="1" :max="100" :disabled="isRunning"
|
|
@change="writeUploadThreads()"/>
|
|
</div>
|
|
|
|
<!-- <div class="form-item">-->
|
|
<!-- <el-checkbox v-model="autoStart" label="运行时自动启动上传" size="large" :disabled="isRunning" @change="writeAutoStart()"/>-->
|
|
<!-- </div>-->
|
|
|
|
<div class="form-item">
|
|
<label>上传进度</label>
|
|
<div class="progress-list">
|
|
<div v-for="(item, index) in sortedProgressList" :key="index" class="progress-item">
|
|
<span class="file-name">{{ item.name }}</span>
|
|
<el-progress :percentage="item.percentage" :status="item.percentage === 100 ? 'success' : undefined"/>
|
|
<span class="progress-text">{{ item.uploaded }}/{{ item.total }}</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="buttons">
|
|
<el-button type="primary" @click="startRun" :disabled="isRunning">开始运行</el-button>
|
|
<el-button type="danger" @click="stopRun" :disabled="!isRunning">停止运行</el-button>
|
|
<el-button @click="clearLog">清除日志</el-button>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="right-panel">
|
|
<div class="log-header">
|
|
日志输出
|
|
<el-checkbox v-model="logRoll" label="开启日志滚动"/>
|
|
</div>
|
|
<div class="log-content" ref="logContentRef">
|
|
<div v-for="(log, index) in logOutput" :key="index" class="log-line">{{ log }}</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<ConfirmClearDialog
|
|
v-model:visible="clearDialogVisible"
|
|
:file-list="filesToClear"
|
|
/>
|
|
</template>
|
|
|
|
<style scoped>
|
|
.container {
|
|
display: flex;
|
|
height: calc(100vh - 40px);
|
|
padding: 20px;
|
|
gap: 20px;
|
|
background-color: #f5f5f5;
|
|
}
|
|
|
|
.left-panel {
|
|
width: 350px;
|
|
min-width: 300px;
|
|
background: white;
|
|
padding: 20px;
|
|
border-radius: 8px;
|
|
display: flex;
|
|
flex-direction: column;
|
|
gap: 16px;
|
|
}
|
|
|
|
.form-item {
|
|
display: flex;
|
|
flex-direction: column;
|
|
}
|
|
|
|
.form-item label {
|
|
font-size: 14px;
|
|
color: #606266;
|
|
font-weight: 500;
|
|
}
|
|
|
|
.dir-input {
|
|
display: flex;
|
|
gap: 8px;
|
|
}
|
|
|
|
.dir-input .el-input {
|
|
flex: 1;
|
|
}
|
|
|
|
.buttons {
|
|
display: flex;
|
|
gap: 10px;
|
|
flex-wrap: wrap;
|
|
margin-top: 10px;
|
|
}
|
|
|
|
.progress-list {
|
|
margin-top: 12px;
|
|
max-height: 250px;
|
|
overflow-y: auto;
|
|
display: flex;
|
|
flex-direction: column;
|
|
gap: 10px;
|
|
}
|
|
|
|
.progress-item {
|
|
display: flex;
|
|
align-items: center;
|
|
}
|
|
|
|
.file-name {
|
|
width: 130px;
|
|
font-size: 12px;
|
|
color: #606266;
|
|
overflow: hidden;
|
|
text-overflow: ellipsis;
|
|
white-space: nowrap;
|
|
}
|
|
|
|
.progress-item .el-progress {
|
|
margin-left: 8px;
|
|
flex: 1;
|
|
}
|
|
|
|
.progress-text {
|
|
width: 75px;
|
|
font-size: 12px;
|
|
color: #909399;
|
|
text-align: right;
|
|
}
|
|
|
|
.right-panel {
|
|
flex: 1;
|
|
background: white;
|
|
border-radius: 8px;
|
|
display: flex;
|
|
flex-direction: column;
|
|
overflow: hidden;
|
|
}
|
|
|
|
.log-header {
|
|
padding: 12px 20px;
|
|
border-bottom: 1px solid #e4e7ed;
|
|
font-size: 14px;
|
|
font-weight: 500;
|
|
color: #303133;
|
|
display: flex;
|
|
justify-content: space-between;
|
|
align-items: center;
|
|
}
|
|
|
|
.log-content {
|
|
flex: 1;
|
|
padding: 5px 5px;
|
|
overflow-x: auto;
|
|
overflow-y: auto;
|
|
background: #1e1e1e;
|
|
font-family: Consolas, Monaco, 'Courier New', monospace;
|
|
font-size: 12px;
|
|
}
|
|
|
|
.log-line {
|
|
color: #dcdfe4;
|
|
line-height: 1.4;
|
|
white-space: nowrap;
|
|
}
|
|
|
|
.log-line:hover {
|
|
background: #2d2d2d;
|
|
}
|
|
</style> |