@yinuo-ngm/server 1.0.15 → 1.0.17
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/app.js +3 -15
- package/lib/common/editor.js +2 -2
- package/lib/env.d.ts +1 -0
- package/lib/env.js +1 -0
- package/lib/plugins/error-handler.plugin.d.ts +2 -2
- package/lib/plugins/error-handler.plugin.js +97 -88
- package/lib/plugins/ws/topics/nginx.ws.js +2 -1
- package/lib/plugins/ws/topics/svn.ws.d.ts +2 -1
- package/lib/plugins/ws/topics/svn.ws.js +3 -2
- package/lib/plugins/ws/topics/syslog.ws.d.ts +1 -1
- package/lib/plugins/ws/topics/task.ws.d.ts +2 -1
- package/lib/plugins/ws/topics/task.ws.js +2 -1
- package/lib/plugins/ws/ws.context.d.ts +1 -1
- package/lib/plugins/ws/ws.plugin.js +4 -3
- package/lib/plugins/ws/ws.router.d.ts +2 -2
- package/lib/plugins/ws/ws.router.js +8 -7
- package/lib/routes/api-client/collection.routes.js +8 -6
- package/lib/routes/api-client/env.routes.js +4 -3
- package/lib/routes/api-client/history.routes.js +3 -2
- package/lib/routes/api-client/hub-token.routes.js +32 -10
- package/lib/routes/api-client/request.routes.js +7 -6
- package/lib/routes/api-client/send.routes.js +3 -2
- package/lib/routes/config.routes.js +5 -5
- package/lib/routes/hub.routes.js +10 -10
- package/lib/routes/index.js +2 -0
- package/lib/routes/nginx/nginx-lifecycle.routes.js +4 -0
- package/lib/routes/nginx/nginx-route.context.js +23 -7
- package/lib/routes/nginx/nginx-server.routes.js +158 -6
- package/lib/routes/node-version.routes.d.ts +2 -0
- package/lib/routes/node-version.routes.js +56 -0
- package/lib/routes/project.routes.js +14 -9
- package/lib/routes/rss.routes.js +3 -3
- package/lib/routes/sprite-browse.routes.js +21 -6
- package/lib/routes/sprite.routes.js +18 -12
- package/lib/routes/static-files.routes.js +21 -5
- package/lib/routes/svn.routes.js +5 -3
- package/lib/routes/system.routes.js +20 -1
- package/lib/routes/task.routes.js +10 -3
- package/package.json +13 -6
- package/www/3rdpartylicenses.txt +66 -118
- package/www/browser/chunk-2L7NUOMX.js +2 -0
- package/www/browser/chunk-2NZJ7CN2.js +20 -0
- package/www/browser/chunk-3CM4SKDO.js +15 -0
- package/www/browser/chunk-3I7BQCXS.js +1 -0
- package/www/browser/chunk-3M56F2S2.js +1 -0
- package/www/browser/chunk-3OHBKMAA.js +1 -0
- package/www/browser/chunk-3XNNQFWR.js +1 -0
- package/www/browser/chunk-4BRW6LCZ.js +4 -0
- package/www/browser/chunk-4LBSLURA.js +1 -0
- package/www/browser/chunk-4X42HB6N.js +2 -0
- package/www/browser/chunk-5DYX4DUX.js +11 -0
- package/www/browser/chunk-6SYVDN5L.js +1 -0
- package/www/browser/chunk-6YYNHZ2A.js +1 -0
- package/www/browser/chunk-75W3GVSO.js +1 -0
- package/www/browser/chunk-7U44RF5F.js +63 -0
- package/www/browser/chunk-AELTP6YN.js +1 -0
- package/www/browser/chunk-AMXRL4GR.js +1 -0
- package/www/browser/chunk-AV2ZODEH.js +1 -0
- package/www/browser/chunk-AZ6SIMYH.js +1 -0
- package/www/browser/chunk-B3C35ET3.js +2 -0
- package/www/browser/chunk-BTQIUVTQ.js +1 -0
- package/www/browser/chunk-CN5J4WNO.js +1 -0
- package/www/browser/chunk-D2ODDESN.js +1 -0
- package/www/browser/chunk-DE6E23ET.js +1 -0
- package/www/browser/chunk-DIJPUYIA.js +1 -0
- package/www/browser/chunk-DLGJD6YU.js +4 -0
- package/www/browser/chunk-EEDA5U4V.js +1 -0
- package/www/browser/chunk-FK6Z4HLL.js +1 -0
- package/www/browser/chunk-FL6GDGHW.js +1 -0
- package/www/browser/chunk-FXCG34QS.js +1 -0
- package/www/browser/chunk-H2USFIYR.js +1 -0
- package/www/browser/chunk-H5HGMOE6.js +1 -0
- package/www/browser/chunk-HB3HECPD.js +1 -0
- package/www/browser/chunk-HDNG236Q.js +1 -0
- package/www/browser/chunk-HFZLJHYR.js +1 -0
- package/www/browser/chunk-HJTXXSMC.js +1 -0
- package/www/browser/chunk-HUMCWAKJ.js +3 -0
- package/www/browser/chunk-IKB3EQCP.js +2 -0
- package/www/browser/chunk-K7PESFPY.js +1 -0
- package/www/browser/chunk-KRYMOHYF.js +2 -0
- package/www/browser/chunk-M4QRBV3K.js +1 -0
- package/www/browser/chunk-N2PELLMM.js +30 -0
- package/www/browser/chunk-ONXBYGIG.js +1 -0
- package/www/browser/chunk-OSBDR36P.js +1 -0
- package/www/browser/chunk-OZCK4XVV.js +1 -0
- package/www/browser/chunk-QJP5F735.js +1 -0
- package/www/browser/chunk-RGOYDY7H.js +1 -0
- package/www/browser/chunk-UJKK4A7Y.js +1 -0
- package/www/browser/chunk-WD2EKZQC.js +1 -0
- package/www/browser/chunk-WUA5JFDD.js +1 -0
- package/www/browser/chunk-XLFHB7RS.js +3 -0
- package/www/browser/chunk-YNW4HEJO.js +37 -0
- package/www/browser/chunk-ZTDLWBW5.js +1 -0
- package/www/browser/dark.css +1 -30433
- package/www/browser/default.css +1 -30149
- package/www/browser/index.html +3 -3
- package/www/browser/main-N64WJCHX.js +34 -0
- package/www/browser/scripts-U25HCVEI.js +6 -0
- package/www/browser/styles-ROAHD7MY.css +1 -0
- package/www/browser/add-widget-drawer.component.css.map +0 -7
- package/www/browser/advanced-editor.component.css.map +0 -7
- package/www/browser/api-client.component.css.map +0 -7
- package/www/browser/api-history-drawer.component.css.map +0 -7
- package/www/browser/app.css.map +0 -7
- package/www/browser/attachment-viewer.component.css.map +0 -7
- package/www/browser/auth-editor.component.css.map +0 -7
- package/www/browser/body-editor.component.css.map +0 -7
- package/www/browser/chunk-2YSUXBGC.js +0 -627
- package/www/browser/chunk-2YSUXBGC.js.map +0 -1
- package/www/browser/chunk-3G2GEOPV.js +0 -456
- package/www/browser/chunk-3G2GEOPV.js.map +0 -1
- package/www/browser/chunk-3L72DF3R.js +0 -1683
- package/www/browser/chunk-3L72DF3R.js.map +0 -1
- package/www/browser/chunk-3MCIETCQ.js +0 -8279
- package/www/browser/chunk-3MCIETCQ.js.map +0 -1
- package/www/browser/chunk-665WC4RU.js +0 -5383
- package/www/browser/chunk-665WC4RU.js.map +0 -1
- package/www/browser/chunk-6QMSEZPT.js +0 -10044
- package/www/browser/chunk-6QMSEZPT.js.map +0 -1
- package/www/browser/chunk-6TBQERYX.js +0 -280
- package/www/browser/chunk-6TBQERYX.js.map +0 -1
- package/www/browser/chunk-6UW4MRJZ.js +0 -43
- package/www/browser/chunk-6UW4MRJZ.js.map +0 -7
- package/www/browser/chunk-6XUMIL3W.js +0 -5495
- package/www/browser/chunk-6XUMIL3W.js.map +0 -1
- package/www/browser/chunk-724YOJI3.js +0 -903
- package/www/browser/chunk-724YOJI3.js.map +0 -1
- package/www/browser/chunk-766T7YES.js +0 -437
- package/www/browser/chunk-766T7YES.js.map +0 -1
- package/www/browser/chunk-7FC7DN65.js +0 -728
- package/www/browser/chunk-7FC7DN65.js.map +0 -1
- package/www/browser/chunk-APGQRYWX.js +0 -156
- package/www/browser/chunk-APGQRYWX.js.map +0 -7
- package/www/browser/chunk-AQHSGTHS.js +0 -1960
- package/www/browser/chunk-AQHSGTHS.js.map +0 -1
- package/www/browser/chunk-CTOEAJQK.js +0 -40
- package/www/browser/chunk-CTOEAJQK.js.map +0 -7
- package/www/browser/chunk-DEGQJKKZ.js +0 -409
- package/www/browser/chunk-DEGQJKKZ.js.map +0 -1
- package/www/browser/chunk-DIJX2663.js +0 -1166
- package/www/browser/chunk-DIJX2663.js.map +0 -1
- package/www/browser/chunk-E4XD4GLT.js +0 -427
- package/www/browser/chunk-E4XD4GLT.js.map +0 -1
- package/www/browser/chunk-EQOY6A3M.js +0 -212
- package/www/browser/chunk-EQOY6A3M.js.map +0 -1
- package/www/browser/chunk-ETTBRXVA.js +0 -2643
- package/www/browser/chunk-ETTBRXVA.js.map +0 -1
- package/www/browser/chunk-FLSUSPBD.js +0 -5569
- package/www/browser/chunk-FLSUSPBD.js.map +0 -1
- package/www/browser/chunk-FZNHBEAZ.js +0 -102
- package/www/browser/chunk-FZNHBEAZ.js.map +0 -1
- package/www/browser/chunk-GJC7CZIJ.js +0 -361
- package/www/browser/chunk-GJC7CZIJ.js.map +0 -7
- package/www/browser/chunk-GMCNMOTD.js +0 -844
- package/www/browser/chunk-GMCNMOTD.js.map +0 -7
- package/www/browser/chunk-H43HGCRW.js +0 -198
- package/www/browser/chunk-H43HGCRW.js.map +0 -7
- package/www/browser/chunk-J447GBHM.js +0 -160
- package/www/browser/chunk-J447GBHM.js.map +0 -1
- package/www/browser/chunk-JN3VOWP7.js +0 -384
- package/www/browser/chunk-JN3VOWP7.js.map +0 -1
- package/www/browser/chunk-KSHAGY2M.js +0 -399
- package/www/browser/chunk-KSHAGY2M.js.map +0 -7
- package/www/browser/chunk-KV72AKOD.js +0 -59
- package/www/browser/chunk-KV72AKOD.js.map +0 -7
- package/www/browser/chunk-LAVMY2SJ.js +0 -26
- package/www/browser/chunk-LAVMY2SJ.js.map +0 -7
- package/www/browser/chunk-LLRVGHG5.js +0 -73
- package/www/browser/chunk-LLRVGHG5.js.map +0 -7
- package/www/browser/chunk-LPME4AJ3.js +0 -196
- package/www/browser/chunk-LPME4AJ3.js.map +0 -1
- package/www/browser/chunk-LVPSURVU.js +0 -4615
- package/www/browser/chunk-LVPSURVU.js.map +0 -1
- package/www/browser/chunk-MMPO7QLO.js +0 -4146
- package/www/browser/chunk-MMPO7QLO.js.map +0 -7
- package/www/browser/chunk-O7LB6VFM.js +0 -1953
- package/www/browser/chunk-O7LB6VFM.js.map +0 -1
- package/www/browser/chunk-P5CWA4FO.js +0 -685
- package/www/browser/chunk-P5CWA4FO.js.map +0 -1
- package/www/browser/chunk-RBWIWNTL.js +0 -203
- package/www/browser/chunk-RBWIWNTL.js.map +0 -7
- package/www/browser/chunk-RUXJCM3V.js +0 -26199
- package/www/browser/chunk-RUXJCM3V.js.map +0 -1
- package/www/browser/chunk-S77VVYUZ.js +0 -168
- package/www/browser/chunk-S77VVYUZ.js.map +0 -1
- package/www/browser/chunk-SCXPYFOB.js +0 -4316
- package/www/browser/chunk-SCXPYFOB.js.map +0 -1
- package/www/browser/chunk-SS73S33S.js +0 -471
- package/www/browser/chunk-SS73S33S.js.map +0 -7
- package/www/browser/chunk-T6UAOWNP.js +0 -600
- package/www/browser/chunk-T6UAOWNP.js.map +0 -1
- package/www/browser/chunk-TEW4MY4J.js +0 -148
- package/www/browser/chunk-TEW4MY4J.js.map +0 -7
- package/www/browser/chunk-TVORF3SF.js +0 -82
- package/www/browser/chunk-TVORF3SF.js.map +0 -7
- package/www/browser/chunk-UAN42EUZ.js +0 -2147
- package/www/browser/chunk-UAN42EUZ.js.map +0 -1
- package/www/browser/chunk-ULOHDK7Y.js +0 -1
- package/www/browser/chunk-ULOHDK7Y.js.map +0 -7
- package/www/browser/chunk-UYJ3FVRV.js +0 -3978
- package/www/browser/chunk-UYJ3FVRV.js.map +0 -1
- package/www/browser/chunk-VXHZMSDM.js +0 -5509
- package/www/browser/chunk-VXHZMSDM.js.map +0 -1
- package/www/browser/chunk-VYNQPZQO.js +0 -281
- package/www/browser/chunk-VYNQPZQO.js.map +0 -1
- package/www/browser/chunk-W3J23PZI.js +0 -9213
- package/www/browser/chunk-W3J23PZI.js.map +0 -1
- package/www/browser/chunk-W5HGHCQT.js +0 -1642
- package/www/browser/chunk-W5HGHCQT.js.map +0 -7
- package/www/browser/chunk-XF5H7E4L.js +0 -4723
- package/www/browser/chunk-XF5H7E4L.js.map +0 -1
- package/www/browser/chunk-XNFNEBMY.js +0 -398
- package/www/browser/chunk-XNFNEBMY.js.map +0 -7
- package/www/browser/chunk-XQY5SPGI.js +0 -30811
- package/www/browser/chunk-XQY5SPGI.js.map +0 -1
- package/www/browser/chunk-Y7JBZHNK.js +0 -514
- package/www/browser/chunk-Y7JBZHNK.js.map +0 -1
- package/www/browser/chunk-YWHRP4X3.js +0 -406
- package/www/browser/chunk-YWHRP4X3.js.map +0 -1
- package/www/browser/chunk-Z7FJIV62.js +0 -95
- package/www/browser/chunk-Z7FJIV62.js.map +0 -7
- package/www/browser/chunk-ZBZHXS46.js +0 -1674
- package/www/browser/chunk-ZBZHXS46.js.map +0 -1
- package/www/browser/chunk-ZZA5NVAI.js +0 -735
- package/www/browser/chunk-ZZA5NVAI.js.map +0 -1
- package/www/browser/collection-modal.component.css.map +0 -7
- package/www/browser/collection-tree-item.component.css.map +0 -7
- package/www/browser/collection-tree.component.css.map +0 -7
- package/www/browser/config-change-bar-component.css.map +0 -7
- package/www/browser/config-item-component.css.map +0 -7
- package/www/browser/config-nav-component.css.map +0 -7
- package/www/browser/config-section-component.css.map +0 -7
- package/www/browser/create-summary-aside.component.css.map +0 -7
- package/www/browser/curl-actions.component.css.map +0 -7
- package/www/browser/dark.css.map +0 -7
- package/www/browser/dashboard-canvas.component.css.map +0 -7
- package/www/browser/dashboard.component.css.map +0 -7
- package/www/browser/default.css.map +0 -7
- package/www/browser/detail-item-card.component.css.map +0 -7
- package/www/browser/ellipsis-text.component.css.map +0 -7
- package/www/browser/env-modal.component.css.map +0 -7
- package/www/browser/env-picker.component.css.map +0 -7
- package/www/browser/feedback.component.css.map +0 -7
- package/www/browser/fs-explorer.component.css.map +0 -7
- package/www/browser/git-import-modal.component.css.map +0 -7
- package/www/browser/hub-v2-personal-token-modal.component.css.map +0 -7
- package/www/browser/issue-action-area.component.css.map +0 -7
- package/www/browser/issue-add-participants-dialog.component.css.map +0 -7
- package/www/browser/issue-assign-dialog.component.css.map +0 -7
- package/www/browser/issue-attachment-area.component.css.map +0 -7
- package/www/browser/issue-base-info-area.component.css.map +0 -7
- package/www/browser/issue-branches.component.css.map +0 -7
- package/www/browser/issue-close-dialog.component.css.map +0 -7
- package/www/browser/issue-collaborators-panel.component.css.map +0 -7
- package/www/browser/issue-comment-editor.component.css.map +0 -7
- package/www/browser/issue-create-branch-dialog.component.css.map +0 -7
- package/www/browser/issue-description-area.component.css.map +0 -7
- package/www/browser/issue-detail.component.css.map +0 -7
- package/www/browser/issue-resolve-dialog.component.css.map +0 -7
- package/www/browser/issue-start-own-branch-dialog.component.css.map +0 -7
- package/www/browser/issues-list-table.component.css.map +0 -7
- package/www/browser/issues.component.css.map +0 -7
- package/www/browser/kill-port-widget.component.css.map +0 -7
- package/www/browser/kv-table.component.css.map +0 -7
- package/www/browser/layout-footer.component.css.map +0 -7
- package/www/browser/layout-header.component.css.map +0 -7
- package/www/browser/layout-menu.component.css.map +0 -7
- package/www/browser/layout-project-nav.component.css.map +0 -7
- package/www/browser/layout-sidebar.component.css.map +0 -7
- package/www/browser/layout.component.css.map +0 -7
- package/www/browser/less-viewport-component.css.map +0 -7
- package/www/browser/main.js +0 -1872
- package/www/browser/main.js.map +0 -1
- package/www/browser/markdown-viewer.component.css.map +0 -7
- package/www/browser/news-feed-widget.component.css.map +0 -7
- package/www/browser/ng-devtool.component.css.map +0 -7
- package/www/browser/nginx-config-editor.component.css.map +0 -7
- package/www/browser/nginx-log-viewer.component.css.map +0 -7
- package/www/browser/nginx-secondary-logs-tab.component.css.map +0 -7
- package/www/browser/nginx-secondary-perf-tab.component.css.map +0 -7
- package/www/browser/nginx-secondary-settings-tab.component.css.map +0 -7
- package/www/browser/nginx-secondary-ssl-tab.component.css.map +0 -7
- package/www/browser/nginx-secondary-test-tab.component.css.map +0 -7
- package/www/browser/nginx-secondary-traffic-tab.component.css.map +0 -7
- package/www/browser/nginx-secondary-upstream-tab.component.css.map +0 -7
- package/www/browser/nginx-section-card.component.css.map +0 -7
- package/www/browser/nginx-server-drawer.component.css.map +0 -7
- package/www/browser/nginx-server-list.component.css.map +0 -7
- package/www/browser/nginx-stat-card.component.css.map +0 -7
- package/www/browser/nginx.component.css.map +0 -7
- package/www/browser/page-layout.component.css.map +0 -7
- package/www/browser/pick-workspace-modal.component.css.map +0 -7
- package/www/browser/polyfills.js +0 -26584
- package/www/browser/polyfills.js.map +0 -7
- package/www/browser/project-conf.component.css.map +0 -7
- package/www/browser/project-create-modal.component.css.map +0 -7
- package/www/browser/project-create.component.css.map +0 -7
- package/www/browser/project-deps.component.css.map +0 -7
- package/www/browser/project-edit-modal.component.css.map +0 -7
- package/www/browser/project-import.component.css.map +0 -7
- package/www/browser/project-item-popover.component.css.map +0 -7
- package/www/browser/project-item.component.css.map +0 -7
- package/www/browser/project-list.component.css.map +0 -7
- package/www/browser/projects.component.css.map +0 -7
- package/www/browser/quick-task-widget.component.css.map +0 -7
- package/www/browser/rd-action-area.component.css.map +0 -7
- package/www/browser/rd-advance-stage-dialog.component.css.map +0 -7
- package/www/browser/rd-block-dialog.component.css.map +0 -7
- package/www/browser/rd-create-dialog.component.css.map +0 -7
- package/www/browser/rd-detail.component.css.map +0 -7
- package/www/browser/rd-item-card.component.css.map +0 -7
- package/www/browser/rd-list-board.component.css.map +0 -7
- package/www/browser/rd-list-table.component.css.map +0 -7
- package/www/browser/rd.component.css.map +0 -7
- package/www/browser/request-collections.component.css.map +0 -7
- package/www/browser/request-editor.component.css.map +0 -7
- package/www/browser/request-list-item.component.css.map +0 -7
- package/www/browser/request-list.component.css.map +0 -7
- package/www/browser/request-tabs-bar.component.css.map +0 -7
- package/www/browser/request-tabs.component.css.map +0 -7
- package/www/browser/request-urlbar.component.css.map +0 -7
- package/www/browser/response-viewer.component.css.map +0 -7
- package/www/browser/scripts.js +0 -245
- package/www/browser/scripts.js.map +0 -7
- package/www/browser/setting.component.css.map +0 -7
- package/www/browser/sprite-conf-modal.component.css.map +0 -7
- package/www/browser/sprite-icons-panel-component.css.map +0 -7
- package/www/browser/sprite-images-panel-component.css.map +0 -7
- package/www/browser/sprite-result-tabs.component.css.map +0 -7
- package/www/browser/sprite-viewport-component.css.map +0 -7
- package/www/browser/sprite.component.css.map +0 -7
- package/www/browser/step-advance.component.css.map +0 -7
- package/www/browser/step-basic.component.css.map +0 -7
- package/www/browser/step-config.component.css.map +0 -7
- package/www/browser/step-features.component.css.map +0 -7
- package/www/browser/step-preset.component.css.map +0 -7
- package/www/browser/step-summary-aside.component.css.map +0 -7
- package/www/browser/styles.css +0 -258
- package/www/browser/styles.css.map +0 -7
- package/www/browser/system-log.component.css.map +0 -7
- package/www/browser/task-actions.component.css.map +0 -7
- package/www/browser/task-console.component.css.map +0 -7
- package/www/browser/task-header.component.css.map +0 -7
- package/www/browser/task-list.component.css.map +0 -7
- package/www/browser/tasks.component.css.map +0 -7
- package/www/browser/terminal-view.component.css.map +0 -7
- package/www/browser/welcome-widget.component.css.map +0 -7
- package/www/browser/widget-base.component.css.map +0 -7
- package/www/browser/widget-host.component.css.map +0 -7
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["angular:jit:style:inline:src\\app\\pages\\api-client\\api-client.component.ts;CiAgICAucGFnZXsKICAgICAgaGVpZ2h0OiAxMDAlOwogICAgICBkaXNwbGF5OiBmbGV4OwogICAgICBmbGV4LWRpcmVjdGlvbjogcm93OwogICAgICBvdmVyZmxvdzogaGlkZGVuOwogICAgICBnYXA6IDE2cHg7CiAgICAgIHBhZGRpbmc6MCAxNnB4OwogICAgfQogICAgLmNvbnRlbnQgewogICAgICBmbGV4OiAxIDEgYXV0bzsKICAgICAgd2lkdGg6IDA7CiAgICAgIGRpc3BsYXk6IGZsZXg7CiAgICAgIGZsZXgtZGlyZWN0aW9uOiBjb2x1bW47CiAgICAgIGhlaWdodDogMTAwJTsKICAgICAgb3ZlcmZsb3c6IGhpZGRlbjsKICAgIH0KICAgIC5lZGl0b3ItYXJlYSB7CiAgICAgIGZsZXg6IDEgMSBhdXRvOwogICAgICBkaXNwbGF5OiBmbGV4OwogICAgICBmbGV4LWRpcmVjdGlvbjogY29sdW1uOwogICAgICBtaW4taGVpZ2h0OiAwOwogICAgfQogICAgYXBwLXJlcXVlc3QtZWRpdG9yIHsKICAgICAgZmxleDogMCAwIGF1dG87CiAgICAgIGhlaWdodDo1MCU7CiAgICB9CiAgICBhcHAtcmVzcG9uc2Utdmlld2VyIHsKICAgICAgZmxleDogMCAwIGF1dG87CiAgICAgIGhlaWdodDo1MCU7CiAgICAgIG92ZXJmbG93OiBhdXRvOwogICAgfQogICAg","angular:jit:style:inline:src\\app\\pages\\api-client\\components\\history\\api-history-drawer.component.ts;CiAgICAubGlzdHsKICAgICAgZGlzcGxheTpmbGV4OwogICAgICBmbGV4LWRpcmVjdGlvbjpjb2x1bW47CiAgICAgIGdhcDoxMnB4OwogICAgfQogICAgLml0ZW17CiAgICAgIGJvcmRlcjoxcHggc29saWQgI2YwZjBmMDsKICAgICAgYm9yZGVyLXJhZGl1czo4cHg7CiAgICAgIHBhZGRpbmc6MTBweDsKICAgIH0KICAgIC5yb3d7CiAgICAgIGRpc3BsYXk6ZmxleDsKICAgICAgZ2FwOjhweDsKICAgICAgYWxpZ24taXRlbXM6Y2VudGVyOwogICAgICBmb250LXdlaWdodDo1MDA7CiAgICB9CiAgICAudXJsewogICAgICBmbGV4OjE7CiAgICAgIG92ZXJmbG93OmhpZGRlbjsKICAgICAgdGV4dC1vdmVyZmxvdzplbGxpcHNpczsKICAgICAgd2hpdGUtc3BhY2U6bm93cmFwOwogICAgfQogICAgLm1ldGF7CiAgICAgIG1hcmdpbi10b3A6NnB4OwogICAgICBkaXNwbGF5OmZsZXg7CiAgICAgIGdhcDo4cHg7CiAgICAgIGZvbnQtc2l6ZToxMnB4OwogICAgICBvcGFjaXR5Oi43OwogICAgfQogICAgLmFjdGlvbnN7CiAgICAgIG1hcmdpbi10b3A6OHB4OwogICAgICBkaXNwbGF5OmZsZXg7CiAgICAgIGdhcDo4cHg7CiAgICB9CiAgICAuZW1wdHl7CiAgICAgIHBhZGRpbmc6MTZweDsKICAgICAgb3BhY2l0eTouNjsKICAgICAgdGV4dC1hbGlnbjpjZW50ZXI7CiAgICB9CiAg","src/app/pages/api-client/components/history/api-history-drawer.component.ts","angular:jit:style:inline:src\\app\\pages\\api-client\\components\\request-collections\\request-list.component.ts;CiAgICAubGlzdHsgZGlzcGxheTpmbGV4OyBmbGV4LWRpcmVjdGlvbjpjb2x1bW47IGdhcDo4cHg7IHBhZGRpbmc6MTBweDsgfQogICAgCiAgICAucm93MXsgZGlzcGxheTpmbGV4OyBnYXA6OHB4OyBhbGlnbi1pdGVtczpjZW50ZXI7IH0KICAgIC5tZXRob2R7IG1hcmdpbjowOyB9CiAgICAubmFtZXsKICAgICAgZm9udC13ZWlnaHQ6NjAwOwogICAgICBvdmVyZmxvdzpoaWRkZW47CiAgICAgIHRleHQtb3ZlcmZsb3c6ZWxsaXBzaXM7CiAgICAgIHdoaXRlLXNwYWNlOm5vd3JhcDsKICAgICAgZmxleDoxOwogICAgICBtaW4td2lkdGg6MDsKICAgIH0KICAgIC5yb3cyeyBtYXJnaW4tdG9wOjZweDsgZm9udC1zaXplOjEycHg7IG9wYWNpdHk6Ljc1OyB9CiAgICAudXJsewogICAgICBvdmVyZmxvdzpoaWRkZW47CiAgICAgIHRleHQtb3ZlcmZsb3c6ZWxsaXBzaXM7CiAgICAgIHdoaXRlLXNwYWNlOm5vd3JhcDsKICAgICAgZGlzcGxheTpibG9jazsKICAgIH0KICAgIC5yb3czeyBtYXJnaW4tdG9wOjZweDsgZm9udC1zaXplOjEycHg7IG9wYWNpdHk6LjU1OyB9CiAgICAuZW1wdHl7IHBhZGRpbmc6MTZweDsgb3BhY2l0eTouNjsgdGV4dC1hbGlnbjpjZW50ZXI7IH0KICA=","angular:jit:style:inline:src\\app\\pages\\api-client\\components\\request-collections\\request-list-item.component.ts;CiAgICAgIDpob3N0LnJlcXVlc3QtaXRlbSB7CiAgICAgICAgZGlzcGxheTogZmxleDsKICAgICAgICBhbGlnbi1pdGVtczogY2VudGVyOwogICAgICAgIGp1c3RpZnktY29udGVudDogc3BhY2UtYmV0d2VlbjsKICAgICAgICBnYXA6IDhweDsKICAgICAgICBwYWRkaW5nOiA4cHggMTBweDsKICAgICAgICBib3JkZXItcmFkaXVzOiA2cHg7CiAgICAgICAgY3Vyc29yOiBwb2ludGVyOwogICAgICAgIHRyYW5zaXRpb246IGJhY2tncm91bmQtY29sb3IgMC4ycyBlYXNlOwogICAgICB9CiAgICAgIAogICAgICA6aG9zdC5yZXF1ZXN0LWl0ZW06aG92ZXIgewogICAgICAgIGJhY2tncm91bmQtY29sb3I6IHJnYmEoMCwgMCwgMCwgMC4wNCk7CiAgICAgIH0KICAgICAgCiAgICAgIDpob3N0LnJlcXVlc3QtaXRlbS5hY3RpdmUgewogICAgICAgIGJhY2tncm91bmQtY29sb3I6ICNlNmY3ZmY7CiAgICAgIH0KICAgICAgCiAgICAgIDpob3N0LnJlcXVlc3QtaXRlbS5hY3RpdmU6aG92ZXIgewogICAgICAgIGJhY2tncm91bmQtY29sb3I6ICNiYWU3ZmY7CiAgICAgIH0KICAgICAgCiAgICAgIC5jb250ZW50IHsKICAgICAgICBkaXNwbGF5OiBmbGV4OwogICAgICAgIGFsaWduLWl0ZW1zOiBjZW50ZXI7CiAgICAgICAgZ2FwOiA4cHg7CiAgICAgICAgZmxleDogMTsKICAgICAgICBvdmVyZmxvdzogaGlkZGVuOwogICAgICB9CiAgICAgIAogICAgICBidXR0b24ubW9yZS1hY3Rpb25zIHsKICAgICAgICBmbGV4OiAwIDAgYXV0bzsKICAgICAgICB3aWR0aDogMjBweDsKICAgICAgICBoZWlnaHQ6IDIwcHg7CiAgICAgICAgcGFkZGluZzogMCAhaW1wb3J0YW50OwogICAgICAgIHZpc2liaWxpdHk6IGhpZGRlbjsKICAgICAgICBvcGFjaXR5OiAwLjU7CiAgICAgIH0KICAgICAgCiAgICAgIGJ1dHRvbi5tb3JlLWFjdGlvbnM6aG92ZXIgewogICAgICAgIG9wYWNpdHk6IDE7CiAgICAgIH0KICAgICAgCiAgICAgIDpob3N0LnJlcXVlc3QtaXRlbTpob3ZlciBidXR0b24ubW9yZS1hY3Rpb25zIHsKICAgICAgICB2aXNpYmlsaXR5OiB2aXNpYmxlOwogICAgICB9CiAgICAgIAogICAgICAubWV0aG9kIHsKICAgICAgICBmbGV4OiAwIDAgYXV0bzsKICAgICAgICBmb250LXNpemU6IDEwcHg7CiAgICAgICAgZm9udC13ZWlnaHQ6IDYwMDsKICAgICAgICBsaW5lLWhlaWdodDogMS40OwogICAgICAgIHBhZGRpbmc6IDAgNHB4OwogICAgICAgIG1hcmdpbjogMDsKICAgICAgfQogICAgICAKICAgICAgLm5hbWUgewogICAgICAgIGZsZXg6IDEgMSBhdXRvOwogICAgICAgIGZvbnQtc2l6ZTogMTNweDsKICAgICAgICBmb250LXdlaWdodDogNTAwOwogICAgICAgIG92ZXJmbG93OiBoaWRkZW47CiAgICAgICAgdGV4dC1vdmVyZmxvdzogZWxsaXBzaXM7CiAgICAgICAgd2hpdGUtc3BhY2U6IG5vd3JhcDsKICAgICAgICBjb2xvcjogcmdiYSgwLCAwLCAwLCAwLjg1KTsKICAgICAgfQogICAgICAKICAgICAgLm1lbnUtaXRlbSB7CiAgICAgICAgZGlzcGxheTogZmxleDsKICAgICAgICBhbGlnbi1pdGVtczogY2VudGVyOwogICAgICB9CiAgICA=","src/app/pages/api-client/components/request-collections/request-list-item.component.ts","src/app/pages/api-client/components/request-collections/request-list.component.ts","angular:jit:style:inline:src\\app\\pages\\api-client\\components\\request-collections\\request-collections.component.ts;CiAgICA6aG9zdCB7IAogICAgICBoZWlnaHQ6IDEwMCU7IAogICAgICBkaXNwbGF5OiBmbGV4OyAKICAgICAgZmxleC1kaXJlY3Rpb246IGNvbHVtbjsgCiAgICAgIHdpZHRoOiAzMDBweDsgCiAgICAgIGZsZXg6IDAgMCAzMDBweDsgCiAgICB9CiAgICAKICAgIC53cmFwIHsgCiAgICAgIGhlaWdodDogMTAwJTsgCiAgICAgIGRpc3BsYXk6IGZsZXg7IAogICAgICBmbGV4LWRpcmVjdGlvbjogY29sdW1uOyAKICAgICAgYm9yZGVyOiAxcHggc29saWQgcmdiYSgwLCAwLCAwLCAwLjA4KTsgCiAgICAgIGJvcmRlci1yYWRpdXM6IDhweDsgCiAgICAgIG92ZXJmbG93OiBoaWRkZW47IAogICAgICBiYWNrZ3JvdW5kOiAjZmZmOwogICAgfQogICAgCiAgICAuaGVhZGVyIHsKICAgICAgd2lkdGg6IDEwMCU7CiAgICAgIHBhZGRpbmc6IDhweCAxMHB4OwogICAgICBkaXNwbGF5OiBmbGV4OwogICAgICBnYXA6IDZweDsKICAgICAgYWxpZ24taXRlbXM6IGNlbnRlcjsKICAgICAganVzdGlmeS1jb250ZW50OiBzcGFjZS1iZXR3ZWVuOwogICAgICBib3JkZXItYm90dG9tOiAxcHggc29saWQgcmdiYSgwLCAwLCAwLCAwLjA2KTsKICAgICAgZmxleDogMCAwIGF1dG87CiAgICAgIGJhY2tncm91bmQ6ICNmYWZhZmE7CiAgICB9CiAgICAKICAgIC5oZWFkZXIgbnotaW5wdXQtd3JhcHBlciB7CiAgICAgIGZsZXg6IDE7CiAgICAgIG1pbi13aWR0aDogMDsKICAgIH0KICAgIAogICAgLmhlYWRlciBpbnB1dFtuei1pbnB1dF0gewogICAgICBmb250LXNpemU6IDEzcHg7CiAgICB9CiAgICAKICAgIC5oZWFkZXIgYnV0dG9uIHsKICAgICAgd2lkdGg6IDMycHg7CiAgICAgIGhlaWdodDogMzJweDsKICAgICAgcGFkZGluZzogMCAhaW1wb3J0YW50OwogICAgfQogICAgCiAgICAuc2VhcmNoLWljb24gewogICAgICBjb2xvcjogcmdiYSgwLCAwLCAwLCAwLjM1KTsKICAgIH0KICAgIAogICAgLmJvZHkgewogICAgICBmbGV4OiAxIDEgYXV0bzsKICAgICAgaGVpZ2h0OiAwOwogICAgICBkaXNwbGF5OiBmbGV4OwogICAgICBmbGV4LWRpcmVjdGlvbjogY29sdW1uOwogICAgfQogIA==","angular:jit:style:inline:src\\app\\pages\\api-client\\components\\request-collections\\collection-tree.component.ts;CiAgICA6aG9zdC50cmVlLWJvZHkgewogICAgICBmbGV4OiAxIDEgYXV0bzsKICAgICAgaGVpZ2h0OiAwOwogICAgICBvdmVyZmxvdzogYXV0bzsKICAgICAgcGFkZGluZzogOHB4OwogICAgICBkaXNwbGF5OiBmbGV4OwogICAgICBmbGV4LWRpcmVjdGlvbjogY29sdW1uOwogICAgICBnYXA6IDRweDsKICAgIH0KICAgIAogICAgOmhvc3QudHJlZS1ib2R5IC5lbXB0eSB7CiAgICAgIHBhZGRpbmc6IDI0cHggMTZweDsKICAgICAgb3BhY2l0eTogMC41OwogICAgICB0ZXh0LWFsaWduOiBjZW50ZXI7CiAgICAgIGZvbnQtc2l6ZTogMTNweDsKICAgIH0KICA=","angular:jit:style:inline:src\\app\\pages\\api-client\\components\\request-collections\\collection-tree-item.component.ts;CiAgICA6aG9zdC5jdHJlZS1pdGVtIHsgCiAgICAgIGRpc3BsYXk6IGJsb2NrOyAKICAgIH0KICAgIAogICAgLnJvdyB7CiAgICAgIGRpc3BsYXk6IGZsZXg7CiAgICAgIGFsaWduLWl0ZW1zOiBjZW50ZXI7CiAgICAgIGdhcDogNHB4OwogICAgICBwYWRkaW5nOiA2cHggOHB4OwogICAgICBib3JkZXItcmFkaXVzOiA2cHg7CiAgICAgIGN1cnNvcjogcG9pbnRlcjsKICAgICAgdHJhbnNpdGlvbjogYmFja2dyb3VuZC1jb2xvciAwLjJzIGVhc2U7CiAgICB9CiAgICAKICAgIC5yb3c6aG92ZXIgewogICAgICBiYWNrZ3JvdW5kLWNvbG9yOiByZ2JhKDAsIDAsIDAsIDAuMDQpOwogICAgfQogICAgCiAgICAucm93LmFjdGl2ZSB7CiAgICAgIGJhY2tncm91bmQtY29sb3I6ICNlNmY3ZmY7CiAgICB9CiAgICAKICAgIC5yb3cuYWN0aXZlOmhvdmVyIHsKICAgICAgYmFja2dyb3VuZC1jb2xvcjogI2JhZTdmZjsKICAgIH0KICAgIAogICAgLmNoZXYgewogICAgICBmbGV4OiAwIDAgYXV0bzsKICAgICAgd2lkdGg6IDIwcHg7CiAgICAgIGhlaWdodDogMjBweDsKICAgICAgcGFkZGluZzogMCAhaW1wb3J0YW50OwogICAgfQogICAgCiAgICAuY2hldi1pY29uIHsKICAgICAgZm9udC1zaXplOiAxMnB4OwogICAgICB0cmFuc2l0aW9uOiB0cmFuc2Zvcm0gMC4ycyBlYXNlOwogICAgICBjb2xvcjogcmdiYSgwLCAwLCAwLCAwLjQ1KTsKICAgIH0KICAgIAogICAgLmNoZXYtaWNvbi5leHBhbmRlZCB7CiAgICAgIHRyYW5zZm9ybTogcm90YXRlKDkwZGVnKTsKICAgIH0KICAgIAogICAgLm1haW4gewogICAgICBkaXNwbGF5OiBmbGV4OwogICAgICBhbGlnbi1pdGVtczogY2VudGVyOwogICAgICBnYXA6IDhweDsKICAgICAgZmxleDogMTsKICAgICAgbWluLXdpZHRoOiAwOwogICAgfQogICAgCiAgICAuaWNvbiB7CiAgICAgIG9wYWNpdHk6IDAuNjU7CiAgICAgIGZvbnQtc2l6ZTogMTRweDsKICAgIH0KICAgIAogICAgLm1ldGhvZCB7CiAgICAgIGZsZXg6IDAgMCBhdXRvOwogICAgICBmb250LXNpemU6IDEwcHg7CiAgICAgIGZvbnQtd2VpZ2h0OiA2MDA7CiAgICAgIGxpbmUtaGVpZ2h0OiAxLjQ7CiAgICAgIHBhZGRpbmc6IDAgNHB4OwogICAgICBtYXJnaW46IDA7CiAgICB9CiAgICAKICAgIC50ZXh0cyB7CiAgICAgIGZsZXg6IDE7CiAgICAgIG1pbi13aWR0aDogMDsKICAgIH0KICAgIAogICAgLnRpdGxlIHsKICAgICAgZm9udC1zaXplOiAxM3B4OwogICAgICBmb250LXdlaWdodDogNTAwOwogICAgICBvdmVyZmxvdzogaGlkZGVuOwogICAgICB0ZXh0LW92ZXJmbG93OiBlbGxpcHNpczsKICAgICAgd2hpdGUtc3BhY2U6IG5vd3JhcDsKICAgICAgY29sb3I6IHJnYmEoMCwgMCwgMCwgMC44NSk7CiAgICB9CiAgICAKICAgIC5zdWIgewogICAgICBmb250LXNpemU6IDEycHg7CiAgICAgIG9wYWNpdHk6IDAuNTsKICAgICAgb3ZlcmZsb3c6IGhpZGRlbjsKICAgICAgdGV4dC1vdmVyZmxvdzogZWxsaXBzaXM7CiAgICAgIHdoaXRlLXNwYWNlOiBub3dyYXA7CiAgICAgIG1hcmdpbi10b3A6IDJweDsKICAgIH0KICAgIAogICAgLm1vcmUgewogICAgICBmbGV4OiAwIDAgYXV0bzsKICAgICAgd2lkdGg6IDIwcHg7CiAgICAgIGhlaWdodDogMjBweDsKICAgICAgcGFkZGluZzogMCAhaW1wb3J0YW50OwogICAgICB2aXNpYmlsaXR5OiBoaWRkZW47CiAgICAgIG9wYWNpdHk6IDAuNTsKICAgIH0KICAgIAogICAgLm1vcmU6aG92ZXIgewogICAgICBvcGFjaXR5OiAxOwogICAgfQogICAgCiAgICAucm93OmhvdmVyIC5tb3JlIHsKICAgICAgdmlzaWJpbGl0eTogdmlzaWJsZTsKICAgIH0KICAgIAogICAgLmNoaWxkcmVuIHsKICAgICAgbWFyZ2luLWxlZnQ6IDIwcHg7CiAgICAgIHBhZGRpbmctbGVmdDogNHB4OwogICAgICBib3JkZXItbGVmdDogMXB4IGRhc2hlZCByZ2JhKDAsIDAsIDAsIDAuMDgpOwogICAgICBtYXJnaW4tdG9wOiA0cHg7CiAgICAgIGRpc3BsYXk6IGZsZXg7CiAgICAgIGZsZXgtZGlyZWN0aW9uOiBjb2x1bW47CiAgICAgIGdhcDogMnB4OwogICAgfQogIA==","src/app/pages/api-client/components/request-collections/collection-tree-item.component.ts","src/app/pages/api-client/components/request-collections/collection-tree.component.ts","src/app/pages/api-client/components/request-collections/request-collections.component.ts","angular:jit:style:inline:src\\app\\pages\\api-client\\components\\request-editor\\auth-editor.component.ts;CiAgICAgIC53cmFweyBkaXNwbGF5OmZsZXg7IGZsZXgtZGlyZWN0aW9uOmNvbHVtbjsgaGVpZ2h0OjEwMCU7IG1pbi1oZWlnaHQ6MjIwcHg7IH0KICAgICAgLmJhcnsKICAgICAgICBkaXNwbGF5OmZsZXg7IGdhcDoxMHB4OyBhbGlnbi1pdGVtczpjZW50ZXI7CiAgICAgICAgcGFkZGluZzo4cHggMDsgYm9yZGVyLWJvdHRvbToxcHggc29saWQgI2YwZjBmMDsKICAgICAgfQogICAgICAudHlwZXsgd2lkdGg6MTYwcHg7IH0KICAgICAgLmlueyB3aWR0aDoxNDBweDsgfQoKICAgICAgLm1haW57IGZsZXg6MSAxIGF1dG87IG92ZXJmbG93OmF1dG87IHBhZGRpbmctdG9wOjEwcHg7IH0KICAgICAgLmVtcHR5eyBwYWRkaW5nOjEycHg7IG9wYWNpdHk6Ljc7IH0KCiAgICAgIC5ncmlkeyBkaXNwbGF5OmZsZXg7IGZsZXgtZGlyZWN0aW9uOmNvbHVtbjsgZ2FwOjEwcHg7IH0KICAgICAgLnJvd3sgZGlzcGxheTpncmlkOyBncmlkLXRlbXBsYXRlLWNvbHVtbnM6IDEwMHB4IDFmcjsgYWxpZ24taXRlbXM6Y2VudGVyOyBnYXA6MTBweDsgfQogICAgICAucm93LXRvcHsgYWxpZ24taXRlbXM6c3RhcnQ7IH0KICAgICAgLmxhYmVseyBmb250LXNpemU6MTJweDsgb3BhY2l0eTouODsgfQogICAg","node_modules/ng-zorro-antd/fesm2022/ng-zorro-antd-alert.mjs","src/app/pages/api-client/components/request-editor/auth-editor.component.ts","angular:jit:style:inline:src\\app\\pages\\api-client\\components\\request-editor\\body-editor.component.ts;CiAgICAud3JhcHsgZGlzcGxheTpmbGV4OyBmbGV4LWRpcmVjdGlvbjpjb2x1bW47IGhlaWdodDoxMDAlOyBtaW4taGVpZ2h0OjI2MHB4OyB9CiAgICAuYmFyewogICAgICBkaXNwbGF5OmZsZXg7IGdhcDoxMHB4OyBhbGlnbi1pdGVtczpjZW50ZXI7CiAgICAgIHBhZGRpbmc6OHB4IDA7IGJvcmRlci1ib3R0b206MXB4IHNvbGlkICNmMGYwZjA7CiAgICB9CiAgICAubW9kZXsgd2lkdGg6MTQwcHg7IH0KICAgIC5jdHlwZXsgZmxleDoxIDEgYXV0bzsgfQogICAgLm1haW57IGZsZXg6MSAxIGF1dG87IG92ZXJmbG93OmF1dG87IHBhZGRpbmctdG9wOjEwcHg7IH0KICAgIC50YXsgd2lkdGg6MTAwJTsgaGVpZ2h0OjEwMCU7IG1pbi1oZWlnaHQ6MjQwcHg7IGZvbnQtZmFtaWx5OiB1aS1tb25vc3BhY2UsIFNGTW9uby1SZWd1bGFyLCBNZW5sbywgTW9uYWNvLCBDb25zb2xhcywgIkxpYmVyYXRpb24gTW9ubyIsICJDb3VyaWVyIE5ldyIsIG1vbm9zcGFjZTsgZm9udC1zaXplOjEycHg7IH0KICAgIC5lbXB0eXsgcGFkZGluZzoxMnB4OyBvcGFjaXR5Oi43OyB9CiAgICAuZXJyeyBtYXJnaW4tdG9wOjhweDsgY29sb3I6I2E4MDcxYTsgZm9udC1zaXplOjEycHg7IH0KICA=","angular:jit:style:inline:src\\app\\pages\\api-client\\components\\request-editor\\kv-table.component.ts;CiAgICAua3Ytd3JhcHsgZGlzcGxheTpmbGV4OyBmbGV4LWRpcmVjdGlvbjpjb2x1bW47IGhlaWdodDoxMDAlOyB9CiAgICAua3YtdG9vbGJhcnsKICAgICAgcGFkZGluZzo4cHggMDsKICAgICAgZGlzcGxheTpmbGV4OwogICAgICBqdXN0aWZ5LWNvbnRlbnQ6c3BhY2UtYmV0d2VlbjsKICAgICAgYWxpZ24taXRlbXM6Y2VudGVyOwogICAgICBnYXA6MTBweDsKICAgIH0KICAgIC5rdi10b29sYmFyIC5sZWZ0LCAua3YtdG9vbGJhciAucmlnaHR7IGRpc3BsYXk6ZmxleDsgZ2FwOjhweDsgYWxpZ24taXRlbXM6Y2VudGVyOyB9CiAgICAuaGludHsgZm9udC1zaXplOjEycHg7IG9wYWNpdHk6Ljc7IH0KCiAgICAua3YtaGVhZHsKICAgICAgZGlzcGxheTpncmlkOwogICAgICBncmlkLXRlbXBsYXRlLWNvbHVtbnM6IDQwcHggMWZyIDFmciAyZnIgNDRweDsKICAgICAgZ2FwOjhweDsKICAgICAgcGFkZGluZzo2cHggMDsKICAgICAgZm9udC1zaXplOjE0cHg7CiAgICAgIGJvcmRlci1ib3R0b206MXB4IHNvbGlkICNmMGYwZjA7CiAgICAgIGFsaWduLWl0ZW1zOmNlbnRlcjsKICAgICAgLmMta2V5LCAuYy12YWwsIC5jLWRlc3sKICAgICAgICBvcGFjaXR5Oi43NTsKICAgICAgfQogICAgfQoKICAgIC5rdi1ib2R5ewogICAgICBmbGV4OjEgMSBhdXRvOwogICAgICBvdmVyZmxvdzphdXRvOwogICAgICBwYWRkaW5nOjhweCAwOwogICAgfQoKICAgIC5rdi1yb3d7CiAgICAgIGRpc3BsYXk6Z3JpZDsKICAgICAgZ3JpZC10ZW1wbGF0ZS1jb2x1bW5zOiA0MHB4IDFmciAxZnIgMmZyIDQ0cHg7CiAgICAgIGdhcDo4cHg7CiAgICAgIGFsaWduLWl0ZW1zOmNlbnRlcjsKICAgICAgcGFkZGluZzo2cHggMDsKICAgICAgYm9yZGVyLWJvdHRvbToxcHggZGFzaGVkICNmMGYwZjA7CiAgICB9CgogICAgLmMtY2hlY2t7IGRpc3BsYXk6ZmxleDsganVzdGlmeS1jb250ZW50OmNlbnRlcjsgfQogICAgLmMtb3B7IGRpc3BsYXk6ZmxleDsganVzdGlmeS1jb250ZW50OmNlbnRlcjsgfQoKICAgIC5rdi1lbXB0eXsKICAgICAgcGFkZGluZzoxNnB4OwogICAgICBvcGFjaXR5Oi43NTsKICAgICAgZGlzcGxheTpmbGV4OwogICAgICBhbGlnbi1pdGVtczpjZW50ZXI7CiAgICAgIGp1c3RpZnktY29udGVudDpzcGFjZS1iZXR3ZWVuOwogICAgICBib3JkZXI6MXB4IGRhc2hlZCAjZThlOGU4OwogICAgICBib3JkZXItcmFkaXVzOjhweDsKICAgICAgbWFyZ2luLXRvcDo4cHg7CiAgICB9CiAg","src/app/pages/api-client/components/request-editor/kv-table.component.ts","src/app/pages/api-client/components/request-editor/body-editor.component.ts","angular:jit:style:inline:src\\app\\pages\\api-client\\components\\request-editor\\env-picker.component.ts;CiAgICAucGlja2VyeyBkaXNwbGF5OmZsZXg7IGdhcDo4cHg7IGFsaWduLWl0ZW1zOmNlbnRlcjsgfQogICAgLnNlbHsgd2lkdGg6MTYwcHg7IH0KICA=","src/app/pages/api-client/services/api-client-state.service.ts","src/app/pages/api-client/store/api-client-tab.store.ts","src/app/pages/api-client/utils/variable-resolver.ts","src/app/pages/api-client/utils/sync-path-params.ts","src/app/pages/api-client/utils/env-mapper.ts","src/app/pages/api-client/utils/collection-node.ts","src/app/pages/api-client/services/api-client.service.ts","angular:jit:style:inline:src\\app\\pages\\api-client\\components\\request-collections\\collection-modal.component.ts;CiAgICAubW9kYWwtYm9keSB7IGRpc3BsYXk6IGdyaWQ7IGdhcDogMTJweDsgfQogICAgLmxhYmVseyBmb250LXdlaWdodDo2MDA7IH0KICAgIC5oaW50IHsgZm9udC1zaXplOiAxMnB4OyBvcGFjaXR5OiAuNzU7IH0KICAgIC5oaW50LmVycnsgY29sb3I6I2NmMTMyMjsgb3BhY2l0eToxOyB9CgogICAgLnBpY2tlcnsKICAgICAgbWF4LWhlaWdodDogNTJ2aDsKICAgICAgb3ZlcmZsb3c6YXV0bzsKICAgICAgYm9yZGVyOiAxcHggc29saWQgcmdiYSgwLDAsMCwuMDgpOwogICAgICBib3JkZXItcmFkaXVzOiAxMnB4OwogICAgICBwYWRkaW5nOiA4cHg7CiAgICAgIGRpc3BsYXk6ZmxleDsKICAgICAgZmxleC1kaXJlY3Rpb246Y29sdW1uOwogICAgICBnYXA6NnB4OwogICAgfQogICAgLnJvd3sKICAgICAgZGlzcGxheTpmbGV4OwogICAgICBhbGlnbi1pdGVtczpjZW50ZXI7CiAgICAgIGdhcDo4cHg7CiAgICAgIHBhZGRpbmc6OHB4IDhweDsKICAgICAgYm9yZGVyLXJhZGl1czoxMHB4OwogICAgICBjdXJzb3I6cG9pbnRlcjsKICAgICAgdXNlci1zZWxlY3Q6bm9uZTsKICAgICAgdHJhbnNpdGlvbjogYmFja2dyb3VuZCAuMTVzOwogICAgICBib3JkZXI6IDFweCBzb2xpZCB0cmFuc3BhcmVudDsKICAgIH0KICAgIC5yb3c6aG92ZXJ7IGJhY2tncm91bmQ6IHJnYmEoMCwwLDAsLjA0KTsgfQogICAgLnJvdy5zZWxlY3RlZHsgYmFja2dyb3VuZDogcmdiYSgwLDAsMCwuMDgpOyBib3JkZXItY29sb3I6IHJnYmEoMCwwLDAsLjA4KTsgfQogICAgLnJvdy5yb290eyBmb250LXdlaWdodDo2MDA7IH0KICAgIC5jaGV2eyBmbGV4OjAgMCBhdXRvOyBuei1pY29ue2ZvbnQtc2l6ZToxMnB4O3RyYW5zaXRpb246dHJhbnNmb3JtIC4xNXN9IH0KICAgIC5pY29ueyBvcGFjaXR5Oi43NTsgfQogICAgLnRpdGxleyBmbGV4OjE7IG1pbi13aWR0aDowOyBvdmVyZmxvdzpoaWRkZW47IHRleHQtb3ZlcmZsb3c6ZWxsaXBzaXM7IHdoaXRlLXNwYWNlOm5vd3JhcDsgfQogICAgLmVtcHR5eyBwYWRkaW5nOjE2cHg7IG9wYWNpdHk6LjY7IHRleHQtYWxpZ246Y2VudGVyOyB9CgogICAgLmZvb3RlciB7IGRpc3BsYXk6IGZsZXg7IGp1c3RpZnktY29udGVudDogZmxleC1lbmQ7IGdhcDogOHB4OyBtYXJnaW4tdG9wOiAxNnB4OyB9CiAg","src/app/pages/api-client/components/request-collections/collection-modal.component.ts","src/app/pages/api-client/services/collection-modal.service.ts","angular:jit:style:inline:src\\app\\pages\\api-client\\components\\request-editor\\env-modal.component.ts;CiAgICAuZHJhd2VyeyBkaXNwbGF5OmdyaWQ7IGdyaWQtdGVtcGxhdGUtY29sdW1uczogMTgwcHggMWZyOyBnYXA6MTJweDsgaGVpZ2h0OjEwMCU7IH0KICAgIC5sZWZ0eyBib3JkZXItcmlnaHQ6MXB4IHNvbGlkICNmMGYwZjA7IHBhZGRpbmctcmlnaHQ6MTJweDsgfQogICAgLnRvb2xiYXJ7IHBhZGRpbmctYm90dG9tOjEwcHg7IH0KICAgIC5lbnYtbGlzdHsgZGlzcGxheTpmbGV4OyBmbGV4LWRpcmVjdGlvbjpjb2x1bW47IGdhcDo4cHg7IH0KICAgIC5lbnYtaXRlbXsgcGFkZGluZzo4cHg7IGJvcmRlcjoxcHggc29saWQgI2YwZjBmMDsgYm9yZGVyLXJhZGl1czo4cHg7IGN1cnNvcjpwb2ludGVyOyB9CiAgICAuZW52LWl0ZW0uYWN0aXZleyBiYWNrZ3JvdW5kOiNmNWY1ZjU7IH0KICAgIC5uYW1leyBmb250LXdlaWdodDo2MDA7IH0KICAgIC5tZXRheyBmb250LXNpemU6MTJweDsgb3BhY2l0eTouNzsgfQogICAgLnJpZ2h0eyBtaW4td2lkdGg6MDsgfQogICAgLmVtcHR5eyBwYWRkaW5nOjEycHg7IG9wYWNpdHk6Ljc7IH0KICAgIC5yb3d7IGRpc3BsYXk6Z3JpZDsgZ3JpZC10ZW1wbGF0ZS1jb2x1bW5zOiA3MHB4IDFmcjsgZ2FwOjEwcHg7IGFsaWduLWl0ZW1zOmNlbnRlcjsgbWFyZ2luLWJvdHRvbToxMHB4OyB9CiAgICAubGFiZWx7IGZvbnQtc2l6ZToxNHB4OyBvcGFjaXR5Oi44OyB9CiAgICAudmFyc3sgaGVpZ2h0OiA0MjBweDsgfQogICAgLmFjdGlvbnN7IGRpc3BsYXk6ZmxleDsgZ2FwOjhweDsgbWFyZ2luLXRvcDoxMnB4OyB9CiAg","src/app/pages/api-client/components/request-editor/env-modal.component.ts","src/app/pages/api-client/components/request-editor/env-picker.component.ts","angular:jit:style:inline:src\\app\\pages\\api-client\\components\\request-editor\\request-tabs.component.ts;CiAgICAgIDpob3N0eyBkaXNwbGF5OmZsZXg7IGZsZXgtZGlyZWN0aW9uOmNvbHVtbjsgaGVpZ2h0OjEwMCU7IG1pbi1oZWlnaHQ6MDsgfQogICAgICBhcHAta3YtdGFibGV7CiAgICAgICAgZGlzcGxheTogYmxvY2s7CiAgICAgICAgaGVpZ2h0OiAxMDAlOwogICAgICB9CiAgICAgIC50YWJzICB7CiAgICAgICAgICBmbGV4OiAxIDEgYXV0bzsKICAgICAgICAgIG92ZXJmbG93OiBoaWRkZW47CiAgICAgICAgICBoZWlnaHQ6IDEwMCU7CiAgICAgIH0KICAgICAgLnRhYnsKICAgICAgICBoZWlnaHQ6IDEwMCU7CiAgICAgICAgb3ZlcmZsb3c6IGhpZGRlbiBhdXRvOwogICAgICB9CiAgICAgIDo6bmctZGVlcCBuei10YWJzLnRhYnN7CiAgICAgICAgLmFudC10YWJzLWNvbnRlbnR7CiAgICAgICAgICBoZWlnaHQ6IDEwMCU7CiAgICAgICAgICAuYW50LXRhYnMtdGFicGFuZXsKICAgICAgICAgICAgaGVpZ2h0OjEwMCU7CiAgICAgICAgICB9CiAgICAgICAgfQogICAgICB9CiAgICA=","angular:jit:style:inline:src\\app\\pages\\api-client\\components\\request-editor\\advanced-editor.component.ts;CiAgICAud3JhcHsKICAgICAgZGlzcGxheTpmbGV4OwogICAgICBmbGV4LWRpcmVjdGlvbjpjb2x1bW47CiAgICAgIGhlaWdodDoxMDAlOwogICAgICBtaW4taGVpZ2h0OjI0MHB4OwogICAgfQoKICAgIC5ncmlkewogICAgICBkaXNwbGF5OmZsZXg7CiAgICAgIGZsZXgtZGlyZWN0aW9uOmNvbHVtbjsKICAgICAgZ2FwOjE0cHg7CiAgICAgIHBhZGRpbmctdG9wOjEwcHg7CiAgICB9CgogICAgLnJvd3sKICAgICAgZGlzcGxheTpncmlkOwogICAgICBncmlkLXRlbXBsYXRlLWNvbHVtbnM6IDE0MHB4IDFmcjsKICAgICAgYWxpZ24taXRlbXM6Y2VudGVyOwogICAgICBnYXA6MTBweDsKICAgIH0KCiAgICAucm93LmNoZWNrYm94ewogICAgICBncmlkLXRlbXBsYXRlLWNvbHVtbnM6IDFmcjsKICAgIH0KCiAgICAubGFiZWx7CiAgICAgIGZvbnQtc2l6ZToxMnB4OwogICAgICBvcGFjaXR5Oi44OwogICAgfQoKICAgIC5kZXNjewogICAgICBncmlkLWNvbHVtbjogMiAvIHNwYW4gMTsKICAgICAgZm9udC1zaXplOjEycHg7CiAgICAgIG9wYWNpdHk6LjY1OwogICAgfQoKICAgIC5yb3cuY2hlY2tib3ggLmRlc2N7CiAgICAgIGdyaWQtY29sdW1uOiAxIC8gc3BhbiAxOwogICAgICBtYXJnaW4tbGVmdDoyNHB4OwogICAgfQoKICAgIC5tdXRlZHsKICAgICAgY29sb3I6Izk5OTsKICAgIH0KICA=","src/app/pages/api-client/components/request-editor/advanced-editor.component.ts","src/app/pages/api-client/components/request-editor/request-tabs.component.ts","angular:jit:style:inline:src\\app\\pages\\api-client\\components\\request-editor\\request-editor.component.ts;CiAgICA6aG9zdHsgZGlzcGxheTogZmxleDsgZmxleC1kaXJlY3Rpb246IGNvbHVtbjt9CiAgICAubmFtZXsgcGFkZGluZzoxMHB4OyBib3JkZXItYm90dG9tOjFweCBzb2xpZCAjZjBmMGYwOyB9CiAgICAudGFic3sgZmxleDoxIDEgYXV0bzsgb3ZlcmZsb3c6aGlkZGVuOyBwYWRkaW5nOjAgMTBweDsgfQogICAgYXBwLXJlcXVlc3QtdGFic3tmbGV4OjEgMSBhdXRvOyBoZWlnaHQ6MDt9CiAg","angular:jit:style:inline:src\\app\\pages\\api-client\\components\\request-editor\\request-urlbar.component.ts;CiAgICAuYmFyewogICAgICBkaXNwbGF5OmZsZXg7CiAgICAgIGdhcDoxMHB4OwogICAgICBwYWRkaW5nOjEwcHg7CiAgICAgIGJvcmRlci1ib3R0b206MXB4IHNvbGlkICNmMGYwZjA7CiAgICAgIGFsaWduLWl0ZW1zOmNlbnRlcjsKICAgIH0KICAgIC5tZXRob2R7IHdpZHRoOjEyMHB4OyB9CiAgICAudXJseyBmbGV4OjEgMSBhdXRvOyB9CiAgICAudmFyLWhpbnR7CiAgICAgIHBhZGRpbmc6IDRweCAxMHB4IDhweDsKICAgICAgZm9udC1zaXplOiAxMnB4OwogICAgICBkaXNwbGF5OiBmbGV4OwogICAgICBnYXA6IDhweDsKICAgICAgYWxpZ24taXRlbXM6IGNlbnRlcjsKICAgIH0KICA=","src/app/pages/api-client/components/request-editor/request-urlbar.component.ts","src/app/pages/api-client/components/request-editor/request-editor.component.ts","angular:jit:style:inline:src\\app\\pages\\api-client\\components\\response-viewer\\curl-actions.component.ts;","src/app/pages/api-client/components/response-viewer/curl-actions.component.ts","angular:jit:style:inline:src\\app\\pages\\api-client\\components\\response-viewer\\response-viewer.component.ts;CiAgICA6aG9zdHsgZGlzcGxheTpmbGV4OyBoZWlnaHQ6MTAwJTsgbWluLWhlaWdodDowOyB9CiAgICAud3JhcHsgZGlzcGxheTpmbGV4OyBmbGV4LWRpcmVjdGlvbjpjb2x1bW47IGhlaWdodDoxMDAlOyBtaW4taGVpZ2h0OjA7IHdpZHRoOjEwMCU7IH0KCiAgICAudG9wewogICAgICBkaXNwbGF5OmZsZXg7CiAgICAgIGp1c3RpZnktY29udGVudDpzcGFjZS1iZXR3ZWVuOwogICAgICBhbGlnbi1pdGVtczpjZW50ZXI7CiAgICAgIHBhZGRpbmc6MTBweCAxMnB4OwogICAgICBib3JkZXItYm90dG9tOjFweCBzb2xpZCAjZjBmMGYwOwogICAgfQogICAgLmxlZnR7IGRpc3BsYXk6ZmxleDsgZ2FwOjEwcHg7IGFsaWduLWl0ZW1zOmNlbnRlcjsgfQogICAgLnRpdGxleyBmb250LXdlaWdodDo3MDA7IH0KICAgIC5tZXRheyBmb250LXNpemU6MTJweDsgb3BhY2l0eTouNjU7IH0KCiAgICAubG9hZGluZ3sgcGFkZGluZzoxNnB4OyB9CiAgICAuZW1wdHl7IHBhZGRpbmc6MTZweDsgb3BhY2l0eTouNjsgfQoKICAgIC50YWJzeyBmbGV4OjEgMSBhdXRvOyBtaW4taGVpZ2h0OjA7IH0KICAgIC5wYW5leyBoZWlnaHQ6MTAwJTsgbWluLWhlaWdodDowOyBvdmVyZmxvdzphdXRvOyBwYWRkaW5nOjEwcHggMTJweDsgfQoKICAgIC5jb2RlewogICAgICBtYXJnaW46MDsKICAgICAgZm9udC1mYW1pbHk6IHVpLW1vbm9zcGFjZSwgU0ZNb25vLVJlZ3VsYXIsIE1lbmxvLCBNb25hY28sIENvbnNvbGFzLCAiTGliZXJhdGlvbiBNb25vIiwgIkNvdXJpZXIgTmV3IiwgbW9ub3NwYWNlOwogICAgICBmb250LXNpemU6MTJweDsKICAgICAgbGluZS1oZWlnaHQ6MS41OwogICAgICB3aGl0ZS1zcGFjZTpwcmUtd3JhcDsKICAgICAgd29yZC1icmVhazpicmVhay13b3JkOwogICAgfQoKICAgIC5obGlzdHsgZGlzcGxheTpmbGV4OyBmbGV4LWRpcmVjdGlvbjpjb2x1bW47IGdhcDo4cHg7IH0KICAgIC5ocm93ewogICAgICBkaXNwbGF5OmdyaWQ7CiAgICAgIGdyaWQtdGVtcGxhdGUtY29sdW1uczogMjAwcHggMWZyOwogICAgICBnYXA6MTBweDsKICAgICAgcGFkZGluZzo4cHg7CiAgICAgIGJvcmRlcjoxcHggc29saWQgI2YwZjBmMDsKICAgICAgYm9yZGVyLXJhZGl1czo4cHg7CiAgICB9CiAgICAuaGt7IGZvbnQtd2VpZ2h0OjYwMDsgZm9udC1zaXplOjEycHg7IH0KICAgIC5odnsgZm9udC1zaXplOjEycHg7IG9wYWNpdHk6Ljg1OyB3b3JkLWJyZWFrOmJyZWFrLXdvcmQ7IH0KICA=","src/app/pages/api-client/components/response-viewer/response-viewer.component.ts","angular:jit:template:src\\app\\pages\\api-client\\components\\request-tabs-bar\\request-tabs-bar.component.html","angular:jit:style:src\\app\\pages\\api-client\\components\\request-tabs-bar\\request-tabs-bar.component.less","src/app/pages/api-client/components/request-tabs-bar/request-tabs-bar.component.ts","src/app/pages/api-client/api-client.component.ts","src/app/pages/api-client/api-client-routing.module.ts","src/app/pages/api-client/api-client.module.ts"],"sourcesContent":["/* angular:styles/component:less;43d540c6ba4e6e48b509c83db85e36183929b3703b772c49b4f9f3fa50efdf2e;D:\\ng-manager\\webapp\\src\\app\\pages\\api-client\\api-client.component.ts */\n.page {\n height: 100%;\n display: flex;\n flex-direction: row;\n overflow: hidden;\n gap: 16px;\n padding: 0 16px;\n}\n.content {\n flex: 1 1 auto;\n width: 0;\n display: flex;\n flex-direction: column;\n height: 100%;\n overflow: hidden;\n}\n.editor-area {\n flex: 1 1 auto;\n display: flex;\n flex-direction: column;\n min-height: 0;\n}\napp-request-editor {\n flex: 0 0 auto;\n height: 50%;\n}\napp-response-viewer {\n flex: 0 0 auto;\n height: 50%;\n overflow: auto;\n}\n/*# sourceMappingURL=api-client.component.css.map */\n","/* angular:styles/component:less;d7b4f4dbc085d63893d028214b767bd20de371e514440bbc69820402fa10f93a;D:\\ng-manager\\webapp\\src\\app\\pages\\api-client\\components\\history\\api-history-drawer.component.ts */\n.list {\n display: flex;\n flex-direction: column;\n gap: 12px;\n}\n.item {\n border: 1px solid #f0f0f0;\n border-radius: 8px;\n padding: 10px;\n}\n.row {\n display: flex;\n gap: 8px;\n align-items: center;\n font-weight: 500;\n}\n.url {\n flex: 1;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n.meta {\n margin-top: 6px;\n display: flex;\n gap: 8px;\n font-size: 12px;\n opacity: 0.7;\n}\n.actions {\n margin-top: 8px;\n display: flex;\n gap: 8px;\n}\n.empty {\n padding: 16px;\n opacity: 0.6;\n text-align: center;\n}\n/*# sourceMappingURL=api-history-drawer.component.css.map */\n","import { CommonModule } from '@angular/common';\r\nimport { Component, EventEmitter, Input, Output } from '@angular/core';\r\nimport { NzDrawerModule } from 'ng-zorro-antd/drawer';\r\nimport { NzButtonModule } from 'ng-zorro-antd/button';\r\nimport { NzSpinModule } from 'ng-zorro-antd/spin';\r\nimport { NzTagModule } from 'ng-zorro-antd/tag';\r\n\r\nimport type { ApiHistoryEntity } from '@models/api-client/api-history.model';\r\n\r\n@Component({\r\n selector: 'app-api-history-drawer',\r\n standalone: true,\r\n imports: [\r\n CommonModule,\r\n NzDrawerModule,\r\n NzButtonModule,\r\n NzSpinModule,\r\n NzTagModule,\r\n ],\r\n template: `\r\n <nz-drawer\r\n nzTitle=\"请求历史\"\r\n [nzVisible]=\"true\"\r\n nzPlacement=\"right\"\r\n [nzWidth]=\"520\"\r\n (nzOnClose)=\"close.emit()\"\r\n >\r\n <ng-container *nzDrawerContent>\r\n @if(loading){\r\n <nz-spin />\r\n } @else {\r\n <div class=\"list\">\r\n @for (h of histories; track h.id) {\r\n <div class=\"item\">\r\n <div class=\"row\">\r\n <nz-tag>{{h.requestSnapshot.method}}</nz-tag>\r\n <span class=\"url\">{{h.requestSnapshot.url}}</span>\r\n </div>\r\n\r\n <div class=\"meta\">\r\n <span>{{h.metrics.durationMs}} ms</span>\r\n @if(h.response){\r\n <nz-tag>HTTP {{h.response.status}}</nz-tag>\r\n }\r\n @if(h.error){\r\n <nz-tag nzColor=\"red\">ERR</nz-tag>\r\n }\r\n </div>\r\n\r\n <div class=\"actions\">\r\n <button nz-button nzSize=\"small\" (click)=\"replay.emit(h)\">重放</button>\r\n @if(h.resolved.curl){\r\n <button nz-button nzSize=\"small\" (click)=\"copy(h.resolved.curl.bash)\">curl</button>\r\n }\r\n </div>\r\n </div>\r\n }\r\n\r\n @if(!histories.length){\r\n <div class=\"empty\">暂无历史记录</div>\r\n }\r\n </div>\r\n }\r\n </ng-container>\r\n </nz-drawer>\r\n `,\r\n styles: [`\r\n .list{\r\n display:flex;\r\n flex-direction:column;\r\n gap:12px;\r\n }\r\n .item{\r\n border:1px solid #f0f0f0;\r\n border-radius:8px;\r\n padding:10px;\r\n }\r\n .row{\r\n display:flex;\r\n gap:8px;\r\n align-items:center;\r\n font-weight:500;\r\n }\r\n .url{\r\n flex:1;\r\n overflow:hidden;\r\n text-overflow:ellipsis;\r\n white-space:nowrap;\r\n }\r\n .meta{\r\n margin-top:6px;\r\n display:flex;\r\n gap:8px;\r\n font-size:12px;\r\n opacity:.7;\r\n }\r\n .actions{\r\n margin-top:8px;\r\n display:flex;\r\n gap:8px;\r\n }\r\n .empty{\r\n padding:16px;\r\n opacity:.6;\r\n text-align:center;\r\n }\r\n `],\r\n})\r\nexport class ApiHistoryDrawerComponent {\r\n @Input() loading = false;\r\n @Input() histories: ApiHistoryEntity[] = [];\r\n\r\n @Output() close = new EventEmitter<void>();\r\n @Output() replay = new EventEmitter<ApiHistoryEntity>();\r\n\r\n copy(text: string) {\r\n navigator.clipboard.writeText(text);\r\n }\r\n}\r\n","/* angular:styles/component:less;ae07397b8578d7f6bec40f1ea1a29780a45a5679bc745311900bac751387d82b;D:\\ng-manager\\webapp\\src\\app\\pages\\api-client\\components\\request-collections\\request-list.component.ts */\n.list {\n display: flex;\n flex-direction: column;\n gap: 8px;\n padding: 10px;\n}\n.row1 {\n display: flex;\n gap: 8px;\n align-items: center;\n}\n.method {\n margin: 0;\n}\n.name {\n font-weight: 600;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n flex: 1;\n min-width: 0;\n}\n.row2 {\n margin-top: 6px;\n font-size: 12px;\n opacity: 0.75;\n}\n.url {\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n display: block;\n}\n.row3 {\n margin-top: 6px;\n font-size: 12px;\n opacity: 0.55;\n}\n.empty {\n padding: 16px;\n opacity: 0.6;\n text-align: center;\n}\n/*# sourceMappingURL=request-list.component.css.map */\n","/* angular:styles/component:less;fa00256422daa02f76d2e7176add9a62a7c1e427676c0200d0ada9f3a2f19e2c;D:\\ng-manager\\webapp\\src\\app\\pages\\api-client\\components\\request-collections\\request-list-item.component.ts */\n:host.request-item {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 8px;\n padding: 8px 10px;\n border-radius: 6px;\n cursor: pointer;\n transition: background-color 0.2s ease;\n}\n:host.request-item:hover {\n background-color: rgba(0, 0, 0, 0.04);\n}\n:host.request-item.active {\n background-color: #e6f7ff;\n}\n:host.request-item.active:hover {\n background-color: #bae7ff;\n}\n.content {\n display: flex;\n align-items: center;\n gap: 8px;\n flex: 1;\n overflow: hidden;\n}\nbutton.more-actions {\n flex: 0 0 auto;\n width: 20px;\n height: 20px;\n padding: 0 !important;\n visibility: hidden;\n opacity: 0.5;\n}\nbutton.more-actions:hover {\n opacity: 1;\n}\n:host.request-item:hover button.more-actions {\n visibility: visible;\n}\n.method {\n flex: 0 0 auto;\n font-size: 10px;\n font-weight: 600;\n line-height: 1.4;\n padding: 0 4px;\n margin: 0;\n}\n.name {\n flex: 1 1 auto;\n font-size: 13px;\n font-weight: 500;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n color: rgba(0, 0, 0, 0.85);\n}\n.menu-item {\n display: flex;\n align-items: center;\n}\n/*# sourceMappingURL=request-list-item.component.css.map */\n","import { CommonModule } from '@angular/common';\r\nimport { Component, EventEmitter, Input, Output } from '@angular/core';\r\nimport { ApiRequestEntity } from '@models/api-client/api-request.model';\r\nimport { NzButtonModule } from 'ng-zorro-antd/button';\r\nimport { NzIconModule } from 'ng-zorro-antd/icon';\r\nimport { NzMenuModule } from 'ng-zorro-antd/menu';\r\nimport { NzPopoverModule } from 'ng-zorro-antd/popover';\r\nimport { NzTagModule } from 'ng-zorro-antd/tag';\r\nimport { NzTooltipModule } from 'ng-zorro-antd/tooltip';\r\n\r\n/**\r\n * 请求列表项组件\r\n */\r\n@Component({\r\n selector: 'app-request-list-item',\r\n imports: [CommonModule, NzTagModule, NzIconModule, NzButtonModule, NzPopoverModule, NzMenuModule, NzTooltipModule],\r\n host: {\r\n '[class.request-item]': 'true',\r\n '[class.active]': 'r.id === activeId',\r\n '(click)': '$event.stopPropagation();select.emit(r.id)',\r\n '(mouseover)': '$event.stopPropagation();mouseover=true',\r\n '(mouseleave)': '$event.stopPropagation();mouseover=false',\r\n },\r\n template: `\r\n <div class=\"content\" [nz-tooltip]=\"r.url\" [nzTooltipTrigger]=\"'hover'\" nzTooltipPlacement=\"right\">\r\n <nz-tag class=\"method\" [nzColor]=\"getMethodColor(r.method)\">{{r.method}}</nz-tag>\r\n <span class=\"name\">{{r.name || '未命名'}}</span>\r\n </div>\r\n <button class=\"more-actions\" nz-button nzType=\"text\" nzSize=\"small\" (click)=\"$event.stopPropagation();\" \r\n nz-popover \r\n nzPopoverTrigger=\"click\" \r\n [nzPopoverContent]=\"contentTemplate\" \r\n nzPopoverPlacement=\"topRight\" \r\n [nzPopoverOverlayClassName]=\"'project-item-popover'\"> \r\n <nz-icon nzType=\"more\" nzTheme=\"outline\" /> \r\n </button>\r\n <ng-template #contentTemplate>\r\n <ul nz-menu>\r\n <li nz-menu-item class=\"menu-item\">\r\n <nz-icon nzType=\"edit\" nzTheme=\"outline\" />\r\n <span>重命名</span>\r\n </li>\r\n <li nz-menu-item class=\"menu-item\">\r\n <nz-icon nzType=\"folder\" nzTheme=\"outline\" />\r\n <span>移动到</span>\r\n </li>\r\n <li nz-menu-item class=\"menu-item\">\r\n <nz-icon nzType=\"export\" nzTheme=\"outline\" />\r\n <span>导出</span>\r\n </li>\r\n <li nz-menu-item class=\"menu-item\">\r\n <nz-icon nzType=\"copy\" nzTheme=\"outline\" />\r\n <span>复制cURL</span>\r\n </li>\r\n <li nz-menu-divider></li>\r\n <li nz-menu-item nzDanger class=\"menu-item\" (click)=\"delete.emit(r.id)\">\r\n <nz-icon nzType=\"delete\"></nz-icon>\r\n <span>删除</span>\r\n </li>\r\n </ul>\r\n </ng-template>\r\n `,\r\n styles: [\r\n `\r\n :host.request-item {\r\n display: flex;\r\n align-items: center;\r\n justify-content: space-between;\r\n gap: 8px;\r\n padding: 8px 10px;\r\n border-radius: 6px;\r\n cursor: pointer;\r\n transition: background-color 0.2s ease;\r\n }\r\n \r\n :host.request-item:hover {\r\n background-color: rgba(0, 0, 0, 0.04);\r\n }\r\n \r\n :host.request-item.active {\r\n background-color: #e6f7ff;\r\n }\r\n \r\n :host.request-item.active:hover {\r\n background-color: #bae7ff;\r\n }\r\n \r\n .content {\r\n display: flex;\r\n align-items: center;\r\n gap: 8px;\r\n flex: 1;\r\n overflow: hidden;\r\n }\r\n \r\n button.more-actions {\r\n flex: 0 0 auto;\r\n width: 20px;\r\n height: 20px;\r\n padding: 0 !important;\r\n visibility: hidden;\r\n opacity: 0.5;\r\n }\r\n \r\n button.more-actions:hover {\r\n opacity: 1;\r\n }\r\n \r\n :host.request-item:hover button.more-actions {\r\n visibility: visible;\r\n }\r\n \r\n .method {\r\n flex: 0 0 auto;\r\n font-size: 10px;\r\n font-weight: 600;\r\n line-height: 1.4;\r\n padding: 0 4px;\r\n margin: 0;\r\n }\r\n \r\n .name {\r\n flex: 1 1 auto;\r\n font-size: 13px;\r\n font-weight: 500;\r\n overflow: hidden;\r\n text-overflow: ellipsis;\r\n white-space: nowrap;\r\n color: rgba(0, 0, 0, 0.85);\r\n }\r\n \r\n .menu-item {\r\n display: flex;\r\n align-items: center;\r\n }\r\n `\r\n ],\r\n})\r\nexport class RequestListItemComponent {\r\n @Input() r!: ApiRequestEntity;\r\n @Input() activeId: string | null = null;\r\n @Output() select = new EventEmitter<string>();\r\n @Output() delete = new EventEmitter<string>();\r\n\r\n mouseover: boolean = false;\r\n\r\n /**\r\n * 获取方法对应的颜色\r\n */\r\n getMethodColor(method: string): string {\r\n const colors: Record<string, string> = {\r\n GET: '#61affe',\r\n POST: '#49cc90',\r\n PUT: '#fca130',\r\n PATCH: '#50e3c2',\r\n DELETE: '#f93e3e',\r\n HEAD: '#909090',\r\n OPTIONS: '#909090',\r\n };\r\n return colors[method.toUpperCase()] || '#909090';\r\n }\r\n}\r\n","import { CommonModule } from '@angular/common';\r\nimport { Component, EventEmitter, Input, Output } from '@angular/core';\r\nimport { NzTagModule } from 'ng-zorro-antd/tag';\r\nimport { NzIconModule } from 'ng-zorro-antd/icon';\r\n\r\nimport type { ApiRequestEntity } from '@models/api-client/api-request.model';\r\nimport { RequestListItemComponent } from './request-list-item.component';\r\n\r\n@Component({\r\n selector: 'app-request-list',\r\n standalone: true,\r\n imports: [CommonModule, NzTagModule, NzIconModule, RequestListItemComponent],\r\n template: `\r\n <div class=\"list\">\r\n @for (r of requests; track r.id) {\r\n <app-request-list-item [r]=\"r\" [activeId]=\"activeId\" (select)=\"select.emit($event)\" />\r\n }\r\n @if(!requests.length){\r\n <div class=\"empty\">暂无请求</div>\r\n }\r\n </div>\r\n `,\r\n styles: [`\r\n .list{ display:flex; flex-direction:column; gap:8px; padding:10px; }\r\n \r\n .row1{ display:flex; gap:8px; align-items:center; }\r\n .method{ margin:0; }\r\n .name{\r\n font-weight:600;\r\n overflow:hidden;\r\n text-overflow:ellipsis;\r\n white-space:nowrap;\r\n flex:1;\r\n min-width:0;\r\n }\r\n .row2{ margin-top:6px; font-size:12px; opacity:.75; }\r\n .url{\r\n overflow:hidden;\r\n text-overflow:ellipsis;\r\n white-space:nowrap;\r\n display:block;\r\n }\r\n .row3{ margin-top:6px; font-size:12px; opacity:.55; }\r\n .empty{ padding:16px; opacity:.6; text-align:center; }\r\n `],\r\n})\r\nexport class RequestListComponent {\r\n @Input() requests: ApiRequestEntity[] = [];\r\n @Input() activeId: string | null = null;\r\n\r\n @Output() select = new EventEmitter<string>();\r\n}\r\n","/* angular:styles/component:less;8c134f25627adb86b870a69d79105b1c916e594d1e9bf0bd33729449a7d255a2;D:\\ng-manager\\webapp\\src\\app\\pages\\api-client\\components\\request-collections\\request-collections.component.ts */\n:host {\n height: 100%;\n display: flex;\n flex-direction: column;\n width: 300px;\n flex: 0 0 300px;\n}\n.wrap {\n height: 100%;\n display: flex;\n flex-direction: column;\n border: 1px solid rgba(0, 0, 0, 0.08);\n border-radius: 8px;\n overflow: hidden;\n background: #fff;\n}\n.header {\n width: 100%;\n padding: 8px 10px;\n display: flex;\n gap: 6px;\n align-items: center;\n justify-content: space-between;\n border-bottom: 1px solid rgba(0, 0, 0, 0.06);\n flex: 0 0 auto;\n background: #fafafa;\n}\n.header nz-input-wrapper {\n flex: 1;\n min-width: 0;\n}\n.header input[nz-input] {\n font-size: 13px;\n}\n.header button {\n width: 32px;\n height: 32px;\n padding: 0 !important;\n}\n.search-icon {\n color: rgba(0, 0, 0, 0.35);\n}\n.body {\n flex: 1 1 auto;\n height: 0;\n display: flex;\n flex-direction: column;\n}\n/*# sourceMappingURL=request-collections.component.css.map */\n","/* angular:styles/component:less;af15c27645b8067eb1a68b8b7ac91bd403934fa4e1f4585fd97bd3b9b4d6baf4;D:\\ng-manager\\webapp\\src\\app\\pages\\api-client\\components\\request-collections\\collection-tree.component.ts */\n:host.tree-body {\n flex: 1 1 auto;\n height: 0;\n overflow: auto;\n padding: 8px;\n display: flex;\n flex-direction: column;\n gap: 4px;\n}\n:host.tree-body .empty {\n padding: 24px 16px;\n opacity: 0.5;\n text-align: center;\n font-size: 13px;\n}\n/*# sourceMappingURL=collection-tree.component.css.map */\n","/* angular:styles/component:less;7bee656b24f9348f17008487fee6e233f0ebe6503bec878d24d192302de93953;D:\\ng-manager\\webapp\\src\\app\\pages\\api-client\\components\\request-collections\\collection-tree-item.component.ts */\n:host.ctree-item {\n display: block;\n}\n.row {\n display: flex;\n align-items: center;\n gap: 4px;\n padding: 6px 8px;\n border-radius: 6px;\n cursor: pointer;\n transition: background-color 0.2s ease;\n}\n.row:hover {\n background-color: rgba(0, 0, 0, 0.04);\n}\n.row.active {\n background-color: #e6f7ff;\n}\n.row.active:hover {\n background-color: #bae7ff;\n}\n.chev {\n flex: 0 0 auto;\n width: 20px;\n height: 20px;\n padding: 0 !important;\n}\n.chev-icon {\n font-size: 12px;\n transition: transform 0.2s ease;\n color: rgba(0, 0, 0, 0.45);\n}\n.chev-icon.expanded {\n transform: rotate(90deg);\n}\n.main {\n display: flex;\n align-items: center;\n gap: 8px;\n flex: 1;\n min-width: 0;\n}\n.icon {\n opacity: 0.65;\n font-size: 14px;\n}\n.method {\n flex: 0 0 auto;\n font-size: 10px;\n font-weight: 600;\n line-height: 1.4;\n padding: 0 4px;\n margin: 0;\n}\n.texts {\n flex: 1;\n min-width: 0;\n}\n.title {\n font-size: 13px;\n font-weight: 500;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n color: rgba(0, 0, 0, 0.85);\n}\n.sub {\n font-size: 12px;\n opacity: 0.5;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n margin-top: 2px;\n}\n.more {\n flex: 0 0 auto;\n width: 20px;\n height: 20px;\n padding: 0 !important;\n visibility: hidden;\n opacity: 0.5;\n}\n.more:hover {\n opacity: 1;\n}\n.row:hover .more {\n visibility: visible;\n}\n.children {\n margin-left: 20px;\n padding-left: 4px;\n border-left: 1px dashed rgba(0, 0, 0, 0.08);\n margin-top: 4px;\n display: flex;\n flex-direction: column;\n gap: 2px;\n}\n/*# sourceMappingURL=collection-tree-item.component.css.map */\n","import { CommonModule } from '@angular/common';\r\nimport { Component, EventEmitter, Input, Output } from '@angular/core';\r\nimport { FormsModule } from '@angular/forms';\r\nimport { ApiCollectionKind, ApiCollectionTreeNode } from '@models/api-client';\r\nimport { NzButtonModule } from 'ng-zorro-antd/button';\r\nimport { NzIconModule } from 'ng-zorro-antd/icon';\r\nimport { NzMenuModule } from 'ng-zorro-antd/menu';\r\nimport { NzPopoverModule } from 'ng-zorro-antd/popover';\r\nimport { NzTagModule } from 'ng-zorro-antd/tag';\r\nimport { NzPopconfirmModule } from \"ng-zorro-antd/popconfirm\";\r\n\r\n/**\r\n * 集合树项组件\r\n */\r\n@Component({\r\n selector: 'app-collection-tree-item',\r\n imports: [CommonModule, NzButtonModule, FormsModule, NzIconModule, NzPopoverModule, NzMenuModule, NzTagModule, NzPopconfirmModule],\r\n template: `\r\n <div class=\"row\" [class.active]=\"activeKey === node.key\">\r\n @if(hasChildren){\r\n <button\r\n class=\"chev\"\r\n nz-button\r\n nzType=\"text\"\r\n nzSize=\"small\"\r\n (click)=\"toggle.emit(node.key); $event.stopPropagation()\"\r\n >\r\n <nz-icon class=\"chev-icon\" [class.expanded]=\"expanded\" [nzType]=\"'right'\"></nz-icon>\r\n </button>\r\n }\r\n\r\n <div class=\"main\" (click)=\"onClick()\">\r\n @if(iconType){\r\n <nz-icon class=\"icon\" [nzType]=\"iconType\"></nz-icon>\r\n }\r\n\r\n @if (node.kind === 'request') {\r\n <nz-tag class=\"method\" [nzColor]=\"getMethodColor(node.method)\">{{ node.method || '' }}</nz-tag>\r\n }\r\n\r\n <div class=\"texts\">\r\n <div class=\"title\">{{ node.title }}</div>\r\n @if (node.subtitle) {\r\n <div class=\"sub\">{{ node.subtitle }}</div>\r\n }\r\n </div>\r\n </div>\r\n\r\n <button\r\n class=\"more\"\r\n nz-button\r\n nzType=\"text\"\r\n nzSize=\"small\"\r\n (click)=\"$event.stopPropagation()\"\r\n nz-popover\r\n nzPopoverTrigger=\"click\"\r\n [(nzPopoverVisible)]=\"visible\"\r\n nzPopover\r\n [nzPopoverContent]=\"menuTpl\"\r\n nzPopoverPlacement=\"right\"\r\n [nzPopoverOverlayClassName]=\"'project-item-popover'\"> \r\n <nz-icon nzType=\"more\" nzTheme=\"outline\"></nz-icon>\r\n </button>\r\n\r\n <ng-template #menuTpl>\r\n <ul nz-menu>\r\n @if (node.kind !== 'request') {\r\n @if(node.kind==='collection') {\r\n <li nz-menu-item (click)=\"createFolder.emit(node.id); visible = false\">\r\n <nz-icon nzType=\"folder\"></nz-icon>\r\n <span>新建目录</span>\r\n </li>\r\n }\r\n <li nz-menu-item (click)=\"createRequest.emit(node.id); visible = false\">\r\n <nz-icon nzType=\"plus\"></nz-icon>\r\n <span>新建请求</span>\r\n </li>\r\n @if(node.kind==='folder') {\r\n <li nz-menu-item (click)=\"move.emit(node.id); visible = false\">\r\n <nz-icon nzType=\"folder\"></nz-icon>\r\n <span>移动到</span>\r\n </li>\r\n }\r\n <li nz-menu-item (click)=\"rename.emit(node.id); visible = false\">\r\n <nz-icon nzType=\"edit\"></nz-icon>\r\n <span>重命名</span>\r\n </li>\r\n <li nz-menu-divider></li>\r\n <li nz-menu-item nzDanger nz-popconfirm nzPopconfirmTitle=\"确认删除吗?\" (nzOnConfirm)=\"delete.emit(node.id)\">\r\n <nz-icon nzType=\"delete\"></nz-icon>\r\n <span>删除</span>\r\n </li>\r\n\r\n } @else {\r\n <li nz-menu-item (click)=\"move.emit(node.id); visible = false\">\r\n <nz-icon nzType=\"folder\"></nz-icon>\r\n <span>移动到</span>\r\n </li>\r\n <li nz-menu-item (click)=\"rename.emit(node.id); visible = false\">\r\n <nz-icon nzType=\"edit\"></nz-icon>\r\n <span>重命名</span>\r\n </li>\r\n <li nz-menu-divider></li>\r\n <li nz-menu-item nzDanger nz-popconfirm nzPopconfirmTitle=\"确认删除吗?\" (nzOnConfirm)=\"delete.emit(node.id)\">\r\n <nz-icon nzType=\"delete\"></nz-icon>\r\n <span>删除</span>\r\n </li>\r\n }\r\n </ul>\r\n </ng-template>\r\n </div>\r\n\r\n @if (hasChildren && expanded) {\r\n <div class=\"children\">\r\n <ng-content />\r\n </div>\r\n }\r\n `,\r\n host: {\r\n '[class.ctree-item]': 'true',\r\n },\r\n styles: `\r\n :host.ctree-item { \r\n display: block; \r\n }\r\n \r\n .row {\r\n display: flex;\r\n align-items: center;\r\n gap: 4px;\r\n padding: 6px 8px;\r\n border-radius: 6px;\r\n cursor: pointer;\r\n transition: background-color 0.2s ease;\r\n }\r\n \r\n .row:hover {\r\n background-color: rgba(0, 0, 0, 0.04);\r\n }\r\n \r\n .row.active {\r\n background-color: #e6f7ff;\r\n }\r\n \r\n .row.active:hover {\r\n background-color: #bae7ff;\r\n }\r\n \r\n .chev {\r\n flex: 0 0 auto;\r\n width: 20px;\r\n height: 20px;\r\n padding: 0 !important;\r\n }\r\n \r\n .chev-icon {\r\n font-size: 12px;\r\n transition: transform 0.2s ease;\r\n color: rgba(0, 0, 0, 0.45);\r\n }\r\n \r\n .chev-icon.expanded {\r\n transform: rotate(90deg);\r\n }\r\n \r\n .main {\r\n display: flex;\r\n align-items: center;\r\n gap: 8px;\r\n flex: 1;\r\n min-width: 0;\r\n }\r\n \r\n .icon {\r\n opacity: 0.65;\r\n font-size: 14px;\r\n }\r\n \r\n .method {\r\n flex: 0 0 auto;\r\n font-size: 10px;\r\n font-weight: 600;\r\n line-height: 1.4;\r\n padding: 0 4px;\r\n margin: 0;\r\n }\r\n \r\n .texts {\r\n flex: 1;\r\n min-width: 0;\r\n }\r\n \r\n .title {\r\n font-size: 13px;\r\n font-weight: 500;\r\n overflow: hidden;\r\n text-overflow: ellipsis;\r\n white-space: nowrap;\r\n color: rgba(0, 0, 0, 0.85);\r\n }\r\n \r\n .sub {\r\n font-size: 12px;\r\n opacity: 0.5;\r\n overflow: hidden;\r\n text-overflow: ellipsis;\r\n white-space: nowrap;\r\n margin-top: 2px;\r\n }\r\n \r\n .more {\r\n flex: 0 0 auto;\r\n width: 20px;\r\n height: 20px;\r\n padding: 0 !important;\r\n visibility: hidden;\r\n opacity: 0.5;\r\n }\r\n \r\n .more:hover {\r\n opacity: 1;\r\n }\r\n \r\n .row:hover .more {\r\n visibility: visible;\r\n }\r\n \r\n .children {\r\n margin-left: 20px;\r\n padding-left: 4px;\r\n border-left: 1px dashed rgba(0, 0, 0, 0.08);\r\n margin-top: 4px;\r\n display: flex;\r\n flex-direction: column;\r\n gap: 2px;\r\n }\r\n `,\r\n})\r\nexport class CollectionTreeItemComponent {\r\n @Input() node!: ApiCollectionTreeNode;\r\n @Input() expanded = false;\r\n @Input() activeKey: string | null = null;\r\n\r\n @Output() toggle = new EventEmitter<string>();\r\n @Output() selectRequest = new EventEmitter<string>();\r\n @Output() selectCollection = new EventEmitter<string>();\r\n\r\n // 菜单事件(先透传,store 后续接)\r\n @Output() createRequest = new EventEmitter<string>(); // collectionId\r\n @Output() createFolder = new EventEmitter<string>(); // collectionId\r\n @Output() rename = new EventEmitter<string>();\r\n @Output() move = new EventEmitter<string>();\r\n @Output() copyCurl = new EventEmitter<string>();\r\n @Output() delete = new EventEmitter<string>();\r\n\r\n visible = false;\r\n\r\n get hasChildren() { return (this.node.children?.length ?? 0) > 0; }\r\n get iconType() {\r\n if (this.node.kind === 'request') return ''; //api\r\n return this.node.kind === 'folder' ? 'folder' : 'database';\r\n }\r\n\r\n onClick() {\r\n if (this.node.kind === 'request') this.selectRequest.emit(this.node.id);\r\n else this.selectCollection.emit(this.node.id);\r\n }\r\n\r\n /**\r\n * 获取方法对应的颜色\r\n */\r\n getMethodColor(method: string | undefined): string {\r\n const colors: Record<string, string> = {\r\n GET: '#61affe',\r\n POST: '#49cc90',\r\n PUT: '#fca130',\r\n PATCH: '#50e3c2',\r\n DELETE: '#f93e3e',\r\n HEAD: '#909090',\r\n OPTIONS: '#909090',\r\n };\r\n return colors[method?.toUpperCase() || ''] || '#909090';\r\n }\r\n}\r\n","import { CommonModule } from '@angular/common';\r\nimport { Component, computed, EventEmitter, input, Input, Output, signal } from '@angular/core';\r\nimport { FormsModule } from '@angular/forms';\r\nimport { ApiCollectionKind, ApiCollectionTreeNode } from '@models/api-client';\r\nimport { NzButtonModule } from 'ng-zorro-antd/button';\r\nimport { NzIconModule } from 'ng-zorro-antd/icon';\r\nimport { NzInputModule } from 'ng-zorro-antd/input';\r\nimport { CollectionTreeItemComponent } from './collection-tree-item.component';\r\n@Component({\r\n selector: 'app-collection-tree',\r\n imports: [CommonModule, FormsModule, NzInputModule, NzIconModule, NzButtonModule, CollectionTreeItemComponent],\r\n host: {\r\n '[class.tree-body]': 'true',\r\n },\r\n template: `\r\n @for (n of nodes; track n.key) {\r\n <ng-container [ngTemplateOutlet]=\"nodeTpl\" [ngTemplateOutletContext]=\"{ $implicit: n }\" />\r\n }\r\n @if (!nodes.length) {\r\n <div class=\"empty\">暂无请求</div>\r\n }\r\n <ng-template #nodeTpl let-node>\r\n <app-collection-tree-item\r\n [node]=\"node\"\r\n [expanded]=\"expanded(node.key)\"\r\n [activeKey]=\"activeKey()\"\r\n (toggle)=\"toggle($event)\"\r\n (selectRequest)=\"onSelectRequest($event)\"\r\n (selectCollection)=\"onSelectCollection($event)\"\r\n (createRequest)=\"createRequest.emit({ collectionId: $event })\"\r\n (createFolder)=\"createFolder.emit({ collectionId: $event })\"\r\n (rename)=\"rename.emit({ id: $event, kind: node.kind })\"\r\n (move)=\"move.emit({ id: $event, kind: node.kind })\"\r\n (copyCurl)=\"copyCurl.emit($event)\"\r\n (delete)=\"delete.emit({ id: $event, kind: node.kind })\"\r\n >\r\n @for (c of node.children; track c.key) {\r\n <ng-container [ngTemplateOutlet]=\"nodeTpl\" [ngTemplateOutletContext]=\"{ $implicit: c }\" />\r\n }\r\n </app-collection-tree-item>\r\n </ng-template>\r\n `,\r\n styles: `\r\n :host.tree-body {\r\n flex: 1 1 auto;\r\n height: 0;\r\n overflow: auto;\r\n padding: 8px;\r\n display: flex;\r\n flex-direction: column;\r\n gap: 4px;\r\n }\r\n \r\n :host.tree-body .empty {\r\n padding: 24px 16px;\r\n opacity: 0.5;\r\n text-align: center;\r\n font-size: 13px;\r\n }\r\n `,\r\n})\r\nexport class CollectionTreeComponent {\r\n\r\n @Input() nodes: ApiCollectionTreeNode[] = [];\r\n\r\n activeRequestId = input<string | null>(null);\r\n\r\n @Output() selectRequest = new EventEmitter<string>();\r\n @Output() selectCollection = new EventEmitter<string>();\r\n\r\n // @Output() createCollection = new EventEmitter<{ parentId: string | null; kind: 'folder' | 'collection' }>();\r\n @Output() createRequest = new EventEmitter<{ collectionId: string | null }>();\r\n @Output() createFolder = new EventEmitter<{ collectionId: string | null }>();\r\n\r\n\r\n // 可选:菜单事件对外透传\r\n @Output() rename = new EventEmitter<{ id: string; kind: ApiCollectionKind }>();\r\n @Output() move = new EventEmitter<{ id: string, kind: ApiCollectionKind }>();\r\n @Output() copyCurl = new EventEmitter<string>();\r\n @Output() delete = new EventEmitter<{ id: string, kind: ApiCollectionKind }>();\r\n\r\n // activeKey:给选中样式用(request 优先)\r\n activeKey = computed(() => {\r\n return (this.activeRequestId() ? `r:${this.activeRequestId()}` : null)\r\n });\r\n\r\n // 当前选中的 collection(用于“新建请求”默认归属)\r\n private _activeCollectionId = signal<string | null>(null);\r\n activeCollectionId = computed(() => this._activeCollectionId());\r\n\r\n // 展开态:key -> boolean\r\n private expandedMap = signal<Record<string, boolean>>({});\r\n\r\n expanded(key: string) {\r\n return !!this.expandedMap()[key];\r\n }\r\n toggle(key: string) {\r\n const m = { ...this.expandedMap() };\r\n m[key] = !m[key];\r\n this.expandedMap.set(m);\r\n }\r\n onSelectRequest(id: string) {\r\n this.selectRequest.emit(id);\r\n }\r\n onSelectCollection(id: string) {\r\n this._activeCollectionId.set(id);\r\n this.selectCollection.emit(id);\r\n // 体验:点 collection 自动展开(MVP)\r\n const key = `c:${id}`;\r\n const m = { ...this.expandedMap() };\r\n m[key] = true;\r\n this.expandedMap.set(m);\r\n }\r\n}\r\n","import { CommonModule } from '@angular/common';\r\nimport { Component, EventEmitter, input, Input, model, Output, signal } from '@angular/core';\r\nimport { FormsModule } from '@angular/forms';\r\nimport { NzButtonModule } from 'ng-zorro-antd/button';\r\nimport { NzIconModule } from 'ng-zorro-antd/icon';\r\nimport { NzInputModule } from 'ng-zorro-antd/input';\r\n\r\nimport { ApiCollectionKind, ApiCollectionTreeNode } from '@models/api-client';\r\nimport { NzMenuModule } from 'ng-zorro-antd/menu';\r\nimport { NzPopoverModule } from 'ng-zorro-antd/popover';\r\nimport { CollectionTreeComponent } from './collection-tree.component';\r\n\r\n@Component({\r\n selector: 'app-request-collections',\r\n standalone: true,\r\n imports: [CommonModule,\r\n FormsModule,\r\n NzButtonModule,\r\n NzInputModule,\r\n NzIconModule,\r\n NzMenuModule,\r\n NzPopoverModule,\r\n CollectionTreeComponent,],\r\n template: `\r\n <div class=\"wrap\">\r\n <div class=\"header\">\r\n <nz-input-wrapper>\r\n <nz-icon class=\"search-icon\" nzInputPrefix nzType=\"search\" />\r\n <input\r\n nz-input\r\n placeholder=\"搜索\"\r\n [(ngModel)]=\"q\"\r\n />\r\n </nz-input-wrapper>\r\n <button nz-button (click)=\"reload.emit()\" nzType=\"text\">\r\n <nz-icon [nzType]=\"loading ? 'loading' : 'reload'\" nzTheme=\"outline\" />\r\n </button>\r\n <button \r\n nz-button \r\n nz-popover \r\n nzPopoverTrigger=\"click\"\r\n [(nzPopoverVisible)]=\"visible\"\r\n [nzPopoverContent]=\"menuTpl\"\r\n nzPopoverPlacement=\"bottomCenter\"\r\n [nzPopoverOverlayClassName]=\"'project-item-popover'\"\r\n nzType=\"text\"\r\n >\r\n <nz-icon nzType=\"plus\" nzTheme=\"outline\" />\r\n </button>\r\n </div>\r\n <div class=\"body\">\r\n <!-- <app-request-list\r\n [requests]=\"filtered()\"\r\n [activeId]=\"activeId\"\r\n (select)=\"select.emit($event)\"\r\n /> -->\r\n <app-collection-tree\r\n [nodes]=\"nodes()\"\r\n [activeRequestId]=\"activeId()\"\r\n (selectRequest)=\"select.emit($event)\"\r\n (createRequest)=\"createRequest.emit({ collectionId: $event.collectionId })\"\r\n (createFolder)=\"createFolder.emit({ collectionId: $event.collectionId ?? null })\"\r\n (rename)=\"rename.emit($event)\"\r\n (move)=\"move.emit($event)\"\r\n (delete)=\"delete.emit({ id: $event.id, kind: $event.kind })\"\r\n >\r\n </app-collection-tree>\r\n </div>\r\n </div>\r\n <ng-template #menuTpl>\r\n <ul nz-menu>\r\n <li nz-menu-item (click)=\"createRequest.emit({ collectionId: null });visible=false\" class=\"item\">\r\n <nz-icon nzType=\"api\"></nz-icon>\r\n <span>新建请求</span>\r\n </li>\r\n <li nz-menu-item (click)=\"createCollection.emit()\" class=\"item\">\r\n <nz-icon nzType=\"folder-add\"></nz-icon>\r\n <span>新建集合</span>\r\n </li>\r\n </ul>\r\n </ng-template>\r\n `,\r\n styles: [`\r\n :host { \r\n height: 100%; \r\n display: flex; \r\n flex-direction: column; \r\n width: 300px; \r\n flex: 0 0 300px; \r\n }\r\n \r\n .wrap { \r\n height: 100%; \r\n display: flex; \r\n flex-direction: column; \r\n border: 1px solid rgba(0, 0, 0, 0.08); \r\n border-radius: 8px; \r\n overflow: hidden; \r\n background: #fff;\r\n }\r\n \r\n .header {\r\n width: 100%;\r\n padding: 8px 10px;\r\n display: flex;\r\n gap: 6px;\r\n align-items: center;\r\n justify-content: space-between;\r\n border-bottom: 1px solid rgba(0, 0, 0, 0.06);\r\n flex: 0 0 auto;\r\n background: #fafafa;\r\n }\r\n \r\n .header nz-input-wrapper {\r\n flex: 1;\r\n min-width: 0;\r\n }\r\n \r\n .header input[nz-input] {\r\n font-size: 13px;\r\n }\r\n \r\n .header button {\r\n width: 32px;\r\n height: 32px;\r\n padding: 0 !important;\r\n }\r\n \r\n .search-icon {\r\n color: rgba(0, 0, 0, 0.35);\r\n }\r\n \r\n .body {\r\n flex: 1 1 auto;\r\n height: 0;\r\n display: flex;\r\n flex-direction: column;\r\n }\r\n `],\r\n})\r\nexport class RequestCollectionsComponent {\r\n\r\n nodes = input<ApiCollectionTreeNode[]>([]);\r\n q = model<string>('');\r\n\r\n activeId = input<string | null>(null);\r\n @Input() loading: boolean = false;\r\n\r\n @Output() select = new EventEmitter<string>();\r\n @Output() createRequest = new EventEmitter<{ collectionId: string | null }>();\r\n @Output() createCollection = new EventEmitter<void>();\r\n @Output() createFolder = new EventEmitter<{ collectionId: string | null }>();\r\n\r\n @Output() reload = new EventEmitter<void>();\r\n @Output() delete = new EventEmitter<{ id: string, kind: ApiCollectionKind }>();\r\n @Output() rename = new EventEmitter<{ id: string, kind: ApiCollectionKind }>();\r\n @Output() move = new EventEmitter<{ id: string, kind: ApiCollectionKind }>();\r\n\r\n visible = false;\r\n\r\n // nodes = computed<ApiCollectionTreeNode[]>(() => {\r\n // const kw = this.q()\r\n // const collections = this.collections()\r\n // const requests = this.requests()\r\n // return genCollectionTreeNodes(collections, requests, kw);\r\n // });\r\n\r\n // filtered = computed(() => {\r\n // const kw = this.q().trim().toLowerCase();\r\n // if (!kw) return this.requests();\r\n\r\n // return (this.requests() ?? []).filter(r => {\r\n // const name = (r.name ?? '').toLowerCase();\r\n // const url = (r.url ?? '').toLowerCase();\r\n // return name.includes(kw) || url.includes(kw);\r\n // });\r\n // });\r\n}\r\n\r\n","/* angular:styles/component:less;328f2c49622602f7047f70a3035d2e6ad9d23054ae6c988c99f892be532b2c3a;D:\\ng-manager\\webapp\\src\\app\\pages\\api-client\\components\\request-editor\\auth-editor.component.ts */\n.wrap {\n display: flex;\n flex-direction: column;\n height: 100%;\n min-height: 220px;\n}\n.bar {\n display: flex;\n gap: 10px;\n align-items: center;\n padding: 8px 0;\n border-bottom: 1px solid #f0f0f0;\n}\n.type {\n width: 160px;\n}\n.in {\n width: 140px;\n}\n.main {\n flex: 1 1 auto;\n overflow: auto;\n padding-top: 10px;\n}\n.empty {\n padding: 12px;\n opacity: 0.7;\n}\n.grid {\n display: flex;\n flex-direction: column;\n gap: 10px;\n}\n.row {\n display: grid;\n grid-template-columns: 100px 1fr;\n align-items: center;\n gap: 10px;\n}\n.row-top {\n align-items: start;\n}\n.label {\n font-size: 12px;\n opacity: 0.8;\n}\n/*# sourceMappingURL=auth-editor.component.css.map */\n","import { __esDecorate, __runInitializers } from 'tslib';\nimport { Directionality } from '@angular/cdk/bidi';\nimport * as i0 from '@angular/core';\nimport { inject, ChangeDetectorRef, DestroyRef, EventEmitter, booleanAttribute, Output, Input, ViewEncapsulation, ChangeDetectionStrategy, Component, NgModule } from '@angular/core';\nimport { takeUntilDestroyed } from '@angular/core/rxjs-interop';\nimport { slideAlertMotion } from 'ng-zorro-antd/core/animation';\nimport { WithConfig, onConfigChangeEventForComponent } from 'ng-zorro-antd/core/config';\nimport * as i2 from 'ng-zorro-antd/core/outlet';\nimport { NzOutletModule } from 'ng-zorro-antd/core/outlet';\nimport * as i1 from 'ng-zorro-antd/icon';\nimport { NzIconModule } from 'ng-zorro-antd/icon';\n\nconst NZ_CONFIG_MODULE_NAME = 'alert';\nlet NzAlertComponent = (() => {\n let _nzCloseable_decorators;\n let _nzCloseable_initializers = [];\n let _nzCloseable_extraInitializers = [];\n let _nzShowIcon_decorators;\n let _nzShowIcon_initializers = [];\n let _nzShowIcon_extraInitializers = [];\n return class NzAlertComponent {\n static {\n const _metadata = typeof Symbol === \"function\" && Symbol.metadata ? Object.create(null) : void 0;\n _nzCloseable_decorators = [WithConfig()];\n _nzShowIcon_decorators = [WithConfig()];\n __esDecorate(null, null, _nzCloseable_decorators, { kind: \"field\", name: \"nzCloseable\", static: false, private: false, access: { has: obj => \"nzCloseable\" in obj, get: obj => obj.nzCloseable, set: (obj, value) => { obj.nzCloseable = value; } }, metadata: _metadata }, _nzCloseable_initializers, _nzCloseable_extraInitializers);\n __esDecorate(null, null, _nzShowIcon_decorators, { kind: \"field\", name: \"nzShowIcon\", static: false, private: false, access: { has: obj => \"nzShowIcon\" in obj, get: obj => obj.nzShowIcon, set: (obj, value) => { obj.nzShowIcon = value; } }, metadata: _metadata }, _nzShowIcon_initializers, _nzShowIcon_extraInitializers);\n if (_metadata) Object.defineProperty(this, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata });\n }\n cdr = inject(ChangeDetectorRef);\n directionality = inject(Directionality);\n destroyRef = inject(DestroyRef);\n _nzModuleName = NZ_CONFIG_MODULE_NAME;\n nzAction = null;\n nzCloseText = null;\n nzIconType = null;\n nzMessage = null;\n nzDescription = null;\n nzType = 'info';\n nzCloseable = __runInitializers(this, _nzCloseable_initializers, false);\n nzShowIcon = (__runInitializers(this, _nzCloseable_extraInitializers), __runInitializers(this, _nzShowIcon_initializers, false));\n nzBanner = (__runInitializers(this, _nzShowIcon_extraInitializers), false);\n nzNoAnimation = false;\n nzIcon = null;\n nzOnClose = new EventEmitter();\n closed = false;\n iconTheme = 'fill';\n inferredIconType = 'info-circle';\n dir = 'ltr';\n isTypeSet = false;\n isShowIconSet = false;\n constructor() {\n onConfigChangeEventForComponent(NZ_CONFIG_MODULE_NAME, () => this.cdr.markForCheck());\n }\n ngOnInit() {\n this.directionality.change?.pipe(takeUntilDestroyed(this.destroyRef)).subscribe((direction) => {\n this.dir = direction;\n this.cdr.detectChanges();\n });\n this.dir = this.directionality.value;\n }\n closeAlert() {\n this.closed = true;\n }\n onFadeAnimationDone() {\n if (this.closed) {\n this.nzOnClose.emit(true);\n }\n }\n ngOnChanges(changes) {\n const { nzShowIcon, nzDescription, nzType, nzBanner } = changes;\n if (nzShowIcon) {\n this.isShowIconSet = true;\n }\n if (nzType) {\n this.isTypeSet = true;\n switch (this.nzType) {\n case 'error':\n this.inferredIconType = 'close-circle';\n break;\n case 'success':\n this.inferredIconType = 'check-circle';\n break;\n case 'info':\n this.inferredIconType = 'info-circle';\n break;\n case 'warning':\n this.inferredIconType = 'exclamation-circle';\n break;\n }\n }\n if (nzDescription) {\n this.iconTheme = this.nzDescription ? 'outline' : 'fill';\n }\n if (nzBanner) {\n if (!this.isTypeSet) {\n this.nzType = 'warning';\n }\n if (!this.isShowIconSet) {\n this.nzShowIcon = true;\n }\n }\n }\n static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: \"12.0.0\", version: \"20.3.0\", ngImport: i0, type: NzAlertComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });\n static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: \"17.0.0\", version: \"20.3.0\", type: NzAlertComponent, isStandalone: true, selector: \"nz-alert\", inputs: { nzAction: \"nzAction\", nzCloseText: \"nzCloseText\", nzIconType: \"nzIconType\", nzMessage: \"nzMessage\", nzDescription: \"nzDescription\", nzType: \"nzType\", nzCloseable: [\"nzCloseable\", \"nzCloseable\", booleanAttribute], nzShowIcon: [\"nzShowIcon\", \"nzShowIcon\", booleanAttribute], nzBanner: [\"nzBanner\", \"nzBanner\", booleanAttribute], nzNoAnimation: [\"nzNoAnimation\", \"nzNoAnimation\", booleanAttribute], nzIcon: \"nzIcon\" }, outputs: { nzOnClose: \"nzOnClose\" }, exportAs: [\"nzAlert\"], usesOnChanges: true, ngImport: i0, template: `\n @if (!closed) {\n <div\n class=\"ant-alert\"\n [class.ant-alert-rtl]=\"dir === 'rtl'\"\n [class.ant-alert-success]=\"nzType === 'success'\"\n [class.ant-alert-info]=\"nzType === 'info'\"\n [class.ant-alert-warning]=\"nzType === 'warning'\"\n [class.ant-alert-error]=\"nzType === 'error'\"\n [class.ant-alert-no-icon]=\"!nzShowIcon\"\n [class.ant-alert-banner]=\"nzBanner\"\n [class.ant-alert-closable]=\"nzCloseable\"\n [class.ant-alert-with-description]=\"!!nzDescription\"\n [@.disabled]=\"nzNoAnimation\"\n [@slideAlertMotion]\n (@slideAlertMotion.done)=\"onFadeAnimationDone()\"\n >\n @if (nzShowIcon) {\n <div class=\"ant-alert-icon\">\n @if (nzIcon) {\n <ng-container *nzStringTemplateOutlet=\"nzIcon\"></ng-container>\n } @else {\n <nz-icon [nzType]=\"nzIconType || inferredIconType\" [nzTheme]=\"iconTheme\" />\n }\n </div>\n }\n\n @if (nzMessage || nzDescription) {\n <div class=\"ant-alert-content\">\n @if (nzMessage) {\n <span class=\"ant-alert-message\">\n <ng-container *nzStringTemplateOutlet=\"nzMessage\">{{ nzMessage }}</ng-container>\n </span>\n }\n @if (nzDescription) {\n <span class=\"ant-alert-description\">\n <ng-container *nzStringTemplateOutlet=\"nzDescription\">{{ nzDescription }}</ng-container>\n </span>\n }\n </div>\n }\n\n @if (nzAction) {\n <div class=\"ant-alert-action\">\n <ng-container *nzStringTemplateOutlet=\"nzAction\">{{ nzAction }}</ng-container>\n </div>\n }\n\n @if (nzCloseable || nzCloseText) {\n <button type=\"button\" tabindex=\"0\" class=\"ant-alert-close-icon\" (click)=\"closeAlert()\">\n @if (nzCloseText) {\n <ng-container *nzStringTemplateOutlet=\"nzCloseText\">\n <span class=\"ant-alert-close-text\">{{ nzCloseText }}</span>\n </ng-container>\n } @else {\n <nz-icon nzType=\"close\" />\n }\n </button>\n }\n </div>\n }\n `, isInline: true, dependencies: [{ kind: \"ngmodule\", type: NzIconModule }, { kind: \"directive\", type: i1.NzIconDirective, selector: \"nz-icon,[nz-icon]\", inputs: [\"nzSpin\", \"nzRotate\", \"nzType\", \"nzTheme\", \"nzTwotoneColor\", \"nzIconfont\"], exportAs: [\"nzIcon\"] }, { kind: \"ngmodule\", type: NzOutletModule }, { kind: \"directive\", type: i2.NzStringTemplateOutletDirective, selector: \"[nzStringTemplateOutlet]\", inputs: [\"nzStringTemplateOutletContext\", \"nzStringTemplateOutlet\"], exportAs: [\"nzStringTemplateOutlet\"] }], animations: [slideAlertMotion], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });\n };\n})();\ni0.ɵɵngDeclareClassMetadata({ minVersion: \"12.0.0\", version: \"20.3.0\", ngImport: i0, type: NzAlertComponent, decorators: [{\n type: Component,\n args: [{\n selector: 'nz-alert',\n exportAs: 'nzAlert',\n animations: [slideAlertMotion],\n imports: [NzIconModule, NzOutletModule],\n template: `\n @if (!closed) {\n <div\n class=\"ant-alert\"\n [class.ant-alert-rtl]=\"dir === 'rtl'\"\n [class.ant-alert-success]=\"nzType === 'success'\"\n [class.ant-alert-info]=\"nzType === 'info'\"\n [class.ant-alert-warning]=\"nzType === 'warning'\"\n [class.ant-alert-error]=\"nzType === 'error'\"\n [class.ant-alert-no-icon]=\"!nzShowIcon\"\n [class.ant-alert-banner]=\"nzBanner\"\n [class.ant-alert-closable]=\"nzCloseable\"\n [class.ant-alert-with-description]=\"!!nzDescription\"\n [@.disabled]=\"nzNoAnimation\"\n [@slideAlertMotion]\n (@slideAlertMotion.done)=\"onFadeAnimationDone()\"\n >\n @if (nzShowIcon) {\n <div class=\"ant-alert-icon\">\n @if (nzIcon) {\n <ng-container *nzStringTemplateOutlet=\"nzIcon\"></ng-container>\n } @else {\n <nz-icon [nzType]=\"nzIconType || inferredIconType\" [nzTheme]=\"iconTheme\" />\n }\n </div>\n }\n\n @if (nzMessage || nzDescription) {\n <div class=\"ant-alert-content\">\n @if (nzMessage) {\n <span class=\"ant-alert-message\">\n <ng-container *nzStringTemplateOutlet=\"nzMessage\">{{ nzMessage }}</ng-container>\n </span>\n }\n @if (nzDescription) {\n <span class=\"ant-alert-description\">\n <ng-container *nzStringTemplateOutlet=\"nzDescription\">{{ nzDescription }}</ng-container>\n </span>\n }\n </div>\n }\n\n @if (nzAction) {\n <div class=\"ant-alert-action\">\n <ng-container *nzStringTemplateOutlet=\"nzAction\">{{ nzAction }}</ng-container>\n </div>\n }\n\n @if (nzCloseable || nzCloseText) {\n <button type=\"button\" tabindex=\"0\" class=\"ant-alert-close-icon\" (click)=\"closeAlert()\">\n @if (nzCloseText) {\n <ng-container *nzStringTemplateOutlet=\"nzCloseText\">\n <span class=\"ant-alert-close-text\">{{ nzCloseText }}</span>\n </ng-container>\n } @else {\n <nz-icon nzType=\"close\" />\n }\n </button>\n }\n </div>\n }\n `,\n changeDetection: ChangeDetectionStrategy.OnPush,\n encapsulation: ViewEncapsulation.None\n }]\n }], ctorParameters: () => [], propDecorators: { nzAction: [{\n type: Input\n }], nzCloseText: [{\n type: Input\n }], nzIconType: [{\n type: Input\n }], nzMessage: [{\n type: Input\n }], nzDescription: [{\n type: Input\n }], nzType: [{\n type: Input\n }], nzCloseable: [{\n type: Input,\n args: [{ transform: booleanAttribute }]\n }], nzShowIcon: [{\n type: Input,\n args: [{ transform: booleanAttribute }]\n }], nzBanner: [{\n type: Input,\n args: [{ transform: booleanAttribute }]\n }], nzNoAnimation: [{\n type: Input,\n args: [{ transform: booleanAttribute }]\n }], nzIcon: [{\n type: Input\n }], nzOnClose: [{\n type: Output\n }] } });\n\n/**\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://github.com/NG-ZORRO/ng-zorro-antd/blob/master/LICENSE\n */\nclass NzAlertModule {\n static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: \"12.0.0\", version: \"20.3.0\", ngImport: i0, type: NzAlertModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });\n static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: \"14.0.0\", version: \"20.3.0\", ngImport: i0, type: NzAlertModule, imports: [NzAlertComponent], exports: [NzAlertComponent] });\n static ɵinj = i0.ɵɵngDeclareInjector({ minVersion: \"12.0.0\", version: \"20.3.0\", ngImport: i0, type: NzAlertModule, imports: [NzAlertComponent] });\n}\ni0.ɵɵngDeclareClassMetadata({ minVersion: \"12.0.0\", version: \"20.3.0\", ngImport: i0, type: NzAlertModule, decorators: [{\n type: NgModule,\n args: [{\n exports: [NzAlertComponent],\n imports: [NzAlertComponent]\n }]\n }] });\n\n/**\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://github.com/NG-ZORRO/ng-zorro-antd/blob/master/LICENSE\n */\n\n/**\n * Generated bundle index. Do not edit.\n */\n\nexport { NzAlertComponent, NzAlertModule };\n\n","import { CommonModule } from '@angular/common';\nimport { Component, EventEmitter, Output, computed, input } from '@angular/core';\nimport { FormsModule } from '@angular/forms';\nimport { NzAlertModule } from 'ng-zorro-antd/alert';\nimport { NzInputModule } from 'ng-zorro-antd/input';\nimport { NzSelectModule } from 'ng-zorro-antd/select';\n\nimport type { ApiRequestEntity } from '@models/api-client/api-request.model';\n\ntype Auth = ApiRequestEntity['auth'];\ntype AuthType = NonNullable<Auth>['type'];\n\n@Component({\n selector: 'app-auth-editor',\n standalone: true,\n imports: [CommonModule, FormsModule, NzSelectModule, NzInputModule, NzAlertModule],\n template: `\n <div class=\"wrap\">\n <div class=\"bar\">\n <nz-select class=\"type\" [ngModel]=\"type()\" (ngModelChange)=\"setType($event)\">\n @for (t of types; track t) {\n <nz-option [nzValue]=\"t\" [nzLabel]=\"t\"></nz-option>\n }\n </nz-select>\n\n @if(type()==='apikey'){\n <nz-select class=\"in\" [ngModel]=\"apiKeyIn()\" (ngModelChange)=\"setApiKeyIn($event)\">\n <nz-option nzValue=\"header\" nzLabel=\"in: header\"></nz-option>\n <nz-option nzValue=\"query\" nzLabel=\"in: query\"></nz-option>\n </nz-select>\n }\n </div>\n\n <div class=\"main\">\n @switch (type()) {\n @case ('none') {\n <div class=\"empty\">无鉴权</div>\n }\n\n @case ('basic') {\n <div class=\"grid\">\n <div class=\"row\">\n <div class=\"label\">Username</div>\n <input\n nz-input\n placeholder=\"username\"\n [ngModel]=\"basicUsername()\"\n (ngModelChange)=\"setBasicUsername($event)\"\n />\n </div>\n\n <div class=\"row\">\n <div class=\"label\">Password</div>\n <input\n nz-input\n placeholder=\"password\"\n type=\"password\"\n [ngModel]=\"basicPassword()\"\n (ngModelChange)=\"setBasicPassword($event)\"\n />\n </div>\n </div>\n }\n\n @case ('bearer') {\n <div class=\"grid\">\n <div class=\"row\">\n <div class=\"label\">Token</div>\n <input\n nz-input\n placeholder=\"Bearer token\"\n [ngModel]=\"bearerToken()\"\n (ngModelChange)=\"setBearerToken($event)\"\n />\n </div>\n </div>\n }\n\n @case ('cookie') {\n <div class=\"grid\">\n <div class=\"row row-top\">\n <div class=\"label\">Cookie</div>\n <textarea\n nz-input\n rows=\"4\"\n placeholder=\"ngm_hub_token=...; other=value\"\n [ngModel]=\"cookieValue()\"\n (ngModelChange)=\"setCookieValue($event)\"\n ></textarea>\n </div>\n\n <nz-alert\n nzType=\"info\"\n nzShowIcon\n nzMessage=\"填写完整 Cookie 头值。适合先调用登录接口拿到 Set-Cookie,再粘贴到这里复用会话。\"\n ></nz-alert>\n </div>\n }\n\n @case ('apikey') {\n <div class=\"grid\">\n <div class=\"row\">\n <div class=\"label\">Key</div>\n <input\n nz-input\n placeholder=\"x-api-key / api_key\"\n [ngModel]=\"apiKeyKey()\"\n (ngModelChange)=\"setApiKeyKey($event)\"\n />\n </div>\n\n <div class=\"row\">\n <div class=\"label\">Value</div>\n <input\n nz-input\n placeholder=\"value\"\n [ngModel]=\"apiKeyValue()\"\n (ngModelChange)=\"setApiKeyValue($event)\"\n />\n </div>\n\n @if(apiKeyIn()==='query'){\n <nz-alert\n nzType=\"info\"\n nzShowIcon\n nzMessage=\"提示:query 型 API Key 不会写入请求头,会在发送时拼接到 URL 查询参数中。\"\n ></nz-alert>\n }\n @if(apiKeyIn()==='header'){\n <nz-alert\n nzType=\"info\"\n nzShowIcon\n nzMessage=\"提示:header 型 API Key 会在发送时写入请求头。\"\n ></nz-alert>\n }\n </div>\n }\n }\n </div>\n </div>\n `,\n styles: [\n `\n .wrap{ display:flex; flex-direction:column; height:100%; min-height:220px; }\n .bar{\n display:flex; gap:10px; align-items:center;\n padding:8px 0; border-bottom:1px solid #f0f0f0;\n }\n .type{ width:160px; }\n .in{ width:140px; }\n\n .main{ flex:1 1 auto; overflow:auto; padding-top:10px; }\n .empty{ padding:12px; opacity:.7; }\n\n .grid{ display:flex; flex-direction:column; gap:10px; }\n .row{ display:grid; grid-template-columns: 100px 1fr; align-items:center; gap:10px; }\n .row-top{ align-items:start; }\n .label{ font-size:12px; opacity:.8; }\n `\n ],\n})\nexport class AuthEditorComponent {\n readonly auth = input<Auth | undefined>(undefined);\n @Output() authChange = new EventEmitter<Auth | undefined>();\n\n types: AuthType[] = ['none', 'basic', 'bearer', 'cookie', 'apikey'];\n\n type = computed<AuthType>(() => (this.auth()?.type ?? 'none') as AuthType);\n\n basicUsername = computed(() => (this.auth()?.type === 'basic' ? (this.auth()?.basic?.username ?? '') : ''));\n basicPassword = computed(() => (this.auth()?.type === 'basic' ? (this.auth()?.basic?.password ?? '') : ''));\n bearerToken = computed(() => (this.auth()?.type === 'bearer' ? (this.auth()?.bearer?.token ?? '') : ''));\n cookieValue = computed(() => (this.auth()?.type === 'cookie' ? (this.auth()?.cookie?.value ?? '') : ''));\n apiKeyIn = computed<'header' | 'query'>(() => {\n if (this.auth()?.type !== 'apikey') return 'header';\n return (this.auth()?.apikey?.in ?? 'header') as 'header' | 'query';\n });\n apiKeyKey = computed(() => (this.auth()?.type === 'apikey' ? (this.auth()?.apikey?.key ?? '') : ''));\n apiKeyValue = computed(() => (this.auth()?.type === 'apikey' ? (this.auth()?.apikey?.value ?? '') : ''));\n\n setType(t: AuthType) {\n if (t === 'none') {\n this.authChange.emit({ type: 'none' } as Auth);\n return;\n }\n\n if (t === 'basic') {\n this.authChange.emit({\n type: 'basic',\n basic: { username: '', password: '' },\n } as Auth);\n return;\n }\n\n if (t === 'bearer') {\n this.authChange.emit({\n type: 'bearer',\n bearer: { token: '' },\n } as Auth);\n return;\n }\n\n if (t === 'cookie') {\n this.authChange.emit({\n type: 'cookie',\n cookie: { value: '' },\n } as Auth);\n return;\n }\n\n this.authChange.emit({\n type: 'apikey',\n apikey: { in: 'header', key: '', value: '' },\n } as Auth);\n }\n\n setBasicUsername(v: string) {\n const current = this.auth();\n const next: Auth = { ...(current ?? { type: 'basic' }), type: 'basic', basic: { ...(current as any)?.basic, username: v } } as Auth;\n this.authChange.emit(next);\n }\n\n setBasicPassword(v: string) {\n const current = this.auth();\n const next: Auth = { ...(current ?? { type: 'basic' }), type: 'basic', basic: { ...(current as any)?.basic, password: v } } as Auth;\n this.authChange.emit(next);\n }\n\n setBearerToken(v: string) {\n const current = this.auth();\n const next: Auth = { ...(current ?? { type: 'bearer' }), type: 'bearer', bearer: { ...(current as any)?.bearer, token: v } } as Auth;\n this.authChange.emit(next);\n }\n\n setCookieValue(v: string) {\n const current = this.auth();\n const next: Auth = { ...(current ?? { type: 'cookie' }), type: 'cookie', cookie: { ...(current as any)?.cookie, value: v } } as Auth;\n this.authChange.emit(next);\n }\n\n setApiKeyIn(v: 'header' | 'query') {\n const current = this.auth();\n const next: Auth = {\n ...(current ?? { type: 'apikey' }),\n type: 'apikey',\n apikey: { ...(current as any)?.apikey, in: v, key: this.apiKeyKey(), value: this.apiKeyValue() },\n } as Auth;\n this.authChange.emit(next);\n }\n\n setApiKeyKey(v: string) {\n const current = this.auth();\n const next: Auth = {\n ...(current ?? { type: 'apikey' }),\n type: 'apikey',\n apikey: { ...(current as any)?.apikey, in: this.apiKeyIn(), key: v, value: this.apiKeyValue() },\n } as Auth;\n this.authChange.emit(next);\n }\n\n setApiKeyValue(v: string) {\n const current = this.auth();\n const next: Auth = {\n ...(current ?? { type: 'apikey' }),\n type: 'apikey',\n apikey: { ...(current as any)?.apikey, in: this.apiKeyIn(), key: this.apiKeyKey(), value: v },\n } as Auth;\n this.authChange.emit(next);\n }\n}\r\n","/* angular:styles/component:less;a2d138daa1be7ada152d2490f4e888dcacc12e206ea493e4a20e8f2b036ce7b0;D:\\ng-manager\\webapp\\src\\app\\pages\\api-client\\components\\request-editor\\body-editor.component.ts */\n.wrap {\n display: flex;\n flex-direction: column;\n height: 100%;\n min-height: 260px;\n}\n.bar {\n display: flex;\n gap: 10px;\n align-items: center;\n padding: 8px 0;\n border-bottom: 1px solid #f0f0f0;\n}\n.mode {\n width: 140px;\n}\n.ctype {\n flex: 1 1 auto;\n}\n.main {\n flex: 1 1 auto;\n overflow: auto;\n padding-top: 10px;\n}\n.ta {\n width: 100%;\n height: 100%;\n min-height: 240px;\n font-family:\n ui-monospace,\n SFMono-Regular,\n Menlo,\n Monaco,\n Consolas,\n \"Liberation Mono\",\n \"Courier New\",\n monospace;\n font-size: 12px;\n}\n.empty {\n padding: 12px;\n opacity: 0.7;\n}\n.err {\n margin-top: 8px;\n color: #a8071a;\n font-size: 12px;\n}\n/*# sourceMappingURL=body-editor.component.css.map */\n","/* angular:styles/component:less;050f257cd99878760f38d3077de3741ff43d594fd3d097d70835075f643e2358;D:\\ng-manager\\webapp\\src\\app\\pages\\api-client\\components\\request-editor\\kv-table.component.ts */\n.kv-wrap {\n display: flex;\n flex-direction: column;\n height: 100%;\n}\n.kv-toolbar {\n padding: 8px 0;\n display: flex;\n justify-content: space-between;\n align-items: center;\n gap: 10px;\n}\n.kv-toolbar .left,\n.kv-toolbar .right {\n display: flex;\n gap: 8px;\n align-items: center;\n}\n.hint {\n font-size: 12px;\n opacity: 0.7;\n}\n.kv-head {\n display: grid;\n grid-template-columns: 40px 1fr 1fr 2fr 44px;\n gap: 8px;\n padding: 6px 0;\n font-size: 14px;\n border-bottom: 1px solid #f0f0f0;\n align-items: center;\n}\n.kv-head .c-key,\n.kv-head .c-val,\n.kv-head .c-des {\n opacity: 0.75;\n}\n.kv-body {\n flex: 1 1 auto;\n overflow: auto;\n padding: 8px 0;\n}\n.kv-row {\n display: grid;\n grid-template-columns: 40px 1fr 1fr 2fr 44px;\n gap: 8px;\n align-items: center;\n padding: 6px 0;\n border-bottom: 1px dashed #f0f0f0;\n}\n.c-check {\n display: flex;\n justify-content: center;\n}\n.c-op {\n display: flex;\n justify-content: center;\n}\n.kv-empty {\n padding: 16px;\n opacity: 0.75;\n display: flex;\n align-items: center;\n justify-content: space-between;\n border: 1px dashed #e8e8e8;\n border-radius: 8px;\n margin-top: 8px;\n}\n/*# sourceMappingURL=kv-table.component.css.map */\n","import { CommonModule } from '@angular/common';\r\nimport { Component, EventEmitter, Input, OnChanges, Output, SimpleChanges, computed } from '@angular/core';\r\nimport { FormsModule } from '@angular/forms';\r\nimport { ApiRequestKvRow } from '@models/api-client';\r\nimport { uniqueId } from 'lodash';\r\nimport { NzButtonModule } from 'ng-zorro-antd/button';\r\nimport { NzCheckboxModule } from 'ng-zorro-antd/checkbox';\r\nimport { NzIconModule } from 'ng-zorro-antd/icon';\r\nimport { NzInputModule } from 'ng-zorro-antd/input';\r\nimport { NzTooltipModule } from 'ng-zorro-antd/tooltip';\r\n\r\n/**\r\n * 生成唯一的行 ID\r\n */\r\nfunction generateRowId(): string {\r\n return `kv_${Date.now().toString(36)}_${Math.random().toString(36).slice(2, 8)}`;\r\n}\r\n\r\n@Component({\r\n selector: 'app-kv-table',\r\n standalone: true,\r\n imports: [\r\n CommonModule,\r\n FormsModule,\r\n NzButtonModule,\r\n NzCheckboxModule,\r\n NzInputModule,\r\n NzIconModule,\r\n NzTooltipModule\r\n ],\r\n template: `\r\n <div class=\"kv-wrap\">\r\n <div class=\"kv-head\">\r\n <div class=\"c-check\">\r\n @if(keepTrailingBlank){\r\n <label nz-checkbox [ngModel]=\"isAllEnabled()\"\r\n (ngModelChange)=\"toggleEnabled($event); \"\r\n ></label>\r\n }\r\n </div>\r\n <div class=\"c-key\">{{keyLabel}}</div>\r\n <div class=\"c-val\">{{valueLabel}}</div>\r\n <div class=\"c-des\">{{descriptionLabel}}</div>\r\n <div class=\"c-op\"></div>\r\n </div>\r\n <div class=\"kv-body\">\r\n @for (r of rows; let idx = $index; track r.id) {\r\n <div class=\"kv-row\">\r\n <div class=\"c-check\">\r\n <label nz-checkbox [ngModel]=\"r.enabled\" [nzDisabled]=\"!keepTrailingBlank\" (ngModelChange)=\"setEnabled($index, $event)\"></label>\r\n </div>\r\n <div class=\"c-key\" [nz-tooltip]=\"!keepTrailingBlank ? '自动提取Url 中的 Path 参数,支持{param} 与 :param' : ''\">\r\n <input\r\n nz-input\r\n [readonly]=\"!keepTrailingBlank\"\r\n [placeholder]=\"keyPlaceholder\"\r\n [ngModel]=\"r.key\"\r\n (ngModelChange)=\"setKey(idx, $event)\"\r\n />\r\n </div>\r\n <div class=\"c-val\">\r\n <input\r\n nz-input\r\n [placeholder]=\"valuePlaceholder\"\r\n [ngModel]=\"r.value\"\r\n (ngModelChange)=\"setValue(idx, $event)\"\r\n />\r\n </div>\r\n <div class=\"c-des\">\r\n <input\r\n nz-input\r\n [placeholder]=\"descriptionLabel\"\r\n [ngModel]=\"r.description\"\r\n (ngModelChange)=\"setDescription(idx, $event)\"\r\n />\r\n </div>\r\n <div class=\"c-op\">\r\n <button nz-button nzType=\"text\" (click)=\"removeRow(idx)\" nz-tooltip nzTooltipTitle=\"删除\">\r\n <nz-icon nzType=\"minus-circle\" nzTheme=\"outline\" />\r\n </button>\r\n </div>\r\n </div>\r\n }\r\n </div>\r\n </div>\r\n `,\r\n styles: [`\r\n .kv-wrap{ display:flex; flex-direction:column; height:100%; }\r\n .kv-toolbar{\r\n padding:8px 0;\r\n display:flex;\r\n justify-content:space-between;\r\n align-items:center;\r\n gap:10px;\r\n }\r\n .kv-toolbar .left, .kv-toolbar .right{ display:flex; gap:8px; align-items:center; }\r\n .hint{ font-size:12px; opacity:.7; }\r\n\r\n .kv-head{\r\n display:grid;\r\n grid-template-columns: 40px 1fr 1fr 2fr 44px;\r\n gap:8px;\r\n padding:6px 0;\r\n font-size:14px;\r\n border-bottom:1px solid #f0f0f0;\r\n align-items:center;\r\n .c-key, .c-val, .c-des{\r\n opacity:.75;\r\n }\r\n }\r\n\r\n .kv-body{\r\n flex:1 1 auto;\r\n overflow:auto;\r\n padding:8px 0;\r\n }\r\n\r\n .kv-row{\r\n display:grid;\r\n grid-template-columns: 40px 1fr 1fr 2fr 44px;\r\n gap:8px;\r\n align-items:center;\r\n padding:6px 0;\r\n border-bottom:1px dashed #f0f0f0;\r\n }\r\n\r\n .c-check{ display:flex; justify-content:center; }\r\n .c-op{ display:flex; justify-content:center; }\r\n\r\n .kv-empty{\r\n padding:16px;\r\n opacity:.75;\r\n display:flex;\r\n align-items:center;\r\n justify-content:space-between;\r\n border:1px dashed #e8e8e8;\r\n border-radius:8px;\r\n margin-top:8px;\r\n }\r\n `],\r\n})\r\nexport class KvTableComponent implements OnChanges {\r\n ngOnChanges(changes: SimpleChanges): void {\r\n if (changes['rows']) {\r\n this.rows = this.withTrailingBlank(this.ensureRowIds(this.rows));\r\n }\r\n }\r\n @Input() rows: ApiRequestKvRow[] = [];\r\n @Output() rowsChange = new EventEmitter<ApiRequestKvRow[]>();\r\n\r\n @Input() keyLabel = 'Key';\r\n @Input() valueLabel = 'Value';\r\n @Input() keyPlaceholder = 'key';\r\n @Input() valuePlaceholder = 'value';\r\n @Input() descriptionLabel = 'Description';\r\n\r\n @Input() keepTrailingBlank = true;\r\n\r\n enabledCount = computed(() => this.rows.filter(x => x.enabled).length);\r\n\r\n isAllEnabled(): boolean {\r\n return this.rows.length > 0 && this.rows.every(x => x.enabled);\r\n }\r\n\r\n toggleEnabled(checked: boolean) {\r\n const next = this.rows.map(r => ({ ...r, enabled: checked }));\r\n this.emit(next);\r\n }\r\n private emit(next: ApiRequestKvRow[]) {\r\n this.rowsChange.emit(next);\r\n }\r\n\r\n /**\r\n * 确保所有行都有唯一 ID\r\n */\r\n private ensureRowIds(rows: ApiRequestKvRow[]): ApiRequestKvRow[] {\r\n return rows.map(r => {\r\n if (!r.id || r.id.trim() === '') {\r\n return { ...r, id: generateRowId() };\r\n }\r\n return r;\r\n });\r\n }\r\n\r\n private withTrailingBlank(rows: ApiRequestKvRow[]) {\r\n return this.keepTrailingBlank ? this.ensureTrailingBlank(rows) : rows;\r\n }\r\n\r\n private createBlankRow(): ApiRequestKvRow {\r\n return { id: generateRowId(), key: '', value: '', description: '', enabled: true };\r\n }\r\n\r\n private isBlankRow(r: ApiRequestKvRow | undefined | null): boolean {\r\n if (!r) return true;\r\n const k = (r.key ?? '').trim();\r\n const v = (r.value ?? '').trim();\r\n const d = (r.description ?? '').trim();\r\n return !k && !v && !d;\r\n }\r\n /** 核心:保证末尾永远有一行空白行 */\r\n private ensureTrailingBlank(rows: ApiRequestKvRow[]): ApiRequestKvRow[] {\r\n const list = Array.isArray(rows) ? rows : [];\r\n if (list.length === 0) return [this.createBlankRow()];\r\n\r\n const last = list[list.length - 1];\r\n if (this.isBlankRow(last)) return list;\r\n\r\n return [...list, this.createBlankRow()];\r\n }\r\n\r\n /** 轻量比较:同引用直接认为相同;否则只比较长度+最后一行是否空白(避免频繁 emit) */\r\n private sameRowsRefOrContent(a: ApiRequestKvRow[], b: ApiRequestKvRow[]): boolean {\r\n if (a === b) return true;\r\n if (a.length !== b.length) return false;\r\n // 只用来阻止 ngOnChanges 的兜底 emit 抖动\r\n const aLastBlank = this.isBlankRow(a[a.length - 1]);\r\n const bLastBlank = this.isBlankRow(b[b.length - 1]);\r\n return aLastBlank === bLastBlank;\r\n }\r\n\r\n removeRow(i: number) {\r\n const base = this.rows.filter((_, idx) => idx !== i);\r\n this.emit(this.withTrailingBlank(base));\r\n }\r\n\r\n setEnabled(i: number, enabled: boolean) {\r\n const base = this.rows.map((r, idx) => idx === i ? { ...r, enabled } : r);\r\n this.emit(base);\r\n }\r\n\r\n setValue(i: number, value: string) {\r\n this.patchRow(i, { value });\r\n }\r\n\r\n setKey(i: number, key: string) {\r\n this.patchRow(i, { key });\r\n }\r\n\r\n setDescription(i: number, description: string) {\r\n this.patchRow(i, { description });\r\n }\r\n\r\n private patchRow(i: number, partial: Partial<ApiRequestKvRow>) {\r\n const base = this.rows.map((r, idx) => idx === i ? { ...r, ...partial } : r);\r\n this.emit(this.withTrailingBlank(base));\r\n }\r\n\r\n addRow() {\r\n const base = [...this.rows, this.createBlankRow()];\r\n this.emit(this.withTrailingBlank(base));\r\n }\r\n\r\n clearDisabled() {\r\n const base = this.rows.filter(x => x.enabled);\r\n this.emit(this.withTrailingBlank(base));\r\n }\r\n\r\n}\r\n","import { CommonModule } from '@angular/common';\r\nimport { Component, EventEmitter, Input, OnChanges, Output, SimpleChanges, computed, inject, signal } from '@angular/core';\r\nimport { FormsModule } from '@angular/forms';\r\nimport { NzButtonModule } from 'ng-zorro-antd/button';\r\nimport { NzInputModule } from 'ng-zorro-antd/input';\r\nimport { NzMessageService } from 'ng-zorro-antd/message';\r\nimport { NzSelectModule } from 'ng-zorro-antd/select';\r\n\r\nimport type { ApiRequestEntityBody, ApiRequestEntityBodyMode, ApiRequestKvRow } from '@models/api-client/api-request.model';\r\nimport { KvTableComponent } from './kv-table.component';\r\nimport { uniqueId } from 'lodash';\r\n\r\n\r\n@Component({\r\n selector: 'app-body-editor',\r\n standalone: true,\r\n imports: [CommonModule, FormsModule, NzButtonModule, NzInputModule, NzSelectModule, KvTableComponent],\r\n template: `\r\n <div class=\"wrap\">\r\n <div class=\"bar\">\r\n <nz-select class=\"mode\" [ngModel]=\"mode()\" (ngModelChange)=\"setMode($event)\">\r\n @for (m of modes; track m) {\r\n <nz-option [nzValue]=\"m\" [nzLabel]=\"m\"></nz-option>\r\n }\r\n </nz-select>\r\n\r\n <input\r\n nz-input\r\n class=\"ctype\"\r\n placeholder=\"content-type(可选)\"\r\n [ngModel]=\"contentType()\"\r\n (ngModelChange)=\"setContentType($event)\"\r\n />\r\n\r\n @if(mode()==='json'){\r\n <button nz-button nzType=\"default\" (click)=\"formatJson()\">格式化 JSON</button>\r\n }\r\n </div>\r\n\r\n <div class=\"main\">\r\n @switch (mode()) {\r\n @case ('none') {\r\n <div class=\"empty\">无 Body</div>\r\n }\r\n @case ('text') {\r\n <textarea\r\n nz-input\r\n class=\"ta\"\r\n placeholder=\"文本内容\"\r\n [ngModel]=\"textBody()\"\r\n (ngModelChange)=\"setTextBody($event)\"\r\n ></textarea>\r\n }\r\n @case ('json') {\r\n <textarea\r\n nz-input\r\n class=\"ta\"\r\n placeholder=\"{ }\"\r\n [ngModel]=\"jsonText()\"\r\n (ngModelChange)=\"setJsonText($event)\"\r\n ></textarea>\r\n @if(jsonError()){\r\n <div class=\"err\">{{jsonError()}}</div>\r\n }\r\n }\r\n @case ('urlencoded') {\r\n <app-kv-table\r\n [rows]=\"urlRows()\"\r\n (rowsChange)=\"setUrlRows($event)\"\r\n keyLabel=\"Key\"\r\n valueLabel=\"Value\"\r\n keyPlaceholder=\"a\"\r\n valuePlaceholder=\"1\"\r\n />\r\n }\r\n @default {\r\n <div class=\"empty\">MVP 仅支持 none/json/text/urlencoded</div>\r\n }\r\n }\r\n </div>\r\n </div>\r\n `,\r\n styles: [`\r\n .wrap{ display:flex; flex-direction:column; height:100%; min-height:260px; }\r\n .bar{\r\n display:flex; gap:10px; align-items:center;\r\n padding:8px 0; border-bottom:1px solid #f0f0f0;\r\n }\r\n .mode{ width:140px; }\r\n .ctype{ flex:1 1 auto; }\r\n .main{ flex:1 1 auto; overflow:auto; padding-top:10px; }\r\n .ta{ width:100%; height:100%; min-height:240px; font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, \"Liberation Mono\", \"Courier New\", monospace; font-size:12px; }\r\n .empty{ padding:12px; opacity:.7; }\r\n .err{ margin-top:8px; color:#a8071a; font-size:12px; }\r\n `],\r\n})\r\nexport class BodyEditorComponent implements OnChanges {\r\n\r\n private msg = inject(NzMessageService);\r\n\r\n @Input() body: ApiRequestEntityBody | undefined;\r\n @Output() bodyChange = new EventEmitter<ApiRequestEntityBody | undefined>();\r\n //用 signal 承载输入\r\n private bodySig = signal<ApiRequestEntityBody | undefined>(undefined);\r\n\r\n modes: Array<ApiRequestEntityBodyMode> = ['none', 'json', 'text', 'urlencoded', 'form', 'binary'];\r\n\r\n // local json text buffer(避免用户输入过程中频繁 JSON.parse 崩)\r\n private _jsonText = signal('');\r\n\r\n mode = computed(() => (this.bodySig()?.mode ?? 'none') as ApiRequestEntityBodyMode);\r\n contentType = computed(() => this.bodySig()?.contentType ?? '');\r\n\r\n jsonText = computed(() => {\r\n if (this.mode() !== 'json') return '';\r\n // 如果外部 content 是 object,优先 stringify;如果是 string,用 string\r\n const c = this.body?.content;\r\n if (typeof c === 'string') return c;\r\n if (c == null) return this._jsonText() || '';\r\n try { return JSON.stringify(c, null, 2); } catch { return this._jsonText() || ''; }\r\n });\r\n\r\n jsonError = signal<string>('');\r\n\r\n textBody = computed(() => (this.body?.mode === 'text' ? String(this.body?.content ?? '') : ''));\r\n\r\n urlRows = computed<ApiRequestKvRow[]>(() => {\r\n if (this.body?.mode !== 'urlencoded') return [];\r\n const c = this.body?.content;\r\n // 约定:urlencoded content 用 Record<string,string>\r\n if (!c || typeof c !== 'object' || Array.isArray(c)) return [];\r\n return Object.entries(c).map(([k, v]) => ({ key: k, value: String(v ?? ''), enabled: true, id: uniqueId() }));\r\n });\r\n\r\n setMode(m: ApiRequestEntityBodyMode) {\r\n // 切换 mode 时给一个合理的默认 contentType(只在未填写时)\r\n const prev = this.body;\r\n const next: any = { ...(prev ?? {}), mode: m };\r\n\r\n if (!next.contentType) {\r\n if (m === 'json') next.contentType = 'application/json; charset=utf-8';\r\n if (m === 'text') next.contentType = 'text/plain; charset=utf-8';\r\n if (m === 'urlencoded') next.contentType = 'application/x-www-form-urlencoded; charset=utf-8';\r\n if (m === 'none') next.contentType = undefined;\r\n }\r\n\r\n if (m === 'none') {\r\n this.bodyChange.emit({ mode: 'none' } as any);\r\n return;\r\n }\r\n\r\n // 初始化 content\r\n if (m === 'json' && (prev?.mode !== 'json')) next.content = {};\r\n if (m === 'text' && (prev?.mode !== 'text')) next.content = '';\r\n if (m === 'urlencoded' && (prev?.mode !== 'urlencoded')) next.content = {};\r\n\r\n this.bodyChange.emit(next);\r\n }\r\n\r\n ngOnChanges(changes: SimpleChanges): void {\r\n if (changes['body']) {\r\n const b = changes['body'].currentValue as ApiRequestEntityBody | undefined;\r\n this.bodySig.set(b);\r\n if (b?.mode === 'json') {\r\n if (typeof b.content === 'string') this._jsonText.set(b.content);\r\n else this._jsonText.set(b.content ? JSON.stringify(b.content, null, 2) : '');\r\n this.jsonError.set('');\r\n }\r\n }\r\n }\r\n\r\n setContentType(v: string) {\r\n const m = this.mode();\r\n const next: any = { ...(this.body ?? { mode: m }), contentType: v };\r\n this.bodyChange.emit(next);\r\n }\r\n\r\n setTextBody(v: string) {\r\n const next: any = { ...(this.body ?? { mode: 'text' }), mode: 'text', content: v };\r\n this.bodyChange.emit(next);\r\n }\r\n\r\n setJsonText(v: string) {\r\n this._jsonText.set(v);\r\n this.jsonError.set('');\r\n\r\n // 宽松策略:输入合法 JSON 才写回 content,否则只保留文本缓冲\r\n try {\r\n const parsed = v.trim() ? JSON.parse(v) : {};\r\n const next: any = { ...(this.body ?? { mode: 'json' }), mode: 'json', content: parsed };\r\n this.bodyChange.emit(next);\r\n } catch (e: any) {\r\n this.jsonError.set('JSON 不合法(继续输入即可)');\r\n }\r\n }\r\n\r\n formatJson() {\r\n const m = this.mode();\r\n if (m !== 'json') return;\r\n\r\n const c = this.body?.content;\r\n try {\r\n const text = JSON.stringify(c ?? {}, null, 2);\r\n this._jsonText.set(text);\r\n this.jsonError.set('');\r\n // 同步写回\r\n const next: any = { ...(this.body ?? { mode: 'json' }), mode: 'json', content: c ?? {} };\r\n this.bodyChange.emit(next);\r\n this.msg.success('已格式化');\r\n } catch {\r\n this.msg.error('格式化失败');\r\n }\r\n }\r\n\r\n setUrlRows(rows: ApiRequestKvRow[]) {\r\n // enabled=false 的不写入 content(更贴近 urlencoded 语义)\r\n const obj: Record<string, string> = {};\r\n for (const r of rows) {\r\n if (!r.enabled) continue;\r\n const k = (r.key ?? '').trim();\r\n if (!k) continue;\r\n obj[k] = String(r.value ?? '');\r\n }\r\n\r\n const next: any = { ...(this.body ?? { mode: 'urlencoded' }), mode: 'urlencoded', content: obj };\r\n this.bodyChange.emit(next);\r\n }\r\n}\r\n","/* angular:styles/component:less;989bfd31cb990865c0ab42417664c48b1b5293cfb0401f010d5e9468c95df56e;D:\\ng-manager\\webapp\\src\\app\\pages\\api-client\\components\\request-editor\\env-picker.component.ts */\n.picker {\n display: flex;\n gap: 8px;\n align-items: center;\n}\n.sel {\n width: 160px;\n}\n/*# sourceMappingURL=env-picker.component.css.map */\n","import { computed, effect, inject, Injectable, signal } from '@angular/core';\r\nimport { ApiCollectionCreateBody, ApiCollectionEntity, ApiCollectionKind, ApiCollectionTreeNode, ApiCollectionUpdateBody, ApiRequestEntity, ApiRequestKvRow, ApiScope } from '@models/api-client';\r\nimport { ApiEnvEntity } from '@models/api-client/api-environment.model';\r\nimport { ApiHistoryEntity } from '@models/api-client/api-history.model';\r\nimport { ProjectStateService } from '@pages/projects/services/project.state.service';\r\nimport { uniqueId } from 'lodash';\r\nimport { NzMessageService } from 'ng-zorro-antd/message';\r\nimport { ApiClientTabStore } from '../store/api-client-tab.store';\r\nimport { envVarsToRecord, genCollectionTreeNodes } from '../utils';\r\nimport { ApiClientService } from './api-client.service';\r\nimport { CollectionModalService } from './collection-modal.service';\r\nimport { ProjectContextStore } from '@app/core/stores';\r\n\r\nfunction now() {\r\n return Date.now();\r\n}\r\nfunction newLocalId(prefix: string) {\r\n const rand = Math.random().toString(16).slice(2, 10);\r\n return `${prefix}_${rand}_${Date.now().toString(16)}`;\r\n}\r\n\r\n@Injectable({\r\n providedIn: 'root',\r\n})\r\nexport class ApiClientStateService {\r\n private api = inject(ApiClientService);\r\n private msg = inject(NzMessageService);\r\n private projectContext = inject(ProjectContextStore);\r\n private collectionModal = inject(CollectionModalService);\r\n \r\n // Tab Store\r\n readonly tabStore = inject(ApiClientTabStore);\r\n\r\n // request state\r\n scope = signal<ApiScope>('project');\r\n loading = signal(false);\r\n\r\n q = signal(''); // 搜索关键词\r\n\r\n // 使用 Tab Store 的 sending 状态\r\n sending = this.tabStore.sending;\r\n requests = signal<ApiRequestEntity[]>([]); // 全部请求列表\r\n\r\n // 当前选中请求 ID - 改用 Tab Store\r\n activeRequestId = computed(() => this.tabStore.activeTab()?.requestId ?? null);\r\n\r\n readonly collections = signal<ApiCollectionEntity[]>([]);\r\n\r\n readonly activeCollectionId = signal<string | null>(null);\r\n\r\n readonly nodes = computed<ApiCollectionTreeNode[]>(() => {\r\n return genCollectionTreeNodes(this.collections(), this.requests(), '').filter(n => n.kind !== 'request');\r\n });\r\n\r\n filteredNodes = computed(() => {\r\n const q = this.q().toLowerCase();\r\n return genCollectionTreeNodes(this.collections(), this.requests(), q ?? '');\r\n })\r\n\r\n // history state\r\n historyOpen = signal(false); // 是否打开 history 面板\r\n historyLoading = signal(false); // history 加载中\r\n histories = signal<ApiHistoryEntity[]>([]); // 历史记录列表\r\n\r\n // environments state\r\n envs = signal<ApiEnvEntity[]>([]);\r\n envLoading = signal(false);\r\n activeEnvId = signal<string | null>(null);\r\n\r\n // send result - 改用 Tab Store\r\n lastResult = this.tabStore.activeResponse;\r\n\r\n // project info\r\n projectId = computed(() => {\r\n const p = this.projectContext.currentProject();\r\n return p?.id ?? '';\r\n });\r\n \r\n // activeRequest 改用 Tab Store\r\n activeRequest = this.tabStore.activeRequest;\r\n \r\n // Tab 相关\r\n readonly tabs = this.tabStore.tabs;\r\n readonly activeTabId = this.tabStore.activeTabId;\r\n readonly activeTab = this.tabStore.activeTab;\r\n readonly canOpenMore = this.tabStore.canOpenMore;\r\n\r\n activeEnv = computed(() => {\r\n const id = this.activeEnvId();\r\n if (!id) return null;\r\n return this.envs().find(e => e.id === id) ?? null;\r\n });\r\n\r\n envVarRecord = computed(() => {\r\n const env = this.activeEnv();\r\n if (!env) return {};\r\n return envVarsToRecord(env.variables);\r\n });\r\n\r\n collectionPath = computed(() => {\r\n const colId = this.activeCollectionId();\r\n if (!colId) return null;\r\n const col = this.collections().find(c => c.id === colId);\r\n if (!col) return null;\r\n const pathNames: string[] = [];\r\n let parentKey: string | null = `${col.id}`;\r\n while (parentKey) {\r\n const parentNode = this.collections().find(n => n.id === parentKey);\r\n if (parentNode) {\r\n pathNames.unshift(parentNode.name || '未命名');\r\n parentKey = parentNode.parentId ? `${parentNode.parentId}` : null;\r\n } else {\r\n parentKey = null;\r\n }\r\n }\r\n return pathNames.join(' / ');\r\n\r\n });\r\n\r\n private projectCtx = computed(() => {\r\n const p = this.projectContext.currentProject();\r\n if (!p) return null;\r\n return {\r\n scope: 'project' as const,\r\n projectId: p.id,\r\n };\r\n });\r\n\r\n\r\n constructor() {\r\n // project 变化时自动 reload\r\n effect(() => {\r\n if (this.scope() !== 'project') return;\r\n const pid = this.projectId();\r\n if (!pid) return;\r\n // void this.loadRequests();\r\n void this.loadAll();\r\n });\r\n\r\n effect(() => {\r\n const scope = this.scope();\r\n if (scope !== 'project') { void this.loadEnvs(); return; }\r\n const pid = this.projectId();\r\n if (!pid) return;\r\n void this.loadEnvs();\r\n });\r\n }\r\n\r\n async loadAll() {\r\n const ctx = this.projectCtx();\r\n if (!ctx) return;\r\n\r\n this.loading.set(true);\r\n try {\r\n const [cols, reqs] = await Promise.all([\r\n this.api.listCollections(ctx.scope, ctx.projectId),\r\n this.api.listRequests(ctx.scope, ctx.projectId),\r\n ]);\r\n this.collections.set(cols ?? []);\r\n this.requests.set(reqs ?? []);\r\n } finally {\r\n this.loading.set(false);\r\n }\r\n }\r\n\r\n async reloadCollections() {\r\n const ctx = this.projectCtx();\r\n if (!ctx) return;\r\n const cols = await this.api.listCollections(ctx.scope, ctx.projectId);\r\n this.collections.set(cols ?? []);\r\n }\r\n\r\n async reloadRequests() {\r\n const ctx = this.projectCtx();\r\n if (!ctx) return;\r\n const reqs = await this.api.listRequests(ctx.scope, ctx.projectId);\r\n this.requests.set(reqs ?? []);\r\n }\r\n\r\n /**\r\n * 加载请求列表\r\n */\r\n async loadRequests() {\r\n const ctx = this.projectCtx();\r\n if (!ctx) return;\r\n this.loading.set(true);\r\n try {\r\n const list = await this.api.listRequests(ctx.scope, ctx.projectId);\r\n this.requests.set(list);\r\n // 默认选中第一个;如果已有 active 且存在则保留\r\n const active = this.activeRequestId();\r\n if (active && list.some((x) => x.id === active)) return;\r\n if (list.length) {\r\n this.selectRequest(list[0].id);\r\n } else {\r\n this.newTab();\r\n }\r\n } catch (e: any) {\r\n this.msg.error(e?.message ?? '加载请求失败');\r\n } finally {\r\n this.loading.set(false);\r\n }\r\n }\r\n\r\n /**\r\n * 选择请求 - 在新 Tab 中打开\r\n */\r\n selectRequest(id: string) {\r\n const req = this.requests().find((x) => x.id === id) || null;\r\n if (req) {\r\n this.tabStore.openRequestInTab(req, id);\r\n this.activeCollectionId.set(req.collectionId ?? null);\r\n }\r\n }\r\n \r\n /**\r\n * 切换 Tab\r\n */\r\n switchTab(tabId: string): void {\r\n this.tabStore.switchTab(tabId);\r\n const tab = this.tabStore.getTab(tabId);\r\n if (tab?.request.collectionId) {\r\n this.activeCollectionId.set(tab.request.collectionId);\r\n }\r\n }\r\n \r\n /**\r\n * 关闭 Tab\r\n */\r\n closeTab(tabId: string): void {\r\n this.tabStore.closeTab(tabId);\r\n }\r\n \r\n /**\r\n * 新建 Tab\r\n */\r\n newTab(collectionId?: string | null): void {\r\n try {\r\n this.tabStore.openNewTab(collectionId);\r\n this.activeCollectionId.set(collectionId ?? null);\r\n } catch (e: any) {\r\n this.msg.warning(e.message);\r\n }\r\n }\r\n \r\n /**\r\n * 重命名 Tab\r\n */\r\n renameTab(tabId: string, title: string): void {\r\n this.tabStore.renameTab(tabId, title);\r\n }\r\n \r\n /**\r\n * 重排序 Tab\r\n */\r\n reorderTabs(from: number, to: number): void {\r\n this.tabStore.reorderTabs(from, to);\r\n }\r\n\r\n /**\r\n * 处理右键菜单操作\r\n */\r\n handleTabContextMenu(event: { tabId: string; action: string }): void {\r\n switch (event.action) {\r\n case 'close':\r\n this.closeTab(event.tabId);\r\n break;\r\n case 'closeOthers':\r\n this.tabStore.closeOtherTabs(event.tabId);\r\n break;\r\n case 'closeRight':\r\n this.tabStore.closeRightTabs(event.tabId);\r\n break;\r\n case 'closeSaved':\r\n this.tabStore.closeSavedTabs();\r\n break;\r\n case 'closeAll':\r\n this.tabStore.closeAllTabs();\r\n break;\r\n case 'rename':\r\n // 重命名由组件处理(启动编辑模式)\r\n break;\r\n case 'duplicate':\r\n try {\r\n this.tabStore.duplicateTab(event.tabId);\r\n this.msg.success('已复制请求');\r\n } catch (e: any) {\r\n this.msg.warning(e.message);\r\n }\r\n break;\r\n case 'copyUrl':\r\n const url = this.tabStore.getTabUrl(event.tabId);\r\n if (url) {\r\n navigator.clipboard.writeText(url).then(() => {\r\n this.msg.success('URL 已复制到剪贴板');\r\n }).catch(() => {\r\n this.msg.error('复制失败');\r\n });\r\n }\r\n break;\r\n case 'moveTo':\r\n // 获取当前 Tab 的请求\r\n const tab = this.tabStore.getTab(event.tabId);\r\n if (tab?.requestId) {\r\n // 打开移动对话框(复用集合移动逻辑)\r\n this.moveCollection(tab.requestId, 'request');\r\n }\r\n break;\r\n }\r\n }\r\n\r\n /**\r\n * 选择集合\r\n */\r\n selectCollection(id: string) {\r\n this.activeCollectionId.set(id);\r\n }\r\n\r\n /**\r\n * 新建集合 / 文件夹\r\n */\r\n async newCollection(input: {\r\n name?: string;\r\n parentId?: string | null;\r\n kind?: 'collection' | 'folder';\r\n }) {\r\n const ctx = this.projectCtx();\r\n if (!ctx) return;\r\n const body: ApiCollectionCreateBody = {\r\n scope: ctx.scope,\r\n projectId: ctx.projectId,\r\n name: input.name ?? '',\r\n kind: input.kind ?? 'collection',\r\n parentId: input.parentId ?? null,\r\n };\r\n const nodes = this.nodes(); // 全量生成树,拿到最新的 collection list\r\n const createdBody = await this.collectionModal.createCollection({ createBody: body, nodes, kind: body.kind as 'collection' | 'folder', initialParentId: body.parentId ?? null });\r\n if (createdBody) {\r\n const newCol = await this.api.createCollection(createdBody);\r\n this.msg.success('创建成功');\r\n this.collections.update(list => [...list, newCol]);\r\n this.activeCollectionId.set(newCol.id);\r\n }\r\n }\r\n\r\n // 删除集合/文件夹\r\n async deleteCollection(id: string, kind: ApiCollectionKind) {\r\n if (kind === 'request') {\r\n this.removeRequest(id);\r\n return;\r\n }\r\n await this.api.deleteCollection(id, this.scope(), this.projectId());\r\n this.msg.success('已删除');\r\n // await this.loadAll();\r\n // 乐观更新\r\n this.collections.update(list => list.filter(c => c.id !== id));\r\n // 如果当前 active collection 是被删的,重置 active collection\r\n if (this.activeCollectionId() === id) {\r\n const firstCol = this.collections()[0];\r\n this.activeCollectionId.set(firstCol?.id ?? null);\r\n }\r\n }\r\n\r\n /**\r\n * 移动集合/文件夹/请求\r\n */\r\n async moveCollection(id: string, kind: ApiCollectionKind) {\r\n let initialParentId = '';\r\n if (kind == 'request') {\r\n const req = this.requests().find(r => r.id === id);\r\n if (!req) {\r\n this.msg.error('请求不存在');\r\n return;\r\n }\r\n initialParentId = req.collectionId ?? '';\r\n } else {\r\n const col = this.collections().find(c => c.id === id);\r\n if (!col) {\r\n this.msg.error('集合不存在');\r\n return;\r\n }\r\n initialParentId = col.parentId ?? '';\r\n }\r\n const nodes = this.nodes();\r\n const { parentId } = await this.collectionModal.moveTarget({\r\n nodes,\r\n target: { kind, id },\r\n initialParentId,\r\n }) || {};\r\n if (parentId === undefined) return;\r\n\r\n if (kind === 'request') {\r\n const req = this.requests().find(r => r.id === id);\r\n if (!req) {\r\n this.msg.error('请求不存在');\r\n return;\r\n }\r\n const updated: Partial<ApiRequestEntity> = {\r\n collectionId: parentId ?? null,\r\n id: req.id,\r\n };\r\n req.collectionId = parentId ?? null;\r\n await this.api.updateRequest(this.scope(), this.projectId(), updated);\r\n this.requests.update(list => list.map(r => r.id === id ? { ...r, collectionId: parentId ?? null } : r));\r\n // 更新 Tab 中的请求\r\n const tab = this.tabs().find(t => t.requestId === id);\r\n if (tab) {\r\n this.tabStore.updateActiveRequest({ collectionId: parentId ?? null });\r\n }\r\n this.msg.success('修改成功');\r\n } else {\r\n const updated: ApiCollectionUpdateBody = {\r\n parentId: parentId ?? null,\r\n }\r\n const newCol = await this.api.updateCollection(id, updated, this.scope(), this.projectId());\r\n this.collections.update(list => list.map(c => c.id === id ? newCol : c));\r\n this.activeCollectionId.set(newCol.id);\r\n this.msg.success('修改成功');\r\n }\r\n }\r\n\r\n /**\r\n * 重命名集合/文件夹/请求\r\n */\r\n async renameCollection(id: string, kind: ApiCollectionKind) {\r\n let name = '';\r\n if (kind == 'request') {\r\n const req = this.requests().find(r => r.id === id);\r\n if (!req) {\r\n this.msg.error('请求不存在');\r\n return;\r\n }\r\n name = req.name ?? '';\r\n } else {\r\n const col = this.collections().find(c => c.id === id);\r\n if (!col) {\r\n this.msg.error('集合不存在');\r\n return;\r\n }\r\n name = col.name ?? '';\r\n }\r\n const nodes = this.nodes(); // 全量生成树,拿到最新的 collection list\r\n const updated = await this.collectionModal.renameCollection({\r\n nodes,\r\n kind,\r\n targetId: id,\r\n initialName: name,\r\n })\r\n if (!updated) return;\r\n if (kind === 'request') {\r\n await this.api.updateRequest(this.scope(), this.projectId(), { id, name: updated.name });\r\n this.requests.update(list => list.map(r => r.id === id ? { ...r, name: updated.name ?? r.name } : r));\r\n this.msg.success('修改成功');\r\n this.reloadRequests();\r\n } else {\r\n const newCol = await this.api.updateCollection(id, updated, this.scope(), this.projectId());\r\n this.collections.update(list => list.map(c => c.id === id ? newCol : c));\r\n this.msg.success('修改成功');\r\n this.reloadCollections();\r\n }\r\n }\r\n\r\n /**\r\n * 新建请求 - 在新 Tab 中打开\r\n */\r\n newRequest(input: { collectionId?: string | null } = {}) {\r\n const pid = this.projectId();\r\n if (this.scope() === 'project' && !pid) {\r\n this.msg.warning('请先选择项目');\r\n return;\r\n }\r\n this.newTab(input.collectionId);\r\n }\r\n\r\n /**\r\n * 更新当前请求字段 - 使用 Tab Store\r\n */\r\n patchActive(patch: Partial<ApiRequestEntity>) {\r\n this.tabStore.updateActiveRequest(patch);\r\n }\r\n\r\n /**\r\n * 保存当前请求 - 使用 Tab Store\r\n */\r\n async saveActive() {\r\n const req = this.activeRequest();\r\n if (!req) return;\r\n\r\n const scope = this.scope();\r\n const pid = scope === 'project' ? this.projectId() : undefined;\r\n if (scope === 'project' && !pid) throw new Error('projectId missing');\r\n\r\n if (!req.name?.trim()) {\r\n this.msg.warning('名称不能为空');\r\n return;\r\n }\r\n if (!req.url?.trim()) {\r\n this.msg.warning('URL 不能为空');\r\n return;\r\n }\r\n\r\n // 新请求提示保存到集合\r\n if (!req.collectionId) {\r\n const nodes = this.nodes();\r\n const { parentId } = await this.collectionModal.pickCollection({\r\n nodes,\r\n }) || {};\r\n req.collectionId = parentId ?? null;\r\n this.tabStore.updateActiveRequest({ collectionId: req.collectionId });\r\n }\r\n\r\n this.loading.set(true);\r\n try {\r\n const result = await this.api.saveRequest(scope, pid, req);\r\n this.msg.success('已保存');\r\n // 标记 Tab 为已保存\r\n this.tabStore.markActiveSaved(result.id);\r\n await this.loadRequests(); // 重新加载列表\r\n } catch (e: any) {\r\n this.msg.error(e?.message ?? '保存失败');\r\n } finally {\r\n this.loading.set(false);\r\n }\r\n }\r\n\r\n /**\r\n * 发送当前请求 - 使用 Tab Store\r\n */\r\n async sendActive() {\r\n const req = this.activeRequest();\r\n if (!req) return;\r\n await this.sendResolvedRequest(req);\r\n }\r\n async sendHubV2Issues() {\r\n const project = this.projectContext.currentProject();\r\n if (!project?.id) {\r\n this.msg.warning('请先选择项目');\r\n return;\r\n }\r\n\r\n const startedAt = Date.now();\r\n this.tabStore.setSending(true);\r\n this.tabStore.updateActiveResponse(null);\r\n try {\r\n const data = await this.api.hubTokenRequest({\r\n projectId: project.id,\r\n path: `/issues`,\r\n method: 'GET',\r\n query: { page: 1, pageSize: 20 },\r\n });\r\n const bodyText = JSON.stringify(data, null, 2);\r\n const endedAt = Date.now();\r\n this.tabStore.updateActiveResponse({\r\n historyId: `hub_token_${endedAt}`,\r\n response: {\r\n status: 200,\r\n statusText: 'OK',\r\n headers: { 'content-type': 'application/json; charset=utf-8' },\r\n bodyText,\r\n bodySize: bodyText.length,\r\n },\r\n metrics: {\r\n startedAt,\r\n endedAt,\r\n durationMs: endedAt - startedAt,\r\n },\r\n });\r\n this.msg.success(`Hub Issues 请求成功 (${Date.now() - startedAt}ms)`);\r\n } catch (e: any) {\r\n const endedAt = Date.now();\r\n this.tabStore.updateActiveResponse({\r\n historyId: `hub_token_${endedAt}`,\r\n error: {\r\n code: 'HUB_TOKEN_REQUEST_ERROR',\r\n message: e?.message ?? 'Hub Issues 请求失败',\r\n },\r\n metrics: {\r\n startedAt,\r\n endedAt,\r\n durationMs: endedAt - startedAt,\r\n },\r\n });\r\n this.msg.error(e?.message ?? 'Hub Issues 请求失败');\r\n } finally {\r\n this.tabStore.setSending(false);\r\n }\r\n }\r\n\r\n /**\r\n * 删除请求\r\n */\r\n async removeRequest(id: string) {\r\n await this.api.deleteRequest(id, this.scope(), this.projectId());\r\n this.msg.success('已删除');\r\n const list = this.requests().filter(r => r.id !== id);\r\n this.requests.set(list);\r\n // 关闭对应的 Tab\r\n const tab = this.tabs().find(t => t.requestId === id);\r\n if (tab) {\r\n this.tabStore.closeTab(tab.id);\r\n }\r\n }\r\n \r\n /**\r\n * 确保 Kv 行有 ID\r\n */\r\n private ensureKvId(rows: ApiRequestKvRow[]): ApiRequestKvRow[] {\r\n return rows.map(ele => {\r\n if (!ele.id) {\r\n ele.id = uniqueId();\r\n }\r\n return ele;\r\n })\r\n }\r\n\r\n /**\r\n * 打开历史记录面板\r\n */\r\n openHistory() {\r\n this.historyOpen.set(true);\r\n void this.loadHistory();\r\n }\r\n\r\n /**\r\n * 关闭历史记录面板\r\n */\r\n closeHistory() {\r\n this.historyOpen.set(false);\r\n }\r\n\r\n /**\r\n * 加载历史记录列表\r\n */\r\n async loadHistory() {\r\n this.historyLoading.set(true);\r\n try {\r\n const list = await this.api.listHistory(this.scope(), this.projectId());\r\n this.histories.set(list);\r\n } finally {\r\n this.historyLoading.set(false);\r\n }\r\n }\r\n\r\n /**\r\n * 重放历史记录 - 在新 Tab 中打开\r\n */\r\n async replayHistory(h: ApiHistoryEntity) {\r\n // 在新 Tab 中打开历史请求\r\n this.tabStore.openRequestInTab(h.requestSnapshot);\r\n await this.sendResolvedRequest(h.requestSnapshot);\r\n }\r\n\r\n /**\r\n * 发送已解析的请求 - 使用 Tab Store\r\n */\r\n private async sendResolvedRequest(request: ApiRequestEntity) {\r\n const scope = this.scope();\r\n const pid = scope === 'project' ? this.projectId() : undefined;\r\n if (scope === 'project' && !pid) {\r\n this.msg.warning('请先选择项目');\r\n return;\r\n }\r\n\r\n // 允许未保存直接发送:request 直传\r\n this.tabStore.setSending(true);\r\n this.tabStore.updateActiveResponse(null);\r\n try {\r\n const res = await this.api.send({\r\n scope,\r\n projectId: pid || undefined,\r\n request,\r\n envId: this.activeEnvId() ?? undefined,\r\n projectRoot:(this.projectContext.currentProject() as any)?.root, // 有就传,没有就 undefined\r\n });\r\n this.tabStore.updateActiveResponse(res);\r\n if (res.error) {\r\n this.msg.error(`${res.error.code}: ${res.error.message}`);\r\n } else {\r\n this.msg.success(`HTTP ${res.response?.status ?? ''} (${res.metrics.durationMs}ms)`);\r\n }\r\n } catch (e: any) {\r\n this.msg.error(e?.message ?? '发送失败');\r\n } finally {\r\n this.tabStore.setSending(false);\r\n }\r\n }\r\n\r\n async loadEnvs() {\r\n const scope = this.scope();\r\n const pid = scope === 'project' ? this.projectId() : undefined;\r\n if (scope === 'project' && !pid) return;\r\n\r\n this.envLoading.set(true);\r\n try {\r\n const list = await this.api.listEnvs(scope, pid);\r\n this.envs.set(list);\r\n // 保底:若当前 active 不存在,默认选第一个;没有则为 null\r\n const cur = this.activeEnvId();\r\n if (cur && list.some(x => x.id === cur)) return;\r\n this.activeEnvId.set(list[0]?.id ?? null);\r\n } finally {\r\n this.envLoading.set(false);\r\n }\r\n }\r\n\r\n // 给 UI 用:切换 env\r\n setActiveEnv(id: string | null) {\r\n this.activeEnvId.set(id);\r\n }\r\n\r\n // upsert env(MVP:简单做保存后 reload)\r\n async saveEnv(env: ApiEnvEntity) {\r\n const scope = this.scope();\r\n const pid = scope === 'project' ? this.projectId() : undefined;\r\n await this.api.saveEnv(scope, pid || undefined, env);\r\n await this.loadEnvs();\r\n }\r\n\r\n async deleteEnv(id: string) {\r\n await this.api.deleteEnv(id, this.scope(), this.projectId());\r\n if (this.activeEnvId() === id) {\r\n this.activeEnvId.set(null);\r\n }\r\n await this.loadEnvs();\r\n }\r\n}\r\n","import { computed, effect, Injectable, signal } from '@angular/core';\r\nimport { isEqual, uniqueId } from 'lodash';\r\nimport type { ApiRequestEntity } from '@models/api-client/api-request.model';\r\nimport type { SendResponse } from '@models/api-client/api-send.model';\r\nimport type { ApiClientTab } from '@models/api-client/api-tab.model';\r\n\r\nconst TAB_STORAGE_KEY = 'hub-v2:api-client:tabs';\r\nconst MAX_STORAGE_AGE = 7 * 24 * 60 * 60 * 1000; // 7 天\r\n\r\nfunction now(): number {\r\n return Date.now();\r\n}\r\n\r\nfunction generateTabId(): string {\r\n return `tab_${now().toString(16)}_${Math.random().toString(16).slice(2, 8)}`;\r\n}\r\n\r\n/**\r\n * API Client Tab 状态管理\r\n * 支持多请求并行编辑\r\n */\r\n@Injectable({ providedIn: 'root' })\r\nexport class ApiClientTabStore {\r\n readonly maxTabs = 20;\r\n\r\n // State\r\n readonly tabs = signal<ApiClientTab[]>([]);\r\n readonly activeTabId = signal<string | null>(null);\r\n readonly sending = signal(false);\r\n\r\n // Computed\r\n readonly activeTab = computed(() => {\r\n const id = this.activeTabId();\r\n const tabs = this.tabs();\r\n return id ? tabs.find((t) => t.id === id) ?? null : null;\r\n });\r\n\r\n readonly activeRequest = computed(() => this.activeTab()?.request ?? null);\r\n\r\n readonly activeResponse = computed(() => this.activeTab()?.lastResponse ?? null);\r\n\r\n readonly canOpenMore = computed(() => this.tabs().length < this.maxTabs);\r\n\r\n readonly tabCount = computed(() => this.tabs().length);\r\n\r\n constructor() {\r\n // 初始化时从 LocalStorage 恢复\r\n this.restoreFromStorage();\r\n\r\n // 变化时自动保存\r\n effect(() => {\r\n const tabs = this.tabs();\r\n const activeId = this.activeTabId();\r\n this.saveToStorage(tabs, activeId);\r\n });\r\n }\r\n\r\n /**\r\n * 创建空白 Tab\r\n */\r\n createEmptyTab(collectionId?: string | null): ApiClientTab {\r\n const t = now();\r\n const request: ApiRequestEntity = {\r\n id: `req_${t.toString(16)}_${Math.random().toString(16).slice(2, 6)}`,\r\n name: '',\r\n method: 'GET',\r\n url: '',\r\n collectionId: collectionId ?? null,\r\n query: [],\r\n pathParams: [],\r\n headers: [],\r\n body: { mode: 'none' },\r\n auth: { type: 'none' },\r\n options: { followRedirects: true, timeoutMs: 30_000 },\r\n tags: [],\r\n createdAt: t,\r\n updatedAt: t,\r\n };\r\n\r\n return {\r\n id: generateTabId(),\r\n requestId: null,\r\n request,\r\n title: 'New Request',\r\n isDirty: false,\r\n lastResponse: null,\r\n createdAt: t,\r\n updatedAt: t,\r\n };\r\n }\r\n\r\n /**\r\n * 新建 Tab\r\n */\r\n openNewTab(collectionId?: string | null): string {\r\n if (!this.canOpenMore()) {\r\n throw new Error('已达到最大 Tab 数量限制');\r\n }\r\n\r\n const tab = this.createEmptyTab(collectionId);\r\n this.tabs.update((tabs) => [...tabs, tab]);\r\n this.activeTabId.set(tab.id);\r\n return tab.id;\r\n }\r\n\r\n /**\r\n * 在新 Tab 中打开请求\r\n */\r\n openRequestInTab(request: ApiRequestEntity, requestId?: string): string {\r\n // 检查是否已打开\r\n const existing = this.tabs().find((t) => t.requestId === request.id);\r\n if (existing) {\r\n this.activeTabId.set(existing.id);\r\n return existing.id;\r\n }\r\n\r\n if (!this.canOpenMore()) {\r\n throw new Error('已达到最大 Tab 数量限制');\r\n }\r\n\r\n const t = now();\r\n const requestCopy = { ...request };\r\n const tab: ApiClientTab = {\r\n id: generateTabId(),\r\n requestId: request.id,\r\n request: requestCopy,\r\n savedSnapshot: requestCopy, // 保存快照用于比较\r\n title: this.generateTabTitle(request),\r\n isDirty: false,\r\n lastResponse: null,\r\n createdAt: t,\r\n updatedAt: t,\r\n };\r\n\r\n this.tabs.update((tabs) => [...tabs, tab]);\r\n this.activeTabId.set(tab.id);\r\n return tab.id;\r\n }\r\n\r\n /**\r\n * 关闭 Tab\r\n */\r\n closeTab(tabId: string): void {\r\n const tabs = this.tabs();\r\n const index = tabs.findIndex((t) => t.id === tabId);\r\n\r\n if (index < 0) return;\r\n\r\n // 如果关闭的是当前激活的 Tab,切换到相邻 Tab\r\n const isActive = this.activeTabId() === tabId;\r\n\r\n this.tabs.update((list) => list.filter((t) => t.id !== tabId));\r\n\r\n // 如果关闭后没有 Tab,创建一个新的\r\n if (this.tabs().length === 0) {\r\n const newTab = this.createEmptyTab();\r\n this.tabs.set([newTab]);\r\n this.activeTabId.set(newTab.id);\r\n return;\r\n }\r\n\r\n // 切换激活 Tab\r\n if (isActive) {\r\n const newTabs = this.tabs();\r\n const newIndex = Math.min(index, newTabs.length - 1);\r\n this.activeTabId.set(newTabs[newIndex]?.id ?? null);\r\n }\r\n }\r\n\r\n /**\r\n * 关闭其他 Tab\r\n */\r\n closeOtherTabs(tabId: string): void {\r\n const tab = this.tabs().find((t) => t.id === tabId);\r\n if (!tab) return;\r\n\r\n this.tabs.set([tab]);\r\n this.activeTabId.set(tabId);\r\n }\r\n\r\n /**\r\n * 关闭右侧 Tab\r\n */\r\n closeRightTabs(tabId: string): void {\r\n const index = this.tabs().findIndex((t) => t.id === tabId);\r\n if (index < 0) return;\r\n\r\n this.tabs.update((tabs) => tabs.slice(0, index + 1));\r\n\r\n // 如果当前激活的 Tab 被关闭,切换到指定 Tab\r\n if (!this.tabs().find((t) => t.id === this.activeTabId())) {\r\n this.activeTabId.set(tabId);\r\n }\r\n }\r\n\r\n /**\r\n * 关闭已保存的 Tab\r\n */\r\n closeSavedTabs(): void {\r\n const activeId = this.activeTabId();\r\n const activeTab = this.tabs().find((t) => t.id === activeId);\r\n\r\n this.tabs.update((tabs) => tabs.filter((t) => t.isDirty || !t.requestId));\r\n\r\n // 如果当前激活的 Tab 被关闭,切换到第一个 Tab\r\n if (!this.tabs().find((t) => t.id === activeId)) {\r\n const firstTab = this.tabs()[0];\r\n if (firstTab) {\r\n this.activeTabId.set(firstTab.id);\r\n } else {\r\n // 如果没有 Tab 了,创建一个新的\r\n const newTab = this.createEmptyTab();\r\n this.tabs.set([newTab]);\r\n this.activeTabId.set(newTab.id);\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * 关闭所有 Tab(保留一个空白 Tab)\r\n */\r\n closeAllTabs(): void {\r\n const newTab = this.createEmptyTab();\r\n this.tabs.set([newTab]);\r\n this.activeTabId.set(newTab.id);\r\n }\r\n\r\n /**\r\n * 复制 Tab(创建新 Tab 并复制请求)\r\n */\r\n duplicateTab(tabId: string): string {\r\n const tab = this.tabs().find((t) => t.id === tabId);\r\n if (!tab) throw new Error('Tab not found');\r\n\r\n if (!this.canOpenMore()) {\r\n throw new Error('已达到最大 Tab 数量限制');\r\n }\r\n\r\n const t = now();\r\n const requestCopy: ApiRequestEntity = {\r\n ...tab.request,\r\n id: `req_${t.toString(16)}_${Math.random().toString(16).slice(2, 6)}`,\r\n name: `${tab.request.name || '未命名'} (副本)`,\r\n createdAt: t,\r\n updatedAt: t,\r\n };\r\n\r\n const newTab: ApiClientTab = {\r\n id: generateTabId(),\r\n requestId: null, // 新请求,未保存\r\n request: requestCopy,\r\n savedSnapshot: null,\r\n title: this.generateTabTitle(requestCopy),\r\n isDirty: true, // 副本视为有修改\r\n lastResponse: null,\r\n createdAt: t,\r\n updatedAt: t,\r\n };\r\n\r\n // 插入到当前 Tab 后面\r\n const index = this.tabs().findIndex((t) => t.id === tabId);\r\n this.tabs.update((tabs) => {\r\n const result = [...tabs];\r\n result.splice(index + 1, 0, newTab);\r\n return result;\r\n });\r\n this.activeTabId.set(newTab.id);\r\n\r\n return newTab.id;\r\n }\r\n\r\n /**\r\n * 获取 Tab 的 URL\r\n */\r\n getTabUrl(tabId: string): string | null {\r\n const tab = this.tabs().find((t) => t.id === tabId);\r\n return tab?.request.url ?? null;\r\n }\r\n\r\n /**\r\n * 切换 Tab\r\n */\r\n switchTab(tabId: string): void {\r\n const tab = this.tabs().find((t) => t.id === tabId);\r\n if (tab) {\r\n this.activeTabId.set(tabId);\r\n }\r\n }\r\n\r\n /**\r\n * 重命名 Tab - 同时更新 request.name\r\n */\r\n renameTab(tabId: string, title: string): void {\r\n this.tabs.update((tabs) =>\r\n tabs.map((t) => {\r\n if (t.id !== tabId) return t;\r\n // 同步更新 request.name\r\n const updatedRequest = { ...t.request, name: title, updatedAt: now() };\r\n return { \r\n ...t, \r\n title, \r\n request: updatedRequest,\r\n isDirty: t.requestId ? true : t.isDirty, // 已保存的请求重命名后标记为 dirty\r\n updatedAt: now() \r\n };\r\n })\r\n );\r\n }\r\n\r\n /**\r\n * 重排序 Tab\r\n */\r\n reorderTabs(fromIndex: number, toIndex: number): void {\r\n if (fromIndex === toIndex) return;\r\n\r\n this.tabs.update((tabs) => {\r\n const result = [...tabs];\r\n const [removed] = result.splice(fromIndex, 1);\r\n result.splice(toIndex, 0, removed);\r\n return result;\r\n });\r\n }\r\n\r\n /**\r\n * 更新当前 Tab 的请求\r\n */\r\n updateActiveRequest(patch: Partial<ApiRequestEntity>): void {\r\n const activeId = this.activeTabId();\r\n if (!activeId) return;\r\n\r\n this.tabs.update((tabs) =>\r\n tabs.map((t) => {\r\n if (t.id !== activeId) return t;\r\n \r\n const updated = { ...t.request, ...patch, updatedAt: now() };\r\n \r\n // 与保存时的快照比较,判断是否有变化\r\n const snapshot = t.savedSnapshot;\r\n const hasChanges = snapshot ? this.hasChanges(snapshot, updated) : true;\r\n \r\n return {\r\n ...t,\r\n request: updated,\r\n title: this.generateTabTitle(updated),\r\n isDirty: hasChanges,\r\n updatedAt: now(),\r\n };\r\n })\r\n );\r\n }\r\n\r\n /**\r\n * 更新当前 Tab 的响应\r\n */\r\n updateActiveResponse(response: SendResponse | null): void {\r\n const activeId = this.activeTabId();\r\n if (!activeId) return;\r\n\r\n this.tabs.update((tabs) =>\r\n tabs.map((t) =>\r\n t.id === activeId ? { ...t, lastResponse: response, updatedAt: now() } : t\r\n )\r\n );\r\n }\r\n\r\n /**\r\n * 标记当前 Tab 为已保存\r\n */\r\n markActiveSaved(requestId: string): void {\r\n const activeId = this.activeTabId();\r\n if (!activeId) return;\r\n\r\n this.tabs.update((tabs) =>\r\n tabs.map((t) => {\r\n if (t.id !== activeId) return t;\r\n // 保存时更新快照\r\n return { \r\n ...t, \r\n requestId, \r\n savedSnapshot: { ...t.request }, // 更新快照\r\n isDirty: false, \r\n updatedAt: now() \r\n };\r\n })\r\n );\r\n }\r\n\r\n /**\r\n * 标记当前 Tab 为脏\r\n */\r\n markActiveDirty(): void {\r\n const activeId = this.activeTabId();\r\n if (!activeId) return;\r\n\r\n this.tabs.update((tabs) =>\r\n tabs.map((t) =>\r\n t.id === activeId ? { ...t, isDirty: true, updatedAt: now() } : t\r\n )\r\n );\r\n }\r\n\r\n /**\r\n * 设置发送状态\r\n */\r\n setSending(value: boolean): void {\r\n this.sending.set(value);\r\n }\r\n\r\n /**\r\n * 获取 Tab\r\n */\r\n getTab(tabId: string): ApiClientTab | null {\r\n return this.tabs().find((t) => t.id === tabId) ?? null;\r\n }\r\n\r\n /**\r\n * 检查 Tab 是否有未保存修改\r\n */\r\n isTabDirty(tabId: string): boolean {\r\n return this.getTab(tabId)?.isDirty ?? false;\r\n }\r\n\r\n // ========== Private Methods ==========\r\n\r\n private generateTabTitle(request: ApiRequestEntity): string {\r\n if (request.name) return request.name;\r\n\r\n if (!request.url) return 'New Request';\r\n\r\n // 提取路径部分\r\n const url = request.url\r\n .replace(/^\\{\\{[^}]+\\}\\}/, '') // 移除变量前缀\r\n .replace(/^https?:\\/\\/[^/]+/, ''); // 移除域名\r\n\r\n const path = url.split('?')[0] || '/';\r\n\r\n return `${request.method} ${path}`;\r\n }\r\n\r\n private hasChanges(original: ApiRequestEntity, current: ApiRequestEntity): boolean {\r\n // 排除 updatedAt,只比较实际内容\r\n const { updatedAt: _1, ...originalWithoutTime } = original;\r\n const { updatedAt: _2, ...currentWithoutTime } = current;\r\n return !isEqual(originalWithoutTime, currentWithoutTime);\r\n }\r\n\r\n private restoreFromStorage(): void {\r\n try {\r\n const raw = localStorage.getItem(TAB_STORAGE_KEY);\r\n if (!raw) {\r\n this.createInitialTab();\r\n return;\r\n }\r\n\r\n const data = JSON.parse(raw);\r\n const age = Date.now() - data.savedAt;\r\n\r\n if (age > MAX_STORAGE_AGE || !Array.isArray(data.tabs) || data.tabs.length === 0) {\r\n this.createInitialTab();\r\n return;\r\n }\r\n\r\n // 过滤掉过期数据\r\n const validTabs = data.tabs.filter(\r\n (t: ApiClientTab) => t.id && t.request\r\n );\r\n\r\n if (validTabs.length === 0) {\r\n this.createInitialTab();\r\n return;\r\n }\r\n\r\n this.tabs.set(validTabs);\r\n this.activeTabId.set(data.activeTabId ?? validTabs[0].id);\r\n } catch {\r\n this.createInitialTab();\r\n }\r\n }\r\n\r\n private saveToStorage(tabs: ApiClientTab[], activeTabId: string | null): void {\r\n try {\r\n // 只保存必要字段,减少存储大小\r\n const minimalTabs = tabs.map((t) => ({\r\n id: t.id,\r\n requestId: t.requestId,\r\n request: t.request,\r\n title: t.title,\r\n isDirty: t.isDirty,\r\n createdAt: t.createdAt,\r\n updatedAt: t.updatedAt,\r\n }));\r\n\r\n localStorage.setItem(\r\n TAB_STORAGE_KEY,\r\n JSON.stringify({\r\n tabs: minimalTabs,\r\n activeTabId,\r\n savedAt: Date.now(),\r\n })\r\n );\r\n } catch {\r\n // Storage full, 清理旧数据\r\n localStorage.removeItem(TAB_STORAGE_KEY);\r\n }\r\n }\r\n\r\n private createInitialTab(): void {\r\n const tab = this.createEmptyTab();\r\n this.tabs.set([tab]);\r\n this.activeTabId.set(tab.id);\r\n }\r\n}\r\n\r\n","import type { ApiEnvVariable } from '@models/api-client/api-environment.model';\r\n\r\nconst VAR_RE = /\\{\\{\\s*([a-zA-Z0-9_.-]+)\\s*\\}\\}/g;\r\n\r\nexport function envVarsToRecord(vars: ApiEnvVariable[] = []): Record<string, string> {\r\n const out: Record<string, string> = {};\r\n for (const v of vars) {\r\n if (!v.enabled) continue;\r\n out[v.key] = String(v.value ?? '');\r\n }\r\n return out;\r\n}\r\n\r\nexport function findVariables(input: string): string[] {\r\n const found = new Set<string>();\r\n let m: RegExpExecArray | null;\r\n while ((m = VAR_RE.exec(input))) found.add(m[1]);\r\n return [...found];\r\n}\r\n\r\nexport function resolveTemplate(\r\n input: string,\r\n vars: Record<string, string>\r\n): { out: string; missing: string[] } {\r\n const missing = new Set<string>();\r\n const out = input.replace(VAR_RE, (_, key) => {\r\n if (key in vars) return String(vars[key] ?? '');\r\n missing.add(key);\r\n return `{{${key}}}`;\r\n });\r\n return { out, missing: [...missing] };\r\n}\r\n\r\n/** 扫描一组字符串,返回缺失变量集合 */\r\nexport function collectMissingFromStrings(\r\n inputs: string[],\r\n vars: Record<string, string>\r\n): string[] {\r\n const miss = new Set<string>();\r\n for (const s of inputs) {\r\n if (!s) continue;\r\n const { missing } = resolveTemplate(s, vars);\r\n missing.forEach(k => miss.add(k));\r\n }\r\n return [...miss];\r\n}\r\n","import { ApiRequestKvRow } from \"@models/api-client\";\r\nimport { uniqueId } from \"lodash\";\r\n\r\n// 从 URL 字符串中提取 path param keys(去重,保持出现顺序)\r\nexport function extractPathParamKeys(url: string): string[] {\r\n if (!url) return [];\r\n\r\n let pathRaw = url;\r\n\r\n try {\r\n const u = new URL(url);\r\n pathRaw = u.pathname || \"\";\r\n } catch {\r\n // 相对 URL 或未带协议:退化处理\r\n pathRaw = url.split(\"?\")[0].split(\"#\")[0] || \"\";\r\n const idx = pathRaw.indexOf(\"/\");\r\n if (idx >= 0) pathRaw = pathRaw.slice(idx);\r\n }\r\n\r\n // pathname 里可能是 %7B %7D(因为 new URL 会 encode { })\r\n const path = safeDecodeURIComponent(pathRaw);\r\n\r\n const keys: string[] = [];\r\n\r\n // 1) :id\r\n const colonRe = /(?:^|\\/):([A-Za-z_][A-Za-z0-9_]*)/g;\r\n let m: RegExpExecArray | null;\r\n while ((m = colonRe.exec(path))) keys.push(m[1]);\r\n\r\n // 2) {id}\r\n const braceRe = /\\{([A-Za-z_][A-Za-z0-9_]*)\\}/g;\r\n while ((m = braceRe.exec(path))) keys.push(m[1]);\r\n\r\n // // 3) 兜底:直接支持 %7Bid%7D(即便没 decode 成功也能识别)\r\n // const encBraceRe = /%7B([A-Za-z_][A-Za-z0-9_]*)%7D/gi;\r\n // while ((m = encBraceRe.exec(pathRaw))) keys.push(m[1]);\r\n\r\n // 去重但保序\r\n // const seen = new Set<string>();\r\n // const out: string[] = [];\r\n // for (const k of keys) {\r\n // if (seen.has(k)) continue;\r\n // seen.add(k);\r\n // out.push(k);\r\n // }\r\n return keys;\r\n}\r\n\r\nfunction safeDecodeURIComponent(s: string): string {\r\n try {\r\n return decodeURIComponent(s);\r\n } catch {\r\n return s;\r\n }\r\n}\r\n\r\nexport function syncPathParamsByUrl(\r\n url: string,\r\n current: ApiRequestKvRow[] | undefined | null\r\n): ApiRequestKvRow[] {\r\n const keys = extractPathParamKeys(url);\r\n // console.log('syncPathParamsByUrl', url, keys);\r\n const list = Array.isArray(current) ? current : [];\r\n\r\n // 建索引:只拿有效 key 的行(忽略 kv-table 尾行空白)\r\n const map = new Map<string, ApiRequestKvRow>();\r\n for (const r of list) {\r\n const k = (r.key ?? \"\").trim();\r\n if (!k) continue;\r\n if (!map.has(k)) map.set(k, r);\r\n }\r\n\r\n // 生成目标 rows(按 keys 顺序)\r\n const next: ApiRequestKvRow[] = keys.map((k) => {\r\n const old = map.get(k);\r\n if (old) {\r\n // path params 不允许 checkbox:强制 enabled=true\r\n return { ...old, key: k, enabled: true };\r\n }\r\n return { key: k, value: \"\", description: \"\", enabled: true, id: uniqueId() };\r\n });\r\n\r\n return next;\r\n}\r\n","import type { ApiEnvVariable, ApiRequestKvRow } from '@models/api-client';\r\nimport { } from '@models/index';\r\nimport { uniqueId } from 'lodash';\r\n\r\nexport function envVarsToRows(vars: ApiEnvVariable[]): ApiRequestKvRow[] {\r\n return (vars ?? []).map(v => ({\r\n key: v.key,\r\n value: v.value,\r\n enabled: v.enabled,\r\n id: uniqueId(),\r\n description: v.description,\r\n }));\r\n}\r\n\r\nexport function rowsToEnvVars(\r\n rows: ApiRequestKvRow[],\r\n prev?: ApiEnvVariable[]\r\n): ApiEnvVariable[] {\r\n const prevMap = new Map(prev?.map(v => [v.key, v]));\r\n return rows\r\n .filter(r => r.key?.trim())\r\n .map(r => ({\r\n key: r.key.trim(),\r\n value: String(r.value ?? ''),\r\n enabled: r.enabled !== false,\r\n secret: prevMap.get(r.key)?.secret,\r\n }));\r\n}\r\n","import type {\r\n ApiCollectionEntity,\r\n ApiCollectionKind,\r\n ApiCollectionTreeNode,\r\n ApiRequestEntity,\r\n} from \"@models/api-client\";\r\n\r\nfunction matchRequest(r: ApiRequestEntity, kw: string) {\r\n if (!kw) return true;\r\n const name = (r.name ?? \"\").toLowerCase();\r\n const url = (r.url ?? \"\").toLowerCase();\r\n return name.includes(kw) || url.includes(kw);\r\n}\r\n\r\n/** normalize id for map keys: null/undefined/''/'null'/'undefined' => null */\r\nfunction normId(v: unknown): string | null {\r\n if (v === null || v === undefined) return null;\r\n const s = String(v).trim();\r\n if (!s) return null;\r\n const l = s.toLowerCase();\r\n if (l === \"null\" || l === \"undefined\") return null;\r\n return s;\r\n}\r\n\r\nfunction sortCollections(a: ApiCollectionEntity, b: ApiCollectionEntity) {\r\n return (\r\n (a.parentId ?? \"\").localeCompare(b.parentId ?? \"\") ||\r\n (a.order ?? 0) - (b.order ?? 0) ||\r\n (a.name ?? \"\").localeCompare(b.name ?? \"\")\r\n );\r\n}\r\n\r\nfunction sortRequests(a: ApiRequestEntity, b: ApiRequestEntity) {\r\n return (\r\n (normId(a.collectionId) ?? \"\").localeCompare(normId(b.collectionId) ?? \"\") ||\r\n (a.order ?? 0) - (b.order ?? 0) ||\r\n (a.name ?? \"\").localeCompare(b.name ?? \"\") ||\r\n (a.url ?? \"\").localeCompare(b.url ?? \"\")\r\n );\r\n}\r\n\r\nexport function genCollectionTreeNodes(\r\n collections: ApiCollectionEntity[],\r\n requests: ApiRequestEntity[],\r\n q?: string\r\n): ApiCollectionTreeNode[] {\r\n const kw = q?.trim().toLowerCase() || \"\";\r\n\r\n // 先做稳定排序,避免 map push 时顺序漂移\r\n const colsSorted = [...(collections ?? [])].sort(sortCollections);\r\n const reqsSorted = [...(requests ?? [])].sort(sortRequests);\r\n\r\n // collections children: parentId -> []\r\n const colChildren = new Map<string | null, ApiCollectionEntity[]>();\r\n for (const c of colsSorted) {\r\n const pid = normId(c.parentId);\r\n const arr = colChildren.get(pid) ?? [];\r\n arr.push(c);\r\n colChildren.set(pid, arr);\r\n }\r\n\r\n // requests children: collectionId -> []\r\n const reqChildren = new Map<string | null, ApiRequestEntity[]>();\r\n for (const r of reqsSorted) {\r\n if (!matchRequest(r, kw)) continue;\r\n const cid = normId(r.collectionId);\r\n const arr = reqChildren.get(cid) ?? [];\r\n arr.push(r);\r\n reqChildren.set(cid, arr);\r\n }\r\n\r\n const buildReqNode = (r: ApiRequestEntity, parentKey: string | null): ApiCollectionTreeNode => ({\r\n key: `r:${String(r.id)}`,\r\n kind: \"request\" as ApiCollectionKind,\r\n id: String(r.id),\r\n title: r.name ?? \"未命名\",\r\n name: r.name,\r\n subtitle: r.url ?? \"\",\r\n method: r.method ?? \"\",\r\n parentKey,\r\n children: [],\r\n });\r\n\r\n const buildCol = (c: ApiCollectionEntity, parentKey: string | null): ApiCollectionTreeNode => {\r\n const id = normId(c.id)!; // collection id 必须存在\r\n const key = `c:${id}`;\r\n\r\n const childCols = colChildren.get(id) ?? [];\r\n const childReqs = reqChildren.get(id) ?? [];\r\n\r\n return {\r\n key,\r\n kind: (c.kind ?? \"collection\") as ApiCollectionKind,\r\n id,\r\n title: c.name ?? \"未命名\",\r\n name: c.name,\r\n parentKey,\r\n children: [\r\n ...childCols.map((cc) => buildCol(cc, key)),\r\n ...childReqs.map((r) => buildReqNode(r, key)),\r\n ],\r\n };\r\n };\r\n\r\n const rootCols = colChildren.get(null) ?? [];\r\n const rootReqs = reqChildren.get(null) ?? [];\r\n\r\n return [\r\n ...rootCols.map((c) => buildCol(c, null)),\r\n ...rootReqs.map((r) => buildReqNode(r, null)),\r\n ];\r\n}\r\n","import { HttpParams } from '@angular/common/http';\r\nimport { inject, Injectable } from '@angular/core';\r\nimport { ApiClient } from '@app/core';\r\nimport { LocalStateStore, LS_KEYS } from '@core/local-state';\r\nimport { ApiHistoryEntity } from '@models/api-client/api-history.model';\r\nimport { ApiCollectionCreateBody, ApiCollectionEntity, ApiCollectionUpdateBody, ApiRequestEntity, ApiScope, SendRequestBody, SendResponse } from '@models/api-client';\r\nimport { ApiEnvEntity } from '@models/api-client/api-environment.model';\r\nimport { firstValueFrom } from 'rxjs';\r\n\r\n\r\n@Injectable({\r\n providedIn: 'root',\r\n})\r\nexport class ApiClientService {\r\n private http = inject(ApiClient);\r\n private ls = inject(LocalStateStore);\r\n private base = '/api/client';\r\n\r\n async listRequests(scope: ApiScope, projectId?: string) {\r\n let params = new HttpParams().set('scope', scope);\r\n if (projectId) params = params.set('projectId', projectId);\r\n return await firstValueFrom(this.http.get<ApiRequestEntity[]>(`${this.base}/requests`, params));\r\n }\r\n\r\n async saveRequest(scope: ApiScope, projectId: string | undefined, request: ApiRequestEntity) {\r\n return await firstValueFrom(\r\n this.http.post<{ id: string }>(`${this.base}/requests`, { scope, projectId, request })\r\n );\r\n }\r\n\r\n async updateRequest(scope: ApiScope, projectId: string | undefined, request: Partial<ApiRequestEntity>) {\r\n return await firstValueFrom(\r\n this.http.post<{ id: string }>(`${this.base}/requests/update`, { scope, projectId, request })\r\n );\r\n }\r\n\r\n\r\n async deleteRequest(id: string, scope: ApiScope, projectId?: string) {\r\n let params = new HttpParams().set('scope', scope);\r\n if (projectId) params = params.set('projectId', projectId);\r\n return await firstValueFrom(\r\n this.http.delete<{ ok: true }>(`${this.base}/requests/${id}`, params)\r\n );\r\n }\r\n\r\n async send(body: SendRequestBody) {\r\n return await firstValueFrom(this.http.post<SendResponse>(`${this.base}/send`, body));\r\n }\r\n\r\n async hubTokenRequest(body: {\r\n projectId: string;\r\n tokenType?: 'project' | 'personal';\r\n path: string;\r\n method?: \"GET\" | \"POST\" | \"PUT\" | \"PATCH\" | \"DELETE\";\r\n query?: Record<string, string | number | boolean | undefined | null>;\r\n payload?: unknown;\r\n headers?: Record<string, string>;\r\n personalToken?: string;\r\n }) {\r\n const tokenType = body.tokenType ?? 'project';\r\n let personalToken = body.personalToken;\r\n if (tokenType === 'personal' && !personalToken) {\r\n personalToken = this.ls.get<string>(LS_KEYS.token.hubV2PersonalToken, '').trim() || undefined;\r\n }\r\n return await firstValueFrom(this.http.post<unknown>(`${this.base}/hub-token/request`, {\r\n projectId: body.projectId,\r\n tokenType,\r\n path: body.path,\r\n method: body.method ?? \"GET\",\r\n query: body.query,\r\n body: body.payload,\r\n headers: body.headers,\r\n personalToken,\r\n }));\r\n }\r\n\r\n async listHistory(scope: ApiScope, projectId?: string) {\r\n let params = new HttpParams().set('scope', scope);\r\n if (projectId) params = params.set('projectId', projectId);\r\n return await firstValueFrom(\r\n this.http.get<ApiHistoryEntity[]>(`${this.base}/history`, params)\r\n );\r\n }\r\n\r\n async listEnvs(scope: ApiScope, projectId?: string) {\r\n let params = new HttpParams().set('scope', scope);\r\n if (projectId) params = params.set('projectId', projectId);\r\n return await firstValueFrom(this.http.get<ApiEnvEntity[]>(`${this.base}/envs`, params));\r\n }\r\n\r\n async saveEnv(scope: ApiScope, projectId: string | undefined, env: ApiEnvEntity) {\r\n return await firstValueFrom(\r\n this.http.post<{ id: string }>(`${this.base}/envs`, { scope, projectId, env })\r\n );\r\n }\r\n\r\n async deleteEnv(id: string, scope: ApiScope, projectId?: string) {\r\n let params = new HttpParams().set('scope', scope);\r\n if (projectId) params = params.set('projectId', projectId);\r\n return await firstValueFrom(this.http.delete<{ ok: true }>(`${this.base}/envs/${id}`, params));\r\n }\r\n\r\n // Collection APIs\r\n async listCollections(scope: ApiScope, projectId?: string) {\r\n let params = new HttpParams().set('scope', scope);\r\n if (projectId) params = params.set('projectId', projectId);\r\n return await firstValueFrom(this.http.get<ApiCollectionEntity[]>(`${this.base}/collections`, params));\r\n }\r\n\r\n async createCollection(body: ApiCollectionCreateBody) {\r\n return await firstValueFrom(\r\n this.http.post<ApiCollectionEntity>(`${this.base}/collections`, body)\r\n );\r\n }\r\n\r\n async updateCollection(id: string, body: Partial<ApiCollectionUpdateBody>, scope: ApiScope, projectId?: string) {\r\n const params = new HttpParams().set('scope', scope).set('projectId', projectId ?? '');\r\n return await firstValueFrom(\r\n this.http.post<ApiCollectionEntity>(`${this.base}/collections/${id}`, body, params)\r\n );\r\n }\r\n\r\n async deleteCollection(id: string, scope: ApiScope, projectId?: string) {\r\n const params = new HttpParams().set('scope', scope).set('projectId', projectId ?? '');\r\n return await firstValueFrom(\r\n this.http.delete<{ ok: true }>(`${this.base}/collections/${id}`, params)\r\n );\r\n }\r\n\r\n}\r\n","/* angular:styles/component:less;32be14231e9363af865b7f69f0194cb76bf9c5d76ff7c68f00d4860a8e3402d3;D:\\ng-manager\\webapp\\src\\app\\pages\\api-client\\components\\request-collections\\collection-modal.component.ts */\n.modal-body {\n display: grid;\n gap: 12px;\n}\n.label {\n font-weight: 600;\n}\n.hint {\n font-size: 12px;\n opacity: 0.75;\n}\n.hint.err {\n color: #cf1322;\n opacity: 1;\n}\n.picker {\n max-height: 52vh;\n overflow: auto;\n border: 1px solid rgba(0, 0, 0, 0.08);\n border-radius: 12px;\n padding: 8px;\n display: flex;\n flex-direction: column;\n gap: 6px;\n}\n.row {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 8px 8px;\n border-radius: 10px;\n cursor: pointer;\n -webkit-user-select: none;\n user-select: none;\n transition: background 0.15s;\n border: 1px solid transparent;\n}\n.row:hover {\n background: rgba(0, 0, 0, 0.04);\n}\n.row.selected {\n background: rgba(0, 0, 0, 0.08);\n border-color: rgba(0, 0, 0, 0.08);\n}\n.row.root {\n font-weight: 600;\n}\n.chev {\n flex: 0 0 auto;\n}\n.chev nz-icon {\n font-size: 12px;\n transition: transform 0.15s;\n}\n.icon {\n opacity: 0.75;\n}\n.title {\n flex: 1;\n min-width: 0;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n.empty {\n padding: 16px;\n opacity: 0.6;\n text-align: center;\n}\n.footer {\n display: flex;\n justify-content: flex-end;\n gap: 8px;\n margin-top: 16px;\n}\n/*# sourceMappingURL=collection-modal.component.css.map */\n","import { CommonModule } from '@angular/common';\r\nimport { Component, computed, inject, signal } from '@angular/core';\r\nimport { FormsModule } from '@angular/forms';\r\nimport { NzButtonModule } from 'ng-zorro-antd/button';\r\nimport { NzIconModule } from 'ng-zorro-antd/icon';\r\nimport { NzInputModule } from 'ng-zorro-antd/input';\r\nimport { NZ_MODAL_DATA, NzModalRef } from 'ng-zorro-antd/modal';\r\n\r\nimport type {\r\n ApiCollectionCreateBody,\r\n ApiCollectionTreeNode,\r\n ApiCollectionUpdateBody,\r\n ApiCollectionModalData,\r\n ApiCollectionRenameModalData,\r\n ApiCollectionCreateModalData,\r\n ApiCollectionMoveModalData,\r\n} from '@models/api-client';\r\n\r\ntype Key = string; // \"c:xxx\"\r\nfunction toKey(id: string | null | undefined): Key | null {\r\n return id ? `c:${id}` : null;\r\n}\r\nfunction keyToId(key: Key | null): string | null {\r\n if (!key) return null;\r\n return key.startsWith('c:') ? key.slice(2) : null;\r\n}\r\n\r\n@Component({\r\n selector: 'app-collection-modal',\r\n standalone: true,\r\n imports: [CommonModule, FormsModule, NzInputModule, NzButtonModule, NzIconModule],\r\n template: `\r\n <div class=\"modal-body\">\r\n @if (showName()) {\r\n <label class=\"label\">名称</label>\r\n <nz-input-wrapper >\r\n <input\r\n nz-input\r\n [ngModel]=\"name()\"\r\n (ngModelChange)=\"name.set($event)\"\r\n placeholder=\"请输入名称\"\r\n autofocus\r\n />\r\n <nz-icon nzInputPrefix [nzType]=\"iconForKind()\" nzTheme=\"outline\"></nz-icon>\r\n </nz-input-wrapper>\r\n @if (nameErr()) { <div class=\"hint err\">{{ nameErr() }}</div> }\r\n }\r\n\r\n @if (showParentPicker()) {\r\n <!-- <label class=\"label\">{{mode() === 'move' ? '移动到' : '选择目录'}}</label> -->\r\n <!-- <nz-input-wrapper >\r\n <input nz-input placeholder=\"搜索目录\" [ngModel]=\"q()\" (ngModelChange)=\"q.set($event)\" />\r\n <nz-icon class=\"search-icon\" nzInputSuffix nzType=\"search\" />\r\n </nz-input-wrapper> -->\r\n\r\n <div class=\"picker\">\r\n <div class=\"row root\" [class.selected]=\"selectedKey() === null\" (click)=\"select(null)\">\r\n <nz-icon nzType=\"home\"></nz-icon>\r\n <span>根目录</span>\r\n </div>\r\n\r\n @for (n of filteredNodes(); track n.key) {\r\n <ng-container\r\n [ngTemplateOutlet]=\"nodeTpl\"\r\n [ngTemplateOutletContext]=\"{ $implicit: n, level: 0 }\"\r\n />\r\n }\r\n\r\n @if (!filteredNodes().length) {\r\n <div class=\"empty\">暂无目录</div>\r\n }\r\n </div>\r\n\r\n @if (moveErr()) { <div class=\"hint err\">{{ moveErr() }}</div> }\r\n }\r\n </div>\r\n\r\n <div class=\"footer\">\r\n <button nz-button (click)=\"cancel()\">取消</button>\r\n <button nz-button nzType=\"primary\" [disabled]=\"!canSubmit()\" (click)=\"ok()\">\r\n 确定\r\n </button>\r\n </div>\r\n\r\n <ng-template #nodeTpl let-node let-level=\"level\">\r\n <div\r\n class=\"row\"\r\n [style.paddingLeft.px]=\"8 + level * 16\"\r\n [class.selected]=\"selectedKey() === node.key\"\r\n (click)=\"select(node.key)\"\r\n >\r\n <button\r\n class=\"chev\"\r\n nz-button\r\n nzType=\"text\"\r\n nzSize=\"small\"\r\n (click)=\"toggle(node.key); $event.stopPropagation()\"\r\n [disabled]=\"!node.children?.length\"\r\n >\r\n <nz-icon [nzType]=\"node.children?.length ? (expanded(node.key) ? 'down' : 'right') : 'minus'\"></nz-icon>\r\n </button>\r\n <nz-icon class=\"icon\" [nzType]=\"node.kind === 'folder' ? 'folder' : 'database'\"></nz-icon>\r\n <span class=\"title\">{{ node.title }}</span>\r\n </div>\r\n\r\n @if ((node.children?.length ?? 0) && expanded(node.key)) {\r\n @for (c of node.children; track c.key) {\r\n <ng-container\r\n [ngTemplateOutlet]=\"nodeTpl\"\r\n [ngTemplateOutletContext]=\"{ $implicit: c, level: level + 1 }\"\r\n />\r\n }\r\n }\r\n </ng-template>\r\n `,\r\n styles: [`\r\n .modal-body { display: grid; gap: 12px; }\r\n .label{ font-weight:600; }\r\n .hint { font-size: 12px; opacity: .75; }\r\n .hint.err{ color:#cf1322; opacity:1; }\r\n\r\n .picker{\r\n max-height: 52vh;\r\n overflow:auto;\r\n border: 1px solid rgba(0,0,0,.08);\r\n border-radius: 12px;\r\n padding: 8px;\r\n display:flex;\r\n flex-direction:column;\r\n gap:6px;\r\n }\r\n .row{\r\n display:flex;\r\n align-items:center;\r\n gap:8px;\r\n padding:8px 8px;\r\n border-radius:10px;\r\n cursor:pointer;\r\n user-select:none;\r\n transition: background .15s;\r\n border: 1px solid transparent;\r\n }\r\n .row:hover{ background: rgba(0,0,0,.04); }\r\n .row.selected{ background: rgba(0,0,0,.08); border-color: rgba(0,0,0,.08); }\r\n .row.root{ font-weight:600; }\r\n .chev{ flex:0 0 auto; nz-icon{font-size:12px;transition:transform .15s} }\r\n .icon{ opacity:.75; }\r\n .title{ flex:1; min-width:0; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }\r\n .empty{ padding:16px; opacity:.6; text-align:center; }\r\n\r\n .footer { display: flex; justify-content: flex-end; gap: 8px; margin-top: 16px; }\r\n `],\r\n})\r\nexport class CollectionModalComponent {\r\n readonly data = inject<ApiCollectionModalData>(NZ_MODAL_DATA);\r\n private modalRef = inject(NzModalRef<CollectionModalComponent>);\r\n\r\n // state\r\n q = signal('');\r\n name = signal('');\r\n selectedKey = signal<Key | null>(null); // move 时使用,null=根目录\r\n\r\n private expandedMap = signal<Record<string, boolean>>({});\r\n\r\n // mode\r\n mode = computed(() => (this.data as any).mode ?? (this.data as any).handleType); // 兼容你旧字段,建议尽快统一为 mode\r\n\r\n // 只有 move 才显示树\r\n showParentPicker = computed(() => this.mode() === 'move' || this.mode() === 'pick');\r\n\r\n // create/rename 才显示 name;move 不显示 name\r\n showName = computed(() => this.mode() === 'create' || this.mode() === 'rename');\r\n\r\n iconForKind = computed(() => {\r\n const kind = (this.data as any).kind ?? ((this.data as any).createBody?.kind ?? 'collection');\r\n return kind === 'folder' ? 'folder' : kind === 'request' ? 'api' : 'database';\r\n });\r\n\r\n // init\r\n ngOnInit() {\r\n const mode = this.mode();\r\n\r\n if (mode === 'create') {\r\n const body = (this.data as ApiCollectionCreateModalData).createBody as ApiCollectionCreateBody | undefined;\r\n this.name.set(body?.name ?? '');\r\n this.selectedKey.set(null);\r\n return;\r\n }\r\n\r\n if (mode === 'rename' || mode === 'update') {\r\n const upd = this.data as ApiCollectionRenameModalData\r\n this.name.set((upd?.initialName ?? '') as string);\r\n this.selectedKey.set(null);\r\n return;\r\n }\r\n\r\n\r\n // move\r\n const initial = (this.data as ApiCollectionMoveModalData).initialParentId as string | null | undefined;\r\n this.selectedKey.set(initial ? (initial.startsWith('c:') ? initial : toKey(initial)) : null);\r\n\r\n // 默认展开一级\r\n const nodes = ((this.data as any).nodes ?? []) as ApiCollectionTreeNode[];\r\n const m: Record<string, boolean> = {};\r\n for (const n of nodes) m[n.key] = true;\r\n this.expandedMap.set(m);\r\n }\r\n\r\n // tree helpers\r\n expanded(key: string) { return !!this.expandedMap()[key]; }\r\n toggle(key: string) {\r\n const m = { ...this.expandedMap() };\r\n m[key] = !m[key];\r\n this.expandedMap.set(m);\r\n }\r\n select(key: Key | null) { this.selectedKey.set(key); }\r\n\r\n // ---------- 仅 move 场景:过滤非法父级(移动文件夹/集合时防环) ----------\r\n private forbiddenKeys = computed<Set<string>>(() => {\r\n if (this.mode() !== 'move' || this.mode() !== 'pick') return new Set();\r\n const t = (this.data as any).target as { kind: 'request' | 'collection' | 'folder'; id: string } | undefined;\r\n if (!t || t.kind === 'request') return new Set();\r\n\r\n const selfKey = `c:${t.id}`;\r\n const set = new Set<string>([selfKey]);\r\n\r\n const nodes = ((this.data as any).nodes ?? []) as ApiCollectionTreeNode[];\r\n\r\n const collect = (node: ApiCollectionTreeNode) => {\r\n for (const c of (node.children ?? [])) {\r\n if (c.kind === 'request') continue;\r\n set.add(c.key);\r\n collect(c);\r\n }\r\n };\r\n\r\n const walk = (arr: ApiCollectionTreeNode[]) => {\r\n for (const n of arr) {\r\n if (n.key === selfKey) collect(n);\r\n else if (n.children?.length) walk(n.children);\r\n }\r\n };\r\n\r\n walk(nodes);\r\n return set;\r\n });\r\n\r\n nodesForPicker = computed<ApiCollectionTreeNode[]>(() => {\r\n const nodes = (((this.data as any).nodes ?? []) as ApiCollectionTreeNode[])\r\n .filter(n => n.kind !== 'request');\r\n\r\n const forbid = this.forbiddenKeys();\r\n\r\n const prune = (arr: ApiCollectionTreeNode[]): ApiCollectionTreeNode[] => {\r\n const out: ApiCollectionTreeNode[] = [];\r\n for (const n of arr) {\r\n if (n.kind === 'request') continue;\r\n if (forbid.has(n.key)) continue;\r\n const children = prune(n.children ?? []);\r\n out.push({ ...n, children });\r\n }\r\n return out;\r\n };\r\n\r\n return prune(nodes);\r\n });\r\n\r\n filteredNodes = computed<ApiCollectionTreeNode[]>(() => {\r\n if (!this.showParentPicker()) return [];\r\n const kw = this.q().trim().toLowerCase();\r\n if (!kw) return this.nodesForPicker();\r\n\r\n const match = (n: ApiCollectionTreeNode) => (n.title ?? '').toLowerCase().includes(kw);\r\n\r\n const keepPath = (arr: ApiCollectionTreeNode[]): ApiCollectionTreeNode[] => {\r\n const out: ApiCollectionTreeNode[] = [];\r\n for (const n of arr) {\r\n const children = keepPath(n.children ?? []);\r\n if (match(n) || children.length) out.push({ ...n, children });\r\n }\r\n return out;\r\n };\r\n\r\n const r = keepPath(this.nodesForPicker());\r\n\r\n // 搜索时自动展开命中路径\r\n const m = { ...this.expandedMap() };\r\n const mark = (arr: ApiCollectionTreeNode[]) => {\r\n for (const n of arr) {\r\n if (n.children?.length) m[n.key] = true;\r\n if (n.children?.length) mark(n.children);\r\n }\r\n };\r\n mark(r);\r\n this.expandedMap.set(m);\r\n\r\n return r;\r\n });\r\n\r\n // ---------- validation ----------\r\n nameErr = computed(() => {\r\n if (!this.showName()) return '';\r\n const v = (this.name() ?? '').trim();\r\n if (!v) return '名称不能为空';\r\n if (v.length > 50) return '名称过长(<= 50)';\r\n return '';\r\n });\r\n\r\n moveErr = computed(() => {\r\n if (!this.showParentPicker()) return '';\r\n // move 必须选一个父级(允许根目录=null)\r\n // 这里无需额外校验;但你若要禁止把 folder 移到根,可在这加规则\r\n return '';\r\n });\r\n\r\n canSubmit = computed(() => {\r\n if (this.showName() && !!this.nameErr()) return false;\r\n if (this.showParentPicker()) {\r\n // selectedKey 默认有值(null=根);如果你希望“必须明确选择”,可改成 selectedKey() !== undefined\r\n return true;\r\n }\r\n return true;\r\n });\r\n\r\n // ---------- submit ----------\r\n ok() {\r\n const mode = this.mode();\r\n\r\n // 兼容旧字段:update = rename\r\n if (mode === 'rename' || mode === 'update') {\r\n const data: ApiCollectionUpdateBody = { name: (this.name() ?? '').trim() };\r\n this.modalRef.close(data);\r\n return;\r\n }\r\n\r\n if (mode === 'create') {\r\n const body = (this.data as any).createBody as ApiCollectionCreateBody;\r\n const data: ApiCollectionCreateBody = {\r\n ...body,\r\n name: (this.name() ?? '').trim(),\r\n // parentId 不在 modal 里改:完全沿用外部传入\r\n parentId: body.parentId ?? null,\r\n };\r\n this.modalRef.close(data);\r\n return;\r\n }\r\n\r\n // move pick\r\n const parentId = keyToId(this.selectedKey());\r\n this.modalRef.close({ parentId });\r\n }\r\n\r\n cancel() {\r\n this.modalRef.close(null);\r\n }\r\n}\r\n","import { Injectable, inject } from '@angular/core';\r\nimport { NzModalService } from 'ng-zorro-antd/modal';\r\nimport { firstValueFrom } from 'rxjs';\r\nimport type {\r\n ApiCollectionCreateBody,\r\n ApiCollectionKind,\r\n ApiCollectionTreeNode,\r\n ApiCollectionUpdateBody,\r\n} from '@models/api-client';\r\nimport { CollectionModalComponent } from '../components/request-collections/collection-modal.component';\r\n\r\n@Injectable({ providedIn: 'root' })\r\nexport class CollectionModalService {\r\n private modal = inject(NzModalService);\r\n\r\n async createCollection(opts: {\r\n kind: 'collection' | 'folder';\r\n createBody: ApiCollectionCreateBody;\r\n nodes: ApiCollectionTreeNode[];\r\n initialParentId?: string | null; // 纯 id\r\n }): Promise<ApiCollectionCreateBody | null> {\r\n const ref = this.modal.create<CollectionModalComponent, any, any>({\r\n nzTitle: opts.kind === 'folder' ? '新建目录' : '新建集合',\r\n nzContent: CollectionModalComponent,\r\n nzFooter: null,\r\n nzWidth: 520,\r\n nzMaskClosable: false,\r\n nzData: {\r\n mode: 'create',\r\n createBody: opts.createBody,\r\n nodes: opts.nodes,\r\n },\r\n });\r\n return await firstValueFrom(ref.afterClose);\r\n }\r\n\r\n async renameCollection(opts: {\r\n kind: ApiCollectionKind;\r\n nodes: ApiCollectionTreeNode[];\r\n targetId: string;\r\n initialName: string;\r\n }): Promise<ApiCollectionUpdateBody | null> {\r\n const ref = this.modal.create<CollectionModalComponent, any, any>({\r\n nzTitle: '重命名',\r\n nzContent: CollectionModalComponent,\r\n nzFooter: null,\r\n nzWidth: 520,\r\n nzMaskClosable: false,\r\n nzData: {\r\n mode: 'rename',\r\n kind: opts.kind,\r\n nodes: opts.nodes,\r\n targetId: opts.targetId,\r\n initialName: opts.initialName,\r\n },\r\n });\r\n return await firstValueFrom(ref.afterClose);\r\n }\r\n\r\n async moveTarget(opts: {\r\n nodes: ApiCollectionTreeNode[];\r\n target: { kind: ApiCollectionKind; id: string };\r\n initialParentId?: string | null; // 纯 id\r\n }): Promise<{ parentId: string | null } | null> {\r\n const ref = this.modal.create<CollectionModalComponent, any, any>({\r\n nzTitle: '移动到',\r\n nzContent: CollectionModalComponent,\r\n nzFooter: null,\r\n nzWidth: 520,\r\n nzMaskClosable: false,\r\n nzData: {\r\n mode: 'move',\r\n nodes: opts.nodes,\r\n target: opts.target,\r\n initialParentId: opts.initialParentId ?? null,\r\n },\r\n });\r\n return await firstValueFrom(ref.afterClose);\r\n }\r\n\r\n async pickCollection(opts: {\r\n nodes: ApiCollectionTreeNode[];\r\n }): Promise<{ parentId: string | null } | null> {\r\n const ref = this.modal.create<CollectionModalComponent, any, any>({\r\n nzTitle: '选择集合/目录',\r\n nzContent: CollectionModalComponent,\r\n nzFooter: null,\r\n nzWidth: 520,\r\n nzMaskClosable: false,\r\n nzData: {\r\n mode: 'pick',\r\n nodes: opts.nodes,\r\n },\r\n });\r\n return await firstValueFrom(ref.afterClose);\r\n }\r\n}\r\n","/* angular:styles/component:less;eabe06dfbf0a15b95c1f401a19b9b1c63a1f01a532d9737274095873e85fa695;D:\\ng-manager\\webapp\\src\\app\\pages\\api-client\\components\\request-editor\\env-modal.component.ts */\n.drawer {\n display: grid;\n grid-template-columns: 180px 1fr;\n gap: 12px;\n height: 100%;\n}\n.left {\n border-right: 1px solid #f0f0f0;\n padding-right: 12px;\n}\n.toolbar {\n padding-bottom: 10px;\n}\n.env-list {\n display: flex;\n flex-direction: column;\n gap: 8px;\n}\n.env-item {\n padding: 8px;\n border: 1px solid #f0f0f0;\n border-radius: 8px;\n cursor: pointer;\n}\n.env-item.active {\n background: #f5f5f5;\n}\n.name {\n font-weight: 600;\n}\n.meta {\n font-size: 12px;\n opacity: 0.7;\n}\n.right {\n min-width: 0;\n}\n.empty {\n padding: 12px;\n opacity: 0.7;\n}\n.row {\n display: grid;\n grid-template-columns: 70px 1fr;\n gap: 10px;\n align-items: center;\n margin-bottom: 10px;\n}\n.label {\n font-size: 14px;\n opacity: 0.8;\n}\n.vars {\n height: 420px;\n}\n.actions {\n display: flex;\n gap: 8px;\n margin-top: 12px;\n}\n/*# sourceMappingURL=env-modal.component.css.map */\n","import { CommonModule } from '@angular/common';\r\nimport { Component, computed, EventEmitter, inject, Output, signal } from '@angular/core';\r\nimport { FormsModule } from '@angular/forms';\r\nimport { ApiEnvEntity, ApiRequestKvRow } from '@models/api-client';\r\nimport { ApiClientStateService } from '@pages/api-client/services';\r\nimport { envVarsToRows, rowsToEnvVars } from '@pages/api-client/utils';\r\nimport { NzButtonModule } from 'ng-zorro-antd/button';\r\nimport { NzInputModule } from 'ng-zorro-antd/input';\r\nimport { NzMessageService } from 'ng-zorro-antd/message';\r\nimport { NzModalRef } from 'ng-zorro-antd/modal';\r\nimport { NzPopconfirmModule } from 'ng-zorro-antd/popconfirm';\r\nimport { KvTableComponent } from './kv-table.component';\r\nfunction now() { return Date.now(); }\r\nfunction newId(prefix: string) {\r\n const rand = Math.random().toString(16).slice(2, 10);\r\n return `${prefix}_${rand}_${Date.now().toString(16)}`;\r\n}\r\n@Component({\r\n selector: 'app-env-modal.component',\r\n imports: [CommonModule, FormsModule, KvTableComponent, NzButtonModule, NzInputModule, NzPopconfirmModule],\r\n template: `\r\n <div class=\"drawer\">\r\n <div class=\"left\">\r\n <div class=\"toolbar\">\r\n <button nz-button nzType=\"primary\" (click)=\"createEnv()\">新建</button>\r\n </div>\r\n\r\n <div class=\"env-list\">\r\n @for (e of store.envs(); track e.id) {\r\n <div class=\"env-item\" [class.active]=\"e.id===draft()?.id\" (click)=\"selectEditEnv(e.id)\">\r\n <div class=\"name\">{{e.name}}</div>\r\n <div class=\"meta\">{{e.variables.length}} vars</div>\r\n </div>\r\n }\r\n @if(!store.envs().length){\r\n <div class=\"empty\">暂无环境</div>\r\n }\r\n </div>\r\n </div>\r\n\r\n <div class=\"right\">\r\n @if(!draft()?.id){\r\n <div class=\"empty\">选择一个环境进行编辑</div>\r\n } @else {\r\n <div class=\"form\">\r\n <div class=\"row\">\r\n <div class=\"label\">名称</div>\r\n <input nz-input [ngModel]=\"draft()!.name\" (ngModelChange)=\"setName($event)\" />\r\n </div>\r\n <div class=\"row\">\r\n <div class=\"label\">前置URL</div>\r\n <input nz-input [ngModel]=\"draft()!.baseUrl\" (ngModelChange)=\"setBaseUrl($event)\" />\r\n </div>\r\n <div class=\"vars\">\r\n <app-kv-table\r\n [rows]=\"varsRows()\"\r\n (rowsChange)=\"varsRows.set($event)\"\r\n keyLabel=\"Key\"\r\n valueLabel=\"Value\"\r\n keyPlaceholder=\"TOKEN\"\r\n valuePlaceholder=\"xxx\"\r\n />\r\n </div>\r\n\r\n <div class=\"actions\">\r\n <button nz-button nzType=\"primary\" (click)=\"save()\">保存</button>\r\n <button\r\n nz-button\r\n nzType=\"default\"\r\n nzDanger\r\n nz-popconfirm\r\n nzPopconfirmTitle=\"确认删除该环境?\"\r\n (nzOnConfirm)=\"remove()\"\r\n >\r\n 删除\r\n </button>\r\n <button nz-button nzType=\"default\" (click)=\"useThisEnv()\">设为当前</button>\r\n </div>\r\n </div>\r\n }\r\n </div>\r\n </div>\r\n `,\r\n styles: `\r\n .drawer{ display:grid; grid-template-columns: 180px 1fr; gap:12px; height:100%; }\r\n .left{ border-right:1px solid #f0f0f0; padding-right:12px; }\r\n .toolbar{ padding-bottom:10px; }\r\n .env-list{ display:flex; flex-direction:column; gap:8px; }\r\n .env-item{ padding:8px; border:1px solid #f0f0f0; border-radius:8px; cursor:pointer; }\r\n .env-item.active{ background:#f5f5f5; }\r\n .name{ font-weight:600; }\r\n .meta{ font-size:12px; opacity:.7; }\r\n .right{ min-width:0; }\r\n .empty{ padding:12px; opacity:.7; }\r\n .row{ display:grid; grid-template-columns: 70px 1fr; gap:10px; align-items:center; margin-bottom:10px; }\r\n .label{ font-size:14px; opacity:.8; }\r\n .vars{ height: 420px; }\r\n .actions{ display:flex; gap:8px; margin-top:12px; }\r\n `,\r\n})\r\nexport class EnvModalComponent {\r\n @Output() envChange = new EventEmitter<string | null>();\r\n\r\n store = inject(ApiClientStateService);\r\n\r\n readonly modalRef = inject(NzModalRef);\r\n private msg = inject(NzMessageService);\r\n\r\n // 编辑缓存\r\n draft = signal<ApiEnvEntity | null>(null);\r\n varsRows = signal<ApiRequestKvRow[]>([]);\r\n\r\n selectEditEnv(id: string) {\r\n this.store.activeEnvId.set(id);\r\n const cur = this.store.envs().find(e => e.id === id);\r\n if (!cur) return;\r\n this.draft.set({ ...cur, variables: cur.variables });\r\n this.varsRows.set(envVarsToRows(cur.variables));\r\n }\r\n\r\n createEnv() {\r\n const t = now();\r\n const env: ApiEnvEntity = {\r\n id: newId('env'),\r\n scope: 'project',\r\n name: '未命名环境',\r\n variables: [],\r\n createdAt: t,\r\n updatedAt: t,\r\n };\r\n // 直接进入编辑态\r\n this.draft.set(env);\r\n this.varsRows.set(envVarsToRows(env.variables));\r\n }\r\n\r\n setName(name: string) {\r\n const d = this.draft();\r\n if (!d) return;\r\n this.draft.set({ ...d, name });\r\n }\r\n\r\n setBaseUrl(baseUrl: string) {\r\n const d = this.draft();\r\n if (!d) return;\r\n this.draft.set({ ...d, baseUrl });\r\n }\r\n\r\n async save() {\r\n const d = this.draft();\r\n if (!d) return;\r\n const env: ApiEnvEntity = {\r\n ...d,\r\n variables: rowsToEnvVars(this.varsRows(), d.variables),\r\n updatedAt: now(),\r\n };\r\n await this.store.saveEnv(env);\r\n // 保存后保持编辑 id(store reload 后列表会更新)\r\n this.store.activeEnvId.set(env.id);\r\n this.msg.success('环境变量保存成功');\r\n this.draft.set(env);\r\n }\r\n\r\n async remove() {\r\n const id = this.store.activeEnvId();\r\n if (!id) return;\r\n await this.store.deleteEnv(id);\r\n this.store.activeEnvId.set(null);\r\n this.draft.set(null);\r\n this.varsRows.set([]);\r\n this.msg.success('环境变量删除成功');\r\n }\r\n\r\n useThisEnv() {\r\n const id = this.store.activeEnvId();\r\n if (!id) return;\r\n this.store.setActiveEnv(id);\r\n }\r\n\r\n close() {\r\n this.modalRef.close();\r\n }\r\n}\r\n\r\nexport type EnvModalData = {\r\n envId: string | null;\r\n envs: ApiEnvEntity[];\r\n saveEnv: (env: ApiEnvEntity) => Promise<void>;\r\n deleteEnv: (id: string) => Promise<void>;\r\n}","import { CommonModule } from '@angular/common';\r\nimport { Component, inject } from '@angular/core';\r\nimport { FormsModule } from '@angular/forms';\r\nimport { NzButtonModule } from 'ng-zorro-antd/button';\r\nimport { NzDrawerModule } from 'ng-zorro-antd/drawer';\r\nimport { NzInputModule } from 'ng-zorro-antd/input';\r\nimport { NzPopconfirmModule } from 'ng-zorro-antd/popconfirm';\r\nimport { NzSelectModule } from 'ng-zorro-antd/select';\r\n\r\nimport { ApiClientStateService } from '@pages/api-client/services';\r\nimport { NzIconModule } from 'ng-zorro-antd/icon';\r\nimport { NzModalService } from 'ng-zorro-antd/modal';\r\nimport { NzTooltipModule } from 'ng-zorro-antd/tooltip';\r\nimport { EnvModalComponent } from './env-modal.component';\r\n\r\n@Component({\r\n selector: 'app-env-picker',\r\n standalone: true,\r\n imports: [\r\n CommonModule,\r\n FormsModule,\r\n NzSelectModule,\r\n NzButtonModule,\r\n NzDrawerModule,\r\n NzInputModule,\r\n NzTooltipModule,\r\n NzIconModule,\r\n NzPopconfirmModule,\r\n ],\r\n template: `\r\n <div class=\"picker\">\r\n <nz-select\r\n class=\"sel\"\r\n [nzPlaceHolder]=\"'Env'\"\r\n [ngModel]=\"store.activeEnvId()\"\r\n (ngModelChange)=\"store.setActiveEnv($event)\"\r\n [nzAllowClear]=\"true\"\r\n >\r\n @for (e of store.envs(); track e.id) {\r\n <nz-option [nzValue]=\"e.id\" [nzLabel]=\"e.name\"></nz-option>\r\n }\r\n </nz-select>\r\n <button nz-button nzType=\"text\" (click)=\"openEnvModal()\" nz-tooltip nzTooltipTitle=\"管理环境变量\">\r\n <nz-icon nzType=\"setting\" nzTheme=\"outline\"></nz-icon>\r\n </button>\r\n </div>\r\n `,\r\n styles: [`\r\n .picker{ display:flex; gap:8px; align-items:center; }\r\n .sel{ width:160px; }\r\n `],\r\n})\r\nexport class EnvPickerComponent {\r\n store = inject(ApiClientStateService);\r\n private modalService = inject(NzModalService);\r\n\r\n openEnvModal() {\r\n const modal = this.modalService.create({\r\n nzTitle: '环境变量',\r\n nzFooter: null,\r\n nzMaskClosable: false,\r\n nzContent: EnvModalComponent,\r\n nzWidth: '1020px',\r\n nzCentered: true,\r\n })\r\n\r\n modal.afterOpen.subscribe(() => {\r\n const instance = modal.getContentComponent() as EnvModalComponent;\r\n if (instance && this.store.activeEnvId()) {\r\n instance.selectEditEnv(this.store.activeEnvId() ?? '');\r\n } else {\r\n instance.createEnv();\r\n }\r\n });\r\n }\r\n\r\n}\r\n","/* angular:styles/component:less;22c649d587fc7dc66f49bbcdaa66d8df46262c892c4428b4ab5dcd2400dd84e3;D:\\ng-manager\\webapp\\src\\app\\pages\\api-client\\components\\request-editor\\request-tabs.component.ts */\n:host {\n display: flex;\n flex-direction: column;\n height: 100%;\n min-height: 0;\n}\napp-kv-table {\n display: block;\n height: 100%;\n}\n.tabs {\n flex: 1 1 auto;\n overflow: hidden;\n height: 100%;\n}\n.tab {\n height: 100%;\n overflow: hidden auto;\n}\n::ng-deep nz-tabs.tabs .ant-tabs-content {\n height: 100%;\n}\n::ng-deep nz-tabs.tabs .ant-tabs-content .ant-tabs-tabpane {\n height: 100%;\n}\n/*# sourceMappingURL=request-tabs.component.css.map */\n","/* angular:styles/component:less;911626d8e9e42e1af92f11315b5e8d0350782730be994257d01c744bb8b89678;D:\\ng-manager\\webapp\\src\\app\\pages\\api-client\\components\\request-editor\\advanced-editor.component.ts */\n.wrap {\n display: flex;\n flex-direction: column;\n height: 100%;\n min-height: 240px;\n}\n.grid {\n display: flex;\n flex-direction: column;\n gap: 14px;\n padding-top: 10px;\n}\n.row {\n display: grid;\n grid-template-columns: 140px 1fr;\n align-items: center;\n gap: 10px;\n}\n.row.checkbox {\n grid-template-columns: 1fr;\n}\n.label {\n font-size: 12px;\n opacity: 0.8;\n}\n.desc {\n grid-column: 2 / span 1;\n font-size: 12px;\n opacity: 0.65;\n}\n.row.checkbox .desc {\n grid-column: 1 / span 1;\n margin-left: 24px;\n}\n.muted {\n color: #999;\n}\n/*# sourceMappingURL=advanced-editor.component.css.map */\n","import { CommonModule } from '@angular/common';\r\nimport { Component, EventEmitter, Input, Output, computed } from '@angular/core';\r\nimport { FormsModule } from '@angular/forms';\r\nimport { NzAlertModule } from 'ng-zorro-antd/alert';\r\nimport { NzCheckboxModule } from 'ng-zorro-antd/checkbox';\r\nimport { NzInputModule } from 'ng-zorro-antd/input';\r\n\r\nimport type { ApiRequestEntity } from '@models/api-client/api-request.model';\r\n\r\ntype Options = ApiRequestEntity['options'];\r\n\r\n@Component({\r\n selector: 'app-advanced-editor',\r\n standalone: true,\r\n imports: [\r\n CommonModule,\r\n FormsModule,\r\n NzCheckboxModule,\r\n NzInputModule,\r\n NzAlertModule,\r\n ],\r\n template: `\r\n <div class=\"wrap\">\r\n <div class=\"grid\">\r\n <!-- timeout -->\r\n <div class=\"row\">\r\n <div class=\"label\">Timeout (ms)</div>\r\n <input\r\n nz-input\r\n type=\"number\"\r\n min=\"0\"\r\n placeholder=\"30000\"\r\n [ngModel]=\"timeoutMs()\"\r\n (ngModelChange)=\"setTimeout($event)\"\r\n />\r\n <div class=\"desc\">请求超时时间,单位毫秒(0 表示不超时)</div>\r\n </div>\r\n\r\n <!-- follow redirects -->\r\n <div class=\"row checkbox\">\r\n <label nz-checkbox [ngModel]=\"followRedirects()\" (ngModelChange)=\"setFollowRedirects($event)\">\r\n Follow Redirects\r\n </label>\r\n <div class=\"desc\">是否自动跟随 HTTP 重定向(302 / 301)</div>\r\n </div>\r\n\r\n <!-- insecure TLS -->\r\n <div class=\"row checkbox\">\r\n <label nz-checkbox [ngModel]=\"insecureTLS()\" (ngModelChange)=\"setInsecureTLS($event)\">\r\n Insecure TLS\r\n </label>\r\n <div class=\"desc\">跳过 TLS 证书校验(仅在 Node 环境下尽力支持)</div>\r\n </div>\r\n\r\n <!-- proxy -->\r\n <div class=\"row\">\r\n <div class=\"label\">Proxy</div>\r\n <input\r\n nz-input\r\n placeholder=\"http://127.0.0.1:7890\"\r\n [ngModel]=\"proxy()\"\r\n (ngModelChange)=\"setProxy($event)\"\r\n />\r\n <div class=\"desc muted\">代理地址(当前版本仅保存,不参与实际请求)</div>\r\n </div>\r\n\r\n <nz-alert\r\n nzType=\"info\"\r\n nzShowIcon\r\n nzMessage=\"说明:Proxy 配置已保存,但当前 NodeHttpClient 尚未实现代理支持,请勿依赖该选项进行调试。\"\r\n ></nz-alert>\r\n </div>\r\n </div>\r\n `,\r\n styles: [`\r\n .wrap{\r\n display:flex;\r\n flex-direction:column;\r\n height:100%;\r\n min-height:240px;\r\n }\r\n\r\n .grid{\r\n display:flex;\r\n flex-direction:column;\r\n gap:14px;\r\n padding-top:10px;\r\n }\r\n\r\n .row{\r\n display:grid;\r\n grid-template-columns: 140px 1fr;\r\n align-items:center;\r\n gap:10px;\r\n }\r\n\r\n .row.checkbox{\r\n grid-template-columns: 1fr;\r\n }\r\n\r\n .label{\r\n font-size:12px;\r\n opacity:.8;\r\n }\r\n\r\n .desc{\r\n grid-column: 2 / span 1;\r\n font-size:12px;\r\n opacity:.65;\r\n }\r\n\r\n .row.checkbox .desc{\r\n grid-column: 1 / span 1;\r\n margin-left:24px;\r\n }\r\n\r\n .muted{\r\n color:#999;\r\n }\r\n `],\r\n})\r\nexport class AdvancedEditorComponent {\r\n @Input() options: Options | undefined;\r\n @Output() optionsChange = new EventEmitter<Options | undefined>();\r\n\r\n timeoutMs = computed(() => this.options?.timeoutMs ?? 30000);\r\n followRedirects = computed(() => this.options?.followRedirects ?? true);\r\n insecureTLS = computed(() => this.options?.insecureTLS ?? false);\r\n proxy = computed(() => this.options?.proxy ?? '');\r\n\r\n private emit(next: Options) {\r\n this.optionsChange.emit(next);\r\n }\r\n\r\n setTimeout(v: number) {\r\n const n = Number(v);\r\n this.emit({ ...(this.options ?? {}), timeoutMs: isNaN(n) ? undefined : n });\r\n }\r\n\r\n setFollowRedirects(v: boolean) {\r\n this.emit({ ...(this.options ?? {}), followRedirects: v });\r\n }\r\n\r\n setInsecureTLS(v: boolean) {\r\n this.emit({ ...(this.options ?? {}), insecureTLS: v });\r\n }\r\n\r\n setProxy(v: string) {\r\n this.emit({ ...(this.options ?? {}), proxy: v || undefined });\r\n }\r\n}\r\n","import { Component, EventEmitter, Input, Output } from '@angular/core';\r\nimport { ApiRequestEntity } from '@models/api-client/api-request.model';\r\nimport { NzTabsModule } from 'ng-zorro-antd/tabs';\r\nimport { AdvancedEditorComponent } from './advanced-editor.component';\r\nimport { AuthEditorComponent } from './auth-editor.component';\r\nimport { BodyEditorComponent } from './body-editor.component';\r\nimport { KvTableComponent } from './kv-table.component';\r\n\r\n@Component({\r\n selector: 'app-request-tabs',\r\n imports: [NzTabsModule, KvTableComponent, BodyEditorComponent, AuthEditorComponent, AdvancedEditorComponent],\r\n template: `\r\n <nz-tabs class=\"tabs\">\r\n <nz-tab nzTitle=\"Params\">\r\n <div class=\"tab\">\r\n <div class=\"item\">\r\n <div class=\"title\">Query 参数</div>\r\n <app-kv-table\r\n [rows]=\"req?.query || []\"\r\n (rowsChange)=\"patch.emit({ query: $event })\"\r\n keyLabel=\"参数名\"\r\n valueLabel=\"参数值\"\r\n descriptionLabel=\"说明\"\r\n keyPlaceholder=\"param\"\r\n valuePlaceholder=\"value\"\r\n />\r\n </div>\r\n @if(req?.pathParams?.length){\r\n <div class=\"item\">\r\n <div class=\"title\">Path 参数</div>\r\n <app-kv-table\r\n [keepTrailingBlank]=\"false\"\r\n [rows]=\"req?.pathParams || []\"\r\n (rowsChange)=\"patch.emit({ pathParams: $event })\"\r\n keyLabel=\"参数名\"\r\n valueLabel=\"参数值\"\r\n descriptionLabel=\"说明\"\r\n keyPlaceholder=\"param\"\r\n valuePlaceholder=\"value\"\r\n />\r\n </div>\r\n }\r\n </div>\r\n </nz-tab>\r\n <nz-tab nzTitle=\"Headers\">\r\n <div class=\"tab\">\r\n <app-kv-table\r\n [rows]=\"req?.headers || []\"\r\n (rowsChange)=\"patch.emit({ headers: $event })\"\r\n keyLabel=\"Header\"\r\n valueLabel=\"Value\"\r\n keyPlaceholder=\"x-header\"\r\n valuePlaceholder=\"value\"\r\n />\r\n </div>\r\n </nz-tab>\r\n <nz-tab nzTitle=\"Body\">\r\n <div class=\"tab\">\r\n <app-body-editor\r\n [body]=\"req?.body\"\r\n (bodyChange)=\"patch.emit({ body: $event })\"\r\n />\r\n </div>\r\n </nz-tab>\r\n <nz-tab nzTitle=\"Auth\">\r\n <div class=\"tab\">\r\n <app-auth-editor \r\n [auth]=\"req?.auth\"\r\n (authChange)=\"patch.emit({ auth: $event })\"\r\n />\r\n </div>\r\n </nz-tab>\r\n <nz-tab nzTitle=\"Advanced\">\r\n <div class=\"tab\">\r\n <app-advanced-editor\r\n [options]=\"req?.options\"\r\n (optionsChange)=\"patch.emit({ options: $event })\"\r\n />\r\n </div>\r\n </nz-tab>\r\n </nz-tabs>\r\n `,\r\n styles: [\r\n `\r\n :host{ display:flex; flex-direction:column; height:100%; min-height:0; }\r\n app-kv-table{\r\n display: block;\r\n height: 100%;\r\n }\r\n .tabs {\r\n flex: 1 1 auto;\r\n overflow: hidden;\r\n height: 100%;\r\n }\r\n .tab{\r\n height: 100%;\r\n overflow: hidden auto;\r\n }\r\n ::ng-deep nz-tabs.tabs{\r\n .ant-tabs-content{\r\n height: 100%;\r\n .ant-tabs-tabpane{\r\n height:100%;\r\n }\r\n }\r\n }\r\n `\r\n ],\r\n})\r\nexport class RequestTabsComponent {\r\n\r\n @Input() req: ApiRequestEntity | null = null;\r\n @Output() patch = new EventEmitter<Partial<ApiRequestEntity>>();\r\n}\r\n\r\n","/* angular:styles/component:less;de9c446db3f77e43cef20849dae466a91b77073ebfb25617c2d7838e1fbb525b;D:\\ng-manager\\webapp\\src\\app\\pages\\api-client\\components\\request-editor\\request-editor.component.ts */\n:host {\n display: flex;\n flex-direction: column;\n}\n.name {\n padding: 10px;\n border-bottom: 1px solid #f0f0f0;\n}\n.tabs {\n flex: 1 1 auto;\n overflow: hidden;\n padding: 0 10px;\n}\napp-request-tabs {\n flex: 1 1 auto;\n height: 0;\n}\n/*# sourceMappingURL=request-editor.component.css.map */\n","/* angular:styles/component:less;2545a7f8140b00be966602c60632d1077fd891b1e8b774540c3a89ad3cc4f9d7;D:\\ng-manager\\webapp\\src\\app\\pages\\api-client\\components\\request-editor\\request-urlbar.component.ts */\n.bar {\n display: flex;\n gap: 10px;\n padding: 10px;\n border-bottom: 1px solid #f0f0f0;\n align-items: center;\n}\n.method {\n width: 120px;\n}\n.url {\n flex: 1 1 auto;\n}\n.var-hint {\n padding: 4px 10px 8px;\n font-size: 12px;\n display: flex;\n gap: 8px;\n align-items: center;\n}\n/*# sourceMappingURL=request-urlbar.component.css.map */\n","import { CommonModule } from '@angular/common';\r\nimport { Component, computed, EventEmitter, Input, OnChanges, Output, SimpleChanges } from '@angular/core';\r\nimport { FormsModule } from '@angular/forms';\r\nimport { NzButtonModule } from 'ng-zorro-antd/button';\r\nimport { NzInputModule } from 'ng-zorro-antd/input';\r\nimport { NzSelectModule } from 'ng-zorro-antd/select';\r\n\r\nimport type { ApiHttpMethod } from '@models/api-client';\r\nimport { collectMissingFromStrings } from '@pages/api-client/utils';\r\nimport { NzTagModule } from 'ng-zorro-antd/tag';\r\n\r\n@Component({\r\n selector: 'app-request-urlbar',\r\n standalone: true,\r\n imports: [CommonModule, FormsModule, NzButtonModule, NzInputModule, NzSelectModule, NzTagModule],\r\n template: `\r\n <div class=\"bar\">\r\n <nz-select class=\"method\" [ngModel]=\"method\" (ngModelChange)=\"methodChange.emit($event)\">\r\n @for (m of methods; track m) {\r\n <nz-option [nzValue]=\"m\" [nzLabel]=\"m\" class=\"m\"></nz-option>\r\n }\r\n </nz-select>\r\n <nz-input-wrapper class=\"url\" [nzAddonBefore]=\"baseUrl ? baseUrl + ' ' : undefined\" >\r\n <input\r\n nz-input\r\n [placeholder]=\"placeholder()\"\r\n [ngModel]=\"draftUrl\"\r\n (ngModelChange)=\"onDraftChange($event)\"\r\n (blur)=\"commit()\"\r\n (keydown.enter)=\"commit()\"\r\n />\r\n </nz-input-wrapper>\r\n <button nz-button nzType=\"primary\" [nzLoading]=\"sending\" (click)=\"send.emit()\">发送</button>\r\n <button nz-button nzType=\"default\" (click)=\"save.emit()\">保存</button>\r\n </div>\r\n @if (missingVars().length) {\r\n <div class=\"var-hint\">\r\n <nz-tag nzColor=\"warning\">\r\n 未解析变量:{{ missingVars().join(', ') }}\r\n </nz-tag>\r\n <a (click)=\"openEnv()\">去配置</a>\r\n </div>\r\n }\r\n `,\r\n styles: [`\r\n .bar{\r\n display:flex;\r\n gap:10px;\r\n padding:10px;\r\n border-bottom:1px solid #f0f0f0;\r\n align-items:center;\r\n }\r\n .method{ width:120px; }\r\n .url{ flex:1 1 auto; }\r\n .var-hint{\r\n padding: 4px 10px 8px;\r\n font-size: 12px;\r\n display: flex;\r\n gap: 8px;\r\n align-items: center;\r\n }\r\n `],\r\n})\r\nexport class RequestUrlbarComponent implements OnChanges {\r\n @Input() envVars: Record<string, string> = {};\r\n @Input() openEnv!: () => void; // 点击提示时打开 Env 管理\r\n @Input() method: ApiHttpMethod = 'GET';\r\n @Input() url = '';\r\n @Input() sending = false;\r\n\r\n // env meta\r\n @Input() envName: string | null = null;\r\n @Input() baseUrl: string | null = null;\r\n \r\n\r\n @Output() methodChange = new EventEmitter<ApiHttpMethod>();\r\n /** 输入过程中(debounce)持续更新 url(只改文本,不同步 path params) */\r\n @Output() urlChange = new EventEmitter<string>();\r\n /** 用户确认(blur/enter)后的提交:用于同步 path params */\r\n @Output() urlCommit = new EventEmitter<string>();\r\n @Output() send = new EventEmitter<void>();\r\n @Output() save = new EventEmitter<void>();\r\n\r\n methods: ApiHttpMethod[] = ['GET', 'POST', 'PUT', 'PATCH', 'DELETE', 'HEAD', 'OPTIONS'];\r\n\r\n missingVars = computed(() => collectMissingFromStrings([this.draftUrl], this.envVars));\r\n\r\n\r\n draftUrl = '';\r\n private t?: number;\r\n\r\n ngOnChanges(changes: SimpleChanges) {\r\n // 外部 url 变化时(切换 request / replay history / reset),同步到 draft\r\n if (changes['url']) {\r\n this.draftUrl = this.url ?? '';\r\n }\r\n }\r\n\r\n onDraftChange(v: string) {\r\n this.draftUrl = v ?? '';\r\n // debounce 发 urlChange,避免每键都 patch store\r\n if (this.t) window.clearTimeout(this.t);\r\n this.t = window.setTimeout(() => {\r\n this.urlChange.emit(this.draftUrl);\r\n }, 250);\r\n }\r\n\r\n commit() {\r\n // 先把最后一次输入也 push 掉(避免 blur 时 draft 未下发)\r\n if (this.t) {\r\n window.clearTimeout(this.t);\r\n this.t = undefined;\r\n }\r\n this.urlChange.emit(this.draftUrl);\r\n this.urlCommit.emit(this.draftUrl);\r\n }\r\n\r\n placeholder = computed(() => {\r\n // 有 baseUrl 时引导用户写相对路径\r\n return this.baseUrl ? `\"/\"开头` : 'http://...';\r\n });\r\n\r\n previewUrl = computed(() => {\r\n const raw = (this.url ?? '').trim();\r\n if (!raw) return '';\r\n\r\n // absolute url → 不展示 preview(本身就是最终)\r\n if (isAbsoluteUrl(raw)) return '';\r\n\r\n // relative url + baseUrl → 展示 resolved\r\n const base = (this.baseUrl ?? '').trim();\r\n if (!base) return '';\r\n\r\n try {\r\n return new URL(raw, base).toString();\r\n } catch {\r\n return '';\r\n }\r\n });\r\n}\r\n\r\nfunction isAbsoluteUrl(u: string) {\r\n return /^https?:\\/\\//i.test(u);\r\n}","import { CommonModule } from '@angular/common';\r\nimport { Component, EventEmitter, Input, Output } from '@angular/core';\r\nimport { FormsModule } from '@angular/forms';\r\nimport { NzButtonModule } from 'ng-zorro-antd/button';\r\nimport { NzInputModule } from 'ng-zorro-antd/input';\r\nimport { NzSelectModule } from 'ng-zorro-antd/select';\r\nimport { NzSpinModule } from 'ng-zorro-antd/spin';\r\n\r\nimport type { ApiRequestEntity, ApiHttpMethod } from '@models/api-client';\r\nimport { RequestTabsComponent } from './request-tabs.component';\r\nimport { RequestUrlbarComponent } from './request-urlbar.component';\r\nimport { extractPathParamKeys, syncPathParamsByUrl } from '@pages/api-client/utils';\r\n@Component({\r\n selector: 'app-request-editor',\r\n standalone: true,\r\n imports: [\r\n CommonModule,\r\n FormsModule,\r\n NzButtonModule,\r\n NzInputModule,\r\n NzSelectModule,\r\n NzSpinModule,\r\n RequestTabsComponent,\r\n RequestUrlbarComponent\r\n ],\r\n template: `\r\n @if(request){\r\n <app-request-urlbar\r\n [method]=\"request.method\"\r\n [baseUrl]=\"baseUrl\"\r\n [envVars]=\"envVars\"\r\n [openEnv]=\"openEnv\"\r\n [url]=\"request.url\"\r\n [sending]=\"sending\"\r\n (methodChange)=\"patch.emit({method:$event})\"\r\n (urlChange)=\"onUrlChange($event)\"\r\n (urlCommit)=\"onUrlCommit($event)\"\r\n (send)=\"send.emit()\"\r\n (save)=\"save.emit()\"\r\n />\r\n <div class=\"name\">\r\n <nz-input-wrapper [nzAddonBefore]=\" (collectionPath || '未分类')\">\r\n <input nz-input placeholder=\"未命名接口名称\" [ngModel]=\"request.name\" (ngModelChange)=\"patch.emit({name:$event})\" />\r\n </nz-input-wrapper>\r\n </div>\r\n <app-request-tabs class=\"tabs\" [req]=\"request\" (patch)=\"patch.emit($event)\" />\r\n } \r\n `,\r\n styles: [`\r\n :host{ display: flex; flex-direction: column;}\r\n .name{ padding:10px; border-bottom:1px solid #f0f0f0; }\r\n .tabs{ flex:1 1 auto; overflow:hidden; padding:0 10px; }\r\n app-request-tabs{flex:1 1 auto; height:0;}\r\n `],\r\n})\r\nexport class RequestEditorComponent {\r\n @Input() request: ApiRequestEntity | null = null;\r\n @Input() sending = false;\r\n @Input() envVars: Record<string, string> = {};\r\n @Input() openEnv!: () => void; // 点击提示时打开 Env 管理\r\n @Input() baseUrl: string | null = null;\r\n\r\n @Output() patch = new EventEmitter<Partial<ApiRequestEntity>>();\r\n @Output() send = new EventEmitter<void>();\r\n @Output() save = new EventEmitter<void>();\r\n @Input() collectionPath: string | null = null; // 分类路径\r\n\r\n methods: ApiHttpMethod[] = ['GET', 'POST', 'PUT', 'PATCH', 'DELETE', 'HEAD', 'OPTIONS'];\r\n\r\n onUrlCommit(nextUrl: string) {\r\n const cur = this.request;\r\n if (!cur) return;\r\n\r\n const nextPathParams = syncPathParamsByUrl(nextUrl, cur.pathParams);\r\n // console.log('onUrlCommit', nextUrl, nextPathParams);\r\n\r\n // keys 变化才 patch,避免无意义写入\r\n const curKeys = extractPathParamKeys(cur.url ?? \"\");\r\n const nextKeys = extractPathParamKeys(nextUrl ?? \"\");\r\n const keysChanged =\r\n curKeys.length !== nextKeys.length || curKeys.some((k, i) => k !== nextKeys[i]);\r\n\r\n if (keysChanged) {\r\n this.patch.emit({ pathParams: nextPathParams });\r\n }\r\n }\r\n\r\n onUrlChange(nextUrl: string) {\r\n const cur = this.request;\r\n if (!cur) {\r\n this.patch.emit({ url: nextUrl });\r\n return;\r\n }\r\n\r\n const nextPathParams = syncPathParamsByUrl(nextUrl, cur.pathParams);\r\n\r\n // 合并 patch:url + pathParams\r\n // 只有当 path keys 发生变化时才带上 pathParams,减少无意义 patch\r\n const curKeys = extractPathParamKeys(cur.url ?? \"\");\r\n const nextKeys = extractPathParamKeys(nextUrl ?? \"\");\r\n const keysChanged =\r\n curKeys.length !== nextKeys.length || curKeys.some((k, i) => k !== nextKeys[i]);\r\n\r\n if (keysChanged) {\r\n this.patch.emit({ url: nextUrl, pathParams: nextPathParams });\r\n } else {\r\n this.patch.emit({ url: nextUrl });\r\n }\r\n }\r\n\r\n}\r\n","/* angular:styles/component:less;e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855;D:\\ng-manager\\webapp\\src\\app\\pages\\api-client\\components\\response-viewer\\curl-actions.component.ts */\n/*# sourceMappingURL=curl-actions.component.css.map */\n","import { Component, inject, Input } from '@angular/core';\r\nimport { ClipboardModule, Clipboard } from '@angular/cdk/clipboard';\r\n\r\nimport { CommonModule } from '@angular/common';\r\nimport { NzSpaceModule } from 'ng-zorro-antd/space';\r\nimport { NzButtonModule } from 'ng-zorro-antd/button';\r\nimport { NzIconModule } from 'ng-zorro-antd/icon';\r\nimport { NzDropDownModule } from 'ng-zorro-antd/dropdown';\r\n@Component({\r\n selector: 'app-curl-actions',\r\n imports: [CommonModule, ClipboardModule, NzSpaceModule, NzButtonModule, NzIconModule, NzDropDownModule],\r\n template: `\r\n <div class=\"wrap\">\r\n <nz-space >\r\n <button nz-button [disabled]=\"!curl\" nz-dropdown [nzDropdownMenu]=\"menu\" nzType=\"default\" nzTrigger=\"hover\" nzPlacement=\"bottomCenter\">\r\n <nz-icon nzType=\"copy\" nzTheme=\"outline\"/>\r\n cURL\r\n </button>\r\n </nz-space>\r\n <nz-dropdown-menu #menu=\"nzDropdownMenu\" >\r\n <ul nz-menu>\r\n <li nz-menu-item>\r\n <button nz-button nzType=\"text\" [disabled]=\"!curl?.bash\" (click)=\"copy(curl!.bash)\">\r\n cURL (Bash)\r\n </button>\r\n </li>\r\n <li nz-menu-item>\r\n <button nz-button nzType=\"text\" [disabled]=\"!curl?.powershell\" (click)=\"copy(curl!.powershell)\">\r\n cURL (PS)\r\n </button>\r\n </li>\r\n <li nz-menu-item>\r\n <button nz-button nzType=\"text\" [disabled]=\"!curl?.cmd\" (click)=\"copy(curl!.cmd)\">\r\n cURL (CMD)\r\n </button>\r\n </li>\r\n </ul>\r\n </nz-dropdown-menu>\r\n </div>\r\n `,\r\n styles: ``,\r\n})\r\nexport class CurlActionsComponent {\r\n private clipboard = inject(Clipboard);\r\n @Input() curl: { bash: string; powershell: string; cmd: string } | null = null;\r\n copy(text: string) {\r\n this.clipboard.copy(text);\r\n }\r\n}\r\n","/* angular:styles/component:less;5a3667eac1a001012f88fa45835368589b34b87936c1945179fde1d4aee84900;D:\\ng-manager\\webapp\\src\\app\\pages\\api-client\\components\\response-viewer\\response-viewer.component.ts */\n:host {\n display: flex;\n height: 100%;\n min-height: 0;\n}\n.wrap {\n display: flex;\n flex-direction: column;\n height: 100%;\n min-height: 0;\n width: 100%;\n}\n.top {\n display: flex;\n justify-content: space-between;\n align-items: center;\n padding: 10px 12px;\n border-bottom: 1px solid #f0f0f0;\n}\n.left {\n display: flex;\n gap: 10px;\n align-items: center;\n}\n.title {\n font-weight: 700;\n}\n.meta {\n font-size: 12px;\n opacity: 0.65;\n}\n.loading {\n padding: 16px;\n}\n.empty {\n padding: 16px;\n opacity: 0.6;\n}\n.tabs {\n flex: 1 1 auto;\n min-height: 0;\n}\n.pane {\n height: 100%;\n min-height: 0;\n overflow: auto;\n padding: 10px 12px;\n}\n.code {\n margin: 0;\n font-family:\n ui-monospace,\n SFMono-Regular,\n Menlo,\n Monaco,\n Consolas,\n \"Liberation Mono\",\n \"Courier New\",\n monospace;\n font-size: 12px;\n line-height: 1.5;\n white-space: pre-wrap;\n word-break: break-word;\n}\n.hlist {\n display: flex;\n flex-direction: column;\n gap: 8px;\n}\n.hrow {\n display: grid;\n grid-template-columns: 200px 1fr;\n gap: 10px;\n padding: 8px;\n border: 1px solid #f0f0f0;\n border-radius: 8px;\n}\n.hk {\n font-weight: 600;\n font-size: 12px;\n}\n.hv {\n font-size: 12px;\n opacity: 0.85;\n word-break: break-word;\n}\n/*# sourceMappingURL=response-viewer.component.css.map */\n","import { CommonModule } from '@angular/common';\r\nimport { Component, Input, OnChanges, OnInit, SimpleChanges, computed, signal } from '@angular/core';\r\nimport { NzTabsModule } from 'ng-zorro-antd/tabs';\r\nimport { NzTagModule } from 'ng-zorro-antd/tag';\r\nimport { NzSpinModule } from 'ng-zorro-antd/spin';\r\nimport { NzAlertModule } from 'ng-zorro-antd/alert';\r\n\r\nimport { CurlActionsComponent } from './curl-actions.component';\r\nimport { ApiResponseEntity } from '@models/api-client/api-response.model';\r\nimport { SendResponse } from '@models/api-client';\r\n\r\n\r\n@Component({\r\n selector: 'app-response-viewer',\r\n standalone: true,\r\n imports: [CommonModule, NzTabsModule, NzTagModule, NzSpinModule, NzAlertModule, CurlActionsComponent],\r\n template: `\r\n <div class=\"wrap\">\r\n <div class=\"top\">\r\n <div class=\"left\">\r\n <div class=\"title\">Response</div>\r\n\r\n @if (response()) {\r\n <nz-tag [nzColor]=\"statusColor()\">\r\n {{ response()?.status }} {{ response()?.statusText || '' }}\r\n </nz-tag>\r\n\r\n <span class=\"meta\">{{ response()?.bodySize }} bytes</span>\r\n } @else {\r\n <span class=\"meta\">-</span>\r\n }\r\n </div>\r\n\r\n <div class=\"right\">\r\n <app-curl-actions [curl]=\"curl()\"></app-curl-actions>\r\n </div>\r\n </div>\r\n\r\n @if (sending) {\r\n <div class=\"loading\">\r\n <nz-spin></nz-spin>\r\n </div>\r\n } @else if (error()) {\r\n <nz-alert nzType=\"error\" nzShowIcon [nzMessage]=\"error()\"></nz-alert>\r\n } @else if (!response()) {\r\n <div class=\"empty\">发送请求后在此查看响应</div>\r\n } @else {\r\n <nz-tabs class=\"tabs\" [(nzSelectedIndex)]=\"tabIndex\">\r\n <nz-tab nzTitle=\"Body\">\r\n <div class=\"pane\">\r\n @if (isJson()) {\r\n <pre class=\"code\">{{ prettyJson() }}</pre>\r\n } @else {\r\n <pre class=\"code\">{{ response()?.bodyText }}</pre>\r\n }\r\n </div>\r\n </nz-tab>\r\n\r\n <nz-tab nzTitle=\"Headers\">\r\n <div class=\"pane\">\r\n <div class=\"hlist\">\r\n @for (k of headerKeys(); track k) {\r\n <div class=\"hrow\">\r\n <div class=\"hk\">{{ k }}</div>\r\n <div class=\"hv\">{{ response()?.headers?.[k] }}</div>\r\n </div>\r\n }\r\n </div>\r\n </div>\r\n </nz-tab>\r\n\r\n <nz-tab nzTitle=\"Raw\">\r\n <div class=\"pane\">\r\n <pre class=\"code\">{{ rawDump() }}</pre>\r\n </div>\r\n </nz-tab>\r\n </nz-tabs>\r\n }\r\n </div>\r\n `,\r\n styles: [`\r\n :host{ display:flex; height:100%; min-height:0; }\r\n .wrap{ display:flex; flex-direction:column; height:100%; min-height:0; width:100%; }\r\n\r\n .top{\r\n display:flex;\r\n justify-content:space-between;\r\n align-items:center;\r\n padding:10px 12px;\r\n border-bottom:1px solid #f0f0f0;\r\n }\r\n .left{ display:flex; gap:10px; align-items:center; }\r\n .title{ font-weight:700; }\r\n .meta{ font-size:12px; opacity:.65; }\r\n\r\n .loading{ padding:16px; }\r\n .empty{ padding:16px; opacity:.6; }\r\n\r\n .tabs{ flex:1 1 auto; min-height:0; }\r\n .pane{ height:100%; min-height:0; overflow:auto; padding:10px 12px; }\r\n\r\n .code{\r\n margin:0;\r\n font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, \"Liberation Mono\", \"Courier New\", monospace;\r\n font-size:12px;\r\n line-height:1.5;\r\n white-space:pre-wrap;\r\n word-break:break-word;\r\n }\r\n\r\n .hlist{ display:flex; flex-direction:column; gap:8px; }\r\n .hrow{\r\n display:grid;\r\n grid-template-columns: 200px 1fr;\r\n gap:10px;\r\n padding:8px;\r\n border:1px solid #f0f0f0;\r\n border-radius:8px;\r\n }\r\n .hk{ font-weight:600; font-size:12px; }\r\n .hv{ font-size:12px; opacity:.85; word-break:break-word; }\r\n `],\r\n})\r\nexport class ResponseViewerComponent implements OnChanges {\r\n\r\n @Input() sending = false;\r\n @Input() result: SendResponse | null = null;\r\n\r\n resultSig = signal<SendResponse | null>(null);\r\n\r\n tabIndex = 0;\r\n\r\n ngOnChanges(changes: SimpleChanges): void {\r\n if (changes['result']) {\r\n const r = changes['result'].currentValue as SendResponse | null;\r\n this.resultSig.set(r);\r\n }\r\n }\r\n\r\n error = computed(() => {\r\n const res = this.resultSig();\r\n if (!res) return null;\r\n return res.error ? res.error.message : null;\r\n });\r\n\r\n curl = computed(() => {\r\n const res = this.resultSig();\r\n if (!res) return null;\r\n return res.curl ? res.curl : null;\r\n });\r\n\r\n response = computed(() => {\r\n const res = this.resultSig();\r\n if (!res) return null;\r\n return res.response;\r\n });\r\n\r\n headerKeys = computed(() => {\r\n const h = this.response()?.headers ?? {};\r\n return Object.keys(h).sort((a, b) => a.localeCompare(b));\r\n });\r\n\r\n statusColor = computed(() => {\r\n const s = this.response()?.status ?? 0;\r\n if (!s) return 'default';\r\n if (s >= 200 && s < 300) return 'green';\r\n if (s >= 300 && s < 400) return 'blue';\r\n if (s >= 400 && s < 500) return 'orange';\r\n return 'red';\r\n });\r\n\r\n isJson = computed(() => {\r\n const res = this.response();\r\n if (!res) return false;\r\n\r\n const ct = (res.headers?.['content-type'] ?? res.headers?.['Content-Type'] ?? '').toLowerCase();\r\n if (ct.includes('application/json')) return true;\r\n\r\n // 容错:bodyText 看起来像 JSON\r\n const t = (res.bodyText ?? '').trim();\r\n return (t.startsWith('{') && t.endsWith('}')) || (t.startsWith('[') && t.endsWith(']'));\r\n });\r\n\r\n prettyJson = computed(() => {\r\n const t = (this.response()?.bodyText ?? '').trim();\r\n try {\r\n const obj = JSON.parse(t);\r\n return JSON.stringify(obj, null, 2);\r\n } catch {\r\n return this.response()?.bodyText ?? '';\r\n }\r\n });\r\n\r\n rawDump = computed(() => {\r\n if (!this.response()) return '';\r\n return JSON.stringify(this.response(), null, 2);\r\n });\r\n}\r\n","<div class=\"tabs-container\" cdkDropList (cdkDropListDropped)=\"onDrop($event)\">\r\n @for (tab of tabs(); track tab.id; let i = $index) {\r\n <div\r\n class=\"tab-item\"\r\n [class.active]=\"tab.id === activeTabId()\"\r\n [class.dirty]=\"tab.isDirty\"\r\n [cdkDragData]=\"tab\"\r\n cdkDrag\r\n (click)=\"onTabClick(tab.id)\"\r\n (contextmenu)=\"onContextMenu($event, tab, i)\"\r\n >\r\n <!-- 拖拽手柄 -->\r\n <span class=\"drag-handle\" cdkDragHandle>\r\n <nz-icon nzType=\"holder\" nzTheme=\"outline\" />\r\n </span>\r\n\r\n <!-- Tab 内容 -->\r\n @if (editingTabId() === tab.id) {\r\n <input\r\n #editInput\r\n class=\"title-input\"\r\n [ngModel]=\"editingTitle()\"\r\n (ngModelChange)=\"editingTitle.set($event)\"\r\n (blur)=\"finishEdit()\"\r\n (keydown.enter)=\"finishEdit()\"\r\n (keydown.escape)=\"cancelEdit()\"\r\n />\r\n } @else {\r\n <span class=\"method\" [class]=\"getMethodClass(tab.request.method)\">\r\n {{ tab.request.method }}\r\n </span>\r\n <span\r\n class=\"title\"\r\n (dblclick)=\"startEdit(tab)\"\r\n nz-tooltip\r\n [nzTooltipTitle]=\"getFullTitle(tab)\"\r\n >\r\n {{ getDisplayTitle(tab) }}\r\n </span>\r\n @if (tab.isDirty) {\r\n <span class=\"dirty-dot\" title=\"未保存\">●</span>\r\n }\r\n }\r\n\r\n <!-- 关闭按钮 -->\r\n <button\r\n class=\"close-btn\"\r\n nz-button\r\n nzType=\"text\"\r\n nzSize=\"small\"\r\n (click)=\"onCloseClick(tab.id, $event)\"\r\n >\r\n <nz-icon nzType=\"close\" nzTheme=\"outline\" />\r\n </button>\r\n </div>\r\n }\r\n\r\n <!-- 新建按钮 -->\r\n @if (canOpenMore) {\r\n <button\r\n class=\"add-btn\"\r\n nz-button\r\n nzType=\"text\"\r\n (click)=\"onAddClick()\"\r\n nz-tooltip\r\n nzTooltipTitle=\"新建请求 (Ctrl+T)\"\r\n >\r\n <nz-icon nzType=\"plus\" nzTheme=\"outline\" />\r\n </button>\r\n }\r\n</div>\r\n\r\n<!-- 右键菜单 -->\r\n<nz-dropdown-menu #contextMenu=\"nzDropdownMenu\" nzOverlayClassName=\"tab-context-menu\">\r\n <ul nz-menu class=\"context-menu\">\r\n <!-- 关闭操作 -->\r\n <li nz-menu-item (click)=\"onMenuAction('close')\">\r\n <nz-icon nzType=\"close\" />\r\n <span>关闭</span>\r\n <!-- <span class=\"shortcut\">Ctrl+W</span> -->\r\n </li>\r\n <li nz-menu-item (click)=\"onMenuAction('closeOthers')\" [nzDisabled]=\"tabs().length <= 1\">\r\n <nz-icon nzType=\"close-circle\" />\r\n <span>关闭其他</span>\r\n </li>\r\n <li nz-menu-item (click)=\"onMenuAction('closeRight')\" [nzDisabled]=\"!hasRightTabs()\">\r\n <nz-icon nzType=\"right-circle\" />\r\n <span>关闭右侧</span>\r\n </li>\r\n <li nz-menu-item (click)=\"onMenuAction('closeSaved')\" [nzDisabled]=\"!hasSavedTabs()\">\r\n <nz-icon nzType=\"check-circle\" />\r\n <span>关闭已保存</span>\r\n </li>\r\n <li nz-menu-item (click)=\"onMenuAction('closeAll')\" [nzDisabled]=\"tabs().length <= 1\">\r\n <nz-icon nzType=\"delete\" />\r\n <span>关闭所有</span>\r\n </li>\r\n\r\n <li nz-menu-divider></li>\r\n\r\n <!-- 编辑操作 -->\r\n <li nz-menu-item (click)=\"onMenuAction('rename')\">\r\n <nz-icon nzType=\"edit\" />\r\n <span>重命名</span>\r\n <!-- <span class=\"shortcut\">F2</span> -->\r\n </li>\r\n <li nz-menu-item (click)=\"onMenuAction('duplicate')\">\r\n <nz-icon nzType=\"copy\" />\r\n <span>复制请求</span>\r\n </li>\r\n\r\n <li nz-menu-divider></li>\r\n\r\n <!-- 其他操作 -->\r\n @if (contextTab()?.request?.url) {\r\n <li nz-menu-item (click)=\"onMenuAction('copyUrl')\">\r\n <nz-icon nzType=\"link\" />\r\n <span>复制 URL</span>\r\n </li>\r\n }\r\n @if (contextTab()?.requestId) {\r\n <li nz-menu-item (click)=\"onMenuAction('moveTo')\">\r\n <nz-icon nzType=\"folder\" />\r\n <span>移动到</span>\r\n </li>\r\n }\r\n </ul>\r\n</nz-dropdown-menu>\r\n","/* src/app/pages/api-client/components/request-tabs-bar/request-tabs-bar.component.less */\n:host {\n display: block;\n width: 100%;\n}\n.tabs-container {\n display: flex;\n align-items: center;\n gap: 2px;\n padding: 4px 8px;\n background: #fafafa;\n border-bottom: 1px solid #f0f0f0;\n overflow-x: auto;\n flex-wrap: nowrap;\n}\n.tabs-container::-webkit-scrollbar {\n height: 4px;\n}\n.tabs-container::-webkit-scrollbar-thumb {\n background: #d9d9d9;\n border-radius: 2px;\n}\n.tab-item {\n display: flex;\n align-items: center;\n gap: 6px;\n padding: 4px 8px;\n min-width: 100px;\n max-width: 200px;\n height: 28px;\n border-radius: 4px 4px 0 0;\n background: #fff;\n border: 1px solid transparent;\n border-bottom: none;\n cursor: pointer;\n -webkit-user-select: none;\n user-select: none;\n transition: all 0.15s;\n}\n.tab-item:hover {\n background: #f5f5f5;\n}\n.tab-item.active {\n background: #fff;\n border-color: #1890ff;\n border-bottom: 1px solid #fff;\n margin-bottom: -1px;\n z-index: 1;\n}\n.tab-item.dirty .title {\n color: #1890ff;\n}\n.drag-handle {\n display: flex;\n align-items: center;\n opacity: 0.3;\n cursor: grab;\n font-size: 10px;\n}\n.drag-handle:hover {\n opacity: 0.6;\n}\n.method {\n font-size: 10px;\n font-weight: 600;\n text-transform: uppercase;\n flex-shrink: 0;\n}\n.method.get {\n color: #61affe;\n}\n.method.post {\n color: #49cc90;\n}\n.method.put {\n color: #fca130;\n}\n.method.patch {\n color: #50e3c2;\n}\n.method.delete {\n color: #f93e3e;\n}\n.method.head,\n.method.options {\n color: #909090;\n}\n.title {\n flex: 1;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n font-size: 13px;\n color: #333;\n}\n.dirty-dot {\n color: #1890ff;\n font-size: 8px;\n flex-shrink: 0;\n}\n.title-input {\n flex: 1;\n border: none;\n background: transparent;\n outline: none;\n font-size: 12px;\n min-width: 60px;\n padding: 0 2px;\n}\n.close-btn {\n padding: 0 2px !important;\n height: 16px !important;\n width: 16px !important;\n font-size: 10px;\n opacity: 0.3;\n flex-shrink: 0;\n}\n.close-btn:hover {\n opacity: 1;\n}\n.add-btn {\n padding: 0 8px !important;\n height: 28px !important;\n opacity: 0.6;\n}\n.add-btn:hover {\n opacity: 1;\n}\n:host ::ng-deep .tab-context-menu .shortcut {\n margin-left: auto;\n opacity: 0.5;\n font-size: 12px;\n font-family: monospace;\n}\n.context-menu ::ng-deep .ant-menu-title-content {\n display: flex;\n align-items: center;\n gap: 8px;\n}\n/*# sourceMappingURL=request-tabs-bar.component.css.map */\n","import { CdkDragDrop, DragDropModule } from '@angular/cdk/drag-drop';\nimport { CommonModule } from '@angular/common';\nimport {\n Component,\n ElementRef,\n EventEmitter,\n HostListener,\n inject,\n Input,\n Output,\n ViewChild,\n computed,\n signal,\n} from '@angular/core';\nimport { FormsModule } from '@angular/forms';\nimport { NzButtonModule } from 'ng-zorro-antd/button';\nimport { NzIconModule } from 'ng-zorro-antd/icon';\nimport { NzTabsModule } from 'ng-zorro-antd/tabs';\nimport { NzTooltipModule } from 'ng-zorro-antd/tooltip';\nimport { NzDropDownModule, NzContextMenuService, NzDropdownMenuComponent } from 'ng-zorro-antd/dropdown';\nimport { NzMenuModule } from 'ng-zorro-antd/menu';\n\nimport type { ApiClientTab } from '@models/api-client';\n\n/**\n * 右键菜单操作类型\n */\nexport type TabContextMenuAction =\n | 'close'\n | 'closeOthers'\n | 'closeRight'\n | 'closeSaved'\n | 'closeAll'\n | 'rename'\n | 'duplicate'\n | 'copyUrl'\n | 'moveTo';\n\n/**\n * 右键菜单事件\n */\nexport interface TabContextMenuEvent {\n tabId: string;\n action: TabContextMenuAction;\n}\n\n/**\n * 请求 Tabs 标签栏组件\n * 支持多请求并行编辑、右键菜单、快捷键\n */\n@Component({\n selector: 'app-request-tabs-bar',\n standalone: true,\n imports: [\n CommonModule,\n FormsModule,\n DragDropModule,\n NzTabsModule,\n NzButtonModule,\n NzIconModule,\n NzTooltipModule,\n NzDropDownModule,\n NzMenuModule,\n ],\n templateUrl: './request-tabs-bar.component.html',\n styleUrls: ['./request-tabs-bar.component.less'],\n \n})\nexport class RequestTabsBarComponent {\n private contextMenuService = inject(NzContextMenuService);\n\n @Input() tabs = signal<ApiClientTab[]>([]);\n @Input() activeTabId = signal<string | null>(null);\n @Input() canOpenMore = true;\n\n @Output() tabChange = new EventEmitter<string>();\n @Output() tabClose = new EventEmitter<string>();\n @Output() tabAdd = new EventEmitter<void>();\n @Output() tabRename = new EventEmitter<{ id: string; title: string }>();\n @Output() tabReorder = new EventEmitter<{ from: number; to: number }>();\n @Output() tabContextMenu = new EventEmitter<TabContextMenuEvent>();\n @Output() startRenameEdit = new EventEmitter<string>(); // 触发重命名编辑模式\n\n @ViewChild('editInput') editInput?: ElementRef<HTMLInputElement>;\n @ViewChild('contextMenu') contextMenu?: NzDropdownMenuComponent\n\n readonly editingTabId = signal<string | null>(null);\n readonly editingTitle = signal('');\n\n // 右键菜单状态\n readonly contextTab = signal<ApiClientTab | null>(null);\n readonly contextIndex = signal(-1);\n\n activeIndex = computed(() => {\n const id = this.activeTabId();\n const tabs = this.tabs();\n return id ? tabs.findIndex((t) => t.id === id) : -1;\n });\n\n /** 是否有右侧 Tab */\n hasRightTabs(): boolean {\n const idx = this.contextIndex();\n return idx >= 0 && idx < this.tabs().length - 1;\n }\n\n /** 是否有已保存的 Tab */\n hasSavedTabs(): boolean {\n return this.tabs().some(t => !t.isDirty && t.requestId);\n }\n\n /**\n * 快捷键支持\n * Ctrl+T: 新建 Tab\n * Ctrl+W: 关闭当前 Tab\n * F2: 重命名当前 Tab\n */\n @HostListener('window:keydown', ['$event'])\n onKeyDown(event: KeyboardEvent): void {\n // Ctrl+T: 新建 Tab\n if (event.ctrlKey && event.key === 't') {\n event.preventDefault();\n this.onAddClick();\n return;\n }\n\n // Ctrl+W: 关闭当前 Tab\n if (event.ctrlKey && event.key === 'w') {\n event.preventDefault();\n const activeId = this.activeTabId();\n if (activeId) {\n this.tabClose.emit(activeId);\n }\n return;\n }\n\n // F2: 重命名当前 Tab\n if (event.key === 'F2') {\n event.preventDefault();\n const activeId = this.activeTabId();\n if (activeId) {\n const tab = this.tabs().find(t => t.id === activeId);\n if (tab) {\n this.startEdit(tab);\n }\n }\n return;\n }\n }\n\n getMethodClass(method: string): string {\n return method.toLowerCase();\n }\n\n getDisplayTitle(tab: ApiClientTab): string {\n if (tab.title && tab.title !== 'New Request') {\n return this.truncate(tab.title, 20);\n }\n\n const request = tab.request;\n if (!request.url) return 'New Request';\n\n const path = this.extractPath(request.url);\n return this.truncate(path, 20);\n }\n\n getFullTitle(tab: ApiClientTab): string {\n if (tab.title && tab.title !== 'New Request') {\n return tab.title;\n }\n\n const request = tab.request;\n if (!request.url) return 'New Request';\n\n return `${request.method} ${request.url}`;\n }\n\n private extractPath(url: string): string {\n const cleaned = url\n .replace(/^\\{\\{[^}]+\\}\\}/, '')\n .replace(/^https?:\\/\\/[^/]+/, '');\n return cleaned.split('?')[0] || '/';\n }\n\n private truncate(str: string, maxLen: number): string {\n if (str.length <= maxLen) return str;\n return str.slice(0, maxLen - 2) + '…';\n }\n\n onTabClick(tabId: string): void {\n if (tabId !== this.activeTabId()) {\n this.tabChange.emit(tabId);\n }\n }\n\n onCloseClick(tabId: string, event: MouseEvent): void {\n event.stopPropagation();\n this.tabClose.emit(tabId);\n }\n\n onAddClick(): void {\n this.tabAdd.emit();\n }\n\n /** 右键菜单 */\n onContextMenu(event: MouseEvent, tab: ApiClientTab, index: number): void {\n event.preventDefault();\n\n this.contextTab.set(tab);\n this.contextIndex.set(index);\n\n // 使用 NzContextMenuService 显示右键菜单\n this.contextMenuService.create(event, this.contextMenu!);\n }\n\n /** 右键菜单操作 */\n onMenuAction(action: TabContextMenuAction): void {\n const tab = this.contextTab();\n if (!tab) return;\n\n // 重命名特殊处理:启动编辑模式\n if (action === 'rename') {\n this.switchToTab(tab.id);\n this.startEdit(tab);\n this.clearContext();\n return;\n }\n\n this.tabContextMenu.emit({\n tabId: tab.id,\n action,\n });\n\n this.clearContext();\n }\n\n /** 切换到指定 Tab */\n private switchToTab(tabId: string): void {\n if (tabId !== this.activeTabId()) {\n this.tabChange.emit(tabId);\n }\n }\n\n /** 开始编辑 */\n startEdit(tab: ApiClientTab): void {\n this.editingTabId.set(tab.id);\n this.editingTitle.set(tab.title || tab.request.name || 'New Request');\n setTimeout(() => {\n this.editInput?.nativeElement?.focus();\n this.editInput?.nativeElement?.select();\n }, 0);\n }\n\n finishEdit(): void {\n const id = this.editingTabId();\n const title = this.editingTitle().trim();\n if (id && title) {\n this.tabRename.emit({ id, title });\n }\n this.cancelEdit();\n }\n\n cancelEdit(): void {\n this.editingTabId.set(null);\n this.editingTitle.set('');\n }\n\n onDrop(event: CdkDragDrop<ApiClientTab[]>): void {\n if (event.previousIndex !== event.currentIndex) {\n this.tabReorder.emit({\n from: event.previousIndex,\n to: event.currentIndex,\n });\n }\n }\n\n /** 清除右键菜单状态 */\n private clearContext(): void {\n this.contextTab.set(null);\n this.contextIndex.set(-1);\n }\n}\n","import { CommonModule } from '@angular/common';\r\nimport { Component, inject, signal, ViewChild } from '@angular/core';\r\nimport { PageLayoutComponent } from '@app/shared';\r\nimport { NzButtonModule } from 'ng-zorro-antd/button';\r\nimport { NzIconModule } from 'ng-zorro-antd/icon';\r\nimport { NzLayoutModule } from 'ng-zorro-antd/layout';\r\nimport { NzTooltipModule } from 'ng-zorro-antd/tooltip';\r\nimport { NzModalModule, NzModalService } from 'ng-zorro-antd/modal';\r\nimport { ApiHistoryDrawerComponent } from './components/history';\r\nimport { RequestCollectionsComponent } from './components/request-collections';\r\nimport { EnvPickerComponent, RequestEditorComponent } from './components/request-editor';\r\nimport { ResponseViewerComponent } from './components/response-viewer';\r\nimport { RequestTabsBarComponent, TabContextMenuEvent } from './components/request-tabs-bar/request-tabs-bar.component';\r\nimport { ApiClientStateService } from './services';\r\nimport { NzEmptyModule } from 'ng-zorro-antd/empty';\r\n\r\n@Component({\r\n selector: 'app-api-client.component',\r\n imports: [\r\n CommonModule,\r\n PageLayoutComponent,\r\n NzButtonModule,\r\n NzIconModule,\r\n NzLayoutModule,\r\n NzTooltipModule,\r\n NzModalModule,\r\n RequestCollectionsComponent,\r\n RequestEditorComponent,\r\n ResponseViewerComponent,\r\n RequestTabsBarComponent,\r\n ApiHistoryDrawerComponent,\r\n EnvPickerComponent,\r\n NzEmptyModule\r\n ],\r\n styles: [\r\n `\r\n .page{\r\n height: 100%;\r\n display: flex;\r\n flex-direction: row;\r\n overflow: hidden;\r\n gap: 16px;\r\n padding:0 16px;\r\n }\r\n .content {\r\n flex: 1 1 auto;\r\n width: 0;\r\n display: flex;\r\n flex-direction: column;\r\n height: 100%;\r\n overflow: hidden;\r\n }\r\n .editor-area {\r\n flex: 1 1 auto;\r\n display: flex;\r\n flex-direction: column;\r\n min-height: 0;\r\n }\r\n app-request-editor {\r\n flex: 0 0 auto;\r\n height:50%;\r\n }\r\n app-response-viewer {\r\n flex: 0 0 auto;\r\n height:50%;\r\n overflow: auto;\r\n }\r\n `\r\n ],\r\n template: `\r\n <app-page-layout [title]=\"'API 请求'\" [loading]=\"store.loading()\" [isFullscreen]=\"true\" [isOverflowYAuto]=\"false\">\r\n <ng-container ngProjectAs=\"actions\">\r\n <app-env-picker/>\r\n <!-- <button nz-button nzType=\"default\" (click)=\"store.sendHubV2Issues()\" nz-tooltip nzTooltipTitle=\"读取当前项目 Hub V2 Issues\">\r\n Hub Issues\r\n </button> -->\r\n <button nz-button nzType=\"text\" (click)=\"store.openHistory()\" nz-tooltip nzTooltipTitle=\"历史记录\">\r\n <nz-icon nzType=\"history\" nzTheme=\"outline\" />\r\n </button>\r\n </ng-container>\r\n <nz-layout class=\"page\">\r\n <app-request-collections\r\n [nodes]=\"store.filteredNodes()\"\r\n [(q)]=\"store.q\"\r\n [activeId]=\"store.activeRequestId()\"\r\n (select)=\"store.selectRequest($event)\"\r\n (createRequest)=\"store.newRequest({collectionId: $event.collectionId})\"\r\n (createCollection)=\"store.newCollection({kind:'collection'})\"\r\n (createFolder)=\"store.newCollection({kind:'folder', parentId: $event.collectionId})\"\r\n (reload)=\"store.loadAll()\"\r\n (delete)=\"store.deleteCollection($event.id, $event.kind)\"\r\n (rename)=\"store.renameCollection($event.id, $event.kind)\"\r\n (move)=\"store.moveCollection($event.id, $event.kind)\"\r\n [loading]=\"store.loading()\"\r\n />\r\n <div class=\"content\">\r\n <!-- Tabs 标签栏 -->\r\n <app-request-tabs-bar\r\n [tabs]=\"store.tabs\"\r\n [activeTabId]=\"store.activeTabId\"\r\n [canOpenMore]=\"store.canOpenMore()\"\r\n (tabChange)=\"store.switchTab($event)\"\r\n (tabClose)=\"handleTabClose($event)\"\r\n (tabAdd)=\"store.newTab()\"\r\n (tabRename)=\"store.renameTab($event.id, $event.title)\"\r\n (tabReorder)=\"store.reorderTabs($event.from, $event.to)\"\r\n (tabContextMenu)=\"handleTabContextMenu($event)\"\r\n />\r\n \r\n @if(store.activeRequest()){\r\n <div class=\"editor-area\">\r\n <app-request-editor\r\n [collectionPath]=\"store.collectionPath()\"\r\n [baseUrl]=\"store.activeEnv()?.baseUrl ?? null\"\r\n [request]=\"store.activeRequest()\"\r\n [sending]=\"store.sending()\"\r\n [envVars]=\"store.envVarRecord()\"\r\n [openEnv]=\"openEnv\"\r\n (patch)=\"store.patchActive($event)\"\r\n (save)=\"store.saveActive()\"\r\n (send)=\"store.sendActive()\"\r\n />\r\n <app-response-viewer\r\n [sending]=\"store.sending()\"\r\n [result]=\"store.lastResult()\"\r\n />\r\n </div>\r\n }@else{\r\n <nz-empty \r\n [nzNotFoundContent]=\"contentTpl\"\r\n [nzNotFoundFooter]=\"footerTpl\">\r\n </nz-empty>\r\n }\r\n <ng-template #contentTpl>\r\n <span>暂无请求,点击左侧面板右上角\"+\" 创建请求</span>\r\n </ng-template>\r\n <ng-template #footerTpl>\r\n <button nz-button nzType=\"primary\" (click)=\"store.newTab()\">立即新增</button>\r\n </ng-template>\r\n </div>\r\n </nz-layout>\r\n </app-page-layout>\r\n @if (store.historyOpen()) {\r\n <app-api-history-drawer\r\n [loading]=\"store.historyLoading()\"\r\n [histories]=\"store.histories()\"\r\n (close)=\"store.closeHistory()\"\r\n (replay)=\"store.replayHistory($event)\"\r\n />\r\n }\r\n `,\r\n})\r\nexport class ApiClientComponent {\r\n store = inject(ApiClientStateService);\r\n private modal = inject(NzModalService);\r\n\r\n @ViewChild('envPicker') envPicker!: EnvPickerComponent;\r\n\r\n openEnv = () => {\r\n this.envPicker.openEnvModal();\r\n }\r\n\r\n /**\r\n * 处理 Tab 关闭\r\n */\r\n handleTabClose(tabId: string): void {\r\n const tab = this.store.tabs().find(t => t.id === tabId);\r\n \r\n if (tab?.isDirty) {\r\n this.modal.confirm({\r\n nzTitle: '关闭确认',\r\n nzContent: '当前请求有未保存的修改,确定要关闭吗?',\r\n nzOkText: '关闭',\r\n nzCancelText: '取消',\r\n nzOnOk: () => {\r\n this.store.closeTab(tabId);\r\n }\r\n });\r\n } else {\r\n this.store.closeTab(tabId);\r\n }\r\n }\r\n\r\n /**\r\n * 处理右键菜单操作\r\n */\r\n handleTabContextMenu(event: TabContextMenuEvent): void {\r\n const { tabId, action } = event;\r\n\r\n switch (action) {\r\n case 'close':\r\n this.handleTabClose(tabId);\r\n break;\r\n\r\n case 'closeOthers': {\r\n const dirtyTabs = this.store.tabs().filter(t => t.id !== tabId && t.isDirty);\r\n if (dirtyTabs.length > 0) {\r\n this.modal.confirm({\r\n nzTitle: '关闭其他标签页',\r\n nzContent: `有 ${dirtyTabs.length} 个标签页有未保存的修改,确定要全部关闭吗?`,\r\n nzOkText: '全部关闭',\r\n nzCancelText: '取消',\r\n nzOnOk: () => {\r\n this.store.tabStore.closeOtherTabs(tabId);\r\n }\r\n });\r\n } else {\r\n this.store.tabStore.closeOtherTabs(tabId);\r\n }\r\n break;\r\n }\r\n\r\n case 'closeRight': {\r\n const idx = this.store.tabs().findIndex(t => t.id === tabId);\r\n const rightTabs = this.store.tabs().slice(idx + 1);\r\n const dirtyTabs = rightTabs.filter(t => t.isDirty);\r\n if (dirtyTabs.length > 0) {\r\n this.modal.confirm({\r\n nzTitle: '关闭右侧标签页',\r\n nzContent: `右侧有 ${dirtyTabs.length} 个标签页有未保存的修改,确定要全部关闭吗?`,\r\n nzOkText: '全部关闭',\r\n nzCancelText: '取消',\r\n nzOnOk: () => {\r\n this.store.tabStore.closeRightTabs(tabId);\r\n }\r\n });\r\n } else {\r\n this.store.tabStore.closeRightTabs(tabId);\r\n }\r\n break;\r\n }\r\n\r\n case 'closeSaved': {\r\n const savedTabs = this.store.tabs().filter(t => !t.isDirty && t.requestId);\r\n if (savedTabs.length > 0) {\r\n this.modal.confirm({\r\n nzTitle: '关闭已保存的标签页',\r\n nzContent: `确定要关闭 ${savedTabs.length} 个已保存的标签页吗?`,\r\n nzOkText: '关闭',\r\n nzCancelText: '取消',\r\n nzOnOk: () => {\r\n this.store.tabStore.closeSavedTabs();\r\n }\r\n });\r\n }\r\n break;\r\n }\r\n\r\n case 'duplicate':\r\n try {\r\n this.store.tabStore.duplicateTab(tabId);\r\n } catch (e: any) {\r\n console.error(e);\r\n }\r\n break;\r\n\r\n case 'copyUrl': {\r\n const url = this.store.tabStore.getTabUrl(tabId);\r\n if (url) {\r\n navigator.clipboard.writeText(url);\r\n }\r\n break;\r\n }\r\n\r\n case 'moveTo': {\r\n const tab = this.store.tabStore.getTab(tabId);\r\n if (tab?.requestId) {\r\n this.store.moveCollection(tab.requestId, 'request');\r\n }\r\n break;\r\n }\r\n }\r\n }\r\n}\r\n","import { NgModule } from '@angular/core';\r\nimport { RouterModule, Routes } from '@angular/router';\r\nimport { ApiClientComponent } from './api-client.component';\r\n\r\nconst routes: Routes = [\r\n { path: '', component: ApiClientComponent }\r\n];\r\n\r\n@NgModule({\r\n imports: [RouterModule.forChild(routes)],\r\n exports: [RouterModule]\r\n})\r\nexport class ApiClientRoutingModule { }\r\n","import { NgModule } from '@angular/core';\r\nimport { CommonModule } from '@angular/common';\r\n\r\nimport { ApiClientRoutingModule } from './api-client-routing.module';\r\n\r\n\r\n@NgModule({\r\n declarations: [],\r\n imports: [\r\n CommonModule,\r\n ApiClientRoutingModule\r\n ]\r\n})\r\nexport class ApiClientModule { }\r\n"],"mappings":"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","names":["ApiHistoryDrawerComponent","RequestListItemComponent","RequestListComponent","CollectionTreeItemComponent","CollectionTreeComponent","RequestCollectionsComponent","AuthEditorComponent","KvTableComponent","BodyEditorComponent","import_lodash","import_lodash","ApiClientTabStore","t","input","import_lodash","import_lodash","ApiClientService","CollectionModalComponent","CollectionModalService","ApiClientStateService","input","now","EnvModalComponent","EnvPickerComponent","AdvancedEditorComponent","RequestTabsComponent","RequestUrlbarComponent","RequestEditorComponent","CurlActionsComponent","ResponseViewerComponent","request_tabs_bar_component_default","RequestTabsBarComponent","ApiClientComponent","ApiClientRoutingModule","ApiClientModule"],"x_google_ignoreList":[14]}
|