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

View File

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

View File

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

View File

@ -1,5 +1,5 @@
<template>
<div class="go-content-charts-item-box">
<div class="go-content-charts-item-box" :class="{ double: chartMode === ChartModeEnum.DOUBLE }">
<!-- 每一项组件的渲染 -->
<div
class="item-box"
@ -11,21 +11,30 @@
@dblclick="dblclickHandle(item)"
>
<div class="list-header">
<mac-os-control-btn :mini="true" :disabled="true"></mac-os-control-btn>
<n-text class="list-header-text" depth="3">{{ item.title }}</n-text>
<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">
<n-ellipsis>{{ item.title }}</n-ellipsis>
</n-text>
</div>
<div class="list-center go-flex-center">
<img class="list-img" v-lazy="item.image" alt="图表图片" />
</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>
</template>
<script setup lang="ts">
import { PropType } from 'vue'
import { PropType, ref, Ref, computed } from 'vue'
import { MacOsControlBtn } from '@/components/Tips/MacOsControlBtn/index'
import { useChartEditStore } from '@/store/modules/chartEditStore/chartEditStore'
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 { DragKeyEnum } from '@/enums/editPageEnum'
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) => {
//
@ -80,13 +96,18 @@ const dblclickHandle = async (item: ConfigType) => {
<style lang="scss" scoped>
/* 列表项宽度 */
$itemWidth: 86%;
$itemWidth: 100%;
$halfItemWidth: 46%;
/* 内容高度 */
$centerHeight: 100px;
$halfCenterHeight: 50px;
@include go('content-charts-item-box') {
display: flex;
flex-wrap: wrap;
gap: 9px;
padding: 10px;
.item-box {
margin: 0 7%;
margin-bottom: 15px;
margin: 0;
width: $itemWidth;
overflow: hidden;
border-radius: 6px;
@ -122,6 +143,39 @@ $centerHeight: 100px;
@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>

View File

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

View File

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