huminmin
2026-04-30 60654abe9a108c9007646d4f2b6ea78863539c9f
src/components/Dialog/FileList.vue
@@ -5,7 +5,8 @@
             @close="handleClose"
             class="attachment-dialog">
    <!-- 工具栏 -->
    <div class="toolbar">
    <div v-if="editable"
         class="toolbar">
      <el-button type="primary"
                 size="small"
                 @click="handleUpload">
@@ -13,12 +14,11 @@
      </el-button>
    </div>
    <!-- 上传组件弹窗 -->
    <el-dialog
        v-model="uploadDialogVisible"
        title="上传附件"
        width="50%"
        @close="closeUpload">
      <AttachmentUpload v-model:file-list="newFileList"/>
    <el-dialog v-model="uploadDialogVisible"
               title="上传附件"
               width="50%"
               @close="closeUpload">
      <AttachmentUpload v-model:file-list="newFileList" />
      <template #footer>
        <el-button @click="saveUpload">保存</el-button>
        <el-button @click="closeUpload">关闭</el-button>
@@ -32,7 +32,7 @@
                :height="tableData.length > 0 ? 'auto' : '120px'">
        <el-table-column label="附件名称"
                         prop="originalFilename"
                         show-overflow-tooltip/>
                         show-overflow-tooltip />
        <el-table-column v-if="showActions"
                         fixed="right"
                         label="操作"
@@ -46,7 +46,8 @@
                       @click="downloadFile(scope.row.downloadURL)">
              下载
            </el-button>
            <el-button link
            <el-button v-if="editable"
                       link
                       type="danger"
                       size="small"
                       @click="handleDelete(scope.row)">
@@ -60,181 +61,185 @@
</template>
<script setup>
import {ref, computed, getCurrentInstance, onMounted, watch} from "vue";
import AttachmentUpload from "@/components/AttachmentUpload/file/index.vue";
import {
  attachmentList,
  deleteAttachment,
  createAttachment,
} from "@/api/basicData/storageAttachment.js";
  import { ref, computed, getCurrentInstance, onMounted, watch } from "vue";
  import AttachmentUpload from "@/components/AttachmentUpload/file/index.vue";
  import {
    attachmentList,
    deleteAttachment,
    createAttachment,
  } from "@/api/basicData/storageAttachment.js";
const props = defineProps({
  visible: {
    type: Boolean,
    required: true,
  },
  recordType: {
    type: String,
    default: "",
    required: true,
  },
  recordId: {
    type: Number,
    default: 0,
    required: true,
  },
  title: {
    type: String,
    default: "附件",
  },
  width: {
    type: String,
    default: "50%",
  },
  showActions: {
    type: Boolean,
    default: true,
  },
});
  const props = defineProps({
    visible: {
      type: Boolean,
      required: true,
    },
    recordType: {
      type: String,
      default: "",
      required: true,
    },
    recordId: {
      type: Number,
      default: 0,
      required: true,
    },
    title: {
      type: String,
      default: "附件",
    },
    width: {
      type: String,
      default: "50%",
    },
    showActions: {
      type: Boolean,
      default: true,
    },
    editable: {
      type: Boolean,
      default: true,
    },
  });
const emit = defineEmits(["close", "download", "upload", "delete"]);
  const emit = defineEmits(["close", "download", "upload", "delete"]);
const {proxy} = getCurrentInstance();
const tableData = ref([]);
const uploadDialogVisible = ref(false);
const newFileList = ref([]);
  const { proxy } = getCurrentInstance();
  const tableData = ref([]);
  const uploadDialogVisible = ref(false);
  const newFileList = ref([]);
const isShow = computed({
  get() {
    return props.visible;
  },
  set(val) {
    emit("update:visible", val);
  },
});
  const isShow = computed({
    get() {
      return props.visible;
    },
    set(val) {
      emit("update:visible", val);
    },
  });
const handleClose = () => {
  isShow.value = false;
};
  const handleClose = () => {
    isShow.value = false;
  };
const handleUpload = () => {
  uploadDialogVisible.value = true;
};
  const handleUpload = () => {
    uploadDialogVisible.value = true;
  };
