perf+ui: gzip (api/static precompressed), immutable attachment cache, responsive dialogs/header, safe-area + dynamic theme-color, mobile tuning
This commit is contained in:
@@ -63,6 +63,7 @@ docker compose -f docker-compose.caddy.yml build \
|
||||
|
||||
```caddyfile
|
||||
footprints.example.com {
|
||||
encode zstd gzip
|
||||
reverse_proxy footprints-sync:8788
|
||||
}
|
||||
```
|
||||
|
||||
@@ -15,9 +15,10 @@
|
||||
"title": "足迹 Footprints",
|
||||
"width": 1280,
|
||||
"height": 800,
|
||||
"minWidth": 960,
|
||||
"minHeight": 640,
|
||||
"center": true
|
||||
"minWidth": 420,
|
||||
"minHeight": 560,
|
||||
"center": true,
|
||||
"backgroundColor": "#f3f4f6"
|
||||
}
|
||||
],
|
||||
"security": {
|
||||
|
||||
@@ -29,7 +29,7 @@ export function Header({ onMenu }: { onMenu?: () => void }) {
|
||||
};
|
||||
|
||||
return (
|
||||
<header className="flex h-14 shrink-0 items-center gap-4 border-b border-line bg-surface px-5">
|
||||
<header className="flex h-14 shrink-0 items-center gap-2 border-b border-line bg-surface px-3 sm:gap-4 sm:px-5">
|
||||
<Button variant="ghost" size="icon" className="lg:hidden" onClick={onMenu} aria-label="打开导航">
|
||||
<Menu size={17} />
|
||||
</Button>
|
||||
@@ -39,7 +39,7 @@ export function Header({ onMenu }: { onMenu?: () => void }) {
|
||||
{meta.sub && <p className="truncate text-[11px] leading-tight text-ink-3">{meta.sub}</p>}
|
||||
</div>
|
||||
|
||||
<div className="relative ml-auto w-[280px]">
|
||||
<div className="relative ml-auto hidden w-[240px] md:block lg:w-[280px]">
|
||||
<Search size={14} className="pointer-events-none absolute left-2.5 top-1/2 -translate-y-1/2 text-ink-3" />
|
||||
<Input
|
||||
className="pl-8"
|
||||
@@ -58,9 +58,9 @@ export function Header({ onMenu }: { onMenu?: () => void }) {
|
||||
{dark ? <Sun size={15} /> : <Moon size={15} />}
|
||||
</Button>
|
||||
|
||||
<Button variant="primary" onClick={() => navigate('/records?new=1')}>
|
||||
<Button variant="primary" onClick={() => navigate('/records?new=1')} aria-label="新建记录">
|
||||
<Plus size={14} />
|
||||
新建记录
|
||||
<span className="hidden sm:inline">新建记录</span>
|
||||
</Button>
|
||||
</header>
|
||||
);
|
||||
|
||||
@@ -21,10 +21,10 @@ export function Dialog({ open, onClose, title, width = 560, children, footer }:
|
||||
if (!open) return null;
|
||||
|
||||
return createPortal(
|
||||
<div className="fixed inset-0 z-50 flex items-start justify-center overflow-y-auto p-6 pt-[8vh]">
|
||||
<div className="fixed inset-0 z-50 flex items-start justify-center overflow-y-auto p-3 pt-[6vh] sm:p-6 sm:pt-[8vh]">
|
||||
<div className="fixed inset-0 bg-black/45" onClick={onClose} />
|
||||
<div
|
||||
className="relative w-full rounded-lg border border-line bg-surface shadow-pop"
|
||||
className="animate-in relative w-full rounded-lg border border-line bg-surface shadow-pop"
|
||||
style={{ maxWidth: width }}
|
||||
role="dialog"
|
||||
>
|
||||
@@ -34,9 +34,9 @@ export function Dialog({ open, onClose, title, width = 560, children, footer }:
|
||||
<X size={15} />
|
||||
</Button>
|
||||
</div>
|
||||
<div className="px-4 py-4 max-h-[64vh] overflow-y-auto">{children}</div>
|
||||
<div className="max-h-[70vh] overflow-y-auto px-3 py-3 sm:px-4 sm:py-4">{children}</div>
|
||||
{footer && (
|
||||
<div className="flex items-center justify-end gap-2 border-t border-line px-4 h-14">
|
||||
<div className="flex flex-wrap items-center justify-end gap-2 border-t border-line px-3 py-2.5 sm:h-14 sm:flex-nowrap sm:px-4 sm:py-0">
|
||||
{footer}
|
||||
</div>
|
||||
)}
|
||||
|
||||
@@ -17,6 +17,14 @@ if (saved === 'dark' || (!saved && window.matchMedia('(prefers-color-scheme: dar
|
||||
document.documentElement.classList.add('dark');
|
||||
}
|
||||
|
||||
// 状态栏/标题栏颜色跟随主题(亮暗切换实时同步)
|
||||
function syncThemeColor() {
|
||||
const bg = getComputedStyle(document.documentElement).getPropertyValue('--bg').trim();
|
||||
if (bg) document.querySelector('meta[name="theme-color"]')?.setAttribute('content', bg);
|
||||
}
|
||||
syncThemeColor();
|
||||
window.addEventListener('fp-theme-change', syncThemeColor);
|
||||
|
||||
// PWA:仅生产构建且非桌面壳时注册(桌面端走 Tauri,无需 SW)
|
||||
if ('serviceWorker' in navigator && import.meta.env.PROD && !('__TAURI_INTERNALS__' in window)) {
|
||||
window.addEventListener('load', () => {
|
||||
|
||||
@@ -80,6 +80,17 @@
|
||||
|
||||
html, body, #root { height: 100%; }
|
||||
|
||||
/* 移动端适配:禁止横向溢出 / 去点按高亮 / 双击不缩放 / 刘海安全区 */
|
||||
html, body { overflow-x: clip; }
|
||||
body {
|
||||
-webkit-tap-highlight-color: transparent;
|
||||
touch-action: manipulation;
|
||||
padding: env(safe-area-inset-top) env(safe-area-inset-right) env(safe-area-inset-bottom) env(safe-area-inset-left);
|
||||
}
|
||||
@media (pointer: coarse) {
|
||||
button, [role='button'], a { min-height: 36px; }
|
||||
}
|
||||
|
||||
body {
|
||||
background: var(--bg);
|
||||
color: var(--text-1);
|
||||
@@ -95,6 +106,11 @@ body {
|
||||
|
||||
h1, h2, h3 { letter-spacing: -0.022em; text-wrap: balance; }
|
||||
|
||||
/* 小屏:分区标题与卡片间距收紧 */
|
||||
@media (max-width: 640px) {
|
||||
.hover-lift:hover { transform: none; }
|
||||
}
|
||||
|
||||
.num { font-variant-numeric: tabular-nums lining-nums; font-feature-settings: 'tnum' 1, 'lnum' 1; }
|
||||
|
||||
::selection { background: color-mix(in srgb, var(--brand) 18%, transparent); }
|
||||
|
||||
@@ -3,5 +3,6 @@
|
||||
# 注:域名不区分大小写,配置统一使用小写 footpr.linyux.cn
|
||||
|
||||
footpr.linyux.cn {
|
||||
encode zstd gzip
|
||||
reverse_proxy footprints-sync:8788
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
// Footprints 自建同步 + Web 服务(零依赖:node:http + node:sqlite)
|
||||
import http from 'node:http';
|
||||
import fs from 'node:fs';
|
||||
import zlib from 'node:zlib';
|
||||
import path from 'node:path';
|
||||
import { fileURLToPath } from 'node:url';
|
||||
import { getDb } from './db.mjs';
|
||||
@@ -26,6 +27,7 @@ const MIME = {
|
||||
|
||||
// 按用户惰性创建命令集(每个用户一个独立 SQLite 档案库)
|
||||
const userCommands = new Map();
|
||||
const gzipCache = new Map(); // 指纹资产 gzip 预压缩缓存
|
||||
let demoUserId;
|
||||
function commandsFor(userId) {
|
||||
let c = userCommands.get(userId);
|
||||
@@ -51,8 +53,16 @@ const server = http.createServer(async (req, res) => {
|
||||
const url = new URL(req.url, 'http://localhost');
|
||||
const route = url.pathname;
|
||||
const send = (code, ok, data) => {
|
||||
res.writeHead(code, { 'Content-Type': 'application/json; charset=utf-8' });
|
||||
res.end(JSON.stringify(ok ? { ok: true, data } : { ok: false, error: data }));
|
||||
let body = Buffer.from(JSON.stringify(ok ? { ok: true, data } : { ok: false, error: data }));
|
||||
const headers = { 'Content-Type': 'application/json; charset=utf-8' };
|
||||
// API JSON gzip:附件 base64 / 列表大负载体积降 70%+
|
||||
if (body.length >= 1024 && /\bgzip\b/.test(String(req.headers['accept-encoding'] || ''))) {
|
||||
body = zlib.gzipSync(body, { level: 6 });
|
||||
headers['Content-Encoding'] = 'gzip';
|
||||
headers.Vary = 'Accept-Encoding';
|
||||
}
|
||||
res.writeHead(code, headers);
|
||||
res.end(body);
|
||||
};
|
||||
|
||||
res.setHeader('Access-Control-Allow-Origin', '*');
|
||||
@@ -198,7 +208,9 @@ const server = http.createServer(async (req, res) => {
|
||||
if (!file) return send(404, false, '附件不存在');
|
||||
res.writeHead(200, {
|
||||
'Content-Type': file.mime || 'application/octet-stream',
|
||||
'Content-Length': file.buf.length
|
||||
'Content-Length': file.buf.length,
|
||||
// 内容寻址 = 不可变:浏览器一年缓存(private:不进共享缓存,杜绝跨账号串缓存)
|
||||
'Cache-Control': 'private, max-age=31536000, immutable'
|
||||
});
|
||||
return res.end(file.buf);
|
||||
}
|
||||
@@ -227,10 +239,21 @@ const server = http.createServer(async (req, res) => {
|
||||
let p = route === '/' ? '/index.html' : decodeURIComponent(route);
|
||||
const abs = path.join(WWW_DIR, path.normalize(p).replace(/^([.][.][\\/])+/, ''));
|
||||
if (abs.startsWith(WWW_DIR) && fs.existsSync(abs) && fs.statSync(abs).isFile()) {
|
||||
res.writeHead(200, {
|
||||
const headers = {
|
||||
'Content-Type': MIME[path.extname(abs).toLowerCase()] || 'application/octet-stream',
|
||||
'Cache-Control': p.startsWith('/assets/') ? 'public, max-age=31536000, immutable' : 'no-cache'
|
||||
});
|
||||
};
|
||||
// 指纹资产预压缩缓存(首次 gzip 后驻留内存,后续零 CPU)
|
||||
if (p.startsWith('/assets/') && /\.(js|css|svg|json)$/.test(p) && /\bgzip\b/.test(String(req.headers['accept-encoding'] || ''))) {
|
||||
let gz = gzipCache.get(abs);
|
||||
if (!gz) { gz = zlib.gzipSync(fs.readFileSync(abs), { level: 6 }); gzipCache.set(abs, gz); }
|
||||
headers['Content-Encoding'] = 'gzip';
|
||||
headers['Content-Length'] = gz.length;
|
||||
headers.Vary = 'Accept-Encoding';
|
||||
res.writeHead(200, headers);
|
||||
return res.end(gz);
|
||||
}
|
||||
res.writeHead(200, headers);
|
||||
return res.end(fs.readFileSync(abs));
|
||||
}
|
||||
const indexHtml = path.join(WWW_DIR, 'index.html');
|
||||
|
||||
+3
-3
File diff suppressed because one or more lines are too long
+1
-1
@@ -1 +1 @@
|
||||
import{r as g,e as v,j as t,S as j,s as S}from"./index-C2sli-Mk.js";import{C as c,a as d,b as x}from"./card-DL3ec4KP.js";import{u as N,i as u,a as m}from"./useChart-f1LAeREn.js";import{u as k,i as w,a as C,b as L,c as R,d as $,e as z,f as T}from"./echarts-BIWefrIc.js";k([w,C,L,R,$,z,T]);function q(){const[l,n]=g.useState(""),i=N(),e=v({queryKey:["stats",l||void 0],queryFn:()=>S(l?Number(l):void 0)}).data,p=u("2"),r=u("3"),h=m(()=>({grid:{left:34,right:12,top:14,bottom:24},tooltip:{trigger:"axis"},xAxis:{type:"category",data:(e==null?void 0:e.monthly.map(a=>a.ym.slice(2)))??[],axisLine:{lineStyle:{color:r}},axisTick:{show:!1},axisLabel:{color:r,fontSize:10}},yAxis:{type:"value",splitLine:{lineStyle:{color:"rgba(128,138,155,0.15)"}},axisLabel:{color:r,fontSize:10}},series:[{type:"bar",data:(e==null?void 0:e.monthly.map(a=>a.count))??[],barMaxWidth:18,itemStyle:{color:"#3056d3",borderRadius:[3,3,0,0]}}]}),[e,i]),b=m(()=>{const a=((e==null?void 0:e.by_type)??[]).filter(s=>s.count>0);return{tooltip:{trigger:"item"},legend:{orient:"vertical",right:4,top:"middle",textStyle:{color:p,fontSize:11},itemWidth:10,itemHeight:10},series:[{type:"pie",radius:["48%","72%"],center:["34%","50%"],label:{show:!1},data:a.map(s=>({name:s.label,value:s.count,itemStyle:{color:s.color||"#64748b"}}))}]}},[e,i]),y=m(()=>{const a=((e==null?void 0:e.by_level)??[]).filter(s=>s.count>0).slice().reverse();return{grid:{left:64,right:24,top:8,bottom:22},tooltip:{trigger:"axis"},xAxis:{type:"value",splitLine:{lineStyle:{color:"rgba(128,138,155,0.15)"}},axisLabel:{color:r,fontSize:10}},yAxis:{type:"category",data:a.map(s=>s.label),axisLine:{show:!1},axisTick:{show:!1},axisLabel:{color:p,fontSize:11}},series:[{type:"bar",data:a.map(s=>({value:s.count,itemStyle:{color:s.color||"#3056d3",borderRadius:[0,3,3,0]}})),barMaxWidth:14}]}},[e,i]),f=((e==null?void 0:e.metrics)??[]).slice(0,3);return t.jsxs("div",{className:"mx-auto max-w-[1080px] px-6 py-5",children:[t.jsxs("div",{className:"mb-4 flex flex-wrap items-center justify-between gap-3",children:[t.jsxs("div",{className:"flex flex-wrap gap-3",children:[t.jsx(o,{label:"总记录",value:(e==null?void 0:e.total)??0}),t.jsx(o,{label:l?l+" 年新增":"本年新增",value:(e==null?void 0:e.total_this_year)??0}),t.jsx(o,{label:"附件总数",value:(e==null?void 0:e.attachment_total)??0}),f.map(a=>t.jsx(o,{label:a.label,value:a.value,unit:a.unit??""},a.key))]}),t.jsx(j,{className:"w-[120px]",value:l,onChange:a=>n(a.target.value),options:[{value:"",label:"全部年份"},...((e==null?void 0:e.years)??[]).map(a=>({value:String(a),label:a+" 年"}))]})]}),!(e!=null&&e.metrics.length)&&t.jsx("div",{className:"mb-4 rounded-md border border-dashed border-line px-4 py-2 text-[12px] text-ink-3",children:"提示:在「统计」配置中注册指标(如志愿时长、读书本数),带单位的数值字段即可在此量化展示。"}),t.jsxs("div",{className:"grid grid-cols-1 lg:grid-cols-2 gap-4",children:[t.jsxs(c,{children:[t.jsx(d,{title:"近 12 个月活跃度"}),t.jsx(x,{children:t.jsx("div",{ref:h,className:"h-[220px]"})})]}),t.jsxs(c,{children:[t.jsx(d,{title:"类型分布"}),t.jsx(x,{children:t.jsx("div",{ref:b,className:"h-[220px]"})})]}),t.jsxs(c,{className:"col-span-2",children:[t.jsx(d,{title:"级别分布"}),t.jsx(x,{children:t.jsx("div",{ref:y,className:"h-[200px]"})})]})]})]})}function o({label:l,value:n,unit:i}){return t.jsxs("div",{className:"min-w-[120px] rounded-lg border border-line bg-surface px-4 py-3 shadow-card",children:[t.jsx("div",{className:"text-[12px] text-ink-3",children:l}),t.jsxs("div",{className:"num mt-0.5 text-[22px] font-semibold leading-tight text-ink-1",children:[n,i&&t.jsx("span",{className:"ml-1 text-[12px] font-normal text-ink-3",children:i})]})]})}export{q as DashboardPage};
|
||||
import{r as g,e as v,j as t,S as j,s as S}from"./index-DZUuFiwq.js";import{C as c,a as d,b as x}from"./card-BjB6wxWQ.js";import{u as N,i as u,a as m}from"./useChart-Csyyulii.js";import{u as k,i as w,a as C,b as L,c as R,d as $,e as z,f as T}from"./echarts-BIWefrIc.js";k([w,C,L,R,$,z,T]);function q(){const[l,n]=g.useState(""),i=N(),e=v({queryKey:["stats",l||void 0],queryFn:()=>S(l?Number(l):void 0)}).data,p=u("2"),r=u("3"),h=m(()=>({grid:{left:34,right:12,top:14,bottom:24},tooltip:{trigger:"axis"},xAxis:{type:"category",data:(e==null?void 0:e.monthly.map(a=>a.ym.slice(2)))??[],axisLine:{lineStyle:{color:r}},axisTick:{show:!1},axisLabel:{color:r,fontSize:10}},yAxis:{type:"value",splitLine:{lineStyle:{color:"rgba(128,138,155,0.15)"}},axisLabel:{color:r,fontSize:10}},series:[{type:"bar",data:(e==null?void 0:e.monthly.map(a=>a.count))??[],barMaxWidth:18,itemStyle:{color:"#3056d3",borderRadius:[3,3,0,0]}}]}),[e,i]),b=m(()=>{const a=((e==null?void 0:e.by_type)??[]).filter(s=>s.count>0);return{tooltip:{trigger:"item"},legend:{orient:"vertical",right:4,top:"middle",textStyle:{color:p,fontSize:11},itemWidth:10,itemHeight:10},series:[{type:"pie",radius:["48%","72%"],center:["34%","50%"],label:{show:!1},data:a.map(s=>({name:s.label,value:s.count,itemStyle:{color:s.color||"#64748b"}}))}]}},[e,i]),y=m(()=>{const a=((e==null?void 0:e.by_level)??[]).filter(s=>s.count>0).slice().reverse();return{grid:{left:64,right:24,top:8,bottom:22},tooltip:{trigger:"axis"},xAxis:{type:"value",splitLine:{lineStyle:{color:"rgba(128,138,155,0.15)"}},axisLabel:{color:r,fontSize:10}},yAxis:{type:"category",data:a.map(s=>s.label),axisLine:{show:!1},axisTick:{show:!1},axisLabel:{color:p,fontSize:11}},series:[{type:"bar",data:a.map(s=>({value:s.count,itemStyle:{color:s.color||"#3056d3",borderRadius:[0,3,3,0]}})),barMaxWidth:14}]}},[e,i]),f=((e==null?void 0:e.metrics)??[]).slice(0,3);return t.jsxs("div",{className:"mx-auto max-w-[1080px] px-6 py-5",children:[t.jsxs("div",{className:"mb-4 flex flex-wrap items-center justify-between gap-3",children:[t.jsxs("div",{className:"flex flex-wrap gap-3",children:[t.jsx(o,{label:"总记录",value:(e==null?void 0:e.total)??0}),t.jsx(o,{label:l?l+" 年新增":"本年新增",value:(e==null?void 0:e.total_this_year)??0}),t.jsx(o,{label:"附件总数",value:(e==null?void 0:e.attachment_total)??0}),f.map(a=>t.jsx(o,{label:a.label,value:a.value,unit:a.unit??""},a.key))]}),t.jsx(j,{className:"w-[120px]",value:l,onChange:a=>n(a.target.value),options:[{value:"",label:"全部年份"},...((e==null?void 0:e.years)??[]).map(a=>({value:String(a),label:a+" 年"}))]})]}),!(e!=null&&e.metrics.length)&&t.jsx("div",{className:"mb-4 rounded-md border border-dashed border-line px-4 py-2 text-[12px] text-ink-3",children:"提示:在「统计」配置中注册指标(如志愿时长、读书本数),带单位的数值字段即可在此量化展示。"}),t.jsxs("div",{className:"grid grid-cols-1 lg:grid-cols-2 gap-4",children:[t.jsxs(c,{children:[t.jsx(d,{title:"近 12 个月活跃度"}),t.jsx(x,{children:t.jsx("div",{ref:h,className:"h-[220px]"})})]}),t.jsxs(c,{children:[t.jsx(d,{title:"类型分布"}),t.jsx(x,{children:t.jsx("div",{ref:b,className:"h-[220px]"})})]}),t.jsxs(c,{className:"col-span-2",children:[t.jsx(d,{title:"级别分布"}),t.jsx(x,{children:t.jsx("div",{ref:y,className:"h-[200px]"})})]})]})]})}function o({label:l,value:n,unit:i}){return t.jsxs("div",{className:"min-w-[120px] rounded-lg border border-line bg-surface px-4 py-3 shadow-card",children:[t.jsx("div",{className:"text-[12px] text-ink-3",children:l}),t.jsxs("div",{className:"num mt-0.5 text-[22px] font-semibold leading-tight text-ink-1",children:[n,i&&t.jsx("span",{className:"ml-1 text-[12px] font-normal text-ink-3",children:i})]})]})}export{q as DashboardPage};
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
import{c as K,e as I,j as e,E as O,t as $,u as k,b as S,r as u,f as y,v as H,w as W,B as g,P as q,C as Q,x as J,y as T,z as U,A as N,k as G,T as E,I as j,D as Y,F as C,H as B,J as V}from"./index-C2sli-Mk.js";import{C as f,a as z,b as _}from"./card-DL3ec4KP.js";import{u as X,i as M,a as L}from"./useChart-f1LAeREn.js";import{u as Z,i as ee,b as se,a as te,c as ae,d as re,e as ne,f as le}from"./echarts-BIWefrIc.js";/**
|
||||
import{c as K,e as I,j as e,E as O,t as $,u as k,b as S,r as u,f as y,v as H,w as W,B as g,P as q,C as Q,x as J,y as T,z as U,A as N,k as G,T as E,I as j,D as Y,F as C,H as B,J as V}from"./index-DZUuFiwq.js";import{C as f,a as z,b as _}from"./card-BjB6wxWQ.js";import{u as X,i as M,a as L}from"./useChart-Csyyulii.js";import{u as Z,i as ee,b as se,a as te,c as ae,d as re,e as ne,f as le}from"./echarts-BIWefrIc.js";/**
|
||||
* @license lucide-react v0.475.0 - ISC
|
||||
*
|
||||
* This source code is licensed under the ISC license.
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
import{c as re,j as e,a as u,r as t,u as oe,b as ce,d as de,e as C,f as ue,I as xe,S as m,B as b,P as Y,g as pe,L as me,G as ve,R as he,h as je,i as ge,k as fe,T as ye,E as be,l as Ne,m as ke,C as Se,n as we,o as Ce,p as Ee,s as qe,q as _e}from"./index-C2sli-Mk.js";/**
|
||||
import{c as re,j as e,a as u,r as t,u as oe,b as ce,d as de,e as C,f as ue,I as xe,S as m,B as b,P as Y,g as pe,L as me,G as ve,R as he,h as je,i as ge,k as fe,T as ye,E as be,l as Ne,m as ke,C as Se,n as we,o as Ce,p as Ee,s as qe,q as _e}from"./index-DZUuFiwq.js";/**
|
||||
* @license lucide-react v0.475.0 - ISC
|
||||
*
|
||||
* This source code is licensed under the ISC license.
|
||||
+1
-1
File diff suppressed because one or more lines are too long
+1
-1
@@ -1,4 +1,4 @@
|
||||
import{c as P,u as Q,b as z,e as B,r as i,f as T,j as e,B as p,P as F,K as q,A as E,k as D,T as I,C as K,M as L,D as G,F as r,I as j,N as H,S as R,O as W,o as J}from"./index-C2sli-Mk.js";import{C as U}from"./card-DL3ec4KP.js";/**
|
||||
import{c as P,u as Q,b as z,e as B,r as i,f as T,j as e,B as p,P as F,K as q,A as E,k as D,T as I,C as K,M as L,D as G,F as r,I as j,N as H,S as R,O as W,o as J}from"./index-DZUuFiwq.js";import{C as U}from"./card-BjB6wxWQ.js";/**
|
||||
* @license lucide-react v0.475.0 - ISC
|
||||
*
|
||||
* This source code is licensed under the ISC license.
|
||||
@@ -1 +1 @@
|
||||
import{j as s,a}from"./index-C2sli-Mk.js";function i({className:r,...e}){return s.jsx("div",{className:a("rounded-lg border border-line bg-surface shadow-card",r),...e})}function t({title:r,extra:e,className:n}){return s.jsxs("div",{className:a("flex min-h-11 flex-wrap items-center justify-between gap-2 border-b border-line px-4 py-1.5",n),children:[s.jsx("h3",{className:"text-[13px] font-semibold text-ink-1",children:r}),e&&s.jsx("div",{className:"flex flex-wrap items-center gap-2",children:e})]})}function c({className:r,...e}){return s.jsx("div",{className:a("p-4",r),...e})}export{i as C,t as a,c as b};
|
||||
import{j as s,a}from"./index-DZUuFiwq.js";function i({className:r,...e}){return s.jsx("div",{className:a("rounded-lg border border-line bg-surface shadow-card",r),...e})}function t({title:r,extra:e,className:n}){return s.jsxs("div",{className:a("flex min-h-11 flex-wrap items-center justify-between gap-2 border-b border-line px-4 py-1.5",n),children:[s.jsx("h3",{className:"text-[13px] font-semibold text-ink-1",children:r}),e&&s.jsx("div",{className:"flex flex-wrap items-center gap-2",children:e})]})}function c({className:r,...e}){return s.jsx("div",{className:a("p-4",r),...e})}export{i as C,t as a,c as b};
|
||||
File diff suppressed because one or more lines are too long
+65
-65
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+1
-1
File diff suppressed because one or more lines are too long
+1
-1
@@ -1 +1 @@
|
||||
import{r}from"./index-C2sli-Mk.js";import{g as f}from"./echarts-BIWefrIc.js";function p(){const[n,o]=r.useState(0);return r.useEffect(()=>{const s=()=>o(t=>t+1);return window.addEventListener("fp-theme-change",s),()=>window.removeEventListener("fp-theme-change",s)},[]),n}function d(n){return getComputedStyle(document.documentElement).getPropertyValue("--text-"+n).trim()||"#454e5c"}function h(n,o){const s=r.useRef(null),[t,i]=r.useState(null),u=r.useRef(n);return u.current=n,r.useEffect(()=>{if(!t)return;const e=f(t);s.current=e,e.setOption(u.current(),{notMerge:!0});const c=new ResizeObserver(()=>e.resize());return c.observe(t),()=>{c.disconnect(),e.dispose(),s.current=null}},[t]),r.useEffect(()=>{var e;(e=s.current)==null||e.setOption(u.current(),{notMerge:!0})},[t,...o]),e=>i(e)}export{h as a,d as i,p as u};
|
||||
import{r}from"./index-DZUuFiwq.js";import{g as f}from"./echarts-BIWefrIc.js";function p(){const[n,o]=r.useState(0);return r.useEffect(()=>{const s=()=>o(t=>t+1);return window.addEventListener("fp-theme-change",s),()=>window.removeEventListener("fp-theme-change",s)},[]),n}function d(n){return getComputedStyle(document.documentElement).getPropertyValue("--text-"+n).trim()||"#454e5c"}function h(n,o){const s=r.useRef(null),[t,i]=r.useState(null),u=r.useRef(n);return u.current=n,r.useEffect(()=>{if(!t)return;const e=f(t);s.current=e,e.setOption(u.current(),{notMerge:!0});const c=new ResizeObserver(()=>e.resize());return c.observe(t),()=>{c.disconnect(),e.dispose(),s.current=null}},[t]),r.useEffect(()=>{var e;(e=s.current)==null||e.setOption(u.current(),{notMerge:!0})},[t,...o]),e=>i(e)}export{h as a,d as i,p as u};
|
||||
@@ -8,8 +8,8 @@
|
||||
<link rel="icon" href="/icons/pwa-192.png" />
|
||||
<link rel="apple-touch-icon" href="/icons/pwa-192.png" />
|
||||
<title>足迹 Footprints</title>
|
||||
<script type="module" crossorigin src="/assets/index-C2sli-Mk.js"></script>
|
||||
<link rel="stylesheet" crossorigin href="/assets/index-BgM7aYS9.css">
|
||||
<script type="module" crossorigin src="/assets/index-DZUuFiwq.js"></script>
|
||||
<link rel="stylesheet" crossorigin href="/assets/index-Dao00G5l.css">
|
||||
</head>
|
||||
<body>
|
||||
<div id="root"></div>
|
||||
|
||||
Reference in New Issue
Block a user