liyong
8 天以前 18a6993750e192fb8af04ce407a72ba20d6024c5
Merge remote-tracking branch 'origin/dev_天津_阳光印刷' into dev_天津_阳光印刷
已添加1个文件
已修改17个文件
1516 ■■■■ 文件已修改
multiple/config.json 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/equipmentManagement/inspectionManagement/components/uploadFiles.vue 620 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/equipmentManagement/inspectionManagement/components/viewFiles.vue 8 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/equipmentManagement/inspectionManagement/index.vue 27 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/equipmentManagement/repair/Modal/RepairModal.vue 10 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/equipmentManagement/repair/index.vue 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/productionManagement/productionCosting/index.vue 15 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/productionManagement/productionOrder/BindRouteDialog.vue 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/productionManagement/productionReporting/index.vue 79 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/productionManagement/workOrder/index.vue 77 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/qualityManagement/finalInspection/components/formDia.vue 23 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/qualityManagement/finalInspection/index.vue 228 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/qualityManagement/processInspection/components/formDia.vue 23 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/qualityManagement/processInspection/index.vue 228 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/qualityManagement/rawMaterialInspection/components/formDia.vue 23 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/qualityManagement/rawMaterialInspection/index.vue 123 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/salesManagement/receiptPaymentLedger/index.vue 14 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
vite.config.js 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
multiple/config.json
@@ -20,7 +20,7 @@
  "YGYS": {
    "env": {
      "VITE_APP_TITLE": "阳光印刷信息管理",
      "VITE_BASE_API": "http://1.15.17.182:9022",
      "VITE_BASE_API": "http://1.15.17.182:9023",
      "VITE_JAVA_API": "http://1.15.17.182:9022"
    },
    "screen": "screen/login-background.png",
src/views/equipmentManagement/inspectionManagement/components/uploadFiles.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,620 @@
<template>
  <div>
    <el-dialog
      v-model="showUploadDialog"
      title="上传巡检记录"
      width="560px"
      :before-close="closeUploadDialog"
    >
      <el-tabs v-model="currentUploadType">
        <el-tab-pane label="生产前" name="before" />
        <el-tab-pane label="生产中" name="after" />
        <el-tab-pane label="生产后" name="issue" />
      </el-tabs>
      <div class="exception-section">
        <div class="section-title">是否存在异常?</div>
        <el-radio-group v-model="hasException">
          <el-radio :value="false">正常</el-radio>
          <el-radio :value="true">存在异常</el-radio>
        </el-radio-group>
      </div>
      <div class="upload-buttons">
        <el-upload
          ref="uploadRef"
          v-model:file-list="uploadFileList"
          :action="uploadUrl"
          :headers="uploadHeaders"
          :show-file-list="false"
          :accept="uploadAccept"
          :multiple="false"
          :before-upload="handleBeforeUpload"
          :on-success="handleUploadSuccess"
          :on-error="handleUploadError"
          :on-progress="handleUploadProgress"
          :disabled="uploading || getCurrentFiles().length >= uploadConfig.limit"
        >
          <el-button
            type="primary"
            :loading="uploading"
            :disabled="getCurrentFiles().length >= uploadConfig.limit"
          >
            é€‰æ‹©å›¾ç‰‡/视频
          </el-button>
        </el-upload>
      </div>
      <el-progress
        v-if="uploading"
        :percentage="uploadProgress"
        style="margin: 12px 0"
      />
      <div v-if="getCurrentFiles().length" class="file-list">
        <div
          v-for="(file, index) in getCurrentFiles()"
          :key="file.uid || file.id || index"
          class="file-item"
        >
          <div class="file-preview-container">
            <img
              v-if="isImageFile(file)"
              :src="file.url || file.downloadUrl"
              class="file-preview"
              @click="previewAttachment(file)"
            />
            <div
              v-else
              class="video-preview"
              @click="previewAttachment(file)"
            >
              è§†é¢‘
            </div>
            <button class="delete-btn" @click="removeFile(index)">x</button>
          </div>
          <div class="file-name">
            {{ file.bucketFilename || file.name || "附件" }}
          </div>
          <div class="file-size">
            {{ formatFileSize(file.size || file.byteSize) }}
          </div>
        </div>
      </div>
      <el-empty
        v-else
        :description="`请选择要上传的${getUploadTypeText()}图片或视频`"
      />
      <div class="upload-summary">
        ç”Ÿäº§å‰ï¼š{{ beforeModelValue.length }} ä¸ª |
        ç”Ÿäº§ä¸­ï¼š{{ afterModelValue.length }} ä¸ª |
        ç”Ÿäº§åŽï¼š{{ issueModelValue.length }} ä¸ª
      </div>
      <template #footer>
                <el-button type="primary" @click="submitUpload">提交</el-button>
        <el-button @click="closeUploadDialog">取消</el-button>
      </template>
    </el-dialog>
    <el-dialog
      v-model="showVideoDialog"
      :title="currentVideoFile?.originalFilename || '视频预览'"
      width="720px"
    >
      <video
        v-if="currentVideoFile"
        :src="currentVideoFile.url || currentVideoFile.downloadUrl"
        class="video-player"
        controls
        autoplay
      />
    </el-dialog>
  </div>
</template>
<script setup>
import { computed, ref } from "vue";
import { ElLoading, ElMessage, ElMessageBox } from "element-plus";
import { getToken } from "@/utils/auth";
import { uploadInspectionTask } from "@/api/inspectionManagement/index.js";
const emit = defineEmits(["closeDia", "success"]);
const showUploadDialog = ref(false);
const uploading = ref(false);
const uploadProgress = ref(0);
const uploadRef = ref(null);
const uploadFileList = ref([]);
const beforeModelValue = ref([]);
const afterModelValue = ref([]);
const issueModelValue = ref([]);
const currentUploadType = ref("before");
const hasException = ref(null);
const currentTask = ref(null);
const showVideoDialog = ref(false);
const currentVideoFile = ref(null);
const uploadConfig = {
  action: "/file/upload",
  limit: 10,
  fileSize: 50,
  fileType: ["jpg", "jpeg", "png", "gif", "webp", "mp4", "mov", "avi", "wmv"],
};
const uploadUrl = computed(() => {
  const type = getTabType();
  return `${import.meta.env.VITE_APP_BASE_API}${uploadConfig.action}?type=${type}`;
});
const uploadHeaders = {
  Authorization: `Bearer ${getToken()}`,
};
const uploadAccept = computed(() =>
  uploadConfig.fileType.map(item => `.${item}`).join(",")
);
const filePreviewBase = __BASE_API__;
const cloneData = value => JSON.parse(JSON.stringify(value || {}));
const normalizeFileUrl = rawUrl => {
  if (!rawUrl || typeof rawUrl !== "string") return "";
  let fileUrl = rawUrl.trim();
  if (!fileUrl) return "";
  if (/^https?:\/\//i.test(fileUrl)) return fileUrl;
  if (fileUrl.indexOf("\\") > -1) {
    const uploadsIndex = fileUrl.toLowerCase().indexOf("uploads");
    if (uploadsIndex > -1) {
      const relativePath = fileUrl.substring(uploadsIndex).replace(/\\/g, "/");
      fileUrl = `/${relativePath}`;
    } else {
      const parts = fileUrl.split("\\");
      const fileName = parts[parts.length - 1];
      fileUrl = `/uploads/${fileName}`;
    }
  }
  if (!fileUrl.startsWith("http")) {
    if (!fileUrl.startsWith("/")) {
      fileUrl = `/${fileUrl}`;
    }
    fileUrl = `${filePreviewBase}${fileUrl}`;
  }
  return fileUrl;
};
const mapExistingFile = (file, type) => ({
  ...file,
  id: file?.id,
  tempId: file?.tempId ?? file?.tempFileId ?? file?.id,
  tempFileId: file?.tempFileId ?? file?.id,
  url: normalizeFileUrl(file?.url || file?.downloadUrl || file?.fileUrl || ""),
  downloadUrl: normalizeFileUrl(
    file?.downloadUrl || file?.url || file?.fileUrl || ""
  ),
  bucketFilename:
    file?.bucketFilename || file?.originalFilename || file?.fileName || file?.name,
  originalFilename:
    file?.originalFilename || file?.bucketFilename || file?.fileName || file?.name,
  size: file?.size || file?.byteSize,
  byteSize: file?.byteSize || file?.size,
  contentType: file?.contentType || "",
  type,
  uid: file?.uid || `${type}-${file?.id || file?.url || Math.random()}`,
});
const resetDialogState = () => {
  beforeModelValue.value = [];
  afterModelValue.value = [];
  issueModelValue.value = [];
  currentUploadType.value = "before";
  hasException.value = null;
  currentTask.value = null;
  uploadProgress.value = 0;
  uploading.value = false;
  uploadFileList.value = [];
  uploadRef.value?.clearFiles?.();
};
const openDialog = task => {
  const rawTask = cloneData(task?.__raw || task);
  currentTask.value = {
    ...rawTask,
    taskId: rawTask.taskId || rawTask.id,
    storageBlobDTO: [],
  };
  beforeModelValue.value = Array.isArray(rawTask.commonFileListBefore)
    ? rawTask.commonFileListBefore.map(file => mapExistingFile(file, 10))
    : [];
  afterModelValue.value = Array.isArray(rawTask.commonFileListAfter)
    ? rawTask.commonFileListAfter.map(file => mapExistingFile(file, 11))
    : [];
  issueModelValue.value = Array.isArray(rawTask.commonFileList)
    ? rawTask.commonFileList.map(file => mapExistingFile(file, 12))
    : [];
  currentUploadType.value = "before";
  hasException.value =
    typeof rawTask.hasException === "boolean" ? rawTask.hasException : null;
  uploadFileList.value = [];
  showUploadDialog.value = true;
};
const closeUploadDialog = () => {
  showUploadDialog.value = false;
  resetDialogState();
  emit("closeDia");
};
const getCurrentFiles = () => {
  if (currentUploadType.value === "before") return beforeModelValue.value;
  if (currentUploadType.value === "after") return afterModelValue.value;
  return issueModelValue.value;
};
const getUploadTypeText = () => {
  if (currentUploadType.value === "before") return "生产前";
  if (currentUploadType.value === "after") return "生产中";
  return "生产后";
};
const getTabType = () => {
  if (currentUploadType.value === "before") return 10;
  if (currentUploadType.value === "after") return 11;
  return 12;
};
const handleBeforeUpload = file => {
  if (getCurrentFiles().length >= uploadConfig.limit) {
    ElMessage.warning(`最多只能选择${uploadConfig.limit}个文件`);
    return false;
  }
  const ext = file.name.split(".").pop()?.toLowerCase();
  if (!uploadConfig.fileType.includes(ext)) {
    ElMessage.warning(`文件格式不支持,请上传 ${uploadConfig.fileType.join("/")} æ ¼å¼`);
    return false;
  }
  const maxSize = uploadConfig.fileSize * 1024 * 1024;
  if (file.size > maxSize) {
    ElMessage.warning(`文件大小不能超过 ${uploadConfig.fileSize}MB`);
    return false;
  }
  uploading.value = true;
  uploadProgress.value = 0;
  return true;
};
const handleUploadProgress = event => {
  if (event?.percent) {
    uploadProgress.value = Math.round(event.percent);
  }
};
const handleUploadSuccess = (response, file) => {
  uploading.value = false;
  uploadProgress.value = 0;
  uploadFileList.value = [];
  uploadRef.value?.clearFiles?.();
  const uploadedFile = response?.data;
  if (response?.code !== 200 || !uploadedFile) {
    ElMessage.error(response?.msg || "上传响应数据格式错误");
    return;
  }
  const type = getTabType();
  const objectUrl = file?.raw ? URL.createObjectURL(file.raw) : "";
  const fileData = {
    id: uploadedFile.id,
    tempId: uploadedFile.tempId ?? uploadedFile.tempFileId ?? uploadedFile.id,
    tempFileId: uploadedFile.tempFileId ?? uploadedFile.id,
    url: normalizeFileUrl(uploadedFile.url || uploadedFile.downloadUrl || objectUrl),
    downloadUrl: normalizeFileUrl(
      uploadedFile.downloadUrl || uploadedFile.url || objectUrl
    ),
    bucketFilename:
      uploadedFile.bucketFilename || uploadedFile.originalFilename || file.name,
    originalFilename:
      uploadedFile.originalFilename || uploadedFile.bucketFilename || file.name,
    size: uploadedFile.size || uploadedFile.byteSize || file.size,
    byteSize: uploadedFile.byteSize || uploadedFile.size || file.size,
    createTime: uploadedFile.createTime || Date.now(),
    contentType: uploadedFile.contentType || file.raw?.type || "",
    type,
    uid: `${Date.now()}-${Math.random()}`,
  };
  if (currentUploadType.value === "before") {
    beforeModelValue.value.push(fileData);
  } else if (currentUploadType.value === "after") {
    afterModelValue.value.push(fileData);
  } else {
    issueModelValue.value.push(fileData);
  }
  ElMessage.success("上传成功");
};
const handleUploadError = error => {
  uploading.value = false;
  uploadProgress.value = 0;
  uploadFileList.value = [];
  uploadRef.value?.clearFiles?.();
  ElMessage.error(error?.message || "上传失败");
};
const removeFile = async index => {
  try {
    await ElMessageBox.confirm("确定要删除这个文件吗?", "确认删除", {
      type: "warning",
    });
    if (currentUploadType.value === "before") {
      beforeModelValue.value.splice(index, 1);
    } else if (currentUploadType.value === "after") {
      afterModelValue.value.splice(index, 1);
    } else {
      issueModelValue.value.splice(index, 1);
    }
    ElMessage.success("删除成功");
  } catch {}
};
const buildSubmitFiles = () => {
  const list = [
    ...beforeModelValue.value,
    ...afterModelValue.value,
    ...issueModelValue.value,
  ];
  return list.map(item => ({
    ...item,
    url: item?.downloadUrl || item?.url || "",
  }));
};
const buildSubmitFileItem = item => {
  if (!item) return null;
  return {
    id: item.id,
    tempId: item.tempId,
    tempFileId: item.tempFileId,
    type: item.type,
    url: item?.downloadUrl || item?.url || "",
    downloadUrl: item?.downloadUrl || item?.url || "",
    bucketFilename: item.bucketFilename,
    originalFilename: item.originalFilename,
    size: item.size,
    byteSize: item.byteSize,
    contentType: item.contentType,
  };
};
const buildGroupedFiles = list => {
  return (list || []).map(buildSubmitFileItem).filter(Boolean);
};
const buildSubmitPayload = () => {
  const {
    createTime,
    updateTime,
    storageBlobDTO,
    commonFileListBefore,
    commonFileListAfter,
    commonFileList,
    __raw,
    ...rest
  } = currentTask.value || {};
  const files = buildSubmitFiles();
  const tempFileIds = files
    .map(item => item?.tempId ?? item?.tempFileId ?? item?.id)
    .filter(Boolean);
  return {
    ...rest,
    hasException: hasException.value,
    tempFileIds,
    commonFileListBefore: buildGroupedFiles(beforeModelValue.value),
    commonFileListAfter: buildGroupedFiles(afterModelValue.value),
    commonFileList: buildGroupedFiles(issueModelValue.value),
  };
};
const submitUpload = async () => {
  if (hasException.value === null) {
    ElMessage.warning("请选择是否存在异常");
    return;
  }
  const files = buildSubmitFiles();
  if (!files.length) {
    ElMessage.warning("请先上传文件");
    return;
  }
  const loadingInstance = ElLoading.service({
    text: "提交中...",
    background: "rgba(0, 0, 0, 0.3)",
  });
  try {
    const payload = buildSubmitPayload();
    const result = await uploadInspectionTask(payload);
    if (result?.code === 200 || result?.success) {
      ElMessage.success("提交成功");
      showUploadDialog.value = false;
      resetDialogState();
      emit("success");
      emit("closeDia");
    } else {
      ElMessage.error(result?.msg || result?.message || "提交失败");
    }
  } catch (error) {
    ElMessage.error(error?.message || "提交失败");
  } finally {
    loadingInstance.close();
  }
};
const goToRepair = () => {
  const taskInfo = {
    taskId: currentTask.value?.taskId || currentTask.value?.id,
    taskName: currentTask.value?.taskName,
    inspectionLocation: currentTask.value?.inspectionLocation,
    inspector: currentTask.value?.inspector,
    uploadedFiles: {
      before: beforeModelValue.value,
      after: afterModelValue.value,
      issue: issueModelValue.value,
    },
  };
  sessionStorage.setItem("repairTaskInfo", JSON.stringify(taskInfo));
  window.location.href = "/equipmentManagement/repair";
};
const previewAttachment = file => {
  if (isImageFile(file)) {
    window.open(file.url || file.downloadUrl, "_blank");
  } else {
    currentVideoFile.value = file;
    showVideoDialog.value = true;
  }
};
const isImageFile = file => {
  if (file?.contentType?.startsWith("image/")) return true;
  const name =
    file?.bucketFilename || file?.originalFilename || file?.name || "";
  const ext = name.split(".").pop()?.toLowerCase();
  return ["jpg", "jpeg", "png", "gif", "webp"].includes(ext);
};
const formatFileSize = size => {
  if (!size) return "";
  if (size < 1024) return `${size}B`;
  if (size < 1024 * 1024) return `${(size / 1024).toFixed(1)}KB`;
  return `${(size / 1024 / 1024).toFixed(1)}MB`;
};
defineExpose({
  openDialog,
});
</script>
<style scoped>
.exception-section {
  margin-bottom: 16px;
  padding: 12px;
  background: #f8f9fa;
  border-radius: 8px;
}
.section-title {
  font-weight: 600;
  margin-bottom: 8px;
}
.upload-buttons {
  margin-bottom: 12px;
}
.file-list {
  display: flex;
  flex-wrap: wrap;
  gap: 12px;
}
.file-item {
  width: 120px;
  padding: 8px;
  border: 1px solid #e5e5e5;
  border-radius: 10px;
  background: #fff;
  text-align: center;
}
.file-preview-container {
  position: relative;
}
.file-preview {
  width: 90px;
  height: 90px;
  object-fit: cover;
  border-radius: 8px;
  border: 1px solid #eee;
  cursor: pointer;
}
.video-preview {
  width: 90px;
  height: 90px;
  margin: 0 auto;
  border-radius: 8px;
  background: #eef3f8;
  display: flex;
  align-items: center;
  justify-content: center;
  color: #409eff;
  cursor: pointer;
}
.delete-btn {
  position: absolute;
  top: -6px;
  right: 6px;
  width: 22px;
  height: 22px;
  border: none;
  border-radius: 50%;
  color: #fff;
  background: #f56c6c;
  cursor: pointer;
}
.file-name {
  margin-top: 6px;
  font-size: 12px;
  color: #333;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.file-size {
  font-size: 11px;
  color: #999;
}
.upload-summary {
  margin-top: 16px;
  padding: 10px;
  background: #f8f9fa;
  border-left: 3px solid #409eff;
  font-size: 13px;
  color: #666;
}
.video-player {
  width: 100%;
  max-height: 70vh;
  background: #000;
}
</style>
src/views/equipmentManagement/inspectionManagement/components/viewFiles.vue
@@ -30,9 +30,9 @@
          </div>
        </div>
        
        <!-- ç”Ÿäº§åŽ -->
        <!-- ç”Ÿäº§ä¸­ -->
        <div class="form-container">
          <div class="title">生产后</div>
          <div class="title">生产中</div>
          
          <!-- å›¾ç‰‡åˆ—表 -->
          <div style="display: flex; flex-wrap: wrap;">
@@ -57,9 +57,9 @@
          </div>
        </div>
        
        <!-- ç”Ÿäº§é—®é¢˜ -->
        <!-- ç”Ÿäº§åŽ -->
        <div class="form-container">
          <div class="title">生产问题</div>
          <div class="title">生产后</div>
          
          <!-- å›¾ç‰‡åˆ—表 -->
          <div style="display: flex; flex-wrap: wrap;">
src/views/equipmentManagement/inspectionManagement/index.vue
@@ -76,6 +76,8 @@
    <form-dia ref="formDia"
              @closeDia="handleQuery"></form-dia>
    <view-files ref="viewFiles"></view-files>
    <upload-files ref="uploadFiles"
                  @closeDia="handleQuery"></upload-files>
  </div>
</template>
@@ -87,6 +89,7 @@
  // ç»„件引入
  import PIMTable from "@/components/PIMTable/PIMTable.vue";
  import FormDia from "@/views/equipmentManagement/inspectionManagement/components/formDia.vue";
  import UploadFiles from "@/views/equipmentManagement/inspectionManagement/components/uploadFiles.vue";
  import ViewFiles from "@/views/equipmentManagement/inspectionManagement/components/viewFiles.vue";
  // æŽ¥å£å¼•å…¥
@@ -100,6 +103,7 @@
  const { proxy } = getCurrentInstance();
  const formDia = ref();
  const viewFiles = ref();
  const uploadFiles = ref();
  // æŸ¥è¯¢å‚æ•°
  const queryParams = reactive({
@@ -184,8 +188,9 @@
    const operationConfig = {
      label: "操作",
      width: 130,
      width: operations.length > 1 ? 180 : 130,
      fixed: "right",
            align: 'center',
      dataType: "action",
      operation: operations
        .map(op => {
@@ -194,6 +199,12 @@
              return {
                name: "编辑",
                clickFun: handleAdd,
                color: "#409EFF",
              };
            case "upload":
              return {
                name: "上传",
                clickFun: openUploadFiles,
                color: "#409EFF",
              };
            case "viewFile":
@@ -226,12 +237,12 @@
      ];
      operationsArr.value = ["edit"];
    } else if (value === "task") {
      const operationColumn = getOperationColumn(["viewFile"]);
      const operationColumn = getOperationColumn(["upload", "viewFile"]);
      tableColumns.value = [
        ...columns.value,
        ...(operationColumn ? [operationColumn] : []),
      ];
      operationsArr.value = ["viewFile"];
      operationsArr.value = ["upload", "viewFile"];
    }
    pageNum.value = 1;
    pageSize.value = 10;
@@ -273,6 +284,7 @@
        // å¤„理 inspector å­—段,将字符串转换为数组(适用于所有情况)
        tableData.value = rawData.map(item => {
          const processedItem = { ...item };
          processedItem.__raw = { ...item };
          // å¤„理 inspector å­—段
          if (processedItem.inspector) {
@@ -322,6 +334,13 @@
  const viewFile = row => {
    nextTick(() => {
      viewFiles.value?.openDialog(row);
    });
  };
  // ä¸Šä¼ é™„ä»¶
  const openUploadFiles = row => {
    nextTick(() => {
      uploadFiles.value?.openDialog(row);
    });
  };
@@ -390,4 +409,4 @@
    color: #909399;
    font-size: 14px;
  }
</style>
</style>
src/views/equipmentManagement/repair/Modal/RepairModal.vue
@@ -31,6 +31,14 @@
          </el-form-item>
        </el-col>
        <el-col :span="12">
          <el-form-item label="报修项目">
            <el-input
              v-model="form.repairProject"
              placeholder="请输入报修项目"
            />
          </el-form-item>
        </el-col>
        <el-col :span="12">
          <el-form-item label="报修日期">
            <el-date-picker
              v-model="form.repairTime"
@@ -111,6 +119,7 @@
  deviceLedgerId: undefined, // è®¾å¤‡Id
  deviceName: undefined, // è®¾å¤‡åç§°
  deviceModel: undefined, // è§„格型号
  repairProject: undefined, // æŠ¥ä¿®é¡¹ç›®
  repairTime: dayjs().format("YYYY-MM-DD"), // æŠ¥ä¿®æ—¥æœŸï¼Œé»˜è®¤å½“天
  repairName: userStore.nickName, // æŠ¥ä¿®äºº
  remark: undefined, // æ•…障现象
@@ -126,6 +135,7 @@
  form.deviceLedgerId = data.deviceLedgerId;
  form.deviceName = data.deviceName;
  form.deviceModel = data.deviceModel;
  form.repairProject = data.repairProject;
  form.repairTime = data.repairTime;
  form.repairName = data.repairName;
  form.remark = data.remark;
src/views/equipmentManagement/repair/index.vue
@@ -188,6 +188,11 @@
        prop: "deviceModel",
      },
      {
        label: "报修项目",
        align: "center",
        prop: "repairProject",
      },
      {
        label: "报修日期",
        align: "center",
        prop: "repairTime",
src/views/productionManagement/productionCosting/index.vue
@@ -149,6 +149,21 @@
    minWidth: 100,
  },
  {
    label: "报废数量",
    prop: "scrapQty",
    minWidth: 100,
  },
  {
    label: "补产数量",
    prop: "replenishQty",
    minWidth: 100,
  },
  {
    label: "加放数",
    prop: "addQty",
    minWidth: 100,
  },
  {
    label: "机台",
    prop: "deviceName",
    minWidth: 100,
src/views/productionManagement/productionOrder/BindRouteDialog.vue
@@ -62,7 +62,7 @@
        <el-table-column label="材料名称">
          <template #default="{ row, $index }">
            <el-tree-select
                v-if="props.type === 'add'"
                v-if="!isDetail && !row.productById"
                v-model="row.productById"
                placeholder="请选择"
                clearable
@@ -70,7 +70,6 @@
                @change="(val) => getModels(val, row, $index)"
                :data="productOptions"
                :render-after-expand="false"
                :disabled="isDetail"
                style="width: 100%"
            />
            <span v-else>{{ row.name }}</span>
@@ -82,13 +81,13 @@
          </template>
          <template #default="{ row }">
            <el-select
                v-if="props.type === 'add'"
                v-if="!isDetail && !row.productModelId"
                v-model="row.productModelId"
                placeholder="请选择规格"
                filterable
                clearable
                @change="(val) => handleMaterialModelChange(val, row)"
                :disabled="isDetail"
                style="width: 100%"
            >
              <el-option
                  v-for="item in row.modelOptions"
src/views/productionManagement/productionReporting/index.vue
@@ -19,12 +19,12 @@
                    style="width: 200px;"
                    @change="handleQuery" />
        </el-form-item>
        <el-form-item label="审核状态:">
          <el-select v-model="searchForm.auditStatus" placeholder="请选择" style="width: 200px;" @change="handleQuery">
              <el-option v-for="item in auditStatusOptions" :key="item.value" :label="item.label" :value="item.value">
              </el-option>
          </el-select>
        </el-form-item>
<!--        <el-form-item label="审核状态:">-->
<!--          <el-select v-model="searchForm.auditStatus" placeholder="请选择" style="width: 200px;" @change="handleQuery">-->
<!--              <el-option v-for="item in auditStatusOptions" :key="item.value" :label="item.label" :value="item.value">-->
<!--              </el-option>-->
<!--          </el-select>-->
<!--        </el-form-item>-->
        <el-form-item>
          <el-button type="primary"
                     @click="handleQuery">搜索</el-button>
@@ -250,30 +250,30 @@
      prop: "deviceName",
      width: 120,
    },
    {
      label: "审核人",
      prop: "auditUserName",
      width: 120,
    },
     {
      label: "审核状态",
      prop: "auditStatus",
      width: 120,
      dataType: "tag",
      formatData: val => {
        const statusMap = { 0: "未审核", 1: "通过", 2: "不通过" };
        return statusMap[val] ?? "未知";
      },
      formatType: val => {
        const typeMap = { 0: "info", 1: "success", 2: "danger" };
        return typeMap[val] ?? "";
      },
    },
    {
      label: "最终审核人",
      prop: "sureAuditUserName",
      width: 120,
    },
    // {
    //   label: "审核人",
    //   prop: "auditUserName",
    //   width: 120,
    // },
    //  {
    //   label: "审核状态",
    //   prop: "auditStatus",
    //   width: 120,
    //   dataType: "tag",
    //   formatData: val => {
    //     const statusMap = { 0: "未审核", 1: "通过", 2: "不通过" };
    //     return statusMap[val] ?? "未知";
    //   },
    //   formatType: val => {
    //     const typeMap = { 0: "info", 1: "success", 2: "danger" };
    //     return typeMap[val] ?? "";
    //   },
    // },
    // {
    //   label: "最终审核人",
    //   prop: "sureAuditUserName",
    //   width: 120,
    // },
    {
      label: "产品名称",
      prop: "productName",
@@ -292,6 +292,11 @@
    {
      label: "报废数量",
      prop: "scrapQty",
      width: 120,
    },
    {
      label: "加放数",
      prop: "addQty",
      width: 120,
    },
    {
@@ -330,13 +335,13 @@
            deleteReport(row);
          },
        },
        {
          name:"审核",
          clickFun: row => {
            handleAudit(row);
          },
          disabled: row => !(Number(row?.auditStatus) === 0 && (Number(row?.auditUserId) === -1 || Number(row?.auditUserId) === Number(userStore.id)))
        },
        // {
        //   name:"审核",
        //   clickFun: row => {
        //     handleAudit(row);
        //   },
        //   disabled: row => !(Number(row?.auditStatus) === 0 && (Number(row?.auditUserId) === -1 || Number(row?.auditUserId) === Number(userStore.id)))
        // },
      ],
    },
  ]);
src/views/productionManagement/workOrder/index.vue
@@ -192,6 +192,7 @@
                  step="1"
                  placeholder="请输入本次生产数量"
                  style="width: 100%"
                  :class="{ 'over-limit': reportForm.quantity > reportForm.planQuantity }"
                  @input="handleQuantityInput"
              />
            </el-form-item>
@@ -218,6 +219,18 @@
                  step="1"
                  placeholder="请输入报废数量"
                  @input="handleScrapQtyInput"
              />
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="加放数" prop="addQty">
              <el-input
                  v-model.number="reportForm.addQty"
                  type="number"
                  min="0"
                  step="1"
                  placeholder="请输入加放数"
              />
            </el-form-item>
          </el-col>
@@ -263,24 +276,24 @@
<!--            </el-form-item>-->
<!--          </el-col>-->
          <el-col :span="12">
            <el-form-item label="审核人" prop="auditUserId">
              <el-select
                  v-model="reportForm.auditUserId"
                  placeholder="请选择审核人"
                  clearable
                  filterable
                  @change="handleReviewerIdChange"
              >
                <el-option
                    v-for="user in userOptions"
                    :key="user.userId"
                    :label="user.nickName"
                    :value="user.userId"
                />
              </el-select>
            </el-form-item>
          </el-col>
<!--          <el-col :span="12">-->
<!--            <el-form-item label="审核人" prop="auditUserId">-->
<!--              <el-select-->
<!--                  v-model="reportForm.auditUserId"-->
<!--                  placeholder="请选择审核人"-->
<!--                  clearable-->
<!--                  filterable-->
<!--                  @change="handleReviewerIdChange"-->
<!--              >-->
<!--                <el-option-->
<!--                    v-for="user in userOptions"-->
<!--                    :key="user.userId"-->
<!--                    :label="user.nickName"-->
<!--                    :value="user.userId"-->
<!--                />-->
<!--              </el-select>-->
<!--            </el-form-item>-->
<!--          </el-col>-->
        </el-row>
      </el-form>
@@ -1121,6 +1134,7 @@
  planQuantity: 0,
  quantity: null,
  scrapQty: null,
  addQty: 0,
  startTime: "",
  endTime: "",
  userName: "",
@@ -1228,7 +1242,7 @@
  scrapQty: [{validator: validateScrapQty, trigger: "blur"}],
  startTime: [{required: true, message: "请选择开始时间", trigger: "change"}],
  endTime: [{required: true, message: "请选择结束时间", trigger: "change"}],
  auditUserId: [{required: true, message: "请选择审核人", trigger: "change"}],
  // auditUserId: [{required: true, message: "请选择审核人", trigger: "change"}],
  teamList: [{required: true, message: "请选择班组", trigger: "change"}],
  deviceId: [{required: true, message: "请选择设备", trigger: "change"}],
};
@@ -1241,12 +1255,6 @@
  }
  const num = Number(value);
  if (isNaN(num)) {
    return;
  }
  // å¦‚果超过待生产数量
  if (num > reportForm.planQuantity) {
    proxy.$modal.msgWarning("本次生产数量不能大于待生产数量");
    reportForm.quantity = reportForm.planQuantity;
    return;
  }
  // å¦‚果小于1,清除
