mirror of
https://github.com/1Panel-dev/1Panel.git
synced 2026-09-22 08:00:53 +00:00
feat: Add carousel settings to overview page (#11853)
This commit is contained in:
@@ -30,6 +30,7 @@ func Init() {
|
||||
migrations.UpdateXpackHideMenuSort,
|
||||
migrations.AdjustXpackNode,
|
||||
migrations.UpdateAiAgentsMenu,
|
||||
migrations.AddDashboardCarouselSetting,
|
||||
})
|
||||
if err := m.Migrate(); err != nil {
|
||||
global.LOG.Error(err)
|
||||
|
||||
@@ -591,13 +591,36 @@ var AddUpgradeBackupCopies = &gormigrate.Migration{
|
||||
}
|
||||
|
||||
var AddScriptSync = &gormigrate.Migration{
|
||||
ID: "20250916-add-script-sync",
|
||||
Migrate: func(tx *gorm.DB) error {
|
||||
if err := tx.Create(&model.Setting{Key: "ScriptSync", Value: constant.StatusEnable}).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
},
|
||||
ID: "20250916-add-script-sync",
|
||||
Migrate: func(tx *gorm.DB) error {
|
||||
if err := tx.Create(&model.Setting{Key: "ScriptSync", Value: constant.StatusEnable}).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
},
|
||||
}
|
||||
|
||||
var AddDashboardCarouselSetting = &gormigrate.Migration{
|
||||
ID: "20260210-add-dashboard-carousel-setting",
|
||||
Migrate: func(tx *gorm.DB) error {
|
||||
var addSettingsIfMissing = func(tx *gorm.DB, key, value string) error {
|
||||
var setting model.Setting
|
||||
if err := tx.Where("key = ?", key).First(&setting).Error; err != nil {
|
||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
return tx.Create(&model.Setting{Key: key, Value: value}).Error
|
||||
}
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
if err := addSettingsIfMissing(tx, "DashboardMemoVisible", constant.StatusEnable); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := addSettingsIfMissing(tx, "DashboardSimpleNodeVisible", constant.StatusEnable); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
},
|
||||
}
|
||||
|
||||
var UpdateXpackHideMenuSort = &gormigrate.Migration{
|
||||
|
||||
@@ -34,6 +34,8 @@ export namespace Setting {
|
||||
allowIPs: string;
|
||||
bindDomain: string;
|
||||
securityEntrance: string;
|
||||
dashboardMemoVisible: string;
|
||||
dashboardSimpleNodeVisible: string;
|
||||
expirationDays: number;
|
||||
expirationTime: string;
|
||||
complexityVerification: string;
|
||||
|
||||
@@ -472,7 +472,8 @@ const message = {
|
||||
disk: 'Disk',
|
||||
|
||||
memo: 'Memo',
|
||||
memoPlaceholder: 'Click to edit memo...',
|
||||
memoPlaceholder: 'Double-click to edit memo content...',
|
||||
carouselSetting: 'Carousel settings',
|
||||
tooltipSensitiveInfo: 'Show/Hide sensitive info',
|
||||
},
|
||||
tabs: {
|
||||
|
||||
@@ -474,7 +474,8 @@ const message = {
|
||||
networkCard: 'Tarjeta de red',
|
||||
disk: 'Disco',
|
||||
memo: 'Memo',
|
||||
memoPlaceholder: 'Haga clic para editar el memo...',
|
||||
memoPlaceholder: 'Doble clic para editar el memo...',
|
||||
carouselSetting: 'Configuración del carrusel',
|
||||
tooltipSensitiveInfo: 'Mostrar/Ocultar información sensible',
|
||||
},
|
||||
tabs: {
|
||||
|
||||
@@ -458,7 +458,8 @@ const message = {
|
||||
networkCard: 'ネットワークカード',
|
||||
disk: 'ディスク',
|
||||
memo: 'メモ',
|
||||
memoPlaceholder: 'クリックしてメモを編集...',
|
||||
memoPlaceholder: 'ダブルクリックしてメモを編集...',
|
||||
carouselSetting: 'カルーセル設定',
|
||||
tooltipSensitiveInfo: '機密情報を表示/非表示',
|
||||
},
|
||||
tabs: {
|
||||
|
||||
@@ -461,7 +461,8 @@ const message = {
|
||||
networkCard: '네트워크 카드',
|
||||
disk: '디스크',
|
||||
memo: '메모',
|
||||
memoPlaceholder: '클릭하여 메모를 편집...',
|
||||
memoPlaceholder: '메모를 편집하려면 두 번 클릭...',
|
||||
carouselSetting: '캐러셀 설정',
|
||||
tooltipSensitiveInfo: '민감한 정보 표시/숨기기',
|
||||
},
|
||||
tabs: {
|
||||
|
||||
@@ -467,7 +467,8 @@ const message = {
|
||||
networkCard: 'Kad rangkaian',
|
||||
disk: 'Disk',
|
||||
memo: 'Catatan',
|
||||
memoPlaceholder: 'Klik untuk mengedit catatan...',
|
||||
memoPlaceholder: 'Dwiklik untuk mengedit memo...',
|
||||
carouselSetting: 'Tetapan karusel',
|
||||
tooltipSensitiveInfo: 'Tunjuk/Sembunyikan maklumat sensitif',
|
||||
},
|
||||
tabs: {
|
||||
|
||||
@@ -465,7 +465,8 @@ const message = {
|
||||
networkCard: 'Placa de rede',
|
||||
disk: 'Disco',
|
||||
memo: 'Memo',
|
||||
memoPlaceholder: 'Clique para editar o memo...',
|
||||
memoPlaceholder: 'Clique duas vezes para editar o memo...',
|
||||
carouselSetting: 'Configuração do carrossel',
|
||||
tooltipSensitiveInfo: 'Mostrar/Ocultar informações sensíveis',
|
||||
},
|
||||
tabs: {
|
||||
|
||||
@@ -462,7 +462,8 @@ const message = {
|
||||
networkCard: 'Интерфейс',
|
||||
disk: 'Диск',
|
||||
memo: 'Заметка',
|
||||
memoPlaceholder: 'Нажмите, чтобы редактировать заметку...',
|
||||
memoPlaceholder: 'Дважды щелкните, чтобы редактировать заметку...',
|
||||
carouselSetting: 'Настройки карусели',
|
||||
tooltipSensitiveInfo: 'Показать/скрыть конфиденциальную информацию',
|
||||
},
|
||||
tabs: {
|
||||
|
||||
@@ -473,7 +473,8 @@ const message = {
|
||||
networkCard: 'Ağ kartı',
|
||||
disk: 'Disk',
|
||||
memo: 'Not',
|
||||
memoPlaceholder: 'Notu düzenlemek için tıklayın...',
|
||||
memoPlaceholder: 'Notu düzenlemek için çift tıklayın...',
|
||||
carouselSetting: 'Karusel ayarları',
|
||||
tooltipSensitiveInfo: 'Hassas bilgileri göster/gizle',
|
||||
},
|
||||
tabs: {
|
||||
|
||||
@@ -456,7 +456,8 @@ const message = {
|
||||
networkCard: '網卡',
|
||||
disk: '磁碟',
|
||||
memo: '備忘錄',
|
||||
memoPlaceholder: '點擊編輯備忘錄內容...',
|
||||
memoPlaceholder: '雙擊可編輯備忘錄內容...',
|
||||
carouselSetting: '輪播設定',
|
||||
tooltipSensitiveInfo: '顯示/隱藏敏感資訊',
|
||||
},
|
||||
tabs: {
|
||||
|
||||
@@ -458,7 +458,8 @@ const message = {
|
||||
disk: '磁盘',
|
||||
|
||||
memo: '备忘录',
|
||||
memoPlaceholder: '点击编辑备忘录内容...',
|
||||
memoPlaceholder: '双击可编辑备忘录内容...',
|
||||
carouselSetting: '轮播设置',
|
||||
tooltipSensitiveInfo: '显示/隐藏敏感信息',
|
||||
},
|
||||
tabs: {
|
||||
|
||||
@@ -166,6 +166,7 @@
|
||||
<el-col :xs="24" :sm="24" :md="8" :lg="8" :xl="8">
|
||||
<el-carousel
|
||||
class="my-carousel"
|
||||
:class="{ 'no-indicator': carouselItemCount <= 1 }"
|
||||
:key="simpleNodes.length"
|
||||
height="368px"
|
||||
indicator-position=""
|
||||
@@ -174,6 +175,49 @@
|
||||
<el-carousel-item key="systemInfo">
|
||||
<CardWithHeader :header="$t('home.systemInfo')">
|
||||
<template #header-r>
|
||||
<el-popover
|
||||
popper-class="dashboard-carousel-popover"
|
||||
placement="bottom"
|
||||
:title="$t('home.carouselSetting')"
|
||||
width="220"
|
||||
trigger="click"
|
||||
>
|
||||
<div class="dashboard-carousel-setting">
|
||||
<div class="setting-item mt-2">
|
||||
<span>{{ $t('home.systemInfo') }}</span>
|
||||
<div class="mr-4">-</div>
|
||||
</div>
|
||||
<div class="setting-item mt-2">
|
||||
<span>{{ $t('home.memo') }}</span>
|
||||
<el-switch
|
||||
v-model="memoCarouselSetting"
|
||||
active-value="Enable"
|
||||
inactive-value="Disable"
|
||||
@change="
|
||||
(val) => updateDashboardCarouselSetting('DashboardMemoVisible', val)
|
||||
"
|
||||
/>
|
||||
</div>
|
||||
<div class="setting-item">
|
||||
<span>{{ $t('setting.panel') }}</span>
|
||||
<el-switch
|
||||
v-model="simpleNodeCarouselSetting"
|
||||
active-value="Enable"
|
||||
inactive-value="Disable"
|
||||
@change="
|
||||
(val) =>
|
||||
updateDashboardCarouselSetting(
|
||||
'DashboardSimpleNodeVisible',
|
||||
val,
|
||||
)
|
||||
"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<template #reference>
|
||||
<el-button class="h-button-setting" link icon="Setting" />
|
||||
</template>
|
||||
</el-popover>
|
||||
<el-tooltip :content="$t('commons.button.refresh')" placement="top">
|
||||
<el-button class="h-button-setting" @click="refreshDashboard" link icon="Refresh" />
|
||||
</el-tooltip>
|
||||
@@ -276,12 +320,9 @@
|
||||
</template>
|
||||
</CardWithHeader>
|
||||
</el-carousel-item>
|
||||
<el-carousel-item key="memoInfo">
|
||||
<el-carousel-item key="memoInfo" v-if="showMemoCarousel">
|
||||
<CardWithHeader :header="$t('home.memo')" class="memo-card">
|
||||
<template #header-r>
|
||||
<el-tooltip v-if="!memoEditing" :content="$t('commons.button.edit')" placement="top">
|
||||
<el-button class="h-button-setting" @click="startMemoEdit" link icon="Edit" />
|
||||
</el-tooltip>
|
||||
<el-tooltip v-if="memoEditing" :content="$t('commons.button.save')" placement="top">
|
||||
<el-button
|
||||
class="h-button-setting"
|
||||
@@ -307,7 +348,7 @@
|
||||
show-word-limit
|
||||
:placeholder="$t('home.memoPlaceholder')"
|
||||
/>
|
||||
<div v-else class="memo-content">
|
||||
<div v-else class="memo-content" @dblclick="startMemoEdit">
|
||||
<MarkDownEditor v-if="memoContent" :content="memoContent" />
|
||||
<span v-else class="memo-placeholder">
|
||||
{{ $t('home.memoPlaceholder') }}
|
||||
@@ -380,7 +421,7 @@
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { onMounted, onBeforeUnmount, ref, reactive } from 'vue';
|
||||
import { onMounted, onBeforeUnmount, ref, reactive, computed } from 'vue';
|
||||
import SystemStatus from '@/views/home/status/index.vue';
|
||||
import AppLauncher from '@/views/home/app/index.vue';
|
||||
import VCharts from '@/components/v-charts/index.vue';
|
||||
@@ -401,6 +442,7 @@ import {
|
||||
loadUpgradeInfo,
|
||||
getMemo,
|
||||
updateMemo,
|
||||
updateSetting,
|
||||
} from '@/api/modules/setting';
|
||||
import { GlobalStore } from '@/store';
|
||||
import { storeToRefs } from 'pinia';
|
||||
@@ -461,6 +503,16 @@ const memoContent = ref('');
|
||||
const memoEditContent = ref('');
|
||||
const memoEditing = ref(false);
|
||||
const memoSaving = ref(false);
|
||||
const memoCarouselSetting = ref();
|
||||
const simpleNodeCarouselSetting = ref();
|
||||
|
||||
const showMemoCarousel = computed(() => memoCarouselSetting.value === 'Enable');
|
||||
const carouselItemCount = computed(() => {
|
||||
let count = 1;
|
||||
if (showMemoCarousel.value) count += 1;
|
||||
if (showSimpleNode()) count += 1;
|
||||
return count;
|
||||
});
|
||||
|
||||
const baseInfo = ref<Dashboard.BaseInfo>({
|
||||
hostname: '',
|
||||
@@ -655,7 +707,11 @@ const quickJump = (item: any) => {
|
||||
};
|
||||
|
||||
const showSimpleNode = () => {
|
||||
return globalStore.isMasterProductPro && simpleNodes.value?.length !== 0;
|
||||
return (
|
||||
simpleNodeCarouselSetting.value === 'Enable' &&
|
||||
globalStore.isMasterProductPro &&
|
||||
simpleNodes.value?.length !== 0
|
||||
);
|
||||
};
|
||||
|
||||
const toggleSensitiveInfo = () => {
|
||||
@@ -783,6 +839,18 @@ const loadMemo = async () => {
|
||||
}
|
||||
};
|
||||
|
||||
const updateDashboardCarouselSetting = async (key: string, value: 'Enable' | 'Disable') => {
|
||||
const target = key === 'DashboardMemoVisible' ? memoCarouselSetting : simpleNodeCarouselSetting;
|
||||
const previous = value === 'Enable' ? 'Disable' : 'Enable';
|
||||
try {
|
||||
await updateSetting({ key, value });
|
||||
MsgSuccess(i18n.global.t('commons.msg.operationSuccess'));
|
||||
} catch (error) {
|
||||
target.value = previous;
|
||||
MsgError(error.message);
|
||||
}
|
||||
};
|
||||
|
||||
const startMemoEdit = () => {
|
||||
memoEditContent.value = memoContent.value;
|
||||
memoEditing.value = true;
|
||||
@@ -862,6 +930,8 @@ const loadSafeStatus = async () => {
|
||||
}
|
||||
const res = await getSettingInfo();
|
||||
isSafety.value = res.data.securityEntrance;
|
||||
memoCarouselSetting.value = res.data.dashboardMemoVisible;
|
||||
simpleNodeCarouselSetting.value = res.data.dashboardSimpleNodeVisible;
|
||||
setDashboardCache('safeStatus', isSafety.value, DASHBOARD_CACHE_TTL.safeStatus);
|
||||
};
|
||||
|
||||
@@ -1027,6 +1097,12 @@ onBeforeUnmount(() => {
|
||||
}
|
||||
|
||||
.my-carousel {
|
||||
&.no-indicator {
|
||||
.el-carousel__indicators {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
.el-carousel__button {
|
||||
margin-bottom: -4px;
|
||||
background-color: var(--el-text-color-regular);
|
||||
@@ -1130,4 +1206,23 @@ onBeforeUnmount(() => {
|
||||
color: var(--el-text-color-placeholder);
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
.dashboard-carousel-setting {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
.setting-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
}
|
||||
}
|
||||
|
||||
.dashboard-carousel-popover {
|
||||
.el-popover__title {
|
||||
padding-bottom: 10px;
|
||||
margin-bottom: 8px;
|
||||
border-bottom: 1px solid var(--el-border-color);
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
Reference in New Issue
Block a user