Thiết kế giao diện: (Chức năng chọn file được đặt bên trong hộp thoại - khi người dùng nhấn nút nhập, hộp thoại sẽ hiển thị, người dùng cần tải mẫu trước, sau đó chọn file và nhấn nút gửi để tải lên)
<div class="excel-import-container">
<el-dialog
:title="dialogTitle"
:visible.sync="showDialog"
:modal-append-to-body="false"
>
<el-upload
:ref="uploadRef"
v-loading="isUploading"
class="file-uploader"
:action="uploadUrl"
:on-preview="handlePreview"
:on-remove="handleFileRemove"
:file-list="selectedFiles"
:headers="requestHeaders"
name="document"
accept=".xlsx"
:on-error="handleUploadError"
:on-success="handleUploadSuccess"
:auto-upload="false"
:http-request="customUpload"
:on-change="onFileChange"
>
<el-button slot="trigger" size="small" type="primary">Chọn tệp</el-button>
<el-button style="margin-left: 10px;" size="small" type="success" @click="downloadTemplate">Tải mẫu</el-button>
<div slot="tip" class="el-upload__tip">Vui lòng tải mẫu trước, sau đó chọn tệp để tải lên!</div>
</el-upload>
<div slot="footer" class="dialog-footer">
<el-button class="cancel-btn" @click="cancelImport">Hủy</el-button>
<el-button type="primary" class="submit-btn" @click="submitFile">Gửi</el-button>
</div>
</el-dialog>
</div>
Chức năng tải mẫu và nhập file:
<script>
import eventBus from '@/utils/eventBus'
import { commonMixin } from '@/utils/mixins'
import { initializeData, initializeChildren } from '@/utils/helpers'
import { sendFile } from '@/api/services/dataImport'
export default {
name: 'ExcelImporter',
mixins: [commonMixin],
data() {
return {
config: {
templateUrl: '', // URL tải mẫu
importEndpoint: '' // API endpoint nhập file
},
selectedFiles: [], // Danh sách file đã chọn
showDialog: false,
requestHeaders: {
'Content-Type': 'multipart/form-data'
},
isUploading: false,
uploadUrl: '',
fileToUpload: null // File sẽ được tải lên
}
},
created() {
this.setupComponent()
},
methods: {
setupComponent() {
this.config = initializeData(this.config, this.meta)
this.children = initializeChildren(this.children, this.componentData)
},
handleFileRemove(file, fileList) {
console.log('File removed:', file, fileList)
},
handlePreview(file) {
console.log('File preview:', file)
},
handleUploadError(err, file, fileList) {
console.error('Upload error:', err)
this.$message.error('Nhập file thất bại')
},
handleUploadSuccess(response, file, fileList) {
console.log('Server response:', response.data.jsonmsg.ERRORMSG)
if (response.data.jsonmsg.ERRORMSG === '') {
this.$message({
message: 'Nhập dữ liệu thành công',
type: 'success'
})
this.setupComponent()
this.showDialog = false
} else {
const errorMsg = response.data.jsonmsg.ERRORMSG.slice(
response.data.jsonmsg.ERRORMSG.indexOf('=') + 1
)
this.$message({
message: errorMsg,
type: 'error'
})
}
},
downloadTemplate() { // Tải mẫu nhập liệu
window.location.href = process.env.VUE_APP_API_BASE + this.config.templateUrl
// process.env.VUE_APP_API_BASE: Địa chỉ cơ sở (từ file môi trường)
},
// Mở dialog nhập file
openImportDialog() {
this.showDialog = true
this.uploadUrl = process.env.VUE_APP_API_BASE + this.config.importEndpoint
// Quan trọng: phải gán giá trị này cho uploadUrl
},
onFileChange(file) {
this.fileToUpload = file.raw // Lưu file khi người dùng chọn
},
// Xử lý tải lên file
customUpload(params) {
if (this.fileToUpload) {
const formData = new FormData() // Tạo đối tượng FormData
this.fileToUpload = params.file
// Phải là params.file, dữ liệu gửi đến server sẽ là file:(binary)
// Không phải this.fileToUpload, nếu không sẽ gửi file:Undefined
formData.append('file', this.fileToUpload)
sendFile({
url: process.env.VUE_APP_API_BASE + this.config.importEndpoint,
params: formData // Tham số phải là formData
}).then(response => {
console.log('Kết quả nhập:', response)
if (response.statusCode === 200) {
this.$notify({
message: 'Nhập dữ liệu thành công',
type: 'success'
})
this.showDialog = false
eventBus.$emit('refreshData')
} else {
this.$notify.error('Nhập dữ liệu thất bại')
}
})
}
},
submitFile() {
this.$refs[this.uploadRef].submit() // Kích hoạt tải lên
},
cancelImport() {
this.showDialog = false
this.$message.info('Đã hủy thao tác tải lên')
}
}
}
</script>
Định nghĩa API:
export function sendFile(obj) {
return request({
url: obj.url,
method: 'post',
data: obj.params
})
}
Lưu ý quan trọng: Header yêu cầu phải là: Content-Type: multipart/form-data; nếu không việc nhập file sẽ thất bại. Tham số truyền đi phải là đối tượng FormData.