├── .editorconfig ├── .gitee └── ISSUE_TEMPLATE.zh-CN.md ├── .gitignore ├── .npmrc ├── .prettierignore ├── .prettierrc.mjs ├── .stylelintignore ├── .vscode ├── extensions.json ├── launch.json └── settings.json ├── LICENSE.txt ├── README.md ├── bin ├── build.bat ├── build.sh ├── install.bat ├── install.sh ├── startup.bat └── startup.sh ├── eslint.config.mjs ├── package.json ├── packages ├── assets │ ├── README.md │ ├── icons │ │ ├── moon.svg │ │ └── sun.svg │ ├── images │ │ ├── header.jpg │ │ ├── logo.png │ │ └── mp.png │ ├── package.json │ ├── svg │ │ ├── illustration.svg │ │ ├── login-bg-dark.svg │ │ ├── login-bg.svg │ │ ├── login-box-bg.svg │ │ ├── net-error.svg │ │ ├── no-data.svg │ │ └── preview │ │ │ ├── p-rotate.svg │ │ │ ├── resume.svg │ │ │ ├── scale.svg │ │ │ ├── unrotate.svg │ │ │ └── unscale.svg │ └── tsconfig.json ├── cms │ ├── README.md │ ├── api │ │ └── cms │ │ │ └── chat.ts │ ├── index.ts │ ├── package.json │ ├── tsconfig.json │ └── views │ │ └── cms │ │ └── chat │ │ └── index.vue ├── core │ ├── README.md │ ├── api │ │ ├── index.ts │ │ ├── model │ │ │ └── baseModel.ts │ │ ├── msg │ │ │ └── msgInner.ts │ │ └── sys │ │ │ ├── account.ts │ │ │ ├── area.ts │ │ │ ├── company.ts │ │ │ ├── config.ts │ │ │ ├── corpAdmin.ts │ │ │ ├── dictData.ts │ │ │ ├── dictType.ts │ │ │ ├── empUser.ts │ │ │ ├── index.ts │ │ │ ├── log.ts │ │ │ ├── login.ts │ │ │ ├── menu.ts │ │ │ ├── module.ts │ │ │ ├── office.ts │ │ │ ├── online.ts │ │ │ ├── post.ts │ │ │ ├── role.ts │ │ │ ├── secAdmin.ts │ │ │ ├── upload.ts │ │ │ └── user.ts │ ├── components │ │ ├── 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 │ │ ├── Authority │ │ │ ├── index.ts │ │ │ └── src │ │ │ │ └── Authority.vue │ │ ├── Basic │ │ │ ├── index.ts │ │ │ └── src │ │ │ │ ├── BasicArrow.vue │ │ │ │ ├── BasicHelp.vue │ │ │ │ └── BasicTitle.vue │ │ ├── Button │ │ │ ├── index.ts │ │ │ └── src │ │ │ │ ├── BasicButton.vue │ │ │ │ ├── PopConfirmButton.vue │ │ │ │ └── props.ts │ │ ├── CardList │ │ │ ├── index.ts │ │ │ └── src │ │ │ │ ├── CardList.vue │ │ │ │ └── data.ts │ │ ├── ClickOutSide │ │ │ ├── index.ts │ │ │ └── src │ │ │ │ └── ClickOutSide.vue │ │ ├── CodeEditor │ │ │ ├── index.ts │ │ │ └── src │ │ │ │ ├── CodeEditor.vue │ │ │ │ ├── codemirror │ │ │ │ └── CodeMirror.vue │ │ │ │ ├── json-preview │ │ │ │ └── JsonPreview.vue │ │ │ │ └── typing.ts │ │ ├── CollapseForm │ │ │ ├── index.ts │ │ │ └── src │ │ │ │ └── CollapseForm.vue │ │ ├── Container │ │ │ ├── index.ts │ │ │ └── src │ │ │ │ ├── LazyContainer.vue │ │ │ │ ├── ScrollContainer.vue │ │ │ │ ├── collapse │ │ │ │ ├── CollapseContainer.vue │ │ │ │ └── CollapseHeader.vue │ │ │ │ └── typing.ts │ │ ├── ContextMenu │ │ │ ├── index.ts │ │ │ └── src │ │ │ │ ├── ContextMenu.vue │ │ │ │ ├── createContextMenu.ts │ │ │ │ └── typing.ts │ │ ├── CountDown │ │ │ ├── index.ts │ │ │ └── src │ │ │ │ ├── CountButton.vue │ │ │ │ ├── CountdownInput.vue │ │ │ │ └── useCountdown.ts │ │ ├── CountTo │ │ │ ├── index.ts │ │ │ └── src │ │ │ │ └── CountTo.vue │ │ ├── Cropper │ │ │ ├── index.ts │ │ │ └── src │ │ │ │ ├── CopperModal.vue │ │ │ │ ├── Cropper.vue │ │ │ │ ├── CropperAvatar.vue │ │ │ │ └── typing.ts │ │ ├── Description │ │ │ ├── index.ts │ │ │ └── src │ │ │ │ ├── Description.vue │ │ │ │ ├── typing.ts │ │ │ │ └── useDescription.ts │ │ ├── Dialog │ │ │ ├── index.ts │ │ │ └── src │ │ │ │ └── BasicDialog.vue │ │ ├── Dict │ │ │ ├── index.ts │ │ │ └── src │ │ │ │ ├── DictLabel.vue │ │ │ │ └── useDict.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 │ │ ├── Excel │ │ │ ├── index.ts │ │ │ └── src │ │ │ │ ├── Export2Excel.ts │ │ │ │ ├── ExportExcelModal.vue │ │ │ │ ├── ImportExcel.vue │ │ │ │ └── typing.ts │ │ ├── Form │ │ │ ├── index.ts │ │ │ └── src │ │ │ │ ├── BasicForm.vue │ │ │ │ ├── componentMap.ts │ │ │ │ ├── components │ │ │ │ ├── FormAction.vue │ │ │ │ ├── FormGroup.vue │ │ │ │ ├── FormItem.vue │ │ │ │ ├── JeeSiteCheckboxGroup.vue │ │ │ │ ├── JeeSiteRadioButtonGroup.vue │ │ │ │ ├── JeeSiteRadioGroup.vue │ │ │ │ ├── JeeSiteSelect.vue │ │ │ │ ├── JeeSiteText.vue │ │ │ │ └── JeeSiteTreeSelect.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 │ │ │ ├── index.ts │ │ │ └── src │ │ │ │ ├── Icon.vue │ │ │ │ ├── IconData.tsx │ │ │ │ └── IconPicker.vue │ │ ├── ListSelect │ │ │ ├── index.ts │ │ │ └── src │ │ │ │ ├── ListSelect.vue │ │ │ │ ├── ListSelectModal.vue │ │ │ │ └── selectType │ │ │ │ ├── empUserSelect.ts │ │ │ │ └── userSelect.ts │ │ ├── Loading │ │ │ ├── index.ts │ │ │ └── src │ │ │ │ ├── Loading.vue │ │ │ │ ├── createLoading.ts │ │ │ │ ├── typing.ts │ │ │ │ └── useLoading.ts │ │ ├── Markdown │ │ │ ├── index.ts │ │ │ └── src │ │ │ │ ├── Markdown.vue │ │ │ │ ├── MarkdownViewer.vue │ │ │ │ ├── adapter.js │ │ │ │ ├── getTheme.ts │ │ │ │ └── typing.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 │ │ │ │ ├── props.ts │ │ │ │ └── typing.ts │ │ ├── Page │ │ │ ├── index.ts │ │ │ └── src │ │ │ │ ├── PageFooter.vue │ │ │ │ └── PageWrapper.vue │ │ ├── Popover │ │ │ ├── index.ts │ │ │ └── src │ │ │ │ ├── Popover.vue │ │ │ │ └── typing.ts │ │ ├── Preview │ │ │ ├── index.ts │ │ │ └── src │ │ │ │ ├── Functional.vue │ │ │ │ ├── Preview.vue │ │ │ │ ├── functional.ts │ │ │ │ └── typing.ts │ │ ├── Qrcode │ │ │ ├── index.ts │ │ │ └── src │ │ │ │ ├── Qrcode.vue │ │ │ │ ├── drawCanvas.ts │ │ │ │ ├── drawLogo.ts │ │ │ │ ├── qrcodePlus.ts │ │ │ │ ├── toCanvas.ts │ │ │ │ └── typing.ts │ │ ├── Resizer │ │ │ ├── Resizer.vue │ │ │ └── index.ts │ │ ├── Scrollbar │ │ │ ├── index.ts │ │ │ └── src │ │ │ │ ├── Scrollbar.vue │ │ │ │ ├── bar.ts │ │ │ │ ├── types.d.ts │ │ │ │ └── util.ts │ │ ├── SimpleMenu │ │ │ ├── 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 │ │ ├── StrengthMeter │ │ │ ├── index.ts │ │ │ └── src │ │ │ │ └── StrengthMeter.vue │ │ ├── Table │ │ │ ├── index.ts │ │ │ └── src │ │ │ │ ├── BasicTable.vue │ │ │ │ ├── componentMap.ts │ │ │ │ ├── components │ │ │ │ ├── EditTableHeaderIcon.vue │ │ │ │ ├── ExpandIcon.tsx │ │ │ │ ├── HeaderCell.vue │ │ │ │ ├── TableAction.vue │ │ │ │ ├── TableFooter.vue │ │ │ │ ├── TableHeader.vue │ │ │ │ ├── TableImg.vue │ │ │ │ ├── TableSelectionBar.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 │ │ ├── Time │ │ │ ├── index.ts │ │ │ └── src │ │ │ │ └── Time.vue │ │ ├── Transition │ │ │ ├── index.ts │ │ │ └── src │ │ │ │ ├── CollapseTransition.vue │ │ │ │ ├── CreateTransition.tsx │ │ │ │ └── ExpandTransition.ts │ │ ├── Tree │ │ │ ├── index.ts │ │ │ └── src │ │ │ │ ├── Tree.vue │ │ │ │ ├── TreeHeader.vue │ │ │ │ ├── TreeIcon.ts │ │ │ │ ├── props.ts │ │ │ │ ├── typing.ts │ │ │ │ └── useTree.ts │ │ ├── Upload │ │ │ ├── index.ts │ │ │ └── src │ │ │ │ ├── BasicUpload.vue │ │ │ │ ├── FileList.vue │ │ │ │ ├── ThumbUrl.vue │ │ │ │ ├── UploadModal.vue │ │ │ │ ├── UploadPreviewModal.vue │ │ │ │ ├── data.tsx │ │ │ │ ├── helper.ts │ │ │ │ ├── props.ts │ │ │ │ ├── typing.ts │ │ │ │ └── useUpload.ts │ │ ├── ValidCode │ │ │ ├── index.ts │ │ │ └── src │ │ │ │ └── ValidCode.vue │ │ ├── Verify │ │ │ ├── index.ts │ │ │ └── src │ │ │ │ ├── DragVerify.vue │ │ │ │ ├── ImgRotate.vue │ │ │ │ ├── props.ts │ │ │ │ └── typing.ts │ │ ├── VirtualScroll │ │ │ ├── index.ts │ │ │ └── src │ │ │ │ └── VirtualScroll.vue │ │ ├── WangEditor │ │ │ ├── index.ts │ │ │ └── src │ │ │ │ └── WangEditor.vue │ │ ├── index.ts │ │ └── registerGlobComp.ts │ ├── design │ │ ├── ant │ │ │ ├── btn.less │ │ │ ├── index.less │ │ │ ├── input.less │ │ │ ├── pagination.less │ │ │ └── table.less │ │ ├── entry.less │ │ ├── index.less │ │ ├── public.less │ │ ├── theme.less │ │ ├── transition │ │ │ ├── base.less │ │ │ ├── fade.less │ │ │ ├── index.less │ │ │ ├── scale.less │ │ │ ├── scroll.less │ │ │ ├── slide.less │ │ │ └── zoom.less │ │ └── var │ │ │ ├── breakpoint.less │ │ │ ├── color.less │ │ │ ├── easing.less │ │ │ └── index.less │ ├── directives │ │ ├── clickOutside.ts │ │ ├── clickOutsideSimple.ts │ │ ├── index.ts │ │ ├── loading.ts │ │ ├── permission.ts │ │ ├── repeatClick.ts │ │ └── ripple │ │ │ ├── index.less │ │ │ └── index.ts │ ├── enums │ │ ├── appEnum.ts │ │ ├── breakpointEnum.ts │ │ ├── cacheEnum.ts │ │ ├── exceptionEnum.ts │ │ ├── httpEnum.ts │ │ ├── menuEnum.ts │ │ ├── pageEnum.ts │ │ ├── roleEnum.ts │ │ └── sizeEnum.ts │ ├── hooks │ │ ├── component │ │ │ ├── useFormItem.ts │ │ │ └── usePageContext.ts │ │ ├── core │ │ │ ├── onMountedOrActivated.ts │ │ │ ├── useAttrs.ts │ │ │ ├── useContext.ts │ │ │ ├── useLockFn.ts │ │ │ ├── useRefs.ts │ │ │ └── useTimeout.ts │ │ ├── event │ │ │ ├── useBreakpoint.ts │ │ │ ├── useEventListener.ts │ │ │ ├── useIntersectionObserver.ts │ │ │ ├── useScroll.ts │ │ │ ├── useScrollTo.ts │ │ │ └── useWindowSizeFn.ts │ │ ├── setting │ │ │ ├── index.ts │ │ │ ├── useHeaderSetting.ts │ │ │ ├── useMenuSetting.ts │ │ │ ├── useMultipleTabSetting.ts │ │ │ ├── useRootSetting.ts │ │ │ └── useTransitionSetting.ts │ │ └── web │ │ │ ├── useAppInject.ts │ │ │ ├── useContentHeight.ts │ │ │ ├── useContextMenu.ts │ │ │ ├── useCopyToClipboard.ts │ │ │ ├── useDesign.ts │ │ │ ├── useECharts.ts │ │ │ ├── useFullContent.ts │ │ │ ├── useI18n.ts │ │ │ ├── useLockPage.ts │ │ │ ├── useMessage.tsx │ │ │ ├── usePage.ts │ │ │ ├── usePagination.ts │ │ │ ├── usePermission.ts │ │ │ ├── useScript.ts │ │ │ ├── useSortable.ts │ │ │ ├── useTabs.ts │ │ │ ├── useTitle.ts │ │ │ └── useWatermark.ts │ ├── index.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 │ │ │ │ │ ├── OnlineCount.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.vue │ │ │ │ ├── index3.less │ │ │ │ ├── types.ts │ │ │ │ ├── useMultipleTabs.ts │ │ │ │ └── useTabDropdown.ts │ │ │ └── trigger │ │ │ │ ├── HeaderTrigger.vue │ │ │ │ ├── SiderTrigger.vue │ │ │ │ └── index.vue │ │ ├── iframe │ │ │ ├── FrameBlank.vue │ │ │ ├── FramePage.vue │ │ │ ├── FrameSimple.vue │ │ │ ├── index.vue │ │ │ └── useFrameKeepAlive.ts │ │ ├── page │ │ │ ├── index.vue │ │ │ └── transition.ts │ │ └── views │ │ │ ├── account │ │ │ ├── center.vue │ │ │ ├── modPwd.vue │ │ │ ├── modPwdQuestion.vue │ │ │ ├── oauth2Binder.vue │ │ │ ├── secureSettings.vue │ │ │ └── userInfo.vue │ │ │ ├── desktop │ │ │ ├── about │ │ │ │ └── index.vue │ │ │ ├── analysis │ │ │ │ ├── components │ │ │ │ │ ├── GrowCard.vue │ │ │ │ │ ├── SalesProductPie.vue │ │ │ │ │ ├── SiteAnalysis.vue │ │ │ │ │ ├── VisitAnalysis.vue │ │ │ │ │ ├── VisitAnalysisBar.vue │ │ │ │ │ ├── VisitRadar.vue │ │ │ │ │ └── VisitSource.vue │ │ │ │ └── index.vue │ │ │ └── workbench │ │ │ │ ├── components │ │ │ │ ├── Data.tsx │ │ │ │ ├── DynamicInfo.vue │ │ │ │ ├── ProjectCard.vue │ │ │ │ ├── QuickNav.vue │ │ │ │ ├── SaleRadar.vue │ │ │ │ └── WorkbenchHeader.vue │ │ │ │ └── index.vue │ │ │ ├── errorLog │ │ │ ├── DetailModal.vue │ │ │ ├── data.tsx │ │ │ └── index.vue │ │ │ ├── exception │ │ │ ├── Exception.vue │ │ │ ├── index.ts │ │ │ └── index.vue │ │ │ ├── lock │ │ │ ├── LockPage.vue │ │ │ ├── index.vue │ │ │ └── useNow.ts │ │ │ ├── login │ │ │ ├── ForgetPasswordForm.vue │ │ │ ├── Login.vue │ │ │ ├── LoginForm.vue │ │ │ ├── LoginFormTitle.vue │ │ │ ├── MobileForm.vue │ │ │ ├── QrCodeForm.vue │ │ │ ├── RegisterForm.vue │ │ │ ├── SessionTimeoutLogin.vue │ │ │ └── useLogin.ts │ │ │ └── redirect │ │ │ └── index.vue │ ├── locales │ │ ├── helper.ts │ │ ├── lang │ │ │ ├── en.ts │ │ │ ├── en │ │ │ │ ├── common.ts │ │ │ │ ├── component.ts │ │ │ │ ├── layout.ts │ │ │ │ ├── routes │ │ │ │ │ ├── basic.ts │ │ │ │ │ ├── dashboard.ts │ │ │ │ │ └── demo.ts │ │ │ │ └── sys.ts │ │ │ ├── zh-CN │ │ │ │ ├── common.ts │ │ │ │ ├── component.ts │ │ │ │ ├── layout.ts │ │ │ │ ├── routes │ │ │ │ │ ├── basic.ts │ │ │ │ │ ├── dashboard.ts │ │ │ │ │ └── demo.ts │ │ │ │ └── sys.ts │ │ │ └── zh_CN.ts │ │ ├── setupI18n.ts │ │ └── useLocale.ts │ ├── logics │ │ ├── error-handle │ │ │ └── index.ts │ │ ├── initAppConfig.ts │ │ ├── mitt │ │ │ └── routeChange.ts │ │ └── theme │ │ │ ├── dark.ts │ │ │ ├── index.ts │ │ │ ├── updateBackground.ts │ │ │ ├── updateColorWeak.ts │ │ │ ├── updateGrayMode.ts │ │ │ └── util.ts │ ├── package.json │ ├── router │ │ ├── constant.ts │ │ ├── guard │ │ │ ├── index.ts │ │ │ ├── paramMenuGuard.ts │ │ │ ├── permissionGuard.ts │ │ │ └── stateGuard.ts │ │ ├── helper │ │ │ ├── menuHelper.ts │ │ │ └── routeHelper.ts │ │ ├── index.ts │ │ ├── menus │ │ │ └── index.ts │ │ ├── routes │ │ │ ├── basic.ts │ │ │ ├── index.ts │ │ │ ├── mainOut.ts │ │ │ └── modules │ │ │ │ ├── account.ts │ │ │ │ └── desktop.ts │ │ └── types.ts │ ├── settings │ │ ├── componentSetting.ts │ │ ├── designSetting.ts │ │ ├── encryptionSetting.ts │ │ ├── localeSetting.ts │ │ ├── projectSetting.ts │ │ └── siteSetting.ts │ ├── store │ │ ├── index.ts │ │ └── modules │ │ │ ├── app.ts │ │ │ ├── errorLog.ts │ │ │ ├── locale.ts │ │ │ ├── lock.ts │ │ │ ├── multipleTab.ts │ │ │ ├── permission.ts │ │ │ └── user.ts │ ├── tsconfig.json │ ├── utils │ │ ├── auth │ │ │ └── index.ts │ │ ├── cache │ │ │ ├── index.ts │ │ │ ├── memory.ts │ │ │ ├── persistent.ts │ │ │ └── storageCache.ts │ │ ├── cipher.ts │ │ ├── color.ts │ │ ├── dateUtil.ts │ │ ├── domUtils.ts │ │ ├── env.ts │ │ ├── event │ │ │ └── index.ts │ │ ├── factory │ │ │ └── createAsyncComponent.tsx │ │ ├── file │ │ │ ├── base64Conver.ts │ │ │ └── download.ts │ │ ├── helper │ │ │ ├── treeHelper.ts │ │ │ └── tsxHelper.tsx │ │ ├── http │ │ │ └── axios │ │ │ │ ├── Axios.ts │ │ │ │ ├── axiosCancel.ts │ │ │ │ ├── axiosTransform.ts │ │ │ │ ├── checkStatus.ts │ │ │ │ ├── helper.ts │ │ │ │ └── index.ts │ │ ├── index.ts │ │ ├── is.ts │ │ ├── lib │ │ │ └── echarts.ts │ │ ├── log.ts │ │ ├── mitt.ts │ │ ├── propTypes.ts │ │ └── uuid.ts │ └── views │ │ ├── msg │ │ └── msgInner │ │ │ ├── form.vue │ │ │ ├── list.vue │ │ │ └── view.vue │ │ └── sys │ │ ├── area │ │ ├── form.vue │ │ ├── index.vue │ │ └── list.vue │ │ ├── company │ │ ├── form.vue │ │ ├── index.vue │ │ └── list.vue │ │ ├── config │ │ ├── form.vue │ │ └── list.vue │ │ ├── corpAdmin │ │ ├── form.vue │ │ └── list.vue │ │ ├── dictData │ │ ├── form.vue │ │ └── list.vue │ │ ├── dictType │ │ ├── form.vue │ │ └── list.vue │ │ ├── empUser │ │ ├── form.vue │ │ ├── formAuthDataScope.vue │ │ ├── formEmployeeOfficeList.vue │ │ ├── formImport.vue │ │ ├── formUserRoleList.vue │ │ ├── index.vue │ │ └── list.vue │ │ ├── log │ │ ├── form.vue │ │ └── list.vue │ │ ├── menu │ │ ├── form.vue │ │ ├── index.vue │ │ └── list.vue │ │ ├── module │ │ ├── form.vue │ │ └── list.vue │ │ ├── office │ │ ├── form.vue │ │ ├── formImport.vue │ │ ├── index.vue │ │ └── list.vue │ │ ├── online │ │ └── list.vue │ │ ├── post │ │ ├── form.vue │ │ └── list.vue │ │ ├── role │ │ ├── components │ │ │ ├── CustomDataScope.vue │ │ │ ├── MenuDataScope.vue │ │ │ ├── RoleDataScope.vue │ │ │ ├── RuleDataScope.vue │ │ │ └── SqlDataScope.vue │ │ ├── form.vue │ │ ├── formAuthDataScope.vue │ │ ├── formAuthUser.vue │ │ └── list.vue │ │ └── secAdmin │ │ ├── form.vue │ │ └── list.vue ├── dbm │ ├── README.md │ ├── api │ │ └── biz │ │ │ └── bizCategory.ts │ ├── index.ts │ ├── package.json │ ├── tsconfig.json │ └── views │ │ ├── biz │ │ └── bizCategory │ │ │ ├── form.vue │ │ │ ├── index.vue │ │ │ └── list.vue │ │ └── dbm │ │ ├── dbmDatasource │ │ └── list.vue │ │ ├── dbmModifyLog │ │ └── list.vue │ │ └── dbmTable │ │ └── list.vue ├── dfm │ ├── .gitignore │ ├── README.md │ ├── index.ts │ ├── package.json │ ├── tsconfig.json │ └── views │ │ └── dfm │ │ └── designer │ │ └── index.vue ├── test │ ├── README.md │ ├── api │ │ └── test │ │ │ ├── testData.ts │ │ │ └── testTree.ts │ ├── package.json │ ├── tsconfig.json │ └── views │ │ ├── demo │ │ ├── markdown.vue │ │ ├── params.vue │ │ └── watermark.vue │ │ └── test │ │ ├── testData │ │ ├── form.vue │ │ ├── formDataChildList.vue │ │ ├── formModal.vue │ │ ├── formRoute.vue │ │ ├── formTabs.vue │ │ ├── list.vue │ │ └── select.ts │ │ └── testTree │ │ ├── form.vue │ │ ├── index.vue │ │ └── list.vue ├── tests │ ├── README.md │ ├── nodemon.json │ ├── package.json │ ├── pm2.config.cjs │ ├── src │ │ ├── config │ │ │ └── index.ts │ │ ├── controller │ │ │ ├── FileController.ts │ │ │ ├── MenuController.ts │ │ │ └── UserController.ts │ │ ├── index.ts │ │ ├── router │ │ │ ├── index.ts │ │ │ └── routes.ts │ │ ├── service │ │ │ ├── FileService.ts │ │ │ ├── MenuService.ts │ │ │ └── UserService.ts │ │ ├── utils │ │ │ └── index.ts │ │ └── ws │ │ │ └── index.ts │ └── tsconfig.json ├── types │ ├── README.md │ ├── axios.d.ts │ ├── config.d.ts │ ├── global.d.ts │ ├── index.d.ts │ ├── package.json │ ├── store.d.ts │ ├── tsconfig.json │ ├── utils.d.ts │ └── vue-router.d.ts └── vite │ ├── README.md │ ├── build.config.ts │ ├── config │ ├── appConfig.ts │ ├── getEnvConfigName.ts │ └── index.ts │ ├── index.ts │ ├── options │ ├── build.ts │ ├── css.ts │ ├── define.ts │ ├── esBuild.ts │ ├── index.ts │ └── server.ts │ ├── package.json │ ├── plugins │ ├── compress.ts │ ├── html.ts │ ├── index.ts │ ├── legacy.ts │ ├── monacoEditor.ts │ ├── unocss.ts │ └── visualizer.ts │ ├── theme │ ├── index.ts │ ├── modifyVars.ts │ └── themeConfig.ts │ └── tsconfig.json ├── pnpm-lock.yaml ├── pnpm-workspace.yaml ├── stylelint.config.mjs ├── terms.md ├── tsconfig.json ├── turbo.json ├── uno.config.ts └── web ├── .env ├── .env.development ├── .env.production ├── .env.tomcat ├── api └── sys │ ├── config.ts │ ├── log.ts │ ├── menu.ts │ ├── module.ts │ └── secAdmin.ts ├── index.html ├── package.json ├── public ├── favicon.png ├── resource │ ├── css │ │ └── index.css │ ├── img │ │ ├── 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 │ │ │ ├── total-sales.svg │ │ │ ├── transaction.svg │ │ │ └── visit-count.svg │ │ ├── logo.png │ │ ├── pwa-192x192.png │ │ └── pwa-512x512.png │ └── layer │ │ ├── layer.js │ │ └── theme │ │ └── default │ │ ├── close.svg │ │ ├── full-1.svg │ │ ├── full-2.svg │ │ ├── icon-ext.png │ │ ├── icon.png │ │ ├── layer.css │ │ ├── loading-0.gif │ │ ├── loading-1.gif │ │ └── loading-2.gif └── timestamp.txt ├── src ├── App.vue └── main.ts ├── tsconfig.json ├── uno.config.ts └── vite.config.ts /.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 | [*.{ts,mts,tsx,vue}] 12 | ij_typescript_use_chained_calls_group_indents = false 13 | ij_typescript_use_double_quotes = false 14 | ij_typescript_use_explicit_js_extension = auto 15 | ij_typescript_use_import_type = auto 16 | ij_typescript_use_path_mapping = always 17 | ij_typescript_use_public_modifier = false 18 | ij_typescript_use_semicolon_after_statement = true 19 | 20 | [*.{yml,yaml,json}] 21 | indent_style = space 22 | indent_size = 2 23 | 24 | [*.md] 25 | trim_trailing_whitespace = false 26 | 27 | [Makefile] 28 | indent_style = tab 29 | -------------------------------------------------------------------------------- /.gitee/ISSUE_TEMPLATE.zh-CN.md: -------------------------------------------------------------------------------- 1 | ### 是什么问题、该问题是怎么引起的? 2 | 3 | 1. 4 | 5 | ### 重现步骤、期望结果、截图、代码 6 | 7 | 1. 8 | ``` 9 | 这里贴你的代码块 10 | ``` 11 | 12 | ### 实际结果、报错信息、截图 13 | 14 | 1. 15 | ``` 16 | 这里贴错误信息 17 | ``` 18 | 19 | ### 环境版本: 20 | 21 | - 浏览器版本:Chrome xx、Firefox xx、其它 22 | - 平台版本:JeeSite 4.x.x、5.x.x(package.json里查看) 23 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | Thumbs.db 3 | .DS_Store 4 | .vercel 5 | .turbo 6 | .cache 7 | dist 8 | 9 | upgrade 10 | 11 | # Test files 12 | tests/server/static 13 | tests/server/static/upload 14 | coverage 15 | 16 | # Local files 17 | .local 18 | .env.local 19 | .env.*.local 20 | .eslintcache 21 | 22 | # Log files 23 | npm-debug.log* 24 | yarn-debug.log* 25 | yarn-error.log* 26 | pnpm-debug.log* 27 | vite.config.ts.timestamp* 28 | 29 | # IDE files 30 | .idea 31 | *.suo 32 | *.ntvs* 33 | *.njsproj 34 | *.sln 35 | *.sw? 36 | *.iml 37 | -------------------------------------------------------------------------------- /.npmrc: -------------------------------------------------------------------------------- 1 | @jeesite:registry=https://maven.jeesite.net/repository/npm-package/ 2 | registry=https://registry.npmmirror.com 3 | package-manager-strict=false 4 | auto-install-peers = true 5 | git-checks=false 6 | -------------------------------------------------------------------------------- /.prettierignore: -------------------------------------------------------------------------------- 1 | dist 2 | public 3 | node_modules 4 | 5 | .local 6 | .npmrc 7 | .output.js 8 | 9 | *.sh 10 | *.md 11 | *.svg 12 | *.html 13 | *.json 14 | *-lock.yaml 15 | -------------------------------------------------------------------------------- /.prettierrc.mjs: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2013-Now http://jeesite.com All rights reserved. 3 | * No deletion without permission, or be held responsible to law. 4 | * @author ThinkGem 5 | */ 6 | export default { 7 | printWidth: 120, 8 | tabWidth: 2, 9 | useTabs: false, 10 | semi: true, 11 | vueIndentScriptAndStyle: true, 12 | singleQuote: true, 13 | quoteProps: 'as-needed', 14 | bracketSpacing: true, 15 | trailingComma: 'all', 16 | jsxSingleQuote: false, 17 | arrowParens: 'always', 18 | insertPragma: false, 19 | requirePragma: false, 20 | proseWrap: 'preserve', 21 | htmlWhitespaceSensitivity: 'strict', 22 | endOfLine: 'auto', 23 | plugins: ['prettier-plugin-packagejson'], 24 | overrides: [ 25 | { 26 | files: '.*rc', 27 | options: { 28 | parser: 'json', 29 | }, 30 | }, 31 | ], 32 | }; 33 | -------------------------------------------------------------------------------- /.stylelintignore: -------------------------------------------------------------------------------- 1 | dist 2 | public 3 | node_modules 4 | 5 | *.sh 6 | *.md 7 | -------------------------------------------------------------------------------- /.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 | "antfu.unocss", 11 | "mikestead.dotenv", 12 | "formulahendry.auto-rename-tag", 13 | "donjayamanne.githistory", 14 | "pmneo.tsimporter" 15 | ] 16 | } 17 | -------------------------------------------------------------------------------- /.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "0.2.0", 3 | "configurations": [ 4 | { 5 | "type": "chrome", 6 | "request": "launch", 7 | "name": "Launch Chrome", 8 | "url": "http://localhost:3100", 9 | "webRoot": "${workspaceFolder}/src", 10 | "sourceMaps": true 11 | } 12 | ] 13 | } 14 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | 2 | 版权所有:http://jeesite.com 3 | 4 | 技术服务:http://s.jeesite.com 5 | 6 | 禁止盗版、剽窃、非法复制、抄袭,违者必究。 7 | 8 | Copyright owner: http://jeesite.com 9 | 10 | Technical Services: http://s.jeesite.com 11 | 12 | Unauthorized piracy, plagiarism, illegal copying, and copying 13 | in any form are prohibited. We firmly uphold our legitimate 14 | rights and interests. For any violation of this provision, 15 | once discovered, we will pursue relevant responsibilities 16 | according to the law. 17 | -------------------------------------------------------------------------------- /bin/build.bat: -------------------------------------------------------------------------------- 1 | @echo off 2 | %~d0 3 | cd %~dp0 4 | 5 | cd.. 6 | npm run build 7 | 8 | cd bin 9 | pause -------------------------------------------------------------------------------- /bin/build.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | cd .. 3 | npm run build 4 | 5 | cd bin 6 | -------------------------------------------------------------------------------- /bin/install.bat: -------------------------------------------------------------------------------- 1 | @echo off 2 | %~d0 3 | cd %~dp0 4 | 5 | cd.. 6 | npm run install 7 | 8 | cd bin 9 | pause -------------------------------------------------------------------------------- /bin/install.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | cd.. 3 | npm run install 4 | 5 | cd bin 6 | -------------------------------------------------------------------------------- /bin/startup.bat: -------------------------------------------------------------------------------- 1 | @echo off 2 | %~d0 3 | cd %~dp0 4 | 5 | cd.. 6 | pnpm dev 7 | 8 | cd bin 9 | pause -------------------------------------------------------------------------------- /bin/startup.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | cd .. 3 | pnpm dev 4 | 5 | cd bin 6 | -------------------------------------------------------------------------------- /packages/assets/README.md: -------------------------------------------------------------------------------- 1 | 2 | - 官方网站: 3 | - 使用文档: 4 | - 后端代码: 5 | - 前端代码: 6 | 7 | ------ 8 | 9 |
10 | 如果你喜欢 JeeSite,请给她一个 ⭐️ Star,您的支持将是我们前行的动力。 11 |
12 | 13 | ------ 14 | 15 | - 问题反馈: [【新手必读】](https://gitee.com/thinkgem/jeesite5/issues/I18ARR) 16 | - 需求收集: 17 | - QQ 群:`127515876`、`209330483`、`223507718`、`709534275`、`730390092`、`1373527`、`183903863(外包)` 18 | - 微信群:添加客服微信 邀请您进群 19 | - 关注微信公众号,了解最新动态: 20 | 21 |

22 | JeeSite微信公众号 23 |

24 | -------------------------------------------------------------------------------- /packages/assets/images/header.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thinkgem/jeesite/dbb4a7e878550525657c6e4ac4a694fafd77faa4/packages/assets/images/header.jpg -------------------------------------------------------------------------------- /packages/assets/images/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thinkgem/jeesite/dbb4a7e878550525657c6e4ac4a694fafd77faa4/packages/assets/images/logo.png -------------------------------------------------------------------------------- /packages/assets/images/mp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thinkgem/jeesite/dbb4a7e878550525657c6e4ac4a694fafd77faa4/packages/assets/images/mp.png -------------------------------------------------------------------------------- /packages/assets/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@jeesite/assets", 3 | "version": "5.12.0", 4 | "private": true, 5 | "type": "module", 6 | "scripts": { 7 | "uninstall": "rimraf node_modules", 8 | "update": "ncu -u" 9 | }, 10 | "homepage": "https://jeesite.com", 11 | "repository": { 12 | "type": "git", 13 | "url": "https://gitee.com/thinkgem/jeesite-vue.git" 14 | }, 15 | "bugs": { 16 | "url": "https://gitee.com/thinkgem/jeesite-vue/issues" 17 | }, 18 | "author": { 19 | "name": "ThinkGem", 20 | "email": "thinkgem@163.com", 21 | "url": "https://gitee.com/thinkgem" 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /packages/assets/svg/preview/resume.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /packages/assets/svg/preview/scale.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /packages/assets/svg/preview/unscale.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /packages/assets/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json", 3 | "compilerOptions": { 4 | "baseUrl": ".", 5 | "paths": { 6 | "@jeesite/assets/*": ["./*"] 7 | } 8 | }, 9 | "include": [ 10 | "./**/*.ts", 11 | "./**/*.tsx", 12 | "./**/*.vue" 13 | ], 14 | "exclude": [ 15 | "node_modules", 16 | "vite.config.ts", 17 | "dist" 18 | ] 19 | } 20 | -------------------------------------------------------------------------------- /packages/cms/README.md: -------------------------------------------------------------------------------- 1 | 2 | - 官方网站: 3 | - 使用文档: 4 | - 后端代码: 5 | - 前端代码: 6 | 7 | ------ 8 | 9 |
10 | 如果你喜欢 JeeSite,请给她一个 ⭐️ Star,您的支持将是我们前行的动力。 11 |
12 | 13 | ------ 14 | 15 | - 问题反馈: [【新手必读】](https://gitee.com/thinkgem/jeesite5/issues/I18ARR) 16 | - 需求收集: 17 | - QQ 群:`127515876`、`209330483`、`223507718`、`709534275`、`730390092`、`1373527`、`183903863(外包)` 18 | - 微信群:添加客服微信 邀请您进群 19 | - 关注微信公众号,了解最新动态: 20 | 21 |

22 | JeeSite微信公众号 23 |

24 | -------------------------------------------------------------------------------- /packages/cms/index.ts: -------------------------------------------------------------------------------- 1 | import './node_modules/@jeesite/cms-lib/dist/style.css'; 2 | export { ChatMessage } from './node_modules/@jeesite/cms-lib/dist'; 3 | -------------------------------------------------------------------------------- /packages/cms/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@jeesite/cms", 3 | "version": "5.12.0", 4 | "private": true, 5 | "type": "module", 6 | "scripts": { 7 | "type:check": "vue-tsc --noEmit --skipLibCheck", 8 | "uninstall": "rimraf node_modules", 9 | "update": "ncu -u" 10 | }, 11 | "dependencies": { 12 | "@jeesite/cms-lib": "5.12.0-rc.1", 13 | "qs": "6.14.0" 14 | }, 15 | "devDependencies": { 16 | "@types/qs": "6.9.18" 17 | }, 18 | "homepage": "https://jeesite.com", 19 | "repository": { 20 | "type": "git", 21 | "url": "https://gitee.com/thinkgem/jeesite-vue.git" 22 | }, 23 | "bugs": { 24 | "url": "https://gitee.com/thinkgem/jeesite-vue/issues" 25 | }, 26 | "author": { 27 | "name": "ThinkGem", 28 | "email": "thinkgem@163.com", 29 | "url": "https://gitee.com/thinkgem" 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /packages/cms/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json", 3 | "compilerOptions": { 4 | "baseUrl": ".", 5 | "paths": { 6 | "@jeesite/cms/*": ["./*"] 7 | } 8 | }, 9 | "include": [ 10 | "./**/*.ts", 11 | "./**/*.tsx", 12 | "./**/*.vue" 13 | ], 14 | "exclude": [ 15 | "node_modules", 16 | "vite.config.ts", 17 | "_lib", 18 | "dist" 19 | ] 20 | } 21 | -------------------------------------------------------------------------------- /packages/core/README.md: -------------------------------------------------------------------------------- 1 | 2 | - 官方网站: 3 | - 使用文档: 4 | - 后端代码: 5 | - 前端代码: 6 | 7 | ------ 8 | 9 |
10 | 如果你喜欢 JeeSite,请给她一个 ⭐️ Star,您的支持将是我们前行的动力。 11 |
12 | 13 | ------ 14 | 15 | - 问题反馈: [【新手必读】](https://gitee.com/thinkgem/jeesite5/issues/I18ARR) 16 | - 需求收集: 17 | - QQ 群:`127515876`、`209330483`、`223507718`、`709534275`、`730390092`、`1373527`、`183903863(外包)` 18 | - 微信群:添加客服微信 邀请您进群 19 | - 关注微信公众号,了解最新动态: 20 | 21 |

22 | JeeSite微信公众号 23 |

24 | -------------------------------------------------------------------------------- /packages/core/api/index.ts: -------------------------------------------------------------------------------- 1 | // export * from './sys'; 2 | -------------------------------------------------------------------------------- /packages/core/api/model/baseModel.ts: -------------------------------------------------------------------------------- 1 | import type { Result } from '@jeesite/types/axios'; 2 | 3 | /** 4 | * Copyright (c) 2013-Now http://jeesite.com All rights reserved. 5 | * No deletion without permission, or be held responsible to law. 6 | * @author ThinkGem 7 | */ 8 | export interface Page { 9 | pageNo: number; 10 | pageSize: number; 11 | orderBy: string; 12 | count: number; 13 | list: T[]; 14 | } 15 | 16 | export interface BasicModel extends Result, Recordable { 17 | id: string; 18 | page: Page; 19 | isNewRecord: boolean; 20 | dataMap: Map; 21 | } 22 | 23 | export interface TreeModel extends BasicModel { 24 | parentCode?: string; // 父级编码 25 | parentCodes?: string; // 所有父级编号 26 | 27 | treeNames?: string; // 全节点名 28 | 29 | treeSort?: string; // 排序号 30 | treeSorts?: string; // 所有排序号 31 | 32 | treeLeaf?: string; // 是否叶子节点 33 | treeLevel?: number; // 树层次级别(从0开始) 34 | 35 | childList?: T[]; // 子项列表 36 | 37 | isRoot?: boolean; // 是否根节点 38 | isTreeLeaf?: boolean; // 是否叶子 39 | isLoading?: boolean; // 是否加载中 40 | } 41 | 42 | export interface TreeDataModel { 43 | id: string; 44 | pId: string; 45 | name: string; 46 | value?: string; 47 | title?: string; 48 | } 49 | -------------------------------------------------------------------------------- /packages/core/api/sys/index.ts: -------------------------------------------------------------------------------- 1 | export * from './area'; 2 | export * from './company'; 3 | export * from './config'; 4 | export * from './corpAdmin'; 5 | export * from './dictData'; 6 | export * from './dictType'; 7 | export * from './empUser'; 8 | export * from './log'; 9 | export * from './login'; 10 | export * from './menu'; 11 | export * from './module'; 12 | export * from './office'; 13 | export * from './online'; 14 | export * from './post'; 15 | export * from './role'; 16 | export * from './secAdmin'; 17 | export * from './upload'; 18 | export * from './user'; 19 | -------------------------------------------------------------------------------- /packages/core/api/sys/secAdmin.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2013-Now http://jeesite.com All rights reserved. 3 | * No deletion without permission, or be held responsible to law. 4 | * @author ThinkGem 5 | */ 6 | import { defHttp } from '@jeesite/core/utils/http/axios'; 7 | import { useGlobSetting } from '@jeesite/core/hooks/setting'; 8 | import { Page } from '@jeesite/core/api/model/baseModel'; 9 | import { User } from '@jeesite/core/api/sys/user'; 10 | 11 | const { adminPath } = useGlobSetting(); 12 | 13 | export const secAdminList = (params?: User | any) => 14 | defHttp.get({ url: adminPath + '/sys/secAdmin/list', params }); 15 | 16 | export const secAdminListData = (params?: User | any) => 17 | defHttp.post>({ url: adminPath + '/sys/secAdmin/listData', params }); 18 | 19 | export const secAdminForm = (params?: User | any) => 20 | defHttp.get({ url: adminPath + '/sys/secAdmin/form', params }); 21 | 22 | export const secAdminSave = (params?: any) => defHttp.post({ url: adminPath + '/sys/secAdmin/save', params }); 23 | 24 | export const secAdminDelete = (params?: User | any) => 25 | defHttp.get({ url: adminPath + '/sys/secAdmin/delete', params }); 26 | -------------------------------------------------------------------------------- /packages/core/components/Application/index.ts: -------------------------------------------------------------------------------- 1 | import { withInstall } from '@jeesite/core/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 | -------------------------------------------------------------------------------- /packages/core/components/Application/src/search/AppSearch.vue: -------------------------------------------------------------------------------- 1 | 35 | -------------------------------------------------------------------------------- /packages/core/components/Application/src/search/AppSearchKeyItem.vue: -------------------------------------------------------------------------------- 1 | 6 | 12 | -------------------------------------------------------------------------------- /packages/core/components/Application/src/useAppContext.ts: -------------------------------------------------------------------------------- 1 | import { InjectionKey, Ref } from 'vue'; 2 | import { createContext, useContext } from '@jeesite/core/hooks/core/useContext'; 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 | -------------------------------------------------------------------------------- /packages/core/components/Authority/index.ts: -------------------------------------------------------------------------------- 1 | import { withInstall } from '@jeesite/core/utils'; 2 | import authority from './src/Authority.vue'; 3 | 4 | export const Authority = withInstall(authority); 5 | -------------------------------------------------------------------------------- /packages/core/components/Basic/index.ts: -------------------------------------------------------------------------------- 1 | import { withInstall } from '@jeesite/core/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 | -------------------------------------------------------------------------------- /packages/core/components/Button/index.ts: -------------------------------------------------------------------------------- 1 | import { withInstall } from '@jeesite/core/utils'; 2 | import type { ExtractPropTypes } from 'vue'; 3 | import button from './src/BasicButton.vue'; 4 | import popConfirmButton from './src/PopConfirmButton.vue'; 5 | import { buttonProps } from './src/props'; 6 | 7 | export const Button = withInstall(button); 8 | export const PopConfirmButton = withInstall(popConfirmButton); 9 | export declare type ButtonProps = Partial>; 10 | -------------------------------------------------------------------------------- /packages/core/components/Button/src/BasicButton.vue: -------------------------------------------------------------------------------- 1 | 10 | 36 | -------------------------------------------------------------------------------- /packages/core/components/Button/src/props.ts: -------------------------------------------------------------------------------- 1 | export const buttonProps = { 2 | color: { type: String, validator: (v) => ['error', 'warning', 'success', ''].includes(v) }, 3 | loading: { type: Boolean }, 4 | disabled: { type: Boolean }, 5 | /** 6 | * Text before icon. 7 | */ 8 | preIcon: { type: String }, 9 | /** 10 | * Text after icon. 11 | */ 12 | postIcon: { type: String }, 13 | /** 14 | * preIcon and postIcon icon size. 15 | * @default: 14 16 | */ 17 | iconSize: { type: Number, default: 14 }, 18 | onClick: { type: Function as PropType<(...args) => any>, default: null }, 19 | }; 20 | -------------------------------------------------------------------------------- /packages/core/components/CardList/index.ts: -------------------------------------------------------------------------------- 1 | import { withInstall } from '@jeesite/core/utils'; 2 | import cardList from './src/CardList.vue'; 3 | 4 | export const CardList = withInstall(cardList); 5 | -------------------------------------------------------------------------------- /packages/core/components/CardList/src/data.ts: -------------------------------------------------------------------------------- 1 | import { ref } from 'vue'; 2 | // 每行个数 3 | export const grid = ref(20); 4 | // slider属性 5 | export const useSlider = (min = 6, max = 20) => { 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 | -------------------------------------------------------------------------------- /packages/core/components/ClickOutSide/index.ts: -------------------------------------------------------------------------------- 1 | import { withInstall } from '@jeesite/core/utils'; 2 | import clickOutSide from './src/ClickOutSide.vue'; 3 | 4 | export const ClickOutSide = withInstall(clickOutSide); 5 | -------------------------------------------------------------------------------- /packages/core/components/ClickOutSide/src/ClickOutSide.vue: -------------------------------------------------------------------------------- 1 | 6 | 20 | -------------------------------------------------------------------------------- /packages/core/components/CodeEditor/index.ts: -------------------------------------------------------------------------------- 1 | import { withInstall } from '@jeesite/core/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 | -------------------------------------------------------------------------------- /packages/core/components/CodeEditor/src/json-preview/JsonPreview.vue: -------------------------------------------------------------------------------- 1 | 4 | 12 | 17 | -------------------------------------------------------------------------------- /packages/core/components/CollapseForm/index.ts: -------------------------------------------------------------------------------- 1 | import CollapseForm from './src/CollapseForm.vue'; 2 | 3 | export { CollapseForm }; 4 | -------------------------------------------------------------------------------- /packages/core/components/Container/index.ts: -------------------------------------------------------------------------------- 1 | import { withInstall } from '@jeesite/core/utils'; 2 | import collapseContainer from './src/collapse/CollapseContainer.vue'; 3 | import scrollContainer from './src/ScrollContainer.vue'; 4 | import lazyContainer from './src/LazyContainer.vue'; 5 | 6 | export const CollapseContainer = withInstall(collapseContainer); 7 | export const ScrollContainer = withInstall(scrollContainer); 8 | export const LazyContainer = withInstall(lazyContainer); 9 | 10 | export * from './src/typing'; 11 | -------------------------------------------------------------------------------- /packages/core/components/Container/src/collapse/CollapseHeader.vue: -------------------------------------------------------------------------------- 1 | 17 | 39 | -------------------------------------------------------------------------------- /packages/core/components/Container/src/typing.ts: -------------------------------------------------------------------------------- 1 | export type ScrollType = 'default' | 'main'; 2 | 3 | export interface CollapseContainerOptions { 4 | canExpand?: boolean; 5 | expand?: boolean; 6 | title?: string; 7 | helpMessage?: Array | string; 8 | } 9 | export interface ScrollContainerOptions { 10 | enableScroll?: boolean; 11 | type?: ScrollType; 12 | } 13 | 14 | export type ScrollActionType = RefType<{ 15 | scrollBottom: () => void; 16 | getScrollWrap: () => Nullable; 17 | scrollTo: (top: number) => void; 18 | }>; 19 | -------------------------------------------------------------------------------- /packages/core/components/ContextMenu/index.ts: -------------------------------------------------------------------------------- 1 | export { createContextMenu, destroyContextMenu } from './src/createContextMenu'; 2 | 3 | export * from './src/typing'; 4 | -------------------------------------------------------------------------------- /packages/core/components/ContextMenu/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?: Fn; 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: Fn; 35 | } 36 | -------------------------------------------------------------------------------- /packages/core/components/CountDown/index.ts: -------------------------------------------------------------------------------- 1 | import { withInstall } from '@jeesite/core/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 | -------------------------------------------------------------------------------- /packages/core/components/CountDown/src/useCountdown.ts: -------------------------------------------------------------------------------- 1 | import { ref, unref } from 'vue'; 2 | import { tryOnUnmounted } from '@vueuse/core'; 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 | -------------------------------------------------------------------------------- /packages/core/components/CountTo/index.ts: -------------------------------------------------------------------------------- 1 | import { withInstall } from '@jeesite/core/utils'; 2 | import countTo from './src/CountTo.vue'; 3 | 4 | export const CountTo = withInstall(countTo); 5 | -------------------------------------------------------------------------------- /packages/core/components/Cropper/index.ts: -------------------------------------------------------------------------------- 1 | import { withInstall } from '@jeesite/core/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 | -------------------------------------------------------------------------------- /packages/core/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 | -------------------------------------------------------------------------------- /packages/core/components/Description/index.ts: -------------------------------------------------------------------------------- 1 | import { withInstall } from '@jeesite/core/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 | -------------------------------------------------------------------------------- /packages/core/components/Description/src/useDescription.ts: -------------------------------------------------------------------------------- 1 | import type { DescriptionProps, DescInstance, UseDescReturnType } from './typing'; 2 | import { ref, getCurrentInstance, unref } from 'vue'; 3 | import { isProdMode } from '@jeesite/core/utils/env'; 4 | 5 | export function useDescription(props?: Partial): UseDescReturnType { 6 | if (!getCurrentInstance()) { 7 | throw new Error('useDescription() can only be used inside setup() or functional components!'); 8 | } 9 | const desc = ref>(null); 10 | const loaded = ref(false); 11 | 12 | function register(instance: DescInstance) { 13 | if (unref(loaded) && isProdMode()) { 14 | return; 15 | } 16 | desc.value = instance; 17 | props && instance.setDescProps(props); 18 | loaded.value = true; 19 | } 20 | 21 | const methods: DescInstance = { 22 | setDescProps: (descProps: Partial): void => { 23 | unref(desc)?.setDescProps(descProps); 24 | }, 25 | }; 26 | 27 | return [register, methods]; 28 | } 29 | -------------------------------------------------------------------------------- /packages/core/components/Dialog/index.ts: -------------------------------------------------------------------------------- 1 | import { withInstall } from '@jeesite/core/utils'; 2 | import basicDialog from './src/BasicDialog.vue'; 3 | 4 | export const BasicDialog = withInstall(basicDialog); 5 | export type BasicDialogInstance = InstanceType; 6 | -------------------------------------------------------------------------------- /packages/core/components/Dict/index.ts: -------------------------------------------------------------------------------- 1 | import { withInstall } from '@jeesite/core/utils'; 2 | import dictLabel from './src/DictLabel.vue'; 3 | 4 | export * from './src/useDict'; 5 | export const DictLabel = withInstall(dictLabel); 6 | -------------------------------------------------------------------------------- /packages/core/components/Drawer/index.ts: -------------------------------------------------------------------------------- 1 | import { withInstall } from '@jeesite/core/utils'; 2 | import basicDrawer from './src/BasicDrawer.vue'; 3 | 4 | export const BasicDrawer = withInstall(basicDrawer); 5 | export type BasicDrawerInstance = InstanceType; 6 | 7 | export * from './src/typing'; 8 | export { useDrawer, useDrawerInner } from './src/useDrawer'; 9 | -------------------------------------------------------------------------------- /packages/core/components/Dropdown/index.ts: -------------------------------------------------------------------------------- 1 | import { withInstall } from '@jeesite/core/utils'; 2 | import dropdown from './src/Dropdown.vue'; 3 | 4 | export * from './src/typing'; 5 | export const Dropdown = withInstall(dropdown); 6 | -------------------------------------------------------------------------------- /packages/core/components/Dropdown/src/typing.ts: -------------------------------------------------------------------------------- 1 | export interface DropMenu { 2 | onClick?: Fn; 3 | to?: string; 4 | icon?: string; 5 | event: string | number; 6 | text: string; 7 | disabled?: boolean; 8 | divider?: boolean; 9 | } 10 | -------------------------------------------------------------------------------- /packages/core/components/Excel/index.ts: -------------------------------------------------------------------------------- 1 | import { withInstall } from '@jeesite/core/utils'; 2 | import impExcel from './src/ImportExcel.vue'; 3 | import expExcelModal from './src/ExportExcelModal.vue'; 4 | 5 | export const ImpExcel = withInstall(impExcel); 6 | export const ExpExcelModal = withInstall(expExcelModal); 7 | export * from './src/typing'; 8 | export { jsonToSheetXlsx, aoaToSheetXlsx } from './src/Export2Excel'; 9 | -------------------------------------------------------------------------------- /packages/core/components/Excel/src/typing.ts: -------------------------------------------------------------------------------- 1 | import type { JSON2SheetOpts, WritingOptions, BookType } from 'xlsx'; 2 | 3 | export interface ExcelData { 4 | header: string[]; 5 | results: T[]; 6 | meta: { sheetName: string }; 7 | } 8 | 9 | export interface JsonToSheet { 10 | data: T[]; 11 | header?: T; 12 | filename?: string; 13 | json2sheetOpts?: JSON2SheetOpts; 14 | write2excelOpts?: WritingOptions; 15 | } 16 | 17 | export interface AoAToSheet { 18 | data: T[][]; 19 | header?: T[]; 20 | filename?: string; 21 | write2excelOpts?: WritingOptions; 22 | } 23 | 24 | export interface ExportModalResult { 25 | filename: string; 26 | bookType: BookType; 27 | } 28 | -------------------------------------------------------------------------------- /packages/core/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 Select } from './src/components/JeeSiteSelect.vue'; 10 | export { default as TreeSelect } from './src/components/JeeSiteTreeSelect.vue'; 11 | export { default as RadioGroup } from './src/components/JeeSiteRadioGroup.vue'; 12 | export { default as RadioButtonGroup } from './src/components/JeeSiteRadioButtonGroup.vue'; 13 | export { default as CheckboxGroup } from './src/components/JeeSiteCheckboxGroup.vue'; 14 | export { default as FormGroup } from './src/components/FormGroup.vue'; 15 | 16 | export { BasicForm }; 17 | -------------------------------------------------------------------------------- /packages/core/components/Form/src/components/FormGroup.vue: -------------------------------------------------------------------------------- 1 | 6 | 13 | 14 | 40 | -------------------------------------------------------------------------------- /packages/core/components/Form/src/hooks/useComponentRegister.ts: -------------------------------------------------------------------------------- 1 | import type { ComponentType } from '../types/index'; 2 | import { tryOnUnmounted } from '@vueuse/core'; 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 | -------------------------------------------------------------------------------- /packages/core/components/Form/src/hooks/useFormContext.ts: -------------------------------------------------------------------------------- 1 | import type { InjectionKey } from 'vue'; 2 | import { createContext, useContext } from '@jeesite/core/hooks/core/useContext'; 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 | -------------------------------------------------------------------------------- /packages/core/components/Form/src/types/hooks.ts: -------------------------------------------------------------------------------- 1 | export interface AdvanceState { 2 | isAdvanced: boolean; 3 | hideAdvanceBtn: boolean; 4 | isLoad: boolean; 5 | actionSpan: number; 6 | } 7 | -------------------------------------------------------------------------------- /packages/core/components/Icon/index.ts: -------------------------------------------------------------------------------- 1 | import Icon from './src/Icon.vue'; 2 | import IconPicker from './src/IconPicker.vue'; 3 | 4 | export { Icon, IconPicker }; 5 | 6 | export default Icon; 7 | -------------------------------------------------------------------------------- /packages/core/components/ListSelect/index.ts: -------------------------------------------------------------------------------- 1 | import { withInstall } from '@jeesite/core/utils'; 2 | import listSelect from './src/ListSelect.vue'; 3 | 4 | export const ListSelect = withInstall(listSelect); 5 | -------------------------------------------------------------------------------- /packages/core/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 | -------------------------------------------------------------------------------- /packages/core/components/Loading/src/typing.ts: -------------------------------------------------------------------------------- 1 | import { SizeEnum } from '@jeesite/core/enums/sizeEnum'; 2 | 3 | export interface LoadingProps { 4 | tip: string; 5 | size: SizeEnum; 6 | absolute: boolean; 7 | loading: boolean; 8 | background: string; 9 | theme: 'dark' | 'light'; 10 | } 11 | -------------------------------------------------------------------------------- /packages/core/components/Markdown/index.ts: -------------------------------------------------------------------------------- 1 | import { withInstall } from '@jeesite/core/utils'; 2 | import markdown from './src/Markdown.vue'; 3 | import markdownViewer from './src/MarkdownViewer.vue'; 4 | 5 | export const Markdown = withInstall(markdown); 6 | export const MarkdownViewer = withInstall(markdownViewer); 7 | export * from './src/typing'; 8 | -------------------------------------------------------------------------------- /packages/core/components/Markdown/src/adapter.js: -------------------------------------------------------------------------------- 1 | // https://developer.mozilla.org/zh-CN/docs/Web/API/MediaDevices/getUserMedia 2 | // 推荐使用处理了约束的 adapter.js polyfill 来替代。 3 | 4 | // 浏览器过老或过新都可能不存在 5 | if (!navigator.mediaDevices) { 6 | navigator.mediaDevices = {}; 7 | 8 | // 一些浏览器部分支持 mediaDevices。我们不能直接给对象设置 getUserMedia 9 | // 因为这样可能会覆盖已有的属性。这里我们只会在没有 getUserMedia 属性的时候添加它。 10 | if (!navigator.mediaDevices.getUserMedia) { 11 | navigator.mediaDevices.getUserMedia = function (constraints) { 12 | // 首先,如果有 getUserMedia 的话,就获得它 13 | const getUserMedia = navigator.webkitGetUserMedia || navigator.mozGetUserMedia; 14 | // 一些浏览器根本没实现它 - 那么就返回一个 error 到 promise 的 reject 来保持一个统一的接口 15 | if (!getUserMedia) { 16 | return Promise.reject(new Error('getUserMedia is not implemented in this browser')); 17 | } 18 | // 否则,为老的 navigator.getUserMedia 方法包裹一个 Promise 19 | return new Promise(function (resolve, reject) { 20 | getUserMedia.call(navigator, constraints, resolve, reject); 21 | }); 22 | }; 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /packages/core/components/Markdown/src/getTheme.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * 获取主题类型 深色浅色模式 对应的值 3 | * @param darkModeVal 深色模式值 4 | * @param themeMode 主题类型——外观(默认), 内容, 代码块 5 | */ 6 | export const getTheme = ( 7 | darkModeVal: 'light' | 'dark' | string, 8 | themeMode: 'default' | 'content' | 'code' = 'default', 9 | ) => { 10 | const isDark = darkModeVal === 'dark'; 11 | switch (themeMode) { 12 | case 'default': 13 | return isDark ? 'dark' : 'classic'; 14 | case 'content': 15 | return isDark ? 'dark' : 'light'; 16 | case 'code': 17 | return isDark ? 'dracula' : 'github'; 18 | } 19 | }; 20 | -------------------------------------------------------------------------------- /packages/core/components/Markdown/src/typing.ts: -------------------------------------------------------------------------------- 1 | import Vditor from 'vditor'; 2 | 3 | export interface MarkDownActionType { 4 | getVditor: () => Vditor; 5 | } 6 | -------------------------------------------------------------------------------- /packages/core/components/Menu/index.ts: -------------------------------------------------------------------------------- 1 | import BasicMenu from './src/BasicMenu.vue'; 2 | 3 | export { BasicMenu }; 4 | -------------------------------------------------------------------------------- /packages/core/components/Menu/src/components/BasicMenuItem.vue: -------------------------------------------------------------------------------- 1 | 6 | 25 | -------------------------------------------------------------------------------- /packages/core/components/Menu/src/components/MenuItemContent.vue: -------------------------------------------------------------------------------- 1 | 7 | 37 | -------------------------------------------------------------------------------- /packages/core/components/Menu/src/types.ts: -------------------------------------------------------------------------------- 1 | // import { ComputedRef } from 'vue'; 2 | // import { ThemeEnum } from '@jeesite/core/enums/appEnum'; 3 | // import { MenuModeEnum } from '@jeesite/core/enums/menuEnum'; 4 | export interface MenuState { 5 | // 默认选中的列表 6 | defaultSelectedKeys: string[]; 7 | 8 | // 模式 9 | // mode: MenuModeEnum; 10 | 11 | // // 主题 12 | // theme: ComputedRef | ThemeEnum; 13 | 14 | // 缩进 15 | inlineIndent?: number; 16 | 17 | // 展开数组 18 | openKeys: string[]; 19 | 20 | // 当前选中的菜单项 key 数组 21 | selectedKeys: string[]; 22 | 23 | // 收缩状态下展开的数组 24 | collapsedOpenKeys: string[]; 25 | } 26 | -------------------------------------------------------------------------------- /packages/core/components/Modal/index.ts: -------------------------------------------------------------------------------- 1 | import { withInstall } from '@jeesite/core/utils'; 2 | import basicModal from './src/BasicModal.vue'; 3 | 4 | export const BasicModal = withInstall(basicModal); 5 | export type BasicModalInstance = InstanceType; 6 | 7 | export * from './src/typing'; 8 | export { useModalContext } from './src/hooks/useModalContext'; 9 | export { useModal, useModalInner } from './src/hooks/useModal'; 10 | -------------------------------------------------------------------------------- /packages/core/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 '@jeesite/core/hooks/core/useAttrs'; 6 | import { extendSlots } from '@jeesite/core/utils/helper/tsxHelper'; 7 | 8 | export default defineComponent({ 9 | name: 'Modal', 10 | inheritAttrs: false, 11 | props: basicProps, 12 | setup(props, { slots }) { 13 | const { open, draggable, destroyOnClose } = toRefs(props); 14 | const attrs = useAttrs(); 15 | useModalDragMove({ 16 | open, 17 | destroyOnClose, 18 | draggable, 19 | }); 20 | 21 | return () => { 22 | const propsData = { class: 'jeesite-basic-modal', ...unref(attrs), ...props } as Recordable; 23 | return {extendSlots(slots)}; 24 | }; 25 | }, 26 | }); 27 | -------------------------------------------------------------------------------- /packages/core/components/Modal/src/components/ModalHeader.vue: -------------------------------------------------------------------------------- 1 | 7 | 23 | -------------------------------------------------------------------------------- /packages/core/components/Modal/src/hooks/useModalContext.ts: -------------------------------------------------------------------------------- 1 | import { InjectionKey } from 'vue'; 2 | import { createContext, useContext } from '@jeesite/core/hooks/core/useContext'; 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 | -------------------------------------------------------------------------------- /packages/core/components/Page/index.ts: -------------------------------------------------------------------------------- 1 | import { withInstall } from '@jeesite/core/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 | -------------------------------------------------------------------------------- /packages/core/components/Popover/index.ts: -------------------------------------------------------------------------------- 1 | import { withInstall } from '@jeesite/core/utils'; 2 | import popover from './src/Popover.vue'; 3 | 4 | export * from './src/typing'; 5 | export const Popover = withInstall(popover); 6 | -------------------------------------------------------------------------------- /packages/core/components/Popover/src/typing.ts: -------------------------------------------------------------------------------- 1 | export interface DropMenu { 2 | onClick?: Fn; 3 | to?: string; 4 | icon?: string; 5 | event: string | number; 6 | text: string; 7 | disabled?: boolean; 8 | divider?: boolean; 9 | } 10 | -------------------------------------------------------------------------------- /packages/core/components/Preview/index.ts: -------------------------------------------------------------------------------- 1 | export { default as ImagePreview } from './src/Preview.vue'; 2 | export { createImgPreview } from './src/functional'; 3 | -------------------------------------------------------------------------------- /packages/core/components/Preview/src/functional.ts: -------------------------------------------------------------------------------- 1 | import type { Options, Props } from './typing'; 2 | import ImgPreview from './Functional.vue'; 3 | import { isClient } from '@jeesite/core/utils/is'; 4 | import { createVNode, render } from 'vue'; 5 | 6 | let instance: ReturnType | null = null; 7 | export function createImgPreview(options: Options) { 8 | if (!isClient) return; 9 | const propsData: Partial = {}; 10 | const container = document.createElement('div'); 11 | Object.assign(propsData, { show: true, index: 0, scaleStep: 100 }, options); 12 | 13 | instance = createVNode(ImgPreview, propsData); 14 | render(instance, container); 15 | document.body.appendChild(container); 16 | return instance.component?.exposed; 17 | } 18 | -------------------------------------------------------------------------------- /packages/core/components/Qrcode/index.ts: -------------------------------------------------------------------------------- 1 | import { withInstall } from '@jeesite/core/utils'; 2 | import qrCode from './src/Qrcode.vue'; 3 | 4 | export const QrCode = withInstall(qrCode); 5 | export * from './src/typing'; 6 | -------------------------------------------------------------------------------- /packages/core/components/Qrcode/src/drawCanvas.ts: -------------------------------------------------------------------------------- 1 | import { toCanvas } from 'qrcode'; 2 | import type { QRCodeRenderersOptions } from 'qrcode'; 3 | import { RenderQrCodeParams, ContentType } from './typing'; 4 | import { cloneDeep } from 'lodash-es'; 5 | 6 | export const renderQrCode = ({ canvas, content, width = 0, options: params = {} }: RenderQrCodeParams) => { 7 | const options = cloneDeep(params); 8 | // 容错率,默认对内容少的二维码采用高容错率,内容多的二维码采用低容错率 9 | options.errorCorrectionLevel = options.errorCorrectionLevel || getErrorCorrectionLevel(content); 10 | 11 | return getOriginWidth(content, options).then((_width: number) => { 12 | options.scale = width === 0 ? undefined : (width / _width) * 4; 13 | return toCanvas(canvas, content, options); 14 | }); 15 | }; 16 | 17 | // 得到原QrCode的大小,以便缩放得到正确的QrCode大小 18 | function getOriginWidth(content: ContentType, options: QRCodeRenderersOptions) { 19 | const _canvas = document.createElement('canvas'); 20 | return toCanvas(_canvas, content, options).then(() => _canvas.width); 21 | } 22 | 23 | // 对于内容少的QrCode,增大容错率 24 | function getErrorCorrectionLevel(content: ContentType) { 25 | if (content.length > 36) { 26 | return 'M'; 27 | } else if (content.length > 16) { 28 | return 'Q'; 29 | } else { 30 | return 'H'; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /packages/core/components/Qrcode/src/qrcodePlus.ts: -------------------------------------------------------------------------------- 1 | // 参考 qr-code-with-logo 进行ts版本修改 2 | import { toCanvas } from './toCanvas'; 3 | export * from './typing'; 4 | export { toCanvas }; 5 | -------------------------------------------------------------------------------- /packages/core/components/Qrcode/src/toCanvas.ts: -------------------------------------------------------------------------------- 1 | import { renderQrCode } from './drawCanvas'; 2 | import { drawLogo } from './drawLogo'; 3 | import { RenderQrCodeParams } from './typing'; 4 | export const toCanvas = (options: RenderQrCodeParams) => { 5 | return renderQrCode(options) 6 | .then(() => { 7 | return options; 8 | }) 9 | .then(drawLogo) as Promise; 10 | }; 11 | -------------------------------------------------------------------------------- /packages/core/components/Qrcode/src/typing.ts: -------------------------------------------------------------------------------- 1 | import type { QRCodeSegment, QRCodeRenderersOptions } from 'qrcode'; 2 | 3 | export type ContentType = string | QRCodeSegment[]; 4 | 5 | export type { QRCodeRenderersOptions }; 6 | 7 | export type LogoType = { 8 | src: string; 9 | logoSize: number; 10 | borderColor: string; 11 | bgColor: string; 12 | borderSize: number; 13 | crossOrigin: string; 14 | borderRadius: number; 15 | logoRadius: number; 16 | }; 17 | 18 | export interface RenderQrCodeParams { 19 | canvas: any; 20 | content: ContentType; 21 | width?: number; 22 | options?: QRCodeRenderersOptions; 23 | logo?: LogoType | string; 24 | image?: HTMLImageElement; 25 | downloadName?: string; 26 | download?: boolean | Fn; 27 | } 28 | 29 | export type ToCanvasFn = (options: RenderQrCodeParams) => Promise; 30 | 31 | export interface QrCodeActionType { 32 | download: (fileName?: string) => void; 33 | } 34 | 35 | export interface QrcodeDoneEventParams { 36 | url: string; 37 | ctx?: CanvasRenderingContext2D | null; 38 | } 39 | -------------------------------------------------------------------------------- /packages/core/components/Resizer/index.ts: -------------------------------------------------------------------------------- 1 | import { withInstall } from '@jeesite/core/utils'; 2 | import resizer from './Resizer.vue'; 3 | 4 | export const Resizer = withInstall(resizer); 5 | -------------------------------------------------------------------------------- /packages/core/components/Scrollbar/index.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * copy from element-ui 3 | */ 4 | import Scrollbar from './src/Scrollbar.vue'; 5 | 6 | export { Scrollbar }; 7 | export type { ScrollbarType } from './src/types'; 8 | -------------------------------------------------------------------------------- /packages/core/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 | 12 | export interface BarMap { 13 | vertical: BarMapItem; 14 | horizontal: BarMapItem; 15 | } 16 | 17 | export interface ScrollbarType { 18 | wrap: ElRef; 19 | } 20 | 21 | export type StyleValue = string | CSSProperties | Array; 22 | 23 | export type Merge = { 24 | [K in keyof O | keyof T]: K extends keyof T ? T[K] : K extends keyof O ? O[K] : never; 25 | }; 26 | 27 | /** 28 | * T = [ 29 | * { name: string; age: number; }, 30 | * { sex: 'male' | 'female'; age: string } 31 | * ] 32 | * => 33 | * MergeAll = { 34 | * name: string; 35 | * sex: 'male' | 'female'; 36 | * age: string 37 | * } 38 | */ 39 | export type MergeAll = T extends [ 40 | infer F extends object, 41 | ...infer Rest extends object[], 42 | ] 43 | ? MergeAll> 44 | : R; 45 | -------------------------------------------------------------------------------- /packages/core/components/SimpleMenu/index.ts: -------------------------------------------------------------------------------- 1 | export { default as SimpleMenu } from './src/SimpleMenu.vue'; 2 | export { default as SimpleMenuTag } from './src/SimpleMenuTag.vue'; 3 | -------------------------------------------------------------------------------- /packages/core/components/SimpleMenu/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?: Fn; 23 | level: number; 24 | props: Props; 25 | } 26 | -------------------------------------------------------------------------------- /packages/core/components/SimpleMenu/src/components/useSimpleMenuContext.ts: -------------------------------------------------------------------------------- 1 | import type { InjectionKey, Ref } from 'vue'; 2 | import type { Emitter } from '@jeesite/core/utils/mitt'; 3 | import { createContext, useContext } from '@jeesite/core/hooks/core/useContext'; 4 | 5 | export interface SimpleRootMenuContextProps { 6 | rootMenuEmitter: Emitter; 7 | activeName: Ref; 8 | } 9 | 10 | const key: InjectionKey = Symbol(); 11 | 12 | export function createSimpleRootMenuContext(context: SimpleRootMenuContextProps) { 13 | return createContext(context, key, { readonly: false, native: true }); 14 | } 15 | 16 | export function useSimpleRootMenuContext() { 17 | return useContext(key); 18 | } 19 | -------------------------------------------------------------------------------- /packages/core/components/SimpleMenu/src/types.ts: -------------------------------------------------------------------------------- 1 | export interface MenuState { 2 | activeName: string; 3 | openNames: string[]; 4 | activeSubMenuNames: string[]; 5 | } 6 | -------------------------------------------------------------------------------- /packages/core/components/StrengthMeter/index.ts: -------------------------------------------------------------------------------- 1 | import { withInstall } from '@jeesite/core/utils'; 2 | import strengthMeter from './src/StrengthMeter.vue'; 3 | 4 | export const StrengthMeter = withInstall(strengthMeter); 5 | -------------------------------------------------------------------------------- /packages/core/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 '@jeesite/core/components/Form/src/types/form'; 11 | export type { EditRecordRow } from './src/components/editable'; 12 | -------------------------------------------------------------------------------- /packages/core/components/Table/src/components/EditTableHeaderIcon.vue: -------------------------------------------------------------------------------- 1 | 8 | 17 | -------------------------------------------------------------------------------- /packages/core/components/Table/src/components/editable/helper.ts: -------------------------------------------------------------------------------- 1 | import { ComponentType } from '../../types/componentType'; 2 | import { useI18n } from '@jeesite/core/hooks/web/useI18n'; 3 | 4 | const { t } = useI18n(); 5 | 6 | /** 7 | * @description: 生成placeholder 8 | */ 9 | export function createPlaceholderMessage(component: ComponentType) { 10 | if (component.includes('Input') || component.includes('AutoComplete')) { 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 | -------------------------------------------------------------------------------- /packages/core/components/Table/src/components/settings/FullScreenSetting.vue: -------------------------------------------------------------------------------- 1 | 10 | 39 | -------------------------------------------------------------------------------- /packages/core/components/Table/src/components/settings/RedoSetting.vue: -------------------------------------------------------------------------------- 1 | 9 | 34 | -------------------------------------------------------------------------------- /packages/core/components/Table/src/const.ts: -------------------------------------------------------------------------------- 1 | import componentSetting from '@jeesite/core/settings/componentSetting'; 2 | 3 | const { table } = componentSetting; 4 | 5 | const { pageSizeOptions, defaultPageSize, fetchSetting, defaultSize, defaultSortFn, defaultFilterFn } = table; 6 | 7 | export const ROW_KEY = 'key'; 8 | 9 | // Optional display number per page; 10 | export const PAGE_SIZE_OPTIONS = pageSizeOptions; 11 | 12 | // Number of items displayed per page 13 | export const PAGE_SIZE = defaultPageSize; 14 | 15 | // Common interface field settings 16 | export const FETCH_SETTING = fetchSetting; 17 | 18 | // Default Size 19 | export const DEFAULT_SIZE = defaultSize; 20 | 21 | // Configure general sort function 22 | export const DEFAULT_SORT_FN = defaultSortFn; 23 | 24 | export const DEFAULT_FILTER_FN = defaultFilterFn; 25 | 26 | // Default layout of table cells 27 | export const DEFAULT_ALIGN = 'center'; 28 | 29 | export const INDEX_COLUMN_FLAG = 'INDEX'; 30 | 31 | export const DRAG_COLUMN_FLAG = 'DRAG'; 32 | 33 | export const ACTION_COLUMN_FLAG = 'ACTION'; 34 | -------------------------------------------------------------------------------- /packages/core/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 | -------------------------------------------------------------------------------- /packages/core/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 | export type TableInstance = Omit & { 13 | getBindValues: ComputedRef; 14 | }; 15 | 16 | export function createTableContext(instance: Instance) { 17 | provide(key, instance); 18 | } 19 | 20 | export function useTableContext(): TableInstance { 21 | return inject(key) as TableInstance; 22 | } 23 | -------------------------------------------------------------------------------- /packages/core/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 '@jeesite/core/utils/is'; 5 | 6 | export function useTableStyle(propsRef: ComputedRef, prefixCls: string) { 7 | function getRowClassName(record: TableCustomRecord, index: number) { 8 | const { striped, rowClassName } = unref(propsRef); 9 | const classNames: string[] = []; 10 | if (striped) { 11 | classNames.push((index || 0) % 2 === 1 ? `${prefixCls}-row__striped` : ''); 12 | } 13 | if (rowClassName && isFunction(rowClassName)) { 14 | classNames.push(rowClassName(record, index)); 15 | } 16 | return classNames.filter((cls) => !!cls).join(' '); 17 | } 18 | 19 | return { getRowClassName }; 20 | } 21 | -------------------------------------------------------------------------------- /packages/core/components/Table/src/types/componentType.ts: -------------------------------------------------------------------------------- 1 | import { CheckboxGroup, RadioButtonGroup, RadioGroup } from '@jeesite/core/components/Form'; 2 | import { BasicUpload } from '@jeesite/core/components/Upload'; 3 | import { componentMap } from '@jeesite/core/components/Table/src/componentMap'; 4 | 5 | export type ComponentType = 6 | | 'Input' 7 | | 'InputTextArea' 8 | | 'InputNumber' 9 | | 'Select' 10 | | 'AutoComplete' 11 | | 'TreeSelect' 12 | | 'ListSelect' 13 | | 'RadioButtonGroup' 14 | | 'RadioGroup' 15 | | 'CheckboxGroup' 16 | | 'Upload' 17 | | 'Checkbox' 18 | | 'Switch' 19 | | 'DatePicker' 20 | | 'TimePicker'; 21 | -------------------------------------------------------------------------------- /packages/core/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 '@jeesite/core/enums/roleEnum'; 4 | 5 | export interface ActionItem extends ButtonProps { 6 | onClick?: Fn; 7 | label?: string; 8 | color?: 'success' | 'error' | 'warning'; 9 | icon?: string; 10 | popConfirm?: PopConfirm; 11 | disabled?: boolean; 12 | divider?: boolean; 13 | // 权限编码控制是否显示 14 | auth?: RoleEnum | RoleEnum[] | string | string[]; 15 | // 业务控制是否显示 16 | ifShow?: boolean | ((action: ActionItem) => boolean); 17 | tooltip?: string | TooltipProps; 18 | } 19 | 20 | export interface PopConfirm { 21 | title: string; 22 | okText?: string; 23 | cancelText?: string; 24 | confirm: Fn; 25 | cancel?: Fn; 26 | icon?: string; 27 | placement?: 28 | | 'top' 29 | | 'left' 30 | | 'right' 31 | | 'bottom' 32 | | 'topLeft' 33 | | 'topRight' 34 | | 'leftTop' 35 | | 'leftBottom' 36 | | 'rightTop' 37 | | 'rightBottom' 38 | | 'bottomLeft' 39 | | 'bottomRight'; 40 | } 41 | -------------------------------------------------------------------------------- /packages/core/components/Time/index.ts: -------------------------------------------------------------------------------- 1 | import { withInstall } from '@jeesite/core/utils'; 2 | import time from './src/Time.vue'; 3 | 4 | export const Time = withInstall(time); 5 | -------------------------------------------------------------------------------- /packages/core/components/Tree/index.ts: -------------------------------------------------------------------------------- 1 | import BasicTree from './src/Tree.vue'; 2 | 3 | export { BasicTree }; 4 | export type { ContextMenuItem } from '@jeesite/core/hooks/web/useContextMenu'; 5 | export * from './src/typing'; 6 | -------------------------------------------------------------------------------- /packages/core/components/Tree/src/TreeIcon.ts: -------------------------------------------------------------------------------- 1 | import type { VNode } from 'vue'; 2 | 3 | import { h } from 'vue'; 4 | import { isString } from '@jeesite/core/utils/is'; 5 | import { Icon } from '@jeesite/core/components/Icon'; 6 | 7 | export const TreeIcon = ({ icon }: { icon: VNode | string | undefined }) => { 8 | if (!icon) return null; 9 | if (isString(icon)) { 10 | return h(Icon, { icon, class: 'mr-1' }); 11 | } 12 | return h(Icon); 13 | }; 14 | -------------------------------------------------------------------------------- /packages/core/components/Upload/index.ts: -------------------------------------------------------------------------------- 1 | import { withInstall } from '@jeesite/core/utils'; 2 | import basicUpload from './src/BasicUpload.vue'; 3 | 4 | export const BasicUpload = withInstall(basicUpload); 5 | -------------------------------------------------------------------------------- /packages/core/components/Upload/src/ThumbUrl.vue: -------------------------------------------------------------------------------- 1 | 13 | 23 | 34 | -------------------------------------------------------------------------------- /packages/core/components/ValidCode/index.ts: -------------------------------------------------------------------------------- 1 | import { withInstall } from '@jeesite/core/utils'; 2 | import validCode from './src/ValidCode.vue'; 3 | 4 | export const ValidCode = withInstall(validCode); 5 | export type ValidCodeInstance = InstanceType; 6 | -------------------------------------------------------------------------------- /packages/core/components/Verify/index.ts: -------------------------------------------------------------------------------- 1 | import { withInstall } from '@jeesite/core/utils'; 2 | import basicDragVerify from './src/DragVerify.vue'; 3 | import rotateDragVerify from './src/ImgRotate.vue'; 4 | 5 | export const BasicDragVerify = withInstall(basicDragVerify); 6 | export const RotateDragVerify = withInstall(rotateDragVerify); 7 | export * from './src/typing'; 8 | -------------------------------------------------------------------------------- /packages/core/components/Verify/src/typing.ts: -------------------------------------------------------------------------------- 1 | export interface DragVerifyActionType { 2 | resume: () => void; 3 | } 4 | 5 | export interface PassingData { 6 | isPassing: boolean; 7 | time: number; 8 | } 9 | 10 | export interface MoveData { 11 | event: MouseEvent | TouchEvent; 12 | moveDistance: number; 13 | moveX: number; 14 | } 15 | -------------------------------------------------------------------------------- /packages/core/components/VirtualScroll/index.ts: -------------------------------------------------------------------------------- 1 | import { withInstall } from '@jeesite/core/utils'; 2 | import virtualScroll from './src/VirtualScroll.vue'; 3 | 4 | export const VScroll = withInstall(virtualScroll); 5 | -------------------------------------------------------------------------------- /packages/core/components/WangEditor/index.ts: -------------------------------------------------------------------------------- 1 | import { withInstall } from '@jeesite/core/utils'; 2 | import wangEditor from './src/WangEditor.vue'; 3 | 4 | export const WangEditor = withInstall(wangEditor); 5 | -------------------------------------------------------------------------------- /packages/core/components/index.ts: -------------------------------------------------------------------------------- 1 | // export * from './Button'; 2 | // export * from './CollapseForm'; 3 | // export * from './Dict'; 4 | // export * from './Drawer'; 5 | // export * from './Dropdown'; 6 | // export * from './Form'; 7 | // export * from './Icon'; 8 | // export * from './ListSelect'; 9 | // export * from './Table'; 10 | // export * from './Tree'; 11 | // export * from './Upload'; 12 | // export * from './WangEditor'; 13 | -------------------------------------------------------------------------------- /packages/core/components/registerGlobComp.ts: -------------------------------------------------------------------------------- 1 | import type { App } from 'vue'; 2 | import { Button } from './Button'; 3 | import { Input } from 'ant-design-vue'; 4 | 5 | export function registerGlobComp(app: App) { 6 | app.use(Input).use(Button); 7 | } 8 | -------------------------------------------------------------------------------- /packages/core/design/ant/input.less: -------------------------------------------------------------------------------- 1 | @import (reference) '../var/color.less'; 2 | 3 | // input 4 | .ant-input { 5 | &-number { 6 | min-width: 110px; 7 | } 8 | } 9 | 10 | .ant-input-affix-wrapper .ant-input-suffix { 11 | right: 9px; 12 | } 13 | 14 | .ant-input-clear-icon { 15 | margin-right: 5px; 16 | } 17 | 18 | .ant-input-affix-wrapper-textarea-with-clear-btn { 19 | padding: 0 !important; 20 | 21 | textarea.ant-input { 22 | padding: 4px; 23 | } 24 | } 25 | 26 | .ant-input-group { 27 | .ant-btn-icon-only.ant-btn-sm > * { 28 | font-size: 16px; 29 | } 30 | 31 | svg { 32 | vertical-align: initial; 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /packages/core/design/public.less: -------------------------------------------------------------------------------- 1 | #app { 2 | width: 100%; 3 | height: 100%; 4 | } 5 | 6 | ul { 7 | list-style-type: none; 8 | padding-left: 0; 9 | } 10 | 11 | // ================================= 12 | // ==============scrollbar========== 13 | // ================================= 14 | 15 | ::-webkit-scrollbar { 16 | width: 8px; 17 | height: 8px; 18 | } 19 | 20 | ::-webkit-scrollbar-track { 21 | background-color: rgb(0 0 0 / 5%); 22 | border-radius: 8px; 23 | } 24 | 25 | ::-webkit-scrollbar-thumb { 26 | background-color: rgb(144 147 153 / 20%); 27 | border-radius: 8px; 28 | } 29 | 30 | ::-webkit-scrollbar-thumb:hover { 31 | background-color: @border-color-dark; 32 | } 33 | 34 | ::-webkit-scrollbar-corner { 35 | background: transparent; 36 | } 37 | 38 | // ================================= 39 | // ==============nprogress========== 40 | // ================================= 41 | #nprogress { 42 | pointer-events: none; 43 | 44 | .bar { 45 | position: fixed; 46 | top: 0; 47 | left: 0; 48 | z-index: 99999; 49 | width: 100%; 50 | height: 2px; 51 | background-color: @primary-color; 52 | opacity: 0.75; 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /packages/core/design/transition/base.less: -------------------------------------------------------------------------------- 1 | .transition-default() { 2 | &-enter-active, 3 | &-leave-active { 4 | transition: 0.1s cubic-bezier(0.25, 0.8, 0.5, 1) !important; 5 | } 6 | 7 | &-move { 8 | transition: transform 0.1s; 9 | } 10 | } 11 | 12 | .expand-transition { 13 | .transition-default(); 14 | } 15 | 16 | .expand-x-transition { 17 | .transition-default(); 18 | } 19 | -------------------------------------------------------------------------------- /packages/core/design/transition/index.less: -------------------------------------------------------------------------------- 1 | @import './base.less'; 2 | @import './fade.less'; 3 | @import './scale.less'; 4 | @import './slide.less'; 5 | @import './scroll.less'; 6 | @import './zoom.less'; 7 | 8 | .collapse-transition { 9 | transition: 10 | 0.1s height ease-in-out, 11 | 0.1s padding-top ease-in-out, 12 | 0.1s padding-bottom ease-in-out; 13 | } 14 | -------------------------------------------------------------------------------- /packages/core/design/transition/scale.less: -------------------------------------------------------------------------------- 1 | .scale-transition { 2 | .transition-default(); 3 | 4 | &-enter-from, 5 | &-leave, 6 | &-leave-to { 7 | opacity: 0; 8 | transform: scale(0); 9 | } 10 | } 11 | 12 | .scale-rotate-transition { 13 | .transition-default(); 14 | 15 | &-enter-from, 16 | &-leave, 17 | &-leave-to { 18 | opacity: 0; 19 | transform: scale(0) rotate(-45deg); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /packages/core/design/transition/scroll.less: -------------------------------------------------------------------------------- 1 | .scroll-y-transition { 2 | .transition-default(); 3 | 4 | &-enter-from, 5 | &-leave-to { 6 | opacity: 0; 7 | } 8 | 9 | &-enter-from { 10 | transform: translateY(-15px); 11 | } 12 | 13 | &-leave-to { 14 | transform: translateY(15px); 15 | } 16 | } 17 | 18 | .scroll-y-reverse-transition { 19 | .transition-default(); 20 | 21 | &-enter-from, 22 | &-leave-to { 23 | opacity: 0; 24 | } 25 | 26 | &-enter-from { 27 | transform: translateY(15px); 28 | } 29 | 30 | &-leave-to { 31 | transform: translateY(-15px); 32 | } 33 | } 34 | 35 | .scroll-x-transition { 36 | .transition-default(); 37 | 38 | &-enter-from, 39 | &-leave-to { 40 | opacity: 0; 41 | } 42 | 43 | &-enter-from { 44 | transform: translateX(-15px); 45 | } 46 | 47 | &-leave-to { 48 | transform: translateX(15px); 49 | } 50 | } 51 | 52 | .scroll-x-reverse-transition { 53 | .transition-default(); 54 | 55 | &-enter-from, 56 | &-leave-to { 57 | opacity: 0; 58 | } 59 | 60 | &-enter-from { 61 | transform: translateX(15px); 62 | } 63 | 64 | &-leave-to { 65 | transform: translateX(-15px); 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /packages/core/design/transition/slide.less: -------------------------------------------------------------------------------- 1 | .slide-y-transition { 2 | .transition-default(); 3 | 4 | &-enter-from, 5 | &-leave-to { 6 | opacity: 0; 7 | transform: translateY(-15px); 8 | } 9 | } 10 | 11 | .slide-y-reverse-transition { 12 | .transition-default(); 13 | 14 | &-enter-from, 15 | &-leave-to { 16 | opacity: 0; 17 | transform: translateY(15px); 18 | } 19 | } 20 | 21 | .slide-x-transition { 22 | .transition-default(); 23 | 24 | &-enter-from, 25 | &-leave-to { 26 | opacity: 0; 27 | transform: translateX(-15px); 28 | } 29 | } 30 | 31 | .slide-x-reverse-transition { 32 | .transition-default(); 33 | 34 | &-enter-from, 35 | &-leave-to { 36 | opacity: 0; 37 | transform: translateX(15px); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /packages/core/design/transition/zoom.less: -------------------------------------------------------------------------------- 1 | // zoom-out 2 | .zoom-out-enter-active, 3 | .zoom-out-leave-active { 4 | transition: 5 | opacity 0.1 ease-in-out, 6 | transform 0.15s ease-out; 7 | } 8 | 9 | .zoom-out-enter-from, 10 | .zoom-out-leave-to { 11 | opacity: 0; 12 | transform: scale(0); 13 | } 14 | 15 | // zoom-fade 16 | .zoom-fade-enter-active, 17 | .zoom-fade-leave-active { 18 | transition: 19 | transform 0.1s, 20 | opacity 0.3s ease-out; 21 | } 22 | 23 | .zoom-fade-enter-from { 24 | opacity: 0; 25 | transform: scale(0.92); 26 | } 27 | 28 | .zoom-fade-leave-to { 29 | opacity: 0; 30 | transform: scale(1.06); 31 | } 32 | -------------------------------------------------------------------------------- /packages/core/design/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: 1024px; 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 | -------------------------------------------------------------------------------- /packages/core/design/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 | -------------------------------------------------------------------------------- /packages/core/design/var/index.less: -------------------------------------------------------------------------------- 1 | @import (reference) 'color.less'; 2 | @import 'easing'; 3 | @import 'breakpoint'; 4 | 5 | // headers、HEADER_HEIGHT 6 | @header-height: 48px; 7 | 8 | // logo width 9 | @logo-width: 32px; 10 | 11 | @side-drag-z-index: 200; 12 | 13 | @page-loading-z-index: 10000; 14 | 15 | @lock-page-z-index: 3000; 16 | 17 | @layout-header-fixed-z-index: 500; 18 | 19 | @multiple-tab-fixed-z-index: 505; 20 | 21 | @layout-sider-fixed-z-index: 510; 22 | 23 | @layout-mix-sider-fixed-z-index: 550; 24 | 25 | @preview-comp-z-index: 1000; 26 | 27 | @page-footer-z-index: 99; 28 | -------------------------------------------------------------------------------- /packages/core/directives/clickOutsideSimple.ts: -------------------------------------------------------------------------------- 1 | import type { DirectiveBinding, ObjectDirective } from 'vue'; 2 | 3 | type DocumentHandler = (mouseup: T, mousedown: T) => void; 4 | 5 | type FlushList = Map< 6 | HTMLElement, 7 | { 8 | documentHandler: DocumentHandler; 9 | bindingFn: (...args: unknown[]) => unknown; 10 | } 11 | >; 12 | 13 | const nodeList: FlushList = new Map(); 14 | 15 | function createDocumentHandler(_el: HTMLElement, binding: DirectiveBinding): DocumentHandler { 16 | return function () { 17 | binding.value(); 18 | }; 19 | } 20 | 21 | // 创建新组件,调用之前创建的组件事件 22 | const ClickOutside: ObjectDirective = { 23 | beforeMount(el, binding) { 24 | for (const { documentHandler } of nodeList.values()) { 25 | documentHandler(el, binding); 26 | } 27 | nodeList.set(el, { 28 | documentHandler: createDocumentHandler(el, binding), 29 | bindingFn: binding.value, 30 | }); 31 | }, 32 | unmounted(el) { 33 | nodeList.delete(el); 34 | }, 35 | }; 36 | 37 | export default ClickOutside; 38 | -------------------------------------------------------------------------------- /packages/core/directives/index.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Configure and register global directives 3 | */ 4 | import type { App } from 'vue'; 5 | import { setupPermissionDirective } from './permission'; 6 | import { setupLoadingDirective } from './loading'; 7 | 8 | export function setupGlobDirectives(app: App) { 9 | setupPermissionDirective(app); 10 | setupLoadingDirective(app); 11 | } 12 | -------------------------------------------------------------------------------- /packages/core/directives/permission.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 { App, Directive, DirectiveBinding } from 'vue'; 7 | 8 | import { usePermission } from '@jeesite/core/hooks/web/usePermission'; 9 | 10 | function isAuth(el: Element, binding: any) { 11 | const { hasPermission } = usePermission(); 12 | 13 | const value = binding.value; 14 | if (!value) return; 15 | if (!hasPermission(value)) { 16 | el.parentNode?.removeChild(el); 17 | } 18 | } 19 | 20 | const mounted = (el: Element, binding: DirectiveBinding) => { 21 | isAuth(el, binding); 22 | }; 23 | 24 | const authDirective: Directive = { 25 | mounted, 26 | }; 27 | 28 | export function setupPermissionDirective(app: App) { 29 | app.directive('auth', authDirective); 30 | } 31 | 32 | export default authDirective; 33 | -------------------------------------------------------------------------------- /packages/core/directives/repeatClick.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Prevent repeated clicks 3 | * @Example v-repeat-click="()=>{}" 4 | */ 5 | import { on, once } from '@jeesite/core/utils/domUtils'; 6 | import type { Directive, DirectiveBinding } from 'vue'; 7 | 8 | const repeatDirective: Directive = { 9 | beforeMount(el: Element, binding: DirectiveBinding) { 10 | let interval: Nullable = null; 11 | let startTime = 0; 12 | const handler = (): void => binding?.value(); 13 | const clear = (): void => { 14 | if (Date.now() - startTime < 100) { 15 | handler(); 16 | } 17 | interval && clearInterval(interval); 18 | interval = null; 19 | }; 20 | 21 | on(el, 'mousedown', (e: Event): void => { 22 | if ((e as any).button !== 0) return; 23 | startTime = Date.now(); 24 | once(document as any, 'mouseup', clear); 25 | interval && clearInterval(interval); 26 | interval = setInterval(handler, 100); 27 | }); 28 | }, 29 | }; 30 | 31 | export default repeatDirective; 32 | -------------------------------------------------------------------------------- /packages/core/directives/ripple/index.less: -------------------------------------------------------------------------------- 1 | .ripple-container { 2 | position: absolute; 3 | top: 0; 4 | left: 0; 5 | width: 0; 6 | height: 0; 7 | overflow: hidden; 8 | pointer-events: none; 9 | } 10 | 11 | .ripple-effect { 12 | position: relative; 13 | z-index: 9999; 14 | width: 1px; 15 | height: 1px; 16 | margin-top: 0; 17 | margin-left: 0; 18 | pointer-events: none; 19 | border-radius: 50%; 20 | transition: all 0.6s cubic-bezier(0.4, 0, 0.2, 1); 21 | } 22 | -------------------------------------------------------------------------------- /packages/core/enums/appEnum.ts: -------------------------------------------------------------------------------- 1 | export const SIDE_BAR_MINI_WIDTH = 48; 2 | export const SIDE_BAR_SHOW_TIT_MINI_WIDTH = 80; 3 | 4 | export enum ContentEnum { 5 | // auto width 6 | FULL = 'full', 7 | // fixed width 8 | FIXED = 'fixed', 9 | } 10 | 11 | // menu theme enum 12 | export enum ThemeEnum { 13 | DARK = 'dark', 14 | LIGHT = 'light', 15 | } 16 | 17 | export enum SettingButtonPositionEnum { 18 | AUTO = 'auto', 19 | HEADER = 'header', 20 | FIXED = 'fixed', 21 | } 22 | 23 | export enum SessionTimeoutProcessingEnum { 24 | ROUTE_JUMP, 25 | PAGE_COVERAGE, 26 | } 27 | 28 | /** 29 | * 权限模式 30 | */ 31 | export enum PermissionModeEnum { 32 | // role 33 | ROLE = 'ROLE', 34 | // black 35 | BACK = 'BACK', 36 | // route mapping 37 | ROUTE_MAPPING = 'ROUTE_MAPPING', 38 | } 39 | 40 | // Route switching animation 41 | export enum RouterTransitionEnum { 42 | ZOOM_FADE = 'zoom-fade', 43 | ZOOM_OUT = 'zoom-out', 44 | FADE_SIDE = 'fade-slide', 45 | FADE = 'fade', 46 | FADE_BOTTOM = 'fade-bottom', 47 | FADE_SCALE = 'fade-scale', 48 | } 49 | -------------------------------------------------------------------------------- /packages/core/enums/breakpointEnum.ts: -------------------------------------------------------------------------------- 1 | export enum sizeEnum { 2 | XS = 'XS', 3 | SM = 'SM', 4 | MD = 'MD', 5 | LG = 'LG', 6 | XL = 'XL', 7 | XXL = 'XXL', 8 | } 9 | 10 | export enum screenEnum { 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(sizeEnum.XS, screenEnum.XS); 22 | screenMap.set(sizeEnum.SM, screenEnum.SM); 23 | screenMap.set(sizeEnum.MD, screenEnum.MD); 24 | screenMap.set(sizeEnum.LG, screenEnum.LG); 25 | screenMap.set(sizeEnum.XL, screenEnum.XL); 26 | screenMap.set(sizeEnum.XXL, screenEnum.XXL); 27 | 28 | export { screenMap }; 29 | -------------------------------------------------------------------------------- /packages/core/enums/cacheEnum.ts: -------------------------------------------------------------------------------- 1 | export const TOKEN_KEY = 'TOKEN__'; 2 | export const SESSION_TIMEOUT_KEY = 'SESSION_TIMEOUT__'; 3 | export const USER_INFO_KEY = 'USER_INFO__'; 4 | export const ROLES_KEY = 'ROLES__'; 5 | export const LOCK_INFO_KEY = 'LOCK_INFO__'; 6 | export const PROJ_CFG_KEY = 'PROJ_CFG__'; 7 | export const MULTIPLE_TABS_KEY = 'MULTIPLE_TABS__'; 8 | 9 | export const LOCALE_KEY = 'LOCALE__'; 10 | export const APP_DARK_MODE_KEY = 'APP_DARK_MODE__'; 11 | export const APP_LOCAL_CACHE_KEY = 'COMMON_LOCAL__'; 12 | export const APP_SESSION_CACHE_KEY = 'COMMON_SESSION__'; 13 | 14 | export enum CacheTypeEnum { 15 | SESSION, 16 | LOCAL, 17 | } 18 | -------------------------------------------------------------------------------- /packages/core/enums/exceptionEnum.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * @description: Exception related enumeration 3 | */ 4 | export enum ExceptionEnum { 5 | // page not access 6 | PAGE_NOT_ACCESS = 403, 7 | 8 | // page not found 9 | PAGE_NOT_FOUND = 404, 10 | 11 | // error 12 | ERROR = 500, 13 | 14 | // net work error 15 | NET_WORK_ERROR = 10000, 16 | 17 | // No data on the page. In fact, it is not an exception page 18 | PAGE_NOT_DATA = 10100, 19 | } 20 | 21 | export enum ErrorTypeEnum { 22 | VUE = 'vue', 23 | SCRIPT = 'script', 24 | RESOURCE = 'resource', 25 | AJAX = 'ajax', 26 | PROMISE = 'promise', 27 | } 28 | -------------------------------------------------------------------------------- /packages/core/enums/httpEnum.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * @description: Request result set 3 | */ 4 | export enum ResultEnum { 5 | SUCCESS = 0, 6 | ERROR = 1, 7 | TIMEOUT = 401, 8 | TYPE = 'success', 9 | } 10 | 11 | /** 12 | * @description: request method 13 | */ 14 | export enum RequestEnum { 15 | GET = 'GET', 16 | POST = 'POST', 17 | PUT = 'PUT', 18 | DELETE = 'DELETE', 19 | } 20 | 21 | /** 22 | * @description: contentTyp 23 | */ 24 | export enum ContentTypeEnum { 25 | // json 26 | JSON = 'application/json;charset=UTF-8', 27 | // form-data qs 28 | FORM_URLENCODED = 'application/x-www-form-urlencoded;charset=UTF-8', 29 | // form-data upload 30 | FORM_DATA = 'multipart/form-data;charset=UTF-8', 31 | } 32 | -------------------------------------------------------------------------------- /packages/core/enums/menuEnum.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/core/enums/pageEnum.ts: -------------------------------------------------------------------------------- 1 | export enum PageEnum { 2 | // basic login path 3 | BASE_LOGIN = '/login', 4 | // basic home path 5 | BASE_HOME = '/desktop', 6 | // error page path 7 | ERROR_PAGE = '/exception', 8 | // error log page path 9 | ERROR_LOG_PAGE = '/errorLog/list', 10 | // basic login path 11 | MOD_PWD_PAGE = '/modPwd', 12 | } 13 | -------------------------------------------------------------------------------- /packages/core/enums/roleEnum.ts: -------------------------------------------------------------------------------- 1 | export enum RoleEnum { 2 | // super admin 3 | SUPER = 'super', 4 | 5 | // tester 6 | TEST = 'test', 7 | } 8 | -------------------------------------------------------------------------------- /packages/core/enums/sizeEnum.ts: -------------------------------------------------------------------------------- 1 | export enum SizeEnum { 2 | DEFAULT = 'default', 3 | SMALL = 'small', 4 | LARGE = 'large', 5 | } 6 | 7 | export enum SizeNumberEnum { 8 | DEFAULT = 48, 9 | SMALL = 16, 10 | LARGE = 64, 11 | } 12 | 13 | export const sizeMap: Map = (() => { 14 | const map = new Map(); 15 | map.set(SizeEnum.DEFAULT, SizeNumberEnum.DEFAULT); 16 | map.set(SizeEnum.SMALL, SizeNumberEnum.SMALL); 17 | map.set(SizeEnum.LARGE, SizeNumberEnum.LARGE); 18 | return map; 19 | })(); 20 | -------------------------------------------------------------------------------- /packages/core/hooks/component/usePageContext.ts: -------------------------------------------------------------------------------- 1 | import type { InjectionKey, ComputedRef, Ref } from 'vue'; 2 | import { createContext, useContext } from '@jeesite/core/hooks/core/useContext'; 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 | -------------------------------------------------------------------------------- /packages/core/hooks/core/onMountedOrActivated.ts: -------------------------------------------------------------------------------- 1 | import { nextTick, onMounted, onActivated } from 'vue'; 2 | 3 | export function onMountedOrActivated(hook: Fn) { 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 | -------------------------------------------------------------------------------- /packages/core/hooks/core/useContext.ts: -------------------------------------------------------------------------------- 1 | import { 2 | InjectionKey, 3 | provide, 4 | inject, 5 | reactive, 6 | readonly as defineReadonly, 7 | // defineComponent, 8 | UnwrapRef, 9 | } from 'vue'; 10 | 11 | export interface CreateContextOptions { 12 | readonly?: boolean; 13 | createProvider?: boolean; 14 | native?: boolean; 15 | } 16 | 17 | type ShallowUnwrap = { 18 | [P in keyof T]: UnwrapRef; 19 | }; 20 | 21 | export function createContext(context: any, key: InjectionKey = Symbol(), options: CreateContextOptions = {}) { 22 | const { readonly = true, createProvider = false, native = false } = options; 23 | 24 | const state = reactive(context); 25 | const provideData = readonly ? defineReadonly(state) : state; 26 | !createProvider && provide(key, native ? context : provideData); 27 | 28 | return { 29 | state, 30 | }; 31 | } 32 | 33 | export function useContext(key: InjectionKey, native?: boolean): T; 34 | export function useContext(key: InjectionKey, defaultValue?: any, native?: boolean): T; 35 | 36 | export function useContext(key: InjectionKey = Symbol(), defaultValue?: any): ShallowUnwrap { 37 | return inject(key, defaultValue || {}); 38 | } 39 | -------------------------------------------------------------------------------- /packages/core/hooks/core/useLockFn.ts: -------------------------------------------------------------------------------- 1 | import { ref, unref } from 'vue'; 2 | 3 | export function useLockFn

(fn: (...args: P) => Promise) { 4 | const lockRef = ref(false); 5 | return async function (...args: P) { 6 | if (unref(lockRef)) return; 7 | lockRef.value = true; 8 | try { 9 | const ret = await fn(...args); 10 | lockRef.value = false; 11 | return ret; 12 | } catch (e) { 13 | lockRef.value = false; 14 | throw e; 15 | } 16 | }; 17 | } 18 | -------------------------------------------------------------------------------- /packages/core/hooks/core/useRefs.ts: -------------------------------------------------------------------------------- 1 | import type { ComponentPublicInstance, Ref } from 'vue'; 2 | import { onBeforeUpdate, shallowRef } from 'vue'; 3 | 4 | function useRefs(): { 5 | refs: Ref; 6 | setRefs: (index: number) => (el: Element | ComponentPublicInstance | null) => void; 7 | } { 8 | const refs = shallowRef([]) as Ref; 9 | 10 | onBeforeUpdate(() => { 11 | refs.value = []; 12 | }); 13 | 14 | const setRefs = (index: number) => (el: Element | ComponentPublicInstance | null) => { 15 | refs.value[index] = el as T; 16 | }; 17 | 18 | return { 19 | refs, 20 | setRefs, 21 | }; 22 | } 23 | 24 | export { useRefs }; 25 | -------------------------------------------------------------------------------- /packages/core/hooks/core/useTimeout.ts: -------------------------------------------------------------------------------- 1 | import { ref, watch } from 'vue'; 2 | import { tryOnUnmounted } from '@vueuse/core'; 3 | import { isFunction } from '@jeesite/core/utils/is'; 4 | 5 | export function useTimeoutFn(handle: Fn, wait: number, native = false) { 6 | if (!isFunction(handle)) { 7 | throw new Error('handle is not Function!'); 8 | } 9 | 10 | const { readyRef, stop, start } = useTimeoutRef(wait); 11 | if (native) { 12 | handle(); 13 | } else { 14 | watch( 15 | readyRef, 16 | (maturity) => { 17 | maturity && handle(); 18 | }, 19 | { immediate: false }, 20 | ); 21 | } 22 | return { readyRef, stop, start }; 23 | } 24 | 25 | export function useTimeoutRef(wait: number) { 26 | const readyRef = ref(false); 27 | 28 | let timer: TimeoutHandle; 29 | function stop(): void { 30 | readyRef.value = false; 31 | timer && window.clearTimeout(timer); 32 | } 33 | function start(): void { 34 | stop(); 35 | timer = setTimeout(() => { 36 | readyRef.value = true; 37 | }, wait); 38 | } 39 | 40 | start(); 41 | 42 | tryOnUnmounted(stop); 43 | 44 | return { readyRef, stop, start }; 45 | } 46 | -------------------------------------------------------------------------------- /packages/core/hooks/event/useIntersectionObserver.ts: -------------------------------------------------------------------------------- 1 | import { Ref, watchEffect, ref } from 'vue'; 2 | 3 | interface IntersectionObserverProps { 4 | target: Ref; 5 | root?: Ref; 6 | onIntersect: IntersectionObserverCallback; 7 | rootMargin?: string; 8 | threshold?: number; 9 | } 10 | 11 | export function useIntersectionObserver({ 12 | target, 13 | root, 14 | onIntersect, 15 | rootMargin = '0px', 16 | threshold = 0.1, 17 | }: IntersectionObserverProps) { 18 | let cleanup = () => {}; 19 | const observer: Ref> = ref(null); 20 | const stopEffect = watchEffect(() => { 21 | cleanup(); 22 | 23 | observer.value = new IntersectionObserver(onIntersect, { 24 | root: root ? root.value : null, 25 | rootMargin, 26 | threshold, 27 | }); 28 | 29 | const current = target.value; 30 | 31 | current && observer.value.observe(current); 32 | 33 | cleanup = () => { 34 | if (observer.value) { 35 | observer.value.disconnect(); 36 | target.value && observer.value.unobserve(target.value); 37 | } 38 | }; 39 | }); 40 | 41 | return { 42 | observer, 43 | stop: () => { 44 | cleanup(); 45 | stopEffect(); 46 | }, 47 | }; 48 | } 49 | -------------------------------------------------------------------------------- /packages/core/hooks/event/useWindowSizeFn.ts: -------------------------------------------------------------------------------- 1 | import { tryOnMounted, tryOnUnmounted } from '@vueuse/core'; 2 | import { useDebounceFn } from '@vueuse/core'; 3 | 4 | interface WindowSizeOptions { 5 | once?: boolean; 6 | immediate?: boolean; 7 | listenerOptions?: AddEventListenerOptions | boolean; 8 | } 9 | 10 | export function useWindowSizeFn(fn: Fn, wait = 150, options?: WindowSizeOptions) { 11 | let handler = () => { 12 | fn(); 13 | }; 14 | const handleSize = useDebounceFn(handler, wait); 15 | handler = handleSize; 16 | 17 | const start = () => { 18 | if (options && options.immediate) { 19 | handler(); 20 | } 21 | window.addEventListener('resize', handler); 22 | }; 23 | 24 | const stop = () => { 25 | window.removeEventListener('resize', handler); 26 | }; 27 | 28 | tryOnMounted(() => { 29 | start(); 30 | }); 31 | 32 | tryOnUnmounted(() => { 33 | stop(); 34 | }); 35 | return [start, stop]; 36 | } 37 | -------------------------------------------------------------------------------- /packages/core/hooks/setting/useMultipleTabSetting.ts: -------------------------------------------------------------------------------- 1 | import type { MultiTabsSetting } from '@jeesite/types/config'; 2 | 3 | import { computed } from 'vue'; 4 | 5 | import { useAppStore } from '@jeesite/core/store/modules/app'; 6 | 7 | export function useMultipleTabSetting() { 8 | const appStore = useAppStore(); 9 | 10 | const getShowMultipleTab = computed(() => appStore.getMultiTabsSetting.show); 11 | 12 | const getTabsStyle = computed(() => appStore.getMultiTabsSetting.style); 13 | 14 | const getShowQuick = computed(() => appStore.getMultiTabsSetting.showQuick); 15 | 16 | const getShowRedo = computed(() => appStore.getMultiTabsSetting.showRedo); 17 | 18 | const getShowFold = computed(() => appStore.getMultiTabsSetting.showFold); 19 | 20 | function setMultipleTabSetting(multiTabsSetting: Partial) { 21 | appStore.setProjectConfig({ multiTabsSetting }); 22 | } 23 | return { 24 | setMultipleTabSetting, 25 | getShowMultipleTab, 26 | getTabsStyle, 27 | getShowQuick, 28 | getShowRedo, 29 | getShowFold, 30 | }; 31 | } 32 | -------------------------------------------------------------------------------- /packages/core/hooks/setting/useTransitionSetting.ts: -------------------------------------------------------------------------------- 1 | import type { TransitionSetting } from '@jeesite/types/config'; 2 | 3 | import { computed } from 'vue'; 4 | 5 | import { useAppStore } from '@jeesite/core/store/modules/app'; 6 | 7 | export function useTransitionSetting() { 8 | const appStore = useAppStore(); 9 | 10 | const getEnableTransition = computed(() => appStore.getTransitionSetting?.enable); 11 | 12 | const getOpenNProgress = computed(() => appStore.getTransitionSetting?.openNProgress); 13 | 14 | const getOpenPageLoading = computed((): boolean => { 15 | return !!appStore.getTransitionSetting?.openPageLoading; 16 | }); 17 | 18 | const getBasicTransition = computed(() => appStore.getTransitionSetting?.basicTransition); 19 | 20 | function setTransitionSetting(transitionSetting: Partial) { 21 | appStore.setProjectConfig({ transitionSetting }); 22 | } 23 | return { 24 | setTransitionSetting, 25 | 26 | getEnableTransition, 27 | getOpenNProgress, 28 | getOpenPageLoading, 29 | getBasicTransition, 30 | }; 31 | } 32 | -------------------------------------------------------------------------------- /packages/core/hooks/web/useAppInject.ts: -------------------------------------------------------------------------------- 1 | import { useAppProviderContext } from '@jeesite/core/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 | -------------------------------------------------------------------------------- /packages/core/hooks/web/useContextMenu.ts: -------------------------------------------------------------------------------- 1 | import { onUnmounted, getCurrentInstance } from 'vue'; 2 | import { createContextMenu, destroyContextMenu } from '@jeesite/core/components/ContextMenu'; 3 | import type { ContextMenuItem } from '@jeesite/core/components/ContextMenu'; 4 | export type { ContextMenuItem }; 5 | export function useContextMenu(authRemove = true) { 6 | if (getCurrentInstance() && authRemove) { 7 | onUnmounted(() => { 8 | destroyContextMenu(); 9 | }); 10 | } 11 | return [createContextMenu, destroyContextMenu]; 12 | } 13 | -------------------------------------------------------------------------------- /packages/core/hooks/web/useDesign.ts: -------------------------------------------------------------------------------- 1 | import { useAppProviderContext } from '@jeesite/core/components/Application'; 2 | import { theme } from 'ant-design-vue'; 3 | // import { computed } from 'vue'; 4 | // import { lowerFirst } from 'lodash-es'; 5 | 6 | export function useDesign(scope: string) { 7 | const values = useAppProviderContext(); 8 | const token = theme.useToken(); 9 | // const $style = cssModule ? useCssModule() : {}; 10 | 11 | // const style: Record = {}; 12 | // if (cssModule) { 13 | // Object.keys($style).forEach((key) => { 14 | // // const moduleCls = $style[key]; 15 | // const k = key.replace(new RegExp(`^${values.prefixCls}-?`, 'ig'), ''); 16 | // style[lowerFirst(k)] = $style[key]; 17 | // }); 18 | // } 19 | return { 20 | // prefixCls: computed(() => `${values.prefixCls}-${scope}`), 21 | prefixCls: `${values.prefixCls}-${scope}`, 22 | prefixVar: values.prefixCls, 23 | hashId: token.hashId.value, 24 | // style, 25 | }; 26 | } 27 | -------------------------------------------------------------------------------- /packages/core/hooks/web/useFullContent.ts: -------------------------------------------------------------------------------- 1 | import { computed, unref } from 'vue'; 2 | 3 | import { useAppStore } from '@jeesite/core/store/modules/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 | -------------------------------------------------------------------------------- /packages/core/hooks/web/usePagination.ts: -------------------------------------------------------------------------------- 1 | import type { Ref } from 'vue'; 2 | import { ref, unref, computed } from 'vue'; 3 | 4 | function pagination(list: T[], pageNo: number, pageSize: number): T[] { 5 | const offset = (pageNo - 1) * Number(pageSize); 6 | const ret = 7 | offset + Number(pageSize) >= list.length 8 | ? list.slice(offset, list.length) 9 | : list.slice(offset, offset + Number(pageSize)); 10 | return ret; 11 | } 12 | 13 | export function usePagination(list: Ref, pageSize: number) { 14 | const currentPage = ref(1); 15 | const pageSizeRef = ref(pageSize); 16 | 17 | const getPaginationList = computed(() => { 18 | return pagination(unref(list), unref(currentPage), unref(pageSizeRef)); 19 | }); 20 | 21 | const getTotal = computed(() => { 22 | return unref(list).length; 23 | }); 24 | 25 | function setCurrentPage(page: number) { 26 | currentPage.value = page; 27 | } 28 | 29 | function setPageSize(pageSize: number) { 30 | pageSizeRef.value = pageSize; 31 | } 32 | 33 | return { setCurrentPage, getTotal, setPageSize, getPaginationList }; 34 | } 35 | -------------------------------------------------------------------------------- /packages/core/hooks/web/useScript.ts: -------------------------------------------------------------------------------- 1 | import { onMounted, onUnmounted, ref } from 'vue'; 2 | 3 | interface ScriptOptions { 4 | src: string; 5 | } 6 | 7 | export function 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/core/hooks/web/useSortable.ts: -------------------------------------------------------------------------------- 1 | import { nextTick, unref } from 'vue'; 2 | import type { Ref } from 'vue'; 3 | import type { Options } from 'sortablejs'; 4 | 5 | export function useSortable(el: HTMLElement | Ref, options?: Options) { 6 | function initSortable() { 7 | nextTick(async () => { 8 | if (!el) return; 9 | 10 | const Sortable = (await import('sortablejs')).default; 11 | Sortable.create(unref(el), { 12 | animation: 500, 13 | delay: 400, 14 | delayOnTouchOnly: true, 15 | ...options, 16 | }); 17 | }); 18 | } 19 | 20 | return { initSortable }; 21 | } 22 | -------------------------------------------------------------------------------- /packages/core/hooks/web/useTitle.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2013-Now http://jeesite.com All rights reserved. 3 | * No deletion without permission, or be held responsible to law. 4 | * @author ThinkGem 5 | */ 6 | import { watch, unref } from 'vue'; 7 | import { useI18n } from '@jeesite/core/hooks/web/useI18n'; 8 | import { useTitle as usePageTitle } from '@vueuse/core'; 9 | import { useGlobSetting } from '@jeesite/core/hooks/setting'; 10 | import { useRouter } from 'vue-router'; 11 | 12 | import { REDIRECT_NAME } from '@jeesite/core/router/constant'; 13 | 14 | /** 15 | * Listening to page changes and dynamically changing site titles 16 | */ 17 | export function useTitle() { 18 | const { title } = useGlobSetting(); 19 | const { t } = useI18n(); 20 | const { currentRoute } = useRouter(); 21 | 22 | const pageTitle = usePageTitle(); 23 | 24 | watch( 25 | () => currentRoute.value.path, 26 | () => { 27 | const route = unref(currentRoute); 28 | 29 | if (route.name === REDIRECT_NAME) { 30 | return; 31 | } 32 | 33 | const tTitle = t(route?.meta?.title as string); 34 | pageTitle.value = tTitle ? ` ${tTitle} - ${title} ` : `${title}`; 35 | }, 36 | { immediate: true }, 37 | ); 38 | } 39 | -------------------------------------------------------------------------------- /packages/core/index.ts: -------------------------------------------------------------------------------- 1 | // export * from './api'; 2 | // export * from './components'; 3 | -------------------------------------------------------------------------------- /packages/core/layouts/default/content/useContentContext.ts: -------------------------------------------------------------------------------- 1 | import type { InjectionKey, ComputedRef } from 'vue'; 2 | import { createContext, useContext } from '@jeesite/core/hooks/core/useContext'; 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 | -------------------------------------------------------------------------------- /packages/core/layouts/default/header/components/FullScreen.vue: -------------------------------------------------------------------------------- 1 | 9 | 36 | -------------------------------------------------------------------------------- /packages/core/layouts/default/header/components/index.ts: -------------------------------------------------------------------------------- 1 | import { createAsyncComponent } from '@jeesite/core/utils/factory/createAsyncComponent'; 2 | import FullScreen from './FullScreen.vue'; 3 | import UserDropDown from './user-dropdown/index.vue'; 4 | 5 | export const LayoutBreadcrumb = createAsyncComponent(() => import('./Breadcrumb.vue')); 6 | 7 | export const Notify = createAsyncComponent(() => import('./notify/index.vue')); 8 | 9 | export const ErrorAction = createAsyncComponent(() => import('./ErrorAction.vue')); 10 | 11 | export const OnlineCount = createAsyncComponent(() => import('./OnlineCount.vue')); 12 | 13 | export const SettingDrawer = createAsyncComponent(() => import('@jeesite/core/layouts/default/setting/index.vue'), { 14 | loading: true, 15 | }); 16 | 17 | export { FullScreen, UserDropDown }; 18 | -------------------------------------------------------------------------------- /packages/core/layouts/default/header/components/user-dropdown/DropMenuItem.vue: -------------------------------------------------------------------------------- 1 | 10 | 33 | -------------------------------------------------------------------------------- /packages/core/layouts/default/setting/components/index.ts: -------------------------------------------------------------------------------- 1 | import { createAsyncComponent } from '@jeesite/core/utils/factory/createAsyncComponent'; 2 | 3 | export const TypePicker = createAsyncComponent(() => import('./TypePicker.vue'), { loading: true }); 4 | export const ThemeColorPicker = createAsyncComponent(() => import('./ThemeColorPicker.vue')); 5 | export const SettingFooter = createAsyncComponent(() => import('./SettingFooter.vue')); 6 | export const SwitchItem = createAsyncComponent(() => import('./SwitchItem.vue')); 7 | export const SelectItem = createAsyncComponent(() => import('./SelectItem.vue')); 8 | export const InputNumberItem = createAsyncComponent(() => import('./InputNumberItem.vue')); 9 | -------------------------------------------------------------------------------- /packages/core/layouts/default/setting/index.vue: -------------------------------------------------------------------------------- 1 | 7 | 27 | -------------------------------------------------------------------------------- /packages/core/layouts/default/tabs/components/TabRedo.vue: -------------------------------------------------------------------------------- 1 | 6 | 34 | -------------------------------------------------------------------------------- /packages/core/layouts/default/tabs/types.ts: -------------------------------------------------------------------------------- 1 | import type { DropMenu } from '@jeesite/core/components/Dropdown'; 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 | -------------------------------------------------------------------------------- /packages/core/layouts/default/trigger/HeaderTrigger.vue: -------------------------------------------------------------------------------- 1 | 6 | 26 | -------------------------------------------------------------------------------- /packages/core/layouts/default/trigger/SiderTrigger.vue: -------------------------------------------------------------------------------- 1 | 7 | 22 | -------------------------------------------------------------------------------- /packages/core/layouts/default/trigger/index.vue: -------------------------------------------------------------------------------- 1 | 5 | 23 | -------------------------------------------------------------------------------- /packages/core/layouts/iframe/FrameBlank.vue: -------------------------------------------------------------------------------- 1 | 4 | 10 | -------------------------------------------------------------------------------- /packages/core/layouts/iframe/FrameSimple.vue: -------------------------------------------------------------------------------- 1 | 10 | 25 | -------------------------------------------------------------------------------- /packages/core/layouts/iframe/index.vue: -------------------------------------------------------------------------------- 1 | 8 | 26 | -------------------------------------------------------------------------------- /packages/core/layouts/page/transition.ts: -------------------------------------------------------------------------------- 1 | import type { FunctionalComponent } from 'vue'; 2 | import type { RouteLocation } from 'vue-router'; 3 | 4 | export interface DefaultContext { 5 | Component: FunctionalComponent & { type: Recordable }; 6 | route: RouteLocation; 7 | } 8 | 9 | export function getTransitionName({ 10 | route, 11 | openCache, 12 | cacheTabs, 13 | enableTransition, 14 | def, 15 | }: Pick & { 16 | enableTransition: boolean; 17 | openCache: boolean; 18 | def: string; 19 | cacheTabs: string[]; 20 | }): string | undefined { 21 | if (!enableTransition) { 22 | return undefined; 23 | } 24 | 25 | const isInCache = cacheTabs.includes(route.name as string); 26 | const transitionName = 'fade-slide'; 27 | let name: string | undefined = transitionName; 28 | 29 | if (openCache) { 30 | name = isInCache && route.meta.loaded ? transitionName : undefined; 31 | } 32 | return name || (route.meta.transitionName as string) || def; 33 | } 34 | -------------------------------------------------------------------------------- /packages/core/layouts/views/desktop/analysis/components/SiteAnalysis.vue: -------------------------------------------------------------------------------- 1 | 17 | 45 | -------------------------------------------------------------------------------- /packages/core/layouts/views/desktop/analysis/index.vue: -------------------------------------------------------------------------------- 1 | 12 | 19 | -------------------------------------------------------------------------------- /packages/core/layouts/views/desktop/workbench/components/DynamicInfo.vue: -------------------------------------------------------------------------------- 1 | 24 | 32 | -------------------------------------------------------------------------------- /packages/core/layouts/views/desktop/workbench/components/ProjectCard.vue: -------------------------------------------------------------------------------- 1 | 22 | 35 | -------------------------------------------------------------------------------- /packages/core/layouts/views/desktop/workbench/components/QuickNav.vue: -------------------------------------------------------------------------------- 1 | 13 | 20 | -------------------------------------------------------------------------------- /packages/core/layouts/views/errorLog/DetailModal.vue: -------------------------------------------------------------------------------- 1 | 6 | 28 | -------------------------------------------------------------------------------- /packages/core/layouts/views/exception/index.ts: -------------------------------------------------------------------------------- 1 | export { default as Exception } from './Exception.vue'; 2 | -------------------------------------------------------------------------------- /packages/core/layouts/views/exception/index.vue: -------------------------------------------------------------------------------- 1 | 4 | 7 | -------------------------------------------------------------------------------- /packages/core/layouts/views/lock/index.vue: -------------------------------------------------------------------------------- 1 | 6 | 14 | -------------------------------------------------------------------------------- /packages/core/layouts/views/login/LoginFormTitle.vue: -------------------------------------------------------------------------------- 1 | 6 | 26 | -------------------------------------------------------------------------------- /packages/core/layouts/views/login/QrCodeForm.vue: -------------------------------------------------------------------------------- 1 | 14 | 29 | -------------------------------------------------------------------------------- /packages/core/layouts/views/redirect/index.vue: -------------------------------------------------------------------------------- 1 | 4 | 31 | -------------------------------------------------------------------------------- /packages/core/locales/helper.ts: -------------------------------------------------------------------------------- 1 | import type { LocaleType } from '@jeesite/types/config'; 2 | 3 | import { set } from 'lodash-es'; 4 | 5 | export const loadLocalePool: LocaleType[] = []; 6 | 7 | export function setHtmlPageLang(locale: LocaleType) { 8 | document.querySelector('html')?.setAttribute('lang', locale); 9 | } 10 | 11 | export function setLoadLocalePool(cb: (loadLocalePool: LocaleType[]) => void) { 12 | cb(loadLocalePool); 13 | } 14 | 15 | export function genMessage(langs: Record>, prefix = 'lang') { 16 | const obj: Recordable = {}; 17 | 18 | Object.keys(langs).forEach((key) => { 19 | const langFileModule = langs[key].default; 20 | let fileName = key.replace(`./${prefix}/`, '').replace(/^\.\//, ''); 21 | const lastIndex = fileName.lastIndexOf('.'); 22 | fileName = fileName.substring(0, lastIndex); 23 | const keyList = fileName.split('/'); 24 | const moduleName = keyList.shift(); 25 | const objKey = keyList.join('.'); 26 | 27 | if (moduleName) { 28 | if (objKey) { 29 | set(obj, moduleName, obj[moduleName] || {}); 30 | set(obj[moduleName], objKey, langFileModule); 31 | } else { 32 | set(obj, moduleName, langFileModule || {}); 33 | } 34 | } 35 | }); 36 | return obj; 37 | } 38 | -------------------------------------------------------------------------------- /packages/core/locales/lang/en.ts: -------------------------------------------------------------------------------- 1 | import { genMessage } from '../helper'; 2 | import antdLocale from 'ant-design-vue/es/locale/en_US'; 3 | 4 | const modules = import.meta.glob('./en/**/*.ts', { eager: true }); 5 | 6 | export default { 7 | message: { 8 | ...genMessage(modules as Recordable, 'en'), 9 | antdLocale, 10 | }, 11 | dateLocale: null, 12 | dateLocaleName: 'en', 13 | }; 14 | -------------------------------------------------------------------------------- /packages/core/locales/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 | modifyText: 'Modify', 10 | submitText: 'Submit', 11 | searchText: 'Search', 12 | queryText: 'Search', 13 | 14 | showText: 'Show', 15 | hideText: 'Hide', 16 | 17 | inputText: 'Please enter', 18 | chooseText: 'Please choose', 19 | 20 | redo: 'Refresh', 21 | back: 'Back', 22 | 23 | light: 'Light', 24 | dark: 'Dark', 25 | 26 | notYetRealized: 'Not yet realized', 27 | validateError: 'The information you have filled in is incorrect, please correct it according to the prompt.', 28 | 29 | settingsSave: 'Your Settings have cached locally', 30 | settingsReset: 'Your Settings have been reset', 31 | 32 | comma: ',', 33 | selectedItems: 'Select {0} items', 34 | }; 35 | -------------------------------------------------------------------------------- /packages/core/locales/lang/en/routes/basic.ts: -------------------------------------------------------------------------------- 1 | export default { 2 | login: 'Login', 3 | errorLogList: 'Error Log', 4 | }; 5 | -------------------------------------------------------------------------------- /packages/core/locales/lang/en/routes/dashboard.ts: -------------------------------------------------------------------------------- 1 | export default { 2 | dashboard: 'Dashboard', 3 | about: 'About', 4 | workbench: 'Workbench', 5 | analysis: 'Analysis', 6 | }; 7 | -------------------------------------------------------------------------------- /packages/core/locales/lang/zh-CN/common.ts: -------------------------------------------------------------------------------- 1 | export default { 2 | okText: '确认', 3 | closeText: '关闭', 4 | cancelText: '取消', 5 | loadingText: '加载中...', 6 | saveText: '保存', 7 | delText: '删除', 8 | resetText: '重置', 9 | modifyText: '修改', 10 | submitText: '提交', 11 | searchText: '搜索', 12 | queryText: '查询', 13 | 14 | showText: '显示', 15 | hideText: '隐藏', 16 | 17 | inputText: '请输入', 18 | chooseText: '请选择', 19 | 20 | redo: '刷新', 21 | back: '返回', 22 | 23 | light: '亮色主题', 24 | dark: '黑暗主题', 25 | 26 | notYetRealized: '暂未实现', 27 | validateError: '您填写的信息有误,请根据提示修正。', 28 | 29 | selectedItems: '当前已选择 {0} 项', 30 | }; 31 | -------------------------------------------------------------------------------- /packages/core/locales/lang/zh-CN/routes/basic.ts: -------------------------------------------------------------------------------- 1 | export default { 2 | login: '登录', 3 | errorLogList: '错误日志列表', 4 | }; 5 | -------------------------------------------------------------------------------- /packages/core/locales/lang/zh-CN/routes/dashboard.ts: -------------------------------------------------------------------------------- 1 | export default { 2 | dashboard: '控制面板', 3 | workbench: '我的工作', 4 | analysis: '仪表盘', 5 | about: '关于我们', 6 | }; 7 | -------------------------------------------------------------------------------- /packages/core/locales/lang/zh_CN.ts: -------------------------------------------------------------------------------- 1 | import { genMessage } from '../helper'; 2 | import antdLocale from 'ant-design-vue/es/locale/zh_CN'; 3 | 4 | const modules = import.meta.glob('./zh-CN/**/*.ts', { eager: true }); 5 | 6 | export default { 7 | message: { 8 | ...genMessage(modules as Recordable, 'zh-CN'), 9 | antdLocale, 10 | }, 11 | dateLocale: null, 12 | dateLocaleName: 'zh-cn', 13 | }; 14 | -------------------------------------------------------------------------------- /packages/core/logics/mitt/routeChange.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 | 5 | import type { RouteLocationNormalized } from 'vue-router'; 6 | import { getRawRoute } from '@jeesite/core/utils'; 7 | import { mitt } from '@jeesite/core/utils/mitt'; 8 | 9 | const emitter = mitt<{ 10 | [key]: RouteLocationNormalized; 11 | }>(); 12 | 13 | const key = Symbol(); 14 | 15 | let lastChangeTab: RouteLocationNormalized; 16 | 17 | export function setRouteChange(lastChangeRoute: RouteLocationNormalized) { 18 | const r = getRawRoute(lastChangeRoute); 19 | emitter.emit(key, r); 20 | lastChangeTab = r; 21 | } 22 | 23 | export function listenerRouteChange(callback: (route: RouteLocationNormalized) => void, immediate = true) { 24 | emitter.on(key, callback); 25 | immediate && lastChangeTab && callback(lastChangeTab); 26 | } 27 | 28 | export function removeTabChangeListener() { 29 | emitter.clear(); 30 | } 31 | -------------------------------------------------------------------------------- /packages/core/logics/theme/dark.ts: -------------------------------------------------------------------------------- 1 | import { darkCssIsReady, loadDarkThemeCss } from 'vite-plugin-theme-vite3/es/client'; 2 | import { addClass, hasClass, removeClass } from '@jeesite/core/utils/domUtils'; 3 | import { isProdMode } from '@jeesite/core/utils/env'; 4 | 5 | export async function updateDarkTheme(mode: string | null = 'light') { 6 | const htmlRoot = document.getElementById('htmlRoot'); 7 | if (!htmlRoot) { 8 | return; 9 | } 10 | const hasDarkClass = hasClass(htmlRoot, 'dark'); 11 | if (mode === 'dark') { 12 | if (isProdMode() && !darkCssIsReady) { 13 | await loadDarkThemeCss(); 14 | } 15 | htmlRoot.setAttribute('data-theme', 'dark'); 16 | if (!hasDarkClass) { 17 | addClass(htmlRoot, 'dark'); 18 | } 19 | } else { 20 | htmlRoot.setAttribute('data-theme', 'light'); 21 | if (hasDarkClass) { 22 | removeClass(htmlRoot, 'dark'); 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /packages/core/logics/theme/index.ts: -------------------------------------------------------------------------------- 1 | import { getThemeColors, generateColors } from '@jeesite/vite/theme/themeConfig'; 2 | 3 | import { replaceStyleVariables } from 'vite-plugin-theme-vite3/es/client'; 4 | import { mixLighten, mixDarken, tinycolor } from 'vite-plugin-theme-vite3/es/colorUtils'; 5 | 6 | export async function changeTheme(color: string) { 7 | const colors = generateColors({ 8 | mixDarken, 9 | mixLighten, 10 | tinycolor, 11 | color, 12 | }); 13 | 14 | return await replaceStyleVariables({ 15 | colorVariables: [...getThemeColors(color), ...colors], 16 | }); 17 | } 18 | -------------------------------------------------------------------------------- /packages/core/logics/theme/updateColorWeak.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 | -------------------------------------------------------------------------------- /packages/core/logics/theme/updateGrayMode.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 | -------------------------------------------------------------------------------- /packages/core/logics/theme/util.ts: -------------------------------------------------------------------------------- 1 | const docEle = document.documentElement; 2 | export function toggleClass(flag: boolean, clsName: string, target?: HTMLElement) { 3 | const targetEl = target || document.body; 4 | let { className } = targetEl; 5 | className = className.replace(clsName, ''); 6 | targetEl.className = flag ? `${className} ${clsName} ` : className; 7 | } 8 | 9 | export function setCssVar(prop: string, val: any, dom = docEle) { 10 | dom.style.setProperty(prop, val); 11 | } 12 | -------------------------------------------------------------------------------- /packages/core/router/constant.ts: -------------------------------------------------------------------------------- 1 | export const REDIRECT_NAME = 'Redirect'; 2 | export const PARENT_LAYOUT_NAME = 'ParentLayout'; 3 | export const PAGE_NOT_FOUND_NAME = 'PageNotFound'; 4 | 5 | /** 6 | * @description: default layout 7 | */ 8 | export const LAYOUT = () => import('@jeesite/core/layouts/default/index.vue'); 9 | export const IFRAME_BLANK = () => import('@jeesite/core/layouts/iframe/FrameBlank.vue'); 10 | export const IFRAME_SIMPLE = () => import('@jeesite/core/layouts/iframe/FrameSimple.vue'); 11 | export const EXCEPTION_COMPONENT = () => import('@jeesite/core/layouts/views/exception/Exception.vue'); 12 | 13 | /** 14 | * @description: parent-layout 15 | */ 16 | export const getParentLayout = (_name?: string) => { 17 | return () => 18 | new Promise((resolve) => { 19 | resolve({ 20 | name: PARENT_LAYOUT_NAME, 21 | }); 22 | }); 23 | }; 24 | -------------------------------------------------------------------------------- /packages/core/router/guard/stateGuard.ts: -------------------------------------------------------------------------------- 1 | import type { Router } from 'vue-router'; 2 | import { useAppStore } from '@jeesite/core/store/modules/app'; 3 | import { useMultipleTabStore } from '@jeesite/core/store/modules/multipleTab'; 4 | import { useUserStore } from '@jeesite/core/store/modules/user'; 5 | import { usePermissionStore } from '@jeesite/core/store/modules/permission'; 6 | import { PageEnum } from '@jeesite/core/enums/pageEnum'; 7 | import { removeTabChangeListener } from '@jeesite/core/logics/mitt/routeChange'; 8 | 9 | export function createStateGuard(router: Router) { 10 | router.afterEach((to) => { 11 | const tabStore = useMultipleTabStore(); 12 | const userStore = useUserStore(); 13 | const appStore = useAppStore(); 14 | const permissionStore = usePermissionStore(); 15 | // Just enter the login page and clear the authentication information 16 | if (to.path === PageEnum.BASE_LOGIN) { 17 | appStore.resetAllState(); 18 | permissionStore.resetState(); 19 | tabStore.resetState(); 20 | userStore.resetState(); 21 | removeTabChangeListener(); 22 | } 23 | }); 24 | } 25 | -------------------------------------------------------------------------------- /packages/core/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 | */ 6 | import type { AppRouteModule } from '@jeesite/core/router/types'; 7 | 8 | // test 9 | // http:ip:port/main-out 10 | export const mainOutRoutes: AppRouteModule[] = []; 11 | 12 | export const mainOutRouteNames = mainOutRoutes.map((item) => item.name); 13 | -------------------------------------------------------------------------------- /packages/core/settings/designSetting.ts: -------------------------------------------------------------------------------- 1 | import { ThemeEnum } from '../enums/appEnum'; 2 | 3 | export const darkMode = ThemeEnum.LIGHT; 4 | 5 | // header preset color 6 | export const HEADER_PRESET_BG_COLOR_LIST: string[] = [ 7 | '#1951be', 8 | '#1677ff', 9 | '#394664', 10 | '#ffffff', 11 | '#009688', 12 | '#5172DC', 13 | '#e74c3c', 14 | '#001529', 15 | '#151515', 16 | '#24292e', 17 | '#383f45', 18 | ]; 19 | 20 | // app theme preset color 21 | export const APP_PRESET_COLOR_LIST: string[] = [ 22 | '#2a50ec', 23 | '#1677ff', 24 | '#009688', 25 | '#536dfe', 26 | '#ff5c93', 27 | '#ee4f12', 28 | '#0096c7', 29 | '#9c27b0', 30 | '#ff9800', 31 | ]; 32 | 33 | // sider preset color 34 | export const SIDE_BAR_BG_COLOR_LIST: string[] = [ 35 | '#ffffff', 36 | '#001529', 37 | '#273352', 38 | '#151515', 39 | '#191b24', 40 | '#191a23', 41 | '#304156', 42 | '#001628', 43 | '#28333E', 44 | '#344058', 45 | '#383f45', 46 | ]; 47 | -------------------------------------------------------------------------------- /packages/core/settings/encryptionSetting.ts: -------------------------------------------------------------------------------- 1 | import { isDevMode } from '@jeesite/core/utils/env'; 2 | 3 | // System default cache time, in seconds ( 60 days ) 4 | export const DEFAULT_CACHE_TIME = 60 * 60 * 24 * 60; 5 | 6 | // aes encryption key(key and iv 16 bits) 7 | export const cacheCipher = { 8 | key: '_11111000001111@', 9 | iv: '@11111000001111_', 10 | }; 11 | 12 | // Whether the system cache is encrypted using aes 13 | export const enableStorageEncryption = !isDevMode(); 14 | -------------------------------------------------------------------------------- /packages/core/settings/localeSetting.ts: -------------------------------------------------------------------------------- 1 | import type { DropMenu } from '../components/Dropdown'; 2 | import type { LocaleSetting, LocaleType } from '@jeesite/types/config'; 3 | 4 | export const LOCALE: { [key: string]: LocaleType } = { 5 | ZH_CN: 'zh_CN', 6 | EN_US: 'en', 7 | }; 8 | 9 | export const localeSetting: LocaleSetting = { 10 | showPicker: true, 11 | // Locale 12 | locale: LOCALE.ZH_CN, 13 | // Default locale 14 | fallback: LOCALE.ZH_CN, 15 | // available Locales 16 | availableLocales: [LOCALE.ZH_CN, LOCALE.EN_US], 17 | }; 18 | 19 | // locale list 20 | export const localeList: DropMenu[] = [ 21 | { 22 | text: '简体中文', 23 | event: LOCALE.ZH_CN, 24 | }, 25 | { 26 | text: 'English', 27 | event: LOCALE.EN_US, 28 | }, 29 | ]; 30 | -------------------------------------------------------------------------------- /packages/core/settings/siteSetting.ts: -------------------------------------------------------------------------------- 1 | // github repo url 2 | export const GITHUB_URL = 'https://gitee.com/thinkgem'; 3 | 4 | // jeesite docs 5 | export const DOC_URL = 'http://docs.jeesite.com'; 6 | 7 | // linker url 8 | export const LINK_URL = 'http://s.jeesite.com'; 9 | 10 | // site url 11 | export const SITE_URL = 'https://jeesite.com'; 12 | -------------------------------------------------------------------------------- /packages/core/store/index.ts: -------------------------------------------------------------------------------- 1 | import type { App } from 'vue'; 2 | import { createPinia } from 'pinia'; 3 | 4 | const store = createPinia(); 5 | 6 | export function setupStore(app: App) { 7 | app.use(store); 8 | } 9 | 10 | export { store }; 11 | -------------------------------------------------------------------------------- /packages/core/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json", 3 | "compilerOptions": { 4 | "baseUrl": ".", 5 | "paths": { 6 | "@jeesite/core/*": ["./*"] 7 | } 8 | }, 9 | "include": [ 10 | "./**/*.ts", 11 | "./**/*.tsx", 12 | "./**/*.vue" 13 | ], 14 | "exclude": [ 15 | "node_modules", 16 | "vite.config.ts", 17 | "_lib", 18 | "dist" 19 | ] 20 | } 21 | -------------------------------------------------------------------------------- /packages/core/utils/auth/index.ts: -------------------------------------------------------------------------------- 1 | import { Persistent, BasicKeys } from '@jeesite/core/utils/cache/persistent'; 2 | import { CacheTypeEnum } from '@jeesite/core/enums/cacheEnum'; 3 | import projectSetting from '@jeesite/core/settings/projectSetting'; 4 | import { TOKEN_KEY } from '@jeesite/core/enums/cacheEnum'; 5 | 6 | const { permissionCacheType } = projectSetting; 7 | const isLocal = permissionCacheType === CacheTypeEnum.LOCAL; 8 | 9 | export function getToken() { 10 | return getAuthCache(TOKEN_KEY); 11 | } 12 | 13 | export function getAuthCache(key: BasicKeys) { 14 | const fn = isLocal ? Persistent.getLocal : Persistent.getSession; 15 | return fn(key) as T; 16 | } 17 | 18 | export function setAuthCache(key: BasicKeys, value) { 19 | const fn = isLocal ? Persistent.setLocal : Persistent.setSession; 20 | return fn(key, value, true); 21 | } 22 | 23 | export function clearAuthCache(immediate = true) { 24 | const fn = isLocal ? Persistent.clearLocal : Persistent.clearSession; 25 | return fn(immediate); 26 | } 27 | -------------------------------------------------------------------------------- /packages/core/utils/cache/index.ts: -------------------------------------------------------------------------------- 1 | import { getStorageShortName } from '@jeesite/core/utils/env'; 2 | import { createStorage as create, CreateStorageParams } from './storageCache'; 3 | import { enableStorageEncryption } from '@jeesite/core/settings/encryptionSetting'; 4 | import { DEFAULT_CACHE_TIME } from '@jeesite/core/settings/encryptionSetting'; 5 | 6 | export type Options = Partial; 7 | 8 | const createOptions = (storage: Storage, options: Options = {}): Options => { 9 | return { 10 | // No encryption in debug mode 11 | hasEncrypt: enableStorageEncryption, 12 | storage, 13 | prefixKey: getStorageShortName(), 14 | ...options, 15 | }; 16 | }; 17 | 18 | export const WebStorage = create(createOptions(sessionStorage)); 19 | 20 | export const createStorage = (storage: Storage = sessionStorage, options: Options = {}) => { 21 | return create(createOptions(storage, options)); 22 | }; 23 | 24 | export const createSessionStorage = (options: Options = {}) => { 25 | return createStorage(sessionStorage, { ...options, timeout: DEFAULT_CACHE_TIME }); 26 | }; 27 | 28 | export const createLocalStorage = (options: Options = {}) => { 29 | return createStorage(localStorage, { ...options, timeout: DEFAULT_CACHE_TIME }); 30 | }; 31 | 32 | export default WebStorage; 33 | -------------------------------------------------------------------------------- /packages/core/utils/dateUtil.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Independent time operation tool to facilitate subsequent switch to dayjs 3 | */ 4 | import dayjs from 'dayjs'; 5 | 6 | const DATE_TIME_FORMAT = 'YYYY-MM-DD HH:mm:ss'; 7 | const DATE_FORMAT = 'YYYY-MM-DD'; 8 | 9 | export function formatToDateTime( 10 | date: dayjs.ConfigType | undefined = undefined, 11 | format = DATE_TIME_FORMAT, 12 | ): string | undefined { 13 | if (!date) return undefined; 14 | return dayjs(date).format(format); 15 | } 16 | 17 | export function formatToDate(date: dayjs.ConfigType | undefined = undefined, format = DATE_FORMAT): string | undefined { 18 | if (!date) return undefined; 19 | return dayjs(date).format(format); 20 | } 21 | 22 | export const dateUtil = dayjs; 23 | -------------------------------------------------------------------------------- /packages/core/utils/file/base64Conver.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * @description: base64 to blob 3 | */ 4 | export function dataURLtoBlob(base64Buf: string): Blob { 5 | const arr = base64Buf.split(','); 6 | const typeItem = arr[0]; 7 | const mime = typeItem.match(/:(.*?);/)![1]; 8 | const bstr = atob(arr[1]); 9 | let n = bstr.length; 10 | const u8arr = new Uint8Array(n); 11 | while (n--) { 12 | u8arr[n] = bstr.charCodeAt(n); 13 | } 14 | return new Blob([u8arr], { type: mime }); 15 | } 16 | 17 | /** 18 | * img url to base64 19 | * @param url 20 | */ 21 | export function urlToBase64(url: string, mineType?: string): Promise { 22 | return new Promise((resolve, reject) => { 23 | let canvas = document.createElement('CANVAS') as Nullable; 24 | const ctx = canvas!.getContext('2d'); 25 | 26 | const img = new Image(); 27 | img.crossOrigin = ''; 28 | img.onload = function () { 29 | if (!canvas || !ctx) { 30 | return reject(); 31 | } 32 | canvas.height = img.height; 33 | canvas.width = img.width; 34 | ctx.drawImage(img, 0, 0); 35 | const dataURL = canvas.toDataURL(mineType || 'image/png'); 36 | canvas = null; 37 | resolve(dataURL); 38 | }; 39 | img.src = url; 40 | }); 41 | } 42 | -------------------------------------------------------------------------------- /packages/core/utils/helper/tsxHelper.tsx: -------------------------------------------------------------------------------- 1 | import { Slots } from 'vue'; 2 | import { isFunction } from '@jeesite/core/utils/is'; 3 | 4 | /** 5 | * @description: Get slot to prevent empty error 6 | */ 7 | export function 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 function 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] = (data) => getSlot(slots, key, data); 33 | }); 34 | return ret; 35 | } 36 | -------------------------------------------------------------------------------- /packages/core/utils/lib/echarts.ts: -------------------------------------------------------------------------------- 1 | import * as echarts from 'echarts/core'; 2 | 3 | import { BarChart, LineChart, PieChart, MapChart, PictorialBarChart, RadarChart } from 'echarts/charts'; 4 | 5 | import { 6 | TitleComponent, 7 | TooltipComponent, 8 | GridComponent, 9 | PolarComponent, 10 | AriaComponent, 11 | ParallelComponent, 12 | LegendComponent, 13 | RadarComponent, 14 | ToolboxComponent, 15 | DataZoomComponent, 16 | VisualMapComponent, 17 | TimelineComponent, 18 | CalendarComponent, 19 | GraphicComponent, 20 | } from 'echarts/components'; 21 | 22 | import { SVGRenderer } from 'echarts/renderers'; 23 | 24 | echarts.use([ 25 | LegendComponent, 26 | TitleComponent, 27 | TooltipComponent, 28 | GridComponent, 29 | PolarComponent, 30 | AriaComponent, 31 | ParallelComponent, 32 | BarChart, 33 | LineChart, 34 | PieChart, 35 | MapChart, 36 | RadarChart, 37 | SVGRenderer, 38 | PictorialBarChart, 39 | RadarComponent, 40 | ToolboxComponent, 41 | DataZoomComponent, 42 | VisualMapComponent, 43 | TimelineComponent, 44 | CalendarComponent, 45 | GraphicComponent, 46 | ]); 47 | 48 | export default echarts; 49 | -------------------------------------------------------------------------------- /packages/core/utils/log.ts: -------------------------------------------------------------------------------- 1 | export const env = import.meta.env; 2 | 3 | export function warn(message: string) { 4 | console.warn(`[${env.VITE_GLOB_APP_TITLE} warn]:${message}`); 5 | } 6 | 7 | export function error(message: string) { 8 | throw new Error(`[${env.VITE_GLOB_APP_TITLE} error]:${message}`); 9 | } 10 | -------------------------------------------------------------------------------- /packages/core/utils/propTypes.ts: -------------------------------------------------------------------------------- 1 | import { CSSProperties, VNodeChild } from 'vue'; 2 | import { createTypes, VueTypeValidableDef, VueTypesInterface } from 'vue-types'; 3 | 4 | export type VueNode = VNodeChild | JSX.Element; 5 | 6 | type PropTypes = VueTypesInterface & { 7 | readonly style: VueTypeValidableDef; 8 | readonly VNodeChild: VueTypeValidableDef; 9 | // readonly trueBool: VueTypeValidableDef; 10 | }; 11 | 12 | const propTypes = createTypes({ 13 | func: undefined, 14 | bool: undefined, 15 | string: undefined, 16 | number: undefined, 17 | object: undefined, 18 | integer: undefined, 19 | }) as PropTypes; 20 | 21 | // propTypes.extend([ 22 | // { 23 | // name: 'style', 24 | // getter: true, 25 | // type: [String, Object], 26 | // default: undefined, 27 | // }, 28 | // { 29 | // name: 'VNodeChild', 30 | // getter: true, 31 | // type: undefined, 32 | // }, 33 | // ]); 34 | export { propTypes }; 35 | -------------------------------------------------------------------------------- /packages/core/utils/uuid.ts: -------------------------------------------------------------------------------- 1 | const hexList: string[] = []; 2 | for (let i = 0; i <= 15; i++) { 3 | hexList[i] = i.toString(16); 4 | } 5 | 6 | export function buildUUID(): string { 7 | let uuid = ''; 8 | for (let i = 1; i <= 36; i++) { 9 | if (i === 9 || i === 14 || i === 19 || i === 24) { 10 | uuid += '-'; 11 | } else if (i === 15) { 12 | uuid += 4; 13 | } else if (i === 20) { 14 | uuid += hexList[(Math.random() * 4) | 8]; 15 | } else { 16 | uuid += hexList[(Math.random() * 16) | 0]; 17 | } 18 | } 19 | return uuid.replace(/-/g, ''); 20 | } 21 | 22 | let unique = 0; 23 | export function buildShortUUID(prefix = ''): string { 24 | const time = Date.now(); 25 | const random = Math.floor(Math.random() * 1000000000); 26 | unique++; 27 | return prefix + '_' + random + unique + String(time); 28 | } 29 | -------------------------------------------------------------------------------- /packages/core/views/sys/company/index.vue: -------------------------------------------------------------------------------- 1 | 6 | 22 | 33 | -------------------------------------------------------------------------------- /packages/core/views/sys/office/index.vue: -------------------------------------------------------------------------------- 1 | 6 | 22 | 33 | -------------------------------------------------------------------------------- /packages/dbm/README.md: -------------------------------------------------------------------------------- 1 | 2 | - 官方网站: 3 | - 使用文档: 4 | - 后端代码: 5 | - 前端代码: 6 | 7 | ------ 8 | 9 |

10 | 如果你喜欢 JeeSite,请给她一个 ⭐️ Star,您的支持将是我们前行的动力。 11 |
12 | 13 | ------ 14 | 15 | - 问题反馈: [【新手必读】](https://gitee.com/thinkgem/jeesite5/issues/I18ARR) 16 | - 需求收集: 17 | - QQ 群:`127515876`、`209330483`、`223507718`、`709534275`、`730390092`、`1373527`、`183903863(外包)` 18 | - 微信群:添加客服微信 邀请您进群 19 | - 关注微信公众号,了解最新动态: 20 | 21 |

22 | JeeSite微信公众号 23 |

24 | -------------------------------------------------------------------------------- /packages/dbm/index.ts: -------------------------------------------------------------------------------- 1 | import './node_modules/@jeesite/dbm-lib/dist/style.css'; 2 | export { DbmDatasourceList, DbmModifyLogList, DbmTableList } from './node_modules/@jeesite/dbm-lib/dist'; 3 | -------------------------------------------------------------------------------- /packages/dbm/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@jeesite/dbm", 3 | "version": "5.12.0", 4 | "private": true, 5 | "type": "module", 6 | "scripts": { 7 | "type:check": "vue-tsc --noEmit --skipLibCheck", 8 | "uninstall": "rimraf node_modules", 9 | "update": "ncu -u" 10 | }, 11 | "dependencies": { 12 | "@jeesite/dbm-lib": "5.12.0-rc.1", 13 | "qs": "6.14.0" 14 | }, 15 | "devDependencies": { 16 | "@types/qs": "6.9.18" 17 | }, 18 | "homepage": "https://jeesite.com", 19 | "repository": { 20 | "type": "git", 21 | "url": "https://gitee.com/thinkgem/jeesite-vue.git" 22 | }, 23 | "bugs": { 24 | "url": "https://gitee.com/thinkgem/jeesite-vue/issues" 25 | }, 26 | "author": { 27 | "name": "ThinkGem", 28 | "email": "thinkgem@163.com", 29 | "url": "https://gitee.com/thinkgem" 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /packages/dbm/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json", 3 | "compilerOptions": { 4 | "baseUrl": ".", 5 | "paths": { 6 | "@jeesite/dbm/*": ["./*"] 7 | } 8 | }, 9 | "include": [ 10 | "./**/*.ts", 11 | "./**/*.tsx", 12 | "./**/*.vue" 13 | ], 14 | "exclude": [ 15 | "node_modules", 16 | "vite.config.ts", 17 | "_lib", 18 | "dist" 19 | ] 20 | } 21 | -------------------------------------------------------------------------------- /packages/dbm/views/biz/bizCategory/index.vue: -------------------------------------------------------------------------------- 1 | 6 | 21 | 36 | -------------------------------------------------------------------------------- /packages/dbm/views/dbm/dbmDatasource/list.vue: -------------------------------------------------------------------------------- 1 | 6 | 9 | 12 | -------------------------------------------------------------------------------- /packages/dbm/views/dbm/dbmModifyLog/list.vue: -------------------------------------------------------------------------------- 1 | 6 | 9 | 12 | -------------------------------------------------------------------------------- /packages/dbm/views/dbm/dbmTable/list.vue: -------------------------------------------------------------------------------- 1 | 6 | 9 | 12 | -------------------------------------------------------------------------------- /packages/dfm/.gitignore: -------------------------------------------------------------------------------- 1 | /assets 2 | -------------------------------------------------------------------------------- /packages/dfm/README.md: -------------------------------------------------------------------------------- 1 | 2 | - 官方网站: 3 | - 使用文档: 4 | - 后端代码: 5 | - 前端代码: 6 | 7 | ------ 8 | 9 |
10 | 如果你喜欢 JeeSite,请给她一个 ⭐️ Star,您的支持将是我们前行的动力。 11 |
12 | 13 | ------ 14 | 15 | - 问题反馈: [【新手必读】](https://gitee.com/thinkgem/jeesite5/issues/I18ARR) 16 | - 需求收集: 17 | - QQ 群:`127515876`、`209330483`、`223507718`、`709534275`、`730390092`、`1373527`、`183903863(外包)` 18 | - 微信群:添加客服微信 邀请您进群 19 | - 关注微信公众号,了解最新动态: 20 | 21 |

22 | JeeSite微信公众号 23 |

24 | -------------------------------------------------------------------------------- /packages/dfm/index.ts: -------------------------------------------------------------------------------- 1 | import './node_modules/@jeesite/dfm-lib/dist/style.css'; 2 | export { DBuilder, DDesigner, setupDForm } from './node_modules/@jeesite/dfm-lib/dist'; 3 | -------------------------------------------------------------------------------- /packages/dfm/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@jeesite/dfm", 3 | "version": "5.12.0", 4 | "private": true, 5 | "type": "module", 6 | "scripts": { 7 | "type:check": "vue-tsc --noEmit --skipLibCheck", 8 | "uninstall": "rimraf node_modules", 9 | "update": "ncu -u" 10 | }, 11 | "dependencies": { 12 | "@jeesite/dfm-lib": "5.12.0-rc.1", 13 | "@vueuse/core": "13.1.0", 14 | "dayjs": "1.11.13", 15 | "less": "4.3.0", 16 | "lodash-es": "4.17.21", 17 | "monaco-editor": "0.52.2", 18 | "vuedraggable": "4.1.0", 19 | "vue-i18n": "11.1.3", 20 | "vue-types": "6.0.0" 21 | }, 22 | "devDependencies": { 23 | "@vitejs/plugin-vue": "5.2.4", 24 | "vite-plugin-dts": "4.5.3", 25 | "vitest": "3.1.3" 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /packages/dfm/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json", 3 | "compilerOptions": { 4 | "baseUrl": ".", 5 | "paths": { 6 | "@jeesite/dfm/*": ["./*"] 7 | } 8 | }, 9 | "include": [ 10 | "./**/*.ts", 11 | "./**/*.tsx", 12 | "./**/*.vue" 13 | ], 14 | "exclude": [ 15 | "node_modules", 16 | "vite.config.ts", 17 | "_lib", 18 | "dist" 19 | ] 20 | } 21 | -------------------------------------------------------------------------------- /packages/dfm/views/dfm/designer/index.vue: -------------------------------------------------------------------------------- 1 | 6 | 10 | -------------------------------------------------------------------------------- /packages/test/README.md: -------------------------------------------------------------------------------- 1 | 2 | - 官方网站: 3 | - 使用文档: 4 | - 后端代码: 5 | - 前端代码: 6 | 7 | ------ 8 | 9 |
10 | 如果你喜欢 JeeSite,请给她一个 ⭐️ Star,您的支持将是我们前行的动力。 11 |
12 | 13 | ------ 14 | 15 | - 问题反馈: [【新手必读】](https://gitee.com/thinkgem/jeesite5/issues/I18ARR) 16 | - 需求收集: 17 | - QQ 群:`127515876`、`209330483`、`223507718`、`709534275`、`730390092`、`1373527`、`183903863(外包)` 18 | - 微信群:添加客服微信 邀请您进群 19 | - 关注微信公众号,了解最新动态: 20 | 21 |

22 | JeeSite微信公众号 23 |

24 | -------------------------------------------------------------------------------- /packages/test/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@jeesite/test", 3 | "version": "5.12.0", 4 | "private": true, 5 | "type": "module", 6 | "scripts": { 7 | "type:check": "vue-tsc --noEmit --skipLibCheck", 8 | "uninstall": "rimraf node_modules", 9 | "update": "ncu -u" 10 | }, 11 | "homepage": "https://jeesite.com", 12 | "repository": { 13 | "type": "git", 14 | "url": "https://gitee.com/thinkgem/jeesite-vue.git" 15 | }, 16 | "bugs": { 17 | "url": "https://gitee.com/thinkgem/jeesite-vue/issues" 18 | }, 19 | "author": { 20 | "name": "ThinkGem", 21 | "email": "thinkgem@163.com", 22 | "url": "https://gitee.com/thinkgem" 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /packages/test/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json", 3 | "compilerOptions": { 4 | "baseUrl": ".", 5 | "paths": { 6 | "@jeesite/test/*": ["./*"] 7 | } 8 | }, 9 | "include": [ 10 | "./**/*.ts", 11 | "./**/*.tsx", 12 | "./**/*.vue" 13 | ], 14 | "exclude": [ 15 | "node_modules", 16 | "vite.config.ts", 17 | "_lib", 18 | "dist" 19 | ] 20 | } 21 | -------------------------------------------------------------------------------- /packages/test/views/demo/watermark.vue: -------------------------------------------------------------------------------- 1 | 9 | 27 | -------------------------------------------------------------------------------- /packages/test/views/test/testTree/index.vue: -------------------------------------------------------------------------------- 1 | 6 | 22 | 33 | -------------------------------------------------------------------------------- /packages/tests/README.md: -------------------------------------------------------------------------------- 1 | # Test Server 2 | 3 | It is used to start the test interface service, which can test the upload, 4 | websocket, login and other interfaces. 5 | 6 | ## Usage 7 | 8 | ```bash 9 | 10 | cd ./tests/server 11 | 12 | yarn install 13 | 14 | yarn serve 15 | 16 | ``` 17 | -------------------------------------------------------------------------------- /packages/tests/nodemon.json: -------------------------------------------------------------------------------- 1 | { 2 | "watch": ["src"], 3 | "ext": "ts", 4 | "exec": "ts-node -r tsconfig-paths/register src/index.ts", 5 | "events": { 6 | "restart": "clear" 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /packages/tests/pm2.config.cjs: -------------------------------------------------------------------------------- 1 | const { name } = require('./package.json'); 2 | const path = require('path'); 3 | 4 | module.exports = { 5 | apps: [ 6 | { 7 | name, 8 | script: path.resolve(__dirname, './dist/index.js'), 9 | instances: require('os').cpus().length, 10 | autorestart: true, 11 | watch: true, 12 | env_production: { 13 | NODE_ENV: 'production', 14 | }, 15 | }, 16 | ], 17 | }; 18 | -------------------------------------------------------------------------------- /packages/tests/src/config/index.ts: -------------------------------------------------------------------------------- 1 | export default { 2 | host: 'localhost', 3 | port: 3300, 4 | }; 5 | -------------------------------------------------------------------------------- /packages/tests/src/controller/FileController.ts: -------------------------------------------------------------------------------- 1 | import FileService from '../service/FileService'; 2 | import { router } from '../router'; 3 | 4 | const service: FileService = new FileService(); 5 | 6 | router.post('/menuRoute', async (ctx) => { 7 | const files: any = ctx.request.files.file; 8 | console.log(files); 9 | 10 | if (files.length === undefined) { 11 | service.upload(ctx, files, false); 12 | } else { 13 | service.upload(ctx, files, true); 14 | } 15 | }); 16 | -------------------------------------------------------------------------------- /packages/tests/src/controller/MenuController.ts: -------------------------------------------------------------------------------- 1 | import MenuService from '../service/MenuService'; 2 | import { router } from '../router'; 3 | 4 | const service: MenuService = new MenuService(); 5 | 6 | router.get('/menuRoute', async (ctx) => { 7 | ctx.body = await service.menuRoute(ctx); 8 | }); 9 | -------------------------------------------------------------------------------- /packages/tests/src/controller/UserController.ts: -------------------------------------------------------------------------------- 1 | import UserService from '../service/UserService'; 2 | import { router } from '../router'; 3 | 4 | const service: UserService = new UserService(); 5 | 6 | router.get('/login', async (ctx) => { 7 | ctx.body = await service.login(ctx); 8 | }); 9 | 10 | router.get('/index', async (ctx) => { 11 | ctx.body = await service.index(ctx); 12 | }); 13 | -------------------------------------------------------------------------------- /packages/tests/src/index.ts: -------------------------------------------------------------------------------- 1 | import path from 'path'; 2 | import Koa from 'koa'; 3 | import koaStatic from 'koa-static'; 4 | import koaWebsocket from 'koa-websocket'; 5 | import websocket from './ws'; 6 | import config from './config'; 7 | import router from './router'; 8 | import './router/routes'; 9 | 10 | const app = koaWebsocket(new Koa()); 11 | 12 | websocket(app); 13 | 14 | router(app); 15 | 16 | app.use(koaStatic(path.join(__dirname, '../'))); 17 | 18 | app.listen(config.port, () => { 19 | console.log(`Application started successfully: http://${config.host}:${config.port}`); 20 | }); 21 | -------------------------------------------------------------------------------- /packages/tests/src/router/index.ts: -------------------------------------------------------------------------------- 1 | import Router from 'koa-router'; 2 | // import routes from './routes'; 3 | import cors from 'koa2-cors'; 4 | import body from 'koa-body'; 5 | 6 | const router = new Router(); 7 | 8 | function initRouter(app: any): Router { 9 | // routes.forEach((route) => router[route.method](route.path, route.action)); 10 | app.use(cors()); 11 | app.use( 12 | body({ 13 | encoding: 'gzip', 14 | multipart: true, 15 | formidable: { 16 | // uploadDir: path.join(__dirname, '../../static/upload/'), // 设置文件上传目录 17 | keepExtensions: true, 18 | maxFieldsSize: 20 * 1024 * 1024, 19 | }, 20 | }), 21 | ); 22 | app.use(router.routes()); 23 | app.use(router.allowedMethods()); 24 | return router; 25 | } 26 | 27 | export { router }; 28 | 29 | export default initRouter; 30 | -------------------------------------------------------------------------------- /packages/tests/src/router/routes.ts: -------------------------------------------------------------------------------- 1 | import '../controller/UserController'; 2 | import '../controller/MenuController'; 3 | import '../controller/FileController'; 4 | -------------------------------------------------------------------------------- /packages/tests/src/utils/index.ts: -------------------------------------------------------------------------------- 1 | export class Result { 2 | static success(data: any) { 3 | return { 4 | code: 0, 5 | success: true, 6 | result: data, 7 | }; 8 | } 9 | static error(data: any) { 10 | return { 11 | code: 0, 12 | success: false, 13 | result: data, 14 | }; 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /packages/tests/src/ws/index.ts: -------------------------------------------------------------------------------- 1 | import route from 'koa-route'; 2 | 3 | function initWebsocket(app: any) { 4 | app.ws.use(function (ctx, next) { 5 | ctx.websocket.send('connection succeeded!'); 6 | return next(ctx); 7 | }); 8 | 9 | app.ws.use( 10 | route.all('/test', function (ctx) { 11 | // ctx.websocket.send('Hello World'); 12 | ctx.websocket.on('message', function (message) { 13 | // do something with the message from client 14 | if (message !== 'ping') { 15 | const data = JSON.stringify({ 16 | id: Math.ceil(Math.random() * 1000), 17 | time: new Date().getTime(), 18 | res: `${message}`, 19 | }); 20 | ctx.websocket.send(data); 21 | } 22 | console.log(message); 23 | }); 24 | }), 25 | ); 26 | } 27 | 28 | export default initWebsocket; 29 | -------------------------------------------------------------------------------- /packages/tests/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "baseUrl": ".", 4 | "module": "commonjs", 5 | "declaration": false, 6 | "removeComments": true, 7 | "emitDecoratorMetadata": true, 8 | "experimentalDecorators": true, 9 | "target": "es6", 10 | "sourceMap": false, 11 | "esModuleInterop": true, 12 | "outDir": "./dist" 13 | }, 14 | "exclude": ["node_modules"] 15 | } 16 | -------------------------------------------------------------------------------- /packages/types/README.md: -------------------------------------------------------------------------------- 1 | 2 | - 官方网站: 3 | - 使用文档: 4 | - 后端代码: 5 | - 前端代码: 6 | 7 | ------ 8 | 9 |
10 | 如果你喜欢 JeeSite,请给她一个 ⭐️ Star,您的支持将是我们前行的动力。 11 |
12 | 13 | ------ 14 | 15 | - 问题反馈: [【新手必读】](https://gitee.com/thinkgem/jeesite5/issues/I18ARR) 16 | - 需求收集: 17 | - QQ 群:`127515876`、`209330483`、`223507718`、`709534275`、`730390092`、`1373527`、`183903863(外包)` 18 | - 微信群:添加客服微信 邀请您进群 19 | - 关注微信公众号,了解最新动态: 20 | 21 |

22 | JeeSite微信公众号 23 |

24 | -------------------------------------------------------------------------------- /packages/types/index.d.ts: -------------------------------------------------------------------------------- 1 | export * from './axios'; 2 | export * from './config'; 3 | export * from './global'; 4 | export * from './store'; 5 | export * from './utils'; 6 | export * from './vue-router'; 7 | -------------------------------------------------------------------------------- /packages/types/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@jeesite/types", 3 | "version": "5.12.0", 4 | "private": true, 5 | "type": "module", 6 | "scripts": { 7 | "type:check": "vue-tsc --noEmit --skipLibCheck", 8 | "lint:eslint": "eslint --cache --max-warnings 0 \"./**/*.{vue,ts,tsx}\" --fix", 9 | "lint:all": "npm run type:check && npm run lint:eslint", 10 | "uninstall": "rimraf node_modules", 11 | "update": "ncu -u" 12 | }, 13 | "homepage": "https://jeesite.com", 14 | "repository": { 15 | "type": "git", 16 | "url": "https://gitee.com/thinkgem/jeesite-vue.git" 17 | }, 18 | "bugs": { 19 | "url": "https://gitee.com/thinkgem/jeesite-vue/issues" 20 | }, 21 | "author": { 22 | "name": "ThinkGem", 23 | "email": "thinkgem@163.com", 24 | "url": "https://gitee.com/thinkgem" 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /packages/types/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json", 3 | "compilerOptions": { 4 | "baseUrl": ".", 5 | "paths": { 6 | "@jeesite/types/*": ["./*"] 7 | } 8 | }, 9 | "include": [ 10 | "./**/*.ts", 11 | "./**/*.tsx", 12 | "./**/*.vue" 13 | ], 14 | "exclude": [ 15 | "node_modules", 16 | "vite.config.ts", 17 | "dist" 18 | ] 19 | } 20 | -------------------------------------------------------------------------------- /packages/types/utils.d.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/types/vue-router.d.ts: -------------------------------------------------------------------------------- 1 | export {}; 2 | 3 | declare module 'vue-router' { 4 | interface RouteMeta extends Record { 5 | orderNo?: number; 6 | // title 7 | title: string; 8 | // Whether to ignore permissions 9 | ignoreAuth?: boolean; 10 | // role info 11 | roles?: RoleEnum[]; 12 | // Whether not to cache 13 | ignoreKeepAlive?: boolean; 14 | // Is it fixed on tab 15 | affix?: boolean; 16 | // icon on tab 17 | icon?: string; 18 | frameSrc?: string; 19 | // current page transition 20 | transitionName?: string; 21 | // Whether the route has been dynamically added 22 | hideBreadcrumb?: boolean; 23 | // Hide submenu 24 | hideChildrenInMenu?: boolean; 25 | // Carrying parameters 26 | carryParam?: boolean; 27 | // Used internally to mark single-level menus 28 | single?: boolean; 29 | // Currently active menu 30 | currentActiveMenu?: string; 31 | // Never show in tab 32 | hideTab?: boolean; 33 | // Never show in menu 34 | hideMenu?: boolean; 35 | isLink?: boolean; 36 | // only build for Menu 37 | ignoreRoute?: boolean; 38 | // Hide path for children 39 | hidePathForChildren?: boolean; 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /packages/vite/README.md: -------------------------------------------------------------------------------- 1 | 2 | - 官方网站: 3 | - 使用文档: 4 | - 后端代码: 5 | - 前端代码: 6 | 7 | ------ 8 | 9 |
10 | 如果你喜欢 JeeSite,请给她一个 ⭐️ Star,您的支持将是我们前行的动力。 11 |
12 | 13 | ------ 14 | 15 | - 问题反馈: [【新手必读】](https://gitee.com/thinkgem/jeesite5/issues/I18ARR) 16 | - 需求收集: 17 | - QQ 群:`127515876`、`209330483`、`223507718`、`709534275`、`730390092`、`1373527`、`183903863(外包)` 18 | - 微信群:添加客服微信 邀请您进群 19 | - 关注微信公众号,了解最新动态: 20 | 21 |

22 | JeeSite微信公众号 23 |

24 | -------------------------------------------------------------------------------- /packages/vite/build.config.ts: -------------------------------------------------------------------------------- 1 | import { defineBuildConfig } from 'unbuild'; 2 | 3 | export default defineBuildConfig({ 4 | clean: true, 5 | declaration: true, 6 | entries: ['./index', './config/getEnvConfigName', './theme/themeConfig'], 7 | }); 8 | -------------------------------------------------------------------------------- /packages/vite/config/getEnvConfigName.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2013-Now http://jeesite.com All rights reserved. 3 | * No deletion without permission, or be held responsible to law. 4 | * @author ThinkGem 5 | */ 6 | export const getEnvConfigName = (env: Record) => { 7 | return `__PRODUCTION__${env.VITE_GLOB_APP_SHORT_NAME || '__APP'}__CONF__`.toUpperCase().replace(/\s/g, ''); 8 | }; 9 | -------------------------------------------------------------------------------- /packages/vite/index.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2013-Now http://jeesite.com All rights reserved. 3 | * No deletion without permission, or be held responsible to law. 4 | * @author ThinkGem 5 | */ 6 | export * from './config'; 7 | export * from './options'; 8 | export * from './plugins'; 9 | -------------------------------------------------------------------------------- /packages/vite/options/css.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2013-Now http://jeesite.com All rights reserved. 3 | * No deletion without permission, or be held responsible to law. 4 | * @author ThinkGem 5 | */ 6 | import type { CSSOptions } from 'vite'; 7 | import { generateModifyVars } from '../theme/modifyVars'; 8 | 9 | export function createCSSOptions(): CSSOptions { 10 | return { 11 | preprocessorOptions: { 12 | less: { 13 | modifyVars: generateModifyVars(), 14 | javascriptEnabled: true, 15 | }, 16 | }, 17 | }; 18 | } 19 | -------------------------------------------------------------------------------- /packages/vite/options/esBuild.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2013-Now http://jeesite.com All rights reserved. 3 | * No deletion without permission, or be held responsible to law. 4 | * @author ThinkGem 5 | */ 6 | import type { ESBuildOptions } from 'vite'; 7 | 8 | export function createEsBuildOptions(mode: string): ESBuildOptions { 9 | return { 10 | // pure: viteEnv.VITE_DROP_CONSOLE ? ['console.log', 'debugger'] : [], 11 | drop: mode === 'production' ? ['console', 'debugger'] : [], 12 | }; 13 | } 14 | -------------------------------------------------------------------------------- /packages/vite/options/index.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2013-Now http://jeesite.com All rights reserved. 3 | * No deletion without permission, or be held responsible to law. 4 | * @author ThinkGem 5 | */ 6 | export * from './build'; 7 | export * from './css'; 8 | export * from './define'; 9 | export * from './esBuild'; 10 | export * from './server'; 11 | -------------------------------------------------------------------------------- /packages/vite/plugins/html.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2013-Now http://jeesite.com All rights reserved. 3 | * No deletion without permission, or be held responsible to law. 4 | * @author ThinkGem 5 | */ 6 | import { type PluginOption } from 'vite'; 7 | import { createHtmlPlugin } from 'vite-plugin-html'; 8 | 9 | /** 10 | * Plugin to minimize and use ejs template syntax in index.html. 11 | * https://github.com/anncwb/vite-plugin-html 12 | */ 13 | export function configHtmlPlugin(isBuild: boolean): PluginOption { 14 | return createHtmlPlugin({ 15 | minify: isBuild, 16 | }); 17 | } 18 | -------------------------------------------------------------------------------- /packages/vite/plugins/legacy.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2013-Now http://jeesite.com All rights reserved. 3 | * No deletion without permission, or be held responsible to law. 4 | * @author ThinkGem 5 | */ 6 | import { type PluginOption } from 'vite'; 7 | import legacy from '@vitejs/plugin-legacy'; 8 | import { legacyTargets } from '../options/build'; 9 | 10 | export function configLegacyPlugin(isBuild: boolean, viteEnv: ViteEnv): PluginOption { 11 | if (!(isBuild && viteEnv.VITE_LEGACY)) { 12 | return []; 13 | } 14 | return legacy({ 15 | targets: legacyTargets, 16 | modernPolyfills: true, 17 | }); 18 | } 19 | -------------------------------------------------------------------------------- /packages/vite/plugins/monacoEditor.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2013-Now http://jeesite.com All rights reserved. 3 | * No deletion without permission, or be held responsible to law. 4 | * @author ThinkGem 5 | */ 6 | import type { PluginOption } from 'vite'; 7 | import monacoEditorPlugin from 'vite-plugin-monaco-editor'; 8 | 9 | export function configMonacoEditorPlugin(): PluginOption { 10 | return (monacoEditorPlugin as any).default({ 11 | languageWorkers: ['editorWorkerService', 'json', 'html'], 12 | customDistPath: (root, buildOutDir) => `${buildOutDir}/monaco`, 13 | publicPath: 'monaco', 14 | }); 15 | } 16 | -------------------------------------------------------------------------------- /packages/vite/plugins/unocss.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2013-Now http://jeesite.com All rights reserved. 3 | * No deletion without permission, or be held responsible to law. 4 | * @author ThinkGem 5 | */ 6 | import { type PluginOption } from 'vite'; 7 | import UnoCSS from 'unocss/vite'; 8 | import UnoCSSConfig from '../../../uno.config'; 9 | 10 | export function configUnoCSSPlugin(): PluginOption { 11 | return UnoCSS(UnoCSSConfig); 12 | } 13 | -------------------------------------------------------------------------------- /packages/vite/plugins/visualizer.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2013-Now http://jeesite.com All rights reserved. 3 | * No deletion without permission, or be held responsible to law. 4 | * @author ThinkGem 5 | */ 6 | import { type PluginOption } from 'vite'; 7 | import visualizer from 'rollup-plugin-visualizer'; 8 | 9 | export function isReportMode(): boolean { 10 | return process.env.REPORT === 'true'; 11 | } 12 | 13 | export function configVisualizerPlugin(): PluginOption { 14 | if (!isReportMode()) { 15 | return []; 16 | } 17 | return (visualizer as any).default({ 18 | filename: './node_modules/.cache/visualizer/stats.html', 19 | open: true, 20 | gzipSize: true, 21 | brotliSize: true, 22 | }); 23 | } 24 | -------------------------------------------------------------------------------- /packages/vite/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json", 3 | "compilerOptions": { 4 | "baseUrl": ".", 5 | "paths": { 6 | "@jeesite/vite/*": ["./*"] 7 | } 8 | }, 9 | "include": [ 10 | "./**/*.ts", 11 | "./**/*.tsx", 12 | "./**/*.vue" 13 | ], 14 | "exclude": [ 15 | "node_modules", 16 | "vite.config.ts", 17 | "dist" 18 | ] 19 | } 20 | -------------------------------------------------------------------------------- /pnpm-workspace.yaml: -------------------------------------------------------------------------------- 1 | packages: 2 | - 'packages/**' 3 | - 'web' 4 | -------------------------------------------------------------------------------- /terms.md: -------------------------------------------------------------------------------- 1 | 2 | # 服务条款: 3 | 4 | 1. 不得将 JeeSite 应用于危害国家安全、荣誉和利益的行为,不能以任何形式用于非法为目的的行为。 5 | 2. 在使用本软件时,由于它集成了众多第三方开源软件,请共同遵守这些开源软件的使用许可条款规定。 6 | 3. 关于底层未开源代码,我们保证不添加任何数据安全性控制代码,请放心使用。但您也需了解使用本软件的风险, 7 | 是软件皆有漏洞,任何软件都无法保证100%没有漏洞。请软件上线使用前进行足够的安全检测。 8 | 4. 付费之前请确认已通过社区版或免费版了解和试用本产品,并确认产品功能符合您的需求。 9 | 已提供商业代码、内部资料、技术服务支持或许可文件一经发出均不提供退货服务。 10 | 5. 基于 JeeSite 开发的项目或产品名称以及公司名称,同意支持 JeeSite 推广的案例公布,谢谢您的支持。 11 | 6. 若您已经购买本产品许可文件或以其它方式使用本产品,将被视为您对本服务条款全部的完全接受,如果您未 12 | 能遵守本服务条款,您的许可授权将被终止,许可的权利将被收回,同时您应承担相应法律责任。 13 | 14 | # 联系方式: 15 | 16 | 网址:http://s.jeesite.com 17 | -------------------------------------------------------------------------------- /turbo.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://turbo.build/schema.json", 3 | "tasks": { 4 | "build": { 5 | "dependsOn": ["^build"], 6 | "outputs": ["dist/**"] 7 | }, 8 | "build:deploy": { 9 | "dependsOn": ["^build:deploy"], 10 | "outputs": ["dist/**"] 11 | }, 12 | "dev": { 13 | "cache": false, 14 | "persistent": true 15 | }, 16 | "type:check": { 17 | "cache": false 18 | }, 19 | "uninstall": { 20 | "cache": false 21 | }, 22 | "update": { 23 | "cache": false 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /uno.config.ts: -------------------------------------------------------------------------------- 1 | import { defineConfig, UserConfig, presetTypography, presetIcons, transformerDirectives } from 'unocss'; 2 | import { FileSystemIconLoader } from '@iconify/utils/lib/loader/node-loaders'; 3 | import { presetWind3 } from '@unocss/preset-wind3'; 4 | 5 | export default defineConfig({ 6 | inspector: false, 7 | content: { 8 | pipeline: { 9 | include: ['**/*.vue', '**/*.tsx', '**/*.ts', '**/*-lib/**/*.mjs'], 10 | exclude: ['.git', '.idea', '.turbo', 'node_modules', 'public'], 11 | }, 12 | }, 13 | presets: [ 14 | presetWind3(), 15 | presetTypography(), 16 | presetIcons({ 17 | extraProperties: { 18 | display: 'inline-block', 19 | 'vertical-align': 'middle', 20 | }, 21 | collections: { 22 | svg: FileSystemIconLoader(__dirname + '/packages/assets/icons'), 23 | }, 24 | }), 25 | ], 26 | transformers: [transformerDirectives()], 27 | } as UserConfig); 28 | -------------------------------------------------------------------------------- /web/.env: -------------------------------------------------------------------------------- 1 | # 访问端口 2 | VITE_PORT = 3100 3 | 4 | # 软件标题 5 | VITE_GLOB_APP_TITLE = JeeSite 快速开发平台 6 | 7 | # 软件英文名(小写、全英文、无空格、无特殊字符) 8 | VITE_GLOB_APP_SHORT_NAME = jeesite 9 | -------------------------------------------------------------------------------- /web/.env.development: -------------------------------------------------------------------------------- 1 | # 访问项目的根路径 2 | VITE_PUBLIC_PATH = / 3 | 4 | # 路由模式(true: history、false: hash) 5 | VITE_ROUTE_WEB_HISTORY = true 6 | 7 | # 代理设置,可配置多个,不能换行,格式:[访问接口的根路径, 代理地址, 是否保持Host头] 8 | # VITE_PROXY = [["/js","https://vue.jeesite.com/js",true]] 9 | VITE_PROXY = [["/js","http://127.0.0.1:8980/js",false]] 10 | 11 | # 是否删除 console 调试信息 12 | VITE_DROP_CONSOLE = false 13 | 14 | # 访问接口的根路径(例如:https://vue.jeesite.com)建议为空 15 | VITE_GLOB_API_URL = 16 | 17 | # 访问接口的前缀,在根路径之后 18 | VITE_GLOB_API_URL_PREFIX = /js 19 | 20 | # 访问接口的管理基础路径 21 | VITE_GLOB_ADMIN_PATH = /a 22 | 23 | # 文件预览类型(true、oss) 24 | VITE_FILE_PREVIEW = true 25 | -------------------------------------------------------------------------------- /web/.env.production: -------------------------------------------------------------------------------- 1 | # 访问项目的根路径 2 | VITE_PUBLIC_PATH = / 3 | 4 | # 路由模式(true: history、false: hash) 5 | VITE_ROUTE_WEB_HISTORY = true 6 | 7 | # 是否删除 console 调试信息 8 | VITE_DROP_CONSOLE = true 9 | 10 | # 是否启用 gzip 或 brotli 压缩,多个使用 `,` 分隔 11 | # 支持选项: gzip | brotli | none 12 | VITE_BUILD_COMPRESS = 'none' 13 | 14 | # 是否删除源文件时使用压缩,默认为 false 15 | VITE_BUILD_COMPRESS_DELETE_ORIGIN_FILE = false 16 | 17 | # 访问接口的根路径(例如:https://vue.jeesite.com)建议为空 18 | VITE_GLOB_API_URL = 19 | 20 | # 访问接口的前缀,在根路径之后 21 | VITE_GLOB_API_URL_PREFIX = /js 22 | 23 | # 访问接口的管理基础路径 24 | VITE_GLOB_ADMIN_PATH = /a 25 | 26 | # 文件预览类型(true、oss) 27 | VITE_FILE_PREVIEW = true 28 | 29 | # 是否启用 Vue PWA 30 | VITE_USE_PWA = false 31 | 32 | # 是否兼容 Chrome 内核比较低的浏览器,如 QQ 浏览器(编译包会变大) 33 | VITE_LEGACY = true 34 | -------------------------------------------------------------------------------- /web/.env.tomcat: -------------------------------------------------------------------------------- 1 | # 访问项目的根路径 2 | VITE_PUBLIC_PATH = /vuePath 3 | 4 | # 打包编译发布路径 5 | VITE_OUTPUT_DIR = ../../jeesite-vue-dist/vue-dist-5.12.0/src/main/resources/vue-ui 6 | 7 | # 路由模式(true: history、false: hash) 8 | VITE_ROUTE_WEB_HISTORY = true 9 | 10 | # 是否删除 console 调试信息 11 | VITE_DROP_CONSOLE = true 12 | 13 | # 是否启用 gzip 或 brotli 压缩,多个使用 `,` 分隔 14 | # 支持选项: gzip | brotli | none 15 | VITE_BUILD_COMPRESS = 'none' 16 | 17 | # 是否删除源文件时使用压缩,默认为 false 18 | VITE_BUILD_COMPRESS_DELETE_ORIGIN_FILE = false 19 | 20 | # 访问接口的根路径(例如:https://vue.jeesite.com)建议为空 21 | VITE_GLOB_API_URL = 22 | 23 | # 访问接口的前缀,在根路径之后 24 | VITE_GLOB_API_URL_PREFIX = 25 | 26 | # 访问接口的管理基础路径 27 | VITE_GLOB_ADMIN_PATH = /a 28 | 29 | # 文件预览类型(true、oss) 30 | VITE_FILE_PREVIEW = true 31 | 32 | # 是否启用 Vue PWA 33 | VITE_USE_PWA = false 34 | 35 | # 是否兼容 Chrome 内核比较低的浏览器,如 QQ 浏览器(编译包会变大) 36 | VITE_LEGACY = true 37 | -------------------------------------------------------------------------------- /web/api/sys/secAdmin.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2013-Now http://jeesite.com All rights reserved. 3 | * No deletion without permission, or be held responsible to law. 4 | * @author ThinkGem 5 | */ 6 | import { defHttp } from '@jeesite/core/utils/http/axios'; 7 | import { useGlobSetting } from '@jeesite/core/hooks/setting'; 8 | import { Page } from '@jeesite/core/api/model/baseModel'; 9 | import { User } from '@jeesite/core/api/sys/user'; 10 | 11 | const { adminPath } = useGlobSetting(); 12 | 13 | export const secAdminList = (params?: User | any) => 14 | defHttp.get({ url: adminPath + '/sys/secAdmin/list', params }); 15 | 16 | export const secAdminListData = (params?: User | any) => 17 | defHttp.post>({ url: adminPath + '/sys/secAdmin/listData', params }); 18 | 19 | export const secAdminForm = (params?: User | any) => 20 | defHttp.get({ url: adminPath + '/sys/secAdmin/form', params }); 21 | 22 | export const secAdminSave = (params?: any) => defHttp.post({ url: adminPath + '/sys/secAdmin/save', params }); 23 | 24 | export const secAdminDelete = (params?: User | any) => 25 | defHttp.get({ url: adminPath + '/sys/secAdmin/delete', params }); 26 | -------------------------------------------------------------------------------- /web/public/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thinkgem/jeesite/dbb4a7e878550525657c6e4ac4a694fafd77faa4/web/public/favicon.png -------------------------------------------------------------------------------- /web/public/resource/img/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thinkgem/jeesite/dbb4a7e878550525657c6e4ac4a694fafd77faa4/web/public/resource/img/logo.png -------------------------------------------------------------------------------- /web/public/resource/img/pwa-192x192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thinkgem/jeesite/dbb4a7e878550525657c6e4ac4a694fafd77faa4/web/public/resource/img/pwa-192x192.png -------------------------------------------------------------------------------- /web/public/resource/img/pwa-512x512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thinkgem/jeesite/dbb4a7e878550525657c6e4ac4a694fafd77faa4/web/public/resource/img/pwa-512x512.png -------------------------------------------------------------------------------- /web/public/resource/layer/theme/default/close.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /web/public/resource/layer/theme/default/full-1.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /web/public/resource/layer/theme/default/full-2.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /web/public/resource/layer/theme/default/icon-ext.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thinkgem/jeesite/dbb4a7e878550525657c6e4ac4a694fafd77faa4/web/public/resource/layer/theme/default/icon-ext.png -------------------------------------------------------------------------------- /web/public/resource/layer/theme/default/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thinkgem/jeesite/dbb4a7e878550525657c6e4ac4a694fafd77faa4/web/public/resource/layer/theme/default/icon.png -------------------------------------------------------------------------------- /web/public/resource/layer/theme/default/loading-0.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thinkgem/jeesite/dbb4a7e878550525657c6e4ac4a694fafd77faa4/web/public/resource/layer/theme/default/loading-0.gif -------------------------------------------------------------------------------- /web/public/resource/layer/theme/default/loading-1.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thinkgem/jeesite/dbb4a7e878550525657c6e4ac4a694fafd77faa4/web/public/resource/layer/theme/default/loading-1.gif -------------------------------------------------------------------------------- /web/public/resource/layer/theme/default/loading-2.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thinkgem/jeesite/dbb4a7e878550525657c6e4ac4a694fafd77faa4/web/public/resource/layer/theme/default/loading-2.gif -------------------------------------------------------------------------------- /web/public/timestamp.txt: -------------------------------------------------------------------------------- 1 | 1 2 | -------------------------------------------------------------------------------- /web/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../tsconfig.json", 3 | "compilerOptions": { 4 | "baseUrl": ".", 5 | "paths": { 6 | "@jeesite/web/*": ["./*"] 7 | } 8 | }, 9 | "include": [ 10 | "./**/*.ts", 11 | "./**/*.tsx", 12 | "./**/*.vue" 13 | ], 14 | "exclude": [ 15 | "node_modules", 16 | "vite.config.ts", 17 | "dist" 18 | ] 19 | } 20 | -------------------------------------------------------------------------------- /web/uno.config.ts: -------------------------------------------------------------------------------- 1 | import UnoConfig from '../uno.config'; 2 | 3 | export default UnoConfig; 4 | -------------------------------------------------------------------------------- /web/vite.config.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2013-Now http://jeesite.com All rights reserved. 3 | * No deletion without permission, or be held responsible to law. 4 | * @author ThinkGem 5 | */ 6 | import type { UserConfig, ConfigEnv } from 'vite'; 7 | import { defineConfig, loadEnv } from 'vite'; 8 | import path from 'path'; 9 | import { 10 | createBuildOptions, 11 | createCSSOptions, 12 | createDefineOptions, 13 | createEsBuildOptions, 14 | createServerOptions, 15 | createVitePlugins, 16 | wrapperEnv, 17 | } from '@jeesite/vite'; 18 | 19 | export default defineConfig(async ({ command, mode }: ConfigEnv) => { 20 | const root = process.cwd(); 21 | const isBuild = command === 'build'; 22 | const viteEnv = wrapperEnv(loadEnv(mode, root)); 23 | const config: UserConfig = { 24 | root, 25 | base: viteEnv.VITE_PUBLIC_PATH, 26 | define: await createDefineOptions(), 27 | plugins: createVitePlugins(isBuild, viteEnv), 28 | server: createServerOptions(viteEnv), 29 | esbuild: createEsBuildOptions(mode), 30 | build: createBuildOptions(viteEnv), 31 | css: createCSSOptions(), 32 | resolve: { 33 | alias: { 34 | '@jeesite/web': path.resolve(__dirname, './'), 35 | }, 36 | }, 37 | }; 38 | return config; 39 | }); 40 | --------------------------------------------------------------------------------