fix(环保门禁): 照片上传改为存相对路径(原绝对URL手机访问不到)、上传前自动压缩到1280px、错误提示按状态码细分(413/401/415)
已修改1个文件
72 ■■■■■ 文件已修改
src/views/environmentAccess/components/PhotoCapture.vue 72 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/environmentAccess/components/PhotoCapture.vue
@@ -50,6 +50,48 @@
  emit("update:modelValue", "");
};
/**
 * 上传前压缩图片:按最大宽度等比缩放 + JPEG 质量压缩
 * 手机原图 2-5MB → 通常 200-500KB,避免被 nginx 的 client_max_body_size 拦截
 */
const compressImage = (file, maxWidth = 1280, quality = 0.75) =>
  new Promise((resolve) => {
    // 非图片或环境不支持时直接返回原文件
    if (!/^image\//.test(file.type) || typeof document === "undefined") {
      resolve(file);
      return;
    }
    const objectUrl = URL.createObjectURL(file);
    const img = new Image();
    img.onload = () => {
      URL.revokeObjectURL(objectUrl);
      let width = img.naturalWidth || img.width;
      let height = img.naturalHeight || img.height;
      if (!width || !height) {
        resolve(file);
        return;
      }
      if (width > maxWidth) {
        height = Math.round((height * maxWidth) / width);
        width = maxWidth;
      }
      const canvas = document.createElement("canvas");
      canvas.width = width;
      canvas.height = height;
      canvas.getContext("2d").drawImage(img, 0, 0, width, height);
      canvas.toBlob(
        (blob) => resolve(blob || file),
        "image/jpeg",
        quality
      );
    };
    img.onerror = () => {
      URL.revokeObjectURL(objectUrl);
      resolve(file);
    };
    img.src = objectUrl;
  });
const onChange = async (e) => {
  const file = e.target.files && e.target.files[0];
  e.target.value = "";
@@ -64,8 +106,11 @@
  }
  loading.value = true;
  try {
    // 上传前先压缩:手机原图通常 2-5MB,压到 1280px 宽、质量 0.75 后一般 200-500KB
    // 既省手机流量,也避免被 nginx 的 client_max_body_size 拦住
    const compressed = await compressImage(file);
    const fd = new FormData();
    fd.append("file", file);
    fd.append("file", compressed, file.name || "photo.jpg");
    const res = await axios.post(import.meta.env.VITE_APP_BASE_API + "/common/upload", fd, {
      headers: {
        Authorization: "Bearer " + getToken(),
@@ -74,13 +119,34 @@
    });
    const body = res && res.data;
    if (body && body.code === 200) {
      emit("update:modelValue", body.url || body.fileName || "");
      // 只保留相对路径:后端返回的 url 带 host(如 http://10.136.58.73:7003/profile/...),
      // 手机经端口转发或外网访问时该 host 不通,必须用 /profile/... 相对路径
      let path = body.fileName || body.url || "";
      if (/^https?:\/\//i.test(path)) {
        try {
          path = new URL(path).pathname;
        } catch (e) {
          // 解析失败就保持原值
        }
      }
      emit("update:modelValue", path);
      ElMessage.success("上传成功");
    } else {
      ElMessage.error((body && body.msg) || "上传失败");
    }
  } catch (err) {
    ElMessage.error("上传失败,请检查网络后重试");
    const status = err && err.response ? err.response.status : 0;
    if (status === 413) {
      ElMessage.error("照片太大,上传被服务器拒绝,请压缩后重试");
    } else if (status === 401) {
      ElMessage.error("登录已过期,请重新登录后再上传");
    } else if (status === 415) {
      ElMessage.error("文件格式不支持,请选择图片文件");
    } else if (status) {
      ElMessage.error("上传失败(HTTP " + status + "),请重试");
    } else {
      ElMessage.error("上传失败,请检查网络后重试");
    }
  } finally {
    loading.value = false;
  }