@@ -1456,6 +1464,7 @@
  reportForm.replenishQty = 0;
  reportForm.teamList = [];
  reportForm.scrapQty = 0;
  reportForm.addQty = 0;
  reportForm.userIds = row.userIds || [];
  const ids = (row.userIds || "")
@@ -1464,7 +1473,7 @@
      .filter(Boolean);
  reportForm.userIdsList = userTeamOptions.value
      .filter(item => ids.includes(String(item.userId)))
      // .filter(item => ids.includes(String(item.userId)))
      .map(item => ({
        userId: item.userId,
        nickName: item.nickName
@@ -1535,12 +1544,12 @@
      return;
    }
    if (quantity > reportForm.planQuantity) {
      ElMessageBox.alert("本次生产数量不能超过待生产数量", "提示", {
        confirmButtonText: "确定",
      });
      return;
    }
    // if (quantity > reportForm.planQuantity) {
    //   ElMessageBox.alert("本次生产数量不能超过待生产数量", "提示", {
    //     confirmButtonText: "确定",
    //   });
    //   return;
    // }
    const submitData = {
      ...reportForm,
@@ -1805,4 +1814,8 @@
  white-space: normal !important;
  word-break: break-all;
}
.over-limit .el-input__inner {
  color: #f56c6c !important;
}
</style>
src/views/qualityManagement/finalInspection/components/formDia.vue
@@ -80,7 +80,7 @@
        <el-row :gutter="30">
          <el-col :span="12">
            <el-form-item label="检验员:" prop="checkName">
                            <el-select v-model="form.checkName" placeholder="请选择" clearable>
                            <el-select v-model="form.checkName" placeholder="请选择" clearable filterable>
                                <el-option v-for="item in userList" :key="item.nickName" :label="item.nickName"
                                                     :value="item.nickName"/>
                            </el-select>
@@ -203,13 +203,13 @@
const modelOptions = ref([]);
// æ‰“开弹框
const openDialog = async (type, row) => {
const openDialog = async (type, row, defaultCheckResult = "", defaultCheckName = "") => {
  operationType.value = type;
  dialogFormVisible.value = true;
  // å…ˆæ¸…空表单验证状态,避免闪烁
  await nextTick();
  proxy.$refs.formRef?.clearValidate();
  // å¹¶è¡ŒåŠ è½½åŸºç¡€æ•°æ®
  const [userListsRes] = await Promise.all([
    userListNoPage(),
@@ -218,17 +218,28 @@
      supplierList.value = res.data;
    })
  ]);
  userList.value = userListsRes.data;
  // ç­›é€‰ roleIds åŒ…含 106 çš„用户
  userList.value = (userListsRes.data || []).filter(user => {
    const roleIds = user.roleIds || [];
    return roleIds.includes(106) || roleIds.includes('106');
  });
  form.value = {}
  testStandardOptions.value = [];
  tableData.value = [];
  if (operationType.value === 'edit') {
    // å…ˆä¿å­˜ testStandardId,避免被清空
    const savedTestStandardId = row.testStandardId;
    // å…ˆè®¾ç½®è¡¨å•数据,但暂时清空 testStandardId,等选项加载完成后再设置
    form.value = {...row, testStandardId: ''}
    // å¦‚果传入了默认检测结果,覆盖row中的值
    if (defaultCheckResult) {
      form.value.checkResult = defaultCheckResult;
    }
    // å¦‚果传入了默认检验员,覆盖row中的值(优先使用传入的检验员)
    console.log('formDia checkName debug:', { defaultCheckName, rowCheckName: row.checkName });
    form.value.checkName = defaultCheckName || row.checkName || "";
    currentProductId.value = row.productId || 0
    // æ¸…空验证状态,避免数据加载过程中的校验闪烁
    nextTick(() => {
src/views/qualityManagement/finalInspection/index.vue
@@ -40,23 +40,56 @@
    <InspectionFormDia ref="inspectionFormDia" @close="handleQuery"></InspectionFormDia>
    <FormDia ref="formDia" @close="handleQuery"></FormDia>
    <files-dia ref="filesDia" @close="handleQuery"></files-dia>
        <el-dialog v-model="dialogFormVisible" title="编辑检验员" width="30%"
    <!-- æ£€éªŒç»“果选择对话框 -->
    <el-dialog v-model="quickCheckVisible" title="检验结果" width="30%" @close="closeQuickCheck">
      <el-form :model="quickCheckForm" label-width="140px" label-position="top" ref="quickCheckRef">
        <el-form-item label="检测结果:" required>
          <el-radio-group v-model="quickCheckForm.checkResult">
            <el-radio value="合格">合格</el-radio>
            <el-radio value="不合格">不合格</el-radio>
          </el-radio-group>
        </el-form-item>
        <el-form-item label="检验员:">
          <el-select v-model="quickCheckForm.checkName" placeholder="请选择" clearable style="width: 100%">
            <el-option v-for="item in userList" :key="item.nickName" :label="item.nickName" :value="item.nickName"/>
          </el-select>
        </el-form-item>
        <el-form-item label="检测日期:">
          <el-date-picker
            v-model="quickCheckForm.checkTime"
            type="date"
            placeholder="请选择日期"
            value-format="YYYY-MM-DD"
            format="YYYY-MM-DD"
            clearable
            style="width: 100%"
          />
        </el-form-item>
      </el-form>
      <template #footer>
        <div class="dialog-footer">
          <el-button type="primary" @click="handleQuickCheckConfirm">确认</el-button>
          <el-button @click="closeQuickCheck">取消</el-button>
        </div>
      </template>
    </el-dialog>
    <el-dialog v-model="dialogFormVisible" title="编辑检验员" width="30%"
                             @close="closeDia">
            <el-form :model="form" label-width="140px" label-position="top" :rules="rules" ref="formRef">
                <el-form-item label="检验员:" prop="checkName">
                    <el-select v-model="form.checkName" placeholder="请选择" clearable>
                        <el-option v-for="item in userList" :key="item.nickName" :label="item.nickName"
                                             :value="item.nickName"/>
                    </el-select>
                </el-form-item>
            </el-form>
            <template #footer>
                <div class="dialog-footer">
                    <el-button type="primary" @click="submitForm">确认</el-button>
                    <el-button @click="closeDia">取消</el-button>
                </div>
            </template>
        </el-dialog>
                <el-form :model="form" label-width="140px" label-position="top" :rules="rules" ref="formRef">
                    <el-form-item label="检验员:" prop="checkName">
                        <el-select v-model="form.checkName" placeholder="请选择" clearable>
                            <el-option v-for="item in userList" :key="item.nickName" :label="item.nickName"
                                                 :value="item.nickName"/>
                        </el-select>
                    </el-form-item>
                </el-form>
                <template #footer>
                    <div class="dialog-footer">
                        <el-button type="primary" @click="submitForm">确认</el-button>
                        <el-button @click="closeDia">取消</el-button>
                    </div>
                </template>
            </el-dialog>
  </div>
</template>
@@ -159,10 +192,10 @@
    width: 280,
    operation: [
      {
        name: "编辑",
        name: "检验",
        type: "text",
        clickFun: (row) => {
          openForm("edit", row);
          openQuickCheck(row);
        },
                disabled: (row) => {
                    // å·²æäº¤åˆ™ç¦ç”¨
@@ -181,43 +214,43 @@
          openFilesFormDia(row);
        },
      },
            {
                name: "提交",
                type: "text",
                clickFun: (row) => {
                    submit(row.id);
                },
                disabled: (row) => {
                    // å·²æäº¤åˆ™ç¦ç”¨
                    if (row.inspectState == 1) return true;
                    // å¦‚果检验员有值,只有当前登录用户能提交
                    if (row.checkName) {
                        return row.checkName !== userStore.nickName;
                    }
                    return false;
                }
            },
            {
                name: "分配检验员",
                type: "text",
                clickFun: (row) => {
                    if (!row.checkName) {
                        open(row)
                    } else {
                        proxy.$modal.msgError("检验员已存在");
                {
                    name: "提交",
                    type: "text",
                    clickFun: (row) => {
                        submit(row.id);
                    },
                    disabled: (row) => {
                        // å·²æäº¤åˆ™ç¦ç”¨
                        if (row.inspectState == 1) return true;
                        // å¦‚果检验员有值,只有当前登录用户能提交
                        if (row.checkName) {
                            return row.checkName !== userStore.nickName;
                        }
                        return false;
                    }
                },
                disabled: (row) => {
                    return row.inspectState == 1 || row.checkName;
                }
            },
            {
                name: "下载",
                type: "text",
                clickFun: (row) => {
                    downLoadFile(row);
                {
                    name: "分配检验员",
                    type: "text",
                    clickFun: (row) => {
                        if (!row.checkName) {
                            open(row)
                        } else {
                            proxy.$modal.msgError("检验员已存在");
                        }
                    },
                    disabled: (row) => {
                        return row.inspectState == 1 || row.checkName;
                    }
                },
            },
                {
                    name: "下载",
                    type: "text",
                    clickFun: (row) => {
                        downLoadFile(row);
                    },
                },
    ],
  },
]);
@@ -240,6 +273,13 @@
    checkName: ""
});
const dialogFormVisible = ref(false);
const quickCheckVisible = ref(false);
const quickCheckForm = ref({
    checkResult: "合格",
    checkName: "",
    checkTime: ""
});
const quickCheckRef = ref(null);
const changeDaterange = (value) => {
  searchForm.value.entryDateStart = undefined;
@@ -367,7 +407,11 @@
const open = async (row) => {
    let userLists = await userListNoPage();
    userList.value = userLists.data;
    // ç­›é€‰ roleIds åŒ…含 106 çš„用户
    userList.value = (userLists.data || []).filter(user => {
        const roleIds = user.roleIds || [];
        return roleIds.includes(106) || roleIds.includes('106');
    });
    currentRow.value = row
    dialogFormVisible.value = true
}
@@ -378,17 +422,91 @@
            type: 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
        })
        const downloadUrl = window.URL.createObjectURL(blob)
        const link = document.createElement('a')
        link.href = downloadUrl
        link.download = '原材料检验报告.docx'
        document.body.appendChild(link)
        link.click()
        document.body.removeChild(link)
        window.URL.revokeObjectURL(downloadUrl)
    })
};
// æ‰“开检验结果选择对话框
const openQuickCheck = async (row) => {
    currentRow.value = row;
    // åŠ è½½ç”¨æˆ·åˆ—è¡¨ï¼Œç­›é€‰ roleIds åŒ…含 106 çš„用户
    try {
        const userLists = await userListNoPage();
        userList.value = (userLists.data || []).filter(user => {
            const roleIds = user.roleIds || [];
            return roleIds.includes(106) || roleIds.includes('106');
        });
    } catch (e) {
        console.error("加载检验员列表失败", e);
        userList.value = [];
    }
    // è®¾ç½®é»˜è®¤å€¼ï¼ˆæ£€éªŒå‘˜é»˜è®¤ä¸ºå½“前登录用户)
    quickCheckForm.value = {
        checkResult: "合格",
        checkName: userStore.nickName || "",
        checkTime: dayjs().format("YYYY-MM-DD")
    };
    quickCheckVisible.value = true;
};
// å…³é—­æ£€éªŒç»“果选择对话框
const closeQuickCheck = () => {
    quickCheckVisible.value = false;
    quickCheckForm.value = {
        checkResult: "合格",
        checkName: "",
        checkTime: ""
    };
};
// ç¡®è®¤æ£€éªŒç»“æžœ
const handleQuickCheckConfirm = () => {
    if (!quickCheckForm.value.checkResult) {
        proxy.$modal.msgWarning("请选择检测结果");
        return;
    }
    if (!quickCheckForm.value.checkName) {
        proxy.$modal.msgWarning("请选择检验员");
        return;
    }
    if (!quickCheckForm.value.checkTime) {
        proxy.$modal.msgWarning("请选择检测日期");
        return;
    }
    if (quickCheckForm.value.checkResult === "合格") {
        // åˆæ ¼ï¼šç›´æŽ¥æäº¤
        const data = {
            id: currentRow.value.id,
            checkResult: "合格",
            checkName: quickCheckForm.value.checkName,
            checkTime: quickCheckForm.value.checkTime,
            inspectType: 2
        };
        qualityInspectUpdate(data).then(res => {
            proxy.$modal.msgSuccess("检验成功");
            closeQuickCheck();
            getList();
        });
    } else {
        // ä¸åˆæ ¼ï¼šæ‰“开详细填写页面,传递检验员信息
        // å…ˆä¿å­˜æ£€éªŒå‘˜å€¼ï¼Œé¿å… closeQuickCheck é‡ç½®åŽä¸¢å¤±
        const checkNameToPass = quickCheckForm.value.checkName;
        closeQuickCheck();
        nextTick(() => {
            formDia.value?.openDialog("edit", currentRow.value, "不合格", checkNameToPass);
        });
    }
};
onMounted(() => {
  getList();
});
src/views/qualityManagement/processInspection/components/formDia.vue
@@ -89,7 +89,7 @@
        <el-row :gutter="30">
          <el-col :span="12">
            <el-form-item label="检验员:" prop="checkName">
                            <el-select v-model="form.checkName" placeholder="请选择" clearable>
                            <el-select v-model="form.checkName" placeholder="请选择" clearable filterable>
                                <el-option v-for="item in userList" :key="item.nickName" :label="item.nickName"
                                                     :value="item.nickName"/>
                            </el-select>
