upload-modal.vue 5.34 KB
<template>
    <section class="upload-modal" v-show="isUploadModalVisible">
        <Card :title="$t('uploadfile')" customClass="upload-modal-card">
            <template v-slot:extend>
                <el-icon class="icon" :size="24" @click="onCloseModal">
                    <Close />
                </el-icon>
            </template>
            <template v-slot:component>
                <el-upload
                    class="upload-demo"
                    ref="uploadRef"
                    action="#"
                    drag
                    multiple
                    accept=".stl,.stx,.pts"
                    :before-upload="beforeUpload"
                    :http-request="httpRequest"
                    :on-remove="onRemove"
                >
                    <el-icon class="el-icon--upload"><upload-filled /></el-icon>
                    <div class="el-upload__text">
                        <div v-text="$t('uploadText')" />
                        <div class="upload-limit-text" v-text="$t('uploadLimitText')" />
                    </div>
                </el-upload>
                <div class="button">
                    <span class="button-hollow" @click="onCloseModal">
                        {{ $t('cancel') }}
                    </span>
                    <span class="button-big" @click="onLoadModel">
                        {{ $t('upload') }}
                    </span>
                </div>
            </template>
        </Card>
    </section>
</template>
<script setup>
import { useI18n } from 'vue-i18n';
import { ref, watch } from 'vue';
import { storeToRefs } from 'pinia';
import Card from '@/components/simple-card.vue';
import { useCanvasHeaderToolsStore } from '@/views/stores/header/useCanvasHeaderToolsStore';
import { useLoadSceneModelStore } from '@/views/stores/useLoadSceneModelStore';
import { Close, UploadFilled } from '@element-plus/icons-vue';
import { ElMessage } from 'element-plus';

const i18n = useI18n();

const store = useCanvasHeaderToolsStore();
const { isUploadModalVisible } = storeToRefs(store);
const { setUploadModalVisible } = store;

const loadStore = useLoadSceneModelStore();
const { loadScene } = loadStore;

const uploadRef = ref();
const files = ref([]);
const uploadlistVisible = ref('none');

const beforeUpload = (file) => {
    const isStl =
        file.name.includes('.stl') ||
        file.name.includes('.stx') ||
        file.name.includes('.STL') ||
        file.name.includes('.STX') ||
        file.name.includes('.pts') ||
        file.name.includes('.PTS');
    return isStl;
};

const httpRequest = (data) => {
    if (!data) return;
    const { file } = data;
    files.value.push(file);
};

const onRemove = (uploadFile, uploadFiles) => {
    const fileList = [];
    uploadFiles.forEach((el) => {
        fileList.push(el.raw);
    });
    files.value = [...fileList];
};

const onCloseModal = () => {
    setUploadModalVisible(false);
    files.value = [];
    uploadRef.value.clearFiles();
};

const roundTo = (number = 0.0, decimal = 2) => {
    return Math.round((number * Math.pow(10, decimal)).toPrecision(15)) / Math.pow(10, decimal);
};

const isFilesSizeExceed = (allfiles) => {
    let isSizeExceed = false;
    allfiles.forEach((el) => {
        const size = roundTo(el.size / 1024 / 1000, 3);
        if (size > 100) {
            isSizeExceed = true;
        }
    });
    return isSizeExceed;
};

const onLoadModel = () => {
    if (files.value.length > 0) {
        const isExceed = isFilesSizeExceed(files.value);
        if (isExceed) {
            ElMessage.error(i18n.t('uploadFilesSizeExceed'));
            return;
        }
        if (files.value.length > 5) {
            ElMessage.error(i18n.t('uploadFilesNumberExceed'));
            return;
        }
        loadScene(files.value);
    }
    onCloseModal();
};

watch(
    () => files.value.length,
    (length) => {
        uploadlistVisible.value = length > 0 ? 'block' : 'none';
    }
);
</script>
<style lang="less" scoped>
.upload-modal-card {
    position: absolute;
    background-color: #fff;
    box-shadow: 1px 1px 1px 1px rgba(0, 0, 0, 0.1);
    border: 1px solid #cdd1d5;
    top: 40%;
    left: 50%;
    -webkit-transform: translate(-50%, -50%);
    transform: translate(-50%, -50%);
    z-index: 200;
    width: calc(480px * 943 / 1008) !important;
    :deep(.el-upload-list__item .el-icon--close) {
        display: unset;
    }
    :deep(.el-upload-list) {
        overflow-y: auto;
        height: 140px;
        display: v-bind('uploadlistVisible');
        top: 10px;
    }
    .icon {
        cursor: pointer;
        &:hover {
            background-color: rgb(246, 247, 248);
        }
        &:active {
            background-color: #eef0f2;
        }
    }
    .upload-limit-text {
        color: #c0c1c2;
        font-weight: 400 !important;
        font-size: 14px !important;
    }
    .button {
        display: flex;
        justify-content: space-between;
        button-big {
            &:hover {
                background-color: @color-button-main-hover;
            }
            &:active {
                background-color: @color-button-main-active;
            }
        }
    }
}
.upload-demo {
    padding: 16px 0;
}
</style>

<style lang="less">
.upload-modal-card.card {
    padding: 22px !important;
    .header .title {
        margin: 0px;
        font-size: 20px;
        line-height: 34px;
        font-weight: 700;
    }
}
</style>