zhangjq
2026-02-07 81846734e6ee1bf7da9acbbd5871e277b8a0ccd0
src/views/copywritingUp/BatchPublish.vue
@@ -207,22 +207,16 @@
  // 批量发稿
  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('未登录,请先登录系统');
@@ -230,63 +224,34 @@
        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 {
@@ -303,37 +268,31 @@
          }
        };
        
        // 监听网络错误
        // 网络错误处理
        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 = [
          {
@@ -352,7 +311,7 @@
      } else {
        // 处理失败响应
        showResult.value = false; // 失败时不显示结果
        createMessage.error(responseData?.message || responseData?.msg || '批量发稿失败');
        createMessage.error(data?.message || data?.msg || '批量发稿失败');
      }
      
    } catch (error: any) {
@@ -380,6 +339,11 @@
    console.log('选择的合同ID:', value);
  };
  
  // 过滤选项
  const filterOption = (input: string, option: any) => {
    return (option?.label || '').toLowerCase().includes(input.toLowerCase());
  };
  // 页面加载时初始化
  onMounted(async () => {
    // 加载合同列表