@@ -216,7 +216,7 @@
const modelOptions = ref([]);
// æ‰“开弹框
const openDialog = async (type, row) => {
const openDialog = async (type, row, defaultCheckResult = "", defaultCheckName = "") => {
    operationType.value = type;
    getOptions().then((res) => {
        supplierList.value = res.data;
@@ -230,12 +230,16 @@
        processList.value = [];
    }
    let userLists = await userListNoPage();
    userList.value = userLists.data;
    // å…ˆé‡ç½®è¡¨å•数据(保持字段完整,避免弹窗首次渲染时触发必填红框“闪一下”)
    // ç­›é€‰ roleIds åŒ…含 106 çš„用户
    userList.value = (userLists.data || []).filter(user => {
        const roleIds = user.roleIds || [];
        return roleIds.includes(106) || roleIds.includes('106');
    });
    // å…ˆé‡ç½®è¡¨å•数据(保持字段完整,避免弹窗首次渲染时触发必填红框"闪一下")
    form.value = {
        checkTime: "",
        process: "",
        checkName: "",
        checkName: defaultCheckName || "",
        productName: "",
        productId: "",
        productModelId: "",
@@ -244,7 +248,7 @@
        unit: "",
        quantity: "",
        checkCompany: "",
        checkResult: "",
        checkResult: defaultCheckResult || "",
    }
    testStandardOptions.value = [];
    tableData.value = [];
@@ -255,6 +259,13 @@
        const savedTestStandardId = row.testStandardId;
        // å…ˆè®¾ç½®è¡¨å•数据,但暂时清空 testStandardId,等选项加载完成后再设置
        form.value = {...row, testStandardId: ''}
        // å¦‚果传入了默认检测结果,覆盖row中的值
        if (defaultCheckResult) {
        form.value.checkResult = defaultCheckResult;
        }
        // å¦‚果传入了默认检验员,覆盖row中的值(优先使用传入的检验员)
        console.log('formDia checkName debug:', { defaultCheckName, rowCheckName: row.checkName });
            form.value.checkName = defaultCheckName || row.checkName || "";
        currentProductId.value = row.productId || 0
        // å…³é”®ï¼šç¼–辑时加载规格型号下拉选项,才能反显 productModelId
        if (currentProductId.value) {
src/views/qualityManagement/processInspection/index.vue
@@ -40,23 +40,56 @@
    <InspectionFormDia ref="inspectionFormDia" @close="handleQuery"></InspectionFormDia>
    <FormDia ref="formDia" @close="handleQuery"></FormDia>
    <files-dia ref="filesDia" @close="handleQuery"></files-dia>
        <el-dialog v-model="dialogFormVisible" title="编辑检验员" width="30%"
    <!-- æ£€éªŒç»“果选择对话框 -->
    <el-dialog v-model="quickCheckVisible" title="检验结果" width="30%" @close="closeQuickCheck">
      <el-form :model="quickCheckForm" label-width="140px" label-position="top" ref="quickCheckRef">
        <el-form-item label="检测结果:" required>
          <el-radio-group v-model="quickCheckForm.checkResult">
            <el-radio value="合格">合格</el-radio>
            <el-radio value="不合格">不合格</el-radio>
          </el-radio-group>
        </el-form-item>
        <el-form-item label="检验员:">
          <el-select v-model="quickCheckForm.checkName" placeholder="请选择" clearable style="width: 100%">
            <el-option v-for="item in userList" :key="item.nickName" :label="item.nickName" :value="item.nickName"/>
          </el-select>
        </el-form-item>
        <el-form-item label="检测日期:">
          <el-date-picker
            v-model="quickCheckForm.checkTime"
            type="date"
            placeholder="请选择日期"
            value-format="YYYY-MM-DD"
            format="YYYY-MM-DD"
            clearable
            style="width: 100%"
          />
        </el-form-item>
      </el-form>
      <template #footer>
        <div class="dialog-footer">
          <el-button type="primary" @click="handleQuickCheckConfirm">确认</el-button>
          <el-button @click="closeQuickCheck">取消</el-button>
        </div>
      </template>
    </el-dialog>
    <el-dialog v-model="dialogFormVisible" title="编辑检验员" width="30%"
                             @close="closeDia">
            <el-form :model="form" label-width="140px" label-position="top" :rules="rules" ref="formRef">
                <el-form-item label="检验员:" prop="checkName">
                    <el-select v-model="form.checkName" placeholder="请选择" clearable>
                        <el-option v-for="item in userList" :key="item.nickName" :label="item.nickName"
                                             :value="item.nickName"/>
                    </el-select>
                </el-form-item>
            </el-form>
            <template #footer>
                <div class="dialog-footer">
                    <el-button type="primary" @click="submitForm">确认</el-button>
                    <el-button @click="closeDia">取消</el-button>
                </div>
            </template>
        </el-dialog>
                <el-form :model="form" label-width="140px" label-position="top" :rules="rules" ref="formRef">
                    <el-form-item label="检验员:" prop="checkName">
                        <el-select v-model="form.checkName" placeholder="请选择" clearable>
                            <el-option v-for="item in userList" :key="item.nickName" :label="item.nickName"
                                                 :value="item.nickName"/>
                        </el-select>
                    </el-form-item>
                </el-form>
                <template #footer>
                    <div class="dialog-footer">
                        <el-button type="primary" @click="submitForm">确认</el-button>
                        <el-button @click="closeDia">取消</el-button>
                    </div>
                </template>
            </el-dialog>
  </div>
</template>
@@ -164,10 +197,10 @@
    width: 280,
    operation: [
      {
        name: "编辑",
        name: "检验",
        type: "text",
        clickFun: (row) => {
          openForm("edit", row);
          openQuickCheck(row);
        },
                disabled: (row) => {
                    // å·²æäº¤åˆ™ç¦ç”¨
@@ -186,43 +219,43 @@
          openFilesFormDia(row);
        },
      },
            {
                name: "提交",
                type: "text",
                clickFun: (row) => {
                    submit(row.id);
                },
                disabled: (row) => {
                    // å·²æäº¤åˆ™ç¦ç”¨
                    if (row.inspectState == 1) return true;
                    // å¦‚果检验员有值,只有当前登录用户能提交
                    if (row.checkName) {
                        return row.checkName !== userStore.nickName;
                    }
                    return false;
                }
            },
            {
                name: "分配检验员",
                type: "text",
                clickFun: (row) => {
                    if (!row.checkName) {
                        open(row)
                    } else {
                        proxy.$modal.msgError("检验员已存在");
                {
                    name: "提交",
                    type: "text",
                    clickFun: (row) => {
                        submit(row.id);
                    },
                    disabled: (row) => {
                        // å·²æäº¤åˆ™ç¦ç”¨
                        if (row.inspectState == 1) return true;
                        // å¦‚果检验员有值,只有当前登录用户能提交
                        if (row.checkName) {
                            return row.checkName !== userStore.nickName;
                        }
                        return false;
                    }
                },
                disabled: (row) => {
                    return row.inspectState == 1 || row.checkName;
                }
            },
            {
                name: "下载",
                type: "text",
                clickFun: (row) => {
                    downLoadFile(row);
                {
                    name: "分配检验员",
                    type: "text",
                    clickFun: (row) => {
                        if (!row.checkName) {
                            open(row)
                        } else {
                            proxy.$modal.msgError("检验员已存在");
                        }
                    },
                    disabled: (row) => {
                        return row.inspectState == 1 || row.checkName;
                    }
                },
            },
                {
                    name: "下载",
                    type: "text",
                    clickFun: (row) => {
                        downLoadFile(row);
                    },
                },
    ],
  },
]);
@@ -235,6 +268,13 @@
const form = ref({
    checkName: ""
});
const quickCheckVisible = ref(false);
const quickCheckForm = ref({
    checkResult: "合格",
    checkName: "",
    checkTime: ""
});
const quickCheckRef = ref(null);
const page = reactive({
  current: 1,
  size: 100,
@@ -310,7 +350,11 @@
}
const open = async (row) => {
    let userLists = await userListNoPage();
    userList.value = userLists.data;
    // ç­›é€‰ roleIds åŒ…含 106 çš„用户
    userList.value = (userLists.data || []).filter(user => {
        const roleIds = user.roleIds || [];
        return roleIds.includes(106) || roleIds.includes('106');
    });
    currentRow.value = row
    dialogFormVisible.value = true
}
@@ -363,13 +407,13 @@
            type: 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
        })
        const downloadUrl = window.URL.createObjectURL(blob)
        const link = document.createElement('a')
        link.href = downloadUrl
        link.download = '过程检验报告.docx'
        document.body.appendChild(link)
        link.click()
        document.body.removeChild(link)
        window.URL.revokeObjectURL(downloadUrl)
    })
@@ -388,6 +432,80 @@
        proxy.$modal.msg("已取消");
      });
};
// æ‰“开检验结果选择对话框
const openQuickCheck = async (row) => {
    currentRow.value = row;
    // åŠ è½½ç”¨æˆ·åˆ—è¡¨ï¼Œç­›é€‰ roleIds åŒ…含 106 çš„用户
    try {
        const userLists = await userListNoPage();
        userList.value = (userLists.data || []).filter(user => {
            const roleIds = user.roleIds || [];
            return roleIds.includes(106) || roleIds.includes('106');
        });
    } catch (e) {
        console.error("加载检验员列表失败", e);
        userList.value = [];
    }
    // è®¾ç½®é»˜è®¤å€¼ï¼ˆæ£€éªŒå‘˜é»˜è®¤ä¸ºå½“前登录用户)
    quickCheckForm.value = {
        checkResult: "合格",
        checkName: userStore.nickName || "",
        checkTime: dayjs().format("YYYY-MM-DD")
    };
    quickCheckVisible.value = true;
};
// å…³é—­æ£€éªŒç»“果选择对话框
const closeQuickCheck = () => {
    quickCheckVisible.value = false;
    quickCheckForm.value = {
        checkResult: "合格",
        checkName: "",
        checkTime: ""
    };
};
// ç¡®è®¤æ£€éªŒç»“æžœ
const handleQuickCheckConfirm = () => {
    if (!quickCheckForm.value.checkResult) {
        proxy.$modal.msgWarning("请选择检测结果");
        return;
    }
    if (!quickCheckForm.value.checkName) {
        proxy.$modal.msgWarning("请选择检验员");
        return;
    }
    if (!quickCheckForm.value.checkTime) {
        proxy.$modal.msgWarning("请选择检测日期");
        return;
    }
    if (quickCheckForm.value.checkResult === "合格") {
        // åˆæ ¼ï¼šç›´æŽ¥æäº¤
        const data = {
            id: currentRow.value.id,
            checkResult: "合格",
            checkName: quickCheckForm.value.checkName,
            checkTime: quickCheckForm.value.checkTime,
            inspectType: 1
        };
        qualityInspectUpdate(data).then(res => {
            proxy.$modal.msgSuccess("检验成功");
            closeQuickCheck();
            getList();
        });
    } else {
        // ä¸åˆæ ¼ï¼šæ‰“开详细填写页面,传递检验员信息
        // å…ˆä¿å­˜æ£€éªŒå‘˜å€¼ï¼Œé¿å… closeQuickCheck é‡ç½®åŽä¸¢å¤±
        const checkNameToPass = quickCheckForm.value.checkName;
        closeQuickCheck();
        nextTick(() => {
            formDia.value?.openDialog("edit", currentRow.value, "不合格", checkNameToPass);
        });
    }
};
onMounted(() => {
  getList();
});
src/views/qualityManagement/rawMaterialInspection/components/formDia.vue
@@ -100,7 +100,7 @@
        <el-row :gutter="30">
          <el-col :span="12">
            <el-form-item label="检验员:" prop="checkName">
              <el-select v-model="form.checkName" placeholder="请选择" clearable style="width: 100%">
              <el-select v-model="form.checkName" placeholder="请选择" clearable style="width: 100%" filterable>
                <el-option v-for="item in userList" :key="item.nickName" :label="item.nickName" :value="item.nickName"/>
              </el-select>
            </el-form-item>
