feat(数据大屏): 增加图形组件

This commit is contained in:
wangjiahao 2024-02-18 18:21:08 +08:00
parent c15b098d46
commit a85578ff7a
10 changed files with 361 additions and 2 deletions

View File

@ -0,0 +1 @@
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1708249747987" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="8596" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><path d="M512 64c60.5 0 119.2 11.8 174.4 35.2 53.3 22.6 101.3 54.9 142.4 96 41.2 41.2 73.5 89.1 96 142.4C948.2 392.8 960 451.5 960 512s-11.8 119.2-35.2 174.4c-22.6 53.3-54.9 101.3-96 142.4-41.2 41.2-89.1 73.5-142.4 96C631.2 948.2 572.5 960 512 960s-119.2-11.8-174.4-35.2c-53.3-22.6-101.3-54.9-142.4-96-41.2-41.2-73.5-89.1-96-142.4C75.8 631.2 64 572.5 64 512s11.8-119.2 35.2-174.4c22.6-53.3 54.9-101.3 96-142.4s89.1-73.5 142.4-96C392.8 75.8 451.5 64 512 64m0-64C229.2 0 0 229.2 0 512s229.2 512 512 512 512-229.2 512-512S794.8 0 512 0z" p-id="8597"></path></svg>

After

Width:  |  Height:  |  Size: 884 B

View File

@ -0,0 +1 @@
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1708246996806" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="4208" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><path d="M928 896H96a53.393333 53.393333 0 0 1-53.333333-53.333333V181.333333a53.393333 53.393333 0 0 1 53.333333-53.333333h832a53.393333 53.393333 0 0 1 53.333333 53.333333v661.333334a53.393333 53.393333 0 0 1-53.333333 53.333333zM96 170.666667a10.666667 10.666667 0 0 0-10.666667 10.666666v661.333334a10.666667 10.666667 0 0 0 10.666667 10.666666h832a10.666667 10.666667 0 0 0 10.666667-10.666666V181.333333a10.666667 10.666667 0 0 0-10.666667-10.666666z" p-id="4209"></path></svg>

After

Width:  |  Height:  |  Size: 808 B

View File

@ -0,0 +1 @@
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1708249769352" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="9558" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><path d="M928.64 896a2.144 2.144 0 0 1-0.64 0H96a32.032 32.032 0 0 1-27.552-48.288l416-704c11.488-19.456 43.552-19.456 55.104 0l413.152 699.2A31.936 31.936 0 0 1 928.64 896z m-776.576-64h719.84L512 222.912 152.064 832z" p-id="9559"></path></svg>

After

Width:  |  Height:  |  Size: 569 B

View File

@ -0,0 +1 @@
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1708250676998" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="10597" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><path d="M832 337.6 832 106.688C832 83.072 812.864 64 789.376 64L106.688 64C83.072 64 64 83.072 64 106.688l0 682.688C64 812.928 83.072 832 106.688 832l251.456 0c62.912 96.192 171.328 160 294.592 160 194.112 0 352-157.952 352-352C1004.736 511.424 935.232 399.04 832 337.6zM128 768 128 128l640 0 0 179.776C731.776 295.168 693.12 288 652.736 288 458.688 288 300.8 445.952 300.8 640c0 45.184 8.896 88.256 24.448 128L128 768zM652.736 928C494.016 928 364.8 798.784 364.8 640s129.216-288 287.936-288 288 129.216 288 288S811.52 928 652.736 928z" p-id="10598"></path></svg>

After

Width:  |  Height:  |  Size: 889 B

View File

