diff --git a/backend/app/dto/dashboard.go b/backend/app/dto/dashboard.go index 85fd9a8f7..94c07f3b7 100644 --- a/backend/app/dto/dashboard.go +++ b/backend/app/dto/dashboard.go @@ -69,6 +69,8 @@ type DashboardCurrent struct { NetBytesSent uint64 `json:"netBytesSent"` NetBytesRecv uint64 `json:"netBytesRecv"` + GPUData []GPUInfo `json:"gpuData"` + ShotTime time.Time `json:"shotTime"` } @@ -86,3 +88,18 @@ type DiskInfo struct { InodesFree uint64 `json:"inodesFree"` InodesUsedPercent float64 `json:"inodesUsedPercent"` } + +type GPUInfo struct { + Index uint `json:"index"` + ProductName string `json:"productName"` + GPUUtil string `json:"gpuUtil"` + Temperature string `json:"temperature"` + PerformanceState string `json:"performanceState"` + PowerUsage string `json:"powerUsage"` + PowerDraw string `json:"powerDraw"` + MaxPowerLimit string `json:"maxPowerLimit"` + MemoryUsage string `json:"memoryUsage"` + MemUsed string `json:"memUsed"` + MemTotal string `json:"memTotal"` + FanSpeed string `json:"fanSpeed"` +} diff --git a/backend/app/service/dashboard.go b/backend/app/service/dashboard.go index 5504b95a9..27e256f5b 100644 --- a/backend/app/service/dashboard.go +++ b/backend/app/service/dashboard.go @@ -11,6 +11,8 @@ import ( "github.com/1Panel-dev/1Panel/backend/app/dto" "github.com/1Panel-dev/1Panel/backend/global" "github.com/1Panel-dev/1Panel/backend/utils/cmd" + "github.com/1Panel-dev/1Panel/backend/utils/copier" + "github.com/1Panel-dev/1Panel/backend/utils/xpack" "github.com/shirou/gopsutil/v3/cpu" "github.com/shirou/gopsutil/v3/disk" "github.com/shirou/gopsutil/v3/host" @@ -154,6 +156,7 @@ func (u *DashboardService) LoadCurrentInfo(ioOption string, netOption string) *d currentInfo.SwapMemoryUsedPercent = swapInfo.UsedPercent currentInfo.DiskData = loadDiskInfo() + currentInfo.GPUData = loadGPUInfo() if ioOption == "all" { diskInfo, _ := disk.IOCounters() @@ -289,3 +292,21 @@ func loadDiskInfo() []dto.DiskInfo { }) return datas } + +func loadGPUInfo() []dto.GPUInfo { + list := xpack.LoadGpuInfo() + if len(list) == 0 { + return nil + } + var data []dto.GPUInfo + for _, gpu := range list { + var dataItem dto.GPUInfo + if err := copier.Copy(&dataItem, &gpu); err != nil { + continue + } + dataItem.PowerUsage = dataItem.PowerDraw + " / " + dataItem.MaxPowerLimit + dataItem.MemoryUsage = dataItem.MemUsed + " / " + dataItem.MemTotal + data = append(data, dataItem) + } + return data +} diff --git a/backend/init/migration/migrate.go b/backend/init/migration/migrate.go index c0a6a532d..0850ec7e8 100644 --- a/backend/init/migration/migrate.go +++ b/backend/init/migration/migrate.go @@ -79,6 +79,7 @@ func Init() { migrations.AddCronjobCommand, migrations.NewMonitorDB, migrations.AddNoAuthSetting, + migrations.UpdateXpackHideMenu, }) if err := m.Migrate(); err != nil { global.LOG.Error(err) diff --git a/backend/init/migration/migrations/v_1_10.go b/backend/init/migration/migrations/v_1_10.go index 4ce0ca200..d7ae96cf9 100644 --- a/backend/init/migration/migrations/v_1_10.go +++ b/backend/init/migration/migrations/v_1_10.go @@ -118,3 +118,13 @@ var AddNoAuthSetting = &gormigrate.Migration{ return nil }, } + +var UpdateXpackHideMenu = &gormigrate.Migration{ + ID: "20240411-update-xpack-hide-menu", + Migrate: func(tx *gorm.DB) error { + if err := tx.Model(&model.Setting{}).Where("key", "XpackHideMenu").Updates(map[string]interface{}{"value": "{\"id\":\"1\",\"label\":\"/xpack\",\"isCheck\":true,\"title\":\"xpack.menu\",\"children\":[{\"id\":\"2\",\"title\":\"xpack.waf.name\",\"path\":\"/xpack/waf/dashboard\",\"label\":\"Dashboard\",\"isCheck\":true},{\"id\":\"3\",\"title\":\"xpack.tamper.tamper\",\"path\":\"/xpack/tamper\",\"label\":\"Tamper\",\"isCheck\":true},{\"id\":\"4\",\"title\":\"xpack.gpu.gpu\",\"path\":\"/xpack/gpu\",\"label\":\"GPU\",\"isCheck\":true},{\"id\":\"5\",\"title\":\"xpack.setting.setting\",\"path\":\"/xpack/setting\",\"label\":\"XSetting\",\"isCheck\":true}]}"}).Error; err != nil { + return err + } + return nil + }, +} diff --git a/backend/utils/xpack/xpack.go b/backend/utils/xpack/xpack.go index 9c5ba63b1..31a3b18fe 100644 --- a/backend/utils/xpack/xpack.go +++ b/backend/utils/xpack/xpack.go @@ -2,5 +2,8 @@ package xpack -func RemoveTamper(website string) { +func RemoveTamper(website string) {} + +func LoadGpuInfo() []interface{} { + return nil } diff --git a/cmd/server/docs/docs.go b/cmd/server/docs/docs.go index b2456f1d0..952d50d16 100644 --- a/cmd/server/docs/docs.go +++ b/cmd/server/docs/docs.go @@ -15194,6 +15194,12 @@ const docTemplate = `{ "$ref": "#/definitions/dto.DiskInfo" } }, + "gpuData": { + "type": "array", + "items": { + "$ref": "#/definitions/dto.GPUInfo" + } + }, "ioCount": { "type": "integer" }, @@ -15777,6 +15783,47 @@ const docTemplate = `{ } } }, + "dto.GPUInfo": { + "type": "object", + "properties": { + "fanSpeed": { + "type": "string" + }, + "gpuUtil": { + "type": "string" + }, + "index": { + "type": "integer" + }, + "maxPowerLimit": { + "type": "string" + }, + "memTotal": { + "type": "string" + }, + "memUsed": { + "type": "string" + }, + "memoryUsage": { + "type": "string" + }, + "performanceState": { + "type": "string" + }, + "powerDraw": { + "type": "string" + }, + "powerUsage": { + "type": "string" + }, + "productName": { + "type": "string" + }, + "temperature": { + "type": "string" + } + } + }, "dto.GenerateLoad": { "type": "object", "required": [ @@ -17788,6 +17835,9 @@ const docTemplate = `{ "monitorStoreDays": { "type": "string" }, + "noAuthSetting": { + "type": "string" + }, "ntpSite": { "type": "string" }, @@ -18915,7 +18965,6 @@ const docTemplate = `{ "request.FileCreate": { "type": "object", "required": [ - "mode", "path" ], "properties": { diff --git a/cmd/server/docs/swagger.json b/cmd/server/docs/swagger.json index 646c17d02..6116f4a93 100644 --- a/cmd/server/docs/swagger.json +++ b/cmd/server/docs/swagger.json @@ -15187,6 +15187,12 @@ "$ref": "#/definitions/dto.DiskInfo" } }, + "gpuData": { + "type": "array", + "items": { + "$ref": "#/definitions/dto.GPUInfo" + } + }, "ioCount": { "type": "integer" }, @@ -15770,6 +15776,47 @@ } } }, + "dto.GPUInfo": { + "type": "object", + "properties": { + "fanSpeed": { + "type": "string" + }, + "gpuUtil": { + "type": "string" + }, + "index": { + "type": "integer" + }, + "maxPowerLimit": { + "type": "string" + }, + "memTotal": { + "type": "string" + }, + "memUsed": { + "type": "string" + }, + "memoryUsage": { + "type": "string" + }, + "performanceState": { + "type": "string" + }, + "powerDraw": { + "type": "string" + }, + "powerUsage": { + "type": "string" + }, + "productName": { + "type": "string" + }, + "temperature": { + "type": "string" + } + } + }, "dto.GenerateLoad": { "type": "object", "required": [ @@ -17781,6 +17828,9 @@ "monitorStoreDays": { "type": "string" }, + "noAuthSetting": { + "type": "string" + }, "ntpSite": { "type": "string" }, @@ -18908,7 +18958,6 @@ "request.FileCreate": { "type": "object", "required": [ - "mode", "path" ], "properties": { diff --git a/cmd/server/docs/swagger.yaml b/cmd/server/docs/swagger.yaml index 9092b3491..6200df8f4 100644 --- a/cmd/server/docs/swagger.yaml +++ b/cmd/server/docs/swagger.yaml @@ -795,6 +795,10 @@ definitions: items: $ref: '#/definitions/dto.DiskInfo' type: array + gpuData: + items: + $ref: '#/definitions/dto.GPUInfo' + type: array ioCount: type: integer ioReadBytes: @@ -1190,6 +1194,33 @@ definitions: - type - vars type: object + dto.GPUInfo: + properties: + fanSpeed: + type: string + gpuUtil: + type: string + index: + type: integer + maxPowerLimit: + type: string + memTotal: + type: string + memUsed: + type: string + memoryUsage: + type: string + performanceState: + type: string + powerDraw: + type: string + powerUsage: + type: string + productName: + type: string + temperature: + type: string + type: object dto.GenerateLoad: properties: encryptionMode: @@ -2550,6 +2581,8 @@ definitions: type: string monitorStoreDays: type: string + noAuthSetting: + type: string ntpSite: type: string panelName: @@ -3311,7 +3344,6 @@ definitions: sub: type: boolean required: - - mode - path type: object request.FileDeCompress: diff --git a/frontend/src/api/interface/dashboard.ts b/frontend/src/api/interface/dashboard.ts index 930addb71..30730631c 100644 --- a/frontend/src/api/interface/dashboard.ts +++ b/frontend/src/api/interface/dashboard.ts @@ -59,6 +59,8 @@ export namespace Dashboard { diskData: Array; + gpuData: Array; + netBytesSent: number; netBytesRecv: number; @@ -78,4 +80,14 @@ export namespace Dashboard { inodesFree: number; inodesUsedPercent: number; } + export interface GPUInfo { + index: number; + productName: string; + gpuUtil: string; + temperature: string; + performanceState: string; + powerUsage: string; + memoryUsage: string; + fanSpeed: string; + } } diff --git a/frontend/src/assets/iconfont/iconfont.css b/frontend/src/assets/iconfont/iconfont.css index 3402a8aa3..af01b2750 100644 --- a/frontend/src/assets/iconfont/iconfont.css +++ b/frontend/src/assets/iconfont/iconfont.css @@ -1,9 +1,9 @@ @font-face { font-family: "panel"; /* Project id 3575356 */ - src: url('iconfont.woff2?t=1712045188451') format('woff2'), - url('iconfont.woff?t=1712045188451') format('woff'), - url('iconfont.ttf?t=1712045188451') format('truetype'), - url('iconfont.svg?t=1712045188451#panel') format('svg'); + src: url('iconfont.woff2?t=1712805038256') format('woff2'), + url('iconfont.woff?t=1712805038256') format('woff'), + url('iconfont.ttf?t=1712805038256') format('truetype'), + url('iconfont.svg?t=1712805038256#panel') format('svg'); } .panel { @@ -15,7 +15,15 @@ } .p-xpack:before { - content: "\eb70"; + content: "\e604"; +} + +.p-gpu-2:before { + content: "\e6d8"; +} + +.p-gpu-1:before { + content: "\e623"; } .p-waf-4:before { diff --git a/frontend/src/assets/iconfont/iconfont.js b/frontend/src/assets/iconfont/iconfont.js index 763ee230f..f1c2d4f08 100644 --- a/frontend/src/assets/iconfont/iconfont.js +++ b/frontend/src/assets/iconfont/iconfont.js @@ -1 +1 @@ -window._iconfont_svg_string_3575356='',function(c){var l=(l=document.getElementsByTagName("script"))[l.length-1],h=l.getAttribute("data-injectcss"),l=l.getAttribute("data-disable-injectsvg");if(!l){var a,t,v,p,z,i=function(l,h){h.parentNode.insertBefore(l,h)};if(h&&!c.__iconfont__svg__cssinject__){c.__iconfont__svg__cssinject__=!0;try{document.write("")}catch(l){console&&console.log(l)}}a=function(){var l,h=document.createElement("div");h.innerHTML=c._iconfont_svg_string_3575356,(h=h.getElementsByTagName("svg")[0])&&(h.setAttribute("aria-hidden","true"),h.style.position="absolute",h.style.width=0,h.style.height=0,h.style.overflow="hidden",h=h,(l=document.body).firstChild?i(h,l.firstChild):l.appendChild(h))},document.addEventListener?~["complete","loaded","interactive"].indexOf(document.readyState)?setTimeout(a,0):(t=function(){document.removeEventListener("DOMContentLoaded",t,!1),a()},document.addEventListener("DOMContentLoaded",t,!1)):document.attachEvent&&(v=a,p=c.document,z=!1,d(),p.onreadystatechange=function(){"complete"==p.readyState&&(p.onreadystatechange=null,m())})}function m(){z||(z=!0,v())}function d(){try{p.documentElement.doScroll("left")}catch(l){return void setTimeout(d,50)}m()}}(window); \ No newline at end of file +window._iconfont_svg_string_3575356='',function(c){var l=(l=document.getElementsByTagName("script"))[l.length-1],h=l.getAttribute("data-injectcss"),l=l.getAttribute("data-disable-injectsvg");if(!l){var a,t,v,p,z,i=function(l,h){h.parentNode.insertBefore(l,h)};if(h&&!c.__iconfont__svg__cssinject__){c.__iconfont__svg__cssinject__=!0;try{document.write("")}catch(l){console&&console.log(l)}}a=function(){var l,h=document.createElement("div");h.innerHTML=c._iconfont_svg_string_3575356,(h=h.getElementsByTagName("svg")[0])&&(h.setAttribute("aria-hidden","true"),h.style.position="absolute",h.style.width=0,h.style.height=0,h.style.overflow="hidden",h=h,(l=document.body).firstChild?i(h,l.firstChild):l.appendChild(h))},document.addEventListener?~["complete","loaded","interactive"].indexOf(document.readyState)?setTimeout(a,0):(t=function(){document.removeEventListener("DOMContentLoaded",t,!1),a()},document.addEventListener("DOMContentLoaded",t,!1)):document.attachEvent&&(v=a,p=c.document,z=!1,d(),p.onreadystatechange=function(){"complete"==p.readyState&&(p.onreadystatechange=null,m())})}function m(){z||(z=!0,v())}function d(){try{p.documentElement.doScroll("left")}catch(l){return void setTimeout(d,50)}m()}}(window); \ No newline at end of file diff --git a/frontend/src/assets/iconfont/iconfont.json b/frontend/src/assets/iconfont/iconfont.json index 14cdccf1d..b270e0992 100644 --- a/frontend/src/assets/iconfont/iconfont.json +++ b/frontend/src/assets/iconfont/iconfont.json @@ -6,11 +6,25 @@ "description": "", "glyphs": [ { - "icon_id": "5387846", - "name": "钻石_o", + "icon_id": "4657672", + "name": "会员", "font_class": "xpack", - "unicode": "eb70", - "unicode_decimal": 60272 + "unicode": "e604", + "unicode_decimal": 58884 + }, + { + "icon_id": "640495", + "name": "详细信息", + "font_class": "gpu-2", + "unicode": "e6d8", + "unicode_decimal": 59096 + }, + { + "icon_id": "6176565", + "name": "监控", + "font_class": "gpu-1", + "unicode": "e623", + "unicode_decimal": 58915 }, { "icon_id": "8229531", diff --git a/frontend/src/assets/iconfont/iconfont.svg b/frontend/src/assets/iconfont/iconfont.svg index c063f5457..ae67d6d1e 100644 --- a/frontend/src/assets/iconfont/iconfont.svg +++ b/frontend/src/assets/iconfont/iconfont.svg @@ -14,7 +14,11 @@ /> - + + + + + diff --git a/frontend/src/assets/iconfont/iconfont.ttf b/frontend/src/assets/iconfont/iconfont.ttf index fe17259ba..1ecd75691 100644 Binary files a/frontend/src/assets/iconfont/iconfont.ttf and b/frontend/src/assets/iconfont/iconfont.ttf differ diff --git a/frontend/src/assets/iconfont/iconfont.woff b/frontend/src/assets/iconfont/iconfont.woff index 6101c65d6..c526804ec 100644 Binary files a/frontend/src/assets/iconfont/iconfont.woff and b/frontend/src/assets/iconfont/iconfont.woff differ diff --git a/frontend/src/assets/iconfont/iconfont.woff2 b/frontend/src/assets/iconfont/iconfont.woff2 index 716cc5a47..8eed41e89 100644 Binary files a/frontend/src/assets/iconfont/iconfont.woff2 and b/frontend/src/assets/iconfont/iconfont.woff2 differ diff --git a/frontend/src/lang/modules/en.ts b/frontend/src/lang/modules/en.ts index 6747bdaf6..40c76c3d9 100644 --- a/frontend/src/lang/modules/en.ts +++ b/frontend/src/lang/modules/en.ts @@ -892,6 +892,13 @@ const message = { up: 'Up', down: 'Down', interval: 'Interval(min)', + + gpuUtil: 'GPU Utilization', + temperature: 'Temperature', + performanceState: 'Performance State', + powerUsage: 'Power Usage', + memoryUsage: 'Memory Usage', + fanSpeed: 'Fan Speed', }, terminal: { conn: 'connection', @@ -1505,10 +1512,11 @@ const message = { knowMorePro: 'Learn More', closeAlert: 'The current page can be closed in the panel settings', introduce: 'Feature Introduction', - waf: 'Upgrade to the professional version to get interception maps, logs, blocking records, geographical location blocking, custom rules, custom blocking pages and other functions', - tamper: '1Panel tamper-proof function is a security measure used to protect a website from unauthorized modifications or tampering.', + waf: 'Upgrading to the professional version can provide features such as interception map, logs, block records, geographical location blocking, custom rules, custom interception pages, etc.', + tamper: 'Upgrading to the professional version can protect websites from unauthorized modifications or tampering.', + gpu: 'Upgrading to the professional version can help users visually monitor important parameters of GPU such as workload, temperature, memory usage in real time.', setting: - '1Panel interface settings function allow you to customize panel logos, welcome messages, and other information.', + 'Upgrading to the professional version allows customization of panel logo, welcome message, and other information.', }, clean: { scan: 'Start Scanning', diff --git a/frontend/src/lang/modules/tw.ts b/frontend/src/lang/modules/tw.ts index 2a39d3288..d39023162 100644 --- a/frontend/src/lang/modules/tw.ts +++ b/frontend/src/lang/modules/tw.ts @@ -852,6 +852,13 @@ const message = { up: '上行', down: '下行', interval: '采集間隔(分鐘)', + + gpuUtil: 'GPU 使用率', + temperature: '溫度', + performanceState: '性能狀態', + powerUsage: '功耗', + memoryUsage: '顯存使用率', + fanSpeed: '風扇轉速', }, terminal: { conn: '連接', @@ -1404,9 +1411,10 @@ const message = { knowMorePro: '了解更多', closeAlert: '當前頁面可在面板設置中關閉顯示', introduce: '功能介紹', - waf: '升級專業版可以獲得攔截地圖、日誌、封鎖記錄、地理位置封鎖、自訂規則、自訂攔截頁面等功能', - tamper: '1Panel 防篡改功能是一種用於保護網站免受未經授權的修改或篡改的安全措施。', - setting: '1Panel 介面設置功能可自定義面板 Logo、歡迎簡介等信息。', + waf: '升級專業版可以獲得攔截地圖、日誌、封鎖記錄、地理位置封禁、自定義規則、自定義攔截頁面等功能。', + tamper: '升級專業版可以保護網站免受未經授權的修改或篡改。', + gpu: '升級專業版可以幫助用戶實時直觀查看到 GPU 的工作負載、溫度、顯存等重要參數。', + setting: '升級專業版可以自定義面板 Logo、歡迎簡介等信息。', }, clean: { scan: '開始掃描', diff --git a/frontend/src/lang/modules/zh.ts b/frontend/src/lang/modules/zh.ts index 2b1ce36d2..57b3ddfbf 100644 --- a/frontend/src/lang/modules/zh.ts +++ b/frontend/src/lang/modules/zh.ts @@ -853,6 +853,13 @@ const message = { up: '上行', down: '下行', interval: '采集间隔(分钟)', + + gpuUtil: 'GPU 使用率', + temperature: '温度', + performanceState: '性能状态', + powerUsage: '功耗', + memoryUsage: '显存使用率', + fanSpeed: '风扇转速', }, terminal: { conn: '连接', @@ -1405,9 +1412,10 @@ const message = { knowMorePro: '了解更多', closeAlert: '当前页面可在面板设置中关闭显示', introduce: '功能介绍', - waf: '升级专业版可以获得拦截地图、日志、封锁记录、地理位置封禁、自定义规则、自定义拦截页面等功能', - tamper: '1Panel 防篡改功能是一种用于保护网站免受未经授权的修改或篡改的安全措施。', - setting: '1Panel 界面设置功能可自定义面板 Logo、欢迎简介等信息。', + waf: '升级专业版可以获得拦截地图、日志、封锁记录、地理位置封禁、自定义规则、自定义拦截页面等功能。', + tamper: '升级专业版可以保护网站免受未经授权的修改或篡改。', + gpu: '升级专业版可以帮助用户实时直观查看到 GPU 的工作负载、温度、显存等重要参数。', + setting: '升级专业版可以自定义面板 Logo、欢迎简介等信息。', }, clean: { scan: '开始扫描', diff --git a/frontend/src/views/home/index.vue b/frontend/src/views/home/index.vue index 39127b1c3..489dc2e28 100644 --- a/frontend/src/views/home/index.vue +++ b/frontend/src/views/home/index.vue @@ -336,6 +336,7 @@ const currentInfo = ref({ ioWriteTime: 0, diskData: [], + gpuData: [], netBytesSent: 0, netBytesRecv: 0, diff --git a/frontend/src/views/home/status/index.vue b/frontend/src/views/home/status/index.vue index 288279a54..d3c2e198e 100644 --- a/frontend/src/views/home/status/index.vue +++ b/frontend/src/views/home/status/index.vue @@ -161,6 +161,59 @@ {{ computeSize(item.used) }} / {{ computeSize(item.total) }} + {{ $t('tabs.more') }} @@ -183,6 +236,7 @@