| | |
| | | :width="width" |
| | | :before-close="handleClose" |
| | | > |
| | | <div class="file-list-toolbar" v-if="showToolbar"> |
| | | <template v-if="useBuiltInUpload"> |
| | | <el-upload |
| | | v-model:file-list="uploadFileList" |
| | | class="upload-demo" |
| | | :action="uploadAction" |
| | | :headers="uploadHeaders" |
| | | :show-file-list="false" |
| | | :on-success="handleDefaultUploadSuccess" |
| | | :on-error="handleDefaultUploadError" |
| | | > |
| | | <el-button |
| | | v-if="showUploadButton" |
| | | type="primary" |
| | | size="small" |
| | | > |
| | | 上传附件 |
| | | </el-button> |
| | | </el-upload> |
| | | </template> |
| | | <template v-else> |
| | | <el-button |
| | | v-if="showUploadButton" |
| | | type="primary" |
| | | size="small" |
| | | @click="handleUpload" |
| | | > |
| | | 新增附件 |
| | | </el-button> |
| | | </template> |
| | | </div> |
| | | <el-table :data="tableData" border :height="tableHeight"> |
| | | <el-table-column |
| | | :label="nameColumnLabel" |
| | |
| | | > |
| | | 预览 |
| | | </el-button> |
| | | <el-button |
| | | v-if="showDeleteButton" |
| | | link |
| | | type="danger" |
| | | size="small" |
| | | @click="handleDelete(scope.row, scope.$index)" |
| | | > |
| | | 删除 |
| | | </el-button> |
| | | <slot name="actions" :row="scope.row"></slot> |
| | | </template> |
| | | </el-table-column> |
| | |
| | | |
| | | <script setup> |
| | | import { ref, computed, getCurrentInstance } from 'vue' |
| | | import { ElMessage } from 'element-plus' |
| | | import filePreview from '@/components/filePreview/index.vue' |
| | | import { getToken } from '@/utils/auth' |
| | | |
| | | const props = defineProps({ |
| | | modelValue: { |
| | |
| | | }, |
| | | actionColumnWidth: { |
| | | type: [String, Number], |
| | | default: 100 |
| | | default: 160 |
| | | }, |
| | | showActions: { |
| | | type: Boolean, |
| | |
| | | type: Boolean, |
| | | default: true |
| | | }, |
| | | showUploadButton: { |
| | | type: Boolean, |
| | | default: false |
| | | }, |
| | | showDeleteButton: { |
| | | type: Boolean, |
| | | default: false |
| | | }, |
| | | urlField: { |
| | | type: String, |
| | | default: 'url' |
| | |
| | | previewMethod: { |
| | | type: Function, |
| | | default: null |
| | | }, |
| | | uploadMethod: { |
| | | type: Function, |
| | | default: null |
| | | }, |
| | | deleteMethod: { |
| | | type: Function, |
| | | default: null |
| | | }, |
| | | rulesRegulationsManagementId: { |
| | | type: [String, Number], |
| | | default: '' |
| | | }, |
| | | uploadUrl: { |
| | | type: String, |
| | | default: `${import.meta.env.VITE_APP_BASE_API}/file/upload` |
| | | } |
| | | }) |
| | | |
| | | const emit = defineEmits(['update:modelValue', 'close', 'download', 'preview']) |
| | | const emit = defineEmits(['update:modelValue', 'close', 'download', 'preview', 'upload', 'delete']) |
| | | |
| | | const { proxy } = getCurrentInstance() |
| | | const filePreviewRef = ref(null) |
| | | const uploadFileList = ref([]) |
| | | |
| | | const dialogVisible = computed({ |
| | | get: () => props.modelValue, |
| | |
| | | }) |
| | | |
| | | const tableData = ref([]) |
| | | const showToolbar = computed(() => props.showUploadButton) |
| | | const useBuiltInUpload = computed(() => !props.uploadMethod) |
| | | const uploadAction = computed(() => props.uploadUrl) |
| | | const uploadHeaders = computed(() => ({ |
| | | Authorization: `Bearer ${getToken()}` |
| | | })) |
| | | |
| | | const handleClose = () => { |
| | | emit('close') |
| | |
| | | tableData.value = list || [] |
| | | } |
| | | |
| | | const handleUpload = async () => { |
| | | if (props.uploadMethod) { |
| | | const newItem = await props.uploadMethod() |
| | | if (newItem) { |
| | | addAttachment(newItem) |
| | | } |
| | | } |
| | | emit('upload') |
| | | } |
| | | |
| | | const handleDelete = async (row, index) => { |
| | | if (props.deleteMethod) { |
| | | const result = await props.deleteMethod(row, index) |
| | | if (result === false) { |
| | | return |
| | | } |
| | | // 如果提供了 deleteMethod,由父组件负责刷新列表,不在这里删除 |
| | | } else { |
| | | // 如果没有提供 deleteMethod,才在组件内部删除 |
| | | removeAttachment(index) |
| | | } |
| | | emit('delete', row) |
| | | } |
| | | |
| | | const addAttachment = (item) => { |
| | | tableData.value = [...tableData.value, item] |
| | | } |
| | | |
| | | const handleDefaultUploadSuccess = async (res, file) => { |
| | | if (res?.code !== 200) { |
| | | ElMessage.error(res?.msg || '文件上传失败') |
| | | return |
| | | } |
| | | if (!props.rulesRegulationsManagementId) { |
| | | ElMessage.error('缺少规章制度ID,无法保存附件') |
| | | return |
| | | } |
| | | const fileName = res?.data?.originalName || file?.name |
| | | const fileUrl = res?.data?.tempPath || res?.data?.url |
| | | const payload = { |
| | | fileName, |
| | | fileUrl, |
| | | rulesRegulationsManagementId: props.rulesRegulationsManagementId, |
| | | raw: res?.data || {} |
| | | } |
| | | emit('upload', payload) |
| | | } |
| | | |
| | | const handleDefaultUploadError = () => { |
| | | ElMessage.error('文件上传失败') |
| | | } |
| | | |
| | | const removeAttachment = (index) => { |
| | | if (index > -1 && index < tableData.value.length) { |
| | | const newList = [...tableData.value] |
| | | newList.splice(index, 1) |
| | | tableData.value = newList |
| | | } |
| | | } |
| | | |
| | | const setList = (list) => { |
| | | tableData.value = list || [] |
| | | } |
| | | |
| | | defineExpose({ |
| | | open |
| | | open, |
| | | addAttachment, |
| | | removeAttachment, |
| | | setList, |
| | | handleUpload, |
| | | handleDelete |
| | | }) |
| | | </script> |
| | | |
| | | <style scoped> |
| | | .file-list-toolbar { |
| | | margin-bottom: 8px; |
| | | text-align: right; |
| | | } |
| | | </style> |
| | | |