Skip to content

Commit 08c5728

Browse files
Merge pull request #112 from jinwandalaohu66/submission/salary_widget_mnyqeg8t
2 parents 8650a66 + b2ce294 commit 08c5728

2 files changed

Lines changed: 216 additions & 2 deletions

File tree

script_library/index.json

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"format_version": 1,
3-
"data_version": 91,
4-
"updated": "2026-04-14T11:44:03Z",
3+
"data_version": 92,
4+
"updated": "2026-04-14T14:43:21.842Z",
55
"announcement": null,
66
"categories": [
77
{
@@ -1561,6 +1561,29 @@
15611561
"updated": null,
15621562
"status": "active",
15631563
"lines": 146
1564+
},
1565+
{
1566+
"id": "salary_widget_mnyqeg8t",
1567+
"name": "salary_widget",
1568+
"name_en": "salary_widget",
1569+
"desc": "看看每天可以摸多少薪水",
1570+
"desc_en": "看看每天可以摸多少薪水",
1571+
"category": "widgets",
1572+
"file": "scripts/widgets/salary_widget_mnyqeg8t.py",
1573+
"thumbnail": null,
1574+
"version": 1,
1575+
"file_type": "py",
1576+
"author": "AirouLin",
1577+
"author_en": "AirouLin",
1578+
"tags": [
1579+
"community"
1580+
],
1581+
"requires": [],
1582+
"min_app_version": "1.5.0",
1583+
"added": "2026-04-14",
1584+
"updated": null,
1585+
"status": "active",
1586+
"lines": 192
15641587
}
15651588
]
15661589
}
Lines changed: 191 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,191 @@
1+
from widget import Widget, family, SMALL, MEDIUM, LARGE
2+
from datetime import datetime, date
3+
4+
# 年薪(元),修改此數值
5+
ANNUAL_SALARY = 1_000_000
6+
7+
# 台灣國定假日 2026
8+
TW_HOLIDAYS_2026 = {
9+
date(2026, 1, 1), # 元旦
10+
date(2026, 2, 16), # 除夕
11+
date(2026, 2, 17), # 春節
12+
date(2026, 2, 18), # 春節
13+
date(2026, 2, 19), # 春節
14+
date(2026, 2, 20), # 春節
15+
date(2026, 2, 28), # 和平紀念日
16+
date(2026, 4, 3), # 兒童節
17+
date(2026, 4, 4), # 清明節
18+
date(2026, 5, 1), # 勞動節
19+
date(2026, 6, 19), # 端午節
20+
date(2026, 9, 25), # 中秋節
21+
date(2026, 10, 9), # 國慶日補假
22+
date(2026, 10, 10), # 國慶日
23+
}
24+
25+
TW_HOLIDAYS = TW_HOLIDAYS_2026
26+
27+
28+
# 判斷是否為工作日,排除週六日與國定假日
29+
def is_workday(d):
30+
if d.weekday() >= 5: # 週六=5, 週日=6
31+
return False
32+
if d in TW_HOLIDAYS:
33+
return False
34+
return True
35+
36+
37+
# 計算指定年份的總工作天數
38+
def count_workdays_in_year(year):
39+
d = date(year, 1, 1)
40+
count = 0
41+
while d.year == year:
42+
if is_workday(d):
43+
count += 1
44+
d = date.fromordinal(d.toordinal() + 1)
45+
return count
46+
47+
48+
# 計算今天已賺的金額與年度累積
49+
def calc_earned_today(salary):
50+
now = datetime.now()
51+
today = now.date()
52+
year = today.year
53+
54+
total_workdays = count_workdays_in_year(year)
55+
daily_salary = salary / total_workdays
56+
57+
# 今年元旦到昨天的工作日數
58+
days_elapsed = (today - date(year, 1, 1)).days
59+
workdays_before_today = sum(
60+
1 for i in range(days_elapsed)
61+
if is_workday(date.fromordinal(date(year, 1, 1).toordinal() + i))
62+
)
63+
64+
today_is_workday = is_workday(today)
65+
66+
if today_is_workday:
67+
# 工作時間 08:20 ~ 17:45
68+
work_start = now.replace(hour=8, minute=20, second=0, microsecond=0)
69+
work_end = now.replace(hour=17, minute=45, second=0, microsecond=0)
70+
71+
if now < work_start:
72+
fraction = 0.0
73+
elif now >= work_end:
74+
fraction = 1.0
75+
else:
76+
elapsed = (now - work_start).total_seconds()
77+
total = (work_end - work_start).total_seconds()
78+
fraction = elapsed / total
79+
80+
today_earned = daily_salary * fraction
81+
else:
82+
fraction = 0.0
83+
today_earned = 0.0
84+
85+
ytd_earned = (workdays_before_today + (fraction if today_is_workday else 0)) * daily_salary
86+
87+
return {
88+
"today_earned": today_earned,
89+
"ytd_earned": ytd_earned,
90+
"daily_salary": daily_salary,
91+
"total_workdays": total_workdays,
92+
"today_is_workday": today_is_workday,
93+
"fraction": fraction,
94+
"now": now,
95+
}
96+
97+
98+
# 執行計算
99+
info = calc_earned_today(ANNUAL_SALARY)
100+
now = info["now"]
101+
102+
fmt_today = f"${info['today_earned']:,.0f}"
103+
fmt_ytd = f"${info['ytd_earned']:,.0f}"
104+
fmt_daily = f"${info['daily_salary']:,.0f}"
105+
progress_val = info["fraction"]
106+
107+
day_status = "工作日 💼" if info["today_is_workday"] else "假日 🎉"
108+
time_str = now.strftime("%H:%M")
109+
date_str = now.strftime("%m/%d")
110+
111+
# 工作日顯示綠色進度條,假日顯示灰色
112+
bar_color = "#4ADE80" if info["today_is_workday"] else "#6B7280"
113+
114+
# 建立 Widget,深色背景
115+
w = Widget(background=("#0F172A", "#0F172A"), padding=0)
116+
117+
if family == SMALL:
118+
with w.vstack(spacing=6, padding=12):
119+
w.text("今日薪資", size=11, color="#94A3B8", weight="medium")
120+
w.text(fmt_today, size=22, color="#4ADE80", weight="bold")
121+
w.spacer(length=2)
122+
w.progress(progress_val, color=bar_color, height=5, track_color="#1E293B")
123+
w.text(f"{date_str} {time_str} {day_status}", size=10, color="#64748B")
124+
125+
elif family == LARGE:
126+
with w.vstack(spacing=10, padding=16):
127+
# 標題列
128+
with w.hstack(spacing=6):
129+
w.icon("dollarsign.circle.fill", size=16, color="#4ADE80")
130+
w.text("薪資追蹤器", size=14, color="#CBD5E1", weight="semibold")
131+
w.spacer()
132+
w.text(f"{date_str} {time_str}", size=12, color="#64748B")
133+
134+
w.divider(color="#1E293B")
135+
136+
# 今日薪資
137+
w.text("今日已賺", size=12, color="#94A3B8")
138+
w.text(fmt_today, size=36, color="#4ADE80", weight="bold")
139+
w.text(day_status, size=12, color="#94A3B8")
140+
141+
# 進度條與百分比
142+
w.progress(progress_val, color=bar_color, height=8, track_color="#1E293B")
143+
w.text(f"工作進度 {progress_val * 100:.0f}%", size=11, color="#64748B", align="trailing")
144+
145+
w.spacer(length=4)
146+
w.divider(color="#1E293B")
147+
148+
# 年度統計三欄
149+
with w.hstack(spacing=8):
150+
with w.card(background="#1E293B", corner_radius=10, padding=10):
151+
w.text("年薪", size=11, color="#94A3B8")
152+
w.text(f"${ANNUAL_SALARY:,}", size=14, color="white", weight="bold")
153+
with w.card(background="#1E293B", corner_radius=10, padding=10):
154+
w.text("日薪", size=11, color="#94A3B8")
155+
w.text(fmt_daily, size=14, color="white", weight="bold")
156+
with w.card(background="#1E293B", corner_radius=10, padding=10):
157+
w.text("年度累積", size=11, color="#94A3B8")
158+
w.text(fmt_ytd, size=14, color="#FCD34D", weight="bold")
159+
160+
else:
161+
# MEDIUM 尺寸(預設)
162+
with w.vstack(spacing=0, padding=6):
163+
# 上半:今日薪資 + 時間狀態
164+
with w.hstack():
165+
with w.vstack(spacing=2, align="leading"):
166+
w.text("今日薪資", size=15, color="#94A3B8", weight="medium")
167+
w.text(fmt_today, size=44, color="#4ADE80", weight="bold")
168+
w.spacer()
169+
with w.vstack(spacing=3, align="trailing"):
170+
w.text(date_str, size=16, color="#64748B", weight="medium")
171+
w.text(time_str, size=23, color="#CBD5E1", weight="semibold")
172+
w.text(day_status, size=15, color="#94A3B8")
173+
174+
w.spacer()
175+
176+
# 進度條
177+
w.progress(progress_val, color=bar_color, height=8, track_color="#1E293B")
178+
179+
w.spacer(length=6)
180+
181+
# 下半:日薪 + 年度累計
182+
with w.hstack(padding=2):
183+
with w.vstack(spacing=2, align="leading"):
184+
w.text("日薪", size=14, color="#64748B")
185+
w.text(fmt_daily, size=20, color="#CBD5E1", weight="semibold")
186+
w.spacer()
187+
with w.vstack(spacing=2, align="trailing"):
188+
w.text("年度累積", size=14, color="#64748B")
189+
w.text(fmt_ytd, size=20, color="#FCD34D", weight="semibold")
190+
191+
w.render()

0 commit comments

Comments
 (0)