Files
platform/ruoyi/uploadPath/appResource/html/upload.html
2025-03-24 17:34:52 +08:00

333 lines
9.5 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>文件上传管理系统</title>
<link
rel="stylesheet"
href="https://unpkg.com/element-plus/dist/index.css"
/>
<style>
.container {
display: flex;
height: 100vh;
padding: 20px;
box-sizing: border-box;
gap: 20px;
}
.left-panel {
width: 300px;
padding: 20px;
border-right: 1px solid #ebeef5;
overflow-y: auto;
}
.right-panel {
flex: 1;
padding: 20px;
}
.checkbox-group {
display: flex;
flex-direction: column;
gap: 12px;
margin-top: 15px;
}
.action-bar {
display: flex;
justify-content: space-between;
margin: 20px 0;
}
/* 拖拽上传区域样式 */
.upload-area {
height: 300px;
border: 2px dashed #dcdfe6;
border-radius: 6px;
background-color: #f5f7fa;
margin-bottom: 20px;
}
.upload-area .el-upload {
width: 100% !important;
height: 100% !important;
display: flex;
align-items: center;
justify-content: center;
}
.upload-area:hover {
border-color: #409eff;
}
.submit-btn {
width: 100%;
margin-top: 10px;
}
</style>
</head>
<body>
<div id="app">
<div class="container">
<!-- 左侧选择面板 -->
<div class="left-panel">
<h3>选择主题</h3>
<el-select
v-model="selectedTheme"
placeholder="请选择主题"
@change="handleThemeChange"
style="width: 100%; margin-bottom: 20px"
>
<el-option
v-for="item in themeOptions"
:key="item.value"
:label="item.label"
:value="item.value"
/>
</el-select>
<div class="action-bar">
<el-checkbox
v-model="checkAll"
:indeterminate="isIndeterminate"
@change="handleCheckAllChange"
>
全选({{ userIds.length }}
</el-checkbox>
<el-button
type="primary"
@click="downloadTemplateFile"
size="small"
>
下载模板
</el-button>
</div>
<div v-loading="loading" class="checkbox-group">
<template v-if="currentList.length">
<el-checkbox
v-for="item in currentList"
:key="item.userId"
v-model="userIds"
:label="item.userId"
class="checkbox-item"
>
{{ item.username }}
</el-checkbox>
</template>
<div v-else class="el-upload__tip">{{ listStatusText }}</div>
</div>
</div>
<!-- 右侧上传面板 -->
<div class="right-panel">
<h3 style="margin-bottom: 15px">文件上传区域</h3>
<el-upload
ref="uploadRef"
class="upload-area"
drag
action="#"
:auto-upload="false"
:on-change="handleFileChange"
:limit="1"
:on-exceed="handleExceed"
:on-remove="handleFileRemove"
accept=".zip"
>
<div class="el-upload__text">
<i
class="el-icon-upload"
style="font-size: 40px; color: #409eff"
></i>
<div style="margin-top: 10px">
将文件拖到此处,或<em style="color: #409eff">点击上传</em>
</div>
</div>
</el-upload>
<el-button
type="primary"
class="submit-btn"
@click="submitUpload"
:disabled="!uploadFile"
>
确认上传
</el-button>
</div>
</div>
</div>
</body>
<script src="https://unpkg.com/vue@3/dist/vue.global.js"></script>
<script src="https://unpkg.com/element-plus/dist/index.full.js"></script>
<script>
const { createApp } = Vue;
const app = createApp({
data() {
return {
baseUrl: "http://192.168.110.3:9099",
themeOptions: [],
selectedTheme: "",
currentList: [],
userIds: [],
loading: false,
listStatusText: "请先选择主题",
userId: "1893247598219890699",
checkAll: false,
isIndeterminate: false,
uploadFile: null,
};
},
mounted() {
this.getRecruitList();
},
methods: {
// 初始化加载主题列表
async getRecruitList() {
this.loading = true;
try {
const response = await this.ajaxRequest({
url: `/ruoyi/app/bgt/recruit/htmlList?userId=${this.userId}`,
method: "GET",
});
this.themeOptions = response.data.map((item) => ({
value: item.id,
label: item.recruitName,
}));
// 自动选中第一个主题
if (this.themeOptions.length > 0) {
this.selectedTheme = this.themeOptions[0].value;
this.handleThemeChange(this.selectedTheme);
}
} finally {
this.loading = false;
}
},
// 主题切换处理
async handleThemeChange(val) {
this.loading = true;
try {
const response = await this.ajaxRequest({
url: `/ruoyi/app/bgt/apply/htmlList?recruitId=${val}`,
method: "GET",
});
this.currentList = response.data;
this.userIds = [];
} finally {
this.loading = false;
}
},
// 文件超出限制处理
handleExceed(files) {
this.$refs.uploadRef.clearFiles();
const file = files[0];
file.uid = ElementPlus.genFileId();
this.$refs.uploadRef.handleStart(file);
this.uploadFile = file;
},
// 文件变化处理
handleFileChange(file) {
console.log("文件", file.raw?.type);
if (
file.raw?.type != "application/zip" &&
file.raw?.type != "application/x-zip-compressed"
) {
this.$refs.uploadRef.handleRemove(file);
ElementPlus.ElMessage.warning("仅支持ZIP格式文件");
return;
}
this.uploadFile = file.raw;
},
// 文件删除处理
handleFileRemove(file) {
this.uploadFile = null;
ElementPlus.ElMessage.success("文件已删除");
},
// 提交上传
async submitUpload() {
if (!this.uploadFile) return;
const formData = new FormData();
formData.append("file", this.uploadFile);
formData.append("recruitId", this.selectedTheme);
formData.append("userId", this.userId);
try {
await this.ajaxRequest({
url: "/ruoyi/upload-zip",
method: "POST",
body: formData,
});
this.$refs.uploadRef.clearFiles();
this.uploadFile = null;
ElementPlus.ElMessage.success("上传成功");
} catch (error) {
ElementPlus.ElMessage.error("上传失败");
}
},
handleCheckAllChange(val) {
this.userIds = val ? this.currentList.map((i) => i.userId) : [];
},
async downloadTemplateFile() {
try {
const response = await this.ajaxRequest({
url: "/ruoyi/download-folders",
method: "POST",
body: { recruitId: this.selectedTheme, userIds: this.userIds },
isDownload: true,
});
const temp = this.themeOptions.find(
(item) => item.value == this.selectedTheme
);
const link = document.createElement("a");
link.href = URL.createObjectURL(new Blob([response]));
link.setAttribute(
"download",
`${this.selectedTheme}_${temp.label}.zip`
); // 设置文件名
link.click();
} catch (error) {
ElementPlus.ElMessage.error("下载失败");
}
},
async ajaxRequest(options) {
const config = {
method: options.method,
headers: options.headers || {},
};
if (options.body) {
if (options.body instanceof FormData) {
config.body = options.body;
} else {
config.headers["Content-Type"] = "application/json";
config.body = JSON.stringify(options.body);
}
}
const response = await fetch(this.baseUrl + options.url, config);
if (!response.ok) throw new Error(response.statusText);
return options.isDownload ? response.arrayBuffer() : response.json();
},
},
watch: {
userIds(newVal) {
const total = this.currentList.length;
this.checkAll = newVal.length === total && total > 0;
this.isIndeterminate = newVal.length > 0 && newVal.length < total;
},
},
});
app.use(ElementPlus);
app.mount("#app");
</script>
</html>