2026/10/14 13:11:41

个人技能管理系统实践:基于SQLite与ECharts的可视化看板

个人技能管理系统实践:基于SQLite与ECharts的可视化看板 1. 项目起源从一团乱麻到一张图谱我之前一直有个毛病学了东西就忘忘了再学学了又忘。英语单词背到abandonPython学到函数就转向PS打开教程收藏了几十篇真正动手不到五次。直到某天整理电脑发现硬盘里躺着四五个学习资料文件夹每个都塞得满满当当但真要我说清楚自己到底会什么、不会什么、学到什么程度我竟然答不上来。那一刻我意识到问题不在学得不够多而在于缺少一个对自身技能的系统化梳理。就像手里有一堆拼图却从来不看整体画面东拼一块西拼一块最后拼出来个四不像。所以我决定做一个叫skills的个人项目——一个轻量级的技能管理看板用技术手段把我所有的技能、水平、学习进度、关联关系全部可视化出来。项目核心只有一句话把我好像会点什么变成我会什么、会到什么程度、接下来该补什么。这个项目适合所有想认真做技能盘点的人特别是程序员、产品经理、设计师这类需要持续学习多种技能的从业者也适合在校学生用来规划学习路线。它不挑平台不依赖重型框架一个小型数据库加一个前端页面就能跑起来甚至你可以把它当成个人知识管理的补充工具和笔记软件配合使用。说实话做完这个项目对我个人的帮助远超预期。以前我对自己会什么只有一个模糊的感觉现在打开看板一目了然哪些技能荒废了该捡起来哪些技能用得少但可能有潜力哪些技能卡在瓶颈期需要突破全都有数据支撑。这篇文章我会完整记录整个项目的设计思路和实现过程从数据结构怎么设计到可视化图表怎么选型再到遇到过哪些坑全部分享出来。2. 为什么非要做一个技能管理系统而不是用现成工具2.1 现成方案的痛点在哪里动手之前我其实也研究过市面上的现成工具。有些笔记软件可以建技能标签有些学习平台自带技能树还有一些简历工具有技能评估功能。但用下来发现几个共性痛点一是维度单一。大多数工具只能记录你标了哪些技能标签顶多多一个熟练度打分但技能和技能之间的关联关系完全没有。比如Python和数据分析其实是强相关的学好了Python能直接带动数据分析的水平只会看标签的工具根本体现不出这种关系。二是数据不归自己管。有些在线平台的技能数据存在别人服务器上导出不方便格式还受限万一平台哪天调整产品方向你的数据可能就没了。自己搞一个本地系统数据全在自己手里格式、字段、展示方式都由自己做主。三是没有办法做趋势追踪。人的技能水平是动态变化的用现成工具记录一次评估就像拍了一张静态照片看不到时间维度上的变化。我想知道这个月相比上个月我的前端开发水平是提高了还是退步了这需要系统性地记录历史数据而不仅仅是存一个当前值。2.2 从需求反推项目设计想清楚痛点之后我试着把需求列成一个清单技能要有分类体系不能所有技能平铺在一个列表里每个技能需要多维度的评估不能只有熟练度一个指标要能记录技能之间的关系比如前置依赖、相关带动要能追踪技能水平的历史变化支持趋势分析界面要直观一眼就能看出整体的技能版图数据必须本地化轻量部署最好能在个人电脑上直接运行这个清单做出来之后整个项目的技术选型其实就变得非常明朗了数据层用轻量级的数据库展示层用Web页面中间加一层简单的数据处理逻辑。不需要微服务不需要分布式不需要消息队列这些在这个场景下就是杀鸡用牛刀。在具体选型上我对比了MySQL和SQLite最终选了SQLite。原因很简单——这个系统是单机个人用的SQLite支持标准SQL语法数据库文件就是一个普通文件备份和迁移直接复制文件就行零配置零守护进程。MySQL虽然功能更强但要装服务、配用户、管权限对一个个人项目来说负担重了。展示层我用的是一个偏轻量的前端方案配合ECharts做图表渲染无需后端渲染模板前端直接请求JSON数据接口。这个设计的好处很明显以后想换前端框架、想加新功能、想把数据导出给其他系统用都很自由。数据层和展示层之间是准标准的HTTP接口解耦程度很高哪怕哪天我想把它重写成移动端应用接口也能直接复用。3. 核心细节解析数据模型、评估逻辑和可视化设计3.1 技能分类体系怎么设计技能分类是整个系统的地基地基要是歪了上面盖什么都歪。我参考了一些职业能力模型把技能分成了三个层级领域域最高层分类比如编程开发、设计创作、数据分析、软技能技能簇中间层归类比如编程开发下面有前端开发、后端开发、移动开发具体技能最小粒度比如前端开发下面有JavaScript、React、CSS布局这样三层结构的优势在于既能从宏观上看自己的技能分布——哪些领域强哪些领域弱又能下钻到细节——某个具体技能当前处于什么水平。做盘点的时候我不会因为JavaScript这一个技能弱就否定整个前端方向也不会因为前端整体不错就忽略某个具体技能的短板。每个具体技能还挂了几个基础属性熟练度0到100的整数、兴趣度0到100、使用频率按周为单位记录每周大概用几次、最后使用时间、备注说明。熟练度是核心指标兴趣度用来判断持续学习的动力使用频率和最后使用时间用来识别冷却技能——就是那种学了很多但很久没用的。这里有个关键设计决定熟练度我不要那种笼统的入门/中级/高级因为这种离散档位区分度太低两个人都标中级实际水平可能差很远。我采用0到100的连续值并建议每隔一个月重新评估一次哪怕只是凭感觉打分只要保持口径一致趋势数据就有参考价值。不用纠结自己的某个技能到底是68分还是70分重要的是是不是从上个月的60分涨上来的。3.2 权重和综合指数的计算逻辑单个技能的水平只是最基础的数据如果只看到这一层那跟用Excel列表记录没什么区别。skills系统真正有价值的地方在于把孤立技能逐级汇聚成可对比的综合指数。每个技能簇的指数不是简单取平均值而是根据技能的权重加权计算。权重怎么定我说一下我的逻辑某个技能的权重主要看两点——对该技能簇的重要程度和当前实际使用场景。比如编程开发这个技能簇下面JavaScript权重可以设到0.9因为几乎前端的一切都离不开它而Shell脚本权重可能只有0.4因为它是加分项但不是必选项。权重的作用在于当某个高权重技能水平不高时即使一堆低权重技能分数很高整个技能簇的指数也不会虚高。这个设计思路类似于大学里学分绩点的计算逻辑——学分高的课程考得差对GPA的拖累就大这样才能真实反映学习质量。领域域指数则是下属所有技能簇指数的加权平均权重根据该领域在你当前职业或目标中的占比来设定。比如我把编程开发的权重设为0.5把数据分析设为0.3设计创作设为0.15软技能仅仅0.05这样算出来的整体综合指数基本反映了我的精力分配方向。趋势追踪怎么实现系统会在每次评估时写一条快照记录包含当前所有技能簇指数和领域域指数。快照只需要记录指数不需要把成千上万个技能明细全部冗余存储历史数据类型小、查询快画趋势图的时候性能完全没压力。3.3 可视化的形式如何选数据攒了一批之后怎么展示成为关键问题。我最开始用的是表格就是传统的一行一个技能、列显示各个属性。但这种形式有个致命问题——信息之间没有空间感你看到一个表格脑子里很难快速形成我的优势集中在哪里、短板在哪里的整体认知。后来我应用了三种图表形式雷达图用来展示各领域域指数。把多个领域综合在一张雷达图上外行人也能一眼看出你的能力结构轮廓是偏科还是均衡。气泡图用来展示具体技能分布。横轴是熟练度纵轴是兴趣度气泡大小代表使用频率气泡颜色代表所属技能簇。这个图信息密度极高能同时体现四个维度。堆叠面积图或折线图用来展示技能簇指数在时间维度上的变化。看趋势比看单个时间点的绝对值更有参考价值。这里我想多说一句雷达图的适用场景——雷达图不适合塞太多维度。我一开始试过把一个领域下的所有具体技能全塞进雷达图八九个维度挤在一起多边形变得非常杂乱根本读不出信息。后来形成规矩雷达图只用来展示六到八个领域域维度具体技能放到气泡图各司其职。3.4 关系图谱的引入前面提到现成工具不擅长表达技能之间的关联关系skills系统在这一点上做了增强设计——技能前置关系。什么是前置关系就是学技能B之前强烈建议先掌握技能A。比如学Vue之前最好先会JavaScript和ES6学数据可视化之前最好先有Python基础和一定的前端基础。这些关系在系统里被记录成一条一条的边A是B的前置技能。引入关系之后系统能做两件傻瓜工具做不了的事一是学习路径推荐。当我选定了目标技能比如机器学习系统可以找出从我现在已掌握的技能出发需要依次补齐哪些前置技能形成一条拓扑排序的学习路线。哪一步先走、哪一步后走一目了然。二是风险预警。如果我发现某个技能簇的指数在下降除了这个技能簇本身的原因之外还可以顺藤摸瓜查它的前置技能簇是不是也变了色往往是根基技能退步导致的连锁反应。这两个功能让我真正感觉这个系统不是一张死图谱而是一个能给出建议的向导这也是它区别于普通记录工具的核心价值。4. 实操过程从空库到第一版完整看板4.1 数据库表结构和初始化流程我直接把建表的关键SQL放出来这个结构基本是项目的数据层骨架后续扩展功能都在这个基础上加。-- 领域域表 CREATE TABLE domains ( id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT NOT NULL UNIQUE, weight REAL NOT NULL DEFAULT 1.0, sort_order INTEGER NOT NULL DEFAULT 0 ); -- 技能簇表 CREATE TABLE skill_groups ( id INTEGER PRIMARY KEY AUTOINCREMENT, domain_id INTEGER NOT NULL REFERENCES domains(id), name TEXT NOT NULL UNIQUE, weight REAL NOT NULL DEFAULT 1.0, sort_order INTEGER NOT NULL DEFAULT 0 ); -- 具体技能表 CREATE TABLE skills ( id INTEGER PRIMARY KEY AUTOINCREMENT, group_id INTEGER NOT NULL REFERENCES skill_groups(id), name TEXT NOT NULL UNIQUE, proficiency INTEGER NOT NULL DEFAULT 0 CHECK(proficiency 0 AND proficiency 100), interest INTEGER NOT NULL DEFAULT 0 CHECK(interest 0 AND interest 100), weekly_frequency INTEGER NOT NULL DEFAULT 0, last_used DATE, notes TEXT ); -- 技能前置关系表 CREATE TABLE prerequisites ( skill_id INTEGER NOT NULL REFERENCES skills(id), prereq_id INTEGER NOT NULL REFERENCES skills(id), PRIMARY KEY (skill_id, prereq_id) ); -- 历史快照表 CREATE TABLE snapshots ( id INTEGER PRIMARY KEY AUTOINCREMENT, captured_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, domain_scores TEXT NOT NULL, -- JSON格式存储各领域指数 group_scores TEXT NOT NULL -- JSON格式存储各技能簇指数 );初始化的时候要做几件事先把领域域四条基础记录插进去然后往每个领域下挂技能簇最后按技能簇逐个挂具体技能。顺序很关键先有父级才有子级关系表必须在具体技能都建好之后再维护否则外键找不到对应记录。我第一次建表时犯了个低级错误——技能表里忘了加CHECK约束导致后来某次评估不小心写入了一个120的熟练度图表上那个点直接飙到坐标轴外面去了。加上CHECK约束之后非法数据根本进不来从源头防呆。4.2 综合指数的计算过程实例空谈概念容易让人迷糊我拿一个真实例子来演示加权指数的计算过程。假设数据分析这个技能簇下面挂了三个技能Python熟练度85权重0.9SQL熟练度70权重0.8Excel熟练度60权重0.5这个技能簇的指数就是(85 × 0.9 70 × 0.8 60 × 0.5) / (0.9 0.8 0.5) (76.5 56 30) / 2.2 162.5 / 2.2 ≈ 73.86。小数点后的值保留两位存入快照。注意这里用的是加权平均而不是简单平均简单平均会是(857060)/3 71.7看上去差别不大但在技能数量多、权重差异大的场景下加权和简单平均的结果可能相差十多个点必须用加权。领域域指数的计算逻辑完全一样把技能簇的指数和权重代入公式即可。整个计算逻辑封装成一个函数每次点击评估并保存快照按钮时统一触发保证口径一致。4.3 可视化页面的搭建与效果调优后端数据和计算逻辑就绪之后前端可视化我用了ECharts。三个图布局在一片完整的仪表盘页面上左上雷达图、右上气泡图、下方全宽堆叠面积图。整体采用深色主题技能簇用不同色系区分视觉上比白色背景更能突出高亮区域。雷达图的配置要特别注意坐标轴的最大值。我一开始用了默认的最大值100但我的领域域指数普遍在60到80之间导致雷达图五边形挤在一起差异完全看不出来。后来我把坐标轴的最大值动态设置为当前所有领域域指数最大值的1.2倍且不低于80这样图形就能撑满整个雷达区域各个领域的高低对比一目了然。气泡图的实现遇到过一个有趣的坑——数据点重叠。当两个技能熟练度和兴趣度差不多时气泡几乎完全重合鼠标悬停只能选中其中一个另一个点就像隐身了。我的解决思路是给气泡增加一个轻微的随机抖动偏移抖动量控制在两个像素以内不影响数据判断但能有效减少点与点之间的完全重叠。堆叠面积图比较顺利快照表的时间字段直接作为横轴各类技能簇指数作为多个系列。做完之后我发现一个很有价值的用途——每次评估完都截图保存月底翻一翻就能直观看到自己这个月技能变化的曲线那种明明感觉忙了一个月回头一看曲线几乎是一条直线的冲击感非常真实。4.4 部署和日常使用流程全部开发完成之后运行就非常简单了。SQLite是一个文件Flask是一个Python进程前端页面是几个静态文件。我在电脑上写了个简单的启动脚本双击之后浏览器自动打开本机地址输入预先设置的四位PIN码就能进入看板。日常使用流程我固定成了一套习惯每周日晚花十分钟快速过一遍所有技能的使用频率更新一下本周用到哪些技能每月最后一天认真做一次熟练度重新评估调整权重每次学完一门新课、完成一个项目之后及时把新技能加进系统季度性复盘时重点看趋势图和技能关联图谱制定下季度学习计划这套流程坚持了几个月之后最大的变化不是数据多好看了而是做学习决策的时候不再靠模糊记忆。以前规划下个月学什么是凭感觉觉得自己Python好像一般要补补现在是Python熟练度65低于整个编程领域的平均值72而且近两个月的趋势线在走平确实该加大投入。5. 常见问题与排查技巧实录5.1 权重怎么设才能既主观又不失真权重这个问题项目做完之后好几个人问我到底怎么定。我的答案是权重本身就是一种主观判断无需追求客观精确但要遵守相对一致性的原则。一个容易踩的坑是不同人之间甚至同一个人在不同时期对同一技能的权重判断可能漂移。比如我一个月前觉得JavaScript权重应该0.9一个月后觉得0.8更合适如果直接改掉权重历史快照里的指数就会变得不可比。我的方案是权重修改只影响未来的计算历史快照保持原样。快照表里存的就是当时算出来的指数值不会因为后来权重调整而追溯变动。这就像股票的复权因子——如果一直回到过去改价格K线图就没法看了。实际操作中我给权重的取值范围划了档0.2到1.0之间以0.1为步长。低于0.2的技能意味着它在这个分类下几乎没有影响力那通常应该把它移到别的地方去或者干脆删掉。5.2 气泡图数据点重叠和视觉拥挤这个在前面提到过但值得展开说说。气泡图的信息密度很高但反过来就是容易乱。当我技能数量超过四五十个之后整个图表区域密密麻麻的几乎没法阅读。我尝试了几个优化方案。第一个方案是按使用频率做过滤——只展示每周使用频率大于等于1的技能把那些学过但很久没碰的技能折叠起来需要时再展开。第二个方案是分组渲染不同技能簇的气泡用不同颜色图例可以单独开关想看前端方向就把其他方向隐藏。第三个方案是宏观到微观的联动在雷达图上点击某个领域域下面的气泡图自动只显示该领域下的技能实现下钻查看。三个方案叠加之后即使技能总数超过六十个界面也能保持清爽。这给了我一个很重要的经验——可视化不是把数据全部堆出来就够了更关键的是怎么让用户有控制权能按需查看不同粒度的数据。5.3 趋势线突然跳崖或者冲顶有次我正常打开看板发现某条趋势线在一个时间点上突然掉了二十多分这个异常让我挺慌的以为哪里的代码算错了。排查下来发现真相很乌龙——那条线是数据分析技能簇的指数而数据分析簇的指数之前一直依赖Excel这个技能撑着但那个月我把Excel的熟练度从75重新评估到了50因为我意识到自己其实只会基础操作根本达不到75的水平。这暴露了一个系统设计上的缺陷——指数变化的部分原因可能是评估口径变了而不是真实水平变了。这不是bug但很容易误导读图的人。我的对策是在快照表里加了一个字段叫做校准说明。每次评估时如果有某些技能做了大幅度的口径调整或者重估就把说明文字存下来。在做趋势分析的时候一旦发现相邻两个时间点的指数变化超过15分就自动列出这个时间段内所有校准说明让你搞清楚这次变化究竟是水平真的变了还是评估标准变了。诚实评估真的很重要。我发现一旦自己知道这些数据会被记录、会被展示、会被对比打分的时候反而比随口一说要认真得多这说明把技能管理当作一个严肃的记录体系本身就会反向塑造你的学习行为。5.4 常见问题速查表我把项目使用过程中最常遇到的问题整理成一个表方便同样在做这个系统的朋友直接对照排查。问题现象可能原因解决办法指标算出来比预期高很多权重设置过于平均没有体现核心技能的突出作用给核心技能更高权重低价值技能权重降到0.3以下雷达图所有维度都挤在中间坐标轴最大值设置过大动态调整最大值到当前指数最大值的1.2倍左右趋势图上某个月出现明显折线异常该月做过大规模技能口径调整检查校准说明必要时还原旧口径重新计算数据库文件损坏打不开断电或异常终止导致SQLite写操作中断用SQLite自带恢复命令尝试修复平时注意备份数据库文件技能数量太多导致界面卡顿前端图表一次性渲染过多数据点开启过滤机制按领域或频率分片加载新导入的数据在图上不显示缓存未刷新或者新技能没挂到技能簇下强制刷新页面检查skill的group_id外键是否正确数据备份没有自动化忘记手动复制数据库文件写个简单脚本每周自动把数据库文件复制到云端目录6. 从技能管理到个人成长地图做完skills这个项目之后我最大的体会是管理技能本质上是在管理注意力。我们一天只有24小时能稳定输出的精力更是有限把有限的精力投放到什么地方直接决定了一年后你是什么状态。如果没有一个系统做记录和反馈人的注意力很容易被紧急但不重要的事情带跑。在我自己用了三个月之后我已经养成了一个习惯——每次接触新知识之前先打开skills系统看看这个新知识和现有技能版图之间是什么关系。如果它是某个现有技能的延伸我会先评估现有技能的水平是否足以支撑学习如果它是一个全新的领域我要想清楚这个新领域在整体目标中占的权重到底有多大值不值得投入。这里有一个很实用的技巧学习新技能之后立刻更新系统别拖到周末。人是健忘的学完一门新手艺后两周不记录再打开系统你可能发现自己已经完全忘了当时学到什么程度。我一般是学完当天晚上花两分钟顺手更新数据保鲜度大幅提升。从技术角度看这个项目没有用到任何前沿技术数据库是最基础的SQLite前端是最常见的ECharts后端就是一个轻量级的Web服务但它解决了我的真实问题。这让我更加确信一件事——工具的价值不在于用了多高大上的技术栈而在于用户是否真正持续使用它。后续这个项目还可以继续扩展的方向其实挺多的比如加上待办和学习计划管理的模块让盘点和规划打通比如做一个浏览器插件在浏览技术文章时自动识别涉及到的技能并提示关联到系统再比如加入模拟面试功能基于技能关联图谱生成针对性的面试题。这些都是很自然的方向但我暂时不打算继续堆功能了——工具做到够用就行再多就变成管理工具的工具了。最后分享一个小经验如果你也想做一个类似的系统第一版一定要快功能一定要少数据入口一定要顺。我身边有人想做一个全功能的个人成长平台结果半年过去了还没上线因为一直在加功能、调设计。我第一版只用了两天就上线了界面简陋得很但能记录数据就能跑通闭环后续再一点一点打磨反而越用越顺手。把技能盘点变成习惯之后你的人生规划就有了仪表盘做决策时不再是拍脑袋而是看着数据做判断。这套方法不一定适合所有人但对那些愿意把成长过程数据化的人真的很管用。