feat: 动态阴影显示

This commit is contained in:
马军
2026-05-12 15:37:35 +08:00
parent 48bf4aa989
commit 0870598fce
3 changed files with 106 additions and 58 deletions

View File

@@ -37,7 +37,13 @@
</n-tabs> </n-tabs>
<!-- 编辑 --> <!-- 编辑 -->
<n-tabs v-if="selectTarget" v-model:value="tabsSelect" class="tabs-box" size="small" type="segment"> <n-tabs
v-if="selectTarget"
v-model:value="tabsSelect"
class="tabs-box"
size="small"
type="segment"
>
<n-tab-pane <n-tab-pane
v-for="item in selectTarget.isGroup ? chartsDefaultTabList : chartsTabList" v-for="item in selectTarget.isGroup ? chartsDefaultTabList : chartsTabList"
:key="item.key" :key="item.key"
@@ -62,104 +68,107 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { ref, toRefs, watch, computed } from 'vue' import { ref, toRefs, watch, computed } from "vue";
import { icon } from '@/plugins' import { icon } from "@/plugins";
import { loadAsyncComponent } from '@/utils' import { loadAsyncComponent } from "@/utils";
import { ContentBox } from '../ContentBox/index' import { ContentBox } from "../ContentBox/index";
import { TabsEnum } from './index.d' import { TabsEnum } from "./index.d";
import { useChartLayoutStore } from '@/store/modules/chartLayoutStore/chartLayoutStore' import { useChartLayoutStore } from "@/store/modules/chartLayoutStore/chartLayoutStore";
import { ChartLayoutStoreEnum } from '@/store/modules/chartLayoutStore/chartLayoutStore.d' import { ChartLayoutStoreEnum } from "@/store/modules/chartLayoutStore/chartLayoutStore.d";
import { useChartEditStore } from '@/store/modules/chartEditStore/chartEditStore' import { useChartEditStore } from "@/store/modules/chartEditStore/chartEditStore";
const { getDetails } = toRefs(useChartLayoutStore()) const { getDetails } = toRefs(useChartLayoutStore());
const { setItem } = useChartLayoutStore() const { setItem } = useChartLayoutStore();
const chartEditStore = useChartEditStore() const chartEditStore = useChartEditStore();
const { ConstructIcon, FlashIcon, DesktopOutlineIcon, LeafIcon, RocketIcon } = icon.ionicons5 const { ConstructIcon, FlashIcon, DesktopOutlineIcon, LeafIcon, RocketIcon } = icon.ionicons5;
const ContentEdit = loadAsyncComponent(() => import('../ContentEdit/index.vue')) const ContentEdit = loadAsyncComponent(() => import("../ContentEdit/index.vue"));
const CanvasPage = loadAsyncComponent(() => import('./components/CanvasPage/index.vue')) const CanvasPage = loadAsyncComponent(() => import("./components/CanvasPage/index.vue"));
const ChartSetting = loadAsyncComponent(() => import('./components/ChartSetting/index.vue')) const ChartSetting = loadAsyncComponent(() => import("./components/ChartSetting/index.vue"));
const ChartData = loadAsyncComponent(() => import('./components/ChartData/index.vue')) const ChartData = loadAsyncComponent(() => import("./components/ChartData/index.vue"));
const ChartEvent = loadAsyncComponent(() => import('./components/ChartEvent/index.vue')) const ChartEvent = loadAsyncComponent(() => import("./components/ChartEvent/index.vue"));
const ChartAnimation = loadAsyncComponent(() => import('./components/ChartAnimation/index.vue')) const ChartAnimation = loadAsyncComponent(() => import("./components/ChartAnimation/index.vue"));
const collapsed = ref<boolean>(getDetails.value) const collapsed = ref<boolean>(getDetails.value);
const tabsSelect = ref<TabsEnum>(TabsEnum.CHART_SETTING) const tabsSelect = ref<TabsEnum>(TabsEnum.CHART_SETTING);
const collapsedHandle = () => { const collapsedHandle = () => {
collapsed.value = true collapsed.value = true;
setItem(ChartLayoutStoreEnum.DETAILS, true) setItem(ChartLayoutStoreEnum.DETAILS, true);
} };
const expandHandle = () => { const expandHandle = () => {
collapsed.value = false collapsed.value = false;
setItem(ChartLayoutStoreEnum.DETAILS, false) setItem(ChartLayoutStoreEnum.DETAILS, false);
} };
const selectTarget = computed(() => { const selectTarget = computed(() => {
const selectId = chartEditStore.getTargetChart.selectId const selectId = chartEditStore.getTargetChart.selectId;
// 排除多个 // 排除多个
if (selectId.length !== 1) return undefined if (selectId.length !== 1) return undefined;
const target = chartEditStore.componentList[chartEditStore.fetchTargetIndex()] const target = chartEditStore.componentList[chartEditStore.fetchTargetIndex()];
if (target?.isGroup) { if (target?.isGroup) {
// eslint-disable-next-line vue/no-side-effects-in-computed-properties // eslint-disable-next-line vue/no-side-effects-in-computed-properties
tabsSelect.value = TabsEnum.CHART_SETTING tabsSelect.value = TabsEnum.CHART_SETTING;
} }
return target return target;
}) });
watch(getDetails, newData => { watch(getDetails, (newData) => {
if (newData) { if (newData) {
collapsedHandle() collapsedHandle();
} else { } else {
expandHandle() expandHandle();
} }
}) });
// 页面设置 // 页面设置
const globalTabList = [ const globalTabList = [
{ {
key: TabsEnum.PAGE_SETTING, key: TabsEnum.PAGE_SETTING,
title: '页面配置', title: "页面配置",
icon: DesktopOutlineIcon, icon: DesktopOutlineIcon,
render: CanvasPage render: CanvasPage,
} },
] ];
const chartsDefaultTabList = [ const chartsDefaultTabList = [
{ {
key: TabsEnum.CHART_SETTING, key: TabsEnum.CHART_SETTING,
title: '定制', title: "定制",
icon: ConstructIcon, icon: ConstructIcon,
render: ChartSetting render: ChartSetting,
}, },
{ {
key: TabsEnum.CHART_ANIMATION, key: TabsEnum.CHART_ANIMATION,
title: '动画', title: "动画",
icon: LeafIcon, icon: LeafIcon,
render: ChartAnimation render: ChartAnimation,
} },
] ];
const chartsTabList = [ const chartsTabList = [
...chartsDefaultTabList, ...chartsDefaultTabList,
{ {
key: TabsEnum.CHART_DATA, key: TabsEnum.CHART_DATA,
title: '数据', title: "数据",
icon: FlashIcon, icon: FlashIcon,
render: ChartData render: ChartData,
}, },
{ {
key: TabsEnum.CHART_EVENT, key: TabsEnum.CHART_EVENT,
title: '事件', title: "事件",
icon: RocketIcon, icon: RocketIcon,
render: ChartEvent render: ChartEvent,
} },
] ];
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
::v-deep .n-layout-toggle-bar {
z-index: 9;
}
@include go(content-configurations) { @include go(content-configurations) {
overflow: hidden; overflow: hidden;
.tabs-box { .tabs-box {

View File

@@ -30,6 +30,7 @@ import type { CSSProperties } from 'vue'
import { listen } from 'dom-helpers' import { listen } from 'dom-helpers'
import { useDesignStore } from '@/store/modules/designStore/designStore' import { useDesignStore } from '@/store/modules/designStore/designStore'
import { useChartEditStore } from '@/store/modules/chartEditStore/chartEditStore' import { useChartEditStore } from '@/store/modules/chartEditStore/chartEditStore'
import { CreateComponentGroupType } from '@/packages/index.d'
import throttle from 'lodash/throttle' import throttle from 'lodash/throttle'
const chartEditStore = useChartEditStore() const chartEditStore = useChartEditStore()
@@ -71,7 +72,7 @@ const paletteStyle = computed(() => {
longfgColor: '#4d4d4d', longfgColor: '#4d4d4d',
shortfgColor: '#4d4d4d', shortfgColor: '#4d4d4d',
fontColor: '#4d4d4d', fontColor: '#4d4d4d',
shadowColor: '#18181c', shadowColor: '#232324',
borderColor: '#18181c', borderColor: '#18181c',
cornerActiveColor: '#18181c' cornerActiveColor: '#18181c'
} }
@@ -89,13 +90,50 @@ const canvasStyle = computed((): CSSProperties => {
height: `${height.value}px` height: `${height.value}px`
} }
}) })
// 根据 id 查找组件(含分组内子组件)
const findComponentById = (id: string) => {
for (const item of chartEditStore.getComponentList) {
if (item.id === id) return item
if (item.isGroup) {
const child = (item as CreateComponentGroupType).groupList.find(c => c.id === id)
if (child) return child
}
}
return null
}
// 阴影(画布在标尺坐标系中的位置,从 thick 偏移开始) // 阴影(画布在标尺坐标系中的位置,从 thick 偏移开始)
const shadow = computed(() => { const shadow = computed(() => {
const selectIds = chartEditStore.getTargetChart.selectId
if (!selectIds.length) {
return { x: 0, y: 0, width: 0, height: 0 }
}
let minX = Infinity
let minY = Infinity
let maxX = -Infinity
let maxY = -Infinity
for (const id of selectIds) {
const comp = findComponentById(id)
if (comp) {
const { x, y, w, h } = comp.attr
minX = Math.min(minX, x)
minY = Math.min(minY, y)
maxX = Math.max(maxX, x + w)
maxY = Math.max(maxY, y + h)
}
}
if (minX === Infinity) {
return { x: 0, y: 0, width: 0, height: 0 }
}
return { return {
x: 0, x: minX,
y: 0, y: minY,
width: 200, width: maxX - minX,
height: 200 height: maxY - minY
} }
}) })

View File

@@ -223,6 +223,7 @@ $asideBottom: 70px;
@include go('chart-edit-tools') { @include go('chart-edit-tools') {
@extend .go-background-filter; @extend .go-background-filter;
z-index: 9;
position: absolute; position: absolute;
display: flex; display: flex;
justify-content: space-around; justify-content: space-around;