package tui import ( "fmt" "get-container/utils" "regexp" "strconv" "strings" "github.com/charmbracelet/bubbles/progress" tea "github.com/charmbracelet/bubbletea" "github.com/charmbracelet/lipgloss" "github.com/muesli/termenv" ) type ModelDCUInfo struct { pro progress.Model // 进度条 proWidth int // 进度条宽度 modMsg *ModelMsg width, height int } const ( TopLine = `╞═══════════════════════════════╪══════════════════════╪══════════════════════╪` MiddleLine = `├───────────────────────────────┼──────────────────────┼──────────────────────┼` BottomLine = `╞═══════════════════════════════╧══════════════════════╧══════════════════════╪` OtherWidth = 8 StaticWidth = 79 // 固定表格的宽度 ProgressMinWidth = 15 // 进度条最小宽度 ) var ( ReDCUName = regexp.MustCompile(`(?i)^[A-Z0-9-_]*`) ) func NewModelDCUInfo(w, h int) *ModelDCUInfo { return &ModelDCUInfo{width: w, height: h} } func (m *ModelDCUInfo) Init() tea.Cmd { if m.width < StaticWidth+ProgressMinWidth+OtherWidth { return tea.Quit } m.proWidth = ProgressMinWidth if m.width > StaticWidth+ProgressMinWidth+OtherWidth { m.proWidth = m.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: m.modMsg = msg return m, nil case tea.WindowSizeMsg: m.height = msg.Height m.width = msg.Width return m, nil } return m, nil } func (m *ModelDCUInfo) View() string { if m.modMsg == nil { return "" } lineWidth := 0 qmap, qlock := m.modMsg.DCUInfo.GetQuitInfo() smap, slock := m.modMsg.DCUInfo.GetSlowInfo() defer slock.Unlock() defer qlock.Unlock() conTime := 0 strBuilder := strings.Builder{} infos := make([]string, 0) for i := range 128 { qinfo, haveq := qmap[i] sinfo, haves := smap[i] if !(haveq || haves) { conTime++ if conTime > 8 { break } continue } strBuilder.WriteString(myBorder.Left) strBuilder.WriteByte(' ') strBuilder.WriteString(FormatStr(strconv.Itoa(qinfo.Id), 4, lipgloss.Left)) strBuilder.WriteByte(' ') strBuilder.WriteString(FormatStr(ReDCUName.FindString(qinfo.Name), 8, lipgloss.Left)) strBuilder.WriteByte(' ') strBuilder.WriteString(FormatStr(qinfo.PerformanceLevel, 15, lipgloss.Right)) strBuilder.WriteByte(' ') strBuilder.WriteString(myBorder.Left) strBuilder.WriteByte(' ') strBuilder.WriteString(FormatStr(qinfo.BusId, 13, lipgloss.Left)) strBuilder.WriteByte(' ') strBuilder.WriteString(FormatStr("Off", 6, lipgloss.Right)) strBuilder.WriteByte(' ') strBuilder.WriteString(myBorder.Left) strBuilder.WriteByte(' ') if sinfo.Mig.Load() { strBuilder.WriteString(FormatStr("On", 16, lipgloss.Left)) } else { strBuilder.WriteString(FormatStr("Off", 16, lipgloss.Left)) } strBuilder.WriteByte(' ') if sinfo.Ecc.Load() { 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(qinfo.DCUUTil / 100))) strBuilder.WriteByte(' ') strBuilder.WriteString(myBorder.Left) strBuilder.WriteByte('\n') strBuilder.WriteString(myBorder.Left) strBuilder.WriteByte(' ') strBuilder.WriteString(FormatStr(qinfo.Fan, 4, lipgloss.Left)) strBuilder.WriteByte(' ') strBuilder.WriteString(FormatStr(fmt.Sprintf("%.1fC", qinfo.Temp), 6, lipgloss.Left)) strBuilder.WriteByte(' ') // 18 strBuilder.WriteString(FormatStr(fmt.Sprintf("%.1fW / %.1fW", qinfo.PwrAvg, qinfo.PwrCap), 17, lipgloss.Right)) strBuilder.WriteByte(' ') strBuilder.WriteString(myBorder.Left) strBuilder.WriteByte(' ') // 20 strBuilder.WriteString(FormatStr(fmt.Sprintf("%dMiB / %dMiB", qinfo.MemUsed/uint64(utils.MiB), qinfo.MemTotal/uint64(utils.MiB)), 20, lipgloss.Right)) strBuilder.WriteByte(' ') strBuilder.WriteString(myBorder.Left) strBuilder.WriteByte(' ') strBuilder.WriteString(FormatStr(fmt.Sprintf("%.1f%%", qinfo.DCUUTil), 6, lipgloss.Left)) strBuilder.WriteByte(' ') strBuilder.WriteString(FormatStr(sinfo.PwrMode.Load().(string), 13, lipgloss.Right)) strBuilder.WriteByte(' ') strBuilder.WriteString(myBorder.Left) strBuilder.WriteString(" Mem: ") strBuilder.WriteString(m.pro.ViewAs(float64(qinfo.MemUsed) / float64(qinfo.MemTotal))) strBuilder.WriteByte(' ') strBuilder.WriteString(myBorder.Left) infos = append(infos, 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 }