├── .editorconfig
├── .env.build
├── .env.build-test
├── .env.serve-dev
├── .env.serve-local
├── .env.serve-test
├── .eslintignore
├── .eslintrc.json
├── .gitignore
├── .husky
├── commit-msg
└── pre-commit
├── .npmrc
├── .prettierrc
├── .vscode
├── extensions.json
└── settings.json
├── README.md
├── eslintrc
├── .eslintrc-auto-import.json
└── eslint-config.cjs
├── index.html
├── mock-prod-server.ts
├── mock
├── example.ts
├── excel.ts
└── table.ts
├── optimize-include.ts
├── package.json
├── public
└── favicon.ico
├── src
├── App.vue
├── api
│ ├── dataAuth.ts
│ ├── dept.ts
│ ├── dict.ts
│ ├── dictData.ts
│ ├── loginInfo.ts
│ ├── menu.ts
│ ├── operatorLog.ts
│ ├── oss.ts
│ ├── ossConfig.ts
│ ├── platform.ts
│ ├── post.ts
│ ├── rbac.ts
│ ├── remote-search.ts
│ ├── role.ts
│ ├── system
│ │ └── dict
│ │ │ ├── data.js
│ │ │ └── type.js
│ ├── table.ts
│ └── user.ts
├── assets
│ ├── 401_images
│ │ └── 401.gif
│ ├── 404_images
│ │ ├── 404.png
│ │ └── 404_cloud.png
│ ├── gif
│ │ └── dianchi.gif
│ └── layout
│ │ ├── animation-image.gif
│ │ ├── login-bg.svg
│ │ ├── login-front.svg
│ │ ├── login-top.svg
│ │ ├── login.svg
│ │ └── logo.png
├── components
│ ├── ColumnFilter.vue
│ ├── DictTag.vue
│ ├── ElSvgIcon.vue
│ ├── FileUpload
│ │ ├── imgDillUtils.ts
│ │ └── index.vue
│ ├── InnerLink
│ │ └── index.vue
│ ├── JsonInput.vue
│ ├── Pagination
│ │ └── index.vue
│ ├── ParentView
│ │ └── index.vue
│ ├── RightToolBar.vue
│ ├── RightToolbar
│ │ └── index.vue
│ ├── TestUnit.vue
│ └── __tests__
│ │ └── el-svgIcon.test.jsx
├── directives
│ ├── example
│ │ ├── clickoutside.js
│ │ ├── copy.js
│ │ ├── debounce.js
│ │ ├── longpress.js
│ │ ├── watermark.js
│ │ ├── waves.css
│ │ └── waves.js
│ ├── has-perm.ts
│ ├── has-role.ts
│ ├── index.ts
│ └── lang.ts
├── hooks
│ ├── use-common.ts
│ ├── use-data-dict.ts
│ ├── use-element.ts
│ ├── use-error-log.ts
│ ├── use-layout.ts
│ ├── use-menu.ts
│ ├── use-permission.ts
│ ├── use-self-router.ts
│ └── use-table.ts
├── icons
│ ├── SvgIcon.vue
│ ├── common
│ │ ├── 404.svg
│ │ ├── bug.svg
│ │ ├── build.svg
│ │ ├── button.svg
│ │ ├── cascader.svg
│ │ ├── chart.svg
│ │ ├── checkbox.svg
│ │ ├── clipboard.svg
│ │ ├── code.svg
│ │ ├── color.svg
│ │ ├── component.svg
│ │ ├── dashboard.svg
│ │ ├── date-range.svg
│ │ ├── date.svg
│ │ ├── demo.svg
│ │ ├── dict.svg
│ │ ├── documentation.svg
│ │ ├── download.svg
│ │ ├── drag.svg
│ │ ├── druid.svg
│ │ ├── edit.svg
│ │ ├── education.svg
│ │ ├── email.svg
│ │ ├── example.svg
│ │ ├── excel.svg
│ │ ├── exit-fullscreen.svg
│ │ ├── eye-open.svg
│ │ ├── eye.svg
│ │ ├── form.svg
│ │ ├── fullscreen.svg
│ │ ├── github.svg
│ │ ├── guide.svg
│ │ ├── hamburger.svg
│ │ ├── icon.svg
│ │ ├── input.svg
│ │ ├── international.svg
│ │ ├── job.svg
│ │ ├── language.svg
│ │ ├── link.svg
│ │ ├── list.svg
│ │ ├── lock.svg
│ │ ├── log.svg
│ │ ├── logininfor.svg
│ │ ├── message.svg
│ │ ├── money.svg
│ │ ├── monitor.svg
│ │ ├── nested.svg
│ │ ├── number.svg
│ │ ├── online.svg
│ │ ├── password.svg
│ │ ├── pdf.svg
│ │ ├── people.svg
│ │ ├── peoples.svg
│ │ ├── phone.svg
│ │ ├── post.svg
│ │ ├── qq.svg
│ │ ├── question.svg
│ │ ├── radio.svg
│ │ ├── rate.svg
│ │ ├── redis-list.svg
│ │ ├── redis.svg
│ │ ├── row.svg
│ │ ├── search.svg
│ │ ├── select.svg
│ │ ├── server.svg
│ │ ├── shopping.svg
│ │ ├── sidebar-logo.svg
│ │ ├── size.svg
│ │ ├── skill.svg
│ │ ├── slider.svg
│ │ ├── star.svg
│ │ ├── swagger.svg
│ │ ├── switch.svg
│ │ ├── system.svg
│ │ ├── tab.svg
│ │ ├── table.svg
│ │ ├── textarea.svg
│ │ ├── theme.svg
│ │ ├── time-range.svg
│ │ ├── time.svg
│ │ ├── tool.svg
│ │ ├── tree-table.svg
│ │ ├── tree.svg
│ │ ├── upload.svg
│ │ ├── user.svg
│ │ ├── validCode.svg
│ │ ├── wechat.svg
│ │ └── zip.svg
│ └── nav-bar
│ │ ├── dashboard.svg
│ │ ├── example.svg
│ │ ├── eye-open.svg
│ │ ├── eye.svg
│ │ ├── form.svg
│ │ ├── language.svg
│ │ ├── link.svg
│ │ ├── nested.svg
│ │ ├── password.svg
│ │ ├── table.svg
│ │ ├── theme-icon.svg
│ │ ├── tree.svg
│ │ ├── user.svg
│ │ └── validCode.svg
├── lang
│ ├── en.ts
│ ├── index.ts
│ └── zh.ts
├── layout
│ ├── app-main
│ │ ├── Breadcrumb.vue
│ │ ├── Hamburger.vue
│ │ ├── Navbar.vue
│ │ ├── TagsView.vue
│ │ ├── component
│ │ │ ├── LangSelect.vue
│ │ │ ├── ScreenFull.vue
│ │ │ ├── ScreenLock.vue
│ │ │ ├── SizeSelect.vue
│ │ │ └── ThemeSelect.vue
│ │ └── index.vue
│ ├── index.vue
│ └── sidebar
│ │ ├── Link.vue
│ │ ├── Logo.vue
│ │ ├── MenuIcon.vue
│ │ ├── SidebarItem.vue
│ │ └── index.vue
├── lib
│ ├── el-svg-icon.ts
│ └── element-plus.ts
├── main.ts
├── permission.ts
├── plugins
│ └── vite-plugin-setup-extend
│ │ └── index.ts
├── router
│ ├── index.ts
│ └── modules
│ │ ├── basic-demo.ts
│ │ ├── charts.ts
│ │ ├── directive.ts
│ │ ├── excel.ts
│ │ ├── guid.ts
│ │ ├── other.ts
│ │ ├── rich-text.ts
│ │ └── table.ts
├── settings.ts
├── store
│ ├── basic.ts
│ ├── config.ts
│ ├── dict.ts
│ └── tags-view.ts
├── styles
│ ├── index.scss
│ ├── init-loading.css
│ ├── project-style.scss
│ ├── reset-elemenet-plus.scss
│ ├── scss-suger.scss
│ └── transition.scss
├── theme
│ ├── base
│ │ ├── custom
│ │ │ └── ct-css-vars.scss
│ │ ├── element-plus
│ │ │ ├── button.scss
│ │ │ ├── checkbox.scss
│ │ │ ├── css-vars.scss
│ │ │ ├── form.scss
│ │ │ ├── pagination.scss
│ │ │ ├── redio.scss
│ │ │ ├── table.scss
│ │ │ └── var.scss
│ │ └── index.scss
│ ├── china-red
│ │ ├── custom
│ │ │ └── ct-css-vars.scss
│ │ ├── element-plus
│ │ │ ├── button.scss
│ │ │ ├── checkbox.scss
│ │ │ ├── css-vars.scss
│ │ │ ├── form.scss
│ │ │ ├── pagination.scss
│ │ │ ├── redio.scss
│ │ │ ├── table.scss
│ │ │ └── var.scss
│ │ └── index.scss
│ ├── dark
│ │ ├── custom
│ │ │ └── ct-css-vars.scss
│ │ ├── element-plus
│ │ │ ├── button.scss
│ │ │ ├── checkbox.scss
│ │ │ ├── css-vars.css
│ │ │ ├── css-vars.css.map
│ │ │ ├── css-vars.scss
│ │ │ ├── form.scss
│ │ │ ├── pagination.scss
│ │ │ ├── redio.scss
│ │ │ ├── table.scss
│ │ │ └── var.scss
│ │ └── index.scss
│ ├── index.scss
│ ├── lighting
│ │ ├── custom
│ │ │ └── ct-css-vars.scss
│ │ ├── element-plus
│ │ │ ├── button.scss
│ │ │ ├── checkbox.scss
│ │ │ ├── css-vars.css
│ │ │ ├── css-vars.css.map
│ │ │ ├── css-vars.scss
│ │ │ ├── form.scss
│ │ │ ├── pagination.scss
│ │ │ ├── redio.scss
│ │ │ ├── table.scss
│ │ │ └── var.scss
│ │ └── index.scss
│ ├── mixins
│ │ ├── _var.scss
│ │ ├── config.scss
│ │ ├── function.scss
│ │ └── mixins.scss
│ └── utils
│ │ ├── change-theme.ts
│ │ └── index.ts
├── utils
│ ├── axios-req.ts
│ ├── bus.ts
│ ├── common-util.ts
│ ├── mock-axios-req.ts
│ └── scroll-to.ts
└── views
│ ├── charts
│ ├── components
│ │ ├── Keyboard.vue
│ │ ├── LineMarker.vue
│ │ ├── MixChart.vue
│ │ └── mixins
│ │ │ └── resize.js
│ ├── echarts-demo.vue
│ ├── keyboard.vue
│ ├── line.vue
│ └── mix-chart.vue
│ ├── d3
│ ├── component
│ │ └── NodeDetail.vue
│ ├── data.json
│ ├── relation-map.vue
│ ├── useD3.js
│ └── useDatas.js
│ ├── dashboard
│ ├── ElTag.vue
│ └── index.vue
│ ├── directive
│ ├── clickoutside.vue
│ ├── copy.vue
│ ├── debounce.vue
│ ├── longpress.vue
│ ├── watermark.vue
│ └── waves.vue
│ ├── error-page
│ ├── 401.vue
│ └── 404.vue
│ ├── excel
│ ├── excel.js
│ ├── exportExcel.vue
│ └── importExcel.vue
│ ├── form
│ ├── basic
│ │ └── index.vue
│ ├── config.ts
│ ├── dynamic
│ │ └── index.vue
│ └── validators.ts
│ ├── guide
│ ├── index.vue
│ └── steps.ts
│ ├── login
│ ├── index.vue
│ ├── login-alt.vue
│ ├── login-basic.vue
│ ├── login-lighting.vue
│ └── register.vue
│ ├── redirect
│ └── index.tsx
│ ├── rich-text
│ └── wang-edit
│ │ └── index.vue
│ ├── setting-switch
│ ├── SettingSwitch.vue
│ └── index.vue
│ ├── system
│ ├── dept
│ │ ├── AddEditModal.vue
│ │ ├── index-hook.ts
│ │ └── index.vue
│ ├── dict-data
│ │ ├── AddEditModal.vue
│ │ ├── index-hook.ts
│ │ └── index.vue
│ ├── dict
│ │ ├── AddEditModal.vue
│ │ ├── index-hook.ts
│ │ └── index.vue
│ ├── login-info
│ │ ├── index-hook.ts
│ │ └── index.vue
│ ├── menu
│ │ ├── AddEditModal.vue
│ │ ├── IconSelect.vue
│ │ ├── index-hook.js
│ │ ├── index.vue
│ │ └── requireIcons.js
│ ├── operator-log
│ │ ├── index-hook.ts
│ │ └── index.vue
│ ├── oss-config
│ │ ├── AddEditModal.vue
│ │ ├── index-hook.ts
│ │ └── index.vue
│ ├── oss
│ │ ├── UploadFileImage.vue
│ │ ├── imgDillUtils.js
│ │ ├── index-hook.ts
│ │ └── index.vue
│ ├── platform
│ │ ├── AddEditModal.vm
│ │ ├── AddEditModal.vue
│ │ ├── Import.vue
│ │ ├── index-hook.ts
│ │ ├── index.vm
│ │ └── index.vue
│ ├── post
│ │ ├── AddEditModal.vue
│ │ ├── index-hook.ts
│ │ └── index.vue
│ ├── role
│ │ ├── AddEditModal.vue
│ │ ├── DataAuthorModal.vue
│ │ ├── Import.vue
│ │ ├── SelectUser.vue
│ │ ├── auth-user.vue
│ │ ├── index-hook.js
│ │ └── index.vue
│ └── user
│ │ ├── AddEditModal.vue
│ │ ├── Import.vue
│ │ ├── auth-role.vue
│ │ ├── current-hook.js
│ │ └── index.vue
│ └── table
│ ├── DynamicTable.vue
│ ├── dynamic-table.vue
│ ├── index.vue
│ └── vxe-table.vue
├── ts-out-dir
├── package.json
└── src
│ ├── api
│ ├── user.d.ts
│ └── user.js
│ ├── directives
│ ├── button-codes.d.ts
│ ├── button-codes.js
│ ├── codes-permission.d.ts
│ ├── codes-permission.js
│ ├── index.d.ts
│ ├── index.js
│ ├── roles-permission.d.ts
│ └── roles-permission.js
│ ├── hooks
│ ├── use-common.d.ts
│ ├── use-common.js
│ ├── use-element.d.ts
│ ├── use-element.js
│ ├── use-error-log.d.ts
│ ├── use-error-log.js
│ ├── use-layout.d.ts
│ ├── use-layout.js
│ ├── use-permission.d.ts
│ ├── use-permission.js
│ ├── use-self-router.d.ts
│ ├── use-self-router.js
│ ├── use-table.d.ts
│ └── use-table.js
│ ├── lib
│ ├── element-plus.d.ts
│ └── element-plus.js
│ ├── main.d.ts
│ ├── main.js
│ ├── permission.d.ts
│ ├── permission.js
│ ├── router
│ ├── index.d.ts
│ └── index.js
│ ├── settings.d.ts
│ ├── settings.js
│ ├── store
│ ├── basic.d.ts
│ ├── basic.js
│ ├── tagsView.d.ts
│ └── tagsView.js
│ ├── utils
│ ├── axios-req.d.ts
│ ├── axios-req.js
│ ├── bus.d.ts
│ ├── bus.js
│ ├── common-util.d.ts
│ └── common-util.js
│ └── views
│ └── redirect
│ ├── index.d.ts
│ └── index.jsx
├── tsconfig.base.json
├── tsconfig.json
├── typings
├── auto-imports.d.ts
├── basic.d.ts
├── components.d.ts
├── env.d.ts
├── global.d.ts
└── shims-vue.d.ts
├── vite.config.ts
├── vitest.config.ts
└── vitest.setup.ts
/.editorconfig:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jzfai/vue3-admin-plus/e68d9108785ab118ef4fc0e6196a93778d2fff29/.editorconfig
--------------------------------------------------------------------------------
/.env.build:
--------------------------------------------------------------------------------
1 | VITE_APP_ENV = 'prod'
2 | #自动获取地址推荐
3 | VITE_APP_BASE_URL = 'https://github.jzfai.top/micro-service-api'
4 |
5 | #image or oss address
6 | VITE_APP_IMAGE_URL = 'https://github.jzfai.top/minio'
7 |
--------------------------------------------------------------------------------
/.env.build-test:
--------------------------------------------------------------------------------
1 | VITE_APP_ENV = 'test'
2 | #自动获取地址推荐
3 | #VITE_APP_BASE_URL = '/micro-service-api'
4 | VITE_APP_BASE_URL = 'https://github.jzfai.top/micro-service-api'
5 | VITE_APP_BASE_WS_URL = ''
6 |
7 | #image or oss address
8 | VITE_APP_IMAGE_URL = 'https://github.jzfai.top/minio'
9 |
--------------------------------------------------------------------------------
/.env.serve-dev:
--------------------------------------------------------------------------------
1 | #The defined variable must start with VITE_APP_
2 | VITE_APP_ENV = 'dev'
3 | VITE_APP_BASE_URL = 'https://github.jzfai.top/micro-service-api'
4 |
5 | #image or oss address
6 | VITE_APP_IMAGE_URL = 'https://github.jzfai.top/minio'
7 |
8 |
9 | #代理拦截前缀
10 | VITE_PROXY_BASE_URL = '/proxy'
11 | #proxy转发地址(请求完整地址)
12 | VITE_PROXY_URL = 'http://localhost:8081'
13 |
--------------------------------------------------------------------------------
/.env.serve-local:
--------------------------------------------------------------------------------
1 | #The defined variable must start with VITE_APP_
2 | VITE_APP_ENV = 'test'
3 | VITE_APP_BASE_URL = 'http://localhost:12050'
4 | #image or oss address
5 | VITE_APP_IMAGE_URL = 'https://github.jzfai.top/minio'
6 |
7 | #proxy, use this to test proxy
8 | #VITE_APP_BASE_URL = '/api'
9 | #VITE_APP_PROXY_URL = 'https://github.jzfai.top/micro-service-api'
10 |
--------------------------------------------------------------------------------
/.env.serve-test:
--------------------------------------------------------------------------------
1 | #The defined variable must start with VITE_APP_
2 | VITE_APP_ENV = 'test'
3 | VITE_APP_BASE_URL = 'http://localhost:30121'
4 | #image or oss address
5 | VITE_APP_IMAGE_URL = 'https://github.jzfai.top/minio'
6 |
7 | #proxy, use this to test proxy
8 | #VITE_APP_BASE_URL = '/api'
9 | #VITE_APP_PROXY_URL = 'https://github.jzfai.top/micro-service-api'
10 |
--------------------------------------------------------------------------------
/.eslintignore:
--------------------------------------------------------------------------------
1 | public
2 | node_modules
3 | .history
4 | .husky
5 | dist
6 | *.d.ts
7 |
--------------------------------------------------------------------------------
/.eslintrc.json:
--------------------------------------------------------------------------------
1 | {
2 | "root": true,
3 | "extends": ["./eslintrc/eslint-config.cjs", "./eslintrc/.eslintrc-auto-import.json"]
4 | }
5 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # compiled output
2 | /dist
3 | /dist-ssr
4 | /node_modules
5 |
6 | #lock
7 | pnpm-lock.yaml
8 |
9 | # Logs
10 | logs
11 | *.log
12 | npm-debug.log*
13 | pnpm-debug.log*
14 | yarn-debug.log*
15 | yarn-error.log*
16 | lerna-debug.log*
17 |
18 | # OS
19 | .DS_Store
20 |
21 | # Tests
22 | /coverage
23 | /.nyc_output
24 |
25 | # IDEs and editors
26 | /.idea
27 | .project
28 | .classpath
29 | .c9/
30 | *.launch
31 | .settings/
32 | *.sublime-workspace
33 |
34 | # IDE - VSCode
35 | .vscode/*
36 | !.vscode/settings.json
37 | !.vscode/tasks.json
38 | !.vscode/launch.json
39 | !.vscode/extensions.json
40 |
41 | # Other
42 | .history
43 | *.local
44 | yarn*
45 | pnpm*
46 |
47 |
48 | #.eslintrc-auto-import.json
49 | #auto-imports.d.ts
50 | #components.d.ts
51 | stats.html
52 |
--------------------------------------------------------------------------------
/.husky/commit-msg:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 | #. "$(dirname "$0")/_/husky.sh"
3 | #在项目中我们会使用commit-msg这个git hook来校验我们commit时添加的备注信息是否符合规范。在以前的我们通常是这样配置:
4 | #--no-install 参数表示强制npx使用项目中node_modules目录中的commitlint包(如果需要开启,注意:需要安装npx)
5 | #npx --no-install commitlint --edit $1
6 |
--------------------------------------------------------------------------------
/.husky/pre-commit:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 | . "$(dirname "$0")/_/husky.sh"
3 |
4 | #推送之前运行eslint检查
5 | npm run lint
6 | #推送之前运行单元测试检查
7 | #npm run test:unit
8 |
9 |
--------------------------------------------------------------------------------
/.npmrc:
--------------------------------------------------------------------------------
1 | shamefully-hoist=true
2 | strict-peer-dependencies=false
3 |
4 | ###aliyun address
5 | registry = https://registry.npmmirror.com
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/.prettierrc:
--------------------------------------------------------------------------------
1 | {
2 | "useTabs": false,
3 | "tabWidth": 2,
4 | "printWidth": 120,
5 | "singleQuote": true,
6 | "trailingComma": "none",
7 | "bracketSpacing": true,
8 | "semi": false,
9 | "htmlWhitespaceSensitivity": "ignore"
10 | }
11 |
--------------------------------------------------------------------------------
/.vscode/extensions.json:
--------------------------------------------------------------------------------
1 | {
2 | "recommendations": ["johnsoncodehk.volar", "esbenp.prettier-vscode","dbaeumer.vscode-eslint"]
3 | }
4 |
--------------------------------------------------------------------------------
/.vscode/settings.json:
--------------------------------------------------------------------------------
1 | {
2 | "editor.defaultFormatter": "esbenp.prettier-vscode",
3 | "npm.packageManager": "yarn"
4 | }
5 |
--------------------------------------------------------------------------------
/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 | <%= title %>
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
--------------------------------------------------------------------------------
/mock-prod-server.ts:
--------------------------------------------------------------------------------
1 | import { createProdMockServer } from 'vite-plugin-mock/es/createProdMockServer'
2 | //https://cn.vitejs.dev/guide/features.html#glob-import
3 | const modulesFiles = import.meta.glob('../mock/*', { eager: true })
4 | let modules = []
5 | for (const filePath in modulesFiles) {
6 | //读取文件内容到 modules
7 | modules = modules.concat(modulesFiles[filePath].default)
8 | }
9 | export function setupProdMockServer() {
10 | //创建prod mock server
11 | createProdMockServer([...modules])
12 | }
13 |
--------------------------------------------------------------------------------
/mock/example.ts:
--------------------------------------------------------------------------------
1 | export default [
2 | {
3 | url: '/getMapInfo',
4 | method: 'get',
5 | response: () => {
6 | return {
7 | code: 200,
8 | title: 'mock请求测试'
9 | }
10 | }
11 | }
12 | ]
13 |
--------------------------------------------------------------------------------
/mock/excel.ts:
--------------------------------------------------------------------------------
1 | import Mock from 'mockjs'
2 |
3 | const NameList: any = []
4 | const count = 100
5 |
6 | for (let i = 0; i < count; i++) {
7 | NameList.push(
8 | Mock.mock({
9 | name: '@first'
10 | })
11 | )
12 | }
13 | NameList.push({ name: 'mock-Pan' })
14 |
15 | export default [
16 | {
17 | url: '/vue3-admin-plus/search/user',
18 | method: 'get',
19 | response: (config) => {
20 | const { name } = config.query
21 | const mockNameList = NameList.filter((item) => {
22 | // @ts-ignore
23 | const lowerCaseName = item.name.toLowerCase()
24 | return !(name && !lowerCaseName.includes(name.toLowerCase()))
25 | })
26 | return {
27 | code: 20000,
28 | data: { items: mockNameList }
29 | }
30 | }
31 | },
32 | {
33 | url: '/vue3-admin-plus/transaction/list',
34 | method: 'get',
35 | response: () => {
36 | return {
37 | code: 20000,
38 | data: {
39 | total: 20,
40 | 'items|20': [
41 | {
42 | order_no: '@guid()',
43 | timestamp: +Mock.Random.date('T'),
44 | username: '@name()',
45 | price: '@float(1000, 15000, 0, 2)',
46 | 'status|1': ['success', 'pending']
47 | }
48 | ]
49 | }
50 | }
51 | }
52 | }
53 | ]
54 |
--------------------------------------------------------------------------------
/mock/table.ts:
--------------------------------------------------------------------------------
1 | import Mock from 'mockjs'
2 |
3 | const data = Mock.mock({
4 | 'items|30': [
5 | {
6 | id: '@id',
7 | title: '@sentence(10, 20)',
8 | 'status|1': ['published', 'draft', 'deleted'],
9 | author: 'name',
10 | display_time: '@datetime',
11 | pageviews: '@integer(300, 5000)'
12 | }
13 | ]
14 | })
15 |
16 | export default [
17 | {
18 | url: '/vue3-admin-plus/table/list',
19 | method: 'get',
20 | response: () => {
21 | const items = data.items
22 | return {
23 | code: 20000,
24 | data: {
25 | total: items.length,
26 | items
27 | }
28 | }
29 | }
30 | }
31 | ]
32 |
--------------------------------------------------------------------------------
/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jzfai/vue3-admin-plus/e68d9108785ab118ef4fc0e6196a93778d2fff29/public/favicon.ico
--------------------------------------------------------------------------------
/src/App.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
40 |
46 |
--------------------------------------------------------------------------------
/src/api/dataAuth.ts:
--------------------------------------------------------------------------------
1 | // 新增和编辑接口
2 | import request from '@/utils/axios-req'
3 | //新增
4 | export const addDataAuth = (data) => {
5 | return request({
6 | url: `/system/role/dataScope`,
7 | data,
8 | reqLoading: false,
9 | method: 'post'
10 | })
11 | }
12 | //更新
13 | export const updateDataAuth = (data) => {
14 | return request({
15 | url: `/system/role/dataScope`,
16 | data,
17 | method: 'put'
18 | })
19 | }
20 | //详情
21 | export const getDataAuth = (id) => {
22 | return request({
23 | url: `/system/role/deptTree/${id}`,
24 | method: 'get'
25 | })
26 | }
27 |
28 | // 查询部门下拉树结构
29 | // 根据角色ID查询部门树结构
30 | export function deptTreeSelect(roleId) {
31 | return request({
32 | url: `/system/role/deptTree/${roleId}`,
33 | method: 'get'
34 | })
35 | }
36 |
--------------------------------------------------------------------------------
/src/api/dept.ts:
--------------------------------------------------------------------------------
1 | //查询列表页面接口
2 | import request from '@/utils/axios-req'
3 |
4 | export const listReq = (query) => {
5 | //查询列表
6 | return request({
7 | url: '/system/dept/list',
8 | method: 'post',
9 | reqLoading: false,
10 | data: query||{}
11 | })
12 | }
13 |
14 | //导出
15 | export const exportReq = (reqConfig) => {
16 | return request({
17 | url: `/system/dept/export`,
18 | responseType: 'blob',
19 | method: 'post',
20 | params: Object.assign(reqConfig, { responseType: 'blob' })
21 | })
22 | }
23 |
24 | //删除
25 | export const deleteReq = (id) => {
26 | return request({
27 | url: `/system/dept/${id}`,
28 | method: 'delete'
29 | })
30 | }
31 |
32 | /**
33 | * 新增编辑页面接口
34 | *Dept新增
35 | */
36 | export const addDept = (data) => {
37 | return request({
38 | url: `/system/dept`,
39 | data,
40 | method: 'post'
41 | })
42 | }
43 |
44 | /**
45 | *Dept更新
46 | @param {*} id 详情id
47 | */
48 | export const updateDept = (data) => {
49 | return request({
50 | url: `/system/dept`,
51 | method: 'put',
52 | data
53 | })
54 | }
55 |
56 | /**
57 | *Dept详情
58 | * @param {*} data json数据
59 | */
60 | export const getDept = (id) => {
61 | return request({
62 | url: `/system/dept/${id}`,
63 | method: 'get'
64 | })
65 | }
66 |
--------------------------------------------------------------------------------
/src/api/dictData.ts:
--------------------------------------------------------------------------------
1 | //查询列表页面接口
2 | import request from '@/utils/axios-req'
3 |
4 | export const listReq = (query) => {
5 | //查询列表
6 | return request({
7 | url: '/system/sysDictData/list',
8 | method: 'post',
9 | reqLoading: false,
10 | data: query
11 | })
12 | }
13 |
14 | //删除
15 | export const deleteReq = (id) => {
16 | return request({
17 | url: `/system/sysDictData/${id}`,
18 | method: 'delete'
19 | })
20 | }
21 |
22 | //批量删除
23 | export const multiDeleteReq = (id) => {
24 | return request({
25 | url: `/system/sysDictData/${id}`,
26 | method: 'delete'
27 | })
28 | }
29 |
30 | //导出
31 | export const exportReq = (reqConfig) => {
32 | return request({
33 | url: `/system/sysDictData/export`,
34 | responseType: 'blob',
35 | method: 'post',
36 | params: Object.assign(reqConfig, { responseType: 'blob' })
37 | })
38 | }
39 |
40 | /**
41 | * 新增编辑页面接口
42 | *Dict新增
43 | */
44 | export const addDict = (data) => {
45 | return request({
46 | url: `/system/sysDictData`,
47 | data,
48 | method: 'post'
49 | })
50 | }
51 |
52 | /**
53 | *Dict更新
54 | @param {*} id 详情id
55 | */
56 | export const updateDict = (data) => {
57 | return request({
58 | url: `/system/sysDictData`,
59 | method: 'put',
60 | data
61 | })
62 | }
63 |
64 | /**
65 | *Dict详情
66 | * @param {*} data json数据
67 | */
68 | export const getDict = (id) => {
69 | return request({
70 | url: `/system/sysDictData/${id}`,
71 | method: 'get'
72 | })
73 | }
74 |
--------------------------------------------------------------------------------
/src/api/loginInfo.ts:
--------------------------------------------------------------------------------
1 | //查询列表页面接口
2 | import request from '@/utils/axios-req'
3 |
4 | export const listReq = (query) => {
5 | //查询列表
6 | return request({
7 | url: '/monitor/loginInfo/list',
8 | method: 'post',
9 | reqLoading: false,
10 | data: query
11 | })
12 | }
13 |
14 | //删除
15 | export const deleteReq = (id) => {
16 | return request({
17 | url: `/monitor/loginInfo/${id}`,
18 | method: 'delete'
19 | })
20 | }
21 |
22 | //批量删除
23 | export const multiDeleteReq = (id) => {
24 | return request({
25 | url: `/monitor/loginInfo/${id}`,
26 | method: 'delete'
27 | })
28 | }
29 |
30 | //导出
31 | export const exportReq = (reqConfig) => {
32 | return request({
33 | url: `monitor/loginInfo/export`,
34 | responseType: 'blob',
35 | method: 'post',
36 | params: Object.assign(reqConfig, { responseType: 'blob' })
37 | })
38 | }
39 |
40 | // 解锁用户登录状态
41 | export function unlockLoginInfo(userName) {
42 | return request({
43 | url: `/monitor/loginInfo/unlock/${userName}`,
44 | method: 'get'
45 | })
46 | }
47 |
48 | // 清空登录日志
49 | export function cleanLoginInfo() {
50 | return request({
51 | url: '/monitor/loginInfo/clean',
52 | method: 'delete'
53 | })
54 | }
55 |
--------------------------------------------------------------------------------
/src/api/menu.ts:
--------------------------------------------------------------------------------
1 | //查询列表页面接口
2 | import request from '@/utils/axios-req'
3 |
4 | export const listMenuReq = (query) => {
5 | //查询列表
6 | return request({
7 | url: '/system/menu/list',
8 | method: 'post',
9 | reqLoading: false,
10 | data: query
11 | })
12 | }
13 |
14 | //删除
15 | export const deleteReq = (id) => {
16 | return request({
17 | url: `/system/menu/deleteById/${id}`,
18 | method: 'delete'
19 | })
20 | }
21 |
22 | //模板下载
23 | export const downloadTemplateReq = () => {
24 | return request({
25 | url: `system/role/importTemplate`,
26 | method: 'post'
27 | })
28 | }
29 |
30 | // 新增和编辑接口
31 |
32 | //新增
33 | export const addMenu = (data) => {
34 | return request({
35 | url: `/system/menu`,
36 | data,
37 | method: 'post'
38 | })
39 | }
40 | //更新
41 | export const updateMenu = (data) => {
42 | return request({
43 | url: `/system/menu`,
44 | data,
45 | method: 'put'
46 | })
47 | }
48 | //详情
49 | export const getMenu = (id) => {
50 | return request({
51 | url: `/system/menu/${id}`,
52 | method: 'get'
53 | })
54 | }
55 |
--------------------------------------------------------------------------------
/src/api/operatorLog.ts:
--------------------------------------------------------------------------------
1 | //查询列表页面接口
2 | import request from '@/utils/axios-req'
3 |
4 | export const listReq = (query) => {
5 | //查询列表
6 | return request({
7 | url: '/monitor/operatorLog/list',
8 | method: 'post',
9 | reqLoading: false,
10 | data: query
11 | })
12 | }
13 |
14 | //删除
15 | export const deleteReq = (id) => {
16 | return request({
17 | url: `/monitor/operatorLog/${id}`,
18 | method: 'delete'
19 | })
20 | }
21 |
22 | //批量删除
23 | export const multiDeleteReq = (id) => {
24 | return request({
25 | url: `/monitor/operatorLog/${id}`,
26 | method: 'delete'
27 | })
28 | }
29 |
30 | //导出
31 | export const exportReq = (reqConfig) => {
32 | return request({
33 | url: `monitor/operatorLog/export`,
34 | responseType: 'blob',
35 | method: 'post',
36 | params: Object.assign(reqConfig, { responseType: 'blob' })
37 | })
38 | }
39 |
--------------------------------------------------------------------------------
/src/api/oss.ts:
--------------------------------------------------------------------------------
1 | //查询列表页面接口
2 | import request from '@/utils/axios-req'
3 |
4 | export const listReq = (query) => {
5 | //查询列表
6 | return request({
7 | url: '/system/oss/listPage',
8 | method: 'get',
9 | reqLoading: false,
10 | params: query
11 | })
12 | }
13 |
14 | //删除
15 | export const deleteReq = (id) => {
16 | return request({
17 | url: `/system/oss/${id}`,
18 | method: 'delete'
19 | })
20 | }
21 |
22 | //批量删除
23 | export const multiDeleteReq = (id) => {
24 | return request({
25 | url: `/system/oss/mul/${id}`,
26 | method: 'delete'
27 | })
28 | }
29 |
30 | export const exportReq = () => {}
31 |
--------------------------------------------------------------------------------
/src/api/ossConfig.ts:
--------------------------------------------------------------------------------
1 | //查询列表页面接口
2 | import request from '@/utils/axios-req'
3 |
4 | export const listReq = (query) => {
5 | //查询列表
6 | return request({
7 | url: '/system/oss/config/list',
8 | method: 'get',
9 | reqLoading: false,
10 | params: query
11 | })
12 | }
13 |
14 | //删除
15 | export const deleteReq = (id) => {
16 | return request({
17 | url: `/system/oss/config/${id}`,
18 | method: 'delete'
19 | })
20 | }
21 |
22 | //批量删除
23 | export const multiDeleteReq = (id) => {
24 | return request({
25 | url: `/system/oss/config/${id}`,
26 | method: 'delete'
27 | })
28 | }
29 |
30 | /**
31 | * 新增编辑页面接口
32 | *OssConfig新增
33 | */
34 | export const addOssConfig = (data) => {
35 | return request({
36 | url: `/system/oss/config`,
37 | data,
38 | method: 'post'
39 | })
40 | }
41 |
42 | // 对象存储状态修改
43 | export const changeOssConfigStatus = (ossConfigId, status, configKey) => {
44 | const data = {
45 | ossConfigId,
46 | status,
47 | configKey
48 | }
49 | return request({
50 | url: '/system/oss/config/changeStatus',
51 | method: 'put',
52 | data
53 | })
54 | }
55 |
56 | /**
57 | *OssConfig更新
58 | @param {*} id 详情id
59 | */
60 | export const updateOssConfig = (data) => {
61 | return request({
62 | url: `/system/oss/config`,
63 | method: 'put',
64 | data
65 | })
66 | }
67 |
68 | /**
69 | *OssConfig详情
70 | * @param {*} data json数据
71 | */
72 | export const getOssConfig = (id) => {
73 | return request({
74 | url: `/system/oss/config/${id}`,
75 | method: 'get'
76 | })
77 | }
78 |
--------------------------------------------------------------------------------
/src/api/post.ts:
--------------------------------------------------------------------------------
1 | //查询列表页面接口
2 | import request from '@/utils/axios-req'
3 |
4 | export const listReq = (query) => {
5 | //查询列表
6 | return request({
7 | url: '/system/post/list',
8 | method: 'post',
9 | reqLoading: false,
10 | data: query||{}
11 | })
12 | }
13 |
14 | //删除
15 | export const deleteReq = (id) => {
16 | return request({
17 | url: `/system/post/${id}`,
18 | method: 'delete'
19 | })
20 | }
21 |
22 | //批量删除
23 | export const multiDeleteReq = (id) => {
24 | return request({
25 | url: `/system/post/${id}`,
26 | method: 'delete'
27 | })
28 | }
29 |
30 | //导出
31 | export const exportReq = (reqConfig) => {
32 | return request({
33 | url: `/system/post/export`,
34 | responseType: 'blob',
35 | method: 'post',
36 | params: Object.assign(reqConfig, { responseType: 'blob' })
37 | })
38 | }
39 |
40 | /**
41 | * 新增编辑页面接口
42 | *Post新增
43 | */
44 | export const addPost = (data) => {
45 | return request({
46 | url: `/system/post`,
47 | data,
48 | method: 'post'
49 | })
50 | }
51 |
52 | /**
53 | *Post更新
54 | @param {*} id 详情id
55 | */
56 | export const updatePost = (data) => {
57 | return request({
58 | url: `/system/post`,
59 | method: 'put',
60 | data
61 | })
62 | }
63 |
64 | /**
65 | *Post详情
66 | * @param {*} data json数据
67 | */
68 | export const getPost = (id) => {
69 | return request({
70 | url: `/system/post/${id}`,
71 | method: 'get'
72 | })
73 | }
74 |
--------------------------------------------------------------------------------
/src/api/rbac.ts:
--------------------------------------------------------------------------------
1 | import request from '@/utils/axios-req'
2 | import settings from '@/settings'
3 |
4 | export const userInfoReq = () => {
5 | return new Promise((resolve) => {
6 | const reqConfig = {
7 | url: 'rbac/getInfo',
8 | data:{platformId: settings.platformId},
9 | method: 'get'
10 | }
11 | request(reqConfig).then(({ data }) => {
12 | resolve(data)
13 | })
14 | })
15 | }
16 |
17 | //登录
18 | export const loginReq = (subForm) => {
19 | return request({
20 | url: 'rbac/login',
21 | data: subForm,
22 | method: 'post',
23 | isNotTipErrorMsg: true
24 | })
25 | }
26 | // 注册方法
27 | export const register = (data) => {
28 | return request({
29 | url: 'rbac/register',
30 | method: 'post',
31 | data
32 | })
33 | }
34 | //获取验证码
35 | export const getCodeImg = () => {
36 | return request({
37 | url: 'rbac/getCode',
38 | params:{width:85,height:50},
39 | method: 'get'
40 | })
41 | }
42 |
--------------------------------------------------------------------------------
/src/api/remote-search.ts:
--------------------------------------------------------------------------------
1 | import request from 'axios'
2 |
3 | export function searchUser(name) {
4 | return request({
5 | url: '/vue3-admin-plus/search/user',
6 | method: 'get',
7 | params: { name }
8 | })
9 | }
10 |
11 | export function transactionList(query) {
12 | return request({
13 | url: '/vue3-admin-plus/transaction/list',
14 | method: 'get',
15 | params: query
16 | })
17 | }
18 |
--------------------------------------------------------------------------------
/src/api/system/dict/data.js:
--------------------------------------------------------------------------------
1 | import request from '@/utils/axios-req'
2 |
3 | // 查询字典数据列表
4 | export function listData(query) {
5 | return request({
6 | url: '/system/dict/data/list',
7 | method: 'get',
8 | params: query
9 | })
10 | }
11 |
12 | // 查询字典数据详细
13 | export function getData(dictCode) {
14 | return request({
15 | url: `/system/dict/data/${dictCode}`,
16 | method: 'get'
17 | })
18 | }
19 |
20 | // 根据字典类型查询字典数据信息
21 | export function getDicts(dictType) {
22 | return request({
23 | url: `/system/dict/data/type/${dictType}`,
24 | method: 'get'
25 | })
26 | }
27 |
28 | // 新增字典数据
29 | export function addData(data) {
30 | return request({
31 | url: '/system/dict/data',
32 | method: 'post',
33 | data
34 | })
35 | }
36 |
37 | // 修改字典数据
38 | export function updateData(data) {
39 | return request({
40 | url: '/system/dict/data',
41 | method: 'put',
42 | data
43 | })
44 | }
45 |
46 | // 删除字典数据
47 | export function delData(dictCode) {
48 | return request({
49 | url: `/system/dict/data/${dictCode}`,
50 | method: 'delete'
51 | })
52 | }
53 |
--------------------------------------------------------------------------------
/src/api/system/dict/type.js:
--------------------------------------------------------------------------------
1 | import request from '@/utils/request'
2 |
3 | // 查询字典类型列表
4 | export function listType(query) {
5 | return request({
6 | url: 'system/sysDictype/list',
7 | method: 'get',
8 | params: query
9 | })
10 | }
11 |
12 | // 查询字典类型详细
13 | export function getType(dictId) {
14 | return request({
15 | url: `system/sysDictype/${ dictId}`,
16 | method: 'get'
17 | })
18 | }
19 |
20 | // 新增字典类型
21 | export function addType(data) {
22 | return request({
23 | url: '/system/dict/type',
24 | method: 'post',
25 | data
26 | })
27 | }
28 |
29 | // 修改字典类型
30 | export function updateType(data) {
31 | return request({
32 | url: '/system/dict/type',
33 | method: 'put',
34 | data
35 | })
36 | }
37 |
38 | // 删除字典类型
39 | export function delType(dictId) {
40 | return request({
41 | url: `system/sysDictype/${ dictId}`,
42 | method: 'delete'
43 | })
44 | }
45 |
46 | // 刷新字典缓存
47 | export function refreshCache() {
48 | return request({
49 | url: 'system/sysDictype/refreshCache',
50 | method: 'delete'
51 | })
52 | }
53 |
54 | // 获取字典选择框列表
55 | export function optionselect() {
56 | return request({
57 | url: 'system/sysDictype/optionselect',
58 | method: 'get'
59 | })
60 | }
61 |
--------------------------------------------------------------------------------
/src/api/table.ts:
--------------------------------------------------------------------------------
1 | import request from 'axios'
2 |
3 | export function getList(params) {
4 | return request({
5 | url: '/vue3-admin-plus/table/list',
6 | method: 'get',
7 | params
8 | })
9 | }
10 |
--------------------------------------------------------------------------------
/src/assets/401_images/401.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jzfai/vue3-admin-plus/e68d9108785ab118ef4fc0e6196a93778d2fff29/src/assets/401_images/401.gif
--------------------------------------------------------------------------------
/src/assets/404_images/404.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jzfai/vue3-admin-plus/e68d9108785ab118ef4fc0e6196a93778d2fff29/src/assets/404_images/404.png
--------------------------------------------------------------------------------
/src/assets/404_images/404_cloud.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jzfai/vue3-admin-plus/e68d9108785ab118ef4fc0e6196a93778d2fff29/src/assets/404_images/404_cloud.png
--------------------------------------------------------------------------------
/src/assets/gif/dianchi.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jzfai/vue3-admin-plus/e68d9108785ab118ef4fc0e6196a93778d2fff29/src/assets/gif/dianchi.gif
--------------------------------------------------------------------------------
/src/assets/layout/animation-image.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jzfai/vue3-admin-plus/e68d9108785ab118ef4fc0e6196a93778d2fff29/src/assets/layout/animation-image.gif
--------------------------------------------------------------------------------
/src/assets/layout/login-bg.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/assets/layout/login-front.svg:
--------------------------------------------------------------------------------
1 |
7 |
--------------------------------------------------------------------------------
/src/assets/layout/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jzfai/vue3-admin-plus/e68d9108785ab118ef4fc0e6196a93778d2fff29/src/assets/layout/logo.png
--------------------------------------------------------------------------------
/src/components/DictTag.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 | {{ label }}
4 |
5 |
6 |
7 |
26 |
27 |
32 |
--------------------------------------------------------------------------------
/src/components/ElSvgIcon.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
27 |
28 |
37 |
--------------------------------------------------------------------------------
/src/components/InnerLink/index.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
20 |
--------------------------------------------------------------------------------
/src/components/JsonInput.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
32 |
33 |
43 |
--------------------------------------------------------------------------------
/src/components/ParentView/index.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/src/components/TestUnit.vue:
--------------------------------------------------------------------------------
1 |
2 | TestUnit.vue
3 |
4 |
5 |
14 |
15 |
16 |
--------------------------------------------------------------------------------
/src/directives/example/clickoutside.js:
--------------------------------------------------------------------------------
1 |
2 | export default {
3 | mounted(el, binding) {
4 | if (typeof binding.value !== 'function') {
5 | throw 'callback must be a function';
6 | }
7 | el.__handleClick__ = function (e) {
8 | if (el.contains(e.target)) {
9 | binding.value(false);
10 | }
11 | else {
12 | binding.value(true);
13 | }
14 | };
15 | document.addEventListener('click', el.__handleClick__);
16 | },
17 | beforeUnmount(el) {
18 | document.removeEventListener('click', el.__handleClick__);
19 | }
20 |
21 | }
22 |
--------------------------------------------------------------------------------
/src/directives/example/copy.js:
--------------------------------------------------------------------------------
1 | /**
2 | * v-copy
3 | * 复制某个值至剪贴板
4 | * 接收参数:string类型/Ref类型/Reactive类型
5 | */
6 | import { ElMessage } from 'element-plus';
7 | function handleClick(ev) {
8 | const input = document.createElement('input');
9 | input.value = this.copyData.toLocaleString();
10 | document.body.appendChild(input);
11 | input.select();
12 | document.execCommand('Copy');
13 | document.body.removeChild(input);
14 | ElMessage({
15 | type: 'success',
16 | message: '复制成功'
17 | });
18 | }
19 | export default {
20 | mounted(el, binding) {
21 | el.copyData = binding.value;
22 | el.addEventListener('click', handleClick);
23 | },
24 | updated(el, binding) {
25 | el.copyData = binding.value;
26 | },
27 | beforeUnmount(el) {
28 | el.removeEventListener('click', el.__handleClick__);
29 | }
30 | };
31 |
32 |
--------------------------------------------------------------------------------
/src/directives/example/debounce.js:
--------------------------------------------------------------------------------
1 | /**
2 | * v-debounce
3 | * 按钮防抖指令,可自行扩展至input
4 | * 接收参数:function类型
5 | */
6 | export default {
7 | mounted(el, binding) {
8 | if (typeof binding.value !== 'function') {
9 | console.error('callback must be a function');
10 | return;
11 | }
12 | let timer = null;
13 | el.__handleClick__ = function (e) {
14 | if (timer) {
15 | clearInterval(timer);
16 | }
17 | timer = setTimeout(() => {
18 | binding.value();
19 | }, 200);
20 | };
21 | el.addEventListener('click', el.__handleClick__);
22 | },
23 | beforeUnmount(el) {
24 | el.removeEventListener('click', el.__handleClick__);
25 | }
26 | };
27 |
--------------------------------------------------------------------------------
/src/directives/example/longpress.js:
--------------------------------------------------------------------------------
1 | /**
2 | * v-longpress
3 | * 长按指令,长按时触发事件
4 | */
5 | export default {
6 | mounted(el, binding) {
7 | if (typeof binding.value !== 'function') {
8 | throw 'callback must be a function';
9 | }
10 | // 定义变量
11 | let pressTimer = null;
12 | // 创建计时器( 2秒后执行函数 )
13 | const start = (e) => {
14 | if (e.button) {
15 | if (e.type === 'click' && e.button !== 0) {
16 | return;
17 | }
18 | }
19 | if (pressTimer === null) {
20 | pressTimer = setTimeout(() => {
21 | handler(e);
22 | }, 1000);
23 | }
24 | };
25 | // 取消计时器
26 | const cancel = (e) => {
27 | if (pressTimer !== null) {
28 | clearTimeout(pressTimer);
29 | pressTimer = null;
30 | }
31 | };
32 | // 运行函数
33 | const handler = (e) => {
34 | binding.value(e);
35 | };
36 | // 添加事件监听器
37 | el.addEventListener('mousedown', start);
38 | el.addEventListener('touchstart', start);
39 | // 取消计时器
40 | el.addEventListener('click', cancel);
41 | el.addEventListener('mouseout', cancel);
42 | el.addEventListener('touchend', cancel);
43 | el.addEventListener('touchcancel', cancel);
44 | },
45 | };
46 |
--------------------------------------------------------------------------------
/src/directives/example/watermark.js:
--------------------------------------------------------------------------------
1 | /**
2 | * v-watermark可接收参数,均为非必填
3 | * { text: 'vue-admin-box', font: '16px Microsoft JhengHei', textColor: '#000' }
4 | */
5 | function addWaterMark(str, parentNode, font, textColor) {
6 | // 水印文字,父元素,字体,文字颜色
7 | const can = document.createElement('canvas');
8 | parentNode.appendChild(can);
9 | can.width = 200;
10 | can.height = 150;
11 | can.style.display = 'none';
12 | const cans = can.getContext('2d');
13 | cans.rotate((-20 * Math.PI) / 180);
14 | cans.font = font || '16px Microsoft JhengHei';
15 | cans.fillStyle = textColor || 'rgba(180, 180, 180, 0.3)';
16 | cans.textAlign = 'left';
17 | cans.textBaseline = 'middle';
18 | cans.fillText(str || 'vue3-admin-plus', can.width / 10, can.height / 2);
19 | parentNode.style.backgroundImage = `url(${ can.toDataURL('image/png') })`;
20 | }
21 | export default {
22 | mounted(el, binding) {
23 | binding.value ? binding.value : binding.value = {};
24 | addWaterMark(binding.value.text, el, binding.value.font, binding.value.textColor);
25 | }
26 | }
27 |
28 |
29 |
--------------------------------------------------------------------------------
/src/directives/example/waves.css:
--------------------------------------------------------------------------------
1 | .waves-ripple {
2 | position: absolute;
3 | border-radius: 100%;
4 | background-color: rgba(0, 0, 0, 0.15);
5 | background-clip: padding-box;
6 | pointer-events: none;
7 | -webkit-user-select: none;
8 | -moz-user-select: none;
9 | -ms-user-select: none;
10 | user-select: none;
11 | -webkit-transform: scale(0);
12 | -ms-transform: scale(0);
13 | transform: scale(0);
14 | opacity: 1;
15 | }
16 |
17 | .waves-ripple.z-active {
18 | opacity: 0;
19 | -webkit-transform: scale(2);
20 | -ms-transform: scale(2);
21 | transform: scale(2);
22 | -webkit-transition: opacity 1.2s ease-out, -webkit-transform 0.6s ease-out;
23 | transition: opacity 1.2s ease-out, -webkit-transform 0.6s ease-out;
24 | transition: opacity 1.2s ease-out, transform 0.6s ease-out;
25 | transition: opacity 1.2s ease-out, transform 0.6s ease-out, -webkit-transform 0.6s ease-out;
26 | }
--------------------------------------------------------------------------------
/src/directives/has-perm.ts:
--------------------------------------------------------------------------------
1 | import { useBasicStore } from '@/store/basic'
2 | function checkPermission(el, { value }) {
3 | const { permission } = useBasicStore()
4 | const allPermission = '*:*:*'
5 | if (value && Array.isArray(value) && value.length > 0) {
6 | const permissionFlag = value
7 | const hasPermissions = permission.some((permission) => {
8 | return allPermission === permission || permissionFlag.includes(permission)
9 | })
10 | if (!hasPermissions) {
11 | el.parentNode && el.parentNode.removeChild(el)
12 | }
13 | } else {
14 | throw new Error(`请设置操作权限标签值`)
15 | }
16 | }
17 | export default {
18 | mounted(el, binding) {
19 | checkPermission(el, binding)
20 | },
21 | componentUpdated(el, binding) {
22 | checkPermission(el, binding)
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/src/directives/has-role.ts:
--------------------------------------------------------------------------------
1 | import { useBasicStore } from '@/store/basic'
2 | function checkPermission(el, { value }) {
3 | const superAdmin = 'admin'
4 | const { roles } = useBasicStore()
5 | if (value && Array.isArray(value) && value.length > 0) {
6 | const roleFlag = value
7 |
8 | const hasRole = roles.some((role) => {
9 | return superAdmin === role || roleFlag.includes(role)
10 | })
11 |
12 | if (!hasRole) {
13 | el.parentNode && el.parentNode.removeChild(el)
14 | }
15 | } else {
16 | throw new Error(`请设置角色权限标签值`)
17 | }
18 | }
19 | export default {
20 | mounted(el, binding) {
21 | checkPermission(el, binding)
22 | },
23 | componentUpdated(el, binding) {
24 | checkPermission(el, binding)
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/src/directives/index.ts:
--------------------------------------------------------------------------------
1 | import hasPerm from './has-perm'
2 | import hasRole from './has-role'
3 | import lang from './lang'
4 |
5 | import copy from './example/copy'
6 | import longpress from './example/longpress'
7 | import debounce from './example/debounce'
8 | import watermark from './example/watermark'
9 | import waves from './example/waves.js'
10 | import clickoutside from './example/clickoutside'
11 |
12 | export default function (app) {
13 | app.directive('hasPerm', hasPerm)
14 | app.directive('hasRole', hasRole)
15 | app.directive('lang', lang)
16 |
17 | //example
18 | app.directive('copy', copy)
19 | app.directive('longpress', longpress)
20 | app.directive('debounce', debounce)
21 | app.directive('watermark', watermark)
22 | app.directive('waves', waves)
23 | app.directive('clickoutside', clickoutside)
24 | }
25 |
--------------------------------------------------------------------------------
/src/directives/lang.ts:
--------------------------------------------------------------------------------
1 | import { watch } from 'vue'
2 | import { storeToRefs } from 'pinia/dist/pinia'
3 | import { langTitle } from '@/hooks/use-common'
4 | import { useConfigStore } from '@/store/config'
5 | //element-plus
6 | const componentToProps = {
7 | ElInput: 'placeholder',
8 | ElTableColumn: 'label'
9 | }
10 |
11 | function checkPermission(el, { value }) {
12 | let saveOriginTitle = ''
13 | const { language } = storeToRefs(useConfigStore())
14 | //save the original title
15 | const name = el.__vueParentComponent?.type?.name
16 | const nameTitle = el.__vueParentComponent?.props[componentToProps[name]]
17 | saveOriginTitle = nameTitle || el.innerText
18 | watch(
19 | () => language.value,
20 | () => {
21 | //element tag or component
22 | if (name?.startsWith('EL')) {
23 | //self cunstrom
24 | if (Object.keys(componentToProps).includes(name)) {
25 | const props = el.__vueParentComponent.props
26 | props[componentToProps[name]] = langTitle(saveOriginTitle)
27 | } else {
28 | el.innerText = langTitle(saveOriginTitle)
29 | }
30 | } else {
31 | //common tag such as div span output so on;
32 | if (el.__vnode?.type) {
33 | el.innerText = langTitle(saveOriginTitle)
34 | }
35 | }
36 | },
37 | { immediate: true }
38 | )
39 | }
40 | export default {
41 | mounted(el, binding) {
42 | checkPermission(el, binding)
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/src/hooks/use-error-log.ts:
--------------------------------------------------------------------------------
1 | /*js 错误日志收集*/
2 | import { jsErrorCollection } from 'js-error-collection'
3 | import axiosReq from 'axios'
4 | import pack from '../../package.json'
5 | import settings from '@/settings'
6 | import bus from '@/utils/bus'
7 | //此处不要使用utils下的axios
8 | const reqUrl = '/integration-front/errorCollection/insert'
9 | let repeatErrorLogJudge = ''
10 | const errorLogReq = (errLog: string) => {
11 | axiosReq({
12 | url: import.meta.env.VITE_APP_BASE_URL+reqUrl,
13 | data: {
14 | pageUrl: window.location.href,
15 | errorLog: errLog,
16 | browserType: navigator.userAgent,
17 | version: pack.version
18 | },
19 | method: 'post'
20 | }).then(() => {
21 | //通知错误列表页面更新数据
22 | bus.emit('reloadErrorPage', {})
23 | })
24 | }
25 |
26 | export const useErrorLog = () => {
27 | //判断该环境是否需要收集错误日志,由settings配置决定
28 | if (settings.errorLog?.includes(import.meta.env.VITE_APP_ENV)) {
29 | jsErrorCollection({ runtimeError: true, rejectError: true, consoleError: true }, (errLog) => {
30 | if (!repeatErrorLogJudge || !errLog.includes(repeatErrorLogJudge)) {
31 | errorLogReq(errLog)
32 | //移除重复日志,fix重复提交错误日志,避免造成死循环
33 | repeatErrorLogJudge = errLog.slice(0, 20)
34 | }
35 | })
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/src/hooks/use-layout.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * 判断是否是外链
3 | * @param {string} path
4 | * @returns {Boolean}
5 | */
6 | import { onBeforeMount, onBeforeUnmount, onMounted } from 'vue'
7 | import { useBasicStore } from '@/store/basic'
8 | export function isExternal(path) {
9 | return /^(https?:|mailto:|tel:)/.test(path)
10 | }
11 |
12 | /*判断窗口变化控制侧边栏收起或展开*/
13 | export function resizeHandler() {
14 | const { body } = document
15 | const WIDTH = 992
16 | const basicStore = useBasicStore()
17 | const isMobile = () => {
18 | const rect = body.getBoundingClientRect()
19 | return rect.width - 1 < WIDTH
20 | }
21 | const resizeHandler = () => {
22 | if (!document.hidden) {
23 | if (isMobile()) {
24 | /*此处只做根据window尺寸关闭sideBar功能*/
25 | basicStore.setSidebarOpen(false)
26 | } else {
27 | basicStore.setSidebarOpen(true)
28 | }
29 | }
30 | }
31 | onBeforeMount(() => {
32 | window.addEventListener('resize', resizeHandler)
33 | })
34 | onMounted(() => {
35 | if (isMobile()) {
36 | basicStore.setSidebarOpen(false)
37 | } else {
38 | basicStore.setSidebarOpen(true)
39 | }
40 | })
41 | onBeforeUnmount(() => {
42 | window.removeEventListener('resize', resizeHandler)
43 | })
44 | }
45 |
--------------------------------------------------------------------------------
/src/hooks/use-self-router.ts:
--------------------------------------------------------------------------------
1 | import router from '@/router'
2 | export const getQueryParam = () => {
3 | const route: any = router.currentRoute
4 | if (route.value?.query) {
5 | return route.value.query
6 | } else {
7 | return {}
8 | }
9 | }
10 | // vue router
11 | export const routerPush = (name, params) => {
12 | let data = {}
13 | if (params) {
14 | data = params
15 | } else {
16 | data = {}
17 | }
18 | router.push({
19 | name,
20 | query: data
21 | })
22 | }
23 | export const routerReplace = (name, params) => {
24 | let data = {}
25 | if (params) {
26 | data = JSON.stringify(params)
27 | } else {
28 | data = {}
29 | }
30 | router.replace({
31 | name,
32 | query: data
33 | })
34 | }
35 |
36 | export const routeInfo = () => {
37 | return router.currentRoute
38 | }
39 | export const routerBack = () => {
40 | router.go(-1)
41 | }
42 |
--------------------------------------------------------------------------------
/src/icons/SvgIcon.vue:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
7 |
28 |
29 |
46 |
--------------------------------------------------------------------------------
/src/icons/common/404.svg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jzfai/vue3-admin-plus/e68d9108785ab118ef4fc0e6196a93778d2fff29/src/icons/common/404.svg
--------------------------------------------------------------------------------
/src/icons/common/bug.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/icons/common/build.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/icons/common/chart.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/icons/common/checkbox.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/icons/common/clipboard.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/icons/common/code.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/icons/common/component.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/icons/common/demo.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/icons/common/documentation.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/icons/common/download.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/icons/common/drag.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/icons/common/druid.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/icons/common/edit.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/icons/common/education.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/icons/common/email.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/icons/common/example.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/icons/common/excel.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/icons/common/eye-open.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/icons/common/eye.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/icons/common/fullscreen.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/icons/common/github.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/icons/common/guide.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/icons/common/hamburger.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/icons/common/icon.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/icons/common/input.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/icons/common/international.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/icons/common/language.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/icons/common/link.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/icons/common/list.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/icons/common/lock.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/icons/common/log.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/icons/common/message.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/icons/common/money.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/icons/common/monitor.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/icons/common/nested.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/icons/common/password.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/icons/common/people.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/icons/common/peoples.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/icons/common/phone.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/icons/common/post.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/icons/common/question.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/icons/common/radio.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/icons/common/row.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/icons/common/search.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/icons/common/select.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/icons/common/server.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/icons/common/sidebar-logo.svg:
--------------------------------------------------------------------------------
1 |
3 |
--------------------------------------------------------------------------------
/src/icons/common/size.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/icons/common/skill.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/icons/common/slider.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/icons/common/star.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/icons/common/switch.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/icons/common/tab.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/icons/common/table.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/icons/common/textarea.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/icons/common/theme.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/icons/common/time.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/icons/common/tree-table.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/icons/common/upload.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/icons/common/user.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/icons/common/validCode.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/icons/common/wechat.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/icons/common/zip.svg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jzfai/vue3-admin-plus/e68d9108785ab118ef4fc0e6196a93778d2fff29/src/icons/common/zip.svg
--------------------------------------------------------------------------------
/src/icons/nav-bar/example.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/icons/nav-bar/eye-open.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/icons/nav-bar/eye.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/icons/nav-bar/link.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/icons/nav-bar/nested.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/icons/nav-bar/password.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/icons/nav-bar/table.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/icons/nav-bar/user.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/icons/nav-bar/validCode.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/lang/index.ts:
--------------------------------------------------------------------------------
1 | import { createI18n } from 'vue-i18n'
2 | import en from './en'
3 | import zh from './zh'
4 | import settings from '@/settings'
5 | const messages = { en, zh }
6 |
7 | const localeData = {
8 | globalInjection: true, //如果设置true, $t() 函数将注册到全局
9 | legacy: false, //如果想在composition api中使用需要设置为false
10 | locale: settings.defaultLanguage,
11 | messages // set locale messages
12 | }
13 |
14 | export const i18n = createI18n(localeData)
15 | export const setupI18n = {
16 | install(app) {
17 | app.use(i18n)
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/src/layout/app-main/Hamburger.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
21 |
22 |
34 |
--------------------------------------------------------------------------------
/src/layout/app-main/component/LangSelect.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
12 | {{ item.label }}
13 |
14 |
15 |
16 |
17 |
18 |
19 |
40 |
41 |
42 |
--------------------------------------------------------------------------------
/src/layout/app-main/component/ScreenFull.vue:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
10 |
50 |
51 |
58 |
--------------------------------------------------------------------------------
/src/layout/app-main/component/SizeSelect.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
12 | {{ item.label }}
13 |
14 |
15 |
16 |
17 |
18 |
19 |
38 |
39 |
40 |
--------------------------------------------------------------------------------
/src/layout/app-main/component/ThemeSelect.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
12 | {{ item.label }}
13 |
14 |
15 |
16 |
17 |
18 |
19 |
40 |
41 |
53 |
--------------------------------------------------------------------------------
/src/layout/sidebar/Link.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
32 |
--------------------------------------------------------------------------------
/src/layout/sidebar/MenuIcon.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
15 |
16 |
25 |
--------------------------------------------------------------------------------
/src/layout/sidebar/index.vue:
--------------------------------------------------------------------------------
1 |
2 |
18 |
19 |
20 |
38 |
47 |
--------------------------------------------------------------------------------
/src/lib/el-svg-icon.ts:
--------------------------------------------------------------------------------
1 | import * as components from '@element-plus/icons-vue'
2 |
3 | export default {
4 | install: (app) => {
5 | for (const key in components) {
6 | const componentConfig = components[key];
7 | app.component(componentConfig.name, componentConfig);
8 | }
9 | },
10 | };
11 |
--------------------------------------------------------------------------------
/src/lib/element-plus.ts:
--------------------------------------------------------------------------------
1 | import * as AllComponent from 'element-plus'
2 | //element-plus中按需引入会引起首次加载过慢
3 | const elementPlusComponentNameArr = ['ElButton']
4 | export default function (app) {
5 | elementPlusComponentNameArr.forEach((component) => {
6 | app.component(component, AllComponent[component])
7 | })
8 | }
9 |
--------------------------------------------------------------------------------
/src/main.ts:
--------------------------------------------------------------------------------
1 | import { createApp } from 'vue'
2 | import { createPinia } from 'pinia'
3 | import piniaPluginPersistedstate from 'pinia-plugin-persistedstate'
4 | import ElementPlus from 'element-plus'
5 | import JsonEditorVue from 'json-editor-vue3'
6 | import VXETable from 'vxe-table'
7 | import App from './App.vue'
8 | import router from './router'
9 |
10 | //import theme
11 | import './theme/index.scss'
12 |
13 | //import unocss
14 | import 'uno.css'
15 |
16 | //i18n
17 | import { setupI18n } from '@/lang'
18 |
19 | import '@/styles/index.scss' // global css
20 |
21 | //svg-icon
22 | import 'virtual:svg-icons-register'
23 | import svgIcon from '@/icons/SvgIcon.vue'
24 | import directive from '@/directives'
25 |
26 | //import router intercept
27 | import './permission'
28 |
29 | //import element-plus
30 | import 'element-plus/dist/index.css'
31 | //import element-plus svg icon
32 | import ElSvgIcon from '@/lib/el-svg-icon'
33 |
34 |
35 | //jsonEidt
36 | import 'jsoneditor'
37 |
38 | //import vxe-table
39 | import 'vxe-table/lib/style.css'
40 | const app = createApp(App)
41 | app.use(ElSvgIcon)
42 | app.use(JsonEditorVue)
43 | //router
44 | app.use(router)
45 |
46 | //pinia
47 | const pinia = createPinia()
48 | pinia.use(piniaPluginPersistedstate)
49 | app.use(pinia)
50 |
51 | //i18n
52 | app.use(setupI18n)
53 | app.component('SvgIcon', svgIcon)
54 | directive(app)
55 |
56 | //element-plus
57 | app.use(ElementPlus)
58 | app.use(VXETable)
59 |
60 | app.mount('#app')
61 |
--------------------------------------------------------------------------------
/src/plugins/vite-plugin-setup-extend/index.ts:
--------------------------------------------------------------------------------
1 | import { parse } from '@vue/compiler-sfc'
2 | import { render } from 'ejs'
3 | import type { Plugin } from 'vite'
4 | export default ({ inject }): Plugin => {
5 | // let viteConfig
6 | return {
7 | name: 'vite-plugin-setup-extend',
8 | enforce: 'pre',
9 | // configResolved(resolvedConfig) {
10 | // viteConfig = resolvedConfig
11 | // },
12 | async transformIndexHtml(html) {
13 | const result = await render(html, { ...inject })
14 | return result
15 | },
16 | transform(code, id) {
17 | if (/\.vue$/.test(id)) {
18 | const { descriptor } = parse(code)
19 | if (!descriptor?.scriptSetup?.setup) {
20 | return null
21 | }
22 | const { lang, name } = descriptor.scriptSetup?.attrs || {}
23 | const dillStr = headString(lang, name)
24 | code += dillStr
25 | return code
26 | }
27 | }
28 | }
29 | }
30 |
31 | const headString = (lang, name) => {
32 | return `\n`
38 | }
39 |
--------------------------------------------------------------------------------
/src/router/modules/charts.ts:
--------------------------------------------------------------------------------
1 | /** When your routing table is too long, you can split it into small modules**/
2 |
3 | import Layout from '@/layout/index.vue'
4 |
5 | const chartsRouter = {
6 | path: '/charts',
7 | component: Layout,
8 | redirect: 'noRedirect',
9 | name: 'Charts',
10 | meta: {
11 | title: 'Charts',
12 | icon: 'chart'
13 | },
14 | children: [
15 | {
16 | path: 'keyboard',
17 | component: () => import('@/views/charts/keyboard.vue'),
18 | name: 'KeyboardChart',
19 | meta: { title: 'Keyboard Chart', noCache: true }
20 | },
21 | {
22 | path: 'line',
23 | component: () => import('@/views/charts/line.vue'),
24 | name: 'LineChart',
25 | meta: { title: 'Line Chart', noCache: true }
26 | },
27 | {
28 | path: 'mix-chart',
29 | component: () => import('@/views/charts/mix-chart.vue'),
30 | name: 'MixChart',
31 | meta: { title: 'Mix Chart', noCache: true }
32 | },
33 | {
34 | path: 'echarts-demo',
35 | component: () => import('@/views/charts/echarts-demo.vue'),
36 | name: 'EchartsDemo',
37 | meta: { title: 'Echarts Demo', noCache: true }
38 | }
39 | ]
40 | }
41 |
42 | export default chartsRouter
43 |
--------------------------------------------------------------------------------
/src/router/modules/directive.ts:
--------------------------------------------------------------------------------
1 | import Layout from '@/layout/index.vue'
2 |
3 | const directive = {
4 | path: '/directive',
5 | component: Layout,
6 | meta: { title: 'Directive', icon: 'education' },
7 | alwaysShow: true,
8 | children: [
9 | {
10 | path: 'copy',
11 | component: () => import('@/views/directive/copy.vue'),
12 | name: 'copy',
13 | meta: { title: 'v-copy' }
14 | },
15 | {
16 | path: 'debounce',
17 | component: () => import('@/views/directive/debounce.vue'),
18 | name: 'debounce',
19 | meta: { title: 'v-debounce' }
20 | },
21 | {
22 | path: 'longpress',
23 | component: () => import('@/views/directive/longpress.vue'),
24 | name: 'longpress',
25 | meta: { title: 'v-longpress' }
26 | },
27 | {
28 | path: 'watermark',
29 | component: () => import('@/views/directive/watermark.vue'),
30 | name: 'watermark',
31 | meta: { title: 'v-watermark' }
32 | },
33 | {
34 | path: 'waves',
35 | component: () => import('@/views/directive/waves.vue'),
36 | name: 'waves',
37 | meta: { title: 'v-waves' }
38 | },
39 | {
40 | path: 'clickoutside',
41 | component: () => import('@/views/directive/clickoutside.vue'),
42 | name: 'clickoutside',
43 | meta: { title: 'v-clickoutside' }
44 | }
45 | ]
46 | }
47 |
48 | export default directive
49 |
--------------------------------------------------------------------------------
/src/router/modules/excel.ts:
--------------------------------------------------------------------------------
1 | import Layout from '@/layout/index.vue'
2 | const excel = {
3 | path: '/excel',
4 | component: Layout,
5 | meta: { title: 'EXCEL', icon: 'excel' },
6 | alwaysShow: true,
7 | children: [
8 | {
9 | path: 'exportExcel',
10 | component: () => import('@/views/excel/exportExcel.vue'),
11 | name: 'exportExcel',
12 | meta: { title: 'exportExcel' }
13 | },
14 | {
15 | path: 'importExcel',
16 | component: () => import('@/views/excel/importExcel.vue'),
17 | name: 'importExcel',
18 | meta: { title: 'importExcel' }
19 | }
20 | ]
21 | }
22 |
23 | export default excel
24 |
--------------------------------------------------------------------------------
/src/router/modules/guid.ts:
--------------------------------------------------------------------------------
1 | import Layout from '@/layout/index.vue'
2 | const guid = {
3 | path: '/guide',
4 | component: Layout,
5 | children: [
6 | {
7 | path: 'index',
8 | component: () => import('@/views/guide/index.vue'),
9 | name: 'Guide',
10 | meta: { title: 'Guide', icon: 'guide' }
11 | }
12 | ]
13 | }
14 | export default guid
15 |
--------------------------------------------------------------------------------
/src/router/modules/other.ts:
--------------------------------------------------------------------------------
1 | import Layout from '@/layout/index.vue'
2 | const other = {
3 | path: '/other',
4 | component: Layout,
5 | meta: { title: 'Other', icon: 'eye-open' },
6 | alwaysShow: true,
7 | children: [
8 | {
9 | path: 'count-to',
10 | component: () => import('@/views/other/count-to.vue'),
11 | name: 'CountTo',
12 | meta: { title: 'CountTo' }
13 | },
14 | {
15 | path: 'd3',
16 | component: () => import('@/views/other/d3/index.vue'),
17 | name: 'd3',
18 | meta: { title: 'd3' }
19 | },
20 | {
21 | path: 'drag-pane',
22 | component: () => import('@/views/other/drag-pane.vue'),
23 | name: 'DragPane',
24 | meta: { title: 'DragPane' }
25 | },
26 | {
27 | path: 'signboard',
28 | component: () => import('@/views/other/signboard/index.vue'),
29 | name: 'signboard',
30 | meta: { title: 'signboard' }
31 | }
32 | ]
33 | }
34 |
35 | export default other
36 |
--------------------------------------------------------------------------------
/src/router/modules/rich-text.ts:
--------------------------------------------------------------------------------
1 | import Layout from '@/layout/index.vue'
2 | const richText = {
3 | path: '/rich-text',
4 | component: Layout,
5 | meta: { title: 'Rich Text', icon: 'clipboard' },
6 | alwaysShow: true,
7 | children: [
8 | {
9 | path: 'tinymce',
10 | name: 'Tinymce',
11 | component: () => import('@/views/rich-text/TinymceExample.vue'),
12 | meta: { title: 'Tinymce', icon: 'nested' }
13 | }
14 | ]
15 | }
16 |
17 | export default richText
18 |
--------------------------------------------------------------------------------
/src/router/modules/table.ts:
--------------------------------------------------------------------------------
1 | import Layout from '@/layout/index.vue'
2 | const table = {
3 | path: '/table',
4 | component: Layout,
5 | meta: { title: 'Table', icon: 'table' },
6 | alwaysShow: true,
7 | children: [
8 | {
9 | path: 'dynamic-table',
10 | name: 'DynamicTable',
11 | component: () => import('@/views/table/dynamic-table.vue'),
12 | meta: { title: 'Dynamic Table', icon: 'nested' }
13 | },
14 | {
15 | path: 'vxe-table',
16 | name: 'VxeTable',
17 | component: () => import('@/views/table/vxe-table.vue'),
18 | meta: { title: 'Vxe Table', icon: 'nested' }
19 | }
20 | ]
21 | }
22 |
23 | export default table
24 |
--------------------------------------------------------------------------------
/src/store/config.ts:
--------------------------------------------------------------------------------
1 | import { defineStore } from 'pinia'
2 | import { langTitle } from '@/hooks/use-common'
3 | import settings from '@/settings'
4 | import { toggleHtmlClass } from '@/theme/utils'
5 | import { i18n } from '@/lang'
6 | export const useConfigStore = defineStore('config', {
7 | state: () => {
8 | return {
9 | language: settings.defaultLanguage,
10 | theme: settings.defaultTheme,
11 | size: settings.defaultSize,
12 | rememberMe: settings.rememberMe,
13 | username: settings.username,
14 | password: settings.password,
15 | }
16 | },
17 | persist: {
18 | storage: localStorage,
19 | paths: ['language', 'theme', 'size',"rememberMe","username","password"]
20 | },
21 | actions: {
22 | setLoginInfo({username,password,rememberMe}){
23 | this.username = username
24 | this.password = password
25 | this.rememberMe = rememberMe
26 | },
27 | setTheme(data: string) {
28 | this.theme = data
29 | toggleHtmlClass(data)
30 | },
31 | setSize(data: string) {
32 | this.size = data
33 | },
34 | setLanguage(lang: string, title) {
35 | const { locale }: any = i18n.global
36 | this.language = lang
37 | locale.value = lang
38 | document.title = langTitle(title) // i18 page title
39 | }
40 | }
41 | })
42 |
--------------------------------------------------------------------------------
/src/store/dict.ts:
--------------------------------------------------------------------------------
1 | /*数据字典*/
2 | import { defineStore } from 'pinia'
3 | const useDictStore = defineStore('dict', {
4 | state: () => ({
5 | dict: {}
6 | }),
7 | actions: {
8 | // 获取字典
9 | getDict(_key) {
10 | return this.dict[_key]||[]
11 | },
12 | // 设置字典
13 | setDict(_key, value) {
14 | this.dict[_key]=value
15 | },
16 | // 删除字典
17 | deleteDict(_key) {
18 | this.dict[_key]=[]
19 | },
20 | // 清空字典
21 | cleanDict() {
22 | this.dict ={}
23 | },
24 | },
25 | // persist: {
26 | // storage: localStorage,
27 | // paths: ['dict']
28 | // },
29 | })
30 | export default useDictStore
31 |
--------------------------------------------------------------------------------
/src/styles/index.scss:
--------------------------------------------------------------------------------
1 | //scss 语法糖包含常用的布局方式 flex column
2 | @import './scss-suger.scss';
3 | //重置 element-plus 样式
4 | @import 'reset-elemenet-plus.scss';
5 | //动画文件
6 | @import './transition.scss';
7 | @import './project-style.scss';
8 |
9 | //reset style
10 | body {
11 | height: 100%;
12 | margin: 0;
13 | padding: 0;
14 | font-size: 14px;
15 | }
16 | * {
17 | box-sizing: border-box;
18 | }
19 | *::before,
20 | *::after {
21 | box-sizing: border-box;
22 | }
23 | a:focus,
24 | a:active {
25 | outline: none;
26 | }
27 | a,
28 | a:focus,
29 | a:hover {
30 | cursor: pointer;
31 | color: inherit;
32 | text-decoration: none;
33 | }
34 |
35 | h1,
36 | h2,
37 | h3,
38 | h4,
39 | h5,
40 | h6 {
41 | line-height: 1;
42 | font-weight: 400;
43 | margin: 0;
44 | padding: 0;
45 | }
46 | span,
47 | output {
48 | display: inline-block;
49 | line-height: 1;
50 | }
51 |
52 | //scroll
53 | @mixin main-show-wh() {
54 | /* css 声明 */
55 | height: calc(90vh - #{var(--nav-bar-height)} - #{var(--tag-view-height)} - #{calc(var(--app-main-padding) * 2)});
56 | width: 100%;
57 | }
58 | .scroll-y {
59 | @include main-show-wh();
60 | overflow-y: auto;
61 | }
62 | .scroll-x {
63 | @include main-show-wh();
64 | overflow-x: auto;
65 | }
66 | .scroll-xy {
67 | @include main-show-wh();
68 | overflow: auto;
69 | }
70 |
71 |
--------------------------------------------------------------------------------
/src/styles/init-loading.css:
--------------------------------------------------------------------------------
1 | /*开屏loading样式设置*/
2 | .loader-wrapper{
3 | display: flex;
4 | flex-direction: column;
5 | justify-content: center;
6 | align-items: center;
7 | height: 80vh;
8 | }
9 |
10 | .loading-gif{
11 |
12 | }
13 |
14 | .load_title{
15 | margin-top: 30px;
16 | font-size: 16px;
17 | }
18 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/src/styles/project-style.scss:
--------------------------------------------------------------------------------
1 | .project-page-style {
2 | background: #fff;
3 | padding: 20px;
4 | padding-top: 0;
5 | }
6 |
7 | .query-page-style {
8 | background: #fff;
9 | padding: 20px;
10 | }
11 |
12 | //汽包
13 | .triangle {
14 | position: relative;
15 | left: 150px;
16 | width: 0;
17 | height: 0;
18 | border: 6px solid transparent;
19 | border-bottom-color: #fafafa;
20 | }
21 |
22 | //table relative
23 | .table-operation-btn {
24 | span {
25 | cursor: pointer;
26 | color: var(--el-color-primary);
27 | display: inline-block;
28 | padding: 0 6px;
29 | }
30 | }
31 | //新增底部 btn
32 | .footer-btn {
33 | position: fixed;
34 | width: calc(100% - var(--side-bar-width));
35 | text-align: center;
36 | border-top: 1px solid var(--lineB3);
37 | background: #ffffff;
38 | padding: 12px 0;
39 | margin-left: 0;
40 | bottom: 0;
41 | z-index: 11;
42 | left: var(--side-bar-width) px;
43 | }
44 |
45 |
46 | /* wi宽度全局样式
47 | ------------------------------- */
48 | @for $i from 5 through 1000 {
49 | .wi-#{$i}px {
50 | width: #{$i}px !important;
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/src/styles/reset-elemenet-plus.scss:
--------------------------------------------------------------------------------
1 | //leave the padding of el-scroll sidebar
2 |
3 | #Sidebar{
4 | .el-scrollbar__view {
5 | padding-bottom: 80px;
6 | }
7 |
8 | }
9 |
10 |
11 | //button icon
12 | .fixed-width {
13 | .el-button {
14 | padding: 7px 0!important;
15 | }
16 | }
17 | //button
18 | .el-button{
19 | padding: 7px 12px!important;
20 | }
21 | .el-dialog {
22 | transform: none;
23 | left: 0;
24 | position: relative;
25 | margin: 0 auto;
26 | }
27 |
28 |
29 | .el-scrollbar{
30 | --el-menu-base-level-padding:15px;
31 | }
32 |
33 |
34 | /* loading loading遮罩层
35 | ------------------------------- */
36 | .el-loading-mask {
37 | // position: relative !important;
38 | .el-loading-spinner {
39 | position: fixed !important;
40 | background: #ffffff !important;
41 | width: 200px !important;
42 | height: 120px !important;
43 | border-radius: 8px !important;
44 | left: 50% !important;
45 | transform: translate(-50%, -50%) !important;
46 | padding-top: 20px !important;
47 | box-shadow: 0 2px 12px 0 rgb(0 0 0 / 10%);
48 | i {
49 | font-size: 20px;
50 | }
51 | .el-loading-text {
52 | margin: 12px 0 0 0 !important;
53 | //color: set-color(brand) !important;
54 | }
55 | }
56 | }
57 |
--------------------------------------------------------------------------------
/src/styles/transition.scss:
--------------------------------------------------------------------------------
1 | // vue global transition css define
2 | /* sidebar-logo-fade */
3 | .sidebar-logo-fade-enter-active {
4 | transition: opacity var(--logo-switch-duration);
5 | }
6 | .sidebar-logo-fade-enter-from,
7 | .sidebar-logo-fade-leave-to {
8 | opacity: 0;
9 | }
10 |
11 | /* fade-transform AppMain*/
12 | .fade-transform-leave-active,
13 | .fade-transform-enter-active {
14 | transition: all var(--page-transform-duration);
15 | }
16 |
17 | .fade-transform-enter-from {
18 | opacity: 0;
19 | transform: translateX(-10px);
20 | }
21 |
22 | .fade-transform-leave-to {
23 | opacity: 0;
24 | transform: translateX(10px);
25 | }
26 | .fade-transform-active {
27 | position: absolute;
28 | }
29 |
30 | /* breadcrumb transition */
31 | .breadcrumb-enter-active,
32 | .breadcrumb-leave-active {
33 | transition: all var(--breadcrumb-change-duration);
34 | }
35 |
36 | .breadcrumb-enter-from,
37 | .breadcrumb-leave-active {
38 | opacity: 0;
39 | transform: translateX(10px);
40 | }
41 |
42 | .breadcrumb-leave-active {
43 | position: absolute;
44 | }
45 |
--------------------------------------------------------------------------------
/src/theme/base/element-plus/checkbox.scss:
--------------------------------------------------------------------------------
1 | html.china-red {
2 | .el-checkbox {
3 | --el-checkbox-font-size: 14px;
4 | --el-checkbox-font-weight: var(--el-font-weight-primary);
5 | --el-checkbox-text-color: #262626;
6 | --el-checkbox-input-height: 14px;
7 | --el-checkbox-input-width: 14px;
8 | --el-checkbox-border-radius: var(--el-border-radius-small);
9 | --el-checkbox-bg-color: var(--el-fill-color-blank);
10 | --el-checkbox-input-border: var(--el-border);
11 |
12 | //disabled
13 | --el-checkbox-disabled-border-color: var(--el-border-color);
14 | --el-checkbox-disabled-input-fill: var(--el-fill-color-light);
15 | --el-checkbox-disabled-icon-color: var(--el-text-color-placeholder);
16 | --el-checkbox-disabled-checked-input-fill: var(--el-border-color-extra-light);
17 | --el-checkbox-disabled-checked-input-border-color: var(--el-border-color);
18 | --el-checkbox-disabled-checked-icon-color: var(--el-text-color-placeholder);
19 |
20 | //check
21 | --el-checkbox-checked-text-color: #262626;
22 | --el-checkbox-checked-input-border-color: transparent;
23 | --el-checkbox-checked-bg-color: #c72210;
24 | --el-checkbox-checked-icon-color: #ffffff;
25 | --el-checkbox-input-border-color-hover: #c72210;
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/src/theme/base/element-plus/css-vars.scss:
--------------------------------------------------------------------------------
1 | @use 'sass:map';
2 |
3 | @use './var' as *;
4 | @use '../../mixins/var' as *;
5 | @use '../../mixins/mixins' as *;
6 |
7 | html.china-red {
8 | color-scheme: china-red;
9 | @each $type in (primary, success, warning, danger, error, info) {
10 | @include set-css-color-rgb($colors, $type);
11 | }
12 |
13 | @each $type in (primary, success, warning, danger, error, info) {
14 | @include set-css-color-type($colors, $type);
15 | }
16 | //--el-color-primary: #c72210;
17 | }
18 |
--------------------------------------------------------------------------------
/src/theme/base/element-plus/form.scss:
--------------------------------------------------------------------------------
1 | html.china-red {
2 | //date
3 | .el-date-range-picker {
4 | --el-datepicker-text-color: var(--el-text-color-regular);
5 | --el-datepicker-off-text-color: var(--el-text-color-placeholder);
6 | --el-datepicker-header-text-color: var(--el-text-color-regular);
7 | --el-datepicker-icon-color: var(--el-text-color-primary);
8 | --el-datepicker-border-color: var(--el-disabled-border-color);
9 | --el-datepicker-inner-border-color: var(--el-border-color-light);
10 | --el-datepicker-inrange-bg-color: #ffece6;
11 | --el-datepicker-inrange-hover-bg-color: var(--el-border-color-extra-light);
12 | --el-datepicker-active-color: var(--el-color-primary);
13 | --el-datepicker-hover-text-color: var(--el-color-primary);
14 | }
15 |
16 | .el-select-dropdown__item.hover,
17 | .el-select-dropdown__item:hover {
18 | background-color: #ffece6;
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/src/theme/base/element-plus/pagination.scss:
--------------------------------------------------------------------------------
1 | html.china-red {
2 | .el-pagination {
3 | --el-text-color-regular: #8c8c8c;
4 | --el-pagination-font-size: 14px;
5 | --el-pagination-bg-color: var(--el-fill-color-blank);
6 | --el-pagination-text-color: var(--el-text-color-primary);
7 | --el-pagination-border-radius: 3px;
8 | --el-pagination-button-color: var(--el-text-color-primary);
9 | --el-pagination-button-width: 32px;
10 | --el-pagination-button-height: 32px;
11 | --el-pagination-button-disabled-color: var(--el-text-color-placeholder);
12 | --el-pagination-button-disabled-bg-color: var(--el-fill-color-blank);
13 | --el-pagination-button-bg-color: var(--el-fill-color);
14 | --el-pagination-hover-color: var(--el-color-primary);
15 | --el-pagination-height-extra-small: 24px;
16 | --el-pagination-line-height-extra-small: var(--el-pagination-height-extra-small);
17 | white-space: nowrap;
18 | padding: 2px 5px;
19 | color: var(--el-pagination-text-color);
20 | font-weight: 400;
21 | display: flex;
22 | align-items: center;
23 | }
24 |
25 | .el-pagination__total {
26 | margin-right: 16px;
27 | font-weight: 400;
28 | color: var(--el-text-color-regular);
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/src/theme/base/element-plus/redio.scss:
--------------------------------------------------------------------------------
1 | html.china-red {
2 | .el-radio {
3 | --el-radio-font-size: var(--el-font-size-base);
4 | --el-radio-text-color: #262626;
5 | --el-radio-font-weight: var(--el-font-weight-primary);
6 | --el-radio-input-height: 14px;
7 | --el-radio-input-width: 14px;
8 | --el-radio-input-border-radius: var(--el-border-radius-circle);
9 | --el-radio-input-bg-color: var(--el-fill-color-blank);
10 | --el-radio-input-border: var(--el-border);
11 | --el-radio-input-border-color: transparent;
12 | //--el-radio-input-border-color-hover: transparent;
13 | }
14 |
15 | .el-radio__input.is-checked + .el-radio__label {
16 | color: #262626;
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/src/theme/base/element-plus/table.scss:
--------------------------------------------------------------------------------
1 | html.china-red {
2 | .el-table {
3 | --el-table-border-color: #f0f0f0;
4 | --el-table-border: 1px solid #f0f0f0;
5 | --el-table-text-color: var(--el-text-color-regular);
6 | --el-table-header-text-color: var(--el-text-color-secondary);
7 | --el-table-row-hover-bg-color: #ffece6;
8 | --el-table-current-row-bg-color: var(--el-color-primary-light-9);
9 | --el-table-header-bg-color: #fafafa;
10 | --el-table-fixed-box-shadow: var(--el-box-shadow-light);
11 | --el-table-bg-color: var(--el-fill-color-blank);
12 | --el-table-tr-bg-color: var(--el-fill-color-blank);
13 | --el-table-expanded-cell-bg-color: var(--el-fill-color-blank);
14 | --el-table-fixed-left-column: inset 10px 0 10px -10px rgba(0, 0, 0, 0.15);
15 | --el-table-fixed-right-column: inset -10px 0 10px -10px rgba(0, 0, 0, 0.15);
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/src/theme/base/index.scss:
--------------------------------------------------------------------------------
1 | /*china-red*/
2 | //element-plus
3 | @use "./element-plus/css-vars";
4 | @use "./element-plus/var";
5 | @use "./element-plus/button";
6 | @use "./element-plus/checkbox";
7 | @use "./element-plus/redio";
8 | @use "./element-plus/pagination";
9 | @use "./element-plus/form";
10 | @use "./element-plus/table";
11 |
12 | //custom
13 | @use "./custom/ct-css-vars";
14 |
--------------------------------------------------------------------------------
/src/theme/china-red/element-plus/checkbox.scss:
--------------------------------------------------------------------------------
1 | html.china-red {
2 | .el-checkbox {
3 | --el-checkbox-font-size: 14px;
4 | --el-checkbox-font-weight: var(--el-font-weight-primary);
5 | --el-checkbox-text-color: #262626;
6 | --el-checkbox-input-height: 14px;
7 | --el-checkbox-input-width: 14px;
8 | --el-checkbox-border-radius: var(--el-border-radius-small);
9 | --el-checkbox-bg-color: var(--el-fill-color-blank);
10 | --el-checkbox-input-border: var(--el-border);
11 |
12 | //disabled
13 | --el-checkbox-disabled-border-color: var(--el-border-color);
14 | --el-checkbox-disabled-input-fill: var(--el-fill-color-light);
15 | --el-checkbox-disabled-icon-color: var(--el-text-color-placeholder);
16 | --el-checkbox-disabled-checked-input-fill: var(--el-border-color-extra-light);
17 | --el-checkbox-disabled-checked-input-border-color: var(--el-border-color);
18 | --el-checkbox-disabled-checked-icon-color: var(--el-text-color-placeholder);
19 |
20 | //check
21 | --el-checkbox-checked-text-color: #262626;
22 | --el-checkbox-checked-input-border-color: transparent;
23 | --el-checkbox-checked-bg-color: #c72210;
24 | --el-checkbox-checked-icon-color: #ffffff;
25 | --el-checkbox-input-border-color-hover: #c72210;
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/src/theme/china-red/element-plus/css-vars.scss:
--------------------------------------------------------------------------------
1 | @use 'sass:map';
2 |
3 | @use './var' as *;
4 | @use '../../mixins/var' as *;
5 | @use '../../mixins/mixins' as *;
6 |
7 | html.china-red {
8 | color-scheme: china-red;
9 | @each $type in (primary, success, warning, danger, error, info) {
10 | @include set-css-color-rgb($colors, $type);
11 | }
12 |
13 | @each $type in (primary, success, warning, danger, error, info) {
14 | @include set-css-color-type($colors, $type);
15 | }
16 | //--el-color-primary: #c72210;
17 | }
18 |
--------------------------------------------------------------------------------
/src/theme/china-red/element-plus/form.scss:
--------------------------------------------------------------------------------
1 | html.china-red {
2 | //date
3 | .el-date-range-picker {
4 | --el-datepicker-text-color: var(--el-text-color-regular);
5 | --el-datepicker-off-text-color: var(--el-text-color-placeholder);
6 | --el-datepicker-header-text-color: var(--el-text-color-regular);
7 | --el-datepicker-icon-color: var(--el-text-color-primary);
8 | --el-datepicker-border-color: var(--el-disabled-border-color);
9 | --el-datepicker-inner-border-color: var(--el-border-color-light);
10 | --el-datepicker-inrange-bg-color: #ffece6;
11 | --el-datepicker-inrange-hover-bg-color: var(--el-border-color-extra-light);
12 | --el-datepicker-active-color: var(--el-color-primary);
13 | --el-datepicker-hover-text-color: var(--el-color-primary);
14 | }
15 |
16 | .el-select-dropdown__item.hover,
17 | .el-select-dropdown__item:hover {
18 | background-color: #ffece6;
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/src/theme/china-red/element-plus/pagination.scss:
--------------------------------------------------------------------------------
1 | html.china-red {
2 | .el-pagination {
3 | --el-text-color-regular: #8c8c8c;
4 | --el-pagination-font-size: 14px;
5 | --el-pagination-bg-color: var(--el-fill-color-blank);
6 | --el-pagination-text-color: var(--el-text-color-primary);
7 | --el-pagination-border-radius: 3px;
8 | --el-pagination-button-color: var(--el-text-color-primary);
9 | --el-pagination-button-width: 32px;
10 | --el-pagination-button-height: 32px;
11 | --el-pagination-button-disabled-color: var(--el-text-color-placeholder);
12 | --el-pagination-button-disabled-bg-color: var(--el-fill-color-blank);
13 | --el-pagination-button-bg-color: var(--el-fill-color);
14 | --el-pagination-hover-color: var(--el-color-primary);
15 | --el-pagination-height-extra-small: 24px;
16 | --el-pagination-line-height-extra-small: var(--el-pagination-height-extra-small);
17 | white-space: nowrap;
18 | padding: 2px 5px;
19 | color: var(--el-pagination-text-color);
20 | font-weight: 400;
21 | display: flex;
22 | align-items: center;
23 | }
24 |
25 | .el-pagination__total {
26 | margin-right: 16px;
27 | font-weight: 400;
28 | color: var(--el-text-color-regular);
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/src/theme/china-red/element-plus/redio.scss:
--------------------------------------------------------------------------------
1 | html.china-red {
2 | .el-radio {
3 | --el-radio-font-size: var(--el-font-size-base);
4 | --el-radio-text-color: #262626;
5 | --el-radio-font-weight: var(--el-font-weight-primary);
6 | --el-radio-input-height: 14px;
7 | --el-radio-input-width: 14px;
8 | --el-radio-input-border-radius: var(--el-border-radius-circle);
9 | --el-radio-input-bg-color: var(--el-fill-color-blank);
10 | --el-radio-input-border: var(--el-border);
11 | --el-radio-input-border-color: transparent;
12 | //--el-radio-input-border-color-hover: transparent;
13 | }
14 |
15 | .el-radio__input.is-checked + .el-radio__label {
16 | color: #262626;
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/src/theme/china-red/element-plus/table.scss:
--------------------------------------------------------------------------------
1 | html.china-red {
2 | .el-table {
3 | --el-table-border-color: #f0f0f0;
4 | --el-table-border: 1px solid #f0f0f0;
5 | --el-table-text-color: var(--el-text-color-regular);
6 | --el-table-header-text-color: var(--el-text-color-secondary);
7 | --el-table-row-hover-bg-color: #ffece6;
8 | --el-table-current-row-bg-color: var(--el-color-primary-light-9);
9 | --el-table-header-bg-color: #fafafa;
10 | --el-table-fixed-box-shadow: var(--el-box-shadow-light);
11 | --el-table-bg-color: var(--el-fill-color-blank);
12 | --el-table-tr-bg-color: var(--el-fill-color-blank);
13 | --el-table-expanded-cell-bg-color: var(--el-fill-color-blank);
14 | --el-table-fixed-left-column: inset 10px 0 10px -10px rgba(0, 0, 0, 0.15);
15 | --el-table-fixed-right-column: inset -10px 0 10px -10px rgba(0, 0, 0, 0.15);
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/src/theme/china-red/index.scss:
--------------------------------------------------------------------------------
1 | /*china-red*/
2 | //element-plus
3 | @use "./element-plus/css-vars";
4 | @use "./element-plus/var";
5 | @use "./element-plus/button";
6 | @use "./element-plus/checkbox";
7 | @use "./element-plus/redio";
8 | @use "./element-plus/pagination";
9 | @use "./element-plus/form";
10 | @use "./element-plus/table";
11 |
12 | //custom
13 | @use "./custom/ct-css-vars";
14 |
--------------------------------------------------------------------------------
/src/theme/dark/element-plus/checkbox.scss:
--------------------------------------------------------------------------------
1 | html.china-red {
2 | .el-checkbox {
3 | --el-checkbox-font-size: 14px;
4 | --el-checkbox-font-weight: var(--el-font-weight-primary);
5 | --el-checkbox-text-color: #262626;
6 | --el-checkbox-input-height: 14px;
7 | --el-checkbox-input-width: 14px;
8 | --el-checkbox-border-radius: var(--el-border-radius-small);
9 | --el-checkbox-bg-color: var(--el-fill-color-blank);
10 | --el-checkbox-input-border: var(--el-border);
11 |
12 | //disabled
13 | --el-checkbox-disabled-border-color: var(--el-border-color);
14 | --el-checkbox-disabled-input-fill: var(--el-fill-color-light);
15 | --el-checkbox-disabled-icon-color: var(--el-text-color-placeholder);
16 | --el-checkbox-disabled-checked-input-fill: var(--el-border-color-extra-light);
17 | --el-checkbox-disabled-checked-input-border-color: var(--el-border-color);
18 | --el-checkbox-disabled-checked-icon-color: var(--el-text-color-placeholder);
19 |
20 | //check
21 | --el-checkbox-checked-text-color: #262626;
22 | --el-checkbox-checked-input-border-color: transparent;
23 | --el-checkbox-checked-bg-color: #c72210;
24 | --el-checkbox-checked-icon-color: #ffffff;
25 | --el-checkbox-input-border-color-hover: #c72210;
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/src/theme/dark/element-plus/css-vars.css:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jzfai/vue3-admin-plus/e68d9108785ab118ef4fc0e6196a93778d2fff29/src/theme/dark/element-plus/css-vars.css
--------------------------------------------------------------------------------
/src/theme/dark/element-plus/css-vars.css.map:
--------------------------------------------------------------------------------
1 | {"version":3,"sourceRoot":"","sources":["var.scss","css-vars.scss","../../mixins/_var.scss"],"names":[],"mappings":"AAAA;ACMA;EACE;ECKA;EAAA;EAAA;EAAA;EAAA;EAAA;EAAA;EAAA;EAAA;EAAA;EAAA;EAAA;EAAA;EAAA;EAAA;EAAA;EAAA;EAAA;EAAA;EAAA;EAAA;EAAA;EAAA;EAAA;EAAA;EAAA;EAAA;EAAA;EAAA;EAAA;EAAA;EAAA;EAAA;EAAA;EAAA;EAAA;EAAA;EAAA;EAAA;EAAA;EAAA;EAAA","file":"css-vars.css"}
--------------------------------------------------------------------------------
/src/theme/dark/element-plus/css-vars.scss:
--------------------------------------------------------------------------------
1 | @use 'sass:map';
2 |
3 | @use './var' as *;
4 | @use '../../mixins/var' as *;
5 | @use '../../mixins/mixins' as *;
6 |
7 | html.china-red {
8 | color-scheme: china-red;
9 | @each $type in (primary, success, warning, danger, error, info) {
10 | @include set-css-color-rgb($colors, $type);
11 | }
12 |
13 | @each $type in (primary, success, warning, danger, error, info) {
14 | @include set-css-color-type($colors, $type);
15 | }
16 | //--el-color-primary: #c72210;
17 | }
18 |
--------------------------------------------------------------------------------
/src/theme/dark/element-plus/form.scss:
--------------------------------------------------------------------------------
1 | html.china-red {
2 | //date
3 | .el-date-range-picker {
4 | --el-datepicker-text-color: var(--el-text-color-regular);
5 | --el-datepicker-off-text-color: var(--el-text-color-placeholder);
6 | --el-datepicker-header-text-color: var(--el-text-color-regular);
7 | --el-datepicker-icon-color: var(--el-text-color-primary);
8 | --el-datepicker-border-color: var(--el-disabled-border-color);
9 | --el-datepicker-inner-border-color: var(--el-border-color-light);
10 | --el-datepicker-inrange-bg-color: #ffece6;
11 | --el-datepicker-inrange-hover-bg-color: var(--el-border-color-extra-light);
12 | --el-datepicker-active-color: var(--el-color-primary);
13 | --el-datepicker-hover-text-color: var(--el-color-primary);
14 | }
15 |
16 | .el-select-dropdown__item.hover,
17 | .el-select-dropdown__item:hover {
18 | background-color: #ffece6;
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/src/theme/dark/element-plus/pagination.scss:
--------------------------------------------------------------------------------
1 | html.china-red {
2 | .el-pagination {
3 | --el-text-color-regular: #8c8c8c;
4 | --el-pagination-font-size: 14px;
5 | --el-pagination-bg-color: var(--el-fill-color-blank);
6 | --el-pagination-text-color: var(--el-text-color-primary);
7 | --el-pagination-border-radius: 3px;
8 | --el-pagination-button-color: var(--el-text-color-primary);
9 | --el-pagination-button-width: 32px;
10 | --el-pagination-button-height: 32px;
11 | --el-pagination-button-disabled-color: var(--el-text-color-placeholder);
12 | --el-pagination-button-disabled-bg-color: var(--el-fill-color-blank);
13 | --el-pagination-button-bg-color: var(--el-fill-color);
14 | --el-pagination-hover-color: var(--el-color-primary);
15 | --el-pagination-height-extra-small: 24px;
16 | --el-pagination-line-height-extra-small: var(--el-pagination-height-extra-small);
17 | white-space: nowrap;
18 | padding: 2px 5px;
19 | color: var(--el-pagination-text-color);
20 | font-weight: 400;
21 | display: flex;
22 | align-items: center;
23 | }
24 |
25 | .el-pagination__total {
26 | margin-right: 16px;
27 | font-weight: 400;
28 | color: var(--el-text-color-regular);
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/src/theme/dark/element-plus/redio.scss:
--------------------------------------------------------------------------------
1 | html.china-red {
2 | .el-radio {
3 | --el-radio-font-size: var(--el-font-size-base);
4 | --el-radio-text-color: #262626;
5 | --el-radio-font-weight: var(--el-font-weight-primary);
6 | --el-radio-input-height: 14px;
7 | --el-radio-input-width: 14px;
8 | --el-radio-input-border-radius: var(--el-border-radius-circle);
9 | --el-radio-input-bg-color: var(--el-fill-color-blank);
10 | --el-radio-input-border: var(--el-border);
11 | --el-radio-input-border-color: transparent;
12 | //--el-radio-input-border-color-hover: transparent;
13 | }
14 |
15 | .el-radio__input.is-checked + .el-radio__label {
16 | color: #262626;
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/src/theme/dark/element-plus/table.scss:
--------------------------------------------------------------------------------
1 | html.china-red {
2 | .el-table {
3 | --el-table-border-color: #f0f0f0;
4 | --el-table-border: 1px solid #f0f0f0;
5 | --el-table-text-color: var(--el-text-color-regular);
6 | --el-table-header-text-color: var(--el-text-color-secondary);
7 | --el-table-row-hover-bg-color: #ffece6;
8 | --el-table-current-row-bg-color: var(--el-color-primary-light-9);
9 | --el-table-header-bg-color: #fafafa;
10 | --el-table-fixed-box-shadow: var(--el-box-shadow-light);
11 | --el-table-bg-color: var(--el-fill-color-blank);
12 | --el-table-tr-bg-color: var(--el-fill-color-blank);
13 | --el-table-expanded-cell-bg-color: var(--el-fill-color-blank);
14 | --el-table-fixed-left-column: inset 10px 0 10px -10px rgba(0, 0, 0, 0.15);
15 | --el-table-fixed-right-column: inset -10px 0 10px -10px rgba(0, 0, 0, 0.15);
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/src/theme/dark/index.scss:
--------------------------------------------------------------------------------
1 | /*china-red*/
2 | //element-plus
3 | //@use "./element-plus/css-vars";
4 | //@use "./element-plus/var";
5 | //@use "./element-plus/button";
6 | //@use "./element-plus/checkbox";
7 | //@use "./element-plus/redio";
8 | //@use "./element-plus/pagination";
9 | //@use "./element-plus/form";
10 | //@use "./element-plus/table";
11 |
12 | //custom
13 | @use "./custom/ct-css-vars";
14 |
--------------------------------------------------------------------------------
/src/theme/index.scss:
--------------------------------------------------------------------------------
1 | // we can add this to custom namespace, default is 'el'
2 | //@forward "element-plus/theme-chalk/src/mixins/config.scss" with (
3 | // $namespace: "el"
4 | //);
5 |
6 | //base-theme
7 | @use "./base";
8 | //theme style such as dark-theme lighting
9 | @use "./dark";
10 | @use "./lighting";
11 | @use "./china-red";
12 |
--------------------------------------------------------------------------------
/src/theme/lighting/element-plus/checkbox.scss:
--------------------------------------------------------------------------------
1 | html.china-red {
2 | .el-checkbox {
3 | --el-checkbox-font-size: 14px;
4 | --el-checkbox-font-weight: var(--el-font-weight-primary);
5 | --el-checkbox-text-color: #262626;
6 | --el-checkbox-input-height: 14px;
7 | --el-checkbox-input-width: 14px;
8 | --el-checkbox-border-radius: var(--el-border-radius-small);
9 | --el-checkbox-bg-color: var(--el-fill-color-blank);
10 | --el-checkbox-input-border: var(--el-border);
11 |
12 | //disabled
13 | --el-checkbox-disabled-border-color: var(--el-border-color);
14 | --el-checkbox-disabled-input-fill: var(--el-fill-color-light);
15 | --el-checkbox-disabled-icon-color: var(--el-text-color-placeholder);
16 | --el-checkbox-disabled-checked-input-fill: var(--el-border-color-extra-light);
17 | --el-checkbox-disabled-checked-input-border-color: var(--el-border-color);
18 | --el-checkbox-disabled-checked-icon-color: var(--el-text-color-placeholder);
19 |
20 | //check
21 | --el-checkbox-checked-text-color: #262626;
22 | --el-checkbox-checked-input-border-color: transparent;
23 | --el-checkbox-checked-bg-color: #c72210;
24 | --el-checkbox-checked-icon-color: #ffffff;
25 | --el-checkbox-input-border-color-hover: #c72210;
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/src/theme/lighting/element-plus/css-vars.css:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jzfai/vue3-admin-plus/e68d9108785ab118ef4fc0e6196a93778d2fff29/src/theme/lighting/element-plus/css-vars.css
--------------------------------------------------------------------------------
/src/theme/lighting/element-plus/css-vars.css.map:
--------------------------------------------------------------------------------
1 | {"version":3,"sourceRoot":"","sources":["var.scss","css-vars.scss","../../mixins/_var.scss"],"names":[],"mappings":"AAAA;ACMA;EACE;ECKA;EAAA;EAAA;EAAA;EAAA;EAAA;EAAA;EAAA;EAAA;EAAA;EAAA;EAAA;EAAA;EAAA;EAAA;EAAA;EAAA;EAAA;EAAA;EAAA;EAAA;EAAA;EAAA;EAAA;EAAA;EAAA;EAAA;EAAA;EAAA;EAAA;EAAA;EAAA;EAAA;EAAA;EAAA;EAAA;EAAA;EAAA;EAAA;EAAA;EAAA;EAAA","file":"css-vars.css"}
--------------------------------------------------------------------------------
/src/theme/lighting/element-plus/css-vars.scss:
--------------------------------------------------------------------------------
1 | @use 'sass:map';
2 |
3 | @use './var' as *;
4 | @use '../../mixins/var' as *;
5 | @use '../../mixins/mixins' as *;
6 |
7 | html.china-red {
8 | color-scheme: china-red;
9 | @each $type in (primary, success, warning, danger, error, info) {
10 | @include set-css-color-rgb($colors,$type);
11 | }
12 |
13 | @each $type in (primary, success, warning, danger, error, info) {
14 | @include set-css-color-type($colors, $type);
15 | }
16 | //--el-color-primary: #c72210;
17 | }
18 |
--------------------------------------------------------------------------------
/src/theme/lighting/element-plus/form.scss:
--------------------------------------------------------------------------------
1 | html.china-red {
2 | //date
3 | .el-date-range-picker {
4 | --el-datepicker-text-color: var(--el-text-color-regular);
5 | --el-datepicker-off-text-color: var(--el-text-color-placeholder);
6 | --el-datepicker-header-text-color: var(--el-text-color-regular);
7 | --el-datepicker-icon-color: var(--el-text-color-primary);
8 | --el-datepicker-border-color: var(--el-disabled-border-color);
9 | --el-datepicker-inner-border-color: var(--el-border-color-light);
10 | --el-datepicker-inrange-bg-color: #ffece6;
11 | --el-datepicker-inrange-hover-bg-color: var(--el-border-color-extra-light);
12 | --el-datepicker-active-color: var(--el-color-primary);
13 | --el-datepicker-hover-text-color: var(--el-color-primary);
14 | }
15 |
16 | .el-select-dropdown__item.hover,
17 | .el-select-dropdown__item:hover {
18 | background-color: #ffece6;
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/src/theme/lighting/element-plus/pagination.scss:
--------------------------------------------------------------------------------
1 | html.china-red {
2 | .el-pagination {
3 | --el-text-color-regular: #8c8c8c;
4 | --el-pagination-font-size: 14px;
5 | --el-pagination-bg-color: var(--el-fill-color-blank);
6 | --el-pagination-text-color: var(--el-text-color-primary);
7 | --el-pagination-border-radius: 3px;
8 | --el-pagination-button-color: var(--el-text-color-primary);
9 | --el-pagination-button-width: 32px;
10 | --el-pagination-button-height: 32px;
11 | --el-pagination-button-disabled-color: var(--el-text-color-placeholder);
12 | --el-pagination-button-disabled-bg-color: var(--el-fill-color-blank);
13 | --el-pagination-button-bg-color: var(--el-fill-color);
14 | --el-pagination-hover-color: var(--el-color-primary);
15 | --el-pagination-height-extra-small: 24px;
16 | --el-pagination-line-height-extra-small: var(--el-pagination-height-extra-small);
17 | white-space: nowrap;
18 | padding: 2px 5px;
19 | color: var(--el-pagination-text-color);
20 | font-weight: 400;
21 | display: flex;
22 | align-items: center;
23 | }
24 |
25 | .el-pagination__total {
26 | margin-right: 16px;
27 | font-weight: 400;
28 | color: var(--el-text-color-regular);
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/src/theme/lighting/element-plus/redio.scss:
--------------------------------------------------------------------------------
1 | html.china-red {
2 | .el-radio {
3 | --el-radio-font-size: var(--el-font-size-base);
4 | --el-radio-text-color: #262626;
5 | --el-radio-font-weight: var(--el-font-weight-primary);
6 | --el-radio-input-height: 14px;
7 | --el-radio-input-width: 14px;
8 | --el-radio-input-border-radius: var(--el-border-radius-circle);
9 | --el-radio-input-bg-color: var(--el-fill-color-blank);
10 | --el-radio-input-border: var(--el-border);
11 | --el-radio-input-border-color: transparent;
12 | //--el-radio-input-border-color-hover: transparent;
13 | }
14 |
15 | .el-radio__input.is-checked + .el-radio__label {
16 | color: #262626;
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/src/theme/lighting/element-plus/table.scss:
--------------------------------------------------------------------------------
1 | html.china-red {
2 | .el-table {
3 | --el-table-border-color: #f0f0f0;
4 | --el-table-border: 1px solid #f0f0f0;
5 | --el-table-text-color: var(--el-text-color-regular);
6 | --el-table-header-text-color: var(--el-text-color-secondary);
7 | --el-table-row-hover-bg-color: #ffece6;
8 | --el-table-current-row-bg-color: var(--el-color-primary-light-9);
9 | --el-table-header-bg-color: #fafafa;
10 | --el-table-fixed-box-shadow: var(--el-box-shadow-light);
11 | --el-table-bg-color: var(--el-fill-color-blank);
12 | --el-table-tr-bg-color: var(--el-fill-color-blank);
13 | --el-table-expanded-cell-bg-color: var(--el-fill-color-blank);
14 | --el-table-fixed-left-column: inset 10px 0 10px -10px rgba(0, 0, 0, 0.15);
15 | --el-table-fixed-right-column: inset -10px 0 10px -10px rgba(0, 0, 0, 0.15);
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/src/theme/lighting/index.scss:
--------------------------------------------------------------------------------
1 | /*china-red*/
2 | //element-plus
3 | //@use "./element-plus/css-vars";
4 | //@use "./element-plus/var";
5 | //@use "./element-plus/button";
6 | //@use "./element-plus/checkbox";
7 | //@use "./element-plus/redio";
8 | //@use "./element-plus/pagination";
9 | //@use "./element-plus/form";
10 | //@use "./element-plus/table";
11 |
12 | //custom
13 | @use "./custom/ct-css-vars";
14 |
--------------------------------------------------------------------------------
/src/theme/mixins/config.scss:
--------------------------------------------------------------------------------
1 | $namespace: 'el' !default;
2 | $common-separator: '-' !default;
3 | $element-separator: '__' !default;
4 | $modifier-separator: '--' !default;
5 | $state-prefix: 'is-' !default;
6 |
--------------------------------------------------------------------------------
/src/theme/mixins/mixins.scss:
--------------------------------------------------------------------------------
1 | //input function
2 | @use 'function' as *;
3 | @forward 'function';
4 |
5 | @forward 'config';
6 | @use 'config' as *;
7 | // el-button{}
8 | @mixin b($block) {
9 | $B: $namespace + '-' + $block !global;
10 |
11 | .#{$B} {
12 | @content;
13 | }
14 | }
15 | @mixin e($element) {
16 | $E: $element !global;
17 | $selector: &;
18 | $currentSelector: '';
19 | @each $unit in $element {
20 | //el-button__text
21 | $currentSelector: #{$currentSelector + '.' + $B + $element-separator + $unit + ','};
22 | }
23 |
24 | @if hitAllSpecialNestRule($selector) {
25 | @at-root {
26 | #{$selector} {
27 | #{$currentSelector} {
28 | @content;
29 | }
30 | }
31 | }
32 | } @else {
33 | @at-root {
34 | #{$currentSelector} {
35 | @content;
36 | }
37 | }
38 | }
39 | }
40 |
41 | @mixin m($modifier) {
42 | $selector: &;
43 | $currentSelector: '';
44 | @each $unit in $modifier {
45 | $currentSelector: #{$currentSelector + $selector + $modifier-separator + $unit + ','};
46 | }
47 |
48 | @at-root {
49 | #{$currentSelector} {
50 | @content;
51 | }
52 | }
53 | }
54 |
55 | @mixin when($state) {
56 | @at-root {
57 | &.#{$state-prefix + $state} {
58 | @content;
59 | }
60 | }
61 | }
62 |
--------------------------------------------------------------------------------
/src/theme/utils/change-theme.ts:
--------------------------------------------------------------------------------
1 | export const toggleHtmlClass = (className) => {
2 | document.querySelectorAll('html')[0].className = className
3 | }
4 |
--------------------------------------------------------------------------------
/src/theme/utils/index.ts:
--------------------------------------------------------------------------------
1 | export * from './change-theme'
2 |
--------------------------------------------------------------------------------
/src/utils/bus.ts:
--------------------------------------------------------------------------------
1 | //bus even
2 | import mitt from 'mitt'
3 | export default mitt()
4 |
--------------------------------------------------------------------------------
/src/utils/mock-axios-req.ts:
--------------------------------------------------------------------------------
1 | import axios from 'axios'
2 | import { ElMessage } from 'element-plus'
3 |
4 | // create an axios instance
5 | const service = axios.create({
6 | baseURL: '', // url = base url + request url
7 | // withCredentials: true, // send cookies when cross-domain requests
8 | timeout: 8000 // request timeout
9 | })
10 |
11 | // request interceptor
12 | service.interceptors.request.use(
13 | (config) => {
14 | return config
15 | },
16 | (error) => {
17 | return Promise.reject(error)
18 | }
19 | )
20 |
21 | // response interceptor
22 | service.interceptors.response.use(
23 | /**
24 | * If you want to get http information such as headers or status
25 | * Please return response => response
26 | */
27 |
28 | /**
29 | * Determine the request status by custom code
30 | * Here is just an example
31 | * You can also judge the status by HTTP Status Code
32 | */
33 | (response) => {
34 | const res = response.data
35 |
36 | // if the custom code is not 20000, it is judged as an error.
37 | if (res.code !== 20000) {
38 | ElMessage({
39 | message: res.ElMessage || 'Error',
40 | type: 'error',
41 | duration: 5 * 1000
42 | })
43 | return Promise.reject(new Error(res.ElMessage || 'Error'))
44 | } else {
45 | return res
46 | }
47 | },
48 | (error) => {
49 | console.log(`err${error}`) // for debug
50 | ElMessage({
51 | message: error.ElMessage,
52 | type: 'error',
53 | duration: 5 * 1000
54 | })
55 | return Promise.reject(error)
56 | }
57 | )
58 |
59 | export default service
60 |
--------------------------------------------------------------------------------
/src/views/charts/keyboard.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
10 |
11 |
18 |
--------------------------------------------------------------------------------
/src/views/charts/line.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
10 |
11 |
18 |
--------------------------------------------------------------------------------
/src/views/charts/mix-chart.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
10 |
11 |
18 |
--------------------------------------------------------------------------------
/src/views/dashboard/ElTag.vue:
--------------------------------------------------------------------------------
1 |
2 | {{label}}
3 |
4 |
5 |
29 |
--------------------------------------------------------------------------------
/src/views/directive/clickoutside.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | 点击状态:{{ sideStr }}
5 |
6 | InSide
7 |
8 |
9 |
10 |
11 |
12 |
22 |
23 |
36 |
--------------------------------------------------------------------------------
/src/views/directive/copy.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | 复制到剪切板
5 |
6 |
7 |
8 |
11 |
12 |
20 |
--------------------------------------------------------------------------------
/src/views/directive/debounce.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 | 防抖按钮
4 |
5 |
6 |
7 |
23 |
24 |
25 |
--------------------------------------------------------------------------------
/src/views/directive/longpress.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
长按指令
4 |
{{ data }}
5 |
6 |
7 |
8 |
14 |
15 |
16 |
--------------------------------------------------------------------------------
/src/views/directive/watermark.vue:
--------------------------------------------------------------------------------
1 |
2 | 我是一个水印页面
3 |
4 |
5 |
6 |
7 |
13 |
--------------------------------------------------------------------------------
/src/views/directive/waves.vue:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
8 |
9 |
10 |
18 |
--------------------------------------------------------------------------------
/src/views/excel/importExcel.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
12 |
13 |
14 |
15 | 上传excel
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
53 |
54 |
55 |
--------------------------------------------------------------------------------
/src/views/form/validators.ts:
--------------------------------------------------------------------------------
1 | interface IValidators {
2 | select: any,
3 | number: any,
4 | text: any
5 | }
6 |
7 | const validators: IValidators = {
8 | select: (rule: any, value: any, callback: any) => {
9 | if (!value) {
10 | callback(new Error('This field is required'))
11 | } else {
12 | callback()
13 | }
14 | },
15 | number: (rule: any, value: any, callback: any) => {
16 | if (!value) {
17 | callback(new Error('This field is required'))
18 | } else {
19 | if (/^\d+$/.test(value)) {
20 | callback()
21 | } else {
22 | callback(new Error('Only numbers'))
23 | }
24 | }
25 | },
26 | text: (rule: any, value: any, callback: any) => {
27 | if (!value) {
28 | callback(new Error('This field is required'))
29 | } else {
30 | callback()
31 | }
32 | }
33 | }
34 |
35 | export default validators
36 |
--------------------------------------------------------------------------------
/src/views/guide/index.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
7 |
8 | {{ t('guide.button') }}
9 |
10 |
11 |
12 |
13 |
34 |
--------------------------------------------------------------------------------
/src/views/guide/steps.ts:
--------------------------------------------------------------------------------
1 | const steps = [
2 | {
3 | element: '#hamburger-container',
4 | popover: {
5 | title: 'Hamburger',
6 | description: 'Open && Close sidebar',
7 | position: 'bottom'
8 | }
9 | },
10 | {
11 | element: '#breadcrumb-container',
12 | popover: {
13 | title: 'Breadcrumb',
14 | description: 'Indicate the current page location',
15 | position: 'bottom'
16 | }
17 | },
18 | {
19 | element: '#screenfull',
20 | popover: {
21 | title: 'Screenfull',
22 | description: 'Set the page into fullscreen',
23 | position: 'left'
24 | }
25 | },
26 | {
27 | element: '#size-select',
28 | popover: {
29 | title: 'Switch Size',
30 | description: 'Switch the system size',
31 | position: 'left'
32 | }
33 | },
34 | {
35 | element: '#tags-view-container',
36 | popover: {
37 | title: 'Tags view',
38 | description: 'The history of the page you visited',
39 | position: 'bottom'
40 | },
41 | padding: 0
42 | }
43 | ]
44 |
45 | export default steps
46 |
--------------------------------------------------------------------------------
/src/views/login/index.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
21 |
22 |
23 |
--------------------------------------------------------------------------------
/src/views/redirect/index.tsx:
--------------------------------------------------------------------------------
1 | import { defineComponent } from 'vue'
2 | export default defineComponent({
3 | setup() {
4 | const route = useRoute()
5 | const router = useRouter()
6 | onBeforeMount(() => {
7 | const { params, query } = route
8 | const { path } = params
9 | router.replace({ path: `/${path}`, query })
10 | })
11 | return () =>
12 | }
13 | })
14 |
--------------------------------------------------------------------------------
/src/views/system/menu/IconSelect.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 | {{ item }}
10 |
11 |
12 |
13 |
14 |
15 |
43 |
44 |
63 |
--------------------------------------------------------------------------------
/src/views/system/menu/requireIcons.js:
--------------------------------------------------------------------------------
1 | const icons = []
2 | const modules = import.meta.glob('../../../icons/common/*.svg')
3 | for (const path in modules) {
4 | const p = path.split('icons/common/')[1].split('.svg')[0]
5 | icons.push(p)
6 | }
7 |
8 | export default icons
9 |
--------------------------------------------------------------------------------
/ts-out-dir/src/api/user.d.ts:
--------------------------------------------------------------------------------
1 | export declare const userInfoReq: () => Promise;
2 | export declare const loginReq: (subForm: any) => import("axios").AxiosPromise;
3 | export declare const loginOutReq: () => import("axios").AxiosPromise;
4 |
--------------------------------------------------------------------------------
/ts-out-dir/src/api/user.js:
--------------------------------------------------------------------------------
1 | import axiosReq from '@/utils/axios-req';
2 | export const userInfoReq = () => {
3 | return new Promise((resolve) => {
4 | const reqConfig = {
5 | url: '/basis-func/user/getUserInfo',
6 | params: { plateFormId: 2 },
7 | method: 'post'
8 | };
9 | axiosReq(reqConfig).then(({ data }) => {
10 | resolve(data);
11 | });
12 | });
13 | };
14 | export const loginReq = (subForm) => {
15 | return axiosReq({
16 | url: '/basis-func/user/loginValid',
17 | params: subForm,
18 | method: 'post'
19 | });
20 | };
21 | export const loginOutReq = () => {
22 | return axiosReq({
23 | url: '/basis-func/user/loginValid',
24 | method: 'post'
25 | });
26 | };
27 |
--------------------------------------------------------------------------------
/ts-out-dir/src/directives/button-codes.d.ts:
--------------------------------------------------------------------------------
1 | declare const _default: {
2 | mounted(el: any, binding: any): void;
3 | componentUpdated(el: any, binding: any): void;
4 | };
5 | export default _default;
6 |
--------------------------------------------------------------------------------
/ts-out-dir/src/directives/button-codes.js:
--------------------------------------------------------------------------------
1 | import { useBasicStore } from '@/store/basic';
2 | function checkPermission(el, { value }) {
3 | if (value && Array.isArray(value)) {
4 | if (value.length) {
5 | const permissionRoles = value;
6 | const hasPermission = useBasicStore().buttonCodes?.some((code) => permissionRoles.includes(code));
7 | if (!hasPermission)
8 | el.parentNode && el.parentNode.removeChild(el);
9 | }
10 | }
11 | else {
12 | throw new Error(`need roles! Like v-permission="['admin','editor']"`);
13 | }
14 | }
15 | export default {
16 | mounted(el, binding) {
17 | checkPermission(el, binding);
18 | },
19 | componentUpdated(el, binding) {
20 | checkPermission(el, binding);
21 | }
22 | };
23 |
--------------------------------------------------------------------------------
/ts-out-dir/src/directives/codes-permission.d.ts:
--------------------------------------------------------------------------------
1 | declare const _default: {
2 | mounted(el: any, binding: any): void;
3 | componentUpdated(el: any, binding: any): void;
4 | };
5 | export default _default;
6 |
--------------------------------------------------------------------------------
/ts-out-dir/src/directives/codes-permission.js:
--------------------------------------------------------------------------------
1 | import { useBasicStore } from '@/store/basic';
2 | function checkPermission(el, { value }) {
3 | if (value && Array.isArray(value)) {
4 | if (value.length > 0) {
5 | const permissionRoles = value;
6 | const hasPermission = useBasicStore().codes?.some((role) => permissionRoles.includes(role));
7 | if (!hasPermission)
8 | el.parentNode && el.parentNode.removeChild(el);
9 | }
10 | }
11 | else {
12 | throw new Error(`need codes! Like v-codes-permission="['admin','editor']"`);
13 | }
14 | }
15 | export default {
16 | mounted(el, binding) {
17 | checkPermission(el, binding);
18 | },
19 | componentUpdated(el, binding) {
20 | checkPermission(el, binding);
21 | }
22 | };
23 |
--------------------------------------------------------------------------------
/ts-out-dir/src/directives/index.d.ts:
--------------------------------------------------------------------------------
1 | export default function (app: any): void;
2 |
--------------------------------------------------------------------------------
/ts-out-dir/src/directives/index.js:
--------------------------------------------------------------------------------
1 | import buttonCodes from './button-codes';
2 | import codesPermission from './codes-permission';
3 | import rolesPermission from './roles-permission';
4 | export default function (app) {
5 | app.directive('ButtonCodes', buttonCodes);
6 | app.directive('CodesPermission', codesPermission);
7 | app.directive('RolesPermission', rolesPermission);
8 | }
9 |
--------------------------------------------------------------------------------
/ts-out-dir/src/directives/roles-permission.d.ts:
--------------------------------------------------------------------------------
1 | declare const _default: {
2 | mounted(el: any, binding: any): void;
3 | componentUpdated(el: any, binding: any): void;
4 | };
5 | export default _default;
6 |
--------------------------------------------------------------------------------
/ts-out-dir/src/directives/roles-permission.js:
--------------------------------------------------------------------------------
1 | import { useBasicStore } from '@/store/basic';
2 | function checkPermission(el, { value }) {
3 | if (value && Array.isArray(value)) {
4 | if (value.length > 0) {
5 | const permissionRoles = value;
6 | const hasPermission = useBasicStore().roles?.some((role) => permissionRoles.includes(role));
7 | if (!hasPermission)
8 | el.parentNode && el.parentNode.removeChild(el);
9 | }
10 | }
11 | else {
12 | throw new Error(`need roles! Like v-roles-permission="['admin','editor']"`);
13 | }
14 | }
15 | export default {
16 | mounted(el, binding) {
17 | checkPermission(el, binding);
18 | },
19 | componentUpdated(el, binding) {
20 | checkPermission(el, binding);
21 | }
22 | };
23 |
--------------------------------------------------------------------------------
/ts-out-dir/src/hooks/use-common.d.ts:
--------------------------------------------------------------------------------
1 | export declare const sleepTimeout: (time: number) => Promise;
2 | export declare const useCommon: () => {
3 | totalPage: import("vue").Ref;
4 | startEndArr: import("vue").Ref;
5 | searchForm: import("vue").Ref<{}>;
6 | dialogTitle: import("vue").Ref;
7 | detailDialog: import("vue").Ref;
8 | };
9 | export declare function cloneDeep(value: any): any;
10 | export declare const copyValueToClipboard: (value: any) => void;
11 |
--------------------------------------------------------------------------------
/ts-out-dir/src/hooks/use-common.js:
--------------------------------------------------------------------------------
1 | import { reactive, toRefs } from 'vue';
2 | import useClipboard from 'vue-clipboard3';
3 | import { ElMessage } from 'element-plus';
4 | export const sleepTimeout = (time) => {
5 | return new Promise((resolve) => {
6 | const timer = setTimeout(() => {
7 | clearTimeout(timer);
8 | resolve(null);
9 | }, time);
10 | });
11 | };
12 | export const useCommon = () => {
13 | const state = reactive({
14 | totalPage: 0,
15 | startEndArr: [],
16 | searchForm: {},
17 | dialogTitle: '',
18 | detailDialog: false
19 | });
20 | return {
21 | ...toRefs(state)
22 | };
23 | };
24 | export function cloneDeep(value) {
25 | return JSON.parse(JSON.stringify(value));
26 | }
27 | const { toClipboard } = useClipboard();
28 | export const copyValueToClipboard = (value) => {
29 | toClipboard(JSON.stringify(value));
30 | ElMessage.success('复制成功');
31 | };
32 |
--------------------------------------------------------------------------------
/ts-out-dir/src/hooks/use-error-log.d.ts:
--------------------------------------------------------------------------------
1 | export declare const useErrorLog: () => void;
2 |
--------------------------------------------------------------------------------
/ts-out-dir/src/hooks/use-error-log.js:
--------------------------------------------------------------------------------
1 | import { jsErrorCollection } from 'js-error-collection';
2 | import pack from '../../package.json';
3 | import settings from '@/settings';
4 | import bus from '@/utils/bus';
5 | import axiosReq from '@/utils/axios-req';
6 | const reqUrl = '/integration-front/errorCollection/insert';
7 | const errorLogReq = (errLog) => {
8 | axiosReq({
9 | url: reqUrl,
10 | data: {
11 | pageUrl: window.location.href,
12 | errorLog: errLog,
13 | browserType: navigator.userAgent,
14 | version: pack.version
15 | },
16 | method: 'post'
17 | }).then(() => {
18 | bus.emit('reloadErrorPage', {});
19 | });
20 | };
21 | export const useErrorLog = () => {
22 | if (settings.errorLog?.includes(import.meta.env.VITE_APP_ENV)) {
23 | jsErrorCollection({ runtimeError: true, rejectError: true, consoleError: true }, (errLog) => {
24 | if (!errLog.includes(reqUrl))
25 | errorLogReq(errLog);
26 | });
27 | }
28 | };
29 |
--------------------------------------------------------------------------------
/ts-out-dir/src/hooks/use-layout.d.ts:
--------------------------------------------------------------------------------
1 | export declare function isExternal(path: any): boolean;
2 | export declare function resizeHandler(): void;
3 |
--------------------------------------------------------------------------------
/ts-out-dir/src/hooks/use-layout.js:
--------------------------------------------------------------------------------
1 | import { onBeforeMount, onBeforeUnmount, onMounted } from 'vue';
2 | import { useBasicStore } from '@/store/basic';
3 | export function isExternal(path) {
4 | return /^(https?:|mailto:|tel:)/.test(path);
5 | }
6 | export function resizeHandler() {
7 | const { body } = document;
8 | const WIDTH = 992;
9 | const basicStore = useBasicStore();
10 | const isMobile = () => {
11 | const rect = body.getBoundingClientRect();
12 | return rect.width - 1 < WIDTH;
13 | };
14 | const resizeHandler = () => {
15 | if (!document.hidden) {
16 | if (isMobile()) {
17 | basicStore.setSidebarOpen(false);
18 | }
19 | else {
20 | basicStore.setSidebarOpen(true);
21 | }
22 | }
23 | };
24 | onBeforeMount(() => {
25 | window.addEventListener('resize', resizeHandler);
26 | });
27 | onMounted(() => {
28 | if (isMobile()) {
29 | basicStore.setSidebarOpen(false);
30 | }
31 | else {
32 | basicStore.setSidebarOpen(true);
33 | }
34 | });
35 | onBeforeUnmount(() => {
36 | window.removeEventListener('resize', resizeHandler);
37 | });
38 | }
39 |
--------------------------------------------------------------------------------
/ts-out-dir/src/hooks/use-permission.d.ts:
--------------------------------------------------------------------------------
1 | import type { RouterTypes } from '~/basic';
2 | import 'nprogress/nprogress.css';
3 | export declare const filterAsyncRoutesByMenuList: (menuList: any) => RouterTypes;
4 | export declare function filterAsyncRoutesByRoles(routes: any, roles: any): RouterTypes;
5 | export declare function filterAsyncRouterByCodes(codesRoutes: any, codes: any): RouterTypes;
6 | export declare function filterAsyncRouter({ menuList, roles, codes }: {
7 | menuList: any;
8 | roles: any;
9 | codes: any;
10 | }): void;
11 | export declare function resetRouter(): void;
12 | export declare function resetState(): void;
13 | export declare function freshRouter(data: any): void;
14 | export declare const progressStart: () => void;
15 | export declare const progressClose: () => void;
16 |
--------------------------------------------------------------------------------
/ts-out-dir/src/hooks/use-self-router.d.ts:
--------------------------------------------------------------------------------
1 | export declare const getQueryParam: () => any;
2 | export declare const routerPush: (name: any, params: any) => void;
3 | export declare const routerReplace: (name: any, params: any) => void;
4 | export declare const routerBack: () => void;
5 |
--------------------------------------------------------------------------------
/ts-out-dir/src/hooks/use-self-router.js:
--------------------------------------------------------------------------------
1 | import router from '@/router';
2 | export const getQueryParam = () => {
3 | const route = router.currentRoute;
4 | if (route.value?.query.params) {
5 | return JSON.parse(route.value.query.params);
6 | }
7 | };
8 | export const routerPush = (name, params) => {
9 | let data = {};
10 | if (params) {
11 | data = {
12 | params: JSON.stringify(params)
13 | };
14 | }
15 | else {
16 | data = {};
17 | }
18 | router.push({
19 | name,
20 | query: data
21 | });
22 | };
23 | export const routerReplace = (name, params) => {
24 | let data = {};
25 | if (params) {
26 | data = {
27 | params: JSON.stringify(params)
28 | };
29 | }
30 | else {
31 | data = {};
32 | }
33 | router.replace({
34 | name,
35 | query: data
36 | });
37 | };
38 | export const routerBack = () => {
39 | router.go(-1);
40 | };
41 |
--------------------------------------------------------------------------------
/ts-out-dir/src/hooks/use-table.d.ts:
--------------------------------------------------------------------------------
1 | export declare const useTable: (searchForm: any, selectPageReq: any) => {
2 | pageNum: import("vue").Ref;
3 | pageSize: import("vue").Ref;
4 | totalPage: import("vue").Ref;
5 | tableListData: import("vue").Ref;
6 | tableListReq: (config: any) => import("axios").AxiosPromise;
7 | dateRangePacking: (timeArr: any) => void;
8 | multipleSelection: import("vue").Ref;
9 | handleSelectionChange: (val: any) => void;
10 | handleCurrentChange: (val: any) => void;
11 | handleSizeChange: (val: any) => void;
12 | resetPageReq: () => void;
13 | multiDelBtnDill: (reqConfig: any) => void;
14 | tableDelDill: (row: any, reqConfig: any) => void;
15 | };
16 |
--------------------------------------------------------------------------------
/ts-out-dir/src/lib/element-plus.d.ts:
--------------------------------------------------------------------------------
1 | export default function (app: any): void;
2 |
--------------------------------------------------------------------------------
/ts-out-dir/src/lib/element-plus.js:
--------------------------------------------------------------------------------
1 | import * as AllComponent from 'element-plus';
2 | const elementPlusComponentNameArr = ['ElButton'];
3 | export default function (app) {
4 | elementPlusComponentNameArr.forEach((component) => {
5 | app.component(component, AllComponent[component]);
6 | });
7 | }
8 |
--------------------------------------------------------------------------------
/ts-out-dir/src/main.d.ts:
--------------------------------------------------------------------------------
1 | import '@/styles/index.scss';
2 | import 'virtual:svg-icons-register';
3 | import './permission';
4 | import './theme/index.scss';
5 | import 'uno.css';
6 | import 'element-plus/dist/index.css';
7 |
--------------------------------------------------------------------------------
/ts-out-dir/src/main.js:
--------------------------------------------------------------------------------
1 | import { createApp } from 'vue';
2 | import App from './App.vue';
3 | const app = createApp(App);
4 | import router from './router';
5 | import '@/styles/index.scss';
6 | import 'virtual:svg-icons-register';
7 | import svgIcon from '@/icons/SvgIcon.vue';
8 | import directive from '@/directives';
9 | import './permission';
10 | import './theme/index.scss';
11 | import 'uno.css';
12 | import ElementPlus from 'element-plus';
13 | import 'element-plus/dist/index.css';
14 | app.use(ElementPlus);
15 | app.component('SvgIcon', svgIcon);
16 | directive(app);
17 | import { createPinia } from 'pinia';
18 | import piniaPluginPersistedstate from 'pinia-plugin-persistedstate';
19 | const pinia = createPinia();
20 | pinia.use(piniaPluginPersistedstate);
21 | app.use(pinia);
22 | app.use(router).mount('#app');
23 |
--------------------------------------------------------------------------------
/ts-out-dir/src/permission.d.ts:
--------------------------------------------------------------------------------
1 | export {};
2 |
--------------------------------------------------------------------------------
/ts-out-dir/src/permission.js:
--------------------------------------------------------------------------------
1 | import router from '@/router';
2 | import { filterAsyncRouter, progressClose, progressStart } from '@/hooks/use-permission';
3 | import { useBasicStore } from '@/store/basic';
4 | import { userInfoReq } from '@/api/user';
5 | const whiteList = ['/login', '/404', '/401'];
6 | router.beforeEach(async (to) => {
7 | progressStart();
8 | const basicStore = useBasicStore();
9 | if (basicStore.token) {
10 | if (to.path === '/login') {
11 | return '/';
12 | }
13 | else {
14 | if (!basicStore.getUserInfo) {
15 | try {
16 | const userData = await userInfoReq();
17 | filterAsyncRouter(userData);
18 | basicStore.setUserInfo(userData);
19 | return { ...to, replace: true };
20 | }
21 | catch (e) {
22 | console.error(`route permission error${e}`);
23 | basicStore.resetState();
24 | progressClose();
25 | return `/login?redirect=${to.path}`;
26 | }
27 | }
28 | else {
29 | return true;
30 | }
31 | }
32 | }
33 | else {
34 | if (!whiteList.includes(to.path)) {
35 | return `/login?redirect=${to.path}`;
36 | }
37 | else {
38 | return true;
39 | }
40 | }
41 | });
42 | router.afterEach(() => {
43 | progressClose();
44 | });
45 |
--------------------------------------------------------------------------------
/ts-out-dir/src/router/index.d.ts:
--------------------------------------------------------------------------------
1 | import type { RouterTypes } from '~/basic';
2 | export declare const constantRoutes: RouterTypes;
3 | export declare const roleCodeRoutes: RouterTypes;
4 | export declare const asyncRoutes: RouterTypes;
5 | declare const router: import("vue-router").Router;
6 | export default router;
7 |
--------------------------------------------------------------------------------
/ts-out-dir/src/settings.d.ts:
--------------------------------------------------------------------------------
1 | import type { SettingsConfig } from '~/basic';
2 | declare const settings: SettingsConfig;
3 | export default settings;
4 |
--------------------------------------------------------------------------------
/ts-out-dir/src/settings.js:
--------------------------------------------------------------------------------
1 | const settings = {
2 | title: 'Vue3 Admin Template',
3 | sidebarLogo: true,
4 | showNavbarTitle: false,
5 | ShowDropDown: true,
6 | showHamburger: true,
7 | showLeftMenu: true,
8 | showTagsView: true,
9 | tagsViewNum: 6,
10 | showTopNavbar: true,
11 | mainNeedAnimation: true,
12 | isNeedNprogress: true,
13 | isNeedLogin: true,
14 | permissionMode: 'roles',
15 | openProdMock: true,
16 | errorLog: ['prod'],
17 | delWindowHeight: '210px',
18 | tmpToken: 'tmp_token',
19 | viteBasePath: './'
20 | };
21 | export default settings;
22 |
--------------------------------------------------------------------------------
/ts-out-dir/src/store/basic.d.ts:
--------------------------------------------------------------------------------
1 | import type { RouterTypes } from '~/basic';
2 | export declare const useBasicStore: import("pinia").StoreDefinition<"basic", {
3 | token: string;
4 | getUserInfo: boolean;
5 | userInfo: {
6 | username: string;
7 | avatar: string;
8 | };
9 | allRoutes: RouterTypes;
10 | buttonCodes: never[];
11 | filterAsyncRoutes: never[];
12 | roles: string[];
13 | codes: number[];
14 | cachedViews: string[];
15 | cachedViewsDeep: string[];
16 | sidebar: {
17 | opened: boolean;
18 | };
19 | axiosPromiseArr: ObjKeys[];
20 | settings: import("~/basic").SettingsConfig;
21 | }, {}, {
22 | setToken(data: any): void;
23 | setFilterAsyncRoutes(routes: any): void;
24 | setUserInfo({ userInfo, roles, codes }: {
25 | userInfo: any;
26 | roles: any;
27 | codes: any;
28 | }): void;
29 | resetState(): void;
30 | resetStateAndToLogin(): void;
31 | M_settings(data: any): void;
32 | setSidebarOpen(data: any): void;
33 | setToggleSideBar(): void;
34 | addCachedView(view: any): void;
35 | delCachedView(view: any): void;
36 | M_RESET_CACHED_VIEW(): void;
37 | addCachedViewDeep(view: any): void;
38 | setCacheViewDeep(view: any): void;
39 | M_RESET_CACHED_VIEW_DEEP(): void;
40 | A_sidebar_opened(data: any): void;
41 | }>;
42 |
--------------------------------------------------------------------------------
/ts-out-dir/src/store/tagsView.d.ts:
--------------------------------------------------------------------------------
1 | export declare const useTagsViewStore: import("pinia").StoreDefinition<"tagsView", {
2 | visitedViews: never[];
3 | }, {}, {
4 | addVisitedView(view: any): void;
5 | delVisitedView(view: any): Promise;
6 | delOthersVisitedViews(view: any): Promise;
7 | delAllVisitedViews(): Promise;
8 | }>;
9 |
--------------------------------------------------------------------------------
/ts-out-dir/src/utils/axios-req.d.ts:
--------------------------------------------------------------------------------
1 | export default function axiosReq(config: any): import("axios").AxiosPromise;
2 |
--------------------------------------------------------------------------------
/ts-out-dir/src/utils/bus.d.ts:
--------------------------------------------------------------------------------
1 | declare const _default: import("mitt").Emitter>;
2 | export default _default;
3 |
--------------------------------------------------------------------------------
/ts-out-dir/src/utils/bus.js:
--------------------------------------------------------------------------------
1 | import mitt from 'mitt';
2 | export default mitt();
3 |
--------------------------------------------------------------------------------
/ts-out-dir/src/utils/common-util.d.ts:
--------------------------------------------------------------------------------
1 | declare const _default: {
2 | getWeek(): string;
3 | mobilePhone(str: any): boolean;
4 | toSplitNumFor(num: any, numToSpace: any): any;
5 | bankCardNo(str: any): boolean;
6 | regEmail(str: any): boolean;
7 | idCardNumber(str: any): boolean;
8 | deleteArrItem(arr: any, arrItem: any): void;
9 | arrToRepeat(arr: any): any;
10 | deRepeatArr(seriesArr: any): unknown[];
11 | byArrObjDeleteArrObj2(arrObj: any, arrObj2: any, objKey: any): any;
12 | deleteArrObjByKey(arrObj: any, objKey: any, value: any): any;
13 | findArrObjByKey(arrObj: any, objKey: any, value: any): any;
14 | byArrObjFindArrObj2(arrObj: any, arrObj2: any, objKey: any): any[];
15 | };
16 | export default _default;
17 |
--------------------------------------------------------------------------------
/ts-out-dir/src/views/redirect/index.d.ts:
--------------------------------------------------------------------------------
1 | declare const _default: import("vue").DefineComponent<{}, () => JSX.Element, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").VNodeProps & import("vue").AllowedComponentProps & import("vue").ComponentCustomProps, Readonly>, {}>;
2 | export default _default;
3 |
--------------------------------------------------------------------------------
/ts-out-dir/src/views/redirect/index.jsx:
--------------------------------------------------------------------------------
1 | import { defineComponent } from 'vue';
2 | export default defineComponent({
3 | setup() {
4 | const route = useRoute();
5 | const router = useRouter();
6 | onBeforeMount(() => {
7 | const { params, query } = route;
8 | const { path } = params;
9 | router.replace({ path: `/${path}`, query });
10 | });
11 | return () =>
;
12 | }
13 | });
14 |
--------------------------------------------------------------------------------
/tsconfig.base.json:
--------------------------------------------------------------------------------
1 | {
2 | //设置files为空,则不会自动扫描默认目录,也就是只会扫描include配置的目录
3 | "files": [],
4 | "compilerOptions": {
5 | "target": "esnext",
6 | "module": "esnext",
7 | //启用所有严格类型检查选项。
8 | //启用 --strict相当于启用 --noImplicitAny, --noImplicitThis, --alwaysStrict, --strictNullChecks和 --strictFunctionTypes和--strictPropertyInitialization。
9 | "strict": true,
10 | // 允许编译器编译JS,JSX文件
11 | "allowJs": false,
12 | // 允许在JS文件中报错,通常与allowJS一起使用
13 | "checkJs": false,
14 | // 允许使用jsx
15 | "jsx": "preserve",
16 | "declaration": true,
17 | //移除注解
18 | "removeComments": true,
19 | //不可以忽略any
20 | "noImplicitAny": false,
21 | //关闭 this 类型注解提示
22 | "noImplicitThis": true,
23 | //null/undefined不能作为其他类型的子类型:
24 | //let a: number = null; //这里会报错.
25 | "strictNullChecks": true,
26 | //生成枚举的映射代码
27 | "preserveConstEnums": true,
28 | //根目录
29 | //输出目录
30 | "outDir": "./ts-out-dir",
31 | //是否输出src2.js.map文件
32 | "sourceMap": false,
33 | //变量定义了但是未使用
34 | "noUnusedLocals": false,
35 | //是否允许把json文件当做模块进行解析
36 | "resolveJsonModule": true,
37 | //和noUnusedLocals一样,针对func
38 | "noUnusedParameters": false,
39 | // 模块解析策略,ts默认用node的解析策略,即相对的方式导入
40 | "moduleResolution": "node",
41 | //允许export=导出,由import from 导入
42 | "esModuleInterop": true,
43 | //忽略所有的声明文件( *.d.ts)的类型检查。
44 | "skipLibCheck": true,
45 | "baseUrl": ".",
46 | //指定默认读取的目录
47 | //"typeRoots": ["./node_modules/@types/", "./types"],
48 | "lib": ["ES2018", "DOM"]
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "./tsconfig.base.json",
3 | "compilerOptions": {
4 | "paths": {
5 | "@/*": ["src/*"],
6 | "~/*": ["typings/*"]
7 | }
8 | },
9 | "include": ["src", "typings"],
10 | "exclude": ["node_modules", "**/dist"]
11 | }
12 |
--------------------------------------------------------------------------------
/typings/components.d.ts:
--------------------------------------------------------------------------------
1 | // generated by unplugin-vue-components
2 | // We suggest you to commit this file into source control
3 | // Read more: https://github.com/vuejs/core/pull/3399
4 | import '@vue/runtime-core'
5 |
6 | export {}
7 |
8 | declare module '@vue/runtime-core' {
9 | export interface GlobalComponents {
10 | ColumnFilter: typeof import('./../src/components/ColumnFilter.vue')['default']
11 | DictTag: typeof import('./../src/components/DictTag.vue')['default']
12 | ElSvgIcon: typeof import('./../src/components/ElSvgIcon.vue')['default']
13 | FileUpload: typeof import('./../src/components/FileUpload/index.vue')['default']
14 | InnerLink: typeof import('./../src/components/InnerLink/index.vue')['default']
15 | JsonInput: typeof import('./../src/components/JsonInput.vue')['default']
16 | Pagination: typeof import('./../src/components/Pagination/index.vue')['default']
17 | ParentView: typeof import('./../src/components/ParentView/index.vue')['default']
18 | RightToolbar: typeof import('./../src/components/RightToolbar/index.vue')['default']
19 | RightToolBar: typeof import('./../src/components/RightToolBar.vue')['default']
20 | RouterLink: typeof import('vue-router')['RouterLink']
21 | RouterView: typeof import('vue-router')['RouterView']
22 | SvgIcon: typeof import('./../src/icons/SvgIcon.vue')['default']
23 | TestUnit: typeof import('./../src/components/TestUnit.vue')['default']
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/typings/env.d.ts:
--------------------------------------------------------------------------------
1 | declare global {
2 | interface ImportMetaEnv {
3 | readonly VITE_APP_BASE_URL: string
4 | readonly VITE_APP_IMAGE_URL: string
5 | readonly VITE_APP_ENV: string
6 | // 更多环境变量...
7 | }
8 | interface ImportMeta {
9 | readonly env: ImportMetaEnv
10 | }
11 | }
12 | export {}
13 |
--------------------------------------------------------------------------------
/typings/global.d.ts:
--------------------------------------------------------------------------------
1 | import type { defineOptions as _defineOptions } from 'unplugin-vue-define-options/macros.d.ts'
2 | declare global {
3 | interface ObjKeys {
4 | [propName: string]: any
5 | }
6 | const GLOBAL_VAR: String
7 | const defineOptions: typeof _defineOptions
8 | }
9 | export {}
10 |
--------------------------------------------------------------------------------
/typings/shims-vue.d.ts:
--------------------------------------------------------------------------------
1 | /*fix the import warning issue of vue file*/
2 | declare module '*.vue' {
3 | import { DefineComponent } from 'vue'
4 | const component: DefineComponent<{}, {}, any>
5 | export default component
6 | }
7 |
--------------------------------------------------------------------------------
/vitest.config.ts:
--------------------------------------------------------------------------------
1 | import { defineConfig } from 'vitest/config'
2 | import Vue from '@vitejs/plugin-vue'
3 | import VueJsx from '@vitejs/plugin-vue-jsx'
4 | // @ts-ignore
5 | import DefineOptions from 'unplugin-vue-define-options/vite'
6 | export default defineConfig({
7 | plugins: [Vue(), VueJsx(), DefineOptions()],
8 | optimizeDeps: {
9 | disabled: true
10 | },
11 | test: {
12 | clearMocks: true,
13 | environment: 'jsdom',
14 | //setup 文件的路径。它们将运行在每个测试文件之前。
15 | setupFiles: ['./vitest.setup.ts'],
16 | transformMode: {
17 | web: [/\.[jt]sx$/]
18 | }
19 | }
20 | })
21 |
--------------------------------------------------------------------------------
/vitest.setup.ts:
--------------------------------------------------------------------------------
1 | import { config } from '@vue/test-utils'
2 | import { vi } from 'vitest'
3 | import ResizeObserver from 'resize-observer-polyfill'
4 | vi.stubGlobal('ResizeObserver', ResizeObserver)
5 | config.global.stubs = {}
6 |
--------------------------------------------------------------------------------