zhengyiming
2025-02-10 e5a465d9d2102774cf54912102b1c5d0114bf2d5
feat: init bmini
204个文件已添加
2个文件已修改
26799 ■■■■■ 已修改文件
apps/bMiniApp/.eslintrc 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
apps/bMiniApp/.eslintrc-auto-import.json 91 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
apps/bMiniApp/CHANGELOG.md 62 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
apps/bMiniApp/README.md 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
apps/bMiniApp/auto-imports.d.ts 90 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
apps/bMiniApp/babel.config.js 32 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
apps/bMiniApp/ci/private.wx88251c84f5cd886b.key 27 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
apps/bMiniApp/ci/upload.js 41 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
apps/bMiniApp/config/dev.js 23 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
apps/bMiniApp/config/index.js 231 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
apps/bMiniApp/config/prod.js 41 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
apps/bMiniApp/config/staging.js 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
apps/bMiniApp/mock/Purchase.mock.js 106 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
apps/bMiniApp/mock/index.js 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
apps/bMiniApp/package.json 137 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
apps/bMiniApp/pnpm-lock.yaml 15613 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
apps/bMiniApp/project.config.json 55 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
apps/bMiniApp/project.private.config.json 15 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
apps/bMiniApp/project.tt.json 9 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
apps/bMiniApp/src/app.config.ts 72 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
apps/bMiniApp/src/app.scss 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
apps/bMiniApp/src/app.ts 85 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
apps/bMiniApp/src/assets/authentication/icon-arrow.png 补丁 | 查看 | 原始文档 | blame | 历史
apps/bMiniApp/src/assets/authentication/icon-faren.png 补丁 | 查看 | 原始文档 | blame | 历史
apps/bMiniApp/src/assets/authentication/icon-jbr.png 补丁 | 查看 | 原始文档 | blame | 历史
apps/bMiniApp/src/assets/authentication/icon-result-error.png 补丁 | 查看 | 原始文档 | blame | 历史
apps/bMiniApp/src/assets/authentication/icon-result-success.png 补丁 | 查看 | 原始文档 | blame | 历史
apps/bMiniApp/src/assets/common/icon-common-page-bg.png 补丁 | 查看 | 原始文档 | blame | 历史
apps/bMiniApp/src/assets/common/icon-navi-arrow-white.png 补丁 | 查看 | 原始文档 | blame | 历史
apps/bMiniApp/src/assets/common/icon-navi-arrow.png 补丁 | 查看 | 原始文档 | blame | 历史
apps/bMiniApp/src/assets/components/fail.png 补丁 | 查看 | 原始文档 | blame | 历史
apps/bMiniApp/src/assets/components/icon-add.png 补丁 | 查看 | 原始文档 | blame | 历史
apps/bMiniApp/src/assets/components/icon-back-top.png 补丁 | 查看 | 原始文档 | blame | 历史
apps/bMiniApp/src/assets/components/icon-dark-arrow.png 补丁 | 查看 | 原始文档 | blame | 历史
apps/bMiniApp/src/assets/components/icon-default-avatar.png 补丁 | 查看 | 原始文档 | blame | 历史
apps/bMiniApp/src/assets/components/icon-phone.png 补丁 | 查看 | 原始文档 | blame | 历史
apps/bMiniApp/src/assets/components/icon-small-dark-arrow.png 补丁 | 查看 | 原始文档 | blame | 历史
apps/bMiniApp/src/assets/components/rich-card/icon-add-editor.png 补丁 | 查看 | 原始文档 | blame | 历史
apps/bMiniApp/src/assets/components/rich-card/icon-add.png 补丁 | 查看 | 原始文档 | blame | 历史
apps/bMiniApp/src/assets/components/rich-card/icon-delete.png 补丁 | 查看 | 原始文档 | blame | 历史
apps/bMiniApp/src/assets/components/rich-card/icon-move-down-active.png 补丁 | 查看 | 原始文档 | blame | 历史
apps/bMiniApp/src/assets/components/rich-card/icon-move-down.png 补丁 | 查看 | 原始文档 | blame | 历史
apps/bMiniApp/src/assets/components/rich-card/icon-move-up-active.png 补丁 | 查看 | 原始文档 | blame | 历史
apps/bMiniApp/src/assets/components/rich-card/icon-move-up.png 补丁 | 查看 | 原始文档 | blame | 历史
apps/bMiniApp/src/assets/components/success.png 补丁 | 查看 | 原始文档 | blame | 历史
apps/bMiniApp/src/assets/font/D-DIN.otf 补丁 | 查看 | 原始文档 | blame | 历史
apps/bMiniApp/src/assets/login/icon-btn-captcha.png 补丁 | 查看 | 原始文档 | blame | 历史
apps/bMiniApp/src/assets/login/icon-btn-password.png 补丁 | 查看 | 原始文档 | blame | 历史
apps/bMiniApp/src/assets/login/icon-tab-bg-1.png 补丁 | 查看 | 原始文档 | blame | 历史
apps/bMiniApp/src/assets/login/icon-tab-bg-2.png 补丁 | 查看 | 原始文档 | blame | 历史
apps/bMiniApp/src/assets/mine/icon-arrow.png 补丁 | 查看 | 原始文档 | blame | 历史
apps/bMiniApp/src/assets/mine/icon-bg.png 补丁 | 查看 | 原始文档 | blame | 历史
apps/bMiniApp/src/assets/mine/icon-card.png 补丁 | 查看 | 原始文档 | blame | 历史
apps/bMiniApp/src/assets/mine/icon-edit.png 补丁 | 查看 | 原始文档 | blame | 历史
apps/bMiniApp/src/assets/mine/icon-id-bg.png 补丁 | 查看 | 原始文档 | blame | 历史
apps/bMiniApp/src/assets/mine/icon-lamp.png 补丁 | 查看 | 原始文档 | blame | 历史
apps/bMiniApp/src/assets/mine/icon-menu-business.png 补丁 | 查看 | 原始文档 | blame | 历史
apps/bMiniApp/src/assets/mine/icon-menu-contact.png 补丁 | 查看 | 原始文档 | blame | 历史
apps/bMiniApp/src/assets/mine/icon-message.png 补丁 | 查看 | 原始文档 | blame | 历史
apps/bMiniApp/src/assets/mine/icon-setting.png 补丁 | 查看 | 原始文档 | blame | 历史
apps/bMiniApp/src/assets/mine/icon-unCertified.png 补丁 | 查看 | 原始文档 | blame | 历史
apps/bMiniApp/src/assets/setting/icon-account.png 补丁 | 查看 | 原始文档 | blame | 历史
apps/bMiniApp/src/assets/setting/icon-arrow.png 补丁 | 查看 | 原始文档 | blame | 历史
apps/bMiniApp/src/assets/setting/icon-coo.png 补丁 | 查看 | 原始文档 | blame | 历史
apps/bMiniApp/src/assets/setting/icon-loginout.png 补丁 | 查看 | 原始文档 | blame | 历史
apps/bMiniApp/src/assets/setting/icon-note.png 补丁 | 查看 | 原始文档 | blame | 历史
apps/bMiniApp/src/assets/setting/icon-toggle-bg.png 补丁 | 查看 | 原始文档 | blame | 历史
apps/bMiniApp/src/assets/setting/icon-warning.png 补丁 | 查看 | 原始文档 | blame | 历史
apps/bMiniApp/src/assets/setting/icon-wx.png 补丁 | 查看 | 原始文档 | blame | 历史
apps/bMiniApp/src/assets/tabbar/icon-follow-active.png 补丁 | 查看 | 原始文档 | blame | 历史
apps/bMiniApp/src/assets/tabbar/icon-follow.png 补丁 | 查看 | 原始文档 | blame | 历史
apps/bMiniApp/src/assets/tabbar/icon-friend-active.png 补丁 | 查看 | 原始文档 | blame | 历史
apps/bMiniApp/src/assets/tabbar/icon-friend.png 补丁 | 查看 | 原始文档 | blame | 历史
apps/bMiniApp/src/assets/tabbar/icon-home-active.png 补丁 | 查看 | 原始文档 | blame | 历史
apps/bMiniApp/src/assets/tabbar/icon-home.png 补丁 | 查看 | 原始文档 | blame | 历史
apps/bMiniApp/src/assets/tabbar/icon-information-active.png 补丁 | 查看 | 原始文档 | blame | 历史
apps/bMiniApp/src/assets/tabbar/icon-information.png 补丁 | 查看 | 原始文档 | blame | 历史
apps/bMiniApp/src/assets/tabbar/icon-message-active.png 补丁 | 查看 | 原始文档 | blame | 历史
apps/bMiniApp/src/assets/tabbar/icon-message.png 补丁 | 查看 | 原始文档 | blame | 历史
apps/bMiniApp/src/assets/tabbar/icon-mine-active.png 补丁 | 查看 | 原始文档 | blame | 历史
apps/bMiniApp/src/assets/tabbar/icon-mine.png 补丁 | 查看 | 原始文档 | blame | 历史
apps/bMiniApp/src/assets/tabbar/icon-product-active.png 补丁 | 查看 | 原始文档 | blame | 历史
apps/bMiniApp/src/assets/tabbar/icon-product.png 补丁 | 查看 | 原始文档 | blame | 历史
apps/bMiniApp/src/assets/tabbar/icon-publish.png 补丁 | 查看 | 原始文档 | blame | 历史
apps/bMiniApp/src/assets/user/icon-address.png 补丁 | 查看 | 原始文档 | blame | 历史
apps/bMiniApp/src/assets/user/icon-bg.png 补丁 | 查看 | 原始文档 | blame | 历史
apps/bMiniApp/src/assets/user/icon-email.png 补丁 | 查看 | 原始文档 | blame | 历史
apps/bMiniApp/src/assets/user/icon-my-attention.png 补丁 | 查看 | 原始文档 | blame | 历史
apps/bMiniApp/src/assets/user/icon-phone.png 补丁 | 查看 | 原始文档 | blame | 历史
apps/bMiniApp/src/components/Avatar/UserAvatar.vue 14 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
apps/bMiniApp/src/components/Avatar/UserInfoAvatar.vue 95 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
apps/bMiniApp/src/components/Button/LargeButton.vue 28 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
apps/bMiniApp/src/components/Card/Card.vue 64 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
apps/bMiniApp/src/components/Card/CommonCard.vue 146 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
apps/bMiniApp/src/components/Card/cardProps.ts 20 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
apps/bMiniApp/src/components/Chunk/Cell.vue 74 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
apps/bMiniApp/src/components/Chunk/ChunkTitle.vue 43 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
apps/bMiniApp/src/components/InfiniteLoading/InfiniteLoading.vue 235 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
apps/bMiniApp/src/components/Layout/ContentScrollView.vue 54 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
apps/bMiniApp/src/components/Layout/ContentView.vue 29 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
apps/bMiniApp/src/components/Layout/LoadingLayout.vue 58 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
apps/bMiniApp/src/components/Layout/PageLayout.vue 141 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
apps/bMiniApp/src/components/Layout/PageLayoutWithBg.vue 48 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
apps/bMiniApp/src/components/Layout/layout.ts 19 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
apps/bMiniApp/src/components/Menu/Menu.vue 214 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
apps/bMiniApp/src/components/Menu/MenuItem.vue 220 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
apps/bMiniApp/src/components/Menu/menu.scss 41 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
apps/bMiniApp/src/components/NavigationBar/CommonNavigationBar.vue 104 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
apps/bMiniApp/src/components/NavigationBar/LargeTitleNavigationBar.vue 61 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
apps/bMiniApp/src/components/NavigationBar/NavBar.vue 58 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
apps/bMiniApp/src/components/NavigationBar/TransparentNavigationBar.vue 77 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
apps/bMiniApp/src/components/NavigationBar/commonNavigationBar.ts 28 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
apps/bMiniApp/src/components/NavigationBar/navBar.ts 14 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
apps/bMiniApp/src/components/NoData/NoData.vue 44 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
apps/bMiniApp/src/components/PageFooter/PageFooter.vue 177 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
apps/bMiniApp/src/components/PageFooter/PageFooterAction.vue 67 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
apps/bMiniApp/src/components/PageFooter/PageFooterBtn.vue 34 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
apps/bMiniApp/src/components/Policy/Policy.vue 89 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
apps/bMiniApp/src/components/RichEditCard/RichContent.vue 46 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
apps/bMiniApp/src/components/RichEditCard/RichEditCard.vue 137 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
apps/bMiniApp/src/components/RichEditor/RichEditorContent.vue 59 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
apps/bMiniApp/src/components/RichEditor/style.css 715 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
apps/bMiniApp/src/components/Uploader/CoverUploader.vue 139 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
apps/bMiniApp/src/components/Uploader/Uploader.vue 125 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
apps/bMiniApp/src/components/Uploader/uploader.ts 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
apps/bMiniApp/src/components/UserHome/UserHomeTopView.vue 149 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
apps/bMiniApp/src/components/index.ts 25 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
apps/bMiniApp/src/constants/enum.ts 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
apps/bMiniApp/src/constants/img.ts 17 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
apps/bMiniApp/src/constants/index.ts 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
apps/bMiniApp/src/constants/query.ts 10 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
apps/bMiniApp/src/constants/router.ts 21 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
apps/bMiniApp/src/constants/tabBar.ts 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
apps/bMiniApp/src/custom-tab-bar/index.scss 119 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
apps/bMiniApp/src/custom-tab-bar/index.tsx 168 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
apps/bMiniApp/src/hooks/access.ts 45 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
apps/bMiniApp/src/hooks/authentication.ts 71 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
apps/bMiniApp/src/hooks/index.ts 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
apps/bMiniApp/src/hooks/login.ts 76 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
apps/bMiniApp/src/hooks/router.ts 27 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
apps/bMiniApp/src/hooks/user.ts 107 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
apps/bMiniApp/src/index.html 17 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
apps/bMiniApp/src/pages/home/index.config.ts 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
apps/bMiniApp/src/pages/home/index.scss 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
apps/bMiniApp/src/pages/home/index.vue 52 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
apps/bMiniApp/src/pages/mine/index.config.ts 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
apps/bMiniApp/src/pages/mine/index.scss 151 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
apps/bMiniApp/src/pages/mine/index.vue 110 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
apps/bMiniApp/src/stores/index.ts 10 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
apps/bMiniApp/src/stores/modules/system.ts 116 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
apps/bMiniApp/src/stores/modules/user.ts 312 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
apps/bMiniApp/src/styles/common.scss 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
apps/bMiniApp/src/styles/config.scss 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
apps/bMiniApp/src/styles/custom_theme.scss 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
apps/bMiniApp/src/styles/font.scss 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
apps/bMiniApp/src/styles/function.scss 78 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
apps/bMiniApp/src/styles/hairline.scss 200 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
apps/bMiniApp/src/styles/index.scss 83 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
apps/bMiniApp/src/styles/mixins.scss 76 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
apps/bMiniApp/src/styles/nut.scss 160 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
apps/bMiniApp/src/styles/reset.scss 30 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
apps/bMiniApp/src/styles/var.scss 35 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
apps/bMiniApp/src/subpackages/authentication/authenticationFaRen/InnerPage.vue 216 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
apps/bMiniApp/src/subpackages/authentication/authenticationFaRen/authenticationFaRen.config.ts 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
apps/bMiniApp/src/subpackages/authentication/authenticationFaRen/authenticationFaRen.vue 14 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
apps/bMiniApp/src/subpackages/authentication/authenticationHome/InnerPage.vue 76 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
apps/bMiniApp/src/subpackages/authentication/authenticationHome/authenticationHome.config.ts 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
apps/bMiniApp/src/subpackages/authentication/authenticationHome/authenticationHome.vue 35 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
apps/bMiniApp/src/subpackages/authentication/authenticationHome/authenticationHomeItem.vue 159 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
apps/bMiniApp/src/subpackages/authentication/authenticationJBR/InnerPage.vue 244 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
apps/bMiniApp/src/subpackages/authentication/authenticationJBR/authenticationJBR.config.ts 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
apps/bMiniApp/src/subpackages/authentication/authenticationJBR/authenticationJBR.vue 14 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
apps/bMiniApp/src/subpackages/authentication/authenticationResult/InnerPage.vue 97 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
apps/bMiniApp/src/subpackages/authentication/authenticationResult/authenticationResult.config.ts 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
apps/bMiniApp/src/subpackages/authentication/authenticationResult/authenticationResult.vue 28 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
apps/bMiniApp/src/subpackages/authentication/hooks/index.ts 191 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
apps/bMiniApp/src/subpackages/city/citySelect/citySelect.config.ts 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
apps/bMiniApp/src/subpackages/city/citySelect/citySelect.vue 87 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
apps/bMiniApp/src/subpackages/login/authorization/authorization.vue 289 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
apps/bMiniApp/src/subpackages/login/authorization/index.config.ts 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
apps/bMiniApp/src/subpackages/login/components/LoginPageLayout/LoginPageLayout.vue 58 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
apps/bMiniApp/src/subpackages/login/components/OtherLoginChannel/OtherLoginChannel.vue.vue 17 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
apps/bMiniApp/src/subpackages/login/constants/index.ts 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
apps/bMiniApp/src/subpackages/login/loginByForm/accountLoginForm.vue 118 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
apps/bMiniApp/src/subpackages/login/loginByForm/index.config.ts 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
apps/bMiniApp/src/subpackages/login/loginByForm/loginByForm.vue 79 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
apps/bMiniApp/src/subpackages/login/loginByForm/verificationCodeLoginForm.vue 115 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
apps/bMiniApp/src/subpackages/login/registerForm/registerForm.vue 178 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
apps/bMiniApp/src/subpackages/login/styles/login.scss 165 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
apps/bMiniApp/src/subpackages/login/userPolicy/index.config.ts 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
apps/bMiniApp/src/subpackages/login/userPolicy/userPolicy.vue 290 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
apps/bMiniApp/src/subpackages/user/complaint/complaint.config.ts 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
apps/bMiniApp/src/subpackages/user/complaint/complaint.vue 116 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
apps/bMiniApp/src/utils/index.ts 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
apps/bMiniApp/src/utils/page.ts 25 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
apps/bMiniApp/src/utils/request/index.ts 289 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
apps/bMiniApp/src/utils/storage/auth.ts 71 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
apps/bMiniApp/src/utils/storage/index.ts 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
apps/bMiniApp/src/utils/storage/storage.ts 39 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
apps/bMiniApp/tsconfig.json 34 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
apps/bMiniApp/types/global.d.ts 83 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
apps/bMiniApp/types/globalType.d.ts 8 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
apps/bMiniApp/types/pagination.d.ts 43 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
apps/bMiniApp/types/shims-vue.d.ts 15 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
apps/cMiniApp/project.private.config.json 119 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pnpm-lock.yaml 841 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
apps/bMiniApp/.eslintrc
New file
@@ -0,0 +1,12 @@
// ESLint 检查 .vue 文件需要单独配置编辑器:
// https://eslint.vuejs.org/user-guide/#editor-integrations
{
  "root": true,
  "env": {
    "node": true
  },
  "extends": ["../../.eslintrc", "./.eslintrc-auto-import.json"],
  "parser": "vue-eslint-parser"
}
apps/bMiniApp/.eslintrc-auto-import.json
New file
@@ -0,0 +1,91 @@
{
  "globals": {
    "Component": true,
    "ComponentPublicInstance": true,
    "ComputedRef": true,
    "EffectScope": true,
    "InjectionKey": true,
    "PropType": true,
    "Ref": true,
    "VNode": true,
    "WritableComputedRef": true,
    "acceptHMRUpdate": true,
    "computed": true,
    "createApp": true,
    "createPinia": true,
    "customRef": true,
    "defineAsyncComponent": true,
    "defineComponent": true,
    "defineStore": true,
    "effectScope": true,
    "getActivePinia": true,
    "getCurrentInstance": true,
    "getCurrentScope": true,
    "h": true,
    "inject": true,
    "isProxy": true,
    "isReactive": true,
    "isReadonly": true,
    "isRef": true,
    "mapActions": true,
    "mapGetters": true,
    "mapState": true,
    "mapStores": true,
    "mapWritableState": true,
    "markRaw": true,
    "nextTick": true,
    "onActivated": true,
    "onBeforeMount": true,
    "onBeforeRouteLeave": true,
    "onBeforeRouteUpdate": true,
    "onBeforeUnmount": true,
    "onBeforeUpdate": true,
    "onDeactivated": true,
    "onErrorCaptured": true,
    "onMounted": true,
    "onRenderTracked": true,
    "onRenderTriggered": true,
    "onScopeDispose": true,
    "onServerPrefetch": true,
    "onUnmounted": true,
    "onUpdated": true,
    "provide": true,
    "reactive": true,
    "readonly": true,
    "ref": true,
    "resolveComponent": true,
    "setActivePinia": true,
    "setMapStoreSuffix": true,
    "shallowReactive": true,
    "shallowReadonly": true,
    "shallowRef": true,
    "storeToRefs": true,
    "toRaw": true,
    "toRef": true,
    "toRefs": true,
    "toValue": true,
    "triggerRef": true,
    "unref": true,
    "useAttrs": true,
    "useCssModule": true,
    "useCssVars": true,
    "useLink": true,
    "useRoute": true,
    "useRouter": true,
    "useSlots": true,
    "watch": true,
    "watchEffect": true,
    "watchPostEffect": true,
    "watchSyncEffect": true,
    "useOmitProps": true,
    "usePickProps": true,
    "RouterPath": true,
    "ExtractDefaultPropTypes": true,
    "ExtractPropTypes": true,
    "ExtractPublicPropTypes": true,
    "onWatcherCleanup": true,
    "useId": true,
    "useModel": true,
    "useTemplateRef": true
  }
}
apps/bMiniApp/CHANGELOG.md
New file
@@ -0,0 +1,62 @@
## [1.1.1](http://120.26.58.240:8888/r/12333MiniAppNew/compare/@12333/informationMiniApp/v1.1.0...@12333/informationMiniApp/v1.1.1) (2024-10-31)
### Bug Fixes
* 资讯 ([d26fdcb](http://120.26.58.240:8888/r/12333MiniAppNew/commits/d26fdcb841880df40ae59251ef45110d76eb6374))
# [1.1.0](http://120.26.58.240:8888/r/12333MiniAppNew/compare/@12333/informationMiniApp/v1.0.2...@12333/informationMiniApp/v1.1.0) (2024-10-31)
### Bug Fixes
* 资讯 ([44f857d](http://120.26.58.240:8888/r/12333MiniAppNew/commits/44f857d922b06ab08531ffab140245e66e80c468))
* 资讯 ([3fd5fe3](http://120.26.58.240:8888/r/12333MiniAppNew/commits/3fd5fe3e773ca1667476b30ab38dec8844578c46))
* 资讯 ([0eb7314](http://120.26.58.240:8888/r/12333MiniAppNew/commits/0eb7314bc0d4916c0bea7daedc44688a4422fa27))
* 资讯 ([43deac7](http://120.26.58.240:8888/r/12333MiniAppNew/commits/43deac74a2c0271e929d678af9b1def0d9f1a3f1))
* 资讯 ([56b6e15](http://120.26.58.240:8888/r/12333MiniAppNew/commits/56b6e15d1d664c37b448d77449435463dda3014a))
* 资讯 ([b68d3fc](http://120.26.58.240:8888/r/12333MiniAppNew/commits/b68d3fc205f1f7938023ae3f8c4fb2a06b9303cc))
* 资讯 ([dade5b7](http://120.26.58.240:8888/r/12333MiniAppNew/commits/dade5b7ef95a29515d8eb226f35af69587c8b793))
* 资讯 ([5195e1b](http://120.26.58.240:8888/r/12333MiniAppNew/commits/5195e1bad322cd8b5eb711c36d5945ced5f43fc4))
* 资讯 ([b68f61f](http://120.26.58.240:8888/r/12333MiniAppNew/commits/b68f61f590a2261699408e1a710d39731aecde55))
* 资讯 ([ee998c2](http://120.26.58.240:8888/r/12333MiniAppNew/commits/ee998c2ce2adbd61f0f186d77b2d551dbeb1d41d))
* 资讯 ([590ab73](http://120.26.58.240:8888/r/12333MiniAppNew/commits/590ab73e9fdb5c6d6f84d56ff76dd09fe10c59f5))
* 资讯 ([0af9fe3](http://120.26.58.240:8888/r/12333MiniAppNew/commits/0af9fe3c29023e9314f3b8435938651f8a3c94a6))
* 资讯 ([61a1c3a](http://120.26.58.240:8888/r/12333MiniAppNew/commits/61a1c3a838d6b073970b3624bfc80464b123ed2f))
* 资讯 ([2a3a541](http://120.26.58.240:8888/r/12333MiniAppNew/commits/2a3a541db2c3e8866fa5ef41acca9db0608dfd60))
* 资讯 ([8299138](http://120.26.58.240:8888/r/12333MiniAppNew/commits/8299138625464602c1d059cda9fc9ae9ca7f3444))
* 资讯 ([0e26605](http://120.26.58.240:8888/r/12333MiniAppNew/commits/0e26605cc5da99cd0dd2c7ee7de08393d4052956))
* 资讯 ([54f89f9](http://120.26.58.240:8888/r/12333MiniAppNew/commits/54f89f932a62707d26f25c042923f3d7920d1984))
* 资讯 ([c4d7351](http://120.26.58.240:8888/r/12333MiniAppNew/commits/c4d7351e14343fa6277bbea23b81acf72e56bf9c))
* 资讯 ([413fc5b](http://120.26.58.240:8888/r/12333MiniAppNew/commits/413fc5b5e60a25f8d58197fcd1305e72a5958d7f))
* release-it ([cc1d95b](http://120.26.58.240:8888/r/12333MiniAppNew/commits/cc1d95b1523929289a156357c50c0b2001697c9f))
## 1.0.2 (2024-09-25)
### Bug Fixes
* 登录 注册 ([1c1f30d](http://120.26.58.240:8888/commits/1c1f30d04600ab668d4af647635aff57f47c1455))
* 首页 ([10ff8c4](http://120.26.58.240:8888/commits/10ff8c41d6218ee1cf520c0a396caac00c63d380))
* 修改结构 ([2005902](http://120.26.58.240:8888/commits/200590241b6687b78cfa56e5629cf557b14983c8))
* 优化 ([321889d](http://120.26.58.240:8888/commits/321889d6be3b240b81a3309662236b15e3f31780))
* 优化 ([ac462c1](http://120.26.58.240:8888/commits/ac462c1b0e9ec0757a3ca77fd0d9abe77213dc47))
* 资讯详情 ([accfec4](http://120.26.58.240:8888/commits/accfec4a55c2584d825ff5bc36e64cd7ff9b119b))
* init ([c074b4e](http://120.26.58.240:8888/commits/c074b4edf4694da1cf540a01179a15ad5ee8af46))
* init ([91a31d3](http://120.26.58.240:8888/commits/91a31d39c4b3146003ce4b0889b9978378339df7))
* init ([6ba459d](http://120.26.58.240:8888/commits/6ba459d5de2a533da7eb91136fc2f9577a9866a9))
* init ([6ba5d34](http://120.26.58.240:8888/commits/6ba5d345b15f308a188d3fcea8e4b4930b8fc52c))
* some ([23a3ad8](http://120.26.58.240:8888/commits/23a3ad8a7f533e4659fd42fba490f0c8f65ab55e))
* some ([f66bf2f](http://120.26.58.240:8888/commits/f66bf2f7d0e82eed08db3a1ee01eb1513f498de3))
* some ([7a03b99](http://120.26.58.240:8888/commits/7a03b995c2b81f5be444c7045196a17bb3dfb4e0))
* some ([d8bf2ac](http://120.26.58.240:8888/commits/d8bf2ac1957d75512fc53df8d46be12df7d26e1a))
# @12333/informationMiniApp
## 1.0.1
### Patch Changes
- 资讯小程序
apps/bMiniApp/README.md
New file
@@ -0,0 +1 @@
安装 pnpm install
apps/bMiniApp/auto-imports.d.ts
New file
@@ -0,0 +1,90 @@
/* eslint-disable */
/* prettier-ignore */
// @ts-nocheck
// noinspection JSUnusedGlobalSymbols
// Generated by unplugin-auto-import
export {}
declare global {
  const EffectScope: typeof import('vue')['EffectScope']
  const RouterPath: typeof import('@/constants')['RouterPath']
  const acceptHMRUpdate: typeof import('pinia')['acceptHMRUpdate']
  const computed: typeof import('vue')['computed']
  const createApp: typeof import('vue')['createApp']
  const createPinia: typeof import('pinia')['createPinia']
  const customRef: typeof import('vue')['customRef']
  const defineAsyncComponent: typeof import('vue')['defineAsyncComponent']
  const defineComponent: typeof import('vue')['defineComponent']
  const defineStore: typeof import('pinia')['defineStore']
  const effectScope: typeof import('vue')['effectScope']
  const getActivePinia: typeof import('pinia')['getActivePinia']
  const getCurrentInstance: typeof import('vue')['getCurrentInstance']
  const getCurrentScope: typeof import('vue')['getCurrentScope']
  const h: typeof import('vue')['h']
  const inject: typeof import('vue')['inject']
  const isProxy: typeof import('vue')['isProxy']
  const isReactive: typeof import('vue')['isReactive']
  const isReadonly: typeof import('vue')['isReadonly']
  const isRef: typeof import('vue')['isRef']
  const mapActions: typeof import('pinia')['mapActions']
  const mapGetters: typeof import('pinia')['mapGetters']
  const mapState: typeof import('pinia')['mapState']
  const mapStores: typeof import('pinia')['mapStores']
  const mapWritableState: typeof import('pinia')['mapWritableState']
  const markRaw: typeof import('vue')['markRaw']
  const nextTick: typeof import('vue')['nextTick']
  const onActivated: typeof import('vue')['onActivated']
  const onBeforeMount: typeof import('vue')['onBeforeMount']
  const onBeforeRouteLeave: typeof import('vue-router')['onBeforeRouteLeave']
  const onBeforeRouteUpdate: typeof import('vue-router')['onBeforeRouteUpdate']
  const onBeforeUnmount: typeof import('vue')['onBeforeUnmount']
  const onBeforeUpdate: typeof import('vue')['onBeforeUpdate']
  const onDeactivated: typeof import('vue')['onDeactivated']
  const onErrorCaptured: typeof import('vue')['onErrorCaptured']
  const onMounted: typeof import('vue')['onMounted']
  const onRenderTracked: typeof import('vue')['onRenderTracked']
  const onRenderTriggered: typeof import('vue')['onRenderTriggered']
  const onScopeDispose: typeof import('vue')['onScopeDispose']
  const onServerPrefetch: typeof import('vue')['onServerPrefetch']
  const onUnmounted: typeof import('vue')['onUnmounted']
  const onUpdated: typeof import('vue')['onUpdated']
  const onWatcherCleanup: typeof import('vue')['onWatcherCleanup']
  const provide: typeof import('vue')['provide']
  const reactive: typeof import('vue')['reactive']
  const readonly: typeof import('vue')['readonly']
  const ref: typeof import('vue')['ref']
  const resolveComponent: typeof import('vue')['resolveComponent']
  const setActivePinia: typeof import('pinia')['setActivePinia']
  const setMapStoreSuffix: typeof import('pinia')['setMapStoreSuffix']
  const shallowReactive: typeof import('vue')['shallowReactive']
  const shallowReadonly: typeof import('vue')['shallowReadonly']
  const shallowRef: typeof import('vue')['shallowRef']
  const storeToRefs: typeof import('pinia')['storeToRefs']
  const toRaw: typeof import('vue')['toRaw']
  const toRef: typeof import('vue')['toRef']
  const toRefs: typeof import('vue')['toRefs']
  const toValue: typeof import('vue')['toValue']
  const triggerRef: typeof import('vue')['triggerRef']
  const unref: typeof import('vue')['unref']
  const useAttrs: typeof import('vue')['useAttrs']
  const useCssModule: typeof import('vue')['useCssModule']
  const useCssVars: typeof import('vue')['useCssVars']
  const useId: typeof import('vue')['useId']
  const useLink: typeof import('vue-router')['useLink']
  const useModel: typeof import('vue')['useModel']
  const useOmitProps: typeof import('@/hooks')['useOmitProps']
  const usePickProps: typeof import('@/hooks')['usePickProps']
  const useRoute: typeof import('vue-router')['useRoute']
  const useRouter: typeof import('vue-router')['useRouter']
  const useSlots: typeof import('vue')['useSlots']
  const useTemplateRef: typeof import('vue')['useTemplateRef']
  const watch: typeof import('vue')['watch']
  const watchEffect: typeof import('vue')['watchEffect']
  const watchPostEffect: typeof import('vue')['watchPostEffect']
  const watchSyncEffect: typeof import('vue')['watchSyncEffect']
}
// for type re-export
declare global {
  // @ts-ignore
  export type { Component, ComponentPublicInstance, ComputedRef, ExtractDefaultPropTypes, ExtractPropTypes, ExtractPublicPropTypes, InjectionKey, PropType, Ref, VNode, WritableComputedRef } from 'vue'
  import('vue')
}
apps/bMiniApp/babel.config.js
New file
@@ -0,0 +1,32 @@
// babel-preset-taro 更多选项和默认值:
// https://github.com/NervJS/taro/blob/next/packages/babel-preset-taro/README.md
module.exports = {
  compact: false,
  presets: [
    [
      'taro',
      {
        framework: 'vue3',
        ts: true,
      },
    ],
  ],
  plugins: [
    [
      'import',
      {
        libraryName: 'lodash',
        libraryDirectory: '',
        camel2DashComponentName: false, // default: true
      },
      'lodash',
    ],
    // 'lodash',
  ],
  env: {
    production: {
      plugins: ['transform-remove-console'],
    },
  },
};
apps/bMiniApp/ci/private.wx88251c84f5cd886b.key
New file
@@ -0,0 +1,27 @@
-----BEGIN RSA PRIVATE KEY-----
MIIEowIBAAKCAQEAxd7jgcSJvGO3n2YaxYB/165LDUBwK2pGqvnbEJjin0dl1+ZX
U9rdwGUBM1K954bx3E0pwQGfzMjiO8PFKhzE+ztpyBjYpiEXG+H4ZRNAJ0lomJMu
aCzE/EUSboUKEcsBmRdWN0x7UWFeEmedE9vTBaoXCn+A93StDdLMPfGh16Ia+q9e
c6019GODYNDe3f+sK00rVHmu+n+GADTqX6C2N40DtdgfBx4eAy4s+w5sjbXZ3O3o
CzrJ6KCLAG91dSyze8BTkaSX3dH9tkDjmhFON6yTzqBOe5TFiuA7dT4uBijGIkXW
sdIPnP71zGC+P/05UW9gFIpscP36QMQJ1jG+ZwIDAQABAoIBADTrv/1dC1mPcfT3
4gEgtRCCVSBeM6Ho8q2X1bdCrJndBqgPuxt6VgS2/vMzFgduWBGLsbclMBAdSiSh
34G74BMxeMFDo+4Ku5uBfGXMGERppcfo1WiXULgH4T4d5uuLWAoR68Uud2z0laxm
eeRtzqqdKzxrjZqhYgdocae/kIGTKSekIVEEGDgZAVBwuT98hdTp+i0OlUHxmn77
+Sj7GXsRZQRkDmCvrOXYPiOOLRkkzKVMVUZ2///KY5J4eCCM/8EBT/2wjpZb7dhT
MwcFe6D7dtsfNzrkuGR/LADSCeLKtLhp2Pi7NdsphyGYwPW03iz+Xt16XT0Ln8K+
joYy0YECgYEA5mIdcxbZuLq7cq7F2bF0FhT6Csf491ONsvYoWL9tZ9gxQTggAkqD
PjTDfPLULYPuUZ+Ud3JfCs0OpsFyLPR0+1utQ/3gQgQ+1AK4qqm6dPfHv8pIp44o
dj/wyMD5qMAeHNL7FvIdEhshMug0LAjKXhqDjc62hs5m8Yg5zQhMdP8CgYEA299M
gGCaVee7jqEwJrRZCHREpu5JxJ0lhTbSYS5VnyMGsqIKj9+RrdWV+km2cHjeO1PE
x5puhaOnzwbYrIEcMtaQxJRX2Ab9T37wKZmio+AY0zg/jF+i8ZFlrzpuMYtg5cnD
TzFVM2Uh2LHvEzsz99BEkI0zMzoBDlpj5RqGLpkCgYBCiM12gn/ocM1X5o+vOieL
hQ1ddbk6PIAs0hh+4PIIzpATBNGBt+FFYtmeSUbryjFWk16+TGKUbPoxQKbnwsXS
HfzhKP3OMwmuEwcgCpqV00V150aqVUzsMbUpVUoE6U8JBgmL6+pnYzxoRlVi7jr7
iG670po2Pn/Oe4gt5ZqnIwKBgQC3iBiCnKCXjpy3vQLFfAtJjEv2D7gR357/KLjJ
l/Supn0jxTEN0W/36+6KAte/4JSYbx82Akm5Udd0b2GT9R3FrecfwDfnQkZWAj6U
awMgyaHPRgd9tCL+hACeGSb8Qjy68wUN6L8W7JcpG7XVlriVZgqloseXPha9lWQH
THGvGQKBgH9LOe3Potc/4EGtlPFMbNQbJd/vzHp5skC1DKqK8I5bsTYVctVyPe0S
xO/JjHI2PnhcoXnLc2LwQrMwri6ijCYYgApCxzOhe9FmZP3NuH3b3dE+QpUYSd4f
vXjfyO1ilaf5j1OhOMKKE7Vk6Q7UqWcNmZowqSF+eL01oK3QF3Dq
-----END RSA PRIVATE KEY-----
apps/bMiniApp/ci/upload.js
New file
@@ -0,0 +1,41 @@
const config = require('../project.config.json');
const pkg = require('../package.json');
const path = require('path');
const semver = require('semver');
let projectPath = path.resolve(__dirname, '..');
const CIPluginFn = async () => {
  let version;
  let robot = 30;
  let desc = '';
  if (process.env.NODE_ENV === 'production') {
    version = pkg.version;
    robot = 1;
    desc = '正式环境小程序';
    if (process.env.APP_ENV === 'staging') {
      version = semver.inc(version, 'patch');
      robot = 2;
      desc = '测试环境小程序';
    }
  }
  /**
   * @typedef { import("@tarojs/plugin-mini-ci").CIOptions } CIOptions
   * @type {CIOptions}
   */
  return {
    weapp: {
      appid: config.appid,
      privateKeyPath: `${projectPath}/ci/private.wx88251c84f5cd886b.key`,
      robot: robot,
      setting: {
        minify: true,
      },
    },
    version,
    desc: desc,
  };
};
module.exports = { CIPluginFn };
apps/bMiniApp/config/dev.js
New file
@@ -0,0 +1,23 @@
const mocks = require('../mock');
module.exports = {
  env: {
    NODE_ENV: '"development"',
    BASE_URL: '"http://localhost:57190"',
    BASE_URL_JX: '"https://api.jx818.com"',
    OSS_URL: '"https://waterdroptest2.oss-cn-hangzhou.aliyuncs.com/"',
    WEMAP_KEY: 'T2UBZ-N563J-ZCHFF-XDOXN-VCH7S-CJB2T',
  },
  plugins: [
    [
      '@tarojs/plugin-mock',
      {
        mocks: mocks,
      },
    ],
  ],
  defineConstants: {},
  mini: {},
  h5: {},
};
apps/bMiniApp/config/index.js
New file
@@ -0,0 +1,231 @@
const path = require('path');
const { CIPluginFn } = require('../ci/upload');
import AutoImport from 'unplugin-auto-import/webpack';
import ComponentsPlugin from 'unplugin-vue-components/webpack';
import NutUIResolver from '@nutui/nutui-taro/dist/resolver';
const config = {
  projectName: 'vue-mini',
  date: '2022-11-29',
  designWidth(input) {
    // 配置 NutUI 375 尺寸
    if (input?.file?.replace(/\\+/g, '/').indexOf('@nutui') > -1) {
      return 375;
    }
    // 全局使用 Taro 默认的 750 尺寸
    return 750;
  },
  deviceRatio: {
    375: 2 / 1,
    640: 2.34 / 2,
    750: 1,
    828: 1.81 / 2,
  },
  alias: {
    '@': path.resolve(__dirname, '..', 'src'),
    '@components/assets': path.resolve(__dirname, '..', 'node_modules', '@12333/components/assets'),
  },
  sourceRoot: 'src',
  outputRoot: 'dist',
  plugins: [
    ['@tarojs/plugin-mini-ci', CIPluginFn],
    [
      '@tarojs/plugin-vue-devtools',
      {
        port: 9999,
      },
    ],
    '@tarojs/plugin-html',
    [
      '@tarojs/plugin-http',
      {
        enableCookie: true,
      },
    ],
    'taro-plugin-pinia',
    [
      '@tarojs/plugin-framework-vue3',
      {
        vueLoaderOption: {
          compilerOptions: {
            isCustomElement: (tag) => tag.includes('ec-canvas'),
          },
          reactivityTransform: true, // 开启vue3响应性语法糖
        },
      },
    ],
  ],
  defineConstants: {
    // CLIENT_ID: JSON.stringify('frontend-admin-app-client'),
    // START_YEAR: '2022',
  },
  copy: {
    patterns: [],
    options: {},
  },
  framework: 'vue3',
  compiler: {
    type: 'webpack5',
    prebundle: { enable: false },
  },
  cache: {
    enable: false, // Webpack 持久化缓存配置,建议开启。默认配置请参考:https://docs.taro.zone/docs/config-detail#cache
  },
  sass: {
    resource: [path.resolve(__dirname, '..', 'src/styles/custom_theme.scss')],
    data: `@import "@nutui/nutui-taro/dist/styles/variables.scss";`,
  },
  mini: {
    hot: true,
    miniCssExtractPluginOption: {
      ignoreOrder: true,
    },
    postcss: {
      pxtransform: {
        enable: true,
        config: {
          selectorBlackList: ['nut-'],
        },
      },
      url: {
        enable: true,
        config: {
          limit: 1024, // 设定转换尺寸上限
        },
      },
      cssModules: {
        enable: true, // 默认为 false,如需使用 css modules 功能,则设为 true
        config: {
          namingPattern: 'module', // 转换模式,取值为 global/module
          generateScopedName: '[name]__[local]___[hash:base64:5]',
        },
      },
    },
    webpackChain(chain, webpack) {
      if (process.env.NODE_ENV === 'development') {
        chain.plugin('analyzer').use(require('webpack-bundle-analyzer').BundleAnalyzerPlugin, []);
      }
      chain.plugin('unplugin-auto-import').use(
        AutoImport({
          imports: ['vue', 'pinia', 'vue-router', { '@/constants': ['RouterPath'] }],
          eslintrc: {
            enabled: true, // Default `false`
            filepath: './.eslintrc-auto-import.json', // Default `./.eslintrc-auto-import.json`
            globalsPropValue: true, // Default `true`, (true | false | 'readonly' | 'readable' | 'writable' | 'writeable')
          },
        })
      );
      chain.plugin('unplugin-vue-components').use(
        ComponentsPlugin({
          include: [/\.[tj]sx?$/, /\.vue$/, /\.vue\?vue/],
          resolvers: [NutUIResolver({ taro: true })],
          dts: true,
        })
      );
      chain.merge({
        plugin: {
          install: {
            plugin: require('terser-webpack-plugin'),
            args: [
              {
                terserOptions: {
                  compress: true, // 默认使用terser压缩
                  keep_classnames: true, // 不改变class名称
                  keep_fnames: true, // 不改变函数名称
                },
              },
            ],
          },
        },
      });
      chain.merge({
        optimization: {
          splitChunks: {
            cacheGroups: {
              nutui: {
                name: 'nutui',
                minChunks: 2,
                test: (module) => {
                  return /[\\/]node_modules[\\/]@nutui[\\/]/.test(module.resource);
                },
                priority: 20,
              },
              lodash: {
                name: 'lodash',
                minChunks: 2,
                test: (module) => {
                  return /[\\/]node_modules[\\/]lodash[\\/]/.test(module.resource);
                },
                priority: 20,
              },
              // senin: {
              //   name: 'senin',
              //   minChunks: 2,
              //   test: (module) => {
              //     return /[\\/]node_modules[\\/]senin-mini[\\/]/.test(module.resource);
              //   },
              //   priority: 30,
              // },
            },
          },
        },
      });
    },
    commonChunks(commonChunks) {
      commonChunks.push('nutui');
      commonChunks.push('lodash');
      // commonChunks.push('senin');
      return commonChunks;
    },
  },
  h5: {
    publicPath: '/',
    staticDirectory: 'static',
    postcss: {
      autoprefixer: {
        enable: true,
        config: {},
      },
      cssModules: {
        enable: false, // 默认为 false,如需使用 css modules 功能,则设为 true
        config: {
          namingPattern: 'module', // 转换模式,取值为 global/module
          generateScopedName: '[name]__[local]___[hash:base64:5]',
        },
      },
    },
  },
  rn: {
    appName: 'taroDemo',
    postcss: {
      cssModules: {
        enable: false, // 默认为 false,如需使用 css modules 功能,则设为 true
      },
    },
  },
};
module.exports = function (merge) {
  if (process.env.NODE_ENV === 'development') {
    return merge(
      {},
      config,
      require('./dev'),
      process.env.APP_ENV === 'staging' ? require('./staging') : {}
    );
  }
  return merge(
    {},
    config,
    require('./prod'),
    process.env.APP_ENV === 'staging' ? require('./staging') : {}
  );
};
apps/bMiniApp/config/prod.js
New file
@@ -0,0 +1,41 @@
module.exports = {
  env: {
    NODE_ENV: '"production"',
    BASE_URL: '"https://api.81812333.com"',
    BASE_URL_JX: '"https://api.jx818.com"',
    OSS_URL: '"https://parkmanagement.oss-cn-hangzhou.aliyuncs.com"',
    WEMAP_KEY: 'DYRBZ-ZGPCF-X3OJN-N2AA3-JWUCE-HEBXJ',
  },
  defineConstants: {},
  mini: {},
  h5: {
    /**
     * WebpackChain 插件配置
     * @docs https://github.com/neutrinojs/webpack-chain
     */
    // webpackChain (chain) {
    //   /**
    //    * 如果 h5 端编译后体积过大,可以使用 webpack-bundle-analyzer 插件对打包体积进行分析。
    //    * @docs https://github.com/webpack-contrib/webpack-bundle-analyzer
    //    */
    //   chain.plugin('analyzer')
    //     .use(require('webpack-bundle-analyzer').BundleAnalyzerPlugin, [])
    //   /**
    //    * 如果 h5 端首屏加载时间过长,可以使用 prerender-spa-plugin 插件预加载首页。
    //    * @docs https://github.com/chrisvfritz/prerender-spa-plugin
    //    */
    //   const path = require('path')
    //   const Prerender = require('prerender-spa-plugin')
    //   const staticDir = path.join(__dirname, '..', 'dist')
    //   chain
    //     .plugin('prerender')
    //     .use(new Prerender({
    //       staticDir,
    //       routes: [ '/pages/index/index' ],
    //       postProcess: (context) => ({ ...context, outputPath: path.join(staticDir, 'index.html') })
    //     }))
    // }
  },
};
apps/bMiniApp/config/staging.js
New file
@@ -0,0 +1,12 @@
module.exports = {
  env: {
    BASE_URL: '"https://testrlywx.boleyuma.com"',
    BASE_URL_JX: '"https://api.jx818.com"',
    OSS_URL: '"https://waterdroptest2.oss-cn-hangzhou.aliyuncs.com/"',
    APP_ENV: '"staging"',
    WEMAP_KEY: 'T2UBZ-N563J-ZCHFF-XDOXN-VCH7S-CJB2T',
  },
};
apps/bMiniApp/mock/Purchase.mock.js
New file
@@ -0,0 +1,106 @@
const Mock = require('mockjs');
module.exports = {
  'POST /api/Purchase/getMySells': Mock.mock({
    error: null,
    msg: null,
    success: true,
    unAuthorizedRequest: false,
    result: {
      pageModel: {
        rows: 64,
        page: 97,
        orderInput: [],
        totalCount: 68,
        totalPage: 72,
      },
      objectData: null,
      'data|1-10': [
        {
          'name|+1': Mock.mock('@title'),
          'id|+1': Mock.mock('@guid'),
          'categoryName|+1': Mock.mock('@cname'),
          productId: Mock.mock('@guid'),
          productName: Mock.mock('@cname'),
          purchaserId: Mock.mock('@guid'),
          purchaser: Mock.mock('@string'),
          purchaseContacter: Mock.mock('@string'),
          purchaseContacterPhone: Mock.mock('@string'),
          unitPrice: Mock.mock('@integer(60, 100)'),
          count: Mock.mock('@integer(60, 100)'),
          amount: Mock.mock('@integer(60, 100)'),
          'status|+1': [0, 10, 20, -10, -20, -30],
          purchaseDate: Mock.mock('@datetime'),
          fixtureDate: Mock.mock('@datetime'),
          comment: Mock.mock({
            'starCount|1-5': 5,
            content: Mock.mock('@cparagraph'),
            creationTime: Mock.mock('@datetime'),
          }),
          refund: {
            refundApplyRemark: Mock.mock('@cparagraph'),
            refundApplyTime: Mock.mock('@datetime'),
            refundDealRemark: Mock.mock('@cparagraph'),
          },
        },
      ],
    },
  }),
  'POST /api/Purchase/getMyPurchases': Mock.mock({
    error: null,
    msg: null,
    success: true,
    unAuthorizedRequest: false,
    result: {
      pageModel: {
        rows: 64,
        page: 97,
        orderInput: [],
        totalCount: 68,
        totalPage: 72,
      },
      objectData: null,
      'data|8': [
        {
          'id|+1': Mock.mock('@guid'),
          'categoryName|+1': Mock.mock('@cname'),
          'productId|+1': Mock.mock('@guid'),
          productName: Mock.mock('@cname'),
          'covers|1-10': [
            {
              url: Mock.mock('@string'),
              'sequence|1-100': 100,
              'isMain|1-2': true,
            },
          ],
          tags: [
            {
              tagId: Mock.mock('@guid'),
              tagName: Mock.mock('@cname'),
              'sequence|1-100': 100,
              type: 1,
            },
          ],
          versionName: Mock.mock('@cname'),
          count: Mock.mock('@integer(60, 100)'),
          unitPrice: Mock.mock('@integer(60, 100)'),
          amount: Mock.mock('@integer(60, 100)'),
          seller: Mock.mock('@cname'),
          purchaseDate: Mock.mock('@datetime'),
          comment: {
            'starCount|1-5': 5,
            content: Mock.mock('@cparagraph'),
            creationTime: Mock.mock('@datetime'),
          },
          refund: {
            refundApplyRemark: Mock.mock('@cparagraph'),
            refundApplyTime: Mock.mock('@datetime'),
            refundDealRemark: Mock.mock('@cparagraph'),
          },
          'status|+1': [0, 10, 20, -10, -20, -30],
          chargeWay: '年',
        },
      ],
    },
  }),
};
apps/bMiniApp/mock/index.js
New file
@@ -0,0 +1,5 @@
const purchaseMocks = require('./Purchase.mock');
module.exports = {
  ...purchaseMocks,
};
apps/bMiniApp/package.json
New file
@@ -0,0 +1,137 @@
{
  "name": "@12333/bMiniApp",
  "version": "1.0.0",
  "private": true,
  "description": "",
  "templateInfo": {
    "name": "default",
    "typescript": true,
    "css": "sass"
  },
  "scripts": {
    "build:weapp": "cross-env NODE_OPTIONS=--openssl-legacy-provider taro build --type weapp",
    "build:weapp:upload": "npm run build:weapp -- --upload",
    "build:weapp:staging": "cross-env APP_ENV=staging npm run build:weapp --",
    "build:weapp:staging:upload": "npm run build:weapp:staging -- --upload",
    "build:swan": "taro build --type swan",
    "build:alipay": "taro build --type alipay",
    "build:tt": "taro build --type tt",
    "build:h5": "taro build --type h5",
    "build:rn": "taro build --type rn",
    "build:qq": "taro build --type qq",
    "build:jd": "taro build --type jd",
    "build:quickapp": "taro build --type quickapp",
    "dev:weapp": "npm run build:weapp -- --watch",
    "dev:weapp:staging": "npm run build:weapp:staging -- --watch",
    "dev:swan": "npm run build:swan -- --watch",
    "dev:alipay": "npm run build:alipay -- --watch",
    "dev:tt": "npm run build:tt -- --watch",
    "dev:h5": "npm run build:h5 -- --watch",
    "dev:rn": "npm run build:rn -- --watch",
    "dev:qq": "npm run build:qq -- --watch",
    "dev:jd": "npm run build:jd -- --watch",
    "dev:quickapp": "npm run build:quickapp -- --watch",
    "release": "release-it --config ../../.release-it.json --git.tagName='@12333/bMiniApp/v${version}' --hooks.after:release='npm run build:weapp:upload'"
  },
  "browserslist": [
    "last 3 versions",
    "Android >= 4.1",
    "ios >= 8"
  ],
  "author": "",
  "dependencies": {
    "@12333/components": "workspace:^",
    "@12333/constants": "workspace:*",
    "@12333/hooks": "workspace:^",
    "@12333/services": "workspace:^",
    "@12333/utils": "workspace:^",
    "@babel/runtime": "^7.7.7",
    "@bole-12333/chat-kit": "^1.0.1",
    "@bole-core/request": "^0.0.1",
    "@nutui/icons-vue-taro": "^0.0.9",
    "@nutui/nutui-taro": "^4.3.13",
    "@tanstack/vue-query": "^4.35.3",
    "@tarojs/components": "3.6.20",
    "@tarojs/helper": "3.6.20",
    "@tarojs/plugin-framework-vue3": "3.6.20",
    "@tarojs/plugin-html": "3.6.20",
    "@tarojs/plugin-http": "3.6.20",
    "@tarojs/plugin-platform-alipay": "3.6.20",
    "@tarojs/plugin-platform-jd": "3.6.20",
    "@tarojs/plugin-platform-qq": "3.6.20",
    "@tarojs/plugin-platform-swan": "3.6.20",
    "@tarojs/plugin-platform-tt": "3.6.20",
    "@tarojs/plugin-platform-weapp": "3.6.20",
    "@tarojs/router": "3.6.20",
    "@tarojs/runtime": "3.6.20",
    "@tarojs/shared": "3.6.20",
    "@tarojs/taro": "3.6.20",
    "@tarojs/taro-h5": "3.6.20",
    "@tencentcloud/chat-uikit-engine": "^2.0.3",
    "@tencentcloud/chat-uikit-uniapp": "^2.0.3",
    "@tencentcloud/tui-customer-service-plugin": "^2.0.3",
    "@vant/weapp": "^1.11.1",
    "axios": "^1.4.0",
    "crypto-js": "^4.1.1",
    "dayjs": "^1.11.6",
    "js-base64": "^3.7.5",
    "lodash": "^4.17.21",
    "pinia": "^2.1.6",
    "qs": "^6.11.1",
    "senin-mini": "^1.0.10",
    "senior-request": "^1.0.3",
    "taro-plugin-pinia": "^1.0.0",
    "vconsole": "^3.15.1",
    "vue": "3.5.12",
    "vue-component-type-helpers": "^2.1.10"
  },
  "devDependencies": {
    "@babel/core": "^7.8.0",
    "@nutui/auto-import-resolver": "^1.0.0",
    "@tarojs/cli": "3.6.20",
    "@tarojs/plugin-mini-ci": "^4.0.7",
    "@tarojs/plugin-mock": "^0.0.9",
    "@tarojs/plugin-vue-devtools": "^3.6.20",
    "@tarojs/service": "^3.6.20",
    "@tarojs/webpack5-runner": "3.6.20",
    "@types/crypto-js": "^4.1.1",
    "@types/lodash": "^4.14.198",
    "@types/webpack-env": "^1.13.6",
    "@vue/babel-plugin-jsx": "^1.0.6",
    "@vue/compiler-sfc": "^3.5.12",
    "babel-plugin-import": "^1.13.8",
    "babel-plugin-lodash": "^3.3.4",
    "babel-plugin-transform-remove-console": "^6.9.4",
    "babel-preset-taro": "3.6.20",
    "cache-loader": "^4.1.0",
    "cross-env": "^7.0.3",
    "mockjs": "^1.1.0",
    "postcss": "^8.4.19",
    "postcss-html": "^1.5.0",
    "postcss-loader": "^7.3.3",
    "postcss-scss": "^4.0.6",
    "prettier": "^2.7.1",
    "stylelint": "^14.15.0",
    "stylelint-config-html": "^1.1.0",
    "stylelint-config-prettier": "^9.0.4",
    "stylelint-config-recess-order": "^3.0.0",
    "stylelint-config-recommended": "^9.0.0",
    "stylelint-config-standard": "^29.0.0",
    "stylelint-config-standard-scss": "^6.1.0",
    "stylelint-order": "^5.0.0",
    "stylelint-scss": "^4.3.0",
    "taro-plugin-compiler-optimization": "^1.0.4",
    "thread-loader": "^4.0.2",
    "unplugin-auto-import": "^0.16.6",
    "unplugin-vue-components": "^0.27.4",
    "vue-eslint-parser": "^9.3.1",
    "vue-loader": "^17.0.0",
    "webpack": "^5.78.0",
    "webpack-bundle-analyzer": "^4.7.0"
  },
  "pnpm": {
    "patchedDependencies": {
      "@nutui/nutui-taro@4.1.5": "../../patches/@nutui__nutui-taro@4.1.5.patch"
    }
  }
}
apps/bMiniApp/pnpm-lock.yaml
New file
Diff too large
apps/bMiniApp/project.config.json
New file
@@ -0,0 +1,55 @@
{
    "miniprogramRoot": "dist/",
    "description": "",
    "setting": {
        "urlCheck": false,
        "es6": false,
        "enhance": false,
        "postcss": false,
        "preloadBackgroundData": false,
        "minified": false,
        "newFeature": false,
        "coverView": true,
        "nodeModules": false,
        "autoAudits": false,
        "showShadowRootInWxmlPanel": true,
        "scopeDataCheck": false,
        "uglifyFileName": false,
        "checkInvalidKey": true,
        "checkSiteMap": false,
        "uploadWithSourceMap": true,
        "compileHotReLoad": false,
        "lazyloadPlaceholderEnable": false,
        "useMultiFrameRuntime": true,
        "babelSetting": {
            "ignore": [],
            "disablePlugins": [],
            "outputPath": ""
        },
        "enableEngineNative": false,
        "useIsolateContext": true,
        "userConfirmedBundleSwitch": false,
        "packNpmManually": false,
        "packNpmRelationList": [],
        "minifyWXSS": false,
        "disableUseStrict": false,
        "minifyWXML": false,
        "showES6CompileOption": false,
        "useCompilerPlugins": false,
        "ignoreUploadUnusedFiles": true,
        "condition": false
    },
    "compileType": "miniprogram",
    "editorSetting": {
        "tabIndent": "insertSpaces",
        "tabSize": 4
    },
    "srcMiniprogramRoot": "dist/",
    "condition": {},
    "libVersion": "3.1.0",
    "packOptions": {
        "ignore": [],
        "include": []
    },
    "appid": "wx88251c84f5cd886b"
}
apps/bMiniApp/project.private.config.json
New file
@@ -0,0 +1,15 @@
{
  "description": "项目私有配置文件。此文件中的内容将覆盖 project.config.json 中的相同字段。项目的改动优先同步到此文件中。详见文档:https://developers.weixin.qq.com/miniprogram/dev/devtools/projectconfig.html",
  "projectname": "bMiniApp",
  "setting": {
    "compileHotReLoad": true,
    "bigPackageSizeSupport": true,
    "skylineRenderEnable": false
  },
  "condition": {
    "miniprogram": {
      "list": []
    }
  },
  "libVersion": "3.7.3"
}
apps/bMiniApp/project.tt.json
New file
@@ -0,0 +1,9 @@
{
  "miniprogramRoot": "./",
  "projectname": "bMiniApp",
  "appid": "testAppId",
  "setting": {
    "es6": false,
    "minified": false
  }
}
apps/bMiniApp/src/app.config.ts
New file
@@ -0,0 +1,72 @@
export default defineAppConfig({
  entryPagePath: 'pages/home/index',
  pages: ['pages/home/index', 'pages/mine/index'],
  requiredPrivateInfos: ['getLocation'],
  permission: {
    'scope.userLocation': {
      desc: '你的位置信息将用于小程序数据的效果展示',
    },
  },
  window: {
    backgroundTextStyle: 'light',
    navigationBarBackgroundColor: '#ff6d33',
    navigationBarTitleText: 'WeChat',
    navigationBarTextStyle: 'black',
    backgroundColorTop: '#ff6d33',
    backgroundColor: '#f7f7f7',
    backgroundColorBottom: '#f7f7f7',
    navigationStyle: 'custom',
  },
  tabBar: {
    list: [
      {
        pagePath: 'pages/home/index',
        iconPath: 'assets/tabbar/icon-home.png',
        selectedIconPath: 'assets/tabbar/icon-home-active.png',
        text: '首页',
      },
      {
        pagePath: 'pages/mine/index',
        iconPath: 'assets/tabbar/icon-mine.png',
        selectedIconPath: 'assets/tabbar/icon-mine-active.png',
        text: '我的',
      },
    ],
    color: '#000',
    selectedColor: '#ff6d33',
    backgroundColor: '#fff',
    borderStyle: 'black',
    custom: true,
  },
  lazyCodeLoading: 'requiredComponents', // 按需注入和用时注入(按需注入+占位组件)
  subpackages: [
    {
      root: 'subpackages/login',
      pages: [
        'authorization/authorization',
        'userPolicy/userPolicy',
        'loginByForm/loginByForm',
        'registerForm/registerForm',
      ],
    },
    {
      root: 'subpackages/authentication',
      pages: [
        'authenticationHome/authenticationHome',
        'authenticationFaRen/authenticationFaRen',
        'authenticationJBR/authenticationJBR',
        'authenticationResult/authenticationResult',
      ],
    },
    {
      root: 'subpackages/city',
      pages: ['citySelect/citySelect'],
    },
  ],
  // preloadRule: {
  //   'pages/mine/index': {
  //     network: 'all',
  //     packages: ['subpackages/setting', 'subpackages/message'],
  //   },
  // },
});
apps/bMiniApp/src/app.scss
New file
@@ -0,0 +1 @@
@import '@/styles/index.scss';
apps/bMiniApp/src/app.ts
New file
@@ -0,0 +1,85 @@
import { createApp } from 'vue';
import '@nutui/nutui-taro/dist/style.css';
import './app.scss';
import { setupStore } from '@/stores';
import { useSystemStore } from '@/stores/modules/system';
import { useUserStore } from '@/stores/modules/user';
import Taro from '@tarojs/taro';
import { VueQueryPlugin, VueQueryPluginOptions } from '@tanstack/vue-query';
import { myClient } from '@/constants/query';
window.uni = Taro;
function updateVersions() {
  const updateManager = Taro.getUpdateManager();
  updateManager.onCheckForUpdate(function (_res) {
    // 请求完新版本信息的回调
  });
  updateManager.onUpdateReady(function () {
    Taro.showModal({
      title: '更新提示',
      content: '新版本已经准备好,是否重启应用?',
      success: function (res) {
        if (res.confirm) {
          // 新的版本已经下载好,调用 applyUpdate 应用新版本并重启
          updateManager.applyUpdate();
        }
      },
    });
  });
  updateManager.onUpdateFailed(function () {
    // 新的版本下载失败
    Taro.showToast({
      title: '新的版本下载失败,请重新进入',
      icon: 'none',
      duration: 2000,
    });
  });
}
const App = createApp({
  // 可以使用所有的 Vue 生命周期方法
  mounted() {},
  // 对应 onLaunch
  onLaunch(options) {
    // 如果是收藏进入
    if (options.query.collect) {
      Taro.reLaunch({
        url: '/pages/index/index',
      });
      return;
    }
    // 将启动参数放进到全局去
    const system = useSystemStore();
    system.init(options);
    system.setInfo(Taro.getSystemInfoSync());
  },
  // 对应 onShow
  onShow(options) {
    updateVersions();
  },
  // 对应 onHide
  onHide() {},
  // 入口组件不需要实现 render 方法,即使实现了也会被 taro 所覆盖
});
setupStore(App);
import { IconFont } from '@nutui/icons-vue-taro';
App.component('IconFont', IconFont); // 全局组件
const vueQueryPluginOptions: VueQueryPluginOptions = {
  queryClient: myClient,
};
App.use(VueQueryPlugin, vueQueryPluginOptions);
export default App;
apps/bMiniApp/src/assets/authentication/icon-arrow.png
apps/bMiniApp/src/assets/authentication/icon-faren.png
apps/bMiniApp/src/assets/authentication/icon-jbr.png
apps/bMiniApp/src/assets/authentication/icon-result-error.png
apps/bMiniApp/src/assets/authentication/icon-result-success.png
apps/bMiniApp/src/assets/common/icon-common-page-bg.png
apps/bMiniApp/src/assets/common/icon-navi-arrow-white.png
apps/bMiniApp/src/assets/common/icon-navi-arrow.png
apps/bMiniApp/src/assets/components/fail.png
apps/bMiniApp/src/assets/components/icon-add.png
apps/bMiniApp/src/assets/components/icon-back-top.png
apps/bMiniApp/src/assets/components/icon-dark-arrow.png
apps/bMiniApp/src/assets/components/icon-default-avatar.png
apps/bMiniApp/src/assets/components/icon-phone.png
apps/bMiniApp/src/assets/components/icon-small-dark-arrow.png
apps/bMiniApp/src/assets/components/rich-card/icon-add-editor.png
apps/bMiniApp/src/assets/components/rich-card/icon-add.png
apps/bMiniApp/src/assets/components/rich-card/icon-delete.png
apps/bMiniApp/src/assets/components/rich-card/icon-move-down-active.png
apps/bMiniApp/src/assets/components/rich-card/icon-move-down.png
apps/bMiniApp/src/assets/components/rich-card/icon-move-up-active.png
apps/bMiniApp/src/assets/components/rich-card/icon-move-up.png
apps/bMiniApp/src/assets/components/success.png
apps/bMiniApp/src/assets/font/D-DIN.otf
Binary files differ
apps/bMiniApp/src/assets/login/icon-btn-captcha.png
apps/bMiniApp/src/assets/login/icon-btn-password.png
apps/bMiniApp/src/assets/login/icon-tab-bg-1.png
apps/bMiniApp/src/assets/login/icon-tab-bg-2.png
apps/bMiniApp/src/assets/mine/icon-arrow.png
apps/bMiniApp/src/assets/mine/icon-bg.png
apps/bMiniApp/src/assets/mine/icon-card.png
apps/bMiniApp/src/assets/mine/icon-edit.png
apps/bMiniApp/src/assets/mine/icon-id-bg.png
apps/bMiniApp/src/assets/mine/icon-lamp.png
apps/bMiniApp/src/assets/mine/icon-menu-business.png
apps/bMiniApp/src/assets/mine/icon-menu-contact.png
apps/bMiniApp/src/assets/mine/icon-message.png
apps/bMiniApp/src/assets/mine/icon-setting.png
apps/bMiniApp/src/assets/mine/icon-unCertified.png
apps/bMiniApp/src/assets/setting/icon-account.png
apps/bMiniApp/src/assets/setting/icon-arrow.png
apps/bMiniApp/src/assets/setting/icon-coo.png
apps/bMiniApp/src/assets/setting/icon-loginout.png
apps/bMiniApp/src/assets/setting/icon-note.png
apps/bMiniApp/src/assets/setting/icon-toggle-bg.png
apps/bMiniApp/src/assets/setting/icon-warning.png
apps/bMiniApp/src/assets/setting/icon-wx.png
apps/bMiniApp/src/assets/tabbar/icon-follow-active.png
apps/bMiniApp/src/assets/tabbar/icon-follow.png
apps/bMiniApp/src/assets/tabbar/icon-friend-active.png
apps/bMiniApp/src/assets/tabbar/icon-friend.png
apps/bMiniApp/src/assets/tabbar/icon-home-active.png
apps/bMiniApp/src/assets/tabbar/icon-home.png
apps/bMiniApp/src/assets/tabbar/icon-information-active.png
apps/bMiniApp/src/assets/tabbar/icon-information.png
apps/bMiniApp/src/assets/tabbar/icon-message-active.png
apps/bMiniApp/src/assets/tabbar/icon-message.png
apps/bMiniApp/src/assets/tabbar/icon-mine-active.png
apps/bMiniApp/src/assets/tabbar/icon-mine.png
apps/bMiniApp/src/assets/tabbar/icon-product-active.png
apps/bMiniApp/src/assets/tabbar/icon-product.png
apps/bMiniApp/src/assets/tabbar/icon-publish.png
apps/bMiniApp/src/assets/user/icon-address.png
apps/bMiniApp/src/assets/user/icon-bg.png
apps/bMiniApp/src/assets/user/icon-email.png
apps/bMiniApp/src/assets/user/icon-my-attention.png
apps/bMiniApp/src/assets/user/icon-phone.png
apps/bMiniApp/src/components/Avatar/UserAvatar.vue
New file
@@ -0,0 +1,14 @@
<template>
  <Avatar :src="userDetail?.avatarUrl"></Avatar>
</template>
<script setup lang="ts">
import { Avatar } from '@12333/components';
import { useUser } from '@/hooks';
defineOptions({
  name: 'UserAvatar',
});
const { userDetail } = useUser();
</script>
apps/bMiniApp/src/components/Avatar/UserInfoAvatar.vue
New file
@@ -0,0 +1,95 @@
<template>
  <div class="user-info-avatar-wrapper">
    <Avatar :size="60" class="user-info-avatar" :src="src" />
    <div class="user-info">
      <div class="user-info-item-name-wrapper">
        <div class="user-info-item-name">{{ name }}</div>
        <template v-if="jobTitle">
          <div class="user-info-item-dot"></div>
          <div class="user-info-item-jobTitle">{{ jobTitle }}</div>
        </template>
      </div>
      <div class="user-info-item-company">{{ company }}</div>
    </div>
  </div>
</template>
<script setup lang="ts">
import { Avatar } from '@12333/components';
defineOptions({
  name: 'UserInfoAvatar',
});
type Props = {
  src?: string;
  name?: string;
  company?: string;
  jobTitle?: string;
};
const props = withDefaults(defineProps<Props>(), {});
</script>
<style lang="scss">
@import '@/styles/common.scss';
.user-info-avatar-wrapper {
  display: flex;
  flex: 1;
  min-width: 0;
  .user-info-avatar {
    margin-right: 24px;
  }
  .user-info {
    flex: 1;
    min-width: 0;
    display: flex;
    flex-direction: column;
    justify-content: space-between;
    padding: 12px 0;
    .user-info-item-name-wrapper {
      color: #ffffff;
      line-height: 44px;
      @include ellipsis;
      vertical-align: middle;
      font-size: 0;
    }
    .user-info-item-name {
      display: inline-block;
      font-weight: 600;
      font-size: 32px;
      vertical-align: middle;
    }
    .user-info-item-dot {
      display: inline-block;
      width: 4px;
      height: 4px;
      background: #ffffff;
      vertical-align: middle;
      border-radius: 50%;
      margin: 0 8px;
    }
    .user-info-item-jobTitle {
      display: inline-block;
      font-weight: 400;
      font-size: 28px;
      vertical-align: middle;
    }
    .user-info-item-company {
      font-weight: 400;
      font-size: 24px;
      color: #ffffff;
      line-height: 34px;
      @include ellipsis;
    }
  }
}
</style>
apps/bMiniApp/src/components/Button/LargeButton.vue
New file
@@ -0,0 +1,28 @@
<template>
  <nut-button class="large-button" type="primary">
    <template v-for="(item, key, i) in $slots" :key="i" v-slot:[key]>
      <slot :name="key"></slot>
    </template>
  </nut-button>
</template>
<script setup lang="ts">
defineOptions({
  name: 'LargeButton',
});
</script>
<style lang="scss">
@import '@/styles/common.scss';
.page-layout-wrapper {
  .large-button {
    display: block;
    height: 88px;
    font-size: 32px;
    font-weight: 400;
    color: #ffffff;
    line-height: 44px;
  }
}
</style>
apps/bMiniApp/src/components/Card/Card.vue
New file
@@ -0,0 +1,64 @@
<template>
  <div :class="['card-wrapper', { shadow, clickable: isLink }]">
    <slot />
  </div>
</template>
<script setup lang="ts">
defineOptions({
  name: 'Card',
});
type Props = {
  shadow?: boolean;
  isLink?: boolean;
};
withDefaults(defineProps<Props>(), {
  shadow: false,
  isLink: false,
});
</script>
<style lang="scss">
@import '@/styles/common.scss';
.card-wrapper {
  background: #ffffff;
  overflow: hidden;
  margin-bottom: 24px;
  position: relative;
  border-radius: 8px;
  &:last-child {
    margin-bottom: 0;
  }
  &.shadow {
    box-shadow: 0px 10px 30px 0px rgba(66, 66, 66, 0.1);
  }
  &:active::before {
    opacity: 0.1;
  }
  &.clickable {
    cursor: pointer;
    &::before {
      position: absolute;
      top: 50%;
      left: 50%;
      width: 100%;
      height: 100%;
      background-color: #000;
      border: inherit;
      border-color: #000;
      border-radius: inherit;
      transform: translate(-50%, -50%);
      opacity: 0;
      content: ' ';
    }
  }
}
</style>
apps/bMiniApp/src/components/Card/CommonCard.vue
New file
@@ -0,0 +1,146 @@
<template>
  <div class="common-card-wrapper">
    <div class="common-card-content">
      <div class="common-card-title-wrapper">
        <div class="common-card-title">{{ title }}</div>
        <slot name="title-right"></slot>
      </div>
      <slot></slot>
    </div>
    <div class="common-card-footer">
      <slot name="footer">
        <Avatar
          @click.stop="goUserHomePage"
          class="common-card-footer-avatar"
          :size="24"
          :src="src ? setOSSLink(src) : ''"
        />
        <div class="common-card-footer-name-wrapper">
          <div class="common-card-footer-name">{{ name }}</div>
          <template v-if="jobTitle">
            <div class="common-card-footer-dot"></div>
            <div class="common-card-footer-jobTitle">{{ jobTitle }}</div>
          </template>
          <div class="common-card-footer-time">{{ dayjs(time).format('MM-DD HH:mm') }}</div>
        </div>
      </slot>
    </div>
  </div>
</template>
<script setup lang="ts">
import { commonCardProps } from './cardProps';
import { Avatar } from '@12333/components';
import { setOSSLink } from '@12333/utils';
import dayjs from 'dayjs';
import Taro from '@tarojs/taro';
defineOptions({
  name: 'CommonCard',
});
const props = defineProps(commonCardProps);
function goUserHomePage() {
  if (props.userId) {
    Taro.navigateTo({
      url: `${RouterPath.userHomePage}?userId=${props.userId}`,
    });
  }
}
</script>
<style lang="scss">
@import '@/styles/common.scss';
.common-card-wrapper {
  background: #ffffff;
  border-radius: 8px;
  padding: 0 28px;
  margin-bottom: 24px;
  &:last-child {
    margin-bottom: 0;
  }
  .common-card-content {
    padding: 24px 0;
    border-bottom: 1px solid #f6f6f6;
    .common-card-title-wrapper {
      display: flex;
      align-items: center;
      margin-bottom: 24px;
      .common-card-title {
        flex: 1;
        min-width: 0;
        font-weight: 600;
        font-size: 32px;
        color: boleGetCssVar('text-color', 'primary');
        line-height: 44px;
        @include ellipsis;
      }
      .nut-button {
        height: 44rpx;
        font-size: 24rpx;
        padding: 0 30rpx;
      }
    }
  }
  .common-card-footer {
    padding: 14px 0;
    display: flex;
    align-items: center;
    .common-card-footer-avatar {
      margin-right: 16px;
    }
    .common-card-footer-name-wrapper {
      color: boleGetCssVar('text-color', 'primary');
      line-height: 34px;
      font-size: 0;
      display: flex;
      align-items: center;
      flex: 1;
      min-width: 0;
    }
    .common-card-footer-name {
      font-weight: 400;
      font-size: 24px;
      vertical-align: middle;
      @include ellipsis;
    }
    .common-card-footer-dot {
      width: 4px;
      height: 4px;
      background: boleGetCssVar('text-color', 'primary');
      vertical-align: middle;
      border-radius: 50%;
      margin: 0 8px;
      flex-shrink: 0;
    }
    .common-card-footer-jobTitle {
      font-weight: 400;
      font-size: 24px;
      vertical-align: middle;
      flex-shrink: 0;
    }
    .common-card-footer-time {
      font-weight: 400;
      font-size: 24px;
      vertical-align: middle;
      color: boleGetCssVar('text-color', 'secondary');
      margin-left: 16px;
      flex-shrink: 0;
    }
  }
}
</style>
apps/bMiniApp/src/components/Card/cardProps.ts
New file
@@ -0,0 +1,20 @@
export const commonCardProps = {
  title: {
    type: String,
  },
  src: {
    type: String,
  },
  name: {
    type: String,
  },
  jobTitle: {
    type: String,
  },
  time: {
    type: String,
  },
  userId: {
    type: String,
  },
};
apps/bMiniApp/src/components/Chunk/Cell.vue
New file
@@ -0,0 +1,74 @@
<template>
  <div class="bole-cell-wrapper">
    <div class="cell-title-wrapper">
      <slot name="title">
        <div :class="titleSize === 'normal' ? 'cell-title' : 'cell-title-large'">{{ title }}</div>
        <slot name="title-right"></slot>
      </slot>
    </div>
    <slot></slot>
  </div>
</template>
<script setup lang="ts">
defineOptions({
  name: 'Cell',
});
type Props = {
  title?: string;
  titleSize?: 'large' | 'normal';
};
const props = withDefaults(defineProps<Props>(), {
  titleSize: 'normal',
});
</script>
<style lang="scss">
@import '@/styles/common.scss';
.bole-cell-wrapper {
  background: #ffffff;
  border-radius: 8px;
  padding: 24px 28px;
  margin-bottom: 24px;
  .cell-title-wrapper {
    display: flex;
    align-items: center;
    margin-bottom: 24px;
    justify-content: space-between;
    .cell-title {
      font-weight: 600;
      font-size: 28px;
      color: boleGetCssVar('text-color', 'primary');
      line-height: 40px;
      position: relative;
      z-index: 1;
      @include ellipsis;
      &::after {
        content: '';
        width: 100%;
        height: 16px;
        background: linear-gradient(90deg, #cfe4ff 0%, rgba(207, 228, 255, 0) 100%);
        border-radius: 8px;
        position: absolute;
        bottom: 0;
        left: 0;
        z-index: -1;
      }
    }
    .cell-title-large {
      font-weight: 600;
      font-size: 32px;
      color: boleGetCssVar('text-color', 'primary');
      line-height: 44px;
      @include ellipsis;
    }
  }
}
</style>
apps/bMiniApp/src/components/Chunk/ChunkTitle.vue
New file
@@ -0,0 +1,43 @@
<template>
  <div class="chunk-title-wrapper">
    <div class="chunk-title-line"></div>
    <div class="chunk-title">{{ title }}</div>
  </div>
</template>
<script setup lang="ts">
defineOptions({
  name: 'ChunkTitle',
});
type Props = {
  title?: string;
};
const props = withDefaults(defineProps<Props>(), {});
</script>
<style lang="scss">
@import '@/styles/common.scss';
.chunk-title-wrapper {
  padding: 32px 0;
  display: flex;
  align-items: center;
  .chunk-title-line {
    width: 4px;
    height: 32px;
    background: linear-gradient(90deg, #7198fb 0%, #3a71ff 100%);
    border-radius: 2px;
    margin-right: 16px;
  }
  .chunk-title {
    font-weight: 600;
    font-size: 28px;
    color: boleGetCssVar('text-color', 'primary');
    line-height: 32px;
  }
}
</style>
apps/bMiniApp/src/components/InfiniteLoading/InfiniteLoading.vue
New file
@@ -0,0 +1,235 @@
<template>
  <scroll-view
    :scroll-y="true"
    :refresher-background="'transparent'"
    :lowerThreshold="100"
    @scrolltolower="lower"
    :refresherEnabled="refresherEnabled"
    :refresherTriggered="state.triggered"
    @refresherrefresh="onRefresherRefresh"
    :show-scrollbar="false"
    :style="scrollViewStyle"
    :enable-back-to-top="true"
    :class="[scrollViewClassName]"
    @scroll="onScroll"
    :scroll-top="scrollDistance"
    enhanced
    :scroll-with-animation="true"
    v-bind="{ ...$attrs }"
  >
    <slot name="header"></slot>
    <LoadingLayout :loading="isLoading" :error="isError" :loadError="() => refetch?.()">
      <NoData v-if="hasNoData" />
      <div
        :class="['infinite-list-inner', { noShowMoreText: !showMoreText, hasPaddingTop }]"
        v-else
      >
        <slot name="extra" />
        <slot v-if="$slots.default" />
        <template v-else>
          <template v-for="(group, index) in listData.pages" :key="index">
            <template v-for="(item, i) in group.data" :key="i">
              <slot
                name="renderItem"
                :item="item"
                :groupIndex="index"
                :itemIndex="i"
                :index="findDataIndex(item)"
              />
            </template>
          </template>
        </template>
      </div>
      <div
        v-if="!hasNoData && showMoreText && listData?.pages?.length > 0 && !hasMore"
        class="loading-more-tips"
      >
        {{ noMoreText }}
      </div>
      <div v-if="isFetching && hasMore && enabledLoadingMore" class="infiniting-tips">
        <Loading class="infiniting-tips-icon"></Loading>数据加载中...
      </div>
    </LoadingLayout>
  </scroll-view>
  <div class="back-top-wrapper" @click.stop="backToTop" v-show="oldScrollDistance > 100">
    <img class="back-top-img" :src="IconBackTop" />
    <div class="back-top-text">返回顶部</div>
  </div>
</template>
<script lang="ts" setup generic="T">
import { VNode, CSSProperties } from 'vue';
import NoData from '../NoData/NoData.vue';
import LoadingLayout from '../Layout/LoadingLayout.vue';
import { FetchNextPageOptions } from '@tanstack/vue-query';
import { Loading } from '@nutui/icons-vue-taro';
import { useScrollDistance } from 'senin-mini/hooks';
import IconBackTop from '@/assets/components/icon-back-top.png';
defineOptions({
  name: 'InfiniteLoading',
});
type Page = {
  data?: T[];
  pageModel?: {
    rows?: number;
    page?: number;
    totalCount?: number;
    totalPage?: number;
  };
  [key: string]: any;
};
type TData = {
  pages: Page[];
};
type Props = {
  // list?: TData;
  listData?: TData;
  flattenListData?: T[];
  renderItem?: (item: T, index: number) => VNode;
  refresherEnabled?: boolean;
  hasMore?: boolean;
  isLoading?: boolean;
  isError?: boolean;
  isFetching?: boolean;
  isFetchingNextPage?: boolean;
  refetch?: (options?: any) => Promise<any>;
  scrollViewStyle?: string | CSSProperties;
  scrollViewClassName?: string;
  fetchNextPage?: (options?: FetchNextPageOptions) => Promise<any>;
  showMoreText?: boolean;
  hasPaddingTop?: boolean;
  noMoreText?: string;
  enabledLoadingMore?: boolean;
  customNoData?: boolean;
};
const props = withDefaults(defineProps<Props>(), {
  renderItem: () => () => null,
  refresherEnabled: true,
  showMoreText: true,
  hasPaddingTop: false,
  noMoreText: '没有更多内容了~',
  enabledLoadingMore: true,
  customNoData: undefined,
});
const emit = defineEmits<{
  (e: 'refresh', done: () => any): void;
  (e: 'loadMore'): void;
}>();
const hasNoData = computed(() => {
  if (props.customNoData !== undefined) return props.customNoData;
  if (props.listData?.pages?.length) {
    return props.listData?.pages[0].data.length === 0;
  }
  return true;
});
const state = reactive({
  triggered: false,
});
function lower() {
  if (props.hasMore && props.enabledLoadingMore) {
    props.fetchNextPage?.();
    emit('loadMore');
  }
}
// eslint-disable-next-line no-unused-vars
async function onRefresherRefresh() {
  try {
    // 正处于刷新状态
    if (state.triggered) return;
    state.triggered = true;
    await props.refetch?.();
    state.triggered = false;
  } catch (error) {}
}
const { onScroll, scrollDistance, oldScrollDistance, setScrollDistance } = useScrollDistance();
function backToTop() {
  setScrollDistance(0);
}
const scrollToBottom = (dis = 300) => {
  setScrollDistance(scrollDistance.value + dis);
};
function findDataIndex(item: T) {
  return props.flattenListData?.findIndex((data) => data === item);
}
defineExpose({ backToTop, scrollToBottom });
</script>
<style lang="scss">
@import '@/styles/common.scss';
.loading-more-tips {
  color: boleGetCssVar('text-color', 'primary');
  padding: 18px 10px;
  width: auto;
  font-size: 24px;
  text-align: center;
}
.infinite-list-inner {
  // padding: 30px 30px 0;
  &.hasPaddingTop {
    padding-top: 20px;
  }
  &.noShowMoreText {
    padding-bottom: 30px;
  }
}
.infiniting-tips {
  color: boleGetCssVar('text-color', 'primary');
  padding: 18px 10px;
  width: auto;
  font-size: 24px;
  display: flex;
  align-items: center;
  justify-content: center;
  .infiniting-tips-icon {
    margin-right: 10px;
  }
}
.back-top-wrapper {
  width: 92px;
  height: 92px;
  background: #ffffff;
  box-shadow: 0px 0px 28px 0px rgba(0, 0, 0, 0.18);
  position: fixed;
  border-radius: 50%;
  right: boleGetCssVar('size', 'body-padding-h');
  bottom: 390px;
  .back-top-img {
    width: 44px;
    height: 44px;
    margin: 12px auto 2px;
  }
  .back-top-text {
    font-weight: 400;
    font-size: 16px;
    color: boleGetCssVar('text-color', 'regular');
    line-height: 22px;
    text-align: center;
  }
}
</style>
apps/bMiniApp/src/components/Layout/ContentScrollView.vue
New file
@@ -0,0 +1,54 @@
<template>
  <scroll-view class="content-scroll-view-wrapper" :class="{ hasPaddingTop }" :scroll-y="true">
    <ContentView
      :class="['content-scroll-view-wrapper-inner', props.allHeight ? 'all-height' : '']"
      :paddingH="paddingH"
    >
      <slot />
    </ContentView>
  </scroll-view>
</template>
<script setup lang="ts">
import ContentView from './ContentView.vue';
defineOptions({
  name: 'ContentScrollView',
});
type Props = {
  hasPaddingTop?: boolean;
  allHeight?: boolean;
  paddingH?: boolean;
};
const props = withDefaults(defineProps<Props>(), {
  hasPaddingTop: false,
  allHeight: false,
  paddingH: true,
});
</script>
<style lang="scss">
@import '@/styles/common.scss';
.content-scroll-view-wrapper {
  @include listScrollViewWithNoPadding;
  background-color: $body-background-color;
  &.hasPaddingTop {
    padding-top: 20px;
  }
  .content-scroll-view-wrapper-inner {
    @include ScrollViewInner;
    &.all-height {
      height: 100%;
      padding-bottom: 0;
      display: flex;
      flex-direction: column;
    }
  }
}
</style>
apps/bMiniApp/src/components/Layout/ContentView.vue
New file
@@ -0,0 +1,29 @@
<template>
  <div :class="['content-view-wrapper', { paddingH }]">
    <slot />
  </div>
</template>
<script setup lang="ts">
defineOptions({
  name: 'ContentView',
});
type Props = {
  paddingH?: boolean;
};
const props = withDefaults(defineProps<Props>(), {
  paddingH: true,
});
</script>
<style lang="scss">
@import '@/styles/common.scss';
.content-view-wrapper {
  &.paddingH {
    padding: 0 boleGetCssVar('size', 'body-padding-h');
  }
}
</style>
apps/bMiniApp/src/components/Layout/LoadingLayout.vue
New file
@@ -0,0 +1,58 @@
<template>
  <div v-if="loading" class="loading-layout-loading-content-wrapper">
    <IconFont name="loading" />
    <div class="list-empty-hint-text">数据加载中......</div>
  </div>
  <nut-empty
    v-else-if="error"
    class="loading-layout-error-wrapper"
    status="error"
    description="加载失败"
  >
    <div :style="{ marginTop: '10px' }">
      <nut-button type="primary" @click="loadError"> 重试 </nut-button>
    </div>
  </nut-empty>
  <template v-else>
    <NoData v-if="showNoData" />
    <slot v-else></slot>
  </template>
</template>
<script setup lang="ts">
import { loadingLayoutProps } from './layout';
import { IconFont } from '@nutui/icons-vue-taro';
import NoData from '../NoData/NoData.vue';
defineOptions({
  name: 'LoadingLayout',
});
const props = defineProps(loadingLayoutProps);
</script>
<style lang="scss">
@import '@/styles/common.scss';
.loading-layout-loading-content-wrapper {
  padding: 40px;
  display: flex;
  justify-content: center;
  align-items: center;
  .nut-icon {
    color: boleGetCssVar('text-color', 'primary');
    margin-right: 8px;
  }
  .list-empty-hint-text {
    line-height: 1;
    font-size: 30px;
    color: boleGetCssVar('text-color', 'primary');
  }
}
.loading-layout-error-wrapper {
  height: 100%;
}
</style>
apps/bMiniApp/src/components/Layout/PageLayout.vue
New file
@@ -0,0 +1,141 @@
<template>
  <Portal.Host>
    <div class="page-layout-wrapper" v-bind="$attrs">
      <slot v-if="showNavigationBar" name="navigationBar">
        <CommonNavigationBar v-bind="_commonNavigationBarProps" />
      </slot>
      <slot name="bg">
        <div
          v-if="hasLinearBg"
          class="page-layout-linear-bg"
          :style="{
            height: Taro.pxTransform(props.linearBgHeight),
          }"
        ></div>
      </slot>
      <div class="page-layout-scroll-view-wrapper" :style="{ height: scrollViewHeight }">
        <slot :scrollViewHeight="scrollViewHeight" v-if="isAuth"></slot>
        <!-- <template v-if="isAuth">
          <slot v-if="useView" :scrollViewHeight="scrollViewHeight"></slot>
          <scroll-view
            v-else
            class="page-scrollview"
            :scroll-y="true"
            :style="{ height: scrollViewHeight }"
          >
            <slot :scrollViewHeight="scrollViewHeight"></slot>
          </scroll-view>
        </template> -->
      </div>
      <div v-if="!pageHeightWithTabBar" class="safe-area-bottom"></div>
    </div>
  </Portal.Host>
</template>
<script setup lang="ts">
// import LoadingLayout from './LoadingLayout.vue';
// import { loadingLayoutProps } from './layout';
import CommonNavigationBar from '../NavigationBar/CommonNavigationBar.vue';
import { commonNavigationBarProps } from '../NavigationBar/commonNavigationBar';
import { useSystemStore } from '@/stores/modules/system';
import Taro from '@tarojs/taro';
import { TabBarPageRouter } from '@/constants';
import { useAuth } from '@/hooks';
import { Portal } from 'senin-mini/components';
import { usePickProps } from 'senin-mini/hooks';
defineOptions({
  name: 'PageLayout',
  inheritAttrs: false,
});
const props = defineProps({
  ...commonNavigationBarProps,
  needAuth: {
    type: Boolean,
    default: true,
  },
  useView: {
    type: Boolean,
    default: false,
  },
  hasLinearBg: {
    type: Boolean,
    default: false,
  },
  linearBgHeight: {
    type: Number,
    default: 388,
  },
});
const _commonNavigationBarProps = usePickProps(props, commonNavigationBarProps);
const { isAuth } = useAuth({
  needAuth: props.needAuth,
});
const systemStore = useSystemStore();
const router = Taro.useRouter();
const pageHeightWithTabBar = computed(() =>
  Object.values(TabBarPageRouter).some((x) => x.toLowerCase() === router.path.toLowerCase())
);
const navigationBarHeight = computed(
  () => systemStore.info.statusBarHeight + systemStore.navigationBarHeight
);
const scrollViewHeight = computed(() => {
  let pageHeight = pageHeightWithTabBar.value
    ? systemStore.pageHeightWithTab
    : systemStore.pageHeight;
  pageHeight = pageHeight + (props.showNavigationBar ? 0 : navigationBarHeight.value);
  return pageHeight + 'px';
});
Taro.getSetting({
  success: function (res) {
    if (!res.authSetting['scope.userLocation']) {
      Taro.authorize({
        scope: 'scope.userLocation',
      });
    }
  },
});
</script>
<style lang="scss">
@import '@/styles/common.scss';
.page-layout-wrapper {
  // background-color: $body-background-color;
  .page-layout-scroll-view-wrapper {
    display: flex;
    flex-direction: column;
    .page-scrollview {
      box-sizing: border-box;
    }
  }
  .page-layout-linear-bg {
    position: fixed;
    z-index: -1;
    top: 0;
    left: 0;
    width: 100%;
    background: linear-gradient(
      180deg,
      boleGetCssVar('color', 'primary') 0%,
      #5a86f6 56%,
      #f9f9fb 100%
    );
    filter: blur(0px);
    border-radius: 0px 0px 20px 20px;
  }
}
</style>
apps/bMiniApp/src/components/Layout/PageLayoutWithBg.vue
New file
@@ -0,0 +1,48 @@
<template>
  <PageLayout v-bind="props">
    <template #navigationBar>
      <TransparentNavigationBar :title="title" :is-absolute="false">
        <template #left>
          <slot name="left"></slot>
        </template>
      </TransparentNavigationBar>
    </template>
    <template #bg>
      <img :src="OssAssets.common.CommonPageBg" class="common-page-bg" />
    </template>
    <template #default>
      <slot />
    </template>
  </PageLayout>
</template>
<script setup lang="ts">
import PageLayout from './PageLayout.vue';
import TransparentNavigationBar from '../NavigationBar/TransparentNavigationBar.vue';
import _ from 'lodash';
import { OssAssets } from '@/constants';
defineOptions({
  name: 'PageLayoutWithBg',
});
type Props = {
  title?: string;
};
const props = withDefaults(defineProps<Props>(), {});
</script>
<style lang="scss">
@import '@/styles/common.scss';
.common-page-bg {
  position: fixed;
  z-index: -1;
  top: 0;
  left: 0;
  width: 100%;
  height: 516px;
  object-fit: cover;
}
</style>
apps/bMiniApp/src/components/Layout/layout.ts
New file
@@ -0,0 +1,19 @@
import { PropType } from 'vue';
export const loadingLayoutProps = {
  loading: {
    type: Boolean,
  },
  error: {
    type: Boolean,
  },
  showNoData: {
    type: Boolean,
  },
  loadError: {
    type: Function as PropType<(...args: any[]) => any>,
  },
  id: {
    type: String,
  },
};
apps/bMiniApp/src/components/Menu/Menu.vue
New file
@@ -0,0 +1,214 @@
<template>
  <view :class="classes">
    <view
      :id="'nut-menu__bar' + refRandomId"
      class="nut-menu__bar"
      :class="{ opened: opened, around }"
      ref="barRef"
    >
      <template v-for="(item, index) in children" :key="index">
        <view
          class="nut-menu__item"
          @click="!item.disabled && toggleItem(index)"
          :class="{ disabled: item.disabled, active: item.state.showPopup }"
          :style="{ color: item.state.showPopup ? activeColor : '' }"
        >
          <view class="nut-menu__title" :class="getClasses(item.state.showPopup)">
            <view class="nut-menu__title-text">{{ item.renderTitle() }}</view>
            <span class="nut-menu__title-icon">
              <slot name="icon">
                <RectUp v-if="direction === 'up'" :size="12" />
                <RectDown v-else :size="12" />
              </slot>
            </span>
          </view>
        </view>
      </template>
    </view>
    <slot></slot>
  </view>
</template>
<script lang="ts">
import Taro, { usePageScroll } from '@tarojs/taro';
import { RectUp, RectDown } from '@nutui/icons-vue-taro';
import { useTaroRect } from 'senin-mini/hooks';
import './menu.scss';
const componentName = 'nut-menu';
export default defineComponent({
  name: 'bl-menu',
  components: {
    RectDown,
    RectUp,
  },
  props: {
    activeColor: {
      type: String,
      default: '',
    },
    overlay: {
      type: Boolean,
      default: true as const,
    },
    lockScroll: {
      type: Boolean,
      default: true as const,
    },
    duration: {
      type: [Number, String],
      default: 0.3,
    },
    closeOnClickOverlay: {
      type: Boolean,
      default: true,
    },
    direction: {
      type: String,
      default: 'down',
    },
    scrollFixed: {
      type: [Boolean, String, Number],
      default: false,
    },
    titleClass: [String],
    around: {
      type: Boolean,
      default: false,
    },
  },
  setup(props) {
    const barRef = ref<HTMLElement>();
    const refRandomId = Math.random().toString(36).slice(-8);
    const offset = ref(0);
    const isScrollFixed = ref(false);
    const useChildren = () => {
      const publicChildren: any[] = reactive([]);
      const internalChildren: any[] = reactive([]);
      const linkChildren = (value?: any) => {
        const link = (child: any) => {
          if (child.proxy) {
            internalChildren.push(child);
            publicChildren.push(child.proxy as any);
          }
        };
        const removeLink = (child: any) => {
          if (child.proxy) {
            let internalIndex = internalChildren.indexOf(child);
            if (internalIndex > -1) {
              internalChildren.splice(internalIndex, 1);
            }
            let publicIndex = publicChildren.indexOf(child.proxy);
            if (internalIndex > -1) {
              publicChildren.splice(publicIndex, 1);
            }
          }
        };
        provide(
          'menuParent',
          Object.assign(
            {
              removeLink,
              link,
              children: publicChildren,
              internalChildren,
            },
            value
          )
        );
      };
      return {
        children: publicChildren,
        linkChildren,
      };
    };
    const { children, linkChildren } = useChildren();
    const opened = computed(() => children.some((item) => item.state.showWrapper));
    const classes = computed(() => {
      const prefixCls = componentName;
      return {
        [prefixCls]: true,
        'scroll-fixed': isScrollFixed.value,
        'bole-menu-wrapper': true,
      };
    });
    const updateOffset = (children: any) => {
      if (barRef.value) {
        setTimeout(() => {
          useTaroRect(barRef, Taro).then((rect: any) => {
            if (props.direction === 'down') {
              offset.value = rect.bottom;
            } else {
              offset.value = Taro.getSystemInfoSync().windowHeight - rect.top;
            }
            children.toggle();
          });
        }, 100);
      }
    };
    linkChildren({ props, offset });
    const toggleItem = (active: number) => {
      children.forEach((item, index) => {
        if (index === active) {
          updateOffset(item);
        } else if (item.state.showPopup) {
          item.toggle(false, { immediate: true });
        }
      });
    };
    const onScroll = (res: { scrollTop: number }) => {
      const { scrollFixed } = props;
      const scrollTop = res.scrollTop;
      isScrollFixed.value =
        scrollTop > (typeof scrollFixed === 'boolean' ? 30 : Number(scrollFixed));
    };
    const getClasses = (showPopup: boolean) => {
      let str = '';
      const { titleClass } = props;
      if (showPopup) {
        str += 'active';
      }
      if (titleClass) {
        str += ` ${titleClass}`;
      }
      return str;
    };
    usePageScroll((res) => {
      const { scrollFixed } = props;
      if (scrollFixed) {
        onScroll(res);
      }
    });
    return {
      toggleItem,
      children,
      opened,
      classes,
      barRef,
      refRandomId,
      getClasses,
    };
  },
});
</script>
apps/bMiniApp/src/components/Menu/MenuItem.vue
New file
@@ -0,0 +1,220 @@
<template>
  <view class="nut-menu-item" v-show="state.showWrapper" :style="style">
    <view
      v-show="state.showPopup"
      @click="handleClickOutside"
      class="nut-menu-item-placeholder-element"
      :style="placeholderElementStyle"
      :catch-move="parent.props.lockScroll"
    >
    </view>
    <nut-popup
      :style="{ position: 'absolute' }"
      :overlayStyle="{ position: 'absolute' }"
      v-bind="$attrs"
      v-model:visible="state.showPopup"
      :position="parent.props.direction === 'down' ? 'top' : 'bottom'"
      :duration="parent.props.duration"
      :destroy-on-close="false"
      :overlay="parent.props.overlay"
      :lockScroll="parent.props.lockScroll"
      @closed="handleClose"
      :close-on-click-overlay="parent.props.closeOnClickOverlay"
    >
      <scroll-view :scroll-y="true">
        <view class="nut-menu-item__content" :class="{ noPadding: !options?.length }">
          <view
            v-for="(option, index) in options"
            :key="index"
            class="nut-menu-item__option"
            :class="[{ active: optionIsActive(option) }]"
            :style="{ 'flex-basis': 100 / cols + '%' }"
            @click="onClick(option)"
          >
            <span
              class="nut-menu-item__span"
              v-if="optionIsActive(option)"
              :class="[optionIsActive(option) ? activeTitleClass : inactiveTitleClass]"
            >
              <slot name="icon">
                <Check v-bind="$attrs" :color="parent.props.activeColor"></Check>
              </slot>
            </span>
            <view
              :class="[optionIsActive(option) ? activeTitleClass : inactiveTitleClass]"
              :style="{ color: optionIsActive(option) ? parent.props.activeColor : '' }"
              >{{ option.text }}</view
            >
          </view>
        </view>
        <slot></slot>
      </scroll-view>
    </nut-popup>
  </view>
</template>
<script lang="ts">
import { MenuItemOption } from '@nutui/nutui-taro/dist/types/__VUE/menuitem/type';
import { Check } from '@nutui/icons-vue-taro';
import { isArray } from 'lodash';
export default defineComponent({
  name: 'bl-menu-item',
  props: {
    title: String,
    options: {
      type: Array as PropType<MenuItemOption[]>,
      default: () => [] as MenuItemOption[],
    },
    disabled: {
      type: Boolean,
      default: false,
    },
    modelValue: {
      type: [Array, String, Number],
    },
    cols: {
      type: Number,
      default: 1,
    },
    activeTitleClass: String,
    inactiveTitleClass: String,
    emptyValue: {
      type: [String, Number],
      default: null,
    },
    emptyTitle: {
      type: String,
      default: '',
    },
    enableCancelSelect: {
      type: Boolean,
      default: true,
    },
    multiple: {
      type: Boolean,
      default: false,
    },
  },
  components: {
    Check,
  },
  emits: ['update:modelValue', 'change', 'closePopup'],
  setup(props, { emit }) {
    const state = reactive({
      showPopup: false,
      showWrapper: false,
    });
    const useParent: any = () => {
      const parent = inject('menuParent', null);
      if (parent) {
        // 获取子组件自己的实例
        const instance = getCurrentInstance()!;
        const { link, removeLink } = parent;
        // @ts-ignore
        link(instance);
        onUnmounted(() => {
          // @ts-ignore
          removeLink(instance);
        });
        return { parent };
      }
    };
    const { parent } = useParent();
    const style = computed(() => {
      return parent.props.direction === 'down'
        ? { top: parent.offset.value + 'px' }
        : { bottom: parent.offset.value + 'px' };
    });
    const placeholderElementStyle = computed(() => {
      const heightStyle = { height: parent.offset.value + 'px' };
      if (parent.props.direction === 'down') {
        return { ...heightStyle, top: '0px' };
      } else {
        return { ...heightStyle, bottom: '0px' };
      }
    });
    const toggle = (show = !state.showPopup) => {
      if (show === state.showPopup) {
        return;
      }
      state.showPopup = show;
      if (show) {
        state.showWrapper = true;
      }
    };
    const renderTitle = () => {
      if (props.title) {
        return props.title;
      }
      if (isArray(props.modelValue)) {
        const selectedOptions = (props.options ?? [])
          .filter((option) => (props.modelValue as any).includes(option.value))
          .map((x) => x.text);
        return selectedOptions.length > 0 ? selectedOptions.join(',') : props.emptyTitle;
      }
      const match: any = props.options?.find((option: any) => option.value === props.modelValue);
      return match ? match.text : props.emptyTitle;
    };
    const onClick = (option: MenuItemOption) => {
      console.log(1);
      state.showPopup = false;
      if (props.multiple) {
        const modelValue = props.modelValue as Array<any>;
        const val = modelValue.includes(option.value)
          ? modelValue.filter((x) => x !== option.value)
          : [...modelValue, option.text];
        console.log('val: ', val);
        emit('update:modelValue', val);
        emit('change', val);
      } else {
        if (option.value !== props.modelValue) {
          emit('update:modelValue', option.value);
          emit('change', option.value);
        } else {
          if (props.enableCancelSelect) {
            emit('update:modelValue', props.emptyValue);
            emit('change', props.emptyValue);
          }
        }
      }
    };
    const handleClose = () => {
      state.showWrapper = false;
    };
    const handleClickOutside = () => {
      state.showPopup = false;
      emit('closePopup');
    };
    function optionIsActive(option: MenuItemOption) {
      return isArray(props.modelValue)
        ? props.modelValue.includes(option.value)
        : option.value === props.modelValue;
    }
    return {
      style,
      placeholderElementStyle,
      renderTitle,
      state,
      parent,
      toggle,
      onClick,
      handleClose,
      handleClickOutside,
      optionIsActive,
    };
  },
});
</script>
apps/bMiniApp/src/components/Menu/menu.scss
New file
@@ -0,0 +1,41 @@
@import '@/styles/common.scss';
.bole-menu-wrapper {
  font-size: 24px !important;
  color: boleGetCssVar('text-color', 'primary');
  .nut-menu__title-icon {
    color: #000;
  }
  .nut-menu__title.active {
    .nut-menu__title-icon {
      color: boleGetCssVar('color', 'primary');
    }
  }
  &.nut-menu {
    .nut-menu__bar {
      box-shadow: none;
      padding: 0 48rpx;
      justify-content: space-between;
      .nut-menu__item {
        flex: none;
        .nut-menu__title-text {
          padding-left: 0;
          font-size: 24rpx;
          color: #000;
        }
      }
      &.around {
        padding: 0 96rpx;
      }
    }
    .nut-menu-item__content {
      &.noPadding {
        padding: 0;
      }
    }
  }
}
apps/bMiniApp/src/components/NavigationBar/CommonNavigationBar.vue
New file
@@ -0,0 +1,104 @@
<template>
  <NavBar v-bind="props">
    <div
      :class="['common-navigation-bar-wrapper', { dark: props.mode == 'dark' }]"
      :style="barStyle"
    >
      <div
        class="menu-btn-wrapper"
        v-if="(!isLastPage || !isTabbarPage) && showLeftArrow"
        @click="handleBack()"
      >
        <img class="menu-btn" :src="props.mode == 'dark' ? IconArrowWhite : IconArrow" />
      </div>
      <span class="common-navigation-bar-title">{{ title }}</span>
    </div>
  </NavBar>
</template>
<script setup lang="ts">
import NavBar from './NavBar.vue';
import { commonNavigationBarProps } from './commonNavigationBar';
import { useSystemStore } from '@/stores/modules/system';
import { CSSProperties } from 'vue';
import IconArrow from '@/assets/common/icon-navi-arrow.png';
import IconArrowWhite from '@/assets/common/icon-navi-arrow-white.png';
import Taro from '@tarojs/taro';
import { goBack } from '@/utils';
import { TabBarPageRouter } from '@/constants';
defineOptions({
  name: 'CommonNavigationBar',
});
const systemStore = useSystemStore();
const props = defineProps(commonNavigationBarProps);
const router = Taro.useRouter();
const isLastPage = computed(() => {
  const pages = Taro.getCurrentPages();
  return pages.length <= 1;
});
const isTabbarPage = computed(() =>
  Object.values(TabBarPageRouter).some((x) => x.toLowerCase() === router.path.toLowerCase())
);
const barStyle = computed(() => {
  const distance = systemStore.menuButtonWidth + systemStore.menuButtonRightDistance + 4;
  return {
    paddingLeft: `${distance}px`,
    paddingRight: `${distance}px`,
    height: systemStore.navigationBarHeight + 'px',
  } as CSSProperties;
});
function handleBack() {
  if (props.backFn) {
    props.backFn();
  } else {
    goBack();
  }
}
</script>
<style lang="scss">
@import '@/styles/common.scss';
.common-navigation-bar-wrapper {
  width: 100%;
  line-height: 1;
  font-size: 32px;
  color: boleGetCssVar('color', 'title-color');
  min-width: 0;
  position: relative;
  align-items: center;
  display: flex;
  justify-content: center;
  .common-navigation-bar-title {
    @include ellipsis;
    font-weight: 600;
  }
  &.dark {
    color: #fff;
  }
  .menu-btn-wrapper {
    padding: 20px;
    padding-left: 0;
    position: absolute;
    left: boleGetCssVar('size', 'body-padding-h');
    // top: -20px;
  }
  .menu-btn {
    width: 20px;
    height: 30px;
  }
}
</style>
apps/bMiniApp/src/components/NavigationBar/LargeTitleNavigationBar.vue
New file
@@ -0,0 +1,61 @@
<template>
  <NavBar v-bind="props" class="large-title-navigation-bar">
    <div :class="['large-title-navigation-bar-wrapper']" :style="barStyle">
      <slot name="title">
        <span class="large-title-navigation-bar-title">{{ title }}</span>
      </slot>
    </div>
  </NavBar>
</template>
<script setup lang="ts">
import NavBar from './NavBar.vue';
import { commonNavigationBarProps } from './commonNavigationBar';
import { useSystemStore } from '@/stores/modules/system';
import { CSSProperties } from 'vue';
// import Taro from '@tarojs/taro';
defineOptions({
  name: 'LargeTitleNavigationBar',
});
const systemStore = useSystemStore();
const props = defineProps(commonNavigationBarProps);
const barStyle = computed(() => {
  const distance = systemStore.menuButtonWidth + systemStore.menuButtonRightDistance + 4;
  return {
    // paddingLeft: `${distance}px`,
    paddingRight: `${distance}px`,
    height: systemStore.navigationBarHeight + 'px',
  } as CSSProperties;
});
</script>
<style lang="scss">
@import '@/styles/common.scss';
.large-title-navigation-bar {
  background-color: transparent;
  position: relative;
  z-index: 1;
}
.large-title-navigation-bar-wrapper {
  width: 100%;
  line-height: 1;
  font-size: 40px;
  color: #fff;
  min-width: 0;
  position: relative;
  align-items: center;
  display: flex;
  font-weight: bold;
  padding-left: 30px;
  .large-title-navigation-bar-title {
    @include ellipsis;
  }
}
</style>
apps/bMiniApp/src/components/NavigationBar/NavBar.vue
New file
@@ -0,0 +1,58 @@
<template>
  <div
    :class="[
      'navigation-bar-wrapper',
      { active: props.mode === 'dark', plain: props.plain, hasBorder: props.hasBorder },
    ]"
    :style="barStyle"
  >
    <slot></slot>
  </div>
</template>
<script setup lang="ts">
import { CSSProperties } from 'vue';
import { useSystemStore } from '@/stores/modules/system';
import { navigationBarProps } from './navBar';
defineOptions({
  name: 'NavBar',
});
const props = defineProps(navigationBarProps);
const systemStore = useSystemStore();
const barStyle = computed(
  () =>
    ({
      paddingTop: systemStore.info.statusBarHeight + 'px',
      // height: systemStore.navigationBarHeight + 'px',
    } as CSSProperties)
);
</script>
<style lang="scss">
@import '@/styles/common.scss';
.navigation-bar-wrapper {
  background-color: #fff;
  display: flex;
  position: relative;
  // box-shadow: 0px 1px 7px 0px rgb(237, 238, 241);
  z-index: 10;
  &.plain {
    border-bottom-left-radius: 20px;
    border-bottom-right-radius: 20px;
  }
  &.active {
    background-color: boleGetCssVar('color', 'primary');
  }
  &.hasBorder {
    border-bottom: 1px solid #f6f6f6;
  }
}
</style>
apps/bMiniApp/src/components/NavigationBar/TransparentNavigationBar.vue
New file
@@ -0,0 +1,77 @@
<template>
  <NavBar v-bind="props" dark class="transparent-navigation-bar" :style="wrapperStyle">
    <div :class="['common-navigation-bar-wrapper', { dark: mode == 'dark' }]" :style="barStyle">
      <slot name="left">
        <div
          class="menu-btn-wrapper"
          v-if="(!isLastPage || !isTabbarPage) && showLeftArrow"
          @click="goBack()"
        >
          <img v-if="props.navigationArrowWhite" class="menu-btn" :src="IconArrowWhite" />
          <img v-else class="menu-btn" :src="IconArrow" />
        </div>
      </slot>
      <span class="common-navigation-bar-title">{{ title }}</span>
    </div>
  </NavBar>
</template>
<script setup lang="ts">
import NavBar from './NavBar.vue';
import { commonNavigationBarProps } from './commonNavigationBar';
import { useSystemStore } from '@/stores/modules/system';
import { CSSProperties } from 'vue';
import IconArrow from '@/assets/common/icon-navi-arrow.png';
import IconArrowWhite from '@/assets/common/icon-navi-arrow-white.png';
import Taro from '@tarojs/taro';
import { goBack } from '@/utils';
import { TabBarPageRouter } from '@/constants';
defineOptions({
  name: 'TransparentNavigationBar',
});
const systemStore = useSystemStore();
const props = defineProps(commonNavigationBarProps);
const router = Taro.useRouter();
const isLastPage = computed(() => {
  const pages = Taro.getCurrentPages();
  return pages.length <= 1;
});
const isTabbarPage = computed(() =>
  Object.values(TabBarPageRouter).some((x) => x.toLowerCase() === router.path.toLowerCase())
);
const barStyle = computed(() => {
  const distance = systemStore.menuButtonWidth + systemStore.menuButtonRightDistance + 4;
  return {
    paddingLeft: `${distance}px`,
    paddingRight: `${distance}px`,
    height: systemStore.navigationBarHeight + 'px',
  } as CSSProperties;
});
const wrapperStyle = computed(() => {
  return props.isAbsolute
    ? ({
        position: 'absolute',
      } as CSSProperties)
    : {};
});
</script>
<style lang="scss">
.transparent-navigation-bar.navigation-bar-wrapper {
  background-color: transparent;
  /* position: absolute; */
  width: 100%;
  .common-navigation-bar-title {
    height: 36px;
  }
}
</style>
apps/bMiniApp/src/components/NavigationBar/commonNavigationBar.ts
New file
@@ -0,0 +1,28 @@
import { navigationBarProps } from './navBar';
export const commonNavigationBarProps = {
  title: {
    type: String,
    default: '',
  },
  showLeftArrow: {
    type: Boolean,
    default: true,
  },
  showNavigationBar: {
    type: Boolean,
    default: true,
  },
  navigationArrowWhite: {
    type: Boolean,
    default: false,
  },
  isAbsolute: {
    type: Boolean,
    default: true,
  },
  backFn: {
    type: Function,
  },
  ...navigationBarProps,
};
apps/bMiniApp/src/components/NavigationBar/navBar.ts
New file
@@ -0,0 +1,14 @@
export const navigationBarProps = {
  mode: {
    type: String as PropType<'light' | 'dark'>,
    default: 'light',
  },
  plain: {
    type: Boolean,
    default: false,
  },
  hasBorder: {
    type: Boolean,
    default: false,
  },
};
apps/bMiniApp/src/components/NoData/NoData.vue
New file
@@ -0,0 +1,44 @@
<template>
  <div class="no-data-wrapper">
    <img class="no-data-img" :src="NoDataImage" alt="" />
    <span class="no-data-text">暂无数据</span>
  </div>
</template>
<script lang="ts">
import { defineComponent } from 'vue';
import { NoDataImage } from '@12333/constants';
export default defineComponent({
  name: 'NoData',
  setup() {
    return {
      NoDataImage,
    };
  },
});
</script>
<style lang="scss">
.no-data-wrapper {
  display: flex;
  width: 100%;
  height: 100%;
  justify-content: center;
  align-items: center;
  flex-direction: column;
  .no-data-img {
    width: 284px;
    height: 202px;
  }
  .no-data-text {
    font-size: 20px;
    color: #333333;
    line-height: 2.4;
  }
}
</style>
apps/bMiniApp/src/components/PageFooter/PageFooter.vue
New file
@@ -0,0 +1,177 @@
<template>
  <div :class="['page-footer', { isOnlyAction }]">
    <div class="page-footer-inner">
      <slot></slot>
    </div>
  </div>
</template>
<script setup lang="ts">
defineOptions({
  name: 'PageFooter',
});
type Props = {
  isOnlyAction?: boolean;
};
const props = withDefaults(defineProps<Props>(), {
  isOnlyAction: true,
});
</script>
<style lang="scss">
@import '@/styles/common.scss';
.page-footer {
  /* height: 112px; */
  background-color: #fff;
  //   position: fixed;
  //   bottom: 0;
  width: 100%;
  display: flex;
  box-shadow: $base-footer-box-shadow;
  position: relative;
  z-index: 1;
  //   padding-bottom: constant(safe-area-inset-bottom);
  //   padding-bottom: env(safe-area-inset-bottom);
  // z-index: 10000;
  &::after {
    content: '';
    position: absolute;
    left: 0;
    right: 0;
    bottom: 0;
    transform: translateY(100%);
    padding-bottom: constant(safe-area-inset-bottom);
    padding-bottom: env(safe-area-inset-bottom);
    background-color: #fff;
  }
  .page-footer-inner {
    padding: 24px 0;
    width: 100%;
    display: flex;
    box-sizing: border-box;
    align-items: center;
  }
  &.isOnlyAction {
    .page-footer-inner {
      padding: 16px 0;
      align-items: flex-start;
    }
  }
  .is-button-footer {
    display: flex;
    width: 100%;
    height: 100%;
    padding: 25px 30px;
    box-sizing: border-box;
    .common-page-footer-btn-group {
      margin: 0 -12rpx;
      display: flex;
      width: calc(100% + 24rpx);
    }
    .nut-button {
      flex: 1;
      margin: 0 12rpx;
      height: 100%;
      font-size: 32rpx;
      border-radius: 10rpx;
      border: none;
      font-weight: 400;
      &.cancel-btn {
        color: boleGetCssVar('text-color', 'primary') !important;
      }
      &.confirm-btn {
        box-shadow: 0px 3px 7px 0px rgba(240, 67, 73, 0.35);
      }
    }
  }
  .common-page-footer {
    display: flex;
    width: 100%;
    height: 100%;
    align-items: center;
    .common-page-footer-actions {
      flex: 1;
      display: flex;
      justify-content: space-around;
      min-width: 0;
      padding-right: 20px;
      .common-page-footer-action {
        display: flex;
        flex-direction: column;
        justify-content: center;
        align-items: center;
        .common-page-footer-action-icon {
          width: 35px;
          height: 35px;
          margin-bottom: 14px;
        }
        .common-page-footer-action-text {
          line-height: 1;
          font-size: 22px;
          color: #1b232f;
        }
      }
    }
    .common-page-footer-btn-group {
      display: flex;
      margin: 0 -20rpx;
      width: auto;
      .nut-button {
        margin: 0 20rpx;
      }
      &.small {
        margin: 0 -12rpx;
        .nut-button {
          margin: 0 12rpx;
        }
      }
      .one-btn {
        width: 364px;
        font-size: 26px;
        border-radius: 36px;
      }
    }
    .common-page-footer-btn-badge {
      z-index: 10;
    }
    .common-page-footer-btn {
      width: 200px;
      height: 80px;
      border-radius: 10px;
      min-width: 0;
      font-size: 32px;
      flex: none;
    }
    .contact-btn {
      margin: 0;
      margin-left: 20px;
    }
  }
}
</style>
apps/bMiniApp/src/components/PageFooter/PageFooterAction.vue
New file
@@ -0,0 +1,67 @@
<template>
  <button :class="['page-footer-action', { isFlex }]">
    <img :src="icon" class="page-footer-action-icon" />
    <div class="page-footer-action-text">{{ text }}</div>
  </button>
</template>
<script setup lang="ts">
defineOptions({
  name: 'PageFooterAction',
});
type Props = {
  isFlex?: boolean;
  icon?: string;
  text?: string;
};
const props = withDefaults(defineProps<Props>(), {
  isFlex: true,
});
</script>
<style lang="scss">
@import '@/styles/common.scss';
.page-footer-action {
  display: flex;
  flex-direction: column;
  align-items: center;
  background-color: transparent;
  border-radius: 0;
  outline: none;
  border: none;
  padding: 0;
  appearance: none;
  user-select: none;
  margin: 0 28px;
  &::after {
    display: none;
  }
  &.isFlex {
    flex: 1;
    min-width: 0;
    margin: 0;
    & + .page-footer-action.isFlex {
      border-left: 1px solid #ebebeb;
    }
  }
  .page-footer-action-icon {
    width: 40px;
    height: 40px;
    margin-bottom: 4px;
  }
  .page-footer-action-text {
    font-weight: 400;
    font-size: 24px;
    color: boleGetCssVar('text-color', 'regular');
    line-height: 34px;
  }
}
</style>
apps/bMiniApp/src/components/PageFooter/PageFooterBtn.vue
New file
@@ -0,0 +1,34 @@
<template>
  <nut-button class="page-footer-btn">
    <slot></slot>
  </nut-button>
</template>
<script setup lang="ts">
defineOptions({
  name: 'PageFooterBtn',
});
// type Props = {
//   text;
// };
// const props = withDefaults(defineProps<Props>(), {});
</script>
<style lang="scss">
@import '@/styles/common.scss';
.page-footer-btn {
  flex: 1;
  min-width: 0;
  height: 88px;
  font-size: 32px;
  margin: 0 28px;
  border-radius: 44px;
  &.nut-button--plain {
    border-width: 1px;
  }
}
</style>
apps/bMiniApp/src/components/Policy/Policy.vue
New file
@@ -0,0 +1,89 @@
<template>
  <div class="policy-wrapper">
    <nut-radio-group v-model="innerModelValue">
      <BlRadio :label="true">
        <div class="policy-content">
          {{ props.policyBtnText }}
          <div class="policy-content-btn" @click.stop="goPolicy">《用户协议和隐私政策》</div>
        </div>
      </BlRadio>
    </nut-radio-group>
  </div>
</template>
<script setup lang="ts">
import { Radio as BlRadio } from '@12333/components';
import Taro from '@tarojs/taro';
defineOptions({
  name: 'Policy',
});
const props = defineProps<{
  modelValue: boolean;
  policyBtnText?: string;
}>();
const emit = defineEmits<{
  (e: 'update:modelValue', value: boolean): void;
}>();
const innerModelValue = computed({
  get() {
    return props.modelValue;
  },
  set(val) {
    emit('update:modelValue', val);
  },
});
function goPolicy() {
  Taro.navigateTo({
    url: RouterPath.userPolicy,
  });
}
</script>
<style lang="scss">
@import '@/styles/common.scss';
.policy-wrapper {
  text-align: center;
  padding: 0 64px;
  .nut-radio-group {
    vertical-align: middle;
    .nutui-iconfont {
      font-size: 12px;
      height: 16px !important;
      width: 16px !important;
    }
    .bl-radio {
      align-items: flex-start;
    }
    .nut-radio__icon--unchecked {
      color: boleGetCssVar('text-color', 'secondary');
    }
  }
  .nut-radio__label {
    margin-left: 2px;
  }
  .policy-content {
    font-size: 24px;
    color: boleGetCssVar('text-color', 'secondary');
    line-height: 30px;
    text-align: left;
    word-break: break-all;
    .policy-content-btn {
      color: boleGetCssVar('color', 'primary');
      display: inline;
    }
  }
}
</style>
apps/bMiniApp/src/components/RichEditCard/RichContent.vue
New file
@@ -0,0 +1,46 @@
<template>
  <div :class="['rich-edit-content', size]">
    <template v-for="(item, index) in content" :key="index">
      <AutoWidthImage
        v-if="item.type === EditorType.Image"
        wrapperClassName="rich-content-item rich-content-image-item"
        :src="setOSSLink(item.path)"
      />
      <Video
        v-else-if="item.type === EditorType.Video"
        class="rich-content-item rich-content-video-item"
        :src="setOSSLink(item.path)"
      ></Video>
      <RichEditorContent
        v-else-if="item.type === EditorType.Rich || item.type === EditorType.WXContent"
        :content="item.content"
      ></RichEditorContent>
      <div v-else class="rich-content-item rich-content-text-item">
        {{ item.content }}
      </div>
    </template>
  </div>
</template>
<script setup lang="ts">
import { AutoWidthImage } from '@12333/components';
import { EditorType } from '@12333/constants';
import { setOSSLink } from '@12333/utils';
import { Video } from '@tarojs/components';
import RichEditorContent from '../RichEditor/RichEditorContent.vue';
// import {} from '@nutui/nutui-taro/dist/packages/video'
defineOptions({
  name: 'RichContent',
});
type Props = {
  content?: API.IntroInfo[];
  size?: 'small' | 'default' | 'large';
};
const props = withDefaults(defineProps<Props>(), {
  content: () => [],
  size: 'default',
});
</script>
apps/bMiniApp/src/components/RichEditCard/RichEditCard.vue
New file
@@ -0,0 +1,137 @@
<template>
  <Card class="rich-edit-card">
    <div class="rich-edit-card-title">{{ title }}</div>
    <slot>
      <RichContent v-if="content.length > 0" :content="content" />
      <div class="rich-edit-card-add-wrapper" @click="handleClick">
        <img :src="AddIcon" class="rich-edit-card-add-icon" />
        <div class="rich-edit-card-add-text">可添加图文介绍</div>
        <div class="rich-edit-card-add-danger">去编辑</div>
      </div>
    </slot>
  </Card>
</template>
<script setup lang="ts">
import Card from '../Card/Card.vue';
import AddIcon from '@/assets/components/rich-card/icon-add.png';
import Taro from '@tarojs/taro';
import RichContent from './RichContent.vue';
import { EmptyTextEditorItem } from '@12333/constants';
defineOptions({
  name: 'RichEditCard',
});
type Props = {
  title?: string;
  content?: API.IntroInfo[];
};
const props = withDefaults(defineProps<Props>(), {
  content: () => [],
});
const emit = defineEmits<{
  (e: 'update:content', content: Props['content']): void;
}>();
function handleClick() {
  Taro.navigateTo({
    url: RouterPath.editRichContent,
    events: {
      addRichContent: function (data: { content: API.IntroInfo[] }) {
        console.log('EditRichContent onChange', data.content);
        emit(
          'update:content',
          data.content.length > 0 ? data.content : [{ ...EmptyTextEditorItem }]
        );
      },
    },
    success: function (res) {
      res.eventChannel.emit('acceptRichContent', { content: props.content });
    },
  });
}
</script>
<style lang="scss">
@import '@/styles/common.scss';
.rich-edit-card {
  padding: 28px 32px;
  .rich-edit-card-title {
    margin-bottom: 20px;
    font-size: 28px;
    color: boleGetCssVar('text-color', 'primary');
    // font-weight: bold;
  }
  .rich-edit-card-add-wrapper {
    margin-top: 32px;
    display: flex;
    justify-content: center;
    align-items: center;
    .rich-edit-card-add-icon {
      width: 20px;
      height: 20px;
      margin-right: 10px;
    }
    .rich-edit-card-add-text,
    .rich-edit-card-add-danger {
      line-height: 1;
      font-size: 26px;
    }
    .rich-edit-card-add-text {
      color: #8c8c8c;
      margin-right: 6px;
    }
    .rich-edit-card-add-danger {
      color: boleGetCssVar('color', 'primary');
    }
  }
  .nut-textarea {
    padding: 0;
  }
}
.rich-edit-content {
  .rich-content-item {
    margin-bottom: 10px;
    &:last-child {
      margin-bottom: 0;
    }
  }
  .rich-content-image-item {
    display: block;
  }
  .rich-content-text-item {
    word-break: break-all;
    white-space: pre-line;
    font-size: 30px;
    line-height: 50px;
    color: boleGetCssVar('text-color', 'primary');
  }
  .rich-content-video-item {
    width: 100%;
    height: 300px;
  }
  &.small {
    .rich-content-text-item {
      font-size: 24px;
      line-height: 36px;
    }
  }
}
</style>
apps/bMiniApp/src/components/RichEditor/RichEditorContent.vue
New file
@@ -0,0 +1,59 @@
<template>
  <div class="rich-text-wrapper">
    <rich-text :nodes="_content" style="word-wrap: break-word"></rich-text>
  </div>
</template>
<script setup lang="ts">
defineOptions({
  name: 'RichEditorContent',
});
type Props = {
  content: string;
};
const _content = computed(() =>
  props.content.replace(/<img[^>]*>/g, (match) => {
    let str = match.replace(`width=""`, '').replace(`height=""`, '').replace(`style=""`, '');
    if (/style="/.test(str)) {
      str = str.replace('style="', 'style="max-width: 100%; ');
    } else {
      str = str.replace('<img', '<img style="max-width: 100%;" ');
    }
    return str;
  })
);
const props = withDefaults(defineProps<Props>(), {});
</script>
<!-- <style>
@import './style.css';
</style> -->
<style lang="scss">
@import '@/styles/common.scss';
.rich-text-wrapper {
  overflow-x: hidden;
  color: boleGetCssVar('text-color', 'primary');
  font-size: 28px;
  rich-text {
    overflow-x: hidden;
    word-wrap: break-word;
    white-space: normal;
  }
  /* .h5-img,
  img {
    max-width: 100%;
    min-height: 20px;
    min-width: 20px;
    display: inline !important;
  } */
}
</style>
apps/bMiniApp/src/components/RichEditor/style.css
New file
@@ -0,0 +1,715 @@
:host,
:root {
  --w-e-textarea-bg-color: #fff;
  --w-e-textarea-color: #333;
  --w-e-textarea-border-color: #ccc;
  --w-e-textarea-slight-border-color: #e8e8e8;
  --w-e-textarea-slight-color: #d4d4d4;
  --w-e-textarea-slight-bg-color: #f5f2f0;
  --w-e-textarea-selected-border-color: #b4d5ff;
  --w-e-textarea-handler-bg-color: #4290f7;
  --w-e-toolbar-color: #595959;
  --w-e-toolbar-bg-color: #fff;
  --w-e-toolbar-active-color: #333;
  --w-e-toolbar-active-bg-color: #f1f1f1;
  --w-e-toolbar-disabled-color: #999;
  --w-e-toolbar-border-color: #e8e8e8;
  --w-e-modal-button-bg-color: #fafafa;
  --w-e-modal-button-border-color: #d9d9d9;
}
.w-e-text-container *,
.w-e-toolbar * {
  box-sizing: border-box;
  margin: 0;
  outline: none;
  padding: 0;
}
.w-e-text-container blockquote,
.w-e-text-container li,
.w-e-text-container p,
.w-e-text-container td,
.w-e-text-container th,
.w-e-toolbar * {
  line-height: 1.5;
}
.w-e-text-container {
  background-color: var(--w-e-textarea-bg-color);
  color: var(--w-e-textarea-color);
  height: 100%;
  position: relative;
}
.no-scroll {
  width: 100%;
}
.w-e-text-container .w-e-scroll {
  -webkit-overflow-scrolling: touch;
  height: 100%;
}
.w-e-text-container [data-slate-editor] {
  word-wrap: break-word;
  border-top: 1px solid transparent;
  min-height: 100%;
  outline: 0;
  padding: 0 10px;
  white-space: pre-wrap;
}
.w-e-text-container [data-slate-editor] p {
  margin: 15px 0;
}
.w-e-text-container [data-slate-editor] h1,
.w-e-text-container [data-slate-editor] h2,
.w-e-text-container [data-slate-editor] h3,
.w-e-text-container [data-slate-editor] h4,
.w-e-text-container [data-slate-editor] h5 {
  margin: 20px 0;
}
.w-e-text-container img {
  cursor: default;
  display: inline !important;
  max-width: 100%;
  min-height: 20px;
  min-width: 20px;
}
.w-e-text-container [data-slate-editor] span {
  text-indent: 0;
}
.w-e-text-container [data-slate-editor] [data-selected='true'] {
  box-shadow: 0 0 0 2px var(--w-e-textarea-selected-border-color);
}
.w-e-text-placeholder {
  font-style: italic;
  left: 10px;
  top: 17px;
  width: 90%;
}
.w-e-max-length-info,
.w-e-text-placeholder {
  color: var(--w-e-textarea-slight-color);
  pointer-events: none;
  position: absolute;
  -webkit-user-select: none;
  -moz-user-select: none;
  user-select: none;
}
.w-e-max-length-info {
  bottom: 0.5em;
  right: 1em;
}
.w-e-bar {
  background-color: var(--w-e-toolbar-bg-color);
  color: var(--w-e-toolbar-color);
  font-size: 14px;
  padding: 0 5px;
}
.w-e-bar svg {
  fill: var(--w-e-toolbar-color);
  height: 14px;
  width: 14px;
}
.w-e-bar-show {
  display: flex;
}
.w-e-bar-hidden {
  display: none;
}
.w-e-hover-bar {
  border: 1px solid var(--w-e-toolbar-border-color);
  border-radius: 3px;
  box-shadow: 0 2px 5px #0000001f;
  position: absolute;
}
.w-e-toolbar {
  flex-wrap: wrap;
  position: relative;
}
.w-e-bar-divider {
  background-color: var(--w-e-toolbar-border-color);
  display: inline-flex;
  height: 40px;
  margin: 0 5px;
  width: 1px;
}
.w-e-bar-item {
  display: flex;
  height: 40px;
  padding: 4px;
  position: relative;
  text-align: center;
}
.w-e-bar-item,
.w-e-bar-item button {
  align-items: center;
  justify-content: center;
}
.w-e-bar-item button {
  background: transparent;
  border: none;
  color: var(--w-e-toolbar-color);
  cursor: pointer;
  display: inline-flex;
  height: 32px;
  overflow: hidden;
  padding: 0 8px;
  white-space: nowrap;
}
.w-e-bar-item button:hover {
  background-color: var(--w-e-toolbar-active-bg-color);
  color: var(--w-e-toolbar-active-color);
}
.w-e-bar-item button .title {
  margin-left: 5px;
}
.w-e-bar-item .active {
  background-color: var(--w-e-toolbar-active-bg-color);
  color: var(--w-e-toolbar-active-color);
}
.w-e-bar-item .disabled {
  color: var(--w-e-toolbar-disabled-color);
  cursor: not-allowed;
}
.w-e-bar-item .disabled svg {
  fill: var(--w-e-toolbar-disabled-color);
}
.w-e-bar-item .disabled:hover {
  background-color: var(--w-e-toolbar-bg-color);
  color: var(--w-e-toolbar-disabled-color);
}
.w-e-bar-item .disabled:hover svg {
  fill: var(--w-e-toolbar-disabled-color);
}
.w-e-menu-tooltip-v5:before {
  background-color: var(--w-e-toolbar-active-color);
  border-radius: 5px;
  color: var(--w-e-toolbar-bg-color);
  content: attr(data-tooltip);
  font-size: 0.75em;
  padding: 5px 10px;
  text-align: center;
  top: 40px;
  white-space: pre;
  z-index: 1;
}
.w-e-menu-tooltip-v5:after,
.w-e-menu-tooltip-v5:before {
  opacity: 0;
  position: absolute;
  transition: opacity 0.6s;
  visibility: hidden;
}
.w-e-menu-tooltip-v5:after {
  border: 5px solid transparent;
  border-bottom: 5px solid var(--w-e-toolbar-active-color);
  content: '';
  top: 30px;
}
.w-e-menu-tooltip-v5:hover:after,
.w-e-menu-tooltip-v5:hover:before {
  opacity: 1;
  visibility: visible;
}
.w-e-menu-tooltip-v5.tooltip-right:before {
  left: 100%;
  top: 10px;
}
.w-e-menu-tooltip-v5.tooltip-right:after {
  border-bottom-color: transparent;
  border-left-color: transparent;
  border-right-color: var(--w-e-toolbar-active-color);
  border-top-color: transparent;
  left: 100%;
  margin-left: -10px;
  top: 16px;
}
.w-e-bar-item-group .w-e-bar-item-menus-container {
  background-color: var(--w-e-toolbar-bg-color);
  border: 1px solid var(--w-e-toolbar-border-color);
  border-radius: 3px;
  box-shadow: 0 2px 10px #0000001f;
  display: none;
  left: 0;
  margin-top: 40px;
  position: absolute;
  top: 0;
  z-index: 1;
}
.w-e-bar-item-group:hover .w-e-bar-item-menus-container {
  display: block;
}
.w-e-select-list {
  background-color: var(--w-e-toolbar-bg-color);
  border: 1px solid var(--w-e-toolbar-border-color);
  border-radius: 3px;
  box-shadow: 0 2px 10px #0000001f;
  left: 0;
  margin-top: 40px;
  max-height: 350px;
  min-width: 100px;
  overflow-y: auto;
  position: absolute;
  top: 0;
  z-index: 1;
}
.w-e-select-list ul {
  line-height: 1;
  list-style: none;
}
.w-e-select-list ul .selected {
  background-color: var(--w-e-toolbar-active-bg-color);
}
.w-e-select-list ul li {
  cursor: pointer;
  padding: 7px 0 7px 25px;
  position: relative;
  text-align: left;
  white-space: nowrap;
}
.w-e-select-list ul li:hover {
  background-color: var(--w-e-toolbar-active-bg-color);
}
.w-e-select-list ul li svg {
  left: 0;
  margin-left: 5px;
  margin-top: -7px;
  position: absolute;
  top: 50%;
}
.w-e-bar-bottom .w-e-select-list {
  bottom: 0;
  margin-bottom: 40px;
  margin-top: 0;
  top: inherit;
}
.w-e-drop-panel {
  background-color: var(--w-e-toolbar-bg-color);
  border: 1px solid var(--w-e-toolbar-border-color);
  border-radius: 3px;
  box-shadow: 0 2px 10px #0000001f;
  margin-top: 40px;
  min-width: 200px;
  padding: 10px;
  position: absolute;
  top: 0;
  z-index: 1;
}
.w-e-bar-bottom .w-e-drop-panel {
  bottom: 0;
  margin-bottom: 40px;
  margin-top: 0;
  top: inherit;
}
.w-e-modal {
  background-color: var(--w-e-toolbar-bg-color);
  border: 1px solid var(--w-e-toolbar-border-color);
  border-radius: 3px;
  box-shadow: 0 2px 10px #0000001f;
  color: var(--w-e-toolbar-color);
  font-size: 14px;
  min-height: 40px;
  min-width: 100px;
  padding: 20px 15px 0;
  position: absolute;
  text-align: left;
  z-index: 1;
}
.w-e-modal .btn-close {
  cursor: pointer;
  line-height: 1;
  padding: 5px;
  position: absolute;
  right: 8px;
  top: 7px;
}
.w-e-modal .btn-close svg {
  fill: var(--w-e-toolbar-color);
  height: 10px;
  width: 10px;
}
.w-e-modal .babel-container {
  display: block;
  margin-bottom: 15px;
}
.w-e-modal .babel-container span {
  display: block;
  margin-bottom: 10px;
}
.w-e-modal .button-container {
  margin-bottom: 15px;
}
.w-e-modal button {
  background-color: var(--w-e-modal-button-bg-color);
  cursor: pointer;
  font-weight: 400;
  height: 32px;
  padding: 4.5px 15px;
  text-align: center;
  touch-action: manipulation;
  transition: all 0.3s cubic-bezier(0.645, 0.045, 0.355, 1);
  -webkit-user-select: none;
  -moz-user-select: none;
  user-select: none;
  white-space: nowrap;
}
.w-e-modal button,
.w-e-modal input[type='number'],
.w-e-modal input[type='text'],
.w-e-modal textarea {
  border: 1px solid var(--w-e-modal-button-border-color);
  border-radius: 4px;
  color: var(--w-e-toolbar-color);
}
.w-e-modal input[type='number'],
.w-e-modal input[type='text'],
.w-e-modal textarea {
  font-feature-settings: 'tnum';
  background-color: var(--w-e-toolbar-bg-color);
  font-variant: tabular-nums;
  padding: 4.5px 11px;
  transition: all 0.3s;
  width: 100%;
}
.w-e-modal textarea {
  min-height: 60px;
}
body .w-e-modal,
body .w-e-modal * {
  box-sizing: border-box;
}
.w-e-progress-bar {
  background-color: var(--w-e-textarea-handler-bg-color);
  height: 1px;
  position: absolute;
  transition: width 0.3s;
  width: 0;
}
.w-e-full-screen-container {
  bottom: 0 !important;
  display: flex !important;
  flex-direction: column !important;
  height: 100% !important;
  left: 0 !important;
  margin: 0 !important;
  padding: 0 !important;
  position: fixed;
  right: 0 !important;
  top: 0 !important;
  width: 100% !important;
}
.w-e-full-screen-container [data-w-e-textarea='true'] {
  flex: 1 !important;
}
.w-e-text-container [data-slate-editor] code {
  background-color: var(--w-e-textarea-slight-bg-color);
  border-radius: 3px;
  font-family: monospace;
  padding: 3px;
}
.w-e-panel-content-color {
  list-style: none;
  text-align: left;
  width: 230px;
}
.w-e-panel-content-color li {
  border: 1px solid var(--w-e-toolbar-bg-color);
  border-radius: 3px 3px;
  cursor: pointer;
  display: inline-block;
  padding: 2px;
}
.w-e-panel-content-color li:hover {
  border-color: var(--w-e-toolbar-color);
}
.w-e-panel-content-color li .color-block {
  border: 1px solid var(--w-e-toolbar-border-color);
  border-radius: 3px 3px;
  height: 17px;
  width: 17px;
}
.w-e-panel-content-color .active {
  border-color: var(--w-e-toolbar-color);
}
.w-e-panel-content-color .clear {
  line-height: 1.5;
  margin-bottom: 5px;
  width: 100%;
}
.w-e-panel-content-color .clear svg {
  height: 16px;
  margin-bottom: -4px;
  width: 16px;
}
.w-e-text-container [data-slate-editor] blockquote {
  background-color: var(--w-e-textarea-slight-bg-color);
  border-left: 8px solid var(--w-e-textarea-selected-border-color);
  display: block;
  font-size: 100%;
  line-height: 1.5;
  margin: 10px 0;
  padding: 10px;
}
.w-e-panel-content-emotion {
  font-size: 20px;
  list-style: none;
  text-align: left;
  width: 300px;
}
.w-e-panel-content-emotion li {
  border-radius: 3px 3px;
  cursor: pointer;
  display: inline-block;
  padding: 0 5px;
}
.w-e-panel-content-emotion li:hover {
  background-color: var(--w-e-textarea-slight-bg-color);
}
.w-e-textarea-divider {
  border-radius: 3px;
  margin: 20px auto;
  padding: 20px;
}
.w-e-textarea-divider hr {
  background-color: var(--w-e-textarea-border-color);
  border: 0;
  display: block;
  height: 1px;
}
.w-e-text-container [data-slate-editor] pre > code {
  background-color: var(--w-e-textarea-slight-bg-color);
  border: 1px solid var(--w-e-textarea-slight-border-color);
  border-radius: 4px 4px;
  display: block;
  font-size: 14px;
  padding: 10px;
  text-indent: 0;
}
.w-e-text-container [data-slate-editor] .w-e-image-container {
  display: inline-block;
  margin: 0 3px;
}
.w-e-text-container [data-slate-editor] .w-e-image-container:hover {
  box-shadow: 0 0 0 2px var(--w-e-textarea-selected-border-color);
}
.w-e-text-container [data-slate-editor] .w-e-selected-image-container {
  overflow: hidden;
  position: relative;
}
.w-e-text-container [data-slate-editor] .w-e-selected-image-container .w-e-image-dragger {
  background-color: var(--w-e-textarea-handler-bg-color);
  height: 7px;
  position: absolute;
  width: 7px;
}
.w-e-text-container [data-slate-editor] .w-e-selected-image-container .left-top {
  cursor: nwse-resize;
  left: 0;
  top: 0;
}
.w-e-text-container [data-slate-editor] .w-e-selected-image-container .right-top {
  cursor: nesw-resize;
  right: 0;
  top: 0;
}
.w-e-text-container [data-slate-editor] .w-e-selected-image-container .left-bottom {
  bottom: 0;
  cursor: nesw-resize;
  left: 0;
}
.w-e-text-container [data-slate-editor] .w-e-selected-image-container .right-bottom {
  bottom: 0;
  cursor: nwse-resize;
  right: 0;
}
.w-e-text-container [contenteditable='false'] .w-e-image-container:hover,
.w-e-text-container [data-slate-editor] .w-e-selected-image-container:hover {
  box-shadow: none;
}
.w-e-text-container [data-slate-editor] .table-container {
  border: 1px dashed var(--w-e-textarea-border-color);
  border-radius: 5px;
  margin-top: 10px;
  overflow-x: auto;
  padding: 10px;
  position: relative;
  width: 100%;
}
.w-e-text-container [data-slate-editor] table {
  border-collapse: collapse;
  table-layout: fixed;
}
.w-e-text-container [data-slate-editor] table td,
.w-e-text-container [data-slate-editor] table th {
  border: 1px solid var(--w-e-textarea-border-color);
  line-height: 1.5;
  min-width: 30px;
  overflow: hidden;
  overflow-wrap: break-word;
  padding: 3px 5px;
  text-align: left;
  white-space: pre-wrap;
  word-break: break-all;
}
.w-e-text-container [data-slate-editor] table th {
  background-color: var(--w-e-textarea-slight-bg-color);
  font-weight: 700;
  text-align: center;
}
.w-e-text-container [data-slate-editor] table td.w-e-selected,
.w-e-text-container [data-slate-editor] table th.w-e-selected {
  background-color: rgba(20, 86, 240, 0.18);
}
.w-e-text-container [data-slate-editor] table.table-selection-none ::-moz-selection {
  background: none;
}
.w-e-text-container [data-slate-editor] table.table-selection-none ::selection {
  background: none;
}
.w-e-text-container [data-slate-editor] .column-resizer {
  display: flex;
  height: 0;
  left: 11px;
  position: absolute;
  top: 10px;
  width: 0;
  z-index: 1;
}
.w-e-text-container [data-slate-editor] .column-resizer .column-resizer-item {
  position: relative;
}
.w-e-text-container [data-slate-editor] .resizer-line-hotzone {
  cursor: col-resize;
  opacity: 0;
  position: absolute;
  right: -3px;
  transition: opacity 0.2s ease, visibility 0.2s ease;
  visibility: hidden;
  width: 10px;
}
.w-e-text-container [data-slate-editor] .resizer-line-hotzone .resizer-line {
  background: rgba(20, 86, 240, 0.8);
  height: 100%;
  margin-left: 5px;
  -webkit-user-select: none;
  -moz-user-select: none;
  user-select: none;
  width: 2px;
}
.w-e-text-container [data-slate-editor] .resizer-line-hotzone.visible {
  visibility: visible;
}
.w-e-text-container [data-slate-editor] .resizer-line-hotzone.highlight {
  opacity: 1;
}
.w-e-panel-content-table {
  background-color: var(--w-e-toolbar-bg-color);
}
.w-e-panel-content-table table {
  border-collapse: collapse;
  table-layout: fixed;
}
.w-e-panel-content-table td,
.w-e-panel-content-table th {
  overflow: hidden;
  overflow-wrap: break-word;
  white-space: pre-wrap;
  word-break: break-all;
}
.w-e-panel-content-table td {
  border: 1px solid var(--w-e-toolbar-border-color);
  cursor: pointer;
  height: 15px;
  padding: 3px 5px;
  width: 20px;
}
.w-e-panel-content-table td.active {
  background-color: var(--w-e-toolbar-active-bg-color);
}
.w-e-textarea-video-container {
  background-image: linear-gradient(45deg, #eee 25%, transparent 0, transparent 75%, #eee 0, #eee),
    linear-gradient(45deg, #eee 25%, #fff 0, #fff 75%, #eee 0, #eee);
  background-position: 0 0, 10px 10px;
  background-size: 20px 20px;
  border: 1px dashed var(--w-e-textarea-border-color);
  border-radius: 5px;
  margin: 10px auto 0;
  padding: 10px 0;
  text-align: center;
}
.w-e-text-container [data-slate-editor] pre > code {
  word-wrap: normal;
  font-family: Consolas, Monaco, Andale Mono, Ubuntu Mono, monospace;
  -webkit-hyphens: none;
  hyphens: none;
  line-height: 1.5;
  margin: 0.5em 0;
  overflow: auto;
  padding: 1em;
  -moz-tab-size: 4;
  -o-tab-size: 4;
  tab-size: 4;
  text-align: left;
  text-shadow: 0 1px #fff;
  white-space: pre;
  word-break: normal;
  word-spacing: normal;
}
.w-e-text-container [data-slate-editor] pre > code .token.cdata,
.w-e-text-container [data-slate-editor] pre > code .token.comment,
.w-e-text-container [data-slate-editor] pre > code .token.doctype,
.w-e-text-container [data-slate-editor] pre > code .token.prolog {
  color: #708090;
}
.w-e-text-container [data-slate-editor] pre > code .token.punctuation {
  color: #999;
}
.w-e-text-container [data-slate-editor] pre > code .token.namespace {
  opacity: 0.7;
}
.w-e-text-container [data-slate-editor] pre > code .token.boolean,
.w-e-text-container [data-slate-editor] pre > code .token.constant,
.w-e-text-container [data-slate-editor] pre > code .token.deleted,
.w-e-text-container [data-slate-editor] pre > code .token.number,
.w-e-text-container [data-slate-editor] pre > code .token.property,
.w-e-text-container [data-slate-editor] pre > code .token.symbol,
.w-e-text-container [data-slate-editor] pre > code .token.tag {
  color: #905;
}
.w-e-text-container [data-slate-editor] pre > code .token.attr-name,
.w-e-text-container [data-slate-editor] pre > code .token.builtin,
.w-e-text-container [data-slate-editor] pre > code .token.char,
.w-e-text-container [data-slate-editor] pre > code .token.inserted,
.w-e-text-container [data-slate-editor] pre > code .token.selector,
.w-e-text-container [data-slate-editor] pre > code .token.string {
  color: #690;
}
.w-e-text-container [data-slate-editor] pre > code .language-css .token.string,
.w-e-text-container [data-slate-editor] pre > code .style .token.string,
.w-e-text-container [data-slate-editor] pre > code .token.entity,
.w-e-text-container [data-slate-editor] pre > code .token.operator,
.w-e-text-container [data-slate-editor] pre > code .token.url {
  color: #9a6e3a;
}
.w-e-text-container [data-slate-editor] pre > code .token.atrule,
.w-e-text-container [data-slate-editor] pre > code .token.attr-value,
.w-e-text-container [data-slate-editor] pre > code .token.keyword {
  color: #07a;
}
.w-e-text-container [data-slate-editor] pre > code .token.class-name,
.w-e-text-container [data-slate-editor] pre > code .token.function {
  color: #dd4a68;
}
.w-e-text-container [data-slate-editor] pre > code .token.important,
.w-e-text-container [data-slate-editor] pre > code .token.regex,
.w-e-text-container [data-slate-editor] pre > code .token.variable {
  color: #e90;
}
.w-e-text-container [data-slate-editor] pre > code .token.bold,
.w-e-text-container [data-slate-editor] pre > code .token.important {
  font-weight: 700;
}
.w-e-text-container [data-slate-editor] pre > code .token.italic {
  font-style: italic;
}
.w-e-text-container [data-slate-editor] pre > code .token.entity {
  cursor: help;
}
apps/bMiniApp/src/components/Uploader/CoverUploader.vue
New file
@@ -0,0 +1,139 @@
<template>
  <div class="cover-uploader-wrapper">
    <Uploader v-model:file-list="innerFileList">
      <template #extra-img="{ item }">
        <div class="set-cover-btn" @click="handleSetCover(item)">
          {{ item.isMain ? '取消封面' : '设为封面' }}
        </div>
      </template>
    </Uploader>
    <div class="system-cover-uploader-wrapper" v-if="demoCoverList.length > 0">
      <div class="system-cover-uploader-title">您还可以从系统中选择图片</div>
      <div class="system-cover-uploader-list">
        <div
          v-for="cover in demoCoverList"
          :key="cover.url"
          class="system-cover-uploader-list-item"
          @click="handleUploadSystemCover(cover.url)"
        >
          <img class="system-cover-uploader-list-img" :src="cover.url" />
        </div>
      </div>
    </div>
  </div>
</template>
<script setup lang="ts">
import Uploader from './Uploader.vue';
import { CoverItem } from './uploader';
import { convertApiPath2Url } from '@12333/utils';
defineOptions({
  name: 'CoverUploader',
});
type Props = {
  fileList: CoverItem[];
  demoCoverList?: API.CoverMsg[];
};
const props = withDefaults(defineProps<Props>(), {
  demoCoverList: () => [] as API.CoverMsg[],
});
const emit = defineEmits<{
  (e: 'update:fileList', list: CoverItem[]): void;
}>();
const innerFileList = computed({
  get() {
    return props.fileList;
  },
  set(val) {
    emit('update:fileList', val);
  },
});
function handleUploadSystemCover(url: string) {
  emit('update:fileList', [
    ...props.fileList,
    {
      ...(convertApiPath2Url(url) as any),
    },
  ]);
}
function handleSetCover(item: CoverItem) {
  emit(
    'update:fileList',
    props.fileList.map((x) => {
      return {
        ...x,
        isMain: x.uid === item.uid,
      };
    })
  );
}
watch(
  () => props.fileList.length,
  (newValue, oldValue) => {
    if (newValue !== oldValue) {
      const index = props.fileList.findIndex((x) => x.isMain);
      if (index < 0) {
        handleSetCover(props.fileList[0]);
      }
    }
  }
);
</script>
<style lang="scss">
@import '@/styles/common.scss';
.cover-uploader-wrapper {
  padding-top: 16px;
  .nut-uploader__preview.picture {
    .set-cover-btn {
      width: 100%;
      position: absolute;
      height: 30px;
      line-height: 30px;
      text-align: center;
      bottom: 0;
      left: 0;
      font-size: 16px;
      background-color: rgba(#000, 0.3);
      color: #fff;
    }
  }
  .system-cover-uploader-wrapper {
    margin-top: 16px;
    .system-cover-uploader-title {
      font-size: 24px;
      color: boleGetCssVar('text-color', 'regular');
      margin-bottom: 10px;
    }
    .system-cover-uploader-list {
      display: flex;
      flex-wrap: wrap;
      margin: -10px;
      .system-cover-uploader-list-item {
        padding: 10px;
        .system-cover-uploader-list-img {
          width: 100px;
          height: 100px;
          border: 1px solid #dadada;
          border-radius: 4px;
        }
      }
    }
  }
}
</style>
apps/bMiniApp/src/components/Uploader/Uploader.vue
New file
@@ -0,0 +1,125 @@
<template>
  <nut-uploader
    v-if="$slots.default"
    v-model:file-list="innerFileList"
    multiple
    :media-type="['image']"
    :before-xhr-upload="beforeXhrUpload"
    @failure="handleFailure"
    :maximize="maximize"
  >
    <template #upload-icon>
      <slot name="upload-icon"></slot>
    </template>
    <template #default>
      <slot></slot>
    </template>
    <template #extra-img>
      <slot name="extra-img"></slot>
    </template>
  </nut-uploader>
  <nut-uploader
    v-else
    v-model:file-list="innerFileList"
    multiple
    :media-type="['image']"
    :before-xhr-upload="beforeXhrUpload"
    @failure="handleFailure"
    :maximize="maximize"
  >
    <template #upload-icon>
      <slot name="upload-icon"></slot>
    </template>
    <template #extra-img="extraImgProps">
      <slot name="extra-img" v-bind="extraImgProps"></slot>
    </template>
  </nut-uploader>
</template>
<script setup lang="ts">
import { ossUpload } from '@12333/utils/oss';
import { guid } from '@12333/utils';
import { FileItem } from '@nutui/nutui-taro/dist/types/__VUE/uploader/type';
import { UploadOptions } from '@nutui/nutui-taro/dist/types/__VUE/uploader/uploader';
import Taro from '@tarojs/taro';
defineOptions({
  name: 'Uploader',
});
type Props = {
  fileList: FileItem[];
  onMySuccess?: (file: FileItem) => any;
  limitFileSize?: number;
};
const props = withDefaults(defineProps<Props>(), {
  limitFileSize: 2,
});
const emit = defineEmits<{
  (e: 'update:fileList', list: FileItem[]): void;
}>();
const innerFileList = computed({
  get() {
    return props.fileList;
  },
  set(val) {
    emit('update:fileList', val);
  },
});
const maximize = computed(() => props.limitFileSize * 1024 * 1024);
const beforeXhrUpload = (taroUploadFile: any, options: UploadOptions) => {
  const current = innerFileList.value.find((x) => x.path === options.taroFilePath);
  const uploadTask = ossUpload({
    filePath: options.taroFilePath,
    fileType: options.fileType,
    name: options.name || 'file',
    customFileName: () => guid(),
    showLoading: false,
    success(response: { errMsg: any; statusCode: number; data: string }, ossRes) {
      options.onSuccess?.(response, options);
      current.name = ossRes.name;
      current.path = ossRes.path;
      current.url = ossRes.url;
      // innerFileList.value.map((x) => {
      //     if (x.uid === current.uid) {
      //       return {
      //         ...x,
      //         name: ossRes.name,
      //         path: ossRes.path,
      //         url: ossRes.url,
      //       };
      //     }
      //     return { ...x };
      //   })
      // emit('update:fileList', innerFileList.value);
      nextTick(() => {
        props.onMySuccess?.(innerFileList.value.find((x) => x.path === ossRes.path));
      });
    },
    fail(e: any) {
      console.log('e: ', e);
      options.onFailure?.(e, options);
    },
  });
  options.onStart?.(options);
  // uploadTask?.progress(
  //   (res: { progress: any; totalBytesSent: any; totalBytesExpectedToSend: any }) => {
  //     options.onProgress?.(res, options);
  //     // console.log('上传进度', res.progress);
  //     // console.log('已经上传的数据长度', res.totalBytesSent);
  //     // console.log('预期需要上传的数据总长度', res.totalBytesExpectedToSend);
  //   }
  // );
  // uploadTask.abort(); // 取消上传任务
};
function handleFailure(ev) {
  console.log('Failure ev: ', ev);
}
</script>
apps/bMiniApp/src/components/Uploader/uploader.ts
New file
@@ -0,0 +1,5 @@
import { FileItem } from '@nutui/nutui-taro/dist/types/__VUE/uploader/type';
export type CoverItem = Partial<FileItem> & {
  isMain?: boolean;
};
apps/bMiniApp/src/components/UserHome/UserHomeTopView.vue
New file
@@ -0,0 +1,149 @@
<template>
  <div class="mine-page-top-view">
    <slot name="avatar"></slot>
    <div class="setting-wrapper" v-if="showUserHomePageBtn" @click="goUserHomePage">
      <div class="setting-text">我的主页</div>
    </div>
  </div>
  <div class="mine-page-operation-wrapper" v-if="showOperation">
    <div class="mine-page-operation-item" @click="goEditProfile">
      <img class="mine-page-operation-item-icon" :src="IconEdit" />
      <div class="mine-page-operation-item-text">编辑资料</div>
      <img class="mine-page-operation-item-arrow" :src="IconArrow" />
    </div>
    <button class="mine-page-operation-item share" open-type="share">
      <!-- <div class="mine-page-operation-item-inner"> -->
      <img class="mine-page-operation-item-icon" :src="IconCard" />
      <div class="mine-page-operation-item-text">发送名片</div>
      <img class="mine-page-operation-item-arrow" :src="IconArrow" />
      <!-- </div> -->
    </button>
  </div>
</template>
<script setup lang="ts">
import { useUser, useIsLogin } from '@/hooks';
import Taro from '@tarojs/taro';
import IconEdit from '@/assets/mine/icon-edit.png';
import IconCard from '@/assets/mine/icon-card.png';
import IconArrow from '@/assets/mine/icon-arrow.png';
defineOptions({
  name: 'UserHomeTopView',
});
type Props = {
  showUserHomePageBtn?: boolean;
  showOperation?: boolean;
};
const props = withDefaults(defineProps<Props>(), {
  showUserHomePageBtn: false,
  showOperation: false,
});
const { userDetail } = useUser();
function goUserHomePage() {
  Taro.navigateTo({
    url: `${RouterPath.userHomePage}?userId=${userDetail.value?.userId}`,
  });
}
function goEditProfile() {
  Taro.navigateTo({
    url: RouterPath.userInfo,
  });
}
</script>
<style lang="scss">
@import '@/styles/common.scss';
.mine-page-top-view {
  padding-top: 34px;
  display: flex;
  margin-bottom: 20px;
  .setting-wrapper {
    height: 56px;
    background: rgba(#000, $alpha: 0.15);
    border-radius: 200px 0px 0px 200px;
    align-self: center;
    display: flex;
    align-items: center;
    margin-right: calc(boleGetCssVar('size', 'body-padding-h') * -1);
    padding-left: 24px;
    padding-right: 16px;
    .setting-icon {
      width: 32px;
      height: 32px;
      margin-right: 4px;
      margin-left: 32px;
    }
    .setting-text {
      font-weight: 400;
      font-size: 24px;
      color: #ffffff;
      line-height: 34px;
    }
  }
}
.mine-page-operation-wrapper {
  display: flex;
  padding-top: 22px;
  margin-bottom: 36px;
  .mine-page-operation-item {
    flex: 1;
    min-width: 0;
    align-items: center;
    display: flex;
    padding-left: 28px;
    border-right: 1px solid #efefef;
    &:last-child {
      border-right: none;
    }
    &.share {
      background-color: transparent;
      padding-right: 0;
      appearance: none;
      text-align: left;
      &::after {
        border: none;
      }
      /* .mine-page-operation-item-inner {
        display: flex;
        align-items: center;
      } */
    }
    .mine-page-operation-item-icon {
      width: 32px;
      height: 32px;
      margin-right: 8px;
    }
    .mine-page-operation-item-text {
      flex: 1;
      min-width: 0;
      font-weight: bold;
      font-size: 24px;
      color: boleGetCssVar('text-color', 'primary');
      line-height: 34px;
    }
    .mine-page-operation-item-arrow {
      width: 28px;
      height: 28px;
      margin-right: 28px;
    }
  }
}
</style>
apps/bMiniApp/src/components/index.ts
New file
@@ -0,0 +1,25 @@
export { default as CommonNavigationBar } from './NavigationBar/CommonNavigationBar.vue';
export { default as TransparentNavigationBar } from './NavigationBar/TransparentNavigationBar.vue';
export { default as LargeTitleNavigationBar } from './NavigationBar/LargeTitleNavigationBar.vue';
export { default as PageLayout } from './Layout/PageLayout.vue';
export { default as PageLayoutWithBg } from './Layout/PageLayoutWithBg.vue';
export { default as LoadingLayout } from './Layout/LoadingLayout.vue';
export { default as Policy } from './Policy/Policy.vue';
export { default as Menu } from './Menu/Menu.vue';
export { default as MenuItem } from './Menu/MenuItem.vue';
export { default as InfiniteLoading } from './InfiniteLoading/InfiniteLoading.vue';
export { default as PageFooter } from './PageFooter/PageFooter.vue';
export { default as Uploader } from './Uploader/Uploader.vue';
export { default as CoverUploader } from './Uploader/CoverUploader.vue';
export * from './Uploader/uploader';
export { default as LargeButton } from './Button/LargeButton.vue';
export { default as RichEditCard } from './RichEditCard/RichEditCard.vue';
export { default as RichContent } from './RichEditCard/RichContent.vue';
export { default as NoData } from './NoData/NoData.vue';
export { default as UserAvatar } from './Avatar/UserAvatar.vue';
export { default as ContentScrollView } from './Layout/ContentScrollView.vue';
export { default as ContentView } from './Layout/ContentView.vue';
export { default as PageFooterAction } from './PageFooter/PageFooterAction.vue';
export { default as PageFooterBtn } from './PageFooter/PageFooterBtn.vue';
export { default as ChunkTitle } from './Chunk/ChunkTitle.vue';
export { default as UserHomeTopView } from './UserHome/UserHomeTopView.vue';
apps/bMiniApp/src/constants/enum.ts
New file
@@ -0,0 +1,4 @@
export enum BackType {
  toDetail = 'toDetail',
  back = 'back',
}
apps/bMiniApp/src/constants/img.ts
New file
@@ -0,0 +1,17 @@
const OssBasePath = 'https://renliyuan.oss-cn-hangzhou.aliyuncs.com/12333';
export const OssAssets = {
  common: {
    CommonPageBg: `${OssBasePath}/matchMakingMini/assets/common/icon-common-page-bg.png`,
  },
  mine: {
    Bg: `${OssBasePath}/matchMakingMini/assets/mine/icon-bg.png`,
    IdBg: `${OssBasePath}/matchMakingMini/assets/mine/icon-id-bg.png`,
  },
  setting: {
    ToggleBg: `${OssBasePath}/matchMakingMini/assets/setting/icon-toggle-bg.png`,
  },
  user: {
    Bg: `${OssBasePath}/matchMakingMini/assets/user/icon-bg.png`,
  },
};
apps/bMiniApp/src/constants/index.ts
New file
@@ -0,0 +1,4 @@
export * from './enum';
export * from './tabBar';
export * from './router';
export * from './img';
apps/bMiniApp/src/constants/query.ts
New file
@@ -0,0 +1,10 @@
import { QueryClient } from '@tanstack/vue-query';
export const myClient = new QueryClient({
  defaultOptions: {
    queries: {
      refetchOnWindowFocus: false,
      retry: false,
    },
  },
});
apps/bMiniApp/src/constants/router.ts
New file
@@ -0,0 +1,21 @@
export enum RouterPath {
  authorization = '/subpackages/login/authorization/authorization',
  userPolicy = '/subpackages/login/userPolicy/userPolicy',
  loginByForm = '/subpackages/login/loginByForm/loginByForm',
  registerForm = '/subpackages/login/registerForm/registerForm',
  home = '/pages/home/index',
  mine = '/pages/mine/index',
  editRichContent = '/subpackages/editRichContent/editRichContent',
  // userInfo = '/subpackages/setting/userInfo/userInfo',
  // setting = '/subpackages/setting/setting/setting',
  // privacyAgreement = '/subpackages/setting/privacyAgreement/privacyAgreement',
  // cooperation = '/subpackages/setting/cooperation/cooperation',
  // faq = '/subpackages/setting/faq/faq',
  authenticationHome = '/subpackages/authentication/authenticationHome/authenticationHome',
  authenticationResult = '/subpackages/authentication/authenticationResult/authenticationResult',
  authenticationFaRen = '/subpackages/authentication/authenticationFaRen/authenticationFaRen',
  authenticationJBR = '/subpackages/authentication/authenticationJBR/authenticationJBR',
  citySelect = '/subpackages/city/citySelect/citySelect',
}
apps/bMiniApp/src/constants/tabBar.ts
New file
@@ -0,0 +1,4 @@
export const TabBarPageRouter = {
  Home: '/pages/home/index',
  Mine: '/pages/mine/index',
};
apps/bMiniApp/src/custom-tab-bar/index.scss
New file
@@ -0,0 +1,119 @@
@import '@/styles/common.scss';
.bottom-tab {
  position: fixed;
  display: flex;
  width: 100%;
  height: 118px;
  // height: 100px;
  background: white;
  box-shadow: 0px -5px 6px 1px rgba(0, 0, 0, 0.04);
  bottom: 0;
  .bottom-tab-left,
  .bottom-tab-right {
    height: 100%;
    display: flex;
    width: 50%;
    justify-content: space-around;
  }
  .bottom-tab-left {
    padding-right: 20px;
  }
  .bottom-tab-right {
    padding-left: 20px;
  }
  &-item {
    // padding: 36px 20px 32px;
    // padding-bottom: 16px;
    padding: 20px 0;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: flex-start;
    flex: 1;
    position: relative;
    .bottom-tab-item-icon-wrapper {
      margin-bottom: 8px;
      position: relative;
    }
    .bottom-tab-item-icon {
      width: 40px;
      height: 40px;
    }
    .bottom-tab-item-text {
      color: #707070;
      font-size: 20px;
      line-height: 24px;
    }
    .bottom-tab-item-badge {
      line-height: 28px;
      padding: 0 8px;
      background: #ff4d4f;
      border-radius: 14px;
      color: #fff;
      font-size: 22px;
      position: absolute;
      top: -6px;
      right: -10px;
    }
    &.active {
      .bottom-tab-item-text {
        color: #3a71ff;
      }
    }
  }
  .publish-wrapper {
    position: relative;
    display: flex;
    flex-direction: column;
    justify-content: flex-end;
    .bottom-tab-item-text {
      margin-top: 50px;
    }
    .bottom-tab-item-img-publish {
      position: absolute;
      width: 103px;
      height: 103px;
      left: 50%;
      top: -50px;
      transform: translateX(-50%);
    }
    .bottom-tab-float-btn {
      position: absolute;
      width: 85px;
      height: 85px;
      background: #ffffff;
      box-shadow: 0px -9px 9px 1px rgba(209, 209, 209, 0.35);
      border-radius: 50%;
      left: 50%;
      top: -30px;
      transform: translateX(-50%);
      display: flex;
      justify-content: center;
      align-items: center;
      .bottom-tab-float-btn-inner {
        width: 70px;
        height: 70px;
        background: linear-gradient(88deg, #2c7eff, #629dfa);
        border-radius: 50%;
        display: flex;
        justify-content: center;
        align-items: center;
      }
    }
  }
}
apps/bMiniApp/src/custom-tab-bar/index.tsx
New file
@@ -0,0 +1,168 @@
import './index.scss';
import { SetupContext } from 'vue';
import { View, Text, Image } from '@tarojs/components';
import Taro from '@tarojs/taro';
import { useSystemStore } from '@/stores/modules/system';
import { storeToRefs } from 'pinia';
import { TabBarPageRouter } from '@/constants';
// import IconPublish from '@/assets/tabbar/icon-publish.png';
import { useUser, useIsLogin } from '@/hooks';
import { Message } from '@12333/utils';
type TarBarItemProps = {
  text: string;
  icon: string;
  activeIcon: string;
  pagePath: string;
  active: boolean;
  className: string;
  onClick?: (url: string, index: number) => any;
  index: number;
  badge?: number;
};
type TarBarItemEvents = {
  click: (url: string, index: number) => any;
};
const TarBarItem = function (props: TarBarItemProps, context: SetupContext<TarBarItemEvents>) {
  const _badge = props.badge > 99 ? '99+' : props.badge;
  return (
    <div
      class={['bottom-tab-item', { active: props.active }, props.className]}
      onClick={() => context.emit('click', props.pagePath, props.index)}
    >
      <div class="bottom-tab-item-icon-wrapper">
        {props.badge > 0 && <div class="bottom-tab-item-badge">{_badge}</div>}
        <img class="bottom-tab-item-icon" src={props.active ? props.activeIcon : props.icon} />
      </div>
      <div class="bottom-tab-item-text">{props.text}</div>
    </div>
  );
};
TarBarItem.emits = {
  click: (url: string, index: number) => typeof url === 'string',
};
const whitePageList = [RouterPath.home, RouterPath.mine];
export default {
  name: 'CustomTabBar',
  components: {
    View,
    Text,
    Image,
    TarBarItem,
  },
  setup() {
    const system = useSystemStore();
    const { IPhoneXPadding } = storeToRefs(system);
    const router = Taro.useRouter();
    const isLogin = useIsLogin();
    const loginTipShowed = ref(false);
    const switchTab = (url: string, index: number) => {
      if (!isLogin.value && whitePageList.every((x) => x !== url)) {
        if (!loginTipShowed.value) {
          loginTipShowed.value = true;
          Message.confirm({ message: '请前往登录' })
            .then(() => {
              Taro.navigateTo({
                url: `${RouterPath.authorization}?redirect=${url}`,
              });
            })
            .finally(() => {
              loginTipShowed.value = false;
            });
        }
        return;
      }
      system.setTabIndex(index);
      Taro.switchTab({ url });
    };
    function goPublish() {
      if (!isLogin.value) {
        if (!loginTipShowed.value) {
          loginTipShowed.value = true;
          Message.confirm({ message: '请前往登录' })
            .then(() => {
              Taro.navigateTo({
                url: `${RouterPath.authorization}?redirect=${RouterPath.home}`,
              });
            })
            .finally(() => {
              loginTipShowed.value = false;
            });
        }
        return;
      }
      // Taro.navigateTo({
      //   url: RouterPath.pulishCircleFriend,
      // });
    }
    return () => {
      return (
        <View
          class="bottom-tab"
          style={{
            paddingBottom: `${IPhoneXPadding.value}px`,
          }}
        >
          <TarBarItem
            text={'homeTitle'}
            icon="../assets/tabbar/icon-home.png"
            activeIcon="../assets/tabbar/icon-home-active.png"
            pagePath={TabBarPageRouter.Home}
            index={0}
            active={system.activeTab === 0}
            className="home"
            onClick={switchTab}
          ></TarBarItem>
          {/* <TarBarItem
            text="行业圈"
            icon="../assets/tabbar/icon-friend.png"
            activeIcon="../assets/tabbar/icon-friend-active.png"
            pagePath={TabBarPageRouter.CircleFriend}
            index={1}
            active={system.activeTab === 1}
            className="circleFriend"
            onClick={switchTab}
          ></TarBarItem>
          <div class="bottom-tab-item publish-wrapper" onClick={goPublish}>
            <img class="bottom-tab-item-img-publish" src={IconPublish} />
            <div class="bottom-tab-item-text">发布</div>
          </div>
          <TarBarItem
            text="消息"
            icon="../assets/tabbar/icon-message.png"
            activeIcon="../assets/tabbar/icon-message-active.png"
            pagePath={TabBarPageRouter.Message}
            active={system.activeTab === 2}
            className="message"
            onClick={switchTab}
            index={2}
            badge={(isLogin.value && myMessageCount.value?.unReadCount) ?? 0}
          ></TarBarItem> */}
          <TarBarItem
            text="我的"
            icon="../assets/tabbar/icon-mine.png"
            activeIcon="../assets/tabbar/icon-mine-active.png"
            pagePath={TabBarPageRouter.Mine}
            active={system.activeTab === 3}
            className="mine"
            onClick={switchTab}
            index={3}
          ></TarBarItem>
        </View>
      );
    };
  },
};
apps/bMiniApp/src/hooks/access.ts
New file
@@ -0,0 +1,45 @@
import { useUserStore } from '@/stores/modules/user';
import Taro from '@tarojs/taro';
import { Message } from '@12333/utils';
import { useIsLogin, useUser } from './user';
/**
 * 需要登录
 */
export function useAccessLogin<T extends (...args: any[]) => any>(fn: T) {
  const isLogin = useIsLogin();
  const router = Taro.useRouter();
  const _fn = (...args2) => {
    if (!isLogin.value) {
      Message.confirm({ message: '请前往登录' }).then(() => {
        Taro.navigateTo({
          url: `${RouterPath.authorization}`,
        });
      });
      return;
    }
    fn?.(...args2);
  };
  return _fn as T;
}
/**
 * 是否完善个人信息(企业名称,手机号)
 */
export function useAccessPersonalInfo<T extends (...args: any[]) => any>(fn: T) {
  const { isCompletePersonalInfo } = useUser();
  const _fn = useAccessLogin((...args2) => {
    if (!isCompletePersonalInfo.value) {
      Message.confirm({ message: '请完善您的个人信息', title: '完善信息' }).then(() => {
        Taro.navigateTo({
          url: `${RouterPath.userInfo}`,
        });
      });
      return;
    }
    fn?.(...args2);
  });
  return _fn as T;
}
apps/bMiniApp/src/hooks/authentication.ts
New file
@@ -0,0 +1,71 @@
import * as userServices from '@12333/services/api/User';
import { useQuery, useQueryClient } from '@tanstack/vue-query';
import { getUserCertificationFrontStatusAdapter } from '@12333/utils';
import { UserCertificationFrontStatus } from '@12333/constants';
import { useUser } from './user';
type UseMyCertificationAuditInfoOptions = {
  onSuccess?: (data: API.MyCertificationAuditDto) => void;
};
export function useMyCertificationAuditInfo(options: UseMyCertificationAuditInfoOptions = {}) {
  const { onSuccess } = options;
  const { updateUserInfo } = useUser();
  const queryClient = useQueryClient();
  const { data, isLoading } = useQuery({
    queryKey: ['userServices/getMyCertificationAuditInfo'],
    queryFn: async () => {
      return await userServices.getMyCertificationAuditInfo({ showLoading: false });
    },
    placeholderData: () => null as API.MyCertificationAuditDto,
    select(data) {
      if (data) {
        data.frontStatus = getUserCertificationFrontStatusAdapter(data.status, data.auditStatus);
      }
      return data;
    },
    onSuccess(data) {
      onSuccess?.(data);
    },
  });
  /**
   * 是否有审核单
   */
  const hasAduit = computed(() => {
    return data && !!data.value?.currentUserCertificationAuditId;
  });
  const isCertified = computed(
    () => data?.value?.frontStatus === UserCertificationFrontStatus.Certified
  );
  const isExpired = computed(
    () => data?.value?.frontStatus === UserCertificationFrontStatus.Expired
  );
  function invalidateCertificationAuditInfo() {
    updateUserInfo();
    return queryClient.invalidateQueries({
      queryKey: ['userServices/getMyCertificationAuditInfo'],
    });
  }
  function ensureCertificationAuditInfo() {
    return queryClient.ensureQueryData({
      queryKey: ['userServices/getMyCertificationAuditInfo'],
    });
  }
  return {
    myCertificationAuditInfo: data,
    isLoading,
    hasAduit,
    invalidateCertificationAuditInfo,
    isCertified,
    isExpired,
    ensureCertificationAuditInfo,
  };
}
apps/bMiniApp/src/hooks/index.ts
New file
@@ -0,0 +1,5 @@
export * from './user';
export * from './router';
export * from './access';
export * from './login';
export * from './authentication';
apps/bMiniApp/src/hooks/login.ts
New file
@@ -0,0 +1,76 @@
import Taro from '@tarojs/taro';
import { object2query } from '@12333/utils';
import { goBack } from '@/utils';
import { useSwitchTab } from './router';
import { TabBarPageRouter } from '@/constants';
import { useQueryClient } from '@tanstack/vue-query';
function getOtherQuery(query: Partial<Record<string, string>>) {
  if (query) {
    return Object.keys(query).reduce((acc, cur) => {
      if (cur !== 'redirect' && cur !== '$taroTimestamp') {
        acc[cur] = query[cur];
      }
      return acc;
    }, {});
  }
}
export function useLoginedJump() {
  const router = Taro.useRouter();
  const { redirect } = router.params;
  const otherQuery = getOtherQuery(router.params);
  const otherQueryString = computed(() => {
    const str = object2query(otherQuery);
    return str.length > 0 ? `${str}` : '';
  });
  const redirectPath = computed(() => {
    return redirect
      ? otherQueryString.value
        ? `${redirect}?${otherQueryString.value}`
        : redirect
      : '';
  });
  const redirectParams = computed(() => {
    return redirect ? `${redirect}&${otherQueryString.value}` : '';
  });
  const switchTab = useSwitchTab();
  const queryClient = useQueryClient();
  const pages = Taro.getCurrentPages();
  function goBackFromAuthorization() {
    const authorizationIndex = pages.findIndex((x) =>
      `/${x.route}`.includes(RouterPath.authorization)
    );
    let delta = authorizationIndex >= 0 ? pages.length - authorizationIndex : 1;
    goBack(delta);
  }
  function jump() {
    if (redirect) {
      const isTabBarPage = Object.values(TabBarPageRouter).includes(redirect as any);
      if (isTabBarPage) {
        switchTab({
          url: redirectPath.value,
        });
      } else {
        // Taro.redirectTo({
        //   url: redirectPath.value,
        // });
        goBackFromAuthorization();
      }
    } else {
      goBackFromAuthorization();
    }
    queryClient.refetchQueries();
  }
  return { jump, redirectPath, redirectParams };
}
apps/bMiniApp/src/hooks/router.ts
New file
@@ -0,0 +1,27 @@
import Taro from '@tarojs/taro';
import { TabBarPageRouter } from '@/constants';
import { useSystemStore } from '@/stores/modules/system';
export function useSwitchTab() {
  const systemStore = useSystemStore();
  const switchTab = (option: Taro.switchTab.Option) => {
    const index = Object.values(TabBarPageRouter).findIndex((x) => option.url.includes(x));
    console.log('index: ', index);
    systemStore.setTabIndex(index);
    Taro.switchTab(option);
  };
  return switchTab;
}
// export function useFirstEnter() {
//   const systemStore = useSystemStore();
//   const { isFirstEnter } = storeToRefs(systemStore);
//   console.log('isFirstEnter: ', isFirstEnter);
//   onMounted(() => {
//     systemStore.setIsFirstEnter(false);
//   });
//   return { isFirstEnter };
// }
apps/bMiniApp/src/hooks/user.ts
New file
@@ -0,0 +1,107 @@
import { useUserStore } from '@/stores/modules/user';
import Taro from '@tarojs/taro';
import { object2query, LocationUtils } from '@12333/utils';
import { ParkOrHRStatus, UserCertificationFrontStatus } from '@12333/constants';
import * as userServices from '@12333/services/api/User';
import { useQuery } from '@tanstack/vue-query';
import { MaybeRef } from 'vue';
import { useRefeshDidShow } from '@12333/hooks/infiniteLoading';
export function useUser() {
  const userStore = useUserStore();
  const { userDetail, userInfo, locationCity } = storeToRefs(userStore);
  function updateUserInfo() {
    return userStore.getCurrentUserInfo();
  }
  const isCompanyAudited = computed(() => {
    return userDetail.value?.openHRSiteStatus === ParkOrHRStatus.Running;
  });
  /**
   * 是否完善个人信息(企业名称,手机号)
   */
  const isCompletePersonalInfo = computed(() => {
    return (
      !!userDetail.value?.customerName &&
      !!userDetail.value?.contacter &&
      !!userDetail.value?.cityName
    );
  });
  const isCertified = computed(() => {
    return userDetail.value?.frontStatus === UserCertificationFrontStatus.Certified;
  });
  return {
    user: userInfo,
    userDetail: userDetail,
    updateUserInfo,
    isCompletePersonalInfo,
    isCompanyAudited,
    isCertified,
    locationCity,
  };
}
export function useIsLogin() {
  const { user, userDetail } = useUser();
  return computed(() => !!user.value);
  // return user?.isPersonal ? !!user : !!user && !!enterpriseInfo;
}
type UseAuthOptions = {
  needAuth?: boolean;
};
export function useAuth(options: UseAuthOptions = {}) {
  const { needAuth = true } = options;
  const userStore = useUserStore();
  const isLogin = useIsLogin();
  const isAuth = computed(() => !needAuth || isLogin.value);
  const router = Taro.useRouter();
  Taro.useReady(async () => {
    let res;
    try {
      res = await LocationUtils.getLocation();
    } catch (error) {}
    if (isLogin.value && userStore.firstGetUserDetail) {
      userStore.firstGetUserDetail = false;
      if (LocationUtils.isProvinceChange(userStore.locationProvince)) {
        userStore.resetState();
      } else {
        userStore.getCurrentUserInfo();
      }
    }
    if (res?.result?.ad_info?.city && userStore.firstSetLocation) {
      userStore.setLocationCity(res.result.ad_info.city, res.result.ad_info.province);
    }
    if (needAuth && !isLogin.value) {
      Taro.navigateTo({
        url: `${RouterPath.authorization}?redirect=${router.path}&${object2query(router.params)}`,
      });
    }
  });
  return { isAuth };
}
export function useGoLogin() {
  const router = Taro.useRouter();
  function goLoginFn() {
    Taro.navigateTo({
      url: `${RouterPath.authorization}?redirect=${router.path}&${object2query(router.params)}`,
    });
  }
  return {
    goLoginFn,
  };
}
apps/bMiniApp/src/index.html
New file
@@ -0,0 +1,17 @@
<!DOCTYPE html>
<html>
<head>
  <meta content="text/html; charset=utf-8" http-equiv="Content-Type">
  <meta content="width=device-width,initial-scale=1,user-scalable=no" name="viewport">
  <meta name="apple-mobile-web-app-capable" content="yes">
  <meta name="apple-touch-fullscreen" content="yes">
  <meta name="format-detection" content="telephone=no,address=no">
  <meta name="apple-mobile-web-app-status-bar-style" content="white">
  <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" >
  <title>vue-mini</title>
  <script><%= htmlWebpackPlugin.options.script %></script>
</head>
<body>
  <div id="app"></div>
</body>
</html>
apps/bMiniApp/src/pages/home/index.config.ts
New file
@@ -0,0 +1,5 @@
export default definePageConfig({
  navigationStyle: 'custom',
  disableScroll: true,
  navigationBarTextStyle: 'white',
});
apps/bMiniApp/src/pages/home/index.scss
New file
@@ -0,0 +1,5 @@
@import '@/styles/common.scss';
page {
  background-color: #fff;
}
apps/bMiniApp/src/pages/home/index.vue
New file
@@ -0,0 +1,52 @@
<template>
  <PageLayoutWithBg class="index-page-wrapper" :title="'首页'" :need-auth="false">
    <template #left>
      <div class="menu-btn-wrapper city-btn" @click="goCitySelect">
        <div class="city-btn-text">{{ locationCity }}</div>
        <RectDown :size="12" />
      </div>
    </template>
  </PageLayoutWithBg>
</template>
<script setup lang="ts">
import { useUser } from '@/hooks';
import { useUserStore } from '@/stores/modules/user';
import { RectDown } from '@nutui/icons-vue-taro';
import Taro from '@tarojs/taro';
import { LocationUtils } from '@12333/utils';
const { locationCity } = useUser();
const userStore = useUserStore();
function goCitySelect() {
  Taro.navigateTo({
    url: RouterPath.citySelect,
  });
}
// onMounted(async () => {
//   if (!isSetMatchMakingIdentity.value) {
//     Taro.navigateTo({
//       url: RouterPath.toggleMatchMakingIdentity,
//     });
//   }
// });
</script>
<style lang="scss">
@import '@/styles/common.scss';
.index-page-wrapper {
  .city-btn {
    display: flex;
    align-items: center;
    .city-btn-text {
      max-width: 200px;
      @include ellipsis;
      margin-right: 12px;
    }
  }
}
</style>
apps/bMiniApp/src/pages/mine/index.config.ts
New file
@@ -0,0 +1,7 @@
export default definePageConfig({
  navigationBarTitleText: 'Mine',
  usingComponents: {},
  disableScroll: true,
  navigationBarTextStyle: 'white',
  enableShareAppMessage: true,
});
apps/bMiniApp/src/pages/mine/index.scss
New file
@@ -0,0 +1,151 @@
@import '@/styles/common.scss';
.mine-page-bg {
  position: fixed;
  z-index: -1;
  top: 0;
  left: 0;
  width: 750px;
  height: 434px;
  object-fit: cover;
}
.mine-page-wrapper {
  .mine-avatar-wrapper {
    flex: 1;
    min-width: 0;
    display: flex;
    .mine-avatar {
      margin-right: 24px;
    }
    .user-info {
      flex: 1;
      min-width: 0;
      display: flex;
      flex-direction: column;
      padding: 12px 0;
      justify-content: space-between;
      .user-info-item {
        font-weight: 600;
        font-size: 32px;
        color: #ffffff;
        line-height: 44px;
        @include ellipsis;
      }
      .user-info-item2 {
        font-weight: 400;
        font-size: 24px;
        color: #ffffff;
        line-height: 34px;
      }
      .user-info-unCertified {
        display: inline-flex;
        align-items: center;
        height: 40px;
        background: #fffae0;
        border-radius: 4px;
        padding: 0 8px;
        width: fit-content;
        .user-info-unCertified-icon {
          width: 28px;
          height: 28px;
        }
        .user-info-unCertified-text {
          font-weight: 400;
          font-size: 22px;
          color: #a0541e;
          line-height: 24px;
        }
      }
    }
    .mine-go-login {
      font-size: 40px;
      color: #fff;
      line-height: 120px;
    }
  }
  .mine-content-scroll-view {
    padding-top: 26px;
    .mine-id-menu-wrapper {
      height: 124px;
      background: url('https://renliyuan.oss-cn-hangzhou.aliyuncs.com/12333/matchMakingMini/assets/mine/icon-id-bg.png')
        no-repeat;
      background-size: cover;
      display: flex;
      align-items: center;
      padding: 0 boleGetCssVar('size', 'body-padding-h');
      margin-bottom: 24px;
      .mine-id-menu-icon {
        width: 24px;
        height: 36px;
        margin-right: 16px;
      }
      .mine-id-menu-text {
        font-weight: 400;
        font-size: 28px;
        color: #ffffff;
        line-height: 40px;
        flex: 1;
        min-width: 0;
      }
      .mine-id-menu-btn {
        width: 152px;
        height: 52px;
        background: #ffffff;
        border-radius: 26px;
        font-weight: bold;
        font-size: 24px;
        color: #444444;
        line-height: 52px;
        text-align: center;
      }
    }
    .mine-menu-list {
      display: flex;
      gap: 30px;
      margin-bottom: 24px;
      .mine-menu-list-item {
        flex: 1;
        min-width: 0;
        display: flex;
        align-items: center;
        height: 152px;
        background: #ffffff;
        border-radius: 8px;
        padding-left: 48px;
        .mine-menu-list-item-icon {
          width: 72px;
          height: 72px;
          margin-right: 24px;
        }
        .mine-menu-list-item-text {
          font-weight: 400;
          font-size: 28px;
          color: #333333;
          line-height: 40px;
        }
      }
    }
    .mine-setting-list {
      border-radius: 8px;
    }
  }
}
apps/bMiniApp/src/pages/mine/index.vue
New file
@@ -0,0 +1,110 @@
<template>
  <PageLayout class="mine-page-wrapper" :need-auth="false">
    <template #navigationBar>
      <TransparentNavigationBar
        title="个人中心"
        :is-absolute="false"
        mode="dark"
      ></TransparentNavigationBar>
    </template>
    <template #bg>
      <img :src="OssAssets.mine.Bg" class="mine-page-bg" :style="{ height: `${bgHeight}px` }" />
    </template>
    <ContentView>
      <UserHomeTopView :showUserHomePageBtn="isLogin" :showOperation="isLogin">
        <template #avatar>
          <div class="mine-avatar-wrapper" @click="goLogin">
            <UserAvatar :size="60" class="mine-avatar" />
            <div class="user-info" v-if="isLogin">
              <div class="user-info-item">{{ userDetail?.userName ?? '' }}</div>
              <div class="user-info-item2" v-if="isCertified">
                {{ userDetail?.customerName ?? '' }}
              </div>
              <div class="user-info-unCertified" v-else @click.stop="goAuthentication">
                <img :src="IconUnCertified" class="user-info-unCertified-icon" />
                <div class="user-info-unCertified-text">未认证</div>
              </div>
            </div>
            <div class="mine-go-login" v-else>去登录</div>
          </div>
        </template>
      </UserHomeTopView>
    </ContentView>
    <ContentScrollView v-if="isLogin" class="mine-content-scroll-view">
      <div class="mine-id-menu-wrapper">
        <img :src="IconLamp" class="mine-id-menu-icon" />
      </div>
      <List class="mine-setting-list">
        <ListItem :icon="IconSetting" title="设置" @click="goSetting"></ListItem>
      </List>
    </ContentScrollView>
  </PageLayout>
</template>
<script setup lang="ts">
import {
  PageLayout,
  TransparentNavigationBar,
  ContentScrollView,
  UserHomeTopView,
} from '@/components';
import IconUnCertified from '@/assets/mine/icon-unCertified.png';
import IconLamp from '@/assets/mine/icon-lamp.png';
import IconMenuBusiness from '@/assets/mine/icon-menu-business.png';
import IconMenuContact from '@/assets/mine/icon-menu-contact.png';
import IconSetting from '@/assets/mine/icon-setting.png';
import IconMessage from '@/assets/mine/icon-message.png';
import { useUser, useIsLogin, useGoLogin } from '@/hooks';
import Taro from '@tarojs/taro';
import { RouterPath, OssAssets } from '@/constants';
import { List, ListItem } from '@12333/components';
import { useSystemStore } from '@/stores/modules/system';
const { userDetail, isCertified } = useUser();
const isLogin = useIsLogin();
const systemStore = useSystemStore();
const { goLoginFn } = useGoLogin();
const bgHeight = computed(() => 133 + systemStore.navHeight);
function goLogin() {
  if (!isLogin.value) {
    goLoginFn();
  }
}
function goPage(routeName: string) {
  Taro.navigateTo({
    url: routeName,
  });
}
function goSetting() {
  // goPage(RouterPath.setting);
}
Taro.showShareMenu({
  showShareItems: ['shareAppMessage'],
});
Taro.useShareAppMessage((res) => {
  return {
    title: `${userDetail.value?.contacter}名片`,
    // path: `${RouterPath.userHomePage}?userId=${userDetail.value?.userId}`,
    imageUrl: userDetail.value?.avatarUrl,
  };
});
function goAuthentication() {
  goPage(RouterPath.authenticationHome);
}
</script>
<style lang="scss">
@import '@/styles/common.scss';
@import './index.scss';
.mine-setting-badge {
  margin-right: 20px;
}
</style>
apps/bMiniApp/src/stores/index.ts
New file
@@ -0,0 +1,10 @@
import type { App } from 'vue';
import { createPinia } from 'pinia';
const store = createPinia();
export function setupStore(app: App<Element>) {
  app.use(store);
}
export { store };
apps/bMiniApp/src/stores/modules/system.ts
New file
@@ -0,0 +1,116 @@
import Taro from '@tarojs/taro';
import { defineStore } from 'pinia';
import { store } from '@/stores';
export interface Options {
  path: string;
  scene: number;
  query: object;
  shareTicket: string;
  referrerInfo: object;
  tabIndex: number;
  IPhoneXPadding: number;
  navHeight: number;
  safeAreaTop: number;
  buttonBottom: number;
  redirectPath: string;
  isTabSwitch: boolean;
  isFirstEnter: boolean;
}
export const useSystemStore = defineStore({
  id: 'app-system',
  /** 状态 */
  state: () => ({
    options: {} as Options,
    activeTab: 0,
    info: {} as Taro.getSystemInfoSync.Result,
    designWidth: 750,
    screenHeight: 0,
    screenWidth: 0,
    pageHeightWithTab: 0,
    pageHeight: 0,
    IPhoneXPadding: 0,
    navHeight: 0,
    bottomNavHeight: 0,
    safeAreaTop: 0,
    navigationBarHeight: 0,
    //右上角胶囊按钮高度
    menuButtonHeight: 0,
    menuButtonWidth: 0,
    menuButtonRightDistance: 0,
    menuButtonTop: 0,
    isFirstEnter: true,
  }),
  actions: {
    init(options: Options) {
      this.options = options; // 放一下页面相关的数据例如scene等 页面高度之类的不存!
    },
    setInfo(info: Taro.getSystemInfoSync.Result) {
      this.info = info;
      console.log('info: ', info);
      this.setNavigationBarHeight(info);
      this.screenHeight = info.screenHeight;
      this.screenWidth = info.screenWidth;
      this.IPhoneXPadding = info.screenHeight - info.safeArea.bottom;
      this.navHeight = info.statusBarHeight + this.navigationBarHeight;
      this.safeAreaTop = info.safeArea.top;
      const scale = info.screenWidth / this.designWidth;
      /**
       * 100为底部tabber的高度
       */
      this.bottomNavHeight = 118 * scale;
      this.pageHeight = info.screenHeight - this.navHeight - this.IPhoneXPadding; // 无底部tabber
      this.pageHeightWithTab = this.pageHeight - this.bottomNavHeight; // 有底部tabber
    },
    setNavigationBarHeight(systemInfo: Taro.getSystemInfoSync.Result) {
      const { right, height, width, top } = Taro.getMenuButtonBoundingClientRect();
      let navigationBarHeight = 0;
      if (systemInfo.platform === 'android') {
        navigationBarHeight = 48;
      } else {
        navigationBarHeight = 44;
      }
      this.menuButtonHeight = height;
      this.menuButtonWidth = width;
      this.menuButtonTop = top;
      this.menuButtonRightDistance = systemInfo.screenWidth - right;
      this.navigationBarHeight = navigationBarHeight;
    },
    setTabIndex(tabIndex: number) {
      this.activeTab = tabIndex;
    },
    setIsFirstEnter(isFirstEnter: boolean) {
      this.isFirstEnter = isFirstEnter;
    },
  },
});
// Need to be used outside the setup
export function useSystemStoreWithOut() {
  return useSystemStore(store);
}
apps/bMiniApp/src/stores/modules/user.ts
New file
@@ -0,0 +1,312 @@
import { defineStore } from 'pinia';
import { store } from '@/stores';
import {
  getToken as getCacheToken,
  getUserInfo as getCacheUserInfo,
  setUserInfo,
  removeUserInfo,
  setUserDetail,
  getUserDetail,
  removeUserDetail,
  removeMatchMakingIdentity,
  getMatchMakingIdentity,
  setMatchMakingIdentity,
} from '@/utils/storage/auth';
import * as accountServices from '@12333/services/api/Account';
import * as userServices from '@12333/services/api/User';
import Taro, { useRouter } from '@tarojs/taro';
import { ButtonProps } from '@tarojs/components';
import { debounce } from 'lodash';
import { goHome, getStorageLocationCity, setStorageLocationCity } from '@/utils';
import {
  getAccountInfoFromAccessToken,
  AccountInfo,
  setOSSLink,
  getUserCertificationFrontStatusAdapter,
  LocationUtils,
} from '@12333/utils';
import DefaultAvatar from '@/assets/components/icon-default-avatar.png';
import { WxMiniAppEnum } from '@12333/constants';
import { myClient } from '@/constants/query';
import { globalEventEmitter } from '@12333/hooks';
interface UserState {
  userInfo?: Nullable<API.IdentityModelTokenCacheItem>;
  token?: Nullable<string>;
  refreshToken?: Nullable<string>;
  userDetail?: Nullable<API.UserInfoV2>;
  firstGetUserDetail?: boolean;
  locationCity?: string;
  locationProvince?: string;
  firstSetLocation?: boolean;
}
const goAuthorization = debounce(
  () => {
    const route = Taro.getCurrentInstance().router;
    if (route.path !== RouterPath.authorization) {
      Taro.navigateTo({
        url: RouterPath.authorization,
      });
    }
  },
  300,
  {
    leading: true,
    trailing: false,
  }
);
export const useUserStore = defineStore({
  id: 'app-user',
  state: (): UserState => {
    const userInfo = getCacheUserInfo();
    const userDetail = getUserDetail();
    const storageLocation = getStorageLocationCity();
    return {
      // user info
      userInfo: userInfo,
      // token
      token: userInfo?.accessToken ?? '',
      refreshToken: userInfo?.refreshToken ?? '',
      userDetail: userDetail,
      firstGetUserDetail: true,
      locationCity: storageLocation?.city ?? '北京市',
      locationProvince: storageLocation?.province ?? '北京',
      firstSetLocation: true,
    };
  },
  getters: {
    cacheToken: (state) => {
      if (!state.token) {
        const storageToken = getCacheToken() as API.IdentityModelTokenCacheItem;
        state.token = storageToken.accessToken;
      }
      return state.token || null;
    },
    cacheRefreshToken: (state) => {
      return state.refreshToken;
    },
    accountInfo(): Partial<AccountInfo> {
      return getAccountInfoFromAccessToken(this.userInfo?.accessToken);
    },
    // matchMakingIdentity(state): MatchMakingIdentityEnum {
    // },
  },
  actions: {
    // 手机号授权Code登录
    async getTokenByPhone(
      detail: ButtonProps.onGetPhoneNumberEventDetail,
      wxMiniAppUserLoginRes: any
    ) {
      try {
        let res: API.IdentityModelTokenCacheItem;
        if (!wxMiniAppUserLoginRes.accessToken) {
          let params: API.WxMiniAppPhoneLoginInput = {
            openId: wxMiniAppUserLoginRes.openId,
            sessionKey: wxMiniAppUserLoginRes.sessionKey,
            encryptedData: detail.encryptedData,
            iv: detail.iv,
            wxMiniApp: WxMiniAppEnum.人单合一,
          };
          res = await accountServices.wxMiniAppPhoneAuthLogin(params);
          this.loginSuccess(res);
        }
        return res;
      } catch (error) {
        console.log('error3: ', error);
      }
    },
    // 用户手机验证码登入
    async loginByUsername(data: API.PhoneMesssageCodeLoginInput) {
      let res = await accountServices.phoneMesssageCodeLogin(
        {
          phoneNumber: data.phoneNumber,
          code: data.code,
        },
        { showLoading: false }
      );
      if (res) {
        this.loginSuccess(res);
      }
      return res;
    },
    // 用户账号密码登入
    async loginByPassword(data: API.AccessRequestDto) {
      let res = await accountServices.passwordLogin(
        {
          loginName: data.userName,
          password: data.userPassword,
        },
        { showLoading: false }
      );
      if (res) {
        this.loginSuccess(res);
      }
      return res;
    },
    async loginSuccess(res: API.IdentityModelTokenCacheItem) {
      try {
        this.setUserInfoAction(res);
        this.setTokenAction(res);
        await this.getCurrentUserInfo();
      } catch (error) {}
    },
    async wxMiniAppUserLoginFromScan(wxIndentityRes: API.WxMiniAppIndentityInfo, uuid: string) {
      try {
        let res = await accountServices.wxMiniAppUserLoginFromScan({
          uId: uuid,
          userName: wxIndentityRes.userName,
          openId: wxIndentityRes.openId,
        });
        this.loginSuccess(res);
        return res;
      } catch (error) {}
    },
    async wxMiniAppPhoneAuthLoginFromScan(
      detail: ButtonProps.onGetPhoneNumberEventDetail,
      wxIndentityRes: API.WxMiniAppIndentityInfo,
      uuid: string
    ) {
      try {
        let res = await accountServices.wxMiniAppPhoneAuthLoginFromScan({
          uId: uuid,
          openId: wxIndentityRes.openId,
          sessionKey: wxIndentityRes.sessionKey,
          encryptedData: detail.encryptedData,
          iv: detail.iv,
          wxMiniApp: WxMiniAppEnum.人单合一,
        });
        this.loginSuccess(res);
        return res;
      } catch (error) {}
    },
    async getCurrentUserInfo() {
      try {
        let res = await userServices.getUserInfo({ showLoading: false });
        if (res) {
          res.frontStatus = getUserCertificationFrontStatusAdapter(
            res.userCertificationStatus,
            res.userCertificationAuditStatus
          );
          res.originalAvatarUrl = res.avatarUrl;
          res.avatarUrl = res.avatarUrl ? setOSSLink(res.avatarUrl) : DefaultAvatar;
          this.setUserDetail(res);
          this.firstGetUserDetail = false;
        }
      } catch (error) {}
    },
    setTokenAction(tokenInfo: API.IdentityModelTokenCacheItem) {
      this.token = tokenInfo?.accessToken;
      this.refreshToken = tokenInfo.refreshToken ?? '';
    },
    setUserInfoAction(info: API.IdentityModelTokenCacheItem) {
      this.userInfo = info;
      setUserInfo(info);
    },
    setUserDetail(detail: API.UserInfoV2) {
      this.userDetail = detail;
      setUserDetail(detail);
    },
    resetState() {
      this.userInfo = null;
      this.token = '';
      this.refreshToken = '';
      this.userDetail = null;
      removeUserInfo();
      removeUserDetail();
      removeMatchMakingIdentity();
    },
    /**
     * @description: logout
     */
    logout() {
      this.resetState();
      myClient.removeQueries();
      goAuthorization();
    },
    logoutAndToHome() {
      this.resetState();
      goHome();
    },
    toLoginPage(targetUrl?: string) {
      // 存 登录后跳转目标页
      if (targetUrl) {
        // tabbar 跳转:不是在具体页面判断用户是否登录
      } else {
        // 页面里 跳转登录页 存当前页面路径 已供登陆后
        const currentPage = useRouter();
        // const params = omit(currentPage.params, '$taroTimestamp');
        console.log(currentPage.params);
        // 直接用currentPage.path,params 会丢失
        Taro.redirectTo({
          url: `/packageLogin/authLogin/index`,
        });
      }
    },
    async getTokenByRefreshToken(params: API.AccessRefreshToken) {
      try {
        const res = await accountServices.getTokenByRefreshToken(params, {
          showLoading: false,
        });
        if (res) {
          this.setTokenAction(res);
          this.setUserInfoAction(res);
          return res;
        } else {
          throw new Error('刷新token失败');
        }
      } catch (error) {
        throw new Error('error');
      }
    },
    setLocationCity(cityName: string, provinceName: string) {
      this.locationCity = cityName;
      this.locationProvince = provinceName;
      this.firstSetLocation = false;
      setStorageLocationCity({ city: cityName, province: provinceName });
      if (LocationUtils.isProvinceChange(provinceName)) {
        this.resetState();
        myClient.removeQueries();
        globalEventEmitter.trigger('logout/refresh');
        // myClient.invalidateQueries({
        //   queryKey: ['logout/refresh'],
        // });
      }
      LocationUtils.currentProvinceName = provinceName;
    },
  },
});
// Need to be used outside the setup
export function useUserStoreWithOut() {
  return useUserStore(store);
}
apps/bMiniApp/src/styles/common.scss
New file
@@ -0,0 +1,6 @@
@forward './custom_theme.scss';
@forward './var.scss';
@forward './function.scss';
@forward './hairline.scss';
@forward './mixins.scss';
@forward 'sass:map';
apps/bMiniApp/src/styles/config.scss
New file
@@ -0,0 +1,5 @@
$bole-namespace: 'bole' !default;
$bole-separator: '-' !default;
$bole-element-separator: '__' !default;
$bole-modifier-separator: '--' !default;
$bole-state-prefix: 'is-' !default;
apps/bMiniApp/src/styles/custom_theme.scss
New file
@@ -0,0 +1,11 @@
$primary-color: #3a71ff;
$primary-color-end: #496af2;
$form-item-error-line-color: #fa2c19;
$form-item-required-color: #fa2c19;
$form-item-error-message-color: #fa2c19;
$button-border-width: 0;
$button-primary-background-color: $primary-color;
$body-background-color: #f9f9fb;
apps/bMiniApp/src/styles/font.scss
New file
@@ -0,0 +1,7 @@
@font-face {
  font-family: D-DIN; /* Project id 4331987 */
  src: url('../assets/font/D-DIN.otf') format('otf');
  //   url('@/assets/font/D-DIN') format('otf');
  // url('iconfont.woff?t=1700036113989') format('woff'),
  // url('iconfont.ttf?t=1700036113989') format('truetype');
}
apps/bMiniApp/src/styles/function.scss
New file
@@ -0,0 +1,78 @@
/* stylelint-disable */
@use 'sass:map';
@use './config.scss';
@mixin bole-set-css-var-value($name, $value) {
  #{boleJoinVarName($name)}: #{$value};
}
@function boleJoinVarName($list) {
  $name: '--' + config.$bole-namespace;
  @each $item in $list {
    @if $item != '' {
      $name: $name + '-' + $item;
    }
  }
  @return $name;
}
// getCssVar('button', 'text-color') => var(--bole-button-text-color)
@function boleGetCssVar($args...) {
  @return var(#{boleJoinVarName($args)});
}
// getCssVarName('button', 'text-color') => '--bole-button-text-color'
@function boleGetCssVarName($args...) {
  @return boleJoinVarName($args);
}
// getCssVarWithDefault(('button', 'text-color'), red) => var(--el-button-text-color, red)
@function boleGetCssVarWithDefault($args, $default) {
  @return var(#{boleJoinVarName($args)}, #{$default});
}
// set all css var for component by map
@mixin bole-set-component-css-var($name, $variables) {
  @each $attribute, $value in $variables {
    @if $attribute == 'default' {
      #{boleGetCssVarName($name)}: #{$value};
    } @else {
      #{boleGetCssVarName($name, $attribute)}: #{$value};
    }
  }
}
// bem('block', 'element', 'modifier') => 'el-block__element--modifier'
@function bem($block, $element: '', $modifier: '') {
  $name: config.$bole-namespace + config.$bole-separator + $block;
  @if $element != '' {
    $name: $name + config.$bole-element-separator + $element;
  }
  @if $modifier != '' {
    $name: $name + config.$bole-modifier-separator + $modifier;
  }
  // @debug $name;
  @return $name;
}
@mixin bole-set-css-color-type($colors, $type) {
  @include bole-set-css-var-value(('color', $type), map.get($colors, $type, 'base'));
  @each $i in (3, 5, 7, 8, 9) {
    @include bole-set-css-var-value(
      ('color', $type, 'light', $i),
      map.get($colors, $type, 'light-#{$i}')
    );
  }
  @include bole-set-css-var-value(('color', $type, 'dark-2'), map.get($colors, $type, 'dark-2'));
}
@function mapGet($args1, $args2) {
  @return map.get($args1, $args2);
}
apps/bMiniApp/src/styles/hairline.scss
New file
@@ -0,0 +1,200 @@
$color-border-light: #eaeaea;
@mixin hairline-common() {
  content: '';
  position: absolute;
  transform-origin: center;
  box-sizing: border-box;
  pointer-events: none;
}
@mixin hairline() {
  @include hairline-common();
  top: -50%;
  right: -50%;
  bottom: -50%;
  left: -50%;
  border: 0 solid $color-border-light;
  transform: scale(0.5);
}
@mixin hairline-base($color: $color-border-light, $style: solid) {
  @include hairline-common();
  top: -50%;
  left: -50%;
  right: -50%;
  bottom: -50%;
  border: 0 $style $color;
  transform: scale(0.5);
}
@mixin hairline-surround($color: $color-border-light, $style: solid, $width: 1px) {
  position: relative;
  &::after {
    @include hairline-base($color, $style);
    border-width: $width;
  }
}
@mixin hairline-top($color: $color-border-light, $style: solid, $width: 1px) {
  position: relative;
  &::after {
    @include hairline-base($color, $style);
    border-top-width: $width;
  }
}
@mixin hairline-bottom($color: $color-border-light, $style: solid, $width: 1px) {
  position: relative;
  &::after {
    @include hairline-base($color, $style);
    border-bottom-width: $width;
  }
}
@mixin hairline-left($color: $color-border-light, $style: solid, $width: 1px) {
  position: relative;
  &::after {
    @include hairline-base($color, $style);
    border-left-width: $width;
  }
}
@mixin hairline-right($color: $color-border-light, $style: solid, $width: 1px) {
  position: relative;
  &::after {
    @include hairline-base($color, $style);
    border-right-width: $width;
  }
}
@mixin hairline-top-bottom($color: $color-border-light, $style: solid, $width: 1px) {
  position: relative;
  &::after {
    @include hairline-base($color, $style);
    border-top-width: $width;
    border-bottom-width: $width;
  }
}
@mixin hairline-bottom-relative($color: $color-border-light, $style: solid, $width: 1px, $left: 0) {
  position: relative;
  &::after {
    @include hairline-common();
    top: auto;
    left: $left;
    right: 0;
    bottom: 0;
    transform: scaleY(0.5);
    border-bottom: $width $style $color;
  }
}
@mixin hairline-top-relative($color: $color-border-light, $style: solid, $width: 1px, $left: 0) {
  position: relative;
  &::before {
    @include hairline-common();
    top: 0;
    left: $left;
    right: 0;
    bottom: auto;
    transform: scaleY(0.5);
    border-top: $width $style $color;
  }
}
@mixin hairline-left-relative($color: $color-border-light, $style: solid, $width: 1px, $top: 0) {
  position: relative;
  &::after {
    @include hairline-common();
    top: $top;
    left: 0;
    right: auto;
    bottom: 0;
    transform: scaleX(0.5);
    border-left: $width $style $color;
  }
}
@mixin hairline-right-relative($color: $color-border-light, $style: solid, $width: 1px, $top: 0) {
  position: relative;
  &::after {
    @include hairline-common();
    top: $top;
    left: auto;
    right: 0;
    bottom: 0;
    transform: scaleX(0.5);
    border-right: $width $style $color;
  }
}
.van-hairline--bottom {
  @include hairline-bottom(#ddd, 0, 0);
}
[class*='van-hairline'] {
  &::after {
    @include hairline();
  }
}
.van-hairline {
  &,
  &--top,
  &--left,
  &--right,
  &--bottom,
  &--surround,
  &--top-bottom {
    position: relative;
  }
  &--top::after {
    border-top-width: 1px;
  }
  &--left::after {
    border-left-width: 1px;
  }
  &--right::after {
    border-right-width: 1px;
  }
  &--bottom::after {
    border-bottom-width: 1px;
  }
  &,
  &-unset {
    &--top-bottom::after {
      border-width: 1px 0;
    }
  }
  &--surround::after {
    border-width: 1px;
  }
}
apps/bMiniApp/src/styles/index.scss
New file
@@ -0,0 +1,83 @@
@use './var.scss' as *;
@use './function.scss' as *;
@use './reset.scss' as *;
@use './nut.scss' as *;
@use './mixins.scss' as *;
@use './font.scss' as *;
@use 'sass:map';
@use 'senin-mini/dist/styles/index.scss' as *;
:root,
page {
  @include bole-set-component-css-var('color', $bole-colors);
  @include bole-set-component-css-var('text-color', $bole-text-color);
  @include bole-set-component-css-var('size', $bole-size);
  background-color: map-get($bole-colors, 'body-background-color');
  font-family: Source Han Sans CN, 'PingFang SC', 'miui', 'Microsoft Yahei', BlinkMacSystemFont,
    'Helvetica Neue', Helvetica, Segoe UI, Arial, Roboto, 'Hiragino Sans GB', sans-serif;
  --primary-color: #{map-get($bole-colors, 'primary')};
  overflow: hidden;
  --nut-primary-color: #{map-get($bole-colors, 'primary')};
  --nut-primary-color-end: $primary-color-end;
  --nut-tag-success-background-color: #d0f8e2;
  --nut-tag-danger-background-color: #ffe5e5;
  --nut-badge-background-color: #{map-get($bole-colors, 'danger')};
}
.clearfix:after {
  content: '';
  display: block;
  height: 0;
  clear: both;
  visibility: hidden;
}
.clearfix {
  /* 触发 hasLayout */
  zoom: 1;
}
// 解决iPhone x 以后的机型 底部安全区域的问题 https://jelly.jd.com/article/6006b1055b6c6a01506c87fd
.safe-area-bottom {
  padding-bottom: constant(safe-area-inset-bottom);
  padding-bottom: env(safe-area-inset-bottom);
}
.primary {
  color: boleGetCssVar('color', 'primary');
}
.warning {
  color: boleGetCssVar('color', 'warning');
}
.danger {
  color: boleGetCssVar('color', 'danger');
}
.success {
  color: boleGetCssVar('color', 'success');
}
.common-infinite-scroll-list-no-padding {
  @include listScrollViewWithNoPadding;
}
.common-infinite-scroll-list {
  @include listScrollView;
}
.common-page-infinite-scroll-list {
  @include listScrollView;
  padding-top: 16px;
}
.id-imgUrl-wrapper {
  display: flex;
  gap: 40px;
}
apps/bMiniApp/src/styles/mixins.scss
New file
@@ -0,0 +1,76 @@
@use './var.scss' as *;
@mixin multi-ellipsis($lines) {
  display: -webkit-box;
  overflow: hidden;
  text-overflow: ellipsis;
  -webkit-line-clamp: $lines;
  -webkit-box-orient: vertical;
}
@mixin ellipsis() {
  overflow: hidden;
  white-space: nowrap;
  text-overflow: ellipsis;
}
.ellipsis {
  @include ellipsis();
}
.multi-ellipsis--l2 {
  @include multi-ellipsis(2);
}
.multi-ellipsis--l3 {
  @include multi-ellipsis(3);
}
.multi-ellipsis--l9 {
  @include multi-ellipsis(9);
}
@mixin infiniteLoadingInTabBarPage {
  .loading-more-tips,
  .infiniting-tips {
    padding-bottom: 40px;
  }
}
@mixin safe-area-bottom() {
  padding-bottom: constant(safe-area-inset-bottom);
  padding-bottom: env(safe-area-inset-bottom);
}
@mixin listScrollViewWithNoPadding {
  flex: 1;
  min-height: 0;
  box-sizing: border-box;
}
@mixin listScrollView {
  padding: 0 map-get($bole-size, 'body-padding-h');
  @include listScrollViewWithNoPadding;
}
@mixin infiniteLoadingInTabBarPage {
  .loading-more-tips,
  .infiniting-tips {
    padding-bottom: 50px;
  }
}
@mixin ScrollViewInner {
  // padding: 20px 0;
  padding-bottom: 24px;
}
@mixin hiddenScrollBar {
  ::-webkit-scrollbar {
    display: none;
    width: 0;
    height: 0;
    color: transparent;
  }
}
apps/bMiniApp/src/styles/nut.scss
New file
@@ -0,0 +1,160 @@
@use './function.scss' as *;
@use './hairline.scss' as *;
:root,
page {
  .category-searchbar-container {
    padding: 30px;
  }
  .h5-view.nut-popup.nut-popup--bottom {
    padding-bottom: constant(safe-area-inset-bottom);
    padding-bottom: env(safe-area-inset-bottom);
  }
  .nut-button.dark-btn {
    color: boleGetCssVar('text-color', 'primary') !important;
  }
  .nut-form {
    .nut-cell-group__wrap {
      margin-top: 0;
      border-radius: 0;
    }
    .nut-cell.bole-form-item {
      --nut-form-item-label-width: 120px;
      &:not(.alignTop) {
        align-items: center !important;
      }
      &.labelTop {
        display: block;
      }
      padding: 30rpx;
      &::after {
        border-bottom: 1px solid #f0f0f0;
        left: 30rpx;
        right: 30rpx;
        display: none;
      }
      .nut-form-item__body__tips {
        position: absolute;
        bottom: 0;
      }
      &:not(.bole-form-item-phone) {
        .nut-form-item__body__tips {
          right: 30rpx;
        }
      }
      .nut-form-item__label {
        font-size: 28rpx;
        color: boleGetCssVar('text-color', 'primary');
      }
      &.vertical {
        flex-direction: column;
        align-items: flex-start !important;
      }
      .nut-form-item__label.required::before {
        position: absolute;
        left: 12rpx;
      }
      .nut-radio-group--horizontal {
        .nut-radio {
          margin-bottom: 0;
          vertical-align: middle;
        }
      }
      .nut-rate {
        vertical-align: middle;
      }
      &.hidden-label {
        .nut-form-item__label {
          opacity: 0;
        }
      }
      .bole-uploader {
        padding-top: 16rpx;
        &.nopaddingtop {
          padding-top: 0;
        }
      }
    }
    .bole-form-item-phone {
      padding: 24rpx 30rpx;
    }
    .nut-uploader {
      // justify-content: flex-end;
    }
  }
  .bole-input-text:not(.nut-input--disabled) {
    .h5-input {
      color: boleGetCssVar('text-color', 'primary') !important;
      display: block;
      font-size: 26rpx;
    }
    .input-placeholder {
      color: boleGetCssVar('text-color', 'placeholder') !important;
      font-size: 26rpx;
    }
  }
  .bole-input-textarea:not(.nut-input--disabled) {
    color: boleGetCssVar('text-color', 'primary') !important;
    height: 100rpx;
  }
  .bole-input-text-placeholder {
    color: boleGetCssVar('text-color', 'placeholder') !important;
    font-size: 26rpx;
    line-height: 20rpx;
  }
  .form-item-divider {
    margin: 0 28px;
    width: calc(100% - 56px);
    color: #f0f0f0;
  }
  // .nut-overlay {
  //   z-index: 20022221 !important;
  // }
  // .nut-popup {
  //   z-index: 2222222222 !important;
  // }
  .nut-tabs__titles-item__smile {
    // display: none;
    opacity: 0;
    transition: width 0.3s ease;
  }
  .nut-tabs__titles.smile .nut-tabs__titles-item.active .nut-tabs__titles-item__smile {
    // display: block;
    opacity: 1;
  }
  .nut-toast {
    z-index: 99999999999;
  }
  .pro-form-item-tips {
    word-break: break-all;
  }
}
apps/bMiniApp/src/styles/reset.scss
New file
@@ -0,0 +1,30 @@
h1,
h2,
h3,
h4,
h5,
h6,
strong,
p,
ul,
input,
i,
b,
em,
li,
ol,
dl,
dd,
page {
  font: 32px Source Han Sans CN;
  font-family: Source Han Sans CN, 'PingFang SC', 'miui', 'Microsoft Yahei', BlinkMacSystemFont,
    'Helvetica Neue', Helvetica, Segoe UI, Arial, Roboto, 'Hiragino Sans GB', sans-serif;
  margin: 0;
  padding: 0;
  list-style: none;
}
img {
  border: none;
  display: block;
}
apps/bMiniApp/src/styles/var.scss
New file
@@ -0,0 +1,35 @@
@use './custom_theme.scss' as *;
@use 'sass:map';
@use 'sass:math';
$bole-colors: () !default;
$bole-colors: map.deep-merge(
  (
    'primary': $primary-color,
    'body-background-color': $body-background-color,
    'title-color': #444444,
    'shadow-color': rgba(0, 0, 0, 0.15),
    'warning': #ef9c00,
    'danger': #fe3333,
    'success': #31b573,
    'info': #e9e8e8,
  ),
  $bole-colors
);
$bole-text-color: (
  'primary': #444444,
  'regular': #7c7c7c,
  'secondary': #9e9e9e,
  'placeholder': #cbcbcb,
);
$bole-size: () !default;
$bole-size: map.deep-merge(
  (
    'body-padding-h': 28px,
  ),
  $bole-size
);
$base-footer-box-shadow: 0px -10px 40px 0px map-get($bole-colors, 'shadow-color');
apps/bMiniApp/src/subpackages/authentication/authenticationFaRen/InnerPage.vue
New file
@@ -0,0 +1,216 @@
<template>
  <ContentScrollView :paddingH="false">
    <nut-form :model-value="form" ref="formRef" :rules="rules">
      <nut-form-item label="营业执照:" class="bole-form-item alignTop" prop="licenseUrl" required>
        <Uploader
          v-model:file-list="form.licenseUrl"
          :maximum="1"
          :limitFileSize="10"
          class="bole-uploader nopaddingtop"
          @my-success="handleLicenseUrlChange"
        >
        </Uploader>
        <div class="pro-form-item-tips">
          请上传最新的营业执照原件照片、扫描件或加盖公章的复印件,支持png/jpg/jpeg格式,文件大小不超过10MB
        </div>
      </nut-form-item>
      <nut-form-item label="企业全称:" class="bole-form-item" prop="enterpriseName" required>
        <nut-input
          v-model.trim="form.enterpriseName"
          class="nut-input-text bole-input-text"
          placeholder="请输入您营业执照上的企业名称"
          type="text"
          :max-length="35"
        />
      </nut-form-item>
      <nut-form-item
        label="统一社会信用代码:"
        class="bole-form-item"
        prop="societyCreditCode"
        required
      >
        <nut-input
          v-model.trim="form.societyCreditCode"
          class="nut-input-text bole-input-text"
          placeholder="请输入您营业执照上的信用代码"
          type="text"
        />
      </nut-form-item>
      <ProFormItemCell label="法人身份证照片:" required>
        <div class="id-imgUrl-wrapper">
          <nut-form-item
            label=" "
            class="bole-form-item"
            prop="legalPersonIdFrontImgUrl"
            label-width="0px"
          >
            <Uploader
              v-model:file-list="form.legalPersonIdFrontImgUrl"
              :maximum="1"
              :limitFileSize="10"
              class="bole-uploader nopaddingtop"
              @my-success="handleFrontImgUrlChange"
            >
              <template #upload-icon>
                <div class="photograph-wrapper">
                  <Photograph color="#808080" />
                  <div>身份证人像面</div>
                </div>
              </template>
            </Uploader>
          </nut-form-item>
          <nut-form-item
            label=" "
            class="bole-form-item"
            prop="legalPersonIdBackImgUrl"
            label-width="0px"
          >
            <Uploader
              v-model:file-list="form.legalPersonIdBackImgUrl"
              :maximum="1"
              :limitFileSize="10"
              class="bole-uploader nopaddingtop"
            >
              <template #upload-icon>
                <div class="photograph-wrapper">
                  <Photograph color="#808080" />
                  <div>身份证国徽面</div>
                </div>
              </template>
            </Uploader>
          </nut-form-item>
        </div>
        <div class="pro-form-item-tips">
          请上传法人身份证的正反面照片,确保身份证清晰可见,支持png/jpg/jpeg格式,文件大小不超过10MB
        </div>
      </ProFormItemCell>
      <nut-form-item label="法人姓名:" class="bole-form-item" prop="legalPersonName" required>
        <nut-input
          v-model.trim="form.legalPersonName"
          class="nut-input-text bole-input-text"
          placeholder="请填写企业法人的姓名"
          type="text"
        />
      </nut-form-item>
      <nut-form-item
        label="法人身份证号:"
        class="bole-form-item"
        prop="legalPersonIdNumber"
        required
      >
        <nut-input
          v-model.trim="form.legalPersonIdNumber"
          class="nut-input-text bole-input-text"
          placeholder="请填写企业法人的身份证号码"
          type="text"
        />
      </nut-form-item>
      <nut-form-item
        label="法人手机号:"
        class="bole-form-item"
        prop="legalPersonContactPhone"
        required
      >
        <nut-input
          v-model.trim="form.legalPersonContactPhone"
          class="nut-input-text bole-input-text"
          placeholder="请填写企业法人的手机号码"
          type="text"
        >
          <template #right>
            <ProFormCaptcha
              :onGetCaptcha="() => onGetCaptcha(form.legalPersonContactPhone)"
              :phonePropName="['legalPersonContactPhone', 'legalPersonName', 'legalPersonIdNumber']"
              :validateField="formRef?.validate"
            ></ProFormCaptcha>
          </template>
        </nut-input>
      </nut-form-item>
      <nut-form-item label="短信验证码:" class="bole-form-item" prop="verificationCode" required>
        <nut-input
          v-model.trim="form.verificationCode"
          class="nut-input-text bole-input-text"
          placeholder="请输入验证码"
          type="number"
        />
      </nut-form-item>
    </nut-form>
  </ContentScrollView>
  <PageFooter :isOnlyAction="false">
    <PageFooterBtn type="primary" @click="handleSubmit()" :loading="loading"
      >提交认证</PageFooterBtn
    >
  </PageFooter>
</template>
<script setup lang="ts">
import { useAuthenticationFlow } from '../hooks';
import {
  UserCertificationModeEnumV2,
  VerificationCodeBusinessType,
  UserCertificationElementEnum,
} from '@12333/constants';
import { ProFormCaptcha, ProFormItemCell } from 'senin-mini/components';
import * as commonServices from '@12333/services/api/Common';
import { FileItem } from '@nutui/nutui-taro/dist/types/__VUE/uploader/type';
import { vatLicense, userCredentialVerifyOcrIDCard } from '@12333/hooks';
import { Message } from '@12333/utils';
import { Photograph } from '@nutui/icons-vue-taro';
defineOptions({
  name: 'InnerPage',
});
const { form, rules, formRef, handleSubmit, loading } = useAuthenticationFlow({
  certificationMode: UserCertificationModeEnumV2.LegalPersonPhoneCertification,
  certificationElement: UserCertificationElementEnum.Identity4,
});
async function onGetCaptcha(phoneNumber: string) {
  await commonServices.sendPhoneCertificationVerificationCode(
    {
      name: form.legalPersonName,
      identity: form.legalPersonIdNumber,
      mobile: form.legalPersonContactPhone,
      businessType: VerificationCodeBusinessType.UserCertificationPhoneCertification,
    },
    { showLoading: false }
  );
}
const handleLicenseUrlChange = (response: FileItem) => {
  vatLicense(response, {
    onSuccess(res) {
      let tips: string[] = [];
      res?.name ? (form.enterpriseName = res.name) : tips.push('企业名称');
      res?.societyCode ? (form.societyCreditCode = res.societyCode) : tips.push('统一社会信用代码');
      if (tips.length > 0) {
        Message.error(`未能识别到您上传的图片,请重新上传清晰的图片或手动输入${tips.join('和')}`);
      }
    },
  });
};
function handleFrontImgUrlChange(response: FileItem) {
  userCredentialVerifyOcrIDCard(response, {
    onSuccess(res) {
      if (res.realName) form.legalPersonName = res.realName;
      if (res.idcardNum) form.legalPersonIdNumber = res.idcardNum;
    },
  });
}
</script>
<style lang="scss">
@import '@/styles/common.scss';
.authenticationFaRen-page-wrapper {
  .photograph-wrapper {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
  }
}
</style>
apps/bMiniApp/src/subpackages/authentication/authenticationFaRen/authenticationFaRen.config.ts
New file
@@ -0,0 +1,3 @@
export default definePageConfig({
  disableScroll: true,
});
apps/bMiniApp/src/subpackages/authentication/authenticationFaRen/authenticationFaRen.vue
New file
@@ -0,0 +1,14 @@
<template>
  <PageLayout title="企业法人认证" class="authenticationFaRen-page-wrapper" hasBorder>
    <InnerPage />
  </PageLayout>
</template>
<script setup lang="ts">
import { PageLayout } from '@/components';
import InnerPage from './InnerPage.vue';
defineOptions({
  name: 'authenticationFaRen',
});
</script>
apps/bMiniApp/src/subpackages/authentication/authenticationHome/InnerPage.vue
New file
@@ -0,0 +1,76 @@
<template>
  <ContentScrollView class="authenticationHome-page-view">
    <div class="authenticationHome-page-title">实名认证</div>
    <authenticationHomeItem
      title="企业法人认证"
      :icon="IconFaren"
      :info="[['企业营业执照照片', '法人身份证照片'], ['法人手机号码(接收短信验证码进行短信核验)']]"
      @click="goFaRen"
    ></authenticationHomeItem>
    <authenticationHomeItem
      title="企业经办人认证"
      isJBR
      :icon="IconJBR"
      :info="[
        ['企业授权书', '企业营业执照照片', '经办人身份证照片'],
        ['经办人手机号码(接收短信验证码进行短信核验)'],
      ]"
      @click="goJBR"
    >
      <template #title-extra>
        <div class="authenticationHome-page-title-btn" @click.stop="downloadPowerAttorneyTemplate">
          下载授权书模版
        </div>
      </template>
    </authenticationHomeItem>
  </ContentScrollView>
</template>
<script setup lang="ts">
import authenticationHomeItem from './authenticationHomeItem.vue';
import IconFaren from '@/assets/authentication/icon-faren.png';
import IconJBR from '@/assets/authentication/icon-jbr.png';
import Taro from '@tarojs/taro';
import { useDownloadPowerAttorneyTemplate } from '../hooks';
defineOptions({
  name: 'InnerPage',
});
function goFaRen() {
  Taro.navigateTo({ url: RouterPath.authenticationFaRen });
}
function goJBR() {
  Taro.navigateTo({ url: RouterPath.authenticationJBR });
}
const { downloadPowerAttorneyTemplate } = useDownloadPowerAttorneyTemplate();
</script>
<style lang="scss">
@import '@/styles/common.scss';
.authenticationHome-page-wrapper {
  .authenticationHome-page-view {
    padding-top: 48px;
    background-color: transparent;
  }
  .authenticationHome-page-title {
    font-weight: 600;
    font-size: 44px;
    color: #2f4879;
    line-height: 60px;
    margin-bottom: 44px;
  }
  .authenticationHome-page-title-btn {
    font-weight: bold;
    font-size: 24px;
    color: boleGetCssVar('color', 'primary');
    line-height: 34px;
    margin-left: 24px;
  }
}
</style>
apps/bMiniApp/src/subpackages/authentication/authenticationHome/authenticationHome.config.ts
New file
@@ -0,0 +1,3 @@
export default definePageConfig({
  disableScroll: true,
});
apps/bMiniApp/src/subpackages/authentication/authenticationHome/authenticationHome.vue
New file
@@ -0,0 +1,35 @@
<template>
  <PageLayout class="authenticationHome-page-wrapper">
    <template #navigationBar>
      <TransparentNavigationBar title="实名认证" :is-absolute="false"></TransparentNavigationBar>
    </template>
    <template #bg>
      <img :src="OssAssets.authentication.AuthenticationBg" class="authenticationHome-page-bg" />
    </template>
    <InnerPage />
  </PageLayout>
</template>
<script setup lang="ts">
import { PageLayout } from '@/components';
import { OssAssets } from '@12333/constants';
import InnerPage from './InnerPage.vue';
defineOptions({
  name: 'authenticationHome',
});
</script>
<style lang="scss">
@import '@/styles/common.scss';
.authenticationHome-page-bg {
  position: fixed;
  z-index: -1;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
}
</style>
apps/bMiniApp/src/subpackages/authentication/authenticationHome/authenticationHomeItem.vue
New file
@@ -0,0 +1,159 @@
<template>
  <div :class="['authentication-home-item', { isJBR }]">
    <div class="authentication-home-item-top">
      <img class="authentication-home-item-icon" :src="icon" />
      <div class="authentication-home-item-title-wrapper">
        <div class="authentication-home-item-title">
          <div class="authentication-home-item-title-text">
            {{ title }}
          </div>
          <slot name="title-extra"></slot>
        </div>
        <div class="authentication-home-item-subtitle">您需要准备</div>
      </div>
      <img :src="IconArrow" alt="" class="authentication-home-item-arrow" />
    </div>
    <div class="authentication-home-item-info">
      <div class="authentication-home-item-info-row" v-for="(infoItem, index) in info" :key="index">
        <div class="authentication-home-item-info-item" v-for="(item, i) in infoItem" :key="i">
          <div class="authentication-home-item-info-item-dot"></div>
          <div class="authentication-home-item-info-item-text">{{ item }}</div>
        </div>
      </div>
    </div>
  </div>
</template>
<script setup lang="ts">
import IconArrow from '@/assets/authentication/icon-arrow.png';
defineOptions({
  name: 'authenticationHomeItem',
});
type Props = {
  title?: string;
  isJBR?: boolean;
  icon?: string;
  info?: string[][];
};
const props = withDefaults(defineProps<Props>(), {
  info: () => [],
});
</script>
<style lang="scss">
@import '@/styles/common.scss';
.authentication-home-item {
  background-color: #fff;
  padding: 36px 24px 32px;
  border-radius: 32px;
  position: relative;
  z-index: 1;
  margin-bottom: 32px;
  &::before {
    content: '';
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    height: 80px;
    background: linear-gradient(180deg, #eff6ff 0%, rgba(239, 246, 255, 0) 100%);
    border-radius: 30px 30px 0px 0px;
    z-index: -1;
  }
  &.isJBR {
    &::before {
      background: linear-gradient(180deg, #fff7f7 0%, rgba(255, 247, 247, 0) 100%);
    }
  }
  .authentication-home-item-top {
    display: flex;
    align-items: center;
    margin-bottom: 40px;
    .authentication-home-item-icon {
      width: 72px;
      height: 72px;
      margin-right: 16px;
    }
    .authentication-home-item-title-wrapper {
      flex: 1;
      min-width: 0;
      .authentication-home-item-title {
        font-weight: 600;
        font-size: 32px;
        line-height: 44px;
        display: flex;
        align-items: center;
        .authentication-home-item-title-text {
          color: boleGetCssVar('text-color', 'primary');
        }
      }
      .authentication-home-item-subtitle {
        font-weight: 400;
        font-size: 24px;
        color: boleGetCssVar('text-color', 'regular');
        line-height: 34px;
      }
    }
    .authentication-home-item-arrow {
      width: 32px;
      height: 32px;
    }
  }
  .authentication-home-item-info {
    background: #f9fbff;
    border-radius: 8px;
    padding: 24px;
    display: flex;
    flex-wrap: wrap;
    .authentication-home-item-info-row {
      display: flex;
      align-items: center;
      margin-bottom: 16px;
      &:last-child {
        margin-bottom: 0;
      }
    }
    .authentication-home-item-info-item {
      display: flex;
      align-items: center;
      margin-right: 24px;
      &:last-child {
        margin-right: 0;
      }
      .authentication-home-item-info-item-dot {
        width: 8px;
        height: 8px;
        background: #7bb0f6;
        border-radius: 50%;
        margin-right: 16px;
      }
      .authentication-home-item-info-item-text {
        font-weight: 400;
        font-size: 24px;
        color: boleGetCssVar('text-color', 'primary');
        line-height: 34px;
      }
    }
  }
}
</style>
apps/bMiniApp/src/subpackages/authentication/authenticationJBR/InnerPage.vue
New file
@@ -0,0 +1,244 @@
<template>
  <ContentScrollView :paddingH="false">
    <nut-form :model-value="form" ref="formRef" :rules="rules">
      <nut-form-item label="营业执照:" class="bole-form-item alignTop" prop="licenseUrl" required>
        <Uploader
          v-model:file-list="form.licenseUrl"
          :maximum="1"
          :limitFileSize="10"
          class="bole-uploader nopaddingtop"
          @my-success="handleLicenseUrlChange"
        >
        </Uploader>
        <div class="pro-form-item-tips">
          请上传最新的营业执照原件照片、扫描件或加盖公章的复印件,支持png/jpg/jpeg格式,文件大小不超过10MB
        </div>
      </nut-form-item>
      <nut-form-item label="企业全称:" class="bole-form-item" prop="enterpriseName" required>
        <nut-input
          v-model.trim="form.enterpriseName"
          class="nut-input-text bole-input-text"
          placeholder="请输入您营业执照上的企业名称"
          type="text"
          :max-length="35"
        />
      </nut-form-item>
      <nut-form-item
        label="统一社会信用代码:"
        class="bole-form-item"
        prop="societyCreditCode"
        required
      >
        <nut-input
          v-model.trim="form.societyCreditCode"
          class="nut-input-text bole-input-text"
          placeholder="请输入您营业执照上的信用代码"
          type="text"
        />
      </nut-form-item>
      <nut-form-item label="法人姓名:" class="bole-form-item" prop="legalPersonName" required>
        <nut-input
          v-model.trim="form.legalPersonName"
          class="nut-input-text bole-input-text"
          placeholder="请填写企业法人的姓名"
          type="text"
        />
      </nut-form-item>
      <ProFormItemCell label="经办人身份证照片:" required>
        <div class="id-imgUrl-wrapper">
          <nut-form-item
            label=" "
            class="bole-form-item"
            prop="proxyPersonIdFrontImgUrl"
            label-width="0px"
          >
            <Uploader
              v-model:file-list="form.proxyPersonIdFrontImgUrl"
              :maximum="1"
              :limitFileSize="10"
              class="bole-uploader nopaddingtop"
              @my-success="handleFrontImgUrlChange"
            >
              <template #upload-icon>
                <div class="photograph-wrapper">
                  <Photograph color="#808080" />
                  <div>身份证人像面</div>
                </div>
              </template>
            </Uploader>
          </nut-form-item>
          <nut-form-item
            label=" "
            class="bole-form-item"
            prop="proxyPersonIdBackImgUrl"
            label-width="0px"
          >
            <Uploader
              v-model:file-list="form.proxyPersonIdBackImgUrl"
              :maximum="1"
              :limitFileSize="10"
              class="bole-uploader nopaddingtop"
            >
              <template #upload-icon>
                <div class="photograph-wrapper">
                  <Photograph color="#808080" />
                  <div>身份证国徽面</div>
                </div>
              </template>
            </Uploader>
          </nut-form-item>
        </div>
        <div class="pro-form-item-tips">
          请上传经办人身份证的正反面照片,确保身份证清晰可见,支持png/jpg/jpeg格式,文件大小不超过10MB
        </div>
      </ProFormItemCell>
      <nut-form-item label="经办人姓名:" class="bole-form-item" prop="proxyPersonName" required>
        <nut-input
          v-model.trim="form.proxyPersonName"
          class="nut-input-text bole-input-text"
          placeholder="请填写经办人的姓名"
          type="text"
        />
      </nut-form-item>
      <nut-form-item
        label="经办人身份证号:"
        class="bole-form-item"
        prop="proxyPersonIdNumber"
        required
      >
        <nut-input
          v-model.trim="form.proxyPersonIdNumber"
          class="nut-input-text bole-input-text"
          placeholder="请填写经办人的身份证号码"
          type="text"
        />
      </nut-form-item>
      <nut-form-item
        label="经办人手机号:"
        class="bole-form-item"
        prop="proxyPersonContactPhone"
        required
      >
        <nut-input
          v-model.trim="form.proxyPersonContactPhone"
          class="nut-input-text bole-input-text"
          placeholder="请填写经办人的手机号码"
          type="text"
        >
          <template #right>
            <ProFormCaptcha
              :onGetCaptcha="() => onGetCaptcha(form.proxyPersonContactPhone)"
              phonePropName="proxyPersonContactPhone"
              :validateField="formRef?.validate"
            ></ProFormCaptcha>
          </template>
        </nut-input>
      </nut-form-item>
      <nut-form-item label="短信验证码:" class="bole-form-item" prop="verificationCode" required>
        <nut-input
          v-model.trim="form.verificationCode"
          class="nut-input-text bole-input-text"
          placeholder="请输入验证码"
          type="number"
        />
      </nut-form-item>
      <nut-form-item
        label="企业授权书:"
        class="bole-form-item alignTop"
        prop="proxyPowerAttorneyUrl"
        required
      >
        <Uploader
          v-model:file-list="form.proxyPowerAttorneyUrl"
          :maximum="1"
          :limitFileSize="10"
          class="bole-uploader nopaddingtop"
        >
        </Uploader>
        <div class="pro-form-item-tips">
          请上传加盖公章的企业授权书照片或扫描件,支持png/jpg/jpeg/pdf格式,文件大小不超过10MB
          <span class="primary" @click="downloadPowerAttorneyTemplate">授权书模板下载</span>
        </div>
      </nut-form-item>
    </nut-form>
  </ContentScrollView>
  <PageFooter :isOnlyAction="false">
    <PageFooterBtn type="primary" @click="handleSubmit()" :loading="loading"
      >提交认证</PageFooterBtn
    >
  </PageFooter>
</template>
<script setup lang="ts">
import { useAuthenticationFlow, useDownloadPowerAttorneyTemplate } from '../hooks';
import {
  UserCertificationModeEnumV2,
  VerificationCodeBusinessType,
  UserCertificationElementEnum,
} from '@12333/constants';
import { ProFormCaptcha, ProFormItemCell } from 'senin-mini/components';
import * as commonServices from '@12333/services/api/Common';
import { FileItem } from '@nutui/nutui-taro/dist/types/__VUE/uploader/type';
import { vatLicense, userCredentialVerifyOcrIDCard } from '@12333/hooks';
import { Message } from '@12333/utils';
import { Photograph } from '@nutui/icons-vue-taro';
defineOptions({
  name: 'InnerPage',
});
const { form, rules, formRef, handleSubmit, loading } = useAuthenticationFlow({
  certificationMode: UserCertificationModeEnumV2.ProxyPersonPhoneCertification,
  certificationElement: UserCertificationElementEnum.Identity3,
});
const { downloadPowerAttorneyTemplate } = useDownloadPowerAttorneyTemplate();
async function onGetCaptcha(phoneNumber: string) {
  await commonServices.sendPhoneCertificationVerificationCode(
    {
      name: form.proxyPersonName,
      identity: form.proxyPersonIdNumber,
      mobile: form.proxyPersonContactPhone,
      businessType: VerificationCodeBusinessType.UserCertificationPhoneCertification,
    },
    { showLoading: false }
  );
}
const handleLicenseUrlChange = (response: FileItem) => {
  vatLicense(response, {
    onSuccess(res) {
      let tips: string[] = [];
      res?.name ? (form.enterpriseName = res.name) : tips.push('企业名称');
      res?.societyCode ? (form.societyCreditCode = res.societyCode) : tips.push('统一社会信用代码');
      if (tips.length > 0) {
        Message.error(`未能识别到您上传的图片,请重新上传清晰的图片或手动输入${tips.join('和')}`);
      }
    },
  });
};
function handleFrontImgUrlChange(response: FileItem) {
  userCredentialVerifyOcrIDCard(response, {
    onSuccess(res) {
      if (res.realName) form.proxyPersonName = res.realName;
      if (res.idcardNum) form.proxyPersonIdNumber = res.idcardNum;
    },
  });
}
</script>
<style lang="scss">
@import '@/styles/common.scss';
.authenticationJBR-page-wrapper {
  .photograph-wrapper {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
  }
}
</style>
apps/bMiniApp/src/subpackages/authentication/authenticationJBR/authenticationJBR.config.ts
New file
@@ -0,0 +1,3 @@
export default definePageConfig({
  disableScroll: true,
});
apps/bMiniApp/src/subpackages/authentication/authenticationJBR/authenticationJBR.vue
New file
@@ -0,0 +1,14 @@
<template>
  <PageLayout title="企业经办人认证" class="authenticationJBR-page-wrapper" hasBorder>
    <InnerPage />
  </PageLayout>
</template>
<script setup lang="ts">
import { PageLayout } from '@/components';
import InnerPage from './InnerPage.vue';
defineOptions({
  name: 'authenticationJBR',
});
</script>
apps/bMiniApp/src/subpackages/authentication/authenticationResult/InnerPage.vue
New file
@@ -0,0 +1,97 @@
<template>
  <LoadingLayout :loading="isLoading">
    <div
      class="result-wrapper"
      v-if="myCertificationAuditInfo?.frontStatus === UserCertificationFrontStatus.NotCertified"
    >
      <div class="result-title">未认证</div>
    </div>
    <div
      class="result-wrapper"
      v-else-if="myCertificationAuditInfo?.frontStatus === UserCertificationFrontStatus.Certified"
    >
      <img class="result-icon" :src="IconSuccess" />
      <div class="result-title">认证成功</div>
      <div class="result-subtitle">您的企业实名已认证成功</div>
      <PageFooterBtn type="primary" class="result-btn" @click="goUserCenter"
        >返回个人中心</PageFooterBtn
      >
    </div>
    <div
      class="result-wrapper"
      v-else-if="myCertificationAuditInfo?.frontStatus === UserCertificationFrontStatus.Rejected"
    >
      <img class="result-icon" :src="IconError" />
      <div class="result-title">认证失败</div>
      <div class="result-subtitle">您的企业实名认证失败</div>
      <div class="result-subtitle">失败原因:{{ myCertificationAuditInfo?.auditNote ?? '' }}</div>
      <PageFooterBtn type="primary" class="result-btn" @click="goBack()"
        >重新提交认证</PageFooterBtn
      >
    </div>
  </LoadingLayout>
</template>
<script setup lang="ts">
import { useMyCertificationAuditInfo, useSwitchTab } from '@/hooks';
import Taro from '@tarojs/taro';
import { goBack } from '@/utils';
import IconSuccess from '@/assets/authentication/icon-result-success.png';
import IconError from '@/assets/authentication/icon-result-error.png';
import { UserCertificationFrontStatus } from '@12333/constants';
defineOptions({
  name: 'InnerPage',
});
const { myCertificationAuditInfo, isLoading } = useMyCertificationAuditInfo();
const switchTab = useSwitchTab();
function goUserCenter() {
  switchTab({
    url: RouterPath.mine,
  });
}
</script>
<style lang="scss">
@import '@/styles/common.scss';
.authenticationResult-page-wrapper {
  .result-wrapper {
    display: flex;
    flex-direction: column;
    align-items: center;
    padding-top: 150px;
    .result-icon {
      width: 320px;
      height: 184px;
      object-fit: cover;
      margin-bottom: 12px;
    }
    .result-title {
      font-weight: 400;
      font-size: 32px;
      color: boleGetCssVar('text-color', 'primary');
      line-height: 32px;
      margin-bottom: 32px;
    }
    .result-subtitle {
      font-weight: 400;
      font-size: 28px;
      color: boleGetCssVar('text-color', 'regular');
      line-height: 44px;
      margin-bottom: 40px;
    }
    .result-btn {
      width: 542px;
      font-size: 28px;
    }
  }
}
</style>
apps/bMiniApp/src/subpackages/authentication/authenticationResult/authenticationResult.config.ts
New file
@@ -0,0 +1,3 @@
export default definePageConfig({
  disableScroll: true,
});
apps/bMiniApp/src/subpackages/authentication/authenticationResult/authenticationResult.vue
New file
@@ -0,0 +1,28 @@
<template>
  <PageLayout
    title="实名认证"
    class="authenticationResult-page-wrapper"
    hasBorder
    :backFn="handleBack"
  >
    <InnerPage />
  </PageLayout>
</template>
<script setup lang="ts">
import { PageLayout } from '@/components';
import InnerPage from './InnerPage.vue';
import { useSwitchTab } from '@/hooks';
defineOptions({
  name: 'authenticationResult',
});
const switchTab = useSwitchTab();
function handleBack() {
  switchTab({
    url: RouterPath.mine,
  });
}
</script>
apps/bMiniApp/src/subpackages/authentication/hooks/index.ts
New file
@@ -0,0 +1,191 @@
import { FormRules } from '@nutui/nutui-taro/dist/types/__VUE/form/types';
import { useUser } from '@/hooks';
import { FileItem } from '@nutui/nutui-taro/dist/types/__VUE/uploader/type';
import {
  EnterpriseType,
  UserCertificationModeEnumV2,
  VerificationCodeBusinessType,
  UserCertificationElementEnum,
  UserCertificationChannelEnum,
  UserCertificationPayType,
} from '@12333/constants';
import * as commonServices from '@12333/services/api/Common';
import * as userServices from '@12333/services/api/User';
import { FormValidator, Message } from '@12333/utils';
import { useUserCertificationSetting } from '@12333/hooks';
import Taro from '@tarojs/taro';
type UseAuthenticationFlowOptions = {
  certificationMode: UserCertificationModeEnumV2;
  certificationElement: UserCertificationElementEnum;
};
export function useAuthenticationFlow({
  certificationMode,
  certificationElement,
}: UseAuthenticationFlowOptions) {
  const { userDetail } = useUser();
  const form = reactive({
    licenseUrl: [] as FileItem[],
    enterpriseType: userDetail.value?.authType ?? EnterpriseType.HREnterprise,
    enterpriseName: '',
    societyCreditCode: '',
    certificationMode: certificationMode,
    certificationElement: certificationElement,
    legalPersonName: '',
    legalPersonIdNumber: '',
    legalPersonIdFrontImgUrl: [] as FileItem[],
    legalPersonIdBackImgUrl: [] as FileItem[],
    legalPersonBankCardImgUrl: [] as FileItem[],
    legalPersonContactPhone: '',
    verificationCode: '',
    proxyPersonName: '',
    proxyPersonIdNumber: '',
    proxyPersonContactPhone: '',
    proxyPersonIdFrontImgUrl: [] as FileItem[],
    proxyPersonIdBackImgUrl: [] as FileItem[],
    proxyPersonBankCardImgUrl: [] as FileItem[],
    proxyPowerAttorneyUrl: [] as FileItem[],
    bankCardNumber: '',
  });
  const rules: FormRules = {
    licenseUrl: [
      { required: true, message: '请上传营业执照', validator: FormValidator.validatorArray },
    ],
    enterpriseName: [{ required: true, message: '请输入企业名称' }],
    societyCreditCode: [
      { required: true, message: '请输入您营业执照上的信用代码' },
      { message: '请输入正确的信用代码', validator: FormValidator.validatorSocietyCreditCode },
    ],
    legalPersonName: [{ required: true, message: '请填写企业法人的姓名' }],
    legalPersonIdFrontImgUrl: [
      { required: true, message: '请上传身份证人像面', validator: FormValidator.validatorArray },
    ],
    legalPersonIdBackImgUrl: [
      { required: true, message: '请上传身份证国徽面', validator: FormValidator.validatorArray },
    ],
    legalPersonIdNumber: [
      { required: true, message: '请填写企业法人的身份证号码' },
      { message: '请输入正确的身份证号码', validator: FormValidator.validatorIDCard },
    ],
    legalPersonContactPhone: [
      { required: true, message: '请填写企业法人的手机号码' },
      { message: '请输入正确的手机号码', validator: FormValidator.validatorPhoneNumber },
    ],
    verificationCode: [{ required: true, message: '请输入验证码' }],
    proxyPersonName: [{ required: true, message: '请填写经办人的姓名' }],
    proxyPersonIdNumber: [
      { required: true, message: '请填写经办人的身份证号码' },
      { message: '请输入正确的身份证号码', validator: FormValidator.validatorIDCard },
    ],
    proxyPersonContactPhone: [
      { required: true, message: '请填写经办人的手机号码' },
      { message: '请输入正确的手机号码', validator: FormValidator.validatorPhoneNumber },
    ],
    proxyPowerAttorneyUrl: [
      { required: true, message: '请上传企业授权书', validator: FormValidator.validatorArray },
    ],
  };
  const { updateUserInfo } = useUser();
  const formRef = ref<any>(null);
  function handleSubmit() {
    if (!formRef.value) return;
    formRef.value.validate().then(({ valid, errors }: any) => {
      if (valid) {
        addUserCertificationAudit();
      }
    });
  }
  const loading = ref(false);
  async function addUserCertificationAudit() {
    try {
      let params: API.AddUserCertificationAuditInput = {
        enterpriseType: form.enterpriseType,
        licenseUrl: form.licenseUrl[0].path,
        enterpriseName: form.enterpriseName,
        societyCreditCode: form.societyCreditCode,
        certificationMode: form.certificationMode,
        legalPersonName: form.legalPersonName,
        legalPersonIdNumber: form.legalPersonIdNumber,
        legalPersonIdImgUrl: form.legalPersonIdFrontImgUrl?.[0]?.path ?? '',
        legalPersonIdBackImgUrl: form.legalPersonIdBackImgUrl?.[0]?.path ?? '',
        legalPersonBankCardImgUrl: form.legalPersonBankCardImgUrl?.[0]?.path ?? '',
        certificationContact:
          form.certificationElement === UserCertificationElementEnum.Identity4
            ? form.legalPersonName
            : form.proxyPersonName,
        certificationContactPhone:
          form.certificationElement === UserCertificationElementEnum.Identity4
            ? form.legalPersonContactPhone
            : form.proxyPersonContactPhone,
        proxyPersonName: form.proxyPersonName,
        proxyPersonIdNumber: form.proxyPersonIdNumber,
        proxyPersonIdImgUrl: form.proxyPersonIdFrontImgUrl?.[0]?.path ?? '',
        proxyPersonIdBackImgUrl: form.proxyPersonIdBackImgUrl?.[0]?.path ?? '',
        proxyPersonBankCardImgUrl: form.proxyPersonBankCardImgUrl?.[0]?.path ?? '',
        proxyPowerAttorneyUrl: form.proxyPowerAttorneyUrl?.[0]?.path ?? '',
        certificationChannel: UserCertificationChannelEnum.ThirdParty,
        certificationElement: form.certificationElement,
        vCode: form.verificationCode,
        bankCardNumber: form.bankCardNumber,
        payType: UserCertificationPayType.NotNeedPay,
      };
      loading.value = true;
      let res = await userServices.addUserCertificationAudit(params, { showLoading: false });
      if (res) {
        updateUserInfo();
        Taro.redirectTo({
          url: RouterPath.authenticationResult,
        });
      }
    } catch (error) {
    } finally {
      loading.value = false;
    }
  }
  return {
    form,
    rules,
    formRef,
    handleSubmit,
    loading,
  };
}
export function useDownloadPowerAttorneyTemplate() {
  const { userCertificationSetting } = useUserCertificationSetting();
  function downloadPowerAttorneyTemplate() {
    Taro.showLoading({
      title: '下载中',
    });
    Taro.downloadFile({
      url: userCertificationSetting.value.enterprisePowerAttorneyTempPath,
      success: function (res) {
        Taro.hideLoading();
        // Message.success('下载成功');
        var filePath = res.tempFilePath;
        Taro.openDocument({
          filePath: filePath,
          showMenu: true,
        });
      },
      fail: function (error: any) {
        Taro.hideLoading();
        Message.error('下载失败');
      },
    });
  }
  return {
    downloadPowerAttorneyTemplate,
  };
}
apps/bMiniApp/src/subpackages/city/citySelect/citySelect.config.ts
New file
@@ -0,0 +1,3 @@
export default definePageConfig({
  disableScroll: true,
});
apps/bMiniApp/src/subpackages/city/citySelect/citySelect.vue
New file
@@ -0,0 +1,87 @@
<template>
  <PageLayout title="选择城市" class="citySelect-page-wrapper" :need-auth="false">
    <ContentView class="citySelect-content-wrapper">
      <div class="current-city">当前城市:{{ locationCity }}</div>
      <Elevator :index-list="elevatorData" :height="'100%'" @click-item="clickItem" />
    </ContentView>
  </PageLayout>
</template>
<script setup lang="ts">
import { PageLayout, LoadingLayout, ContentScrollView, ContentView } from '@/components';
import { useUser } from '@/hooks';
import { useArea } from '@12333/hooks';
import { AreaType } from '@12333/constants';
import { groupBy, sortBy } from 'lodash';
import { useUserStore } from '@/stores/modules/user';
import { Elevator } from '@12333/components';
defineOptions({
  name: 'citySelect',
});
const { completeAreaList, getAreaByAreaCode } = useArea();
const { locationCity } = useUser();
const userStore = useUserStore();
const cityList = computed(() => {
  if (completeAreaList.value?.length > 0) {
    return [...completeAreaList.value].filter((x) => x.layer === AreaType.City);
  }
  return [];
});
const elevatorData = computed(() => {
  let cityGroups = groupBy(
    sortBy(cityList.value, (c) => c.quickQuery.charAt(0)),
    (city) => city.quickQuery.charAt(0)
  );
  const _elevatorData = [];
  for (let key in cityGroups) {
    _elevatorData.push({
      title: key,
      list: cityGroups[key].map((x) => ({
        name: x.areaName,
        id: x.areaCode,
        parentId: x.parentId,
      })),
    });
  }
  return _elevatorData;
});
console.log('elevatorData: ', elevatorData);
const clickItem = (key: string, item: any) => {
  console.log('item: ', item, getAreaByAreaCode(item.parentId).areaName);
  userStore.setLocationCity(item.name, getAreaByAreaCode(item.parentId).areaName);
};
</script>
<style lang="scss">
@import '@/styles/common.scss';
.citySelect-page-wrapper {
  .current-city {
    padding: 20px 0;
    color: boleGetCssVar('text-color', 'primary');
    font-size: 28px;
  }
  .citySelect-content-wrapper {
    display: flex;
    flex-direction: column;
    height: 100%;
  }
  .nut-elevator {
    flex: 1;
    min-height: 0;
    .nut-elevator__list__item__name,
    .nut-elevator__list__item__code {
      padding: 0;
    }
  }
}
</style>
apps/bMiniApp/src/subpackages/login/authorization/authorization.vue
New file
@@ -0,0 +1,289 @@
<template>
  <LoginPageLayout class="authorization-page-wrapper">
    <div class="authorization-page-wechat-btn-wrapper">
      <nut-button
        v-if="isAccount"
        type="primary"
        class="authorization-page-wechat-wrapper"
        @click="handleLoginByHasAccount"
      >
        <div class="authorization-page-wechat">手机号快速登录</div></nut-button
      >
      <AccessOpenTypeButton
        v-else
        type="primary"
        class="authorization-page-wechat-wrapper"
        open-type="getPhoneNumber"
        :access="state.policyChecked"
        @noAccess="noAccess"
        @getphonenumber="login"
      >
        <div class="authorization-page-wechat">手机号快速登录</div>
      </AccessOpenTypeButton>
    </div>
    <Policy
      v-model="state.policyChecked"
      policyBtnText="若手机号未注册,将为您直接注册账号,注册即为同意"
    />
    <div class="other-login-channel-wrapper" v-if="!isLoginByWeb">
      <nut-divider>其他登录方式</nut-divider>
      <div class="other-login-channel-list">
        <div class="other-login-channel-list-item" @click="goLoginByForm()">
          <div class="other-login-channel-list-item-icon">
            <img :src="IconCaptcha" />
          </div>
          <div class="other-login-channel-list-item-text">验证码登录</div>
        </div>
        <div
          class="other-login-channel-list-item"
          @click="goLoginByForm(LoginFormTabs.AccountLogin)"
        >
          <div class="other-login-channel-list-item-icon">
            <img :src="IconPassword" />
          </div>
          <div class="other-login-channel-list-item-text">账户登录</div>
        </div>
      </div>
    </div>
  </LoginPageLayout>
</template>
<script setup lang="ts">
import { Policy } from '@/components';
import { AccessOpenTypeButton } from '@12333/components';
import LoginPageLayout from '../components/LoginPageLayout/LoginPageLayout.vue';
import { useUserStore } from '@/stores/modules/user';
import { Message } from '@12333/utils';
import { CommonEventFunction, ButtonProps } from '@tarojs/components';
import Taro from '@tarojs/taro';
import { useLoginedJump } from '@/hooks';
import * as accountServices from '@12333/services/api/Account';
import IconCaptcha from '@/assets/login/icon-btn-captcha.png';
import IconPassword from '@/assets/login/icon-btn-password.png';
import { LoginFormTabs } from '../constants';
import { WxMiniAppEnum } from '@12333/constants';
defineOptions({
  name: 'authorization',
});
const state = reactive({
  policyChecked: false,
});
const userStore = useUserStore();
function noAccess() {
  Message.warning('请先阅读并勾选协议');
}
const { jump, redirectParams } = useLoginedJump();
const launchOptions = Taro.getEnterOptionsSync();
console.log('launchOptions: ', launchOptions);
const router = Taro.useRouter();
const uuid = router.params?.scene ?? '';
const isLoginByWeb = computed(
  () =>
    RouterPath.authorization.includes(launchOptions.path) && launchOptions.scene === 1047 && uuid
);
const wxIndentityRes = ref<API.WxMiniAppIndentityInfo>();
const wxMiniAppUserLoginRes = ref<API.IdentityModelTokenCacheItem>();
const isAccount = ref(false);
onMounted(async () => {
  try {
    let loginRes = await Taro.login();
    if (isLoginByWeb.value) {
      const wxIndentity = await accountServices.getWxIndentity({
        code: loginRes.code,
        wxMiniApp: WxMiniAppEnum.人单合一,
      });
      wxIndentityRes.value = wxIndentity;
      if (wxIndentityRes.value.userName) {
        isAccount.value = true;
      }
    } else {
      const params: API.APIwxMiniAppUserLoginParams = {
        code: loginRes.code,
        wxMiniApp: WxMiniAppEnum.人单合一,
      };
      wxMiniAppUserLoginRes.value = await accountServices.wxMiniAppUserLogin(params);
      if (wxMiniAppUserLoginRes.value.accessToken) {
        isAccount.value = true;
      }
    }
  } catch (error) {}
});
const login: CommonEventFunction<ButtonProps.onGetPhoneNumberEventDetail> = async function (ev) {
  try {
    const { errMsg, code } = ev.detail;
    console.log('errMsg: ', errMsg, isLoginByWeb.value);
    if (errMsg === 'getPhoneNumber:ok') {
      if (isLoginByWeb.value) {
        let res = await userStore.wxMiniAppPhoneAuthLoginFromScan(
          ev.detail,
          wxIndentityRes.value,
          uuid
        );
        if (res) {
          handleLoginSuccess();
        }
      } else {
        let res = await userStore.getTokenByPhone(ev.detail, wxMiniAppUserLoginRes.value);
        if (res) {
          handleLoginSuccess();
        }
      }
    } else {
      Message.warning('无法获取手机号!');
    }
  } catch (error) {
    console.log('error: ', error);
  }
};
async function handleLoginByHasAccount() {
  try {
    if (state.policyChecked) {
      if (isLoginByWeb.value) {
        console.log('uuid: ', uuid);
        let res = await userStore.wxMiniAppUserLoginFromScan(wxIndentityRes.value, uuid);
        if (res) {
          handleLoginSuccess();
        }
      } else {
        userStore.loginSuccess(wxMiniAppUserLoginRes.value);
        handleLoginSuccess();
      }
    } else {
      noAccess();
    }
  } catch (error) {}
}
function handleLoginSuccess() {
  Message.success('授权登录成功', {
    onClosed: () => {
      jump();
    },
  });
}
function goLoginByForm(tab = LoginFormTabs.VerificationCodeLogin) {
  Taro.navigateTo({
    url: `${RouterPath.loginByForm}?redirect=${redirectParams.value}&tab=${tab}`,
  });
}
</script>
<style lang="scss">
@import '@/styles/common.scss';
.authorization-page-wrapper {
  .authorization-page-top {
    width: 750px;
    height: 225px;
    margin-bottom: 78px;
  }
  .authorization-page-title {
    margin-bottom: 160px;
  }
  .authorization-page-wechat-btn-wrapper {
    padding: 0 64px;
    margin-bottom: 40px;
  }
  .authorization-page-wechat-wrapper {
    width: 100%;
    height: 88px;
  }
  .authorization-page-wechat {
    display: flex;
    justify-content: center;
    align-items: center;
    font-weight: 400;
    font-size: 32px;
    color: #ffffff;
    line-height: 44px;
    .authorization-page-wechat-icon {
      width: 44px;
      height: 36px;
      margin-right: 10px;
    }
  }
  .page-layout-scroll-view-wrapper {
    position: relative;
    .other-login-channel-wrapper {
      width: 520px;
      position: absolute;
      bottom: 40px;
      left: 50%;
      transform: translateX(-50%);
      .nut-divider {
        margin: 0;
        margin-bottom: 40rpx;
        color: boleGetCssVar('text-color', 'secondary');
        &::before,
        &::after {
          border-color: #f0f0f0;
        }
      }
      .other-login-channel-list {
        display: flex;
        justify-content: space-around;
        .other-login-channel-list-item {
          .other-login-channel-list-item-icon {
            width: 80px;
            height: 80px;
            background: #f5f5f5;
            border-radius: 50%;
            margin: 0 auto 8px;
            display: flex;
            justify-content: center;
            align-items: center;
            img {
              width: 38px;
              height: 48px;
            }
          }
          .other-login-channel-list-item-text {
            font-weight: 400;
            font-size: 24px;
            color: boleGetCssVar('text-color', 'regular');
            line-height: 34px;
            text-align: center;
          }
        }
      }
    }
  }
}
.authorization-page-auth {
  position: fixed;
  z-index: -1;
  top: 0;
  left: 0;
  width: 750px;
  height: 1624px;
  object-fit: cover;
}
</style>
apps/bMiniApp/src/subpackages/login/authorization/index.config.ts
New file
@@ -0,0 +1,3 @@
export default definePageConfig({
  disableScroll: true,
});
apps/bMiniApp/src/subpackages/login/components/LoginPageLayout/LoginPageLayout.vue
New file
@@ -0,0 +1,58 @@
<template>
  <PageLayout :needAuth="false" class="login-page-layout">
    <template #navigationBar>
      <TransparentNavigationBar :title="title" :is-absolute="false"></TransparentNavigationBar>
    </template>
    <template #bg>
      <img :src="OssAssets.login.AuthBg" class="authorization-page-auth" />
    </template>
    <div class="authorization-page-title">欢迎使用818平台</div>
    <slot></slot>
  </PageLayout>
</template>
<script setup lang="ts">
import { PageLayout, TransparentNavigationBar } from '@/components';
import { OssAssets } from '@12333/constants';
defineOptions({
  name: 'LoginPageLayout',
});
type Props = {
  title?: string;
};
const props = withDefaults(defineProps<Props>(), {
  title: '登录',
});
</script>
<style lang="scss">
@import '@/styles/common.scss';
.login-page-layout {
  .authorization-page-title {
    font-size: 60px;
    color: boleGetCssVar('text-color', 'primary');
    font-weight: bold;
    text-align: center;
    margin-bottom: 108px;
    margin-top: 136px;
    line-height: 84px;
    @include ellipsis;
  }
}
.authorization-page-auth {
  position: fixed;
  z-index: -1;
  top: 0;
  left: 0;
  width: 750px;
  height: 1624px;
  object-fit: cover;
}
</style>
apps/bMiniApp/src/subpackages/login/components/OtherLoginChannel/OtherLoginChannel.vue.vue
New file
@@ -0,0 +1,17 @@
<template>
  <div></div>
</template>
<script setup lang="ts">
defineOptions({
  name: 'OtherLoginChannel',
});
// type Props = {};
// const props = withDefaults(defineProps<Props>(), {});
</script>
<style lang="scss">
@import '@/styles/common.scss';
</style>
apps/bMiniApp/src/subpackages/login/constants/index.ts
New file
@@ -0,0 +1,4 @@
export enum LoginFormTabs {
  VerificationCodeLogin = 10,
  AccountLogin,
}
apps/bMiniApp/src/subpackages/login/loginByForm/accountLoginForm.vue
New file
@@ -0,0 +1,118 @@
<template>
  <div class="verification-code-login-form-wrapper">
    <nut-form class="verification-code-login-form" ref="formRef" :model-value="form" :rules="rules">
      <nut-form-item label="" class="bole-form-item" prop="userName" required>
        <nut-input
          v-model.trim="form.userName"
          class="bole-input-text"
          placeholder="请输入账号/手机号/邮箱"
          type="text"
        />
      </nut-form-item>
      <nut-form-item label="" class="bole-form-item" prop="userPassword" required>
        <nut-input
          v-model.trim="form.userPassword"
          class="bole-input-text"
          placeholder="请输入密码"
          :type="isShowPassword ? 'text' : 'password'"
          :key="isShowPassword ? 'text' : 'password'"
        >
          <template #right>
            <div class="password-icon-wrapper" @click="isShowPassword = !isShowPassword">
              <Eye v-if="isShowPassword"></Eye>
              <Marshalling v-else></Marshalling>
            </div>
          </template>
        </nut-input>
      </nut-form-item>
    </nut-form>
    <LargeButton class="login-btn" @click="handleLogin" :loading="form.loading">登录</LargeButton>
    <div class="go-register-btn" @click="goRegister">立即注册</div>
  </div>
</template>
<script setup lang="ts">
import { Message } from '@12333/utils';
import { FormRules } from '@nutui/nutui-taro/dist/types/__VUE/form/types';
import { LargeButton } from '@/components';
import { useLoginedJump } from '@/hooks';
import { useUserStore } from '@/stores/modules/user';
import { Eye, Marshalling } from '@nutui/icons-vue-taro';
import Taro from '@tarojs/taro';
defineOptions({
  name: 'AccountLoginForm',
});
type Props = {
  policyChecked?: boolean;
};
const props = withDefaults(defineProps<Props>(), {});
const userStore = useUserStore();
const { jump } = useLoginedJump();
const isShowPassword = ref(false);
const formRef = ref(null);
const form = reactive({
  loading: false,
  userName: '',
  userPassword: '',
});
const rules = reactive<FormRules>({
  userName: [{ required: true, message: '请输入账号/手机号/邮箱' }],
  userPassword: [{ required: true, message: '请输入密码' }],
});
async function handleLogin() {
  try {
    if (props.policyChecked) {
      const { valid } = await formRef.value.validate();
      if (valid) {
        form.loading = true;
        await userStore.loginByPassword({
          userName: form.userName,
          userPassword: form.userPassword,
        });
        jump();
      }
    } else {
      noAccess();
    }
  } catch (error) {
  } finally {
    form.loading = false;
  }
}
function noAccess() {
  Message.warning('请先阅读并勾选协议');
}
function goRegister() {
  console.log('RouterPath.registerForm: ', RouterPath.registerForm);
  Taro.navigateTo({
    url: RouterPath.registerForm,
  });
}
</script>
<style lang="scss">
@import '@/styles/common.scss';
.verification-code-login-form-wrapper {
  .password-icon-wrapper {
    padding: 0 10px;
    display: inline-flex;
    .nutui-iconfont {
      font-size: 28px;
    }
  }
}
</style>
apps/bMiniApp/src/subpackages/login/loginByForm/index.config.ts
New file
@@ -0,0 +1,3 @@
export default definePageConfig({
  disableScroll: true,
});
apps/bMiniApp/src/subpackages/login/loginByForm/loginByForm.vue
New file
@@ -0,0 +1,79 @@
<template>
  <LoginPageLayout class="loginByForm-page-wrapper">
    <div class="loginB-form-wrapper">
      <div class="loginB-form-tab">
        <div
          :class="[
            'loginB-form-tab-item',
            { active: tabType === LoginFormTabs.VerificationCodeLogin },
          ]"
          @click="handleTabChange(LoginFormTabs.VerificationCodeLogin)"
        >
          <img :src="IconTabBg1" alt="" class="loginB-form-tab-item-bg1" />
          <div class="loginB-form-tab-item-content">
            <div class="loginB-form-tab-item-text">验证码登录</div>
            <div class="loginB-form-tab-item-line"></div>
          </div>
        </div>
        <div
          :class="['loginB-form-tab-item', { active: tabType === LoginFormTabs.AccountLogin }]"
          @click="handleTabChange(LoginFormTabs.AccountLogin)"
        >
          <img :src="IconTabBg2" alt="" class="loginB-form-tab-item-bg2" />
          <div class="loginB-form-tab-item-content">
            <div class="loginB-form-tab-item-text">账户登录</div>
            <div class="loginB-form-tab-item-line"></div>
          </div>
        </div>
      </div>
      <VerificationCodeLoginForm
        v-show="tabType === LoginFormTabs.VerificationCodeLogin"
        :policyChecked="state.policyChecked"
      />
      <AccountLoginForm
        v-show="tabType === LoginFormTabs.AccountLogin"
        :policyChecked="state.policyChecked"
      />
    </div>
    <Policy
      v-model="state.policyChecked"
      policyBtnText="我已阅读并同意"
      class="loginB-form-policy"
    />
  </LoginPageLayout>
</template>
<script setup lang="ts">
import { useUserStore } from '@/stores/modules/user';
import LoginPageLayout from '../components/LoginPageLayout/LoginPageLayout.vue';
import { LoginFormTabs } from '../constants';
import IconTabBg1 from '@/assets/login/icon-tab-bg-1.png';
import IconTabBg2 from '@/assets/login/icon-tab-bg-2.png';
import VerificationCodeLoginForm from './verificationCodeLoginForm.vue';
import AccountLoginForm from './accountLoginForm.vue';
import { Policy } from '@/components';
import Taro from '@tarojs/taro';
defineOptions({
  name: 'loginByForm',
});
const userStore = useUserStore();
const state = reactive({
  policyChecked: false,
});
const router = Taro.useRouter();
const tabType = ref(Number(router.params?.tab ?? LoginFormTabs.VerificationCodeLogin));
function handleTabChange(tab: LoginFormTabs) {
  tabType.value = tab;
}
</script>
<style lang="scss">
@import '@/styles/common.scss';
@import '../styles/login.scss';
</style>
apps/bMiniApp/src/subpackages/login/loginByForm/verificationCodeLoginForm.vue
New file
@@ -0,0 +1,115 @@
<template>
  <div class="verification-code-login-form-wrapper">
    <nut-form class="verification-code-login-form" ref="formRef" :model-value="form" :rules="rules">
      <nut-form-item label="" class="bole-form-item" prop="phoneNumber" required>
        <nut-input
          v-model.trim="form.phoneNumber"
          class="bole-input-text"
          placeholder="请输入手机号"
          type="text"
        />
      </nut-form-item>
      <nut-form-item label="" class="bole-form-item" prop="verificationCode" required>
        <nut-input
          v-model.trim="form.verificationCode"
          class="bole-input-text"
          placeholder="请输入验证码"
          type="number"
        >
          <template #right>
            <ProFormCaptcha
              :onGetCaptcha="onGetCaptcha"
              phonePropName="phoneNumber"
              :validateField="formRef?.validate"
            ></ProFormCaptcha>
          </template>
        </nut-input>
      </nut-form-item>
    </nut-form>
    <LargeButton class="login-btn" @click="handleLogin" :loading="form.loading">登录</LargeButton>
    <div class="go-register-btn" @click="goRegister">立即注册</div>
  </div>
</template>
<script setup lang="ts">
import * as commonServices from '@12333/services/api/Common';
import { FormRules } from '@nutui/nutui-taro/dist/types/__VUE/form/types';
import { FormValidator, Message } from '@12333/utils';
import { LargeButton } from '@/components';
import { ProFormCaptcha } from 'senin-mini/components';
import { VerificationCodeBusinessType } from '@12333/constants';
import { useLoginedJump } from '@/hooks';
import { useUserStore } from '@/stores/modules/user';
import Taro from '@tarojs/taro';
defineOptions({
  name: 'verificationCodeLoginForm',
});
type Props = {
  policyChecked?: boolean;
};
const props = withDefaults(defineProps<Props>(), {});
const userStore = useUserStore();
const { jump } = useLoginedJump();
const formRef = ref(null);
const form = reactive({
  loading: false,
  phoneNumber: '',
  verificationCode: '',
});
const rules = reactive<FormRules>({
  phoneNumber: [
    { required: true, message: '请输入手机号' },
    { validator: FormValidator.validatorPhoneNumber, message: '请输入正确的手机号' },
  ],
  verificationCode: [{ required: true, message: '请输入验证码' }],
});
async function onGetCaptcha() {
  await commonServices.sendVerificationCode(
    {
      phoneNumber: form.phoneNumber,
      businessType: VerificationCodeBusinessType.PhoneMesssageCodeLogin,
    },
    { showLoading: false }
  );
}
async function handleLogin() {
  try {
    if (props.policyChecked) {
      const { valid } = await formRef.value.validate();
      if (valid) {
        form.loading = true;
        await userStore.loginByUsername({
          phoneNumber: form.phoneNumber,
          code: form.verificationCode,
        });
        jump();
      }
    } else {
      noAccess();
    }
  } catch (error) {
  } finally {
    form.loading = false;
  }
}
function noAccess() {
  Message.warning('请先阅读并勾选协议');
}
function goRegister() {
  Taro.navigateTo({
    url: RouterPath.registerForm,
  });
}
</script>
apps/bMiniApp/src/subpackages/login/registerForm/registerForm.vue
New file
@@ -0,0 +1,178 @@
<template>
  <LoginPageLayout class="registerForm-page-wrapper" title="注册">
    <div class="loginB-form-wrapper">
      <div class="register-form-title-wrapper">
        <div class="register-form-title">注册</div>
        <div class="register-form-title-line"></div>
      </div>
      <div class="verification-code-login-form-wrapper">
        <nut-form
          class="verification-code-login-form"
          ref="formRef"
          :model-value="form"
          :rules="rules"
        >
          <nut-form-item label="" class="bole-form-item" prop="phoneNumber" required>
            <nut-input
              v-model.trim="form.phoneNumber"
              class="bole-input-text"
              placeholder="请输入手机号"
              type="text"
            />
          </nut-form-item>
          <nut-form-item label="" class="bole-form-item" prop="verificationCode" required>
            <nut-input
              v-model.trim="form.verificationCode"
              class="bole-input-text"
              placeholder="请输入验证码"
              type="number"
            >
              <template #right>
                <ProFormCaptcha
                  :onGetCaptcha="onGetCaptcha"
                  phonePropName="phoneNumber"
                  :validateField="formRef?.validate"
                ></ProFormCaptcha>
              </template>
            </nut-input>
          </nut-form-item>
        </nut-form>
        <LargeButton class="login-btn" @click="handleRegister" :loading="form.loading"
          >注册</LargeButton
        >
        <div class="go-register-btn" @click="goLogin">立即登录</div>
      </div>
    </div>
    <Policy
      v-model="state.policyChecked"
      policyBtnText="我已阅读并同意"
      class="loginB-form-policy"
    />
  </LoginPageLayout>
</template>
<script setup lang="ts">
import LoginPageLayout from '../components/LoginPageLayout/LoginPageLayout.vue';
import { Policy } from '@/components';
import * as commonServices from '@12333/services/api/Common';
import { FormRules } from '@nutui/nutui-taro/dist/types/__VUE/form/types';
import { FormValidator, Message } from '@12333/utils';
import { LargeButton } from '@/components';
import { ProFormCaptcha } from 'senin-mini/components';
import { VerificationCodeBusinessType } from '@12333/constants';
import Taro from '@tarojs/taro';
import { ResponseCode } from '@12333/constants';
import * as accountServices from '@12333/services/api/Account';
defineOptions({
  name: 'registerForm',
});
const state = reactive({
  policyChecked: false,
});
const formRef = ref(null);
const form = reactive({
  loading: false,
  phoneNumber: '',
  verificationCode: '',
});
const rules = reactive<FormRules>({
  phoneNumber: [
    { required: true, message: '请输入手机号' },
    { validator: FormValidator.validatorPhoneNumber, message: '请输入正确的手机号' },
  ],
  verificationCode: [{ required: true, message: '请输入验证码' }],
});
async function onGetCaptcha() {
  await commonServices.sendVerificationCode(
    {
      phoneNumber: form.phoneNumber,
      businessType: VerificationCodeBusinessType.PhoneMesssageCodeRegister,
    },
    {
      showLoading: false,
      customErrorHandler(error) {
        if (error?.response?.data?.error?.code === ResponseCode.RegisterExistsPhoneNumber) {
          Message.confirm({
            message: '该手机号已注册,请去登录页登录',
            confirmText: '去登录',
          }).then(() => {
            goLogin();
          });
          return true;
        }
      },
    }
  );
}
async function handleRegister() {
  try {
    if (state.policyChecked) {
      const { valid } = await formRef.value.validate();
      if (valid) {
        let params: API.PhoneMesssageCodeRegisterInput = {
          code: form.verificationCode,
          phoneNumber: form.phoneNumber,
        };
        let res = await accountServices.phoneMesssageCodeRegister(params);
        if (res) {
          Message.success('注册成功', {
            onClosed: () => {
              goLogin();
            },
          });
        }
      }
    } else {
      noAccess();
    }
  } catch (error) {
  } finally {
    form.loading = false;
  }
}
function noAccess() {
  Message.warning('请先阅读并勾选协议');
}
const router = Taro.useRouter();
function goLogin() {
  Taro.navigateBack();
}
</script>
<style lang="scss">
@import '@/styles/common.scss';
@import '../styles/login.scss';
.registerForm-page-wrapper {
  .register-form-title-wrapper {
    padding-top: 20px;
    margin-bottom: 92px;
    .register-form-title {
      font-weight: 400;
      font-size: 28px;
      color: boleGetCssVar('color', 'primary');
      line-height: 40px;
      text-align: center;
      margin-bottom: 8px;
    }
    .register-form-title-line {
      width: 38px;
      height: 2px;
      background-color: boleGetCssVar('color', 'primary');
      margin: 0 auto;
    }
  }
}
</style>
apps/bMiniApp/src/subpackages/login/styles/login.scss
New file
@@ -0,0 +1,165 @@
@import '@/styles/common.scss';
.loginB-form-wrapper {
  flex: 1;
  min-height: 0;
  background-color: #fff;
  border-radius: 32px 32px 0px 0px;
  margin: 0 32px;
  display: flex;
  flex-direction: column;
  .loginB-form-tab {
    height: 108px;
    display: flex;
    margin-bottom: 46px;
    .loginB-form-tab-item {
      flex: 1;
      min-width: 0;
      display: flex;
      justify-content: center;
      padding-top: 20px;
      position: relative;
      .loginB-form-tab-item-content {
        position: relative;
        z-index: 1;
      }
      .loginB-form-tab-item-text {
        font-weight: 400;
        font-size: 28px;
        color: boleGetCssVar('text-color', 'primary');
        line-height: 40px;
        margin-bottom: 8px;
      }
      .loginB-form-tab-item-line {
        width: 36px;
        height: 2px;
        background-color: boleGetCssVar('color', 'primary');
        margin: 0 auto;
        display: none;
      }
      .loginB-form-tab-item-bg1 {
        position: absolute;
        z-index: 0;
        width: 376px;
        height: 108px;
        top: 1px;
        left: 1px;
      }
      .loginB-form-tab-item-bg2 {
        position: absolute;
        z-index: 0;
        width: 376px;
        height: 108px;
        top: 1px;
        right: 1px;
      }
      &.active {
        .loginB-form-tab-item-text {
          color: boleGetCssVar('color', 'primary');
        }
        .loginB-form-tab-item-line {
          display: block;
        }
        .loginB-form-tab-item-bg1,
        .loginB-form-tab-item-bg2 {
          display: none;
        }
      }
    }
  }
  .nut-cell-group__wrap {
    overflow: visible;
  }
  .bole-form-item {
    padding: 0 !important;
    margin-bottom: 40px;
    &:last-child {
      margin-bottom: 0;
    }
    &.error.line::before {
      z-index: 1;
      display: none;
      // right: 0;
      // left: 0;
      // top: 0;
      // border-radius: 44px;
    }
    &.error {
      .bole-input-text {
        border: 1px solid #fa2c19;
        box-sizing: border-box;
      }
    }
    .nut-form-item__body__tips {
      left: 30rpx !important;
      bottom: -36rpx !important;
    }
  }
  .bole-input-text {
    // border-bottom: none;
    border: 1px solid #f5f7fb;
    height: 88px;
    background: #f5f7fb;
    border-radius: 44px;
    padding: 24px 32px;
    /* .nut-input-value {
        display: flex;
        align-items: center;
      } */
    .h5-input {
      font-size: 28px;
    }
  }
}
.loginByForm-page-wrapper,
.registerForm-page-wrapper {
  .loginB-form-policy {
    margin-bottom: 40px;
  }
}
.verification-code-login-form-wrapper {
  display: flex;
  flex-direction: column;
  padding: 0 32px;
  .verification-code-login-form {
    margin-bottom: 60px;
    .nut-cell-group__wrap {
      box-shadow: none;
      margin-bottom: 0;
    }
  }
  .login-btn {
    margin-bottom: 32px;
  }
  .go-register-btn {
    align-self: center;
    color: boleGetCssVar('color', 'primary');
    font-size: 24px;
    line-height: 34px;
  }
}
apps/bMiniApp/src/subpackages/login/userPolicy/index.config.ts
New file
@@ -0,0 +1,3 @@
export default definePageConfig({
  disableScroll: true,
});
apps/bMiniApp/src/subpackages/login/userPolicy/userPolicy.vue
New file
@@ -0,0 +1,290 @@
<template>
  <PageLayout title="用户协议" :needAuth="false" class="userPolicy-page-wrapper">
    <scroll-view style="height: 100%" :scroll-y="true">
      <div class="userPolicy-page-scrollview-content">
        <div class="userPolicy-page-title">818平台用户服务协议</div>
        <UserPolicyCell title="一、接受条款">
          <div>1、本协议由您与818平台的经营者(以下称“平台”)共同缔结,本服务协议具有合同效力。</div>
          <div>
            2、由于互联网高速发展,您与平台签署的本协议列明的条款并不能完整罗列并覆盖您与平台所有权利与义务,现有的约定也不能保证完全符合未来发展的需求。因此,所有平台已经发布的或将来可能发布的各类规则均为本协议的补充协议,与本协议不可分割且具有同等法律效力。如您继续使用平台服务,视为您同意上述补充协议。
          </div>
          <div>
            3、在本服务协议中没有以“规则”字样表示的链接文字所指示的文件不属于本服务协议的组成部分,而是其它内容的协议或有关参考数据,与本协议没有法律上的直接关系。
          </div>
          <div>
            4、用户在使用平台提供的各项服务的同时,承诺接受并遵守各项相关规则的规定。平台有权根据需要不时地制定、修改本协议或各类规则,如本协议有任何变更,平台将以网站公告的形式进行更新,不再单独通知予您。如用户不同意相关变更,必须停止使用“服务”。经修订的协议一经在平台网站上公布后,立即自动生效。各类规则会在发布后生效,亦成为本协议的一部分。登录或继续使用“服务”将表示用户接受经修订的协议。除另行明确声明外,任何使“服务”范围扩大或功能增强的新内容均受本协议约束。
          </div>
          <div>
            5、用户确认本服务协议后,本服务协议即在用户和平台之间产生法律效力。请用户务必在注册之前认真阅读全部服务协议内容,如有任何疑问,可向平台咨询。
            <div>1)无论用户事实上是否在注册之前认真阅读了本服务协议,只要用户点击协议正本下方的“确认”按钮并按照平台注册程序成功注册为用户,用户的行为仍然表示其同意并签署了本服务协议。</div>
            <div>2)本协议不涉及用户与平台其它用户之间因网上交易而产生的法律关系及法律纠纷。</div>
          </div>
        </UserPolicyCell>
        <UserPolicyCell title="二、定义">
          <div>1、818平台:818平台指由818平台经营者运营的网络平台,包括但不限于818人力资源产业链平台,域名为www.81812333.com及81812333小程序等。</div>
          <div>2、818平台经营者:平台经营者是指法律认可的经营该平台网站的责任主体,有关818平台经营者的信息请查看818平台首页顶部的“关于”链接。</div>
          <div>3、818平台服务:818平台服务是指平台注册用户可在818平台上发布企业信息、交易信息、查询产品、产品相关信息及其他服务信息、达成交易意向并进行交易、对其他注册用户进行评价、参加平台组织的活动以及使用其它信息服务及技术服务。</div>
          <div>
            4、用户及用户账户:
            <div>1.用户:用户必须是具备完全民事行为能力的自然人,或者是具有合法经营资格的实体组织。无民事行为能力人、限制民事行为能力人以及无经营或特定经营资格的组织不当注册为平台用户或超过其民事权利或行为能力范围从事交易的,其与平台之间的服务协议自始无效,平台一经发现,有权立即注销该用户,并追究其使用平台“服务”的一切法律责任。</div>
            <div>2.用户注册:用户注册是指用户登陆平台,并按要求填写相关信息并确认同意履行相关用户协议的过程。</div>
            <div>3.账户转让:由于用户账户关联用户信用信息,仅当有法律明文规定、司法裁定或经平台同意的情况下,您可进行账户的转让。您的账户一经转让,该账户项下权利义务一并转移。除此外,您的账户不得以任何方式转让,否则平台有权追究您的违约责任,且由此产生的一切责任均由您承担。</div>
            <div>4.实名认证:为使您更好地使用平台的各项服务,保障您的账户安全,平台可要求您按国家法律法规的规定完成实名认证。</div>
            <div>5.不活跃账户回收:如您的账户同时符合以下条件,您的平台登录账户可能被屏蔽,不能再登陆平台,所有平台服务将同时终止:</div>
            <div>5.1.未通过实名认证的平台账户;</div>
            <div>5.2.连续180天未使用您的邮箱、手机或平台认可的其他方式和密码登录过平台网站;</div>
            <div>5.3.不存在未到期的有效业务</div>
            <div>6.注册信息管理</div>
            <div>6.1.在完成注册或激活流程时,您应当按平台相应页面的提示准确完整地提供并及时更新您的信息,以使之真实、及时,完整和准确。在国家法律法规有明确规定要求平台作为平台服务提供者必须对用户(如人力资源公司等)的信息进行核实的情况下,平台将依法不时地对您的信息进行检查核实,您应当配合提供最新、真实、完整、有效的信息。</div>
            <div>6.2.如平台按您最后一次提供的信息与您联系未果、您未按平台的要求及时提供信息、您提供的信息存在明显不实或行政司法机关核实您提供的信息无效的,您将承担因此对您自身、他人及平台造成的全部损失与不利后果。平台可向您发出询问或要求整改的通知,并要求您进行资料更新或重新认证,直至中止、终止对您提供部分或全部平台服务,平台对此不承担责任。</div>
            <div>6.3.您设置的账户登录名及昵称不得违反国家法律法规及平台规则的相应管理规定,否则平台可回收您的登录名及昵称,并按平台规则进行相应的处理。</div>
          </div>
        </UserPolicyCell>
        <UserPolicyCell title="三、用户的权利和义务">
          <div>1、用户有权使用您设置或确认的邮箱、手机号码(以下简称“账户名称”)及您设置的密码(账户名称及密码合称“账户”)登录平台。
            由于您的平台网账户关联您的个人信息及平台商业信息,您的平台网账户仅限您本人使用。未经平台同意,您直接或间接授权第三方使用您平台网账户或获取您账户项下信息的行为无效。如平台判断您账户的使用可能危及您的账户安全及/或平台信息安全的,平台可拒绝提供相应服务或终止本协议。</div>
          <div>2、用户应积极维护平台运营秩序,不得通过软件、程序等方式,大批量注册账户,妨害平台运营秩序(以下简称“不当注册”)。对于平台排查到的涉嫌不当注册的会员,平台将视情节采取警告、身份验证、限制开通展台、限制购买网站相关服务、限制发布产品、限制网站登录等临时性管理措施。</div>
          <div>3、用户有权根据本服务协议的规定以及平台上发布的相关规则利用平台发布企业信息、交易信息、查询产品、产品相关信息及其他服务信息、达成交易意向并进行交易、对其他注册用户进行评价、参加平台组织的活动以及使用其它信息服务及技术服务。</div>
          <div>4、用户在平台网上交易过程中如与平台其他用户因交易产生纠纷,可以请求平台从中予以协调。用户如发现平台其他用户有违法或违反本服务协议的行为,可以向平台进行反映要求处理。如用户因网上交易与其他用户产生诉讼的,用户有权通过司法部门要求平台提供相关资料;</div>
          <div>5、用户有义务在注册时提供自己的真实资料,并保证诸如电子邮件地址、联系电话、联系地址、邮政编码等内容的有效性及安全性,保证平台及平台其他用户可以通过上述联系方式与自己进行联系。同时,用户也有义务在相关资料实际变更时及时更新有关注册资料。用户保证不以他人资料在平台上进行注册或认证;如用户提供的信息不真实、不准确、不及时或不完全,或平台有合理的理由怀疑其真实性、准确性、及时性和完整性,则平台有权视情况对用户采取警告、账户限权限制直至账户屏蔽等管理措施,并有权拒绝用户使用任何现有的服务及以后可能提供的任何功能或服务。</div>
          <div>6、用户应充分了解并同意,818人力资源产业链平台是一个行业平台,故您的询价、采购行为应当基于真实的行业需求,不得存在对产品及/或服务实施恶意询价、采购、恶意维权等扰乱平台正常交易秩序的行为。基于维护平台交易秩序及交易安全的需要,平台发现上述情形时可主动执行关闭相关交易订单等操作。</div>
          <div>7、用户在平台上不得发布如下各类违法或违规信息;</div>
        </UserPolicyCell>
        <UserPolicyCell title="四、平台的权利和义务">
          <div>1、平台有义务在现有技术上维护整个平台的正常运行,并努力提升和改进技术,使用户网上交易活动得以顺利进行;</div>
          <div>2、对用户在注册使用平台中所遇到的与交易或注册有关的问题及反映的情况,平台应及时作出回复;</div>
          <div>3、对于用户在平台上的不当行为或其它任何平台认为应当终止服务的情况,平台有权随时作出删除相关信息、终止服务提供等处理,而无须征得用户的同意;</div>
          <div>
            4、因网上交易平台的特殊性,平台没有义务对所有用户的注册数据、所有的交易行为以及与交易有关的其它事项进行事先审查,但如存在下列情况:
            <div>1)用户或其它第三方通知平台,认为某个具体用户或具体交易事项可能存在重大问题;</div>
            <div>2)用户或其它第三方向平台告知平台上有违法或不当行为的,平台以普通非专业交易者的知识水平标准对相关内容进行判别,可以明显认为这些内容或行为具有违法或不当性质的;</div>
            <div>针对上述情况(包括但不限于),平台有权根据不同情况选择保留或删除相关信息或继续、停止对该用户提供服务,并追究相关法律责任。</div>
          </div>
          <div>5、用户在平台交易过程中如与平台其它用户因交易产生纠纷,请求平台从中予以调处,经平台审核后,平台有权通过电话、电子邮件等联系方式向纠纷双方了解情况,并将所了解的情况通过电话、电子邮件等联系方式互相通知对方;</div>
          <div>6、用户因在平台上交易与其它用户产生诉讼的,用户通过司法部门或行政部门依照法定程序要求平台提供相关数据,平台应积极配合并提供有关资料;</div>
          <div>7、平台有权对用户的注册数据及交易行为进行查阅,发现注册数据或交易行为中存在任何问题或怀疑,均有权向用户发出询问及要求改正的通知或者直接作出删除等处理;</div>
          <div>8、经国家生效法律文书或行政处罚决定确认用户存在违法行为,或者平台有足够事实依据可以认定用户存在违法或违反服务协议行为的,平台有权在平台上以公告发布的形式公布用户的违法行为;</div>
          <div>9、对于用户在平台发布的下列各类信息,平台有权在不通知用户的前提下进行删除或采取其它限制性措施,包括但不限于以规避费用为目的的信息;以炒作信用为目的的信息;平台有理由相信存在欺诈等恶意或虚假内容的信息;平台有理由相信与网上交易无关或不是以交易为目的的信息;平台有理由相信存在恶意竞价或其它试图扰乱正常交易秩序因素的信息;平台有理由相信该信息违反公共利益或可能严重损害平台和其它用户合法利益的;</div>
          <div>10、用户因进行交易、获取有偿服务或接触平台服务器而发生的所有应纳税赋,以及一切硬件、软件、服务及其它方面的费用均由用户负责支付;</div>
          <div>11、平台仅作为交易地点。平台仅作为用户物色交易对象,就产品和服务的交易进行协商,以及获取各类相关的服务的地点。平台不能控制交易所涉及的物品、服务的质量、安全或合法性,信息的真实性或准确性,以及交易方履行其在协议项下的各项义务的能力;</div>
          <div>12、平台并不作为买家或是卖家的身份参与买卖行为的本身。平台提醒用户应该通过自己的谨慎判断确定相关信息的真实性、合法性和有效性;</div>
          <div>13、许可使用权。 用户以此授予平台及其关联公司独家的、全球通用的、永久的、免费的许可使用权利 (并有权在多个层面对该权利进行再授权),使平台及其关联公司有权(全部或部份地) 使用、复制、修订、改写、发布、翻译、分发、执行和展示用户的全部资料数据(包括但不限于注册资料、交易行为数据及全部展示于网站的各类信息)或制作其派生作品,和/或以现在已知或日后开发的任何形式、媒体或技术,将上述信息纳入其它作品内。</div>
        </UserPolicyCell>
        <UserPolicyCell title="五、用户的违约及处理">
          <div>1、违约认定</div>
          <div>发生如下情形之一的,视为您违约:</div>
          <div>1.使用平台服务时违反有关法律法规规定的;</div>
          <div>2.违反本协议或平台将在未来更新的其他类型的补充协议的;</div>
          <div>为适应电子商务发展和满足海量用户对高效优质服务的需求,您理解并同意,平台可在平台规则中约定违约认定的程序和标准。如:平台可依据您的用户数据与海量用户数据的关系来认定您是否构成违约;您有义务对您的数据异常现象进行充分举证和合理解释,否则将被认定为违约。</div>
          <div>2、违约处理措施</div>
          <div>1.您在平台上发布的信息构成违约的,平台可根据相应规则立即对相应信息进行删除、屏蔽处理。</div>
          <div>2.您在平台上实施的行为,或虽未在平台上实施但对平台及其用户产生影响的行为构成违约的,平台可依据相应规则对您执行账户惩戒、限制参加活动、中止向您提供部分或全部服务、划扣违约金等处理措施。如您的行为构成根本违约的,平台可关闭您的账户,终止向您提供服务。</div>
          <div>3.当您违约的同时存在欺诈、售假、盗用他人账户等特定情形或您存在危及他人交易安全或账户安全风险时,平台会依照您行为的风险程度对您的平台账户采取取消收款、资金止付等强制措施。</div>
          <div>4.平台可将对您上述违约行为处理措施信息以及其他经国家行政或司法机关生效法律文书确认的违法信息在平台上予以公示。</div>
          <div>3、赔偿责任</div>
          <div>1.如您的行为使平台遭受损失(包括自身的直接经济损失、商誉损失及对外支付的赔偿金、和解款、律师费、诉讼费等间接经济损失),您应赔偿平台的上述全部损失。</div>
          <div>2.如您的行为使平台遭受第三人主张权利,平台可在对第三人承担金钱给付等义务后就全部损失向您追偿。</div>
        </UserPolicyCell>
        <UserPolicyCell title="六、服务的中断和终止">
          <div>1、用户同意,在平台未向用户收取服务费的情况下,平台可自行全权决定以任何理由 (包括但不限于平台认为用户已违反本协议的字面意义和精神,或以不符合本协议的字面意义和精神的方式行事,或用户在超过180天的时间内未以用户的账号及密码登录网站等) 终止用户的“服务”密码、账户 (或其任何部份) 或用户对“服务”的使用,并删除(不再保存)用户在使用“服务”中提交的任何资料。同时平台可自行全权决定,在发出通知或不发出通知的情况下,随时停止提供“服务”或其任何部份。账号终止后,平台没有义务为用户保留原账号中或与之相关的任何信息,或转发任何未曾阅读或发送的信息给用户或第三方。此外,用户同意,平台不就终止用户接入“服务”而对用户或任何第三者承担任何责任;</div>
          <div>2、如用户向平台提出注销平台注册用户身份时,经平台审核同意,由平台注销该注册用户,用户即解除与平台的服务协议关系。但注销该用户账号后,平台仍保留下列权利:</div>
          <div>1)用户注销后,平台有权保留该用户的注册数据及以前的交易行为记录;</div>
          <div>2)用户注销后,如用户在注销前在平台交易平台上存在违法行为或违反合同的行为,平台仍可行使本服务协议所规定的权利。</div>
          <div>3、在下列情况下,平台可以通过注销用户的方式终止服务:</div>
          <div>1)在用户违反本服务协议相关规定时,平台有权终止向该用户提供服务。平台将在中断服务时通知用户。但如该用户在被平台终止提供服务后,再一次直接或间接或以他人名义注册为平台用户的,平台有权再次单方面终止向该用户提供服务;</div>
          <div>2)如平台通过用户提供的信息与用户联系时,发现用户在注册时填写的手机号码、电子邮箱已不存在或无法接听电话或接收电子邮件的,经平台以其它联系方式通知用户更改,而用户在三个工作日内仍未能提供新的手机号码或电子邮箱地址的,平台有权终止向该用户提供服务;</div>
          <div>3)一旦平台发现用户注册数据中主要内容是虚假的,平台有权随时终止向该用户提供服务;</div>
          <div>4)一旦平台发现用户盗用他人账户、发布违禁信息、欺诈、售假、扰乱市场秩序、采取不正当手段牟利等行为的,平台有权随时终止向该用户提供服务;</div>
          <div>5)平台基于合理理由相信用户的行为可能会使平台及平台用户等相关方发生严重损害或产生法律责任的,平台有权随时终止向该用户提供服务;</div>
          <div>6)对于隐瞒其从事同业互联网服务的用户,平台一经发现,有权立即终止服务;</div>
          <div>7)本服务协议终止或更新时,用户明示不愿接受新的服务协议的;</div>
          <div>8)其它平台认为需终止服务的情况。</div>
          <div>4、服务中断、终止之前用户交易行为的处理因用户违反法律法规或者违反服务协议规定而致使平台中断、终止对用户服务的,对于服务中断、终止之前用户交易行为依下列原则处理:</div>
          <div>1)服务中断、终止之前,用户已经上传至平台的产品尚未交易或尚未交易完成的,平台有权在中断、终止服务的同时删除此项产品的相关信息;</div>
          <div>2)服务中断、终止之前,用户已经就其它用户出售的具体产品作出要约,但交易尚未结束,平台有权在中断或终止服务的同时删除该用户的相关要约;</div>
          <div>3)服务中断、终止之前,用户已经与另一用户就具体交易达成一致,平台可以不删除该项交易,但平台有权在中断、终止服务的同时将用户被中断或终止服务的情况通知用户的交易对方。</div>
        </UserPolicyCell>
        <UserPolicyCell title="七、隐私权政策">
          <div>1、适用范围:</div>
          <div>1)在用户注册平台账户时,用户根据平台要求提供的个人注册信息;</div>
          <div>2)在用户使用平台服务,参加平台活动,或访问平台网站时,平台自动接收并记录的用户浏览器上的服务器数值,包括但不限于IP地址等数据及用户要求取用的网页记录;</div>
          <div>3)平台收集到的用户在平台进行交易的有关数据,包括但不限于出价、购买、产品登录、信用评价及违规记录;</div>
          <div>4)平台通过合法途径从商业伙伴处取得的用户个人数据。</div>
          <div>5)我们收集数据是根据您与我们的互动和您所做出的选择,包括您的隐私设置以及您使用的产品和功能。我们收集的数据可能包括SDK/API/JS代码版本、浏览器、互联网服务提供商、IP地址、平台、时间戳、应用标识符、应用程序版本、应用分发渠道、独立设备标识符、iOS广告标识符(IDFA)、安卓广告主标识符、网卡(MAC)地址、国际移动设备识别码(IMEI)、设备型号、终端制造厂商、终端设备操作系统版本、会话启动/停止时间、语言所在地、时区和网络状态(WiFi等)、硬盘、CPU和电池使用情况等。</div>
          <div>2、信息使用:</div>
          <div>1)平台不会向任何人出售或出借用户的个人信息,除非事先得到用户得许可。</div>
          <div>2)平台亦不允许任何第三方以任何手段收集、编辑、出售或者无偿传播用户的个人信息。任何用户如从事上述活动,一经发现,平台有权立即终止与该用户的服务协议,查封其账号。</div>
          <div>3)为服务用户的目的,平台可能通过使用用户的个人信息,向用户提供服务及产品改进,包括但不限于向用户发出产品和服务信息,或者与平台合作伙伴共享信息以便他们向用户发送有关其产品和服务的信息(后者需要用户的事先同意)。例如,我们聘请来提供数据分析服务的公司可能需要采集和访问个人数据以进行数据统计和分析。在这种情况下,这些公司必须遵守我们的数据隐私和安全要求。</div>
          <div>4)我们已在上文介绍了处理个人数据的目的。我们处理个人数据的法律基础包括:为履行与您之间的合同(例如,为您提供您所请求的服务、对您进行识别和认证,以便您可以使用网站);为遵守法律要求(例如,为遵守适用的会计规则,履行执法部门强制披露的要求);为保护我们的正当利益(例如,管理我们与您的关系,为确保我们服务的安全性,与您沟通我们的产品和服务);以及基于我们客户的同意(例如,投放cookies,为广告宣传之目的与第三方共享您的信息)。在某些情况下,您可能需要为我们提供个人数据以进行上述的处理,以便我们能够为您提供我们的全部服务,并方便您使用我们网站的全部功能。</div>
          <div>5)个人数据的跨境传输。针对欧盟成员国用户,我们的业务可能需要我们转移您的个人数据至欧洲经济区以外的国家(中国)。我们会采取适当的措施以确保您个人数据的接收者履行保密义务,并确保如标准合同条款等措施的执行。您可以通过联系我们的帮助中心获得这些条款。</div>
          <div>6)针对欧盟成员国用户,根据适用法律,您有权反对或要求限制对您个人数据的处理,并要求您本人数据的访问、校正、删除和可携带权。在对您的信息的使用是基于您的同意的情况下,您有权在任何时候撤回该同意,但同意的撤回不影响撤回前基于同意进行的数据处理的合法性。您可以通过客服电话16505012333向我们提交您的要求。如果您发现您的信息发生变化或不准确,请将这些变化通知我们以便我们的记录可以被更新或更正。如果您认为我们对您个人数据的处理违反了适用法律,您可以向监管机构投诉。我们对您个人数据的保留时间视向您提供服务或产品的需要而定,或根据适用法律如税法和会计法的要求或许可确定。</div>
          <div>3、信息披露,用户的个人信息将在下述情况下部分或全部被披露:</div>
          <div>1)经用户同意,向第三方披露;</div>
          <div>2)如用户是符合资格的知识产权投诉人并已提起投诉,应被投诉人要求,向被投诉人披露,以便双方处理可能的权利纠纷;</div>
          <div>3)根据法律的有关规定,或者行政或司法机构的要求,向第三方或者行政、司法机构披露;</div>
          <div>4)如果用户出现违反中国有关法律或者网站政策的情况,需要向第三方披露;</div>
          <div>5)为提供您所要求的产品和服务,而必须和第三方分享用户的个人信息;</div>
          <div>6)在平台上创建的某一交易中,如交易任何一方履行或部分履行了交易义务并提出信息披露请求的,平台有全权可以决定向该用户提供其交易对方的联络方式等必要信息,以促成交易的完成或纠纷的解决;</div>
          <div>7)其它平台根据法律或者网站政策认为合适的披露。</div>
          <div>4、信息安全:</div>
          <div>1)平台及平台账户均有安全保护功能,请妥善保管用户的账户及密码信息;</div>
          <div>2)在使用平台服务进行网上交易时,用户不可避免的要向交易对方或潜在的交易对方提供自己的个人信息,如联络方式或者邮政地址。请用户妥善保护自己的个人信息,仅在必要的情形下向他人提供;</div>
          <div>3)如果用户发现自己的个人信息泄密,尤其是平台账户及密码发生泄露,请用户立即联络平台客服,以便平台采取相应措施。</div>
        </UserPolicyCell>
        <UserPolicyCell title="八、责任范围和责任限制">
          <div>1、您明确理解和同意,平台不对因下述任一情况而发生的任何损害赔偿承担责任,包括但不限于利润、商誉、使用、数据等方面的损失或其他无形损失的损害赔偿 (无论平台是否已被告知该等损害赔偿的可能性):</div>
          <div>1)使用或未能使用“服务;</div>
          <div>2)第三方未经批准的接入或第三方更改用户的传输数据或数据;</div>
          <div>3)第三方对“服务”的声明或关于“服务”的行为;或非因平台的原因而引起的与“服务”有关的任何其它事宜,包括疏忽。</div>
          <div>2、平台会尽一切努力使您在使用平台的过程中得到乐趣。遗憾的是,平台不能随时预见到任何技术上的问题或其他困难。该等困难可能会导致数据损失或其他服务中断。为此,您明确理解和同意,您使用“服务”的风险由您自行承担,且“服务”以“按现状”和“按可得到 ”的状态提供。平台明确声明不作任何种类的明示或暗示的保证,包括但不限于关于适销性、适用于某一特定用途和无侵权行为等方面的保证。平台对下述内容不作保证:</div>
          <div>1)“服务”会符合您的要求;</div>
          <div>2)“服务”不会中断,且适时、安全和不带任何错误;</div>
          <div>3)通过使用“服务”而可能获取的结果将是准确或可信赖的;</div>
          <div>4)您通过“服务”而购买或获取的任何产品、服务、资料或其他材料的质量将符合您的预期。通过使用“服务”而下载或以其他形式获取任何材料是由您自行全权决定进行的,且与此有关的风险由您自行承担,对于因您下载任何该等材料而发生的您的电脑系统的任何损毁或任何数据损失,您将自行承担责任。您从平台或通过或从“服务”获取的任何口头或书面意见或资料,均不产生未在本协议内明确载明的任何保证责任。</div>
          <div>3、不论在何种情况下,平台均不对由于信息网络正常的设备维护,信息网络连接故障,电脑、通讯或其他系统的故障,电力故障,罢工,劳动争议,暴乱,起义,骚乱,生产力或生产资料不足,火灾,洪水,风暴,爆炸,战争,政府行为,司法行政机关的命令或第三方的不作为而造成的不能服务或延迟服务承担责任。</div>
          <div>4、平台仅向您提供本协议约定之服务,您了解平台上的信息系用户自行发布,且可能存在风险和瑕疵。平台将通过依照法律规定建立相关检查监控制度尽可能保障您在平台上的合法权益及良好体验。同时,鉴于平台具备存在海量信息及信息网络环境下信息与实物相分离的特点,平台无法逐一审查产品及/或服务的信息,无法逐一审查交易所涉及的产品及/或服务的质量、安全以及合法性、真实性、准确性,对此您应谨慎判断。</div>
          <div>5、您理解并同意,在争议调处服务中,平台的客服并非专业人士,仅能以普通人的认知对用户提交的凭证进行判断,平台不保证争议调处决定一定符合您的期望,除存在故意或重大过失外,平台对争议调处决定免责。</div>
        </UserPolicyCell>
        <UserPolicyCell title="九、政策修改:平台保留对本政策作出不时修改的权利。"></UserPolicyCell>
        <UserPolicyCell title="十、商标、知识产权的保护">
          <div>1、平台上所有内容,包括但不限于著作、图片、档案、资讯、资料、网站架构、网站画面的安排、网页设计,均由平台依法拥有其知识产权,包括但不限于商标权、专利权、著作权、商业秘密等。</div>
          <div>2、非经平台书面同意,任何人不得擅自使用、修改、复制、公开传播、改变、散布、发行或公开发表平台网站程序或内容。</div>
          <div>3、尊重知识产权是您应尽的义务,如有违反,您应承担损害赔偿责任。</div>
        </UserPolicyCell>
        <UserPolicyCell title="十一、法律适用、管辖及其他">
          <div>1、本协议之效力、解释、变更、执行与争议解决均适用中华人民共和国大陆地区法律,如无相关法律规定的,则应参照通用国际商业惯例和(或)行业惯例;</div>
          <div>2、您与平台仅为独立订约人关系。本协议无意结成或创设任何代理、合伙、合营、雇佣与被雇佣或特性授权与被授权关系;</div>
          <div>3、您同意平台因经营业务需要有权将本协议项下的权力义务就部分或全部进行转让,而无须再通知予您并取得您的同意;</div>
          <div>4、因本协议或平台服务所引起或与其有关的任何争议应向平台经营者所在地人民法院提起诉讼;</div>
          <div>5、本协议取代您和平台先前就相同事项订立的任何书面或口头协议。倘若本协议任何条款被裁定为无效或不可强制执行,该项条款应被撤销,而其余条款应予遵守和执行。条款标题仅为方便参阅而设,并不以任何方式界定、限制、解释或描述该条款的范围或限度。平台未就您或其他人士的某项违约行为采取行动,并不表明平台撤回就任何继后或类似的违约事件采取动的权利。</div>
        </UserPolicyCell>
        <div class="userPolicy-page-title">818人力资源产业链平台用户服务隐私政策</div>
        <UserPolicyCell title="1、适用范围:">
          <div>1)在用户注册818人力资源产业链平台账户时(以下简称“平台”),用户根据平台要求提供的相关个人信息;</div>
          <div>
            2)在用户使用平台服务,参加平台活动,或访问平台网站时,平台将自动接收并记录的用户浏览器上的服务器数值,包括但不限于IP地址等数据及用户要求取用的网页/客户端记录;
          </div>
          <div>
            3)平台收集到的用户在平台进行交易的有关数据,包括但不限于出价、购买、产品登录、信用评价及违规记录;
          </div>
          <div>
            4)平台通过合法途径从商业伙伴处取得的用户个人数据。
          </div>
          <div>
            5)我们收集数据是根据您与我们的互动和您所做出的选择,包括您的隐私设置以及您使用的产品和功能。我们收集的数据可能包括SDK/API/JS代码版本、浏览器、互联网服务提供商、IP地址、平台、时间戳、应用标识符、应用程序版本、应用分发渠道、独立设备标识符、iOS广告标识符(IDFA)、安卓广告主标识符、网卡(MAC)地址、国际移动设备识别码(IMEI)、设备型号、终端制造厂商、终端设备操作系统版本、会话启动/停止时间、语言所在地、时区和网络状态(WiFi等)等。
          </div>
        </UserPolicyCell>
        <UserPolicyCell title="2、信息使用:">
          <div>1)平台不会向任何人出售或出借用户的个人信息,除非事先得到用户得许可。</div>
          <div>2)平台亦不允许任何第三方以任何手段收集、编辑、出售或者无偿传播用户的个人信息。任何用户如从事上述活动,一经发现,平台有权立即终止与该用户的服务协议,查封其账号。</div>
          <div>3)为服务用户的目的,平台可能通过使用用户的个人信息,向用户提供服务及产品改进,包括但不限于向用户发出产品和服务信息,或者与平台合作伙伴共享信息以便他们向用户发送有关其产品和服务的信息(后者需要用户的事先同意)。例如,我们聘请来提供数据分析服务的公司可能需要采集和访问个人数据以进行数据统计和分析。在这种情况下,这些公司必须遵守我们的数据隐私和安全要求。</div>
          <div>4)我们已在上文介绍了处理个人数据的目的。我们处理个人数据的法律基础包括:为履行与您之间的合同(例如,为您提供您所请求的服务、对您进行识别和认证,以便您可以使用网站);为遵守法律要求(例如,为遵守适用的会计规则,履行执法部门强制披露的要求);为保护我们的正当利益(例如,管理我们与您的关系,为确保我们服务的安全性,与您沟通我们的产品和服务);以及基于我们客户的同意(例如,投放cookies,为广告宣传之目的与第三方共享您的信息)。在某些情况下,您可能需要为我们提供个人数据以进行上述的处理,以便我们能够为您提供我们的全部服务,并方便您使用我们网站的全部功能。</div>
          <div>5)个人数据的跨境传输。针对欧盟成员国用户,我们的业务可能需要我们转移您的个人数据至欧洲经济区以外的国家(中国)。我们会采取适当的措施以确保您个人数据的接收者履行保密义务,并确保如标准合同条款等措施的执行。您可以通过联系我们的帮助中心获得这些条款。</div>
          <div>6)针对欧盟成员国用户,根据适用法律,您有权反对或要求限制对您个人数据的处理,并要求您本人数据的访问、校正、删除和可携带权。在对您的信息的使用是基于您的同意的情况下,您有权在任何时候撤回该同意,但同意的撤回不影响撤回前基于同意进行的数据处理的合法性。您可以通过客服电话:16505012333向我们提交您的要求。如果您发现您的信息发生变化或不准确,请将这些变化通知我们以便我们的记录可以被更新或更正。如果您认为我们对您个人数据的处理违反了适用法律,您可以向监管机构投诉。我们对您个人数据的保留时间视向您提供服务或产品的需要而定,或根据适用法律如税法和会计法的要求或许可确定。</div>
        </UserPolicyCell>
        <UserPolicyCell title="3、信息披露,用户的个人信息将在下述情况下部分或全部被披露:">
          <div>1)经用户同意,向第三方披露;</div>
          <div>2)如用户是符合资格的知识产权投诉人并已提起投诉,应被投诉人要求,向被投诉人披露,以便双方处理可能的权利纠纷;</div>
          <div>3)根据法律的有关规定,或者行政或司法机构的要求,向第三方或者行政、司法机构披露;</div>
          <div>4)如果用户出现违反中国有关法律或者网站政策的情况,需要向第三方披露;</div>
          <div>5)为提供您所要求的产品和服务,而必须和第三方分享用户的个人信息;</div>
          <div>6)在平台网上创建的某一交易中,如交易任何一方履行或部分履行了交易义务并提出信息披露请求的,平台有全权可以决定向该用户提供其交易对方的联络方式等必要信息,以促成交易的完成或纠纷的解决;</div>
          <div>7)其它平台根据法律或者网站政策认为合适的披露。</div>
        </UserPolicyCell>
        <UserPolicyCell title="4、信息安全:">
          <div>1)平台及平台账户均有安全保护功能,请妥善保管用户的账户及密码信息;</div>
          <div>2)在使用平台服务进行网上交易时,用户不可避免的要向交易对方或潜在的交易对方提供自己的个人信息,如联络方式或者邮政地址。请用户妥善保护自己的个人信息,仅在必要的情形下向他人提供;</div>
          <div>3)如果用户发现自己的个人信息泄密,尤其是平台账户及密码发生泄露,请用户立即联络平台客服,以便平台采取相应措施。
            如用户对如何撤回信息授权有疑问,可以在工作日(周一到周五 及 法定节假日调整的工作日)工作时间(09:00 -- 18:00) 致电平台客服电话:16505012333,请客服人员协助处理</div>
        </UserPolicyCell>
        <UserPolicyCell title="5、如何注销/删除账户">
          <div>1)用户可以在工作日(周一到周五及法定节假日调整的工作日)工作时间(09:00 -- 18:00) 致电平台客服电话:16505012333,告知客服人员注册账户信息,并告知客服人员需要注销/删除个人用户信息,致电第二日开始计算,两个工作日内办结并致电/短信通知申请人。</div>
          <div>2)用户可以任何时间,访问平台反馈中心网页,www.81812333.com在线留言,客服工作日接收信息后,会致电申请人确认信息,并在两个工作日内办结。</div>
        </UserPolicyCell>
        <UserPolicyCell title="6、APP所收集个人信息的目的、方式和范围">
          <div>1)、平台所收集的信息,仅限于用户在平台网开展基础业务活动。</div>
          <div>2)、信息收集的方式和范围</div>
          <div>获取您相册、相机的权限,用于企业信息、订单发布、个人头像的图片上传。</div>
          <div>获取本地存储权限,我们将请求您的存储权限获取外置存储信息(SD卡数据)以保存您在平台千询的使用过程中的业务数据。</div>
          <div>获取您的设备信息(包括IMEI、设备序列号、OAID、MEID、Android ID、IMSI、GUID、MAC地址、SIM卡序列号),设备特征码和IP地址,已安装APP信息或运行中的进程信息,来保证您账号使用的唯一性、安全性。</div>
          <div>当您播放视频等内容时,为了适配您的设备状态,我们会调用设备的重力、加速度等传感器信息,以识别您的设备横竖屏状态。</div>
          <div>在您分享或接收被分享的信息时,需要在本地访问您的剪切板,读取其中包含的口令、分享码、链接等,以实现跳转、分享、活动联动等功能或服务。</div>
        </UserPolicyCell>
        <UserPolicyCell title="7、自启动和关联启动说明">
          <div>为确保本应用处于关闭或后台运行状态下可正常接收到客户端推送的广播消息,本应用须使用(自启动)能力,将存在一定频率通过系统发送广播唤醒本应用自启动或关联启动行为,是因实现功能及服务所必要的。</div>
        </UserPolicyCell>
      </div>
    </scroll-view>
  </PageLayout>
</template>
<script setup lang="ts">
import { PageLayout } from '@/components';
import { ScrollView } from '@tarojs/components';
defineOptions({
  name: 'userPolicy',
});
const UserPolicyCell = defineComponent({
  name: 'UserPolicyCell',
  props: {
    title: {
      type: String,
    },
    content: {
      type: String,
    },
  },
  setup(props, { slots }) {
    return () => {
      return h('div', { class: 'userPolicy-cell-wrapper' }, [
        h('div', { class: 'userPolicy-cell-title' }, [props.title]),
        h('div', { class: 'userPolicy-cell-content' }, slots.default?.()),
      ]);
    };
  },
});
</script>
<style lang="scss">
@import '@/styles/common.scss';
.userPolicy-page-wrapper {
  background-color: #fafafa;
  .userPolicy-page-scrollview {
    // flex: 1;
    height: 100%;
    box-sizing: border-box;
  }
  .userPolicy-page-scrollview-content {
      padding: 42px;
      .userPolicy-page-title {
        margin-bottom: 40px;
      }
  }
  .userPolicy-cell-wrapper {
    margin-bottom: 32px;
    .userPolicy-cell-title {
      color: #292929;
      font-size: 30px;
      margin-bottom: 22px;
      font-weight: 500;
    }
    .userPolicy-cell-content {
      div {
        font-size: 24px;
        line-height: 40px;
        text-indent: 28px;
        color: #888888;
      }
    }
  }
}
</style>
apps/bMiniApp/src/subpackages/user/complaint/complaint.config.ts
New file
@@ -0,0 +1,3 @@
export default definePageConfig({
  disableScroll: true,
});
apps/bMiniApp/src/subpackages/user/complaint/complaint.vue
New file
@@ -0,0 +1,116 @@
<template>
  <PageLayout title="投诉举报" class="cooperation-page-wrapper" hasBorder :needAuth="false">
    <ContentScrollView :paddingH="false">
      <nut-form :model-value="form" ref="formRef" :rules="rules">
        <nut-form-item label="企业名称:" class="bole-form-item" prop="companyName" required>
          <nut-input
            v-model.trim="form.companyName"
            class="nut-input-text bole-input-text"
            placeholder="请输入企业名称"
            type="text"
            :max-length="35"
            show-word-limit
          />
        </nut-form-item>
        <nut-form-item label="联系人:" class="bole-form-item" prop="contact" required>
          <nut-input
            v-model.trim="form.contact"
            class="nut-input-text bole-input-text"
            placeholder="请输入联系人姓名"
            type="text"
            :max-length="10"
            show-word-limit
          />
        </nut-form-item>
        <nut-form-item label="联系电话:" class="bole-form-item" prop="contactPhone" required>
          <nut-input
            v-model.trim="form.contactPhone"
            class="nut-input-text bole-input-text"
            placeholder="请输入联系人电话"
            type="text"
          />
        </nut-form-item>
        <nut-form-item label="投诉说明:" class="bole-form-item alignTop" prop="remark" required>
          <nut-textarea
            placeholder="请输入举报投诉的说明"
            placeholderClass="bole-input-text-placeholder"
            autoSize
            class="bole-input-textarea"
            v-model="form.remark"
            :max-length="500"
            show-word-limit
          >
          </nut-textarea>
        </nut-form-item>
      </nut-form>
    </ContentScrollView>
    <PageFooter :isOnlyAction="false">
      <PageFooterBtn type="primary" @click="handleConfirm">提交</PageFooterBtn>
    </PageFooter>
  </PageLayout>
</template>
<script setup lang="ts">
import { FormRules } from '@nutui/nutui-taro/dist/types/__VUE/form/types';
import * as cooperationApplyServices from '@12333/services/api/CooperationApply';
import { CooperateTypeText, CooperateApplyTypeEnum } from '@12333/constants';
import { FormValidator, Message } from '@12333/utils';
import Taro from '@tarojs/taro';
import { useUser } from '@/hooks';
defineOptions({
  name: 'complaint',
});
const { userDetail } = useUser();
const form = reactive({
  companyName: userDetail.value?.customerName ?? '',
  contact: userDetail.value?.contacter ?? '',
  contactPhone: userDetail.value?.phoneNumber ?? '',
  remark: '',
});
const rules = reactive<FormRules>({
  companyName: [{ required: true, message: '请输入企业名称' }],
  contact: [{ required: true, message: '请输入联系人姓名' }],
  contactPhone: [
    { required: true, message: '请输入联系电话' },
    { message: '请输入正确的联系电话', validator: FormValidator.validatorTelNumber },
  ],
  remark: [{ required: true, message: '请输入举报投诉的说明' }],
});
const formRef = ref<any>(null);
function handleConfirm() {
  if (!formRef.value) return;
  formRef.value.validate().then(({ valid, errors }: any) => {
    if (valid) {
      createPlatformCooperationApply();
    }
  });
}
async function createPlatformCooperationApply() {
  try {
    let params: API.CreatePlatformCooperationApplyInput = {
      title: CooperateTypeText.Complaint,
      contact: form.contact,
      contactPhone: form.contactPhone,
      applyDescription: form.remark,
      companyName: form.companyName,
      applyType: CooperateApplyTypeEnum.Complaint,
    };
    let res = await cooperationApplyServices.createPlatformCooperationApply(params);
    if (res) {
      await Message.confirm({
        message: '信息已提交,请耐心等待工作人员的联系',
      });
      Taro.navigateBack({
        delta: 1,
      });
    }
  } catch (error) {}
}
</script>
apps/bMiniApp/src/utils/index.ts
New file
@@ -0,0 +1,2 @@
export * from './storage';
export * from './page';
apps/bMiniApp/src/utils/page.ts
New file
@@ -0,0 +1,25 @@
import { TabBarPageRouter } from '@/constants';
import Taro from '@tarojs/taro';
import { useSystemStoreWithOut } from '@/stores/modules/system';
export function goBack(delta = 1) {
  const pages = Taro.getCurrentPages();
  const systemStore = useSystemStoreWithOut();
  if (pages.length > 1) {
    Taro.navigateBack({ delta: delta });
  } else {
    Taro.switchTab({
      url: Object.values(TabBarPageRouter)[systemStore.activeTab],
    });
  }
}
export function goHome() {
  const systemStore = useSystemStoreWithOut();
  systemStore.setTabIndex(0);
  Taro.switchTab({
    url: '/pages/home/index',
  });
}
apps/bMiniApp/src/utils/request/index.ts
New file
@@ -0,0 +1,289 @@
import { type IRequestOptions, Request, type RequestConfig } from 'senior-request';
import { type AxiosRequestConfig, type AxiosError } from 'axios';
import qs from 'qs';
import Taro from '@tarojs/taro';
import { getToken } from '@/utils';
import { tokenIsExpired, Message, SensitiveManage } from '@12333/utils';
import * as accountServices from '@12333/services/api/Account';
import { useUserStoreWithOut } from '@/stores/modules/user';
const RefreshTokenUrl = '/gettokenbyrefreshtoken';
/** 请求白名单,放置一些不需要token的接口(通过设置请求白名单,防止token过期后再请求造成的死循环问题) */
const whiteList = [RefreshTokenUrl];
export function startLoading(showNavigationBarLoading: boolean) {
  if (showNavigationBarLoading) {
    Taro.showNavigationBarLoading();
  } else {
    Taro.showLoading({
      title: '',
      mask: true,
    });
  }
}
export function endLoading() {
  Taro.hideNavigationBarLoading();
  Taro.hideLoading();
}
// 错误处理方案: 错误类型
enum ErrorShowType {
  /**
   * 啥也不干
   */
  SILENT = 0,
  WARN_MESSAGE = 1,
  ERROR_MESSAGE = 2,
  /**
   * 通知报错
   */
  NOTIFICATION = 3,
  /**
   * 重定向
   */
  REDIRECT = 9,
}
// 与后端约定的响应数据格式
interface ResponseStructure {
  success: boolean;
  data: any;
  /**
   * 错误码
   */
  error?: number;
  /**
   * 错误信息
   */
  msg?: string;
  showType?: ErrorShowType;
}
interface ErrorResponse {
  error?: {
    data: any;
    code: number;
    message: string;
  };
}
interface ErrorInfo {
  errorCode?: number;
  errorMessage?: string;
  showType?: ErrorShowType;
  data: any;
}
const AxiosOptions: AxiosRequestConfig = {
  baseURL: process.env.BASE_URL,
  timeout: 10 * 1000,
  headers: {
    Accept: 'application/json, text/plain, */*',
    'Content-Type': 'application/json',
    'X-Requested-With': 'XMLHttpRequest',
  },
  // 数组格式参数序列化
  paramsSerializer: {
    //@ts-ignore
    serialize: (params) => qs.stringify(params, { indices: false }),
  },
  withCredentials: true,
};
const config: RequestConfig<ResponseStructure, IRequestOptions> = {
  ...AxiosOptions,
  errorConfig: {
    // 错误接收及处理
    errorHandler: (error, opts) => {
      console.log('error: ', error);
      if (opts?.skipErrorHandler) throw error;
      if (opts?.customErrorHandler) {
        if (opts?.customErrorHandler(error)) {
          return;
        }
      }
      // 我们的 errorThrower 抛出的错误。
      if (error.name === 'BizError') {
        const errorInfo: ErrorInfo | undefined = (error as any).info;
        if (errorInfo) {
          const { errorMessage, errorCode } = errorInfo;
          switch (errorInfo.showType) {
            case ErrorShowType.SILENT:
              // do nothing
              break;
            case ErrorShowType.WARN_MESSAGE:
              Message.warning(errorMessage);
              break;
            case ErrorShowType.ERROR_MESSAGE:
              Message.error(errorMessage);
              break;
            case ErrorShowType.NOTIFICATION:
              Message.error(errorMessage);
              break;
            case ErrorShowType.REDIRECT:
              // TODO: redirect
              break;
            default:
              Message.error(errorMessage);
          }
        }
      } else if ((error as AxiosError<ResponseStructure, IRequestOptions>).response) {
        // Axios 的错误
        // 请求成功发出且服务器也响应了状态码,但状态代码超出了 2xx 的范围
        handleAxiosResponseError(error as AxiosError<ErrorResponse, IRequestOptions>);
        // Message.errorMessage(`Response status:${(error as AxiosError).response.status}`);
      } else if ((error as AxiosError).request) {
        // 请求已经成功发起,但没有收到响应
        // \`error.request\` 在浏览器中是 XMLHttpRequest 的实例,
        // 而在node.js中是 http.ClientRequest 的实例
        Message.error('服务器无响应,请重试');
      } else {
        // 发送请求时出了点问题
        Message.error('发送请求时出了点问题');
      }
    },
    // 错误抛出
    errorThrower: (res) => {
      const { success, data, error: errorCode, msg, showType } = res;
      if (!success) {
        const error: any = new Error(msg);
        error.name = 'BizError';
        error.info = { errorCode, errorMessage: msg, showType, data };
        throw error; // 抛出自制的错误
      }
    },
  },
  requestInterceptors: [
    [
      (config) => {
        const $config = config;
        const token = getToken();
        const userStore = useUserStoreWithOut();
        const userInfo = userStore.userInfo;
        const { showLoading = true, showNavigationBarLoading, mock } = $config;
        if (mock && process.env.NODE_ENV === 'development') {
          $config.baseURL = 'http://localhost:9527';
        }
        /**
         * 如果是refreshToken这个方法 就直接返回 防止内存泄漏
         */
        if (whiteList.some((url) => $config.url!.toLowerCase().includes(url.toLowerCase()))) {
          return $config;
        }
        if (showLoading) {
          startLoading(showNavigationBarLoading);
        }
        return new Promise((resolve, reject) => {
          if (userInfo && token && $config.withCredentials) {
            if (tokenIsExpired(userInfo)) {
              if (!Request.refreshTokenPending) {
                Request.refreshTokenPending = true;
                // token过期刷新
                useUserStoreWithOut()
                  .getTokenByRefreshToken({
                    refreshToken: userInfo.refreshToken,
                    clientId: userStore.accountInfo?.client_id,
                  })
                  .then((res) => {
                    $config.headers['Authorization'] = 'Bearer ' + res.accessToken;
                    Request.requests.forEach((cb) => cb(res.accessToken));
                    Request.requests = [];
                  })
                  .catch((err) => {
                    Request.requests.forEach((cb) => cb());
                    Request.requests = [];
                    reject(err);
                  })
                  .finally(() => {
                    Request.refreshTokenPending = false;
                  });
              }
              resolve(Request.retryOriginalRequest($config));
            } else {
              $config.headers['Authorization'] = 'Bearer ' + token;
              resolve($config);
            }
          } else {
            resolve($config);
          }
        });
      },
      (error: AxiosError) => {
        endLoading();
        return Promise.reject(error);
      },
    ],
  ],
  responseInterceptors: [
    [
      (response) => {
        const $config = response.config as IRequestOptions;
        const { needNProcess, getResponse = false } = $config;
        endLoading();
        return getResponse
          ? response
          : SensitiveManage.filterSensitiveWord((response.data as any).result);
      },
      (error) => {
        endLoading();
        return Promise.reject(error);
      },
    ],
  ],
};
const ErrorMessageMap = {
  [400]: '请求错误',
  [401]: '未授权,请登录',
  [403]: '拒绝访问',
  [404]: '请求地址出错',
  [408]: '请求超时',
  [500]: '服务器内部错误',
  [501]: '服务未实现',
  [502]: '网关错误',
  [503]: '服务不可用',
  [504]: '网关超时',
  [505]: 'HTTP版本不受支持',
};
function handleAxiosResponseError(error: AxiosError<ErrorResponse, IRequestOptions>) {
  if (error.response.config.url.toLowerCase().includes(RefreshTokenUrl.toLowerCase())) {
    handleLogout();
    return;
  }
  if (error && error.response) {
    let message = ErrorMessageMap[error.response?.status] ?? '请求错误';
    if (error.response.data?.error?.message) {
      message = error.response.data?.error?.message;
    }
    if (error.response?.status === 401) {
      handleLogout();
    }
    Message.error(message);
  }
}
function handleLogout() {
  useUserStoreWithOut().logout();
}
export const request = Request.create(config);
apps/bMiniApp/src/utils/storage/auth.ts
New file
@@ -0,0 +1,71 @@
import { storageLocal } from './storage';
import { useUserStoreWithOut } from '@/stores/modules/user';
import { MatchMakingIdentityEnum } from '@12333/constants';
const StorageKey = {
  USER_INFO_KEY: 'USER__INFO__',
  USER_DETAIL_KEY: 'USER_DETAIL_KEY',
  MatchMakingIdentity_KEY: 'MatchMakingIdentity_KEY',
  LocationCity_KEY: 'LocationCity_KEY',
};
export function getToken() {
  return useUserStoreWithOut().token;
}
export function getRefreshToken() {
  return useUserStoreWithOut().refreshToken;
}
export function getUserInfo() {
  return storageLocal.getItem<API.IdentityModelTokenCacheItem>(StorageKey.USER_INFO_KEY);
}
export function setUserInfo(userInfo: API.IdentityModelTokenCacheItem) {
  return storageLocal.setItem(StorageKey.USER_INFO_KEY, userInfo);
}
export function removeUserInfo() {
  return storageLocal.removeItem(StorageKey.USER_INFO_KEY);
}
export function getUserDetail() {
  return storageLocal.getItem<API.UserInfoV2>(StorageKey.USER_DETAIL_KEY);
}
export function setUserDetail(userDetail: API.UserInfoV2) {
  return storageLocal.setItem(StorageKey.USER_DETAIL_KEY, userDetail);
}
export function removeUserDetail() {
  return storageLocal.removeItem(StorageKey.USER_DETAIL_KEY);
}
export function getMatchMakingIdentity() {
  return storageLocal.getItem<MatchMakingIdentityEnum>(StorageKey.MatchMakingIdentity_KEY);
}
export function setMatchMakingIdentity(matchMakingIdentity: MatchMakingIdentityEnum) {
  return storageLocal.setItem(StorageKey.MatchMakingIdentity_KEY, matchMakingIdentity);
}
export function removeMatchMakingIdentity() {
  return storageLocal.removeItem(StorageKey.MatchMakingIdentity_KEY);
}
type StorageLocation = {
  city: string;
  province: string;
};
export function getStorageLocationCity() {
  return storageLocal.getItem<StorageLocation>(StorageKey.LocationCity_KEY);
}
export function setStorageLocationCity(location: StorageLocation) {
  return storageLocal.setItem(StorageKey.LocationCity_KEY, location);
}
export function removeStorageLocationCity() {
  return storageLocal.removeItem(StorageKey.LocationCity_KEY);
}
apps/bMiniApp/src/utils/storage/index.ts
New file
@@ -0,0 +1,2 @@
export * from './storage';
export * from './auth';
apps/bMiniApp/src/utils/storage/storage.ts
New file
@@ -0,0 +1,39 @@
/* eslint-disable @typescript-eslint/no-explicit-any */
import Taro from '@tarojs/taro';
//sessionStorage operate
class localStorageProxy {
  constructor() {}
  // 存
  public setItem(key: string, value: any): void {
    return Taro.setStorageSync(key, JSON.stringify(value));
  }
  // 取
  public getItem<T = any>(key: string): Nullable<T> {
    try {
      const value = Taro.getStorageSync(key);
      if (value) {
        // Do something with return value
        return JSON.parse(value);
      }
      return null;
    } catch (e) {
      // Do something when catch error
      return null;
    }
  }
  // 删
  public removeItem(key: string) {
    return Taro.removeStorageSync(key);
  }
  // 清空
  public clear() {
    return Taro.clearStorage();
  }
}
export const storageLocal = new localStorageProxy();
apps/bMiniApp/tsconfig.json
New file
@@ -0,0 +1,34 @@
{
  "extends": "../../tsconfig.base.json",
  "compilerOptions": {
    "baseUrl": ".",
    "ignoreDeprecations": "5.0",
    "paths": {
      "@12333/*": ["../../packages/*"],
      "@/*": ["src/*"]
    },
    "composite": true,
    "types": [
      "node",
      "@12333/services/api/typings.d.ts",
      "@12333/services/types.d.ts",
      "@12333/services/globalType.d.ts",
      "@tarojs/components/vue3"
    ]
  },
  "include": [
    "./src/**/*",
    "./types/**/*.d.ts",
    "./components.d.ts",
    "./auto-imports.d.ts",
    "../../types/api.d.ts"
  ],
  "exclude": ["node_modules", "dist"],
  "references": [
    { "path": "../../packages/constants" },
    { "path": "../../packages/services" },
    { "path": "../../packages/hooks" },
    { "path": "../../packages/utils" },
    { "path": "../../packages/components" }
  ]
}
apps/bMiniApp/types/global.d.ts
New file
@@ -0,0 +1,83 @@
/* eslint-disable @typescript-eslint/no-explicit-any */
/// <reference types="@tarojs/taro" />
declare module '*.png'
declare module '*.gif'
declare module '*.jpg'
declare module '*.jpeg'
declare module '*.svg'
declare module '*.css'
declare module '*.less'
declare module '*.scss'
declare module '*.sass'
declare module '*.styl'
declare module '*.vue' {
  import { ComponentOptions } from 'vue'
  const componentOptions: ComponentOptions
  export default componentOptions
}
declare module '*.tsx' {
  import Vue from 'compatible-vue';
  export default Vue;
}
declare global {
  namespace JSX {
    type Element = VNode;
    type ElementClass = Vue;
    interface IntrinsicElements {
      [elem: string]: any;
    }
  }
}
declare namespace NodeJS {
  interface ProcessEnv {
    TARO_ENV: 'weapp' | 'swan' | 'alipay' | 'h5' | 'rn' | 'tt' | 'quickapp' | 'qq' | 'jd'
    NODE_ENV: 'development' | 'production';
    APP_ENV: 'staging';
    BASE_URL: string;
    TEST_BASE_URL: string;
    OSS_URL: string;
    TEST_OSS_URL: string;
    WEMAP_KEY: string;
  }
}
declare module '@tarojs/components' {
  export * from '@tarojs/components/types/index.vue3'
}
declare const CLIENT_ID: string
declare type Nullable<T> = T | null
declare type Recordable<T = unknown> = Record<string, T>
declare type ReadonlyRecordable<T = any> = {
  readonly [key: string]: T
}
declare type Indexable<T = any> = {
  [key: string]: T
}
declare type DeepPartial<T> = {
  [P in keyof T]?: DeepPartial<T[P]>
}
declare interface WeMapModel {
  latitude?: number;
  longitude?: number;
  provinceName?: string;
  cityName?: string;
  countyName?: string;
  provinceCode?: number;
  cityCode?: number;
  countyCode?: number;
  address?: string;
}
declare const uni = Taro
apps/bMiniApp/types/globalType.d.ts
New file
@@ -0,0 +1,8 @@
import type { AxiosRequestConfig } from 'axios';
declare namespace GlobalType {
    interface RequestConfig extends AxiosRequestConfig {}
}
export = GlobalType;
export as namespace GlobalType;
apps/bMiniApp/types/pagination.d.ts
New file
@@ -0,0 +1,43 @@
/**
 * Pagination Start
 */
// declare type PageOutput<T> = {
//   data: T[]
//   pageModel: Pagination
//   objectData: unknown
// }
// declare type Pagination = {
//   rows: number
//   page: number
//   orderInput?: OrderInput[]
//   totalCount?: number
// }
// declare type PageInput = {
//   pageModel: Pagination
// }
// declare enum OrderTypeEnum {
//   Asc = 0,
//   Desc = 1,
// }
// declare type OrderInput = {
//   property: string
//   order: OrderTypeEnum
// }
declare type PageState = {
  hasMore: boolean
  pageInfo: {
    rows: number
    page: number
    total?: number
  }
}
/**
 * Pagination End
 */
apps/bMiniApp/types/shims-vue.d.ts
New file
@@ -0,0 +1,15 @@
import { ComponentObjectPropsOptions as VComponentObjectPropsOptions } from 'vue';
import Taro from '@tarojs/taro'
type Data = {
    [x: string]: unknown;
}
declare global {
    type ComponentObjectPropsOptions<T=Data> = VComponentObjectPropsOptions<T>
    interface Window {
        uni: Taro
    }
}
apps/cMiniApp/project.private.config.json
@@ -6,123 +6,6 @@
        "bigPackageSizeSupport": true,
        "skylineRenderEnable": false
    },
    "condition": {
        "miniprogram": {
            "list": [
                {
                    "name": "联系记录",
                    "pathName": "subpackages/setting/tradeChatRecord/tradeChatRecord",
                    "query": "",
                    "launchMode": "default",
                    "scene": null
                },
                {
                    "name": "authenticationResult",
                    "pathName": "subpackages/authentication/authenticationResult/authenticationResult",
                    "query": "",
                    "launchMode": "default",
                    "scene": null
                },
                {
                    "name": "authenticationJBR",
                    "pathName": "subpackages/authentication/authenticationJBR/authenticationJBR",
                    "query": "",
                    "launchMode": "default",
                    "scene": null
                },
                {
                    "name": "authenticationFaRen",
                    "pathName": "subpackages/authentication/authenticationFaRen/authenticationFaRen",
                    "query": "",
                    "launchMode": "default",
                    "scene": null
                },
                {
                    "name": "authenticationHome",
                    "pathName": "subpackages/authentication/authenticationHome/authenticationHome",
                    "query": "",
                    "launchMode": "default",
                    "scene": null
                },
                {
                    "name": "发布订单",
                    "pathName": "subpackages/order/publishOrder/publishOrder",
                    "query": "orderOperateBtnStatus=1",
                    "launchMode": "default",
                    "scene": null
                },
                {
                    "name": "发布资源",
                    "pathName": "subpackages/resource/publishResource/publishResource",
                    "query": "resourceOperateBtnStatus=1",
                    "launchMode": "default",
                    "scene": null
                },
                {
                    "name": "资源管理",
                    "pathName": "subpackages/setting/resourceManage/resourceManage",
                    "query": "",
                    "launchMode": "default",
                    "scene": null
                },
                {
                    "name": "订单管理",
                    "pathName": "subpackages/setting/orderManage/orderManage",
                    "query": "",
                    "launchMode": "default",
                    "scene": null
                },
                {
                    "name": "资源详情",
                    "pathName": "subpackages/resource/resourceDetail/resourceDetail",
                    "query": "id=dba1fa1d-30e4-22b7-54f8-3a1611763273",
                    "launchMode": "default",
                    "scene": null
                },
                {
                    "name": "订单详情",
                    "pathName": "subpackages/order/orderDetail/orderDetail",
                    "query": "id=4e06ca70-7159-b307-46e5-3a15e8597d2c",
                    "launchMode": "default",
                    "scene": null
                },
                {
                    "name": "切换身份",
                    "pathName": "subpackages/setting/toggleMatchMakingIdentity/toggleMatchMakingIdentity",
                    "query": "",
                    "launchMode": "default",
                    "scene": null
                },
                {
                    "name": "我的主页",
                    "pathName": "subpackages/user/userHomePage/userHomePage",
                    "query": "userId=fe8dca52-5fbd-1088-a2ae-3a147a6a7f42",
                    "launchMode": "default",
                    "scene": null
                },
                {
                    "name": "编辑名片",
                    "pathName": "subpackages/setting/userInfo/userInfo",
                    "query": "",
                    "launchMode": "default",
                    "scene": null
                },
                {
                    "name": "设置",
                    "pathName": "subpackages/setting/setting/setting",
                    "query": "",
                    "launchMode": "default",
                    "scene": null
                },
                {
                    "name": "我的",
                    "pathName": "pages/mine/index",
                    "query": "",
                    "launchMode": "default",
                    "scene": null
                }
            ]
        }
    },
    "condition": {},
    "libVersion": "3.7.3"
}
pnpm-lock.yaml
@@ -119,6 +119,268 @@
        specifier: ^5.2.2
        version: 5.2.2
  apps/bMiniApp:
    dependencies:
      '@12333/components':
        specifier: workspace:^
        version: link:../../packages/components
      '@12333/constants':
        specifier: workspace:*
        version: link:../../packages/constants
      '@12333/hooks':
        specifier: workspace:^
        version: link:../../packages/hooks
      '@12333/services':
        specifier: workspace:^
        version: link:../../packages/services
      '@12333/utils':
        specifier: workspace:^
        version: link:../../packages/utils
      '@babel/runtime':
        specifier: ^7.7.7
        version: 7.7.7
      '@bole-12333/chat-kit':
        specifier: ^1.0.1
        version: 1.0.1(@tencentcloud/chat-uikit-engine@2.0.3)(lodash@4.17.21)(vue@3.5.12)
      '@bole-core/request':
        specifier: ^0.0.1
        version: 0.0.1(axios@1.4.0)
      '@nutui/icons-vue-taro':
        specifier: ^0.0.9
        version: 0.0.9
      '@nutui/nutui-taro':
        specifier: ^4.3.13
        version: 4.3.13(patch_hash=jq3denbtva5gwaaxiatjgbkrsm)(unplugin-vue-components@0.27.4)(vue@3.5.12)
      '@tanstack/vue-query':
        specifier: ^4.35.3
        version: 4.35.3(@vue/composition-api@1.7.2)(vue@3.5.12)
      '@tarojs/components':
        specifier: 3.6.20
        version: 3.6.20(postcss@8.4.19)(react@19.0.0)(vue@3.5.12)
      '@tarojs/helper':
        specifier: 3.6.20
        version: 3.6.20
      '@tarojs/plugin-framework-vue3':
        specifier: 3.6.20
        version: 3.6.20(postcss@8.4.19)(vue@3.5.12)
      '@tarojs/plugin-html':
        specifier: 3.6.20
        version: 3.6.20(postcss@8.4.19)(vue@3.5.12)
      '@tarojs/plugin-http':
        specifier: 3.6.20
        version: 3.6.20(postcss@8.4.19)(vue@3.5.12)
      '@tarojs/plugin-platform-alipay':
        specifier: 3.6.20
        version: 3.6.20(postcss@8.4.19)(react@19.0.0)(vue@3.5.12)
      '@tarojs/plugin-platform-jd':
        specifier: 3.6.20
        version: 3.6.20(postcss@8.4.19)(vue@3.5.12)
      '@tarojs/plugin-platform-qq':
        specifier: 3.6.20
        version: 3.6.20(postcss@8.4.19)(react@19.0.0)(vue@3.5.12)
      '@tarojs/plugin-platform-swan':
        specifier: 3.6.20
        version: 3.6.20(postcss@8.4.19)(react@19.0.0)(vue@3.5.12)
      '@tarojs/plugin-platform-tt':
        specifier: 3.6.20
        version: 3.6.20(postcss@8.4.19)(react@19.0.0)(vue@3.5.12)
      '@tarojs/plugin-platform-weapp':
        specifier: 3.6.20
        version: 3.6.20(postcss@8.4.19)(react@19.0.0)(vue@3.5.12)
      '@tarojs/router':
        specifier: 3.6.20
        version: 3.6.20(postcss@8.4.19)(vue@3.5.12)
      '@tarojs/runtime':
        specifier: 3.6.20
        version: 3.6.20
      '@tarojs/shared':
        specifier: 3.6.20
        version: 3.6.20
      '@tarojs/taro':
        specifier: 3.6.20
        version: 3.6.20(postcss@8.4.19)(vue@3.5.12)
      '@tarojs/taro-h5':
        specifier: 3.6.20
        version: 3.6.20(postcss@8.4.19)(react@19.0.0)(vue@3.5.12)
      '@tencentcloud/chat-uikit-engine':
        specifier: ^2.0.3
        version: 2.0.3(react-native@0.77.0)(react@19.0.0)
      '@tencentcloud/chat-uikit-uniapp':
        specifier: ^2.0.3
        version: 2.0.3(@vue/runtime-dom@3.5.12)(react-native@0.77.0)(react@19.0.0)(vue@3.5.12)(webpack@5.78.0)
      '@tencentcloud/tui-customer-service-plugin':
        specifier: ^2.0.3
        version: 2.0.3(@tencentcloud/tui-core@2.4.0)(@vue/composition-api@1.7.2)(vue@3.5.12)
      '@vant/weapp':
        specifier: ^1.11.1
        version: 1.11.1
      axios:
        specifier: ^1.4.0
        version: 1.4.0
      crypto-js:
        specifier: ^4.1.1
        version: 4.1.1
      dayjs:
        specifier: ^1.11.6
        version: 1.11.6
      js-base64:
        specifier: ^3.7.5
        version: 3.7.5
      lodash:
        specifier: ^4.17.21
        version: 4.17.21
      pinia:
        specifier: ^2.1.6
        version: 2.1.6(@vue/composition-api@1.7.2)(typescript@5.2.2)(vue@3.5.12)
      qs:
        specifier: ^6.11.1
        version: 6.11.1
      senin-mini:
        specifier: ^1.0.10
        version: 1.0.10(@nutui/icons-vue-taro@0.0.9)(@nutui/nutui-taro@4.3.13)(@tanstack/vue-query@4.35.3)(@tarojs/components@3.6.20)(@tarojs/taro@3.6.20)(axios@1.4.0)(dayjs@1.11.6)(lodash@4.17.21)(vue@3.5.12)
      senior-request:
        specifier: ^1.0.3
        version: 1.0.3(axios@1.4.0)
      taro-plugin-pinia:
        specifier: ^1.0.0
        version: 1.0.0
      vconsole:
        specifier: ^3.15.1
        version: 3.15.1
      vue:
        specifier: 3.5.12
        version: 3.5.12(typescript@5.2.2)
      vue-component-type-helpers:
        specifier: ^2.1.10
        version: 2.1.10
    devDependencies:
      '@babel/core':
        specifier: ^7.8.0
        version: 7.8.0
      '@nutui/auto-import-resolver':
        specifier: ^1.0.0
        version: 1.0.0
      '@tarojs/cli':
        specifier: 3.6.20
        version: 3.6.20(postcss@8.4.19)(vue@3.5.12)
      '@tarojs/plugin-mini-ci':
        specifier: ^4.0.7
        version: 4.0.7(miniprogram-ci@1.9.16)
      '@tarojs/plugin-mock':
        specifier: ^0.0.9
        version: 0.0.9
      '@tarojs/plugin-vue-devtools':
        specifier: ^3.6.20
        version: 3.6.20(postcss@8.4.19)(vue@3.5.12)
      '@tarojs/service':
        specifier: ^3.6.20
        version: 3.6.20(postcss@8.4.19)(vue@3.5.12)
      '@tarojs/webpack5-runner':
        specifier: 3.6.20
        version: 3.6.20(@babel/core@7.8.0)(@swc/core@1.3.96)(@vue/compiler-sfc@3.5.12)(cache-loader@4.1.0)(postcss@8.4.19)(prettier@2.7.1)(react@19.0.0)(typescript@5.2.2)(vue@3.5.12)(webpack@5.78.0)
      '@types/crypto-js':
        specifier: ^4.1.1
        version: 4.1.1
      '@types/lodash':
        specifier: ^4.14.198
        version: 4.14.198
      '@types/webpack-env':
        specifier: ^1.13.6
        version: 1.13.6
      '@vue/babel-plugin-jsx':
        specifier: ^1.0.6
        version: 1.0.6(@babel/core@7.8.0)
      '@vue/compiler-sfc':
        specifier: ^3.5.12
        version: 3.5.12
      babel-plugin-import:
        specifier: ^1.13.8
        version: 1.13.8
      babel-plugin-lodash:
        specifier: ^3.3.4
        version: 3.3.4
      babel-plugin-transform-remove-console:
        specifier: ^6.9.4
        version: 6.9.4
      babel-preset-taro:
        specifier: 3.6.20
        version: 3.6.20(@babel/core@7.8.0)
      cache-loader:
        specifier: ^4.1.0
        version: 4.1.0(webpack@5.78.0)
      cross-env:
        specifier: ^7.0.3
        version: 7.0.3
      mockjs:
        specifier: ^1.1.0
        version: 1.1.0
      postcss:
        specifier: ^8.4.19
        version: 8.4.19
      postcss-html:
        specifier: ^1.5.0
        version: 1.5.0
      postcss-loader:
        specifier: ^7.3.3
        version: 7.3.3(postcss@8.4.19)(typescript@5.2.2)(webpack@5.78.0)
      postcss-scss:
        specifier: ^4.0.6
        version: 4.0.6(postcss@8.4.19)
      prettier:
        specifier: ^2.7.1
        version: 2.7.1
      stylelint:
        specifier: ^14.15.0
        version: 14.15.0
      stylelint-config-html:
        specifier: ^1.1.0
        version: 1.1.0(postcss-html@1.5.0)(stylelint@14.15.0)
      stylelint-config-prettier:
        specifier: ^9.0.4
        version: 9.0.4(stylelint@14.15.0)
      stylelint-config-recess-order:
        specifier: ^3.0.0
        version: 3.0.0(stylelint@14.15.0)
      stylelint-config-recommended:
        specifier: ^9.0.0
        version: 9.0.0(stylelint@14.15.0)
      stylelint-config-standard:
        specifier: ^29.0.0
        version: 29.0.0(stylelint@14.15.0)
      stylelint-config-standard-scss:
        specifier: ^6.1.0
        version: 6.1.0(postcss@8.4.19)(stylelint@14.15.0)
      stylelint-order:
        specifier: ^5.0.0
        version: 5.0.0(stylelint@14.15.0)
      stylelint-scss:
        specifier: ^4.3.0
        version: 4.3.0(stylelint@14.15.0)
      taro-plugin-compiler-optimization:
        specifier: ^1.0.4
        version: 1.0.4
      thread-loader:
        specifier: ^4.0.2
        version: 4.0.2(webpack@5.78.0)
      unplugin-auto-import:
        specifier: ^0.16.6
        version: 0.16.6
      unplugin-vue-components:
        specifier: ^0.27.4
        version: 0.27.4(vue@3.5.12)
      vue-eslint-parser:
        specifier: ^9.3.1
        version: 9.3.1(eslint@8.41.0)
      vue-loader:
        specifier: ^17.0.0
        version: 17.0.0(webpack@5.78.0)
      webpack:
        specifier: ^5.78.0
        version: 5.78.0(@swc/core@1.3.96)
      webpack-bundle-analyzer:
        specifier: ^4.7.0
        version: 4.7.0
  apps/cMiniApp:
    dependencies:
      '@12333/components':
@@ -478,7 +740,7 @@
      '@babel/traverse': 7.25.6
      '@babel/types': 7.25.6
      convert-source-map: 1.9.0
      debug: 4.3.7
      debug: 4.4.0
      gensync: 1.0.0-beta.2
      json5: 2.2.3
      lodash: 4.17.21
@@ -541,7 +803,7 @@
    engines: {node: '>=6.9.0'}
    dependencies:
      '@babel/compat-data': 7.25.4
      '@babel/helper-validator-option': 7.24.8
      '@babel/helper-validator-option': 7.25.9
      browserslist: 4.23.3
      lru-cache: 5.1.1
      semver: 6.3.1
@@ -655,7 +917,7 @@
    dependencies:
      '@babel/core': 7.25.2
      '@babel/helper-compilation-targets': 7.25.2
      '@babel/helper-plugin-utils': 7.24.8
      '@babel/helper-plugin-utils': 7.26.5
      debug: 4.4.0
      lodash.debounce: 4.0.8
      resolve: 1.22.8
@@ -669,7 +931,7 @@
    dependencies:
      '@babel/core': 7.8.0
      '@babel/helper-compilation-targets': 7.25.2
      '@babel/helper-plugin-utils': 7.24.8
      '@babel/helper-plugin-utils': 7.26.5
      debug: 4.4.0
      lodash.debounce: 4.0.8
      resolve: 1.22.8
@@ -893,10 +1155,6 @@
    resolution: {integrity: sha512-rR+PBcQ1SMQDDyF6X0wxtG8QyLCgUB0eRAGguqRLfkCA87l7yAP7ehq8SNj96OOGTO8OBV70KhuFYcIkHXOg0w==}
    engines: {node: '>=6.9.0'}
  /@babel/helper-validator-option@7.24.8:
    resolution: {integrity: sha512-xb8t9tD1MHLungh/AIoWYN+gVHaB9kwlu8gffXGSt3FFEIT7RjS+xWbc2vUD1UTZdIpKj/ab3rdqJ7ufngyi2Q==}
    engines: {node: '>=6.9.0'}
  /@babel/helper-validator-option@7.25.9:
    resolution: {integrity: sha512-e/zv1co8pp55dNdEcCynfj9X7nyUKUXoUEwfXqaZt0omVOmDe9oOTdKStH4GmAw6zxMFs50ZayuMfHDKlO7Tfw==}
    engines: {node: '>=6.9.0'}
@@ -960,7 +1218,7 @@
      '@babel/core': ^7.0.0
    dependencies:
      '@babel/core': 7.25.2
      '@babel/helper-plugin-utils': 7.24.8
      '@babel/helper-plugin-utils': 7.26.5
      '@babel/traverse': 7.25.6
    transitivePeerDependencies:
      - supports-color
@@ -972,7 +1230,7 @@
      '@babel/core': ^7.0.0
    dependencies:
      '@babel/core': 7.8.0
      '@babel/helper-plugin-utils': 7.24.8
      '@babel/helper-plugin-utils': 7.26.5
      '@babel/traverse': 7.25.6
    transitivePeerDependencies:
      - supports-color
@@ -984,7 +1242,7 @@
      '@babel/core': ^7.0.0
    dependencies:
      '@babel/core': 7.25.2
      '@babel/helper-plugin-utils': 7.24.8
      '@babel/helper-plugin-utils': 7.26.5
  /@babel/plugin-bugfix-safari-class-field-initializer-scope@7.25.0(@babel/core@7.8.0):
    resolution: {integrity: sha512-Bm4bH2qsX880b/3ziJ8KD711LT7z4u8CFudmjqle65AZj/HNUFhEf90dqYv6O86buWvSBmeQDjv0Tn2aF/bIBA==}
@@ -993,7 +1251,7 @@
      '@babel/core': ^7.0.0
    dependencies:
      '@babel/core': 7.8.0
      '@babel/helper-plugin-utils': 7.24.8
      '@babel/helper-plugin-utils': 7.26.5
  /@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@7.25.0(@babel/core@7.21.4):
    resolution: {integrity: sha512-lXwdNZtTmeVOOFtwM/WDe7yg1PL8sYhRk/XH0FzbR2HDQ0xC+EnQ/JHeoMYSavtU115tnUk0q9CDyq8si+LMAA==}
@@ -1002,7 +1260,7 @@
      '@babel/core': ^7.0.0
    dependencies:
      '@babel/core': 7.21.4
      '@babel/helper-plugin-utils': 7.24.8
      '@babel/helper-plugin-utils': 7.26.5
    dev: true
  /@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@7.25.0(@babel/core@7.25.2):
@@ -1012,7 +1270,7 @@
      '@babel/core': ^7.0.0
    dependencies:
      '@babel/core': 7.25.2
      '@babel/helper-plugin-utils': 7.24.8
      '@babel/helper-plugin-utils': 7.26.5
  /@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@7.25.0(@babel/core@7.8.0):
    resolution: {integrity: sha512-lXwdNZtTmeVOOFtwM/WDe7yg1PL8sYhRk/XH0FzbR2HDQ0xC+EnQ/JHeoMYSavtU115tnUk0q9CDyq8si+LMAA==}
@@ -1021,7 +1279,7 @@
      '@babel/core': ^7.0.0
    dependencies:
      '@babel/core': 7.8.0
      '@babel/helper-plugin-utils': 7.24.8
      '@babel/helper-plugin-utils': 7.26.5
  /@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining@7.24.7(@babel/core@7.21.4):
    resolution: {integrity: sha512-+izXIbke1T33mY4MSNnrqhPXDz01WYhEf3yF5NbnUtkiNnm+XBZJl3kNfoK6NKmYlz/D07+l2GWVK/QfDkNCuQ==}
@@ -1030,7 +1288,7 @@
      '@babel/core': ^7.13.0
    dependencies:
      '@babel/core': 7.21.4
      '@babel/helper-plugin-utils': 7.24.8
      '@babel/helper-plugin-utils': 7.26.5
      '@babel/helper-skip-transparent-expression-wrappers': 7.24.7
      '@babel/plugin-transform-optional-chaining': 7.24.8(@babel/core@7.21.4)
    transitivePeerDependencies:
@@ -1044,7 +1302,7 @@
      '@babel/core': ^7.13.0
    dependencies:
      '@babel/core': 7.25.2
      '@babel/helper-plugin-utils': 7.24.8
      '@babel/helper-plugin-utils': 7.26.5
      '@babel/helper-skip-transparent-expression-wrappers': 7.24.7
      '@babel/plugin-transform-optional-chaining': 7.24.8(@babel/core@7.25.2)
    transitivePeerDependencies:
@@ -1057,7 +1315,7 @@
      '@babel/core': ^7.13.0
    dependencies:
      '@babel/core': 7.8.0
      '@babel/helper-plugin-utils': 7.24.8
      '@babel/helper-plugin-utils': 7.26.5
      '@babel/helper-skip-transparent-expression-wrappers': 7.24.7
      '@babel/plugin-transform-optional-chaining': 7.24.8(@babel/core@7.8.0)
    transitivePeerDependencies:
@@ -1070,7 +1328,7 @@
      '@babel/core': ^7.0.0
    dependencies:
      '@babel/core': 7.25.2
      '@babel/helper-plugin-utils': 7.24.8
      '@babel/helper-plugin-utils': 7.26.5
      '@babel/traverse': 7.25.6
    transitivePeerDependencies:
      - supports-color
@@ -1082,7 +1340,7 @@
      '@babel/core': ^7.0.0
    dependencies:
      '@babel/core': 7.8.0
      '@babel/helper-plugin-utils': 7.24.8
      '@babel/helper-plugin-utils': 7.26.5
      '@babel/traverse': 7.25.6
    transitivePeerDependencies:
      - supports-color
@@ -1096,7 +1354,7 @@
    dependencies:
      '@babel/core': 7.21.4
      '@babel/helper-environment-visitor': 7.24.7
      '@babel/helper-plugin-utils': 7.24.8
      '@babel/helper-plugin-utils': 7.26.5
      '@babel/helper-remap-async-to-generator': 7.25.0(@babel/core@7.21.4)
      '@babel/plugin-syntax-async-generators': 7.8.4(@babel/core@7.21.4)
    transitivePeerDependencies:
@@ -1112,7 +1370,7 @@
    dependencies:
      '@babel/core': 7.8.0
      '@babel/helper-environment-visitor': 7.24.7
      '@babel/helper-plugin-utils': 7.24.8
      '@babel/helper-plugin-utils': 7.26.5
      '@babel/helper-remap-async-to-generator': 7.25.0(@babel/core@7.8.0)
      '@babel/plugin-syntax-async-generators': 7.8.4(@babel/core@7.8.0)
    transitivePeerDependencies:
@@ -1128,7 +1386,7 @@
    dependencies:
      '@babel/core': 7.21.4
      '@babel/helper-create-class-features-plugin': 7.25.4(@babel/core@7.21.4)
      '@babel/helper-plugin-utils': 7.24.8
      '@babel/helper-plugin-utils': 7.26.5
    transitivePeerDependencies:
      - supports-color
    dev: true
@@ -1142,7 +1400,7 @@
    dependencies:
      '@babel/core': 7.8.0
      '@babel/helper-create-class-features-plugin': 7.25.4(@babel/core@7.8.0)
      '@babel/helper-plugin-utils': 7.24.8
      '@babel/helper-plugin-utils': 7.26.5
    transitivePeerDependencies:
      - supports-color
    dev: true
@@ -1186,7 +1444,7 @@
    dependencies:
      '@babel/core': 7.25.2
      '@babel/helper-create-class-features-plugin': 7.25.4(@babel/core@7.25.2)
      '@babel/helper-plugin-utils': 7.24.8
      '@babel/helper-plugin-utils': 7.26.5
      '@babel/plugin-syntax-decorators': 7.24.7(@babel/core@7.25.2)
    transitivePeerDependencies:
      - supports-color
@@ -1199,7 +1457,7 @@
    dependencies:
      '@babel/core': 7.8.0
      '@babel/helper-create-class-features-plugin': 7.25.4(@babel/core@7.8.0)
      '@babel/helper-plugin-utils': 7.24.8
      '@babel/helper-plugin-utils': 7.26.5
      '@babel/plugin-syntax-decorators': 7.24.7(@babel/core@7.8.0)
    transitivePeerDependencies:
      - supports-color
@@ -1246,7 +1504,7 @@
      '@babel/core': ^7.0.0-0
    dependencies:
      '@babel/core': 7.8.0
      '@babel/helper-plugin-utils': 7.24.8
      '@babel/helper-plugin-utils': 7.26.5
      '@babel/plugin-syntax-export-default-from': 7.24.7(@babel/core@7.8.0)
  /@babel/plugin-proposal-export-namespace-from@7.18.9(@babel/core@7.21.4):
@@ -1318,7 +1576,7 @@
      '@babel/core': ^7.0.0-0
    dependencies:
      '@babel/core': 7.21.4
      '@babel/helper-plugin-utils': 7.24.8
      '@babel/helper-plugin-utils': 7.26.5
      '@babel/plugin-syntax-nullish-coalescing-operator': 7.8.3(@babel/core@7.21.4)
    dev: true
@@ -1330,7 +1588,7 @@
      '@babel/core': ^7.0.0-0
    dependencies:
      '@babel/core': 7.8.0
      '@babel/helper-plugin-utils': 7.24.8
      '@babel/helper-plugin-utils': 7.26.5
      '@babel/plugin-syntax-nullish-coalescing-operator': 7.8.3(@babel/core@7.8.0)
    dev: true
@@ -1356,7 +1614,7 @@
      '@babel/compat-data': 7.25.4
      '@babel/core': 7.21.4
      '@babel/helper-compilation-targets': 7.25.2
      '@babel/helper-plugin-utils': 7.24.8
      '@babel/helper-plugin-utils': 7.26.5
      '@babel/plugin-syntax-object-rest-spread': 7.8.3(@babel/core@7.21.4)
      '@babel/plugin-transform-parameters': 7.24.7(@babel/core@7.21.4)
    dev: true
@@ -1371,7 +1629,7 @@
      '@babel/compat-data': 7.25.4
      '@babel/core': 7.25.2
      '@babel/helper-compilation-targets': 7.25.2
      '@babel/helper-plugin-utils': 7.24.8
      '@babel/helper-plugin-utils': 7.26.5
      '@babel/plugin-syntax-object-rest-spread': 7.8.3(@babel/core@7.25.2)
      '@babel/plugin-transform-parameters': 7.24.7(@babel/core@7.25.2)
@@ -1385,7 +1643,7 @@
      '@babel/compat-data': 7.25.4
      '@babel/core': 7.8.0
      '@babel/helper-compilation-targets': 7.25.2
      '@babel/helper-plugin-utils': 7.24.8
      '@babel/helper-plugin-utils': 7.26.5
      '@babel/plugin-syntax-object-rest-spread': 7.8.3(@babel/core@7.8.0)
      '@babel/plugin-transform-parameters': 7.24.7(@babel/core@7.8.0)
    dev: true
@@ -1398,7 +1656,7 @@
      '@babel/core': ^7.0.0-0
    dependencies:
      '@babel/core': 7.21.4
      '@babel/helper-plugin-utils': 7.24.8
      '@babel/helper-plugin-utils': 7.26.5
      '@babel/plugin-syntax-optional-catch-binding': 7.8.3(@babel/core@7.21.4)
    dev: true
@@ -1410,7 +1668,7 @@
      '@babel/core': ^7.0.0-0
    dependencies:
      '@babel/core': 7.8.0
      '@babel/helper-plugin-utils': 7.24.8
      '@babel/helper-plugin-utils': 7.26.5
      '@babel/plugin-syntax-optional-catch-binding': 7.8.3(@babel/core@7.8.0)
    dev: true
@@ -1422,7 +1680,7 @@
      '@babel/core': ^7.0.0-0
    dependencies:
      '@babel/core': 7.21.4
      '@babel/helper-plugin-utils': 7.24.8
      '@babel/helper-plugin-utils': 7.26.5
      '@babel/helper-skip-transparent-expression-wrappers': 7.24.7
      '@babel/plugin-syntax-optional-chaining': 7.8.3(@babel/core@7.21.4)
    transitivePeerDependencies:
@@ -1437,7 +1695,7 @@
      '@babel/core': ^7.0.0-0
    dependencies:
      '@babel/core': 7.8.0
      '@babel/helper-plugin-utils': 7.24.8
      '@babel/helper-plugin-utils': 7.26.5
      '@babel/helper-skip-transparent-expression-wrappers': 7.24.7
      '@babel/plugin-syntax-optional-chaining': 7.8.3(@babel/core@7.8.0)
    transitivePeerDependencies:
@@ -1530,7 +1788,7 @@
      '@babel/core': ^7.0.0-0
    dependencies:
      '@babel/core': 7.21.4
      '@babel/helper-plugin-utils': 7.24.8
      '@babel/helper-plugin-utils': 7.26.5
    dev: true
  /@babel/plugin-syntax-async-generators@7.8.4(@babel/core@7.25.2):
@@ -1539,7 +1797,7 @@
      '@babel/core': ^7.0.0-0
    dependencies:
      '@babel/core': 7.25.2
      '@babel/helper-plugin-utils': 7.24.8
      '@babel/helper-plugin-utils': 7.26.5
  /@babel/plugin-syntax-async-generators@7.8.4(@babel/core@7.8.0):
    resolution: {integrity: sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==}
@@ -1547,7 +1805,7 @@
      '@babel/core': ^7.0.0-0
    dependencies:
      '@babel/core': 7.8.0
      '@babel/helper-plugin-utils': 7.24.8
      '@babel/helper-plugin-utils': 7.26.5
  /@babel/plugin-syntax-bigint@7.8.3(@babel/core@7.8.0):
    resolution: {integrity: sha512-wnTnFlG+YxQm3vDxpGE57Pj0srRU4sHE/mDkt1qv2YJJSeUAec2ma4WLUnUPeKjyrfntVwe/N6dCXpU+zL3Npg==}
@@ -1564,7 +1822,7 @@
      '@babel/core': ^7.0.0-0
    dependencies:
      '@babel/core': 7.21.4
      '@babel/helper-plugin-utils': 7.24.8
      '@babel/helper-plugin-utils': 7.26.5
    dev: true
  /@babel/plugin-syntax-class-properties@7.12.13(@babel/core@7.25.2):
@@ -1573,7 +1831,7 @@
      '@babel/core': ^7.0.0-0
    dependencies:
      '@babel/core': 7.25.2
      '@babel/helper-plugin-utils': 7.24.8
      '@babel/helper-plugin-utils': 7.26.5
  /@babel/plugin-syntax-class-properties@7.12.13(@babel/core@7.8.0):
    resolution: {integrity: sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==}
@@ -1581,7 +1839,7 @@
      '@babel/core': ^7.0.0-0
    dependencies:
      '@babel/core': 7.8.0
      '@babel/helper-plugin-utils': 7.24.8
      '@babel/helper-plugin-utils': 7.26.5
  /@babel/plugin-syntax-class-static-block@7.14.5(@babel/core@7.21.4):
    resolution: {integrity: sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw==}
@@ -1590,7 +1848,7 @@
      '@babel/core': ^7.0.0-0
    dependencies:
      '@babel/core': 7.21.4
      '@babel/helper-plugin-utils': 7.24.8
      '@babel/helper-plugin-utils': 7.26.5
    dev: true
  /@babel/plugin-syntax-class-static-block@7.14.5(@babel/core@7.25.2):
@@ -1600,7 +1858,7 @@
      '@babel/core': ^7.0.0-0
    dependencies:
      '@babel/core': 7.25.2
      '@babel/helper-plugin-utils': 7.24.8
      '@babel/helper-plugin-utils': 7.26.5
  /@babel/plugin-syntax-class-static-block@7.14.5(@babel/core@7.8.0):
    resolution: {integrity: sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw==}
@@ -1609,7 +1867,7 @@
      '@babel/core': ^7.0.0-0
    dependencies:
      '@babel/core': 7.8.0
      '@babel/helper-plugin-utils': 7.24.8
      '@babel/helper-plugin-utils': 7.26.5
  /@babel/plugin-syntax-decorators@7.24.7(@babel/core@7.21.4):
    resolution: {integrity: sha512-Ui4uLJJrRV1lb38zg1yYTmRKmiZLiftDEvZN2iq3kd9kUFU+PttmzTbAFC2ucRk/XJmtek6G23gPsuZbhrT8fQ==}
@@ -1618,7 +1876,7 @@
      '@babel/core': ^7.0.0-0
    dependencies:
      '@babel/core': 7.21.4
      '@babel/helper-plugin-utils': 7.24.8
      '@babel/helper-plugin-utils': 7.26.5
    dev: true
  /@babel/plugin-syntax-decorators@7.24.7(@babel/core@7.25.2):
@@ -1628,7 +1886,7 @@
      '@babel/core': ^7.0.0-0
    dependencies:
      '@babel/core': 7.25.2
      '@babel/helper-plugin-utils': 7.24.8
      '@babel/helper-plugin-utils': 7.26.5
  /@babel/plugin-syntax-decorators@7.24.7(@babel/core@7.8.0):
    resolution: {integrity: sha512-Ui4uLJJrRV1lb38zg1yYTmRKmiZLiftDEvZN2iq3kd9kUFU+PttmzTbAFC2ucRk/XJmtek6G23gPsuZbhrT8fQ==}
@@ -1637,7 +1895,7 @@
      '@babel/core': ^7.0.0-0
    dependencies:
      '@babel/core': 7.8.0
      '@babel/helper-plugin-utils': 7.24.8
      '@babel/helper-plugin-utils': 7.26.5
    dev: true
  /@babel/plugin-syntax-do-expressions@7.22.5(@babel/core@7.21.4):
@@ -1656,7 +1914,7 @@
      '@babel/core': ^7.0.0-0
    dependencies:
      '@babel/core': 7.21.4
      '@babel/helper-plugin-utils': 7.24.8
      '@babel/helper-plugin-utils': 7.26.5
    dev: true
  /@babel/plugin-syntax-dynamic-import@7.8.3(@babel/core@7.25.2):
@@ -1665,7 +1923,7 @@
      '@babel/core': ^7.0.0-0
    dependencies:
      '@babel/core': 7.25.2
      '@babel/helper-plugin-utils': 7.24.8
      '@babel/helper-plugin-utils': 7.26.5
  /@babel/plugin-syntax-dynamic-import@7.8.3(@babel/core@7.8.0):
    resolution: {integrity: sha512-5gdGbFon+PszYzqs83S3E5mpi7/y/8M9eC90MRTZfduQOYW76ig6SOSPNe41IG5LoP3FGBn2N0RjVDSQiS94kQ==}
@@ -1673,7 +1931,7 @@
      '@babel/core': ^7.0.0-0
    dependencies:
      '@babel/core': 7.8.0
      '@babel/helper-plugin-utils': 7.24.8
      '@babel/helper-plugin-utils': 7.26.5
  /@babel/plugin-syntax-export-default-from@7.24.7(@babel/core@7.21.4):
    resolution: {integrity: sha512-bTPz4/635WQ9WhwsyPdxUJDVpsi/X9BMmy/8Rf/UAlOO4jSql4CxUCjWI5PiM+jG+c4LVPTScoTw80geFj9+Bw==}
@@ -1682,7 +1940,7 @@
      '@babel/core': ^7.0.0-0
    dependencies:
      '@babel/core': 7.21.4
      '@babel/helper-plugin-utils': 7.24.8
      '@babel/helper-plugin-utils': 7.26.5
    dev: true
  /@babel/plugin-syntax-export-default-from@7.24.7(@babel/core@7.8.0):
@@ -1692,7 +1950,7 @@
      '@babel/core': ^7.0.0-0
    dependencies:
      '@babel/core': 7.8.0
      '@babel/helper-plugin-utils': 7.24.8
      '@babel/helper-plugin-utils': 7.26.5
  /@babel/plugin-syntax-export-namespace-from@7.8.3(@babel/core@7.21.4):
    resolution: {integrity: sha512-MXf5laXo6c1IbEbegDmzGPwGNTsHZmEy6QGznu5Sh2UCWvueywb2ee+CCE4zQiZstxU9BMoQO9i6zUFSY0Kj0Q==}
@@ -1700,7 +1958,7 @@
      '@babel/core': ^7.0.0-0
    dependencies:
      '@babel/core': 7.21.4
      '@babel/helper-plugin-utils': 7.24.8
      '@babel/helper-plugin-utils': 7.26.5
    dev: true
  /@babel/plugin-syntax-export-namespace-from@7.8.3(@babel/core@7.25.2):
@@ -1709,7 +1967,7 @@
      '@babel/core': ^7.0.0-0
    dependencies:
      '@babel/core': 7.25.2
      '@babel/helper-plugin-utils': 7.24.8
      '@babel/helper-plugin-utils': 7.26.5
  /@babel/plugin-syntax-export-namespace-from@7.8.3(@babel/core@7.8.0):
    resolution: {integrity: sha512-MXf5laXo6c1IbEbegDmzGPwGNTsHZmEy6QGznu5Sh2UCWvueywb2ee+CCE4zQiZstxU9BMoQO9i6zUFSY0Kj0Q==}
@@ -1717,17 +1975,7 @@
      '@babel/core': ^7.0.0-0
    dependencies:
      '@babel/core': 7.8.0
      '@babel/helper-plugin-utils': 7.24.8
  /@babel/plugin-syntax-flow@7.24.7(@babel/core@7.8.0):
    resolution: {integrity: sha512-9G8GYT/dxn/D1IIKOUBmGX0mnmj46mGH9NnZyJLwtCpgh5f7D2VbuKodb+2s9m1Yavh1s7ASQN8lf0eqrb1LTw==}
    engines: {node: '>=6.9.0'}
    peerDependencies:
      '@babel/core': ^7.0.0-0
    dependencies:
      '@babel/core': 7.8.0
      '@babel/helper-plugin-utils': 7.24.8
    dev: true
      '@babel/helper-plugin-utils': 7.26.5
  /@babel/plugin-syntax-flow@7.26.0(@babel/core@7.25.2):
    resolution: {integrity: sha512-B+O2DnPc0iG+YXFqOxv2WNuNU97ToWjOomUQ78DouOENWUaM5sVrmet9mcomUGQFwpJd//gvUagXBSdzO1fRKg==}
@@ -1747,7 +1995,6 @@
    dependencies:
      '@babel/core': 7.8.0
      '@babel/helper-plugin-utils': 7.26.5
    dev: false
  /@babel/plugin-syntax-function-bind@7.22.5(@babel/core@7.21.4):
    resolution: {integrity: sha512-Sjy7XIhHF9L++0Mk/3Y4H4439cjI//wc/jE8Ly3+qGPkTUYYEhe4rzMv/JnyZpekfOBL22X6DAq42I7GM/3KzA==}
@@ -1776,7 +2023,7 @@
      '@babel/core': ^7.0.0-0
    dependencies:
      '@babel/core': 7.21.4
      '@babel/helper-plugin-utils': 7.24.8
      '@babel/helper-plugin-utils': 7.26.5
    dev: true
  /@babel/plugin-syntax-import-assertions@7.25.6(@babel/core@7.25.2):
@@ -1786,7 +2033,7 @@
      '@babel/core': ^7.0.0-0
    dependencies:
      '@babel/core': 7.25.2
      '@babel/helper-plugin-utils': 7.24.8
      '@babel/helper-plugin-utils': 7.26.5
  /@babel/plugin-syntax-import-assertions@7.25.6(@babel/core@7.8.0):
    resolution: {integrity: sha512-aABl0jHw9bZ2karQ/uUD6XP4u0SG22SJrOHFoL6XB1R7dTovOP4TzTlsxOYC5yQ1pdscVK2JTUnF6QL3ARoAiQ==}
@@ -1795,7 +2042,7 @@
      '@babel/core': ^7.0.0-0
    dependencies:
      '@babel/core': 7.8.0
      '@babel/helper-plugin-utils': 7.24.8
      '@babel/helper-plugin-utils': 7.26.5
  /@babel/plugin-syntax-import-attributes@7.25.6(@babel/core@7.25.2):
    resolution: {integrity: sha512-sXaDXaJN9SNLymBdlWFA+bjzBhFD617ZaFiY13dGt7TVslVvVgA6fkZOP7Ki3IGElC45lwHdOTrCtKZGVAWeLQ==}
@@ -1804,7 +2051,7 @@
      '@babel/core': ^7.0.0-0
    dependencies:
      '@babel/core': 7.25.2
      '@babel/helper-plugin-utils': 7.24.8
      '@babel/helper-plugin-utils': 7.26.5
  /@babel/plugin-syntax-import-attributes@7.25.6(@babel/core@7.8.0):
    resolution: {integrity: sha512-sXaDXaJN9SNLymBdlWFA+bjzBhFD617ZaFiY13dGt7TVslVvVgA6fkZOP7Ki3IGElC45lwHdOTrCtKZGVAWeLQ==}
@@ -1813,7 +2060,7 @@
      '@babel/core': ^7.0.0-0
    dependencies:
      '@babel/core': 7.8.0
      '@babel/helper-plugin-utils': 7.24.8
      '@babel/helper-plugin-utils': 7.26.5
  /@babel/plugin-syntax-import-meta@7.10.4(@babel/core@7.25.2):
    resolution: {integrity: sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==}
@@ -1821,7 +2068,7 @@
      '@babel/core': ^7.0.0-0
    dependencies:
      '@babel/core': 7.25.2
      '@babel/helper-plugin-utils': 7.24.8
      '@babel/helper-plugin-utils': 7.26.5
  /@babel/plugin-syntax-import-meta@7.10.4(@babel/core@7.8.0):
    resolution: {integrity: sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==}
@@ -1829,7 +2076,7 @@
      '@babel/core': ^7.0.0-0
    dependencies:
      '@babel/core': 7.8.0
      '@babel/helper-plugin-utils': 7.24.8
      '@babel/helper-plugin-utils': 7.26.5
  /@babel/plugin-syntax-json-strings@7.8.3(@babel/core@7.21.4):
    resolution: {integrity: sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==}
@@ -1837,7 +2084,7 @@
      '@babel/core': ^7.0.0-0
    dependencies:
      '@babel/core': 7.21.4
      '@babel/helper-plugin-utils': 7.24.8
      '@babel/helper-plugin-utils': 7.26.5
    dev: true
  /@babel/plugin-syntax-json-strings@7.8.3(@babel/core@7.25.2):
@@ -1846,7 +2093,7 @@
      '@babel/core': ^7.0.0-0
    dependencies:
      '@babel/core': 7.25.2
      '@babel/helper-plugin-utils': 7.24.8
      '@babel/helper-plugin-utils': 7.26.5
  /@babel/plugin-syntax-json-strings@7.8.3(@babel/core@7.8.0):
    resolution: {integrity: sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==}
@@ -1854,7 +2101,7 @@
      '@babel/core': ^7.0.0-0
    dependencies:
      '@babel/core': 7.8.0
      '@babel/helper-plugin-utils': 7.24.8
      '@babel/helper-plugin-utils': 7.26.5
  /@babel/plugin-syntax-jsx@7.24.7(@babel/core@7.25.2):
    resolution: {integrity: sha512-6ddciUPe/mpMnOKv/U+RSd2vvVy+Yw/JfBB0ZHYjEZt9NLHmCUylNYlsbqCCS1Bffjlb0fCwC9Vqz+sBz6PsiQ==}
@@ -1872,7 +2119,7 @@
      '@babel/core': ^7.0.0-0
    dependencies:
      '@babel/core': 7.8.0
      '@babel/helper-plugin-utils': 7.24.8
      '@babel/helper-plugin-utils': 7.26.5
  /@babel/plugin-syntax-logical-assignment-operators@7.10.4(@babel/core@7.21.4):
    resolution: {integrity: sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==}
@@ -1880,7 +2127,7 @@
      '@babel/core': ^7.0.0-0
    dependencies:
      '@babel/core': 7.21.4
      '@babel/helper-plugin-utils': 7.24.8
      '@babel/helper-plugin-utils': 7.26.5
    dev: true
  /@babel/plugin-syntax-logical-assignment-operators@7.10.4(@babel/core@7.25.2):
@@ -1889,7 +2136,7 @@
      '@babel/core': ^7.0.0-0
    dependencies:
      '@babel/core': 7.25.2
      '@babel/helper-plugin-utils': 7.24.8
      '@babel/helper-plugin-utils': 7.26.5
  /@babel/plugin-syntax-logical-assignment-operators@7.10.4(@babel/core@7.8.0):
    resolution: {integrity: sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==}
@@ -1897,7 +2144,7 @@
      '@babel/core': ^7.0.0-0
    dependencies:
      '@babel/core': 7.8.0
      '@babel/helper-plugin-utils': 7.24.8
      '@babel/helper-plugin-utils': 7.26.5
  /@babel/plugin-syntax-nullish-coalescing-operator@7.8.3(@babel/core@7.21.4):
    resolution: {integrity: sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==}
@@ -1905,7 +2152,7 @@
      '@babel/core': ^7.0.0-0
    dependencies:
      '@babel/core': 7.21.4
      '@babel/helper-plugin-utils': 7.24.8
      '@babel/helper-plugin-utils': 7.26.5
    dev: true
  /@babel/plugin-syntax-nullish-coalescing-operator@7.8.3(@babel/core@7.25.2):
@@ -1914,7 +2161,7 @@
      '@babel/core': ^7.0.0-0
    dependencies:
      '@babel/core': 7.25.2
      '@babel/helper-plugin-utils': 7.24.8
      '@babel/helper-plugin-utils': 7.26.5
  /@babel/plugin-syntax-nullish-coalescing-operator@7.8.3(@babel/core@7.8.0):
    resolution: {integrity: sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==}
@@ -1922,7 +2169,7 @@
      '@babel/core': ^7.0.0-0
    dependencies:
      '@babel/core': 7.8.0
      '@babel/helper-plugin-utils': 7.24.8
      '@babel/helper-plugin-utils': 7.26.5
  /@babel/plugin-syntax-numeric-separator@7.10.4(@babel/core@7.21.4):
    resolution: {integrity: sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==}
@@ -1930,7 +2177,7 @@
      '@babel/core': ^7.0.0-0
    dependencies:
      '@babel/core': 7.21.4
      '@babel/helper-plugin-utils': 7.24.8
      '@babel/helper-plugin-utils': 7.26.5
    dev: true
  /@babel/plugin-syntax-numeric-separator@7.10.4(@babel/core@7.25.2):
@@ -1939,7 +2186,7 @@
      '@babel/core': ^7.0.0-0
    dependencies:
      '@babel/core': 7.25.2
      '@babel/helper-plugin-utils': 7.24.8
      '@babel/helper-plugin-utils': 7.26.5
  /@babel/plugin-syntax-numeric-separator@7.10.4(@babel/core@7.8.0):
    resolution: {integrity: sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==}
@@ -1947,7 +2194,7 @@
      '@babel/core': ^7.0.0-0
    dependencies:
      '@babel/core': 7.8.0
      '@babel/helper-plugin-utils': 7.24.8
      '@babel/helper-plugin-utils': 7.26.5
  /@babel/plugin-syntax-object-rest-spread@7.8.3(@babel/core@7.21.4):
    resolution: {integrity: sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==}
@@ -1955,7 +2202,7 @@
      '@babel/core': ^7.0.0-0
    dependencies:
      '@babel/core': 7.21.4
      '@babel/helper-plugin-utils': 7.24.8
      '@babel/helper-plugin-utils': 7.26.5
    dev: true
  /@babel/plugin-syntax-object-rest-spread@7.8.3(@babel/core@7.25.2):
@@ -1964,7 +2211,7 @@
      '@babel/core': ^7.0.0-0
    dependencies:
      '@babel/core': 7.25.2
      '@babel/helper-plugin-utils': 7.24.8
      '@babel/helper-plugin-utils': 7.26.5
  /@babel/plugin-syntax-object-rest-spread@7.8.3(@babel/core@7.8.0):
    resolution: {integrity: sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==}
@@ -1972,7 +2219,7 @@
      '@babel/core': ^7.0.0-0
    dependencies:
      '@babel/core': 7.8.0
      '@babel/helper-plugin-utils': 7.24.8
      '@babel/helper-plugin-utils': 7.26.5
  /@babel/plugin-syntax-optional-catch-binding@7.8.3(@babel/core@7.21.4):
    resolution: {integrity: sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==}
@@ -1980,7 +2227,7 @@
      '@babel/core': ^7.0.0-0
    dependencies:
      '@babel/core': 7.21.4
      '@babel/helper-plugin-utils': 7.24.8
      '@babel/helper-plugin-utils': 7.26.5
    dev: true
  /@babel/plugin-syntax-optional-catch-binding@7.8.3(@babel/core@7.25.2):
@@ -1989,7 +2236,7 @@
      '@babel/core': ^7.0.0-0
    dependencies:
      '@babel/core': 7.25.2
      '@babel/helper-plugin-utils': 7.24.8
      '@babel/helper-plugin-utils': 7.26.5
  /@babel/plugin-syntax-optional-catch-binding@7.8.3(@babel/core@7.8.0):
    resolution: {integrity: sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==}
@@ -1997,7 +2244,7 @@
      '@babel/core': ^7.0.0-0
    dependencies:
      '@babel/core': 7.8.0
      '@babel/helper-plugin-utils': 7.24.8
      '@babel/helper-plugin-utils': 7.26.5
  /@babel/plugin-syntax-optional-chaining@7.8.3(@babel/core@7.21.4):
    resolution: {integrity: sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==}
@@ -2005,7 +2252,7 @@
      '@babel/core': ^7.0.0-0
    dependencies:
      '@babel/core': 7.21.4
      '@babel/helper-plugin-utils': 7.24.8
      '@babel/helper-plugin-utils': 7.26.5
    dev: true
  /@babel/plugin-syntax-optional-chaining@7.8.3(@babel/core@7.25.2):
@@ -2014,7 +2261,7 @@
      '@babel/core': ^7.0.0-0
    dependencies:
      '@babel/core': 7.25.2
      '@babel/helper-plugin-utils': 7.24.8
      '@babel/helper-plugin-utils': 7.26.5
  /@babel/plugin-syntax-optional-chaining@7.8.3(@babel/core@7.8.0):
    resolution: {integrity: sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==}
@@ -2022,7 +2269,7 @@
      '@babel/core': ^7.0.0-0
    dependencies:
      '@babel/core': 7.8.0
      '@babel/helper-plugin-utils': 7.24.8
      '@babel/helper-plugin-utils': 7.26.5
  /@babel/plugin-syntax-pipeline-operator@7.22.5(@babel/core@7.21.4):
    resolution: {integrity: sha512-7yuGXd+h8gpR14FnPDTTCd5TfC/1B9njNZJT29GJ7UFF/WVbzkZy7728DynrENqgImqj5xyPTQAo8si9n3QVJQ==}
@@ -2041,7 +2288,7 @@
      '@babel/core': ^7.0.0-0
    dependencies:
      '@babel/core': 7.21.4
      '@babel/helper-plugin-utils': 7.24.8
      '@babel/helper-plugin-utils': 7.26.5
    dev: true
  /@babel/plugin-syntax-private-property-in-object@7.14.5(@babel/core@7.25.2):
@@ -2051,7 +2298,7 @@
      '@babel/core': ^7.0.0-0
    dependencies:
      '@babel/core': 7.25.2
      '@babel/helper-plugin-utils': 7.24.8
      '@babel/helper-plugin-utils': 7.26.5
  /@babel/plugin-syntax-private-property-in-object@7.14.5(@babel/core@7.8.0):
    resolution: {integrity: sha512-0wVnp9dxJ72ZUJDV27ZfbSj6iHLoytYZmh3rFcxNnvsJF3ktkzLDZPy/mA17HGsaQT3/DQsWYX1f1QGWkCoVUg==}
@@ -2060,7 +2307,7 @@
      '@babel/core': ^7.0.0-0
    dependencies:
      '@babel/core': 7.8.0
      '@babel/helper-plugin-utils': 7.24.8
      '@babel/helper-plugin-utils': 7.26.5
  /@babel/plugin-syntax-throw-expressions@7.22.5(@babel/core@7.21.4):
    resolution: {integrity: sha512-oCyfA7rDVcQIydA7ZOmnHCQTzz5JvG9arY++Z+ASL/q5q+mJLblaRNHoK6ggV54X2c14wCK/lQi7z1DujmEmZA==}
@@ -2079,7 +2326,7 @@
      '@babel/core': ^7.0.0-0
    dependencies:
      '@babel/core': 7.21.4
      '@babel/helper-plugin-utils': 7.24.8
      '@babel/helper-plugin-utils': 7.26.5
    dev: true
  /@babel/plugin-syntax-top-level-await@7.14.5(@babel/core@7.25.2):
@@ -2089,7 +2336,7 @@
      '@babel/core': ^7.0.0-0
    dependencies:
      '@babel/core': 7.25.2
      '@babel/helper-plugin-utils': 7.24.8
      '@babel/helper-plugin-utils': 7.26.5
  /@babel/plugin-syntax-top-level-await@7.14.5(@babel/core@7.8.0):
    resolution: {integrity: sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==}
@@ -2098,7 +2345,7 @@
      '@babel/core': ^7.0.0-0
    dependencies:
      '@babel/core': 7.8.0
      '@babel/helper-plugin-utils': 7.24.8
      '@babel/helper-plugin-utils': 7.26.5
  /@babel/plugin-syntax-typescript@7.25.4(@babel/core@7.21.4):
    resolution: {integrity: sha512-uMOCoHVU52BsSWxPOMVv5qKRdeSlPuImUCB2dlPuBSU+W2/ROE7/Zg8F2Kepbk+8yBa68LlRKxO+xgEVWorsDg==}
@@ -2107,7 +2354,7 @@
      '@babel/core': ^7.0.0-0
    dependencies:
      '@babel/core': 7.21.4
      '@babel/helper-plugin-utils': 7.24.8
      '@babel/helper-plugin-utils': 7.26.5
    dev: true
  /@babel/plugin-syntax-typescript@7.25.4(@babel/core@7.25.2):
@@ -2117,7 +2364,7 @@
      '@babel/core': ^7.0.0-0
    dependencies:
      '@babel/core': 7.25.2
      '@babel/helper-plugin-utils': 7.24.8
      '@babel/helper-plugin-utils': 7.26.5
  /@babel/plugin-syntax-typescript@7.25.4(@babel/core@7.8.0):
    resolution: {integrity: sha512-uMOCoHVU52BsSWxPOMVv5qKRdeSlPuImUCB2dlPuBSU+W2/ROE7/Zg8F2Kepbk+8yBa68LlRKxO+xgEVWorsDg==}
@@ -2126,7 +2373,7 @@
      '@babel/core': ^7.0.0-0
    dependencies:
      '@babel/core': 7.8.0
      '@babel/helper-plugin-utils': 7.24.8
      '@babel/helper-plugin-utils': 7.26.5
  /@babel/plugin-syntax-unicode-sets-regex@7.18.6(@babel/core@7.25.2):
    resolution: {integrity: sha512-727YkEAPwSIQTv5im8QHz3upqp92JTWhidIC81Tdx4VJYIte/VndKf1qKrfnnhPLiPghStWfvC/iFaMCQu7Nqg==}
@@ -2136,7 +2383,7 @@
    dependencies:
      '@babel/core': 7.25.2
      '@babel/helper-create-regexp-features-plugin': 7.25.2(@babel/core@7.25.2)
      '@babel/helper-plugin-utils': 7.24.8
      '@babel/helper-plugin-utils': 7.26.5
  /@babel/plugin-syntax-unicode-sets-regex@7.18.6(@babel/core@7.8.0):
    resolution: {integrity: sha512-727YkEAPwSIQTv5im8QHz3upqp92JTWhidIC81Tdx4VJYIte/VndKf1qKrfnnhPLiPghStWfvC/iFaMCQu7Nqg==}
@@ -2146,7 +2393,7 @@
    dependencies:
      '@babel/core': 7.8.0
      '@babel/helper-create-regexp-features-plugin': 7.25.2(@babel/core@7.8.0)
      '@babel/helper-plugin-utils': 7.24.8
      '@babel/helper-plugin-utils': 7.26.5
  /@babel/plugin-transform-arrow-functions@7.24.7(@babel/core@7.21.4):
    resolution: {integrity: sha512-Dt9LQs6iEY++gXUwY03DNFat5C2NbO48jj+j/bSAz6b3HgPs39qcPiYt77fDObIcFwj3/C2ICX9YMwGflUoSHQ==}
@@ -2155,7 +2402,7 @@
      '@babel/core': ^7.0.0-0
    dependencies:
      '@babel/core': 7.21.4
      '@babel/helper-plugin-utils': 7.24.8
      '@babel/helper-plugin-utils': 7.26.5
    dev: true
  /@babel/plugin-transform-arrow-functions@7.24.7(@babel/core@7.25.2):
@@ -2165,7 +2412,7 @@
      '@babel/core': ^7.0.0-0
    dependencies:
      '@babel/core': 7.25.2
      '@babel/helper-plugin-utils': 7.24.8
      '@babel/helper-plugin-utils': 7.26.5
  /@babel/plugin-transform-arrow-functions@7.24.7(@babel/core@7.8.0):
    resolution: {integrity: sha512-Dt9LQs6iEY++gXUwY03DNFat5C2NbO48jj+j/bSAz6b3HgPs39qcPiYt77fDObIcFwj3/C2ICX9YMwGflUoSHQ==}
@@ -2174,7 +2421,7 @@
      '@babel/core': ^7.0.0-0
    dependencies:
      '@babel/core': 7.8.0
      '@babel/helper-plugin-utils': 7.24.8
      '@babel/helper-plugin-utils': 7.26.5
  /@babel/plugin-transform-async-generator-functions@7.25.4(@babel/core@7.25.2):
    resolution: {integrity: sha512-jz8cV2XDDTqjKPwVPJBIjORVEmSGYhdRa8e5k5+vN+uwcjSrSxUaebBRa4ko1jqNF2uxyg8G6XYk30Jv285xzg==}
@@ -2183,7 +2430,7 @@
      '@babel/core': ^7.0.0-0
    dependencies:
      '@babel/core': 7.25.2
      '@babel/helper-plugin-utils': 7.24.8
      '@babel/helper-plugin-utils': 7.26.5
      '@babel/helper-remap-async-to-generator': 7.25.0(@babel/core@7.25.2)
      '@babel/plugin-syntax-async-generators': 7.8.4(@babel/core@7.25.2)
      '@babel/traverse': 7.25.6
@@ -2197,7 +2444,7 @@
      '@babel/core': ^7.0.0-0
    dependencies:
      '@babel/core': 7.8.0
      '@babel/helper-plugin-utils': 7.24.8
      '@babel/helper-plugin-utils': 7.26.5
      '@babel/helper-remap-async-to-generator': 7.25.0(@babel/core@7.8.0)
      '@babel/plugin-syntax-async-generators': 7.8.4(@babel/core@7.8.0)
      '@babel/traverse': 7.25.6
@@ -2212,7 +2459,7 @@
    dependencies:
      '@babel/core': 7.21.4
      '@babel/helper-module-imports': 7.24.7
      '@babel/helper-plugin-utils': 7.24.8
      '@babel/helper-plugin-utils': 7.26.5
      '@babel/helper-remap-async-to-generator': 7.25.0(@babel/core@7.21.4)
    transitivePeerDependencies:
      - supports-color
@@ -2226,7 +2473,7 @@
    dependencies:
      '@babel/core': 7.25.2
      '@babel/helper-module-imports': 7.24.7
      '@babel/helper-plugin-utils': 7.24.8
      '@babel/helper-plugin-utils': 7.26.5
      '@babel/helper-remap-async-to-generator': 7.25.0(@babel/core@7.25.2)
    transitivePeerDependencies:
      - supports-color
@@ -2239,7 +2486,7 @@
    dependencies:
      '@babel/core': 7.8.0
      '@babel/helper-module-imports': 7.24.7
      '@babel/helper-plugin-utils': 7.24.8
      '@babel/helper-plugin-utils': 7.26.5
      '@babel/helper-remap-async-to-generator': 7.25.0(@babel/core@7.8.0)
    transitivePeerDependencies:
      - supports-color
@@ -2251,7 +2498,7 @@
      '@babel/core': ^7.0.0-0
    dependencies:
      '@babel/core': 7.21.4
      '@babel/helper-plugin-utils': 7.24.8
      '@babel/helper-plugin-utils': 7.26.5
    dev: true
  /@babel/plugin-transform-block-scoped-functions@7.24.7(@babel/core@7.25.2):
@@ -2261,7 +2508,7 @@
      '@babel/core': ^7.0.0-0
    dependencies:
      '@babel/core': 7.25.2
      '@babel/helper-plugin-utils': 7.24.8
      '@babel/helper-plugin-utils': 7.26.5
  /@babel/plugin-transform-block-scoped-functions@7.24.7(@babel/core@7.8.0):
    resolution: {integrity: sha512-yO7RAz6EsVQDaBH18IDJcMB1HnrUn2FJ/Jslc/WtPPWcjhpUJXU/rjbwmluzp7v/ZzWcEhTMXELnnsz8djWDwQ==}
@@ -2270,7 +2517,7 @@
      '@babel/core': ^7.0.0-0
    dependencies:
      '@babel/core': 7.8.0
      '@babel/helper-plugin-utils': 7.24.8
      '@babel/helper-plugin-utils': 7.26.5
  /@babel/plugin-transform-block-scoping@7.25.0(@babel/core@7.21.4):
    resolution: {integrity: sha512-yBQjYoOjXlFv9nlXb3f1casSHOZkWr29NX+zChVanLg5Nc157CrbEX9D7hxxtTpuFy7Q0YzmmWfJxzvps4kXrQ==}
@@ -2279,7 +2526,7 @@
      '@babel/core': ^7.0.0-0
    dependencies:
      '@babel/core': 7.21.4
      '@babel/helper-plugin-utils': 7.24.8
      '@babel/helper-plugin-utils': 7.26.5
    dev: true
  /@babel/plugin-transform-block-scoping@7.25.0(@babel/core@7.25.2):
@@ -2289,7 +2536,7 @@
      '@babel/core': ^7.0.0-0
    dependencies:
      '@babel/core': 7.25.2
      '@babel/helper-plugin-utils': 7.24.8
      '@babel/helper-plugin-utils': 7.26.5
  /@babel/plugin-transform-block-scoping@7.25.0(@babel/core@7.8.0):
    resolution: {integrity: sha512-yBQjYoOjXlFv9nlXb3f1casSHOZkWr29NX+zChVanLg5Nc157CrbEX9D7hxxtTpuFy7Q0YzmmWfJxzvps4kXrQ==}
@@ -2298,7 +2545,7 @@
      '@babel/core': ^7.0.0-0
    dependencies:
      '@babel/core': 7.8.0
      '@babel/helper-plugin-utils': 7.24.8
      '@babel/helper-plugin-utils': 7.26.5
  /@babel/plugin-transform-class-properties@7.25.4(@babel/core@7.25.2):
    resolution: {integrity: sha512-nZeZHyCWPfjkdU5pA/uHiTaDAFUEqkpzf1YoQT2NeSynCGYq9rxfyI3XpQbfx/a0hSnFH6TGlEXvae5Vi7GD8g==}
@@ -2308,7 +2555,7 @@
    dependencies:
      '@babel/core': 7.25.2
      '@babel/helper-create-class-features-plugin': 7.25.4(@babel/core@7.25.2)
      '@babel/helper-plugin-utils': 7.24.8
      '@babel/helper-plugin-utils': 7.26.5
    transitivePeerDependencies:
      - supports-color
@@ -2320,7 +2567,7 @@
    dependencies:
      '@babel/core': 7.8.0
      '@babel/helper-create-class-features-plugin': 7.25.4(@babel/core@7.8.0)
      '@babel/helper-plugin-utils': 7.24.8
      '@babel/helper-plugin-utils': 7.26.5
    transitivePeerDependencies:
      - supports-color
@@ -2332,7 +2579,7 @@
    dependencies:
      '@babel/core': 7.25.2
      '@babel/helper-create-class-features-plugin': 7.25.4(@babel/core@7.25.2)
      '@babel/helper-plugin-utils': 7.24.8
      '@babel/helper-plugin-utils': 7.26.5
      '@babel/plugin-syntax-class-static-block': 7.14.5(@babel/core@7.25.2)
    transitivePeerDependencies:
      - supports-color
@@ -2345,7 +2592,7 @@
    dependencies:
      '@babel/core': 7.8.0
      '@babel/helper-create-class-features-plugin': 7.25.4(@babel/core@7.8.0)
      '@babel/helper-plugin-utils': 7.24.8
      '@babel/helper-plugin-utils': 7.26.5
      '@babel/plugin-syntax-class-static-block': 7.14.5(@babel/core@7.8.0)
    transitivePeerDependencies:
      - supports-color
@@ -2359,7 +2606,7 @@
      '@babel/core': 7.21.4
      '@babel/helper-annotate-as-pure': 7.24.7
      '@babel/helper-compilation-targets': 7.25.2
      '@babel/helper-plugin-utils': 7.24.8
      '@babel/helper-plugin-utils': 7.26.5
      '@babel/helper-replace-supers': 7.25.0(@babel/core@7.21.4)
      '@babel/traverse': 7.25.6
      globals: 11.12.0
@@ -2376,7 +2623,7 @@
      '@babel/core': 7.25.2
      '@babel/helper-annotate-as-pure': 7.24.7
      '@babel/helper-compilation-targets': 7.25.2
      '@babel/helper-plugin-utils': 7.24.8
      '@babel/helper-plugin-utils': 7.26.5
      '@babel/helper-replace-supers': 7.25.0(@babel/core@7.25.2)
      '@babel/traverse': 7.25.6
      globals: 11.12.0
@@ -2392,7 +2639,7 @@
      '@babel/core': 7.8.0
      '@babel/helper-annotate-as-pure': 7.24.7
      '@babel/helper-compilation-targets': 7.25.2
      '@babel/helper-plugin-utils': 7.24.8
      '@babel/helper-plugin-utils': 7.26.5
      '@babel/helper-replace-supers': 7.25.0(@babel/core@7.8.0)
      '@babel/traverse': 7.25.6
      globals: 11.12.0
@@ -2406,7 +2653,7 @@
      '@babel/core': ^7.0.0-0
    dependencies:
      '@babel/core': 7.21.4
      '@babel/helper-plugin-utils': 7.24.8
      '@babel/helper-plugin-utils': 7.26.5
      '@babel/template': 7.25.0
    dev: true
@@ -2417,7 +2664,7 @@
      '@babel/core': ^7.0.0-0
    dependencies:
      '@babel/core': 7.25.2
      '@babel/helper-plugin-utils': 7.24.8
      '@babel/helper-plugin-utils': 7.26.5
      '@babel/template': 7.25.0
  /@babel/plugin-transform-computed-properties@7.24.7(@babel/core@7.8.0):
@@ -2427,7 +2674,7 @@
      '@babel/core': ^7.0.0-0
    dependencies:
      '@babel/core': 7.8.0
      '@babel/helper-plugin-utils': 7.24.8
      '@babel/helper-plugin-utils': 7.26.5
      '@babel/template': 7.25.0
  /@babel/plugin-transform-destructuring@7.24.8(@babel/core@7.21.4):
@@ -2437,7 +2684,7 @@
      '@babel/core': ^7.0.0-0
    dependencies:
      '@babel/core': 7.21.4
      '@babel/helper-plugin-utils': 7.24.8
      '@babel/helper-plugin-utils': 7.26.5
    dev: true
  /@babel/plugin-transform-destructuring@7.24.8(@babel/core@7.25.2):
@@ -2447,7 +2694,7 @@
      '@babel/core': ^7.0.0-0
    dependencies:
      '@babel/core': 7.25.2
      '@babel/helper-plugin-utils': 7.24.8
      '@babel/helper-plugin-utils': 7.26.5
  /@babel/plugin-transform-destructuring@7.24.8(@babel/core@7.8.0):
    resolution: {integrity: sha512-36e87mfY8TnRxc7yc6M9g9gOB7rKgSahqkIKwLpz4Ppk2+zC2Cy1is0uwtuSG6AE4zlTOUa+7JGz9jCJGLqQFQ==}
@@ -2456,7 +2703,7 @@
      '@babel/core': ^7.0.0-0
    dependencies:
      '@babel/core': 7.8.0
      '@babel/helper-plugin-utils': 7.24.8
      '@babel/helper-plugin-utils': 7.26.5
  /@babel/plugin-transform-dotall-regex@7.24.7(@babel/core@7.21.4):
    resolution: {integrity: sha512-ZOA3W+1RRTSWvyqcMJDLqbchh7U4NRGqwRfFSVbOLS/ePIP4vHB5e8T8eXcuqyN1QkgKyj5wuW0lcS85v4CrSw==}
@@ -2466,7 +2713,7 @@
    dependencies:
      '@babel/core': 7.21.4
      '@babel/helper-create-regexp-features-plugin': 7.25.2(@babel/core@7.21.4)
      '@babel/helper-plugin-utils': 7.24.8
      '@babel/helper-plugin-utils': 7.26.5
    dev: true
  /@babel/plugin-transform-dotall-regex@7.24.7(@babel/core@7.25.2):
@@ -2477,7 +2724,7 @@
    dependencies:
      '@babel/core': 7.25.2
      '@babel/helper-create-regexp-features-plugin': 7.25.2(@babel/core@7.25.2)
      '@babel/helper-plugin-utils': 7.24.8
      '@babel/helper-plugin-utils': 7.26.5
  /@babel/plugin-transform-dotall-regex@7.24.7(@babel/core@7.8.0):
    resolution: {integrity: sha512-ZOA3W+1RRTSWvyqcMJDLqbchh7U4NRGqwRfFSVbOLS/ePIP4vHB5e8T8eXcuqyN1QkgKyj5wuW0lcS85v4CrSw==}
@@ -2487,7 +2734,7 @@
    dependencies:
      '@babel/core': 7.8.0
      '@babel/helper-create-regexp-features-plugin': 7.25.2(@babel/core@7.8.0)
      '@babel/helper-plugin-utils': 7.24.8
      '@babel/helper-plugin-utils': 7.26.5
  /@babel/plugin-transform-duplicate-keys@7.24.7(@babel/core@7.21.4):
    resolution: {integrity: sha512-JdYfXyCRihAe46jUIliuL2/s0x0wObgwwiGxw/UbgJBr20gQBThrokO4nYKgWkD7uBaqM7+9x5TU7NkExZJyzw==}
@@ -2496,7 +2743,7 @@
      '@babel/core': ^7.0.0-0
    dependencies:
      '@babel/core': 7.21.4
      '@babel/helper-plugin-utils': 7.24.8
      '@babel/helper-plugin-utils': 7.26.5
    dev: true
  /@babel/plugin-transform-duplicate-keys@7.24.7(@babel/core@7.25.2):
@@ -2506,7 +2753,7 @@
      '@babel/core': ^7.0.0-0
    dependencies:
      '@babel/core': 7.25.2
      '@babel/helper-plugin-utils': 7.24.8
      '@babel/helper-plugin-utils': 7.26.5
  /@babel/plugin-transform-duplicate-keys@7.24.7(@babel/core@7.8.0):
    resolution: {integrity: sha512-JdYfXyCRihAe46jUIliuL2/s0x0wObgwwiGxw/UbgJBr20gQBThrokO4nYKgWkD7uBaqM7+9x5TU7NkExZJyzw==}
@@ -2515,7 +2762,7 @@
      '@babel/core': ^7.0.0-0
    dependencies:
      '@babel/core': 7.8.0
      '@babel/helper-plugin-utils': 7.24.8
      '@babel/helper-plugin-utils': 7.26.5
  /@babel/plugin-transform-duplicate-named-capturing-groups-regex@7.25.0(@babel/core@7.25.2):
    resolution: {integrity: sha512-YLpb4LlYSc3sCUa35un84poXoraOiQucUTTu8X1j18JV+gNa8E0nyUf/CjZ171IRGr4jEguF+vzJU66QZhn29g==}
@@ -2525,7 +2772,7 @@
    dependencies:
      '@babel/core': 7.25.2
      '@babel/helper-create-regexp-features-plugin': 7.25.2(@babel/core@7.25.2)
      '@babel/helper-plugin-utils': 7.24.8
      '@babel/helper-plugin-utils': 7.26.5
  /@babel/plugin-transform-duplicate-named-capturing-groups-regex@7.25.0(@babel/core@7.8.0):
    resolution: {integrity: sha512-YLpb4LlYSc3sCUa35un84poXoraOiQucUTTu8X1j18JV+gNa8E0nyUf/CjZ171IRGr4jEguF+vzJU66QZhn29g==}
@@ -2535,7 +2782,7 @@
    dependencies:
      '@babel/core': 7.8.0
      '@babel/helper-create-regexp-features-plugin': 7.25.2(@babel/core@7.8.0)
      '@babel/helper-plugin-utils': 7.24.8
      '@babel/helper-plugin-utils': 7.26.5
  /@babel/plugin-transform-dynamic-import@7.24.7(@babel/core@7.25.2):
    resolution: {integrity: sha512-sc3X26PhZQDb3JhORmakcbvkeInvxz+A8oda99lj7J60QRuPZvNAk9wQlTBS1ZynelDrDmTU4pw1tyc5d5ZMUg==}
@@ -2544,7 +2791,7 @@
      '@babel/core': ^7.0.0-0
    dependencies:
      '@babel/core': 7.25.2
      '@babel/helper-plugin-utils': 7.24.8
      '@babel/helper-plugin-utils': 7.26.5
      '@babel/plugin-syntax-dynamic-import': 7.8.3(@babel/core@7.25.2)
  /@babel/plugin-transform-dynamic-import@7.24.7(@babel/core@7.8.0):
@@ -2554,7 +2801,7 @@
      '@babel/core': ^7.0.0-0
    dependencies:
      '@babel/core': 7.8.0
      '@babel/helper-plugin-utils': 7.24.8
      '@babel/helper-plugin-utils': 7.26.5
      '@babel/plugin-syntax-dynamic-import': 7.8.3(@babel/core@7.8.0)
  /@babel/plugin-transform-exponentiation-operator@7.24.7(@babel/core@7.21.4):
@@ -2565,7 +2812,7 @@
    dependencies:
      '@babel/core': 7.21.4
      '@babel/helper-builder-binary-assignment-operator-visitor': 7.24.7
      '@babel/helper-plugin-utils': 7.24.8
      '@babel/helper-plugin-utils': 7.26.5
    transitivePeerDependencies:
      - supports-color
    dev: true
@@ -2578,7 +2825,7 @@
    dependencies:
      '@babel/core': 7.25.2
      '@babel/helper-builder-binary-assignment-operator-visitor': 7.24.7
      '@babel/helper-plugin-utils': 7.24.8
      '@babel/helper-plugin-utils': 7.26.5
    transitivePeerDependencies:
      - supports-color
@@ -2590,7 +2837,7 @@
    dependencies:
      '@babel/core': 7.8.0
      '@babel/helper-builder-binary-assignment-operator-visitor': 7.24.7
      '@babel/helper-plugin-utils': 7.24.8
      '@babel/helper-plugin-utils': 7.26.5
    transitivePeerDependencies:
      - supports-color
@@ -2601,7 +2848,7 @@
      '@babel/core': ^7.0.0-0
    dependencies:
      '@babel/core': 7.25.2
      '@babel/helper-plugin-utils': 7.24.8
      '@babel/helper-plugin-utils': 7.26.5
      '@babel/plugin-syntax-export-namespace-from': 7.8.3(@babel/core@7.25.2)
  /@babel/plugin-transform-export-namespace-from@7.24.7(@babel/core@7.8.0):
@@ -2611,19 +2858,8 @@
      '@babel/core': ^7.0.0-0
    dependencies:
      '@babel/core': 7.8.0
      '@babel/helper-plugin-utils': 7.24.8
      '@babel/helper-plugin-utils': 7.26.5
      '@babel/plugin-syntax-export-namespace-from': 7.8.3(@babel/core@7.8.0)
  /@babel/plugin-transform-flow-strip-types@7.25.2(@babel/core@7.8.0):
    resolution: {integrity: sha512-InBZ0O8tew5V0K6cHcQ+wgxlrjOw1W4wDXLkOTjLRD8GYhTSkxTVBtdy3MMtvYBrbAWa1Qm3hNoTc1620Yj+Mg==}
    engines: {node: '>=6.9.0'}
    peerDependencies:
      '@babel/core': ^7.0.0-0
    dependencies:
      '@babel/core': 7.8.0
      '@babel/helper-plugin-utils': 7.24.8
      '@babel/plugin-syntax-flow': 7.24.7(@babel/core@7.8.0)
    dev: true
  /@babel/plugin-transform-flow-strip-types@7.26.5(@babel/core@7.25.2):
    resolution: {integrity: sha512-eGK26RsbIkYUns3Y8qKl362juDDYK+wEdPGHGrhzUl6CewZFo55VZ7hg+CyMFU4dd5QQakBN86nBMpRsFpRvbQ==}
@@ -2645,7 +2881,6 @@
      '@babel/core': 7.8.0
      '@babel/helper-plugin-utils': 7.26.5
      '@babel/plugin-syntax-flow': 7.26.0(@babel/core@7.8.0)
    dev: false
  /@babel/plugin-transform-for-of@7.24.7(@babel/core@7.21.4):
    resolution: {integrity: sha512-wo9ogrDG1ITTTBsy46oGiN1dS9A7MROBTcYsfS8DtsImMkHk9JXJ3EWQM6X2SUw4x80uGPlwj0o00Uoc6nEE3g==}
@@ -2654,7 +2889,7 @@
      '@babel/core': ^7.0.0-0
    dependencies:
      '@babel/core': 7.21.4
      '@babel/helper-plugin-utils': 7.24.8
      '@babel/helper-plugin-utils': 7.26.5
      '@babel/helper-skip-transparent-expression-wrappers': 7.24.7
    transitivePeerDependencies:
      - supports-color
@@ -2667,7 +2902,7 @@
      '@babel/core': ^7.0.0-0
    dependencies:
      '@babel/core': 7.25.2
      '@babel/helper-plugin-utils': 7.24.8
      '@babel/helper-plugin-utils': 7.26.5
      '@babel/helper-skip-transparent-expression-wrappers': 7.24.7
    transitivePeerDependencies:
      - supports-color
@@ -2679,7 +2914,7 @@
      '@babel/core': ^7.0.0-0
    dependencies:
      '@babel/core': 7.8.0
      '@babel/helper-plugin-utils': 7.24.8
      '@babel/helper-plugin-utils': 7.26.5
      '@babel/helper-skip-transparent-expression-wrappers': 7.24.7
    transitivePeerDependencies:
      - supports-color
@@ -2692,7 +2927,7 @@
    dependencies:
      '@babel/core': 7.21.4
      '@babel/helper-compilation-targets': 7.25.2
      '@babel/helper-plugin-utils': 7.24.8
      '@babel/helper-plugin-utils': 7.26.5
      '@babel/traverse': 7.25.6
    transitivePeerDependencies:
      - supports-color
@@ -2706,7 +2941,7 @@
    dependencies:
      '@babel/core': 7.25.2
      '@babel/helper-compilation-targets': 7.25.2
      '@babel/helper-plugin-utils': 7.24.8
      '@babel/helper-plugin-utils': 7.26.5
      '@babel/traverse': 7.25.6
    transitivePeerDependencies:
      - supports-color
@@ -2719,7 +2954,7 @@
    dependencies:
      '@babel/core': 7.8.0
      '@babel/helper-compilation-targets': 7.25.2
      '@babel/helper-plugin-utils': 7.24.8
      '@babel/helper-plugin-utils': 7.26.5
      '@babel/traverse': 7.25.6
    transitivePeerDependencies:
      - supports-color
@@ -2731,7 +2966,7 @@
      '@babel/core': ^7.0.0-0
    dependencies:
      '@babel/core': 7.25.2
      '@babel/helper-plugin-utils': 7.24.8
      '@babel/helper-plugin-utils': 7.26.5
      '@babel/plugin-syntax-json-strings': 7.8.3(@babel/core@7.25.2)
  /@babel/plugin-transform-json-strings@7.24.7(@babel/core@7.8.0):
@@ -2741,7 +2976,7 @@
      '@babel/core': ^7.0.0-0
    dependencies:
      '@babel/core': 7.8.0
      '@babel/helper-plugin-utils': 7.24.8
      '@babel/helper-plugin-utils': 7.26.5
      '@babel/plugin-syntax-json-strings': 7.8.3(@babel/core@7.8.0)
  /@babel/plugin-transform-literals@7.25.2(@babel/core@7.21.4):
@@ -2751,7 +2986,7 @@
      '@babel/core': ^7.0.0-0
    dependencies:
      '@babel/core': 7.21.4
      '@babel/helper-plugin-utils': 7.24.8
      '@babel/helper-plugin-utils': 7.26.5
    dev: true
  /@babel/plugin-transform-literals@7.25.2(@babel/core@7.25.2):
@@ -2761,7 +2996,7 @@
      '@babel/core': ^7.0.0-0
    dependencies:
      '@babel/core': 7.25.2
      '@babel/helper-plugin-utils': 7.24.8
      '@babel/helper-plugin-utils': 7.26.5
  /@babel/plugin-transform-literals@7.25.2(@babel/core@7.8.0):
    resolution: {integrity: sha512-HQI+HcTbm9ur3Z2DkO+jgESMAMcYLuN/A7NRw9juzxAezN9AvqvUTnpKP/9kkYANz6u7dFlAyOu44ejuGySlfw==}
@@ -2770,7 +3005,7 @@
      '@babel/core': ^7.0.0-0
    dependencies:
      '@babel/core': 7.8.0
      '@babel/helper-plugin-utils': 7.24.8
      '@babel/helper-plugin-utils': 7.26.5
  /@babel/plugin-transform-logical-assignment-operators@7.24.7(@babel/core@7.25.2):
    resolution: {integrity: sha512-4D2tpwlQ1odXmTEIFWy9ELJcZHqrStlzK/dAOWYyxX3zT0iXQB6banjgeOJQXzEc4S0E0a5A+hahxPaEFYftsw==}
@@ -2779,7 +3014,7 @@
      '@babel/core': ^7.0.0-0
    dependencies:
      '@babel/core': 7.25.2
      '@babel/helper-plugin-utils': 7.24.8
      '@babel/helper-plugin-utils': 7.26.5
      '@babel/plugin-syntax-logical-assignment-operators': 7.10.4(@babel/core@7.25.2)
  /@babel/plugin-transform-logical-assignment-operators@7.24.7(@babel/core@7.8.0):
@@ -2789,7 +3024,7 @@
      '@babel/core': ^7.0.0-0
    dependencies:
      '@babel/core': 7.8.0
      '@babel/helper-plugin-utils': 7.24.8
      '@babel/helper-plugin-utils': 7.26.5
      '@babel/plugin-syntax-logical-assignment-operators': 7.10.4(@babel/core@7.8.0)
  /@babel/plugin-transform-member-expression-literals@7.24.7(@babel/core@7.21.4):
@@ -2799,7 +3034,7 @@
      '@babel/core': ^7.0.0-0
    dependencies:
      '@babel/core': 7.21.4
      '@babel/helper-plugin-utils': 7.24.8
      '@babel/helper-plugin-utils': 7.26.5
    dev: true
  /@babel/plugin-transform-member-expression-literals@7.24.7(@babel/core@7.25.2):
@@ -2809,7 +3044,7 @@
      '@babel/core': ^7.0.0-0
    dependencies:
      '@babel/core': 7.25.2
      '@babel/helper-plugin-utils': 7.24.8
      '@babel/helper-plugin-utils': 7.26.5
  /@babel/plugin-transform-member-expression-literals@7.24.7(@babel/core@7.8.0):
    resolution: {integrity: sha512-T/hRC1uqrzXMKLQ6UCwMT85S3EvqaBXDGf0FaMf4446Qx9vKwlghvee0+uuZcDUCZU5RuNi4781UQ7R308zzBw==}
@@ -2818,7 +3053,7 @@
      '@babel/core': ^7.0.0-0
    dependencies:
      '@babel/core': 7.8.0
      '@babel/helper-plugin-utils': 7.24.8
      '@babel/helper-plugin-utils': 7.26.5
  /@babel/plugin-transform-modules-amd@7.24.7(@babel/core@7.21.4):
    resolution: {integrity: sha512-9+pB1qxV3vs/8Hdmz/CulFB8w2tuu6EB94JZFsjdqxQokwGa9Unap7Bo2gGBGIvPmDIVvQrom7r5m/TCDMURhg==}
@@ -2828,7 +3063,7 @@
    dependencies:
      '@babel/core': 7.21.4
      '@babel/helper-module-transforms': 7.25.2(@babel/core@7.21.4)
      '@babel/helper-plugin-utils': 7.24.8
      '@babel/helper-plugin-utils': 7.26.5
    transitivePeerDependencies:
      - supports-color
    dev: true
@@ -2841,7 +3076,7 @@
    dependencies:
      '@babel/core': 7.25.2
      '@babel/helper-module-transforms': 7.25.2(@babel/core@7.25.2)
      '@babel/helper-plugin-utils': 7.24.8
      '@babel/helper-plugin-utils': 7.26.5
    transitivePeerDependencies:
      - supports-color
@@ -2853,7 +3088,7 @@
    dependencies:
      '@babel/core': 7.8.0
      '@babel/helper-module-transforms': 7.25.2(@babel/core@7.8.0)
      '@babel/helper-plugin-utils': 7.24.8
      '@babel/helper-plugin-utils': 7.26.5
    transitivePeerDependencies:
      - supports-color
@@ -2879,7 +3114,7 @@
    dependencies:
      '@babel/core': 7.21.4
      '@babel/helper-module-transforms': 7.25.2(@babel/core@7.21.4)
      '@babel/helper-plugin-utils': 7.24.8
      '@babel/helper-plugin-utils': 7.26.5
      '@babel/helper-simple-access': 7.24.7
    transitivePeerDependencies:
      - supports-color
@@ -2893,7 +3128,7 @@
    dependencies:
      '@babel/core': 7.25.2
      '@babel/helper-module-transforms': 7.25.2(@babel/core@7.25.2)
      '@babel/helper-plugin-utils': 7.24.8
      '@babel/helper-plugin-utils': 7.26.5
      '@babel/helper-simple-access': 7.24.7
    transitivePeerDependencies:
      - supports-color
@@ -2906,7 +3141,7 @@
    dependencies:
      '@babel/core': 7.8.0
      '@babel/helper-module-transforms': 7.25.2(@babel/core@7.8.0)
      '@babel/helper-plugin-utils': 7.24.8
      '@babel/helper-plugin-utils': 7.26.5
      '@babel/helper-simple-access': 7.24.7
    transitivePeerDependencies:
      - supports-color
@@ -2919,7 +3154,7 @@
    dependencies:
      '@babel/core': 7.21.4
      '@babel/helper-module-transforms': 7.25.2(@babel/core@7.21.4)
      '@babel/helper-plugin-utils': 7.24.8
      '@babel/helper-plugin-utils': 7.26.5
      '@babel/helper-validator-identifier': 7.24.7
      '@babel/traverse': 7.25.6
    transitivePeerDependencies:
@@ -2934,7 +3169,7 @@
    dependencies:
      '@babel/core': 7.25.2
      '@babel/helper-module-transforms': 7.25.2(@babel/core@7.25.2)
      '@babel/helper-plugin-utils': 7.24.8
      '@babel/helper-plugin-utils': 7.26.5
      '@babel/helper-validator-identifier': 7.24.7
      '@babel/traverse': 7.25.6
    transitivePeerDependencies:
@@ -2948,7 +3183,7 @@
    dependencies:
      '@babel/core': 7.8.0
      '@babel/helper-module-transforms': 7.25.2(@babel/core@7.8.0)
      '@babel/helper-plugin-utils': 7.24.8
      '@babel/helper-plugin-utils': 7.26.5
      '@babel/helper-validator-identifier': 7.24.7
      '@babel/traverse': 7.25.6
    transitivePeerDependencies:
@@ -2962,7 +3197,7 @@
    dependencies:
      '@babel/core': 7.21.4
      '@babel/helper-module-transforms': 7.25.2(@babel/core@7.21.4)
      '@babel/helper-plugin-utils': 7.24.8
      '@babel/helper-plugin-utils': 7.26.5
    transitivePeerDependencies:
      - supports-color
    dev: true
@@ -2975,7 +3210,7 @@
    dependencies:
      '@babel/core': 7.25.2
      '@babel/helper-module-transforms': 7.25.2(@babel/core@7.25.2)
      '@babel/helper-plugin-utils': 7.24.8
      '@babel/helper-plugin-utils': 7.26.5
    transitivePeerDependencies:
      - supports-color
@@ -2987,7 +3222,7 @@
    dependencies:
      '@babel/core': 7.8.0
      '@babel/helper-module-transforms': 7.25.2(@babel/core@7.8.0)
      '@babel/helper-plugin-utils': 7.24.8
      '@babel/helper-plugin-utils': 7.26.5
    transitivePeerDependencies:
      - supports-color
@@ -2999,7 +3234,7 @@
    dependencies:
      '@babel/core': 7.21.4
      '@babel/helper-create-regexp-features-plugin': 7.25.2(@babel/core@7.21.4)
      '@babel/helper-plugin-utils': 7.24.8
      '@babel/helper-plugin-utils': 7.26.5
    dev: true
  /@babel/plugin-transform-named-capturing-groups-regex@7.24.7(@babel/core@7.25.2):
@@ -3010,7 +3245,7 @@
    dependencies:
      '@babel/core': 7.25.2
      '@babel/helper-create-regexp-features-plugin': 7.25.2(@babel/core@7.25.2)
      '@babel/helper-plugin-utils': 7.24.8
      '@babel/helper-plugin-utils': 7.26.5
  /@babel/plugin-transform-named-capturing-groups-regex@7.24.7(@babel/core@7.8.0):
    resolution: {integrity: sha512-/jr7h/EWeJtk1U/uz2jlsCioHkZk1JJZVcc8oQsJ1dUlaJD83f4/6Zeh2aHt9BIFokHIsSeDfhUmju0+1GPd6g==}
@@ -3020,7 +3255,7 @@
    dependencies:
      '@babel/core': 7.8.0
      '@babel/helper-create-regexp-features-plugin': 7.25.2(@babel/core@7.8.0)
      '@babel/helper-plugin-utils': 7.24.8
      '@babel/helper-plugin-utils': 7.26.5
  /@babel/plugin-transform-new-target@7.24.7(@babel/core@7.21.4):
    resolution: {integrity: sha512-RNKwfRIXg4Ls/8mMTza5oPF5RkOW8Wy/WgMAp1/F1yZ8mMbtwXW+HDoJiOsagWrAhI5f57Vncrmr9XeT4CVapA==}
@@ -3029,7 +3264,7 @@
      '@babel/core': ^7.0.0-0
    dependencies:
      '@babel/core': 7.21.4
      '@babel/helper-plugin-utils': 7.24.8
      '@babel/helper-plugin-utils': 7.26.5
    dev: true
  /@babel/plugin-transform-new-target@7.24.7(@babel/core@7.25.2):
@@ -3039,7 +3274,7 @@
      '@babel/core': ^7.0.0-0
    dependencies:
      '@babel/core': 7.25.2
      '@babel/helper-plugin-utils': 7.24.8
      '@babel/helper-plugin-utils': 7.26.5
  /@babel/plugin-transform-new-target@7.24.7(@babel/core@7.8.0):
    resolution: {integrity: sha512-RNKwfRIXg4Ls/8mMTza5oPF5RkOW8Wy/WgMAp1/F1yZ8mMbtwXW+HDoJiOsagWrAhI5f57Vncrmr9XeT4CVapA==}
@@ -3048,7 +3283,7 @@
      '@babel/core': ^7.0.0-0
    dependencies:
      '@babel/core': 7.8.0
      '@babel/helper-plugin-utils': 7.24.8
      '@babel/helper-plugin-utils': 7.26.5
  /@babel/plugin-transform-nullish-coalescing-operator@7.24.7(@babel/core@7.25.2):
    resolution: {integrity: sha512-Ts7xQVk1OEocqzm8rHMXHlxvsfZ0cEF2yomUqpKENHWMF4zKk175Y4q8H5knJes6PgYad50uuRmt3UJuhBw8pQ==}
@@ -3057,7 +3292,7 @@
      '@babel/core': ^7.0.0-0
    dependencies:
      '@babel/core': 7.25.2
      '@babel/helper-plugin-utils': 7.24.8
      '@babel/helper-plugin-utils': 7.26.5
      '@babel/plugin-syntax-nullish-coalescing-operator': 7.8.3(@babel/core@7.25.2)
  /@babel/plugin-transform-nullish-coalescing-operator@7.24.7(@babel/core@7.8.0):
@@ -3067,7 +3302,7 @@
      '@babel/core': ^7.0.0-0
    dependencies:
      '@babel/core': 7.8.0
      '@babel/helper-plugin-utils': 7.24.8
      '@babel/helper-plugin-utils': 7.26.5
      '@babel/plugin-syntax-nullish-coalescing-operator': 7.8.3(@babel/core@7.8.0)
  /@babel/plugin-transform-numeric-separator@7.24.7(@babel/core@7.25.2):
@@ -3077,7 +3312,7 @@
      '@babel/core': ^7.0.0-0
    dependencies:
      '@babel/core': 7.25.2
      '@babel/helper-plugin-utils': 7.24.8
      '@babel/helper-plugin-utils': 7.26.5
      '@babel/plugin-syntax-numeric-separator': 7.10.4(@babel/core@7.25.2)
  /@babel/plugin-transform-numeric-separator@7.24.7(@babel/core@7.8.0):
@@ -3087,7 +3322,7 @@
      '@babel/core': ^7.0.0-0
    dependencies:
      '@babel/core': 7.8.0
      '@babel/helper-plugin-utils': 7.24.8
      '@babel/helper-plugin-utils': 7.26.5
      '@babel/plugin-syntax-numeric-separator': 7.10.4(@babel/core@7.8.0)
  /@babel/plugin-transform-object-rest-spread@7.24.7(@babel/core@7.25.2):
@@ -3098,7 +3333,7 @@
    dependencies:
      '@babel/core': 7.25.2
      '@babel/helper-compilation-targets': 7.25.2
      '@babel/helper-plugin-utils': 7.24.8
      '@babel/helper-plugin-utils': 7.26.5
      '@babel/plugin-syntax-object-rest-spread': 7.8.3(@babel/core@7.25.2)
      '@babel/plugin-transform-parameters': 7.24.7(@babel/core@7.25.2)
@@ -3110,7 +3345,7 @@
    dependencies:
      '@babel/core': 7.8.0
      '@babel/helper-compilation-targets': 7.25.2
      '@babel/helper-plugin-utils': 7.24.8
      '@babel/helper-plugin-utils': 7.26.5
      '@babel/plugin-syntax-object-rest-spread': 7.8.3(@babel/core@7.8.0)
      '@babel/plugin-transform-parameters': 7.24.7(@babel/core@7.8.0)
@@ -3121,7 +3356,7 @@
      '@babel/core': ^7.0.0-0
    dependencies:
      '@babel/core': 7.21.4
      '@babel/helper-plugin-utils': 7.24.8
      '@babel/helper-plugin-utils': 7.26.5
      '@babel/helper-replace-supers': 7.25.0(@babel/core@7.21.4)
    transitivePeerDependencies:
      - supports-color
@@ -3134,7 +3369,7 @@
      '@babel/core': ^7.0.0-0
    dependencies:
      '@babel/core': 7.25.2
      '@babel/helper-plugin-utils': 7.24.8
      '@babel/helper-plugin-utils': 7.26.5
      '@babel/helper-replace-supers': 7.25.0(@babel/core@7.25.2)
    transitivePeerDependencies:
      - supports-color
@@ -3146,7 +3381,7 @@
      '@babel/core': ^7.0.0-0
    dependencies:
      '@babel/core': 7.8.0
      '@babel/helper-plugin-utils': 7.24.8
      '@babel/helper-plugin-utils': 7.26.5
      '@babel/helper-replace-supers': 7.25.0(@babel/core@7.8.0)
    transitivePeerDependencies:
      - supports-color
@@ -3158,7 +3393,7 @@
      '@babel/core': ^7.0.0-0
    dependencies:
      '@babel/core': 7.25.2
      '@babel/helper-plugin-utils': 7.24.8
      '@babel/helper-plugin-utils': 7.26.5
      '@babel/plugin-syntax-optional-catch-binding': 7.8.3(@babel/core@7.25.2)
  /@babel/plugin-transform-optional-catch-binding@7.24.7(@babel/core@7.8.0):
@@ -3168,7 +3403,7 @@
      '@babel/core': ^7.0.0-0
    dependencies:
      '@babel/core': 7.8.0
      '@babel/helper-plugin-utils': 7.24.8
      '@babel/helper-plugin-utils': 7.26.5
      '@babel/plugin-syntax-optional-catch-binding': 7.8.3(@babel/core@7.8.0)
  /@babel/plugin-transform-optional-chaining@7.24.8(@babel/core@7.21.4):
@@ -3178,7 +3413,7 @@
      '@babel/core': ^7.0.0-0
    dependencies:
      '@babel/core': 7.21.4
      '@babel/helper-plugin-utils': 7.24.8
      '@babel/helper-plugin-utils': 7.26.5
      '@babel/helper-skip-transparent-expression-wrappers': 7.24.7
      '@babel/plugin-syntax-optional-chaining': 7.8.3(@babel/core@7.21.4)
    transitivePeerDependencies:
@@ -3192,7 +3427,7 @@
      '@babel/core': ^7.0.0-0
    dependencies:
      '@babel/core': 7.25.2
      '@babel/helper-plugin-utils': 7.24.8
      '@babel/helper-plugin-utils': 7.26.5
      '@babel/helper-skip-transparent-expression-wrappers': 7.24.7
      '@babel/plugin-syntax-optional-chaining': 7.8.3(@babel/core@7.25.2)
    transitivePeerDependencies:
@@ -3205,7 +3440,7 @@
      '@babel/core': ^7.0.0-0
    dependencies:
      '@babel/core': 7.8.0
      '@babel/helper-plugin-utils': 7.24.8
      '@babel/helper-plugin-utils': 7.26.5
      '@babel/helper-skip-transparent-expression-wrappers': 7.24.7
      '@babel/plugin-syntax-optional-chaining': 7.8.3(@babel/core@7.8.0)
    transitivePeerDependencies:
@@ -3218,7 +3453,7 @@
      '@babel/core': ^7.0.0-0
    dependencies:
      '@babel/core': 7.21.4
      '@babel/helper-plugin-utils': 7.24.8
      '@babel/helper-plugin-utils': 7.26.5
    dev: true
  /@babel/plugin-transform-parameters@7.24.7(@babel/core@7.25.2):
@@ -3228,7 +3463,7 @@
      '@babel/core': ^7.0.0-0
    dependencies:
      '@babel/core': 7.25.2
      '@babel/helper-plugin-utils': 7.24.8
      '@babel/helper-plugin-utils': 7.26.5
  /@babel/plugin-transform-parameters@7.24.7(@babel/core@7.8.0):
    resolution: {integrity: sha512-yGWW5Rr+sQOhK0Ot8hjDJuxU3XLRQGflvT4lhlSY0DFvdb3TwKaY26CJzHtYllU0vT9j58hc37ndFPsqT1SrzA==}
@@ -3237,7 +3472,7 @@
      '@babel/core': ^7.0.0-0
    dependencies:
      '@babel/core': 7.8.0
      '@babel/helper-plugin-utils': 7.24.8
      '@babel/helper-plugin-utils': 7.26.5
  /@babel/plugin-transform-private-methods@7.25.4(@babel/core@7.25.2):
    resolution: {integrity: sha512-ao8BG7E2b/URaUQGqN3Tlsg+M3KlHY6rJ1O1gXAEUnZoyNQnvKyH87Kfg+FoxSeyWUB8ISZZsC91C44ZuBFytw==}
@@ -3247,7 +3482,7 @@
    dependencies:
      '@babel/core': 7.25.2
      '@babel/helper-create-class-features-plugin': 7.25.4(@babel/core@7.25.2)
      '@babel/helper-plugin-utils': 7.24.8
      '@babel/helper-plugin-utils': 7.26.5
    transitivePeerDependencies:
      - supports-color
@@ -3259,7 +3494,7 @@
    dependencies:
      '@babel/core': 7.8.0
      '@babel/helper-create-class-features-plugin': 7.25.4(@babel/core@7.8.0)
      '@babel/helper-plugin-utils': 7.24.8
      '@babel/helper-plugin-utils': 7.26.5
    transitivePeerDependencies:
      - supports-color
@@ -3272,7 +3507,7 @@
      '@babel/core': 7.25.2
      '@babel/helper-annotate-as-pure': 7.24.7
      '@babel/helper-create-class-features-plugin': 7.25.4(@babel/core@7.25.2)
      '@babel/helper-plugin-utils': 7.24.8
      '@babel/helper-plugin-utils': 7.26.5
      '@babel/plugin-syntax-private-property-in-object': 7.14.5(@babel/core@7.25.2)
    transitivePeerDependencies:
      - supports-color
@@ -3286,7 +3521,7 @@
      '@babel/core': 7.8.0
      '@babel/helper-annotate-as-pure': 7.24.7
      '@babel/helper-create-class-features-plugin': 7.25.4(@babel/core@7.8.0)
      '@babel/helper-plugin-utils': 7.24.8
      '@babel/helper-plugin-utils': 7.26.5
      '@babel/plugin-syntax-private-property-in-object': 7.14.5(@babel/core@7.8.0)
    transitivePeerDependencies:
      - supports-color
@@ -3298,7 +3533,7 @@
      '@babel/core': ^7.0.0-0
    dependencies:
      '@babel/core': 7.21.4
      '@babel/helper-plugin-utils': 7.24.8
      '@babel/helper-plugin-utils': 7.26.5
    dev: true
  /@babel/plugin-transform-property-literals@7.24.7(@babel/core@7.25.2):
@@ -3308,7 +3543,7 @@
      '@babel/core': ^7.0.0-0
    dependencies:
      '@babel/core': 7.25.2
      '@babel/helper-plugin-utils': 7.24.8
      '@babel/helper-plugin-utils': 7.26.5
  /@babel/plugin-transform-property-literals@7.24.7(@babel/core@7.8.0):
    resolution: {integrity: sha512-EMi4MLQSHfd2nrCqQEWxFdha2gBCqU4ZcCng4WBGZ5CJL4bBRW0ptdqqDdeirGZcpALazVVNJqRmsO8/+oNCBA==}
@@ -3317,7 +3552,7 @@
      '@babel/core': ^7.0.0-0
    dependencies:
      '@babel/core': 7.8.0
      '@babel/helper-plugin-utils': 7.24.8
      '@babel/helper-plugin-utils': 7.26.5
  /@babel/plugin-transform-react-display-name@7.24.7(@babel/core@7.8.0):
    resolution: {integrity: sha512-H/Snz9PFxKsS1JLI4dJLtnJgCJRoo0AUm3chP6NYr+9En1JMKloheEiLIhlp5MDVznWo+H3AAC1Mc8lmUEpsgg==}
@@ -3326,7 +3561,7 @@
      '@babel/core': ^7.0.0-0
    dependencies:
      '@babel/core': 7.8.0
      '@babel/helper-plugin-utils': 7.24.8
      '@babel/helper-plugin-utils': 7.26.5
  /@babel/plugin-transform-react-jsx-development@7.24.7(@babel/core@7.8.0):
    resolution: {integrity: sha512-QG9EnzoGn+Qar7rxuW+ZOsbWOt56FvvI93xInqsZDC5fsekx1AlIO4KIJ5M+D0p0SqSH156EpmZyXq630B8OlQ==}
@@ -3347,7 +3582,7 @@
      '@babel/core': ^7.0.0-0
    dependencies:
      '@babel/core': 7.8.0
      '@babel/helper-plugin-utils': 7.24.8
      '@babel/helper-plugin-utils': 7.26.5
  /@babel/plugin-transform-react-jsx-source@7.24.7(@babel/core@7.8.0):
    resolution: {integrity: sha512-J2z+MWzZHVOemyLweMqngXrgGC42jQ//R0KdxqkIz/OrbVIIlhFI3WigZ5fO+nwFvBlncr4MGapd8vTyc7RPNQ==}
@@ -3356,7 +3591,7 @@
      '@babel/core': ^7.0.0-0
    dependencies:
      '@babel/core': 7.8.0
      '@babel/helper-plugin-utils': 7.24.8
      '@babel/helper-plugin-utils': 7.26.5
  /@babel/plugin-transform-react-jsx@7.25.2(@babel/core@7.8.0):
    resolution: {integrity: sha512-KQsqEAVBpU82NM/B/N9j9WOdphom1SZH3R+2V7INrQUH+V9EBFwZsEJl8eBIVeQE62FxJCc70jzEZwqU7RcVqA==}
@@ -3367,7 +3602,7 @@
      '@babel/core': 7.8.0
      '@babel/helper-annotate-as-pure': 7.24.7
      '@babel/helper-module-imports': 7.24.7
      '@babel/helper-plugin-utils': 7.24.8
      '@babel/helper-plugin-utils': 7.26.5
      '@babel/plugin-syntax-jsx': 7.24.7(@babel/core@7.8.0)
      '@babel/types': 7.25.6
    transitivePeerDependencies:
@@ -3381,7 +3616,7 @@
    dependencies:
      '@babel/core': 7.8.0
      '@babel/helper-annotate-as-pure': 7.24.7
      '@babel/helper-plugin-utils': 7.24.8
      '@babel/helper-plugin-utils': 7.26.5
    dev: true
  /@babel/plugin-transform-regenerator@7.24.7(@babel/core@7.21.4):
@@ -3391,7 +3626,7 @@
      '@babel/core': ^7.0.0-0
    dependencies:
      '@babel/core': 7.21.4
      '@babel/helper-plugin-utils': 7.24.8
      '@babel/helper-plugin-utils': 7.26.5
      regenerator-transform: 0.15.2
    dev: true
@@ -3402,7 +3637,7 @@
      '@babel/core': ^7.0.0-0
    dependencies:
      '@babel/core': 7.25.2
      '@babel/helper-plugin-utils': 7.24.8
      '@babel/helper-plugin-utils': 7.26.5
      regenerator-transform: 0.15.2
  /@babel/plugin-transform-regenerator@7.24.7(@babel/core@7.8.0):
@@ -3412,7 +3647,7 @@
      '@babel/core': ^7.0.0-0
    dependencies:
      '@babel/core': 7.8.0
      '@babel/helper-plugin-utils': 7.24.8
      '@babel/helper-plugin-utils': 7.26.5
      regenerator-transform: 0.15.2
  /@babel/plugin-transform-reserved-words@7.24.7(@babel/core@7.21.4):
@@ -3422,7 +3657,7 @@
      '@babel/core': ^7.0.0-0
    dependencies:
      '@babel/core': 7.21.4
      '@babel/helper-plugin-utils': 7.24.8
      '@babel/helper-plugin-utils': 7.26.5
    dev: true
  /@babel/plugin-transform-reserved-words@7.24.7(@babel/core@7.25.2):
@@ -3432,7 +3667,7 @@
      '@babel/core': ^7.0.0-0
    dependencies:
      '@babel/core': 7.25.2
      '@babel/helper-plugin-utils': 7.24.8
      '@babel/helper-plugin-utils': 7.26.5
  /@babel/plugin-transform-reserved-words@7.24.7(@babel/core@7.8.0):
    resolution: {integrity: sha512-0DUq0pHcPKbjFZCfTss/pGkYMfy3vFWydkUBd9r0GHpIyfs2eCDENvqadMycRS9wZCXR41wucAfJHJmwA0UmoQ==}
@@ -3441,7 +3676,7 @@
      '@babel/core': ^7.0.0-0
    dependencies:
      '@babel/core': 7.8.0
      '@babel/helper-plugin-utils': 7.24.8
      '@babel/helper-plugin-utils': 7.26.5
  /@babel/plugin-transform-runtime@7.21.4(@babel/core@7.21.4):
    resolution: {integrity: sha512-1J4dhrw1h1PqnNNpzwxQ2UBymJUF8KuPjAAnlLwZcGhHAIqUigFW7cdK6GHoB64ubY4qXQNYknoUeks4Wz7CUA==}
@@ -3468,7 +3703,7 @@
    dependencies:
      '@babel/core': 7.25.2
      '@babel/helper-module-imports': 7.24.7
      '@babel/helper-plugin-utils': 7.24.8
      '@babel/helper-plugin-utils': 7.26.5
      babel-plugin-polyfill-corejs2: 0.4.11(@babel/core@7.25.2)
      babel-plugin-polyfill-corejs3: 0.10.6(@babel/core@7.25.2)
      babel-plugin-polyfill-regenerator: 0.6.2(@babel/core@7.25.2)
@@ -3484,7 +3719,7 @@
    dependencies:
      '@babel/core': 7.8.0
      '@babel/helper-module-imports': 7.24.7
      '@babel/helper-plugin-utils': 7.24.8
      '@babel/helper-plugin-utils': 7.26.5
      babel-plugin-polyfill-corejs2: 0.4.11(@babel/core@7.8.0)
      babel-plugin-polyfill-corejs3: 0.10.6(@babel/core@7.8.0)
      babel-plugin-polyfill-regenerator: 0.6.2(@babel/core@7.8.0)
@@ -3499,7 +3734,7 @@
      '@babel/core': ^7.0.0-0
    dependencies:
      '@babel/core': 7.21.4
      '@babel/helper-plugin-utils': 7.24.8
      '@babel/helper-plugin-utils': 7.26.5
    dev: true
  /@babel/plugin-transform-shorthand-properties@7.24.7(@babel/core@7.25.2):
@@ -3509,7 +3744,7 @@
      '@babel/core': ^7.0.0-0
    dependencies:
      '@babel/core': 7.25.2
      '@babel/helper-plugin-utils': 7.24.8
      '@babel/helper-plugin-utils': 7.26.5
  /@babel/plugin-transform-shorthand-properties@7.24.7(@babel/core@7.8.0):
    resolution: {integrity: sha512-KsDsevZMDsigzbA09+vacnLpmPH4aWjcZjXdyFKGzpplxhbeB4wYtury3vglQkg6KM/xEPKt73eCjPPf1PgXBA==}
@@ -3518,7 +3753,7 @@
      '@babel/core': ^7.0.0-0
    dependencies:
      '@babel/core': 7.8.0
      '@babel/helper-plugin-utils': 7.24.8
      '@babel/helper-plugin-utils': 7.26.5
  /@babel/plugin-transform-spread@7.24.7(@babel/core@7.21.4):
    resolution: {integrity: sha512-x96oO0I09dgMDxJaANcRyD4ellXFLLiWhuwDxKZX5g2rWP1bTPkBSwCYv96VDXVT1bD9aPj8tppr5ITIh8hBng==}
@@ -3527,7 +3762,7 @@
      '@babel/core': ^7.0.0-0
    dependencies:
      '@babel/core': 7.21.4
      '@babel/helper-plugin-utils': 7.24.8
      '@babel/helper-plugin-utils': 7.26.5
      '@babel/helper-skip-transparent-expression-wrappers': 7.24.7
    transitivePeerDependencies:
      - supports-color
@@ -3540,7 +3775,7 @@
      '@babel/core': ^7.0.0-0
    dependencies:
      '@babel/core': 7.25.2
      '@babel/helper-plugin-utils': 7.24.8
      '@babel/helper-plugin-utils': 7.26.5
      '@babel/helper-skip-transparent-expression-wrappers': 7.24.7
    transitivePeerDependencies:
      - supports-color
@@ -3552,7 +3787,7 @@
      '@babel/core': ^7.0.0-0
    dependencies:
      '@babel/core': 7.8.0
      '@babel/helper-plugin-utils': 7.24.8
      '@babel/helper-plugin-utils': 7.26.5
      '@babel/helper-skip-transparent-expression-wrappers': 7.24.7
    transitivePeerDependencies:
      - supports-color
@@ -3564,7 +3799,7 @@
      '@babel/core': ^7.0.0-0
    dependencies:
      '@babel/core': 7.21.4
      '@babel/helper-plugin-utils': 7.24.8
      '@babel/helper-plugin-utils': 7.26.5
    dev: true
  /@babel/plugin-transform-sticky-regex@7.24.7(@babel/core@7.25.2):
@@ -3574,7 +3809,7 @@
      '@babel/core': ^7.0.0-0
    dependencies:
      '@babel/core': 7.25.2
      '@babel/helper-plugin-utils': 7.24.8
      '@babel/helper-plugin-utils': 7.26.5
  /@babel/plugin-transform-sticky-regex@7.24.7(@babel/core@7.8.0):
    resolution: {integrity: sha512-kHPSIJc9v24zEml5geKg9Mjx5ULpfncj0wRpYtxbvKyTtHCYDkVE3aHQ03FrpEo4gEe2vrJJS1Y9CJTaThA52g==}
@@ -3583,7 +3818,7 @@
      '@babel/core': ^7.0.0-0
    dependencies:
      '@babel/core': 7.8.0
      '@babel/helper-plugin-utils': 7.24.8
      '@babel/helper-plugin-utils': 7.26.5
  /@babel/plugin-transform-template-literals@7.24.7(@babel/core@7.21.4):
    resolution: {integrity: sha512-AfDTQmClklHCOLxtGoP7HkeMw56k1/bTQjwsfhL6pppo/M4TOBSq+jjBUBLmV/4oeFg4GWMavIl44ZeCtmmZTw==}
@@ -3592,7 +3827,7 @@
      '@babel/core': ^7.0.0-0
    dependencies:
      '@babel/core': 7.21.4
      '@babel/helper-plugin-utils': 7.24.8
      '@babel/helper-plugin-utils': 7.26.5
    dev: true
  /@babel/plugin-transform-template-literals@7.24.7(@babel/core@7.25.2):
@@ -3602,7 +3837,7 @@
      '@babel/core': ^7.0.0-0
    dependencies:
      '@babel/core': 7.25.2
      '@babel/helper-plugin-utils': 7.24.8
      '@babel/helper-plugin-utils': 7.26.5
  /@babel/plugin-transform-template-literals@7.24.7(@babel/core@7.8.0):
    resolution: {integrity: sha512-AfDTQmClklHCOLxtGoP7HkeMw56k1/bTQjwsfhL6pppo/M4TOBSq+jjBUBLmV/4oeFg4GWMavIl44ZeCtmmZTw==}
@@ -3611,7 +3846,7 @@
      '@babel/core': ^7.0.0-0
    dependencies:
      '@babel/core': 7.8.0
      '@babel/helper-plugin-utils': 7.24.8
      '@babel/helper-plugin-utils': 7.26.5
  /@babel/plugin-transform-typeof-symbol@7.24.8(@babel/core@7.21.4):
    resolution: {integrity: sha512-adNTUpDCVnmAE58VEqKlAA6ZBlNkMnWD0ZcW76lyNFN3MJniyGFZfNwERVk8Ap56MCnXztmDr19T4mPTztcuaw==}
@@ -3620,7 +3855,7 @@
      '@babel/core': ^7.0.0-0
    dependencies:
      '@babel/core': 7.21.4
      '@babel/helper-plugin-utils': 7.24.8
      '@babel/helper-plugin-utils': 7.26.5
    dev: true
  /@babel/plugin-transform-typeof-symbol@7.24.8(@babel/core@7.25.2):
@@ -3630,7 +3865,7 @@
      '@babel/core': ^7.0.0-0
    dependencies:
      '@babel/core': 7.25.2
      '@babel/helper-plugin-utils': 7.24.8
      '@babel/helper-plugin-utils': 7.26.5
  /@babel/plugin-transform-typeof-symbol@7.24.8(@babel/core@7.8.0):
    resolution: {integrity: sha512-adNTUpDCVnmAE58VEqKlAA6ZBlNkMnWD0ZcW76lyNFN3MJniyGFZfNwERVk8Ap56MCnXztmDr19T4mPTztcuaw==}
@@ -3639,7 +3874,7 @@
      '@babel/core': ^7.0.0-0
    dependencies:
      '@babel/core': 7.8.0
      '@babel/helper-plugin-utils': 7.24.8
      '@babel/helper-plugin-utils': 7.26.5
  /@babel/plugin-transform-typescript@7.21.3(@babel/core@7.21.4):
    resolution: {integrity: sha512-RQxPz6Iqt8T0uw/WsJNReuBpWpBqs/n7mNo18sKLoTbMp+UrEekhH+pKSVC7gWz+DNjo9gryfV8YzCiT45RgMw==}
@@ -3665,7 +3900,7 @@
      '@babel/core': 7.25.2
      '@babel/helper-annotate-as-pure': 7.24.7
      '@babel/helper-create-class-features-plugin': 7.25.4(@babel/core@7.25.2)
      '@babel/helper-plugin-utils': 7.24.8
      '@babel/helper-plugin-utils': 7.26.5
      '@babel/helper-skip-transparent-expression-wrappers': 7.24.7
      '@babel/plugin-syntax-typescript': 7.25.4(@babel/core@7.25.2)
    transitivePeerDependencies:
@@ -3680,7 +3915,7 @@
      '@babel/core': 7.8.0
      '@babel/helper-annotate-as-pure': 7.24.7
      '@babel/helper-create-class-features-plugin': 7.25.4(@babel/core@7.8.0)
      '@babel/helper-plugin-utils': 7.24.8
      '@babel/helper-plugin-utils': 7.26.5
      '@babel/helper-skip-transparent-expression-wrappers': 7.24.7
      '@babel/plugin-syntax-typescript': 7.25.4(@babel/core@7.8.0)
    transitivePeerDependencies:
@@ -3693,7 +3928,7 @@
      '@babel/core': ^7.0.0-0
    dependencies:
      '@babel/core': 7.21.4
      '@babel/helper-plugin-utils': 7.24.8
      '@babel/helper-plugin-utils': 7.26.5
    dev: true
  /@babel/plugin-transform-unicode-escapes@7.24.7(@babel/core@7.25.2):
@@ -3703,7 +3938,7 @@
      '@babel/core': ^7.0.0-0
    dependencies:
      '@babel/core': 7.25.2
      '@babel/helper-plugin-utils': 7.24.8
      '@babel/helper-plugin-utils': 7.26.5
  /@babel/plugin-transform-unicode-escapes@7.24.7(@babel/core@7.8.0):
    resolution: {integrity: sha512-U3ap1gm5+4edc2Q/P+9VrBNhGkfnf+8ZqppY71Bo/pzZmXhhLdqgaUl6cuB07O1+AQJtCLfaOmswiNbSQ9ivhw==}
@@ -3712,7 +3947,7 @@
      '@babel/core': ^7.0.0-0
    dependencies:
      '@babel/core': 7.8.0
      '@babel/helper-plugin-utils': 7.24.8
      '@babel/helper-plugin-utils': 7.26.5
  /@babel/plugin-transform-unicode-property-regex@7.24.7(@babel/core@7.25.2):
    resolution: {integrity: sha512-uH2O4OV5M9FZYQrwc7NdVmMxQJOCCzFeYudlZSzUAHRFeOujQefa92E74TQDVskNHCzOXoigEuoyzHDhaEaK5w==}
@@ -3722,7 +3957,7 @@
    dependencies:
      '@babel/core': 7.25.2
      '@babel/helper-create-regexp-features-plugin': 7.25.2(@babel/core@7.25.2)
      '@babel/helper-plugin-utils': 7.24.8
      '@babel/helper-plugin-utils': 7.26.5
  /@babel/plugin-transform-unicode-property-regex@7.24.7(@babel/core@7.8.0):
    resolution: {integrity: sha512-uH2O4OV5M9FZYQrwc7NdVmMxQJOCCzFeYudlZSzUAHRFeOujQefa92E74TQDVskNHCzOXoigEuoyzHDhaEaK5w==}
@@ -3732,7 +3967,7 @@
    dependencies:
      '@babel/core': 7.8.0
      '@babel/helper-create-regexp-features-plugin': 7.25.2(@babel/core@7.8.0)
      '@babel/helper-plugin-utils': 7.24.8
      '@babel/helper-plugin-utils': 7.26.5
  /@babel/plugin-transform-unicode-regex@7.24.7(@babel/core@7.21.4):
    resolution: {integrity: sha512-hlQ96MBZSAXUq7ltkjtu3FJCCSMx/j629ns3hA3pXnBXjanNP0LHi+JpPeA81zaWgVK1VGH95Xuy7u0RyQ8kMg==}
@@ -3742,7 +3977,7 @@
    dependencies:
      '@babel/core': 7.21.4
      '@babel/helper-create-regexp-features-plugin': 7.25.2(@babel/core@7.21.4)
      '@babel/helper-plugin-utils': 7.24.8
      '@babel/helper-plugin-utils': 7.26.5
    dev: true
  /@babel/plugin-transform-unicode-regex@7.24.7(@babel/core@7.25.2):
@@ -3753,7 +3988,7 @@
    dependencies:
      '@babel/core': 7.25.2
      '@babel/helper-create-regexp-features-plugin': 7.25.2(@babel/core@7.25.2)
      '@babel/helper-plugin-utils': 7.24.8
      '@babel/helper-plugin-utils': 7.26.5
  /@babel/plugin-transform-unicode-regex@7.24.7(@babel/core@7.8.0):
    resolution: {integrity: sha512-hlQ96MBZSAXUq7ltkjtu3FJCCSMx/j629ns3hA3pXnBXjanNP0LHi+JpPeA81zaWgVK1VGH95Xuy7u0RyQ8kMg==}
@@ -3763,7 +3998,7 @@
    dependencies:
      '@babel/core': 7.8.0
      '@babel/helper-create-regexp-features-plugin': 7.25.2(@babel/core@7.8.0)
      '@babel/helper-plugin-utils': 7.24.8
      '@babel/helper-plugin-utils': 7.26.5
  /@babel/plugin-transform-unicode-sets-regex@7.25.4(@babel/core@7.25.2):
    resolution: {integrity: sha512-qesBxiWkgN1Q+31xUE9RcMk79eOXXDCv6tfyGMRSs4RGlioSg2WVyQAm07k726cSE56pa+Kb0y9epX2qaXzTvA==}
@@ -3773,7 +4008,7 @@
    dependencies:
      '@babel/core': 7.25.2
      '@babel/helper-create-regexp-features-plugin': 7.25.2(@babel/core@7.25.2)
      '@babel/helper-plugin-utils': 7.24.8
      '@babel/helper-plugin-utils': 7.26.5
  /@babel/plugin-transform-unicode-sets-regex@7.25.4(@babel/core@7.8.0):
    resolution: {integrity: sha512-qesBxiWkgN1Q+31xUE9RcMk79eOXXDCv6tfyGMRSs4RGlioSg2WVyQAm07k726cSE56pa+Kb0y9epX2qaXzTvA==}
@@ -3783,7 +4018,7 @@
    dependencies:
      '@babel/core': 7.8.0
      '@babel/helper-create-regexp-features-plugin': 7.25.2(@babel/core@7.8.0)
      '@babel/helper-plugin-utils': 7.24.8
      '@babel/helper-plugin-utils': 7.26.5
  /@babel/preset-env@7.21.4(@babel/core@7.21.4):
    resolution: {integrity: sha512-2W57zHs2yDLm6GD5ZpvNn71lZ0B/iypSdIeq25OurDKji6AdzV07qp4s3n1/x5BqtiGaTrPN3nerlSCaC5qNTw==}
@@ -3880,8 +4115,8 @@
      '@babel/compat-data': 7.25.4
      '@babel/core': 7.25.2
      '@babel/helper-compilation-targets': 7.25.2
      '@babel/helper-plugin-utils': 7.24.8
      '@babel/helper-validator-option': 7.24.8
      '@babel/helper-plugin-utils': 7.26.5
      '@babel/helper-validator-option': 7.25.9
      '@babel/plugin-bugfix-firefox-class-in-computed-class-key': 7.25.3(@babel/core@7.25.2)
      '@babel/plugin-bugfix-safari-class-field-initializer-scope': 7.25.0(@babel/core@7.25.2)
      '@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression': 7.25.0(@babel/core@7.25.2)
@@ -3973,8 +4208,8 @@
      '@babel/compat-data': 7.25.4
      '@babel/core': 7.8.0
      '@babel/helper-compilation-targets': 7.25.2
      '@babel/helper-plugin-utils': 7.24.8
      '@babel/helper-validator-option': 7.24.8
      '@babel/helper-plugin-utils': 7.26.5
      '@babel/helper-validator-option': 7.25.9
      '@babel/plugin-bugfix-firefox-class-in-computed-class-key': 7.25.3(@babel/core@7.8.0)
      '@babel/plugin-bugfix-safari-class-field-initializer-scope': 7.25.0(@babel/core@7.8.0)
      '@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression': 7.25.0(@babel/core@7.8.0)
@@ -4088,7 +4323,7 @@
      '@babel/core': ^7.0.0-0 || ^8.0.0-0 <8.0.0
    dependencies:
      '@babel/core': 7.25.2
      '@babel/helper-plugin-utils': 7.24.8
      '@babel/helper-plugin-utils': 7.26.5
      '@babel/types': 7.25.6
      esutils: 2.0.3
@@ -4098,7 +4333,7 @@
      '@babel/core': ^7.0.0-0 || ^8.0.0-0 <8.0.0
    dependencies:
      '@babel/core': 7.8.0
      '@babel/helper-plugin-utils': 7.24.8
      '@babel/helper-plugin-utils': 7.26.5
      '@babel/types': 7.25.6
      esutils: 2.0.3
@@ -4109,8 +4344,8 @@
      '@babel/core': ^7.0.0-0
    dependencies:
      '@babel/core': 7.8.0
      '@babel/helper-plugin-utils': 7.24.8
      '@babel/helper-validator-option': 7.24.8
      '@babel/helper-plugin-utils': 7.26.5
      '@babel/helper-validator-option': 7.25.9
      '@babel/plugin-transform-react-display-name': 7.24.7(@babel/core@7.8.0)
      '@babel/plugin-transform-react-jsx': 7.25.2(@babel/core@7.8.0)
      '@babel/plugin-transform-react-jsx-development': 7.24.7(@babel/core@7.8.0)
@@ -4126,8 +4361,8 @@
      '@babel/core': ^7.0.0-0
    dependencies:
      '@babel/core': 7.25.2
      '@babel/helper-plugin-utils': 7.24.8
      '@babel/helper-validator-option': 7.24.8
      '@babel/helper-plugin-utils': 7.26.5
      '@babel/helper-validator-option': 7.25.9
      '@babel/plugin-syntax-jsx': 7.24.7(@babel/core@7.25.2)
      '@babel/plugin-transform-modules-commonjs': 7.24.8(@babel/core@7.25.2)
      '@babel/plugin-transform-typescript': 7.25.2(@babel/core@7.25.2)
@@ -4141,8 +4376,8 @@
      '@babel/core': ^7.0.0-0
    dependencies:
      '@babel/core': 7.8.0
      '@babel/helper-plugin-utils': 7.24.8
      '@babel/helper-validator-option': 7.24.8
      '@babel/helper-plugin-utils': 7.26.5
      '@babel/helper-validator-option': 7.25.9
      '@babel/plugin-syntax-jsx': 7.24.7(@babel/core@7.8.0)
      '@babel/plugin-transform-modules-commonjs': 7.24.8(@babel/core@7.8.0)
      '@babel/plugin-transform-typescript': 7.25.2(@babel/core@7.8.0)
@@ -6336,20 +6571,6 @@
      - conventional-commits-parser
    dev: true
  /@rollup/pluginutils@5.1.0:
    resolution: {integrity: sha512-XTIWOPPcpvyKI6L1NHo0lFlCyznUEyPmPY1mc3KpPVDYulHSTvyeLNVW00QTLIAFNhR3kYnJTQHeGqU4M3n09g==}
    engines: {node: '>=14.0.0'}
    peerDependencies:
      rollup: ^1.20.0||^2.0.0||^3.0.0||^4.0.0
    peerDependenciesMeta:
      rollup:
        optional: true
    dependencies:
      '@types/estree': 1.0.5
      estree-walker: 2.0.2
      picomatch: 2.3.1
    dev: true
  /@rollup/pluginutils@5.1.4:
    resolution: {integrity: sha512-USm05zrsFxYLPdWWq+K3STlWiT/3ELn3RcV5hJMghpeAIhxfsUIg6mt12CBJBInWMV4VneoV7SfGv8xIwo2qNQ==}
    engines: {node: '>=14.0.0'}
@@ -8226,7 +8447,7 @@
      '@vue/compiler-ssr': 3.5.12
      '@vue/shared': 3.5.12
      estree-walker: 2.0.2
      magic-string: 0.30.11
      magic-string: 0.30.17
      postcss: 8.4.47
      source-map-js: 1.2.1
@@ -8555,13 +8776,13 @@
      acorn-walk: 8.3.4
    dev: true
  /acorn-import-assertions@1.9.0(acorn@8.12.1):
  /acorn-import-assertions@1.9.0(acorn@8.14.0):
    resolution: {integrity: sha512-cmMwop9x+8KFhxvKrKfPYmN6/pKTYYHBqLa0DfvVZcKMJWNyWLnaqND7dx/qn66R7ewM1UX5XMaDVP5wlVTaVA==}
    deprecated: package has been renamed to acorn-import-attributes
    peerDependencies:
      acorn: ^8
    dependencies:
      acorn: 8.12.1
      acorn: 8.14.0
  /acorn-jsx@5.3.2(acorn@8.14.0):
    resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==}
@@ -8583,11 +8804,6 @@
    engines: {node: '>=0.4.0'}
    hasBin: true
    dev: true
  /acorn@8.12.1:
    resolution: {integrity: sha512-tcpGyI9zbizT9JbV6oYE477V6mTlXvvi0T0G3SNIYE2apm/G5huBa1+K89VGeovbg+jycCrfhl3ADxErOuO6Jg==}
    engines: {node: '>=0.4.0'}
    hasBin: true
  /acorn@8.14.0:
    resolution: {integrity: sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA==}
@@ -11682,6 +11898,7 @@
        optional: true
    dependencies:
      ms: 2.1.3
    dev: true
  /debug@4.4.0:
    resolution: {integrity: sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==}
@@ -13052,17 +13269,6 @@
  /fast-diff@1.3.0:
    resolution: {integrity: sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw==}
    dev: true
  /fast-glob@3.3.2:
    resolution: {integrity: sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==}
    engines: {node: '>=8.6.0'}
    dependencies:
      '@nodelib/fs.stat': 2.0.5
      '@nodelib/fs.walk': 1.2.8
      glob-parent: 5.1.2
      merge2: 1.4.1
      micromatch: 4.0.8
    dev: true
  /fast-glob@3.3.3:
@@ -15944,11 +16150,6 @@
    engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
    dev: true
  /magic-string@0.30.11:
    resolution: {integrity: sha512-+Wri9p0QHMy+545hKww7YAu5NyzF8iomPL/RQazugQ9+Ez4Ic3mERMd8ZTX5rfK944j+560ZJi8iAwgak1Ac7A==}
    dependencies:
      '@jridgewell/sourcemap-codec': 1.5.0
  /magic-string@0.30.17:
    resolution: {integrity: sha512-sNPKHvyjVf7gyjwS4xGTaW/mCnF8wnjtifKBEhxfZ7E/S8tQ0rssrwGNn6q8JH/ohItJfSQp9mBtQYuTlH5QnA==}
    dependencies:
@@ -16258,7 +16459,7 @@
      '@babel/plugin-proposal-optional-chaining': 7.21.0(@babel/core@7.8.0)
      '@babel/plugin-syntax-dynamic-import': 7.8.3(@babel/core@7.8.0)
      '@babel/plugin-syntax-export-default-from': 7.24.7(@babel/core@7.8.0)
      '@babel/plugin-syntax-flow': 7.24.7(@babel/core@7.8.0)
      '@babel/plugin-syntax-flow': 7.26.0(@babel/core@7.8.0)
      '@babel/plugin-syntax-nullish-coalescing-operator': 7.8.3(@babel/core@7.8.0)
      '@babel/plugin-syntax-optional-chaining': 7.8.3(@babel/core@7.8.0)
      '@babel/plugin-transform-arrow-functions': 7.24.7(@babel/core@7.8.0)
@@ -16268,7 +16469,7 @@
      '@babel/plugin-transform-computed-properties': 7.24.7(@babel/core@7.8.0)
      '@babel/plugin-transform-destructuring': 7.24.8(@babel/core@7.8.0)
      '@babel/plugin-transform-exponentiation-operator': 7.24.7(@babel/core@7.8.0)
      '@babel/plugin-transform-flow-strip-types': 7.25.2(@babel/core@7.8.0)
      '@babel/plugin-transform-flow-strip-types': 7.26.5(@babel/core@7.8.0)
      '@babel/plugin-transform-function-name': 7.25.1(@babel/core@7.8.0)
      '@babel/plugin-transform-literals': 7.25.2(@babel/core@7.8.0)
      '@babel/plugin-transform-modules-commonjs': 7.24.8(@babel/core@7.8.0)
@@ -20189,8 +20390,8 @@
      colord: 2.9.3
      cosmiconfig: 7.1.0
      css-functions-list: 3.2.2
      debug: 4.3.7
      fast-glob: 3.3.2
      debug: 4.4.0
      fast-glob: 3.3.3
      fastest-levenshtein: 1.0.16
      file-entry-cache: 6.0.1
      global-modules: 2.0.0
@@ -20977,10 +21178,10 @@
        optional: true
    dependencies:
      '@antfu/utils': 0.7.10
      '@rollup/pluginutils': 5.1.0
      fast-glob: 3.3.2
      '@rollup/pluginutils': 5.1.4
      fast-glob: 3.3.3
      local-pkg: 0.4.3
      magic-string: 0.30.11
      magic-string: 0.30.17
      minimatch: 9.0.5
      unimport: 3.12.0
      unplugin: 1.14.1
@@ -21334,7 +21535,7 @@
    peerDependencies:
      eslint: '>=6.0.0'
    dependencies:
      debug: 4.3.7
      debug: 4.4.0
      eslint: 8.41.0
      eslint-scope: 7.2.2
      eslint-visitor-keys: 3.4.3
@@ -21522,7 +21723,7 @@
    engines: {node: '>= 10.13.0'}
    hasBin: true
    dependencies:
      acorn: 8.12.1
      acorn: 8.14.0
      acorn-walk: 8.3.4
      chalk: 4.1.2
      commander: 7.2.0
@@ -21653,8 +21854,8 @@
      '@webassemblyjs/ast': 1.11.1
      '@webassemblyjs/wasm-edit': 1.11.1
      '@webassemblyjs/wasm-parser': 1.11.1
      acorn: 8.12.1
      acorn-import-assertions: 1.9.0(acorn@8.12.1)
      acorn: 8.14.0
      acorn-import-assertions: 1.9.0(acorn@8.14.0)
      browserslist: 4.23.3
      chrome-trace-event: 1.0.4
      enhanced-resolve: 5.17.1