feat: 新增图表展示模式切换

This commit is contained in:
奔跑的面条 2022-11-13 21:28:38 +08:00
parent 3308a7abbb
commit 18d976cf3c
7 changed files with 244 additions and 116 deletions

View File

@ -63,7 +63,8 @@ import {
Images as ImagesIcon, Images as ImagesIcon,
List as ListIcon, List as ListIcon,
EyeOutline as EyeOutlineIcon, EyeOutline as EyeOutlineIcon,
EyeOffOutline as EyeOffOutlineIcon EyeOffOutline as EyeOffOutlineIcon,
Albums as AlbumsIcon
} from '@vicons/ionicons5' } from '@vicons/ionicons5'
import { import {
@ -95,7 +96,8 @@ import {
Carbon3DCursor as Carbon3DCursorIcon, Carbon3DCursor as Carbon3DCursorIcon,
Carbon3DSoftware as Carbon3DSoftwareIcon, Carbon3DSoftware as Carbon3DSoftwareIcon,
Filter as FilterIcon, Filter as FilterIcon,
FilterEdit as FilterEditIcon FilterEdit as FilterEditIcon,
Laptop as LaptopIcon
} from '@vicons/carbon' } from '@vicons/carbon'
const ionicons5 = { const ionicons5 = {
@ -228,7 +230,9 @@ const ionicons5 = {
ListIcon, ListIcon,
// 眼睛 // 眼睛
EyeOutlineIcon, EyeOutlineIcon,
EyeOffOutlineIcon EyeOffOutlineIcon,
// 图表列表
AlbumsIcon
} }
const carbon = { const carbon = {
@ -279,7 +283,9 @@ const carbon = {
Carbon3DSoftwareIcon, Carbon3DSoftwareIcon,
// 过滤器 // 过滤器
FilterIcon, FilterIcon,
FilterEditIcon FilterEditIcon,
// 图层
LaptopIcon
} }
// https://www.xicons.org/#/ 还有很多 // https://www.xicons.org/#/ 还有很多

View File

@ -1,3 +1,8 @@
export enum ChartModeEnum {
SINGLE= 'single',
DOUBLE = 'double'
}
export enum LayerModeEnum { export enum LayerModeEnum {
THUMBNAIL = 'thumbnail', THUMBNAIL = 'thumbnail',
TEXT = 'text' TEXT = 'text'
@ -7,6 +12,7 @@ export enum ChartLayoutStoreEnum {
LAYERS = 'layers', LAYERS = 'layers',
CHARTS = 'charts', CHARTS = 'charts',
DETAILS = 'details', DETAILS = 'details',
Chart_TYPE = 'chartType',
LAYER_TYPE = 'layerType' LAYER_TYPE = 'layerType'
} }
@ -17,6 +23,8 @@ export interface ChartLayoutType {
[ChartLayoutStoreEnum.CHARTS]: boolean [ChartLayoutStoreEnum.CHARTS]: boolean
// 详情设置 // 详情设置
[ChartLayoutStoreEnum.DETAILS]: boolean [ChartLayoutStoreEnum.DETAILS]: boolean
// 组件展示方式
[ChartLayoutStoreEnum.Chart_TYPE]: ChartModeEnum
// 层级展示方式 // 层级展示方式
[ChartLayoutStoreEnum.LAYER_TYPE]: LayerModeEnum [ChartLayoutStoreEnum.LAYER_TYPE]: LayerModeEnum
} }

View File

@ -1,5 +1,5 @@
import { defineStore } from 'pinia' import { defineStore } from 'pinia'
import { ChartLayoutType, LayerModeEnum } from './chartLayoutStore.d' import { ChartLayoutType, LayerModeEnum, ChartModeEnum } from './chartLayoutStore.d'
import { setLocalStorage, getLocalStorage } from '@/utils' import { setLocalStorage, getLocalStorage } from '@/utils'
import { StorageEnum } from '@/enums/storageEnum' import { StorageEnum } from '@/enums/storageEnum'
import { useChartEditStore } from '@/store/modules/chartEditStore/chartEditStore' import { useChartEditStore } from '@/store/modules/chartEditStore/chartEditStore'
@ -21,6 +21,8 @@ export const useChartLayoutStore = defineStore({
charts: true, charts: true,
// 详情设置收缩为true // 详情设置收缩为true
details: false, details: false,
// 组件列表展示类型(默认单列)
chartType: ChartModeEnum.SINGLE,
// 图层类型(默认图片) // 图层类型(默认图片)
layerType: LayerModeEnum.THUMBNAIL layerType: LayerModeEnum.THUMBNAIL
}, },
@ -34,6 +36,9 @@ export const useChartLayoutStore = defineStore({
getDetails(): boolean { getDetails(): boolean {
return this.details return this.details
}, },
getChartType(): ChartModeEnum {
return this.chartType
},
getLayerType(): LayerModeEnum { getLayerType(): LayerModeEnum {
return this.layerType return this.layerType
} }

View File

@ -1,5 +1,5 @@
<template> <template>
<div class="go-content-charts-item-box"> <div class="go-content-charts-item-box" :class="{ double: chartMode === ChartModeEnum.DOUBLE }">
<!-- 每一项组件的渲染 --> <!-- 每一项组件的渲染 -->
<div <div
class="item-box" class="item-box"
@ -11,21 +11,30 @@
@dblclick="dblclickHandle(item)" @dblclick="dblclickHandle(item)"
> >
<div class="list-header"> <div class="list-header">
<mac-os-control-btn :mini="true" :disabled="true"></mac-os-control-btn> <mac-os-control-btn class="list-header-control-btn" :mini="true" :disabled="true"></mac-os-control-btn>
<n-text class="list-header-text" depth="3">{{ item.title }}</n-text> <n-text class="list-header-text" depth="3">
<n-ellipsis>{{ item.title }}</n-ellipsis>
</n-text>
</div> </div>
<div class="list-center go-flex-center"> <div class="list-center go-flex-center">
<img class="list-img" v-lazy="item.image" alt="图表图片" /> <img class="list-img" v-lazy="item.image" alt="图表图片" />
</div> </div>
<div class="list-bottom">
<n-text class="list-bottom-text" depth="3">
<n-ellipsis style="max-width: 90%">{{ item.title }}</n-ellipsis>
</n-text>
</div>
</div> </div>
</div> </div>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { PropType } from 'vue' import { PropType, ref, Ref, computed } from 'vue'
import { MacOsControlBtn } from '@/components/Tips/MacOsControlBtn/index' import { MacOsControlBtn } from '@/components/Tips/MacOsControlBtn/index'
import { useChartEditStore } from '@/store/modules/chartEditStore/chartEditStore' import { useChartEditStore } from '@/store/modules/chartEditStore/chartEditStore'
import { EditCanvasTypeEnum } from '@/store/modules/chartEditStore/chartEditStore.d' import { EditCanvasTypeEnum } from '@/store/modules/chartEditStore/chartEditStore.d'
import { ChartModeEnum } from '@/store/modules/chartLayoutStore/chartLayoutStore.d'
import { useChartLayoutStore } from '@/store/modules/chartLayoutStore/chartLayoutStore'
import { componentInstall, loadingStart, loadingFinish, loadingError } from '@/utils' import { componentInstall, loadingStart, loadingFinish, loadingError } from '@/utils'
import { DragKeyEnum } from '@/enums/editPageEnum' import { DragKeyEnum } from '@/enums/editPageEnum'
import { createComponent } from '@/packages' import { createComponent } from '@/packages'
@ -41,6 +50,13 @@ defineProps({
} }
}) })
const chartLayoutStore = useChartLayoutStore()
//
const chartMode: Ref<ChartModeEnum> = computed(() => {
return chartLayoutStore.getChartType
})
// //
const dragStartHandle = (e: DragEvent, item: ConfigType) => { const dragStartHandle = (e: DragEvent, item: ConfigType) => {
// //
@ -80,13 +96,18 @@ const dblclickHandle = async (item: ConfigType) => {
<style lang="scss" scoped> <style lang="scss" scoped>
/* 列表项宽度 */ /* 列表项宽度 */
$itemWidth: 86%; $itemWidth: 100%;
$halfItemWidth: 46%;
/* 内容高度 */ /* 内容高度 */
$centerHeight: 100px; $centerHeight: 100px;
$halfCenterHeight: 50px;
@include go('content-charts-item-box') { @include go('content-charts-item-box') {
display: flex;
flex-wrap: wrap;
gap: 9px;
padding: 10px;
.item-box { .item-box {
margin: 0 7%; margin: 0;
margin-bottom: 15px;
width: $itemWidth; width: $itemWidth;
overflow: hidden; overflow: hidden;
border-radius: 6px; border-radius: 6px;
@ -122,6 +143,39 @@ $centerHeight: 100px;
@extend .go-transition; @extend .go-transition;
} }
} }
.list-bottom {
display: none;
.list-bottom-text {
font-size: 12px;
padding-left: 5px;
}
}
}
/* 缩小展示 */
&.double {
.list-header {
padding: 2px 5px;
.list-header-text {
display: none;
}
.list-header-control-btn {
transform: scale(0.7);
}
}
.item-box {
width: $halfItemWidth;
}
.list-center {
height: $halfCenterHeight;
padding-bottom: 0px;
.list-img {
height: $halfCenterHeight;
width: auto;
}
}
.list-bottom {
display: block;
}
} }
} }
</style> </style>

