diff --git a/.gitignore b/.gitignore
index b4c82c0..306a408 100644
--- a/.gitignore
+++ b/.gitignore
@@ -2,6 +2,8 @@
# gitignore template for Vue.js projects
#
# Recommended template: Node.gitignore
+node_modules/
+.claude/
# TODO: where does this rule come from?
docs/_book
diff --git a/data/vol02.json b/data/vol02.json
new file mode 100644
index 0000000..174bcbf
--- /dev/null
+++ b/data/vol02.json
@@ -0,0 +1,187 @@
+{
+ "volume": "卷二",
+ "chapters": ["第01章 老奸巨猾", "第02章 尔虞我诈", "第03章 误打误撞", "第04章 发财大计", "第05章 东溟夫人", "第06章 利己利人", "第07章 网中之鱼", "第08章 红粉帮主", "第09章 初窥堂奥", "第10章 秘密账簿", "第11章 毒如蛇蝎", "第12章 诈死脱身"],
+
+ "locations": [
+ { "id": "liyang", "name": "历阳", "type": "city", "lat": 31.7, "lng": 118.37, "description": "杜伏威占据的重镇,江淮军的根据地" },
+ { "id": "xin_an", "name": "新安郡", "type": "city", "lat": 31.2, "lng": 118.5, "description": "沿长江南岸兴旺大城,寇徐与杜伏威同行处" },
+ { "id": "danyang", "name": "丹阳", "type": "city", "lat": 32.0, "lng": 118.95, "description": "长江沿岸重镇,宋师道活动地" },
+ { "id": "long_hai", "name": "陇海", "type": "city", "lat": 31.9, "lng": 118.7, "description": "沿海重镇" },
+ { "id": "yu_hang", "name": "余杭", "type": "city", "lat": 30.3, "lng": 120.1, "description": "沿海郡县,海沙帮分舵所在地" },
+ { "id": "sea_beach", "name": "海滩", "type": "landmark", "lat": 29.8, "lng": 121.5, "description": "东溟派船队停泊地,寇徐修炼两月处" },
+ { "id": "hui_shui", "name": "淮水", "type": "waterway", "lat": 32.1, "lng": 117.0, "description": "贯通南北的重要水道" },
+ { "id": "lei_gong_gorge", "name": "雷公峡", "type": "landmark", "lat": 32.5, "lng": 116.8, "description": "淮水沿岸险峻峡谷,杜伏威与巨鲲帮对战处" },
+ { "id": "peng_cheng", "name": "彭城", "type": "city", "lat": 34.4, "lng": 117.1, "description": "东溟夫人单美仙与李渊会面之地" },
+ { "id": "zhong_yang", "name": "钟阳", "type": "city", "lat": 31.0, "lng": 116.0, "description": "云玉真计划前往地" }
+ ],
+
+ "factions": [
+ {
+ "id": "du_fuwei_army",
+ "name": "杜伏威军",
+ "type": "义军",
+ "color": "#FF8C00",
+ "leader": "杜伏威",
+ "territory": ["liyang"],
+ "key_figures": ["杜伏威", "辅公祏"],
+ "description": "江淮义军,占据历阳,攻占新安郡,与寇徐因缘际会相识"
+ },
+ {
+ "id": "hai_sha_bang",
+ "name": "海沙帮",
+ "type": "帮派",
+ "color": "#1E90FF",
+ "leader": "韩盖天",
+ "territory": ["yu_hang"],
+ "key_figures": ["韩盖天", "游秋雁", "尤贵", "凌志高"],
+ "description": "东南沿海三大帮派之一,私盐贸易,依附宇文门阀,龙王韩盖天之名颇著"
+ },
+ {
+ "id": "ju_kun_bang",
+ "name": "巨鲲帮",
+ "type": "帮派",
+ "color": "#FF1493",
+ "leader": "云玉真",
+ "territory": [],
+ "key_figures": ["云玉真", "卜天志", "云芝", "陈老谋"],
+ "description": "东南沿海三大帮派之一,独立自主,红粉帮主云玉真武艺精湛,实为独孤阀幕后势力"
+ },
+ {
+ "id": "shui_long_bang",
+ "name": "水龙帮",
+ "type": "帮派",
+ "color": "#4169E1",
+ "leader": "未提及",
+ "territory": [],
+ "key_figures": [],
+ "description": "东南沿海三大帮派之一,依附南方宋姓门阀"
+ },
+ {
+ "id": "ba_ling_bang",
+ "name": "巴陵帮",
+ "type": "帮派",
+ "color": "#8B0000",
+ "leader": "隋炀帝杨广",
+ "territory": [],
+ "key_figures": [],
+ "description": "以洞庭湖为根据地,专事贩卖妇女,供应妓院,获利最厚,背后乃皇帝"
+ },
+ {
+ "id": "dong_ming_pai",
+ "name": "东溟派",
+ "type": "外族势力",
+ "color": "#00CED1",
+ "leader": "单美仙",
+ "territory": [],
+ "key_figures": ["单美仙", "游秋雁", "东溟夫人"],
+ "description": "来自琉球大海岛,以女性为主,打造优质兵器,每年春分到中土选少男,运营飘香号"
+ },
+ {
+ "id": "du_gu_fa",
+ "name": "独孤阀",
+ "type": "门阀",
+ "color": "#9932CC",
+ "leader": "独孤峰",
+ "territory": [],
+ "key_figures": ["独孤策", "独孤峰", "尤楚红"],
+ "description": "四姓门阀之一,独孤策为阀主独孤峰之子,武功高强,与云玉真勾结"
+ },
+ {
+ "id": "li_fa",
+ "name": "李阀",
+ "type": "门阀",
+ "color": "#DC143C",
+ "leader": "李渊",
+ "territory": [],
+ "key_figures": ["李渊"],
+ "description": "四姓门阀之一,与东溟派有交易往来,购买兵器"
+ },
+ {
+ "id": "yu_wen_fa",
+ "name": "宇文阀",
+ "type": "门阀",
+ "color": "#4169E1",
+ "leader": "宇文伤",
+ "territory": [],
+ "key_figures": ["宇文化及", "宇文伤"],
+ "description": "四姓门阀之一,宇文化及为禁卫总管,命海沙帮追捕寇徐,图谋获取东溟派账簿"
+ }
+ ],
+
+ "character_routes": [
+ {
+ "character": "寇仲 & 徐子陵",
+ "color": "#FF4500",
+ "route": [
+ { "location": "liyang", "chapter": 1, "event": "逃出杜伏威追捕,被挟到新安郡" },
+ { "location": "xin_an", "chapter": 2, "event": "到新安郡酒楼,遇沈乃堂和梁舜明,杜伏威动武" },
+ { "location": "xin_an", "chapter": 3, "event": "逃入飘香院躲避杜伏威追捕" },
+ { "lat": 30.5, "lng": 120.0, "chapter": 5, "event": "在海上从东溟派大船跳入水中,首次学会水底闭气" },
+ { "location": "yu_hang", "chapter": 5, "event": "登陆余杭城,遇老刘和谭勇,得知东溟派信息" },
+ { "lat": 30.2, "lng": 120.3, "chapter": 6, "event": "被海沙帮追捕后逃脱" },
+ { "lat": 29.8, "lng": 121.5, "chapter": 7, "event": "与偷盐船被海沙帮追获,被困铁笼,成功逃脱" },
+ { "location": "sea_beach", "chapter": 8, "event": "船只触礁沉没,损失盐包,遇云玉真" },
+ { "location": "sea_beach", "chapter": 9, "event": "海滩修炼两月,观海鸥悟道,获得天人合一之境" },
+ { "location": "sea_beach", "chapter": 10, "event": "尝试跳崖修炼轻功,成功突破" },
+ { "location": "sea_beach", "chapter": 11, "event": "被纳入云玉真巨鲲帮,船上修为大进" },
+ { "lat": 32.5, "lng": 116.8, "chapter": 12, "event": "淮水激战,杜伏威对独孤策,危崖绝境" }
+ ]
+ },
+ {
+ "character": "杜伏威",
+ "color": "#FF8C00",
+ "route": [
+ { "location": "liyang", "chapter": 1, "event": "在镇外路上擒拿寇徐二人,强行索取关帝庙秘密" },
+ { "location": "xin_an", "chapter": 2, "event": "在新安郡酒楼与沈乃堂、梁舜明对战" },
+ { "location": "xin_an", "chapter": 3, "event": "追捕逃离的寇徐" },
+ { "lat": 32.5, "lng": 116.8, "chapter": 12, "event": "追击云玉真等人至雷公峡,与独孤策对战十招" }
+ ]
+ },
+ {
+ "character": "云玉真",
+ "color": "#FF1493",
+ "route": [
+ { "location": "sea_beach", "chapter": 8, "event": "沙滩出现,与寇徐交手,提议拜师" },
+ { "location": "sea_beach", "chapter": 9, "event": "三次到沙滩传授鸟渡术轻功心法" },
+ { "lat": 32.0, "lng": 119.5, "chapter": 10, "event": "约定接寇徐上船进行任务" },
+ { "location": "yu_hang", "chapter": 11, "event": "接寇徐上巨鲲帮战船,传授偷盗技艺,与独孤策密会" },
+ { "lat": 32.1, "lng": 117.0, "chapter": 12, "event": "淮水行进中遭遇杜伏威,逃离至雷公峡绝崖" }
+ ]
+ },
+ {
+ "character": "韩盖天",
+ "color": "#1E90FF",
+ "route": [
+ { "lat": 30.0, "lng": 120.5, "chapter": 7, "event": "海上追获偷盐船,俘获寇徐" },
+ { "location": "yu_hang", "chapter": 7, "event": "船队审问寇徐,获悉杨公宝藏信息" }
+ ]
+ },
+ {
+ "character": "东溟派",
+ "color": "#00CED1",
+ "route": [
+ { "lat": 30.5, "lng": 120.0, "chapter": 5, "event": "飘香号船队在海上与海沙帮交战,寇徐从船上跳海逃脱" },
+ { "location": "yu_hang", "chapter": 5, "event": "东溟派在余杭招募选婿" },
+ { "location": "peng_cheng", "chapter": 11, "event": "东溟夫人单美仙七天后赴彭城会李渊,为偷账簿的机会窗口" }
+ ]
+ }
+ ],
+
+ "key_events": [
+ { "chapter": 1, "location": "liyang", "event": "杜伏威在官道上追获逃离的寇徐,威胁要杀人灭口" },
+ { "chapter": 1, "location": "xin_an", "event": "寇徐被杜伏威挟到新安郡,众人在酒楼进餐" },
+ { "chapter": 2, "location": "xin_an", "event": "杜伏威与沈乃堂、梁舜明交手,展示袖里乾坤武功" },
+ { "chapter": 3, "event": "寇徐逃入飘香院躲避杜伏威,遇沈无双踩踏" },
+ { "chapter": 5, "event": "寇徐首次登上东溟派飘香号,遇单美仙但被逐下船", "lat": 30.5, "lng": 120.0 },
+ { "chapter": 5, "event": "寇徐从飘香号跳海,在水底首次领悟内息呼吸之妙" },
+ { "chapter": 6, "event": "寇徐进城遇海沙帮人员,得知盐仓位置和东溟派信息" },
+ { "chapter": 7, "event": "海沙帮五船追获寇徐与偷盐船,韩盖天审问与威胁" },
+ { "chapter": 7, "event": "寇徐在船底挖洞脱逃,偷盐船与海沙帮分开,触礁沉没", "lat": 30.0, "lng": 121.0 },
+ { "chapter": 8, "event": "徐子陵遇海鸥受启发,与寇仲一击打散其剑,首次成功使用奇功" },
+ { "chapter": 9, "event": "两人从高崖跳下,在生死关头突破轻功,掌握反劲之道" },
+ { "chapter": 10, "event": "寇徐试图在海底修炼,后来通过观察鱼儿与螃蟹修行渐悟奥妙" },
+ { "chapter": 11, "event": "云玉真与独孤策在船舱密会,寇徐无意中听闻被杀人灭口计划" },
+ { "chapter": 11, "event": "寇徐得知云玉真真实身份与陷害,计划诈死脱身" },
+ { "chapter": 12, "location": "lei_gong_gorge", "event": "杜伏威追至雷公峡,与独孤策约定十招对决,寇徐危崖绝处" }
+ ]
+}
diff --git a/data/vol03.json b/data/vol03.json
new file mode 100644
index 0000000..89ecabe
--- /dev/null
+++ b/data/vol03.json
@@ -0,0 +1,166 @@
+{
+ "volume": "卷三",
+ "chapters": ["第01章 生灵涂炭", "第02章 阴谋诡计", "第03章 美女赌约", "第04章 中计被擒", "第05章 一单交易", "第06章 绝地逃生", "第07章 嫖赌合一", "第08章 赌场风云", "第09章 东溟公主", "第10章 微湖战火"],
+
+ "locations": [
+ { "id": "pengcheng", "name": "彭城", "aliases": ["徐州"], "type": "city", "lat": 34.28, "lng": 117.57, "description": "卷三主要活动地点,战略要地,隋朝重镇" },
+ { "id": "shuishui", "name": "泗水", "aliases": ["泗河"], "type": "waterway", "lat": 34.5, "lng": 117.0, "description": "贯通中原的重要水道,寇徐二人逃生路线" },
+ { "id": "lvliang_mountain", "name": "吕梁山", "type": "landmark", "lat": 34.8, "lng": 117.3, "description": "彭城附近的山脉,秦叔宝念想所在" },
+ { "id": "piaoxi_number", "name": "飘香号", "aliases": ["飘香船"], "type": "landmark", "lat": 32.5, "lng": 119.0, "description": "东溟夫人的商船,海沙帮欲攻打之地,李世民船队所在" },
+ { "id": "luo_yang", "name": "洛阳", "aliases": ["东都"], "type": "city", "lat": 34.62, "lng": 112.45, "description": "李世民船队出发地" },
+ { "id": "xingyang", "name": "荥阳", "type": "city", "lat": 34.79, "lng": 113.38, "description": "瓦岗军翟让根据地,寇徐欲寻素素处" },
+ { "id": "taiyang", "name": "太原", "type": "city", "lat": 37.87, "lng": 112.55, "description": "李渊驻地,李世民活动范围" },
+ { "id": "fuchun", "name": "扶春", "type": "town", "lat": 34.5, "lng": 115.0, "description": "沈落雁防守之地,秦叔宝与隋将张须陀的战场" },
+ { "id": "ghost_stone_gorge", "name": "鬼石峡", "type": "landmark", "lat": 34.2, "lng": 117.3, "description": "泗水险滩,寇徐与渔夫失船处" },
+ { "id": "qinglong_beach", "name": "青龙滩", "type": "landmark", "lat": 34.15, "lng": 117.25, "description": "泗水上打鱼地点" },
+ { "id": "hunan", "name": "湖南", "type": "region", "lat": 27.0, "lng": 112.0, "description": "飘香号来往路线区域" }
+ ],
+
+ "factions": [
+ {
+ "id": "sui",
+ "name": "隋朝",
+ "type": "朝廷",
+ "color": "#FFD700",
+ "leader": "杨广(隋炀帝)",
+ "territory": ["pengcheng", "luo_yang"],
+ "key_figures": ["杨广", "秦叔宝", "张须陀"],
+ "description": "杨广统治下衰亡中的隋朝,诸将各有心思"
+ },
+ {
+ "id": "wagang_army",
+ "name": "瓦岗军",
+ "type": "义军",
+ "color": "#FF6347",
+ "leader": "翟让/李密",
+ "territory": ["xingyang"],
+ "key_figures": ["翟让", "李密", "沈落雁", "祖君彦"],
+ "description": "天下最大义军势力,李密智计过人,沈落雁为俏军师"
+ },
+ {
+ "id": "du_fuwei",
+ "name": "杜伏威军",
+ "type": "义军",
+ "color": "#FF8C00",
+ "leader": "杜伏威",
+ "territory": ["pengcheng"],
+ "key_figures": ["杜伏威"],
+ "description": "江淮义军首领,内功深厚,掌控彭城地区,与寇徐二人有师徒渊源"
+ },
+ {
+ "id": "li_clan",
+ "name": "李阀",
+ "type": "门阀",
+ "color": "#DC143C",
+ "leader": "李渊",
+ "territory": ["taiyang"],
+ "key_figures": ["李渊", "李世民", "李秀宁"],
+ "description": "四姓门阀之一,暗中购买兵器,李世民智计过人,与寇徐二人有交易"
+ },
+ {
+ "id": "dongming_pai",
+ "name": "东溟派",
+ "type": "江湖势力",
+ "color": "#20B2AA",
+ "leader": "东溟夫人(单美仙)",
+ "territory": ["piaoxi_number"],
+ "key_figures": ["东溟夫人", "单秀", "单玉蝶", "云玉真"],
+ "description": "琉球兵器贸易大户,掌控天下兵器供应,护法仙子武力超群"
+ },
+ {
+ "id": "pengliang_gang",
+ "name": "彭梁会",
+ "type": "黑道帮会",
+ "color": "#8B008B",
+ "leader": "任媚媚/香贵",
+ "territory": ["pengcheng"],
+ "key_figures": ["任媚媚", "香贵", "香玉山"],
+ "description": "彭城重要黑帮,专事人口贩卖,与皇帝勾结"
+ },
+ {
+ "id": "turks",
+ "name": "突厥",
+ "type": "外族",
+ "color": "#2F4F4F",
+ "leader": "始毕可汗",
+ "territory": [],
+ "key_figures": ["颜里回", "慕铁雄"],
+ "description": "北方外患,与宇文阀勾结暗害翟让"
+ }
+ ],
+
+ "character_routes": [
+ {
+ "character": "寇仲 & 徐子陵",
+ "color": "#FF4500",
+ "route": [
+ { "lat": 32.8, "lng": 116.5, "chapter": 12, "event": "离开翠山镇,北上赶往彭城" },
+ { "lat": 33.5, "lng": 117.0, "chapter": 12, "event": "遇见战场生灵涂炭之象,斩杀隋兵" },
+ { "lat": 34.0, "lng": 117.2, "chapter": 12, "event": "参与大战,与沈落雁初识" },
+ { "location": "pengcheng", "chapter": 13, "event": "到达彭城,遇秦叔宝" },
+ { "location": "shuishui", "chapter": 13, "event": "河边约定与沈落雁赌赛" },
+ { "lat": 34.2, "lng": 117.3, "chapter": 13, "event": "乘船逆流,遇莫成老渔夫,潜水脱险" },
+ { "lat": 34.3, "lng": 117.4, "chapter": 14, "event": "乘船逃脱被发现,躲入水底" },
+ { "location": "pengcheng", "chapter": 14, "event": "返回彭城,入住旅馆" },
+ { "location": "pengcheng", "chapter": 14, "event": "与沈落雁交手,冲破包围逃脱" },
+ { "location": "pengcheng", "chapter": 15, "event": "入翠碧楼,遭沈落雁暗杀队伏击" },
+ { "location": "pengcheng", "chapter": 16, "event": "赌场与杜伏威对峙,东溟派援救" }
+ ]
+ },
+ {
+ "character": "沈落雁",
+ "color": "#FF1493",
+ "route": [
+ { "location": "shuishui", "chapter": 13, "event": "船上生擒秦叔宝,与寇徐定赌约" },
+ { "lat": 34.2, "lng": 117.3, "chapter": 13, "event": "追捕过程中,投放追踪粉末" },
+ { "location": "pengcheng", "chapter": 14, "event": "追至彭城,多次围捕寇徐" },
+ { "lat": 34.5, "lng": 117.5, "chapter": 14, "event": "房间内与寇徐交手,闯关失败" },
+ { "location": "pengcheng", "chapter": 15, "event": "警告寇徐不要去青楼" },
+ { "location": "pengcheng", "chapter": 16, "event": "赌场制止任媚媚,对阵杜伏威与东溟派" }
+ ]
+ },
+ {
+ "character": "秦叔宝",
+ "color": "#FFB6C1",
+ "route": [
+ { "location": "shuishui", "chapter": 13, "event": "河边遇寇仲徐子陵,被沈落雁生擒" },
+ { "location": "pengcheng", "chapter": 13, "event": "到达彭城,参与赌赛" },
+ { "location": "pengcheng", "chapter": 14, "event": "与寇徐分头逃走,最终被沈落雁所擒" },
+ { "location": "pengcheng", "chapter": 16, "event": "已归降瓦岗军,与沈落雁配合" }
+ ]
+ },
+ {
+ "character": "李世民",
+ "color": "#4169E1",
+ "route": [
+ { "location": "luo_yang", "chapter": 14, "event": "与李渊船队从洛阳出发" },
+ { "location": "shuishui", "chapter": 14, "event": "船上与寇徐相识,达成合作协议" },
+ { "location": "pengcheng", "chapter": 14, "event": "船队到达彭城,继续谈判" }
+ ]
+ },
+ {
+ "character": "杜伏威",
+ "color": "#FF8C00",
+ "route": [
+ { "location": "pengcheng", "chapter": 16, "event": "在赌场突然出现,力压群雄" }
+ ]
+ }
+ ],
+
+ "key_events": [
+ { "chapter": 12, "event": "寇徐二人目睹隋军暴行,开始习武对敌", "lat": 33.5, "lng": 117.0 },
+ { "chapter": 12, "event": "寇徐参与战场,遇见沈落雁率领的青衣武士", "lat": 33.8, "lng": 117.2 },
+ { "chapter": 13, "location": "pengcheng", "event": "秦叔宝、寇徐遇沈落雁于泗水,定下赌约" },
+ { "chapter": 13, "event": "寇徐二人身上被沾追踪粉末,识破鸟儿追踪之法", "lat": 34.0, "lng": 117.2 },
+ { "chapter": 13, "event": "渔夫莫成布局,寇徐潜水脱险,乘大船逃脱", "lat": 34.15, "lng": 117.25 },
+ { "chapter": 14, "event": "莫成等人为李阀来客所阻,意识到形势变化", "lat": 34.15, "lng": 117.2 },
+ { "chapter": 14, "event": "李世民在船上与寇徐相识,得知东溟夫人账簿秘密", "location": "shuishui" },
+ { "chapter": 14, "event": "寇徐进城赴约,提防沈落雁陷阱", "location": "pengcheng" },
+ { "chapter": 14, "event": "寇徐在旅馆遭沈落雁暴力追杀,破壁逃脱", "location": "pengcheng" },
+ { "chapter": 15, "event": "寇徐计划攀城逃脱,购取钩子与绳索", "location": "pengcheng" },
+ { "chapter": 15, "event": "入翠碧楼,遇香玉山与任媚媚,被施展媚术", "location": "pengcheng" },
+ { "chapter": 16, "event": "赌场与任媚媚对赌,沈落雁突然现身", "location": "pengcheng" },
+ { "chapter": 16, "event": "杜伏威突现赌场,压倒众人,欲带寇徐回家", "location": "pengcheng" },
+ { "chapter": 16, "event": "东溟派护法单秀、单玉蝶现身,与杜伏威对峙", "location": "pengcheng" }
+ ]
+}
diff --git a/data/vol04.json b/data/vol04.json
new file mode 100644
index 0000000..e97cfd3
--- /dev/null
+++ b/data/vol04.json
@@ -0,0 +1,186 @@
+{
+ "volume": "卷四",
+ "chapters": [
+ "第01章 志比天高",
+ "第02章 井边悟道",
+ "第03章 彗星北来",
+ "第04章 奇女青璇",
+ "第05章 宇文无敌",
+ "第06章 重会素素",
+ "第07章 避难学艺",
+ "第08章 笼中之鸟",
+ "第09章 衷诚合作",
+ "第10章 以怨报德",
+ "第11章 夜访青楼",
+ "第12章 大祸忽至"
+ ],
+
+ "locations": [
+ { "id": "baiyezeregion", "name": "巨野泽地区", "aliases": ["巨野", "大湖"], "type": "waterway", "lat": 35.0, "lng": 115.3, "description": "鲁西南运河沿线湖泽,寇徐与李世民分手处" },
+ { "id": "dongpingg郡", "name": "东平郡", "aliases": ["东平"], "type": "city", "lat": 35.4, "lng": 115.8, "description": "运河沿线重镇,石青璇初现、跋锋寒约战欧阳希夷处,寇徐短暂隐居处" },
+ { "id": "xingyang", "name": "荥阳", "aliases": ["荥阳城"], "type": "city", "lat": 34.79, "lng": 113.38, "description": "瓦岗军大龙头翟让根据地,大运河与黄河交汇处,兵家必争之地" },
+ { "id": "luokou", "name": "洛口", "aliases": ["兴洛仓", "洛口仓"], "type": "landmark", "lat": 34.5, "lng": 113.1, "description": "大运河与黄河交汇处,隋朝最大粮仓,李密攻占处" },
+ { "id": "luoyang", "name": "洛阳", "aliases": ["东都"], "type": "city", "lat": 34.62, "lng": 112.45, "description": "隋朝东都,王世充镇守处" },
+ { "id": "hujie", "name": "虎牢", "aliases": ["虎牢关"], "type": "landmark", "lat": 34.78, "lng": 112.95, "description": "荥阳西要塞,裴仁基守兵处" },
+ { "id": "xiangyang_region", "name": "香玉山来处", "type": "landmark", "lat": 31.0, "lng": 116.0, "description": "巴陵帮二当家萧铣活动地区" },
+ { "id": "leshoucheng", "name": "乐寿", "aliases": ["乐寿城"], "type": "city", "lat": 38.5, "lng": 116.8, "description": "窦建德根据地,河北地区" }
+ ],
+
+ "factions": [
+ {
+ "id": "wagang_army",
+ "name": "瓦岗军",
+ "type": "义军",
+ "color": "#FF6347",
+ "leader": "翟让(后由李密取而代之)",
+ "territory": ["xingyang", "luokou"],
+ "key_figures": ["翟让", "李密", "祖君彦", "沈落雁", "王伯当", "徐世绩"],
+ "description": "天下义军之首,翟让为名义大龙头,但李密实权逐渐上升,最终导致内争"
+ },
+ {
+ "id": "li_clan",
+ "name": "李阀",
+ "type": "门阀",
+ "color": "#DC143C",
+ "leader": "李渊",
+ "territory": [],
+ "key_figures": ["李渊", "李世民", "李秀宁"],
+ "description": "四姓门阀之一,李世民招募寇徐,图谋割据"
+ },
+ {
+ "id": "yuwen",
+ "name": "宇文阀",
+ "type": "门阀",
+ "color": "#4169E1",
+ "leader": "宇文伤",
+ "territory": ["daxing"],
+ "key_figures": ["宇文伤", "宇文化及", "宇文无敌", "宇文成都"],
+ "description": "四姓门阀之一,宇文无敌为高手,追捕寇徐账簿"
+ },
+ {
+ "id": "balingang",
+ "name": "巴陵帮",
+ "type": "江湖势力",
+ "color": "#9370DB",
+ "leader": "萧铣(二当家)",
+ "territory": [],
+ "key_figures": ["萧铣", "香玉山", "陆抗"],
+ "description": "八帮次席,经营青楼赌馆庞大网络,与宇文阿针对"
+ },
+ {
+ "id": "dou_jiande",
+ "name": "窦建德军",
+ "type": "义军",
+ "color": "#8B4513",
+ "leader": "窦建德",
+ "territory": ["leshoucheng"],
+ "key_figures": ["窦建德"],
+ "description": "河北黑道霸主,翟让往日命交"
+ },
+ {
+ "id": "dong_ming_pai",
+ "name": "东溟派",
+ "type": "江湖势力",
+ "color": "#FF8C00",
+ "leader": "东溟夫人",
+ "territory": [],
+ "key_figures": ["单婉晶", "尚明", "尚邦", "尚奎义"],
+ "description": "海上势力,贩运兵器,与李阀、宇文阀有贸易往来"
+ },
+ {
+ "id": "sui",
+ "name": "隋朝",
+ "type": "朝廷",
+ "color": "#FFD700",
+ "leader": "杨广(隋炀帝)",
+ "territory": ["luoyang", "yangzhou"],
+ "key_figures": ["杨广", "王世充", "刘长恭", "裴仁基"],
+ "description": "当朝政权,各地义军起义,气数将尽"
+ }
+ ],
+
+ "character_routes": [
+ {
+ "character": "寇仲 & 徐子陵",
+ "color": "#FF4500",
+ "route": [
+ { "location": "baiyezeregion", "chapter": 1, "event": "与李世民分手,寇仲立志争天下" },
+ { "lat": 35.2, "lng": 115.5, "chapter": 1, "event": "两人在野外露宿,讨论人生理想" },
+ { "location": "dongpingg郡", "chapter": 2, "event": "抵达东平郡,在酒楼与沈乃堂等遇见" },
+ { "lat": 35.4, "lng": 115.8, "chapter": 3, "event": "在王府见证跋锋寒与欧阳希夷激战,听石青璇箫音" },
+ { "location": "dongpingg郡", "chapter": 4, "event": "在王府柴房潜修七天,领悟武道真谛" },
+ { "lat": 34.9, "lng": 114.5, "chapter": 5, "event": "途中遇宇文无敌,首次恶战获胜,伤敌不伤己" },
+ { "location": "xingyang", "chapter": 6, "event": "抵达荥阳翟府,重逢素素" },
+ { "location": "xingyang", "chapter": 7, "event": "在翟府学艺于屠叔方,被翟娇奴役于膳房" },
+ { "location": "xingyang", "chapter": 8, "event": "与屠叔方交心,获得保护与指导" },
+ { "location": "xingyang", "chapter": 9, "event": "在街上遇香玉山,洽谈合作协议" },
+ { "location": "xingyang", "chapter": 10, "event": "见翟让,遭其掌击,进入合作双修阶段" },
+ { "lat": 34.8, "lng": 113.2, "chapter": 11, "event": "赴黛青院见沈落雁,获悉翟让伪装让位计划" },
+ { "location": "xingyang", "chapter": 12, "event": "李密发动突变,与素素逃离荥阳" }
+ ]
+ },
+ {
+ "character": "翟让",
+ "color": "#FF1493",
+ "route": [
+ { "location": "xingyang", "chapter": 6, "event": "大胜张须陀,声威如日中天" },
+ { "location": "xingyang", "chapter": 10, "event": "被李密暗算受重伤,与寇徐二人激战" },
+ { "location": "xingyang", "chapter": 11, "event": "伪装让位,设计延缓李密动作" },
+ { "location": "xingyang", "chapter": 12, "event": "与李密决战,为寇徐逃脱争取时间" }
+ ]
+ },
+ {
+ "character": "李密",
+ "color": "#8B0000",
+ "route": [
+ { "location": "luokou", "chapter": 6, "event": "攻占兴洛仓,声望日增,威胁翟让地位" },
+ { "location": "xingyang", "chapter": 10, "event": "暗算翟让,伤其经脉" },
+ { "location": "xingyang", "chapter": 12, "event": "率军进攻翟府,发动最终决战" }
+ ]
+ },
+ {
+ "character": "沈落雁",
+ "color": "#228B22",
+ "route": [
+ { "location": "luokou", "chapter": 8, "event": "在洛口战场统军" },
+ { "location": "xingyang", "chapter": 8, "event": "返回荥阳,对寇徐用刑逼供" },
+ { "location": "xingyang", "chapter": 11, "event": "在黛青院与寇徐谈心,试探真实意图" },
+ { "location": "xingyang", "chapter": 12, "event": "配合李密行动,发动突变" }
+ ]
+ },
+ {
+ "character": "素素",
+ "color": "#FFB6C1",
+ "route": [
+ { "location": "xingyang", "chapter": 6, "event": "在翟府与寇徐重逢,充当桥梁人物" },
+ { "location": "xingyang", "chapter": 7, "event": "被王伯当所辱,心灵创伤" },
+ { "location": "xingyang", "chapter": 10, "event": "陪伴寇徐,成为三人唯一纽带" },
+ { "location": "xingyang", "chapter": 12, "event": "与寇徐逃离荥阳,踏上新征途" }
+ ]
+ },
+ {
+ "character": "跋锋寒",
+ "color": "#DC143C",
+ "route": [
+ { "location": "dongpingg郡", "chapter": 4, "event": "初临中原,与欧阳希夷激战,震撼众人" }
+ ]
+ }
+ ],
+
+ "key_events": [
+ { "chapter": 1, "location": "baiyezeregion", "event": "寇仲立志争天下,与李世民和平分手" },
+ { "chapter": 2, "location": "dongpingg郡", "event": "寇徐在井边悟道,领悟'不波井水'心法精髓" },
+ { "chapter": 3, "location": "dongpingg郡", "event": "跋锋寒现身,与欧阳希夷激战,石青璇箫音化解恶斗" },
+ { "chapter": 4, "location": "dongpingg郡", "event": "寇徐躲藏柴房七天,深化武学理解" },
+ { "chapter": 5, "lat": 34.9, "lng": 114.5, "event": "寇徐与宇文无敌首次对战,双方受伤,分出高下" },
+ { "chapter": 6, "location": "xingyang", "event": "寇徐抵达荥阳,与素素重逢,获翟让接纳" },
+ { "chapter": 6, "location": "luokou", "event": "瓦岗军攻占兴洛仓,李密声望上升,翟让地位动摇" },
+ { "chapter": 7, "location": "xingyang", "event": "寇徐在翟府学艺,屠叔方成为恩师" },
+ { "chapter": 8, "location": "xingyang", "event": "沈落雁对寇徐进行盘问与试探,双方交集增加" },
+ { "chapter": 9, "location": "xingyang", "event": "香玉山出现,代表巴陵帮提议合作对付宇文阀" },
+ { "chapter": 10, "lat": 34.75, "lng": 113.4, "event": "翟让因内伤复发与寇徐激战,双方力量均衡" },
+ { "chapter": 10, "location": "xingyang", "event": "翟让与李密之间的矛盾公开化,翟让拟将大权下交" },
+ { "chapter": 11, "lat": 35.4, "lng": 115.8, "event": "寇徐赴黛青院见沈落雁,获悉翟让伪装让位的计谋" },
+ { "chapter": 12, "location": "xingyang", "event": "李密发动突变进攻翟府,翟让与其决战,寇徐素素乘乱逃脱" }
+ ]
+}
diff --git a/data/vol05.json b/data/vol05.json
new file mode 100644
index 0000000..eb4bad6
--- /dev/null
+++ b/data/vol05.json
@@ -0,0 +1,183 @@
+{
+ "volume": "卷五",
+ "chapters": ["第01章 仅以身免", "第02章 大隐于市", "第03章 影子刺客", "第04章 偷龙转凤", "第05章 情孽纠缠"],
+
+ "locations": [
+ { "id": "yangzhou", "name": "扬州", "aliases": ["江都"], "type": "city", "lat": 32.39, "lng": 119.43, "description": "隋朝南都,长江与运河交汇的重镇,寇仲徐子陵的出生地" },
+ { "id": "xingyang", "name": "荥阳", "type": "city", "lat": 34.79, "lng": 113.38, "description": "瓦岗军翟让的根据地,本卷主要舞台" },
+ { "id": "wagang", "name": "瓦岗寨", "type": "town", "lat": 35.25, "lng": 114.7, "description": "翟让起义之地,大龙头府所在地" },
+ { "id": "grand_canal", "name": "大运河", "aliases": ["运河","通济渠"], "type": "waterway", "lat": 33.5, "lng": 118.0, "description": "贯通南北的水路交通线" },
+ { "id": "yangtze", "name": "长江", "aliases": ["大江"], "type": "waterway", "lat": 32.2, "lng": 119.0, "description": "中国第一大河" },
+ { "id": "liyang", "name": "历阳", "type": "city", "lat": 31.7, "lng": 118.37, "description": "长江沿岸重镇,被杜伏威攻占,截断长江水道" },
+ { "id": "luoyang", "name": "洛阳", "aliases": ["东都"], "type": "city", "lat": 34.62, "lng": 112.45, "description": "隋朝东都" },
+ { "id": "daxing", "name": "大兴", "aliases": ["长安","京师"], "type": "city", "lat": 34.26, "lng": 108.94, "description": "隋朝西京,帝国首都" },
+ { "id": "heiyang", "name": "黎阳仓", "type": "town", "lat": 35.8, "lng": 114.5, "description": "粮仓重镇,李密攻打的目标" }
+ ],
+
+ "factions": [
+ {
+ "id": "wagang_army",
+ "name": "瓦岗军",
+ "type": "义军",
+ "color": "#FF6347",
+ "leader": "翟让(已死)、李密",
+ "territory": ["xingyang", "wagang"],
+ "key_figures": ["翟让(死于本卷开头)", "李密", "徐世绩", "沈落雁", "祖君彦"],
+ "description": "天下义军之首,翟让已遭李密属下击杀,内部出现严重分裂。李密接管势力,但仍有翟让旧部不服。现驻荥阳"
+ },
+ {
+ "id": "li_clan",
+ "name": "李阀",
+ "type": "门阀",
+ "color": "#DC143C",
+ "leader": "李渊",
+ "territory": [],
+ "key_figures": ["李渋"],
+ "description": "四姓门阀之一"
+ },
+ {
+ "id": "song_clan",
+ "name": "宋阀",
+ "type": "门阀",
+ "color": "#228B22",
+ "leader": "宋缺",
+ "territory": ["chengdu"],
+ "key_figures": ["宋缺", "宋师道", "宋玉致"],
+ "description": "四姓门阀之一,派宋玉致往荥阳联结瓦岗军,图谋联手对付杜伏威"
+ },
+ {
+ "id": "du_fuwei",
+ "name": "杜伏威军",
+ "type": "义军",
+ "color": "#FF8C00",
+ "leader": "杜伏威",
+ "territory": ["liyang"],
+ "key_figures": ["杜伏威", "辅公祏"],
+ "description": "江淮义军,占据历阳,截断长江盐船交通,成为宋阀和瓦岗军的共同威胁"
+ },
+ {
+ "id": "sui",
+ "name": "隋朝",
+ "type": "朝廷",
+ "color": "#FFD700",
+ "leader": "杨广(隋炀帝)",
+ "territory": [],
+ "key_figures": ["杨广"],
+ "description": "当朝政权,大军源源进驻江东,图谋收复江南"
+ },
+ {
+ "id": "baijing_bang",
+ "name": "巴陵帮",
+ "type": "江湖势力",
+ "color": "#DAA520",
+ "leader": "佩佩(香玉山)",
+ "territory": [],
+ "key_figures": ["佩佩", "香玉山", "云娘"],
+ "description": "荥阳黛青楼所属势力,老板娘佩佩为首领,受瓦岗军压制"
+ },
+ {
+ "id": "iron_serfs",
+ "name": "铁勒",
+ "type": "外族",
+ "color": "#696969",
+ "leader": "铁勒王",
+ "territory": [],
+ "key_figures": ["曲傲"],
+ "description": "西疆势力,与突厥为敌,派曲傲来中原联结势力,密谋刺杀李密"
+ }
+ ],
+
+ "character_routes": [
+ {
+ "character": "寇仲 & 徐子陵",
+ "color": "#FF4500",
+ "route": [
+ { "location": "wagang", "chapter": 1, "event": "大龙头府火烧翟让死讯传出,两人在府内逃脱" },
+ { "lat": 34.79, "lng": 113.35, "chapter": 1, "event": "躲在水池假石山干井内,听李密与沈落雁商议" },
+ { "location": "xingyang", "chapter": 2, "event": "潜入沈落雁香居落雁庄躲藏" },
+ { "lat": 34.79, "lng": 113.38, "chapter": 2, "event": "在衣铺购买绸缎计划,通过素素寻找佩佩" },
+ { "location": "xingyang", "chapter": 3, "event": "徐子陵在沈宅闺房遭杨虚彦重创,险些丧命" },
+ { "lat": 34.79, "lng": 113.35, "chapter": 3, "event": "徐子陵伤重后潜逃,后向沈落雁诈降救素素" },
+ { "location": "xingyang", "chapter": 4, "event": "两人互换名册,以论语骗沈落雁,救出素素" },
+ { "location": "xingyang", "chapter": 5, "event": "躲入黛青楼,寻求佩佩帮助无果,改道潜入徐世绩府第探图" }
+ ]
+ },
+ {
+ "character": "素素",
+ "color": "#FFB6C1",
+ "route": [
+ { "location": "wagang", "chapter": 1, "event": "翟府大火中被寇仲背着逃出,躲在水池假石山干井" },
+ { "location": "xingyang", "chapter": 2, "event": "进入沈落雁香居躲藏,后被沈府婢仆发现行迹异常" },
+ { "location": "xingyang", "chapter": 2, "event": "以小婢身份赴衣铺购买绸缎,获取佩佩的联系方式" },
+ { "location": "xingyang", "chapter": 3, "event": "在沈宅遭徐世绩逮捕,但寇仲以名册诈降救回" },
+ { "location": "xingyang", "chapter": 5, "event": "躲入徐世绩府中大柜,被徐子陵以真气保护呼吸" }
+ ]
+ },
+ {
+ "character": "李密",
+ "color": "#FF6347",
+ "route": [
+ { "location": "wagang", "chapter": 1, "event": "率众火烧翟让大龙头府,杀翟让并接管瓦岗军" },
+ { "lat": 34.79, "lng": 113.35, "chapter": 1, "event": "亲临现场搜捕漏网之人,对寇仲徐子陵下杀令" },
+ { "location": "xingyang", "chapter": 2, "event": "率兵出城北上,攻打黎阳仓" }
+ ]
+ },
+ {
+ "character": "沈落雁",
+ "color": "#228B22",
+ "route": [
+ { "location": "wagang", "chapter": 1, "event": "与沈落雁在翟府外商议李密建议" },
+ { "location": "xingyang", "chapter": 2, "event": "在落雁庄接待宋玉致,商议对付杜伏威的计划" },
+ { "location": "xingyang", "chapter": 3, "event": "闺房遭杨虚彦暗袭,险被刺杀" },
+ { "location": "xingyang", "chapter": 4, "event": "与寇仲在门前交易,以素素换名册,却被骗以论语替代" },
+ { "location": "xingyang", "chapter": 5, "event": "与徐世绩商议搜捕计划,怀疑徐子陵未死" }
+ ]
+ },
+ {
+ "character": "徐世绩",
+ "color": "#FF6347",
+ "route": [
+ { "location": "wagang", "chapter": 1, "event": "参与火烧翟府,主持全城搜捕寇徐二人" },
+ { "location": "xingyang", "chapter": 2, "event": "在沈宅设伏搜索,全城逐户逐街查缉" },
+ { "location": "xingyang", "chapter": 5, "event": "与沈落雁商议扩大搜索范围,对感情生变而不悦" }
+ ]
+ },
+ {
+ "character": "宋玉致",
+ "color": "#228B22",
+ "route": [
+ { "location": "xingyang", "chapter": 2, "event": "自成都来荥阳谒见李密,与沈落雁商议联手对付杜伏威及曲傲" }
+ ]
+ },
+ {
+ "character": "杨虚彦",
+ "color": "#000000",
+ "route": [
+ { "location": "xingyang", "chapter": 3, "event": "躲在沈落雁闺房内暗袭,误将徐子陵作为沈落雁的人而重创他" }
+ ]
+ },
+ {
+ "character": "佩佩",
+ "color": "#DAA520",
+ "route": [
+ { "location": "xingyang", "chapter": 5, "event": "返回黛青楼闺房,遭沈落雁威胁,决定向其报告寇徐消息" }
+ ]
+ }
+ ],
+
+ "key_events": [
+ { "chapter": 1, "location": "wagang", "event": "翟让大龙头府大火,翟让遭李密属下击杀,瓦岗军内部分裂" },
+ { "chapter": 1, "lat": 34.79, "lng": 113.35, "event": "寇仲徐子陵救素素躲入水池假石山干井,听李密决议杀死两人" },
+ { "chapter": 1, "event": "沈落雁对徐世绩表示寇徐两人功力日增,可能成为祸患", "lat": 34.79, "lng": 113.35 },
+ { "chapter": 2, "location": "xingyang", "event": "三人潜入沈落雁的落雁庄,利用荥阳城的迷宫般小巷躲避搜查" },
+ { "chapter": 2, "event": "宋玉致抵荥阳,向沈落雁透露曲傲密谋刺杀李密的计划", "lat": 34.79, "lng": 113.38 },
+ { "chapter": 2, "event": "素素为获取佩佩联系方式,赴衣铺指定购买绸缎,险被沈落雁撞见", "lat": 34.79, "lng": 113.38 },
+ { "chapter": 3, "location": "xingyang", "event": "沈宅内徐子陵遭影子刺客杨虚彦重创,险些丧命,寇仲救出" },
+ { "chapter": 3, "event": "三人夜间逃离沈宅,躲入附近民居储物房,徐子陵通过真气疗伤恢复", "lat": 34.79, "lng": 113.35 },
+ { "chapter": 4, "location": "xingyang", "event": "寇仲赴沈宅门前诈降,声称徐子陵已死,骗得沈落雁释放素素" },
+ { "chapter": 4, "event": "寇仲以论语替代名册,骗过沈落雁的验证,成功救出素素", "lat": 34.79, "lng": 113.38 },
+ { "chapter": 5, "location": "xingyang", "event": "三人躲入黛青楼,计划通过佩佩(香玉山)获得逃生帮助" },
+ { "chapter": 5, "event": "佩佩被沈落雁威胁,决定向其通报寇徐行踪,望破灭", "lat": 34.79, "lng": 113.38 },
+ { "chapter": 5, "event": "寇徐潜入徐世绩府中,在书室搜得荥阳城地下水沟图,寻得逃脱之路", "lat": 34.79, "lng": 113.38 }
+ ]
+}
diff --git a/frontend/App.vue b/frontend/App.vue
new file mode 100644
index 0000000..eaae09a
--- /dev/null
+++ b/frontend/App.vue
@@ -0,0 +1,507 @@
+
+
+
+
+
大唐双龙传 - 势力分布地图
+
+
+
+
势力图例
+
+
+
{{ faction.name }}({{ faction.leader }})
+
+
+
+
人物路线
+
+
+
{{ route.character }}
+
+
+
+
+
+
+
章节进度
+
+
+
第 {{ currentChapter }} / {{ maxChapter }} 章
+
{{ currentChapterName }}
+
+
+
+
+
×
+
{{ selectedFaction.name }}
+
首领:{{ selectedFaction.leader }}
+
{{ selectedFaction.description }}
+
+ 据点:{{ getTerritoryNames(selectedFaction.territory).join('、') }}
+
+
+ 关键人物:{{ selectedFaction.key_figures.join('、') }}
+
+
+
+
+
+
+
+
diff --git a/frontend/index.html b/frontend/index.html
new file mode 100644
index 0000000..78f5609
--- /dev/null
+++ b/frontend/index.html
@@ -0,0 +1,12 @@
+
+
+
+
+
+ 大唐双龙传 - 势力分布地图
+
+
+
+
+
+
diff --git a/frontend/main.js b/frontend/main.js
new file mode 100644
index 0000000..fe5bae3
--- /dev/null
+++ b/frontend/main.js
@@ -0,0 +1,5 @@
+import { createApp } from 'vue'
+import App from './App.vue'
+import './style.css'
+
+createApp(App).mount('#app')
diff --git a/frontend/package-lock.json b/frontend/package-lock.json
new file mode 100644
index 0000000..8fb36ee
--- /dev/null
+++ b/frontend/package-lock.json
@@ -0,0 +1,1214 @@
+{
+ "name": "dt-map",
+ "version": "1.0.0",
+ "lockfileVersion": 3,
+ "requires": true,
+ "packages": {
+ "": {
+ "name": "dt-map",
+ "version": "1.0.0",
+ "dependencies": {
+ "leaflet": "^1.9.4",
+ "vue": "^3.4.0"
+ },
+ "devDependencies": {
+ "@vitejs/plugin-vue": "^5.0.0",
+ "vite": "^5.0.0"
+ }
+ },
+ "node_modules/@babel/helper-string-parser": {
+ "version": "7.27.1",
+ "resolved": "https://registry.npmmirror.com/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz",
+ "integrity": "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-validator-identifier": {
+ "version": "7.28.5",
+ "resolved": "https://registry.npmmirror.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.28.5.tgz",
+ "integrity": "sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/parser": {
+ "version": "7.29.2",
+ "resolved": "https://registry.npmmirror.com/@babel/parser/-/parser-7.29.2.tgz",
+ "integrity": "sha512-4GgRzy/+fsBa72/RZVJmGKPmZu9Byn8o4MoLpmNe1m8ZfYnz5emHLQz3U4gLud6Zwl0RZIcgiLD7Uq7ySFuDLA==",
+ "license": "MIT",
+ "dependencies": {
+ "@babel/types": "^7.29.0"
+ },
+ "bin": {
+ "parser": "bin/babel-parser.js"
+ },
+ "engines": {
+ "node": ">=6.0.0"
+ }
+ },
+ "node_modules/@babel/types": {
+ "version": "7.29.0",
+ "resolved": "https://registry.npmmirror.com/@babel/types/-/types-7.29.0.tgz",
+ "integrity": "sha512-LwdZHpScM4Qz8Xw2iKSzS+cfglZzJGvofQICy7W7v4caru4EaAmyUuO6BGrbyQ2mYV11W0U8j5mBhd14dd3B0A==",
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-string-parser": "^7.27.1",
+ "@babel/helper-validator-identifier": "^7.28.5"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@esbuild/aix-ppc64": {
+ "version": "0.21.5",
+ "resolved": "https://registry.npmmirror.com/@esbuild/aix-ppc64/-/aix-ppc64-0.21.5.tgz",
+ "integrity": "sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ==",
+ "cpu": [
+ "ppc64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "aix"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/android-arm": {
+ "version": "0.21.5",
+ "resolved": "https://registry.npmmirror.com/@esbuild/android-arm/-/android-arm-0.21.5.tgz",
+ "integrity": "sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg==",
+ "cpu": [
+ "arm"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "android"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/android-arm64": {
+ "version": "0.21.5",
+ "resolved": "https://registry.npmmirror.com/@esbuild/android-arm64/-/android-arm64-0.21.5.tgz",
+ "integrity": "sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "android"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/android-x64": {
+ "version": "0.21.5",
+ "resolved": "https://registry.npmmirror.com/@esbuild/android-x64/-/android-x64-0.21.5.tgz",
+ "integrity": "sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "android"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/darwin-arm64": {
+ "version": "0.21.5",
+ "resolved": "https://registry.npmmirror.com/@esbuild/darwin-arm64/-/darwin-arm64-0.21.5.tgz",
+ "integrity": "sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/darwin-x64": {
+ "version": "0.21.5",
+ "resolved": "https://registry.npmmirror.com/@esbuild/darwin-x64/-/darwin-x64-0.21.5.tgz",
+ "integrity": "sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/freebsd-arm64": {
+ "version": "0.21.5",
+ "resolved": "https://registry.npmmirror.com/@esbuild/freebsd-arm64/-/freebsd-arm64-0.21.5.tgz",
+ "integrity": "sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "freebsd"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/freebsd-x64": {
+ "version": "0.21.5",
+ "resolved": "https://registry.npmmirror.com/@esbuild/freebsd-x64/-/freebsd-x64-0.21.5.tgz",
+ "integrity": "sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "freebsd"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/linux-arm": {
+ "version": "0.21.5",
+ "resolved": "https://registry.npmmirror.com/@esbuild/linux-arm/-/linux-arm-0.21.5.tgz",
+ "integrity": "sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA==",
+ "cpu": [
+ "arm"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/linux-arm64": {
+ "version": "0.21.5",
+ "resolved": "https://registry.npmmirror.com/@esbuild/linux-arm64/-/linux-arm64-0.21.5.tgz",
+ "integrity": "sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/linux-ia32": {
+ "version": "0.21.5",
+ "resolved": "https://registry.npmmirror.com/@esbuild/linux-ia32/-/linux-ia32-0.21.5.tgz",
+ "integrity": "sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg==",
+ "cpu": [
+ "ia32"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/linux-loong64": {
+ "version": "0.21.5",
+ "resolved": "https://registry.npmmirror.com/@esbuild/linux-loong64/-/linux-loong64-0.21.5.tgz",
+ "integrity": "sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg==",
+ "cpu": [
+ "loong64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/linux-mips64el": {
+ "version": "0.21.5",
+ "resolved": "https://registry.npmmirror.com/@esbuild/linux-mips64el/-/linux-mips64el-0.21.5.tgz",
+ "integrity": "sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg==",
+ "cpu": [
+ "mips64el"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/linux-ppc64": {
+ "version": "0.21.5",
+ "resolved": "https://registry.npmmirror.com/@esbuild/linux-ppc64/-/linux-ppc64-0.21.5.tgz",
+ "integrity": "sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w==",
+ "cpu": [
+ "ppc64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/linux-riscv64": {
+ "version": "0.21.5",
+ "resolved": "https://registry.npmmirror.com/@esbuild/linux-riscv64/-/linux-riscv64-0.21.5.tgz",
+ "integrity": "sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA==",
+ "cpu": [
+ "riscv64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/linux-s390x": {
+ "version": "0.21.5",
+ "resolved": "https://registry.npmmirror.com/@esbuild/linux-s390x/-/linux-s390x-0.21.5.tgz",
+ "integrity": "sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A==",
+ "cpu": [
+ "s390x"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/linux-x64": {
+ "version": "0.21.5",
+ "resolved": "https://registry.npmmirror.com/@esbuild/linux-x64/-/linux-x64-0.21.5.tgz",
+ "integrity": "sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/netbsd-x64": {
+ "version": "0.21.5",
+ "resolved": "https://registry.npmmirror.com/@esbuild/netbsd-x64/-/netbsd-x64-0.21.5.tgz",
+ "integrity": "sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "netbsd"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/openbsd-x64": {
+ "version": "0.21.5",
+ "resolved": "https://registry.npmmirror.com/@esbuild/openbsd-x64/-/openbsd-x64-0.21.5.tgz",
+ "integrity": "sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "openbsd"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/sunos-x64": {
+ "version": "0.21.5",
+ "resolved": "https://registry.npmmirror.com/@esbuild/sunos-x64/-/sunos-x64-0.21.5.tgz",
+ "integrity": "sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "sunos"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/win32-arm64": {
+ "version": "0.21.5",
+ "resolved": "https://registry.npmmirror.com/@esbuild/win32-arm64/-/win32-arm64-0.21.5.tgz",
+ "integrity": "sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/win32-ia32": {
+ "version": "0.21.5",
+ "resolved": "https://registry.npmmirror.com/@esbuild/win32-ia32/-/win32-ia32-0.21.5.tgz",
+ "integrity": "sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA==",
+ "cpu": [
+ "ia32"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/win32-x64": {
+ "version": "0.21.5",
+ "resolved": "https://registry.npmmirror.com/@esbuild/win32-x64/-/win32-x64-0.21.5.tgz",
+ "integrity": "sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@jridgewell/sourcemap-codec": {
+ "version": "1.5.5",
+ "resolved": "https://registry.npmmirror.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz",
+ "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==",
+ "license": "MIT"
+ },
+ "node_modules/@rollup/rollup-android-arm-eabi": {
+ "version": "4.60.1",
+ "resolved": "https://registry.npmmirror.com/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.60.1.tgz",
+ "integrity": "sha512-d6FinEBLdIiK+1uACUttJKfgZREXrF0Qc2SmLII7W2AD8FfiZ9Wjd+rD/iRuf5s5dWrr1GgwXCvPqOuDquOowA==",
+ "cpu": [
+ "arm"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "android"
+ ]
+ },
+ "node_modules/@rollup/rollup-android-arm64": {
+ "version": "4.60.1",
+ "resolved": "https://registry.npmmirror.com/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.60.1.tgz",
+ "integrity": "sha512-YjG/EwIDvvYI1YvYbHvDz/BYHtkY4ygUIXHnTdLhG+hKIQFBiosfWiACWortsKPKU/+dUwQQCKQM3qrDe8c9BA==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "android"
+ ]
+ },
+ "node_modules/@rollup/rollup-darwin-arm64": {
+ "version": "4.60.1",
+ "resolved": "https://registry.npmmirror.com/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.60.1.tgz",
+ "integrity": "sha512-mjCpF7GmkRtSJwon+Rq1N8+pI+8l7w5g9Z3vWj4T7abguC4Czwi3Yu/pFaLvA3TTeMVjnu3ctigusqWUfjZzvw==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "darwin"
+ ]
+ },
+ "node_modules/@rollup/rollup-darwin-x64": {
+ "version": "4.60.1",
+ "resolved": "https://registry.npmmirror.com/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.60.1.tgz",
+ "integrity": "sha512-haZ7hJ1JT4e9hqkoT9R/19XW2QKqjfJVv+i5AGg57S+nLk9lQnJ1F/eZloRO3o9Scy9CM3wQ9l+dkXtcBgN5Ew==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "darwin"
+ ]
+ },
+ "node_modules/@rollup/rollup-freebsd-arm64": {
+ "version": "4.60.1",
+ "resolved": "https://registry.npmmirror.com/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.60.1.tgz",
+ "integrity": "sha512-czw90wpQq3ZsAVBlinZjAYTKduOjTywlG7fEeWKUA7oCmpA8xdTkxZZlwNJKWqILlq0wehoZcJYfBvOyhPTQ6w==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "freebsd"
+ ]
+ },
+ "node_modules/@rollup/rollup-freebsd-x64": {
+ "version": "4.60.1",
+ "resolved": "https://registry.npmmirror.com/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.60.1.tgz",
+ "integrity": "sha512-KVB2rqsxTHuBtfOeySEyzEOB7ltlB/ux38iu2rBQzkjbwRVlkhAGIEDiiYnO2kFOkJp+Z7pUXKyrRRFuFUKt+g==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "freebsd"
+ ]
+ },
+ "node_modules/@rollup/rollup-linux-arm-gnueabihf": {
+ "version": "4.60.1",
+ "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.60.1.tgz",
+ "integrity": "sha512-L+34Qqil+v5uC0zEubW7uByo78WOCIrBvci69E7sFASRl0X7b/MB6Cqd1lky/CtcSVTydWa2WZwFuWexjS5o6g==",
+ "cpu": [
+ "arm"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rollup/rollup-linux-arm-musleabihf": {
+ "version": "4.60.1",
+ "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.60.1.tgz",
+ "integrity": "sha512-n83O8rt4v34hgFzlkb1ycniJh7IR5RCIqt6mz1VRJD6pmhRi0CXdmfnLu9dIUS6buzh60IvACM842Ffb3xd6Gg==",
+ "cpu": [
+ "arm"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rollup/rollup-linux-arm64-gnu": {
+ "version": "4.60.1",
+ "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.60.1.tgz",
+ "integrity": "sha512-Nql7sTeAzhTAja3QXeAI48+/+GjBJ+QmAH13snn0AJSNL50JsDqotyudHyMbO2RbJkskbMbFJfIJKWA6R1LCJQ==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rollup/rollup-linux-arm64-musl": {
+ "version": "4.60.1",
+ "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.60.1.tgz",
+ "integrity": "sha512-+pUymDhd0ys9GcKZPPWlFiZ67sTWV5UU6zOJat02M1+PiuSGDziyRuI/pPue3hoUwm2uGfxdL+trT6Z9rxnlMA==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rollup/rollup-linux-loong64-gnu": {
+ "version": "4.60.1",
+ "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.60.1.tgz",
+ "integrity": "sha512-VSvgvQeIcsEvY4bKDHEDWcpW4Yw7BtlKG1GUT4FzBUlEKQK0rWHYBqQt6Fm2taXS+1bXvJT6kICu5ZwqKCnvlQ==",
+ "cpu": [
+ "loong64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rollup/rollup-linux-loong64-musl": {
+ "version": "4.60.1",
+ "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-loong64-musl/-/rollup-linux-loong64-musl-4.60.1.tgz",
+ "integrity": "sha512-4LqhUomJqwe641gsPp6xLfhqWMbQV04KtPp7/dIp0nzPxAkNY1AbwL5W0MQpcalLYk07vaW9Kp1PBhdpZYYcEw==",
+ "cpu": [
+ "loong64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rollup/rollup-linux-ppc64-gnu": {
+ "version": "4.60.1",
+ "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.60.1.tgz",
+ "integrity": "sha512-tLQQ9aPvkBxOc/EUT6j3pyeMD6Hb8QF2BTBnCQWP/uu1lhc9AIrIjKnLYMEroIz/JvtGYgI9dF3AxHZNaEH0rw==",
+ "cpu": [
+ "ppc64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rollup/rollup-linux-ppc64-musl": {
+ "version": "4.60.1",
+ "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-ppc64-musl/-/rollup-linux-ppc64-musl-4.60.1.tgz",
+ "integrity": "sha512-RMxFhJwc9fSXP6PqmAz4cbv3kAyvD1etJFjTx4ONqFP9DkTkXsAMU4v3Vyc5BgzC+anz7nS/9tp4obsKfqkDHg==",
+ "cpu": [
+ "ppc64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rollup/rollup-linux-riscv64-gnu": {
+ "version": "4.60.1",
+ "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.60.1.tgz",
+ "integrity": "sha512-QKgFl+Yc1eEk6MmOBfRHYF6lTxiiiV3/z/BRrbSiW2I7AFTXoBFvdMEyglohPj//2mZS4hDOqeB0H1ACh3sBbg==",
+ "cpu": [
+ "riscv64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rollup/rollup-linux-riscv64-musl": {
+ "version": "4.60.1",
+ "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.60.1.tgz",
+ "integrity": "sha512-RAjXjP/8c6ZtzatZcA1RaQr6O1TRhzC+adn8YZDnChliZHviqIjmvFwHcxi4JKPSDAt6Uhf/7vqcBzQJy0PDJg==",
+ "cpu": [
+ "riscv64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rollup/rollup-linux-s390x-gnu": {
+ "version": "4.60.1",
+ "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.60.1.tgz",
+ "integrity": "sha512-wcuocpaOlaL1COBYiA89O6yfjlp3RwKDeTIA0hM7OpmhR1Bjo9j31G1uQVpDlTvwxGn2nQs65fBFL5UFd76FcQ==",
+ "cpu": [
+ "s390x"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rollup/rollup-linux-x64-gnu": {
+ "version": "4.60.1",
+ "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.60.1.tgz",
+ "integrity": "sha512-77PpsFQUCOiZR9+LQEFg9GClyfkNXj1MP6wRnzYs0EeWbPcHs02AXu4xuUbM1zhwn3wqaizle3AEYg5aeoohhg==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rollup/rollup-linux-x64-musl": {
+ "version": "4.60.1",
+ "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.60.1.tgz",
+ "integrity": "sha512-5cIATbk5vynAjqqmyBjlciMJl1+R/CwX9oLk/EyiFXDWd95KpHdrOJT//rnUl4cUcskrd0jCCw3wpZnhIHdD9w==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rollup/rollup-openbsd-x64": {
+ "version": "4.60.1",
+ "resolved": "https://registry.npmmirror.com/@rollup/rollup-openbsd-x64/-/rollup-openbsd-x64-4.60.1.tgz",
+ "integrity": "sha512-cl0w09WsCi17mcmWqqglez9Gk8isgeWvoUZ3WiJFYSR3zjBQc2J5/ihSjpl+VLjPqjQ/1hJRcqBfLjssREQILw==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "openbsd"
+ ]
+ },
+ "node_modules/@rollup/rollup-openharmony-arm64": {
+ "version": "4.60.1",
+ "resolved": "https://registry.npmmirror.com/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.60.1.tgz",
+ "integrity": "sha512-4Cv23ZrONRbNtbZa37mLSueXUCtN7MXccChtKpUnQNgF010rjrjfHx3QxkS2PI7LqGT5xXyYs1a7LbzAwT0iCA==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "openharmony"
+ ]
+ },
+ "node_modules/@rollup/rollup-win32-arm64-msvc": {
+ "version": "4.60.1",
+ "resolved": "https://registry.npmmirror.com/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.60.1.tgz",
+ "integrity": "sha512-i1okWYkA4FJICtr7KpYzFpRTHgy5jdDbZiWfvny21iIKky5YExiDXP+zbXzm3dUcFpkEeYNHgQ5fuG236JPq0g==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ]
+ },
+ "node_modules/@rollup/rollup-win32-ia32-msvc": {
+ "version": "4.60.1",
+ "resolved": "https://registry.npmmirror.com/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.60.1.tgz",
+ "integrity": "sha512-u09m3CuwLzShA0EYKMNiFgcjjzwqtUMLmuCJLeZWjjOYA3IT2Di09KaxGBTP9xVztWyIWjVdsB2E9goMjZvTQg==",
+ "cpu": [
+ "ia32"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ]
+ },
+ "node_modules/@rollup/rollup-win32-x64-gnu": {
+ "version": "4.60.1",
+ "resolved": "https://registry.npmmirror.com/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.60.1.tgz",
+ "integrity": "sha512-k+600V9Zl1CM7eZxJgMyTUzmrmhB/0XZnF4pRypKAlAgxmedUA+1v9R+XOFv56W4SlHEzfeMtzujLJD22Uz5zg==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ]
+ },
+ "node_modules/@rollup/rollup-win32-x64-msvc": {
+ "version": "4.60.1",
+ "resolved": "https://registry.npmmirror.com/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.60.1.tgz",
+ "integrity": "sha512-lWMnixq/QzxyhTV6NjQJ4SFo1J6PvOX8vUx5Wb4bBPsEb+8xZ89Bz6kOXpfXj9ak9AHTQVQzlgzBEc1SyM27xQ==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ]
+ },
+ "node_modules/@types/estree": {
+ "version": "1.0.8",
+ "resolved": "https://registry.npmmirror.com/@types/estree/-/estree-1.0.8.tgz",
+ "integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@vitejs/plugin-vue": {
+ "version": "5.2.4",
+ "resolved": "https://registry.npmmirror.com/@vitejs/plugin-vue/-/plugin-vue-5.2.4.tgz",
+ "integrity": "sha512-7Yx/SXSOcQq5HiiV3orevHUFn+pmMB4cgbEkDYgnkUWb0WfeQ/wa2yFv6D5ICiCQOVpjA7vYDXrC7AGO8yjDHA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": "^18.0.0 || >=20.0.0"
+ },
+ "peerDependencies": {
+ "vite": "^5.0.0 || ^6.0.0",
+ "vue": "^3.2.25"
+ }
+ },
+ "node_modules/@vue/compiler-core": {
+ "version": "3.5.31",
+ "resolved": "https://registry.npmmirror.com/@vue/compiler-core/-/compiler-core-3.5.31.tgz",
+ "integrity": "sha512-k/ueL14aNIEy5Onf0OVzR8kiqF/WThgLdFhxwa4e/KF/0qe38IwIdofoSWBTvvxQOesaz6riAFAUaYjoF9fLLQ==",
+ "license": "MIT",
+ "dependencies": {
+ "@babel/parser": "^7.29.2",
+ "@vue/shared": "3.5.31",
+ "entities": "^7.0.1",
+ "estree-walker": "^2.0.2",
+ "source-map-js": "^1.2.1"
+ }
+ },
+ "node_modules/@vue/compiler-dom": {
+ "version": "3.5.31",
+ "resolved": "https://registry.npmmirror.com/@vue/compiler-dom/-/compiler-dom-3.5.31.tgz",
+ "integrity": "sha512-BMY/ozS/xxjYqRFL+tKdRpATJYDTTgWSo0+AJvJNg4ig+Hgb0dOsHPXvloHQ5hmlivUqw1Yt2pPIqp4e0v1GUw==",
+ "license": "MIT",
+ "dependencies": {
+ "@vue/compiler-core": "3.5.31",
+ "@vue/shared": "3.5.31"
+ }
+ },
+ "node_modules/@vue/compiler-sfc": {
+ "version": "3.5.31",
+ "resolved": "https://registry.npmmirror.com/@vue/compiler-sfc/-/compiler-sfc-3.5.31.tgz",
+ "integrity": "sha512-M8wpPgR9UJ8MiRGjppvx9uWJfLV7A/T+/rL8s/y3QG3u0c2/YZgff3d6SuimKRIhcYnWg5fTfDMlz2E6seUW8Q==",
+ "license": "MIT",
+ "dependencies": {
+ "@babel/parser": "^7.29.2",
+ "@vue/compiler-core": "3.5.31",
+ "@vue/compiler-dom": "3.5.31",
+ "@vue/compiler-ssr": "3.5.31",
+ "@vue/shared": "3.5.31",
+ "estree-walker": "^2.0.2",
+ "magic-string": "^0.30.21",
+ "postcss": "^8.5.8",
+ "source-map-js": "^1.2.1"
+ }
+ },
+ "node_modules/@vue/compiler-ssr": {
+ "version": "3.5.31",
+ "resolved": "https://registry.npmmirror.com/@vue/compiler-ssr/-/compiler-ssr-3.5.31.tgz",
+ "integrity": "sha512-h0xIMxrt/LHOvJKMri+vdYT92BrK3HFLtDqq9Pr/lVVfE4IyKZKvWf0vJFW10Yr6nX02OR4MkJwI0c1HDa1hog==",
+ "license": "MIT",
+ "dependencies": {
+ "@vue/compiler-dom": "3.5.31",
+ "@vue/shared": "3.5.31"
+ }
+ },
+ "node_modules/@vue/reactivity": {
+ "version": "3.5.31",
+ "resolved": "https://registry.npmmirror.com/@vue/reactivity/-/reactivity-3.5.31.tgz",
+ "integrity": "sha512-DtKXxk9E/KuVvt8VxWu+6Luc9I9ETNcqR1T1oW1gf02nXaZ1kuAx58oVu7uX9XxJR0iJCro6fqBLw9oSBELo5g==",
+ "license": "MIT",
+ "dependencies": {
+ "@vue/shared": "3.5.31"
+ }
+ },
+ "node_modules/@vue/runtime-core": {
+ "version": "3.5.31",
+ "resolved": "https://registry.npmmirror.com/@vue/runtime-core/-/runtime-core-3.5.31.tgz",
+ "integrity": "sha512-AZPmIHXEAyhpkmN7aWlqjSfYynmkWlluDNPHMCZKFHH+lLtxP/30UJmoVhXmbDoP1Ng0jG0fyY2zCj1PnSSA6Q==",
+ "license": "MIT",
+ "dependencies": {
+ "@vue/reactivity": "3.5.31",
+ "@vue/shared": "3.5.31"
+ }
+ },
+ "node_modules/@vue/runtime-dom": {
+ "version": "3.5.31",
+ "resolved": "https://registry.npmmirror.com/@vue/runtime-dom/-/runtime-dom-3.5.31.tgz",
+ "integrity": "sha512-xQJsNRmGPeDCJq/u813tyonNgWBFjzfVkBwDREdEWndBnGdHLHgkwNBQxLtg4zDrzKTEcnikUy1UUNecb3lJ6g==",
+ "license": "MIT",
+ "dependencies": {
+ "@vue/reactivity": "3.5.31",
+ "@vue/runtime-core": "3.5.31",
+ "@vue/shared": "3.5.31",
+ "csstype": "^3.2.3"
+ }
+ },
+ "node_modules/@vue/server-renderer": {
+ "version": "3.5.31",
+ "resolved": "https://registry.npmmirror.com/@vue/server-renderer/-/server-renderer-3.5.31.tgz",
+ "integrity": "sha512-GJuwRvMcdZX/CriUnyIIOGkx3rMV3H6sOu0JhdKbduaeCji6zb60iOGMY7tFoN24NfsUYoFBhshZtGxGpxO4iA==",
+ "license": "MIT",
+ "dependencies": {
+ "@vue/compiler-ssr": "3.5.31",
+ "@vue/shared": "3.5.31"
+ },
+ "peerDependencies": {
+ "vue": "3.5.31"
+ }
+ },
+ "node_modules/@vue/shared": {
+ "version": "3.5.31",
+ "resolved": "https://registry.npmmirror.com/@vue/shared/-/shared-3.5.31.tgz",
+ "integrity": "sha512-nBxuiuS9Lj5bPkPbWogPUnjxxWpkRniX7e5UBQDWl6Fsf4roq9wwV+cR7ezQ4zXswNvPIlsdj1slcLB7XCsRAw==",
+ "license": "MIT"
+ },
+ "node_modules/csstype": {
+ "version": "3.2.3",
+ "resolved": "https://registry.npmmirror.com/csstype/-/csstype-3.2.3.tgz",
+ "integrity": "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==",
+ "license": "MIT"
+ },
+ "node_modules/entities": {
+ "version": "7.0.1",
+ "resolved": "https://registry.npmmirror.com/entities/-/entities-7.0.1.tgz",
+ "integrity": "sha512-TWrgLOFUQTH994YUyl1yT4uyavY5nNB5muff+RtWaqNVCAK408b5ZnnbNAUEWLTCpum9w6arT70i1XdQ4UeOPA==",
+ "license": "BSD-2-Clause",
+ "engines": {
+ "node": ">=0.12"
+ },
+ "funding": {
+ "url": "https://github.com/fb55/entities?sponsor=1"
+ }
+ },
+ "node_modules/esbuild": {
+ "version": "0.21.5",
+ "resolved": "https://registry.npmmirror.com/esbuild/-/esbuild-0.21.5.tgz",
+ "integrity": "sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw==",
+ "dev": true,
+ "hasInstallScript": true,
+ "license": "MIT",
+ "bin": {
+ "esbuild": "bin/esbuild"
+ },
+ "engines": {
+ "node": ">=12"
+ },
+ "optionalDependencies": {
+ "@esbuild/aix-ppc64": "0.21.5",
+ "@esbuild/android-arm": "0.21.5",
+ "@esbuild/android-arm64": "0.21.5",
+ "@esbuild/android-x64": "0.21.5",
+ "@esbuild/darwin-arm64": "0.21.5",
+ "@esbuild/darwin-x64": "0.21.5",
+ "@esbuild/freebsd-arm64": "0.21.5",
+ "@esbuild/freebsd-x64": "0.21.5",
+ "@esbuild/linux-arm": "0.21.5",
+ "@esbuild/linux-arm64": "0.21.5",
+ "@esbuild/linux-ia32": "0.21.5",
+ "@esbuild/linux-loong64": "0.21.5",
+ "@esbuild/linux-mips64el": "0.21.5",
+ "@esbuild/linux-ppc64": "0.21.5",
+ "@esbuild/linux-riscv64": "0.21.5",
+ "@esbuild/linux-s390x": "0.21.5",
+ "@esbuild/linux-x64": "0.21.5",
+ "@esbuild/netbsd-x64": "0.21.5",
+ "@esbuild/openbsd-x64": "0.21.5",
+ "@esbuild/sunos-x64": "0.21.5",
+ "@esbuild/win32-arm64": "0.21.5",
+ "@esbuild/win32-ia32": "0.21.5",
+ "@esbuild/win32-x64": "0.21.5"
+ }
+ },
+ "node_modules/estree-walker": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmmirror.com/estree-walker/-/estree-walker-2.0.2.tgz",
+ "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==",
+ "license": "MIT"
+ },
+ "node_modules/fsevents": {
+ "version": "2.3.3",
+ "resolved": "https://registry.npmmirror.com/fsevents/-/fsevents-2.3.3.tgz",
+ "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==",
+ "dev": true,
+ "hasInstallScript": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": "^8.16.0 || ^10.6.0 || >=11.0.0"
+ }
+ },
+ "node_modules/leaflet": {
+ "version": "1.9.4",
+ "resolved": "https://registry.npmmirror.com/leaflet/-/leaflet-1.9.4.tgz",
+ "integrity": "sha512-nxS1ynzJOmOlHp+iL3FyWqK89GtNL8U8rvlMOsQdTTssxZwCXh8N2NB3GDQOL+YR3XnWyZAxwQixURb+FA74PA==",
+ "license": "BSD-2-Clause"
+ },
+ "node_modules/magic-string": {
+ "version": "0.30.21",
+ "resolved": "https://registry.npmmirror.com/magic-string/-/magic-string-0.30.21.tgz",
+ "integrity": "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==",
+ "license": "MIT",
+ "dependencies": {
+ "@jridgewell/sourcemap-codec": "^1.5.5"
+ }
+ },
+ "node_modules/nanoid": {
+ "version": "3.3.11",
+ "resolved": "https://registry.npmmirror.com/nanoid/-/nanoid-3.3.11.tgz",
+ "integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==",
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/ai"
+ }
+ ],
+ "license": "MIT",
+ "bin": {
+ "nanoid": "bin/nanoid.cjs"
+ },
+ "engines": {
+ "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1"
+ }
+ },
+ "node_modules/picocolors": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmmirror.com/picocolors/-/picocolors-1.1.1.tgz",
+ "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==",
+ "license": "ISC"
+ },
+ "node_modules/postcss": {
+ "version": "8.5.8",
+ "resolved": "https://registry.npmmirror.com/postcss/-/postcss-8.5.8.tgz",
+ "integrity": "sha512-OW/rX8O/jXnm82Ey1k44pObPtdblfiuWnrd8X7GJ7emImCOstunGbXUpp7HdBrFQX6rJzn3sPT397Wp5aCwCHg==",
+ "funding": [
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/postcss/"
+ },
+ {
+ "type": "tidelift",
+ "url": "https://tidelift.com/funding/github/npm/postcss"
+ },
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/ai"
+ }
+ ],
+ "license": "MIT",
+ "dependencies": {
+ "nanoid": "^3.3.11",
+ "picocolors": "^1.1.1",
+ "source-map-js": "^1.2.1"
+ },
+ "engines": {
+ "node": "^10 || ^12 || >=14"
+ }
+ },
+ "node_modules/rollup": {
+ "version": "4.60.1",
+ "resolved": "https://registry.npmmirror.com/rollup/-/rollup-4.60.1.tgz",
+ "integrity": "sha512-VmtB2rFU/GroZ4oL8+ZqXgSA38O6GR8KSIvWmEFv63pQ0G6KaBH9s07PO8XTXP4vI+3UJUEypOfjkGfmSBBR0w==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/estree": "1.0.8"
+ },
+ "bin": {
+ "rollup": "dist/bin/rollup"
+ },
+ "engines": {
+ "node": ">=18.0.0",
+ "npm": ">=8.0.0"
+ },
+ "optionalDependencies": {
+ "@rollup/rollup-android-arm-eabi": "4.60.1",
+ "@rollup/rollup-android-arm64": "4.60.1",
+ "@rollup/rollup-darwin-arm64": "4.60.1",
+ "@rollup/rollup-darwin-x64": "4.60.1",
+ "@rollup/rollup-freebsd-arm64": "4.60.1",
+ "@rollup/rollup-freebsd-x64": "4.60.1",
+ "@rollup/rollup-linux-arm-gnueabihf": "4.60.1",
+ "@rollup/rollup-linux-arm-musleabihf": "4.60.1",
+ "@rollup/rollup-linux-arm64-gnu": "4.60.1",
+ "@rollup/rollup-linux-arm64-musl": "4.60.1",
+ "@rollup/rollup-linux-loong64-gnu": "4.60.1",
+ "@rollup/rollup-linux-loong64-musl": "4.60.1",
+ "@rollup/rollup-linux-ppc64-gnu": "4.60.1",
+ "@rollup/rollup-linux-ppc64-musl": "4.60.1",
+ "@rollup/rollup-linux-riscv64-gnu": "4.60.1",
+ "@rollup/rollup-linux-riscv64-musl": "4.60.1",
+ "@rollup/rollup-linux-s390x-gnu": "4.60.1",
+ "@rollup/rollup-linux-x64-gnu": "4.60.1",
+ "@rollup/rollup-linux-x64-musl": "4.60.1",
+ "@rollup/rollup-openbsd-x64": "4.60.1",
+ "@rollup/rollup-openharmony-arm64": "4.60.1",
+ "@rollup/rollup-win32-arm64-msvc": "4.60.1",
+ "@rollup/rollup-win32-ia32-msvc": "4.60.1",
+ "@rollup/rollup-win32-x64-gnu": "4.60.1",
+ "@rollup/rollup-win32-x64-msvc": "4.60.1",
+ "fsevents": "~2.3.2"
+ }
+ },
+ "node_modules/source-map-js": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmmirror.com/source-map-js/-/source-map-js-1.2.1.tgz",
+ "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==",
+ "license": "BSD-3-Clause",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/vite": {
+ "version": "5.4.21",
+ "resolved": "https://registry.npmmirror.com/vite/-/vite-5.4.21.tgz",
+ "integrity": "sha512-o5a9xKjbtuhY6Bi5S3+HvbRERmouabWbyUcpXXUA1u+GNUKoROi9byOJ8M0nHbHYHkYICiMlqxkg1KkYmm25Sw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "esbuild": "^0.21.3",
+ "postcss": "^8.4.43",
+ "rollup": "^4.20.0"
+ },
+ "bin": {
+ "vite": "bin/vite.js"
+ },
+ "engines": {
+ "node": "^18.0.0 || >=20.0.0"
+ },
+ "funding": {
+ "url": "https://github.com/vitejs/vite?sponsor=1"
+ },
+ "optionalDependencies": {
+ "fsevents": "~2.3.3"
+ },
+ "peerDependencies": {
+ "@types/node": "^18.0.0 || >=20.0.0",
+ "less": "*",
+ "lightningcss": "^1.21.0",
+ "sass": "*",
+ "sass-embedded": "*",
+ "stylus": "*",
+ "sugarss": "*",
+ "terser": "^5.4.0"
+ },
+ "peerDependenciesMeta": {
+ "@types/node": {
+ "optional": true
+ },
+ "less": {
+ "optional": true
+ },
+ "lightningcss": {
+ "optional": true
+ },
+ "sass": {
+ "optional": true
+ },
+ "sass-embedded": {
+ "optional": true
+ },
+ "stylus": {
+ "optional": true
+ },
+ "sugarss": {
+ "optional": true
+ },
+ "terser": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/vue": {
+ "version": "3.5.31",
+ "resolved": "https://registry.npmmirror.com/vue/-/vue-3.5.31.tgz",
+ "integrity": "sha512-iV/sU9SzOlmA/0tygSmjkEN6Jbs3nPoIPFhCMLD2STrjgOU8DX7ZtzMhg4ahVwf5Rp9KoFzcXeB1ZrVbLBp5/Q==",
+ "license": "MIT",
+ "dependencies": {
+ "@vue/compiler-dom": "3.5.31",
+ "@vue/compiler-sfc": "3.5.31",
+ "@vue/runtime-dom": "3.5.31",
+ "@vue/server-renderer": "3.5.31",
+ "@vue/shared": "3.5.31"
+ },
+ "peerDependencies": {
+ "typescript": "*"
+ },
+ "peerDependenciesMeta": {
+ "typescript": {
+ "optional": true
+ }
+ }
+ }
+ }
+}
diff --git a/frontend/package.json b/frontend/package.json
new file mode 100644
index 0000000..bff7867
--- /dev/null
+++ b/frontend/package.json
@@ -0,0 +1,18 @@
+{
+ "name": "dt-map",
+ "version": "1.0.0",
+ "type": "module",
+ "scripts": {
+ "dev": "vite",
+ "build": "vite build",
+ "preview": "vite preview"
+ },
+ "dependencies": {
+ "vue": "^3.4.0",
+ "leaflet": "^1.9.4"
+ },
+ "devDependencies": {
+ "@vitejs/plugin-vue": "^5.0.0",
+ "vite": "^5.0.0"
+ }
+}
diff --git a/frontend/style.css b/frontend/style.css
new file mode 100644
index 0000000..dc0907d
--- /dev/null
+++ b/frontend/style.css
@@ -0,0 +1,14 @@
+* { margin: 0; padding: 0; box-sizing: border-box }
+body { font-family: 'Microsoft YaHei', 'SimSun', sans-serif; background: #1a1a2e; color: #e0e0e0 }
+#app { width: 100%; height: 100vh; overflow: hidden }
+#map { width: 100%; height: 100vh }
+
+.leaflet-popup-content-wrapper {
+ background: rgba(30,30,50,0.95) !important;
+ color: #e0e0e0 !important;
+ border: 1px solid #c9a96e !important;
+ border-radius: 6px !important
+}
+.leaflet-popup-tip { background: rgba(30,30,50,0.95) !important }
+.leaflet-popup-content { font-size: 13px !important; line-height: 1.5 !important }
+.leaflet-popup-content b { color: #c9a96e }
diff --git a/frontend/vite.config.js b/frontend/vite.config.js
new file mode 100644
index 0000000..34e186c
--- /dev/null
+++ b/frontend/vite.config.js
@@ -0,0 +1,36 @@
+import { defineConfig } from 'vite'
+import vue from '@vitejs/plugin-vue'
+import { resolve } from 'path'
+import fs from 'fs'
+import path from 'path'
+import { fileURLToPath } from 'url'
+
+const __dirname = path.dirname(fileURLToPath(import.meta.url))
+
+export default defineConfig({
+ plugins: [
+ vue(),
+ // 开发时将 ../data 目录挂载到 /data 路径
+ {
+ name: 'serve-data-dir',
+ configureServer(server) {
+ server.middlewares.use('/data', (req, res, next) => {
+ const filePath = path.resolve(__dirname, '../data', req.url.replace(/^\//, '').split('?')[0])
+ try {
+ const content = fs.readFileSync(filePath, 'utf-8')
+ res.setHeader('Content-Type', 'application/json; charset=utf-8')
+ res.end(content)
+ } catch {
+ next()
+ }
+ })
+ }
+ }
+ ],
+ server: {
+ port: 5173
+ },
+ build: {
+ outDir: resolve(__dirname, '../dist')
+ }
+})
diff --git a/index.html b/index.html
deleted file mode 100644
index bb1d55f..0000000
--- a/index.html
+++ /dev/null
@@ -1,443 +0,0 @@
-
-
-
-
-
-大唐双龙传 - 势力分布地图(卷一)
-
-
-
-
-
-
-
-大唐双龙传 - 卷一势力分布图
-
-
-
-
-
章节进度
-
-
第 11 / 11 章
-
第11章 追兵忽至
-
-
-
-
-
-
-