Skip to content

Commit

Permalink
Merge pull request #4485 from Tinhone/improve-custom-font-family
Browse files Browse the repository at this point in the history
[组件-自定义字体] feat: 改善组件代码和功能
  • Loading branch information
the1812 authored Nov 22, 2023
2 parents 8894659 + a8903f9 commit e3d611f
Show file tree
Hide file tree
Showing 10 changed files with 407 additions and 257 deletions.
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<template>
<div class="custom-font-family-extra-options-entry">
<VButton ref="button" @mouseover="loadExtraOptions()" @click="toggleExtraOptionsDisplay()">
<VButton @mouseover="loadPanel()" @click="togglePanelDisplay()">
字体设置<VIcon icon="right-arrow" :size="16"></VIcon>
</VButton>
</div>
Expand All @@ -9,12 +9,7 @@
<script lang="ts">
import { defineComponent } from 'vue'
import { VIcon, VButton } from '@/ui'
import {
setTriggerElement,
getExtraOptionsLoadState,
loadExtraOptions,
toggleExtraOptionsDisplay,
} from './vm'
import { loadPanel, togglePanelDisplay } from './vm'
export default defineComponent({
components: {
Expand All @@ -23,15 +18,8 @@ export default defineComponent({
},
methods: {
async loadExtraOptions() {
const isLoaded = await getExtraOptionsLoadState()
if (!isLoaded) {
await loadExtraOptions()
const triggerButton = this.$refs.button.$el as HTMLElement
setTriggerElement(triggerButton)
}
},
toggleExtraOptionsDisplay,
loadPanel,
togglePanelDisplay,
},
})
</script>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
<template>
<VPopup v-model="popupOpen" class="be-extra-options-panel" fixed :lazy="false">
<div class="be-eop-header">
<div class="be-eop-h-title">
<VIcon class="be-eop-h-t-icon" :icon="initData.header.title.icon" :size="24"></VIcon>
<div class="be-eop-h-t-text">{{ initData.header.title.text }}</div>
</div>

<div class="be-eop-h-actions">
<div v-for="action in initData.header.actions" :key="action.id" class="be-eop-h-a-action">
<VIcon
:ref="`action${action.id}`"
:class="`action-${action.actionClassNameSuffix}`"
:title="action.title"
:icon="action.icon"
:size="24"
></VIcon>
</div>
<div class="be-eop-h-a-action">
<VIcon
class="action-close"
title="关闭"
icon="mdi-close"
:size="24"
@click="popupOpen = false"
></VIcon>
</div>
</div>
</div>

<div class="be-eop-separator"></div>

<div class="be-eop-content">
<div v-for="option in initData.content.options" :key="option.id" class="be-eop-c-option">
<div class="be-eop-c-o-title">{{ option.title }}</div>
<div class="be-eop-c-o-description">{{ option.description }}</div>
<div class="be-eop-c-o-input" :class="`input-${option.inputClassNameSuffix}`">
<slot :name="`input${option.id}`">
选项输入入口默认文字,使用含 v-slot 指令的 template 元素以替换默认内容
</slot>
</div>
</div>
</div>
</VPopup>
</template>

<script lang="ts">
import { defineComponent } from 'vue'
import { VPopup, VIcon } from '@/ui'
import { defaultInitData } from './extra-options-panel'
export default defineComponent({
name: 'ExtraOptionsPanel',
components: {
VPopup,
VIcon,
},
props: {
initData: {
type: Object,
default: defaultInitData,
},
},
data() {
return {
popupOpen: false,
}
},
})
</script>

<style lang="scss">
@import './extra-options-panel';
.be-extra-options-panel {
@include extra-options-panel();
}
</style>
Original file line number Diff line number Diff line change
@@ -0,0 +1,148 @@
<template>
<ExtraOptionsPanel
ref="extraOptionsPanel"
class="custom-font-family-extra-options-panel"
:class="{ peek: isPeeking }"
:init-data="initData"
>
<template #input0>
<TextArea v-model="inputFontFamily" />
</template>
</ExtraOptionsPanel>
</template>

<script lang="ts">
import { defineComponent } from 'vue'
import { TextArea } from '@/ui'
import ExtraOptionsPanel from './ExtraOptionsPanel.vue'
import { getComponentSettings } from '@/core/settings'
import { Toast } from '@/core/toast'
import { delay } from '@/core/utils'
import { useScopedConsole } from '@/core/utils/log'
import { fontFamilyDefaultValue } from '../font-family-default-value'
import { ExtraOptionsPanelInitData } from './extra-options-panel'
const initData: ExtraOptionsPanelInitData = {
header: {
title: {
text: '自定义字体',
icon: 'mdi-format-font',
},
actions: [
{
id: 0,
title: '重置面板中的所有选项为默认值',
icon: 'mdi-cog-sync-outline',
actionClassNameSuffix: 'reset',
},
{
id: 1,
title: '透视',
icon: 'mdi-eye-outline',
actionClassNameSuffix: 'peek',
},
],
},
content: {
options: [
{
id: 0,
title: '自定义字体',
description: '输入需要设置的字体,不同字体之间必须以英文逗号分隔',
inputClassNameSuffix: 'input-font-family',
},
],
},
}
const console = useScopedConsole('自定义字体')
export default defineComponent({
components: {
ExtraOptionsPanel,
TextArea,
},
data() {
return {
isPeeking: false,
isMouseOverPeekIcon: false,
initData,
// 设置 inputFontFamily 初始值为组件 fontFamily 选项的值
inputFontFamily: getComponentSettings('customFontFamily').options.fontFamily,
}
},
watch: {
// 监听 inputFontFamily 修改动作,实时修改组件 fontFamily 选项为 inputFontFamily 修改后的新值,并拥有 1000ms 防抖
inputFontFamily: lodash.debounce(value => {
getComponentSettings('customFontFamily').options.fontFamily = value
}, 1000),
async isMouseOverPeekIcon(value: boolean) {
if (!value) {
this.isPeeking = false
return
}
if (value) {
await delay(200)
}
if (this.isMouseOverPeekIcon) {
this.isPeeking = true
}
},
},
mounted() {
// 当在 v-for 中使用模板引用时,相应的引用中包含的值是一个数组
// 但 ref 数组并不保证与源数组相同的顺序,所以统一命名且不加用以区分的后缀,仅靠数组选择元素是不现实的
// https://cn.vuejs.org/guide/essentials/template-refs.html#refs-inside-v-for
const action0Reset = this.$refs.extraOptionsPanel.$refs.action0[0].$el as HTMLElement
action0Reset.addEventListener('click', this.confirmResetOptions)
const action1Peek = this.$refs.extraOptionsPanel.$refs.action1[0].$el as HTMLElement
action1Peek.addEventListener('mouseover', this.setIsMouseOverPeekIconToTrue)
action1Peek.addEventListener('mouseout', this.setIsMouseOverPeekIconToFalse)
},
methods: {
toggleDisplay() {
this.$refs.extraOptionsPanel.popupOpen = !this.$refs.extraOptionsPanel.popupOpen
},
setIsMouseOverPeekIconToTrue() {
this.isMouseOverPeekIcon = true
},
setIsMouseOverPeekIconToFalse() {
this.isMouseOverPeekIcon = false
},
confirmResetOptions() {
if (confirm('确定将面板中的所有选项重置为默认值吗?')) {
this.resetOptions()
}
},
resetOptions() {
getComponentSettings('customFontFamily').options.fontFamily = fontFamilyDefaultValue
this.inputFontFamily = fontFamilyDefaultValue
Toast.success('字体设置面板中的所有选项已成功被重置为默认值', '自定义字体', 2000)
console.log('字体设置面板中的所有选项已成功被重置为默认值')
},
},
})
</script>

<style lang="scss">
.custom-font-family-extra-options-panel {
&.peek {
opacity: 0.1;
}
> .be-eop-content > .be-eop-c-option > .be-eop-c-o-input.input-input-font-family > .be-text-area {
min-height: 160px;
}
}
</style>
Original file line number Diff line number Diff line change
@@ -1,59 +1,52 @@
@import 'common';

$pref: 'eop';
$prefH: 'eop-h';
$prefHL: 'eop-h-l';
$prefHR: 'eop-h-r';
$prefC: 'eop-c';
$prefCS: 'eop-c-s';

$panelPadding: 22px;
$pref: 'be-eop';
$panel-padding: 18px;
$internal-spacing: 14px;

@mixin extra-options-panel {
&.extra-options-panel {
&.be-extra-options-panel {
@include popup();
display: flex;
flex-direction: column;
width: 500px;
max-width: 80vw;
max-height: 80vh;
padding: $panelPadding 0;
padding: $panel-padding 0;
left: 50%;
top: 50%;
transform: translateX(-50%) translateY(-50%) scale(0.95);
transition: all 0.2s ease-out;
font-size: 14px;
line-height: normal;
z-index: 100002;

&.open {
transform: translateX(-50%) translateY(-50%) scale(1);
}

&.peek {
opacity: 0.1;
}

> .#{$pref}-header {
display: flex;
justify-content: space-between;
padding: 0 $panelPadding 18px $panelPadding;
padding: 0 $panel-padding $internal-spacing $panel-padding;
flex-shrink: 0;

> .#{$prefH}-left {
> .#{$pref}-h-title {
display: flex;
column-gap: 4px;

> .#{$prefHL}-title {
> .#{$pref}-h-t-text {
@include semi-bold();
font-size: 19px;
line-height: 20px;
}
}

> .#{$prefH}-right {
> .#{$pref}-h-actions {
display: flex;
column-gap: 20px;
column-gap: ($internal-spacing + 4px);

> [class*='#{$prefHR}'] {
> .#{$pref}-h-a-action {
cursor: pointer;
transition: all 0.2s ease-out;

Expand All @@ -66,40 +59,41 @@ $panelPadding: 22px;

> .#{$pref}-separator {
height: 1px;
margin: 0 $panelPadding;
background: rgba(0, 0, 0, 0.1);
margin: 0 $panel-padding;
background-color: rgba(0, 0, 0, 0.1);
flex-shrink: 0;

body.dark & {
background: rgba(255, 255, 255, 0.1);
background-color: rgba(255, 255, 255, 0.1);
}
}

> .#{$pref}-content {
padding: 0 $panelPadding;
@include no-scrollbar();
padding: $internal-spacing $panel-padding 0 $panel-padding;
overflow: auto;
flex-grow: 1;
flex-shrink: 1;

> .#{$prefC}-section {
margin: 18px 0;
> .#{$pref}-c-option {
margin-bottom: ($internal-spacing + 4px);

&:nth-child(1):nth-last-child(1) {
margin-bottom: 12px;
&:nth-last-child(1) {
margin-bottom: ($internal-spacing - 2px);
}

> .#{$prefCS}-title {
> .#{$pref}-c-o-title {
margin-bottom: 2px;
font-size: 14px;
}

> .#{$prefCS}-description {
> .#{$pref}-c-o-description {
margin-bottom: 8px;
opacity: 0.6;
font-size: 12px;
}

> .#{$prefCS}-input {
> .#{$pref}-c-o-input {
@include h-center();
flex-wrap: wrap;
}
Expand Down
Loading

0 comments on commit e3d611f

Please sign in to comment.