[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"home-content":3,"home-stories":242},{"generatedAt":4,"source":5,"albums":6,"gallery":86,"banners":169,"journeyCovers":175,"storyCovers":187,"aboutPhotos":191,"journeys":192,"stories":234},"2026-11-03T07:51:36.971Z","cloud",[7,16,25,34,41,50,59,68,77],{"id":8,"label":9,"description":11,"date":14,"photoCount":15},"ocean-kingdom-2026-08-10",{"zh":10,"en":10},"海洋王国",{"zh":12,"en":13},"海洋王国，记录于 2026-08-10。","海洋王国, captured on 2026-08-10.","2026-08-10",50,{"id":17,"label":18,"description":20,"date":23,"photoCount":24},"changde-wildlife-park-2026-06-28",{"zh":19,"en":19},"常德野生动物园游",{"zh":21,"en":22},"常德野生动物园游，记录于 2026-06-28，共 113 张照片。","常德野生动物园游, captured on 2026-06-28.","2026-06-28",113,{"id":26,"label":27,"description":29,"date":32,"photoCount":33},"hundred-day-feast-2026-09-06",{"zh":28,"en":28},"百日宴",{"zh":30,"en":31},"百日宴，记录于 2026-06-16，共 21 张照片。","百日宴, captured on 2026-06-16.","2026-06-16",22,{"id":35,"label":36,"description":38,"date":32,"photoCount":33},"hundred-day-photos-2026-09-06",{"zh":37,"en":37},"百日照",{"zh":39,"en":40},"百日照，记录于 2026-06-16，共 22 张照片。","百日照, captured on 2026-06-16.",{"id":42,"label":43,"description":45,"date":48,"photoCount":49},"xian-trip-2025-01-11",{"zh":44,"en":44},"西安行",{"zh":46,"en":47},"西安行，记录于 2025-01-11，共 356 张照片。","西安行, captured on 2025-01-11.","2025-01-11",356,{"id":51,"label":52,"description":54,"date":57,"photoCount":58},"hong-kong-macau-2024-02-10",{"zh":53,"en":53},"香港澳门行",{"zh":55,"en":56},"香港澳门行，记录于 2024-02-10，共 225 张照片。","香港澳门行, captured on 2024-02-10.","2024-02-10",225,{"id":60,"label":61,"description":63,"date":66,"photoCount":67},"wedding-portraits-2023-11-26",{"zh":62,"en":62},"结婚照",{"zh":64,"en":65},"结婚照，记录于 2023-11-26，共 59 张照片。","结婚照, captured on 2023-11-26.","2023-11-26",59,{"id":69,"label":70,"description":72,"date":75,"photoCount":76},"wedding-photos-2023-10-01",{"zh":71,"en":71},"婚纱照",{"zh":73,"en":74},"婚纱照，记录于 2023-10-01，共 46 张照片。","婚纱照, captured on 2023-10-01.","2023-10-01",46,{"id":78,"label":79,"description":81,"date":84,"photoCount":85},"wedding-preparation-2023-09-30",{"zh":80,"en":80},"婚礼筹备中",{"zh":82,"en":83},"婚礼筹备中，记录于 2023-09-30，共 41 张照片。","婚礼筹备中, captured on 2023-09-30.","2023-09-30",230,[87,97,105,113,123,133,143,153,161],{"id":88,"src":89,"alt":90,"title":91,"caption":93,"date":14,"location":94,"album":8,"width":95,"height":96},"ocean-kingdom-2026-08-10-1","https:\u002F\u002Fmp-174d4239-a43e-4e0a-9fdc-92547241a10b.cdn.bspapp.com\u002Fkeepsake\u002Falbums\u002Focean-kingdom-2026-08-10\u002F001.jpg","海洋王国 - 照片 001",{"zh":92,"en":92},"海洋王国 · 001",{"zh":12,"en":12},{"zh":10,"en":10},4032,3024,{"id":98,"src":99,"alt":100,"title":101,"caption":103,"date":23,"location":104,"album":17,"width":96,"height":95},"changde-wildlife-park-2026-06-28-1","https:\u002F\u002Fmp-174d4239-a43e-4e0a-9fdc-92547241a10b.cdn.bspapp.com\u002Fkeepsake\u002Falbums\u002Fchangde-wildlife-park-2026-06-28\u002F001.jpg","常德野生动物园游 - 照片 001",{"zh":102,"en":102},"常德野生动物园游 · 001",{"zh":21,"en":21},{"zh":19,"en":19},{"id":106,"src":107,"alt":108,"title":109,"caption":111,"date":32,"location":112,"album":26,"width":95,"height":96},"hundred-day-feast-2026-09-06-1","https:\u002F\u002Fmp-174d4239-a43e-4e0a-9fdc-92547241a10b.cdn.bspapp.com\u002Fkeepsake\u002Falbums\u002Fhundred-day-feast-2026-09-06\u002F001.jpg","百日宴 - 照片 001",{"zh":110,"en":110},"百日宴 · 001",{"zh":30,"en":30},{"zh":28,"en":28},{"id":114,"src":115,"alt":116,"title":117,"caption":119,"date":32,"location":120,"album":35,"width":121,"height":122},"hundred-day-photos-2026-09-06-1","https:\u002F\u002Fmp-174d4239-a43e-4e0a-9fdc-92547241a10b.cdn.bspapp.com\u002Fkeepsake\u002Falbums\u002Fhundred-day-photos-2026-09-06\u002F001.jpg","百日照 - 照片 001",{"zh":118,"en":118},"百日照 · 001",{"zh":39,"en":39},{"zh":37,"en":37},6000,4000,{"id":124,"src":125,"alt":126,"title":127,"caption":129,"date":48,"location":130,"album":42,"width":131,"height":132},"xian-trip-2025-01-11-1","https:\u002F\u002Fmp-174d4239-a43e-4e0a-9fdc-92547241a10b.cdn.bspapp.com\u002Fkeepsake\u002Falbums\u002Fxian-trip-2025-01-11\u002F001.png","西安行 - 照片 001",{"zh":128,"en":128},"西安行 · 001",{"zh":46,"en":46},{"zh":44,"en":44},1179,2556,{"id":134,"src":135,"alt":136,"title":137,"caption":139,"date":57,"location":140,"album":51,"width":141,"height":142},"hong-kong-macau-2024-02-10-1","https:\u002F\u002Fmp-174d4239-a43e-4e0a-9fdc-92547241a10b.cdn.bspapp.com\u002Fkeepsake\u002Falbums\u002Fhong-kong-macau-2024-02-10\u002F001.jpg","香港澳门行 - 照片 001",{"zh":138,"en":138},"香港澳门行 · 001",{"zh":55,"en":55},{"zh":53,"en":53},2880,2160,{"id":144,"src":145,"alt":146,"title":147,"caption":149,"date":66,"location":150,"album":60,"width":151,"height":152},"wedding-portraits-2023-11-26-1","https:\u002F\u002Fmp-174d4239-a43e-4e0a-9fdc-92547241a10b.cdn.bspapp.com\u002Fkeepsake\u002Falbums\u002Fwedding-portraits-2023-11-26\u002F001.jpg","结婚照 - 照片 001",{"zh":148,"en":148},"结婚照 · 001",{"zh":64,"en":64},{"zh":62,"en":62},5304,7952,{"id":154,"src":155,"alt":156,"title":157,"caption":159,"date":75,"location":160,"album":69,"width":151,"height":152},"wedding-photos-2023-10-01-1","https:\u002F\u002Fmp-174d4239-a43e-4e0a-9fdc-92547241a10b.cdn.bspapp.com\u002Fkeepsake\u002Falbums\u002Fwedding-photos-2023-10-01\u002F001.jpg","婚纱照 - 照片 001",{"zh":158,"en":158},"婚纱照 · 001",{"zh":73,"en":73},{"zh":71,"en":71},{"id":162,"src":163,"alt":164,"title":165,"caption":167,"date":84,"location":168,"album":78,"width":96,"height":96},"wedding-preparation-2023-09-30-1","https:\u002F\u002Fmp-174d4239-a43e-4e0a-9fdc-92547241a10b.cdn.bspapp.com\u002Fkeepsake\u002Falbums\u002Fwedding-preparation-2023-09-30\u002F001.jpg","婚礼筹备中 - 照片 001",{"zh":166,"en":166},"婚礼筹备中 · 001",{"zh":82,"en":82},{"zh":80,"en":80},[170],{"src":171,"filename":172,"width":173,"height":174},"https:\u002F\u002Fmp-174d4239-a43e-4e0a-9fdc-92547241a10b.cdn.bspapp.com\u002Fkeepsake\u002Fbanner\u002F202607180001.jpg","keepsake\u002Fbanner\u002F202607180001.jpg",2000,1329,[176,181,184],{"src":177,"filename":178,"width":179,"height":180},"https:\u002F\u002Fmp-174d4239-a43e-4e0a-9fdc-92547241a10b.cdn.bspapp.com\u002Fkeepsake\u002Fjourneys\u002Fcover-03.jpg","cover-03.jpg",1600,1000,{"src":182,"filename":183,"width":179,"height":180},"https:\u002F\u002Fmp-174d4239-a43e-4e0a-9fdc-92547241a10b.cdn.bspapp.com\u002Fcloudstorage\u002F025af65f-34cc-4a5c-9162-d277a3005e98.jpg","025af65f-34cc-4a5c-9162-d277a3005e98.jpg",{"src":185,"filename":186,"width":179,"height":180},"https:\u002F\u002Fmp-174d4239-a43e-4e0a-9fdc-92547241a10b.cdn.bspapp.com\u002Fcloudstorage\u002Fa2020fb5-9479-497d-9770-d4cc3362c2c8.jpg","a2020fb5-9479-497d-9770-d4cc3362c2c8.jpg",[188],{"src":189,"filename":190,"width":179,"height":180},"https:\u002F\u002Fmp-174d4239-a43e-4e0a-9fdc-92547241a10b.cdn.bspapp.com\u002Fkeepsake\u002Fstories\u002F2026-10-21.jpg","2026-10-21.jpg",[],[193,208,221],{"id":194,"bvid":195,"title":196,"description":199,"location":202,"date":205,"duration":206,"featured":207},"wedding-day","BV1BJnr6AEs8",{"zh":197,"en":198},"婚礼那天","Wedding Day",{"zh":200,"en":201},"婚礼当天，留下属于我们的珍贵片段。","The moments we kept from our wedding day.",{"zh":203,"en":204},"婚礼记录","Wedding memories","2026-10-22","34:53",false,{"id":209,"bvid":210,"title":211,"description":213,"location":216,"date":32,"duration":219,"featured":220},"hundred-day-photo","BV1CFnq68Esj",{"zh":37,"en":212},"100-Day Photo Session",{"zh":214,"en":215},"记录宝宝百日照的拍摄花絮。","Behind the scenes of our baby’s 100-day photo session.",{"zh":217,"en":218},"家庭日常","Family moments","03:17",true,{"id":222,"bvid":223,"title":224,"description":227,"location":230,"date":32,"duration":233,"featured":220},"hundred-day-record","BV1zTnq6RE2v",{"zh":225,"en":226},"百日记录","100-Day Memories",{"zh":228,"en":229},"属于宝宝百日的家庭成长记录。","A family keepsake from our baby’s first 100 days.",{"zh":231,"en":232},"成长记录","Growing up","03:50",[235],{"path":236,"title":237,"description":238,"date":239,"category":240,"cover":189,"readingTime":241},"\u002Fstories\u002Fproject-documentation","项目说明：把一家人的记忆放进同一个地方","Keepsake 的设计目标、功能结构、媒体方案、技术选型与当前边界。","2026-10-21","项目文档",8,[243,607],{"id":244,"title":237,"body":245,"category":240,"date":239,"description":238,"extension":601,"location":602,"meta":603,"navigation":220,"path":236,"readingTime":241,"seo":604,"stem":605,"__hash__":606},"stories\u002Fstories\u002Fproject-documentation.md",{"type":246,"value":247,"toc":576},"minimark",[248,252,256,259,262,281,284,288,291,294,297,309,312,315,318,321,324,327,341,345,348,351,354,357,374,377,391,394,397,400,403,406,514,517,520,523,526,529,532,535,538,541,544,564,567,570,573],[249,250,251],"p",{},"Keepsake 是一个面向一家人的家庭记忆网站。它不追求成为内容平台，也不试图把所有生活都变成公开作品。它更像一本可以随时翻开的家庭档案，把照片、旅行影像、文字和那些当时觉得普通、以后却可能很珍贵的日子放在一起。",[253,254,255],"h2",{"id":255},"为什么做这个项目",[249,257,258],{},"社交平台会让内容快速滚动，照片、视频和文字也容易散落在不同应用里。几年以后，我们可能还记得去过哪里，却很难再找到一个地方，完整地看见那一天的光线、说过的话和当时的情绪。",[249,260,261],{},"Keepsake 想解决的问题很具体：",[263,264,265,269,272,275,278],"ul",{},[266,267,268],"li",{},"把家庭照片按旅行和时间整理起来",[266,270,271],{},"用视频保留照片无法表达的现场感",[266,273,274],{},"用文章记录照片背后的故事",[266,276,277],{},"让家庭成员在手机和电脑上都能浏览",[266,279,280],{},"保持视觉克制，让内容本身成为重点",[253,282,283],{"id":283},"当前已经具备的功能",[285,286,287],"h3",{"id":287},"家庭首页",[249,289,290],{},"首页使用横幅照片建立第一印象，并展示家庭统计、精选相册、旅行影像和最新文章。相册统计直接来自媒体库，内容增加后不需要手动改数字。",[285,292,293],{"id":293},"相册浏览",[249,295,296],{},"相册页面采用两级浏览方式：",[298,299,300,303,306],"ol",{},[266,301,302],{},"“全部”只显示每本相册的第一张封面",[266,304,305],{},"点击相册后，显示该相册的全部照片",[266,307,308],{},"照片支持灯箱预览和浏览器本地收藏",[249,310,311],{},"相册标题和上传日期直接来自媒体文件夹名称，不需要逐张维护标题。",[285,313,314],{"id":314},"旅行影像",[249,316,317],{},"旅行视频保存在 Bilibili，网站通过官方播放器嵌入。项目不保存视频文件，只维护视频编号、标题和文字说明。",[285,319,320],{"id":320},"文字记录",[249,322,323],{},"文章使用 Markdown 管理，适合保存旅行手记、成长记录和项目文档。文章页面采用偏阅读的排版，强调长文本的可读性。",[285,325,326],{"id":326},"主题与语言",[263,328,329,332,335,338],{},[266,330,331],{},"支持亮色与暗色主题",[266,333,334],{},"记住浏览器中的主题偏好",[266,336,337],{},"支持中文和英文界面切换",[266,339,340],{},"相册和视频标题支持双语字段",[285,342,344],{"id":343},"pwa","PWA",[249,346,347],{},"网站支持安装到桌面，并缓存必要的静态资源。需要注意，私人照片不建议在共用电脑上长期保留离线副本。",[253,349,350],{"id":350},"当前的媒体方案",[249,352,353],{},"照片不使用传统的“先复制到网站项目，再一起提交”方式，而是由本地媒体服务实时读取照片目录。",[249,355,356],{},"浏览照片时，流程大致是：",[298,358,359,362,365,368,371],{},[266,360,361],{},"页面请求媒体清单",[266,363,364],{},"服务端扫描相册目录",[266,366,367],{},"返回相册、照片数量、日期和图片地址",[266,369,370],{},"浏览器请求具体照片",[266,372,373],{},"服务端读取原图并按需转换为 WebP",[249,375,376],{},"这种方案有几个优点：",[263,378,379,382,385,388],{},[266,380,381],{},"原图不会进入 Git 仓库",[266,383,384],{},"项目体积更小",[266,386,387],{},"新增相册后不需要重新登记大量图片信息",[266,389,390],{},"图片在输出时统一压缩和限制尺寸",[249,392,393],{},"同时也带来一个明确限制：网站必须运行在能够访问本地照片目录的电脑上。普通静态托管平台无法直接访问家庭电脑中的照片，因此不能把当前版本当作纯静态站发布。",[253,395,396],{"id":396},"相册组织原则",[249,398,399],{},"相册使用“相册标题 + 上传日期”的文件夹名称，照片按数字顺序命名。特殊图片使用固定用途目录，例如首页横幅、视频封面和文章封面。",[249,401,402],{},"这套规则让日常维护保持简单：新增一次旅行时，只需要新建相册文件夹、整理照片顺序，不需要同时修改页面代码和图片配置。",[253,404,405],{"id":405},"技术选型",[407,408,409,422],"table",{},[410,411,412],"thead",{},[413,414,415,419],"tr",{},[416,417,418],"th",{},"技术",[416,420,421],{},"作用",[423,424,425,434,442,450,458,466,474,482,490,498,506],"tbody",{},[413,426,427,431],{},[428,429,430],"td",{},"Nuxt 4",[428,432,433],{},"路由、服务端接口、构建与页面渲染",[413,435,436,439],{},[428,437,438],{},"Vue 3",[428,440,441],{},"页面组件和交互状态",[413,443,444,447],{},[428,445,446],{},"TypeScript",[428,448,449],{},"数据结构与错误检查",[413,451,452,455],{},[428,453,454],{},"Tailwind CSS 4",[428,456,457],{},"响应式布局和视觉样式",[413,459,460,463],{},[428,461,462],{},"Nuxt Content",[428,464,465],{},"Markdown 文章解析",[413,467,468,471],{},[428,469,470],{},"Nuxt i18n",[428,472,473],{},"中英文界面",[413,475,476,479],{},[428,477,478],{},"Pinia",[428,480,481],{},"相册选择、主题和本地收藏",[413,483,484,487],{},[428,485,486],{},"Sharp",[428,488,489],{},"运行时图片读取和 WebP 转换",[413,491,492,495],{},[428,493,494],{},"Reka UI",[428,496,497],{},"无障碍菜单、灯箱和弹窗",[413,499,500,503],{},[428,501,502],{},"Motion for Vue",[428,504,505],{},"首页进场动画",[413,507,508,511],{},[428,509,510],{},"Vite PWA",[428,512,513],{},"安装与离线资源缓存",[253,515,516],{"id":516},"设计原则",[285,518,519],{"id":519},"内容优先",[249,521,522],{},"视觉元素服务于照片和文字，不使用过多装饰干扰阅读。卡片、标题和留白都围绕浏览节奏设计。",[285,524,525],{"id":525},"数据与视图分离",[249,527,528],{},"页面组件只负责展示。相册信息和媒体地址由接口返回，旅行视频的文字索引和文章正文保持独立。",[285,530,531],{"id":531},"移动端优先被认真对待",[249,533,534],{},"导航、标题字号、相册网格和灯箱都针对窄屏重新设计，而不是简单缩小桌面页面。",[285,536,537],{"id":537},"私人内容必须可控",[249,539,540],{},"家庭照片不应依赖“别人猜不到网址”来保护。正式公开部署前，需要明确访问控制、备份和照片权限策略。",[253,542,543],{"id":543},"当前边界",[263,545,546,549,552,555,558,561],{},[266,547,548],{},"没有后台管理界面",[266,550,551],{},"没有用户登录和权限系统",[266,553,554],{},"没有数据库",[266,556,557],{},"照片依赖家庭电脑在线",[266,559,560],{},"文章和视频说明仍由代码维护",[266,562,563],{},"相册收藏只保存在当前浏览器",[249,565,566],{},"这些边界不是缺陷，而是当前阶段的选择。项目优先验证视觉、阅读体验和媒体浏览方式，再决定是否进入数据化阶段。",[253,568,569],{"id":569},"下一步",[249,571,572],{},"当前最值得升级的不是页面数量，而是数据管理方式。建议将相册、照片、文章、视频和媒体资源元数据迁移到 MySQL，并把图片文件放到对象存储或家庭 NAS。这样可以获得更稳定的远程访问、权限管理、全文检索和后台编辑能力。",[249,574,575],{},"具体演进方案见同系列的《项目建议：用 MySQL 管好照片、文章和视频》。",{"title":577,"searchDepth":578,"depth":578,"links":579},"",2,[580,581,590,591,592,593,599,600],{"id":255,"depth":578,"text":255},{"id":283,"depth":578,"text":283,"children":582},[583,585,586,587,588,589],{"id":287,"depth":584,"text":287},3,{"id":293,"depth":584,"text":293},{"id":314,"depth":584,"text":314},{"id":320,"depth":584,"text":320},{"id":326,"depth":584,"text":326},{"id":343,"depth":584,"text":344},{"id":350,"depth":578,"text":350},{"id":396,"depth":578,"text":396},{"id":405,"depth":578,"text":405},{"id":516,"depth":578,"text":516,"children":594},[595,596,597,598],{"id":519,"depth":584,"text":519},{"id":525,"depth":584,"text":525},{"id":531,"depth":584,"text":531},{"id":537,"depth":584,"text":537},{"id":543,"depth":578,"text":543},{"id":569,"depth":578,"text":569},"md",null,{},{"title":237,"description":238},"stories\u002Fproject-documentation","_eZlmZ3WciQrwUDkA-1DyGuhP27OkHjar6b1Cm0B33M",{"id":608,"title":609,"body":610,"category":1048,"date":1049,"description":1050,"extension":601,"location":602,"meta":1051,"navigation":220,"path":1052,"readingTime":1053,"seo":1054,"stem":1055,"__hash__":1056},"stories\u002Fstories\u002Fproject-recommendations.md","项目建议：用 MySQL 管好照片、文章和视频",{"type":246,"value":611,"toc":1024},[612,615,618,635,638,641,645,648,651,661,664,670,673,676,679,682,717,720,723,763,768,771,774,798,801,804,828,831,834,837,859,863,866,877,880,883,889,892,895,918,921,941,944,947,967,970,973,977,980,984,987,991,994,998,1001,1004,1007,1021],[249,613,614],{},"Keepsake 目前采用轻量方案：照片留在本地，服务端在运行时扫描目录并返回媒体信息，文字内容由代码和 Markdown 维护。",[249,616,617],{},"这套方案适合验证产品，但当相册数量、文章数量和访问设备不断增长时，会逐渐遇到新问题：",[263,619,620,623,626,629,632],{},[266,621,622],{},"文件夹名称承担了过多业务含义",[266,624,625],{},"查询和筛选依赖目录扫描",[266,627,628],{},"文章、相册、视频之间无法建立正式关系",[266,630,631],{},"访问权限难以细化到相册或家庭成员",[266,633,634],{},"后台管理、搜索和操作日志缺少数据基础",[249,636,637],{},"因此，建议在下一阶段引入 MySQL。重点不是“把文件塞进数据库”，而是把结构化的信息和真实的媒体文件分开管理。",[253,639,640],{"id":640},"核心原则",[285,642,644],{"id":643},"图片文件不直接存入-mysql","图片文件不直接存入 MySQL",[249,646,647],{},"不要把大图保存成数据库中的二进制大字段。数据库更适合保存标题、日期、相册关系、对象存储路径、尺寸、权限和排序信息。",[249,649,650],{},"推荐结构：",[652,653,658],"pre",{"className":654,"code":656,"language":657,"meta":577},[655],"language-text","MySQL：照片元数据 + 业务关系\n对象存储 \u002F NAS：照片文件与缩略图\n应用服务：鉴权、查询、上传、转换和签名访问\n","text",[659,660,656],"code",{"__ignoreMap":577},[249,662,663],{},"数据库中的媒体记录只保存对象键，例如：",[652,665,668],{"className":666,"code":667,"language":657,"meta":577},[655],"albums\u002F2026-hong-kong\u002F001.webp\n",[659,669,667],{"__ignoreMap":577},[249,671,672],{},"以后从家庭 NAS 迁移到 uniCloud、腾讯云 COS 或阿里云 OSS，不需要修改相册业务数据。",[253,674,675],{"id":675},"建议的数据表",[285,677,678],{"id":678},"albums",[249,680,681],{},"保存相册本身：",[263,683,684,687,690,693,696,699,702,705,708,711,714],{},[266,685,686],{},"id",[266,688,689],{},"title",[266,691,692],{},"slug",[266,694,695],{},"taken_at",[266,697,698],{},"published_at",[266,700,701],{},"cover_photo_id",[266,703,704],{},"description",[266,706,707],{},"visibility",[266,709,710],{},"sort_order",[266,712,713],{},"created_at",[266,715,716],{},"updated_at",[285,718,719],{"id":719},"photos",[249,721,722],{},"保存每张照片的信息：",[263,724,725,727,730,733,736,739,742,745,748,751,754,756,758,761],{},[266,726,686],{},[266,728,729],{},"album_id",[266,731,732],{},"storage_key",[266,734,735],{},"thumbnail_key",[266,737,738],{},"filename",[266,740,741],{},"width",[266,743,744],{},"height",[266,746,747],{},"mime_type",[266,749,750],{},"file_size",[266,752,753],{},"caption",[266,755,695],{},[266,757,710],{},[266,759,760],{},"checksum",[266,762,713],{},[249,764,765,767],{},[659,766,760],{}," 可以帮助发现重复文件，也方便迁移和备份校验。",[285,769,770],{"id":770},"media_assets",[249,772,773],{},"如果视频封面、首页横幅和文章封面也需要统一管理，可以使用通用媒体表：",[263,775,776,778,781,784,787,789,791,793,796],{},[266,777,686],{},[266,779,780],{},"owner_type",[266,782,783],{},"owner_id",[266,785,786],{},"usage",[266,788,732],{},[266,790,741],{},[266,792,744],{},[266,794,795],{},"alt_text",[266,797,710],{},[285,799,800],{"id":800},"articles",[249,802,803],{},"文章可以从 Markdown 文件迁移到数据库：",[263,805,806,808,810,812,815,818,821,824,826],{},[266,807,686],{},[266,809,692],{},[266,811,689],{},[266,813,814],{},"summary",[266,816,817],{},"content_markdown",[266,819,820],{},"cover_asset_id",[266,822,823],{},"status",[266,825,698],{},[266,827,716],{},[249,829,830],{},"如果仍然希望保留版本管理，可以继续把正文保存为 Markdown 文件，只把索引和分类放入 MySQL。",[285,832,833],{"id":833},"videos",[249,835,836],{},"旅行视频只需保存索引，不需要保存视频文件：",[263,838,839,841,844,847,849,851,853,855,857],{},[266,840,686],{},[266,842,843],{},"provider",[266,845,846],{},"provider_video_id",[266,848,689],{},[266,850,704],{},[266,852,820],{},[266,854,698],{},[266,856,710],{},[266,858,707],{},[285,860,862],{"id":861},"users-与-album_access","users 与 album_access",[249,864,865],{},"如果只允许家庭成员访问，建议至少包含：",[263,867,868,871,874],{},[266,869,870],{},"users：账号、邮箱、状态",[266,872,873],{},"roles：管理员、家庭成员、访客",[266,875,876],{},"album_access：用户与相册的访问关系",[249,878,879],{},"权限应服务端判断，不能依赖前端隐藏按钮。",[253,881,882],{"id":882},"推荐的服务接口",[652,884,887],{"className":885,"code":886,"language":657,"meta":577},[655],"GET    \u002Fapi\u002Falbums\nGET    \u002Fapi\u002Falbums\u002F:id\nGET    \u002Fapi\u002Falbums\u002F:id\u002Fphotos\nGET    \u002Fapi\u002Farticles\nGET    \u002Fapi\u002Farticles\u002F:slug\nGET    \u002Fapi\u002Fvideos\nPOST   \u002Fapi\u002Fadmin\u002Falbums\nPOST   \u002Fapi\u002Fadmin\u002Fphotos\nPATCH  \u002Fapi\u002Fadmin\u002Fphotos\u002F:id\nDELETE \u002Fapi\u002Fadmin\u002Fphotos\u002F:id\n",[659,888,886],{"__ignoreMap":577},[249,890,891],{},"媒体访问建议通过短时效签名 URL，或由服务端完成权限校验后代理返回。不要把数据库账号、对象存储密钥或永久私有地址暴露给浏览器。",[253,893,894],{"id":894},"推荐的上传流程",[298,896,897,900,903,906,909,912,915],{},[266,898,899],{},"家庭管理员上传原图。",[266,901,902],{},"服务端计算校验值，避免重复文件。",[266,904,905],{},"自动读取 EXIF 拍摄时间并校正方向。",[266,907,908],{},"生成网页版 WebP 和缩略图。",[266,910,911],{},"原图与网页图分别写入存储。",[266,913,914],{},"MySQL 保存相册关系、尺寸、顺序和对象键。",[266,916,917],{},"页面只请求业务接口和受控媒体地址。",[253,919,920],{"id":920},"数据库带来的收益",[263,922,923,926,929,932,935,938],{},[266,924,925],{},"相册、照片、文章和视频可以通过外键稳定关联",[266,927,928],{},"支持按日期、地点、标签和成员筛选",[266,930,931],{},"支持真正的分页，而不是一次扫描全部目录",[266,933,934],{},"支持后台编辑、软删除和操作记录",[266,936,937],{},"支持多设备和多用户同步",[266,939,940],{},"更容易接入全文搜索、备份和监控",[253,942,943],{"id":943},"需要接受的成本",[249,945,946],{},"MySQL 不是零成本升级。需要承担：",[263,948,949,952,955,958,961,964],{},[266,950,951],{},"数据库服务运行和维护",[266,953,954],{},"账号、权限和备份策略",[266,956,957],{},"数据迁移与字段升级",[266,959,960],{},"API 安全、限流和日志",[266,962,963],{},"图片存储和带宽费用",[266,965,966],{},"家庭服务器或云服务的持续在线要求",[249,968,969],{},"如果仍然只在一台电脑上浏览，当前目录扫描方案已经足够。只有当“远程稳定访问、统一管理、多用户、后台编辑”成为真实需求时，MySQL 才值得引入。",[253,971,972],{"id":972},"分阶段实施方案",[285,974,976],{"id":975},"第一阶段迁移元数据","第一阶段：迁移元数据",[249,978,979],{},"先只把相册、照片、文章和视频的结构化信息迁移到 MySQL，图片文件仍然放在原有目录或 NAS。",[285,981,983],{"id":982},"第二阶段统一媒体服务","第二阶段：统一媒体服务",[249,985,986],{},"将图片转换、权限校验、缩略图和签名访问集中到一个媒体服务，页面不再依赖物理目录。",[285,988,990],{"id":989},"第三阶段后台管理","第三阶段：后台管理",[249,992,993],{},"增加管理员登录、上传、排序、封面选择、文章编辑和软删除。",[285,995,997],{"id":996},"第四阶段云端或混合存储","第四阶段：云端或混合存储",[249,999,1000],{},"根据访问量和隐私要求，将网页图片同步到对象存储。原图可以继续保留在家庭 NAS，只把适合浏览的 WebP 放上云。",[253,1002,1003],{"id":1003},"最终建议",[249,1005,1006],{},"推荐采用“MySQL + 对象存储\u002FNAS + 独立媒体 API”的混合结构：",[263,1008,1009,1012,1015,1018],{},[266,1010,1011],{},"MySQL 负责结构和关系",[266,1013,1014],{},"NAS 或对象存储负责大文件",[266,1016,1017],{},"应用服务负责权限与媒体转换",[266,1019,1020],{},"Vue 前端只负责浏览和管理交互",[249,1022,1023],{},"这样既能保留家庭照片的私密性，也能获得稳定的远程访问和长期可维护性。",{"title":577,"searchDepth":578,"depth":578,"links":1025},[1026,1029,1037,1038,1039,1040,1041,1047],{"id":640,"depth":578,"text":640,"children":1027},[1028],{"id":643,"depth":584,"text":644},{"id":675,"depth":578,"text":675,"children":1030},[1031,1032,1033,1034,1035,1036],{"id":678,"depth":584,"text":678},{"id":719,"depth":584,"text":719},{"id":770,"depth":584,"text":770},{"id":800,"depth":584,"text":800},{"id":833,"depth":584,"text":833},{"id":861,"depth":584,"text":862},{"id":882,"depth":578,"text":882},{"id":894,"depth":578,"text":894},{"id":920,"depth":578,"text":920},{"id":943,"depth":578,"text":943},{"id":972,"depth":578,"text":972,"children":1042},[1043,1044,1045,1046],{"id":975,"depth":584,"text":976},{"id":982,"depth":584,"text":983},{"id":989,"depth":584,"text":990},{"id":996,"depth":584,"text":997},{"id":1003,"depth":578,"text":1003},"项目建议","2026-10-20","从本地媒体服务升级到数据库驱动的家庭内容系统，包含数据模型、接口、安全与分阶段方案。",{},"\u002Fstories\u002Fproject-recommendations",10,{"title":609,"description":1050},"stories\u002Fproject-recommendations","LQXApwy5JrK88LUJuXd4KmKuXZgJRDqcoIx9H71DsTQ"]