@@ -228,7 +228,7 @@
});
// æ‰“开弹框
const openDialog = async (type, row) => {
const openDialog = async (type, row, defaultCheckResult = "", defaultCheckName = "") => {
  operationType.value = type;
  getOptions().then((res) => {
    supplierList.value = res.data;
@@ -236,16 +236,20 @@
  try {
    const userRes = await userListNoPage();
    userList.value = userRes.data || [];
    // ç­›é€‰ roleIds åŒ…含 106 çš„用户
    userList.value = (userRes.data || []).filter(user => {
      const roleIds = user.roleIds || [];
      return roleIds.includes(106) || roleIds.includes('106');
    });
  } catch (e) {
    console.error("加载检验员列表失败", e);
    userList.value = [];
  }
  // å…ˆé‡ç½®è¡¨å•数据(保持字段完整,避免弹窗首次渲染时触发必填红框“闪一下”)
  // å…ˆé‡ç½®è¡¨å•数据(保持字段完整,避免弹窗首次渲染时触发必填红框"闪一下")
    form.value = {
    checkTime: "",
    supplier: "",
    checkName: "",
    checkName: defaultCheckName || "",
    productName: "",
    productId: "",
    productModelId: "",
@@ -254,7 +258,7 @@
    unit: "",
    quantity: "",
    checkCompany: "",
    checkResult: "",
    checkResult: defaultCheckResult || "",
  }
  testStandardOptions.value = [];
  tableData.value = [];
@@ -264,6 +268,13 @@
    // å…ˆä¿å­˜ testStandardId,避免被清空
    const savedTestStandardId = row.testStandardId;
    form.value = {...row}
    // å¦‚果传入了默认检测结果,覆盖row中的值
    if (defaultCheckResult) {
      form.value.checkResult = defaultCheckResult;
    }
    // å¦‚果传入了默认检验员,覆盖row中的值(优先使用传入的检验员)
    console.log('formDia checkName debug:', { defaultCheckName, rowCheckName: row.checkName });
    form.value.checkName = defaultCheckName || row.checkName || "";
    currentProductId.value = row.productId || 0
    // å…³é”®ï¼šç¼–辑时加载规格型号下拉选项,才能反显 productModelId
    if (currentProductId.value) {
src/views/qualityManagement/rawMaterialInspection/index.vue
@@ -41,6 +41,39 @@
    <InspectionFormDia ref="inspectionFormDia" @close="handleQuery"></InspectionFormDia>
    <FormDia ref="formDia" @close="handleQuery"></FormDia>
    <files-dia ref="filesDia" @close="handleQuery"></files-dia>
    <!-- æ£€éªŒç»“果选择对话框 -->
    <el-dialog v-model="quickCheckVisible" title="检验结果" width="30%" @close="closeQuickCheck">
      <el-form :model="quickCheckForm" label-width="140px" label-position="top" ref="quickCheckRef">
        <el-form-item label="检测结果:" required>
          <el-radio-group v-model="quickCheckForm.checkResult">
            <el-radio value="合格">合格</el-radio>
            <el-radio value="不合格">不合格</el-radio>
          </el-radio-group>
        </el-form-item>
        <el-form-item label="检验员:">
          <el-select v-model="quickCheckForm.checkName" placeholder="请选择" clearable style="width: 100%">
            <el-option v-for="item in userList" :key="item.nickName" :label="item.nickName" :value="item.nickName"/>
          </el-select>
        </el-form-item>
        <el-form-item label="检测日期:">
          <el-date-picker
            v-model="quickCheckForm.checkTime"
            type="date"
            placeholder="请选择日期"
            value-format="YYYY-MM-DD"
            format="YYYY-MM-DD"
            clearable
            style="width: 100%"
          />
        </el-form-item>
      </el-form>
      <template #footer>
        <div class="dialog-footer">
          <el-button type="primary" @click="handleQuickCheckConfirm">确认</el-button>
          <el-button @click="closeQuickCheck">取消</el-button>
        </div>
      </template>
    </el-dialog>
    <el-dialog v-model="dialogFormVisible" title="编辑检验员" width="30%"
               @close="closeDia">
      <el-form :model="form" label-width="140px" label-position="top" :rules="rules" ref="formRef">
@@ -166,10 +199,10 @@
    width: 280,
    operation: [
      {
        name: "编辑",
        name: "检验",
        type: "text",
        clickFun: (row) => {
          openForm("edit", row);
          openQuickCheck(row);
        },
                disabled: (row) => {
                    // å·²æäº¤åˆ™ç¦ç”¨
@@ -236,6 +269,13 @@
const form = ref({
  checkName: ""
});
const quickCheckVisible = ref(false);
const quickCheckForm = ref({
  checkResult: "合格",
  checkName: "",
  checkTime: ""
});
const quickCheckRef = ref(null);
const page = reactive({
  current: 1,
  size: 100,
@@ -367,7 +407,11 @@
const open = async (row) => {
  let userLists = await userListNoPage();
  userList.value = userLists.data;
  // ç­›é€‰ roleIds åŒ…含 106 çš„用户
  userList.value = (userLists.data || []).filter(user => {
    const roleIds = user.roleIds || [];
    return roleIds.includes(106) || roleIds.includes('106');
  });
  currentRow.value = row
  dialogFormVisible.value = true
}
@@ -390,6 +434,79 @@
  })
};
// æ‰“开检验结果选择对话框
const openQuickCheck = async (row) => {
  currentRow.value = row;
  // åŠ è½½ç”¨æˆ·åˆ—è¡¨ï¼Œç­›é€‰ roleIds åŒ…含 106 çš„用户
  try {
    const userLists = await userListNoPage();
    userList.value = (userLists.data || []).filter(user => {
      const roleIds = user.roleIds || [];
      return roleIds.includes(106) || roleIds.includes('106');
    });
  } catch (e) {
    console.error("加载检验员列表失败", e);
    userList.value = [];
  }
  // è®¾ç½®é»˜è®¤å€¼ï¼ˆæ£€éªŒå‘˜é»˜è®¤ä¸ºå½“前登录用户)
  quickCheckForm.value = {
    checkResult: "合格",
    checkName: userStore.nickName || "",
    checkTime: dayjs().format("YYYY-MM-DD")
  };
  quickCheckVisible.value = true;
};
// å…³é—­æ£€éªŒç»“果选择对话框
const closeQuickCheck = () => {
  quickCheckVisible.value = false;
  quickCheckForm.value = {
    checkResult: "合格",
    checkName: "",
    checkTime: ""
  };
};
// ç¡®è®¤æ£€éªŒç»“æžœ
const handleQuickCheckConfirm = () => {
  if (!quickCheckForm.value.checkResult) {
    proxy.$modal.msgWarning("请选择检测结果");
    return;
  }
  if (!quickCheckForm.value.checkName) {
    proxy.$modal.msgWarning("请选择检验员");
    return;
  }
  if (!quickCheckForm.value.checkTime) {
    proxy.$modal.msgWarning("请选择检测日期");
    return;
  }
  if (quickCheckForm.value.checkResult === "合格") {
    // åˆæ ¼ï¼šç›´æŽ¥æäº¤
    const data = {
      id: currentRow.value.id,
      checkResult: "合格",
      checkName: quickCheckForm.value.checkName,
      checkTime: quickCheckForm.value.checkTime,
      inspectType: 0
    };
    qualityInspectUpdate(data).then(res => {
      proxy.$modal.msgSuccess("检验成功");
      closeQuickCheck();
      getList();
    });
  } else {
    // ä¸åˆæ ¼ï¼šæ‰“开详细填写页面,传递检验员信息
    // å…ˆä¿å­˜æ£€éªŒå‘˜å€¼ï¼Œé¿å… closeQuickCheck é‡ç½®åŽä¸¢å¤±
    const checkNameToPass = quickCheckForm.value.checkName;
    closeQuickCheck();
    nextTick(() => {
      formDia.value?.openDialog("edit", currentRow.value, "不合格", checkNameToPass);
    });
  }
};
onMounted(() => {
  getList();
});
src/views/salesManagement/receiptPaymentLedger/index.vue
@@ -46,6 +46,13 @@
            :formatter="formattedNumber"
          />
          <el-table-column
              label="回款金额(元)"
              prop="receiptPaymentAmount"
              show-overflow-tooltip
              :formatter="formattedNumber"
              width="200"
          />
          <el-table-column
            label="应收金额(元)"
            prop="unReceiptPaymentAmount"
            show-overflow-tooltip
@@ -101,6 +108,13 @@
                        width="200"
          />
          <el-table-column
              label="回款金额(元)"
              prop="receiptPaymentAmount"
              show-overflow-tooltip
              :formatter="formattedNumber"
              width="200"
          />
          <el-table-column
            label="应收金额(元)"
            prop="unReceiptPaymentAmount"
            show-overflow-tooltip
vite.config.js
@@ -8,11 +8,11 @@
  const { VITE_APP_ENV } = env;
  const baseUrl =
      env.VITE_APP_ENV === "development"
          ? "http://1.15.17.182:9023"
          ? "http://1.15.17.182:9038"
          : env.VITE_BASE_API;
  const javaUrl =
      env.VITE_APP_ENV === "development"
          ? "http://1.15.17.182:9023"
          ? "http://1.15.17.182:9039"
          : env.VITE_JAVA_API;
  return {
    define:{