Skip to content

Commit d596f0e

Browse files
committed
add DxfViewerComponent and integrate into ResultModal; update package dependencies
1 parent dbd60f5 commit d596f0e

File tree

5 files changed

+244
-27
lines changed

5 files changed

+244
-27
lines changed

components/DialogWrapper.vue

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,8 @@
22
<teleport to="body">
33
<div v-if="isModalOpen" class="modal">
44
<div class="modal__background" @click="closeModal"></div>
5-
65
<div class="modal__body modal-body">
7-
<MainButton label="close modal" :isLabelShow=false :size="sizeType.s" :icon="iconType.close"
8-
@click="closeModal" class="modal-body__close" />
9-
10-
6+
<MainButton label="close modal" :isLabelShow=false :size="sizeType.s" :icon="iconType.close" @click="closeModal" class="modal-body__close" />
117
<slot />
128
</div>
139
</div>

components/DxfViewerComponent.vue

Lines changed: 153 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,153 @@
1+
<template>
2+
<div class="dxf-viewer-container" ref="containerRef">
3+
<div v-if="isLoading" class="loading-overlay">
4+
<MainLoader />
5+
</div>
6+
<div v-if="error" class="error-overlay">
7+
Err
8+
</div>
9+
</div>
10+
</template>
11+
12+
<script setup>
13+
14+
const props = defineProps({
15+
dxfUrl: {
16+
type: String,
17+
default: null
18+
},
19+
options: {
20+
type: Object,
21+
default: () => ({
22+
autoResize: true,
23+
colorCorrection: true,
24+
clearColor: 0xE9E9E7,
25+
})
26+
}
27+
})
28+
const containerRef = ref(null)
29+
const isLoading = ref(false)
30+
const error = ref(null)
31+
let dxfViewer = null
32+
33+
const loadDxf = async (url) => {
34+
if (!url || !dxfViewer) return
35+
36+
isLoading.value = true
37+
error.value = null
38+
39+
try {
40+
await dxfViewer.Load({ url })
41+
} catch (err) {
42+
console.error('DXF loading error:', err)
43+
error.value = err.message || err.toString()
44+
} finally {
45+
isLoading.value = false
46+
}
47+
}
48+
49+
const clearViewer = () => {
50+
if (dxfViewer) {
51+
dxfViewer.Clear()
52+
error.value = null
53+
}
54+
}
55+
56+
onMounted(async () => {
57+
await nextTick()
58+
59+
if (process.client && containerRef.value) {
60+
const [{ DxfViewer }, THREE] = await Promise.all([
61+
import('dxf-viewer'),
62+
import('three')
63+
])
64+
const viewerOptions = {
65+
...props.options
66+
}
67+
if (props.options.clearColor !== undefined) {
68+
viewerOptions.clearColor = new THREE.Color(props.options.clearColor)
69+
}
70+
dxfViewer = new DxfViewer(containerRef.value, viewerOptions)
71+
if (props.dxfUrl) {
72+
await loadDxf(props.dxfUrl)
73+
}
74+
}
75+
})
76+
77+
onBeforeUnmount(() => {
78+
if (dxfViewer) {
79+
dxfViewer.Destroy()
80+
dxfViewer = null
81+
}
82+
})
83+
84+
watch(() => props.dxfUrl, async (newUrl, oldUrl) => {
85+
if (newUrl !== oldUrl) {
86+
if (newUrl) {
87+
await loadDxf(newUrl)
88+
} else {
89+
clearViewer()
90+
}
91+
}
92+
})
93+
94+
defineExpose({
95+
getViewer: () => dxfViewer,
96+
loadDxf,
97+
clearViewer
98+
})
99+
</script>
100+
101+
<style scoped lang="scss">
102+
.dxf-viewer-container {
103+
position: relative;
104+
max-height: 100%;
105+
max-width: 100%;
106+
width: 100%;
107+
min-height: 320px;
108+
border-radius: 8px;
109+
display: flex;
110+
align-items: center;
111+
justify-content: center;
112+
overflow: hidden;
113+
114+
canvas {
115+
display: block;
116+
max-width: 100%;
117+
max-height: 100%;
118+
width: 100%;
119+
}
120+
}
121+
122+
.loading-overlay {
123+
position: absolute;
124+
top: 0;
125+
left: 0;
126+
right: 0;
127+
bottom: 0;
128+
display: flex;
129+
flex-direction: column;
130+
align-items: center;
131+
justify-content: center;
132+
background: var(--fill-tertiary);
133+
z-index: 10;
134+
border-radius: 8px;
135+
}
136+
137+
.error-overlay {
138+
z-index: 1;
139+
position: absolute;
140+
top: 0;
141+
left: 0;
142+
right: 0;
143+
bottom: 0;
144+
display: flex;
145+
align-items: center;
146+
justify-content: center;
147+
text-align: center;
148+
border-radius: 8px;
149+
background-color: var(--error-background);
150+
border: solid 1px var(--error-border);
151+
color: var(--label-primary);
152+
}
153+
</style>

components/ResultModal.vue

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -33,15 +33,15 @@
3333
class="controls__next"
3434
/>
3535
</div>
36+
3637
<div class="modal__wrapper">
3738
<div v-if="isHaveError" :class="placeholderClasses" class="modal__placeholder">
3839
Err
3940
</div>
4041
<template v-else-if="resultModalData.isMultiSheet">
41-
<SvgDisplay
42-
:src="resultModalData.svgs[activePart]"
43-
:class="displayClasses"
44-
@click="updateFullScreen"
42+
<DxfViewerComponent
43+
:dxfUrl="resultModalData.dxfs[activePart]"
44+
:class="displayClasses"
4545
class="modal__display"
4646
/>
4747
<MainButton
@@ -55,11 +55,10 @@
5555
:theme="themeType.primary"
5656
/>
5757
</template>
58-
<SvgDisplay
58+
<DxfViewerComponent
5959
v-else
60-
:src="resultModalData.svgs[0]"
61-
:class="displayClasses"
62-
@click="updateFullScreen"
60+
:dxfUrl="resultModalData.dxfs[0]"
61+
:class="displayClasses"
6362
class="modal__display"
6463
/>
6564
<MainButton v-if="!isHaveError" label="fullscreen" :size="sizeType.s" :theme="themeType.primary"
@@ -145,8 +144,15 @@ const updateFullScreen = () => {
145144
localStorage.setItem('isFullScreen', unref(isFullScreen))
146145
}
147146
onMounted(() => {
147+
activePart.value = 0
148148
isFullScreen.value = localStorage.getItem('isFullScreen') === 'true'
149149
})
150+
151+
watch(resultDialog, (isOpen) => {
152+
if (isOpen) {
153+
activePart.value = 0
154+
}
155+
})
150156
const displayClasses = computed(() => ({
151157
'modal__display--is-fullscreen': unref(isFullScreen) && !unref(isHaveError)
152158
}))

0 commit comments

Comments
 (0)