Commit b2c6363f075d7ea72db9fb4c9bef6bc93fef42c1

Authored by fengwotao
1 parent 0d4c0edf

perf(external/Composes): 三维模型新增可以自定义上传

1 -import { defHttp } from "@/utils/external/http/axios";  
2 -import { DictItem, UploadResponse } from "./model"; 1 +import { defHttp } from '@/utils/external/http/axios'
  2 +import { DictItem, UploadResponse } from './model'
3 3
4 enum Api { 4 enum Api {
5 GET_DICT = '/dict_item', 5 GET_DICT = '/dict_item',
6 - UPLOAD = '/oss/upload' 6 + UPLOAD = '/oss/upload',
  7 + DOWNLOAD = '/oss/download_file/'
7 } 8 }
8 9
9 export const getDictItemByCode = (value: string) => { 10 export const getDictItemByCode = (value: string) => {
@@ -21,3 +22,7 @@ export const upload = (file: FormData) => { @@ -21,3 +22,7 @@ export const upload = (file: FormData) => {
21 params: file 22 params: file
22 }) 23 })
23 } 24 }
  25 +
  26 +export const downloadFile = (fileName: string) => {
  27 + return defHttp.get({ url: `${Api.DOWNLOAD}${fileName}` })
  28 +}
@@ -6,7 +6,7 @@ import { chartInitConfig } from '@/settings/designSetting' @@ -6,7 +6,7 @@ import { chartInitConfig } from '@/settings/designSetting'
6 6
7 export const option = { 7 export const option = {
8 //vue3dLoader支持数组或字符串,暂且绑定字符串,这个插件可以加载多个模型 8 //vue3dLoader支持数组或字符串,暂且绑定字符串,这个插件可以加载多个模型
9 - dataset: 'src/assets/external/models/fbx/宿舍楼.fbx', 9 + dataset: '',
10 backgroundColor: '', //场景背景色 10 backgroundColor: '', //场景背景色
11 backgroundAlpha: 0, //场景透明度 11 backgroundAlpha: 0, //场景透明度
12 enableDamping: false, //是否启用阻尼 12 enableDamping: false, //是否启用阻尼
1 <template> 1 <template>
2 - <collapse-item name="三维静态路径" :expanded="true">  
3 - <setting-item-box>  
4 - <setting-item name="路径"> 2 + <collapse-item name="三维配置" :expanded="true">
  3 + <setting-item-box name="文件上传" :alone="true">
  4 + <setting-item :name="fileSizeMsg">
  5 + <n-upload
  6 + :max="1"
  7 + :customRequest="customRequest"
  8 + :onBeforeUpload="beforeUploadHandle"
  9 + :default-file-list="defaultFileList"
  10 + >
  11 + <n-button> 上传文件</n-button>
  12 + </n-upload>
  13 + </setting-item>
  14 + </setting-item-box>
  15 + <setting-item-box name="静态路径">
  16 + <setting-item>
5 <n-select 17 <n-select
6 @change="handlePathChange" 18 @change="handlePathChange"
7 style="width: 12vw" 19 style="width: 12vw"
@@ -12,9 +24,7 @@ @@ -12,9 +24,7 @@
12 ></n-select> 24 ></n-select>
13 </setting-item> 25 </setting-item>
14 </setting-item-box> 26 </setting-item-box>
15 - </collapse-item>  
16 - <collapse-item name="三维配置属性" :expanded="true">  
17 - <setting-item-box> 27 + <setting-item-box name="属性配置">
18 <setting-item name="场景色(需要这种格式HEX #000000,否则失效)"> 28 <setting-item name="场景色(需要这种格式HEX #000000,否则失效)">
19 <n-color-picker size="small" :show-alpha="false" v-model:value="optionData.backgroundColor"></n-color-picker> 29 <n-color-picker size="small" :show-alpha="false" v-model:value="optionData.backgroundColor"></n-color-picker>
20 </setting-item> 30 </setting-item>
@@ -24,19 +34,6 @@ @@ -24,19 +34,6 @@
24 <SettingItem name="启用阻尼"> 34 <SettingItem name="启用阻尼">
25 <n-switch v-model:value="optionData.enableDamping" size="small" /> 35 <n-switch v-model:value="optionData.enableDamping" size="small" />
26 </SettingItem> 36 </SettingItem>
27 - <!-- <SettingItem name="选择灯光">  
28 - <setting-item name="灯光">  
29 - <n-select  
30 - @change="handleLightChange"  
31 - v-model:value="selectLight"  
32 - size="small"  
33 - :options="lightList"  
34 - ></n-select>  
35 - </setting-item>  
36 - <setting-item name="灯光颜色选择">  
37 - <n-color-picker size="small" :show-alpha="false" v-model:value="lightColor"></n-color-picker>  
38 - </setting-item>  
39 - </SettingItem> -->  
40 <SettingItem v-if="optionData.enableDamping" name="阻尼值"> 37 <SettingItem v-if="optionData.enableDamping" name="阻尼值">
41 <n-input-number v-model:value="optionData.dampingFactor" :min="0" :max="1" size="small"></n-input-number> 38 <n-input-number v-model:value="optionData.dampingFactor" :min="0" :max="1" size="small"></n-input-number>
42 </SettingItem> 39 </SettingItem>
@@ -54,10 +51,13 @@ @@ -54,10 +51,13 @@
54 </template> 51 </template>
55 52
56 <script setup lang="ts"> 53 <script setup lang="ts">
57 -import { PropType, h, ref, watch } from 'vue' 54 +import { PropType, h, ref, nextTick } from 'vue'
58 import { option } from './config' 55 import { option } from './config'
59 import { CollapseItem, SettingItemBox, SettingItem } from '@/components/Pages/ChartItemSetting' 56 import { CollapseItem, SettingItemBox, SettingItem } from '@/components/Pages/ChartItemSetting'
60 -import { NEllipsis, NInputNumber, NSelect, NSpace, SelectOption } from 'naive-ui' 57 +import { NEllipsis, NInputNumber, NSelect, NSpace, SelectOption, NCard } from 'naive-ui'
  58 +import { uploadFile } from '@/api/external/contentSave/content'
  59 +import { downloadFile } from '@/api/external/common'
  60 +import { UploadCustomRequestOptions } from 'naive-ui'
61 61
62 const props = defineProps({ 62 const props = defineProps({
63 optionData: { 63 optionData: {
@@ -66,6 +66,11 @@ const props = defineProps({ @@ -66,6 +66,11 @@ const props = defineProps({
66 } 66 }
67 }) 67 })
68 68
  69 +const defaultFileList = ref([])
  70 +
  71 +//文件限制大小
  72 +const fileSizeConst = ref(15)
  73 +
69 const handleChange = (e: boolean) => { 74 const handleChange = (e: boolean) => {
70 if (e) props.optionData.dataset = '' 75 if (e) props.optionData.dataset = ''
71 } 76 }
@@ -79,44 +84,6 @@ const encodinghList = [ @@ -79,44 +84,6 @@ const encodinghList = [
79 { label: 'sRGB ', value: 'sRGB ' } 84 { label: 'sRGB ', value: 'sRGB ' }
80 ] 85 ]
81 86
82 -/**  
83 -环境光(AmbientLight) | 方向光(DirectionalLight) | 点光(PointLight) | 半球光(HemisphereLight)  
84 -暂且支持 环境光  
85 - */  
86 -const lightList = [  
87 - {  
88 - type: 'AmbientLight',  
89 - value: 'AmbientLight',  
90 - label: '环境光'  
91 - }  
92 -]  
93 -  
94 -const selectLight = ref('')  
95 -  
96 -const lightColor = ref('')  
97 -  
98 -const lightChange = (type: string, color: string) => {  
99 - props.optionData.lights = [  
100 - {  
101 - type,  
102 - color  
103 - }  
104 - ] as any  
105 -}  
106 -  
107 -const handleLightChange = (e: string) => {  
108 - selectLight.value = e  
109 - lightChange(e, lightColor.value)  
110 -}  
111 -  
112 -watch(  
113 - () => lightColor.value,  
114 - newValue => {  
115 - lightChange(selectLight.value, newValue)  
116 - }  
117 -)  
118 -  
119 -//TODO:三维静态路径地址,无法通过import.meta.globEager来引入,要报错,待优化  
120 const pathList = [ 87 const pathList = [
121 { 88 {
122 label: '猫模型', 89 label: '猫模型',
@@ -167,4 +134,55 @@ const renderOption = (option: SelectOption) => { @@ -167,4 +134,55 @@ const renderOption = (option: SelectOption) => {
167 h(NEllipsis, null, () => option.label) 134 h(NEllipsis, null, () => option.label)
168 ]) 135 ])
169 } 136 }
  137 +
  138 +const fileSizeMsg = ref(`文件需小于 ${fileSizeConst.value}M ,格式为${threeSupportFileFormat.join(',')}的文件`)
  139 +
  140 +const extname = (filename: string) => {
  141 + if (!filename || typeof filename != 'string') {
  142 + return false
  143 + }
  144 + let a = filename.split('').reverse().join('')
  145 + let b = a.substring(0, a.search(/\./)).split('').reverse().join('')
  146 + return b
  147 +}
  148 +
  149 +// 上传图片前置处理
  150 +// eslint-disable-next-line @typescript-eslint/ban-ts-comment
  151 +//@ts-ignore
  152 +const beforeUploadHandle = async ({ file }) => {
  153 + defaultFileList.value = []
  154 + const type = extname(file.file.name) as string
  155 + const size = file.file.size
  156 + if (size / (1024 * 1024) > fileSizeConst.value) {
  157 + window['$message'].warning(`文件超出 ${fileSizeConst.value}M限制,请重新上传!`)
  158 + return false
  159 + }
  160 + if (!threeSupportFileFormat.includes(type)) {
  161 + window['$message'].warning('文件格式不符合,请重新上传!')
  162 + return false
  163 + }
  164 + return true
  165 +}
  166 +
  167 +// 自定义上传操作
  168 +const customRequest = (options: UploadCustomRequestOptions) => {
  169 + const { file } = options
  170 + nextTick(async () => {
  171 + if (file.file) {
  172 + const formData = new FormData()
  173 + formData.append('file', file.file)
  174 + const uploadRes = await uploadFile(formData)
  175 + if (uploadRes) {
  176 + props.optionData.dataset = uploadRes?.fileStaticUri
  177 + const res = await downloadFile(uploadRes?.fileName)
  178 + console.log(res)
  179 + window['$message'].success('上传文件成功!')
  180 + }
  181 + } else {
  182 + window['$message'].error('上传文件失败,请稍后重试!')
  183 + }
  184 + })
  185 +}
170 </script> 186 </script>
  187 +
  188 +<style lang="scss" scoped></style>
1 <template> 1 <template>
2 <div class="go-content-box"> 2 <div class="go-content-box">
3 - <!-- fix: 预览三维图像需加上preserveDrawingBuffer: true -->  
4 <div v-if="supportWebGL"> 3 <div v-if="supportWebGL">
5 <vue3dLoader 4 <vue3dLoader
6 ref="vue3dLoaderRef" 5 ref="vue3dLoaderRef"
@@ -15,7 +14,7 @@ @@ -15,7 +14,7 @@
15 :outputEncoding="outputEncoding" 14 :outputEncoding="outputEncoding"
16 :clearScene="clearScene" 15 :clearScene="clearScene"
17 :dampingFactor="dampingFactor" 16 :dampingFactor="dampingFactor"
18 - :labels="labels" 17 + :intersectRecursive="true"
19 @process="onProcess" 18 @process="onProcess"
20 @load="onLoad" 19 @load="onLoad"
21 @click="onClick" 20 @click="onClick"
@@ -54,48 +53,10 @@ const vue3dLoaderRef = ref(null) @@ -54,48 +53,10 @@ const vue3dLoaderRef = ref(null)
54 const webGLRendererOptions = { 53 const webGLRendererOptions = {
55 alpha: true, // 透明 54 alpha: true, // 透明
56 antialias: true, // 抗锯齿 55 antialias: true, // 抗锯齿
  56 + // fix: 预览三维图像需加上preserveDrawingBuffer: true
57 preserveDrawingBuffer: true //缩略图生效需开启 57 preserveDrawingBuffer: true //缩略图生效需开启
58 } 58 }
59 59
60 -//标注示例可以多个支持图片和文字  
61 -const labels = ref()  
62 -labels.value = [  
63 - {  
64 - text: 'co2浓度:44',  
65 - position: { x: 0, y: 18, z: 0 },  
66 - scale: { x: 11.5, y: 10.8, z: 30.5 },  
67 - textStyle: {  
68 - fontFamily: 'Arial',  
69 - fontSize: 12,  
70 - fontWeight: 600,  
71 - lineHeight: 1,  
72 - color: '#ffffff',  
73 - borderWidth: 8,  
74 - borderRadius: 0,  
75 - borderColor: '#000000',  
76 - backgroundColor: 'rgba(0,0,0,1)'  
77 - },  
78 - sid: 3 // 自定义标识,可有可无  
79 - },  
80 - {  
81 - text: '氧气浓度:100',  
82 - position: { x: 10, y: 18, z: 0 },  
83 - scale: { x: 11.5, y: 10.8, z: 30.5 },  
84 - textStyle: {  
85 - fontFamily: 'Arial',  
86 - fontSize: 12,  
87 - fontWeight: 600,  
88 - lineHeight: 1,  
89 - color: '#ffffff',  
90 - borderWidth: 8,  
91 - borderRadius: 0,  
92 - borderColor: '#000000',  
93 - backgroundColor: 'rgba(0,0,0,1)'  
94 - },  
95 - sid: 4 // 自定义标识,可有可无  
96 - }  
97 -]  
98 -  
99 //三维模型加载 60 //三维模型加载
100 const show = ref(true) 61 const show = ref(true)
101 62
@@ -109,7 +70,7 @@ const onLoad = async () => { @@ -109,7 +70,7 @@ const onLoad = async () => {
109 const process = ref(0) 70 const process = ref(0)
110 71
111 const onProcess = (event: any) => { 72 const onProcess = (event: any) => {
112 - process.value= Math.floor((event.loaded / event.total) * 100) 73 + process.value = Math.floor((event.loaded / event.total) * 100)
113 } 74 }
114 75
115 const onClick = (event: any) => { 76 const onClick = (event: any) => {