officialblock 1.0.6 → 1.0.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (73) hide show
  1. package/dist/index-Ch_ldWmA.js +1 -0
  2. package/dist/index-DXm2cqxo.mjs +485 -0
  3. package/dist/official-block.cjs.js +74 -74
  4. package/dist/official-block.es.js +13577 -10832
  5. package/dist/official-block.umd.js +78 -78
  6. package/dist/style.css +1 -1
  7. package/dist/swiper-JiLDDxAF.js +1 -0
  8. package/dist/swiper-acbnDJoL.mjs +2035 -0
  9. package/dist/utils-DD-vVZej.mjs +316 -0
  10. package/dist/utils-DOLLD0-F.js +1 -0
  11. package/package.json +2 -1
  12. package/src/components/ArticleList/article.vue +3 -3
  13. package/src/components/ArticleList/contact.vue +9 -9
  14. package/src/components/ArticleList/index.ts +1 -1
  15. package/src/components/ArticleList/index.vue +24 -82
  16. package/src/components/ArticleList/setting.vue +61 -71
  17. package/src/components/ArticleList/type.ts +12 -18
  18. package/src/components/BannerImage/index.ts +11 -0
  19. package/src/components/BannerImage/index.vue +153 -0
  20. package/src/components/BannerImage/setting.vue +55 -0
  21. package/src/components/BannerImage/type.ts +10 -0
  22. package/src/components/BannerPage/index.ts +11 -0
  23. package/src/components/BannerPage/index.vue +283 -0
  24. package/src/components/BannerPage/setting.vue +55 -0
  25. package/src/components/BannerPage/type.ts +10 -0
  26. package/src/components/BtnList/index.ts +11 -0
  27. package/src/components/BtnList/index.vue +588 -0
  28. package/src/components/BtnList/setting.vue +255 -0
  29. package/src/components/BtnList/type.ts +10 -0
  30. package/src/components/Button/index.vue +45 -33
  31. package/src/components/CustomSpace/index.ts +11 -0
  32. package/src/components/CustomSpace/index.vue +82 -0
  33. package/src/components/CustomSpace/setting.vue +89 -0
  34. package/src/components/CustomSpace/type.ts +10 -0
  35. package/src/components/GalleryList/index.ts +12 -0
  36. package/src/components/GalleryList/index.vue +311 -0
  37. package/src/components/GalleryList/setting.vue +268 -0
  38. package/src/components/GalleryList/type.ts +10 -0
  39. package/src/components/HeroSlide/index.ts +1 -1
  40. package/src/components/HeroSlide/index.vue +85 -133
  41. package/src/components/HeroSlide/setting.vue +435 -0
  42. package/src/components/HeroSlide/type.ts +5 -14
  43. package/src/components/LinkLIst/index.ts +11 -0
  44. package/src/components/LinkLIst/index.vue +317 -0
  45. package/src/components/LinkLIst/setting.vue +264 -0
  46. package/src/components/LinkLIst/type.ts +10 -0
  47. package/src/components/Media/index.vue +18 -18
  48. package/src/components/Operate/index.vue +17 -7
  49. package/src/components/Profile/index.vue +999 -0
  50. package/src/components/Profile/modal.vue +56 -0
  51. package/src/components/Profile/setting.vue +330 -0
  52. package/src/components/QuickLinks/index.vue +166 -0
  53. package/src/components/QuoteText/index.ts +11 -0
  54. package/src/components/QuoteText/index.vue +133 -0
  55. package/src/components/QuoteText/setting.vue +81 -0
  56. package/src/components/QuoteText/type.ts +10 -0
  57. package/src/components/ScrollKeyInfo/index.vue +0 -0
  58. package/src/components/Swiper/index.vue +538 -0
  59. package/src/components/index.ts +23 -5
  60. package/src/index.ts +56 -12
  61. package/src/main.ts +6 -3
  62. package/src/router/index.ts +6 -0
  63. package/src/style.css +17 -0
  64. package/src/styles/component-isolation.scss +256 -0
  65. package/src/styles/editor.scss +1 -1
  66. package/src/styles/layers.scss +256 -0
  67. package/src/styles/main.scss +21687 -0
  68. package/src/styles/mixins/style-isolation.scss +262 -0
  69. package/src/styles/smart-reset.scss +287 -0
  70. package/src/styles/test.scss +1 -1
  71. package/src/types/button.ts +10 -0
  72. package/src/views/StyleIsolationTest.vue +292 -0
  73. package/src/views/components/ArticleListDemo.vue +49 -10
