LoongPanel-Asp/web/components/Grid/MainGrid.vue

219 lines
5.7 KiB
Vue

<script lang="ts" setup>
import {GridItem, GridLayout} from 'grid-layout-plus'
import ICard from "~/components/Cards/ICard.vue";
import IChart from "~/components/Cards/IChart.vue";
import {type IGridItem, type Layouts, useMainLayoutStore} from "~/strores/UseMainLayoutStore";
import {UseDraggable} from '@vueuse/components'
import AddCard from "~/components/AddCard.vue";
import {type dataHistoryType, useDataStore} from "~/strores/DataStore";
import _ from "lodash";
import {useLoadStore} from "~/strores/LoadStore";
import type {HttpType} from "~/types/baseType";
import type {UserInfoType} from "~/types/UserType";
import {deepEqual} from "~/utils";
const layout = ref<IGridItem[]>([])
const presetLayouts = ref<Layouts>(<Layouts>{})
const {width, height} = useWindowSize()
const el = ref(null)
const {width: gridWidth, height: gridHeight} = useElementSize(el)
const mainLayoutStore = useMainLayoutStore()
const loadStore = useLoadStore()
const dataStore = useDataStore()
onMounted(() => {
layout.value = mainLayoutStore.LayoutsConfig.lg
presetLayouts.value = mainLayoutStore.LayoutsConfig
console.log(layout.value)
console.log(presetLayouts.value)
})
const visible = ref(false)
const cardVisible = ref(false)
const items = ref([
{
label: '添加图表',
icon: 'pi pi-chart-line',
command: () => {
visible.value = true
}
},
{
label: '添加信息卡片',
icon: 'pi pi-plus',
command: () => {
cardVisible.value = true
}
},
{
label: 'Delete',
icon: 'pi pi-trash',
command: () => {
toast.add({severity: 'error', summary: 'Delete', detail: 'Data Deleted'});
}
},
{
label: 'Upload',
icon: 'pi pi-upload',
command: () => {
router.push('/fileupload');
}
},
{
label: 'Vue Website',
icon: 'pi pi-external-link',
command: () => {
window.location.href = 'https://vuejs.org/'
}
}
])
const layoutChangedEvent = _.throttle((newLayout: IGridItem[]) => {
let breakPoint = 'lg';
//计算对应的breakPoint
if (gridWidth.value <= 1200) {
breakPoint = 'md';
}
if (gridWidth.value <= 992) {
breakPoint = 'sm';
}
if (gridWidth.value <= 768) {
breakPoint = 'xs';
}
mainLayoutStore.LayoutsConfig[breakPoint] = newLayout;
presetLayouts.value[breakPoint] = newLayout;
}, 500)
onMounted(() => {
$fetch('/Api/User/GetLayoutConfig', {
method: 'POST',
responseType: "json",
body: {
layout: JSON.stringify(mainLayoutStore.LayoutsConfig),
},
headers: {
'Authorization': 'Bearer ' + useCookie('token').value
},
baseURL: useRuntimeConfig().public.baseUrl,
}).then((res) => {
if (res === 'null') return;
const data = JSON.parse(res as string) as Layouts
console.log(data)
mainLayoutStore.LayoutsConfig = data;
presetLayouts.value = data;
if (loadStore.LayoutLoad) return;
loadStore.LayoutLoad = true
window.location.reload()
})
})
watchDebounced(
layout,
() => {
$fetch('/Api/User/PutLayoutConfig', {
method: 'PUT',
body: {
Layout: JSON.stringify(mainLayoutStore.LayoutsConfig),
},
headers: {
'Authorization': 'Bearer ' + useCookie('token').value
},
baseURL: useRuntimeConfig().public.baseUrl,
}).catch((err) => {
console.log(err)
})
},
{debounce: 15000, maxWait: 60000}
)
</script>
<template>
<div class="main-grid-layout">
<UseDraggable v-slot="{x,y}"
:initial-value="{ x: width-150, y: height-350 }"
class="draggable-action"
>
<SpeedDial :model="items"
:radius="80"
:tooltipOptions="{ position: 'right' }"
type="circle"/>
</UseDraggable>
<Dialog
v-model:visible="visible"
:pt="{
root: {
style:'border:unset;background-color:unset;'
},
mask: {
style: 'backdrop-filter: blur(20px)'
}
}"
modal
>
<template #container="{ closeCallback }">
<SettingCard :close-callback="closeCallback"/>
</template>
</Dialog>
<Dialog
v-model:visible="cardVisible"
:pt="{
root: {
style:'border:unset;background-color:unset;'
},
mask: {
style: 'backdrop-filter: blur(20px)'
}
}"
modal
>
<template #container="{ closeCallback }">
<AddCard :close-callback="closeCallback"/>
</template>
</Dialog>
<GridLayout
ref="el"
v-model:layout="layout"
:breakpoints="{ lg: 1200, md: 996, sm: 768, xs: 480, xxs: 0 }"
:col-num="16"
:cols="{ lg: 12, md: 10, sm: 6, xs: 4, xxs: 2 }"
:responsive-layouts="presetLayouts"
:row-height="30"
is-draggable
is-resizables
responsive
use-css-transforms
vertical-compact
@layoutUpdated="layoutChangedEvent"
>
<GridItem
v-for="item in layout"
:key="item.i"
:h="item.h"
:i="item.i"
:w="item.w"
:x="item.x"
:y="item.y"
drag-allow-from=".vue-draggable-handle"
drag-ignore-from=".no-drag"
>
<IChart v-if="item.type==='chart'&&item.serverValues&&item.selectChart" :id="String(item.i)"
:chart="item.selectChart"
:title="item.cardConfig?.['name'].value??'默认标题'" :values="item.serverValues"/>
<ICard v-if="item.type==='card'&&item.selectCard" :id="String(item.i)" :card-id="item.selectCard"/>
</GridItem>
</GridLayout>
</div>
</template>
<style lang="scss" scoped>
.main-grid-layout {
//min-width: 950px;
}
.draggable-action {
background: red;
position: fixed;
z-index: 100;
}
.vgl-layout {
margin: -10px;
}
</style>