From 88891b9510f198f0b0a8c7207878452cda9d636b Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 28 Jan 2026 13:01:17 +0000 Subject: [PATCH 1/5] Initial plan From 47770f47ff78dbcbdee4158c261f6c098d7ffc29 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 28 Jan 2026 13:13:10 +0000 Subject: [PATCH 2/5] Add dashboard memo feature Co-authored-by: HynoR <20227709+HynoR@users.noreply.github.com> --- core/app/api/v2/setting.go | 36 ++++++++ core/app/dto/setting.go | 4 + core/app/service/setting.go | 15 ++++ core/router/ro_setting.go | 3 + frontend/src/api/modules/setting.ts | 8 ++ frontend/src/lang/modules/en.ts | 4 + frontend/src/lang/modules/zh.ts | 4 + frontend/src/views/home/index.vue | 122 +++++++++++++++++++++++++++- 8 files changed, 194 insertions(+), 2 deletions(-) diff --git a/core/app/api/v2/setting.go b/core/app/api/v2/setting.go index a33fc9538b2d..05b62e3a00af 100644 --- a/core/app/api/v2/setting.go +++ b/core/app/api/v2/setting.go @@ -598,6 +598,42 @@ func (b *BaseApi) GetAppstoreConfig(c *gin.Context) { helper.SuccessWithData(c, res) } +// @Tags System Setting +// @Summary Load dashboard memo +// @Success 200 {string} memo +// @Security ApiKeyAuth +// @Security Timestamp +// @Router /core/settings/memo [get] +func (b *BaseApi) GetMemo(c *gin.Context) { + memo, err := settingService.GetMemo() + if err != nil { + helper.InternalServer(c, err) + return + } + helper.SuccessWithData(c, memo) +} + +// @Tags System Setting +// @Summary Update dashboard memo +// @Accept json +// @Param request body dto.MemoUpdate true "request" +// @Success 200 +// @Security ApiKeyAuth +// @Security Timestamp +// @Router /core/settings/memo [post] +// @x-panel-log {"bodyKeys":[],"paramKeys":[],"BeforeFunctions":[],"formatZH":"更新仪表盘备忘录","formatEN":"update dashboard memo"} +func (b *BaseApi) UpdateMemo(c *gin.Context) { + var req dto.MemoUpdate + if err := helper.CheckBindAndValidate(&req, c); err != nil { + return + } + if err := settingService.UpdateMemo(req.Content); err != nil { + helper.InternalServer(c, err) + return + } + helper.Success(c) +} + func checkEntrancePattern(val string) bool { if len(val) == 0 { return true diff --git a/core/app/dto/setting.go b/core/app/dto/setting.go index bd275b0ab807..7b59e341cce9 100644 --- a/core/app/dto/setting.go +++ b/core/app/dto/setting.go @@ -263,3 +263,7 @@ type PasskeyInfo struct { CreatedAt string `json:"createdAt"` LastUsedAt string `json:"lastUsedAt"` } + +type MemoUpdate struct { + Content string `json:"content" validate:"max=500"` +} diff --git a/core/app/service/setting.go b/core/app/service/setting.go index a418d424a7b9..7a78445cf134 100644 --- a/core/app/service/setting.go +++ b/core/app/service/setting.go @@ -66,6 +66,9 @@ type ISettingService interface { UpdateAppstoreConfig(req dto.AppstoreUpdate) error GetAppstoreConfig() (*dto.AppstoreConfig, error) DefaultMenu() error + + GetMemo() (string, error) + UpdateMemo(content string) error } func NewISettingService() ISettingService { @@ -781,3 +784,15 @@ func checkProxy(req dto.ProxyUpdate) error { func (u *SettingService) DefaultMenu() error { return settingRepo.DefaultMenu() } + +func (u *SettingService) GetMemo() (string, error) { + memo, err := settingRepo.GetValueByKey("DashboardMemo") + if err != nil { + return "", nil + } + return memo, nil +} + +func (u *SettingService) UpdateMemo(content string) error { + return settingRepo.UpdateOrCreate("DashboardMemo", content) +} diff --git a/core/router/ro_setting.go b/core/router/ro_setting.go index e4c62c5b33d7..d26e827e70d9 100644 --- a/core/router/ro_setting.go +++ b/core/router/ro_setting.go @@ -53,5 +53,8 @@ func (s *SettingRouter) InitRouter(Router *gin.RouterGroup) { settingRouter.POST("/apps/store/update", baseApi.UpdateAppstoreConfig) settingRouter.GET("/apps/store/config", baseApi.GetAppstoreConfig) + + settingRouter.GET("/memo", baseApi.GetMemo) + settingRouter.POST("/memo", baseApi.UpdateMemo) } } diff --git a/frontend/src/api/modules/setting.ts b/frontend/src/api/modules/setting.ts index 3fd346f238ce..ef74e40a34f7 100644 --- a/frontend/src/api/modules/setting.ts +++ b/frontend/src/api/modules/setting.ts @@ -212,3 +212,11 @@ export const generateApiKey = () => { export const updateApiConfig = (param: Setting.ApiConfig) => { return http.post(`/core/settings/api/config/update`, param); }; + +// memo +export const getMemo = () => { + return http.get(`/core/settings/memo`); +}; +export const updateMemo = (content: string) => { + return http.post(`/core/settings/memo`, { content: content }); +}; diff --git a/frontend/src/lang/modules/en.ts b/frontend/src/lang/modules/en.ts index a8f950900b92..e8f5355724d0 100644 --- a/frontend/src/lang/modules/en.ts +++ b/frontend/src/lang/modules/en.ts @@ -469,6 +469,10 @@ const message = { networkCard: 'Network card', disk: 'Disk', + + memo: 'Memo', + memoPlaceholder: 'Click to edit memo...', + memoHelper: 'Memo content supports up to 500 characters', }, tabs: { more: 'More', diff --git a/frontend/src/lang/modules/zh.ts b/frontend/src/lang/modules/zh.ts index dea62f6a3b17..9f5e100ce36f 100644 --- a/frontend/src/lang/modules/zh.ts +++ b/frontend/src/lang/modules/zh.ts @@ -455,6 +455,10 @@ const message = { networkCard: '网卡', disk: '磁盘', + + memo: '备忘录', + memoPlaceholder: '点击编辑备忘录内容...', + memoHelper: '备忘录内容最多支持 500 个字符', }, tabs: { more: '更多', diff --git a/frontend/src/views/home/index.vue b/frontend/src/views/home/index.vue index 0cce337767fd..dadf27e158d1 100644 --- a/frontend/src/views/home/index.vue +++ b/frontend/src/views/home/index.vue @@ -168,7 +168,7 @@ class="my-carousel" :key="simpleNodes.length" height="368px" - :indicator-position="showSimpleNode() ? '' : 'none'" + indicator-position="" arrow="never" > @@ -270,6 +270,55 @@ + + + + + +