@@ -0,0 +1,56 @@
1
+ <template>
2
+ <a-modal v-model:visible="visible" :hideTitle="true" :footer="false" bodyClass="profile-model" @cancel="handleCancel">
3
+ <Profile :data="data" @close="handleCancel"></Profile>
4
+ </a-modal>
5
+ </template>
6
+
7
+ <script setup lang="ts">
8
+ import { computed } from 'vue'
9
+ import Profile from './index.vue'
10
+
11
+ const props = defineProps({
12
+ show: {
13
+ type: Boolean,
14
+ default: false
15
+ },
16
+
17
+ data: {
18
+ type: Object,
19
+ default: () => {}
20
+ }
21
+ })
22
+
23
+ const visible = computed(() => props.show)
24
+
25
+ const emit = defineEmits(['update:show'])
26
+
27
+ const handleCancel = () => {
28
+ emit('update:show', false)
29
+ }
30
+ </script>
31
+
32
+ <style lang="scss">
33
+ .arco-modal {
34
+ width: fit-content;
35
+ }
36
+
37
+ .profile-model {
38
+ padding: 0;
39
+ width: 100vw;
40
+ overflow: hidden;
41
+ }
42
+
43
+ @media (min-width: 768px) {
44
+ .profile-model {
45
+ max-height: calc(100vh - 160px);
46
+ border-radius: 12px;
47
+ }
48
+ }
49
+
50
+ @media (max-width: 767.98px) {
51
+ .profile-model {
52
+ border-radius: 0;
53
+ height: 100vh;
54
+ }
55
+ }
56
+ </style>
@@ -0,0 +1,330 @@
1
+ <template>
2
+ <template v-if="showLogo">
3
+ <p class="item-title">学校logo</p>
4
+ <img class="item-img" :src="data.logo" />
5
+ <div class="item-uplaod flex items-center">
6
+ <a-input v-model="data.logo" placeholder="请输入图片链接" allow-clear />
7
+ <a-upload class="fit-content" :show-file-list="false" action="/" />
8
+ </div>
9
+ </template>
10
+ <p class="item-title">标题</p>
11
+ <a-input v-model="data.title" placeholder="请输入标题" allow-clear />
12
+ <p class="item-title">子标题</p>
13
+ <a-input v-model="data.subTitle" placeholder="请输入子标题" allow-clear />
14
+ <p class="item-title">名称</p>
15
+ <a-input v-model="data.name" placeholder="请输入名称" allow-clear />
16
+ <p class="item-title">标签</p>
17
+ <a-input v-model="data.label" placeholder="请输入标签" allow-clear />
18
+ <p class="item-title">图片</p>
19
+ <img class="item-img" :src="data.imgSrc" />
20
+ <div class="item-uplaod flex items-center">
21
+ <a-input v-model="data.imgSrc" placeholder="请输入图片链接" allow-clear />
22
+ <a-upload class="fit-content" :show-file-list="false" action="/" />
23
+ </div>
24
+ <a-input class="mt-2" v-model="data.alt" placeholder="图片alt" allow-clear />
25
+ <p class="item-title pt-2">按钮(最多{{ maxNum }}个)</p>
26
+ <draggable
27
+ v-model="data.buttonList.data"
28
+ :component-data="{
29
+ tag: 'div',
30
+ type: 'transition-group',
31
+ name: !drag ? 'flip-list' : null
32
+ }"
33
+ v-bind="buttonDragOptions"
34
+ :disabled="!shouldShowDragHandle(data.buttonList.data)"
35
+ @start="drag = true"
36
+ @end="drag = false"
37
+ item-key="id"
38
+ >
39
+ <template #item="{ element: button }">
40
+ <div
41
+ class="item-button item-link draggable-item"
42
+ :class="{ 'sortable-disabled': !shouldShowDragHandle(data.buttonList.data) }"
43
+ :key="button.id"
44
+ >
45
+ <div class="btn-group">
46
+ <div
47
+ v-if="shouldShowDragHandle(data.buttonList.data)"
48
+ class="drag-handle"
49
+ >
50
+ <icon-drag-arrow class="drag-icon" />
51
+ </div>
52
+ <icon-delete class="btn-delete" @click="handleDeleteButton(data.buttonList.data, button.id)" />
53
+ </div>
54
+ <a-button type="primary">{{ button.text }}</a-button>
55
+ <div class="item-action flex items-center">
56
+ <a-input class="action-text" v-model="button.text" placeholder="按钮文本" allow-clear />
57
+ <a-input v-model="button.url" placeholder="按钮链接" allow-clear />
58
+ </div>
59
+ <a-checkbox :model-value="button.isExternal">是否外部链接</a-checkbox>
60
+ </div>
61
+ </template>
62
+ </draggable>
63
+ <a-button-group class="mt-2" type="primary">
64
+ <a-button size="mini" @click="handleAddButton('default', data.buttonList.data)"><template #icon><icon-plus /></template> 默认按钮 </a-button>
65
+ <a-button size="mini" @click="handleAddButton('white', data.buttonList.data)"><template #icon><icon-plus /></template> 白色按钮 </a-button>
66
+ <a-button size="mini" @click="handleAddButton('light', data.buttonList.data)"><template #icon><icon-plus /></template> 亮色按钮 </a-button>
67
+ <a-button size="mini" @click="handleAddButton('blue', data.buttonList.data)"><template #icon><icon-plus /></template> 蓝色按钮 </a-button>
68
+ </a-button-group>
69
+ <p class="item-name mt-2">段落</p>
70
+ <draggable
71
+ v-model="data.paragraphs"
72
+ :component-data="{
73
+ tag: 'div',
74
+ type: 'transition-group',
75
+ name: !drag ? 'flip-list' : null
76
+ }"
77
+ v-bind="paragraphDragOptions"
78
+ :disabled="!shouldShowDragHandle(data.paragraphs)"
79
+ @start="drag = true"
80
+ @end="drag = false"
81
+ item-key="id"
82
+ >
83
+ <template #item="{ element: paragraph }">
84
+ <div
85
+ class="item-button item-link draggable-item"
86
+ :class="{ 'sortable-disabled': !shouldShowDragHandle(data.paragraphs) }"
87
+ :key="paragraph.id"
88
+ >
89
+ <div class="btn-group">
90
+ <div
91
+ v-if="shouldShowDragHandle(data.paragraphs)"
92
+ class="drag-handle"
93
+ >
94
+ <icon-drag-arrow class="drag-icon" />
95
+ </div>
96
+ <icon-delete v-if="canAddParagraph" class="btn-delete" @click="handleDeleteButton(data.paragraphs, paragraph.id)" />
97
+ </div>
98
+ <p class="item-title">标题</p>
99
+ <a-input v-model="paragraph.title" placeholder="请输入标题" allow-clear />
100
+
101
+ <p class="item-title mt-2">内容</p>
102
+ <RichTextEditor v-model="paragraph.content"></RichTextEditor>
103
+ </div>
104
+ </template>
105
+ </draggable>
106
+ <div v-if="canAddParagraph" class="item-add-btn flex items-center" @click="handleAddParagraph(data.paragraphs)">
107
+ <icon-plus />
108
+ <span class="btn-text">添加段落</span>
109
+ </div>
110
+ </template>
111
+
112
+ <script lang="ts" setup>
113
+ import { ref, computed } from 'vue'
114
+ import draggable from 'vuedraggable'
115
+ import RichTextEditor from '@/components/RichTextEditor'
116
+ import { randomString } from '@/utils/common'
117
+
118
+ // 拖拽相关状态
119
+ const drag = ref(false)
120
+
121
+ const buttonDragOptions = computed(() => ({
122
+ animation: 200,
123
+ group: 'buttons', // 按钮专用分组
124
+ disabled: false,
125
+ ghostClass: 'ghost'
126
+ }))
127
+
128
+ const paragraphDragOptions = computed(() => ({
129
+ animation: 200,
130
+ group: 'paragraphs', // 段落专用分组
131
+ disabled: false,
132
+ ghostClass: 'ghost'
133
+ }))
134
+
135
+ // 检查是否应该显示拖拽图标
136
+ const shouldShowDragHandle = (list: any[]) => {
137
+ return list && list.length > 1
138
+ }
139
+
140
+ const props = defineProps({
141
+ data: {
142
+ type: Object,
143
+ default: () => {}
144
+ },
145
+
146
+ showLogo: {
147
+ type: Boolean,
148
+ default: true
149
+ },
150
+
151
+ maxNum: {
152
+ type: Number,
153
+ default: 2
154
+ },
155
+
156
+ canAddParagraph: {
157
+ type: Boolean,
158
+ default: false
159
+ }
160
+ })
161
+
162
+ const handleAddButton = (type: string, list: any[]) => {
163
+ if (list.length >= props.maxNum) return
164
+ list.push({
165
+ id: randomString(),
166
+ type,
167
+ text: '查看更多',
168
+ url: undefined,
169
+ isExternal: false
170
+ })
171
+ }
172
+
173
+ const handleDeleteButton = (list: any[], id: string) => {
174
+ list.splice(list.findIndex(item => item.id === id), 1)
175
+ }
176
+
177
+ const handleAddParagraph = (list: any[]) => {
178
+ list.push({
179
+ title: '耀华国际教育学校浙江桐乡',
180
+ subTitle: '耀华国际教育学校浙江桐乡',
181
+ name: '耀华国际教育学校浙江桐乡',
182
+ label: '123',
183
+ imgSrc: 'https://osswebsite.ycyw.com/media-library/ywies-bj/images/home/ywies-tx.jpg',
184
+ alt: '',
185
+ buttonList: {
186
+ id: randomString(),
187
+ type: 'BtnList',
188
+ readOnly: true,
189
+ width: '',
190
+ bgColor: '',
191
+ data: []
192
+ },
193
+ paragraphs: {
194
+ title: '',
195
+ content: ''
196
+ }
197
+ })
198
+ }
199
+ </script>
200
+
201
+ <style lang="scss" scoped>
202
+ .setting-item {
203
+ position: relative;
204
+ padding: 16px 12px;
205
+ background: #f0f2f5;
206
+ border-radius: 8px;
207
+ margin-bottom: 20px;
208
+
209
+ .btn-group {
210
+ position: absolute;
211
+ right: 0;
212
+ top: 0;
213
+ display: flex;
214
+ align-items: center;
215
+ padding: 4px;
216
+
217
+ .btn-delete {
218
+ padding: 4px;
219
+ font-size: 24px;
220
+ cursor: pointer;
221
+ }
222
+ }
223
+
224
+ .item-name {
225
+ font-size: 16px;
226
+ font-weight: 600;
227
+ padding-bottom: 10px;
228
+ border-bottom: 1px solid #fff;
229
+ }
230
+
231
+ .item-button {
232
+ position: relative;
233
+ padding: 12px 8px 4px;
234
+ background: #fff;
235
+ border-radius: 4px;
236
+ margin: 4px 0;
237
+ transition: all 0.3s ease;
238
+
239
+ &.draggable-item {
240
+ cursor: move;
241
+
242
+ &:hover {
243
+ box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
244
+ transform: translateY(-1px);
245
+ }
246
+
247
+ // 当禁用拖拽时,不显示拖拽效果
248
+ &.sortable-disabled {
249
+ cursor: default;
250
+
251
+ &:hover {
252
+ box-shadow: none;
253
+ transform: none;
254
+ }
255
+ }
256
+ }
257
+
258
+ .arco-input-wrapper {
259
+ background: #f2f3f5;
260
+ }
261
+ }
262
+
263
+ .item-link {
264
+ background: #f0f2f5;
265
+
266
+ .arco-input-wrapper {
267
+ background: #fff;
268
+ }
269
+ }
270
+
271
+ .item-img {
272
+ height: 100px;
273
+ }
274
+
275
+ // 拖拽相关样式
276
+ .flip-list-move {
277
+ transition: transform 0.5s;
278
+ }
279
+
280
+ .no-move {
281
+ transition: transform 0s;
282
+ }
283
+
284
+ .ghost {
285
+ opacity: 0.5;
286
+ background: #c8ebfb;
287
+ }
288
+
289
+ .item-action {
290
+ padding: 10px 0;
291
+
292
+ .action-text {
293
+ width: 150px;
294
+ margin-right: 8px;
295
+ }
296
+ }
297
+
298
+ .item-add-btn {
299
+ display: inline-block;
300
+ padding: 2px 8px;
301
+ margin-top: 5px;
302
+ font-size: 11px;
303
+ color: #165dff;
304
+ border-radius: 4px;
305
+ font-weight: 600;
306
+ border: 1px solid #165dff;
307
+ cursor: pointer;
308
+ }
309
+ }
310
+
311
+ .drag-handle {
312
+ padding: 4px;
313
+ cursor: grab;
314
+ padding: 4px;
315
+ border-radius: 4px;
316
+
317
+ &:hover {
318
+ background-color: #f0f2f5;
319
+ }
320
+
321
+ &:active {
322
+ cursor: grabbing;
323
+ }
324
+
325
+ .drag-icon {
326
+ font-size: 16px;
327
+ color: #86909c;
328
+ }
329
+ }
330
+ </style>
@@ -0,0 +1,166 @@
1
+ <template>
2
+ <div class="banner-quicklinks">
3
+ <div class="quick-links__nav__prev" v-show="showPrev" @click="scrollPrev"></div>
4
+ <div class="quick-links__wrapper" ref="quickLinksWrapperRef" @scroll="onScroll">
5
+ <div class="quick-links__list">
6
+ <Button v-for="item in data" :key="item.id" :data="item" :hasHoverBg="false"></Button>
7
+ </div>
8
+ </div>
9
+ <div class="quick-links__nav__next" v-show="showNext" @click="scrollNext"></div>
10
+ </div>
11
+ </template>
12
+
13
+ <script lang="ts" setup>
14
+ import { ref, watch, onMounted, nextTick, onUnmounted } from 'vue'
15
+ import type { PropType } from 'vue'
16
+ import type { ButtonProps } from '@/types/button'
17
+ import Button from '@/components/Button/index.vue'
18
+
19
+ const props = defineProps({
20
+ data: {
21
+ type: Array as PropType<ButtonProps[]>,
22
+ default: () => []
23
+ }
24
+ })
25
+
26
+ const quickLinksWrapperRef = ref<HTMLDivElement | null>(null)
27
+ const showPrev = ref(false)
28
+ const showNext = ref(false)
29
+
30
+ const checkScroll = () => {
31
+ const el = quickLinksWrapperRef.value
32
+ if (!el) return
33
+ showPrev.value = el.scrollLeft > 0
34
+ showNext.value = el.scrollLeft + el.clientWidth < el.scrollWidth
35
+ }
36
+
37
+ const scrollPrev = () => {
38
+ const el = quickLinksWrapperRef.value
39
+ if (!el) return
40
+ el.scrollBy({ left: -el.clientWidth / 1.5, behavior: 'smooth' })
41
+ }
42
+
43
+ const scrollNext = () => {
44
+ const el = quickLinksWrapperRef.value
45
+ if (!el) return
46
+ el.scrollBy({ left: el.clientWidth / 1.5, behavior: 'smooth' })
47
+ }
48
+
49
+ const onScroll = () => {
50
+ checkScroll()
51
+ }
52
+
53
+ watch(() => props.data, async () => {
54
+ await nextTick()
55
+ checkScroll()
56
+ })
57
+
58
+ onMounted(() => {
59
+ window.addEventListener('resize', checkScroll)
60
+ nextTick(checkScroll)
61
+ })
62
+
63
+ onUnmounted(() => {
64
+ window.removeEventListener('resize', checkScroll)
65
+ })
66
+ </script>
67
+
68
+ <style lang="scss" scoped>
69
+ .banner-quicklinks {
70
+ position: relative;
71
+ width: 100%;
72
+ height: 44px;
73
+ background: #0a1f8f;
74
+ }
75
+
76
+ @media (max-width: 767.98px) {
77
+ .banner-quicklinks {
78
+ height: 41px;
79
+ }
80
+ }
81
+
82
+ .banner-quicklinks .quick-links__wrapper {
83
+ display: flex;
84
+ align-items: center;
85
+ justify-content: space-around;
86
+ position: absolute;
87
+ left: 0;
88
+ bottom: 0;
89
+ width: 100%;
90
+ height: 100%;
91
+ z-index: 1;
92
+ background-color: #0a1f8f;
93
+ overflow-x: scroll;
94
+ scroll-behavior: smooth;
95
+ scrollbar-color: transparent;
96
+ scrollbar-width: none;
97
+ }
98
+
99
+ .banner-quicklinks .quick-links__list {
100
+ display: flex;
101
+ }
102
+
103
+ .banner-quicklinks .quick-links__nav__next,
104
+ .banner-quicklinks .quick-links__nav__prev {
105
+ position: absolute;
106
+ width: 33px;
107
+ height: 100%;
108
+ box-shadow: 0 4px 4px hsla(0,0%,100%,.2);
109
+ background-color: #0032a0;
110
+ display: flex;
111
+ align-items: center;
112
+ justify-content: center;
113
+ z-index: 2;
114
+ cursor: pointer;
115
+ }
116
+
117
+ @media (max-width: 1023.98px) {
118
+ .banner-quicklinks .quick-links__nav__next,
119
+ .banner-quicklinks .quick-links__nav__prev {
120
+ width: 28px;
121
+ }
122
+ }
123
+
124
+ @media (max-width: 767.98px) {
125
+ .banner-quicklinks .quick-links__nav__next,
126
+ .banner-quicklinks .quick-links__nav__prev {
127
+ box-shadow: 0 4px 4px hsla(0,0%,100%,.2);
128
+ }
129
+ }
130
+
131
+ .banner-quicklinks .quick-links__nav__next:after,
132
+ .banner-quicklinks .quick-links__nav__prev:after {
133
+ content: "";
134
+ width: 24px;
135
+ height: 24px;
136
+ background-image: url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjQiIGhlaWdodD0iMjQiIHZpZXdCb3g9IjAgMCAyNCAyNCIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggZD0iTTkgNkwxNSAxMkw5IDE4IiBzdHJva2U9IiNmZmZmZmYiIHN0cm9rZS13aWR0aD0iMS41IiBzdHJva2UtbGluZWNhcD0icm91bmQiIHN0cm9rZS1saW5lam9pbj0icm91bmQiLz4KPC9zdmc+Cg==);
137
+ background-position: 50%;
138
+ background-size: cover;
139
+ background-repeat: no-repeat;
140
+ background-color: hsla(0,0%,100%,0);
141
+ }
142
+
143
+ @media (max-width: 1023.98px) {
144
+ .banner-quicklinks .quick-links__nav__next:after,
145
+ .banner-quicklinks .quick-links__nav__prev:after {
146
+ width: 14px;
147
+ height: 14px;
148
+ }
149
+ }
150
+
151
+ .banner-quicklinks .quick-links__nav__prev {
152
+ left: -1px;
153
+ }
154
+
155
+ .banner-quicklinks .quick-links__nav__prev:after {
156
+ transform: scale(-1);
157
+ }
158
+
159
+ .banner-quicklinks .quick-links__nav__next {
160
+ right: -1px;
161
+ }
162
+
163
+ :deep(.button-primary) {
164
+ background: transparent;
165
+ }
166
+ </style>
@@ -0,0 +1,11 @@
1
+ import type { App, Plugin } from 'vue'
2
+ import QuoteText from './index.vue'
3
+
4
+ export default {
5
+ install: (app: App) => {
6
+ app.component('BannerImage', QuoteText)
7
+ },
8
+ } satisfies Plugin
9
+
10
+ export { default as QuoteText } from './index.vue'
11
+ export type { QuoteTextProps, QuoteTextEmits } from './type'
@@ -0,0 +1,133 @@
1
+ <template>
2
+ <div class="quote-text" @mouseenter="isHover = true" @mouseleave="isHover = false">
3
+ <div class="quote-text__container quote-text--normal container-content" :style="{ background: modelValue?.data.bgColor || 'transparent' }">
4
+ <div v-if="modelValue?.data.hasLine" class="quote-text__line"></div>
5
+ <div class="quote-text__content" v-html="modelValue?.data.text"></div>
6
+ <div class="quote-text__desc" v-html="modelValue?.data.desc"></div>
7
+ </div>
8
+
9
+ <Operate v-if="!modelValue?.readOnly" v-model:show="isHover" @handle-edit="showSetting = true" @handle-delete="handleDelete" @handle-copy="handleCopy"></Operate>
10
+ </div>
11
+
12
+ <Setting v-model:show="showSetting" :data="modelValue"></Setting>
13
+ </template>
14
+
15
+ <script lang="ts" setup>
16
+ import { ref } from 'vue'
17
+ import { randomString } from '@/utils/common'
18
+ import Operate from '@/components/Operate/index.vue'
19
+ import Setting from './setting.vue'
20
+
21
+ // 定义组件名称
22
+ defineOptions({
23
+ name: 'OuoteText'
24
+ })
25
+
26
+ const props = defineProps({
27
+ modelValue: {
28
+ type: Object,
29
+ default: () => {}
30
+ },
31
+
32
+ // 是否预览
33
+ isPreview: {
34
+ type: Boolean,
35
+ default: false
36
+ }
37
+ })
38
+
39
+ const emit = defineEmits(['update:modelValue', 'handleDelete', 'handleCopy'])
40
+
41
+ const handleInit = () => {
42
+ if (props.modelValue && props.modelValue.data) return // 有数据不用初始化
43
+ const data = {
44
+ id: props.modelValue?.id || randomString(),
45
+ type: 'OuoteText',
46
+ readOnly: props.modelValue?.readOnly || false,
47
+ data: {
48
+ width: '',
49
+ bgColor: '',
50
+ hasLine: true,
51
+ text: '浙江桐乡特色高中将于今年9月成立!',
52
+ desc: '耀华国际教育学校浙江桐乡校区成立于 2017 年,先进的校园设施确保学 生在安全友好的环境中学习。学校坐落于高桥镇,提供从幼儿阶段至高中 阶段 (K2 至13 年级) 的教育服务,招收2 岁至18 岁本地和外籍学生。'
53
+ }
54
+ }
55
+ emit('update:modelValue', data)
56
+ }
57
+
58
+ const isHover = ref<boolean>(false);
59
+ const showSetting = ref<boolean>(false);
60
+
61
+ const handleDelete = () => {
62
+ emit('handleDelete', props.modelValue.id)
63
+ }
64
+
65
+ const handleCopy = () => {
66
+ emit('handleCopy', props.modelValue)
67
+ }
68
+
69
+ handleInit()
70
+ </script>
71
+
72
+ <style lang="scss" scoped>
73
+ .quote-text {
74
+ position: relative;
75
+ }
76
+
77
+ .quote-text__container {
78
+ display: flex;
79
+ flex-direction: column;
80
+ align-items: center;
81
+ }
82
+
83
+ .quote-text--large .quote-text__line {
84
+ margin-bottom: 19px;
85
+ }
86
+
87
+ @media (max-width: 767.98px) {
88
+ .quote-text--large .quote-text__line {
89
+ margin-bottom: 12px;
90
+ }
91
+ }
92
+
93
+ .quote-text--large .quote-text__content,
94
+ .quote-text--large .quote-text__desc {
95
+ color: #0032a0;
96
+ color: var(--text-color--primary, #0032a0);
97
+ }
98
+
99
+ @media (max-width: 767.98px) {
100
+ .quote-text--large .quote-text__content,
101
+ .quote-text--large .quote-text__desc {
102
+ color: #0032a0;
103
+ color: var(--text-color--primary, #0032a0);
104
+ }
105
+ }
106
+
107
+ .quote-text__line {
108
+ width: 2px;
109
+ height: 24px;
110
+ background-color: #0048e8;
111
+ background-color: var(--quote-line-color, #0048e8);
112
+ margin-bottom: 32px;
113
+ }
114
+
115
+ @media (max-width: 1023.98px) {
116
+ .quote-text__line {
117
+ margin-bottom: 24px;
118
+ }
119
+ }
120
+
121
+ @media (max-width: 767.98px) {
122
+ .quote-text__line {
123
+ width: 1px;
124
+ height: 20px;
125
+ margin-bottom: 12px;
126
+ }
127
+ }
128
+
129
+ .quote-text__content {
130
+ color: #151f8c;
131
+ color: var(--quote-text-color, #151f8c);
132
+ }
133
+ </style>