| | |
| | | |
| | | // 批量发稿 |
| | | const handleBatchPublish = async () => { |
| | | if (!formRef.value) return; |
| | | |
| | | try { |
| | | // 1. 表单验证 |
| | | await formRef.value.validate(); |
| | | if (!formState.contractId) { |
| | | createMessage.error('请选择合同'); |
| | | return; |
| | | } |
| | | |
| | | submitLoading.value = true; |
| | | |
| | | // 2. 构建请求参数 |
| | | const requestData = { |
| | | contractId: formState.contractId, |
| | | }; |
| | | |
| | | console.log('=== 批量发稿请求数据 ==='); |
| | | console.log('请求数据:', requestData); |
| | | |
| | | // 3. 获取登录 Token |
| | | // 2. 获取登录 Token |
| | | const token = getToken(); |
| | | if (!token) { |
| | | createMessage.error('未登录,请先登录系统'); |
| | |
| | | return; |
| | | } |
| | | |
| | | // 4. 生成时间戳和签名 |
| | | const timestamp = Date.now().toString(); |
| | | const sign = generateSign(token, timestamp, formState.contractId); |
| | | |
| | | // 5. 构建 FormData |
| | | // 3. 构建 FormData |
| | | const formData = new FormData(); |
| | | formData.append('contractId', formState.contractId); |
| | | if (formState.mediaGroups) { |
| | | // 将媒体列表字符串按逗号分割并添加到FormData中 |
| | | const mediaArray = formState.mediaGroups.split(',').map(item => item.trim()); |
| | | console.log('媒体数组:', mediaArray); |
| | | // 对于multipart/form-data格式,重复添加同名参数来传递数组 |
| | | mediaArray.forEach((media, index) => { |
| | | formData.append('mediaList', media); |
| | | console.log(`添加参数: mediaList = ${media}`); |
| | | }); |
| | | } |
| | | |
| | | // 6. 发送请求 - 参考批量导入的代码,使用 XMLHttpRequest 手动构建请求 |
| | | // 这样可以绕过拦截器,确保在不同环境下都能正常调用 |
| | | const domainUrl = import.meta.env.VITE_GLOB_DOMAIN_URL || 'http://192.168.31.222:8080/jeecg-boot'; |
| | | // 4. 发送请求 - 使用 XMLHttpRequest 发送 multipart/form-data 请求 |
| | | const domainUrl = 'http://192.168.31.222:8080/jeecg-boot'; |
| | | const url = `${domainUrl}/api/excel/batchPublish`; |
| | | |
| | | console.log('===== 手动构建 multipart/form-data 请求 ====='); |
| | | console.log('===== 发送 multipart/form-data 请求 ====='); |
| | | console.log('请求 URL:', url); |
| | | console.log('请求参数:', requestData); |
| | | console.log('合同ID:', formState.contractId); |
| | | console.log('媒体列表:', formState.mediaGroups); |
| | | |
| | | // 手动构建 multipart/form-data 请求 |
| | | // 发送请求 |
| | | const responseData = await new Promise((resolve, reject) => { |
| | | // 生成随机边界 |
| | | const boundary = '----WebKitFormBoundary' + Math.random().toString(36).substr(2, 16); |
| | | |
| | | // 构建请求体的各个部分 |
| | | const parts = []; |
| | | |
| | | // 添加 contractId 参数 |
| | | parts.push( |
| | | `--${boundary}\r\n`, |
| | | 'Content-Disposition: form-data; name="contractId"\r\n', |
| | | 'Content-Type: text/plain\r\n', |
| | | '\r\n', |
| | | formState.contractId, |
| | | '\r\n' |
| | | ); |
| | | |
| | | // 添加 mediaGroups 参数 |
| | | parts.push( |
| | | `--${boundary}\r\n`, |
| | | 'Content-Disposition: form-data; name="mediaGroups"\r\n', |
| | | 'Content-Type: text/plain\r\n', |
| | | '\r\n', |
| | | formState.mediaGroups, |
| | | '\r\n' |
| | | ); |
| | | |
| | | // 添加结束边界 |
| | | parts.push( |
| | | `--${boundary}--\r\n` |
| | | ); |
| | | |
| | | // 创建最终的请求体 Blob |
| | | const requestBody = new Blob(parts, { type: `multipart/form-data; boundary=${boundary}` }); |
| | | |
| | | // 创建 XMLHttpRequest |
| | | const xhr = new XMLHttpRequest(); |
| | | |
| | | // 监听请求完成 |
| | | // 响应处理 |
| | | xhr.onload = function() { |
| | | if (xhr.status >= 200 && xhr.status < 300) { |
| | | try { |
| | |
| | | } |
| | | }; |
| | | |
| | | // 监听网络错误 |
| | | // 网络错误处理 |
| | | xhr.onerror = function() { |
| | | console.error('网络错误'); |
| | | reject(new Error('网络错误')); |
| | | }; |
| | | |
| | | // 打开请求 |
| | | // 打开连接 |
| | | xhr.open('POST', url, true); |
| | | |
| | | // 设置请求头 - 参考批量导入的代码,确保包含所有必需的请求头 |
| | | xhr.setRequestHeader('Accept', 'application/json, text/plain, */*'); |
| | | xhr.setRequestHeader('Authorization', `Bearer ${token}`); |
| | | xhr.setRequestHeader('Referer', window.location.href); |
| | | // 设置请求头 |
| | | xhr.setRequestHeader('X-Access-Token', token); |
| | | xhr.setRequestHeader('X-Sign', sign); |
| | | xhr.setRequestHeader('X-TIMESTAMP', timestamp); |
| | | xhr.setRequestHeader('X-Tenant-Id', '0'); |
| | | xhr.setRequestHeader('X-Version', 'v3'); |
| | | // 手动设置正确的 Content-Type,包含边界 |
| | | xhr.setRequestHeader('Content-Type', `multipart/form-data; boundary=${boundary}`); |
| | | // 设置 Content-Length |
| | | xhr.setRequestHeader('Content-Length', requestBody.size.toString()); |
| | | xhr.setRequestHeader('Accept', 'application/json, text/plain, */*'); |
| | | // 注意:使用FormData时,浏览器会自动设置Content-Type头,包含正确的边界 |
| | | |
| | | // 发送请求 |
| | | xhr.send(requestBody); |
| | | xhr.send(formData); |
| | | }); |
| | | |
| | | console.log('后端响应数据:', responseData); |
| | | |
| | | // 7. 处理响应 |
| | | if (responseData && (responseData.success || responseData.code === 200 || responseData.code === 201)) { |
| | | // 4. 处理响应 |
| | | const data = responseData.data; |
| | | if (data && (data.success || data.code === 200 || data.code === 201)) { |
| | | // 处理成功响应 |
| | | publishResults.value = [ |
| | | { |
| | |
| | | } else { |
| | | // 处理失败响应 |
| | | showResult.value = false; // 失败时不显示结果 |
| | | createMessage.error(responseData?.message || responseData?.msg || '批量发稿失败'); |
| | | createMessage.error(data?.message || data?.msg || '批量发稿失败'); |
| | | } |
| | | |
| | | } catch (error: any) { |
| | |
| | | console.log('选择的合同ID:', value); |
| | | }; |
| | | |
| | | // 过滤选项 |
| | | const filterOption = (input: string, option: any) => { |
| | | return (option?.label || '').toLowerCase().includes(input.toLowerCase()); |
| | | }; |
| | | |
| | | // 页面加载时初始化 |
| | | onMounted(async () => { |
| | | // 加载合同列表 |