[{"data":1,"prerenderedAt":248},["ShallowReactive",2],{"content:\u002Fsnippets":3},[4,66,87,129,160,185,226],{"id":5,"title":6,"description":7,"extension":8,"meta":9,"stem":64,"__hash__":65},"snippets\u002Fsnippets\u002F1.my-nuxt-deploy-github-actions.md","该项目部署使用的 GitHub Actions",null,"md",{"readingTime":10,"body":15},{"text":11,"minutes":12,"time":13,"words":14},"1 min read",0.925,55500,185,{"type":16,"value":17,"toc":61},"minimark",[18,30],[19,20,27],"pre",{"className":21,"code":23,"filename":24,"language":25,"meta":26},[22],"language-yml","name: deploy nuxt app\non:\n  push:\n    branches:\n      - main\njobs:\n  deploy:\n    runs-on: ubuntu-24.04\n    steps:\n      - name: Checkout code\n        uses: actions\u002Fcheckout@v4\n\n      - uses: pnpm\u002Faction-setup@v4\n        name: Install pnpm\n        with:\n          version: 10.24.0\n          run_install: false\n\n      - name: Setup Node.js\n        uses: actions\u002Fsetup-node@v4\n        with:\n          node-version: 24.x\n          cache: pnpm\n\n      - name: Install dependencies\n        run: pnpm install\n\n      - name: Build the app\n        run: pnpm run build\n\n      - name: Deploy to Server\n        uses: appleboy\u002Fscp-action@v1\n        with:\n          host: ${{ secrets.WXW_HOST }}\n          username: ${{ secrets.WXW_USERNAME }}\n          password: ${{ secrets.WXW_PASSWORD }}\n          port: 22\n          source: .output\u002F\n          target: ${{ secrets.WXW_TARGET }}\n",".github\u002Fworkflows\u002Fdeploy.yml","yml","",[28,29,23],"code",{"__ignoreMap":26},[31,32,33,34,37,38,41,42,41,45,48,49,52,53,56,57,60],"p",{},"这里的 ",[28,35,36],{"code":36},"secrets"," 是在 GitHub 仓库的设置中配置的环境变量，确保你已经在仓库的 Secrets 中添加了 ",[28,39,40],{"code":40},"WXW_HOST",", ",[28,43,44],{"code":44},"WXW_USERNAME",[28,46,47],{"code":47},"WXW_PASSWORD",", 和 ",[28,50,51],{"code":51},"WXW_TARGET","。\n这样配置后，每次你向 ",[28,54,55],{"code":55},"main"," 分支推送代码时，GitHub Actions 会自动触发部署流程，构建你的 Nuxt 应用并将其部署到指定的服务器上。\n你可以根据自己的需求调整 ",[28,58,59],{"code":59},"node-version"," 和其他配置项。",{"title":26,"searchDepth":62,"depth":62,"links":63},4,[],"snippets\u002F1.my-nuxt-deploy-github-actions","OofNW0eY1mQ50CasTxlTyd_JKwK5gvIssCEP06U7Rjk",{"id":67,"title":68,"description":7,"extension":8,"meta":69,"stem":85,"__hash__":86},"snippets\u002Fsnippets\u002F2.pnpm-workspace.md","pnpm 工作区配置",{"readingTime":70,"body":74},{"text":11,"minutes":71,"time":72,"words":73},0.035,2100,7,{"type":16,"value":75,"toc":83},[76],[19,77,81],{"className":78,"code":79,"filename":80,"language":25,"meta":26},[22],"packages:\n  - 'packages\u002F*'\n  - 'apps\u002F*'\n  - '!**\u002Ftest\u002F**'\n","pnpm-workspace.yaml",[28,82,79],{"__ignoreMap":26},{"title":26,"searchDepth":62,"depth":62,"links":84},[],"snippets\u002F2.pnpm-workspace","d1BG6kZ29_xilAMgEoZpGpTuGpIW2IG-ubga7Di084M",{"id":88,"title":89,"description":7,"extension":8,"meta":90,"stem":127,"__hash__":128},"snippets\u002Fsnippets\u002F3.pinia.md","pinia 常用",{"readingTime":91,"body":95},{"text":11,"minutes":92,"time":93,"words":94},0.305,18300,61,{"type":16,"value":96,"toc":122},[97,101,110,113],[98,99,100],"h2",{"id":100},"仓库配置",[19,102,108],{"className":103,"code":105,"filename":106,"language":107,"meta":26},[104],"language-ts","import { defineStore } from 'pinia'\nimport { ref } from 'vue'\n\nexport const useAppStore = defineStore('appStore', () => {\n    const user = ref(null)\n\n    return {\n        user,\n    }\n})\n","app.store.ts","ts",[28,109,105],{"__ignoreMap":26},[98,111,112],{"id":112},"使用",[19,114,120],{"className":115,"code":117,"filename":118,"language":119,"meta":26},[116],"language-vue","\u003Cscript setup lang=\"ts\">\nimport { storeToRefs } from 'pinia'\n\nimport { useAppStore } from '@\u002Fstore\u002Fapp.store'\n\nconst appStore = useAppStore()\nconst { user } = storeToRefs(appStore)\n\u003C\u002Fscript>\n","app.vue","vue",[28,121,117],{"__ignoreMap":26},{"title":26,"searchDepth":62,"depth":62,"links":123},[124,126],{"id":100,"depth":125,"text":100},2,{"id":112,"depth":125,"text":112},"snippets\u002F3.pinia","C4xtIdiLJ_cSdakEjTArs4EeS9NhqO_s_xUg9xtgsUs",{"id":130,"title":131,"description":7,"extension":8,"meta":132,"stem":158,"__hash__":159},"snippets\u002Fsnippets\u002F4.nestjs-transform-interceptors.md","Nestjs 全局响应拦截器",{"readingTime":133,"body":137},{"text":11,"minutes":134,"time":135,"words":136},0.91,54600,182,{"type":16,"value":138,"toc":156},[139,142,149],[31,140,141],{},"添加这个可以让所有接口返回值都符合统一的格式",[19,143,147],{"className":144,"code":145,"filename":146,"language":107,"meta":26},[104],"import type { IResponse, IResponseWithExtra } from 'src\u002Ftypes\u002Fresponse.type';\n\nimport { CallHandler, NestInterceptor } from '@nestjs\u002Fcommon';\nimport { Observable } from 'rxjs';\nimport { map } from 'rxjs\u002Foperators';\n\nexport class TransformInterceptor\u003CT = any>\nimplements NestInterceptor\u003CT, IResponse\u003CT>> {\n    intercept(_, next: CallHandler\u003CT>): Observable\u003CIResponse\u003CT>> {\n        return next.handle().pipe(\n            map((data) => {\n                console.log(data, 'data');\n                const responseData = data as T | IResponseWithExtra\u003CT>;\n                if (\n                    responseData instanceof Object\n                    && 'data' in responseData\n                    && 'extra' in responseData\n                ) {\n                    return {\n                        data: responseData.data!,\n                        status: 200,\n                        extra: responseData.extra || {},\n                        message: 'success',\n                        success: true,\n                    };\n                }\n                return {\n                    data,\n                    status: 200,\n                    extra: {},\n                    message: 'success',\n                    success: true,\n                };\n            }),\n        );\n    }\n}\n","transform.interceptor.ts",[28,148,145],{"__ignoreMap":26},[19,150,154],{"className":151,"code":152,"filename":153,"language":107,"meta":26},[104],"export interface IResponse\u003CT> {\n    data: T\n    status: number\n    extra: Record\u003Cstring, any>\n    message: string\n    success: boolean\n}\n\nexport interface IResponseWithExtra\u003CT, R = Record\u003Cstring, any>> {\n    data?: T\n    extra?: R\n}\n\ninterface IPaginationExtra {\n    total: number\n    page: number\n    pageSize: number\n    [key: string]: any \u002F\u002F 其他字段\n}\n\nexport interface IResponseWithPagination\u003CT, R = IPaginationExtra> {\n    data?: T[]\n    extra?: R\n}\n","types\u002Fresponse.type.ts",[28,155,152],{"__ignoreMap":26},{"title":26,"searchDepth":62,"depth":62,"links":157},[],"snippets\u002F4.nestjs-transform-interceptors","f53J_67ZKphugR-ObG4Fnei0qhletj74geb3IeQ34b8",{"id":161,"title":162,"description":7,"extension":8,"meta":163,"stem":183,"__hash__":184},"snippets\u002Fsnippets\u002F5.vscode.snippets.md","VSCode 代码片段",{"readingTime":164,"body":168},{"text":11,"minutes":165,"time":166,"words":167},0.365,21900,73,{"type":16,"value":169,"toc":181},[170,173],[31,171,172],{},"一些我用的 VSCode 代码片段",[19,174,179],{"className":175,"code":177,"language":178,"meta":26},[176],"language-json","{\n  \"vue3 setup base\": {\n    \"prefix\": \"v3\",\n    \"body\": [\n      \"\u003Cscript lang='ts' setup>\",\n      \"\",\n      \"\u003C\u002Fscript>\",\n      \"\",\n      \"\u003Ctemplate>\",\n      \"$1\",\n      \"\u003C\u002Ftemplate>\",\n      \"\",\n    ],\n    \"description\": \"vue3 setup base\",\n  },\n  \"pinia base\": {\n    \"prefix\": \"v3-store\",\n    \"body\": [\n      \"import { defineStore } from 'pinia'\",\n      \"\",\n      \"export const use${TM_FILENAME_BASE\u002F^(.)|-(.)\u002F${1:\u002Fcapitalize}${2:\u002Fcapitalize}\u002Fg} = defineStore('$TM_FILENAME_BASE', () => {\",\n      \"    \",\n      \"\",\n      \"    return {\",\n      \"        \",\n      \"    }\",\n      \"})\",\n    ],\n    \"description\": \"pinia base\",\n  },\n}\n","json",[28,180,177],{"__ignoreMap":26},{"title":26,"searchDepth":62,"depth":62,"links":182},[],"snippets\u002F5.vscode.snippets","ASFbnS_LLJGaYfEf85Ovr3rJn-6hzU3x4kbHEgAMlwA",{"id":186,"title":187,"description":7,"extension":8,"meta":188,"stem":224,"__hash__":225},"snippets\u002Fsnippets\u002F6.antfu-eslint-plugin.md","对 @antfu\u002Feslint-config 的覆盖规则",{"readingTime":189,"body":193},{"text":11,"minutes":190,"time":191,"words":192},0.425,25500,85,{"type":16,"value":194,"toc":222},[195,204,214],[31,196,197],{},[198,199,203],"a",{"href":200,"rel":201},"https:\u002F\u002Fgithub.com\u002Fantfu\u002Feslint-config",[202],"nofollow","antfu\u002Feslint-config",[205,206,207],"blockquote",{},[31,208,209,210,213],{},"需要额外安装 ",[28,211,212],{"code":212},"@tanstack\u002Feslint-plugin-query"," 使用 tanstack-query 的规则",[19,215,220],{"className":216,"code":218,"language":219,"meta":26},[217],"language-js","import antfu from '@antfu\u002Feslint-config'\nimport pluginQuery from '@tanstack\u002Feslint-plugin-query'\n\nexport default antfu({\n    type: 'app',\n    vue: {\n        overrides: {\n        'vue\u002Fblock-lang': ['warn', {\n            script: { lang: ['ts', 'tsx'] },\n        }],\n        },\n    },\n    typescript: true,\n    formatters: {\n        css: true,\n        html: true,\n        markdown: 'prettier',\n    },\n\n    ignores: [\n        '**\u002Fbuild\u002F**',\n        '**\u002Fcomponents\u002Fui\u002F**',\n    ],\n    settings: {\n        'import\u002Fcore-modules': ['vue-router\u002Fauto-routes'],\n    },\n    globals: {\n        definePage: 'readonly',\n    },\n\n    imports: {\n        overrides: {\n        'perfectionist\u002Fsort-imports': ['error', {\n            tsconfig: { rootDir: '.' },\n        }],\n        },\n    },\n    ...pluginQuery.configs['flat\u002Frecommended'],\n})\n","js",[28,221,218],{"__ignoreMap":26},{"title":26,"searchDepth":62,"depth":62,"links":223},[],"snippets\u002F6.antfu-eslint-plugin","oUmYHdoPg_ZnkGTuN__fL2M2VkND3OIYd7MZTHno0nM",{"id":227,"title":228,"description":7,"extension":8,"meta":229,"stem":246,"__hash__":247},"snippets\u002Fsnippets\u002F7.vue-history-in-nginx.md","vue-hisory项目在nginx下的伪静态配置",{"readingTime":230,"body":234},{"text":11,"minutes":231,"time":232,"words":233},0.385,23100,77,{"type":16,"value":235,"toc":244},[236],[19,237,242],{"className":238,"code":240,"language":241,"meta":26},[239],"language-nginx","location \u002F {\n    try_files $uri $uri\u002F \u002Findex.html last;\n    index index.html;\n}\n\nadd_header 'Access-Control-Allow-Origin' '*' always; #允许来自所有的访问地址\nadd_header 'Access-Control-Allow-Credentials' 'true' always; #允许来自所有的访问地址\nadd_header 'Access-Control-Allow-Headers' 'Origin, X-Requested-With, Content-Type, Accept, token, platform' always;\nadd_header 'Access-Control-Allow-Methods' 'GET,POST,PUT,DELETE,HEAD,OPTIONS' always; #允许来自所有的访问地址\n\nif ($request_method = OPTIONS ) {\n    return 200;\n}\n","nginx",[28,243,240],{"__ignoreMap":26},{"title":26,"searchDepth":62,"depth":62,"links":245},[],"snippets\u002F7.vue-history-in-nginx","VkFeO1OZg2LNEbmlhvV58x3nDAdQ4-yhDfQkmXnFWDg",1789642583750]