[{"data":1,"prerenderedAt":874},["ShallowReactive",2],{"rainink-post-cn-server-deploy-pitfalls":3,"rainink-content-index":687},{"id":4,"title":5,"body":6,"category":669,"cover":670,"date":671,"description":672,"draft":673,"extension":674,"featured":673,"lang":670,"meta":675,"navigation":676,"order":670,"path":677,"period":670,"pinned":673,"repo":670,"seo":678,"slug":670,"stack":670,"stem":679,"tags":680,"thumb":670,"toc":676,"updated":670,"__hash__":686},"content\u002Fposts\u002Fcn-server-deploy-pitfalls.md","国内服务器部署的十个坑：从镜像源到 certbot",{"type":7,"value":8,"toc":654},"minimark",[9,16,21,29,32,73,87,91,98,122,126,141,164,168,171,179,182,261,275,279,301,304,327,337,344,347,358,365,376,385,403,407,410,425,440,444,447,474,481,485,491,514,517,582,590,594,600,618,621,625,628,634,637,647,650],[10,11,12],"blockquote",{},[13,14,15],"p",{},"这篇是上一份部署路径的\"另一半\"：把过程中真实卡住的地方逐条记下来，方便下次少走一遍。",[17,18,20],"h2",{"id":19},"_1-nvm-装不上github-拉不动","1. nvm 装不上：GitHub 拉不动",[13,22,23,24,28],{},"现象是 ",[25,26,27],"code",{},"curl -o- https:\u002F\u002Fraw.githubusercontent.com\u002F...\u002Finstall.sh | bash"," 一直挂着，最后超时。",[13,30,31],{},"解法是换镜像源，两条环境变量就够：",[33,34,39],"pre",{"className":35,"code":36,"language":37,"meta":38,"style":38},"language-bash shiki shiki-themes github-light github-dark","export NVM_SOURCE=https:\u002F\u002Fgitee.com\u002Fmirrors\u002Fnvm.git\nexport NODEJS_ORG_MIRROR=https:\u002F\u002Fnpmmirror.com\u002Fmirrors\u002Fnode\u002F\n","bash","",[25,40,41,60],{"__ignoreMap":38},[42,43,46,50,54,57],"span",{"class":44,"line":45},"line",1,[42,47,49],{"class":48},"szBVR","export",[42,51,53],{"class":52},"sVt8B"," NVM_SOURCE",[42,55,56],{"class":48},"=",[42,58,59],{"class":52},"https:\u002F\u002Fgitee.com\u002Fmirrors\u002Fnvm.git\n",[42,61,63,65,68,70],{"class":44,"line":62},2,[42,64,49],{"class":48},[42,66,67],{"class":52}," NODEJS_ORG_MIRROR",[42,69,56],{"class":48},[42,71,72],{"class":52},"https:\u002F\u002Fnpmmirror.com\u002Fmirrors\u002Fnode\u002F\n",[13,74,75,78,79,82,83,86],{},[25,76,77],{},"NVM_SOURCE"," 管的是 nvm 自己，",[25,80,81],{},"NODEJS_ORG_MIRROR"," 管的是后续 ",[25,84,85],{},"nvm install"," 下载 Node 二进制。只改前者，装完 nvm 依然会在下载 Node 时卡住。",[17,88,90],{"id":89},"_2-npm-源没跟着换","2. npm 源没跟着换",[13,92,93,94,97],{},"nvm 换完源，",[25,95,96],{},"npm install"," 还是慢。补一条持久化配置：",[33,99,101],{"className":35,"code":100,"language":37,"meta":38,"style":38},"npm config set registry https:\u002F\u002Fregistry.npmmirror.com\n",[25,102,103],{"__ignoreMap":38},[42,104,105,109,113,116,119],{"class":44,"line":45},[42,106,108],{"class":107},"sScJk","npm",[42,110,112],{"class":111},"sZZnC"," config",[42,114,115],{"class":111}," set",[42,117,118],{"class":111}," registry",[42,120,121],{"class":111}," https:\u002F\u002Fregistry.npmmirror.com\n",[17,123,125],{"id":124},"_3-权限ubuntu-用户读不了-root","3. 权限：ubuntu 用户读不了 \u002Froot",[13,127,128,129,132,133,136,137,140],{},"想让 Nginx 指向某个目录，",[25,130,131],{},"ls"," 报 ",[25,134,135],{},"Permission denied","——文件在 ",[25,138,139],{},"\u002Froot"," 下面。",[13,142,143,144,148,149,152,153,156,157,160,161,163],{},"原则很直接：",[145,146,147],"strong",{},"Web 根目录永远不要放在任何用户的家目录里","。统一放 ",[25,150,151],{},"\u002Fvar\u002Fwww\u002F\u003C站点名>","，属主给 ",[25,154,155],{},"www-data","，权限 ",[25,158,159],{},"755","。",[25,162,139],{}," 是 700，Nginx 的 worker 进程进不去。",[17,165,167],{"id":166},"_4-typeorm-部署到空库直接起不来","4. TypeORM 部署到空库直接起不来",[13,169,170],{},"三个报错连着来：",[33,172,177],{"className":173,"code":175,"language":176},[174],"language-text","Unknown argument: src\u002Fdata-source.ts\nGiven data source file must contain only one export\nEntity metadata for Menu#roleMenus was not found\n","text",[25,178,175],{"__ignoreMap":38},[13,180,181],{},"对应三个原因：",[183,184,185,201],"table",{},[186,187,188],"thead",{},[189,190,191,195,198],"tr",{},[192,193,194],"th",{},"报错",[192,196,197],{},"原因",[192,199,200],{},"处理",[202,203,204,226,248],"tbody",{},[189,205,206,212,223],{},[207,208,209],"td",{},[25,210,211],{},"Unknown argument",[207,213,214,215,218,219,222],{},"命令后多拼了 ",[25,216,217],{},"-d src\u002Fdata-source.ts","，",[25,220,221],{},"package.json"," 的脚本里已经带了",[207,224,225],{},"删掉多余参数",[189,227,228,233,243],{},[207,229,230],{},[25,231,232],{},"must contain only one export",[207,234,235,236,239,240],{},"文件里同时有 ",[25,237,238],{},"export const"," 和 ",[25,241,242],{},"export default",[207,244,245,246],{},"删掉 ",[25,247,242],{},[189,249,250,255,258],{},[207,251,252],{},[25,253,254],{},"Entity metadata ... not found",[207,256,257],{},"只手写注册了部分实体",[207,259,260],{},"改成 glob 扫描模块目录",[13,262,263,264,267,268,271,272,160],{},"另外，项目里没有迁移文件却设了 ",[25,265,266],{},"DB_SYNC=false","，空库永远建不出表。临时解法是先 ",[25,269,270],{},"DB_SYNC=true"," 跑通，再补迁移——不要在空库上死等 ",[25,273,274],{},"migration:run",[17,276,278],{"id":277},"_5-curl-请求本机命中了别的站点","5. curl 请求本机，命中了别的站点",[13,280,281,284,285,288,289,292,293,296,297,300],{},[25,282,283],{},"curl 127.0.0.1"," 返回的不是预期站点的内容。原因很简单：Nginx 里 ",[25,286,287],{},"server_name"," 是 ",[25,290,291],{},"admin.xxx.com","，请求没有 ",[25,294,295],{},"Host"," 头，Nginx 就交给 ",[25,298,299],{},"default_server"," 处理了。",[13,302,303],{},"验证时手动带 Host：",[33,305,307],{"className":35,"code":306,"language":37,"meta":38,"style":38},"curl -sS -H 'Host: api.rainink.net' http:\u002F\u002F127.0.0.1\u002Fapi\u002Fhealth\n",[25,308,309],{"__ignoreMap":38},[42,310,311,314,318,321,324],{"class":44,"line":45},[42,312,313],{"class":107},"curl",[42,315,317],{"class":316},"sj4cs"," -sS",[42,319,320],{"class":316}," -H",[42,322,323],{"class":111}," 'Host: api.rainink.net'",[42,325,326],{"class":111}," http:\u002F\u002F127.0.0.1\u002Fapi\u002Fhealth\n",[13,328,329,330,333,334,160],{},"这条坑和 ",[25,331,332],{},"--resolve"," 是同一类问题的两面：",[145,335,336],{},"域名相关的配置，必须带域名去验证",[17,338,340,341],{"id":339},"_6-powershell-吞掉远端命令里的-date","6. PowerShell 吞掉远端命令里的 ",[25,342,343],{},"$(date)",[13,345,346],{},"想给配置加时间戳备份：",[33,348,352],{"className":349,"code":350,"language":351,"meta":38,"style":38},"language-powershell shiki shiki-themes github-light github-dark","ssh ubuntu@host \"sudo cp x.conf x.conf.bak.$(date +%Y%m%d%H%M%S)\"\n","powershell",[25,353,354],{"__ignoreMap":38},[42,355,356],{"class":44,"line":45},[42,357,350],{},[13,359,360,361,364],{},"结果本地 PowerShell 先执行了 ",[25,362,363],{},"$(date ...)","，报\"无法将值 +%Y%m%d%H%M%S 转换为 DateTime\"。",[13,366,367,368,371,372,375],{},"原因：双引号里的内容在本地就被展开了。远端命令必须用",[145,369,370],{},"单引号","包裹，让 ",[25,373,374],{},"$"," 原样传过去：",[33,377,379],{"className":349,"code":378,"language":351,"meta":38,"style":38},"ssh ubuntu@host 'sudo cp x.conf x.conf.bak.$(date +%Y%m%d%H%M%S)'\n",[25,380,381],{"__ignoreMap":38},[42,382,383],{"class":44,"line":45},[42,384,378],{},[13,386,387,388,391,392,395,396,398,399,402],{},"反过来的坑也存在：",[25,389,390],{},"$host","、",[25,393,394],{},"$uri"," 这类 Nginx 变量如果写在双引号里，会被 PowerShell 当场吃掉。所以凡是内容里带 ",[25,397,374],{}," 的，一律改成本地写文件 + ",[25,400,401],{},"scp"," 上传，比在命令行里跟引号搏斗可靠得多。",[17,404,406],{"id":405},"_7-scp-上传配置再-mv比-heredoc-安全","7. scp 上传配置再 mv，比 heredoc 安全",[13,408,409],{},"带引号的 Nginx 配置通过 SSH 直接写，极易被本地 shell 改写。稳定做法：",[33,411,413],{"className":349,"code":412,"language":351,"meta":38,"style":38},"scp -i $pem .\\temp\\rainink.conf ubuntu@host:\u002Ftmp\u002Frainink_new.conf\nssh -i $pem ubuntu@host 'sudo cp \u002Fetc\u002Fnginx\u002Fsites-available\u002Frainink.conf \u002Fetc\u002Fnginx\u002Fsites-available\u002Frainink.conf.bak.$(date +%Y%m%d%H%M%S) && sudo cp \u002Ftmp\u002Frainink_new.conf \u002Fetc\u002Fnginx\u002Fsites-available\u002Frainink.conf && sudo nginx -t && sudo systemctl reload nginx'\n",[25,414,415,420],{"__ignoreMap":38},[42,416,417],{"class":44,"line":45},[42,418,419],{},"scp -i $pem .\\temp\\rainink.conf ubuntu@host:\u002Ftmp\u002Frainink_new.conf\n",[42,421,422],{"class":44,"line":62},[42,423,424],{},"ssh -i $pem ubuntu@host 'sudo cp \u002Fetc\u002Fnginx\u002Fsites-available\u002Frainink.conf \u002Fetc\u002Fnginx\u002Fsites-available\u002Frainink.conf.bak.$(date +%Y%m%d%H%M%S) && sudo cp \u002Ftmp\u002Frainink_new.conf \u002Fetc\u002Fnginx\u002Fsites-available\u002Frainink.conf && sudo nginx -t && sudo systemctl reload nginx'\n",[13,426,427,428,431,432,435,436,439],{},"先在 ",[25,429,430],{},"\u002Ftmp"," 落地、备份、替换、",[25,433,434],{},"nginx -t","、reload，五步串在一条 ",[25,437,438],{},"&&"," 链里，任何一步失败都不会把线上配置弄坏。",[17,441,443],{"id":442},"_8-未备案就别解析域名验收用-ip-端口","8. 未备案就别解析域名，验收用 IP + 端口",[13,445,446],{},"备案审核期的验收方案：",[448,449,450,462,465],"ul",{},[451,452,453,454,457,458,461],"li",{},"后端：",[25,455,456],{},"ufw allow 3000\u002Ftcp","，直接验 ",[25,459,460],{},"http:\u002F\u002F\u003CIP>:3000\u002Fapi\u002Fhealth","；",[451,463,464],{},"前端：临时开 8080 端口验页面；",[451,466,467,473],{},[145,468,469,470],{},"验完立即 ",[25,471,472],{},"ufw delete allow 3000\u002Ftcp","，别把临时口留着过夜。",[13,475,476,477,480],{},"或者更干净的做法：不开放任何额外端口，在服务器本机用 ",[25,478,479],{},"curl -H 'Host: ...'"," 验证，验完即走。",[17,482,484],{"id":483},"_9-certbot-多域名的坑","9. certbot 多域名的坑",[13,486,487,490],{},[25,488,489],{},"--redirect"," 会补一个 80 端口只做 301 的 server 块。站点多了以后常见两个问题：",[492,493,494,503],"ol",{},[451,495,496,497,499,500,461],{},"同一个 IP 上多个证书，80 端口块的 ",[25,498,287],{}," 写重复，Nginx 报 ",[25,501,502],{},"conflicting server name",[451,504,505,506,509,510,513],{},"申请时漏了 ",[25,507,508],{},"www","，导致 ",[25,511,512],{},"https:\u002F\u002Fwww.xxx"," 证书主体不匹配。",[13,515,516],{},"确认一下证书覆盖范围：",[33,518,520],{"className":35,"code":519,"language":37,"meta":38,"style":38},"echo | openssl s_client -connect 127.0.0.1:443 -servername xxx.net 2>\u002Fdev\u002Fnull \\\n  | openssl x509 -noout -subject -dates -ext subjectAltName\n",[25,521,522,557],{"__ignoreMap":38},[42,523,524,527,530,533,536,539,542,545,548,551,554],{"class":44,"line":45},[42,525,526],{"class":316},"echo",[42,528,529],{"class":48}," |",[42,531,532],{"class":107}," openssl",[42,534,535],{"class":111}," s_client",[42,537,538],{"class":316}," -connect",[42,540,541],{"class":111}," 127.0.0.1:443",[42,543,544],{"class":316}," -servername",[42,546,547],{"class":111}," xxx.net",[42,549,550],{"class":48}," 2>",[42,552,553],{"class":111},"\u002Fdev\u002Fnull",[42,555,556],{"class":316}," \\\n",[42,558,559,562,564,567,570,573,576,579],{"class":44,"line":62},[42,560,561],{"class":48},"  |",[42,563,532],{"class":107},[42,565,566],{"class":111}," x509",[42,568,569],{"class":316}," -noout",[42,571,572],{"class":316}," -subject",[42,574,575],{"class":316}," -dates",[42,577,578],{"class":316}," -ext",[42,580,581],{"class":111}," subjectAltName\n",[13,583,584,587,588,160],{},[25,585,586],{},"subject"," 与 SAN 里应该同时出现裸域和 ",[25,589,508],{},[17,591,593],{"id":592},"_10-续期演练没人做","10. 续期演练没人做",[13,595,596,599],{},[25,597,598],{},"certbot renew --dry-run"," 通过，不代表真的会续。要检查三件事：",[448,601,602,608,615],{},[451,603,604,607],{},[25,605,606],{},"systemctl list-timers | grep certbot"," 有定时器；",[451,609,610,611,614],{},"80 端口对 ACME 验证可达（安全组、",[25,612,613],{},"ufw"," 都要放行）；",[451,616,617],{},"续期后 Nginx 会自动 reload（certbot 的 deploy hook）。",[13,619,620],{},"这三条任意一条断了，三个月后就是一次线上事故。",[17,622,624],{"id":623},"附一套顺序化的自检清单","附：一套顺序化的自检清单",[13,626,627],{},"上线前后按这个顺序过一遍，能挡掉上面绝大多数问题：",[33,629,632],{"className":630,"code":631,"language":176,"meta":38},[174],"[ ] node\u002Fnpm 源已指向国内镜像\n[ ] 数据库\u002FRedis 只监听 127.0.0.1，安全组未放行 3306\u002F6379\n[ ] Web 根目录在 \u002Fvar\u002Fwww，属主 www-data\n[ ] 构建产物 rsync 带 --delete\n[ ] nginx -t 与 reload 用 && 串联\n[ ] 每个域名都能带 Host 在 127.0.0.1 上验通\n[ ] http → https 301 生效，www 与非 www 只有一个规范域\n[ ] 证书 SAN 包含全部域名\n[ ] certbot renew --dry-run 全绿，定时器存在\n[ ] 临时放行的端口已删除\n[ ] 上一版产物与配置备份都还在\n",[25,633,631],{"__ignoreMap":38},[17,635,636],{"id":636},"小结",[13,638,639,640,643,644,646],{},"这十个问题里，只有两个是\"知识型\"的（TypeORM 实体注册、certbot 多域名），其余八个都是",[145,641,642],{},"执行习惯","问题：引号怎么包、备份做不做、",[25,645,434],{}," 串不串、临时端口删不删。",[13,648,649],{},"习惯类问题不会因为经验增加而消失，只会因为清单存在而被跳过。所以最后那份自检清单，比任何一条具体的解决办法都更值得留着。",[651,652,653],"style",{},"html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .szBVR, html code.shiki .szBVR{--shiki-default:#D73A49;--shiki-dark:#F97583}html pre.shiki code .sVt8B, html code.shiki .sVt8B{--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .sScJk, html code.shiki .sScJk{--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .sZZnC, html code.shiki .sZZnC{--shiki-default:#032F62;--shiki-dark:#9ECBFF}html pre.shiki code .sj4cs, html code.shiki .sj4cs{--shiki-default:#005CC5;--shiki-dark:#79B8FF}",{"title":38,"searchDepth":62,"depth":62,"links":655},[656,657,658,659,660,661,663,664,665,666,667,668],{"id":19,"depth":62,"text":20},{"id":89,"depth":62,"text":90},{"id":124,"depth":62,"text":125},{"id":166,"depth":62,"text":167},{"id":277,"depth":62,"text":278},{"id":339,"depth":62,"text":662},"6. PowerShell 吞掉远端命令里的 $(date)",{"id":405,"depth":62,"text":406},{"id":442,"depth":62,"text":443},{"id":483,"depth":62,"text":484},{"id":592,"depth":62,"text":593},{"id":623,"depth":62,"text":624},{"id":636,"depth":62,"text":636},"tech",null,"2026-10-22","从镜像源到 certbot 的十个真实故障：nvm 拉不动、目录权限、空库迁移、Host 头命中错站、证书续期与备案期验收。",false,"md",{},true,"\u002Fposts\u002Fcn-server-deploy-pitfalls",{"title":5,"description":672},"posts\u002Fcn-server-deploy-pitfalls",[681,682,683,684,685],"部署","踩坑","Nginx","PowerShell","运维","ReEBjBVlO74Cgnsc-JL_1Aeo9lLTkefBGdYRMsR-1n0",{"all":688,"posts":809,"essays":834,"projects":835,"tags":842},[689,706,711,722,735,747,757,769,780,798],{"title":690,"description":691,"path":692,"slug":693,"category":669,"categoryLabel":694,"kind":695,"tags":696,"date":701,"updated":702,"minutes":703,"pinned":676,"draft":673,"order":704,"stack":705,"period":38,"repo":38,"thumb":38},"用 Nuxt 4 + Nuxt Content 搭一个纯静态个人站","站点骨架的取舍：内容目录怎么定、SSG 怎么预渲染、设计令牌怎么从原型抽成一套 CSS 变量，以及首屏主题闪烁的解法。","\u002Fposts\u002Fnuxt4-static-site","nuxt4-static-site","技术","post",[697,698,699,700],"Nuxt","Nuxt Content","SSG","前端工程化","2026-10-12","2026-10-18",5,0,[],{"title":5,"description":672,"path":677,"slug":707,"category":669,"categoryLabel":694,"kind":695,"tags":708,"date":671,"updated":38,"minutes":709,"pinned":673,"draft":673,"order":704,"stack":710,"period":38,"repo":38,"thumb":38},"cn-server-deploy-pitfalls",[681,682,683,684,685],6,[],{"title":712,"description":713,"path":714,"slug":715,"category":669,"categoryLabel":694,"kind":695,"tags":716,"date":719,"updated":38,"minutes":720,"pinned":673,"draft":673,"order":704,"stack":721,"period":38,"repo":38,"thumb":38},"一台腾讯云轻量跑起多站点：从裸机到 HTTPS 的实际路径","一台 2C4G 腾讯云轻量同时承载后台、接口与静态站：备案施工顺序、Nginx 多 server 块、certbot 签证书与上线验收。","\u002Fposts\u002Fmulti-site-deploy-to-https","multi-site-deploy-to-https",[681,683,717,685,718],"HTTPS","腾讯云","2026-10-21",7,[],{"title":723,"description":724,"path":725,"slug":726,"category":669,"categoryLabel":694,"kind":695,"tags":727,"date":732,"updated":38,"minutes":733,"pinned":673,"draft":673,"order":704,"stack":734,"period":38,"repo":38,"thumb":38},"底座能力的边界：什么该沉进数据字典，什么必须单独立表","B 端底座能力的边界判断：哪些配置该沉进数据字典、哪些必须单独立表，以及单级字典不升级成树的理由。","\u002Fposts\u002Fbase-dictionary-boundary","base-dictionary-boundary",[728,729,730,731],"B端","架构设计","数据字典","super-admin","2026-10-20",4,[],{"title":736,"description":737,"path":738,"slug":739,"category":669,"categoryLabel":694,"kind":695,"tags":740,"date":732,"updated":38,"minutes":733,"pinned":673,"draft":673,"order":704,"stack":746,"period":38,"repo":38,"thumb":38},"先画全链路，再切分期：我做 ERP\u002FWMS\u002FMES\u002FQC 需求的方法","ERP\u002FWMS\u002FMES\u002FQC 需求方法：先用编号体系与硬闸点把端到端流程关进文档，再按里程碑切成可交付的分期。","\u002Fposts\u002Ferp-wms-mes-qc-requirement-method","erp-wms-mes-qc-requirement-method",[741,742,743,744,745],"MES","ERP","WMS","需求设计","流程设计",[],{"title":748,"description":749,"path":750,"slug":751,"category":669,"categoryLabel":694,"kind":695,"tags":752,"date":755,"updated":38,"minutes":733,"pinned":673,"draft":673,"order":704,"stack":756,"period":38,"repo":38,"thumb":38},"主数据状态机不是字段，是一份跨模块公共契约","MES 主数据状态机的设计取舍：六态加停用怎么定、四方口径为什么必须交叉核对，以及 BOM 与编号体系为什么会互相污染。","\u002Fposts\u002Fmes-master-data-state-machine","mes-master-data-state-machine",[741,753,744,754],"领域建模","状态机","2026-10-19",[],{"title":758,"description":759,"path":760,"slug":761,"category":669,"categoryLabel":694,"kind":695,"tags":762,"date":767,"updated":38,"minutes":703,"pinned":673,"draft":673,"order":704,"stack":768,"period":38,"repo":38,"thumb":38},"B 端后台底座：把权限、菜单、请求收敛成三层","后台系统做多了会发现，真正需要沉淀的不是页面，而是权限模型、动态菜单和请求层这三块底座。","\u002Fposts\u002Fvue3-admin-base","vue3-admin-base",[763,764,765,766],"Vue","后台","架构","权限","2026-09-24",[],{"title":770,"description":771,"path":772,"slug":773,"category":669,"categoryLabel":694,"kind":695,"tags":774,"date":778,"updated":38,"minutes":703,"pinned":673,"draft":673,"order":704,"stack":779,"period":38,"repo":38,"thumb":38},"工作流引擎实操笔记：节点、流转与幂等","从状态机到可配置流程：一次工作流引擎落地中关于节点模型、流转条件、幂等与补偿的实操记录。","\u002Fposts\u002Fworkflow-engine-notes","workflow-engine-notes",[775,776,765,777],"工作流","后端","幂等","2026-08-30",[],{"title":781,"description":782,"path":783,"slug":731,"category":784,"categoryLabel":785,"kind":784,"tags":786,"date":787,"updated":38,"minutes":45,"pinned":673,"draft":673,"order":45,"stack":788,"period":796,"repo":38,"thumb":797},"Super Admin 后台底座","一套可复用的 B 端后台前端底座：权限三层收敛、动态菜单、请求层封装与通用表格表单组件，新项目接入只需替换业务页面。","\u002Fprojects\u002Fsuper-admin","project","项目",[763,764,700],"2026-05-20",[789,790,791,792,793,794,795],"Vue 3","TypeScript","Vite","Pinia","Antdv Next","Node.js","Next.js","2026 年至今","SA",{"title":799,"description":800,"path":801,"slug":802,"category":784,"categoryLabel":785,"kind":784,"tags":803,"date":702,"updated":38,"minutes":45,"pinned":673,"draft":673,"order":804,"stack":805,"period":807,"repo":38,"thumb":808},"雨墨 RainInk 本站","你正在看的这个站：Nuxt 4 + Nuxt Content 的纯静态个人站，手写设计令牌、无评论无用户输入、产物可直接静态托管。","\u002Fprojects\u002Frainink-site","rainink-site",[697,699,700],3,[806,789,698,790],"Nuxt 4","2026 年 10 月","RI",[810,813,816,819,822,825,828,831],{"title":690,"description":691,"path":692,"slug":693,"category":669,"categoryLabel":694,"kind":695,"tags":811,"date":701,"updated":702,"minutes":703,"pinned":676,"draft":673,"order":704,"stack":812,"period":38,"repo":38,"thumb":38},[697,698,699,700],[],{"title":5,"description":672,"path":677,"slug":707,"category":669,"categoryLabel":694,"kind":695,"tags":814,"date":671,"updated":38,"minutes":709,"pinned":673,"draft":673,"order":704,"stack":815,"period":38,"repo":38,"thumb":38},[681,682,683,684,685],[],{"title":712,"description":713,"path":714,"slug":715,"category":669,"categoryLabel":694,"kind":695,"tags":817,"date":719,"updated":38,"minutes":720,"pinned":673,"draft":673,"order":704,"stack":818,"period":38,"repo":38,"thumb":38},[681,683,717,685,718],[],{"title":723,"description":724,"path":725,"slug":726,"category":669,"categoryLabel":694,"kind":695,"tags":820,"date":732,"updated":38,"minutes":733,"pinned":673,"draft":673,"order":704,"stack":821,"period":38,"repo":38,"thumb":38},[728,729,730,731],[],{"title":736,"description":737,"path":738,"slug":739,"category":669,"categoryLabel":694,"kind":695,"tags":823,"date":732,"updated":38,"minutes":733,"pinned":673,"draft":673,"order":704,"stack":824,"period":38,"repo":38,"thumb":38},[741,742,743,744,745],[],{"title":748,"description":749,"path":750,"slug":751,"category":669,"categoryLabel":694,"kind":695,"tags":826,"date":755,"updated":38,"minutes":733,"pinned":673,"draft":673,"order":704,"stack":827,"period":38,"repo":38,"thumb":38},[741,753,744,754],[],{"title":758,"description":759,"path":760,"slug":761,"category":669,"categoryLabel":694,"kind":695,"tags":829,"date":767,"updated":38,"minutes":703,"pinned":673,"draft":673,"order":704,"stack":830,"period":38,"repo":38,"thumb":38},[763,764,765,766],[],{"title":770,"description":771,"path":772,"slug":773,"category":669,"categoryLabel":694,"kind":695,"tags":832,"date":778,"updated":38,"minutes":703,"pinned":673,"draft":673,"order":704,"stack":833,"period":38,"repo":38,"thumb":38},[775,776,765,777],[],[],[836,839],{"title":781,"description":782,"path":783,"slug":731,"category":784,"categoryLabel":785,"kind":784,"tags":837,"date":787,"updated":38,"minutes":45,"pinned":673,"draft":673,"order":45,"stack":838,"period":796,"repo":38,"thumb":797},[763,764,700],[789,790,791,792,793,794,795],{"title":799,"description":800,"path":801,"slug":802,"category":784,"categoryLabel":785,"kind":784,"tags":840,"date":702,"updated":38,"minutes":45,"pinned":673,"draft":673,"order":804,"stack":841,"period":807,"repo":38,"thumb":808},[697,699,700],[806,789,698,790],[843,845,846,847,848,849,850,852,853,854,855,856,857,858,859,860,861,862,863,864,865,866,867,868,869,870,871,872,873],{"name":741,"count":62,"weight":844},1.6,{"name":683,"count":62,"weight":844},{"name":765,"count":62,"weight":844},{"name":685,"count":62,"weight":844},{"name":681,"count":62,"weight":844},{"name":744,"count":62,"weight":844},{"name":728,"count":45,"weight":851},1.25,{"name":742,"count":45,"weight":851},{"name":717,"count":45,"weight":851},{"name":697,"count":45,"weight":851},{"name":698,"count":45,"weight":851},{"name":684,"count":45,"weight":851},{"name":699,"count":45,"weight":851},{"name":731,"count":45,"weight":851},{"name":763,"count":45,"weight":851},{"name":743,"count":45,"weight":851},{"name":700,"count":45,"weight":851},{"name":764,"count":45,"weight":851},{"name":776,"count":45,"weight":851},{"name":775,"count":45,"weight":851},{"name":777,"count":45,"weight":851},{"name":730,"count":45,"weight":851},{"name":766,"count":45,"weight":851},{"name":729,"count":45,"weight":851},{"name":745,"count":45,"weight":851},{"name":754,"count":45,"weight":851},{"name":718,"count":45,"weight":851},{"name":682,"count":45,"weight":851},{"name":753,"count":45,"weight":851},1792738754341]