officialblock 1.0.1 → 1.0.2
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.
- package/README.md +25 -1
- package/dist/official-block.cjs.js +186 -1
- package/dist/official-block.es.js +22619 -73
- package/dist/official-block.umd.js +186 -1
- package/dist/style.css +1 -1
- package/package.json +12 -2
- package/src/App.vue +32 -82
- package/src/components/ArticleList/article.vue +73 -0
- package/src/components/ArticleList/contact.vue +95 -0
- package/src/components/ArticleList/index.vue +215 -48
- package/src/components/ArticleList/setting.vue +407 -0
- package/src/components/Button/index.vue +183 -0
- package/src/components/Media/index.vue +327 -0
- package/src/components/Operate/index.vue +74 -0
- package/src/components/RichTextEditor/RichTextEditor.vue +277 -0
- package/src/components/RichTextEditor/index.ts +7 -0
- package/src/components/ThemePreview/ThemePreview.vue +462 -0
- package/src/components/ThemePreview/index.ts +4 -0
- package/src/components/index.ts +3 -0
- package/src/composables/useTheme.ts +205 -0
- package/src/index.ts +15 -4
- package/src/main.ts +16 -1
- package/src/router/index.ts +84 -0
- package/src/style.css +0 -1
- package/src/styles/editor.scss +649 -0
- package/src/styles/test.scss +20 -0
- package/src/styles/variables.scss +639 -0
- package/src/utils/common.ts +13 -0
- package/src/utils/theme.ts +335 -0
- package/src/views/Layout.vue +247 -0
- package/src/views/NotFound.vue +114 -0
- package/src/views/components/ArticleListDemo.vue +167 -0
- package/src/views/components/HeroSlideDemo.vue +353 -0
- package/src/views/components/RichTextEditorDemo.vue +53 -0
- package/src/views/components/ThemeDemo.vue +477 -0
- package/src/views/guide/Installation.vue +234 -0
- package/src/views/guide/Introduction.vue +174 -0
- package/src/views/guide/QuickStart.vue +265 -0
|
@@ -1,78 +1,245 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
2
|
+
<a-row class="article-list" @mouseenter="isHover = true" @mouseleave="isHover = false">
|
|
3
|
+
<!-- 左侧文本 后侧媒体 -->
|
|
4
|
+
<!-- 左侧一直是一半,但只有左侧时是100% -->
|
|
5
|
+
<a-col :sm="{span: 24}" :md="{span: hasMedia ? 12 : 24}">
|
|
6
|
+
<div class="article-list-left">
|
|
7
|
+
<template v-for="item in modelValue?.data" :key="item.id">
|
|
8
|
+
<Article v-if="item.type === 'Article'" :article="item.data"></Article>
|
|
9
|
+
<Contact v-if="item.type === 'Contact'" :contact="item.data"></Contact>
|
|
10
|
+
</template>
|
|
11
|
+
</div>
|
|
12
|
+
</a-col>
|
|
13
|
+
<a-col v-if="hasMedia" :sm="{span: 24}" :md="{span: 12}">
|
|
14
|
+
<div class="article-list-right">
|
|
15
|
+
<template v-for="item in modelValue?.data" :key="item.id">
|
|
16
|
+
<Media :type="item.type" :data="item.data" :preview="modelValue.isPreview"></Media>
|
|
17
|
+
</template>
|
|
18
|
+
</div>
|
|
19
|
+
</a-col>
|
|
20
|
+
|
|
21
|
+
<!-- <div v-if="isHover" class="add-btn">
|
|
22
|
+
<icon-plus />
|
|
23
|
+
<span class="btn-text">添加组件</span>
|
|
24
|
+
</div> -->
|
|
25
|
+
<Operate v-model:show="isHover" @handle-edit="showSetting = true" @handle-delete="handleDelete" @handle-copy="handleCopy"></Operate>
|
|
26
|
+
</a-row>
|
|
27
|
+
|
|
28
|
+
<Setting v-model:show="showSetting" :data="modelValue"></Setting>
|
|
12
29
|
</template>
|
|
13
30
|
|
|
14
31
|
<script lang="ts" setup>
|
|
15
|
-
import { computed } from 'vue'
|
|
16
|
-
import
|
|
32
|
+
import { computed, ref } from 'vue'
|
|
33
|
+
import { randomString } from '@/utils/common'
|
|
34
|
+
import Article from './article.vue'
|
|
35
|
+
import Contact from './contact.vue'
|
|
36
|
+
import Media from '@/components/Media/index.vue'
|
|
37
|
+
import Setting from './setting.vue'
|
|
38
|
+
import Operate from '@/components/Operate/index.vue'
|
|
17
39
|
|
|
18
40
|
// 定义组件名称
|
|
19
41
|
defineOptions({
|
|
20
42
|
name: 'ArticleList'
|
|
21
43
|
})
|
|
22
44
|
|
|
23
|
-
const props =
|
|
24
|
-
|
|
25
|
-
|
|
45
|
+
const props = defineProps({
|
|
46
|
+
modelValue: {
|
|
47
|
+
type: Object,
|
|
48
|
+
default: () => {}
|
|
49
|
+
},
|
|
50
|
+
|
|
51
|
+
// 是否预览
|
|
52
|
+
isPreview: {
|
|
53
|
+
type: Boolean,
|
|
54
|
+
default: false
|
|
55
|
+
}
|
|
26
56
|
})
|
|
27
57
|
|
|
28
|
-
const emit = defineEmits
|
|
29
|
-
defineSlots<ComponentSlots>()
|
|
58
|
+
const emit = defineEmits(['update:modelValue', 'handleDelete', 'handleCopy'])
|
|
30
59
|
|
|
31
|
-
const
|
|
60
|
+
const hasMedia = computed(() => {
|
|
61
|
+
if (!(props.modelValue && props.modelValue.data && props.modelValue.data.length)) return false
|
|
62
|
+
return props.modelValue.data.some((item: any) => item.type === 'Image' || item.type === 'Video' || item.type === 'ImageList')
|
|
63
|
+
})
|
|
32
64
|
|
|
33
|
-
|
|
34
|
-
if (
|
|
35
|
-
|
|
65
|
+
const handleInit = () => {
|
|
66
|
+
if (props.modelValue && props.modelValue.id) return // 有数据不用初始化
|
|
67
|
+
const data = {
|
|
68
|
+
id: randomString(),
|
|
69
|
+
type: 'ArticleList',
|
|
70
|
+
isPreview: false,
|
|
71
|
+
width: '',
|
|
72
|
+
background: '',
|
|
73
|
+
data: [
|
|
74
|
+
{
|
|
75
|
+
id: randomString(),
|
|
76
|
+
type: 'Article',
|
|
77
|
+
data: {
|
|
78
|
+
title: '这里是标题',
|
|
79
|
+
content: '耀华国际教育学校浙江桐乡校区成立于 2017 年,先进的校园设施确保学 生在安全友好的环境中学习。学校坐落于高桥镇,提供从幼儿阶段至高中 阶段 (K2 至13 年级) 的教育服务,招收2 岁至18 岁本地和外籍学生。',
|
|
80
|
+
buttonList: [
|
|
81
|
+
{
|
|
82
|
+
id: randomString(),
|
|
83
|
+
text: '查看更多',
|
|
84
|
+
url: 'https://www.baidu.com',
|
|
85
|
+
isExternal: false
|
|
86
|
+
}
|
|
87
|
+
],
|
|
88
|
+
linkList: [
|
|
89
|
+
{
|
|
90
|
+
id: randomString(),
|
|
91
|
+
text: '查看更多',
|
|
92
|
+
url: 'https://www.baidu.com',
|
|
93
|
+
isExternal: false
|
|
94
|
+
}
|
|
95
|
+
]
|
|
96
|
+
}
|
|
97
|
+
},
|
|
98
|
+
{
|
|
99
|
+
id: randomString(),
|
|
100
|
+
type: 'Image',
|
|
101
|
+
data: {
|
|
102
|
+
imgSrc: 'https://osswebsite.ycyw.com/media-library/ywies-bj/images/home/ywies-tx.jpg',
|
|
103
|
+
caption: '',
|
|
104
|
+
alt: '',
|
|
105
|
+
isRound: false
|
|
106
|
+
}
|
|
107
|
+
},
|
|
108
|
+
{
|
|
109
|
+
id: randomString(),
|
|
110
|
+
type: 'Contact',
|
|
111
|
+
data: {
|
|
112
|
+
title: '这里是标题',
|
|
113
|
+
content: '耀华国际教育学校浙江桐乡校区成立于 2017 年,先进的校园设施确保学 生在安全友好的环境中学习。学校坐落于高桥镇,提供从幼儿阶段至高中 阶段 (K2 至13 年级) 的教育服务,招收2 岁至18 岁本地和外籍学生。',
|
|
114
|
+
categories: [
|
|
115
|
+
{
|
|
116
|
+
id: randomString(),
|
|
117
|
+
text: '分类1'
|
|
118
|
+
}
|
|
119
|
+
],
|
|
120
|
+
linkList: [
|
|
121
|
+
{
|
|
122
|
+
id: randomString(),
|
|
123
|
+
text: '查看更多',
|
|
124
|
+
url: 'https://www.baidu.com',
|
|
125
|
+
isExternal: false
|
|
126
|
+
}
|
|
127
|
+
]
|
|
128
|
+
}
|
|
129
|
+
},
|
|
130
|
+
{
|
|
131
|
+
id: randomString(),
|
|
132
|
+
type: 'ImageList',
|
|
133
|
+
data: {
|
|
134
|
+
imageList: [
|
|
135
|
+
{
|
|
136
|
+
id: randomString(),
|
|
137
|
+
src: 'https://osswebsite.ycyw.com/media-library/ywies-bj/images/home/ywies-tx.jpg'
|
|
138
|
+
}
|
|
139
|
+
],
|
|
140
|
+
}
|
|
141
|
+
},
|
|
142
|
+
{
|
|
143
|
+
id: randomString(),
|
|
144
|
+
type: 'Video',
|
|
145
|
+
data: {
|
|
146
|
+
videoSrc: 'http://mpv.videocc.net/4b964bbdf4/3/4b964bbdf481505df84cfd703c4b3043_2.mp4',
|
|
147
|
+
imgSrc: 'https://object.ycyw.com/media-library/ycyw-edu/news/20250628%20HKDSE%20Forum/Cover.jpg',
|
|
148
|
+
}
|
|
149
|
+
},
|
|
150
|
+
]
|
|
36
151
|
}
|
|
37
|
-
|
|
38
|
-
|
|
152
|
+
emit('update:modelValue', data)
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
const isHover = ref<boolean>(false);
|
|
156
|
+
const showSetting = ref<boolean>(false);
|
|
39
157
|
|
|
40
|
-
|
|
41
|
-
.
|
|
42
|
-
padding: 16px;
|
|
43
|
-
border: 1px solid #ddd;
|
|
44
|
-
border-radius: 8px;
|
|
45
|
-
background: #fff;
|
|
46
|
-
transition: all 0.3s ease;
|
|
158
|
+
const handleDelete = () => {
|
|
159
|
+
emit('handleDelete', props.modelValue.id)
|
|
47
160
|
}
|
|
48
161
|
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
box-shadow: 0 2px 8px rgba(64, 158, 255, 0.2);
|
|
162
|
+
const handleCopy = () => {
|
|
163
|
+
emit('handleCopy', props.modelValue)
|
|
52
164
|
}
|
|
53
165
|
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
166
|
+
handleInit()
|
|
167
|
+
</script>
|
|
168
|
+
|
|
169
|
+
<style lang="scss" scoped>
|
|
170
|
+
/* ===== 响应式设计 - 桌面优先,确保正确的层叠顺序 ===== */
|
|
171
|
+
|
|
172
|
+
/* 基础样式 - 桌面端 (1024px 及以上) */
|
|
173
|
+
.article-list {
|
|
174
|
+
position: relative;
|
|
175
|
+
max-width: 952px;
|
|
176
|
+
padding: 16px 36px;
|
|
177
|
+
margin: 0 auto;
|
|
178
|
+
|
|
179
|
+
// &:hover {
|
|
180
|
+
// border: 2px solid $primary-color;
|
|
181
|
+
// }
|
|
182
|
+
|
|
183
|
+
.add-btn {
|
|
184
|
+
position: absolute;
|
|
185
|
+
left: 50%;
|
|
186
|
+
bottom: 0;
|
|
187
|
+
transform: translate(-50%, 50%);
|
|
188
|
+
|
|
189
|
+
padding: 4px 8px;
|
|
190
|
+
font-size: 10px;
|
|
191
|
+
background: $primary-color;
|
|
192
|
+
color: #fff;
|
|
193
|
+
border-radius: 4px;
|
|
194
|
+
font-weight: 600;
|
|
195
|
+
cursor: pointer;
|
|
196
|
+
}
|
|
58
197
|
}
|
|
59
198
|
|
|
60
|
-
.
|
|
61
|
-
|
|
62
|
-
|
|
199
|
+
.article-list-right {
|
|
200
|
+
margin-left: 60px;
|
|
201
|
+
max-width: 409px;
|
|
63
202
|
}
|
|
64
203
|
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
204
|
+
/* 平板设备 (768px - 1023px) */
|
|
205
|
+
@media (max-width: 1023.98px) {
|
|
206
|
+
.article-list {
|
|
207
|
+
padding: 12px 24px;
|
|
208
|
+
max-width: 1000px;
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
.article-list-right {
|
|
212
|
+
justify-content: flex-end;
|
|
213
|
+
margin-left: 20px;
|
|
214
|
+
max-width: 320px;
|
|
215
|
+
}
|
|
68
216
|
}
|
|
69
217
|
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
218
|
+
/* 小平板和大手机 (576px - 767px) */
|
|
219
|
+
@media (max-width: 767.98px) {
|
|
220
|
+
.article-list {
|
|
221
|
+
padding: 8px 12px;
|
|
222
|
+
max-width: 976px;
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
.article-list-right {
|
|
226
|
+
justify-content: flex-start;
|
|
227
|
+
margin-left: 0;
|
|
228
|
+
max-width: 100vw;
|
|
229
|
+
}
|
|
73
230
|
}
|
|
74
231
|
|
|
75
|
-
|
|
76
|
-
|
|
232
|
+
/* 小手机 (575px 及以下) */
|
|
233
|
+
@media (max-width: 575.98px) {
|
|
234
|
+
.article-list {
|
|
235
|
+
padding: 8px 12px;
|
|
236
|
+
max-width: 100%;
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
.article-list-right {
|
|
240
|
+
justify-content: flex-start;
|
|
241
|
+
margin-left: 0;
|
|
242
|
+
max-width: 100%;
|
|
243
|
+
}
|
|
77
244
|
}
|
|
78
245
|
</style>
|
|
@@ -0,0 +1,407 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<a-drawer :width="500" :visible="show" :footer="false" @cancel="handleCancel" unmountOnClose>
|
|
3
|
+
<template #title>
|
|
4
|
+
{{data.type}}组件编辑
|
|
5
|
+
</template>
|
|
6
|
+
<div class="setting-content">
|
|
7
|
+
<!-- 组件自身属性 -->
|
|
8
|
+
<div class="setting-header flex items-center">
|
|
9
|
+
<span class="header-title">组件宽度</span>
|
|
10
|
+
<a-select v-model="data.width" placeholder="请选择" allow-clear>
|
|
11
|
+
<a-option value="default">默认</a-option>
|
|
12
|
+
<a-option value="small">小</a-option>
|
|
13
|
+
<a-option value="medium">中</a-option>
|
|
14
|
+
<a-option value="large">大</a-option>
|
|
15
|
+
</a-select>
|
|
16
|
+
</div>
|
|
17
|
+
<div class="setting-header flex items-center">
|
|
18
|
+
<span class="header-title">组件背景</span>
|
|
19
|
+
<a-select v-model="data.background" placeholder="请选择" allow-clear>
|
|
20
|
+
<a-option value="white">白色</a-option>
|
|
21
|
+
<a-option value="grey">灰色</a-option>
|
|
22
|
+
</a-select>
|
|
23
|
+
</div>
|
|
24
|
+
|
|
25
|
+
<a-button-group type="primary">
|
|
26
|
+
<a-button size="mini" @click="handleAdd('Article')"><template #icon><icon-plus /></template> Article </a-button>
|
|
27
|
+
<a-button size="mini" @click="handleAdd('Contact')"><template #icon><icon-plus /></template> Contact </a-button>
|
|
28
|
+
<a-button size="mini" @click="handleAdd('Image')"><template #icon><icon-plus /></template> Image </a-button>
|
|
29
|
+
<a-button size="mini" @click="handleAdd('ImageList')"><template #icon><icon-plus /></template> ImageList </a-button>
|
|
30
|
+
<a-button size="mini" @click="handleAdd('Video')"><template #icon><icon-plus /></template> Video </a-button>
|
|
31
|
+
</a-button-group>
|
|
32
|
+
|
|
33
|
+
<!-- 子组件属性 -->
|
|
34
|
+
<div class="setting-body">
|
|
35
|
+
<div class="setting-item" v-for="item in data.data" :key="item.id">
|
|
36
|
+
<p class="item-name">{{ item.type }}</p>
|
|
37
|
+
|
|
38
|
+
<template v-if="item.type === 'Article'">
|
|
39
|
+
<p class="item-title">标题</p>
|
|
40
|
+
<a-input v-model="item.data.title" placeholder="请输入标题" allow-clear />
|
|
41
|
+
|
|
42
|
+
<p class="item-title">内容</p>
|
|
43
|
+
<RichTextEditor v-model="item.data.content"></RichTextEditor>
|
|
44
|
+
|
|
45
|
+
<p class="item-title">按钮</p>
|
|
46
|
+
<div class="item-button" v-for="button in item.data.buttonList" :key="button.id">
|
|
47
|
+
<icon-delete class="btn-delete" @click="handleDeleteButton(item.data.buttonList, button.id)" />
|
|
48
|
+
<a-button type="primary">{{ button.text }}</a-button>
|
|
49
|
+
<div class="item-action flex items-center">
|
|
50
|
+
<a-input class="action-text" v-model="button.text" placeholder="按钮文本" allow-clear />
|
|
51
|
+
<a-input v-model="button.url" placeholder="按钮链接" allow-clear />
|
|
52
|
+
</div>
|
|
53
|
+
<a-checkbox :model-value="button.isExternal">是否外部链接</a-checkbox>
|
|
54
|
+
</div>
|
|
55
|
+
<div class="item-add-btn flex items-center" @click="handleAddButton(item.data.buttonList)">
|
|
56
|
+
<icon-plus />
|
|
57
|
+
<span class="btn-text">添加按钮</span>
|
|
58
|
+
</div>
|
|
59
|
+
|
|
60
|
+
<p class="item-title">链接</p>
|
|
61
|
+
<div class="item-button" v-for="link in item.data.linkList" :key="link.id">
|
|
62
|
+
<icon-delete class="btn-delete" @click="handleDeleteLink(item.data.linkList, link.id)" />
|
|
63
|
+
<a-link href="link">{{ link.text }}</a-link>
|
|
64
|
+
<div class="item-action flex items-center">
|
|
65
|
+
<a-input class="action-text" v-model="link.text" placeholder="按钮文本" allow-clear />
|
|
66
|
+
<a-input v-model="link.url" placeholder="按钮链接" allow-clear />
|
|
67
|
+
</div>
|
|
68
|
+
<a-checkbox :model-value="link.isExternal">是否外部链接</a-checkbox>
|
|
69
|
+
</div>
|
|
70
|
+
<div class="item-add-btn flex items-center" @click="handleAddLink(item.data.linkList)">
|
|
71
|
+
<icon-plus />
|
|
72
|
+
<span class="btn-text">添加链接</span>
|
|
73
|
+
</div>
|
|
74
|
+
</template>
|
|
75
|
+
|
|
76
|
+
<template v-if="item.type === 'Contact'">
|
|
77
|
+
<p class="item-title">标题</p>
|
|
78
|
+
<a-input v-model="item.data.title" placeholder="请输入标题" allow-clear />
|
|
79
|
+
|
|
80
|
+
<p class="item-title">内容</p>
|
|
81
|
+
<RichTextEditor v-model="item.data.content"></RichTextEditor>
|
|
82
|
+
|
|
83
|
+
<p class="item-title">分类</p>
|
|
84
|
+
<div class="item-button" v-for="category in item.data.categories" :key="category.id">
|
|
85
|
+
<icon-delete class="btn-delete" @click="handleDeleteCategory(item.data.categories, category.id)" />
|
|
86
|
+
<a-link href="link">{{ category.text }}</a-link>
|
|
87
|
+
<div class="item-action flex items-center">
|
|
88
|
+
<a-input v-model="category.text" placeholder="分类名称" allow-clear />
|
|
89
|
+
</div>
|
|
90
|
+
</div>
|
|
91
|
+
<div class="item-add-btn flex items-center" @click="handleAddCategory(item.data.categories)">
|
|
92
|
+
<icon-plus />
|
|
93
|
+
<span class="btn-text">添加分类</span>
|
|
94
|
+
</div>
|
|
95
|
+
|
|
96
|
+
<p class="item-title">链接</p>
|
|
97
|
+
<div class="item-button" v-for="link in item.data.linkList" :key="link.id">
|
|
98
|
+
<icon-delete class="btn-delete" @click="handleDeleteLink(item.data.linkList, link.id)" />
|
|
99
|
+
<a-link href="link">{{ link.text }}</a-link>
|
|
100
|
+
<div class="item-action flex items-center">
|
|
101
|
+
<a-input class="action-text" v-model="link.text" placeholder="按钮文本" allow-clear />
|
|
102
|
+
<a-input v-model="link.url" placeholder="按钮链接" allow-clear />
|
|
103
|
+
</div>
|
|
104
|
+
<a-checkbox :model-value="link.isExternal">是否外部链接</a-checkbox>
|
|
105
|
+
</div>
|
|
106
|
+
<div class="item-add-btn flex items-center" @click="handleAddLink(item.data.linkList)">
|
|
107
|
+
<icon-plus />
|
|
108
|
+
<span class="btn-text">添加链接</span>
|
|
109
|
+
</div>
|
|
110
|
+
</template>
|
|
111
|
+
|
|
112
|
+
<template v-if="item.type === 'Image'">
|
|
113
|
+
<img class="item-img" :src="item.data.imgSrc" />
|
|
114
|
+
<div class="item-uplaod flex items-center">
|
|
115
|
+
<a-input v-model="item.data.imgSrc" placeholder="请输入标题" allow-clear />
|
|
116
|
+
<a-upload class="fit-content" :show-file-list="false" action="/" />
|
|
117
|
+
</div>
|
|
118
|
+
<a-input class="mt-10" v-model="item.data.caption" placeholder="图片描述" allow-clear />
|
|
119
|
+
<a-input class="mt-10" v-model="item.data.alt" placeholder="图片alt" allow-clear />
|
|
120
|
+
<a-checkbox class="pt-10" :model-value="item.data.isRound">圆角</a-checkbox>
|
|
121
|
+
</template>
|
|
122
|
+
|
|
123
|
+
<template v-if="item.type === 'ImageList'">
|
|
124
|
+
<p class="item-title">图片组</p>
|
|
125
|
+
<div class="item-img-list">
|
|
126
|
+
<div class="img-list-item flex" v-for="img in item.data.imageList" :key="img.id">
|
|
127
|
+
<div class="item-img-box" v-if="img.src">
|
|
128
|
+
<icon-close-circle-fill class="item-img-dlete" @click="handleDeleteImage(item.data.imageList, img.id)" />
|
|
129
|
+
<img class="item-img small-img" :src="img.src" />
|
|
130
|
+
</div>
|
|
131
|
+
|
|
132
|
+
<div class="item-right flex-1">
|
|
133
|
+
<a-input style="margin-bottom: 12px" v-model="img.src" placeholder="请输入图片路径" allow-clear />
|
|
134
|
+
<a-upload :show-file-list="false" action="/" />
|
|
135
|
+
</div>
|
|
136
|
+
</div>
|
|
137
|
+
</div>
|
|
138
|
+
<div class="item-add-btn flex items-center" @click="handleAddImage(item.data.imageList)">
|
|
139
|
+
<icon-plus />
|
|
140
|
+
<span class="btn-text">添加图片</span>
|
|
141
|
+
</div>
|
|
142
|
+
</template>
|
|
143
|
+
|
|
144
|
+
<template v-if="item.type === 'Video'">
|
|
145
|
+
<p class="item-title">视频</p>
|
|
146
|
+
<video class="item-img" :src="item.data.videoSrc" controls></video>
|
|
147
|
+
<div class="item-uplaod flex items-center">
|
|
148
|
+
<a-input v-model="item.data.videoSrc" placeholder="请输入视频链接" allow-clear />
|
|
149
|
+
<a-upload class="fit-content" :show-file-list="false" action="/" />
|
|
150
|
+
</div>
|
|
151
|
+
<img class="item-img" :src="item.data.imgSrc" />
|
|
152
|
+
<div class="item-uplaod flex items-center">
|
|
153
|
+
<a-input v-model="item.data.imgSrc" placeholder="视频封面" allow-clear />
|
|
154
|
+
<a-upload class="fit-content" :show-file-list="false" action="/" />
|
|
155
|
+
</div>
|
|
156
|
+
</template>
|
|
157
|
+
</div>
|
|
158
|
+
</div>
|
|
159
|
+
</div>
|
|
160
|
+
</a-drawer>
|
|
161
|
+
</template>
|
|
162
|
+
|
|
163
|
+
<script lang="ts" setup>
|
|
164
|
+
import RichTextEditor from '@/components/RichTextEditor'
|
|
165
|
+
import { randomString } from '@/utils/common'
|
|
166
|
+
|
|
167
|
+
const props = defineProps({
|
|
168
|
+
show: {
|
|
169
|
+
type: Boolean,
|
|
170
|
+
default: false
|
|
171
|
+
},
|
|
172
|
+
|
|
173
|
+
data: {
|
|
174
|
+
type: Object,
|
|
175
|
+
default: () => {}
|
|
176
|
+
}
|
|
177
|
+
})
|
|
178
|
+
|
|
179
|
+
const emit = defineEmits(['update:show']);
|
|
180
|
+
|
|
181
|
+
const handleCancel = () => {
|
|
182
|
+
emit('update:show', false);
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
const handleAdd = (type: string) => {
|
|
186
|
+
const detail = props.data;
|
|
187
|
+
if (type === 'Article') {
|
|
188
|
+
detail.data.push({
|
|
189
|
+
id: randomString(),
|
|
190
|
+
type: 'Article',
|
|
191
|
+
data: {
|
|
192
|
+
title: '',
|
|
193
|
+
content: '',
|
|
194
|
+
buttonList: [],
|
|
195
|
+
linkList: []
|
|
196
|
+
}
|
|
197
|
+
})
|
|
198
|
+
} else if (type === 'Contact') {
|
|
199
|
+
detail.data.push({
|
|
200
|
+
id: randomString(),
|
|
201
|
+
type: 'Contact',
|
|
202
|
+
data: {
|
|
203
|
+
title: '',
|
|
204
|
+
content: '',
|
|
205
|
+
categories: [],
|
|
206
|
+
linkList: []
|
|
207
|
+
}
|
|
208
|
+
})
|
|
209
|
+
} else if (type === 'Image') {
|
|
210
|
+
detail.data.push({
|
|
211
|
+
id: randomString(),
|
|
212
|
+
type: 'Image',
|
|
213
|
+
data: {
|
|
214
|
+
imgSrc: '',
|
|
215
|
+
caption: '',
|
|
216
|
+
alt: '',
|
|
217
|
+
isRound: false
|
|
218
|
+
}
|
|
219
|
+
})
|
|
220
|
+
} else if (type === 'ImageList') {
|
|
221
|
+
detail.data.push({
|
|
222
|
+
id: randomString(),
|
|
223
|
+
type: 'ImageList',
|
|
224
|
+
data: {
|
|
225
|
+
imageList: []
|
|
226
|
+
}
|
|
227
|
+
})
|
|
228
|
+
} else if (type === 'Video') {
|
|
229
|
+
detail.data.push({
|
|
230
|
+
id: randomString(),
|
|
231
|
+
type: 'Video',
|
|
232
|
+
data: {
|
|
233
|
+
videoSrc: '',
|
|
234
|
+
imgSrc: ''
|
|
235
|
+
}
|
|
236
|
+
})
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
const handleAddButton = (list: any[]) => {
|
|
241
|
+
list.push({
|
|
242
|
+
id: randomString(),
|
|
243
|
+
text: '查看更多',
|
|
244
|
+
url: 'https://www.baidu.com',
|
|
245
|
+
isExternal: false
|
|
246
|
+
})
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
const handleDeleteButton = (list: any[], id: string) => {
|
|
250
|
+
list.splice(list.findIndex(item => item.id === id), 1)
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
const handleAddLink = (list: any[]) => {
|
|
254
|
+
list.push({
|
|
255
|
+
id: randomString(),
|
|
256
|
+
text: '查看更多',
|
|
257
|
+
url: 'https://www.baidu.com',
|
|
258
|
+
isExternal: false
|
|
259
|
+
})
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
const handleDeleteLink = (list: any[], id: string) => {
|
|
263
|
+
list.splice(list.findIndex(item => item.id === id), 1)
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
const handleAddCategory = (list: any[]) => {
|
|
267
|
+
list.push({
|
|
268
|
+
id: randomString(),
|
|
269
|
+
text: '分类'
|
|
270
|
+
})
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
const handleDeleteCategory = (list: any[], id: string) => {
|
|
274
|
+
list.splice(list.findIndex(item => item.id === id), 1)
|
|
275
|
+
}
|
|
276
|
+
const handleAddImage = (list: any[]) => {
|
|
277
|
+
list.push({
|
|
278
|
+
id: randomString(),
|
|
279
|
+
src: ''
|
|
280
|
+
})
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
const handleDeleteImage = (list: any[], img: string) => {
|
|
284
|
+
list.splice(list.findIndex(item => item === img), 1)
|
|
285
|
+
}
|
|
286
|
+
</script>
|
|
287
|
+
|
|
288
|
+
<style lang="scss" scoped>
|
|
289
|
+
.setting-content {
|
|
290
|
+
.setting-header {
|
|
291
|
+
padding-bottom: 12px;
|
|
292
|
+
|
|
293
|
+
.header-title {
|
|
294
|
+
width: 120px;
|
|
295
|
+
padding-right: 12px;
|
|
296
|
+
text-align: right;
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
.setting-body {
|
|
301
|
+
margin-top: 12px;
|
|
302
|
+
|
|
303
|
+
.setting-item {
|
|
304
|
+
padding: 16px 12px;
|
|
305
|
+
background: #f0f2f5;
|
|
306
|
+
border-radius: 8px;
|
|
307
|
+
margin-bottom: 20px;
|
|
308
|
+
|
|
309
|
+
.item-name {
|
|
310
|
+
font-size: 16px;
|
|
311
|
+
font-weight: 600;
|
|
312
|
+
padding-bottom: 10px;
|
|
313
|
+
border-bottom: 1px solid #fff;
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
.item-title {
|
|
317
|
+
padding: 12px 0 8px 0;
|
|
318
|
+
font-size: 14px;
|
|
319
|
+
font-weight: 600;
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
.arco-input-wrapper {
|
|
323
|
+
background: #fff;
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
.item-button {
|
|
327
|
+
position: relative;
|
|
328
|
+
padding: 12px 8px 4px;
|
|
329
|
+
background: #fff;
|
|
330
|
+
border-radius: 4px;
|
|
331
|
+
margin-bottom: 4px;
|
|
332
|
+
|
|
333
|
+
.arco-input-wrapper {
|
|
334
|
+
background: #f2f3f5;
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
.btn-delete {
|
|
338
|
+
position: absolute;
|
|
339
|
+
padding: 12px;
|
|
340
|
+
top: 0;
|
|
341
|
+
right: 0;
|
|
342
|
+
font-size: 40px;
|
|
343
|
+
cursor: pointer;
|
|
344
|
+
}
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
.item-action {
|
|
348
|
+
padding: 10px 0;
|
|
349
|
+
|
|
350
|
+
.action-text {
|
|
351
|
+
width: 150px;
|
|
352
|
+
margin-right: 8px;
|
|
353
|
+
}
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
.item-add-btn {
|
|
357
|
+
display: inline-block;
|
|
358
|
+
padding: 2px 8px;
|
|
359
|
+
margin-top: 5px;
|
|
360
|
+
font-size: 11px;
|
|
361
|
+
color: #165dff;
|
|
362
|
+
border-radius: 4px;
|
|
363
|
+
font-weight: 600;
|
|
364
|
+
border: 1px solid #165dff;
|
|
365
|
+
cursor: pointer;
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
.item-img {
|
|
369
|
+
margin-top: 12px;
|
|
370
|
+
height: 160px;
|
|
371
|
+
}
|
|
372
|
+
|
|
373
|
+
.fit-content {
|
|
374
|
+
width: fit-content;
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
.item-img-list {
|
|
378
|
+
.img-list-item {
|
|
379
|
+
margin-top: 8px;
|
|
380
|
+
}
|
|
381
|
+
.item-img-box {
|
|
382
|
+
margin-right: 12px;
|
|
383
|
+
position: relative;
|
|
384
|
+
width: 133px;
|
|
385
|
+
height: 100px;
|
|
386
|
+
|
|
387
|
+
.item-img-dlete {
|
|
388
|
+
position: absolute;
|
|
389
|
+
padding: 8px;
|
|
390
|
+
font-size: 32px;
|
|
391
|
+
top: -16px;
|
|
392
|
+
right: -16px;
|
|
393
|
+
color: red;
|
|
394
|
+
cursor: pointer;
|
|
395
|
+
}
|
|
396
|
+
}
|
|
397
|
+
|
|
398
|
+
.small-img {
|
|
399
|
+
margin: 0;
|
|
400
|
+
height: 100px;
|
|
401
|
+
object-fit: cover;
|
|
402
|
+
}
|
|
403
|
+
}
|
|
404
|
+
}
|
|
405
|
+
}
|
|
406
|
+
}
|
|
407
|
+
</style>
|