123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266 |
- <script setup lang="ts">
- import { computed, onUnmounted, ref, watch } from 'vue';
- import { useRequest } from '@/hooks/request';
- import { t } from '@/i18n';
- import { getGroupModuleInfo } from '@/api';
- import { addUnit } from '@/utils';
- import { VisualModuleType } from '@/constants';
- import AdvancedSettings from './AdvancedSettings.vue';
- import AIOptimization from './AIOptimization.vue';
- import AIStartStop from './AIStartStop.vue';
- import type { Component, CSSProperties } from 'vue';
- import type { GroupModuleInfo } from '@/types';
- interface Props {
- info: GroupModuleInfo;
- }
- const props = defineProps<Props>();
- const { handleRequest } = useRequest();
- const moduleInfo = ref<GroupModuleInfo>(props.info);
- let moduleTimer: number | undefined;
- const getModuleInfo = () => {
- clearTimeout(moduleTimer);
- handleRequest(async () => {
- moduleInfo.value = await getGroupModuleInfo({
- groupId: props.info.groupId,
- moduleType: VisualModuleType.Module2D,
- });
- });
- moduleTimer = window.setTimeout(getModuleInfo, 3000);
- };
- interface ConfigItem {
- label: string;
- component: Component;
- style?: CSSProperties;
- }
- const activeConfigIndex = ref(-1);
- const configs = computed<ConfigItem[]>(() => {
- return [
- { label: t('realTimeMonitor.aiStartStop'), component: AIStartStop },
- { label: t('realTimeMonitor.aiOptimization'), component: AIOptimization },
- {
- label: t('common.advancedSettings'),
- component: AdvancedSettings,
- style: {
- paddingBlock: addUnit(16),
- },
- },
- ];
- });
- const showCtrlPanel = computed(() => {
- return activeConfigIndex.value !== -1;
- });
- watch(activeConfigIndex, () => {
- // 仅打开智能启停面板时定时获取数据
- if (activeConfigIndex.value !== 0) {
- clearTimeout(moduleTimer);
- } else {
- getModuleInfo();
- }
- });
- const toggleConfig = (index: number) => {
- if (activeConfigIndex.value === index) {
- closeCtrlPanel();
- } else {
- activeConfigIndex.value = index;
- }
- };
- const closeCtrlPanel = () => {
- activeConfigIndex.value = -1;
- };
- onUnmounted(() => {
- clearTimeout(moduleTimer);
- });
- defineExpose({
- closeCtrlPanel,
- });
- </script>
- <template>
- <div class="ctrl-button-conatiner top-1/2 flex flex-col -translate-y-1/2" @click.stop>
- <div
- :class="['ctrl-button', { 'ctrl-button-active': activeConfigIndex === index }]"
- v-for="(item, index) in configs"
- :key="index"
- :style="item.style"
- @click="toggleConfig(index)"
- >
- <div class="corner-border lt-border"></div>
- <div class="corner-border rt-border"></div>
- <div class="corner-border lb-border"></div>
- <div class="corner-border rb-border"></div>
- {{ item.label }}
- </div>
- <div class="ctrl-panel" v-if="showCtrlPanel">
- <div class="ctrl-panel-title">{{ configs[activeConfigIndex].label }}</div>
- <component :is="configs[activeConfigIndex].component" :info="moduleInfo" />
- </div>
- </div>
- </template>
- <style lang="scss" scoped>
- .ctrl-button-conatiner {
- position: fixed;
- right: 16px;
- margin-inline: 16px;
- }
- .ctrl-button {
- position: relative;
- width: 32px;
- height: 96px;
- padding: 8px;
- font-size: 14px;
- line-height: 16px;
- color: #fff;
- cursor: pointer;
- background-color: #323a47;
- border: 1px solid rgb(134 141 152 / 40%);
- box-shadow: inset 0 0 3px 0 rgb(255 255 255 / 24%);
- & + & {
- margin-top: 16px;
- }
- }
- .ctrl-button-active {
- background-color: var(--antd-color-primary);
- border: 1px solid rgb(255 255 255 / 50%);
- box-shadow: inset 0 0 6px 1px rgb(255 255 255 / 70%);
- .corner-border {
- --corner-border-color: #fff;
- }
- }
- .ctrl-panel {
- position: absolute;
- top: -147px;
- right: 48px;
- width: 464px;
- height: 630px;
- padding-block: 24px;
- background: rgb(30 37 48 / 50%);
- backdrop-filter: blur(12px);
- border: 1px solid rgb(255 255 255 / 24%);
- border-radius: 8px;
- }
- .ctrl-panel-title {
- margin-bottom: 16px;
- margin-left: 24px;
- font-size: 16px;
- font-weight: 500;
- line-height: 22px;
- color: #fff;
- }
- .ctrl-panel-scroll-container {
- height: calc(100% - 38px);
- padding-left: 24px;
- overflow: hidden;
- }
- :deep(.ctrl-panel-scroll-content) {
- height: calc(100% - 52px);
- padding-right: 20px;
- margin-right: 4px;
- overflow: hidden auto;
- &::-webkit-scrollbar {
- width: 6px;
- height: 6px;
- }
- &::-webkit-scrollbar-thumb {
- cursor: pointer;
- background: #55585e;
- border-radius: 3px;
- }
- &::-webkit-scrollbar-corner {
- display: none;
- }
- }
- :deep(.ant-segmented) {
- padding: 4px;
- margin-bottom: 16px;
- color: #fff;
- background-color: rgb(255 255 255 / 8%);
- border-radius: 4px;
- .ant-segmented-group > div {
- background-color: var(--antd-color-primary);
- }
- .ant-segmented-item-label {
- display: flex;
- align-items: center;
- padding-inline: 0;
- span {
- padding-inline: 12px;
- }
- }
- .ant-segmented-item-selected {
- color: #fff;
- background-color: var(--antd-color-primary);
- box-shadow: none;
- }
- .ant-segmented-item {
- + .ant-segmented-item {
- margin-left: 8px;
- }
- &:hover:not(.ant-segmented-item-selected, .ant-segmented-item-disabled) {
- color: #fff;
- &::after {
- background-color: var(--antd-color-primary-opacity-15);
- }
- }
- }
- .ant-segmented-item-disabled,
- .ant-segmented-item-disabled:hover,
- .ant-segmented-item-disabled:focus {
- color: rgb(255 255 255 / 25%);
- }
- }
- :deep(.ant-switch) {
- background: rgb(255 255 255 / 25%);
- &:hover:not(.ant-switch-disabled) {
- background: rgb(255 255 255 / 45%);
- }
- &.ant-switch-checked {
- background: var(--antd-color-primary);
- &:hover:not(.ant-switch-disabled) {
- background: var(--antd-color-primary-hover);
- }
- }
- }
- </style>
|