|
|
@@ -0,0 +1,260 @@
|
|
|
+<template>
|
|
|
+ <el-dialog
|
|
|
+ title="上传"
|
|
|
+ v-model="dialogVisible"
|
|
|
+ width="500px"
|
|
|
+ :before-close="handleClose"
|
|
|
+ :close-on-click-modal="false"
|
|
|
+ >
|
|
|
+ <div class="upload-container">
|
|
|
+ <!-- <div class="group-select">
|
|
|
+ <span style="margin-right: 10px"><span class="required">*</span>资源包类型</span>
|
|
|
+ <el-radio-group v-model="sourceType">
|
|
|
+ <el-radio value="orig">原始数据</el-radio>
|
|
|
+ <el-radio value="offline">离线包</el-radio>
|
|
|
+ </el-radio-group>
|
|
|
+ </div> -->
|
|
|
+ <div class="upload-area" style="display: flex;">
|
|
|
+ <p class="upload-title"><span class="required">*</span>文件</p>
|
|
|
+ <el-upload
|
|
|
+ class="upload-box"
|
|
|
+ action="/api/fusion/scene/uploadSceneFile"
|
|
|
+ :data="{sourceType}"
|
|
|
+ limit="1"
|
|
|
+ :headers="{Token: user.token}"
|
|
|
+ :accept="acceptType"
|
|
|
+ :on-change="handleFileChange"
|
|
|
+ :on-success="handleChange"
|
|
|
+ :on-remove="handleFileRemove"
|
|
|
+ :file-list="fileList"
|
|
|
+ >
|
|
|
+ <div class="upload-button">
|
|
|
+ <el-button type="primary">选择文件</el-button>
|
|
|
+ </div>
|
|
|
+ </el-upload>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <template #footer>
|
|
|
+ <span class="dialog-footer">
|
|
|
+ <el-button @click="handleClose">取 消</el-button>
|
|
|
+ <el-button type="primary" :disabled="!filePath" @click="handleUpload">确 定</el-button>
|
|
|
+ </span>
|
|
|
+ </template>
|
|
|
+ </el-dialog>
|
|
|
+</template>
|
|
|
+
|
|
|
+<script setup lang="ts">
|
|
|
+import { ref, defineEmits, defineProps, computed } from 'vue';
|
|
|
+import { ElMessage } from 'element-plus';
|
|
|
+import { uploadNewMedia } from '@/store/mediaLibrary';
|
|
|
+import { user } from "@/store/user";
|
|
|
+import { uploadScene } from "@/store/scene";
|
|
|
+const props = defineProps({
|
|
|
+ visible: {
|
|
|
+ type: Boolean,
|
|
|
+ default: false
|
|
|
+ },
|
|
|
+ groupList: {
|
|
|
+ type: Array,
|
|
|
+ default: () => []
|
|
|
+ }
|
|
|
+});
|
|
|
+
|
|
|
+const selectedGroup = ref('');
|
|
|
+const sourceType = ref('orig');
|
|
|
+const filePath = ref(null);
|
|
|
+const emit = defineEmits(['update:visible', 'refresh']);
|
|
|
+const acceptType = computed(() => {
|
|
|
+ if (selectedGroup.value == 1) {
|
|
|
+ return '.obj,.glb,.zip';
|
|
|
+ } else {
|
|
|
+ return '.jpg,.png,.jpeg,.mp4,.wav,.mp3,.shp,.zip';
|
|
|
+ }
|
|
|
+});
|
|
|
+const dialogVisible = computed({
|
|
|
+ get: () => props.visible,
|
|
|
+ set: (val) => emit('update:visible', val)
|
|
|
+});
|
|
|
+
|
|
|
+const fileList = ref([]);
|
|
|
+const changeGroup = (value) => {
|
|
|
+ fileList.value = [];
|
|
|
+};
|
|
|
+// 处理文件变化
|
|
|
+const handleChange = (file, files) => {
|
|
|
+ if(file.data){
|
|
|
+ // 检查文件类型和大小
|
|
|
+ filePath.value = file.data?.url;
|
|
|
+ } else {
|
|
|
+ ElMessage.error(file.message || `不支持的文件类型`);
|
|
|
+ files.status = 'fail'
|
|
|
+ fileList.value = [];
|
|
|
+ filePath.value = null;
|
|
|
+ }
|
|
|
+};
|
|
|
+
|
|
|
+// 处理文件变化
|
|
|
+const handleFileChange = (file, files) => {
|
|
|
+ if(file){
|
|
|
+ // 检查文件类型和大小
|
|
|
+ const isValidFile = validateFile(file);
|
|
|
+ if (!isValidFile) {
|
|
|
+ // 如果文件无效,从文件列表中移除
|
|
|
+ const index = files.indexOf(file);
|
|
|
+ if (index !== -1) {
|
|
|
+ files.splice(index, 1);
|
|
|
+ }
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ fileList.value = [];
|
|
|
+ filePath.value = null;
|
|
|
+ }
|
|
|
+};
|
|
|
+
|
|
|
+// 验证文件类型和大小
|
|
|
+const validateFile = (file) => {
|
|
|
+ if (!file || !file.raw) return false;
|
|
|
+
|
|
|
+ const fileName = file.name || '';
|
|
|
+ const fileSize = file.size || 0;
|
|
|
+ const fileExt = fileName.split('.').pop().toLowerCase();
|
|
|
+
|
|
|
+ // 检查文件类型
|
|
|
+ // 模型库组只允许 obj、glb、zip 格式
|
|
|
+ if (!['obj', 'glb', 'zip'].includes(fileExt)) {
|
|
|
+ ElMessage.error(`不支持的文件类型`);
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 检查文件大小,不能超过 5MB
|
|
|
+ const maxSize = 5 * 1024 * 1024; // 5MB
|
|
|
+ if (fileSize > maxSize) {
|
|
|
+ ElMessage.error(`上传文件不能超过 5MB`);
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ return true;
|
|
|
+};
|
|
|
+
|
|
|
+// 处理文件删除
|
|
|
+const handleFileRemove = (file, fileList) => {
|
|
|
+ filePath.value = '';
|
|
|
+};
|
|
|
+
|
|
|
+// 关闭弹窗
|
|
|
+const handleClose = () => {
|
|
|
+ dialogVisible.value = false;
|
|
|
+ selectedGroup.value = '';
|
|
|
+ fileList.value = [];
|
|
|
+};
|
|
|
+
|
|
|
+// 上传文件
|
|
|
+const handleUpload = async () => {
|
|
|
+ if (!filePath.value) {
|
|
|
+ ElMessage.warning('请选择要上传的文件');
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ try {
|
|
|
+ // 这里实现文件上传逻辑
|
|
|
+ const formData = new FormData();
|
|
|
+ formData.append('dictId', selectedGroup.value);
|
|
|
+
|
|
|
+ fileList.value.forEach(file => {
|
|
|
+ formData.append('file', file.raw);
|
|
|
+ });
|
|
|
+
|
|
|
+ await uploadScene({sourceType: sourceType.value, filePath: filePath.value});
|
|
|
+
|
|
|
+ ElMessage.success('上传成功');
|
|
|
+ handleClose();
|
|
|
+ emit('refresh');
|
|
|
+ } catch (error) {
|
|
|
+ console.error('上传失败:', error);
|
|
|
+ }
|
|
|
+};
|
|
|
+</script>
|
|
|
+
|
|
|
+<style lang="scss" scoped>
|
|
|
+.upload-container {
|
|
|
+ padding: 0 20px;
|
|
|
+ max-height: 600px;
|
|
|
+ overflow-y: auto;
|
|
|
+ :deep(.el-upload-list__item-info){
|
|
|
+ min-width: 300px;
|
|
|
+ max-width: 360px;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+.group-select {
|
|
|
+ margin-bottom: 20px;
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+
|
|
|
+ .required {
|
|
|
+ color: #f56c6c;
|
|
|
+ margin-right: 5px;
|
|
|
+ }
|
|
|
+
|
|
|
+ .el-select {
|
|
|
+ margin-left: 10px;
|
|
|
+ width: 200px;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+.upload-area {
|
|
|
+ margin-bottom: 20px;
|
|
|
+ .upload-box{
|
|
|
+ width: calc(100% - 100px);
|
|
|
+ }
|
|
|
+ .upload-title{
|
|
|
+ line-height: 40px;
|
|
|
+ // padding-left: 10px;
|
|
|
+ min-width: 40px;
|
|
|
+ margin-left: 40px;
|
|
|
+ margin-right: 10px;;
|
|
|
+ }
|
|
|
+ .required{
|
|
|
+ color: #f56c6c;
|
|
|
+ margin-right: 5px;
|
|
|
+ }
|
|
|
+ .upload-button {
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+
|
|
|
+ span {
|
|
|
+ margin-right: 10px;
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+.upload-tips {
|
|
|
+ .tip-item {
|
|
|
+ margin-bottom: 15px;
|
|
|
+
|
|
|
+ .tip-number {
|
|
|
+ font-weight: bold;
|
|
|
+ margin-bottom: 5px;
|
|
|
+ display: inline-block;
|
|
|
+ }
|
|
|
+
|
|
|
+ .tip-content {
|
|
|
+ margin-bottom: 5px;
|
|
|
+ color: #606266;
|
|
|
+ font-size: 14px;
|
|
|
+ }
|
|
|
+
|
|
|
+ .tip-example {
|
|
|
+ margin-top: 5px;
|
|
|
+ border: 1px solid #ebeef5;
|
|
|
+ padding: 10px;
|
|
|
+ background-color: #f5f7fa;
|
|
|
+
|
|
|
+ img {
|
|
|
+ max-width: 100%;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+</style>
|