feat: 汉字介绍待续

This commit is contained in:
R524809
2026-02-09 13:30:43 +08:00
parent b13ab6f9fb
commit 3569961115
10 changed files with 36260 additions and 16 deletions
@@ -0,0 +1,33 @@
const fs = require('fs');
// Read char_common_base.json (each line is a JSON object)
const basePath = '/Users/joey-xd/sites/pipi-learn/platform-pipi/apps/api/src/data/char_common_base.json';
const baseText = fs.readFileSync(basePath, 'utf8').trim();
const baseLines = baseText.split('\n').filter(l => l.trim());
const chars = baseLines.map(l => {
let cleaned = l.trim().replace(/,$/, '');
return JSON.parse(cleaned);
});
console.log(`总字数: ${chars.length}`);
const singlePinyin = chars.filter(c => c.pinyin.length === 1);
const multiPinyin = chars.filter(c => c.pinyin.length > 1);
console.log(`单音字: ${singlePinyin.length}`);
console.log(`多音字: ${multiPinyin.length}`);
// Count by number of pinyins
const byCount = {};
multiPinyin.forEach(c => {
const n = c.pinyin.length;
if (!byCount[n]) byCount[n] = [];
byCount[n].push(c);
});
Object.keys(byCount).sort().forEach(n => {
console.log(`\n=== ${n} 个读音 (${byCount[n].length} 字) ===`);
byCount[n].forEach(c => {
console.log(` ${c.char}: [${c.pinyin.join(', ')}]`);
});
});
@@ -0,0 +1,420 @@
const fs = require('fs');
const inputPath =
'/Users/joey-xd/sites/pipi-learn/platform-pipi/packages/voice-production/data/char/char_introduce_v2.json';
const data = JSON.parse(fs.readFileSync(inputPath, 'utf8'));
// ========== 修复词典 ==========
// 格式: char → 常用词/短语,用于生成 "char,word的char"
// 覆盖 "X字的X" 和 "X的X" 两类问题
const wordFixes = {
// --- "X字的X" 类 (294个) ---
迟: '迟到',
局: '局面',
改: '改变',
张: '张开',
忌: '禁忌',
际: '国际',
陆: '陆地',
阿: '阿谀',
陈: '陈列',
阻: '阻止',
附: '附近',
坠: '坠落',
妓: '歌妓',
妙: '美妙',
妖: '妖怪',
姊: '姊妹',
妨: '妨碍',
妒: '嫉妒',
努: '努力',
忍: '忍耐',
抽: '抽屉',
拐: '拐弯',
拖: '拖延',
者: '读者',
拍: '拍手',
顶: '头顶',
拆: '拆除',
拎: '拎包',
拥: '拥抱',
抵: '抵达',
拘: '拘留',
势: '势力',
抱: '拥抱',
拄: '拄杖',
垃: '垃圾',
拉: '拉开',
拦: '拦截',
幸: '幸福',
拌: '搅拌',
拧: '拧开',
歧: '分歧',
肯: '肯定',
齿: '牙齿',
些: '一些',
卓: '卓越',
虎: '老虎',
虏: '俘虏',
肾: '肾脏',
贤: '贤明',
尚: '高尚',
旺: '兴旺',
具: '工具',
味: '味道',
果: '水果',
昆: '昆虫',
国: '国家',
哎: '哎呀',
咕: '咕噜',
昌: '昌盛',
呵: '呵护',
疙: '疙瘩',
柑: '柑橘',
枯: '枯萎',
柄: '把柄',
栋: '栋梁',
相: '互相',
查: '检查',
柏: '柏树',
栅: '栅栏',
柳: '柳树',
柱: '柱子',
柿: '柿子',
栏: '栏杆',
柠: '柠檬',
树: '大树',
勃: '蓬勃',
要: '需要',
柬: '请柬',
咸: '咸淡',
威: '威力',
歪: '歪斜',
韭: '韭菜',
背: '背后',
战: '战争',
点: '点头',
虐: '虐待',
临: '临时',
览: '浏览',
竖: '竖立',
省: '省份',
削: '削苹果',
尝: '品尝',
昧: '愚昧',
盹: '打盹',
是: '是非',
盼: '盼望',
眨: '眨眼',
哇: '哇塞',
哄: '哄堂大笑',
哑: '哑巴',
显: '显然',
很: '很好',
猎: '打猎',
猫: '猫咪',
凰: '凤凰',
猖: '猖狂',
猛: '猛烈',
祭: '祭祀',
馅: '馅饼',
馆: '博物馆',
凑: '凑合',
减: '减少',
毫: '毫米',
烹: '烹饪',
庶: '庶民',
麻: '麻烦',
庵: '尼姑庵',
痊: '痊愈',
痒: '发痒',
痕: '痕迹',
廊: '走廊',
康: '健康',
谓: '所谓',
谚: '谚语',
谜: '谜语',
逮: '逮捕',
敢: '勇敢',
尉: '上尉',
屠: '屠宰',
弹: '子弹',
隋: '隋朝',
堕: '堕落',
随: '随便',
蛋: '鸡蛋',
隅: '角隅',
隆: '隆重',
隐: '隐藏',
婚: '结婚',
婶: '婶婶',
婉: '婉转',
颇: '颇多',
颈: '颈椎',
替: '替代',
揍: '揍人',
款: '款式',
堪: '堪称',
塔: '宝塔',
搭: '搭建',
堰: '堤堰',
揩: '揩油',
越: '超越',
趁: '趁机',
趋: '趋势',
超: '超级',
揽: '包揽',
堤: '堤坝',
提: '提高',
博: '博学',
揭: '揭开',
喜: '欢喜',
彭: '彭姓',
揣: '揣测',
装: '装扮',
蛮: '野蛮',
就: '成就',
敦: '敦厚',
斌: '文武双全',
痘: '痘痘',
痢: '痢疾',
痪: '瘫痪',
痛: '痛苦',
童: '儿童',
竣: '竣工',
阔: '辽阔',
善: '善良',
翔: '飞翔',
羡: '羡慕',
普: '普通',
粪: '粪便',
尊: '尊重',
奠: '奠基',
道: '道路',
榄: '橄榄',
想: '想象',
槐: '槐树',
榆: '榆树',
楼: '楼房',
概: '大概',
赖: '依赖',
酬: '报酬',
感: '感觉',
碍: '阻碍',
尴: '尴尬',
矮: '矮小',
辞: '辞职',
稚: '幼稚',
稠: '稠密',
颓: '颓废',
愁: '忧愁',
筹: '筹划',
简: '简单',
筷: '筷子',
毁: '毁灭',
舅: '舅舅',
鼠: '老鼠',
催: '催促',
傻: '傻瓜',
像: '好像',
躲: '躲藏',
魁: '魁梧',
衙: '衙门',
微: '微小',
馍: '馍馍',
叠: '重叠',
缠: '缠绕',
缤: '缤纷',
剿: '围剿',
静: '安静',
碧: '碧绿',
璃: '玻璃',
赘: '累赘',
熬: '熬夜',
墙: '围墙',
墟: '废墟',
嘉: '嘉奖',
摧: '摧毁',
赫: '显赫',
截: '截断',
誓: '发誓',
境: '环境',
摘: '采摘',
摔: '摔倒',
撇: '撇开',
聚: '聚集',
蜡: '蜡烛',
蝇: '苍蝇',
蜘: '蜘蛛',
蝉: '蝉鸣',
嘛: '干嘛',
嘀: '嘀咕',
赚: '赚钱',
锹: '铁锹',
锻: '锻炼',
镀: '镀金',
舞: '跳舞',
舔: '舔嘴',
稳: '稳定',
熏: '熏陶',
箕: '簸箕',
算: '计算',
箩: '箩筐',
管: '管理',
箫: '洞箫',
舆: '舆论',
薄: '薄饼',
颠: '颠倒',
翰: '翰墨',
噩: '噩梦',
橱: '橱柜',
橙: '橙子',
橘: '橘子',
整: '整齐',
融: '融化',
瓢: '瓢虫',
醒: '清醒',
霍: '霍然',
霎: '霎时',
辙: '车辙',
冀: '希冀',
餐: '餐厅',
嘴: '嘴巴',
踱: '踱步',
蹄: '马蹄',
蹂: '蹂躏',
靡: '奢靡',
癣: '皮癣',
瓣: '花瓣',
羹: '肉羹',
鳖: '甲鳖',
爆: '爆炸',
疆: '边疆',
鬓: '鬓角',
壤: '土壤',
馨: '温馨',
耀: '闪耀',
躁: '急躁',
蠕: '蠕动',
嚼: '咀嚼',
嚷: '叫嚷',
巍: '巍峨',
籍: '书籍',
鳞: '鱼鳞',
魔: '魔法',
糯: '糯米',
// --- "X的X" 类 (47个) ---
你: '你好',
系: '关系',
茎: '茎叶',
画: '画画',
鱼: '鲤鱼',
狗: '小狗',
底: '底部',
油: '石油',
泡: '泡泡',
空: '天空',
钠: '钠元素',
看: '看见',
剑: '宝剑',
总: '总是',
给: '给予',
起: '起来',
根: '树根',
党: '党员',
哦: '哦哦',
圆: '圆形',
钾: '钾元素',
铁: '铁路',
铅: '铅笔',
秤: '秤杆',
般: '一般',
爱: '爱心',
狼: '灰狼',
谁: '谁人',
球: '足球',
硅: '硅谷',
做: '做事',
您: '您好',
假: '真假',
率: '效率',
锅: '铁锅',
锌: '锌元素',
鹅: '白鹅',
然: '自然',
粥: '稀粥',
鼓: '打鼓',
搬: '搬家',
摇: '摇晃',
搞: '搞笑',
塘: '池塘',
摊: '摊贩',
聘: '聘请',
慢: '慢慢',
};
// ========== 修复逻辑 ==========
let fixCount = 0;
function fixIntroduce(ch, intro) {
// 检测 "X,X字的X" 模式
const m1 = intro.match(/^(.),(.)字的\1$/);
if (m1 && m1[1] === m1[2]) {
const okPairs = ['文字', '写字', '名字', '签字', '数字'];
if (!okPairs.includes(m1[2] + '字')) {
if (wordFixes[ch]) {
fixCount++;
return `${ch},${wordFixes[ch]}的${ch}`;
}
}
}
// 检测 "X,X的X" 自引用模式
const m2 = intro.match(/^(.),\1的\1$/);
if (m2) {
if (wordFixes[ch]) {
fixCount++;
return `${ch},${wordFixes[ch]}的${ch}`;
}
}
return intro;
}
Object.entries(data).forEach(([ch, val]) => {
if (ch.startsWith('_')) return;
if (typeof val[0] === 'string') {
// 单音字: [pinyin, meaning, introduce]
val[2] = fixIntroduce(ch, val[2]);
} else {
// 多音字: [[pinyin, meaning, introduce], ...]
val.forEach((r) => {
r[2] = fixIntroduce(ch, r[2]);
});
}
});
// ========== 写入 ==========
fs.writeFileSync(inputPath, JSON.stringify(data, null, 2), 'utf8');
console.log(`修复完成: ${fixCount} 个 introduce 已更新`);
// ========== 验证 ==========
const dataCheck = JSON.parse(fs.readFileSync(inputPath, 'utf8'));
let remaining = 0;
Object.entries(dataCheck).forEach(([ch, val]) => {
if (ch.startsWith('_')) return;
function check(intro) {
const m1 = intro.match(/^(.),(.)字的\1$/);
if (
m1 &&
m1[1] === m1[2] &&
!['文字', '写字', '名字', '签字', '数字'].includes(m1[2] + '字')
)
remaining++;
const m2 = intro.match(/^(.),\1的\1$/);
if (m2) remaining++;
}
if (typeof val[0] === 'string') check(val[2]);
else val.forEach((r) => check(r[2]));
});
console.log(`剩余问题: ${remaining}`);
File diff suppressed because it is too large Load Diff