Commit d9b910cfc47c166935302886fa6772f941202f78

Authored by xp.Huang
2 parents 8e32c5d6 9cfda80c

Merge branch 'feat/threejs-editor/10-11/2024' into 'main_dev'

feat(src/packages): 大屏3D编辑器,支持列表预览跟3D自定义组件加载

See merge request yunteng/thingskit-view!291
Showing 60 changed files with 2438 additions and 598 deletions
... ... @@ -3,5 +3,6 @@ node_modules
3 3 dist
4 4 dist-ssr
5 5 *.local
  6 +*.zip
6 7 .vscode
7 8 .idea
... ...
... ... @@ -37,6 +37,8 @@
37 37 <script type="module" src="./js/libs/ternjs/doc_comment.js"></script>
38 38 <script type="module" src="./js/libs/tern-threejs/threejs.js"></script>
39 39 <script type="module" src="./js/libs/signals.min.js"></script>
  40 + <script type="module" src="./js/libs/axios.min.js"></script>
  41 + <script type="module" src="./js/libs/http/config.js"></script>
40 42
41 43 <script src="./main.js" type="module"></script>
42 44 </body>
... ...
1   -import { UIPanel, UIRow, UIHorizontalRule } from './libs/ui.js';
  1 +import { UIPanel, UIRow, UIHorizontalRule } from './libs/ui.js'
  2 +import useMessage from './MessageDialog.js'
  3 +import { saveOrUpdateThreeJsModel } from './libs/http/api.js'
  4 +
  5 +function MenubarFile(editor) {
  6 + const strings = editor.strings
  7 +
  8 + const saveArrayBuffer = editor.utils.saveArrayBuffer
  9 + const saveString = editor.utils.saveString
  10 +
  11 + const container = new UIPanel()
  12 + container.setClass('menu')
  13 +
  14 + const title = new UIPanel()
  15 + title.setClass('title')
  16 + title.setTextContent(strings.getKey('menubar/file'))
  17 + container.add(title)
  18 +
  19 + const options = new UIPanel()
  20 + options.setClass('options')
  21 + container.add(options)
  22 +
  23 + // New Project
  24 +
  25 + const newProjectSubmenuTitle = new UIRow()
  26 + .setTextContent(strings.getKey('menubar/file/new'))
  27 + .addClass('option')
  28 + .addClass('submenu-title')
  29 + newProjectSubmenuTitle.onMouseOver(function () {
  30 + const { top, right } = this.dom.getBoundingClientRect()
  31 + const { paddingTop } = getComputedStyle(this.dom)
  32 + newProjectSubmenu.setLeft(right + 'px')
  33 + newProjectSubmenu.setTop(top - parseFloat(paddingTop) + 'px')
  34 + newProjectSubmenu.setDisplay('block')
  35 + })
  36 + newProjectSubmenuTitle.onMouseOut(function () {
  37 + newProjectSubmenu.setDisplay('none')
  38 + })
  39 + options.add(newProjectSubmenuTitle)
  40 +
  41 + const newProjectSubmenu = new UIPanel().setPosition('fixed').addClass('options').setDisplay('none')
  42 + newProjectSubmenuTitle.add(newProjectSubmenu)
  43 +
  44 + // New Project / Empty
  45 +
  46 + let option = new UIRow().setTextContent(strings.getKey('menubar/file/new/empty')).setClass('option')
  47 + option.onClick(function () {
  48 + if (confirm(strings.getKey('prompt/file/open'))) {
  49 + editor.clear()
  50 + }
  51 + })
  52 + newProjectSubmenu.add(option)
  53 +
  54 + //
  55 +
  56 + newProjectSubmenu.add(new UIHorizontalRule())
  57 +
  58 + // New Project / ...
  59 +
  60 + const examples = [
  61 + { title: 'menubar/file/new/Arkanoid', file: 'arkanoid.app.json' },
  62 + { title: 'menubar/file/new/Camera', file: 'camera.app.json' },
  63 + { title: 'menubar/file/new/Particles', file: 'particles.app.json' },
  64 + { title: 'menubar/file/new/Pong', file: 'pong.app.json' },
  65 + { title: 'menubar/file/new/Shaders', file: 'shaders.app.json' }
  66 + ]
  67 +
  68 + const loader = new THREE.FileLoader()
  69 +
  70 + for (let i = 0; i < examples.length; i++) {
  71 + ;(function (i) {
  72 + const example = examples[i]
  73 +
  74 + const option = new UIRow()
  75 + option.setClass('option')
  76 + option.setTextContent(strings.getKey(example.title))
  77 + option.onClick(function () {
  78 + if (confirm(strings.getKey('prompt/file/open'))) {
  79 + loader.load('examples/' + example.file, function (text) {
  80 + editor.clear()
  81 + editor.fromJSON(JSON.parse(text))
  82 + })
  83 + }
  84 + })
  85 + newProjectSubmenu.add(option)
  86 + })(i)
  87 + }
  88 +
  89 + // Open
  90 +
  91 + const openProjectForm = document.createElement('form')
  92 + openProjectForm.style.display = 'none'
  93 + document.body.appendChild(openProjectForm)
  94 +
  95 + const openProjectInput = document.createElement('input')
  96 + openProjectInput.multiple = false
  97 + openProjectInput.type = 'file'
  98 + openProjectInput.accept = '.json'
  99 + openProjectInput.addEventListener('change', async function () {
  100 + const file = openProjectInput.files[0]
  101 +
  102 + if (file === undefined) return
  103 +
  104 + try {
  105 + const json = JSON.parse(await file.text())
  106 +
  107 + async function onEditorCleared() {
  108 + await editor.fromJSON(json)
  109 +
  110 + editor.signals.editorCleared.remove(onEditorCleared)
  111 + }
  112 +
  113 + editor.signals.editorCleared.add(onEditorCleared)
  114 +
  115 + editor.clear()
  116 + } catch (e) {
  117 + alert(strings.getKey('prompt/file/failedToOpenProject'))
  118 + console.error(e)
  119 + } finally {
  120 + form.reset()
  121 + }
  122 + })
  123 +
  124 + openProjectForm.appendChild(openProjectInput)
  125 +
  126 + option = new UIRow()
  127 + .addClass('option')
  128 + .setTextContent(strings.getKey('menubar/file/open'))
  129 + .onClick(function () {
  130 + if (confirm(strings.getKey('prompt/file/open'))) {
  131 + openProjectInput.click()
  132 + }
  133 + })
  134 +
  135 + options.add(option)
  136 +
  137 + /**
  138 + * THINGS_KIT 修改
  139 + */
  140 + option = new UIRow()
  141 + .addClass('option')
  142 + .setTextContent(strings.getKey('menubar/file/save'))
  143 + .onClick(async function () {
  144 + const file_json = editor.toJSON()
  145 + const paramsStr = window.location.search
  146 + const params = new URLSearchParams(paramsStr)
  147 + const file_uuid = params.get('three_file_uuid')
  148 + await saveOrUpdateThreeJsModel({
  149 + id: file_uuid,
  150 + data: file_json
  151 + })
  152 + const { success } = useMessage()
  153 + success('保存成功')
  154 + })
  155 + options.add(option)
  156 +
  157 + // // Save
  158 +
  159 + // option = new UIRow()
  160 + // .addClass( 'option' )
  161 + // .setTextContent( strings.getKey( 'menubar/file/save' ) )
  162 + // .onClick( function () {
  163 +
  164 + // const json = editor.toJSON();
  165 + // const blob = new Blob( [ JSON.stringify( json ) ], { type: 'application/json' } );
  166 + // editor.utils.save( blob, 'project.json' );
  167 +
  168 + // } );
  169 +
  170 + // options.add( option );
  171 +
  172 + // //
  173 +
  174 + options.add(new UIHorizontalRule())
  175 +
  176 + // Import
  177 +
  178 + const form = document.createElement('form')
  179 + form.style.display = 'none'
  180 + document.body.appendChild(form)
  181 +
  182 + const fileInput = document.createElement('input')
  183 + fileInput.multiple = true
  184 + fileInput.type = 'file'
  185 + fileInput.addEventListener('change', function () {
  186 + editor.loader.loadFiles(fileInput.files)
  187 + form.reset()
  188 + })
  189 + form.appendChild(fileInput)
  190 +
  191 + option = new UIRow()
  192 + option.setClass('option')
  193 + option.setTextContent(strings.getKey('menubar/file/import'))
  194 + option.onClick(function () {
  195 + fileInput.click()
  196 + })
  197 + options.add(option)
  198 +
  199 + // Export
  200 +
  201 + const fileExportSubmenuTitle = new UIRow()
  202 + .setTextContent(strings.getKey('menubar/file/export'))
  203 + .addClass('option')
  204 + .addClass('submenu-title')
  205 + fileExportSubmenuTitle.onMouseOver(function () {
  206 + const { top, right } = this.dom.getBoundingClientRect()
  207 + const { paddingTop } = getComputedStyle(this.dom)
  208 + fileExportSubmenu.setLeft(right + 'px')
  209 + fileExportSubmenu.setTop(top - parseFloat(paddingTop) + 'px')
  210 + fileExportSubmenu.setDisplay('block')
  211 + })
  212 + fileExportSubmenuTitle.onMouseOut(function () {
  213 + fileExportSubmenu.setDisplay('none')
  214 + })
  215 + options.add(fileExportSubmenuTitle)
  216 +
  217 + const fileExportSubmenu = new UIPanel().setPosition('fixed').addClass('options').setDisplay('none')
  218 + fileExportSubmenuTitle.add(fileExportSubmenu)
  219 +
  220 + // Export DRC
  221 +
  222 + option = new UIRow()
  223 + option.setClass('option')
  224 + option.setTextContent('DRC')
  225 + option.onClick(async function () {
  226 + const object = editor.selected
  227 +
  228 + if (object === null || object.isMesh === undefined) {
  229 + alert(strings.getKey('prompt/file/export/noMeshSelected'))
  230 + return
  231 + }
  232 +
  233 + const { DRACOExporter } = await import('three/addons/exporters/DRACOExporter.js')
  234 +
  235 + const exporter = new DRACOExporter()
  236 +
  237 + const options = {
  238 + decodeSpeed: 5,
  239 + encodeSpeed: 5,
  240 + encoderMethod: DRACOExporter.MESH_EDGEBREAKER_ENCODING,
  241 + quantization: [16, 8, 8, 8, 8],
  242 + exportUvs: true,
  243 + exportNormals: true,
  244 + exportColor: object.geometry.hasAttribute('color')
  245 + }
  246 +
  247 + // TODO: Change to DRACOExporter's parse( geometry, onParse )?
  248 + const result = exporter.parse(object, options)
  249 + saveArrayBuffer(result, 'model.drc')
  250 + })
  251 + fileExportSubmenu.add(option)
  252 +
  253 + // Export GLB
  254 +
  255 + option = new UIRow()
  256 + option.setClass('option')
  257 + option.setTextContent('GLB')
  258 + option.onClick(async function () {
  259 + const scene = editor.scene
  260 + const animations = getAnimations(scene)
  261 +
  262 + const optimizedAnimations = []
  263 +
  264 + for (const animation of animations) {
  265 + optimizedAnimations.push(animation.clone().optimize())
  266 + }
  267 +
  268 + const { GLTFExporter } = await import('three/addons/exporters/GLTFExporter.js')
  269 +
  270 + const exporter = new GLTFExporter()
  271 +
  272 + exporter.parse(
  273 + scene,
  274 + function (result) {
  275 + saveArrayBuffer(result, 'scene.glb')
  276 + },
  277 + undefined,
  278 + { binary: true, animations: optimizedAnimations }
  279 + )
  280 + })
  281 + fileExportSubmenu.add(option)
  282 +
  283 + // Export GLTF
  284 +
  285 + option = new UIRow()
  286 + option.setClass('option')
  287 + option.setTextContent('GLTF')
  288 + option.onClick(async function () {
  289 + const scene = editor.scene
  290 + const animations = getAnimations(scene)
  291 +
  292 + const optimizedAnimations = []
  293 +
  294 + for (const animation of animations) {
  295 + optimizedAnimations.push(animation.clone().optimize())
  296 + }
  297 +
  298 + const { GLTFExporter } = await import('three/addons/exporters/GLTFExporter.js')
  299 +
  300 + const exporter = new GLTFExporter()
  301 +
  302 + exporter.parse(
  303 + scene,
  304 + function (result) {
  305 + saveString(JSON.stringify(result, null, 2), 'scene.gltf')
  306 + },
  307 + undefined,
  308 + { animations: optimizedAnimations }
  309 + )
  310 + })
  311 + fileExportSubmenu.add(option)
  312 +
  313 + // Export OBJ
2 314
3   -function MenubarFile( editor ) {
  315 + option = new UIRow()
  316 + option.setClass('option')
  317 + option.setTextContent('OBJ')
  318 + option.onClick(async function () {
  319 + const object = editor.selected
4 320
5   - const strings = editor.strings;
  321 + if (object === null) {
  322 + alert(strings.getKey('prompt/file/export/noObjectSelected'))
  323 + return
  324 + }
6 325
7   - const saveArrayBuffer = editor.utils.saveArrayBuffer;
8   - const saveString = editor.utils.saveString;
  326 + const { OBJExporter } = await import('three/addons/exporters/OBJExporter.js')
9 327
10   - const container = new UIPanel();
11   - container.setClass( 'menu' );
  328 + const exporter = new OBJExporter()
12 329
13   - const title = new UIPanel();
14   - title.setClass( 'title' );
15   - title.setTextContent( strings.getKey( 'menubar/file' ) );
16   - container.add( title );
  330 + saveString(exporter.parse(object), 'model.obj')
  331 + })
  332 + fileExportSubmenu.add(option)
17 333
18   - const options = new UIPanel();
19   - options.setClass( 'options' );
20   - container.add( options );
  334 + // Export PLY (ASCII)
21 335
22   - // New Project
  336 + option = new UIRow()
  337 + option.setClass('option')
  338 + option.setTextContent('PLY')
  339 + option.onClick(async function () {
  340 + const { PLYExporter } = await import('three/addons/exporters/PLYExporter.js')
23 341
24   - const newProjectSubmenuTitle = new UIRow().setTextContent( strings.getKey( 'menubar/file/new' ) ).addClass( 'option' ).addClass( 'submenu-title' );
25   - newProjectSubmenuTitle.onMouseOver( function () {
  342 + const exporter = new PLYExporter()
26 343
27   - const { top, right } = this.dom.getBoundingClientRect();
28   - const { paddingTop } = getComputedStyle( this.dom );
29   - newProjectSubmenu.setLeft( right + 'px' );
30   - newProjectSubmenu.setTop( top - parseFloat( paddingTop ) + 'px' );
31   - newProjectSubmenu.setDisplay( 'block' );
  344 + exporter.parse(editor.scene, function (result) {
  345 + saveArrayBuffer(result, 'model.ply')
  346 + })
  347 + })
  348 + fileExportSubmenu.add(option)
32 349
33   - } );
34   - newProjectSubmenuTitle.onMouseOut( function () {
  350 + // Export PLY (BINARY)
35 351
36   - newProjectSubmenu.setDisplay( 'none' );
  352 + option = new UIRow()
  353 + option.setClass('option')
  354 + option.setTextContent('PLY (BINARY)')
  355 + option.onClick(async function () {
  356 + const { PLYExporter } = await import('three/addons/exporters/PLYExporter.js')
37 357
38   - } );
39   - options.add( newProjectSubmenuTitle );
  358 + const exporter = new PLYExporter()
40 359
41   - const newProjectSubmenu = new UIPanel().setPosition( 'fixed' ).addClass( 'options' ).setDisplay( 'none' );
42   - newProjectSubmenuTitle.add( newProjectSubmenu );
  360 + exporter.parse(
  361 + editor.scene,
  362 + function (result) {
  363 + saveArrayBuffer(result, 'model-binary.ply')
  364 + },
  365 + { binary: true }
  366 + )
  367 + })
  368 + fileExportSubmenu.add(option)
43 369
44   - // New Project / Empty
  370 + // Export STL (ASCII)
45 371
46   - let option = new UIRow().setTextContent( strings.getKey( 'menubar/file/new/empty' ) ).setClass( 'option' );
47   - option.onClick( function () {
  372 + option = new UIRow()
  373 + option.setClass('option')
  374 + option.setTextContent('STL')
  375 + option.onClick(async function () {
  376 + const { STLExporter } = await import('three/addons/exporters/STLExporter.js')
48 377
49   - if ( confirm( strings.getKey( 'prompt/file/open' ) ) ) {
  378 + const exporter = new STLExporter()
50 379
51   - editor.clear();
  380 + saveString(exporter.parse(editor.scene), 'model.stl')
  381 + })
  382 + fileExportSubmenu.add(option)
52 383
53   - }
  384 + // Export STL (BINARY)
54 385
55   - } );
56   - newProjectSubmenu.add( option );
  386 + option = new UIRow()
  387 + option.setClass('option')
  388 + option.setTextContent('STL (BINARY)')
  389 + option.onClick(async function () {
  390 + const { STLExporter } = await import('three/addons/exporters/STLExporter.js')
57 391
58   - //
  392 + const exporter = new STLExporter()
59 393
60   - newProjectSubmenu.add( new UIHorizontalRule() );
  394 + saveArrayBuffer(exporter.parse(editor.scene, { binary: true }), 'model-binary.stl')
  395 + })
  396 + fileExportSubmenu.add(option)
61 397
62   - // New Project / ...
  398 + // Export USDZ
63 399
64   - const examples = [
65   - { title: 'menubar/file/new/Arkanoid', file: 'arkanoid.app.json' },
66   - { title: 'menubar/file/new/Camera', file: 'camera.app.json' },
67   - { title: 'menubar/file/new/Particles', file: 'particles.app.json' },
68   - { title: 'menubar/file/new/Pong', file: 'pong.app.json' },
69   - { title: 'menubar/file/new/Shaders', file: 'shaders.app.json' }
70   - ];
  400 + option = new UIRow()
  401 + option.setClass('option')
  402 + option.setTextContent('USDZ')
  403 + option.onClick(async function () {
  404 + const { USDZExporter } = await import('three/addons/exporters/USDZExporter.js')
71 405
72   - const loader = new THREE.FileLoader();
  406 + const exporter = new USDZExporter()
73 407
74   - for ( let i = 0; i < examples.length; i ++ ) {
  408 + saveArrayBuffer(await exporter.parseAsync(editor.scene), 'model.usdz')
  409 + })
  410 + fileExportSubmenu.add(option)
75 411
76   - ( function ( i ) {
  412 + //
77 413
78   - const example = examples[ i ];
  414 + function getAnimations(scene) {
  415 + const animations = []
79 416
80   - const option = new UIRow();
81   - option.setClass( 'option' );
82   - option.setTextContent( strings.getKey( example.title ) );
83   - option.onClick( function () {
  417 + scene.traverse(function (object) {
  418 + animations.push(...object.animations)
  419 + })
84 420
85   - if ( confirm( strings.getKey( 'prompt/file/open' ) ) ) {
86   -
87   - loader.load( 'examples/' + example.file, function ( text ) {
88   -
89   - editor.clear();
90   - editor.fromJSON( JSON.parse( text ) );
91   -
92   - } );
93   -
94   - }
95   -
96   - } );
97   - newProjectSubmenu.add( option );
98   -
99   - } )( i );
100   -
101   - }
102   -
103   - // Open
104   -
105   - const openProjectForm = document.createElement( 'form' );
106   - openProjectForm.style.display = 'none';
107   - document.body.appendChild( openProjectForm );
108   -
109   - const openProjectInput = document.createElement( 'input' );
110   - openProjectInput.multiple = false;
111   - openProjectInput.type = 'file';
112   - openProjectInput.accept = '.json';
113   - openProjectInput.addEventListener( 'change', async function () {
114   -
115   - const file = openProjectInput.files[ 0 ];
116   -
117   - if ( file === undefined ) return;
118   -
119   - try {
120   -
121   - const json = JSON.parse( await file.text() );
122   -
123   - async function onEditorCleared() {
124   -
125   - await editor.fromJSON( json );
126   -
127   - editor.signals.editorCleared.remove( onEditorCleared );
128   -
129   - }
130   -
131   - editor.signals.editorCleared.add( onEditorCleared );
132   -
133   - editor.clear();
134   -
135   - } catch ( e ) {
136   -
137   - alert( strings.getKey( 'prompt/file/failedToOpenProject' ) );
138   - console.error( e );
139   -
140   - } finally {
141   -
142   - form.reset();
143   -
144   - }
145   -
146   - } );
147   -
148   - openProjectForm.appendChild( openProjectInput );
149   -
150   - option = new UIRow()
151   - .addClass( 'option' )
152   - .setTextContent( strings.getKey( 'menubar/file/open' ) )
153   - .onClick( function () {
154   -
155   - if ( confirm( strings.getKey( 'prompt/file/open' ) ) ) {
156   -
157   - openProjectInput.click();
158   -
159   - }
160   -
161   - } );
162   -
163   - options.add( option );
164   -
165   - // Save
166   -
167   - option = new UIRow()
168   - .addClass( 'option' )
169   - .setTextContent( strings.getKey( 'menubar/file/save' ) )
170   - .onClick( function () {
171   -
172   - const json = editor.toJSON();
173   - const blob = new Blob( [ JSON.stringify( json ) ], { type: 'application/json' } );
174   - editor.utils.save( blob, 'project.json' );
175   -
176   - } );
177   -
178   - options.add( option );
179   -
180   - //
181   -
182   - options.add( new UIHorizontalRule() );
183   -
184   - // Import
185   -
186   - const form = document.createElement( 'form' );
187   - form.style.display = 'none';
188   - document.body.appendChild( form );
189   -
190   - const fileInput = document.createElement( 'input' );
191   - fileInput.multiple = true;
192   - fileInput.type = 'file';
193   - fileInput.addEventListener( 'change', function () {
194   -
195   - editor.loader.loadFiles( fileInput.files );
196   - form.reset();
197   -
198   - } );
199   - form.appendChild( fileInput );
200   -
201   - option = new UIRow();
202   - option.setClass( 'option' );
203   - option.setTextContent( strings.getKey( 'menubar/file/import' ) );
204   - option.onClick( function () {
205   -
206   - fileInput.click();
207   -
208   - } );
209   - options.add( option );
210   -
211   - // Export
212   -
213   - const fileExportSubmenuTitle = new UIRow().setTextContent( strings.getKey( 'menubar/file/export' ) ).addClass( 'option' ).addClass( 'submenu-title' );
214   - fileExportSubmenuTitle.onMouseOver( function () {
215   -
216   - const { top, right } = this.dom.getBoundingClientRect();
217   - const { paddingTop } = getComputedStyle( this.dom );
218   - fileExportSubmenu.setLeft( right + 'px' );
219   - fileExportSubmenu.setTop( top - parseFloat( paddingTop ) + 'px' );
220   - fileExportSubmenu.setDisplay( 'block' );
221   -
222   - } );
223   - fileExportSubmenuTitle.onMouseOut( function () {
224   -
225   - fileExportSubmenu.setDisplay( 'none' );
226   -
227   - } );
228   - options.add( fileExportSubmenuTitle );
229   -
230   - const fileExportSubmenu = new UIPanel().setPosition( 'fixed' ).addClass( 'options' ).setDisplay( 'none' );
231   - fileExportSubmenuTitle.add( fileExportSubmenu );
232   -
233   - // Export DRC
234   -
235   - option = new UIRow();
236   - option.setClass( 'option' );
237   - option.setTextContent( 'DRC' );
238   - option.onClick( async function () {
239   -
240   - const object = editor.selected;
241   -
242   - if ( object === null || object.isMesh === undefined ) {
243   -
244   - alert( strings.getKey( 'prompt/file/export/noMeshSelected' ) );
245   - return;
246   -
247   - }
248   -
249   - const { DRACOExporter } = await import( 'three/addons/exporters/DRACOExporter.js' );
250   -
251   - const exporter = new DRACOExporter();
252   -
253   - const options = {
254   - decodeSpeed: 5,
255   - encodeSpeed: 5,
256   - encoderMethod: DRACOExporter.MESH_EDGEBREAKER_ENCODING,
257   - quantization: [ 16, 8, 8, 8, 8 ],
258   - exportUvs: true,
259   - exportNormals: true,
260   - exportColor: object.geometry.hasAttribute( 'color' )
261   - };
262   -
263   - // TODO: Change to DRACOExporter's parse( geometry, onParse )?
264   - const result = exporter.parse( object, options );
265   - saveArrayBuffer( result, 'model.drc' );
266   -
267   - } );
268   - fileExportSubmenu.add( option );
269   -
270   - // Export GLB
271   -
272   - option = new UIRow();
273   - option.setClass( 'option' );
274   - option.setTextContent( 'GLB' );
275   - option.onClick( async function () {
276   -
277   - const scene = editor.scene;
278   - const animations = getAnimations( scene );
279   -
280   - const optimizedAnimations = [];
281   -
282   - for ( const animation of animations ) {
283   -
284   - optimizedAnimations.push( animation.clone().optimize() );
285   -
286   - }
287   -
288   - const { GLTFExporter } = await import( 'three/addons/exporters/GLTFExporter.js' );
289   -
290   - const exporter = new GLTFExporter();
291   -
292   - exporter.parse( scene, function ( result ) {
293   -
294   - saveArrayBuffer( result, 'scene.glb' );
295   -
296   - }, undefined, { binary: true, animations: optimizedAnimations } );
297   -
298   - } );
299   - fileExportSubmenu.add( option );
300   -
301   - // Export GLTF
302   -
303   - option = new UIRow();
304   - option.setClass( 'option' );
305   - option.setTextContent( 'GLTF' );
306   - option.onClick( async function () {
307   -
308   - const scene = editor.scene;
309   - const animations = getAnimations( scene );
310   -
311   - const optimizedAnimations = [];
312   -
313   - for ( const animation of animations ) {
314   -
315   - optimizedAnimations.push( animation.clone().optimize() );
316   -
317   - }
318   -
319   - const { GLTFExporter } = await import( 'three/addons/exporters/GLTFExporter.js' );
320   -
321   - const exporter = new GLTFExporter();
322   -
323   - exporter.parse( scene, function ( result ) {
324   -
325   - saveString( JSON.stringify( result, null, 2 ), 'scene.gltf' );
326   -
327   - }, undefined, { animations: optimizedAnimations } );
328   -
329   -
330   - } );
331   - fileExportSubmenu.add( option );
332   -
333   - // Export OBJ
334   -
335   - option = new UIRow();
336   - option.setClass( 'option' );
337   - option.setTextContent( 'OBJ' );
338   - option.onClick( async function () {
339   -
340   - const object = editor.selected;
341   -
342   - if ( object === null ) {
343   -
344   - alert( strings.getKey( 'prompt/file/export/noObjectSelected' ) );
345   - return;
346   -
347   - }
348   -
349   - const { OBJExporter } = await import( 'three/addons/exporters/OBJExporter.js' );
350   -
351   - const exporter = new OBJExporter();
352   -
353   - saveString( exporter.parse( object ), 'model.obj' );
354   -
355   - } );
356   - fileExportSubmenu.add( option );
357   -
358   - // Export PLY (ASCII)
359   -
360   - option = new UIRow();
361   - option.setClass( 'option' );
362   - option.setTextContent( 'PLY' );
363   - option.onClick( async function () {
364   -
365   - const { PLYExporter } = await import( 'three/addons/exporters/PLYExporter.js' );
366   -
367   - const exporter = new PLYExporter();
368   -
369   - exporter.parse( editor.scene, function ( result ) {
370   -
371   - saveArrayBuffer( result, 'model.ply' );
372   -
373   - } );
374   -
375   - } );
376   - fileExportSubmenu.add( option );
377   -
378   - // Export PLY (BINARY)
379   -
380   - option = new UIRow();
381   - option.setClass( 'option' );
382   - option.setTextContent( 'PLY (BINARY)' );
383   - option.onClick( async function () {
384   -
385   - const { PLYExporter } = await import( 'three/addons/exporters/PLYExporter.js' );
386   -
387   - const exporter = new PLYExporter();
388   -
389   - exporter.parse( editor.scene, function ( result ) {
390   -
391   - saveArrayBuffer( result, 'model-binary.ply' );
392   -
393   - }, { binary: true } );
394   -
395   - } );
396   - fileExportSubmenu.add( option );
397   -
398   - // Export STL (ASCII)
399   -
400   - option = new UIRow();
401   - option.setClass( 'option' );
402   - option.setTextContent( 'STL' );
403   - option.onClick( async function () {
404   -
405   - const { STLExporter } = await import( 'three/addons/exporters/STLExporter.js' );
406   -
407   - const exporter = new STLExporter();
408   -
409   - saveString( exporter.parse( editor.scene ), 'model.stl' );
410   -
411   - } );
412   - fileExportSubmenu.add( option );
413   -
414   - // Export STL (BINARY)
415   -
416   - option = new UIRow();
417   - option.setClass( 'option' );
418   - option.setTextContent( 'STL (BINARY)' );
419   - option.onClick( async function () {
420   -
421   - const { STLExporter } = await import( 'three/addons/exporters/STLExporter.js' );
422   -
423   - const exporter = new STLExporter();
424   -
425   - saveArrayBuffer( exporter.parse( editor.scene, { binary: true } ), 'model-binary.stl' );
426   -
427   - } );
428   - fileExportSubmenu.add( option );
429   -
430   - // Export USDZ
431   -
432   - option = new UIRow();
433   - option.setClass( 'option' );
434   - option.setTextContent( 'USDZ' );
435   - option.onClick( async function () {
436   -
437   - const { USDZExporter } = await import( 'three/addons/exporters/USDZExporter.js' );
438   -
439   - const exporter = new USDZExporter();
440   -
441   - saveArrayBuffer( await exporter.parseAsync( editor.scene ), 'model.usdz' );
442   -
443   - } );
444   - fileExportSubmenu.add( option );
445   -
446   - //
447   -
448   - function getAnimations( scene ) {
449   -
450   - const animations = [];
451   -
452   - scene.traverse( function ( object ) {
453   -
454   - animations.push( ... object.animations );
455   -
456   - } );
457   -
458   - return animations;
459   -
460   - }
461   -
462   - return container;
  421 + return animations
  422 + }
463 423
  424 + return container
464 425 }
465 426
466   -export { MenubarFile };
  427 +export { MenubarFile }
... ...
  1 +/**
  2 + * 消息提示条
  3 + * @param {object} params
  4 + * @param {number} params.duration 持续时间(毫秒),默认`2000`
  5 + * @param {number} params.zIndex 起始定位层级,默认`1000`
  6 + */
  7 +
  8 +export default function useMessage(params = {}) {
  9 + const doc = document
  10 + const cssModule = `__${Math.random().toString(36).slice(2, 7)}`
  11 + const className = {
  12 + box: `msg-box${cssModule}`,
  13 + hide: `hide${cssModule}`,
  14 + text: `msg-text${cssModule}`,
  15 + icon: `msg-icon${cssModule}`
  16 + }
  17 + const style = doc.createElement('style')
  18 + style.textContent = `
  19 + .${className.box}, .${className.icon}, .${className.text} {
  20 + padding: 0;
  21 + margin: 0;
  22 + box-sizing: border-box;
  23 + }
  24 + .${className.box} {
  25 + position: fixed;
  26 + top: 0;
  27 + left: 50%;
  28 + display: flex;
  29 + padding: 12px 16px;
  30 + border-radius: 2px;
  31 + background-color: #fff;
  32 + box-shadow: 0 3px 3px -2px rgba(0,0,0,.2),0 3px 4px 0 rgba(0,0,0,.14),0 1px 8px 0 rgba(0,0,0,.12);
  33 + white-space: nowrap;
  34 + animation: ${className.box}-move .4s;
  35 + transition: .4s all;
  36 + transform: translate3d(-50%, 0%, 0);
  37 + opacity: 1;
  38 + overflow: hidden;
  39 + }
  40 + .${className.box}::after {
  41 + content: "";
  42 + position: absolute;
  43 + left: 0;
  44 + top: 0;
  45 + height: 100%;
  46 + width: 4px;
  47 + }
  48 + @keyframes ${className.box}-move {
  49 + 0% {
  50 + opacity: 0;
  51 + transform: translate3d(-50%, -100%, 0);
  52 + }
  53 + 100% {
  54 + opacity: 1;
  55 + transform: translate3d(-50%, 0%, 0);
  56 + }
  57 + }
  58 + .${className.box}.${className.hide} {
  59 + opacity: 0;
  60 + /* transform: translate3d(-50%, -100%, 0); */
  61 + transform: translate3d(-50%, -100%, 0) scale(0);
  62 + }
  63 + .${className.icon} {
  64 + display: inline-block;
  65 + width: 18px;
  66 + height: 18px;
  67 + border-radius: 50%;
  68 + overflow: hidden;
  69 + margin-right: 6px;
  70 + position: relative;
  71 + }
  72 + .${className.text} {
  73 + font-size: 14px;
  74 + line-height: 18px;
  75 + color: #555;
  76 + }
  77 + .${className.icon}::after,
  78 + .${className.icon}::before {
  79 + position: absolute;
  80 + content: "";
  81 + background-color: #fff;
  82 + }
  83 + .${className.box}.info .${className.icon}, .${className.box}.info::after {
  84 + background-color: #1890ff;
  85 + }
  86 + .${className.box}.success .${className.icon}, .${className.box}.success::after {
  87 + background-color: #52c41a;
  88 + }
  89 + .${className.box}.warning .${className.icon}, .${className.box}.warning::after {
  90 + background-color: #faad14;
  91 + }
  92 + .${className.box}.error .${className.icon}, .${className.box}.error::after {
  93 + background-color: #ff4d4f;
  94 + }
  95 + .${className.box}.info .${className.icon}::after,
  96 + .${className.box}.warning .${className.icon}::after {
  97 + top: 15%;
  98 + left: 50%;
  99 + margin-left: -1px;
  100 + width: 2px;
  101 + height: 2px;
  102 + border-radius: 50%;
  103 + }
  104 + .${className.box}.info .${className.icon}::before,
  105 + .${className.box}.warning .${className.icon}::before {
  106 + top: calc(15% + 4px);
  107 + left: 50%;
  108 + margin-left: -1px;
  109 + width: 2px;
  110 + height: 40%;
  111 + }
  112 + .${className.box}.error .${className.icon}::after,
  113 + .${className.box}.error .${className.icon}::before {
  114 + top: 20%;
  115 + left: 50%;
  116 + width: 2px;
  117 + height: 60%;
  118 + margin-left: -1px;
  119 + border-radius: 1px;
  120 + }
  121 + .${className.box}.error .${className.icon}::after {
  122 + transform: rotate(-45deg);
  123 + }
  124 + .${className.box}.error .${className.icon}::before {
  125 + transform: rotate(45deg);
  126 + }
  127 + .${className.box}.success .${className.icon}::after {
  128 + box-sizing: content-box;
  129 + background-color: transparent;
  130 + border: 2px solid #fff;
  131 + border-left: 0;
  132 + border-top: 0;
  133 + height: 50%;
  134 + left: 35%;
  135 + top: 13%;
  136 + transform: rotate(45deg);
  137 + width: 20%;
  138 + transform-origin: center;
  139 + }
  140 + `
  141 + .replace(/(\n|\t|\s)*/gi, '$1')
  142 + .replace(/\n|\t|\s(\{|\}|\,|\:|\;)/gi, '$1')
  143 + .replace(/(\{|\}|\,|\:|\;)\s/gi, '$1')
  144 + doc.head.appendChild(style)
  145 + /** 一直累加的定位层级 */
  146 + let zIndex = params.zIndex || 1000
  147 + /**
  148 + * 消息队列
  149 + * @type {Array<HTMLElement>}
  150 + */
  151 + const messageList = []
  152 +
  153 + /**
  154 + * 获取指定`item`的定位`top`
  155 + * @param {HTMLElement=} el
  156 + */
  157 + function getItemTop(el) {
  158 + let top = 10
  159 + for (let i = 0; i < messageList.length; i++) {
  160 + const item = messageList[i]
  161 + if (el && el === item) {
  162 + break
  163 + }
  164 + top += item.clientHeight + 20
  165 + }
  166 + return top
  167 + }
  168 +
  169 + /**
  170 + * 删除指定列表项
  171 + * @param {HTMLElement} el
  172 + */
  173 + function removeItem(el) {
  174 + for (let i = 0; i < messageList.length; i++) {
  175 + const item = messageList[i]
  176 + if (item === el) {
  177 + messageList.splice(i, 1)
  178 + break
  179 + }
  180 + }
  181 + el.classList.add(className.hide)
  182 + messageList.forEach(function (item) {
  183 + item.style.top = `${getItemTop(item)}px`
  184 + })
  185 + }
  186 +
  187 + /**
  188 + * 显示一条消息
  189 + * @param {string} content 内容
  190 + * @param {"info"|"success"|"warning"|"error"} type 消息类型
  191 + * @param {number} duration 持续时间,优先级比默认值高
  192 + */
  193 + function show(content, type = 'info', duration) {
  194 + const el = doc.createElement('div')
  195 + el.className = `${className.box} ${type}`
  196 + el.style.top = `${getItemTop()}px`
  197 + el.style.zIndex = zIndex
  198 + el.innerHTML = `
  199 + <span class="${className.icon}"></span>
  200 + <span class="${className.text}">${content}</span>
  201 + `
  202 + zIndex++
  203 + messageList.push(el)
  204 + doc.body.appendChild(el)
  205 + // 添加动画监听事件
  206 + function animationEnd() {
  207 + el.removeEventListener('animationend', animationEnd)
  208 + setTimeout(removeItem, duration || params.duration || 2000, el)
  209 + }
  210 + el.addEventListener('animationend', animationEnd)
  211 + function transitionEnd() {
  212 + if (getComputedStyle(el).opacity !== '0') return
  213 + el.removeEventListener('transitionend', transitionEnd)
  214 + el.remove()
  215 + }
  216 + el.addEventListener('transitionend', transitionEnd)
  217 + }
  218 +
  219 + return {
  220 + show,
  221 + /**
  222 + * 普通描述提示
  223 + * @param {string} msg
  224 + */
  225 + info(msg) {
  226 + show(msg, 'info')
  227 + },
  228 + /**
  229 + * 成功提示
  230 + * @param {string} msg
  231 + */
  232 + success(msg) {
  233 + show(msg, 'success')
  234 + },
  235 + /**
  236 + * 警告提示
  237 + * @param {string} msg
  238 + */
  239 + warning(msg) {
  240 + show(msg, 'warning')
  241 + },
  242 + /**
  243 + * 错误提示
  244 + * @param {string} msg
  245 + */
  246 + error(msg) {
  247 + show(msg, 'error')
  248 + }
  249 + }
  250 +}
... ...
... ... @@ -714,19 +714,34 @@ const vertexShaderVariables = [
714 714 'attribute vec3 position;\n\n',
715 715 ].join( '\n' );
716 716
  717 +// const meshMaterialOptions = {
  718 +// 'MeshBasicMaterial': 'MeshBasicMaterial',
  719 +// 'MeshDepthMaterial': 'MeshDepthMaterial',
  720 +// 'MeshNormalMaterial': 'MeshNormalMaterial',
  721 +// 'MeshLambertMaterial': 'MeshLambertMaterial',
  722 +// 'MeshMatcapMaterial': 'MeshMatcapMaterial',
  723 +// 'MeshPhongMaterial': 'MeshPhongMaterial',
  724 +// 'MeshToonMaterial': 'MeshToonMaterial',
  725 +// 'MeshStandardMaterial': 'MeshStandardMaterial',
  726 +// 'MeshPhysicalMaterial': 'MeshPhysicalMaterial',
  727 +// 'RawShaderMaterial': 'RawShaderMaterial',
  728 +// 'ShaderMaterial': 'ShaderMaterial',
  729 +// 'ShadowMaterial': 'ShadowMaterial'
  730 +// };
  731 +
717 732 const meshMaterialOptions = {
718   - 'MeshBasicMaterial': 'MeshBasicMaterial',
719   - 'MeshDepthMaterial': 'MeshDepthMaterial',
720   - 'MeshNormalMaterial': 'MeshNormalMaterial',
721   - 'MeshLambertMaterial': 'MeshLambertMaterial',
722   - 'MeshMatcapMaterial': 'MeshMatcapMaterial',
723   - 'MeshPhongMaterial': 'MeshPhongMaterial',
724   - 'MeshToonMaterial': 'MeshToonMaterial',
725   - 'MeshStandardMaterial': 'MeshStandardMaterial',
726   - 'MeshPhysicalMaterial': 'MeshPhysicalMaterial',
727   - 'RawShaderMaterial': 'RawShaderMaterial',
728   - 'ShaderMaterial': 'ShaderMaterial',
729   - 'ShadowMaterial': 'ShadowMaterial'
  733 + 'MeshBasicMaterial': '基础网格材质(MeshBasicMaterial)',
  734 + 'MeshDepthMaterial': '深度网格材质(MeshDepthMaterial)',
  735 + 'MeshNormalMaterial': '法线网格材质(MeshNormalMaterial)',
  736 + 'MeshLambertMaterial': 'Lambert网格材质(MeshLambertMaterial)',
  737 + 'MeshMatcapMaterial': 'MatCap网格材质(MeshMatcapMaterial)',
  738 + 'MeshPhongMaterial': 'Phong网格材质(MeshPhongMaterial)',
  739 + 'MeshToonMaterial': '卡通网格材质(MeshToonMaterial)',
  740 + 'MeshStandardMaterial': '标准网格材质(MeshStandardMaterial)',
  741 + 'MeshPhysicalMaterial': '物理网格材质(MeshPhysicalMaterial)',
  742 + 'RawShaderMaterial': '原始着色器材质(RawShaderMaterial)',
  743 + 'ShaderMaterial': '着色器材质(ShaderMaterial)',
  744 + 'ShadowMaterial': '阴影材质(ShadowMaterial)'
730 745 };
731 746
732 747 const lineMaterialOptions = {
... ...
  1 +/*
  2 +封装本地存储模块
  3 + */
  4 +
  5 +export const getItem = name => {
  6 + const data = window.localStorage.getItem(name)
  7 + try {
  8 + return JSON.parse(data)
  9 + } catch (err) {
  10 + return data
  11 + }
  12 +}
  13 +
  14 +export const setItem = (name, value) => {
  15 + if (typeof value === 'object') {
  16 + value = JSON.stringify(value)
  17 + }
  18 + window.localStorage.setItem(name, value)
  19 +}
  20 +
  21 +export const removeItem = name => {
  22 + window.localStorage.removeItem(name)
  23 +}
  24 +
  25 +export const clearItem = () => {
  26 + window.localStorage.clearItem()
  27 +}
... ...
  1 +!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t():"function"==typeof define&&define.amd?define(t):(e="undefined"!=typeof globalThis?globalThis:e||self).axios=t()}(this,(function(){"use strict";function e(e){var r,n;function o(r,n){try{var a=e[r](n),u=a.value,s=u instanceof t;Promise.resolve(s?u.v:u).then((function(t){if(s){var n="return"===r?"return":"next";if(!u.k||t.done)return o(n,t);t=e[n](t).value}i(a.done?"return":"normal",t)}),(function(e){o("throw",e)}))}catch(e){i("throw",e)}}function i(e,t){switch(e){case"return":r.resolve({value:t,done:!0});break;case"throw":r.reject(t);break;default:r.resolve({value:t,done:!1})}(r=r.next)?o(r.key,r.arg):n=null}this._invoke=function(e,t){return new Promise((function(i,a){var u={key:e,arg:t,resolve:i,reject:a,next:null};n?n=n.next=u:(r=n=u,o(e,t))}))},"function"!=typeof e.return&&(this.return=void 0)}function t(e,t){this.v=e,this.k=t}function r(e){var r={},n=!1;function o(r,o){return n=!0,o=new Promise((function(t){t(e[r](o))})),{done:!1,value:new t(o,1)}}return r["undefined"!=typeof Symbol&&Symbol.iterator||"@@iterator"]=function(){return this},r.next=function(e){return n?(n=!1,e):o("next",e)},"function"==typeof e.throw&&(r.throw=function(e){if(n)throw n=!1,e;return o("throw",e)}),"function"==typeof e.return&&(r.return=function(e){return n?(n=!1,e):o("return",e)}),r}function n(e){var t,r,n,i=2;for("undefined"!=typeof Symbol&&(r=Symbol.asyncIterator,n=Symbol.iterator);i--;){if(r&&null!=(t=e[r]))return t.call(e);if(n&&null!=(t=e[n]))return new o(t.call(e));r="@@asyncIterator",n="@@iterator"}throw new TypeError("Object is not async iterable")}function o(e){function t(e){if(Object(e)!==e)return Promise.reject(new TypeError(e+" is not an object."));var t=e.done;return Promise.resolve(e.value).then((function(e){return{value:e,done:t}}))}return o=function(e){this.s=e,this.n=e.next},o.prototype={s:null,n:null,next:function(){return t(this.n.apply(this.s,arguments))},return:function(e){var r=this.s.return;return void 0===r?Promise.resolve({value:e,done:!0}):t(r.apply(this.s,arguments))},throw:function(e){var r=this.s.return;return void 0===r?Promise.reject(e):t(r.apply(this.s,arguments))}},new o(e)}function i(e){return new t(e,0)}function a(e,t){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);t&&(n=n.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),r.push.apply(r,n)}return r}function u(e){for(var t=1;t<arguments.length;t++){var r=null!=arguments[t]?arguments[t]:{};t%2?a(Object(r),!0).forEach((function(t){m(e,t,r[t])})):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(r)):a(Object(r)).forEach((function(t){Object.defineProperty(e,t,Object.getOwnPropertyDescriptor(r,t))}))}return e}function s(){s=function(){return t};var e,t={},r=Object.prototype,n=r.hasOwnProperty,o=Object.defineProperty||function(e,t,r){e[t]=r.value},i="function"==typeof Symbol?Symbol:{},a=i.iterator||"@@iterator",u=i.asyncIterator||"@@asyncIterator",c=i.toStringTag||"@@toStringTag";function f(e,t,r){return Object.defineProperty(e,t,{value:r,enumerable:!0,configurable:!0,writable:!0}),e[t]}try{f({},"")}catch(e){f=function(e,t,r){return e[t]=r}}function l(e,t,r,n){var i=t&&t.prototype instanceof m?t:m,a=Object.create(i.prototype),u=new P(n||[]);return o(a,"_invoke",{value:T(e,r,u)}),a}function h(e,t,r){try{return{type:"normal",arg:e.call(t,r)}}catch(e){return{type:"throw",arg:e}}}t.wrap=l;var p="suspendedStart",d="executing",v="completed",y={};function m(){}function b(){}function g(){}var w={};f(w,a,(function(){return this}));var E=Object.getPrototypeOf,O=E&&E(E(L([])));O&&O!==r&&n.call(O,a)&&(w=O);var S=g.prototype=m.prototype=Object.create(w);function x(e){["next","throw","return"].forEach((function(t){f(e,t,(function(e){return this._invoke(t,e)}))}))}function R(e,t){function r(o,i,a,u){var s=h(e[o],e,i);if("throw"!==s.type){var c=s.arg,f=c.value;return f&&"object"==typeof f&&n.call(f,"__await")?t.resolve(f.__await).then((function(e){r("next",e,a,u)}),(function(e){r("throw",e,a,u)})):t.resolve(f).then((function(e){c.value=e,a(c)}),(function(e){return r("throw",e,a,u)}))}u(s.arg)}var i;o(this,"_invoke",{value:function(e,n){function o(){return new t((function(t,o){r(e,n,t,o)}))}return i=i?i.then(o,o):o()}})}function T(t,r,n){var o=p;return function(i,a){if(o===d)throw new Error("Generator is already running");if(o===v){if("throw"===i)throw a;return{value:e,done:!0}}for(n.method=i,n.arg=a;;){var u=n.delegate;if(u){var s=k(u,n);if(s){if(s===y)continue;return s}}if("next"===n.method)n.sent=n._sent=n.arg;else if("throw"===n.method){if(o===p)throw o=v,n.arg;n.dispatchException(n.arg)}else"return"===n.method&&n.abrupt("return",n.arg);o=d;var c=h(t,r,n);if("normal"===c.type){if(o=n.done?v:"suspendedYield",c.arg===y)continue;return{value:c.arg,done:n.done}}"throw"===c.type&&(o=v,n.method="throw",n.arg=c.arg)}}}function k(t,r){var n=r.method,o=t.iterator[n];if(o===e)return r.delegate=null,"throw"===n&&t.iterator.return&&(r.method="return",r.arg=e,k(t,r),"throw"===r.method)||"return"!==n&&(r.method="throw",r.arg=new TypeError("The iterator does not provide a '"+n+"' method")),y;var i=h(o,t.iterator,r.arg);if("throw"===i.type)return r.method="throw",r.arg=i.arg,r.delegate=null,y;var a=i.arg;return a?a.done?(r[t.resultName]=a.value,r.next=t.nextLoc,"return"!==r.method&&(r.method="next",r.arg=e),r.delegate=null,y):a:(r.method="throw",r.arg=new TypeError("iterator result is not an object"),r.delegate=null,y)}function A(e){var t={tryLoc:e[0]};1 in e&&(t.catchLoc=e[1]),2 in e&&(t.finallyLoc=e[2],t.afterLoc=e[3]),this.tryEntries.push(t)}function j(e){var t=e.completion||{};t.type="normal",delete t.arg,e.completion=t}function P(e){this.tryEntries=[{tryLoc:"root"}],e.forEach(A,this),this.reset(!0)}function L(t){if(t||""===t){var r=t[a];if(r)return r.call(t);if("function"==typeof t.next)return t;if(!isNaN(t.length)){var o=-1,i=function r(){for(;++o<t.length;)if(n.call(t,o))return r.value=t[o],r.done=!1,r;return r.value=e,r.done=!0,r};return i.next=i}}throw new TypeError(typeof t+" is not iterable")}return b.prototype=g,o(S,"constructor",{value:g,configurable:!0}),o(g,"constructor",{value:b,configurable:!0}),b.displayName=f(g,c,"GeneratorFunction"),t.isGeneratorFunction=function(e){var t="function"==typeof e&&e.constructor;return!!t&&(t===b||"GeneratorFunction"===(t.displayName||t.name))},t.mark=function(e){return Object.setPrototypeOf?Object.setPrototypeOf(e,g):(e.__proto__=g,f(e,c,"GeneratorFunction")),e.prototype=Object.create(S),e},t.awrap=function(e){return{__await:e}},x(R.prototype),f(R.prototype,u,(function(){return this})),t.AsyncIterator=R,t.async=function(e,r,n,o,i){void 0===i&&(i=Promise);var a=new R(l(e,r,n,o),i);return t.isGeneratorFunction(r)?a:a.next().then((function(e){return e.done?e.value:a.next()}))},x(S),f(S,c,"Generator"),f(S,a,(function(){return this})),f(S,"toString",(function(){return"[object Generator]"})),t.keys=function(e){var t=Object(e),r=[];for(var n in t)r.push(n);return r.reverse(),function e(){for(;r.length;){var n=r.pop();if(n in t)return e.value=n,e.done=!1,e}return e.done=!0,e}},t.values=L,P.prototype={constructor:P,reset:function(t){if(this.prev=0,this.next=0,this.sent=this._sent=e,this.done=!1,this.delegate=null,this.method="next",this.arg=e,this.tryEntries.forEach(j),!t)for(var r in this)"t"===r.charAt(0)&&n.call(this,r)&&!isNaN(+r.slice(1))&&(this[r]=e)},stop:function(){this.done=!0;var e=this.tryEntries[0].completion;if("throw"===e.type)throw e.arg;return this.rval},dispatchException:function(t){if(this.done)throw t;var r=this;function o(n,o){return u.type="throw",u.arg=t,r.next=n,o&&(r.method="next",r.arg=e),!!o}for(var i=this.tryEntries.length-1;i>=0;--i){var a=this.tryEntries[i],u=a.completion;if("root"===a.tryLoc)return o("end");if(a.tryLoc<=this.prev){var s=n.call(a,"catchLoc"),c=n.call(a,"finallyLoc");if(s&&c){if(this.prev<a.catchLoc)return o(a.catchLoc,!0);if(this.prev<a.finallyLoc)return o(a.finallyLoc)}else if(s){if(this.prev<a.catchLoc)return o(a.catchLoc,!0)}else{if(!c)throw new Error("try statement without catch or finally");if(this.prev<a.finallyLoc)return o(a.finallyLoc)}}}},abrupt:function(e,t){for(var r=this.tryEntries.length-1;r>=0;--r){var o=this.tryEntries[r];if(o.tryLoc<=this.prev&&n.call(o,"finallyLoc")&&this.prev<o.finallyLoc){var i=o;break}}i&&("break"===e||"continue"===e)&&i.tryLoc<=t&&t<=i.finallyLoc&&(i=null);var a=i?i.completion:{};return a.type=e,a.arg=t,i?(this.method="next",this.next=i.finallyLoc,y):this.complete(a)},complete:function(e,t){if("throw"===e.type)throw e.arg;return"break"===e.type||"continue"===e.type?this.next=e.arg:"return"===e.type?(this.rval=this.arg=e.arg,this.method="return",this.next="end"):"normal"===e.type&&t&&(this.next=t),y},finish:function(e){for(var t=this.tryEntries.length-1;t>=0;--t){var r=this.tryEntries[t];if(r.finallyLoc===e)return this.complete(r.completion,r.afterLoc),j(r),y}},catch:function(e){for(var t=this.tryEntries.length-1;t>=0;--t){var r=this.tryEntries[t];if(r.tryLoc===e){var n=r.completion;if("throw"===n.type){var o=n.arg;j(r)}return o}}throw new Error("illegal catch attempt")},delegateYield:function(t,r,n){return this.delegate={iterator:L(t),resultName:r,nextLoc:n},"next"===this.method&&(this.arg=e),y}},t}function c(e){var t=function(e,t){if("object"!=typeof e||!e)return e;var r=e[Symbol.toPrimitive];if(void 0!==r){var n=r.call(e,t||"default");if("object"!=typeof n)return n;throw new TypeError("@@toPrimitive must return a primitive value.")}return("string"===t?String:Number)(e)}(e,"string");return"symbol"==typeof t?t:String(t)}function f(e){return f="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},f(e)}function l(t){return function(){return new e(t.apply(this,arguments))}}function h(e,t,r,n,o,i,a){try{var u=e[i](a),s=u.value}catch(e){return void r(e)}u.done?t(s):Promise.resolve(s).then(n,o)}function p(e){return function(){var t=this,r=arguments;return new Promise((function(n,o){var i=e.apply(t,r);function a(e){h(i,n,o,a,u,"next",e)}function u(e){h(i,n,o,a,u,"throw",e)}a(void 0)}))}}function d(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}function v(e,t){for(var r=0;r<t.length;r++){var n=t[r];n.enumerable=n.enumerable||!1,n.configurable=!0,"value"in n&&(n.writable=!0),Object.defineProperty(e,c(n.key),n)}}function y(e,t,r){return t&&v(e.prototype,t),r&&v(e,r),Object.defineProperty(e,"prototype",{writable:!1}),e}function m(e,t,r){return(t=c(t))in e?Object.defineProperty(e,t,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[t]=r,e}function b(e,t){return w(e)||function(e,t){var r=null==e?null:"undefined"!=typeof Symbol&&e[Symbol.iterator]||e["@@iterator"];if(null!=r){var n,o,i,a,u=[],s=!0,c=!1;try{if(i=(r=r.call(e)).next,0===t){if(Object(r)!==r)return;s=!1}else for(;!(s=(n=i.call(r)).done)&&(u.push(n.value),u.length!==t);s=!0);}catch(e){c=!0,o=e}finally{try{if(!s&&null!=r.return&&(a=r.return(),Object(a)!==a))return}finally{if(c)throw o}}return u}}(e,t)||O(e,t)||x()}function g(e){return function(e){if(Array.isArray(e))return S(e)}(e)||E(e)||O(e)||function(){throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}()}function w(e){if(Array.isArray(e))return e}function E(e){if("undefined"!=typeof Symbol&&null!=e[Symbol.iterator]||null!=e["@@iterator"])return Array.from(e)}function O(e,t){if(e){if("string"==typeof e)return S(e,t);var r=Object.prototype.toString.call(e).slice(8,-1);return"Object"===r&&e.constructor&&(r=e.constructor.name),"Map"===r||"Set"===r?Array.from(e):"Arguments"===r||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(r)?S(e,t):void 0}}function S(e,t){(null==t||t>e.length)&&(t=e.length);for(var r=0,n=new Array(t);r<t;r++)n[r]=e[r];return n}function x(){throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}function R(e,t){return function(){return e.apply(t,arguments)}}e.prototype["function"==typeof Symbol&&Symbol.asyncIterator||"@@asyncIterator"]=function(){return this},e.prototype.next=function(e){return this._invoke("next",e)},e.prototype.throw=function(e){return this._invoke("throw",e)},e.prototype.return=function(e){return this._invoke("return",e)};var T,k=Object.prototype.toString,A=Object.getPrototypeOf,j=(T=Object.create(null),function(e){var t=k.call(e);return T[t]||(T[t]=t.slice(8,-1).toLowerCase())}),P=function(e){return e=e.toLowerCase(),function(t){return j(t)===e}},L=function(e){return function(t){return f(t)===e}},N=Array.isArray,_=L("undefined");var C=P("ArrayBuffer");var F=L("string"),U=L("function"),B=L("number"),D=function(e){return null!==e&&"object"===f(e)},I=function(e){if("object"!==j(e))return!1;var t=A(e);return!(null!==t&&t!==Object.prototype&&null!==Object.getPrototypeOf(t)||Symbol.toStringTag in e||Symbol.iterator in e)},q=P("Date"),M=P("File"),z=P("Blob"),H=P("FileList"),J=P("URLSearchParams"),W=b(["ReadableStream","Request","Response","Headers"].map(P),4),G=W[0],K=W[1],V=W[2],X=W[3];function $(e,t){var r,n,o=arguments.length>2&&void 0!==arguments[2]?arguments[2]:{},i=o.allOwnKeys,a=void 0!==i&&i;if(null!=e)if("object"!==f(e)&&(e=[e]),N(e))for(r=0,n=e.length;r<n;r++)t.call(null,e[r],r,e);else{var u,s=a?Object.getOwnPropertyNames(e):Object.keys(e),c=s.length;for(r=0;r<c;r++)u=s[r],t.call(null,e[u],u,e)}}function Y(e,t){t=t.toLowerCase();for(var r,n=Object.keys(e),o=n.length;o-- >0;)if(t===(r=n[o]).toLowerCase())return r;return null}var Q="undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:"undefined"!=typeof window?window:global,Z=function(e){return!_(e)&&e!==Q};var ee,te=(ee="undefined"!=typeof Uint8Array&&A(Uint8Array),function(e){return ee&&e instanceof ee}),re=P("HTMLFormElement"),ne=function(e){var t=Object.prototype.hasOwnProperty;return function(e,r){return t.call(e,r)}}(),oe=P("RegExp"),ie=function(e,t){var r=Object.getOwnPropertyDescriptors(e),n={};$(r,(function(r,o){var i;!1!==(i=t(r,o,e))&&(n[o]=i||r)})),Object.defineProperties(e,n)},ae="abcdefghijklmnopqrstuvwxyz",ue="0123456789",se={DIGIT:ue,ALPHA:ae,ALPHA_DIGIT:ae+ae.toUpperCase()+ue};var ce,fe,le,he,pe=P("AsyncFunction"),de=(ce="function"==typeof setImmediate,fe=U(Q.postMessage),ce?setImmediate:fe?(le="axios@".concat(Math.random()),he=[],Q.addEventListener("message",(function(e){var t=e.source,r=e.data;t===Q&&r===le&&he.length&&he.shift()()}),!1),function(e){he.push(e),Q.postMessage(le,"*")}):function(e){return setTimeout(e)}),ve="undefined"!=typeof queueMicrotask?queueMicrotask.bind(Q):"undefined"!=typeof process&&process.nextTick||de,ye={isArray:N,isArrayBuffer:C,isBuffer:function(e){return null!==e&&!_(e)&&null!==e.constructor&&!_(e.constructor)&&U(e.constructor.isBuffer)&&e.constructor.isBuffer(e)},isFormData:function(e){var t;return e&&("function"==typeof FormData&&e instanceof FormData||U(e.append)&&("formdata"===(t=j(e))||"object"===t&&U(e.toString)&&"[object FormData]"===e.toString()))},isArrayBufferView:function(e){return"undefined"!=typeof ArrayBuffer&&ArrayBuffer.isView?ArrayBuffer.isView(e):e&&e.buffer&&C(e.buffer)},isString:F,isNumber:B,isBoolean:function(e){return!0===e||!1===e},isObject:D,isPlainObject:I,isReadableStream:G,isRequest:K,isResponse:V,isHeaders:X,isUndefined:_,isDate:q,isFile:M,isBlob:z,isRegExp:oe,isFunction:U,isStream:function(e){return D(e)&&U(e.pipe)},isURLSearchParams:J,isTypedArray:te,isFileList:H,forEach:$,merge:function e(){for(var t=Z(this)&&this||{},r=t.caseless,n={},o=function(t,o){var i=r&&Y(n,o)||o;I(n[i])&&I(t)?n[i]=e(n[i],t):I(t)?n[i]=e({},t):N(t)?n[i]=t.slice():n[i]=t},i=0,a=arguments.length;i<a;i++)arguments[i]&&$(arguments[i],o);return n},extend:function(e,t,r){var n=arguments.length>3&&void 0!==arguments[3]?arguments[3]:{},o=n.allOwnKeys;return $(t,(function(t,n){r&&U(t)?e[n]=R(t,r):e[n]=t}),{allOwnKeys:o}),e},trim:function(e){return e.trim?e.trim():e.replace(/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g,"")},stripBOM:function(e){return 65279===e.charCodeAt(0)&&(e=e.slice(1)),e},inherits:function(e,t,r,n){e.prototype=Object.create(t.prototype,n),e.prototype.constructor=e,Object.defineProperty(e,"super",{value:t.prototype}),r&&Object.assign(e.prototype,r)},toFlatObject:function(e,t,r,n){var o,i,a,u={};if(t=t||{},null==e)return t;do{for(i=(o=Object.getOwnPropertyNames(e)).length;i-- >0;)a=o[i],n&&!n(a,e,t)||u[a]||(t[a]=e[a],u[a]=!0);e=!1!==r&&A(e)}while(e&&(!r||r(e,t))&&e!==Object.prototype);return t},kindOf:j,kindOfTest:P,endsWith:function(e,t,r){e=String(e),(void 0===r||r>e.length)&&(r=e.length),r-=t.length;var n=e.indexOf(t,r);return-1!==n&&n===r},toArray:function(e){if(!e)return null;if(N(e))return e;var t=e.length;if(!B(t))return null;for(var r=new Array(t);t-- >0;)r[t]=e[t];return r},forEachEntry:function(e,t){for(var r,n=(e&&e[Symbol.iterator]).call(e);(r=n.next())&&!r.done;){var o=r.value;t.call(e,o[0],o[1])}},matchAll:function(e,t){for(var r,n=[];null!==(r=e.exec(t));)n.push(r);return n},isHTMLForm:re,hasOwnProperty:ne,hasOwnProp:ne,reduceDescriptors:ie,freezeMethods:function(e){ie(e,(function(t,r){if(U(e)&&-1!==["arguments","caller","callee"].indexOf(r))return!1;var n=e[r];U(n)&&(t.enumerable=!1,"writable"in t?t.writable=!1:t.set||(t.set=function(){throw Error("Can not rewrite read-only method '"+r+"'")}))}))},toObjectSet:function(e,t){var r={},n=function(e){e.forEach((function(e){r[e]=!0}))};return N(e)?n(e):n(String(e).split(t)),r},toCamelCase:function(e){return e.toLowerCase().replace(/[-_\s]([a-z\d])(\w*)/g,(function(e,t,r){return t.toUpperCase()+r}))},noop:function(){},toFiniteNumber:function(e,t){return null!=e&&Number.isFinite(e=+e)?e:t},findKey:Y,global:Q,isContextDefined:Z,ALPHABET:se,generateString:function(){for(var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:16,t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:se.ALPHA_DIGIT,r="",n=t.length;e--;)r+=t[Math.random()*n|0];return r},isSpecCompliantForm:function(e){return!!(e&&U(e.append)&&"FormData"===e[Symbol.toStringTag]&&e[Symbol.iterator])},toJSONObject:function(e){var t=new Array(10);return function e(r,n){if(D(r)){if(t.indexOf(r)>=0)return;if(!("toJSON"in r)){t[n]=r;var o=N(r)?[]:{};return $(r,(function(t,r){var i=e(t,n+1);!_(i)&&(o[r]=i)})),t[n]=void 0,o}}return r}(e,0)},isAsyncFn:pe,isThenable:function(e){return e&&(D(e)||U(e))&&U(e.then)&&U(e.catch)},setImmediate:de,asap:ve};function me(e,t,r,n,o){Error.call(this),Error.captureStackTrace?Error.captureStackTrace(this,this.constructor):this.stack=(new Error).stack,this.message=e,this.name="AxiosError",t&&(this.code=t),r&&(this.config=r),n&&(this.request=n),o&&(this.response=o,this.status=o.status?o.status:null)}ye.inherits(me,Error,{toJSON:function(){return{message:this.message,name:this.name,description:this.description,number:this.number,fileName:this.fileName,lineNumber:this.lineNumber,columnNumber:this.columnNumber,stack:this.stack,config:ye.toJSONObject(this.config),code:this.code,status:this.status}}});var be=me.prototype,ge={};["ERR_BAD_OPTION_VALUE","ERR_BAD_OPTION","ECONNABORTED","ETIMEDOUT","ERR_NETWORK","ERR_FR_TOO_MANY_REDIRECTS","ERR_DEPRECATED","ERR_BAD_RESPONSE","ERR_BAD_REQUEST","ERR_CANCELED","ERR_NOT_SUPPORT","ERR_INVALID_URL"].forEach((function(e){ge[e]={value:e}})),Object.defineProperties(me,ge),Object.defineProperty(be,"isAxiosError",{value:!0}),me.from=function(e,t,r,n,o,i){var a=Object.create(be);return ye.toFlatObject(e,a,(function(e){return e!==Error.prototype}),(function(e){return"isAxiosError"!==e})),me.call(a,e.message,t,r,n,o),a.cause=e,a.name=e.name,i&&Object.assign(a,i),a};function we(e){return ye.isPlainObject(e)||ye.isArray(e)}function Ee(e){return ye.endsWith(e,"[]")?e.slice(0,-2):e}function Oe(e,t,r){return e?e.concat(t).map((function(e,t){return e=Ee(e),!r&&t?"["+e+"]":e})).join(r?".":""):t}var Se=ye.toFlatObject(ye,{},null,(function(e){return/^is[A-Z]/.test(e)}));function xe(e,t,r){if(!ye.isObject(e))throw new TypeError("target must be an object");t=t||new FormData;var n=(r=ye.toFlatObject(r,{metaTokens:!0,dots:!1,indexes:!1},!1,(function(e,t){return!ye.isUndefined(t[e])}))).metaTokens,o=r.visitor||c,i=r.dots,a=r.indexes,u=(r.Blob||"undefined"!=typeof Blob&&Blob)&&ye.isSpecCompliantForm(t);if(!ye.isFunction(o))throw new TypeError("visitor must be a function");function s(e){if(null===e)return"";if(ye.isDate(e))return e.toISOString();if(!u&&ye.isBlob(e))throw new me("Blob is not supported. Use a Buffer instead.");return ye.isArrayBuffer(e)||ye.isTypedArray(e)?u&&"function"==typeof Blob?new Blob([e]):Buffer.from(e):e}function c(e,r,o){var u=e;if(e&&!o&&"object"===f(e))if(ye.endsWith(r,"{}"))r=n?r:r.slice(0,-2),e=JSON.stringify(e);else if(ye.isArray(e)&&function(e){return ye.isArray(e)&&!e.some(we)}(e)||(ye.isFileList(e)||ye.endsWith(r,"[]"))&&(u=ye.toArray(e)))return r=Ee(r),u.forEach((function(e,n){!ye.isUndefined(e)&&null!==e&&t.append(!0===a?Oe([r],n,i):null===a?r:r+"[]",s(e))})),!1;return!!we(e)||(t.append(Oe(o,r,i),s(e)),!1)}var l=[],h=Object.assign(Se,{defaultVisitor:c,convertValue:s,isVisitable:we});if(!ye.isObject(e))throw new TypeError("data must be an object");return function e(r,n){if(!ye.isUndefined(r)){if(-1!==l.indexOf(r))throw Error("Circular reference detected in "+n.join("."));l.push(r),ye.forEach(r,(function(r,i){!0===(!(ye.isUndefined(r)||null===r)&&o.call(t,r,ye.isString(i)?i.trim():i,n,h))&&e(r,n?n.concat(i):[i])})),l.pop()}}(e),t}function Re(e){var t={"!":"%21","'":"%27","(":"%28",")":"%29","~":"%7E","%20":"+","%00":"\0"};return encodeURIComponent(e).replace(/[!'()~]|%20|%00/g,(function(e){return t[e]}))}function Te(e,t){this._pairs=[],e&&xe(e,this,t)}var ke=Te.prototype;function Ae(e){return encodeURIComponent(e).replace(/%3A/gi,":").replace(/%24/g,"$").replace(/%2C/gi,",").replace(/%20/g,"+").replace(/%5B/gi,"[").replace(/%5D/gi,"]")}function je(e,t,r){if(!t)return e;var n,o=r&&r.encode||Ae,i=r&&r.serialize;if(n=i?i(t,r):ye.isURLSearchParams(t)?t.toString():new Te(t,r).toString(o)){var a=e.indexOf("#");-1!==a&&(e=e.slice(0,a)),e+=(-1===e.indexOf("?")?"?":"&")+n}return e}ke.append=function(e,t){this._pairs.push([e,t])},ke.toString=function(e){var t=e?function(t){return e.call(this,t,Re)}:Re;return this._pairs.map((function(e){return t(e[0])+"="+t(e[1])}),"").join("&")};var Pe=function(){function e(){d(this,e),this.handlers=[]}return y(e,[{key:"use",value:function(e,t,r){return this.handlers.push({fulfilled:e,rejected:t,synchronous:!!r&&r.synchronous,runWhen:r?r.runWhen:null}),this.handlers.length-1}},{key:"eject",value:function(e){this.handlers[e]&&(this.handlers[e]=null)}},{key:"clear",value:function(){this.handlers&&(this.handlers=[])}},{key:"forEach",value:function(e){ye.forEach(this.handlers,(function(t){null!==t&&e(t)}))}}]),e}(),Le={silentJSONParsing:!0,forcedJSONParsing:!0,clarifyTimeoutError:!1},Ne={isBrowser:!0,classes:{URLSearchParams:"undefined"!=typeof URLSearchParams?URLSearchParams:Te,FormData:"undefined"!=typeof FormData?FormData:null,Blob:"undefined"!=typeof Blob?Blob:null},protocols:["http","https","file","blob","url","data"]},_e="undefined"!=typeof window&&"undefined"!=typeof document,Ce="object"===("undefined"==typeof navigator?"undefined":f(navigator))&&navigator||void 0,Fe=_e&&(!Ce||["ReactNative","NativeScript","NS"].indexOf(Ce.product)<0),Ue="undefined"!=typeof WorkerGlobalScope&&self instanceof WorkerGlobalScope&&"function"==typeof self.importScripts,Be=_e&&window.location.href||"http://localhost",De=u(u({},Object.freeze({__proto__:null,hasBrowserEnv:_e,hasStandardBrowserWebWorkerEnv:Ue,hasStandardBrowserEnv:Fe,navigator:Ce,origin:Be})),Ne);function Ie(e){function t(e,r,n,o){var i=e[o++];if("__proto__"===i)return!0;var a=Number.isFinite(+i),u=o>=e.length;return i=!i&&ye.isArray(n)?n.length:i,u?(ye.hasOwnProp(n,i)?n[i]=[n[i],r]:n[i]=r,!a):(n[i]&&ye.isObject(n[i])||(n[i]=[]),t(e,r,n[i],o)&&ye.isArray(n[i])&&(n[i]=function(e){var t,r,n={},o=Object.keys(e),i=o.length;for(t=0;t<i;t++)n[r=o[t]]=e[r];return n}(n[i])),!a)}if(ye.isFormData(e)&&ye.isFunction(e.entries)){var r={};return ye.forEachEntry(e,(function(e,n){t(function(e){return ye.matchAll(/\w+|\[(\w*)]/g,e).map((function(e){return"[]"===e[0]?"":e[1]||e[0]}))}(e),n,r,0)})),r}return null}var qe={transitional:Le,adapter:["xhr","http","fetch"],transformRequest:[function(e,t){var r,n=t.getContentType()||"",o=n.indexOf("application/json")>-1,i=ye.isObject(e);if(i&&ye.isHTMLForm(e)&&(e=new FormData(e)),ye.isFormData(e))return o?JSON.stringify(Ie(e)):e;if(ye.isArrayBuffer(e)||ye.isBuffer(e)||ye.isStream(e)||ye.isFile(e)||ye.isBlob(e)||ye.isReadableStream(e))return e;if(ye.isArrayBufferView(e))return e.buffer;if(ye.isURLSearchParams(e))return t.setContentType("application/x-www-form-urlencoded;charset=utf-8",!1),e.toString();if(i){if(n.indexOf("application/x-www-form-urlencoded")>-1)return function(e,t){return xe(e,new De.classes.URLSearchParams,Object.assign({visitor:function(e,t,r,n){return De.isNode&&ye.isBuffer(e)?(this.append(t,e.toString("base64")),!1):n.defaultVisitor.apply(this,arguments)}},t))}(e,this.formSerializer).toString();if((r=ye.isFileList(e))||n.indexOf("multipart/form-data")>-1){var a=this.env&&this.env.FormData;return xe(r?{"files[]":e}:e,a&&new a,this.formSerializer)}}return i||o?(t.setContentType("application/json",!1),function(e,t,r){if(ye.isString(e))try{return(t||JSON.parse)(e),ye.trim(e)}catch(e){if("SyntaxError"!==e.name)throw e}return(r||JSON.stringify)(e)}(e)):e}],transformResponse:[function(e){var t=this.transitional||qe.transitional,r=t&&t.forcedJSONParsing,n="json"===this.responseType;if(ye.isResponse(e)||ye.isReadableStream(e))return e;if(e&&ye.isString(e)&&(r&&!this.responseType||n)){var o=!(t&&t.silentJSONParsing)&&n;try{return JSON.parse(e)}catch(e){if(o){if("SyntaxError"===e.name)throw me.from(e,me.ERR_BAD_RESPONSE,this,null,this.response);throw e}}}return e}],timeout:0,xsrfCookieName:"XSRF-TOKEN",xsrfHeaderName:"X-XSRF-TOKEN",maxContentLength:-1,maxBodyLength:-1,env:{FormData:De.classes.FormData,Blob:De.classes.Blob},validateStatus:function(e){return e>=200&&e<300},headers:{common:{Accept:"application/json, text/plain, */*","Content-Type":void 0}}};ye.forEach(["delete","get","head","post","put","patch"],(function(e){qe.headers[e]={}}));var Me=qe,ze=ye.toObjectSet(["age","authorization","content-length","content-type","etag","expires","from","host","if-modified-since","if-unmodified-since","last-modified","location","max-forwards","proxy-authorization","referer","retry-after","user-agent"]),He=Symbol("internals");function Je(e){return e&&String(e).trim().toLowerCase()}function We(e){return!1===e||null==e?e:ye.isArray(e)?e.map(We):String(e)}function Ge(e,t,r,n,o){return ye.isFunction(n)?n.call(this,t,r):(o&&(t=r),ye.isString(t)?ye.isString(n)?-1!==t.indexOf(n):ye.isRegExp(n)?n.test(t):void 0:void 0)}var Ke=function(e,t){function r(e){d(this,r),e&&this.set(e)}return y(r,[{key:"set",value:function(e,t,r){var n=this;function o(e,t,r){var o=Je(t);if(!o)throw new Error("header name must be a non-empty string");var i=ye.findKey(n,o);(!i||void 0===n[i]||!0===r||void 0===r&&!1!==n[i])&&(n[i||t]=We(e))}var i=function(e,t){return ye.forEach(e,(function(e,r){return o(e,r,t)}))};if(ye.isPlainObject(e)||e instanceof this.constructor)i(e,t);else if(ye.isString(e)&&(e=e.trim())&&!/^[-_a-zA-Z0-9^`|~,!#$%&'*+.]+$/.test(e.trim()))i(function(e){var t,r,n,o={};return e&&e.split("\n").forEach((function(e){n=e.indexOf(":"),t=e.substring(0,n).trim().toLowerCase(),r=e.substring(n+1).trim(),!t||o[t]&&ze[t]||("set-cookie"===t?o[t]?o[t].push(r):o[t]=[r]:o[t]=o[t]?o[t]+", "+r:r)})),o}(e),t);else if(ye.isHeaders(e)){var a,u=function(e,t){var r="undefined"!=typeof Symbol&&e[Symbol.iterator]||e["@@iterator"];if(!r){if(Array.isArray(e)||(r=O(e))||t&&e&&"number"==typeof e.length){r&&(e=r);var n=0,o=function(){};return{s:o,n:function(){return n>=e.length?{done:!0}:{done:!1,value:e[n++]}},e:function(e){throw e},f:o}}throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}var i,a=!0,u=!1;return{s:function(){r=r.call(e)},n:function(){var e=r.next();return a=e.done,e},e:function(e){u=!0,i=e},f:function(){try{a||null==r.return||r.return()}finally{if(u)throw i}}}}(e.entries());try{for(u.s();!(a=u.n()).done;){var s=b(a.value,2),c=s[0];o(s[1],c,r)}}catch(e){u.e(e)}finally{u.f()}}else null!=e&&o(t,e,r);return this}},{key:"get",value:function(e,t){if(e=Je(e)){var r=ye.findKey(this,e);if(r){var n=this[r];if(!t)return n;if(!0===t)return function(e){for(var t,r=Object.create(null),n=/([^\s,;=]+)\s*(?:=\s*([^,;]+))?/g;t=n.exec(e);)r[t[1]]=t[2];return r}(n);if(ye.isFunction(t))return t.call(this,n,r);if(ye.isRegExp(t))return t.exec(n);throw new TypeError("parser must be boolean|regexp|function")}}}},{key:"has",value:function(e,t){if(e=Je(e)){var r=ye.findKey(this,e);return!(!r||void 0===this[r]||t&&!Ge(0,this[r],r,t))}return!1}},{key:"delete",value:function(e,t){var r=this,n=!1;function o(e){if(e=Je(e)){var o=ye.findKey(r,e);!o||t&&!Ge(0,r[o],o,t)||(delete r[o],n=!0)}}return ye.isArray(e)?e.forEach(o):o(e),n}},{key:"clear",value:function(e){for(var t=Object.keys(this),r=t.length,n=!1;r--;){var o=t[r];e&&!Ge(0,this[o],o,e,!0)||(delete this[o],n=!0)}return n}},{key:"normalize",value:function(e){var t=this,r={};return ye.forEach(this,(function(n,o){var i=ye.findKey(r,o);if(i)return t[i]=We(n),void delete t[o];var a=e?function(e){return e.trim().toLowerCase().replace(/([a-z\d])(\w*)/g,(function(e,t,r){return t.toUpperCase()+r}))}(o):String(o).trim();a!==o&&delete t[o],t[a]=We(n),r[a]=!0})),this}},{key:"concat",value:function(){for(var e,t=arguments.length,r=new Array(t),n=0;n<t;n++)r[n]=arguments[n];return(e=this.constructor).concat.apply(e,[this].concat(r))}},{key:"toJSON",value:function(e){var t=Object.create(null);return ye.forEach(this,(function(r,n){null!=r&&!1!==r&&(t[n]=e&&ye.isArray(r)?r.join(", "):r)})),t}},{key:Symbol.iterator,value:function(){return Object.entries(this.toJSON())[Symbol.iterator]()}},{key:"toString",value:function(){return Object.entries(this.toJSON()).map((function(e){var t=b(e,2);return t[0]+": "+t[1]})).join("\n")}},{key:Symbol.toStringTag,get:function(){return"AxiosHeaders"}}],[{key:"from",value:function(e){return e instanceof this?e:new this(e)}},{key:"concat",value:function(e){for(var t=new this(e),r=arguments.length,n=new Array(r>1?r-1:0),o=1;o<r;o++)n[o-1]=arguments[o];return n.forEach((function(e){return t.set(e)})),t}},{key:"accessor",value:function(e){var t=(this[He]=this[He]={accessors:{}}).accessors,r=this.prototype;function n(e){var n=Je(e);t[n]||(!function(e,t){var r=ye.toCamelCase(" "+t);["get","set","has"].forEach((function(n){Object.defineProperty(e,n+r,{value:function(e,r,o){return this[n].call(this,t,e,r,o)},configurable:!0})}))}(r,e),t[n]=!0)}return ye.isArray(e)?e.forEach(n):n(e),this}}]),r}();Ke.accessor(["Content-Type","Content-Length","Accept","Accept-Encoding","User-Agent","Authorization"]),ye.reduceDescriptors(Ke.prototype,(function(e,t){var r=e.value,n=t[0].toUpperCase()+t.slice(1);return{get:function(){return r},set:function(e){this[n]=e}}})),ye.freezeMethods(Ke);var Ve=Ke;function Xe(e,t){var r=this||Me,n=t||r,o=Ve.from(n.headers),i=n.data;return ye.forEach(e,(function(e){i=e.call(r,i,o.normalize(),t?t.status:void 0)})),o.normalize(),i}function $e(e){return!(!e||!e.__CANCEL__)}function Ye(e,t,r){me.call(this,null==e?"canceled":e,me.ERR_CANCELED,t,r),this.name="CanceledError"}function Qe(e,t,r){var n=r.config.validateStatus;r.status&&n&&!n(r.status)?t(new me("Request failed with status code "+r.status,[me.ERR_BAD_REQUEST,me.ERR_BAD_RESPONSE][Math.floor(r.status/100)-4],r.config,r.request,r)):e(r)}function Ze(e,t){e=e||10;var r,n=new Array(e),o=new Array(e),i=0,a=0;return t=void 0!==t?t:1e3,function(u){var s=Date.now(),c=o[a];r||(r=s),n[i]=u,o[i]=s;for(var f=a,l=0;f!==i;)l+=n[f++],f%=e;if((i=(i+1)%e)===a&&(a=(a+1)%e),!(s-r<t)){var h=c&&s-c;return h?Math.round(1e3*l/h):void 0}}}function et(e,t){var r,n,o=0,i=1e3/t,a=function(t){var i=arguments.length>1&&void 0!==arguments[1]?arguments[1]:Date.now();o=i,r=null,n&&(clearTimeout(n),n=null),e.apply(null,t)};return[function(){for(var e=Date.now(),t=e-o,u=arguments.length,s=new Array(u),c=0;c<u;c++)s[c]=arguments[c];t>=i?a(s,e):(r=s,n||(n=setTimeout((function(){n=null,a(r)}),i-t)))},function(){return r&&a(r)}]}ye.inherits(Ye,me,{__CANCEL__:!0});var tt=function(e,t){var r=arguments.length>2&&void 0!==arguments[2]?arguments[2]:3,n=0,o=Ze(50,250);return et((function(r){var i=r.loaded,a=r.lengthComputable?r.total:void 0,u=i-n,s=o(u);n=i;var c=m({loaded:i,total:a,progress:a?i/a:void 0,bytes:u,rate:s||void 0,estimated:s&&a&&i<=a?(a-i)/s:void 0,event:r,lengthComputable:null!=a},t?"download":"upload",!0);e(c)}),r)},rt=function(e,t){var r=null!=e;return[function(n){return t[0]({lengthComputable:r,total:e,loaded:n})},t[1]]},nt=function(e){return function(){for(var t=arguments.length,r=new Array(t),n=0;n<t;n++)r[n]=arguments[n];return ye.asap((function(){return e.apply(void 0,r)}))}},ot=De.hasStandardBrowserEnv?function(){var e,t=De.navigator&&/(msie|trident)/i.test(De.navigator.userAgent),r=document.createElement("a");function n(e){var n=e;return t&&(r.setAttribute("href",n),n=r.href),r.setAttribute("href",n),{href:r.href,protocol:r.protocol?r.protocol.replace(/:$/,""):"",host:r.host,search:r.search?r.search.replace(/^\?/,""):"",hash:r.hash?r.hash.replace(/^#/,""):"",hostname:r.hostname,port:r.port,pathname:"/"===r.pathname.charAt(0)?r.pathname:"/"+r.pathname}}return e=n(window.location.href),function(t){var r=ye.isString(t)?n(t):t;return r.protocol===e.protocol&&r.host===e.host}}():function(){return!0},it=De.hasStandardBrowserEnv?{write:function(e,t,r,n,o,i){var a=[e+"="+encodeURIComponent(t)];ye.isNumber(r)&&a.push("expires="+new Date(r).toGMTString()),ye.isString(n)&&a.push("path="+n),ye.isString(o)&&a.push("domain="+o),!0===i&&a.push("secure"),document.cookie=a.join("; ")},read:function(e){var t=document.cookie.match(new RegExp("(^|;\\s*)("+e+")=([^;]*)"));return t?decodeURIComponent(t[3]):null},remove:function(e){this.write(e,"",Date.now()-864e5)}}:{write:function(){},read:function(){return null},remove:function(){}};function at(e,t){return e&&!/^([a-z][a-z\d+\-.]*:)?\/\//i.test(t)?function(e,t){return t?e.replace(/\/?\/$/,"")+"/"+t.replace(/^\/+/,""):e}(e,t):t}var ut=function(e){return e instanceof Ve?u({},e):e};function st(e,t){t=t||{};var r={};function n(e,t,r){return ye.isPlainObject(e)&&ye.isPlainObject(t)?ye.merge.call({caseless:r},e,t):ye.isPlainObject(t)?ye.merge({},t):ye.isArray(t)?t.slice():t}function o(e,t,r){return ye.isUndefined(t)?ye.isUndefined(e)?void 0:n(void 0,e,r):n(e,t,r)}function i(e,t){if(!ye.isUndefined(t))return n(void 0,t)}function a(e,t){return ye.isUndefined(t)?ye.isUndefined(e)?void 0:n(void 0,e):n(void 0,t)}function u(r,o,i){return i in t?n(r,o):i in e?n(void 0,r):void 0}var s={url:i,method:i,data:i,baseURL:a,transformRequest:a,transformResponse:a,paramsSerializer:a,timeout:a,timeoutMessage:a,withCredentials:a,withXSRFToken:a,adapter:a,responseType:a,xsrfCookieName:a,xsrfHeaderName:a,onUploadProgress:a,onDownloadProgress:a,decompress:a,maxContentLength:a,maxBodyLength:a,beforeRedirect:a,transport:a,httpAgent:a,httpsAgent:a,cancelToken:a,socketPath:a,responseEncoding:a,validateStatus:u,headers:function(e,t){return o(ut(e),ut(t),!0)}};return ye.forEach(Object.keys(Object.assign({},e,t)),(function(n){var i=s[n]||o,a=i(e[n],t[n],n);ye.isUndefined(a)&&i!==u||(r[n]=a)})),r}var ct,ft,lt=function(e){var t,r,n=st({},e),o=n.data,i=n.withXSRFToken,a=n.xsrfHeaderName,u=n.xsrfCookieName,s=n.headers,c=n.auth;if(n.headers=s=Ve.from(s),n.url=je(at(n.baseURL,n.url),e.params,e.paramsSerializer),c&&s.set("Authorization","Basic "+btoa((c.username||"")+":"+(c.password?unescape(encodeURIComponent(c.password)):""))),ye.isFormData(o))if(De.hasStandardBrowserEnv||De.hasStandardBrowserWebWorkerEnv)s.setContentType(void 0);else if(!1!==(t=s.getContentType())){var f=t?t.split(";").map((function(e){return e.trim()})).filter(Boolean):[],l=w(r=f)||E(r)||O(r)||x(),h=l[0],p=l.slice(1);s.setContentType([h||"multipart/form-data"].concat(g(p)).join("; "))}if(De.hasStandardBrowserEnv&&(i&&ye.isFunction(i)&&(i=i(n)),i||!1!==i&&ot(n.url))){var d=a&&u&&it.read(u);d&&s.set(a,d)}return n},ht="undefined"!=typeof XMLHttpRequest&&function(e){return new Promise((function(t,r){var n,o,i,a,u,s=lt(e),c=s.data,f=Ve.from(s.headers).normalize(),l=s.responseType,h=s.onUploadProgress,p=s.onDownloadProgress;function d(){a&&a(),u&&u(),s.cancelToken&&s.cancelToken.unsubscribe(n),s.signal&&s.signal.removeEventListener("abort",n)}var v=new XMLHttpRequest;function y(){if(v){var n=Ve.from("getAllResponseHeaders"in v&&v.getAllResponseHeaders());Qe((function(e){t(e),d()}),(function(e){r(e),d()}),{data:l&&"text"!==l&&"json"!==l?v.response:v.responseText,status:v.status,statusText:v.statusText,headers:n,config:e,request:v}),v=null}}if(v.open(s.method.toUpperCase(),s.url,!0),v.timeout=s.timeout,"onloadend"in v?v.onloadend=y:v.onreadystatechange=function(){v&&4===v.readyState&&(0!==v.status||v.responseURL&&0===v.responseURL.indexOf("file:"))&&setTimeout(y)},v.onabort=function(){v&&(r(new me("Request aborted",me.ECONNABORTED,e,v)),v=null)},v.onerror=function(){r(new me("Network Error",me.ERR_NETWORK,e,v)),v=null},v.ontimeout=function(){var t=s.timeout?"timeout of "+s.timeout+"ms exceeded":"timeout exceeded",n=s.transitional||Le;s.timeoutErrorMessage&&(t=s.timeoutErrorMessage),r(new me(t,n.clarifyTimeoutError?me.ETIMEDOUT:me.ECONNABORTED,e,v)),v=null},void 0===c&&f.setContentType(null),"setRequestHeader"in v&&ye.forEach(f.toJSON(),(function(e,t){v.setRequestHeader(t,e)})),ye.isUndefined(s.withCredentials)||(v.withCredentials=!!s.withCredentials),l&&"json"!==l&&(v.responseType=s.responseType),p){var m=b(tt(p,!0),2);i=m[0],u=m[1],v.addEventListener("progress",i)}if(h&&v.upload){var g=b(tt(h),2);o=g[0],a=g[1],v.upload.addEventListener("progress",o),v.upload.addEventListener("loadend",a)}(s.cancelToken||s.signal)&&(n=function(t){v&&(r(!t||t.type?new Ye(null,e,v):t),v.abort(),v=null)},s.cancelToken&&s.cancelToken.subscribe(n),s.signal&&(s.signal.aborted?n():s.signal.addEventListener("abort",n)));var w,E,O=(w=s.url,(E=/^([-+\w]{1,25})(:?\/\/|:)/.exec(w))&&E[1]||"");O&&-1===De.protocols.indexOf(O)?r(new me("Unsupported protocol "+O+":",me.ERR_BAD_REQUEST,e)):v.send(c||null)}))},pt=function(e,t){var r=(e=e?e.filter(Boolean):[]).length;if(t||r){var n,o=new AbortController,i=function(e){if(!n){n=!0,u();var t=e instanceof Error?e:this.reason;o.abort(t instanceof me?t:new Ye(t instanceof Error?t.message:t))}},a=t&&setTimeout((function(){a=null,i(new me("timeout ".concat(t," of ms exceeded"),me.ETIMEDOUT))}),t),u=function(){e&&(a&&clearTimeout(a),a=null,e.forEach((function(e){e.unsubscribe?e.unsubscribe(i):e.removeEventListener("abort",i)})),e=null)};e.forEach((function(e){return e.addEventListener("abort",i)}));var s=o.signal;return s.unsubscribe=function(){return ye.asap(u)},s}},dt=s().mark((function e(t,r){var n,o,i;return s().wrap((function(e){for(;;)switch(e.prev=e.next){case 0:if(n=t.byteLength,r&&!(n<r)){e.next=5;break}return e.next=4,t;case 4:return e.abrupt("return");case 5:o=0;case 6:if(!(o<n)){e.next=13;break}return i=o+r,e.next=10,t.slice(o,i);case 10:o=i,e.next=6;break;case 13:case"end":return e.stop()}}),e)})),vt=function(){var e=l(s().mark((function e(t,o){var a,u,c,f,l,h;return s().wrap((function(e){for(;;)switch(e.prev=e.next){case 0:a=!1,u=!1,e.prev=2,f=n(yt(t));case 4:return e.next=6,i(f.next());case 6:if(!(a=!(l=e.sent).done)){e.next=12;break}return h=l.value,e.delegateYield(r(n(dt(h,o))),"t0",9);case 9:a=!1,e.next=4;break;case 12:e.next=18;break;case 14:e.prev=14,e.t1=e.catch(2),u=!0,c=e.t1;case 18:if(e.prev=18,e.prev=19,!a||null==f.return){e.next=23;break}return e.next=23,i(f.return());case 23:if(e.prev=23,!u){e.next=26;break}throw c;case 26:return e.finish(23);case 27:return e.finish(18);case 28:case"end":return e.stop()}}),e,null,[[2,14,18,28],[19,,23,27]])})));return function(t,r){return e.apply(this,arguments)}}(),yt=function(){var e=l(s().mark((function e(t){var o,a,u,c;return s().wrap((function(e){for(;;)switch(e.prev=e.next){case 0:if(!t[Symbol.asyncIterator]){e.next=3;break}return e.delegateYield(r(n(t)),"t0",2);case 2:return e.abrupt("return");case 3:o=t.getReader(),e.prev=4;case 5:return e.next=7,i(o.read());case 7:if(a=e.sent,u=a.done,c=a.value,!u){e.next=12;break}return e.abrupt("break",16);case 12:return e.next=14,c;case 14:e.next=5;break;case 16:return e.prev=16,e.next=19,i(o.cancel());case 19:return e.finish(16);case 20:case"end":return e.stop()}}),e,null,[[4,,16,20]])})));return function(t){return e.apply(this,arguments)}}(),mt=function(e,t,r,n){var o,i=vt(e,t),a=0,u=function(e){o||(o=!0,n&&n(e))};return new ReadableStream({pull:function(e){return p(s().mark((function t(){var n,o,c,f,l;return s().wrap((function(t){for(;;)switch(t.prev=t.next){case 0:return t.prev=0,t.next=3,i.next();case 3:if(n=t.sent,o=n.done,c=n.value,!o){t.next=10;break}return u(),e.close(),t.abrupt("return");case 10:f=c.byteLength,r&&(l=a+=f,r(l)),e.enqueue(new Uint8Array(c)),t.next=19;break;case 15:throw t.prev=15,t.t0=t.catch(0),u(t.t0),t.t0;case 19:case"end":return t.stop()}}),t,null,[[0,15]])})))()},cancel:function(e){return u(e),i.return()}},{highWaterMark:2})},bt="function"==typeof fetch&&"function"==typeof Request&&"function"==typeof Response,gt=bt&&"function"==typeof ReadableStream,wt=bt&&("function"==typeof TextEncoder?(ct=new TextEncoder,function(e){return ct.encode(e)}):function(){var e=p(s().mark((function e(t){return s().wrap((function(e){for(;;)switch(e.prev=e.next){case 0:return e.t0=Uint8Array,e.next=3,new Response(t).arrayBuffer();case 3:return e.t1=e.sent,e.abrupt("return",new e.t0(e.t1));case 5:case"end":return e.stop()}}),e)})));return function(t){return e.apply(this,arguments)}}()),Et=function(e){try{for(var t=arguments.length,r=new Array(t>1?t-1:0),n=1;n<t;n++)r[n-1]=arguments[n];return!!e.apply(void 0,r)}catch(e){return!1}},Ot=gt&&Et((function(){var e=!1,t=new Request(De.origin,{body:new ReadableStream,method:"POST",get duplex(){return e=!0,"half"}}).headers.has("Content-Type");return e&&!t})),St=gt&&Et((function(){return ye.isReadableStream(new Response("").body)})),xt={stream:St&&function(e){return e.body}};bt&&(ft=new Response,["text","arrayBuffer","blob","formData","stream"].forEach((function(e){!xt[e]&&(xt[e]=ye.isFunction(ft[e])?function(t){return t[e]()}:function(t,r){throw new me("Response type '".concat(e,"' is not supported"),me.ERR_NOT_SUPPORT,r)})})));var Rt=function(){var e=p(s().mark((function e(t){var r;return s().wrap((function(e){for(;;)switch(e.prev=e.next){case 0:if(null!=t){e.next=2;break}return e.abrupt("return",0);case 2:if(!ye.isBlob(t)){e.next=4;break}return e.abrupt("return",t.size);case 4:if(!ye.isSpecCompliantForm(t)){e.next=9;break}return r=new Request(De.origin,{method:"POST",body:t}),e.next=8,r.arrayBuffer();case 8:case 15:return e.abrupt("return",e.sent.byteLength);case 9:if(!ye.isArrayBufferView(t)&&!ye.isArrayBuffer(t)){e.next=11;break}return e.abrupt("return",t.byteLength);case 11:if(ye.isURLSearchParams(t)&&(t+=""),!ye.isString(t)){e.next=16;break}return e.next=15,wt(t);case 16:case"end":return e.stop()}}),e)})));return function(t){return e.apply(this,arguments)}}(),Tt=function(){var e=p(s().mark((function e(t,r){var n;return s().wrap((function(e){for(;;)switch(e.prev=e.next){case 0:return n=ye.toFiniteNumber(t.getContentLength()),e.abrupt("return",null==n?Rt(r):n);case 2:case"end":return e.stop()}}),e)})));return function(t,r){return e.apply(this,arguments)}}(),kt=bt&&function(){var e=p(s().mark((function e(t){var r,n,o,i,a,c,f,l,h,p,d,v,y,m,g,w,E,O,S,x,R,T,k,A,j,P,L,N,_,C,F,U,B,D;return s().wrap((function(e){for(;;)switch(e.prev=e.next){case 0:if(r=lt(t),n=r.url,o=r.method,i=r.data,a=r.signal,c=r.cancelToken,f=r.timeout,l=r.onDownloadProgress,h=r.onUploadProgress,p=r.responseType,d=r.headers,v=r.withCredentials,y=void 0===v?"same-origin":v,m=r.fetchOptions,p=p?(p+"").toLowerCase():"text",g=pt([a,c&&c.toAbortSignal()],f),E=g&&g.unsubscribe&&function(){g.unsubscribe()},e.prev=4,e.t0=h&&Ot&&"get"!==o&&"head"!==o,!e.t0){e.next=11;break}return e.next=9,Tt(d,i);case 9:e.t1=O=e.sent,e.t0=0!==e.t1;case 11:if(!e.t0){e.next=15;break}S=new Request(n,{method:"POST",body:i,duplex:"half"}),ye.isFormData(i)&&(x=S.headers.get("content-type"))&&d.setContentType(x),S.body&&(R=rt(O,tt(nt(h))),T=b(R,2),k=T[0],A=T[1],i=mt(S.body,65536,k,A));case 15:return ye.isString(y)||(y=y?"include":"omit"),j="credentials"in Request.prototype,w=new Request(n,u(u({},m),{},{signal:g,method:o.toUpperCase(),headers:d.normalize().toJSON(),body:i,duplex:"half",credentials:j?y:void 0})),e.next=20,fetch(w);case 20:return P=e.sent,L=St&&("stream"===p||"response"===p),St&&(l||L&&E)&&(N={},["status","statusText","headers"].forEach((function(e){N[e]=P[e]})),_=ye.toFiniteNumber(P.headers.get("content-length")),C=l&&rt(_,tt(nt(l),!0))||[],F=b(C,2),U=F[0],B=F[1],P=new Response(mt(P.body,65536,U,(function(){B&&B(),E&&E()})),N)),p=p||"text",e.next=26,xt[ye.findKey(xt,p)||"text"](P,t);case 26:return D=e.sent,!L&&E&&E(),e.next=30,new Promise((function(e,r){Qe(e,r,{data:D,headers:Ve.from(P.headers),status:P.status,statusText:P.statusText,config:t,request:w})}));case 30:return e.abrupt("return",e.sent);case 33:if(e.prev=33,e.t2=e.catch(4),E&&E(),!e.t2||"TypeError"!==e.t2.name||!/fetch/i.test(e.t2.message)){e.next=38;break}throw Object.assign(new me("Network Error",me.ERR_NETWORK,t,w),{cause:e.t2.cause||e.t2});case 38:throw me.from(e.t2,e.t2&&e.t2.code,t,w);case 39:case"end":return e.stop()}}),e,null,[[4,33]])})));return function(t){return e.apply(this,arguments)}}(),At={http:null,xhr:ht,fetch:kt};ye.forEach(At,(function(e,t){if(e){try{Object.defineProperty(e,"name",{value:t})}catch(e){}Object.defineProperty(e,"adapterName",{value:t})}}));var jt=function(e){return"- ".concat(e)},Pt=function(e){return ye.isFunction(e)||null===e||!1===e},Lt=function(e){for(var t,r,n=(e=ye.isArray(e)?e:[e]).length,o={},i=0;i<n;i++){var a=void 0;if(r=t=e[i],!Pt(t)&&void 0===(r=At[(a=String(t)).toLowerCase()]))throw new me("Unknown adapter '".concat(a,"'"));if(r)break;o[a||"#"+i]=r}if(!r){var u=Object.entries(o).map((function(e){var t=b(e,2),r=t[0],n=t[1];return"adapter ".concat(r," ")+(!1===n?"is not supported by the environment":"is not available in the build")}));throw new me("There is no suitable adapter to dispatch the request "+(n?u.length>1?"since :\n"+u.map(jt).join("\n"):" "+jt(u[0]):"as no adapter specified"),"ERR_NOT_SUPPORT")}return r};function Nt(e){if(e.cancelToken&&e.cancelToken.throwIfRequested(),e.signal&&e.signal.aborted)throw new Ye(null,e)}function _t(e){return Nt(e),e.headers=Ve.from(e.headers),e.data=Xe.call(e,e.transformRequest),-1!==["post","put","patch"].indexOf(e.method)&&e.headers.setContentType("application/x-www-form-urlencoded",!1),Lt(e.adapter||Me.adapter)(e).then((function(t){return Nt(e),t.data=Xe.call(e,e.transformResponse,t),t.headers=Ve.from(t.headers),t}),(function(t){return $e(t)||(Nt(e),t&&t.response&&(t.response.data=Xe.call(e,e.transformResponse,t.response),t.response.headers=Ve.from(t.response.headers))),Promise.reject(t)}))}var Ct="1.7.7",Ft={};["object","boolean","number","function","string","symbol"].forEach((function(e,t){Ft[e]=function(r){return f(r)===e||"a"+(t<1?"n ":" ")+e}}));var Ut={};Ft.transitional=function(e,t,r){function n(e,t){return"[Axios v1.7.7] Transitional option '"+e+"'"+t+(r?". "+r:"")}return function(r,o,i){if(!1===e)throw new me(n(o," has been removed"+(t?" in "+t:"")),me.ERR_DEPRECATED);return t&&!Ut[o]&&(Ut[o]=!0,console.warn(n(o," has been deprecated since v"+t+" and will be removed in the near future"))),!e||e(r,o,i)}};var Bt={assertOptions:function(e,t,r){if("object"!==f(e))throw new me("options must be an object",me.ERR_BAD_OPTION_VALUE);for(var n=Object.keys(e),o=n.length;o-- >0;){var i=n[o],a=t[i];if(a){var u=e[i],s=void 0===u||a(u,i,e);if(!0!==s)throw new me("option "+i+" must be "+s,me.ERR_BAD_OPTION_VALUE)}else if(!0!==r)throw new me("Unknown option "+i,me.ERR_BAD_OPTION)}},validators:Ft},Dt=Bt.validators,It=function(){function e(t){d(this,e),this.defaults=t,this.interceptors={request:new Pe,response:new Pe}}var t;return y(e,[{key:"request",value:(t=p(s().mark((function e(t,r){var n,o;return s().wrap((function(e){for(;;)switch(e.prev=e.next){case 0:return e.prev=0,e.next=3,this._request(t,r);case 3:return e.abrupt("return",e.sent);case 6:if(e.prev=6,e.t0=e.catch(0),e.t0 instanceof Error){Error.captureStackTrace?Error.captureStackTrace(n={}):n=new Error,o=n.stack?n.stack.replace(/^.+\n/,""):"";try{e.t0.stack?o&&!String(e.t0.stack).endsWith(o.replace(/^.+\n.+\n/,""))&&(e.t0.stack+="\n"+o):e.t0.stack=o}catch(e){}}throw e.t0;case 10:case"end":return e.stop()}}),e,this,[[0,6]])}))),function(e,r){return t.apply(this,arguments)})},{key:"_request",value:function(e,t){"string"==typeof e?(t=t||{}).url=e:t=e||{};var r=t=st(this.defaults,t),n=r.transitional,o=r.paramsSerializer,i=r.headers;void 0!==n&&Bt.assertOptions(n,{silentJSONParsing:Dt.transitional(Dt.boolean),forcedJSONParsing:Dt.transitional(Dt.boolean),clarifyTimeoutError:Dt.transitional(Dt.boolean)},!1),null!=o&&(ye.isFunction(o)?t.paramsSerializer={serialize:o}:Bt.assertOptions(o,{encode:Dt.function,serialize:Dt.function},!0)),t.method=(t.method||this.defaults.method||"get").toLowerCase();var a=i&&ye.merge(i.common,i[t.method]);i&&ye.forEach(["delete","get","head","post","put","patch","common"],(function(e){delete i[e]})),t.headers=Ve.concat(a,i);var u=[],s=!0;this.interceptors.request.forEach((function(e){"function"==typeof e.runWhen&&!1===e.runWhen(t)||(s=s&&e.synchronous,u.unshift(e.fulfilled,e.rejected))}));var c,f=[];this.interceptors.response.forEach((function(e){f.push(e.fulfilled,e.rejected)}));var l,h=0;if(!s){var p=[_t.bind(this),void 0];for(p.unshift.apply(p,u),p.push.apply(p,f),l=p.length,c=Promise.resolve(t);h<l;)c=c.then(p[h++],p[h++]);return c}l=u.length;var d=t;for(h=0;h<l;){var v=u[h++],y=u[h++];try{d=v(d)}catch(e){y.call(this,e);break}}try{c=_t.call(this,d)}catch(e){return Promise.reject(e)}for(h=0,l=f.length;h<l;)c=c.then(f[h++],f[h++]);return c}},{key:"getUri",value:function(e){return je(at((e=st(this.defaults,e)).baseURL,e.url),e.params,e.paramsSerializer)}}]),e}();ye.forEach(["delete","get","head","options"],(function(e){It.prototype[e]=function(t,r){return this.request(st(r||{},{method:e,url:t,data:(r||{}).data}))}})),ye.forEach(["post","put","patch"],(function(e){function t(t){return function(r,n,o){return this.request(st(o||{},{method:e,headers:t?{"Content-Type":"multipart/form-data"}:{},url:r,data:n}))}}It.prototype[e]=t(),It.prototype[e+"Form"]=t(!0)}));var qt=It,Mt=function(){function e(t){if(d(this,e),"function"!=typeof t)throw new TypeError("executor must be a function.");var r;this.promise=new Promise((function(e){r=e}));var n=this;this.promise.then((function(e){if(n._listeners){for(var t=n._listeners.length;t-- >0;)n._listeners[t](e);n._listeners=null}})),this.promise.then=function(e){var t,r=new Promise((function(e){n.subscribe(e),t=e})).then(e);return r.cancel=function(){n.unsubscribe(t)},r},t((function(e,t,o){n.reason||(n.reason=new Ye(e,t,o),r(n.reason))}))}return y(e,[{key:"throwIfRequested",value:function(){if(this.reason)throw this.reason}},{key:"subscribe",value:function(e){this.reason?e(this.reason):this._listeners?this._listeners.push(e):this._listeners=[e]}},{key:"unsubscribe",value:function(e){if(this._listeners){var t=this._listeners.indexOf(e);-1!==t&&this._listeners.splice(t,1)}}},{key:"toAbortSignal",value:function(){var e=this,t=new AbortController,r=function(e){t.abort(e)};return this.subscribe(r),t.signal.unsubscribe=function(){return e.unsubscribe(r)},t.signal}}],[{key:"source",value:function(){var t;return{token:new e((function(e){t=e})),cancel:t}}}]),e}(),zt=Mt;var Ht={Continue:100,SwitchingProtocols:101,Processing:102,EarlyHints:103,Ok:200,Created:201,Accepted:202,NonAuthoritativeInformation:203,NoContent:204,ResetContent:205,PartialContent:206,MultiStatus:207,AlreadyReported:208,ImUsed:226,MultipleChoices:300,MovedPermanently:301,Found:302,SeeOther:303,NotModified:304,UseProxy:305,Unused:306,TemporaryRedirect:307,PermanentRedirect:308,BadRequest:400,Unauthorized:401,PaymentRequired:402,Forbidden:403,NotFound:404,MethodNotAllowed:405,NotAcceptable:406,ProxyAuthenticationRequired:407,RequestTimeout:408,Conflict:409,Gone:410,LengthRequired:411,PreconditionFailed:412,PayloadTooLarge:413,UriTooLong:414,UnsupportedMediaType:415,RangeNotSatisfiable:416,ExpectationFailed:417,ImATeapot:418,MisdirectedRequest:421,UnprocessableEntity:422,Locked:423,FailedDependency:424,TooEarly:425,UpgradeRequired:426,PreconditionRequired:428,TooManyRequests:429,RequestHeaderFieldsTooLarge:431,UnavailableForLegalReasons:451,InternalServerError:500,NotImplemented:501,BadGateway:502,ServiceUnavailable:503,GatewayTimeout:504,HttpVersionNotSupported:505,VariantAlsoNegotiates:506,InsufficientStorage:507,LoopDetected:508,NotExtended:510,NetworkAuthenticationRequired:511};Object.entries(Ht).forEach((function(e){var t=b(e,2),r=t[0],n=t[1];Ht[n]=r}));var Jt=Ht;var Wt=function e(t){var r=new qt(t),n=R(qt.prototype.request,r);return ye.extend(n,qt.prototype,r,{allOwnKeys:!0}),ye.extend(n,r,null,{allOwnKeys:!0}),n.create=function(r){return e(st(t,r))},n}(Me);return Wt.Axios=qt,Wt.CanceledError=Ye,Wt.CancelToken=zt,Wt.isCancel=$e,Wt.VERSION=Ct,Wt.toFormData=xe,Wt.AxiosError=me,Wt.Cancel=Wt.CanceledError,Wt.all=function(e){return Promise.all(e)},Wt.spread=function(e){return function(t){return e.apply(null,t)}},Wt.isAxiosError=function(e){return ye.isObject(e)&&!0===e.isAxiosError},Wt.mergeConfig=st,Wt.AxiosHeaders=Ve,Wt.formToJSON=function(e){return Ie(ye.isHTMLForm(e)?new FormData(e):e)},Wt.getAdapter=Lt,Wt.HttpStatusCode=Jt,Wt.default=Wt,Wt}));
  2 +//# sourceMappingURL=axios.min.js.map
... ...
  1 +import request from './axios.js'
  2 +
  3 +const API = {
  4 + URL: '3d_component/'
  5 +}
  6 +
  7 +export function saveOrUpdateThreeJsModel(params = {}) {
  8 + return request({
  9 + url: API['URL'] + params['id'],
  10 + method: 'POST',
  11 + data: params['data']
  12 + })
  13 +}
  14 +
  15 +export function getThreeJsModel(id) {
  16 + return request({
  17 + url: API['URL'] + id,
  18 + method: 'get',
  19 + })
  20 +}
  21 +
... ...
  1 +import axios from 'axios'
  2 +import { BASE_URL } from './config.js'
  3 +import { getJwtToken } from '@/utils/external/auth'
  4 +
  5 +const service = axios.create({
  6 + baseURL: BASE_URL,
  7 + timeout: 5000
  8 +})
  9 +
  10 +service.interceptors.request.use(
  11 + config => {
  12 + const token = getJwtToken()
  13 + if (token) {
  14 + config.headers['x-authorization'] = `Bearer ${token}`
  15 + }
  16 + return config
  17 + },
  18 + error => {
  19 + return Promise.reject(error)
  20 + }
  21 +)
  22 +
  23 +service.interceptors.response.use(
  24 + response => {
  25 + const { status, data } = response
  26 + if (status === 200) {
  27 + const { code } = data
  28 + switch (code) {
  29 + case 1003:
  30 + return Promise.reject(data)
  31 + default:
  32 + return data
  33 + }
  34 + }
  35 + },
  36 + error => {
  37 + if (error.response) {
  38 + const { status, data } = error.response
  39 + if (status === 2001) {
  40 + }
  41 + }
  42 + return Promise.reject(error)
  43 + }
  44 +)
  45 +
  46 +export default service
... ...
  1 +let threeFilePath = ''
  2 +
  3 +const VITE_GLOB_PROXY = import.meta.env.VITE_GLOB_PROXY
  4 +
  5 +const VITE_GLOB_API_URL_PREFIX = import.meta.env.VITE_GLOB_API_URL_PREFIX
  6 +
  7 +try {
  8 + const getViteGlobProxy= Array.isArray(JSON.parse(VITE_GLOB_PROXY)) ? JSON.parse(VITE_GLOB_PROXY)[0][1] : VITE_GLOB_PROXY
  9 + threeFilePath = getViteGlobProxy
  10 +} catch {
  11 + // 生产环境是字符串,json parse 报错,直接等于字符串即可
  12 + threeFilePath = getViteGlobProxy
  13 +}
  14 +
  15 +export const BASE_URL = `${threeFilePath}${VITE_GLOB_API_URL_PREFIX}`
... ...
1   -import * as THREE from 'three';
  1 +import * as THREE from 'three'
2 2
3   -import { Editor } from './js/Editor.js';
4   -import { Viewport } from './js/Viewport.js';
5   -import { Toolbar } from './js/Toolbar.js';
6   -import { Script } from './js/Script.js';
7   -import { Player } from './js/Player.js';
8   -import { Sidebar } from './js/Sidebar.js';
9   -import { Menubar } from './js/Menubar.js';
10   -import { Resizer } from './js/Resizer.js';
  3 +import { Editor } from './js/Editor.js'
  4 +import { Viewport } from './js/Viewport.js'
  5 +import { Toolbar } from './js/Toolbar.js'
  6 +import { Script } from './js/Script.js'
  7 +import { Player } from './js/Player.js'
  8 +import { Sidebar } from './js/Sidebar.js'
  9 +import { Menubar } from './js/Menubar.js'
  10 +import { Resizer } from './js/Resizer.js'
  11 +import { getThreeJsModel } from './js/libs/http/api.js'
11 12
12   -window.URL = window.URL || window.webkitURL;
13   -window.BlobBuilder = window.BlobBuilder || window.WebKitBlobBuilder || window.MozBlobBuilder;
  13 +window.URL = window.URL || window.webkitURL
  14 +window.BlobBuilder = window.BlobBuilder || window.WebKitBlobBuilder || window.MozBlobBuilder
14 15
15 16 //
16 17
17   -const editor = new Editor();
  18 +const editor = new Editor()
18 19
19   -window.editor = editor; // Expose editor to Console
20   -window.THREE = THREE; // Expose THREE to APP Scripts and Console
  20 +window.editor = editor // Expose editor to Console
  21 +window.THREE = THREE // Expose THREE to APP Scripts and Console
21 22
22   -const viewport = new Viewport(editor);
23   -document.body.appendChild(viewport.dom);
  23 +const viewport = new Viewport(editor)
  24 +document.body.appendChild(viewport.dom)
24 25
25   -const toolbar = new Toolbar(editor);
26   -document.body.appendChild(toolbar.dom);
  26 +const toolbar = new Toolbar(editor)
  27 +document.body.appendChild(toolbar.dom)
27 28
28   -const script = new Script(editor);
29   -document.body.appendChild(script.dom);
  29 +const script = new Script(editor)
  30 +document.body.appendChild(script.dom)
30 31
31   -const player = new Player(editor);
32   -document.body.appendChild(player.dom);
  32 +const player = new Player(editor)
  33 +document.body.appendChild(player.dom)
33 34
34   -const sidebar = new Sidebar(editor);
35   -document.body.appendChild(sidebar.dom);
  35 +const sidebar = new Sidebar(editor)
  36 +document.body.appendChild(sidebar.dom)
36 37
37   -const menubar = new Menubar(editor);
38   -document.body.appendChild(menubar.dom);
  38 +const menubar = new Menubar(editor)
  39 +document.body.appendChild(menubar.dom)
39 40
40   -const resizer = new Resizer(editor);
41   -document.body.appendChild(resizer.dom);
  41 +const resizer = new Resizer(editor)
  42 +document.body.appendChild(resizer.dom)
42 43
43 44 //
44 45
45   -editor.storage.init(function () {
  46 +/**
  47 + * THINGS_KIT 修改
  48 + */
  49 +
  50 +editor.storage.init(async function () {
  51 + const paramsStr = window.location.search
  52 + const params = new URLSearchParams(paramsStr)
  53 + const file_uuid = params.get('three_file_uuid')
  54 + const fileData = await getThreeJsModel(file_uuid)
  55 + if (!fileData) return
  56 + if (!fileData['content']) return
  57 + await editor.fromJSON(fileData['content'])
  58 + const selected = editor.config.getKey('selected')
  59 + if (selected !== undefined) {
  60 + editor.selectByUuid(selected)
  61 + }
  62 + let timeout
  63 + function saveState() {
  64 + if (editor.config.getKey('autosave') === false) {
  65 + return
  66 + }
  67 + clearTimeout(timeout)
  68 + timeout = setTimeout(function () {
  69 + editor.signals.savingStarted.dispatch()
46 70
47   - editor.storage.get(async function (state) {
  71 + timeout = setTimeout(function () {
  72 + editor.storage.set(editor.toJSON())
48 73
49   - if (isLoadingFromHash) return;
  74 + editor.signals.savingFinished.dispatch()
  75 + }, 100)
  76 + }, 1000)
  77 + }
  78 + const signals = editor.signals
  79 + signals.geometryChanged.add(saveState)
  80 + signals.objectAdded.add(saveState)
  81 + signals.objectChanged.add(saveState)
  82 + signals.objectRemoved.add(saveState)
  83 + signals.materialChanged.add(saveState)
  84 + signals.sceneBackgroundChanged.add(saveState)
  85 + signals.sceneEnvironmentChanged.add(saveState)
  86 + signals.sceneFogChanged.add(saveState)
  87 + signals.sceneGraphChanged.add(saveState)
  88 + signals.scriptChanged.add(saveState)
  89 + signals.historyChanged.add(saveState)
  90 +})
  91 +//
50 92
51   - if (state !== undefined) {
  93 +// editor.storage.init( function () {
52 94
53   - await editor.fromJSON(state);
  95 +// editor.storage.get( async function ( state ) {
54 96
55   - }
  97 +// if ( isLoadingFromHash ) return;
56 98
57   - const selected = editor.config.getKey('selected');
  99 +// if ( state !== undefined ) {
58 100
59   - if (selected !== undefined) {
  101 +// await editor.fromJSON( state );
60 102
61   - editor.selectByUuid(selected);
  103 +// }
62 104
63   - }
  105 +// const selected = editor.config.getKey( 'selected' );
64 106
65   - });
  107 +// if ( selected !== undefined ) {
66 108
67   - //
  109 +// editor.selectByUuid( selected );
68 110
69   - let timeout;
  111 +// }
70 112
71   - function saveState() {
  113 +// } );
72 114
73   - if (editor.config.getKey('autosave') === false) {
  115 +// //
74 116
75   - return;
  117 +// let timeout;
76 118
77   - }
  119 +// function saveState() {
78 120
79   - clearTimeout(timeout);
  121 +// if ( editor.config.getKey( 'autosave' ) === false ) {
80 122
81   - timeout = setTimeout(function () {
  123 +// return;
82 124
83   - editor.signals.savingStarted.dispatch();
  125 +// }
84 126
85   - timeout = setTimeout(function () {
  127 +// clearTimeout( timeout );
86 128
87   - editor.storage.set(editor.toJSON());
  129 +// timeout = setTimeout( function () {
88 130
89   - editor.signals.savingFinished.dispatch();
  131 +// editor.signals.savingStarted.dispatch();
90 132
91   - }, 100);
  133 +// timeout = setTimeout( function () {
92 134
93   - }, 1000);
  135 +// editor.storage.set( editor.toJSON() );
94 136
95   - }
  137 +// editor.signals.savingFinished.dispatch();
96 138
97   - const signals = editor.signals;
  139 +// }, 100 );
98 140
99   - signals.geometryChanged.add(saveState);
100   - signals.objectAdded.add(saveState);
101   - signals.objectChanged.add(saveState);
102   - signals.objectRemoved.add(saveState);
103   - signals.materialChanged.add(saveState);
104   - signals.sceneBackgroundChanged.add(saveState);
105   - signals.sceneEnvironmentChanged.add(saveState);
106   - signals.sceneFogChanged.add(saveState);
107   - signals.sceneGraphChanged.add(saveState);
108   - signals.scriptChanged.add(saveState);
109   - signals.historyChanged.add(saveState);
  141 +// }, 1000 );
110 142
111   -});
  143 +// }
112 144
113   -//
  145 +// const signals = editor.signals;
114 146
115   -document.addEventListener('dragover', function (event) {
  147 +// signals.geometryChanged.add( saveState );
  148 +// signals.objectAdded.add( saveState );
  149 +// signals.objectChanged.add( saveState );
  150 +// signals.objectRemoved.add( saveState );
  151 +// signals.materialChanged.add( saveState );
  152 +// signals.sceneBackgroundChanged.add( saveState );
  153 +// signals.sceneEnvironmentChanged.add( saveState );
  154 +// signals.sceneFogChanged.add( saveState );
  155 +// signals.sceneGraphChanged.add( saveState );
  156 +// signals.scriptChanged.add( saveState );
  157 +// signals.historyChanged.add( saveState );
116 158
117   - event.preventDefault();
118   - event.dataTransfer.dropEffect = 'copy';
  159 +// } );
119 160
120   -});
  161 +//
121 162
122   -document.addEventListener('drop', function (event) {
  163 +document.addEventListener('dragover', function (event) {
  164 + event.preventDefault()
  165 + event.dataTransfer.dropEffect = 'copy'
  166 +})
123 167
124   - event.preventDefault();
  168 +document.addEventListener('drop', function (event) {
  169 + event.preventDefault()
125 170
126   - if (event.dataTransfer.types[0] === 'text/plain') return; // Outliner drop
  171 + if (event.dataTransfer.types[0] === 'text/plain') return // Outliner drop
127 172
128 173 if (event.dataTransfer.items) {
129   -
130 174 // DataTransferItemList supports folders
131 175
132   - editor.loader.loadItemList(event.dataTransfer.items);
133   -
  176 + editor.loader.loadItemList(event.dataTransfer.items)
134 177 } else {
135   -
136   - editor.loader.loadFiles(event.dataTransfer.files);
137   -
  178 + editor.loader.loadFiles(event.dataTransfer.files)
138 179 }
139   -
140   -});
  180 +})
141 181
142 182 function onWindowResize() {
143   -
144   - editor.signals.windowResize.dispatch();
145   -
  183 + editor.signals.windowResize.dispatch()
146 184 }
147 185
148   -window.addEventListener('resize', onWindowResize);
  186 +window.addEventListener('resize', onWindowResize)
149 187
150   -onWindowResize();
  188 +onWindowResize()
151 189
152 190 //
153 191
154   -let isLoadingFromHash = false;
155   -const hash = window.location.hash;
  192 +let isLoadingFromHash = false
  193 +const hash = window.location.hash
156 194
157 195 if (hash.slice(1, 6) === 'file=') {
158   -
159   - const file = hash.slice(6);
  196 + const file = hash.slice(6)
160 197
161 198 if (confirm(editor.strings.getKey('prompt/file/open'))) {
162   -
163   - const loader = new THREE.FileLoader();
164   - loader.crossOrigin = '';
  199 + const loader = new THREE.FileLoader()
  200 + loader.crossOrigin = ''
165 201 loader.load(file, function (text) {
  202 + editor.clear()
  203 + editor.fromJSON(JSON.parse(text))
  204 + })
166 205
167   - editor.clear();
168   - editor.fromJSON(JSON.parse(text));
169   -
170   - });
171   -
172   - isLoadingFromHash = true;
173   -
  206 + isLoadingFromHash = true
174 207 }
175   -
176 208 }
177 209
178 210 // ServiceWorker
179 211
180 212 if ('serviceWorker' in navigator) {
181   -
182 213 try {
183   -
184   - // navigator.serviceWorker.register(new URL('./sw.js', import.meta.url));
185   -
186   - } catch (error) {
187   -
188   - }
189   -
  214 + navigator.serviceWorker.register('sw.js')
  215 + } catch (error) {}
190 216 }
... ...
1 1 import { defHttp } from '@/utils/external/http/axios'
2   -import { BaseSaveContentParams, BaseUpdateContentParams, DataViewListRecord, DateViewConfigurationInfoType } from './model/contentModel'
  2 +import {
  3 + BaseSaveContentParams,
  4 + BaseUpdateContentParams,
  5 + DataViewListRecord,
  6 + DateViewConfigurationInfoType
  7 +} from './model/contentModel'
3 8 import type { ErrorMessageMode, PaginationResult } from '/#/external/axios'
  9 +import { ChartType } from '@/views/three/items'
4 10
5 11 enum Api {
6 12 //大屏设计器
7 13 DATA_VIEW_CONTENT = '/data_view/content',
8 14 //大屏内容
9 15 DATA_VIEW = '/data_view',
10   - FILE_UPLOAD = '/oss/upload'
  16 + FILE_UPLOAD = '/oss/upload',
  17 + // 针对3D模型
  18 + THREE_JS_MODEL = '/3d_component'
11 19 }
12 20
13 21 /**
... ... @@ -91,9 +99,73 @@ export const saveDataViewList = (data: object) => {
91 99 */
92 100 export const uploadFile = async (file: FormData, mode: ErrorMessageMode = 'modal') => {
93 101 return defHttp.post(
94   - { url: Api.FILE_UPLOAD, params: file},
  102 + { url: Api.FILE_UPLOAD, params: file },
95 103 {
96 104 errorMessageMode: mode
97 105 }
98 106 )
99 107 }
  108 +
  109 +/**
  110 + * @description: 3D模型编辑 delete api
  111 + */
  112 +export function threeJsDeleteApi(ids: string[], mode: ErrorMessageMode = 'modal') {
  113 + return defHttp.delete(
  114 + {
  115 + url: Api.THREE_JS_MODEL +'?ids=' + ids,
  116 + },
  117 + {
  118 + errorMessageMode: mode
  119 + }
  120 + )
  121 +}
  122 +
  123 +/**
  124 + * @description: 3D模型编辑 分页 api
  125 + */
  126 +export const getThreeJsModelList = (params: object) => {
  127 + return defHttp.get<PaginationResult<ChartType>>({
  128 + url: Api.THREE_JS_MODEL + '/page',
  129 + params
  130 + })
  131 +}
  132 +
  133 +/**
  134 + * @description: 3D模型 发布 api
  135 + */
  136 +export const putThreeJsModelRelease = (params: { id: string | number; state: number }) => {
  137 + return defHttp.put({
  138 + url: Api.THREE_JS_MODEL + '/publish' + '/' + params['id'] + '/' + params['state'],
  139 + params
  140 + })
  141 +}
  142 +
  143 +/**
  144 + * @description: 3D模型 更新 api
  145 + */
  146 +export const updateThreeJsModel = (params: { id: string; name: string }) => {
  147 + return defHttp.put({
  148 + url: Api.THREE_JS_MODEL +'/' + params['id'] + '/' + params['name'],
  149 + params
  150 + })
  151 +}
  152 +
  153 +/**
  154 + * @description: 3D模型 保存 api
  155 + */
  156 +export function saveOrUpdateThreeJsModel(params: Recordable) {
  157 + return defHttp.post({
  158 + url: Api.THREE_JS_MODEL +'/' + params['id'],
  159 + data: params['data']
  160 + })
  161 +}
  162 +
  163 +/**
  164 + * @description: 3D模型 获取 api
  165 + */
  166 +export function getThreeJsModel(id: string) {
  167 + return defHttp.get({
  168 + url: Api.THREE_JS_MODEL +'/' + id,
  169 + })
  170 +}
  171 +
... ...
  1 +<svg xmlns="http://www.w3.org/2000/svg" width="128" height="128" class="icon" viewBox="0 0 1024 1024"><path fill="#82c9f5" d="M400.01 789.13a274.123 274.123 0 1 0-167.497-216.99A274.123 274.123 0 0 0 400.01 789.13zm0 0"/><path fill="#0D51A2" d="M590.344 480.63h-4.714L146.773 355.312a15.197 15.197 0 0 1-10.971-12.516 14.872 14.872 0 0 1 6.258-15.685l282.25-203.58a23.324 23.324 0 0 1 14.14-3.17l438.858 125.318a15.197 15.197 0 0 1 10.971 12.515 14.872 14.872 0 0 1-6.257 15.685L599.69 477.542a22.268 22.268 0 0 1-9.427 3.17zm-402.61-147.424 400.985 114.59L837.81 267.623 436.825 153.275zm79.075 341.334 46.974-33.971 18.367 25.844-46.974 33.97zm97.524-31.452-18.774-25.03 78.344-56.402a21.049 21.049 0 0 1 14.141-3.17l94.03 26.657-8.127 29.745-86.146-25.031zm190.334-17.31 8.614-30.151 78.344 22.024-8.614 30.15zm110.039 31.532 8.615-30.15 63.228 18.041-8.615 30.151zm0 0"/><path fill="#0D51A2" d="M590.344 919.324h-4.714L146.773 794.006a15.197 15.197 0 0 1-10.971-12.515 14.872 14.872 0 0 1 6.258-15.685l94.029-67.373 19.017 24.869-67.373 48.761L588.8 886.41l249.01-180.175-78.343-21.943 8.127-29.745 109.633 31.37a15.197 15.197 0 0 1 10.971 12.516 14.872 14.872 0 0 1-6.258 15.685L599.934 917.78c-3.17 0-6.258 1.544-9.427 1.544zm0 0"/><path fill="#0D51A2" d="M136.046 339.708h31.37v438.857h-31.37zm438.857 125.318h31.37v438.857h-31.614zM417.97 480.63h31.37v94.029h-31.37zm0-109.633h31.37v78.344h-31.37zm0-94.03h31.37v62.74h-31.37zm0-141.003h31.37V245.68h-31.37zm438.857 125.319h31.37V700.14h-31.37zm0 0"/><path fill="#82c9f5" d="M637.318 903.64a46.974 46.974 0 1 1-46.974-46.975 46.161 46.161 0 0 1 46.974 46.974zm0 0"/><path fill="#0D51A2" d="M590.344 966.298a62.659 62.659 0 1 1 62.66-62.659 62.822 62.822 0 0 1-62.66 62.66zm0-94.029a31.289 31.289 0 1 0 31.37 31.37 31.451 31.451 0 0 0-31.37-31.37zm0 0"/><path fill="#82c9f5" d="M919.324 699.977a46.974 46.974 0 1 1-46.974-46.974 46.161 46.161 0 0 1 46.974 46.974zm0 0"/><path fill="#0D51A2" d="M872.27 762.636a62.659 62.659 0 1 1 62.333-62.659 62.822 62.822 0 0 1-62.659 62.66zm0-94.029a31.37 31.37 0 1 0 31.288 31.37 31.451 31.451 0 0 0-31.289-31.37zm0 0"/><path fill="#82c9f5" d="M480.63 574.659a46.974 46.974 0 1 1-46.974-46.974 46.161 46.161 0 0 1 46.974 46.974zm0 0"/><path fill="#0D51A2" d="M433.656 637.318a62.659 62.659 0 1 1 62.659-62.659 62.822 62.822 0 0 1-62.66 62.66zm0-94.03a31.37 31.37 0 1 0 31.289 31.29 31.451 31.451 0 0 0-31.29-31.29zm0 0"/><path fill="#82c9f5" d="M198.705 778.321a46.161 46.161 0 0 1-46.974 46.974 46.974 46.974 0 1 1 0-94.029 46.161 46.161 0 0 1 46.974 46.974zm0 0"/><path fill="#0D51A2" d="M151.73 840.98a62.659 62.659 0 1 1 62.66-62.659 62.822 62.822 0 0 1-62.66 62.66zm0-94.029a31.289 31.289 0 1 0 31.371 31.37 31.451 31.451 0 0 0-31.37-31.37zm0 0"/><path fill="#82c9f5" d="M198.705 339.708a46.161 46.161 0 0 1-46.974 46.974 46.974 46.974 0 0 1 0-94.03 46.161 46.161 0 0 1 46.974 46.975zm0 0"/><path fill="#0D51A2" d="M151.73 402.367a62.659 62.659 0 1 1 62.66-62.66 56.889 56.889 0 0 1-18.773 43.887 56.889 56.889 0 0 1-43.886 18.773zm0-94.03a31.37 31.37 0 0 0 0 62.66 32.508 32.508 0 0 0 31.371-31.37 31.451 31.451 0 0 0-31.37-31.37zm0 0"/><path fill="#82c9f5" d="M480.63 136.046a46.974 46.974 0 0 1-94.03 0 46.974 46.974 0 0 1 94.03 0zm0 0"/><path fill="#0D51A2" d="M433.656 198.705a56.889 56.889 0 0 1-43.56-18.774 61.846 61.846 0 0 1-18.774-43.885 62.659 62.659 0 1 1 62.659 62.659zm0-94.03a31.451 31.451 0 0 0-31.37 31.29 32.508 32.508 0 0 0 31.37 31.37 31.289 31.289 0 0 0 0-62.66zm0 0"/><path fill="#82c9f5" d="M919.324 261.364a46.974 46.974 0 1 1-46.974-46.974 46.161 46.161 0 0 1 46.974 46.974zm0 0"/><path fill="#0D51A2" d="M872.27 324.023a62.659 62.659 0 1 1 62.333-62.66 62.822 62.822 0 0 1-62.659 62.66zm0-94.03a31.289 31.289 0 1 0 31.288 31.29 31.451 31.451 0 0 0-31.289-31.29zm0 0"/><path fill="#82c9f5" d="M637.318 465.026a46.974 46.974 0 1 1-46.974-46.974 46.161 46.161 0 0 1 46.974 46.974zm0 0"/><path fill="#0D51A2" d="M590.344 527.685a62.659 62.659 0 1 1 62.66-62.659 62.822 62.822 0 0 1-62.66 62.66zm0-94.03a31.289 31.289 0 1 0 31.37 31.371 31.451 31.451 0 0 0-31.37-31.37zm0 0"/></svg>
\ No newline at end of file
... ...
  1 +<svg xmlns="http://www.w3.org/2000/svg" width="128" height="128" class="icon" viewBox="0 0 1024 1024"><path fill="#82c9f5" d="M400.01 789.13a274.123 274.123 0 1 0-167.497-216.99A274.123 274.123 0 0 0 400.01 789.13zm0 0"/><path fill="#0D51A2" d="M590.344 480.63h-4.714L146.773 355.312a15.197 15.197 0 0 1-10.971-12.516 14.872 14.872 0 0 1 6.258-15.685l282.25-203.58a23.324 23.324 0 0 1 14.14-3.17l438.858 125.318a15.197 15.197 0 0 1 10.971 12.515 14.872 14.872 0 0 1-6.257 15.685L599.69 477.542a22.268 22.268 0 0 1-9.427 3.17zm-402.61-147.424 400.985 114.59L837.81 267.623 436.825 153.275zm79.075 341.334 46.974-33.971 18.367 25.844-46.974 33.97zm97.524-31.452-18.774-25.03 78.344-56.402a21.049 21.049 0 0 1 14.141-3.17l94.03 26.657-8.127 29.745-86.146-25.031zm190.334-17.31 8.614-30.151 78.344 22.024-8.614 30.15zm110.039 31.532 8.615-30.15 63.228 18.041-8.615 30.151zm0 0"/><path fill="#0D51A2" d="M590.344 919.324h-4.714L146.773 794.006a15.197 15.197 0 0 1-10.971-12.515 14.872 14.872 0 0 1 6.258-15.685l94.029-67.373 19.017 24.869-67.373 48.761L588.8 886.41l249.01-180.175-78.343-21.943 8.127-29.745 109.633 31.37a15.197 15.197 0 0 1 10.971 12.516 14.872 14.872 0 0 1-6.258 15.685L599.934 917.78c-3.17 0-6.258 1.544-9.427 1.544zm0 0"/><path fill="#0D51A2" d="M136.046 339.708h31.37v438.857h-31.37zm438.857 125.318h31.37v438.857h-31.614zM417.97 480.63h31.37v94.029h-31.37zm0-109.633h31.37v78.344h-31.37zm0-94.03h31.37v62.74h-31.37zm0-141.003h31.37V245.68h-31.37zm438.857 125.319h31.37V700.14h-31.37zm0 0"/><path fill="#82c9f5" d="M637.318 903.64a46.974 46.974 0 1 1-46.974-46.975 46.161 46.161 0 0 1 46.974 46.974zm0 0"/><path fill="#0D51A2" d="M590.344 966.298a62.659 62.659 0 1 1 62.66-62.659 62.822 62.822 0 0 1-62.66 62.66zm0-94.029a31.289 31.289 0 1 0 31.37 31.37 31.451 31.451 0 0 0-31.37-31.37zm0 0"/><path fill="#82c9f5" d="M919.324 699.977a46.974 46.974 0 1 1-46.974-46.974 46.161 46.161 0 0 1 46.974 46.974zm0 0"/><path fill="#0D51A2" d="M872.27 762.636a62.659 62.659 0 1 1 62.333-62.659 62.822 62.822 0 0 1-62.659 62.66zm0-94.029a31.37 31.37 0 1 0 31.288 31.37 31.451 31.451 0 0 0-31.289-31.37zm0 0"/><path fill="#82c9f5" d="M480.63 574.659a46.974 46.974 0 1 1-46.974-46.974 46.161 46.161 0 0 1 46.974 46.974zm0 0"/><path fill="#0D51A2" d="M433.656 637.318a62.659 62.659 0 1 1 62.659-62.659 62.822 62.822 0 0 1-62.66 62.66zm0-94.03a31.37 31.37 0 1 0 31.289 31.29 31.451 31.451 0 0 0-31.29-31.29zm0 0"/><path fill="#82c9f5" d="M198.705 778.321a46.161 46.161 0 0 1-46.974 46.974 46.974 46.974 0 1 1 0-94.029 46.161 46.161 0 0 1 46.974 46.974zm0 0"/><path fill="#0D51A2" d="M151.73 840.98a62.659 62.659 0 1 1 62.66-62.659 62.822 62.822 0 0 1-62.66 62.66zm0-94.029a31.289 31.289 0 1 0 31.371 31.37 31.451 31.451 0 0 0-31.37-31.37zm0 0"/><path fill="#82c9f5" d="M198.705 339.708a46.161 46.161 0 0 1-46.974 46.974 46.974 46.974 0 0 1 0-94.03 46.161 46.161 0 0 1 46.974 46.975zm0 0"/><path fill="#0D51A2" d="M151.73 402.367a62.659 62.659 0 1 1 62.66-62.66 56.889 56.889 0 0 1-18.773 43.887 56.889 56.889 0 0 1-43.886 18.773zm0-94.03a31.37 31.37 0 0 0 0 62.66 32.508 32.508 0 0 0 31.371-31.37 31.451 31.451 0 0 0-31.37-31.37zm0 0"/><path fill="#82c9f5" d="M480.63 136.046a46.974 46.974 0 0 1-94.03 0 46.974 46.974 0 0 1 94.03 0zm0 0"/><path fill="#0D51A2" d="M433.656 198.705a56.889 56.889 0 0 1-43.56-18.774 61.846 61.846 0 0 1-18.774-43.885 62.659 62.659 0 1 1 62.659 62.659zm0-94.03a31.451 31.451 0 0 0-31.37 31.29 32.508 32.508 0 0 0 31.37 31.37 31.289 31.289 0 0 0 0-62.66zm0 0"/><path fill="#82c9f5" d="M919.324 261.364a46.974 46.974 0 1 1-46.974-46.974 46.161 46.161 0 0 1 46.974 46.974zm0 0"/><path fill="#0D51A2" d="M872.27 324.023a62.659 62.659 0 1 1 62.333-62.66 62.822 62.822 0 0 1-62.659 62.66zm0-94.03a31.289 31.289 0 1 0 31.288 31.29 31.451 31.451 0 0 0-31.289-31.29zm0 0"/><path fill="#82c9f5" d="M637.318 465.026a46.974 46.974 0 1 1-46.974-46.974 46.161 46.161 0 0 1 46.974 46.974zm0 0"/><path fill="#0D51A2" d="M590.344 527.685a62.659 62.659 0 1 1 62.66-62.659 62.822 62.822 0 0 1-62.66 62.66zm0-94.03a31.289 31.289 0 1 0 31.37 31.371 31.451 31.451 0 0 0-31.37-31.37zm0 0"/></svg>
\ No newline at end of file
... ...
... ... @@ -32,11 +32,15 @@ export enum PageEnum {
32 32
33 33 // 首页
34 34 BASE_HOME = '/project',
  35 + THREE_HOME = '/three_project',
35 36 BASE_HOME_NAME = 'Project',
  37 + THREE_HOME_NAME = 'ThreeProject',
36 38
37 39 // 我的项目
38 40 BASE_HOME_ITEMS = '/project/items',
39   - BASE_HOME_ITEMS_NAME = 'Project-Items',
  41 + BASE_HOME_ITEMS_NAME = 'Project-Items',
  42 + THREE_HOME_ITEMS = '/three/items',
  43 + THREE_HOME_ITEMS_NAME = 'Three-Items',
40 44
41 45 // 我的模板
42 46 BASE_HOME_TEMPLATE = '/project/my-template',
... ...
... ... @@ -105,5 +105,6 @@ export default {
105 105 customRequest:'Custom request',
106 106 publicInterface:'Public interface',
107 107 },
108   - color:'Color'
  108 + color:'Color',
  109 + threeDModel:'3D model',
109 110 }
... ...
... ... @@ -6,6 +6,9 @@ export default {
6 6 createNowText: 'Create now',
7 7 successText: 'Success',
8 8 operationSuccessText: 'Operation successful!',
  9 + deleteSuccessText: 'Delete successful!',
  10 + cancelReleaseSuccessText: 'Cancel release successful',
  11 + releaseSuccessText: 'Release successful',
9 12 failText: 'Fail',
10 13 delText: 'Delete',
11 14 noneText: 'None',
... ...
... ... @@ -11,5 +11,6 @@ export default {
11 11 // items
12 12 release: 'Release',
13 13 unreleased: 'Unrelease',
14   - last_edit: 'Last edit time'
  14 + last_edit: 'Last edit time',
  15 + three_project:'3D model'
15 16 }
... ...
... ... @@ -30,7 +30,15 @@ const i18n = createI18n({
30 30 messages: {
31 31 [LangEnum.ZH]: zh,
32 32 [LangEnum.EN]: en
33   - }
  33 + },
  34 + /**
  35 + * 解决Not found ‘xx‘ key in ‘x‘ locale messages. 的警告
  36 + */
  37 + silentTranslationWarn: true,
  38 + missingWarn: false,
  39 + silentFallbackWarn: true,
  40 + fallbackWarn: false,
  41 + //
34 42 })
35 43
36 44 export default i18n
... ...
... ... @@ -105,5 +105,6 @@ export default {
105 105 customRequest:'自定义请求',
106 106 publicInterface:'公共接口',
107 107 },
108   - color:'颜色'
  108 + color:'颜色',
  109 + threeDModel:'3D 模型',
109 110 }
... ...
... ... @@ -6,6 +6,9 @@ export default {
6 6 createNowText: '立即创建',
7 7 successText: '成功',
8 8 operationSuccessText: '操作成功!',
  9 + deleteSuccessText: '删除成功',
  10 + cancelReleaseSuccessText: '取消发布成功',
  11 + releaseSuccessText: '发布成功',
9 12 failText: '失败',
10 13 delText: '删除',
11 14 noneText: '暂无',
... ...
... ... @@ -12,5 +12,6 @@ export default {
12 12 // items
13 13 release: '已发布',
14 14 unreleased: '未发布',
15   - last_edit: '最后编辑'
  15 + last_edit: '最后编辑',
  16 + three_project:'3D 模型'
16 17 }
... ...
  1 +import { PublicConfigClass } from '@/packages/public'
  2 +import { CreateComponentType } from '@/packages/index.d'
  3 +import { chartInitConfig } from '@/settings/designSetting'
  4 +import { LoaderConfig } from './index'
  5 +import cloneDeep from 'lodash/cloneDeep'
  6 +
  7 +export const option = {
  8 + dataset: '',
  9 +}
  10 +
  11 +export default class Config extends PublicConfigClass implements CreateComponentType {
  12 + public key = LoaderConfig.key
  13 + public attr = { ...chartInitConfig, w: 600, h: 500, zIndex: 1 }
  14 + public chartConfig = cloneDeep(LoaderConfig)
  15 + public option = cloneDeep(option)
  16 +}
... ...
  1 +<template>
  2 + <!-- <collapse-item :name="t('component.treeConfig')" :expanded="true">
  3 + <setting-item-box :name="t('component.borderConfig')">
  4 + <setting-item :name="t('common.colorText')"> </setting-item>
  5 + </setting-item-box>
  6 + </collapse-item> -->
  7 +</template>
  8 +
  9 +<script setup lang="ts">
  10 +import { PropType } from 'vue'
  11 +import { option } from './config'
  12 +// import { CollapseItem, SettingItemBox, SettingItem } from '@/components/Pages/ChartItemSetting'
  13 +
  14 +defineProps({
  15 + optionData: {
  16 + type: Object as PropType<typeof option>,
  17 + required: true
  18 + }
  19 +})
  20 +
  21 +// const t = window['$t']
  22 +</script>
  23 +
  24 +<style lang="scss" scoped></style>
... ...
  1 +import { ConfigType, PackagesCategoryEnum, ChartFrameEnum } from '@/packages/index.d'
  2 +import { ChatCategoryEnum, ChatCategoryEnumName } from '@/packages/components/Decorates/index.d'
  3 +import { useWidgetKey } from '@/packages/external/useWidgetKey'
  4 +
  5 +const { key, chartKey, conKey } = useWidgetKey('Loader', true)
  6 +export const LoaderConfig: ConfigType = {
  7 + key,
  8 + chartKey,
  9 + conKey,
  10 + title: '3D模型加载器',
  11 + category: ChatCategoryEnum.THREE,
  12 + categoryName: ChatCategoryEnumName.THREE,
  13 + package: PackagesCategoryEnum.DECORATES,
  14 + chartFrame: ChartFrameEnum.STATIC,
  15 + image: 'threeModelDefault.svg'
  16 +}
... ...
  1 +<template>
  2 + <div class="go-content-box">
  3 + <div>
  4 + <vue3dLoader
  5 + ref="vue3dLoaderRef"
  6 + :requestHeader="headers"
  7 + :webGLRendererOptions="webGLRendererOptions"
  8 + :height="h"
  9 + :width="w"
  10 + :filePath="dataset"
  11 + @process="onProcess"
  12 + @load="onLoad"
  13 + :intersectRecursive="true"
  14 + />
  15 + <div v-show="show" class="process">
  16 + <span> 拼命加载中... </span>
  17 + <n-progress type="line" :color="themeColor" :percentage="process" :indicator-placement="'inside'" processing />
  18 + </div>
  19 + </div>
  20 + </div>
  21 +</template>
  22 +<script setup lang="ts">
  23 +import { PropType, toRefs, ref, nextTick, computed } from 'vue'
  24 +import { CreateComponentType } from '@/packages/index.d'
  25 +import { vue3dLoader } from 'vue-3d-loader'
  26 +import { useDesignStore } from '@/store/modules/designStore/designStore'
  27 +import { getJwtToken } from '@/utils/external/auth'
  28 +
  29 +const designStore = useDesignStore()
  30 +
  31 +const props = defineProps({
  32 + chartConfig: {
  33 + type: Object as PropType<CreateComponentType>,
  34 + required: true
  35 + }
  36 +})
  37 +
  38 +const themeColor = computed(() => {
  39 + return designStore.getAppTheme
  40 +})
  41 +
  42 +const vue3dLoaderRef = ref(null)
  43 +
  44 +const headers = {
  45 + 'x-authorization': `Bearer ${getJwtToken()}`
  46 +}
  47 +const webGLRendererOptions = {
  48 + alpha: true, // 透明
  49 + antialias: true, // 抗锯齿
  50 + // fix: 预览三维图像需加上preserveDrawingBuffer: true
  51 + preserveDrawingBuffer: true //缩略图生效需开启
  52 +}
  53 +
  54 +//三维模型加载
  55 +const show = ref(false)
  56 +
  57 +const onLoad = async () => {
  58 + //加载完成
  59 + await nextTick()
  60 + show.value = false
  61 +}
  62 +
  63 +//三维模型进度条
  64 +const process = ref(0)
  65 +
  66 +const onProcess = (event: Recordable) => {
  67 + process.value = Math.floor((event.loaded / event.total) * 100)
  68 +}
  69 +
  70 +const { w, h } = toRefs(props.chartConfig.attr)
  71 +
  72 +const { dataset } = toRefs(props.chartConfig.option) as Recordable
  73 +</script>
  74 +
  75 +<style lang="scss" scoped>
  76 +.go-content-box {
  77 + height: 100%;
  78 + .process {
  79 + position: absolute;
  80 + top: 50%;
  81 + left: 50%;
  82 + width: 50%;
  83 + transform: translate(-50%, -50%);
  84 + }
  85 +}
  86 +</style>
... ...
... ... @@ -21,7 +21,6 @@
21 21 @mousedown="handleMouseDown"
22 22 :position="position"
23 23 :rotation="rotation"
24   - :lights="[lights[lightInput]]"
25 24 :showFps="showFps"
26 25 :intersectRecursive="true"
27 26 :labels="labels"
... ... @@ -93,10 +92,8 @@ const {
93 92 borderConfig,
94 93 position,
95 94 rotation,
96   - lights,
97 95 showFps,
98 96 labels,
99   - lightInput
100 97 } = toRefs(props.chartConfig.option) as any
101 98
102 99 const handleMouseDown = (e:any,d:any)=>{
... ...
... ... @@ -40,6 +40,7 @@ import { OverrideDialConfig } from '@/packages/components/external/Charts/Mores/
40 40 import { PickIconConfig } from '@/packages/components/external/Decorates/Mores/PickIcon'
41 41 import { WeatherConfig } from '@/packages/components/external/Decorates/Mores/Weather'
42 42 import { ThreeDimensionalConfig } from '@/packages/components/external/Decorates/Three/ThreeDimensional'
  43 +// import { LoaderConfig } from '@/packages/components/external/Decorates/Three/Loader'
43 44 import { Headline1Config } from '@/packages/components/external/Decorates/Headline/Headline1'
44 45 import { Headline2Config } from '@/packages/components/external/Decorates/Headline/Headline2'
45 46 import { Subtitle1Config } from '@/packages/components/external/Decorates/Subtitle/Subtitle1'
... ... @@ -90,6 +91,7 @@ export function useInjectLib(packagesList: EPackagesType) {
90 91 addWidgetToCategoryByCategoryName(packagesList, PackagesCategoryEnum.DECORATES, PickIconConfig)//新增小组件图标
91 92 addWidgetToCategoryByCategoryName(packagesList, PackagesCategoryEnum.DECORATES, WeatherConfig)//新增小组件天气
92 93 addWidgetToCategoryByCategoryName(packagesList, PackagesCategoryEnum.DECORATES, ThreeDimensionalConfig)//三维模型
  94 + // addWidgetToCategoryByCategoryName(packagesList, PackagesCategoryEnum.DECORATES, LoaderConfig)//三维模型加载器
93 95 addWidgetToCategoryByCategoryName(packagesList, PackagesCategoryEnum.DECORATES, Headline1Config)//大标题1
94 96 addWidgetToCategoryByCategoryName(packagesList, PackagesCategoryEnum.DECORATES, Headline2Config)//大标题2
95 97 addWidgetToCategoryByCategoryName(packagesList, PackagesCategoryEnum.DECORATES, Subtitle1Config)//小标题1
... ...
... ... @@ -15,14 +15,25 @@ const getChartConfigFile = async (path: string) => {
15 15
16 16 export const createComponent = async (configType: ConfigType) => {
17 17 // eslint-disable-next-line prefer-const
18   - let { key, chartKey, category, package: packageName, redirectComponent, categoryName , conKey} = configType
  18 + // eslint-disable-next-line prefer-const
  19 + let { key, chartKey, category, package: packageName, redirectComponent, categoryName , conKey, isThreeModel} = configType
19 20 // redirectComponent 是给图片组件库和图标组件库使用的
20   - if (redirectComponent) {
  21 + if (!isThreeModel && redirectComponent) {
21 22 const [packageName, categoryName, keyName] = redirectComponent.split('/')
22 23 const filePath = `../components/${packageName}/${categoryName}/${keyName}/config.ts`
23 24 const redirectChart = await getChartConfigFile(filePath)
24 25 return new redirectChart.default()
25 26 }
  27 + // isThreeModel是给3D模型使用的
  28 + if(isThreeModel && redirectComponent) {
  29 + const [packageName, categoryName, keyName] = (redirectComponent as string).split('/')
  30 + const hasExternalPrefix = matchExternalPrefixReg.test(chartKey)
  31 + const filePath = `../components${hasExternalPrefix ? '/external' : ''}/${packageName}/${categoryName}/${keyName}/config.ts`
  32 + const redirectChart = await getChartConfigFile(filePath)
  33 + return new redirectChart.default()
  34 + }
  35 +
  36 +
26 37 /**
27 38 * 兼容之前导入错误的补丁
28 39 */
... ...
... ... @@ -43,6 +43,11 @@ export type ConfigType = {
43 43 icon?: string
44 44 // 事件
45 45 configEvents?: { [T: string]: Function }
  46 + // 区分3D模型标识
  47 + isThreeModel?: false
  48 + // 3D模型数据
  49 + threeModelContent?: any
  50 + threeModelFilePath?: string
46 51 }
47 52
48 53 // 数据请求
... ...
1 1 import type { App } from 'vue'
2 2 import { createRouter, createWebHashHistory, RouteRecordRaw } from 'vue-router'
3 3 import { RedirectRoute } from '@/router/base'
4   -import { createRouterGuards } from './router-guards'
  4 +// import { createRouterGuards } from './router-guards'
5 5 import { PageEnum } from '@/enums/pageEnum'
6 6 import { HttpErrorPage, LoginRoute, ReloadRoute } from '@/router/base'
7 7 import { Layout } from '@/router/constant'
... ... @@ -27,6 +27,7 @@ const RootRoute: Array<RouteRecordRaw> = [
27 27 modules.chartRoutes,
28 28 modules.previewRoutes,
29 29 modules.editRoutes,
  30 + modules.threeRoutes,
30 31 // THINGS_KIT 新增分享路由
31 32 shareRoutes
32 33 ]
... ...
... ... @@ -2,10 +2,12 @@ import projectRoutes from './project.router'
2 2 import chartRoutes from './chart.route'
3 3 import previewRoutes from './preview.route'
4 4 import editRoutes from './edit.route'
  5 +import threeRoutes from './three.router'
5 6
6 7 export default {
7 8 projectRoutes,
8 9 chartRoutes,
9 10 previewRoutes,
10   - editRoutes
  11 + editRoutes,
  12 + threeRoutes
11 13 }
\ No newline at end of file
... ...
  1 +import { RouteRecordRaw } from 'vue-router'
  2 +import { PageEnum } from '@/enums/pageEnum'
  3 +
  4 +// 引入路径
  5 +const importPath = {
  6 + 'PageEnum.THREE_HOME_NAME': () => import('@/views/three/index.vue'),
  7 + 'PageEnum.THREE_HOME_ITEMS_NAME': () => import('@/views/three/items/index.vue'),
  8 +}
  9 +
  10 +const threeRoutes: RouteRecordRaw = {
  11 + path: PageEnum.THREE_HOME,
  12 + name: PageEnum.THREE_HOME_NAME,
  13 + component: importPath['PageEnum.THREE_HOME_NAME'],
  14 + redirect: PageEnum.THREE_HOME_ITEMS,
  15 + meta: {
  16 + title: '项目',
  17 + isRoot: true
  18 + },
  19 + children: [
  20 + {
  21 + path: PageEnum.THREE_HOME_ITEMS,
  22 + name: PageEnum.THREE_HOME_ITEMS_NAME,
  23 + component: importPath['PageEnum.THREE_HOME_ITEMS_NAME'],
  24 + meta: {
  25 + title: '我的项目'
  26 + }
  27 + },
  28 + ]
  29 +}
  30 +
  31 +export default threeRoutes
... ...
... ... @@ -72,6 +72,7 @@ import { icon } from '@/plugins'
72 72 // THINGS_KIT 覆盖原始创建组件逻辑
73 73 import { createComponent } from '@/packages/external/override'
74 74 import omit from 'lodash/omit'
  75 +import { isObject } from '@/utils/external/is'
75 76
76 77 const t: any = window['$t']
77 78
... ... @@ -128,11 +129,17 @@ const dblclickHandle = async (item: ConfigType) => {
128 129 componentInstall(item.conKey, fetchConfigComponent(item))
129 130 // 创建新图表组件
130 131 let newComponent: CreateComponentType = await createComponent(item)
131   - if (item.redirectComponent) {
  132 + if (!item?.isThreeModel && item.redirectComponent) {
132 133 item.dataset && (newComponent.option.dataset = item.dataset)
133 134 newComponent.chartConfig.title = item.title
134 135 newComponent.chartConfig.chartFrame = item.chartFrame
135 136 }
  137 + //3D模型注入
  138 + if (item?.isThreeModel && item.redirectComponent) {
  139 + newComponent.option.dataset = item?.threeModelFilePath
  140 + newComponent.chartConfig.title = item.title
  141 + newComponent.chartConfig.chartFrame = item.chartFrame
  142 + }
136 143 // 添加
137 144 chartEditStore.addComponentList(newComponent, false, true)
138 145 // 选中
... ...
... ... @@ -23,9 +23,12 @@ import { ConfigType } from '@/packages/index.d'
23 23 import { useSettingStore } from '@/store/modules/settingStore/settingStore'
24 24 import { loadAsyncComponent } from '@/utils'
25 25 import { usePackagesStore } from '@/store/modules/packagesStore/packagesStore'
26   -import { PackagesCategoryEnum } from '@/packages/index.d'
  26 +// import { PackagesCategoryEnum } from '@/packages/index.d'
27 27 import { hideAsideComponentsObj } from './config'
28 28 import { remove } from 'lodash'
  29 +import { getThreeJsModelList } from '@/api/external/contentSave/content'
  30 +import { ChartType } from '@/views/three/items'
  31 +import { isArray } from '@/utils/external/is'
29 32
30 33 const ChartsItemBox = loadAsyncComponent(() => import('../../../components/ChartsItemBox/index.vue'))
31 34 const packagesStore = usePackagesStore()
... ... @@ -33,11 +36,12 @@ const packagesStore = usePackagesStore()
33 36 const props = defineProps({
34 37 selectOptions: {
35 38 type: Object,
  39 + // eslint-disable-next-line @typescript-eslint/no-empty-function
36 40 default: () => {}
37 41 }
38 42 })
39 43
40   -const t =window['$t']
  44 +const t = window['$t']
41 45
42 46 // 隐藏设置
43 47 const settingStore = useSettingStore()
... ... @@ -69,6 +73,9 @@ let packages = reactive<{
69 73
70 74 const selectValue = ref<string>('all')
71 75
  76 +const threeJsModels = ref<Recordable[]>([])
  77 +
  78 +
72 79 // 设置初始列表
73 80 const setSelectOptions = (categorys: any) => {
74 81 for (const val in categorys) {
... ... @@ -78,7 +85,7 @@ const setSelectOptions = (categorys: any) => {
78 85 }
79 86
80 87 // THINGS_KIT修改左侧边栏隐藏部分组件(比如重写的,有问题的等需要隐藏)
81   -const byKeyhideAside = (hideAsideComponentsObj: Record<string, string[]>, categorys: Record<string, any>) => {
  88 +const byKeyHideAside = (hideAsideComponentsObj: Record<string, string[]>, categorys: Record<string, any>) => {
82 89 for (const key in categorys) {
83 90 const categoryKey = key
84 91 const categoryValue = categorys[key]
... ... @@ -97,13 +104,50 @@ const byKeyhideAside = (hideAsideComponentsObj: Record<string, string[]>, catego
97 104 }
98 105
99 106 watch(
  107 + // eslint-disable-next-line @typescript-eslint/ban-ts-comment
100 108 // @ts-ignore
101 109 () => props.selectOptions,
102   - (newData: { list: ConfigType[] }) => {
  110 + async (newData: { list: ConfigType[] }) => {
103 111 packages.categorysNum = 0
104 112 if (!newData) return
105   - newData.list.forEach((e: ConfigType) => {
106   - const value: ConfigType[] = (packages.categorys as any)[e.category]
  113 + if (newData.list.map((list: ConfigType) => list.category).includes('Three')) {
  114 + const { items } = await getThreeJsModelList({
  115 + page: 1,
  116 + pageSize: 999999
  117 + })
  118 + let threeFilePath = ''
  119 + const VITE_GLOB_PROXY: [string, string][] | string = import.meta.env.VITE_GLOB_PROXY
  120 + const VITE_GLOB_API_URL_PREFIX = import.meta.env.VITE_GLOB_API_URL_PREFIX
  121 + try {
  122 + const getViteGlobProxy = isArray(JSON.parse(VITE_GLOB_PROXY as unknown as string)) ? JSON.parse(VITE_GLOB_PROXY as unknown as string)[0][1] : VITE_GLOB_PROXY
  123 + threeFilePath = getViteGlobProxy
  124 + } catch {
  125 + // 生产环境是字符串,json parse 报错,直接等于字符串即可
  126 + threeFilePath = VITE_GLOB_PROXY as unknown as string
  127 + }
  128 + threeJsModels.value = items
  129 + ?.filter(filterItem => filterItem.state === 1)
  130 + ?.map((modelItem: ChartType) => {
  131 + return {
  132 + category: 'Three',
  133 + categoryName: 'business.component.THREE',
  134 + chartFrame: 'static',
  135 + chartKey: 'ExternalVCLoader',
  136 + conKey: 'ExternalVCCLoader',
  137 + image: 'threeModelDefault.svg',
  138 + key: 'Loader',
  139 + package: 'Decorates',
  140 + title: modelItem.name ?? modelItem.id,
  141 + redirectComponent: 'Decorates/Three/Loader',
  142 + isThreeModel: true,
  143 + threeModelContent: modelItem.content,
  144 + threeModelFilePath: `${threeFilePath}${VITE_GLOB_API_URL_PREFIX}/3d_component/json/${modelItem.id}/scene.json`
  145 + }
  146 + })
  147 + }
  148 + const mergeList = [...newData.list,...threeJsModels.value] as ConfigType[]
  149 + mergeList.forEach((e: ConfigType) => {
  150 + const value: ConfigType[] = (packages.categorys as Recordable)[e.category]
107 151 packages.categorys[e.category] = value && value.length ? [...value, e] : [e]
108 152 packages.categoryNames[e.category] = e.categoryName
109 153 packages.categorys['all'].push(e)
... ... @@ -116,7 +160,7 @@ watch(
116 160 })
117 161 }
118 162 setSelectOptions(packages.categorys)
119   - byKeyhideAside(hideAsideComponentsObj, packages.categorys)
  163 + byKeyHideAside(hideAsideComponentsObj, packages.categorys)
120 164 // 默认选中处理
121 165 selectValue.value = packages.menuOptions[0]['key']
122 166 },
... ...
... ... @@ -169,14 +169,14 @@ const options = computed(() => {
169 169 .history-list-box {
170 170 width: 100%;
171 171 .list-item {
172   - z-index: 2;
173   - position: relative;
174   - cursor: default;
  172 + // z-index: 2;
  173 + // position: relative;
  174 + cursor: pointer;
175 175 padding: 2px;
176 176 .item-icon {
177 177 margin-right: 10px;
178 178 }
179   - }
  179 + }
180 180 }
181 181 }
182 182 </style>
... ...
... ... @@ -33,12 +33,18 @@ export const dragHandle = async (e: DragEvent) => {
33 33 if (dropData.disabled) return
34 34
35 35 // 创建新图表组件
36   - let newComponent: CreateComponentType = await createComponent(dropData)
37   - if (dropData.redirectComponent) {
  36 + const newComponent: CreateComponentType = await createComponent(dropData)
  37 + if (!dropData?.isThreeModel && dropData.redirectComponent) {
38 38 dropData.dataset && (newComponent.option.dataset = dropData.dataset)
39 39 newComponent.chartConfig.title = dropData.title
40 40 newComponent.chartConfig.chartFrame = dropData.chartFrame
41 41 }
  42 + // 3D模型注入
  43 + if (dropData?.isThreeModel && dropData.redirectComponent) {
  44 + newComponent.option.dataset = dropData?.threeModelFilePath
  45 + newComponent.chartConfig.title = dropData.title
  46 + newComponent.chartConfig.chartFrame = dropData.chartFrame
  47 + }
42 48 /**
43 49 * 修复火狐浏览器随便拖拽一个组件,默认位置都在左上角并遮住。
44 50 * 原因是浏览器兼容问题,火狐浏览器的offsetX和offsetY始终为0值,而应该使用layerX和layerY,其余浏览器使用offsetX和offsetY即可。
... ... @@ -236,7 +242,7 @@ export const useMouseHandle = () => {
236 242 const startY = e.screenY
237 243
238 244 // 记录历史位置
239   - let prevComponentInstance: Array<CreateComponentType | CreateComponentGroupType> = []
  245 + const prevComponentInstance: Array<CreateComponentType | CreateComponentGroupType> = []
240 246 chartEditStore.getTargetChart.selectId.forEach(id => {
241 247 if (!targetMap.has(id)) return
242 248
... ... @@ -254,8 +260,8 @@ export const useMouseHandle = () => {
254 260 chartEditStore.setMousePosition(moveEvent.screenX, moveEvent.screenY)
255 261
256 262 // 当前偏移量,处理 scale 比例问题
257   - let offsetX = (moveEvent.screenX - startX) / scale
258   - let offsetY = (moveEvent.screenY - startY) / scale
  263 + const offsetX = (moveEvent.screenX - startX) / scale
  264 + const offsetY = (moveEvent.screenY - startY) / scale
259 265
260 266 chartEditStore.getTargetChart.selectId.forEach(id => {
261 267 if (!targetMap.has(id)) return
... ... @@ -365,8 +371,8 @@ export const useMousePointHandle = (e: MouseEvent, point: string, attr: PickCrea
365 371 const mousemove = throttle((moveEvent: MouseEvent) => {
366 372 chartEditStore.setMousePosition(moveEvent.screenX, moveEvent.screenY)
367 373
368   - let currX = Math.round((moveEvent.screenX - startX) / scale)
369   - let currY = Math.round((moveEvent.screenY - startY) / scale)
  374 + const currX = Math.round((moveEvent.screenX - startX) / scale)
  375 + const currY = Math.round((moveEvent.screenY - startY) / scale)
370 376
371 377 const isTop = /t/.test(point)
372 378 const isBottom = /b/.test(point)
... ...
... ... @@ -87,6 +87,7 @@ const { dataSyncFetch, intervalDataSyncUpdate } = useSyncRemote()
87 87 provide(SCALE_KEY, null)
88 88
89 89 // 布局处理
  90 +// eslint-disable-next-line @typescript-eslint/no-empty-function
90 91 useLayout(async () => { })
91 92
92 93 // 点击事件
... ...
... ... @@ -11,8 +11,8 @@
11 11
12 12 <script setup lang="ts">
13 13 import { computed } from 'vue'
14   -import { renderIcon, goDialog, fetchPathByName, routerTurnByPath, setSessionStorage, getLocalStorage } from '@/utils'
15   -import { PreviewEnum } from '@/enums/pageEnum'
  14 +import { renderIcon, goDialog, fetchPathByName, routerTurnByPath, setSessionStorage, getLocalStorage, routerTurnByName } from '@/utils'
  15 +import { PageEnum, PreviewEnum } from '@/enums/pageEnum'
16 16 import { StorageEnum } from '@/enums/storageEnum'
17 17 import { useRoute } from 'vue-router'
18 18 import { useChartEditStore } from '@/store/modules/chartEditStore/chartEditStore'
... ... @@ -59,8 +59,9 @@ const previewHandle = () => {
59 59
60 60 // 发布
61 61 const sendHandle = () => {
62   - const { host,protocol,pathname } = location
63   - window.open(`${protocol}//${host}${pathname}editor/`)
  62 + // const { host,protocol,pathname } = location
  63 + // window.open(`${protocol}//${host}${pathname}editor/`)
  64 + routerTurnByName(PageEnum.THREE_HOME_NAME, false, true)
64 65 // goDialog({
65 66 // message: '想体验发布功能,请前往 master-fetch 分支查看: https://demo.mtruning.club/#/login',
66 67 // positiveText: '了然',
... ... @@ -83,9 +84,9 @@ const btnList = [
83 84 icon: renderIcon(BrowsersOutlineIcon),
84 85 event: previewHandle
85 86 },
86   - {
  87 + {
87 88 select: true,
88   - title: '编辑器',
  89 + title: t('business.threeDModel'),
89 90 icon: renderIcon(SendIcon),
90 91 event: sendHandle
91 92 }
... ...
  1 +<template>
  2 + <div class="go-project">
  3 + <n-layout has-sider position="absolute">
  4 + <n-space vertical>
  5 + <project-layout-sider></project-layout-sider>
  6 + </n-space>
  7 + <n-layout>
  8 + <n-layout
  9 + id="go-project-content-top"
  10 + class="content-top"
  11 + position="absolute"
  12 + :native-scrollbar="false"
  13 + >
  14 + <n-layout-content>
  15 + <layout-transition-main>
  16 + <router-view></router-view>
  17 + </layout-transition-main>
  18 + </n-layout-content>
  19 + </n-layout>
  20 + </n-layout>
  21 + </n-layout>
  22 + </div>
  23 +</template>
  24 +
  25 +<script setup lang="ts">
  26 +import { ProjectLayoutSider } from './layout/components/ProjectLayoutSider'
  27 +import { LayoutTransitionMain } from '@/layout/components/LayoutTransitionMain/index'
  28 +</script>
  29 +
  30 +<style lang="scss" scoped>
  31 +@include go(project) {
  32 + .content-top {
  33 + top: $--header-height;
  34 + margin-top: 1px;
  35 + }
  36 +}
  37 +</style>
... ...
  1 +import ProjectItemsCard from './index.vue'
  2 +
  3 +export { ProjectItemsCard }
... ...
  1 +<template>
  2 + <div v-if="cardData" class="go-items-list-card">
  3 + <n-card hoverable size="small">
  4 + <div class="list-content">
  5 + <!-- 顶部按钮 -->
  6 + <div class="list-content-top">
  7 + <mac-os-control-btn
  8 + class="top-btn"
  9 + :hidden="['remove']"
  10 + @close="deleteHandle"
  11 + @resize="resizeHandle"
  12 + ></mac-os-control-btn>
  13 + </div>
  14 + <!-- 中间 -->
  15 + <div class="list-content-img" @click="resizeHandle">
  16 + <n-image
  17 + object-fit="contain"
  18 + height="180"
  19 + preview-disabled
  20 + :src="requireUrl('ThreeModelDefault.svg')"
  21 + :fallback-src="requireErrorImg()"
  22 + ></n-image>
  23 + </div>
  24 + </div>
  25 + <template #action>
  26 + <div class="go-flex-items-center list-footer" justify="space-between">
  27 + <n-text @click="handleFocus">
  28 + <n-button v-show="!focus" secondary size="tiny">
  29 + <span class="title">
  30 + {{ cardData.name || cardData.id }}
  31 + </span>
  32 + </n-button>
  33 + </n-text>
  34 + <n-input
  35 + v-show="focus"
  36 + ref="inputInstRef"
  37 + size="small"
  38 + type="text"
  39 + maxlength="16"
  40 + show-count
  41 + v-model:value.trim="title"
  42 + @keyup.enter="handleBlur"
  43 + @blur="handleBlur"
  44 + ></n-input>
  45 + <!-- 工具 -->
  46 + <div class="go-flex-items-center list-footer-ri">
  47 + <n-space>
  48 + <n-text>
  49 + <n-badge
  50 + class="go-animation-twinkle"
  51 + dot
  52 + :color="cardData.state === 1 ? '#34c749' : '#fcbc40'"
  53 + ></n-badge>
  54 + {{ cardData.state === 1 ? $t('project.release') : $t('project.unreleased') }}
  55 + </n-text>
  56 +
  57 + <template v-for="item in fnBtnList" :key="item.key">
  58 + <template v-if="item.key === 'select'">
  59 + <n-dropdown
  60 + trigger="hover"
  61 + placement="bottom"
  62 + :options="selectOptions"
  63 + :show-arrow="true"
  64 + @select="handleSelect"
  65 + >
  66 + <n-button size="small">
  67 + <template #icon>
  68 + <component :is="item.icon"></component>
  69 + </template>
  70 + </n-button>
  71 + </n-dropdown>
  72 + </template>
  73 +
  74 + <n-tooltip v-else placement="bottom" trigger="hover">
  75 + <template #trigger>
  76 + <n-button size="small" @click="handleSelect(item.key)">
  77 + <template #icon>
  78 + <component :is="item.icon"></component>
  79 + </template>
  80 + </n-button>
  81 + </template>
  82 + <component :is="item.label"></component>
  83 + </n-tooltip>
  84 + </template>
  85 + </n-space>
  86 + </div>
  87 + <!-- end -->
  88 + </div>
  89 + </template>
  90 + </n-card>
  91 + </div>
  92 +</template>
  93 +
  94 +<script setup lang="ts">
  95 +import { reactive, ref, PropType, nextTick } from 'vue'
  96 +import { renderIcon, renderLang, requireErrorImg } from '@/utils'
  97 +import { icon } from '@/plugins'
  98 +import { MacOsControlBtn } from '@/components/Tips/MacOsControlBtn'
  99 +import { ChartType } from '../..'
  100 +import { updateThreeJsModel } from '@/api/external/contentSave/content'
  101 +const { EllipsisHorizontalCircleSharpIcon, TrashIcon, HammerIcon, SendIcon } = icon.ionicons5
  102 +
  103 +const emit = defineEmits(['delete', 'resize', 'edit', 'release', 'inputUpdateCard'])
  104 +
  105 +const props = defineProps({
  106 + cardData: Object as PropType<ChartType>
  107 +})
  108 +
  109 +const focus = ref<boolean>(false)
  110 +
  111 +const inputInstRef = ref(null)
  112 +
  113 +const title = ref<string>('')
  114 +
  115 +// 处理url获取
  116 +const requireUrl = (name: string) => {
  117 + return new URL(`../../../../../assets/images/${name}`, import.meta.url).href
  118 +}
  119 +
  120 +const fnBtnList = reactive([
  121 + {
  122 + label: renderLang('global.r_edit'),
  123 + key: 'edit',
  124 + icon: renderIcon(HammerIcon)
  125 + },
  126 + {
  127 + label: renderLang('global.r_more'),
  128 + key: 'select',
  129 + icon: renderIcon(EllipsisHorizontalCircleSharpIcon)
  130 + }
  131 +])
  132 +
  133 +const selectOptions = ref([
  134 + {
  135 + label: props.cardData?.state ? renderLang('global.r_unpublish') : renderLang('global.r_publish'),
  136 + key: 'release',
  137 + icon: renderIcon(SendIcon)
  138 + },
  139 + {
  140 + label: renderLang('global.r_delete'),
  141 + key: 'delete',
  142 + icon: renderIcon(TrashIcon)
  143 + }
  144 +])
  145 +
  146 +const handleSelect = (key: string) => {
  147 + switch (key) {
  148 + case 'delete':
  149 + deleteHandle()
  150 + break
  151 + case 'release':
  152 + releaseHandle()
  153 + break
  154 + case 'edit':
  155 + editHandle()
  156 + break
  157 + }
  158 +}
  159 +
  160 +// 删除处理
  161 +const deleteHandle = () => {
  162 + emit('delete', props.cardData)
  163 +}
  164 +
  165 +// 编辑处理
  166 +const editHandle = () => {
  167 + emit('edit', props.cardData)
  168 +}
  169 +
  170 +// 发布处理
  171 +const releaseHandle = () => {
  172 + emit('release', props.cardData)
  173 +}
  174 +
  175 +// 放大处理
  176 +const resizeHandle = () => {
  177 + emit('resize', props.cardData)
  178 +}
  179 +
  180 +const handleFocus = () => {
  181 + focus.value = true
  182 + nextTick(() => {
  183 + inputInstRef.value && (inputInstRef.value as any).focus()
  184 + })
  185 +}
  186 +
  187 +const handleBlur = async () => {
  188 + focus.value = false
  189 + if(!title.value) return
  190 + await updateThreeJsModel({
  191 + id: props.cardData?.id as string,
  192 + name: title.value
  193 + })
  194 + emit('inputUpdateCard')
  195 + window['$message'].success(window['$t']('common.operationSuccessText'))
  196 +}
  197 +</script>
  198 +
  199 +<style lang="scss" scoped>
  200 +$contentHeight: 180px;
  201 +@include go('items-list-card') {
  202 + position: relative;
  203 + border-radius: $--border-radius-base;
  204 + border: 1px solid rgba(0, 0, 0, 0);
  205 + @extend .go-transition;
  206 + &:hover {
  207 + @include hover-border-color('hover-border-color');
  208 + }
  209 + .list-content {
  210 + margin-top: 20px;
  211 + margin-bottom: 5px;
  212 + cursor: pointer;
  213 + border-radius: $--border-radius-base;
  214 + @include background-image('background-point');
  215 + @extend .go-point-bg;
  216 + &-top {
  217 + position: absolute;
  218 + top: 10px;
  219 + left: 10px;
  220 + height: 22px;
  221 + }
  222 + &-img {
  223 + height: $contentHeight;
  224 + @extend .go-flex-center;
  225 + @extend .go-border-radius;
  226 + @include deep() {
  227 + img {
  228 + @extend .go-border-radius;
  229 + }
  230 + }
  231 + }
  232 + }
  233 + .list-footer {
  234 + flex-wrap: nowrap;
  235 + justify-content: space-between;
  236 + line-height: 30px;
  237 + &-ri {
  238 + justify-content: flex-end;
  239 + min-width: 180px;
  240 + }
  241 + }
  242 +}
  243 +</style>
... ...
  1 +import { getDataViewList } from "@/api/external/contentSave/content"
  2 +import { onMounted, Ref } from "vue"
  3 +import { ChartList } from "../../.."
  4 +
  5 +export function useListData(list: Ref<ChartList>) {
  6 + onMounted(async () => {
  7 + try {
  8 + const { items } = await getDataViewList({ page: 1, pageSize: 10 })
  9 + list.value = items as unknown as ChartList
  10 + } catch (error) {
  11 + console.log(error)
  12 + }
  13 + })
  14 +}
... ...
  1 +import { ref, reactive } from 'vue'
  2 +import { goDialog } from '@/utils'
  3 +import { DialogEnum } from '@/enums/pluginEnum'
  4 +import { ChartType, ChartList } from '../../../index.d'
  5 +import { getThreeJsModelList, putThreeJsModelRelease, threeJsDeleteApi } from '@/api/external/contentSave/content'
  6 +import { PaginationResult } from '/#/external/axios'
  7 +
  8 +// 数据初始化
  9 +export const useDataListInit = () => {
  10 + const loading = ref(true)
  11 +
  12 + const pagination = reactive({
  13 + // 当前页数
  14 + page: 1,
  15 + // 每页值
  16 + pageSize: 12,
  17 + // 总数
  18 + count: 10
  19 + })
  20 +
  21 + const list = ref<ChartList>([])
  22 +
  23 + // 数据请求
  24 + const fetchList = async () => {
  25 + loading.value = true
  26 + const res = await getThreeJsModelList({
  27 + page: pagination.page,
  28 + pageSize: pagination.pageSize
  29 + })
  30 + if (res) {
  31 + const { total, items } = res as PaginationResult<ChartType>
  32 + pagination.count = total
  33 + list.value = items
  34 + setTimeout(() => {
  35 + loading.value = false
  36 + }, 500)
  37 + return
  38 + }
  39 + }
  40 +
  41 + const inputUpdateHandle = () => fetchList()
  42 +
  43 + // 修改页数
  44 + const changePage = (_page: number) => {
  45 + pagination.page = _page
  46 + fetchList()
  47 + }
  48 +
  49 + // 修改大小
  50 + const changeSize = (_size: number) => {
  51 + pagination.pageSize = _size
  52 + fetchList()
  53 + }
  54 +
  55 + // 删除处理
  56 + const deleteHandle = (cardData: ChartType) => {
  57 + goDialog({
  58 + type: DialogEnum.DELETE,
  59 + promise: true,
  60 + // eslint-disable-next-line @typescript-eslint/no-empty-function
  61 + onPositiveCallback: () => {},
  62 + promiseResCallback: async () => {
  63 + await threeJsDeleteApi([cardData.id] as string[])
  64 + window['$message'].success(window['$t']('common.deleteSuccessText'))
  65 + fetchList()
  66 + }
  67 + })
  68 + }
  69 +
  70 + // 发布处理
  71 + const releaseHandle = async (cardData: ChartType) => {
  72 + const { id, state } = cardData
  73 + await putThreeJsModelRelease({
  74 + id,
  75 + // [0未发布, 1发布]
  76 + state: state === 1 ? 0 : 1
  77 + })
  78 + list.value = []
  79 + fetchList()
  80 + // 发布 -> 未发布
  81 + if (state === 1) {
  82 + window['$message'].success(window['$t']('common.cancelReleaseSuccessText'))
  83 + return
  84 + }
  85 + // 未发布 -> 发布
  86 + window['$message'].success(window['$t']('common.releaseSuccessText'))
  87 + return
  88 + }
  89 +
  90 + // 立即请求
  91 + fetchList()
  92 +
  93 + return {
  94 + loading,
  95 + pagination,
  96 + list,
  97 + fetchList,
  98 + changeSize,
  99 + changePage,
  100 + deleteHandle,
  101 + releaseHandle,
  102 + inputUpdateHandle
  103 + }
  104 +}
... ...
  1 +import { ref } from 'vue'
  2 +import { ChartType } from '../../..'
  3 +
  4 +export const useModalDataInit = () => {
  5 + const modalShow = ref<boolean>(false)
  6 + const modalData = ref<ChartType | null>(null)
  7 +
  8 + // 关闭 modal
  9 + const closeModal = () => {
  10 + modalShow.value = false
  11 + modalData.value = null
  12 + }
  13 +
  14 + // 打开 modal
  15 + const resizeHandle = (cardData: ChartType) => {
  16 + if (!cardData) return
  17 + modalShow.value = true
  18 + modalData.value = cardData
  19 + }
  20 +
  21 + // 打开 modal
  22 + const editHandle = (cardData: ChartType) => {
  23 + if (!cardData) return
  24 + if (!cardData?.id) return
  25 + const { host, protocol, pathname } = location
  26 + window.open(`${protocol}//${host}${pathname}editor/?three_file_uuid=${cardData?.id}`)
  27 + }
  28 +
  29 + return {
  30 + modalData,
  31 + modalShow,
  32 + closeModal,
  33 + resizeHandle,
  34 + editHandle
  35 + }
  36 +}
... ...
  1 +import ProjectItemsList from './index.vue'
  2 +
  3 +export { ProjectItemsList }
... ...
  1 +<template>
  2 + <div class="go-items-list">
  3 + <div v-show="loading">
  4 + <go-loading></go-loading>
  5 + </div>
  6 + <div v-show="!loading">
  7 + <n-grid :x-gap="20" :y-gap="20" cols="2 s:2 m:3 l:4 xl:4 xxl:4" responsive="screen">
  8 + <n-grid-item v-for="(item, index) in list" :key="item.id">
  9 + <div style="display: none">{{ index }}</div>
  10 + <project-items-card
  11 + :cardData="item"
  12 + @resize="resizeHandle"
  13 + @delete="deleteHandle(item)"
  14 + @release="releaseHandle(item)"
  15 + @edit="editHandle"
  16 + @inputUpdateCard="inputUpdateHandle"
  17 + ></project-items-card>
  18 + </n-grid-item>
  19 + </n-grid>
  20 + </div>
  21 + <div class="list-pagination">
  22 + <n-pagination
  23 + :page="pagination.page"
  24 + :page-size="pagination.pageSize"
  25 + :item-count="pagination.count"
  26 + :page-sizes="[12, 24, 36, 48]"
  27 + @update:page="changePage"
  28 + @update:page-size="changeSize"
  29 + show-size-picker
  30 + />
  31 + </div>
  32 + </div>
  33 + <project-items-modal-card
  34 + v-if="modalData"
  35 + :modalShow="modalShow"
  36 + :cardData="modalData"
  37 + @close="closeModal"
  38 + @edit="editHandle"
  39 + ></project-items-modal-card>
  40 +</template>
  41 +
  42 +<script setup lang="ts">
  43 +import { ProjectItemsCard } from '../ProjectItemsCard/index'
  44 +import { ProjectItemsModalCard } from '../ProjectItemsModalCard/index'
  45 +import { useModalDataInit } from './hooks/useModal.hook'
  46 +import { useDataListInit } from './hooks/useData.hook'
  47 +
  48 +const { modalData, modalShow, closeModal, resizeHandle, editHandle } = useModalDataInit()
  49 +
  50 +const { loading, pagination, list, changeSize, changePage, deleteHandle, releaseHandle, inputUpdateHandle } = useDataListInit()
  51 +</script>
  52 +
  53 +<style lang="scss" scoped>
  54 +$contentHeight: 250px;
  55 +@include go('items-list') {
  56 + display: flex;
  57 + flex-direction: column;
  58 + justify-content: space-between;
  59 + min-height: calc(100vh - #{$--header-height} * 2 - 2px);
  60 + .list-content {
  61 + position: relative;
  62 + height: $contentHeight;
  63 + }
  64 + .list-pagination {
  65 + display: flex;
  66 + justify-content: flex-end;
  67 + margin-top: 20px;
  68 + }
  69 +}
  70 +</style>
... ...
  1 +import ProjectItemsModalCard from './index.vue'
  2 +
  3 +export { ProjectItemsModalCard }
... ...
  1 +<template>
  2 + <!-- mask-closable 暂时是失效的,不知道为啥 -->
  3 + <n-modal
  4 + class="go-modal-box"
  5 + v-model:show="showRef"
  6 + @afterLeave="closeHandle"
  7 + >
  8 + <n-card hoverable size="small">
  9 + <div class="list-content">
  10 + <!-- 标题 -->
  11 + <n-space class="list-content-top go-px-0" justify="center">
  12 + <n-space>
  13 + <n-text>
  14 + {{ cardData?.title || '' }}
  15 + </n-text>
  16 + </n-space>
  17 + </n-space>
  18 + <!-- 顶部按钮 -->
  19 + <n-space class="list-content-top">
  20 + <mac-os-control-btn
  21 + :narrow="true"
  22 + :hidden="['close']"
  23 + @remove="closeHandle"
  24 + ></mac-os-control-btn>
  25 + </n-space>
  26 + <!-- 中间 -->
  27 + <div class="list-content-img">
  28 + <img
  29 + :src="
  30 + requireUrl('project/moke-20211219181327.png')
  31 + "
  32 + :alt="cardData?.title"
  33 + />
  34 + </div>
  35 + </div>
  36 + <template #action>
  37 + <n-space class="list-footer" justify="space-between">
  38 + <n-text depth="3">
  39 + {{ $t('project.last_edit') }}:
  40 + <n-time :time="new Date()" format="yyyy-MM-dd hh:mm"></n-time>
  41 + </n-text>
  42 + <!-- 工具 -->
  43 + <n-space>
  44 + <n-text>
  45 + <n-badge
  46 + class="go-animation-twinkle"
  47 + dot
  48 + :color="cardData?.release ? '#34c749' : '#fcbc40'"
  49 + ></n-badge>
  50 + {{
  51 + cardData?.release
  52 + ? $t('project.release')
  53 + : $t('project.unreleased')
  54 + }}
  55 + </n-text>
  56 +
  57 + <template v-for="item in fnBtnList" :key="item.key">
  58 + <n-tooltip placement="bottom" trigger="hover">
  59 + <template #trigger>
  60 + <n-button size="small" @click="handleSelect(item.key)">
  61 + <template #icon>
  62 + <component :is="item.icon"></component>
  63 + </template>
  64 + </n-button>
  65 + </template>
  66 + <component :is="item.label"></component>
  67 + </n-tooltip>
  68 + </template>
  69 + </n-space>
  70 + <!-- end -->
  71 + </n-space>
  72 + </template>
  73 + </n-card>
  74 + </n-modal>
  75 +</template>
  76 +
  77 +<script setup lang="ts">
  78 +import { ref, reactive, watch } from 'vue'
  79 +import { renderIcon, renderLang } from '@/utils'
  80 +import { icon } from '@/plugins'
  81 +import { MacOsControlBtn } from '@/components/Tips/MacOsControlBtn'
  82 +
  83 +const { HammerIcon } = icon.ionicons5
  84 +const showRef = ref(false)
  85 +const emit = defineEmits(['close', 'edit'])
  86 +
  87 +const props = defineProps({
  88 + modalShow: {
  89 + required: true,
  90 + type: Boolean
  91 + },
  92 + cardData: {
  93 + required: true,
  94 + type: Object
  95 + }
  96 +})
  97 +
  98 +watch(
  99 + () => props.modalShow,
  100 + newValue => {
  101 + showRef.value = newValue
  102 + },
  103 + {
  104 + immediate: true
  105 + }
  106 +)
  107 +
  108 +// 处理url获取
  109 +const requireUrl = (name: string) => {
  110 + return new URL(`../../../../../assets/images/${name}`, import.meta.url).href
  111 +}
  112 +
  113 +const fnBtnList = reactive([
  114 + {
  115 + label: renderLang('global.r_edit'),
  116 + key: 'edit',
  117 + icon: renderIcon(HammerIcon)
  118 + }
  119 +])
  120 +
  121 +const handleSelect = (key: string) => {
  122 + switch (key) {
  123 + case 'edit':
  124 + editHandle()
  125 + break
  126 + }
  127 +}
  128 +
  129 +// 编辑处理
  130 +const editHandle = () => {
  131 + emit('edit', props.cardData)
  132 +}
  133 +
  134 +// 关闭对话框
  135 +const closeHandle = () => {
  136 + emit('close')
  137 +}
  138 +</script>
  139 +
  140 +<style lang="scss" scoped>
  141 +$padding: 30px;
  142 +$contentHeight: calc(80vh);
  143 +$contentWidth: calc(82vw);
  144 +
  145 +@include go('modal-box') {
  146 + width: $contentWidth;
  147 + .list-content {
  148 + margin-top: 28px;
  149 + border-radius: $--border-radius-base;
  150 + overflow: hidden;
  151 + @include background-image('background-point');
  152 + @extend .go-point-bg;
  153 + &-top {
  154 + position: absolute;
  155 + top: 7px;
  156 + left: 0px;
  157 + padding-left: 10px;
  158 + height: 22px;
  159 + width: $contentWidth;
  160 + }
  161 + &-img {
  162 + @extend .go-flex-center;
  163 + img {
  164 + max-height: $contentHeight;
  165 + min-height: 200px;
  166 + max-width: 100%;
  167 + @extend .go-border-radius;
  168 + }
  169 + }
  170 + }
  171 + .list-footer {
  172 + line-height: 30px;
  173 + }
  174 +}
  175 +</style>
... ...
  1 +export type ChartType = {
  2 + id: number | string
  3 + creator?: string
  4 + createTime?: string
  5 + enabled?: boolean
  6 + tenantId?: string
  7 + content?: any
  8 + state?: number
  9 + name?: string
  10 +}
  11 +
  12 +export type ChartList = ChartType[]
... ...
  1 +<template>
  2 + <div class="go-project-items">
  3 + <project-items-list></project-items-list>
  4 + </div>
  5 +</template>
  6 +
  7 +<script setup lang="ts">
  8 +import { ProjectItemsList } from './components/ProjectItemsList'
  9 +</script>
  10 +
  11 +<style lang="scss" scoped>
  12 +@include go(project-items) {
  13 + padding: 30px 20px;
  14 +}
  15 +</style>
... ...
  1 +import ProjectLayoutAsideFooter from './index.vue'
  2 +
  3 +export { ProjectLayoutAsideFooter }
... ...
  1 +<template>
  2 + <div class="go-aside-footer">
  3 + <n-divider class="go-mt-0"></n-divider>
  4 + <n-space justify="space-around">
  5 + <n-tooltip v-if="collapsed" placement="right" trigger="hover">
  6 + <template #trigger>
  7 + <n-button secondary @click="handleDoc">
  8 + <template #icon>
  9 + <n-icon size="18">
  10 + <document-text-icon></document-text-icon>
  11 + </n-icon>
  12 + </template>
  13 + </n-button>
  14 + </template>
  15 + <n-text>
  16 + {{ $t('global.doc') }}
  17 + </n-text>
  18 + </n-tooltip>
  19 +
  20 + <n-button v-else secondary @click="handleDoc">
  21 + <template #icon>
  22 + <n-icon size="18">
  23 + <document-text-icon></document-text-icon>
  24 + </n-icon>
  25 + </template>
  26 + <n-text>{{ $t('global.doc') }}</n-text>
  27 + </n-button>
  28 +
  29 + <n-tooltip v-if="collapsed" placement="right" trigger="hover">
  30 + <template #trigger>
  31 + <n-button secondary @click="handleDoc">
  32 + <template #icon>
  33 + <n-icon size="18">
  34 + <code-slash-icon></code-slash-icon>
  35 + </n-icon>
  36 + </template>
  37 + </n-button>
  38 + </template>
  39 + <n-text>
  40 + {{ $t('global.code_addr') }}
  41 + </n-text>
  42 + </n-tooltip>
  43 +
  44 + <n-button v-else secondary @click="handleCode">
  45 + <template #icon>
  46 + <n-icon size="18">
  47 + <code-slash-icon></code-slash-icon>
  48 + </n-icon>
  49 + </template>
  50 + <n-text v-show="!collapsed">{{ $t('global.code_addr') }}</n-text>
  51 + </n-button>
  52 + </n-space>
  53 + </div>
  54 +</template>
  55 +<script setup lang="ts">
  56 +import { openDoc, openGiteeSourceCode } from '@/utils'
  57 +
  58 +import { icon } from '@/plugins'
  59 +const { DocumentTextIcon, CodeSlashIcon } = icon.ionicons5
  60 +
  61 +const props = defineProps({
  62 + collapsed: Boolean
  63 +})
  64 +
  65 +const handleDoc = () => {
  66 + openDoc()
  67 +}
  68 +const handleCode = () => {
  69 + openGiteeSourceCode()
  70 +}
  71 +</script>
  72 +
  73 +<style lang="scss" scoped>
  74 +@include go('aside-footer') {
  75 + padding-bottom: 20px;
  76 +}
  77 +</style>
... ...
  1 +import CreateModal from './index.vue'
  2 +
  3 +export { CreateModal }
... ...
  1 +<template>
  2 + <n-modal v-model:show="showRef" class="go-create-modal" @afterLeave="closeHandle">
  3 + <n-space size="large">
  4 + <n-card class="card-box" hoverable>
  5 + <template #header>
  6 + <n-text class="card-box-tite">{{ $t('project.create_tip') }}</n-text>
  7 + </template>
  8 + <template #header-extra>
  9 + <n-text @click="closeHandle">
  10 + <n-icon size="20">
  11 + <component :is="CloseIcon"></component>
  12 + </n-icon>
  13 + </n-text>
  14 + </template>
  15 + <n-space class="card-box-content" justify="center">
  16 + <n-button
  17 + size="large"
  18 + :disabled="item.disabled"
  19 + v-for="item in typeList"
  20 + :key="item.key"
  21 + @click="btnHandle"
  22 + >
  23 + <component :is="item.title"></component>
  24 + <template #icon>
  25 + <n-icon size="18">
  26 + <component :is="item.icon"></component>
  27 + </n-icon>
  28 + </template>
  29 + </n-button>
  30 + </n-space>
  31 + <template #action></template>
  32 + </n-card>
  33 + </n-space>
  34 + </n-modal>
  35 +</template>
  36 +
  37 +<script lang="ts" setup>
  38 +import { ref, watch, shallowRef } from 'vue'
  39 +import { icon } from '@/plugins'
  40 +import { PageEnum, ChartEnum } from '@/enums/pageEnum'
  41 +import { fetchPathByName, routerTurnByPath, renderLang, getUUID } from '@/utils'
  42 +
  43 +const { FishIcon, CloseIcon } = icon.ionicons5
  44 +const { StoreIcon, ObjectStorageIcon } = icon.carbon
  45 +const showRef = ref(false)
  46 +
  47 +const emit = defineEmits(['close'])
  48 +const props = defineProps({
  49 + show: Boolean
  50 +})
  51 +
  52 +const typeList = shallowRef([
  53 + {
  54 + title: renderLang('project.new_project'),
  55 + key: ChartEnum.CHART_HOME_NAME,
  56 + icon: FishIcon,
  57 + disabled: false
  58 + },
  59 + {
  60 + title: renderLang('project.my_templete'),
  61 + key: PageEnum.BASE_HOME_TEMPLATE_NAME,
  62 + icon: ObjectStorageIcon,
  63 + disabled: true
  64 + },
  65 + {
  66 + title: renderLang('project.template_market'),
  67 + key: PageEnum.BASE_HOME_TEMPLATE_MARKET_NAME,
  68 + icon: StoreIcon,
  69 + disabled: true
  70 + }
  71 +])
  72 +
  73 +watch(props, newValue => {
  74 + showRef.value = newValue.show
  75 +})
  76 +
  77 +// 关闭对话框
  78 +const closeHandle = () => {
  79 + emit('close', false)
  80 +}
  81 +
  82 +// 处理按钮点击
  83 +const btnHandle = (key: string) => {
  84 + closeHandle()
  85 + const id = getUUID()
  86 + const path = fetchPathByName(ChartEnum.CHART_HOME_NAME, 'href')
  87 + routerTurnByPath(path, [id], undefined, true)
  88 +}
  89 +</script>
  90 +<style lang="scss" scoped>
  91 +$cardWidth: 570px;
  92 +
  93 +@include go('create-modal') {
  94 + position: fixed;
  95 + top: 200px;
  96 + left: 50%;
  97 + transform: translateX(-50%);
  98 + .card-box {
  99 + width: $cardWidth;
  100 + cursor: pointer;
  101 + border: 1px solid rgba(0, 0, 0, 0);
  102 + @extend .go-transition;
  103 + &:hover {
  104 + @include hover-border-color('hover-border-color');
  105 + }
  106 + &-tite {
  107 + font-size: 14px;
  108 + }
  109 + &-content {
  110 + padding: 0px 10px;
  111 + width: 100%;
  112 + }
  113 + }
  114 +}
  115 +</style>
... ...
  1 +import ProjectLayoutCreate from './index.vue'
  2 +
  3 +export { ProjectLayoutCreate }
... ...
  1 +<template>
  2 + <div @click="clickHandle">
  3 + <n-tooltip v-if="collapsed" placement="right" trigger="hover">
  4 + <template #trigger>
  5 + <n-button ghost type="primary" size="small">
  6 + <template #icon>
  7 + <n-icon>
  8 + <DuplicateOutlineIcon v-show="designStore.getDarkTheme"></DuplicateOutlineIcon>
  9 + <DuplicateIcon v-show="!designStore.getDarkTheme"></DuplicateIcon>
  10 + </n-icon>
  11 + </template>
  12 + </n-button>
  13 + </template>
  14 + <span>
  15 + {{ $t('project.create_btn') }}
  16 + </span>
  17 + </n-tooltip>
  18 + <n-button v-else ghost type="primary">
  19 + <template #icon>
  20 + <n-icon>
  21 + <DuplicateOutlineIcon v-show="designStore.getDarkTheme"></DuplicateOutlineIcon>
  22 + <DuplicateIcon v-show="!designStore.getDarkTheme"></DuplicateIcon>
  23 + </n-icon>
  24 + </template>
  25 + <span>
  26 + {{ $t('project.create_btn') }}
  27 + </span>
  28 + </n-button>
  29 + </div>
  30 + <CreateModal :show="modalShow" @close="closeHandle"></CreateModal>
  31 +</template>
  32 +<script setup lang="ts">
  33 +import { ref } from 'vue'
  34 +import { useDesignStore } from '@/store/modules/designStore/designStore'
  35 +import { CreateModal } from './components/CreateModal/index'
  36 +import { icon } from '@/plugins'
  37 +import { getUUID } from '@/utils'
  38 +
  39 +const { DuplicateIcon, DuplicateOutlineIcon } = icon.ionicons5
  40 +const designStore = useDesignStore()
  41 +
  42 +defineProps({
  43 + collapsed: Boolean
  44 +})
  45 +
  46 +const modalShow = ref<boolean>(false)
  47 +
  48 +const clickHandle = () => {
  49 + const { host, protocol, pathname } = location
  50 + const randomId = getUUID(32)
  51 + window.open(`${protocol}//${host}${pathname}editor/?three_file_uuid=${randomId}`)
  52 +}
  53 +
  54 +const closeHandle = () => {
  55 + modalShow.value = false
  56 +}
  57 +</script>
... ...
  1 +import ProjectLayoutSider from './index.vue'
  2 +
  3 +export { ProjectLayoutSider }
... ...
  1 +<template>
  2 + <n-layout-sider
  3 + class="go-project-sider"
  4 + bordered
  5 + collapse-mode="width"
  6 + show-trigger="bar"
  7 + :collapsed="collapsed"
  8 + :native-scrollbar="false"
  9 + :collapsed-width="getAsideCollapsedWidth"
  10 + :width="asideWidth"
  11 + @collapse="collapsed = true"
  12 + @expand="collapsed = false"
  13 + >
  14 + <div class="go-project-sider-flex">
  15 + <aside>
  16 + <n-space vertical class="go-project-sider-top">
  17 + <project-layout-create :collapsed="collapsed"></project-layout-create>
  18 + </n-space>
  19 + <n-menu
  20 + :value="menuValue"
  21 + :options="menuOptions"
  22 + :collapsed-width="getAsideCollapsedWidth"
  23 + :collapsed-icon-size="22"
  24 + :default-expanded-keys="defaultExpandedKeys"
  25 + ></n-menu>
  26 + </aside>
  27 + <!-- 底部提示 -->
  28 + <!-- <div class="sider-bottom">
  29 + <project-layout-aside-footer :collapsed="collapsed"></project-layout-aside-footer>
  30 + </div> -->
  31 + </div>
  32 + </n-layout-sider>
  33 +</template>
  34 +
  35 +<script setup lang="ts">
  36 +import { ref, computed, onMounted, onUnmounted, toRefs } from 'vue'
  37 +import { ProjectLayoutCreate } from '../ProjectLayoutCreate/index'
  38 +import { ProjectLayoutAsideFooter } from '../ProjectLayoutAsideFooter/index'
  39 +import { asideWidth } from '@/settings/designSetting'
  40 +import { useRoute } from 'vue-router'
  41 +import { useSettingStore } from '@/store/modules/settingStore/settingStore'
  42 +import { menuOptionsInit, expandedKeys } from './menu'
  43 +
  44 +const collapsed = ref<boolean>(false)
  45 +const { getAsideCollapsedWidth } = toRefs(useSettingStore())
  46 +
  47 +const route = useRoute()
  48 +const menuValue = computed(() => route.name)
  49 +
  50 +const menuOptions = menuOptionsInit()
  51 +
  52 +const defaultExpandedKeys = expandedKeys()
  53 +
  54 +const watchWidth = () => {
  55 + const Width = document.body.clientWidth
  56 + if (Width <= 950) {
  57 + collapsed.value = true
  58 + } else collapsed.value = false
  59 +}
  60 +
  61 +onMounted(() => {
  62 + window.addEventListener('resize', watchWidth)
  63 +})
  64 +
  65 +onUnmounted(()=> {
  66 + window.removeEventListener('resize', watchWidth)
  67 +})
  68 +</script>
  69 +
  70 +<style lang="scss" scoped>
  71 +$siderHeight: 100vh;
  72 +
  73 +@include go(project) {
  74 + &-sider {
  75 + @include fetch-bg-color('aside-background-color');
  76 + &-top {
  77 + display: flex;
  78 + align-items: center;
  79 + justify-content: space-between;
  80 + flex-direction: column;
  81 + margin-top: 30px;
  82 + margin-bottom: 20px;
  83 + }
  84 + &-flex {
  85 + display: flex;
  86 + flex-direction: column;
  87 + justify-content: space-between;
  88 + height: $siderHeight;
  89 + }
  90 + }
  91 + &-layout-sider {
  92 + height: $siderHeight;
  93 + }
  94 + .content-top {
  95 + top: $--header-height;
  96 + margin-top: 1px;
  97 + }
  98 +}
  99 +</style>
... ...
  1 +import { reactive, h } from 'vue'
  2 +import { renderIcon } from '@/utils'
  3 +import { RouterLink } from 'vue-router'
  4 +import { PageEnum } from '@/enums/pageEnum'
  5 +import { MenuOption, MenuGroupOption } from 'naive-ui'
  6 +import { icon } from '@/plugins'
  7 +
  8 +const { TvOutlineIcon } = icon.ionicons5
  9 +const { DevicesIcon } = icon.carbon
  10 +export const renderMenuLabel = (option: MenuOption | MenuGroupOption) => {
  11 + return option.label
  12 +}
  13 +
  14 +export const expandedKeys = () => ['three-project']
  15 +
  16 +export const menuOptionsInit = () => {
  17 + const t = window['$t']
  18 +
  19 + return reactive([
  20 + {
  21 + key: 'divider-1',
  22 + type: 'divider'
  23 + },
  24 + {
  25 + label: () => h('span', null, { default: () => t('project.project') }),
  26 + key: 'three-project',
  27 + icon: renderIcon(DevicesIcon),
  28 + children: [
  29 + {
  30 + type: 'group',
  31 + label: () => h('span', null, { default: () => t('project.three_project') }),
  32 + key: 'my-three-project',
  33 + children: [
  34 + {
  35 + label: () =>
  36 + h(
  37 + RouterLink,
  38 + {
  39 + to: {
  40 + name: PageEnum.THREE_HOME_ITEMS_NAME
  41 + }
  42 + },
  43 + { default: () => t('project.all_project') }
  44 + ),
  45 + key: PageEnum.THREE_HOME_ITEMS_NAME,
  46 + icon: renderIcon(TvOutlineIcon)
  47 + }
  48 + ]
  49 + }
  50 + ]
  51 + }
  52 + ])
  53 +}
... ...