yyb
19 小时以前 cc9a176227083c4477339452383ba3c159be55e3
添加附件管理功能,支持上传、删除和查看设备报修附件
已修改1个文件
177 ■■■■■ 文件已修改
src/views/equipmentManagement/repair/index.vue 177 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/equipmentManagement/repair/index.vue
@@ -112,6 +112,14 @@
            编辑
          </el-button>
          <el-button
            type="info"
            link
            :disabled="row.status === 1"
            @click="openAttachment(row)"
          >
            附件
          </el-button>
          <el-button
            type="success"
            link
            :disabled="row.status === 1"
@@ -132,23 +140,60 @@
    </div>
    <RepairModal ref="repairModalRef" @ok="getTableData"/>
    <MaintainModal ref="maintainModalRef" @ok="getTableData"/>
    <el-dialog v-model="attachment.visible" title="附件" width="860px" @closed="onAttachmentClosed">
      <div v-loading="attachment.loading" class="attachment-wrap">
        <div class="attachment-actions">
          <el-upload
            v-model:file-list="attachment.fileList"
            :action="upload.url"
            multiple
            ref="attachmentFileUpload"
            auto-upload
            :headers="upload.headers"
            :data="{ deviceRepairId: attachment.deviceRepairId }"
            :before-upload="handleAttachmentBeforeUpload"
            :on-error="handleAttachmentUploadError"
            :on-success="handleAttachmentUploadSuccess"
            :on-remove="handleAttachmentRemove"
            list-type="picture-card"
            :limit="9"
            accept="image/png,image/jpeg,image/jpg"
          >
            +
          </el-upload>
        </div>
        <el-empty v-if="!attachment.loading && attachment.files.length === 0" description="暂无附件" />
      </div>
      <template #footer>
        <el-button @click="attachment.visible = false">关闭</el-button>
      </template>
    </el-dialog>
  </div>
</template>
<script setup>
import { onMounted, getCurrentInstance, computed } from "vue";
import {usePaginationApi} from "@/hooks/usePaginationApi";
import {getRepairPage, delRepair} from "@/api/equipmentManagement/repair";
import {
  getRepairPage,
  delRepair,
  getRepairFileList,
  deleteRepairFile,
} from "@/api/equipmentManagement/repair";
import RepairModal from "./Modal/RepairModal.vue";
import {ElMessageBox, ElMessage} from "element-plus";
import dayjs from "dayjs";
import MaintainModal from "./Modal/MaintainModal.vue";
import { getToken } from "@/utils/auth";
defineOptions({
  name: "设备报修",
});
const {proxy} = getCurrentInstance();
const javaApi = proxy?.javaApi || "";
// 模态框实例
const repairModalRef = ref();
@@ -156,6 +201,47 @@
// 表格多选框选中项
const multipleList = ref([]);
const attachment = reactive({
  visible: false,
  loading: false,
  deviceRepairId: undefined,
  files: [],
  fileList: [],
});
const normalizeFileUrl = (rawUrl = '') => {
  let fileUrl = rawUrl || '';
  if (fileUrl && fileUrl.indexOf('\\') > -1) {
    const lowerPath = fileUrl.toLowerCase();
    const uploadPathIndex = lowerPath.indexOf('uploadpath');
    if (uploadPathIndex > -1) {
      fileUrl = fileUrl
        .substring(uploadPathIndex)
        .replace(/\\/g, '/');
    } else {
      fileUrl = fileUrl.replace(/\\/g, '/');
    }
  }
  fileUrl = fileUrl.replace(/^\/?uploadPath/, '/profile');
  if (!fileUrl.startsWith('http')) {
    if (!fileUrl.startsWith('/')) fileUrl = '/' + fileUrl;
    fileUrl = javaApi + fileUrl;
  }
  return fileUrl;
};
const attachmentUploadAction = "/device/repair/uploadFile";
const upload = reactive({
  url: import.meta.env.VITE_APP_BASE_API + attachmentUploadAction,
  headers: {
    Authorization: "Bearer " + getToken(),
  },
});
// 表格钩子
const {
@@ -326,6 +412,83 @@
      });
};
const openAttachment = async (row) => {
  attachment.fileList = [];
  attachment.visible = true;
  attachment.deviceRepairId = row?.id;
  await refreshAttachmentList();
};
const refreshAttachmentList = async () => {
  if (!attachment.deviceRepairId) return;
  attachment.loading = true;
  try {
    const res = await getRepairFileList(attachment.deviceRepairId);
    attachment.files = Array.isArray(res?.data) ? res.data : [];
    attachment.fileList = attachment.files.map((item) => ({
      id: item.id,
      name: item.name,
      url: normalizeFileUrl(item.url),
    }));
  } finally {
    attachment.loading = false;
  }
};
const onAttachmentClosed = () => {
  attachment.loading = false;
  attachment.deviceRepairId = undefined;
  attachment.files = [];
  attachment.fileList = [];
};
const handleAttachmentBeforeUpload = (file) => {
  const isImage = ["image/png", "image/jpeg", "image/jpg"].includes(file.type);
  if (!isImage) {
    ElMessage.error("只能上传 png/jpg/jpeg 图片");
    return false;
  }
  return true;
};
const handleAttachmentUploadSuccess = async (res) => {
  if (res?.code === 200) {
    ElMessage.success("上传成功");
    await refreshAttachmentList();
  }
};
const handleAttachmentUploadError = () => {
  ElMessage.error("上传失败");
};
const handleAttachmentRemove = async (file) => {
  // 仅移除前端未入库文件时,不调用删除接口
  const matched = attachment.files.find((item) => item.id === file?.id)
    || attachment.files.find((item) => item.name === file?.name);
  if (!matched) return;
  try {
    await confirmDeleteAttachment(matched);
  } finally {
    // 取消删除时,el-upload 已先移除,刷新一次保持与后端一致
    await refreshAttachmentList();
  }
};
const confirmDeleteAttachment = (fileRow) => {
  return ElMessageBox.confirm("确认删除该附件?", "警告", {
    confirmButtonText: "确定",
    cancelButtonText: "取消",
    type: "warning",
  }).then(async () => {
    const { code } = await deleteRepairFile(fileRow.id);
    if (code === 200) {
      ElMessage.success("删除成功");
      await refreshAttachmentList();
    }
  });
};
onMounted(() => {
  getTableData();
});
@@ -341,4 +504,16 @@
  justify-content: space-between;
  margin-bottom: 10px;
}
.attachment-wrap {
  min-height: 240px;
}
.attachment-actions {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 12px;
}
</style>