Files
platform/ruoyi/uploadPath/appResource/html/upload.html
2025-04-30 09:21:00 +08:00

522 lines
16 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="./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;
}
.checkbox-item {
display: flex;
width: 100%; /* 确保宽度占满父容器 */
}
.el-checkbox__label {
display: flex;
align-items: center; /* 垂直居中 */
justify-content: space-between;
width: 100%; /* 确保宽度占满父容器 */
}
/* 添加状态颜色样式 */
.status-text.not-uploaded {
color: rgb(255, 0, 0);
}
.status-text.partially-uploaded {
color: rgb(255, 225, 7);
}
.status-text.uploaded {
color: rgb(8, 224, 8);
}
.status-text {
color: #999;
}
.action-bar {
display: flex;
justify-content: space-between;
margin: 2px 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;
}
.el-table--border {
margin: 10px 0;
}
.el-table .cell {
white-space: nowrap;
}
</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-checkbox
v-model="isFilter"
:disabled="isFilterDisabled"
@change="handleFilterChange"
>
筛选未上传的人员列表
</el-checkbox>
</div>
<div class="action-bar">
<div></div>
<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"
>
<span>{{ item.username }}</span>
<!-- 添加状态显示 -->
<span
:class="['status-text', getUploadStatusClass(item.uploadType)]"
>
{{ getUploadStatus(item.uploadType) }}
<el-button
v-if="item.uploadType == '2'||item.uploadType == '1'"
type="primary"
@click="checkoutDetail(item)"
size="small"
>
查看
</el-button>
</span>
</el-checkbox>
</template>
<div v-else class="el-upload__tip">{{ listStatusText }}</div>
</div>
</div>
<!-- 右侧上传面板 -->
<div v-loading="uploadLoading" 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"
:loading="uploadLoading"
>
确认上传
</el-button>
<div style="background-color: #f5f7fa; border-radius: 4px">
<h4 style="margin: 0 0 10px 0; color: #409eff">操作流程:</h4>
<ol style="margin: 0; padding-left: 20px">
<li>选择主题</li>
<li>勾选需要上传文件的人员</li>
<li>点击"下载模板"按钮</li>
<li>解压下载的模板文件</li>
<li>将图片或PDF文件放入相应人员的文件夹中</li>
<li>压缩文件夹并上传</li>
</ol>
<h4 style="margin: 15px 0 10px 0; color: #f56c6c">注意事项:</h4>
<ul style="margin: 0; padding-left: 20px">
<li>请确保压缩文件为.zip格式</li>
<li>压缩层级与下载模板保持一致</li>
<li>每个人员的文件请放入对应的文件夹中</li>
</ul>
</div>
</div>
</div>
<!-- 查看详情弹窗 -->
<el-dialog v-model="dialogVisible" title="附件详情" width="80%">
<el-table :data="tableData" style="width: 100%">
<el-table-column prop="annexName" label="附件名称"></el-table-column>
<el-table-column prop="annexUrl" label="附件路径">
<template #default="scope"> {{ scope.row.annexUrl }} </template>
</el-table-column>
<el-table-column prop="annexType" width="120" label="附件类型">
<template #default="scope">
<span
>{{ scope.row.annexType == '1' ? "劳动合同" : "保单" }}</span
>
</template>
</el-table-column>
<!-- 如果需要更多字段,可继续添加 -->
</el-table>
</el-dialog>
</div>
</body>
<script src="./vue.global.js"></script>
<script src="./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,
uploadLoading: false,
listStatusText: "请先选择主题",
userId: "1893247598219890699",
checkAll: false,
isIndeterminate: false,
uploadFile: null,
isFilter: false,
dialogVisible: false,
detailLoading: false,
dialogData: {},
tableData: [],
};
},
computed: {
isListEmpty() {
return this.currentList.length === 0;
},
isFilterDisabled() {
// 仅在未选择主题或原始列表为空时禁用
return (
!this.selectedTheme ||
(this.currentList.length === 0 && !this.isFilter)
);
},
},
mounted() {
const protocol = window.location.protocol;
const host = window.location.host;
// this.baseUrl = `${protocol}//${host}/lhyg`; // 动态获取基础 URL
// 获取 URL 中的 userId 参数
const urlParams = new URLSearchParams(window.location.search);
this.userId = urlParams.get("userId");
console.log("userId", this.userId);
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}&isNotUpload=${this.isFilter}`,
method: "GET",
});
this.currentList = response.data;
this.userIds = [];
} finally {
this.loading = false;
}
},
// 筛选未上传文件的人员列表
async handleFilterChange() {
// if (this.isListEmpty) {
// // 新增空列表判断
// this.isFilter = false;
// return;
// }
this.loading = true;
try {
const response = await this.ajaxRequest({
url: `/ruoyi/app/bgt/apply/htmlList?recruitId=${this.selectedTheme}&isNotUpload=${this.isFilter}`,
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;
if (this.themeOptions && this.themeOptions.length == 0) {
ElementPlus.ElMessage.error(`请先选择招工主题`);
return;
}
const formData = new FormData();
formData.append("file", this.uploadFile);
formData.append("recruitId", this.selectedTheme);
formData.append("userId", this.userId);
this.uploadLoading = true;
try {
const res = await this.ajaxRequest({
url: "/ruoyi/upload-zip",
method: "POST",
body: formData,
});
this.$refs.uploadRef.clearFiles();
this.uploadFile = null;
if (res.code == 200) {
ElementPlus.ElMessage.success("上传成功");
} else {
ElementPlus.ElMessage.error(`${res.msg}`);
}
} catch (error) {
ElementPlus.ElMessage.error(`${error}`);
} finally {
this.uploadLoading = false;
}
},
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 checkoutDetail(item) {
console.log("点击详情", item);
try {
this.detailLoading = true;
const response = await this.ajaxRequest({
url: `/ruoyi/common/annex/getHtmlWgzAnnex?recruitApplyId=${item.id}&wgzUserId=${item.userId}`,
method: "GET",
});
// 转换数据结构
this.dialogData = response.data;
// 将后端返回的数据转换为适合表格展示的格式
this.tableData = Object.values(this.dialogData).flat();
this.dialogVisible = true;
console.log("获取详情数据", this.tableData);
} catch (error) {
ElementPlus.ElMessage.error("获取详情失败");
} finally {
this.detailLoading = false;
}
},
// 统一的 AJAX 请求方法
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();
},
// 根据uploadType返回状态文本
getUploadStatus(uploadType) {
switch (uploadType) {
case "0":
return "未上传";
case "1":
return "部分上传";
case "2":
return "已上传";
default:
return "未知状态";
}
},
// 根据uploadType返回状态样式类名
getUploadStatusClass(uploadType) {
switch (uploadType) {
case "0":
return "not-uploaded";
case "1":
return "partially-uploaded";
case "2":
return "uploaded";
default:
return "";
}
},
},
watch: {
userIds(newVal) {
const total = this.currentList.length;
this.checkAll = newVal.length === total && total > 0;
this.isIndeterminate = newVal.length > 0 && newVal.length < total;
},
// currentList(newVal) {
// if (newVal.length === 0) {
// this.isFilter = false;
// }
// },
},
});
app.use(ElementPlus);
app.mount("#app");
</script>
</html>