View File

@ -123,7 +123,6 @@ $menuWidth: 65px;
display: flex; display: flex;
flex-direction: column; flex-direction: column;
align-items: center; align-items: center;
padding: 10px 0;
} }
@include deep() { @include deep() {
.n-menu-item { .n-menu-item {

View File

@ -1,82 +1,104 @@
<template> <template>
<div class="go-chart-search"> <div class="go-chart-search-box">
<n-popover <div class="chart-search go-transition" :class="{ 'chart-search-focus': isFocus }">
class="chart-search-popover" <n-popover
:show-arrow="false" class="chart-search-popover"
:show="showPopover" :show-arrow="false"
:to="false" :show="showPopover"
trigger="hover" :to="false"
placement="bottom-start" trigger="hover"
> placement="bottom-start"
<template #trigger> >
<n-input-group> <template #trigger>
<n-input <n-input-group>
v-model:value.trim="search" <n-input
size="small" size="small"
:loading="loading" placeholder="搜索组件"
placeholder="请输入组件名称" v-model:value.trim="search"
@update:value="searchHandle" :loading="loading"
> @focus="focusHandle(true)"
<template #suffix> @blur="focusHandle(false)"
<n-icon v-show="!loading" :component="SearchIcon" /> @update:value="searchHandle"
</template> >
</n-input> <template #suffix>
</n-input-group> <n-icon v-show="!loading" :component="SearchIcon" />
</template> </template>
</n-input>
</n-input-group>
</template>
<div class="search-list-box"> <div class="search-list-box">
<n-scrollbar style="max-height: 500px"> <n-scrollbar style="max-height: 500px">
<n-empty <n-empty v-show="!searchRes.length" size="small" description="没有找到组件~"></n-empty>
v-show="!searchRes.length" <div
size="small" class="list-item go-flex-items-center go-ellipsis-1"
description="没有找到组件~" v-for="item in searchRes"
></n-empty> :key="item.key"
<div :title="item.title"
class="list-item go-flex-items-center go-ellipsis-1" @click="selectChartHandle(item)"
v-for="item in searchRes" >
:key="item.key" <img class="list-item-img" v-lazy="item.image" alt="展示图" />
:title="item.title" <n-text class="list-item-fs" depth="2">{{ item.title }}</n-text>
@click="selectChartHandle(item)" </div>
> </n-scrollbar>
<img class="list-item-img" v-lazy="item.image" alt="展示图" /> <div class="popover-modal"></div>
<n-text class="list-item-fs" depth="2">{{ item.title }}</n-text> </div>
</div> </n-popover>
</n-scrollbar> </div>
<div class="popover-modal"></div> <n-button-group class="btn-group go-transition" :class="{ 'btn-group-focus': isFocus }" style="display: flex">
</div> <n-button
</n-popover> ghost
size="small"
:key="index"
:type="chartMode === item.value ? 'primary' : 'tertiary'"
v-for="(item, index) in chartModeList"
@click="changeChartModeType(item.value)"
>
<n-tooltip :show-arrow="false" trigger="hover">
<template #trigger>
<n-icon size="14" :component="item.icon" />
</template>
{{ item.label }}
</n-tooltip>
</n-button>
</n-button-group>
</div> </div>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { ref, onUnmounted } from 'vue' import { ref, onUnmounted } from 'vue'
import { icon } from '@/plugins' import { icon } from '@/plugins'
import { createComponent } from '@/packages'
import { ConfigType, CreateComponentType } from '@/packages/index.d'
import { themeColor, MenuOptionsType } from '../../hooks/useAside.hook' import { themeColor, MenuOptionsType } from '../../hooks/useAside.hook'
import { useChartEditStore } from '@/store/modules/chartEditStore/chartEditStore' import { useChartEditStore } from '@/store/modules/chartEditStore/chartEditStore'
import { ConfigType, CreateComponentType } from '@/packages/index.d' import { ChartModeEnum, ChartLayoutStoreEnum } from '@/store/modules/chartLayoutStore/chartLayoutStore.d'
import { createComponent } from '@/packages' import { useChartLayoutStore } from '@/store/modules/chartLayoutStore/chartLayoutStore'
import { isString, addEventListener, removeEventListener } from '@/utils' import { isString, addEventListener, removeEventListener } from '@/utils'
import { fetchConfigComponent, fetchChartComponent } from '@/packages/index' import { fetchConfigComponent, fetchChartComponent } from '@/packages/index'
import { import { componentInstall, loadingStart, loadingFinish, loadingError } from '@/utils'
componentInstall,
loadingStart,
loadingFinish,
loadingError,
} from '@/utils'
const props = defineProps({ const props = defineProps({
menuOptions: { menuOptions: {
type: Array, type: Array,
default: () => [], default: () => []
}, }
}) })
const { SearchIcon } = icon.ionicons5
const chartEditStore = useChartEditStore() const chartEditStore = useChartEditStore()
const chartLayoutStore = useChartLayoutStore()
const { SearchIcon, AlbumsIcon, GridIcon } = icon.ionicons5
const isFocus = ref<boolean>(false)
const showPopover = ref<boolean>(false) const showPopover = ref<boolean>(false)
const loading = ref<boolean | undefined>(undefined) const loading = ref<boolean | undefined>(undefined)
const search = ref<string | null>(null) const search = ref<string | null>(null)
const searchRes = ref<ConfigType[]>([]) const searchRes = ref<ConfigType[]>([])
const chartMode = ref<ChartModeEnum>(chartLayoutStore.getChartType)
const chartModeList = [
{ label: '单列', icon: AlbumsIcon, value: ChartModeEnum.SINGLE },
{ label: '双列', icon: GridIcon, value: ChartModeEnum.DOUBLE }
]
// //
const listFormatHandle = (options: any[]) => { const listFormatHandle = (options: any[]) => {
@ -106,9 +128,7 @@ const searchHandle = (key: string | null) => {
} }
loading.value = true loading.value = true
showPopover.value = true showPopover.value = true
searchRes.value = List.filter( searchRes.value = List.filter((e: ConfigType) => !key || e.title.toLowerCase().includes(key.toLowerCase()))
(e: ConfigType) => !key || e.title.toLowerCase().includes(key.toLowerCase())
)
setTimeout(() => { setTimeout(() => {
loading.value = undefined loading.value = undefined
}, 500) }, 500)
@ -145,6 +165,17 @@ const selectChartHandle = async (item: ConfigType) => {
} }
} }
//
const focusHandle = (value: boolean) => {
isFocus.value = value
}
//
const changeChartModeType = (value: ChartModeEnum) => {
chartMode.value = value
chartLayoutStore.setItem(ChartLayoutStoreEnum.Chart_TYPE, value)
}
addEventListener(document, 'click', (e: Event) => { addEventListener(document, 'click', (e: Event) => {
listenerCloseHandle(e) listenerCloseHandle(e)
}) })
@ -155,54 +186,78 @@ onUnmounted(() => {
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
$width: 178px; $width: 98px;
@include go('chart-search') { $searchWidth: 176px;
width: $width;
margin-right: -12px; @include go('chart-search-box') {
.chart-search-popover { display: flex;
.search-list-box { .chart-search {
width: calc(#{$width} - 30px); width: $width;
.list-item { margin-right: 10px;
z-index: 2; &.chart-search-focus {
position: relative; width: $searchWidth;
cursor: pointer; &.chart-search {
padding: 2px; margin-right: 0;
padding-left: 6px; }
margin-bottom: 5px; }
&-fs { @include deep() {
font-size: 12px; .chart-search-popover {
} padding-left: 5px;
&-img { padding-right: 8px;
height: 28px; }
margin-right: 5px; }
border-radius: 5px; .chart-search-popover {
} .search-list-box {
&:hover { width: 163px;
&::before { .list-item {
content: ''; z-index: 2;
position: absolute; position: relative;
width: 3px; cursor: pointer;
height: 100%; padding: 2px;
left: 0; padding-left: 6px;
top: 0; margin-bottom: 5px;
border-radius: 2px; &-fs {
background-color: v-bind('themeColor'); font-size: 12px;
} }
&::after { &-img {
z-index: -1; height: 28px;
content: ''; margin-right: 5px;
position: absolute;
width: 100%;
height: 100%;
opacity: 0.1;
left: 0;
top: 0;
border-radius: 5px; border-radius: 5px;
background-color: v-bind('themeColor'); }
&:hover {
&::before {
content: '';
position: absolute;
width: 3px;
height: 100%;
left: 0;
top: 0;
border-radius: 2px;
background-color: v-bind('themeColor');
}
&::after {
z-index: -1;
content: '';
position: absolute;
width: 100%;
height: 100%;
opacity: 0.1;
left: 0;
top: 0;
border-radius: 5px;
background-color: v-bind('themeColor');
}
} }
} }
} }
} }
} }
.btn-group {
width: 68px;
overflow: hidden;
&.btn-group-focus {
width: 0px;
}
}
} }
</style> </style>

View File

@ -81,12 +81,13 @@ import { LayersGroupListItem } from './components/LayersGroupListItem/index'
import { icon } from '@/plugins' import { icon } from '@/plugins'
const { LayersIcon, GridIcon, ListIcon } = icon.ionicons5 const { LayersIcon, GridIcon, ListIcon } = icon.ionicons5
const { LaptopIcon } = icon.carbon
const chartLayoutStore = useChartLayoutStore() const chartLayoutStore = useChartLayoutStore()
const chartEditStore = useChartEditStore() const chartEditStore = useChartEditStore()
const { handleContextMenu, onClickOutSide } = useContextMenu() const { handleContextMenu, onClickOutSide } = useContextMenu()
const layerModeList = [ const layerModeList = [
{ label: '缩略图', icon: GridIcon, value: LayerModeEnum.THUMBNAIL }, { label: '缩略图', icon: LaptopIcon, value: LayerModeEnum.THUMBNAIL },
{ label: '文本列表', icon: ListIcon, value: LayerModeEnum.TEXT } { label: '文本列表', icon: ListIcon, value: LayerModeEnum.TEXT }
] ]