diff --git a/ui/console-src/modules/dashboard/components/ActionButton.vue b/ui/console-src/modules/dashboard/components/ActionButton.vue new file mode 100644 index 000000000..ee0b765fd --- /dev/null +++ b/ui/console-src/modules/dashboard/components/ActionButton.vue @@ -0,0 +1,8 @@ + + + + + + diff --git a/ui/console-src/modules/dashboard/components/WidgetEditableItem.vue b/ui/console-src/modules/dashboard/components/WidgetEditableItem.vue index cc9a25ab1..46eb4bc02 100644 --- a/ui/console-src/modules/dashboard/components/WidgetEditableItem.vue +++ b/ui/console-src/modules/dashboard/components/WidgetEditableItem.vue @@ -6,6 +6,7 @@ import type { DashboardWidgetDefinition, } from "@halo-dev/console-shared"; import { computed, inject, ref, type ComputedRef } from "vue"; +import ActionButton from "./ActionButton.vue"; import WidgetConfigFormModal from "./WidgetConfigFormModal.vue"; const props = defineProps<{ @@ -61,21 +62,18 @@ function handleSaveConfig(config: Record) { @update:config="handleSaveConfig" /> - - - - - - + + + + + { :width="1380" :layer-closable="true" :title="$t('core.dashboard_designer.widgets_modal.title')" + mount-to-body @close="emit('close')" > +import WidgetCard from "@console/modules/dashboard/components/WidgetCard.vue"; +import { IconSettings, VButton } from "@halo-dev/components"; +import { nextTick, onMounted, onUnmounted, ref } from "vue"; +import StackWidgetConfigModal from "./StackWidgetConfigModal.vue"; +import IndexIndicator from "./components/IndexIndicator.vue"; +import WidgetViewItem from "./components/WidgetViewItem.vue"; +import type { StackWidgetConfig } from "./types"; + +const props = defineProps<{ + config: StackWidgetConfig; + editMode?: boolean; + previewMode?: boolean; +}>(); + +const emit = defineEmits<{ + (e: "update:config", config: StackWidgetConfig): void; +}>(); + +const configVisible = ref(false); + +const index = ref(0); + +function handleNavigate(direction: -1 | 1) { + const targetIndex = index.value + direction; + + if (targetIndex < 0) { + index.value = props.config.widgets.length - 1; + } else if (targetIndex >= props.config.widgets.length) { + index.value = 0; + } else { + index.value = targetIndex; + } +} + +// auto play +const autoPlayInterval = ref(null); + +function startAutoPlay() { + if (!props.config.auto_play || configVisible.value) { + return; + } + if (autoPlayInterval.value) { + clearInterval(autoPlayInterval.value); + } + autoPlayInterval.value = setInterval(() => { + handleNavigate(1); + }, props.config.auto_play_interval || 3000); +} + +function stopAutoPlay() { + if (autoPlayInterval.value) { + clearInterval(autoPlayInterval.value); + autoPlayInterval.value = null; + } +} + +onMounted(() => { + startAutoPlay(); +}); + +onUnmounted(() => { + stopAutoPlay(); +}); + +async function handleSave(config: StackWidgetConfig) { + emit("update:config", config); + configVisible.value = false; + + await nextTick(); + + if (config.auto_play) { + startAutoPlay(); + } else { + stopAutoPlay(); + } +} + + + + + + {{ + $t( + "core.dashboard.widgets.presets.stack.operations.add_widget.button" + ) + }} + + + + + + + + {{ $t("core.dashboard.widgets.presets.stack.title") }} + + + + + + + + + + + + + + + + diff --git a/ui/console-src/modules/dashboard/widgets/presets/core/stack/StackWidgetConfigModal.vue b/ui/console-src/modules/dashboard/widgets/presets/core/stack/StackWidgetConfigModal.vue new file mode 100644 index 000000000..c4f8f8877 --- /dev/null +++ b/ui/console-src/modules/dashboard/widgets/presets/core/stack/StackWidgetConfigModal.vue @@ -0,0 +1,205 @@ + + + + + + + + + + {{ + $t( + "core.dashboard.widgets.presets.stack.config_modal.fields.widgets.label" + ) + }} + + + + + + + + + + + + + + + + {{ $t("core.common.buttons.add") }} + + + + + + + + + + {{ $t("core.common.buttons.save") }} + + + {{ $t("core.common.buttons.cancel") }} + + + + + + + diff --git a/ui/console-src/modules/dashboard/widgets/presets/core/stack/components/IndexIndicator.vue b/ui/console-src/modules/dashboard/widgets/presets/core/stack/components/IndexIndicator.vue new file mode 100644 index 000000000..0c3f005d3 --- /dev/null +++ b/ui/console-src/modules/dashboard/widgets/presets/core/stack/components/IndexIndicator.vue @@ -0,0 +1,53 @@ + + + + + + + + + + + + + + + + + + + diff --git a/ui/console-src/modules/dashboard/widgets/presets/core/stack/components/WidgetEditableItem.vue b/ui/console-src/modules/dashboard/widgets/presets/core/stack/components/WidgetEditableItem.vue new file mode 100644 index 000000000..201be8d33 --- /dev/null +++ b/ui/console-src/modules/dashboard/widgets/presets/core/stack/components/WidgetEditableItem.vue @@ -0,0 +1,84 @@ + + + + + + + + + + + + + + + + diff --git a/ui/console-src/modules/dashboard/widgets/presets/core/stack/components/WidgetViewItem.vue b/ui/console-src/modules/dashboard/widgets/presets/core/stack/components/WidgetViewItem.vue new file mode 100644 index 000000000..0b6d54368 --- /dev/null +++ b/ui/console-src/modules/dashboard/widgets/presets/core/stack/components/WidgetViewItem.vue @@ -0,0 +1,31 @@ + + + + + + + diff --git a/ui/console-src/modules/dashboard/widgets/presets/core/stack/types.ts b/ui/console-src/modules/dashboard/widgets/presets/core/stack/types.ts new file mode 100644 index 000000000..fdb74e7e5 --- /dev/null +++ b/ui/console-src/modules/dashboard/widgets/presets/core/stack/types.ts @@ -0,0 +1,11 @@ +export interface SimpleWidget { + i: string; + id: string; + config?: Record; +} + +export interface StackWidgetConfig { + auto_play?: boolean; + auto_play_interval?: number; + widgets: SimpleWidget[]; +} diff --git a/ui/src/locales/_missing_translations_es.yaml b/ui/src/locales/_missing_translations_es.yaml index ca355e77d..b7fe0c3a9 100644 --- a/ui/src/locales/_missing_translations_es.yaml +++ b/ui/src/locales/_missing_translations_es.yaml @@ -38,6 +38,22 @@ core: label: Enabled Items pending_comments: title: Pending Comments + stack: + title: Widget Stack + operations: + add_widget: + button: Add Widget + config_modal: + title: Widget Stack Config + fields: + auto_play: + label: Auto play + auto_play_interval: + label: Auto play interval + widgets: + label: Widgets + toast: + nest_warning: You cannot add a stack widget to a stack widget dashboard_designer: title: Edit Dashboard actions: diff --git a/ui/src/locales/en.yaml b/ui/src/locales/en.yaml index cb2ae898e..c736058b7 100644 --- a/ui/src/locales/en.yaml +++ b/ui/src/locales/en.yaml @@ -108,6 +108,22 @@ core: title: Pending Comments views_stats: title: Visits + stack: + title: Widget Stack + operations: + add_widget: + button: Add Widget + config_modal: + title: Widget Stack Config + fields: + auto_play: + label: Auto play + auto_play_interval: + label: Auto play interval + widgets: + label: Widgets + toast: + nest_warning: You cannot add a stack widget to a stack widget dashboard_designer: title: Edit Dashboard actions: diff --git a/ui/src/locales/zh-CN.yaml b/ui/src/locales/zh-CN.yaml index 6f8c5bc6e..8dd27e471 100644 --- a/ui/src/locales/zh-CN.yaml +++ b/ui/src/locales/zh-CN.yaml @@ -104,6 +104,22 @@ core: title: 浏览量 pending_comments: title: 新评论 + stack: + title: 堆叠部件 + operations: + add_widget: + button: 添加部件 + config_modal: + title: 堆叠部件配置 + fields: + auto_play: + label: 自动切换 + auto_play_interval: + label: 自动切换间隔 + widgets: + label: 部件 + toast: + nest_warning: 不能将堆叠部件添加到堆叠部件中 dashboard_designer: title: 编辑仪表盘 actions: diff --git a/ui/src/locales/zh-TW.yaml b/ui/src/locales/zh-TW.yaml index 1f8d9c768..583dd032e 100644 --- a/ui/src/locales/zh-TW.yaml +++ b/ui/src/locales/zh-TW.yaml @@ -104,6 +104,22 @@ core: title: 瀏覽量 pending_comments: title: 新評論 + stack: + title: 堆疊部件 + operations: + add_widget: + button: 添加部件 + config_modal: + title: 堆疊部件配置 + fields: + auto_play: + label: 自動切換 + auto_play_interval: + label: 自動切換間隔 + widgets: + label: 部件 + toast: + nest_warning: 不能將堆疊部件添加到堆疊部件中 dashboard_designer: title: 編輯儀表盤 actions: