feat(移动端): 背景设置

This commit is contained in:
dataeaseShu 2024-02-19 16:14:26 +08:00
parent 821d30faf1
commit fa09825b5d
7 changed files with 261 additions and 34 deletions

View File

@ -32,7 +32,7 @@ export function uploadFileResult(file, callback) {
const fileUrl = staticResourcePath + newFileName
const param = new FormData()
param.append('file', file)
uploadFile(fileId, param).then(() => {
return uploadFile(fileId, param).then(() => {
callback(fileUrl)
})
}

View File

@ -182,8 +182,14 @@ export function getComponentRotatedStyle(style) {
}
export function getCanvasStyle(canvasStyleData) {
const { backgroundColorSelect, background, backgroundColor, backgroundImageEnable, fontSize } =
canvasStyleData
const {
backgroundColorSelect,
background,
backgroundColor,
backgroundImageEnable,
fontSize,
mobileSetting
} = canvasStyleData
const style = { fontSize: fontSize + 'px', color: canvasStyleData.color }
// 仪表板默认色#f5f6f7 大屏默认配色 #1a1a1a
let colorRGBA = dvMainStore.dvInfo.type === 'dashboard' ? '#f5f6f7' : '#1a1a1a'
@ -195,6 +201,17 @@ export function getCanvasStyle(canvasStyleData) {
} else {
style['background-color'] = colorRGBA
}
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
}
}
console.log('style', style)
return style
}

View File

@ -0,0 +1,208 @@
<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([])
const mobileSetting = reactive({ ...MOBILE_SETTING })
const dvMainStore = dvMainStoreWithOut()
const snapshotStore = snapshotStoreWithOut()
const { canvasStyleData } = storeToRefs(dvMainStore)
const init = () => {
const { imageUrl } = canvasStyleData.value.mobileSetting || {}
fileList.value = imageUrl ? [{ url: imgUrlTrans(imageUrl) }] : []
}
onMounted(() => {
init()
})
const commitStyle = () => {
const canvasStyleDataCopy = cloneDeep(canvasStyleData.value)
canvasStyleDataCopy.mobileSetting = unref(mobileSetting)
dvMainStore.setCanvasStyle(canvasStyleDataCopy)
useEmitt().emitter.emit('onMobileStatusChange', {
type: 'setCanvasStyle',
value: JSON.parse(JSON.stringify(unref(canvasStyleDataCopy)))
})
snapshotStore.recordSnapshotCache()
}
const upload = file => {
return uploadFileResult(file.file, fileUrl => {
mobileSetting.imageUrl = fileUrl
commitStyle()
})
}
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()
}
</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;
}
}
.avatar-uploader {
width: 90px;
height: 80px;
overflow: hidden;
}
.avatar-uploader {
width: 90px;
:deep(.ed-upload) {
width: 80px;
height: 80px;
line-height: 90px;
}
: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;
}
}
}
}
.upload-img {
margin-top: 8px;
&.disabled {
cursor: not-allowed;
color: #8f959e;
:deep(.avatar-uploader) {
width: 90px;
pointer-events: none;
}
:deep(.ed-upload--picture-card) {
cursor: not-allowed;
.ed-icon {
color: #bbbfc4;
}
}
&:hover {
.ed-icon {
color: #8f959e;
}
}
}
}
.image-hint {
color: #8f959e;
font-size: 14px;
line-height: 22px;
font-weight: 400;
margin-top: 8px;
}
}
</style>

View File

@ -1,6 +1,7 @@
<script lang="ts" setup>
import { ref, onMounted, unref, onBeforeUnmount, computed } from 'vue'
import eventBus from '@/utils/eventBus'
import MobileBackgroundSelector from './MobileBackgroundSelector.vue'
import { useEmitt } from '@/hooks/web/useEmitt'
import { dvMainStoreWithOut } from '@/store/modules/data-visualization/dvMain'
import { getStyle } from '@/utils/style'
@ -85,7 +86,7 @@ onMounted(() => {
dvMainStore.setMobileInPc(true)
useEmitt({
name: 'onMobileStatusChange',
callback: (type, value) => {
callback: ({ type, value }) => {
mobileStatusChange(type, value)
}
})
@ -156,6 +157,7 @@ const addToMobile = com => {
<div class="pc-select-to-mobile" v-if="!mobileLoading" @click="addToMobile(config)"></div>
</div>
</template>
<MobileBackgroundSelector v-else></MobileBackgroundSelector>
</div>
</div>
</template>

View File

@ -4,6 +4,7 @@ import { storeToRefs } from 'pinia'
import { dvMainStoreWithOut } from '@/store/modules/data-visualization/dvMain'
import { BusiTreeRequest } from '@/models/tree/TreeNode'
import { interactiveStoreWithOut } from '@/store/modules/interactive'
import { useRouter } from 'vue-router'
import VanCell from 'vant/es/cell'
import VanSticky from 'vant/es/sticky'
import VanSearch from 'vant/es/search'
@ -43,22 +44,33 @@ const activeTableData = computed(() => {
return directId.value.length ? dfsTree([...directId.value], tableData.value) : tableData.value
})
const emits = defineEmits(['hiddentabbar', 'setLoading'])
const emits = defineEmits(['hiddenTabbar', 'setLoading'])
const onClickLeft = () => {
directName.value.pop()
activeDirectName.value = directName.value[directName.value.length - 1]
directId.value.pop()
if (!!directName.value.length) {
emits('hiddentabbar', false)
emits('hiddenTabbar', false)
}
}
const router = useRouter()
const handleCellClick = ele => {
router.push({
path: '/panel/mobile',
query: {
dvId: ele.id
}
})
}
const dataClick = val => {
directName.value.push(val.name)
activeDirectName.value = val.name
directId.value.push(val.id)
if (directName.value.length === 1) {
emits('hiddentabbar', true)
if (val.leaf) {
emits('hiddenTabbar', true)
handleCellClick(val)
}
}

View File

@ -1,5 +1,5 @@
<script lang="ts" setup>
import { ref, onMounted } from 'vue'
import { ref } from 'vue'
import Home from './home/index.vue'
import Directory from './directory/index.vue'
import Personal from './personal/index.vue'
@ -15,30 +15,6 @@ import 'vant/es/loading/style'
const activeTabbar = ref('home')
const showLoading = ref(false)
const hiddenTabbar = ref(false)
const fixFocus = () => {
let u = navigator.userAgent
let isiOS = !!u.match(/\(i[^;]+;( U;)? CPU.+Mac OS X/)
if (isiOS) {
let flag = false
let pageBackNormFunc
document.body.addEventListener('focusin', () => {
flag = true
pageBackNormFunc && clearTimeout(pageBackNormFunc)
})
document.body.addEventListener('focusout', () => {
if (flag) {
pageBackNormFunc = setTimeout(() => {
window.scrollTo({ top: 0, left: 0, behavior: 'smooth' })
}, 200)
}
flag = false
})
}
}
onMounted(() => {
fixFocus()
})
</script>
<template>
@ -63,7 +39,15 @@ onMounted(() => {
</div>
</template>
<style lang="less" scoped>
<style lang="less">
body {
min-height: 100vh;
min-height: -webkit-fill-available;
}
html {
height: -webkit-fill-available;
}
.mobile-index {
width: 100vw;
height: 100vh;

View File

@ -39,6 +39,10 @@ const hanedleMessage = event => {
dvMainStore.componentData.push(component)
}
if (event.data.type === 'setCanvasStyle') {
dvMainStore.setCanvasStyle(event.data.value)
}
if (event.data.type === 'mobileSave') {
window.top.postMessage(
{