index.vue
10.6 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
<template>
<div class="go-canvas-setting">
<n-form inline :label-width="45" size="small" label-placement="left">
<n-form-item label="宽度">
<!-- 尺寸选择 -->
<n-input-number
size="small"
v-model:value="canvasConfig.width"
:disabled="editCanvas.lockScale"
:validator="validator"
@update:value="changeSizeHandle"
></n-input-number>
</n-form-item>
<n-form-item label="高度">
<n-input-number
size="small"
v-model:value="canvasConfig.height"
:disabled="editCanvas.lockScale"
:validator="validator"
@update:value="changeSizeHandle"
></n-input-number>
</n-form-item>
</n-form>
<div class="upload-box">
<n-upload
v-model:file-list="uploadFileListRef"
:show-file-list="false"
:customRequest="customRequest"
:onBeforeUpload="beforeUploadHandle"
>
<n-upload-dragger>
<img v-if="canvasConfig.backgroundImage" class="upload-show" :src="getBackgroundImagePath(canvasConfig.backgroundImage)" alt="背景" />
<div class="upload-img" v-show="!canvasConfig.backgroundImage">
<img src="@/assets/images/canvas/noImage.png" />
<n-text class="upload-desc" depth="3">
背景图需小于 {{ backgroundImageSize }}M ,格式为 png/jpg/gif 的文件
</n-text>
</div>
</n-upload-dragger>
</n-upload>
</div>
<n-space vertical :size="12">
<n-space>
<!-- THINGS_KIT 新增预置背景选择 -->
<SelectBackgroundImage ref="selectBackgroundImageRef" @bgChange="handleBgChange" />
<n-text>背景颜色</n-text>
<div class="picker-height">
<n-color-picker
v-if="!switchSelectColorLoading"
size="small"
style="width: 250px"
v-model:value="canvasConfig.background"
:showPreview="true"
:swatches="swatchesColors"
></n-color-picker>
</div>
</n-space>
<n-space>
<n-text>应用类型</n-text>
<n-select
size="small"
style="width: 250px"
v-model:value="selectColorValue"
:disabled="!canvasConfig.backgroundImage"
:options="selectColorOptions"
@update:value="selectColorValueHandle"
/>
</n-space>
<n-space>
<n-text>背景控制</n-text>
<n-button class="clear-btn" size="small" :disabled="!canvasConfig.backgroundImage" @click="clearImage">
清除背景
</n-button>
<n-button class="clear-btn" size="small" :disabled="!canvasConfig.background" @click="clearColor">
清除颜色
</n-button>
</n-space>
<n-space>
<n-text>适配方式</n-text>
<n-button-group>
<n-button
v-for="item in previewTypeList"
:key="item.key"
:type="canvasConfig.previewScaleType === item.key ? 'primary' : 'tertiary'"
ghost
size="small"
@click="selectPreviewType(item.key)"
>
<n-tooltip :show-arrow="false" trigger="hover">
<template #trigger>
<n-icon class="select-preview-icon" size="18">
<component :is="item.icon"></component>
</n-icon>
</template>
{{ item.desc }}
</n-tooltip>
</n-button>
</n-button-group>
</n-space>
</n-space>
<!-- 滤镜 -->
<styles-setting :isCanvas="true" :chartStyles="canvasConfig"></styles-setting>
<n-divider style="margin: 10px 0"></n-divider>
<!-- 主题选择和全局配置 -->
<n-tabs class="tabs-box" size="small" type="segment">
<n-tab-pane
v-for="item in globalTabList"
:key="item.key"
:name="item.key"
size="small"
display-directive="show:lazy"
>
<template #tab>
<n-space>
<span>{{ item.title }}</span>
<n-icon size="16" class="icon-position">
<component :is="item.icon"></component>
</n-icon>
</n-space>
</template>
<component :is="item.render"></component>
</n-tab-pane>
</n-tabs>
</div>
</template>
<script setup lang="ts">
import { ref, nextTick, watch, computed } from 'vue'
import { backgroundImageSize } from '@/settings/designSetting'
import { swatchesColors } from '@/settings/chartThemes/index'
import { FileTypeEnum } from '@/enums/fileTypeEnum'
import { useChartEditStore } from '@/store/modules/chartEditStore/chartEditStore'
import { EditCanvasConfigEnum } from '@/store/modules/chartEditStore/chartEditStore.d'
import { StylesSetting } from '@/components/Pages/ChartItemSetting'
import { UploadCustomRequestOptions } from 'naive-ui'
import { fileToUrl, loadAsyncComponent } from '@/utils'
import { PreviewScaleEnum } from '@/enums/styleEnum'
import { icon } from '@/plugins'
// THINGS_KIT 路径转换,同步生产环境与开发环境的保存的静态资源文件路径不一致
import SelectBackgroundImage from './external/SelectBackgroundImage.vue'
import { useBackgroundSelect } from '@/utils/external/useBackgroundImageSelect'
import { useUploadBackgroundImg } from './external/useUploadBackground'
const { getBackgroundImagePath } = useBackgroundSelect()
const { ColorPaletteIcon } = icon.ionicons5
const { ScaleIcon, FitToScreenIcon, FitToHeightIcon, FitToWidthIcon } = icon.carbon
const chartEditStore = useChartEditStore()
const canvasConfig = computed(() => chartEditStore.getEditCanvasConfig)
const editCanvas = chartEditStore.getEditCanvas
const uploadFileListRef = ref()
const switchSelectColorLoading = ref(false)
const selectColorValue = ref(0)
const ChartThemeColor = loadAsyncComponent(() => import('./components/ChartThemeColor/index.vue'))
// 默认应用类型
const selectColorOptions = [
{
label: '应用颜色',
value: 0
},
{
label: '应用背景',
value: 1
}
]
const globalTabList = [
{
key: 'ChartTheme',
title: '主题颜色',
icon: ColorPaletteIcon,
render: ChartThemeColor
}
]
// THINGS_KIT 优化适配方式默认选中X轴铺满,Y轴自适应滚动
const previewTypeList = [
{
key: PreviewScaleEnum.SCROLL_Y,
title: 'Y轴滚动',
icon: FitToWidthIcon,
desc: 'X轴铺满,Y轴自适应滚动'
},
{
key: PreviewScaleEnum.FIT,
title: '自适应',
icon: ScaleIcon,
desc: '自适应比例展示,页面会有留白'
},
{
key: PreviewScaleEnum.SCROLL_X,
title: 'X轴滚动',
icon: FitToHeightIcon,
desc: 'Y轴铺满,X轴自适应滚动'
},
{
key: PreviewScaleEnum.FULL,
title: '铺满',
icon: FitToScreenIcon,
desc: '强行拉伸画面,填充所有视图'
}
]
watch(
() => canvasConfig.value.selectColor,
newValue => {
selectColorValue.value = newValue ? 0 : 1
},
{
immediate: true
}
)
// 画布尺寸规则
const validator = (x: number) => x > 50
// 修改尺寸
const changeSizeHandle = () => {
chartEditStore.computedScale()
}
// 上传图片前置处理
//@ts-ignore
const beforeUploadHandle = async ({ file }) => {
uploadFileListRef.value = []
const type = file.file.type
const size = file.file.size
if (size > 1024 * 1024 * backgroundImageSize) {
window['$message'].warning(`图片超出 ${backgroundImageSize}M 限制,请重新上传!`)
return false
}
if (type !== FileTypeEnum.PNG && type !== FileTypeEnum.JPEG && type !== FileTypeEnum.GIF) {
window['$message'].warning('文件格式不符合,请重新上传!')
return false
}
return true
}
// 应用颜色
const selectColorValueHandle = (value: number) => {
canvasConfig.value.selectColor = value == 0
}
// THINGS_KIT 优化清除背景,背景选择下拉框值还存在
const selectBackgroundImageRef=ref<typeof SelectBackgroundImage|null>()
// 清除背景
const clearImage = () => {
chartEditStore.setEditCanvasConfig(EditCanvasConfigEnum.BACKGROUND_IMAGE, undefined)
chartEditStore.setEditCanvasConfig(EditCanvasConfigEnum.SELECT_COLOR, true)
// THINGS_KIT 优化清除背景,背景选择下拉框值还存在
selectBackgroundImageRef.value?.removeBg()
}
// 启用/关闭 颜色(强制更新)
const switchSelectColorHandle = () => {
switchSelectColorLoading.value = true
setTimeout(() => {
switchSelectColorLoading.value = false
})
}
// 清除颜色
const clearColor = () => {
chartEditStore.setEditCanvasConfig(EditCanvasConfigEnum.BACKGROUND, undefined)
if (canvasConfig.value.backgroundImage) {
chartEditStore.setEditCanvasConfig(EditCanvasConfigEnum.SELECT_COLOR, false)
}
switchSelectColorHandle()
}
// 自定义上传操作
const customRequest = (options: UploadCustomRequestOptions) => {
const { file } = options
nextTick(() => {
if (file.file) {
// THINGS_KIT 上传图片逻辑修改
useUploadBackgroundImg(file.file)
// const ImageUrl = fileToUrl(file.file)
// chartEditStore.setEditCanvasConfig(EditCanvasConfigEnum.BACKGROUND_IMAGE, ImageUrl)
// chartEditStore.setEditCanvasConfig(EditCanvasConfigEnum.SELECT_COLOR, false)
} else {
window['$message'].error('添加图片失败,请稍后重试!')
}
})
}
// 选择适配方式
const selectPreviewType = (key: PreviewScaleEnum) => {
chartEditStore.setEditCanvasConfig(EditCanvasConfigEnum.PREVIEW_SCALE_TYPE, key)
}
// THINGS_KIT 优化背景图片选择,应用类型自动选择应用背景
const handleBgChange=(value:string)=>{
if(!value) return
selectColorValue.value = 1,selectColorValueHandle(1),chartEditStore.setEditCanvasConfig(EditCanvasConfigEnum.BACKGROUND_IMAGE, value)
}
</script>
<style lang="scss" scoped>
$uploadWidth: 326px;
$uploadHeight: 193px;
@include go(canvas-setting) {
padding-top: 20px;
.upload-box {
cursor: pointer;
margin-bottom: 20px;
@include deep() {
.n-card__content {
padding: 0;
overflow: hidden;
}
.n-upload-dragger {
padding: 5px;
width: $uploadWidth;
background-color: rgba(0, 0, 0, 0);
}
}
.upload-show {
width: -webkit-fill-available;
height: $uploadHeight;
border-radius: 5px;
}
.upload-img {
display: flex;
flex-direction: column;
align-items: center;
img {
height: 150px;
}
.upload-desc {
padding: 10px 0;
}
}
}
.icon-position {
padding-top: 2px;
}
.picker-height {
min-height: 35px;
}
.clear-btn {
padding-left: 2.25em;
padding-right: 2.25em;
}
.select-preview-icon {
padding-right: 0.68em;
padding-left: 0.68em;
}
.tabs-box {
margin-top: 20px;
}
}
</style>