| 
									
										
										
										
											2025-03-24 17:34:52 +08:00
										 |  |  |  | <!DOCTYPE html> | 
					
						
							|  |  |  |  | <html lang="zh-CN"> | 
					
						
							|  |  |  |  |   <head> | 
					
						
							|  |  |  |  |     <meta charset="UTF-8" /> | 
					
						
							|  |  |  |  |     <meta name="viewport" content="width=device-width, initial-scale=1.0" /> | 
					
						
							|  |  |  |  |     <title>文件上传管理系统</title> | 
					
						
							| 
									
										
										
										
											2025-03-25 18:27:39 +08:00
										 |  |  |  |     <link rel="stylesheet" href="./index.css" /> | 
					
						
							| 
									
										
										
										
											2025-03-24 17:34:52 +08:00
										 |  |  |  |     <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> | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |         <!-- 右侧上传面板 --> | 
					
						
							| 
									
										
										
										
											2025-03-25 18:27:39 +08:00
										 |  |  |  |         <div v-loading="uploadLoading" class="right-panel"> | 
					
						
							| 
									
										
										
										
											2025-03-24 17:34:52 +08:00
										 |  |  |  |           <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" | 
					
						
							| 
									
										
										
										
											2025-03-25 18:27:39 +08:00
										 |  |  |  |             :loading="uploadLoading" | 
					
						
							| 
									
										
										
										
											2025-03-24 17:34:52 +08:00
										 |  |  |  |           > | 
					
						
							|  |  |  |  |             确认上传 | 
					
						
							|  |  |  |  |           </el-button> | 
					
						
							|  |  |  |  |         </div> | 
					
						
							|  |  |  |  |       </div> | 
					
						
							|  |  |  |  |     </div> | 
					
						
							|  |  |  |  |   </body> | 
					
						
							| 
									
										
										
										
											2025-03-25 18:27:39 +08:00
										 |  |  |  |   <script src="./vue.global.js"></script> | 
					
						
							|  |  |  |  |   <script src="./index.full.js"></script> | 
					
						
							| 
									
										
										
										
											2025-03-24 17:34:52 +08:00
										 |  |  |  | 
 | 
					
						
							|  |  |  |  |   <script> | 
					
						
							|  |  |  |  |     const { createApp } = Vue; | 
					
						
							|  |  |  |  |     const app = createApp({ | 
					
						
							|  |  |  |  |       data() { | 
					
						
							|  |  |  |  |         return { | 
					
						
							|  |  |  |  |           baseUrl: "http://192.168.110.3:9099", | 
					
						
							|  |  |  |  |           themeOptions: [], | 
					
						
							|  |  |  |  |           selectedTheme: "", | 
					
						
							|  |  |  |  |           currentList: [], | 
					
						
							|  |  |  |  |           userIds: [], | 
					
						
							|  |  |  |  |           loading: false, | 
					
						
							| 
									
										
										
										
											2025-03-25 18:27:39 +08:00
										 |  |  |  |           uploadLoading: false, | 
					
						
							| 
									
										
										
										
											2025-03-24 17:34:52 +08:00
										 |  |  |  |           listStatusText: "请先选择主题", | 
					
						
							| 
									
										
										
										
											2025-03-25 10:26:59 +08:00
										 |  |  |  |           userId: "", | 
					
						
							| 
									
										
										
										
											2025-03-24 17:34:52 +08:00
										 |  |  |  |           checkAll: false, | 
					
						
							|  |  |  |  |           isIndeterminate: false, | 
					
						
							|  |  |  |  |           uploadFile: null, | 
					
						
							|  |  |  |  |         }; | 
					
						
							|  |  |  |  |       }, | 
					
						
							|  |  |  |  |       mounted() { | 
					
						
							| 
									
										
										
										
											2025-03-25 10:26:59 +08:00
										 |  |  |  |         const protocol = window.location.protocol; | 
					
						
							|  |  |  |  |         const host = window.location.host; | 
					
						
							|  |  |  |  |         this.baseUrl = `${protocol}//${host}`; // 动态获取基础 URL | 
					
						
							|  |  |  |  |         // 获取 URL 中的 userId 参数 | 
					
						
							|  |  |  |  |         const urlParams = new URLSearchParams(window.location.search); | 
					
						
							|  |  |  |  |         this.userId = urlParams.get("userId"); | 
					
						
							| 
									
										
										
										
											2025-03-25 18:27:39 +08:00
										 |  |  |  |         // console.log("userId", this.userId); | 
					
						
							| 
									
										
										
										
											2025-03-25 10:26:59 +08:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-03-24 17:34:52 +08:00
										 |  |  |  |         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; | 
					
						
							| 
									
										
										
										
											2025-03-25 18:27:39 +08:00
										 |  |  |  |           if (this.themeOptions && this.themeOptions.length == 0) { | 
					
						
							|  |  |  |  |             ElementPlus.ElMessage.error(`请先选择招工主题`); | 
					
						
							|  |  |  |  |             return; | 
					
						
							|  |  |  |  |           } | 
					
						
							| 
									
										
										
										
											2025-03-24 17:34:52 +08:00
										 |  |  |  |           const formData = new FormData(); | 
					
						
							|  |  |  |  |           formData.append("file", this.uploadFile); | 
					
						
							|  |  |  |  |           formData.append("recruitId", this.selectedTheme); | 
					
						
							|  |  |  |  |           formData.append("userId", this.userId); | 
					
						
							| 
									
										
										
										
											2025-03-25 18:27:39 +08:00
										 |  |  |  |           this.uploadLoading = true; | 
					
						
							| 
									
										
										
										
											2025-03-24 17:34:52 +08:00
										 |  |  |  |           try { | 
					
						
							| 
									
										
										
										
											2025-03-25 10:26:59 +08:00
										 |  |  |  |             const res = await this.ajaxRequest({ | 
					
						
							| 
									
										
										
										
											2025-03-24 17:34:52 +08:00
										 |  |  |  |               url: "/ruoyi/upload-zip", | 
					
						
							|  |  |  |  |               method: "POST", | 
					
						
							|  |  |  |  |               body: formData, | 
					
						
							|  |  |  |  |             }); | 
					
						
							|  |  |  |  |             this.$refs.uploadRef.clearFiles(); | 
					
						
							|  |  |  |  |             this.uploadFile = null; | 
					
						
							| 
									
										
										
										
											2025-03-25 10:26:59 +08:00
										 |  |  |  |             if (res.code == 200) { | 
					
						
							|  |  |  |  |               ElementPlus.ElMessage.success("上传成功"); | 
					
						
							|  |  |  |  |             } else { | 
					
						
							|  |  |  |  |               ElementPlus.ElMessage.error(`${res.msg}`); | 
					
						
							|  |  |  |  |             } | 
					
						
							| 
									
										
										
										
											2025-03-24 17:34:52 +08:00
										 |  |  |  |           } catch (error) { | 
					
						
							| 
									
										
										
										
											2025-03-25 10:26:59 +08:00
										 |  |  |  |             ElementPlus.ElMessage.error(`${error}`); | 
					
						
							| 
									
										
										
										
											2025-03-25 18:27:39 +08:00
										 |  |  |  |           } finally { | 
					
						
							|  |  |  |  |             this.uploadLoading = false; | 
					
						
							| 
									
										
										
										
											2025-03-24 17:34:52 +08:00
										 |  |  |  |           } | 
					
						
							|  |  |  |  |         }, | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |         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> |