package tui import ( "fmt" "get-container/cmd/hytop/backend" "maps" "regexp" "strconv" "strings" "github.com/charmbracelet/bubbles/progress" tea "github.com/charmbracelet/bubbletea" "github.com/charmbracelet/lipgloss" "github.com/muesli/termenv" ) type ModelDCUInfo struct { parent *ModelMain info map[int]backend.DCUInfo // dcu相关信息 pro progress.Model // 进度条 proWidth int // 进度条宽度 } const ( TopLine = `╞═══════════════════════════════╪══════════════════════╪══════════════════════╪` MiddleLine = `├───────────────────────────────┼──────────────────────┼──────────────────────┼` BottomLine = `╞═══════════════════════════════╧══════════════════════╧══════════════════════╪` OtherWidth = 8 StaticWidth = 79 // 固定表格的宽度 ProgressMinWidth = 15 // 进度条最小宽度 ) var ( ReDCUName = regexp.MustCompile(`(?i)^[A-Z0-9-_]*`) ) func NewModelDCUInfo(m *ModelMain) *ModelDCUInfo { return &ModelDCUInfo{ parent: m, info: make(map[int]backend.DCUInfo), } } func (m *ModelDCUInfo) Init() tea.Cmd { if m.parent.width < StaticWidth+ProgressMinWidth+OtherWidth { return tea.Quit } m.proWidth = ProgressMinWidth if m.parent.width > StaticWidth+ProgressMinWidth+OtherWidth { m.proWidth = m.parent.width - OtherWidth - StaticWidth } m.pro = progress.New(progress.WithColorProfile(termenv.TrueColor), progress.WithGradient("#0000ffff", "#ff0000ff"), progress.WithWidth(m.proWidth)) return nil } func (m *ModelDCUInfo) Update(inputMsg tea.Msg) (tea.Model, tea.Cmd) { switch msg := inputMsg.(type) { case *ModelMsg: clear(m.info) maps.Copy(m.info, msg.DCUInfo) return m, nil } return m, nil } func (m *ModelDCUInfo) View() string { lineWidth := 0 l := len(m.info) strBuilder := strings.Builder{} infos := make([]string, l) for i := range l { ii := m.info[i] strBuilder.WriteString(myBorder.Left) strBuilder.WriteByte(' ') strBuilder.WriteString(FormatStr(strconv.Itoa(ii.Id), 4, lipgloss.Left)) strBuilder.WriteByte(' ') strBuilder.WriteString(FormatStr(ReDCUName.FindString(ii.Name), 8, lipgloss.Left)) strBuilder.WriteByte(' ') strBuilder.WriteString(FormatStr(ii.PerformanceLevel, 15, lipgloss.Right)) strBuilder.WriteByte(' ') strBuilder.WriteString(myBorder.Left) strBuilder.WriteByte(' ') strBuilder.WriteString(FormatStr(ii.BusId, 13, lipgloss.Left)) strBuilder.WriteByte(' ') strBuilder.WriteString(FormatStr("Off", 6, lipgloss.Right)) strBuilder.WriteByte(' ') strBuilder.WriteString(myBorder.Left) strBuilder.WriteByte(' ') if ii.Mig { strBuilder.WriteString(FormatStr("On", 16, lipgloss.Left)) } else { strBuilder.WriteString(FormatStr("Off", 16, lipgloss.Left)) } strBuilder.WriteByte(' ') if ii.Ecc { strBuilder.WriteString(FormatStr("On", 3, lipgloss.Right)) } else { strBuilder.WriteString(FormatStr("Off", 3, lipgloss.Right)) } strBuilder.WriteByte(' ') strBuilder.WriteString(myBorder.Left) strBuilder.WriteString(" DCU: ") strBuilder.WriteString(m.pro.ViewAs(float64(ii.DCUUTil) / 100)) strBuilder.WriteByte(' ') strBuilder.WriteString(myBorder.Left) strBuilder.WriteByte('\n') strBuilder.WriteString(myBorder.Left) strBuilder.WriteByte(' ') strBuilder.WriteString(FormatStr(ii.Fan, 4, lipgloss.Left)) strBuilder.WriteByte(' ') strBuilder.WriteString(FormatStr(fmt.Sprintf("%.1fC", ii.Temp), 6, lipgloss.Left)) strBuilder.WriteByte(' ') // 18 strBuilder.WriteString(FormatStr(fmt.Sprintf("%.1fW / %.1fW", ii.PwrAvg, ii.PwrCap), 17, lipgloss.Right)) strBuilder.WriteByte(' ') strBuilder.WriteString(myBorder.Left) strBuilder.WriteByte(' ') // 20 strBuilder.WriteString(FormatStr(fmt.Sprintf("%dMiB / %dMiB", ii.MemUsed, ii.MemTotal), 20, lipgloss.Right)) strBuilder.WriteByte(' ') strBuilder.WriteString(myBorder.Left) strBuilder.WriteByte(' ') strBuilder.WriteString(FormatStr(fmt.Sprintf("%.1f%%", ii.DCUUTil), 6, lipgloss.Left)) strBuilder.WriteByte(' ') strBuilder.WriteString(FormatStr(ii.PwrMode, 13, lipgloss.Right)) strBuilder.WriteByte(' ') strBuilder.WriteString(myBorder.Left) strBuilder.WriteString(" Mem: ") strBuilder.WriteString(m.pro.ViewAs(float64(ii.MemUsedPerent) / 100)) strBuilder.WriteByte(' ') strBuilder.WriteString(myBorder.Left) infos[i] = strBuilder.String() strBuilder.Reset() } if len(infos) > 0 { lineWidth = lipgloss.Width(infos[0]) } subLen := lineWidth - StaticWidth - 1 if subLen <= 0 { subLen = 0 } top := TopLine + strings.Repeat("═", subLen) + "╕\n" middle := "\n" + MiddleLine + strings.Repeat("─", subLen) + "┤\n" bottom := "\n" + BottomLine + strings.Repeat("═", subLen) + "╡\n" return top + strings.Join(infos, middle) + bottom }