const saveUpload = async () => {
  // 检查是否有新上传的文件
  if (newFileList.value.length > 0) {
  const saveUpload = async () => {
    // 检查是否有新上传的文件
    if (newFileList.value.length > 0) {
      try {
        await createAttachment({
          application: "file",
          recordType: props.recordType,
          recordId: props.recordId,
          storageBlobDTOs: [...newFileList.value, ...tableData.value],
        });
        newFileList.value = [];
        // 刷新列表
        setList();
      } catch (error) {
        proxy?.$modal?.msgError("上传失败");
      }
    }
    uploadDialogVisible.value = false;
  };
  const closeUpload = () => {
    newFileList.value = [];
    uploadDialogVisible.value = false;
  };
  const handleDelete = async (row, index) => {
    try {
      await createAttachment({
        application: "file",
        recordType: props.recordType,
        recordId: props.recordId,
        storageBlobDTOs: [...newFileList.value, ...tableData.value],
      });
      newFileList.value = [];
      // 刷新列表
      await deleteAttachment([row.storageAttachmentId]);
      proxy?.$modal?.msgSuccess("删除成功");
      setList();
    } catch (error) {
      proxy?.$modal?.msgError("上传失败");
      proxy?.$modal?.msgError("删除失败");
    }
  }
  uploadDialogVisible.value = false;
};
  };
const closeUpload = () => {
  newFileList.value = [];
  uploadDialogVisible.value = false;
}
  const setList = () => {
    attachmentList({
      recordType: props.recordType,
      recordId: props.recordId,
    }).then(res => {
      if (res && res.data) {
        tableData.value = res.data || [];
      }
    });
  };
const handleDelete = async (row, index) => {
  try {
    await deleteAttachment([row.storageAttachmentId]);
    proxy?.$modal?.msgSuccess("删除成功");
  const downloadFile = url => {
    window.open(url, "_blank");
  };
  onMounted(() => {
    setList();
  } catch (error) {
    proxy?.$modal?.msgError("删除失败");
  }
};
const setList = () => {
  attachmentList({
    recordType: props.recordType,
    recordId: props.recordId,
  }).then(res => {
    if (res && res.data) {
      tableData.value = res.data || [];
    }
  });
};
const downloadFile = (url) => {
  window.open(url, "_blank");
};
onMounted(() => {
  setList();
});
</script>
<style scoped>
.attachment-dialog {
  border-radius: 12px;
}
  .attachment-dialog {
    border-radius: 12px;
  }
.toolbar {
  margin-bottom: 16px;
  text-align: right;
}
  .toolbar {
    margin-bottom: 16px;
    text-align: right;
  }
.table-container {
  max-height: 40vh;
  overflow-y: auto;
  min-height: 120px;
  padding-bottom: 16px;
  box-sizing: border-box;
  will-change: scroll-position;
  transform: translateZ(0);
  -webkit-overflow-scrolling: touch;
}
  .table-container {
    max-height: 40vh;
    overflow-y: auto;
    min-height: 120px;
    padding-bottom: 16px;
    box-sizing: border-box;
    will-change: scroll-position;
    transform: translateZ(0);
    -webkit-overflow-scrolling: touch;
  }
:deep(.el-table) {
  margin-bottom: 0;
}
  :deep(.el-table) {
    margin-bottom: 0;
  }
:deep(.el-table__body-wrapper) {
  overflow-y: auto;
  will-change: transform;
  transform: translateZ(0);
}
  :deep(.el-table__body-wrapper) {
    overflow-y: auto;
    will-change: transform;
    transform: translateZ(0);
  }
:deep(.el-table__body tr) {
  transition: none;
}
  :deep(.el-table__body tr) {
    transition: none;
  }
:deep(.el-dialog__footer) {
  padding-top: 12px;
  border-top: 1px solid #e9ecef;
}
  :deep(.el-dialog__footer) {
    padding-top: 12px;
    border-top: 1px solid #e9ecef;
  }
.attachment-table {
  border-radius: 8px;
}
  .attachment-table {
    border-radius: 8px;
  }
:deep(.el-dialog__header) {
  background-color: #f8f9fa;
  border-bottom: 1px solid #e9ecef;
  padding: 16px 20px;
}
  :deep(.el-dialog__header) {
    background-color: #f8f9fa;
    border-bottom: 1px solid #e9ecef;
    padding: 16px 20px;
  }
:deep(.el-dialog__title) {
  font-size: 16px;
  font-weight: 600;
}
  :deep(.el-dialog__title) {
    font-size: 16px;
    font-weight: 600;
  }
:deep(.el-dialog__body) {
  padding: 16px 20px;
}
  :deep(.el-dialog__body) {
    padding: 16px 20px;
  }
:deep(.el-table__empty-text) {
  color: #999;
}
  :deep(.el-table__empty-text) {
    color: #999;
  }
</style>