├── .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 |
2 |
3 |
4 |
5 |
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 |
2 |
3 |
4 |
5 |
6 |
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 |
2 |
3 |
4 |
5 |
6 |
45 |
46 |
60 |
--------------------------------------------------------------------------------
/packages/apps/admin/src/views/common/login/components/matter/index.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
40 |
41 |
52 |
--------------------------------------------------------------------------------
/packages/apps/admin/src/views/common/login/components/nav/index.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
23 |
24 |
49 |
--------------------------------------------------------------------------------
/packages/apps/admin/src/views/common/login/components/rotation/microapp.vue:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
9 |
18 |
19 |
47 |
--------------------------------------------------------------------------------
/packages/apps/admin/src/views/common/login/components/rotation/pnpm.vue:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
9 |
18 |
19 |
57 |
--------------------------------------------------------------------------------
/packages/apps/admin/src/views/common/login/components/rotation/ts.vue:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
9 |
18 |
19 |
57 |
--------------------------------------------------------------------------------
/packages/apps/admin/src/views/common/login/index.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
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 |
2 |
3 |
12 |
13 |
14 |
15 |
16 |
31 |
32 |
42 |
--------------------------------------------------------------------------------
/packages/apps/admin/src/views/layouts/default/feature/setting/index.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | {{ t('layout.settings.title') }}
5 |
6 |
7 |
8 | 主题
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
25 |
26 |
33 |
--------------------------------------------------------------------------------
/packages/apps/admin/src/views/layouts/default/feature/setting/theme/index.vue:
--------------------------------------------------------------------------------
1 |
2 | 主题
3 |
4 |
5 |
6 |
16 |
--------------------------------------------------------------------------------
/packages/apps/admin/src/views/layouts/default/header/setting/index.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
14 |
--------------------------------------------------------------------------------
/packages/apps/admin/src/views/layouts/default/header/trigger/index.vue:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
10 |
20 |
21 |
28 |
--------------------------------------------------------------------------------
/packages/apps/admin/src/views/layouts/default/main/index.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
31 |
32 |
39 |
--------------------------------------------------------------------------------
/packages/apps/admin/src/views/layouts/default/navIcon/index.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
8 |
13 |
18 |
19 |
20 |
21 |
35 |
36 |
46 |
--------------------------------------------------------------------------------
/packages/apps/admin/src/views/layouts/default/tabs/full/index.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
13 |
--------------------------------------------------------------------------------
/packages/apps/admin/src/views/layouts/default/tabs/set/index.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 | 刷新页面
9 |
10 | removeTab()">
11 | 关闭当前
12 |
13 |
14 | 关闭所有
15 |
16 |
17 |
18 |
19 |
20 |
21 |
31 |
--------------------------------------------------------------------------------
/packages/apps/admin/src/views/layouts/default/theme/index.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
22 |
--------------------------------------------------------------------------------
/packages/apps/admin/src/views/layouts/micro/index.vue:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 |
11 |
15 |
16 |
25 |
--------------------------------------------------------------------------------
/packages/apps/admin/src/views/layouts/parentLayout/index.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
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 |
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 |
2 |
3 |
4 |
5 |
6 |
7 |
10 |
--------------------------------------------------------------------------------
/packages/apps/micro-docs/src/application/Application.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
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 |
2 |
8 |
9 |
10 |
30 |
31 |
42 |
--------------------------------------------------------------------------------
/packages/apps/micro-docs/src/components/icon/svg-icon.vue:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 |
11 |
38 |
39 |
63 |
--------------------------------------------------------------------------------
/packages/apps/micro-docs/src/components/markdown/index.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
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 |
2 |
3 |
4 |
5 |
6 |
7 |
10 |
--------------------------------------------------------------------------------
/packages/apps/micro-docs/src/views/basics/git/index.docs.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
10 |
--------------------------------------------------------------------------------
/packages/apps/micro-docs/src/views/basics/linux/index.docs.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
10 |
--------------------------------------------------------------------------------
/packages/apps/micro-docs/src/views/basics/network/index.docs.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
10 |
--------------------------------------------------------------------------------
/packages/apps/micro-docs/src/views/basics/node/index.docs.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
10 |
--------------------------------------------------------------------------------
/packages/apps/micro-docs/src/views/common/iframe/index.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
45 |
46 |
60 |
--------------------------------------------------------------------------------
/packages/apps/micro-docs/src/views/performance/optimization/index.docs.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
10 |
--------------------------------------------------------------------------------
/packages/apps/micro-docs/src/views/performance/virtual-scroll/demo/fixation-height.demo.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | {{ item.label }}
7 |
8 |
9 |
10 |
11 |
12 |
13 |
29 |
30 |
35 |
--------------------------------------------------------------------------------
/packages/apps/micro-docs/src/views/performance/virtual-scroll/index.docs.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | ### 固定高度虚拟列表
8 |
9 |
10 |
11 |
12 |
13 | ### 动态高度虚拟列表
14 | 动态高度虚拟列表可通过成熟的插件实现
15 | ```
16 | pnpm add vue-virtual-scroller@next
17 | ```
18 |
19 | ```javascript
20 | import { RecycleScroller } from 'vue-virtual-scroller'
21 | import 'vue-virtual-scroller/dist/vue-virtual-scroller.css'
22 | ```
23 |
24 |
25 |
26 |
27 |
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 |
2 | console.log('确定', e)"> 原生EP组件
3 | console.log('确定', e)" />
4 | console.log('取消', e)" />
5 | console.log('搜索', e)" />
6 |
7 |
10 |
--------------------------------------------------------------------------------
/packages/apps/micro-docs/src/views/repackage/components/demo/checkbox.demo.vue:
--------------------------------------------------------------------------------
1 |
2 | options来传递对应选项参数,支持format来更改映射值
3 |
11 |
12 | label:{{ label }}
13 |
14 |
15 |
16 |
20 |
--------------------------------------------------------------------------------
/packages/apps/micro-docs/src/views/repackage/components/demo/input.demo.vue:
--------------------------------------------------------------------------------
1 |
2 | 利用valueFormat处理绑定值,keepNumbers只允许数字
3 |
4 | 利用format来处理显示千分位,只影响显示不影响绑定值
5 |
6 | 可以自定义函数来处理值
7 |
12 | 支持多个函数/预设函数处理,是一个返回值为下一个函数参数
13 |
14 | 原有ElInput正常按element文档使用,并且保持良好的属性提示
15 |
16 |
17 |
18 |
19 |
20 |
21 |
27 |
--------------------------------------------------------------------------------
/packages/apps/micro-docs/src/views/repackage/components/demo/radio.demo.vue:
--------------------------------------------------------------------------------
1 |
2 | options来传递对应选项参数,并且支持原有组件插件传递
3 |
12 |
13 |
14 | {{ label }}
15 |
16 |
17 |
18 |
19 |
26 |
--------------------------------------------------------------------------------
/packages/apps/micro-docs/src/views/repackage/components/demo/select.demo.vue:
--------------------------------------------------------------------------------
1 |
2 | options来传递对应选项参数,支持format来更改映射值
3 |
15 |
16 | {{ label }}:
17 | {{ value }}
18 |
19 |
20 |
21 |
29 |
--------------------------------------------------------------------------------
/packages/apps/micro-docs/src/views/system/auto-publish/demo/micro-app.demo.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
9 |
--------------------------------------------------------------------------------
/packages/apps/micro-docs/src/views/system/css/demo/bem.demo.vue:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
9 |
18 |
19 |
31 |
--------------------------------------------------------------------------------
/packages/apps/micro-docs/src/views/system/css/demo/tailwind.demo.vue:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
--------------------------------------------------------------------------------
/packages/apps/micro-docs/src/views/system/docs/demo/button.demo.vue:
--------------------------------------------------------------------------------
1 |
2 | 这是一个EP按钮
3 |
4 |
--------------------------------------------------------------------------------
/packages/apps/micro-docs/src/views/system/home/index.docs.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
10 |
--------------------------------------------------------------------------------
/packages/apps/micro-docs/src/views/system/micro/demo/micro-app.demo.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
9 |
--------------------------------------------------------------------------------
/packages/apps/micro-docs/src/views/visual/animation/demo/bounce.demo.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
开始弹跳动画
4 |
结束弹跳动画
5 |
6 |
7 |
8 |
9 |
34 |
35 |
48 |
--------------------------------------------------------------------------------
/packages/apps/micro-docs/src/views/visual/animation/demo/fade.demo.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
开始淡入动画
4 |
结束淡入动画
5 |
6 |
7 |
8 |
9 |
32 |
33 |
46 |
--------------------------------------------------------------------------------
/packages/apps/micro-docs/src/views/visual/animation/demo/pulse.demo.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
开始脉冲动画
4 |
结束脉冲动画
5 |
6 |
7 |
8 |
9 |
34 |
35 |
48 |
--------------------------------------------------------------------------------
/packages/apps/micro-docs/src/views/visual/animation/demo/rotate.demo.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
开始旋转动画
4 |
结束旋转动画
5 |
6 |
7 |
8 |
9 |
34 |
35 |
48 |
--------------------------------------------------------------------------------
/packages/apps/micro-docs/src/views/visual/animation/demo/scale.demo.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
开始缩放动画
4 |
结束缩放动画
5 |
6 |
7 |
8 |
9 |
34 |
35 |
48 |
--------------------------------------------------------------------------------
/packages/apps/micro-docs/src/views/visual/animation/demo/slide.demo.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
开始滑动动画
4 |
结束滑动动画
5 |
6 |
7 |
8 |
9 |
32 |
33 |
46 |
--------------------------------------------------------------------------------
/packages/apps/micro-docs/src/views/visual/chart/demo/box.demo.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
39 |
--------------------------------------------------------------------------------
/packages/apps/micro-docs/src/views/visual/chart/demo/bubble.demo.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
43 |
--------------------------------------------------------------------------------
/packages/apps/micro-docs/src/views/visual/chart/demo/gauge.demo.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
31 |
--------------------------------------------------------------------------------
/packages/apps/micro-docs/src/views/visual/chart/demo/heatmap.demo.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
34 |
--------------------------------------------------------------------------------
/packages/apps/micro-docs/src/views/visual/chart/demo/map.demo.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
25 |
--------------------------------------------------------------------------------
/packages/apps/micro-docs/src/views/visual/chart/demo/pie.demo.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
41 |
--------------------------------------------------------------------------------
/packages/apps/micro-docs/src/views/visual/chart/demo/radar.demo.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
38 |
--------------------------------------------------------------------------------
/packages/apps/micro-docs/src/views/visual/chart/demo/sankey.demo.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
37 |
--------------------------------------------------------------------------------
/packages/apps/micro-docs/src/views/visual/chart/demo/sunburst.demo.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
47 |
--------------------------------------------------------------------------------
/packages/apps/micro-docs/src/views/visual/chart/demo/tree.demo.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
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 |
2 | {{ props.title + props.name || '' }}
3 |
4 |
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 |
2 |
9 |
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 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
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 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
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 |
--------------------------------------------------------------------------------