五件套徒手健身打卡应用:FastAPI+Vue3+PWA

This commit is contained in:
2026-08-13 06:33:56 +08:00
commit d529dad183
915 changed files with 295087 additions and 0 deletions
Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

File diff suppressed because one or more lines are too long
+1
View File
@@ -0,0 +1 @@
:root{--bg: #fdfaf3;--card: #ffffff;--text: #4a3f3a;--sub: #9e8f84;--orange: #f15a29;--orange-light: #fdeee6;--orange-dark: #d64a1e;--shadow: 0 2px 14px rgba(241, 90, 41, .1);--radius: 18px;--radius-sm: 12px}*{margin:0;padding:0;box-sizing:border-box}body{background:var(--bg);color:var(--text);font-family:Noto Sans SC,-apple-system,BlinkMacSystemFont,PingFang SC,sans-serif;-webkit-font-smoothing:antialiased}.app{max-width:720px;margin:0 auto;padding:16px 16px 40px}.topbar{display:flex;align-items:center;justify-content:space-between;padding:14px 6px}.logo{font-size:22px;font-weight:800;color:var(--orange)}.topbar-right{display:flex;gap:8px}.streak-badge,.weight-badge{background:var(--orange-light);color:var(--orange-dark);font-size:13px;font-weight:700;padding:6px 12px;border-radius:999px}.install-banner{display:flex;align-items:center;gap:10px;background:var(--card);border:2px solid #f8e3d3;border-radius:var(--radius-sm);padding:10px 14px;margin-bottom:14px;font-size:14px;box-shadow:var(--shadow)}.install-banner .btn-close{margin-left:auto;background:none;border:none;font-size:18px;color:var(--sub);cursor:pointer}.card{background:var(--card);border-radius:var(--radius);padding:20px;margin-bottom:16px;box-shadow:var(--shadow)}.card-title{display:flex;align-items:center;gap:8px;font-size:17px;font-weight:800;margin-bottom:14px}.card-title-icon{font-size:20px}.date-hint{margin-left:auto;font-size:13px;color:var(--sub);font-weight:500}.action-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(120px,1fr));gap:12px}.action-item{background:var(--bg);border-radius:var(--radius-sm);padding:12px 8px;text-align:center}.action-emoji{font-size:26px}.action-name{font-size:13px;font-weight:700;margin:4px 0 8px}.action-input{display:flex;align-items:center;justify-content:center;gap:4px}.step-btn{width:28px;height:28px;border:2px solid var(--orange-light);background:#fff;color:var(--orange);border-radius:8px;font-size:16px;font-weight:700;cursor:pointer;transition:all .2s}.step-btn:active{transform:scale(.9)}.num-input{width:52px;text-align:center;border:2px solid #f0e2d5;border-radius:8px;padding:5px 2px;font-size:15px;font-weight:700;color:var(--text);background:#fff;outline:none}.num-input:focus{border-color:var(--orange)}.action-unit{font-size:11px;color:var(--sub);margin-top:4px}.today-prev{margin-top:12px;font-size:13px;color:var(--sub);background:var(--bg);padding:8px 12px;border-radius:var(--radius-sm)}.prev-hint{font-weight:700;color:var(--text)}.prev-text{color:var(--sub)}.btn{cursor:pointer;border:2px solid transparent;border-radius:var(--radius-sm);font-size:15px;font-weight:700;padding:11px 20px;transition:all .2s ease;font-family:inherit}.btn:active{transform:scale(.95)}.btn-primary{background:linear-gradient(135deg,#f15a29,#f48a5e);color:#fff;box-shadow:0 4px 14px #f15a294d}.btn-primary:hover{transform:translateY(-2px)}.btn-primary:disabled{opacity:.6;cursor:not-allowed}.btn-secondary{background:#fff;color:var(--orange);border:2px solid var(--orange-light)}.btn-secondary:hover{background:var(--orange-light);border-color:var(--orange-dark)}.btn-sm{padding:6px 14px;font-size:13px}.btn-save{width:100%;margin-top:14px;padding:13px;font-size:16px}.save-tip{text-align:center;margin-top:10px;color:var(--orange-dark);font-weight:700;font-size:14px}.stat-grid{display:grid;grid-template-columns:repeat(4,1fr);gap:8px;text-align:center}.stat-item{background:var(--bg);border-radius:var(--radius-sm);padding:12px 4px}.stat-num{font-size:22px;font-weight:800;color:var(--orange)}.stat-label{font-size:11px;color:var(--sub);margin-top:4px}.weight-trend{margin-top:12px;text-align:center;font-size:13px;color:var(--sub)}.weight-trend b.up{color:#2e9e5b}.weight-trend b.down{color:var(--orange-dark)}.weight-form{display:flex;gap:10px}.weight-input{flex:1;width:auto;text-align:left;padding:11px 14px;font-size:15px}.empty{text-align:center;color:var(--sub);padding:20px 0;font-size:14px}.history-item{display:flex;align-items:center;justify-content:space-between;gap:10px;padding:12px 0;border-bottom:1px solid #f7efe6}.history-item:last-child{border-bottom:none}.history-date{font-size:14px;font-weight:700;margin-bottom:6px}.history-chips{display:flex;flex-wrap:wrap;gap:6px}.chip{background:var(--orange-light);color:var(--orange-dark);font-size:12px;font-weight:700;padding:3px 9px;border-radius:999px}.chip-empty{font-size:12px;color:var(--sub)}.btn-del{background:none;border:none;font-size:16px;cursor:pointer;opacity:.4;transition:opacity .2s}.btn-del:hover{opacity:1}.foot{text-align:center;color:var(--sub);font-size:13px;margin-top:10px}@media (max-width: 420px){.stat-grid,.action-grid{grid-template-columns:repeat(2,1fr)}}
Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.7 KiB

+19
View File
@@ -0,0 +1,19 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, viewport-fit=cover">
<meta name="theme-color" content="#f15a29">
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent">
<meta name="apple-mobile-web-app-title" content="五件套">
<link rel="manifest" href="/manifest.json">
<link rel="apple-touch-icon" href="/icon-192.png">
<title>五件套 · 徒手健身打卡</title>
<script type="module" crossorigin src="/assets/index-CVxSxPPn.js"></script>
<link rel="stylesheet" crossorigin href="/assets/index-DiM9j3KJ.css">
</head>
<body>
<div id="app"></div>
</body>
</html>
+14
View File
@@ -0,0 +1,14 @@
{
"name": "五件套 · 徒手健身打卡",
"short_name": "五件套",
"description": "俯卧撑 · 深蹲 · 卷腹 · 登山跑 · 平板支撑 每日打卡",
"start_url": "/",
"display": "standalone",
"orientation": "portrait",
"background_color": "#fdfaf3",
"theme_color": "#f15a29",
"icons": [
{ "src": "/icon-192.png", "sizes": "192x192", "type": "image/png", "purpose": "any maskable" },
{ "src": "/icon-512.png", "sizes": "512x512", "type": "image/png", "purpose": "any maskable" }
]
}
+26
View File
@@ -0,0 +1,26 @@
const CACHE = 'workout-five-v1'
const ASSETS = ['/', '/manifest.json', '/icon-192.png', '/icon-512.png', '/apple-touch-icon.png']
self.addEventListener('install', (e) => {
e.waitUntil(caches.open(CACHE).then((c) => c.addAll(ASSETS)).then(() => self.skipWaiting()))
})
self.addEventListener('activate', (e) => {
e.waitUntil(
caches.keys().then((keys) => Promise.all(keys.filter((k) => k !== CACHE).map((k) => caches.delete(k)))).then(() => self.clients.claim())
)
})
self.addEventListener('fetch', (e) => {
const url = new URL(e.request.url)
if (e.request.method !== 'GET' || url.pathname.startsWith('/api/')) {
return // API 走网络
}
e.respondWith(
caches.match(e.request).then((hit) => hit || fetch(e.request).then((resp) => {
const clone = resp.clone()
caches.open(CACHE).then((c) => c.put(e.request, clone))
return resp
}))
)
})