@@ -1302,6 +1302,8 @@ def __init__(self):
13021302 self ._base_icon_path : Optional [str ] = icon
13031303 self ._ring_icon_path : Optional [str ] = os .path .join (CONFIG_DIR , "ring_icon.png" )
13041304 self ._last_ring_val : Optional [int ] = None # 0..100 整数缓存,避免频繁重绘
1305+ # 圆环图标上次渲染状态签名(包含百分比、配色与文字内容等),用于决定是否需要重绘
1306+ self ._last_ring_key : Optional [str ] = None
13051307
13061308 # 信息区(只读)
13071309 self .info_title = rumps .MenuItem (_t ("status_uninitialized" ))
@@ -2003,6 +2005,7 @@ def _toggle_ring_colored(self, _: Optional[rumps.MenuItem] = None):
20032005 save_config (self ._cfg )
20042006 # 强制下次重绘
20052007 self ._last_ring_val = None
2008+ self ._last_ring_key = None
20062009 self ._update_ring_menu_checkmarks ()
20072010 self ._render_cached_state ()
20082011
@@ -2012,6 +2015,7 @@ def _toggle_ring_reverse(self, _: Optional[rumps.MenuItem] = None):
20122015 self ._cfg ["ring_reverse" ] = not cur
20132016 save_config (self ._cfg )
20142017 self ._last_ring_val = None
2018+ self ._last_ring_key = None
20152019 self ._update_ring_menu_checkmarks ()
20162020 self ._render_cached_state ()
20172021
@@ -2021,6 +2025,7 @@ def _toggle_ring_text(self, _: Optional[rumps.MenuItem] = None):
20212025 self ._cfg ["ring_text_enabled" ] = not cur
20222026 save_config (self ._cfg )
20232027 self ._last_ring_val = None
2028+ self ._last_ring_key = None
20242029 self ._update_ring_menu_checkmarks ()
20252030 self ._render_cached_state ()
20262031
@@ -2030,6 +2035,7 @@ def _toggle_ring_text_percent(self, _: Optional[rumps.MenuItem] = None):
20302035 self ._cfg ["ring_text_percent_sign" ] = not cur
20312036 save_config (self ._cfg )
20322037 self ._last_ring_val = None
2038+ self ._last_ring_key = None
20332039 self ._update_ring_menu_checkmarks ()
20342040 self ._render_cached_state ()
20352041
@@ -2039,6 +2045,7 @@ def _toggle_ring_text_label(self, _: Optional[rumps.MenuItem] = None):
20392045 self ._cfg ["ring_text_show_label" ] = not cur
20402046 save_config (self ._cfg )
20412047 self ._last_ring_val = None
2048+ self ._last_ring_key = None
20422049 self ._update_ring_menu_checkmarks ()
20432050 self ._render_cached_state ()
20442051
@@ -2047,6 +2054,7 @@ def _set_ring_text_mode_percent(self, _: Optional[rumps.MenuItem] = None):
20472054 self ._cfg ["ring_text_mode" ] = "percent"
20482055 save_config (self ._cfg )
20492056 self ._last_ring_val = None
2057+ self ._last_ring_key = None
20502058 self ._update_ring_menu_checkmarks ()
20512059 self ._render_cached_state ()
20522060
@@ -2055,6 +2063,7 @@ def _set_ring_text_mode_calls(self, _: Optional[rumps.MenuItem] = None):
20552063 self ._cfg ["ring_text_mode" ] = "calls"
20562064 save_config (self ._cfg )
20572065 self ._last_ring_val = None
2066+ self ._last_ring_key = None
20582067 self ._update_ring_menu_checkmarks ()
20592068 self ._render_cached_state ()
20602069
@@ -2063,6 +2072,7 @@ def _set_ring_text_mode_spent(self, _: Optional[rumps.MenuItem] = None):
20632072 self ._cfg ["ring_text_mode" ] = "spent"
20642073 save_config (self ._cfg )
20652074 self ._last_ring_val = None
2075+ self ._last_ring_key = None
20662076 self ._update_ring_menu_checkmarks ()
20672077 self ._render_cached_state ()
20682078
@@ -2071,6 +2081,7 @@ def _set_ring_color_mode_colorful(self, _: Optional[rumps.MenuItem] = None):
20712081 self ._cfg ["ring_color_mode" ] = "colorful"
20722082 save_config (self ._cfg )
20732083 self ._last_ring_val = None
2084+ self ._last_ring_key = None
20742085 self ._update_ring_menu_checkmarks ()
20752086 self ._render_cached_state ()
20762087
@@ -2079,6 +2090,7 @@ def _set_ring_color_mode_green(self, _: Optional[rumps.MenuItem] = None):
20792090 self ._cfg ["ring_color_mode" ] = "green"
20802091 save_config (self ._cfg )
20812092 self ._last_ring_val = None
2093+ self ._last_ring_key = None
20822094 self ._update_ring_menu_checkmarks ()
20832095 self ._render_cached_state ()
20842096
@@ -2087,6 +2099,7 @@ def _set_ring_color_mode_blue(self, _: Optional[rumps.MenuItem] = None):
20872099 self ._cfg ["ring_color_mode" ] = "blue"
20882100 save_config (self ._cfg )
20892101 self ._last_ring_val = None
2102+ self ._last_ring_key = None
20902103 self ._update_ring_menu_checkmarks ()
20912104 self ._render_cached_state ()
20922105
@@ -2095,6 +2108,7 @@ def _set_ring_color_mode_gradient(self, _: Optional[rumps.MenuItem] = None):
20952108 self ._cfg ["ring_color_mode" ] = "gradient"
20962109 save_config (self ._cfg )
20972110 self ._last_ring_val = None
2111+ self ._last_ring_key = None
20982112 self ._update_ring_menu_checkmarks ()
20992113 self ._render_cached_state ()
21002114
@@ -2514,6 +2528,52 @@ def _make_title(self, info: Dict[str, Any], usage: Optional[Dict[str, Any]]) ->
25142528 return title
25152529
25162530 # ------------- 圆环图标渲染 -------------
2531+ def _compute_ring_text (self , percent : int ) -> str :
2532+ """根据当前配置与数据,计算圆环内部需显示的文本。如果未启用则返回空串。"""
2533+ try :
2534+ if not bool (self ._cfg .get ("ring_text_enabled" , False )):
2535+ return ""
2536+ src = (self ._cfg .get ("ring_source" ) or "daily" ).lower ()
2537+ mode_txt = (self ._cfg .get ("ring_text_mode" ) or "percent" ).lower ()
2538+ if mode_txt == "calls" :
2539+ calls = None
2540+ try :
2541+ u = getattr (self , "_last_usage" , None ) or {}
2542+ tu = u .get ("today_usage" ) or {}
2543+ calls = int (tu .get ("api_calls" )) if (tu and tu .get ("api_calls" ) is not None ) else None
2544+ except Exception :
2545+ calls = None
2546+ text = str (calls ) if calls is not None else "-"
2547+ elif mode_txt == "spent" :
2548+ v = None
2549+ try :
2550+ info = getattr (self , "_last_data" , None ) or {}
2551+ if src == "monthly" :
2552+ v = float (info .get ("monthly_spent_usd" )) if info .get ("monthly_spent_usd" ) is not None else None
2553+ else :
2554+ v = float (info .get ("daily_spent_usd" )) if info .get ("daily_spent_usd" ) is not None else None
2555+ except Exception :
2556+ v = None
2557+ if v is None :
2558+ text = "-"
2559+ else :
2560+ if v >= 1000 :
2561+ text = "999+"
2562+ elif v >= 10 :
2563+ text = f"{ int (v ):d} "
2564+ else :
2565+ text = f"{ v :.1f} "
2566+ else :
2567+ val = int (percent )
2568+ show_pct = bool (self ._cfg .get ("ring_text_percent_sign" , True ))
2569+ text = f"{ val } %" if show_pct else f"{ val } "
2570+ if bool (self ._cfg .get ("ring_text_show_label" , False )):
2571+ prefix = "D" if src != "monthly" else "M"
2572+ text = f"{ prefix } { text } "
2573+ return text
2574+ except Exception :
2575+ return ""
2576+
25172577 def _apply_ring_icon (self , d_pct : Optional [float ], m_pct : Optional [float ]) -> None :
25182578 try :
25192579 enabled = bool (self ._cfg .get ("ring_enabled" , False ))
@@ -2527,6 +2587,7 @@ def _apply_ring_icon(self, d_pct: Optional[float], m_pct: Optional[float]) -> No
25272587 if self .icon != self ._base_icon_path :
25282588 self .icon = self ._base_icon_path
25292589 self ._last_ring_val = None
2590+ self ._last_ring_key = None
25302591 return
25312592
25322593 # 选择来源
@@ -2543,7 +2604,13 @@ def _apply_ring_icon(self, d_pct: Optional[float], m_pct: Optional[float]) -> No
25432604 self ._last_ring_val = None
25442605 return
25452606 iv = int (max (0 , min (100 , round (val ))))
2546- if self ._last_ring_val is not None and self ._last_ring_val == iv :
2607+ # 计算当前渲染签名:百分比、配色模式/反转、以及内部文字
2608+ colored = bool (self ._cfg .get ("ring_colored" , False ))
2609+ mode = (self ._cfg .get ("ring_color_mode" ) or "colorful" ).lower ()
2610+ reverse = bool (self ._cfg .get ("ring_reverse" , False ))
2611+ text = self ._compute_ring_text (iv )
2612+ cur_key = f"{ iv } |{ colored } |{ mode } |{ reverse } |{ text } "
2613+ if self ._last_ring_key is not None and self ._last_ring_key == cur_key :
25472614 return
25482615
25492616 # 绘制 PNG,并将应用图标切换为模板模式
@@ -2557,6 +2624,7 @@ def _apply_ring_icon(self, d_pct: Optional[float], m_pct: Optional[float]) -> No
25572624 pass
25582625 self .icon = out_path
25592626 self ._last_ring_val = iv
2627+ self ._last_ring_key = cur_key
25602628 else :
25612629 # 失败退回基础图标
25622630 try :
@@ -2566,11 +2634,13 @@ def _apply_ring_icon(self, d_pct: Optional[float], m_pct: Optional[float]) -> No
25662634 if self ._base_icon_path :
25672635 self .icon = self ._base_icon_path
25682636 self ._last_ring_val = None
2637+ self ._last_ring_key = None
25692638 except Exception :
25702639 try :
25712640 if self ._base_icon_path :
25722641 self .icon = self ._base_icon_path
25732642 self ._last_ring_val = None
2643+ self ._last_ring_key = None
25742644 except Exception :
25752645 pass
25762646
@@ -2696,50 +2766,8 @@ def _draw_ring_png(self, percent: int) -> Optional[str]:
26962766
26972767 # 文字:在圆环内显示内容(百分比/调用次数/使用金额)
26982768 try :
2699- if bool (self ._cfg .get ("ring_text_enabled" , False )):
2700- src = (self ._cfg .get ("ring_source" ) or "daily" ).lower ()
2701- mode_txt = (self ._cfg .get ("ring_text_mode" ) or "percent" ).lower ()
2702- text = ""
2703- if mode_txt == "calls" :
2704- # 今日调用次数
2705- calls = None
2706- try :
2707- u = getattr (self , "_last_usage" , None ) or {}
2708- tu = u .get ("today_usage" ) or {}
2709- calls = int (tu .get ("api_calls" )) if (tu and tu .get ("api_calls" ) is not None ) else None
2710- except Exception :
2711- calls = None
2712- text = str (calls ) if calls is not None else "-"
2713- elif mode_txt == "spent" :
2714- # 已用金额(按来源)
2715- v = None
2716- try :
2717- info = getattr (self , "_last_data" , None ) or {}
2718- if src == "monthly" :
2719- v = float (info .get ("monthly_spent_usd" )) if info .get ("monthly_spent_usd" ) is not None else None
2720- else :
2721- v = float (info .get ("daily_spent_usd" )) if info .get ("daily_spent_usd" ) is not None else None
2722- except Exception :
2723- v = None
2724- if v is None :
2725- text = "-"
2726- else :
2727- # 简洁格式:<10 保留1位小数;>=10 取整;>=1000 显示999+
2728- if v >= 1000 :
2729- text = "999+"
2730- elif v >= 10 :
2731- text = f"{ int (v ):d} "
2732- else :
2733- text = f"{ v :.1f} "
2734- else :
2735- # 百分比
2736- val = int (percent )
2737- show_pct = bool (self ._cfg .get ("ring_text_percent_sign" , True ))
2738- text = f"{ val } %" if show_pct else f"{ val } "
2739- # 可选来源标签(D/M)
2740- if bool (self ._cfg .get ("ring_text_show_label" , False )):
2741- prefix = "D" if src != "monthly" else "M"
2742- text = f"{ prefix } { text } "
2769+ text = self ._compute_ring_text (percent )
2770+ if text :
27432771 # 字号根据位数微调
27442772 fs = 8.0 if percent < 100 else 7.0
27452773 para = NSMutableParagraphStyle .alloc ().init ()
0 commit comments