diff --git a/agent/app/repo/agent_account.go b/agent/app/repo/agent_account.go index dde50b4d9..a5cc1b50c 100644 --- a/agent/app/repo/agent_account.go +++ b/agent/app/repo/agent_account.go @@ -18,6 +18,7 @@ type IAgentAccountRepo interface { Save(account *model.AgentAccount) error DeleteByID(id uint) error List(opts ...DBOption) ([]model.AgentAccount, error) + Count() (int64, error) CountTextByProviders(providers []string) (map[string]int64, error) SaveLocal(account *model.AgentAccount, models []model.AgentAccountModel) error } @@ -69,6 +70,12 @@ func (a AgentAccountRepo) List(opts ...DBOption) ([]model.AgentAccount, error) { return accounts, nil } +func (a AgentAccountRepo) Count() (int64, error) { + var count int64 + err := getDb().Model(&model.AgentAccount{}).Count(&count).Error + return count, err +} + func (a AgentAccountRepo) CountTextByProviders(providers []string) (map[string]int64, error) { normalizedProviders := normalizeProviders(providers) counts := make(map[string]int64, len(normalizedProviders)) diff --git a/agent/app/repo/app_launcher.go b/agent/app/repo/app_launcher.go index 1bd575707..8210e832f 100644 --- a/agent/app/repo/app_launcher.go +++ b/agent/app/repo/app_launcher.go @@ -86,10 +86,10 @@ func (u *LauncherRepo) ListQuickJump(withAll bool) []model.QuickJump { } if !withAll && len(quicks) == 0 { return []model.QuickJump{ + {Name: "ModelServices", Title: "aiTools.model.model", Recommend: 0, IsShow: true, Router: "/ai/model"}, {Name: "Agent", Title: "aiTools.agents.agent", Recommend: 1, IsShow: true, Router: "/ai/agents/agent"}, {Name: "Website", Title: "menu.website", Recommend: 10, IsShow: true, Router: "/websites"}, {Name: "Database", Title: "menu.database", Recommend: 30, IsShow: true, Router: "/databases"}, - {Name: "Cronjob", Title: "menu.cronjob", Recommend: 50, IsShow: false, Router: "/cronjobs"}, {Name: "AppInstalled", Title: "home.appInstalled", Recommend: 70, IsShow: true, Router: "/apps/installed"}, } } diff --git a/agent/app/service/dashboard.go b/agent/app/service/dashboard.go index 463c40472..fc004489c 100644 --- a/agent/app/service/dashboard.go +++ b/agent/app/service/dashboard.go @@ -414,7 +414,7 @@ func (u *DashboardService) ChangeQuick(req dto.ChangeQuicks) error { if showCount == 0 { return buserr.New("ErrMinQuickJump") } - if showCount > 4 { + if showCount > 5 { return buserr.New("ErrMaxQuickJump") } @@ -709,6 +709,12 @@ func loadQuickJump(base *dto.DashboardBase) { quicks := launcherRepo.ListQuickJump(false) for i := 0; i < len(quicks); i++ { switch quicks[i].Name { + case "ModelServices": + count, err := agentAccountRepo.Count() + if err != nil { + global.LOG.Errorf("load model service count: %v", err) + } + quicks[i].Detail = fmt.Sprintf("%d", count) case "File": count, err := launcherRepo.CountQuickDirectories() if err != nil { diff --git a/agent/i18n/lang/en.yaml b/agent/i18n/lang/en.yaml index c61e82476..5b177d9d4 100644 --- a/agent/i18n/lang/en.yaml +++ b/agent/i18n/lang/en.yaml @@ -46,7 +46,7 @@ ErrHttpReqNotFound: 'Requested resource not found: {{ .err }}' # quick jump ErrMinQuickJump: 'Set at least one quick jump entry' -ErrMaxQuickJump: 'At most 4 quick jump entries' +ErrMaxQuickJump: 'At most 5 quick jump entries' # common ErrShutDown: 'Command stopped manually' @@ -252,6 +252,7 @@ ErrSSLCertificateNotFound: 'The certificate file does not exist' ErrSSLKeyFormat: 'Private key file verification failed' ErrSSLCertificateFormat: 'Invalid certificate format; use PEM' ErrEabKidOrEabHmacKeyCannotBlank: 'EabKid or EabHmacKey cannot be blank' +ErrOpenrestyInstall: "Please install OpenResty from the App Store first" ErrOpenrestyNotFound: 'HTTP mode requires OpenResty' ApplySSLStart: 'Starting certificate request. Domain: [{{ .domain }}], method: [{{ .type }}]' dnsAccount: 'DNS Auto' diff --git a/agent/i18n/lang/es-ES.yaml b/agent/i18n/lang/es-ES.yaml index e64a97c1b..6eb34d1f7 100644 --- a/agent/i18n/lang/es-ES.yaml +++ b/agent/i18n/lang/es-ES.yaml @@ -46,7 +46,7 @@ ErrHttpReqNotFound: 'No se pudo encontrar el recurso solicitado {{ .err }}' # salto rápido ErrMinQuickJump: 'Agrega al menos una entrada rápida' -ErrMaxQuickJump: 'Máximo 4 entradas rápidas' +ErrMaxQuickJump: 'Máximo 5 entradas rápidas' # común ErrShutDown: 'Comando detenido manualmente' @@ -252,6 +252,7 @@ ErrSSLCertificateNotFound: 'El archivo de certificado no existe' ErrSSLKeyFormat: 'Error en la verificación del archivo de clave privada' ErrSSLCertificateFormat: 'Formato de certificado incorrecto, use formato pem' ErrEabKidOrEabHmacKeyCannotBlank: 'EabKid o EabHmacKey no pueden estar en blanco' +ErrOpenrestyInstall: "Instale primero OpenResty desde la tienda de aplicaciones" ErrOpenrestyNotFound: 'El modo HTTP requiere OpenResty' ApplySSLStart: 'Iniciando solicitud de certificado, dominio [{{ .domain }}] método de solicitud [{{ .type }}]' dnsAccount: 'DNS Automático' diff --git a/agent/i18n/lang/fa.yaml b/agent/i18n/lang/fa.yaml index d6716865e..ac4cc3629 100644 --- a/agent/i18n/lang/fa.yaml +++ b/agent/i18n/lang/fa.yaml @@ -46,7 +46,7 @@ ErrHttpReqNotFound: 'منبع درخواستی یافت نشد: {{ .err }}' # پرش سریع ErrMinQuickJump: 'حداقل یک ورودی پرش سریع تنظیم کنید' -ErrMaxQuickJump: 'حداکثر ۴ ورودی پرش سریع' +ErrMaxQuickJump: 'حداکثر ۵ ورودی پرش سریع' # عمومی ErrShutDown: 'دستور به صورت دستی متوقف شد' @@ -252,6 +252,7 @@ ErrSSLCertificateNotFound: 'فایل گواهی وجود ندارد' ErrSSLKeyFormat: 'تأیید فایل کلید خصوصی ناموفق بود' ErrSSLCertificateFormat: 'فرمت گواهی نامعتبر است؛ از PEM استفاده کنید' ErrEabKidOrEabHmacKeyCannotBlank: 'EabKid یا EabHmacKey نمی‌توانند خالی باشند' +ErrOpenrestyInstall: "لطفاً ابتدا OpenResty را از فروشگاه برنامه‌ها نصب کنید" ErrOpenrestyNotFound: 'حالت HTTP نیاز به OpenResty دارد' ApplySSLStart: 'شروع درخواست گواهی. دامنه: [{{ .domain }}]، روش: [{{ .type }}]' dnsAccount: 'خودکار DNS' diff --git a/agent/i18n/lang/ja.yaml b/agent/i18n/lang/ja.yaml index 451dee002..a894648fa 100644 --- a/agent/i18n/lang/ja.yaml +++ b/agent/i18n/lang/ja.yaml @@ -46,7 +46,7 @@ ErrHttpReqNotFound: '要求されたリソース {{ .err }} が見つかりま # クイックジャンプ ErrMinQuickJump: 'クイックアクセスを1件以上追加' -ErrMaxQuickJump: '最大4件のクイックアクセス' +ErrMaxQuickJump: '最大5件のクイックアクセス' # 共通 ErrShutDown: 'コマンドは手動で停止されました' @@ -252,6 +252,7 @@ ErrSSLCertificateNotFound: '証明書ファイルが存在しません' ErrSSLKeyFormat: '秘密鍵ファイルの検証に失敗しました' ErrSSLCertificateFormat: '証明書ファイルの形式が正しくありません。pem 形式を使用してください' ErrEabKidOrEabHmacKeyCannotBlank: 'EabKid または EabHmacKey は空白にできません' +ErrOpenrestyInstall: "先にアプリストアから OpenResty をインストールしてください" ErrOpenrestyNotFound: 'HTTP モードでは OpenResty が必要です' ApplySSLStart: '証明書の申請を開始します。ドメイン名 [{{ .domain }}] 申請方法 [{{ .type }}]' dnsAccount: 'DNS 自動' diff --git a/agent/i18n/lang/ko.yaml b/agent/i18n/lang/ko.yaml index a29e79dcc..c089ef5d3 100644 --- a/agent/i18n/lang/ko.yaml +++ b/agent/i18n/lang/ko.yaml @@ -46,7 +46,7 @@ ErrHttpReqNotFound: '요청한 리소스 {{ .err }}을 찾을 수 없습니다.' # 빠른 이동 ErrMinQuickJump: '퀵 액세스를 하나 이상 추가하세요' -ErrMaxQuickJump: '퀵 액세스는 최대 4개' +ErrMaxQuickJump: '퀵 액세스는 최대 5개' # 공통 ErrShutDown: '명령이 수동으로 중단되었습니다' @@ -252,6 +252,7 @@ ErrSSLCertificateNotFound: '인증서 파일이 존재하지 않습니다' ErrSSLKeyFormat: '개인 키 파일 검증에 실패했습니다' ErrSSLCertificateFormat: '인증서 파일 형식이 올바르지 않습니다. pem 형식을 사용하세요.' ErrEabKidOrEabHmacKeyCannotBlank: 'EabKid 또는 EabHmacKey는 비워둘 수 없습니다' +ErrOpenrestyInstall: "먼저 앱 스토어에서 OpenResty를 설치하세요" ErrOpenrestyNotFound: 'HTTP 모드에서는 OpenResty가 필요합니다' ApplySSLStart: '인증서 신청 시작, 도메인 이름 [{{ .domain }}] 신청 방법 [{{ .type }}]' dnsAccount: 'DNS 자동' diff --git a/agent/i18n/lang/lo.yaml b/agent/i18n/lang/lo.yaml index 1b97892a7..8930753ed 100644 --- a/agent/i18n/lang/lo.yaml +++ b/agent/i18n/lang/lo.yaml @@ -32,7 +32,7 @@ ErrApiConfigKeyTimeInvalid: 'ເວລາ (Timestamp) ຂອງ API ບໍ່ຖ ErrShutDown: 'ຄຳສັ່ງຖືກຢຸດດ້ວຍຕົນເອງ' ErrMinQuickJump: 'ກະລຸນາຕັ້ງຄ່າລາຍການທາງລັດຢ່າງໜ້ອຍໜຶ່ງລາຍການ' -ErrMaxQuickJump: 'ສາມາດຕັ້ງຄ່າລາຍການທາງລັດໄດ້ສູງສຸດ 4 ລາຍການ' +ErrMaxQuickJump: 'ສາມາດຕັ້ງຄ່າລາຍການທາງລັດໄດ້ສູງສຸດ 5 ລາຍການ' #common ErrUsernameIsExist: 'ຊື່ຜູ້ໃຊ້ມີຢູ່ໃນລະບົບແລ້ວ' @@ -242,6 +242,7 @@ ErrSSLCertificateNotFound: 'ບໍ່ມີໄຟລ໌ໃບຮັບຮອງ ErrSSLKeyFormat: 'ການກວດສອບໄຟລ໌ກຸນແຈສ່ວນຕົວລົ້ມເຫຼວ' ErrSSLCertificateFormat: 'ຮູບແບບໃບຮັບຮອງບໍ່ຖືກຕ້ອງ; ກະລຸນາໃຊ້ PEM' ErrEabKidOrEabHmacKeyCannotBlank: 'EabKid ຫຼື EabHmacKey ບໍ່ສາມາດປະຫວ່າງໄດ້' +ErrOpenrestyInstall: "ກະລຸນາຕິດຕັ້ງ OpenResty ຈາກຮ້ານແອັບກ່ອນ" ErrOpenrestyNotFound: 'ໂໝດ HTTP ຕ້ອງການ OpenResty' ApplySSLStart: 'ກຳລັງເລີ່ມການຮ້ອງຂໍໃບຮັບຮອງ. ໂດເມນ: [{{ .domain }}], ວິທີການ: [{{ .type }}]' dnsAccount: 'DNS ອັດຕະໂນມັດ' diff --git a/agent/i18n/lang/ms.yaml b/agent/i18n/lang/ms.yaml index 5536c3089..8a076e0ef 100644 --- a/agent/i18n/lang/ms.yaml +++ b/agent/i18n/lang/ms.yaml @@ -46,7 +46,7 @@ ErrHttpReqNotFound: 'Sumber yang diminta {{ .err }} tidak dapat ditemui' # lompat pantas ErrMinQuickJump: 'Tambah sekurang-kurangnya satu pintasan pantas' -ErrMaxQuickJump: 'Maksimum 4 pintasan pantas' +ErrMaxQuickJump: 'Maksimum 5 pintasan pantas' # umum ErrShutDown: 'Arahan diberhentikan manual' @@ -252,6 +252,7 @@ ErrSSLCertificateNotFound: 'Fail sijil tidak wujud' ErrSSLKeyFormat: 'Pengesahan fail kunci peribadi gagal' ErrSSLCertificateFormat: 'Format fail sijil tidak betul, sila gunakan format pem' ErrEabKidOrEabHmacKeyCannotBlank: 'EabKid atau EabHmacKey tidak boleh kosong' +ErrOpenrestyInstall: "Sila pasang OpenResty daripada gedung aplikasi terlebih dahulu" ErrOpenrestyNotFound: 'Mod HTTP memerlukan OpenResty dipasang terlebih dahulu' ApplySSLStart: 'Mula memohon sijil, nama domain [{{ .domain }}] kaedah permohonan [{{ .type }}]' dnsAccount: 'DNS automatik' diff --git a/agent/i18n/lang/pt-BR.yaml b/agent/i18n/lang/pt-BR.yaml index 78980c76b..52df6d62d 100644 --- a/agent/i18n/lang/pt-BR.yaml +++ b/agent/i18n/lang/pt-BR.yaml @@ -46,7 +46,7 @@ ErrHttpReqNotFound: 'O recurso solicitado {{ .err }} não pôde ser encontrado' # atalho rápido ErrMinQuickJump: 'Adicione pelo menos um atalho rápido' -ErrMaxQuickJump: 'Máximo 4 atalhos rápidos' +ErrMaxQuickJump: 'Máximo 5 atalhos rápidos' # comum ErrShutDown: 'Comando parado manualmente' @@ -252,6 +252,7 @@ ErrSSLCertificateNotFound: 'O arquivo de certificado não existe' ErrSSLKeyFormat: 'Falha na verificação do arquivo de chave privada' ErrSSLCertificateFormat: 'O formato do arquivo de certificado está incorreto, use o formato pem' ErrEabKidOrEabHmacKeyCannotBlank: 'EabKid ou EabHmacKey não podem estar em branco' +ErrOpenrestyInstall: "Instale primeiro o OpenResty pela loja de aplicativos" ErrOpenrestyNotFound: 'O modo HTTP requer o OpenResty instalado' ApplySSLStart: 'Comece a solicitar um certificado, nome de domínio [{{ .domain }}] método de solicitação [{{ .type }}]' dnsAccount: 'DNS Automático' diff --git a/agent/i18n/lang/ru.yaml b/agent/i18n/lang/ru.yaml index fe41f9f58..ac493cd2d 100644 --- a/agent/i18n/lang/ru.yaml +++ b/agent/i18n/lang/ru.yaml @@ -46,7 +46,7 @@ ErrHttpReqNotFound: 'Запрошенный ресурс {{ .err }} не най # быстрый переход ErrMinQuickJump: 'Добавьте хотя бы одну быструю ссылку' -ErrMaxQuickJump: 'Не более 4 быстрых ссылок' +ErrMaxQuickJump: 'Не более 5 быстрых ссылок' # общее ErrShutDown: 'Команда остановлена вручную' @@ -252,6 +252,7 @@ ErrSSLCertificateNotFound: 'Файл сертификата не существ ErrSSLKeyFormat: 'Проверка файла закрытого ключа не удалась' ErrSSLCertificateFormat: 'Неверный формат файла сертификата, используйте формат pem' ErrEabKidOrEabHmacKeyCannotBlank: 'EabKid или EabHmacKey не могут быть пустыми' +ErrOpenrestyInstall: "Сначала установите OpenResty из магазина приложений" ErrOpenrestyNotFound: 'Для режима HTTP требуется OpenResty' ApplySSLStart: 'Начать подачу заявки на сертификат, доменное имя [{{ .domain }}], метод подачи заявки [{{ .type }}]' dnsAccount: 'DNS Авто' diff --git a/agent/i18n/lang/tr.yaml b/agent/i18n/lang/tr.yaml index b9122edfa..dd655eaac 100644 --- a/agent/i18n/lang/tr.yaml +++ b/agent/i18n/lang/tr.yaml @@ -46,7 +46,7 @@ ErrHttpReqNotFound: 'İstenen kaynak {{ .err }} bulunamadı' # hızlı geçiş ErrMinQuickJump: 'En az bir hızlı erişim ekle' -ErrMaxQuickJump: '4 hızlı erişim hakkı var' +ErrMaxQuickJump: '5 hızlı erişim hakkı var' # genel ErrShutDown: 'Komut manuel durduruldu' @@ -252,6 +252,7 @@ ErrSSLCertificateNotFound: 'Sertifika dosyası mevcut değil' ErrSSLKeyFormat: 'Özel anahtar dosyası doğrulama başarısız' ErrSSLCertificateFormat: 'Sertifika dosyası formatı yanlış, lütfen pem formatını kullanın' ErrEabKidOrEabHmacKeyCannotBlank: 'EabKid veya EabHmacKey boş olamaz' +ErrOpenrestyInstall: "Lütfen önce uygulama mağazasından OpenResty yükleyin" ErrOpenrestyNotFound: 'HTTP modu için OpenResty gereklidir' ApplySSLStart: 'Sertifika başvurusu başlatılıyor, alan adı [{{ .domain }}] başvuru yöntemi [{{ .type }}]' dnsAccount: 'DNS Otomatik' diff --git a/agent/i18n/lang/zh-Hant.yaml b/agent/i18n/lang/zh-Hant.yaml index 959eb0b3d..70a58d55a 100644 --- a/agent/i18n/lang/zh-Hant.yaml +++ b/agent/i18n/lang/zh-Hant.yaml @@ -46,7 +46,7 @@ ErrHttpReqNotFound: '無法找到要求的資源{{ .err }}' # 快速跳轉 ErrMinQuickJump: '請至少設定一個快速跳轉入口!' -ErrMaxQuickJump: '最多可設定四個快速跳轉入口!' +ErrMaxQuickJump: '最多可設定五個快速跳轉入口!' # 通用 ErrShutDown: '指令被手動結束!' @@ -252,6 +252,7 @@ ErrSSLCertificateNotFound: '憑證檔案不存在' ErrSSLKeyFormat: '私鑰檔案驗證失敗' ErrSSLCertificateFormat: '憑證檔案格式錯誤,請使用 pem 格式' ErrEabKidOrEabHmacKeyCannotBlank: 'EabKid 或 EabHmacKey 不可為空' +ErrOpenrestyInstall: "請先在應用程式商店安裝 OpenResty" ErrOpenrestyNotFound: 'HTTP 模式需要先安裝 OpenResty' ApplySSLStart: '開始申請憑證,網域名稱[{{ .domain }}] 申請方式[{{ .type }}]' dnsAccount: 'DNS 自動' diff --git a/agent/i18n/lang/zh.yaml b/agent/i18n/lang/zh.yaml index c51d41821..945589c48 100644 --- a/agent/i18n/lang/zh.yaml +++ b/agent/i18n/lang/zh.yaml @@ -46,7 +46,7 @@ ErrHttpReqNotFound: "无法找到请求的资源 {{ .err }}" # 快速跳转 ErrMinQuickJump: "至少设置 1 个快速跳转入口" -ErrMaxQuickJump: "最多设置 4 个快速跳转入口" +ErrMaxQuickJump: "最多设置 5 个快速跳转入口" # 通用 ErrShutDown: "命令已手动终止" @@ -252,6 +252,7 @@ ErrSSLCertificateNotFound: '证书文件不存在' ErrSSLKeyFormat: '私钥文件校验失败' ErrSSLCertificateFormat: '证书文件格式错误,请使用 pem 格式' ErrEabKidOrEabHmacKeyCannotBlank: 'EabKid 或 EabHmacKey 不能为空' +ErrOpenrestyInstall: "请先在应用商店安装 OpenResty" ErrOpenrestyNotFound: 'Http 模式需要首先安装 Openresty' ApplySSLStart: '开始申请证书,域名 [{{ .domain }}],方式 [{{ .type }}]' dnsAccount: "DNS 自动" diff --git a/agent/init/migration/migrate.go b/agent/init/migration/migrate.go index b075fe247..8b86ab959 100644 --- a/agent/init/migration/migrate.go +++ b/agent/init/migration/migrate.go @@ -119,6 +119,7 @@ func agentDBMigrations() []*gormigrate.Migration { migrations.AddQuickDirectory, migrations.AddLocalModelAccountLink, migrations.AddOllamaModelAccountSync, + migrations.AddModelQuickJump, } } diff --git a/agent/init/migration/migrations/init.go b/agent/init/migration/migrations/init.go index 8bf0a030a..aa80d5a82 100644 --- a/agent/init/migration/migrations/init.go +++ b/agent/init/migration/migrations/init.go @@ -1939,3 +1939,16 @@ var AddOllamaModelAccountSync = &gormigrate.Migration{ return nil }, } + +var AddModelQuickJump = &gormigrate.Migration{ + ID: "20261030-add-model-quick-jump", + Migrate: func(tx *gorm.DB) error { + return tx.Where("name = ?", "ModelServices").FirstOrCreate(&model.QuickJump{ + Name: "ModelServices", + Title: "aiTools.model.model", + Recommend: 0, + IsShow: true, + Router: "/ai/model", + }).Error + }, +} diff --git a/frontend/src/lang/modules/en.ts b/frontend/src/lang/modules/en.ts index 0adf9d404..73d3daccf 100644 --- a/frontend/src/lang/modules/en.ts +++ b/frontend/src/lang/modules/en.ts @@ -498,7 +498,7 @@ const message = { quickDirDelete: 'Delete ({0})?', quickDir: 'Quick Access', minQuickJump: 'Add at least one quick access entry', - maxQuickJump: 'You can add up to four quick access entries', + maxQuickJump: 'You can add up to five quick access entries', database: 'Database - All', restart_1panel: 'Restart panel', restart_system: 'Restart server', @@ -1757,6 +1757,7 @@ const message = { migModeNA: 'Not Supported', current: 'Real-time Status', history: 'Monitoring Data', + viewHistory: 'View monitoring data', notSupport: 'The current version or driver does not support displaying this parameter.', }, mcp: { diff --git a/frontend/src/lang/modules/es-es.ts b/frontend/src/lang/modules/es-es.ts index 968174887..1cd09fda2 100644 --- a/frontend/src/lang/modules/es-es.ts +++ b/frontend/src/lang/modules/es-es.ts @@ -497,7 +497,7 @@ const message = { quickDirDelete: '¿Confirmar la eliminación de ({0})?', quickDir: 'Acceso rápido', minQuickJump: 'Agrega al menos una entrada de acceso rápido', - maxQuickJump: 'Puedes agregar hasta cuatro entradas de acceso rápido', + maxQuickJump: 'Puedes agregar hasta cinco entradas de acceso rápido', database: 'Database - All', restart_1panel: 'Reiniciar panel', restart_system: 'Reiniciar servidor', @@ -1769,6 +1769,7 @@ const message = { migModeNA: 'No Compatible', current: 'Estado en tiempo real', history: 'Datos de monitoreo', + viewHistory: 'Ver datos de monitoreo', notSupport: 'La versión actual o el controlador no admiten mostrar este parámetro.', processCount: 'Procesos', }, diff --git a/frontend/src/lang/modules/fa.ts b/frontend/src/lang/modules/fa.ts index ebbd95e9f..f76aa9820 100644 --- a/frontend/src/lang/modules/fa.ts +++ b/frontend/src/lang/modules/fa.ts @@ -493,7 +493,7 @@ const message = { quickDirDelete: 'حذف ({0}) را تأیید می‌کنید؟', quickDir: 'دسترسی سریع', minQuickJump: 'حداقل یک ورودی دسترسی سریع اضافه کنید', - maxQuickJump: 'می‌توانید حداکثر چهار ورودی دسترسی سریع اضافه کنید', + maxQuickJump: 'می‌توانید حداکثر پنج ورودی دسترسی سریع اضافه کنید', database: 'پایگاه داده - همه', restart_1panel: 'راه‌اندازی مجدد پنل', restart_system: 'راه‌اندازی مجدد سرور', @@ -1739,6 +1739,7 @@ const message = { migModeNA: 'پشتیبانی نمی‌شود', current: 'وضعیت بلادرنگ', history: 'داده‌های نظارتی', + viewHistory: 'مشاهده داده‌های نظارتی', notSupport: 'نسخه فعلی یا درایور از نمایش این پارامتر پشتیبانی نمی‌کند.', }, mcp: { diff --git a/frontend/src/lang/modules/ja.ts b/frontend/src/lang/modules/ja.ts index a1f49aa88..5c8a8060e 100644 --- a/frontend/src/lang/modules/ja.ts +++ b/frontend/src/lang/modules/ja.ts @@ -496,7 +496,7 @@ const message = { quickDirDelete: '({0})を削除しますか?', quickDir: 'クイックアクセス', minQuickJump: 'クイックアクセス項目を1つ以上追加してください', - maxQuickJump: '最大4件のクイックアクセス項目を追加できます', + maxQuickJump: '最大5件のクイックアクセス項目を追加できます', database: 'データベース - すべて', restart_1panel: 'パネルを再起動します', restart_system: 'サーバーを再起動します', @@ -1739,6 +1739,7 @@ const message = { migModeNA: 'サポートされていません', current: 'リアルタイム状態', history: '監視データ', + viewHistory: '監視データを表示', notSupport: '現在のバージョンまたはドライバーはこのパラメータの表示をサポートしていません。', processCount: 'プロセス数', }, diff --git a/frontend/src/lang/modules/ko.ts b/frontend/src/lang/modules/ko.ts index d6eea982c..6ba3c8378 100644 --- a/frontend/src/lang/modules/ko.ts +++ b/frontend/src/lang/modules/ko.ts @@ -491,7 +491,7 @@ const message = { quickDirDelete: '({0})을(를) 삭제하시겠습니까?', quickDir: '빠른 액세스', minQuickJump: '최소 하나의 빠른 액세스 항목을 추가하세요', - maxQuickJump: '빠른 액세스를 최대 4개까지 추가할 수 있습니다', + maxQuickJump: '빠른 액세스를 최대 5개까지 추가할 수 있습니다', database: '데이터베이스 - 전체', restart_1panel: '패널 재시작', restart_system: '서버 재시작', @@ -1724,6 +1724,7 @@ const message = { migModeNA: '지원되지 않음', current: '실시간 상태', history: '모니터링 데이터', + viewHistory: '모니터링 데이터 보기', notSupport: '현재 버전 또는 드라이버는 이 매개변수 표시를 지원하지 않습니다.', processCount: '프로세스 수', }, diff --git a/frontend/src/lang/modules/lo.ts b/frontend/src/lang/modules/lo.ts index 654554336..74d563566 100644 --- a/frontend/src/lang/modules/lo.ts +++ b/frontend/src/lang/modules/lo.ts @@ -492,7 +492,7 @@ const message = { quickDirDelete: 'ຢືນຢັນການລຶບ ({0}) ຫຼືບໍ່?', quickDir: 'ເຂົ້າເຖິງດ່ວນ', minQuickJump: 'ເພີ່ມການເຂົ້າເຖິງດ່ວນຢ່າງໜ້ອຍໜຶ່ງລາຍການ', - maxQuickJump: 'ທ່ານສາມາດເພີ່ມການເຂົ້າເຖິງດ່ວນໄດ້ສູງສຸດສີ່ລາຍການ', + maxQuickJump: 'ທ່ານສາມາດເພີ່ມການເຂົ້າເຖິງດ່ວນໄດ້ສູງສຸດຫ້າລາຍການ', database: 'ຖານຂໍ້ມູນ - ທັງໝົດ', restart_1panel: 'ຣີສະຕາດແພນເນວ', restart_system: 'ຣີສະຕາດເຊີເວີ', @@ -1716,6 +1716,7 @@ const message = { migModeNA: 'ບໍ່ຮອງຮັບ', current: 'ສະຖານະແບບທັນທີ', history: 'ຂໍ້ມູນການຕິດຕາມ', + viewHistory: 'ເບິ່ງຂໍ້ມູນການຕິດຕາມ', notSupport: 'ເວີຊັນ ຫຼື driver ປັດຈຸບັນບໍ່ຮອງຮັບການສະແດງຄ່ານີ້.', }, mcp: { diff --git a/frontend/src/lang/modules/ms.ts b/frontend/src/lang/modules/ms.ts index b974f6def..77109e7d7 100644 --- a/frontend/src/lang/modules/ms.ts +++ b/frontend/src/lang/modules/ms.ts @@ -503,7 +503,7 @@ const message = { quickDirDelete: 'Sahkan pemadaman ({0})?', quickDir: 'Akses Pantas', minQuickJump: 'Tambah sekurang-kurangnya satu entri akses pantas', - maxQuickJump: 'Anda boleh menambah sehingga empat entri akses pantas', + maxQuickJump: 'Anda boleh menambah sehingga lima entri akses pantas', database: 'Pangkalan Data - Semua', restart_1panel: 'Mulakan semula panel', restart_system: 'Mulakan semula pelayan', @@ -1770,6 +1770,7 @@ const message = { migModeNA: 'Tidak Disokong', current: 'Status Masa Nyata', history: 'Data Pemantauan', + viewHistory: 'Lihat data pemantauan', notSupport: 'Versi atau pemacu semasa tidak menyokong paparan parameter ini.', processCount: 'Bilangan proses', }, diff --git a/frontend/src/lang/modules/pt-br.ts b/frontend/src/lang/modules/pt-br.ts index 3dcecd6a8..b0882e19b 100644 --- a/frontend/src/lang/modules/pt-br.ts +++ b/frontend/src/lang/modules/pt-br.ts @@ -496,7 +496,7 @@ const message = { quickDirDelete: 'Confirmar a exclusão de ({0})?', quickDir: 'Acesso rápido', minQuickJump: 'Adicione pelo menos uma entrada de acesso rápido', - maxQuickJump: 'Você pode adicionar até quatro entradas de acesso rápido', + maxQuickJump: 'Você pode adicionar até cinco entradas de acesso rápido', database: 'Banco de Dados - Todos', restart_1panel: 'Reiniciar painel', restart_system: 'Reiniciar servidor', @@ -1770,6 +1770,7 @@ const message = { migModeNA: 'Não Suportado', current: 'Status em tempo real', history: 'Dados de monitoramento', + viewHistory: 'Ver dados de monitoramento', notSupport: 'A versão atual ou o driver não suportam exibir este parâmetro.', processCount: 'Qtd. de processos', }, diff --git a/frontend/src/lang/modules/ru.ts b/frontend/src/lang/modules/ru.ts index cde353c2b..ca15716ca 100644 --- a/frontend/src/lang/modules/ru.ts +++ b/frontend/src/lang/modules/ru.ts @@ -494,7 +494,7 @@ const message = { quickDirDelete: 'Подтвердить удаление ({0})?', quickDir: 'Быстрый доступ', minQuickJump: 'Добавьте хотя бы одну запись быстрого доступа', - maxQuickJump: 'Вы можете добавить до четырех записей быстрого доступа', + maxQuickJump: 'Вы можете добавить до пяти записей быстрого доступа', database: 'База данных - Все', restart_1panel: 'Перезапустить панель', restart_system: 'Перезапустить сервер', @@ -1759,6 +1759,7 @@ const message = { migModeNA: 'Не Поддерживается', current: 'Состояние в реальном времени', history: 'Данные мониторинга', + viewHistory: 'Просмотреть данные мониторинга', notSupport: 'Текущая версия или драйвер не поддерживает отображение этого параметра.', processCount: 'Кол-во процессов', }, diff --git a/frontend/src/lang/modules/tr.ts b/frontend/src/lang/modules/tr.ts index f5ee54181..31d4e01b1 100644 --- a/frontend/src/lang/modules/tr.ts +++ b/frontend/src/lang/modules/tr.ts @@ -499,7 +499,7 @@ const message = { quickDirDelete: '({0}) silinsin mi?', quickDir: 'Hızlı Erişim', minQuickJump: 'En az bir hızlı erişim girdisi ekleyin', - maxQuickJump: 'En fazla dört hızlı erişim girdisi ekleyebilirsiniz', + maxQuickJump: 'En fazla beş hızlı erişim girdisi ekleyebilirsiniz', database: 'Veritabanı - Tümü', restart_1panel: 'Paneli yeniden başlat', restart_system: 'Sunucuyu yeniden başlat', @@ -1766,6 +1766,7 @@ const message = { migModeNA: 'Desteklenmiyor', current: 'Gerçek Zamanlı Durum', history: 'İzleme Verileri', + viewHistory: 'İzleme verilerini görüntüle', notSupport: 'Mevcut sürüm veya sürücü bu parametrenin görüntülenmesini desteklemiyor.', processCount: 'Süreç sayısı', }, diff --git a/frontend/src/lang/modules/zh-Hant.ts b/frontend/src/lang/modules/zh-Hant.ts index ecfd6cd37..288df09e7 100644 --- a/frontend/src/lang/modules/zh-Hant.ts +++ b/frontend/src/lang/modules/zh-Hant.ts @@ -477,7 +477,7 @@ const message = { quickDirDelete: '確定刪除({0})', quickDir: '快捷目錄', minQuickJump: '請至少設定一個快速跳轉入口', - maxQuickJump: '最多可設定四個快速跳轉入口', + maxQuickJump: '最多可設定五個快速跳轉入口', database: '資料庫 - 全部', restart_1panel: '重新啟動面板', restart_system: '重新啟動伺服器', @@ -1664,6 +1664,7 @@ const message = { migModeNA: '不支援', current: '即時狀態', history: '監控資料', + viewHistory: '查看監控資料', notSupport: '當前版本或驅動不支援顯示該參數。', processCount: '行程數', }, diff --git a/frontend/src/lang/modules/zh.ts b/frontend/src/lang/modules/zh.ts index 03f22f6bb..e5ef6a43d 100644 --- a/frontend/src/lang/modules/zh.ts +++ b/frontend/src/lang/modules/zh.ts @@ -477,7 +477,7 @@ const message = { quickDirDelete: '确定删除({0})', quickDir: '快捷目录', minQuickJump: '请至少设置一个快速跳转入口!', - maxQuickJump: '最多可设置四个快速跳转入口!', + maxQuickJump: '最多可设置五个快速跳转入口!', database: '数据库 - 所有', restart_1panel: '重启面板', restart_system: '重启服务器', @@ -1679,6 +1679,7 @@ const message = { migModeNA: '不支持', current: '实时状态', history: '监控数据', + viewHistory: '查看监控数据', notSupport: '当前版本或驱动不支持显示该参数。', }, mcp: { diff --git a/frontend/src/views/home/index.vue b/frontend/src/views/home/index.vue index 2ced09637..78a72a2ee 100644 --- a/frontend/src/views/home/index.vue +++ b/frontend/src/views/home/index.vue @@ -47,7 +47,7 @@ - - - - + + + + @@ -501,12 +491,8 @@ const DASHBOARD_CACHE_TTL = { netOptions: 60 * 60 * 1000, ioOptions: 60 * 60 * 1000, }; -const monitorChartGrid = { left: 65, right: 65, bottom: '20%' }; +const monitorChartGrid = { left: 55, right: 25, bottom: '20%' }; const monitorChartLegend = { top: 0, bottom: 'auto' }; -const monitorTagsStyle = { - left: `${monitorChartGrid.left}px`, - right: `${monitorChartGrid.right}px`, -}; const monitorChartEmptyLength = 20; const loadMonitorEmptyData = () => Array.from({ length: monitorChartEmptyLength }, () => null); const loadMonitorEmptyTime = () => Array.from({ length: monitorChartEmptyLength }, () => ''); @@ -553,11 +539,9 @@ const isSafety = ref(); const welcomeOpen = ref(); const shadowContainer = ref(); -const chartOption = ref('network'); const statusOption = ref(localStorage.getItem('dashboard_status_view') === 'gpu' ? 'gpu' : 'system'); let timer: ReturnType | null = null; let initialSampleTimer: ReturnType | null = null; -let isInit = ref(true); let isStatusInit = ref(true); let isActive = ref(true); let isCurrentActive = ref(true); @@ -587,6 +571,7 @@ const quickJumpPermissionMap = Object.fromEntries( ['Cronjob', 'cronjob_view'], ['AppInstalled', 'app_view'], ['File', 'host_file_view'], + ['ModelServices', 'ai_model_view'], ].map(([name, permission]) => [name, useCan(permission)]), ) as Record>; @@ -723,11 +708,6 @@ const updateCurrentInfo = (data: Dashboard.CurrentInfo) => { }; }; -const changeOption = async () => { - isInit.value = true; - loadData(); -}; - const applyDefaultNetOption = () => { if (!netOptions.value || netOptions.value.length === 0) return; const defaultNet = defaultNetwork.value || netOptions.value[0]; @@ -1032,12 +1012,9 @@ const saveMemo = async () => { } }; -const loadData = async () => { - if (chartOption.value === 'io') { - chartsOption.value['ioChart'] = loadIOChartOption(); - } else { - chartsOption.value['networkChart'] = loadNetworkChartOption(); - } +const loadData = () => { + chartsOption.value['ioChart'] = loadIOChartOption(); + chartsOption.value['networkChart'] = loadNetworkChartOption(); }; const hideEntrance = () => { @@ -1205,15 +1182,6 @@ onBeforeUnmount(() => { font-size: 12px; } -.monitor-chart-content { - position: relative; - margin-top: 60px; -} - -.mobile-monitor-chart { - margin-top: 40px; -} - @media only screen and (max-width: 767px) { .dashboard-entrance-alert { padding-right: 40px; @@ -1255,6 +1223,11 @@ onBeforeUnmount(() => { .h-overview { text-align: center; + .overview-item { + flex: 1; + min-width: 0; + } + span:first-child { font-size: 14px; color: var(--el-text-color-regular); @@ -1355,49 +1328,54 @@ onBeforeUnmount(() => { border-top: var(--panel-border); } -.monitor-tags { - position: absolute; - top: -10px; +.monitor-grid { + display: grid; + grid-template-columns: repeat(2, minmax(0, 1fr)); + gap: 24px; +} + +.monitor-panel { + min-width: 0; +} + +.monitor-panel-header { display: flex; + align-items: center; + justify-content: space-between; flex-wrap: wrap; - gap: 10px; + gap: 8px; + margin-bottom: 12px; + font-weight: 500; } -@media only screen and (max-width: 1024px) { - .monitor-chart-content { - margin-top: 20px; - } +.monitor-select { + width: 200px; + max-width: 100%; +} - .monitor-chart-content .monitor-tags { - position: static; - display: grid; +.monitor-tags { + display: grid; + grid-template-columns: repeat(2, minmax(0, 1fr)); + gap: 8px; + margin-bottom: 16px; + + :deep(.el-tag) { width: 100%; - grid-template-columns: repeat(2, minmax(0, 1fr)); - gap: 8px; - margin-bottom: 12px; - - :deep(.el-tag) { - width: 100%; - max-width: 100%; - height: auto; - min-height: 24px; - justify-content: center; - padding-block: 3px; - line-height: 1.3; - text-align: center; - white-space: normal; - overflow-wrap: anywhere; - } - } - - .mobile-monitor-chart { - margin-top: 0; + max-width: 100%; + height: auto; + min-height: 24px; + justify-content: center; + padding-block: 3px; + line-height: 1.3; + text-align: center; + white-space: normal; + overflow-wrap: anywhere; } } -@media only screen and (min-width: 768px) and (max-width: 1024px) { - .monitor-chart-content .monitor-tags { - grid-template-columns: repeat(4, minmax(0, 1fr)); +@media only screen and (max-width: 991px) { + .monitor-grid { + grid-template-columns: minmax(0, 1fr); } } @@ -1420,10 +1398,6 @@ onBeforeUnmount(() => { } } -.chart-card { - min-height: 383px; -} - .memo-container { height: 270px; } diff --git a/frontend/src/views/home/quick/index.vue b/frontend/src/views/home/quick/index.vue index c53bc20ed..0f8185eae 100644 --- a/frontend/src/views/home/quick/index.vue +++ b/frontend/src/views/home/quick/index.vue @@ -59,7 +59,7 @@ const onChangeShow = async () => { MsgInfo(i18n.global.t('home.minQuickJump')); return; } - if (i > 4) { + if (i > 5) { MsgInfo(i18n.global.t('home.maxQuickJump')); return; } diff --git a/frontend/src/views/home/status/gpu.vue b/frontend/src/views/home/status/gpu.vue index 81e080dc8..edb7e28e6 100644 --- a/frontend/src/views/home/status/gpu.vue +++ b/frontend/src/views/home/status/gpu.vue @@ -16,7 +16,7 @@ - {{ $t('aiTools.gpu.gpu') }} + {{ $t('aiTools.gpu.viewHistory') }} diff --git a/frontend/src/views/home/status/index.vue b/frontend/src/views/home/status/index.vue index 716aaf5dc..29d49f60a 100644 --- a/frontend/src/views/home/status/index.vue +++ b/frontend/src/views/home/status/index.vue @@ -318,7 +318,11 @@ {{ computeSize(item.used) }} / {{ computeSize(item.total) }} - +