├── .changeset ├── README.md └── config.json ├── .commitlintrc.js ├── .eslintignore ├── .eslintrc.js ├── .github └── workflows │ ├── Dockerfile │ ├── docker-deploy.yml │ ├── dockerBootstrap.sh │ └── nginx.conf ├── .gitignore ├── .husky ├── commit-msg ├── common.sh └── pre-commit ├── .lintstagedrc.js ├── .npmrc ├── .prettierignore ├── .prettierrc.js ├── LICENSE ├── README.md ├── configs ├── lint │ ├── commitlint.js │ ├── cz-config.js │ ├── eslint.js │ ├── lintstaged.js │ ├── package.json │ ├── prettier.js │ └── stylelint.js └── tsconfig │ ├── base.json │ ├── package.json │ └── server.json ├── package.json ├── packages ├── apps │ ├── admin │ │ ├── .env │ │ ├── .env.development │ │ ├── .env.production │ │ ├── .env.test │ │ ├── .gitignore │ │ ├── .vscode │ │ │ └── extensions.json │ │ ├── index.html │ │ ├── mock │ │ │ ├── index.ts │ │ │ ├── module │ │ │ │ ├── system │ │ │ │ │ ├── menu.ts │ │ │ │ │ └── role.ts │ │ │ │ └── user │ │ │ │ │ └── user.ts │ │ │ └── util.ts │ │ ├── package.json │ │ ├── src │ │ │ ├── App.vue │ │ │ ├── assets │ │ │ │ ├── img │ │ │ │ │ └── common │ │ │ │ │ │ ├── logo.jpg │ │ │ │ │ │ ├── vite.svg │ │ │ │ │ │ └── vue.svg │ │ │ │ └── svg │ │ │ │ │ ├── common │ │ │ │ │ ├── left.svg │ │ │ │ │ └── right.svg │ │ │ │ │ ├── layout │ │ │ │ │ ├── dark.svg │ │ │ │ │ ├── full.svg │ │ │ │ │ ├── gitee.svg │ │ │ │ │ ├── github.svg │ │ │ │ │ ├── h1.svg │ │ │ │ │ ├── h2.svg │ │ │ │ │ ├── h3.svg │ │ │ │ │ ├── h4.svg │ │ │ │ │ ├── h5.svg │ │ │ │ │ ├── light.svg │ │ │ │ │ ├── set.svg │ │ │ │ │ ├── setting.svg │ │ │ │ │ ├── slider.svg │ │ │ │ │ └── yuque.svg │ │ │ │ │ └── logo │ │ │ │ │ ├── echarts.svg │ │ │ │ │ ├── elementui.svg │ │ │ │ │ ├── microapp.svg │ │ │ │ │ ├── nextjs.svg │ │ │ │ │ ├── pinia.svg │ │ │ │ │ ├── pnpm.svg │ │ │ │ │ ├── react.svg │ │ │ │ │ ├── rspack.svg │ │ │ │ │ ├── ting.svg │ │ │ │ │ ├── typescript.svg │ │ │ │ │ ├── unocss.svg │ │ │ │ │ ├── vite.svg │ │ │ │ │ └── vue.svg │ │ │ ├── auto-imports.d.ts │ │ │ ├── components.d.ts │ │ │ ├── directives │ │ │ │ ├── auth.ts │ │ │ │ └── index.ts │ │ │ ├── global.d.ts │ │ │ ├── hooks │ │ │ │ ├── useEnv.ts │ │ │ │ ├── useSetting.ts │ │ │ │ └── useTabs.ts │ │ │ ├── locale │ │ │ │ ├── helper.ts │ │ │ │ ├── lang │ │ │ │ │ ├── en.ts │ │ │ │ │ ├── en │ │ │ │ │ │ └── layout.ts │ │ │ │ │ ├── zh-CN.ts │ │ │ │ │ └── zh-CN │ │ │ │ │ │ └── layout.ts │ │ │ │ ├── setup-i18n.ts │ │ │ │ ├── use-i18n.ts │ │ │ │ └── use-locale.ts │ │ │ ├── main.ts │ │ │ ├── router │ │ │ │ ├── index.ts │ │ │ │ ├── modules │ │ │ │ │ └── system.ts │ │ │ │ ├── routerGuards.ts │ │ │ │ └── type.ts │ │ │ ├── store │ │ │ │ ├── index.ts │ │ │ │ └── modules │ │ │ │ │ ├── setting.ts │ │ │ │ │ ├── tabs.ts │ │ │ │ │ └── user.ts │ │ │ ├── styles │ │ │ │ ├── base │ │ │ │ │ ├── element.scss │ │ │ │ │ ├── index.scss │ │ │ │ │ ├── normalize.scss │ │ │ │ │ └── reset.scss │ │ │ │ ├── global.scss │ │ │ │ ├── index.scss │ │ │ │ ├── mixin │ │ │ │ │ ├── config.scss │ │ │ │ │ ├── function.scss │ │ │ │ │ └── mixins.scss │ │ │ │ ├── theme │ │ │ │ │ ├── dark.scss │ │ │ │ │ ├── dark │ │ │ │ │ │ ├── github-markdown-dark.scss │ │ │ │ │ │ ├── prism-dark.scss │ │ │ │ │ │ └── var.scss │ │ │ │ │ ├── default │ │ │ │ │ │ ├── github-markdown.scss │ │ │ │ │ │ ├── prism.scss │ │ │ │ │ │ └── var.scss │ │ │ │ │ ├── index.scss │ │ │ │ │ └── var.scss │ │ │ │ └── transition │ │ │ │ │ ├── base.scss │ │ │ │ │ ├── fade.scss │ │ │ │ │ ├── index.scss │ │ │ │ │ ├── scale.scss │ │ │ │ │ ├── scroll.scss │ │ │ │ │ ├── slide.scss │ │ │ │ │ └── zoom.scss │ │ │ └── views │ │ │ │ ├── application │ │ │ │ ├── Application.vue │ │ │ │ ├── index.ts │ │ │ │ └── useAppContext.ts │ │ │ │ ├── common │ │ │ │ ├── error │ │ │ │ │ └── 404.vue │ │ │ │ ├── iframe │ │ │ │ │ └── index.vue │ │ │ │ ├── login │ │ │ │ │ ├── components │ │ │ │ │ │ ├── matter │ │ │ │ │ │ │ ├── hooks │ │ │ │ │ │ │ │ └── matter.ts │ │ │ │ │ │ │ └── index.vue │ │ │ │ │ │ ├── nav │ │ │ │ │ │ │ └── index.vue │ │ │ │ │ │ └── rotation │ │ │ │ │ │ │ ├── index.vue │ │ │ │ │ │ │ ├── microapp.vue │ │ │ │ │ │ │ ├── pnpm.vue │ │ │ │ │ │ │ ├── react.vue │ │ │ │ │ │ │ ├── text.vue │ │ │ │ │ │ │ ├── ts.vue │ │ │ │ │ │ │ ├── vite.vue │ │ │ │ │ │ │ └── vue.vue │ │ │ │ │ └── index.vue │ │ │ │ └── redirect │ │ │ │ │ └── index.vue │ │ │ │ └── layouts │ │ │ │ ├── default │ │ │ │ ├── aside │ │ │ │ │ └── index.vue │ │ │ │ ├── feature │ │ │ │ │ ├── index.vue │ │ │ │ │ └── setting │ │ │ │ │ │ ├── index.vue │ │ │ │ │ │ └── theme │ │ │ │ │ │ └── index.vue │ │ │ │ ├── header │ │ │ │ │ ├── breadcrumb │ │ │ │ │ │ └── index.vue │ │ │ │ │ ├── index.vue │ │ │ │ │ ├── setting │ │ │ │ │ │ └── index.vue │ │ │ │ │ └── trigger │ │ │ │ │ │ └── index.vue │ │ │ │ ├── index.vue │ │ │ │ ├── logo │ │ │ │ │ └── index.vue │ │ │ │ ├── main │ │ │ │ │ └── index.vue │ │ │ │ ├── navIcon │ │ │ │ │ └── index.vue │ │ │ │ ├── tabs │ │ │ │ │ ├── full │ │ │ │ │ │ └── index.vue │ │ │ │ │ ├── index.vue │ │ │ │ │ └── set │ │ │ │ │ │ └── index.vue │ │ │ │ └── theme │ │ │ │ │ └── index.vue │ │ │ │ ├── micro │ │ │ │ └── index.vue │ │ │ │ └── parentLayout │ │ │ │ └── index.vue │ │ ├── tsconfig.json │ │ └── vite.config.ts │ ├── micro-demo │ │ ├── .env.development │ │ ├── .env.production │ │ ├── index.html │ │ ├── package.json │ │ ├── rspack.config.ts │ │ ├── src │ │ │ ├── assets │ │ │ │ └── react.svg │ │ │ ├── components │ │ │ │ ├── application │ │ │ │ │ └── inedx.tsx │ │ │ │ └── layout │ │ │ │ │ ├── index.tsx │ │ │ │ │ └── transition-layout │ │ │ │ │ └── index.tsx │ │ │ ├── main.tsx │ │ │ ├── router │ │ │ │ ├── baseRouters.tsx │ │ │ │ ├── index.tsx │ │ │ │ └── modules │ │ │ │ │ └── micro.tsx │ │ │ ├── style │ │ │ │ ├── index.less │ │ │ │ └── test.less │ │ │ ├── types │ │ │ │ ├── global.d.ts │ │ │ │ └── module.d.ts │ │ │ ├── utils │ │ │ │ └── env.ts │ │ │ └── views │ │ │ │ ├── common │ │ │ │ └── error │ │ │ │ │ ├── index.module.css │ │ │ │ │ └── index.tsx │ │ │ │ └── micro │ │ │ │ └── micro-app-demo │ │ │ │ └── index.tsx │ │ ├── tailwind.config.js │ │ └── tsconfig.json │ └── micro-docs │ │ ├── index.html │ │ ├── package.json │ │ ├── postcss.config.cjs │ │ ├── src │ │ ├── App.vue │ │ ├── application │ │ │ ├── Application.vue │ │ │ ├── index.ts │ │ │ └── useAppContext.ts │ │ ├── auto-imports.d.ts │ │ ├── components.d.ts │ │ ├── components │ │ │ ├── code-block │ │ │ │ ├── index.vue │ │ │ │ ├── sound-code-once.vue │ │ │ │ └── sound-path-once.vue │ │ │ ├── docs-layout │ │ │ │ ├── index.vue │ │ │ │ └── navigation │ │ │ │ │ ├── index-once.vue │ │ │ │ │ └── tree-once.vue │ │ │ ├── flow │ │ │ │ └── index.vue │ │ │ ├── icon │ │ │ │ ├── icon.vue │ │ │ │ └── svg-icon.vue │ │ │ └── markdown │ │ │ │ └── index.vue │ │ ├── directives │ │ │ ├── auth.ts │ │ │ └── index.ts │ │ ├── global.d.ts │ │ ├── hooks │ │ │ ├── useSetting.ts │ │ │ └── useX6.ts │ │ ├── main.ts │ │ ├── router │ │ │ ├── index.ts │ │ │ └── modules │ │ │ │ ├── basics.ts │ │ │ │ ├── performance.ts │ │ │ │ ├── repackage.ts │ │ │ │ ├── system.ts │ │ │ │ └── visual.ts │ │ ├── store │ │ │ ├── index.ts │ │ │ └── modules │ │ │ │ └── setting.ts │ │ ├── styles │ │ │ ├── base │ │ │ │ ├── element.scss │ │ │ │ ├── index.scss │ │ │ │ ├── normalize.scss │ │ │ │ └── reset.scss │ │ │ ├── global.scss │ │ │ ├── index.scss │ │ │ ├── mixin │ │ │ │ ├── config.scss │ │ │ │ ├── function.scss │ │ │ │ └── mixins.scss │ │ │ ├── theme │ │ │ │ ├── dark.scss │ │ │ │ ├── dark │ │ │ │ │ ├── github-markdown-dark.scss │ │ │ │ │ ├── prism-dark.scss │ │ │ │ │ └── var.scss │ │ │ │ ├── default │ │ │ │ │ ├── github-markdown.scss │ │ │ │ │ ├── prism.scss │ │ │ │ │ └── var.scss │ │ │ │ ├── index.scss │ │ │ │ └── var.scss │ │ │ └── transition │ │ │ │ ├── base.scss │ │ │ │ ├── fade.scss │ │ │ │ ├── index.scss │ │ │ │ ├── scale.scss │ │ │ │ ├── scroll.scss │ │ │ │ ├── slide.scss │ │ │ │ └── zoom.scss │ │ └── views │ │ │ ├── basics │ │ │ ├── docker │ │ │ │ ├── index.docs.vue │ │ │ │ └── index.md │ │ │ ├── git │ │ │ │ ├── index.docs.vue │ │ │ │ └── index.md │ │ │ ├── linux │ │ │ │ ├── index.docs.vue │ │ │ │ └── index.md │ │ │ ├── network │ │ │ │ ├── index.docs.vue │ │ │ │ └── index.md │ │ │ └── node │ │ │ │ ├── index.docs.vue │ │ │ │ └── index.md │ │ │ ├── common │ │ │ ├── error │ │ │ │ └── 404.vue │ │ │ └── iframe │ │ │ │ └── index.vue │ │ │ ├── performance │ │ │ ├── optimization │ │ │ │ ├── index.docs.vue │ │ │ │ └── index.md │ │ │ └── virtual-scroll │ │ │ │ ├── demo │ │ │ │ ├── dynamic-height.demo.vue │ │ │ │ └── fixation-height.demo.vue │ │ │ │ ├── index.docs.vue │ │ │ │ └── index.md │ │ │ ├── repackage │ │ │ ├── components │ │ │ │ ├── demo │ │ │ │ │ ├── button.demo.vue │ │ │ │ │ ├── checkbox.demo.vue │ │ │ │ │ ├── input.demo.vue │ │ │ │ │ ├── radio.demo.vue │ │ │ │ │ └── select.demo.vue │ │ │ │ ├── index.docs.vue │ │ │ │ └── index.md │ │ │ └── low-code │ │ │ │ └── index.docs.vue │ │ │ ├── system │ │ │ ├── auto-publish │ │ │ │ ├── demo │ │ │ │ │ └── micro-app.demo.vue │ │ │ │ └── index.docs.vue │ │ │ ├── css │ │ │ │ ├── demo │ │ │ │ │ ├── bem.demo.vue │ │ │ │ │ └── tailwind.demo.vue │ │ │ │ └── index.docs.vue │ │ │ ├── docs │ │ │ │ ├── demo │ │ │ │ │ └── button.demo.vue │ │ │ │ ├── index.docs.vue │ │ │ │ └── index.md │ │ │ ├── engineering │ │ │ │ └── index.docs.vue │ │ │ ├── home │ │ │ │ └── index.docs.vue │ │ │ └── micro │ │ │ │ ├── demo │ │ │ │ └── micro-app.demo.vue │ │ │ │ └── index.docs.vue │ │ │ └── visual │ │ │ ├── animation │ │ │ ├── demo │ │ │ │ ├── base.demo.vue │ │ │ │ ├── bounce.demo.vue │ │ │ │ ├── fade.demo.vue │ │ │ │ ├── pulse.demo.vue │ │ │ │ ├── rotate.demo.vue │ │ │ │ ├── scale.demo.vue │ │ │ │ └── slide.demo.vue │ │ │ └── index.docs.vue │ │ │ ├── chart │ │ │ ├── demo │ │ │ │ ├── bar.demo.vue │ │ │ │ ├── box.demo.vue │ │ │ │ ├── bubble.demo.vue │ │ │ │ ├── flow.demo.vue │ │ │ │ ├── funnel.demo.vue │ │ │ │ ├── gauge.demo.vue │ │ │ │ ├── heatmap.demo.vue │ │ │ │ ├── line.demo.vue │ │ │ │ ├── map.demo.vue │ │ │ │ ├── pie.demo.vue │ │ │ │ ├── radar.demo.vue │ │ │ │ ├── sankey.demo.vue │ │ │ │ ├── scatter.demo.vue │ │ │ │ ├── sunburst.demo.vue │ │ │ │ └── tree.demo.vue │ │ │ └── index.docs.vue │ │ │ └── flow │ │ │ ├── components │ │ │ ├── graph.vue │ │ │ └── stencil.vue │ │ │ ├── hooks │ │ │ └── useGraph.ts │ │ │ └── index.vue │ │ ├── tailwind.config.cjs │ │ ├── tsconfig.json │ │ └── vite.config.ts ├── cli │ ├── create │ │ ├── README.md │ │ ├── bin │ │ │ └── index.mjs │ │ ├── build.config.ts │ │ ├── package.json │ │ ├── src │ │ │ ├── cli.ts │ │ │ ├── downloadTemplate.ts │ │ │ ├── index.ts │ │ │ ├── init.ts │ │ │ └── inquirer.ts │ │ └── tsconfig.json │ ├── template │ │ ├── cli │ │ │ ├── bin │ │ │ │ └── index.mjs │ │ │ ├── build.config.ts │ │ │ ├── package.json │ │ │ ├── src │ │ │ │ ├── cli.ts │ │ │ │ ├── error.ts │ │ │ │ ├── index.ts │ │ │ │ └── init.ts │ │ │ └── tsconfig.json │ │ └── package.json │ └── utils │ │ ├── build.config.ts │ │ ├── package.json │ │ ├── src │ │ ├── index.ts │ │ ├── inquirer.ts │ │ ├── log.ts │ │ ├── npm.ts │ │ └── pkg.ts │ │ └── tsconfig.json └── lib │ ├── react │ ├── package.json │ └── src │ │ └── index.ts │ ├── request │ ├── index.ts │ ├── package.json │ ├── src │ │ └── axios │ │ │ ├── Axios.ts │ │ │ ├── axiosCancel.ts │ │ │ ├── axiosTransform.ts │ │ │ ├── checkStatus.ts │ │ │ ├── enums.ts │ │ │ ├── helper.ts │ │ │ ├── index.ts │ │ │ └── types.ts │ └── tsconfig.json │ ├── system │ ├── build.config.ts │ ├── package.json │ ├── src │ │ ├── api │ │ │ └── apiSystem.ts │ │ ├── global-data │ │ │ ├── element.ts │ │ │ ├── env.ts │ │ │ ├── index.ts │ │ │ ├── mitt.ts │ │ │ └── user.ts │ │ ├── global.d.ts │ │ ├── hooks │ │ │ ├── auth.ts │ │ │ ├── browser.ts │ │ │ ├── eventListener.ts │ │ │ ├── index.ts │ │ │ ├── login.ts │ │ │ ├── micro.ts │ │ │ ├── namespace.ts │ │ │ ├── router.ts │ │ │ ├── setting.ts │ │ │ └── user.ts │ │ ├── index.ts │ │ └── init │ │ │ ├── api.ts │ │ │ └── index.ts │ └── tsconfig.json │ ├── utils │ ├── build.config.ts │ ├── package.json │ ├── src │ │ ├── browser │ │ │ └── index.ts │ │ ├── date │ │ │ ├── index.ts │ │ │ └── test │ │ │ │ └── date.test.ts │ │ ├── download │ │ │ └── index.ts │ │ ├── format │ │ │ ├── index.ts │ │ │ └── test │ │ │ │ └── format.test.ts │ │ ├── index.ts │ │ ├── is │ │ │ ├── index.ts │ │ │ └── test │ │ │ │ └── is.test.ts │ │ ├── log.ts │ │ ├── math │ │ │ ├── index.ts │ │ │ └── test │ │ │ │ └── math.test.ts │ │ ├── storage │ │ │ └── index.ts │ │ ├── tree.ts │ │ └── util │ │ │ └── index.ts │ └── tsconfig.json │ ├── vite-plugin-code │ ├── build.config.ts │ ├── package.json │ ├── src │ │ ├── createFilter.ts │ │ ├── index.ts │ │ └── transform.ts │ └── tsconfig.json │ └── vue │ ├── .gitignore │ ├── package.json │ ├── src │ ├── assets │ │ └── svg │ │ │ └── common │ │ │ ├── left.svg │ │ │ └── right.svg │ ├── components │ │ ├── demo │ │ │ ├── demo.vue │ │ │ └── index.ts │ │ ├── icon │ │ │ ├── SvgIcon.vue │ │ │ ├── icon.vue │ │ │ └── index.ts │ │ ├── index.ts │ │ └── virtual-scroll │ │ │ ├── index.ts │ │ │ └── index.vue │ ├── element-plus │ │ ├── button │ │ │ ├── button-map │ │ │ │ └── index.vue │ │ │ ├── index.ts │ │ │ └── index.vue │ │ ├── checkbox │ │ │ ├── index.ts │ │ │ └── index.vue │ │ ├── demo │ │ │ ├── index.ts │ │ │ └── index.vue │ │ ├── index.ts │ │ ├── input │ │ │ ├── index.ts │ │ │ └── index.vue │ │ ├── radio │ │ │ ├── index.ts │ │ │ └── index.vue │ │ └── select │ │ │ ├── index.ts │ │ │ └── index.vue │ ├── global.d.ts │ ├── hooks │ │ ├── index.ts │ │ ├── useContext.ts │ │ ├── useDialog.ts │ │ └── useSlots.ts │ ├── index.scss │ └── index.ts │ ├── tsconfig.json │ └── vite.config.ts ├── pnpm-lock.yaml ├── pnpm-workspace.yaml ├── scripts ├── build.ts ├── dev.ts ├── helper.ts └── package.json └── turbo.json /.changeset/README.md: -------------------------------------------------------------------------------- 1 | # Changesets 2 | 3 | Hello and welcome! This folder has been automatically generated by `@changesets/cli`, a build tool that works with multi-package repos, or single-package repos to help you version and publish your code. You can find the full documentation for it [in our repository](https://github.com/changesets/changesets) 4 | 5 | We have a quick list of common questions to get you started engaging with this project in [our documentation](https://github.com/changesets/changesets/blob/main/docs/common-questions.md) 6 | -------------------------------------------------------------------------------- /.changeset/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://unpkg.com/@changesets/config@2.3.1/schema.json", 3 | "changelog": "@changesets/cli/changelog", 4 | "commit": false, 5 | "fixed": [], 6 | "linked": [], 7 | "access": "restricted", 8 | "baseBranch": "master", 9 | "updateInternalDependencies": "patch", 10 | "ignore": [] 11 | } 12 | -------------------------------------------------------------------------------- /.commitlintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = require('@config/lint/commitlint') 2 | -------------------------------------------------------------------------------- /.eslintignore: -------------------------------------------------------------------------------- 1 | *.sh 2 | node_modules 3 | *.md 4 | *.woff 5 | *.ttf 6 | .vscode 7 | .idea 8 | .husky 9 | .local 10 | dist 11 | public 12 | docs 13 | bin 14 | Dockerfile 15 | -------------------------------------------------------------------------------- /.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = require('@config/lint/eslint') 2 | -------------------------------------------------------------------------------- /.github/workflows/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM nginx 2 | # 复制构建文件到容器中 3 | COPY ./packages/apps/admin/dist/ /usr/share/nginx/html/ 4 | COPY ./packages/apps/micro-demo/dist/ /usr/share/nginx/html/demo/ 5 | COPY ./packages/apps/micro-docs/dist/ /usr/share/nginx/html/docs/ 6 | # 复制nginx配置到容器中 7 | COPY ./.github/workflows/nginx.conf /etc/nginx/nginx.conf 8 | # 指定端口 9 | EXPOSE 80 8680 10 | # 启动 Nginx 11 | CMD ["nginx", "-g", "daemon off;"] 12 | -------------------------------------------------------------------------------- /.github/workflows/dockerBootstrap.sh: -------------------------------------------------------------------------------- 1 | # 停掉容器 2 | docker stop web-admin 3 | echo -e "---------删除本地容器和镜像--------" 4 | 5 | # 删除本地镜像 6 | docker rmi tingcode/web-admin:latest 7 | echo -e "---------拉取镜像--------" 8 | 9 | # 拉取镜像 10 | docker pull tingcode/web-admin:latest 11 | echo -e "---------创建容器并运行容器--------" 12 | 13 | docker run --rm -d -p 8680:8680 -p 80:80 --name web-admin tingcode/web-admin:latest 14 | echo -e "---------执行完毕--------" 15 | 16 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | .DS_Store 3 | dist 4 | *-dist 5 | .cache 6 | 7 | .turbo 8 | .local 9 | # local env files 10 | .env.local 11 | .env.*.local 12 | .eslintcache 13 | 14 | # Log files 15 | npm-debug.log* 16 | yarn-debug.log* 17 | yarn-error.log* 18 | .pnpm-debug.log* 19 | 20 | # Editor directories and files 21 | .idea 22 | # .vscode 23 | *.suo 24 | *.ntvs* 25 | *.njsproj 26 | *.sln 27 | *.sw? 28 | *.rar 29 | 30 | -------------------------------------------------------------------------------- /.husky/commit-msg: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # shellcheck source=./_/husky.sh 4 | . "$(dirname "$0")/_/husky.sh" 5 | 6 | npx --no-install commitlint --edit "$1" 7 | -------------------------------------------------------------------------------- /.husky/common.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | command_exists () { 3 | command -v "$1" >/dev/null 2>&1 4 | } 5 | 6 | # Workaround for Windows 10, Git Bash and Yarn 7 | if command_exists winpty && test -t 1; then 8 | exec < /dev/tty 9 | fi 10 | -------------------------------------------------------------------------------- /.husky/pre-commit: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | . "$(dirname "$0")/_/husky.sh" 3 | . "$(dirname "$0")/common.sh" 4 | 5 | [ -n "$CI" ] && exit 0 6 | 7 | # commit 触发 lint 8 | pnpm exec lint-staged 9 | pnpm exec pretty-quick --staged 10 | 11 | -------------------------------------------------------------------------------- /.lintstagedrc.js: -------------------------------------------------------------------------------- 1 | module.exports = require('@config/lint/lintstaged') 2 | -------------------------------------------------------------------------------- /.npmrc: -------------------------------------------------------------------------------- 1 | shamefully-hoist = true 2 | ignore-workspace-root-check=true 3 | public-hoist-pattern[]=* 4 | -------------------------------------------------------------------------------- /.prettierignore: -------------------------------------------------------------------------------- 1 | .local 2 | dist 3 | node_modules 4 | public 5 | packages/apps/admin/src/auto-imports.d.ts 6 | packages/apps/admin/src/components.d.ts 7 | -------------------------------------------------------------------------------- /.prettierrc.js: -------------------------------------------------------------------------------- 1 | module.exports = require('@config/lint/prettier') 2 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2025 Ting 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /configs/lint/commitlint.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | // 继承的规则 @commitlint/config-conventional 3 | extends: ['git-commit-emoji', 'cz'] 4 | // 定义规则类型 5 | // rules: { 6 | // // type 类型定义,表示 git 提交的 type 必须在以下类型范围内 7 | // 'type-enum': [ 8 | // 2, 9 | // 'always', 10 | // [ 11 | // 'feat', // 新功能 feature 12 | // 'fix', // 修复 bug 13 | // 'docs', // 文档注释 14 | // 'style', // 代码格式(不影响代码运行的变动) 15 | // 'refactor', // 重构(既不增加新功能,也不是修复bug) 16 | // 'perf', // 性能优化 17 | // 'test', // 增加测试 18 | // 'chore', // 构建过程或辅助工具的变动 19 | // 'build', // 打包 20 | // 'revert', // 回退 21 | // 'version' //发布版本 22 | // ] 23 | // ], 24 | // // subject 大小写不做校验 25 | // 'subject-case': [0] 26 | // } 27 | } 28 | -------------------------------------------------------------------------------- /configs/lint/cz-config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | //可选类型 3 | types: [ 4 | { value: ':sparkles: feat', name: '✨ feat: 新功能' }, 5 | { value: ':bug: fix', name: '🐛 fix: 修复' }, 6 | { value: ':memo: docs', name: '📝 docs: 文档变更' }, 7 | { 8 | value: ':art: style', 9 | name: '🎨 style: 代码格式(不影响代码运行的变动)' 10 | }, 11 | { 12 | value: ':hammer: refactor', 13 | name: '🔨 refactor:重构(既不是增加feature),也不是修复bug' 14 | }, 15 | { value: ':zap: perf', name: '⚡️ perf: 性能优化' }, 16 | { value: ':mag: test', name: '🔍 test: 增加测试' }, 17 | { value: ':package: chore', name: '📦 chore: 构建过程或辅助功能的变动' }, 18 | { value: ':rocket: build', name: '🚀 build: 打包' }, 19 | { value: ':rewind: revert', name: '⏪ revert: 回退' }, 20 | { value: ':tada: version', name: '🎉 version: 发布版本' } 21 | ], 22 | scopes: [ 23 | { name: 'business' }, 24 | { name: 'library' }, 25 | { name: 'config' }, 26 | { name: 'docs' }, 27 | { name: 'architecture' } 28 | ], 29 | //消息步骤 30 | messages: { 31 | type: '请选择提交类型', 32 | customScope: '请输入修改范围(可选)', 33 | subject: '请简要描述提交(必填)', 34 | body: '请输入详细描述(可选)', 35 | footer: '请输入要关闭的issue(可选)', 36 | confirmCommit: '确认以上信息提交?(y/n)' 37 | }, 38 | //跳过问题 39 | skipQuestion: ['body', 'footer'], 40 | //subject文字长度默认是 41 | subjectLimit: 72 42 | } 43 | -------------------------------------------------------------------------------- /configs/lint/lintstaged.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | '*.{js,jsx,ts,tsx}': ['eslint --fix', 'prettier --write'], 3 | '*.vue': ['eslint --fix', 'prettier --write'], 4 | '*.{scss,less,styl,html}': ['prettier --write'] 5 | } 6 | -------------------------------------------------------------------------------- /configs/lint/prettier.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | printWidth: 100, // 默认80 超过多少字符强制换行 3 | tabWidth: 2, // 使用1个空格缩进 4 | useTabs: false, // 不使用缩进符,而使用空格 5 | semi: false, // 未尾逗号, default: true 代码结尾是否加分号 6 | singleQuote: true, // 单引号 default: false // 是否使用单引号 7 | // quoteProps: 'as-needed', 对象的key仅在必要时用引号 8 | // jsxSingleQuote: false, // jsx不使用单引号,而使用双引号 9 | trailingComma: 'none', // 未尾分号 default: es5 all | none | es5 10 | // bracketSpacing: true, // 对象大括号内两边是否加空格 { a:0 } 11 | // bracketSameLine: false, 12 | //rangeStart: 0, // 每个文件格式化的范围是文件的全部内容 13 | //rangeEnd: Infinity, // 结尾 14 | // jsxBracketSameLine: false, // jsx标签的反尖括号需要换行 15 | arrowParens: 'always', // default: always avoid单个参数的箭头函数不加括号 x => x 16 | // insertPragma: false, // 不需要自动在文件开头插入 @prettier 17 | // requirePragma: false, // 不需要写文件开头的 @prettier 18 | proseWrap: 'never', // preserve默认的折行标准 19 | htmlWhitespaceSensitivity: 'strict', // (css| strict )根据显示样式决定html要不要折行 20 | vueIndentScriptAndStyle: true, // .vue 缩进 21 | endOfLine: 'auto' // default lf 文件换行格式 LF/CRLF 22 | } 23 | -------------------------------------------------------------------------------- /configs/tsconfig/base.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://json.schemastore.org/tsconfig", 3 | "display": "Base", 4 | "compilerOptions": { 5 | "composite": false, 6 | "declaration": true, 7 | "declarationMap": true, 8 | "esModuleInterop": true, 9 | "jsx": "preserve", 10 | "allowJs": true, 11 | "strictFunctionTypes": false, 12 | "allowSyntheticDefaultImports": true, 13 | "forceConsistentCasingInFileNames": true, 14 | "inlineSources": false, 15 | "isolatedModules": true, 16 | "moduleResolution": "node", 17 | "noUnusedLocals": false, 18 | "noUnusedParameters": false, 19 | "preserveWatchOutput": true, 20 | "skipLibCheck": true, 21 | "strict": true, 22 | "resolveJsonModule": true, 23 | "removeComments": true, 24 | "noImplicitAny": false, 25 | "experimentalDecorators": true 26 | }, 27 | "exclude": ["**/node_modules/**", "**/dist/**"] 28 | } 29 | -------------------------------------------------------------------------------- /configs/tsconfig/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@config/tsconfig", 3 | "version": "0.0.0", 4 | "private": true, 5 | "scripts": { 6 | "lint:prettier": "prettier --write --cache --ignore-unknown --ignore-path=../../.prettierignore ." 7 | }, 8 | "files": [ 9 | "base.json", 10 | "server.json" 11 | ] 12 | } 13 | -------------------------------------------------------------------------------- /configs/tsconfig/server.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://json.schemastore.org/tsconfig", 3 | "display": "Server", 4 | "extends": "./base.json", 5 | "compilerOptions": { 6 | "module": "commonjs", 7 | "declaration": true, 8 | "experimentalDecorators": true, 9 | "emitDecoratorMetadata": true, 10 | "target": "esnext", 11 | "sourceMap": false, 12 | "lib": ["ESNext", "DOM"], 13 | "types": ["node"], 14 | "typeRoots": ["node_modules/@types/", "types"] 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /packages/apps/admin/.env: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ting-Code/Ting-Library-Monorepo/9cc73df070e2f9d4660312447f49ae7c5cd32753/packages/apps/admin/.env -------------------------------------------------------------------------------- /packages/apps/admin/.env.development: -------------------------------------------------------------------------------- 1 | # just a flag 2 | ENV = 'development' 3 | 4 | # API 接口地址 5 | VITE_GLOB_API_URL= 6 | 7 | # 网站前缀 8 | VITE_GLOB_API_URL_PREFIX=/fake-api 9 | -------------------------------------------------------------------------------- /packages/apps/admin/.env.production: -------------------------------------------------------------------------------- 1 | # just a flag 2 | ENV = 'production' 3 | 4 | # API 接口地址 5 | VITE_GLOB_API_URL= 6 | 7 | # 网站前缀 8 | VITE_GLOB_API_URL_PREFIX=/fake-api 9 | 10 | 11 | -------------------------------------------------------------------------------- /packages/apps/admin/.env.test: -------------------------------------------------------------------------------- 1 | # just a flag 2 | ENV = 'test' 3 | 4 | # API 接口地址 5 | VITE_GLOB_API_URL= 6 | 7 | # 网站前缀 8 | VITE_GLOB_API_URL_PREFIX=/fake-api 9 | -------------------------------------------------------------------------------- /packages/apps/admin/.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | pnpm-debug.log* 8 | lerna-debug.log* 9 | 10 | node_modules 11 | dist 12 | dist-ssr 13 | *.local 14 | 15 | # Editor directories and files 16 | .vscode/* 17 | !.vscode/extensions.json 18 | .idea 19 | .DS_Store 20 | *.suo 21 | *.ntvs* 22 | *.njsproj 23 | *.sln 24 | *.sw? 25 | -------------------------------------------------------------------------------- /packages/apps/admin/.vscode/extensions.json: -------------------------------------------------------------------------------- 1 | { 2 | "recommendations": ["Vue.volar", "Vue.vscode-typescript-vue-plugin"] 3 | } 4 | -------------------------------------------------------------------------------- /packages/apps/admin/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 10 | Ting Library 11 | 12 | 13 |
14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /packages/apps/admin/mock/index.ts: -------------------------------------------------------------------------------- 1 | import { createProdMockServer } from 'vite-plugin-mock/es/createProdMockServer' 2 | 3 | import system from './module/system/menu' 4 | import user from './module/user/user' 5 | 6 | export function setupProdMockServer() { 7 | createProdMockServer([...system, ...user]) 8 | } 9 | -------------------------------------------------------------------------------- /packages/apps/admin/mock/module/system/role.ts: -------------------------------------------------------------------------------- 1 | import { resultSuccess, doCustomTimes } from '../../util' 2 | 3 | function getMenuKeys() { 4 | const keys = ['dashboard', 'console', 'workplace', 'basic-form', 'step-form', 'detail'] 5 | const newKeys = [] as any[] 6 | doCustomTimes(parseInt(Math.random() * 6), () => { 7 | const key = keys[Math.floor(Math.random() * keys.length)] 8 | newKeys.push(key) 9 | }) 10 | return Array.from(new Set(newKeys)) 11 | } 12 | 13 | const roleList = (pageSize) => { 14 | const result: any[] = [] 15 | doCustomTimes(pageSize, () => { 16 | result.push({ 17 | id: '@integer(10,100)', 18 | name: '@cname()', 19 | explain: '@cname()', 20 | isDefault: '@boolean()', 21 | menu_keys: getMenuKeys(), 22 | create_date: `@date('yyyy-MM-dd hh:mm:ss')`, 23 | 'status|1': ['normal', 'enable', 'disable'] 24 | }) 25 | }) 26 | return result 27 | } 28 | 29 | export default [ 30 | { 31 | url: '/api/role/list', 32 | timeout: 1000, 33 | method: 'get', 34 | response: ({ query }) => { 35 | const { page = 1, pageSize = 10 } = query 36 | const list = roleList(Number(pageSize)) 37 | return resultSuccess({ 38 | page: Number(page), 39 | pageSize: Number(pageSize), 40 | pageCount: 60, 41 | list 42 | }) 43 | } 44 | } 45 | ] 46 | -------------------------------------------------------------------------------- /packages/apps/admin/src/App.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 10 | -------------------------------------------------------------------------------- /packages/apps/admin/src/assets/img/common/logo.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ting-Code/Ting-Library-Monorepo/9cc73df070e2f9d4660312447f49ae7c5cd32753/packages/apps/admin/src/assets/img/common/logo.jpg -------------------------------------------------------------------------------- /packages/apps/admin/src/assets/img/common/vite.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /packages/apps/admin/src/assets/img/common/vue.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /packages/apps/admin/src/assets/svg/common/left.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /packages/apps/admin/src/assets/svg/common/right.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /packages/apps/admin/src/assets/svg/layout/gitee.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /packages/apps/admin/src/assets/svg/layout/h1.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /packages/apps/admin/src/assets/svg/layout/h2.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /packages/apps/admin/src/assets/svg/layout/h3.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /packages/apps/admin/src/assets/svg/layout/h4.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /packages/apps/admin/src/assets/svg/layout/h5.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /packages/apps/admin/src/assets/svg/layout/slider.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /packages/apps/admin/src/assets/svg/logo/elementui.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /packages/apps/admin/src/assets/svg/logo/microapp.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /packages/apps/admin/src/assets/svg/logo/pnpm.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /packages/apps/admin/src/assets/svg/logo/unocss.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /packages/apps/admin/src/assets/svg/logo/vite.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /packages/apps/admin/src/assets/svg/logo/vue.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /packages/apps/admin/src/directives/auth.ts: -------------------------------------------------------------------------------- 1 | import { ObjectDirective, App } from 'vue' 2 | import { isArray, isObject, isString } from '@tingcode/utils' 3 | import { hasAuth } from '@tingcode/system' 4 | 5 | const accessesVerified = (value: string | string[] | unknown) => { 6 | if (isString(value)) { 7 | return [value] 8 | } 9 | if (isArray(value)) { 10 | return value 11 | } 12 | throw new Error(`[v-auth]: ${value} auth 不是字符串或数组!`) 13 | } 14 | 15 | export interface IAuthObject { 16 | disabled?: boolean 17 | auth?: string | string[] 18 | } 19 | 20 | export const auth: ObjectDirective = { 21 | mounted(el, binding) { 22 | const value = binding.value 23 | let disabled = false 24 | let accesses: string[] = [] 25 | if (isObject(value)) { 26 | disabled = !!value.disabled 27 | accesses = accessesVerified(value?.auth) 28 | } else { 29 | accesses = accessesVerified(value) 30 | } 31 | if (!hasAuth(accesses)) { 32 | if (disabled) { 33 | el.disabled = true 34 | el.style['disabled'] = 'disabled' 35 | } else { 36 | // 异步销毁会出现闪屏现象 display: none会先隐藏避免闪屏 37 | el.style['display'] = 'none' 38 | // 由于某些组件用到了css v-bind 如果挂载的时候销毁Dom就会报错 所以需要异步销毁 39 | setTimeout(() => { 40 | el.parentNode?.removeChild(el) 41 | }, 0) 42 | } 43 | } 44 | } 45 | } 46 | 47 | export function setupAuthDirective(app: App) { 48 | app.directive('auth', auth) 49 | } 50 | -------------------------------------------------------------------------------- /packages/apps/admin/src/directives/index.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Configure and register global directives 3 | * 统一注册vue自定义指令 4 | */ 5 | import type { App } from 'vue' 6 | import { setupAuthDirective } from './auth' 7 | 8 | export function setupGlobDirectives(app: App) { 9 | setupAuthDirective(app) 10 | } 11 | -------------------------------------------------------------------------------- /packages/apps/admin/src/locale/helper.ts: -------------------------------------------------------------------------------- 1 | import { set } from 'lodash-es' 2 | import { LocaleType } from '@/locale/setup-i18n' 3 | 4 | export const loadLocalePool: LocaleType[] = [] 5 | 6 | export const setHtmlPageLang = (locale: LocaleType) => { 7 | document.querySelector('html')?.setAttribute('lang', locale) 8 | } 9 | 10 | export const setLoadLocalePool = (cb: (loadLocalePool: LocaleType[]) => void) => { 11 | cb(loadLocalePool) 12 | } 13 | 14 | export const genMessage = (langs, prefix = 'lang') => { 15 | const obj: Recordable = {} 16 | 17 | Object.keys(langs).forEach((key) => { 18 | const langFileModule = langs[key].default 19 | let fileName = key.replace(`./${prefix}/`, '').replace(/^\.\//, '') 20 | const lastIndex = fileName.lastIndexOf('.') 21 | fileName = fileName.substring(0, lastIndex) 22 | const keyList = fileName.split('/') 23 | const moduleName = keyList.shift() 24 | const objKey = keyList.join('.') 25 | 26 | if (moduleName) { 27 | if (objKey) { 28 | set(obj, moduleName, obj[moduleName] || {}) 29 | set(obj[moduleName], objKey, langFileModule) 30 | } else { 31 | set(obj, moduleName, langFileModule || {}) 32 | } 33 | } 34 | }) 35 | return obj 36 | } 37 | -------------------------------------------------------------------------------- /packages/apps/admin/src/locale/lang/en.ts: -------------------------------------------------------------------------------- 1 | import { genMessage } from '@/locale/helper' 2 | 3 | const modules = import.meta.glob('./en/**/*.ts', { eager: true }) 4 | export default { 5 | message: { 6 | ...genMessage(modules, 'en') 7 | }, 8 | dateLocale: null, 9 | dateLocaleName: 'en' 10 | } 11 | -------------------------------------------------------------------------------- /packages/apps/admin/src/locale/lang/en/layout.ts: -------------------------------------------------------------------------------- 1 | export default { 2 | settings: { 3 | title: 'System Settings' 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /packages/apps/admin/src/locale/lang/zh-CN.ts: -------------------------------------------------------------------------------- 1 | import { genMessage } from '@/locale/helper' 2 | 3 | const modules = import.meta.glob('./zh-CN/**/*.ts', { eager: true }) 4 | export default { 5 | message: { 6 | ...genMessage(modules, 'zh-CN') 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /packages/apps/admin/src/locale/lang/zh-CN/layout.ts: -------------------------------------------------------------------------------- 1 | export default { 2 | settings: { 3 | title: '系统设置' 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /packages/apps/admin/src/main.ts: -------------------------------------------------------------------------------- 1 | import '@s/index.scss' 2 | import '@tingcode/lib-vue/dist/css/components/index.css' 3 | import { createApp } from 'vue' 4 | import App from './App.vue' 5 | import { setupStore } from '@/store' 6 | import { setupRouter } from '@/router' 7 | import { setupGlobDirectives } from '@/directives' 8 | import 'virtual:svg-icons-register' 9 | import { setupI18n } from '@/locale/setup-i18n' 10 | import * as EPIcon from '@element-plus/icons-vue' 11 | import { ElMessage, ElMessageBox } from 'element-plus' 12 | import { 13 | initMicroApp, 14 | initNamespace, 15 | setGlobalDataEnv, 16 | setGlobalDataElement, 17 | initRequest, 18 | initMitt 19 | } from '@tingcode/system' 20 | import { useEnv } from '@/hooks/useEnv' 21 | import { NAMESPACE } from '@/hooks/useSetting' 22 | async function bootstrap() { 23 | initMicroApp() 24 | initNamespace(NAMESPACE) 25 | setGlobalDataEnv(useEnv()) 26 | setGlobalDataElement({ ElMessage, ElMessageBox }) 27 | initRequest() 28 | initMitt() 29 | const app = createApp(App) 30 | setupRouter(app) 31 | setupStore(app) 32 | setupGlobDirectives(app) 33 | setupI18n(app) 34 | app.mount('#app') 35 | } 36 | 37 | bootstrap() 38 | 39 | export { EPIcon } 40 | -------------------------------------------------------------------------------- /packages/apps/admin/src/router/modules/system.ts: -------------------------------------------------------------------------------- 1 | import { RouteRecordRaw } from 'vue-router' 2 | 3 | /** 4 | * @param name 路由名称, 必须设置,且不能重名 5 | * @param meta 路由元信息(路由附带扩展信息) 6 | * @param redirect 重定向地址, 访问这个路由时,自定进行重定向 7 | * @param meta.disabled 禁用整个菜单 8 | * @param meta.title 菜单名称 9 | * @param meta.icon 菜单图标 10 | * @param meta.keepAlive 缓存该路由 11 | * 12 | * */ 13 | const routes: Array = [ 14 | // { 15 | // path: '/system/home', 16 | // name: 'system_home', 17 | // component: () => import('@/views/pages/system/home/index.docs.vue') 18 | // }, 19 | // { 20 | // path: '/system/markdown', 21 | // name: 'system_markdown', 22 | // component: () => import('@/views/pages/system/docs/index.docs.vue') 23 | // }, 24 | // { 25 | // path: '/system/micro', 26 | // name: 'system_micro', 27 | // component: () => import('@/views/pages/system/micro/index.docs.vue') 28 | // }, 29 | { 30 | path: '/system/404', 31 | name: 'system_404', 32 | meta: { 33 | transition: true 34 | }, 35 | component: () => import('@/views/common/error/404.vue') 36 | } 37 | ] 38 | 39 | export default routes 40 | -------------------------------------------------------------------------------- /packages/apps/admin/src/router/type.ts: -------------------------------------------------------------------------------- 1 | import type { RouteRecordRaw } from 'vue-router' 2 | import { defineComponent } from 'vue' 3 | import { Recordable } from 'vite-plugin-mock' 4 | 5 | export type Component = ReturnType | (() => Promise) 6 | 7 | export interface AppRouteRecordRaw extends Omit { 8 | name?: string 9 | module?: string 10 | meta?: Meta 11 | component?: Component | string 12 | components?: Component 13 | children?: AppRouteRecordRaw[] 14 | props?: Recordable 15 | fullPath?: string 16 | } 17 | 18 | export interface Meta { 19 | // 名称 20 | title: string 21 | // 是否固定在tab上 22 | affix?: boolean 23 | // tab上的图标 24 | icon?: string 25 | // 是否进入动画 26 | transition?: boolean 27 | keepAlive?: boolean 28 | } 29 | -------------------------------------------------------------------------------- /packages/apps/admin/src/store/index.ts: -------------------------------------------------------------------------------- 1 | import { createPinia } from 'pinia' 2 | import { App } from 'vue' 3 | 4 | export const store = createPinia() 5 | 6 | export function setupStore(app: App) { 7 | app.use(store) 8 | } 9 | -------------------------------------------------------------------------------- /packages/apps/admin/src/store/modules/setting.ts: -------------------------------------------------------------------------------- 1 | import { defineStore } from 'pinia' 2 | import { store } from '@/store' 3 | import { useDark } from '@vueuse/core' 4 | 5 | interface RootSettingState { 6 | rootTheme: string // 主题 7 | isOpenSetting: boolean // 是否打开设置 8 | isOpenSlider: boolean // 侧边栏 9 | isOpenFull: boolean // 全屏 10 | } 11 | 12 | export const useSettingStore = defineStore('app-root-setting', { 13 | state: (): RootSettingState => ({ 14 | rootTheme: 'dark', 15 | isOpenSetting: false, 16 | isOpenSlider: false, 17 | isOpenFull: false 18 | }), 19 | getters: { 20 | getRootTheme(): string { 21 | return this.rootTheme 22 | } 23 | }, 24 | actions: { 25 | // 设置主题 26 | setRootTheme(value: string): void { 27 | const isDark = useDark() 28 | isDark.value = value === 'dark' 29 | this.rootTheme = value 30 | } 31 | } 32 | }) 33 | 34 | export function useSettingStoreWithOut() { 35 | return useSettingStore(store) 36 | } 37 | -------------------------------------------------------------------------------- /packages/apps/admin/src/styles/base/element.scss: -------------------------------------------------------------------------------- 1 | @use '../mixin/config' as *; 2 | 3 | @forward 'element-plus/theme-chalk/src/mixins/config.scss' with ( 4 | $namespace: $namespace 5 | ); 6 | -------------------------------------------------------------------------------- /packages/apps/admin/src/styles/base/index.scss: -------------------------------------------------------------------------------- 1 | @use './reset.scss'; 2 | @use './normalize.scss'; 3 | -------------------------------------------------------------------------------- /packages/apps/admin/src/styles/global.scss: -------------------------------------------------------------------------------- 1 | // global 会被全局引用 可以写scss变量mixin 等 2 | // @use 'theme/index' as *; // 已废弃 3 | // 改变 element 的命名空间 4 | @use 'transition/index' as *; 5 | @use 'base/element'; 6 | -------------------------------------------------------------------------------- /packages/apps/admin/src/styles/index.scss: -------------------------------------------------------------------------------- 1 | // index会被全局引用但是不能写scss变量等需要未编译功能 如@mixin 2 | // 若需要定义公共变量需要到global.scss 3 | @use './base/index' as *; 4 | @use 'theme/var' as *; 5 | @use 'theme/dark' as *; 6 | // 导入dark变量 7 | @use 'element-plus/theme-chalk/src/dark/css-vars.scss'; 8 | // 按需引入弹出框样式 9 | @use 'element-plus/theme-chalk/src/message.scss'; 10 | @use 'element-plus/theme-chalk/src/dialog.scss'; 11 | @use 'element-plus/theme-chalk/src/message-box.scss'; 12 | -------------------------------------------------------------------------------- /packages/apps/admin/src/styles/mixin/config.scss: -------------------------------------------------------------------------------- 1 | $namespace: 'admin' !default; 2 | $common-separator: '-' !default; 3 | $element-separator: '__' !default; 4 | $modifier-separator: '--' !default; 5 | $state-prefix: 'is-' !default; 6 | -------------------------------------------------------------------------------- /packages/apps/admin/src/styles/theme/dark.scss: -------------------------------------------------------------------------------- 1 | @use 'sass:map'; 2 | 3 | // CSS3 var 4 | @use '../mixin/mixins' as *; 5 | @use 'dark/var' as *; 6 | @use 'dark/github-markdown-dark' as *; 7 | @use 'dark/prism-dark' as *; 8 | 9 | // common 10 | html.dark { 11 | @include set-component-css-var('text-color', $text-color); 12 | @include set-component-css-var('border-color', $border-color); 13 | @include set-component-css-var('bg-color', $bg-color); 14 | 15 | @include github-markdown-dark(); 16 | @include prism-dark(); 17 | } 18 | -------------------------------------------------------------------------------- /packages/apps/admin/src/styles/theme/dark/var.scss: -------------------------------------------------------------------------------- 1 | @use 'sass:map'; 2 | 3 | // text 4 | $text-color-base: #f0f5ff; 5 | $text-color: () !default; 6 | $text-color: map.merge( 7 | ( 8 | 'primary': rgba($text-color-base, 0.95), 9 | 'regular': rgba($text-color-base, 0.85), 10 | 'secondary': rgba($text-color-base, 0.65), 11 | 'placeholder': rgba($text-color-base, 0.55), 12 | 'disabled': rgba($text-color-base, 0.4) 13 | ), 14 | $text-color 15 | ); 16 | 17 | // border 18 | $border-color-base: #f5f8ff; 19 | $border-color: () !default; 20 | $border-color: map.merge( 21 | ( 22 | 'darker': rgba($border-color-base, 0.35), 23 | 'dark': rgba($border-color-base, 0.3), 24 | '': rgba($border-color-base, 0.25), 25 | 'light': rgba($border-color-base, 0.2), 26 | 'lighter': rgba($border-color-base, 0.15), 27 | 'extra-light': rgba($border-color-base, 0.1) 28 | ), 29 | $border-color 30 | ); 31 | 32 | // Background 33 | $bg-color: () !default; 34 | $bg-color: map.merge( 35 | ( 36 | '': #141414, 37 | 'main': #444a54 38 | ), 39 | $bg-color 40 | ); 41 | -------------------------------------------------------------------------------- /packages/apps/admin/src/styles/theme/default/var.scss: -------------------------------------------------------------------------------- 1 | @use 'sass:map'; 2 | 3 | $text-color: () !default; 4 | $text-color: map.merge( 5 | ( 6 | 'primary': #303133, 7 | 'regular': #606266, 8 | 'secondary': #909399, 9 | 'placeholder': #a8abb2, 10 | 'disabled': #c0c4cc 11 | ), 12 | $text-color 13 | ); 14 | 15 | $border-color: () !default; 16 | $border-color: map.merge( 17 | ( 18 | '': #dcdfe6, 19 | 'light': #e4e7ed, 20 | 'lighter': #ebeef5, 21 | 'extra-light': #f2f6fc, 22 | 'dark': #d4d7de, 23 | 'darker': #cdd0d6 24 | ), 25 | $border-color 26 | ); 27 | 28 | // Background 29 | $bg-color: () !default; 30 | $bg-color: map.merge( 31 | ( 32 | '': #ffffff, 33 | 'main': #e7eaef 34 | ), 35 | $bg-color 36 | ); 37 | -------------------------------------------------------------------------------- /packages/apps/admin/src/styles/theme/index.scss: -------------------------------------------------------------------------------- 1 | // 该文件废弃 改为css变量主题模式 2 | $theme-default: ( 3 | layout: ( 4 | background: red 5 | ) 6 | ); 7 | 8 | $themes: ( 9 | default: $theme-default 10 | ); 11 | 12 | $theme-map: null; 13 | 14 | // 第三步: 定义混合指令, 切换主题,并将主题中的所有规则添加到theme-map中 15 | @mixin themify() { 16 | @each $theme-name, $map in $themes { 17 | // & 表示父级元素 !global 表示覆盖原来的 18 | [data-theme='#{$theme-name}'] & { 19 | $theme-map: () !global; 20 | // 循环合并键值对 21 | @each $namespaces, $value in $map { 22 | $theme-map: map-merge( 23 | $theme-map, 24 | ( 25 | $namespaces: $value 26 | ) 27 | ) !global; 28 | } 29 | // 表示包含 下面函数 themed() 30 | @content; 31 | } 32 | } 33 | } 34 | 35 | @function themed($namespaces, $variety) { 36 | @return map-get(map-get($theme-map, $namespaces), $variety); 37 | } 38 | 39 | @mixin them-pick($key, $namespaces, $variety) { 40 | @include themify() { 41 | $key: themed($namespaces, $variety); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /packages/apps/admin/src/styles/theme/var.scss: -------------------------------------------------------------------------------- 1 | @use 'sass:map'; 2 | 3 | // CSS3 var 4 | @use '../mixin/mixins' as *; 5 | @use 'default/var' as *; 6 | @use 'default/github-markdown' as *; 7 | @use 'default/prism' as *; 8 | // common 9 | :root { 10 | @include github-markdown(); 11 | @include prism(); 12 | @include set-component-css-var('text-color', $text-color); 13 | @include set-component-css-var('border-color', $border-color); 14 | @include set-component-css-var('bg-color', $bg-color); 15 | 16 | @include set-css-var-value('font-weight-primary', 500); 17 | @include set-css-var-value('font-weight-bold', 700); 18 | 19 | @include set-css-var-value('low-z-index', -1); 20 | @include set-css-var-value('flat-z-index', 100); 21 | @include set-css-var-value('high-z-index', 100); 22 | @include set-css-var-value('top-z-index', 1000); 23 | 24 | // 默认text-color 25 | color: getCssVar('text-color', 'primary'); 26 | } 27 | -------------------------------------------------------------------------------- /packages/apps/admin/src/styles/transition/base.scss: -------------------------------------------------------------------------------- 1 | @mixin transition-default { 2 | &-enter-active, 3 | &-leave-active { 4 | transition: 0.3s cubic-bezier(0.25, 0.8, 0.5, 1) !important; 5 | } 6 | 7 | &-move { 8 | transition: transform 0.4s; 9 | } 10 | } 11 | 12 | .expand-transition { 13 | @include transition-default; 14 | } 15 | 16 | .expand-x-transition { 17 | @include transition-default; 18 | } 19 | -------------------------------------------------------------------------------- /packages/apps/admin/src/styles/transition/index.scss: -------------------------------------------------------------------------------- 1 | @use 'base' as *; 2 | @use 'fade'; 3 | @use 'scale'; 4 | @use 'slide'; 5 | @use 'scroll'; 6 | @use 'zoom'; 7 | 8 | .collapse-transition { 9 | transition: 10 | 0.2s height ease-in-out, 11 | 0.2s padding-top ease-in-out, 12 | 0.2s padding-bottom ease-in-out; 13 | } 14 | -------------------------------------------------------------------------------- /packages/apps/admin/src/styles/transition/scale.scss: -------------------------------------------------------------------------------- 1 | @use 'base' as *; 2 | 3 | .scale-transition { 4 | @include transition-default; 5 | 6 | &-enter-from, 7 | &-leave, 8 | &-leave-to { 9 | opacity: 0; 10 | transform: scale(0); 11 | } 12 | } 13 | 14 | .scale-rotate-transition { 15 | @include transition-default; 16 | 17 | &-enter-from, 18 | &-leave, 19 | &-leave-to { 20 | opacity: 0; 21 | transform: scale(0) rotate(-45deg); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /packages/apps/admin/src/styles/transition/scroll.scss: -------------------------------------------------------------------------------- 1 | @use 'base' as *; 2 | 3 | .scroll-y-transition { 4 | @include transition-default; 5 | 6 | &-enter-from, 7 | &-leave-to { 8 | opacity: 0; 9 | } 10 | 11 | &-enter-from { 12 | transform: translateY(-15px); 13 | } 14 | 15 | &-leave-to { 16 | transform: translateY(15px); 17 | } 18 | } 19 | 20 | .scroll-y-reverse-transition { 21 | @include transition-default; 22 | 23 | &-enter-from, 24 | &-leave-to { 25 | opacity: 0; 26 | } 27 | 28 | &-enter-from { 29 | transform: translateY(15px); 30 | } 31 | 32 | &-leave-to { 33 | transform: translateY(-15px); 34 | } 35 | } 36 | 37 | .scroll-x-transition { 38 | @include transition-default; 39 | 40 | &-enter-from, 41 | &-leave-to { 42 | opacity: 0; 43 | } 44 | 45 | &-enter-from { 46 | transform: translateX(-15px); 47 | } 48 | 49 | &-leave-to { 50 | transform: translateX(15px); 51 | } 52 | } 53 | 54 | .scroll-x-reverse-transition { 55 | @include transition-default; 56 | 57 | &-enter-from, 58 | &-leave-to { 59 | opacity: 0; 60 | } 61 | 62 | &-enter-from { 63 | transform: translateX(15px); 64 | } 65 | 66 | &-leave-to { 67 | transform: translateX(-15px); 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /packages/apps/admin/src/styles/transition/slide.scss: -------------------------------------------------------------------------------- 1 | @use 'base' as *; 2 | 3 | .slide-y-transition { 4 | @include transition-default; 5 | 6 | &-enter-from, 7 | &-leave-to { 8 | opacity: 0; 9 | transform: translateY(-15px); 10 | } 11 | } 12 | 13 | .slide-y-reverse-transition { 14 | @include transition-default; 15 | 16 | &-enter-from, 17 | &-leave-to { 18 | opacity: 0; 19 | transform: translateY(15px); 20 | } 21 | } 22 | 23 | .slide-x-transition { 24 | @include transition-default; 25 | 26 | &-enter-from, 27 | &-leave-to { 28 | opacity: 0; 29 | transform: translateX(-15px); 30 | } 31 | } 32 | 33 | .slide-x-reverse-transition { 34 | @include transition-default; 35 | 36 | &-enter-from, 37 | &-leave-to { 38 | opacity: 0; 39 | transform: translateX(15px); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /packages/apps/admin/src/styles/transition/zoom.scss: -------------------------------------------------------------------------------- 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.2s, 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/apps/admin/src/views/application/Application.vue: -------------------------------------------------------------------------------- 1 | 7 | 8 | 40 | -------------------------------------------------------------------------------- /packages/apps/admin/src/views/application/index.ts: -------------------------------------------------------------------------------- 1 | import AppProvider from './Application.vue' 2 | 3 | export { AppProvider } 4 | -------------------------------------------------------------------------------- /packages/apps/admin/src/views/application/useAppContext.ts: -------------------------------------------------------------------------------- 1 | import { InjectionKey, Ref } from 'vue' 2 | import { createContext, useContext } from '@tingcode/lib-vue' 3 | import { screenSizeEnum } from '@tingcode/system' 4 | 5 | export interface AppProviderContextProps { 6 | namespace: Ref 7 | screen: Ref 8 | width: Ref 9 | screenWidth: Ref 10 | isMobile: Ref 11 | } 12 | 13 | const key: InjectionKey = Symbol() 14 | 15 | export function createAppProviderContext(context: AppProviderContextProps) { 16 | return createContext(context, key as symbol) 17 | } 18 | 19 | export function useAppProviderContext() { 20 | return useContext(key as symbol) 21 | } 22 | -------------------------------------------------------------------------------- /packages/apps/admin/src/views/common/iframe/index.vue: -------------------------------------------------------------------------------- 1 | 6 | 45 | 46 | 60 | -------------------------------------------------------------------------------- /packages/apps/admin/src/views/common/login/components/matter/index.vue: -------------------------------------------------------------------------------- 1 | 4 | 5 | 40 | 41 | 52 | -------------------------------------------------------------------------------- /packages/apps/admin/src/views/common/login/components/nav/index.vue: -------------------------------------------------------------------------------- 1 | 14 | 15 | 23 | 24 | 49 | -------------------------------------------------------------------------------- /packages/apps/admin/src/views/common/login/components/rotation/microapp.vue: -------------------------------------------------------------------------------- 1 | 8 | 9 | 18 | 19 | 47 | -------------------------------------------------------------------------------- /packages/apps/admin/src/views/common/login/components/rotation/pnpm.vue: -------------------------------------------------------------------------------- 1 | 8 | 9 | 18 | 19 | 57 | -------------------------------------------------------------------------------- /packages/apps/admin/src/views/common/login/components/rotation/ts.vue: -------------------------------------------------------------------------------- 1 | 8 | 9 | 18 | 19 | 57 | -------------------------------------------------------------------------------- /packages/apps/admin/src/views/common/login/index.vue: -------------------------------------------------------------------------------- 1 | 10 | 11 | 23 | 24 | 41 | -------------------------------------------------------------------------------- /packages/apps/admin/src/views/common/redirect/index.vue: -------------------------------------------------------------------------------- 1 | 38 | -------------------------------------------------------------------------------- /packages/apps/admin/src/views/layouts/default/feature/index.vue: -------------------------------------------------------------------------------- 1 | 15 | 16 | 31 | 32 | 42 | -------------------------------------------------------------------------------- /packages/apps/admin/src/views/layouts/default/feature/setting/index.vue: -------------------------------------------------------------------------------- 1 | 15 | 16 | 25 | 26 | 33 | -------------------------------------------------------------------------------- /packages/apps/admin/src/views/layouts/default/feature/setting/theme/index.vue: -------------------------------------------------------------------------------- 1 | 5 | 6 | 16 | -------------------------------------------------------------------------------- /packages/apps/admin/src/views/layouts/default/header/setting/index.vue: -------------------------------------------------------------------------------- 1 | 4 | 5 | 14 | -------------------------------------------------------------------------------- /packages/apps/admin/src/views/layouts/default/header/trigger/index.vue: -------------------------------------------------------------------------------- 1 | 9 | 10 | 20 | 21 | 28 | -------------------------------------------------------------------------------- /packages/apps/admin/src/views/layouts/default/main/index.vue: -------------------------------------------------------------------------------- 1 | 19 | 20 | 31 | 32 | 39 | -------------------------------------------------------------------------------- /packages/apps/admin/src/views/layouts/default/navIcon/index.vue: -------------------------------------------------------------------------------- 1 | 20 | 21 | 35 | 36 | 46 | -------------------------------------------------------------------------------- /packages/apps/admin/src/views/layouts/default/tabs/full/index.vue: -------------------------------------------------------------------------------- 1 | 4 | 5 | 13 | -------------------------------------------------------------------------------- /packages/apps/admin/src/views/layouts/default/tabs/set/index.vue: -------------------------------------------------------------------------------- 1 | 20 | 21 | 31 | -------------------------------------------------------------------------------- /packages/apps/admin/src/views/layouts/default/theme/index.vue: -------------------------------------------------------------------------------- 1 | 5 | 6 | 22 | -------------------------------------------------------------------------------- /packages/apps/admin/src/views/layouts/micro/index.vue: -------------------------------------------------------------------------------- 1 | 10 | 11 | 15 | 16 | 25 | -------------------------------------------------------------------------------- /packages/apps/admin/src/views/layouts/parentLayout/index.vue: -------------------------------------------------------------------------------- 1 | 4 | 5 | 13 | -------------------------------------------------------------------------------- /packages/apps/admin/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "@config/tsconfig/base.json", 3 | "compilerOptions": { 4 | "target": "esnext", 5 | "module": "esnext", 6 | "baseUrl": ".", 7 | "paths": { 8 | "@/*": ["src/*"], 9 | "@s/*": ["src/styles/*"] 10 | }, 11 | "lib": ["dom", "esnext"], 12 | "types": ["vite/client"] 13 | }, 14 | "include": [ 15 | "src", 16 | "mock", 17 | "vite.config.ts", 18 | "src/**/*.ts", 19 | "src/**/*.d.ts", 20 | "src/**/*.tsx", 21 | "src/**/*.vue" 22 | ] 23 | } 24 | -------------------------------------------------------------------------------- /packages/apps/micro-demo/.env.development: -------------------------------------------------------------------------------- 1 | # just a flag 2 | ENV = 'development' -------------------------------------------------------------------------------- /packages/apps/micro-demo/.env.production: -------------------------------------------------------------------------------- 1 | # just a flag 2 | ENV = 'production' -------------------------------------------------------------------------------- /packages/apps/micro-demo/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Rspack + React 7 | 8 | 9 |
10 | 11 | 12 | -------------------------------------------------------------------------------- /packages/apps/micro-demo/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@apps/micro-demo", 3 | "private": true, 4 | "version": "0.0.1", 5 | "scripts": { 6 | "dev": "rspack serve", 7 | "build": "rspack build", 8 | "lint:eslint": "eslint . --cache --max-warnings 0 --fix --ignore-path=../../../.eslintignore", 9 | "lint:prettier": "prettier --write --cache --ignore-unknown --ignore-path=../../../.prettierignore ." 10 | }, 11 | "dependencies": { 12 | "react": "^18.2.0", 13 | "react-dom": "^18.2.0", 14 | "react-router-dom": "^6.9.0" 15 | }, 16 | "devDependencies": { 17 | "@config/tsconfig": "workspace:*", 18 | "@react-spring/web": "^9.7.1", 19 | "@rspack/cli": "1.0.0-rc.1", 20 | "@rspack/core": "1.0.0-rc.1", 21 | "@rspack/plugin-react-refresh": "1.0.0", 22 | "@types/node": "^20.4.4", 23 | "@types/react": "^18.2.48", 24 | "@types/react-dom": "^18.2.18", 25 | "autoprefixer": "^10.4.14", 26 | "classnames": "^2.3.2", 27 | "css-loader": "^7.1.2", 28 | "less": "^4.1.3", 29 | "less-loader": "^11.1.0", 30 | "postcss": "^8.4.12", 31 | "postcss-loader": "^7.1.0", 32 | "react-refresh": "^0.14.2", 33 | "tailwindcss": "^3.2.7", 34 | "typescript": "catalog:" 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /packages/apps/micro-demo/src/components/application/inedx.tsx: -------------------------------------------------------------------------------- 1 | import React, { FC, ReactNode } from 'react' 2 | 3 | const Application: FC<{ children: ReactNode }> = ({ children }) => { 4 | return <>{children} 5 | } 6 | 7 | export { Application } 8 | -------------------------------------------------------------------------------- /packages/apps/micro-demo/src/components/layout/index.tsx: -------------------------------------------------------------------------------- 1 | import { TransitionLayout } from '@/components/layout/transition-layout' 2 | 3 | const Layout = () => { 4 | return ( 5 |
6 | Home 7 |
8 |
asdasd
9 |
{}
10 |
11 |
12 | ) 13 | } 14 | 15 | export { Layout } 16 | -------------------------------------------------------------------------------- /packages/apps/micro-demo/src/components/layout/transition-layout/index.tsx: -------------------------------------------------------------------------------- 1 | import { animated, useTransition } from '@react-spring/web' 2 | import type { ReactNode } from 'react' 3 | import React, { useRef } from 'react' 4 | import { useLocation, useOutlet } from 'react-router-dom' 5 | 6 | export const TransitionLayout: React.FC = () => { 7 | const map = useRef>({}) 8 | const location = useLocation() 9 | const outlet = useOutlet() 10 | map.current[location.pathname] = outlet 11 | const transitions = useTransition(location.pathname, { 12 | from: { transform: 'translateX(100%)' }, 13 | enter: { transform: 'translateX(0%)' }, 14 | leave: { transform: 'translateX(-100%)' }, 15 | config: { duration: 300 } 16 | }) 17 | return transitions((style, pathname) => { 18 | return ( 19 | 20 | {map.current[location.pathname]} 21 | 22 | ) 23 | }) 24 | } 25 | -------------------------------------------------------------------------------- /packages/apps/micro-demo/src/main.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import ReactDOM from 'react-dom/client' 3 | import { Application } from '@/components/application/inedx' 4 | import '@/style/index.less' 5 | import('@/style/test.less') 6 | import { RouterProvider } from 'react-router-dom' 7 | import { router } from '@/router' 8 | 9 | const rootElement = document.getElementById('rspack') as HTMLElement 10 | let rspack: ReactDOM.Root 11 | 12 | window.mount = () => { 13 | rspack = ReactDOM.createRoot(rootElement) 14 | rspack.render( 15 | 16 | 17 | 18 | ) 19 | } 20 | 21 | window.unmount = () => { 22 | rspack.unmount() 23 | } 24 | // 如果不在微前端环境,则直接执行mount渲染 25 | if (!window.__MICRO_APP_ENVIRONMENT__) { 26 | window.mount() 27 | } 28 | -------------------------------------------------------------------------------- /packages/apps/micro-demo/src/router/baseRouters.tsx: -------------------------------------------------------------------------------- 1 | import { Navigate, RouteObject, Link } from 'react-router-dom' 2 | import { Layout } from '@/components/layout' 3 | import { ErrorPage } from '@/views/common/error' 4 | import { microRouters } from './modules/micro' 5 | import React from 'react' 6 | 7 | export const routers: RouteObject[] = [ 8 | ...microRouters, 9 | { 10 | path: '/', 11 | element: , 12 | errorElement: 13 | }, 14 | { 15 | path: '/layout', 16 | element: , 17 | errorElement: , 18 | children: [ 19 | { path: 'home', element: 跳转到路径 }, 20 | { path: 'open', element:
Hello open!
}, 21 | { index: true, element: } 22 | ] 23 | } 24 | ] 25 | -------------------------------------------------------------------------------- /packages/apps/micro-demo/src/router/index.tsx: -------------------------------------------------------------------------------- 1 | import { createBrowserRouter } from 'react-router-dom' 2 | import { routers } from '@/router/baseRouters' 3 | import { isProdMode } from '@/utils/env' 4 | 5 | export const router: any = createBrowserRouter(routers, { 6 | basename: isProdMode() ? '/micro/demo' : '' 7 | }) 8 | -------------------------------------------------------------------------------- /packages/apps/micro-demo/src/router/modules/micro.tsx: -------------------------------------------------------------------------------- 1 | import { RouteObject } from 'react-router-dom' 2 | import { ErrorPage } from '@/views/common/error' 3 | import React, { lazy, Suspense } from 'react' 4 | const MicroAppDemo = lazy(() => import('@/views/micro/micro-app-demo/index')) 5 | export const microRouters: RouteObject[] = [ 6 | { 7 | path: '/microAppDemo', 8 | element: ( 9 | 10 | 11 | 12 | ), 13 | errorElement: 14 | } 15 | ] 16 | -------------------------------------------------------------------------------- /packages/apps/micro-demo/src/style/index.less: -------------------------------------------------------------------------------- 1 | @tailwind base; 2 | @tailwind components; 3 | @tailwind utilities; 4 | -------------------------------------------------------------------------------- /packages/apps/micro-demo/src/style/test.less: -------------------------------------------------------------------------------- 1 | .test { 2 | display: flex; 3 | } 4 | .app_test_created_tin { 5 | color: #0a3069; 6 | } 7 | -------------------------------------------------------------------------------- /packages/apps/micro-demo/src/types/global.d.ts: -------------------------------------------------------------------------------- 1 | declare global { 2 | namespace NodeJS { 3 | declare interface ProcessEnv { 4 | NODE_ENV: 'development' | 'production' | 'test' 5 | [key: string]: string | undefined 6 | } 7 | } 8 | } 9 | 10 | interface Window { 11 | unmount: () => void 12 | mount: () => void 13 | __MICRO_APP_ENVIRONMENT__: boolean 14 | } 15 | 16 | interface Process { 17 | NODE_ENV: 'development' | 'production' | 'test' 18 | [key: string]: string | undefined 19 | } 20 | -------------------------------------------------------------------------------- /packages/apps/micro-demo/src/types/module.d.ts: -------------------------------------------------------------------------------- 1 | declare module '*.scss' { 2 | const classes: { [key: string]: string } 3 | export default classes 4 | } 5 | declare module '*.less' { 6 | const classes: { [key: string]: string } 7 | export default classes 8 | } 9 | 10 | declare module '*.css' { 11 | const classes: { [key: string]: string } 12 | export default classes 13 | } 14 | 15 | declare interface ProcessEnv { 16 | NODE_ENV: 'development' | 'production' | 'test' 17 | [key: string]: string | undefined 18 | } 19 | -------------------------------------------------------------------------------- /packages/apps/micro-demo/src/utils/env.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * @description: Development model 3 | */ 4 | export const devMode = 'development' 5 | 6 | /** 7 | * @description: Production mode 8 | */ 9 | export const prodMode = 'production' 10 | 11 | /** 12 | * @description: Get environment variables 13 | */ 14 | 15 | export function getEnv(): string | undefined { 16 | return process.env.NODE_ENV 17 | } 18 | 19 | /** 20 | * @description: Is it a development mode 21 | * @returns: 22 | * @example: 23 | */ 24 | export function isDevMode(): boolean { 25 | return process.env.NODE_ENV === devMode 26 | } 27 | 28 | /** 29 | * @description: Is it a production mode 30 | * @returns: 31 | * @example: 32 | */ 33 | export function isProdMode(): boolean { 34 | return process.env.NODE_ENV === prodMode 35 | } 36 | -------------------------------------------------------------------------------- /packages/apps/micro-demo/src/views/common/error/index.tsx: -------------------------------------------------------------------------------- 1 | import s from './index.module.css' 2 | const ErrorPage = () => { 3 | return ( 4 | <> 5 |
6 |
7 |

8 | 404 9 |

10 |

11 | NOT FOUND 12 |

13 |
14 |
15 |
16 | 17 | ) 18 | } 19 | 20 | export { ErrorPage } 21 | -------------------------------------------------------------------------------- /packages/apps/micro-demo/src/views/micro/micro-app-demo/index.tsx: -------------------------------------------------------------------------------- 1 | const MicroAppDemo = () => { 2 | return ( 3 | <> 4 |
16 |

这里是Rspack搭建的React子项目2

17 |
18 | 19 | ) 20 | } 21 | 22 | export default MicroAppDemo 23 | -------------------------------------------------------------------------------- /packages/apps/micro-demo/tailwind.config.js: -------------------------------------------------------------------------------- 1 | /** @type {import('tailwindcss').Config} */ 2 | module.exports = { 3 | content: ['./**/*.{html,js}'], 4 | theme: { 5 | extend: {} 6 | }, 7 | plugins: [] 8 | } 9 | -------------------------------------------------------------------------------- /packages/apps/micro-demo/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "@config/tsconfig/base.json", 3 | "compilerOptions": { 4 | "target": "esnext", 5 | "module": "esnext", 6 | "baseUrl": ".", 7 | "paths": { 8 | "@/*": ["src/*"] 9 | }, 10 | "lib": ["dom", "esnext"], 11 | "types": ["node", "./node_modules/@types"], 12 | "isolatedModules": true, 13 | "allowSyntheticDefaultImports": true, 14 | "typeRoots": ["./node_modules/@types", "./src/types"] 15 | }, 16 | "include": ["src", "mock", "@/types/module.d.ts"], 17 | "ts-node": { 18 | "compilerOptions": { 19 | "module": "CommonJS" 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /packages/apps/micro-docs/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 10 | Ting Library 11 | 12 | 13 |
14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /packages/apps/micro-docs/postcss.config.cjs: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | plugins: { 3 | tailwindcss: {}, 4 | autoprefixer: {} 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /packages/apps/micro-docs/src/App.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 10 | -------------------------------------------------------------------------------- /packages/apps/micro-docs/src/application/Application.vue: -------------------------------------------------------------------------------- 1 | 7 | 8 | 45 | -------------------------------------------------------------------------------- /packages/apps/micro-docs/src/application/index.ts: -------------------------------------------------------------------------------- 1 | import AppProvider from './Application.vue' 2 | 3 | export { AppProvider } 4 | -------------------------------------------------------------------------------- /packages/apps/micro-docs/src/application/useAppContext.ts: -------------------------------------------------------------------------------- 1 | import { InjectionKey, Ref } from 'vue' 2 | import { createContext, useContext } from '@tingcode/lib-vue' 3 | import { screenSizeEnum } from '@tingcode/system' 4 | 5 | export interface AppProviderContextProps { 6 | namespace: Ref 7 | screen: Ref 8 | width: Ref 9 | screenWidth: Ref 10 | isMobile: Ref 11 | } 12 | 13 | const key: InjectionKey = Symbol() 14 | 15 | export function createAppProviderContext(context: AppProviderContextProps) { 16 | return createContext(context, key) 17 | } 18 | 19 | export function useAppProviderContext() { 20 | return useContext(key) 21 | } 22 | -------------------------------------------------------------------------------- /packages/apps/micro-docs/src/components/code-block/sound-path-once.vue: -------------------------------------------------------------------------------- 1 | 9 | 10 | 30 | 31 | 42 | -------------------------------------------------------------------------------- /packages/apps/micro-docs/src/components/icon/svg-icon.vue: -------------------------------------------------------------------------------- 1 | 10 | 11 | 38 | 39 | 63 | -------------------------------------------------------------------------------- /packages/apps/micro-docs/src/components/markdown/index.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 12 | -------------------------------------------------------------------------------- /packages/apps/micro-docs/src/directives/auth.ts: -------------------------------------------------------------------------------- 1 | import { ObjectDirective, App } from 'vue' 2 | import { isArray, isObject, isString } from '@tingcode/utils' 3 | import { hasAuth } from '@tingcode/system' 4 | 5 | const accessesVerified = (value: string | string[] | unknown) => { 6 | if (isString(value)) { 7 | return [value] 8 | } 9 | if (isArray(value)) { 10 | return value 11 | } 12 | throw new Error(`[v-auth]: ${value} auth 不是字符串或数组!`) 13 | } 14 | 15 | export interface IAuthObject { 16 | disabled?: boolean 17 | auth?: string | string[] 18 | } 19 | 20 | export const auth: ObjectDirective = { 21 | mounted(el, binding) { 22 | const value = binding.value 23 | let disabled = false 24 | let accesses: string[] = [] 25 | if (isObject(value)) { 26 | disabled = !!value.disabled 27 | accesses = accessesVerified(value?.auth) 28 | } else { 29 | accesses = accessesVerified(value) 30 | } 31 | if (!hasAuth(accesses)) { 32 | if (disabled) { 33 | el.disabled = true 34 | el.style['disabled'] = 'disabled' 35 | } else { 36 | // 异步销毁会出现闪屏现象 display: none会先隐藏避免闪屏 37 | el.style['display'] = 'none' 38 | // 由于某些组件用到了css v-bind 如果挂载的时候销毁Dom就会报错 所以需要异步销毁 39 | setTimeout(() => { 40 | el.parentNode?.removeChild(el) 41 | }, 0) 42 | } 43 | } 44 | } 45 | } 46 | 47 | export function setupAuthDirective(app: App) { 48 | app.directive('auth', auth) 49 | } 50 | -------------------------------------------------------------------------------- /packages/apps/micro-docs/src/directives/index.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Configure and register global directives 3 | * 统一注册vue自定义指令 4 | */ 5 | import type { App } from 'vue' 6 | import { setupAuthDirective } from './auth' 7 | 8 | export function setupGlobDirectives(app: App) { 9 | setupAuthDirective(app) 10 | } 11 | -------------------------------------------------------------------------------- /packages/apps/micro-docs/src/main.ts: -------------------------------------------------------------------------------- 1 | import '@s/index.scss' 2 | import '@tingcode/lib-vue/dist/css/components/index.css' 3 | import { createApp, App } from 'vue' 4 | import AppVue from './App.vue' 5 | import { setupStore } from '@/store' 6 | import { unmountRouter, setupRouter } from '@/router' 7 | import { setupGlobDirectives } from '@/directives' 8 | import * as EPIcon from '@element-plus/icons-vue' 9 | import { initDocsMicroApp, initNamespace } from '@tingcode/system' 10 | import { NAMESPACE } from '@/hooks/useSetting' 11 | import { graphRegisterNodes } from '@/hooks/useX6' 12 | initDocsMicroApp() 13 | graphRegisterNodes() 14 | let app: App 15 | 16 | window.mount = () => { 17 | initNamespace(NAMESPACE) 18 | app = createApp(AppVue) 19 | setupRouter(app) 20 | setupStore(app) 21 | setupGlobDirectives(app) 22 | app.mount('#docs') 23 | } 24 | 25 | window.unmount = () => { 26 | app.unmount() 27 | unmountRouter() 28 | } 29 | 30 | // 如果不在微前端环境,则直接执行mount渲染 31 | if (!window.__MICRO_APP_ENVIRONMENT__) { 32 | window.mount() 33 | } 34 | 35 | export { EPIcon } 36 | -------------------------------------------------------------------------------- /packages/apps/micro-docs/src/router/modules/basics.ts: -------------------------------------------------------------------------------- 1 | import { RouteRecordRaw } from 'vue-router' 2 | 3 | /** 4 | * @param name 路由名称, 必须设置,且不能重名 5 | * @param meta 路由元信息(路由附带扩展信息) 6 | * @param redirect 重定向地址, 访问这个路由时,自定进行重定向 7 | * @param meta.disabled 禁用整个菜单 8 | * @param meta.title 菜单名称 9 | * @param meta.icon 菜单图标 10 | * @param meta.keepAlive 缓存该路由 11 | * 12 | * */ 13 | const routes: Array = [ 14 | { 15 | path: '/basics/git', 16 | name: 'basics_git', 17 | component: () => import('@/views/basics/git/index.docs.vue') 18 | }, 19 | { 20 | path: '/basics/node', 21 | name: 'basics_node', 22 | component: () => import('@/views/basics/node/index.docs.vue') 23 | }, 24 | { 25 | path: '/basics/docker', 26 | name: 'basics_docker', 27 | component: () => import('@/views/basics/docker/index.docs.vue') 28 | }, 29 | { 30 | path: '/basics/linux', 31 | name: 'basics_linux', 32 | component: () => import('@/views/basics/linux/index.docs.vue') 33 | }, 34 | { 35 | path: '/basics/network', 36 | name: 'basics_network', 37 | component: () => import('@/views/basics/network/index.docs.vue') 38 | } 39 | ] 40 | 41 | export default routes 42 | -------------------------------------------------------------------------------- /packages/apps/micro-docs/src/router/modules/performance.ts: -------------------------------------------------------------------------------- 1 | import { RouteRecordRaw } from 'vue-router' 2 | 3 | /** 4 | * @param name 路由名称, 必须设置,且不能重名 5 | * @param meta 路由元信息(路由附带扩展信息) 6 | * @param redirect 重定向地址, 访问这个路由时,自定进行重定向 7 | * @param meta.disabled 禁用整个菜单 8 | * @param meta.title 菜单名称 9 | * @param meta.icon 菜单图标 10 | * @param meta.keepAlive 缓存该路由 11 | * 12 | * */ 13 | const routes: Array = [ 14 | { 15 | path: '/performance/optimization', 16 | name: 'performance_optimization', 17 | component: () => import('@/views/performance/optimization/index.docs.vue') 18 | }, 19 | { 20 | path: '/performance/virtual-scroll', 21 | name: 'performance_virtual_scroll', 22 | component: () => import('@/views/performance/virtual-scroll/index.docs.vue') 23 | } 24 | ] 25 | 26 | export default routes 27 | -------------------------------------------------------------------------------- /packages/apps/micro-docs/src/router/modules/repackage.ts: -------------------------------------------------------------------------------- 1 | import { RouteRecordRaw } from 'vue-router' 2 | 3 | /** 4 | * @param name 路由名称, 必须设置,且不能重名 5 | * @param meta 路由元信息(路由附带扩展信息) 6 | * @param redirect 重定向地址, 访问这个路由时,自定进行重定向 7 | * @param meta.disabled 禁用整个菜单 8 | * @param meta.title 菜单名称 9 | * @param meta.icon 菜单图标 10 | * @param meta.keepAlive 缓存该路由 11 | * 12 | * */ 13 | const routes: Array = [ 14 | { 15 | path: '/repackage/components', 16 | name: 'repackage_components', 17 | component: () => import('@/views/repackage/components/index.docs.vue') 18 | }, 19 | { 20 | path: '/repackage/low-code', 21 | name: 'repackage_low_code', 22 | component: () => import('@/views/repackage/low-code/index.docs.vue') 23 | } 24 | ] 25 | 26 | export default routes 27 | -------------------------------------------------------------------------------- /packages/apps/micro-docs/src/router/modules/visual.ts: -------------------------------------------------------------------------------- 1 | import { RouteRecordRaw } from 'vue-router' 2 | 3 | /** 4 | * @param name 路由名称, 必须设置,且不能重名 5 | * @param meta 路由元信息(路由附带扩展信息) 6 | * @param redirect 重定向地址, 访问这个路由时,自定进行重定向 7 | * @param meta.disabled 禁用整个菜单 8 | * @param meta.title 菜单名称 9 | * @param meta.icon 菜单图标 10 | * @param meta.keepAlive 缓存该路由 11 | * 12 | * */ 13 | const routes: Array = [ 14 | { 15 | path: '/visual/chart', 16 | name: 'visual_chart', 17 | component: () => import('@/views/visual/chart/index.docs.vue') 18 | }, 19 | { 20 | path: '/visual/flow', 21 | name: 'visual_flow', 22 | component: () => import('@/views/visual/flow/index.vue') 23 | }, 24 | { 25 | path: '/visual/animation', 26 | name: 'visual_animation', 27 | component: () => import('@/views/visual/animation/index.docs.vue') 28 | } 29 | ] 30 | 31 | export default routes 32 | -------------------------------------------------------------------------------- /packages/apps/micro-docs/src/store/index.ts: -------------------------------------------------------------------------------- 1 | import { createPinia } from 'pinia' 2 | import { App } from 'vue' 3 | 4 | export const store = createPinia() 5 | 6 | export function setupStore(app: App) { 7 | app.use(store) 8 | } 9 | -------------------------------------------------------------------------------- /packages/apps/micro-docs/src/store/modules/setting.ts: -------------------------------------------------------------------------------- 1 | import { defineStore } from 'pinia' 2 | import { store } from '@/store' 3 | import { useDark } from '@vueuse/core' 4 | 5 | interface RootSettingState { 6 | rootTheme: string // 主题 7 | isOpenSetting: boolean // 是否打开设置 8 | isOpenSlider: boolean // 侧边栏 9 | isOpenFull: boolean // 全屏 10 | } 11 | 12 | export const useSettingStore = defineStore('app-root-setting', { 13 | state: (): RootSettingState => ({ 14 | rootTheme: 'dark', 15 | isOpenSetting: false, 16 | isOpenSlider: false, 17 | isOpenFull: false 18 | }), 19 | getters: { 20 | getRootTheme(): string { 21 | return this.rootTheme 22 | } 23 | }, 24 | actions: { 25 | // 设置主题 26 | setRootTheme(value: string): void { 27 | const isDark = useDark() 28 | isDark.value = value === 'dark' 29 | this.rootTheme = value 30 | } 31 | } 32 | }) 33 | 34 | export function useSettingStoreWithOut() { 35 | return useSettingStore(store) 36 | } 37 | -------------------------------------------------------------------------------- /packages/apps/micro-docs/src/styles/base/element.scss: -------------------------------------------------------------------------------- 1 | @use '../mixin/config' as *; 2 | 3 | @forward 'element-plus/theme-chalk/src/mixins/config.scss' with ( 4 | $namespace: $namespace 5 | ); 6 | -------------------------------------------------------------------------------- /packages/apps/micro-docs/src/styles/base/index.scss: -------------------------------------------------------------------------------- 1 | @use './reset.scss'; 2 | @use './normalize.scss'; 3 | -------------------------------------------------------------------------------- /packages/apps/micro-docs/src/styles/global.scss: -------------------------------------------------------------------------------- 1 | // global 会被全局引用 可以写scss变量mixin 等 2 | // @use 'theme/index' as *; // 已废弃 3 | // 改变 element 的命名空间 4 | @use 'transition/index' as *; 5 | @use 'base/element'; 6 | -------------------------------------------------------------------------------- /packages/apps/micro-docs/src/styles/index.scss: -------------------------------------------------------------------------------- 1 | // index会被全局引用但是不能写scss变量等需要未编译功能 如@mixin 2 | // 若需要定义公共变量需要到global.scss 3 | @use './base/index' as *; 4 | @use 'theme/var' as *; 5 | @use 'theme/dark' as *; 6 | // 导入dark变量 7 | @use 'element-plus/theme-chalk/src/dark/css-vars.scss'; 8 | // 按需引入弹出框样式 9 | @use 'element-plus/theme-chalk/src/message.scss'; 10 | @use 'element-plus/theme-chalk/src/dialog.scss'; 11 | @use 'element-plus/theme-chalk/src/button.scss'; 12 | @use 'element-plus/theme-chalk/src/input.scss'; 13 | @use 'element-plus/theme-chalk/src/radio.scss'; 14 | @use 'element-plus/theme-chalk/src/radio-button.scss'; 15 | @use 'element-plus/theme-chalk/src/radio-group.scss'; 16 | @use 'element-plus/theme-chalk/src/select.scss'; 17 | @use 'element-plus/theme-chalk/src/checkbox.scss'; 18 | @use 'element-plus/theme-chalk/src/checkbox-button.scss'; 19 | @use 'element-plus/theme-chalk/src/checkbox-group.scss'; 20 | 21 | @tailwind base; 22 | @tailwind components; 23 | @tailwind utilities; 24 | -------------------------------------------------------------------------------- /packages/apps/micro-docs/src/styles/mixin/config.scss: -------------------------------------------------------------------------------- 1 | $namespace: 'docs' !default; 2 | $common-separator: '-' !default; 3 | $element-separator: '__' !default; 4 | $modifier-separator: '--' !default; 5 | $state-prefix: 'is-' !default; 6 | -------------------------------------------------------------------------------- /packages/apps/micro-docs/src/styles/theme/dark.scss: -------------------------------------------------------------------------------- 1 | @use 'sass:map'; 2 | 3 | // CSS3 var 4 | @use '../mixin/mixins' as *; 5 | @use 'dark/var' as *; 6 | @use 'dark/github-markdown-dark' as *; 7 | @use 'dark/prism-dark' as *; 8 | 9 | // common 10 | html.dark { 11 | @include set-component-css-var('text-color', $text-color); 12 | @include set-component-css-var('border-color', $border-color); 13 | @include set-component-css-var('bg-color', $bg-color); 14 | 15 | @include github-markdown-dark(); 16 | @include prism-dark(); 17 | } 18 | -------------------------------------------------------------------------------- /packages/apps/micro-docs/src/styles/theme/dark/var.scss: -------------------------------------------------------------------------------- 1 | @use 'sass:map'; 2 | 3 | // text 4 | $text-color-base: #f0f5ff; 5 | $text-color: () !default; 6 | $text-color: map.merge( 7 | ( 8 | 'primary': rgba($text-color-base, 0.95), 9 | 'regular': rgba($text-color-base, 0.85), 10 | 'secondary': rgba($text-color-base, 0.65), 11 | 'placeholder': rgba($text-color-base, 0.55), 12 | 'disabled': rgba($text-color-base, 0.4) 13 | ), 14 | $text-color 15 | ); 16 | 17 | // border 18 | $border-color-base: #f5f8ff; 19 | $border-color: () !default; 20 | $border-color: map.merge( 21 | ( 22 | 'darker': rgba($border-color-base, 0.35), 23 | 'dark': rgba($border-color-base, 0.3), 24 | '': rgba($border-color-base, 0.25), 25 | 'light': rgba($border-color-base, 0.2), 26 | 'lighter': rgba($border-color-base, 0.15), 27 | 'extra-light': rgba($border-color-base, 0.1) 28 | ), 29 | $border-color 30 | ); 31 | 32 | // Background 33 | $bg-color: () !default; 34 | $bg-color: map.merge( 35 | ( 36 | '': #141414, 37 | 'main': #444a54 38 | ), 39 | $bg-color 40 | ); 41 | -------------------------------------------------------------------------------- /packages/apps/micro-docs/src/styles/theme/default/var.scss: -------------------------------------------------------------------------------- 1 | @use 'sass:map'; 2 | 3 | $text-color: () !default; 4 | $text-color: map.merge( 5 | ( 6 | 'primary': #303133, 7 | 'regular': #606266, 8 | 'secondary': #909399, 9 | 'placeholder': #a8abb2, 10 | 'disabled': #c0c4cc 11 | ), 12 | $text-color 13 | ); 14 | 15 | $border-color: () !default; 16 | $border-color: map.merge( 17 | ( 18 | '': #dcdfe6, 19 | 'light': #e4e7ed, 20 | 'lighter': #ebeef5, 21 | 'extra-light': #f2f6fc, 22 | 'dark': #d4d7de, 23 | 'darker': #cdd0d6 24 | ), 25 | $border-color 26 | ); 27 | 28 | // Background 29 | $bg-color: () !default; 30 | $bg-color: map.merge( 31 | ( 32 | '': #ffffff, 33 | 'main': #e7eaef 34 | ), 35 | $bg-color 36 | ); 37 | -------------------------------------------------------------------------------- /packages/apps/micro-docs/src/styles/theme/index.scss: -------------------------------------------------------------------------------- 1 | // 该文件废弃 改为css变量主题模式 2 | $theme-default: ( 3 | layout: ( 4 | background: red 5 | ) 6 | ); 7 | 8 | $themes: ( 9 | default: $theme-default 10 | ); 11 | 12 | $theme-map: null; 13 | 14 | // 第三步: 定义混合指令, 切换主题,并将主题中的所有规则添加到theme-map中 15 | @mixin themify() { 16 | @each $theme-name, $map in $themes { 17 | // & 表示父级元素 !global 表示覆盖原来的 18 | [data-theme='#{$theme-name}'] & { 19 | $theme-map: () !global; 20 | // 循环合并键值对 21 | @each $namespaces, $value in $map { 22 | $theme-map: map-merge( 23 | $theme-map, 24 | ( 25 | $namespaces: $value 26 | ) 27 | ) !global; 28 | } 29 | // 表示包含 下面函数 themed() 30 | @content; 31 | } 32 | } 33 | } 34 | 35 | @function themed($namespaces, $variety) { 36 | @return map-get(map-get($theme-map, $namespaces), $variety); 37 | } 38 | 39 | @mixin them-pick($key, $namespaces, $variety) { 40 | @include themify() { 41 | $key: themed($namespaces, $variety); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /packages/apps/micro-docs/src/styles/theme/var.scss: -------------------------------------------------------------------------------- 1 | @use 'sass:map'; 2 | 3 | // CSS3 var 4 | @use '../mixin/mixins' as *; 5 | @use 'default/var' as *; 6 | @use 'default/github-markdown' as *; 7 | @use 'default/prism' as *; 8 | // common 9 | :root { 10 | @include github-markdown(); 11 | @include prism(); 12 | @include set-component-css-var('text-color', $text-color); 13 | @include set-component-css-var('border-color', $border-color); 14 | @include set-component-css-var('bg-color', $bg-color); 15 | 16 | @include set-css-var-value('font-weight-primary', 500); 17 | @include set-css-var-value('font-weight-bold', 700); 18 | 19 | @include set-css-var-value('low-z-index', -1); 20 | @include set-css-var-value('flat-z-index', 100); 21 | @include set-css-var-value('high-z-index', 100); 22 | @include set-css-var-value('top-z-index', 1000); 23 | 24 | // 默认text-color 25 | color: getCssVar('text-color', 'primary'); 26 | } 27 | -------------------------------------------------------------------------------- /packages/apps/micro-docs/src/styles/transition/base.scss: -------------------------------------------------------------------------------- 1 | @mixin transition-default { 2 | &-enter-active, 3 | &-leave-active { 4 | transition: 0.3s cubic-bezier(0.25, 0.8, 0.5, 1) !important; 5 | } 6 | 7 | &-move { 8 | transition: transform 0.4s; 9 | } 10 | } 11 | 12 | .expand-transition { 13 | @include transition-default; 14 | } 15 | 16 | .expand-x-transition { 17 | @include transition-default; 18 | } 19 | -------------------------------------------------------------------------------- /packages/apps/micro-docs/src/styles/transition/index.scss: -------------------------------------------------------------------------------- 1 | @use 'base' as *; 2 | @use 'fade'; 3 | @use 'scale'; 4 | @use 'slide'; 5 | @use 'scroll'; 6 | @use 'zoom'; 7 | 8 | .collapse-transition { 9 | transition: 10 | 0.2s height ease-in-out, 11 | 0.2s padding-top ease-in-out, 12 | 0.2s padding-bottom ease-in-out; 13 | } 14 | -------------------------------------------------------------------------------- /packages/apps/micro-docs/src/styles/transition/scale.scss: -------------------------------------------------------------------------------- 1 | @use 'base' as *; 2 | 3 | .scale-transition { 4 | @include transition-default; 5 | 6 | &-enter-from, 7 | &-leave, 8 | &-leave-to { 9 | opacity: 0; 10 | transform: scale(0); 11 | } 12 | } 13 | 14 | .scale-rotate-transition { 15 | @include transition-default; 16 | 17 | &-enter-from, 18 | &-leave, 19 | &-leave-to { 20 | opacity: 0; 21 | transform: scale(0) rotate(-45deg); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /packages/apps/micro-docs/src/styles/transition/scroll.scss: -------------------------------------------------------------------------------- 1 | @use 'base' as *; 2 | 3 | .scroll-y-transition { 4 | @include transition-default; 5 | 6 | &-enter-from, 7 | &-leave-to { 8 | opacity: 0; 9 | } 10 | 11 | &-enter-from { 12 | transform: translateY(-15px); 13 | } 14 | 15 | &-leave-to { 16 | transform: translateY(15px); 17 | } 18 | } 19 | 20 | .scroll-y-reverse-transition { 21 | @include transition-default; 22 | 23 | &-enter-from, 24 | &-leave-to { 25 | opacity: 0; 26 | } 27 | 28 | &-enter-from { 29 | transform: translateY(15px); 30 | } 31 | 32 | &-leave-to { 33 | transform: translateY(-15px); 34 | } 35 | } 36 | 37 | .scroll-x-transition { 38 | @include transition-default; 39 | 40 | &-enter-from, 41 | &-leave-to { 42 | opacity: 0; 43 | } 44 | 45 | &-enter-from { 46 | transform: translateX(-15px); 47 | } 48 | 49 | &-leave-to { 50 | transform: translateX(15px); 51 | } 52 | } 53 | 54 | .scroll-x-reverse-transition { 55 | @include transition-default; 56 | 57 | &-enter-from, 58 | &-leave-to { 59 | opacity: 0; 60 | } 61 | 62 | &-enter-from { 63 | transform: translateX(15px); 64 | } 65 | 66 | &-leave-to { 67 | transform: translateX(-15px); 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /packages/apps/micro-docs/src/styles/transition/slide.scss: -------------------------------------------------------------------------------- 1 | @use 'base' as *; 2 | 3 | .slide-y-transition { 4 | @include transition-default; 5 | 6 | &-enter-from, 7 | &-leave-to { 8 | opacity: 0; 9 | transform: translateY(-15px); 10 | } 11 | } 12 | 13 | .slide-y-reverse-transition { 14 | @include transition-default; 15 | 16 | &-enter-from, 17 | &-leave-to { 18 | opacity: 0; 19 | transform: translateY(15px); 20 | } 21 | } 22 | 23 | .slide-x-transition { 24 | @include transition-default; 25 | 26 | &-enter-from, 27 | &-leave-to { 28 | opacity: 0; 29 | transform: translateX(-15px); 30 | } 31 | } 32 | 33 | .slide-x-reverse-transition { 34 | @include transition-default; 35 | 36 | &-enter-from, 37 | &-leave-to { 38 | opacity: 0; 39 | transform: translateX(15px); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /packages/apps/micro-docs/src/styles/transition/zoom.scss: -------------------------------------------------------------------------------- 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.2s, 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/apps/micro-docs/src/views/basics/docker/index.docs.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 10 | -------------------------------------------------------------------------------- /packages/apps/micro-docs/src/views/basics/git/index.docs.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 10 | -------------------------------------------------------------------------------- /packages/apps/micro-docs/src/views/basics/linux/index.docs.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 10 | -------------------------------------------------------------------------------- /packages/apps/micro-docs/src/views/basics/network/index.docs.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 10 | -------------------------------------------------------------------------------- /packages/apps/micro-docs/src/views/basics/node/index.docs.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 10 | -------------------------------------------------------------------------------- /packages/apps/micro-docs/src/views/common/iframe/index.vue: -------------------------------------------------------------------------------- 1 | 6 | 45 | 46 | 60 | -------------------------------------------------------------------------------- /packages/apps/micro-docs/src/views/performance/optimization/index.docs.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 10 | -------------------------------------------------------------------------------- /packages/apps/micro-docs/src/views/performance/virtual-scroll/demo/fixation-height.demo.vue: -------------------------------------------------------------------------------- 1 | 12 | 13 | 29 | 30 | 35 | -------------------------------------------------------------------------------- /packages/apps/micro-docs/src/views/performance/virtual-scroll/index.docs.vue: -------------------------------------------------------------------------------- 1 | 28 | 29 | 34 | -------------------------------------------------------------------------------- /packages/apps/micro-docs/src/views/performance/virtual-scroll/index.md: -------------------------------------------------------------------------------- 1 | # 📜虚拟列表优化 2 | 3 | 在前端开发中,当需要展示大量数据列表时,传统的全量渲染方式会带来严重的性能问题,如页面加载缓慢、滚动卡顿等。虚拟列表优化技术应运而生,它通过只渲染当前可见区域的数据,大大提高了页面的性能和响应速度。本文将深入探讨虚拟列表优化的原理、实现方式以及应用场景。 4 | 5 | ## 虚拟列表优化的原理 6 | 7 | 虚拟列表的核心原理是根据用户的滚动位置和视口大小,动态计算并渲染当前可见区域的数据项,而不是一次性渲染整个列表。具体来说,当用户滚动页面时,虚拟列表会监听滚动事件,根据滚动距离和视口高度,确定当前可见的数据项范围,然后只渲染这些数据项。这样可以显著减少 DOM 节点的数量,从而提高页面的渲染性能。 8 | 9 | ## 实现虚拟列表优化的步骤 10 | 11 | 1. 计算可见区域首先,需要确定视口的高度和滚动位置。通过监听滚动事件,可以获取当前的滚动距离。然后,根据视口高度和每个数据项的高度,计算出当前可见区域的数据项范围。 12 | 13 | 2. 渲染可见数据项根据计算出的可见区域,从数据源中提取相应的数据项,并将其渲染到页面上。在渲染过程中,需要注意数据项的位置和样式,确保它们能够正确显示在视口中。 14 | 15 | 3. 处理滚动事件当用户滚动页面时,需要重新计算可见区域,并更新渲染的数据项。为了提高性能,可以使用节流或防抖技术来减少滚动事件的触发频率。 16 | -------------------------------------------------------------------------------- /packages/apps/micro-docs/src/views/repackage/components/demo/button.demo.vue: -------------------------------------------------------------------------------- 1 | 7 | 10 | -------------------------------------------------------------------------------- /packages/apps/micro-docs/src/views/repackage/components/demo/checkbox.demo.vue: -------------------------------------------------------------------------------- 1 | 16 | 20 | -------------------------------------------------------------------------------- /packages/apps/micro-docs/src/views/repackage/components/demo/input.demo.vue: -------------------------------------------------------------------------------- 1 | 21 | 27 | -------------------------------------------------------------------------------- /packages/apps/micro-docs/src/views/repackage/components/demo/radio.demo.vue: -------------------------------------------------------------------------------- 1 | 19 | 26 | -------------------------------------------------------------------------------- /packages/apps/micro-docs/src/views/repackage/components/demo/select.demo.vue: -------------------------------------------------------------------------------- 1 | 21 | 29 | -------------------------------------------------------------------------------- /packages/apps/micro-docs/src/views/system/auto-publish/demo/micro-app.demo.vue: -------------------------------------------------------------------------------- 1 | 4 | 5 | 9 | -------------------------------------------------------------------------------- /packages/apps/micro-docs/src/views/system/css/demo/bem.demo.vue: -------------------------------------------------------------------------------- 1 | 8 | 9 | 18 | 19 | 31 | -------------------------------------------------------------------------------- /packages/apps/micro-docs/src/views/system/css/demo/tailwind.demo.vue: -------------------------------------------------------------------------------- 1 | 6 | -------------------------------------------------------------------------------- /packages/apps/micro-docs/src/views/system/docs/demo/button.demo.vue: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /packages/apps/micro-docs/src/views/system/home/index.docs.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 10 | -------------------------------------------------------------------------------- /packages/apps/micro-docs/src/views/system/micro/demo/micro-app.demo.vue: -------------------------------------------------------------------------------- 1 | 4 | 5 | 9 | -------------------------------------------------------------------------------- /packages/apps/micro-docs/src/views/visual/animation/demo/bounce.demo.vue: -------------------------------------------------------------------------------- 1 | 8 | 9 | 34 | 35 | 48 | -------------------------------------------------------------------------------- /packages/apps/micro-docs/src/views/visual/animation/demo/fade.demo.vue: -------------------------------------------------------------------------------- 1 | 8 | 9 | 32 | 33 | 46 | -------------------------------------------------------------------------------- /packages/apps/micro-docs/src/views/visual/animation/demo/pulse.demo.vue: -------------------------------------------------------------------------------- 1 | 8 | 9 | 34 | 35 | 48 | -------------------------------------------------------------------------------- /packages/apps/micro-docs/src/views/visual/animation/demo/rotate.demo.vue: -------------------------------------------------------------------------------- 1 | 8 | 9 | 34 | 35 | 48 | -------------------------------------------------------------------------------- /packages/apps/micro-docs/src/views/visual/animation/demo/scale.demo.vue: -------------------------------------------------------------------------------- 1 | 8 | 9 | 34 | 35 | 48 | -------------------------------------------------------------------------------- /packages/apps/micro-docs/src/views/visual/animation/demo/slide.demo.vue: -------------------------------------------------------------------------------- 1 | 8 | 9 | 32 | 33 | 46 | -------------------------------------------------------------------------------- /packages/apps/micro-docs/src/views/visual/chart/demo/box.demo.vue: -------------------------------------------------------------------------------- 1 | 4 | 5 | 39 | -------------------------------------------------------------------------------- /packages/apps/micro-docs/src/views/visual/chart/demo/bubble.demo.vue: -------------------------------------------------------------------------------- 1 | 4 | 5 | 43 | -------------------------------------------------------------------------------- /packages/apps/micro-docs/src/views/visual/chart/demo/gauge.demo.vue: -------------------------------------------------------------------------------- 1 | 4 | 5 | 31 | -------------------------------------------------------------------------------- /packages/apps/micro-docs/src/views/visual/chart/demo/heatmap.demo.vue: -------------------------------------------------------------------------------- 1 | 4 | 5 | 34 | -------------------------------------------------------------------------------- /packages/apps/micro-docs/src/views/visual/chart/demo/map.demo.vue: -------------------------------------------------------------------------------- 1 | 4 | 5 | 25 | -------------------------------------------------------------------------------- /packages/apps/micro-docs/src/views/visual/chart/demo/pie.demo.vue: -------------------------------------------------------------------------------- 1 | 4 | 5 | 41 | -------------------------------------------------------------------------------- /packages/apps/micro-docs/src/views/visual/chart/demo/radar.demo.vue: -------------------------------------------------------------------------------- 1 | 4 | 5 | 38 | -------------------------------------------------------------------------------- /packages/apps/micro-docs/src/views/visual/chart/demo/sankey.demo.vue: -------------------------------------------------------------------------------- 1 | 4 | 5 | 37 | -------------------------------------------------------------------------------- /packages/apps/micro-docs/src/views/visual/chart/demo/sunburst.demo.vue: -------------------------------------------------------------------------------- 1 | 4 | 5 | 47 | -------------------------------------------------------------------------------- /packages/apps/micro-docs/src/views/visual/chart/demo/tree.demo.vue: -------------------------------------------------------------------------------- 1 | 4 | 5 | 57 | -------------------------------------------------------------------------------- /packages/apps/micro-docs/src/views/visual/flow/hooks/useGraph.ts: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ting-Code/Ting-Library-Monorepo/9cc73df070e2f9d4660312447f49ae7c5cd32753/packages/apps/micro-docs/src/views/visual/flow/hooks/useGraph.ts -------------------------------------------------------------------------------- /packages/apps/micro-docs/tailwind.config.cjs: -------------------------------------------------------------------------------- 1 | /** @type {import('tailwindcss').Config} */ 2 | module.exports = { 3 | content: ['./src/**/*.{html,ts,vue}'], 4 | theme: { 5 | extend: {} 6 | }, 7 | plugins: [] 8 | } 9 | -------------------------------------------------------------------------------- /packages/apps/micro-docs/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "@config/tsconfig/base.json", 3 | "compilerOptions": { 4 | "target": "esnext", 5 | "module": "esnext", 6 | "baseUrl": ".", 7 | "paths": { 8 | "@/*": ["src/*"], 9 | "@s/*": ["src/styles/*"] 10 | }, 11 | "lib": ["dom", "esnext"], 12 | "types": ["vite/client"] 13 | }, 14 | "include": [ 15 | "src", 16 | "mock", 17 | "vite.config.ts", 18 | "src/**/*.ts", 19 | "src/**/*.d.ts", 20 | "src/**/*.tsx", 21 | "src/**/*.vue" 22 | ] 23 | } 24 | -------------------------------------------------------------------------------- /packages/cli/create/README.md: -------------------------------------------------------------------------------- 1 | # create-tingcli 2 | 3 | 我写了一个快速搭建脚手架的脚手架 4 | 5 | 快速开始 6 | 7 | ```bash 8 | pnpm create tingcli 9 | ``` 10 | 11 | 选择 cli 回车 12 | 13 | ```bash 14 | ❯ cli 15 | monorepo 16 | ``` 17 | 18 | 创建项目名,不填则为当前目录 19 | 20 | ```bash 21 | ? 项目类型 cli 22 | ? 项目名称 23 | ``` 24 | 25 | 也可以通过命令行快速创建 26 | 27 | ```bash 28 | pnpm create tingcli -t cli -n project-name 29 | ``` 30 | 31 | 这样就可以快速创建你的脚手架啦,修改 package.json 就可以快速发包啦 32 | 33 | ```bash 34 | pnpm i 35 | pnpm build 36 | npm publish 37 | ``` 38 | -------------------------------------------------------------------------------- /packages/cli/create/bin/index.mjs: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 'use strict' 3 | import '../dist/cli.mjs' 4 | -------------------------------------------------------------------------------- /packages/cli/create/build.config.ts: -------------------------------------------------------------------------------- 1 | import { defineBuildConfig } from 'unbuild' 2 | 3 | export default defineBuildConfig({ 4 | entries: ['src/index', 'src/cli'], 5 | rollup: { 6 | inlineDependencies: true 7 | }, 8 | clean: true, 9 | declaration: true 10 | }) 11 | -------------------------------------------------------------------------------- /packages/cli/create/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "create-tingcli", 3 | "type": "module", 4 | "version": "0.2.8", 5 | "description": "", 6 | "main": "dist/index.mjs", 7 | "module": "dist/index.mjs", 8 | "types": "dist/index.d.ts", 9 | "publishConfig": { 10 | "access": "public", 11 | "registry": "https://registry.npmjs.org/" 12 | }, 13 | "bin": { 14 | "create-tingcli": "bin/index.mjs" 15 | }, 16 | "files": [ 17 | "dist/*", 18 | "bin/*" 19 | ], 20 | "scripts": { 21 | "dev": "esno ./src/cli.ts", 22 | "start": "node ./bin/index.mjs", 23 | "build": "unbuild", 24 | "test": "vitest", 25 | "lint:eslint": "eslint . --cache --max-warnings 0 --fix --ignore-path=../../../.eslintignore", 26 | "lint:prettier": "prettier --write --cache --ignore-unknown --ignore-path=../../../.prettierignore ." 27 | }, 28 | "license": "ISC", 29 | "keywords": [], 30 | "devDependencies": { 31 | "@inquirer/type": "^1.5.3", 32 | "@types/fs-extra": "^11.0.1", 33 | "esno": "^0.16.3", 34 | "typescript": "catalog:", 35 | "unbuild": "^1.2.0", 36 | "vitest": "catalog:" 37 | }, 38 | "dependencies": { 39 | "@inquirer/prompts": "^5.4.0", 40 | "commander": "^10.0.0", 41 | "execa": "^7.1.1", 42 | "fs-extra": "^11.1.1", 43 | "ora": "^6.3.0", 44 | "path-exists": "^5.0.0" 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /packages/cli/create/src/cli.ts: -------------------------------------------------------------------------------- 1 | import * as process from 'process' 2 | import { init } from './init' 3 | import { getProjectName, getSelectType, TYPE } from './inquirer' 4 | import { downloadTemplate } from './downloadTemplate' 5 | 6 | const program = init() 7 | program 8 | .option('-t, --type [type]', '项目类型') 9 | .option('-n, --name [name]', '模板名称') 10 | .action(async ({ type, name }) => { 11 | let _type = type 12 | let _name = name 13 | if (!TYPE.map((i) => i.value).includes(type)) { 14 | // 获取项目类型 15 | _type = await getSelectType() 16 | } 17 | if (typeof name !== 'string') { 18 | // 获取项目名称 19 | _name = await getProjectName(`ting-library-${_type}`) 20 | } 21 | console.log(`正在 ${_name} 下创建 ${_type} 项目`) 22 | downloadTemplate(_type, _name || 'demo2') 23 | }) 24 | 25 | program.parse(process.argv) 26 | -------------------------------------------------------------------------------- /packages/cli/create/src/index.ts: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ting-Code/Ting-Library-Monorepo/9cc73df070e2f9d4660312447f49ae7c5cd32753/packages/cli/create/src/index.ts -------------------------------------------------------------------------------- /packages/cli/create/src/init.ts: -------------------------------------------------------------------------------- 1 | import { program } from 'commander' 2 | import { version, bin } from '../package.json' 3 | 4 | export function init() { 5 | program.name(Object.keys(bin)[0]).usage(' [options]').version(version) 6 | return program 7 | } 8 | -------------------------------------------------------------------------------- /packages/cli/create/src/inquirer.ts: -------------------------------------------------------------------------------- 1 | import { input, select } from '@inquirer/prompts' 2 | import { CancelablePromise } from '@inquirer/type' 3 | 4 | export const TYPE = [ 5 | { name: 'monorepo', value: 'monorepo', description: 'ting-library-monorepo 主项目' }, 6 | { name: 'cli', value: 'cli', description: 'ting-library-cli 脚本项目' } 7 | ] 8 | 9 | export const getSelectType = (): CancelablePromise => { 10 | return select({ 11 | message: '项目类型', 12 | choices: TYPE 13 | }) 14 | } 15 | 16 | export const getProjectName = (defaultValue?: string): CancelablePromise => { 17 | return input({ 18 | message: '项目名称', 19 | default: defaultValue 20 | }) 21 | } 22 | -------------------------------------------------------------------------------- /packages/cli/create/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "rootDir": ".", 4 | "target": "es2018", 5 | "module": "esnext", 6 | "lib": ["esnext"], 7 | "moduleResolution": "node", 8 | "esModuleInterop": true, 9 | "strict": true, 10 | "strictNullChecks": true, 11 | "resolveJsonModule": true, 12 | "skipLibCheck": true, 13 | "skipDefaultLibCheck": true, 14 | "paths": { 15 | "@ting-create": ["./src/index.ts"] 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /packages/cli/template/cli/bin/index.mjs: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 'use strict' 3 | import '../dist/cli.mjs' 4 | -------------------------------------------------------------------------------- /packages/cli/template/cli/build.config.ts: -------------------------------------------------------------------------------- 1 | import { defineBuildConfig } from 'unbuild' 2 | 3 | export default defineBuildConfig({ 4 | entries: ['src/index', 'src/cli'], 5 | rollup: { 6 | inlineDependencies: true 7 | }, 8 | clean: true, 9 | declaration: true 10 | }) 11 | -------------------------------------------------------------------------------- /packages/cli/template/cli/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@tingcli/create", 3 | "type": "module", 4 | "version": "0.0.1", 5 | "description": "", 6 | "main": "dist/index.mjs", 7 | "module": "dist/index.mjs", 8 | "types": "dist/index.d.ts", 9 | "bin": { 10 | "@tingcli/create": "bin/index.mjs" 11 | }, 12 | "files": [ 13 | "dist" 14 | ], 15 | "scripts": { 16 | "dev": "esno ./src/cli.ts", 17 | "start": "esno ./src/cli.ts", 18 | "build": "unbuild", 19 | "test": "vitest", 20 | "lint:eslint": "eslint . --cache --max-warnings 0 --fix" 21 | }, 22 | "keywords": [], 23 | "author": "", 24 | "license": "ISC", 25 | "dependencies": { 26 | "@tingcli/cli-utils": "workspace:*", 27 | "chalk": "^5.2.0", 28 | "commander": "^10.0.0", 29 | "semver": "^7.3.8" 30 | }, 31 | "devDependencies": { 32 | "esno": "^0.16.3", 33 | "execa": "^7.1.1", 34 | "typescript": "catalog:", 35 | "unbuild": "^1.2.0" 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /packages/cli/template/cli/src/cli.ts: -------------------------------------------------------------------------------- 1 | import * as process from 'process' 2 | import { log } from '@tingcli/cli-utils' 3 | import { init } from './init' 4 | import './error' 5 | 6 | log.info('cli', 'start') 7 | const program = init() 8 | 9 | program.action(() => { 10 | console.log('action') 11 | }) 12 | 13 | program.parse(process.argv) 14 | log.info('cli', 'end') 15 | -------------------------------------------------------------------------------- /packages/cli/template/cli/src/error.ts: -------------------------------------------------------------------------------- 1 | import { isDebug, log } from '@tingcli/cli-utils' 2 | 3 | export function printErrorLog(e: Error, type: string) { 4 | if (isDebug()) { 5 | log.error(type, e as any) 6 | } else { 7 | log.error(type, e.message) 8 | } 9 | } 10 | 11 | process.on('uncaughtException', (e) => printErrorLog(e, 'error')) 12 | 13 | process.on('unhandledRejection', (e) => printErrorLog(e as Error, 'promise')) 14 | -------------------------------------------------------------------------------- /packages/cli/template/cli/src/index.ts: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ting-Code/Ting-Library-Monorepo/9cc73df070e2f9d4660312447f49ae7c5cd32753/packages/cli/template/cli/src/index.ts -------------------------------------------------------------------------------- /packages/cli/template/cli/src/init.ts: -------------------------------------------------------------------------------- 1 | import { program } from 'commander' 2 | import { log } from '@tingcli/cli-utils' 3 | import { version, bin } from '../package.json' 4 | import semver from 'semver' 5 | import chalk from 'chalk' 6 | 7 | const LOWEST_NODE_VERSION = '16.0.0' 8 | function checkNodeVersion() { 9 | log.verbose('node version', process.version) 10 | if (!semver.gte(process.version, LOWEST_NODE_VERSION)) { 11 | throw new Error(chalk.red(`cli 需要安装 ${LOWEST_NODE_VERSION} 以上版本的 Node.js`)) 12 | } 13 | } 14 | 15 | function preAction() { 16 | // 检查Node版本 17 | checkNodeVersion() 18 | } 19 | 20 | export function init() { 21 | log.info('version', version) 22 | program 23 | .name(Object.keys(bin)[0]) 24 | .usage(' [options]') 25 | .version(version) 26 | .option('-d, --debug', '是否开启debug', false) 27 | .hook('preAction', preAction) 28 | 29 | program.on('option:debug', function () { 30 | console.log(program.opts()) 31 | if (program.opts().debug) { 32 | log.verbose('debug', 'launch debug mode') 33 | } 34 | }) 35 | 36 | program.on('command:*', function (obj) { 37 | log.error('未知的命令:', obj[0]) 38 | }) 39 | return program 40 | } 41 | -------------------------------------------------------------------------------- /packages/cli/template/cli/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "rootDir": ".", 4 | "target": "es2018", 5 | "module": "esnext", 6 | "lib": ["esnext"], 7 | "moduleResolution": "node", 8 | "esModuleInterop": true, 9 | "strict": true, 10 | "strictNullChecks": true, 11 | "resolveJsonModule": true, 12 | "skipLibCheck": true, 13 | "skipDefaultLibCheck": true, 14 | "paths": { 15 | "@ting-create": ["./src/index.ts"] 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /packages/cli/template/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@tingcli/template", 3 | "version": "0.0.2", 4 | "scripts": { 5 | "lint:eslint": "eslint . --cache --max-warnings 0 --fix --ignore-path=../../../.eslintignore", 6 | "lint:prettier": "prettier --write --cache --ignore-unknown --ignore-path=../../../.prettierignore ." 7 | }, 8 | "publishConfig": { 9 | "access": "public", 10 | "registry": "https://registry.npmjs.org/" 11 | }, 12 | "files": [ 13 | "cli" 14 | ], 15 | "keywords": [ 16 | "template" 17 | ], 18 | "author": "", 19 | "license": "ISC" 20 | } 21 | -------------------------------------------------------------------------------- /packages/cli/utils/build.config.ts: -------------------------------------------------------------------------------- 1 | import { defineBuildConfig } from 'unbuild' 2 | 3 | export default defineBuildConfig({ 4 | entries: ['src/index'], 5 | rollup: { 6 | inlineDependencies: true 7 | }, 8 | clean: true, 9 | declaration: true 10 | }) 11 | -------------------------------------------------------------------------------- /packages/cli/utils/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@tingcli/cli-utils", 3 | "type": "module", 4 | "version": "0.0.5", 5 | "publishConfig": { 6 | "access": "public", 7 | "registry": "https://registry.npmjs.org/" 8 | }, 9 | "main": "dist/index.mjs", 10 | "module": "dist/index.mjs", 11 | "types": "dist/index.d.ts", 12 | "files": [ 13 | "dist" 14 | ], 15 | "scripts": { 16 | "build": "unbuild", 17 | "up": "npm publish", 18 | "lint:eslint": "eslint . --cache --max-warnings 0 --fix --ignore-path=../../../.eslintignore", 19 | "lint:prettier": "prettier --write --cache --ignore-unknown --ignore-path=../../../.prettierignore ." 20 | }, 21 | "keywords": [], 22 | "author": "", 23 | "license": "ISC", 24 | "dependencies": { 25 | "axios": "^1.3.4", 26 | "execa": "^7.1.1", 27 | "inquirer": "^9.1.5", 28 | "npmlog": "^7.0.1", 29 | "unbuild": "^1.2.0", 30 | "url-join": "^5.0.0" 31 | }, 32 | "devDependencies": { 33 | "@types/inquirer": "^9.0.3", 34 | "@types/npmlog": "^4.1.4" 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /packages/cli/utils/src/index.ts: -------------------------------------------------------------------------------- 1 | import log, { isDebug } from './log' 2 | export * from './pkg' 3 | export * from './npm' 4 | export * from './inquirer' 5 | export { log, isDebug } 6 | -------------------------------------------------------------------------------- /packages/cli/utils/src/inquirer.ts: -------------------------------------------------------------------------------- 1 | import inquirer from 'inquirer' 2 | 3 | export interface Params { 4 | type: 'list' | 'input' | 'password' | 'confirm' | 'expand' | 'checkbox' | 'editor' 5 | choices?: any[] 6 | message?: string 7 | mask?: string 8 | validate?: (value: string) => boolean 9 | filter?: (value: string) => string // 过滤器, 返回修改后的回答。优先级高于 `validte` 10 | transformer?: (value: string) => string // 转换器, 返回转换后的值,只作为显示,不影响收集结果 11 | defaultValue?: any 12 | loop?: boolean 13 | pageSize?: number 14 | name?: string 15 | } 16 | interface Options extends Params { 17 | default?: any 18 | } 19 | 20 | export function inquirerInput({ 21 | choices, 22 | defaultValue, 23 | message = '请选择', 24 | type = 'list', 25 | mask = '*', 26 | validate, 27 | pageSize, 28 | loop, 29 | name = 'name' 30 | }: Params) { 31 | const options: Options = { 32 | name, 33 | default: defaultValue, 34 | message, 35 | type, 36 | mask, 37 | validate, 38 | pageSize, 39 | loop 40 | } 41 | if (type === 'list') { 42 | options.choices = choices 43 | } 44 | return inquirer.prompt(options) 45 | } 46 | 47 | interface SelectParams extends Params { 48 | type: 'list' | 'checkbox' 49 | choices: { name: string; value: string }[] 50 | } 51 | 52 | export const inquirerSelect = (params: SelectParams) => { 53 | return inquirerInput({ 54 | ...params 55 | }) 56 | } 57 | 58 | export const test = (a: any) => { 59 | return a 60 | } 61 | -------------------------------------------------------------------------------- /packages/cli/utils/src/log.ts: -------------------------------------------------------------------------------- 1 | import log from 'npmlog' 2 | 3 | export function isDebug() { 4 | return process.argv.includes('--debug') || process.argv.includes('-d') 5 | } 6 | 7 | if (isDebug()) { 8 | log.level = 'verbose' 9 | } else { 10 | log.level = 'info' 11 | } 12 | 13 | log.heading = 'ting' 14 | log.addLevel('success', 2000, { fg: 'green', bold: true }) 15 | 16 | export default log 17 | -------------------------------------------------------------------------------- /packages/cli/utils/src/npm.ts: -------------------------------------------------------------------------------- 1 | import urlJoin from 'url-join' 2 | import axios from 'axios' 3 | 4 | import log from './log.js' 5 | 6 | export const getNpmInfo = (npmName: string) => { 7 | // cnpm源:https://registry.npmmirror.com/ 8 | const registry = 'https://registry.npmjs.org/' 9 | const url = urlJoin(registry, npmName) 10 | return axios.get(url).then((response) => { 11 | try { 12 | return response.data 13 | } catch (err) { 14 | return Promise.reject(err) 15 | } 16 | }) 17 | } 18 | 19 | export const getLatestVersion = (npmName: string) => { 20 | return getNpmInfo(npmName).then((data) => { 21 | if (!data['dist-tags'] || !data['dist-tags'].latest) { 22 | log.error('error', '没有 latest 版本号') 23 | return Promise.reject(new Error('没有 latest 版本号')) 24 | } 25 | return data['dist-tags'].latest 26 | }) 27 | } 28 | -------------------------------------------------------------------------------- /packages/cli/utils/src/pkg.ts: -------------------------------------------------------------------------------- 1 | import { execa } from 'execa' 2 | 3 | type WorkspacePackage = { name: string; version?: string; path: string } 4 | // 获取所有子项目的信息 as WorkspacePackage (筛选需要打包的子项目) 5 | async function getAllPackages(namespace?: string | undefined) { 6 | const { stdout } = await execa('pnpm', ['ls', '-r', '--depth', '-1', '--json']) 7 | return (JSON.parse(stdout) as WorkspacePackage[]).filter((p) => { 8 | return p.name.includes(namespace || '') || !namespace 9 | }) 10 | } 11 | 12 | async function getPackage() { 13 | const { stdout } = await execa('npm', ['ls', '-r', '--depth', '-1', '--json']) 14 | return JSON.parse(stdout) as WorkspacePackage 15 | } 16 | 17 | export { getPackage, getAllPackages } 18 | -------------------------------------------------------------------------------- /packages/cli/utils/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "rootDir": ".", 4 | "target": "es2018", 5 | "module": "esnext", 6 | "lib": ["esnext"], 7 | "moduleResolution": "node", 8 | "esModuleInterop": true, 9 | "strict": true, 10 | "strictNullChecks": true, 11 | "resolveJsonModule": true, 12 | "skipLibCheck": true, 13 | "skipDefaultLibCheck": true, 14 | "allowSyntheticDefaultImports": true 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /packages/lib/react/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@tingcode/lib-react", 3 | "version": "0.0.1", 4 | "description": "", 5 | "main": "dist/index.js", 6 | "type": "module", 7 | "types": "dist/index.d.ts", 8 | "scripts": { 9 | "lint:eslint": "eslint . --cache --max-warnings 0 --fix --ignore-path=../../../.eslintignore", 10 | "lint:prettier": "prettier --write --cache --ignore-unknown --ignore-path=../../../.prettierignore ." 11 | }, 12 | "files": [ 13 | "dist" 14 | ], 15 | "keywords": [], 16 | "author": "", 17 | "license": "ISC" 18 | } 19 | -------------------------------------------------------------------------------- /packages/lib/react/src/index.ts: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ting-Code/Ting-Library-Monorepo/9cc73df070e2f9d4660312447f49ae7c5cd32753/packages/lib/react/src/index.ts -------------------------------------------------------------------------------- /packages/lib/request/index.ts: -------------------------------------------------------------------------------- 1 | export * from './src/axios' 2 | -------------------------------------------------------------------------------- /packages/lib/request/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@tingcode/request", 3 | "version": "0.0.1", 4 | "description": "", 5 | "main": "index.ts", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1", 8 | "lint:eslint": "eslint . --cache --max-warnings 0 --fix --ignore-path=../../../.eslintignore", 9 | "lint:prettier": "prettier --write --cache --ignore-unknown --ignore-path=../../../.prettierignore ." 10 | }, 11 | "keywords": [], 12 | "author": "", 13 | "license": "ISC", 14 | "dependencies": { 15 | "@tingcode/utils": "workspace:*", 16 | "@types/qs": "^6.9.15", 17 | "axios": "^1.3.4", 18 | "qs": "^6.11.2" 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /packages/lib/request/src/axios/axiosTransform.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * 数据处理类,可以根据项目自行配置 3 | */ 4 | import type { AxiosRequestConfig, AxiosResponse } from 'axios' 5 | import type { RequestOptions, Result } from './types' 6 | 7 | export interface CreateAxiosOptions extends AxiosRequestConfig { 8 | authenticationScheme?: string 9 | transform?: AxiosTransform 10 | requestOptions?: RequestOptions 11 | } 12 | 13 | export abstract class AxiosTransform { 14 | /** 15 | * @description: 请求之前处理配置 16 | * @description: Process configuration before request 17 | */ 18 | beforeRequestHook?: (config: AxiosRequestConfig, options: RequestOptions) => AxiosRequestConfig 19 | 20 | /** 21 | * @description: 请求成功处理 22 | */ 23 | transformRequestData?: (res: AxiosResponse, options: RequestOptions) => any 24 | 25 | /** 26 | * @description: 请求失败处理 27 | */ 28 | requestCatch?: (e: Error) => Promise 29 | 30 | /** 31 | * @description: 请求之前的拦截器 32 | */ 33 | requestInterceptors?: ( 34 | config: AxiosRequestConfig, 35 | options: CreateAxiosOptions 36 | ) => AxiosRequestConfig 37 | 38 | /** 39 | * @description: 请求之后的拦截器 40 | */ 41 | responseInterceptors?: (res: AxiosResponse) => AxiosResponse 42 | 43 | /** 44 | * @description: 请求之前的拦截器错误处理 45 | */ 46 | requestInterceptorsCatch?: (error: Error) => void 47 | 48 | /** 49 | * @description: 请求之后的拦截器错误处理 50 | */ 51 | responseInterceptorsCatch?: (error: Error) => void 52 | } 53 | -------------------------------------------------------------------------------- /packages/lib/request/src/axios/checkStatus.ts: -------------------------------------------------------------------------------- 1 | export function checkStatus(status: number, msg: string, message: any): void { 2 | switch (status) { 3 | case 400: 4 | message.error(`${msg}`) 5 | break 6 | // 401: 未登录 7 | // 未登录则跳转登录页面,并携带当前页面的路径 8 | // 在登录成功后返回当前页面,这一步需要在登录页操作。 9 | case 401: 10 | message.error('用户没有权限(令牌、用户名、密码错误)!') 11 | break 12 | case 403: 13 | message.error('用户得到授权,但是访问是被禁止的。!') 14 | break 15 | // 404请求不存在 16 | case 404: 17 | message.error('网络请求错误,未找到该资源!') 18 | break 19 | case 405: 20 | message.error('网络请求错误,请求方法未允许!') 21 | break 22 | case 408: 23 | message.error('网络请求超时!') 24 | break 25 | case 500: 26 | message.error('服务器错误,请联系管理员!') 27 | break 28 | case 501: 29 | message.error('网络未实现!') 30 | break 31 | case 502: 32 | message.error('网络错误!') 33 | break 34 | case 503: 35 | message.error('服务不可用,服务器暂时过载或维护!') 36 | break 37 | case 504: 38 | message.error('网络超时!') 39 | break 40 | case 505: 41 | message.error('http版本不支持该请求!') 42 | break 43 | default: 44 | message.error(msg) 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /packages/lib/request/src/axios/enums.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * @description: Request result set 3 | */ 4 | export enum ResultEnum { 5 | SUCCESS = 200, 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: contentType 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 | 33 | /** 34 | * Exception related enumeration 35 | */ 36 | export enum ExceptionEnum { 37 | // page not access 38 | PAGE_NOT_ACCESS = 403, 39 | 40 | // page not found 41 | PAGE_NOT_FOUND = 404, 42 | 43 | // error 44 | ERROR = 500, 45 | 46 | // net work error 47 | NET_WORK_ERROR = 10000, 48 | 49 | // No data on the page. In fact, it is not an exception page 50 | PAGE_NOT_DATA = 10100 51 | } 52 | -------------------------------------------------------------------------------- /packages/lib/request/src/axios/helper.ts: -------------------------------------------------------------------------------- 1 | import { isObject, isString } from '@tingcode/utils' 2 | import { Recordable } from './types' 3 | 4 | const DATE_TIME_FORMAT = 'YYYY-MM-DD HH:mm' 5 | 6 | export function joinTimestamp( 7 | join: boolean, 8 | restful: T 9 | ): T extends true ? string : object 10 | 11 | export function joinTimestamp(join: boolean, restful = false): string | object { 12 | if (!join) { 13 | return restful ? '' : {} 14 | } 15 | const now = new Date().getTime() 16 | if (restful) { 17 | return `?_t=${now}` 18 | } 19 | return { _t: now } 20 | } 21 | 22 | /** 23 | * @description: 统一格式化请求时间 24 | */ 25 | export function formatRequestDate(params: Recordable) { 26 | if (Object.prototype.toString.call(params) !== '[object Object]') { 27 | return 28 | } 29 | 30 | for (const key in params) { 31 | const format = params[key]?.format ?? null 32 | if (format && typeof format === 'function') { 33 | params[key] = params[key].format(DATE_TIME_FORMAT) 34 | } 35 | if (isString(key)) { 36 | const value = params[key] 37 | if (value) { 38 | try { 39 | params[key] = isString(value) ? value.trim() : value 40 | } catch (error) { 41 | throw new Error(error as any) 42 | } 43 | } 44 | } 45 | if (isObject(params[key])) { 46 | formatRequestDate(params[key]) 47 | } 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /packages/lib/request/src/axios/index.ts: -------------------------------------------------------------------------------- 1 | // axios配置 可自行根据项目进行更改,只需更改该文件即可,其他文件可以不动 2 | export { VAxios } from './Axios' 3 | export type { CreateAxiosOptions, Recordable, RequestOptions, Result } from './types' 4 | export { AxiosTransform } from './axiosTransform' 5 | export type { AxiosResponse } from 'axios' 6 | export { checkStatus } from './checkStatus' 7 | export { joinTimestamp, formatRequestDate } from './helper' 8 | export { RequestEnum, ResultEnum, ContentTypeEnum } from './enums' 9 | import axios from 'axios' 10 | export { axios } 11 | -------------------------------------------------------------------------------- /packages/lib/request/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "@config/tsconfig/base.json", 3 | "compilerOptions": { 4 | "target": "esnext", 5 | "module": "esnext", 6 | "baseUrl": ".", 7 | "paths": { 8 | "@/*": ["src/*"] 9 | }, 10 | "lib": ["dom", "esnext"] 11 | }, 12 | "include": ["src"] 13 | } 14 | -------------------------------------------------------------------------------- /packages/lib/system/build.config.ts: -------------------------------------------------------------------------------- 1 | import { defineBuildConfig } from 'unbuild' 2 | 3 | export default defineBuildConfig({ 4 | entries: [ 5 | './src/index', 6 | { 7 | builder: 'rollup', 8 | input: './src/api/apiSystem', 9 | outDir: './dist' 10 | } 11 | ], 12 | clean: true, 13 | outDir: 'dist', 14 | declaration: true 15 | }) 16 | -------------------------------------------------------------------------------- /packages/lib/system/src/api/apiSystem.ts: -------------------------------------------------------------------------------- 1 | import { request, BasicResponseModel } from '../init' 2 | 3 | export interface IMeta { 4 | keepAlive?: boolean 5 | transition?: boolean 6 | title: string 7 | affix?: boolean 8 | icon?: string 9 | module?: string 10 | dynamicLevel?: number 11 | realPath?: string 12 | } 13 | 14 | export interface IMenu { 15 | name: string 16 | path?: string 17 | meta: IMeta 18 | module?: string 19 | children?: IMenu[] 20 | auth?: string[] 21 | } 22 | 23 | export interface IUserInfo { 24 | menu: IMenu[] 25 | } 26 | 27 | /** 28 | * @description: 获取用户信息 (前端权限)啊 29 | */ 30 | export function apiGetUserInfo() { 31 | return request.request({ 32 | url: '/admin_info', 33 | method: 'GET' 34 | }) 35 | } 36 | 37 | /** 38 | * @description: 用户登录 39 | */ 40 | export function apiLogin(params: any) { 41 | return request.request( 42 | { 43 | url: '/login', 44 | method: 'POST', 45 | params 46 | }, 47 | { 48 | isTransformResponse: false 49 | } 50 | ) 51 | } 52 | 53 | /** 54 | * @description: 根据用户id获取用户菜单 (后端权限) 55 | */ 56 | export function apiAdminMenus() { 57 | return request.request({ 58 | url: '/menus', 59 | method: 'GET' 60 | }) 61 | } 62 | -------------------------------------------------------------------------------- /packages/lib/system/src/global-data/element.ts: -------------------------------------------------------------------------------- 1 | import { getGlobalData, GlobalDataKeyEnum, setGlobalData } from './index' 2 | 3 | export interface IEL { 4 | ElMessage: any 5 | ElMessageBox: any 6 | } 7 | 8 | export function setGlobalDataElement(El: T) { 9 | setGlobalData(GlobalDataKeyEnum.EL, El) 10 | } 11 | 12 | export function getGlobalDataElement(): T { 13 | const globalData = getGlobalData() 14 | return globalData?.[GlobalDataKeyEnum.EL] 15 | } 16 | -------------------------------------------------------------------------------- /packages/lib/system/src/global-data/env.ts: -------------------------------------------------------------------------------- 1 | import { getGlobalData, GlobalDataKeyEnum, setGlobalData } from './index' 2 | 3 | export interface IENV { 4 | env: 'production' | 'development' | 'test' 5 | urlPrefix: string 6 | apiUrl: string 7 | } 8 | 9 | export function setGlobalDataEnv(env: IENV) { 10 | setGlobalData(GlobalDataKeyEnum.ENV, env) 11 | } 12 | 13 | export function getGlobalDataEnv(): IENV | undefined { 14 | const globalData = getGlobalData() 15 | return globalData?.[GlobalDataKeyEnum.ENV] 16 | } 17 | -------------------------------------------------------------------------------- /packages/lib/system/src/global.d.ts: -------------------------------------------------------------------------------- 1 | declare interface Window { 2 | microApp: any 3 | namespace: string 4 | __MICRO_APP_BASE_APPLICATION__: boolean 5 | __MICRO_APP_NAME__: string 6 | rawWindow: Window 7 | } 8 | -------------------------------------------------------------------------------- /packages/lib/system/src/hooks/auth.ts: -------------------------------------------------------------------------------- 1 | import { getUrl } from './router' 2 | import { getGlobalDataAuth } from '../global-data' 3 | import { error, isArray, isString } from '@tingcode/utils' 4 | 5 | export function getAuthPathList(): string[] { 6 | const url = getUrl() 7 | const authList = getGlobalDataAuth() 8 | if (!authList || !authList.length) return [] 9 | const authPathList = authList.find((item) => item.path === url?.pathname) 10 | return authPathList ? authPathList?.auth || [] : [] 11 | } 12 | 13 | /** 14 | * 判断是否存在权限 15 | * @param accesses 16 | * */ 17 | export function hasAuth(accesses: string[] | string): boolean { 18 | const auth = getAuthPathList() 19 | if (isString(accesses)) { 20 | return auth.includes(accesses as string) 21 | } 22 | if (isArray(accesses)) { 23 | return auth.some((item) => { 24 | return accesses.includes(item) 25 | }) 26 | } 27 | return error(`[hasAuth]: ${accesses} should be a array or string !`) 28 | } 29 | 30 | /** 31 | * 是否包含指定的所有权限 32 | * @param accesses 33 | */ 34 | export function hasEveryAuth(accesses: string[]): boolean { 35 | const auth = getAuthPathList() 36 | if (isArray(accesses)) { 37 | return auth.every((access: string) => accesses.includes(access)) 38 | } 39 | throw new Error(`[hasEveryAuth]: ${accesses} should be a array !`) 40 | } 41 | -------------------------------------------------------------------------------- /packages/lib/system/src/hooks/eventListener.ts: -------------------------------------------------------------------------------- 1 | import { throttle, debounce } from '@tingcode/utils' 2 | 3 | export type RemoveEventFn = () => void 4 | export interface UseEventParams { 5 | el?: Element | Window | any 6 | name: string 7 | listener: EventListener 8 | options?: boolean | AddEventListenerOptions 9 | autoRemove?: boolean 10 | isDebounce?: boolean 11 | wait?: number 12 | } 13 | export function useEventListener({ 14 | el = window, 15 | name, 16 | listener, 17 | options, 18 | isDebounce = true, 19 | wait = 80 20 | }: UseEventParams): { removeEvent: RemoveEventFn } { 21 | let remove: RemoveEventFn = () => {} 22 | 23 | if (el) { 24 | const element = el as Element 25 | 26 | const handler = isDebounce ? debounce(listener, wait) : throttle(listener, wait) 27 | const realHandler = wait ? handler : listener 28 | const removeEventListener = (e: Element) => { 29 | e.removeEventListener(name, realHandler, options) 30 | } 31 | const addEventListener = (e: Element = el) => e.addEventListener(name, realHandler, options) 32 | 33 | addEventListener() 34 | 35 | remove = () => { 36 | removeEventListener(element) 37 | } 38 | } 39 | return { removeEvent: remove } 40 | } 41 | -------------------------------------------------------------------------------- /packages/lib/system/src/hooks/index.ts: -------------------------------------------------------------------------------- 1 | export * from './login' 2 | export * from './router' 3 | export * from './user' 4 | export * from './eventListener' 5 | export * from './browser' 6 | export * from './namespace' 7 | export * from './setting' 8 | export * from './auth' 9 | export * from './micro' 10 | -------------------------------------------------------------------------------- /packages/lib/system/src/hooks/setting.ts: -------------------------------------------------------------------------------- 1 | import { emitMitt, onMitt } from '../global-data/mitt' 2 | 3 | export function emitIsOpenSetting(value: boolean) { 4 | emitMitt('isOpenSetting', value) 5 | } 6 | export function onIsOpenSetting(fn: (opt: boolean) => void) { 7 | onMitt('isOpenSetting', fn) 8 | } 9 | 10 | export function emitIsOpenSlider(value: boolean) { 11 | emitMitt('isOpenSlider', value) 12 | } 13 | export function onIsOpenSlider(fn: (opt: boolean) => void) { 14 | onMitt('isOpenSlider', fn) 15 | } 16 | export function emitIsOpenFull(value: boolean) { 17 | emitMitt('isOpenFull', value) 18 | } 19 | export function onIsOpenFull(fn: (opt: boolean) => void) { 20 | onMitt('isOpenFull', fn) 21 | } 22 | export function emitTheme(value: string) { 23 | emitMitt('theme', value) 24 | } 25 | export function onTheme(fn: (opt: string) => void) { 26 | onMitt('theme', fn) 27 | } 28 | -------------------------------------------------------------------------------- /packages/lib/system/src/hooks/user.ts: -------------------------------------------------------------------------------- 1 | import { apiGetUserInfo, IMenu } from '../api/apiSystem' 2 | import { setGlobalDataAuth, setGlobalDataMenu } from '../global-data' 3 | 4 | /** 5 | * @description 获取用户信息(菜单和权限) 6 | */ 7 | export async function getUserInfo() { 8 | try { 9 | const res = await apiGetUserInfo() 10 | setGlobalDataMenu(res.menu) 11 | const auth = transAuth(res.menu) 12 | setGlobalDataAuth(auth) 13 | return { menu: res.menu, auth } 14 | } catch (e) { 15 | return Promise.reject(e) 16 | } 17 | } 18 | 19 | /** 20 | * 将页面权限拍平 21 | * @param menu 22 | */ 23 | function transAuth(menu: IMenu[]) { 24 | let auth: Omit[] = [] 25 | menu.forEach((menuItem) => { 26 | if (menuItem?.path && !menuItem?.children) { 27 | auth.push(menuItem) 28 | } 29 | if (menuItem?.children) { 30 | auth = [...auth, ...transAuth(menuItem.children)] 31 | } 32 | }) 33 | return auth 34 | } 35 | -------------------------------------------------------------------------------- /packages/lib/system/src/index.ts: -------------------------------------------------------------------------------- 1 | import microApp from '@micro-zoe/micro-app' 2 | 3 | export { microApp } 4 | export * from './init' 5 | export * from './global-data' 6 | export * from './hooks' 7 | // export * from './api' 8 | -------------------------------------------------------------------------------- /packages/lib/system/src/init/index.ts: -------------------------------------------------------------------------------- 1 | import mitt from 'mitt' 2 | import microApp from '@micro-zoe/micro-app' 3 | import { error } from '@tingcode/utils' 4 | import { createAxios, BasicResponseModel } from './api' 5 | import { IMittEvents, setGlobalDataMitt } from '../global-data' 6 | export function checkWindow() { 7 | if (!window) return error('System windows not found') 8 | } 9 | 10 | /** 11 | * @description 初始化微前端 12 | */ 13 | export function initMicroApp() { 14 | microApp.start({ 15 | 'router-mode': 'native' 16 | }) 17 | } 18 | /** 19 | * @description 初始化docs嵌套微前端 20 | */ 21 | export function initDocsMicroApp() { 22 | microApp.start({ 23 | tagName: 'micro-app-docs' 24 | }) 25 | } 26 | 27 | /** 28 | * @description 初始化命名空间 29 | * @param namespace 30 | */ 31 | export function initNamespace(namespace: string) { 32 | checkWindow() 33 | window.namespace = namespace 34 | } 35 | 36 | let request = createAxios() 37 | 38 | /** 39 | * @description 初始化请求工具 40 | */ 41 | export function initRequest() { 42 | return (request = createAxios()) 43 | } 44 | 45 | export function initMitt() { 46 | const emitter = mitt() 47 | setGlobalDataMitt(emitter) 48 | } 49 | 50 | export { request } 51 | export type { BasicResponseModel } 52 | -------------------------------------------------------------------------------- /packages/lib/system/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "@config/tsconfig/base.json", 3 | "compilerOptions": { 4 | "target": "esnext", 5 | "module": "esnext", 6 | "baseUrl": "." 7 | }, 8 | "include": ["src"] 9 | } 10 | -------------------------------------------------------------------------------- /packages/lib/utils/build.config.ts: -------------------------------------------------------------------------------- 1 | import { defineBuildConfig } from 'unbuild' 2 | 3 | export default defineBuildConfig({ 4 | entries: ['src/index'], 5 | rollup: { 6 | inlineDependencies: true 7 | }, 8 | clean: true, 9 | declaration: true 10 | }) 11 | -------------------------------------------------------------------------------- /packages/lib/utils/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@tingcode/utils", 3 | "type": "module", 4 | "version": "0.0.2", 5 | "publishConfig": { 6 | "access": "public", 7 | "registry": "https://registry.npmjs.org/" 8 | }, 9 | "main": "dist/index.mjs", 10 | "module": "dist/index.mjs", 11 | "types": "dist/index.d.ts", 12 | "files": [ 13 | "dist" 14 | ], 15 | "scripts": { 16 | "build": "unbuild", 17 | "dev": "unbuild", 18 | "up": "npm publish", 19 | "lint:eslint": "eslint . --cache --max-warnings 0 --fix --ignore-path=../../../.eslintignore", 20 | "lint:prettier": "prettier --write --cache --ignore-unknown --ignore-path=../../../.prettierignore ." 21 | }, 22 | "keywords": [], 23 | "author": "", 24 | "license": "ISC", 25 | "dependencies": { 26 | "@types/lodash-es": "^4.17.9", 27 | "bignumber.js": "^9.1.2", 28 | "dayjs": "catalog:", 29 | "lodash-es": "^4.17.21", 30 | "nzh": "^1.0.12" 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /packages/lib/utils/src/date/index.ts: -------------------------------------------------------------------------------- 1 | import type { ConfigType } from 'dayjs' 2 | import dayjs from 'dayjs' 3 | import { isEmpty } from 'lodash-es' 4 | 5 | const DATE_TIME_FORMAT = 'YYYY-MM-DD HH:mm:ss' 6 | const DATE_FORMAT = 'YYYY-MM-DD' 7 | 8 | export const dateUtil = dayjs 9 | 10 | export const formatDate = ( 11 | date: ConfigType, 12 | format = DATE_TIME_FORMAT, 13 | repair: unknown = '' 14 | ): string | unknown => { 15 | if (isEmpty(date) || isNaN(dateUtil(date).toDate().getTime())) return repair 16 | return dateUtil(date).format(format) 17 | } 18 | 19 | export const formatSecond = (date: ConfigType): unknown => { 20 | return formatDate(date, DATE_FORMAT) 21 | } 22 | 23 | /** 24 | * @description 25 | * @param date 26 | */ 27 | export const formatDay = (date: ConfigType): unknown => { 28 | return formatDate(date, DATE_TIME_FORMAT) 29 | } 30 | -------------------------------------------------------------------------------- /packages/lib/utils/src/date/test/date.test.ts: -------------------------------------------------------------------------------- 1 | import { expect, test, describe } from 'vitest' 2 | import { formatDate } from '../index' 3 | 4 | describe('测试 formatDate 相关函数', async () => { 5 | test('测试formatDate 非时间情况', () => { 6 | expect(formatDate(undefined)).toBe('') 7 | expect(formatDate('abc')).toBe('') 8 | expect(formatDate(null)).toBe('') 9 | expect(formatDate('2023')).toBe('2023-01-01 00:00:00') 10 | }) 11 | }) 12 | -------------------------------------------------------------------------------- /packages/lib/utils/src/format/index.ts: -------------------------------------------------------------------------------- 1 | import { isString, isArray } from 'lodash-es' 2 | import { keepNumbers } from '../math' 3 | 4 | export interface SplitConfig { 5 | repair?: unknown 6 | error?: Function 7 | separator?: string 8 | } 9 | 10 | /** 11 | * @description 12 | * @param val 13 | * @param config 14 | */ 15 | export function stringSplitArray(val: unknown, config: SplitConfig = {}) { 16 | const { repair = val, separator = ',', error } = config 17 | if (!isString(val)) return error ? error(val) : repair 18 | return val ? val.split(separator) : [] 19 | } 20 | 21 | export function stringSplitNumberArray(val: unknown, config: SplitConfig = {}) { 22 | const { repair = val, separator = ',', error } = config 23 | if (!isString(val)) return error ? error(val) : repair 24 | return (val ? val.split(separator) : []).map((item) => { 25 | return keepNumbers(item) 26 | }) 27 | } 28 | 29 | export function arrayJoinString(val: unknown, config: SplitConfig = {}) { 30 | const { repair = val, separator = ',', error } = config 31 | if (!isArray(val)) return error ? error(val) : repair 32 | return val.join(separator) 33 | } 34 | -------------------------------------------------------------------------------- /packages/lib/utils/src/format/test/format.test.ts: -------------------------------------------------------------------------------- 1 | import { expect, test, describe } from 'vitest' 2 | import { stringSplitArray, arrayJoinString, stringSplitNumberArray } from '../index' 3 | 4 | describe('测试format对应函数', async () => { 5 | test('测试stringToArray函数', () => { 6 | expect((stringSplitArray('1,2,3') as Array).join(',')).toBe('1,2,3') 7 | expect(stringSplitArray(undefined)).toBe(undefined) 8 | expect(stringSplitArray(123, { repair: '' })).toBe('') 9 | }) 10 | 11 | test('测试stringSplitNumberArray函数', () => { 12 | expect((stringSplitNumberArray('1,2,3') as Array)[0]).toBe(1) 13 | expect(stringSplitNumberArray(undefined)).toBe(undefined) 14 | expect(stringSplitNumberArray(123, { repair: '' })).toBe('') 15 | }) 16 | 17 | test('测试arrayToString函数', () => { 18 | expect(arrayJoinString([1, 2, 3])).toBe('1,2,3') 19 | expect(arrayJoinString(undefined)).toBe(undefined) 20 | expect(arrayJoinString([], { repair: '' })).toBe('') 21 | }) 22 | }) 23 | -------------------------------------------------------------------------------- /packages/lib/utils/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from './is' 2 | export * from './log' 3 | export * from './util' 4 | export * from './math' 5 | export * from './date' 6 | export * from './download' 7 | export * from './browser' 8 | export * from './storage' 9 | export * from './format' 10 | export { groupBy, debounce, throttle } from 'lodash-es' 11 | -------------------------------------------------------------------------------- /packages/lib/utils/src/util/index.ts: -------------------------------------------------------------------------------- 1 | export { curry, curryRight } from 'lodash-es' 2 | /** 3 | * Add the object as a parameter to the URL 将对象添加当作参数拼接到URL上面 4 | * @param baseUrl url 5 | * @param obj 6 | * @returns {string} 7 | * eg: 8 | * let obj = {a: '3', b: '4'} 9 | * setObjToUrlParams('www.baidu.com', obj) 10 | * ==>www.baidu.com?a=3&b=4 11 | */ 12 | import { isObject } from '../is' 13 | 14 | export function setObjToUrlParams(baseUrl: string, obj: any): string { 15 | let parameters = '' 16 | for (const key in obj) { 17 | parameters += key + '=' + encodeURIComponent(obj[key]) + '&' 18 | } 19 | parameters = parameters.replace(/&$/, '') 20 | return /\?$/.test(baseUrl) ? baseUrl + parameters : baseUrl.replace(/\/?$/, '?') + parameters 21 | } 22 | 23 | export function deepMerge(src: any = {}, target: any = {}): T { 24 | let key: string 25 | for (key in target) { 26 | src[key] = isObject(src[key]) ? deepMerge(src[key], target[key]) : (src[key] = target[key]) 27 | } 28 | return src 29 | } 30 | -------------------------------------------------------------------------------- /packages/lib/utils/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "@config/tsconfig/base.json", 3 | "compilerOptions": { 4 | "target": "esnext", 5 | "module": "esnext", 6 | "baseUrl": "." 7 | }, 8 | "include": ["src"] 9 | } 10 | -------------------------------------------------------------------------------- /packages/lib/vite-plugin-code/build.config.ts: -------------------------------------------------------------------------------- 1 | import { defineBuildConfig } from 'unbuild' 2 | 3 | export default defineBuildConfig({ 4 | entries: ['src/index'], 5 | rollup: { 6 | inlineDependencies: true 7 | }, 8 | clean: true, 9 | declaration: true, 10 | failOnWarn: false 11 | }) 12 | -------------------------------------------------------------------------------- /packages/lib/vite-plugin-code/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "vite-plugin-code", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "dist/index.mjs", 6 | "module": "dist/index.mjs", 7 | "types": "dist/index.d.ts", 8 | "exports": { 9 | ".": { 10 | "import": { 11 | "types": "./dist/index.d.ts", 12 | "default": "./dist/index.mjs" 13 | }, 14 | "require": { 15 | "types": "./dist/index.d.ts", 16 | "default": "./dist/index.mjs" 17 | } 18 | } 19 | }, 20 | "files": [ 21 | "dist" 22 | ], 23 | "scripts": { 24 | "build": "unbuild", 25 | "dev": "unbuild", 26 | "lint:eslint": "eslint . --cache --max-warnings 0 --fix", 27 | "lint:prettier": "prettier --write --cache --ignore-unknown --ignore-path=../../../.prettierignore ." 28 | }, 29 | "keywords": [], 30 | "author": "", 31 | "license": "ISC", 32 | "dependencies": { 33 | "@vue/compiler-core": "^3.3.4", 34 | "@vue/compiler-dom": "^3.3.4", 35 | "@vue/compiler-sfc": "^3.3.4", 36 | "cheerio": "1.0.0-rc.12", 37 | "markdown-it": "^13.0.1", 38 | "node-html-parser": "^6.1.5", 39 | "pug": "^3.0.2", 40 | "vite": "catalog:" 41 | }, 42 | "devDependencies": { 43 | "unbuild": "^1.2.0" 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /packages/lib/vite-plugin-code/src/createFilter.ts: -------------------------------------------------------------------------------- 1 | // Picomatch is CJS only and causing conflicts so I am implementing a handler of the `FilterPattern` temporarily here 2 | 3 | export type FilterPattern = ReadonlyArray | string | RegExp | null 4 | 5 | function test(value: string, tst: string | RegExp): boolean { 6 | return typeof tst === 'string' ? value === tst : tst.test(value) 7 | } 8 | 9 | export function createFilter(include: FilterPattern, exclude?: FilterPattern) { 10 | const includeArr = Array.isArray(include) 11 | ? (include as ReadonlyArray) 12 | : include === null 13 | ? [] 14 | : ([include] as ReadonlyArray) 15 | 16 | const excludeArr = Array.isArray(exclude) 17 | ? (exclude as ReadonlyArray) 18 | : !exclude || exclude === null 19 | ? [] 20 | : ([exclude] as ReadonlyArray) 21 | 22 | return (val: string) => 23 | includeArr.some((t) => test(val, t)) && !excludeArr.some((t) => test(val, t)) 24 | } 25 | -------------------------------------------------------------------------------- /packages/lib/vite-plugin-code/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "@config/tsconfig/base.json", 3 | "compilerOptions": { 4 | "target": "esnext", 5 | "module": "esnext", 6 | "baseUrl": ".", 7 | "lib": ["dom", "esnext"], 8 | "types": ["vite/client"] 9 | }, 10 | "include": ["src"] 11 | } 12 | -------------------------------------------------------------------------------- /packages/lib/vue/.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | pnpm-debug.log* 8 | lerna-debug.log* 9 | 10 | node_modules 11 | dist 12 | dist-ssr 13 | *.local 14 | 15 | # Editor directories and files 16 | .vscode/* 17 | !.vscode/extensions.json 18 | .idea 19 | .DS_Store 20 | *.suo 21 | *.ntvs* 22 | *.njsproj 23 | *.sln 24 | *.sw? 25 | -------------------------------------------------------------------------------- /packages/lib/vue/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@tingcode/lib-vue", 3 | "version": "0.0.1", 4 | "description": "", 5 | "main": "dist/index.js", 6 | "type": "module", 7 | "types": "dist/index.d.ts", 8 | "scripts": { 9 | "build": "vite build", 10 | "dev": "vite build", 11 | "lint:eslint": "eslint . --cache --max-warnings 0 --fix --ignore-path=../../../.eslintignore", 12 | "lint:prettier": "prettier --write --cache --ignore-unknown --ignore-path=../../../.prettierignore ." 13 | }, 14 | "files": [ 15 | "dist" 16 | ], 17 | "keywords": [], 18 | "author": "", 19 | "license": "ISC", 20 | "devDependencies": { 21 | "@vitejs/plugin-vue": "catalog:", 22 | "@vitejs/plugin-vue-jsx": "catalog:", 23 | "postcss": "8.4.49", 24 | "sass": "catalog:", 25 | "typescript": "catalog:", 26 | "vite": "catalog:", 27 | "vite-plugin-dts": "^4.3.0", 28 | "vite-plugin-svg-icons": "catalog:" 29 | }, 30 | "dependencies": { 31 | "@tingcode/utils": "workspace:*", 32 | "@vueuse/core": "catalog:", 33 | "element-plus": "catalog:", 34 | "vue": "catalog:" 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /packages/lib/vue/src/assets/svg/common/left.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /packages/lib/vue/src/assets/svg/common/right.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /packages/lib/vue/src/components/demo/demo.vue: -------------------------------------------------------------------------------- 1 | 5 | 6 | 20 | -------------------------------------------------------------------------------- /packages/lib/vue/src/components/demo/index.ts: -------------------------------------------------------------------------------- 1 | import Demo from './demo.vue' 2 | 3 | export { Demo } 4 | export interface IDemoProps { 5 | loading?: boolean 6 | } 7 | -------------------------------------------------------------------------------- /packages/lib/vue/src/components/icon/SvgIcon.vue: -------------------------------------------------------------------------------- 1 | 10 | 11 | 38 | 39 | 63 | -------------------------------------------------------------------------------- /packages/lib/vue/src/components/icon/index.ts: -------------------------------------------------------------------------------- 1 | import SvgIcon from './SvgIcon.vue' 2 | import Icon from './icon.vue' 3 | 4 | export { SvgIcon, Icon } 5 | -------------------------------------------------------------------------------- /packages/lib/vue/src/components/index.ts: -------------------------------------------------------------------------------- 1 | export * from './demo/index' 2 | export * from './virtual-scroll/index' 3 | export * from './icon/index' 4 | -------------------------------------------------------------------------------- /packages/lib/vue/src/components/virtual-scroll/index.ts: -------------------------------------------------------------------------------- 1 | import VirtualScroll from './index.vue' 2 | 3 | export { VirtualScroll } 4 | -------------------------------------------------------------------------------- /packages/lib/vue/src/element-plus/button/button-map/index.vue: -------------------------------------------------------------------------------- 1 | 35 | -------------------------------------------------------------------------------- /packages/lib/vue/src/element-plus/button/index.ts: -------------------------------------------------------------------------------- 1 | import Button from './index.vue' 2 | import ElButton from 'element-plus/es/components/button/src/button.vue' 3 | 4 | export type IButtonMapType = 'confirm' | 'cancel' | 'search' 5 | export type ITButtonType = IButtonMapType | 'native' 6 | 7 | export type ElButtonInstance = InstanceType 8 | export type IElButtonAttrs = ElButtonInstance['$props'] 9 | export type IElButtonSlots = ElButtonInstance['$slots'] 10 | export type IElButtonEmits = ElButtonInstance['$emit'] 11 | 12 | export interface ITButtonProps extends /** @vue-ignore */ Omit { 13 | type?: ITButtonType | IElButtonAttrs['type'] 14 | } 15 | export type ReButtonProps = ITButtonProps 16 | 17 | export interface ReButtonEmits extends /** @vue-ignore */ IElButtonEmits {} 18 | 19 | export type ReButtonSlots = IElButtonSlots 20 | export const ReButton = Button 21 | export default ReButton 22 | -------------------------------------------------------------------------------- /packages/lib/vue/src/element-plus/button/index.vue: -------------------------------------------------------------------------------- 1 | 9 | 10 | 36 | -------------------------------------------------------------------------------- /packages/lib/vue/src/element-plus/demo/index.ts: -------------------------------------------------------------------------------- 1 | import REDemo from './index.vue' 2 | 3 | export { REDemo } 4 | -------------------------------------------------------------------------------- /packages/lib/vue/src/element-plus/demo/index.vue: -------------------------------------------------------------------------------- 1 | 9 | 10 | 19 | -------------------------------------------------------------------------------- /packages/lib/vue/src/element-plus/index.ts: -------------------------------------------------------------------------------- 1 | export * from './button/index' 2 | export * from './input/index' 3 | export * from './radio/index' 4 | export * from './select/index' 5 | export * from './checkbox/index' 6 | export * from './demo/index' 7 | -------------------------------------------------------------------------------- /packages/lib/vue/src/hooks/index.ts: -------------------------------------------------------------------------------- 1 | export { useEventListener } from '@vueuse/core' 2 | export * from './useSlots' 3 | export * from './useContext' 4 | export * from './useDialog' 5 | -------------------------------------------------------------------------------- /packages/lib/vue/src/hooks/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( 22 | context: any, 23 | key: InjectionKey = Symbol(), 24 | options: CreateContextOptions = {} 25 | ) { 26 | const { readonly = true, createProvider = false, native = false } = options 27 | 28 | const state = reactive(context) 29 | const provideData = readonly ? defineReadonly(state) : state 30 | !createProvider && provide(key, native ? context : provideData) 31 | 32 | return { 33 | state 34 | } 35 | } 36 | 37 | export function useContext(key: InjectionKey, native?: boolean): T 38 | export function useContext(key: InjectionKey, defaultValue?: any, native?: boolean): T 39 | 40 | export function useContext( 41 | key: InjectionKey = Symbol(), 42 | defaultValue?: any 43 | ): ShallowUnwrap { 44 | return inject(key, defaultValue || {}) 45 | } 46 | -------------------------------------------------------------------------------- /packages/lib/vue/src/hooks/useDialog.ts: -------------------------------------------------------------------------------- 1 | import { DialogProps, ElDialog, ElConfigProvider } from 'element-plus' 2 | import { App, Component, createApp, h, ref } from 'vue' 3 | 4 | export const useDialog = >( 5 | options?: T, 6 | component?: Component, 7 | namespace: string = 'admin' 8 | ) => { 9 | const Dialog = component || ElDialog 10 | const visible = ref(false) 11 | const appDocument = document.querySelector('#app')! 12 | let div: HTMLDivElement 13 | let app: App 14 | const create = () => { 15 | div = document.createElement('div') 16 | appDocument.appendChild(div) 17 | app = createApp({ 18 | render() { 19 | return h(ElConfigProvider, { namespace } as any, () => 20 | h(Dialog, { 21 | modelValue: visible.value, 22 | 'onUpdate:modelValue': (newVisible) => { 23 | visible.value = newVisible 24 | }, 25 | ...options 26 | }) 27 | ) 28 | } 29 | }) 30 | app.mount(div) 31 | } 32 | const close = () => { 33 | app.unmount() 34 | div.remove() 35 | } 36 | const hide = () => { 37 | visible.value = false 38 | } 39 | const show = () => { 40 | visible.value = true 41 | } 42 | return { 43 | hide, 44 | show, 45 | close, 46 | create 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /packages/lib/vue/src/hooks/useSlots.ts: -------------------------------------------------------------------------------- 1 | import { Slots } from 'vue' 2 | import { isFunction } from '@tingcode/utils' 3 | 4 | /** 5 | * @description: 获取插槽内容 6 | */ 7 | export function getSlot( 8 | slots: Slots, 9 | slot = 'default', 10 | data?: any, 11 | opts?: { 12 | disabled: boolean 13 | [key: string]: any 14 | } 15 | ) { 16 | if (!slots || !Reflect.has(slots, slot)) { 17 | return null 18 | } 19 | if (!isFunction(slots[slot])) { 20 | console.error(`${slot} is not a function!`) 21 | return null 22 | } 23 | const slotFn = slots[slot] 24 | if (!slotFn) return null 25 | const params = { ...data, ...opts } 26 | return slotFn(params) 27 | } 28 | 29 | /** 30 | * @description 拓展插槽 31 | * @param slots 32 | * @param excludeKeys 33 | */ 34 | export function extendSlots(slots: Slots, excludeKeys: string[] = []) { 35 | const slotKeys = Object.keys(slots) 36 | const ret: any = {} 37 | slotKeys.forEach((key) => { 38 | if (!excludeKeys.includes(key)) { 39 | ret[key] = (data?: any) => getSlot(slots, key, data) 40 | } 41 | }) 42 | return ret 43 | } 44 | -------------------------------------------------------------------------------- /packages/lib/vue/src/index.scss: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ting-Code/Ting-Library-Monorepo/9cc73df070e2f9d4660312447f49ae7c5cd32753/packages/lib/vue/src/index.scss -------------------------------------------------------------------------------- /packages/lib/vue/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from './element-plus/index' 2 | export * from './components/index' 3 | export * from './hooks/index' 4 | -------------------------------------------------------------------------------- /packages/lib/vue/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "@config/tsconfig/base.json", 3 | "compilerOptions": { 4 | "target": "esnext", 5 | "module": "esnext", 6 | "baseUrl": ".", 7 | "paths": { 8 | "@/*": ["src/*"] 9 | }, 10 | "lib": ["dom", "esnext"], 11 | "types": ["vite/client"] 12 | }, 13 | "include": [ 14 | "src", 15 | "vite.config.ts", 16 | "src/**/*.ts", 17 | "src/**/*.d.ts", 18 | "src/**/*.tsx", 19 | "src/**/*.vue" 20 | ] 21 | } 22 | -------------------------------------------------------------------------------- /pnpm-workspace.yaml: -------------------------------------------------------------------------------- 1 | packages: 2 | - packages/** 3 | - configs/* 4 | - scripts 5 | 6 | catalog: 7 | '@vueuse/core': 13.0.0 8 | '@vueuse/integrations': 13.0.0 9 | '@vitejs/plugin-vue': 5.2.1 10 | '@vitejs/plugin-vue-jsx': 4.1.1 11 | typescript: 5.8.2 12 | vite: 6.2.1 13 | vitest: 3.1.1 14 | unbuild: 3.5.0 15 | vue: 3.5.13 16 | element-plus: 2.9.6 17 | pinia: 3.0.1 18 | vue-router: 4.5.0 19 | sass: 1.85.1 20 | dayjs: 1.11.13 21 | vite-plugin-compression: 0.5.1 22 | vite-plugin-eslint: 1.8.1 23 | vite-plugin-md: 0.21.5 24 | vite-plugin-mock: 2.9.6 25 | vite-plugin-svg-icons: 2.0.1 26 | vue-tsc: 2.2.8 27 | unplugin-auto-import: 19.1.1 28 | unplugin-vue-components: 28.4.1 29 | 30 | onlyBuiltDependencies: 31 | - '@parcel/watcher' 32 | - esbuild 33 | - vue-demi 34 | -------------------------------------------------------------------------------- /scripts/build.ts: -------------------------------------------------------------------------------- 1 | import { runPromptsSelect, runSingleScript, getPackages, runScript } from './helper' 2 | 3 | export async function runBuild() { 4 | const command = 'build' 5 | const main = async () => { 6 | const packages = await getPackages((pkg) => { 7 | return !!pkg 8 | // return [ 9 | // '@apps/admin', 10 | // '@apps/micro', 11 | // ].includes(pkg.name) 12 | }) 13 | if (!packages.length) { 14 | console.log('没识别到任何项目') 15 | return 16 | } 17 | if (packages.length === 1) { 18 | runSingleScript(packages[0], command) 19 | return 20 | } 21 | const { value } = await runPromptsSelect(packages, { type: 'multiselect' }) 22 | 23 | runScript( 24 | packages.filter((p) => value.includes(p.name)), 25 | command 26 | ) 27 | } 28 | 29 | main().catch((error) => { 30 | console.error(error) 31 | process.exit(1) 32 | }) 33 | } 34 | 35 | runBuild() 36 | -------------------------------------------------------------------------------- /scripts/dev.ts: -------------------------------------------------------------------------------- 1 | import { runPromptsSelect, runSingleScript, getPackages, runScript } from './helper' 2 | 3 | export async function runDev() { 4 | const command = 'dev' 5 | const main = async () => { 6 | const packages = await getPackages((p) => p.name.startsWith('@apps')) 7 | if (!packages.length) { 8 | console.log('没识别到任何项目') 9 | return 10 | } 11 | 12 | if (packages.length === 1) { 13 | runSingleScript(packages[0], command) 14 | return 15 | } 16 | const { value } = await runPromptsSelect(packages, { type: 'multiselect' }) 17 | 18 | runScript( 19 | packages.filter((p) => value.includes(p.name)), 20 | command 21 | ) 22 | } 23 | 24 | main().catch((error) => { 25 | console.error(error) 26 | process.exit(1) 27 | }) 28 | } 29 | 30 | runDev() 31 | -------------------------------------------------------------------------------- /scripts/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "scripts", 3 | "private": true, 4 | "bin": {}, 5 | "scripts": { 6 | "clean": "pnpm rimraf node_modules && pnpm rimraf dist && pnpm rimraf .turbo", 7 | "dev": "pnpm esno ./dev.ts", 8 | "build": "pnpm esno ./build.ts", 9 | "lint:eslint": "eslint . --cache --max-warnings 0 --fix", 10 | "lint:prettier": "prettier --write --cache --ignore-unknown --ignore-path=../.prettierignore ." 11 | }, 12 | "devDependencies": { 13 | "@types/prompts": "^2.4.0", 14 | "execa": "^7.0.0", 15 | "prompts": "^2.4.2" 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /turbo.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://turborepo.org/schema.json", 3 | "pipeline": { 4 | "build": { 5 | "outputs": ["dist/**"], 6 | "dependsOn": ["^build"] 7 | }, 8 | "clean": { 9 | "outputs": [], 10 | "dependsOn": ["^clean"] 11 | }, 12 | "stub": {}, 13 | "test": { 14 | "dependsOn": ["^test"], 15 | "outputs": [] 16 | }, 17 | "dev": { 18 | "cache": false 19 | }, 20 | "lint:eslint": {}, 21 | "lint:prettier": {}, 22 | "lint:stylelint": {} 23 | } 24 | } 25 | --------------------------------------------------------------------------------