fix(resume): remove shadowing local ResumeSectionCfg (use types.ts with edu kind)
This commit is contained in:
@@ -336,6 +336,8 @@ function openDb(dbPath) {
|
|||||||
d.exec('PRAGMA foreign_keys = ON;');
|
d.exec('PRAGMA foreign_keys = ON;');
|
||||||
preMigrateColumns(d);
|
preMigrateColumns(d);
|
||||||
d.exec(fs.readFileSync(path.join(__dirname, '..', 'schema.sql'), 'utf8'));
|
d.exec(fs.readFileSync(path.join(__dirname, '..', 'schema.sql'), 'utf8'));
|
||||||
|
// 个人信息表兜底(确保任何挂载形态下都存在)
|
||||||
|
d.exec("CREATE TABLE IF NOT EXISTS profile (id INTEGER PRIMARY KEY AUTOINCREMENT, uuid TEXT, content TEXT NOT NULL DEFAULT '{}', deleted_at TEXT, origin TEXT, hlc TEXT)");
|
||||||
migrateSync(d);
|
migrateSync(d);
|
||||||
ensureBuiltin(d);
|
ensureBuiltin(d);
|
||||||
alignBuiltinUuids(d);
|
alignBuiltinUuids(d);
|
||||||
|
|||||||
+27
-21
@@ -1,4 +1,4 @@
|
|||||||
import type { FootprintRow, ProfileInfo, ResumeConfig } from './types';
|
import type { FootprintRow, ProfileInfo, ResumeConfig, ResumeSectionCfg } from './types';
|
||||||
|
|
||||||
// ---------- 简历数据模型 v2 ----------
|
// ---------- 简历数据模型 v2 ----------
|
||||||
|
|
||||||
@@ -6,34 +6,33 @@ export interface ResumeItemCfg { title: string; subtitle?: string; date?: string
|
|||||||
|
|
||||||
export interface ResumeSectionDef {
|
export interface ResumeSectionDef {
|
||||||
key: string; defaultTitle: string;
|
key: string; defaultTitle: string;
|
||||||
kind: 'info' | 'list' | 'text';
|
kind: 'info' | 'edu' | 'list' | 'text';
|
||||||
types?: string[]; // list 类:从哪些记录类型装配
|
types?: string[]; // list 类:从哪些记录类型装配
|
||||||
fixed?: boolean; // 不可删除/停用(基本信息、自我评价)
|
fixed?: boolean; // 不可删除/停用
|
||||||
}
|
}
|
||||||
|
|
||||||
export const RESUME_SECTION_DEFS: ResumeSectionDef[] = [
|
export const RESUME_SECTION_DEFS: ResumeSectionDef[] = [
|
||||||
{ key: 'info', defaultTitle: '基本信息', kind: 'info', fixed: true },
|
{ key: 'info', defaultTitle: '基本信息', kind: 'info', fixed: true },
|
||||||
{ key: 'education', defaultTitle: '教育背景', kind: 'list', types: ['学业'] },
|
{ key: 'education', defaultTitle: '教育经历', kind: 'edu', fixed: true },
|
||||||
{ key: 'skills', defaultTitle: '技能证书', kind: 'list', types: ['证书技能'] },
|
{ key: 'skills', defaultTitle: '核心技能', kind: 'text' },
|
||||||
{ key: 'awards', defaultTitle: '荣誉奖项', kind: 'list', types: ['荣誉惩处'] },
|
{ key: 'projects', defaultTitle: '项目经历', kind: 'list', types: ['竞赛', '科研', '实习实践'] },
|
||||||
{ key: 'competition', defaultTitle: '竞赛经历', kind: 'list', types: ['竞赛'] },
|
{ key: 'certs', defaultTitle: '证书与荣誉', kind: 'list', types: ['荣誉惩处', '证书技能'] },
|
||||||
{ key: 'research', defaultTitle: '科研经历', kind: 'list', types: ['科研'] },
|
{ key: 'campus', defaultTitle: '在校经历', kind: 'list', types: ['学生工作', '志愿公益'] },
|
||||||
{ key: 'practice', defaultTitle: '实践经历', kind: 'list', types: ['志愿公益', '实习实践', '学生工作'] },
|
|
||||||
{ key: 'activity', defaultTitle: '文体活动', kind: 'list', types: ['文体活动'] },
|
{ key: 'activity', defaultTitle: '文体活动', kind: 'list', types: ['文体活动'] },
|
||||||
{ key: 'other', defaultTitle: '其他经历', kind: 'list' }, // 未归类的自定义类型 + 自定义条目
|
{ key: 'other', defaultTitle: '其他经历', kind: 'list' },
|
||||||
{ key: 'self', defaultTitle: '自我评价', kind: 'text', fixed: true },
|
{ key: 'self', defaultTitle: '自我评价', kind: 'text', fixed: true },
|
||||||
];
|
];
|
||||||
|
|
||||||
export interface ResumeSectionCfg {
|
// 首次使用种子内容(IT/网安方向示例,可自由修改)
|
||||||
key: string;
|
const SEED: Record<string, { text?: string; items?: { title: string; subtitle?: string; date?: string; desc?: string }[] }> = {
|
||||||
title: string;
|
skills: { text: '路由交换:熟悉TCP/IP协议栈与基础路由交换,掌握VLAN、链路聚合、MSTP、VRRP/VRRP6等园区网冗余技术,熟悉OSPF、RIP、BGP等动态路由协议,具备IPv4/IPv6双栈网络的规划与部署能力。\n网络安全:熟悉防火墙安全区域、ACL访问控制与安全策略配置,掌握NAPT、NAT Server、NAT64地址转换,了解GRE over IPsec隧道与防火墙双机热备。\n网络设备:熟悉华为交换机、路由器、防火墙CLI操作与配置,掌握GVRP、MSTP、VRRP、链路聚合及BFD联动快速收敛,熟悉Wireshark抓包分析。\n运维基础:熟悉RedHat、Ubuntu等Linux系统部署与日常维护,了解Docker、K8s、Prometheus等云原生运维工具。' },
|
||||||
enabled: boolean;
|
campus: { items: [
|
||||||
kind?: 'info' | 'list' | 'text';
|
{ title: '学校图书馆 勤工俭学固定岗', subtitle: '图书管理员', date: '2024.12 - 2026.7', desc: '负责图书上架、整理和维护,定时进行馆内安全巡检,协助读者检索和借阅服务,累计服务读者超2000人次,零服务投诉。这段经历培养了高度的责任意识与服务意识,锻炼了高效执行和多任务时间管理能力。' },
|
||||||
types?: string[];
|
{ title: '学院团总支学生会宣传部 干事', subtitle: '视觉设计', date: '2023.9 - 2024.9', desc: '独立完成学院活动海报、邀请函、KT板、易拉宝等40余份宣传物料设计,参与换届大会、迎新、毕业季等重大活动视觉设计与宣传品制作。负责报告厅后台多媒体设备控制,保障12场大型活动视觉呈现零失误,锻炼了应急处置能力与谨慎细致的工作态度。' },
|
||||||
excluded?: number[]; // 隐藏的记录 id
|
]},
|
||||||
items?: ResumeItemCfg[]; // 自定义条目
|
self: { text: '心态沉稳、抗压能力较好,遇到突发状况能冷静应对、稳住局面。做事有计划性,习惯提前预判风险并做好预案,追求稳妥与确定性,执行质量有保障,能在压力下保持稳定输出。责任心强,凡事有始有终,注重细节与条理,能在复杂环境中稳步推进工作,是一名可靠、值得信赖的执行者。' },
|
||||||
text?: string; // text 板块内容
|
};
|
||||||
}
|
|
||||||
|
|
||||||
export type ResumeTemplate = 'classic' | 'tech' | 'minimal';
|
export type ResumeTemplate = 'classic' | 'tech' | 'minimal';
|
||||||
|
|
||||||
@@ -44,6 +43,9 @@ export function defaultResumeConfig(): ResumeConfig {
|
|||||||
fontScale: 1, density: 'normal', onePage: false,
|
fontScale: 1, density: 'normal', onePage: false,
|
||||||
sections: RESUME_SECTION_DEFS.map(d => ({
|
sections: RESUME_SECTION_DEFS.map(d => ({
|
||||||
key: d.key, title: d.defaultTitle, enabled: true, kind: d.kind, types: d.types,
|
key: d.key, title: d.defaultTitle, enabled: true, kind: d.kind, types: d.types,
|
||||||
|
...(d.key === 'skills' ? { text: SEED.skills.text } : {}),
|
||||||
|
...(d.key === 'campus' ? { items: SEED.campus.items } : {}),
|
||||||
|
...(d.key === 'self' ? { text: SEED.self.text } : {}),
|
||||||
})),
|
})),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -57,7 +59,11 @@ export function migrateResumeConfig(raw: unknown): ResumeConfig {
|
|||||||
const sections = def.sections.map(d => {
|
const sections = def.sections.map(d => {
|
||||||
const old = oldSections.find(o => o.key === d.key);
|
const old = oldSections.find(o => o.key === d.key);
|
||||||
const dd = RESUME_SECTION_DEFS.find(x => x.key === d.key);
|
const dd = RESUME_SECTION_DEFS.find(x => x.key === d.key);
|
||||||
return { ...d, enabled: old?.enabled ?? true, title: old?.title ?? dd?.defaultTitle ?? d.title };
|
const base: ResumeSectionCfg = { ...d, enabled: old?.enabled ?? true, title: old?.title ?? dd?.defaultTitle ?? d.title };
|
||||||
|
if (d.key === 'skills' && !base.text) base.text = SEED.skills.text;
|
||||||
|
if (d.key === 'campus' && !(base.items?.length)) base.items = SEED.campus.items;
|
||||||
|
if (d.key === 'self' && !base.text) base.text = SEED.self.text;
|
||||||
|
return base;
|
||||||
});
|
});
|
||||||
// v1 里用户新增的板块(不在默认定义中)→ 追加为自定义文本板块
|
// v1 里用户新增的板块(不在默认定义中)→ 追加为自定义文本板块
|
||||||
for (const o of oldSections) {
|
for (const o of oldSections) {
|
||||||
|
|||||||
@@ -235,7 +235,7 @@ export interface GradesOverview {
|
|||||||
export interface ProfileInfo {
|
export interface ProfileInfo {
|
||||||
name: string; gender: string; birth: string; nation: string; native: string;
|
name: string; gender: string; birth: string; nation: string; native: string;
|
||||||
political: string; school: string; college: string; major: string;
|
political: string; school: string; college: string; major: string;
|
||||||
className: string; studentId: string; degree: string;
|
className: string; studentId: string; degree: string; eduLength: string; eduStart: string; eduEnd: string; majorCourses: string;
|
||||||
phone: string; email: string; homepage: string; photoUrl: string;
|
phone: string; email: string; homepage: string; photoUrl: string;
|
||||||
selfIntro: string;
|
selfIntro: string;
|
||||||
}
|
}
|
||||||
@@ -243,7 +243,7 @@ export interface ResumeItemCfg { title: string; subtitle?: string; date?: string
|
|||||||
|
|
||||||
export interface ResumeSectionCfg {
|
export interface ResumeSectionCfg {
|
||||||
key: string; title: string; enabled: boolean;
|
key: string; title: string; enabled: boolean;
|
||||||
kind?: 'info' | 'list' | 'text';
|
kind?: 'info' | 'edu' | 'list' | 'text';
|
||||||
types?: string[];
|
types?: string[];
|
||||||
excluded?: number[];
|
excluded?: number[];
|
||||||
items?: ResumeItemCfg[];
|
items?: ResumeItemCfg[];
|
||||||
|
|||||||
@@ -8,7 +8,8 @@ import { Button, Dialog, Field, Input, Select, Textarea, useToast } from '@/comp
|
|||||||
const EMPTY: ProfileInfo = {
|
const EMPTY: ProfileInfo = {
|
||||||
name: '', gender: '', birth: '', nation: '', native: '', political: '',
|
name: '', gender: '', birth: '', nation: '', native: '', political: '',
|
||||||
school: '', college: '', major: '', className: '', studentId: '', degree: '',
|
school: '', college: '', major: '', className: '', studentId: '', degree: '',
|
||||||
phone: '', email: '', homepage: '', photoUrl: '', selfIntro: ''
|
phone: '', email: '', homepage: '', photoUrl: '', selfIntro: '',
|
||||||
|
eduLength: '', eduStart: '', eduEnd: '', majorCourses: ''
|
||||||
};
|
};
|
||||||
|
|
||||||
const FIELD_GROUPS: { title: string; fields: { key: keyof ProfileInfo; label: string; type?: string; options?: string[] }[] }[] = [
|
const FIELD_GROUPS: { title: string; fields: { key: keyof ProfileInfo; label: string; type?: string; options?: string[] }[] }[] = [
|
||||||
@@ -27,6 +28,12 @@ const FIELD_GROUPS: { title: string; fields: { key: keyof ProfileInfo; label: st
|
|||||||
{ key: 'className', label: '班级' },
|
{ key: 'className', label: '班级' },
|
||||||
{ key: 'studentId', label: '学号' },
|
{ key: 'studentId', label: '学号' },
|
||||||
{ key: 'degree', label: '学历层次', options: ['', '专科', '本科', '硕士研究生', '博士研究生'] },
|
{ key: 'degree', label: '学历层次', options: ['', '专科', '本科', '硕士研究生', '博士研究生'] },
|
||||||
|
{ key: 'eduLength', label: '学制', options: ['', '两年', '三年', '四年', '五年'] },
|
||||||
|
{ key: 'eduStart', label: '入学时间', type: 'month' },
|
||||||
|
{ key: 'eduEnd', label: '毕业时间', type: 'month' },
|
||||||
|
]},
|
||||||
|
{ title: '主修课程', fields: [
|
||||||
|
{ key: 'majorCourses', label: '主修课程' },
|
||||||
]},
|
]},
|
||||||
{ title: '联系方式', fields: [
|
{ title: '联系方式', fields: [
|
||||||
{ key: 'phone', label: '手机' },
|
{ key: 'phone', label: '手机' },
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ CREATE TABLE IF NOT EXISTS footprint_type (
|
|||||||
color TEXT NOT NULL DEFAULT '#64748b',
|
color TEXT NOT NULL DEFAULT '#64748b',
|
||||||
sort INTEGER NOT NULL DEFAULT 100,
|
sort INTEGER NOT NULL DEFAULT 100,
|
||||||
form_template TEXT NOT NULL DEFAULT '[]',
|
form_template TEXT NOT NULL DEFAULT '[]',
|
||||||
|
profile TEXT,
|
||||||
is_builtin INTEGER NOT NULL DEFAULT 0,
|
is_builtin INTEGER NOT NULL DEFAULT 0,
|
||||||
closed INTEGER NOT NULL DEFAULT 0,
|
closed INTEGER NOT NULL DEFAULT 0,
|
||||||
deleted_at TEXT,
|
deleted_at TEXT,
|
||||||
@@ -89,6 +90,11 @@ CREATE TABLE IF NOT EXISTS attachment (
|
|||||||
size INTEGER NOT NULL DEFAULT 0,
|
size INTEGER NOT NULL DEFAULT 0,
|
||||||
rel_path TEXT NOT NULL,
|
rel_path TEXT NOT NULL,
|
||||||
sha256 TEXT,
|
sha256 TEXT,
|
||||||
|
thumb_rel_path TEXT,
|
||||||
|
remote_url TEXT,
|
||||||
|
remote_thumb TEXT,
|
||||||
|
remote_key TEXT,
|
||||||
|
remote_thumb_key TEXT,
|
||||||
taken_at TEXT,
|
taken_at TEXT,
|
||||||
deleted_at TEXT,
|
deleted_at TEXT,
|
||||||
origin TEXT,
|
origin TEXT,
|
||||||
@@ -197,6 +203,15 @@ CREATE TRIGGER IF NOT EXISTS footprint_au AFTER UPDATE OF search_text ON footpri
|
|||||||
END;
|
END;
|
||||||
|
|
||||||
CREATE INDEX IF NOT EXISTS idx_footprint_start ON footprint(start_date);
|
CREATE INDEX IF NOT EXISTS idx_footprint_start ON footprint(start_date);
|
||||||
|
CREATE TABLE IF NOT EXISTS profile (
|
||||||
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||||
|
uuid TEXT,
|
||||||
|
content TEXT NOT NULL DEFAULT '{}',
|
||||||
|
deleted_at TEXT,
|
||||||
|
origin TEXT,
|
||||||
|
hlc TEXT
|
||||||
|
);
|
||||||
|
|
||||||
CREATE INDEX IF NOT EXISTS idx_footprint_type ON footprint(type_id);
|
CREATE INDEX IF NOT EXISTS idx_footprint_type ON footprint(type_id);
|
||||||
CREATE INDEX IF NOT EXISTS idx_footprint_group ON footprint(group_id);
|
CREATE INDEX IF NOT EXISTS idx_footprint_group ON footprint(group_id);
|
||||||
CREATE INDEX IF NOT EXISTS idx_footprint_hlc ON footprint(hlc);
|
CREATE INDEX IF NOT EXISTS idx_footprint_hlc ON footprint(hlc);
|
||||||
|
|||||||
+3
-3
File diff suppressed because one or more lines are too long
+1
-1
@@ -1 +1 @@
|
|||||||
import{r as g,f as v,j as t,S as j,t as S}from"./index-CSVqyJB0.js";import{C as c,a as d,b as x}from"./card-BcMbz03g.js";import{u as N,i as u,a as m}from"./useChart-CUy-j464.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-3 py-4 sm:px-6 sm: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:"lg: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,f as v,j as t,S as j,t as S}from"./index-DWQlGpif.js";import{C as c,a as d,b as x}from"./card-BkBMnQAf.js";import{u as N,i as u,a as m}from"./useChart-q1r1yv4-.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-3 py-4 sm:px-6 sm: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:"lg: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 R,f as I,j as e,E as O,w as $,u as N,d as f,r as u,g as v,x as H,y as W,B as b,P as q,C as L,z as J,A as T,D as U,m as k,l as F,T as z,I as g,F as Y,H as S,J as E,K as V}from"./index-CSVqyJB0.js";import{C,a as M,b as _}from"./card-BcMbz03g.js";import{u as X,i as Q,a as K}from"./useChart-CUy-j464.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 R,f as I,j as e,E as O,w as $,u as N,d as f,r as u,g as v,x as H,y as W,B as b,P as q,C as L,z as J,A as T,D as U,m as k,l as F,T as z,I as g,F as Y,H as S,J as E,K as V}from"./index-DWQlGpif.js";import{C,a as M,b as _}from"./card-BkBMnQAf.js";import{u as X,i as Q,a as K}from"./useChart-q1r1yv4-.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
|
* @license lucide-react v0.475.0 - ISC
|
||||||
*
|
*
|
||||||
* This source code is licensed under the ISC license.
|
* This source code is licensed under the ISC license.
|
||||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+1
-1
@@ -1,4 +1,4 @@
|
|||||||
import{c as fe,j as e,a as N,r as s,b as he,u as ve,d as ge,e as je,f as L,g as ye,I as be,S as k,B as w,P as Q,h as te,L as se,G as ae,R as Ne,i as ne,k as ke,l as we,T as Ce,E as le,m as Ee,n as Se,o as _e,C as ze,p as qe,q as Le,s as Re,t as De,v as Ie}from"./index-CSVqyJB0.js";/**
|
import{c as fe,j as e,a as N,r as s,b as he,u as ve,d as ge,e as je,f as L,g as ye,I as be,S as k,B as w,P as Q,h as te,L as se,G as ae,R as Ne,i as ne,k as ke,l as we,T as Ce,E as le,m as Ee,n as Se,o as _e,C as ze,p as qe,q as Le,s as Re,t as De,v as Ie}from"./index-DWQlGpif.js";/**
|
||||||
* @license lucide-react v0.475.0 - ISC
|
* @license lucide-react v0.475.0 - ISC
|
||||||
*
|
*
|
||||||
* This source code is licensed under the ISC license.
|
* This source code is licensed under the ISC license.
|
||||||
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,4 +1,4 @@
|
|||||||
import{c as D,u as K,d as F,f as L,r,g as I,j as e,B as p,P as q,M as O,m as _,l as H,T as P,C as R,N as G,F as U,H as i,I as j,O as W,S as z,Q as J,U as V,q as X}from"./index-CSVqyJB0.js";import{C as Y}from"./card-BcMbz03g.js";/**
|
import{c as D,u as K,d as F,f as L,r,g as I,j as e,B as p,P as q,M as O,m as _,l as H,T as P,C as R,N as G,F as U,H as i,I as j,O as W,S as z,Q as J,U as V,q as X}from"./index-DWQlGpif.js";import{C as Y}from"./card-BkBMnQAf.js";/**
|
||||||
* @license lucide-react v0.475.0 - ISC
|
* @license lucide-react v0.475.0 - ISC
|
||||||
*
|
*
|
||||||
* This source code is licensed under the ISC license.
|
* This source code is licensed under the ISC license.
|
||||||
@@ -1 +1 @@
|
|||||||
import{j as s,a}from"./index-CSVqyJB0.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-DWQlGpif.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
+1
-1
File diff suppressed because one or more lines are too long
+1
-1
@@ -1 +1 @@
|
|||||||
import{r}from"./index-CSVqyJB0.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-DWQlGpif.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};
|
||||||
@@ -9,7 +9,7 @@
|
|||||||
<link rel="icon" href="/icons/pwa-192.png" />
|
<link rel="icon" href="/icons/pwa-192.png" />
|
||||||
<link rel="apple-touch-icon" href="/icons/pwa-192.png" />
|
<link rel="apple-touch-icon" href="/icons/pwa-192.png" />
|
||||||
<title>足迹 Footprints</title>
|
<title>足迹 Footprints</title>
|
||||||
<script type="module" crossorigin src="/assets/index-CSVqyJB0.js"></script>
|
<script type="module" crossorigin src="/assets/index-DWQlGpif.js"></script>
|
||||||
<link rel="stylesheet" crossorigin href="/assets/index-CIs6Yi-t.css">
|
<link rel="stylesheet" crossorigin href="/assets/index-CIs6Yi-t.css">
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
|
|||||||
Reference in New Issue
Block a user