Merge pull request #11803 from dataease/pr@dev-v2_st

feat(系统设置): 字体管理
This commit is contained in:
dataeaseShu 2024-08-28 11:31:25 +08:00 committed by GitHub
commit 2e76ed28a1
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 177 additions and 65 deletions

View File

@ -60,6 +60,7 @@ router.beforeEach(async (to, from, next) => {
}
await appearanceStore.setAppearance()
if ((wsCache.get('user.token') || isDesktop) && !to.path.startsWith('/de-link/')) {
await appearanceStore.setFontList()
if (!userStore.getUid) {
await userStore.setUser()
}

View File

@ -1,6 +1,6 @@
import { defineStore } from 'pinia'
import { store } from '@/store/index'
import { defaultFont } from '@/api/font'
import { defaultFont, list } from '@/api/font'
import { uiLoadApi } from '@/api/login'
import { useCache } from '@/hooks/web/useCache'
import colorFunctions from 'less/lib/less/functions/color.js'
@ -31,6 +31,7 @@ interface AppearanceState {
showDemoTips?: boolean
demoTipsContent?: string
community: boolean
fontList: Array<{ name: string; id: string }>
}
const { wsCache } = useCache()
export const useAppearanceStore = defineStore('appearanceStore', {
@ -57,7 +58,8 @@ export const useAppearanceStore = defineStore('appearanceStore', {
loaded: false,
showDemoTips: false,
demoTipsContent: '',
community: true
community: true,
fontList: []
}
},
getters: {
@ -153,6 +155,27 @@ export const useAppearanceStore = defineStore('appearanceStore', {
setMobileLogin(data: string) {
this.mobileLogin = data
},
async setFontList() {
const res = await list()
this.fontList = res || []
},
setCurrentFont(name) {
const currentFont = this.fontList.find(ele => ele.name === name)
if (currentFont) {
let fontStyleElement = document.querySelector(`#de-custom_font${name}`)
if (!fontStyleElement) {
fontStyleElement = document.createElement('style')
fontStyleElement.setAttribute('id', `de-custom_font${name}`)
document.querySelector('head').appendChild(fontStyleElement)
}
fontStyleElement.innerHTML = `@font-face {
font-family: '${name}';
src: url(${basePath}/typeface/download/${currentFont.id});
font-weight: normal;
font-style: normal;
}`
}
},
setMobileLoginBg(data: string) {
this.mobileLoginBg = data
},
@ -180,7 +203,6 @@ export const useAppearanceStore = defineStore('appearanceStore', {
if (this.loaded) {
return
}
defaultFont().then(res => {
const [font] = res || []
setDefaultFont(`${basePath}/typeface/download/${font?.id}`, font?.name)
@ -199,6 +221,7 @@ export const useAppearanceStore = defineStore('appearanceStore', {
font-style: normal;
}`
document.documentElement.style.setProperty('--de-custom_font', `${name}`)
document.documentElement.style.setProperty('--van-base-font', `${name}`)
}
})
if (!isDataEaseBi) {

View File

@ -1,45 +1,54 @@
.vjs-custom-skin > .video-js {
width: 100%;
background-color: rgba(0, 0, 0, 0);
font-family: "AlibabaPuHuiTi","Helvetica Neue","Hiragino Sans GB","Segoe UI","Microsoft YaHei","微软雅黑",sans-serif;
font-family: 'Helvetica Neue', 'Hiragino Sans GB', 'Segoe UI', 'Microsoft YaHei', '微软雅黑',
sans-serif;
}
.vjs-custom-skin > .video-js .vjs-menu-button-inline.vjs-slider-active,.vjs-custom-skin > .video-js .vjs-menu-button-inline:focus,.vjs-custom-skin > .video-js .vjs-menu-button-inline:hover,.video-js.vjs-no-flex .vjs-menu-button-inline {
width: 10em
.vjs-custom-skin > .video-js .vjs-menu-button-inline.vjs-slider-active,
.vjs-custom-skin > .video-js .vjs-menu-button-inline:focus,
.vjs-custom-skin > .video-js .vjs-menu-button-inline:hover,
.video-js.vjs-no-flex .vjs-menu-button-inline {
width: 10em;
}
.vjs-custom-skin > .video-js .vjs-controls-disabled .vjs-big-play-button {
display: none!important
display: none !important;
}
.vjs-custom-skin > .video-js .vjs-control {
width: 3em
width: 3em;
}
.vjs-custom-skin > .video-js .vjs-control.vjs-live-control{
.vjs-custom-skin > .video-js .vjs-control.vjs-live-control {
width: auto;
padding-left: .5em;
letter-spacing: .1em;
padding-left: 0.5em;
letter-spacing: 0.1em;
}
.vjs-custom-skin > .video-js .vjs-menu-button-inline:before {
width: 1.5em
width: 1.5em;
}
.vjs-menu-button-inline .vjs-menu {
left: 3em
left: 3em;
}
.vjs-paused.vjs-has-started.vjs-custom-skin > .video-js .vjs-big-play-button,.video-js.vjs-ended .vjs-big-play-button,.video-js.vjs-paused .vjs-big-play-button {
display: block
.vjs-paused.vjs-has-started.vjs-custom-skin > .video-js .vjs-big-play-button,
.video-js.vjs-ended .vjs-big-play-button,
.video-js.vjs-paused .vjs-big-play-button {
display: block;
}
.vjs-custom-skin > .video-js .vjs-load-progress div,.vjs-seeking .vjs-big-play-button,.vjs-waiting .vjs-big-play-button {
display: none!important
.vjs-custom-skin > .video-js .vjs-load-progress div,
.vjs-seeking .vjs-big-play-button,
.vjs-waiting .vjs-big-play-button {
display: none !important;
}
.vjs-custom-skin > .video-js .vjs-mouse-display:after,.vjs-custom-skin > .video-js .vjs-play-progress:after {
padding: 0 .4em .3em
.vjs-custom-skin > .video-js .vjs-mouse-display:after,
.vjs-custom-skin > .video-js .vjs-play-progress:after {
padding: 0 0.4em 0.3em;
}
.video-js.vjs-ended .vjs-loading-spinner {
@ -50,46 +59,51 @@
display: block !important;
}
.video-js.vjs-ended .vjs-big-play-button,.video-js.vjs-paused .vjs-big-play-button,.vjs-paused.vjs-has-started.vjs-custom-skin > .video-js .vjs-big-play-button {
display: block
.video-js.vjs-ended .vjs-big-play-button,
.video-js.vjs-paused .vjs-big-play-button,
.vjs-paused.vjs-has-started.vjs-custom-skin > .video-js .vjs-big-play-button {
display: block;
}
.vjs-custom-skin > .video-js .vjs-big-play-button {
top: 50%;
left: 50%;
margin-left: -1.5em;
margin-top: -1em
margin-top: -1em;
}
.vjs-custom-skin > .video-js .vjs-big-play-button {
background-color: rgba(0,0,0,0.45);
background-color: rgba(0, 0, 0, 0.45);
font-size: 3.5em;
/*border-radius: 50%;*/
/*border-radius: 50%;*/
height: 2em !important;
line-height: 2em !important;
margin-top: -1em !important
margin-top: -1em !important;
}
.video-js:hover .vjs-big-play-button,.vjs-custom-skin > .video-js .vjs-big-play-button:focus,.vjs-custom-skin > .video-js .vjs-big-play-button:active {
background-color: rgba(36,131,213,0.9)
.video-js:hover .vjs-big-play-button,
.vjs-custom-skin > .video-js .vjs-big-play-button:focus,
.vjs-custom-skin > .video-js .vjs-big-play-button:active {
background-color: rgba(36, 131, 213, 0.9);
}
.vjs-custom-skin > .video-js .vjs-loading-spinner {
border-color: rgba(36,131,213,0.8)
border-color: rgba(36, 131, 213, 0.8);
}
.vjs-custom-skin > .video-js .vjs-control-bar2 {
background-color: #000000
background-color: #000000;
}
.vjs-custom-skin > .video-js .vjs-control-bar {
/*background-color: rgba(0,0,0,0.3) !important;*/
/*background-color: rgba(0,0,0,0.3) !important;*/
color: #ffffff;
font-size: 14px
font-size: 14px;
}
.vjs-custom-skin > .video-js .vjs-play-progress,.vjs-custom-skin > .video-js .vjs-volume-level {
background-color: #2483d5
.vjs-custom-skin > .video-js .vjs-play-progress,
.vjs-custom-skin > .video-js .vjs-volume-level {
background-color: #2483d5;
}
.vjs-custom-skin > .video-js .vjs-play-progress:before {
@ -108,7 +122,8 @@
padding: 0;
line-height: 2em;
font-size: 1.1em;
font-family: "AlibabaPuHuiTi","Helvetica Neue","Hiragino Sans GB","Segoe UI","Microsoft YaHei","微软雅黑",sans-serif;
font-family: 'Helvetica Neue', 'Hiragino Sans GB', 'Segoe UI', 'Microsoft YaHei', '微软雅黑',
sans-serif;
}
.vjs-custom-skin > .video-js .vjs-time-tooltip,
@ -133,10 +148,10 @@
}
.vjs-custom-skin > .video-js .vjs-control-bar .vjs-resolution-button .vjs-menu {
/*order: 4;*/
/*order: 4;*/
}
/*排序顺序*/
/*排序顺序*/
.vjs-custom-skin > .video-js .vjs-control-bar .vjs-play-control {
order: 0;
}
@ -144,13 +159,13 @@
.vjs-custom-skin > .video-js .vjs-control-bar .vjs-time-control {
min-width: 1em;
padding: 0;
margin: 0 .1em;
margin: 0 0.1em;
text-align: center;
display: block;
order: 1;
}
.vjs-custom-skin > .video-js .vjs-control-bar .vjs-playback-rate .vjs-playback-rate-value{
.vjs-custom-skin > .video-js .vjs-control-bar .vjs-playback-rate .vjs-playback-rate-value {
font-size: 1.2em;
line-height: 2.4;
}

View File

@ -416,7 +416,7 @@ strong {
box-shadow: 0px 4px 8px 0px #1f23291a;
& > p {
font-family: AlibabaPuHuiTi;
font-family: var(--de-custom_font, 'PingFang');
font-size: 14px;
font-weight: 500;
line-height: 22px;

View File

@ -1,5 +1,6 @@
<script lang="ts" setup>
import { PropType, computed, onMounted, reactive, toRefs, watch, nextTick, ref } from 'vue'
import { useAppearanceStoreWithOut } from '@/store/modules/appearance'
import { useI18n } from '@/hooks/web/useI18n'
import {
COLOR_PANEL,
@ -30,13 +31,18 @@ const props = defineProps({
type: Array<string>
}
})
const appearanceStore = useAppearanceStoreWithOut()
const emit = defineEmits(['onTextChange'])
const toolTip = computed(() => {
return props.themes === 'dark' ? 'ndark' : 'dark'
})
const predefineColors = COLOR_PANEL
const fontFamily = CHART_FONT_FAMILY
const fontFamily = CHART_FONT_FAMILY.concat(
appearanceStore.fontList.map(ele => ({
name: ele.name,
value: ele.name
}))
)
const fontLetterSpace = CHART_FONT_LETTER_SPACE
const state = reactive({

View File

@ -2,6 +2,7 @@
import { useI18n } from '@/hooks/web/useI18n'
import ChartComponentG2Plot from './components/ChartComponentG2Plot.vue'
import DeIndicator from '@/custom-component/indicator/DeIndicator.vue'
import { useAppearanceStoreWithOut } from '@/store/modules/appearance'
import { useAppStoreWithOut } from '@/store/modules/app'
import router from '@/router'
import { useEmbedded } from '@/store/modules/embedded'
@ -57,6 +58,7 @@ const { emitter } = useEmitt()
let innerRefreshTimer = null
const appStore = useAppStoreWithOut()
const appearanceStore = useAppearanceStoreWithOut()
const isDataEaseBi = computed(() => appStore.getIsDataEaseBi)
const isIframe = computed(() => appStore.getIsIframe)
@ -270,10 +272,16 @@ const initTitle = () => {
state.title_class.textAlign = customStyle.text.hPosition as CSSProperties['textAlign']
state.title_class.fontStyle = customStyle.text.isItalic ? 'italic' : 'normal'
state.title_class.fontWeight = customStyle.text.isBolder ? 'bold' : 'normal'
if (!!appearanceStore.fontList.length) {
appearanceStore.fontList.forEach(ele => {
CHART_FONT_FAMILY_MAP[ele.name] = ele.name
})
}
state.title_class.fontFamily = customStyle.text.fontFamily
? CHART_FONT_FAMILY_MAP[customStyle.text.fontFamily]
: DEFAULT_TITLE_STYLE.fontFamily
appearanceStore.setCurrentFont(state.title_class.fontFamily)
state.title_class.letterSpacing =
(customStyle.text.letterSpace
? customStyle.text.letterSpace

View File

@ -8,14 +8,30 @@ const fontList = ref([])
const basePath = import.meta.env.VITE_API_BASEPATH
const uploadDetail = ref()
const loading = ref(false)
const uploadFont = (title, type, item) => {
uploadDetail.value.init(title, type, item)
}
const listFont = () => {
list({}).then(res => {
fontList.value = res
})
loading.value = true
list({})
.then(res => {
fontList.value = [
{
name: 'PingFang',
id: '0',
isBuiltin: true,
updateTime: new Date(),
fileName: '-',
isDefault: Number(!(res || []).some(ele => ele.isDefault))
},
...(res || [])
]
})
.finally(() => {
loading.value = false
})
}
const deleteFont = item => {
@ -29,20 +45,53 @@ const deleteFont = item => {
autofocus: false,
showClose: false
}).then(() => {
deleteById(item.id).then(() => {
ElMessage.success('删除成功')
listFont()
getDefaultFont()
})
loading.value = true
deleteById(item.id)
.then(() => {
ElMessage.success('删除成功')
listFont()
getDefaultFont()
})
.finally(() => {
loading.value = false
})
})
}
const setToDefault = item => {
item.isDefault = 1
edit(item).then(() => {
ElMessage.success('设置成功')
getDefaultFont()
})
if (item.id === '0') {
fontList.value.forEach(ele => {
if (ele.isDefault) {
ele.isDefault = 0
loading.value = true
edit(ele)
.then(() => {
ElMessage.success('设置成功')
getDefaultFont()
})
.finally(() => {
loading.value = false
})
}
})
item.isDefault = 1
} else {
fontList.value.forEach(ele => {
if (ele.id === '0' && ele.isDefault) {
ele.isDefault = 0
}
})
item.isDefault = 1
loading.value = true
edit(item)
.then(() => {
ElMessage.success('设置成功')
getDefaultFont()
})
.finally(() => {
loading.value = false
})
}
}
const setDefaultFont = (url, name) => {
let fontStyleElement = document.querySelector('#de-custom_font')
@ -60,6 +109,7 @@ const setDefaultFont = (url, name) => {
}`
: ''
document.documentElement.style.setProperty('--de-custom_font', `${name ? name : ''}`)
document.documentElement.style.setProperty('--van-base-font', `${name ? name : ''}`)
}
const getDefaultFont = () => {
defaultFont().then(res => {
@ -69,11 +119,21 @@ const getDefaultFont = () => {
}
const cancelDefault = item => {
item.isDefault = 0
edit(item).then(() => {
ElMessage.success('取消成功')
getDefaultFont()
fontList.value.forEach(ele => {
if (ele.id === '0') {
ele.isDefault = 1
}
})
item.isDefault = 0
loading.value = true
edit(item)
.then(() => {
ElMessage.success('取消成功')
getDefaultFont()
})
.finally(() => {
loading.value = false
})
}
onMounted(() => {
@ -82,7 +142,7 @@ onMounted(() => {
</script>
<template>
<div class="font-management_system">
<div class="font-management_system" v-loading="loading">
<div class="route-title">
字体管理
<div class="search-font">
@ -114,25 +174,24 @@ onMounted(() => {
</div>
<div class="font-upload_btn">
<el-button
v-if="!ele.fileTransName"
v-if="!ele.fileTransName && ele.id !== '0'"
@click="uploadFont('上传字库文件', 'uploadFile', ele)"
secondary
>上传字库文件</el-button
>
<el-button
v-if="ele.fileTransName"
v-if="ele.fileTransName && ele.id !== '0'"
@click="uploadFont('替换字库文件', 'uploadFile', ele)"
secondary
>替换字库文件</el-button
>
<el-button v-if="!ele.isDefault" @click="setToDefault(ele)" secondary
<el-button v-if="!ele.isDefault || ele.id === '0'" @click="setToDefault(ele)" secondary
>设为默认字体</el-button
>
<el-button v-if="ele.isDefault" @click="cancelDefault(ele)" secondary
<el-button v-if="ele.isDefault && ele.id !== '0'" @click="cancelDefault(ele)" secondary
>取消默认字体</el-button
>
<el-button @click="uploadFont('重命名', 'rename', ele)" secondary>重命名</el-button>
<el-button @click="deleteFont(ele)" secondary>删除</el-button>
<el-button v-if="ele.id !== '0'" @click="deleteFont(ele)" secondary>删除</el-button>
</div>
</div>
</div>