fix(resume): remove shadowing local ResumeSectionCfg (use types.ts with edu kind)

This commit is contained in:
root
2026-10-17 12:48:13 +08:00
parent f95efd481f
commit 9d2e14b72a
20 changed files with 113 additions and 80 deletions
+2
View File
@@ -336,6 +336,8 @@ function openDb(dbPath) {
d.exec('PRAGMA foreign_keys = ON;');
preMigrateColumns(d);
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);
ensureBuiltin(d);
alignBuiltinUuids(d);
+27 -21
View File
@@ -1,4 +1,4 @@
import type { FootprintRow, ProfileInfo, ResumeConfig } from './types';
import type { FootprintRow, ProfileInfo, ResumeConfig, ResumeSectionCfg } from './types';
// ---------- 简历数据模型 v2 ----------
@@ -6,34 +6,33 @@ export interface ResumeItemCfg { title: string; subtitle?: string; date?: string
export interface ResumeSectionDef {
key: string; defaultTitle: string;
kind: 'info' | 'list' | 'text';
kind: 'info' | 'edu' | 'list' | 'text';
types?: string[]; // list 类:从哪些记录类型装配
fixed?: boolean; // 不可删除/停用(基本信息、自我评价)
fixed?: boolean; // 不可删除/停用
}
export const RESUME_SECTION_DEFS: ResumeSectionDef[] = [
{ key: 'info', defaultTitle: '基本信息', kind: 'info', fixed: true },
{ key: 'education', defaultTitle: '教育背景', kind: 'list', types: ['学业'] },
{ key: 'skills', defaultTitle: '技能证书', kind: 'list', types: ['证书技能'] },
{ key: 'awards', defaultTitle: '荣誉奖项', kind: 'list', types: ['荣誉惩处'] },
{ key: 'competition', defaultTitle: '竞赛经历', kind: 'list', types: ['竞赛'] },
{ key: 'research', defaultTitle: '科研经历', kind: 'list', types: ['科研'] },
{ key: 'practice', defaultTitle: '实践经历', kind: 'list', types: ['志愿公益', '实习实践', '学生工作'] },
{ key: 'education', defaultTitle: '教育经历', kind: 'edu', fixed: true },
{ key: 'skills', defaultTitle: '核心技能', kind: 'text' },
{ key: 'projects', defaultTitle: '项目经历', kind: 'list', types: ['竞赛', '科研', '实习实践'] },
{ key: 'certs', defaultTitle: '证书与荣誉', kind: 'list', types: ['荣誉惩处', '证书技能'] },
{ key: 'campus', 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 },
];
export interface ResumeSectionCfg {
key: string;
title: string;
enabled: boolean;
kind?: 'info' | 'list' | 'text';
types?: string[];
excluded?: number[]; // 隐藏的记录 id
items?: ResumeItemCfg[]; // 自定义条目
text?: string; // text 板块内容
}
// 首次使用种子内容(IT/网安方向示例,可自由修改)
const SEED: Record<string, { text?: string; items?: { title: string; subtitle?: string; date?: string; desc?: 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等云原生运维工具。' },
campus: { items: [
{ title: '学校图书馆 勤工俭学固定岗', subtitle: '图书管理员', date: '2024.12 - 2026.7', desc: '负责图书上架、整理和维护,定时进行馆内安全巡检,协助读者检索和借阅服务,累计服务读者超2000人次,零服务投诉。这段经历培养了高度的责任意识与服务意识,锻炼了高效执行和多任务时间管理能力。' },
{ title: '学院团总支学生会宣传部 干事', subtitle: '视觉设计', date: '2023.9 - 2024.9', desc: '独立完成学院活动海报、邀请函、KT板、易拉宝等40余份宣传物料设计,参与换届大会、迎新、毕业季等重大活动视觉设计与宣传品制作。负责报告厅后台多媒体设备控制,保障12场大型活动视觉呈现零失误,锻炼了应急处置能力与谨慎细致的工作态度。' },
]},
self: { text: '心态沉稳、抗压能力较好,遇到突发状况能冷静应对、稳住局面。做事有计划性,习惯提前预判风险并做好预案,追求稳妥与确定性,执行质量有保障,能在压力下保持稳定输出。责任心强,凡事有始有终,注重细节与条理,能在复杂环境中稳步推进工作,是一名可靠、值得信赖的执行者。' },
};
export type ResumeTemplate = 'classic' | 'tech' | 'minimal';
@@ -44,6 +43,9 @@ export function defaultResumeConfig(): ResumeConfig {
fontScale: 1, density: 'normal', onePage: false,
sections: RESUME_SECTION_DEFS.map(d => ({
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 old = oldSections.find(o => o.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 里用户新增的板块(不在默认定义中)→ 追加为自定义文本板块
for (const o of oldSections) {
+2 -2
View File
@@ -235,7 +235,7 @@ export interface GradesOverview {
export interface ProfileInfo {
name: string; gender: string; birth: string; nation: string; native: 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;
selfIntro: string;
}
@@ -243,7 +243,7 @@ export interface ResumeItemCfg { title: string; subtitle?: string; date?: string
export interface ResumeSectionCfg {
key: string; title: string; enabled: boolean;
kind?: 'info' | 'list' | 'text';
kind?: 'info' | 'edu' | 'list' | 'text';
types?: string[];
excluded?: number[];
items?: ResumeItemCfg[];
+8 -1
View File
@@ -8,7 +8,8 @@ import { Button, Dialog, Field, Input, Select, Textarea, useToast } from '@/comp
const EMPTY: ProfileInfo = {
name: '', gender: '', birth: '', nation: '', native: '', political: '',
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[] }[] }[] = [
@@ -27,6 +28,12 @@ const FIELD_GROUPS: { title: string; fields: { key: keyof ProfileInfo; label: st
{ key: 'className', label: '班级' },
{ key: 'studentId', label: '学号' },
{ 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: [
{ key: 'phone', label: '手机' },