PhysicalLibraryWeb/src/views/common/DataResourcePanel.vue

280 lines
8.3 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<div class="resource-panel">
<div class="toolbar" v-if="showToolbar">
<el-button type="primary" :icon="Upload" @click="openUploadDialog">上传文件</el-button>
<el-button type="success" :icon="Link" @click="openCloudDialog">指定云资源路径</el-button>
</div>
<el-table :data="fileData" border style="width: 100%">
<el-table-column prop="file_name" label="资源名称" min-width="180" />
<el-table-column prop="source_type" label="来源类型" width="110">
<template #default="scope">
<el-tag :type="scope.row.source_type === 'cloud' ? 'success' : 'primary'" size="small">
{{ scope.row.source_type === 'cloud' ? '云资源' : '本地上传' }}
</el-tag>
</template>
</el-table-column>
<el-table-column prop="file_path" label="路径" min-width="260" show-overflow-tooltip />
<el-table-column prop="file_size" label="文件大小" width="120">
<template #default="scope">
{{ formatFileSize(scope.row.file_size) }}
</template>
</el-table-column>
<el-table-column prop="create_time" label="添加时间" width="170" />
<el-table-column label="操作" width="100" align="center">
<template #default="scope">
<el-popconfirm
confirm-button-text="确定"
cancel-button-text="取消"
title="是否确认删除?"
@confirm="handleDelete(scope.row.id)"
>
<template #reference>
<el-button link type="danger" size="small">删除</el-button>
</template>
</el-popconfirm>
</template>
</el-table-column>
</el-table>
<el-empty v-if="!fileData.length" description="暂无数据资源,请上传文件或指定云资源路径" />
<!-- 上传文件弹窗 -->
<el-dialog v-model="uploadDialogVisible" title="上传文件" width="520" destroy-on-close>
<el-form label-width="90px">
<el-form-item label="选择文件">
<el-upload
ref="uploadRef"
drag
:auto-upload="false"
:limit="1"
:on-change="handleFileChange"
:on-remove="handleFileRemove"
>
<el-icon class="upload-icon"><Upload /></el-icon>
<div class="el-upload__text">将文件拖到此处,或<em>点击上传</em></div>
<template #tip>
<div class="el-upload__tip">支持 raw、sgy、nc、csv 等地球物理数据格式</div>
</template>
</el-upload>
</el-form-item>
<el-form-item label="备注">
<el-input v-model="uploadRemark" type="textarea" :rows="2" placeholder="可选,填写文件说明" />
</el-form-item>
</el-form>
<template #footer>
<el-button @click="uploadDialogVisible = false">取消</el-button>
<el-button type="primary" :loading="uploadLoading" @click="confirmUpload">确认上传</el-button>
</template>
</el-dialog>
<!-- 云资源路径弹窗 -->
<el-dialog v-model="cloudDialogVisible" title="指定云资源路径" width="560" destroy-on-close>
<el-form ref="cloudFormRef" :model="cloudForm" :rules="cloudRules" label-width="110px">
<el-form-item label="云资源路径" prop="cloud_path">
<el-input
v-model="cloudForm.cloud_path"
placeholder="例如s3://geodata-bucket/seismic/2024/data.sgy"
/>
</el-form-item>
<el-form-item label="资源名称" prop="resource_name">
<el-input v-model="cloudForm.resource_name" placeholder="可选,默认取路径末尾文件名" />
</el-form-item>
<el-form-item label="存储类型">
<el-select v-model="cloudForm.storage_type" style="width: 100%">
<el-option label="对象存储 (S3/OSS)" value="object" />
<el-option label="NAS 共享目录" value="nas" />
<el-option label="HDFS" value="hdfs" />
</el-select>
</el-form-item>
<el-form-item label="说明">
<el-input v-model="cloudForm.remark" type="textarea" :rows="2" placeholder="可选,填写云资源说明" />
</el-form-item>
</el-form>
<template #footer>
<el-button @click="cloudDialogVisible = false">取消</el-button>
<el-button type="primary" :loading="cloudLoading" @click="confirmCloudPath">确认添加</el-button>
</template>
</el-dialog>
</div>
</template>
<script setup>
import { ref, reactive, watch, onMounted } from 'vue'
import { Upload, Link } from '@element-plus/icons-vue'
import { ElMessage } from 'element-plus'
import { dataFileList, dataFileUpload, dataCloudPathAdd, dataFileDelete } from '@/api/data.js'
const props = defineProps({
dataId: {
type: [String, Number],
default: ''
},
showToolbar: {
type: Boolean,
default: true
}
})
const emit = defineEmits(['updated'])
const fileData = ref([])
const uploadDialogVisible = ref(false)
const cloudDialogVisible = ref(false)
const uploadLoading = ref(false)
const cloudLoading = ref(false)
const uploadRemark = ref('')
const selectedFile = ref(null)
const cloudFormRef = ref(null)
const cloudForm = reactive({
cloud_path: '',
resource_name: '',
storage_type: 'object',
remark: ''
})
const cloudRules = {
cloud_path: [{ required: true, message: '请输入云资源路径', trigger: 'blur' }]
}
/**
* 格式化文件大小
* @param {number} bytes
* @returns {string}
*/
const formatFileSize = (bytes) => {
if (!bytes) return '—'
const k = 1024
const sizes = ['B', 'KB', 'MB', 'GB', 'TB']
const i = Math.floor(Math.log(bytes) / Math.log(k))
return `${parseFloat((bytes / Math.pow(k, i)).toFixed(2))} ${sizes[i]}`
}
const loadFileList = () => {
if (!props.dataId) {
fileData.value = []
return
}
dataFileList({ data_id: props.dataId }).then((res) => {
fileData.value = res.array || []
})
}
const ensureDataId = () => {
if (!props.dataId) {
ElMessage.warning('请先保存数据基本信息')
return false
}
return true
}
const openUploadDialog = () => {
if (!ensureDataId()) return
selectedFile.value = null
uploadRemark.value = ''
uploadDialogVisible.value = true
}
const openCloudDialog = () => {
if (!ensureDataId()) return
cloudForm.cloud_path = ''
cloudForm.resource_name = ''
cloudForm.storage_type = 'object'
cloudForm.remark = ''
cloudDialogVisible.value = true
}
const handleFileChange = (file) => {
selectedFile.value = file.raw
}
const handleFileRemove = () => {
selectedFile.value = null
}
const confirmUpload = () => {
if (!selectedFile.value) {
ElMessage.warning('请选择要上传的文件')
return
}
uploadLoading.value = true
dataFileUpload({
data_id: props.dataId,
file_name: selectedFile.value.name,
file_size: selectedFile.value.size
}).then((res) => {
uploadLoading.value = false
if (res.success) {
ElMessage.success('文件上传成功')
uploadDialogVisible.value = false
loadFileList()
emit('updated')
} else {
ElMessage.error(res.message || '上传失败')
}
})
}
const confirmCloudPath = async () => {
if (!cloudFormRef.value) return
await cloudFormRef.value.validate((valid) => {
if (!valid) return
cloudLoading.value = true
dataCloudPathAdd({
data_id: props.dataId,
cloud_path: cloudForm.cloud_path,
resource_name: cloudForm.resource_name
}).then((res) => {
cloudLoading.value = false
if (res.success) {
ElMessage.success('云资源路径添加成功')
cloudDialogVisible.value = false
loadFileList()
emit('updated')
} else {
ElMessage.error(res.message || '添加失败')
}
})
})
}
const handleDelete = (fileId) => {
dataFileDelete({ data_id: props.dataId, file_id: fileId }).then(() => {
ElMessage.success('删除成功')
loadFileList()
emit('updated')
})
}
watch(() => props.dataId, () => {
loadFileList()
})
onMounted(() => {
loadFileList()
})
defineExpose({
openUploadDialog,
openCloudDialog,
loadFileList
})
</script>
<style lang="scss" scoped>
.resource-panel {
.toolbar {
display: flex;
gap: 12px;
margin-bottom: 16px;
}
.upload-icon {
font-size: 48px;
color: #909399;
margin-bottom: 8px;
}
}
</style>