gongchunyi
8 天以前 25372b64f4ac756bd44cc730af87b1c46e6b9f77
src/views/equipmentManagement/repair/Modal/MaintainModal.vue
@@ -1,53 +1,226 @@
<template>
  <el-drawer v-model="visible" :title="modalOptions.title" direction="ltr">
    <MaintainForm ref="maintainFormRef" />
    <template #footer>
         <el-button type="primary" @click="sendForm" :loading="loading">
            {{ modalOptions.confirmText }}
         </el-button>
      <el-button @click="closeModal">{{ modalOptions.cancelText }}</el-button>
    </template>
  </el-drawer>
  <FormDialog
    v-model="visible"
    title="设备维修"
    width="640px"
    :loading="loading"
    @confirm="sendForm"
    @cancel="handleCancel"
    @close="handleClose"
  >
    <el-form ref="formRef" :model="form" :rules="rules" label-width="90px">
      <el-form-item label="维修人" prop="maintenanceName">
        <el-input
          v-model="form.maintenanceName"
          :placeholder="isEditableMaintenanceName ? '请输入维修人姓名' : '报修时指定的维修人'"
          :disabled="!isEditableMaintenanceName"
        />
      </el-form-item>
      <el-form-item label="维修结果" prop="maintenanceResult">
        <el-input
          v-model="form.maintenanceResult"
          type="textarea"
          :autosize="{ minRows: 2, maxRows: 6 }"
          placeholder="请输入维修结果"
        />
      </el-form-item>
      <el-form-item label="维修状态" prop="status">
        <el-select v-model="form.status" style="width: 100%">
          <el-option label="待验收" :value="3" />
          <el-option label="维修失败" :value="2" />
        </el-select>
      </el-form-item>
      <el-form-item label="维修日期" prop="maintenanceTime">
        <el-date-picker
          v-model="form.maintenanceTime"
          placeholder="请选择维修日期"
          format="YYYY-MM-DD HH:mm:ss"
          value-format="YYYY-MM-DD HH:mm:ss"
          type="datetime"
          clearable
          style="width: 100%"
        />
      </el-form-item>
      <el-form-item label="附件">
        <el-upload
          class="repair-attachment-upload"
          v-model:file-list="attachmentFileList"
          drag
          multiple
          :auto-upload="false"
          :limit="9"
          accept="image/png,image/jpeg,image/jpg"
          :before-upload="beforeAttachmentUpload"
        >
          <el-icon class="repair-upload-icon"><UploadFilled /></el-icon>
          <div class="el-upload__text">将文件拖到此处,或 <em>点击选择文件</em></div>
          <template #tip>
            <div class="el-upload__tip">
              支持 png / jpg / jpeg,单个不超过 50MB,保存后与列表「附件」同步
            </div>
          </template>
        </el-upload>
      </el-form-item>
    </el-form>
  </FormDialog>