@ -60,6 +60,31 @@ export const CANVAS_MATERIAL = [
}
]
},
{
category: 'DeGraphical',
title: '图形',
span: 8,
details: [
{
value: 'rect',
type: 'graphical',
title: '矩形',
icon: 'graphical-rect'
},
{
value: 'triangle',
type: 'graphical',
title: '三角形',
icon: 'graphical-triangle'
},
{
value: 'circular',
type: 'graphical',
title: '圆形',
icon: 'graphical-circular'
}
]
},
{
category: 'CanvasIcon',
title: '图标',

View File

@ -86,7 +86,7 @@ const groupActiveChange = category => {
:data-id="groupInfo.category + '&' + chartInfo.value"
>
<Icon
v-if="chartInfo.type === 'outer_svg'"
v-if="['outer_svg', 'graphical'].includes(chartInfo.type)"
class-name="item-top-icon"
:name="chartInfo.icon"
/>

View File

@ -181,6 +181,26 @@ const list = [
color: ''
}
},
{
component: 'DeGraphical',
name: '图形',
label: '图形',
propValue: '',
icon: 'icon_graphical',
innerType: '',
editing: false,
canvasActive: false,
x: 1,
y: 1,
sizeX: 15,
sizeY: 15,
style: {
width: 300,
height: 200,
color: '#000000',
board: 1
}
},
{
component: 'DeTabs',
name: '选项卡',

View File

@ -0,0 +1,268 @@
<script setup lang="ts">
import CommonAttr from '@/custom-component/common/CommonAttr.vue'
import { dvMainStoreWithOut } from '@/store/modules/data-visualization/dvMain'
import { snapshotStoreWithOut } from '@/store/modules/data-visualization/snapshot'
import { storeToRefs } from 'pinia'
import { ElIcon, ElMessage } from 'element-plus-secondary'
import { ref, onMounted, onBeforeUnmount, watch } from 'vue'
import { beforeUploadCheck, uploadFileResult } from '@/api/staticResource'
import { imgUrlTrans } from '@/utils/imgUtils'
import eventBus from '@/utils/eventBus'
import ImgViewDialog from '@/custom-component/ImgViewDialog.vue'
withDefaults(
defineProps<{
themes?: EditorTheme
}>(),
{
themes: 'dark'
}
)
const dvMainStore = dvMainStoreWithOut()
const snapshotStore = snapshotStoreWithOut()
const { curComponent } = storeToRefs(dvMainStore)
const fileList = ref([])
const dialogImageUrl = ref('')
const dialogVisible = ref(false)
const uploadDisabled = ref(false)
const files = ref(null)
const maxImageSize = 15000000
const handlePictureCardPreview = file => {
dialogImageUrl.value = file.url
dialogVisible.value = true
}
const handleRemove = (_, fileList) => {
uploadDisabled.value = false
curComponent.value.propValue.url = null
fileList.value = []
snapshotStore.recordSnapshotCache()
}
async function upload(file) {
uploadFileResult(file.file, fileUrl => {
snapshotStore.recordSnapshotCache()
curComponent.value.propValue.url = fileUrl
})
}
const goFile = () => {
files.value.click()
}
const reUpload = e => {
const file = e.target.files[0]
if (file.size > maxImageSize) {
sizeMessage()
}
uploadFileResult(file, fileUrl => {
snapshotStore.recordSnapshotCache()
curComponent.value.propValue.url = fileUrl
fileList.value = [{ url: imgUrlTrans(curComponent.value.propValue.url) }]
})
}
const sizeMessage = () => {
ElMessage.success('图片大小不符合')
}
const init = () => {
if (curComponent.value.propValue.url) {
fileList.value = [{ url: imgUrlTrans(curComponent.value.propValue.url) }]
} else {
fileList.value = []
}
}
watch(
() => curComponent.value.propValue.url,
() => {
init()
}
)
onMounted(() => {
init()
eventBus.on('uploadImg', goFile)
})
onBeforeUnmount(() => {
eventBus.off('uploadImg', goFile)
})
</script>
<template>
<div class="attr-list de-collapse-style">
<input
id="input"
ref="files"
type="file"
accept=".jpeg,.jpg,.png,.gif"
hidden
@click="
e => {
e.target.value = ''
}
"
@change="reUpload"
/>
<CommonAttr
:themes="themes"
:element="curComponent"
:background-color-picker-width="197"
:background-border-select-width="197"
>
<el-collapse-item :effect="themes" title="图片" name="picture">
<el-row class="img-area" :class="`img-area_${themes}`">
<el-col style="width: 130px !important">
<el-upload
:themes="themes"
action=""
accept=".jpeg,.jpg,.png,.gif,.svg"
class="avatar-uploader"
list-type="picture-card"
:class="{ disabled: uploadDisabled }"
:on-preview="handlePictureCardPreview"
:on-remove="handleRemove"
:before-upload="beforeUploadCheck"
:http-request="upload"
:file-list="fileList"
>
<el-icon><Plus /></el-icon>
</el-upload>
<img-view-dialog v-model="dialogVisible" :image-url="dialogImageUrl"></img-view-dialog>
</el-col>
</el-row>
<el-row style="margin-bottom: 16px">
<span
style="margin-top: 2px"
v-if="!curComponent.propValue.url"
class="image-hint"
:class="`image-hint_${themes}`"
>
支持JPGPNGGIF
</span>
<el-button
size="small"
style="margin: 8px 0 0 -4px"
v-if="curComponent.propValue.url"
text
@click="goFile"
>
重新上传
</el-button>
</el-row>
</el-collapse-item>
</CommonAttr>
</div>
</template>
<style lang="less" scoped>
.de-collapse-style {
:deep(.ed-collapse-item__header) {
height: 36px !important;
line-height: 36px !important;
font-size: 12px !important;
padding: 0 !important;
font-weight: 500 !important;
.ed-collapse-item__arrow {
margin: 0 6px 0 8px;
}
}
:deep(.ed-collapse-item__content) {
padding: 16px 8px 0;
}
:deep(.ed-form-item) {
display: block;
margin-bottom: 8px;
}
:deep(.ed-form-item__label) {
justify-content: flex-start;
}
}
.disabled :deep(.el-upload--picture-card) {
display: none;
}
.avatar-uploader :deep(.ed-upload) {
width: 80px;
height: 80px;
line-height: 90px;
}
.avatar-uploader :deep(.ed-upload-list li) {
width: 80px !important;
height: 80px !important;
}
:deep(.ed-upload--picture-card) {
background: #eff0f1;
border: 1px dashed #dee0e3;
border-radius: 4px;
.ed-icon {
color: #1f2329;
}
&:hover {
.ed-icon {
color: #3370ff;
}
}
}
.img-area {
height: 80px;
width: 80px;
margin-top: 10px;
overflow: hidden;
&.img-area_dark {
:deep(.ed-upload-list__item).is-success {
border-color: #434343;
}
:deep(.ed-upload--picture-card) {
background: #373737;
border-color: #434343;
.ed-icon {
color: #ebebeb;
}
&:hover {
.ed-icon {
color: #3370ff;
}
}
}
}
&.img-area_light {
:deep(.ed-upload-list__item).is-success {
border-color: #dee0e3;
}
}
}
.image-hint {
color: #8f959e;
size: 14px;
line-height: 22px;
font-weight: 400;
margin-top: 2px;
&.image-hint_dark {
color: #757575;
}
}
.re-update-span {
cursor: pointer;
color: #3370ff;
size: 14px;
line-height: 22px;
font-weight: 400;
}
</style>

View File

@ -0,0 +1,38 @@
<template>
<div class="rect-main">
<svg width="100%" height="100%" xmlns="http://www.w3.org/2000/svg">
<rect
width="100%"
height="100%"
fill="transparent"
:stroke="style.color"
:stroke-width="style.fontSize"
/>
</svg>
</div>
</template>
<script setup lang="ts">
import { computed, toRefs } from 'vue'
const props = defineProps({
element: {
type: Object,
default() {
return {
style: {}
}
}
}
})
const { element } = toRefs(props)
const style = computed(() => element.value.style)
</script>
<style lang="less" scoped>
.rect-main {
width: 100%;
height: 100%;
}
</style>

View File

@ -13,6 +13,8 @@ import CanvasIcon from '@/custom-component/canvas-icon/Component.vue'
import CanvasIconAttr from '@/custom-component/canvas-icon/Attr.vue'
import DeTabs from '@/custom-component/de-tabs/Component.vue'
import DeTabsAttr from '@/custom-component/de-tabs/Attr.vue'
import DeGraphical from '@/custom-component/de-graphical/Component.vue'
import DeGraphicalAttr from '@/custom-component/de-graphical/Attr.vue'
export const componentsMap = {
VText: VText,
@ -29,7 +31,9 @@ export const componentsMap = {
CanvasIcon: CanvasIcon,
CanvasIconAttr: CanvasIconAttr,
DeTabs: DeTabs,
DeTabsAttr: DeTabsAttr
DeTabsAttr: DeTabsAttr,
DeGraphical: DeGraphical,
DeGraphicalAttr: DeGraphicalAttr
}
export default function findComponent(key) {