├── .changeset ├── README.md └── config.json ├── .commitlintrc.js ├── .editorconfig ├── .eslintignore ├── .eslintrc.js ├── .github ├── ISSUE_TEMPLATE │ ├── 1-bug.md │ ├── 2-feature.md │ ├── 3-bug-cn.md │ └── config.yml ├── commit-convention.md ├── contributing.md ├── pull_request_template.md └── workflows │ ├── deploy.yml │ ├── ftp-schedule.yml │ ├── issue-close-require.yml │ ├── issue-labeled.yml │ └── release.yml ├── .gitignore ├── .gitpod.yml ├── .lintstagedrc.js ├── .npmrc ├── .prettierignore ├── .prettierrc.js ├── .stylelintignore ├── .stylelintrc.js ├── .vscode ├── extensions.json ├── launch.json └── settings.json ├── LICENSE ├── README.md ├── README.zh-CN.md ├── apps ├── amis │ ├── .env.development │ ├── .gitignore │ ├── .prettierrc │ ├── App.tsx │ ├── Dockerfile │ ├── README.md │ ├── auth │ │ ├── login.html │ │ ├── login.tsx │ │ ├── logincallback.html │ │ └── logincallback.tsx │ ├── component │ │ ├── AMISRenderer.tsx │ │ └── AddPageModal.tsx │ ├── deploy-gh-pages.sh │ ├── editor.html │ ├── editor │ │ └── MyRenderer.tsx │ ├── fis-conf.js │ ├── index.html │ ├── index.tsx │ ├── loadMonacoEditor.ts │ ├── mod.js │ ├── package.json │ ├── renderer │ │ └── MyRenderer.tsx │ ├── route │ │ ├── Editor copy.tsx │ │ ├── Editor.tsx │ │ ├── EditorUmi.tsx │ │ ├── NotFound.tsx │ │ ├── Preview.tsx │ │ ├── View.tsx │ │ ├── auth │ │ │ └── authService.ts │ │ ├── index.tsx │ │ └── oldEditor.tsx │ ├── scss │ │ └── style.scss │ ├── service │ │ └── api.ts │ ├── store │ │ ├── Page.ts │ │ └── index.ts │ ├── tsconfig.json │ ├── upload2cdn.js │ └── yarn.lock └── ant-admin │ ├── .env │ ├── .env.development │ ├── .env.production │ ├── .env.staging │ ├── .env.test │ ├── index.html │ ├── mock │ ├── _mock-server.ts │ ├── _util.ts │ ├── demo │ │ ├── account.ts │ │ ├── api-cascader.ts │ │ ├── select-demo.ts │ │ ├── system.ts │ │ ├── table-demo.ts │ │ └── tree-demo.ts │ └── sys │ │ ├── menu.ts │ │ └── user.ts │ ├── package.json │ ├── postcss.config.js │ ├── public │ ├── favicon.ico │ ├── img │ │ └── logo.png │ └── resource │ │ ├── img │ │ ├── logo.png │ │ ├── pwa-192x192.png │ │ └── pwa-512x512.png │ │ └── tinymce │ │ ├── langs │ │ ├── en.js │ │ └── zh_CN.js │ │ └── skins │ │ └── ui │ │ ├── oxide-dark │ │ ├── content.inline.min.css │ │ ├── content.min.css │ │ ├── content.mobile.min.css │ │ ├── skin.min.css │ │ └── skin.mobile.min.css │ │ └── oxide │ │ ├── content.inline.min.css │ │ ├── content.min.css │ │ ├── content.mobile.min.css │ │ ├── fonts │ │ └── tinymce-mobile.woff │ │ ├── skin.min.css │ │ └── skin.mobile.min.css │ ├── scripts │ ├── build-config.ts │ ├── generate-icon.ts │ └── post-build.ts │ ├── src │ ├── api │ │ ├── ContentTypeService.ts │ │ ├── VbenFormService.ts │ │ ├── VbenListService.ts │ │ ├── authService.ts │ │ ├── contentHelper.ts │ │ └── ocUtils.ts │ ├── app.vue │ ├── assets │ │ ├── icons │ │ │ ├── download-count.svg │ │ │ ├── dynamic-avatar-1.svg │ │ │ ├── dynamic-avatar-2.svg │ │ │ ├── dynamic-avatar-3.svg │ │ │ ├── dynamic-avatar-4.svg │ │ │ ├── dynamic-avatar-5.svg │ │ │ ├── dynamic-avatar-6.svg │ │ │ ├── moon.svg │ │ │ ├── sun.svg │ │ │ ├── test.svg │ │ │ ├── total-sales.svg │ │ │ ├── transaction.svg │ │ │ └── visit-count.svg │ │ ├── images │ │ │ ├── demo.png │ │ │ ├── header.jpg │ │ │ └── logo.png │ │ └── svg │ │ │ ├── illustration.svg │ │ │ ├── login-bg-dark.svg │ │ │ ├── login-bg.svg │ │ │ ├── login-box-bg.svg │ │ │ ├── net-error.svg │ │ │ └── no-data.svg │ ├── components │ │ ├── Amis │ │ │ ├── index.ts │ │ │ └── src │ │ │ │ ├── amisEnv.ts │ │ │ │ ├── index.vue │ │ │ │ ├── react_app │ │ │ │ ├── MyRenderer.tsx │ │ │ │ └── Renderer.jsx │ │ │ │ ├── style │ │ │ │ └── themes │ │ │ │ │ ├── ang.less │ │ │ │ │ ├── antd.less │ │ │ │ │ ├── antd_var.less │ │ │ │ │ ├── cxd.less │ │ │ │ │ ├── cxd │ │ │ │ │ ├── fix.less │ │ │ │ │ └── fixvars.less │ │ │ │ │ ├── dark.less │ │ │ │ │ └── default.less │ │ │ │ ├── types │ │ │ │ └── index.ts │ │ │ │ ├── veauryAMISRenderer.vue │ │ │ │ └── vue │ │ │ │ ├── AA.vue │ │ │ │ └── Basic.vue │ │ ├── Authority │ │ │ ├── index.ts │ │ │ └── src │ │ │ │ └── index.vue │ │ ├── CodeEditor │ │ │ ├── index.ts │ │ │ └── src │ │ │ │ ├── CodeEditor.vue │ │ │ │ ├── codemirror │ │ │ │ ├── CodeMirror.vue │ │ │ │ ├── codeMirror.ts │ │ │ │ └── codemirror.css │ │ │ │ ├── json-preview │ │ │ │ └── JsonPreview.vue │ │ │ │ └── typing.ts │ │ ├── MonacoEditor │ │ │ └── index.vue │ │ ├── OrchardCore │ │ │ ├── hooks │ │ │ │ └── useContentForm.ts │ │ │ ├── index.ts │ │ │ ├── src │ │ │ │ ├── ContentForm.vue │ │ │ │ └── props.ts │ │ │ └── types │ │ │ │ └── ContentFormProps.ts │ │ ├── Tree │ │ │ ├── index.ts │ │ │ ├── src │ │ │ │ ├── index.vue │ │ │ │ ├── tree-header.vue │ │ │ │ ├── tree-icon.ts │ │ │ │ ├── tree.ts │ │ │ │ └── use-tree.ts │ │ │ └── style │ │ │ │ ├── index.less │ │ │ │ └── index.ts │ │ ├── Upload │ │ │ ├── index.ts │ │ │ └── src │ │ │ │ ├── data.tsx │ │ │ │ ├── file-list.vue │ │ │ │ ├── helper.ts │ │ │ │ ├── index.vue │ │ │ │ ├── props.ts │ │ │ │ ├── thumb-url.vue │ │ │ │ ├── typing.ts │ │ │ │ ├── upload-modal.vue │ │ │ │ ├── upload-preview-modal.vue │ │ │ │ └── use-upload.ts │ │ ├── application │ │ │ ├── index.ts │ │ │ └── src │ │ │ │ ├── AppDarkModeToggle.vue │ │ │ │ ├── AppLocalePicker.vue │ │ │ │ ├── AppLogo.vue │ │ │ │ ├── AppProvider.vue │ │ │ │ ├── search │ │ │ │ ├── AppSearch.vue │ │ │ │ ├── AppSearchFooter.vue │ │ │ │ ├── AppSearchKeyItem.vue │ │ │ │ ├── AppSearchModal.vue │ │ │ │ └── useMenuSearch.ts │ │ │ │ └── useAppContext.ts │ │ ├── basic │ │ │ ├── index.ts │ │ │ └── src │ │ │ │ ├── BasicArrow.vue │ │ │ │ ├── BasicHelp.vue │ │ │ │ └── BasicTitle.vue │ │ ├── button │ │ │ ├── index.ts │ │ │ └── src │ │ │ │ └── PopConfirmButton.vue │ │ ├── card-list │ │ │ ├── index.ts │ │ │ └── src │ │ │ │ ├── CardList.vue │ │ │ │ └── data.ts │ │ ├── container │ │ │ ├── index.ts │ │ │ └── src │ │ │ │ ├── ScrollContainer.vue │ │ │ │ ├── collapse │ │ │ │ ├── CollapseContainer.vue │ │ │ │ └── CollapseHeader.vue │ │ │ │ └── typing.ts │ │ ├── context-menu │ │ │ ├── index.ts │ │ │ └── src │ │ │ │ ├── ContextMenu.vue │ │ │ │ ├── createContextMenu.ts │ │ │ │ └── typing.ts │ │ ├── count-down │ │ │ ├── index.ts │ │ │ └── src │ │ │ │ ├── CountButton.vue │ │ │ │ ├── CountdownInput.vue │ │ │ │ └── useCountdown.ts │ │ ├── cropper │ │ │ ├── index.ts │ │ │ └── src │ │ │ │ ├── CopperModal.vue │ │ │ │ ├── Cropper.vue │ │ │ │ ├── CropperAvatar.vue │ │ │ │ └── typing.ts │ │ ├── description │ │ │ ├── index.ts │ │ │ └── src │ │ │ │ ├── Description.vue │ │ │ │ ├── typing.ts │ │ │ │ └── useDescription.ts │ │ ├── drawer │ │ │ ├── index.ts │ │ │ └── src │ │ │ │ ├── BasicDrawer.vue │ │ │ │ ├── components │ │ │ │ ├── DrawerFooter.vue │ │ │ │ └── DrawerHeader.vue │ │ │ │ ├── props.ts │ │ │ │ ├── typing.ts │ │ │ │ └── useDrawer.ts │ │ ├── dropdown │ │ │ ├── index.ts │ │ │ └── src │ │ │ │ ├── Dropdown.vue │ │ │ │ └── typing.ts │ │ ├── form │ │ │ ├── index.ts │ │ │ └── src │ │ │ │ ├── BasicForm.vue │ │ │ │ ├── componentMap.ts │ │ │ │ ├── components │ │ │ │ ├── ApiCascader.vue │ │ │ │ ├── ApiRadioGroup.vue │ │ │ │ ├── ApiSelect.vue │ │ │ │ ├── ApiTreeSelect.vue │ │ │ │ ├── ContentTreeSelect.vue │ │ │ │ ├── FormAction.vue │ │ │ │ ├── FormItem.vue │ │ │ │ └── RadioButtonGroup.vue │ │ │ │ ├── helper.ts │ │ │ │ ├── hooks │ │ │ │ ├── useAdvanced.ts │ │ │ │ ├── useAutoFocus.ts │ │ │ │ ├── useComponentRegister.ts │ │ │ │ ├── useForm.ts │ │ │ │ ├── useFormContext.ts │ │ │ │ ├── useFormEvents.ts │ │ │ │ ├── useFormValues.ts │ │ │ │ └── useLabelWidth.ts │ │ │ │ ├── props.ts │ │ │ │ └── types │ │ │ │ ├── form.ts │ │ │ │ ├── formItem.ts │ │ │ │ ├── hooks.ts │ │ │ │ └── index.ts │ │ ├── icon │ │ │ ├── data │ │ │ │ └── icons.data.ts │ │ │ ├── index.ts │ │ │ └── src │ │ │ │ └── IconPicker.vue │ │ ├── loading │ │ │ ├── index.ts │ │ │ └── src │ │ │ │ ├── Loading.vue │ │ │ │ ├── createLoading.ts │ │ │ │ ├── typing.ts │ │ │ │ └── useLoading.ts │ │ ├── menu │ │ │ ├── index.ts │ │ │ └── src │ │ │ │ ├── BasicMenu.vue │ │ │ │ ├── components │ │ │ │ ├── BasicMenuItem.vue │ │ │ │ ├── BasicSubMenuItem.vue │ │ │ │ └── MenuItemContent.vue │ │ │ │ ├── index.less │ │ │ │ ├── props.ts │ │ │ │ ├── types.ts │ │ │ │ └── useOpenKeys.ts │ │ ├── modal │ │ │ ├── index.ts │ │ │ └── src │ │ │ │ ├── BasicModal.vue │ │ │ │ ├── components │ │ │ │ ├── Modal.tsx │ │ │ │ ├── ModalClose.vue │ │ │ │ ├── ModalFooter.vue │ │ │ │ ├── ModalHeader.vue │ │ │ │ └── ModalWrapper.vue │ │ │ │ ├── hooks │ │ │ │ ├── useModal.ts │ │ │ │ ├── useModalContext.ts │ │ │ │ ├── useModalDrag.ts │ │ │ │ └── useModalFullScreen.ts │ │ │ │ ├── index.less │ │ │ │ ├── props.ts │ │ │ │ └── typing.ts │ │ ├── page │ │ │ ├── index.ts │ │ │ └── src │ │ │ │ ├── PageFooter.vue │ │ │ │ ├── PageWrapper.vue │ │ │ │ └── useContentHeight.ts │ │ ├── scrollbar │ │ │ ├── index.ts │ │ │ └── src │ │ │ │ ├── Scrollbar.vue │ │ │ │ ├── bar.ts │ │ │ │ ├── types.d.ts │ │ │ │ └── util.ts │ │ ├── simple-menu │ │ │ ├── index.ts │ │ │ └── src │ │ │ │ ├── SimpleMenu.vue │ │ │ │ ├── SimpleMenuTag.vue │ │ │ │ ├── SimpleSubMenu.vue │ │ │ │ ├── components │ │ │ │ ├── Menu.vue │ │ │ │ ├── MenuCollapseTransition.vue │ │ │ │ ├── MenuItem.vue │ │ │ │ ├── SubMenuItem.vue │ │ │ │ ├── menu.less │ │ │ │ ├── types.ts │ │ │ │ ├── useMenu.ts │ │ │ │ └── useSimpleMenuContext.ts │ │ │ │ ├── index.less │ │ │ │ ├── types.ts │ │ │ │ └── useOpenKeys.ts │ │ └── table │ │ │ ├── index.ts │ │ │ └── src │ │ │ ├── BasicTable.vue │ │ │ ├── componentMap.ts │ │ │ ├── components │ │ │ ├── EditTableHeaderIcon.vue │ │ │ ├── HeaderCell.vue │ │ │ ├── TableAction.vue │ │ │ ├── TableFooter.vue │ │ │ ├── TableHeader.vue │ │ │ ├── TableImg.vue │ │ │ ├── TableTitle.vue │ │ │ ├── editable │ │ │ │ ├── CellComponent.ts │ │ │ │ ├── EditableCell.vue │ │ │ │ ├── helper.ts │ │ │ │ └── index.ts │ │ │ └── settings │ │ │ │ ├── ColumnSetting.vue │ │ │ │ ├── FullScreenSetting.vue │ │ │ │ ├── RedoSetting.vue │ │ │ │ ├── SizeSetting.vue │ │ │ │ └── index.vue │ │ │ ├── const.ts │ │ │ ├── hooks │ │ │ ├── useColumns.ts │ │ │ ├── useCustomRow.ts │ │ │ ├── useDataSource.ts │ │ │ ├── useLoading.ts │ │ │ ├── usePagination.tsx │ │ │ ├── useRowSelection.ts │ │ │ ├── useScrollTo.ts │ │ │ ├── useTable.ts │ │ │ ├── useTableContext.ts │ │ │ ├── useTableExpand.ts │ │ │ ├── useTableFooter.ts │ │ │ ├── useTableForm.ts │ │ │ ├── useTableHeader.ts │ │ │ ├── useTableScroll.ts │ │ │ └── useTableStyle.ts │ │ │ ├── props.ts │ │ │ └── types │ │ │ ├── column.ts │ │ │ ├── componentType.ts │ │ │ ├── pagination.ts │ │ │ ├── table.ts │ │ │ └── tableAction.ts │ ├── global-components.d.ts │ ├── hooks │ │ ├── component │ │ │ ├── use-form-item.ts │ │ │ └── use-page-context.ts │ │ ├── event │ │ │ ├── use-breakpoint.ts │ │ │ ├── use-event-listener.ts │ │ │ └── use-scroll-to.ts │ │ ├── setting │ │ │ ├── useHeaderSetting.ts │ │ │ ├── useMenuSetting.ts │ │ │ ├── useMultipleTabSetting.ts │ │ │ └── useRootSetting.ts │ │ └── web │ │ │ ├── use-app-inject.ts │ │ │ ├── use-echarts │ │ │ ├── echarts.ts │ │ │ └── index.ts │ │ │ ├── use-tabs.ts │ │ │ ├── useContextMenu.ts │ │ │ ├── useCopyToClipboard.ts │ │ │ ├── useDesign.ts │ │ │ ├── useFullContent.ts │ │ │ ├── useLockPage.ts │ │ │ ├── useMessage.tsx │ │ │ ├── usePage.ts │ │ │ ├── usePermission.ts │ │ │ └── useSortable.ts │ ├── init-packages.ts │ ├── internal │ │ ├── component.ts │ │ ├── config.ts │ │ ├── factory │ │ │ ├── component-factory.ts │ │ │ └── index.ts │ │ ├── index.ts │ │ └── pinia │ │ │ ├── index.ts │ │ │ └── persist.ts │ ├── layouts │ │ ├── default │ │ │ ├── content │ │ │ │ ├── index.vue │ │ │ │ ├── useContentContext.ts │ │ │ │ └── useContentViewHeight.ts │ │ │ ├── feature │ │ │ │ └── index.vue │ │ │ ├── footer │ │ │ │ └── index.vue │ │ │ ├── header │ │ │ │ ├── MultipleHeader.vue │ │ │ │ ├── components │ │ │ │ │ ├── Breadcrumb.vue │ │ │ │ │ ├── ErrorAction.vue │ │ │ │ │ ├── FullScreen.vue │ │ │ │ │ ├── index.ts │ │ │ │ │ ├── lock │ │ │ │ │ │ └── LockModal.vue │ │ │ │ │ ├── notify │ │ │ │ │ │ ├── NoticeList.vue │ │ │ │ │ │ ├── data.ts │ │ │ │ │ │ └── index.vue │ │ │ │ │ └── user-dropdown │ │ │ │ │ │ ├── DropMenuItem.vue │ │ │ │ │ │ └── index.vue │ │ │ │ ├── index.less │ │ │ │ └── index.vue │ │ │ ├── index.vue │ │ │ ├── menu │ │ │ │ ├── index.vue │ │ │ │ └── useLayoutMenu.ts │ │ │ ├── setting │ │ │ │ ├── SettingDrawer.tsx │ │ │ │ ├── components │ │ │ │ │ ├── InputNumberItem.vue │ │ │ │ │ ├── SelectItem.vue │ │ │ │ │ ├── SettingFooter.vue │ │ │ │ │ ├── SwitchItem.vue │ │ │ │ │ ├── ThemeColorPicker.vue │ │ │ │ │ ├── TypePicker.vue │ │ │ │ │ └── index.ts │ │ │ │ ├── enum.ts │ │ │ │ ├── handler.ts │ │ │ │ └── index.vue │ │ │ ├── sider │ │ │ │ ├── DragBar.vue │ │ │ │ ├── LayoutSider.vue │ │ │ │ ├── MixSider.vue │ │ │ │ ├── index.vue │ │ │ │ └── useLayoutSider.ts │ │ │ ├── tabs │ │ │ │ ├── components │ │ │ │ │ ├── FoldButton.vue │ │ │ │ │ ├── TabContent.vue │ │ │ │ │ └── TabRedo.vue │ │ │ │ ├── index.less │ │ │ │ ├── index.vue │ │ │ │ ├── types.ts │ │ │ │ ├── useMultipleTabs.ts │ │ │ │ └── useTabDropdown.ts │ │ │ └── trigger │ │ │ │ ├── HeaderTrigger.vue │ │ │ │ ├── SiderTrigger.vue │ │ │ │ └── index.vue │ │ ├── iframe │ │ │ ├── index.vue │ │ │ └── use-frame-keepalive.ts │ │ └── page │ │ │ └── index.vue │ ├── logics │ │ ├── init-app-config.ts │ │ ├── mitt │ │ │ └── route-change.ts │ │ └── theme │ │ │ ├── dark.ts │ │ │ ├── index.ts │ │ │ ├── theme.ts │ │ │ ├── update-background.ts │ │ │ ├── update-color-weak.ts │ │ │ ├── update-gray-mode.ts │ │ │ └── util.ts │ ├── main.ts │ ├── router │ │ ├── constant.ts │ │ ├── guard │ │ │ ├── index.ts │ │ │ ├── param-menu.ts │ │ │ ├── permission.ts │ │ │ └── state.ts │ │ ├── helper │ │ │ ├── menu.ts │ │ │ └── route.ts │ │ ├── index.ts │ │ ├── menus │ │ │ └── index.ts │ │ ├── routes │ │ │ ├── backend │ │ │ │ └── static-menus.ts │ │ │ ├── basic.ts │ │ │ ├── index.ts │ │ │ ├── mainOut.ts │ │ │ └── modules │ │ │ │ ├── about.ts │ │ │ │ ├── amis.ts │ │ │ │ ├── crm │ │ │ │ └── index.ts │ │ │ │ ├── dashboard.ts │ │ │ │ ├── develop.ts │ │ │ │ └── system.ts │ │ └── types.ts │ ├── store │ │ ├── app.ts │ │ ├── error-log.ts │ │ ├── lock.ts │ │ ├── multiple-tab.ts │ │ ├── permission.ts │ │ └── user.ts │ ├── styles │ │ ├── ant │ │ │ ├── amis_override.less │ │ │ ├── index.less │ │ │ ├── pagination.less │ │ │ └── table.less │ │ ├── color.less │ │ ├── config.less │ │ ├── index.less │ │ ├── index.ts │ │ ├── public.less │ │ ├── tailwind.css │ │ ├── theme.less │ │ ├── transition.less │ │ └── var │ │ │ ├── breakpoint.less │ │ │ ├── easing.less │ │ │ └── index.less │ └── views │ │ ├── CRM │ │ └── Customer │ │ │ ├── EditModal.vue │ │ │ ├── data.ts │ │ │ └── index.vue │ │ ├── DynamicPage │ │ ├── EditContentTypeDrawer.vue │ │ ├── EditModal.vue │ │ └── index.vue │ │ ├── amis │ │ ├── AmisDynamic.vue │ │ ├── Editor.vue │ │ ├── GenCrud.ts │ │ ├── GenFromType.json │ │ ├── GenFromType.vue │ │ ├── index.json │ │ ├── index.vue │ │ └── schematpls │ │ │ ├── crud.json │ │ │ └── formItem_contentPicker.json │ │ ├── dashboard │ │ ├── analysis │ │ │ ├── components │ │ │ │ ├── GrowCard.vue │ │ │ │ ├── SalesProductPie.vue │ │ │ │ ├── SiteAnalysis.vue │ │ │ │ ├── VisitAnalysis.vue │ │ │ │ ├── VisitAnalysisBar.vue │ │ │ │ ├── VisitRadar.vue │ │ │ │ ├── VisitSource.vue │ │ │ │ └── props.ts │ │ │ ├── data.ts │ │ │ └── index.vue │ │ └── workbench │ │ │ ├── components │ │ │ ├── DynamicInfo.vue │ │ │ ├── ProjectCard.vue │ │ │ ├── QuickNav.vue │ │ │ ├── SaleRadar.vue │ │ │ ├── WorkbenchHeader.vue │ │ │ └── data.ts │ │ │ └── index.vue │ │ ├── develop │ │ ├── contentType │ │ │ ├── EditContentTypeDrawer.vue │ │ │ ├── data.ts │ │ │ ├── dynamicIndex.json │ │ │ ├── dynamicIndex.vue │ │ │ └── index.vue │ │ ├── listManagement │ │ │ ├── ListDetails.vue │ │ │ ├── data.ts │ │ │ ├── index.vue │ │ │ └── listPreview.vue │ │ └── menu │ │ │ ├── MenuDrawer.vue │ │ │ ├── index.vue │ │ │ └── menu.data.ts │ │ ├── sys │ │ ├── about │ │ │ └── index.vue │ │ ├── exception │ │ │ └── index.vue │ │ ├── iframe │ │ │ ├── FrameBlank.vue │ │ │ └── index.vue │ │ ├── lock │ │ │ ├── index.vue │ │ │ ├── lock-page.vue │ │ │ └── useNow.ts │ │ ├── login │ │ │ ├── forget-password-form.vue │ │ │ ├── login copy.vue │ │ │ ├── login-form copy.vue │ │ │ ├── login-form-title.vue │ │ │ ├── login-form.vue │ │ │ ├── login.vue │ │ │ ├── loginCallback.vue │ │ │ ├── logoutcallback.vue │ │ │ ├── mobile-form.vue │ │ │ ├── qrcode-form.vue │ │ │ ├── register-form.vue │ │ │ ├── session-timeout.vue │ │ │ └── use-login.ts │ │ └── redirect │ │ │ └── index.vue │ │ └── system │ │ ├── account │ │ ├── AccountDetail.vue │ │ ├── AccountModal.json │ │ ├── AccountModal.vue │ │ ├── DeptTree.vue │ │ ├── account.data.ts │ │ ├── account.json │ │ ├── index copy.vue │ │ └── index.vue │ │ ├── dept │ │ ├── DeptModal.vue │ │ ├── dept.data.ts │ │ └── index.vue │ │ ├── password │ │ ├── index.vue │ │ └── pwd.data.ts │ │ └── role │ │ ├── RoleDrawer.vue │ │ ├── index.vue │ │ └── role.data.ts │ ├── tailwind.config.js │ ├── tsconfig.json │ └── vite.config.ts ├── configs ├── css-preprocess │ ├── package.json │ ├── postcss.js │ └── tailwind.js ├── lint │ ├── commitlint.js │ ├── eslint.js │ ├── lintstaged.js │ ├── package.json │ ├── prettier.js │ └── stylelint.js ├── tsconfig │ ├── base.json │ ├── package.json │ └── server.json └── vite │ ├── build.config.ts │ ├── package.json │ ├── src │ ├── constants.ts │ ├── index.ts │ ├── plugins │ │ ├── compress.ts │ │ ├── html.ts │ │ ├── imagemin.ts │ │ ├── index.ts │ │ ├── mock.ts │ │ ├── svg-icons.ts │ │ └── visualizer.ts │ ├── presets │ │ ├── ant │ │ │ ├── index.ts │ │ │ ├── modify-vars.ts │ │ │ ├── theme-plugin.ts │ │ │ └── theme.ts │ │ └── index.ts │ └── utils │ │ └── index.ts │ └── tsconfig.json ├── nswag ├── Templates │ ├── AxiosClient.liquid │ ├── Client.Method.Documentation.liquid │ ├── Client.ProcessResponse.HandleStatusCode.liquid │ ├── Client.ProcessResponse.ReadBodyEnd.liquid │ ├── Client.ProcessResponse.ReadBodyStart.liquid │ ├── Client.ProcessResponse.ReadHeaders.liquid │ ├── Client.ProcessResponse.Return.liquid │ ├── Client.ProcessResponse.liquid │ ├── Client.RequestBody.liquid │ ├── Client.RequestUrl.liquid │ ├── File.Utilities.liquid │ └── File.liquid ├── refresh.bat └── service.config.nswag ├── package.json ├── packages ├── apis │ ├── account.ts │ ├── demo │ │ ├── account.ts │ │ ├── cascader.ts │ │ ├── error.ts │ │ ├── index.ts │ │ ├── select.ts │ │ ├── system.ts │ │ ├── table.ts │ │ └── tree.ts │ ├── develop.ts │ ├── eoc │ │ ├── app-service-base.ts │ │ ├── app-service-proxies.ts │ │ ├── contentApi.ts │ │ └── graphqlApi.ts │ ├── package.json │ ├── sys │ │ ├── index.ts │ │ ├── menu.ts │ │ ├── upload.ts │ │ └── user.ts │ ├── system.ts │ └── types.ts ├── components │ ├── antd │ │ └── package.json │ └── common │ │ ├── count-to │ │ └── index.vue │ │ ├── icon │ │ └── index.vue │ │ ├── index.ts │ │ ├── package.json │ │ ├── qrcode │ │ ├── draw-canvas.ts │ │ ├── draw-logo.ts │ │ ├── index.vue │ │ ├── to-canvas.ts │ │ └── typing.ts │ │ ├── svg-icon │ │ └── index.vue │ │ ├── time │ │ └── index.vue │ │ └── transition │ │ └── collapse-transition.vue ├── directives │ ├── bridge.ts │ ├── index.ts │ ├── package.json │ └── src │ │ ├── auth.ts │ │ ├── click-outside.ts │ │ └── loading.ts ├── locale │ ├── index.ts │ ├── package.json │ ├── src │ │ ├── helper.ts │ │ ├── lang │ │ │ ├── en.ts │ │ │ ├── en │ │ │ │ ├── common.ts │ │ │ │ ├── component.ts │ │ │ │ ├── layout.ts │ │ │ │ ├── routes │ │ │ │ │ ├── basic.ts │ │ │ │ │ ├── dashboard.ts │ │ │ │ │ ├── default.ts │ │ │ │ │ ├── demo.ts │ │ │ │ │ └── develop.ts │ │ │ │ └── sys.ts │ │ │ ├── zh-CN │ │ │ │ ├── common.ts │ │ │ │ ├── component.ts │ │ │ │ ├── layout.ts │ │ │ │ ├── routes │ │ │ │ │ ├── amis.ts │ │ │ │ │ ├── basic.ts │ │ │ │ │ ├── crm.ts │ │ │ │ │ ├── dashboard.ts │ │ │ │ │ ├── default.ts │ │ │ │ │ ├── demo.ts │ │ │ │ │ └── develop.ts │ │ │ │ └── sys.ts │ │ │ └── zh_CN.ts │ │ ├── setup-i18n.ts │ │ ├── store.ts │ │ ├── use-i18n.ts │ │ └── use-locale.ts │ └── tsconfig.json ├── request │ ├── bridge.ts │ ├── index.ts │ ├── package.json │ └── src │ │ ├── Axios.ts │ │ ├── axiosCancel.ts │ │ ├── axiosTransform.ts │ │ ├── checkStatus.ts │ │ ├── helper.ts │ │ └── index.ts ├── setting │ ├── index.ts │ ├── package.json │ └── src │ │ ├── component.ts │ │ ├── design.ts │ │ ├── index.ts │ │ ├── locale.ts │ │ ├── project.ts │ │ └── site.ts ├── styles │ ├── common │ │ ├── color.css │ │ ├── common.css │ │ ├── index.ts │ │ └── tailwind.css │ └── package.json ├── tokens │ ├── index.ts │ ├── package.json │ └── src │ │ ├── cache.ts │ │ ├── enums │ │ ├── breakpoint.ts │ │ ├── http.ts │ │ ├── index.ts │ │ └── menu.ts │ │ ├── index.ts │ │ ├── router.ts │ │ └── sidebar.ts ├── types │ ├── index.ts │ ├── package.json │ └── src │ │ ├── OrchardScripts │ │ ├── OCJavaScriptBackendMethods.ts │ │ └── OCLiquidFilters.md │ │ ├── config.ts │ │ ├── global.ts │ │ ├── index.ts │ │ ├── router.ts │ │ ├── service.ts │ │ ├── shims │ │ ├── index.ts │ │ ├── module.ts │ │ ├── pinia.ts │ │ └── vue-router.ts │ │ ├── store.ts │ │ └── util.ts ├── use │ ├── index.ts │ ├── package.json │ └── src │ │ ├── index.ts │ │ ├── use-attrs.ts │ │ ├── use-context.ts │ │ ├── use-pagination.ts │ │ ├── use-refs.ts │ │ ├── use-script.ts │ │ ├── use-title.ts │ │ ├── use-watermark.ts │ │ └── use-window-resize.ts └── utils │ ├── bem.ts │ ├── index.ts │ ├── package.json │ └── src │ ├── color.ts │ ├── config.ts │ ├── date.ts │ ├── deep-merge.ts │ ├── dom.ts │ ├── event.ts │ ├── file.ts │ ├── helper │ ├── index.ts │ ├── route.ts │ ├── slot.ts │ └── tree.ts │ ├── index.ts │ ├── is.ts │ ├── lifecycle.ts │ ├── log.ts │ ├── mitt.ts │ ├── util.ts │ ├── uuid.ts │ └── with-install.ts ├── pnpm-lock.yaml ├── pnpm-workspace.yaml ├── scripts ├── package.json └── src │ ├── build.ts │ ├── dev.ts │ └── helper.ts ├── turbo.json ├── vitest.config.ts └── 问题梳理.md /.changeset/README.md: -------------------------------------------------------------------------------- 1 | # Changesets 2 | 3 | Hello and welcome! This folder has been automatically generated by `@changesets/cli`, a build tool that works 4 | with multi-package repos, or single-package repos to help you version and publish your code. You can 5 | find the full documentation for it [in our repository](https://github.com/changesets/changesets) 6 | 7 | We have a quick list of common questions to get you started engaging with this project in 8 | [our documentation](https://github.com/changesets/changesets/blob/main/docs/common-questions.md) 9 | -------------------------------------------------------------------------------- /.changeset/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://unpkg.com/@changesets/config@1.6.3/schema.json", 3 | "changelog": "@changesets/cli/changelog", 4 | "commit": false, 5 | "linked": [], 6 | "access": "restricted", 7 | "baseBranch": "next", 8 | "updateInternalDependencies": "patch", 9 | "ignore": [] 10 | } 11 | -------------------------------------------------------------------------------- /.commitlintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = require('@config/lint/commitlint') 2 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | charset=utf-8 5 | end_of_line=lf 6 | insert_final_newline=true 7 | indent_style=space 8 | indent_size=2 9 | max_line_length = 100 10 | 11 | [*.{yml,yaml,json}] 12 | indent_style = space 13 | indent_size = 2 14 | 15 | [*.md] 16 | trim_trailing_whitespace = false 17 | 18 | [Makefile] 19 | indent_style = tab 20 | -------------------------------------------------------------------------------- /.eslintignore: -------------------------------------------------------------------------------- 1 | 2 | *.sh 3 | node_modules 4 | *.md 5 | *.woff 6 | *.ttf 7 | .vscode 8 | .idea 9 | dist 10 | public 11 | docs 12 | .husky 13 | .local 14 | bin 15 | Dockerfile 16 | -------------------------------------------------------------------------------- /.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = require('@config/lint/eslint') 2 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/2-feature.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: 🚀 Feature request 3 | about: Suggest an idea for this project 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | --- 8 | 9 | 17 | 18 | ### Subject of the feature 19 | 20 | Describe your issue here. 21 | 22 | ### Problem 23 | 24 | If the feature requests relates to a problem, please describe the problem you are trying to solve here. 25 | 26 | ### Expected behaviour 27 | 28 | What should happen? Please describe the desired behaviour. 29 | 30 | ### Alternatives 31 | 32 | What are the alternative solutions? Please describe what else you have considered? 33 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/3-bug-cn.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: 🐛 Bug 报告 3 | about: 向我们报告一个Bug以帮助我们改进 4 | title: '' 5 | labels: 'bug: pending triage' 6 | assignees: '' 7 | --- 8 | 9 | **⚠️ 重要 ⚠️ 在进一步操作之前,请检查下列选项。如果您忽视此模板或者没有提供关键信息,您的 Issue 将直接被关闭** 10 | 11 | - [ ] 已阅读 [文档](https://anncwb.github.io/vue-vben-admin-doc/). 12 | - [ ] 确保您的代码已是最新或者所报告的 Bug 在最新版本中可以重现. (部分 Bug 可能已经在最近的代码中修复) 13 | - [ ] 已在 Issues 中搜索了相关的关键词 14 | - [ ] 不是 ant design vue 组件库的 Bug 15 | 16 | ### 描述 Bug 17 | 18 | 请清晰地描述此 Bug 的具体表现。 19 | 20 | ### 复现 Bug 21 | 22 | 请描述在演示页面中复现 Bug 的详细步骤,以确保我们可以理解并定位问题。部分 Bug 如果未在 Demo 中涉及,请务必提供关键代码 23 | 24 | ## 系统信息 25 | 26 | - 操作系统: 27 | - Node 版本: 28 | - 包管理器 (npm/yarn/pnpm) 及其版本: 29 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/config.yml: -------------------------------------------------------------------------------- 1 | blank_issues_enabled: false 2 | contact_links: 3 | - name: Discord Chat 4 | url: https://discord.gg/8GuAdwDhj6 5 | about: Ask questions and discuss with other Vben users in real time. 6 | - name: Questions & Discussions 7 | url: https://github.com/anncwb/vue-vben-admin/discussions 8 | about: Use GitHub discussions for message-board style questions and discussions. 9 | -------------------------------------------------------------------------------- /.github/contributing.md: -------------------------------------------------------------------------------- 1 | # Contributing Guide 2 | 3 | 1. Make sure you put things in the right category! 4 | 2. Always add your items to the end of a list. To be fair, the order is first-come-first-serve. 5 | 3. If you think something belongs in the wrong category, or think there needs to be a new category, feel free to edit things too. 6 | -------------------------------------------------------------------------------- /.github/workflows/issue-close-require.yml: -------------------------------------------------------------------------------- 1 | name: Issue Close Require 2 | 3 | on: 4 | schedule: 5 | - cron: '0 0 * * *' 6 | 7 | jobs: 8 | close-issues: 9 | runs-on: ubuntu-latest 10 | steps: 11 | - name: need reproduction 12 | uses: actions-cool/issues-helper@v2.1.1 13 | with: 14 | actions: 'close-issues' 15 | token: ${{ secrets.OPER_TOKEN }} 16 | labels: 'need reproduction' 17 | inactive-day: 3 18 | -------------------------------------------------------------------------------- /.github/workflows/issue-labeled.yml: -------------------------------------------------------------------------------- 1 | name: Issue Labeled 2 | 3 | on: 4 | issues: 5 | types: [labeled] 6 | 7 | jobs: 8 | reply-labeled: 9 | runs-on: ubuntu-latest 10 | steps: 11 | - name: remove pending 12 | if: github.event.label.name == 'enhancement' || github.event.label.name == 'bug' 13 | uses: actions-cool/issues-helper@v2.1.1 14 | with: 15 | actions: 'remove-labels' 16 | token: ${{ secrets.OPER_TOKEN }} 17 | issue-number: ${{ github.event.issue.number }} 18 | labels: 'bug: pending triage' 19 | 20 | - name: need reproduction 21 | if: github.event.label.name == 'need reproduction' 22 | uses: actions-cool/issues-helper@v2.1.1 23 | with: 24 | actions: 'create-comment, remove-labels' 25 | token: ${{ secrets.OPER_TOKEN }} 26 | issue-number: ${{ github.event.issue.number }} 27 | body: | 28 | Hello @${{ github.event.issue.user.login }}. Please provide the complete reproduction steps and code. Issues labeled by `need reproduction` will be closed if no activities in 3 days. 29 | labels: 'bug: pending triage' 30 | -------------------------------------------------------------------------------- /.github/workflows/release.yml: -------------------------------------------------------------------------------- 1 | name: Create Release 2 | 3 | on: 4 | push: 5 | tags: 6 | - v* 7 | 8 | jobs: 9 | build: 10 | name: Create Release 11 | runs-on: ubuntu-latest 12 | steps: 13 | - name: Checkout code 14 | uses: actions/checkout@master 15 | 16 | - name: Create Release for Tag 17 | id: release_tag 18 | uses: yyx990803/release-tag@master 19 | env: 20 | GITHUB_TOKEN: ${{ secrets.OPER_TOKEN }} 21 | with: 22 | tag_name: ${{ github.ref }} 23 | body: | 24 | Please refer to [CHANGELOG.md](https://github.com/anncwb/vue-vben-admin/blob/main/CHANGELOG.md) for details. 25 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | .DS_Store 3 | dist 4 | *-dist 5 | .cache 6 | 7 | .turbo 8 | .local 9 | # local env files 10 | .env.local 11 | .env.*.local 12 | .eslintcache 13 | 14 | # Log files 15 | npm-debug.log* 16 | yarn-debug.log* 17 | yarn-error.log* 18 | .pnpm-debug.log* 19 | 20 | # Editor directories and files 21 | .idea 22 | # .vscode 23 | *.suo 24 | *.ntvs* 25 | *.njsproj 26 | *.sln 27 | *.sw? 28 | apps/ant-admin/public/amis-editor-renderer 29 | -------------------------------------------------------------------------------- /.gitpod.yml: -------------------------------------------------------------------------------- 1 | ports: 2 | - port: 3344 3 | onOpen: open-preview 4 | tasks: 5 | - init: pnpm install 6 | command: pnpm run dev 7 | -------------------------------------------------------------------------------- /.lintstagedrc.js: -------------------------------------------------------------------------------- 1 | module.exports = require('@config/lint/lintstaged') 2 | -------------------------------------------------------------------------------- /.npmrc: -------------------------------------------------------------------------------- 1 | shamefully-hoist = true 2 | ignore-workspace-root-check=true 3 | public-hoist-pattern[]=* 4 | -------------------------------------------------------------------------------- /.prettierignore: -------------------------------------------------------------------------------- 1 | dist 2 | node_modules 3 | public 4 | .local 5 | -------------------------------------------------------------------------------- /.prettierrc.js: -------------------------------------------------------------------------------- 1 | module.exports = require('@config/lint/prettier') 2 | -------------------------------------------------------------------------------- /.stylelintignore: -------------------------------------------------------------------------------- 1 | dist 2 | public 3 | node_modules 4 | -------------------------------------------------------------------------------- /.stylelintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = require('@config/lint/stylelint') 2 | -------------------------------------------------------------------------------- /.vscode/extensions.json: -------------------------------------------------------------------------------- 1 | { 2 | "recommendations": [ 3 | "vue.volar", 4 | "dbaeumer.vscode-eslint", 5 | "stylelint.vscode-stylelint", 6 | "esbenp.prettier-vscode", 7 | "mrmlnc.vscode-less", 8 | "lokalise.i18n-ally", 9 | "antfu.iconify", 10 | "mikestead.dotenv", 11 | "heybourn.headwind" 12 | ] 13 | } 14 | -------------------------------------------------------------------------------- /.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "0.2.0", 3 | "configurations": [ 4 | { 5 | "type": "vscode-edge-devtools.debug", 6 | "request": "attach", 7 | "name": "Attach to Microsoft Edge and open the Edge DevTools", 8 | "url": "http://localhost:8080", 9 | "webRoot": "${workspaceFolder}" 10 | }, 11 | { 12 | "type": "chrome", 13 | "request": "launch", 14 | "name": "Launch Chrome", 15 | "url": "http://localhost:3000", 16 | "webRoot": "${workspaceFolder}/src", 17 | "sourceMaps": true 18 | } 19 | ] 20 | } 21 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020-present, Vben 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | ## 基于 Vue Vben Admin 的OC中后台模板 3 | 4 | ### OIDC 授权 5 | - [x] 集成OC登录授权 6 | 7 | 8 | 9 | 10 | 以 vben admin next 分支为基础搭建的 OrchardCore SAP 前端框架 11 | 12 | 服务端:https://github.com/EasyOC/EasyOC 13 | 14 | QQ群:877196442 15 | ## 框架 16 | 17 | - [x] oidc password 授权登录 18 | - [ ] oidc code 授权登录 19 | 20 | 21 | ### 基础信息管理 22 | - [X] 用户列表 (动态属性) 23 | ![YX8TP2L7W%V )T7IWUKEW)3](https://user-images.githubusercontent.com/15613121/150072609-b25abb26-f3c9-4efe-b526-77e234c1309f.png) 24 | 25 | - [X] 用户列表部门筛选 (graphql+lucene) 26 | ![SC)RH3LX%FV}6FN99N 5Y U](https://user-images.githubusercontent.com/15613121/150072622-4c0f33fd-804c-48d1-bf72-976a764c0173.png) 27 | 28 | - [ ] 修改用户信息 (暂时用OC后台编辑,通过配置 UserProfile 类型实现动态属性) 29 | - [ ] 角色管理 30 | - [ ] 部门管理 31 | 32 | ### 通用功能 33 | - [ ] Excel 导入导出 34 | - [ ] 用户自定义列表顺序 (不同用户查看的不同列顺序) 35 | 36 | ### VbenAdmin 代码生成器/自动组件 37 | ![TCQ0DGL1BV2{BY{YT@0RXK](https://user-images.githubusercontent.com/15613121/155528839-093f9a80-761c-44ef-beaf-22ddd69c5a2e.jpg) 38 | ![$Q3K$A{)62MKXU2Y9{YDL0G](https://user-images.githubusercontent.com/15613121/155528861-818e611e-ca2e-428f-b4f8-edae751f806a.jpg) 39 | 40 | -------------------------------------------------------------------------------- /README.zh-CN.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EasyOC/EasyOC.VbenAdmin/4f711c4e480be3274e4ed6b68532834fd443acc3/README.zh-CN.md -------------------------------------------------------------------------------- /apps/amis/.env.development: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EasyOC/EasyOC.VbenAdmin/4f711c4e480be3274e4ed6b68532834fd443acc3/apps/amis/.env.development -------------------------------------------------------------------------------- /apps/amis/.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | 8 | # Runtime data 9 | pids 10 | *.pid 11 | *.seed 12 | *.pid.lock 13 | 14 | # Directory for instrumented libs generated by jscoverage/JSCover 15 | lib-cov 16 | 17 | # Coverage directory used by tools like istanbul 18 | coverage 19 | 20 | # nyc test coverage 21 | .nyc_output 22 | 23 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 24 | .grunt 25 | 26 | # Bower dependency directory (https://bower.io/) 27 | bower_components 28 | 29 | # node-waf configuration 30 | .lock-wscript 31 | 32 | # Compiled binary addons (https://nodejs.org/api/addons.html) 33 | build/Release 34 | 35 | # Dependency directories 36 | node_modules/ 37 | jspm_packages/ 38 | 39 | # TypeScript v1 declaration files 40 | typings/ 41 | 42 | # Optional npm cache directory 43 | .npm 44 | 45 | # Optional eslint cache 46 | .eslintcache 47 | 48 | # Optional REPL history 49 | .node_repl_history 50 | 51 | # Output of 'npm pack' 52 | *.tgz 53 | 54 | # Yarn Integrity file 55 | .yarn-integrity 56 | 57 | # dotenv environment variables file 58 | .env 59 | 60 | # next.js build output 61 | .next 62 | 63 | gh-pages 64 | /public 65 | 66 | package-lock.json -------------------------------------------------------------------------------- /apps/amis/.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "printWidth": 120, 3 | "tabWidth": 4, 4 | "useTabs": false, 5 | "singleQuote": true, 6 | "semi": true, 7 | "trailingComma": "none", 8 | "bracketSpacing": false, 9 | "arrowParens": "avoid", 10 | "jsxBracketSameLine": false 11 | } 12 | -------------------------------------------------------------------------------- /apps/amis/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM node:14.16.0-alpine3.12 2 | 3 | RUN mkdir -p /etc/amis-editor 4 | 5 | WORKDIR /etc/amis-editor 6 | 7 | COPY . . 8 | 9 | EXPOSE 8082 10 | 11 | ENTRYPOINT [ "npm", "run", "server" ] 12 | -------------------------------------------------------------------------------- /apps/amis/auth/login.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 正在登陆... 8 | 9 | 10 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /apps/amis/auth/login.tsx: -------------------------------------------------------------------------------- 1 | import authService from "route/auth/authService"; 2 | export function bootstrap() { 3 | authService.login() 4 | } 5 | -------------------------------------------------------------------------------- /apps/amis/auth/logincallback.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 |
14 | 15 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /apps/amis/auth/logincallback.tsx: -------------------------------------------------------------------------------- 1 | import authService from 'route/auth/authService'; 2 | export function bootstrap() { 3 | authService.completeLogin().then(() => { 4 | if (window.opener) { 5 | if (window.localStorage.getItem('needReload') == '1') { 6 | window.localStorage.removeItem('needReload'); 7 | const returnUrl = window.localStorage.getItem('returnUrl'); 8 | if (returnUrl) { 9 | window.localStorage.removeItem('returnUrl'); 10 | window.location.href = returnUrl; 11 | // } else { 12 | // window.opener.location.reload(); 13 | } 14 | } 15 | // window.close(); 16 | } 17 | }); 18 | } 19 | -------------------------------------------------------------------------------- /apps/amis/deploy-gh-pages.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -e 3 | 4 | if [ -z "$(git status --porcelain)" ]; then 5 | # Working directory clean 6 | echo "Working directory clean" 7 | else 8 | # Uncommitted changes 9 | read -p "You got uncommitted changes, press y to continue? " -n 1 -r 10 | echo # (optional) move to a new line 11 | if [[ ! $REPLY =~ ^[Yy]$ ]]; then 12 | echo "Skiped!" 13 | [[ "$0" == "$BASH_SOURCE" ]] && exit 1 || return 1 # handle exits from shell or function but don't exit interactive shell 14 | fi 15 | fi 16 | 17 | rm -rf gh-pages 18 | 19 | fis3 release gh-pages -c 20 | 21 | node ./upload2cdn.js $1 22 | 23 | git add gh-pages -f 24 | 25 | git commit -m "更新 gh-pages" 26 | 27 | git push 28 | 29 | git subtree push --prefix gh-pages origin gh-pages 30 | 31 | git commit -m 'rebuild pages' --allow-empty 32 | 33 | git push origin 34 | 35 | echo "done" 36 | -------------------------------------------------------------------------------- /apps/amis/index.tsx: -------------------------------------------------------------------------------- 1 | /** 2 | * @file entry of this example. 3 | */ 4 | import React from 'react'; 5 | import ReactDom from 'react-dom'; 6 | import authService from 'route/auth/authService'; 7 | import App from './App'; 8 | 9 | export function bootstrap(mountTo: HTMLElement) { 10 | // new login().login().then(() => { 11 | // console.log("authService.completeLogin()"); 12 | // }) 13 | // authService.signinPopup(); 14 | ReactDom.render(, mountTo); 15 | } 16 | -------------------------------------------------------------------------------- /apps/amis/renderer/MyRenderer.tsx: -------------------------------------------------------------------------------- 1 | import {Renderer} from 'amis'; 2 | import { RendererProps } from 'amis/lib/factory'; 3 | import React from 'react'; 4 | 5 | export interface MyRendererProps extends RendererProps { 6 | target?: string; 7 | } 8 | 9 | @Renderer({ 10 | test: /\bmy-renderer$/, 11 | name: 'my-renderer' 12 | }) 13 | export default class MyRenderer extends React.Component { 14 | static defaultProps = { 15 | target: 'world' 16 | } 17 | 18 | render() { 19 | const { 20 | target 21 | } = this.props; 22 | 23 | return ( 24 |

Hello {target}!

25 | ); 26 | } 27 | } -------------------------------------------------------------------------------- /apps/amis/route/NotFound.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import {Link} from 'react-router-dom'; 3 | import {NotFound} from 'amis'; 4 | 5 | export default () => ( 6 | 9 | 10 | 11 | 去首页 12 | 13 | } 14 | footerText={''} 15 | /> 16 | ); 17 | -------------------------------------------------------------------------------- /apps/amis/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../tsconfig.json", 3 | "compilerOptions": { 4 | "baseUrl": ".", 5 | "outDir": "output", 6 | "module": "commonjs", 7 | "target": "es5", 8 | "lib": ["es6", "dom"], 9 | "sourceMap": true, 10 | "jsx": "react", 11 | "moduleResolution": "node", 12 | "rootDir": "./", 13 | "noImplicitReturns": true, 14 | "noImplicitThis": true, 15 | "noImplicitAny": true, 16 | "strictNullChecks": true, 17 | "experimentalDecorators": true, 18 | "emitDecoratorMetadata": true, 19 | "allowSyntheticDefaultImports": true, 20 | "typeRoots": ["./node_modules/@types", "./typings"] 21 | }, 22 | "include": ["**/*"], 23 | "exclude": ["node_modules", "build", "scripts", "acceptance-tests", "webpack", "jest", "src/setupTests.ts"], 24 | "types": ["typePatches"] 25 | } 26 | -------------------------------------------------------------------------------- /apps/ant-admin/.env: -------------------------------------------------------------------------------- 1 | # spa title 2 | VITE_GLOB_APP_TITLE = EasyOC Admin 3 | 4 | # spa shortname 5 | VITE_GLOB_APP_SHORT_NAME = easyocvben 6 | -------------------------------------------------------------------------------- /apps/ant-admin/.env.development: -------------------------------------------------------------------------------- 1 | # Whether to open mock 2 | VITE_USE_MOCK = false 3 | 4 | # public path 5 | VITE_PUBLIC_PATH = / 6 | 7 | # Cross-domain proxy, you can configure multiple 8 | # Please note that no line breaks 9 | # VITE_PROXY = [["/basic-api","http://localhost:3000"],["/upload","http://localhost:3300/upload"]] 10 | # VITE_PROXY=[["/api","https://vvbin.cn/test"]] 11 | 12 | VITE_USE_PWA = true 13 | # Delete console 14 | VITE_DROP_CONSOLE = false 15 | 16 | # Basic interface address SPA 17 | VITE_GLOB_API_URL='http://localhost:2919' 18 | 19 | # Basic interface address OTHERAPI 20 | VITE_GLOB_OTHERAPI_URL='http://localhost:2919' 21 | 22 | # File upload address, optional 23 | VITE_GLOB_UPLOAD_URL=/upload 24 | 25 | VITE_GLOB_amisEditor = 'http://localhost:8082/' 26 | VITE_GLOB_OIDC_clientRoot = 'http://localhost:3000/' 27 | VITE_GLOB_OIDC_stsAuthority = 'http://localhost:2919/' 28 | VITE_GLOB_OIDC_CLIENTID='vue_client_app' 29 | 30 | # Interface prefix 31 | VITE_GLOB_API_URL_PREFIX= 32 | 33 | 34 | -------------------------------------------------------------------------------- /apps/ant-admin/.env.production: -------------------------------------------------------------------------------- 1 | # Whether to open mock 2 | VITE_USE_MOCK = false 3 | 4 | # public path 5 | VITE_PUBLIC_PATH = / 6 | 7 | # Delete console 8 | VITE_DROP_CONSOLE = true 9 | 10 | # Whether to enable gzip or brotli compression 11 | # Optional: gzip | brotli | none 12 | # If you need multiple forms, you can use `,` to separate 13 | VITE_BUILD_COMPRESS = 'none' 14 | 15 | # Whether to delete origin files when using compress, default false 16 | VITE_BUILD_COMPRESS_DELETE_ORIGIN_FILE = false 17 | 18 | # Basic interface address SPA 19 | VITE_GLOB_API_URL='https://easyoc.netabp.com' 20 | 21 | # File upload address, optional 22 | # It can be forwarded by nginx or write the actual address directly 23 | VITE_GLOB_UPLOAD_URL=/upload 24 | 25 | # Interface prefix 26 | VITE_GLOB_API_URL_PREFIX= 27 | 28 | # Whether to enable image compression 29 | VITE_USE_IMAGEMIN= true 30 | 31 | # use pwa 32 | # VITE_USE_PWA = false 33 | 34 | # Is it compatible with older browsers 35 | # VITE_LEGACY = false 36 | VITE_GLOB_amisEditor = 'https://easyoc.netabp.com/' 37 | VITE_GLOB_OIDC_CLIENTID='vue_client_app' 38 | VITE_GLOB_OTHERAPI_URL='https://easyoc.netabp.com/' 39 | VITE_GLOB_OIDC_clientRoot = 'https://easyocvben.netabp.com/' 40 | VITE_GLOB_OIDC_stsAuthority = 'https://easyoc.netabp.com/' 41 | -------------------------------------------------------------------------------- /apps/ant-admin/.env.staging: -------------------------------------------------------------------------------- 1 | # Whether to open mock 2 | VITE_USE_MOCK = true 3 | NODE_ENV=staging 4 | # public path 5 | VITE_PUBLIC_PATH = / 6 | 7 | # Cross-domain proxy, you can configure multiple 8 | # Please note that no line breaks 9 | # VITE_PROXY = [["/basic-api","http://localhost:3000"],["/upload","http://localhost:3300/upload"]] 10 | # VITE_PROXY=[["/api","https://vvbin.cn/test"]] 11 | 12 | # Delete console 13 | VITE_DROP_CONSOLE = false 14 | 15 | # Basic interface address SPA 16 | VITE_GLOB_API_URL='https://easyoc.netabp.com' 17 | 18 | # Basic interface address OTHERAPI 19 | VITE_GLOB_OTHERAPI_URL='https://easyoc.netabp.com' 20 | 21 | # File upload address, optional 22 | VITE_GLOB_UPLOAD_URL=/upload 23 | 24 | VITE_GLOB_OIDC_clientRoot = 'http://localhost:3000/' 25 | VITE_GLOB_OIDC_stsAuthority = 'https://easyoc.netabp.com/' 26 | VITE_GLOB_OIDC_CLIENTID='vue_client_app' 27 | 28 | # Interface prefix 29 | VITE_GLOB_API_URL_PREFIX= 30 | 31 | 32 | -------------------------------------------------------------------------------- /apps/ant-admin/.env.test: -------------------------------------------------------------------------------- 1 | NODE_ENV=production 2 | 3 | # Whether to open mock 4 | VITE_USE_MOCK = true 5 | 6 | # public path 7 | VITE_PUBLIC_PATH = / 8 | 9 | # Delete console 10 | VITE_DROP_CONSOLE = true 11 | 12 | # Whether to enable gzip or brotli compression 13 | # Optional: gzip | brotli | none 14 | # If you need multiple forms, you can use `,` to separate 15 | VITE_BUILD_COMPRESS = 'none' 16 | 17 | # Whether to delete origin files when using compress, default false 18 | VITE_BUILD_COMPRESS_DELETE_ORIGIN_FILE = false 19 | 20 | # Basic interface address SPA 21 | VITE_GLOB_API_URL=/basic-api 22 | 23 | # File upload address, optional 24 | # It can be forwarded by nginx or write the actual address directly 25 | VITE_GLOB_UPLOAD_URL=/upload 26 | 27 | # Whether to enable image compression 28 | VITE_USE_IMAGEMIN= true 29 | 30 | # use pwa 31 | VITE_USE_PWA = false 32 | 33 | # Is it compatible with older browsers 34 | VITE_LEGACY = false 35 | -------------------------------------------------------------------------------- /apps/ant-admin/mock/_mock-server.ts: -------------------------------------------------------------------------------- 1 | import { createProdMockServer } from 'vite-plugin-mock/es/createProdMockServer' 2 | 3 | const modules = import.meta.globEager('./**/*.ts') 4 | 5 | const mockModules: any[] = [] 6 | Object.keys(modules).forEach((key) => { 7 | if (key.includes('/_')) { 8 | return 9 | } 10 | mockModules.push(...modules[key].default) 11 | }) 12 | 13 | /** 14 | * Used in a production environment. Need to manually import all modules 15 | */ 16 | export const setupProdMockServer = () => createProdMockServer(mockModules) 17 | -------------------------------------------------------------------------------- /apps/ant-admin/mock/demo/select-demo.ts: -------------------------------------------------------------------------------- 1 | import { MockMethod } from 'vite-plugin-mock' 2 | import { resultSuccess } from '../_util' 3 | 4 | const demoList = (keyword, count = 20) => { 5 | const result = { 6 | list: [] as any[], 7 | } 8 | for (let index = 0; index < count; index++) { 9 | result.list.push({ 10 | name: `${keyword ?? ''}选项${index}`, 11 | id: `${index}`, 12 | }) 13 | } 14 | return result 15 | } 16 | 17 | export default [ 18 | { 19 | url: '/basic-api/select/getDemoOptions', 20 | timeout: 1000, 21 | method: 'get', 22 | response: ({ query }) => { 23 | const { keyword, count } = query 24 | console.log(keyword) 25 | return resultSuccess(demoList(keyword, count)) 26 | }, 27 | }, 28 | ] as MockMethod[] 29 | -------------------------------------------------------------------------------- /apps/ant-admin/mock/demo/tree-demo.ts: -------------------------------------------------------------------------------- 1 | import { MockMethod } from 'vite-plugin-mock' 2 | import { resultSuccess } from '../_util' 3 | 4 | const demoTreeList = (keyword) => { 5 | const result = { 6 | list: [] as Recordable[], 7 | } 8 | for (let index = 0; index < 5; index++) { 9 | const children: Recordable[] = [] 10 | for (let j = 0; j < 3; j++) { 11 | children.push({ 12 | title: `${keyword ?? ''}选项${index}-${j}`, 13 | value: `${index}-${j}`, 14 | key: `${index}-${j}`, 15 | }) 16 | } 17 | result.list.push({ 18 | title: `${keyword ?? ''}选项${index}`, 19 | value: `${index}`, 20 | key: `${index}`, 21 | children, 22 | }) 23 | } 24 | return result 25 | } 26 | 27 | export default [ 28 | { 29 | url: '/basic-api/tree/getDemoOptions', 30 | timeout: 1000, 31 | method: 'get', 32 | response: ({ query }) => { 33 | const { keyword } = query 34 | console.log(keyword) 35 | return resultSuccess(demoTreeList(keyword)) 36 | }, 37 | }, 38 | ] as MockMethod[] 39 | -------------------------------------------------------------------------------- /apps/ant-admin/postcss.config.js: -------------------------------------------------------------------------------- 1 | module.exports = require('@config/css-preprocess/postcss') 2 | -------------------------------------------------------------------------------- /apps/ant-admin/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EasyOC/EasyOC.VbenAdmin/4f711c4e480be3274e4ed6b68532834fd443acc3/apps/ant-admin/public/favicon.ico -------------------------------------------------------------------------------- /apps/ant-admin/public/img/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EasyOC/EasyOC.VbenAdmin/4f711c4e480be3274e4ed6b68532834fd443acc3/apps/ant-admin/public/img/logo.png -------------------------------------------------------------------------------- /apps/ant-admin/public/resource/img/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EasyOC/EasyOC.VbenAdmin/4f711c4e480be3274e4ed6b68532834fd443acc3/apps/ant-admin/public/resource/img/logo.png -------------------------------------------------------------------------------- /apps/ant-admin/public/resource/img/pwa-192x192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EasyOC/EasyOC.VbenAdmin/4f711c4e480be3274e4ed6b68532834fd443acc3/apps/ant-admin/public/resource/img/pwa-192x192.png -------------------------------------------------------------------------------- /apps/ant-admin/public/resource/img/pwa-512x512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EasyOC/EasyOC.VbenAdmin/4f711c4e480be3274e4ed6b68532834fd443acc3/apps/ant-admin/public/resource/img/pwa-512x512.png -------------------------------------------------------------------------------- /apps/ant-admin/public/resource/tinymce/skins/ui/oxide-dark/content.mobile.min.css: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Tiny Technologies, Inc. All rights reserved. 3 | * Licensed under the LGPL or a commercial license. 4 | * For LGPL see License.txt in the project root for license information. 5 | * For commercial licenses see https://www.tiny.cloud/ 6 | */ 7 | .tinymce-mobile-unfocused-selections .tinymce-mobile-unfocused-selection{position: absolute;display: inline-block;background-color: green;opacity: .5;} 8 | 9 | body{-webkit-text-size-adjust: none;} 10 | 11 | body img{max-width: 96vw;} 12 | 13 | body table img{max-width: 95%;} 14 | 15 | body{font-family: sans-serif;} 16 | 17 | table{border-collapse: collapse;} 18 | -------------------------------------------------------------------------------- /apps/ant-admin/public/resource/tinymce/skins/ui/oxide/content.mobile.min.css: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Tiny Technologies, Inc. All rights reserved. 3 | * Licensed under the LGPL or a commercial license. 4 | * For LGPL see License.txt in the project root for license information. 5 | * For commercial licenses see https://www.tiny.cloud/ 6 | */ 7 | .tinymce-mobile-unfocused-selections .tinymce-mobile-unfocused-selection{position: absolute;display: inline-block;background-color: green;opacity: .5;} 8 | 9 | body{-webkit-text-size-adjust: none;} 10 | 11 | body img{max-width: 96vw;} 12 | 13 | body table img{max-width: 95%;} 14 | 15 | body{font-family: sans-serif;} 16 | 17 | table{border-collapse: collapse;} 18 | -------------------------------------------------------------------------------- /apps/ant-admin/public/resource/tinymce/skins/ui/oxide/fonts/tinymce-mobile.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EasyOC/EasyOC.VbenAdmin/4f711c4e480be3274e4ed6b68532834fd443acc3/apps/ant-admin/public/resource/tinymce/skins/ui/oxide/fonts/tinymce-mobile.woff -------------------------------------------------------------------------------- /apps/ant-admin/scripts/post-build.ts: -------------------------------------------------------------------------------- 1 | // #!/usr/bin/env node 2 | 3 | import { runBuildConfig } from './build-config' 4 | import { cyan, red } from 'picocolors' 5 | import pkg from '../package.json' 6 | 7 | export const runBuild = async () => { 8 | try { 9 | const argvList = process.argv.splice(2) 10 | 11 | // Generate configuration file 12 | if (!argvList.includes('disabled-config')) { 13 | runBuildConfig() 14 | } 15 | 16 | console.log(`✨ ${cyan(`[${pkg.name}]`)}` + ' - build successfully!') 17 | } catch (error) { 18 | console.log(red('vite build error:\n' + error)) 19 | process.exit(1) 20 | } 21 | } 22 | runBuild() 23 | -------------------------------------------------------------------------------- /apps/ant-admin/src/api/ocUtils.ts: -------------------------------------------------------------------------------- 1 | import { FormSchema } from "@/components/form" 2 | import { clone, get, has, set } from "@pkg/utils" 3 | 4 | export function expandComplexModel(model: any, schemas: FormSchema[]) { 5 | //克隆新的对象 6 | const res: any = clone(model) 7 | //复杂对象展开 8 | schemas.filter(x => x.fieldMap && !!x.fieldMap.mapTo).forEach((schema) => { 9 | if (schema.fieldMap) { 10 | const item = schema.fieldMap 11 | if (has(res, item.mapTo)) { 12 | res[schema.field] = get(res, item.mapTo) 13 | } 14 | } 15 | }) 16 | console.log("expanded model", res) 17 | return res 18 | } 19 | 20 | export function restoreComplexModel(model: any, schemas: FormSchema[]) { 21 | //克隆为新的对象,避免保存失败后,原对象被修改 22 | const res: any = clone(model) //复杂对象恢复 23 | schemas.filter(x => x.fieldMap && !!x.fieldMap.mapTo) 24 | .forEach(schema => { 25 | if (schema.fieldMap) { 26 | set(res, schema.fieldMap.mapTo, res[schema.field]) 27 | } 28 | }) 29 | console.log(res, "NewData") 30 | return res 31 | } -------------------------------------------------------------------------------- /apps/ant-admin/src/app.vue: -------------------------------------------------------------------------------- 1 | 33 | 34 | 41 | -------------------------------------------------------------------------------- /apps/ant-admin/src/assets/images/demo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EasyOC/EasyOC.VbenAdmin/4f711c4e480be3274e4ed6b68532834fd443acc3/apps/ant-admin/src/assets/images/demo.png -------------------------------------------------------------------------------- /apps/ant-admin/src/assets/images/header.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EasyOC/EasyOC.VbenAdmin/4f711c4e480be3274e4ed6b68532834fd443acc3/apps/ant-admin/src/assets/images/header.jpg -------------------------------------------------------------------------------- /apps/ant-admin/src/assets/images/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EasyOC/EasyOC.VbenAdmin/4f711c4e480be3274e4ed6b68532834fd443acc3/apps/ant-admin/src/assets/images/logo.png -------------------------------------------------------------------------------- /apps/ant-admin/src/components/Amis/index.ts: -------------------------------------------------------------------------------- 1 | // import { useAppStore } from '@/store/app' 2 | import { withInstall } from '@pkg/utils' 3 | // const appStore = useAppStore() 4 | 5 | import AmisSdk from './src/index.vue' 6 | export const Amis = withInstall(AmisSdk) 7 | 8 | // import veauryAMISRenderer from './src/veauryAMISRenderer.vue' 9 | // const mode = appStore.projectConfig?.amisRenderMode != "react" ? "sdk" : "react" 10 | // console.warn(`Amis 当前正在使用${mode}渲染器`) 11 | // export const Amis = mode != "react" ? withInstall(AmisSdk) : withInstall(veauryAMISRenderer) 12 | // export const Amis = withInstall(veauryAMISRenderer) 13 | -------------------------------------------------------------------------------- /apps/ant-admin/src/components/Amis/src/vue/AA.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 16 | 17 | 20 | -------------------------------------------------------------------------------- /apps/ant-admin/src/components/Amis/src/vue/Basic.vue: -------------------------------------------------------------------------------- 1 | 8 | 16 | -------------------------------------------------------------------------------- /apps/ant-admin/src/components/Authority/index.ts: -------------------------------------------------------------------------------- 1 | import { withInstall } from '@pkg/utils' 2 | import authority from './src/index.vue' 3 | 4 | export const Authority = withInstall(authority) 5 | -------------------------------------------------------------------------------- /apps/ant-admin/src/components/CodeEditor/index.ts: -------------------------------------------------------------------------------- 1 | import { withInstall } from '@pkg/utils' 2 | import codeEditor from './src/CodeEditor.vue'; 3 | import jsonPreview from './src/json-preview/JsonPreview.vue'; 4 | 5 | export const CodeEditor = withInstall(codeEditor); 6 | export const JsonPreview = withInstall(jsonPreview); 7 | 8 | export * from './src/typing'; 9 | -------------------------------------------------------------------------------- /apps/ant-admin/src/components/CodeEditor/src/codemirror/codeMirror.ts: -------------------------------------------------------------------------------- 1 | import CodeMirror from 'codemirror'; 2 | import './codemirror.css'; 3 | import 'codemirror/theme/idea.css'; 4 | import 'codemirror/theme/material-palenight.css'; 5 | // import 'codemirror/addon/lint/lint.css'; 6 | 7 | // modes 8 | import 'codemirror/mode/javascript/javascript'; 9 | import 'codemirror/mode/css/css'; 10 | import 'codemirror/mode/htmlmixed/htmlmixed'; 11 | // addons 12 | // import 'codemirror/addon/edit/closebrackets'; 13 | // import 'codemirror/addon/edit/closetag'; 14 | // import 'codemirror/addon/comment/comment'; 15 | // import 'codemirror/addon/fold/foldcode'; 16 | // import 'codemirror/addon/fold/foldgutter'; 17 | // import 'codemirror/addon/fold/brace-fold'; 18 | // import 'codemirror/addon/fold/indent-fold'; 19 | // import 'codemirror/addon/lint/json-lint'; 20 | // import 'codemirror/addon/fold/comment-fold'; 21 | export { CodeMirror }; 22 | -------------------------------------------------------------------------------- /apps/ant-admin/src/components/CodeEditor/src/json-preview/JsonPreview.vue: -------------------------------------------------------------------------------- 1 | 4 | 5 | 13 | -------------------------------------------------------------------------------- /apps/ant-admin/src/components/CodeEditor/src/typing.ts: -------------------------------------------------------------------------------- 1 | export enum MODE { 2 | JSON = 'application/json', 3 | HTML = 'htmlmixed', 4 | JS = 'javascript', 5 | } 6 | -------------------------------------------------------------------------------- /apps/ant-admin/src/components/OrchardCore/index.ts: -------------------------------------------------------------------------------- 1 | import ContentForm from './src/ContentForm.vue' 2 | 3 | export { ContentForm } 4 | -------------------------------------------------------------------------------- /apps/ant-admin/src/components/OrchardCore/src/props.ts: -------------------------------------------------------------------------------- 1 | import type { PropType } from 'vue' 2 | 3 | export const basicProps = { 4 | contentItemId: { 5 | type: String as PropType, 6 | require: true, 7 | }, 8 | /** 9 | * 类型名称 10 | */ 11 | typeName: { 12 | type: String as PropType, 13 | default: '', 14 | }, 15 | } 16 | -------------------------------------------------------------------------------- /apps/ant-admin/src/components/OrchardCore/types/ContentFormProps.ts: -------------------------------------------------------------------------------- 1 | export interface ContentFormProps { 2 | contentItemId: string 3 | /** 4 | * 类型名称 5 | */ 6 | typeName: string 7 | } 8 | -------------------------------------------------------------------------------- /apps/ant-admin/src/components/Tree/index.ts: -------------------------------------------------------------------------------- 1 | import BasicTree from './src/index.vue' 2 | import './style' 3 | 4 | export { BasicTree } 5 | export type { ContextMenuItem } from '@/hooks/web/useContextMenu' 6 | export * from './src/tree' 7 | -------------------------------------------------------------------------------- /apps/ant-admin/src/components/Tree/src/tree-icon.ts: -------------------------------------------------------------------------------- 1 | import type { VNode, FunctionalComponent } from 'vue' 2 | import { h } from 'vue' 3 | import { isString } from '@pkg/utils' 4 | import { Icon } from '@components/common' 5 | 6 | export const TreeIcon: FunctionalComponent = ({ 7 | icon, 8 | }: { 9 | icon: VNode | string 10 | }) => { 11 | if (!icon) return null 12 | if (isString(icon)) { 13 | return h(Icon, { icon, class: 'mr-1' }) 14 | } 15 | return Icon 16 | } 17 | -------------------------------------------------------------------------------- /apps/ant-admin/src/components/Tree/style/index.less: -------------------------------------------------------------------------------- 1 | @tree-prefix-cls: ~'@{namespace}-tree'; 2 | 3 | .@{tree-prefix-cls} { 4 | background-color: @component-background; 5 | 6 | .ant-tree-node-content-wrapper { 7 | position: relative; 8 | 9 | .ant-tree-title { 10 | position: absolute; 11 | left: 0; 12 | width: 100%; 13 | overflow: hidden; 14 | text-overflow: ellipsis; 15 | white-space: nowrap; 16 | } 17 | } 18 | 19 | &__title { 20 | position: relative; 21 | display: flex; 22 | align-items: center; 23 | width: 100%; 24 | padding-right: 10px; 25 | 26 | &:hover { 27 | .@{tree-prefix-cls}__action { 28 | visibility: visible; 29 | } 30 | } 31 | } 32 | 33 | &__content { 34 | overflow: hidden; 35 | } 36 | 37 | &__actions { 38 | position: absolute; 39 | //top: 2px; 40 | right: 3px; 41 | display: flex; 42 | } 43 | 44 | &__action { 45 | margin-left: 4px; 46 | visibility: hidden; 47 | } 48 | 49 | &-header { 50 | border-bottom: 1px solid @border-color-base; 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /apps/ant-admin/src/components/Tree/style/index.ts: -------------------------------------------------------------------------------- 1 | import './index.less' 2 | -------------------------------------------------------------------------------- /apps/ant-admin/src/components/Upload/index.ts: -------------------------------------------------------------------------------- 1 | import { withInstall } from '@pkg/utils' 2 | import basicUpload from './src/index.vue' 3 | 4 | export const BasicUpload = withInstall(basicUpload) 5 | -------------------------------------------------------------------------------- /apps/ant-admin/src/components/Upload/src/helper.ts: -------------------------------------------------------------------------------- 1 | export function checkFileType(file: File, accepts: string[]) { 2 | const newTypes = accepts.join('|') 3 | // const reg = /\.(jpg|jpeg|png|gif|txt|doc|docx|xls|xlsx|xml)$/i; 4 | const reg = new RegExp('\\.(' + newTypes + ')$', 'i') 5 | 6 | return reg.test(file.name) 7 | } 8 | 9 | export function checkImgType(file: File) { 10 | return isImgTypeByName(file.name) 11 | } 12 | 13 | export function isImgTypeByName(name: string) { 14 | return /\.(jpg|jpeg|png|gif)$/i.test(name) 15 | } 16 | 17 | export function getBase64WithFile(file: File) { 18 | return new Promise<{ 19 | result: string 20 | file: File 21 | }>((resolve, reject) => { 22 | const reader = new FileReader() 23 | reader.readAsDataURL(file) 24 | reader.onload = () => resolve({ result: reader.result as string, file }) 25 | reader.onerror = (error) => reject(error) 26 | }) 27 | } 28 | -------------------------------------------------------------------------------- /apps/ant-admin/src/components/Upload/src/thumb-url.vue: -------------------------------------------------------------------------------- 1 | 6 | 18 | 29 | -------------------------------------------------------------------------------- /apps/ant-admin/src/components/application/index.ts: -------------------------------------------------------------------------------- 1 | import { withInstall } from '@pkg/utils' 2 | 3 | import appLogo from './src/AppLogo.vue' 4 | import appProvider from './src/AppProvider.vue' 5 | import appSearch from './src/search/AppSearch.vue' 6 | import appLocalePicker from './src/AppLocalePicker.vue' 7 | import appDarkModeToggle from './src/AppDarkModeToggle.vue' 8 | 9 | export { useAppProviderContext } from './src/useAppContext' 10 | 11 | export const AppLogo = withInstall(appLogo) 12 | export const AppProvider = withInstall(appProvider) 13 | export const AppSearch = withInstall(appSearch) 14 | export const AppLocalePicker = withInstall(appLocalePicker) 15 | export const AppDarkModeToggle = withInstall(appDarkModeToggle) 16 | -------------------------------------------------------------------------------- /apps/ant-admin/src/components/application/src/search/AppSearch.vue: -------------------------------------------------------------------------------- 1 | 37 | -------------------------------------------------------------------------------- /apps/ant-admin/src/components/application/src/search/AppSearchKeyItem.vue: -------------------------------------------------------------------------------- 1 | 7 | 8 | 13 | -------------------------------------------------------------------------------- /apps/ant-admin/src/components/application/src/useAppContext.ts: -------------------------------------------------------------------------------- 1 | import { InjectionKey, Ref } from 'vue' 2 | import { createContext, useContext } from '@pkg/use' 3 | 4 | export interface AppProviderContextProps { 5 | prefixCls: Ref 6 | isMobile: Ref 7 | } 8 | 9 | const key: InjectionKey = Symbol() 10 | 11 | export function createAppProviderContext(context: AppProviderContextProps) { 12 | return createContext(context, key) 13 | } 14 | 15 | export function useAppProviderContext() { 16 | return useContext(key) 17 | } 18 | -------------------------------------------------------------------------------- /apps/ant-admin/src/components/basic/index.ts: -------------------------------------------------------------------------------- 1 | import { withInstall } from '@pkg/utils' 2 | import basicArrow from './src/BasicArrow.vue' 3 | import basicTitle from './src/BasicTitle.vue' 4 | import basicHelp from './src/BasicHelp.vue' 5 | 6 | export const BasicArrow = withInstall(basicArrow) 7 | export const BasicTitle = withInstall(basicTitle) 8 | export const BasicHelp = withInstall(basicHelp) 9 | -------------------------------------------------------------------------------- /apps/ant-admin/src/components/button/index.ts: -------------------------------------------------------------------------------- 1 | import { withInstall } from '@pkg/utils' 2 | import popConfirmButton from './src/PopConfirmButton.vue' 3 | 4 | export const PopConfirmButton = withInstall(popConfirmButton) 5 | -------------------------------------------------------------------------------- /apps/ant-admin/src/components/card-list/index.ts: -------------------------------------------------------------------------------- 1 | import { withInstall } from '@pkg/utils' 2 | import cardList from './src/CardList.vue' 3 | 4 | export const CardList = withInstall(cardList) 5 | -------------------------------------------------------------------------------- /apps/ant-admin/src/components/card-list/src/data.ts: -------------------------------------------------------------------------------- 1 | import { ref } from 'vue' 2 | // 每行个数 3 | export const grid = ref(12) 4 | // slider属性 5 | export const useSlider = (min = 6, max = 12) => { 6 | // 每行显示个数滑动条 7 | const getMarks = () => { 8 | const l = {} 9 | for (let i = min; i < max + 1; i++) { 10 | l[i] = { 11 | style: { 12 | color: '#fff', 13 | }, 14 | label: i, 15 | } 16 | } 17 | return l 18 | } 19 | return { 20 | min, 21 | max, 22 | marks: getMarks(), 23 | step: 1, 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /apps/ant-admin/src/components/container/index.ts: -------------------------------------------------------------------------------- 1 | import { withInstall } from '@pkg/utils' 2 | import collapseContainer from './src/collapse/CollapseContainer.vue' 3 | import scrollContainer from './src/ScrollContainer.vue' 4 | 5 | export const CollapseContainer = withInstall(collapseContainer) 6 | export const ScrollContainer = withInstall(scrollContainer) 7 | 8 | export * from './src/typing' 9 | -------------------------------------------------------------------------------- /apps/ant-admin/src/components/container/src/collapse/CollapseHeader.vue: -------------------------------------------------------------------------------- 1 | 17 | 39 | -------------------------------------------------------------------------------- /apps/ant-admin/src/components/container/src/typing.ts: -------------------------------------------------------------------------------- 1 | export type ScrollType = 'default' | 'main' 2 | 3 | export interface CollapseContainerOptions { 4 | canExpand?: boolean 5 | title?: string 6 | helpMessage?: Array | string 7 | } 8 | export interface ScrollContainerOptions { 9 | enableScroll?: boolean 10 | type?: ScrollType 11 | } 12 | 13 | export type ScrollActionType = Nullable<{ 14 | scrollBottom: () => void 15 | getScrollWrap: () => Nullable 16 | scrollTo: (top: number) => void 17 | }> 18 | -------------------------------------------------------------------------------- /apps/ant-admin/src/components/context-menu/index.ts: -------------------------------------------------------------------------------- 1 | export { createContextMenu, destroyContextMenu } from './src/createContextMenu' 2 | 3 | export * from './src/typing' 4 | -------------------------------------------------------------------------------- /apps/ant-admin/src/components/context-menu/src/typing.ts: -------------------------------------------------------------------------------- 1 | export interface Axis { 2 | x: number 3 | y: number 4 | } 5 | 6 | export interface ContextMenuItem { 7 | label: string 8 | icon?: string 9 | disabled?: boolean 10 | handler?: AnyFunction 11 | divider?: boolean 12 | children?: ContextMenuItem[] 13 | } 14 | export interface CreateContextOptions { 15 | event: MouseEvent 16 | icon?: string 17 | styles?: any 18 | items?: ContextMenuItem[] 19 | } 20 | 21 | export interface ContextMenuProps { 22 | event?: MouseEvent 23 | styles?: any 24 | items: ContextMenuItem[] 25 | customEvent?: MouseEvent 26 | axis?: Axis 27 | width?: number 28 | showIcon?: boolean 29 | } 30 | 31 | export interface ItemContentProps { 32 | showIcon: boolean | undefined 33 | item: ContextMenuItem 34 | handler: AnyFunction 35 | } 36 | -------------------------------------------------------------------------------- /apps/ant-admin/src/components/count-down/index.ts: -------------------------------------------------------------------------------- 1 | import { withInstall } from '@pkg/utils' 2 | import countButton from './src/CountButton.vue' 3 | import countdownInput from './src/CountdownInput.vue' 4 | 5 | export const CountdownInput = withInstall(countdownInput) 6 | export const CountButton = withInstall(countButton) 7 | -------------------------------------------------------------------------------- /apps/ant-admin/src/components/count-down/src/useCountdown.ts: -------------------------------------------------------------------------------- 1 | import { ref, unref } from 'vue' 2 | import { tryOnUnmounted } from '@pkg/utils' 3 | 4 | export function useCountdown(count: number) { 5 | const currentCount = ref(count) 6 | 7 | const isStart = ref(false) 8 | 9 | let timerId: ReturnType | null 10 | 11 | function clear() { 12 | timerId && window.clearInterval(timerId) 13 | } 14 | 15 | function stop() { 16 | isStart.value = false 17 | clear() 18 | timerId = null 19 | } 20 | 21 | function start() { 22 | if (unref(isStart) || !!timerId) { 23 | return 24 | } 25 | isStart.value = true 26 | timerId = setInterval(() => { 27 | if (unref(currentCount) === 1) { 28 | stop() 29 | currentCount.value = count 30 | } else { 31 | currentCount.value -= 1 32 | } 33 | }, 1000) 34 | } 35 | 36 | function reset() { 37 | currentCount.value = count 38 | stop() 39 | } 40 | 41 | function restart() { 42 | reset() 43 | start() 44 | } 45 | 46 | tryOnUnmounted(() => { 47 | reset() 48 | }) 49 | 50 | return { start, reset, restart, clear, stop, currentCount, isStart } 51 | } 52 | -------------------------------------------------------------------------------- /apps/ant-admin/src/components/cropper/index.ts: -------------------------------------------------------------------------------- 1 | import { withInstall } from '@pkg/utils' 2 | import cropperImage from './src/Cropper.vue' 3 | import avatarCropper from './src/CropperAvatar.vue' 4 | 5 | export * from './src/typing' 6 | export const CropperImage = withInstall(cropperImage) 7 | export const CropperAvatar = withInstall(avatarCropper) 8 | -------------------------------------------------------------------------------- /apps/ant-admin/src/components/cropper/src/typing.ts: -------------------------------------------------------------------------------- 1 | import type Cropper from 'cropperjs' 2 | 3 | export interface CropendResult { 4 | imgBase64: string 5 | imgInfo: Cropper.Data 6 | } 7 | 8 | export type { Cropper } 9 | -------------------------------------------------------------------------------- /apps/ant-admin/src/components/description/index.ts: -------------------------------------------------------------------------------- 1 | import { withInstall } from '@pkg/utils' 2 | import description from './src/Description.vue' 3 | 4 | export * from './src/typing' 5 | export { useDescription } from './src/useDescription' 6 | export const Description = withInstall(description) 7 | -------------------------------------------------------------------------------- /apps/ant-admin/src/components/description/src/useDescription.ts: -------------------------------------------------------------------------------- 1 | import type { 2 | DescriptionProps, 3 | DescInstance, 4 | UseDescReturnType, 5 | } from './typing' 6 | import { ref, getCurrentInstance, unref } from 'vue' 7 | 8 | export function useDescription( 9 | props?: Partial, 10 | ): UseDescReturnType { 11 | if (!getCurrentInstance()) { 12 | throw new Error( 13 | 'useDescription() can only be used inside setup() or functional components!', 14 | ) 15 | } 16 | const desc = ref>(null) 17 | const loaded = ref(false) 18 | 19 | function register(instance: DescInstance) { 20 | if (unref(loaded) && import.meta.env.PROD) { 21 | return 22 | } 23 | desc.value = instance 24 | props && instance.setDescProps(props) 25 | loaded.value = true 26 | } 27 | 28 | const methods: DescInstance = { 29 | setDescProps: (descProps: Partial): void => { 30 | unref(desc)?.setDescProps(descProps) 31 | }, 32 | } 33 | 34 | return [register, methods] 35 | } 36 | -------------------------------------------------------------------------------- /apps/ant-admin/src/components/drawer/index.ts: -------------------------------------------------------------------------------- 1 | import { withInstall } from '@pkg/utils' 2 | import basicDrawer from './src/BasicDrawer.vue' 3 | 4 | export const BasicDrawer = withInstall(basicDrawer) 5 | export * from './src/typing' 6 | export { useDrawer, useDrawerInner } from './src/useDrawer' 7 | -------------------------------------------------------------------------------- /apps/ant-admin/src/components/dropdown/index.ts: -------------------------------------------------------------------------------- 1 | import { withInstall } from '@pkg/utils' 2 | import dropdown from './src/Dropdown.vue' 3 | 4 | export * from './src/typing' 5 | export const Dropdown = withInstall(dropdown) 6 | -------------------------------------------------------------------------------- /apps/ant-admin/src/components/dropdown/src/typing.ts: -------------------------------------------------------------------------------- 1 | export interface DropMenu { 2 | onClick?: AnyFunction 3 | to?: string 4 | icon?: string 5 | event: string | number 6 | text: string 7 | disabled?: boolean 8 | divider?: boolean 9 | } 10 | -------------------------------------------------------------------------------- /apps/ant-admin/src/components/form/index.ts: -------------------------------------------------------------------------------- 1 | import BasicForm from './src/BasicForm.vue' 2 | 3 | export * from './src/types/form' 4 | export * from './src/types/formItem' 5 | 6 | export { useComponentRegister } from './src/hooks/useComponentRegister' 7 | export { useForm } from './src/hooks/useForm' 8 | 9 | export { default as ApiSelect } from './src/components/ApiSelect.vue' 10 | export { default as RadioButtonGroup } from './src/components/RadioButtonGroup.vue' 11 | export { default as ApiTreeSelect } from './src/components/ApiTreeSelect.vue' 12 | export { default as ApiRadioGroup } from './src/components/ApiRadioGroup.vue' 13 | export { default as ApiCascader } from './src/components/ApiCascader.vue' 14 | 15 | export { BasicForm } 16 | -------------------------------------------------------------------------------- /apps/ant-admin/src/components/form/src/hooks/useComponentRegister.ts: -------------------------------------------------------------------------------- 1 | import type { ComponentType } from '../types/index' 2 | import { tryOnUnmounted } from '@pkg/utils' 3 | import { add, del } from '../componentMap' 4 | import type { Component } from 'vue' 5 | 6 | export function useComponentRegister(compName: ComponentType, comp: Component) { 7 | add(compName, comp) 8 | tryOnUnmounted(() => { 9 | del(compName) 10 | }) 11 | } 12 | -------------------------------------------------------------------------------- /apps/ant-admin/src/components/form/src/hooks/useFormContext.ts: -------------------------------------------------------------------------------- 1 | import type { InjectionKey } from 'vue' 2 | import { createContext, useContext } from '@pkg/use' 3 | 4 | export interface FormContextProps { 5 | resetAction: () => Promise 6 | submitAction: () => Promise 7 | } 8 | 9 | const key: InjectionKey = Symbol() 10 | 11 | export function createFormContext(context: FormContextProps) { 12 | return createContext(context, key) 13 | } 14 | 15 | export function useFormContext() { 16 | return useContext(key) 17 | } 18 | -------------------------------------------------------------------------------- /apps/ant-admin/src/components/form/src/types/hooks.ts: -------------------------------------------------------------------------------- 1 | export interface AdvanceState { 2 | isAdvanced: boolean 3 | hideAdvanceBtn: boolean 4 | isLoad: boolean 5 | actionSpan: number 6 | } 7 | -------------------------------------------------------------------------------- /apps/ant-admin/src/components/icon/index.ts: -------------------------------------------------------------------------------- 1 | import IconPicker from './src/IconPicker.vue' 2 | 3 | export { IconPicker } 4 | -------------------------------------------------------------------------------- /apps/ant-admin/src/components/loading/index.ts: -------------------------------------------------------------------------------- 1 | import Loading from './src/Loading.vue' 2 | 3 | export { Loading } 4 | export { useLoading } from './src/useLoading' 5 | export { createLoading } from './src/createLoading' 6 | -------------------------------------------------------------------------------- /apps/ant-admin/src/components/loading/src/typing.ts: -------------------------------------------------------------------------------- 1 | import { ComponentSizeEnum } from '@pkg/tokens' 2 | 3 | export interface LoadingProps { 4 | tip: string 5 | size: ComponentSizeEnum 6 | absolute: boolean 7 | loading: boolean 8 | background: string 9 | theme: 'dark' | 'light' 10 | } 11 | -------------------------------------------------------------------------------- /apps/ant-admin/src/components/menu/index.ts: -------------------------------------------------------------------------------- 1 | import BasicMenu from './src/BasicMenu.vue' 2 | 3 | export { BasicMenu } 4 | -------------------------------------------------------------------------------- /apps/ant-admin/src/components/menu/src/components/BasicMenuItem.vue: -------------------------------------------------------------------------------- 1 | 6 | 21 | -------------------------------------------------------------------------------- /apps/ant-admin/src/components/menu/src/components/MenuItemContent.vue: -------------------------------------------------------------------------------- 1 | 12 | 39 | -------------------------------------------------------------------------------- /apps/ant-admin/src/components/menu/src/types.ts: -------------------------------------------------------------------------------- 1 | export interface MenuState { 2 | // 默认选中的列表 3 | defaultSelectedKeys: string[] 4 | 5 | // 模式 6 | // mode: MenuModeEnum; 7 | 8 | // // 主题 9 | // theme: ComputedRef | ThemeEnum; 10 | 11 | // 缩进 12 | inlineIndent?: number 13 | 14 | // 展开数组 15 | openKeys: string[] 16 | 17 | // 当前选中的菜单项 key 数组 18 | selectedKeys: string[] 19 | 20 | // 收缩状态下展开的数组 21 | collapsedOpenKeys: string[] 22 | } 23 | -------------------------------------------------------------------------------- /apps/ant-admin/src/components/modal/index.ts: -------------------------------------------------------------------------------- 1 | import { withInstall } from '@pkg/utils' 2 | import './src/index.less' 3 | import basicModal from './src/BasicModal.vue' 4 | 5 | export const BasicModal = withInstall(basicModal) 6 | export { useModalContext } from './src/hooks/useModalContext' 7 | export { useModal, useModalInner } from './src/hooks/useModal' 8 | export * from './src/typing' 9 | -------------------------------------------------------------------------------- /apps/ant-admin/src/components/modal/src/components/Modal.tsx: -------------------------------------------------------------------------------- 1 | import { Modal } from 'ant-design-vue' 2 | import { defineComponent, toRefs, unref } from 'vue' 3 | import { basicProps } from '../props' 4 | import { useModalDragMove } from '../hooks/useModalDrag' 5 | import { useAttrs } from '@pkg/use' 6 | import { extendSlots } from '@pkg/utils' 7 | 8 | export default defineComponent({ 9 | name: 'Modal', 10 | inheritAttrs: false, 11 | props: basicProps, 12 | emits: ['cancel'], 13 | setup(props, { slots, emit }) { 14 | const { visible, draggable, destroyOnClose } = toRefs(props) 15 | const attrs = useAttrs() 16 | useModalDragMove({ 17 | visible, 18 | destroyOnClose, 19 | draggable, 20 | }) 21 | 22 | const onCancel = (e: Event) => { 23 | emit('cancel', e) 24 | } 25 | 26 | return () => { 27 | const propsData = { ...unref(attrs), ...props, onCancel } as Recordable 28 | return {extendSlots(slots)} 29 | } 30 | }, 31 | }) 32 | -------------------------------------------------------------------------------- /apps/ant-admin/src/components/modal/src/components/ModalFooter.vue: -------------------------------------------------------------------------------- 1 | 24 | 45 | -------------------------------------------------------------------------------- /apps/ant-admin/src/components/modal/src/components/ModalHeader.vue: -------------------------------------------------------------------------------- 1 | 6 | 23 | -------------------------------------------------------------------------------- /apps/ant-admin/src/components/modal/src/hooks/useModalContext.ts: -------------------------------------------------------------------------------- 1 | import { InjectionKey } from 'vue' 2 | import { createContext, useContext } from '@pkg/use' 3 | 4 | export interface ModalContextProps { 5 | redoModalHeight: () => void 6 | } 7 | 8 | const key: InjectionKey = Symbol() 9 | 10 | export function createModalContext(context: ModalContextProps) { 11 | return createContext(context, key) 12 | } 13 | 14 | export function useModalContext() { 15 | return useContext(key) 16 | } 17 | -------------------------------------------------------------------------------- /apps/ant-admin/src/components/page/index.ts: -------------------------------------------------------------------------------- 1 | import { withInstall } from '@pkg/utils' 2 | 3 | import pageFooter from './src/PageFooter.vue' 4 | import pageWrapper from './src/PageWrapper.vue' 5 | 6 | export const PageFooter = withInstall(pageFooter) 7 | export const PageWrapper = withInstall(pageWrapper) 8 | 9 | export const PageWrapperFixedHeightKey = 'PageWrapperFixedHeight' 10 | -------------------------------------------------------------------------------- /apps/ant-admin/src/components/scrollbar/index.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * copy from element-ui 3 | */ 4 | 5 | import Scrollbar from './src/Scrollbar.vue' 6 | 7 | export { Scrollbar } 8 | export type { ScrollbarType } from './src/types' 9 | -------------------------------------------------------------------------------- /apps/ant-admin/src/components/scrollbar/src/types.d.ts: -------------------------------------------------------------------------------- 1 | export interface BarMapItem { 2 | offset: string 3 | scroll: string 4 | scrollSize: string 5 | size: string 6 | key: string 7 | axis: string 8 | client: string 9 | direction: string 10 | } 11 | export interface BarMap { 12 | vertical: BarMapItem 13 | horizontal: BarMapItem 14 | } 15 | 16 | export interface ScrollbarType { 17 | wrap: ElRef 18 | } 19 | -------------------------------------------------------------------------------- /apps/ant-admin/src/components/simple-menu/index.ts: -------------------------------------------------------------------------------- 1 | export { default as SimpleMenu } from './src/SimpleMenu.vue' 2 | export { default as SimpleMenuTag } from './src/SimpleMenuTag.vue' 3 | -------------------------------------------------------------------------------- /apps/ant-admin/src/components/simple-menu/src/components/types.ts: -------------------------------------------------------------------------------- 1 | import { Ref } from 'vue' 2 | 3 | export interface Props { 4 | theme: string 5 | activeName?: string | number | undefined 6 | openNames: string[] 7 | accordion: boolean 8 | width: string 9 | collapsedWidth: string 10 | indentSize: number 11 | collapse: boolean 12 | activeSubMenuNames: (string | number)[] 13 | } 14 | 15 | export interface SubMenuProvider { 16 | addSubMenu: (name: string | number, update?: boolean) => void 17 | removeSubMenu: (name: string | number, update?: boolean) => void 18 | removeAll: () => void 19 | sliceIndex: (index: number) => void 20 | isRemoveAllPopup: Ref 21 | getOpenNames: () => (string | number)[] 22 | handleMouseleave?: AnyFunction 23 | level: number 24 | props: Props 25 | } 26 | -------------------------------------------------------------------------------- /apps/ant-admin/src/components/simple-menu/src/components/useSimpleMenuContext.ts: -------------------------------------------------------------------------------- 1 | import type { InjectionKey, Ref } from 'vue' 2 | import type { Emitter } from '@pkg/utils' 3 | import { createContext, useContext } from '@pkg/use' 4 | 5 | export interface SimpleRootMenuContextProps { 6 | rootMenuEmitter: Emitter 7 | activeName: Ref 8 | } 9 | 10 | const key: InjectionKey = Symbol() 11 | 12 | export function createSimpleRootMenuContext( 13 | context: SimpleRootMenuContextProps, 14 | ) { 15 | return createContext(context, key, { 16 | readonly: false, 17 | native: true, 18 | }) 19 | } 20 | 21 | export function useSimpleRootMenuContext() { 22 | return useContext(key) 23 | } 24 | -------------------------------------------------------------------------------- /apps/ant-admin/src/components/simple-menu/src/types.ts: -------------------------------------------------------------------------------- 1 | export interface MenuState { 2 | activeName: string 3 | openNames: string[] 4 | activeSubMenuNames: string[] 5 | } 6 | -------------------------------------------------------------------------------- /apps/ant-admin/src/components/table/index.ts: -------------------------------------------------------------------------------- 1 | export { default as BasicTable } from './src/BasicTable.vue' 2 | export { default as TableAction } from './src/components/TableAction.vue' 3 | export { default as EditTableHeaderIcon } from './src/components/EditTableHeaderIcon.vue' 4 | export { default as TableImg } from './src/components/TableImg.vue' 5 | 6 | export * from './src/types/table' 7 | export * from './src/types/pagination' 8 | export * from './src/types/tableAction' 9 | export { useTable } from './src/hooks/useTable' 10 | export type { FormSchema, FormProps } from '@/components/form/src/types/form' 11 | export type { EditRecordRow } from './src/components/editable' 12 | -------------------------------------------------------------------------------- /apps/ant-admin/src/components/table/src/componentMap.ts: -------------------------------------------------------------------------------- 1 | import type { Component } from 'vue' 2 | import { 3 | Input, 4 | Select, 5 | Checkbox, 6 | InputNumber, 7 | Switch, 8 | DatePicker, 9 | TimePicker, 10 | } from 'ant-design-vue' 11 | import type { ComponentType } from './types/componentType' 12 | import { ApiSelect, ApiTreeSelect } from '@/components/form' 13 | 14 | const componentMap = new Map() 15 | 16 | componentMap.set('Input', Input) 17 | componentMap.set('InputNumber', InputNumber) 18 | componentMap.set('Select', Select) 19 | componentMap.set('ApiSelect', ApiSelect) 20 | componentMap.set('ApiTreeSelect', ApiTreeSelect) 21 | componentMap.set('Switch', Switch) 22 | componentMap.set('Checkbox', Checkbox) 23 | componentMap.set('DatePicker', DatePicker) 24 | componentMap.set('TimePicker', TimePicker) 25 | 26 | export function add(compName: ComponentType, component: Component) { 27 | componentMap.set(compName, component) 28 | } 29 | 30 | export function del(compName: ComponentType) { 31 | componentMap.delete(compName) 32 | } 33 | 34 | export { componentMap } 35 | -------------------------------------------------------------------------------- /apps/ant-admin/src/components/table/src/components/EditTableHeaderIcon.vue: -------------------------------------------------------------------------------- 1 | 8 | 17 | -------------------------------------------------------------------------------- /apps/ant-admin/src/components/table/src/components/editable/CellComponent.ts: -------------------------------------------------------------------------------- 1 | import type { FunctionalComponent, defineComponent } from 'vue' 2 | import type { ComponentType } from '../../types/componentType' 3 | import { componentMap } from '@/components/table/src/componentMap' 4 | 5 | import { Popover } from 'ant-design-vue' 6 | import { h } from 'vue' 7 | 8 | export interface ComponentProps { 9 | component: ComponentType 10 | rule: boolean 11 | popoverVisible: boolean 12 | ruleMessage: string 13 | getPopupContainer?: AnyFunction 14 | } 15 | 16 | export const CellComponent: FunctionalComponent = ( 17 | { 18 | component = 'Input', 19 | rule = true, 20 | ruleMessage, 21 | popoverVisible, 22 | getPopupContainer, 23 | }: ComponentProps, 24 | { attrs }, 25 | ) => { 26 | const Comp = componentMap.get(component) as typeof defineComponent 27 | 28 | const DefaultComp = h(Comp, attrs) 29 | if (!rule) { 30 | return DefaultComp 31 | } 32 | return h( 33 | Popover, 34 | { 35 | overlayClassName: 'edit-cell-rule-popover', 36 | visible: !!popoverVisible, 37 | ...(getPopupContainer ? { getPopupContainer } : {}), 38 | }, 39 | { 40 | default: () => DefaultComp, 41 | content: () => ruleMessage, 42 | }, 43 | ) 44 | } 45 | -------------------------------------------------------------------------------- /apps/ant-admin/src/components/table/src/components/editable/helper.ts: -------------------------------------------------------------------------------- 1 | import { ComponentType } from '../../types/componentType' 2 | import { useI18n } from '@pkg/locale' 3 | 4 | const { t } = useI18n() 5 | 6 | /** 7 | * @description: 生成placeholder 8 | */ 9 | export function createPlaceholderMessage(component: ComponentType) { 10 | if (component.includes('Input')) { 11 | return t('common.inputText') 12 | } 13 | if (component.includes('Picker')) { 14 | return t('common.chooseText') 15 | } 16 | 17 | if ( 18 | component.includes('Select') || 19 | component.includes('Checkbox') || 20 | component.includes('Radio') || 21 | component.includes('Switch') || 22 | component.includes('DatePicker') || 23 | component.includes('TimePicker') 24 | ) { 25 | return t('common.chooseText') 26 | } 27 | return '' 28 | } 29 | -------------------------------------------------------------------------------- /apps/ant-admin/src/components/table/src/components/settings/FullScreenSetting.vue: -------------------------------------------------------------------------------- 1 | 10 | 42 | -------------------------------------------------------------------------------- /apps/ant-admin/src/components/table/src/components/settings/RedoSetting.vue: -------------------------------------------------------------------------------- 1 | 9 | 34 | -------------------------------------------------------------------------------- /apps/ant-admin/src/components/table/src/const.ts: -------------------------------------------------------------------------------- 1 | import { componentSetting } from '@pkg/setting' 2 | 3 | const { table } = componentSetting 4 | 5 | const { 6 | pageSizeOptions, 7 | defaultPageSize, 8 | fetchSetting, 9 | defaultSize, 10 | defaultSortFn, 11 | defaultFilterFn, 12 | } = table 13 | 14 | export const ROW_KEY = 'key' 15 | 16 | // Optional display number per page; 17 | export const PAGE_SIZE_OPTIONS = pageSizeOptions 18 | 19 | // Number of items displayed per page 20 | export const PAGE_SIZE = defaultPageSize 21 | 22 | // Common interface field settings 23 | export const FETCH_SETTING = fetchSetting 24 | 25 | // Default Size 26 | export const DEFAULT_SIZE = defaultSize 27 | 28 | // Configure general sort function 29 | export const DEFAULT_SORT_FN = defaultSortFn 30 | 31 | export const DEFAULT_FILTER_FN = defaultFilterFn 32 | 33 | // Default layout of table cells 34 | export const DEFAULT_ALIGN = 'center' 35 | 36 | export const INDEX_COLUMN_FLAG = 'INDEX' 37 | 38 | export const ACTION_COLUMN_FLAG = 'ACTION' 39 | -------------------------------------------------------------------------------- /apps/ant-admin/src/components/table/src/hooks/useLoading.ts: -------------------------------------------------------------------------------- 1 | import { ref, ComputedRef, unref, computed, watch } from 'vue' 2 | import type { BasicTableProps } from '../types/table' 3 | 4 | export function useLoading(props: ComputedRef) { 5 | const loadingRef = ref(unref(props).loading) 6 | 7 | watch( 8 | () => unref(props).loading, 9 | (loading) => { 10 | loadingRef.value = loading 11 | }, 12 | ) 13 | 14 | const getLoading = computed(() => unref(loadingRef)) 15 | 16 | function setLoading(loading: boolean) { 17 | loadingRef.value = loading 18 | } 19 | 20 | return { getLoading, setLoading } 21 | } 22 | -------------------------------------------------------------------------------- /apps/ant-admin/src/components/table/src/hooks/useTableContext.ts: -------------------------------------------------------------------------------- 1 | import type { Ref } from 'vue' 2 | import type { BasicTableProps, TableActionType } from '../types/table' 3 | import { provide, inject, ComputedRef } from 'vue' 4 | 5 | const key = Symbol('basic-table') 6 | 7 | type Instance = TableActionType & { 8 | wrapRef: Ref> 9 | getBindValues: ComputedRef 10 | } 11 | 12 | type RetInstance = Omit & { 13 | getBindValues: ComputedRef 14 | } 15 | 16 | export function createTableContext(instance: Instance) { 17 | provide(key, instance) 18 | } 19 | 20 | export function useTableContext(): RetInstance { 21 | return inject(key) as RetInstance 22 | } 23 | -------------------------------------------------------------------------------- /apps/ant-admin/src/components/table/src/hooks/useTableStyle.ts: -------------------------------------------------------------------------------- 1 | import type { ComputedRef } from 'vue' 2 | import type { BasicTableProps, TableCustomRecord } from '../types/table' 3 | import { unref } from 'vue' 4 | import { isFunction } from '@pkg/utils' 5 | 6 | export function useTableStyle( 7 | propsRef: ComputedRef, 8 | prefixCls: string, 9 | ) { 10 | function getRowClassName(record: TableCustomRecord, index: number) { 11 | const { striped, rowClassName } = unref(propsRef) 12 | const classNames: string[] = [] 13 | if (striped) { 14 | classNames.push((index || 0) % 2 === 1 ? `${prefixCls}-row__striped` : '') 15 | } 16 | if (rowClassName && isFunction(rowClassName)) { 17 | classNames.push(rowClassName(record, index)) 18 | } 19 | return classNames.filter((cls) => !!cls).join(' ') 20 | } 21 | 22 | return { getRowClassName } 23 | } 24 | -------------------------------------------------------------------------------- /apps/ant-admin/src/components/table/src/types/componentType.ts: -------------------------------------------------------------------------------- 1 | export type ComponentType = 2 | | 'Input' 3 | | 'InputNumber' 4 | | 'Select' 5 | | 'ApiSelect' 6 | | 'ApiTreeSelect' 7 | | 'Checkbox' 8 | | 'Switch' 9 | | 'DatePicker' 10 | | 'TimePicker' 11 | -------------------------------------------------------------------------------- /apps/ant-admin/src/components/table/src/types/tableAction.ts: -------------------------------------------------------------------------------- 1 | import { ButtonProps } from 'ant-design-vue/es/button/buttonTypes' 2 | import { TooltipProps } from 'ant-design-vue/es/tooltip/Tooltip' 3 | import { RoleEnum } from '@pkg/tokens' 4 | export interface ActionItem extends ButtonProps { 5 | onClick?: AnyFunction 6 | label?: string 7 | color?: 'success' | 'error' | 'warning' 8 | icon?: string 9 | popConfirm?: PopConfirm 10 | disabled?: boolean 11 | divider?: boolean 12 | // 权限编码控制是否显示 13 | auth?: RoleEnum | RoleEnum[] | string | string[] 14 | // 业务控制是否显示 15 | ifShow?: boolean | ((action: ActionItem) => boolean) 16 | tooltip?: string | TooltipProps 17 | } 18 | 19 | export interface PopConfirm { 20 | title: string 21 | okText?: string 22 | cancelText?: string 23 | confirm: AnyFunction 24 | cancel?: AnyFunction 25 | icon?: string 26 | placement?: 27 | | 'top' 28 | | 'left' 29 | | 'right' 30 | | 'bottom' 31 | | 'topLeft' 32 | | 'topRight' 33 | | 'leftTop' 34 | | 'leftBottom' 35 | | 'rightTop' 36 | | 'rightBottom' 37 | | 'bottomLeft' 38 | | 'bottomRight' 39 | } 40 | -------------------------------------------------------------------------------- /apps/ant-admin/src/hooks/component/use-page-context.ts: -------------------------------------------------------------------------------- 1 | import type { InjectionKey, ComputedRef, Ref } from 'vue' 2 | import { createContext, useContext } from '@pkg/use' 3 | 4 | export interface PageContextProps { 5 | contentHeight: ComputedRef 6 | pageHeight: Ref 7 | setPageHeight: (height: number) => Promise 8 | } 9 | 10 | const key: InjectionKey = Symbol() 11 | 12 | export function createPageContext(context: PageContextProps) { 13 | return createContext(context, key, { native: true }) 14 | } 15 | 16 | export function usePageContext() { 17 | return useContext(key) 18 | } 19 | -------------------------------------------------------------------------------- /apps/ant-admin/src/hooks/setting/useMultipleTabSetting.ts: -------------------------------------------------------------------------------- 1 | import type { MultiTabsSetting } from '@pkg/types' 2 | 3 | import { computed } from 'vue' 4 | 5 | import { useAppStore } from '@/store/app' 6 | 7 | export function useMultipleTabSetting() { 8 | const appStore = useAppStore() 9 | 10 | const getShowMultipleTab = computed(() => appStore.getMultiTabsSetting.show) 11 | 12 | const getShowQuick = computed(() => appStore.getMultiTabsSetting.showQuick) 13 | 14 | const getShowRedo = computed(() => appStore.getMultiTabsSetting.showRedo) 15 | 16 | const getShowFold = computed(() => appStore.getMultiTabsSetting.showFold) 17 | 18 | function setMultipleTabSetting(multiTabsSetting: Partial) { 19 | appStore.setProjectConfig({ multiTabsSetting }) 20 | } 21 | return { 22 | setMultipleTabSetting, 23 | getShowMultipleTab, 24 | getShowQuick, 25 | getShowRedo, 26 | getShowFold, 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /apps/ant-admin/src/hooks/web/use-app-inject.ts: -------------------------------------------------------------------------------- 1 | import { useAppProviderContext } from '@/components/application' 2 | import { computed, unref } from 'vue' 3 | 4 | export function useAppInject() { 5 | const values = useAppProviderContext() 6 | 7 | return { 8 | getIsMobile: computed(() => unref(values.isMobile)), 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /apps/ant-admin/src/hooks/web/use-echarts/echarts.ts: -------------------------------------------------------------------------------- 1 | import * as echarts from 'echarts/core' 2 | import { SVGRenderer } from 'echarts/renderers' 3 | import { 4 | BarChart, 5 | LineChart, 6 | PieChart, 7 | MapChart, 8 | PictorialBarChart, 9 | RadarChart, 10 | } from 'echarts/charts' 11 | import { 12 | TitleComponent, 13 | TooltipComponent, 14 | GridComponent, 15 | PolarComponent, 16 | AriaComponent, 17 | ParallelComponent, 18 | LegendComponent, 19 | RadarComponent, 20 | ToolboxComponent, 21 | DataZoomComponent, 22 | VisualMapComponent, 23 | TimelineComponent, 24 | CalendarComponent, 25 | GraphicComponent, 26 | } from 'echarts/components' 27 | 28 | echarts.use([ 29 | LegendComponent, 30 | TitleComponent, 31 | TooltipComponent, 32 | GridComponent, 33 | PolarComponent, 34 | AriaComponent, 35 | ParallelComponent, 36 | BarChart, 37 | LineChart, 38 | PieChart, 39 | MapChart, 40 | RadarChart, 41 | SVGRenderer, 42 | PictorialBarChart, 43 | RadarComponent, 44 | ToolboxComponent, 45 | DataZoomComponent, 46 | VisualMapComponent, 47 | TimelineComponent, 48 | CalendarComponent, 49 | GraphicComponent, 50 | ]) 51 | 52 | export default echarts 53 | -------------------------------------------------------------------------------- /apps/ant-admin/src/hooks/web/useContextMenu.ts: -------------------------------------------------------------------------------- 1 | import { onUnmounted, getCurrentInstance } from 'vue' 2 | import { 3 | createContextMenu, 4 | destroyContextMenu, 5 | } from '@/components/context-menu' 6 | import type { ContextMenuItem } from '@/components/context-menu' 7 | export type { ContextMenuItem } 8 | export function useContextMenu(authRemove = true) { 9 | if (getCurrentInstance() && authRemove) { 10 | onUnmounted(() => { 11 | destroyContextMenu() 12 | }) 13 | } 14 | return [createContextMenu, destroyContextMenu] 15 | } 16 | -------------------------------------------------------------------------------- /apps/ant-admin/src/hooks/web/useDesign.ts: -------------------------------------------------------------------------------- 1 | import { useAppProviderContext } from '@/components/application' 2 | export function useDesign(scope: string) { 3 | const values = useAppProviderContext() 4 | // const $style = cssModule ? useCssModule() : {}; 5 | 6 | // const style: Record = {}; 7 | // if (cssModule) { 8 | // Object.keys($style).forEach((key) => { 9 | // // const moduleCls = $style[key]; 10 | // const k = key.replace(new RegExp(`^${values.prefixCls}-?`, 'ig'), ''); 11 | // style[lowerFirst(k)] = $style[key]; 12 | // }); 13 | // } 14 | return { 15 | // prefixCls: computed(() => `${values.prefixCls}-${scope}`), 16 | prefixCls: `${values.prefixCls}-${scope}`, 17 | prefixVar: values.prefixCls, 18 | // style, 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /apps/ant-admin/src/hooks/web/useFullContent.ts: -------------------------------------------------------------------------------- 1 | import { computed, unref } from 'vue' 2 | 3 | import { useAppStore } from '@/store/app' 4 | 5 | import { useRouter } from 'vue-router' 6 | 7 | /** 8 | * @description: Full screen display content 9 | */ 10 | export const useFullContent = () => { 11 | const appStore = useAppStore() 12 | const router = useRouter() 13 | const { currentRoute } = router 14 | 15 | // Whether to display the content in full screen without displaying the menu 16 | const getFullContent = computed(() => { 17 | // Query parameters, the full screen is displayed when the address bar has a full parameter 18 | const route = unref(currentRoute) 19 | const query = route.query 20 | if (query && Reflect.has(query, '__full__')) { 21 | return true 22 | } 23 | // Return to the configuration in the configuration file 24 | return appStore.getProjectConfig.fullContent 25 | }) 26 | 27 | return { getFullContent } 28 | } 29 | -------------------------------------------------------------------------------- /apps/ant-admin/src/hooks/web/useSortable.ts: -------------------------------------------------------------------------------- 1 | import type { Ref } from 'vue' 2 | import type { Options } from 'sortablejs' 3 | 4 | import { nextTick, unref } from 'vue' 5 | 6 | export function useSortable( 7 | el: HTMLElement | Ref, 8 | options?: Options, 9 | ) { 10 | function initSortable() { 11 | nextTick(async () => { 12 | if (!el) return 13 | 14 | const Sortable = (await import('sortablejs')).default 15 | Sortable.create(unref(el), { 16 | animation: 500, 17 | delay: 400, 18 | delayOnTouchOnly: true, 19 | ...options, 20 | }) 21 | }) 22 | } 23 | 24 | return { initSortable } 25 | } 26 | -------------------------------------------------------------------------------- /apps/ant-admin/src/internal/factory/component-factory.ts: -------------------------------------------------------------------------------- 1 | import { defineAsyncComponent, h } from 'vue' 2 | import { Spin } from 'ant-design-vue' 3 | import { NOOP } from '@pkg/utils' 4 | 5 | interface Options { 6 | size?: 'default' | 'small' | 'large' 7 | delay?: number 8 | timeout?: number 9 | loading?: boolean 10 | retry?: boolean 11 | } 12 | 13 | export const createAsyncComponent = ( 14 | loader: AnyFunction, 15 | options: Options = {}, 16 | ) => { 17 | const { 18 | size = 'small', 19 | delay = 100, 20 | timeout = 30000, 21 | loading = false, 22 | retry = true, 23 | } = options 24 | return defineAsyncComponent({ 25 | loader, 26 | loadingComponent: loading ? h(Spin, { spinning: true, size }) : undefined, 27 | timeout, 28 | delay, 29 | onError: !retry 30 | ? NOOP 31 | : (error, retry, fail, attempts) => { 32 | if (error.message.match(/fetch/) && attempts <= 3) { 33 | retry() 34 | } else { 35 | fail() 36 | } 37 | }, 38 | }) 39 | } 40 | -------------------------------------------------------------------------------- /apps/ant-admin/src/internal/factory/index.ts: -------------------------------------------------------------------------------- 1 | export { createAsyncComponent } from './component-factory' 2 | -------------------------------------------------------------------------------- /apps/ant-admin/src/internal/index.ts: -------------------------------------------------------------------------------- 1 | export * from './config' 2 | export * from './pinia' 3 | export * from './factory' 4 | export * from './component' 5 | -------------------------------------------------------------------------------- /apps/ant-admin/src/internal/pinia/index.ts: -------------------------------------------------------------------------------- 1 | import { createPinia } from 'pinia' 2 | import { createPersistPlugin } from './persist' 3 | import { createStorageName } from '@/internal/config' 4 | 5 | const pinia = createPinia() 6 | 7 | // Persistence plugin, modified from open source, adding namespace support 8 | pinia.use(createPersistPlugin({ namespace: createStorageName() })) 9 | 10 | export { pinia } 11 | -------------------------------------------------------------------------------- /apps/ant-admin/src/layouts/default/content/useContentContext.ts: -------------------------------------------------------------------------------- 1 | import type { InjectionKey, ComputedRef } from 'vue' 2 | import { createContext, useContext } from '@pkg/use' 3 | 4 | export interface ContentContextProps { 5 | contentHeight: ComputedRef 6 | setPageHeight: (height: number) => Promise 7 | } 8 | 9 | const key: InjectionKey = Symbol() 10 | 11 | export function createContentContext(context: ContentContextProps) { 12 | return createContext(context, key, { native: true }) 13 | } 14 | 15 | export function useContentContext() { 16 | return useContext(key) 17 | } 18 | -------------------------------------------------------------------------------- /apps/ant-admin/src/layouts/default/header/components/FullScreen.vue: -------------------------------------------------------------------------------- 1 | 9 | 41 | -------------------------------------------------------------------------------- /apps/ant-admin/src/layouts/default/header/components/index.ts: -------------------------------------------------------------------------------- 1 | import { createAsyncComponent } from '@/internal' 2 | import FullScreen from './FullScreen.vue' 3 | import UserDropDown from './user-dropdown/index.vue' 4 | 5 | export const LayoutBreadcrumb = createAsyncComponent( 6 | () => import('./Breadcrumb.vue'), 7 | ) 8 | 9 | export const Notify = createAsyncComponent(() => import('./notify/index.vue')) 10 | 11 | export { FullScreen, UserDropDown } 12 | -------------------------------------------------------------------------------- /apps/ant-admin/src/layouts/default/header/components/user-dropdown/DropMenuItem.vue: -------------------------------------------------------------------------------- 1 | 9 | 30 | -------------------------------------------------------------------------------- /apps/ant-admin/src/layouts/default/setting/components/index.ts: -------------------------------------------------------------------------------- 1 | import { createAsyncComponent } from '@/internal' 2 | 3 | export const TypePicker = createAsyncComponent(() => import('./TypePicker.vue')) 4 | export const ThemeColorPicker = createAsyncComponent( 5 | () => import('./ThemeColorPicker.vue'), 6 | ) 7 | export const SettingFooter = createAsyncComponent( 8 | () => import('./SettingFooter.vue'), 9 | ) 10 | export const SwitchItem = createAsyncComponent(() => import('./SwitchItem.vue')) 11 | export const SelectItem = createAsyncComponent(() => import('./SelectItem.vue')) 12 | export const InputNumberItem = createAsyncComponent( 13 | () => import('./InputNumberItem.vue'), 14 | ) 15 | -------------------------------------------------------------------------------- /apps/ant-admin/src/layouts/default/setting/index.vue: -------------------------------------------------------------------------------- 1 | 7 | 27 | -------------------------------------------------------------------------------- /apps/ant-admin/src/layouts/default/tabs/components/TabRedo.vue: -------------------------------------------------------------------------------- 1 | 6 | 34 | -------------------------------------------------------------------------------- /apps/ant-admin/src/layouts/default/tabs/types.ts: -------------------------------------------------------------------------------- 1 | import type { DropMenu } from '@/components/dropdown/index' 2 | import type { RouteLocationNormalized } from 'vue-router' 3 | 4 | export enum TabContentEnum { 5 | TAB_TYPE, 6 | EXTRA_TYPE, 7 | } 8 | 9 | export type { DropMenu } 10 | 11 | export interface TabContentProps { 12 | tabItem: RouteLocationNormalized 13 | type?: TabContentEnum 14 | trigger?: ('click' | 'hover' | 'contextmenu')[] 15 | } 16 | 17 | export enum MenuEventEnum { 18 | REFRESH_PAGE, 19 | CLOSE_CURRENT, 20 | CLOSE_LEFT, 21 | CLOSE_RIGHT, 22 | CLOSE_OTHER, 23 | CLOSE_ALL, 24 | SCALE, 25 | } 26 | -------------------------------------------------------------------------------- /apps/ant-admin/src/layouts/default/trigger/HeaderTrigger.vue: -------------------------------------------------------------------------------- 1 | 6 | 28 | -------------------------------------------------------------------------------- /apps/ant-admin/src/layouts/default/trigger/SiderTrigger.vue: -------------------------------------------------------------------------------- 1 | 7 | 22 | -------------------------------------------------------------------------------- /apps/ant-admin/src/layouts/default/trigger/index.vue: -------------------------------------------------------------------------------- 1 | 5 | 28 | -------------------------------------------------------------------------------- /apps/ant-admin/src/layouts/iframe/index.vue: -------------------------------------------------------------------------------- 1 | 10 | 11 | 22 | -------------------------------------------------------------------------------- /apps/ant-admin/src/logics/mitt/route-change.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Used to monitor routing changes to change the status of menus and tabs. There is no need to monitor the route, because the route status change is affected by the page rendering time, which will be slow 3 | */ 4 | import type { RouteLocationNormalized } from 'vue-router' 5 | 6 | import { mitt, getRawRoute } from '@pkg/utils' 7 | 8 | const emitter = mitt() 9 | 10 | const key = Symbol() 11 | 12 | let lastChangeTab: RouteLocationNormalized 13 | 14 | export function setRouteChange(lastChangeRoute: RouteLocationNormalized) { 15 | const _router = getRawRoute(lastChangeRoute) 16 | emitter.emit(key, _router) 17 | lastChangeTab = _router 18 | } 19 | 20 | export function listenerRouteChange( 21 | callback: (route: RouteLocationNormalized) => void, 22 | immediate = true, 23 | ) { 24 | emitter.on(key, callback) 25 | immediate && lastChangeTab && callback(lastChangeTab) 26 | } 27 | 28 | export function removeTabChangeListener() { 29 | emitter.clear() 30 | } 31 | -------------------------------------------------------------------------------- /apps/ant-admin/src/logics/theme/dark.ts: -------------------------------------------------------------------------------- 1 | import { darkCssIsReady, loadDarkThemeCss } from 'vite-plugin-theme/es/client' 2 | import { addClass, hasClass, removeClass } from '@pkg/utils' 3 | 4 | export async function updateDarkTheme(mode: string | null = 'light') { 5 | const htmlRoot = document.getElementById('htmlRoot') 6 | if (!htmlRoot) { 7 | return 8 | } 9 | const hasDarkClass = hasClass(htmlRoot, 'dark') 10 | if (mode === 'dark') { 11 | if (import.meta.env.PROD && !darkCssIsReady) { 12 | await loadDarkThemeCss() 13 | } 14 | htmlRoot.setAttribute('data-theme', 'dark') 15 | if (!hasDarkClass) { 16 | addClass(htmlRoot, 'dark') 17 | } 18 | } else { 19 | htmlRoot.setAttribute('data-theme', 'light') 20 | if (hasDarkClass) { 21 | removeClass(htmlRoot, 'dark') 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /apps/ant-admin/src/logics/theme/index.ts: -------------------------------------------------------------------------------- 1 | import { getThemeColors, generateColors } from './theme' 2 | 3 | import { replaceStyleVariables } from 'vite-plugin-theme/es/client' 4 | import { 5 | mixLighten, 6 | mixDarken, 7 | tinycolor, 8 | } from 'vite-plugin-theme/es/colorUtils' 9 | 10 | export async function changeTheme(color: string) { 11 | const colors = generateColors({ 12 | mixDarken, 13 | mixLighten, 14 | tinycolor, 15 | color, 16 | }) 17 | 18 | return await replaceStyleVariables({ 19 | colorVariables: [...getThemeColors(color), ...colors], 20 | }) 21 | } 22 | -------------------------------------------------------------------------------- /apps/ant-admin/src/logics/theme/update-color-weak.ts: -------------------------------------------------------------------------------- 1 | import { toggleClass } from './util' 2 | 3 | /** 4 | * Change the status of the project's color weakness mode 5 | * @param colorWeak 6 | */ 7 | export function updateColorWeak(colorWeak: boolean) { 8 | toggleClass(colorWeak, 'color-weak', document.documentElement) 9 | } 10 | -------------------------------------------------------------------------------- /apps/ant-admin/src/logics/theme/update-gray-mode.ts: -------------------------------------------------------------------------------- 1 | import { toggleClass } from './util' 2 | 3 | /** 4 | * Change project gray mode status 5 | * @param gray 6 | */ 7 | export function updateGrayMode(gray: boolean) { 8 | toggleClass(gray, 'gray-mode', document.documentElement) 9 | } 10 | -------------------------------------------------------------------------------- /apps/ant-admin/src/logics/theme/util.ts: -------------------------------------------------------------------------------- 1 | const docEle = document.documentElement 2 | export function toggleClass( 3 | flag: boolean, 4 | clsName: string, 5 | target?: HTMLElement, 6 | ) { 7 | const targetEl = target || document.body 8 | let { className } = targetEl 9 | className = className.replace(clsName, '') 10 | targetEl.className = flag ? `${className} ${clsName} ` : className 11 | } 12 | 13 | export function setCssVar(prop: string, val: any, dom = docEle) { 14 | dom.style.setProperty(prop, val) 15 | } 16 | -------------------------------------------------------------------------------- /apps/ant-admin/src/router/constant.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * @description: default layout 3 | */ 4 | export const LAYOUT = () => import('@/layouts/default/index.vue') 5 | 6 | /** 7 | * @description: parent-layout 8 | */ 9 | export const getParentLayout = () => () => 10 | new Promise((resolve) => { 11 | resolve({ name: 'ParentLayout' }) 12 | }) 13 | 14 | -------------------------------------------------------------------------------- /apps/ant-admin/src/router/guard/state.ts: -------------------------------------------------------------------------------- 1 | import type { Router } from 'vue-router' 2 | import { useAppStore } from '@/store/app' 3 | import { useMultipleTabStore } from '@/store/multiple-tab' 4 | import { useUserStore } from '@/store/user' 5 | import { usePermissionStore } from '@/store/permission' 6 | import { PageEnum } from '@pkg/tokens' 7 | import { removeTabChangeListener } from '@/logics/mitt/route-change' 8 | 9 | export function createStateGuard(router: Router) { 10 | router.afterEach((to) => { 11 | // Just enter the login page and clear the authentication information 12 | if (to.path === PageEnum.BASE_LOGIN) { 13 | const tabStore = useMultipleTabStore() 14 | const userStore = useUserStore() 15 | const appStore = useAppStore() 16 | const permissionStore = usePermissionStore() 17 | appStore.resetAllState() 18 | permissionStore.resetState() 19 | tabStore.resetState() 20 | userStore.resetState() 21 | removeTabChangeListener() 22 | } 23 | }) 24 | } 25 | -------------------------------------------------------------------------------- /apps/ant-admin/src/router/index.ts: -------------------------------------------------------------------------------- 1 | import type { App } from 'vue' 2 | import { createRouter, createWebHistory } from 'vue-router' 3 | import { basicRoutes } from './routes' 4 | 5 | // 白名单应该包含基本静态路由 6 | const WHITE_NAME_LIST: string[] = [] 7 | 8 | ;(() => { 9 | const getRouteNames = (array: any[]) => 10 | array.forEach((item) => { 11 | WHITE_NAME_LIST.push(item.name) 12 | getRouteNames(item.children || []) 13 | }) 14 | 15 | getRouteNames(basicRoutes) 16 | })() 17 | 18 | // app router 19 | export const router = createRouter({ 20 | history: createWebHistory(import.meta.env.VITE_PUBLIC_PATH), 21 | routes: basicRoutes, 22 | strict: true, 23 | scrollBehavior: () => ({ left: 0, top: 0 }), 24 | }) 25 | 26 | // reset router 27 | export const resetRouter = () => { 28 | router.getRoutes().forEach((route) => { 29 | const { name } = route 30 | if (name && !WHITE_NAME_LIST.includes(name as string)) { 31 | router.hasRoute(name) && router.removeRoute(name) 32 | } 33 | }) 34 | } 35 | 36 | // config router 37 | export const setupRouter = (app: App) => app.use(router) 38 | -------------------------------------------------------------------------------- /apps/ant-admin/src/router/routes/mainOut.ts: -------------------------------------------------------------------------------- 1 | /** 2 | The routing of this file will not show the layout. 3 | It is an independent new page. 4 | the contents of the file still need to log in to access 5 | Test with annotations turned on 6 | 7 | 这个文件的路由不会显示布局。 8 | 这是一个独立的新页面。 9 | 文件内容仍需登录才能访问 10 | 打开注释后进行测试 11 | */ 12 | 13 | // test 14 | // http:ip:port/main-out 15 | export const mainOutRoutes: RouteRecordItem[] = [ 16 | // { 17 | // path: '/main-out', 18 | // name: 'MainOut', 19 | // component: () => import('@/views/demo/main-out/index.vue'), 20 | // meta: { 21 | // title: 'MainOut', 22 | // ignoreAuth: true, 23 | // }, 24 | // }, 25 | ] 26 | 27 | export const mainOutRouteNames = mainOutRoutes.map((item) => item.name) 28 | -------------------------------------------------------------------------------- /apps/ant-admin/src/router/routes/modules/about.ts: -------------------------------------------------------------------------------- 1 | import { LAYOUT } from '@/router/constant' 2 | import { t } from '@pkg/locale' 3 | 4 | const dashboard: RouteRecordItem = { 5 | path: '/about', 6 | name: 'About', 7 | component: LAYOUT, 8 | redirect: '/about/index', 9 | meta: { 10 | hideChildrenInMenu: true, 11 | icon: 'simple-icons:about-dot-me', 12 | title: t('routes.dashboard.about'), 13 | orderNo: 100000, 14 | }, 15 | children: [ 16 | { 17 | path: 'index', 18 | name: 'AboutPage', 19 | component: () => import('@/views/sys/about/index.vue'), 20 | meta: { 21 | title: t('routes.dashboard.about'), 22 | icon: 'simple-icons:about-dot-me', 23 | hideMenu: true, 24 | }, 25 | }, 26 | ], 27 | } 28 | 29 | export default dashboard 30 | -------------------------------------------------------------------------------- /apps/ant-admin/src/router/routes/modules/crm/index.ts: -------------------------------------------------------------------------------- 1 | import { LAYOUT } from '@/router/constant' 2 | import { t } from '@pkg/locale' 3 | 4 | const crm: RouteRecordItem = { 5 | path: '/crm', 6 | name: 'crm', 7 | component: LAYOUT, 8 | redirect: '/crm/customer', 9 | meta: { 10 | orderNo: 2001, 11 | icon: 'carbon:development', 12 | title: t('routes.crm.crm'), 13 | }, 14 | children: [ 15 | { 16 | path: 'customer', 17 | name: 'customer', 18 | component: () => import('@/views/CRM/Customer/index.vue'), 19 | meta: { 20 | // affix: true, 21 | title: t('routes.crm.customer'), 22 | }, 23 | }, 24 | ], 25 | } 26 | 27 | export default crm 28 | -------------------------------------------------------------------------------- /apps/ant-admin/src/router/routes/modules/dashboard.ts: -------------------------------------------------------------------------------- 1 | import { LAYOUT } from '@/router/constant' 2 | import { t } from '@pkg/locale' 3 | 4 | const dashboard: RouteRecordItem = { 5 | path: '/dashboard', 6 | name: 'Dashboard', 7 | component: LAYOUT, 8 | redirect: '/dashboard/analysis', 9 | meta: { 10 | orderNo: 10, 11 | icon: 'ion:grid-outline', 12 | title: t('routes.dashboard.dashboard'), 13 | }, 14 | children: [ 15 | { 16 | path: 'analysis', 17 | name: 'Analysis', 18 | component: () => import('@/views/dashboard/analysis/index.vue'), 19 | meta: { 20 | // affix: true, 21 | title: t('routes.dashboard.analysis'), 22 | }, 23 | }, 24 | { 25 | path: 'workbench', 26 | name: 'Workbench', 27 | component: () => import('@/views/dashboard/workbench/index.vue'), 28 | meta: { 29 | title: t('routes.dashboard.workbench'), 30 | }, 31 | }, 32 | ], 33 | } 34 | 35 | export default dashboard 36 | -------------------------------------------------------------------------------- /apps/ant-admin/src/router/types.ts: -------------------------------------------------------------------------------- 1 | import type { RouteMeta } from 'vue-router' 2 | import { RoleEnum } from '@pkg/tokens' 3 | 4 | export interface MenuTag { 5 | type?: 'primary' | 'error' | 'warn' | 'success' 6 | content?: string 7 | dot?: boolean 8 | } 9 | 10 | export interface Menu { 11 | name: string 12 | 13 | icon?: string 14 | 15 | path: string 16 | 17 | // path contains param, auto assignment. 18 | paramPath?: string 19 | 20 | disabled?: boolean 21 | 22 | children?: Menu[] 23 | 24 | orderNo?: number 25 | 26 | roles?: RoleEnum[] 27 | 28 | meta?: Partial 29 | 30 | tag?: MenuTag 31 | 32 | hideMenu?: boolean 33 | } 34 | 35 | export interface MenuModule { 36 | orderNo?: number 37 | menu: Menu 38 | } 39 | -------------------------------------------------------------------------------- /apps/ant-admin/src/styles/ant/amis_override.less: -------------------------------------------------------------------------------- 1 | @import './pagination.less'; 2 | 3 | .ant-message { 4 | z-index: 10000000 !important; 5 | } 6 | 7 | .ant-message .anticon { 8 | top: -5px !important; 9 | } 10 | 11 | .anticon .anticon-bell { 12 | position: relative !important; 13 | top: -5px !important; 14 | } 15 | -------------------------------------------------------------------------------- /apps/ant-admin/src/styles/ant/index.less: -------------------------------------------------------------------------------- 1 | @import './pagination.less'; 2 | @import './amis_override.less'; 3 | 4 | .modal-icon-warning { 5 | color: @warning-color !important; 6 | } 7 | 8 | .modal-icon-success { 9 | color: @success-color !important; 10 | } 11 | 12 | .modal-icon-error { 13 | color: @error-color !important; 14 | } 15 | 16 | .modal-icon-info { 17 | color: @primary-color !important; 18 | } 19 | 20 | .ant-checkbox-checked .ant-checkbox-inner::after, 21 | .ant-tree-checkbox-checked .ant-tree-checkbox-inner::after { 22 | border-top: 0 !important; 23 | border-left: 0 !important; 24 | } 25 | -------------------------------------------------------------------------------- /apps/ant-admin/src/styles/config.less: -------------------------------------------------------------------------------- 1 | @import (reference) 'color.less'; 2 | @import (reference) 'var/index.less'; 3 | -------------------------------------------------------------------------------- /apps/ant-admin/src/styles/index.less: -------------------------------------------------------------------------------- 1 | @import 'transition.less'; 2 | @import 'var/index.less'; 3 | @import 'public.less'; 4 | @import 'ant/index.less'; 5 | @import './theme.less'; 6 | 7 | input:-webkit-autofill { 8 | box-shadow: 0 0 0 1000px white inset !important; 9 | } 10 | 11 | :-webkit-autofill { 12 | transition: background-color 5000s ease-in-out 0s !important; 13 | } 14 | 15 | html { 16 | overflow: hidden; 17 | text-size-adjust: 100%; 18 | } 19 | 20 | html, 21 | body { 22 | width: 100%; 23 | height: 100%; 24 | overflow: visible !important; 25 | overflow-x: hidden !important; 26 | 27 | &.color-weak { 28 | filter: invert(80%); 29 | } 30 | 31 | &.gray-mode { 32 | filter: grayscale(100%); 33 | filter: progid:dximagetransform.microsoft.basicimage(grayscale=1); 34 | } 35 | } 36 | 37 | a:focus, 38 | a:active, 39 | button, 40 | div, 41 | svg, 42 | span { 43 | outline: none !important; 44 | } 45 | -------------------------------------------------------------------------------- /apps/ant-admin/src/styles/index.ts: -------------------------------------------------------------------------------- 1 | import './index.less' 2 | import './tailwind.css' 3 | import 'ant-design-vue/dist/antd.less' 4 | -------------------------------------------------------------------------------- /apps/ant-admin/src/styles/public.less: -------------------------------------------------------------------------------- 1 | #app { 2 | width: 100%; 3 | height: 100%; 4 | } 5 | 6 | ::-webkit-scrollbar { 7 | width: 7px; 8 | height: 8px; 9 | } 10 | 11 | ::-webkit-scrollbar-track { 12 | background-color: rgb(0 0 0 / 5%); 13 | } 14 | 15 | ::-webkit-scrollbar-thumb { 16 | background-color: rgb(144 147 153 / 30%); 17 | border-radius: 2px; 18 | box-shadow: inset 0 0 6px rgb(0 0 0 / 20%); 19 | } 20 | 21 | ::-webkit-scrollbar-thumb:hover { 22 | background-color: @border-color-dark; 23 | } 24 | 25 | // ================================= 26 | // ==============nprogress========== 27 | // ================================= 28 | #nprogress { 29 | pointer-events: none; 30 | 31 | .bar { 32 | position: fixed; 33 | top: 0; 34 | left: 0; 35 | z-index: 99999; 36 | width: 100%; 37 | height: 2px; 38 | background-color: @primary-color; 39 | opacity: 0.75; 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /apps/ant-admin/src/styles/tailwind.css: -------------------------------------------------------------------------------- 1 | @tailwind base; 2 | @tailwind components; 3 | @tailwind utilities; 4 | -------------------------------------------------------------------------------- /apps/ant-admin/src/styles/transition.less: -------------------------------------------------------------------------------- 1 | .transition-default() { 2 | &-enter-active, 3 | &-leave-active { 4 | transition: 0.3s cubic-bezier(0.25, 0.8, 0.5, 1) !important; 5 | } 6 | 7 | &-move { 8 | transition: transform 0.4s; 9 | } 10 | } 11 | 12 | /* fade-slide */ 13 | .fade-slide-leave-active, 14 | .fade-slide-enter-active { 15 | transition: all 0.3s; 16 | } 17 | 18 | .fade-slide-enter-from { 19 | opacity: 0; 20 | transform: translateX(-30px); 21 | } 22 | 23 | .fade-slide-leave-to { 24 | opacity: 0; 25 | transform: translateX(30px); 26 | } 27 | 28 | .expand-transition { 29 | .transition-default(); 30 | } 31 | 32 | .expand-x-transition { 33 | .transition-default(); 34 | } 35 | -------------------------------------------------------------------------------- /apps/ant-admin/src/styles/var/breakpoint.less: -------------------------------------------------------------------------------- 1 | // ================================= 2 | // ==============屏幕断点============ 3 | // ================================= 4 | 5 | // Extra small screen / phone 6 | @screen-xs: 480px; 7 | @screen-xs-min: @screen-xs; 8 | 9 | // Small screen / tablet 10 | @screen-sm: 576px; 11 | @screen-sm-min: @screen-sm; 12 | 13 | // Medium screen / desktop 14 | @screen-md: 768px; 15 | @screen-md-min: @screen-md; 16 | 17 | // Large screen / wide desktop 18 | @screen-lg: 992px; 19 | @screen-lg-min: @screen-lg; 20 | 21 | // Extra large screen / full hd 22 | @screen-xl: 1200px; 23 | @screen-xl-min: @screen-xl; 24 | 25 | // Extra extra large screen / large desktop 26 | @screen-2xl: 1600px; 27 | @screen-2xl-min: @screen-2xl; 28 | 29 | @screen-xs-max: (@screen-sm-min - 1px); 30 | @screen-sm-max: (@screen-md-min - 1px); 31 | @screen-md-max: (@screen-lg-min - 1px); 32 | @screen-lg-max: (@screen-xl-min - 1px); 33 | @screen-xl-max: (@screen-2xl-min - 1px); 34 | -------------------------------------------------------------------------------- /apps/ant-admin/src/styles/var/easing.less: -------------------------------------------------------------------------------- 1 | // ================================= 2 | // ==============动画函数-=========== 3 | // ================================= 4 | 5 | @ease-base-out: cubic-bezier(0.7, 0.3, 0.1, 1); 6 | @ease-base-in: cubic-bezier(0.9, 0, 0.3, 0.7); 7 | @ease-out: cubic-bezier(0.215, 0.61, 0.355, 1); 8 | @ease-in: cubic-bezier(0.55, 0.055, 0.675, 0.19); 9 | @ease-in-out: cubic-bezier(0.645, 0.045, 0.355, 1); 10 | @ease-out-back: cubic-bezier(0.12, 0.4, 0.29, 1.46); 11 | @ease-in-back: cubic-bezier(0.71, -0.46, 0.88, 0.6); 12 | @ease-in-out-back: cubic-bezier(0.71, -0.46, 0.29, 1.46); 13 | @ease-out-circ: cubic-bezier(0.08, 0.82, 0.17, 1); 14 | @ease-in-circ: cubic-bezier(0.6, 0.04, 0.98, 0.34); 15 | @ease-in-out-circ: cubic-bezier(0.78, 0.14, 0.15, 0.86); 16 | @ease-out-quint: cubic-bezier(0.23, 1, 0.32, 1); 17 | @ease-in-quint: cubic-bezier(0.755, 0.05, 0.855, 0.06); 18 | @ease-in-out-quint: cubic-bezier(0.86, 0, 0.07, 1); 19 | -------------------------------------------------------------------------------- /apps/ant-admin/src/styles/var/index.less: -------------------------------------------------------------------------------- 1 | @import (reference) '../color.less'; 2 | @import 'easing'; 3 | @import 'breakpoint'; 4 | 5 | @namespace: vben; 6 | 7 | // tabs 8 | @multiple-height: 30px; 9 | 10 | // headers 11 | @header-height: 48px; 12 | 13 | // logo width 14 | @logo-width: 32px; 15 | 16 | @side-drag-z-index: 200; 17 | 18 | @page-loading-z-index: 10000; 19 | 20 | @lock-page-z-index: 3000; 21 | 22 | @layout-header-fixed-z-index: 500; 23 | 24 | @multiple-tab-fixed-z-index: 505; 25 | 26 | @layout-sider-fixed-z-index: 510; 27 | 28 | @layout-mix-sider-fixed-z-index: 550; 29 | 30 | @preview-comp-z-index: 1000; 31 | 32 | @page-footer-z-index: 99; 33 | -------------------------------------------------------------------------------- /apps/ant-admin/src/views/DynamicPage/EditModal.vue: -------------------------------------------------------------------------------- 1 | 7 | 35 | -------------------------------------------------------------------------------- /apps/ant-admin/src/views/amis/schematpls/formItem_contentPicker.json: -------------------------------------------------------------------------------- 1 | { 2 | "label": "内容项选择下拉菜单", 3 | "name": "select", 4 | "type": "select", 5 | "checkAll": false, 6 | "searchable": true, 7 | "autoComplete": { 8 | "method": "post", 9 | "url": "/api/graphql", 10 | "data": null, 11 | "dataType": "json", 12 | "requestAdaptor": "const query=`{\r\n options:customer(status: PUBLISHED, first: 10,\r\n where: {displayText_contains: \"${api.body.term}\"}) {\r\n label:displayText\r\n value:contentItemId\r\n }\r\n}`\r\napi.data={query}\r\n\r\nreturn api\r\n", 13 | "adaptor": "", 14 | "replaceData": false 15 | } 16 | } -------------------------------------------------------------------------------- /apps/ant-admin/src/views/dashboard/analysis/components/SiteAnalysis.vue: -------------------------------------------------------------------------------- 1 | 16 | 39 | -------------------------------------------------------------------------------- /apps/ant-admin/src/views/dashboard/analysis/components/props.ts: -------------------------------------------------------------------------------- 1 | import { PropType } from 'vue' 2 | 3 | export interface BasicProps { 4 | width: string 5 | height: string 6 | } 7 | export const basicProps = { 8 | width: { 9 | type: String as PropType, 10 | default: '100%', 11 | }, 12 | height: { 13 | type: String as PropType, 14 | default: '280px', 15 | }, 16 | } 17 | -------------------------------------------------------------------------------- /apps/ant-admin/src/views/dashboard/analysis/data.ts: -------------------------------------------------------------------------------- 1 | export interface GrowCardItem { 2 | icon: string 3 | title: string 4 | value: number 5 | total: number 6 | color: string 7 | action: string 8 | } 9 | 10 | export const growCardList: GrowCardItem[] = [ 11 | { 12 | title: '访问数', 13 | icon: 'visit-count', 14 | value: 2000, 15 | total: 120000, 16 | color: 'green', 17 | action: '月', 18 | }, 19 | { 20 | title: '成交额', 21 | icon: 'total-sales', 22 | value: 20000, 23 | total: 500000, 24 | color: 'blue', 25 | action: '月', 26 | }, 27 | { 28 | title: '下载数', 29 | icon: 'download-count', 30 | value: 8000, 31 | total: 120000, 32 | color: 'orange', 33 | action: '周', 34 | }, 35 | { 36 | title: '成交数', 37 | icon: 'transaction', 38 | value: 5000, 39 | total: 50000, 40 | color: 'purple', 41 | action: '年', 42 | }, 43 | ] 44 | -------------------------------------------------------------------------------- /apps/ant-admin/src/views/dashboard/analysis/index.vue: -------------------------------------------------------------------------------- 1 | 15 | 29 | -------------------------------------------------------------------------------- /apps/ant-admin/src/views/dashboard/workbench/components/DynamicInfo.vue: -------------------------------------------------------------------------------- 1 | 26 | 34 | -------------------------------------------------------------------------------- /apps/ant-admin/src/views/dashboard/workbench/components/ProjectCard.vue: -------------------------------------------------------------------------------- 1 | 20 | 33 | -------------------------------------------------------------------------------- /apps/ant-admin/src/views/dashboard/workbench/components/QuickNav.vue: -------------------------------------------------------------------------------- 1 | 11 | 18 | -------------------------------------------------------------------------------- /apps/ant-admin/src/views/develop/contentType/dynamicIndex.vue: -------------------------------------------------------------------------------- 1 | 5 | 32 | -------------------------------------------------------------------------------- /apps/ant-admin/src/views/sys/iframe/FrameBlank.vue: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /apps/ant-admin/src/views/sys/lock/index.vue: -------------------------------------------------------------------------------- 1 | 6 | 14 | -------------------------------------------------------------------------------- /apps/ant-admin/src/views/sys/login/login-form-title.vue: -------------------------------------------------------------------------------- 1 | 21 | 28 | -------------------------------------------------------------------------------- /apps/ant-admin/src/views/sys/login/login.vue: -------------------------------------------------------------------------------- 1 | 5 | 22 | -------------------------------------------------------------------------------- /apps/ant-admin/src/views/sys/login/loginCallback.vue: -------------------------------------------------------------------------------- 1 | 5 | 20 | -------------------------------------------------------------------------------- /apps/ant-admin/src/views/sys/login/logoutcallback.vue: -------------------------------------------------------------------------------- 1 | 6 | 21 | -------------------------------------------------------------------------------- /apps/ant-admin/src/views/sys/login/qrcode-form.vue: -------------------------------------------------------------------------------- 1 | 16 | 17 | 33 | -------------------------------------------------------------------------------- /apps/ant-admin/src/views/sys/redirect/index.vue: -------------------------------------------------------------------------------- 1 | 27 | 28 | 31 | -------------------------------------------------------------------------------- /apps/ant-admin/src/views/system/account/index.vue: -------------------------------------------------------------------------------- 1 | 5 | 32 | -------------------------------------------------------------------------------- /apps/ant-admin/src/views/system/password/pwd.data.ts: -------------------------------------------------------------------------------- 1 | import { FormSchema } from '@/components/form' 2 | 3 | export const formSchema: FormSchema[] = [ 4 | { 5 | field: 'passwordOld', 6 | label: '当前密码', 7 | component: 'InputPassword', 8 | required: true, 9 | }, 10 | { 11 | field: 'passwordNew', 12 | label: '新密码', 13 | component: 'InputPassword', 14 | componentProps: { 15 | placeholder: '新密码', 16 | }, 17 | rules: [ 18 | { 19 | required: true, 20 | message: '请输入新密码', 21 | }, 22 | ], 23 | }, 24 | { 25 | field: 'confirmPassword', 26 | label: '确认密码', 27 | component: 'InputPassword', 28 | 29 | dynamicRules: ({ values }) => { 30 | return [ 31 | { 32 | required: true, 33 | validator: (_, value) => { 34 | if (!value) { 35 | return Promise.reject('不能为空') 36 | } 37 | if (value !== values.passwordNew) { 38 | return Promise.reject('两次输入的密码不一致!') 39 | } 40 | return Promise.resolve() 41 | }, 42 | }, 43 | ] 44 | }, 45 | }, 46 | ] 47 | -------------------------------------------------------------------------------- /apps/ant-admin/tailwind.config.js: -------------------------------------------------------------------------------- 1 | module.exports = require('@config/css-preprocess/tailwind') 2 | -------------------------------------------------------------------------------- /apps/ant-admin/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "tsconfig/base.json", 3 | "compilerOptions": { 4 | "target": "esnext", 5 | "module": "esnext", 6 | "baseUrl": ".", 7 | "paths": { 8 | "@/*": ["src/*"] 9 | }, 10 | "lib": ["dom", "esnext"], 11 | "types": ["vite/client"] 12 | }, 13 | "include": ["src", "mock", "vite.config.ts"] 14 | } 15 | -------------------------------------------------------------------------------- /apps/ant-admin/vite.config.ts: -------------------------------------------------------------------------------- 1 | import type { ViteConfig } from '@config/vite' 2 | import { createViteConfig } from '@config/vite' 3 | 4 | export default createViteConfig(process.cwd(), 'ant') as ViteConfig 5 | -------------------------------------------------------------------------------- /configs/css-preprocess/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@config/css-preprocess", 3 | "version": "0.0.0", 4 | "private": true, 5 | "files": [ 6 | "postcss.js", 7 | "tailwind.js" 8 | ], 9 | "scripts": { 10 | "clean": "pnpm rimraf node_modules && pnpm rimraf dist && pnpm rimraf .turbo" 11 | }, 12 | "dependencies": { 13 | "autoprefixer": "^10.4.4", 14 | "postcss": "^8.4.12", 15 | "tailwindcss": "^3.0.23" 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /configs/css-preprocess/postcss.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | plugins: { 3 | tailwindcss: {}, 4 | autoprefixer: {}, 5 | }, 6 | } 7 | -------------------------------------------------------------------------------- /configs/lint/commitlint.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | extends: ['@commitlint/config-conventional'], 3 | rules: { 4 | 'body-leading-blank': [2, 'always'], 5 | 'footer-leading-blank': [1, 'always'], 6 | 'header-max-length': [2, 'always', 108], 7 | 'subject-empty': [2, 'never'], 8 | 'type-empty': [2, 'never'], 9 | 'subject-case': [0], 10 | 'type-enum': [ 11 | 2, 12 | 'always', 13 | [ 14 | 'feat', 15 | 'fix', 16 | 'perf', 17 | 'style', 18 | 'docs', 19 | 'test', 20 | 'refactor', 21 | 'build', 22 | 'ci', 23 | 'chore', 24 | 'revert', 25 | 'workflow', 26 | 'types', 27 | 'wip', 28 | ], 29 | ], 30 | }, 31 | } 32 | -------------------------------------------------------------------------------- /configs/lint/lintstaged.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | '*.{js,jsx,ts,tsx}': ['eslint --fix', 'prettier --write'], 3 | '*.vue': ['eslint --fix', 'stylelint --fix', 'prettier --write'], 4 | '*.{scss,less,styl,html}': ['stylelint --fix', 'prettier --write'], 5 | } 6 | -------------------------------------------------------------------------------- /configs/lint/prettier.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | printWidth: 80, 3 | semi: false, 4 | singleQuote: true, 5 | trailingComma: 'all', 6 | endOfLine: 'auto', 7 | } 8 | -------------------------------------------------------------------------------- /configs/tsconfig/base.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://json.schemastore.org/tsconfig", 3 | "display": "Base", 4 | "compilerOptions": { 5 | "composite": false, 6 | "declaration": true, 7 | "declarationMap": true, 8 | "esModuleInterop": true, 9 | "jsx": "preserve", 10 | "allowJs": true, 11 | "strictFunctionTypes": false, 12 | "allowSyntheticDefaultImports": true, 13 | "forceConsistentCasingInFileNames": true, 14 | "inlineSources": false, 15 | "isolatedModules": true, 16 | "moduleResolution": "node", 17 | "noUnusedLocals": false, 18 | "noUnusedParameters": false, 19 | "preserveWatchOutput": true, 20 | "skipLibCheck": true, 21 | "strict": true, 22 | "resolveJsonModule": true, 23 | "removeComments": true, 24 | "noImplicitAny": false, 25 | "experimentalDecorators": true 26 | }, 27 | "exclude": ["**/node_modules/**", "**/dist/**"] 28 | } 29 | -------------------------------------------------------------------------------- /configs/tsconfig/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "tsconfig", 3 | "version": "0.0.0", 4 | "private": true, 5 | "files": [ 6 | "base.json", 7 | "server.json" 8 | ] 9 | } 10 | -------------------------------------------------------------------------------- /configs/tsconfig/server.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://json.schemastore.org/tsconfig", 3 | "display": "Server", 4 | "extends": "./base.json", 5 | "compilerOptions": { 6 | "module": "commonjs", 7 | "declaration": true, 8 | "experimentalDecorators": true, 9 | "emitDecoratorMetadata": true, 10 | "target": "esnext", 11 | "sourceMap": false, 12 | "lib": ["ESNext", "DOM"], 13 | "types": ["node"], 14 | "typeRoots": ["node_modules/@types/", "types"] 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /configs/vite/build.config.ts: -------------------------------------------------------------------------------- 1 | import { defineBuildConfig } from 'unbuild' 2 | 3 | export default defineBuildConfig({ 4 | clean: true, 5 | entries: ['src/index'], 6 | declaration: true, 7 | outDir: 'dist', 8 | rollup: { 9 | emitCJS: true, 10 | cjsBridge: true, 11 | }, 12 | }) 13 | -------------------------------------------------------------------------------- /configs/vite/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@config/vite", 3 | "version": "0.0.0", 4 | "private": true, 5 | "main": "dist/index.cjs", 6 | "types": "dist/index.d.ts", 7 | "scripts": { 8 | "clean": "pnpm rimraf node_modules && pnpm rimraf dist && pnpm rimraf .turbo", 9 | "prepack": "pnpm unbuild --stub" 10 | }, 11 | "dependencies": { 12 | "@ant-design/colors": "^6.0.0", 13 | "@vitejs/plugin-legacy": "^1.7.1", 14 | "@vitejs/plugin-vue": "^2.2.4", 15 | "@vitejs/plugin-vue-jsx": "^1.3.8", 16 | "dayjs": "^1.11.0", 17 | "less": "^4.1.2", 18 | "picocolors": "^1.0.0", 19 | "pkg-types": "^0.3.2", 20 | "rollup-plugin-visualizer": "^5.6.0", 21 | "tsconfig": "workspace:*", 22 | "vite": "2.9.0-beta.4", 23 | "vite-plugin-compression": "^0.5.1", 24 | "vite-plugin-html": "^3.2.0", 25 | "vite-plugin-imagemin": "^0.6.1", 26 | "vite-plugin-mkcert": "^1.6.0", 27 | "vite-plugin-mock": "^2.9.6", 28 | "vite-plugin-purge-icons": "^0.8.1", 29 | "vite-plugin-svg-icons": "^2.0.1", 30 | "vite-plugin-theme": "^0.8.6", 31 | "vite-plugin-vue-setup-extend": "^0.4.0" 32 | }, 33 | "devDependencies": { 34 | "mockjs": "^1.1.0", 35 | "vue": "^3.2.31" 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /configs/vite/src/constants.ts: -------------------------------------------------------------------------------- 1 | // The name of the configuration file entered in the production environment 2 | export const GLOB_CONFIG_FILE_NAME = '_app.config.js' 3 | 4 | // vite package output directory 5 | export const OUTPUT_DIR = 'dist' 6 | -------------------------------------------------------------------------------- /configs/vite/src/plugins/compress.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Used to package and output gzip. Note that this does not work properly in Vite, the specific reason is still being investigated 3 | * @see https://github.com/anncwb/vite-plugin-compression 4 | */ 5 | import type { PluginOption } from 'vite' 6 | import compressPlugin from 'vite-plugin-compression' 7 | 8 | export function configCompressPlugin( 9 | compress: 'gzip' | 'brotli' | 'none', 10 | deleteOriginFile = false, 11 | ) { 12 | const compressList = compress.split(',') 13 | 14 | const plugins: PluginOption[] = [] 15 | 16 | if (compressList.includes('gzip')) { 17 | plugins.push(compressPlugin({ deleteOriginFile })) 18 | } 19 | 20 | if (compressList.includes('brotli')) { 21 | plugins.push( 22 | compressPlugin({ 23 | algorithm: 'brotliCompress', 24 | deleteOriginFile, 25 | }), 26 | ) 27 | } 28 | return plugins 29 | } 30 | -------------------------------------------------------------------------------- /configs/vite/src/plugins/imagemin.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Image resource files used to compress the output of the production environment 3 | * @see https://github.com/anncwb/vite-plugin-imagemin 4 | */ 5 | import viteImagemin from 'vite-plugin-imagemin' 6 | 7 | export function configImageminPlugin() { 8 | return viteImagemin({ 9 | gifsicle: { 10 | optimizationLevel: 7, 11 | interlaced: false, 12 | }, 13 | optipng: { 14 | optimizationLevel: 7, 15 | }, 16 | mozjpeg: { 17 | quality: 20, 18 | }, 19 | pngquant: { 20 | quality: [0.8, 0.9], 21 | speed: 4, 22 | }, 23 | svgo: { 24 | plugins: [ 25 | { 26 | name: 'removeViewBox', 27 | }, 28 | { 29 | name: 'removeEmptyAttrs', 30 | active: false, 31 | }, 32 | ], 33 | }, 34 | }) 35 | } 36 | -------------------------------------------------------------------------------- /configs/vite/src/plugins/mock.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Mock plugin for development and production. 3 | * @see https://github.com/anncwb/vite-plugin-mock 4 | */ 5 | import { viteMockServe } from 'vite-plugin-mock' 6 | 7 | export function configMockPlugin(isBuild: boolean) { 8 | return viteMockServe({ 9 | ignore: /^\_/, 10 | mockPath: 'mock', 11 | localEnabled: !isBuild, 12 | prodEnabled: isBuild, 13 | }) 14 | } 15 | -------------------------------------------------------------------------------- /configs/vite/src/plugins/svg-icons.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Vite Plugin for fast creating SVG sprites. 3 | * @see https://github.com/anncwb/vite-plugin-svg-icons 4 | */ 5 | 6 | import { createSvgIconsPlugin } from 'vite-plugin-svg-icons' 7 | import { resolve } from 'path' 8 | 9 | export function configSvgIconsPlugin(isBuild: boolean) { 10 | const svgIconsPlugin = createSvgIconsPlugin({ 11 | iconDirs: [resolve(process.cwd(), 'src/assets/icons')], 12 | svgoOptions: isBuild, 13 | }) 14 | return svgIconsPlugin 15 | } 16 | -------------------------------------------------------------------------------- /configs/vite/src/plugins/visualizer.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Package file volume analysis 3 | * @see https://github.com/btd/rollup-plugin-visualizer 4 | */ 5 | import type { PluginOption } from 'vite' 6 | import visualizer from 'rollup-plugin-visualizer' 7 | 8 | export function configVisualizerConfig(): PluginOption { 9 | if (process.env.REPORT === 'true') { 10 | return visualizer({ 11 | filename: './node_modules/.cache/visualizer/stats.html', 12 | open: true, 13 | gzipSize: true, 14 | brotliSize: true, 15 | }) 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /configs/vite/src/presets/ant/index.ts: -------------------------------------------------------------------------------- 1 | import type { UserConfig } from 'vite' 2 | 3 | export async function createAntdPreset(command: string): Promise { 4 | const { generateModifyVars } = await import('./modify-vars') 5 | const { configThemePlugin } = await import('./theme-plugin') 6 | return { 7 | plugins: [ 8 | // vite-plugin-theme 9 | configThemePlugin(command === 'build'), 10 | ], 11 | optimizeDeps: { 12 | include: [ 13 | '@ant-design/icons-vue', 14 | 'ant-design-vue/es/locale/zh_CN', 15 | 'ant-design-vue/es/locale/en_US', 16 | ], 17 | exclude: ['vue-demi'], 18 | }, 19 | css: { 20 | preprocessorOptions: { 21 | less: { 22 | modifyVars: generateModifyVars(), 23 | javascriptEnabled: true, 24 | }, 25 | }, 26 | }, 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /configs/vite/src/presets/index.ts: -------------------------------------------------------------------------------- 1 | import { createAntdPreset } from './ant' 2 | 3 | export type FrameworkType = 'ant' 4 | 5 | export function createPreset(framework: FrameworkType) { 6 | const presets = { 7 | ant: createAntdPreset, 8 | } 9 | return presets[framework] 10 | } 11 | -------------------------------------------------------------------------------- /configs/vite/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "tsconfig/base.json", 3 | "include": ["src"], 4 | "exclude": ["dist", "node_modules"] 5 | } 6 | -------------------------------------------------------------------------------- /nswag/Templates/Client.Method.Documentation.liquid: -------------------------------------------------------------------------------- 1 | {% if operation.HasDocumentation -%} 2 | /** 3 | {% if operation.HasSummary -%} 4 | * {{ operation.Summary }} 5 | {% endif -%} 6 | {% for parameter in operation.Parameters -%} 7 | {% if parameter.HasDescriptionOrIsOptional -%} 8 | * @param {{ parameter.VariableName }}{% if parameter.IsOptional %} (optional){% endif %} {{ parameter.Description }} 9 | {% endif -%} 10 | {% endfor -%} 11 | {% if operation.HasResultDescription -%} 12 | * @return {{ operation.ResultDescription }} 13 | {% endif -%} 14 | {% if operation.IsDeprecated -%} 15 | * @deprecated 16 | {% endif -%} 17 | */ 18 | {% endif -%} -------------------------------------------------------------------------------- /nswag/Templates/Client.ProcessResponse.ReadBodyEnd.liquid: -------------------------------------------------------------------------------- 1 | {% if Framework.IsFetchOrAurelia or operation.RequestAngularBlobs or Framework.Angular.UseHttpClient or operation.RequestAngularJSBlobs -%} 2 | {% if Framework.IsAngular and Framework.UseRxJs6 and (Framework.Angular.UseHttpClient or operation.RequestAngularBlobs) -%} 3 | })); 4 | {% else -%} 5 | }); 6 | {% endif -%} 7 | {% endif -%} 8 | -------------------------------------------------------------------------------- /nswag/Templates/Client.ProcessResponse.ReadBodyStart.liquid: -------------------------------------------------------------------------------- 1 | {% if Framework.IsFetchOrAurelia -%} 2 | return response.text().then((_responseText) => { 3 | {% elseif Framework.Angular.UseHttpClient -%} 4 | {% if Framework.UseRxJs6 -%} 5 | return blobToText(responseBlob).pipe({{ Framework.RxJs.ObservableMergeMapMethod }}(_responseText => { 6 | {% else -%} 7 | return blobToText(responseBlob).flatMap(_responseText => { 8 | {% endif -%} 9 | {% elseif operation.RequestAngularBlobs -%} 10 | {% if Framework.UseRxJs6 -%} 11 | return blobToText(response.blob()).pipe({{ Framework.RxJs.ObservableMergeMapMethod }}(_responseText => { 12 | {% else -%} 13 | return blobToText(response.blob()).flatMap(_responseText => { 14 | {% endif -%} 15 | {% elseif operation.RequestAngularJSBlobs -%} 16 | return blobToText(new Blob([response]), this.q).then(_responseText => { 17 | {% elseif Framework.IsAngular -%} 18 | const _responseText = response.text(); 19 | {% elseif Framework.IsAngularJS -%} 20 | const _responseText = response.data; 21 | {% elseif Framework.IsAxios -%} 22 | const _responseText = response.data.data; 23 | {% else -%} 24 | const _responseText = xhr.responseText; 25 | {% endif -%} -------------------------------------------------------------------------------- /nswag/Templates/Client.ProcessResponse.ReadHeaders.liquid: -------------------------------------------------------------------------------- 1 | {% if Framework.IsAngular -%} 2 | {% if Framework.Angular.UseHttpClient -%} 3 | let _headers: any = {}; if (response.headers) { for (let key of response.headers.keys()) { _headers[key] = response.headers.get(key); }}; 4 | {% else -%} 5 | let _headers: any = response.headers ? response.headers.toJSON() : {}; 6 | {% endif -%} 7 | {% elseif Framework.IsFetchOrAurelia -%} 8 | let _headers: any = {}; if (response.headers && response.headers.forEach) { response.headers.forEach((v: any, k: any) => _headers[k] = v); }; 9 | {% elseif Framework.IsAxios -%} 10 | let _headers: any = {}; 11 | if (response.headers && typeof response.headers === "object") { 12 | for (let k in response.headers) { 13 | if (response.headers.hasOwnProperty(k)) { 14 | _headers[k] = response.headers[k]; 15 | } 16 | } 17 | } 18 | {% else -%} 19 | let _headers: any = {}; 20 | {% endif -%} -------------------------------------------------------------------------------- /nswag/Templates/Client.ProcessResponse.liquid: -------------------------------------------------------------------------------- 1 | {% template Client.ProcessResponse.ReadHeaders %} 2 | {% if operation.HandleReferences and operation.RequiresMappings -%} 3 | let _mappings: { source: any, target: any }[] = []; 4 | {% endif -%} 5 | {% for response in operation.Responses -%} 6 | if (status === {{ response.StatusCode }}{% if response.CheckChunkedStatusCode %} || status === 206{% endif %}) { 7 | {% template Client.ProcessResponse.HandleStatusCode %} 8 | } else {% endfor -%} 9 | {% if operation.HasDefaultResponse -%} 10 | { 11 | {% assign response = operation.DefaultResponse -%} 12 | {% template Client.ProcessResponse.HandleStatusCode %} 13 | } 14 | {% else -%} 15 | if (status !== 200 && status !== 204) { 16 | {% template Client.ProcessResponse.ReadBodyStart %} 17 | return throwException({% if Framework.IsAngularJS %}this.q, {% endif %}"An unexpected server error occurred.", status, _responseText, _headers); 18 | {% template Client.ProcessResponse.ReadBodyEnd %} 19 | } 20 | {% template Client.ProcessResponse.Return %} 21 | {% endif -%} -------------------------------------------------------------------------------- /nswag/refresh.bat: -------------------------------------------------------------------------------- 1 | "..\node_modules\.bin\nswag" run /runtime:NetCore31 2 | -------------------------------------------------------------------------------- /packages/apis/account.ts: -------------------------------------------------------------------------------- 1 | 2 | // import { request } from '../request' 3 | 4 | // enum Api { 5 | // ACCOUNT_INFO = '/account/getAccountInfo', 6 | // SESSION_TIMEOUT = '/user/sessionTimeout', 7 | // TOKEN_EXPIRED = '/user/tokenExpired', 8 | // } 9 | // export interface GetAccountInfoModel { 10 | // email: string 11 | // name: string 12 | // introduction: string 13 | // phone: string 14 | // address: string 15 | // } 16 | 17 | // // Get personal center-basic settings 18 | 19 | // export const accountInfoApi = () => 20 | // request.get({ url: Api.ACCOUNT_INFO }) 21 | 22 | // export const sessionTimeoutApi = () => 23 | // request.post({ url: Api.SESSION_TIMEOUT }) 24 | 25 | // export const tokenExpiredApi = () => 26 | // request.post({ url: Api.TOKEN_EXPIRED }) 27 | -------------------------------------------------------------------------------- /packages/apis/demo/account.ts: -------------------------------------------------------------------------------- 1 | import { request } from '@pkg/request' 2 | 3 | export interface GetAccountInfoModel { 4 | email: string 5 | name: string 6 | introduction: string 7 | phone: string 8 | address: string 9 | } 10 | 11 | enum Api { 12 | ACCOUNT_INFO = '/account/getAccountInfo', 13 | SESSION_TIMEOUT = '/user/sessionTimeout', 14 | TOKEN_EXPIRED = '/user/tokenExpired', 15 | } 16 | 17 | // Get personal center-basic settings 18 | 19 | export const accountInfoApi = () => 20 | request.get({ url: Api.ACCOUNT_INFO }) 21 | 22 | export const sessionTimeoutApi = () => 23 | request.post({ url: Api.SESSION_TIMEOUT }) 24 | 25 | export const tokenExpiredApi = () => 26 | request.post({ url: Api.TOKEN_EXPIRED }) 27 | -------------------------------------------------------------------------------- /packages/apis/demo/cascader.ts: -------------------------------------------------------------------------------- 1 | import { request } from '@pkg/request' 2 | 3 | export interface AreaModel { 4 | id: string 5 | code: string 6 | parentCode: string 7 | name: string 8 | levelType: number 9 | [key: string]: string | number 10 | } 11 | 12 | export interface AreaParams { 13 | parentCode: string 14 | } 15 | 16 | enum Api { 17 | AREA_RECORD = '/cascader/getAreaRecord', 18 | } 19 | 20 | export const areaRecord = (data: AreaParams) => 21 | request.post({ url: Api.AREA_RECORD, data }) 22 | -------------------------------------------------------------------------------- /packages/apis/demo/error.ts: -------------------------------------------------------------------------------- 1 | import { request } from '@pkg/request' 2 | 3 | enum Api { 4 | // The address does not exist 5 | Error = '/error', 6 | } 7 | 8 | /** 9 | * @description: Trigger ajax error 10 | */ 11 | 12 | export const fireErrorApi = () => request.get({ url: Api.Error }) 13 | -------------------------------------------------------------------------------- /packages/apis/demo/index.ts: -------------------------------------------------------------------------------- 1 | export * from './account' 2 | export * from './cascader' 3 | export * from './error' 4 | export * from './select' 5 | // export * from './system' 6 | export * from './table' 7 | export * from './tree' 8 | -------------------------------------------------------------------------------- /packages/apis/demo/select.ts: -------------------------------------------------------------------------------- 1 | import { request } from '@pkg/request' 2 | 3 | export interface DemoOptionsItem { 4 | label: string 5 | value: string 6 | } 7 | 8 | export interface SelectParams { 9 | id: number | string 10 | } 11 | 12 | enum Api { 13 | OPTIONS_LIST = '/select/getDemoOptions', 14 | } 15 | 16 | /** 17 | * @description: Get sample options value 18 | */ 19 | export const optionsListApi = (params?: SelectParams) => 20 | request.get({ url: Api.OPTIONS_LIST, params }) 21 | -------------------------------------------------------------------------------- /packages/apis/demo/table.ts: -------------------------------------------------------------------------------- 1 | import type { BasicPageParams, BasicFetchResult } from '../types' 2 | import { request } from '@pkg/request' 3 | 4 | /** 5 | * @description: Request list interface parameters 6 | */ 7 | export type DemoParams = BasicPageParams 8 | 9 | export interface DemoListItem { 10 | id: string 11 | beginTime: string 12 | endTime: string 13 | address: string 14 | name: string 15 | no: number 16 | status: number 17 | } 18 | 19 | /** 20 | * @description: Request list return value 21 | */ 22 | export type DemoListGetResultModel = BasicFetchResult 23 | 24 | enum Api { 25 | DEMO_LIST = '/table/getDemoList', 26 | } 27 | 28 | /** 29 | * @description: Get sample list value 30 | */ 31 | 32 | export const demoListApi = (params: DemoParams) => 33 | request.get({ 34 | url: Api.DEMO_LIST, 35 | params, 36 | headers: { 37 | // @ts-ignore 38 | ignoreCancelToken: true, 39 | }, 40 | }) 41 | -------------------------------------------------------------------------------- /packages/apis/demo/tree.ts: -------------------------------------------------------------------------------- 1 | import { request } from '@pkg/request' 2 | 3 | enum Api { 4 | TREE_OPTIONS_LIST = '/tree/getDemoOptions', 5 | } 6 | 7 | /** 8 | * @description: Get sample options value 9 | */ 10 | export const treeOptionsListApi = (params?: Recordable) => 11 | request.get({ url: Api.TREE_OPTIONS_LIST, params }) 12 | -------------------------------------------------------------------------------- /packages/apis/develop.ts: -------------------------------------------------------------------------------- 1 | import { ContentTypeManagementServiceProxy, Stereotype } from './eoc/app-service-proxies' 2 | 3 | export async function getAllTypes(params: { 4 | stereotype: number | Stereotype 5 | filter: string | undefined 6 | page: number | undefined 7 | pageSize: number | undefined 8 | }) { 9 | const data = await new ContentTypeManagementServiceProxy().getAllTypes(params) 10 | console.log(data, 'getAllTypes') 11 | return data 12 | } 13 | -------------------------------------------------------------------------------- /packages/apis/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@pkg/apis", 3 | "version": "3.0.0-alpha.4", 4 | "main": "index.ts", 5 | "module": "index.ts", 6 | "license": "MIT", 7 | "scripts": { 8 | "clean": "pnpm rimraf node_modules && pnpm rimraf dist && pnpm rimraf .turbo" 9 | }, 10 | "dependencies": { 11 | "@pkg/request": "workspace:*", 12 | "@pkg/types": "workspace:*" 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /packages/apis/sys/index.ts: -------------------------------------------------------------------------------- 1 | export * from './menu' 2 | export * from './upload' 3 | export * from './user' 4 | -------------------------------------------------------------------------------- /packages/apis/sys/menu.ts: -------------------------------------------------------------------------------- 1 | import { request } from '@pkg/request' 2 | 3 | export interface RouteItem { 4 | path: string 5 | component: any 6 | meta: any 7 | name?: string 8 | alias?: string | string[] 9 | redirect?: string 10 | caseSensitive?: boolean 11 | children?: RouteItem[] 12 | } 13 | 14 | 15 | /** 16 | * @description: Get menu return value 17 | */ 18 | export type GetMenuListResultModel = RouteItem[] 19 | 20 | enum Api { 21 | GetMenuList = '/getMenuList', 22 | } 23 | 24 | /** 25 | * @description: Get user menu based on id 26 | */ 27 | 28 | export const getMenuList = () => { 29 | return request.get({ url: Api.GetMenuList }) 30 | } 31 | -------------------------------------------------------------------------------- /packages/apis/sys/upload.ts: -------------------------------------------------------------------------------- 1 | import type { RequestUploadFileOptions } from '@pkg/types' 2 | import { request } from '@pkg/request' 3 | 4 | export interface UploadApiResult { 5 | message: string 6 | code: number 7 | url: string 8 | } 9 | 10 | /** 11 | * @description: Upload interface 12 | */ 13 | export function uploadApi( 14 | params: RequestUploadFileOptions, 15 | onUploadProgress: (progressEvent: ProgressEvent) => void, 16 | ) { 17 | return request.uploadFile( 18 | { 19 | // TODO 20 | // url: context.uploadUrl, 21 | onUploadProgress, 22 | }, 23 | params, 24 | ) 25 | } 26 | -------------------------------------------------------------------------------- /packages/apis/types.ts: -------------------------------------------------------------------------------- 1 | export interface BasicPageParams { 2 | page: number 3 | pageSize: number 4 | } 5 | 6 | export interface BasicFetchResult { 7 | items: T[] 8 | total: number 9 | } 10 | -------------------------------------------------------------------------------- /packages/components/antd/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@components/antd", 3 | "version": "3.0.0-alpha.4", 4 | "license": "MIT", 5 | "scripts": { 6 | "clean": "pnpm rimraf node_modules && pnpm rimraf dist && pnpm rimraf .turbo" 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /packages/components/common/index.ts: -------------------------------------------------------------------------------- 1 | export { default as CountTo } from './count-to/index.vue' 2 | export { default as SvgIcon } from './svg-icon/index.vue' 3 | export { default as Icon } from './icon/index.vue' 4 | export { default as Time } from './time/index.vue' 5 | export { default as CollapseTransition } from './transition/collapse-transition.vue' 6 | 7 | export { default as QrCode } from './qrcode/index.vue' 8 | export type { QrCodeActionType } from './qrcode/typing' 9 | -------------------------------------------------------------------------------- /packages/components/common/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@components/common", 3 | "version": "3.0.0-alpha.4", 4 | "main": "index.ts", 5 | "module": "index.ts", 6 | "license": "MIT", 7 | "scripts": { 8 | "clean": "pnpm rimraf node_modules && pnpm rimraf dist && pnpm rimraf .turbo" 9 | }, 10 | "dependencies": { 11 | "@pkg/locale": "workspace:*", 12 | "@pkg/use": "workspace:*", 13 | "@pkg/utils": "workspace:*", 14 | "qrcode": "^1.5.0" 15 | }, 16 | "devDependencies": { 17 | "@types/qrcode": "^1.4.2" 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /packages/components/common/qrcode/to-canvas.ts: -------------------------------------------------------------------------------- 1 | import type { RenderQrCodeParams } from './typing' 2 | import { renderQrCode } from './draw-canvas' 3 | import { drawLogo } from './draw-logo' 4 | 5 | export const toCanvas = (options: RenderQrCodeParams) => { 6 | return renderQrCode(options) 7 | .then(() => { 8 | return options 9 | }) 10 | .then(drawLogo) as Promise 11 | } 12 | -------------------------------------------------------------------------------- /packages/components/common/qrcode/typing.ts: -------------------------------------------------------------------------------- 1 | import type { QRCodeSegment, QRCodeRenderersOptions } from 'qrcode' 2 | 3 | export type ContentType = string | QRCodeSegment[] 4 | export type { QRCodeRenderersOptions } 5 | 6 | export type LogoType = { 7 | src: string 8 | logoSize: number 9 | borderColor: string 10 | bgColor: string 11 | borderSize: number 12 | crossOrigin: string 13 | borderRadius: number 14 | logoRadius: number 15 | } 16 | 17 | export interface RenderQrCodeParams { 18 | canvas: any 19 | content: ContentType 20 | width?: number 21 | options?: QRCodeRenderersOptions 22 | logo?: LogoType | string 23 | image?: HTMLImageElement 24 | downloadName?: string 25 | download?: boolean | AnyFunction 26 | } 27 | 28 | export type ToCanvasFn = (options: RenderQrCodeParams) => Promise 29 | 30 | export interface QrCodeActionType { 31 | download: (fileName?: string) => void 32 | } 33 | 34 | export interface QrcodeDoneEventParams { 35 | url: string 36 | ctx?: CanvasRenderingContext2D | null 37 | } 38 | -------------------------------------------------------------------------------- /packages/directives/bridge.ts: -------------------------------------------------------------------------------- 1 | import { RoleEnum } from '@pkg/tokens' 2 | 3 | export interface ContextOptions { 4 | hasPermission: ( 5 | value?: string | RoleEnum[] | string[] | undefined, 6 | def?: boolean, 7 | ) => boolean 8 | createLoading: AnyFunction 9 | } 10 | 11 | export let context: ContextOptions = { 12 | hasPermission: () => false, 13 | createLoading: () => {}, 14 | } 15 | 16 | export const initDirective = async (_context: ContextOptions) => { 17 | context = _context 18 | } 19 | -------------------------------------------------------------------------------- /packages/directives/index.ts: -------------------------------------------------------------------------------- 1 | import type { App } from 'vue' 2 | import { loading } from './src/loading' 3 | import { auth } from './src/auth' 4 | 5 | export { clickOutside } from './src/click-outside' 6 | export { auth, loading } 7 | export * from './bridge' 8 | 9 | export const registerGlobalDirective = (app: App) => { 10 | app.directive('loading', loading) 11 | app.directive('auth', auth) 12 | } 13 | -------------------------------------------------------------------------------- /packages/directives/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@pkg/directives", 3 | "version": "3.0.0-alpha.4", 4 | "main": "index.ts", 5 | "module": "index.ts", 6 | "types": "index.d.js", 7 | "unpkg": "index.js", 8 | "jsdelivr": "index.js", 9 | "license": "MIT", 10 | "scripts": { 11 | "clean": "pnpm rimraf node_modules && pnpm rimraf dist && pnpm rimraf .turbo" 12 | }, 13 | "dependencies": { 14 | "@pkg/utils": "workspace:*", 15 | "@pkg/tokens": "workspace:*" 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /packages/directives/src/auth.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Global authority directive 3 | * Used for fine-grained control of component permissions 4 | * @Example v-auth="RoleEnum.TEST" 5 | */ 6 | import type { Directive, DirectiveBinding } from 'vue' 7 | 8 | import { context } from '../bridge' 9 | 10 | const isAuth = (el: Element, binding: any) => { 11 | const value = binding.value 12 | if (!value) return 13 | if (!context.hasPermission(value)) { 14 | el.parentNode?.removeChild(el) 15 | } 16 | } 17 | 18 | const mounted = (el: Element, binding: DirectiveBinding) => { 19 | isAuth(el, binding) 20 | } 21 | 22 | const auth: Directive = { 23 | mounted, 24 | } 25 | 26 | export { auth } 27 | -------------------------------------------------------------------------------- /packages/directives/src/loading.ts: -------------------------------------------------------------------------------- 1 | import type { Directive } from 'vue' 2 | 3 | import { context } from '../bridge' 4 | 5 | const loading: Directive = { 6 | mounted(el, binding) { 7 | const tip = el.getAttribute('loading-tip') 8 | const background = el.getAttribute('loading-background') 9 | const size = el.getAttribute('loading-size') 10 | const fullscreen = !!binding.modifiers.fullscreen 11 | const instance = context.createLoading( 12 | { 13 | tip, 14 | background, 15 | size: size || 'large', 16 | loading: !!binding.value, 17 | absolute: !fullscreen, 18 | }, 19 | fullscreen ? document.body : el, 20 | ) 21 | el.instance = instance 22 | }, 23 | updated(el, binding) { 24 | const instance = el.instance 25 | if (!instance) return 26 | instance.setTip(el.getAttribute('loading-tip')) 27 | if (binding.oldValue !== binding.value) { 28 | instance.setLoading?.(binding.value && !instance.loading) 29 | } 30 | }, 31 | unmounted(el) { 32 | el?.instance?.close() 33 | }, 34 | } 35 | 36 | export { loading } 37 | -------------------------------------------------------------------------------- /packages/locale/index.ts: -------------------------------------------------------------------------------- 1 | export { setupI18n } from './src/setup-i18n' 2 | export { useI18n, t } from './src/use-i18n' 3 | export { useLocale } from './src/use-locale' 4 | export { showLocalePicker } from './src/store' 5 | -------------------------------------------------------------------------------- /packages/locale/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@pkg/locale", 3 | "version": "3.0.0-alpha.4", 4 | "main": "index.ts", 5 | "module": "index.ts", 6 | "license": "MIT", 7 | "scripts": { 8 | "clean": "pnpm rimraf node_modules && pnpm rimraf dist && pnpm rimraf .turbo" 9 | }, 10 | "optionalDependencies": { 11 | "vue": "^3.2.31" 12 | }, 13 | "dependencies": { 14 | "@pkg/setting": "workspace:*", 15 | "@pkg/tokens": "workspace:*", 16 | "@pkg/types": "workspace:*", 17 | "@pkg/utils": "workspace:*", 18 | "@vueuse/core": "^8.1.2", 19 | "vue-i18n": "^9.1.9" 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /packages/locale/src/lang/en.ts: -------------------------------------------------------------------------------- 1 | import { genMessage } from '../helper' 2 | 3 | const modules = import.meta.globEager('./en/**/*.ts') 4 | export default { 5 | message: { 6 | ...genMessage(modules, 'en'), 7 | }, 8 | dateLocale: null, 9 | dateLocaleName: 'en', 10 | } 11 | -------------------------------------------------------------------------------- /packages/locale/src/lang/en/common.ts: -------------------------------------------------------------------------------- 1 | export default { 2 | okText: 'OK', 3 | closeText: 'Close', 4 | cancelText: 'Cancel', 5 | loadingText: 'Loading...', 6 | saveText: 'Save', 7 | delText: 'Delete', 8 | resetText: 'Reset', 9 | searchText: 'Search', 10 | queryText: 'Search', 11 | 12 | inputText: 'Please enter', 13 | chooseText: 'Please choose', 14 | 15 | redo: 'Refresh', 16 | back: 'Back', 17 | 18 | light: 'Light', 19 | dark: 'Dark', 20 | } 21 | -------------------------------------------------------------------------------- /packages/locale/src/lang/en/routes/basic.ts: -------------------------------------------------------------------------------- 1 | export default { 2 | login: 'Login', 3 | } 4 | -------------------------------------------------------------------------------- /packages/locale/src/lang/en/routes/dashboard.ts: -------------------------------------------------------------------------------- 1 | export default { 2 | dashboard: 'Dashboard', 3 | about: 'About', 4 | workbench: 'Workbench', 5 | analysis: 'Analysis', 6 | } 7 | -------------------------------------------------------------------------------- /packages/locale/src/lang/en/routes/develop.ts: -------------------------------------------------------------------------------- 1 | export default { 2 | develop: '开发', 3 | type: '类型', 4 | } 5 | -------------------------------------------------------------------------------- /packages/locale/src/lang/zh-CN/common.ts: -------------------------------------------------------------------------------- 1 | export default { 2 | okText: '确认', 3 | closeText: '关闭', 4 | cancelText: '取消', 5 | loadingText: '加载中...', 6 | saveText: '保存', 7 | delText: '删除', 8 | resetText: '重置', 9 | searchText: '搜索', 10 | queryText: '查询', 11 | 12 | inputText: '请输入', 13 | chooseText: '请选择', 14 | 15 | redo: '刷新', 16 | back: '返回', 17 | 18 | light: '亮色主题', 19 | dark: '黑暗主题', 20 | } 21 | -------------------------------------------------------------------------------- /packages/locale/src/lang/zh-CN/routes/amis.ts: -------------------------------------------------------------------------------- 1 | export default { 2 | amis: 'AMIS', 3 | amisIndex: '页面辑器', 4 | amisPageList: '动态页管理', 5 | Internal: '编辑器(内嵌)', 6 | amisEditor: '页面辑器', 7 | AmisDynamic: '动态架构', 8 | AmisPreview: '动态页预览', 9 | } 10 | -------------------------------------------------------------------------------- /packages/locale/src/lang/zh-CN/routes/basic.ts: -------------------------------------------------------------------------------- 1 | export default { 2 | login: '登录', 3 | } 4 | -------------------------------------------------------------------------------- /packages/locale/src/lang/zh-CN/routes/crm.ts: -------------------------------------------------------------------------------- 1 | export default { 2 | crm: 'CRM', 3 | customer: '客户', 4 | } 5 | -------------------------------------------------------------------------------- /packages/locale/src/lang/zh-CN/routes/dashboard.ts: -------------------------------------------------------------------------------- 1 | export default { 2 | dashboard: 'Dashboard', 3 | about: '关于', 4 | workbench: '工作台', 5 | analysis: '分析页', 6 | } 7 | -------------------------------------------------------------------------------- /packages/locale/src/lang/zh-CN/routes/develop.ts: -------------------------------------------------------------------------------- 1 | export default { 2 | develop: '开发', 3 | type: '类型', 4 | listManagement: '列表管理', 5 | listDetails: '新建列表', 6 | } 7 | -------------------------------------------------------------------------------- /packages/locale/src/lang/zh_CN.ts: -------------------------------------------------------------------------------- 1 | import { genMessage } from '../helper' 2 | 3 | const modules = import.meta.globEager('./zh-CN/**/*.ts') 4 | export default { 5 | message: { 6 | ...genMessage(modules, 'zh-CN'), 7 | }, 8 | } 9 | -------------------------------------------------------------------------------- /packages/locale/src/store.ts: -------------------------------------------------------------------------------- 1 | import type { LocaleType } from '@pkg/types' 2 | 3 | import { computed } from 'vue' 4 | import { LOCALE_KEY } from '@pkg/tokens' 5 | import { useLocalStorage } from '@vueuse/core' 6 | import { localeSetting } from '@pkg/setting' 7 | 8 | const store = useLocalStorage(LOCALE_KEY, localeSetting) 9 | 10 | export const setLocale = (locale: LocaleType) => { 11 | store.value.locale = locale 12 | } 13 | 14 | export const getLocale = computed(() => store.value.locale) 15 | 16 | export const showLocalePicker = computed(() => store.value.showPicker) 17 | -------------------------------------------------------------------------------- /packages/locale/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "tsconfig/base.json", 3 | "compilerOptions": { 4 | "target": "esnext", 5 | "module": "esnext", 6 | "baseUrl": ".", 7 | "paths": { 8 | "@/*": ["src/*"] 9 | }, 10 | "lib": ["dom", "esnext"], 11 | "types": ["vite/client"] 12 | }, 13 | "include": ["src"], 14 | "exclude": ["**/node_modules/**", "**/dist/**"] 15 | } 16 | -------------------------------------------------------------------------------- /packages/request/index.ts: -------------------------------------------------------------------------------- 1 | export { initRequest } from './bridge' 2 | export { AxiosCanceler as RequestCanceler } from './src/axiosCancel' 3 | export { request, ocApi } from './src/index' 4 | -------------------------------------------------------------------------------- /packages/request/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@pkg/request", 3 | "version": "3.0.0-alpha.4", 4 | "main": "index.ts", 5 | "module": "index.ts", 6 | "license": "MIT", 7 | "scripts": { 8 | "clean": "pnpm rimraf node_modules && pnpm rimraf dist && pnpm rimraf .turbo" 9 | }, 10 | "dependencies": { 11 | "@pkg/locale": "workspace:*", 12 | "@pkg/tokens": "workspace:*", 13 | "@pkg/types": "workspace:*", 14 | "@pkg/utils": "workspace:*", 15 | "axios": "^0.26.1", 16 | "qs": "^6.10.3" 17 | }, 18 | "devDependencies": { 19 | "@types/qs": "^6.9.7" 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /packages/setting/index.ts: -------------------------------------------------------------------------------- 1 | export * from './src' 2 | -------------------------------------------------------------------------------- /packages/setting/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@pkg/setting", 3 | "version": "3.0.0-alpha.4", 4 | "main": "index.ts", 5 | "module": "index.ts", 6 | "license": "MIT", 7 | "scripts": { 8 | "clean": "pnpm rimraf node_modules && pnpm rimraf dist && pnpm rimraf .turbo" 9 | }, 10 | "dependencies": { 11 | "@pkg/tokens": "workspace:*", 12 | "@pkg/types": "workspace:*" 13 | }, 14 | "optionalDependencies": { 15 | "vue": "^3.2.31" 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /packages/setting/src/design.ts: -------------------------------------------------------------------------------- 1 | import { ThemeEnum } from '@pkg/tokens' 2 | 3 | export const namespace = 'vben' 4 | 5 | export const primaryColor = '#0960bd' 6 | 7 | export const darkMode = ThemeEnum.LIGHT 8 | 9 | // app theme preset color 10 | export const APP_PRESET_COLOR_LIST: string[] = [ 11 | '#0960bd', 12 | '#0084f4', 13 | '#009688', 14 | '#536dfe', 15 | '#ff5c93', 16 | '#ee4f12', 17 | '#0096c7', 18 | '#9c27b0', 19 | '#ff9800', 20 | ] 21 | 22 | // header preset color 23 | export const HEADER_PRESET_BG_COLOR_LIST: string[] = [ 24 | '#ffffff', 25 | '#151515', 26 | '#009688', 27 | '#5172DC', 28 | '#018ffb', 29 | '#409eff', 30 | '#e74c3c', 31 | '#24292e', 32 | '#394664', 33 | '#001529', 34 | '#383f45', 35 | ] 36 | 37 | // sider preset color 38 | export const SIDE_BAR_BG_COLOR_LIST: string[] = [ 39 | '#001529', 40 | '#212121', 41 | '#273352', 42 | '#ffffff', 43 | '#191b24', 44 | '#191a23', 45 | '#304156', 46 | '#001628', 47 | '#28333E', 48 | '#344058', 49 | '#383f45', 50 | ] 51 | -------------------------------------------------------------------------------- /packages/setting/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from './locale' 2 | export * from './design' 3 | export * from './component' 4 | export * from './site' 5 | export * from './project' 6 | -------------------------------------------------------------------------------- /packages/setting/src/locale.ts: -------------------------------------------------------------------------------- 1 | import type { LocaleSetting, LocaleType } from '@pkg/types' 2 | 3 | export const LOCALE: { [key: string]: LocaleType } = { 4 | zh: 'zh_CN', 5 | en: 'en', 6 | } 7 | 8 | export const localeSetting: LocaleSetting = { 9 | showPicker: true, 10 | // Locale 11 | locale: LOCALE.zh, 12 | // Default locale 13 | fallback: LOCALE.zh, 14 | // available Locales 15 | availableLocales: [LOCALE.zh, LOCALE.en], 16 | } 17 | 18 | // locale list 19 | export const localeList: any[] = [ 20 | { 21 | text: '简体中文', 22 | event: LOCALE.zh, 23 | }, 24 | { 25 | text: 'English', 26 | event: LOCALE.en, 27 | }, 28 | ] 29 | -------------------------------------------------------------------------------- /packages/setting/src/site.ts: -------------------------------------------------------------------------------- 1 | // github repo url 2 | export const GITHUB_URL = 'https://github.com/anncwb/vue-vben-admin' 3 | 4 | // vue-vben-admin-next-doc 5 | export const DOC_URL = 'https://vvbin.cn/doc-next/' 6 | 7 | // site url 8 | export const SITE_URL = 'https://vvbin.cn/next/' 9 | -------------------------------------------------------------------------------- /packages/styles/common/color.css: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EasyOC/EasyOC.VbenAdmin/4f711c4e480be3274e4ed6b68532834fd443acc3/packages/styles/common/color.css -------------------------------------------------------------------------------- /packages/styles/common/common.css: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EasyOC/EasyOC.VbenAdmin/4f711c4e480be3274e4ed6b68532834fd443acc3/packages/styles/common/common.css -------------------------------------------------------------------------------- /packages/styles/common/index.ts: -------------------------------------------------------------------------------- 1 | import './common.css' 2 | import './tailwind.css' 3 | -------------------------------------------------------------------------------- /packages/styles/common/tailwind.css: -------------------------------------------------------------------------------- 1 | @tailwind base; 2 | @tailwind components; 3 | @tailwind utilities; 4 | -------------------------------------------------------------------------------- /packages/styles/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@pkg/styles", 3 | "version": "3.0.0-alpha.4", 4 | "license": "MIT", 5 | "scripts": { 6 | "clean": "pnpm rimraf node_modules && pnpm rimraf dist && pnpm rimraf .turbo" 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /packages/tokens/index.ts: -------------------------------------------------------------------------------- 1 | export * from './src' 2 | -------------------------------------------------------------------------------- /packages/tokens/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@pkg/tokens", 3 | "version": "3.0.0-alpha.4", 4 | "main": "index.ts", 5 | "module": "index.ts", 6 | "license": "MIT", 7 | "scripts": { 8 | "clean": "pnpm rimraf node_modules && pnpm rimraf dist && pnpm rimraf .turbo" 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /packages/tokens/src/cache.ts: -------------------------------------------------------------------------------- 1 | // token key 2 | export const TOKEN_KEY = 'TOKEN' 3 | 4 | export const LOCALE_KEY = 'LOCALE' 5 | 6 | // user info key 7 | export const USER_INFO_KEY = 'USER__INFO' 8 | 9 | // role info key 10 | export const ROLES_KEY = 'ROLES__KEY' 11 | 12 | // project config key 13 | export const PROJ_CFG_KEY = 'PROJ__CFG__KEY' 14 | 15 | // lock info 16 | export const LOCK_INFO_KEY = 'LOCK__INFO__KEY' 17 | 18 | export const MULTIPLE_TABS_KEY = 'MULTIPLE_TABS__KEY' 19 | 20 | export const APP_DARK_MODE_KEY_ = '__APP__DARK__MODE' 21 | 22 | // base global local key 23 | export const APP_LOCAL_CACHE_KEY = 'COMMON__LOCAL__KEY' 24 | 25 | // base global session key 26 | export const APP_SESSION_CACHE_KEY = 'COMMON__SESSION__KEY' 27 | 28 | export enum CacheTypeEnum { 29 | SESSION, 30 | LOCAL, 31 | } 32 | -------------------------------------------------------------------------------- /packages/tokens/src/enums/breakpoint.ts: -------------------------------------------------------------------------------- 1 | export enum ScreenSizeEnum { 2 | XS = 'XS', 3 | SM = 'SM', 4 | MD = 'MD', 5 | LG = 'LG', 6 | XL = 'XL', 7 | XXL = 'XXL', 8 | } 9 | 10 | export enum ScreenValueEnum { 11 | XS = 480, 12 | SM = 576, 13 | MD = 768, 14 | LG = 992, 15 | XL = 1200, 16 | XXL = 1600, 17 | } 18 | 19 | const screenMap = new Map() 20 | 21 | screenMap.set(ScreenSizeEnum.XS, ScreenValueEnum.XS) 22 | screenMap.set(ScreenSizeEnum.SM, ScreenValueEnum.SM) 23 | screenMap.set(ScreenSizeEnum.MD, ScreenValueEnum.MD) 24 | screenMap.set(ScreenSizeEnum.LG, ScreenValueEnum.LG) 25 | screenMap.set(ScreenSizeEnum.XL, ScreenValueEnum.XL) 26 | screenMap.set(ScreenSizeEnum.XXL, ScreenValueEnum.XXL) 27 | 28 | export { screenMap } 29 | -------------------------------------------------------------------------------- /packages/tokens/src/enums/http.ts: -------------------------------------------------------------------------------- 1 | 2 | /** 3 | * @description: Request result set 4 | */ 5 | export enum ResultEnum { 6 | SUCCESS = 200, 7 | ERROR = 1, 8 | TIMEOUT = 401, 9 | TYPE = 'success', 10 | } 11 | 12 | /** 13 | * @description: request method 14 | */ 15 | export enum RequestEnum { 16 | GET = 'GET', 17 | POST = 'POST', 18 | PUT = 'PUT', 19 | DELETE = 'DELETE', 20 | } 21 | 22 | /** 23 | * @description: contentType 24 | */ 25 | export enum ContentTypeEnum { 26 | // json 27 | JSON = 'application/json;charset=UTF-8', 28 | // form-data qs 29 | FORM_URLENCODED = 'application/x-www-form-urlencoded;charset=UTF-8', 30 | // form-data upload 31 | FORM_DATA = 'multipart/form-data;charset=UTF-8', 32 | } 33 | 34 | /** 35 | * Exception related enumeration 36 | */ 37 | export enum ExceptionEnum { 38 | // page not access 39 | PAGE_NOT_ACCESS = 403, 40 | 41 | // page not found 42 | PAGE_NOT_FOUND = 404, 43 | 44 | // error 45 | ERROR = 500, 46 | 47 | // net work error 48 | NET_WORK_ERROR = 10000, 49 | 50 | // No data on the page. In fact, it is not an exception page 51 | PAGE_NOT_DATA = 10100, 52 | } 53 | -------------------------------------------------------------------------------- /packages/tokens/src/enums/menu.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * @description: menu type 3 | */ 4 | export enum MenuTypeEnum { 5 | // left menu 6 | SIDEBAR = 'sidebar', 7 | 8 | MIX_SIDEBAR = 'mix-sidebar', 9 | // mixin menu 10 | MIX = 'mix', 11 | // top menu 12 | TOP_MENU = 'top-menu', 13 | } 14 | 15 | // 折叠触发器位置 16 | export enum TriggerEnum { 17 | // 不显示 18 | NONE = 'NONE', 19 | // 菜单底部 20 | FOOTER = 'FOOTER', 21 | // 头部 22 | HEADER = 'HEADER', 23 | } 24 | 25 | export type Mode = 'vertical' | 'vertical-right' | 'horizontal' | 'inline' 26 | 27 | // menu mode 28 | export enum MenuModeEnum { 29 | VERTICAL = 'vertical', 30 | HORIZONTAL = 'horizontal', 31 | VERTICAL_RIGHT = 'vertical-right', 32 | INLINE = 'inline', 33 | } 34 | 35 | export enum MenuSplitTyeEnum { 36 | NONE, 37 | TOP, 38 | LEFT, 39 | } 40 | 41 | export enum TopMenuAlignEnum { 42 | CENTER = 'center', 43 | START = 'start', 44 | END = 'end', 45 | } 46 | 47 | export enum MixSidebarTriggerEnum { 48 | HOVER = 'hover', 49 | CLICK = 'click', 50 | } 51 | -------------------------------------------------------------------------------- /packages/tokens/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from './enums' 2 | export * from './cache' 3 | export * from './sidebar' 4 | export * from './router' 5 | -------------------------------------------------------------------------------- /packages/tokens/src/router.ts: -------------------------------------------------------------------------------- 1 | export const REDIRECT_NAME = 'Redirect' 2 | 3 | export const PAGE_NOT_FOUND_NAME = 'PageNotFound' 4 | -------------------------------------------------------------------------------- /packages/tokens/src/sidebar.ts: -------------------------------------------------------------------------------- 1 | export const SIDE_BAR_MINI_WIDTH = 48 2 | export const SIDE_BAR_SHOW_TIT_MINI_WIDTH = 80 3 | -------------------------------------------------------------------------------- /packages/types/index.ts: -------------------------------------------------------------------------------- 1 | export * from './src' 2 | -------------------------------------------------------------------------------- /packages/types/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@pkg/types", 3 | "version": "3.0.0-alpha.4", 4 | "main": "index.ts", 5 | "module": "index.ts", 6 | "license": "MIT", 7 | "scripts": { 8 | "clean": "pnpm rimraf node_modules && pnpm rimraf dist && pnpm rimraf .turbo" 9 | }, 10 | "dependencies": { 11 | "@pkg/tokens": "workspace:*" 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /packages/types/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from './util' 2 | export * from './config' 3 | export * from './store' 4 | export * from './service' 5 | export * from './shims' 6 | export * from './router' 7 | export * from './global' 8 | -------------------------------------------------------------------------------- /packages/types/src/router.ts: -------------------------------------------------------------------------------- 1 | import type { RouteRecordRaw, RouteMeta, RouteComponent } from 'vue-router' 2 | 3 | type Lazy = () => Promise 4 | 5 | export type RouteRecordItem = { 6 | path: string 7 | orderNo?: number 8 | name: string 9 | meta: RouteMeta 10 | children?: RouteRecordItem[] 11 | component?: RouteComponent | Lazy | string 12 | } & RouteRecordRaw 13 | -------------------------------------------------------------------------------- /packages/types/src/shims/index.ts: -------------------------------------------------------------------------------- 1 | import './module' 2 | 3 | export * from './vue-router' 4 | export * from './pinia' 5 | -------------------------------------------------------------------------------- /packages/types/src/shims/module.ts: -------------------------------------------------------------------------------- 1 | declare module '*.vue' { 2 | import { DefineComponent } from 'vue' 3 | const Component: DefineComponent<{}, {}, any> 4 | export default Component 5 | } 6 | 7 | declare module 'virtual:*' { 8 | const result: any 9 | export default result 10 | } 11 | -------------------------------------------------------------------------------- /packages/types/src/shims/pinia.ts: -------------------------------------------------------------------------------- 1 | // @ts-ignore 2 | // eslint-disable-next-line 3 | import type { PiniaPluginContext } from 'pinia' 4 | 5 | declare module 'pinia' { 6 | export interface DefineStoreOptions< 7 | // eslint-disable-next-line 8 | Id, 9 | // eslint-disable-next-line 10 | S, 11 | // eslint-disable-next-line 12 | G, 13 | // eslint-disable-next-line 14 | A, 15 | > { 16 | /** 17 | * Persist store in storage. 18 | */ 19 | persist?: PersistOptions 20 | } 21 | } 22 | 23 | export interface PersistStrategy { 24 | key?: string 25 | storage?: Storage 26 | paths?: string[] 27 | } 28 | 29 | export interface PersistOptions { 30 | strategies?: PersistStrategy[] 31 | } 32 | -------------------------------------------------------------------------------- /packages/types/src/util.ts: -------------------------------------------------------------------------------- 1 | import type { ComputedRef, Ref } from 'vue' 2 | 3 | export type DynamicProps = { 4 | [P in keyof T]: Ref | T[P] | ComputedRef 5 | } 6 | -------------------------------------------------------------------------------- /packages/use/index.ts: -------------------------------------------------------------------------------- 1 | export * from './src' 2 | 3 | export { 4 | useTimeoutFn, 5 | useThrottleFn, 6 | useDebounceFn, 7 | onKeyStroke, 8 | onClickOutside, 9 | useTransition, 10 | TransitionPresets, 11 | useMutationObserver, 12 | useFullscreen, 13 | useIntervalFn, 14 | useWebSocket, 15 | useLocalStorage, 16 | } from '@vueuse/core' 17 | -------------------------------------------------------------------------------- /packages/use/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@pkg/use", 3 | "version": "3.0.0-alpha.4", 4 | "main": "index.ts", 5 | "module": "index.ts", 6 | "license": "MIT", 7 | "scripts": { 8 | "clean": "pnpm rimraf node_modules && pnpm rimraf dist && pnpm rimraf .turbo" 9 | }, 10 | "dependencies": { 11 | "@pkg/locale": "workspace:*", 12 | "@pkg/utils": "workspace:*", 13 | "@vueuse/core": "^8.1.2" 14 | }, 15 | "optionalDependencies": { 16 | "vue": "^3.2.31" 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /packages/use/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from './use-attrs' 2 | export * from './use-context' 3 | export * from './use-refs' 4 | export * from './use-pagination' 5 | export * from './use-script' 6 | export * from './use-watermark' 7 | export * from './use-title' 8 | export * from './use-window-resize' 9 | -------------------------------------------------------------------------------- /packages/use/src/use-context.ts: -------------------------------------------------------------------------------- 1 | import { 2 | InjectionKey, 3 | provide, 4 | inject, 5 | reactive, 6 | readonly as defineReadonly, 7 | UnwrapRef, 8 | } from 'vue' 9 | 10 | export interface CreateContextOptions { 11 | readonly?: boolean 12 | createProvider?: boolean 13 | native?: boolean 14 | } 15 | 16 | type ShallowUnwrap = { 17 | [P in keyof T]: UnwrapRef 18 | } 19 | 20 | export const createContext = ( 21 | context: any, 22 | key: InjectionKey = Symbol(), 23 | options: CreateContextOptions = {}, 24 | ) => { 25 | const { readonly = true, createProvider = false, native = false } = options 26 | 27 | const state = reactive(context) 28 | const provideData = readonly ? defineReadonly(state) : state 29 | !createProvider && provide(key, native ? context : provideData) 30 | 31 | return { state } 32 | } 33 | 34 | export function useContext(key: InjectionKey, native?: boolean): T 35 | export function useContext( 36 | key: InjectionKey, 37 | defaultValue?: any, 38 | native?: boolean, 39 | ): T 40 | 41 | export function useContext( 42 | key: InjectionKey = Symbol(), 43 | defaultValue?: any, 44 | ): ShallowUnwrap { 45 | return inject(key, defaultValue || {}) 46 | } 47 | -------------------------------------------------------------------------------- /packages/use/src/use-pagination.ts: -------------------------------------------------------------------------------- 1 | import type { Ref } from 'vue' 2 | import { ref, unref, computed } from 'vue' 3 | 4 | const pagination = ( 5 | list: T[], 6 | pageNo: number, 7 | pageSize: number, 8 | ): T[] => { 9 | const offset = (pageNo - 1) * Number(pageSize) 10 | const ret = 11 | offset + Number(pageSize) >= list.length 12 | ? list.slice(offset, list.length) 13 | : list.slice(offset, offset + Number(pageSize)) 14 | return ret 15 | } 16 | 17 | export const usePagination = (list: Ref, pageSize: number) => { 18 | const currentPage = ref(1) 19 | const pageSizeRef = ref(pageSize) 20 | 21 | const getPaginationList = computed(() => { 22 | return pagination(unref(list), unref(currentPage), unref(pageSizeRef)) 23 | }) 24 | 25 | const getTotal = computed(() => { 26 | return unref(list).length 27 | }) 28 | 29 | function setCurrentPage(page: number) { 30 | currentPage.value = page 31 | } 32 | 33 | function setPageSize(pageSize: number) { 34 | pageSizeRef.value = pageSize 35 | } 36 | 37 | return { setCurrentPage, getTotal, setPageSize, getPaginationList } 38 | } 39 | -------------------------------------------------------------------------------- /packages/use/src/use-refs.ts: -------------------------------------------------------------------------------- 1 | import type { Ref } from 'vue' 2 | import { ref, onBeforeUpdate } from 'vue' 3 | 4 | export const useRefs = (): [ 5 | Ref, 6 | (index: number) => (el: HTMLElement) => void, 7 | ] => { 8 | const refs = ref([]) as Ref 9 | 10 | onBeforeUpdate(() => { 11 | refs.value = [] 12 | }) 13 | 14 | const setRefs = (index: number) => (el: HTMLElement) => { 15 | refs.value[index] = el 16 | } 17 | 18 | return [refs, setRefs] 19 | } 20 | -------------------------------------------------------------------------------- /packages/use/src/use-script.ts: -------------------------------------------------------------------------------- 1 | import { onMounted, onUnmounted, ref } from 'vue' 2 | 3 | interface ScriptOptions { 4 | src: string 5 | } 6 | 7 | export const useScript = (opts: ScriptOptions) => { 8 | const isLoading = ref(false) 9 | const error = ref(false) 10 | const success = ref(false) 11 | let script: HTMLScriptElement 12 | 13 | const promise = new Promise((resolve, reject) => { 14 | onMounted(() => { 15 | script = document.createElement('script') 16 | script.type = 'text/javascript' 17 | script.onload = function () { 18 | isLoading.value = false 19 | success.value = true 20 | error.value = false 21 | resolve('') 22 | } 23 | 24 | script.onerror = function (err) { 25 | isLoading.value = false 26 | success.value = false 27 | error.value = true 28 | reject(err) 29 | } 30 | 31 | script.src = opts.src 32 | document.head.appendChild(script) 33 | }) 34 | }) 35 | 36 | onUnmounted(() => { 37 | script && script.remove() 38 | }) 39 | 40 | return { 41 | isLoading, 42 | error, 43 | success, 44 | toPromise: () => promise, 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /packages/use/src/use-title.ts: -------------------------------------------------------------------------------- 1 | import type { RouteLocationNormalizedLoaded } from 'vue-router' 2 | 3 | import { watch, unref } from 'vue' 4 | import { useRouter } from 'vue-router' 5 | import { useTitle as _useTitle } from '@vueuse/core' 6 | import { useI18n, useLocale } from '@pkg/locale' 7 | 8 | /** 9 | * Listening to page changes and dynamically changing site titles 10 | */ 11 | export const useTitle = ( 12 | title: string, 13 | preventHandler: ( 14 | route: RouteLocationNormalizedLoaded, 15 | ) => Promise | boolean, 16 | ) => { 17 | const { t } = useI18n() 18 | const { currentRoute } = useRouter() 19 | 20 | const pageTitle = _useTitle() 21 | const { getLocale } = useLocale() 22 | 23 | watch( 24 | [() => currentRoute.value.path, () => getLocale.value], 25 | async () => { 26 | const route = unref(currentRoute) 27 | 28 | if (!preventHandler(route)) { 29 | return 30 | } 31 | 32 | const tTitle = t(route?.meta?.title as string) 33 | pageTitle.value = tTitle ? ` ${tTitle} - ${title} ` : `${title}` 34 | }, 35 | { immediate: true }, 36 | ) 37 | } 38 | -------------------------------------------------------------------------------- /packages/use/src/use-window-resize.ts: -------------------------------------------------------------------------------- 1 | import { tryOnMounted, tryOnUnmounted } from '@pkg/utils' 2 | import { useDebounceFn } from '@vueuse/core' 3 | 4 | interface WindowSizeOptions { 5 | once?: boolean 6 | immediate?: boolean 7 | listenerOptions?: AddEventListenerOptions | boolean 8 | } 9 | 10 | export const useWindowResize = ( 11 | fn: AnyFunction, 12 | wait = 150, 13 | options?: WindowSizeOptions, 14 | ) => { 15 | let handler = () => { 16 | fn() 17 | } 18 | const handleSize = useDebounceFn(handler, wait) 19 | handler = handleSize 20 | 21 | const start = () => { 22 | if (options && options.immediate) { 23 | handler() 24 | } 25 | window.addEventListener('resize', handler) 26 | } 27 | 28 | const stop = () => { 29 | window.removeEventListener('resize', handler) 30 | } 31 | 32 | tryOnMounted(() => { 33 | start() 34 | }) 35 | 36 | tryOnUnmounted(() => { 37 | stop() 38 | }) 39 | return [start, stop] 40 | } 41 | -------------------------------------------------------------------------------- /packages/utils/index.ts: -------------------------------------------------------------------------------- 1 | export * from './src' 2 | export * from './bem' 3 | 4 | export { 5 | cloneDeep, 6 | sortBy, 7 | omit, 8 | upperFirst, 9 | uniq, 10 | uniqBy, 11 | pick, 12 | merge, 13 | clone, 14 | set, 15 | has, 16 | get, 17 | fromPairs, 18 | difference, 19 | intersection, 20 | } from 'lodash-es' 21 | -------------------------------------------------------------------------------- /packages/utils/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@pkg/utils", 3 | "version": "3.0.0-alpha.4", 4 | "main": "index.ts", 5 | "module": "index.ts", 6 | "license": "MIT", 7 | "scripts": { 8 | "clean": "pnpm rimraf node_modules && pnpm rimraf dist && pnpm rimraf .turbo" 9 | }, 10 | "dependencies": { 11 | "@pkg/setting": "workspace:*", 12 | "@vue/runtime-core": "^3.2.31", 13 | "@vue/shared": "^3.2.31", 14 | "@vueuse/core": "^8.1.2", 15 | "@vueuse/shared": "^8.1.2", 16 | "dayjs": "^1.11.0", 17 | "lodash-es": "^4.17.21" 18 | }, 19 | "devDependencies": { 20 | "@types/lodash-es": "^4.17.6" 21 | }, 22 | "optionalDependencies": { 23 | "vue": "^3.2.31" 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /packages/utils/src/config.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Get the configuration file variable name 3 | * @param env 4 | */ 5 | export const getAppConfigFileName = (env: Record) => { 6 | return `__PRODUCTION__${env.VITE_GLOB_APP_SHORT_NAME || '__APP'}__CONF__` 7 | .toUpperCase() 8 | .replace(/\s/g, '') 9 | } 10 | -------------------------------------------------------------------------------- /packages/utils/src/date.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Independent time operation tool to facilitate subsequent switch to dayjs 3 | */ 4 | import type { ConfigType } from 'dayjs' 5 | import dayjs from 'dayjs' 6 | import utc from 'dayjs/plugin/utc' 7 | import timezone from 'dayjs/plugin/timezone' 8 | import { isString } from '@vue/shared' 9 | const DATE_TIME_FORMAT = 'YYYY-MM-DD HH:mm:ss' 10 | const DATE_FORMAT = 'YYYY-MM-DD' 11 | dayjs.extend(utc) 12 | dayjs.extend(timezone) 13 | export const dateUtil = dayjs 14 | 15 | export const formatToDateTime = ( 16 | date: ConfigType, 17 | format = DATE_TIME_FORMAT, 18 | ): string => { 19 | return dateUtil(date).format(format) 20 | } 21 | const UTC_DATE_FORMAT_PREFIX = 'utc|' 22 | export const formatToDate = ( 23 | date: ConfigType, 24 | format = DATE_FORMAT, 25 | ): string => { 26 | if (isString(format) && format.startsWith(UTC_DATE_FORMAT_PREFIX)) { 27 | const dateFormat = format.replace(UTC_DATE_FORMAT_PREFIX, '') 28 | // return dateUtil(date).tz(dayjs.tz.guess()).format(dateFormat) 29 | return dateUtil(date).tz("Asia/Shanghai").format(dateFormat) 30 | } 31 | return dateUtil(date).format(format) 32 | } 33 | -------------------------------------------------------------------------------- /packages/utils/src/deep-merge.ts: -------------------------------------------------------------------------------- 1 | import { isObject } from './is' 2 | 3 | export const deepMerge = (src: any = {}, target: any = {}): T => { 4 | let key: string 5 | for (key in target) { 6 | src[key] = isObject(src[key]) 7 | ? deepMerge(src[key], target[key]) 8 | : (src[key] = target[key]) 9 | } 10 | return src 11 | } 12 | -------------------------------------------------------------------------------- /packages/utils/src/helper/index.ts: -------------------------------------------------------------------------------- 1 | export * from './slot' 2 | export * from './tree' 3 | export * from './route' 4 | -------------------------------------------------------------------------------- /packages/utils/src/helper/route.ts: -------------------------------------------------------------------------------- 1 | import type { RouteLocationNormalized, RouteRecordNormalized } from 'vue-router' 2 | 3 | export const getRawRoute = ( 4 | route: RouteLocationNormalized, 5 | ): RouteLocationNormalized => { 6 | if (!route) { 7 | return route 8 | } 9 | const { matched, ...opt } = route 10 | return { 11 | ...opt, 12 | matched: (matched 13 | ? matched.map((item) => ({ 14 | meta: item.meta, 15 | name: item.name, 16 | path: item.path, 17 | })) 18 | : undefined) as RouteRecordNormalized[], 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /packages/utils/src/helper/slot.ts: -------------------------------------------------------------------------------- 1 | import type { Slots } from 'vue' 2 | import { isFunction } from '../is' 3 | 4 | /** 5 | * @description: Get slot to prevent empty error 6 | */ 7 | export const getSlot = (slots: Slots, slot = 'default', data?: any) => { 8 | if (!slots || !Reflect.has(slots, slot)) { 9 | return null 10 | } 11 | if (!isFunction(slots[slot])) { 12 | console.error(`${slot} is not a function!`) 13 | return null 14 | } 15 | const slotFn = slots[slot] 16 | if (!slotFn) return null 17 | return slotFn(data) 18 | } 19 | 20 | /** 21 | * extends slots 22 | * @param slots 23 | * @param excludeKeys 24 | */ 25 | export const extendSlots = (slots: Slots, excludeKeys: string[] = []) => { 26 | const slotKeys = Object.keys(slots) 27 | const ret: any = {} 28 | slotKeys.map((key) => { 29 | if (excludeKeys.includes(key)) { 30 | return null 31 | } 32 | ret[key] = () => getSlot(slots, key) 33 | }) 34 | return ret 35 | } 36 | -------------------------------------------------------------------------------- /packages/utils/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from './is' 2 | export * from './mitt' 3 | export * from './uuid' 4 | export * from './config' 5 | export * from './log' 6 | export * from './date' 7 | export * from './deep-merge' 8 | export * from './util' 9 | export * from './file' 10 | export * from './helper' 11 | export * from './event' 12 | export * from './dom' 13 | export * from './lifecycle' 14 | export * from './color' 15 | export * from './with-install' 16 | -------------------------------------------------------------------------------- /packages/utils/src/is.ts: -------------------------------------------------------------------------------- 1 | import { isUndefined, isNull } from 'lodash-es' 2 | export { NOOP, isFunction, isString, isArray, isMap } from '@vue/shared' 3 | 4 | export { isClient, isWindow } from '@vueuse/core' 5 | 6 | export { 7 | isNull, 8 | isEmpty, 9 | isNumber, 10 | isBoolean, 11 | isEqual, 12 | isUndefined, 13 | upperFirst, 14 | } from 'lodash-es' 15 | 16 | export const is = (val: unknown, type: string) => { 17 | return toString.call(val) === `[object ${type}]` 18 | } 19 | 20 | export const isUrl = (path: string): boolean => { 21 | const reg = 22 | /(((^https?:(?:\/\/)?)(?:[-;:&=\+\$,\w]+@)?[A-Za-z0-9.-]+(?::\d+)?|(?:www.|[-;:&=\+\$,\w]+@)[A-Za-z0-9.-]+)((?:\/[\+~%\/.\w-_]*)?\??(?:[-\+=&;%@.\w_]*)#?(?:[\w]*))?)$/ 23 | return reg.test(path) 24 | } 25 | 26 | export const isDefined = (val?: T): val is T => !isUndefined(val) 27 | 28 | export const isNullOrUndefined = (val?: T): val is T => 29 | isUndefined(val) || isNull(val) 30 | 31 | export const isObject = (val: any): val is Record => 32 | val !== null && is(val, 'Object') 33 | -------------------------------------------------------------------------------- /packages/utils/src/lifecycle.ts: -------------------------------------------------------------------------------- 1 | import { nextTick, onMounted, onActivated } from 'vue' 2 | 3 | export const onMountedOrActivated = (hook: AnyFunction) => { 4 | let mounted: boolean 5 | 6 | onMounted(() => { 7 | hook() 8 | nextTick(() => { 9 | mounted = true 10 | }) 11 | }) 12 | 13 | onActivated(() => { 14 | if (mounted) { 15 | hook() 16 | } 17 | }) 18 | } 19 | 20 | export { tryOnUnmounted, tryOnMounted } from '@vueuse/core' 21 | -------------------------------------------------------------------------------- /packages/utils/src/log.ts: -------------------------------------------------------------------------------- 1 | export const warn = (message: string) => { 2 | console.warn(`[admin warn]:${message}`) 3 | } 4 | 5 | export const error = (message: string): never => { 6 | throw new Error(`[admin error]:${message}`) 7 | } 8 | -------------------------------------------------------------------------------- /packages/utils/src/uuid.ts: -------------------------------------------------------------------------------- 1 | const hexList: string[] = [] 2 | let unique = 0 3 | 4 | for (let i = 0; i <= 15; i++) { 5 | hexList[i] = i.toString(16) 6 | } 7 | 8 | export const buildUUID = (): string => { 9 | let uuid = '' 10 | for (let i = 1; i <= 36; i++) { 11 | if (i === 9 || i === 14 || i === 19 || i === 24) { 12 | uuid += '-' 13 | } else if (i === 15) { 14 | uuid += 4 15 | } else if (i === 20) { 16 | uuid += hexList[(Math.random() * 4) | 8] 17 | } else { 18 | uuid += hexList[(Math.random() * 16) | 0] 19 | } 20 | } 21 | return uuid.replace(/-/g, '') 22 | } 23 | 24 | export const buildShortUUID = (prefix = ''): string => { 25 | const time = Date.now() 26 | const random = Math.floor(Math.random() * 1000000000) 27 | unique++ 28 | return prefix + '_' + random + unique + String(time) 29 | } 30 | -------------------------------------------------------------------------------- /packages/utils/src/with-install.ts: -------------------------------------------------------------------------------- 1 | import { NOOP } from '@vue/shared' 2 | 3 | export const withInstall = >( 4 | main: T, 5 | extra?: E, 6 | ) => { 7 | ;(main as SFCWithInstall).install = (app): void => { 8 | for (const comp of [main, ...Object.values(extra ?? {})]) { 9 | app.component(comp.name, comp) 10 | } 11 | } 12 | 13 | if (extra) { 14 | for (const [key, comp] of Object.entries(extra)) { 15 | ;(main as any)[key] = comp 16 | } 17 | } 18 | return main as SFCWithInstall & E 19 | } 20 | 21 | export const withInstallFunction = (fn: T, name: string) => { 22 | ;(fn as SFCWithInstall).install = (app) => { 23 | app.config.globalProperties[name] = fn 24 | } 25 | 26 | return fn as SFCWithInstall 27 | } 28 | 29 | export const withNoopInstall = (component: T) => { 30 | ;(component as SFCWithInstall).install = NOOP 31 | 32 | return component as SFCWithInstall 33 | } 34 | -------------------------------------------------------------------------------- /pnpm-workspace.yaml: -------------------------------------------------------------------------------- 1 | packages: 2 | - 'packages/*' 3 | - 'packages/components/*' 4 | - 'apps/*' 5 | - 'configs/*' 6 | - 'scripts' 7 | -------------------------------------------------------------------------------- /scripts/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "scripts", 3 | "private": true, 4 | "bin": {}, 5 | "scripts": { 6 | "clean": "pnpm rimraf node_modules && pnpm rimraf dist && pnpm rimraf .turbo", 7 | "dev": "pnpm esno ./src/dev.ts", 8 | "build": "pnpm esno ./src/build.ts" 9 | }, 10 | "devDependencies": { 11 | "@types/prompts": "^2.4.0", 12 | "execa": "^6.1.0", 13 | "prompts": "^2.4.2" 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /scripts/src/build.ts: -------------------------------------------------------------------------------- 1 | import { run } from './helper' 2 | 3 | run('build') 4 | -------------------------------------------------------------------------------- /scripts/src/dev.ts: -------------------------------------------------------------------------------- 1 | import { run } from './helper' 2 | 3 | run('dev') 4 | -------------------------------------------------------------------------------- /turbo.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://turborepo.org/schema.json", 3 | "pipeline": { 4 | "build": { 5 | "outputs": ["dist/**"], 6 | "dependsOn": ["^build"] 7 | }, 8 | "clean": { 9 | "dependsOn": ["^clean"] 10 | }, 11 | "test": { 12 | "dependsOn": ["^test"], 13 | "outputs": [] 14 | }, 15 | "dev": { 16 | "cache": false 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /vitest.config.ts: -------------------------------------------------------------------------------- 1 | /// 2 | import type { AliasOptions } from 'vite' 3 | import { defineConfig } from 'vite' 4 | // import { resolve } from 'path' 5 | 6 | // const _resolve = (p: string) => resolve(__dirname, p) 7 | 8 | const alias: AliasOptions = {} 9 | 10 | export default defineConfig({ 11 | // test: { 12 | // environment: 'jsdom', 13 | // deps: { 14 | // inline: ['@vue', '@vueuse', 'vue-demi'], 15 | // }, 16 | // }, 17 | resolve: { 18 | alias, 19 | }, 20 | }) 21 | -------------------------------------------------------------------------------- /问题梳理.md: -------------------------------------------------------------------------------- 1 | # 问题梳理 2 | 3 | ## 2022年4月2日 4 | 5 | OrchardCore 的性能问题 6 | 如果开启了ContentField_SQLIndex, 由于存在大量数据更新时需要为多个字段创建索引数据 7 | 算上 全局文档表,会将所有字段都作为索引行 8 | 9 | 比如:如果要批量更新100条数据,相关类型包含10个字段 10 | 11 | 那么,索引行的数量就是100 * 11 = 1100 条插入语句 12 | 13 | 社区讨论的结果是更倾向于为每个类型创建独立的索引表 14 | 既然要一个类型对应一张表,那么OrchardCore 的意义何在? 15 | 16 | 如果基于Abp-Vnext 自己做一个灵活的管理系统需要哪些工作? 17 | 18 | 1. 商业授权问题:VNext版本使用的是 LGPL 授权,只要不修改官方发布的dll,就可以不开源 19 | 2. 动态类型问题:可以参考OC自己做动态类型设计,但是需要自己实现一个类型管理器 20 | 3. 工作流:可以尝试使用 `elsa-core` 21 | 22 | ## 基于Abp的动态化设计 23 | 24 | ### 类型管理系统 25 | #### 类型管理器 26 | - 类型管理器:管理类型的创建,类型的查询,类型的更新,类型的删除 27 | - 类型事件钩子 28 | - 可复用类型: 对应OC的 Part 29 | - 内容事件钩子 30 | - 内容验证 31 | - 字段验证 32 | - 结构管理器 33 | ### 工作流系统 34 | 35 | 36 | --------------------------------------------------------------------------------