├── .env
├── .env.development
├── .env.production
├── .gitignore
├── .vscode
└── settings.json
├── LICENSE
├── README.md
├── index.html
├── jsconfig.json
├── package.json
├── postcss.config.cjs
├── public
├── auth-bg.svg
├── avatar.jpg
├── favicon.ico
├── logo.png
├── not-image.png
└── skins-thumb
│ ├── businessGray
│ └── thumb.jpg
│ ├── city
│ └── thumb.jpg
│ ├── classics
│ └── thumb.jpg
│ └── mine
│ └── thumb.jpg
├── src
├── App.vue
├── api
│ ├── common.js
│ ├── login.js
│ ├── system
│ │ ├── attachment.js
│ │ ├── config.js
│ │ ├── database.js
│ │ ├── dept.js
│ │ ├── dict.js
│ │ ├── emailLog.js
│ │ ├── loginLog.js
│ │ ├── menu.js
│ │ ├── monitor.js
│ │ ├── notice.js
│ │ ├── operLog.js
│ │ ├── post.js
│ │ ├── role.js
│ │ └── user.js
│ └── tool
│ │ ├── crontab.js
│ │ └── generate.js
├── assets
│ ├── 404.svg
│ ├── image
│ │ ├── action.svg
│ │ ├── attach.svg
│ │ ├── login.svg
│ │ └── user.svg
│ ├── login_picture.svg
│ └── userBanner.jpg
├── components
│ ├── index.js
│ ├── ma-cityLinkage
│ │ ├── index.vue
│ │ └── lib
│ │ │ └── city.json
│ ├── ma-codeEditor
│ │ └── index.vue
│ ├── ma-colorPicker
│ │ └── index.vue
│ ├── ma-verifyCode
│ │ └── index.vue
│ ├── ma-wangEditor
│ │ └── index.vue
│ ├── sa-chart
│ │ └── index.vue
│ ├── sa-checkbox
│ │ └── index.vue
│ ├── sa-dict
│ │ └── index.vue
│ ├── sa-icon-picker
│ │ ├── iconify
│ │ │ └── bi.json
│ │ └── index.vue
│ ├── sa-icon
│ │ └── index.vue
│ ├── sa-radio
│ │ └── index.vue
│ ├── sa-resource
│ │ ├── button.vue
│ │ └── index.vue
│ ├── sa-select
│ │ └── index.vue
│ ├── sa-switch
│ │ └── index.vue
│ ├── sa-table
│ │ ├── defaultOptions.js
│ │ ├── import.vue
│ │ └── index.vue
│ ├── sa-treeSlider
│ │ └── index.vue
│ ├── sa-upload-file
│ │ └── index.vue
│ ├── sa-upload-image
│ │ └── index.vue
│ └── sa-user
│ │ └── index.vue
├── config
│ └── skins.js
├── directives
│ ├── auth
│ │ ├── auth.js
│ │ └── index.js
│ ├── copy
│ │ └── index.js
│ ├── index.js
│ └── role
│ │ ├── index.js
│ │ └── role.js
├── i18n
│ ├── en
│ │ ├── crud.js
│ │ ├── maResource.js
│ │ ├── menus.js
│ │ ├── skin.js
│ │ ├── sys.js
│ │ ├── upload.js
│ │ └── user.js
│ ├── index.js
│ └── zh_CN
│ │ ├── crud.js
│ │ ├── maResource.js
│ │ ├── menus.js
│ │ ├── skin.js
│ │ ├── sys.js
│ │ ├── upload.js
│ │ └── user.js
├── layout
│ ├── 404.vue
│ ├── components
│ │ ├── banner
│ │ │ └── index.vue
│ │ ├── classic
│ │ │ ├── index.vue
│ │ │ ├── ma-classic-header.vue
│ │ │ └── ma-classic-slider.vue
│ │ ├── columns
│ │ │ ├── index.vue
│ │ │ ├── ma-columns-header.vue
│ │ │ └── ma-columns-menu.vue
│ │ ├── components
│ │ │ ├── children-banner.vue
│ │ │ ├── children-menu.vue
│ │ │ ├── iframe-view.vue
│ │ │ ├── message-notification.vue
│ │ │ ├── search.vue
│ │ │ ├── skin.vue
│ │ │ └── sub-menu.vue
│ │ ├── ma-breadcrumb.vue
│ │ ├── ma-buttonMenu.vue
│ │ ├── ma-menu.vue
│ │ ├── ma-operation.vue
│ │ ├── ma-tags.vue
│ │ ├── ma-workerArea.vue
│ │ └── mixed
│ │ │ ├── index.vue
│ │ │ └── top-menu.vue
│ ├── empty.vue
│ ├── index.vue
│ ├── search.vue
│ └── setting.vue
├── main.js
├── plugin
│ └── index.js
├── router
│ ├── homePageRoutes.js
│ ├── index.js
│ └── webRouter.js
├── store
│ ├── index.js
│ └── modules
│ │ ├── app.js
│ │ ├── config.js
│ │ ├── dict.js
│ │ ├── iframe.js
│ │ ├── keepAlive.js
│ │ ├── message.js
│ │ ├── tag.js
│ │ └── user.js
├── style
│ ├── animation.less
│ ├── dark.less
│ ├── global.less
│ ├── index.css
│ ├── skin.less
│ └── skins
│ │ ├── businessGray
│ │ └── index.less
│ │ ├── city
│ │ ├── background.jpg
│ │ └── index.less
│ │ ├── classics
│ │ └── index.less
│ │ └── mine
│ │ └── index.less
├── utils
│ ├── common.js
│ ├── print.js
│ ├── push-vue.js
│ ├── request.js
│ └── tool.js
└── views
│ ├── dashboard
│ ├── components
│ │ ├── components
│ │ │ ├── st-announced.vue
│ │ │ ├── st-count.vue
│ │ │ ├── st-loginChart.vue
│ │ │ ├── st-saiadmin.vue
│ │ │ └── st-welcome.vue
│ │ ├── statistics.vue
│ │ └── work-panel.vue
│ ├── index.vue
│ └── userCenter
│ │ ├── components
│ │ ├── modifyPassword.vue
│ │ └── userInfomation.vue
│ │ └── index.vue
│ ├── login.vue
│ ├── system
│ ├── attachment
│ │ └── index.vue
│ ├── config
│ │ ├── components
│ │ │ ├── add-group.vue
│ │ │ ├── edit.vue
│ │ │ ├── js
│ │ │ │ └── inputType.js
│ │ │ └── manage-config.vue
│ │ └── index.vue
│ ├── database
│ │ ├── index.vue
│ │ ├── recycle.vue
│ │ └── struct.vue
│ ├── dept
│ │ ├── edit.vue
│ │ ├── index.vue
│ │ └── leader.vue
│ ├── dict
│ │ ├── dataList.vue
│ │ ├── edit-data.vue
│ │ ├── edit.vue
│ │ └── index.vue
│ ├── logs
│ │ ├── emailLog.vue
│ │ ├── loginLog.vue
│ │ └── operLog.vue
│ ├── menu
│ │ ├── edit.vue
│ │ └── index.vue
│ ├── monitor
│ │ └── server
│ │ │ └── index.vue
│ ├── notice
│ │ ├── edit.vue
│ │ └── index.vue
│ ├── post
│ │ ├── edit.vue
│ │ ├── index.vue
│ │ └── view.vue
│ ├── role
│ │ ├── components
│ │ │ └── menuPermission.vue
│ │ ├── edit.vue
│ │ └── index.vue
│ └── user
│ │ ├── edit.vue
│ │ └── index.vue
│ └── tool
│ ├── code
│ ├── components
│ │ ├── editInfo.vue
│ │ ├── loadTable.vue
│ │ ├── preview.vue
│ │ └── settingComponent.vue
│ ├── index.vue
│ └── js
│ │ └── vars.js
│ └── crontab
│ ├── edit.vue
│ ├── index.vue
│ ├── logList.vue
│ └── view.vue
├── tailwind.config.cjs
├── tsconfig.json
├── vite.config.js
└── yarn.lock
/.env:
--------------------------------------------------------------------------------
1 | VITE_APP_TITLE = SaiAdmin
2 | VITE_APP_PORT = 8888
3 | VITE_APP_OPEN_PROXY = true
4 | VITE_APP_BASE = /
5 | VITE_APP_TOKEN_PREFIX = token
--------------------------------------------------------------------------------
/.env.development:
--------------------------------------------------------------------------------
1 | # .env.development
2 | VITE_APP_ENV = development
3 |
4 | VITE_APP_BASE_URL = http://127.0.0.1:8787
5 | VITE_APP_WS_URL = ws://127.0.0.1:3131
6 | VITE_APP_WS_APPKEY = 8c849eaf1e166c0a71d02fcec7c8df78
7 | VITE_APP_PROXY_PREFIX = /dev
--------------------------------------------------------------------------------
/.env.production:
--------------------------------------------------------------------------------
1 | # .env.production
2 | VITE_APP_ENV = production
3 |
4 | VITE_APP_BASE_URL = http://admin.saithink.top
5 | VITE_APP_WS_URL = ws://127.0.0.1:3131
6 | VITE_APP_WS_APPKEY = 2f97f2e18b6b6e6304ce77fdb779c650
7 | VITE_APP_PROXY_PREFIX = /prod
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules
2 | .DS_Store
3 | dist
4 | dist-ssr
5 | *.local
6 | .idea
--------------------------------------------------------------------------------
/.vscode/settings.json:
--------------------------------------------------------------------------------
1 | {
2 | "[scss]": {
3 | "editor.defaultFormatter": "esbenp.prettier-vscode"
4 | },
5 | "[jsonc]": {
6 | "editor.defaultFormatter": "esbenp.prettier-vscode"
7 | },
8 | "[javascript]": {
9 | "editor.defaultFormatter": "esbenp.prettier-vscode",
10 | "prettier.singleQuote": true,
11 | "prettier.trailingComma": "none",
12 | "prettier.semi": false
13 | },
14 | "[html]": {
15 | "editor.defaultFormatter": "esbenp.prettier-vscode"
16 | },
17 | "[typescript]": {
18 | "editor.defaultFormatter": "esbenp.prettier-vscode"
19 | },
20 | "[json]": {
21 | "editor.defaultFormatter": "esbenp.prettier-vscode"
22 | },
23 | "[vue]": {
24 | "editor.defaultFormatter": "esbenp.prettier-vscode",
25 | "prettier.semi": false,
26 | "prettier.singleQuote": true,
27 | "prettier.bracketSameLine": true,
28 | "prettier.printWidth": 120,
29 | "prettier.bracketSpacing": true
30 | },
31 | "[css]": {
32 | "editor.defaultFormatter": "esbenp.prettier-vscode"
33 | },
34 | "eslint.options": {
35 | "extensions": [".js", ".vue", ".ts", ".tsx"]
36 | },
37 | "eslint.validate": [
38 | "vue",
39 | "html",
40 | "javascript",
41 | "graphql",
42 | "javascriptreact",
43 | "json",
44 | "typescript",
45 | "typescriptreact",
46 | "vue-html"
47 | ],
48 | "eslint.format.enable": true,
49 | "editor.codeActionsOnSave": {
50 | "source.fixAll.eslint": "explicit"
51 | },
52 | "editor.formatOnSave": true,
53 | "editor.tabSize": 2
54 | }
55 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2022 青衣煮茶
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 | ## 简介
10 |
11 | `Saidmin Vue` 5.x
12 |
13 | ## 安装使用
14 |
15 | - 获取代码
16 |
17 | ```
18 | git clone https://github.com/saithink/saiadmin-vue.git
19 | ```
20 |
21 | 或
22 |
23 | ```
24 | git clone https://gitee.com/appsai/saiadmin-vue.git
25 | ```
26 |
27 | 或
28 |
29 | ```
30 | git clone https://gitcode.com/saigroup/saiadmin-vue.git
31 | ```
32 |
33 | - 安装依赖
34 |
35 | ```
36 | cd saiadmin-vue && yarn install
37 | ```
38 |
39 | - 运行
40 |
41 | ```
42 | yarn dev
43 | ```
44 |
45 | - 打包
46 |
47 | ```
48 | yarn build
49 | ```
50 |
--------------------------------------------------------------------------------
/jsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "baseUrl": ".",
4 | "paths": {
5 | "@/*": ["src/*"],
6 | "@cps/*": ["src/components/*"],
7 | "vue-i18n": ["vue-i18n/dist/vue-i18n.cjs.js"]
8 | },
9 | "jsx": "preserve"
10 | },
11 | "exclude": ["node_modules", "dist", "build"]
12 | }
13 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "saiadmin-vue",
3 | "admin_name": "saiadmin",
4 | "version": "5.0.1",
5 | "type": "module",
6 | "license": "MIT",
7 | "scripts": {
8 | "dev": "vite serve --mode development",
9 | "build": "vite build",
10 | "preview": "vite preview",
11 | "tailwind": "tailwind-config-viewer -o -c tailwind.config.cjs"
12 | },
13 | "dependencies": {
14 | "@arco-design/color": "^0.4.0",
15 | "@arco-design/web-vue": "^2.57.0",
16 | "@wangeditor/editor": "^5.1.23",
17 | "@wangeditor/editor-for-vue": "^5.1.12",
18 | "autoprefixer": "^10.4.17",
19 | "axios": "^0.27.2",
20 | "crypto-js": "^4.2.0",
21 | "dayjs": "^1.11.11",
22 | "echarts": "^5.4.2",
23 | "file2md5": "^1.3.0",
24 | "lodash": "^4.17.21",
25 | "md-editor-v3": "^4.13.5",
26 | "monaco-editor": "^0.33.0",
27 | "nprogress": "^0.2.0",
28 | "pinia": "^2.1.7",
29 | "postcss-import": "^14.1.0",
30 | "qs": "^6.10.3",
31 | "resize-observer-polyfill": "^1.5.1",
32 | "sortablejs": "^1.15.0",
33 | "tailwindcss": "^3.4.1",
34 | "vue": "^3.4.19",
35 | "vue-clipboard3": "^2.0.0",
36 | "vue-color-kit": "^1.0.5",
37 | "vue-echarts": "^6.0.2",
38 | "vue-i18n": "^9.1.10",
39 | "vue-router": "^4.2.5",
40 | "vuedraggable": "^4.1.0"
41 | },
42 | "devDependencies": {
43 | "@iconify/vue": "^4.2.0",
44 | "@vitejs/plugin-vue": "^5.0.4",
45 | "@vitejs/plugin-vue-jsx": "^3.1.0",
46 | "less": "^4.1.3",
47 | "less-loader": "^11.1.4",
48 | "rollup-plugin-visualizer": "^5.12.0",
49 | "tailwind-config-viewer": "^1.7.3",
50 | "typescript": "^4.7.4",
51 | "vite": "^5.1.4"
52 | }
53 | }
54 |
--------------------------------------------------------------------------------
/postcss.config.cjs:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | plugins: {
3 | tailwindcss: {},
4 | autoprefixer: {},
5 | },
6 | }
7 |
--------------------------------------------------------------------------------
/public/avatar.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/saithink/saiadmin-vue/141805149a25a2d4fe13447504c41a19939e26b1/public/avatar.jpg
--------------------------------------------------------------------------------
/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/saithink/saiadmin-vue/141805149a25a2d4fe13447504c41a19939e26b1/public/favicon.ico
--------------------------------------------------------------------------------
/public/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/saithink/saiadmin-vue/141805149a25a2d4fe13447504c41a19939e26b1/public/logo.png
--------------------------------------------------------------------------------
/public/not-image.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/saithink/saiadmin-vue/141805149a25a2d4fe13447504c41a19939e26b1/public/not-image.png
--------------------------------------------------------------------------------
/public/skins-thumb/businessGray/thumb.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/saithink/saiadmin-vue/141805149a25a2d4fe13447504c41a19939e26b1/public/skins-thumb/businessGray/thumb.jpg
--------------------------------------------------------------------------------
/public/skins-thumb/city/thumb.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/saithink/saiadmin-vue/141805149a25a2d4fe13447504c41a19939e26b1/public/skins-thumb/city/thumb.jpg
--------------------------------------------------------------------------------
/public/skins-thumb/classics/thumb.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/saithink/saiadmin-vue/141805149a25a2d4fe13447504c41a19939e26b1/public/skins-thumb/classics/thumb.jpg
--------------------------------------------------------------------------------
/public/skins-thumb/mine/thumb.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/saithink/saiadmin-vue/141805149a25a2d4fe13447504c41a19939e26b1/public/skins-thumb/mine/thumb.jpg
--------------------------------------------------------------------------------
/src/App.vue:
--------------------------------------------------------------------------------
1 |
10 |
11 |
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/src/api/login.js:
--------------------------------------------------------------------------------
1 | import { request } from '@/utils/request.js'
2 |
3 | export default {
4 | /**
5 | * 获取验证码
6 | * @returns
7 | */
8 | getCaptch() {
9 | // return import.meta.env.VITE_APP_PROXY_PREFIX + '/core/captcha?' + Date.parse(new Date().toString())
10 | return request({
11 | url: '/core/captcha',
12 | method: 'get',
13 | })
14 | },
15 |
16 | /**
17 | * 用户登录
18 | * @param {object} params
19 | * @returns
20 | */
21 | login(params = {}) {
22 | return request({
23 | url: '/core/login',
24 | method: 'post',
25 | data: params,
26 | })
27 | },
28 |
29 | /**
30 | * 用户退出
31 | * @param {object} params
32 | * @returns
33 | */
34 | logout(params = {}) {
35 | return request({
36 | url: '/core/logout',
37 | method: 'post',
38 | data: params,
39 | })
40 | },
41 |
42 | /**
43 | * 获取登录用户信息
44 | * @param {object} params
45 | * @returns
46 | */
47 | getInfo(params = {}) {
48 | return request({
49 | url: '/core/system/user',
50 | method: 'get',
51 | data: params,
52 | })
53 | },
54 | }
55 |
--------------------------------------------------------------------------------
/src/api/system/attachment.js:
--------------------------------------------------------------------------------
1 | import { request } from '@/utils/request.js'
2 |
3 | export default {
4 | /**
5 | * 获取文件分页列表
6 | * @returns
7 | */
8 | getPageList(params = {}) {
9 | return request({
10 | url: '/core/attachment/index',
11 | method: 'get',
12 | params
13 | })
14 | },
15 |
16 | /**
17 | * 删除数据
18 | * @returns
19 | */
20 | destroy(data) {
21 | return request({
22 | url: '/core/attachment/destroy',
23 | method: 'delete',
24 | data
25 | })
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/src/api/system/config.js:
--------------------------------------------------------------------------------
1 | import { request } from '@/utils/request.js'
2 |
3 | /**
4 | * 系统设置接口
5 | */
6 | export default {
7 | /**
8 | * 获取配置列表
9 | * @returns
10 | */
11 | getConfigList(params) {
12 | return request({
13 | url: '/core/config/index',
14 | method: 'get',
15 | params
16 | })
17 | },
18 |
19 | /**
20 | * 删除配置
21 | * @returns
22 | */
23 | destroy(data) {
24 | return request({
25 | url: '/core/config/destroy',
26 | method: 'delete',
27 | data
28 | })
29 | },
30 |
31 | /**
32 | * 保存配置
33 | * @returns
34 | */
35 | save(data = {}) {
36 | return request({
37 | url: '/core/config/save',
38 | method: 'post',
39 | data
40 | })
41 | },
42 |
43 | /**
44 | * 修改配置
45 | * @returns
46 | */
47 | update(id, data = {}) {
48 | return request({
49 | url: '/core/config/update?id=' + id,
50 | method: 'put',
51 | data
52 | })
53 | },
54 |
55 | /**
56 | * 按 keys 更新配置
57 | * @returns
58 | */
59 | updateByKeys(data) {
60 | return request({
61 | url: '/core/config/updateByKeys',
62 | method: 'post',
63 | data
64 | })
65 | },
66 |
67 | /**
68 | * 批量修改配置值
69 | * @returns
70 | */
71 | batchUpdate(data) {
72 | return request({
73 | url: '/core/config/batchUpdate',
74 | method: 'post',
75 | data
76 | })
77 | },
78 |
79 | /**
80 | * 获取组列表
81 | * @returns
82 | */
83 | getConfigGroupList(params = {}) {
84 | return request({
85 | url: '/core/configGroup/index',
86 | method: 'get',
87 | params
88 | })
89 | },
90 |
91 | /**
92 | * 保存配置组
93 | * @returns
94 | */
95 | saveConfigGroup(data = {}) {
96 | return request({
97 | url: '/core/configGroup/save',
98 | method: 'post',
99 | data
100 | })
101 | },
102 |
103 | /**
104 | * 更新配置组
105 | * @returns
106 | */
107 | updateConfigGroup(id, data = {}) {
108 | return request({
109 | url: '/core/configGroup/update?id=' + id,
110 | method: 'put',
111 | data
112 | })
113 | },
114 |
115 | /**
116 | * 删除配置组
117 | * @returns
118 | */
119 | deleteConfigGroup(data = {}) {
120 | return request({
121 | url: '/core/configGroup/destroy',
122 | method: 'delete',
123 | data
124 | })
125 | },
126 |
127 | /**
128 | * 邮箱测试
129 | * @returns
130 | */
131 | testEmail(data = {}) {
132 | return request({
133 | url: '/core/configGroup/email',
134 | method: 'post',
135 | data
136 | })
137 | }
138 | }
139 |
--------------------------------------------------------------------------------
/src/api/system/database.js:
--------------------------------------------------------------------------------
1 | import { request } from '@/utils/request.js'
2 |
3 | export default {
4 | /**
5 | * 获取数据表分页列表
6 | * @returns
7 | */
8 | getPageList(params = {}) {
9 | return request({
10 | url: '/core/database/index',
11 | method: 'get',
12 | params
13 | })
14 | },
15 |
16 | /**
17 | * 获取数据源
18 | * @returns
19 | */
20 | getDataSource(params = {}) {
21 | return request({
22 | url: '/core/database/dataSource',
23 | method: 'get',
24 | params
25 | })
26 | },
27 |
28 | /**
29 | * 获取表字段列表
30 | * @returns
31 | */
32 | getDetailed(params = {}) {
33 | return request({
34 | url: '/core/database/detailed',
35 | method: 'get',
36 | params
37 | })
38 | },
39 |
40 | /**
41 | * 获取回收站数据
42 | * @returns
43 | */
44 | getRecycle(params = {}) {
45 | return request({
46 | url: '/core/database/recycle',
47 | method: 'get',
48 | params
49 | })
50 | },
51 |
52 | /**
53 | * 销毁数据
54 | * @returns
55 | */
56 | delete(data) {
57 | return request({
58 | url: '/core/database/delete',
59 | method: 'delete',
60 | data
61 | })
62 | },
63 |
64 | /**
65 | * 恢复数据
66 | * @returns
67 | */
68 | recovery(data) {
69 | return request({
70 | url: '/core/database/recovery',
71 | method: 'post',
72 | data
73 | })
74 | },
75 |
76 | /**
77 | * 优化表
78 | * @returns
79 | */
80 | optimize(data = {}) {
81 | return request({
82 | url: '/core/database/optimize',
83 | method: 'post',
84 | data
85 | })
86 | },
87 |
88 | /**
89 | * 清理表碎片
90 | * @returns
91 | */
92 | fragment(data = {}) {
93 | return request({
94 | url: '/core/database/fragment',
95 | method: 'post',
96 | data
97 | })
98 | }
99 | }
100 |
--------------------------------------------------------------------------------
/src/api/system/dept.js:
--------------------------------------------------------------------------------
1 | import { request } from '@/utils/request.js'
2 |
3 | export default {
4 | /**
5 | * 获取部门树
6 | * @returns
7 | */
8 | getPageList(params = {}) {
9 | return request({
10 | url: '/core/dept/index',
11 | method: 'get',
12 | params
13 | })
14 | },
15 |
16 | /**
17 | * 获取部门领导列表
18 | * @returns
19 | */
20 | getLeaderList(params = {}) {
21 | return request({
22 | url: '/core/dept/leaders',
23 | method: 'get',
24 | params
25 | })
26 | },
27 |
28 | /**
29 | * 新增部门领导
30 | * @returns
31 | */
32 | addLeader(data = {}) {
33 | return request({
34 | url: '/core/dept/addLeader',
35 | method: 'post',
36 | data
37 | })
38 | },
39 |
40 | /**
41 | * 删除部门领导
42 | * @returns
43 | */
44 | delLeader(data = {}) {
45 | return request({
46 | url: '/core/dept/delLeader',
47 | method: 'delete',
48 | data
49 | })
50 | },
51 |
52 | /**
53 | * 获取部门选择树
54 | * @returns
55 | */
56 | tree() {
57 | return request({
58 | url: '/core/dept/index?tree=true',
59 | method: 'get'
60 | })
61 | },
62 |
63 | /**
64 | * 添加数据
65 | * @returns
66 | */
67 | save(params = {}) {
68 | return request({
69 | url: '/core/dept/save',
70 | method: 'post',
71 | data: params
72 | })
73 | },
74 |
75 | /**
76 | * 删除数据
77 | * @returns
78 | */
79 | destroy(data) {
80 | return request({
81 | url: '/core/dept/destroy',
82 | method: 'delete',
83 | data
84 | })
85 | },
86 |
87 | /**
88 | * 修改数据
89 | * @returns
90 | */
91 | update(id, params = {}) {
92 | return request({
93 | url: '/core/dept/update?id=' + id,
94 | method: 'put',
95 | data: params
96 | })
97 | },
98 |
99 | /**
100 | * 更改状态
101 | * @returns
102 | */
103 | changeStatus(data = {}) {
104 | return request({
105 | url: '/core/dept/changeStatus',
106 | method: 'post',
107 | data
108 | })
109 | }
110 | }
111 |
--------------------------------------------------------------------------------
/src/api/system/dict.js:
--------------------------------------------------------------------------------
1 | import { request } from '@/utils/request.js'
2 |
3 | export const dictType = {
4 | /**
5 | * 获取字典类型,无分页
6 | * @returns
7 | */
8 | getPageList(params = {}) {
9 | return request({
10 | url: '/core/dictType/index',
11 | method: 'get',
12 | params
13 | })
14 | },
15 |
16 | /**
17 | * 添加字典类型
18 | * @returns
19 | */
20 | save(params = {}) {
21 | return request({
22 | url: '/core/dictType/save',
23 | method: 'post',
24 | data: params
25 | })
26 | },
27 |
28 | /**
29 | * 删除字典类型
30 | * @returns
31 | */
32 | destroy(data) {
33 | return request({
34 | url: '/core/dictType/destroy',
35 | method: 'delete',
36 | data
37 | })
38 | },
39 |
40 | /**
41 | * 修改字典类型
42 | * @returns
43 | */
44 | update(id, data = {}) {
45 | return request({
46 | url: '/core/dictType/update?id=' + id,
47 | method: 'put',
48 | data
49 | })
50 | },
51 |
52 | /**
53 | * 更改字典类型状态
54 | * @returns
55 | */
56 | changeStatus(data = {}) {
57 | return request({
58 | url: '/core/dictType/changeStatus',
59 | method: 'post',
60 | data
61 | })
62 | }
63 | }
64 |
65 | export const dict = {
66 | /**
67 | * 快捷查询字典
68 | * @param {*} params
69 | * @returns
70 | */
71 | getDict(code) {
72 | return request({
73 | url: '/core/dataDict/index?code=' + code,
74 | method: 'get'
75 | })
76 | },
77 |
78 | /**
79 | * 获取字典数据分页列表
80 | * @returns
81 | */
82 | getPageList(params = {}) {
83 | return request({
84 | url: '/core/dictData/index',
85 | method: 'get',
86 | params
87 | })
88 | },
89 |
90 | /**
91 | * 添加字典数据
92 | * @returns
93 | */
94 | addDictData(data = {}) {
95 | return request({
96 | url: '/core/dictData/save',
97 | method: 'post',
98 | data
99 | })
100 | },
101 |
102 | /**
103 | * 删除字典数据
104 | * @returns
105 | */
106 | destroyDictData(data) {
107 | return request({
108 | url: '/core/dictData/destroy',
109 | method: 'delete',
110 | data
111 | })
112 | },
113 |
114 | /**
115 | * 更新字典数据
116 | * @returns
117 | */
118 | editDictData(id, data = {}) {
119 | return request({
120 | url: '/core/dictData/update?id=' + id,
121 | method: 'put',
122 | data
123 | })
124 | },
125 |
126 | /**
127 | * 更改字典状态
128 | * @returns
129 | */
130 | changeStatus(data = {}) {
131 | return request({
132 | url: '/core/dictData/changeStatus',
133 | method: 'post',
134 | data
135 | })
136 | }
137 | }
138 |
--------------------------------------------------------------------------------
/src/api/system/emailLog.js:
--------------------------------------------------------------------------------
1 | import { request } from '@/utils/request.js'
2 |
3 | /**
4 | * 邮件日志接口
5 | */
6 | export default {
7 | /**
8 | * 数据列表
9 | * @returns
10 | */
11 | getPageList(params = {}) {
12 | return request({
13 | url: '/core/email/index',
14 | method: 'get',
15 | params
16 | })
17 | },
18 |
19 | /**
20 | * 删除数据
21 | * @returns
22 | */
23 | destroy(data) {
24 | return request({
25 | url: '/core/email/destroy',
26 | method: 'delete',
27 | data
28 | })
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/src/api/system/loginLog.js:
--------------------------------------------------------------------------------
1 | import { request } from '@/utils/request.js'
2 |
3 | /**
4 | * 登录日志接口
5 | */
6 | export default {
7 | /**
8 | * 数据列表
9 | * @returns
10 | */
11 | getPageList(params = {}) {
12 | return request({
13 | url: '/core/logs/getLoginLogPageList',
14 | method: 'get',
15 | params
16 | })
17 | },
18 |
19 | /**
20 | * 删除数据
21 | * @returns
22 | */
23 | destroy(data) {
24 | return request({
25 | url: '/core/logs/deleteLoginLog',
26 | method: 'delete',
27 | data
28 | })
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/src/api/system/menu.js:
--------------------------------------------------------------------------------
1 | import { request } from '@/utils/request.js'
2 |
3 | export default {
4 | /**
5 | * 获取数据
6 | * @returns
7 | */
8 | getList(params = {}) {
9 | return request({
10 | url: '/core/menu/index',
11 | method: 'get',
12 | params
13 | })
14 | },
15 |
16 | /**
17 | * 可操作菜单
18 | * @returns
19 | */
20 | accessMenu(params = {}) {
21 | return request({
22 | url: '/core/menu/accessMenu',
23 | method: 'get',
24 | params
25 | })
26 | },
27 |
28 | /**
29 | * 添加数据
30 | * @returns
31 | */
32 | save(params = {}) {
33 | return request({
34 | url: '/core/menu/save',
35 | method: 'post',
36 | data: params
37 | })
38 | },
39 |
40 | /**
41 | * 删除数据
42 | * @returns
43 | */
44 | destroy(data) {
45 | return request({
46 | url: '/core/menu/destroy',
47 | method: 'delete',
48 | data
49 | })
50 | },
51 |
52 | /**
53 | * 更新数据
54 | * @returns
55 | */
56 | update(id, data = {}) {
57 | return request({
58 | url: '/core/menu/update?id=' + id,
59 | method: 'put',
60 | data
61 | })
62 | }
63 | }
64 |
--------------------------------------------------------------------------------
/src/api/system/monitor.js:
--------------------------------------------------------------------------------
1 | import { request } from '@/utils/request.js'
2 |
3 | /**
4 | * 服务监控接口
5 | */
6 | export default {
7 | /**
8 | * 获取服务器信息
9 | * @returns
10 | */
11 | getServerInfo() {
12 | return request({
13 | url: '/core/system/monitor',
14 | method: 'get'
15 | })
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/src/api/system/notice.js:
--------------------------------------------------------------------------------
1 | import { request } from '@/utils/request.js'
2 |
3 | /**
4 | * 通知公告接口
5 | */
6 | export default {
7 | /**
8 | * 数据列表
9 | * @returns
10 | */
11 | getPageList(params = {}) {
12 | return request({
13 | url: '/core/notice/index',
14 | method: 'get',
15 | params
16 | })
17 | },
18 |
19 | /**
20 | * 添加数据
21 | * @returns
22 | */
23 | save(params = {}) {
24 | return request({
25 | url: '/core/notice/save',
26 | method: 'post',
27 | data: params
28 | })
29 | },
30 |
31 | /**
32 | * 读取数据
33 | * @returns
34 | */
35 | read(id) {
36 | return request({
37 | url: '/core/notice/read?id=' + id,
38 | method: 'get'
39 | })
40 | },
41 |
42 | /**
43 | * 删除数据
44 | * @returns
45 | */
46 | destroy(data) {
47 | return request({
48 | url: '/core/notice/destroy',
49 | method: 'delete',
50 | data
51 | })
52 | },
53 |
54 | /**
55 | * 修改数据
56 | * @returns
57 | */
58 | update(id, data = {}) {
59 | return request({
60 | url: '/core/notice/update?id=' + id,
61 | method: 'put',
62 | data
63 | })
64 | },
65 |
66 | /**
67 | * 修改状态
68 | * @returns
69 | */
70 | changeStatus(data = {}) {
71 | return request({
72 | url: '/core/notice/changeStatus',
73 | method: 'post',
74 | data
75 | })
76 | }
77 | }
78 |
--------------------------------------------------------------------------------
/src/api/system/operLog.js:
--------------------------------------------------------------------------------
1 | import { request } from '@/utils/request.js'
2 |
3 | /**
4 | * 操作日志接口
5 | */
6 | export default {
7 | /**
8 | * 数据列表
9 | * @returns
10 | */
11 | getPageList(params = {}) {
12 | return request({
13 | url: '/core/logs/getOperLogPageList',
14 | method: 'get',
15 | params
16 | })
17 | },
18 |
19 | /**
20 | * 删除数据
21 | * @returns
22 | */
23 | destroy(data) {
24 | return request({
25 | url: '/core/logs/deleteOperLog',
26 | method: 'delete',
27 | data
28 | })
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/src/api/system/post.js:
--------------------------------------------------------------------------------
1 | import { request } from '@/utils/request.js'
2 |
3 | /**
4 | * 岗位数据接口
5 | */
6 | export default {
7 | /**
8 | * 数据列表
9 | * @returns
10 | */
11 | getPageList(params = {}) {
12 | return request({
13 | url: '/core/post/index',
14 | method: 'get',
15 | params
16 | })
17 | },
18 |
19 | /**
20 | * 读取数据
21 | * @returns
22 | */
23 | read(id) {
24 | return request({
25 | url: '/core/post/read?id=' + id,
26 | method: 'get'
27 | })
28 | },
29 |
30 | /**
31 | * 添加数据
32 | * @returns
33 | */
34 | save(params = {}) {
35 | return request({
36 | url: '/core/post/save',
37 | method: 'post',
38 | data: params
39 | })
40 | },
41 |
42 | /**
43 | * 修改数据
44 | * @returns
45 | */
46 | update(id, data = {}) {
47 | return request({
48 | url: '/core/post/update?id=' + id,
49 | method: 'put',
50 | data
51 | })
52 | },
53 |
54 | /**
55 | * 更改状态
56 | * @returns
57 | */
58 | changeStatus(data = {}) {
59 | return request({
60 | url: '/core/post/changeStatus',
61 | method: 'post',
62 | data
63 | })
64 | },
65 |
66 | /**
67 | * 删除数据
68 | * @returns
69 | */
70 | destroy(data) {
71 | return request({
72 | url: '/core/post/destroy',
73 | method: 'delete',
74 | data
75 | })
76 | }
77 | }
78 |
--------------------------------------------------------------------------------
/src/api/system/role.js:
--------------------------------------------------------------------------------
1 | import { request } from '@/utils/request.js'
2 |
3 | export default {
4 | /**
5 | * 获取数据列表
6 | * @returns
7 | */
8 | getPageList(params = {}) {
9 | return request({
10 | url: '/core/role/index',
11 | method: 'get',
12 | params
13 | })
14 | },
15 |
16 | /**
17 | * 通过角色获取菜单
18 | * @returns
19 | */
20 | getMenuByRole(id) {
21 | return request({
22 | url: '/core/role/getMenuByRole?id=' + id,
23 | method: 'get'
24 | })
25 | },
26 |
27 | /**
28 | * 通过角色获取部门
29 | * @returns
30 | */
31 | getDeptByRole(id) {
32 | return request({
33 | url: '/core/role/getDeptByRole?id=' + id,
34 | method: 'get'
35 | })
36 | },
37 |
38 | /**
39 | * 添加数据
40 | * @returns
41 | */
42 | save(data = {}) {
43 | return request({
44 | url: '/core/role/save',
45 | method: 'post',
46 | data
47 | })
48 | },
49 |
50 | /**
51 | * 删除数据
52 | * @returns
53 | */
54 | destroy(data) {
55 | return request({
56 | url: '/core/role/destroy',
57 | method: 'delete',
58 | data
59 | })
60 | },
61 |
62 | /**
63 | * 更新数据
64 | * @returns
65 | */
66 | update(id, data = {}) {
67 | return request({
68 | url: '/core/role/update?id=' + id,
69 | method: 'put',
70 | data
71 | })
72 | },
73 |
74 | /**
75 | * 更新菜单权限
76 | * @returns
77 | */
78 | updateMenuPermission(id, data) {
79 | return request({
80 | url: '/core/role/menuPermission?id=' + id,
81 | method: 'post',
82 | data
83 | })
84 | },
85 |
86 | /**
87 | * 更新数据权限
88 | * @returns
89 | */
90 | updateDataPermission(id, data) {
91 | return request({
92 | url: '/core/role/dataPermission?id=' + id,
93 | method: 'post',
94 | data
95 | })
96 | },
97 |
98 | /**
99 | * 更改数据状态
100 | * @returns
101 | */
102 | changeStatus(params = {}) {
103 | return request({
104 | url: '/core/role/changeStatus',
105 | method: 'post',
106 | data: params
107 | })
108 | }
109 | }
110 |
--------------------------------------------------------------------------------
/src/api/system/user.js:
--------------------------------------------------------------------------------
1 | import { request } from '@/utils/request.js'
2 |
3 | export default {
4 | /**
5 | * 获取数据列表
6 | * @returns
7 | */
8 | getPageList(params = {}) {
9 | return request({
10 | url: '/core/user/index',
11 | method: 'get',
12 | params
13 | })
14 | },
15 |
16 | /**
17 | * 读取数据
18 | * @returns
19 | */
20 | read(id) {
21 | return request({
22 | url: '/core/user/read?id=' + id,
23 | method: 'get'
24 | })
25 | },
26 |
27 | /**
28 | * 添加数据
29 | * @returns
30 | */
31 | save(params = {}) {
32 | return request({
33 | url: '/core/user/save',
34 | method: 'post',
35 | data: params
36 | })
37 | },
38 |
39 | /**
40 | * 删除数据
41 | * @returns
42 | */
43 | destroy(data) {
44 | return request({
45 | url: '/core/user/destroy',
46 | method: 'delete',
47 | data
48 | })
49 | },
50 |
51 | /**
52 | * 更新数据
53 | * @returns
54 | */
55 | update(id, data = {}) {
56 | return request({
57 | url: '/core/user/update?id=' + id,
58 | method: 'put',
59 | data
60 | })
61 | },
62 |
63 | /**
64 | * 更改数据状态
65 | * @returns
66 | */
67 | changeStatus(data = {}) {
68 | return request({
69 | url: '/core/user/changeStatus',
70 | method: 'post',
71 | data
72 | })
73 | },
74 |
75 | /**
76 | * 清除用户缓存
77 | * @returns
78 | */
79 | clearCache(params = {}) {
80 | return request({
81 | url: '/core/user/clearCache',
82 | method: 'post',
83 | data: params
84 | })
85 | },
86 |
87 | /**
88 | * 设置用户首页
89 | * @returns
90 | */
91 | setHomePage(data = {}) {
92 | return request({
93 | url: '/core/user/setHomePage',
94 | method: 'post',
95 | data
96 | })
97 | },
98 |
99 | /**
100 | * 初始化用户密码
101 | * @returns
102 | */
103 | initUserPassword(data) {
104 | return request({
105 | url: '/core/user/initUserPassword',
106 | method: 'post',
107 | data
108 | })
109 | },
110 |
111 | /**
112 | * 用户更新个人资料
113 | * @returns
114 | */
115 | updateInfo(data = {}) {
116 | return request({
117 | url: '/core/user/updateInfo',
118 | method: 'post',
119 | data
120 | })
121 | },
122 |
123 | /**
124 | * 用户修改密码
125 | * @returns
126 | */
127 | modifyPassword(data = {}) {
128 | return request({
129 | url: '/core/user/modifyPassword',
130 | method: 'post',
131 | data
132 | })
133 | }
134 | }
135 |
--------------------------------------------------------------------------------
/src/api/tool/crontab.js:
--------------------------------------------------------------------------------
1 | import { request } from '@/utils/request.js'
2 |
3 | /**
4 | * 定时任务接口
5 | */
6 | export default {
7 | /**
8 | * 数据列表
9 | * @returns
10 | */
11 | getPageList(params = {}) {
12 | return request({
13 | url: '/tool/crontab/index',
14 | method: 'get',
15 | params
16 | })
17 | },
18 |
19 | /**
20 | * 日志列表
21 | * @returns
22 | */
23 | getLogPageList(params = {}) {
24 | return request({
25 | url: '/tool/crontab/logPageList',
26 | method: 'get',
27 | params
28 | })
29 | },
30 |
31 | /**
32 | * 删除定时任务日志
33 | * @returns
34 | */
35 | deleteLog(data) {
36 | return request({
37 | url: '/tool/crontab/deleteCrontabLog',
38 | method: 'delete',
39 | data
40 | })
41 | },
42 |
43 | /**
44 | * 立刻执行一次定时任务
45 | * @returns
46 | */
47 | run(data = {}) {
48 | return request({
49 | url: '/tool/crontab/run',
50 | method: 'post',
51 | data
52 | })
53 | },
54 |
55 | /**
56 | * 读取数据
57 | * @returns
58 | */
59 | read(id) {
60 | return request({
61 | url: '/tool/crontab/read?id=' + id,
62 | method: 'get'
63 | })
64 | },
65 |
66 | /**
67 | * 添加
68 | * @returns
69 | */
70 | save(data = {}) {
71 | return request({
72 | url: '/tool/crontab/save',
73 | method: 'post',
74 | data
75 | })
76 | },
77 |
78 | /**
79 | * 删除
80 | * @returns
81 | */
82 | destroy(data) {
83 | return request({
84 | url: '/tool/crontab/destroy',
85 | method: 'delete',
86 | data
87 | })
88 | },
89 |
90 | /**
91 | * 更新数据
92 | * @returns
93 | */
94 | update(id, params = {}) {
95 | return request({
96 | url: '/tool/crontab/update?id=' + id,
97 | method: 'put',
98 | data: params
99 | })
100 | },
101 |
102 | /**
103 | * 更改状态
104 | * @returns
105 | */
106 | changeStatus(data = {}) {
107 | return request({
108 | url: '/tool/crontab/changeStatus',
109 | method: 'post',
110 | data
111 | })
112 | }
113 | }
114 |
--------------------------------------------------------------------------------
/src/api/tool/generate.js:
--------------------------------------------------------------------------------
1 | import { request } from '@/utils/request.js'
2 |
3 | export default {
4 | /**
5 | * 数据列表
6 | * @returns
7 | */
8 | getPageList(params = {}) {
9 | return request({
10 | url: '/tool/code/index',
11 | method: 'get',
12 | params
13 | })
14 | },
15 |
16 | /**
17 | * 删除数据
18 | * @returns
19 | */
20 | destroy(data) {
21 | return request({
22 | url: '/tool/code/destroy',
23 | method: 'delete',
24 | data
25 | })
26 | },
27 |
28 | /**
29 | * 编辑信息
30 | * @returns
31 | */
32 | update(id, data = {}) {
33 | return request({
34 | url: '/tool/code/update?id=' + id,
35 | method: 'put',
36 | data
37 | })
38 | },
39 |
40 | /**
41 | * 读取信息
42 | */
43 | readTable(id) {
44 | return request({
45 | url: '/tool/code/read?id=' + id,
46 | method: 'get'
47 | })
48 | },
49 |
50 | /**
51 | * 生成代码
52 | * @returns
53 | */
54 | generateCode(data = {}) {
55 | return request({
56 | url: '/tool/code/generate',
57 | method: 'post',
58 | responseType: 'blob',
59 | timeout: 20 * 1000,
60 | data
61 | })
62 | },
63 |
64 | /**
65 | * 生成到文件
66 | * @returns
67 | */
68 | generateFile(data = {}) {
69 | return request({
70 | url: '/tool/code/generateFile',
71 | method: 'post',
72 | data
73 | })
74 | },
75 |
76 | /**
77 | * 装载数据表
78 | * @returns
79 | */
80 | loadTable(data = {}) {
81 | return request({
82 | url: '/tool/code/loadTable',
83 | method: 'post',
84 | data
85 | })
86 | },
87 |
88 | /**
89 | * 同步数据表
90 | * @returns
91 | */
92 | sync(id) {
93 | return request({
94 | url: '/tool/code/sync?id=' + id,
95 | method: 'post'
96 | })
97 | },
98 |
99 | /**
100 | * 预览代码
101 | * @returns
102 | */
103 | preview(id) {
104 | return request({
105 | url: '/tool/code/preview?id=' + id,
106 | method: 'get'
107 | })
108 | },
109 |
110 | // 获取表中字段信息
111 | getTableColumns(params = {}) {
112 | return request({
113 | url: '/tool/code/getTableColumns',
114 | method: 'get',
115 | params
116 | })
117 | },
118 |
119 | // 获取数据源列表
120 | getDataSourceList(params = {}) {
121 | return request({
122 | url: '/tool/code/getDataSourceList',
123 | method: 'get',
124 | params
125 | })
126 | },
127 |
128 | // 获取所有模型
129 | getModels() {
130 | return request({
131 | url: '/tool/code/getModels',
132 | method: 'get'
133 | })
134 | }
135 | }
136 |
--------------------------------------------------------------------------------
/src/assets/image/action.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/assets/image/attach.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/assets/image/login.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/assets/image/user.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/assets/userBanner.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/saithink/saiadmin-vue/141805149a25a2d4fe13447504c41a19939e26b1/src/assets/userBanner.jpg
--------------------------------------------------------------------------------
/src/components/index.js:
--------------------------------------------------------------------------------
1 | import { use } from 'echarts/core'
2 | import { CanvasRenderer } from 'echarts/renderers'
3 | import {
4 | BarChart,
5 | LineChart,
6 | PieChart,
7 | RadarChart,
8 | GaugeChart
9 | } from 'echarts/charts'
10 | import {
11 | GridComponent,
12 | TooltipComponent,
13 | LegendComponent,
14 | DataZoomComponent,
15 | GraphicComponent
16 | } from 'echarts/components'
17 |
18 | import MaWangEditor from './ma-wangEditor/index.vue'
19 | import MaColorPicker from './ma-colorPicker/index.vue'
20 | import MaCityLinkage from './ma-cityLinkage/index.vue'
21 |
22 | import SaChart from './sa-chart/index.vue'
23 | import SaCheckbox from './sa-checkbox/index.vue'
24 | import SaRadio from './sa-radio/index.vue'
25 | import SaSelect from './sa-select/index.vue'
26 | import SaSwitch from './sa-switch/index.vue'
27 | import SaTable from './sa-table/index.vue'
28 | import SaTreeSlider from './sa-treeSlider/index.vue'
29 | import SaResource from './sa-resource/index.vue'
30 | import SaResourceButton from './sa-resource/button.vue'
31 | import SaDict from './sa-dict/index.vue'
32 | import SaUser from './sa-user/index.vue'
33 | import SaUploadImage from './sa-upload-image/index.vue'
34 | import SaUploadFile from './sa-upload-file/index.vue'
35 | import SaIcon from './sa-icon/index.vue'
36 | import SaIconPicker from './sa-icon-picker/index.vue'
37 |
38 | use([
39 | CanvasRenderer,
40 | BarChart,
41 | LineChart,
42 | PieChart,
43 | RadarChart,
44 | GaugeChart,
45 | GridComponent,
46 | TooltipComponent,
47 | LegendComponent,
48 | DataZoomComponent,
49 | GraphicComponent
50 | ])
51 |
52 | export default {
53 | install(Vue) {
54 | Vue.component('MaWangEditor', MaWangEditor)
55 | Vue.component('MaColorPicker', MaColorPicker)
56 | Vue.component('MaCityLinkage', MaCityLinkage)
57 |
58 | Vue.component('SaChart', SaChart)
59 | Vue.component('SaCheckbox', SaCheckbox)
60 | Vue.component('SaRadio', SaRadio)
61 | Vue.component('SaSelect', SaSelect)
62 | Vue.component('SaSwitch', SaSwitch)
63 | Vue.component('SaTable', SaTable)
64 | Vue.component('SaTreeSlider', SaTreeSlider)
65 | Vue.component('SaResource', SaResource)
66 | Vue.component('SaResourceButton', SaResourceButton)
67 | Vue.component('SaDict', SaDict)
68 | Vue.component('SaUser', SaUser)
69 | Vue.component('SaUploadImage', SaUploadImage)
70 | Vue.component('SaUploadFile', SaUploadFile)
71 | Vue.component('SaIcon', SaIcon)
72 | Vue.component('SaIconPicker', SaIconPicker)
73 | }
74 | }
75 |
--------------------------------------------------------------------------------
/src/components/ma-codeEditor/index.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
101 |
102 |
109 |
--------------------------------------------------------------------------------
/src/components/ma-colorPicker/index.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | 选择颜色
5 |
6 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
--------------------------------------------------------------------------------
/src/components/ma-verifyCode/index.vue:
--------------------------------------------------------------------------------
1 |
91 |
92 |
93 |
94 |
100 |
101 |
102 |
103 |
--------------------------------------------------------------------------------
/src/components/sa-chart/index.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
37 |
38 |
39 |
--------------------------------------------------------------------------------
/src/components/sa-checkbox/index.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | {{ item.label }}
5 |
6 |
7 |
8 |
9 |
42 |
--------------------------------------------------------------------------------
/src/components/sa-dict/index.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | {{ tool.getLabel(value, props.options.length > 0 ? props.options : dictList[props.dict]) }}
6 |
7 |
8 |
13 | {{ tool.getLabel(value, props.options.length > 0 ? props.options : dictList[props.dict]) }}
14 |
15 |
16 |
17 |
18 |
19 |
43 |
--------------------------------------------------------------------------------
/src/components/sa-icon-picker/index.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 | (visible = true)">选择图标
9 |
10 |
11 |
12 | 选择图标
13 |
14 |
15 |
20 |
21 |
22 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
76 |
77 |
121 |
--------------------------------------------------------------------------------
/src/components/sa-icon/index.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
30 |
--------------------------------------------------------------------------------
/src/components/sa-radio/index.vue:
--------------------------------------------------------------------------------
1 |
2 |
8 | {{ props.nullLabel }}
9 |
10 | {{ item.label }}
11 |
12 |
13 |
14 |
15 |
56 |
--------------------------------------------------------------------------------
/src/components/sa-resource/button.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | 预览已选
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 | 资源选择器
22 |
23 |
24 | 资源选择器
25 |
26 |
27 |
28 |
29 |
30 |
69 |
70 |
83 |
--------------------------------------------------------------------------------
/src/components/sa-select/index.vue:
--------------------------------------------------------------------------------
1 |
2 |
11 |
12 |
13 |
14 |
56 |
--------------------------------------------------------------------------------
/src/components/sa-switch/index.vue:
--------------------------------------------------------------------------------
1 |
2 |
13 | {{ props.checkedText }}
14 | {{ props.uncheckedText }}
15 |
16 |
17 |
18 |
61 |
--------------------------------------------------------------------------------
/src/components/sa-table/defaultOptions.js:
--------------------------------------------------------------------------------
1 | export default {
2 | // 当前crud组件的 id,全局唯一,不指定则随机生成一个
3 | id: undefined,
4 | // 主键名称
5 | pk: 'id',
6 | // 请求api方法
7 | api: () => {},
8 | // 设置分页组件每页记录数
9 | pageSizeOption: [10, 20, 30, 50, 100],
10 | // 设置选择列
11 | rowSelection: undefined,
12 | // 是否显示边框
13 | bordered: { wrapper: true, cell: false },
14 | // 每页记录数
15 | pageSize: 10,
16 | // 默认展开所有行
17 | expandAllRows: false,
18 | // 是否显示总结行
19 | showSummary: false,
20 | // 斑马线
21 | stripe: true,
22 | // 表格大小
23 | size: 'large',
24 | // 是否显示展开/折叠按钮
25 | isExpand: false,
26 | // 是否显示工具栏
27 | showTools: true,
28 | // 页面布局方式,支持 normal(标准)和 fixed(固定)两种
29 | pageLayout: 'fixed',
30 | height: 0,
31 | // 简洁模式
32 | pageSimple: false,
33 | // 显示排序
34 | showSort: true,
35 | // 显示搜索
36 | showSearch: true,
37 | // 搜索提交按钮文案
38 | searchText: '搜索',
39 | // 搜索重置按钮文案
40 | resetText: '重置',
41 | // 强制搜索一行显示
42 | singleLine: false,
43 |
44 | view: {
45 | // 新增api
46 | func: undefined,
47 | // 显示新增按钮的权限
48 | auth: [],
49 | // 按钮文案
50 | text: '查看',
51 | // 是否显示
52 | show: false
53 | },
54 |
55 | add: {
56 | // 新增api
57 | func: undefined,
58 | // 显示新增按钮的权限
59 | auth: [],
60 | // 按钮文案
61 | text: '新增',
62 | // 是否显示
63 | show: false
64 | },
65 | edit: {
66 | // 编辑api
67 | func: undefined,
68 | // 显示编辑按钮的权限
69 | auth: [],
70 | // 按钮文案
71 | text: '编辑',
72 | // 是否显示
73 | show: false
74 | },
75 | delete: {
76 | // 删除api
77 | func: undefined,
78 | // 显示删除按钮的权限
79 | auth: [],
80 | // 按钮文案
81 | text: '删除',
82 | // 是否显示
83 | show: false,
84 | // 是否显示批量处理按钮
85 | batch: true
86 | },
87 | import: {
88 | // 导入url
89 | url: undefined,
90 | // 导入参数
91 | params: {},
92 | // 下载模板地址
93 | templateUrl: undefined,
94 | // 显示导入按钮的权限
95 | auth: [],
96 | // 按钮文案
97 | text: '导入',
98 | // 是否显示
99 | show: false
100 | },
101 | export: {
102 | // 导出url
103 | url: undefined,
104 | // 显示导出按钮的权限
105 | auth: [],
106 | // 按钮文案
107 | text: '导出',
108 | // 是否显示
109 | show: false
110 | },
111 |
112 | // 列对齐方式
113 | columnAlign: 'left',
114 |
115 | // 是否显示索引列
116 | showIndex: false,
117 | // 索引列名称
118 | indexLabel: '序号',
119 | // 索引列宽度
120 | indexColumnWidth: 70,
121 | // 索引列固定方向,false 为不固定
122 | indexColumnFixed: 'left',
123 |
124 | // 是否显示操作列
125 | operationColumn: true,
126 | // 操作列宽度
127 | operationColumnWidth: 190,
128 | // 操作列名称
129 | operationColumnText: '操作'
130 | }
131 |
--------------------------------------------------------------------------------
/src/components/sa-table/import.vue:
--------------------------------------------------------------------------------
1 |
2 |
8 | 导入
9 |
10 |
11 |
14 |
15 |
16 |
导入Excel
17 | 将文件拖到此处,或
点击上传,只能上传 xls/xlsx 文件
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
73 |
--------------------------------------------------------------------------------
/src/components/sa-treeSlider/index.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | {
8 | isExpand ? saTree.expandAll(false) : saTree.expandAll(true)
9 | isExpand = !isExpand
10 | }
11 | "
12 | >{{ isExpand ? '折叠' : '展开' }}
14 |
15 |
16 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
108 |
109 |
121 |
--------------------------------------------------------------------------------
/src/config/skins.js:
--------------------------------------------------------------------------------
1 | export default [
2 | {
3 | name: 'mine',
4 | thumb: 'skins-thumb/mine/thumb.jpg',
5 | },
6 | {
7 | name: 'classics',
8 | thumb: 'skins-thumb/classics/thumb.jpg',
9 | },
10 | {
11 | name: 'businessGray',
12 | thumb: 'skins-thumb/businessGray/thumb.jpg',
13 | },
14 | {
15 | name: 'city',
16 | thumb: 'skins-thumb/city/thumb.jpg',
17 | }
18 | ]
--------------------------------------------------------------------------------
/src/directives/auth/auth.js:
--------------------------------------------------------------------------------
1 | import { useUserStore } from '@/store'
2 |
3 | const auth = name => {
4 | const userStore = useUserStore()
5 | return (userStore.codes && userStore.codes.includes(name)) || (userStore.codes && userStore.codes.includes('*'))
6 | }
7 |
8 | export default auth
--------------------------------------------------------------------------------
/src/directives/auth/index.js:
--------------------------------------------------------------------------------
1 | import auth from './auth'
2 |
3 | const checkAuth = (el, binding) => {
4 | const { value } = binding
5 |
6 | if (Array.isArray(value)) {
7 | if (value.length > 0) {
8 | let isHas = false
9 | value.map(item => {
10 | isHas = auth(item)
11 | })
12 |
13 | if (!isHas && el.parentNode) {
14 | el.parentNode.removeChild(el)
15 | }
16 | }
17 | } else {
18 | throw new Error(`need permission! Like v-auth="['admin','user']"`)
19 | }
20 | }
21 |
22 | export default {
23 | mounted(el, binding) {
24 | checkAuth(el, binding)
25 | },
26 | updated(el, binding) {
27 | checkAuth(el, binding)
28 | },
29 | };
30 |
--------------------------------------------------------------------------------
/src/directives/copy/index.js:
--------------------------------------------------------------------------------
1 | import useClipboard from 'vue-clipboard3'
2 | import { Message } from '@arco-design/web-vue'
3 |
4 | const copy = (el, binding) => {
5 | const { value } = binding
6 | el.addEventListener('click', async () => {
7 | if (value && value !== '') {
8 | try {
9 | await useClipboard().toClipboard(value)
10 | Message.success('已成功复制到剪切板')
11 | } catch(e) {
12 | Message.error('复制失败')
13 | }
14 | } else {
15 | throw new Error(`need for copy content! Like v-copy="Hello World"`)
16 | }
17 | })
18 | }
19 |
20 | export default {
21 | mounted(el, binding) {
22 | copy(el, binding)
23 | },
24 | updated(el, binding) {
25 | copy(el, binding)
26 | },
27 | };
28 |
--------------------------------------------------------------------------------
/src/directives/index.js:
--------------------------------------------------------------------------------
1 | import auth from './auth/index'
2 | import role from './role/index'
3 | import copy from './copy/index'
4 |
5 |
6 | export default {
7 | install (Vue) {
8 | Vue.directive('auth', auth)
9 | Vue.directive('role', role)
10 | Vue.directive('copy', copy)
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/src/directives/role/index.js:
--------------------------------------------------------------------------------
1 | import role from './role'
2 |
3 | const checkRole = (el, binding) => {
4 | const { value } = binding
5 |
6 | if (Array.isArray(value)) {
7 | if (value.length > 0) {
8 | let isHas = false
9 | value.map(item => {
10 | if(!isHas) {
11 | isHas = role(item)
12 | }
13 | })
14 |
15 | if (!isHas && el.parentNode) {
16 | el.parentNode.remove()
17 | }
18 | }
19 | } else {
20 | throw new Error(`need role! Like v-role="['seo', 'cfo']"`)
21 | }
22 | }
23 |
24 | export default {
25 | mounted(el, binding) {
26 | checkRole(el, binding)
27 | },
28 | updated(el, binding) {
29 | checkRole(el, binding)
30 | },
31 | };
32 |
--------------------------------------------------------------------------------
/src/directives/role/role.js:
--------------------------------------------------------------------------------
1 | import { useUserStore } from '@/store'
2 |
3 | const role = name => {
4 | const userStore = useUserStore()
5 | return (userStore.roles && userStore.roles.includes(name)) || (userStore.roles && userStore.roles.includes('superAdmin'))
6 | }
7 |
8 | export default role
--------------------------------------------------------------------------------
/src/i18n/en/crud.js:
--------------------------------------------------------------------------------
1 | export default {
2 |
3 | }
--------------------------------------------------------------------------------
/src/i18n/en/maResource.js:
--------------------------------------------------------------------------------
1 | export default {
2 | loadingText: 'Loading...',
3 | searchFileNotice: 'Search file by name',
4 | searchResource: 'Search resource type',
5 | saveNetworkImage: 'Save network image',
6 | networkImageNotice: 'Please paste the web picture address',
7 | ok: 'OK',
8 | }
--------------------------------------------------------------------------------
/src/i18n/en/menus.js:
--------------------------------------------------------------------------------
1 | export default {
2 | // 特殊页
3 | 'openForm': 'CRUD',
4 |
5 | // 首页菜单
6 | 'home': 'Home',
7 | 'dashboard': 'Dashboard',
8 | 'userCenter': 'User Center',
9 | 'message': 'Message Center',
10 | 'setting:config': 'System Setting',
11 | 'demo': 'Component Demo',
12 |
13 | // 权限
14 | 'permission': 'Permission',
15 | 'system:user': 'User Manage',
16 | 'system:role': 'Role Manage',
17 | 'system:dept': 'Department Manage',
18 | 'system:menu': 'Menu Manage',
19 | 'system:post': 'Post Manage',
20 |
21 | 'dataCenter': 'Data Center',
22 | 'system:dict': 'Dictionary',
23 | 'system:attachment': 'Attached',
24 | 'system:dataMaintain': 'Table Maintenance',
25 | 'system:notice': 'Notice',
26 | 'apps': 'App Center',
27 | 'system:appGroup': 'App Group',
28 | 'system:app': 'App Manage',
29 | 'apis': 'Api Center',
30 | 'system:apiGroup': 'Api Group',
31 | 'system:api': 'Api Manage',
32 |
33 | // 监控
34 | 'monitor': 'Monitor',
35 | 'system:monitor:server': 'Server Monitor',
36 | 'system:onlineUser': 'Online User',
37 | 'system:cache': 'Cache Monitor',
38 | 'system:monitor:rely': 'Reliance Monitor',
39 | 'logs': 'Logs Monitor',
40 | 'system:queueLog': 'Queue Logs',
41 | 'system:loginLog': 'Login Logs',
42 | 'system:operLog': 'Operation Logs',
43 | 'system:apiLog': 'Apis Logs',
44 |
45 | // 工具
46 | 'devTools': 'Tools',
47 | 'setting:module': 'Module Manage',
48 | 'setting:code': 'Code Generator',
49 | 'setting:code:update': 'Edit the build information',
50 | 'setting:crontab': 'Crontab',
51 | 'setting:table': 'Table Designer',
52 | 'systemInterface': 'System Apis',
53 | }
--------------------------------------------------------------------------------
/src/i18n/en/skin.js:
--------------------------------------------------------------------------------
1 | export default {
2 | mine: 'Mine',
3 | classics: 'classics',
4 | businessGray: 'Business gray',
5 | city: 'City',
6 |
7 | mineDesc: 'Predominantly pure white, Mine defaults to skin',
8 | classicsDesc: 'Classic dark sidebar skin',
9 | businessGrayDesc: 'Gray versatility and atmosphere, creating business and stability',
10 | cityDesc: 'May there be a warmth in every angle of the city',
11 |
12 | activated: 'Activated',
13 | use: 'Use'
14 | }
--------------------------------------------------------------------------------
/src/i18n/en/sys.js:
--------------------------------------------------------------------------------
1 | export default {
2 | pageSetting: 'Page Setting',
3 | chinese: '简体中文',
4 | english: 'English',
5 | search: 'Search',
6 | store: 'App Store',
7 | fullScreen: 'Full Screen',
8 | closeFullScreen: 'Close Full Screen',
9 | changeSkin: 'Change Skin',
10 | skin: 'Skin',
11 | layouts: 'Layout',
12 | language: 'Language',
13 | dark: 'Dark Mode',
14 | tag: 'Open Tags',
15 | water: 'Watermark',
16 | waterContent: 'Watermark content',
17 | menuFold: 'Menu Fold',
18 | menuWidth: 'Mene Width',
19 | skinHelp: 'Set up background skins',
20 | layoutsHelp: 'Set the background display',
21 | languageHelp: 'Set the page language and the request background language',
22 | darkHelp: 'Sets the page display mode',
23 | tagHelp: 'Whether to enable multi-tab mode',
24 | waterHelp: 'Whether to display the watermark',
25 | menuFoldHelp: 'Whether the left menu of the system is collapsed',
26 | menuWidthHelp: 'Sets the display width of the left menu',
27 | saveToBackend: 'Save to backend',
28 | backendSettingTitle: 'Backend setting',
29 | systemPrimaryColor: 'System Primary Color',
30 | personalizedConfig: 'Personalized configuration',
31 | layout: {
32 | classic: 'Classic',
33 | columns: 'Columns',
34 | banner: 'Banner',
35 | mixed: 'Mixed',
36 | },
37 | userCenter: 'User Center',
38 | clearCache: 'Clear Cache',
39 | logout: 'Logout System',
40 | logoutAlert: 'Exit prompt',
41 | logoutMessage: 'Are you sure you want to sign out?',
42 | operationMessage: {
43 | message: 'Message',
44 | notification: 'Notification',
45 | todo: 'Todo',
46 | },
47 | goHome: 'Go Home',
48 | notFoundPage: 'Exit tip Ah oh, the page visited was hijacked by the Martians...',
49 | login: {
50 | slogan: 'High-quality middle and back office management system out of the box',
51 | title: 'Login System',
52 | username: 'Username',
53 | usernameNotice: 'Please enter the username',
54 | password: 'Passoword',
55 | passwordNotice: 'Please enter the password',
56 | verifyCode: 'Please enter the verification code',
57 | verifyCodeNotice: 'Please enter the correct verification code',
58 | loginBtn: 'Login in',
59 | otherLoginType: 'Other ways to sign in'
60 | },
61 | verifyCode: {
62 | switch: 'Click Toggle verification code',
63 | error: 'The verification code is incorrect',
64 | notice: 'Please enter the verification code'
65 | },
66 | i18n: 'open multi-language',
67 | i18nHelp: 'Whether to enable the multi-language feature',
68 | ws: 'open websocket',
69 | wsHelp: 'Whether to enable the websocket feature',
70 | round: 'opend round',
71 | roundHelp: 'Whether to enable the round feature',
72 | animation: 'Animation',
73 | animationHelp: 'Page transition animation effect',
74 | animate: {
75 | fade: 'The page fades out',
76 | sliderLeft: 'The page fades to the left',
77 | sliderRight:'The page fades to the right',
78 | sliderDown:'The page fades to the down',
79 | sliderUp:'The page fades to the up',
80 | },
81 | tags: {
82 | refresh: 'Refresh',
83 | fullscreen: 'Full screen',
84 | closeRightTag: 'Close right tag',
85 | closeLeftTag: 'Close left tag',
86 | closeTag: 'Close current tag',
87 | closeOtherTag: 'Close other tag',
88 | },
89 | noticeTitle: 'System Prompted',
90 | save: 'Save',
91 | cancel: 'Cancel',
92 | }
93 |
--------------------------------------------------------------------------------
/src/i18n/en/upload.js:
--------------------------------------------------------------------------------
1 | export default {
2 | fileHashFail: 'Get file hash failed, please try again!',
3 | sizeLimit: 'The file size exceeds the upload limit',
4 | uploadFailed: 'File upload failed',
5 | buttonText: 'Local upload',
6 | clickUpload: 'Click upload',
7 | uploadDesc: 'Drag the file here, or ',
8 | }
--------------------------------------------------------------------------------
/src/i18n/en/user.js:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/saithink/saiadmin-vue/141805149a25a2d4fe13447504c41a19939e26b1/src/i18n/en/user.js
--------------------------------------------------------------------------------
/src/i18n/index.js:
--------------------------------------------------------------------------------
1 | import { createI18n } from 'vue-i18n'
2 | import tool from '@/utils/tool'
3 |
4 | const setting = tool.local.get('setting')
5 |
6 | const getLanguage = () => {
7 | const loadFile = () => {
8 | if (setting.language === 'zh_CN') {
9 | return import.meta.glob('./zh_CN/**/*.js', { eager:true })
10 | } else if (setting.language === 'en') {
11 | return import.meta.glob('./en/**/*.js', { eager:true })
12 | }
13 | }
14 |
15 | const generateLanguage = (fileNames, fileContent, generateLanguages = {}) => {
16 | const fileName = fileNames.shift()
17 | if (fileNames.length > 0) {
18 | if (typeof generateLanguages[fileName] == 'undefined') {
19 | generateLanguages[fileName] = {}
20 | }
21 | generateLanguages[fileName] = generateLanguage(fileNames, fileContent, generateLanguages[fileName])
22 | }else{
23 | generateLanguages[fileName] = fileContent
24 | }
25 | return generateLanguages
26 | }
27 |
28 | const files = loadFile()
29 | let messages = { [setting.language]: {} }
30 | for (let path in files) {
31 | const names = path.match(/([A-Za-z0-9_]+)/g)
32 | //去除语言文件夹和文件后缀名
33 | names.shift()
34 | names.pop()
35 | if (files[path].default) {
36 | messages[setting.language] = generateLanguage(names, files[path].default, messages[setting.language])
37 | }
38 | }
39 | return messages
40 | }
41 |
42 | const i18n = createI18n({
43 | locale: setting.language,
44 | legacy: false,
45 | globalInjection: true,
46 | fallbackLocale: 'zh_CN',
47 | messages: getLanguage()
48 | })
49 |
50 | export default i18n
--------------------------------------------------------------------------------
/src/i18n/zh_CN/crud.js:
--------------------------------------------------------------------------------
1 | export default {
2 |
3 | }
--------------------------------------------------------------------------------
/src/i18n/zh_CN/maResource.js:
--------------------------------------------------------------------------------
1 | export default {
2 | loadingText: '数据加载中...',
3 | searchFileNotice: '文件名搜索',
4 | searchResource: '搜索资源类型',
5 | saveNetworkImage: '保存网络图片',
6 | networkImageNotice: '请粘贴网络图片地址',
7 | ok: '确定'
8 | }
--------------------------------------------------------------------------------
/src/i18n/zh_CN/menus.js:
--------------------------------------------------------------------------------
1 | export default {
2 | // 特殊页
3 | 'openForm': '公共表单',
4 |
5 | // 首页菜单
6 | 'home': '首页',
7 | 'dashboard': '仪表盘',
8 | 'userCenter': '个人中心',
9 | 'message': '消息中心',
10 | 'setting:config': '系统配置',
11 | 'demo': '组件演示',
12 |
13 | // 权限
14 | 'permission': '权限',
15 | 'system:user': '用户管理',
16 | 'system:role': '角色管理',
17 | 'system:dept': '部门管理',
18 | 'system:menu': '菜单管理',
19 | 'system:post': '岗位管理',
20 |
21 | 'dataCenter': '数据',
22 | 'system:dict': '数据字典',
23 | 'system:attachment': '附件管理',
24 | 'system:dataMaintain': '数据表维护',
25 | 'system:notice': '系统公告',
26 | 'apps': '应用中心',
27 | 'system:appGroup': '应用分组',
28 | 'system:app': '应用管理',
29 | 'apis': '应用接口',
30 | 'system:apiGroup': '接口分组',
31 | 'system:api': '接口管理',
32 |
33 | // 监控
34 | 'monitor': '监控',
35 | 'system:monitor:server': '服务监控',
36 | 'system:onlineUser': '在线用户',
37 | 'system:cache': '缓存监控',
38 | 'system:monitor:rely': '依赖监控',
39 | 'logs': '日志监控',
40 | 'system:queueLog': '队列日志',
41 | 'system:loginLog': '登录日志',
42 | 'system:operLog': '操作日志',
43 | 'system:apiLog': '接口日志',
44 |
45 | // 工具
46 | 'devTools': '工具',
47 | 'setting:module': '模块管理',
48 | 'setting:code': '代码生成器',
49 | 'setting:code:update': '编辑生成信息',
50 | 'setting:crontab': '定时任务',
51 | 'setting:table': '数据表设计器',
52 | 'systemInterface': '系统接口',
53 | }
--------------------------------------------------------------------------------
/src/i18n/zh_CN/skin.js:
--------------------------------------------------------------------------------
1 | export default {
2 | mine: 'Mine',
3 | classics: '经典',
4 | businessGray: '商务灰',
5 | city: '城市',
6 |
7 | mineDesc: '以纯净的白色为主,Mine默认皮肤',
8 | classicsDesc: '经典的深色侧边栏皮肤',
9 | businessGrayDesc: '灰色的百搭与大气,营造商务与稳重',
10 | cityDesc: '愿城市每一个角度,都有一份温馨',
11 |
12 | activated: '已激活',
13 | use: '使用'
14 | }
--------------------------------------------------------------------------------
/src/i18n/zh_CN/sys.js:
--------------------------------------------------------------------------------
1 | export default {
2 | pageSetting: '页面设置',
3 | chinese: '简体中文',
4 | english: 'English',
5 | search: '搜索',
6 | store: '应用市场',
7 | fullScreen: '全屏',
8 | closeFullScreen: '关闭全屏',
9 | changeSkin: '换肤',
10 | skin: '当前皮肤',
11 | layouts: '布局',
12 | language: '语言',
13 | dark: '黑夜模式',
14 | tag: '多标签',
15 | water: '水印',
16 | waterContent: '水印内容',
17 | menuFold: '菜单折叠',
18 | menuWidth: '菜单宽度',
19 | skinHelp: '设置后台皮肤',
20 | layoutsHelp: '设置后台显示方式',
21 | languageHelp: '设置页面语言和请求后台语言',
22 | darkHelp: '设置页面显示模式',
23 | tagHelp: '是否启用多标签方式',
24 | waterHelp: '是否显示水印',
25 | menuFoldHelp: '系统左侧菜单是否折叠起来',
26 | menuWidthHelp: '设置左侧菜单的显示宽度',
27 | saveToBackend: '保存到后台',
28 | backendSettingTitle: '后台设置',
29 | systemPrimaryColor: '系统主色调',
30 | personalizedConfig: '个性化配置 ',
31 | layout: {
32 | classic: '经典',
33 | columns: '分栏',
34 | banner: '通栏',
35 | mixed: '混合',
36 | },
37 | userCenter: '个人中心',
38 | clearCache: '清除缓存',
39 | logout: '退出系统',
40 | logoutAlert: '退出提示',
41 | logoutMessage: '确定要退出登录吗?',
42 | operationMessage: {
43 | message: '消息',
44 | notification: '通知',
45 | todo: '待办',
46 | },
47 | goHome: '回到首页',
48 | notFoundPage: '啊哦,访问的页面被火星人劫走了...',
49 | login: {
50 | slogan: '开箱即用的高质量中后台管理系统',
51 | title: '登录',
52 | username: '账户',
53 | usernameNotice: '请输入账户',
54 | password: '密码',
55 | passwordNotice: '请输入密码',
56 | verifyCode: '请输入验证码',
57 | verifyCodeNotice: '请输入正确的验证码',
58 | loginBtn: '登录',
59 | otherLoginType: '其他登录方式'
60 | },
61 | verifyCode: {
62 | switch: '点击切换验证码',
63 | error: '验证码错误',
64 | notice: '请输入验证码'
65 | },
66 | i18n: '开启多语言',
67 | i18nHelp: '是否开启多语言功能',
68 | ws: '开启Ws',
69 | wsHelp: '是否开启Websocket连接',
70 | round: '圆角',
71 | roundHelp: '是否开启圆角',
72 | animation: '切换动画',
73 | animationHelp: '工作区页面切换的进场和出场动画效果',
74 | animate: {
75 | fade: '页面渐隐渐出',
76 | sliderLeft: '页面向左渐出',
77 | sliderRight:'页面向右渐出',
78 | sliderDown:'页面向下渐出',
79 | sliderUp:'页面向上渐出',
80 | },
81 | tags: {
82 | refresh: '刷新',
83 | fullscreen: '全屏',
84 | closeRightTag: '关闭右侧标签',
85 | closeLeftTag: '关闭左侧标签',
86 | closeTag: '关闭当前标签',
87 | closeOtherTag: '关闭其他标签',
88 | },
89 | noticeTitle: '系统提示',
90 | save: '保存',
91 | cancel: '取消',
92 | }
93 |
--------------------------------------------------------------------------------
/src/i18n/zh_CN/upload.js:
--------------------------------------------------------------------------------
1 | export default {
2 | fileHashFail: '获取文件Hash失败,请重试',
3 | sizeLimit: '文件大小超过了限制',
4 | uploadFailed: '文件上传失败',
5 | buttonText: '本地上传',
6 | clickUpload: '点击上传',
7 | uploadDesc: '将文件拖到此处,或',
8 | }
--------------------------------------------------------------------------------
/src/i18n/zh_CN/user.js:
--------------------------------------------------------------------------------
1 | export default {
2 | name: '菜单管理',
3 | 'system:cache': '系统缓存'
4 | }
--------------------------------------------------------------------------------
/src/layout/404.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |

6 |
{{ $t('sys.notFoundPage') }}
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/src/layout/components/banner/index.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
13 |
14 |
15 |
16 |
17 |
18 |
42 |
43 |
63 |
--------------------------------------------------------------------------------
/src/layout/components/classic/index.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
22 |
--------------------------------------------------------------------------------
/src/layout/components/classic/ma-classic-header.vue:
--------------------------------------------------------------------------------
1 |
2 |
10 |
11 |
12 |
17 |
--------------------------------------------------------------------------------
/src/layout/components/classic/ma-classic-slider.vue:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
![]()
8 |
{{ $title }}
9 |
10 |
15 |
16 |
17 |
18 |
34 |
35 |
38 |
--------------------------------------------------------------------------------
/src/layout/components/columns/index.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
40 |
--------------------------------------------------------------------------------
/src/layout/components/columns/ma-columns-header.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
11 |
12 |
13 |
18 |
--------------------------------------------------------------------------------
/src/layout/components/components/children-banner.vue:
--------------------------------------------------------------------------------
1 |
2 |
24 |
25 |
54 |
55 |
--------------------------------------------------------------------------------
/src/layout/components/components/children-menu.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
30 |
31 |
51 |
52 |
--------------------------------------------------------------------------------
/src/layout/components/components/iframe-view.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/src/layout/components/components/message-notification.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | {{ $t('sys.operationMessage.message') }}
7 |
13 |
14 |
15 |
19 |
20 |
21 |
22 | 发送人:{{item.send_user.nickname}}
23 | 时间:{{item.create_time.substr(0, 10)}}
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 | {{ $t('sys.operationMessage.todo') }}
38 |
39 |
40 |
41 |
42 |
43 |
44 | 消息详情
45 |
46 |
47 | {{ row?.title }}
48 |
49 |
50 |
51 | 创建时间:{{ row?.create_time }}
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
75 |
76 |
--------------------------------------------------------------------------------
/src/layout/components/components/search.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/src/layout/components/components/skin.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 | {{ $t('sys.changeSkin') }}
4 |
5 |
11 |
12 |
13 | {{ $t(`skin.${item.name}`) }}
14 |
15 |
16 |
17 |
18 |
19 | {{ $t(`skin.${item.name}Desc`) }}
20 |
21 |
22 |
27 | {{ appStore.skin === item.name ? $t('skin.activated') : $t('skin.use') }}
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
53 |
54 |
--------------------------------------------------------------------------------
/src/layout/components/components/sub-menu.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | {{ appStore.i18n ? ($t(`menus.${menuInfo.name}`).indexOf('.') > 0 ? menuInfo.meta.title : $t(`menus.${menuInfo.name}`)) : menuInfo.meta.title }}
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 | {{ appStore.i18n ? ($t(`menus.${item.name}`).indexOf('.') > 0 ? item.meta.title : $t(`menus.${item.name}`)) : item.meta.title }}
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
42 |
--------------------------------------------------------------------------------
/src/layout/components/ma-breadcrumb.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | {{ $t('menus.dashboard') }}
8 |
9 |
10 |
11 |
12 |
15 |
16 |
17 |
18 | {{ appStore.i18n ? ( $t('menus.' + r.name).indexOf('.') > 0 ? r.meta.title : $t('menus.' + r.name) ) : r.meta.title }}
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
35 |
--------------------------------------------------------------------------------
/src/layout/components/ma-buttonMenu.vue:
--------------------------------------------------------------------------------
1 |
2 |
20 |
21 |
22 |
32 |
33 |
36 |
--------------------------------------------------------------------------------
/src/layout/components/ma-menu.vue:
--------------------------------------------------------------------------------
1 |
2 |
18 |
19 |
20 |
89 |
103 |
--------------------------------------------------------------------------------
/src/layout/components/ma-workerArea.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
24 |
--------------------------------------------------------------------------------
/src/layout/components/mixed/top-menu.vue:
--------------------------------------------------------------------------------
1 |
2 |
16 |
17 |
42 |
43 |
--------------------------------------------------------------------------------
/src/layout/empty.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
--------------------------------------------------------------------------------
/src/layout/index.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
65 |
67 |
--------------------------------------------------------------------------------
/src/main.js:
--------------------------------------------------------------------------------
1 | import { createApp } from 'vue'
2 | import ArcoVue from '@arco-design/web-vue'
3 | import ArcoVueIcon from '@arco-design/web-vue/es/icon'
4 |
5 | import globalComponents from '@/components'
6 | import App from './App.vue'
7 | import router from './router'
8 | import store from './store'
9 | import i18n from '@/i18n'
10 | import directives from './directives'
11 | import dayjs from 'dayjs'
12 | import zhCn from 'dayjs/locale/zh-cn'
13 | import relativeTime from 'dayjs/plugin/relativeTime'
14 | dayjs.locale(zhCn)
15 | dayjs.extend(relativeTime)
16 |
17 | // 官方样式
18 | import '@arco-design/web-vue/dist/arco.css'
19 | import './style/skin.less'
20 | import './style/index.css'
21 | import './style/global.less'
22 |
23 | import tool from '@/utils/tool'
24 | import * as common from '@/utils/common'
25 | import packageJson from '../package.json'
26 |
27 | const app = createApp(App)
28 |
29 | app
30 | .use(ArcoVue, {})
31 | .use(ArcoVueIcon)
32 | .use(router)
33 | .use(store)
34 | .use(i18n)
35 | .use(directives)
36 | .use(globalComponents)
37 |
38 | app.config.globalProperties.$tool = tool
39 | app.config.globalProperties.$common = common
40 | app.config.globalProperties.$title = import.meta.env.VITE_APP_TITLE
41 | app.config.globalProperties.$url = import.meta.env.VITE_APP_BASE
42 |
43 | app.mount('#app')
44 |
45 | tool.capsule('SaiAdmin', `v${packageJson.version} release`)
46 | console.log('SaiAdmin 官网 https://saithink.top')
47 |
--------------------------------------------------------------------------------
/src/plugin/index.js:
--------------------------------------------------------------------------------
1 | export default {
2 | install: (Vue) => {
3 | const pluginList = import.meta.glob('./*/main.js')
4 | Object.keys(pluginList).forEach((path) => {
5 | pluginList[path]().then(plugin => Vue.use(plugin.default || plugin))
6 | })
7 | }
8 | }
--------------------------------------------------------------------------------
/src/router/homePageRoutes.js:
--------------------------------------------------------------------------------
1 | const homePageRoutes = [
2 | {
3 | name: 'dashboard',
4 | path: '/dashboard',
5 | meta: {
6 | title: '仪表盘',
7 | icon: 'icon-dashboard',
8 | type: 'M',
9 | affix: true
10 | },
11 | component: () => import('@/views/dashboard/index.vue')
12 | },
13 | {
14 | name: 'userCenter',
15 | path: '/usercenter',
16 | meta: {
17 | title: '个人信息',
18 | icon: 'icon-user',
19 | type: 'M'
20 | },
21 | component: () => import('@/views/dashboard/userCenter/index.vue')
22 | },
23 | {
24 | name: 'appStore',
25 | path: 'https://saas.saithink.top/#/appStore',
26 | meta: {
27 | title: '插件市场',
28 | icon: 'icon-apps',
29 | type: 'L'
30 | }
31 | }
32 | ]
33 |
34 | export const homePage = {
35 | name: 'home',
36 | path: '/home',
37 | meta: { title: '首页', icon: 'icon-home', hidden: false, type: 'M' }
38 | }
39 |
40 | export default homePageRoutes
41 |
--------------------------------------------------------------------------------
/src/router/index.js:
--------------------------------------------------------------------------------
1 | import { createRouter, createWebHashHistory, createWebHistory } from 'vue-router'
2 | import { useUserStore } from '@/store'
3 | import NProgress from 'nprogress'
4 | import tool from '@/utils/tool'
5 | import 'nprogress/nprogress.css'
6 |
7 | import routes from './webRouter.js'
8 |
9 | const title = import.meta.env.VITE_APP_TITLE
10 | const defaultRoutePath = '/'
11 | const whiteRoute = ['login']
12 |
13 | const router = createRouter({
14 | history: createWebHashHistory(),
15 | routes
16 | })
17 |
18 | router.beforeEach(async (to, from, next) => {
19 | NProgress.start()
20 | const userStore = useUserStore()
21 | let toTitle = to.meta.title ? to.meta.title : to.name
22 | document.title = `${toTitle} - ${title}`
23 | const token = tool.local.get(import.meta.env.VITE_APP_TOKEN_PREFIX)
24 |
25 | // 登录状态下
26 | if (token) {
27 | if (to.name === 'login') {
28 | next({ path: defaultRoutePath })
29 | return
30 | }
31 |
32 | if (! userStore.user && userStore.user == undefined ) {
33 | const data = await userStore.requestUserInfo()
34 | data && next({ path: to.path, query: to.query })
35 | } else {
36 | next()
37 | }
38 | } else {
39 | // 未登录的情况下允许访问的路由
40 | if (! whiteRoute.includes(to.name)) {
41 | next({ name: 'login', query: { redirect: to.fullPath } })
42 | } else {
43 | next()
44 | }
45 | }
46 | })
47 |
48 | router.afterEach((to, from) => {
49 | NProgress.done()
50 | })
51 |
52 | router.onError(error => {
53 | NProgress.done();
54 | });
55 |
56 |
57 | export default router
--------------------------------------------------------------------------------
/src/router/webRouter.js:
--------------------------------------------------------------------------------
1 | import homePageRoutes from './homePageRoutes'
2 | //系统路由
3 | const routes = [
4 | {
5 | name: 'layout',
6 | path: '/',
7 | component: () => import('@/layout/index.vue'),
8 | redirect: 'dashboard',
9 | children: homePageRoutes
10 | },
11 | {
12 | name: 'login',
13 | path: '/login',
14 | component: () => import('@/views/login.vue'),
15 | meta: { title: '登录' }
16 | },
17 | {
18 | path: '/:pathMatch(.*)*',
19 | hidden: true,
20 | meta: { title: '访问的页面不存在' },
21 | component: () => import('@/layout/404.vue')
22 | }
23 | ]
24 |
25 | export default routes
26 |
--------------------------------------------------------------------------------
/src/store/index.js:
--------------------------------------------------------------------------------
1 | import { createPinia } from 'pinia'
2 | import useUserStore from './modules/user'
3 | import useAppStore from './modules/app'
4 | import useTagStore from './modules/tag'
5 | import useKeepAliveStore from './modules/keepAlive'
6 | import useIframeStore from './modules/iframe'
7 | import useConfigStore from './modules/config'
8 | import useMessageStore from './modules/message'
9 | import useDictStore from './modules/dict'
10 |
11 | const pinia = createPinia()
12 |
13 | export {
14 | useUserStore,
15 | useAppStore,
16 | useTagStore,
17 | useKeepAliveStore,
18 | useIframeStore,
19 | useConfigStore,
20 | useMessageStore,
21 | useDictStore
22 | }
23 | export default pinia
24 |
--------------------------------------------------------------------------------
/src/store/modules/config.js:
--------------------------------------------------------------------------------
1 |
2 | import { defineStore } from 'pinia'
3 |
4 | let defaultConfig = {
5 | site_name: 'SaiAdmin',
6 | site_keywords: '',
7 | site_desc: '',
8 | site_record_number: '',
9 | site_copyright: '',
10 | site_storage_mode: '',
11 | web_close: '',
12 | }
13 |
14 | const useConfigStore = defineStore('config', {
15 | state: () => ({ ...defaultConfig }),
16 |
17 | getters: {
18 | appCurrentConfig() {
19 | return { ...this.$state }
20 | },
21 | },
22 |
23 | actions: {
24 | updateSettings(partial) {
25 | this.$patch(partial);
26 | },
27 | },
28 | })
29 |
30 | export default useConfigStore
--------------------------------------------------------------------------------
/src/store/modules/dict.js:
--------------------------------------------------------------------------------
1 | import { defineStore } from 'pinia'
2 | import commonApi from '@/api/common'
3 |
4 | // 定义字典store,名称是dict
5 | const useDictStore = defineStore('dict', {
6 | // 字典数据是数组,我们定义一个data来进行保存
7 | state: () => ({ data: undefined }),
8 | getters: {
9 | // 获取store状态
10 | getState() {
11 | return { ...this.$state }
12 | }
13 | },
14 | actions: {
15 | //给字典数据赋值
16 | setInfo(data) {
17 | this.$patch(data)
18 | },
19 | // 初始化字典数据
20 | async initData() {
21 | const { data } = await commonApi.dictAll()
22 | this.data = data
23 | }
24 | }
25 | })
26 |
27 | export default useDictStore
28 |
--------------------------------------------------------------------------------
/src/store/modules/iframe.js:
--------------------------------------------------------------------------------
1 | import { defineStore } from 'pinia'
2 |
3 | const useIframeStore = defineStore('iframe', {
4 | state: () => ({
5 | iframes: [],
6 | name: null,
7 | show: true
8 | }),
9 |
10 | getters: {
11 | getState() {
12 | return { ...this.$state }
13 | },
14 | },
15 |
16 | actions: {
17 |
18 | addIframe (component) {
19 | if (! this.iframes.includes(component)) {
20 | this.iframes.push(component)
21 | }
22 | },
23 |
24 | removeIframe (component) {
25 | const idx = this.iframes.indexOf(component)
26 | if (idx !== -1) {
27 | this.iframes.splice(idx, 1)
28 | }
29 | },
30 |
31 | display () { this.show = true },
32 |
33 | hidden () { this.show = false },
34 |
35 | setName (name) { this.name = name },
36 |
37 | clearIframe() { this.iframes = [] },
38 | },
39 | })
40 |
41 | export default useIframeStore
--------------------------------------------------------------------------------
/src/store/modules/keepAlive.js:
--------------------------------------------------------------------------------
1 | import { defineStore } from 'pinia'
2 |
3 | const useKeepAliveStore = defineStore('keepAlive', {
4 | state: () => ({
5 | keepAlives: [],
6 | show: true
7 | }),
8 |
9 | getters: {
10 | getState() {
11 | return { ...this.$state }
12 | }
13 | },
14 |
15 | actions: {
16 | addKeepAlive(component) {
17 | if (component.path.indexOf('maIframe') > -1) {
18 | return
19 | }
20 | if (!this.keepAlives.includes(component.name)) {
21 | this.keepAlives.push(component.name)
22 | }
23 | },
24 |
25 | removeKeepAlive(component) {
26 | const idx = this.keepAlives.indexOf(component.name)
27 | if (idx !== -1) {
28 | this.keepAlives.splice(idx, 1)
29 | }
30 | },
31 |
32 | display() {
33 | this.show = true
34 | },
35 |
36 | hidden() {
37 | this.show = false
38 | },
39 |
40 | clearKeepAlive() {
41 | this.keepAlives = []
42 | }
43 | }
44 | })
45 |
46 | export default useKeepAliveStore
47 |
--------------------------------------------------------------------------------
/src/store/modules/message.js:
--------------------------------------------------------------------------------
1 |
2 | import { defineStore } from 'pinia'
3 |
4 | let defaultType = {
5 | messageList: [],
6 | }
7 |
8 | const useMessageStore = defineStore('message', {
9 | state: () => ({ ...defaultType }),
10 |
11 | getters: {
12 | getState() {
13 | return { ...this.$state }
14 | },
15 | },
16 |
17 | actions: {
18 | updateMessage(partial) {
19 | this.$patch(partial);
20 | },
21 | },
22 | })
23 |
24 | export default useMessageStore
--------------------------------------------------------------------------------
/src/store/modules/tag.js:
--------------------------------------------------------------------------------
1 | import { defineStore } from 'pinia'
2 | import tool from '@/utils/tool'
3 |
4 | const defaultTag = [ { name: 'dashboard', title: '仪表盘', path: '/dashboard', affix: true } ]
5 | const useTagStore = defineStore('tag', {
6 | state: () => ({
7 | tags: (! tool.local.get('tags') || tool.local.get('tags').length === 0 ) ? defaultTag : tool.local.get('tags')
8 | }),
9 |
10 | getters: {
11 | getState() {
12 | return { ...this.$state }
13 | },
14 | },
15 |
16 | actions: {
17 |
18 | addTag(tag) {
19 | const target = this.tags.find( item => item.path === tag.path )
20 | if (! target && tag.path ) {
21 | this.tags.push(tag)
22 | }
23 | this.updateTagsToLocal()
24 | },
25 |
26 | removeTag(tag) {
27 | let index = 0
28 | this.tags.map((item, idx) => {
29 | if ( item.path === tag.path && ! item.affix ) {
30 | if (this.tags[(idx + 1)]) {
31 | index = idx
32 | } else if ( idx > 0) {
33 | index = idx - 1
34 | }
35 | this.tags.splice(idx, 1)
36 | }
37 | })
38 | this.updateTagsToLocal()
39 | return this.tags[index]
40 | },
41 |
42 | updateTag(tag) {
43 | this.tags.map(item => {
44 | if (item.path == tag.path) {
45 | item = Object.assign(item, tag)
46 | }
47 | })
48 | this.updateTagsToLocal()
49 | },
50 |
51 | updateTagTitle(path, title) {
52 | this.tags.map(item => {
53 | if (item.path == path) {
54 | item.customTitle = title
55 | }
56 | })
57 | this.updateTagsToLocal()
58 | },
59 |
60 | updateTagsToLocal() {
61 | tool.local.set('tags', this.tags)
62 | },
63 |
64 | clearTags() {
65 | this.tags = defaultTag
66 | tool.local.set('tags', defaultTag)
67 | },
68 | },
69 | })
70 |
71 | export default useTagStore
--------------------------------------------------------------------------------
/src/style/animation.less:
--------------------------------------------------------------------------------
1 | .ma-fade-enter-active,
2 | .ma-fade-leave-active {
3 | transition: opacity 0.15s ease;
4 | }
5 |
6 | .ma-fade-enter-from,
7 | .ma-fade-leave-to {
8 | opacity: 0;
9 | }
10 | .ma-slide-right-enter-active,
11 | .ma-slide-right-leave-active,
12 | .ma-slide-left-enter-active,
13 | .ma-slide-left-leave-active {
14 | will-change: transform;
15 | transition: all 0.2s ease;
16 | }
17 | // ma-slide-right
18 | .ma-slide-right-enter-from {
19 | opacity: 0;
20 | transform: translateX(-10px);
21 | }
22 | .ma-slide-right-leave-to {
23 | opacity: 0;
24 | transform: translateX(10px);
25 | }
26 | // ma-slide-left
27 | .ma-slide-left-enter-from {
28 | &:extend(.ma-slide-right-leave-to);
29 | }
30 | .ma-slide-left-leave-to {
31 | &:extend(.ma-slide-right-enter-from);
32 | }
33 |
34 | .ma-slide-down-enter-active,
35 | .ma-slide-down-leave-active,
36 | .ma-slide-up-enter-active,
37 | .ma-slide-up-leave-active {
38 | will-change: transform;
39 | transition: all 0.2s ease;
40 | }
41 | // ma-slide-down
42 | .ma-slide-down-enter-from {
43 | opacity: 0;
44 | transform: translateY(-10px);
45 | }
46 | .ma-slide-down-leave-to {
47 | opacity: 0;
48 | transform: translateY(10px);
49 | }
50 | // ma-slide-up
51 | .ma-slide-up-enter-from {
52 | &:extend(.ma-slide-down-leave-to);
53 | }
54 | .ma-slide-up-leave-to {
55 | &:extend(.ma-slide-down-enter-from);
56 | }
--------------------------------------------------------------------------------
/src/style/dark.less:
--------------------------------------------------------------------------------
1 | [arco-theme="dark"] {
2 | .menu-title { color: #efefef }
3 | .logo { span { color: #efefef } }
4 |
5 | .sys-search-container .results li .title,
6 | .sys-search-container .arco-icon
7 | {
8 | color: #efefef;
9 | }
10 |
11 | .sys-search-container .icon {
12 | fill: #efefef;
13 | }
14 | }
--------------------------------------------------------------------------------
/src/style/index.css:
--------------------------------------------------------------------------------
1 | /* ./src/index.css */
2 | @tailwind base;
3 | @tailwind components;
4 | @tailwind utilities;
--------------------------------------------------------------------------------
/src/style/skin.less:
--------------------------------------------------------------------------------
1 | @import './skins/mine/index.less';
2 | @import './skins/city/index.less';
3 | @import './skins/classics/index.less';
4 | @import './skins/businessGray/index.less';
--------------------------------------------------------------------------------
/src/style/skins/city/background.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/saithink/saiadmin-vue/141805149a25a2d4fe13447504c41a19939e26b1/src/style/skins/city/background.jpg
--------------------------------------------------------------------------------
/src/style/skins/classics/index.less:
--------------------------------------------------------------------------------
1 | [mine-skin="classics"] {
2 |
3 | .logo {
4 | border-bottom: 0;
5 | }
6 |
7 | .arco-layout-sider,
8 | .arco-layout-sider-light,
9 | .arco-menu-light
10 | {
11 | background: #1c1e23;
12 | }
13 |
14 | .logo span,
15 | .arco-menu-light .arco-menu-pop-header,
16 | .layout-banner-header .banner-menus li {
17 | color: rgb(var(--primary-5));
18 | fill: rgb(var(--primary-5));
19 | }
20 |
21 | .arco-menu-light.arco-menu-horizontal .arco-menu-pop-header.arco-menu-selected:hover
22 | {
23 | background-color: #2e3033;
24 | }
25 |
26 | .arco-menu-light .arco-menu-item {
27 | background-color: rgba(0, 0, 0, 0);
28 | color: #fff;
29 | fill: #fff;
30 | }
31 |
32 | .arco-menu-light .arco-menu-item:hover,
33 | .arco-menu-light .arco-menu-inline-header:hover,
34 | .arco-menu-light .arco-menu-item.arco-menu-selected {
35 | // background-color: #ffffff14;
36 | background-color: rgb(var(--primary-6));
37 | }
38 |
39 |
40 | .ma-menu .icon,
41 | .arco-menu-selected .icon {
42 | fill: #fff;
43 | }
44 |
45 | .arco-menu-light .arco-menu-inline-header,
46 | .arco-menu-light .arco-menu-pop-header,
47 | .arco-menu-light .arco-menu-collapse-button,
48 | .arco-menu-light .arco-menu-collapse-button:hover {
49 | background-color: rgba(255, 255, 255, 0);
50 | }
51 |
52 | .arco-menu-light .arco-menu-inline-header.arco-menu-selected:hover,
53 | .arco-menu-light .arco-menu-pop-header:hover,
54 | .arco-menu-light .arco-menu-pop-header.arco-menu-selected {
55 | background-color: rgba(0, 0, 0, 0.35);
56 | }
57 |
58 | .arco-menu-light .arco-menu-pop-header .arco-icon,
59 | .arco-menu-light .arco-menu-pop-header .iconify-icon,
60 | .arco-menu-light .arco-menu-pop-header.arco-menu-selected .arco-menu-icon,
61 | .arco-menu-light .arco-menu-item .arco-icon,
62 | .arco-menu-light .arco-menu-item .arco-menu-icon,
63 | .arco-menu-light .arco-menu-inline-header .iconify-icon,
64 | .arco-menu-light .arco-menu-inline-header .arco-icon,
65 | .arco-menu-light .arco-menu-inline-header {
66 | color: #fff;
67 | }
68 |
69 | .layout-columns-left-panel {
70 |
71 | .menu-title {
72 | font-weight: bold;
73 | color: #fff;
74 | background-color: #232324;
75 | border-bottom: none;
76 | }
77 | }
78 |
79 | .layout-columns-left-panel .sider {
80 | background-color: #17171a;
81 | }
82 |
83 |
84 |
85 | .parent-menu.active {
86 | background-color: #ffffff14;
87 | }
88 |
89 | .parent-menu:hover {
90 | background-color: #ffffff14;
91 | }
92 |
93 | }
94 |
--------------------------------------------------------------------------------
/src/style/skins/mine/index.less:
--------------------------------------------------------------------------------
1 | [mine-skin="mine"] {
2 |
3 | .arco-menu-light .arco-menu-has-icon .arco-icon,
4 | .arco-menu-light .arco-menu-has-icon .iconify-icon,
5 | .arco-menu-light .arco-menu-item .arco-icon,
6 | .arco-menu-light .arco-menu-item .iconify-icon {
7 | color: var(--color-text-1);
8 | }
9 |
10 | .arco-trigger-menu .arco-trigger-menu-has-icon .arco-trigger-menu-icon,
11 | .sys-menus .arco-menu-icon .icon {
12 | fill: var(--color-text-2);
13 | }
14 |
15 | .arco-menu-light .arco-menu-item.arco-menu-selected .arco-icon,
16 | .arco-menu-light .arco-menu-item.arco-menu-selected .iconify-icon {
17 | color: rgb(var(--primary-6));
18 | }
19 |
20 | .arco-menu-light .arco-menu-inline-header.arco-menu-selected .arco-menu-icon .arco-icon,
21 | .arco-menu-light .arco-menu-inline-header.arco-menu-selected .arco-menu-icon .iconify-icon {
22 | color: rgb(var(--primary-6));
23 | }
24 |
25 | .layout-banner-header .banner-menus li.active {
26 | background-color: rgb(var(--primary-1));
27 | color: rgb(var(--primary-6));
28 | fill: rgb(var(--primary-6));
29 | }
30 |
31 | .layout-columns-left-panel .sider {
32 | background-color: var(--color-bg-1);
33 | }
34 |
35 | .parent-menu {
36 | color: var(--color-text-2);
37 | fill: var(--color-text-2);
38 | }
39 |
40 | .parent-menu:hover {
41 | background-color: var(--color-fill-2);
42 | fill: var(--color-text-2);
43 | }
44 |
45 |
46 | .parent-menu.active {
47 | background-color: rgb(var(--primary-1));
48 | color: rgb(var(--primary-6));
49 | fill: rgb(var(--primary-6));
50 | }
51 |
52 | .sys-menus .arco-menu-item.arco-menu-selected .icon {
53 | fill: rgb(var(--primary-6));
54 | }
55 |
56 | }
--------------------------------------------------------------------------------
/src/views/dashboard/components/components/st-announced.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
7 |
8 |
9 | {{ record.title }}
10 |
11 |
12 |
13 |
14 | 公告详情
15 |
16 |
17 | {{ row?.title }}
18 |
19 |
20 |
21 | 创建时间:{{ row?.create_time }}
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
57 |
--------------------------------------------------------------------------------
/src/views/dashboard/components/components/st-count.vue:
--------------------------------------------------------------------------------
1 |
2 |
46 |
47 |
48 |
66 |
67 |
91 |
--------------------------------------------------------------------------------
/src/views/dashboard/components/components/st-saiadmin.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
SaiAdmin 相关
4 |
5 |
6 | 官方网站
7 |
8 |
9 |
10 | 开发文档
11 |
12 |
13 |
14 |
15 | Github
16 |
17 |
18 |
19 | Gitee
20 |
21 |
22 |
23 |
SaiAdmin v{{ config.version }} release
24 |
25 |
26 |
27 |
28 |
35 |
--------------------------------------------------------------------------------
/src/views/dashboard/components/components/st-welcome.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
10 |
11 |
12 |
{{ userStore.user.nickname || userStore.user.username }},欢迎回来!
13 |
14 |
免费开源、可商用
15 | 欢迎使用SaiAdmin后台权限管理系统。喜欢的请去点个 ⭐Star,谢谢!
16 |
17 |
18 |
19 |
20 |
{{ time }}
21 |
{{ day }}
22 |
23 |
24 |
25 |
26 |
27 |
50 |
51 |
61 |
--------------------------------------------------------------------------------
/src/views/dashboard/components/statistics.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
19 |
--------------------------------------------------------------------------------
/src/views/dashboard/components/work-panel.vue:
--------------------------------------------------------------------------------
1 |
2 | 自行开发
3 |
4 |
--------------------------------------------------------------------------------
/src/views/dashboard/index.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
14 |
17 |
--------------------------------------------------------------------------------
/src/views/dashboard/userCenter/components/modifyPassword.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
9 |
14 |
15 |
21 | passwordSafePercent = 0"
25 | autocomplete="off"
26 | allow-clear
27 | />
28 |
29 |
30 |
37 |
38 |
44 |
49 |
50 |
51 | 保存
52 |
53 |
54 |
55 |
56 | 提示
57 | 密码已经修改成功,需要重新登录系统,点击确定跳转登录页面。
58 |
59 |
60 |
61 |
129 |
--------------------------------------------------------------------------------
/src/views/dashboard/userCenter/components/userInfomation.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 | 保存
20 |
21 |
22 |
23 |
24 |
46 |
--------------------------------------------------------------------------------
/src/views/system/config/components/add-group.vue:
--------------------------------------------------------------------------------
1 |
2 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
96 |
--------------------------------------------------------------------------------
/src/views/system/config/components/js/inputType.js:
--------------------------------------------------------------------------------
1 | export const inputComponent = [
2 | { label: '文本框', value: 'input' },
3 | { label: '文本域', value: 'textarea' },
4 | { label: '下拉选择框', value: 'select' },
5 | { label: '单选框', value: 'radio' },
6 | { label: '图片上传', value: 'uploadImage' },
7 | { label: '文件上传', value: 'uploadFile' },
8 | { label: '富文本编辑器', value: 'wangEditor' }
9 | ]
10 |
--------------------------------------------------------------------------------
/src/views/system/config/components/manage-config.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 | 管理配置
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
113 |
--------------------------------------------------------------------------------
/src/views/system/database/struct.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 | 表结构信息
4 |
5 |
16 |
17 |
18 |
19 |
61 |
--------------------------------------------------------------------------------
/src/views/system/dept/index.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
{{ item.username }}
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 | 领导列表
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
127 |
--------------------------------------------------------------------------------
/src/views/system/dept/leader.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 | 部门领导列表
4 | 部门的领导人可以跨部门设置
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
106 |
--------------------------------------------------------------------------------
/src/views/system/dict/edit-data.vue:
--------------------------------------------------------------------------------
1 |
2 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
127 |
--------------------------------------------------------------------------------
/src/views/system/dict/edit.vue:
--------------------------------------------------------------------------------
1 |
2 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
121 |
--------------------------------------------------------------------------------
/src/views/system/logs/emailLog.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 | 成功
40 | 失败
41 |
42 |
43 |
44 |
45 |
46 |
111 |
--------------------------------------------------------------------------------
/src/views/system/logs/loginLog.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 | 成功
32 | 失败
33 |
34 |
35 |
36 |
37 |
38 |
103 |
--------------------------------------------------------------------------------
/src/views/system/logs/operLog.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
90 |
--------------------------------------------------------------------------------
/src/views/system/notice/edit.vue:
--------------------------------------------------------------------------------
1 |
2 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
123 |
--------------------------------------------------------------------------------
/src/views/system/notice/index.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
99 |
--------------------------------------------------------------------------------
/src/views/system/post/edit.vue:
--------------------------------------------------------------------------------
1 |
2 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
125 |
--------------------------------------------------------------------------------
/src/views/system/post/view.vue:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
68 |
--------------------------------------------------------------------------------
/src/views/tool/code/components/preview.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 | 预览代码
4 |
5 |
6 |
10 |
11 |
12 |
13 |
14 |
15 |
40 |
41 |
49 |
--------------------------------------------------------------------------------
/src/views/tool/code/js/vars.js:
--------------------------------------------------------------------------------
1 | export const realtionsType = [
2 | { name: '一对一', value: 'hasOne' },
3 | { name: '一对多', value: 'hasMany' },
4 | { name: '一对一(反向)', value: 'belongsTo' },
5 | { name: '多对多', value: 'belongsToMany' }
6 | ]
7 |
8 | export const queryType = [
9 | { label: '=', value: 'eq' },
10 | { label: '!=', value: 'neq' },
11 | { label: '>', value: 'gt' },
12 | { label: '>=', value: 'gte' },
13 | { label: '<', value: 'lt' },
14 | { label: '<=', value: 'lte' },
15 | { label: 'LIKE', value: 'like' },
16 | { label: 'IN', value: 'in' },
17 | { label: 'NOT IN', value: 'notin' },
18 | { label: 'BETWEEN', value: 'between' }
19 | ]
20 |
21 | // 页面控件
22 | export const viewComponent = [
23 | { label: '输入框', value: 'input' },
24 | { label: '密码框', value: 'password' },
25 | { label: '文本域', value: 'textarea' },
26 | { label: '数字输入框', value: 'inputNumber' },
27 | { label: '标签输入框', value: 'inputTag' },
28 | // { label: '提及', value: 'mention' },
29 | { label: '开关', value: 'switch' },
30 | { label: '滑块', value: 'slider' },
31 | { label: '数据下拉框', value: 'select' },
32 | { label: '字典下拉框', value: 'saSelect' },
33 | { label: '树形下拉框', value: 'treeSelect' },
34 | { label: '单选框', value: 'radio' },
35 | { label: '复选框', value: 'checkbox' },
36 | { label: '日期选择器', value: 'date' },
37 | { label: '时间选择器', value: 'time' },
38 | { label: '评分器', value: 'rate' },
39 | { label: '级联选择器', value: 'cascader' },
40 | // { label: '数据穿梭框', value: 'transfer' },
41 | { label: '用户选择器', value: 'userSelect' },
42 | // { label: '用户信息', value: 'userinfo' },
43 | { label: '省市区联动', value: 'cityLinkage' },
44 | // { label: '子表单', value: 'formGroup' },
45 | { label: '图片上传', value: 'uploadImage' },
46 | { label: '文件上传', value: 'uploadFile' },
47 | // { label: '资源选择器', value: 'selectResource' },
48 | { label: '富文本控件', value: 'wangEditor' }
49 | // { label: '代码编辑器', value: 'codeEditor' }
50 | ]
51 |
--------------------------------------------------------------------------------
/src/views/tool/crontab/logList.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 | 执行日志
4 |
5 |
6 |
7 |
8 | {{ record.status == 1 ? '成功' : '失败' }}
9 |
10 |
11 |
12 | 查看
13 |
14 |
15 |
16 |
17 |
18 |
90 |
--------------------------------------------------------------------------------
/src/views/tool/crontab/view.vue:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
10 |
11 | {{ formData?.id }}
12 | {{ formData?.name }}
13 | {{ formData?.code }}
14 | {{ formData?.sort }}
15 |
16 |
17 |
18 | {{ formData?.remark }}
19 |
20 |
21 |
22 |
23 |
24 |
25 |
58 |
--------------------------------------------------------------------------------
/tailwind.config.cjs:
--------------------------------------------------------------------------------
1 | const colors = require('tailwindcss/colors')
2 | module.exports = {
3 | content: [ './src/**/*.{js,jxs,vue}' ],
4 | darkMode: 'class', // or 'media' or 'class'
5 | theme: {
6 | fontFamily: {
7 | sans: ['Graphik', 'sans-serif'],
8 | serif: ['Merriweather', 'serif'],
9 | },
10 | extend: {
11 | spacing: {
12 | '128': '32rem',
13 | '144': '36rem',
14 | },
15 | borderRadius: {
16 | '4xl': '2rem',
17 | }
18 | }
19 | },
20 | variants: {
21 | extend: {
22 | borderColor: ['focus-visible'],
23 | opacity: ['disabled'],
24 | }
25 | },
26 | plugins: [
27 | ],
28 | }
29 |
--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "composite": false,
4 | "declaration": true,
5 | "declarationMap": true,
6 | "esModuleInterop": true,
7 | "jsx": "preserve",
8 | "allowJs": true,
9 | "strictFunctionTypes": false,
10 | "allowSyntheticDefaultImports": true,
11 | "forceConsistentCasingInFileNames": true,
12 | "inlineSources": false,
13 | "isolatedModules": true,
14 | "moduleResolution": "node",
15 | "noUnusedLocals": false,
16 | "noUnusedParameters": false,
17 | "preserveWatchOutput": true,
18 | "skipLibCheck": true,
19 | "strict": true,
20 | "resolveJsonModule": true,
21 | "removeComments": true,
22 | "noImplicitAny": false,
23 | "experimentalDecorators": true,
24 | "target": "esnext",
25 | "module": "esnext",
26 | "baseUrl": ".",
27 | "paths": {
28 | "@/*": ["src/*"],
29 | "@cps/*": ["src/components/*"],
30 | "vue-i18n": ["vue-i18n/dist/vue-i18n.cjs.js"]
31 | },
32 | "lib": ["dom", "esnext"],
33 | "types": ["vite/client"]
34 | },
35 | "include": ["src", "mock", "vite.config.ts","node_modules", "dist", "build"]
36 | }
37 |
--------------------------------------------------------------------------------
/vite.config.js:
--------------------------------------------------------------------------------
1 | import { defineConfig, loadEnv } from 'vite'
2 | import vue from '@vitejs/plugin-vue'
3 | import { resolve } from 'path'
4 | import vueJsx from '@vitejs/plugin-vue-jsx'
5 | import { visualizer } from 'rollup-plugin-visualizer'
6 | export default ({ mode }) => {
7 | const env = loadEnv(mode, process.cwd())
8 | const proxyPrefix = env.VITE_APP_PROXY_PREFIX
9 |
10 | return defineConfig({
11 | base: env.VITE_APP_BASE,
12 | plugins: [
13 | vue(),
14 | vueJsx(),
15 | visualizer({
16 | emitFile: false,
17 | file: 'stats.html', //分析图生成的文件名
18 | open: true //如果存在本地服务端口,将在打包后自动展示
19 | })
20 | ],
21 | resolve: {
22 | alias: {
23 | '@': resolve(__dirname, 'src'),
24 | '@cps': resolve(__dirname, 'src/components'),
25 | 'vue-i18n': 'vue-i18n/dist/vue-i18n.cjs.js'
26 | }
27 | },
28 |
29 | build: {
30 | chunkSizeWarningLimit: 1500
31 | // rollupOptions: {
32 | // output: {
33 | // manualChunks(id) {
34 | // if (id.includes('node_modules')) {
35 | // return id.toString().split("node_modules/")[1].split("/")[0].toString();
36 | // }
37 | // }
38 | // }
39 | // }
40 | },
41 |
42 | server: {
43 | host: '0.0.0.0',
44 | port: env.VITE_APP_PORT || process.env.port,
45 | proxy: {
46 | [proxyPrefix]: {
47 | target: env.VITE_APP_BASE_URL,
48 | changeOrigin: true,
49 | ws: true,
50 | toProxy: true,
51 | rewrite: (path) => path.replace(new RegExp(`^${proxyPrefix}`), '')
52 | }
53 | }
54 | }
55 | })
56 | }
57 |
--------------------------------------------------------------------------------