forked from github/dataease
feat(移动端): 背景设置
This commit is contained in:
parent
821d30faf1
commit
fa09825b5d
@ -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)
|
||||
})
|
||||
}
|
||||
|
@ -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
|
||||
}
|
||||
|
||||
|
@ -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>
|
@ -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>
|
||||
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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(
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user