@gadmin2n/schematics 0.0.63 → 0.0.65
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/dist/lib/application/files/gadmin2-game-angle-demo/.dockerignore +2 -2
- package/dist/lib/application/files/gadmin2-game-angle-demo/Dockerfile +40 -26
- package/dist/lib/application/files/gadmin2-game-angle-demo/Jenkinsfile +30 -4
- package/dist/lib/application/files/gadmin2-game-angle-demo/config/prisma/example.prisma +33 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/config/prisma/system.prisma +163 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/config/ui/Event.ts +70 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/config/ui/Game.ts +6 -6
- package/dist/lib/application/files/gadmin2-game-angle-demo/config/ui/ITActivityDay.ts +70 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/config/ui/Log.ts +2 -2
- package/dist/lib/application/files/gadmin2-game-angle-demo/config/ui/Role.ts +2 -2
- package/dist/lib/application/files/gadmin2-game-angle-demo/server/.env +20 -9
- package/dist/lib/application/files/gadmin2-game-angle-demo/server/.env.local +1 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/server/.eslintrc.js +1 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/server/.prettierignore +1 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/server/README.md +2 -18
- package/dist/lib/application/files/gadmin2-game-angle-demo/server/gadmin-cli.json +1 -1
- package/dist/lib/application/files/gadmin2-game-angle-demo/server/migrate-between-pg-schemas.js +1232 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/server/package.json +65 -38
- package/dist/lib/application/files/gadmin2-game-angle-demo/server/prisma/.generator.prisma +4 -3
- package/dist/lib/application/files/gadmin2-game-angle-demo/server/prisma.config.ts +16 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/server/seed/games.ts +1 -71
- package/dist/lib/application/files/gadmin2-game-angle-demo/server/seed/index.ts +17 -21
- package/dist/lib/application/files/gadmin2-game-angle-demo/server/seed/permissions.ts +278 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/server/seed/seedDataMngtPages.ts +258 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/server/seed/users.ts +7 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/alias.config.ts +7 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/app.controller.ts +151 -11
- package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/app.module.ts +29 -13
- package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/app.service.ts +151 -12
- package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/lib/auth.guard.ts +87 -41
- package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/lib/http-cache.interceptor.ts +21 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/lib/logger.ts +19 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/lib/safe-log.util.ts +176 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/lib/{yufuid.ts → taihu.ts} +49 -34
- package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/lib/tracing.ts +174 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/lib/trim.pipe.ts +51 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/lib/utils.ts +91 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/lib/woaAuth.ts +25 -12
- package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/main.ts +22 -12
- package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/audit/audit.controller.spec.ts +20 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/audit/audit.controller.ts +190 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/audit/audit.module.ts +10 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/audit/audit.service.spec.ts +338 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/audit/audit.service.ts +83 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/game/game.controller.spec.ts +20 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/game/game.controller.ts +188 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/game/game.module.ts +10 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/game/game.service.spec.ts +18 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/game/game.service.ts +83 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/page/page.controller.spec.ts +20 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/page/page.controller.ts +250 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/page/page.module.ts +10 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/page/page.service.spec.ts +18 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/page/page.service.ts +1051 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/pageResource/pageResource.controller.spec.ts +20 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/pageResource/pageResource.controller.ts +196 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/pageResource/pageResource.module.ts +13 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/pageResource/pageResource.service.spec.ts +18 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/pageResource/pageResource.service.ts +219 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/resource/resource.controller.spec.ts +20 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/resource/resource.controller.ts +196 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/resource/resource.module.ts +10 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/resource/resource.service.spec.ts +18 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/resource/resource.service.ts +199 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/role/role.controller.spec.ts +20 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/role/role.controller.ts +210 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/role/role.module.ts +12 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/role/role.service.spec.ts +18 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/role/role.service.ts +849 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/role/roles-refresher.service.ts +133 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/rolePages/rolePages.controller.spec.ts +20 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/rolePages/rolePages.controller.ts +196 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/rolePages/rolePages.module.ts +10 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/rolePages/rolePages.service.spec.ts +18 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/rolePages/rolePages.service.ts +201 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/roleResource/roleResource.controller.spec.ts +20 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/roleResource/roleResource.controller.ts +196 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/roleResource/roleResource.module.ts +10 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/roleResource/roleResource.service.spec.ts +18 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/roleResource/roleResource.service.ts +216 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/user/user.controller.spec.ts +20 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/user/user.controller.ts +198 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/user/user.module.ts +10 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/user/user.service.spec.ts +18 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/user/user.service.ts +104 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/server/start-prod.sh +130 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/server/tsconfig.json +18 -3
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/index.html +19 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/package.json +34 -42
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/postcss.config.cjs +6 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/App.tsx +111 -185
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/auditLogProvider.ts +5 -5
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/components/contexts/color-mode/index.tsx +49 -51
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/components/custom-avatar.tsx +38 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/components/index.ts +4 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/components/layout/{header/index.tsx → header.tsx} +22 -31
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/components/layout/index.ts +3 -1
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/components/layout/layout.tsx +32 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/components/layout/logo.tsx +19 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/components/layout/sider.tsx +331 -166
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/components/layout/title.tsx +61 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/components/pagination-total.tsx +21 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/components/tags/index.ts +1 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/components/tags/role-tag.tsx +44 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/components/text.tsx +74 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/config/routeRegistry.tsx +258 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/constants/layout.ts +16 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/enums/audit-log.enum.ts +13 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/enums/index.ts +1 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/helpers/form.tsx +2 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/helpers/login.ts +22 -4
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/hooks/useDynamicResources.tsx +211 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/hooks/useFetchData.ts +33 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/hooks/useRoles.ts +30 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/hooks/useUserPageAccess.ts +339 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/i18n.ts +8 -4
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/index.tsx +3 -11
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/{public → src}/locales/en/common.json +1 -1
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/{public → src}/locales/zh_CN/common.json +1 -1
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/audit/components/action-cell.css +3 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/audit/components/action-cell.tsx +134 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/audit/create.tsx +113 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/audit/edit.tsx +122 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/audit/index.ts +8 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/audit/index.tsx +6 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/audit/list.tsx +213 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/audit/show.tsx +61 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/page/Components/AssignRolesModal.tsx +168 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/page/Components/CreatePageModal.tsx +42 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/page/Components/EditPageModal.tsx +42 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/page/Components/PageDetailDrawer.tsx +101 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/page/Components/PageFormModal.tsx +731 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/page/create.tsx +113 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/page/edit.tsx +122 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/page/hooks/usePageManagement.ts +36 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/page/index.ts +8 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/page/index.tsx +6 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/page/list.tsx +1113 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/page/queries.ts +17 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/page/show.tsx +61 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/page/types.ts +44 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/pageResource/create.tsx +113 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/pageResource/edit.tsx +122 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/pageResource/index.tsx +6 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/pageResource/list.tsx +243 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/pageResource/show.tsx +61 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/permission-readme/index.tsx +1088 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/resource/Components/CreateModal.tsx +25 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/resource/Components/EditModal.tsx +28 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/resource/Components/ResourceDetailDrawer.tsx +160 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/resource/Components/modal.tsx +202 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/resource/create.tsx +113 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/resource/edit.tsx +122 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/resource/index.ts +9 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/resource/index.tsx +6 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/resource/list.tsx +184 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/resource/queries.ts +10 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/resource/show.tsx +61 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/resource/types.ts +9 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/role/Components/CreateModal.tsx +30 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/role/Components/EditModal.tsx +47 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/role/Components/RoleDetailDrawer.tsx +56 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/role/Components/modal.tsx +302 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/role/create.tsx +113 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/role/edit.tsx +122 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/role/hooks/useRolePage.ts +35 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/role/index.ts +8 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/role/index.tsx +6 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/role/list.tsx +382 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/role/queries.ts +8 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/role/show.tsx +61 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/role/types.ts +8 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/rolePages/create.tsx +113 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/rolePages/edit.tsx +122 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/rolePages/index.tsx +6 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/rolePages/list.tsx +243 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/rolePages/show.tsx +61 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/roleResource/create.tsx +113 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/roleResource/edit.tsx +122 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/roleResource/index.tsx +6 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/roleResource/list.tsx +243 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/roleResource/show.tsx +61 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/user/components/create-modal.tsx +17 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/user/components/edit-modal.tsx +19 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/user/components/form-modal.tsx +188 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/user/components/index.ts +5 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/user/components/role-tag.tsx +48 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/user/components/show-drawer.tsx +140 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/user/create.tsx +113 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/user/edit.tsx +122 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/user/index.ts +8 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/user/index.tsx +6 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/user/list.tsx +342 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/user/queries.ts +14 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/routes/user/show.tsx +61 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/styles/antd.css +132 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/styles/fc.css +58 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/styles/index.css +128 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/styles/show-drawer.module.css +18 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/styles/show-page.module.css +21 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/types/audit-log.ts +1 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/types/index.ts +3 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/types/role.ts +7 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/types/user.ts +1 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/utilities/get-name-initials.ts +8 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/utilities/get-random-color.ts +27 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/utilities/index.ts +2 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/utilities/utils.tsx +5 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/vite-env.d.ts +1 -0
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/tsconfig.json +3 -3
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/vite.config.ts +31 -0
- package/package.json +1 -1
- package/dist/lib/application/files/gadmin2-game-angle-demo/config/prisma/sample.prisma +0 -65
- package/dist/lib/application/files/gadmin2-game-angle-demo/config/ui/Source.ts +0 -76
- package/dist/lib/application/files/gadmin2-game-angle-demo/config/ui/Tasklog.ts +0 -76
- package/dist/lib/application/files/gadmin2-game-angle-demo/server/seed/roles.ts +0 -4
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/craco.config.js +0 -27
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/public/index.html +0 -53
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/components/layout/styles.ts +0 -10
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/react-app-env.d.ts +0 -1
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/reportWebVitals.ts +0 -15
- package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/styles/antd.less +0 -79
- /package/dist/lib/application/files/gadmin2-game-angle-demo/web/src/components/VanillaJSONEditor/{index.js → index.jsx} +0 -0
package/dist/lib/application/files/gadmin2-game-angle-demo/server/src/modules/page/page.service.ts
ADDED
|
@@ -0,0 +1,1051 @@
|
|
|
1
|
+
import { Inject, Injectable } from '@nestjs/common';
|
|
2
|
+
import { Page, Prisma } from '@prisma/client';
|
|
3
|
+
import { WINSTON_MODULE_PROVIDER } from 'nest-winston';
|
|
4
|
+
import { PrismaService } from 'nestjs-prisma';
|
|
5
|
+
import { Logger } from 'winston';
|
|
6
|
+
|
|
7
|
+
import { ConfigService } from '@nestjs/config';
|
|
8
|
+
import { createSafeLogData } from '../../lib/safe-log.util';
|
|
9
|
+
|
|
10
|
+
@Injectable()
|
|
11
|
+
export class PageService {
|
|
12
|
+
constructor(
|
|
13
|
+
private prisma: PrismaService,
|
|
14
|
+
private readonly config: ConfigService,
|
|
15
|
+
@Inject(WINSTON_MODULE_PROVIDER) private readonly logger: Logger,
|
|
16
|
+
) {}
|
|
17
|
+
|
|
18
|
+
async createOne(pageCreateArgs: Prisma.PageCreateArgs) {
|
|
19
|
+
this.logger.info(
|
|
20
|
+
'[Page] Creating page',
|
|
21
|
+
createSafeLogData({
|
|
22
|
+
operation: 'CREATE',
|
|
23
|
+
table: 'page',
|
|
24
|
+
data: pageCreateArgs.data,
|
|
25
|
+
}),
|
|
26
|
+
);
|
|
27
|
+
const result = await this.prisma.page.create(pageCreateArgs);
|
|
28
|
+
this.logger.info(
|
|
29
|
+
'[Page] Page created successfully',
|
|
30
|
+
createSafeLogData({
|
|
31
|
+
operation: 'CREATE',
|
|
32
|
+
table: 'page',
|
|
33
|
+
result: result,
|
|
34
|
+
}),
|
|
35
|
+
);
|
|
36
|
+
return result;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* 在事务中创建 page 及其 pageResource 关系
|
|
41
|
+
* @param pageData 页面创建数据
|
|
42
|
+
* @param resourceIds 资源 ID 数组(可选)
|
|
43
|
+
*/
|
|
44
|
+
async createPageWithResources(
|
|
45
|
+
pageData: Prisma.PageCreateInput,
|
|
46
|
+
resourceIds?: { resourceId: number; actions: string[] }[],
|
|
47
|
+
) {
|
|
48
|
+
// 如果没有 resourceIds,直接创建页面即可
|
|
49
|
+
if (!resourceIds || resourceIds.length === 0) {
|
|
50
|
+
this.logger.info(
|
|
51
|
+
'[Page] Creating page without resources',
|
|
52
|
+
createSafeLogData({
|
|
53
|
+
operation: 'CREATE',
|
|
54
|
+
table: 'page',
|
|
55
|
+
data: pageData,
|
|
56
|
+
}),
|
|
57
|
+
);
|
|
58
|
+
const result = await this.prisma.page.create({
|
|
59
|
+
data: pageData,
|
|
60
|
+
});
|
|
61
|
+
this.logger.info(
|
|
62
|
+
'[Page] Page created successfully',
|
|
63
|
+
createSafeLogData({
|
|
64
|
+
operation: 'CREATE',
|
|
65
|
+
table: 'page',
|
|
66
|
+
result: result,
|
|
67
|
+
}),
|
|
68
|
+
);
|
|
69
|
+
return result;
|
|
70
|
+
}
|
|
71
|
+
//有 resourceIds 时,使用交互式事务确保原子性
|
|
72
|
+
this.logger.info(
|
|
73
|
+
'[Page] Creating page with resources in transaction',
|
|
74
|
+
createSafeLogData({
|
|
75
|
+
operation: 'CREATE_WITH_RESOURCES',
|
|
76
|
+
table: 'page',
|
|
77
|
+
pageData: pageData,
|
|
78
|
+
resourceIds: resourceIds,
|
|
79
|
+
}),
|
|
80
|
+
);
|
|
81
|
+
return await this.prisma.$transaction(async (tx) => {
|
|
82
|
+
// 1. 创建页面
|
|
83
|
+
const page = await tx.page.create({
|
|
84
|
+
data: pageData,
|
|
85
|
+
});
|
|
86
|
+
this.logger.info(
|
|
87
|
+
'[Page] Page created in transaction',
|
|
88
|
+
createSafeLogData({
|
|
89
|
+
operation: 'CREATE',
|
|
90
|
+
table: 'page',
|
|
91
|
+
result: page,
|
|
92
|
+
}),
|
|
93
|
+
);
|
|
94
|
+
|
|
95
|
+
// 2. 创建 pageResource 关系
|
|
96
|
+
const pageResourcesData = resourceIds.map((item) => ({
|
|
97
|
+
pageId: page.id,
|
|
98
|
+
resourceId: item.resourceId,
|
|
99
|
+
actions: item.actions as Prisma.InputJsonValue,
|
|
100
|
+
}));
|
|
101
|
+
|
|
102
|
+
this.logger.info(
|
|
103
|
+
'[PageResource] Creating page resources in transaction',
|
|
104
|
+
createSafeLogData({
|
|
105
|
+
operation: 'CREATE_MANY',
|
|
106
|
+
table: 'pageResource',
|
|
107
|
+
data: pageResourcesData,
|
|
108
|
+
}),
|
|
109
|
+
);
|
|
110
|
+
const createResult = await tx.pageResource.createMany({
|
|
111
|
+
data: pageResourcesData,
|
|
112
|
+
skipDuplicates: true,
|
|
113
|
+
});
|
|
114
|
+
this.logger.info(
|
|
115
|
+
'[PageResource] Page resources created in transaction',
|
|
116
|
+
createSafeLogData({
|
|
117
|
+
operation: 'CREATE_MANY',
|
|
118
|
+
table: 'pageResource',
|
|
119
|
+
count: createResult.count,
|
|
120
|
+
}),
|
|
121
|
+
);
|
|
122
|
+
|
|
123
|
+
return page;
|
|
124
|
+
});
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
async createMany(data: Prisma.PageCreateManyArgs['data']) {
|
|
128
|
+
this.logger.info(
|
|
129
|
+
'[Page] Creating multiple pages',
|
|
130
|
+
createSafeLogData({
|
|
131
|
+
operation: 'CREATE_MANY',
|
|
132
|
+
table: 'page',
|
|
133
|
+
count: Array.isArray(data) ? data.length : 1,
|
|
134
|
+
data: data,
|
|
135
|
+
}),
|
|
136
|
+
);
|
|
137
|
+
const result = await this.prisma.page.createMany({
|
|
138
|
+
data,
|
|
139
|
+
skipDuplicates: true,
|
|
140
|
+
});
|
|
141
|
+
this.logger.info(
|
|
142
|
+
'[Page] Multiple pages created successfully',
|
|
143
|
+
createSafeLogData({
|
|
144
|
+
operation: 'CREATE_MANY',
|
|
145
|
+
table: 'page',
|
|
146
|
+
count: result.count,
|
|
147
|
+
}),
|
|
148
|
+
);
|
|
149
|
+
return result;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
async findMany(
|
|
153
|
+
pageFindManyArgs: Prisma.PageFindManyArgs,
|
|
154
|
+
): Promise<{ itemCount: number; entities: Page[] }> {
|
|
155
|
+
const itemCount = await this.prisma.page.count({
|
|
156
|
+
where: pageFindManyArgs.where,
|
|
157
|
+
});
|
|
158
|
+
const entities = await this.prisma.page.findMany(pageFindManyArgs);
|
|
159
|
+
return { itemCount, entities };
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
async findUnique(id: number, select: Prisma.PageFindUniqueArgs['select']) {
|
|
163
|
+
return await this.prisma.page.findUnique({
|
|
164
|
+
where: { id: id },
|
|
165
|
+
select,
|
|
166
|
+
});
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
async updateMany(pageUpdateManyArgs: Prisma.PageUpdateManyArgs) {
|
|
170
|
+
this.logger.info(
|
|
171
|
+
'[Page] Updating multiple pages',
|
|
172
|
+
createSafeLogData({
|
|
173
|
+
operation: 'UPDATE_MANY',
|
|
174
|
+
table: 'page',
|
|
175
|
+
where: pageUpdateManyArgs.where,
|
|
176
|
+
data: pageUpdateManyArgs.data,
|
|
177
|
+
}),
|
|
178
|
+
);
|
|
179
|
+
const result = await this.prisma.page.updateMany(pageUpdateManyArgs);
|
|
180
|
+
this.logger.info(
|
|
181
|
+
'[Page] Multiple pages updated successfully',
|
|
182
|
+
createSafeLogData({
|
|
183
|
+
operation: 'UPDATE_MANY',
|
|
184
|
+
table: 'page',
|
|
185
|
+
count: result.count,
|
|
186
|
+
}),
|
|
187
|
+
);
|
|
188
|
+
return result;
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
async updateUnique(id: number, data: Prisma.PageUpdateManyArgs['data']) {
|
|
192
|
+
const oldData = await this.prisma.page.findUnique({ where: { id } });
|
|
193
|
+
this.logger.info(
|
|
194
|
+
'[Page] Updating page',
|
|
195
|
+
createSafeLogData({
|
|
196
|
+
operation: 'UPDATE',
|
|
197
|
+
table: 'page',
|
|
198
|
+
id: id,
|
|
199
|
+
oldData: oldData,
|
|
200
|
+
newData: data,
|
|
201
|
+
}),
|
|
202
|
+
);
|
|
203
|
+
const result = await this.prisma.page.update({
|
|
204
|
+
where: { id: id },
|
|
205
|
+
data,
|
|
206
|
+
});
|
|
207
|
+
this.logger.info(
|
|
208
|
+
'[Page] Page updated successfully',
|
|
209
|
+
createSafeLogData({
|
|
210
|
+
operation: 'UPDATE',
|
|
211
|
+
table: 'page',
|
|
212
|
+
id: id,
|
|
213
|
+
result: result,
|
|
214
|
+
}),
|
|
215
|
+
);
|
|
216
|
+
return result;
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
/**
|
|
220
|
+
* 在事务中更新 page 及其 pageResource 关系,并同步更新 roleResource
|
|
221
|
+
*
|
|
222
|
+
* ========== 整体逻辑说明 ==========
|
|
223
|
+
* 数据关系:role -> rolePages -> page -> pageResource -> resource
|
|
224
|
+
* role -> roleResource -> resource
|
|
225
|
+
*
|
|
226
|
+
* 核心原则:
|
|
227
|
+
* 1. roleResource 是角色所有页面资源的【并集】
|
|
228
|
+
* 2. pageResource 的变化会影响 roleResource,但不会逆向影响其他页面
|
|
229
|
+
* 3. 只更新变化的部分,避免全量删除重建
|
|
230
|
+
*
|
|
231
|
+
* 处理策略:
|
|
232
|
+
* - 新增资源:将当前页面的 actions 与 roleResource 已有的 actions 取并集
|
|
233
|
+
* (因为新增时 roleResource 可能因其他页面已经存在,直接合并即可)
|
|
234
|
+
* - 删除资源:检查角色的其他页面是否还有该资源,没有则删除 roleResource,有则跳过
|
|
235
|
+
* - 修改资源:将当前页面的【新 actions】与【其他页面】的 actions 取并集
|
|
236
|
+
* (注意:不能与 roleResource 已有 actions 合并,因为那会保留当前页面的旧 actions)
|
|
237
|
+
* ================================
|
|
238
|
+
*
|
|
239
|
+
* @param id 页面 ID
|
|
240
|
+
* @param pageData 页面更新数据
|
|
241
|
+
* @param resourceIds 资源 ID 数组(可选)
|
|
242
|
+
*/
|
|
243
|
+
async updatePageWithResources(
|
|
244
|
+
id: number,
|
|
245
|
+
pageData: Prisma.PageUpdateManyArgs['data'],
|
|
246
|
+
resourceIds?: { resourceId: number; actions: string[] }[],
|
|
247
|
+
) {
|
|
248
|
+
// 使用交互式事务确保所有操作的原子性和一致性
|
|
249
|
+
return await this.prisma.$transaction(async (tx) => {
|
|
250
|
+
// Step 1: 更新页面基本信息
|
|
251
|
+
const oldPage = await tx.page.findUnique({ where: { id } });
|
|
252
|
+
this.logger.info(
|
|
253
|
+
'[Page] Updating page in transaction',
|
|
254
|
+
createSafeLogData({
|
|
255
|
+
operation: 'UPDATE',
|
|
256
|
+
table: 'page',
|
|
257
|
+
id: id,
|
|
258
|
+
oldData: oldPage,
|
|
259
|
+
newData: pageData,
|
|
260
|
+
}),
|
|
261
|
+
);
|
|
262
|
+
const page = await tx.page.update({
|
|
263
|
+
where: { id },
|
|
264
|
+
data: pageData,
|
|
265
|
+
});
|
|
266
|
+
this.logger.info(
|
|
267
|
+
'[Page] Page updated in transaction',
|
|
268
|
+
createSafeLogData({
|
|
269
|
+
operation: 'UPDATE',
|
|
270
|
+
table: 'page',
|
|
271
|
+
id: id,
|
|
272
|
+
result: page,
|
|
273
|
+
}),
|
|
274
|
+
);
|
|
275
|
+
|
|
276
|
+
// Step 2: 处理 pageResource 关系更新
|
|
277
|
+
if (resourceIds !== undefined && resourceIds !== null) {
|
|
278
|
+
// 2.1 在事务内获取当前页面的旧资源配置(确保数据一致性)
|
|
279
|
+
const oldPageResources = await tx.pageResource.findMany({
|
|
280
|
+
where: { pageId: id },
|
|
281
|
+
select: { resourceId: true, actions: true },
|
|
282
|
+
});
|
|
283
|
+
|
|
284
|
+
// 构建旧资源映射: resourceId -> actions[]
|
|
285
|
+
const oldResourceMap = new Map<number, string[]>();
|
|
286
|
+
for (const pr of oldPageResources) {
|
|
287
|
+
oldResourceMap.set(pr.resourceId, this.parseActions(pr.actions));
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
// 构建新资源映射: resourceId -> actions[]
|
|
291
|
+
const newResourceMap = new Map<number, string[]>();
|
|
292
|
+
for (const item of resourceIds) {
|
|
293
|
+
newResourceMap.set(item.resourceId, item.actions);
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
// 2.2 计算变化:新增的资源、删除的资源、修改的资源
|
|
297
|
+
const addedResources: { resourceId: number; actions: string[] }[] = [];
|
|
298
|
+
const removedResourceIds: number[] = [];
|
|
299
|
+
const modifiedResources: {
|
|
300
|
+
resourceId: number;
|
|
301
|
+
newActions: string[];
|
|
302
|
+
}[] = [];
|
|
303
|
+
|
|
304
|
+
// 找出新增和修改的资源
|
|
305
|
+
for (const [resourceId, newActions] of newResourceMap) {
|
|
306
|
+
const oldActions = oldResourceMap.get(resourceId);
|
|
307
|
+
if (!oldActions) {
|
|
308
|
+
// 新增的资源
|
|
309
|
+
addedResources.push({ resourceId, actions: newActions });
|
|
310
|
+
} else {
|
|
311
|
+
// 检查是否有修改(actions 变化)
|
|
312
|
+
const oldSet = new Set(oldActions);
|
|
313
|
+
const newSet = new Set(newActions);
|
|
314
|
+
const isChanged =
|
|
315
|
+
oldSet.size !== newSet.size ||
|
|
316
|
+
[...oldSet].some((a) => !newSet.has(a));
|
|
317
|
+
if (isChanged) {
|
|
318
|
+
modifiedResources.push({ resourceId, newActions });
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
// 找出删除的资源
|
|
324
|
+
for (const [resourceId] of oldResourceMap) {
|
|
325
|
+
if (!newResourceMap.has(resourceId)) {
|
|
326
|
+
removedResourceIds.push(resourceId);
|
|
327
|
+
}
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
// 2.3 更新 pageResource 表(先删后建)
|
|
331
|
+
this.logger.info(
|
|
332
|
+
'[PageResource] Deleting old page resources',
|
|
333
|
+
createSafeLogData({
|
|
334
|
+
operation: 'DELETE_MANY',
|
|
335
|
+
table: 'pageResource',
|
|
336
|
+
pageId: id,
|
|
337
|
+
oldResources: oldPageResources,
|
|
338
|
+
}),
|
|
339
|
+
);
|
|
340
|
+
const deleteResult = await tx.pageResource.deleteMany({
|
|
341
|
+
where: { pageId: id },
|
|
342
|
+
});
|
|
343
|
+
this.logger.info(
|
|
344
|
+
'[PageResource] Old page resources deleted',
|
|
345
|
+
createSafeLogData({
|
|
346
|
+
operation: 'DELETE_MANY',
|
|
347
|
+
table: 'pageResource',
|
|
348
|
+
pageId: id,
|
|
349
|
+
count: deleteResult.count,
|
|
350
|
+
}),
|
|
351
|
+
);
|
|
352
|
+
|
|
353
|
+
if (resourceIds.length > 0) {
|
|
354
|
+
const pageResourcesData = resourceIds.map((item) => ({
|
|
355
|
+
pageId: id,
|
|
356
|
+
resourceId: item.resourceId,
|
|
357
|
+
actions: item.actions as Prisma.InputJsonValue,
|
|
358
|
+
}));
|
|
359
|
+
|
|
360
|
+
this.logger.info(
|
|
361
|
+
'[PageResource] Creating new page resources',
|
|
362
|
+
createSafeLogData({
|
|
363
|
+
operation: 'CREATE_MANY',
|
|
364
|
+
table: 'pageResource',
|
|
365
|
+
pageId: id,
|
|
366
|
+
data: pageResourcesData,
|
|
367
|
+
}),
|
|
368
|
+
);
|
|
369
|
+
const createResult = await tx.pageResource.createMany({
|
|
370
|
+
data: pageResourcesData,
|
|
371
|
+
skipDuplicates: true,
|
|
372
|
+
});
|
|
373
|
+
this.logger.info(
|
|
374
|
+
'[PageResource] New page resources created',
|
|
375
|
+
createSafeLogData({
|
|
376
|
+
operation: 'CREATE_MANY',
|
|
377
|
+
table: 'pageResource',
|
|
378
|
+
pageId: id,
|
|
379
|
+
count: createResult.count,
|
|
380
|
+
}),
|
|
381
|
+
);
|
|
382
|
+
}
|
|
383
|
+
|
|
384
|
+
// Step 3: 只有当资源有变化时,才需要更新 roleResource
|
|
385
|
+
const hasResourceChanges =
|
|
386
|
+
addedResources.length > 0 ||
|
|
387
|
+
removedResourceIds.length > 0 ||
|
|
388
|
+
modifiedResources.length > 0;
|
|
389
|
+
|
|
390
|
+
if (hasResourceChanges) {
|
|
391
|
+
// 3.1 在事务内查询所有关联此 page 的 role(通过 rolePages)
|
|
392
|
+
const affectedRoles = await tx.rolePages.findMany({
|
|
393
|
+
where: { pageId: id },
|
|
394
|
+
select: { roleId: true },
|
|
395
|
+
});
|
|
396
|
+
|
|
397
|
+
const affectedRoleIds = affectedRoles.map((r) => r.roleId);
|
|
398
|
+
|
|
399
|
+
if (affectedRoleIds.length === 0) {
|
|
400
|
+
// 没有受影响的角色,直接返回更新后的页面
|
|
401
|
+
return page;
|
|
402
|
+
}
|
|
403
|
+
|
|
404
|
+
// 3.2 获取受影响的 resourceIds
|
|
405
|
+
const affectedResourceIds = [
|
|
406
|
+
...addedResources.map((r) => r.resourceId),
|
|
407
|
+
...removedResourceIds,
|
|
408
|
+
...modifiedResources.map((r) => r.resourceId),
|
|
409
|
+
];
|
|
410
|
+
|
|
411
|
+
// 3.3 在事务内一次性查询所有受影响角色的 roleResource(只查受影响的资源)
|
|
412
|
+
const existingRoleResources = await tx.roleResource.findMany({
|
|
413
|
+
where: {
|
|
414
|
+
roleId: { in: affectedRoleIds },
|
|
415
|
+
resourceId: { in: affectedResourceIds },
|
|
416
|
+
},
|
|
417
|
+
select: { roleId: true, resourceId: true, actions: true },
|
|
418
|
+
});
|
|
419
|
+
|
|
420
|
+
// 构建 roleResource 映射: `${roleId}-${resourceId}` -> actions[]
|
|
421
|
+
const roleResourceMap = new Map<string, string[]>();
|
|
422
|
+
for (const rr of existingRoleResources) {
|
|
423
|
+
const key = `${rr.roleId}-${rr.resourceId}`;
|
|
424
|
+
roleResourceMap.set(key, this.parseActions(rr.actions));
|
|
425
|
+
}
|
|
426
|
+
|
|
427
|
+
// 3.4 查询其他页面的资源信息(用于删除和修改资源时的判断)
|
|
428
|
+
// otherPagesResourceSet: 用于判断删除时其他页面是否还有该资源
|
|
429
|
+
// otherPagesActionsMap: 用于修改时获取其他页面对该资源的 actions 并集
|
|
430
|
+
let otherPagesResourceSet = new Set<string>(); // `${roleId}-${resourceId}`
|
|
431
|
+
let otherPagesActionsMap = new Map<string, string[]>(); // `${roleId}-${resourceId}` -> actions 并集
|
|
432
|
+
|
|
433
|
+
// 需要查询其他页面的资源:被删除的 + 被修改的
|
|
434
|
+
const needCheckResourceIds = [
|
|
435
|
+
...removedResourceIds,
|
|
436
|
+
...modifiedResources.map((r) => r.resourceId),
|
|
437
|
+
];
|
|
438
|
+
|
|
439
|
+
if (needCheckResourceIds.length > 0) {
|
|
440
|
+
// 在事务内查询每个角色的其他页面
|
|
441
|
+
const roleOtherPages = await tx.rolePages.findMany({
|
|
442
|
+
where: {
|
|
443
|
+
roleId: { in: affectedRoleIds },
|
|
444
|
+
pageId: { not: id },
|
|
445
|
+
},
|
|
446
|
+
select: { roleId: true, pageId: true },
|
|
447
|
+
});
|
|
448
|
+
|
|
449
|
+
// 按角色分组其他页面 ID
|
|
450
|
+
const roleToOtherPageIds = new Map<number, number[]>();
|
|
451
|
+
for (const rp of roleOtherPages) {
|
|
452
|
+
const pageIds = roleToOtherPageIds.get(rp.roleId) || [];
|
|
453
|
+
pageIds.push(rp.pageId);
|
|
454
|
+
roleToOtherPageIds.set(rp.roleId, pageIds);
|
|
455
|
+
}
|
|
456
|
+
|
|
457
|
+
// 在事务内查询其他页面中相关资源的详细信息(包括 actions)
|
|
458
|
+
const allOtherPageIds = roleOtherPages.map((rp) => rp.pageId);
|
|
459
|
+
if (allOtherPageIds.length > 0) {
|
|
460
|
+
const otherPagesResources = await tx.pageResource.findMany({
|
|
461
|
+
where: {
|
|
462
|
+
pageId: { in: allOtherPageIds },
|
|
463
|
+
resourceId: { in: needCheckResourceIds },
|
|
464
|
+
},
|
|
465
|
+
select: { pageId: true, resourceId: true, actions: true },
|
|
466
|
+
});
|
|
467
|
+
|
|
468
|
+
// 构建 pageId -> { resourceId -> actions } 映射
|
|
469
|
+
const pageResourceActionsMap = new Map<
|
|
470
|
+
number,
|
|
471
|
+
Map<number, string[]>
|
|
472
|
+
>();
|
|
473
|
+
for (const pr of otherPagesResources) {
|
|
474
|
+
let resourceMap = pageResourceActionsMap.get(pr.pageId);
|
|
475
|
+
if (!resourceMap) {
|
|
476
|
+
resourceMap = new Map<number, string[]>();
|
|
477
|
+
pageResourceActionsMap.set(pr.pageId, resourceMap);
|
|
478
|
+
}
|
|
479
|
+
resourceMap.set(pr.resourceId, this.parseActions(pr.actions));
|
|
480
|
+
}
|
|
481
|
+
|
|
482
|
+
// 对每个角色,构建其其他页面的资源信息
|
|
483
|
+
for (const [roleId, pageIds] of roleToOtherPageIds) {
|
|
484
|
+
for (const pageId of pageIds) {
|
|
485
|
+
const resourceMap = pageResourceActionsMap.get(pageId);
|
|
486
|
+
if (resourceMap) {
|
|
487
|
+
for (const [resourceId, actions] of resourceMap) {
|
|
488
|
+
const key = `${roleId}-${resourceId}`;
|
|
489
|
+
|
|
490
|
+
// 标记该角色的其他页面有这个资源(用于删除判断)
|
|
491
|
+
otherPagesResourceSet.add(key);
|
|
492
|
+
|
|
493
|
+
// 合并其他页面对该资源的 actions(用于修改时取并集)
|
|
494
|
+
const existingActions =
|
|
495
|
+
otherPagesActionsMap.get(key) || [];
|
|
496
|
+
const mergedActions = new Set([
|
|
497
|
+
...existingActions,
|
|
498
|
+
...actions,
|
|
499
|
+
]);
|
|
500
|
+
otherPagesActionsMap.set(key, Array.from(mergedActions));
|
|
501
|
+
}
|
|
502
|
+
}
|
|
503
|
+
}
|
|
504
|
+
}
|
|
505
|
+
}
|
|
506
|
+
}
|
|
507
|
+
|
|
508
|
+
// Step 4: 对每个受影响的角色,在事务内更新 roleResource
|
|
509
|
+
for (const roleId of affectedRoleIds) {
|
|
510
|
+
// 4.1 处理删除的资源
|
|
511
|
+
for (const resourceId of removedResourceIds) {
|
|
512
|
+
const key = `${roleId}-${resourceId}`;
|
|
513
|
+
if (otherPagesResourceSet.has(key)) {
|
|
514
|
+
// 其他页面还有这个资源,跳过(roleResource 保持不变)
|
|
515
|
+
continue;
|
|
516
|
+
} else {
|
|
517
|
+
// 其他页面没有这个资源,删除 roleResource
|
|
518
|
+
const oldRoleResource = await tx.roleResource.findFirst({
|
|
519
|
+
where: { roleId, resourceId },
|
|
520
|
+
});
|
|
521
|
+
this.logger.info(
|
|
522
|
+
'[RoleResource] Deleting role resource (no other pages have this resource)',
|
|
523
|
+
createSafeLogData({
|
|
524
|
+
operation: 'DELETE_MANY',
|
|
525
|
+
table: 'roleResource',
|
|
526
|
+
roleId: roleId,
|
|
527
|
+
resourceId: resourceId,
|
|
528
|
+
oldData: oldRoleResource,
|
|
529
|
+
}),
|
|
530
|
+
);
|
|
531
|
+
const deleteResult = await tx.roleResource.deleteMany({
|
|
532
|
+
where: { roleId, resourceId },
|
|
533
|
+
});
|
|
534
|
+
this.logger.info(
|
|
535
|
+
'[RoleResource] Role resource deleted',
|
|
536
|
+
createSafeLogData({
|
|
537
|
+
operation: 'DELETE_MANY',
|
|
538
|
+
table: 'roleResource',
|
|
539
|
+
roleId: roleId,
|
|
540
|
+
resourceId: resourceId,
|
|
541
|
+
count: deleteResult.count,
|
|
542
|
+
}),
|
|
543
|
+
);
|
|
544
|
+
}
|
|
545
|
+
}
|
|
546
|
+
|
|
547
|
+
// 4.2 处理新增的资源
|
|
548
|
+
for (const { resourceId, actions } of addedResources) {
|
|
549
|
+
const key = `${roleId}-${resourceId}`;
|
|
550
|
+
const existingActions = roleResourceMap.get(key) || [];
|
|
551
|
+
|
|
552
|
+
// 合并当前页面的 actions 与已有的 roleResource actions(取并集)
|
|
553
|
+
const mergedActions = new Set<string>([
|
|
554
|
+
...actions,
|
|
555
|
+
...existingActions,
|
|
556
|
+
]);
|
|
557
|
+
|
|
558
|
+
this.logger.info(
|
|
559
|
+
'[RoleResource] Upserting role resource (added resource)',
|
|
560
|
+
createSafeLogData({
|
|
561
|
+
operation: 'UPSERT',
|
|
562
|
+
table: 'roleResource',
|
|
563
|
+
roleId: roleId,
|
|
564
|
+
resourceId: resourceId,
|
|
565
|
+
existingActions: existingActions,
|
|
566
|
+
newActions: actions,
|
|
567
|
+
mergedActions: Array.from(mergedActions),
|
|
568
|
+
}),
|
|
569
|
+
);
|
|
570
|
+
const upsertResult = await tx.roleResource.upsert({
|
|
571
|
+
where: { roleId_resourceId: { roleId, resourceId } },
|
|
572
|
+
update: {
|
|
573
|
+
actions: Array.from(mergedActions) as Prisma.InputJsonValue,
|
|
574
|
+
},
|
|
575
|
+
create: {
|
|
576
|
+
roleId,
|
|
577
|
+
resourceId,
|
|
578
|
+
actions: Array.from(mergedActions) as Prisma.InputJsonValue,
|
|
579
|
+
},
|
|
580
|
+
});
|
|
581
|
+
this.logger.info(
|
|
582
|
+
'[RoleResource] Role resource upserted',
|
|
583
|
+
createSafeLogData({
|
|
584
|
+
operation: 'UPSERT',
|
|
585
|
+
table: 'roleResource',
|
|
586
|
+
result: upsertResult,
|
|
587
|
+
}),
|
|
588
|
+
);
|
|
589
|
+
}
|
|
590
|
+
|
|
591
|
+
// 4.3 处理修改的资源
|
|
592
|
+
// 注意:修改资源时,需要用当前页面的新 actions 与【其他页面】的 actions 取并集
|
|
593
|
+
// 而不是与 roleResource 已有的 actions 取并集(因为那会包含当前页面的旧 actions)
|
|
594
|
+
for (const { resourceId, newActions } of modifiedResources) {
|
|
595
|
+
const key = `${roleId}-${resourceId}`;
|
|
596
|
+
// 获取其他页面对该资源的 actions 并集
|
|
597
|
+
const otherPagesActions = otherPagesActionsMap.get(key) || [];
|
|
598
|
+
|
|
599
|
+
// 合并当前页面的新 actions 与其他页面的 actions(取并集)
|
|
600
|
+
const mergedActions = new Set<string>([
|
|
601
|
+
...newActions,
|
|
602
|
+
...otherPagesActions,
|
|
603
|
+
]);
|
|
604
|
+
|
|
605
|
+
this.logger.info(
|
|
606
|
+
'[RoleResource] Upserting role resource (modified resource)',
|
|
607
|
+
createSafeLogData({
|
|
608
|
+
operation: 'UPSERT',
|
|
609
|
+
table: 'roleResource',
|
|
610
|
+
roleId: roleId,
|
|
611
|
+
resourceId: resourceId,
|
|
612
|
+
newActions: newActions,
|
|
613
|
+
otherPagesActions: otherPagesActions,
|
|
614
|
+
mergedActions: Array.from(mergedActions),
|
|
615
|
+
}),
|
|
616
|
+
);
|
|
617
|
+
const upsertResult = await tx.roleResource.upsert({
|
|
618
|
+
where: { roleId_resourceId: { roleId, resourceId } },
|
|
619
|
+
update: {
|
|
620
|
+
actions: Array.from(mergedActions) as Prisma.InputJsonValue,
|
|
621
|
+
},
|
|
622
|
+
create: {
|
|
623
|
+
roleId,
|
|
624
|
+
resourceId,
|
|
625
|
+
actions: Array.from(mergedActions) as Prisma.InputJsonValue,
|
|
626
|
+
},
|
|
627
|
+
});
|
|
628
|
+
this.logger.info(
|
|
629
|
+
'[RoleResource] Role resource upserted',
|
|
630
|
+
createSafeLogData({
|
|
631
|
+
operation: 'UPSERT',
|
|
632
|
+
table: 'roleResource',
|
|
633
|
+
result: upsertResult,
|
|
634
|
+
}),
|
|
635
|
+
);
|
|
636
|
+
}
|
|
637
|
+
}
|
|
638
|
+
}
|
|
639
|
+
}
|
|
640
|
+
// Step 5: 返回更新后的页面
|
|
641
|
+
this.logger.info(
|
|
642
|
+
'[Page] Page with resources updated successfully',
|
|
643
|
+
createSafeLogData({
|
|
644
|
+
operation: 'UPDATE_WITH_RESOURCES',
|
|
645
|
+
table: 'page',
|
|
646
|
+
id: id,
|
|
647
|
+
finalResult: page,
|
|
648
|
+
}),
|
|
649
|
+
);
|
|
650
|
+
return page;
|
|
651
|
+
});
|
|
652
|
+
}
|
|
653
|
+
|
|
654
|
+
/**
|
|
655
|
+
* 在事务中删除页面及其相关关系,并同步更新roleResource
|
|
656
|
+
*
|
|
657
|
+
* 删除逻辑说明:
|
|
658
|
+
* 1. 删除pageResource中的页面和资源关系
|
|
659
|
+
* 2. 检查哪些role拥有这个被删除的页面(通过rolePages)
|
|
660
|
+
* 3. 检查页面拥有的资源是否在其他页面也存在
|
|
661
|
+
* 4. 更新roleResource中的actions(降级处理)
|
|
662
|
+
* 5. 删除rolePages关系
|
|
663
|
+
* 6. 删除page本身
|
|
664
|
+
*
|
|
665
|
+
* @param id 要删除的页面ID
|
|
666
|
+
*/
|
|
667
|
+
async deletePageWithResources(id: number) {
|
|
668
|
+
return await this.prisma.$transaction(async (tx) => {
|
|
669
|
+
// Step 1: 查询要删除的页面及其相关数据
|
|
670
|
+
const pageToDelete = await tx.page.findUnique({
|
|
671
|
+
where: { id },
|
|
672
|
+
include: {
|
|
673
|
+
pageResources: {
|
|
674
|
+
include: {
|
|
675
|
+
resource: true,
|
|
676
|
+
},
|
|
677
|
+
},
|
|
678
|
+
rolePages: {
|
|
679
|
+
include: {
|
|
680
|
+
role: true,
|
|
681
|
+
},
|
|
682
|
+
},
|
|
683
|
+
},
|
|
684
|
+
});
|
|
685
|
+
|
|
686
|
+
if (!pageToDelete) {
|
|
687
|
+
throw new Error(`Page with id ${id} not found`);
|
|
688
|
+
}
|
|
689
|
+
|
|
690
|
+
this.logger.info(
|
|
691
|
+
'[Page] Starting to delete page with resources',
|
|
692
|
+
createSafeLogData({
|
|
693
|
+
operation: 'DELETE_WITH_RESOURCES',
|
|
694
|
+
table: 'page',
|
|
695
|
+
id: id,
|
|
696
|
+
pageData: pageToDelete,
|
|
697
|
+
}),
|
|
698
|
+
);
|
|
699
|
+
|
|
700
|
+
// Step 2: 获取页面拥有的资源列表
|
|
701
|
+
const pageResourceIds = pageToDelete.pageResources.map(
|
|
702
|
+
(pr) => pr.resourceId,
|
|
703
|
+
);
|
|
704
|
+
const affectedRoleIds = pageToDelete.rolePages.map((rp) => rp.roleId);
|
|
705
|
+
|
|
706
|
+
// Step 3: 查询其他页面中相关资源的信息
|
|
707
|
+
let otherPagesResourceInfo = new Map<
|
|
708
|
+
string,
|
|
709
|
+
{ hasResource: boolean; actions: string[] }
|
|
710
|
+
>();
|
|
711
|
+
|
|
712
|
+
if (pageResourceIds.length > 0 && affectedRoleIds.length > 0) {
|
|
713
|
+
// 3.1 先查询资源信息,过滤掉通用资源
|
|
714
|
+
const resourcesInfo = await tx.resource.findMany({
|
|
715
|
+
where: { id: { in: pageResourceIds } },
|
|
716
|
+
select: { id: true, isCommonResource: true },
|
|
717
|
+
});
|
|
718
|
+
|
|
719
|
+
// 过滤掉通用资源,只处理非通用资源
|
|
720
|
+
const nonCommonResourceIds = resourcesInfo
|
|
721
|
+
.filter((resource) => !resource.isCommonResource)
|
|
722
|
+
.map((resource) => resource.id);
|
|
723
|
+
|
|
724
|
+
// 如果没有非通用资源,跳过后续查询
|
|
725
|
+
if (nonCommonResourceIds.length === 0) {
|
|
726
|
+
// 只有通用资源,不需要查询其他页面信息
|
|
727
|
+
otherPagesResourceInfo = new Map();
|
|
728
|
+
} else {
|
|
729
|
+
// 查询每个角色的其他页面
|
|
730
|
+
const roleOtherPages = await tx.rolePages.findMany({
|
|
731
|
+
where: {
|
|
732
|
+
roleId: { in: affectedRoleIds },
|
|
733
|
+
pageId: { not: id },
|
|
734
|
+
},
|
|
735
|
+
select: { roleId: true, pageId: true },
|
|
736
|
+
});
|
|
737
|
+
|
|
738
|
+
// 按角色分组其他页面ID
|
|
739
|
+
const roleToOtherPageIds = new Map<number, number[]>();
|
|
740
|
+
for (const rp of roleOtherPages) {
|
|
741
|
+
const pageIds = roleToOtherPageIds.get(rp.roleId) || [];
|
|
742
|
+
pageIds.push(rp.pageId);
|
|
743
|
+
roleToOtherPageIds.set(rp.roleId, pageIds);
|
|
744
|
+
}
|
|
745
|
+
|
|
746
|
+
// 查询其他页面中相关资源的详细信息
|
|
747
|
+
const allOtherPageIds = roleOtherPages.map((rp) => rp.pageId);
|
|
748
|
+
if (allOtherPageIds.length > 0) {
|
|
749
|
+
const otherPagesResources = await tx.pageResource.findMany({
|
|
750
|
+
where: {
|
|
751
|
+
pageId: { in: allOtherPageIds },
|
|
752
|
+
resourceId: { in: pageResourceIds },
|
|
753
|
+
},
|
|
754
|
+
select: { pageId: true, resourceId: true, actions: true },
|
|
755
|
+
});
|
|
756
|
+
|
|
757
|
+
// 构建页面资源映射
|
|
758
|
+
const pageResourceActionsMap = new Map<
|
|
759
|
+
number,
|
|
760
|
+
Map<number, string[]>
|
|
761
|
+
>();
|
|
762
|
+
for (const pr of otherPagesResources) {
|
|
763
|
+
let resourceMap = pageResourceActionsMap.get(pr.pageId);
|
|
764
|
+
if (!resourceMap) {
|
|
765
|
+
resourceMap = new Map<number, string[]>();
|
|
766
|
+
pageResourceActionsMap.set(pr.pageId, resourceMap);
|
|
767
|
+
}
|
|
768
|
+
resourceMap.set(pr.resourceId, this.parseActions(pr.actions));
|
|
769
|
+
}
|
|
770
|
+
|
|
771
|
+
// 对每个角色,构建其其他页面的资源信息
|
|
772
|
+
for (const [roleId, pageIds] of roleToOtherPageIds) {
|
|
773
|
+
for (const pageId of pageIds) {
|
|
774
|
+
const resourceMap = pageResourceActionsMap.get(pageId);
|
|
775
|
+
if (resourceMap) {
|
|
776
|
+
for (const [resourceId, actions] of resourceMap) {
|
|
777
|
+
const key = `${roleId}-${resourceId}`;
|
|
778
|
+
const existingInfo = otherPagesResourceInfo.get(key);
|
|
779
|
+
|
|
780
|
+
if (existingInfo) {
|
|
781
|
+
// 合并actions(取并集)
|
|
782
|
+
const mergedActions = new Set([
|
|
783
|
+
...existingInfo.actions,
|
|
784
|
+
...actions,
|
|
785
|
+
]);
|
|
786
|
+
otherPagesResourceInfo.set(key, {
|
|
787
|
+
hasResource: true,
|
|
788
|
+
actions: Array.from(mergedActions),
|
|
789
|
+
});
|
|
790
|
+
} else {
|
|
791
|
+
otherPagesResourceInfo.set(key, {
|
|
792
|
+
hasResource: true,
|
|
793
|
+
actions: actions,
|
|
794
|
+
});
|
|
795
|
+
}
|
|
796
|
+
}
|
|
797
|
+
}
|
|
798
|
+
}
|
|
799
|
+
}
|
|
800
|
+
}
|
|
801
|
+
}
|
|
802
|
+
}
|
|
803
|
+
|
|
804
|
+
// Step 4: 删除pageResource关系
|
|
805
|
+
if (pageToDelete.pageResources.length > 0) {
|
|
806
|
+
this.logger.info(
|
|
807
|
+
'[PageResource] Deleting page resources',
|
|
808
|
+
createSafeLogData({
|
|
809
|
+
operation: 'DELETE_MANY',
|
|
810
|
+
table: 'pageResource',
|
|
811
|
+
pageId: id,
|
|
812
|
+
count: pageToDelete.pageResources.length,
|
|
813
|
+
}),
|
|
814
|
+
);
|
|
815
|
+
await tx.pageResource.deleteMany({
|
|
816
|
+
where: { pageId: id },
|
|
817
|
+
});
|
|
818
|
+
this.logger.info(
|
|
819
|
+
'[PageResource] Page resources deleted',
|
|
820
|
+
createSafeLogData({
|
|
821
|
+
operation: 'DELETE_MANY',
|
|
822
|
+
table: 'pageResource',
|
|
823
|
+
pageId: id,
|
|
824
|
+
}),
|
|
825
|
+
);
|
|
826
|
+
}
|
|
827
|
+
|
|
828
|
+
// Step 5: 更新roleResource(降级处理)
|
|
829
|
+
if (affectedRoleIds.length > 0 && pageResourceIds.length > 0) {
|
|
830
|
+
// 5.1 先查询资源信息,过滤掉通用资源
|
|
831
|
+
const resourcesInfo = await tx.resource.findMany({
|
|
832
|
+
where: { id: { in: pageResourceIds } },
|
|
833
|
+
select: { id: true, isCommonResource: true },
|
|
834
|
+
});
|
|
835
|
+
|
|
836
|
+
// 过滤掉通用资源,只处理非通用资源
|
|
837
|
+
const nonCommonResourceIds = resourcesInfo
|
|
838
|
+
.filter((resource) => !resource.isCommonResource)
|
|
839
|
+
.map((resource) => resource.id);
|
|
840
|
+
|
|
841
|
+
if (nonCommonResourceIds.length > 0) {
|
|
842
|
+
// 查询现有的roleResource关系(只查询非通用资源)
|
|
843
|
+
const existingRoleResources = await tx.roleResource.findMany({
|
|
844
|
+
where: {
|
|
845
|
+
roleId: { in: affectedRoleIds },
|
|
846
|
+
resourceId: { in: nonCommonResourceIds },
|
|
847
|
+
},
|
|
848
|
+
select: { roleId: true, resourceId: true, actions: true },
|
|
849
|
+
});
|
|
850
|
+
|
|
851
|
+
for (const roleResource of existingRoleResources) {
|
|
852
|
+
const key = `${roleResource.roleId}-${roleResource.resourceId}`;
|
|
853
|
+
const otherPagesInfo = otherPagesResourceInfo.get(key);
|
|
854
|
+
|
|
855
|
+
if (otherPagesInfo && otherPagesInfo.hasResource) {
|
|
856
|
+
// 其他页面还有这个资源,更新actions为其他页面的actions并集
|
|
857
|
+
this.logger.info(
|
|
858
|
+
'[RoleResource] Updating role resource actions (other pages have this resource)',
|
|
859
|
+
createSafeLogData({
|
|
860
|
+
operation: 'UPDATE',
|
|
861
|
+
table: 'roleResource',
|
|
862
|
+
roleId: roleResource.roleId,
|
|
863
|
+
resourceId: roleResource.resourceId,
|
|
864
|
+
oldActions: this.parseActions(roleResource.actions),
|
|
865
|
+
newActions: otherPagesInfo.actions,
|
|
866
|
+
}),
|
|
867
|
+
);
|
|
868
|
+
await tx.roleResource.update({
|
|
869
|
+
where: {
|
|
870
|
+
roleId_resourceId: {
|
|
871
|
+
roleId: roleResource.roleId,
|
|
872
|
+
resourceId: roleResource.resourceId,
|
|
873
|
+
},
|
|
874
|
+
},
|
|
875
|
+
data: {
|
|
876
|
+
actions: otherPagesInfo.actions as Prisma.InputJsonValue,
|
|
877
|
+
},
|
|
878
|
+
});
|
|
879
|
+
} else {
|
|
880
|
+
// 其他页面没有这个资源,删除roleResource关系
|
|
881
|
+
this.logger.info(
|
|
882
|
+
'[RoleResource] Deleting role resource (no other pages have this resource)',
|
|
883
|
+
createSafeLogData({
|
|
884
|
+
operation: 'DELETE',
|
|
885
|
+
table: 'roleResource',
|
|
886
|
+
roleId: roleResource.roleId,
|
|
887
|
+
resourceId: roleResource.resourceId,
|
|
888
|
+
oldActions: this.parseActions(roleResource.actions),
|
|
889
|
+
}),
|
|
890
|
+
);
|
|
891
|
+
await tx.roleResource.delete({
|
|
892
|
+
where: {
|
|
893
|
+
roleId_resourceId: {
|
|
894
|
+
roleId: roleResource.roleId,
|
|
895
|
+
resourceId: roleResource.resourceId,
|
|
896
|
+
},
|
|
897
|
+
},
|
|
898
|
+
});
|
|
899
|
+
}
|
|
900
|
+
}
|
|
901
|
+
}
|
|
902
|
+
// 通用资源保持不变,不需要处理
|
|
903
|
+
}
|
|
904
|
+
|
|
905
|
+
// Step 6: 删除rolePages关系
|
|
906
|
+
if (pageToDelete.rolePages.length > 0) {
|
|
907
|
+
this.logger.info(
|
|
908
|
+
'[RolePages] Deleting role pages',
|
|
909
|
+
createSafeLogData({
|
|
910
|
+
operation: 'DELETE_MANY',
|
|
911
|
+
table: 'rolePages',
|
|
912
|
+
pageId: id,
|
|
913
|
+
count: pageToDelete.rolePages.length,
|
|
914
|
+
}),
|
|
915
|
+
);
|
|
916
|
+
await tx.rolePages.deleteMany({
|
|
917
|
+
where: { pageId: id },
|
|
918
|
+
});
|
|
919
|
+
this.logger.info(
|
|
920
|
+
'[RolePages] Role pages deleted',
|
|
921
|
+
createSafeLogData({
|
|
922
|
+
operation: 'DELETE_MANY',
|
|
923
|
+
table: 'rolePages',
|
|
924
|
+
pageId: id,
|
|
925
|
+
}),
|
|
926
|
+
);
|
|
927
|
+
}
|
|
928
|
+
|
|
929
|
+
// Step 7: 删除页面本身
|
|
930
|
+
this.logger.info(
|
|
931
|
+
'[Page] Deleting page',
|
|
932
|
+
createSafeLogData({
|
|
933
|
+
operation: 'DELETE',
|
|
934
|
+
table: 'page',
|
|
935
|
+
id: id,
|
|
936
|
+
oldData: pageToDelete,
|
|
937
|
+
}),
|
|
938
|
+
);
|
|
939
|
+
await tx.page.delete({
|
|
940
|
+
where: { id },
|
|
941
|
+
});
|
|
942
|
+
this.logger.info(
|
|
943
|
+
'[Page] Page deleted successfully',
|
|
944
|
+
createSafeLogData({
|
|
945
|
+
operation: 'DELETE',
|
|
946
|
+
table: 'page',
|
|
947
|
+
id: id,
|
|
948
|
+
}),
|
|
949
|
+
);
|
|
950
|
+
|
|
951
|
+
return { count: 1 };
|
|
952
|
+
});
|
|
953
|
+
}
|
|
954
|
+
|
|
955
|
+
/**
|
|
956
|
+
* 解析 actions 字段(支持多种格式)
|
|
957
|
+
*/
|
|
958
|
+
private parseActions(actions: any): string[] {
|
|
959
|
+
if (!actions) return [];
|
|
960
|
+
|
|
961
|
+
// 如果已经是数组,直接返回
|
|
962
|
+
if (Array.isArray(actions)) {
|
|
963
|
+
return actions.map(String).filter(Boolean);
|
|
964
|
+
}
|
|
965
|
+
|
|
966
|
+
// 如果是字符串,尝试解析为 JSON
|
|
967
|
+
if (typeof actions === 'string') {
|
|
968
|
+
try {
|
|
969
|
+
const parsed = JSON.parse(actions);
|
|
970
|
+
if (Array.isArray(parsed)) {
|
|
971
|
+
return parsed.map(String).filter(Boolean);
|
|
972
|
+
}
|
|
973
|
+
// 如果不是数组,按逗号分隔
|
|
974
|
+
return actions
|
|
975
|
+
.split(',')
|
|
976
|
+
.map((s) => s.trim())
|
|
977
|
+
.filter(Boolean);
|
|
978
|
+
} catch {
|
|
979
|
+
// JSON 解析失败,按逗号分隔
|
|
980
|
+
return actions
|
|
981
|
+
.split(',')
|
|
982
|
+
.map((s) => s.trim())
|
|
983
|
+
.filter(Boolean);
|
|
984
|
+
}
|
|
985
|
+
}
|
|
986
|
+
|
|
987
|
+
return [];
|
|
988
|
+
}
|
|
989
|
+
|
|
990
|
+
async deleteMany(pageDeleteManyArgs: Prisma.PageDeleteManyArgs) {
|
|
991
|
+
const oldData = await this.prisma.page.findMany({
|
|
992
|
+
where: pageDeleteManyArgs.where,
|
|
993
|
+
});
|
|
994
|
+
this.logger.info(
|
|
995
|
+
'[Page] Deleting multiple pages',
|
|
996
|
+
createSafeLogData({
|
|
997
|
+
operation: 'DELETE_MANY',
|
|
998
|
+
table: 'page',
|
|
999
|
+
where: pageDeleteManyArgs.where,
|
|
1000
|
+
oldData: oldData,
|
|
1001
|
+
}),
|
|
1002
|
+
);
|
|
1003
|
+
const result = await this.prisma.page.deleteMany(pageDeleteManyArgs);
|
|
1004
|
+
this.logger.info(
|
|
1005
|
+
'[Page] Multiple pages deleted successfully',
|
|
1006
|
+
createSafeLogData({
|
|
1007
|
+
operation: 'DELETE_MANY',
|
|
1008
|
+
table: 'page',
|
|
1009
|
+
count: result.count,
|
|
1010
|
+
}),
|
|
1011
|
+
);
|
|
1012
|
+
return result;
|
|
1013
|
+
}
|
|
1014
|
+
|
|
1015
|
+
async deleteUnique(id: number) {
|
|
1016
|
+
const oldData = await this.prisma.page.findUnique({ where: { id } });
|
|
1017
|
+
this.logger.info(
|
|
1018
|
+
'[Page] Deleting page',
|
|
1019
|
+
createSafeLogData({
|
|
1020
|
+
operation: 'DELETE',
|
|
1021
|
+
table: 'page',
|
|
1022
|
+
id: id,
|
|
1023
|
+
oldData: oldData,
|
|
1024
|
+
}),
|
|
1025
|
+
);
|
|
1026
|
+
await this.prisma.page.delete({
|
|
1027
|
+
where: { id: id },
|
|
1028
|
+
});
|
|
1029
|
+
this.logger.info(
|
|
1030
|
+
'[Page] Page deleted successfully',
|
|
1031
|
+
createSafeLogData({
|
|
1032
|
+
operation: 'DELETE',
|
|
1033
|
+
table: 'page',
|
|
1034
|
+
id: id,
|
|
1035
|
+
}),
|
|
1036
|
+
);
|
|
1037
|
+
return { count: 1 };
|
|
1038
|
+
}
|
|
1039
|
+
|
|
1040
|
+
async count(pageCountArgs?: Prisma.PageCountArgs) {
|
|
1041
|
+
return await this.prisma.page.count(pageCountArgs);
|
|
1042
|
+
}
|
|
1043
|
+
|
|
1044
|
+
async groupBy(pageGroupByArgs: Prisma.PageGroupByArgs) {
|
|
1045
|
+
return await this.prisma.page.groupBy(pageGroupByArgs as any);
|
|
1046
|
+
}
|
|
1047
|
+
|
|
1048
|
+
async aggregate(pageAggregateArgs: Prisma.PageAggregateArgs) {
|
|
1049
|
+
return await this.prisma.page.aggregate(pageAggregateArgs);
|
|
1050
|
+
}
|
|
1051
|
+
}
|