forked from github/dataease
feat(仪表板): pc-移动端预览视图展示-交互设计
This commit is contained in:
parent
24bf19791a
commit
972bb8beb2
BIN
core/core-frontend/src/assets/img/mobile-bg-pc.png
Normal file
BIN
core/core-frontend/src/assets/img/mobile-bg-pc.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 35 KiB |
4
core/core-frontend/src/assets/svg/mobile-checkbox.svg
Normal file
4
core/core-frontend/src/assets/svg/mobile-checkbox.svg
Normal file
@ -0,0 +1,4 @@
|
||||
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M0 2C0 0.895431 0.895431 0 2 0H14C15.1046 0 16 0.895431 16 2V14C16 15.1046 15.1046 16 14 16H2C0.895431 16 0 15.1046 0 14V2Z" fill="#3370FF"/>
|
||||
<path d="M11.5881 4.90381L12.3966 5.71231C12.4291 5.74481 12.4549 5.78339 12.4725 5.82586C12.4901 5.86833 12.4992 5.91384 12.4992 5.95981C12.4992 6.00577 12.4901 6.05129 12.4725 6.09375C12.4549 6.13622 12.4291 6.17481 12.3966 6.20731L7.17813 11.4258C7.14563 11.4583 7.10705 11.4841 7.06458 11.5017C7.02212 11.5193 6.9766 11.5283 6.93063 11.5283C6.88467 11.5283 6.83915 11.5193 6.79669 11.5017C6.75422 11.4841 6.71564 11.4583 6.68313 11.4258L3.70213 8.44481C3.66963 8.41231 3.64385 8.37372 3.62625 8.33126C3.60866 8.28879 3.59961 8.24327 3.59961 8.19731C3.59961 8.15134 3.60866 8.10583 3.62625 8.06336C3.64385 8.0209 3.66963 7.98231 3.70213 7.94981L4.51063 7.14181C4.54314 7.1093 4.58172 7.08352 4.62419 7.06593C4.66665 7.04834 4.71217 7.03928 4.75813 7.03928C4.8041 7.03928 4.84962 7.04834 4.89208 7.06593C4.93455 7.08352 4.97313 7.1093 5.00563 7.14181L6.93063 9.06631L11.0936 4.90331C11.1261 4.8708 11.1647 4.84502 11.2072 4.82743C11.2497 4.80984 11.2952 4.80078 11.3411 4.80078C11.3871 4.80078 11.4326 4.80984 11.4751 4.82743C11.5175 4.84502 11.5556 4.8713 11.5881 4.90381Z" fill="white"/>
|
||||
</svg>
|
After Width: | Height: | Size: 1.3 KiB |
@ -1,12 +1,9 @@
|
||||
<template>
|
||||
<div class="shape" ref="shapeInnerRef" :id="domId" @dblclick="handleDbClick">
|
||||
<div v-if="showCheck" class="del-from-mobile" @click="delFromMobile">
|
||||
<label class="el-checkbox el-checkbox--small is-checked"
|
||||
><span class="el-checkbox__input is-checked"
|
||||
><input class="el-checkbox__original" checked type="checkbox" /><span
|
||||
class="el-checkbox__inner"
|
||||
></span></span
|
||||
></label>
|
||||
<el-icon>
|
||||
<Icon name="mobile-checkbox"></Icon>
|
||||
</el-icon>
|
||||
</div>
|
||||
<div
|
||||
class="shape-outer"
|
||||
@ -926,9 +923,11 @@ onMounted(() => {
|
||||
|
||||
.del-from-mobile {
|
||||
position: absolute;
|
||||
right: 5px;
|
||||
top: 5px;
|
||||
right: 12px;
|
||||
top: 12px;
|
||||
z-index: 2;
|
||||
font-size: 16px;
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -203,12 +203,13 @@ export function getCanvasStyle(canvasStyleData) {
|
||||
}
|
||||
|
||||
if (dvMainStore.mobileInPc && mobileSetting?.customSetting) {
|
||||
const { backgroundType, color, alpha, imageUrl } = mobileSetting
|
||||
if (backgroundType === 'image' && typeof imageUrl === 'string') {
|
||||
style['background'] = `url(${imgUrlTrans(imageUrl)}) no-repeat`
|
||||
} else if (backgroundType === 'color') {
|
||||
const colorRGBA = hexColorToRGBA(color, alpha === undefined ? 100 : alpha)
|
||||
style['background'] = colorRGBA
|
||||
const { backgroundColorSelect, color, backgroundImageEnable, background } = mobileSetting
|
||||
if (backgroundColorSelect && backgroundImageEnable && typeof background === 'string') {
|
||||
style['background'] = `url(${imgUrlTrans(background)}) no-repeat ${color}`
|
||||
} else if (backgroundColorSelect) {
|
||||
style['background-color'] = color
|
||||
} else if (backgroundImageEnable) {
|
||||
style['background'] = `url(${imgUrlTrans(background)}) no-repeat`
|
||||
}
|
||||
}
|
||||
return style
|
||||
|
@ -1,39 +1,210 @@
|
||||
<script lang="ts" setup>
|
||||
import { dvMainStoreWithOut } from '@/store/modules/data-visualization/dvMain'
|
||||
import { ref, reactive, unref, onMounted, watch } from 'vue'
|
||||
import { COLOR_PANEL } from '@/views/chart/components/editor/util/chart'
|
||||
import { imgUrlTrans } from '@/utils/imgUtils'
|
||||
import ImgViewDialog from '@/custom-component/ImgViewDialog.vue'
|
||||
import { storeToRefs } from 'pinia'
|
||||
import { useEmitt } from '@/hooks/web/useEmitt'
|
||||
import { beforeUploadCheck, uploadFileResult } from '@/api/staticResource'
|
||||
import { snapshotStoreWithOut } from '@/store/modules/data-visualization/snapshot'
|
||||
import { cloneDeep } from 'lodash-es'
|
||||
const MOBILE_SETTING = {
|
||||
customSetting: false,
|
||||
color: '#ffffff',
|
||||
alpha: 100,
|
||||
imageUrl: null,
|
||||
backgroundType: 'image'
|
||||
}
|
||||
const fileList = ref([])
|
||||
<template>
|
||||
<div class="mobile-background-selector">
|
||||
<input
|
||||
id="input"
|
||||
ref="files"
|
||||
type="file"
|
||||
accept=".jpeg,.jpg,.png,.gif"
|
||||
hidden
|
||||
@click="
|
||||
e => {
|
||||
e.target.value = ''
|
||||
}
|
||||
"
|
||||
@change="reUpload"
|
||||
/>
|
||||
<el-checkbox
|
||||
size="small"
|
||||
:effect="themes"
|
||||
v-model="canvasStyleData.mobileSetting.customSetting"
|
||||
@change="onBackgroundChange"
|
||||
>
|
||||
{{ $t('visualization.mobile_style_setting_tips') }}
|
||||
</el-checkbox>
|
||||
<el-form label-position="top" style="width: 100%; padding-left: 22px; margin-bottom: 16px">
|
||||
<el-form-item class="form-item no-margin-bottom" :class="'form-item-' + themes">
|
||||
<el-checkbox
|
||||
size="small"
|
||||
:effect="themes"
|
||||
:disabled="!canvasStyleData.mobileSetting.customSetting"
|
||||
v-model="canvasStyleData.mobileSetting.backgroundColorSelect"
|
||||
@change="onBackgroundChange"
|
||||
>
|
||||
{{ $t('chart.color') }}
|
||||
</el-checkbox>
|
||||
</el-form-item>
|
||||
|
||||
const mobileSetting = reactive({ ...MOBILE_SETTING })
|
||||
const dvMainStore = dvMainStoreWithOut()
|
||||
<div class="indented-container">
|
||||
<div class="indented-item">
|
||||
<el-form-item class="form-item" :class="'form-item-' + themes">
|
||||
<el-color-picker
|
||||
v-model="canvasStyleData.mobileSetting.color"
|
||||
:effect="themes"
|
||||
:disabled="!canvasStyleData.mobileSetting.backgroundColorSelect"
|
||||
:trigger-width="108"
|
||||
is-custom
|
||||
show-alpha
|
||||
class="color-picker-style"
|
||||
:predefine="COLOR_PANEL"
|
||||
@change="onBackgroundChange"
|
||||
/>
|
||||
</el-form-item>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<el-form-item class="form-item no-margin-bottom" :class="'form-item-' + themes">
|
||||
<el-checkbox
|
||||
size="small"
|
||||
:effect="themes"
|
||||
:disabled="!canvasStyleData.mobileSetting.customSetting"
|
||||
v-model="canvasStyleData.mobileSetting.backgroundImageEnable"
|
||||
@change="onBackgroundChange"
|
||||
>
|
||||
{{ t('visualization.background') }}
|
||||
</el-checkbox>
|
||||
</el-form-item>
|
||||
|
||||
<div class="indented-container">
|
||||
<div
|
||||
class="indented-item"
|
||||
:class="{
|
||||
disabled: !canvasStyleData.mobileSetting.backgroundImageEnable
|
||||
}"
|
||||
>
|
||||
<div class="avatar-uploader-container" :class="`img-area_${themes}`">
|
||||
<el-upload
|
||||
action=""
|
||||
:effect="themes"
|
||||
accept=".jpeg,.jpg,.png,.gif,.svg"
|
||||
class="avatar-uploader"
|
||||
list-type="picture-card"
|
||||
:on-preview="handlePictureCardPreview"
|
||||
:on-remove="handleRemove"
|
||||
:before-upload="beforeUploadCheck"
|
||||
:http-request="upload"
|
||||
:file-list="state.fileList"
|
||||
:disabled="!canvasStyleData.mobileSetting.backgroundImageEnable"
|
||||
>
|
||||
<el-icon><Plus /></el-icon>
|
||||
</el-upload>
|
||||
<el-row>
|
||||
<span
|
||||
style="margin-top: 2px"
|
||||
v-if="!canvasStyleData.mobileSetting.background"
|
||||
class="image-hint"
|
||||
:class="`image-hint_${themes}`"
|
||||
>
|
||||
支持JPG、PNG、GIF,大小不超过 1M
|
||||
</span>
|
||||
<el-button
|
||||
size="small"
|
||||
style="margin: 8px 0 0 -4px"
|
||||
v-if="canvasStyleData.mobileSetting.background"
|
||||
text
|
||||
@click="goFile"
|
||||
:disabled="!canvasStyleData.mobileSetting.backgroundImageEnable"
|
||||
>
|
||||
重新上传
|
||||
</el-button>
|
||||
</el-row>
|
||||
</div>
|
||||
|
||||
<img-view-dialog v-model="state.dialogVisible" :image-url="state.dialogImageUrl" />
|
||||
</div>
|
||||
</div>
|
||||
</el-form>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { COLOR_PANEL } from '@/views/chart/components/editor/util/chart'
|
||||
import { onMounted, reactive, ref, watch, unref } from 'vue'
|
||||
import { imgUrlTrans } from '@/utils/imgUtils'
|
||||
import { snapshotStoreWithOut } from '@/store/modules/data-visualization/snapshot'
|
||||
import { beforeUploadCheck, uploadFileResult } from '@/api/staticResource'
|
||||
import { useI18n } from '@/hooks/web/useI18n'
|
||||
import { ElButton, ElMessage } from 'element-plus-secondary'
|
||||
import ImgViewDialog from '@/custom-component/ImgViewDialog.vue'
|
||||
import { useEmitt } from '@/hooks/web/useEmitt'
|
||||
import { dvMainStoreWithOut } from '@/store/modules/data-visualization/dvMain'
|
||||
import { storeToRefs } from 'pinia'
|
||||
import { cloneDeep } from 'lodash-es'
|
||||
const snapshotStore = snapshotStoreWithOut()
|
||||
const { t } = useI18n()
|
||||
const files = ref(null)
|
||||
const maxImageSize = 15000000
|
||||
|
||||
const dvMainStore = dvMainStoreWithOut()
|
||||
const { canvasStyleData } = storeToRefs(dvMainStore)
|
||||
|
||||
const init = () => {
|
||||
const { imageUrl } = canvasStyleData.value.mobileSetting || {}
|
||||
fileList.value = imageUrl ? [{ url: imgUrlTrans(imageUrl) }] : []
|
||||
}
|
||||
onMounted(() => {
|
||||
init()
|
||||
const emits = defineEmits(['styleChange'])
|
||||
withDefaults(
|
||||
defineProps<{
|
||||
themes?: EditorTheme
|
||||
}>(),
|
||||
{
|
||||
themes: 'light'
|
||||
}
|
||||
)
|
||||
|
||||
const state = reactive({
|
||||
fileList: [],
|
||||
dialogImageUrl: '',
|
||||
dialogVisible: false,
|
||||
uploadDisabled: false
|
||||
})
|
||||
|
||||
const goFile = () => {
|
||||
files.value.click()
|
||||
}
|
||||
|
||||
const sizeMessage = () => {
|
||||
ElMessage.success('图片大小不符合')
|
||||
}
|
||||
|
||||
const reUpload = e => {
|
||||
const file = e.target.files[0]
|
||||
if (file.size > maxImageSize) {
|
||||
sizeMessage()
|
||||
}
|
||||
uploadFileResult(file, fileUrl => {
|
||||
canvasStyleData.value.mobileSetting.background = fileUrl
|
||||
state.fileList = [{ url: imgUrlTrans(canvasStyleData.value.mobileSetting.background) }]
|
||||
onBackgroundChange()
|
||||
})
|
||||
}
|
||||
|
||||
const init = () => {
|
||||
if (canvasStyleData.value.mobileSetting.background) {
|
||||
state.fileList.push({ url: imgUrlTrans(canvasStyleData.value.mobileSetting.background) })
|
||||
} else {
|
||||
state.fileList = []
|
||||
}
|
||||
}
|
||||
|
||||
const handleRemove = () => {
|
||||
state.uploadDisabled = false
|
||||
canvasStyleData.value.mobileSetting.background = null
|
||||
state.fileList = []
|
||||
onBackgroundChange()
|
||||
}
|
||||
const handlePictureCardPreview = file => {
|
||||
state.dialogImageUrl = file.url
|
||||
state.dialogVisible = true
|
||||
}
|
||||
const upload = file => {
|
||||
uploadFileResult(file.file, fileUrl => {
|
||||
canvasStyleData.value.mobileSetting.background = fileUrl
|
||||
onBackgroundChange()
|
||||
})
|
||||
}
|
||||
|
||||
const onBackgroundChange = () => {
|
||||
commitStyle()
|
||||
}
|
||||
const commitStyle = () => {
|
||||
emits('styleChange')
|
||||
const canvasStyleDataCopy = cloneDeep(canvasStyleData.value)
|
||||
canvasStyleDataCopy.mobileSetting = unref(mobileSetting)
|
||||
dvMainStore.setCanvasStyle(canvasStyleDataCopy)
|
||||
useEmitt().emitter.emit('onMobileStatusChange', {
|
||||
type: 'setCanvasStyle',
|
||||
@ -42,100 +213,61 @@ const commitStyle = () => {
|
||||
snapshotStore.recordSnapshotCache()
|
||||
}
|
||||
|
||||
const upload = file => {
|
||||
return uploadFileResult(file.file, fileUrl => {
|
||||
mobileSetting.imageUrl = fileUrl
|
||||
commitStyle()
|
||||
})
|
||||
}
|
||||
onMounted(() => {
|
||||
init()
|
||||
})
|
||||
|
||||
const dialogVisible = ref(false)
|
||||
const dialogImageUrl = ref('')
|
||||
const handlePictureCardPreview = file => {
|
||||
dialogImageUrl.value = file.url
|
||||
dialogVisible.value = true
|
||||
}
|
||||
|
||||
const handleRemove = () => {
|
||||
mobileSetting.imageUrl = null
|
||||
dialogImageUrl.value = ''
|
||||
fileList.value = []
|
||||
commitStyle()
|
||||
}
|
||||
watch(
|
||||
() => canvasStyleData.value.mobileSetting.background,
|
||||
() => {
|
||||
init()
|
||||
}
|
||||
)
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="mobile-bg-setting">
|
||||
<div class="is-custom">
|
||||
<el-checkbox v-model="mobileSetting.customSetting" label="自定义移动端背景" />
|
||||
</div>
|
||||
<div class="bg-type">
|
||||
<el-radio-group
|
||||
v-model="mobileSetting.backgroundType"
|
||||
:disabled="!mobileSetting.customSetting"
|
||||
@change="commitStyle"
|
||||
>
|
||||
<el-radio label="color">{{ $t('chart.color') }}</el-radio>
|
||||
<el-radio label="image">图片</el-radio>
|
||||
</el-radio-group>
|
||||
</div>
|
||||
<div v-show="mobileSetting.backgroundType === 'color'" class="bg-color-config">
|
||||
<el-color-picker
|
||||
v-model="mobileSetting.color"
|
||||
:predefine="COLOR_PANEL"
|
||||
:disabled="!mobileSetting.customSetting"
|
||||
@change="commitStyle"
|
||||
/>
|
||||
<span> 不透明度 </span>
|
||||
<el-slider
|
||||
v-model="mobileSetting.alpha"
|
||||
show-input
|
||||
:show-input-controls="false"
|
||||
@change="commitStyle"
|
||||
/>
|
||||
</div>
|
||||
<div
|
||||
:class="{
|
||||
disabled: !mobileSetting.customSetting
|
||||
}"
|
||||
v-show="mobileSetting.backgroundType === 'image'"
|
||||
class="upload-img"
|
||||
>
|
||||
<el-upload
|
||||
action=""
|
||||
accept=".jpeg,.jpg,.png,.gif,.svg"
|
||||
class="avatar-uploader"
|
||||
list-type="picture-card"
|
||||
:http-request="upload"
|
||||
:on-preview="handlePictureCardPreview"
|
||||
:on-remove="handleRemove"
|
||||
:before-upload="beforeUploadCheck"
|
||||
:file-list="fileList"
|
||||
:disabled="!mobileSetting.customSetting"
|
||||
>
|
||||
<el-icon><Plus /></el-icon>
|
||||
</el-upload>
|
||||
<img-view-dialog v-model="dialogVisible" :image-url="dialogImageUrl" />
|
||||
</div>
|
||||
<div v-show="mobileSetting.backgroundType === 'image'" class="image-hint">
|
||||
当前支持jpeg,jpg,png,gif,svg文件,大小15M内
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style lang="less" scoped>
|
||||
.mobile-bg-setting {
|
||||
width: 50%;
|
||||
.bg-color-config {
|
||||
margin-top: 10px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
& > :nth-child(2) {
|
||||
margin: 0 20px;
|
||||
white-space: nowrap;
|
||||
}
|
||||
<style scoped lang="less">
|
||||
.mobile-background-selector {
|
||||
:deep(.ed-form-item) {
|
||||
display: block;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
.avatar-uploader-container {
|
||||
: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_dark {
|
||||
:deep(.ed-upload-list__item).is-ready {
|
||||
border-color: #434343;
|
||||
}
|
||||
:deep(.ed-upload--picture-card) {
|
||||
background: #373737;
|
||||
border-color: #434343;
|
||||
.ed-icon {
|
||||
color: #ebebeb;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&.img-area_light {
|
||||
:deep(.ed-upload-list__item).is-ready {
|
||||
border-color: #dee0e3;
|
||||
}
|
||||
}
|
||||
}
|
||||
.avatar-uploader {
|
||||
width: 90px;
|
||||
height: 80px;
|
||||
@ -171,38 +303,109 @@ const handleRemove = () => {
|
||||
}
|
||||
}
|
||||
|
||||
.upload-img {
|
||||
.shape-item {
|
||||
padding: 6px;
|
||||
border: none;
|
||||
width: 100%;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.ed-select-dropdown__item {
|
||||
height: 100px !important;
|
||||
text-align: center;
|
||||
padding: 0px 5px;
|
||||
}
|
||||
|
||||
.ed-select-dropdown__item.selected::after {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.indented-container {
|
||||
width: 100%;
|
||||
padding-left: 22px;
|
||||
margin-top: 8px;
|
||||
&.disabled {
|
||||
cursor: not-allowed;
|
||||
color: #8f959e;
|
||||
|
||||
:deep(.avatar-uploader) {
|
||||
width: 90px;
|
||||
pointer-events: none;
|
||||
.indented-item {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
|
||||
.fill {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
:deep(.ed-upload--picture-card) {
|
||||
&.disabled {
|
||||
cursor: not-allowed;
|
||||
.ed-icon {
|
||||
color: #bbbfc4;
|
||||
}
|
||||
}
|
||||
color: #8f959e;
|
||||
|
||||
&:hover {
|
||||
.ed-icon {
|
||||
color: #8f959e;
|
||||
:deep(.avatar-uploader) {
|
||||
width: 90px;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
:deep(.ed-upload--picture-card) {
|
||||
cursor: not-allowed;
|
||||
}
|
||||
|
||||
.img-area_dark {
|
||||
:deep(.ed-upload--picture-card) {
|
||||
.ed-icon {
|
||||
color: #5f5f5f;
|
||||
}
|
||||
}
|
||||
}
|
||||
.img-area_light {
|
||||
:deep(.ed-upload--picture-card) {
|
||||
.ed-icon {
|
||||
color: #bbbfc4;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&:hover {
|
||||
.ed-icon {
|
||||
color: #8f959e;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.form-item {
|
||||
&.margin-bottom-8 {
|
||||
margin-bottom: 8px !important;
|
||||
}
|
||||
&.no-margin-bottom {
|
||||
margin-bottom: 0 !important;
|
||||
}
|
||||
}
|
||||
|
||||
.image-hint {
|
||||
color: #8f959e;
|
||||
font-size: 14px;
|
||||
size: 14px;
|
||||
line-height: 22px;
|
||||
font-weight: 400;
|
||||
margin-top: 8px;
|
||||
margin-top: -6px;
|
||||
&.image-hint_dark {
|
||||
color: #757575;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
<style lang="less">
|
||||
.board-select {
|
||||
min-width: 50px !important;
|
||||
width: 304px;
|
||||
.ed-scrollbar__view {
|
||||
display: grid !important;
|
||||
grid-template-columns: repeat(3, 1fr) !important;
|
||||
}
|
||||
.ed-select-dropdown__item.hover {
|
||||
background-color: rgba(0, 0, 0, 0) !important;
|
||||
}
|
||||
.ed-select-dropdown__item.selected {
|
||||
background-color: rgba(0, 0, 0, 0) !important;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
@ -2,6 +2,7 @@
|
||||
import { ref, onMounted, unref, onBeforeUnmount, computed } from 'vue'
|
||||
import eventBus from '@/utils/eventBus'
|
||||
import MobileBackgroundSelector from './MobileBackgroundSelector.vue'
|
||||
import { ElMessageBox } from 'element-plus-secondary'
|
||||
import { useEmitt } from '@/hooks/web/useEmitt'
|
||||
import { dvMainStoreWithOut } from '@/store/modules/data-visualization/dvMain'
|
||||
import { getStyle } from '@/utils/style'
|
||||
@ -10,8 +11,6 @@ import { storeToRefs } from 'pinia'
|
||||
const dvMainStore = dvMainStoreWithOut()
|
||||
const { componentData, canvasStyleData, canvasViewInfo, dvInfo } = storeToRefs(dvMainStore)
|
||||
const mobileLoading = ref(true)
|
||||
const activeName = ref('hide')
|
||||
|
||||
const emits = defineEmits(['pcMode'])
|
||||
|
||||
const getComponentStyleDefault = style => {
|
||||
@ -57,6 +56,7 @@ const hanedleMessage = event => {
|
||||
}
|
||||
|
||||
if (event.data.type === 'delFromMobile') {
|
||||
changeTimes.value++
|
||||
componentData.value.some(ele => {
|
||||
if (ele.id === event.data.value) {
|
||||
ele.inMobile = false
|
||||
@ -99,65 +99,103 @@ onBeforeUnmount(() => {
|
||||
|
||||
const addToMobile = com => {
|
||||
com.inMobile = true
|
||||
changeTimes.value++
|
||||
mobileStatusChange('addToMobile', JSON.parse(JSON.stringify(unref(com))))
|
||||
}
|
||||
|
||||
const changeTimes = ref(0)
|
||||
|
||||
const handleBack = () => {
|
||||
if (!changeTimes.value) {
|
||||
emits('pcMode')
|
||||
return
|
||||
}
|
||||
ElMessageBox.confirm('当前的更改尚未保存,确定退出吗?', {
|
||||
confirmButtonType: 'primary',
|
||||
type: 'warning',
|
||||
autofocus: false,
|
||||
showClose: false
|
||||
}).then(() => {
|
||||
emits('pcMode')
|
||||
})
|
||||
}
|
||||
|
||||
const save = () => {
|
||||
changeTimes.value = 0
|
||||
mobileStatusChange('mobileSave', undefined)
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="mobile-config-panel">
|
||||
<div class="mobile-to-pc">
|
||||
<el-icon class="custom-el-icon back-icon" @click="emits('pcMode')">
|
||||
<Icon class="toolbar-icon" name="icon_left_outlined" />
|
||||
</el-icon>
|
||||
</div>
|
||||
<div class="mobile-save">
|
||||
<el-button type="primary" @click="mobileStatusChange('mobileSave', undefined)"
|
||||
>保存</el-button
|
||||
>
|
||||
<div class="top-bar">
|
||||
<div class="mobile-to-pc">
|
||||
<el-icon @click="handleBack">
|
||||
<Icon name="icon_left_outlined" />
|
||||
</el-icon>
|
||||
{{ dvInfo.name }}
|
||||
</div>
|
||||
<div class="mobile-save">
|
||||
<el-icon @click="handleBack">
|
||||
<Icon name="icon_pc_outlined" />
|
||||
</el-icon>
|
||||
<el-button type="primary" @click="save">保存</el-button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="mobile-canvas">
|
||||
<div class="config-panel-title">{{ dvInfo.name }}</div>
|
||||
<div class="config-panel-title">
|
||||
<el-icon>
|
||||
<Icon name="icon_left_outlined" />
|
||||
</el-icon>
|
||||
{{ dvInfo.name }}
|
||||
</div>
|
||||
<div class="config-panel-content" v-loading="mobileLoading">
|
||||
<iframe src="./mobile.html#/panel" frameborder="0" width="360" height="570" />
|
||||
<iframe src="./mobile.html#/panel" frameborder="0" width="375" height="640" />
|
||||
</div>
|
||||
<div class="config-panel-foot"></div>
|
||||
</div>
|
||||
<div class="mobile-com-list">
|
||||
<el-tabs v-model="activeName">
|
||||
<el-tab-pane label="隐藏的组件" name="hide" />
|
||||
<el-tab-pane label="样式设置" name="style" />
|
||||
</el-tabs>
|
||||
<template v-if="activeName === 'hide'">
|
||||
<div
|
||||
:style="{ height: '200px', width: 'calc(33.3% - 16px)' }"
|
||||
class="mobile-wrapper-inner-adaptor"
|
||||
v-for="config in componentDataNotInMobile"
|
||||
:key="config.id"
|
||||
>
|
||||
<component
|
||||
:is="findComponent(config['component'])"
|
||||
ref="component"
|
||||
class="component"
|
||||
:view="canvasViewInfo[config.id]"
|
||||
:canvas-style-data="canvasStyleData"
|
||||
:dv-info="dvInfo"
|
||||
:dv-type="dvInfo.type"
|
||||
:canvas-view-info="canvasViewInfo"
|
||||
:prop-value="config?.propValue"
|
||||
:element="config"
|
||||
:request="config?.request"
|
||||
:style="getComponentStyleDefault(config?.style)"
|
||||
:linkage="config?.linkage"
|
||||
show-position="preview"
|
||||
:disabled="true"
|
||||
:is-edit="false"
|
||||
/>
|
||||
<div class="mobile-com-mask"></div>
|
||||
|
||||
<div class="pc-select-to-mobile" v-if="!mobileLoading" @click="addToMobile(config)"></div>
|
||||
</div>
|
||||
</template>
|
||||
<MobileBackgroundSelector v-else></MobileBackgroundSelector>
|
||||
<div class="config-mobile-sidebar">移动端配置</div>
|
||||
<el-collapse>
|
||||
<el-collapse-item title="样式设置" name="style" class="content-no-padding-bottom">
|
||||
<MobileBackgroundSelector @styleChange="changeTimes++"></MobileBackgroundSelector>
|
||||
</el-collapse-item>
|
||||
<el-collapse-item title="可视化组件" name="com" class="content-no-padding-bottom">
|
||||
<div
|
||||
:style="{ height: '198px', width: '198px' }"
|
||||
class="mobile-wrapper-inner-adaptor"
|
||||
v-for="config in componentDataNotInMobile"
|
||||
:key="config.id"
|
||||
>
|
||||
<div class="component-outer">
|
||||
<component
|
||||
:is="findComponent(config['component'])"
|
||||
ref="component"
|
||||
class="component"
|
||||
:view="canvasViewInfo[config.id]"
|
||||
:canvas-style-data="canvasStyleData"
|
||||
:dv-info="dvInfo"
|
||||
:dv-type="dvInfo.type"
|
||||
:canvas-view-info="canvasViewInfo"
|
||||
:prop-value="config?.propValue"
|
||||
:element="config"
|
||||
:request="config?.request"
|
||||
:style="getComponentStyleDefault(config?.style)"
|
||||
:linkage="config?.linkage"
|
||||
show-position="preview"
|
||||
:disabled="true"
|
||||
:is-edit="false"
|
||||
/>
|
||||
</div>
|
||||
<div class="mobile-com-mask"></div>
|
||||
<div
|
||||
class="pc-select-to-mobile"
|
||||
v-if="!mobileLoading"
|
||||
@click="addToMobile(config)"
|
||||
></div>
|
||||
</div>
|
||||
</el-collapse-item>
|
||||
</el-collapse>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
@ -167,70 +205,123 @@ const addToMobile = com => {
|
||||
height: 100vh;
|
||||
width: 100vw;
|
||||
position: relative;
|
||||
background: #f5f6f7;
|
||||
overflow-y: auto;
|
||||
|
||||
.mobile-to-pc {
|
||||
position: absolute;
|
||||
left: 20px;
|
||||
top: 20px;
|
||||
cursor: pointer;
|
||||
.top-bar {
|
||||
position: sticky;
|
||||
top: 0;
|
||||
left: 0;
|
||||
z-index: 10;
|
||||
background: #050e21;
|
||||
box-shadow: 0px 2px 4px 0px #1f23291f;
|
||||
height: 64px;
|
||||
padding: 0 24px 0 20px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
|
||||
.mobile-save {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
.ed-icon {
|
||||
font-size: 20px;
|
||||
cursor: pointer;
|
||||
margin-right: 20px;
|
||||
color: #ffffff99;
|
||||
}
|
||||
}
|
||||
|
||||
.mobile-to-pc {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
font-size: 16px;
|
||||
font-weight: 400;
|
||||
line-height: 24px;
|
||||
color: #ffffffe5;
|
||||
.ed-icon {
|
||||
font-size: 20px;
|
||||
cursor: pointer;
|
||||
margin-right: 12px;
|
||||
color: #ffffffcc;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.mobile-save {
|
||||
position: absolute;
|
||||
right: 20px;
|
||||
top: 20px;
|
||||
}
|
||||
.mobile-canvas {
|
||||
border-radius: 30px;
|
||||
width: 370px;
|
||||
min-height: 600px;
|
||||
max-height: 700px;
|
||||
width: 419px;
|
||||
height: 854px;
|
||||
overflow: hidden;
|
||||
background-color: #000;
|
||||
background-size: 100% 100% !important;
|
||||
padding: 5px;
|
||||
height: 777px;
|
||||
position: absolute;
|
||||
top: 100px;
|
||||
left: 100px;
|
||||
top: 104px;
|
||||
left: calc(50% - 419px);
|
||||
background-image: url(../../assets/img/mobile-bg-pc.png);
|
||||
padding: 0 22px;
|
||||
|
||||
.config-panel-title {
|
||||
margin-top: 30px;
|
||||
margin-top: 64px;
|
||||
height: 44px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
background: #fff;
|
||||
text-align: center;
|
||||
position: relative;
|
||||
|
||||
.ed-icon {
|
||||
font-size: 20px;
|
||||
position: absolute;
|
||||
left: 16px;
|
||||
top: 12px;
|
||||
}
|
||||
}
|
||||
|
||||
.config-panel-content {
|
||||
width: 100%;
|
||||
border-bottom-left-radius: 45px;
|
||||
border-bottom-right-radius: 45px;
|
||||
overflow: hidden;
|
||||
}
|
||||
}
|
||||
|
||||
.mobile-com-list {
|
||||
position: absolute;
|
||||
top: 100px;
|
||||
left: 500px;
|
||||
width: calc(100% - 600px);
|
||||
max-height: 700px;
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
background: #f5f6f7;
|
||||
padding: 16px;
|
||||
padding-top: 0;
|
||||
overflow-y: auto;
|
||||
float: right;
|
||||
width: 420px;
|
||||
height: 100%;
|
||||
background-color: #fff;
|
||||
position: relative;
|
||||
border-left: rgba(31, 35, 41, 0.15) 1px solid;
|
||||
height: 100%;
|
||||
|
||||
:deep(.ed-tabs) {
|
||||
width: 100%;
|
||||
margin-bottom: 16px;
|
||||
position: sticky;
|
||||
top: 0;
|
||||
left: 0;
|
||||
z-index: 20;
|
||||
background: #f5f6f7;
|
||||
.config-mobile-sidebar {
|
||||
font-size: 14px;
|
||||
font-weight: 500;
|
||||
line-height: 22px;
|
||||
padding: 8px;
|
||||
}
|
||||
|
||||
.mobile-wrapper-inner-adaptor {
|
||||
position: relative;
|
||||
margin-right: 24px;
|
||||
margin-bottom: 24px;
|
||||
margin-right: 8px;
|
||||
margin-bottom: 8px;
|
||||
float: left;
|
||||
background: #fff;
|
||||
&:nth-child(3n - 2) {
|
||||
margin-right: 0px;
|
||||
padding: 31px 4px 36px 4px;
|
||||
border-radius: 4px;
|
||||
border: 1px solid #dee0e3;
|
||||
&:nth-child(2n) {
|
||||
margin-right: -1px;
|
||||
}
|
||||
|
||||
.component-outer {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
border-color: var(--ed-color-primary);
|
||||
}
|
||||
}
|
||||
|
||||
@ -247,11 +338,11 @@ const addToMobile = com => {
|
||||
position: absolute;
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
top: 0;
|
||||
right: 0;
|
||||
border: 2px solid #ccc;
|
||||
top: 12px;
|
||||
right: 12px;
|
||||
border: 2px solid #8f959e;
|
||||
border-radius: 4px;
|
||||
z-index: 11;
|
||||
z-index: 20;
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
|
@ -17,6 +17,7 @@ import ChartStyleBatchSet from '@/views/chart/components/editor/editor-style/Cha
|
||||
import DeCanvas from '@/views/canvas/DeCanvas.vue'
|
||||
import { check, compareStorage } from '@/utils/CrossPermission'
|
||||
import { useCache } from '@/hooks/web/useCache'
|
||||
import { cloneDeep } from 'lodash-es'
|
||||
import { useEmbedded } from '@/store/modules/embedded'
|
||||
import { snapshotStoreWithOut } from '@/store/modules/data-visualization/snapshot'
|
||||
import { interactiveStoreWithOut } from '@/store/modules/interactive'
|
||||
@ -77,7 +78,20 @@ const checkPer = async resourceId => {
|
||||
const mobileConfig = ref(false)
|
||||
|
||||
const onMobileConfig = () => {
|
||||
mobileConfig.value = true
|
||||
const canvasStyleDataCopy = cloneDeep(canvasStyleData.value)
|
||||
if (!canvasStyleDataCopy.mobileSetting) {
|
||||
canvasStyleDataCopy.mobileSetting = {
|
||||
backgroundColorSelect: false,
|
||||
background: '',
|
||||
color: '#ffffff',
|
||||
backgroundImageEnable: false,
|
||||
customSetting: false
|
||||
}
|
||||
}
|
||||
dvMainStore.setCanvasStyle(canvasStyleDataCopy)
|
||||
nextTick(() => {
|
||||
mobileConfig.value = true
|
||||
})
|
||||
}
|
||||
// 全局监听按键事件
|
||||
onMounted(async () => {
|
||||
@ -96,6 +110,7 @@ onMounted(async () => {
|
||||
return
|
||||
}
|
||||
initDataset()
|
||||
|
||||
state.sourcePid = pid
|
||||
if (resourceId) {
|
||||
dataInitState.value = false
|
||||
|
Loading…
Reference in New Issue
Block a user