</template>
<script setup>
import { useModal } from "@/hooks/useModal";
import MaintainForm from "../Form/MaintainForm.vue";
import { addMaintain } from "@/api/equipmentManagement/repair";
import { computed } from "vue";
import FormDialog from "@/components/Dialog/FormDialog.vue";
import { addMaintain, uploadRepairFile } from "@/api/equipmentManagement/repair";
import { REPAIR_FILE_TYPE_MAINTAIN } from "@/api/equipmentManagement/repairFileType.js";
import useFormData from "@/hooks/useFormData";
import useUserStore from "@/store/modules/user";
import { userListNoPage } from "@/api/system/user.js";
import dayjs from "dayjs";
import { ElMessage } from "element-plus";
import { UploadFilled } from "@element-plus/icons-vue";
defineOptions({
  name: "维修模态框",
});
const maintainFormRef = ref();
const emits = defineEmits(["ok"]);
const {
  id,
  visible,
  loading,
  openModal,
  modalOptions,
  handleConfirm,
  closeModal,
} = useModal({ title: "设备维修" });
const repairId = ref();
const visible = ref(false);
const loading = ref(false);
const formRef = ref();
const attachmentFileList = ref([]);
const ATTACH_MAX_MB = 50;
const userStore = useUserStore();
const systemUserNames = ref([]);
const isSystemUser = (name) => {
  return systemUserNames.value.includes(name);
};
//  维修人是否可编辑:外部人员时可以编辑修改
const isEditableMaintenanceName = computed(() => {
  const name = form.maintenanceName;
  if (!name) return false;
  return !isSystemUser(name);
});
const loadSystemUsers = async () => {
  const res = await userListNoPage();
  systemUserNames.value = (res?.data || []).map((u) => u.nickName);
};
const rules = {
  maintenanceName: [{ required: true, message: "请选择维修人", trigger: "change" }],
  maintenanceResult: [{ required: true, message: "请输入维修结果", trigger: "blur" }],
  maintenanceTime: [{ required: true, message: "请选择维修日期", trigger: "change" }],
};
const { form, resetForm } = useFormData({
  maintenanceName: undefined,
  maintenanceResult: undefined,
  maintenanceTime: dayjs().format("YYYY-MM-DD HH:mm:ss"),
  status: 3,
});
const syncMaintenanceNameFromRow = (row) => {
  form.maintenanceName = row?.maintenanceName || "";
};
const beforeAttachmentUpload = (rawFile) => {
  const okType = ["image/jpeg", "image/jpg", "image/png"].includes(rawFile.type);
  if (!okType) {
    ElMessage.error("只能上传 png / jpg / jpeg 图片");
    return false;
  }
  if (rawFile.size > ATTACH_MAX_MB * 1024 * 1024) {
    ElMessage.error(`单个文件不能超过 ${ATTACH_MAX_MB}MB`);
    return false;
  }
  return true;
};
const clearAttachmentQueue = () => {
  attachmentFileList.value = [];
};
const uploadQueuedImages = async (id) => {
  const files = (attachmentFileList.value || []).map((f) => f.raw).filter(Boolean);
  for (const file of files) {
    const fd = new FormData();
    fd.append("file", file);
    fd.append("deviceRepairId", String(id));
    fd.append("fileType", String(REPAIR_FILE_TYPE_MAINTAIN));
    const res = await uploadRepairFile(fd);
    if (res.code !== 200) {
      throw new Error(res.msg || "附件上传失败");
    }
  }
};
const setForm = (data) => {
  syncMaintenanceNameFromRow(data);
  form.maintenanceResult = data.maintenanceResult;
  form.maintenanceTime = data.maintenanceTime
    ? dayjs(data.maintenanceTime).format("YYYY-MM-DD HH:mm:ss")
    : dayjs().format("YYYY-MM-DD HH:mm:ss");
  form.status = 3;
};
const sendForm = async () => {
  loading.value = true;
  const form = await maintainFormRef.value.getForm();
  const { code } = await addMaintain({ id: id.value, ...form });
  if (code == 200) {
    emits("ok");
    maintainFormRef.value.resetForm();
    closeModal();
  const valid = await formRef.value?.validate().catch(() => false);
  if (!valid) return;
  const maintenanceName = form.maintenanceName;
  // 如果维修人是系统用户且非当前用户,禁止提交
  if (isSystemUser(maintenanceName) && maintenanceName !== userStore.nickName) {
    ElMessage.warning("仅指定的维修人可进行维修");
    return;
  }
  loading.value = false;
  loading.value = true;
  try {
    const { code, msg } = await addMaintain({ id: repairId.value, ...form });
    if (code !== 200) {
      if (msg) ElMessage.error(msg);
      return;
    }
    if (attachmentFileList.value.length) {
      await uploadQueuedImages(repairId.value);
    }
    ElMessage.success("维修成功");
    clearAttachmentQueue();
    visible.value = false;
    emits("ok");
  } catch (e) {
    ElMessage.error(e?.message || "保存或上传附件失败");
  } finally {
    loading.value = false;
  }
};
const handleCancel = () => {
  resetForm();
  clearAttachmentQueue();
  visible.value = false;
};
const handleClose = () => {
  resetForm();
  clearAttachmentQueue();
  visible.value = false;
};
const open = async (id, row) => {
  openModal(id);
  repairId.value = id;
  clearAttachmentQueue();
  visible.value = true;
  await nextTick();
  maintainFormRef.value.setForm(row);
  await loadSystemUsers();
  setForm(row);
  const maintenanceName = row?.maintenanceName;
  // 如果维修人是系统用户且非当前用户,禁止操作
  if (isSystemUser(maintenanceName) && maintenanceName !== userStore.nickName) {
    ElMessage.warning("仅指定的维修人可进行维修");
    visible.value = false;
  }
};
defineExpose({
@@ -55,4 +228,20 @@
});
</script>
<style lang="scss" scoped></style>
<style lang="scss" scoped>
.repair-attachment-upload {
  width: 100%;
  :deep(.el-upload) {
    width: 100%;
  }
  :deep(.el-upload-dragger) {
    width: 100%;
    padding: 20px 16px;
  }
}
.repair-upload-icon {
  font-size: 42px;
  color: var(--el-color-primary);
  margin-bottom: 8px;
}
</style>