From 06160546a6f30d73b719df443c4048df542a5ef0 Mon Sep 17 00:00:00 2001 From: jialin Date: Tue, 31 Mar 2026 15:04:31 +0800 Subject: [PATCH] feat: show the worker version --- src/components/icon-font/index.tsx | 4 +- src/components/version-info/index.tsx | 2 +- src/locales/en-US/resources.ts | 4 +- src/locales/ja-JP/resources.ts | 5 +- src/locales/ru-RU/resources.ts | 7 +- src/locales/tr-TR/menu.ts | 9 ++- src/locales/tr-TR/models.ts | 51 +++++++------ src/locales/tr-TR/no-result.ts | 18 ++++- src/locales/tr-TR/resources.ts | 15 ++-- src/locales/zh-CN/resources.ts | 3 +- .../backends/components/backend-list.tsx | 39 ++-------- src/pages/backends/styles/backend-list.less | 34 +++++++++ .../instance-view/use-instance-columns.tsx | 10 +-- src/pages/resources/components/workers.tsx | 1 + src/pages/resources/config/types.ts | 1 + .../resources/hooks/use-worker-columns.tsx | 72 ++++++++++++------- src/pages/resources/styles/worker.less | 52 ++++++++++++++ 17 files changed, 221 insertions(+), 106 deletions(-) create mode 100644 src/pages/backends/styles/backend-list.less create mode 100644 src/pages/resources/styles/worker.less diff --git a/src/components/icon-font/index.tsx b/src/components/icon-font/index.tsx index c126bdbc..e6fb0e10 100644 --- a/src/components/icon-font/index.tsx +++ b/src/components/icon-font/index.tsx @@ -1,8 +1,8 @@ import { createFromIconfontCN } from '@ant-design/icons'; -import './iconfont/iconfont.js'; +// import './iconfont/iconfont.js'; const IconFont = createFromIconfontCN({ - scriptUrl: '//at.alicdn.com/t/c/font_4613488_7zu9s75km1r.js' + scriptUrl: '//at.alicdn.com/t/c/font_4613488_110n9b7vcjv.js' }); export default IconFont; diff --git a/src/components/version-info/index.tsx b/src/components/version-info/index.tsx index 62657567..992c81d4 100644 --- a/src/components/version-info/index.tsx +++ b/src/components/version-info/index.tsx @@ -88,7 +88,7 @@ export const modalConfig = { icon: null, centered: false, mask: { - closeable: true + closable: true }, footer: null, style: { diff --git a/src/locales/en-US/resources.ts b/src/locales/en-US/resources.ts index bfa5e148..63d50653 100644 --- a/src/locales/en-US/resources.ts +++ b/src/locales/en-US/resources.ts @@ -107,5 +107,7 @@ export default { 'When enter the maintenance mode, the node will stop scheduling new model deployment tasks. Running instances will not be affected.', 'resources.worker.noCluster.tips': 'No available clusters. Please create a cluster before adding a node.', - 'resources.metrics.details': 'Monitoring' + 'resources.metrics.details': 'Monitoring', + 'resoureces.worker.upgrade.tips': + 'Please upgrade to match the GPUStack Server version.' }; diff --git a/src/locales/ja-JP/resources.ts b/src/locales/ja-JP/resources.ts index 29736eb3..405b028a 100644 --- a/src/locales/ja-JP/resources.ts +++ b/src/locales/ja-JP/resources.ts @@ -108,7 +108,9 @@ export default { 'When maintenance mode is enabled, the node will stop scheduling new model deployment tasks. Running instances will not be affected.', 'resources.worker.noCluster.tips': 'No available clusters. Please create a cluster before adding a node.', - 'resources.metrics.details': 'Monitoring' + 'resources.metrics.details': 'Monitoring', + 'resoureces.worker.upgrade.tips': + 'Please upgrade to match the GPUStack Server version.' }; // ========== To-Do: Translate Keys (Remove After Translation) ========== @@ -136,4 +138,5 @@ export default { // 22. 'resources.worker.maintenance.remark.rules': 'Please enter maintenance remarks', // 23. 'resources.worker.maintenance.tips': 'When maintenance mode is enabled, the node will stop scheduling new model deployment tasks. Running instances will not be affected.', // 24. 'resources.worker.noCluster.tips': 'No available clusters. Please create a cluster before adding a node.' +// 25. 'resoureces.worker.upgrade.tips': 'Please upgrade to match the GPUStack Server version.' // ========== End of To-Do List ========== diff --git a/src/locales/ru-RU/resources.ts b/src/locales/ru-RU/resources.ts index 94c6dc06..8e9a4362 100644 --- a/src/locales/ru-RU/resources.ts +++ b/src/locales/ru-RU/resources.ts @@ -106,7 +106,9 @@ export default { 'When maintenance mode is enabled, the node will stop scheduling new model deployment tasks. Running instances will not be affected.', 'resources.worker.noCluster.tips': 'No available clusters. Please create a cluster before adding a node.', - 'resources.metrics.details': 'Monitoring' + 'resources.metrics.details': 'Monitoring', + 'resoureces.worker.upgrade.tips': + 'Please upgrade to match the GPUStack Server version.' }; // ========== To-Do: Translate Keys (Remove After Translation) ========== @@ -117,5 +119,6 @@ export default { // 6. 'resources.worker.maintenance.remark.rules': 'Please enter maintenance remarks', // 7. 'resources.worker.maintenance.tips': 'When maintenance mode is enabled, the node will stop scheduling new model deployment tasks. Running instances will not be affected.', // 8. 'resources.worker.noCluster.tips': 'No available clusters. Please create a cluster before adding a node.', -// 9. 'resources.metrics.details': 'Monitoring' +// 9. 'resources.metrics.details': 'Monitoring', +// 10. 'resoureces.worker.upgrade.tips': 'Please upgrade to match the GPUStack Server version.' // ========== End of To-Do List ========== diff --git a/src/locales/tr-TR/menu.ts b/src/locales/tr-TR/menu.ts index 56844c5a..5203c84c 100644 --- a/src/locales/tr-TR/menu.ts +++ b/src/locales/tr-TR/menu.ts @@ -23,7 +23,7 @@ export default { 'menu.apikeys': 'API Anahtarları', 'menu.users': 'Kullanıcılar', 'menu.resources.workers': 'İşçi Düğümler', - 'menu.resources.gpus': 'GPU\'lar', + 'menu.resources.gpus': "GPU'lar", 'menu.resources.modelfiles': 'Model Dosyaları', 'menu.accessControl': 'Erişim Kontrolü', 'menu.accessControl.apikeys': 'API Anahtarları', @@ -37,5 +37,10 @@ export default { 'menu.clusterManagement.credentials': 'Bulut Kimlik Bilgileri', 'menu.clusterManagement.clusterDetail': 'Küme Detayı', 'menu.clusterManagement.clusterCreate': 'Küme Oluştur', - 'menu.resources.backendsList': 'Çıkarım Altyapıları' + 'menu.resources.backendsList': 'Çıkarım Altyapıları', + 'menu.models.instances': 'Instances' }; + +// ========== To-Do: Translate Keys (Remove After Translation) ========== +// 1. 'menu.models.instances': 'Instances' +// ========== End of To-Do List ========== diff --git a/src/locales/tr-TR/models.ts b/src/locales/tr-TR/models.ts index 2b5c6d85..a98946b3 100644 --- a/src/locales/tr-TR/models.ts +++ b/src/locales/tr-TR/models.ts @@ -24,7 +24,7 @@ export default { 'model.deploy.sort': 'Sırala', 'model.deploy.search.placeholder': 'Modelleri aramak için / yazın', 'model.form.ollamatips': - 'İpucu: Aşağıdakiler GPUStack\'te önceden yapılandırılmış Ollama modelleridir. İstediğiniz modeli seçin veya dağıtmak istediğiniz modeli doğrudan sağdaki 【{name}】 giriş kutusuna yazın.', + "İpucu: Aşağıdakiler GPUStack'te önceden yapılandırılmış Ollama modelleridir. İstediğiniz modeli seçin veya dağıtmak istediğiniz modeli doğrudan sağdaki 【{name}】 giriş kutusuna yazın.", 'models.sort.name': 'Ad', 'models.sort.size': 'Boyut', 'models.sort.likes': 'Beğeniler', @@ -34,8 +34,8 @@ export default { 'models.search.result': '{count} sonuç', 'models.data.card': 'Model Kartı', 'models.available.files': 'Mevcut Dosyalar', - 'models.viewin.hf': 'Hugging Face\'de Görüntüle', - 'models.viewin.modelscope': 'ModelScope\'da Görüntüle', + 'models.viewin.hf': "Hugging Face'de Görüntüle", + 'models.viewin.modelscope': "ModelScope'da Görüntüle", 'models.architecture': 'Mimari', 'models.search.noresult': 'İlgili model bulunamadı', 'models.search.nofiles': 'Mevcut dosya yok', @@ -50,9 +50,9 @@ export default { 'models.form.scheduletype.gpu': 'GPU Belirle', 'models.form.scheduletype.gpuType': 'GPU Türü Belirle', 'models.form.scheduletype.auto.tips': - 'Mevcut kaynak koşullarına göre model örneklerini uygun GPU\'lara otomatik olarak dağıtır.', + "Mevcut kaynak koşullarına göre model örneklerini uygun GPU'lara otomatik olarak dağıtır.", 'models.form.scheduletype.manual.tips': - 'Model örneklerinin dağıtılacağı GPU\'ları manuel olarak belirlemenize olanak tanır.', + "Model örneklerinin dağıtılacağı GPU'ları manuel olarak belirlemenize olanak tanır.", 'models.form.manual.schedule': 'Manuel Zamanlama', 'models.table.gpuindex': 'GPU İndeksi', 'models.table.backend': 'Altyapılar', @@ -91,12 +91,13 @@ export default { 'GGUF format modeller için, Linux, macOS ve Windows destekler.', 'models.form.backend.vllm': 'NVIDIA, AMD, Ascend, Hygon, Moore Threads, Iluvatar, MetaX, T-Head PPU cihazları için yerleşik destek.', - 'models.form.backend.voxbox': 'Yalnızca NVIDIA GPU\'ları ve CPU\'ları destekler.', - 'models.form.backend.mindie': 'Yalnızca Ascend NPU\'ları destekler.', + 'models.form.backend.voxbox': + "Yalnızca NVIDIA GPU'ları ve CPU'ları destekler.", + 'models.form.backend.mindie': "Yalnızca Ascend NPU'ları destekler.", 'models.form.backend.sglang': 'NVIDIA, AMD, Ascend, Moore Threads, MetaX, T-Head PPU cihazları için yerleşik destek.', 'models.form.search.gguftips': - 'İşçi düğüm olarak macOS veya Windows kullanılıyorsa GGUF\'u işaretleyin (ses modelleri için işareti kaldırın).', + "İşçi düğüm olarak macOS veya Windows kullanılıyorsa GGUF'u işaretleyin (ses modelleri için işareti kaldırın).", 'models.form.button.addlabel': 'Etiket Ekle', 'models.filter.category': 'Kategoriye göre filtrele', 'models.list.more.logs': 'Daha Fazla Göster', @@ -141,16 +142,14 @@ export default { 'models.form.check.passed': 'Uyumluluk Kontrolü Başarılı', 'models.form.check.claims': 'Model yaklaşık {vram} VRAM ve {ram} RAM tüketecektir.', - 'models.form.check.claims2': - 'Model yaklaşık {vram} VRAM tüketecektir.', - 'models.form.check.claims3': - 'Model yaklaşık {ram} RAM tüketecektir.', + 'models.form.check.claims2': 'Model yaklaşık {vram} VRAM tüketecektir.', + 'models.form.check.claims3': 'Model yaklaşık {ram} RAM tüketecektir.', 'models.form.update.tips': 'Değişiklikler yalnızca örneği silip yeniden oluşturduğunuzda geçerli olur.', 'models.table.download.progress': 'İlerleme', 'models.table.button.apiAccessInfo': 'API Erişim Bilgisi', - 'models.table.button.apiAccessInfo.tips': `Bu modeli üçüncü taraf uygulamalarla entegre etmek için şu bilgileri kullanın: erişim URL\'si, model adı ve API anahtarı. Bu kimlik bilgileri, model hizmetine düzgün bağlantı ve kullanım sağlamak için gereklidir.`, - 'models.table.apiAccessInfo.endpoint': 'Erişim URL\'si', + 'models.table.button.apiAccessInfo.tips': `Bu modeli üçüncü taraf uygulamalarla entegre etmek için şu bilgileri kullanın: erişim URL'si, model adı ve API anahtarı. Bu kimlik bilgileri, model hizmetine düzgün bağlantı ve kullanım sağlamak için gereklidir.`, + 'models.table.apiAccessInfo.endpoint': "Erişim URL'si", 'models.table.apiAccessInfo.modelName': 'Model Adı', 'models.table.apiAccessInfo.apikey': 'API Anahtarı', 'models.table.apiAccessInfo.openaiCompatible': 'OpenAI Uyumlu', @@ -196,7 +195,7 @@ export default { 'models.form.extendedkvcache': 'Genişletilmiş KV Önbelleğini Etkinleştir', 'models.form.chunkSize': 'Önbellek Parça Boyutu', 'models.form.maxCPUSize': 'Maksimum CPU Önbellek Boyutu (GiB)', - 'models.form.remoteURL': 'Uzak Depolama URL\'si', + 'models.form.remoteURL': "Uzak Depolama URL'si", 'models.form.remoteURL.tips': 'Ayrıntılar için yapılandırma dokümantasyonuna bakın.', 'models.form.runCommandPlaceholder': @@ -213,7 +212,7 @@ export default { 'models.form.gpusAllocationType.auto': 'Otomatik', 'models.form.gpusAllocationType.custom': 'Özel', 'models.form.gpusAllocationType.auto.tips': - 'Sistem kopya başına GPU sayısını otomatik hesaplar, varsayılan olarak ikinin kuvvetlerini kullanır ve seçilen GPU\'larla sınırlandırılır.', + "Sistem kopya başına GPU sayısını otomatik hesaplar, varsayılan olarak ikinin kuvvetlerini kullanır ve seçilen GPU'larla sınırlandırılır.", 'models.form.gpusAllocationType.custom.tips': 'Kopya başına tam GPU sayısını belirleyebilirsiniz.', 'models.mymodels.status.inactive': 'Durduruldu', @@ -227,7 +226,7 @@ export default { 'models.form.ramRatio': 'RAM-VRAM Oranı', 'models.form.ramSize': 'Maksimum RAM Boyutu (GiB)', 'models.form.ramRatio.tips': - 'KV önbellek için kullanılan sistem RAM\'in GPU VRAM\'e oranı. Örneğin, 2.0 RAM\'deki önbelleğin GPU VRAM\'in iki katı olabileceği anlamına gelir.', + "KV önbellek için kullanılan sistem RAM'in GPU VRAM'e oranı. Örneğin, 2.0 RAM'deki önbelleğin GPU VRAM'in iki katı olabileceği anlamına gelir.", 'models.form.ramSize.tips': `Sistem belleğinde depolanan KV önbelleğin maksimum boyutu (GiB). Ayarlanırsa, bu değer "{content}" değerini geçersiz kılar.`, 'models.form.chunkSize.tips': 'KV önbellek parçası başına token sayısı.', 'models.form.mode': 'Mod', @@ -245,9 +244,10 @@ export default { 'Düşük istek eşzamanlılığı altında düşük gecikme için optimize edilmiştir.', 'models.form.mode.baseline.tips': 'Tam (orijinal) hassasiyette çalışır ve uyumluluğu ön planda tutar.', - 'models.form.draftModel.placeholder': 'Lütfen bir taslak model seçin veya girin', + 'models.form.draftModel.placeholder': + 'Lütfen bir taslak model seçin veya girin', 'models.form.draftModel.tips': - 'Yerel yol (örn., /path/to/model) girebilir veya Hugging Face ya da ModelScope\'dan bir model seçebilirsiniz (örn., Tengyunw/qwen3_8b_eagle3). Sistem birincil model kaynağına göre otomatik eşleme yapar.', + "Yerel yol (örn., /path/to/model) girebilir veya Hugging Face ya da ModelScope'dan bir model seçebilirsiniz (örn., Tengyunw/qwen3_8b_eagle3). Sistem birincil model kaynağına göre otomatik eşleme yapar.", 'models.form.quantization': 'Niceleme', 'models.form.backend.custom': 'Kullanıcı tanımlı', 'models.form.rules.name': @@ -255,7 +255,7 @@ export default { 'models.catalog.button.explore': 'Daha Fazla Model Keşfet', 'models.catalog.precision': 'Hassasiyet', 'models.form.gpuPerReplica.tips': 'Özel bir sayı girin', - 'models.form.generic_proxy': 'Genel Proxy\'yi Etkinleştir', + 'models.form.generic_proxy': "Genel Proxy'yi Etkinleştir", 'models.form.enableModelRoute': 'Model Yönlendirmesini Etkinleştir', 'models.form.enableModelRoute.tips': 'Model Yönlendirmesini Etkinleştir', 'models.form.generic_proxy.tips': @@ -274,10 +274,17 @@ export default { 'models.form.backendVersions.tips': `Daha fazla sürüm kullanmak için {link} sayfasına gidin ve sürüm eklemek üzere altyapıyı düzenleyin.`, 'models.catalog.nogpus.tips': 'Seçili kümede bu model için uyumlu GPU bulunmuyor.', - 'models.form.modelfile.notfound': `Belirttiğiniz model dosyası yolu GPUStack sunucusunda mevcut değil. Model dosyasını hem GPUStack sunucusunda hem de GPUStack işçi düğümlerinde aynı yola yerleştirmeniz önerilir. Bu, GPUStack\'in daha iyi kararlar almasına yardımcı olur.`, + 'models.form.modelfile.notfound': `Belirttiğiniz model dosyası yolu GPUStack sunucusunda mevcut değil. Model dosyasını hem GPUStack sunucusunda hem de GPUStack işçi düğümlerinde aynı yola yerleştirmeniz önerilir. Bu, GPUStack'in daha iyi kararlar almasına yardımcı olur.`, 'models.form.readyWorkers': 'hazır işçi düğüm', 'models.form.maxContextLength': 'Maksimum Bağlam Uzunluğu', 'models.form.backend.helperText': 'Henüz etkinleştirilmedi. Dağıtımdan sonra etkinleştirilecektir. ', - 'models.table.instance.benchmark': 'Kıyaslama Çalıştır' + 'models.table.instance.benchmark': 'Kıyaslama Çalıştır', + 'models.table.modelView': 'Model List', + 'models.table.instanceView': 'Instance List' }; + +// ========== To-Do: Translate Keys (Remove After Translation) ========== +// 1. 'models.table.modelView': 'Model List', +// 2. 'models.table.instanceView': 'Instance List', +// ========== End of To-Do List ========== diff --git a/src/locales/tr-TR/no-result.ts b/src/locales/tr-TR/no-result.ts index 3d2210d8..160e75e6 100644 --- a/src/locales/tr-TR/no-result.ts +++ b/src/locales/tr-TR/no-result.ts @@ -1,13 +1,15 @@ export default { 'noresult.button.add': 'Şimdi Ekle', 'noresult.mymodels.title': 'Erişilebilir Model Yok', - 'noresult.mymodels.subTitle': 'Erişim için lütfen yöneticiyle iletişime geçin.', + 'noresult.mymodels.subTitle': + 'Erişim için lütfen yöneticiyle iletişime geçin.', 'noresult.mymodels.nofound': 'Eşleşen model bulunamadı', 'noresult.deployments.title': 'Dağıtılmış Model Yok', 'noresult.deployments.subTitle': 'Henüz hiç model dağıtmadınız. Başlamak için aşağıdaki düğmeye tıklayın.', 'noresult.gpus.title': 'GPU Cihazı Algılanamadı', - 'noresult.gpus.subTitle': 'Lütfen İşçi Düğüm durumunun HAZIR olup olmadığını kontrol edin.', + 'noresult.gpus.subTitle': + 'Lütfen İşçi Düğüm durumunun HAZIR olup olmadığını kontrol edin.', 'noresult.gpus.nofound': 'Eşleşen GPU cihazı bulunamadı.', 'noresult.workers.title': 'İşçi Düğüm Yok', 'noresult.workers.subTitle': 'Hiçbir kümede işçi düğüm bulunamadı.', @@ -48,5 +50,15 @@ export default { 'noresult.providers.nofound': 'Eşleşen sağlayıcı bulunamadı.', 'noresult.routes.title': 'Yönlendirme Yok', 'noresult.routes.subTitle': 'Henüz yönlendirme eklenmedi.', - 'noresult.routes.nofound': 'Eşleşen yönlendirme bulunamadı.' + 'noresult.routes.nofound': 'Eşleşen yönlendirme bulunamadı.', + 'noresult.instances.title': 'No instances', + 'noresult.instances.subTitle': + 'There are no running model instances. Deploy a model to create one automatically.', + 'noresult.instances.nofound': 'No matching instances found.' }; + +// ========== To-Do: Translate Keys (Remove After Translation) ========== +// 1. 'noresult.instances.title': 'No instances', +// 2. 'noresult.instances.subTitle': 'There are no running model instances. Deploy a model to create one automatically.', +// 3. 'noresult.instances.nofound': 'No matching instances found.' +// ========== End of To-Do List ========== diff --git a/src/locales/tr-TR/resources.ts b/src/locales/tr-TR/resources.ts index 92d4fa51..a00d684a 100644 --- a/src/locales/tr-TR/resources.ts +++ b/src/locales/tr-TR/resources.ts @@ -19,7 +19,7 @@ export default { 'resources.form.spread.tips': 'Tüm kümenin kaynaklarını tüm işçi düğümler arasında nispeten eşit dağıtır. Tek bir işçi düğümde daha fazla kaynak parçalanması oluşturabilir.', 'resources.form.binpack.tips': - 'Küme kaynaklarının genel kullanımını önceliklendirerek GPU\'lar/İşçi Düğümlerdeki kaynak parçalanmasını azaltır.', + "Küme kaynaklarının genel kullanımını önceliklendirerek GPU'lar/İşçi Düğümlerdeki kaynak parçalanmasını azaltır.", 'resources.form.workerSelector.description': 'Sistem, önceden tanımlanmış etiketlere göre model örneklerini dağıtmak için en uygun İşçi Düğümü seçer.', 'resources.table.ip': 'IP', @@ -56,7 +56,7 @@ export default { 'Komutu oluşturmak için bir etiket seçin ve kopyala düğmesiyle kopyalayın.', 'resources.worker.script.install': 'Betik Kurulumu', 'resources.worker.container.install': 'Konteyner Kurulumu (Yalnızca Linux)', - 'resources.worker.cann.tips': `Gerekli NPU indeksine göre --device /dev/davinci{index} ayarlayın. Örneğin, NPU0 ve NPU1\'i bağlamak için --device /dev/davinci0 --device /dev/davinci1 ekleyin.`, + 'resources.worker.cann.tips': `Gerekli NPU indeksine göre --device /dev/davinci{index} ayarlayın. Örneğin, NPU0 ve NPU1'i bağlamak için --device /dev/davinci0 --device /dev/davinci1 ekleyin.`, 'resources.modelfiles.form.path': 'Depolama Yolu', 'resources.modelfiles.modelfile': 'Model Dosyaları', 'resources.modelfiles.download': 'Model Dosyası Ekle', @@ -101,11 +101,16 @@ export default { 'resources.worker.maintenance.enable': 'Bakım Moduna Gir', 'resources.worker.maintenance.disable': 'Bakım Modundan Çık', 'resources.worker.maintenance.remark': 'Not', - 'resources.worker.maintenance.remark.rules': - 'Lütfen bakım notlarını girin', + 'resources.worker.maintenance.remark.rules': 'Lütfen bakım notlarını girin', 'resources.worker.maintenance.tips': 'Bakım moduna girildiğinde, düğüm yeni model dağıtım görevlerini zamanlamayı durduracaktır. Çalışan örnekler etkilenmez.', 'resources.worker.noCluster.tips': 'Kullanılabilir küme yok. Lütfen düğüm eklemeden önce bir küme oluşturun.', - 'resources.metrics.details': 'İzleme' + 'resources.metrics.details': 'İzleme', + 'resoureces.worker.upgrade.tips': + 'Please upgrade to match the GPUStack Server version.' }; + +// ========== To-Do: Translate Keys (Remove After Translation) ========== +// 1. 'resoureces.worker.upgrade.tips': 'Please upgrade to match the GPUStack Server version.' +// ========== End of To-Do List ========== diff --git a/src/locales/zh-CN/resources.ts b/src/locales/zh-CN/resources.ts index 7d2430e7..2d52784d 100644 --- a/src/locales/zh-CN/resources.ts +++ b/src/locales/zh-CN/resources.ts @@ -103,5 +103,6 @@ export default { 'resources.worker.maintenance.tips': '进入维护模式后,节点将停止调度新的模型实例部署任务,正在运行的实例不会受到影响。', 'resources.worker.noCluster.tips': '当前无可用集群,请先创建集群再添加节点。', - 'resources.metrics.details': '监控' + 'resources.metrics.details': '监控', + 'resoureces.worker.upgrade.tips': '请升级到与 GPUStack Server 版本一致。' }; diff --git a/src/pages/backends/components/backend-list.tsx b/src/pages/backends/components/backend-list.tsx index 573474a2..2514f247 100644 --- a/src/pages/backends/components/backend-list.tsx +++ b/src/pages/backends/components/backend-list.tsx @@ -4,38 +4,9 @@ import InfiniteScroller from '@/pages/_components/infinite-scroller'; import { useScrollerContext } from '@/pages/_components/infinite-scroller/use-scroller-context'; import { Spin } from 'antd'; import React from 'react'; -import styled from 'styled-components'; +import backendListCss from '../styles/backend-list.less'; import BackendCard from './backend-card'; -const SpinWrapper = styled.div` - width: 100%; - position: absolute; - display: flex; - align-items: center; - justify-content: center; - top: 0; - left: 0; - max-height: 400px; - right: 0; - .skelton-wrapper { - width: 100%; - } -`; - -const SkeletonWrapper = styled.div` - .ant-skeleton-content { - .ant-skeleton-paragraph { - display: flex; - flex-direction: column; - gap: 16px; - margin-bottom: 0; - li { - margin-top: 0 !important; - } - } - } -`; - interface BackendListProps { defaultSpan?: number; resizable?: boolean; @@ -54,7 +25,7 @@ const ListSkeleton: React.FC<{ return (
{loading && ( - +
{isFirst && ( - +
- +
)}
- +
)}
); diff --git a/src/pages/backends/styles/backend-list.less b/src/pages/backends/styles/backend-list.less new file mode 100644 index 00000000..9daf36b4 --- /dev/null +++ b/src/pages/backends/styles/backend-list.less @@ -0,0 +1,34 @@ +.SpinWrapper { + width: 100%; + position: absolute; + display: flex; + align-items: center; + justify-content: center; + top: 0; + left: 0; + max-height: 400px; + right: 0; + + :global { + .skelton-wrapper { + width: 100%; + } + } +} + +.SkeletonWrapper { + :global { + .ant-skeleton-content { + .ant-skeleton-paragraph { + display: flex; + flex-direction: column; + gap: 16px; + margin-bottom: 0; + + li { + margin-top: 0 !important; + } + } + } + } +} diff --git a/src/pages/llmodels/instance-view/use-instance-columns.tsx b/src/pages/llmodels/instance-view/use-instance-columns.tsx index f4f9e92f..f85a723c 100644 --- a/src/pages/llmodels/instance-view/use-instance-columns.tsx +++ b/src/pages/llmodels/instance-view/use-instance-columns.tsx @@ -37,10 +37,10 @@ const WorkerInfoContent: React.FC = ({ record, modelData }) => {
- + GPU:[ {_.join( record.gpu_indexes?.sort?.((a, b) => a - b), @@ -115,10 +115,10 @@ const useProviderColumns = (options: { >
- + {record?.backend || record?.backend || ''} {record.backend_version || record?.backend_version ? `(${record.backend_version || record?.backend_version})` diff --git a/src/pages/resources/components/workers.tsx b/src/pages/resources/components/workers.tsx index e70854a3..14be0d8c 100644 --- a/src/pages/resources/components/workers.tsx +++ b/src/pages/resources/components/workers.tsx @@ -279,6 +279,7 @@ const Workers = () => { sortDirections={TABLE_SORT_DIRECTIONS} showSorterTooltip={false} tableLayout={'auto'} + className={'scroll-table'} dataSource={dataSource.dataList} loading={{ spinning: dataSource.loading, diff --git a/src/pages/resources/config/types.ts b/src/pages/resources/config/types.ts index 3fbe9476..01f58142 100644 --- a/src/pages/resources/config/types.ts +++ b/src/pages/resources/config/types.ts @@ -69,6 +69,7 @@ export interface ListItem { ssh_key_id: string; advertise_address: string; provision_progress: string; + worker_version: string; maintenance: { enabled: boolean; message: string; diff --git a/src/pages/resources/hooks/use-worker-columns.tsx b/src/pages/resources/hooks/use-worker-columns.tsx index 82ae34ac..57906c23 100644 --- a/src/pages/resources/hooks/use-worker-columns.tsx +++ b/src/pages/resources/hooks/use-worker-columns.tsx @@ -1,6 +1,8 @@ import { systemConfigAtom } from '@/atoms/system'; +import { GPUStackVersionAtom } from '@/atoms/user'; import AutoTooltip from '@/components/auto-tooltip'; import DropdownButtons from '@/components/drop-down-buttons'; +import IconFont from '@/components/icon-font'; import LabelsCell from '@/components/label-cell'; import ProgressBar from '@/components/progress-bar'; import InfoColumn from '@/components/simple-table/info-column'; @@ -17,31 +19,16 @@ import { ToolOutlined } from '@ant-design/icons'; import { useIntl } from '@umijs/max'; -import { Tooltip } from 'antd'; +import { Tag, Tooltip } from 'antd'; import { ColumnsType } from 'antd/lib/table'; -import { useAtomValue } from 'jotai'; +import { useAtom, useAtomValue } from 'jotai'; import _ from 'lodash'; import { useMemo } from 'react'; -import styled from 'styled-components'; +import semverCoerce from 'semver/functions/coerce'; +import semverGt from 'semver/functions/gt'; import { status, WorkerStatusMap, WorkerStatusMapValue } from '../config'; import { Filesystem, GPUDeviceItem, ListItem } from '../config/types'; - -const IPWrapper = styled.span` - display: flex; - flex-direction: column; - .item { - display: grid; - grid-template-columns: auto 1fr; - gap: 4px 8px; - .label { - text-align: right; - font-size: 13px; - display: flex; - align-items: center; - color: var(--ant-color-text-tertiary); - } - } -`; +import workerCss from '../styles/worker.less'; const ActionList = [ { label: 'common.button.edit', key: 'edit', icon: }, @@ -110,6 +97,16 @@ const fieldList = [ } ]; +const showUpgrade = ( + workerVersion: string, + currentVersion: string +): boolean => { + const w_ver = semverCoerce(workerVersion); + const c_ver = semverCoerce(currentVersion); + + return !!w_ver && !!c_ver && semverGt(c_ver, w_ver); +}; + const formateUtilization = (val1: number, val2: number): number => val1 && val2 ? _.round((val1 / val2) * 100, 0) : 0; @@ -248,6 +245,9 @@ const useWorkerColumns = ({ }): ColumnsType => { const intl = useIntl(); const systemConfig = useAtomValue(systemConfigAtom); + const [version] = useAtom(GPUStackVersionAtom); + + console.log('version in useWorkerColumns', version); const renderIP = (text: string, record: ListItem) => { if (record.advertise_address === record.ip) { @@ -260,14 +260,14 @@ const useWorkerColumns = ({ record.ip ) { return ( - + {record.ip} {`(${intl.formatMessage({ id: 'clusters.table.ip.internal' })})`} {record.advertise_address} {`(${intl.formatMessage({ id: 'clusters.table.ip.external' })})`} - + ); } return record.ip || record.advertise_address || ''; @@ -297,12 +297,30 @@ const useWorkerColumns = ({ { title: intl.formatMessage({ id: 'common.table.name' }), dataIndex: 'name', - width: 100, + width: 140, sorter: tableSorter(1), - render: (text: string) => ( - - {text} - + render: (text: string, record: ListItem) => ( +
+ + {text} + +
+ + + {version.version} + {showUpgrade(record.worker_version, version.version) && ( + + )} + + +
+
) }, { diff --git a/src/pages/resources/styles/worker.less b/src/pages/resources/styles/worker.less new file mode 100644 index 00000000..97e6365d --- /dev/null +++ b/src/pages/resources/styles/worker.less @@ -0,0 +1,52 @@ +.name { + display: flex; + flex-direction: column; + gap: 4px; + + .worker-version { + color: var(--ant-color-text-tertiary); + display: flex; + align-items: center; + font-size: 12px; + gap: 4px; + + :global(.anticon) { + color: var(--ant-color-warning); + font-size: 14px; + } + + :global { + .version-tag { + display: flex; + align-items: center; + gap: 4px; + font-size: 12px; + height: auto; + border-radius: 4px; + line-height: unset; + background-color: unset; + color: var(--ant-color-text-quaternary); + border: 1px solid var(--ant-color-split); + } + } + } +} + +.ipWrapper { + display: flex; + flex-direction: column; + + .item { + display: grid; + grid-template-columns: auto 1fr; + gap: 4px 8px; + + .label { + text-align: right; + font-size: 13px; + display: flex; + align-items: center; + color: var(--ant-color-text-tertiary); + } + } +}